Astra MCU SDK Peripheral Driver Library
 
Loading...
Searching...
No Matches

Topics

 Enumerated Types
 Enumerated types for SPWM driver.
 
 Data Structures
 Data structures for the SPWM driver.
 
 Functions
 Functions for the SPWM driver.
 

Detailed Description

The SPWM block is a highly flexible Timer/Counter/PWM subsystem designed to support a wide range of timing, waveform generation, and event-capture use cases. Each SPWM instance contains multiple independent groups, where each group can be configured to operate in Timer, Counter, Capture, PWM, PWM with Dead-Time, PWM with Pseudo-Random modulation, Shift Register, or Quadrature Decoder mode.

The driver provides a unified configuration interface while also exposing low-level hardware features such as trigger routing, interrupt control, semaphores, and descriptor-based command sequencing. This allows both straightforward software-driven operation and advanced hardware-automated control flows with minimal CPU intervention.

Features:

Note
SPWM APIs are divided into two categories:
Warning
SPWM groups operate as tightly coupled hardware state machines. Changing operating mode, clocking, or output configuration while a group is enabled or while a descriptor chain is executing may result in unpredictable output behavior. Software should always disable the affected group using spwm_disable and ensure descriptor execution is complete before reconfiguration. Avoid mixing software-driven register updates with trigger-based or descriptor-based control on the same group.

Configuration Considerations

To initialize and operate the SPWM driver:

  1. Call spwm_init to initialize the SPWM instance and internal driver state.
  2. Configure the required clock divider using spwm_clkdiv_config.
  3. Enable the clock divider using spwm_clkdiv_enable.
  4. Populate a spwm_config_t structure according to the selected operating mode and application requirements.
  5. Apply the configuration to a specific SPWM group using spwm_configure.
  6. Optionally configure trigger inputs using spwm_set_trig_in or spwm_set_trig_in_all.
  7. Optionally configure trigger outputs using spwm_set_trig_out and semaphore routing using spwm_set_sema_sel.
  8. Enable required interrupts using spwm_enable_interrupt or register callbacks using spwm_register_callback.
  9. Enable the SPWM group using spwm_enable to start operation.
  10. Control execution using software triggers (spwm_trigger), hardware triggers, or descriptor-based execution.
  11. Disable the group using spwm_disable before modifying configuration or changing operating mode.

For advanced use cases, descriptor chains can be created and executed using the ::spwm_dsc_chain_* APIs to automate configuration updates, synchronize multiple SPWM groups, and minimize CPU involvement.

spwm_init

Initializes the SPWM hardware block and internal driver state for the selected SPWM instance. This function must be called once before configuring clocks, groups, interrupts, or descriptors.

spwm_status_en rc = spwm_init(SPWM_INST);
if (rc != SPWM_OK) {
LOG_ERROR(LOG_MOD_SPWM, "SPWM init failed.\n");
}

spwm_deinit

Deinitializes the SPWM instance and releases all associated hardware resources. All SPWM groups are disabled and the block is returned to a reset-safe state.

rc = spwm_deinit(SPWM_INST);
if (rc != SPWM_OK) {
LOG_ERROR(LOG_MOD_SPWM, "SPWM deinit failed.\n");
}

spwm_configure_clock

Configures and enables a clock divider for SPWM operation. The divider output can be shared across multiple SPWM groups and determines the base timing resolution for timer, capture, and PWM modes.

if (spwm_clkdiv_enable(SPWM_INST, 0, false, 0) != SPWM_OK) {
LOG_ERROR(LOG_MOD_SPWM, "Clock divider disable failed.\n");
}
if (spwm_clkdiv_config(SPWM_INST, 0, 1, 0) != SPWM_OK) {
LOG_ERROR(LOG_MOD_SPWM, "Clock divider config failed.\n");
}
if (spwm_clkdiv_enable(SPWM_INST, 0, true, 0) != SPWM_OK) {
LOG_ERROR(LOG_MOD_SPWM, "Clock divider enable failed.\n");
}

spwm_set_clkdiv

Selects the clock divider source for a specific SPWM group. Each group can independently select a divider based on its required timing or PWM frequency.

rc = spwm_set_clkdiv(SPWM_INST, SPWM_GRP, 0);
if (rc != SPWM_OK) {
LOG_ERROR(LOG_MOD_SPWM, "Clock divider select failed.\n");
}

spwm_configure

