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.

AM5728: Crossbar and INTC configuration

Part Number: AM5728

I'm trying to configure TIMER8 IRQ to CSL_XBAR_INST_MPU_IRQ_134, on A15 core 0.

For some reason the setup fails on the first time, but after setting up the TIMER8 to another XBAR_INST it suddenly works ok.

I can't figure out what is the problem here. It's not a good idea to reconfigure the interrupt in the final application, so the config should be made right on the first time. What do I need to do to make it work?

Attached is a simplified application showing the problem. It's first registering to XBAR_INST_134, which doesn't work. After seeing the IRQ flag 5 times the app reconfigures timer IRQ to it to XBAR_INST_130. After some delay reqonfigurint to XBAR_INST_134, and now it works correctly.

It's loosely based on Vitaly Andrianov's ti-app.c, which was an interrupt latency measurement application.

Also, here is the UART console output:

Board initialized:
Hey, I'm working !!!!!!!!!!!
Configuring interrupt. xbar inst: 127(intcnum 134)
timer id
IRQ flag on - clearing IRQ

IRQ flag on - clearing IRQ

IRQ flag on - clearing IRQ

IRQ flag on - clearing IRQ

IRQ flag on - clearing IRQ

IRQ flag on - clearing IRQ

Reconfiguring interrupt. xbar inst: 125(intcnum 130)
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Reconfiguring interrupt. xbar inst: 127(intcnum 134)
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

**** Build of configuration Debug for project crossbartest ****

"C:\\ti\\ccs910\\ccs\\utils\\bin\\gmake" -k -j 8 all -O 
 
Building file: "../myStartup.S"
Invoking: GNU Compiler
"C:/ti/ccs910/ccs/tools/compiler/gcc-arm-none-eabi-7-2017-q4-major-win32/bin/arm-none-eabi-gcc.exe" -c -mcpu=cortex-a15 -mtune=cortex-a15 -marm -mfloat-abi=hard -mfpu=neon-vfpv4 -DSOC_AM572x -Dam5728 -Dcore0 -I"C:/ti/pdk_am57xx_1_0_13/packages" -I"C:/ProjDir/CCS9_ws/crossbartest" -I"C:/ti/ccs910/ccs/tools/compiler/gcc-arm-none-eabi-7-2017-q4-major-win32/arm-none-eabi/include" -Og -g -gdwarf-3 -gstrict-dwarf -Wall -specs="nosys.specs" -MMD -MP -MF"myStartup.d" -MT"myStartup.o" -x assembler-with-cpp  -o"myStartup.o" "../myStartup.S"
Finished building: "../myStartup.S"
 
Building file: "../main.c"
Invoking: GNU Compiler
"C:/ti/ccs910/ccs/tools/compiler/gcc-arm-none-eabi-7-2017-q4-major-win32/bin/arm-none-eabi-gcc.exe" -c -mcpu=cortex-a15 -mtune=cortex-a15 -marm -mfloat-abi=hard -mfpu=neon-vfpv4 -DSOC_AM572x -Dam5728 -Dcore0 -I"C:/ti/pdk_am57xx_1_0_13/packages" -I"C:/ProjDir/CCS9_ws/crossbartest" -I"C:/ti/ccs910/ccs/tools/compiler/gcc-arm-none-eabi-7-2017-q4-major-win32/arm-none-eabi/include" -Og -g -gdwarf-3 -gstrict-dwarf -Wall -specs="nosys.specs" -MMD -MP -MF"main.d" -MT"main.o"   -o"main.o" "../main.c"
Finished building: "../main.c"
 
Building file: "../ti-app.c"
Invoking: GNU Compiler
"C:/ti/ccs910/ccs/tools/compiler/gcc-arm-none-eabi-7-2017-q4-major-win32/bin/arm-none-eabi-gcc.exe" -c -mcpu=cortex-a15 -mtune=cortex-a15 -marm -mfloat-abi=hard -mfpu=neon-vfpv4 -DSOC_AM572x -Dam5728 -Dcore0 -I"C:/ti/pdk_am57xx_1_0_13/packages" -I"C:/ProjDir/CCS9_ws/crossbartest" -I"C:/ti/ccs910/ccs/tools/compiler/gcc-arm-none-eabi-7-2017-q4-major-win32/arm-none-eabi/include" -Og -g -gdwarf-3 -gstrict-dwarf -Wall -specs="nosys.specs" -MMD -MP -MF"ti-app.d" -MT"ti-app.o"   -o"ti-app.o" "../ti-app.c"
Finished building: "../ti-app.c"
 
