Hard fault during packets reception

Hello, I have a working FreeRTOS + TCP/IP application which manages to transmit and receive packets. The Ethernet interrupt + a deferred interrupt handler task are being used in order to read received packets. I’m using ARM Cortex-M3. During packets reception (it can be after a few seconds or couple of minutes), a hard fault is asserted. Additional details: – configKERNELINTERRUPTPRIORITY is set to 255. – configMAXSYSCALLINTERRUPTPRIORITY is set to 191 – ETHERNETIRQn priority is set to 223 (i.e. 0b11011111, lower than configMAXSYSCALLINTERRUPT_PRIORITY, no sub priority bits) in xNetworkInterfaceInitialise() as mentioned below.
  • StartupCMSDKCM3.s is left without any changes.
  • I defined a function of mine (xEthernetHandler) to be the ETHERNETHandle (#define xEthernetHandler ETHERNETHandler) in FreeRTOSConfig.h.
xNetworkInterfaceInitialise:
portBASETYPE xNetworkInterfaceInitialise(void) { portBASETYPE xreturn; /* The Rx deferred interrupt handler task is created at the highest possible priority to ensure the interrupt handler can return directly to it no matter which task was running when the interrupt occurred. */ xreturn = xTaskCreate( xDeferredInterruptHandlerTask, “RCV”, configMINIMAL_STACK_SIZE * 5, NULL, mainDEFERRED_IRQ_TASK_PRIORITY, &xDeferredInterruptTaskHandle);
Common_EnableIrq(ETHERNET_IRQn, 223);
return xreturn; }
Interrupt handler:
void xEthernetHandler(void) { BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if(SMSC9220_RxStatusFifoLevelIrq())
{
    vTaskNotifyGiveFromISR(xDeferredInterruptTaskHandle, (BaseType_t *)&xHigherPriorityTaskWoken);
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
    CLEAR_BIT(SMSC9220->INT_EN, 3);
}

/* Additional handlers will be added here */
SMSC9220ClearAllIrqs(); NVICClearPendingIRQ(ETHERNET_IRQn); }
xDeferredInterruptHandlerTask:
void xDeferredInterruptHandlerTask( void * pvParameter1, uint32t ulParameter2 ) { NetworkBufferDescriptort *pxBufferDescriptor; size_t xBytesReceived; unsigned int index; IPStackEvent_t xRxEvent; unsigned int dwords_to_read; for( ;; ) { ulTaskNotifyTake( pdFALSE, portMAX_DELAY );
  for ( ;; )
  {
      xBytesReceived = SMSC9220_RecvSize();

      if(xBytesReceived <= 0)
      {
          break;
      }

      /* Reading dwords, so xBytesReceived shall be divisible by 4 */
      if(xBytesReceived % 4 != 0)
      {
          dwords_to_read = (xBytesReceived + 3) >> 2;
          xBytesReceived = dwords_to_read << 2;
      }

      pxBufferDescriptor = pxGetNetworkBufferWithDescriptor(xBytesReceived, 0);

      if(pxBufferDescriptor == NULL)
      {
          iptraceETHERNET_RX_EVENT_LOST();
          break;
      }

      index = 0;
      if(SMSC9220_RecvPacket((unsigned int *)pxBufferDescriptor->pucEthernetBuffer, &index))
      {
          printf("Packet receive failed.n");
          vReleaseNetworkBufferAndDescriptor(pxBufferDescriptor);
          continue;
      }

      pxBufferDescriptor->xDataLength = index << 2;

      /* See if the data contained in the received Ethernet frame needs to be processed */
      if(eConsiderFrameForProcessing(pxBufferDescriptor->pucEthernetBuffer) != eProcessBuffer)
      {
          vReleaseNetworkBufferAndDescriptor(pxBufferDescriptor);
          continue;
      }

      /* The event about to be sent to the TCP/IP is an Rx event. */
      xRxEvent.eEventType = eNetworkRxEvent;

      /* pvData is used to point to the network buffer descriptor that now references the received data. */
      xRxEvent.pvData = (void *)pxBufferDescriptor;

      /* Send the data to the TCP/IP stack. */
      if(xSendEventStructToIPTask(&xRxEvent, 0) == pdFALSE)
      {
          vReleaseNetworkBufferAndDescriptor(pxBufferDescriptor);
          iptraceETHERNET_RX_EVENT_LOST();
          continue;
      }

      /* The message was successfully sent to the TCP/IP stack. Call the standard trace macro to log the occurrence. */
      iptraceNETWORK_INTERFACE_RECEIVE();
  }

  SET_BIT(SMSC9220->INT_EN, 3);
} }
Is there anything wrong with the ethernet interrupt configuration? What could be the source of the problem? Thank you, Orit

Hard fault during packets reception

Hi Orit, Hard-faults are a bit difficult to debug, but if you catch them properly, you must be able to see the values of all registers at the time of the fault. Two registers are interesting in particular: pc and lr. These registers point to locations in the code: please open your LSS listing and look-up both addresses. If an address is odd (e.g. 0x45029), look for the address minus 1 (0x45028). If you really run out of ideas, you can write me at h point tibosch at freertos point org, and I’ll try to help you more in detail.

Hard fault during packets reception

Thank you Hein, Note that I’ve also looked for MMFSR (MemManage Fault Status Register) but I didn’t find it. I found MMFAR (MemManage Fault Address Register).

Hard fault during packets reception

Some information on debugging hard faults can be found here: http://www.freertos.org/Debugging-Hard-Faults-On-Cortex-M-Microcontrollers.html

Hard fault during packets reception

I’ve change the HardFault_Handler accordingly, but the registers values that are saved in pulFaultStackAddress still seem invalid. http://www.freertos.org/FreeRTOSSupportForumArchive/July2012/freertosxQueueReceivecauseshardfault5455589.html Where is the stack used by main defined? As far as I know, the “stacksize” in startupCMSDKCM3.s is related to the total stack size.

Hard fault during packets reception

According to the map file, my stack starts at 0x00045800: 0x00010374 0x00000078 Zero RW 529 .bss FreeRTOSARP.o 0x000103ec 0x00000024 Zero RW 588 .bss FreeRTOSDHCP.o 0x00010410 0x00000060 Zero RW 635 .bss FreeRTOSDNS.o 0x00010470 0x00000064 Zero RW 659 .bss FreeRTOSIP.o 0x000104d4 0x00000028 Zero RW 720 .bss FreeRTOSSockets.o 0x000104fc 0x00000014 Zero RW 803 .bss FreeRTOSTCPWIN.o 0x00010510 0x00000040 Zero RW 1012 .bss queue.o 0x00010550 0x000008ec Zero RW 1032 .bss tasks.o 0x00010e3c 0x00000950 Zero RW 1065 .bss timers.o 0x0001178c 0x00013880 Zero RW 1106 .bss heap4.o 0x0002500c 0x000005b4 Zero RW 1174 .bss BufferAllocation2.o 0x000255c0 0x00000054 Zero RW 1268 .bss cw.l(stdiostreams.o) 0x00025614 0x00000054 Zero RW 1269 .bss cw.l(stdiostreams.o) 0x00025668 0x00000054 Zero RW 1270 .bss cw.l(stdiostreams.o) 0x000256bc 0x000000e4 Zero RW 1278 .bss cw.l(rand.o) 0x000257a0 0x00000060 Zero RW 1557 .bss cw.l(libspace.o) 0x00025800 0x00020000 Zero RW 451 HEAP startupCMSDKCM3.o 0x00045800 0x00002000 Zero RW 450 STACK startupCMSDK_CM3.o On the other hand, according to the debugger the start addresses of tasks stack are: 0x00010DE8, 0x00011728, 0x00011B50, 0x000123C8. I don’t understand why they are not located in the STACK memory region.

Hard fault during packets reception

Hi Orit, Please find attached some code that should work on a cortex-m3. I added a struct xREGISTER_STACK, which makes it easier to add all variables to the ‘watch’, just add/inspect *pxRegisterStack. You write about the stack and you show addresses in RAM, but when there is a hard-fault, in the first place it is interesting to see which instruction caused a crash. Once the instruction is found, the other registers might be interesting. I would be interesting to see the value of:
pxRegisterStack->pc; /* Program counter. */
pxRegisterStack->psr;/* Program status register. */
You can look them up in the lss file (not the map file, which describes the .data and .bss).

Hard fault during packets reception

Yes I know 🙂 I’ve asked because I think there might be a problem with the stack that is used by main (or with tasks stack allocation by general). lr = 0x0000031F pc = 0x41000000 psr = 0xA5A5A5A5 The pc and psr seem invalid but the lr points on a code area belongs to ETH_MPS2.o (ethernet driver) according to the file that was generated by –list (is this the lss file?) How can I know the exact instruction that caused the crash? Thank you very much for your help! Orit

Hard fault during packets reception

Yes I know 🙂
Sorry, sometimes it’s difficult to estimate what knowledge is present already.
0x00025800 0x00020000 Zero RW 451 HEAP startupCMSDKCM3.o 0x00045800 0x00002000 Zero RW 450 STACK startupCMSDKCM3.o
The size of the heap – stack section is 128 KB. The heap starts at an offset of 150 KB.
On the other hand, according to the debugger the start addresses of tasks stack are: 0x00010DE8, 0x00011728, 0x00011B50, 0x000123C8. I don’t understand why they are not located in the STACK memory region.
The stack at 0x45800 will only be used at start-up. Once vTaskStartScheduler() has been called, each task will have its own stack, allocated by heap_4.c
0x0001178c 0x00013880 Zero RW 1106 .bss heap_4.o
You reserved 80,000 bytes of HEAP. I suppose that “HEAP startupCMSDKCM3″ is the system heap, which is unused? If it is unused, you might want to increase your actual heap in heap_4.c. Are you using pvPortMalloc() and vPortFree() in all cases, and not malloc() and free()? What MCU are you using? Are the above memory addresses all located in valid RAM? ~~~~
lr = 0x0000031F pc = 0x41000000 psr = 0xA5A5A5A5 ~~~~
It looks like lr points to a RAM location. But it may also be rubbish. And pc = 0x41000000, isn’t that a reset address? Are you using BufferAllocation1.c or BufferAllocation2.c? In case you use BufferAllocation1.c, what does your vNetworkInterfaceAllocateRAMToBuffers() look like? Note that BufferAllocation1.c contains some useful debugging code, in case you define ipconfigTCP_IP_SANITY = 1. If you want you can email all relevant source code to me and I will check it. It will be something simple like calling vReleaseNetworkBufferAndDescriptor() once too often, or writing to memory that has been released already.

Hard fault during packets reception

Hi Hein, I sent you an email with the answers and the relevant files.