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.

CCS/TM4C129ENCPDT: MPU configuration

Part Number: TM4C129ENCPDT
Other Parts Discussed in Thread: SYSBIOS

Tool/software: Code Composer Studio

Hi guys,

i am working with microcontroller tm4c129encpdt, and trying to use MPU(memory protection unit), i want to protect 2 parts f ram memory  and 1 part of Flash.

the problem is i do not know what is wrong in my configuration that immediately goes to mpu fault or it crash when i run the project.

i read lots of MPU documentation but coudl not find the answer. the problem happens when in switchfxn(),when i want to change configuration:

[code]

void mySwitchFxn(ti_sysbios_knl_Task_Handle from, ti_sysbios_knl_Task_Handle to)
{

uint32_t   pointerSwich = (*(to)).fxn;

if( (pointerSwich >= 0x000b5800) && (pointerSwich < (0x000b5800 + 0x3e800)))   //Flash area

{

MPURegionSet(1, 0x2003fe0c,
MPU_RGN_SIZE_512B |
MPU_RGN_PERM_EXEC |
MPU_RGN_PERM_PRV_RW_USR_RW |
MPU_RGN_ENABLE);

MPURegionSet(0, 0x40040020,
MPU_RGN_SIZE_32B |
MPU_RGN_PERM_EXEC |
MPU_RGN_PERM_PRV_RW_USR_RW |
MPU_RGN_ENABLE);
}
else
{
MPURegionSet(1, 0x2003fe0c,
MPU_RGN_SIZE_512B |
MPU_RGN_PERM_EXEC |
MPU_RGN_PERM_PRV_RO_USR_RO |
MPU_RGN_ENABLE);

MPURegionSet(0, 0x40040020,      //----------->> here i have to protect just 25 byte 
MPU_RGN_SIZE_32B |
MPU_RGN_PERM_EXEC |
MPU_RGN_PERM_PRV_RO_USR_RO |
MPU_SUB_RGN_DISABLE_7 |
MPU_RGN_ENABLE);

}

}