Building target: "crossbartest.out"
Invoking: GNU Linker
"C:/ti/ccs910/ccs/tools/compiler/gcc-arm-none-eabi-7-2017-q4-major-win32/bin/arm-none-eabi-gcc.exe" -mtune=cortex-a15 -marm -DSOC_AM572x -Dam5728 -Dcore0 -Og -g -gdwarf-3 -gstrict-dwarf -Wall -specs="nosys.specs" -mfloat-abi=hard -Wl,-Map,"crossbartest.map" --entry _entry -nostartfiles -static -Wl,--gc-sections -L"C:/ti/pdk_am57xx_1_0_13/packages/ti/drv/gpio/lib/a15/release/" -L"C:/ti/pdk_am57xx_1_0_13/packages/ti/osal/lib/nonos/am572x/a15/release/" -L"C:/ti/pdk_am57xx_1_0_13/packages/ti/csl/lib/am572x/a15/release/" -L"C:/ti/pdk_am57xx_1_0_13/packages/ti/csl/example/utils/common/lib/am572x/a15/release" -L"C:/ti/pdk_am57xx_1_0_13/packages/ti/board/lib/evmAM572x/a15/release" -L"C:/ti/pdk_am57xx_1_0_13/packages/ti/drv/i2c/lib/am572x/a15/release" -L"C:/ti/pdk_am57xx_1_0_13/packages/ti/drv/uart/lib/am572x/a15/release/" -Wl,--defsym,CORE0=1 -Wl,--defsym,STACKSIZE=0x10000 -Wl,--defsym,HEAPSIZE=0x10000 -o"crossbartest.out" "./main.o" "./myStartup.o" "./ti-app.o" -Wl,-T"../AM572x.lds"  -Wl,--start-group -l:ti.board.aa15fg -l:ti.drv.uart.aa15fg -l:csl_utils_common.aa15fg -l:ti.drv.gpio.aa15fg -l:ti.drv.i2c.aa15fg -l:ti.csl.init.aa15fg -l:ti.csl.aa15fg -l:ti.osal.aa15fg -lnosys -lrdimon -lm -lgcc -lc -Wl,--end-group 
Finished building target: "crossbartest.out"
 
C:/ProjDir/CCS9_ws/crossbartest\createsdbootable.bat C:/ti/pdk_am57xx_1_0_13 C:/ProjDir/CCS9_ws/crossbartest/Debug/crossbartest.out C:/ProjDir/CCS9_ws/crossbartest/Debug\app
Converting .out file into SD Bootable file... 
Copy the "app" file into SD card containing MLO (Secondary bootloader) and the app should be loaded.
Parsing the input object file, C:/ProjDir/CCS9_ws/crossbartest/Debug/crossbartest.out.
File conversion complete!
Number of Input Files 1
 
 

**** Build Finished ****

ti-app.c:

/*
 * Copyright (c) Texas Instruments, Inc 2016
 *
 * Authors:
 *  Vitaly Andrianov <vitalya@ti.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2.  See
 * the COPYING file in the top-level directory.
 */
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <ti/board/board.h>
#include <ti/drv/uart/UART_stdio.h>
#include <ti/csl/soc.h>
#include <ti/csl/arch/a15/interrupt.h>
#include <ti/csl/csl_timer.h>

#define INTERVAL 1000 // 10 ms
#define RELOAD	 (0xffffffff - INTERVAL)
#define XBAR_CPU                        (CSL_XBAR_IRQ_CPU_ID_MPU)
#define XBAR_INST                       (CSL_XBAR_INST_MPU_IRQ_134)
#define XBAR_INST_ALTERNATE             (CSL_XBAR_INST_MPU_IRQ_130)
#define XBAR_INTR_SOURCE                (CSL_XBAR_TIMER8_IRQ)


#define TIMER8_IRQ_N (134 + 32)

struct timer_regs {
    volatile uint32_t   tidr;
    uint32_t        res1[3];
    volatile uint32_t   tiocp_cfg;
    uint32_t        res2[3];
    volatile uint32_t   irq_eoi;
    volatile uint32_t   irqstatus_raw;
    volatile uint32_t   irqstatus;
    volatile uint32_t   irqenable_set;
    volatile uint32_t   irqenable_clr;
    volatile uint32_t   irqwakeen;
    volatile uint32_t   tclr;
    volatile uint32_t   tcrr;
    volatile uint32_t   tldr;
    volatile uint32_t   ttgr;
    volatile uint32_t   twps;
    volatile uint32_t   tmap;
    volatile uint32_t   tcar1;
    volatile uint32_t   tsicr;
    volatile uint32_t   tcar2;
};


