I am working on a project with 2 applications.
One builds and runs fine. The other one builds fine but crashes upon the initialization of the BSS (zero_fill_bss function). The init code is the same for the 2 apps, as for the linker file and building options.
zero_fill_bss is provided by the EWL in both cases.
The crash occurs when attempting to execute the very first instruction of zero_fill_bss. To make things clear, please have a look at the following picture:
The crash occurs when trying to execute the first instruction (yellow).
The code aims at calling memset as follow:
"memset(address_bss, 0, size_bss)"
it works as follow:
- the 3 LDR loads hardcoded parameters (the first one is the address of the BSS). Those parameters are buried into the code of the function and are accessed relatively (hence the use of PC). See the arrows. (NOTE: this implies that "instructions" from 03e654 to 03e658 are actually data)
- then it puts 0 into r1, this is the second argument to memset
- then it computes the size of the BSS (SUBS intruction)
- finally it calls memset (BX instruction)
In this case, the first LDR triggers a HardFault. I do not understand why. PC+0x10 properly gives 0x03e654 (take into account that PC was incremented since the instruction was read), which is a properly aligned address.
- calling code is in thumb mode
- this function obviously is in thumb mode (note the +2 increment between eg movs and subs)
- the caller uses BL, which is OK
- LDR are doubleword thumb instructions (hence 32 btis), unless I am mistaken (it is a word instruction for the ARM architecture)
ARM information center about LDR states that:
Use of PC
In Thumb instructions you can use PC for Rt in LDR word instructions and PC for Rn in LDR instructions. Other uses of PC in these Thumb instructions are not permitted.
In this case, PC is used as Rn.
The LDR being a doubleword instruction here (unless I am mistaken), I would have thought "voilà! this instruction is illegal, hence the crash".
- the same code works for the other application (but addresses are different)
- this code is part of EWL (so I would trust it)
Finally, if I comment some application code arbitrarily, the initialization works fine.
This makes me think that there is some issue with the addresses in memory.
- addresses are properly aligned
- LDR seems to be used properly since it works for the other application and comes from EWL
- there seems to be some problem with the addresses when the crash occurs
Do you have an idea?
CodeWarrior For MCU v10.6
Toolchain ARM (not GCC)
zero_fill_bss comes from librt_Thumb_LE_v7M.a