---------------------------------
use of volatile
---------------------------------
Its a qualifier.This keyword is especially valuable when you are interacting with hardware peripheral registers and such via memory-mapped I/O.
It is important to use volatile to declare all variables that are shared by asynchronous software entities, which is important in any kind of multithreaded programming.
int volatile g_flag_shared_with_isr;
uint8_t volatile * p_led_reg = (uint8_t *) 0x00080000;
The first example declares a global flag that can be shared between an ISR and some other part of the code (e.g., a background processing loop in main() or an RTOS task) without fear that the compiler will optimize (i.e., “delete”) the code you write to check for asynchronous changes to the flag’s value. It is important to use volatile to declare all variables that are shared by asynchronous software entities, which is important in any kind of multithreaded programming. (Remember, though, that access to global variables shared by tasks or with an ISR must always also be controlled via a mutex or interrupt disable, respectively.)
The second example declares a pointer to a hardware register at a known physical memory address (80000h)–in this case to manipulate the state of one or more LEDs. Because the pointer to the hardware register is declared volatile, the compiler must always perform each individual write. Even if you write C code to turn an LED on followed immediately by code to turn the same LED off, you can trust that the hardware really will receive both instructions. Because of the sequence point restrictions, you are also guaranteed that the LED will be off after both lines of the C code have been executed. The volatile keyword should always be used with creating pointers to memory-mapped I/O such as this.
---------------------------------
use of const
---------------------------------
uint16_t const max_temp_in_c = 1000;
In C, this variable will exist in memory at run-time, but will typically be located, by the linker, in a non-volatile memory area such as ROM or flash.
Any reference to the const variable will read from that location.
Another use of const is to mark a hardware register as read-only. For example:
uint8_t const * p_latch_reg = 0x10000000;
Declaring the pointer this way, any attempt to write to that physical memory address via the pointer (e.g., *p_latch_reg = 0xFF;) should result in a compile-time error.
---------------------------------
use of volatile and const
---------------------------------
1. Constant Addresses of (Read or Write) Hardware Registers
uint8_t volatile * const p_led_reg = (uint8_t *) 0x00080000;
p_led_reg IS A constant pointer TO A volatile 8-bit unsigned integer. This makes sure that p_led_reg contains address that will never change. Gives us surity that it will always point to same address every time. Typo mistake will not cause any undesired change to value at some different address.
2. Read-Only Shared-Memory Buffer
Another use for a combination of const and volatile is where you have two processors communicating via a shared memory area and you are coding the side of this communications that will only be reading from a shared memory buffer. In this case you could declare variables such as:
int const volatile comm_flag;
uint8_t const volatile comm_buffer[BUFFER_SIZE];
3. (Read-Only) Hardware Register
Sometimes you will run across a read-only hardware register. In addition to enforcing compile-time checking so that the software doesn’t try to overwrite the memory location, you also need to be sure that each and every requested read actually occurs. By declaring your variable IS A (constant) pointer TO A constant and volatile memory location you request all of the appropriate protections, as in:
uint8_t const volatile * const p_latch_reg = (uint8_t *) 0x10000000;
As you can see, the declarations of variables that involve both the volatile and const decorators can quickly become complicated to read. But the technique of combining C’s volatile and const keywords can be useful and even important. This is definitely something you should learn to master to be a master embedded software engineer.
use of volatile
---------------------------------
Its a qualifier.This keyword is especially valuable when you are interacting with hardware peripheral registers and such via memory-mapped I/O.
It is important to use volatile to declare all variables that are shared by asynchronous software entities, which is important in any kind of multithreaded programming.
int volatile g_flag_shared_with_isr;
uint8_t volatile * p_led_reg = (uint8_t *) 0x00080000;
The first example declares a global flag that can be shared between an ISR and some other part of the code (e.g., a background processing loop in main() or an RTOS task) without fear that the compiler will optimize (i.e., “delete”) the code you write to check for asynchronous changes to the flag’s value. It is important to use volatile to declare all variables that are shared by asynchronous software entities, which is important in any kind of multithreaded programming. (Remember, though, that access to global variables shared by tasks or with an ISR must always also be controlled via a mutex or interrupt disable, respectively.)
The second example declares a pointer to a hardware register at a known physical memory address (80000h)–in this case to manipulate the state of one or more LEDs. Because the pointer to the hardware register is declared volatile, the compiler must always perform each individual write. Even if you write C code to turn an LED on followed immediately by code to turn the same LED off, you can trust that the hardware really will receive both instructions. Because of the sequence point restrictions, you are also guaranteed that the LED will be off after both lines of the C code have been executed. The volatile keyword should always be used with creating pointers to memory-mapped I/O such as this.
---------------------------------
use of const
---------------------------------
uint16_t const max_temp_in_c = 1000;
In C, this variable will exist in memory at run-time, but will typically be located, by the linker, in a non-volatile memory area such as ROM or flash.
Any reference to the const variable will read from that location.
Another use of const is to mark a hardware register as read-only. For example:
uint8_t const * p_latch_reg = 0x10000000;
Declaring the pointer this way, any attempt to write to that physical memory address via the pointer (e.g., *p_latch_reg = 0xFF;) should result in a compile-time error.
---------------------------------
use of volatile and const
---------------------------------
1. Constant Addresses of (Read or Write) Hardware Registers
uint8_t volatile * const p_led_reg = (uint8_t *) 0x00080000;
p_led_reg IS A constant pointer TO A volatile 8-bit unsigned integer. This makes sure that p_led_reg contains address that will never change. Gives us surity that it will always point to same address every time. Typo mistake will not cause any undesired change to value at some different address.
2. Read-Only Shared-Memory Buffer
Another use for a combination of const and volatile is where you have two processors communicating via a shared memory area and you are coding the side of this communications that will only be reading from a shared memory buffer. In this case you could declare variables such as:
int const volatile comm_flag;
uint8_t const volatile comm_buffer[BUFFER_SIZE];
3. (Read-Only) Hardware Register
Sometimes you will run across a read-only hardware register. In addition to enforcing compile-time checking so that the software doesn’t try to overwrite the memory location, you also need to be sure that each and every requested read actually occurs. By declaring your variable IS A (constant) pointer TO A constant and volatile memory location you request all of the appropriate protections, as in:
uint8_t const volatile * const p_latch_reg = (uint8_t *) 0x10000000;
As you can see, the declarations of variables that involve both the volatile and const decorators can quickly become complicated to read. But the technique of combining C’s volatile and const keywords can be useful and even important. This is definitely something you should learn to master to be a master embedded software engineer.
No comments:
Post a Comment