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.

Can't get some IRQs working on AM5728



I am using evmAM5728 board and SDK 03.00.00.04.

First, there seem to be two issues with IRQHandler in CSL.

To acknowledge the interrupt, interrupt ID must be written to EOIR and this is what IRQHandler is trying to do by

        LDMFD    r13!, {r2}               @ Get active IRO from stack
        LDR      r1, =addrEoi             @ Load global variable addrEoi address into r1
        LDR      r2, [r1]                 @ Acknowledge the current IRQ
        STR      r3, [r2]

But third and fourth instructions are wrong, they should be
        LDR      r3, [r1]                 @ Acknowledge the current IRQ
        STR      r2, [r3]


Another problem is that number of pushed registers on IRQ stack is odd. First it pushes
        STMFD    r13!, {r0-r3, r12, r14}  @ Save context in IRQ stack
and later
        STMFD    r13!, {r2}               @ Save active IRO in stack

It is against AAPCS, which demands stack pointer to be 8-bytes aligned.

I've fixed these bugs locally. Now, the issue I have a real problem with.

I am trying to map RTC interrupt to GIC. For most IRQ numbers it works fine, but for some of them IRQ never fires, although IRQ is reported pending.
I was trying IRQ numbers 4-159. Here is the list of IRQs, which don't work (IRQ never fires). Some of them are reported pending, some are not.

5, 6, 10 - not pending
16-19 - pending
32-35 - pending
48-51 - pending
64-67 - pending
80-83 - pending
131-133 - not pending
139-142 - not pending

Per MPU_INTC Default Interrupt Mapping (spruhz6g.pdf):
IRQs 5 and 6 are N/A.
IRQ 10 is "not functional", whatever it means.
IRQs 131 and 132 are N/A.
IRQ 133 is available, but has some special considerations.
IRQs 139 and 140 are N/A.

Other IRQs (16-19, 32-35, 48-51, 64-67, 80-83, 141, 142) seem to be normal IRQs, but they don't work for me. For IRQs 141 and 142 pending flag is not set, so problem occurs between crossbar and GIC. For all other IRQs interrupt reaches GIC (pending flag on), but, apparently, is not delivered to CPU interface, I don't know why.

I am attaching the test code, which tries all IRQs from 4 to 159 and outputs the results of checkup. Also I am attaching my output log.
I am not using csl_init library in my project and do my own initialization, which is present in main.c. But I am using CSL's init.asm and exceptionhandler.asm (with my bugfixes).

