2024-03-21 05:41 AM - edited 2024-03-21 06:34 AM
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();
}
Solved! Go to Solution.
2024-03-21 09:48 AM
> 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.