To check if a Cortex-M3 address is in Flash or SRAM memory, you need to understand the memory map of the Cortex-M3 architecture. The Cortex-M3 has a Von Neumann architecture with a unified address space for both code and data. This means that both Flash and SRAM are mapped into the same 4GB address space.
The exact mapping of Flash and SRAM depends on the particular microcontroller implementation. But typically, Flash memory is mapped to the lower addresses starting from 0x00000000, while SRAM is mapped to higher addresses.
There are a few methods you can use to check if an address is in Flash or SRAM:
1. Check Against Flash and SRAM Boundaries
Most Cortex-M3 microcontrollers define symbols that specify the start and end addresses of both Flash and SRAM memory in their memory map. For example: #define FLASH_BASE 0x00000000 #define FLASH_END 0x0003FFFF #define SRAM_BASE 0x20000000 #define SRAM_END 0x2000FFFF
So you can check if an address addr is in Flash memory by: if ((addr >= FLASH_BASE) && (addr <= FLASH_END)) { // addr is in Flash }
And check if addr is in SRAM: if ((addr >= SRAM_BASE) && (addr <= SRAM_END)) { // addr is in SRAM }
2. Sections and Symbols
The linker script will define different sections for Flash and SRAM memory. Code and constants end up in Flash memory sections like .text, while variables get allocated to SRAM sections like .bss and .data.
You can check which section a symbol belongs to using the linker map file. This will tell you if the symbol is stored in Flash or SRAM.
3. Hardware Memory Protection Units
Some Cortex-M3 microcontrollers have Memory Protection Units (MPUs) that can be used to set access permissions for different memory regions. You can configure the MPU to generate a fault on an invalid access.
For example, you can configure Flash as read-only and SRAM as read-write. A read-write access to Flash would fault, telling you the address is in Flash memory.
4. Try Reading/Writing and Check for Bus Fault
As Flash is read-only, a simple way to check if an address is in Flash is to try writing to it and check for a bus fault exception. For example: uint32_t *ptr = (uint32_t *)addr; *ptr = 0; // try writing to addr if (SCB->CFSR & SCB_CFSR_BUSFAULTSR_Msk) { // Bus fault occurred, addr is in Flash } else { // No bus fault, addr is in SRAM }
Just writing to the address will not modify Flash content, but will generate a bus fault if addr is in read-only memory.
You need to enable bus fault exceptions in the NVIC for this to work.
5. Compiler Built-ins
Some compilers like GCC provide built-in functions to check which memory region an address belongs to: if (__is_flash_address(addr)) { // addr is in Flash } if (__is_sram_address(addr)) { // addr is in SRAM }
This uses the linker script memory map to check if an address is in Flash or SRAM.
6. Memory Barriers
When accessing memory, the order of accesses between Flash and SRAM needs special consideration because of the different wait states. The processor uses memory barriers to ensure ordering.
So if your code requires a memory barrier in between accesses, it likely indicates the memory regions are different (i.e. one is Flash and one is SRAM).
7. Toggle GPIO Pin
A simple trick is to toggle a GPIO pin within your code when accessing different memory regions. For example: // Access SRAM GPIOA->ODR ^= (1 << 5); // Access Flash GPIOA->ODR ^= (1 << 5);
Observing the GPIO pin on an oscilloscope will show the toggles and indicate when Flash vs SRAM is being accessed.
8. Toolchain Debug/Diagnostic Features
Most compiler/IDE toolchains have debug views and other features that can reveal information about memory accesses.
For example, you can view a memory map, set data breakpoints, and see disassembly that distinguishes between accesses to different memory regions.
Consult your toolchain documentation to find these useful features.
9. Know the Hardware Architecture
Ultimately, understanding the Cortex-M3 and microcontroller architecture will help you intuitively know whether an address is pointing to Flash or SRAM.
For example, constant data and executable code can only be in Flash. Variables have to be in SRAM. Addresses below 0x20000000 are likely Flash, while above are SRAM.
Knowing the fundamentals of the hardware architecture and memory mapping will go a long way for debugging and optimizing your Cortex-M3 code.
10. Conclusion
In summary, there are several methods you can use to check if a Cortex-M3 address is pointing to Flash or SRAM memory:
- Check against Flash and SRAM base/end address boundaries
- Examine sections and symbols in the linker map file
- Configure MPU regions and check for access faults
- Try reading/writing and check for bus faults
- Use compiler built-ins like __is_flash_address()
- Insert memory barriers and examine code flow
- Toggle GPIO pins to indicate memory region access
- Leverage toolchain debug views and diagnostics
- Understand the hardware memory architecture
Checking the memory region is useful for debugging and optimizing Cortex-M3 code for maximum performance. With the techniques described, you should have no trouble identifying whether an address lies in Flash or SRAM memory.