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: masked-out GPIO interrupts triggering erroneously

Part Number: TM4C123GH6PM


Tool/software:

My circuit contains an H-bridge motor driver and 2 proximity sensors, The idea is to make the motor move in one direction until one sensor is triggered, then stop the motor, then move it in the other direction until the other sensor is triggered, in perpetuity. The sensors are active-low. The motor driver is on pins 2 & 3 and the proximity sensors are on pins 4 & 5, all on PORTA.

The proximity sensor pins are configured as low-level interrupts. The interrupt handler function is as follows:

void pos_sensor_int_handler() {

     GPIOIntClear(GPIO_PORTA_BASE, GPIO_INT_PIN_4 | GPIO_INT_PIN_5);     // clear the proximity sensor interrupts
     static uint32_t state;
     state = GPIOIntStatus(GPIO_PORTA_BASE, true);                                              //get masked interrupt status
     xQueueSendFromISR(pos_sensor_int_queue, &state, NULL);                             //send this to a task where the event is actually processed
}

I set up the GPIO as follows:

int main() {

    ROM_FPULazyStackingEnable();

    ROM_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA)) {}

    GPIOIntRegister(GPIO_PORTA_BASE, pos_sensor_int_handler);

    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, motor_control_pin_R | motor_control_pin_L);      //GPIO pins 2 & 3 are to control the motor

    ROM_GPIOPinTypeGPIOInput(GPIO_PORTA_BASE, pos_sensor_pin_L | pos_sensor_pin_R);               //GPIO pins 4 & 5 are the proximity sensors

    GPIOIntTypeSet(GPIO_PORTA_BASE, pos_sensor_pin_L | pos_sensor_pin_R, GPIO_LOW_LEVEL);

    GPIOIntEnable(GPIO_PORTA_BASE, GPIO_INT_PIN_4 | GPIO_INT_PIN_5);

}

(Code which I don't believe to be relevant is omitted)

The interrupts for pins 4 & 5 do work as expected, however the issue is that I'm also getting spurious interrupts. Using the debugger, I can see that the handler function pos_sensor_int_handler() is randomly (and usually very frequently) being entered even when there was no level change on these pins.

Using the Register view, I can see that the PORTA GPIO Interrupt Mask register (GPIO_IM) is set correctly at 0x00000030, which is the OR result of 16 (pin 5) and 32 (pin 4). When the erroneous interrupt occurs, the GPIO Raw Interrupt Status register (GPIO_RIS) reads 0x00000080, signifying an interrupt on pin 7, which I never enabled! So, I tried explicitly disabling the interrupt for the pin:

GPIOIntDisable(GPIO_PORTA_BASE, GPIO_INT_PIN_7);

Now when it happens, GPIO_RIS just reads all 0s. How is this possible? Shouldn't all interrupts on PORTA be reflected in GPIO_RIS? How could this interrupt handler be entered by any other means than a low level on the enabled pins?

Thank you

  • The interrupts for pins 4 & 5 do work as expected, however the issue is that I'm also getting spurious interrupts. Using the debugger, I can see that the handler function pos_sensor_int_handler() is randomly (and usually very frequently) being entered even when there was no level change on these pins.

    I think the problem is that you use GPIO_LOW_LEVEL. You should try GPIO_FALLING_EDGE for your sensor inputs if the trigger is active low. 

  • Thank you for your reply.

    I tried GPIO_FALLING_EDGE first, but I later switched to GPIO_LOW_LEVEL because GPIO_FALLING EDGE didn't seem to work at all. Using the debugger, I can see that the interrupt does trigger, however GPIOIntStatus(GPIO_PORTA_BASE, true) always returns a 0. I tried setting the bMasked bit to false, same result.

    Do you know what the issue could be? Again, the only interrupts explicitly enabled on PORTA are pins 4 and 5. Therefore it should not be possible, as far as I'm aware, for the status to be returned as 0.

  • You have the below code. You first clear the interrupt flags and then read the status. You should do the opposite by getting the status first and then clear them. It also seems like you are running a FreeRTOS. I will suggest you first run a bare-metal code to get the interrupt working before porting to FreeRTOS as you don't know if FreeRTOS is preventing something from happening. It is just to take out one big variable from troubleshooting the problem. 

    void pos_sensor_int_handler() {

         GPIOIntClear(GPIO_PORTA_BASE, GPIO_INT_PIN_4 | GPIO_INT_PIN_5);     // clear the proximity sensor interrupts
         static uint32_t state;
         state = GPIOIntStatus(GPIO_PORTA_BASE, true);                                              //get masked interrupt status
         xQueueSendFromISR(pos_sensor_int_queue, &state, NULL);                             //send this to a task where the event is actually processed
    }

  • I changed this function to get the status first and clear the interrupt later as you suggested, and this seemed to help somewhat. The spurious interrupts became less frequent, and when they did happen, the masked status no longer came back as 0. Instead, the masked status came back as 48 (0x30). If I changed it to read the unmasked status, it would be randomly changing number between 100 and 200.

    Anyway, I found out this this problem was being caused by noise from 2 DC motors which are being driven off the same circuit board that the TM4C is on. I added series resistors between the sensor inputs and the TM4C, plus capacitors from the sensor inputs to ground, and the spurious interrupts stopped occurring. I'm still curious as to how a non-enabled interrupt managed to trigger the ISR, however I consider the issue solved (for now).

    Thank you for your help