Problem with STM32F030C6T6 timing - Page 1
Forum section: electronics / general

author: BorisRap
author_rank: Contributor
timestamp: November 10, 2022, 08:04:48 am
content: Hello, I'm doing a test board using a STM32F030C6T6. I'm just testing functions now and I'm doing some timers. I noticed that the processor doesn't run at the frequency I think it runs.I made a timer (TIM16) with a counter period of 48 - 1. The timer clock frequency is 48MHz so I should get an interrupt every around 1uSec. Inside the interrupt function I just do a toggle in a pin.That should output a 500khz square wave through that pin.I'm measuring with the oscilloscope the following values on the pin:1) 42Khz when the app is debugging2) 84Khz when the app is reset after debug or when its running in release versionHere is the clock configuration in CubeIDEHere is the timer configurationHere is the code:Code:int main(void){/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_I2C1_Init();MX_ADC_Init();MX_TIM16_Init();/* USER CODE BEGIN 2 */HAL_TIM_Base_Start_IT(&htim16);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */}void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){HAL_GPIO_TogglePin(OUT_LLC_EN_GPIO_Port, OUT_LED_Pin);}And here is the schematic:Why its the timing not correct?Thank you very much

author: newbrain
author_rank: Super Contributor
timestamp: November 10, 2022, 08:26:25 am
content: STM32F0 are Cortex-M0, so with an IRQ latency of 16 cycles.At 48 MHz, and 1 MHz IRQ rate only 32 cycles are left for the actual processing.Unfortunately the HAL tries to be a very general library, and ifyou look at the sourceI would say there's no chance for it to be less than 33 cycles.In practice, the IRS (including your callback) will be continuously executed back-to-back, so you are just measuring its duration (1/84 ms), about 540 cycles (AFAIR, Cortex-M0 does not have IRQ tail-chaining, so IRQ latency cost is always paid).One way it could work is to directly override the weakly declared IRQ service routine (TIM16_IRQHandler), and there just clear the IRQ flag in the timer (writing 0 to TIM16->SR should be enough) and toggle the pin, both with direct register writes.Edit: some more details, and correct latency cycles for M0.

author: BorisRap
author_rank: Contributor
timestamp: November 10, 2022, 08:49:18 am
content: Quote from: newbrain on November 10, 2022, 08:26:25 amThank you for your answer, I changed the counter to 48000-1 and I get now the 500Hz when not debugging, so it seems to be the problem you indicate.I could get a pin compatible alternative with better performance.To what family should I target?When I run the software in debug mode with counter 48000 - 1 I only get a frequency of 250Hz. Is it normal not to run at real time when debugging?

author: DavidAlfa
author_rank: Super Contributor
timestamp: November 10, 2022, 09:39:45 am
content: 1MHZ ISR to make a square wave??Just setup a PWM timer and let it generate the output, no ISR or anything required.

author: SiliconWizard
author_rank: Super Contributor
timestamp: November 10, 2022, 09:22:44 pm
content: I don't understand why people keep trying to bit bang very fast changing signals on GPIOs while they have plethora of peripherals just made for that, with exact timings, no CPU involved and no programming trick involved.

author: GromBeestje
author_rank: Frequent Contributor
timestamp: November 10, 2022, 09:59:00 pm
content: Quote from: SiliconWizard on November 10, 2022, 09:22:44 pmIt was the first thing I tried, failed, and then learned about the other possibilities. But when first coming to the STM32, from little 8 bit experience, I only knew about timers and gpio toggles.

author: westfw
author_rank: Super Contributor
timestamp: November 10, 2022, 10:24:55 pm
content: The more complex the processor, the more expensive it gets to use interrupts.There was awhole discussionon why the 120MHz RPi Pico was taking about 15us (1800 cycles!) to respond to pin change interrupts. (TLDR: the code is in QSPI flash, and relies on caches to provide acceptable performance.)

author: BorisRap
author_rank: Contributor
timestamp: November 11, 2022, 08:04:16 am
content: The pins I have to toggle are not connected to the timer PWM outputs. I've researched if I can do it using a PWM timer in "no output" and also with DMA but I don't really know how to do it

author: DavidAlfa
author_rank: Super Contributor
timestamp: November 11, 2022, 08:32:15 am
content: What about SPI? i2s?You're missing a lot of details. OUT_LLC_EN not defined anywhere.

author: BorisRap
author_rank: Contributor
timestamp: November 11, 2022, 09:08:34 am
content: Oh, I just noticed that, I used the wrong port, but it happens to be the same of the LED so is not a big deal.I left some code outside, but it's just variable delclarations

