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.

Handling a Timer and UART Interrupt



I am a student working on a Sr. Design Project and I'm using the TIVA to be the brain behind my Data Acquisition Rig.

My code uses a UART interrupt to move into a Switch(input) case where "input" is a choice from an options menu. Choice 1 brings you into a test program where I turn on a motor for 15 seconds then turn it off for 10 seconds via a PWM signal. In order to count down those time segments, I'm using TIMER_A one shot countdown. Here's the issue I'm running into:

My code never goes to the TimerIntHandler... Is it because I haven't exited the UARTIntHandler yet? Here is my code:

int timerLoad;
int nextSection

void TestProgram1(void){
	//	Disable UART Interrupts
	UARTIntDisable(UART0_BASE, UART_INT_RX | UART_INT_RT);

	//--------Test Begin--------

	/*	~~~~~ Section # 1 ~~~~~
	 *	Lasts for 5 seconds. Runs motor at 0% speed.
	 */

    	// Set pulse width for 5% duty cycle ~1msec
    	ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_0, DUTY_CYCLE_5_PER);

    	//	Enable PWM Signal
	ROM_PWMOutputState(PWM1_BASE, PWM_OUT_0_BIT, true);
	ROM_PWMGenEnable(PWM1_BASE, PWM_GEN_0);

	// 	Set timer to 5 seconds
	timerLoad = (SysCtlClockGet() * 5) - 1;
	TimerLoadSet(TIMER0_BASE, TIMER_A, timerLoad);

	//	Enable timer
	TimerEnable(TIMER0_BASE, TIMER_A);

	while(!nextSection){
	}

	/*	~~~~~ Section # 2 ~~~~~
	 *	Lasts for 15 seconds. Runs motor at 100% speed.
	 */

	//	Set PWM Signal to 2 ms (100% speed)
	ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_0, DUTY_CYCLE_10_PER);

	// 	Set timer to 15 seconds
	timerLoad = (SysCtlClockGet() * 15) - 1;
	TimerLoadSet(TIMER0_BASE, TIMER_A, timerLoad);
	TimerEnable(TIMER0_BASE, TIMER_A);

	//	Disable continue to next section
	nextSection = false;

	while(!nextSection){
	}

	/*	~~~~~ Section # 3 ~~~~~
	 *	Lasts for 10 seconds. Runs motor at 0% speed.
	 */

	//	Set PWM Signal back to 1 ms (0% speed)
	ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_0, DUTY_CYCLE_5_PER);

	// 	Set timer to 10 seconds
	timerLoad = (SysCtlClockGet() * 10) - 1;
	TimerLoadSet(TIMER0_BASE, TIMER_A, timerLoad);
	TimerEnable(TIMER0_BASE, TIMER_A);

	//	Disable continue to next section
	nextSection = false;

	while(!nextSection){
	}


	/*	~~~~~ Section # 4 ~~~~~
	 *	Terminate Test Program 1
	 */

	//	Turn off
	ROM_PWMOutputState(PWM1_BASE, PWM_OUT_0_BIT, false);
	ROM_PWMGenDisable(PWM1_BASE, PWM_GEN_0);

	IntDisable(INT_TIMER0A);	// disables a specific interrupt associated with TIMER0A
	TimerIntDisable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);

	ROM_UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT);
}

void UARTIntHandler(void) {
	uint32_t ui32Status;
	char optionInput;

	// Save status of MCU before interrupt
	ui32Status = UARTIntStatus(UART0_BASE, true);
	// Clear interrupt flag
	UARTIntClear(UART0_BASE, ui32Status);

	optionInput = UARTCharGetNonBlocking(UART0_BASE);

	switch(optionInput){
		case '1':
		{
			TestProgram1();
			break;
		}
		default:
		//	Tell testing terminal that the selection was invalid
	}
}

void Timer0IntHandler(void){
	// Clear the timer
	TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
	nextSection = true;
}

int main(void) {
	nextSection = false;

	// Sets clock at 50MHz... 400MHz PLL /2 = 200 then div SYSDIV_4 = 50MHz
	ROM_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
	// PWM clock set to SysClock / 16 = 3.125MHz
	ROM_SysCtlPWMClockSet(SYSCTL_PWMDIV_16);
	
	// Enable peripherals...
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1);
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);	// where UART is
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);	// where PWM is

    	// Configure Port F pins to blink blue and red light
    	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);

    	// Configure UART pins, clock, and set BAUD RATE to 115200
    	ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
    	ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
    	ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    	ROM_UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200,
        	(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));

    	// Configure PWM pins and PWM mode
    	ROM_GPIOPinTypePWM(GPIO_PORTD_BASE, GPIO_PIN_0);
    	ROM_GPIOPinConfigure(GPIO_PD0_M1PWM0);
    	// Sets PWM generator as a count down to 0 from a specified value every PWM clock cycle
    	ROM_PWMGenConfigure(PWM1_BASE, PWM_GEN_0, PWM_GEN_MODE_DOWN);
    	// Loads the count number as PWM_COUNT_LOAD
    	ROM_PWMGenPeriodSet(PWM1_BASE, PWM_GEN_0, PWM_COUNT_LOAD);

    	// Configure Timer which will control the timing of test legs
	ROM_TimerConfigure(TIMER0_BASE, TIMER_CFG_ONE_SHOT);

    	// Enable all Interrupts
    	IntMasterEnable();
    	// Enable interrupts from the UART
    	IntEnable(INT_UART0);
    	IntPrioritySet(INT_UART0, 0xE0);
    	UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT);

	// Enable interrupts from the timer
	IntEnable(INT_TIMER0A);
    	IntPrioritySet(INT_TIMER0A, 0);
	TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);

    	// Loop forever and wait for UART interrupts
    	while (1){
    	}
}

  • Hello Timothy,

    For the UART interrupt handler you are calling a blocking function TestProgram1 which refers to nextsection variable set in timer interrupt handler. This approach will not work. Use the interrupt handlers to set a variable that can then be used in the main application code to trigger a timer.

    Regards
    Amit
  • Perhaps it would make more since to -void- the confusion in (main); what came first the chicken or the egg? The MPU might have a fairly good idea the UART should be enabled before the INT can have any switch effect for interrupt driven functions?
  • I see you've used interrupt priorities to enable the timer interrupt to pre-empt the uart interrupt - that approach should work. One potential problem is that you only enable the higher-priority timer interrupt after the uart interrupt, so there is a chance that the uart interrupt fires before the timer interrupt has been enabled, and in that case the program would hang on line 28... Use the debugger to see where your code is merry-going-around.

    Of course, it is better practice to never block within an interrupt handler - on the other hand, it shouldn't be a problem if your main does nothing and you have your interrupt priorities (and firing order!) right.

    And please do declare 'bool' as the datatype if you're feeding 'true' and 'false' into it - it makes my eye twitch! ;)