Null pointer dereference causes hardfault

I am new to freeRTOS, I am trying to notify a task from an ISR using freeRTOS xTaskNotifyFromISR() API, the code works fine, but after some time when this function is called and control reaches to below function it, at line pxList->uxNumberOfItems causes hardFault/BusFault because pxList is null. I am wondering what can make pxList null. I am using coperative scheduling and trying to run task using xTaskDelayUntil and taskYIELD APIs. Can any one help me to trace the issue and fix?

 UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) { /* The list item knows which list it is in. Obtain the list from the list

item. */ List_t * const pxList = pxItemToRemove->pxContainer;

pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious; pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;

/* Only used during decision coverage testing. */ mtCOVERAGE_TEST_DELAY();

/* Make sure the index is left pointing to a valid item. */ if( pxList->pxIndex == pxItemToRemove ) { pxList->pxIndex = pxItemToRemove->pxPrevious; } else { mtCOVERAGE_TEST_MARKER(); }

pxItemToRemove->pxContainer = NULL; ( pxList->uxNumberOfItems )--;

return pxList->uxNumberOfItems; }

My ISR is :-

static void data_eDMADataTransferCompleteCalBk(LPSPI_Type *base, lpspi_slave_edma_handle_t *handle, status_t status, void *userData)
{
	BaseType_t lu32_taskWoken = pdFALSE;
	st_data_bufferInfo2_t **stp_transfer = (st_data_bufferInfo2_t  **)userData;
	st_data_bufferInfo2_t **stp_receiver = stp_transfer + ONE;
	static volatile uint8_t i;
	i = 5;
	/*clear tx fifo*/

	if(NULL != *stp_transfer)
	{
		(*stp_transfer)->mst_frame.mst_cmd.mu16_dummyBytes    = ZERO;
		(*stp_transfer)->mst_frame.mst_cmd.mu16_dataLen       = ZERO;
		(*stp_transfer)->mu16_frameReadyBytes                 = ZERO;
		++u8_CurrSeqCount;
		*stp_transfer = NULL;
		if(!u8_CurrSeqCount)
		{
			u8_CurrSeqCount = ONE;
		}
		else
		{
			/*do nothing*/
		}
	}
	else
	{
		/*do nothing*/
	}

	if(NULL != *stp_receiver && (st_rxBufferHandle.mstp_bufferInfo  == *stp_receiver))
	{

		if(ZERO < (*stp_receiver)->mst_frame.mst_cmd.mu16_dataLen)
		{
			st_rxBufferHandle.mstp_pendingBufferInfo  = (*stp_receiver); /*update received data buffer*/
			(*stp_receiver)                           = NULL;

			if(U8_RX_BUF_COUNT > ++st_rxBufferHandle.mu8_bufferCount)
			{
				st_rxBufferHandle.mstp_bufferInfo = st_rxBufferHandle.mstp_bufferInfoBase + st_rxBufferHandle.mu8_bufferCount;
			}
			else
			{
				st_rxBufferHandle.mstp_bufferInfo = NULL;
			}
			vu8_notifyFlagSet = ONE;
#if 1
			if(NULL != stp_dataParseTaskHandle)
			{

				do{
					if(pdPASS == xTaskNotifyFromISR(stp_dataParseTaskHandle, U32_PARSER_TASK_NOTIFICATION_VALUE, eSetValueWithOverwrite, NULL))
					{
						//portYIELD_FROM_ISR(lu32_taskWoken);
						break;
					}
					else
					{

					}
				}while(i--);
			}
			else
			{
				/*do nothing*/
			}
#endif
		}
		else
		{

		}

	}
	else
	{
		/*do nothing*/
	}

#if defined(USE_PTB0_INTERRUPT) && (0 != USE_PTB0_INTERRUPT)
	//GPIO_SetPinInterruptConfig(GPIOB, LPSPI_SLAVE_PCS_PIN,  kGPIO_InterruptRisingEdge);
	GPIO_SetPinInterruptConfig(GPIOB, LPSPI_SLAVE_PCS_PIN,  kGPIO_InterruptLogicOne);
#endif
}

First question is did you define configASSERT and enabled stack checking ?
See FreeRTOS - stacks and stack overflow checking
It seems that there is an internal data corruption almost always caused by a stack overflow.
If you do not delete the task to be notified while having the interrupt enabled, of course :wink:
Could you also show the code of the task creation and the task code ?
Which MCU is it and which FreeRTOS version do you use ?
See also xTaskNotifyFromISR() Real Time Operating System API documentation for the correct usage of pxHigherPriorityTaskWoken resp. lu32_taskWoken.

The other very possible cause of the corruption is interrupt priorities set wrong (or not set) which would be caught with configASSERT.

One thing to note, your “ISR” isn’t actually an ISR, the routine directly triggered by the interrupt, but part of a callback for some library provided ISR. Depending on the processor, this can make some thing harder to do depending on the rules for that processors portYIELD_FROM_ISR usage.