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.

tiva c TM4C1294NCPD GPIO difficulties

I'm working on a project and for the moment am just trying to get GPIO working on my tiva c launchpad, and sometimes it seems to work and sometimes not.

Here is my current (relevant) code:

int
main(void)
{
    //
    // Run from the PLL at 120 MHz.
    //
    ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                           SYSCTL_OSC_MAIN | SYSCTL_USE_PLL |
                                           SYSCTL_CFG_VCO_480), 120000000);

    //
    // The PWM peripheral must be enabled for use.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);
    PortFunctionInit();

    SysCtlDelay(10);

    //
    // Set the PWM clock to the system clock.
    //
    PWMClockSet(PWM0_BASE, PWM_SYSCLK_DIV_1);

    //
    // Configure the PWM0 to count down without synchronization.
    //
    PWMGenConfigure(PWM0_BASE, PWM_GEN_0, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);

    //
    // Set the PWM period to 13kHz.  To calculate the appropriate parameter
    // use the following equation: N = (1 / f) * SysClk.  Where N is the
    // function parameter, f is the desired frequency, and SysClk is the
    // system clock frequency.
    // In this case you get: (1 / 13kHz) * 120MHz = 9231 cycles.  Note that
    // the maximum period you can set is 2^16.
    //
    PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, 9231);
    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, 7431);
    GPIOPadConfigSet(GPIO_PORTJ_BASE, GPIO_PIN_1 , GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);

    //
    // Enable the PWM0 output signal (PD0).
    //
    PWMOutputState(PWM0_BASE, PWM_OUT_0_BIT, true);

    //
    // Enables the PWM generator block.
    //
    PWMGenEnable(PWM0_BASE, PWM_GEN_0);
    //GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 1);
    //GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 1);
    /*SysCtlDelay((SysCtlClockGet()/(3))*741) ; //delay for 60 seconds, experimentally calculated
    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, 7311);
    SysCtlDelay((SysCtlClockGet()/(3))*741) ; //delay for 60 seconds, experimentally calculated
    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, 7191);
    SysCtlDelay((SysCtlClockGet()/(3))*741) ; //delay for 60 seconds, experimentally calculated
    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, 7071);
    SysCtlDelay((SysCtlClockGet()/(3))*741) ; //delay for 60 seconds, experimentally calculated
    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, 6951);
    SysCtlDelay((SysCtlClockGet()/(3))*741) ; //delay for 60 seconds, experimentally calculated
    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, 6831);
    SysCtlDelay((SysCtlClockGet()/(3))*741) ; //delay for 60 seconds, experimentally calculated
    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, 6711);
    SysCtlDelay((SysCtlClockGet()/(3))*741) ; //delay for 60 seconds, experimentally calculated
    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, 6591);
    SysCtlDelay((SysCtlClockGet()/(3))*741) ; //delay for 60 seconds, experimentally calculated
    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, 6471);
    SysCtlDelay((SysCtlClockGet()/(3))*741) ; //delay for 60 seconds, experimentally calculated
    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, 6351);
    SysCtlDelay((SysCtlClockGet()/(3))*741) ; //delay for 60 seconds, experimentally calculated
    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, 6231);*/
    //GPIOPinWrite(GPIO_PORTH_BASE, GPIO_PIN_3, 1);
    while(1)
    {
    	if (GPIOPinRead(GPIO_PORTJ_BASE , GPIO_PIN_1) == 0)
    	{
    		GPIOPinWrite(GPIO_PORTN_BASE , GPIO_PIN_1, 1);
    	}
    	else
    	{
    		GPIOPinWrite(GPIO_PORTN_BASE , GPIO_PIN_1, 0);
    	}


    }
}

And here's the pinmux output file that it's loading in earlier:

