Skip to main content
Javier1
Principal
May 2, 2022
Solved

How to move DMA ISR functions from flash to RAM? (hoping they run faster)

  • May 2, 2022
  • 17 replies
  • 7061 views

Im using a stm32f105RBT6 and i am in need a ton of softpwm pins.

My solution (with the help of @Community member​ ) was to run 4 DMA channels triggered by 4 different timers addressing 4 different GPIO ports (in a circular mode).

This worked like a charm untill now.

Now i cannot use the external XTAL anymore, limiting the main clock down from 72Mhz to 36Mhz, this makes the softPWM of the DMA channel with the least priority to lack behind in frecuency.......

 0693W00000NoyewQAB.png 

I dont know a lot yet about APB /AHB buses but :

The DMA1 should be completelly clogging the buses0693W00000NoyeXQAR.png 

Links of interest:

This topic has been closed for replies.
Best answer by waclawek.jan

> How to know if the buses/DMA are already at its limit.

Decrease the timers period -> DMA rate.

But a few kHz DMA at 36MHz system clock should not be an issue. And it should not depend on optimization level, not the least. This is something else.

Are these 4 timer-triggered circular DMAs transferring from memory to GPIO, and nothing else?

JW

EDIT Oh, it's an 'F1... GPIO is behind an APB... that might be a bottleneck, and if software accesses peripherals on the same APB, it could be software-dependent indeed... and then even the "inverse" dependence makes sense - the better the software, the more APB is loaded and prevents DMA from working properly... so find what is loading the given APB bus in software (e.g. tight polling loops) and try to relieve on them.

17 replies

Javier1
Javier1Author
Principal
May 2, 2022

The DMA initialization functions

HAL_TIM_Base_Start(&htim1);//soft pwm //A
	HAL_DMA_Start(&hdma_tim1_up, (uint32_t)&(softpwmbufferA[0]), (uint32_t)&(GPIOA->BSRR), sizeof(softpwmbufferA)/sizeof(softpwmbufferA[0]));
	__HAL_TIM_ENABLE_DMA(&htim1, TIM_DMA_UPDATE);
 
	HAL_TIM_Base_Start(&htim2);//soft pwm //B
	HAL_DMA_Start(&hdma_tim2_up, (uint32_t)&(softpwmbufferB[0]), (uint32_t)&(GPIOB->BSRR), sizeof(softpwmbufferB)/sizeof(softpwmbufferB[0]));
	__HAL_TIM_ENABLE_DMA(&htim2, TIM_DMA_UPDATE);
 
	HAL_TIM_Base_Start(&htim3);//soft pwm //C
	HAL_DMA_Start(&hdma_tim3_ch4_up, (uint32_t)&(softpwmbufferC[0]), (uint32_t)&(GPIOC->BSRR), sizeof(softpwmbufferC)/sizeof(softpwmbufferC[0]));
	__HAL_TIM_ENABLE_DMA(&htim3, TIM_DMA_UPDATE);
 
	HAL_TIM_Base_Start(&htim4);//soft pwm //D
	HAL_DMA_Start(&hdma_tim4_up, (uint32_t)&(softpwmbufferD[0]), (uint32_t)&(GPIOD->BSRR), sizeof(softpwmbufferD)/sizeof(softpwmbufferD[0]));
	__HAL_TIM_ENABLE_DMA(&htim4, TIM_DMA_UPDATE);

The ISR functions are unchanged as they come from cubeMx

/**
 * @brief This function handles DMA1 channel2 global interrupt.
 */
void DMA1_Channel2_IRQHandler(void)
{
 /* USER CODE BEGIN DMA1_Channel2_IRQn 0 */
 
 /* USER CODE END DMA1_Channel2_IRQn 0 */
 HAL_DMA_IRQHandler(&hdma_tim2_up);
 /* USER CODE BEGIN DMA1_Channel2_IRQn 1 */
 
 /* USER CODE END DMA1_Channel2_IRQn 1 */
}
 
/**
 * @brief This function handles DMA1 channel3 global interrupt.
 */
void DMA1_Channel3_IRQHandler(void)
{
 /* USER CODE BEGIN DMA1_Channel3_IRQn 0 */
 
 /* USER CODE END DMA1_Channel3_IRQn 0 */
 HAL_DMA_IRQHandler(&hdma_tim3_ch4_up);
 /* USER CODE BEGIN DMA1_Channel3_IRQn 1 */
 
 /* USER CODE END DMA1_Channel3_IRQn 1 */
}
 
/**
 * @brief This function handles DMA1 channel5 global interrupt.
 */
void DMA1_Channel5_IRQHandler(void)
{
 /* USER CODE BEGIN DMA1_Channel5_IRQn 0 */
 
 /* USER CODE END DMA1_Channel5_IRQn 0 */
 HAL_DMA_IRQHandler(&hdma_tim1_up);
 /* USER CODE BEGIN DMA1_Channel5_IRQn 1 */
 
 /* USER CODE END DMA1_Channel5_IRQn 1 */
}
 
/**
 * @brief This function handles DMA1 channel7 global interrupt.
 */
