This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RM57L843: Linker Generate "__TI_CINIT_Limit" is 0xFFFFFFFF

Part Number: RM57L843

Hi,

CCS 12.2.0.00009

TI-CGT-ARM 20.2.7.LTS

I have found an issue while testing a bootloader that has caused us an issue. When I go back over other non-bootloader firmware projects, we have the same issue.

Overview:

The linker generates "__TI_CINIT_Base" and "__TI_CINIT_Limit"

These two values are used to copy the default values for initialised global variables stored in .cinit.

During boot, we copy the table over as per:

    /*lint -e740  Unusual pointer cast (incompatible indirect types) [MISRA 2004 Rule 1.2]  */
	// https://software-dl.ti.com/codegen/docs/tiarmclang/compiler_tools_user_guide/compiler_manual/runtime_environment/system-initialization-stdz0543503.html
	Luint8 **tablePtr   = (Luint8 **)&__TI_CINIT_Base;
	Luint8 **tableLimit = (Luint8 **)&__TI_CINIT_Limit;
	/*lint +e740 */

	/*lint -e681  Loop is not entered [MISRA 2004 Rule 14.1] */
	while(tablePtr < tableLimit)
	{
		//#1476-D (MISRA-C:2004 17.4/R) Array indexing shall be the only allowed form of pointer arithmetic
		//OK In this instance
		Luint8 *loadAdr = *tablePtr++;

The Problem

Once we program the device, we look at the .map file and find the __TI_CINIT_Limit address

And then we find the FLASH in the RM57L843 is 0xFFFFFFFF at that location.

This means that C Init system will run on until 0xFFFFFFFF, which takes quite some time.

Our Linker Script

Linker script is shown below.

There is nothing too special, however for this example we are locating a boot image header at a specific location and moving the reset vector table. This is OK because our bootloader, located in bank 0 knows how to jump to this location.

--retain="*(.intvecs)"

/*----------------------------------------------------------------------------*/
/* Memory Map                                                                 */

MEMORY
{

	/** OAD Image header, length 0x100 */
    OAD_IMAGE_HDR (X)  : origin=0x00200000 length=0x00000100  vfill = 0xffffffff

	/** Reset vectors for the BIM are at the start of FLASH 1, length 0x20 */
    VECTORS (X)  : origin=0x00200000 + 0x100 length=0x00000020  vfill = 0xffffffff

    /** Firmware version marker, length 0x20 - padded for nice ECC fill region */
    FIRMWARE_LFW   : origin=0x00200000 + 0x100 + 0x20 + 0x00 length=0x00000004 fill=0x00000000
    FIRMWARE_MAJOR : origin=0x00200000 + 0x100 + 0x20 + 0x04 length=0x00000004 fill=0x00000000
    FIRMWARE_MINOR : origin=0x00200000 + 0x100 + 0x20 + 0x08 length=0x00000004 fill=0x00000000
    FIRMWARE_SPARE : origin=0x00200000 + 0x100 + 0x20 + 0x0C length=0x00000014 fill=0xffffffff

	/** FreeRTOS Kernel code */
	KERNEL  (RX) : origin=0x00200000 + 0x100 + 0x20 + 0x20 length=0x00008000

    /** Flash 1 for main application, -0x20 for some spare space at the end */
    FLASH1  (RX) : origin=0x00200000 + 0x100 + 0x40 + 0x8000  length=0x002000000 - 0x100 - 0x40 - 0x8000 - 0x020  /*vfill = 0xffffffff*/
    
    STACKS  (RW) : origin=0x08000000 length=0x00000800
	KRAM    (RW) : origin=0x08000800 length=0x00000800
    RAM     (RW) : origin=(0x08000800 + 0x00000800) length=(0x0007F800 - 0x00000800)


	/*
	2.2.3.2 ECC Protection for Flash Accesses
	The access to the program memory – flash bank 0, 1 and 7 are protected by SECDED logic implemented inside the ARM Cortex-R5F CPU
	There is an 8-bit ECC for every 64 bits of data (8 bytes)
	The ECC for the flash array is stored in the flash itself, and is mapped to a region starting at 0xF0400000 for the main flash bank 0 and 1
	*/

	/** ECC region for the OAD Image Header - 0x100/8 = 0x20 */
	ECC_FLASH1_OAD_IMAGE (R)  : origin=0xf0400000 + 0x300000 length=0x20 ECC={ input_range=OAD_IMAGE_HDR }

	/** ECC region for the vector table -  0x20/8 = 4 */
	ECC_FLASH1_VEC (R)  : origin=0xf0400000 + 0x300000 + 0x20 length=0x4 ECC={ input_range=VECTORS }

	/** ECC region for the firmware table -  0x20/8 = 4 */
	ECC_FLASH1_FW (R)  : origin=0xf0400000 + 0x300000 + 0x20 + 0x04 length=0x4 ECC={ input_range=FIRMWARE_LFW }

	/** ECC for OS, 0x8000/8 = 0x1000 */
	ECC_FLASH1_KERNEL (R)  : origin=0xf0400000 + 0x300000 + 0x20 + 0x04 + 0x04 length=0x1000 ECC={ input_range=KERNEL }

	/** ECC for the rest of the FLASH region, (0x002000000 - 0x100 - 0x40 - 0x8000) / 8 =  3FEFD8*/
    ECC_FLA1 (R) : origin=0xf0400000 + 0x300000 + 0x20 + 0x04 + 0x04 + 0x1000 length=0x3FEFD8 ECC={ input_range=FLASH1 }
}

ECC
{
   algo_name : address_mask = 0xfffffff8
   hamming_mask = R4
   parity_mask = 0x0c
   mirroring = F021
}

/*----------------------------------------------------------------------------*/
/* Section Configuration                                                      */

SECTIONS
{
	// Image header is first
	GROUP > OAD_IMAGE_HDR
	{
		.image_header
	}

	/** reset vector */
    .intvecs : {} > VECTORS

    /** Fimrware version markers */
	.lfwFirmware   :  {} > FIRMWARE_LFW
    .majorFirmware :  {} > FIRMWARE_MAJOR
    .minorFirmware :  {} > FIRMWARE_MINOR

    /* FreeRTOS Kernel in protected region of Flash */
	.kernelTEXT  align(32) : {} > KERNEL

    GROUP > FLASH1
	{
		.text align(32)
		.const align(32)

    	/** Boot Time Init Tables */
		.binit align(32)

		/** Init Tables */
		.cinit align(32)

		/** C++ Constructor Tables */
		.pinit align(32) LOAD_END(flashEndAddr)

	}

    .kernelBSS    : {} > KRAM
    .kernelHEAP   : {} > RAM
    .bss     : {} > RAM
    .data    : {} > RAM
	.sysmem  : {} > RAM
	
}

Any suggestions as to why the last word address is 0xFFFFFFFF?

Also cc:  as you've helped me in the past on Linker Issues.

Regards

Stomp!

  • Hi Stomp,

    The __TI_cinit_table starts at 0x236720, and ends at 0x236740, and the table size is 0x20

  • Hi QJ,

    Turns out it was not the "__TI_CINIT_Limit" as defined by the linker, but the way the CINIT table was being generated.

    Here is my output:

    LINKER GENERATED COPY TABLES
    
    __TI_cinit_table @ 00006d48 records: 4, size/record: 8, table size: 32
    	.data: load addr=00006ce0, load size=0000003f bytes, run addr=080703d0, run size=00000168 bytes, compression=lzss
    	.kernelBSS: load addr=00006d2c, load size=00000009 bytes, run addr=08003000, run size=00000140 bytes, compression=lzss
    	.bss: load addr=00006d38, load size=00000008 bytes, run addr=08003800, run size=0006cbce bytes, compression=zero_init
    	.os_swi: load addr=00006d40, load size=00000008 bytes, run addr=00000020, run size=00000004 bytes, compression=zero_init

    You can see that .os_swi actually has a run addx which is inside FLASH memory, this caused the data abort that I through was caused by exceeding the CINIT table limit.

    Thanks.