Changing clock frequency on STM32 without impacting peripherals? - arm

I'm a bit lost with STM32L486 clock management.
I want to change the clock frequency at run-time. Typically I want to be in Low-Power Run/Sleep mode most of the time, and at full frequency the rest of the time.
I know how to set up SysClk either at 80MHz using PLL or at 1MHz using MSI for example.
However the problem is that changing Sysclk is messing up most peripherals setup. For example the USART is not working anymore if I change the clock.
Is it a common practice to do that ( changing the frequency at runtime ) ?
The peripherals I need to use are: LPTIM ( no problem since they can be clocked independantly from SysClk ), ADC, AES accelerator, USART, TIM, SPI.

On STM32L4xx it is not so hard, if you look on "Clock tree" figure in datasheet, many peripherals which are clock dependent (USART, LPTIM, I2C, ..) can be driven with other clock sources than BUS clock, there is also possible to use LSE or internal HSI.
Although internal HSI is not crystal controlled is from my experience enough accurate for UART, also in bigger range of temperatures, but you can tune frequency of this oscillator by comparing its frequency with an external and more accurate clock during runtime, or use auto-buadrate detection.

Related

interrupt every x seconds EFM32G (C)

I working with EFM microcontroller (Silicon Labs)
I need to make a beep every x seconds, when the device in EM3 mode.
I tried so many ways without success.
Please try to help me with code example (I'm HW man, not a SW haha)
Thanks,
Gal.
Refer to page 8 on the datasheet (thanks to #user694733)
EM3 mode description:
still full CPU and RAM retention, as well as Power-on Reset, Pin reset and Brown-out Detection, with a consumption of only 0.6 μA. The low-power ACMP, asynchronous external interrupt, PCNT, and I2C can wake-up the device.
So these are your options. One of these things can wake up the microcontroller. All of them are external inputs. So the microcontroller cannot wake itself up in this mode. This makes sense because all clocks are stopped.
If you had an outside clock connected to the PCNT you could use that to wake it up.
If you want the microcontroller to wake itself up, then you need EM2 mode or less:
In EM2 the high frequency oscillator is turned off, but with the 32.768 kHz
oscillator running, selected low energy peripherals (LCD, RTC, LETIMER,
PCNT, LEUART, I2C, WDOG and ACMP) are still available
In EM2 mode the microcontroller may wake itself up using the RTC (real-time clock), LETIMER (low-energy timer), WDOG (watchdog timer) or PCNT (pulse counter, which can be set to count pulses of the 32.768kHz clock).
The datasheet recommends using the Real-Time Clock or Low Energy Timer (RTC or LETIMER) modules.
... however, if we pay attention, we see the datasheet mentions something called the ULFRCO, Ultra-Low-Frequency RC Oscillator, which runs at approximately 1000 Hz. By searching for the keyword ULFRCO, we see that it does still run in EM3 mode, and it can be used as input for the WDOG. On page 89 we see this listed as a feature of EM3 mode.
So, you may configure the WDOG to reset the system after a few seconds. When the microcontroller resets due to watchdog timeout, it wakes up. You should not be afraid of using a system reset. The RMU_RSTCAUSE allows you to see that the system was reset because of the watchdog timer (not because it was first turned on or the reset pin was used). Memory contents are probably still there, but all peripherals are reset. As long as you can deal with peripherals being reset, you can probably make this work. You might even be able to use a little bit of assembly programming to jump back to exactly the point where the program left off.

stm32f446 When using dma to control PWM duty cycle, the PWM wave has abnormal waveform

MCU: f446rct6
System: freertos
Library: hal
Program logic:
Initialize the timer to output the PWM wave and initialize the DMA and connect to the Capture/Compare register
Start the timer
When data needs to be updated, start a dma transmission
Phenomenon: There is no problem with the frequency and duty cycle of the PWM wave, but a strange triangular waveform often appears in the first or second waveform of DMA transmission.
Ask everyone, do you encounter similar waveforms when using pwm? Please give me a hint to locate this problem, thank you
Potential causes include:
You're switching the pin to DAC mode (if your MCU has a DAC) and driving it with an increasing value.
The pin is disabled, and what you see is the drift of the voltage on the pin's and probe's combined capacitance.
You're inadvertently switching the PWM to a very high frequency and the scope is set to too low sample rate. Make sure you set the scope to highest possible sample rate / sample depth / sampling length, and decrease the horizontal scale (i.e. decrease the time per division by 2x or 5x).

STM32 Difference between Max interface clock and max timer clock

I am using TIM1 on a H743ZI with 3 PWM channels.
I am trying to maximize the PWM resolution so I need to maximize the clock speed on TIM1.
the datasheet (screenshot below) gives 120MHz and 240MHz values for Max interface clock and Max timer clock.
What is the difference between the 2? I have the clocks setup as shown below, with 120MHz on APB2's peripheral clocks and 240MHz on APB2's Timer clocks.
I need a 24KHz frequency on the PWM channels so I set the ARR to 4999 which confirms the H743 is using the 120MHz value (and not the 240MHz one).
Is it because the I am using the timer in a hardware related manner - hence the "peripheral clock"?
of course, my follow up question, would be whether or not I could use the HRTIM instead?
Every timer consists of the counter which is fed by the timer clock and the control unit which is responsible for interfacing with the bus (core and another peripherals) which is fed by the interface clock.
More general all peripherals have a digital control part. This part is fed by the bus clock (the bus the particular peripheral is connected to). Many peripherals have more than one clock - for example ADC where the digital controller form the bus clock, and the analogue part fed from another clock source.

Timer supply to CPU in QEMU

I am trying to emulate the clock control for STM32 machine with CPU cortex m4. It is provided in the STM32 reference manual the clock supplied to the core is by the HCLK.
The RCC feeds the external clock of the Cortex System Timer (SysTick) with the AHB clock (HCLK) divided by 8. The SysTick can work either with this clock or with the Cortex clock (HCLK), configurable in the SysTick control and status register.
Now Cortex m4 is already emulated by QEMU and I am using the same for STM32 emulation. My confusion is should i supply the clock frequency of "HCLK" I have developed for STM32 to send clock pulses to cortex m4 or cortex -m4 itself manages to have its own clock with HCLK clock frequency 168MHz? or the clock frequency is different ?
If I have to pass this frequency to cortex m4, how do i do that?
QEMU's emulation does not generally try to emulate actual clock lines which send pulses at megahertz rates (this would be incredibly inefficient). Instead when the guest programs a timer device the model of the timer device sets up an internal QEMU timer to fire after the appropriate duration (and the handler for that then raises the interrupt line or does whatever is necessary for emulating the hardware behaviour). The duration is calculated from the values the guest has written to the device registers together with a value for what the clock frequency should be.
QEMU doesn't have any infrastructure for handling things like programmable clock dividers or a "clock tree" that routes clock signals around the SoC (one could be added, but nobody has got around to it yet). Instead timer devices are usually either written with a hard-coded frequency, or may be written to have a QOM property that allows the frequency to be set by the board or SoC model code that creates them.
In particular for the SysTick device in the Cortex-M models the current implementation will program the QEMU timer it uses with durations corresponding to a frequency of:
1MHz, if the guest has set the CLKSOURCE bit to 1 (processor clock)
something which the board model has configured via the 'system_clock_scale' global variable (eg 25MHz for the mps2 boards), if the guest has set CLKSOURCE to 0 (external reference clock)
(The system_clock_scale global should be set to NANOSECONDS_PER_SECOND / clk_frq_in_hz.)
The 1MHz is just a silly hardcoded value that nobody has yet bothered to improve upon, because we haven't run into guest code that cares yet. The system_clock_scale global is clunky but works.
None of this affects the speed of the emulated QEMU CPU (ie how many instructions it executes in a given time period). By default QEMU CPUs will run "as fast as possible". You can use the -icount option to specify that you want the CPU to run at a particular rate relative to real time, which sort of implicitly sets the 'cpu frequency', but this will only sort of roughly set an average -- some instructions will run much faster than others, in a not very predictable way. In general QEMU's philosophy is "run guest code as fast as we can", and we don't make any attempt at anything approaching cycle-accurate or otherwise tightly timed emulation.
Update as of 2020: QEMU now has some API and infrastructure for modelling clock trees, which is documented in docs/devel/clocks.rst in the source tree. This is basically a formalized version of the concepts described above, to make it easier for one device to tell another "my clock rate is 20MHz now" without hacks like the "system_clock_scale" global variable or ad-hoc QOM properties.
Systick is supplied via multiplexer and you can choose the AHB bus clock or divided by 8 system timer clock
An old thread and an oft asked question so this should help some of you trying to emulate cortex systems.
If using a .dtb when booting then in your .dts one can add to the 'timers' block a line of clock-frequency = <value>; and recompile it. This will indeed increase the speed of cortex processors. Clearly, value is some large number.

Generate/ output clock pulse ( C code )

Im using Ethernut 2.1 B and I need a C program that outputs a clock signal at the timer 1 output B, with other words on output OCIB. The frequency of the clock signal should be at 1.0 kHz.
Anyone know how this could be done?
You need to look in COM bits for your timer. For instance, for Timer0 (8-bit), the COM bits are set in the TCCR0 register. Probably the setting you'd be interested in is
TCCR0 |= (0<<COM1)|1<<COM0); // Toggle OC0 on compare match
This will toggle the OC0 (pin14) line when timer reaches the specified value.
Which timer you use depends on the precision you need: obviosely the 16-bit timers can give you more precise time resolution then the 8-bit timers.
The setting of the registers for your specific frequency (1Khz) depends on the clock speed of your chip, and which timer you are using: the timers use a pre-scaled general clock signal (see table 56 of the datasheet for possible values). This means that the prescaler settings will depend on your clock speed, and how high you want to count. For most precision you will want to count as high as possible, which means the lowest possible prescaler setting compatible with your timer's maximum value.
As far as where to start, generally, reading the datasheet is a good place, but googling "AVR timer" can also be very helpful.
It seems to be based on the Atmel ATmega 128, so read that CPU's data sheet to figure out how to program the timer hardware.
Not sure if this microcontroller supports directly driving an output from a timer, if it doesn't you're going to have to do it in software from the interrupt service routine.

Resources