What do I do improperly with these IRQs?

  • https://e2e.ti.com/cfs-file/__key/communityserver-discussions-components-files/791/irq_5F00_test.7z

  • Hi,

    I will forward this to the software team. They will respond directly here.
  • Hi John,

    John D97 said:
    I am using evmAM5728 board and SDK 03.00.00.04.

    First, there seem to be two issues with IRQHandler in CSL

    Do you mean that you are using CSL (Chip Support Library) with AM572x device? From where you get this CSL?

    We have also IRQHandler in SDK 03.00.00.04 which has the same format as in the CSL:

    ti-processor-sdk-linux-am57xx-evm-03.00.00.04/linux-devkit/sysroots/cortexa15hf-neon-linux-gnueabi/usr/share/ti/ti-pdk-tree/packages/ti/csl/arch/a15/src/exceptionhandler.asm

    John D97 said:
    I am trying to map RTC interrupt to GIC. For most IRQ numbers it works fine, but for some of them IRQ never fires, although IRQ is reported pending.

    The first step of enabling RTC interrupt is to program the RTC interrupt registers. Note that AM572x RTC has only one interrupt (RTC_SS_IRQ_ALARM) which goes to IRQ_CROSSBAR_217. The timer and alarm interrupts are  OR-ed inside the RTC subsystem and a single interrupt (RTC_SS_IRQ_ALARM)
    is passed to the IRQ_CROSSBAR module. To enable RTC interrupts, RTC_INTERRUPTS_REG is used. The timer interrupt and alarm interrupt can be controlled using this register. You can then check the RTC_STATUS_REG bits if you really have interrupts generated.

    First verify that you have interrupts generated inside the RTC, then we can proceed to IRQ_CROSSBAR config.

    Regards,
    Pavel 




  • I am using CSL, which is a part of AM57x PDK for TI-RTOS, version 03.00.00.04. I do bare metal programming.

    I forgot to say that function CSL_xbarMpuIrqConfigure() from CSL was also incorrect and I hope I fixed it. This how it looks now, please check. Seems like now it matches the datasheet.

    void CSL_xbarMpuIrqConfigure(Uint32 irqNumIdx, CSL_XbarIrq xbarIrq)
    {
        CSL_control_intr_dmaRegs *ctrlCoreIntrDmaReg =
            (CSL_control_intr_dmaRegs *) CSL_MPU_IRQ_DMARQ_CROSSBAR_REGISTERS_REGS;
        CSL_control_coreRegs *ctrlCoreReg =
            (CSL_control_coreRegs *) CSL_MPU_CTRL_MODULE_CORE_CORE_REGISTERS_REGS;
    
        /*
            "Crossbarable" MPU IRQs are 4..159, except 5, 6, 131, 132, 139, 140
        */
    
        if ((irqNumIdx < 4) || (irqNumIdx > 159))
        {
            return;
        }
    
        Uint32 regIdx;
        Uint32 regLsb;
    
        switch (irqNumIdx)
        {
        case 4:
        case 7:
            regIdx = 0;
            regLsb = (irqNumIdx == 4) ? 0 : 16;
            break;
        case 5:
        case 6:
        /*case 10:*/
        case 131:
        case 132:
        case 139:
        case 140:
            /* IRQ is N/A */
            return;
        default:
            regIdx = 1 + (irqNumIdx - 8) / 2;
            regLsb = (irqNumIdx & 1) ? 16 : 0;
        }
    
        Uint32 regMsb = regLsb + 16U;
    
        if((CSL_XBAR_IRQ_MIN < xbarIrq) && (CSL_XBAR_IRQ_MAX > xbarIrq))
        {
            ctrlCoreReg->MMR_LOCK_2 = 0xF757FDC0U;
            CSL_FINSR(ctrlCoreIntrDmaReg->MPU_IRQ[regIdx],
                regMsb, regLsb, xbarIrq);
            ctrlCoreReg->MMR_LOCK_2 = 0xFDF45530U;
        }
    }
    

    I think I set up RTC registers properly. Otherwise no IRQ would ever fire.

    Pavel Botev said:
    Note that AM572x RTC has only one interrupt (RTC_SS_IRQ_ALARM) which goes to IRQ_CROSSBAR_217. The timer and alarm interrupts are  OR-ed inside the RTC subsystem and a single interrupt (RTC_SS_IRQ_ALARM) is passed to the IRQ_CROSSBAR module.

    This seems to be an error in datasheet, but, thankfully, CSL contains the proper definitions.
    CSL provides two literals for RTC IRQs: CSL_XBAR_RTC_SS_IRQ_TIMER (216) and CSL_XBAR_RTC_SS_IRQ_ALARM (217). When I tried to use CSL_XBAR_RTC_SS_IRQ_ALARM, nothing worked at all. So, I am using CSL_XBAR_RTC_SS_IRQ_TIMER, which is not what datasheet says, but in accordance to what CSL suggests. With CSL_XBAR_RTC_SS_IRQ_TIMER it works for most IRQs.

    I updated the test so now it outputs more detail log, let me put here part of its output:
                                        ICDISPR6 ICDISPR5 ICDISPR4 ICDISPR3 ICDISPR2 ICDISPR1 ICDISPR0
    irq_idx =   4, fired = 1, pending = 00000000 00000000 00000000 00000000 00000000 00000000 00000000 ICDISER1 = 00000010
    irq_idx =   5, fired = 0, pending = 00000000 00000000 00000000 00000000 00000000 00000000 00000000 ICDISER1 = 00000020
    irq_idx =   6, fired = 0, pending = 00000000 00000000 00000000 00000000 00000000 00000000 00000000 ICDISER1 = 00000040
    irq_idx =   7, fired = 1, pending = 00000000 00000000 00000000 00000000 00000000 00000000 00000000 ICDISER1 = 00000080
    irq_idx =   8, fired = 1, pending = 00000000 00000000 00000000 00000000 00000000 00000000 00000000 ICDISER1 = 00000100
    irq_idx =   9, fired = 1, pending = 00000000 00000000 00000000 00000000 00000000 00000000 00000000 ICDISER1 = 00000200
    irq_idx =  10, fired = 0, pending = 00000000 00000000 00000000 00000000 00000000 00000000 00000000 ICDISER1 = 00000400
    irq_idx =  11, fired = 1, pending = 00000000 00000000 00000000 00000000 00000000 00000000 00000000 ICDISER1 = 00000800
    irq_idx =  12, fired = 1, pending = 00000000 00000000 00000000 00000000 00000000 00000000 00000000 ICDISER1 = 00001000
    irq_idx =  13, fired = 1, pending = 00000000 00000000 00000000 00000000 00000000 00000000 00000000 ICDISER1 = 00002000
    irq_idx =  14, fired = 1, pending = 00000000 00000000 00000000 00000000 00000000 00000000 00000000 ICDISER1 = 00004000
    irq_idx =  15, fired = 1, pending = 00000000 00000000 00000000 00000000 00000000 00000000 00000000 ICDISER1 = 00008000
    irq_idx =  16, fired = 0, pending = 00000000 00000000 00000000 00000000 00000000 00010000 00000000 ICDISER1 = 00010000
    irq_idx =  17, fired = 0, pending = 00000000 00000000 00000000 00000000 00000000 00030000 00000000 ICDISER1 = 00020000
    irq_idx =  18, fired = 0, pending = 00000000 00000000 00000000 00000000 00000000 00070000 00000000 ICDISER1 = 00040000
    irq_idx =  19, fired = 0, pending = 00000000 00000000 00000000 00000000 00000000 000f0000 00000000 ICDISER1 = 00080000
    irq_idx =  20, fired = 1, pending = 00000000 00000000 00000000 00000000 00000000 000f0000 00000000 ICDISER1 = 00100000
    irq_idx =  21, fired = 1, pending = 00000000 00000000 00000000 00000000 00000000 000f0000 00000000 ICDISER1 = 00200000

    IRQs 5, 6, 10 do not fire, because they are N/A or "not functional" per datasheet.

    But IRQs 16-19 are supposed to work. And they are pending, which means they passed through crossbar. And they are enabled.
    So, for 16-19 IRQ is enabled (ICDISER1 shows it) and pending (ICDISPR1 shows it). Why these interrupts do not fire?

  • John D97 said:
    I am using CSL, which is a part of AM57x PDK for TI-RTOS, version 03.00.00.04.

    So you are using ti-processor-sdk-rtos-am57xx-evm-03.00.00.04

    John D97 said:
    I forgot to say that function CSL_xbarMpuIrqConfigure() from CSL was also incorrect and I hope I fixed it

    Can you be more specific about what error you have found in this CSL_xbarMpuIrqConfigure() function?

    pdk_am57xx_1_0_3/packages/ti/csl/soc/am572x/src/csl_device_xbar.c

    I see this function is used for the RTC test below.

    pdk_am57xx_1_0_3/packages/ti/csl/test/rtc/am572x/armv7/rtc_main.c

    John D97 said:
    This how it looks now, please check.

    Looks fine to me, but I didn't test it.

    John D97 said:
    This seems to be an error in datasheet, but, thankfully, CSL contains the proper definitions.
    CSL provides two literals for RTC IRQs: CSL_XBAR_RTC_SS_IRQ_TIMER (216) and CSL_XBAR_RTC_SS_IRQ_ALARM (217). When I tried to use CSL_XBAR_RTC_SS_IRQ_ALARM, nothing worked at all. So, I am using CSL_XBAR_RTC_SS_IRQ_TIMER, which is not what datasheet says, but in accordance to what CSL suggests. With CSL_XBAR_RTC_SS_IRQ_TIMER it works for most IRQs.

    Yes, that might be error in the AM572x TRM. I will check this with the RTC expert and come back to you when I have something more.

    John D97 said:
    But IRQs 16-19 are supposed to work. And they are pending, which means they passed through crossbar. And they are enabled.
    So, for 16-19 IRQ is enabled (ICDISER1 shows it) and pending (ICDISPR1 shows it). Why these interrupts do not fire?

    What do you mean by "do not fire"? What values you have programmed there in these registers? Have you check if some SW is overwriting your settings there?

    MPU_IRQ_16 (ID48)   IRQ_CROSSBAR_11  CTRL_CORE_MPU_IRQ_16_17[8:0]

    MPU_IRQ_17 (ID49)   IRQ_CROSSBAR_12  CTRL_CORE_MPU_IRQ_16_17[24:16]

    MPU_IRQ_18 (ID50)   IRQ_CROSSBAR_13  CTRL_CORE_MPU_IRQ_18_19[8:0]

    MPU_IRQ_19 (ID51)   IRQ_CROSSBAR_14  CTRL_CORE_MPU_IRQ_18_19[24:16]

    Regards,
    Pavel

  • Pavel Botev said:
    Can you be more specific about what error you have found in this CSL_xbarMpuIrqConfigure() function?

    Can you be more specific about what error you have found in this CSL_xbarMpuIrqConfigure() function?

    This is the original function:

    void CSL_xbarMpuIrqConfigure(Uint32 irqNumIdx, CSL_XbarIrq xbarIrq)
    {
        CSL_control_intr_dmaRegs *ctrlCoreIntrDmaReg =
            (CSL_control_intr_dmaRegs *) CSL_MPU_IRQ_DMARQ_CROSSBAR_REGISTERS_REGS;
        CSL_control_coreRegs *ctrlCoreReg =
            (CSL_control_coreRegs *) CSL_MPU_CTRL_MODULE_CORE_CORE_REGISTERS_REGS;
        Uint32 regIdx = (irqNumIdx - 1U) / 2U;
        Uint32 regLsb = (((irqNumIdx - 1U) % 2U) * 16U);
        Uint32 regMsb = regLsb + 16U;
    
        if((CSL_XBAR_IRQ_MIN < xbarIrq) && (CSL_XBAR_IRQ_MAX > xbarIrq))
        {
            if ((0U < irqNumIdx) && (CSL_MPU_IRQ_XBAR_COUNT >= irqNumIdx))
            {
                ctrlCoreReg->MMR_LOCK_2 = 0xF757FDC0U;
                CSL_FINSR(ctrlCoreIntrDmaReg->MPU_IRQ[regIdx],
                    regMsb, regLsb, xbarIrq);
                ctrlCoreReg->MMR_LOCK_2 = 0xFDF45530U;
            }
        }
    }
    

    Mapping per this original erroneous function:
    MPU_IRQ[0] - 1 and 2
    MPU_IRQ[1] - 3 and 4
    MPU_IRQ[2] - 5 and 6
    and etc..

    Mapping per datasheet:
    MPU_IRQ[0] - 4 and 7
    MPU_IRQ[1] - 8 and 9
    MPU_IRQ[2] - 10 and 11
    and etc..

  • I found the problem with IRQs 16..19, 32..35, 48..51, 64..67, 80..83. CSL's function Intc_IntPrioritySet() is screwed up.

    For whatever reason, these IRQs have default priorities f0 rather than 0 for other IRQs. I was setting interrupt priorities to 0, but, as I said, function Intc_IntPrioritySet() has two bugs. It calculates IPR's indices improperly, which was the reason why some IRQs did not fire. It has additional problem - it changes entire IPRx rather than only desired field in it.

    I hope I fixed this function as well:

    Original version:

    void Intc_IntPrioritySet(uint16_t intrNum, uint16_t priority,
                             uint8_t hostIntRoute)
    {
        uint32_t index, mask;
    
        if (intrNum < NUM_INTERRUPTS_EXTERNAL)
        {
            index = ((uint32_t) intrNum >> 2) + 1U;
            mask  = (uint32_t) intrNum % 4U;
    
            /*Sets the priority of shared peripheral interrupt*/
            HW_WR_REG32(SOC_INTC_MPU_DISTRIBUTOR_BASE +
                        (MPU_GICD_IPR0 + (NUM_BYTES_REG * index)),
                        ((priority & (uint32_t) 0xFF) << (mask * 8U)));
        }
    }
    

    Fixed version:

    void Intc_IntPrioritySet(uint16_t intrNum, uint16_t priority,
                             uint8_t hostIntRoute)
    {
        uint32_t index, lsb;
    
        if (intrNum < NUM_INTERRUPTS_EXTERNAL)
        {
            index = ((uint32_t) intrNum >> 2) + 8U;
            lsb = (intrNum & 0x3) << 3; // 0, 8, 16, 24
    
            /*Sets the priority of shared peripheral interrupt*/
            uint32_t* ipr = (uint32_t*)(SOC_INTC_MPU_DISTRIBUTOR_BASE + (MPU_GICD_IPR0 + (NUM_BYTES_REG * index)));
            uint32_t ipr_value = *ipr;
            ipr_value &= ~(0xffu << lsb);
            ipr_value |= ((priority & 0xffu) << lsb);
            *ipr = ipr_value;
        }
    }
    

    Now the following IRQs do not work:

    5 - N/A per datasheet
    6 - N/A per datasheet
    10 - "not functional" per datasheet

    131 - N/A per datasheet
    132 - N/A per datasheet
    133 - has special considerations per datasheet
    134 -

    139 - N/A per datasheet
    140 - N/A per datasheet
    141 -
    142 -

    So, the real problem is with 133 (probably), 134, 141 and 142.
    I suspect that datasheet is wrong again and MPU_IRQ registers skip some N/A IRQs (like they do it with 5 and 6), because starting from 133, IRQ pending flags start to go off their expected positions. Can you please verify it?

  • Oops, I found it. Datasheet is correct, I am blind. 131 and 132 are skipped, but 139 and 140 are not. This is the updated version of CSL_xbarMpuIrqConfigure(). Now all "normal" IRQs do fire, except for 133, which might be OK, as long as it is not entirely normal.

    void CSL_xbarMpuIrqConfigure(Uint32 irqNumIdx, CSL_XbarIrq xbarIrq)
    {
        CSL_control_intr_dmaRegs *ctrlCoreIntrDmaReg =
            (CSL_control_intr_dmaRegs *) CSL_MPU_IRQ_DMARQ_CROSSBAR_REGISTERS_REGS;
        CSL_control_coreRegs *ctrlCoreReg =
            (CSL_control_coreRegs *) CSL_MPU_CTRL_MODULE_CORE_CORE_REGISTERS_REGS;
    
        /*
            "Crossbarable" MPU IRQs are 4..159, except 5, 6, 131, 132, 139, 140
        */
    
        Uint32 regIdx;
        Uint32 regLsb;
    
        if ((irqNumIdx == 4) || (irqNumIdx == 7))
        {
            regIdx = 0;
            regLsb = (irqNumIdx == 4) ? 0 : 16;
        }
        else if ((8 <= irqNumIdx) && (irqNumIdx <= 130))
        {
            regIdx = 1 + (irqNumIdx - 8) / 2;
            regLsb = (irqNumIdx & 1) ? 16 : 0;
        }
        else if ((133 <= irqNumIdx) && (irqNumIdx <= 159))
        {
            if ((irqNumIdx == 139) || (irqNumIdx == 140))
            {
                return;
            }
            regIdx = 62 + (irqNumIdx - 132) / 2;
            regLsb = (irqNumIdx & 1) ? 16 : 0;
        }
        else
        {
            return;
        }
    
        Uint32 regMsb = regLsb + 16U;
    
        if ((CSL_XBAR_IRQ_MIN <= xbarIrq) && (CSL_XBAR_IRQ_MAX > xbarIrq))
        {
            ctrlCoreReg->MMR_LOCK_2 = 0xF757FDC0U;
            CSL_FINSR(ctrlCoreIntrDmaReg->MPU_IRQ[regIdx],
                regMsb, regLsb, xbarIrq);
            ctrlCoreReg->MMR_LOCK_2 = 0xFDF45530U;
        }
    }
    

  • John,

    I am glad to see that you made it work correct.

    Regarding AM572x TRM update (RTC common irq to be 216 instead of 217), you can submit a ticket to the TRM team with click on the "Submit Documentation Feedback" button, which is located at the left bottom corner of each page of the AM572x TRM SPRUHZ6G.

    Regarding AM572x RTOS update (functions CSL_xbarMpuIrqConfigure() and Intc_intPrioritySet() ) the RTOS expert has been notified regarding this e2e thread.

    Just to note that there are another RTOS functions which configures the xbar, you might be interested to look at:

    pdk_am57xx_1_0_3/packages/ti/csl/soc/common/csl_device_xbar.c -> CSL_xbarIrqConfigure()

    pdk_am57xx_1_0_3/packages/ti/csl/soc/am572x/src/csl_device_xbar.c -> CSL_xbarIrqConfigure()

    Regards,
    Pavel