Getting started with HRTIM

This article explains what HRTIM is and how to use it through examples.

1. What is an HRTIM ?

HRTIM stands for high-resolution timer. HRTIM is a highly accurate timer that can generate complex waveforms such as PWM, phase-shifted. It is made up of six 16-bit up counter and a controller timer with very highly fine timing resolution (184 ps on the STM32G4 series). They can be used independently or synchronized. HRTIM applications are various: from digital power conversion (digital SMPS, solar converters, motor control) to also for general-purpose applications.

1.1. Counter operating modes

Up-counters can operate in three modes:

  • Continuous (also called Free-running): it rolls over to zero when it exceeds the value programmed in the period register (HRTIM_PERxR)
  • Single shot Retriggerable: It starts with a reset event occurs and stops when it reaches the period value (HRTIM_PERxR). In this mode, the user can reset at any time.
  • Single shot non-retriggerable : The same principle as single shot retriggerable but in this mode, reset events are discarded if they occur before the end of the counting phase.

1.2. Block diagram overview

As we can see on the figure below, the HRTIM have a modular architecture. Let us have a look at each block:

HRTIM Block Diagram.png

  • Block 1 Timing units are six 16-bit upcounter with a programmable overflow, two capture registers and four compare registers. Compare event can be generated when the counter is equal to the compare value (HRTIM_CMP1xR).
  • Block 2 Set/Reset Crossbar allows having the output pairs controlled not only by a related timing unit but by external event and other timers.
  • Block 3 Output stage manage a pair of outputs with any kind of logic (polarity, safe states, asynchronous fault protection...).
  • Block 4 Input block includes 10 external events, five fault signals (protect the power stages and shutdown PWM outputs).
  • Block 5 Interface part link the HRTimer with other timers, DMA, ADC, and DAC with internal STM32 connections.

2. Configure the HRTIM to generate a simple PWM

2.1. Objective

  • In this project, you learn how to set up HRTIM in STM32CubeIDE
  • How to generate code in STM32CubeIDE and use HAL functions
  • Provide a simple application to create a single PWM
  • Configure timer in continuous mode, crossbar, and output stage

2.2. Creating the project in STM32CubeIDE

  • File > New > STM32 Project in a main panel.

create STM32CubeIDE project.png

  • Select the NUCLEO-G474RE board using the Board Selector, as shown in the figure below:

Board Selector G474RE.png

  • Answer Yes to initialize all peripherals with their default mode? Popup as below:

Popup.png

  • If not downloaded previously, the download of the STM32CubeG4 Cube library starts automatically. The download may take some time.
  • Save the project.

Save Project HRTIM PWM.png

2.3. Configure HRTIM

  • In the Pinout & Configuration window, select HRTIM1 and choose TA1 output active.

HRTIM TIMA.png

Info white.png Information
Check the PA8 pin is declared correctly on the Pinout view on the right.
  • In User Constants, click on add and enter this constant name TIMA_DUTY_CYCLE with the value 0.5.

Declare User Constant.png

  • In Timer A, in section Time Base Setting , observe the configuration: up_counting and continuous mode with a resulting PWM Frequency of 83050 Hz (Period = 0xFFDF). Keep the settings.
  • Scroll down until Compare Unit 1, and fill as below :
  1. Enable Compare Unit 1 Configuration
  2. Enter 0xFFDF * TIMA_DUTY_CYCLE in the Compare Value
  3. Keep Timer Compare 1 event is generated when counter is equal

Compare Unit.png

  • Scroll down until Output 1 Configuration and fill as below:
  1. Enter 1 as number of Active Set Source and select Timer period event forces the output to its active state as the first set source
  2. Enter 1 as number of Active Reset Source and select Timer compare 1 event forces the output to its inactive state as the first reset source

Output Configuration.png

2.4. Generate project and edit main.c

  • Click Ctrl+S to generate the project.

Generate project.png

  • Open Project.
  • Edit main.c as the picture below:
Info white.png Information
Insert your code between /* USER CODE BEGIN 2 */ and /* USER CODE END 2 */ tags.
  /* USER CODE BEGIN 2 */
  
  /* Enable HRTIM's outputs TA1 and start Timer A */
  HAL_HRTIM_WaveformOutputStart(&hhrtim1, HRTIM_OUTPUT_TA1);  // Enable the generation of the waveform signal on the designated output
  HAL_HRTIM_WaveformCounterStart(&hhrtim1, HRTIM_TIMERID_TIMER_A);  // Start the counter of the Timer A operating in waveform mode
  
  /* USER CODE END 2 */

2.5. Compile and flash

  • Click on Build button Built.png.
  • Click on Debug button (to run step by step) Debug.png.
  • Or on Run button (to execute) Run.png.

3. Result

If you want to observe the output PWM, you need to check on the CN9 the pin n°8 named D7 with an oscilloscope.

  • For a duty cycle of 0.5, we have the waveform below:

Res PWM 05.png

Info white.png Information
Change the Duty Cycle and observe the PWM.
  • Open and edit main.h.
  • In the private defines section, change the value of TIMA_DUTY_CYCLE such as the picture below.
/* Private defines --------------------------------------*/
#define TIMA_DUTY_CYCLE 0.8
  • For a duty cycle of 0.8, we have the waveform below:

Res PWM 08.png

  • For a duty cycle of 0.1, we have the waveform below:

Res PWM 01.png

4. To go further about DMA burst

Info white.png Information
This section is optional and allows to understand DMA burst .

The DMA burst controller allows:

  • Update multiple registers (such as the CMP1xR to control the duty cycle of the PWM).
  • Reprogram dynamically one or several timing units.

Go back in CubeMX in the HRTIM1 configuration in Timer A / Time Base Setting :

  • Enable the Burst DMA configuration.
  • Enter 1 in the number of register to update.
  • Choose CMP1xR register is updated by Burst DMA accesses as the first register.

Burst DMA.png


Then, go in the DMA settings window, and configure as shown in the picture below:

  • Click on Add.
  • Select HRTIM1_A in DMA request.
  • Uncheck Increment address boxes (for both peripheral and memory).
  • Choose Word for data width (for both peripheral and memory).

DMA Settings.png

The last changes in the DMA settings window created a warning in Timer A / Timing Unit / Number of Timer A Internal DMA request sources. Enter 1 instead of 0 like in the picture below :

Nbr TIM DMA.png

Next, generate the code and edit the main.c a second time. (See generate project and edit main.c.)

Info white.png Information
Insert your code between /* USER CODE BEGIN 2 */ and /* USER CODE END 2 */ tags.
/* USER CODE BEGIN 2 */
  
/* Enable HRTIM outputs TA1 and start Timer A */
HAL_HRTIM_WaveformOutputStart(&hhrtim1, HRTIM_OUTPUT_TA1);  // Enable the generation of the waveform signal on the designated output
HAL_HRTIM_WaveformCounterStart(&hhrtim1, HRTIM_TIMERID_TIMER_A);  // Start the counter of the Timer A operating in waveform mode

static uint32_t Reg_Update [] = 
{
   0xFFA0, 
};
if(HAL_HRTIM_BurstDMATransfer(&hhrtim1, HRTIM_TIMERINDEX_TIMER_A, (uint32_t) Reg_Update, sizeof(Reg_Update)/sizeof(uint32_t)) != HAL_OK) //Add a breakpoint here
{
   Error_Handler();
}

/* USER CODE END 2 */

HAL_HRTIM_BurstDMAConfig(): configures the burst DMA burst controller. It allows having multiple HRTIM registers updated with a single DMA request. The burst DMA operation is started by calling HAL_HRTIM_BurstDMATransfer().

For the last step, go in the function HAL_HRTIM_MspInit() where the HRTIM1 DMA is initialize. Declare the direction to DMA_MEMORY_TO_MEMORY and not DMA_MEMORY_TO_PERIPH.

 hdma_hrtim1_a.Init.Direction = DMA_MEMORY_TO_MEMORY;

"The DMA channels may operate without being triggered by a request from a peripheral. This mode is called memory-to-memory mode, and is initiated by software." (extract from chapter DMA in RM0440)

Info white.png Information
Add the CMP1xR expression and observe the new value on the Live Watch after executing the HAL_HRTIM_BurstDMATransfer call.