void
PortFunctionInit(void)
{
    //
    // Enable Peripheral Clocks 
    //
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOJ);
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK);
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOL);
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);

    //
    // Enable pin PJ0 for GPIOInput
    //
    MAP_GPIOPinTypeGPIOInput(GPIO_PORTJ_BASE, GPIO_PIN_0);

    //
    // Enable pin PJ1 for GPIOInput
    //
    MAP_GPIOPinTypeGPIOInput(GPIO_PORTJ_BASE, GPIO_PIN_1);

    //
    // Enable pin PN1 for GPIOOutput
    //
    MAP_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_1);

    //
    // Enable pin PN2 for GPIOOutput
    //
    MAP_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_2);

    //
    // Enable pin PN0 for GPIOOutput
    //
    MAP_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_0);

    //
    // Enable pin PG0 for PWM0 M0PWM4
    //
    MAP_GPIOPinConfigure(GPIO_PG0_M0PWM4);
    MAP_GPIOPinTypePWM(GPIO_PORTG_BASE, GPIO_PIN_0);

    //
    // Enable pin PF0 for PWM0 M0PWM0
    //
    MAP_GPIOPinConfigure(GPIO_PF0_M0PWM0);
    MAP_GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_0);

    //
    // Enable pin PF4 for PWM0 M0FAULT0
    //
    MAP_GPIOPinConfigure(GPIO_PF4_M0FAULT0);
    MAP_GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_4);

    //
    // Enable pin PK4 for PWM0 M0PWM6
    //
    MAP_GPIOPinConfigure(GPIO_PK4_M0PWM6);
    MAP_GPIOPinTypePWM(GPIO_PORTK_BASE, GPIO_PIN_4);

    //
    // Enable pin PG1 for PWM0 M0PWM5
    //
    MAP_GPIOPinConfigure(GPIO_PG1_M0PWM5);
    MAP_GPIOPinTypePWM(GPIO_PORTG_BASE, GPIO_PIN_1);

    //
    // Enable pin PL0 for PWM0 M0FAULT3
    //
    MAP_GPIOPinConfigure(GPIO_PL0_M0FAULT3);
    MAP_GPIOPinTypePWM(GPIO_PORTL_BASE, GPIO_PIN_0);

    //
    // Enable pin PK5 for PWM0 M0PWM7
    //
    MAP_GPIOPinConfigure(GPIO_PK5_M0PWM7);
    MAP_GPIOPinTypePWM(GPIO_PORTK_BASE, GPIO_PIN_5);

    //
    // Enable pin PF2 for PWM0 M0PWM2
    //
    MAP_GPIOPinConfigure(GPIO_PF2_M0PWM2);
    MAP_GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_2);

    //
    // Enable pin PF1 for PWM0 M0PWM1
    //
    MAP_GPIOPinConfigure(GPIO_PF1_M0PWM1);
    MAP_GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_1);

    //
    // Enable pin PK6 for PWM0 M0FAULT1
    //
    MAP_GPIOPinConfigure(GPIO_PK6_M0FAULT1);
    MAP_GPIOPinTypePWM(GPIO_PORTK_BASE, GPIO_PIN_6);

    //
    // Enable pin PK7 for PWM0 M0FAULT2
    //
    MAP_GPIOPinConfigure(GPIO_PK7_M0FAULT2);
    MAP_GPIOPinTypePWM(GPIO_PORTK_BASE, GPIO_PIN_7);

    //
    // Enable pin PF3 for PWM0 M0PWM3
    //
    MAP_GPIOPinConfigure(GPIO_PF3_M0PWM3);
    MAP_GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_3);
}

I'm trying to figure out why none of the other LEDs are lighting up aside from led4 (PF_0, PWM) - have I defined something incorrectly?

What should be happening is that if I push SW2, PJ_1 is tied to ground and N1 gets written high, which would turn on LED1, but nothing happens.

I'd appreciate another set of eyes looking this over!

Thanks

