cancel
Showing results for 
Search instead for 
Did you mean: 

Compiler optimized program has errors

Tobe
Senior III

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!

37 REPLIES 37

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.

Maybe this?

JW

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?

 


@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?

 


@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!


@Tobe wrote:

I just find out, that clearing ANY flag, seems to prevent a second run of the interrupt.


Good - some progress, at least. 👍

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?

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

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;
}