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.

TM4C1230E6PM: Reset of micro

Part Number: TM4C1230E6PM

Hi,

I have several systems that communicate through the CANbus. Microcontrollers use ADC, master I2C, CANbus and systick. all ms, an ADC measurement request is made and every 100ms, I read data on the I2C. the microcontroller receive a request from the CANbus and reponse in a 1ms time base of the scheduler.

Only 1 system can reponse on a request, The ID for each systems is different.

I have 10 systems and in this Week, End, I have 4 who is resetted. (When I have a reset, I lost the power of the microcontroller). I don't have any timer of this problem but my customer who have this installation see a reset after many hour, but all systems isn't resetted.

Is it possible that the request can generate a fault in the microcontroller?

Best Regards,

  • Hello Micou,

    There are many possible causes for a system fault and the description you've provided isn't really sufficient to say what might be happening. That said I don't believe just a simple CAN request could cause a software reset under normal circumstances.

    One means you can initially try and use to debug this is to look at the Reset Cause (RESC) Register to determine what caused the system reset. This may need to be extra code added to your startup routine to read and save the result since the exact reset time isn't clear.

    One area to look at is if there is any cases of a peripheral being disabled in the application. If a peripheral is disabled and another part of the application is unaware and tries to access the peripheral, that alone could cause a system fault.

    Another possibility could be memory issues such as a stack overflow or a buffer overflow. These could trigger unexpected system resets as well, and the cause would be related to what part of the code is prompting the overflow which could include a CAN Request.

    If you get to a point where you can replicate the reset, and it is a software fault in the system, then referring to our Fault Debug Guide would be the next key step: https://www.ti.com/lit/pdf/spma043 - though I don't believe that is currently applicable given the randomness of the resets. Just wanted to provide that upfront so you are aware of that document.

    Those are some initial thoughts to get you started on the debug efforts, and as you find out more details let me know so I can further guide you along how to debug this issue.

    Best Regards,

    Ralph Jacobi

  • Hello Jacobi,

    I mistakenly press the resolved button.

    The RESC resgister doesn't give the state, i have a external watchdog who generate a reset extern when the power supply is under 2.63V. I have already tested this register and I don't have other value than a external reset when I restart the system.

    I have tested this night a soft who write to the EEPROM FaultStatus register, HFaultStatus Register when I go to the Harfault handler. But when I restart the battery, the data read in the EEPROM, I read 0x00000000 this to register.

    I tested for 24h i have a set of 10 systems that are active without the CANbus and no problem occurred

    I tried again with the CANbus and 2 systems stopped. the first, after 4h40 of operation and the second after 12h of operation.

    Best Regards,

    Ludovic Micou

  • Hi,

    After testing the fault record, I saw an error in my code that made the record not to be recorded. So I will repeat my test with this correction. I noticed in my code that I could have an interruption of the CANBus while having a deactivation of the CANBUS 

    Best Regards,

    Ludovic Micou

  • Hello Micou,

    After testing the fault record, I saw an error in my code that made the record not to be recorded. So I will repeat my test with this correction. I noticed in my code that I could have an interruption of the CANBus while having a deactivation of the CANBUS 

    Thanks for the update here, please let me know on the results of this. The code you describe could definitely trigger a fault condition, so hopefully resolving that will have your issue solved.

    No worries about the mistaken resolution button - I will continue monitoring the thread until we agree your problem is fully resolved.

    Best Regards,

    Ralph Jacobi

  • Hello Jacobi,

    I have a error in the FAULTSTAT who is 0x20000 (INVSTAT). I don't use the EPSR Register in my soft. I have in the MMAdress register the data 0xE000ED34 and in the register BusAdress the data 0xE000ED38.

    is  it possible that the EPSR Register is call in the Canbus library of TI?

    What is the possible cause of this Fault?

    Best Regards,

    Ludovic Micou

  • Hello Jacobi,

    I removed the optimization and increased the STACK to 1024. I did not recover a reset after more than 12 hours of operation.

    I only have a problem with the CAN. In only 1 system, I loss the communication in CANBUS. I should reinit the canbus if I detect a error CAN or if the time without detect a receipt for 5 second.

    Interrupt CAN:

    /**
     * @fn void vd_app_scheduler_Update(void)
     * @brief Update scheduler counter and variable
     * @param none
     * @return none
     */
    void CAN0_Handler(void)
    {
    uint32_t ui32Status;
    
         //
         // Read the CAN interrupt status to find the cause of the interrupt
         //
         ui32Status = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE);
    
         //
         // If the cause is a controller status interrupt, then get the status
         //
         if(ui32Status == CAN_INT_INTID_STATUS)
         {
             //
             // Read the controller status.  This will return a field of status
             // error bits that can indicate various errors.  Error processing
             // is not done in this example for simplicity.  Refer to the
             // API documentation for details about the error status bits.
             // The act of reading this status will clear the interrupt.  If the
             // CAN peripheral is not connected to a CAN bus with other CAN devices
             // present, then errors will occur and will be indicated in the
             // controller status.
             //
             ui32Status = CANStatusGet(CAN0_BASE, CAN_STS_CONTROL);
    
             //
             // Set a flag to indicate some errors may have occurred.
             //
    
             if (ui32Status & 0x08)
             {
                 g_bMsgObj3Sent = 1;
                 g_bMsgObj4Sent = 1;
             }
    
             if (ui32Status & 0x10)
             {
                 u8_FlagRx = 1;
             }
    
             CANIntClear(CAN0_BASE, 0);
             CANIntClear(CAN0_BASE, 1);
             CANIntClear(CAN0_BASE, 2);
             CANIntClear(CAN0_BASE, 3);
             CANIntClear(CAN0_BASE, 4);
             if (ui32Status & 0xE3)
             {
                 vd_srv_COM_Init();
                 u8_FlagErrorCan = 1;
                 g_bErrFlag = 1;
    
             }
    
         }
    
         //
         // Check if the cause is message object 1, which is used for sending
         // message 1.
         //
         else if(ui32Status == 1)
         {
             u8_FlagRx = 1;
    
             //
             // Getting to this point means that the TX interrupt occurred on
             // message object 1, and the message TX is complete.  Clear the
             // message object interrupt.
             //
             CANIntClear(CAN0_BASE, 1);
    
             //
             // Increment a counter to keep track of how many messages have been
             // sent.  In a real application this could be used to set flags to
             // indicate when a message is sent.
             //
             g_ui32Msg1Count++;
    
             //
             // Since the message was sent, clear any error flags.
             //
             g_bErrFlag = 0;
         }
    
         //
         // Check if the cause is message object 2, which is used for sending
         // message 2.
         //
         else if(ui32Status == 2)
         {
             u8_FlagRx = 1;
    
             //
             // Getting to this point means that the TX interrupt occurred on
             // message object 1, and the message TX is complete.  Clear the
             // message object interrupt.
             //
             CANIntClear(CAN0_BASE, 2);
    
             //
             // Increment a counter to keep track of how many messages have been
             // sent.  In a real application this could be used to set flags to
             // indicate when a message is sent.
             //
             g_ui32Msg1Count++;
    
             //
             // Since the message was sent, clear any error flags.
             //
             g_bErrFlag = 0;
         }
    
         //
         // Check if the cause is message object 3, which is used for sending
         // messages 3 and 4.
         //
         else if(ui32Status == 3)
         {
             u8_FlagRx = 1;
    
             //
             // Getting to this point means that the TX interrupt occurred on
             // message object 1, and the message TX is complete.  Clear the
             // message object interrupt.
             //
             CANIntClear(CAN0_BASE, 3);
    
             //
             // Increment a counter to keep track of how many messages have been
             // sent.  In a real application this could be used to set flags to
             // indicate when a message is sent.
             //
             g_ui32Msg1Count++;
    
             //
             // Since the message was sent, clear any error flags.
             //
             g_bErrFlag = 0;
         }
    
         //
         // Otherwise, something unexpected caused the interrupt.  This should
         // never happen.
         //
         else if(ui32Status == 4)
         {
             CANIntClear(CAN0_BASE, 4);
    
             //
             // Increment a counter to keep track of how many messages have been
             // sent.  In a real application this could be used to set flags to
             // indicate when a message is sent.
             //
             g_ui32Msg1Count++;
             g_bMsgObj3Sent = 1;
             g_bMsgObj4Sent = 1;
             //
             // Since the message was sent, clear any error flags.
             //
             g_bErrFlag = 0;
         }
         else
         {
             g_bMsgObj3Sent = 1;
             g_bMsgObj4Sent = 1;
             vd_srv_COM_Init();
             u8_FlagErrorCan = 1;
         }
    
    }

    init CAN 

    void vd_srv_COM_Init(void)
    {
        u32_UiCanBus = CAN0_BASE;
        /* Enable Rx interrupt */
        CANDisable(u32_UiCanBus);
        CANIntDisable(u32_UiCanBus, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
    
        IntDisable(INT_CAN0);
        CANInit(u32_UiCanBus);
        CANBitRateSet(u32_UiCanBus, SysCtlClockGet(), 250000);
        CANIntEnable(u32_UiCanBus, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
        IntEnable(INT_CAN0);
        IntPrioritySet(INT_CAN0, 10);
    
        CANEnable(u32_UiCanBus);
        g_sCANMsgObjectRx1.ui32Flags = (MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER
                                     );
        g_sCANMsgObjectRx1.pui8MsgData = u8_CanRxData;
        g_sCANMsgObjectRx1.ui32MsgID = 0x20;
        g_sCANMsgObjectRx1.ui32MsgIDMask = 0;
        g_sCANMsgObjectRx1.ui32Flags = (MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER
                                 );
        g_sCANMsgObjectRx1.ui32MsgLen = 8;
        CANMessageSet(u32_UiCanBus, 1, &g_sCANMsgObjectRx1, MSG_OBJ_TYPE_RX);
        g_sCANMsgObjectRx1.ui32MsgLen = 7;
        CANMessageSet(u32_UiCanBus, 2, &g_sCANMsgObjectRx1, MSG_OBJ_TYPE_RX);
        g_sCANMsgObjectRx1.ui32MsgLen = 8;
        g_sCANMsgObjectRx1.ui32Flags = (MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER | MSG_OBJ_REMOTE_FRAME
                                     );
        CANMessageSet(u32_UiCanBus, 3, &g_sCANMsgObjectRx1, MSG_OBJ_TYPE_RX_REMOTE);
    }

    In the scheduler who execute all ms: 

    void vd_srv_COM_ReceptInt(uint32_t lu32_UiCanBus)
    {
        /* Get RX message */
        if (u8_FlagRx == 1)
        {
            CANMessageGet(lu32_UiCanBus, 1, &g_sCANMsgObjectRx1, 0);
            u8_FlagRx = 0;
            vd_srv_com_ReadCan(lu32_UiCanBus);
        }
        else
        {
            u32_TempoReinitCan++;
            if (u32_TempoReinitCan > 5000UL)
            {
                vd_srv_COM_Init();
                u32_TempoReinitCan = 0UL;
            }
        }
        if (u8_FlagErrorCan == 1)
        {
           // vd_srv_COM_Init();
             u32_TempoReinitCan = 0UL;
            u8_FlagErrorCan = 0;
        }
      
    }

    What can cause me to lose communication and reset not working?

    Best Regards

    Ludovic Micou

  • Hello Micou,

    I have in the MMAdress register the data 0xE000ED34 and in the register BusAdress the data 0xE000ED38.

    That doesn't quite add up to me because those are the addresses of those registers. I think you may not have read the contents correctly.

    is  it possible that the EPSR Register is call in the Canbus library of TI?

    The EPSR is the Execution Program Status Register so it's not necessary a call in the library but something the Cortex-M4F will use consistently as Application code is executed.

    You can examine the EPSR register in the Fault handler to get the current value of the stacked PSR which can help find out what operation triggered the fault.

    I removed the optimization and increased the STACK to 1024. I did not recover a reset after more than 12 hours of operation.

    I am not 100% clear what you mean by 'did not recover a reset' - does that mean the code is executing without issue now?

    If so, I'd wager the stack increase was the more important change. You should place optimizations back on and re-test to see if that solved the issue.

    You can also check for Stack Overflow. If you want to do so, here are the steps you can follow.

    To test for Stack Overflow, the following steps should be done:

    1. Identify the starting memory location of the Stack in the .map file inside of the Debug folder
    2. Enter debug mode but do not start to run code
    3. Go to “View” à “Memory Browser”
    4. Enter the address of the stack into the input box
      1. In my example above, that address is 0x0000420c (you need to add the 0x to the front of it!)
    5. This will show you the stack contents
    6. Next, fill the stack contents with known data:
      1. Go to “Tools” à “Fill Memory”
      2. Input Start Address = Stack Address from .map file
      3. Length = Stack size/2 (In my example this is 500, so 500/2 = 250) – this is because each memory location stores 2 bytes of the Stack
      4. Data Value = 0xAA (or 0x55, or something else that is easily identifiable)
    7. The Memory Browser should now look like:
    8. Since the stack has been overwritten entirely, it is important to restore the initial stack settings before running the code. This can be done by one of two ways:
      1. Use “Soft Reset”
      2. Exit Debug mode and re-enter debug mode
        1. I had to do this for some projects, but usually Soft Reset works
      3. When done correctly, the memory Browser should have non 0xAA bytes at either the top or bottom of the Stack:
    9. Now run the code for a sufficient amount of time based on application
      1. If an overflow occurs, all inputted data (0xAA in my example) would no longer be in the stack

    Note that my example is for a slightly different MCU but the same principle applies for TM4C. You'd see the following for a TM4C .map file:

    Best Regards,

    Ralph Jacobi