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: Interrupt priority assignment on same GPIO port

Part Number: TM4C123GH6PM

I am interfacing common cathode seven segment display with Tiva C series TM4C123GXL tiva launch pad to display interrupt priority number on it. When switch SW2 (GPIO PF_0) is pressed it will indicate 1 and SW1 (GPIO_PF_4) is pressed it will indicate 2 for 5 sec duration each. When there is no interrupt display will indicate 0. For this task i am using GPIO port C and D to interfaced seven segment display with launchpad. pin connection given below.

(PC4 = A, PC5 = B, PC6 = C, PC7 = D , PD0 = E, PD1 = F, PD=G)

I have written some lines of code for this. This code will generating interrupt on microcontroller but performing tail changing task. I have to assign priority in this operation. when i pressed SW1 it will display 2 instantly when i pressed SW1 display will change number from 2 to 1. After completion of 1 it will continue to display 2 and complete 5 sec display.

I have to assign such type of priority but not able to set this priority with IntPrioritySet. Is there any another way to set priority on GPIO port pins?

Thanking you

I have written this code for tail changing.

#include <stdint.h>
#include <stdbool.h>

#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"

void switch_interrupt(void);

int main(void)
{
SysCtlClockSet(SYSCTL_SYSDIV_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN);

SysCtlPeripheralEnable (SYSCTL_PERIPH_GPIOC);
SysCtlPeripheralEnable (SYSCTL_PERIPH_GPIOD);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOF))
{}
while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOD))
{}
while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOC))
{}

GPIOPinTypeGPIOOutput ( GPIO_PORTC_BASE, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 );
GPIOPinTypeGPIOOutput ( GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 );

GPIOIntRegister(GPIO_PORTF_BASE, switch_interrupt);

HWREG(GPIO_PORTF_BASE + 0x520u) = 0x4C4F434Bu;
HWREG(GPIO_PORTF_BASE + 0x524u) = 0xFFu;

GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, (GPIO_PIN_0 | GPIO_PIN_4));
GPIOPadConfigSet(GPIO_PORTF_BASE, (GPIO_PIN_0 | GPIO_PIN_4), GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);

GPIOIntTypeSet(GPIO_PORTF_BASE, (GPIO_PIN_0 | GPIO_PIN_4), GPIO_FALLING_EDGE);
IntEnable(INT_GPIOF);
GPIOIntEnable(GPIO_PORTF_BASE, GPIO_PIN_0|GPIO_PIN_4);

IntMasterEnable();
while(1)
{
GPIOPinWrite ( GPIO_PORTC_BASE, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 , 0XF0); //0
GPIOPinWrite ( GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 , 0X03);
SysCtlDelay (66666666);
}
}

void switch_interrupt()
{
uint32_t interrupt_status;
interrupt_status = GPIOIntStatus(GPIO_PORTF_BASE, 1u);

if(interrupt_status == GPIO_PIN_0)
{
GPIOPinWrite ( GPIO_PORTC_BASE, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 , 0X60); //1
GPIOPinWrite ( GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, 0);
SysCtlDelay (66666666);
}
else if (interrupt_status == GPIO_PIN_4)
{
GPIOPinWrite ( GPIO_PORTC_BASE, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 , 0XB0); //2
GPIOPinWrite ( GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, 0X05);
SysCtlDelay (66666666);
}
GPIOIntClear(GPIO_PORTF_BASE, interrupt_status);
}

  • There is only a single interrupt request for each GPIO port. Since both switches use port F, you cannot use the NVIC (nested vector interrupt controller) to prioritize between them. This needs to be done by your software. 

    While there are different ways to implement what you describe, I would use a software state-machine. I would use the GPIO port F interrupt and the system tick timer interrupt. Let's say you setup the system tick timer to generate an interrupt every 10ms. You define three states (using enums is a good idea), state0, state1 and state2. The variable holding the state should be declared outside of the functions with the volatile keyword so that it can be modified in either your main function or by the interrupt routines. Initialize the state variable to "state0". In the 10ms system timer interrupt routine, if in state 0, send a "0" out the 7 segment display. When you get a GPIO port F interrupt, check which switch was pressed. If in state 0, change to state 1 if SW2 was pressed and set a variable like "state1_count = 500". (Again the variable is declared like the state variable, volatile and not in function scope.) Now in the system timer interrupt, it will see you are in state1, it should output a "1" to the display and decrement "state1_count". When "state1_count" decrements to zero, it should change the state variable back to "state0". (You have now displayed the "1" for 5 seconds (500 x 10ms).

    Now in the GPIO port F interrupt routine, if you are in state0 or state1, and SW1 is pressed, change the state variable to state2 and set "state2_count = 500". In the system timer interrupt, it will see you are in state2, it should output a "2" to the display and decrement "state2_count". When "state2_count" decrements to zero, it should check the state1_count variable. If state1_count is not zero, change the state to state1. If the state1_count variable is zero, change to state0. This allows SW1 to take priority over SW2, and return the display to a "1" for the remainder of the 5 second display.

    If you are in state2, and you get a GPIO port F interrupt, you can ignore it. SW2 is not allowed to change the state back to state1 when displaying a "2".

    You can make all kinds of adjustments using this method, such as extending the time when the switch is pressed again while already in that state.