author: ace1903
author_rank: Regular Contributor
timestamp: November 11, 2022, 09:12:07 am
content: Debugger sets system clocks in order to program the flash memory. CubeMX assumes that processor starts from reset.You should check debugger scripts to see how clocks are set. Probably unintentionally you are forcing to forbidden dividers sets.One option is to modify debugger scripts and the other option is to add un-init to system clock generator.That will explain why you are getting exactly 84 vs 42KHz. Checking all dividers is good learning experience.

author: DavidAlfa
author_rank: Super Contributor
timestamp: November 11, 2022, 09:16:58 am
content: You simply lack CPU power for this, and it's not the proper method for that anyway.If you got it running by optimizing the code, it'll use almost 100% of the cpu in the ISR alone.The lower peformance in Debug mode is probably optimization-related.Release use -O2 by default, Debug uses -O0 so it executes much slower.In any case, the problem is it being unable to cope with so many ISRs, you should see how the waveform is irregular because some ISRs are missing or overlapping.DMA is much easier than you think. You don't even need ISR, simply left it running in circular mode!In CubeMX:[Timer 16]- No ISR, no pre/postscaler, period=47- DMA settings, add TIM16_UP:- Circular mode- Priority: high- Memory to peripheral- Peripheral: Untick addr increase, size=word- Memory: Tick addr increase, size=word- Untick "Force dma interrupts"- Untick the dma channel assigned to Timer16 (Or you'll have 2MHz ISR, every 1/2 transfer!).Then:Code:uint32_t led_toggle_bf = { OUT_LED_Pin, OUT_LED_Pin<<16 }; // Set , Resetvoid start_wave(void){HAL_DMA_Start(htim16.hdma, (uint32_t)&led_toggle_bf, (uint32_t)&OUT_LED_GPIO_Port->BSRR, 2);__HAL_TIM_ENABLE_DMA(&htim16, TIM_DMA_UPDATE);__HAL_TIM_ENABLE(&htim16);};After this, you should have a 500KHz wave with zero cpu intervention nor ISRs.

author: BorisRap
author_rank: Contributor
timestamp: November 11, 2022, 10:15:36 am
content: Thank you for your help, I tried just to try to understand how it works. But The 1MHz square wave was just to verify the processor speed.In reality I'm trying to do 2 ~1.2Khz PWM signals with duty from 0 to 255.My process at start was the same, divide the master clock by 1.2khz and then by 255. Then increase a circular counter to 255. Compare every PWM channel with the counter and toggle the pin accordingly.But the problem is the same, just too many interruptions and the output PWM frequency never reaches 1.2Khz. Then I tried using the timer in PWM mode, but the outputs I need are not those connected to the timer PWM outputs.Now with your example I feel like it may be a way to use the timer in PWM mode and use DMA to toggle the pin I require. But I don't completely understand how to link the DMA event to that particular pin.Anyway, I tried your example and I got this error on compiling after adding the code part:Code:11:06:20 **** Incremental Build of configuration Debug for project LLC ****make -j8 allarm-none-eabi-gcc -o "LLC.elf" @"objects.list" -mcpu=cortex-m0 -T"C:\CubeProj\LLC\STM32F030C6TX_FLASH.ld" --specs=nosys.specs -Wl,-Map="LLC.map" -Wl,--gc-sections -static --specs=nano.specs -mfloat-abi=soft -mthumb -Wl,--start-group -lc -lm -Wl,--end-groupc:\st\stm32cubeide_1.2.0\stm32cubeide\plugins\com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.7-2018-q2-update.win32_1.0.0.201904181610\tools\arm-none-eabi\bin\ld.exe: LLC.elf section `.text' will not fit in region `FLASH'c:\st\stm32cubeide_1.2.0\stm32cubeide\plugins\com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.7-2018-q2-update.win32_1.0.0.201904181610\tools\arm-none-eabi\bin\ld.exe: region `FLASH' overflowed by 488 bytescollect2.exe: error: ld returned 1 exit statusmake: *** [makefile:44: LLC.elf] Error 1"make -j8 all" terminated with exit code 2. Build might be incomplete.11:06:20 Build Failed. 1 errors, 0 warnings. (took 881ms)

author: DavidAlfa
author_rank: Super Contributor
timestamp: November 11, 2022, 10:24:26 am
content: Dude, Wtf? Verifying the processor speed by toggling at 1MHZ in a ISR?Just enable MCO, or do like everyone else in the planet, set the timer to generate a 1ms/100m or even 1s output.The error will be proportional in the same way.

author: BorisRap
author_rank: Contributor
timestamp: November 11, 2022, 10:29:43 am
content: Thank you, I'm still learning

author: DavidAlfa
author_rank: Super Contributor
timestamp: November 11, 2022, 01:28:18 pm
content: Sorry for being rude!