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.

TM4C123GH6PM: How can I configure the timer to run an ISR whenever it captures a rising (or falling) edge on GPIO PB6?

Part Number: TM4C123GH6PM


I am very new to TIVA, and microprocessors in general, so I apologize is my question seems very basic. I have read the related workshop material and seen some example code but I still don't understand why my code is not working. I am feeding a PWM signal into GPIO Pin B6. I tried configuring two timers in capture mode, Timer0A is supposed to trigger an ISR at a rising edge, and TIMER0B is supposed to trigger an ISR at a falling edge. I have changed the corresponding startup file the way it is explained in the workshop, and I was able to make the workshop example work, however I can't seem to get the timer working in capture mode. When I debug, I can see the data in my GPIO PB6 register changing, but the ISR's are never called. Here is my code.

#include <stdint.h>
#include <stdbool.h>
#include <math.h>
#include <stdio.h>
#include <inttypes.h>
#include "driverlib/pin_map.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "inc/hw_qei.h"
#include "inc/hw_ssi.h"
#include "driverlib/sysctl.h"
#include "driverlib/interrupt.h"
#include "driverlib/timer.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/debug.h"
#include "driverlib/pwm.h"
#include "driverlib/pin_map.h"
#include "driverlib/qei.h"
#include "driverlib/ssi.h"
#include "driverlib/rom.h"
#include "driverlib/systick.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"
#include "inc/tm4c123gh6pm.h"
#include "driverlib/adc.h"
#include "driverlib/rom_map.h"

void RisingEdgeInt(void){
	TimerIntClear(TIMER0_BASE, TIMER_CAPA_EVENT);
	// Read the current state of the GPIO pin (blue LED) and
		// write back the opposite state
		if(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_2))
		{
			GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 0);
		}
		else
		{
			GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 4);
		}
}

void FallingEdgeInt(void){
	TimerIntClear(TIMER0_BASE, TIMER_CAPB_EVENT);
	// write back the opposite state
	if(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_2))
	{
		GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 0);
	}
	else
	{
		GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 4);
	}
}
/*
 * main.c
 */
int main(void) {
	SysCtlClockSet(SYSCTL_SYSDIV_4|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);


	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
	MAP_GPIOPadConfigSet(GPIO_PORTB_BASE, GPIO_PIN_6, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);

	GPIOPinConfigure(GPIO_PB6_T0CCP0);

	GPIOPinTypeTimer(GPIO_PORTB_BASE, GPIO_PIN_6);

	//Enable GPIO clock
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
	//Configure GPIO pins as output
	GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);

	SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
	while(!SysCtlPeripheralReady(SYSCTL_PERIPH_TIMER0))
	{
	}


	TimerConfigure(TIMER0_BASE, TIMER_CFG_A_CAP_TIME);

	TimerConfigure(TIMER0_BASE, TIMER_CFG_B_CAP_TIME);

	TimerControlEvent(TIMER0_BASE, TIMER_A, TIMER_EVENT_POS_EDGE);
	TimerControlEvent(TIMER0_BASE, TIMER_B, TIMER_EVENT_NEG_EDGE);

	TimerIntEnable(TIMER0_BASE, TIMER_CAPA_EVENT);
	TimerIntEnable(TIMER0_BASE, TIMER_CAPB_EVENT);

	TimerIntRegister(TIMER0_BASE, TIMER_A, RisingEdgeInt);
	TimerIntRegister(TIMER0_BASE, TIMER_B, FallingEdgeInt);


	TimerIntClear(TIMER0_BASE, TIMER_CAPA_EVENT);
	TimerIntClear(TIMER0_BASE, TIMER_CAPB_EVENT);

	//Enables the processor to respond to interrupts
	IntMasterEnable();

	IntEnable(INT_TIMER0A);
	IntEnable(INT_TIMER0B);

	//Start the timer
	TimerEnable(TIMER0_BASE, TIMER_A);
	TimerEnable(TIMER0_BASE, TIMER_B);

	while(true){}

	return 0;
}

  • Hi Elsa,
    what is the status of the CBEMIS and CAEMIS bits in the GPTMMIS register?
  • Elsa Riachi97 said:
    I have changed the corresponding startup file the way it is explained in the workshop,

    Elsa,

    There are two ways of assigning which function is used to attend an interrupt: either inside the separate file, which is usually *startup_ccs.c, or during the main program itself, using TivaWare functions such as TimerIntRegister().

    Using the startup file is a bit more complex for it requires editing "code outside the main code". But it is faster, for the interrupt addresses are stored directly on the default location.

    Using run-time registration like the TivaWare is easier to visualize, and more convenient for creating "portable functions" - but it usually requires additional processing when the interrupt happens.

    Your sentence above suggests you are using both - which can be conflicting. Did you try to make a simple "GPIO push button interrupt" just to make sure you got the interrupts concept right and properly working, before you go into the timer interrupt?

    One other thing: you are using TIMER0_BASE for both signals:

     

    Elsa Riachi97 said:
    TimerConfigure(TIMER0_BASE, TIMER_CFG_A_CAP_TIME); TimerConfigure(TIMER0_BASE, TIMER_CFG_B_CAP_TIME);

    The second line actually overrides the first, because they deal with the same register. You need to use TIMER_CFG_SPLIT_PAIR and the parameters for each of the two timers on the same call.

    Finally, I see you don't load any value to your timer limit. I am not sure if this is required for capturing signal transition interrupts, but you may need to test and post back your results. If such is needed, load your timer limit value to something different than zero, just in case - by using TimerLoadSet();

    Regards,

    Bruno

  • Thanks to Bruno for spotting the issue and the good hints. Elsa, please try TimerConfigure(TIMER0_BASE, (TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_CAP_TIME | TIMER_CFG_B_CAP_TIME ));