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.

GPIO interrupt priority using PSP driver with DSP/BIOS

Hi,

On our hardware a GPIO interrupt (bank 5) is used to request a realtime data transfer on the EMIFA bus to an FPGA driving lots of ADCs.

The rate can reach 80kHz.

At present time, some other activities of the DSP software (mainly UDP/ NDK, UART)are causing extra delays on the interrupt response time. I think other interrupts can preempt the GPIO interrupt routine. We are using DSP/BIOS 5.41, NDK2.0, CCS3.3 and PSP 1.30 on a C6747 dsp.

Is it possible to increase the GPIO interrupt priority using PSP driver with DSP/BIOS ?

Do you have any advice ?

Best regards,

Frederic

 

Below is an extract of the TCF file :

/* ECM configuration from PSP drivers documentation*/

bios.HWI.instance("HWI_INT7").interruptSelectNumber = 0;

bios.HWI.instance("HWI_INT8").interruptSelectNumber = 1;

bios.HWI.instance("HWI_INT9").interruptSelectNumber = 2;

bios.HWI.instance("HWI_INT10").interruptSelectNumber = 3;

 

 

And of the C code :

void my_gpio_init(void)
{
  LOG_printf(&trace, "GPIO Initilisation.\n");

    /* Configure GPIO_FPGA_RS# pin as an output */
    UserPinCmdArg.pin = GPIO_FPGA_nRS;
    UserPinCmdArg.value = Gpio_Direction_Output;
    Gpio_setPinDir(hGpio,&UserPinCmdArg);
 
    /* Configure GPIO_FPGA_INT# pin as an input */
    UserPinCmdArg.pin = GPIO_FPGA_nINT;
    UserPinCmdArg.value = Gpio_Direction_Input;
    Gpio_setPinDir(hGpio,&UserPinCmdArg);
 
    /* Reset logiciel du FPGA avant de configurer l'interruption */
    fpga_reset();

    /* Configure GPIO_FPGA_INT# to generate interrupt on falling edge */
    Gpio_setFallingEdgeTrigger(hGpio,GPIO_FPGA_nINT);

    /* Enable GPIO Bank interrupt */
    Gpio_bankInterruptEnable(hGpio,GPIO_BANK_5);

    UserIntrCmdArg.value = GPIO_BANK_5;
    UserIntrCmdArg.bankOrPin = Gpio_BankOrPin_isBank;
    UserIntrCmdArg.isrHandler = (Gpio_Isr)&gpio_isr;
    Gpio_regIntHandler(hGpio,&UserIntrCmdArg);

}

 

int uart_init_ll(void) {
    Uart_init();
    uart_uartParams = Uart_PARAMS;
 
//extrait de Uart.h (pspdrivers_01_30_01\packages\ti\pspiom\uart)
//const struct Uart_Params Uart_PARAMS = {
//    TRUE,                   /* cacheEnable                    */
//    TRUE,                   /* fifoEnable                     */
//    Uart_OpMode_INTERRUPT,  /* opMode                         */
//    FALSE,                  /* loopbackEnabled                */
//    Uart_BaudRate_115_2K,   /* baudRate                       */
//    Uart_NumStopBits_1,     /* stopBits                       */
//    Uart_CharLen_8,         /* charLen                        */
//    Uart_Parity_NONE,       /* parity                         */
//    Uart_RxTrigLvl_14,      /* rxThreshold                    */
//    {                       /* fc                             */
//        Uart_FcType_NONE,
//        Uart_FcParam_NONE
//    },
//    0,                      /* edmaRxTC                       */
//    0,                      /* edmaTxTC                       */
//    0,                      /* hwiNumber                      */
//    0xffffffff,             /* polledModeTimeout              */
//    1,                      /* softTxFifoThreshold            */
//    FALSE,                  /* PSC control disabled           */
//    Uart_pllDomain_0        /* PLL domain used by the driver  */
//};
// 

  //utilisation des interruptions pour la gestion de l'UART 2
    uart_uartParams.hwiNumber = 9;

    uart_uartParams.opMode = Uart_OpMode_INTERRUPT;  
   uart_uartParams.rxThreshold = Uart_RxTrigLvl_1;

  return 0;
}

int usb_init_ll(void) {
    Uart_init();
    usb_uartParams = Uart_PARAMS;
 
//extrait de Uart.h (pspdrivers_01_30_01\packages\ti\pspiom\uart)
//const struct Uart_Params Uart_PARAMS = {
//    TRUE,                   /* cacheEnable                    */
//    TRUE,                   /* fifoEnable                     */
//    Uart_OpMode_INTERRUPT,  /* opMode                         */
//    FALSE,                  /* loopbackEnabled                */
//    Uart_BaudRate_115_2K,   /* baudRate                       */
//    Uart_NumStopBits_1,     /* stopBits                       */
//    Uart_CharLen_8,         /* charLen                        */
//    Uart_Parity_NONE,       /* parity                         */
//    Uart_RxTrigLvl_14,      /* rxThreshold                    */
//    {                       /* fc                             */
//        Uart_FcType_NONE,
//        Uart_FcParam_NONE
//    },
//    0,                      /* edmaRxTC                       */
//    0,                      /* edmaTxTC                       */
//    0,                      /* hwiNumber                      */
//    0xffffffff,             /* polledModeTimeout              */
//    1,                      /* softTxFifoThreshold            */
//    FALSE,                  /* PSC control disabled           */
//    Uart_pllDomain_0        /* PLL domain used by the driver  */
//};
// 

  //utilisation des interruptions pour la gestion de l'UART 0 sur USB
    usb_uartParams.hwiNumber = 8;
 
    usb_uartParams.opMode = Uart_OpMode_INTERRUPT;//Uart_OpMode_POLLED;// 
    usb_uartParams.baudRate = 86616u; 

    usb_uartParams.rxThreshold = Uart_RxTrigLvl_1;

  return 0;
}

  • I haven't reviewed the Gpio driver code, but I suspect that its' interrupt is handled via the ECM module (event combiner).  Each event combiner manages 32 events (4 event groups for 128 total events) and if any of those 32 events fire, a single interrupt is driven to one of the core interrupts.  There are 16 core interrupts, 4 are reserved, so 12 available for app.  The event combiner ISR then reads and loops thru bits set in some register to run whichever interrupts have been fired.

    If this is the case, you can route the Gpio interrupt directly to one of the available core interrupts.  Looks like 7-10 are in use by ECM.  14 is typically used by the timer.   Not sure what the NDK driver is using.  You need to find out which interrupts are not in use and use one of the free ones.   The bits in the IER register map one-to-one with interrupt ids, so if you look at IER, you should be able to determine which interrupts are available.

    Change the Gpio code to use HWI directly (instead of ECM).

    Set the IER mask for the dispatcher to "disable all".  This will make the GPIO interrupt the highest priority.   Default is to only disable "self" so interrupts can preempt one-another.  But if you use "disable all", then the Gpio interrupt will be able to preempt the other interrupt service routines, and it will set the IER register to disable the others so no other ISR can preempt the GPIO interrupt.

    Depending on what other events are on that same event combiner group, you might be able to continue to use ECM and specify that the ISR for that given event group use "disable all".  This will keep other event groups and other interrupts from preempting your GPIO interrupt.

    Hope this makes some sense.

    -Karl-