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.

TMS570LC4357: Declaring a non-cachable region while using FreeRTOS

Part Number: TMS570LC4357
Other Parts Discussed in Thread: HALCOGEN

We are trying to use DMA with activated cache on a TMS570LC4357, within a FreeRTOS project. We configured a non-cachable region (region 15) at the end of RAM as explained in https://www.hackster.io/jancumps/hercules-configure-memory-cache-for-dma-0945cd, which is based on a solution coming from the TI forum. However the variables allocated in region 15 still seem to land in the cache, as the DMA sends empty data. If cache is deactivated, it works as expected.

In HalCoGen, in the MPU tab, there is a setting for FreeRTOS:

It looks like FreeRTOS always configures region 15. In the file os_portasm.asm generated by HalCoGen, the following code is found:

portRESTORE_CONTEXT .macro

        LDR     R0, pxCurrentTCBConst
        LDR     R0, [R0]

        ; task stack MPU region
        mov     r4,  #12                     ; Task Stack Region
        add     r12, r0, #4                 ; poin to regions in TCB
        ldmia   r12!, {r1-r3}
        mcr     p15, #0, r4, c6, c2, #0     ; Select region
        mcr     p15, #0, r1, c6, c1, #0     ; Base Address
        mcr     p15, #0, r3, c6, c1, #4     ; Access Attributes
        mcr     p15, #0, r2, c6, c1, #2     ; Size and Enable

        ldr     r5, portMax_MPU_Region
        mov     r4,  #13
        ; dynamic MPU per task
        ldmia   r12!, {r1-r3}
        mcr     p15, #0, r4, c6, c2, #0     ; Select region
        mcr     p15, #0, r1, c6, c1, #0     ; Base Address
        mcr     p15, #0, r3, c6, c1, #4     ; Access Attributes
        mcr     p15, #0, r2, c6, c1, #2     ; Size and Enable
        add     r4, r4, #1
        cmp     r4, r5
        bne     $ - 0x1C

portMax_MPU_Region       .word   16 - 1

If we change to:

portRESTORE_CONTEXT .macro

        LDR     R0, pxCurrentTCBConst
        LDR     R0, [R0]

        ; task stack MPU region
        mov r4, #11                           ; Task Stack Region
        add     r12, r0, #4                 ; poin to regions in TCB
        ldmia   r12!, {r1-r3}
        mcr     p15, #0, r4, c6, c2, #0     ; Select region
        mcr     p15, #0, r1, c6, c1, #0     ; Base Address
        mcr     p15, #0, r3, c6, c1, #4     ; Access Attributes
        mcr     p15, #0, r2, c6, c1, #2     ; Size and Enable

        ldr     r5, portMax_MPU_Region
        mov     r4, #12
; dynamic MPU per task ldmia r12!, {r1-r3} mcr p15, #0, r4, c6, c2, #0 ; Select region mcr p15, #0, r1, c6, c1, #0 ; Base Address mcr p15, #0, r3, c6, c1, #4 ; Access Attributes mcr p15, #0, r2, c6, c1, #2 ; Size and Enable add r4, r4, #1 cmp r4, r5 bne $ - 0x1C portMax_MPU_Region .word 15 - 1

to prevent FreeRTOS from using region 15, the non-cachable region works as expected.

Is this a valid setup or should another setup be used to declare region 15 as non-cachable while using FreeRTOS?

  • FreeROS overrides any MPU configuration done prior to starting the OS. Refer to this application note for more information on how to manage MPU settings when using FreeRTOS. The relevant info is in appendix A.

  • The MPU settings are configured in vPortStoreTaskMPUSettings(). The note before the function says 

    „/* Note: By default, all the RAM regions are configured to be cached (write-back, write-through) for better performance.
       This configuration is not suited in case multiple bus masters access the RAM, for example, DMA or EMAC master.
       Please use the USERCODE section below to change the default MPU settings */“
     
    So we defined the non-cachable section in the user section at the end of the function, with the code
     
    xMPUSettings->xRegion[portNUM_CONFIGURABLE_REGIONS-1].ulRegionBaseAddress = 0x0807F000;
    xMPUSettings->xRegion[portNUM_CONFIGURABLE_REGIONS-1].ulRegionSize        = portMPU_SIZE_4KB | portMPU_REGION_ENABLE;
    xMPUSettings->xRegion[portNUM_CONFIGURABLE_REGIONS-1].ulRegionAttribute   = portMPU_PRIV_RW_USER_RW_NOEXEC | portMPU_NORMAL_OINC_SHARED;
    

    The index (portNUM_CONFIGURABLE_REGIONS-1) is used because we want to use the last configurable region. With this configuraiton, the non-cachable region works as expected.