[/code]

  • In both cases, you are not setting the starting address of MPU region 1 aligned to the size of the region. The starting address of a 512 byte region must end in 0x000, 0x200, 0x400 ... 0xE00.

  • ok so it means the blow config is correct???

    void mySwitchFxn(ti_sysbios_knl_Task_Handle from, ti_sysbios_knl_Task_Handle to)
    {
    
    uint32_t pointerSwich = (*(to)).fxn;
    if( (pointerSwich >= 0x000b5800) &&
    
    (pointerSwich < (0x000b5800 + 0x3e800)))
    {
    
    MPURegionSet(1, 0x2003fe00,
    MPU_RGN_SIZE_512B |
    MPU_RGN_PERM_EXEC |
    MPU_RGN_PERM_PRV_RW_USR_RW |
    MPU_RGN_ENABLE);
    
    MPURegionSet(0, 0x40040020,
    MPU_RGN_SIZE_32B |
    MPU_RGN_PERM_EXEC |
    MPU_RGN_PERM_PRV_RW_USR_RW |
    MPU_RGN_ENABLE);
    }
    else
    {
    MPURegionSet(1, 0x2003fe00,
    MPU_RGN_SIZE_512B |
    MPU_RGN_PERM_EXEC |
    MPU_RGN_PERM_PRV_RO_USR_RO |
    MPU_RGN_ENABLE);
    
    MPURegionSet(0, 0x40040020,
    MPU_RGN_SIZE_32B |
    MPU_RGN_PERM_EXEC |
    MPU_RGN_PERM_PRV_RO_USR_RO |
    MPU_SUB_RGN_DISABLE_7 |
    MPU_RGN_ENABLE);
    }
    
    }


    actualy i couldnot undrestand exactly how to align them, this is an example in my microcontroller user's guid:

    //
    // Define an additional 8-KB region (#2) in RAM from 0x20008000 to
    // 0x2000A000 that is read/write accessible only from privileged
    // mode. This region is initially disabled, to be enabled later.
    //
    MPURegionSet(2, 0x20008000,
    MPU_RGN_SIZE_8K |
    MPU_RGN_PERM_NOEXEC |
    MPU_RGN_PERM_PRV_RW_USR_NO|
    MPU_RGN_DISABLE);

    but the base address is not multyple of the size?????????????

  • Yes, your code now has the region starting address aligned properly. The example in the User's Guide is also properly aligned. The size is 8K bytes. (Note that for computers 1K is 1024, not 1000. It is an even power of 2. 1K is 2^10. 8K is then 8192 (2^13), or in hex 0x2000. Looking at the hex numbers we can see that 0x200008000 is an even multiple of 0x8000. (0x20008000 / 0x2000) = 0x10004. In decimal it is not so clear, but still true: 536903690 / 8192 = 65540

  • ok but i still have the problm. why?now evry thing seems to be correct

  • You are running TI-RTOS correct? I am going to ask the TI-RTOS team to look at this thread as there may be a contention with the way the OS is using the MPU.

  • Yes, thats right, thanks alot.

    another thing that i think the problem is for the second configuration, region1 32B, when i removed them from the project, it works perfectly.

    as i wrote i have to protect just 25 Byte so is that correct that i use "MPU_SUB_RGN_DISABLE_7", to remove the last 4 Bytes ???

    MPURegionSet(0, 0x40040020,
    MPU_RGN_SIZE_32B |
    MPU_RGN_PERM_EXEC |
    MPU_RGN_PERM_PRV_RO_USR_RO |
    MPU_SUB_RGN_DISABLE_7 |
    MPU_RGN_ENABLE);
  • Hi Shirin,

    Could you please attached a zipped CCS project showing the problem?

    Thanks,

    Janet

  • Hi Janet,

    unfortunately i am not allowed to send the project.

    The goal is when a protected part of flash is running the protected parts of RAM are accessible R/W, otherwise they are Read Only.

    i changed alittle the cod.

    void mySwitchFxn(ti_sysbios_knl_Task_Handle from, ti_sysbios_knl_Task_Handle to)
    {
    
        pointerSwich = (*(to)).fxn;
        MPURegionDisable(0); //--> Ram area
        MPURegionDisable(1);// --> Can registers in Ram
    
        if( (pointerSwich >= 0x000F2000) &&
                (pointerSwich < (0x000F2000 + 0x02000)))
        {
    
            MPURegionSet(0, 0x2003fe00,
                     MPU_RGN_SIZE_512B |
                     MPU_RGN_PERM_EXEC |
                     MPU_RGN_PERM_PRV_RW_USR_RW  |
                     MPU_RGN_DISABLE);
    
            MPURegionSet(1, 0x40040000,
                      MPU_RGN_SIZE_256B |
                     MPU_RGN_PERM_EXEC |
                     MPU_RGN_PERM_PRV_RW_USR_RW  |
                     MPU_RGN_DISABLE);
        }
        else
        {
            MPURegionSet(0, 0x2003fe00,
                     MPU_RGN_SIZE_512B |
                     MPU_RGN_PERM_EXEC |
                     MPU_RGN_PERM_PRV_RO_USR_RO |
                     MPU_RGN_DISABLE);
    
            MPURegionSet(1, 0x40040000,
                     MPU_RGN_SIZE_256B |
                     MPU_RGN_PERM_EXEC |
                     MPU_RGN_PERM_PRV_RO_USR_RO  |
                    /* MPU_SUB_RGN_DISABLE_7 |*/
                     MPU_RGN_DISABLE);
    
        }
    
        MPURegionEnable(0);
        MPURegionEnable(1);
    }
    int main(void)
    {
        Error_Block eb;
    
        Error_init(&eb);
    
        Hwi_create(FAULT_MPU, MpuIntHandler, NULL, &eb);
    
    // Protected flash area .. another part of project its thread is runing
            MPURegionSet(2, 0x000F2000,
                     MPU_RGN_SIZE_8K |
                     MPU_RGN_PERM_EXEC |
                     MPU_RGN_PERM_PRV_RO_USR_NO |
                     MPU_RGN_ENABLE);
    
        IntEnable(FAULT_MPU);
    
        MPUEnable(MPU_CONFIG_PRIV_DEFAULT);
    
        /* Configure the hardware. Pass a callback for reading out SW_VER    */
        Lib_BTConfigureHardware(&MAIN_ReadMainSWVersion, &MAIN_ReadHexFilename);
    
        Lib_checkHFault();
    
        /* Configure the CAN. Pass CAN Bitrate, an event callback and if     */
        /* Interrupt will be used for event signaling                        */
        Lib_BTConfigureCAN(CAN_BITRATE, &MAIN_CAN_EventCallback, 0);
    
        /* Configure the Data Gateway. Pass an event callback and connection */
        /* timeout in ms that will be used (0 to disable timeout)            */
        Lib_ConfigureDataGateway(&MAIN_DataGateway_EventCallback, NULL, 0);
    
        /* Configure the BT-ROUTER Events Callback.                          */
        Lib_ConfigureBTREventsCallback(&MAIN_BTR_EventCallback);
    
        /* Configure the BT-ROUTER Commands received from CAN Callback.      */
        Lib_ConfigureBTRCANCommandsCallback(&MAIN_BTR_CommandCallback);
    
        /* Configure the BT-ROUTER Commands replies Callback.                */
        Lib_ConfigureBTRCommandRepliesCallback(&MAIN_BTR_CommandReplyCallback);
    
        /* call the main application thread. NO RETURN FROM THIS PROCEDURE   */
        /* Pass a string with BT Name (MUST BE 0 TERMINATED!!!!), a string   */
        /* with BT pairing PIN to be used when receiving remote pairing      */
        /* requests (0 TERMINATED!) and a callback for User SW initialization*/
        Lib_BTMainThread(BT_DEVICE_NAME, BT_PIN, &MAIN_AppInit);
    }
    
    

  • Hi Shirin,

    Can you simplify your project to try and isolate the problem?

    What happened when you changed your code as described in your latest post?  Is it still faulting in the task switch function?

    Also, I saw in the TRM that regions of size 32, 64, and 128 bytes do not support subregions.

    Thanks,

    Janet

  • dear janet,

    it was very important point that you mentiond, and i forgot it, thanks alot.

    i want to protect the can0 registers that starts from 0x40040000, i have to protect the part that is used for transmit, so transmition should be protected. so it seems it does not like the configuration started with that address(0x40040020). so i changed again. but i am not sure that just protected these registers is enough or not, if i put other addresses or it crash or does not go to MPU Fault

    void mySwitchFxn(ti_sysbios_knl_Task_Handle from, ti_sysbios_knl_Task_Handle to)
    {
    
        pointerSwich = (*(to)).fxn;
        MPURegionDisable(0);
        MPURegionDisable(1);
    
    
        if( (pointerSwich >= 0x000F2000) &&
                (pointerSwich < (0x000F2000 + 0x02000)))
        {
    
            MPURegionSet(0, 0x2003fe00,
                     MPU_RGN_SIZE_512B |
                     MPU_RGN_PERM_EXEC |
                     MPU_RGN_PERM_PRV_RW_USR_RW  |
                     MPU_RGN_DISABLE);
    
            MPURegionSet(1, 0x40040000,
                      MPU_RGN_SIZE_512B |
                     MPU_RGN_PERM_EXEC |
                     MPU_RGN_PERM_PRV_RW_USR_RW  |
                     MPU_RGN_ENABLE);
        }
        else
        {
    
    
            MPURegionSet(0, 0x2003fe00,
                     MPU_RGN_SIZE_512B |
                     MPU_RGN_PERM_EXEC |
                     MPU_RGN_PERM_PRV_RO_USR_RO |
                     MPU_RGN_DISABLE);
           
           MPURegionSet(1, 0x40040040,
                     MPU_RGN_SIZE_64B |
                     MPU_RGN_PERM_EXEC |
                     MPU_RGN_PERM_PRV_RO_USR_RO  |
                     MPU_RGN_DISABLE);
    
    
    
     }
    
        MPURegionEnable(0);
        MPURegionEnable(1);
    
    }
    

  • Hi Shirin,

    Can you try a very simplified project with the memory regions you want to protect in the task switch function?  What is in the 512byte RAM region starting at 0x20003f00?  If you remove the MPU code for region 0 or region 1 from the task switch function can you get your program to work?

    Thanks,

    Janet

  • Hi janet,

    The region 0 contains some amount of variables that have to be protected when the program is runing out of region 2(the protected flash area 0x000F2000) as you see in switch function. now i undrestood that all the can registers have to protected, i found that the problem is in CanInterruptHandler, i puted in area flash to protedt it, but still gives me the same error, when i stop the compiler in canIntHandler with braekpoint in debug  the Pointer in switch fanction does not show the flash area, now my question is:

    does switch occure also for interrupts or no?

    void mySwitchFxn(ti_sysbios_knl_Task_Handle from, ti_sysbios_knl_Task_Handle to)
    {
    
     // whan i stop the compiler in canInterruptHandler the pointerSwich is not in flash area(frome 0x000F2000 to (0x000F2000 + 0x02000))
       
       uint32_t pointerSwich = (*(to)).fxn; 
    
        MPURegionDisable(0);
        MPURegionDisable(1);
    // Area flash
        if( (pointerSwich >= 0x000F2000) &&
                (pointerSwich < (0x000F2000 + 0x02000)))
        {
    
            MPURegionSet(0, 0x2003fe00,
                     MPU_RGN_SIZE_512B |
                     MPU_RGN_PERM_EXEC |
                     MPU_RGN_PERM_PRV_RW_USR_RW  |
                     MPU_RGN_DISABLE);
    //can registers
            MPURegionSet(1, 0x40040000,
                      MPU_RGN_SIZE_4K |
                     MPU_RGN_PERM_EXEC |
                     MPU_RGN_PERM_PRV_RW_USR_RW  |
                     MPU_RGN_DISABLE);
    
        }
        else
        {
    
    
            MPURegionSet(0, 0x2003fe00,
                     MPU_RGN_SIZE_512B |
                     MPU_RGN_PERM_EXEC |
                     MPU_RGN_PERM_PRV_RO_USR_RO |
                     MPU_RGN_DISABLE);
    
    //can registers
            MPURegionSet(1, 0x40040000,
                      MPU_RGN_SIZE_4K |
                      MPU_RGN_PERM_EXEC |
                      MPU_RGN_PERM_PRV_RO_USR_RO|
                      MPU_RGN_DISABLE);
    
        }
     MPURegionEnable(0);
     MPURegionEnable(1);
    
    }
    

  • Hi Shirin,

    It looks like your task switch may be going into the 'else' branch (pointerSwitch outside of the range 0xF2000 - 0xF4000), and setting the permissions of the CAN registers to read-only for both privileged and user modes.  Then if the CAN interrupt is triggered, the CAN ISR can not write to those registers.

    Could you try changing

    MPURegionSet(1, 0x40040000,
                      MPU_RGN_SIZE_4K |
                      MPU_RGN_PERM_EXEC |
                      MPU_RGN_PERM_PRV_RO_USR_RO|
                      MPU_RGN_DISABLE);
    
    to
            MPURegionSet(1, 0x40040000,
                      MPU_RGN_SIZE_4K |
                      MPU_RGN_PERM_EXEC |
                      MPU_RGN_PERM_PRV_RW_USR_RO|
                      MPU_RGN_DISABLE);
    
    in the 'else' branch?

    Best regards,
    Janet
  • Hi jent ,

     yes exactly and as i told in my previous post i puted the interrupt in area flash :

    volatile void CANIntHandler(UArg arg0) __attribute__((section(".pfel")));
    
    

    but it seems still switch function at the moment of interrupt goes to else.

    so my question is does switch also happen for interrupt? if yes why in this case switch does not show the area flash when interrupt is in progress?

  • Hi Shirin,

    The interrupt handler may be in flash, but the interrupt may have occurred during a task that was running in non-flash memory.  The switch function would have made the CAN registers read-only.  Can you try changing the permissions of the CAN registers to

        MPU_RGN_PERM_PRV_RW_USR_RO

    in the 'else' branch of your switch function?

    Best regards,

    Janet