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: PRU to R5 interrupt signalling

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

I have created a project based on the "empty_pru_io_am243x-lp_r5fss0-0_freertos_ti-arm_clang" example, I am writing from icssg0 pru0 to msram and want to raise an interrupt from pru to r5 0-0 to signal the data is ready.

I want to be able to write to __R31 in the pru and raise an interrupt in the R5f, I've tried a variety of channels and numbers and have found combinations where the code gets stuck in the interrupt callback pru0_adc_buffer_filled_irq() and others where the interrupt never happens but not a working combination.

Could someone help me with the correct usage of the PRUICSS API and channel setup for the interrupt as I haven't found examples using PRUICSS and ideally it would be nice to understand if the constants in the sysconfig created configuration in icss0_intc_initdata can be used in the PRUICSS_registerIrqHandler() call.

I am using sysconfig to configure intc

Which produces the following intc config

/*
 *  ICSSG0_INTC
 */
PRUICSS_IntcInitData icss0_intc_initdata =
{
    {
        ICSS_INTC_EVENT_19,
        0xFF
    },
    {
        {
            ICSS_INTC_EVENT_19,
            ICSS_INTC_CHANNEL_2,
            SYS_EVT_POLARITY_HIGH,
            SYS_EVT_TYPE_PULSE,
        },
        {0xFF, 0xFF, 0xFF, 0xFF}
    },
    {
        {
            ICSS_INTC_CHANNEL_2,
            ICSS_INTC_HOST_INTR_2
        },
        {0xFF, 0xFF}
    },
    (
        ICSS_INTC_HOST_INTR_2_HOSTEN_MASK
    )
};

And modified R5f code from the example

gPruIcss0Handle = PRUICSS_open(CONFIG_PRU_ICSS0);
load_pru_firmware();

/* ... */

void load_pru_firmware(void *args)
{
     /* ----------------------------------------------------------------- */
     /* Program empty code on PRU Core/s;                                 */
     /* depends on usecase - might have to program multiple cores         */
     /* ----------------------------------------------------------------- */
     /* clear ICSS PRUx data RAM */
     int status;
     status = PRUICSS_initMemory(gPruIcss0Handle, PRUICSS_DATARAM(PRUICSS_PRUx));
     DebugP_assert(status != 0);
     status = PRUICSS_resetCore(gPruIcss0Handle, PRUICSS_PRUx);
     DebugP_assert(SystemP_SUCCESS == status);
     status = PRUICSS_disableCore(gPruIcss0Handle, PRUICSS_PRUx);
     DebugP_assert(SystemP_SUCCESS == status);

     status = PRUICSS_registerIrqHandler(gPruIcss0Handle, 2, 120, 3, 0, &pru0_adc_buffer_filled_irq);
     DebugP_assert(SystemP_SUCCESS == status);
     status = PRUICSS_intcInit(gPruIcss0Handle, &icss0_intc_initdata);
     DebugP_assert(SystemP_SUCCESS == status);

     /* Load firmware. Set buffer = write to Pru memory */
     status = PRUICSS_writeMemory(gPruIcss0Handle, PRUICSS_IRAM_PRU(PRUICSS_PRUx), 0,
                        (uint32_t *) PRUFirmware_0, sizeof(PRUFirmware_0));
     DebugP_assert(status != 0);

     status = PRUICSS_resetCore(gPruIcss0Handle, PRUICSS_PRUx);
     DebugP_assert(SystemP_SUCCESS == status);

     /* Run firmware */
     status = PRUICSS_enableCore(gPruIcss0Handle, PRUICSS_PRUx);
     DebugP_assert(SystemP_SUCCESS == status);
}

On the PRU

#define PRU_ARM_INTERRUPT_PULSE (0x23) /* bit 5 and channel 3, bits 3:0 */
volatile register uint32_t __R31;


/* GPI Mode 0, GPO Mode 0 */
CT_CFG.gpcfg0_reg = 0x00000000;
    
__R31 = PRU_ARM_INTERRUPT_PULSE;

I am not using the PRU IPC module as I am writing 64k-96k of data to the MSRAM with minimal delays, I'd also like to understand how to set up the interrupts.

There's not much else going on so I have extracted the code related to the interrupts, if full code examples are needed let me know.