/*
 ** Crossbar Instance 5 does not allow crossbar input,
 ** instance 132 and 133 are not connected to INTC;
 ** therefore these three instances cannot be used
 */
static const int32_t intrA15[] = { 4, 7, 8, 9, -1, 11, 12, 13, 14, 15, 16, 17,
                                   18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
                                   29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
                                   40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
                                   51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
                                   62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
                                   73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
                                   84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
                                   95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
                                   105, 106, 107, 108, 109, 110, 111, 112, 113,
                                   114, 115, 116, 117, 118, 119, 120, 121, 122,
                                   123, 124, 125, 126, 127, 128, 129, 130, 133,
                                   134, 135, 136, 137, 138, -1, -1, 141, 142,
                                   143, 144, 145, 146, 147, 148, 149, 150, 151,
                                   152, 153, 154, 155, 156, 157, 158, 159 };




struct timer_regs *timer8 = (struct timer_regs *)CSL_MPU_TIMER8_REGS;

static volatile uint32_t reg_val;


static void myBoardInit(void);
static void INTCConfigure(uint32_t xbarInst);
static void inttest_mainloop(void);
static void myDelay(uint32_t val);

/**
 * main.c
 */
int main(void)
{
    myBoardInit();

    inttest_mainloop();
    return 0;
}


static void handle_IRQ(unsigned int irqn)
{
    static uint8_t ctr;
    timer8->irqstatus = 0x2; // mark IRQ as handled by clearing the flag
    if(ctr++ == 0) UART_puts("-",1);
}

static void myDelay(uint32_t val)
{
    int j, k;

    for (j = 0; j < val; j++){
        for (k = 0; k < 0x7fff; k++) {
            reg_val = HWREG(0x4a0098f8); // CM_L4SEC_SHA2MD52_CLKCTRL
        }
    }
}


void myBoardInit(void)
{
    Board_initCfg boardCfg;

    boardCfg = BOARD_INIT_PINMUX_CONFIG |
               BOARD_INIT_MODULE_CLOCK  |
               BOARD_INIT_UART_STDIO;

    Board_init(boardCfg);


    UART_puts("\nBoard initialized:\n", -1);
}


/*
 ** This function configures the INTC to receive UART interrupts.
 */
static void INTCConfigure(uint32_t xbarInst)
{

    CSL_xbarIrqConfigure(XBAR_CPU, xbarInst, XBAR_INTR_SOURCE);


    /* Registering the Interrupt Service Routine(ISR). */
    uint32_t intcNum = intrA15[xbarInst - 1];
    Intc_IntRegister(intcNum, (IntrFuncPtr) handle_IRQ,
                     (void*) XBAR_INTR_SOURCE);

    /* Setting the priority for the UART interrupt in INTC. */
    Intc_IntPrioritySet(intcNum, 1, 0);

    /* Enabling the UART interrupt in INTC. */
    Intc_SystemEnable(intcNum);
}

static void inttest_mainloop(void)
{
    uint32_t l;
    bool alternate_xbar_conf = false;
    myDelay(10);
    //uart_init();
    UART_printf("Hey, I'm working !!!!!!!!!!!\n\r");

    /* Initializing the Interrupt Controller. */
    Intc_Init();
    /* Enable the interrupt */
    Intc_IntEnable(0);

    myDelay(100);

    UART_printf("Configuring interrupt. xbar inst: %d(intcnum %d)\r\n", XBAR_INST, intrA15[XBAR_INST-1]);
    INTCConfigure(XBAR_INST);
    CSL_a15EnableCache();

    UART_printf("timer id ", timer8->tidr);
    timer8->tcrr = RELOAD;
    timer8->tldr = RELOAD;
    timer8->irqstatus = 0x2;
    l = timer8->tclr;
    l &= ~0x1c;
    l |= 0x23;
    timer8->tclr = l;

    timer8->irqenable_set = CSL_DMTIMER1MS_IRQSTATUS_SET_OVF_EN_FLAG_MASK;

    timer8->irqstatus = 0x2;
    uint16_t irq_fail = 0;
    for (;;)
    {
        // delay so long, that the IRQ flag is on for sure, if the IRQ is not working
        myDelay(100);

        // check the IRQ flag
        if(timer8->irqstatus & 0x02 || irq_fail > 5)
        {
            if(irq_fail <= 5)
            {
                // clear the IRQ flag
                timer8->irqstatus = 0x02;
                UART_printf("\r\nIRQ flag on - clearing IRQ\r\n");
            }
            irq_fail++;
            if(irq_fail > 5)
            {
                // after 5 subsequent fails, change the XBAR configuration.
                // The interrupt seems to work correctly after
                irq_fail  = 0;
                alternate_xbar_conf = !alternate_xbar_conf;
                uint32_t xbarInst = alternate_xbar_conf?XBAR_INST_ALTERNATE:XBAR_INST;
                UART_printf("\r\nReconfiguring interrupt. xbar inst: %d(intcnum %d)\r\n", xbarInst, intrA15[xbarInst-1]);
                INTCConfigure(xbarInst);
            }
        }
        else
        {
            if(alternate_xbar_conf)
            {
                // we don't want the alternate configuration, so increase the fail counter anyway.
                irq_fail++;
            }
            else
            {
                irq_fail = 0;
            }
        }
    }
}

