cancel
Showing results for 
Search instead for 
Did you mean: 

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

Javier1
Principal

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:

we dont need to firmware by ourselves, lets talk
1 ACCEPTED SOLUTION

Accepted Solutions

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

View solution in original post

17 REPLIES 17
Javier1
Principal

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 */
}

we dont need to firmware by ourselves, lets talk
Javier1
Principal

.

we dont need to firmware by ourselves, lets talk

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
Up vote any posts that you find helpful, it shows what's working..
Piranha
Chief II

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

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

we dont need to firmware by ourselves, lets talk

>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

we dont need to firmware by ourselves, lets talk

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

0693W00000Np2gIQAR.png 

we dont need to firmware by ourselves, lets talk

In order:

  • Softpwm from GPIOA (yellow)
  • Softpwm from GPIOB (green)
  • Softpwm from GPIOC (purple)
  • bad Softpwm from GPIOD (blue)

they were all supposed to be 7,5Khz 50% softpwms

Without optimization i get a lazy 5,6Khz 50% in the GPIOD0693W00000Np31kQAB.gifWith optimization i get an even lazier 3~4Khz 50% in the GPIOD

0693W00000Np31zQAB.gif

we dont need to firmware by ourselves, lets talk

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

JW