2024-03-19 12:01 AM - edited 2024-03-20 01:22 AM
While trying to debug a problem, it seems that another one is giving me a hard time.
One function call is not shown, another has the wrong name ("writeFLASHDoubleWord" should be "waitForBusy").
The breakpoint is also missed.
Originally the code worked, but then i moved to the new prototype. I copied the project, and made a few minor changes. Mainly just the pins.
I had some hardfault before, which happend seemingly at "CLEAR_BIT(FLASH->CR, FLASH_CR_PG);" after writing FLASH. But after seeing the above, i doubt this!
2024-03-20 02:50 PM
I just found out, that the interrupt is fired twice. But i dont know why, it does not when there is no optimization. Placing breakpoints does not work at all!
This is quite a tough one.
2024-03-20 04:09 PM
Maybe this?
JW
2024-03-21 02:05 AM - edited 2024-03-21 02:06 AM
No, there is a lot of code behind that part in the interrupt.
I have another finding: When the TFE flag is set, the interrupt is executed a second time, even tough, the interrupt enable IS NOT enabled. How in the world?
void newMessageIRQ()
{
unsigned long nowMicros = micros();
print(100);
if(dataFlowControl() != 0)
return;
print(hfdcan1.Instance->IE >> 3*8);
print(hfdcan1.Instance->IE >> 2*8);
print(hfdcan1.Instance->IE >> 1*8);
print(hfdcan1.Instance->IE >> 0*8);
print(101);
print((uint8_t) (hfdcan1.Instance->IR >> 3*8));
print((uint8_t) (hfdcan1.Instance->IR >> 2*8));
print((uint8_t) (hfdcan1.Instance->IR >> 1*8));
print((uint8_t) (hfdcan1.Instance->IR >> 0*8));
// TODO low prio: make another version of this, that filters out ids below x beforehand
print(TK_FDCAN_GetRx0Message(&hfdcan1, &inputBuffer[inputWriteIndex]));
print(102);
print((uint8_t) (hfdcan1.Instance->IR >> 3*8));
print((uint8_t) (hfdcan1.Instance->IR >> 2*8));
print((uint8_t) (hfdcan1.Instance->IR >> 1*8));
print((uint8_t) (hfdcan1.Instance->IR >> 0*8));
SET_BIT(hfdcan1.Instance->IR, FDCAN_IR_TFE); // Clear bit
// Bootloader does not use ids below ID_REQUEST and 1764 is from diagnose software (dont use it!)
if(inputBuffer[inputWriteIndex].id < ID_REQUEST || inputBuffer[inputWriteIndex].id == 1764){
print(99);
return;
}
print(103);
// Control data
if(inputBuffer[inputWriteIndex].id < ID_DATA_START)
{
lastControlID = (uint32_t) inputBuffer[inputWriteIndex].id;
lastControlMode = (uint32_t) inputBuffer[inputWriteIndex].data[0];
lastAdditionalData = (uint32_t) inputBuffer[inputWriteIndex].data[3];
}
print(104);
lastBusActivityMicros = nowMicros; //TODO: DELETE VARIABLE (is not used)
inputBuffer[inputWriteIndex].timeMicros= nowMicros;
print(105);
inputFrameCount++;
inputWriteIndex++;
print(106);
delayMicroseconds(150);
if(inputWriteIndex >= INPUT_BUFFER_SIZE){
inputWriteIndex = 0;
inputOverFlow = true;
}
delayMicroseconds(150);
print(inputReadIndex);
print(inputWriteIndex);
print(inputOverFlow);
delayMicroseconds(150);
}
It prints (for the registers (IE, IR, and IR after the FDCAN routin) only - decimal, one digit for each byte):
When TFE is set in IR:
0001 / 0021 / 0021 (*) / 0001 / 0020 / 0020 ( For every CAN frame)
When TFE is cleared in IR (in the interrupt):
0001 / 0021 / 0021 (First CAN frame)
0001 / 0003 / 0003 (Second CAN frame - 3 means new Message; buffer full)
How can this interrupt fire, when it is not enabled?
2024-03-21 02:16 AM
@Tobe wrote:there is a lot of code behind that part in the interrupt.
That's generally a Bad Things - ISRs should generally be kept as short as possible.
Placing breakpoints does not work at all! This is quite a tough one.
Although, if it's timing-related, it's possible (likely?) that breakpoints wouldn't help anyhow.
Tough indeed!
Maybe try toggling some pins to observe on a scope or a logic analyser?
2024-03-21 02:27 AM - edited 2024-03-21 02:35 AM
@Andrew Neil wrote:That's generally a Bad Things - ISRs should generally be kept as short as possible.
I know, but my debugging efforts inflated it.
I just find out, that clearing another flag (that is even not set), seems to prevent a second run of the interrupt. I also verfied, that it is not a timing issue, with writing to another register where the bit was set anyway.
This is getting more and more strange!
2024-03-21 02:35 AM
@Tobe wrote:
I just find out, that clearing ANY flag, seems to prevent a second run of the interrupt.
Good - some progress, at least. :thumbs_up:
Does make it sound like @waclawek.jan could be onto something with his link ...
Do you have an ST or Distributor FAE who could give you more direct help with this?
2024-03-21 02:38 AM
I updated my answer above.
The link? I think no? they is plenty of time after the actual "hardware handling".
I dont think anyone would bother with a guy that hasnt had any training nor is a professional...
2024-03-21 03:15 AM
I have found out, that for clearing interrrupt flags, SET_BIT() would clear all the flags. Another thing that gets you confused/ off track... jeeeez.
Another interesting thing. In my routine, i dont even clear the newMessage flag, but it is cleared, when the second false interrupt fires.
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;
}