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.

CCS: TI 28377D's EMIF interface communicate with ET1100 , 8 bit uC

Tool/software: Code Composer Studio

Now I am using 28377d and ET1100 to develop a ECAT servo. We use 8 bit Asynchronous µController Interface to transfer data between 28377 and ET1100. As to the EMIF, my configuration is as follows(use TI's demo project "pdi_hal_test_app" as reference):

                Emif1Regs.ASYNC_CS2_CR.all =  (EMIF_ASYNC_ASIZE_8    | // 8 Bit Memory

                                                                        // Interface

                                               EMIF_ASYNC_TA_1        | // Turn Around time

                                                                       

                                               EMIF_ASYNC_RHOLD_4     | // Read Hold time

                                                                        

                                               EMIF_ASYNC_RSTROBE_10   | // Read Strobe time

                                                                      

                                               EMIF_ASYNC_RSETUP_6    | // Read Setup time

                                                                         

                                               EMIF_ASYNC_WHOLD_2     | // Write Hold time

                                                                         

                                               EMIF_ASYNC_WSTROBE_8   | // Write Strobe time

                                                                      

                                               EMIF_ASYNC_WSETUP_4    | // Write Setup time

                                                                        

                                               EMIF_ASYNC_EW_ENABLE  | // Extended Wait

                                                                     

                                               EMIF_ASYNC_SS_DISABLE    // Strobe Select Mode

                                                                    

                                              );

Now the problem is: When runs in DC mode with Twincat as the ECAT master, Twincat delivers 0x1b error about every 20 seconds. the PDI error register 0x30d's value is alwas 0xff rather 0. I have asked ETG for help. After I changed the watchdog from reading ET1100's register 0x440 to software watchdog which only use 28377 own timer, there's no 0x1b error any more(0x1b means sync manager watchdog error or timeout). This means there is something wrong in PDI interface, which results in reading 0x440 from ET1100 error. And if ignore this error, other things like PDO and SDO both work nomally.

 

In fact, if I use the following TI's demo project "pdi_hal_test_app" EMIF configuration absolutely, another problem often occurs when ECAT master change slave's state from PREOP to OP, the error says "read status 0x04, and status 0x08 expected", then the slave's state falls into SAFEOP ERR. And the two EMIF configuration's difference is I add two CLKs in each EMIF read stage. This may make sure PDI's read operation more stable. But I am not sure what I guess is right or not. And If i add 4 read CLKs or more, the ECAT servo slave will always falls in INIT ERR state. So I am really confused with EMIF configuration. Could you give me some advice and help? Thank you very much.

 

                Emif1Regs.ASYNC_CS2_CR.all =  (EMIF_ASYNC_ASIZE_8    | // 8Bit Memory

                                                                        

                                               EMIF_ASYNC_TA_1        | // Turn Around time

                                                                     

                                               EMIF_ASYNC_RHOLD_2     | // Read Hold time

                                                                        

                                               EMIF_ASYNC_RSTROBE_8   | // Read Strobe time

                                                                        

                                               EMIF_ASYNC_RSETUP_4    | // Read Setup time

                                                                       

                                               EMIF_ASYNC_WHOLD_2     | // Write Hold time

                                                                        

                                               EMIF_ASYNC_WSTROBE_8   | // Write Strobe time

                                                                      

                                               EMIF_ASYNC_WSETUP_4    | // Write Setup time

                                                                       

                                               EMIF_ASYNC_EW_ENABLE  | // Extended Wait

                                                                      

                                               EMIF_ASYNC_SS_DISABLE    // Strobe Select Mode

                                                                     

                                              );

2. Besides, I find EMIF write operation is much slower than EMIF read operation. That is, *XMEM_ps++ = *pTxData++ takes about 21 us, while read operation takes about 300ns/BYTE. I am not sure whether this has something to do with the 0x1b ERROR or not. Thank you.

  • Hi,

    on the 0x1b error (SM WDOG timeout) :- If you see that the number of times the slave stack detects WDOG error is equal to the WDOG counter register value then you might want to increase the default watch dog timeout from the master. But if you see that the slave stack is detecting WDOG status error while the watchdog error counter (0x442 or 0x443) doesn't increment then it is a problem with the PDI. Try to increase the RSTROBE to 56 (560ns is the absolute max time as per ET1100 datasheet) and check. Once it works then try to decrement the RSTROBE and find an optimal value.

    Please let me know how it goes. The EMIF timings/settings configured in the PDI example are for demo, users have to come up with what finally works for their HW, so it is ok if you have to change the settings.

    Once this is fixed we can discuss about the read/write cycles. I can loop in other EMIF experts from the team as needed.

    Hope this helps.

    Best Regards

    Santosh Athuru

  • Hi,

    Thank you for your reply. If I increase RSTROBE to 56, the slave will always stay in INI ERR state. And with the RSTROBE is 10, I read 0x442 in Twincat, the value is always 0. While 0x30d( PDI/CRC ERR) is always 0xff, even I write 0 to reset it, it will come back to 0xff very soon again.

    As to I change the demo's EMIF configuration, I mean that if i do not change it, there is the timeout error( expect 0x08 and read 0x04, and the slave fall into SAFEOP ERR rather OP), so I guess there must be someting wrong in EMIF configuration. But how to change it, I am not clear. Thank you.

    By the way, EMIF runs in 200MHZ based clock. That is, ClkCfgRegs.PERCLKDIVSEL.bit.EMIF1CLKDIV = 0x0;

    Best Regards

    Yanpo, Li

  • By the way, my EMIF CLK configuration as following: ClkCfgRegs.PERCLKDIVSEL.bit.EMIF1CLKDIV = 0x0;
    And as to EMIF, i feel that each stage clk number is not the longer the better. And I use EMIF 8 bit.

    Best Regards
    Yanpo, Li
  • Besides, as to 0x442, I find only when I switch the state between OP and PREOP, will the 0x442's value increase. And each switch increase 1. Thank you.

    Best Regards
    Yanpo, Li
  • Yanpo,

    Can we first make sure you have a proper EMIF configuration and can read the ET1100 registers (for ex: 0x140) and write and read the RAM locations of ET1100? can you try EMIFCLK of 100MHz? 

    Is your EEPROM properly configured for 8 bit uController Async access?

    Having PDI error definitely means you have problem with the EMIF configuration or the GPIOs used for EMIF configuration. Did you always have this error counter issue or does it come when you change the EMIF configurations. I'm trying to understand if you ever had a PDI access without errors so far in your project?

    Best Regards

    Santosh Athuru

  • Hi Santosh,

    I have read 0x140 from Twincat, its value is 0x0e09. I also change emifclk to 100MHZ now. In fact if Twincat runs in non-DC mode, then there is no 0x1b error. All pdo and SDO work noamlly. So I think at least most ot the work time, EMIF works OK. Only sometimes it fails.

    I have tried at least ten kinds of different configuration. But none works without errors. Some configuration 0x1b error occurs about every 1 minute, some occurs about every half minute. Thank you.

    Best Regards
    Yanpo, Li
  • Hi Santosh,

    As to 8 bit EMIF, in fact every read operation is still 16bit, maybe because TI's basic variable length is 16bit. So when i read a 16 bit data, i have to read the same address twice. The following is a read example. While as to write operation each 16 bit data I only need to write once. I am not sure whether this is nomal. Thank you.

    void HW_EscReadIsr( MEM_ADDR *pRXData, UINT16 Address, UINT16 Len )
    {
    Uint16 *pTmpData = (Uint16 *)pRXData;
    Uint16 *XMEM_ps;
    Uint16 Dummydata;
    Uint16 i=0;
    DINT;
    for(i=0;i<Len/2;i++)
    {
    XMEM_ps = (Uint16 *)(Address/2+i+ASRAM_CS2_START_ADDR);//28377EMIF外设起始地址0x100000
    Dummydata = *XMEM_ps; // first time read
    Dummydata = *XMEM_ps; // second time read
    *pTmpData++ = SWAP_WORD(Dummydata);
    }
    EINT;
    }

    void HW_EscWrite(MEM_ADDR *pTxData, UINT16 start_addr, UINT16 len)
    {
    Uint16 *XMEM_ps;
    Uint16 i=0;

    for(i=0;i<len/2;i++)
    {
    XMEM_ps = (Uint16 *)(start_addr/2+i+ASRAM_CS2_START_ADDR);//28377EMIF外设起始地址0x100000

    *XMEM_ps++ = *pTxData++;
    }
    }

    Best Regards,
    Yanpo, Li
  • Hi,

    As to 8 bit EMIF, in fact every read operation is still 16bit, maybe because TI's basic variable length is 16bit. So when i read a 16 bit data, i have to read the same address twice. The following is a read example. While as to write operation each 16 bit data I only need to write once. I am not sure whether this is nomal.

    Yes, C28x is 16bit processor. On READ/WRITE operation via EMIF, if external memory is 8bit then for 16bit access EMIF will split it into 2 8bit access and perform the READ/WRITE operation. You don't have to do two access for that.

    Regards,

    Vivek Singh 

  • Yanpo,

     

    user4435347 said:
    I have read 0x140 from Twincat, its value is 0x0e09. I also change emifclk to 100MHZ now. In fact if Twincat runs in non-DC mode, then there is no 0x1b error. All pdo and SDO work noamlly. So I think at least most ot the work time, EMIF works OK. Only sometimes it fails.

    I have tried at least ten kinds of different configuration. But none works without errors. Some configuration 0x1b error occurs about every 1 minute, some occurs about every half minute. Thank you.

    With reference to the above when the reads for register 0x140 works, did you try any writes to the DPRAM locations as well? So with this EMIF configuration you have ZERO PDI errors.

    Only problem is with DCx enabled you see a WatchDOG timeout error? and You also see the WDOG counter increments in this case? Did you rule out any TwinCAT configuration issues? did you try increasing the SM WDOG timeout value from TwinCAT for the slave node?

    I want you to rule out any other possible errors and confirm that the Slave node (TwinCAT reading 0x1B) is detecting WDOG timeout without the WDOG error counter getting incremented before we suspect the EMIF configuration.

    Can we fix this issue before moving to "how to handle bytes vs 16 bit words in the HAL API"?

    Best Regards

    Santosh Athuru

    Best Regards
    Santosh

  • Hi Santosh,

    I wirte a small program about writing DPRAM and reading DPRAM. In my program, from 0x2000 to 0x2064, I write a diffrent value in each register, and read and compare it with the write value. I find sometimes they really different. If i watch them in debug mode of CCS, then i can find that, for example, progaram says when i=10 , they are different( program enter in the "return 1" break point). But at this time, I move the mouse arrow to *XMEM_ps, the popup window displays the value is right. while the mem_rds[i] is really a wrong and different value with *XMEM_ps.

    At first time, I think if I read two times of every register, this problem can be solved. However, even I read four times of every register, this problem still occur. I think that is why when in OP mode, there is always sometimes program read 0x440 and get a wrong 0 value and think it is a timeout signal. But very possible now 0x440's true value is still 1, but the program read a wrong 0.
    Could you help me solve this problem first, then I will not need to read every register two times or three times. Maybe other timeout problem can be solved at the same time. Thank you.

    XMEM_ps = (unsigned short *)start_addr; // start_addr = 0x101000
    //
    //Fill memory
    //
    for (i=0; i < mem_size*2; i++)
    {
    mem_wds[i]= 0x1000*i+i*2;
    *XMEM_ps = (0x1000*i>>8)+(i*2<<0x8);
    XMEM_ps++;
    }

    XMEM_ps = (unsigned short *)(start_addr);
    for (i=0; i < mem_size; i++)
    {
    mem_rds[i] = *XMEM_ps; // first time read
    mem_rds[i] = *XMEM_ps; // second time read
    if( mem_rds[i] != mem_wds[i])
    {
    return(1); // add break point here
    }
    XMEM_ps++;
    }
    return(0);

    Best Regards
    Yanpo, Li
  • Hi,

    Beisdes, to test it, I add read 0x440 again in function " CheckIfEcatError" of ecatslv.c, like the following. After I add this , in DC OP mode of twincat , even over 30minutes there is no 0x1b error. So i think before this when twincat tells me there is a 0x1b error, in fact there is no timeout error, there is only something wrong in EMIF read operation. This can also explian why 0x30d's value is always 0xff, even in INIT state.
    But this is only a test, the problem is still there. We must know why sometimes after the read operation, like mem_rds[i] = *XMEM_ps; , mem_rds[i] is different of *XMEM_ps, or only the high byte or lowbyte is the same of *XMEM_ps. Even read four times this still occurs or even get worse. I can not understand why. Thank you.

    HW_EscReadWord(WdStatusOK,ESC_PD_WD_STATE);
    WdStatusOK = SWAPWORD(WdStatusOK);//0 means timeout
    if(!(WdStatusOK & ESC_PD_WD_TRIGGER_MASK))
    {
    /*The device is in OP state*/
    HW_EscReadWord(WdStatusOK,ESC_PD_WD_STATE); // extra add. when got a 0 from 0x440, read it again.
    if(!WdStatusOK & bEcatOutputUpdateRunning /* if the extra read of 0x440 get a 0 again ,then tell the master timeout 0x1b error*/
    /*Slave Stack Code Tool :(#if !OP_PD_REQUIRED) lines 2807 to 2809 deleted*/
    )
    {
    AL_ControlInd(STATE_SAFEOP,ALSTATUSCODE_SMWATCHDOG);
    return;
    }
    ......

    Best Regards,
    Yanpo, Li
  • Yanpo,
    on the Twincat master side for the EtherCAT slave box, if you view the EtherCAT->Advanced settings->memory menu and view the address 440 . You will see WD Status at 440 and WD PDI/SM Counter at 442. Can you write 0 (you will have to click on write button after writing 0) at location 442 from TwinCAT master. This will reset the counters.

    You can do the above while slave stack code is running and clearly check when the slave stack detects WD Status as 0x0, the counter (@442 in TwinCAT memory window) incremented or not.

    Doing above will conclude that there is a problem with EMIF. I wrote similar code for debug like you did when I fixed bug in my EMIF 16 bit implementation, I had to increase my RSTROBE time.

    There is not much to this error other than finding out the proper EMIF settings. You said you configured EMIF at 200MHz, can you try using 100MHz clock for EMIF and below settings? If you are using 200MHz then I would double each of these values.

    Emif1Regs.ASYNC_CS2_CR.all = (EMIF_ASYNC_ASIZE_8 |
    EMIF_ASYNC_TA_1 | // Wr to Rd turnaround
    EMIF_ASYNC_RHOLD_2 | //
    EMIF_ASYNC_RSTROBE_56 | //
    EMIF_ASYNC_RSETUP_4 | //
    EMIF_ASYNC_WHOLD_2 | //
    EMIF_ASYNC_WSTROBE_28 | //
    EMIF_ASYNC_WSETUP_4 |
    EMIF_ASYNC_EW_ENABLE | // EMIF_ASYNC_EW_DISABLE
    EMIF_ASYNC_SS_DISABLE // Strobe Select Mode Disable.
    );
    Emif1Regs.ASYNC_WCCR.bit.WP0 = 1; // Active-high Wait Polarity for EM1WAIT.
    Emif1Regs.ASYNC_WCCR.bit.MAX_EXT_WAIT = 0x1;


    Best Regards
    Santosh Athuru
  • Hi,

    Now I also believe that there is a problem with EMIF. I have wirtten a small program to write a fix value in each register of ET1100 from 0x2000, and read them back. Compare them , if they do not equal, the errcnt++. In debug mode, I test different settings of EMIF. with 2, 56, 4(EMIF_ASYNC_RHOLD_2 | //EMIF_ASYNC_RSTROBE_56 | //EMIF_ASYNC_RSETUP_4 | //) what I read back is all 0. When change to 2, 28, 4 is also all 0. Untill when change to 2, 21, 4, then I can read back some registers' value, about 15% is right. When change to 2, 20, 4, is about 50% right. When changed to 2, 18, 4, is about 63% right. And all this only need to be read once.
    However, when change to 2, 14, 4, none is right, I have to read twice every register, then i can read back the right vlaue. For example, the value I write is 0x0001 0x1002 0x2003 0x3004 in each register, when RSTROBE is bigger than 18, then what i read back is also the same or 0. When RSTROBE is less than 14, If I only read once of each register, then the value I read back is 0x0055 0x1001 0x2002 0x3003 0x4004, that is, I need to treat them as a whole, and left them 1 byte. However, if I just read every register twice, like the following, then the result is right.
    mem_rds[i] = *XMEM_ps;
    mem_rds[i] = *XMEM_ps;
    If this way I can get all the right value is also OK. But when I test many times, I find that every 100 times to2000 times there is one error. This can also explain why every about 1 second to 20 second there is a 0x1b error occurs. And if i read 0x440 again when i get a 0 from it, then nearly every time the 0x440's value is right. And there is no 0x1b error any more. The following is my test program.
    while(1)
    {
    XMEM_ps = (unsigned short *)start_addr;
    addcnt++;
    for (i=0; i < mem_size*2; i++) //***mem_size = 50***
    {
    mem_wds[i]= 0x1000*i+(i+1);
    *XMEM_ps = (0x1000*i>>8)+((i+1)<<0x8);//mem_wds[i];//
    XMEM_ps++;
    }

    XMEM_ps = (unsigned short *)(start_addr);
    for (i=0; i < mem_size*2; i++) //***mem_size = 50***
    {
    mem_rds1[i] = *XMEM_ps;
    mem_rds[i] = *XMEM_ps;

    if( mem_rds[i] != mem_wds[i])
    {
    ErrCount++; // ***add a breakpoint here***
    addcnt=0;
    }
    XMEM_ps++;
    }
    }

    when I wath the addcnt's value in the breakpoint, its value range from 100 to 2000. Until now the best settings of EMIF is 2, 9, 4(RSTROBE =9). addcnt's value range from 400 to 2500. But no matter how I change the settings, there is always error occurs, even they are quite rare. So can you tell me how to eliminate the error absolutely? Thank you.

    Best Regards,
    Yanpo, Li
  • Hi,

    By the way, I think I must detail the error's character. When the program enter into the breakpoint position, When I move my mouse arrow to the variable mem_rds, its value displays is really wrong. However, when I move the mouse arrorw to *XMEM_ps, it display is quite right. That means if I read it once again, I can get the right value again. I do not know why. And if I read 4 times for every register, is also the same case. So I can not just increase the read times. Thank you.

    Best Regards
    Yanpo, Li
  • Yanpo,
    I request you to go through the EMIF ASYNC_CS2_CR register description to understand the each bit fields that you are writing to. For the write path you will have to adapt the W_SETUP, W_STROBE, W_HOLD values and the respective ones for the read path.

    You will also have to refer to the ET1100 data sheet , PDI specifications for the timing of ASYNC8/16 interface and come up with the values for the EMIF ASYNC_CS2_CR register.

    To make sure the writes are going correctly, I would use TWINCAT memory window verify. Because you don't know if the write path is not correct or the read path is. You can also write to the RAM from TWINCAT and verify the EMIF read path.

    That is how I approached for the 16 bit EMIF interface talking to ET1100 ASYNC16 PDI, solution.

    Also as Vivek mentioned in the previous post, C28x throws two EMIF reads for every 16 bit read on a 8 bit EMIF interface.

    quote: Vivek Singh from earlier reply
    <:
    Yes, C28x is 16bit processor. On READ/WRITE operation via EMIF, if external memory is 8bit then for 16bit access EMIF will split it into 2 8bit access and perform the READ/WRITE operation. You don't have to do two access for that.
    :>


    Best Regards
    Santosh Athuru
  • Hi Santosh,

    I have solved this problem. What i do is wirte 0 to Emif1Regs.ASYNC_WCCR.bit.WP0. For in ET1100 BUSY pin is also valid in low level. Thank you.
  • Yanpo,
    thanks for the update. We have configured the BUSY to be active high in our EEPROM settings. I'm glad you found the issue.
    I will make a note to document the settings in the next release.

    Best Regard
    Santosh Athuru