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.

RM48L940: FreeRTOS prefetch Abort

Part Number: RM48L940

I'm trying to run freertos onto my custom RM48 board and have followed the TI recommend instructions for doing so. However, I get my prefetch Abort error when I create an OS task. Specifically, I get the prefetch Abort immediately after executing this line highlighted below.

; Start the first task by restoring its context.

        public vPortStartFirstTask
        
vPortStartFirstTask
        cps #0x13
        portRESTORE_CONTEXT

When I step into this macro it seems to manipulates registers normally until at some point my registers look like this:

When I exit the   portRESTORE_CONTEXT macro my registers look like this:

From here the next instruction is the prefetch abort. How do I go about finding out what causes the abort?

My link file looks like this:

/*----------------------------------------------------------------------------*/
define memory mem with size = 4G;

define region VECTORS = mem:[from 0x00000000 size 0x00000020];
define region KERNEL = mem:[from 0x00000020 size 0x00008000];
define region FLASH = mem:[from 0x00008020 size 0x00177FE0]
| mem:[from 0x00180000 size 0x00180000];
define region STACK = mem:[from 0x08000000 size 0x00002500];
define region KRAM = mem:[from 0x08002500 size 0x00000800];
define region RAM = mem:[from (0x08002500+0x00000800) size (0x0003F800 - 0x00000800)];
define block HEAP with size = 0x800, alignment = 8{ };

initialize by copy {readwrite};
do not initialize {section .noinit};

