This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RTOS/TM4C1231H6PGE: [Resolved] TM4C1231H6PGE: PWM interrupt never fires

Part Number: TM4C1231H6PGE

Tool/software: TI-RTOS

I have the same problem using TivaC TI-RTOS 2.16.0.80, XDCtools 3.32.06_core. The solution for the resolved problem does not work as the startup_ccs.c is autogenerated. I expected to be able to register the ISR function by configuring a Hwi:

var m3Hwi0Params = new m3Hwi.Params();
m3Hwi0Params.instance.name = "m3Hwi0";
m3Hwi0Params.priority = 0;    // optional: intended to define a non-BIOS ISR
Program.global.m3Hwi0 = m3Hwi.create(150, "&PWM1_GEN0_ISR", m3Hwi0Params);

 I tried to the registration API without success.

  • Friedrich,

    It isn’t clear to me if this is a vector registration problem, or a problem with getting the interrupt fully enabled to propagate to the CPU (as was the issue on the previous thread).

    Have you looked at the Hwi module state with the ROV tool to see if the ISR is registered properly?    If not, in your debug session select Tools->Runtime Object View, click on the Hwi module, and then look at “Detailed” and “Vector Table”.  Is PWM1_GEN0_ISR registered at the correct vector location?

    Thanks,
    Scott

  • Hi Scott,

    thank you for the advice. The ISR (pwm_isr = PWM1_GEN0_ISR) seems to be registered correctly:

    I want to count the PWM impulses, for which I use a static variable outside of the ISR. I understand that this is equivalent to the booelan value used in the previous threat. I also tried to togglr the green/red LEDs.

    The PWM itself works correctly according to an LED on PD0. I can update period and duty on the fly.

    Regards, 

    Friedrich

  • Hi Friedrich,

    OK, thanks for sending this.  

    In your application are global interrupts enabled at this point?  This happens within the call to BIOS_start() at the end of main().  (I ask because that old thread had a loop in main()).  

    I know you are incrementing a counter, have you also tried setting a breakpoint on pwm_isr()?

    And, can you show the full sequence you use to initialize/start PWM operation?

    Thanks,
    Scott

  • Hi Scott,

    I could finally nail down the issue. First step was to introduce a Swi which was posted from the ISR. I went back to the TI-RTOS Workshop solution files 2015 in order to get this done properly. I realised then that due to debug confusion, I missed to trigger the PWM interrupt enabling. The following sequence, inline with the previous thread, worked for me:

        PWMGenIntTrigEnable (PWM1_BASE, PWM_GEN_0, PWM_INT_CNT_ZERO) ;
        PWMIntEnable (PWM1_BASE, PWM_INT_GEN_0) ;
    
        IntEnable(INT_PWM1_0);
        IntMasterEnable();

    This needs to be complemented with the call to BIOS_start() as you mentioned.

    I add the relevant source files as reference.

    4314.main.c
    /*
     * Copyright (c) 2015, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /*
     *  ======== main.c ========
     */
    /* XDCtools Header files */
    #include <xdc/std.h>
    #include <xdc/cfg/global.h>
    #include <xdc/runtime/System.h>
    
    /* BIOS Header files */
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Task.h>
    
    
    /* TI-RTOS Header files */
    #include <ti/drivers/GPIO.h>
    // #include <ti/drivers/I2C.h>
    // #include <ti/drivers/SDSPI.h>
    // #include <ti/drivers/SPI.h>
    // #include <ti/drivers/UART.h>
    // #include <ti/drivers/Watchdog.h>
    // #include <ti/drivers/WiFi.h>
    
    /* Board Header file */
    #include "Board.h"
    
    #include "lib/pwm.h"
    
    #define TASKSTACKSIZE   512
    
    Task_Struct task0Struct;
    Char task0Stack[TASKSTACKSIZE];
    
    /*
     *  ======== heartBeatFxn ========
     *  Toggle the Board_LED0. The Task_sleep is determined by arg0 which
     *  is configured for the heartBeat Task instance.
     */
    Void heartBeatFxn(UArg arg0, UArg arg1)
    {
        //pwm_start();
        while (1) {
            Task_sleep((UInt)arg0);
            GPIO_toggle(Board_LED0_BLUE);
            pwm_update();
        }
    }
    
    /*
     *  ======== main ========
     */
    int main(void)
    {
        Task_Params taskParams;
    
        /* Call board init functions */
        Board_initGeneral();
        Board_initGPIO();
        // Board_initI2C();
        // Board_initSDSPI();
        // Board_initSPI();
        // Board_initUART();
        // Board_initUSB(Board_USBDEVICE);
        // Board_initWatchdog();
        // Board_initWiFi();
    
        /* Construct heartBeat Task  thread */
        Task_Params_init(&taskParams);
        taskParams.arg0 = 1000;
        taskParams.stackSize = TASKSTACKSIZE;
        taskParams.stack = &task0Stack;
        Task_construct(&task0Struct, (Task_FuncPtr)heartBeatFxn, &taskParams, NULL);
    
        /* Turn on user LED */
        GPIO_write(Board_LED0_BLUE, Board_LED_ON);
        //GPIO_write(Board_LED2_RED, Board_LED_ON);
    
        /* Initialize PWM */
        pwm_init();
    
        System_printf("Starting the example\nSystem provider is set to SysMin. "
                      "Halt the target to view any SysMin contents in ROV.\n");
        /* SysMin will only print to the console when you call flush or exit */
        System_flush();
    
        /* Start BIOS */
        BIOS_start();
    
        return (0);
    }
    
    pwm.c
    #include "lib/pwm.h"
    // TivaWare(tm) Peripheral Driver Library USER’S GUIDE - SPMU298d, section 21
    
    #define USE_SWI 0
    
    void pwm_swi(void)
    {
    #if Use_SWI
        pwmCount++;
        GPIO_toggle(Board_LED2_RED);
    #endif
    }
    
    void pwm_isr(void)
    {
        PWMGenIntClear(PWM1_BASE, PWM_GEN_0, PWM_INT_CNT_ZERO);
    #if Use_SWI
        Swi_post(PWMswi);
    #else
        pwmCount++;
        GPIO_toggle(Board_LED2_RED);
    #endif
    }
    
    
    void pwm_init(void)
    {
        //SysCtlClockSet( SYSCTL_SYSDIV_2_5 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ );
        SysCtlPWMClockSet( SYSCTL_PWMDIV_64 );
    
    #if 1
        // Enable the GPIO peripheral
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
        //
        // Wait for the GPIO module to be ready.
        //
        while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOD))
            ;
    #endif
    
        GPIOPinTypePWM( GPIO_PORTD_BASE, GPIO_PIN_0 );
        GPIOPinConfigure( GPIO_PD0_M1PWM0 );
    
        // Enable the PWM1 peripheral
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1);
        //
        // Wait for the PWM1 module to be ready.
        //
        while(!SysCtlPeripheralReady(SYSCTL_PERIPH_PWM1))
            ;
        //
        // Configure the PWM generator for count down mode with immediate updates
        // to the parameters.
        //
        PWMGenConfigure(PWM1_BASE, PWM_GEN_0,
                        PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);
        //
        // Set the period.
        //
        PWMGenPeriodSet(PWM1_BASE, PWM_GEN_0, F_MAX_CT);
        //
        // Set the pulse width of PWM1 for a single microstep.
        //
        PWMPulseWidthSet(PWM1_BASE, PWM_OUT_0, 2500);
        //
        // Start the timers in generator 0.
        //
        PWMOutputState(PWM1_BASE, PWM_OUT_0_BIT, true);
        PWMGenEnable(PWM1_BASE, PWM_GEN_0);
    
        //PWMGenIntRegister(PWM1_BASE, PWM_GEN_0, &pwm_isr);
        PWMGenIntTrigEnable (PWM1_BASE, PWM_GEN_0, PWM_INT_CNT_ZERO) ;
        PWMIntEnable (PWM1_BASE, PWM_INT_GEN_0) ;
    
        //IntRegister(INT_PWM1_0, &pwm_isr);
        IntEnable(INT_PWM1_0);
    
        IntMasterEnable();
    
    }
    
    
    inline void pwm_start(void)
    {
        // Enable the outputs.
        //
        //PWMOutputState(PWM1_BASE, PWM_OUT_ALL_BITS, true);
    }
    
    
    inline void pwm_stop(void)
    {
        // Disable the outputs.
        //
        //PWMOutputState(PWM1_BASE, PWM_OUT_ALL_BITS, false);
    }
    
    
    void pwm_update(void)
    {
        PWMGenDisable(PWM1_BASE, PWM_GEN_0);
        // Set the period.
        //
        PWMGenPeriodSet(PWM1_BASE, PWM_GEN_0, PWM_period);
        //
        // Set the pulse width of PWM1.
        //
        PWMPulseWidthSet(PWM1_BASE, PWM_OUT_0, PWM_duty);
        PWMGenEnable(PWM1_BASE, PWM_GEN_0);
    }
    
    
    void pwm_setPeriod(uint32_t pwmPeriod)
    {
        // Set the period.
        //
        PWMGenPeriodSet(PWM1_BASE, PWM_GEN_1, pwmPeriod);
    }
    
    
    void pwm_setDuty(uint32_t pwmDuty)
    {
        // Set the pulse width of PWM1.
        //
        PWMPulseWidthSet(PWM1_BASE, PWM_OUT_1, pwmDuty);
    }
    
    steppercli.cfg