Applies a unified configuration to an SPWM group using spwm_config_t.

This API supports all SPWM operating modes, including:

The configuration programs counter behavior, period and compare values, trigger routing, output control, and all mode-specific parameters in a single atomic operation.

/* Prepare TIMER mode configuration */
memset(&cfg, 0, sizeof(cfg));
cfg.mode = SPWM_MODE_TIMER;
cfg.clkdiv_sel = 0;
cfg.count_mode = SPWM_COUNT_UP;
cfg.prescale = SPWM_PRESCALE_DIV1;
cfg.one_shot = false;
cfg.period = 1000;
cfg.period_buff = 1000;
cfg.cc0 = 500;
cfg.cc0_buff = 500;
cfg.cfg.timer.auto_reload_cc0 = true;
/* Apply configuration */
rc = spwm_configure(SPWM_INST, SPWM_GRP, &cfg);
if (rc != SPWM_OK) {
LOG_ERROR(LOG_MOD_SPWM, "SPWM configure failed.\n");
}

spwm_configure_interrupts

Configures interrupt handling for an SPWM group. This includes registering an instance-level ISR callback, clearing pending interrupt state, and enabling selected interrupt sources such as terminal count, compare match, or capture events.

rc = spwm_register_callback(SPWM_INST, spwm_irq_callback, NULL);
if (rc != SPWM_OK) {
LOG_ERROR(LOG_MOD_SPWM, "Callback register failed.\n");
}
spwm_disable_all_interrupts(SPWM_INST, SPWM_GRP);
spwm_clear_all_interrupts(SPWM_INST, SPWM_GRP);
rc = spwm_enable_interrupt(SPWM_INST, SPWM_GRP, SPWM_INTR_CC0_MATCH);
if (rc != SPWM_OK) {
LOG_ERROR(LOG_MOD_SPWM, "Interrupt enable failed.\n");
}

spwm_enable

Enables an SPWM group and starts hardware operation based on the configured mode. Depending on configuration, this may start a timer, PWM generator, capture engine, or descriptor-controlled sequence.

rc = spwm_enable(SPWM_INST, SPWM_GRP);
if (rc != SPWM_OK) {
LOG_ERROR(LOG_MOD_SPWM, "SPWM enable failed.\n");
}

spwm_disable

Disables an SPWM group and halts all activity. Output signals transition to the configured disable state and counters are stopped.

rc = spwm_disable(SPWM_INST, SPWM_GRP);
if (rc != SPWM_OK) {
LOG_ERROR(LOG_MOD_SPWM, "SPWM disable failed.\n");
}

spwm_descriptor_chaining

Supports descriptor-based command chaining for autonomous SPWM operation.

The SPWM descriptor engine enables hardware-driven sequencing of configuration updates and synchronization events without CPU intervention. Descriptor chains are commonly used for PWM ramping, burst generation, synchronized updates, and deterministic timing control across one or more SPWM groups.

A typical descriptor workflow includes:

uint16_t dmem_handle;
if (pwm_dsc_mem_alloc(2048, &dmem_handle) != PWM_DSC_OK) {
LOG_ERROR(LOG_MOD_SPWM, "Descriptor memory allocation failed.\n");
}
pwm_dsc_chain_t *chain = pwm_dsc_chain_create();
if (!chain) {
LOG_ERROR(LOG_MOD_SPWM, "Descriptor chain create failed.\n");
}
if (pwm_dsc_chain_init_for_handle(SPWM_INST, chain, dmem_handle) != PWM_DSC_OK) {
LOG_ERROR(LOG_MOD_SPWM, "Descriptor chain init failed.\n");
}
uint32_t cfg_vals[2] = {
500, /* CC0_BUFF */
1000 /* PERIOD_BUFF */
};
if (pwm_dsc_chain_add_cfg(chain,
SPWM_GRP,
PWM_DSC_REG_CC0_BUFF,
cfg_vals,
2,
false) != PWM_DSC_OK) {
LOG_ERROR(LOG_MOD_SPWM, "Descriptor CFG add failed.\n");
}
if (pwm_dsc_chain_start(SPWM_INST, chain, 0, true) != PWM_DSC_OK) {
LOG_ERROR(LOG_MOD_SPWM, "Descriptor chain start failed.\n");
}
pwm_dsc_chain_destroy(chain);
pwm_dsc_mem_free(dmem_handle);