Electoday 4.0

ไมโครคอนโทรลเลอร์ => Other MCUs => Topic started by: TaoTao on September 07, 2018, 08:20:42 am

Title: มีคำสั่ง ห้ามเปลี่ยนแปลงค่าตัวแปรอีก ไหมครับ
Post by: TaoTao on September 07, 2018, 08:20:42 am
เช่น มีตัวแปรประเภท struct
ให้มันรับค่า ip จากนั้นห้ามเปลี่ยนค่าอีกเลย

คำสั่งแบบนี้ มีไหมครับ
Title: Re: มีคำสั่ง ห้ามเปลี่ยนแปลงค่าตัวแปรอีก ไหมครับ
Post by: dec on September 07, 2018, 02:08:15 pm
ไม่มีโดยตรงครับ

ในทาง software ภาษา C มีคล้าย ๆ กันคือตัวแปรที่มี const นำหน้า คือตัวแปรคงที่
ต้องมีการกำหนดค่าเริ่มต้นตั้งแต่ประกาศตัวแปร compiler จะห้ามไม่ให้เปลี่ยนค่า
ตัวแปรคงที่ขณะ runtime

การใช้ const กับตัวแปร global และ local มีลักษณะต่างกันนิดหน่อย

ถ้าใช้ const กับตัวแปร global ตัวแปรตัวนั้นจะถูกเก็บลง flash แทนที่จะเก็บไว้ใน ram
เพราะมันจะไม่มีการเปลี่ยนค่าอีก ตอน compile มีค่าเป็นอะไร ก็ต้องมีค่าเท่านั้นไปตลอด

ถ้าใช้ const กับตัวแปร local ตัวแปรตัวนั้นจะยังเก็บไว้ใน ram เพราะค่าเริ่มต้นของ
ตัวแปร local มันจะถูกกำหนดได้ในขณะ runtime เท่านั้น ยังไงก็ต้องเก็บไว้ใน ram
แต่ถึงอย่างนั้นเราก็เอา pointer มาล้วงข้างได้ โดยประกาศตัวแปร pointer ที่ไม่ได้เป็น const
แล้วเอาไปชี้ตัวแปร const local ตัวนั้น แล้วเปลี่ยนค่าผ่าน pointer เอา แบบนี้
Code: [Select]
void function(void)
{
  const int x = 100;
  int *ptr = (int *)&x;

  printf("X is %d.\r\n", x);
  *ptr = 101;
  printf("X is %d.\r\n", x);
}

ผลลัพธ์คือ
Code: [Select]
X is 100.
X is 101.


ในทาง hardware ก็มีวิธีอยู่ 2 วิธีคือ

1. ถ้า mcu ตัวนั้นโปรแกรม flash ตัวเองได้ ก็เอาค่านั้นๆ ที่ไม่ต้องการเปลี่ยนอีก
โปรแกรมลง flash memory ไปเลย แล้วเวลาใช้งานก็เอาตัวแปร pointer to const
ชี้ไปยัง address flash นั้นๆ

สมมุติผมเก็บ address 0x10000000 ไว้โปรแกรมข้อมูล ข้อมูลผมเป็น struct ชื่อ config
ผมก็ประกาศตัวแปร pointer to const ชี้ไป address 0x10000000
Code: [Select]
const struct config *config_storage = (const struct config*)0x10000000;
หลังจากนั้นก็ใช้ mcu โปรแกรม flash address 0x10000000 ใหม่โดยกรอกข้อมูลใส่ตัวแปร struct config
แล้วก็โปรแกรมมันลงไปทั้ง struct โดย cast type เป็น uint8_t* หรือ void* ก็แล้วแต่
ฟังก์ชั่นโปรแกรม flash มันจะต้องการ
Code: [Select]
struct config tmp;

//ใส่ข้อมูลที่จะเขียนในตัวแปร tmp

flash_program((uint8_t*)&tmp, sizeof(struct config));

