EtherCAT Slave
 
Loading...
Searching...
No Matches
EtherCAT_Slave_CiA402.c

EtherCAT® Slave Example Application with CiA402 Profile.

EtherCAT® Slave Example Application with CiA402 Profile.

Author
KUNBUS GmbH

Copyright (c) 2024 KUNBUS GmbH.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer./
  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#define TIESC_HW 0
#define PRU_200MHZ 1
/* this one shall the only one to be using it ! */
#include "project.h"
#include "ecSlvCiA402.h"
#if (defined FBTL_REMOTE) && (FBTL_REMOTE==1)
#if (defined FBTLIMPL_LINEUART) && (1==FBTLIMPL_LINEUART)
#include "sysLib_lineUart.h"
#else
#include <sysLib_sharedMemory.h>
#endif
#endif
/* OS */
#include <osal.h>
/* ESL */
#include <ESL_os.h>
#include <ESL_BOARD_config.h>
#include <ESL_BOARD_OS_config.h>
#include <ESL_cia402Obd.h>
#include <ESL_version.h>
/* stack */
#include <ecSlvApi.h>
/* @cppcheck_justify{misra-c2012-8.9} prefer module global over threadsafety */
/* cppcheck-suppress misra-c2012-8.9 */
static OSAL_PJumpBuf_t farJumpBuf_cia;
static uint32_t EC_SLV_APP_CIA_remoteInit(EC_SLV_APP_CIA_Application_t *applicationInstance);
static void EC_SLV_APP_CIA_loopTask(void *pArg_p)
{
/* @cppcheck_justify{misra-c2012-11.5} generic API requires cast */
/* cppcheck-suppress misra-c2012-11.5 */
uint32_t error = EC_API_eERR_NONE;
char *pProductName = NULL;
uint32_t vendorId = 0;
uint32_t productCode = 0;
uint16_t alErrorCode = 0;
if (!pApplicationInstance)
{
/* @cppcheck_justify{misra-c2012-15.1} goto is used to assure single point of exit */
/* cppcheck-suppress misra-c2012-15.1 */
goto Exit;
}
EC_SLV_APP_CIA_initBoardFunctions(pApplicationInstance);
EC_SLV_APP_CIA_registerStacklessBoardFunctions(pApplicationInstance);
error = EC_API_SLV_stackInit(); // EtherCAT stack init
if (error != EC_API_eERR_NONE)
{
OSAL_printf("%s:%d Error code: 0x%08x\r\n", __func__, __LINE__, error);
OSAL_error(__func__, __LINE__, OSAL_STACK_INIT_ERROR, true, 0);
}
EC_SLV_APP_cia402_initAxisObjects(pApplicationInstance);
EC_SLV_APP_CIA_applicationInit(pApplicationInstance);
EC_API_SLV_getVendorId(pApplicationInstance->ptEcSlvApi, &vendorId);
EC_API_SLV_getProductCode(pApplicationInstance->ptEcSlvApi, &productCode);
error = EC_API_SLV_getProductName(pApplicationInstance->ptEcSlvApi, &pProductName);
OSAL_printf("%s - %xh / %xh\r\n", pProductName, vendorId, productCode);
/* spit out versions */
ESL_dumpVersions(pApplicationInstance->ptEcSlvApi);
error = EC_SLV_APP_CiA_fetchAxisObjects(pApplicationInstance);
if (error != EC_API_eERR_NONE)
{
OSAL_printf("%s:%d Error code: 0x%08x\r\n", __func__, __LINE__, error);
OSAL_error(__func__, __LINE__, OSAL_STACK_INIT_ERROR, true, 0);
}
for(;;)
{
#if (defined GPIO_TEST_PINS) && (1==GPIO_TEST_PINS)
#if (defined GPIO_TEST_PROFILE_SEL) && (defined GPIO_TEST_PROFILE_1) && (GPIO_TEST_PROFILE_1 == GPIO_TEST_PROFILE_SEL)
ESL_GPIO_testPins_set(ESL_TESTPIN_STATE_REG_BANK, ESL_TESTPIN_0_MASK/*|ESL_TESTPIN_1_MASK*/);
#endif
#endif
EC_API_SLV_mainLoopCyclic();
#if (defined GPIO_TEST_PINS) && (1==GPIO_TEST_PINS)
#if (defined GPIO_TEST_PROFILE_SEL) && (defined GPIO_TEST_PROFILE_1) && (GPIO_TEST_PROFILE_1 == GPIO_TEST_PROFILE_SEL)
ESL_GPIO_testPins_clear(ESL_TESTPIN_STATE_REG_BANK, ESL_TESTPIN_0_MASK);
#endif
#endif
EC_API_SLV_getState(pApplicationInstance->ptEcSlvApi, &state, &alErrorCode);
if (EC_API_SLV_eESM_init < state)
{
OSAL_SCHED_yield();
}
else
{
/* for carve up give some air */
OSAL_SCHED_sleep(10);
}
}
// not reachable
//EC_SLV_APP_applicationDeInit();
Exit:
ESL_OS_taskLeave();
return;
}
static void EC_SLV_APP_CIA_mainTask(void *pArg_p)
{
/* @cppcheck_justify{misra-c2012-11.5} generic API requires cast */
/* cppcheck-suppress misra-c2012-11.5 */
uint32_t retVal = OSAL_ERR_NoError;
if (!applicationInstance)
{
OSAL_error(__func__, __LINE__, OSAL_ERR_InvalidParm, true, 1, "Application instance missing!!!\r\n");
goto Exit;
}
retVal = ESL_OS_boardInit(applicationInstance->selectedPruInstance);
if (OSAL_ERR_NoError != retVal)
{
OSAL_error(__func__, __LINE__, retVal, true, 1, "OS Board init error\r\n");
}
OSAL_registerPrintOut(NULL, ESL_OS_printf);
retVal = EC_SLV_APP_CIA_remoteInit(applicationInstance);
if(!((OSAL_CONTAINER_LOCALIMPLEMENTATION == retVal) || (OSAL_ERR_NoError == retVal)))
{
OSAL_error(__func__, __LINE__, OSAL_ERR_InvalidParm, true, 1, "Fatal error remote API init!!!\r\n");
/* @cppcheck_justify{misra-c2012-15.1} assure single point of exit */
/* cppcheck-suppress misra-c2012-15.1 */
goto Exit;
}
retVal = EC_API_SLV_load(&farJumpBuf_cia, NULL /* &applErrHandler*/, applicationInstance->selectedPruInstance);
if (EC_API_eERR_NONE == retVal)
{
EC_API_SLV_prepareTasks(KBECSLV_PRIO_PDI, KBECSLV_PRIO_LED, KBECSLV_PRIO_SYNC0, KBECSLV_PRIO_SYNC1);
applicationInstance->loopThreadHandle = OSAL_SCHED_startTask(EC_SLV_APP_CIA_loopTask
,applicationInstance
#if !(defined FBTL_REMOTE) || (0==FBTL_REMOTE)
,OSAL_TASK_Prio_Normal
#else
,OSAL_TASK_Prio_Idle
#endif
,(uint8_t*)EC_SLV_APP_applLoopTaskStack_g
,APPLLOOP_TASK_SIZE_BYTE
,0
,"Appl_LoopTask");
if ( NULL == applicationInstance->loopThreadHandle)
{
OSAL_printf("Error return start Loop Task\r\n");
OSAL_error(__func__, __LINE__, OSAL_STACK_INIT_ERROR, true, 0);
}
OSAL_SCHED_joinTask(applicationInstance->loopThreadHandle);
/* No default tasks (run forever) here, so introduce a wait cycle */
for (;;)
{
OSAL_SCHED_sleep(1000);
}
}
else
{
for (;;)
{
for (;;)
{
OSAL_printf("long jmp restart\r\n");
OSAL_SCHED_sleep(1000);
}
}
}
// not reachable
//ESL_OS_boardDeinit();
//EC_API_SLV_unLoad();
//return 0;
Exit:
return;
}
int main(int argc, char *argv[])
{
/* @cppcheck_justify{threadsafety-threadsafety} no called reentrant */
/* cppcheck-suppress threadsafety-threadsafety */
static uint32_t selectedPruInstance = UINT32_MAX;
/* @cppcheck_justify{threadsafety-threadsafety} no called reentrant */
/* cppcheck-suppress threadsafety-threadsafety */
static EC_SLV_APP_CIA_Application_t applicationInstance = {0};
uint32_t error = OSAL_ERR_NoError;
ESL_OS_init();
#if !(defined FBTL_REMOTE)
selectedPruInstance = ESL_DEFAULT_PRUICSS;
#endif
if (1 < argc)
{
char *inst = argv[1];
selectedPruInstance = strtoul(inst, NULL, 0);
}
#if (defined OSAL_TIRTOS)
/* workaround to assure PRUICSS linkage */
if (0x1000 == argc)
{
/* make this link */
PRUICSS_pruDisable(NULL, 0);
PRUICSS_pruDisable(NULL, 1);
PRUICSS_registerIrqHandler(NULL, 0, 0, 0, 0, NULL);
}
#endif
/* Init osal */
OSAL_init();
applicationInstance.selectedPruInstance = selectedPruInstance;
#if (defined OSAL_FREERTOS)
TaskP_Params_init(&applicationInstance.mainThreadParam);
applicationInstance.mainThreadParam.name = "mainThread";
applicationInstance.mainThreadParam.stackSize = MAIN_TASK_SIZE_BYTE; /* FreeRTOS wants Stacksize in Units, when called direct, using TaskP it's bytes */
applicationInstance.mainThreadParam.stack = (uint8_t*)EC_SLV_APP_mainTaskStack_g;
applicationInstance.mainThreadParam.priority = (TaskP_PRIORITY_LOWEST+1);
applicationInstance.mainThreadParam.taskMain = (TaskP_FxnMain)EC_SLV_APP_CIA_mainTask;
applicationInstance.mainThreadParam.args = (void*)&applicationInstance;
error = TaskP_construct(&applicationInstance.mainThreadHandle
,&applicationInstance.mainThreadParam);
if (SystemP_SUCCESS != error)
{
OSAL_printf("Error setting create thread of %s (%ld)\r\n", applicationInstance.mainThreadParam.name, error);
OSAL_error(__func__, __LINE__, OSAL_STACK_INIT_ERROR, true, 0);
}
#elif (defined OSAL_FREERTOS_JACINTO)
TaskP_Params_init(&applicationInstance.mainThreadParam);
applicationInstance.mainThreadParam.name = (uint8_t*)"mainThread";
applicationInstance.mainThreadParam.stacksize = MAIN_TASK_SIZE_BYTE;
applicationInstance.mainThreadParam.stack = (uint8_t*)EC_SLV_APP_mainTaskStack_g;
applicationInstance.mainThreadParam.priority = (configMAX_PRIORITIES-1);
applicationInstance.mainThreadParam.arg0 = (void*)&applicationInstance;
applicationInstance.mainThreadHandle = TaskP_create(EC_SLV_APP_CIA_mainTask, &applicationInstance.mainThreadParam);
if (NULL == applicationInstance.mainThreadHandle)
{
OSAL_printf("Error setting create thread of %s (%ld)\r\n", applicationInstance.mainThreadParam.name, error);
OSAL_error(__func__, __LINE__, OSAL_STACK_INIT_ERROR, true, 0);
}
#else
applicationInstance.mainThreadHandle = OSAL_SCHED_startTask(EC_SLV_APP_CIA_mainTask, &applicationInstance,
OSAL_TASK_Prio_Idle,
(uint8_t*)EC_SLV_APP_mainTaskStack_g,
MAIN_TASK_SIZE_BYTE, 0, "MainTask");
if ( NULL == applicationInstance.mainThreadHandle)
{
OSAL_printf("Error return start Main Task\r\n");
OSAL_error(__func__, __LINE__, OSAL_STACK_INIT_ERROR, true, 0);
error = OSAL_STACK_INIT_ERROR;
}
#endif
OSAL_startOs();
OSAL_error(__func__, __LINE__, OSAL_ERR_InvalidParm, true, 1, "Not reachable by design!!!\r\n");
// not reachable
//EC_API_SLV_unLoad();
return error;
}
static uint32_t EC_SLV_APP_CIA_remoteInit(EC_SLV_APP_CIA_Application_t *applicationInstance)
{
uint32_t retVal = OSAL_CONTAINER_LOCALIMPLEMENTATION;
if (!applicationInstance)
{
/* @cppcheck_justify{misra-c2012-15.1} goto is used to assure single point of exit */
/* cppcheck-suppress misra-c2012-15.1 */
goto Exit;
}
#if (defined FBTL_REMOTE) && (FBTL_REMOTE==1)
#if (defined FBTLIMPL_LINEUART) && (FBTLIMPL_LINEUART==1)
retVal = SYSLIB_createLibInstanceLine( FBTL_LINE_UART_NAME,
FBTL_MAX_ASYNC_LEN, FBTL_MAX_ASYNC_LEN,
FBTL_MAX_PD_LEN, FBTL_MAX_PD_LEN
#if (defined FBTLTRACECALLS) && (FBTLTRACECALLS==1)
,true
#else
,false
#endif
,&(applicationInstance->remoteHandle)
);
#else
retVal = SYSLIB_createLibInstanceShm(FBTLSHARED_MEM_NAME, FBTLSHARED_MEM_SIZE, false,
FBTL_MAX_ASYNC_LEN, FBTL_MAX_ASYNC_LEN, FBTL_MAX_PD_LEN, FBTL_MAX_PD_LEN
#if (defined FBTLTRACECALLS) && (FBTLTRACECALLS==1)
,true
#else
,false
#endif
,&(applicationInstance->remoteHandle)
);
#endif
#else
OSALUNREF_PARM(applicationInstance);
retVal = OSAL_CONTAINER_LOCALIMPLEMENTATION;
#endif
if(OSAL_CONTAINER_LOCALIMPLEMENTATION == retVal)
{
OSAL_printf("\r\nLocal Implementation\r\n");
}
#if (defined FBTL_REMOTE) && (FBTL_REMOTE==1)
else if(EC_API_eERR_NONE == retVal)
{
retVal = EC_API_SLV_FBTL_configuration(applicationInstance->remoteHandle);
if(EC_API_eERR_NONE != retVal)
{
OSAL_printf("%s:%d Error code: 0x%08x\r\n", __func__, __LINE__, retVal);
OSAL_error(__func__, __LINE__, OSAL_STACK_INIT_ERROR, true, 0);
/* @cppcheck_justify{misra-c2012-15.1} goto is used to assure single point of exit */
/* cppcheck-suppress misra-c2012-15.1 */
goto Exit;
}
}
#endif
else
{
/* nothing to do */
;
}
Exit:
if((OSAL_ERR_NoError != retVal) && (OSAL_CONTAINER_LOCALIMPLEMENTATION != retVal))
{
OSAL_printf("%s:%d::> err ret = 0x%x\r\n", __func__, __LINE__, retVal);
}
return retVal;
}
void EC_SLV_APP_CIA_applicationInit(EC_SLV_APP_CIA_Application_t *pAppInstance_p)
Initialize slave application example.
Definition ecSlvCiA402.c:958
@ EC_API_eERR_NONE
Definition ecSlvApiDef_error.h:45
enum EC_API_SLV_EEsmState EC_API_SLV_EEsmState_t
EC_STATE_T EtherCAT State Machine states.
@ EC_API_SLV_eESM_uninit
Uninitialized State.
Definition ecSlvApi_types.h:70
@ EC_API_SLV_eESM_init
Init State.
Definition ecSlvApi_types.h:71
void * loopThreadHandle
Definition ecSlvCiA402.h:171
void * mainThreadHandle
Definition ecSlvCiA402.h:169
uint32_t selectedPruInstance
Definition ecSlvCiA402.h:159
EC_API_SLV_SHandle_t * ptEcSlvApi
Definition ecSlvCiA402.h:211
void * remoteHandle
Definition ecSlvCiA402.h:175
Definition ecSlvCiA402.h:158