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.

Bus fault

We have developed a TM4C based device, now in production. Unfortunately we have discovered problems with the latest software release. For a particular unit (i.e. most units does not display this problem), about one in five start ups fails. Investigations show that the device hangs in the fault ISR due to a bus fault occurring when writing to the VREF bit of the ADCCTL register.

The ADC peripheral is enabled just before the VREF bit is accessed, i.e. the recommended delay of 3 system clocks between clock enable and register access mistakenly has been omitted. This piece of code is however old and we cannot understand why the problem has arisen now between two software revisions. By inserting a single NOP randomly the problem can go away (e.g. 20 lines of code before enabling the peripheral or 15 lines after does the trick, but not 20 lines after - same function, no optimization). Stack size has been increased without improvements. It seems like code size/placement affects the behavior and vulnerability for lacking delay after peripheral enable, but how?

I just want to understand the circumstances as it feels like there is something to learn from this.

Best Regards,
Johan

  • Hello Johan,

    Now I am not sure which device and what system frequency, but on TM4C12x devices use prefetch buffers at higher frequency. If earlier the code was not in the prefetch range then enabling the clock and subsequently calling any other function would cause the prefetch stall to get the instructions. After code change the position may have changed (a check of the debug symbols should help) causing the new code position to be in prefetch buffer and reducing the delay.

    The right approach to avoid this issue is to use SysCtlPeripheralReady to poll when the peripheral is ready to be accessed after SysCtlClockEnable API is called. Even better approach to ensure a clean start of a peripheral is to call SysCtlPeripheralReset before SysCtlClockEnable is called. In a short set of code line...

    SysCtlPeripheralReset(X);
    SysCtlClockEnable(X);
    while(!(SysCtlPeripheralReady(X));

    where X is the peripheral define in sysctl.h

    Regards
    Amit
  • May that great, "Peripheral Troika" be promoted to, "Sticky" status? (surely this will help many...)
    Further - your detailed explanation of (both) system clock frequency AND prefetch buffers has clarified issues we've long had - & never understood. (till now)
    Great job Amit - thank you - very much appreciated...