cancel
Showing results for 
Search instead for 
Did you mean: 

H723..H735: functions in ITCM, strange behaviour

LCE
Principal II

Heyho,

I recently found that I'm not using ITCM RAM at all, then started to put heap and stack there.

No problems so far.

Then I copied some functions there, and all went well - until I found some strange behaviour:

  • 1..4 SAI RX DMA transfers running, circular mode
  • when all these transfers are complete for each SAI, a function is called to copy the complete DMA buffer from internal AXI SRAM into the big buffer in HyperRAM
  • also in this function a packet counter (a global u32 in DTCM) is incremented once
  • but when this function is in ITCM, this packet counter increments for each SAI active, but there are no extra packets

 

Further info:

- instruction cache: in use

- data cache: not used

 

Is there any guideline what to put in ITCM, what are the limits, etcpp. ?

1 ACCEPTED SOLUTION

Accepted Solutions
FBL
ST Employee

Hi  @LCE 

Few checks that might help narrow it down:

  • Is it invoked in the SAI/DMA transfer complete callback for each SAI? Are you perhaps using the same callback for multiple SAI/DMA handles, so the counter is effectively updated once per active SAI rather than once per packet?
  • With the function executing faster in ITCM, another SAI/DMA interrupt might enter it again before it returns. You could add a simple volatile flag and a breakpoint (or maybe GPIO toggle) inside the function to detect whether it is being re-entered.

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.




Best regards,
FBL

View solution in original post

5 REPLIES 5
LCE
Principal II

... and yes, I checked AN4891, but that's more about benchmarks.

Not really clear about any requirements, but it looks like a function in ITCM doesn't have any restrictions about variable locations.

TDK
Super User

There are no restrictions with putting code into ITCM. It will run faster which can expose some bugs in the code, much the same as switching between Debug and Release can do.

Variables can't live in ITCM since it is dedicated for instructions. They are never put there in a normal workflow, you would have to be explicitly mixing code and data in the same section.

If you feel a post has answered your question, please click "Accept as Solution".
LCE
Principal II

It will run faster which can expose some bugs in the code,
> much the same as switching between Debug and Release can do.

 

This is something I actually like very much about Release / Debug / Optimization On/Off.

But in this case it's so crazy simple - but maybe there's something I just don't see. I'll go check once more...

FBL
ST Employee

Hi  @LCE 

Few checks that might help narrow it down:

  • Is it invoked in the SAI/DMA transfer complete callback for each SAI? Are you perhaps using the same callback for multiple SAI/DMA handles, so the counter is effectively updated once per active SAI rather than once per packet?
  • With the function executing faster in ITCM, another SAI/DMA interrupt might enter it again before it returns. You could add a simple volatile flag and a breakpoint (or maybe GPIO toggle) inside the function to detect whether it is being re-entered.

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.




Best regards,
FBL
LCE
Principal II

@FBL thanks, yes, there was a multiple DMA interrupt race condition.

I already used __disable_irq(); to prevent this, but in the callback it was "too late", as there's done too much in the HAL interrupt handler (which for DMA is one of the better / faster HAL interrupt handlers, which I usually avoid using).

Still need to have another look at it...

This way it works:

/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
/* SAI DMA interrupt handlers
 * 	the global HAL_DMA_IRQHandler()
 *		- resets all flags
 *		- calls the half- / complete callback functions
 */

/* SAI 1 A as ADC */
void DMA1_Stream0_IRQHandler(void)
{
	__disable_irq();
	HAL_DMA_IRQHandler(&hDMA_Sai_1_A);
	__enable_irq();
}

/* SAI 1 B as ADC */
void DMA1_Stream1_IRQHandler(void)
{
	__disable_irq();
	HAL_DMA_IRQHandler(&hDMA_Sai_1_B);
	__enable_irq();
}

/* SAI 4 A as ADC */
void BDMA_Channel0_IRQHandler(void)
{
	__disable_irq();
	HAL_DMA_IRQHandler(&hDMA_Sai_4_A);
	__enable_irq();
}

/* SAI 4 B as ADC */
void BDMA_Channel1_IRQHandler(void)
{
	__disable_irq();
	HAL_DMA_IRQHandler(&hDMA_Sai_4_B);
	__enable_irq();
}