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.

Interrupt based GPIO programming on BeagleBone

Other Parts Discussed in Thread: SYSCONFIG

I am facing problem with interrupt based GPIO programming on beaglebone. The code demomain.c given in starterware6 contain so many things apart from GPIO, and this demo is actually running the GUI demo on evm335x.

So, I just extracted GPIO interrupt features referring to the files demoGPIO.c, gpio_v2.c, demomain.c, interrupt.c, hw_control_am335x.h, etc. and TRM for AM335x.
I have attached my code int_gpio.c. Here I want to make GPIO1_29, GPIO1_30, GPIO1_23 as CLK input, DATA input, LED output respectively, for some application. For startup, I just wanted to blink the LED once whenever a falling edge interrupt is invoked via CLK_pin(GPIO1_29). Problems are listed below:

1. The code is built properly, and after configuring the DATA_Port (GPIO1), I am able to return back to main and print "Hello_all". After that if I give a -ve edge to the pin 29, (pin 26 of P8 on beaglebone). the processor is not entering the ISR.
2. In the code below, what is the register with offset 0x44 (not given in TRM)? 34 and 38 are OK as I read in TRM, and I configured all of them for triggering int for pin 29 = 0x20000000  (deafult was given for pin 2 = 0x4).
    HWREG(GPIO_DATA_PORT + 0x34) = 0x20000000; //GPIO_IRQSTATUS_SET0
    HWREG(GPIO_DATA_PORT + 0x38) = 0x20000000; //GPIO_IRQSTATUS_SET0
    HWREG(GPIO_DATA_PORT + 0x44) = 0x20000000; //what is 0x44??

 So far I have done normal GPIO operations and successfully drove 16x2 LCD module using GPIO APIs of starterware5 and 6. Just facing problem with interrupts.

My code "int_gpio.c" is copied below:

#include "soc_AM335x.h"
#include "beaglebone.h"
#include "gpio_v2.h"
#include "interrupt.h"
#include "hw_control_AM335x.h"

/*****************************************************************************
**                INTERNAL MACRO DEFINITIONS
*****************************************************************************/

#define GPIO_DATA_PORT           (SOC_GPIO_1_REGS)
#define GPIO_CLK_PIN_NUMBER        (29)
#define GPIO_DATA_PIN_NUMBER       (30)
#define GPIO_LED_PIN_NUMBER           (23)

/*******************************************************************************
**                     EXTERNAL FUNCTION DECLARATIONS
*******************************************************************************/

extern void GPIO1PinMuxSetup(unsigned int pinNo);
/*****************************************************************************
**                INTERNAL FUNCTION DEFINITIONS
*****************************************************************************/
/*
** A function which is used to generate a delay.
*/
static void Delay(volatile unsigned int count)
{
    while(count--);
}

// A function to blink LED once each time a falling edge is encountered on CLK pin
static void gpio1Isr(void)
{
    printf("Hello1\n");
    /*    Clear clk interrupt    */
    HWREG(SOC_GPIO_1_REGS + 0x2C) = 0x20000000;
    HWREG(SOC_GPIO_1_REGS + 0x30) = 0x20000000;
    printf("Hello2\n");
    /* Driving a logic HIGH on the GPIO pin. */
    GPIOPinWrite(GPIO_DATA_PORT,
                 GPIO_LED_PIN_NUMBER,
                 GPIO_PIN_HIGH);

    Delay(0x3FFFF);

    /* Driving a logic LOW on the GPIO pin. */
    GPIOPinWrite(GPIO_DATA_PORT,
                 GPIO_LED_PIN_NUMBER,
                 GPIO_PIN_LOW);
    Delay(0x3FFFF);
//again enable Falling edge IRQ
    HWREG(GPIO_DATA_PORT + 0x34) = 0x20000000;
    HWREG(GPIO_DATA_PORT + 0x38) = 0x20000000;
    HWREG(GPIO_DATA_PORT + 0x44) = 0x20000000;

}

static void ConfigDataPort(void)
{
    /* Enabling functional clocks for GPIO1 instance. */
    GPIO1ModuleClkConfig();

    /* Selecting GPIO1 pins for use. */
    GPIO1PinMuxSetup(29);
    GPIO1PinMuxSetup(23);
    GPIO1PinMuxSetup(30);

    /* Enabling the GPIO module. */
    GPIOModuleEnable(GPIO_DATA_PORT);
    /* Resetting the GPIO module. */
    GPIOModuleReset(GPIO_DATA_PORT);

    /* Setting the GPIO data as an input pin. */
    GPIODirModeSet(GPIO_DATA_PORT,
                   GPIO_DATA_PIN_NUMBER,
                   GPIO_DIR_INPUT);
    /* Setting the GPIO clock as an input pin. */
    GPIODirModeSet(GPIO_DATA_PORT,
                   GPIO_CLK_PIN_NUMBER,
                   GPIO_DIR_INPUT);
    /* Setting the GPIO LED as an output pin. */
    GPIODirModeSet(GPIO_DATA_PORT,
                   GPIO_LED_PIN_NUMBER,
                   GPIO_DIR_OUTPUT);

//**************** Check enabling of LED pin ****************
    /* Driving a logic HIGH on the GPIO pin. */
    GPIOPinWrite(GPIO_DATA_PORT,
                 GPIO_LED_PIN_NUMBER,
                 GPIO_PIN_HIGH);

    Delay(0x3FFFF);

    /* Driving a logic LOW on the GPIO pin. */
    GPIOPinWrite(GPIO_DATA_PORT,
                 GPIO_LED_PIN_NUMBER,
                 GPIO_PIN_LOW);
    Delay(0x3FFFF);

//************* Now enable interrupt on CLK pin *************


    /* Initialize the ARM Interrupt Controller */
    IntAINTCInit();

    IntMasterIRQEnable();

    /*    GPIO interrupts    */
    IntSystemEnable(SYS_INT_GPIOINT1A);
    IntPrioritySet(SYS_INT_GPIOINT1A, 0, AINTC_HOSTINT_ROUTE_IRQ);
    IntRegister(SYS_INT_GPIOINT1A, gpio1Isr);
    IntSystemEnable(SYS_INT_GPIOINT1B);
    IntPrioritySet(SYS_INT_GPIOINT1B, 0, AINTC_HOSTINT_ROUTE_IRQ);
    IntRegister(SYS_INT_GPIOINT1B, gpio1Isr);

    /* Setting the GPIO_CLK_PIN_NUMBER to raise IRQ at falling edge of input */
    GPIOIntTypeSet(GPIO_DATA_PORT,
                    GPIO_CLK_PIN_NUMBER,
                    GPIO_INT_TYPE_FALL_EDGE);

    HWREG(GPIO_DATA_PORT + 0x34) = 0x20000000;
    HWREG(GPIO_DATA_PORT + 0x38) = 0x20000000;
    HWREG(GPIO_DATA_PORT + 0x44) = 0x20000000;

}







