cancel
Showing results for 
Search instead for 
Did you mean: 

STM32G431 - Interrupt fires twice, when optimization -O2 is used. How can i find the point of error

Tobe
Senior III

Through an error, i found out, that the interrupt (FDCAN line 0) fires twice, when only one is activated. (See topic https://community.st.com/t5/stm32cubeide-mcus/compiler-optimized-program-has-errors/m-p/652965#M25387).

How can i now find the actual cause. My head is already spinning form all the investigation so far.

 

Update: trimmed the code:

Only the initializations are executed.

HAL_StatusTypeDef TK_FDCAN_GetRx0Message(
		FDCAN_HandleTypeDef *hfdcan,
		struct can_frame *cFrame)
{
	uint32_t *RxAddress;
	uint32_t GetIndex;

	// If no messages
	if ((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0FL) == 0U)
		return HAL_TIMEOUT;

	/* Calculate Rx FIFO 0 element address */
	GetIndex = ((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0GI) >> FDCAN_RXF0S_F0GI_Pos);
	RxAddress = (uint32_t *)(hfdcan->msgRam.RxFIFO0SA + (GetIndex * SRAMCAN_RF0_SIZE));

	/* Retrieve Identifier */
	cFrame->id = ((*RxAddress & FDCAN_ELEMENT_MASK_STDID) >> 18U);

	//    /* Retrieve ErrorStateIndicator */
	//    pRxHeader->ErrorStateIndicator = (*RxAddress & FDCAN_ELEMENT_MASK_ESI);

	/* Increment RxAddress pointer to second word of Rx FIFO element */
	RxAddress++;

// USE EXTERNALLY!
//	/* Retrieve RxTimestamp */
//	cFrame->timeMicros = micros();

	/* Retrieve DataLength - Yes its weird (bitshift)! Just ignore it!*/
	cFrame->count = (*RxAddress & FDCAN_ELEMENT_MASK_DLC) >> 16U;

	/* Increment RxAddress pointer to payload of Rx FIFO element */
	RxAddress++;

	/* Retrieve Rx payload */
	uint8_t  *pData = (uint8_t *)RxAddress;
	for (uint32_t ByteCounter = 0; ByteCounter < cFrame->count; ByteCounter++)
	{
		cFrame->data[ByteCounter] = pData[ByteCounter];
	}

	/* Acknowledge the Rx FIFO 0 that the oldest element is read so that it increments the GetIndex */
	hfdcan->Instance->RXF0A = GetIndex;

	return HAL_OK;
}
FDCAN_RX_FIFO0_MASK (FDCAN_IR_RF0L | FDCAN_IR_RF0F | FDCAN_IR_RF0N)

void clearFIFO0(FDCAN_HandleTypeDef *hfdcan){
	uint32_t RxFifo0ITs;
	RxFifo0ITs  = hfdcan->Instance->IR & FDCAN_RX_FIFO0_MASK;
	//RxFifo0ITs &= hfdcan->Instance->IE;
	__HAL_FDCAN_CLEAR_FLAG(hfdcan, RxFifo0ITs);
}


void TK_FDCAN1_IT0_IRQHandler(void)
{
	newMessageIRQ();
	clearFIFO0(&hfdcan1);	// clear interrupt flag
}

void FDCAN1_IT0_IRQHandler(void)
{
	TK_FDCAN1_IT0_IRQHandler();
}
10 REPLIES 10
Pavel A.
Evangelist III

 to prevent false interrupts, i find it ugly to qualify those.

This is a good point. Robust interrupt handlers should detect "false" interrupts, because they can occur on certain hardware conditions. Serious operating systems do this on behalf of user drivers, when the hardware/bus architecture allows. The modest charm of bare metal is that you do absolutely everything yourself, down to a single CPU instruction.