Hi all,
our application will exceed the 2 MB limit of the internal flash in the near future, so I am working on a solution to run the code from external DRAM. We have already a project-specific bootloader which does update stuff and so on. This bootloader is stored and executed in internal flash and started via BAM. The application currently resides also in internal flash and is started by the bootloader by a soft reset triggered via RGM. If the startup code of the bootloader detects a "soft reset" condition in the RGM registers it branches via a simple function pointer pointing to the entry point of the application, e.g. something like
((void (*)(void)) 0x00001234)();
Everything works quite well so far. I have tried to adopt the bootloader like follows:
1. The application was linked to be executed from DRAM, entry point is now 0x2F80.0600. The binary seems to be correct, I have checked it via map file and disassembly.
2. The bootloader initializes the DRAMC and QSPI with all necessary prerequisites like pad config, clocking and MMU stuff. The 'execute' permissions are set for the full DRAM memory space.
2. The bootloader copies the complete application image from ext. flash to ext. DRAM. This works also as expected, the application image in flash is 'signed' with a CRC which is verified in DRAM after the copying.
3. The bootloader branches to the entry point of the application via a simple function pointer:
((void (*)(void)) 0x2F800600)();
This fails.
Single stepping through the disassembly in the CodeWarrior debugger shows that the branch seems to be correct:
212 (appEntryPoint)( );
00014a7a: se_mtar r12,r3
00014a7c: mtctr r12
00014a80: se_bctrl
The CTR register contains the expected address, namely 0x2F80.0600.
However the PC points to 0x2F80.2FF0 after the se_bctrl was executed and the CPU starts executing from this address which fails after a few instructions, because 0x2F80.2FF0 is not a valid instuction address.
I haven't seen any information about CPU execeptions in the SPR after the branch.
Any ideas ?
Thanks a lot,
Werner
Hi,
hmm what is the reason to use cunter register for jump?
Count register (CTR). The CTR holds a loop count that can be decremented during execution
of appropriately coded branch instructions. The CTR also provides the branch target address
for the Branch [Conditional] to Count Register (bcctr, bcctrl, se_bctr, se_bctrl) instructions.
Did you tried any other type of jump instead of se_bctrl ?
You can try direct jumps:
regards,
Peter
Hello Peter,
I already solved this issue a long time ago. By the way, I didn't use the CTR register directly in assembler code, this was code generated by the compiler. In my C code, I used the "cast-to-function-ptr" approach to jump to program entry point.
I guess the compiler applied the addressing mode "pc_rel" to that function call as documented in "MCU_Power-Architecture_Compiler.pdf":
The permissible addressing modes for codemode are:
• pc_rel - routines must be within plus or minus 24 bits of where pc_rel is called from
• near_abs - routines must be within the first 24 bits of memory address space
• far_abs - routines must be within the first 32 bits of memory address space
The default addressing mode for executable code sections is pc_rel.
I replaced the function-pointer call with a tiny assembler routine which uses 32-bit addressing and everything worked fine.
Bests,
Werner