The TI TM4C129 series ARM Cortex-M4F based microcontrollers have the option of Execute-Only Protection for the flash. Section 8.2.3.5 Execute-Only Protection of the datasheet contains the following, which recognises the impact on the program:
Execute-only protection prevents both modification and visibility to a protected flash block. ...
Literal data introduces a complication to the protection mechanism. When C code is compiled and linked, literal data (constants, and so on) is typically placed in the text section, between functions, by the compiler. The literal data is accessed at run time through the use of the LDR instruction, which loads the data from memory using a PC-relative memory address. The execution of the LDR instruction generates a read transaction across the Cortex-M3's DCode bus, which is subject to the execute-only protection mechanism. If the accessed block is marked as execute only, the transaction is blocked, and the processor is prevented from loading the constant data and, therefore, inhibiting correct execution.
The TI ARM Optimizing C/C++ Compiler v20.2.0.LTS has the following option in 2.3.4 Run-Time Model Options which allows the compiler to know not to place constants in the "execute code only" section:
--embedded_constants={on|off} By default the compiler embeds constants in functions. These constants can include literals, addresses, strings, etc. This is a problem if you wants to prevent reads from a memory region that contains only executable code. To enable the generation of "execute only code", the compiler provides the --embedded_constants=[on|off] option. If the option is not specified, it is assumed to be on. The option is available on the following devices: Cortex-A8, Cortex-M3, Cortex-M4, and Cortex-R4.
While the question is asking a general architecture question, the above example demonstrates how the compilers for microcontrollers may address the problem.
In response to the comment:
So, if my understanding is correct, the linker will put the literal in a dedicated flash memory area. Then how do the CPU access this data while also fetching the next instruction ? It will require to do two reads of the same flash memory module at the same time –
Wheatley
For the example of the ARM Cortex-M4 there are two buses in the Code memory map:
- Instruction fetches are performed over the
ICode
bus.
- Data accesses are performed over the
DCode
bus.
The answer in STM32 I-CODE and D-CODE buses shows a Flash interface which arbitrates access from the ICode and DCode buses to the flash memory. While there is a single flash memory, it has a wider data interface (128 bits) than the ICode and DCode buses (32-bit data bus). Prefetching or caching in flash memory module may hide some latency as a result of accesses from both the ICode and DCode buses.