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.

RTOS/CC2640: Pin Interrupt not working as expected.

Part Number: CC2640

Tool/software: TI-RTOS

Hello Guys,

I am having problems configuring the pin interrupt for my custom designed board,

 

This is the hardware design showing the button and the led, i want the LED to switch on when the button is pressed and go off once its released. 

int main()
{
    

    const PIN_Config BoardGpioLedTable[] = {

                   // DIO 3: LED A (initially off)
                LED_PIN| PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL| PIN_DRVSTR_MAX,


                PIN_TERMINATE
    };

    const PIN_Config BoardGpioButtonTable[] = {
                    // DIO 2: BUTTON A (ensure pull-up as button A is also used by other ICs)
                 BUTTON_PIN | PIN_INPUT_EN| PIN_NOPULL | PIN_IRQ_NEGEDGE| PIN_HYSTERESIS,
                PIN_TERMINATE

    };
    Board_init(); // initializing both the tables above
    ledPinHandle = PIN_open( &ledPinState,BoardGpioLedTable );
    buttonPinHandle = PIN_open( &buttonPinState,BoardGpioButtonTable );
    PIN_registerIntCb(buttonPinHandle,&buttonIntCb);
    PIN_setInterrupt(buttonPinHandle, BUTTON_PIN | PIN_IRQ_NEGEDGE);
    
    BIOS_start();
}

void buttonIntCb( PIN_Handle handle, PIN_Id button_pin){
    
 if(PIN_getInputValue(button_pin)==0)
     PIN_setOutputValue(ledPinHandle, PIN_ID(3), 1);
 else
    PIN_setOutputValue(ledPinHandle, PIN_ID(3), 0);

}

Am i missing something here? With the interrupt handling? 

Any help on this is welcome.

Thanks.

  • HI Harsha,

    What is not working as expected, could you elaborate on this? It seems to me that the code should turn the LED on when you press the button, but as you are not catching positive edges (you only setup interrupt on negative edge), you would not be able to turn it off again.
  • The LED neither turns on when I press the button, nor turns off after I release it, the switch used here is of kind (ON)-OFF. I tried using the PIN_IRQ_BOTHEDGES, but it still doesnt work either.To conclude the interrupt call back doesnt work

  • Hi Harsha,

    Have you tried simply running the "pinInterrupt" example on your hardware to see if this works as expected? This should also provide guidance on how you should setup pin interrupts.
  • Weel, as you can see from the code, i tried working on the code according to the example of pin interrupt. But its not working. Also i tried my board configs with the pin interrupt example from TI and it doesnt work.
  • 1. the 2 variables ledPinHandle and ledPinState should be global or static.

    2.  in the callback, it can use the 2 arguments of handle and pinId directly.

  • Sorry, I didnt get your second point, can you explain?
  • 1. look into the source code, the PIN_Handle variable is a pointer to the PIN_State, which holds the callback pointer. so those 2 variable must live steadily for the callback to work, . so those 2 variable can not be a function local variable living in stack which will be overwritten when the stack is always changing for calling context switching. otherwise, the program would jump to nowhere and go dead when interrupt calls the callback if the callback has been overwritten pointing to anywhere other than the intended callback. so those 2 variable must live in heap, so global or static.

    PIN_Status PIN_registerIntCb(PIN_Handle handle, PIN_IntCb pCb) {
        if (handle) {
            handle->callbackFxn = pCb;
            return PIN_SUCCESS;
        } else {
            return PIN_NO_ACCESS;
        }
    }

    PIN_Handle PIN_open(PIN_State* state, const PIN_Config pinList[]) {
        uint32_t i;
        bool pinsAllocated;
        uint32_t portMask;
        PIN_Id pinId;
    
        // Ensure that only one client at a time can call PIN_open() or PIN_add()
        SemaphoreP_pend(&pinSemaphore, SemaphoreP_WAIT_FOREVER);
    
        // Check whether all pins in pinList are valid and available first
        for (i = 0, pinsAllocated = true, portMask = 0; pinList && (pinId = PIN_ID(pinList[i])) != PIN_TERMINATE; i++) {
            /* Unassigned pins is allowed, but cannot generate a bitmask. */
            if (pinId != PIN_UNASSIGNED) {
                if (pinId > pinUpperBound || pinHandleTable[pinId]) {
                    pinsAllocated = false;
                    break;
                } else {
                    // Generate bitmask for port operations (always one port on CC26xx)
                    portMask |= (1 << pinId);
                }
            }
        }
    
        if (!pinsAllocated) {
            // Indicate that the pins were not allocatable
            state = NULL;
        } else {
            // Setup state object
            state->callbackFxn = NULL;
            state->portMask = 0;
            state->userArg = 0;
    
            // Configure I/O pins according to pinList
            for (i = 0; pinList && (pinId = PIN_ID(pinList[i])) != PIN_TERMINATE; i++) {
                if (pinId != PIN_UNASSIGNED) {
                    pinHandleTable[pinId] = state;
                                                                                                                365,5         58%
                    state->portMask |= (1 << pinId);
                    PIN_setConfig(state, PIN_BM_ALL, pinList[i]);
                }
            }
        }
    
        SemaphoreP_post(&pinSemaphore);
        return state;
    }
    

    2. The callback is called from HWI context with handle and pin ID as arguments. the callback could just use them, if there's only one interrupt registered for the handle, directly use it, if more pins registered for interrupt for the handle,  swich/case by pinId could be used to do the work.

    /** @brief I/O Interrupt callback function pointer type
     *  One PIN Interrupt callback can be registered by each PIN client and it
     *  will be called when one of the pins allocated by the client has an interrupt
     *  event. The callback is called from HWI context with handle and pin ID as
     *  arguments.
     * @remark The callback must, as it runs in HWI context, execute and return
     *         quickly. Any lengthy operations should be performed in SWIs or tasks
     *         triggered by the callback
     */
    typedef void (*PIN_IntCb)(PIN_Handle handle, PIN_Id pinId);

    
    

  • To add on to the explanation of Ke Fan.

    The variables does not necessarily need to be global or statics in order to survive the context switches. It is enough that the the variables live on inside the task context which means you could define them in the start of a task main function.

    In this case, they would be placed on the task stack but as each task in TI-RTOS have it's own stack, it will remain on the stack even if you are switching context (it will just not be on the currently active stack but that should be OK as it is accessed as a pointer to memory).

    In your example, the ledPinHandle would however need to be global so that you can use it inside the button callback. the button state and handle could however be keep local inside main as long as you know main never returns.