Other Parts Discussed in Thread: HALCOGEN, , TMS570LS3137
Hello All!
I have been trying (and have succeeded) to get HALCoGen to output code which can be compiled with an ARM GCC toolchain (without using CCS - not sure if this affects CCS/Linaro) and have stumbled upon an issue with one part of the HALCoGen output :
Part of the startup sequence in sys_startup.c :
/* SourceId : STARTUP_SourceId_001 */
/* DesignId : STARTUP_DesignId_001 */
/* Requirements : HL_SR508 */
void _c_int00(void)
{
/* USER CODE BEGIN (5) */
/* USER CODE END */
/* Initialize Core Registers to avoid CCM Error */
_coreInitRegisters_();
The issue here is that _coreInitRegisters_() is not EABI compliant (it cannot be) and trashes registers GCC does not expect to be clobbered. This emitted the following here :
00000f88 <_c_int00>:
f88: e3e04000 mvn r4, #0
f8c: ebfffc5d bl 108 <_coreInitRegisters_>
f90: ebfffc8a bl 1c0 <_coreInitStackPointer_>
f94: ebfffca4 bl 22c <_coreEnableEventBusExport_>
f98: ebfffd0e bl 3d8 <_errata_CORTEXR4_66_>
f9c: ebfffd07 bl 3c0 <_errata_CORTEXR4_57_>
fa0: e514301b ldr r3, [r4, #-27] ; 0xffffffe5
fa4: e3130902 tst r3, #32768 ; 0x8000
Notice that R4 is set at the very beginning and GCC does not expect it to change [EABI says R4 is callee-save] before the LDR at 0xfa0 - but of course it does, and therefore this results in a data abort at that point. The fetch happens lower down due to this code code in sys_startup.c :
/*SAFETYMCUSW 139 S MR:13.7 <APPROVED> "Hardware status bit read check" */
else if ((SYS_EXCEPTION & WATCHDOG_RESET) !=0U)
[Ironically the 0xffffffe5 is actually "correct" as per disassembly since R4 returns to 0 rather than staying at -1, it should access 0xffffffe4 and it would, if R4 was still -1].
A simple workaround for this issue is to tell GCC that its registers are going to be trashed :
/* USER CODE BEGIN (6) */
__asm__ __volatile__ ("":::"r0","r1","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12","r14");
/* USER CODE END */
Notice what this does to the output :
00000f88 <_c_int00>:
f88: ebfffc5e bl 108 <_coreInitRegisters_>
f8c: e3e04000 mvn r4, #0
f90: ebfffc8a bl 1c0 <_coreInitStackPointer_>
f94: ebfffca4 bl 22c <_coreEnableEventBusExport_>
f98: ebfffd0e bl 3d8 <_errata_CORTEXR4_66_>
f9c: ebfffd07 bl 3c0 <_errata_CORTEXR4_57_>
fa0: e514301b ldr r3, [r4, #-27] ; 0xffffffe5
fa4: e3130902 tst r3, #32768 ; 0x8000
The MVN has now been moved after the non-EABI compliant function call - the other function calls are sufficiently EABI compliant that it doesn't break - and the LDR succeeds.
There may be a more elegant solution to this, but so long as GCC is allowed to allocate things out-of-order, any call to a non-EABI compliant assembly function could be problematic.
This should likely be fixed in HALCoGen.
Just for reference, when building using CCS and the TI compiler (with HALCoGen emitting TI code) we see :
00003c44 <_c_int00>:
3c44: ebfffde3 bl 33d8 <_coreInitRegisters_>
3c48: ebfffe10 bl 3490 <_coreInitStackPointer_>
3c4c: ebfffe2a bl 34fc <_coreEnableEventBusExport_>
3c50: ebfffe92 bl 36a0 <_errata_CORTEXR4_66_>
3c54: ebfffe8d bl 3690 <_errata_CORTEXR4_57_>
3c58: e3e0401b mvn r4, #27
3c5c: e594c000 ldr ip, [r4]
3c60: e31c0902 tst ip, #32768 ; 0x8000
Whilst it is sat somewhat higher up in memory than the GCC output, we can see that it doesn't allocate R4 early like GCC does and thus avoids the issue.
Best regards,
Patrick Herborn.