I took a sample application code with FreeRTOS (v9.0) for the TI TM4C1294NCPDT microcontroller in Code Composer Studio (v12.1.0.00007). The code was compiled successfully and worked properly.
And I moved the same working code a step further to test the microcontroller’s Flash memory protection with the option of Execute-only," which does not allow copying the code from Flash. To do the protection, I need to choose “OFF” for --embedded_constants, which will tell the compiler (ti-cgt-arm_20.2.7.LTS) to embed the constants in different flash memory from code memory. Then I have to fill the microcontroller’s Flash registers.
With these compiler settings and registers, sample projects are working fine without FreeRTOS. When I did the same settings with a project that is using FreeRTOS, the compiler is listing the error “[E0002] PC-relative access violates disabling of embedded constants” in the Portable/CCS/ARM_CM4F/portasm.asm file.
Please check these error lines in portasm.asm
@ line 99: ldr r0, ulMaxSyscallInterruptPriorityConst
@ line 112: ldr r3, pxCurrentTCBConst
@ line 127: ldr r0, ulMaxSyscallInterruptPriorityConst
@ line 160: ldr r3, pxCurrentTCBConst
@ line 177: ldr r0, NVICOffsetConst
@ line 195: ldr.w r0, CPACRConst
Here are my doubts:
- What are these lines doing?
- How are these lines making the compiler show the mentioned error?
- How do I solve this error?
Thanks in advance.
Those lines are using PC-relative addressing to load the 32-bit address of a resource. The 32-bit address is stored within the code image, nearby the instruction that accesses the 32-bit address. This is a very common way to load a 32-bit address into a register in CM4 because there is no load-immediate instruction for 32-bit values and because the architecture provides a separate bus (DCode) for accessing these literals efficiently.
Are there varying levels of flash-readout protection available to you? Maybe there is a less extreme version that would allow the compiler/assembler to continue to use these normal coding conventions?
I would need to double-check the code, but the ARM processors have one basic limitation in addressing memory which means that to access an arbitrary location of memory, you tend to need to load an address constant into a register, but to get to that address constant, it needs to be located where a PC-relative access can get to the address constant. This means much ARM code can not have “Execute Only” permissions but needs the code to be able to do “Data Reads”.
I am not sure how that “Execute Only” option is supposed to work, you might check if it allows the code in the flash to still data access the flash. If not, I am not sure what they intended it for.
Adding to jeff and richard d’s posts - the address constant is stored at the end of the assembly function. With the additional flash protection on, either the processor is prevented from loading the constant because it’s considered a read, or the constants got moved too far away for the assembly instruction to be able to address and load it.