2. คือ mcu ระดับ high end เช่น arm cortex m4, m7 มันจะมี Memory Protection Unit (MPU)
ใช้สำหรับป้องกันการเข้าถึง memory address ต่างๆ นั่นเอง มันสามารถกำหนดได้ว่าจาก address region ไหน
ถึงไหน ทำอะไรได้ และห้ามทำอะไรได้ เช่น เขียนได้อย่างเดียว, อ่านได้อย่างเดียว, ห้าม execute เป็นต้น
Title: Re: มีคำสั่ง ห้ามเปลี่ยนแปลงค่าตัวแปรอีก ไหมครับ
Post by: TaoTao on September 07, 2018, 02:18:07 pm
ไม่มีโดยตรงครับ

ในทาง software ภาษา C มีคล้าย ๆ กันคือตัวแปรที่มี const นำหน้า คือตัวแปรคงที่
ต้องมีการกำหนดค่าเริ่มต้นตั้งแต่ประกาศตัวแปร compiler จะห้ามไม่ให้เปลี่ยนค่า
ตัวแปรคงที่ขณะ runtime

การใช้ const กับตัวแปร global และ local มีลักษณะต่างกันนิดหน่อย

ถ้าใช้ const กับตัวแปร global ตัวแปรตัวนั้นจะถูกเก็บลง flash แทนที่จะเก็บไว้ใน ram
เพราะมันจะไม่มีการเปลี่ยนค่าอีก ตอน compile มีค่าเป็นอะไร ก็ต้องมีค่าเท่านั้นไปตลอด

ถ้าใช้ const กับตัวแปร local ตัวแปรตัวนั้นจะยังเก็บไว้ใน ram เพราะค่าเริ่มต้นของ
ตัวแปร local มันจะถูกกำหนดได้ในขณะ runtime เท่านั้น ยังไงก็ต้องเก็บไว้ใน ram
แต่ถึงอย่างนั้นเราก็เอา pointer มาล้วงข้างได้ โดยประกาศตัวแปร pointer ที่ไม่ได้เป็น const
แล้วเอาไปชี้ตัวแปร const local ตัวนั้น แล้วเปลี่ยนค่าผ่าน pointer เอา แบบนี้
Code: [Select]
void function(void)
{
  const int x = 100;
  int *ptr = (int *)&x;

  printf("X is %d.\r\n", x);
  *ptr = 101;
  printf("X is %d.\r\n", x);
}

ผลลัพธ์คือ
Code: [Select]
X is 100.
X is 101.


ในทาง hardware ก็มีวิธีอยู่ 2 วิธีคือ

1. ถ้า mcu ตัวนั้นโปรแกรม flash ตัวเองได้ ก็เอาค่านั้นๆ ที่ไม่ต้องการเปลี่ยนอีก
โปรแกรมลง flash memory ไปเลย แล้วเวลาใช้งานก็เอาตัวแปร pointer to const
ชี้ไปยัง address flash นั้นๆ

สมมุติผมเก็บ address 0x10000000 ไว้โปรแกรมข้อมูล ข้อมูลผมเป็น struct ชื่อ config
ผมก็ประกาศตัวแปร pointer to const ชี้ไป address 0x10000000
Code: [Select]
const struct config *config_storage = (const struct config*)0x10000000;
หลังจากนั้นก็ใช้ mcu โปรแกรม flash address 0x10000000 ใหม่โดยกรอกข้อมูลใส่ตัวแปร struct config
แล้วก็โปรแกรมมันลงไปทั้ง struct โดย cast type เป็น uint8_t* หรือ void* ก็แล้วแต่
ฟังก์ชั่นโปรแกรม flash มันจะต้องการ
Code: [Select]
struct config tmp;

//ใส่ข้อมูลที่จะเขียนในตัวแปร tmp

flash_program((uint8_t*)&tmp, sizeof(struct config));

2. คือ mcu ระดับ high end เช่น arm cortex m4, m7 มันจะมี Memory Protection Unit (MPU)
ใช้สำหรับป้องกันการเข้าถึง memory address ต่างๆ นั่นเอง มันสามารถกำหนดได้ว่าจาก address region ไหน
ถึงไหน ทำอะไรได้ และห้ามทำอะไรได้ เช่น เขียนได้อย่างเดียว, อ่านได้อย่างเดียว, ห้าม execute เป็นต้น

โอ้ววว พระเจ้ายอด มันจอร์จมาก 😨
ขอบคุณมากมาย ก๊าบบบบ
ตรงประเด็นที่ต้องการเลย 😊