myStartup.S

3124.myStartup.S

BR,

--Jussi

  • Hi Jussi,

    I would suggest you to check register value CTRL_CORE_MPU_IRQ_134_135[8:0] MPU_IRQ_134 in both cases, working and non-working. This register is at address 0x4A002B44 and [8:0] MPU_IRQ_134 should be setup to 0x27 (39), which corresponds to TIMER8_IRQ.

    AM57x Cortex-A15 MPU interrupt mapping is explained in below TRM sections:

    ch 17 Interrupt Controllers
    17.3.12 Mapping of Device Interrupts to IRQ_CROSSBAR Input

    18.4.6.4 IRQ_CROSSBAR Module Functional Description

    And below RTOS user guide explains the SW settings:

    Regards,
    Pavel

  • Hi Pavel,

    thanks for the reply. I've read those TRM and web pages several times. :)

    However, now that I continued debugging  I noticed that the Intc_IntPrioritySet() in C:\ti\pdk_am57xx_1_0_13\packages\ti\csl\arch\a15\src\interrupt.c might have some problem.

    By changing the line 

    Intc_IntPrioritySet(intcNum, 1, 0);

    to

    Intc_IntPrioritySet(intcNum-4, 1, 0);

    seems to do the trick, and the interrupts start working at the first initialization. The registers MPU_GICD_IPR0...MPU_GICD_IPR47 are not all initialized to value 0x00000000 but those interrupts that don't work seem to be initialized (in function CSL_armGicInit() called by Board_init()) to value 0xf0f0f0f0. 

    What is going on in here? Is that a bug in my code or in Intc_IntPrioritySet()?

    BR,

    --Jussi

  • Hi,

    as far as I understand, there seems to be two problems in Intc_IntPrioritySet():

    1) The value is written into wrong register

    2) The whole 32 bit register value is changed, even though only one byte should be touched. 

    Also, I don't understand why each byte of the MPU_GICD_IPR<n> only accepts four upper bits - when you write 0xFFFFFFFF the register value becomes 0xF0F0F0F0. Therefore priority values 0..15 are rendered as value 0.

    --Jussi

  • Fixed IntPrioritySet function:

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

    And original (C:\ti\pdk_am57xx_1_0_13\packages\ti\csl\arch\a15\src\interrupt.c):

    void Intc_IntPrioritySet(uint16_t intrNum, uint16_t priority,
                             uint8_t hostIntRoute)
    {
        uint32_t index, mask;
        uint32_t gicIntrId = (uint32_t)intrNum + (uint32_t)32U;
    
        if (intrNum < NUM_INTERRUPTS_EXTERNAL)
        {
            index = ((uint32_t) gicIntrId >> 2) + 1U;
            mask  = (uint32_t) gicIntrId % 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)));
        }
    }

    The fixed interrupt priority function tested like this:

    - setting interrupt priority to 0xFF => no interrupt, because the distributor blocks (current priority level is same).

    - setting interrupt priority to 0x70 => interrupt works.

    --Jussi 

  • Jussi,

    Thanks for the update.

    Just to note, we have something similar in the below e2e thread:

    Regards,
    Pavel

  • Pavel Botev said:

    Thanks for the update.

    Just to note, we have something similar in the below e2e thread:

    Hi, 
    The Intc_IntPrioritySet() fixed in that thread calculates exactly the same register index values as mine.
    The fix has been given to TI almost three years ago, and the bug still exists in the latest release. Please, notify the RTOS expert again to finally fix this issue.
    However, I don't understand the CSL_xbarMpuIrqConfigure() fix suggested in the other thread - the original function in the current release seems to work for me.
    BR,
    --Jussi