void DMA1_Channel7_IRQHandler(void)
{
 /* USER CODE BEGIN DMA1_Channel7_IRQn 0 */
 
 /* USER CODE END DMA1_Channel7_IRQn 0 */
 HAL_DMA_IRQHandler(&hdma_tim4_up);
 /* USER CODE BEGIN DMA1_Channel7_IRQn 1 */
 
 /* USER CODE END DMA1_Channel7_IRQn 1 */
}

hit me up in https://www.linkedin.com/in/javiermuñoz/
Javier1
Javier1Author
Principal
May 2, 2022

.

hit me up in https://www.linkedin.com/in/javiermuñoz/
Tesla DeLorean
Guru
May 2, 2022

Thought the F1 could do 64 MHz from PLL+HSI

The vector table needs to be in RAM, at a 512 byte boundary (typically, depends on vector count). The address of the table is easily reassigned via SCB->VTOR, and the original content simply memcpy()'d to the new home, it's a uint32_t array of addresses for subroutines.

The SCB->VTOR is typically done in SystemInit(), you can carve out space in RAM via the linker script or scatter file. You could put the memcpy() equivalent code in startup.s

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Javier1
Javier1Author
Principal
May 3, 2022

>Thought the F1 could do 64 MHz from PLL+HSI

It was an unpleasant susprise for me too (question in st community)0693W00000Np27IQAR.png0693W00000Np28VQAR.png0693W00000Np27hQAB.png 

No luck changing the PLL parameters manually, it seems to be at its limit at 36Mhz.

>The vector table needs to be in RAM, at a 512 byte boundary (typically, depends on vector count). The address of the table is easily reassigned via SCB->VTOR, and the original content simply memcpy()'d to the new home, it's a uint32_t array of addresses for subroutines.

I did this in the past, i tought reallocating the vector table would only improve ISR serving latency.

I need the code in the ISR to run faster, this is why i tought i need to copy all ISR functions to RAM....

Edit: moving the ISR vector to RAM doesnt improve a bit the performance of the softpwm

hit me up in https://www.linkedin.com/in/javiermuñoz/
Piranha
Principal III
May 2, 2022

Get rid of the HAL bloatware, polish the ISR code thoroughly, set optimization to Ofast+LTO and you will have ISRs running much faster.

Javier1
Javier1Author
Principal
May 3, 2022

I cannot get rid of the entire HAL because i need to meet a realistic deadline, i but i could polish the ISR, lets see how it goes.

>set optimization to Ofast+LTO

I never changed the optimization options, ill have a look

hit me up in https://www.linkedin.com/in/javiermuñoz/
Javier1
Javier1Author
Principal
May 3, 2022

Optimicing for Ofast worsens the situation somehow.... softpwm with least priority goes even slower

0693W00000Np2gIQAR.png 

hit me up in https://www.linkedin.com/in/javiermuñoz/
waclawek.jan
Super User
May 3, 2022

I don't get it. If you change GPIO using DMA, what do you do in the interrupts?

JW

Javier1
Javier1Author
Principal
May 3, 2022

CubeMX code uses both transfer halfdone and transfer done interrupts.

When DMA is set in circular mode.

Dont know why exactly , im still learning

My first guess was DMA clogging any of the internal APB buses not ISR problems.

hit me up in https://www.linkedin.com/in/javiermuñoz/
Piranha
Principal III
May 3, 2022

Jan is asking what your code is doing in DMA interrupt callbacks. If nothing, then why do you have those interrupts at all?

waclawek.jan
Super User
May 3, 2022

What do you do in the interrupt?

Read out and check/post content of TIM and DMA registers.

JW

waclawek.jan
waclawek.janBest answer
Super User
May 4, 2022

> How to know if the buses/DMA are already at its limit.

Decrease the timers period -> DMA rate.

But a few kHz DMA at 36MHz system clock should not be an issue. And it should not depend on optimization level, not the least. This is something else.

Are these 4 timer-triggered circular DMAs transferring from memory to GPIO, and nothing else?

JW

EDIT Oh, it's an 'F1... GPIO is behind an APB... that might be a bottleneck, and if software accesses peripherals on the same APB, it could be software-dependent indeed... and then even the "inverse" dependence makes sense - the better the software, the more APB is loaded and prevents DMA from working properly... so find what is loading the given APB bus in software (e.g. tight polling loops) and try to relieve on them.

Javier1
Javier1Author
Principal
May 4, 2022

>Decrease the timers period -> DMA rate.

I have done that, the problem goes away when timers go down from 1,2Mhz to 1Mhz

>But a few kHz DMA

I just checked... Timers are running at 1,2Mhz to keep up with the resolution needed for the softpwm.

36Mhz/30(ARR)--> 1,2Mhz -->buffers are 160 words long--->softpwm of 7,5Khz

This might be the problem....

>Are these 4 timer-triggered circular DMAs transferring from memory to GPIO, and nothing else?

exactly

> if software accesses peripherals on the same APB,

Software accesses are not relevant, im not using them while testing right now, i am just software-setting the softpwms once and Starting DMAs.

> the better the software, the more APB is loaded and prevents DMA from working properly... so find what is loading the given APB bus in software (e.g. tight polling loops) and try to relieve on them.

Ill check on this anyway.

Edit: i just lowered the requirements of my system , timmers are now down to 900kHz and everything works

hit me up in https://www.linkedin.com/in/javiermuñoz/