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.

Starterware/DRA72XEVM: Writing an ISR

Part Number: DRA72XEVM

Tool/software: Starterware

Hi,

I'm currently trying to write an ISR in the mcspiMasterSlave_spi1_spi2 example project, and am unsure how to actually capture the interrupt event. I tried using syntax from an MSP:

#pragma vector = PORT1_VECTOR
__interrupt void PORT1_ISR(void)
{
    //code
}

but during compilation got the following error(s):

mcspiMasterSlave_spi1_spi2.c:265:0: warning: ignoring #pragma vector [-Wunknown-pragmas]
#pragma vector = PORT1_VECTOR
^
mcspiMasterSlave_spi1_spi2.c:266:13: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'void'
__interrupt void PORT1_ISR(void)

What is the correct way to capture an interrupt? And a follow up question would be how do I change the pin the ISR is listening to?

Thanks,
Barend

  • Moving this thread to the Automotive forum for better attention.
  • Hi Barend,

    I have forwarded your question to a Starterware experts.

    Regards,
    Yordan
  • Hi Barend,

    Can you refer to mailbox example under <starterware_rootdir>/examples/mailbox/src on how to configure interrupts using starterware.

    Regards,
    Rishabh
  • I see the directory, and am looking at mailbox_sender.c. Could you please explain what is going on in that file?
  • Hi Barend,

    The description is given here: .

    Regards,

    Rishabh

  • Hm, I'm more interested in what is going on in terms of the interrupts, such as setting the crossbar, and capturing a GPIO pin being pulled down, so I can correctly write an ISR. Do you mind explaining those aspects of the file? Thanks.

  • Hi Barend,

    For GPIO I would suggest you to look at <starterware>\examples\gpio\gpio_input_interrupt\src\main.c. In function configurGpioInterrupt, library API IRQXBARConnect is used for crossbar configuration and then a set of Intc APIs are used to initialize and register ISR.
    This application demonstrates GPIO interrupts on input state changes.
    For more details on what this app is doing please refer to "GPIO Input Interrupt Test" section in <starterware>\docs\StarterWare_UserGuide.pdf

    Regards,
    Rishabh
  • Thanks Rishabh,

    I'm looking through that file, specifically the GPIO API calls within configurGpioInterrupt and I see the call "Intc_IntRegister()" has the following parameters:

    * \param intrNum - Interrupt Number
    * \param fnHandler - Function pointer to the ISR
    * \param fun_arg - Argument to the ISR

    can you please answer the following questions based on those parameters?

    1. How do I know what interrupt number I need to choose to link to this: "#define XBAR_INST_MPU_IRQ_29 (24U)" (GPIO1_IRQ_1)
    2. If the argument is null can I just use "null" as the argument

    My next question pertains to "IRQXBARConnect()"

    * \param baseAddr Memory address of IRQ XBAR.
    * \param cpu CPU ID whose interrupt xbar instance is to be setup
    * \param xbarInst IRQ XBAR instance number to be programmed
    * \param intrSource Source interrupt to be selected via the IRQ XBAR instance

    1. Where do I find the values for these parameters? I'm assuming they are in the TRM, but what should I look for in each one?

    Thanks so much,

    Barend

  • Hi Barend,

    You can choose any interrupt number provided the interrupt line is mapped to crossbar. You need to make sure you configure crossbar corresponding to the interrupt line.
    The mapping is: interrupt source -> crossbar -> interrupt line
    E.g. Assume you want to use interrupt line number 26 for A15 CPU for Mailbox2 User0 interrupt source. API calls will be IRQXBARConnect(SOC_IRQ_DMARQ_CROSSBAR_REGISTERS_BASE, CPU_MPUSS, XBAR_INST_MPU_IRQ_26, MAILBOX2_IRQ_USER0) and Intc_IntRegister(26, (IntrFuncPtr) isr, NULL);
    Base addresses are there in soc.h and CPU ID will be there in chip_config.h file. These files are part of starterware package. Similarly you can search for xbarInst and intrSource in starterware (use macros from above example).

    Regards,
    Rishabh
  • Hi Rishabh,

    I've been caught up in some other work, but thanks for your answer!

    I think I've got a pretty good grasp of what I need to do, but I do have a simple follow up question:

    • Do I need to copy anything other than configurGpioInterrupt() and gpioIsr() from the gpio main.c file into the file I'm working on to detect a gpio high to low transition? I see the gpio clock/reset/enable functions being called in main(), but am not sure if they can be ported directly to a different file, such as mcspiMasterSlave_spi1_spi2.c

    Thanks,

    Barend

  • Hi Barend,

    GPIO clock function is defined in "platform.h" and can be directly called in mcspiMasterSlave_spi1_spi2.c as it already has this include.
    GPIO reset and enable functions are part of GPIO HAL. You can include them in mcspiMasterSlave_spi1_spi2.c by including "gpio.h".
    These APIs are used to make sure that the GPIO is enabled and application starts from clean state.
    I would suggest you to include these APIs in your application.

    Regards,
    Rishabh
  • Rishabh,

    One last thing:

    • Can you confirm that the following code appropriately matches the screenshot of the TRM? I'm not sure what some of these variables represent, but I did my best to model them after your example. 
      uint32_t gpio_base_address = SOC_GPIO1_BASE;
      uint32_t gpio_pin          = 24;
      uint32_t interrupt_num     = 29;
      uint32_t xbar_cfg_required = 0;
      #define IRQ_XBAR_CFG_REQUIRED 1
      #define IRQ_XBAR_CPU_ID CPU_IPU1
      #define IRQ_XBAR_INST_NO XBAR_INST_MPU_IRQ_29
      #define IRQ_XBAR_INDEX GPIO1_IRQ_1
      
      /*...*/
      /*code*/
      /*...*/
      
      /*Disable interrupt*/
      GPIOPinIntDisable(gpio_base_address, GPIO_INT_LINE_1, gpio_pin);
      
      /*Read pin*/
      gpio_pin_value = GPIOPinRead(gpio_base_address, gpio_pin);
      
      UARTPuts(uartOutput, -1);
      UARTPutHexNum((gpio_pin_value & (0x1U << gpio_pin)) >> gpio_pin);
      
      GPIOPinIntClear(gpio_base_address, GPIO_INT_LINE_1, gpio_pin);
      
      /*Enable interrupt interrupt*/
      GPIOPinIntEnable(gpio_base_address, GPIO_INT_LINE_1, gpio_pin);

  • Hi Barend,

    There are some issues with this code as you have specified the IPU1 as CPU on which you want interrupts but you are using MPU XBAR configuration.
    Can you specify what exactly you want to achieve with this code so that I can suggest you the correct modifications.

    Regards,
    Rishabh
  • Using the Cortex_M4_IPU1_C0 core, I want to capture an interrupt from the MMC3_DAT6 (pin 31) pin on the EXP_P3 header on a J6 Eco EVM.

  • Hi Barend,

    For IPU1 you need to use IPU1 XBAR.Hence you should do the below:

    #define IRQ_XBAR_INST_NO XBAR_INST_IPU1_IRQ_29

    Regards,

    Rishabh

  • Thanks Rishabh,

    So my code changes would from be:

    #define IRQ_XBAR_INST_NO XBAR_INST_MPU_IRQ_29
    #define IRQ_XBAR_INDEX GPIO1_IRQ_1

    to

    #define IRQ_XBAR_INST_NO XBAR_INST_IPU1_IRQ_29
    #define IRQ_XBAR_INDEX IPU1_IRQ_Crossbar_inst_7 //128?

    Does it matter that those are reserved? Also does the rest of my code look correct?

    Barend

  • HI Barend,

    It does not matter that these are reserved. Also regarding the rest of the code I assumed that you are calling IRQXBARConnect API.

    The call should be like:

    IRQXBARConnect(SOC_IRQ_DMARQ_CROSSBAR_REGISTERS_BASE,
                   CPU_IPU1,
                   XBAR_INST_IPU1_IRQ_29,
                   GPIO1_IRQ_1);

    Then the interrupt registration should be like:

    #define INTR_NUM 29
    
    Intc_Init();
    Intc_IntEnable(0);
    Intc_IntRegister(INTR_NUM, (IntrFuncPtr) isr, (void *) 0);
    Intc_IntPrioritySet(INTR_NUM, 1, 0);
    Intc_SystemEnable(INTR_NUM);

    Regards,

    Rishabh

  • When I create a falling edge, but the gpioIsr() function in the following code isn't being evaluated when I place a breakpoint there.

    #ifdef TDA2XX_FAMILY_BUILD
    uint32_t gpio_base_address = SOC_GPIO1_BASE;
    uint32_t gpio_pin          = 24;
    uint32_t interrupt_num     = 29;
    uint32_t xbar_cfg_required = 0;
    #define IRQ_XBAR_CFG_REQUIRED 1
    #define IRQ_XBAR_CPU_ID CPU_IPU1
    #define IRQ_XBAR_INST_NO XBAR_INST_IPU1_IRQ_29
    #define IRQ_XBAR_INDEX IPU1_IRQ_Crossbar_inst_7 //128
    #endif
    
    void configurGpioInterrupt()
    {
    #if IRQ_XBAR_CFG_REQUIRED
        PlatformUnlockMMR();
        IRQXBARConnect(SOC_IRQ_DMARQ_CROSSBAR_REGISTERS_BASE, CPU_IPU1, XBAR_INST_IPU1_IRQ_29, GPIO1_IRQ_1);
    #endif
        Intc_Init();
        Intc_IntEnable(0);
    
        Intc_IntRegister(24, (IntrFuncPtr) gpioIsr, NULL);
        Intc_IntPrioritySet(interrupt_num, 1, 0);
        Intc_SystemEnable(interrupt_num);
    
    }
    
    void gpioIsr()
    {
        TCAN_Int_Cnt++;
    }
    
    
    int main(void)
    {
        PlatformUartConsoleSetPinMux();
    
        UARTStdioInit();
    
        /* Do GPIO pin mux */
        PlatformGPIOInputOutputSetPinMux();
    
        /*Configure interrupt controller*/
        configurGpioInterrupt();
    
        /*Enable GPIO clock */
        PlatformGPIOClockEnable();
    
        /*Reset GPIO*/
        GPIOModuleReset(gpio_base_address);
    
        /*Enable GPIO*/
        GPIOModuleEnable(gpio_base_address);
    
        //main_SPI1toSPI2();
        main_SPI1toTCAN4550();
        while(1)
        {
            if(TCAN_Int_Cnt > 0)
            {
                TCAN_Int_Cnt--;
    
                /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!ISR!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
                /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
                
                volatile uint32_t gpio_pin_value = 0;
    
                /*Disable interrupt*/
                GPIOPinIntDisable(gpio_base_address, GPIO_INT_LINE_1, gpio_pin);
    
                /*Read pin*/
                gpio_pin_value = GPIOPinRead(gpio_base_address, gpio_pin);
    
                UARTPuts(uartOutput, -1);
                UARTPutHexNum((gpio_pin_value & (0x1U << gpio_pin)) >> gpio_pin);
    
                GPIOPinIntClear(gpio_base_address, GPIO_INT_LINE_1, gpio_pin);
    
                /*Enable interrupt interrupt*/
                GPIOPinIntEnable(gpio_base_address, GPIO_INT_LINE_1, gpio_pin);
                
                uint32_t RXF0S = AHB_READ_B_FL_32(M_CAN_RXF0S);
                UARTPuts("RXF0S: ", -1); UARTPutHexNum(RXF0S); UARTPuts("\n", -1);
            }
        }
        return 1;
    }

    Thanks,

    Barend

  • Hi Barend,

    Interrupts should be registered using  interrupt line number and not GPIO pin number. Please make the below modification:

    Intc_IntRegister(interrupt_num, (IntrFuncPtr) gpioIsr, NULL)

    Regards,

    RIshabh

  • Rishbh,

    Thanks for looking through my code!

    For some reason, when I put a breakpoint in my ISR, it's never being reached. It may be due to a bounce in the switch I'm using to emulate an interrupt from a pin. Here is a screenshot of what the signal looks like. 

    I know this bouncing is an issue, but would it make it so the interrupt is never picked up in the first place?

    Thanks,

    Barend

  • Hi Barend,

    To debug this further, can you try the below:
    1. Set GPIO interrupt register via the CCS memory window and see if you hit ISR breakpoint. This will verify if crossbar and interrupt configuration is fine.
    2. If the crossbar/interrupt configuration is fine, then can you check the pad mux configuration. As per my understanding multiple interrupts should occur due to bouncing and you can use a debouncing circuit to resolve this issue.

    Regards,
    Rishabh
  • I'm not sure exactly what the GPIO interrupt register address. Is it the gpio_base_address? Then the address would be SOC_GPIO1_BASE which has a physical address of 0x4ae10000U, and a value of 50602001. If I change it to 50602000, nothing happens, what should I change it to hit the ISR breakpoint? Or is this the completely wrong register?

    Thanks,
    Barend
  • Hi Barend,

    You can set either Interrupt status or Interrupt Raw Status register i.e. GPIO_IRQSTATUS_RAW_0 0x4AE1_0024 or GPIO_IRQSTATUS_0 0x4AE1_002c for the particular pin.

    Please look at the GPIO HAL Driver(<starterware_rootdir>/drivers) which uses the interrupt registers.

    This will give a better idea as APIs are quite intuitive.

    Regards,

    Rishabh

  • Rishabh,

    Is gpio_v2.c the file you were talking about in the /drivers directory? If so, I see that there is a function

    GPIOTriggerPinInt(uint32_t baseAdd, uint32_t intLine, uint32_t pinNumber)

    that calls

    HW_WR_REG32(baseAdd + GPIO_IRQSTATUS_RAW_0, (uint32_t) 1 << pinNumber);

    I'm assuming that in the memory browser, I just manually set it the address to what you provided me. However, I'm uncertain on two fronts: since my pin number is 24, would the value I write to the address be 48, and when I try to edit the contents of the register by clicking on the string of 0s and pressing enter, the value defaults back to the string of 0s. Is this not the correct way to change values? If not, could you point me to a guide? My search results didn't yield much.

    Thanks,

    Barend

  • Hi Barend,

    Yes I am talking about gpio_v2.c. The values need to be set from memory browser itself and the way you specified is correct. You need to set 0x4ae10024 to 0x00100000 and 0x4ae10034 to 0x00100000. This will set 0x4ae1002c to 0x00100000. This way you should get the interrupt.

    Regards,
    Rishabh
  • Rishabh,

    Thanks! Changing the memory triggered my interrupt, and it executed how I wanted. What steps should I take to check the Padmux settings?

    So far I've added:

    {DEVICE_MODULE_ID_VIP,   DEVICE_MODULE_VIP1_S1_PORTA_INST_ID_0,
     (BOARD_MODE_VIDEO_24BIT), CTRL_CORE_PAD_MMC3_DAT6, 0x4000E},

    to the gBoardTda2exPinMuxData[] in the stw_boardTda2exPinmuxData.c file.

    Thanks,

    Barend

  • Hi Barend,

    The code you had shared did not have any calls to board module. You need to modify PlatformGPIO1SetPinMux() in <starterware>\platform\platform_tda2xx_pad_config.c as given below:

    HW_WR_REG32(SOC_CORE_PAD_IO_REGISTERS_BASE + CTRL_CORE_PAD_MMC3_DAT6,
                (0x60000U | CTRL_CORE_PAD_MMC3_DAT6_MMC3_DAT6_MUXMODE_GPIO1_24_14));

    Regards,

    Rishabh

  • Hi Rishabh,

    Thanks for the code! Unfortunately, flipping the switch still doesn't result in an interrupt. I checked the physical address of GPIO1_24(0x4A00 379C) and it evaluates to 0006000E, does this mean anything to you?

    Is there a way to simply check the value of the pin before and after toggling the switch, to verify that the event is being recognized by the J6?

    Thanks,

    Barend

  • Hi Barend,

    This is a pad mux register and not the physical address of GPIO pin. By looking at its value you can conclude that pad mux is correct.
    Can you call GPIOTriggerPinInt() API and check if the interrupt is being triggered?
    You can look at GPIO_DATAOUT register to see the value of pin before and after toggling the switch.

    Regards,,
    Rishabh
  • Rishabh,

    What parameters do I need to use for the API? It requires baseAdd, intLine, and pinNumber. Also should I just call it in the main loop?

    Thanks,
    Barend
  • Hi Barend,

    Base address is SOC_GPIO1_BASE, Pin number is 24 and Interrupt line is GPIO_INT_LINE_1.
    You can call it in the main function where you want to trigger the interrupt.

    Regards,
    Rishabh
  • Hi Rishabh,

    I called 

    GPIOTriggerPinInt(gpio_base_address, GPIO_INT_LINE_1, gpio_pin);
    

    in the main while loop and the interrupt is not being triggered. What does this mean?

    Thanks,

    Barend

  • Hi Barend,

    This API sets the interrupt raw status register. The ISR was triggered when you had set the registers through memory browser.
    Can you do a step through and check if the same register is being set.
    Also can you try to run the starterware example gpio_input_interrupt_app on you EVM and see if it works. Please share the application code files so that I can have a look.

    Regards,
    Rishabh
  • Hi Rishabh,

    Apologies for the delay, I was out last week.

    After stepping through the code and observing the memory the following changes:

    • 0x4AE10024 - 0000 0000 to 0100 0000
    • 0x4AE10118 - 0000 0000 to 0100 0000

    This second is not the same register that was set previously.

    When I run gpio_input_interrupt_app what should I expect? I run it on the A15 and have teraterm up with a baud rate of 115200, 0 bits of parity and a stop of 1 bit.

    Attached are the files I've changed. Please let me know if you need any others

    Thanks,

    Barend

  • Hi Rishabh,

    Any ideas?

    Thanks,
    Barend
  • Hi Barend,

    With the gpio interrupt app, interrupt is generated when the signal value on the GPIO line configured as input changes.
    We are using the DCAN1 pin and configuring it as GPIO, so that it is easy to ground the pin as the DCAN pin is populated on a connector on TI EVMs.

    If you are selecting a low/ high interrupt UART console should continuously print the pin value when you connect the pin to ground/keep it open(driven high with the internal week pull up at the pad)
    If you select the falling edge or rising edge you should see one line print (sometime two lines because of debouncing) when the pin is connected to ground or released from ground connection.

    Regards,
    Prasad
  • Ok, thank you for the information. Teraterm still isn't displaying anything at all of meaning. What should be baud rate, etc, be set to?

    Thanks,
    Barend
  • Hi Barend,

    Teraterm needs to be set to baud rate 115200, data 8 bit, parity none, 1 stop bit and flow control as none.

    Regards,
    Rishabh
  • Rishabh,

    Thank you for confirming those specs. For some reason, I had to load the binary twice to get output, and knowing that I was using the correct baud rate allowed me to discover this. I am connecting the pin to ground in mode 1, and it is repeatedly saying "GPIO: Low Level detected. Pin value = 0x0" which I believe is the correct behavior. I'm assuming that this means I am setting the wrong address in memory?

    Thanks,
    Barend
  • Hi Barend,

    Let's have a webex to resolve this issue quickly. Please check your mail.

    Regards,
    Rishabh
  • Hi,

    Adding summary in case anyone faces similar issue:

    1. To enable the GPIO interrupt for falling edge call API:

    GPIOIntTypeSet(gpio_base_address, gpio_pin,GPIO_INT_TYPE_FALL_EDGE);

    2. Set the direction of GPIO pin:

    GPIODirModeSet(gpio_base_address, gpio_pin, GPIO_DIR_INPUT);

    3. Enable the GPIO interrupt:

    GPIOPinIntEnable(gpio_base_address, GPIO_INT_LINE_1, gpio_pin);

    All these calls were added before while(1) loop and the issue was resolved

    Regards,

    Rishabh