Difference between revisions of "Const and volatile type qualifiers"

From Teknologisk videncenter
Jump to: navigation, search
m (Example 1)
m (added Category:Embedded using HotCat)
 
(7 intermediate revisions by the same user not shown)
Line 1: Line 1:
 +
{{TOCright}}
 
=const=
 
=const=
 
''const'' means  that something is not modifiable, so a data object that is declared with const as a part of its type specification must not be assigned to in any way during the run of a program.
 
''const'' means  that something is not modifiable, so a data object that is declared with const as a part of its type specification must not be assigned to in any way during the run of a program.
 
=volatile=
 
=volatile=
 
The use of ''volatile'' ensures that the compiler always carries out the memory accesses, rather than optimizing them out (for example if the access is in a loop).
 
The use of ''volatile'' ensures that the compiler always carries out the memory accesses, rather than optimizing them out (for example if the access is in a loop).
 +
=Rules of engagement=
 +
<source lang=c>
 +
int const xxx;
 +
|    |    |
 +
|    |    +-----------------> xxx is a
 +
|    +----------------------> constant
 +
+---------------------------> integer
 +
 +
int const *ptr;
 +
|    |  | |
 +
|    |  | +----------------> ptr is a
 +
|    |  +------------------> pointer to a
 +
|    +---------------------> constant
 +
+---------------------------> integer
 +
 +
int * const ptr;
 +
|  | |    |
 +
|  | |    +---------------> ptr is a
 +
|  | +---------------------> constant
 +
|  +-----------------------> pointer to an
 +
+---------------------------> integer
 +
 +
int const * const ptr;
 +
|    |  |  |    |
 +
|    |  |  |    +---------> ptr is a
 +
|    |  |  +--------------> constant
 +
|    |  +------------------> pointer to a
 +
|    +----------------------> constant
 +
+---------------------------> integer
 +
 +
int volatile * const ptr;
 +
|    |    |  |    |
 +
|    |    |  |    +------> ptr is a
 +
|    |    |  +-----------> constant
 +
|    |    +---------------> pointer to a
 +
|    +---------------------> volatile
 +
+---------------------------> integer
 +
 +
int volatile const * ptr;
 +
|    |    |    |  |
 +
|    |    |    |  +------> ptr is a
 +
|    |    |    +---------> pointer to
 +
|    |    +---------------> constant
 +
|    +---------------------> volatile
 +
+---------------------------> integer
 +
 +
 +
 +
</source>
  
 
=Memorymapped access to a register=
 
=Memorymapped access to a register=
Line 8: Line 58:
 
In the example below the register 32 bit register located in memory at address 0x40000 can be accessed through the ''uartreg'' pointer.   
 
In the example below the register 32 bit register located in memory at address 0x40000 can be accessed through the ''uartreg'' pointer.   
  
 +
 +
In the example below '''uartreg''' is a pointer pointing to a unsigned int 0x40000. The pointer value in memory 0x40000 is a constant not what it points to in memory. Fx. a peripheral register.
 
<source lang=c>
 
<source lang=c>
  
Line 15: Line 67:
 
*uartreg |= 0x1  // *uartreg's contents is OR'et to 0x1. New contents = 0x80000001
 
*uartreg |= 0x1  // *uartreg's contents is OR'et to 0x1. New contents = 0x80000001
 
</source>
 
</source>
 +
 
==Example 2==
 
==Example 2==
 
{|
 
{|
Line 24: Line 77:
 
|-
 
|-
 
|
 
|
===Reading the Flash size register===
+
===Method 1: Reading the Flash size register===
 
<source lang=c>
 
<source lang=c>
 
  uint16_t volatile * const flashsize = (uint16_t *) 0x1ffff7e0;
 
  uint16_t volatile * const flashsize = (uint16_t *) 0x1ffff7e0;
 +
 
  printf("Flashsize: %i KB\n\r", (int) *flashsize );
 
  printf("Flashsize: %i KB\n\r", (int) *flashsize );
 
</source>
 
</source>
 
On the [[STM32F107VC]] the output to stdout would be '''Flashsize: 256 KB'''
 
On the [[STM32F107VC]] the output to stdout would be '''Flashsize: 256 KB'''
 +
|-
 +
|
 +
===Method 2: Reading the Flash size register===
 +
<source lang=c>
 +
#define F_SIZE ((volatile uint16_t * const) 0x1ffff7e0) // Flash Size
 +
 +
printf("Flashsize: %i KB\n\r", (int) *F_SIZE );
 +
</source>
 +
On the [[STM32F107VC]] the output to stdout would be '''Flashsize: 256 KB'''
 +
===Method 3: Reading the Flash size register===
 +
 +
Putting the pointer in the macro
 +
<source lang=c>
 +
#define F_SIZE (*(int volatile  * const) 0x1ffff7e0) // Flash Size
 +
 +
printf("Flashsize: %i KB\n\r", (int) F_SIZE );
 +
</source>
 +
On the [[STM32F107VC]] the output to stdout would be '''Flashsize: 256 KB'''
 +
 
|-
 
|-
 
|}
 
|}
Line 37: Line 110:
 
