2022-05-02 07:52 AM
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.......
I dont know a lot yet about APB /AHB buses but :
The DMA1 should be completelly clogging the buses
Links of interest:
Solved! Go to Solution.
2022-05-04 07:15 AM
> 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.
2022-05-02 07:58 AM
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 */
}
2022-05-02 08:03 AM
.
2022-05-02 09:09 AM
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
2022-05-02 02:12 PM
Get rid of the HAL bloatware, polish the ISR code thoroughly, set optimization to Ofast+LTO and you will have ISRs running much faster.
2022-05-02 11:59 PM
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
2022-05-03 12:09 AM
>Thought the F1 could do 64 MHz from PLL+HSI
It was an unpleasant susprise for me too (question in st community)
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
2022-05-03 01:00 AM
Optimicing for Ofast worsens the situation somehow.... softpwm with least priority goes even slower
2022-05-03 01:33 AM
In order:
they were all supposed to be 7,5Khz 50% softpwms
Without optimization i get a lazy 5,6Khz 50% in the GPIODWith optimization i get an even lazier 3~4Khz 50% in the GPIOD
2022-05-03 07:36 AM
I don't get it. If you change GPIO using DMA, what do you do in the interrupts?
JW