The NVM3 driver provides a way for an application to safely store and retrieve variable size objects in a page based non-volatile memory. The driver is resilient to power loss or reset events, ensuring that objects retrieved from the driver are in a valid state.
Procedures to build the NVM3 example:
1. It needs to define the NVM3_MAX_OBJECT_SIZE in your IDE (e.g. NVM3_MAX_OBJECT_SIZE=4096), it is set to 1900 by default in nvm3.h.
#define NVM3_MAX_OBJECT_SIZE_LOW_LIMIT 204U ///< Minimum value for the max object size
#define NVM3_MAX_OBJECT_SIZE_HIGH_LIMIT 4096U ///< Maximum value for the max object size
#define NVM3_MAX_OBJECT_SIZE_DEFAULT 1900U ///< Default value for the max object size
#if !defined(NVM3_MAX_OBJECT_SIZE)
#define NVM3_MAX_OBJECT_SIZE NVM3_MAX_OBJECT_SIZE_DEFAULT
#endif
For IAR:
For Simplicity IDE:
2. It needs to define a section in linker file that will be used for NVM3. Example below is to set the bottom of 24 kB flash for nvm3Data_section.
For IAR linker file (.icf) :
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x00000000;
define symbol __ICFEDIT_region_ROM_end__ = (0x00000000+0x00200000-0x6000-1);
define symbol __ICFEDIT_region_NVM3_start__ = __ICFEDIT_region_ROM_end__ + 1;
define symbol __ICFEDIT_region_NVM3_end__ = (0x00000000+0x00200000-1);
define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__ = (0x20000000+0x00080000-1);
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x1000;
define symbol __ICFEDIT_size_heap__ = 0x1000;
/**** End of ICF editor section. ###ICF###*/
define memory mem with size = 4G;
define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
define region NVM3_region = mem:[from __ICFEDIT_region_NVM3_start__ to __ICFEDIT_region_NVM3_end__];
define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__];
define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
initialize by copy { readwrite };
do not initialize { section .noinit };
keep { section .intvec };
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
place in ROM_region { readonly };
place in NVM3_region { readonly section nvm3Data_section };
place in RAM_region { readwrite,
block CSTACK,
block HEAP };
4. In source file, uses macro NVM3_DEFINE_SECTION_STATIC_DATA in nvm3.h to define a NVM3 section that matches with the linker file in step 2. Example below creates a 24 kB (6 x 4 kB) nvm3Data_section on EFM32GG11.
5. In source file, uses macro NVM3_DEFINE_SECTION_INIT_DATA in nvm3.h to define a nvm3_Init_t struct for NVM3 initialization and the parameter in this macro must match with parameter (nvm3Data in example below) of NVM3_DEFINE_SECTION_STATIC_DATA in step 4.
The maxObjectSize (default is NVM3_MAX_OBJECT_SIZE_HIGH_LIMIT = 4096) in nvm3_initi_t must be less than or equal to the NVM3_MAX_OBJECT_SIZE that defined in step 1.
Question: Simplicity Commander detects the device, and the upload to the target device seems to complete just fine. However, the program gets hung up on the startup file.
Answer:
If the program hung up at the default handler, make sure there is a bootloader on the device. For series 1 devices, the bootloader is at 0x0FE10000.
If there is no bootloader on your device there are two option as below:
(2) If the factory bootloader isn't needed because firmware updates are handled in a different fashion, then disable it. This can be done by writing a 0 to bit 1 of Configuration Word 0 (CLW0) at offset 0x1E8 in the lock bits page.
What is the minimum voltage required to retain RAM values on EFM32 devices?
Answer:
The minimum voltage for RAM values to be retained is the minimum operating voltage in the General Operating Conditions table of the datasheet. In the case where there are multiple values for different supply rails, the minimum is the minimum DVDD supply voltage.
On series 0 devices, this is typically 1.98 V. On series 1 devices, this is typically 1.62 V.
This minimum value applies across all energy modes.
The goal of this article is to provide a brief introduction about the GNU assemble startup file of EFM32 and EFR32 Arm Cortex M4 devices. With this article, you can understand how the Cortex M4 processor starts.
We will take the GNU assembler startup file of EFM32GG11 startup_efm32gg11b.S as example, you can get the startup file in the folder below after installing the gecko SDK.
Bear in mind, the GNU Assembler (known as GAS) and ARM assembler are two different syntaxes for assembly language source code, however, the organization of the startup code are similar.
Generally, it will specify the instruction set syntax. There are two slightly different syntaxes are support for ARM and THUMB instructions, divided and unified.
.syntax unified
.arch armv7e-m
The ".arch" instruction used to select the target architecture. What the architecture of Cortex-M4 is ARMv7E-M.
Declaration of the Stack area
The stack is a contiguous area of memory that may be used for storage of local variables and for passing additional arguments to subroutines when there are insufficient argument registers available.
The assembly code below declares the stack area, and the ".align 3" makes the starting of this area on a multiple of 8-byte (2^3 = 8) boundary.
If didn’t define the stack size with the macro “__STACK_SIZE”, it will declare a constant Stack_Size of value 0x00000400 with the directive “.equ”.
".globl" directive makes the symbol “__StackTop” and “__StackLimit” visible to GNU linker.
Then emit Stack_Size bytes with the directive “.space Stack_Size”, it will fill the section with zero by default if didn’t specify the fill parameter for the “.space” directive.
Then set the size associated with the symbol name __StackLimit, and the size in bytes is computed from the expression “. - __StackLimit”.
The heap is a pool of memory that are managed by the processor itself (for example, with the C malloc function). It is typically used for the creation of dynamic data objects.
The assembly code below declares the heap area which are similar as the stack declaration. The labels “__HeapBase” and “__HeapLimit” indicate the starting and the ending of the heap area respectively.
What the __HeapBase and __HeapLimit are defined in the linker file.
Vector table
The vector table contains the reset value of the stack pointer, and the start addresses for all exception and interrupt handlers. Figure below shows the order of the Cortex-M4 exception and interrupt vectors in the vector table.
In general, the vector table is fixed at address 0x00000000 on system reset. The privileged software can write to the VTOR register to relocate the vector table start address to a different memory location, in the range 0x00000080 to 0x3FFFFF80.
Once an exception or interrupt is triggered, the processor automatically jumps to the corresponding address in the vector table which contains an address to the relevant exception or interrupt handlers (ISR).
For more information about each exception handler of the Cortex-M4, the reader is referred to the ARM Cortex-M4 Technical Reference Manual.
The assembly code above declared the vectors section with a multiple of 4-bytes (2^2 = 4) boundary, and then places all of the exception and interrupt handlers into the vector section with the directive “.long” since all of the handlers are 32-bit values.
As shown in the figure above, the first 32-bit of the vector table is the value for initializing the stack pointer. And the default value here is “__StackTop” that correspond to the end of RAM. So it will always initialize the stack pointer as the “__StackTop” after resetting.
At the ending, set the size of the __Vectors area, and calculate the size by subtracting the address of __Vectors from the current address.
Assembler code of Reset handler
After defining the vector table, we will discuss about the reset handler in the text segment.
Reset is invoked on power up or a warm reset. The exception model treats reset as a special form of exception. When reset is asserted, the operation of the processor stops, potentially at any point in an instruction.
When reset is deasserted, execution restarts from the address provided by the reset entry in the vector table, which is “Reset_Handler” in our example.
“.type” directive set the symbol “Reset_Handler” to be a function symbol.
If didn’t define the macro __NO_SYSTEM_INIT, it will load the address of “SystemInit” function to R0, and then branch to the label “SystemInit” which defined in the “system_efm32gg11b.c” for system initialization (e.g. set the Vector Table Offset) before the main() routine and any data has been initialized.
After resetting the system, it will branch to the function “ _start”. In fact, the function is provided by the C standard library, in a file called crt0.o, which include a set of execution startup routines to perform initialization and then call program’s main function.
The source code of crt0.s for ARM Cortex-M can be found on the link below with the path newlib/libc/sys/arm/crt0.S, and you can find the call to main() around line 400.
In fact, before branching to the main function, there are much assembler code used for copying data from read only memory to RAM, and clearing the BSS sections.
Definition of interrupt handler
During the code execution, there might be exception or interrupt occurs, and the processor will start executing the exception or interrupt handler.
This “.weak” directive sets the weak attribute on the symbol “Default_Handler”, if the symbol does not already exist in the source code, it will be created. And by default, the handler is just an endless loop by the directive “b .”
And then use the commands “.macro” and “.endm” to define a macro to define the default handlers for all of the exception and interrupt except Reset.
Define a macro called “def_irq_handler” with an argument “handler_name”, the macro will set the symbol “\handler_name” as weak, and then set the value of the symbol “\handler_name” to “Default_Handler”.
For e.g. look at the NMI exception handler above, with the definition of the macro, “def_irq_handler NMI_Handler” is equivalent to the assembly input below:
32-bit Knowledge Base
DMA Request on PRS
EFM32 Series 0 (µDMA) :
EFM32 Series 1 (LDMA):
NVM3 Example
The NVM3 driver provides a way for an application to safely store and retrieve variable size objects in a page based non-volatile memory. The driver is resilient to power loss or reset events, ensuring that objects retrieved from the driver are in a valid state.
Procedures to build the NVM3 example:
1. It needs to define the NVM3_MAX_OBJECT_SIZE in your IDE (e.g. NVM3_MAX_OBJECT_SIZE=4096), it is set to 1900 by default in nvm3.h.
For IAR:
For Simplicity IDE:
2. It needs to define a section in linker file that will be used for NVM3. Example below is to set the bottom of 24 kB flash for nvm3Data_section.
For IAR linker file (.icf) :
For Simplicity IDE linker file (.ld) :
3. Select the NVM3 library from path below (Windows) for corresponding device (M0+, M3, or M4) and development platform (GCC or IAR).
For IAR:
For Simplicity IDE:
4. In source file, uses macro NVM3_DEFINE_SECTION_STATIC_DATA in nvm3.h to define a NVM3 section that matches with the linker file in step 2. Example below creates a 24 kB (6 x 4 kB) nvm3Data_section on EFM32GG11.
5. In source file, uses macro NVM3_DEFINE_SECTION_INIT_DATA in nvm3.h to define a nvm3_Init_t struct for NVM3 initialization and the parameter in this macro must match with parameter (nvm3Data in example below) of NVM3_DEFINE_SECTION_STATIC_DATA in step 4.
The maxObjectSize (default is NVM3_MAX_OBJECT_SIZE_HIGH_LIMIT = 4096) in nvm3_initi_t must be less than or equal to the NVM3_MAX_OBJECT_SIZE that defined in step 1.
6. Terminal output after running the NVM3 example:
Attached are NVM3 example projects for IAR (EFM32GG11, EFM32PG12, and EFM32TG11) and Simplicity IDE (EFM32GG11).
For 32-bit MCU SDK 5.6.1.0:
nvm3_example.zip (IAR)
SLSTK3701A_nvm3.sls (Simplicity IDE)
For 32-bit MCU SDK 5.7.1.0 or above:
nvm3_example_v5.7.1.zip (IAR)
SLSTK3701A_nvm3_v5.7.1.sls (Simplicity IDE)
NVM3_MAX_OBJECT_SIZE (= maxObjectSize )
Program gets hung up on the startup file
Question: Simplicity Commander detects the device, and the upload to the target device seems to complete just fine. However, the program gets hung up on the startup file.
Answer:
If the program hung up at the default handler, make sure there is a bootloader on the device. For series 1 devices, the bootloader is at 0x0FE10000.
If there is no bootloader on your device there are two option as below:
(1) Flash the bootloader binary file. One can get these binaries in the AN0003 app note through Studio, or from here: http://www.silabs.com/documents/public/example-code/an0003-efm32-uart-bootloader.zip
(2) If the factory bootloader isn't needed because firmware updates are handled in a different fashion, then disable it. This can be done by writing a 0 to bit 1 of Configuration Word 0 (CLW0) at offset 0x1E8 in the lock bits page.
Minimum RAM Retention Voltage
Question:
What is the minimum voltage required to retain RAM values on EFM32 devices?
Answer:
The minimum voltage for RAM values to be retained is the minimum operating voltage in the General Operating Conditions table of the datasheet. In the case where there are multiple values for different supply rails, the minimum is the minimum DVDD supply voltage.
On series 0 devices, this is typically 1.98 V. On series 1 devices, this is typically 1.62 V.
This minimum value applies across all energy modes.
Understand the GNU assembler startup file of cortex M4
Introduction:
The goal of this article is to provide a brief introduction about the GNU assemble startup file of EFM32 and EFR32 Arm Cortex M4 devices. With this article, you can understand how the Cortex M4 processor starts.
We will take the GNU assembler startup file of EFM32GG11 startup_efm32gg11b.S as example, you can get the startup file in the folder below after installing the gecko SDK.
Bear in mind, the GNU Assembler (known as GAS) and ARM assembler are two different syntaxes for assembly language source code, however, the organization of the startup code are similar.
For more information about the GNU assembler and ARM assemble, please refer to the online documentation here.
https://ftp.gnu.org/old-gnu/Manuals/gas-2.9.1/html_chapter/as_toc.html
http://www.keil.com/support/man/docs/armasm/
Overview of the Startup code:
The startup code consist of few parts below.
Architecture and syntax
Generally, it will specify the instruction set syntax. There are two slightly different syntaxes are support for ARM and THUMB instructions, divided and unified.
The ".arch" instruction used to select the target architecture. What the architecture of Cortex-M4 is ARMv7E-M.
Declaration of the Stack area
The stack is a contiguous area of memory that may be used for storage of local variables and for passing additional arguments to subroutines when there are insufficient argument registers available.
The assembly code below declares the stack area, and the ".align 3" makes the starting of this area on a multiple of 8-byte (2^3 = 8) boundary.
If didn’t define the stack size with the macro “__STACK_SIZE”, it will declare a constant Stack_Size of value 0x00000400 with the directive “.equ”.
".globl" directive makes the symbol “__StackTop” and “__StackLimit” visible to GNU linker.
Then emit Stack_Size bytes with the directive “.space Stack_Size”, it will fill the section with zero by default if didn’t specify the fill parameter for the “.space” directive.
Then set the size associated with the symbol name __StackLimit, and the size in bytes is computed from the expression “. - __StackLimit”.
The linker file will set the stack top to end of RAM, and stack limit move down by size of stack_dummy section.
Declaration of the Heap area
The heap is a pool of memory that are managed by the processor itself (for example, with the C malloc function). It is typically used for the creation of dynamic data objects.
The assembly code below declares the heap area which are similar as the stack declaration. The labels “__HeapBase” and “__HeapLimit” indicate the starting and the ending of the heap area respectively.
What the __HeapBase and __HeapLimit are defined in the linker file.
Vector table
The vector table contains the reset value of the stack pointer, and the start addresses for all exception and interrupt handlers. Figure below shows the order of the Cortex-M4 exception and interrupt vectors in the vector table.
In general, the vector table is fixed at address 0x00000000 on system reset. The privileged software can write to the VTOR register to relocate the vector table start address to a different memory location, in the range 0x00000080 to 0x3FFFFF80.
Once an exception or interrupt is triggered, the processor automatically jumps to the corresponding address in the vector table which contains an address to the relevant exception or interrupt handlers (ISR).
For more information about each exception handler of the Cortex-M4, the reader is referred to the ARM Cortex-M4 Technical Reference Manual.
The assembly code above declared the vectors section with a multiple of 4-bytes (2^2 = 4) boundary, and then places all of the exception and interrupt handlers into the vector section with the directive “.long” since all of the handlers are 32-bit values.
As shown in the figure above, the first 32-bit of the vector table is the value for initializing the stack pointer. And the default value here is “__StackTop” that correspond to the end of RAM. So it will always initialize the stack pointer as the “__StackTop” after resetting.
At the ending, set the size of the __Vectors area, and calculate the size by subtracting the address of __Vectors from the current address.
Assembler code of Reset handler
After defining the vector table, we will discuss about the reset handler in the text segment.
Reset is invoked on power up or a warm reset. The exception model treats reset as a special form of exception. When reset is asserted, the operation of the processor stops, potentially at any point in an instruction.
When reset is deasserted, execution restarts from the address provided by the reset entry in the vector table, which is “Reset_Handler” in our example.
“.type” directive set the symbol “Reset_Handler” to be a function symbol.
If didn’t define the macro __NO_SYSTEM_INIT, it will load the address of “SystemInit” function to R0, and then branch to the label “SystemInit” which defined in the “system_efm32gg11b.c” for system initialization (e.g. set the Vector Table Offset) before the main() routine and any data has been initialized.
After resetting the system, it will branch to the function “ _start”. In fact, the function is provided by the C standard library, in a file called crt0.o, which include a set of execution startup routines to perform initialization and then call program’s main function.
The source code of crt0.s for ARM Cortex-M can be found on the link below with the path newlib/libc/sys/arm/crt0.S, and you can find the call to main() around line 400.
https://developer.arm.com/open-source/gnu-toolchain/gnu-rm
In fact, before branching to the main function, there are much assembler code used for copying data from read only memory to RAM, and clearing the BSS sections.
Definition of interrupt handler
During the code execution, there might be exception or interrupt occurs, and the processor will start executing the exception or interrupt handler.
This “.weak” directive sets the weak attribute on the symbol “Default_Handler”, if the symbol does not already exist in the source code, it will be created. And by default, the handler is just an endless loop by the directive “b .”
And then use the commands “.macro” and “.endm” to define a macro to define the default handlers for all of the exception and interrupt except Reset.
Define a macro called “def_irq_handler” with an argument “handler_name”, the macro will set the symbol “\handler_name” as weak, and then set the value of the symbol “\handler_name” to “Default_Handler”.
For e.g. look at the NMI exception handler above, with the definition of the macro, “def_irq_handler NMI_Handler” is equivalent to the assembly input below:
So the default handlers of all of the exception and interrupt handlers except Reset will be set as “Default_Handler” which is an endless loop.
Reference:
GNU Assembler Manual
https://ftp.gnu.org/old-gnu/Manuals/gas-2.9.1/html_chapter/as_toc.html
Using ld (The GNU linker)
https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_mono/ld.html
Cortex-M4 Device Generic User Guide
http://infocenter.arm.com/help/topic/com.arm.doc.dui0553a/DUI0553A_cortex_m4_dgug.pdf