SPWM Driver Application

Description

The SPWM driver application provides a configurable PWM framework for generating precise and advanced pulse-width modulated waveforms. It supports multiple PWM operating modes such as Normal PWM, PWM with Dead-Time (PWM_DT), and Pseudo-Random PWM (PWM_PR). The driver enables accurate control of frequency, duty cycle, dead-time, trigger routing, interrupt generation, and descriptor-based burst operation.

The SPWM driver is intended for motor control, power electronics, and timing-critical embedded applications. It supports both continuous operation and descriptor-controlled burst generation, allowing waveform execution with minimal CPU intervention.

Prerequisites

Building and Flashing the Example using VS Code

Use the VS Code flow described in the SL2610 guides and VS Code Extension guide:

Build (VS Code):

  1. Open Build and Deploy -> Build Configurations.

  2. Select cm52_spwm_sample_app_rdk in the Application dropdown.

  3. Build with Build (SDK + App) for the first build, or Build App for rebuilds.

Build Configurations

Flash/Image Generation (VS Code):

Note: On Windows, use WSL for SL2610 image generation.

  1. Build the SL2610 bootloader image.

  2. Open SL2610 Image Generation, select the generated application ELF, and click Run.

    • This is equivalent to make imagegen and directly generates the system sub-image.

  3. Flash/download the MCU image to target.


Building and Flashing the Example using CLI

Use the CLI flow described in the SL2610 Platform Guide:

Build (CLI):

  1. Configure SPWM mode selection in spwm_sample_app.h before building:

    #define SPWM_TIMER_MODE                     0
    #define SPWM_CAPTURE_MODE                   0
    #define SPWM_PWM_MODE                       0
    #define SPWM_PWM_DEADTIME_MODE              0
    #define SPWM_PWM_PSEUDO_RANDOM_MODE         0
    #define SPWM_PWM_MODE_DESC                  0
    
    /* DESCRIPTOR MODE CONFIGURATION */
    #if SPWM_PWM_MODE_DESC
       /* Demo selection - set ONE to 1, rest to 0 */
       #define SPWM_DEMO_440_480KHZ            0
       #define SPWM_DEMO_800_840KHZ            0
       #define SPWM_DEMO_100_400KHZ            0
       #define SPWM_DEMO_200_800KHZ            0
    #endif
    

    Note: Enable only one mode at a time.

  2. Build the SL2610 bootloader from SDK root:

    make sl2610_bootloader_rdk_defconfig BOARD=SL2610_RDK
    make
    
  3. Build SPWM sample app from <sdk-root>/examples:

    cd <sdk-root>/examples
    export SRSDK_DIR=<sdk-root>
    make cm52_spwm_sample_app_rdk_defconfig BOARD=SL2610_RDK BUILD=SRSDK
    

Image Generation and Flash (CLI):

Note: On Windows, use WSL for SL2610 image generation. In WSL, ensure required tools are installed: Python, make, and Arm GNU toolchain. You can use the VS Code extension’s Tools Installer in WSL, or follow Linux Environment guide for CLI setup.

  1. Build the SL2610 bootloader image.

  2. Generate the system sub-image:

    cd <sdk-root>/examples
    export SRSDK_DIR=<sdk-root>
    make imagegen
    
  3. Flash/download image to target.


Running the Application using VS Code Extension

  1. Power the board and press RESET after flashing.

  2. For logging output, connect UART to the target and open a serial console (for example, MobaXterm).

  3. For PWM waveform observation, connect a logic analyzer to the required pins.

Setup

