Hard fault during packets reception

orifai01 wrote on Tuesday, January 17, 2017:

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:

  • configKERNEL_INTERRUPT_PRIORITY is set to 255.

  • configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 191

  • ETHERNET_IRQn priority is set to 223 (i.e. 0b11011111, lower than configMAX_SYSCALL_INTERRUPT_PRIORITY, no sub priority bits) in xNetworkInterfaceInitialise() as mentioned below.

  • Startup_CMSDK_CM3.s is left without any changes.

  • I defined a function of mine (xEthernetHandler) to be the ETHERNET_Handle (#define xEthernetHandler ETHERNET_Handler) in FreeRTOSConfig.h.


portBASE_TYPE xNetworkInterfaceInitialise(void)
portBASE_TYPE 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,

Common_EnableIrq(ETHERNET_IRQn, 223);

return xreturn;

Interrupt handler:

void xEthernetHandler(void)
BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    vTaskNotifyGiveFromISR(xDeferredInterruptTaskHandle, (BaseType_t *)&xHigherPriorityTaskWoken);
    CLEAR_BIT(SMSC9220->INT_EN, 3);

/* Additional handlers will be added here */



void xDeferredInterruptHandlerTask( void * pvParameter1, uint32_t ulParameter2 )
NetworkBufferDescriptor_t *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)

  	/* 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)

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

  	pxBufferDescriptor->xDataLength = index << 2;

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

  	/* 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)

  	/* The message was successfully sent to the TCP/IP stack. Call the standard trace macro to log the occurrence. */

  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,

heinbali01 wrote on Tuesday, January 17, 2017:

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.

orifai01 wrote on Tuesday, January 17, 2017:

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).

rtel wrote on Tuesday, January 17, 2017:

Some information on debugging hard faults can be found here:

orifai01 wrote on Wednesday, January 18, 2017:

I’ve change the HardFault_Handler accordingly, but the registers values that are saved in pulFaultStackAddress still seem invalid.

Where is the stack used by main defined? As far as I know, the “stack_size” in startup_CMSDK_CM3.s is related to the total stack size.

orifai01 wrote on Wednesday, January 18, 2017:

According to the map file, my stack starts at 0x00045800:

0x00010374 0x00000078 Zero RW 529 .bss FreeRTOS_ARP.o
0x000103ec 0x00000024 Zero RW 588 .bss FreeRTOS_DHCP.o
0x00010410 0x00000060 Zero RW 635 .bss FreeRTOS_DNS.o
0x00010470 0x00000064 Zero RW 659 .bss FreeRTOS_IP.o
0x000104d4 0x00000028 Zero RW 720 .bss FreeRTOS_Sockets.o
0x000104fc 0x00000014 Zero RW 803 .bss FreeRTOS_TCP_WIN.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 heap_4.o
0x0002500c 0x000005b4 Zero RW 1174 .bss BufferAllocation_2.o
0x000255c0 0x00000054 Zero RW 1268 .bss c_w.l(stdio_streams.o)
0x00025614 0x00000054 Zero RW 1269 .bss c_w.l(stdio_streams.o)
0x00025668 0x00000054 Zero RW 1270 .bss c_w.l(stdio_streams.o)
0x000256bc 0x000000e4 Zero RW 1278 .bss c_w.l(rand.o)
0x000257a0 0x00000060 Zero RW 1557 .bss c_w.l(libspace.o)
0x00025800 0x00020000 Zero RW 451 HEAP startup_CMSDK_CM3.o
0x00045800 0x00002000 Zero RW 450 STACK startup_CMSDK_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.

heinbali01 wrote on Wednesday, January 18, 2017:

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).

orifai01 wrote on Wednesday, January 18, 2017:

Yes I know :slight_smile: 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!

heinbali01 wrote on Thursday, January 19, 2017:

Yes I know :slight_smile:

Sorry, sometimes it’s difficult to estimate what knowledge is present already.

0x00025800 0x00020000 Zero RW 451 HEAP startup_CMSDK_CM3.o
0x00045800 0x00002000 Zero RW 450 STACK startup_CMSDK_CM3.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 startup_CMSDK_CM3” 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 BufferAllocation_1.c or BufferAllocation_2.c?
In case you use BufferAllocation_1.c, what does your vNetworkInterfaceAllocateRAMToBuffers() look like?
Note that BufferAllocation_1.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.

orifai01 wrote on Thursday, January 19, 2017:

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