lpcware

Hardfault in interrupt driver

Discussion created by lpcware Employee on Jun 15, 2016
Latest reply on Jun 15, 2016 by lpcware
Content originally posted in LPCWare by fentechnt on Mon Feb 15 06:03:02 MST 2010
I've been porting my serial port driver across from LPC21xx and it randomly causes a hard fault.  I've been debugging it by removing lines in the interrupt handler and the fault disappears if I remove the line that writes the incoming serial data to a buffer.


#define SERIAL_BUFFER_SIZE           ( 64 )
#define SERIAL_BUFFER_LENGTH_MASK    ( SERIAL_BUFFER_SIZE - 1 )

typedef struct tSerialBufferTag
{
  int iPutPtr;
  int iGetPtr;
  byte abBuffer[ SERIAL_BUFFER_SIZE ];
} tSerialBuffer;

static volatile tSerialBuffer sInputBuffer;
static volatile tSerialBuffer sOutputBuffer;
static volatile bool boTHRE = TRUE;

void UART_IRQHandler( void )
{
  static char cChar;
  static byte bIIR;

  // What caused the interrupt?
  bIIR = LPC_UART->IIR;
  switch( bIIR & UART_INTERRUPT_SOURCE_MASK )
  {
    case UART_SOURCE_RLS:
      // Not handling this, but clear the interrupt.
      cChar = LPC_UART->LSR;
      break;

    case UART_SOURCE_THRE:
      // The THR is empty.  If there is another character in the Tx
      // buffer, send it now.
      if ( sOutputBuffer.iGetPtr != sOutputBuffer.iPutPtr )
      {
#if 0
        cChar = sOutputBuffer.abBuffer[ sOutputBuffer.iGetPtr & SERIAL_BUFFER_LENGTH_MASK ];
#endif
        sOutputBuffer.iGetPtr++;
        LPC_UART->THR = cChar;
      }
      else
      {
        // nothing to send, indicate transmitter-empty to driver
        boTHRE = TRUE;
      }
      break;

    case UART_SOURCE_RX_TIMEOUT:
    case UART_SOURCE_RX:
      // A character was received.  Place it in the queue of received characters.
      cChar = LPC_UART->RBR;
      if ( sInputBuffer.iPutPtr + 1 != sInputBuffer.iGetPtr )
      {
#if 0
        sInputBuffer.abBuffer[ sInputBuffer.iPutPtr & SERIAL_BUFFER_LENGTH_MASK ] = cChar;
#endif
        sInputBuffer.iPutPtr++;
      }
      break;

    case UART_SOURCE_MSR:
      // @TODO: deal with this properly - for now just clear it
      cChar = LPC_UART->MSR;
      break;

    default:
      // There is nothing to do, leave the ISR.
      break;
  }
}


In the code above, I've commented out the lines that make the hardfault happen.

The fault sometimes happens on the first few characters sent or recieved, other times it happens after several hundred characters.  So it doesn't seem related to the buffer size.

Only other interrupt running is the SysTick interrupt which is handled elsewhere (and only increments a counter for debug).

Any suggestions, anyone?

Outcomes