Using the following I have been getting ESM errors:
- Targeting a TMS570LC4357 in a LAUNCHXL2-570LC43
- Using HALCoGen 04.05.02 to generate the project with the cache enabled
- CCS 6.1.3.00033 with Hercules Emulation 6.0.7
- Auto ECC Generation enabled in the CCS Flash Settings
- TI ARM compiler v15.12.2
As programs were being developed, after some code changes the ERR led on the LAUNCHXL2-570LC43 would illuminate. From looking at the ESM registers in the CCS debugger, the ESM errors occurred due to the Cortex-R5F reporting a "Bus ECC" fatal bus error event to ESM group 2 channel 3.
The attached project repeatably generates a "Bus ECC" fatal bus error ESM event when programmed with CCS using Auto ECC Generation. The user code which has been added the the HALCoGen generated code is the following in HL_sys_main.c which writes the contents of some ESM status registers over SCI1:
/* Include Files */ #include "HL_sys_common.h" /* USER CODE BEGIN (1) */ #include <stdio.h> #include <string.h> #include "HL_esm.h" #include "HL_sci.h" /* USER CODE END */ /** @fn void main(void) * @brief Application main function * @note This function is empty by default. * * This function is called after startup. * The user can use this function to implement the application. */ /* USER CODE BEGIN (2) */ #define UART sciREG1 static void sciDisplayText(sciBASE_t *sci, uint8 *text,uint32 length) { while(length--) { while ((UART->FLR & 0x4) == 4); /* wait until busy */ sciSendByte(UART,*text++); /* send out text */ }; } /* USER CODE END */ void main(void) { /* USER CODE BEGIN (3) */ char buffer[132] = "Inital"; sciInit (); sprintf (buffer, "esmError()=%u\n\r", esmError()); sciDisplayText (UART, (uint8_t *) buffer, strlen(buffer)); sprintf (buffer, "Group 1 ESM status: Chans 95-64=0x%llx Chans 63-0=0x%llx\n\r", esmGetStatusUpper (0, 0xffffffffLL), esmGetStatus (0, 0xffffffffffffffffLL)); sciDisplayText (UART, (uint8_t *) buffer, strlen(buffer)); sprintf (buffer, "Group 2 ESM status: Chans 31-0=0x%llx\n\r", esmGetStatus (1, 0xffffffff)); sciDisplayText (UART, (uint8_t *) buffer, strlen(buffer)); sprintf (buffer, "Group 3 ESM status: Chans 31-0=0x%llx\n\r", esmGetStatus (2, 0xffffffff)); sciDisplayText (UART, (uint8_t *) buffer, strlen(buffer)); /* USER CODE END */ }
When main is reached the ERR led on the launchpad is off. When step over the char buffer[132] = "Inital" statement the ERR led turns on, meaning an ESM error has occurred. By single stepping the code which initializes the buffer[] array, the "Bus ECC" error occurred when the CPU performs a read from the word at address 0x00006460.
The linker map shows that address 0x00006460 is 5 bytes away from the end of the .const section, and that there is a 27 byte "gap" between the end of the .const section and the start of the .cinit section:
SEGMENT ALLOCATION MAP run origin load origin length init length attrs members ---------- ----------- ---------- ----------- ----- ------- 00000000 00000000 000060d0 000060d0 r-x 00000000 00000000 00000020 00000020 r-x .intvecs 00000020 00000020 000060b0 000060b0 r-x .text 000060e0 000060e0 00000385 00000385 r-- 000060e0 000060e0 00000385 00000385 r-- .const 00006480 00006480 0000003c 0000003c r-- 00006480 00006480 0000003c 0000003c r-- .cinit 08001500 08001500 00000068 00000000 rw- 08001500 08001500 00000050 00000000 rw- .bss 08001550 08001550 00000018 00000000 rw- .data
When verbose mode is turned on the CCS flash settings, this appears to show that CCS doesn't attempt to program the "gap" between .const and .cinit sections:
CortexR5: Verifying Flash @ Address 0x00000000 of length 0x000060D0 CortexR5: Writing Flash @ Address 0x000060e0 of Length 0x00000385 CortexR5: Verifying Flash @ Address 0x000060E0 of length 0x00000388 CortexR5: Writing Flash @ Address 0x00006480 of Length 0x0000003c CortexR5: Verifying Flash @ Address 0x00006480 of length 0x0000003C
What I think is happening is that when the CPU attempts to read the word at address 0x00006460, due to the cache being enabled an entire cache line of 32 bytes from address 0x00006460 to 0x0000647f is read from flash. However, because the last 27 bytes of the cache line haven't been programmed by CCS this causes an ECC error to be detected on the 32 bytes read from flash.
The HL_sys_link.cmd file which has been generated by HALCoGen contains the following section definitions:
.text align(32) : {} > FLASH0 | FLASH1 .const align(32) : {} > FLASH0 | FLASH1 .cinit align(32) : {} > FLASH0 | FLASH1 .pinit align(32) : {} > FLASH0 | FLASH1
Note the use of the align(32) directive which aligns the start address of the sections to a 32 byte boundary, but doesn't pad the sections to a multiple of 32 bytes. Manually edited the HL_sys_link.cmd file to instead using the palign(32) directive to pad the sections to a multiple of 32 bytes:
.text palign(32) : {} > FLASH0 | FLASH1 .const palign(32) : {} > FLASH0 | FLASH1 .cinit palign(32) : {} > FLASH0 | FLASH1 .pinit palign(32) : {} > FLASH0 | FLASH1
Following this change to the project the "Bus ECC" ESM error no longer occurred. However, this is not a permanent change since the sections modified in the HL_sys_link.cmd are outside of USER CODE blocks and so will be lost upon regenerating the project in HALCoGen.
Not sure if the problem is either:
- The HALCoGen linker command files should use palign(32) rather than align(32) for the sections.
- The CCS Auto EEC Generation should ensure ECC is set for a multiple of 32-bytes for sections which straddle 32 bytes boundaries.