*[http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka3750.html armcc/tcc: Placing C variables at specific addresses - memory-mapped peripherals]
 
*[http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka3750.html armcc/tcc: Placing C variables at specific addresses - memory-mapped peripherals]
 
[[Category:C]][[Category:C++]]
 
[[Category:C]][[Category:C++]]
 +
[[Category:Embedded]]
 
*[http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka3736.html Use of 'const' and 'volatile']
 
*[http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka3736.html Use of 'const' and 'volatile']

Latest revision as of 08:03, 5 October 2016

const

const means that something is not modifiable, so a data object that is declared with const as a part of its type specification must not be assigned to in any way during the run of a program.

volatile

The use of volatile ensures that the compiler always carries out the memory accesses, rather than optimizing them out (for example if the access is in a loop).

Rules of engagement

int const xxx;
 |    |    |
 |    |    +-----------------> xxx is a
 |    +----------------------> constant
 +---------------------------> integer

int const *ptr;
 |     |  | |
 |     |  | +----------------> ptr is a
 |     |  +------------------> pointer to a
 |     +---------------------> constant
 +---------------------------> integer

int * const ptr;
 |   | |     |
 |   | |     +---------------> ptr is a
 |   | +---------------------> constant
 |   +-----------------------> pointer to an
 +---------------------------> integer

int const * const ptr;
 |    |   |   |    |
 |    |   |   |    +---------> ptr is a
 |    |   |   +--------------> constant
 |    |   +------------------> pointer to a
 |    +----------------------> constant
 +---------------------------> integer

int volatile * const ptr;
 |     |     |   |    |
 |     |     |   |    +------> ptr is a
 |     |     |   +-----------> constant
 |     |     +---------------> pointer to a
 |     +---------------------> volatile
 +---------------------------> integer

int volatile const * ptr;
 |     |     |     |  |
 |     |     |     |  +------> ptr is a
 |     |     |     +---------> pointer to
 |     |     +---------------> constant
 |     +---------------------> volatile
 +---------------------------> integer

Memorymapped access to a register

Example 1

In the example below the register 32 bit register located in memory at address 0x40000 can be accessed through the uartreg pointer.


In the example below uartreg is a pointer pointing to a unsigned int 0x40000. The pointer value in memory 0x40000 is a constant not what it points to in memory. Fx. a peripheral register.

unsigned int volatile * const uartreg = (unsigned int *) 0x40000;
*uartreg = 0x80000000; // Assign 80000000 to the 32 bit register located at memeory address 0x40000
...some code...
*uartreg |= 0x1  // *uartreg's contents is OR'et to 0x1. New contents = 0x80000001

Example 2

From the Cortex M STM32F107VCs Reference manual - See picture below - that the size of the embedded Flash can be seen in KB from the Flash size register at memory location 0x1FFFF7E0.
STM32F107VC Flash size register

Method 1: Reading the Flash size register

 uint16_t volatile * const flashsize = (uint16_t *) 0x1ffff7e0;

 printf("Flashsize: %i KB\n\r", (int) *flashsize );

On the STM32F107VC the output to stdout would be Flashsize: 256 KB

Method 2: Reading the Flash size register

#define F_SIZE	((volatile uint16_t * const) 0x1ffff7e0)		// Flash Size 

 printf("Flashsize: %i KB\n\r", (int) *F_SIZE );

On the STM32F107VC the output to stdout would be Flashsize: 256 KB

Method 3: Reading the Flash size register

Putting the pointer in the macro

#define F_SIZE	(*(int volatile  * const) 0x1ffff7e0)		// Flash Size 

 printf("Flashsize: %i KB\n\r", (int) F_SIZE );

On the STM32F107VC the output to stdout would be Flashsize: 256 KB

Links