place in VECTORS {readonly section .intvecs};
place in KERNEL {readonly section .kernelTEXT};
place in FLASH {readonly};
place in RAM {readwrite section .kernelHEAP};
place in KRAM {readwrite section .kernelBSS};
place in RAM {readwrite};
place in RAM {block HEAP};
/*----------------------------------------------------------------------------*/

  • The offending line of code is portRESTORE_CONTEXT in the snippet below. The initial post added tags highlight tags to it instead of showing the highlighted text.

    ;/*-----------------------------------------------------------*/
    ; Start the first task by restoring its context.

    public vPortStartFirstTask

    vPortStartFirstTask
    cps #0x13
    portRESTORE_CONTEXT
  • Hello,

    A prefetch abort is a precise abort so the application can identify the instruction that causes the abort. Can you check the disassembly window to identify the address from where the next instruction is to be fetched? It appears to be 0xBD3C from your log above. This is a valid address, so it could be the instruction after this one that causes the abort.

    You can check the CPU's instruction fault status and address registers to identify the exact address and the cause of the abort (double-bit ECC error, MPU configuration.

    Regards,
    Sunil
  • Thanks for the reply. The 0x0D3C address is loaded into LR before the call to portRESTOR_CONTEXT. The instruction at that address is the last instruction in the vPortSWI label that I've bolded.

    ;-------------------------------------------------------------------------------
    ; SWI Handler, interface to Protected Mode Functions

    public vPortSWI

    vPortSWI
    stmfd sp!, {r11,r12,lr}
    mrs r12, spsr
    ands r12, r12, #0x20
    ldrbne r12, [lr, #-2]
    ldrbeq r12, [lr, #-4]
    ldr r14, table
    ldr r12, [r14, r12, lsl #2]
    blx r12
    ldmfd sp!, {r11,r12,pc}^

    table
    dcd jumpTable

    jumpTable
    dcd swiPortYield ; 0 - vPortYieldProcessor
    dcd swiRaisePrivilege ; 1 - Raise Priviledge
    dcd swiPortEnterCritical ; 2 - vPortEnterCritical
    dcd swiPortExitCritical ; 3 - vPortExitCritical
    dcd swiPortTaskUsesFPU ; 4 - vPortTaskUsesFPU
    dcd swiPortDisableInterrupts ; 5 - vPortDisableInterrupts
    dcd swiPortEnableInterrupts ; 6 - vPortEnableInterrupts

  • Hello,

    Please review the CPU fault status and address registers to identify the address being accessed that causes the abort. This one appears to be a corruption of the link register causing the return instruction to fetch from an address that is invalid. This address will be captured in the Instruction Fault Address Register (IFAR). See more information about the IFAR on page 133 of the Cortex-R4F TRM revision r1p3.

    Regards,
    Sunil
  • Thanks. The IFAR contains the same invalid address in the LR (see below) so I'm not sure what to make of that. Is the DFSR indicating that this is a "Synchronous Parity/ECC Error"

    This project worked fine on bare-metal so I think it's something that adding FreeRTOS introduced. Could this be related to how the MPU is set up? I'm using the default MPU settings in FreeRTOS shown below.

    In the prvSetupDefaultMPU( void ) function below the flash size is defined as 4MB and SRAM is 512K but the RM48 has 3MB flash and 256K RAM. Is it OK to use this function as-is? I tried changing the sizes to the match the 3MB and 256K but that didn't fix my prefetch abort error.

    /*----------------------------------------------------------------------------*/
    define memory mem with size = 4G;

    define region VECTORS   = mem:[from 0x00000000 size 0x00000020];
    define region KERNEL    = mem:[from 0x00000020 size 0x00008000];
    define region FLASH     = mem:[from 0x00008020 size 0x00177FE0]
                            | mem:[from 0x00180000 size 0x00180000];
    define region STACK     = mem:[from 0x08000000 size 0x00002500];
    define region KRAM      = mem:[from 0x08002500 size 0x00000800];
    define region RAM       = mem:[from (0x08002500+0x00000800) size (0x0003F800 - 0x00000800)];
    define block HEAP with size = 0x800, alignment = 8{ };

    initialize by copy {readwrite};
    do not initialize  {section .noinit};

    place in VECTORS {readonly section .intvecs};
    place in KERNEL  {readonly section .kernelTEXT};
    place in FLASH   {readonly};
    place in RAM     {readwrite section .kernelHEAP};
    place in KRAM    {readwrite section .kernelBSS};
    place in RAM     {readwrite};
    place in RAM     {block HEAP};
    /*----------------------------------------------------------------------------*/

    static void prvSetupDefaultMPU( void )
    {
    	/* make sure MPU is disabled */
    	prvMpuDisable();
    
    	/* First setup the entire flash for unprivileged read only access. */
    	prvMpuSetRegion(portUNPRIVILEGED_FLASH_REGION,  0x00000000, portMPU_SIZE_4MB | portMPU_REGION_ENABLE, portMPU_PRIV_RO_USER_RO_EXEC | portMPU_NORMAL_OIWTNOWA_SHARED);
    
    	/* Setup the first 32K for privileged only access.  This is where the kernel code is
    	placed. */
    	prvMpuSetRegion(portPRIVILEGED_FLASH_REGION,  0x00000000, portMPU_SIZE_32KB | portMPU_REGION_ENABLE, portMPU_PRIV_RO_USER_NA_EXEC | portMPU_NORMAL_OIWTNOWA_SHARED);
    
    	/* Setup the the entire RAM region for privileged read-write and unprivileged read only access */
    	prvMpuSetRegion(portPRIVILEGED_RAM_REGION,  0x08000000, portMPU_SIZE_512KB | portMPU_REGION_ENABLE, portMPU_PRIV_RW_USER_RW_EXEC | portMPU_NORMAL_OIWTNOWA_SHARED);
    
    	/* Default peripherals setup */
    	prvMpuSetRegion(portGENERAL_PERIPHERALS_REGION,  0xF0000000,
    					portMPU_SIZE_256MB | portMPU_REGION_ENABLE | portMPU_SUBREGION_1_DISABLE | portMPU_SUBREGION_2_DISABLE | portMPU_SUBREGION_3_DISABLE | portMPU_SUBREGION_4_DISABLE,
    					portMPU_PRIV_RW_USER_RW_NOEXEC | portMPU_DEVICE_NONSHAREABLE);
    
    	/* Privilege System Region setup */
    	prvMpuSetRegion(portPRIVILEGED_SYSTEM_REGION,  0xFFF80000, portMPU_SIZE_512KB | portMPU_REGION_ENABLE, portMPU_PRIV_RW_USER_RO_NOEXEC | portMPU_DEVICE_NONSHAREABLE);
    	
    	/* Enable MPU */
    	prvMpuEnable();
    }

  • Unfortunately, the image you uploaded for the IFAR and DFAR did not come through. It does appear to be an issue with the MPU setup. Please correct the memory sizes per the available Flash and RAM on RM48x. Also, check the permissions for the regions defined: user mode access allowed or not.

    You can get further information about faults detected by the MPU (background, alignment or permission) via the Auxiliary Instruction Fault Status Register. The bitfield descriptions are on page 129 of the CPU's TRM.

    Regards,
    Sunil
  • I changed the memory size earlier on to match but that didn't help. I've re-attached IFAR and DFAR contents

  • Hello,

    I have sent you a "friend request". That way you can send me your code project without having to upload it on the forum.

    Are you seeing a prefetch abort (vector address 0xC) response from the CPU or a data abort (vector address 0x10)? The DFSR shows an ECC error from the location 0x08000018. Is this location being read without first being initialized?

    Regards,
    Sunil
  • Thanks. I accepted the request.
    Location 0x08000018 is stack space. I initialize RAM with memoryInit(0x1U). I'll take a closer look tomorrow.
  • My problem isn't solved yet but have found a way around it for now. I'll go back to find the root cause and will reach out if need be.
    Workaround: disable all SafeTI tests and no prefetch abort. I suspect memory corruption from one of the tests.
  • Some SafeTI diagnostics do cause intentional data aborts. The data abort handler identifies this as an intentionally caused data abort and manages it differently versus a real data abort.

    Regards,
    Sunil