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.

LP-AM243: Finding out which pin a GPIO interrupt was triggered on

Part Number: LP-AM243
Other Parts Discussed in Thread: SYSCONFIG

SDK version: 8.5.0.24

CCS version: 12.2.0.00009

SysConfig version: 1.15.0

I am currently working on a project that requires interrupts to be registered on eight separate GPIO pins. I attempted to modify the SDK example gpio_input_interrupt_am243x-lp_r5fss0-0_nortos_ti-arm-clang to use the GPIO pins GPIO1_[0..6] as well as pin GPIO1_8 by constructing a separate HwiP_Object instance for each pin. The HwiP_Params.args field was set up to hand the ISR the respective pin number, in the exact same way as done in the example.

However, I found that every time the ISR was called, args had the value of the final pin number for which the interrupt was registered - meaning that if pin GPIO1_0 was the final pin to be registered, the ISR would always be passed 0, and if GPIO1_8 was the final pin, the ISR would always be passed 8.

After scouring through the SDK documentation I came to believe that this had to do with the interrupt router, and that if I could assign a separate interrupt router output index to each pin, it would be possible to specify the ISR arguments and/or callback individually. I managed to modify the SYSFW resource management mappings - partially through trial and error as the SDK docs seem to be incomplete in this regard. Unfortunately, this has not resolved my issue.

I am under the impression that I was partially correct - the interrupt router outputs do allow one to specify separate interrupt parameters, but only on the bank level. Individual GPIO pins will always be handed the ISR parameters that have been registered for their bank. This is in line with the fact that the tisci_msg_rm_irq_set_req.src_index field of the structure passed to Sciclient_rmIrqSet() only seems to care about the GPIO bank index, not the pin number, as can be seen in the example code:

// ti_drivers_config.c, line 92, auto-generated by SysConfig
rmIrqReq.src_index = TISCI_BANK_SRC_IDX_BASE_GPIO1 + GPIO_GET_BANK_INDEX(54);

Question 1: Is this the case? If not please correct me.

Question 2: If this is the case, what is the best method for finding out which pin an interrupt was triggered on inside the ISR? It seems that this can be done based on bank (at least in my case, where all pins reside in bank 0), by calling GPIO_getBankIntrStatus() inside the ISR and checking which bits are 1. I am unsure whether this method is sufficiently reliable.

