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.

AM6442: How to solve the EEPROM in parallel accessed by R50-0 and R51-1

Part Number: AM6442
Other Parts Discussed in Thread: SYSCONFIG

Hi, I'm using AM64 GP Board with running three applications.

The one application is on A53, which just print "Hello World" through UART0 every a second.

Another application is on R50-0 which is an hsr mii example  of SDK.

Other is on R51-1 which is some modified by me and used an lwip-cpsw example of SDK. 

The question is "How to solve the EEPROM in parallel accessed by R50-0 and R51-1" 

Now in debugging, R51-1 executes step by step after R50-0 is running, then R51-1 core is waiting for infinite time by semaphoreP_pend(&object->transferComplete, transaction->timeout) at line 1764 of i2c_v0.c

It is going to read MAC address of cpsw but can't go next step. 

Instead, in debugging, R50-0 executes step by step after R51-1 is running, then R50-0 also is waiting forever by semaphoreP_pend at same upper.

Please let me know how to resolve this situation. Thanks.

  • Hi,

    Thanks for your query.

    Is it same problem mentioned here ?
    https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1218932/am6442-questions-of-linker-cmd-file

    If yes, Can you please help me to close that thread before continuing here ?

    Best Regards

    Ashwani

  • Yes. I clicked on 'This resolved my issue' of previous question.

    I have been trying to resolve this problem through debug. 

    could I know what's going on?

  • Thanks Woong,

    I am working with development team on this.

    It is not advisable to access EEPROM from 2 R5F cores in parallel as both request will go through  same I2C path.

    Still, I need to check this use case with dev team. Please allow me some time to get back to you.

    Best Regards

    Ashwani

  • The question is "How to solve the EEPROM in parallel accessed by R50-0 and R51-1" 

    I request you to update thread title as it will be helpful for other users as well.

    Best Regards

    Ashwani

  • Hi,

    Can you please share sysconfig snapshot for both projects running on R5F_0_0 and R5F_1_1  as below ?

    Best Regards

    Ashwani

  • Other is on R51-1 which is some modified by me and used an lwip-cpsw example of SDK.

    Can you please share this modified project for analysis ?

    Best Regards

    Ashwani

  • [R5_0_0]

    [R5_1_1]

  • I didn't modify code but modify example.syscfg to remove PHY interface aliased with HSR example. Also, I changed linker.cmd that's all.

    I'm sorry for uploading any files because of our policy .

    /**
     * These arguments were used when this file was generated. They will be automatically applied on subsequent loads
     * via the GUI or CLI. Run CLI with '--help' for additional information on how to override these arguments.
     * @cliArgs --device "AM64x_beta" --package "ALV" --part "Default" --context "r5fss1-1" --product "MCU_PLUS_SDK_AM64x@08.05.00"
     * @versions {"tool":"1.14.0+2667"}
     */
    
    /**
     * Import the modules used in this configuration.
     */
    const eeprom     = scripting.addModule("/board/eeprom/eeprom", {}, false);
    const eeprom1    = eeprom.addInstance();
    const gpio       = scripting.addModule("/drivers/gpio/gpio", {}, false);
    const gpio1      = gpio.addInstance();
    const i2c        = scripting.addModule("/drivers/i2c/i2c", {}, false);
    const i2c1       = i2c.addInstance();
    const i2c2       = i2c.addInstance();
    const pruicss    = scripting.addModule("/drivers/pruicss/pruicss", {}, false);
    const pruicss1   = pruicss.addInstance();
    const debug_log  = scripting.addModule("/kernel/dpl/debug_log");
    const mpu_armv7  = scripting.addModule("/kernel/dpl/mpu_armv7", {}, false);
    const mpu_armv71 = mpu_armv7.addInstance();
    const mpu_armv72 = mpu_armv7.addInstance();
    const mpu_armv73 = mpu_armv7.addInstance();
    const mpu_armv74 = mpu_armv7.addInstance();
    const mpu_armv75 = mpu_armv7.addInstance();
    const mpu_armv76 = mpu_armv7.addInstance();
    const mpu_armv77 = mpu_armv7.addInstance();
    const enet_cpsw  = scripting.addModule("/networking/enet_cpsw/enet_cpsw", {}, false);
    const enet_cpsw1 = enet_cpsw.addInstance();
    
    /**
     * Write custom configuration values to the imported modules.
     */
    eeprom1.$name = "CONFIG_EEPROM0";
    
    gpio1.$name                    = "CONFIG_GPIO0";
    gpio1.pinDir                   = "OUTPUT";
    gpio1.useMcuDomainPeripherals  = true;
    gpio1.MCU_GPIO.$assign         = "MCU_GPIO0";
    gpio1.MCU_GPIO.gpioPin.$assign = "ball.A7";
    
    i2c1.$name               = "CONFIG_I2C0";
    eeprom1.peripheralDriver = i2c1;
    i2c1.I2C.$assign         = "I2C0";
    
    i2c2.$name       = "CONFIG_I2C1";
    i2c2.I2C.$assign = "I2C1";
    
    pruicss1.$name                           = "CONFIG_PRU_ICSS1";
    pruicss1.instance                        = "ICSSG1";
    pruicss1.AdditionalICSSSettings[0].$name = "CONFIG_PRU_ICSS_IO0";
    
    debug_log.enableUartLog            = true;
    debug_log.enableCssLog             = false;
    debug_log.uartLog.$name            = "CONFIG_UART0";
    debug_log.uartLog.UART.$assign     = "USART3";
    debug_log.uartLog.UART.RXD.$assign = "ball.D16";
    debug_log.uartLog.UART.TXD.$assign = "ball.E16";
    
    mpu_armv71.$name             = "CONFIG_MPU_REGION0";
    mpu_armv71.size              = 31;
    mpu_armv71.attributes        = "Device";
    mpu_armv71.accessPermissions = "Supervisor RD+WR, User RD";
    mpu_armv71.allowExecute      = false;
    
    mpu_armv72.$name             = "CONFIG_MPU_REGION1";
    mpu_armv72.size              = 15;
    mpu_armv72.accessPermissions = "Supervisor RD+WR, User RD";
    
    mpu_armv73.$name             = "CONFIG_MPU_REGION2";
    mpu_armv73.baseAddr          = 0x41010000;
    mpu_armv73.size              = 15;
    mpu_armv73.accessPermissions = "Supervisor RD+WR, User RD";
    
    mpu_armv74.$name             = "CONFIG_MPU_REGION3";
    mpu_armv74.accessPermissions = "Supervisor RD+WR, User RD";
    mpu_armv74.baseAddr          = 0x70000000;
    mpu_armv74.size              = 23;
    
    mpu_armv75.$name             = "CONFIG_MPU_REGION4";
    mpu_armv75.accessPermissions = "Supervisor RD+WR, User RD";
    mpu_armv75.baseAddr          = 0x80000000;
    mpu_armv75.size              = 31;
    
    mpu_armv76.$name             = "CONFIG_MPU_REGION5";
    mpu_armv76.accessPermissions = "Supervisor RD+WR, User RD";
    mpu_armv76.baseAddr          = 0xA5000000;
    mpu_armv76.size              = 23;
    mpu_armv76.attributes        = "NonCached";
    
    mpu_armv77.$name    = "CONFIG_MPU_REGION6";
    mpu_armv77.size     = 27;
    mpu_armv77.baseAddr = 0x60000000;
    
    enet_cpsw1.$name                       = "CONFIG_ENET_CPSW0";
    enet_cpsw1.PktInfoOnlyEnable           = true;
    enet_cpsw1.LargePoolPktCount           = 32;
    enet_cpsw1.mdioMode                    = "MDIO_MODE_MANUAL";
    enet_cpsw1.macOnlyEn_macPort1          = true;
    enet_cpsw1.macOnlyEn_macPort2          = true;
    enet_cpsw1.macOnlyEn_hostPort          = true;
    enet_cpsw1.DisableMacPort2             = true;
    enet_cpsw1.txDmaChannel[0].$name       = "ENET_DMA_TX_CH0";
    enet_cpsw1.rxDmaChannel[0].$name       = "ENET_DMA_RX_CH0";
    enet_cpsw1.pinmux[0].$name             = "ENET_CPSW_PINMUX0";
    enet_cpsw1.pinmux[0].MDIO.$assign      = "MDIO0";
    enet_cpsw1.pinmux[0].MDIO.MDC.$assign  = "ball.R2";
    enet_cpsw1.pinmux[0].MDIO.MDIO.$assign = "ball.P5";
    enet_cpsw1.pinmux[0].RGMII1.$assign    = "RGMII1";
    enet_cpsw1.pinmux[0].RGMII2.$assign    = "RGMII2";
    enet_cpsw1.netifInstance.create(1);
    enet_cpsw1.netifInstance[0].$name      = "NETIF_INST_ID0";
    
    const udma         = scripting.addModule("/drivers/udma/udma", {}, false);
    const udma1        = udma.addInstance({}, false);
    enet_cpsw1.udmaDrv = udma1;
    
    /**
     * Pinmux solution for unlocked pins/peripherals. This ensures that minor changes to the automatic solver in a future
     * version of the tool will not impact the pinmux you originally saw.  These lines can be completely deleted in order to
     * re-solve from scratch.
     */
    i2c1.I2C.SCL.$suggestSolution                       = "ball.A18";
    i2c1.I2C.SDA.$suggestSolution                       = "ball.B18";
    i2c2.I2C.SCL.$suggestSolution                       = "ball.C18";
    i2c2.I2C.SDA.$suggestSolution                       = "ball.B19";
    enet_cpsw1.pinmux[0].RGMII1.RD0.$suggestSolution    = "ball.W5";
    enet_cpsw1.pinmux[0].RGMII1.RD1.$suggestSolution    = "ball.Y5";
    enet_cpsw1.pinmux[0].RGMII1.RD2.$suggestSolution    = "ball.V6";
    enet_cpsw1.pinmux[0].RGMII1.RD3.$suggestSolution    = "ball.V5";
    enet_cpsw1.pinmux[0].RGMII1.RX_CTL.$suggestSolution = "ball.W6";
    enet_cpsw1.pinmux[0].RGMII1.RXC.$suggestSolution    = "ball.AA5";
    enet_cpsw1.pinmux[0].RGMII1.TD0.$suggestSolution    = "ball.V15";
    enet_cpsw1.pinmux[0].RGMII1.TD1.$suggestSolution    = "ball.V14";
    enet_cpsw1.pinmux[0].RGMII1.TD2.$suggestSolution    = "ball.W14";
    enet_cpsw1.pinmux[0].RGMII1.TD3.$suggestSolution    = "ball.AA14";
    enet_cpsw1.pinmux[0].RGMII1.TX_CTL.$suggestSolution = "ball.U15";
    enet_cpsw1.pinmux[0].RGMII1.TXC.$suggestSolution    = "ball.U14";
    enet_cpsw1.pinmux[0].RGMII2.RD0.$suggestSolution    = "ball.W11";
    enet_cpsw1.pinmux[0].RGMII2.RD1.$suggestSolution    = "ball.V11";
    enet_cpsw1.pinmux[0].RGMII2.RD2.$suggestSolution    = "ball.AA12";
    enet_cpsw1.pinmux[0].RGMII2.RD3.$suggestSolution    = "ball.Y12";
    enet_cpsw1.pinmux[0].RGMII2.RX_CTL.$suggestSolution = "ball.W12";
    enet_cpsw1.pinmux[0].RGMII2.RXC.$suggestSolution    = "ball.U11";
    enet_cpsw1.pinmux[0].RGMII2.TD0.$suggestSolution    = "ball.AA10";
    enet_cpsw1.pinmux[0].RGMII2.TD1.$suggestSolution    = "ball.V10";
    enet_cpsw1.pinmux[0].RGMII2.TD2.$suggestSolution    = "ball.U10";
    enet_cpsw1.pinmux[0].RGMII2.TD3.$suggestSolution    = "ball.AA11";
    enet_cpsw1.pinmux[0].RGMII2.TX_CTL.$suggestSolution = "ball.Y11";
    enet_cpsw1.pinmux[0].RGMII2.TXC.$suggestSolution    = "ball.Y10";
    

    #include "ti_enet_config.h"
    
    /* This is the stack that is used by code running within main()
     * In case of NORTOS,
     * - This means all the code outside of ISR uses this stack
     * In case of FreeRTOS
     * - This means all the code until vTaskStartScheduler() is called in main()
     *   uses this stack.
     * - After vTaskStartScheduler() each task created in FreeRTOS has its own stack
     */
    --stack_size=8192
    /* This is the heap size for malloc() API in NORTOS and FreeRTOS
     * This is also the heap used by pvPortMalloc in FreeRTOS
     */
    --heap_size=34000
    -e_vectors  /* This is the entry of the application, _vector MUST be plabed starting address 0x0 */
    
    /* This is the size of stack when R5 is in IRQ mode
     * In NORTOS,
     * - Here interrupt nesting is disabled as of now
     * - This is the stack used by ISRs registered as type IRQ
     * In FreeRTOS,
     * - Here interrupt nesting is enabled
     * - This is stack that is used initally when a IRQ is received
     * - But then the mode is switched to SVC mode and SVC stack is used for all user ISR callbacks
     * - Hence in FreeRTOS, IRQ stack size is less and SVC stack size is more
     */
    __IRQ_STACK_SIZE = 256;
    /* This is the size of stack when R5 is in IRQ mode
     * - In both NORTOS and FreeRTOS nesting is disabled for FIQ
     */
    __FIQ_STACK_SIZE = 256;
    __SVC_STACK_SIZE = 4096; /* This is the size of stack when R5 is in SVC mode */
    __ABORT_STACK_SIZE = 256;  /* This is the size of stack when R5 is in ABORT mode */
    __UNDEFINED_STACK_SIZE = 256;  /* This is the size of stack when R5 is in UNDEF mode */
    
    SECTIONS
    {
        /* This has the R5F entry point and vector table, this MUST be at 0x0 */
        .vectors:{} palign(8) > R5F_VECS
    
        /* This has the R5F boot code until MPU is enabled,  this MUST be at a address < 0x80000000
         * i.e this cannot be placed in DDR
         */
        GROUP {
            .text.hwi: palign(8)
            .text.cache: palign(8)
            .text.mpu: palign(8)
            .text.boot: palign(8)
            .text:abort: palign(8) /* this helps in loading symbols when using XIP mode */
        } > MSRAM
    
        /* This is rest of code. This can be placed in DDR if DDR is available and needed */
        GROUP {
            .text:   {} palign(8)   /* This is where code resides */
            .rodata: {} palign(8)   /* This is where const's go */
        } > DDR
    
        /* This is rest of initialized data. This can be placed in DDR if DDR is available and needed */
        GROUP {
            .data:   {} palign(8)   /* This is where initialized globals and static go */
        } > DDR
    
        /* This is rest of uninitialized data. This can be placed in DDR if DDR is available and needed */
        GROUP {
            .sysmem: {} palign(8)   /* This is where the malloc heap goes */
            .stack:  {} palign(8)   /* This is where the main() stack goes */
        } > DDR
    
        GROUP {
            .bss:    {} palign(8)   /* This is where uninitialized globals go */
            RUN_START(__BSS_START)
            RUN_END(__BSS_END)
        } > DDR
    
        /* This is where the stacks for different R5F modes go */
        GROUP {
            .irqstack: {. = . + __IRQ_STACK_SIZE;} align(8)
            RUN_START(__IRQ_STACK_START)
            RUN_END(__IRQ_STACK_END)
            .fiqstack: {. = . + __FIQ_STACK_SIZE;} align(8)
            RUN_START(__FIQ_STACK_START)
            RUN_END(__FIQ_STACK_END)
            .svcstack: {. = . + __SVC_STACK_SIZE;} align(8)
            RUN_START(__SVC_STACK_START)
            RUN_END(__SVC_STACK_END)
            .abortstack: {. = . + __ABORT_STACK_SIZE;} align(8)
            RUN_START(__ABORT_STACK_START)
            RUN_END(__ABORT_STACK_END)
            .undefinedstack: {. = . + __UNDEFINED_STACK_SIZE;} align(8)
            RUN_START(__UNDEFINED_STACK_START)
            RUN_END(__UNDEFINED_STACK_END)
        } > DDR
    
        /* General purpose user shared memory, used in some examples */
        .bss.user_shared_mem (NOLOAD) : {} > USER_SHM_MEM
        /* this is used when Debug log's to shared memory are enabled, else this is not used */
        .bss.log_shared_mem  (NOLOAD) : {} > LOG_SHM_MEM
        /* this is used only when IPC RPMessage is enabled, else this is not used */
        .bss.ipc_vring_mem   (NOLOAD) : {} > RTOS_NORTOS_IPC_SHM_MEM
    
        .enet_dma_mem {
            *(*ENET_DMA_DESC_MEMPOOL)
            *(*ENET_DMA_RING_MEMPOOL)
    #if (ENET_SYSCFG_PKT_POOL_ENABLE == 1)
            *(*ENET_DMA_PKT_MEMPOOL)
    #endif
        } (NOLOAD) {} ALIGN (128) > DDR
    
        .bss:ENET_DMA_OBJ_MEM (NOLOAD) {} ALIGN (128) > MSRAM
        .bss:ENET_DMA_PKT_INFO_MEMPOOL (NOLOAD) {} ALIGN (128) > MSRAM
        .bss:ENET_ICSSG_OCMC_MEM (NOLOAD) {} ALIGN (128) > MSRAM
    }
    
    /*
    NOTE: Below memory is reserved for DMSC usage
     - During Boot till security handoff is complete
       0x701E0000 - 0x701FFFFF (128KB)
     - After "Security Handoff" is complete (i.e at run time)
       0x701FC000 - 0x701FFFFF (16KB)
    
     Security handoff is complete when this message is sent to the DMSC,
       TISCI_MSG_SEC_HANDOVER
    
     This should be sent once all cores are loaded and all application
     specific firewall calls are setup.
    */
    
    MEMORY
    {
        R5F_VECS  : ORIGIN = 0x00000000 , LENGTH = 0x00000040
        R5F_TCMA  : ORIGIN = 0x00000040 , LENGTH = 0x00007FC0
        R5F_TCMB0 : ORIGIN = 0x41010000 , LENGTH = 0x00008000
    
        /* when using multi-core application's i.e more than one R5F/M4F active, make sure
         * this memory does not overlap with other R5F's
         */
        MSRAM     : ORIGIN = 0x70080000 , LENGTH = 0x2F00
    
        /* This section can be used to put XIP section of the application in flash, make sure this does not overlap with
         * other CPUs. Also make sure to add a MPU entry for this section and mark it as cached and code executable
         */
        FLASH     : ORIGIN = 0x60200000 , LENGTH = 0x100000
    
        /* when using multi-core application's i.e more than one R5F/M4F active, make sure
         * this memory does not overlap with other R5F's
         */
        DDR       : ORIGIN = 0x80000000 , LENGTH = 0x1F0000
    
        /* shared memory segments */
        /* On R5F,
         * - make sure there is a MPU entry which maps below regions as non-cache
         */
        USER_SHM_MEM            : ORIGIN = 0x701D0000, LENGTH = 0x00004000
        LOG_SHM_MEM             : ORIGIN = 0x701D4000, LENGTH = 0x00004000
        RTOS_NORTOS_IPC_SHM_MEM : ORIGIN = 0x701D8000, LENGTH = 0x00008000
    }
    

  • Hi, I found why the one of cores was the pending state in progress of accessing to EEPROM.

    I2C HW interrupt was not occured forever, when the one of R5 cores accesses to I2C in advance.

    However, I don't know how to resolve this situation.

  • Thanks Woong, for updated info.

    I2C HW interrupt was not occured forever, when the one of R5 cores accesses to I2C in advance.

    However, I don't know how to resolve this situation.

    I am working with dev team on this.

    But, as we cannot same setup on your and my side. Let's try this

    accessing R5F_0_0 <=> I2C0 <=> EEPROM 

    In parallel

    accessing R5F_0_0 <=> I2C0 <=> EEPROM 

    But with bare minimal code (you can refer empty projects in MCUSDK C:\mcu_plus_sdk\examples\empty\am64x-evm).

    Best Regards

    Ashwani

  • In the CPSW example, I got rid of I2C and EEPROM through SYSCONFIG. 

    However, after build the project, automatically  created EnetBoard_getMacAddrList of 'ti_board_config.c' source file

    If I use cpsw, I must use 'EnetBoard_getMacAddrList' ?

  • Not sure If I understood this update.

    You mean,

    • Now only HSR MII example is accessing EEPROM. 
    • ENET CPSW example not accessing EEPROM

    correct ?

    If I use cpsw, I must use 'EnetBoard_getMacAddrList' ?

    Can you please elaborate here from scratch ?

    Best Regards

    Ashwani

  • No, I'm sorry for told the situation exactly. 

    All of examples(HSR / ENET CPSW) are accessing EEPROM when respective example get MAC address from eeprom.

    Note that they are not accessing simultaneously, but one of them used I2C accessing to EEPROM the other one can't access to EEPROM because of no interrupt.

  • Okay.

    A quick fix:  you can overwrite these functions EnetBoard_getMacAddrList with your own, you can hardcode the mac addresses into the macAddr array.

    or you want to access MAC address from EEPROM only ?

    Best Regards
    Ashwani

  • I removed EEPROM, I2C in SYSCONFIG file, but  EnetBoard_getMacAddrList() function was created automatically. 

    Also, I modified some lines related EEPROM of EnetBoard_getMacAddrList(), but the result is same upper.

    I have a question of how to modify "EnetBoard_getMacAddrList() of 'ti_board_config.c' source file"

  • Hi Woong,

    1. Select custom board option

    2. And then copy originally created "'ti_board_config.c" to application code ,

    3. Add it to make file, then edit it

    Please refer below section for details:
    https://software-dl.ti.com/mcu-plus-sdk/esd/AM64X/08_05_00_24/exports/docs/api_guide_am64x/enet_migration_guide_top.html#CustomBoardSupport

    Best Regards

    Ashwani