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.

Configuring EtherCAT Distributed Clocks using HWI instead of Tasks on AM335x

Other Parts Discussed in Thread: AM3359

Hi,

I'm trying to create an EtherCAT Slave application to run on the Sitara AM3359 (currently using the AM335x ICEv2 board) that uses Distributed Clocks in order to minimize jitter between EtherCAT slave devices.  I found that using the SYNC tasks (enabled by default with #define ENABLE_SYNC_TASK) resulted in relatively high jitter (4~8 μs) in the application reacting to D.C. SYNC0 pulses.

Reading the PRU ICSS EtherCAT firmware guide, it appears to switch the SYNC tasks to a HWI all I have to do is comment out two #define's in tiescbsp.h, as per the following instructions:

"if ENABLE_PDI_TASK and ENABLE_SYNC_TASK are NOT defined in tiescbsp.h, PDI and SYNC0 ISR processing will happen in SYS/BIOS HWI context. This is similar to SSC architecture."

However when I un-comment those #define's, I get the following compilation errors:

../EcatStack/tiescbsp.c: In function 'bsp_start_esc_isr':
../EcatStack/tiescbsp.c:1235:5: warning: implicit declaration of function 'PRUSSDRVRegisterIrqHandler' [-Wimplicit-function-declaration]
PRUSSDRVRegisterIrqHandler(HOST_AL_EVENT, 0, &EcatIsr, PRUSS_INSTANCE_IN_USE);
^
../EcatStack/tiescbsp.c:1235:60: error: 'PRUSS_INSTANCE_IN_USE' undeclared (first use in this function)
PRUSSDRVRegisterIrqHandler(HOST_AL_EVENT, 0, &EcatIsr, PRUSS_INSTANCE_IN_USE);
^
../EcatStack/tiescbsp.c:1235:60: note: each undeclared identifier is reported only once for each function it appears in
../EcatStack/tiescbsp.c:1288:5: error: 'pruIsrNum' undeclared (first use in this function)
pruIsrNum = HOST_SYNC0_EVENT;
^
../EcatStack/tiescbsp.c:1305:14: error: redefinition of 'evtOutNum'
uint32_t evtOutNum = HOST_SYNC1_EVENT - 20;
^
../EcatStack/tiescbsp.c:1290:14: note: previous definition of 'evtOutNum' was here
uint32_t evtOutNum = HOST_SYNC0_EVENT - 20;

Is there any additional setup/configuration required to use HWI's for the SYNC0 ISR?

My development environment:

  • SYS/BIOS 6.45.1.29
  • SYS/BIOS Industrial SDK 2.1.1.2
  • XDCtools 3.32.0.06_core
  • Compiler GNU v4.9.3 (Linaro)
  • AM335x Industrial Communication Engine EVM rev2.1
  • I will ask the ISDK team to look at this.
  • Update: I managed to get D.C. SYNC functionality working with HWI's... it seems most of the compiler errors I reported were a result of ALSO trying to port PDI functionality to a HWI.

    To get Sync0Isr running as a HWI, I did the following:

    1. In tiescbsp.h, remove (comment out) the line that reads #define ENABLE_SYNC_TASK (as per instructions in the EtherCAT Firmware Guide)
    2. In tiescbsp.c in function bsp_start_esc_isr, add curly braces around the following code (around lines 1288)
          uint32_t evtOutNum = HOST_SYNC0_EVENT - 20;
          sync0IsrArgs = (PRUICSS_IrqArgs* )malloc(sizeof(PRUICSS_IrqArgs));
          sync0IsrArgs->handle = pruIcssHandle;
          PRUICSS_registerIrqHandler(sync0IsrArgs,
                                     evtOutNum,
                                     pruIsrNum,
                                     1,           /* Used for C66x */
                                     0,
                                     &Sync0Isr);
      

      and

          uint32_t evtOutNum = HOST_SYNC1_EVENT - 20;
          sync1IsrArgs = (PRUICSS_IrqArgs* )malloc(sizeof(PRUICSS_IrqArgs));
          sync1IsrArgs->handle = pruIcssHandle;
          PRUICSS_registerIrqHandler(sync1IsrArgs,
                                     evtOutNum,
                                     pruIsrNum,
                                     1,           /* Used for C66x */
                                     0,
                                     &Sync1Isr);

      This will get rid of the compiler warnings "error: redefinition of 'evtOutNum'"

    It looks like to get the SYNC functionality working there needs to be some minor code fixes to tiescbsp.c

    However, I'm still observing jitter between the SYNC0 pulse from the PRUs and Sync0Isr; typically it responds to the SYNC0 pulse within 1.3 microseconds, but I've seen latency's as high as 6 microseconds, which is longer than my hard real-time deadline.  The ISR never responds quicker than 1 microsecond.

    Where is the HWI actually declared in the code?  I see 'PRUICSS_registerIrqHandler' being called (code above), but I don't see a call to 'Hwi_create' anywhere.  Is a call to Hwi_create not necessary with PRUICSS interrupts?  What is the HWI priority of these Sync ISRs?

  • Jeff,

    Somehow we missed your post. The Hwi_create() is called in HwiOSAL_registerInterrupt() in sdk/os_drivers/source/osdrv_osal.c. Here is the PRUICSS_registerIrqHandler() call flow:

    1. ./sdk/os_drivers/lld/pruss/pruicss_intc.c:
    int PRUICSS_registerIrqHandler(PRUICSS_IrqArgs *irqArgs,
    uint32_t pruEvtoutNum,
    int intrNum,
    int eventNum,
    uint8_t waitEnable,
    PRUICSSDRV_IRQ_HANDLER irqHandler
    )
    {
    ...
    hwiHandle = PRUICSS_osalRegisterInterrupt(intrNum, eventNum,
    PRUICSS_hwiIntHandler,
    (void *)(irqArgs), pruEvtoutNum + 20);
    ...
    }

    2. ./sdk/os_drivers/lld/pruss/pruicss_osal.h:
    #define PRUICSS_osalRegisterInterrupt(X,Y,Z,U,V) HwiOSAL_registerInterrupt(X,Y,Z,U,V)

    3. /sdk/os_drivers/source/osdrv_osal.c:
    void *HwiOSAL_registerInterrupt(int32_t intNum, int32_t eventID,
    HwiOSAL_EntryFxn entry, void *arg, uint8_t priority)

    {
    ...
    hwhandle = Hwi_create(intNum, (Hwi_FuncPtr)entry, &hwiParams, &eb);
    ...
    }

    HWI priority should be highest priority 0 by default.

    Regards,
    Garrett