UART Glitch On Startup Causes Hardfault in FreeRTOS

Jeff,

Below is the GPTimer ISR, where h4l() and h4h() are the gpio port h pin 4 toggles for the GPTimer trace in above logic analyzer figures. No FreeRTOS API references.

void TIM2_IRQHandler(void)
/*
// TIMER2 ISR
//
// Manages and updates the 8 system software timers. If a system timer has not
// reached zero it is decremented.
//
*/
{
uint8_t i;
  h4l();
  h4h();
  // update the 8 system software timers
  for(i = 0; i <= MAX_TIMERS; i++)
  {
    if(Timers[i] > 0)         // if this timer is still counting down
    {
      --Timers[i];            // decrement this timer
      --*Tstatus[i];          // and this timer`s status variable

      if(Timers[i] == 0)      // if this timer has reached zero
        Tstatus[i] = 0;       // NULL this timer`s status pointer
    }
  }
  ++tick;
  TIM2->SR &= ~BIT0;          // reset TIM2 IRQ pending status
  h4l();
}

Okay. Let’s test the hypothesis of entry/exit stack issue. If we guard the entire call/return to CalcAuth(), we observe no hardfault. Now the next test might be to guard the entry or return instead of the entire function call and return. If it protects from the hardfault, then we are most likely getting a stack corruption from the interrupt somehow. This was also a speculated hypothesis from the ST FAE, so it is worth consideration.

Thank you for the reference. I am starting to grok the priorities. Though when I set the GPTimer to NVIC priority 1 (highest without going unmaskable), it runs all the time and on time. When it is 0xf, it does get blocked for a time and then eventually runs, though the timing is inconsistent. With a single FreeRTOS thread it seems odd. Not sure what to make of it given that it should “always” fire.

I assume you are not talking about the USART’s RX buffer here – your code already reads that buffer after the framing error and before the TX/RX packet exchange. Instead I assume you are talking about an RX queue in software. If you pull the errant 0 byte out of the software queue before the parser consumes it, and if that solves your problem, that is an excellent clue.

You are correct, I am talking about the circular buffer that DMA uses, not the hardware 1 byte buffer.

Notably, the compiler output for the C code of the function that handles those first two packets (and the null first byte) requires -O1 or lower to hardfault. -O2 and we see no hardfault. I’ll post the listings as screenshots of Ozone following this reply to see the differences which may be related to the hardfault.

My logic analyzer toggles for PH3 CalcAuth were supposed to be before/after the call/return of CalcAuth(). I discovered they were also before and after the calling function of CalcAuth(), so it could be either. Going high is the call, going low is the return.

CalcAuth() does not use hardware assist. It looks like this:

uint32_t CalcAuth(uint8_t dat)
/*
// Calculates an ongoing CRC on the byte sent in 'dat' and returns the
// calculated value to the caller. Each successive byte sent to this
// function is calculated into CRC of the previous byte stream.
//
*/
{
int i;
unsigned long crc;

  crc = dat;

  ++afbcount;

  if((afbcount % nth_BYTE) == 0)
    dat &= 0xfd;

  for(i = 8; i > 0; i--)
  {
    if(crc & 1)
      crc = ((crc >> 1) ^ CRC_POLYNOMIAL);

    else
      crc >>= 1;
  }

  return crc;
}

I’ll review the hardfault FreeRTOS guidance and get back later.

Cheers,
Joe

EDIT: added rolling count code