/*
** The main function. Application starts here.
*/
int main()
{
    ConfigDataPort();
    printf("Hello_all\n");

    while(1);

}



/******************************* End of file *********************************/

Please tell me what is missing or what is wrong?

--Thanks in advance

  • Hi everyone, I was just waiting for someone's reply....meanwhile just tried to read-back the values which are being written to GPIO IRQ control/status registers and found that everything was written perfectly.
    Then once again, tested my hardware connections and found everything OK. I donno what happened but the same code is running perfectly thereby executing ISR whenever a falling edge is detected at CLK pin (pin29 of GPIO1). So, I am getting the output as I expected...
    At each falling edge int,
    1. Hello1 is printed

    2. Hello2 is printed

    3. LED blinks once.

    program jumps back to while(1) in main :)

  • Hi Tripathi,

    What about "Hello_all"?

    Regards

    AnilKumar

    Please mark this Forum post as answered via the Verify Answer button below if it helps answer your question.  Thanks!

  •    Hello Anil,

    Well, "Hello_all" will be printed only once just after configuring the port....as is clear. In my previous reply I am talking of things that will occur in sequence, each time a falling edge is detected (after program flow reached while(1); )........i.e. I am talking about the ISR part only not the main program.

    By the way, can u tell me what control reg is there at offset 0x44......I saw below sequence in example so I followed the same. But in TRM, I couldn't find 0x44 in GPIO registers list.

       HWREG(GPIO_DATA_PORT + 0x34) = 0x20000000;            //GPIO_IRQSTATUS_SET0
        HWREG(GPIO_DATA_PORT + 0x38) = 0x20000000;           //GPIO_IRQSTATUS_SET1
        HWREG(GPIO_DATA_PORT + 0x44) = 0x20000000;          //what is there at 0x44??

  • Hi Tripathi,

    You can refer OMAP4_GPIO_* macros in http://lxr.linux.no/#linux+v3.3.4/arch/arm/plat-omap/include/plat/gpio.h

    Regards

    AnilKumar

    Please mark this Forum post as answered via the Verify Answer button below if it helps answer your question.  Thanks!

  • 0x44 is the IRQ wake enable register. more details below,
    Wakeup Enable Register for Interrupt 1 (GPIO_IRQWAKEN _0)

    Every 1-bit field in the GPIO_IRQWAKEN_0 register enables a specific (synchronous) IRQ request source to generate an asynchronous wakeup (on the appropriate swakeup line). This register allows the user to mask the expected transition on input GPIO from generating a wakeup request. The GPIO_IRQWAKEN_0 is programmed synchronously with the interface clock before any Idle mode request coming from the host processor.

    This register need to be configured if you want to wake the device form sleep mode. This register is missed in the AM335x TRM. It will be added in the next revision.

    Regards
    Baskaran




  • Thank you so much for your nice reply Mr. Bhaskaran !
    ......that clarified my doubt well.
    One thing more, I would like to know....there are two interrupt lines associated with same GPIO. Registers 0x34,0x2C are used for GPIOINT1A and 0x38,0x30 are meant for GPIOINT1B.
    Suppose, I register both IRQs simultaneously and write two different handlers (one for each), and a falling edge comes, which handler will be executed ? If both will be executed, then in what sequence. OR one should enable only one interrupt line at a time (i.e. intelligently do switching of this enabling/disabling as per requirements).
    Also, is it possible to make one int line +ve edge triggered and other one -ve edge (or level) triggered?

    Thanks!

  • @Bhaskar....BTW, once again I am facing problem with using UARTs other than UART0, on beaglebone. I have copies of files uartEcho.c & uart.c exactly as edited by you last time. Now, we have uninstalled Starterware 5 and using ver 6. I am using above two files but not getting the output. Can u tell me if you had made changes in any other file apart from these two. (For your kind info, you can get above two files as edited by you from Mr. Anuj...as I had mailed him when u left Dehradun)

    Thanks in advance!.

  • Tripathi,

                    These 2 files only need to be changed. please check if you have taken all the changes.

    Regards

    Baskaran

  • Tripathi,

                The GPIO line has capability to generate two interrupts.This is useful in 2 processor environment. For your usage just configure any one.

    "Two identical interrupt generation sub-modules process synchronous interrupt requests from each channel in order to be used independently in a bi-processor environment. Each sub-module controls its own synchronous interrupt request line and has its own Interrupt Enable and Interrupt Status registers. "

     

    Regards

    Baskaran

  • @Baskaran

    i completely agree wid you but still it is not working,, below i m sending as it is code edited by you... it is getting stuck in UARTMODULEREST function and if i m commentig it,  then it further stuck  in UARTFIFOCONFIG..  probably UART0ModuleClkConfig function is not configuring UART1 clock properly....please check out for the wrong/missing thing. Also check if it is a problem of Starterware version (6 or 5).
    //////////////////////////////////////////////////////////UARTEcho.c /////////////////////////////////////////////////////////

    /*
     * \file   uartEcho.c
     *
     * \brief  This is a sample application file which invokes some APIs
     *         from the UART/IrDA/CIR device abstraction library to perform
     *         configuration, transmission and reception operations.
     */

    /* Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
     * ALL RIGHTS RESERVED
     */

    #include "uart_irda_cir.h"
    #include "soc_AM335x.h"
    #include "interrupt.h"
    #include "beaglebone.h"
    #include "hw_types.h"
    #include "hw_cm_per.h"
    #include "hw_cm_wkup.h"

    /******************************************************************************
    **              INTERNAL MACRO DEFINITIONS
    ******************************************************************************/
    #define BAUD_RATE_115200          (115200)
    #define UART_MODULE_INPUT_CLK     (48000000)

    /******************************************************************************
    **              INTERNAL FUNCTION PROTOTYPES
    ******************************************************************************/
    static void UartInterruptEnable(void);
    static void UART0AINTCConfigure(void);
    static void UartFIFOConfigure(void);
    static void UartBaudRateSet(void);
    static void UARTIsr(void);
    static void sumtest3(void);

    /******************************************************************************
    **              GLOBAL VARIABLE DEFINITIONS
    ******************************************************************************/
    unsigned char txArray[] = "StarterWare";// AM335X UART Interrupt application\r\n";

    /******************************************************************************
    **              FUNCTION DEFINITIONS
    ******************************************************************************/

    int main()
    {       printf("HELLO\n");
        //sumtest3();
        /* Configuring the system clocks for UART0 instance. */
        UART0ModuleClkConfig();

        /* Performing the Pin Multiplexing for UART0 instance. */
        UARTPinMuxSetup(1);

        /* Performing a module reset. */
        UARTModuleReset(SOC_UART_1_REGS);

        /* Performing FIFO configurations. */
        UartFIFOConfigure();

        /* Performing Baud Rate settings. */
        UartBaudRateSet();

        /* Switching to Configuration Mode B. */
        UARTRegConfigModeEnable(SOC_UART_1_REGS, UART_REG_CONFIG_MODE_B);

        /* Programming the Line Characteristics. */
        UARTLineCharacConfig(SOC_UART_1_REGS,
                             (UART_FRAME_WORD_LENGTH_8 | UART_FRAME_NUM_STB_1),
                             UART_PARITY_NONE);

        /* Disabling write access to Divisor Latches. */
        UARTDivisorLatchDisable(SOC_UART_1_REGS);

        /* Disabling Break Control. */
        UARTBreakCtl(SOC_UART_1_REGS, UART_BREAK_COND_DISABLE);

        /* Switching to UART16x operating mode. */
        UARTOperatingModeSelect(SOC_UART_1_REGS, UART16x_OPER_MODE);

        /* Performing Interrupt configurations. */
        UartInterruptEnable();

        while(1);
    }

    /*
    ** A wrapper function performing FIFO configurations.
    */

    static void UartFIFOConfigure(void)
    {
        unsigned int fifoConfig = 0;

        /* Setting the TX and RX FIFO Trigger levels as 1. No DMA enabled. */
        fifoConfig = UART_FIFO_CONFIG(UART_TRIG_LVL_GRANULARITY_1,
                                      UART_TRIG_LVL_GRANULARITY_1,
                                      1,
                                      1,
                                      1,
                                      1,
                                      UART_DMA_EN_PATH_SCR,
                                      UART_DMA_MODE_0_ENABLE);

        /* Configuring the FIFO settings. */
        UARTFIFOConfig(SOC_UART_1_REGS, fifoConfig);
    }

    /*
    ** A wrapper function performing Baud Rate settings.
    */

    static void UartBaudRateSet(void)
    {
        unsigned int divisorValue = 0;

        /* Computing the Divisor Value. */
        divisorValue = UARTDivisorValCompute(UART_MODULE_INPUT_CLK,
                                             BAUD_RATE_115200,
                                             UART16x_OPER_MODE,
                                             UART_MIR_OVERSAMPLING_RATE_42);

        /* Programming the Divisor Latches. */
        UARTDivisorLatchWrite(SOC_UART_1_REGS, divisorValue);
    }

    /*
    ** A wrapper function performing Interrupt configurations.
    */

    static void UartInterruptEnable(void)
    {
        /* Enabling IRQ in CPSR of ARM processor. */
        IntMasterIRQEnable();

        /* Configuring AINTC to receive UART0 interrupts. */
        UART0AINTCConfigure();

        /* Enabling the specified UART interrupts. */
        UARTIntEnable(SOC_UART_1_REGS, (UART_INT_LINE_STAT | UART_INT_THR |
                                        UART_INT_RHR_CTI));
    }

    /*
    ** Interrupt Service Routine for UART.
    */

    static void UARTIsr(void)
    {
        static unsigned int txStrLength = sizeof(txArray);
        static unsigned int count = 0;
        unsigned char rxByte = 0;
        unsigned int intId = 0;
     //   printf("HELLO1\n");
        /* Checking ths source of UART interrupt. */
        intId = UARTIntIdentityGet(SOC_UART_1_REGS);

        switch(intId)
        {
            case UART_INTID_TX_THRES_REACH:

                if(0 != txStrLength)
                {                //printf("HELLO2\n");
                    UARTCharPut(SOC_UART_1_REGS, txArray[count]);
                    txStrLength--;
                    count++;
                }
                else
                {                //printf("HELLO3\n");
                    /* Disabling the THR interrupt. */
                    UARTIntDisable(SOC_UART_1_REGS, UART_INT_THR);

                }

            break;

            case UART_INTID_RX_THRES_REACH:
               // printf("HELLO4\n");
                rxByte = UARTCharGetNonBlocking(SOC_UART_1_REGS);
                printf("%c\n", rxByte);
               // UARTCharPutNonBlocking(SOC_UART_1_REGS, rxByte);
            break;

            case UART_INTID_RX_LINE_STAT_ERROR:
            case UART_INTID_CHAR_TIMEOUT:
                rxByte = UARTCharGetNonBlocking(SOC_UART_1_REGS);
            break;
        
            default:
            break;    
        }

    }

    /*
    ** This function configures the AINTC to receive UART interrupts.
    */

    static void UART0AINTCConfigure(void)
    {
        /* Initializing the ARM Interrupt Controller. */
        IntAINTCInit();

        /* Registering the Interrupt Service Routine(ISR). */
        IntRegister(SYS_INT_UART1INT, UARTIsr);

        /* Setting the priority for the system interrupt in AINTC. */
        IntPrioritySet(SYS_INT_UART1INT, 0, AINTC_HOSTINT_ROUTE_IRQ);

        /* Enabling the system interrupt in AINTC. */
        IntSystemEnable(SYS_INT_UART1INT);
    }

    /******************************* End of file *********************************/

    ////////////////////////////////////////////// UART.c ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    /*
     * \file   uart.c
     *
     * \brief  This file contains functions which does the platform specific
     *         configurations for UART.
     */

    /* Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
     * ALL RIGHTS RESERVED
     */

    #include "hw_control_AM335x.h"
    #include "soc_AM335x.h"
    #include "hw_cm_wkup.h"
    #include "hw_cm_per.h"
    #include "beaglebone.h"
    #include "hw_types.h"

    /**
     * \brief   This function selects the UART pins for use. The UART pins
     *          are multiplexed with pins of other peripherals in the SoC
     *          
     * \param   instanceNum       The instance number of the UART to be used.
     *
     * \return  None.
     *
     * \note    This pin multiplexing depends on the profile in which the EVM
     *          is configured.
     */
    void UARTPinMuxSetup(unsigned int instanceNum)
    {
          /* RXD */
          HWREG(SOC_CONTROL_REGS + CONTROL_CONF_UART_RXD(instanceNum)) =
          (CONTROL_CONF_UART0_RXD_CONF_UART0_RXD_PUTYPESEL |
           CONTROL_CONF_UART0_RXD_CONF_UART0_RXD_RXACTIVE);

          /* TXD */
          HWREG(SOC_CONTROL_REGS + CONTROL_CONF_UART_TXD(instanceNum)) =
           CONTROL_CONF_UART0_TXD_CONF_UART0_TXD_PUTYPESEL;
    }

    /*
    ** This function enables the system L3 and system L4_WKUP clocks.
    ** This also enables the clocks for UART0 instance.
    */

    void UART0ModuleClkConfig(void)
    {
        /* Configuring L3 Interface Clocks. */

        /* Writing to MODULEMODE field of CM_PER_L3_CLKCTRL register. */
        HWREG(SOC_CM_PER_REGS + CM_PER_L3_CLKCTRL) |=
              CM_PER_L3_CLKCTRL_MODULEMODE_ENABLE;

        /* Waiting for MODULEMODE field to reflect the written value. */
        while(CM_PER_L3_CLKCTRL_MODULEMODE_ENABLE !=
              (HWREG(SOC_CM_PER_REGS + CM_PER_L3_CLKCTRL) &
               CM_PER_L3_CLKCTRL_MODULEMODE));

        /* Writing to MODULEMODE field of CM_PER_L3_INSTR_CLKCTRL register. */
        HWREG(SOC_CM_PER_REGS + CM_PER_L3_INSTR_CLKCTRL) |=
              CM_PER_L3_INSTR_CLKCTRL_MODULEMODE_ENABLE;

        /* Waiting for MODULEMODE field to reflect the written value. */
        while(CM_PER_L3_INSTR_CLKCTRL_MODULEMODE_ENABLE !=
              (HWREG(SOC_CM_PER_REGS + CM_PER_L3_INSTR_CLKCTRL) &
               CM_PER_L3_INSTR_CLKCTRL_MODULEMODE));

        /* Writing to CLKTRCTRL field of CM_PER_L3_CLKSTCTRL register. */
        HWREG(SOC_CM_PER_REGS + CM_PER_L3_CLKSTCTRL) |=
              CM_PER_L3_CLKSTCTRL_CLKTRCTRL_SW_WKUP;

        /* Waiting for CLKTRCTRL field to reflect the written value. */
        while(CM_PER_L3_CLKSTCTRL_CLKTRCTRL_SW_WKUP !=
              (HWREG(SOC_CM_PER_REGS + CM_PER_L3_CLKSTCTRL) &
               CM_PER_L3_CLKSTCTRL_CLKTRCTRL));

        /* Writing to CLKTRCTRL field of CM_PER_OCPWP_L3_CLKSTCTRL register. */
        HWREG(SOC_CM_PER_REGS + CM_PER_OCPWP_L3_CLKSTCTRL) |=
              CM_PER_OCPWP_L3_CLKSTCTRL_CLKTRCTRL_SW_WKUP;

        /*Waiting for CLKTRCTRL field to reflect the written value. */
        while(CM_PER_OCPWP_L3_CLKSTCTRL_CLKTRCTRL_SW_WKUP !=
              (HWREG(SOC_CM_PER_REGS + CM_PER_OCPWP_L3_CLKSTCTRL) &
               CM_PER_OCPWP_L3_CLKSTCTRL_CLKTRCTRL));

        /* Writing to CLKTRCTRL field of CM_PER_L3S_CLKSTCTRL register. */
        HWREG(SOC_CM_PER_REGS + CM_PER_L3S_CLKSTCTRL) |=
              CM_PER_L3S_CLKSTCTRL_CLKTRCTRL_SW_WKUP;

        /*Waiting for CLKTRCTRL field to reflect the written value. */
        while(CM_PER_L3S_CLKSTCTRL_CLKTRCTRL_SW_WKUP !=
              (HWREG(SOC_CM_PER_REGS + CM_PER_L3S_CLKSTCTRL) &
               CM_PER_L3S_CLKSTCTRL_CLKTRCTRL));

        /* Checking fields for necessary values.  */

        /* Waiting for IDLEST field in CM_PER_L3_CLKCTRL register to be set to 0x0. */
        while((CM_PER_L3_CLKCTRL_IDLEST_FUNC << CM_PER_L3_CLKCTRL_IDLEST_SHIFT)!=
              (HWREG(SOC_CM_PER_REGS + CM_PER_L3_CLKCTRL) &
               CM_PER_L3_CLKCTRL_IDLEST));

        /*
        ** Waiting for IDLEST field in CM_PER_L3_INSTR_CLKCTRL register to attain the
        ** desired value.
        */
        while((CM_PER_L3_INSTR_CLKCTRL_IDLEST_FUNC <<
               CM_PER_L3_INSTR_CLKCTRL_IDLEST_SHIFT)!=
              (HWREG(SOC_CM_PER_REGS + CM_PER_L3_INSTR_CLKCTRL) &
               CM_PER_L3_INSTR_CLKCTRL_IDLEST));

        /*
        ** Waiting for CLKACTIVITY_L3_GCLK field in CM_PER_L3_CLKSTCTRL register to
        ** attain the desired value.
        */
        while(CM_PER_L3_CLKSTCTRL_CLKACTIVITY_L3_GCLK !=
              (HWREG(SOC_CM_PER_REGS + CM_PER_L3_CLKSTCTRL) &
               CM_PER_L3_CLKSTCTRL_CLKACTIVITY_L3_GCLK));

        /*
        ** Waiting for CLKACTIVITY_OCPWP_L3_GCLK field in CM_PER_OCPWP_L3_CLKSTCTRL
        ** register to attain the desired value.
        */
        while(CM_PER_OCPWP_L3_CLKSTCTRL_CLKACTIVITY_OCPWP_L3_GCLK !=
              (HWREG(SOC_CM_PER_REGS + CM_PER_OCPWP_L3_CLKSTCTRL) &
               CM_PER_OCPWP_L3_CLKSTCTRL_CLKACTIVITY_OCPWP_L3_GCLK));

        /*
        ** Waiting for CLKACTIVITY_L3S_GCLK field in CM_PER_L3S_CLKSTCTRL register
        ** to attain the desired value.
        */
        while(CM_PER_L3S_CLKSTCTRL_CLKACTIVITY_L3S_GCLK !=
              (HWREG(SOC_CM_PER_REGS + CM_PER_L3S_CLKSTCTRL) &
              CM_PER_L3S_CLKSTCTRL_CLKACTIVITY_L3S_GCLK));


        /* Configuring registers related to Wake-Up region. */

        /* Writing to MODULEMODE field of CM_WKUP_CONTROL_CLKCTRL register. */
        HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CONTROL_CLKCTRL) |=
              CM_WKUP_CONTROL_CLKCTRL_MODULEMODE_ENABLE;

        /* Waiting for MODULEMODE field to reflect the written value. */
        while(CM_WKUP_CONTROL_CLKCTRL_MODULEMODE_ENABLE !=
              (HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CONTROL_CLKCTRL) &
               CM_WKUP_CONTROL_CLKCTRL_MODULEMODE));

        /* Writing to CLKTRCTRL field of CM_PER_L3S_CLKSTCTRL register. */
        HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CLKSTCTRL) |=
              CM_WKUP_CLKSTCTRL_CLKTRCTRL_SW_WKUP;

        /*Waiting for CLKTRCTRL field to reflect the written value. */
        while(CM_WKUP_CLKSTCTRL_CLKTRCTRL_SW_WKUP !=
              (HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CLKSTCTRL) &
               CM_WKUP_CLKSTCTRL_CLKTRCTRL));

        /* Writing to CLKTRCTRL field of CM_L3_AON_CLKSTCTRL register. */
        HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CM_L3_AON_CLKSTCTRL) |=
              CM_WKUP_CM_L3_AON_CLKSTCTRL_CLKTRCTRL_SW_WKUP;

        /*Waiting for CLKTRCTRL field to reflect the written value. */
        while(CM_WKUP_CM_L3_AON_CLKSTCTRL_CLKTRCTRL_SW_WKUP !=
              (HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CM_L3_AON_CLKSTCTRL) &
               CM_WKUP_CM_L3_AON_CLKSTCTRL_CLKTRCTRL));

        /* Writing to MODULEMODE field of CM_WKUP_UART0_CLKCTRL register. */
        HWREG(SOC_CM_PER_REGS + CM_PER_UART1_CLKCTRL) |=
              CM_PER_UART1_CLKCTRL_MODULEMODE_ENABLE;

        /* Waiting for MODULEMODE field to reflect the written value. */
        while(CM_PER_UART1_CLKCTRL_MODULEMODE_ENABLE !=
              (HWREG(SOC_CM_PER_REGS + CM_PER_UART1_CLKCTRL) &
               CM_PER_UART1_CLKCTRL_MODULEMODE));

        /* Verifying if the other bits are set to required settings. */

        /*
        ** Waiting for IDLEST field in CM_WKUP_CONTROL_CLKCTRL register to attain
        ** desired value.
        */
        while((CM_WKUP_CONTROL_CLKCTRL_IDLEST_FUNC <<
               CM_WKUP_CONTROL_CLKCTRL_IDLEST_SHIFT) !=
              (HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CONTROL_CLKCTRL) &
               CM_WKUP_CONTROL_CLKCTRL_IDLEST));

        /*
        ** Waiting for CLKACTIVITY_L3_AON_GCLK field in CM_L3_AON_CLKSTCTRL
        ** register to attain desired value.
        */
        while(CM_WKUP_CM_L3_AON_CLKSTCTRL_CLKACTIVITY_L3_AON_GCLK !=
              (HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CM_L3_AON_CLKSTCTRL) &
               CM_WKUP_CM_L3_AON_CLKSTCTRL_CLKACTIVITY_L3_AON_GCLK));

        /*
        ** Waiting for IDLEST field in CM_WKUP_L4WKUP_CLKCTRL register to attain
        ** desired value.
        */
        while((CM_WKUP_L4WKUP_CLKCTRL_IDLEST_FUNC <<
               CM_WKUP_L4WKUP_CLKCTRL_IDLEST_SHIFT) !=
              (HWREG(SOC_CM_WKUP_REGS + CM_WKUP_L4WKUP_CLKCTRL) &
               CM_WKUP_L4WKUP_CLKCTRL_IDLEST));

        /*
        ** Waiting for CLKACTIVITY_L4_WKUP_GCLK field in CM_WKUP_CLKSTCTRL register
        ** to attain desired value.
        */
        while(CM_WKUP_CLKSTCTRL_CLKACTIVITY_L4_WKUP_GCLK !=
              (HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CLKSTCTRL) &
               CM_WKUP_CLKSTCTRL_CLKACTIVITY_L4_WKUP_GCLK));

        /*
        ** Waiting for CLKACTIVITY_L4_WKUP_AON_GCLK field in CM_L4_WKUP_AON_CLKSTCTRL
        ** register to attain desired value.
        */
        while(CM_WKUP_CM_L4_WKUP_AON_CLKSTCTRL_CLKACTIVITY_L4_WKUP_AON_GCLK !=
              (HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CM_L4_WKUP_AON_CLKSTCTRL) &
               CM_WKUP_CM_L4_WKUP_AON_CLKSTCTRL_CLKACTIVITY_L4_WKUP_AON_GCLK));

        /*
        ** Waiting for CLKACTIVITY_UART0_GFCLK field in CM_WKUP_CLKSTCTRL
        ** register to attain desired value.
        */
        //while(CM_PER_CLKSTCTRL_CLKACTIVITY_UART1_GFCLK !=
          //    (HWREG(SOC_CM_PER_REGS + CM_PER_UART1_CLKCTRL) &
            //   CM_PER_CLKSTCTRL_CLKACTIVITY_UART1_GFCLK));

        /*
        ** Waiting for IDLEST field in CM_WKUP_UART0_CLKCTRL register to attain
        ** desired value.
        */
        while((CM_PER_UART1_CLKCTRL_IDLEST_FUNC <<
               CM_PER_UART1_CLKCTRL_IDLEST_SHIFT) !=
              (HWREG(SOC_CM_PER_REGS + CM_PER_UART1_CLKCTRL) &
               CM_PER_UART1_CLKCTRL_IDLEST));
    }

    /****************************** End of file *********************************/

  • Hello All,

    I am trying to use the gpio2_7 as interrupt on beaglebone.

    but when trying to reset interrupt controller, it hangs in endless while loop of

    IntAINTCInit()

    any idea, what else i need to do before this?

    br

    Vikas

  • Hello All,

    I am trying to configure lcd_data1 pin (gpio2_7:pin 46,header8 of beaglebone) for the gpio interrupt  falling edge.

    Find below the code i am using, adapted from internet/ti-community for my use...but i am ending into a sort of hanging situation after running this code.
    I plan to register a interrupt handler in kernel space uisng request_irq(), with gpio_to_irq(71) giving the  requisite irq number for gpio2_7(32*2 +7).
     
    All the methods/#define's are from starterware(2.0.0.7), with few methods modified specifically for my cause are also pasted for your kind reference.
     
    ===============
    #define MMAP_OFFSET 0x44c00000
    // redefine vHWREG macro to use MMAP result
    #define vHWREG(x) __mmapl[(x-MMAP_OFFSET)/4]
    #define CM_DEVICE 0x44E00700
    volatile ulong *__mmapl;
    /*****************************************************************************
    ** INTERNAL MACRO DEFINITIONS
    *****************************************************************************/
    #define GPIO_INTERRUPT_PORT (SOC_GPIO_2_REGS)
    #define GPIO_INTERRUPT_PIN_NUMBER (7)
    #define REG_IDX_SHIFT (0x05)
    #define REG_BIT_MASK (0x1F)
    #define NUM_INTERRUPTS (128u)
    /**************** *************************************************************
    ** STATIC VARIABLE DEFINITIONS
    ******************************************************************************/
    void (*fnRAMVectors[NUM_INTERRUPTS])(void);
     
    ...........
    main() Code is like,
     
    /* Enabling functional clocks for GPIO2 instance. */
    GPIO2ModuleClkConfig(); //Check the method below in this post.
    GPIO2PinMuxSetup(1); //lcd_data1...check the method below in this post.
     
    /* Enabling the GPIO module. */
    GPIOModuleEnable(GPIO_INTERRUPT_PORT);

    /* Resetting the GPIO module. */
    GPIOModuleReset(GPIO_INTERRUPT_PORT);
     
    /* Setting the GPIO data as an input pin. */
    GPIODirModeSet(GPIO_INTERRUPT_PORT, GPIO_INTERRUPT_PIN_NUMBER,GPIO_DIR_INPUT);
     
    /* Setting the GPIO_CLK_PIN_NUMBER to raise IRQ at falling edge of input */
    GPIOIntTypeSet(GPIO_INTERRUPT_PORT, GPIO_INTERRUPT_PIN_NUMBER,GPIO_INT_TYPE_FALL_EDGE);
     
    GPIOPinIntEnable(GPIO_INTERRUPT_PORT,GPIO_INT_LINE_1,GPIO_INTERRUPT_PIN_NUMBER); //vHWREG(GPIO_INTERRUPT_PORT + 0x34) = 0x00000080;
    GPIOPinIntEnable(GPIO_INTERRUPT_PORT,GPIO_INT_LINE_2,GPIO_INTERRUPT_PIN_NUMBER); ////vHWREG(GPIO_INTERRUPT_PORT + 0x38) = 0x00000080;

    CPUirqe();
     
    /* Initialize the ARM Interrupt Controller */
    IntAINTCInit();
     
    IntSystemEnable(SYS_INT_GPIOINT2A);
    IntPrioritySet(SYS_INT_GPIOINT2A,0,AINTC_HOSTINT_ROUTE_IRQ);
    IntSystemEnable(SYS_INT_GPIOINT2B);
    IntPrioritySet(SYS_INT_GPIOINT2B,0,AINTC_HOSTINT_ROUTE_IRQ);
     
    ===========
    //helper functions,
    void GPIO2PinMuxSetup(unsigned int pinNo)
    {
        vHWREG(SOC_CONTROL_REGS + CONTROL_CONF_LCD_DATA(pinNo)) =
        (CONTROL_CONF_SLOWSLEW | /* Slew rate slow */
        CONTROL_CONF_RXACTIVE | /* Receiver enabled */
        CONTROL_CONF_PULLUDDISABLE | /* Pull up/down diabled*/
        (CONTROL_CONF_MUXMODE(7)) /* Select mode 7 */
    );
    }
    ============
    void IntAINTCInit(void)
    {
        unsigned int intrNum;
        /* Reset the ARM interrupt controller */
        vHWREG(SOC_AINTC_REGS + INTC_SYSCONFIG) = INTC_SYSCONFIG_SOFTRESET;
       
        /* Wait for the reset to complete */
        while((vHWREG(SOC_AINTC_REGS + INTC_SYSSTATUS)& INTC_SYSSTATUS_RESETDONE) != INTC_SYSSTATUS_RESETDONE);
     
        /* setting the AutoIDLE bit */
        vHWREG(SOC_AINTC_REGS + INTC_SYSCONFIG) = INTC_SYSCONFIG_AUTOIDLE;
       
        /* Enable any interrupt generation by setting priority threshold */
        vHWREG(SOC_AINTC_REGS + INTC_THRESHOLD) = INTC_THRESHOLD_PRIORITYTHRESHOLD;
     
        //clear the interrupt mask bits gpio2_x
        vHWREG(SOC_AINTC_REGS + INTC_MIR_CLEAR(2)) = 0x80;
     
        /* Register the default handler for all interrupts */
        for(intrNum = 0; intrNum < NUM_INTERRUPTS; intrNum++)
        {
            fnRAMVectors[intrNum] = IntDefaultHandler;
        }
    }
    =============
    void GPIO2ModuleClkConfig(void)
    {
        /* Writing to MODULEMODE field of CM_PER_GPIO2_CLKCTRL register. */
        vHWREG(SOC_CM_PER_REGS + CM_PER_GPIO2_CLKCTRL) |=
        CM_PER_GPIO2_CLKCTRL_MODULEMODE_ENABLE;
     
        /* Waiting for MODULEMODE field to reflect the written value. */
        while(CM_PER_GPIO2_CLKCTRL_MODULEMODE_ENABLE !=
        (vHWREG(SOC_CM_PER_REGS + CM_PER_GPIO2_CLKCTRL) &
        CM_PER_GPIO2_CLKCTRL_MODULEMODE));
     
        /*
        ** Writing to OPTFCLKEN_GPIO_2_GDBCLK bit in CM_PER_GPIO2_CLKCTRL
        ** register.
        */
        vHWREG(SOC_CM_PER_REGS + CM_PER_GPIO2_CLKCTRL) |=
        CM_PER_GPIO2_CLKCTRL_OPTFCLKEN_GPIO_2_GDBCLK;
     
        /*
        ** Waiting for OPTFCLKEN_GPIO_2_GDBCLK bit to reflect the desired
        ** value.
        */
        while(CM_PER_GPIO2_CLKCTRL_OPTFCLKEN_GPIO_2_GDBCLK !=
        (vHWREG(SOC_CM_PER_REGS + CM_PER_GPIO2_CLKCTRL) &
        CM_PER_GPIO2_CLKCTRL_OPTFCLKEN_GPIO_2_GDBCLK));
     
        /*
        ** Waiting for IDLEST field in CM_PER_GPIO2_CLKCTRL register to attain the
        ** desired value.
        */
        while((CM_PER_GPIO2_CLKCTRL_IDLEST_FUNC <<
        CM_PER_GPIO2_CLKCTRL_IDLEST_SHIFT) !=
        (vHWREG(SOC_CM_PER_REGS + CM_PER_GPIO2_CLKCTRL) &
        CM_PER_GPIO2_CLKCTRL_IDLEST));
     
        /*
        ** Waiting for CLKACTIVITY_GPIO_2_GDBCLK bit in CM_PER_L4LS_CLKSTCTRL
        ** register to attain desired value.
        */
        while(CM_PER_L4LS_CLKSTCTRL_CLKACTIVITY_GPIO_2_GDBCLK !=
        (vHWREG(SOC_CM_PER_REGS + CM_PER_L4LS_CLKSTCTRL) &
        CM_PER_L4LS_CLKSTCTRL_CLKACTIVITY_GPIO_2_GDBCLK));
    }
     

    ...

    again please help..

    regards,

    Vikas

  • where do we see these print outs?

    dmesg?

    /var/log/??

    or the same terminal, where the application was started??

  • I have a similar question regarding your code. I tried it and it works perfectly, but I would like to use GPIO 2_25. I assume I have to use GPIO2ModuleClkConfig() and GPIO2PinMuxSetup. The trouble I have is that there is no GPIO2ModuleClkConfig, it returns an error stating "unresolved symbol ..., first referenced.."

    Any ideas on how to fix this?

    Jack

  • Jack,

    I ran into the same issue.  My solution was to make a local copy in my project, with a different name, of the platform gpio.c and header file which have the gpio1 config,

    then copy/paste/edit the gpio1 function into a gpio2 function, changing the appropriate register names.  While you are at it, you may as well do GPIO3 also.

    Gerry Belanger

  • Hi Jack,

    Presently GPIO2ModuleClkConfig function is not defined in StarterWare.
    That is the reason why you are getting the undefined symbol warning.
    I am  assuming you are using Beaglebone, on that board  the GPIO2_25 Pin is brought out on the P8
    expansion header.
    You can refer to platform/beaglebone/gpio.c file where the GPIO1ModuleClkConfig
    clock config function for GPIO1 is defined you can use this as reference to write
    a clock config for GPIO2 instance. In the CM_PER_GPIO2_CLKCTRL register you can
    enable the functional clocks and set the correct MODULEMODE to enable the GPIO2 instance.

    Alternatively, if you are using the EVM starter kit or GPEVM then you can refer the Clock and PinMux functions

    defined at the following locations platform/<target Board>/gpio.c

    Hope this helps.

    Regards
    Anant Pai

  • Put this in gpio.c

    "

    /*
    ** This function enables the functional clocks for GPIO2 instance.
    */
    void GPIO2ModuleClkConfig(void)
    {
    /* Writing to MODULEMODE field of CM_PER_GPIO1_CLKCTRL register. */
    HWREG(SOC_CM_PER_REGS + CM_PER_GPIO2_CLKCTRL) |=
    CM_PER_GPIO2_CLKCTRL_MODULEMODE_ENABLE;

    /* Waiting for MODULEMODE field to reflect the written value. */
    while(CM_PER_GPIO2_CLKCTRL_MODULEMODE_ENABLE !=
    (HWREG(SOC_CM_PER_REGS + CM_PER_GPIO2_CLKCTRL) &
    CM_PER_GPIO2_CLKCTRL_MODULEMODE));
    /*
    ** Writing to OPTFCLKEN_GPIO_1_GDBCLK bit in CM_PER_GPIO1_CLKCTRL
    ** register.
    */
    HWREG(SOC_CM_PER_REGS + CM_PER_GPIO2_CLKCTRL) |=
    CM_PER_GPIO2_CLKCTRL_OPTFCLKEN_GPIO_2_GDBCLK;

    /*
    ** Waiting for OPTFCLKEN_GPIO_1_GDBCLK bit to reflect the desired
    ** value.
    */
    while(CM_PER_GPIO2_CLKCTRL_OPTFCLKEN_GPIO_2_GDBCLK !=
    (HWREG(SOC_CM_PER_REGS + CM_PER_GPIO2_CLKCTRL) &
    CM_PER_GPIO2_CLKCTRL_OPTFCLKEN_GPIO_2_GDBCLK));

    /*
    ** Waiting for IDLEST field in CM_PER_GPIO1_CLKCTRL register to attain the
    ** desired value.
    */
    while((CM_PER_GPIO2_CLKCTRL_IDLEST_FUNC <<
    CM_PER_GPIO2_CLKCTRL_IDLEST_SHIFT) !=
    (HWREG(SOC_CM_PER_REGS + CM_PER_GPIO2_CLKCTRL) &
    CM_PER_GPIO2_CLKCTRL_IDLEST));

    /*
    ** Waiting for CLKACTIVITY_GPIO_1_GDBCLK bit in CM_PER_L4LS_CLKSTCTRL
    ** register to attain desired value.
    */
    while(CM_PER_L4LS_CLKSTCTRL_CLKACTIVITY_GPIO_2_GDBCLK !=
    (HWREG(SOC_CM_PER_REGS + CM_PER_L4LS_CLKSTCTRL) &
    CM_PER_L4LS_CLKSTCTRL_CLKACTIVITY_GPIO_2_GDBCLK));
    }

    "

    and this 

    "

    extern void GPIO2ModuleClkConfig(void);

    "

    in evmskAM335x.h and beaglebone.h

  • There is a lot of noise in this thread, so I'll try to answer the original question about IRQ-based inputs. This code is working properly for me for initialisation:

    MUX_VAL(CONTROL_PADCONF_LCD_DATA13, (IEN | PD | MODE7 )) // do pin-mux for the GPIO
    GPIODirModeSet(SOC_GPIO_0_REGS,DIN0_IN,GPIO_DIR_INPUT);  // set it as input
    
    IntRegister(SYS_INT_GPIOINT0A, GPIO0Isr); // register an ISR for all GPIs of bank 0
    IntPrioritySet(SYS_INT_GPIOINT0A,20, AINTC_HOSTINT_ROUTE_IRQ); // set IRQ priority
    IntSystemEnable(SYS_INT_GPIOINT0A);                            // enable IRQ
    
    GPIODebounceFuncControl(SOC_GPIO_0_REGS,DIN0_IN,GPIO_DEBOUNCE_FUNC_ENABLE); // optionally set debouncing options
    GPIODebounceTimeConfig(SOC_GPIO_0_REGS,globalConfig.digiDebounceTime);
    GPIOIntTypeSet(SOC_GPIO_0_REGS,DIN0_IN,GPIO_INT_TYPE_BOTH_EDGE);            // define to let the IRQ happen on rising and falling edge of an input signal
    GPIOPinIntEnable(SOC_GPIO_0_REGS,GPIO_INT_LINE_1,DIN0_IN);                  // enable IRQ for this input

    And this is my ISR handling the input data:

    static void GPIO0Isr(void)
    {
       if (fast_GPIOPinIntLine1Status(SOC_GPIO_0_REGS,DIN0_BIT)) // chek if my DIN0_IN is the reason for the interrupt
       {
          if (fast_GPIOPinRead(SOC_GPIO_0_REGS,DIN0_BIT)) ... // do something dependent on its state
          else ...
          fast_GPIOPinIntLine1Clear(SOC_GPIO_0_REGS,DIN0_BIT); // clear the interrupt information
       }
    }

     

    In this example DIN0_IN and DIN0_BIT are defines for the bit to be used:

    #define DIN0_IN  (9)
    #define DIN0_BIT (1<<DIN0_IN)