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/PROCESSOR-SDK-AM437X: PRU to ARM interrupt

Part Number: PROCESSOR-SDK-AM437X

Tool/software: TI-RTOS

In the PRU example PRU_PRUtoARM_Interrupt, It has the code:

void main(){
  uint32_t *pDdr = (uint32_t *) &CT_DDR;
   /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */
  CT_CFG.SYSCFG_bit.STANDBY_INIT = 0;
  // Globally enable host interrupts
  CT_INTC.GER = 0x1;
   /* Clear any pending PRU-generated events */
  __R31 = 0x00000000;
  /* Start preparing message for host - make sure it's not 0xB */
  pDdr[1] = 0x0001;
  /* Enable Host interrupt 2 */
  CT_INTC.HIEISR |= HOST_NUM;
  /* Map channel 2 to host 2 */
  CT_INTC.HMR0_bit.HINT_MAP_2 = HOST_NUM;
  /* Map PRU0_ARM_INTERRUPT (event 19) to channel 2 */
  CT_INTC.CMR4_bit.CH_MAP_19 = CHAN_NUM;
  /* Ensure PRU0_ARM_INTERRUPT is cleared */
  CT_INTC.SICR = (PRU0_ARM_INTERRUPT - 16);
  /* Enable PRU0_ARM_INTERRUPT */
  CT_INTC.EISR = (PRU0_ARM_INTERRUPT - 16);
  /* Ensure CT_DDR (C31) is pointing to start of DDR memory (0x80000000) */
  PRU0_CTRL.CTPPR1_bit.C31_POINTER = 0x0;
  /* Write value of 0xB which Host will read after receiving the interrupt */
  pDdr[1] = 0xB;
  /* Halt the PRU */
  __halt();
}

I have two question:

1.  does which line of code above set the interrupt ? I can find the enable/map/clear  instructions, but I cannot find set one.

2.  if generated  the interrupt, how the host CPU get it?  On the TRM, there are only four pages to describe interrupt table. How to program about interrupt?where can I have the example programm?

  • The RTOS team have been notified. They will respond here.
  • zhuangbin,

    1. To set the interrupt for event 19, need write __R31 = (16 + 19). The details is described in TRM - 30.4.1.2.2 Event Interface Mapping (R31): PRU System Events:
    Simultaneously writing a '1' to pru<n>_r31_vec_valid (R31 bit 5) and a channel number from 0-15 to pru<n>_r31_vec[3:0] (R31 bits 3:0) creates a pulse on the output of the corresponding pr<k>_pru_mst_intr[x]_intr_req INTC system event.

    The output channels 0-15 are connected to the PRU-ICSS INTC system events 16-31, respectively. This allows the PRU to assert one of the system events 16-31 by writing to its own R31 register.

    2. In order to receive the PRU interrupt, the host needs to
    - initialize the INTC using the API PRUICSS_pruIntcInit(handle,&pruss_intc_initdata); where pruss_intc_initdata is the PRUICSS Interrupt controller initialization data structure that contains system event, channel and host mapping.
    - register the interrupt ISR via PRUICSS_registerIrqHandler()
    - clear the event in interrupt ISR

    You can refer to the example code at PDK packages\ti\drv\pruss\test\src\main_test_pruss2_pru0.c
    This thread may help as well - e2e.ti.com/.../689029

    Regards,
    Garrett
  • Hi Garrett,

    Thanks!

    Do you mean that I should add a line of codes:

    __R31=(16+19);

    in the function main above for generating the INTC?

    About how to receive the PRU interrupt, please tell the basic principle? 

  • Hi zhuangbin,

    I think so - you need to trigger the interrupt by writing the event to R31 register.

    Host Interrupts 2 through 9 exported from PRU-ICSS for signaling ARM interrupt controllers or other machines like EDMA. In addition to the point #2 and example code in my previous post, you can refer to the section 'interrupt and tasks" in the wiki processors.wiki.ti.com/.../ICSS_EMAC_LLD_developers_guide , which describes the details of interrupt mapping.

    Regards,
    Garrett
  • Hi,

    the ICSS_EMAC_LLD example is too complex. So I carefully analysis the example dmtimer_app_cdt. I find that it use the driver functions in C:\ti\pdk_am437x_1_0_4\packages\ti\starterware\soc\gic.c. in this file, the function INTCConfigIntr() is used to set the intterupt number and interrupt Handler.

    Am I right?

  • zhuangbin,

    INTCConfigIntr() from Starterware is not recommended. Instead, you can look into the details of the structure definition:

    typedef struct PRUICSS_IntcInitData_s
    {
    /*Enabled SYSEVTs - Range:0..63
    {-1} indicates end of list*/
    int8_t sysevts_enabled[PRUICSS_NUM_PRU_SYS_EVTS];

    /*SysEvt to Channel map. SYSEVTs - Range:0..63 Channels -Range: 0..9
    {-1, -1} indicates end of list*/
    PRUICSS_SysevtToChannelMap sysevt_to_channel_map[PRUICSS_NUM_PRU_SYS_EVTS];

    /*Channel to Host map.Channels -Range: 0..9 HOSTs - Range:0..9
    {-1, -1} indicates end of list*/
    PRUICSS_ChannelToHostMap channel_to_host_map[PRUICSS_NUM_PRU_CHANNELS];

    /*10-bit mask - Enable Host0-Host9 {Host0/1:PRU0/1, Host2..9 : PRUEVT_OUT0..7)*/
    uint32_t host_enable_bitmask
    }PRUICSS_IntcInitData;

    And the API :
    int32_t PRUICSS_registerIrqHandler(PRUICSS_Handle handle,
    uint32_t pruEvtoutNum,
    int32_t intrNum,
    int32_t eventNum,
    uint8_t waitEnable,
    PRUICSSDRV_IRQ_HANDLER irqHandler
    )

    Regards,
    Garrett

  • Hi Garrett,

    I had knowd this pruss interrupt driver. thank you!