Garrett

  • Garrett Burgwardt said:
    appreciate another set of eyes looking this over!

    And (while they're bit red) they've arrived.

    While, "Duly noted" - PF0 (the one pin you report to work) is in fact, "plagued" by vendor's decision to force it into default, "NMI."  You must perform a special operation to "repurpose PF0" (and another) prior to other use!  (You're likely the 500th to fall victim - that fine decision)  Vendor's "PF0 alert" insufficiently highlighted - but they, "know best!"  (we're told)  And - failing has LONG been, "Duly Noted!"  (scream emerges from office rear...)

    And - look here: "GPIOPinWrite(GPIO_PORTN_BASE , GPIO_PIN_1, 1);" for most all other MCUs - coding schemes known to man - that would work.  But not here!  That final parameter must reflect the "bit position/bias value" of parameter 2 ("GPIO_PIN_1") in your case - and that value is 2 (to make it high) not the expected "1."  (i.e. GPIO_PIN_7 requires 128 - or you can copy paste parameter 2 into parameter 3)  Should you seek to write to a "full" 8bit port employ 255 as param 2 - and param 3 will then determine which bits "go high."  Clear?  Rookie (here) mistake - we've all done that!

    You need only one use of GPIOPinType() - multiple parameters may be clustered (so long as they're w/in same port.)

    PWM Generator set-up is a bit advanced - believe you've missed several function calls there - but we believe in KISS - and PWM should not be for this soon.  (imho) 

    This should get you on your way - Peripheral Driver Library Guide should be required reading - open/ready @ your desk - along w/MCU manual and numerous code examples.  Together - they immensely aid, clarify and boost your productivity...

  • I take it you are telling me that's where the error is, but I don't know of any documentation I can reference my code against.

  • Posts crossed - I spoke not to "specific errors" instead to your (expressed) inability to light that Led.  (you may need to read again - I'm on the road - power/net goes in/out - I post in "blips."

    Again Periph Drv Lib Guide and pwm code examples w/in examples/peripherals/pwm should prove most useful...

  • Sorry for the misunderstanding, I thought you had been a bit snippy when in fact you just had bad internet - I've gotten things working for the most part now.

    While I've got a thread open, could you give me some advice on "deasserting" a pin assignment?

    In other words, I've got pwm output on PF0 and it works, and in another program I have regular digital output on PF0.
     I'd like to be able to switch between the two modes, but I immediately am dumped into a fault ISR when I try and run code that I think should switch between the two.

    Here's what I'm using:

        PortFunctionInit();
        GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_0);
    
    
        while(1)
        {
        	GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 0);
        	SysCtlDelay(39683333);
        	GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, GPIO_PIN_0);
        	SysCtlDelay(39683333);
        	//----
        	//GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_0);
        	SysCtlDelay(39683333);
        	SysCtlDelay(39683333);
    
        	//----
    

    The function call at the beginning after the PWM settings initialization is initializing the pins, including PF0 as PWM. Then I define PF0 as a regular output right after that.

    Going into the loop, I aim to pull PF0 high for 1 second, then low for 1 second, then switch to PWM output for 2 seconds (commented out currently).

    My guess is that I am misunderstanding how to initialize PWM or pin outputs, or both. In my head, I'm initializing the registers so that PWM is functioning but the pin output is muxxed with a GPIO register, and calling the gpiopintypePWM just enables the pwm signal, vs gpiopintypeoutput outputting the gpio register.

    Thanks in advance!

  • Hello Garrett,

    The code to switch over should be the following in my opinion. Otherwise it may be triggering an NMI

    GPIOPinConfigure(GPIO_PF0_M0PWM0);

    GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_0);

    Regards

    Amit

  • That helped a lot Amit, thanks!

    Now, I've edited my code a little bit and it's getting caught up in a function- here's the code, error after:

    int
    main(void)
    {
        //
        // Run from the PLL at 120 MHz.
        //
        ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                               SYSCTL_OSC_MAIN | SYSCTL_USE_PLL |
                                               SYSCTL_CFG_VCO_480), 120000000);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);
    	PWMClockSet(PWM0_BASE, PWM_SYSCLK_DIV_1);
    	PWMGenConfigure(PWM0_BASE, PWM_GEN_0, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);
    	PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, 9231);
    	PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, 7431);
    	PWMOutputState(PWM0_BASE, PWM_OUT_0_BIT, true);
    	PWMGenEnable(PWM0_BASE, PWM_GEN_0);
        PortFunctionInit();
        GPIOPadConfigSet(GPIO_PORTJ_BASE, GPIO_PIN_1 , GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
    
    
        while(1)
        {
        	while (GPIOPinRead(GPIO_PORTJ_BASE, GPIO_PIN_1))
        	{
            	GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_0);
            	GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 0);
            	SysCtlDelay(39683333);
            	GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, GPIO_PIN_0);
            	SysCtlDelay(39683333);
            	//----
        	}
        	while (GPIOPinRead(GPIO_PORTJ_BASE, GPIO_PIN_0) == 0)
        	{
            	GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_0);
            	GPIOPinConfigure(GPIO_PF0_M0PWM0);
            	PWMGenEnable(PWM0_BASE, PWM_GEN_0);
            	SysCtlDelay(39683333);
        	}
    
    
        	//----
    
        }
    }

    What that (hopefully) does is set everything up, and then runs the PWM output if I push the button, and the gpio output (manually toggled up/down) if I don't.

    But when I hit "Resume" in the debugger, it runs until it gets to the line

            HWREG(ui32Gen + PWM_O_X_LOAD) = ui32Period / 2;

    in function PWMGenPeriodSet in pwm.c

    Hitting resume again returns me to that line.

    I've never had this "error" before, what does it mean? No actual errors are showing up in any logs, it just pretends there is a breakpoint there (there isn't).

    Garrett

  • Hello Garrett

    A step debug will help along with switching off the optimization. Also for the PWM Configuration of the IO I would swap the GPIOPinTypePWM and GPIOPinConfigure function and remove the PWMGenEnable since the PWM Generator is already enabled.

    Regards

    Amit

  • Thanks Amit, those changes helped quite a bit!

    I'm still intermittently getting random lockups on seemingly random functions (one was in a function that set output bits to 0, but was being called on startup automatically?). I'm not sure what that could mean, but they are annoying.

    When the code does decide to run properly, it seems like I've gotten everything working properly.

    Thanks guys!

  • Hello Garrett,

    If you can post the final version of the code, I can have a look at it

    Regards

    Amit

  • Hello Garrett,

    The issue was in the second while loop.

    while (GPIOPinRead(GPIO_PORTJ_BASE, GPIO_PIN_0) == 0)

    which should have been GPIO_PIN_1 instead of GPIO_PIN_0

    while (GPIOPinRead(GPIO_PORTJ_BASE, GPIO_PIN_1) == 0)

    Regards

    Amit