Thank you very much for your time!

  • Hi Nestor Hiebl,

    1.  I don't think this is an issue with the Interrupt router, to further confirm if this is the case or it is related to your implementation, Is there any way you could share the code snippet and your syscfg configurations. 

    2. I don't think there is any direct API to get the Pin number that triggered the interrupt, on interrupt, the corresponding GPIO signal bit will be set in the register, so your method of finding it out seems fine.

    Meanwhile you might find this useful:
    Hi,Is there a way to tell which pin from the regular GPIO trigger the interrupt? - Arm-based microcontrollers forum - Arm-based microcontrollers - TI E2E support forums

    BR,
    Shaunak

  • Hi, thank you for your answer!

    I will continue to compute the interrupt pin based on the bank interrupt status, but am still curious whether it is possible to configure the interrupt router to route individual pins instead of banks.

    Here is the code that sets up GPIO interrupts. Forgive the formatting, inserting code blocks does not seem to work for me at the moment:

    #define NUM_UDI_CONNECTIONS 8

    const uint32_t udi_pin_nums[NUM_UDI_CONNECTIONS] = { /* GPIO pin num macros */ };
    const uint32_t udi_pin_base_addresses[NUM_UDI_CONNECTIONS] = { /* GPIO base address macros */ };
    const uint32_t udi_pin_dirs[NUM_UDI_CONNECTIONS] = { /* GPIO pin direction macros */ };
    const uint32_t udi_pin_trig_types[NUM_UDI_CONNECTIONS] = { /* GPIO trigger type macros */ };
    const uint32_t gpio_router_output_indices[NUM_UDI_CONNECTIONS] = { /* GPIOMUX_INTROUTER0 outputs 0 to 7 */ };

    HwiP_Object gpio_hwi_objects[NUM_UDI_CONNECTIONS];

    void gpio_input_interrupt_main() {
        HwiP_Params hwi_prms[NUM_UDI_CONNECTIONS];
        for (int i = 0; i < NUM_UDI_CONNECTIONS; i++) {
            uint32_t pin_addr   = (DWORD) AddrTranslateP_getLocalAddr(udi_pin_base_addresses[i]);
            uint32_t bankNum    = GPIO_GET_BANK_INDEX(udi_pin_nums[i]);
        
            GPIO_setDirMode(pin_addr, udi_pin_nums[i], udi_pin_dirs[i]);
            GPIO_setTrigType(pin_addr, udi_pin_nums[i], udi_pin_trig_types[i]);
            GPIO_bankIntrEnable(pin_addr, bankNum);

            /* Register pin interrupt */
            HwiP_Params_init(&hwi_prms[i]);
            hwi_prms[i].intNum   = gpio_router_output_indices[i];
            hwi_prms[i].callback = &UdiIsrFxn;
            /* I would expect the result of this to be that every pin is handed the
             * appropriate value of i (0-7) in its ISR. This is not the case - all
             * pins are handed 7 */
            hwi_prms[i].args     = (void *) i;
            /* There is a separate HwiP_Object instance for each pin that is kept
             * in memory for as long as the interrupt mapping are needed. */
            int32_t retVal    = HwiP_construct(&gpio_hwi_objects[i], &hwi_prms[i]);
            DebugP_assert(retVal == SystemP_SUCCESS );
        }
    }

    Sciclient GPIO resource management is handled elsewhere, in the following function:

    static void Sciclient_gpioIrqSet(uint32_t interrupt_source_index, uint32_t router_output_index)
    {
    int32_t retVal;
    struct tisci_msg_rm_irq_set_req rmIrqReq;
    struct tisci_msg_rm_irq_set_resp rmIrqResp;


    rmIrqReq.valid_params = 0U;
    rmIrqReq.valid_params |= TISCI_MSG_VALUE_RM_DST_ID_VALID;
    rmIrqReq.valid_params |= TISCI_MSG_VALUE_RM_DST_HOST_IRQ_VALID;
    rmIrqReq.global_event = 0U;

    rmIrqReq.src_id = TISCI_DEV_GPIO1;

    rmIrqReq.src_index = TISCI_BANK_SRC_IDX_BASE_GPIO1 + (uint16_t) GPIO_GET_BANK_INDEX(interrupt_source_index);
    rmIrqReq.dst_id = TISCI_DEV_R5FSS0_CORE0;

    /* The parameter router_output_index is a macro from <drivers/hw_include/cslr_soc.h>, one of
    * CSLR_R5FSS0_CORE0_INTR_MAIN_GPIOMUX_INTROUTER0_OUTP_<0..7>. Note that calling this function
    * more than one time for GPIO pins within the same bank causes the call to Sciclient_rmIrqSet()
    * to fail. This leads me to believe that GPIO interrupt routing can only take place on the
    * bank level, not the pin level. */
    rmIrqReq.dst_host_irq = router_output_index;
    rmIrqReq.ia_id = 0U;
    rmIrqReq.vint = 0U;
    rmIrqReq.vint_status_bit_index = 0U;
    rmIrqReq.secondary_host = TISCI_MSG_VALUE_RM_UNUSED_SECONDARY_HOST;

    retVal = Sciclient_rmIrqSet(&rmIrqReq, &rmIrqResp, SystemP_WAIT_FOREVER);
    if(0 != retVal)
    {
    DebugP_log("[Error] Sciclient event config failed for GPIO pin index %ld\r\n", interrupt_source_index);
    DebugP_assert(FALSE);
    }

    return;
    }

    The SysConfig configuration is attached in a zip file.

    6874.example.zip

  • Hi Nestor,

    Unfortunately there is no direct way to map the interrupt router to the pin instead of the bank.

    What I can suggest is that on am243x we have 9 banks with each bank having 16 GPIO pins.

    So in your use case if possible, you could have 1 pin being used from 8 different banks.

    Then use the GPIO_getBankIntrStatus() API call to get the status of all 8 different banks being used. Not sure if it will be feasible for your use-case.

    But is a limitation that interrupt router can only be mapped to the register bank.

    BR,

    Shaunak

  • Thank you very much - finding a workable solution will be much easier with awareness of this limitation.