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.

[BIOS NDK] Data-Abort when reading/writing EMAC softreset register

Other Parts Discussed in Thread: SYSBIOS

Hi everyone,

we are currently trying to get our Mistral DM814x working.

We are using the "AV BIOS SDK" which basically comprises:

SYS/BIOS 6.33
NDK 2.21
NSP 1.0.0.1 for DM814x
BIOSPSP 3.10.6.0

and a bunch of other (non relevant) stuff.

The NSP contains a demo application cfgdemo which should be a showcase for the usage of the NDK.

Somewhere deep in the NSP drivers (csl_emac.c -> EMAC_open)  there is a call that modifies the EMACs SoftReset register (reading , or'ing and writing):

CSL_FINS(CPSW3G_REGS->SOFT_RESET, CPSW3G_SOFT_RESET_SOFT_RESET, CSL_CPSW3G_SOFT_RESET_SOFT_RESET_RESET);

That call seems to do tree things:

1. Reading the current value from register 0x4A10011C (EMAC SoftReset)
2. Manipulating that value in R12 to the value 0x00000001

3. Writing that value back to 0x4A10011C

And step 1 is causing a dataAbort:

Exception occurred in ThreadType_Task.
Task handle: 0x800ec694.
Task stack base: 0x8007ecc0.
Task stack size: 0x2000.
R0 = 0x4a10011c  R8  = 0xffffffff
R1 = 0x800e3fb8  R9  = 0x800744c4
R2 = 0x00000000  R10 = 0x00000000
R3 = 0x8009428c  R11 = 0x8009f7e0
R4 = 0x80072d84  R12 = 0x4a10011c
R5 = 0x80072d94  SP(R13) = 0x80080b90
R6 = 0x8009f71c  LR(R14) = 0x80094480
R7 = 0x8009f570  PC(R15) = 0x8008c7c8
PSR = 0x6000019f
ti.sysbios.family.arm.exc.Exception: line 176: E_dataAbort: pc = 0x8008c7c8, lr = 0x80094480.
xdc.runtime.Error.raise: terminating execution

The MMU Data Fault Status Register states: 0x1008 (precise external abort, nontranslation).

Any ideas?

Thanks and greetings,
Thomas.

  • Update:

    The above described problem occurs when downloading the binary via JTAG.
    When we are loading that SYS/BIOS binary via u-boot 1st stage, the dataAbort doesn't occur. So I guess there are some register initalization routines in u-boot we are missing here.

  • Thomas,

    This looks like EMAC clock is not enabled. Can you check the value of CM_ALWON_ETHERNET_0_CLKCTRL/0x481815D4 register just before the SOFT_RESET register access? It should be 0x00000002.

    Can you also try to access/read any other EMAC register, to check if the issue is only with SOFT_RESET register.

    BR
    Pavel
  • Hi Pavel,

    The register 0x481815D4 has the value 0x00050002.
    If we are reading the TRM correctly this means, that the module is ENABLED but its in STANDBY and in TRANSITION.

    How can we get that module to leave that transition mode?


    BR,
    Thomas

  • Can you also try to access/read any other EMAC register, to check if the issue is only with SOFT_RESET register.
  • Do you have test the register 0x481815D4 after writing 0x2? This is the code in u-boot:

    /* Ethernet */
    __raw_writel(0x2, CM_ETHERNET_CLKSTCTRL);
    __raw_writel(0x2, CM_ALWON_ETHERNET_0_CLKCTRL);
    while((__raw_readl(CM_ALWON_ETHERNET_0_CLKCTRL) & 0x30000) != 0);

    After this code, the value of CM_ALWON_ETHERNET_0_CLKCTRL/0x481815D4 is 0x00000002.

    BR
    Pavel
  • I tested to read the RXCONTROL / 0x48181014 register ... which also failed.

    The GEL file we originally used, uses code like this:

       *((unsigned int*)(0x48181404)) = 0x2;
       *((unsigned int*)(0x481815d4)) = 0x2;
         while(RD_MEM_32(0x48181404)!=0x0302);
         while((RD_MEM_32(0x481815d4)&0x2)!=0x2);

    I adapted the last line of that code to do the same as u-boot. However, that leads to an endless while loop:

    while((RD_MEM_32(0x481815d4)&0x30000)!=0);

    So for whatever reason the upper bits of that register never get cleared.

  • I can also recommend you to check u-boot code, where this register 0x4A10011C/SOFT_RESET can be access/read successful. You can align to the u-boot ethernet driver.

     http://arago-project.org/git/projects/?p=u-boot-omap3.git;a=shortlog;h=refs/heads/ti81xx-master

    u-boot/drivers/net/cpsw.c

    static int cpsw_init(struct eth_device *dev, bd_t *bis)

    {

    struct cpsw_priv *priv = dev->priv;

    int i, ret;

    priv->data.control(1);

    /* soft reset the controller and initialize priv */

    soft_reset(&priv->regs->soft_reset);

    /* initialize and reset the address lookup engine */

    cpsw_ale_enable(priv, 1);

    cpsw_ale_clear(priv, 1);

    cpsw_ale_vlan_aware(priv, 0); /* vlan unaware mode */

    /* setup host port priority mapping */

    __raw_writel(0x76543210, &priv->host_port_regs->cpdma_tx_pri_map);

    __raw_writel(0, &priv->host_port_regs->cpdma_rx_chan_map);

    /* disable priority elevation and enable statistics on all ports */

    __raw_writel(0, &priv->regs->ptype);

    /* enable statistics collection only on the host port */

    __raw_writel(BIT(priv->host_port), &priv->regs->stat_port_en);

    cpsw_ale_port_state(priv, priv->host_port, ALE_PORT_STATE_FORWARD);

    memcpy(priv->dev->enetaddr, cpsw_eth_mac_addr, 6);

    cpsw_ale_add_ucast(priv, priv->dev->enetaddr, priv->host_port,

      ALE_SECURE);

    cpsw_ale_add_mcast(priv, NetBcastAddr, 1 << priv->host_port);

    for_each_slave(priv, cpsw_slave_init, priv);

    cpsw_update_link(priv);

    /* init descriptor pool */

    for (i = 0; i < NUM_DESCS; i++) {

    desc_write(&priv->descs[i], hw_next,

      (i == (NUM_DESCS - 1)) ? 0 : &priv->descs[i+1]);

    }

    priv->desc_free = priv->descs;

    /* initialize channels */

    memset(&priv->rx_chan, 0, sizeof(struct cpdma_chan));

    priv->rx_chan.hdp = priv->dma_sram_regs + CPDMA_RXHDP;

    priv->rx_chan.cp = priv->dma_sram_regs + CPDMA_RXCP;

    priv->rx_chan.rxfree = priv->dma_regs + CPDMA_RXFREE;

    memset(&priv->tx_chan, 0, sizeof(struct cpdma_chan));

    priv->tx_chan.hdp = priv->dma_sram_regs + CPDMA_TXHDP;

    priv->tx_chan.cp = priv->dma_sram_regs + CPDMA_TXCP;

    /* clear dma state */

    soft_reset(priv->dma_regs + CPDMA_SOFTRESET);

  • Hi Pavel,

    I got it working. BUT... I actually do not know how!

    I was experimenting with some different GEL files (which are supposed to do the register initialization as u-boot does).

    The one which I was successful with was deployed with the used NSP (DM814X_PG2.1_DDR2_DDR3_V3_EVM.gel).

    There is some initialization code:

    ALL_ADPLL_CLOCKS_ENABLE_API();
    GEMSSClkEnable(); //DSP clock must be enabled before EMAC clocks, else EMAC GMII gets overwritten          
    emac_clkenable_API();
    Timer1_32kHClkEnable();
    Timer3_32kHClkEnable();
    DucatiClkEnable();
    DDR3_EMIF0_EMIF1_Config();

    The interesting parts are GEMSSClkEnable(); and emac_clkenable_API();.

    As far as I understand emac_clkenable_API(); does RMII-PinMuxing and enables the EMAC clock:

       rgmii_pinmux_setup();
        GEL_TextOut("CONFIGURE PRCM CLOCKS of EMAC in progress \n\r");
       *((unsigned int*)(0x48181404)) = 0x2;
       *((unsigned int*)(0x481815d4)) = 0x2;
         while(RD_MEM_32(0x48181404)!=0x0302);
         while(RD_MEM_32(0x481815d4)!=0x2);
       GEL_TextOut("PRCM CLOCKS of EMAC  is complete \n\r");

    As you can see, the line while(RD_MEM_32(0x481815d4)!=0x2); does exactly what its supposed to do.

    The GEMSSClkEnable(); does something I do not quite understand (yet):

        unsigned int i=0, k=0, fail=0;

        GEL_TextOut("\tPRCM for GEMSS is in Progress, Please wait.....  \n","Output",1,1,1);                                         

        /*Cortex A8 must be in Supervisor Mode to Access the following two registers*/
        WR_MEM_32(DSPMEM_SLEEP,         0); /*Bring GEM L2RAM out of Power down Mode*/
        WR_MEM_32(DSPBOOTADDR,             0x00800000); /*DSPBOOT ADDRESS*/
        
        GEL_TextOut("\t CP0...Done \n");
        
        /*Enable Clock to MMU CFG*/
        WR_MEM_32(CM_MMUCFG_CLKSTCTRL,         2);
        WR_MEM_32(CM_ALWON_MMUCFG_CLKCTRL,         2);
        while(((RD_MEM_32(CM_ALWON_MMUCFG_CLKCTRL)&0x0))!=0x0);
        while(((RD_MEM_32(CM_MMUCFG_CLKSTCTRL)&0x100))!=0x100);

        GEL_TextOut("\t CP1...Done \n");

        /*Enable Clock to Data*/
        WR_MEM_32(CM_MMU_CLKSTCTRL,         2);
        WR_MEM_32(CM_ALWON_MMUDATA_CLKCTRL,         2);
        while(((RD_MEM_32(CM_ALWON_MMUDATA_CLKCTRL)&0x0))!=0x0);
        while(((RD_MEM_32(CM_MMU_CLKSTCTRL)&0x100))!=0x100);

        GEL_TextOut("\t CP2...Done \n");

        /*Enable Clock to GEMSS*/
        WR_MEM_32(CM_GEM_CLKSTCTRL,         2); /*Enable Power Domain Transition*/
        while(RD_MEM_32(PM_ACTIVE_PWRSTST)!=0x37);    /*Check Power is ON*/
        WR_MEM_32(CM_ACTIVE_GEM_CLKCTRL,     2); /*Enable GEMSS Clocks*/

        GEL_TextOut("\t CP3...Done \n");

        while(((RD_MEM_32(CM_GEM_CLKSTCTRL)&0x700))!=0x700); /*GME Clocks are Active*/

        WR_MEM_32(RM_ACTIVE_RSTCTRL,     1); /*Issue GEM Warm Reset To access GEMSS memories */

        while(((RD_MEM_32(RM_ACTIVE_RSTST)&0x2))!=0x2); /*GEMSS Warm Reset has been Asserted*/

        GEL_TextOut("\t CP4...Done \n");

        for(i=0; i<8; i++) {
          WR_MEM_32((GEM_L2RAM_BASE_ADDR+4*i), 0x12); /*Write Self Branch Instruction*/
        }

        GEL_TextOut("\t CP5...Done \n");

        WR_MEM_32(RM_ACTIVE_RSTCTRL,     0); /*Bring GEM Core out of Reset*/
        
        while(((RD_MEM_32(RM_ACTIVE_RSTST)&0x3))!=0x3); /*GEM core core is out of Reset*/

        GEL_TextOut("\t CP6...Done \n");

        GEL_TextOut("\tUser Can Connect to GEMSS   \n","Output",1,1,1);    
        GEL_TextOut("\tPRCM for GEMSS is DONE ******  \n","Output",1,1,1);                                     

    Anyway:
    That above mentioned while only works (i.e. does not loop forever) if I disable that GEMSSClkEnable();

    Can you tell me why?

  • Thomas Doering said:
    I tested to read the RXCONTROL / 0x48181014 register ... which also failed.

    Do you mean RX_CONTROL / 0x4A100114 (CPDMA_REGS RX Control Register) ?

    BR
    Pavel

  • Thomas Doering said:
    GEMSSClkEnable(); //DSP clock must be enabled before EMAC clocks, else EMAC GMII gets overwritten    

    I do not see how EMAC GMII will be overwritten if you enable DSP clock after EMAC clock:

    ALL_ADPLL_CLOCKS_ENABLE_API();
    emac_clkenable_API();
    GEMSSClkEnable();  
    Timer1_32kHClkEnable();
    Timer3_32kHClkEnable();
    DucatiClkEnable();
    DDR3_EMIF0_EMIF1_Config();

    Also I do not see any relation between DSP clock and EMAC clock.


    Note also that DM8148_EVM.gel file has the below flow, which executes automatically when connect to the DM814x board:

    OnTargetConnect()
    {
        GEL_TextOut( "\nConnecting Target...\n" );
     
        GEL_Reset();
        ALL_ADPLL_CLOCKS_ENABLE_API();
        C674xClkEnable_API();                         ---------------------> enable DSP clock
        ControlModule_ClkEnable();
        PrcmAlwayOnClkEnable();
        Ethernet_PinMux_Setup();                    ---------------------> enable EMAC clock
        SPI_Setup();
        SD_MMC0_Setup();
        DDR3_EMIF0_EMIF1_533MHz_Config();
        
        GEL_TextOut( "Connecting Target... Done.\n\n" );
    }

    Can you test this gel file (attached)?

    40711.DM8148_EVM.gel

    BR
    Pavel

  • Hi Pavel,

    thanks for that GEL-file. Unfortunately that doesn't work either.

    When we take out C674xClkEnable_API(); everythings fine. Otherwise the registers aren't accessible again.

    Line 1682 is different from what u-boot does:

        while((RD_MEM_32(MC_ALWON_ETH_0_CLKSTCTRL) & 0x0F) !=0x2);

    should be

        while(RD_MEM_32(MC_ALWON_ETH_0_CLKSTCTRL) !=0x2);

    And when we do that. We get out endless while-loop again.

    So, something in that DSP-Initialization code keeps that MC_ALWON_ETH_0_CLKSTCTRL register in TRANSITION (i.e. 0x50002) and leaves the EMAC registers inaccessible.

    BR,
    Thomas

  • Hi Thomas,

    When I try with DM8148_EVM.gel file (no modifications) in DM814x TI EVM (www.ti.com/.../tmdxevm8148) silicon revision 2.1, I have the below console output when connect to Cortex-A8 ARM:

    CortexA8: GEL Output:
    Connecting Target...
    CortexA8: Output: **** DM8148 ALL ADPLL INIT IS In Progress .........
    CortexA8: GEL Output: A8 ADPLLJ CLKOUT value is = 600
    CortexA8: GEL Output: L3 ADPLLJ CLKOUT value is = 200
    CortexA8: GEL Output: DSP ADPLLJ CLKOUT value is = 500
    CortexA8: GEL Output: DSS ADPLLJ CLKOUT value is = 200
    CortexA8: GEL Output: HDVICP ADPLLJ CLKOUT value is = 266
    CortexA8: GEL Output: SGX ADPLLJ CLKOUT value is = 200
    CortexA8: GEL Output: USB ADPLLJ CLKOUT value is = 192
    CortexA8: GEL Output: VIDEO-0 ADPLLJ CLKOUT value is = 54
    CortexA8: GEL Output: VIDEO-1 ADPLLJ CLKOUT value is = 148
    CortexA8: GEL Output: VIDEO-2/HDMI ADPLLJ CLKOUT value is = 148
    CortexA8: GEL Output: AUDIO ADPLLJ CLKOUT value is = 200
    CortexA8: Output: **** DM8148 ALL ADPLL INIT IS Done **************
    CortexA8: Output: PRCM for C674x is in Progress, Please wait.....
    CortexA8: GEL Output: CP0...Done
    CortexA8: GEL Output: CP1...Done
    CortexA8: GEL Output: CP2...Done
    CortexA8: GEL Output: CP3...Done
    CortexA8: GEL Output: CP4...Done
    CortexA8: GEL Output: CP5...Done
    CortexA8: GEL Output: CP6...Done
    CortexA8: Output: User Can Connect to C674x
    CortexA8: Output: PRCM for C674x is DONE ******
    CortexA8: Output: PRCM for Control Module in Progress
    CortexA8: Output: PRCM for Control Module Done
    CortexA8: Output: PRCM for OCMCRAM0/1 Initialization in Progress
    CortexA8: Output: PRCM for OCMCRAM0 Initialization Done
    CortexA8: GEL Output: ***** Configuring ethernet Clk and Mux....*****
    CortexA8: GEL Output: ***** GMII pin mux and Clk initialized....*****
    CortexA8: Output: PRCM for SPI-0 CS-0 is in Progress, Please wait.....
    CortexA8: GEL Output: ***** SPI-0 CS-0 is initialized....*****
    CortexA8: Output: PRCM for SD/MMC0 are in Progress, Please wait.....
    CortexA8: GEL Output: ***** MMC0/SD is initialized....*****
    CortexA8: GEL Output: **** Configuring DDR PLL to 533 MHz.........
    CortexA8: GEL Output: DDR ADPLLJ CLKOUT value is = 533
    CortexA8: Output: **** DM8148 DDR3 EVM EMIF0 and EMIF1 configuration in progress.........
    CortexA8: Output: Busy reading back DMM registers Please wait ...
    CortexA8: Output: DMM register read successfully
    CortexA8: Output: **** DM8148 DDR3 EVM EMIF0 and EMIF1 configuration is DONE ****
    CortexA8: GEL Output: Connecting Target... Done.

    Then when I check the values of 0x4A10011C, it is accessible and the value is 0x00000000.

    When I check the value of 0x481815D4, it is 0x00000002.

    BR
    Pavel
  • Hi Pavel,

    I am a colleague of Thomas working on the same topic.

    We found the difference: In both DM8148_EVM.gel and 40711.DM8148_EVM.gel the initialization of the SATA PLL was deactivated. In the DM814X_PG2.1_DDR2_DDR3_V3_EVM.gel it was activated.

    Obviously initializing the SATA PLL is crucial for our setup to make the 3PSW Ethernet Subsystem work.

    Unfortunately after solving this issue we run into the next problem:

    We first tried the cfgdemo example of the provided AV BIOS SDK NSP for DM8148. But it looks like there is no communication possible. The ICMP receive loop never receives any data when sending e.g. a ping request, and even if we modify the example by setting a fixed IP address we can't connect by telnet and sending a UDP broadcast message fails. (Creating and binding the socket works fine, but sendto() returns -1).

    Here is the code snippet which I used to test sending:

    fdOpenSession( TaskSelf() );

    s = socket(AF_INET, SOCK_DGRAM, 0);

    memset(&sockAddr, 0, sizeof(struct sockaddr_in));

    sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);

    sockAddr.sin_family = AF_INET;

    sockAddr.sin_port = htons(0xCB04);

    res = bind(s, &sockAddr, sizeof(struct sockaddr_in));

    memset(&sockAddr, 0, sizeof(struct sockaddr_in));

    sockAddr.sin_family = AF_INET;

    sockAddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);

    sockAddr.sin_port = htons(0xCB04);

    res = sendto(s, "Test", 4, 0, (struct sockaddr*)&sockAddr, sizeof(struct sockaddr));

    Do you have any idea what could be wrong and what we should check first?

    BR,

    Lars

  • Hi Pavel,

    we managed to do the next step - and run into the next problem ...

    Lars Beikirch said:

    The ICMP receive loop never receives any data when sending e.g. a ping request, ...

    Well, in fact no ICMP packet actually reached the DM8148 since my PC didn't find the device in it's ARP table. Now we found in the cfgdemo example description in the NDK manuals that we had to add the ARP entry by hand and after doing so it worked fine.

    Could you give us a hint how to enable ARP handling in the NDK?

    Lars Beikirch said:

    and even if we modify the example by setting a fixed IP address we can't connect by telnet and sending a UDP broadcast message fails. (Creating and binding the socket works fine, but sendto() returns -1).

    My fault: After setting the socket option SO_BROADCAST it worked fine as well.

    Now the next issue:

    While testing the Telnet server we see frequently "TCP retransmissions" in the Wireshark logging - quite often for packets from PC to DM, but sometimes for packets from DM to PC as well. At Thomas' CCS we can see some CCS console output "TCP: Retransmit Timeout". We don't understand why we see it on his PC, but not on mine. Sooner or later the telnet connection stops working at all and can't be reestablished as well.

    Any idea on that?

    BR,

    Lars

  • Lars Beikirch said:

    While testing the Telnet server we see frequently "TCP retransmissions" in the Wireshark logging - quite often for packets from PC to DM, but sometimes for packets from DM to PC as well.

    My fault again: I am using a mirror switch to record network traffic. Accidently I used the same PC port for communication and mirroring. Thus WireShark recorded each packed twice: as normal transmission and as the mirrored packet from the switch. This was interpreted as "Retransmission" by WireShark ...

    Well, looks like we have the NDK working fine on the ARM with SYS/BIOS :-)

    BR, Lars