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.

RTOS/TM4C1294NCPDT: How to use MPU to debug memory issue

Part Number: TM4C1294NCPDT
Other Parts Discussed in Thread: SYSBIOS

Tool/software: TI-RTOS

If I suspect that in my app some code modifies a specific RAM address (or some address randomly within a range), can I use MPU to debug this? My idea is:

  1. Place a useless array to cover the address range.
  2. Setup MPU for this area. I think I can use "module ti.sysbios.family.arm.MPU" or TivaC MPU device driver. The problem is: when a violation occurs, can I know the PC that trigger the violation? By default without enabling the MPU interrupt, a hard fault exception will happen.
  3. How to enable the interrupt for MPU (MPUIntRegister in driverlib can't be used in RTOS project, and there is no function to deal with interrupt in "module ti.sysbios.family.arm.MPU")? Can I get more information about the error in the interrupt function?

Thanks

  • Hi Jianyi,

    I think the TI-RTOS may have already used the MPU. I don't know if TI-RTOS will allow separate MPU management in an OS context. In an non OS environment you can manage the MPU yourself. If there is a MPU fault then you will get a Memory management exception, not interrupt. You can read the cause of the exception in the Fault Status Registers and the offending address in the Fault Address Registers. Please refer to the datasheet and look for the FAULTSTAT and MMADDR registers. Please also refer to the Peripheral Driver library on using the MPU API functions to configure the MPU.

    BTW, what do you mean to place a useless array to cover the address range. I hope you are not really declaring an array for the address range, right? All you need is to define the base address of the MPU region that you want to protect along with the size and protection attributes of the region.
  • Jianyi Bao said:
    If I suspect that in my app some code modifies a specific RAM address (or some address randomly within a range), can I use MPU to debug this?

    Using the MPU to trap such errant writes involves changing the code.

    CCS supports hardware watchpoints which can halt the target on a write to a specific RAM address. See Configure a Hardware Watchpoint. Using a hardware watchpoint to trigger on writes to a specific RAM address may allow to trap the fault without modifying the program, and the debugger will show the offending instruction which performed the write.

  • Hi, Charles,
    I do want to allocate a useless array, because I am suspent some code will modified RAM unexpectedly. But the RAM is also being used normally. Please see e2e.ti.com/.../636949.
    So I can't protect on a single word which is BIOS_Module->threadType in my case. I have to allocate an array near this address (and of course BIOS_Module will be moved to somewhere else), and apply MPU on this array.
  • Hi, Chester 

      Why I can't set such an advanced breakpoint in my CCS? My break point can only be like this:

    I am not attaching my target at present. I wonder if the dialog will be different once it is attached.

  • Jianyi Bao said:
    I am not attaching my target at present. I wonder if the dialog will be different once it is attached.

    Yes, the target does need to be attached before an advanced breakpoint can be set.

  • Hi, Chester 

      How to set a mask for read/write? Thanks

  • Hi, Charles,

      I have difficulties to use MPU in this chip.

    1. <ti/sysbios/family/arm/MPU.h> is not found in my RTOS version. So I can't use BIOS API for MPU.
    2. Then I have to use driverlib. But I found definition like "MPU_RGN_SIZE_32B" is not correct in driverlib/mpu.h. Size bit should be log2(size in bytes) - 1 according to datasheet.
    3. I use the following code to init MPU (Note up till now, only one region is configured), and MpuInit is called in main, exactly before BIOS_start. But just after MPUEnable(MPU_CONFIG_NONE), an exception will occur. Please see the snapshot below to see detailed information about the exception.

    #if 1
    
    
    #define NORMAL_MPU_NUM  4
    #define NORMAL_MPU_SIZE 2048
    #define NORMAL_MPU_ADDR_BASE 0x30000
    #define RAM_TOTAL_BASE 0x20000000
    #define RAM_TOTAL_SIZE 0x40000
    #define NORMAL_MPU_ADDR_STEP ((RAM_TOTAL_SIZE - NORMAL_MPU_ADDR_BASE)/NORMAL_MPU_NUM)
    
    #define NORMAL_MPU_ADDR(n) (RAM_TOTAL_BASE + NORMAL_MPU_ADDR_BASE + (n)*NORMAL_MPU_ADDR_STEP)
    
    #define MPU_ADDR_0 NORMAL_MPU_ADDR(0)
    #define MPU_LEN_0  NORMAL_MPU_SIZE
    #define MPU_ADDR_1 NORMAL_MPU_ADDR(1)
    #define MPU_LEN_1  NORMAL_MPU_SIZE
    #define MPU_ADDR_2 NORMAL_MPU_ADDR(2)
    #define MPU_LEN_2  NORMAL_MPU_SIZE
    #define MPU_ADDR_3 0x2003E800
    #define MPU_LEN_3  0x800
    
    #pragma RETAIN(NormalMpuArray0)
    uint8 NormalMpuArray0[MPU_LEN_0] __attribute__((location(MPU_ADDR_0)));
    
    #pragma RETAIN(NormalMpuArray1)
    uint8 NormalMpuArray1[MPU_LEN_1] __attribute__((location(MPU_ADDR_1)));
    
    
    #pragma RETAIN(NormalMpuArray2)
    uint8 NormalMpuArray2[MPU_LEN_2] __attribute__((location(MPU_ADDR_2)));
    
    #pragma RETAIN(NormalMpuArray3)
    uint8 NormalMpuArray3[MPU_LEN_3] __attribute__((location(MPU_ADDR_3)));
    
    //#include <ti/sysbios/family/arm/MPU.h>
    #include <driverlib/mpu.h>
    
    typedef struct
    {
      uint addr;
      uint len;
    }MpuAddrLenT;
    
    static uint SingleBitLog2(uint v)
    {
      uint count = 0;
      
      while(v)
      {
        if(v & 0x01)
        {
          return count;
        }
    
        count++;
    
        v >>= 1;
      }
    
      return 0;
    }
    
    static const MpuAddrLenT MpuAddrAndLen[] = 
    {
      { MPU_ADDR_0,  MPU_LEN_0},
    //  { MPU_ADDR_1,  MPU_LEN_1},
    //  { MPU_ADDR_2,  MPU_LEN_2},
    //  { MPU_ADDR_3,  MPU_LEN_3},
    };
    
    static void MpuInit(void)
    {
    #if 0
    #else
    
      uint i;
      
      for(i = 0; i < ARRAY_ELEMENTS(MpuAddrAndLen); i++)
      {
        const uint addr = MpuAddrAndLen[i].addr;
        const uint len = MpuAddrAndLen[i].len;
    
        assert(0 == (addr % len));
      
        const uint sizeBits = (SingleBitLog2(len) - 1)<<1;
    
        const uint flags = sizeBits
                    | MPU_RGN_PERM_NOEXEC 
                    | MPU_RGN_PERM_PRV_NO_USR_NO
                    | MPU_RGN_ENABLE
                    ;
        
        MPURegionSet(i, addr, flags);
      }
    
      //MPUEnable(MPU_CONFIG_HARDFLT_NMI);
      MPUEnable(MPU_CONFIG_NONE);
    #endif
    }
    
    #endif

    Also .map is attached.

    It look the error is not related to my region. But I don't know what is wrong.

    0027.map.zip

    Thanks so much.

  • Hi Jianyi,
    I'm checking with the TI-RTOS expert to give comment on your MPU question in the context of TI-RTOS.
  • Jianyi Bao said:
      How to set a mask for read/write? Thanks

    I think the http://processors.wiki.ti.com/index.php/Watchpoints_for_Stellaris_in_CCS#Configure_a_Hardware_Watchpoint wiki page for Stellaris/Tiva devices which contains the "Configure a mask value (bits that will be ignored)" text has been inadvertently copied from the http://processors.wiki.ti.com/index.php/Hardware_Breakpoints_and_Watchpoints_for_C28x_in_CCS#Configure_a_Hardware_Watchpoint wiki page for C28x devices.

    Comparing the screen shots for the watchpoint properties dialogues on those two wiki pages shows:

    a) The C28x device watchpoints have an option for a Location Mask.

    b) The Stellaris/Tiva device watchpoints don't have an option for a Location Mask.

    Hopefully someone from TI can clarify this.