Sample applications logs and output

  1. Timer Application

    • Console logs.

    0000000000:[0][INF]β–’β–’0β–’J:SPWM Timer Mode Starts (group 0)
    0000000005:[0][INF]β–’β–’0β–’J:CLKDIV[0] Setup: int_div=1 frac_div=0
    0000000011:[0][INF]β–’β–’0β–’J:INTERRUPT Setup: group=0 intr=1
    0000000016:[0][INF]β–’β–’0β–’J:[ISR] Callback triggered!
    0000000016:[0][INF]β–’β–’0β–’J:[ISR] Group 0: CC0 match
    0000000016:[0][INF]β–’β–’0β–’J:[ISR] Group 0: CC0 match
    0000000022:[0][INF]β–’β–’0β–’J:CC0 interrupt received, counter=3034
    0000000028:[0][INF]β–’β–’0β–’J:SPWM-Timer Sample App Completed (group 0)!
    
  2. Timer + Capture Application

    • Console logs.

    0000000000:[0][INF]β–’β–’0β–’K:SPWM Timer + Capture App Starts
    0000000005:[0][INF]β–’β–’0β–’K:CLKDIV[0] Setup: int_div=1 frac_div=0
    0000000011:[0][INF]β–’β–’0β–’K:INTERRUPT Setup: group=0 intr=1
    0000000016:[0][INF]β–’β–’0β–’J:[ISR] Callback triggered!
    0000000016:[0][INF]β–’β–’0β–’K:[ISR] Group 0: CC0 match
    0000000022:[0][INF]β–’β–’0β–’K:Capture results: CC0=1108 CC1=1108
    0000000027:[0][INF]β–’β–’0β–’K:Capture successful
    0000000031:[0][INF]β–’β–’0β–’K:SPWM TIMER + CAPTURE Sample App Completed!
    
  3. PWM Sample Application

    • Console logs.

    0000000000:[0][INF]β–’β–’0β–’G:SPWM PWM-Demo Starts
    0000000004:[0][INF]β–’β–’0β–’G:CLKDIV[0] Setup: int_div=1 frac_div=0
    0000000010:[0][INF]β–’β–’0β–’G:SPWM Group 0 Enabled
    0000000014:[0][INF]β–’β–’0β–’G:PWM started: Period=5000 CC0=1000
    0000000020:[0][INF]β–’β–’0β–’G:Duty = 20.0%
    0000000023:[0][INF]β–’β–’0β–’G:PWM Sample App Completed Successfully!
    

    PWM Output

  4. PWM with Deadtime Application

    • Console logs.

    0000000000:[0][INF]β–’β–’0β–’G:PWM-DT App Starts
    0000000003:[0][INF]β–’β–’0β–’G:CLKDIV[0] Setup: int_div=1 frac_div=0
    0000000010:[0][INF]β–’β–’0β–’G:PWM-Deadtime Sample App Completed!
    

    PWMDT Output

  5. PWM Pseudo Random Application

    • Console logs.

    0000000000:[0][INF]β–’β–’0β–’I:SPWM PWM Pseudo Random Mode Test Starts
    0000000005:[0][INF]β–’β–’0β–’I:CLKDIV[0] Setup: int_div=1 frac_div=0
    0000000012:[0][INF]β–’β–’0β–’I:INTERRUPT Setup: group=0 intr=1
    0000000017:[0][INF]β–’β–’0β–’I:PWM Pseudo Random Mode Sample App Completed!
    

    PWMPR Output

  6. PWM Ramp signal with descriptors Application

    • Console logs.

    0000000000:[0][INF]β–’β–’0β–’R:  Step 0: Period=999 CC0=200 Cycles=1 (f=100000 Hz, duty=20.00%, ~11.2Β΅s)
    0000000008:[0][INF]β–’β–’0β–’R:  Step 1: Period=699 CC0=140 Cycles=1 (f=142857 Hz, duty=20.00%, ~11.2Β΅s)
    0000000017:[0][INF]β–’β–’0β–’R:  Step 2: Period=537 CC0=107 Cycles=2 (f=185874 Hz, duty=19.89%, ~11.2Β΅s)
    0000000026:[0][INF]β–’β–’0β–’R:  Step 3: Period=436 CC0=87 Cycles=2 (f=228833 Hz, duty=19.91%, ~11.2Β΅s)
    0000000035:[0][INF]β–’β–’0β–’R:  Step 4: Period=367 CC0=73 Cycles=3 (f=271739 Hz, duty=19.84%, ~11.2Β΅s)
    0000000044:[0][INF]β–’β–’0β–’R:  Step 5: Period=317 CC0=63 Cycles=3 (f=314465 Hz, duty=19.81%, ~11.2Β΅s)
    0000000053:[0][INF]β–’β–’0β–’R:  Step 6: Period=279 CC0=56 Cycles=4 (f=357143 Hz, duty=20.00%, ~11.2Β΅s)
    0000000062:[0][INF]β–’β–’0β–’R:  Step 7: Period=249 CC0=50 Cycles=4 (f=400000 Hz, duty=20.00%, ~11.2Β΅s)
    0000000071:[0][INF]β–’β–’0β–’R:PWM ramp: 8 steps, 20 total cycles, ~90 Β΅s burst, 58 descriptors
    0000000079:[0][INF]β–’β–’0β–’R:CLKDIV[0] Setup: int_div=1 frac_div=0
    0000000085:[0][INF]β–’β–’0β–’R:Initial config: ACTIVE=[Period=10 CC1=2] BUFFER=[Period=999 CC1=200]
    0000000093:[0][INF]β–’β–’0β–’R:Building descriptor chain for configured burst time
    0000000100:[0][INF]β–’β–’0β–’R:Descriptor chain built with 58 descriptors
    0000000107:[0][INF]β–’β–’0β–’R:Descriptor 0 completed
    0000000108:[0][INF]β–’β–’0β–’R:PWM-Ramp started with the configured frequency and duty cycle
    0000000116:[0][INF]β–’β–’0β–’R:PWM-Ramp using Descriptor completed successfully!
    

    PWM with descriptor Output