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.

data abort exception when reading from packed struct in EEPROM Flash.

Other Parts Discussed in Thread: TMS570LS1114, HALCOGEN

Hello,

I am getting a data abort when reading from a specific packed struct located in EEPROM Flash(using __attribute__((__packed__))), however i can't find any reason as to why this exception occurs. The value in question is a 16bit value aligned to an 8-bit boundary, however this is not illegal according to the dcoumentation for the cortex-R4.

Is there any mechanism in the TMS570ls1114 that should prevent this from working?

  • According to the ARM Cortex R4 TRM (r1p3) "any unaligned access to Device or Strongly-ordered memory generates an alignment fault", and the address range of 0xF00000000 - 0xFFFFFFFF is by default "strongly ordered".
  • I just double-checked the halcogen settings, and the memory region 0xF0000000-0xF07FFFFF is by default set to NORMAL_OINC_NONSHARED, PRIV_RW_USER_RO_NOEXEC. It is also the highest priority region which overlaps the EEPROM area. The MPU however still flag a read from this area with an alignment error. For instance, a 16bit read from address 0xF0200039. Any hints?
  • Verify that your code actually calls _mpu_enable_(). If you check the CP15_System_Control register, bit 0 is the MPU and bit 1 disables unaligned access. Verify bit 0 is set and bit 1 is cleared. By default in my simple HALCoGen example the MPU was not enabled.

  • I have added a capture of the cp15 registers at the time of the data abort. As far as i can tell, everything is in order. What am i missing here?

  • I am not able to reproduce the problem. Are you using default MPU settings from HALCoGen?

  • The MPU settings are according to the TMS570ls1114PGE default settings in HALCoGen.
  • I also just tried running your code for reading the specific address, and it seems to work.

    Now to figure out why it doesn't work with members of a packed struct.

  • Just attempted to execute the same code from within the FreeRTOS task where i first experienced the error, and it flags an alignment error. so the same code works when executed in main, but not when executed within a FreeRTOS task.

  • When running from FreeRTOS most tasks are in USER mode instead of SYSTEM mode. In my example I changed to USER mode after setting up the MPU but before doing the unaligned access and it still worked. If I try to setup the MPU in USER mode I get a data abort as expected. Can you verify that setting up the MPU is done in a privileged mode when using FreeRTOS?
  • The init and enable routines for the MPU are done in system mode, in the first part of main. After that the tasks are created and the scheduler is started. The task which causes the error also runs in system mode.
    We are running a standard version of FreeRTOS from their website on top of the HALCoGen which does not make any calls to the MPU. Apart from this issue, everything runs fine.
  • It looks like FreeRTOS is overwriting your MPU settings whenever it starts the scheduler. This function is starting in line 318 of the file os_port.c.

    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_RO_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();
    }


    It looks like it sets the range 0xF0000000 - 0xFFF7FFFF back to device memory.

  • I managed to track down the issue, and it is almost as you describe. The version of FreeRTOS we are using is from their website, and we have made a custom port to use it with a normal non-FreeRTOS halcogen project. Unfortunately someone left in a few assembly instructions which affected p15, thanks for all the help!