Thanks for any help you can provide.

  • replying to myself, I believe PRUICSS_registerIrqHandler(gPruIcss0Handle, 2, 120, 3, 0, &pru0_adc_buffer_filled_irq); is incorrect as I've been trying various values after the expected ones didn't work.

  • Hi,

    One issue that I can see is - the interrupt channel-host mapping in PRUICSS_intcInit should be done before registering an Interrupt Handler for the event through PRUICSS_registerIrqHandler.

    You can refer to the sample project attached in this thread: https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers-forum/am2634-fail-to-generate-an-interrupt-from-pru-to-r5f

    As mentioned in the thread, the attached project is based on an older SDK 8.5, please use the code only as a reference for configuring the interrupt, 

    Do let me know if you have any more questions.

    Regards,

    Nitika

  • Hi Nitika Verma,

    Thanks for your input,

    As I can't import the project I copied the code where possible to my own project but the interrupt does not fire, are these lines significant as I don't have the header files required included in my project?

    Pinmux_config(gPinMuxMainDomainCfg_1, PINMUX_DOMAIN_ID_MAIN);
    HW_WR_REG32(CSL_MSS_CTRL_U_BASE + CSL_MSS_CTRL_ICSSM_PRU0_GPIO_OUT_CTRL, MSS_CTRL_ICSSM_PRU_GPIO_OUT_CTRL_VALUE);
    HW_WR_REG32(CSL_MSS_CTRL_U_BASE + CSL_MSS_CTRL_ICSSM_PRU1_GPIO_OUT_CTRL, MSS_CTRL_ICSSM_PRU_GPIO_OUT_CTRL_VALUE);
    SOC_selectIcssGpiMux(0, 0x0);

    Sysconfig has been changed so it produces icss0_intc_initdata the same as the example

    PRUICSS_IntcInitData icss0_intc_initdata =
    {
        {
            ICSS_INTC_EVENT_16,
            0xFF
        },
        {
            {
                ICSS_INTC_EVENT_16,
                ICSS_INTC_CHANNEL_2,
                SYS_EVT_POLARITY_HIGH,
                SYS_EVT_TYPE_PULSE,
            },
            {0xFF, 0xFF, 0xFF, 0xFF}
        },
        {
            {
                ICSS_INTC_CHANNEL_2,
                ICSS_INTC_HOST_INTR_2
            },
            {0xFF, 0xFF}
        },
        (
            ICSS_INTC_HOST_INTR_2_HOSTEN_MASK
        )
    };


         int status;
    
         gPruIcss0Handle = PRUICSS_open(CONFIG_PRU_ICSS0);
         DebugP_assert(gPruIcss0Handle != NULL);
         status = PRUICSS_intcInit(gPruIcss0Handle, &icss0_intc_initdata);
         DebugP_assert(SystemP_SUCCESS == status);
    
         status = PRUICSS_initMemory(gPruIcss0Handle, PRUICSS_DATARAM(PRUICSS_PRUx));
         DebugP_assert(status != 0);
         status = PRUICSS_resetCore(gPruIcss0Handle, PRUICSS_PRUx);
         DebugP_assert(SystemP_SUCCESS == status);
         status = PRUICSS_disableCore(gPruIcss0Handle, PRUICSS_PRUx);
         DebugP_assert(SystemP_SUCCESS == status);
    
         /* Load firmware. Set buffer = write to Pru memory */
         status = PRUICSS_writeMemory(gPruIcss0Handle, PRUICSS_IRAM_PRU(PRUICSS_PRUx), 0,
                            (uint32_t *) PRUFirmware_0, sizeof(PRUFirmware_0));
         DebugP_assert(status != 0);
    
         status = PRUICSS_resetCore(gPruIcss0Handle, PRUICSS_PRUx);
         DebugP_assert(SystemP_SUCCESS == status);
         status = PRUICSS_enableCore(gPruIcss0Handle, PRUICSS_PRUx);
         DebugP_assert(SystemP_SUCCESS == status);
    
         int32_t                  pruEvtoutNum = 0 ; /*PRU_ICSSG0_PR1_HOST_INTR_PEND_0*/
         int32_t                  r5fIntrNum = 0;
    
         status = PRUICSS_registerIrqHandler(gPruIcss0Handle,
                                        pruEvtoutNum,  /*  pruEvtoutNum PRU_ICSSG0_PR1_HOST_INTR_PEND_0 = 0, .... PRU_ICSSG0_PR1_HOST_INTR_PEND_7 = 7 */
                                        r5fIntrNum,    /*  r5fIntrNum   corresponding r5f input interrupt line */
                                        1,            /*  eventNum(Do not care)*/
                                        0,            /*  wait_enable  */
                                        PRU_R5f_Intrhandler);
         if (status == SystemP_SUCCESS)
         {
             DebugP_log("Registered PRU Interrupt Handler");
         }
         else
         {
             DebugP_log("PRU Interrupt Handler Registration failed");
         }
    
         DebugP_assert(SystemP_SUCCESS == status);

    void PRU_R5f_Intrhandler(void *args)
    {
        int32_t intc_event_num = 16;
        irq_count++;
        PRUICSS_clearEvent(gPruIcss0Handle, intc_event_num); /*INTC Event number(16 to 32)*/
    }

  • Thanks for the help Nitika Verma, I have yet to change interrupt number or count the raised events but it appears to work following the layout of your example code but changing the R5f event number from 0 in the example to 120 as mentioned in a comment in my code.

    Nitika Verma example icss_intc_defines.h (PRU_ICSSG0_PR1_HOST_INTR_PEND_0 = 0)

    /**
     *  @brief AM64x - R5F core interrupt mapping
     *
     *  Interrupt Input           |  Line |  Interrupt ID Source Interrupt
     *  =====================================================================
     *  R5FSS0_CORE0_INTR_IN_0  |  0  |  PRU_ICSSG0_PR1_HOST_INTR_PEND_0
     *  R5FSS0_CORE0_INTR_IN_1  |  1  |  PRU_ICSSG0_PR1_HOST_INTR_PEND_1
     *  R5FSS0_CORE0_INTR_IN_2  |  2  |  PRU_ICSSG0_PR1_HOST_INTR_PEND_2
     *  R5FSS0_CORE0_INTR_IN_3  |  3  |  PRU_ICSSG0_PR1_HOST_INTR_PEND_3
     *  R5FSS0_CORE0_INTR_IN_4  |  4  |  PRU_ICSSG0_PR1_HOST_INTR_PEND_4
     *  R5FSS0_CORE0_INTR_IN_5  |  5  |  PRU_ICSSG0_PR1_HOST_INTR_PEND_5
     *  R5FSS0_CORE0_INTR_IN_6  |  6  |  PRU_ICSSG0_PR1_HOST_INTR_PEND_6
     *  R5FSS0_CORE0_INTR_IN_7  |  7  |  PRU_ICSSG0_PR1_HOST_INTR_PEND_7
     */

    am243x sdk example icss_intc_defines.c (PRU_ICSSG0_PR1_HOST_INTR_PEND_0 = 120)

    /**
     *  @brief AM64x - R5F core interrupt mapping
     *
     *  Interrupt Input           |  Line |  Interrupt ID Source Interrupt
     *  =====================================================================
     *  R5FSS0_CORE0_INTR_IN_120  |  120  |  PRU_ICSSG0_PR1_HOST_INTR_PEND_0
     *  R5FSS0_CORE0_INTR_IN_121  |  121  |  PRU_ICSSG0_PR1_HOST_INTR_PEND_1
     *  R5FSS0_CORE0_INTR_IN_122  |  122  |  PRU_ICSSG0_PR1_HOST_INTR_PEND_2
     *  R5FSS0_CORE0_INTR_IN_123  |  123  |  PRU_ICSSG0_PR1_HOST_INTR_PEND_3
     *  R5FSS0_CORE0_INTR_IN_124  |  124  |  PRU_ICSSG0_PR1_HOST_INTR_PEND_4
     *  R5FSS0_CORE0_INTR_IN_125  |  125  |  PRU_ICSSG0_PR1_HOST_INTR_PEND_5
     *  R5FSS0_CORE0_INTR_IN_126  |  126  |  PRU_ICSSG0_PR1_HOST_INTR_PEND_6
     *  R5FSS0_CORE0_INTR_IN_127  |  127  |  PRU_ICSSG0_PR1_HOST_INTR_PEND_7
     *  ---------------------------------------------------------------------