| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156 |
- /*
- * Main CANopen stack file. It combines Object dictionary (CO_OD) and all other
- * CANopen source files. Configuration information are read from CO_OD.h file.
- *
- * @file CANopen.c
- * @ingroup CO_CANopen
- * @author Janez Paternoster
- * @copyright 2010 - 2020 Janez Paternoster
- *
- * This file is part of CANopenNode, an opensource CANopen Stack.
- * Project home page is <https://github.com/CANopenNode/CANopenNode>.
- * For more information on CANopen see <http://www.can-cia.org/>.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #include "CANopen.h"
- #include <stdlib.h>
- /* Global variables ***********************************************************/
- /* #define CO_USE_GLOBALS */ /* If defined, global variables will be used
- instead of dynamically allocated. */
- extern const CO_OD_entry_t CO_OD[CO_OD_NoOfElements]; /* Object Dictionary */
- static CO_t COO; /* Pointers to CANopen objects */
- CO_t *CO = NULL; /* Pointer to COO */
- static CO_CANrx_t *CO_CANmodule_rxArray0;
- static CO_CANtx_t *CO_CANmodule_txArray0;
- static CO_OD_extension_t *CO_SDO_ODExtensions;
- static CO_HBconsNode_t *CO_HBcons_monitoredNodes;
- #if ((CO_CONFIG_GTW) & CO_CONFIG_GTW_ASCII) && !defined CO_GTWA_ENABLE
- #define CO_GTWA_ENABLE true
- #endif
- #if CO_NO_TRACE > 0
- static uint32_t *CO_traceTimeBuffers[CO_NO_TRACE];
- static int32_t *CO_traceValueBuffers[CO_NO_TRACE];
- static uint32_t CO_traceBufferSize[CO_NO_TRACE];
- #endif
- #ifndef CO_STATUS_FIRMWARE_DOWNLOAD_IN_PROGRESS
- #define CO_STATUS_FIRMWARE_DOWNLOAD_IN_PROGRESS 0
- #endif
- /* Verify number of CANopenNode objects from CO_OD.h **************************/
- #if CO_NO_SYNC > 1 \
- || CO_NO_EMERGENCY != 1 \
- || (CO_NO_SDO_SERVER < 1 || CO_NO_SDO_SERVER > 128) \
- || CO_NO_TIME > 1 \
- || CO_NO_SDO_CLIENT > 128 \
- || CO_NO_GFC > 1 \
- || CO_NO_SRDO > 64 \
- || (CO_NO_RPDO < 1 || CO_NO_RPDO > 0x200) \
- || (CO_NO_TPDO < 1 || CO_NO_TPDO > 0x200) \
- || ODL_consumerHeartbeatTime_arrayLength == 0 \
- || ODL_errorStatusBits_stringLength < 10 \
- || CO_NO_LSS_SLAVE > 1 \
- || CO_NO_LSS_MASTER > 1
- #error Features from CO_OD.h file are not corectly configured for this project!
- #endif
- /* Indexes of CO_CANrx_t objects in CO_CANmodule_t and total number of them. **/
- #define CO_RXCAN_NMT 0
- #define CO_RXCAN_SYNC (CO_RXCAN_NMT + CO_NO_NMT)
- #define CO_RXCAN_EMERG (CO_RXCAN_SYNC + CO_NO_SYNC)
- #define CO_RXCAN_TIME (CO_RXCAN_EMERG + CO_NO_EM_CONS)
- #define CO_RXCAN_GFC (CO_RXCAN_TIME + CO_NO_TIME)
- #define CO_RXCAN_SRDO (CO_RXCAN_GFC + CO_NO_GFC)
- #define CO_RXCAN_RPDO (CO_RXCAN_SRDO + CO_NO_SRDO*2)
- #define CO_RXCAN_SDO_SRV (CO_RXCAN_RPDO + CO_NO_RPDO)
- #define CO_RXCAN_SDO_CLI (CO_RXCAN_SDO_SRV + CO_NO_SDO_SERVER)
- #define CO_RXCAN_CONS_HB (CO_RXCAN_SDO_CLI + CO_NO_SDO_CLIENT)
- #define CO_RXCAN_LSS_SLV (CO_RXCAN_CONS_HB + CO_NO_HB_CONS)
- #define CO_RXCAN_LSS_MST (CO_RXCAN_LSS_SLV + CO_NO_LSS_SLAVE)
- #define CO_RXCAN_NO_MSGS (CO_NO_NMT + \
- CO_NO_SYNC + \
- CO_NO_EM_CONS + \
- CO_NO_TIME + \
- CO_NO_GFC + \
- CO_NO_SRDO*2 + \
- CO_NO_RPDO + \
- CO_NO_SDO_SERVER + \
- CO_NO_SDO_CLIENT + \
- CO_NO_HB_CONS + \
- CO_NO_LSS_SLAVE + \
- CO_NO_LSS_MASTER)
- /* Indexes of CO_CANtx_t objects in CO_CANmodule_t and total number of them. **/
- #define CO_TXCAN_NMT 0
- #define CO_TXCAN_SYNC (CO_TXCAN_NMT + CO_NO_NMT_MST)
- #define CO_TXCAN_EMERG (CO_TXCAN_SYNC + CO_NO_SYNC)
- #define CO_TXCAN_TIME (CO_TXCAN_EMERG + CO_NO_EMERGENCY)
- #define CO_TXCAN_GFC (CO_TXCAN_TIME + CO_NO_TIME)
- #define CO_TXCAN_SRDO (CO_TXCAN_GFC + CO_NO_GFC)
- #define CO_TXCAN_TPDO (CO_TXCAN_SRDO + CO_NO_SRDO*2)
- #define CO_TXCAN_SDO_SRV (CO_TXCAN_TPDO + CO_NO_TPDO)
- #define CO_TXCAN_SDO_CLI (CO_TXCAN_SDO_SRV + CO_NO_SDO_SERVER)
- #define CO_TXCAN_HB (CO_TXCAN_SDO_CLI + CO_NO_SDO_CLIENT)
- #define CO_TXCAN_LSS_SLV (CO_TXCAN_HB + CO_NO_HB_PROD)
- #define CO_TXCAN_LSS_MST (CO_TXCAN_LSS_SLV + CO_NO_LSS_SLAVE)
- #define CO_TXCAN_NO_MSGS (CO_NO_NMT_MST + \
- CO_NO_SYNC + \
- CO_NO_EMERGENCY + \
- CO_NO_TIME + \
- CO_NO_GFC + \
- CO_NO_SRDO*2 + \
- CO_NO_TPDO + \
- CO_NO_SDO_SERVER + \
- CO_NO_SDO_CLIENT + \
- CO_NO_HB_PROD + \
- CO_NO_LSS_SLAVE + \
- CO_NO_LSS_MASTER)
- /* Create objects from heap ***************************************************/
- #ifndef CO_USE_GLOBALS
- CO_ReturnError_t CO_new(uint32_t *heapMemoryUsed) {
- int16_t i;
- uint16_t errCnt = 0;
- uint32_t CO_memoryUsed = 0;
- /* If CANopen was initialized before, return. */
- if (CO != NULL) {
- return CO_ERROR_NO;
- }
- /* globals */
- CO = &COO;
- /* CANmodule */
- CO->CANmodule[0] = (CO_CANmodule_t *)calloc(1, sizeof(CO_CANmodule_t));
- if (CO->CANmodule[0] == NULL) errCnt++;
- CO_CANmodule_rxArray0 =
- (CO_CANrx_t *)calloc(CO_RXCAN_NO_MSGS, sizeof(CO_CANrx_t));
- if (CO_CANmodule_rxArray0 == NULL) errCnt++;
- CO_CANmodule_txArray0 =
- (CO_CANtx_t *)calloc(CO_TXCAN_NO_MSGS, sizeof(CO_CANtx_t));
- if (CO_CANmodule_txArray0 == NULL) errCnt++;
- CO_memoryUsed += sizeof(CO_CANmodule_t) +
- sizeof(CO_CANrx_t) * CO_RXCAN_NO_MSGS +
- sizeof(CO_CANtx_t) * CO_TXCAN_NO_MSGS;
- /* SDOserver */
- for (i = 0; i < CO_NO_SDO_SERVER; i++) {
- CO->SDO[i] = (CO_SDO_t *)calloc(1, sizeof(CO_SDO_t));
- if (CO->SDO[i] == NULL) errCnt++;
- }
- CO_SDO_ODExtensions = (CO_OD_extension_t *)calloc(
- CO_OD_NoOfElements, sizeof(CO_OD_extension_t));
- if (CO_SDO_ODExtensions == NULL) errCnt++;
- CO_memoryUsed += sizeof(CO_SDO_t) * CO_NO_SDO_SERVER +
- sizeof(CO_OD_extension_t) * CO_OD_NoOfElements;
- /* Emergency */
- CO->em = (CO_EM_t *)calloc(1, sizeof(CO_EM_t));
- if (CO->em == NULL) errCnt++;
- CO->emPr = (CO_EMpr_t *)calloc(1, sizeof(CO_EMpr_t));
- if (CO->emPr == NULL) errCnt++;
- CO_memoryUsed += sizeof(CO_EM_t) + sizeof(CO_EMpr_t);
- /* NMT_Heartbeat */
- CO->NMT = (CO_NMT_t *)calloc(1, sizeof(CO_NMT_t));
- if (CO->NMT == NULL) errCnt++;
- CO_memoryUsed += sizeof(CO_NMT_t);
- #if CO_NO_SYNC == 1
- /* SYNC */
- CO->SYNC = (CO_SYNC_t *)calloc(1, sizeof(CO_SYNC_t));
- if (CO->SYNC == NULL) errCnt++;
- CO_memoryUsed += sizeof(CO_SYNC_t);
- #endif
- #if CO_NO_TIME == 1
- /* TIME */
- CO->TIME = (CO_TIME_t *)calloc(1, sizeof(CO_TIME_t));
- if (CO->TIME == NULL) errCnt++;
- CO_memoryUsed += sizeof(CO_TIME_t);
- #endif
- #if CO_NO_GFC == 1
- CO->GFC = (CO_GFC_t *)calloc(1, sizeof(CO_GFC_t));
- if (CO->GFC == NULL) errCnt++;
- CO_memoryUsed += sizeof(CO_GFC_t);
- #endif
- #if CO_NO_SRDO != 0
- /* SRDO */
- CO->SRDOGuard = (CO_SRDOGuard_t *)calloc(1, sizeof(CO_SRDOGuard_t));
- if (CO->SRDOGuard == NULL) errCnt++;
- for (i = 0; i < CO_NO_SRDO; i++) {
- CO->SRDO[i] = (CO_SRDO_t *)calloc(1, sizeof(CO_SRDO_t));
- if (CO->SRDO[i] == NULL) errCnt++;
- }
- CO_memoryUsed += sizeof(CO_SRDO_t) * CO_NO_SRDO + sizeof(CO_SRDOGuard_t);
- #endif
- /* RPDO */
- for (i = 0; i < CO_NO_RPDO; i++) {
- CO->RPDO[i] = (CO_RPDO_t *)calloc(1, sizeof(CO_RPDO_t));
- if (CO->RPDO[i] == NULL) errCnt++;
- }
- CO_memoryUsed += sizeof(CO_RPDO_t) * CO_NO_RPDO;
- /* TPDO */
- for (i = 0; i < CO_NO_TPDO; i++) {
- CO->TPDO[i] = (CO_TPDO_t *)calloc(1, sizeof(CO_TPDO_t));
- if (CO->TPDO[i] == NULL) errCnt++;
- }
- CO_memoryUsed += sizeof(CO_TPDO_t) * CO_NO_TPDO;
- /* Heartbeat consumer */
- CO->HBcons = (CO_HBconsumer_t *)calloc(1, sizeof(CO_HBconsumer_t));
- if (CO->HBcons == NULL) errCnt++;
- CO_HBcons_monitoredNodes =
- (CO_HBconsNode_t *)calloc(CO_NO_HB_CONS, sizeof(CO_HBconsNode_t));
- if (CO_HBcons_monitoredNodes == NULL) errCnt++;
- CO_memoryUsed += sizeof(CO_HBconsumer_t) +
- sizeof(CO_HBconsNode_t) * CO_NO_HB_CONS;
- #if CO_NO_SDO_CLIENT != 0
- /* SDOclient */
- for (i = 0; i < CO_NO_SDO_CLIENT; i++) {
- CO->SDOclient[i] =
- (CO_SDOclient_t *)calloc(1, sizeof(CO_SDOclient_t));
- if (CO->SDOclient[i] == NULL) errCnt++;
- }
- CO_memoryUsed += sizeof(CO_SDOclient_t) * CO_NO_SDO_CLIENT;
- #endif
- #if (CO_CONFIG_LEDS) & CO_CONFIG_LEDS_ENABLE
- /* LEDs */
- CO->LEDs = (CO_LEDs_t *)calloc(1, sizeof(CO_LEDs_t));
- if (CO->LEDs == NULL) errCnt++;
- CO_memoryUsed += sizeof(CO_LEDs_t);
- #endif
- #if CO_NO_LSS_SLAVE == 1
- /* LSSslave */
- CO->LSSslave = (CO_LSSslave_t *)calloc(1, sizeof(CO_LSSslave_t));
- if (CO->LSSslave == NULL) errCnt++;
- CO_memoryUsed += sizeof(CO_LSSslave_t);
- #endif
- #if CO_NO_LSS_MASTER == 1
- /* LSSmaster */
- CO->LSSmaster = (CO_LSSmaster_t *)calloc(1, sizeof(CO_LSSmaster_t));
- if (CO->LSSmaster == NULL) errCnt++;
- CO_memoryUsed += sizeof(CO_LSSmaster_t);
- #endif
- #if (CO_CONFIG_GTW) & CO_CONFIG_GTW_ASCII
- /* Gateway-ascii */
- CO->gtwa = (CO_GTWA_t *)calloc(1, sizeof(CO_GTWA_t));
- if (CO->gtwa == NULL) errCnt++;
- CO_memoryUsed += sizeof(CO_GTWA_t);
- #endif
- #if CO_NO_TRACE > 0
- /* Trace */
- for (i = 0; i < CO_NO_TRACE; i++) {
- CO->trace[i] = (CO_trace_t *)calloc(1, sizeof(CO_trace_t));
- if (CO->trace[i] == NULL) errCnt++;
- }
- CO_memoryUsed += sizeof(CO_trace_t) * CO_NO_TRACE;
- for (i = 0; i < CO_NO_TRACE; i++) {
- CO_traceTimeBuffers[i] =
- (uint32_t *)calloc(OD_traceConfig[i].size, sizeof(uint32_t));
- CO_traceValueBuffers[i] =
- (int32_t *)calloc(OD_traceConfig[i].size, sizeof(int32_t));
- if (CO_traceTimeBuffers[i] != NULL &&
- CO_traceValueBuffers[i] != NULL) {
- CO_traceBufferSize[i] = OD_traceConfig[i].size;
- } else {
- CO_traceBufferSize[i] = 0;
- }
- CO_memoryUsed += CO_traceBufferSize[i] * sizeof(uint32_t) * 2;
- }
- #endif
- if (heapMemoryUsed != NULL) {
- *heapMemoryUsed = CO_memoryUsed;
- }
- return (errCnt == 0) ? CO_ERROR_NO : CO_ERROR_OUT_OF_MEMORY;
- }
- /******************************************************************************/
- void CO_delete(void *CANptr) {
- int16_t i;
- CO_CANsetConfigurationMode(CANptr);
- /* If CANopen isn't initialized, return. */
- if (CO == NULL) {
- return;
- }
- CO_CANmodule_disable(CO->CANmodule[0]);
- #if CO_NO_TRACE > 0
- /* Trace */
- for (i = 0; i < CO_NO_TRACE; i++) {
- free(CO->trace[i]);
- free(CO_traceTimeBuffers[i]);
- free(CO_traceValueBuffers[i]);
- }
- #endif
- #if (CO_CONFIG_GTW) & CO_CONFIG_GTW_ASCII
- /* Gateway-ascii */
- free(CO->gtwa);
- #endif
- #if CO_NO_LSS_MASTER == 1
- /* LSSmaster */
- free(CO->LSSmaster);
- #endif
- #if CO_NO_LSS_SLAVE == 1
- /* LSSslave */
- free(CO->LSSslave);
- #endif
- #if CO_NO_SDO_CLIENT != 0
- /* SDOclient */
- for (i = 0; i < CO_NO_SDO_CLIENT; i++) {
- free(CO->SDOclient[i]);
- }
- #endif
- /* Heartbeat consumer */
- free(CO_HBcons_monitoredNodes);
- free(CO->HBcons);
- #if CO_NO_GFC == 1
- /* GFC */
- free(CO->GFC);
- #endif
- #if CO_NO_SRDO != 0
- /* SRDO */
- for (i = 0; i < CO_NO_SRDO; i++) {
- free(CO->SRDO[i]);
- }
- free(CO->SRDOGuard);
- #endif
- /* TPDO */
- for (i = 0; i < CO_NO_TPDO; i++) {
- free(CO->TPDO[i]);
- }
- /* RPDO */
- for (i = 0; i < CO_NO_RPDO; i++) {
- free(CO->RPDO[i]);
- }
- #if CO_NO_TIME == 1
- /* TIME */
- free(CO->TIME);
- #endif
- #if CO_NO_SYNC == 1
- /* SYNC */
- free(CO->SYNC);
- #endif
- /* NMT_Heartbeat */
- free(CO->NMT);
- /* Emergency */
- free(CO->emPr);
- free(CO->em);
- /* SDOserver */
- free(CO_SDO_ODExtensions);
- for (i = 0; i < CO_NO_SDO_SERVER; i++) {
- free(CO->SDO[i]);
- }
- /* CANmodule */
- free(CO_CANmodule_txArray0);
- free(CO_CANmodule_rxArray0);
- free(CO->CANmodule[0]);
- /* globals */
- CO = NULL;
- }
- #endif /* #ifndef CO_USE_GLOBALS */
- /* Alternatively create objects as globals ************************************/
- #ifdef CO_USE_GLOBALS
- static CO_CANmodule_t COO_CANmodule;
- static CO_CANrx_t COO_CANmodule_rxArray0[CO_RXCAN_NO_MSGS];
- static CO_CANtx_t COO_CANmodule_txArray0[CO_TXCAN_NO_MSGS];
- static CO_SDO_t COO_SDO[CO_NO_SDO_SERVER];
- static CO_OD_extension_t COO_SDO_ODExtensions[CO_OD_NoOfElements];
- static CO_EM_t COO_EM;
- static CO_EMpr_t COO_EMpr;
- static CO_NMT_t COO_NMT;
- #if CO_NO_SYNC == 1
- static CO_SYNC_t COO_SYNC;
- #endif
- #if CO_NO_TIME == 1
- static CO_TIME_t COO_TIME;
- #endif
- #if CO_NO_GFC == 1
- static CO_GFC_t COO_GFC;
- #endif
- #if CO_NO_SRDO != 0
- static CO_SRDOGuard_t COO_SRDOGuard;
- static CO_SRDO_t COO_SRDO[CO_NO_SRDO];
- #endif
- static CO_RPDO_t COO_RPDO[CO_NO_RPDO];
- static CO_TPDO_t COO_TPDO[CO_NO_TPDO];
- static CO_HBconsumer_t COO_HBcons;
- static CO_HBconsNode_t COO_HBcons_monitoredNodes[CO_NO_HB_CONS];
- #if CO_NO_SDO_CLIENT != 0
- static CO_SDOclient_t COO_SDOclient[CO_NO_SDO_CLIENT];
- #endif
- #if (CO_CONFIG_LEDS) & CO_CONFIG_LEDS_ENABLE
- static CO_LEDs_t COO_LEDs;
- #endif
- #if CO_NO_LSS_SLAVE == 1
- static CO_LSSslave_t COO_LSSslave;
- #endif
- #if CO_NO_LSS_MASTER == 1
- static CO_LSSmaster_t COO_LSSmaster;
- #endif
- #if (CO_CONFIG_GTW) & CO_CONFIG_GTW_ASCII
- static CO_GTWA_t COO_gtwa;
- #endif
- #if CO_NO_TRACE > 0
- #ifndef CO_TRACE_BUFFER_SIZE_FIXED
- #define CO_TRACE_BUFFER_SIZE_FIXED 100
- #endif
- static CO_trace_t COO_trace[CO_NO_TRACE];
- static uint32_t COO_traceTimeBuffers[CO_NO_TRACE][CO_TRACE_BUFFER_SIZE_FIXED];
- static int32_t COO_traceValueBuffers[CO_NO_TRACE][CO_TRACE_BUFFER_SIZE_FIXED];
- #endif
- CO_ReturnError_t CO_new(uint32_t *heapMemoryUsed) {
- int16_t i;
- (void)heapMemoryUsed;
- /* If CANopen was initialized before, return. */
- if (CO != NULL) {
- return CO_ERROR_NO;
- }
- /* globals */
- CO = &COO;
- /* CANmodule */
- CO->CANmodule[0] = &COO_CANmodule;
- CO_CANmodule_rxArray0 = &COO_CANmodule_rxArray0[0];
- CO_CANmodule_txArray0 = &COO_CANmodule_txArray0[0];
- /* SDOserver */
- for (i = 0; i < CO_NO_SDO_SERVER; i++) {
- CO->SDO[i] = &COO_SDO[i];
- }
- CO_SDO_ODExtensions = &COO_SDO_ODExtensions[0];
- /* Emergency */
- CO->em = &COO_EM;
- CO->emPr = &COO_EMpr;
- /* NMT_Heartbeat */
- CO->NMT = &COO_NMT;
- #if CO_NO_SYNC == 1
- /* SYNC */
- CO->SYNC = &COO_SYNC;
- #endif
- #if CO_NO_TIME == 1
- /* TIME */
- CO->TIME = &COO_TIME;
- #endif
- #if CO_NO_GFC == 1
- /* GFC */
- CO->GFC = &COO_GFC;
- #endif
- #if CO_NO_SRDO != 0
- /* SRDO */
- CO->SRDOGuard = &COO_SRDOGuard;
- for (i = 0; i < CO_NO_SRDO; i++) {
- CO->SRDO[i] = &COO_SRDO[i];
- }
- #endif
- /* RPDO */
- for (i = 0; i < CO_NO_RPDO; i++) {
- CO->RPDO[i] = &COO_RPDO[i];
- }
- /* TPDO */
- for (i = 0; i < CO_NO_TPDO; i++) {
- CO->TPDO[i] = &COO_TPDO[i];
- }
- /* Heartbeat consumer */
- CO->HBcons = &COO_HBcons;
- CO_HBcons_monitoredNodes = &COO_HBcons_monitoredNodes[0];
- #if CO_NO_SDO_CLIENT != 0
- /* SDOclient */
- for (i = 0; i < CO_NO_SDO_CLIENT; i++) {
- CO->SDOclient[i] = &COO_SDOclient[i];
- }
- #endif
- #if (CO_CONFIG_LEDS) & CO_CONFIG_LEDS_ENABLE
- /* LEDs */
- CO->LEDs = &COO_LEDs;
- #endif
- #if CO_NO_LSS_SLAVE == 1
- /* LSSslave */
- CO->LSSslave = &COO_LSSslave;
- #endif
- #if CO_NO_LSS_MASTER == 1
- /* LSSmaster */
- CO->LSSmaster = &COO_LSSmaster;
- #endif
- #if (CO_CONFIG_GTW) & CO_CONFIG_GTW_ASCII
- /* Gateway-ascii */
- CO->gtwa = &COO_gtwa;
- #endif
- #if CO_NO_TRACE > 0
- /* Trace */
- for (i = 0; i < CO_NO_TRACE; i++) {
- CO->trace[i] = &COO_trace[i];
- CO_traceTimeBuffers[i] = &COO_traceTimeBuffers[i][0];
- CO_traceValueBuffers[i] = &COO_traceValueBuffers[i][0];
- CO_traceBufferSize[i] = CO_TRACE_BUFFER_SIZE_FIXED;
- }
- #endif
- return CO_ERROR_NO;
- }
- /******************************************************************************/
- void CO_delete(void *CANptr) {
- CO_CANsetConfigurationMode(CANptr);
- /* globals */
- CO = NULL;
- }
- #endif /* #ifdef CO_USE_GLOBALS */
- /******************************************************************************/
- CO_ReturnError_t CO_CANinit(void *CANptr,
- uint32_t bitRate)
- {
- CO_ReturnError_t err;
- CO->CANmodule[0]->CANnormal = false;
- CO_CANsetConfigurationMode(CANptr);
- /* CANmodule */
- err = CO_CANmodule_init(CO->CANmodule[0],
- CANptr,
- CO_CANmodule_rxArray0,
- CO_RXCAN_NO_MSGS,
- CO_CANmodule_txArray0,
- CO_TXCAN_NO_MSGS,
- bitRate);
- return err;
- }
- /******************************************************************************/
- #if CO_NO_LSS_SLAVE == 1
- CO_ReturnError_t CO_LSSinit(uint8_t *nodeId,
- uint16_t *bitRate)
- {
- CO_LSS_address_t lssAddress;
- CO_ReturnError_t err;
- /* LSSslave */
- lssAddress.identity.productCode = OD_identity.productCode;
- lssAddress.identity.revisionNumber = OD_identity.revisionNumber;
- lssAddress.identity.serialNumber = OD_identity.serialNumber;
- lssAddress.identity.vendorID = OD_identity.vendorID;
- err = CO_LSSslave_init(CO->LSSslave,
- &lssAddress,
- bitRate,
- nodeId,
- CO->CANmodule[0],
- CO_RXCAN_LSS_SLV,
- CO_CAN_ID_LSS_MST,
- CO->CANmodule[0],
- CO_TXCAN_LSS_SLV,
- CO_CAN_ID_LSS_SLV);
- return err;
- }
- #endif /* CO_NO_LSS_SLAVE == 1 */
- /******************************************************************************/
- CO_ReturnError_t CO_CANopenInit(uint8_t nodeId) {
- int16_t i;
- CO_ReturnError_t err;
- /* Verify CANopen Node-ID */
- CO->nodeIdUnconfigured = false;
- #if CO_NO_LSS_SLAVE == 1
- if (nodeId == CO_LSS_NODE_ID_ASSIGNMENT) {
- CO->nodeIdUnconfigured = true;
- }
- else
- #endif
- if (nodeId < 1 || nodeId > 127) {
- return CO_ERROR_ILLEGAL_ARGUMENT;
- }
- /* Verify parameters from CO_OD */
- #if CO_NO_SRDO != 0
- if (sizeof(OD_SRDOCommunicationParameter_t) != sizeof(CO_SRDOCommPar_t) ||
- sizeof(OD_SRDOMappingParameter_t) != sizeof(CO_SRDOMapPar_t)) {
- return CO_ERROR_OD_PARAMETERS;
- }
- #endif
- if (sizeof(OD_TPDOCommunicationParameter_t) != sizeof(CO_TPDOCommPar_t) ||
- sizeof(OD_TPDOMappingParameter_t) != sizeof(CO_TPDOMapPar_t) ||
- sizeof(OD_RPDOCommunicationParameter_t) != sizeof(CO_RPDOCommPar_t) ||
- sizeof(OD_RPDOMappingParameter_t) != sizeof(CO_RPDOMapPar_t)) {
- return CO_ERROR_OD_PARAMETERS;
- }
- #if CO_NO_SDO_CLIENT != 0
- if (sizeof(OD_SDOClientParameter_t) != sizeof(CO_SDOclientPar_t)) {
- return CO_ERROR_OD_PARAMETERS;
- }
- #endif
- #if (CO_CONFIG_LEDS) & CO_CONFIG_LEDS_ENABLE
- /* LEDs */
- err = CO_LEDs_init(CO->LEDs);
- if (err) return err;
- #endif
- #if CO_NO_LSS_SLAVE == 1
- if (CO->nodeIdUnconfigured) {
- return CO_ERROR_NODE_ID_UNCONFIGURED_LSS;
- }
- #endif
- /* SDOserver */
- for (i = 0; i < CO_NO_SDO_SERVER; i++) {
- uint32_t COB_IDClientToServer;
- uint32_t COB_IDServerToClient;
- if (i == 0) {
- /*Default SDO server must be located at first index*/
- COB_IDClientToServer = CO_CAN_ID_SDO_CLI + nodeId;
- COB_IDServerToClient = CO_CAN_ID_SDO_SRV + nodeId;
- }
- else {
- COB_IDClientToServer =
- OD_SDOServerParameter[i].COB_IDClientToServer;
- COB_IDServerToClient =
- OD_SDOServerParameter[i].COB_IDServerToClient;
- }
- err = CO_SDO_init(CO->SDO[i],
- COB_IDClientToServer,
- COB_IDServerToClient,
- OD_H1200_SDO_SERVER_PARAM + i,
- i == 0 ? 0 : CO->SDO[0],
- &CO_OD[0],
- CO_OD_NoOfElements,
- CO_SDO_ODExtensions,
- nodeId,
- 1000,
- CO->CANmodule[0],
- CO_RXCAN_SDO_SRV + i,
- CO->CANmodule[0],
- CO_TXCAN_SDO_SRV + i);
- if (err) return err;
- }
- /* Emergency */
- err = CO_EM_init(CO->em,
- CO->emPr,
- CO->SDO[0],
- &OD_errorStatusBits[0],
- ODL_errorStatusBits_stringLength,
- &OD_errorRegister,
- &OD_preDefinedErrorField[0],
- ODL_preDefinedErrorField_arrayLength,
- CO->CANmodule[0],
- CO_RXCAN_EMERG,
- CO->CANmodule[0],
- CO_TXCAN_EMERG,
- (uint16_t)CO_CAN_ID_EMERGENCY + nodeId);
- if (err) return err;
- /* NMT_Heartbeat */
- err = CO_NMT_init(CO->NMT,
- CO->emPr,
- nodeId,
- 500,
- CO->CANmodule[0],
- CO_RXCAN_NMT,
- CO_CAN_ID_NMT_SERVICE,
- CO->CANmodule[0],
- CO_TXCAN_NMT,
- CO_CAN_ID_NMT_SERVICE,
- CO->CANmodule[0],
- CO_TXCAN_HB,
- CO_CAN_ID_HEARTBEAT + nodeId);
- if (err) return err;
- #if CO_NO_SYNC == 1
- /* SYNC */
- err = CO_SYNC_init(CO->SYNC,
- CO->em,
- CO->SDO[0],
- &CO->NMT->operatingState,
- OD_COB_ID_SYNCMessage,
- OD_communicationCyclePeriod,
- OD_synchronousCounterOverflowValue,
- CO->CANmodule[0],
- CO_RXCAN_SYNC,
- CO->CANmodule[0],
- CO_TXCAN_SYNC);
- if (err) return err;
- #endif
- #if CO_NO_TIME == 1
- /* TIME */
- err = CO_TIME_init(CO->TIME,
- CO->em,
- CO->SDO[0],
- &CO->NMT->operatingState,
- OD_COB_ID_TIME,
- 1000*30,
- CO->CANmodule[0],
- CO_RXCAN_TIME,
- CO->CANmodule[0],
- CO_TXCAN_TIME);
- if (err) return err;
- #endif
- #if CO_NO_GFC == 1
- /* GFC */
- CO_GFC_init(CO->GFC,
- &OD_globalFailSafeCommandParameter,
- CO->CANmodule[0],
- CO_RXCAN_GFC,
- CO_CAN_ID_GFC,
- CO->CANmodule[0],
- CO_TXCAN_GFC,
- CO_CAN_ID_GFC);
- #endif
- #if CO_NO_SRDO != 0
- /* SRDO */
- err = CO_SRDOGuard_init(CO->SRDOGuard,
- CO->SDO[0],
- &CO->NMT->operatingState,
- &OD_configurationValid,
- OD_H13FE_SRDO_VALID,
- OD_H13FF_SRDO_CHECKSUM);
- if (err) return err;
- for (i = 0; i < CO_NO_SRDO; i++) {
- CO_CANmodule_t *CANdev = CO->CANmodule[0];
- uint16_t CANdevRxIdx = CO_RXCAN_SRDO + 2*i;
- uint16_t CANdevTxIdx = CO_TXCAN_SRDO + 2*i;
- err = CO_SRDO_init(CO->SRDO[i],
- CO->SRDOGuard,
- CO->em,
- CO->SDO[0],
- nodeId,
- ((i == 0) ? CO_CAN_ID_SRDO_1 : 0),
- (CO_SRDOCommPar_t*)&OD_SRDOCommunicationParameter[i],
- (CO_SRDOMapPar_t *)&OD_SRDOMappingParameter[i],
- &OD_safetyConfigurationChecksum[i],
- OD_H1301_SRDO_1_PARAM + i,
- OD_H1381_SRDO_1_MAPPING + i,
- CANdev,
- CANdevRxIdx,
- CANdevRxIdx + 1,
- CANdev,
- CANdevTxIdx,
- CANdevTxIdx + 1);
- if (err) return err;
- }
- #endif
- /* RPDO */
- for (i = 0; i < CO_NO_RPDO; i++) {
- CO_CANmodule_t *CANdevRx = CO->CANmodule[0];
- uint16_t CANdevRxIdx = CO_RXCAN_RPDO + i;
- err = CO_RPDO_init(CO->RPDO[i],
- CO->em,
- CO->SDO[0],
- #if (CO_CONFIG_PDO) & CO_CONFIG_PDO_SYNC_ENABLE
- CO->SYNC,
- #endif
- &CO->NMT->operatingState,
- nodeId,
- ((i < 4) ? (CO_CAN_ID_RPDO_1 + i * 0x100) : 0),
- 0,
- (CO_RPDOCommPar_t*)&OD_RPDOCommunicationParameter[i],
- (CO_RPDOMapPar_t *)&OD_RPDOMappingParameter[i],
- OD_H1400_RXPDO_1_PARAM + i,
- OD_H1600_RXPDO_1_MAPPING + i,
- CANdevRx,
- CANdevRxIdx);
- if (err) return err;
- }
- /* TPDO */
- for (i = 0; i < CO_NO_TPDO; i++) {
- err = CO_TPDO_init(CO->TPDO[i],
- CO->em,
- CO->SDO[0],
- #if (CO_CONFIG_PDO) & CO_CONFIG_PDO_SYNC_ENABLE
- CO->SYNC,
- #endif
- &CO->NMT->operatingState,
- nodeId,
- ((i < 4) ? (CO_CAN_ID_TPDO_1 + i * 0x100) : 0),
- 0,
- (CO_TPDOCommPar_t*)&OD_TPDOCommunicationParameter[i],
- (CO_TPDOMapPar_t *)&OD_TPDOMappingParameter[i],
- OD_H1800_TXPDO_1_PARAM + i,
- OD_H1A00_TXPDO_1_MAPPING + i,
- CO->CANmodule[0],
- CO_TXCAN_TPDO + i);
- if (err) return err;
- }
- /* Heartbeat consumer */
- err = CO_HBconsumer_init(CO->HBcons,
- CO->em,
- CO->SDO[0],
- &OD_consumerHeartbeatTime[0],
- CO_HBcons_monitoredNodes,
- CO_NO_HB_CONS,
- CO->CANmodule[0],
- CO_RXCAN_CONS_HB);
- if (err) return err;
- #if CO_NO_SDO_CLIENT != 0
- /* SDOclient */
- for (i = 0; i < CO_NO_SDO_CLIENT; i++) {
- err = CO_SDOclient_init(CO->SDOclient[i],
- (void *)CO->SDO[0],
- (CO_SDOclientPar_t *)&OD_SDOClientParameter[i],
- CO->CANmodule[0],
- CO_RXCAN_SDO_CLI + i,
- CO->CANmodule[0],
- CO_TXCAN_SDO_CLI + i);
- if (err) return err;
- }
- #endif
- #if CO_NO_LSS_MASTER == 1
- /* LSSmaster */
- err = CO_LSSmaster_init(CO->LSSmaster,
- CO_LSSmaster_DEFAULT_TIMEOUT,
- CO->CANmodule[0],
- CO_RXCAN_LSS_MST,
- CO_CAN_ID_LSS_SLV,
- CO->CANmodule[0],
- CO_TXCAN_LSS_MST,
- CO_CAN_ID_LSS_MST);
- if (err) return err;
- #endif
- #if (CO_CONFIG_GTW) & CO_CONFIG_GTW_ASCII
- /* Gateway-ascii */
- err = CO_GTWA_init(CO->gtwa,
- #if (CO_CONFIG_GTW) & CO_CONFIG_GTW_ASCII_SDO
- CO->SDOclient[0],
- 500,
- false,
- #endif
- #if (CO_CONFIG_GTW) & CO_CONFIG_GTW_ASCII_NMT
- CO->NMT,
- #endif
- #if (CO_CONFIG_GTW) & CO_CONFIG_GTW_ASCII_LSS
- CO->LSSmaster,
- #endif
- #if (CO_CONFIG_GTW) & CO_CONFIG_GTW_ASCII_PRINT_LEDS
- CO->LEDs,
- #endif
- 0);
- if (err) return err;
- #endif /* (CO_CONFIG_GTW) & CO_CONFIG_GTW_ASCII */
- #if CO_NO_TRACE > 0
- /* Trace */
- for (i = 0; i < CO_NO_TRACE; i++) {
- CO_trace_init(CO->trace[i],
- CO->SDO[0],
- OD_traceConfig[i].axisNo,
- CO_traceTimeBuffers[i],
- CO_traceValueBuffers[i],
- CO_traceBufferSize[i],
- &OD_traceConfig[i].map,
- &OD_traceConfig[i].format,
- &OD_traceConfig[i].trigger,
- &OD_traceConfig[i].threshold,
- &OD_trace[i].value,
- &OD_trace[i].min,
- &OD_trace[i].max,
- &OD_trace[i].triggerTime,
- OD_INDEX_TRACE_CONFIG + i,
- OD_INDEX_TRACE + i);
- }
- #endif
- return CO_ERROR_NO;
- }
- /******************************************************************************/
- CO_NMT_reset_cmd_t CO_process(CO_t *co,
- uint32_t timeDifference_us,
- uint32_t *timerNext_us)
- {
- uint8_t i;
- bool_t NMTisPreOrOperational = false;
- CO_NMT_reset_cmd_t reset = CO_RESET_NOT;
- CO_CANmodule_process(CO->CANmodule[0]);
- #if CO_NO_LSS_SLAVE == 1
- bool_t resetLSS = CO_LSSslave_process(co->LSSslave);
- #endif
- #if (CO_CONFIG_LEDS) & CO_CONFIG_LEDS_ENABLE
- bool_t unc = co->nodeIdUnconfigured;
- uint16_t CANerrorStatus = CO->CANmodule[0]->CANerrorStatus;
- CO_LEDs_process(co->LEDs,
- timeDifference_us,
- unc ? CO_NMT_INITIALIZING : co->NMT->operatingState,
- #if CO_NO_LSS_SLAVE == 1
- CO_LSSslave_getState(co->LSSslave)
- == CO_LSS_STATE_CONFIGURATION,
- #else
- false,
- #endif
- (CANerrorStatus & CO_CAN_ERRTX_BUS_OFF) != 0,
- (CANerrorStatus & CO_CAN_ERR_WARN_PASSIVE) != 0,
- 0, /* RPDO event timer timeout */
- unc ? false : CO_isError(co->em, CO_EM_SYNC_TIME_OUT),
- unc ? false : (CO_isError(co->em, CO_EM_HEARTBEAT_CONSUMER)
- || CO_isError(co->em, CO_EM_HB_CONSUMER_REMOTE_RESET)),
- OD_errorRegister != 0,
- CO_STATUS_FIRMWARE_DOWNLOAD_IN_PROGRESS,
- timerNext_us);
- #endif /* (CO_CONFIG_LEDS) & CO_CONFIG_LEDS_ENABLE */
- #if CO_NO_LSS_SLAVE == 1
- if (resetLSS) {
- reset = CO_RESET_COMM;
- }
- if (co->nodeIdUnconfigured) {
- return reset;
- }
- #endif
- if (co->NMT->operatingState == CO_NMT_PRE_OPERATIONAL ||
- co->NMT->operatingState == CO_NMT_OPERATIONAL)
- NMTisPreOrOperational = true;
- /* SDOserver */
- for (i = 0; i < CO_NO_SDO_SERVER; i++) {
- CO_SDO_process(co->SDO[i],
- NMTisPreOrOperational,
- timeDifference_us,
- timerNext_us);
- }
- /* Emergency */
- CO_EM_process(co->emPr,
- NMTisPreOrOperational,
- timeDifference_us,
- OD_inhibitTimeEMCY,
- timerNext_us);
- /* NMT_Heartbeat */
- reset = CO_NMT_process(co->NMT,
- timeDifference_us,
- OD_producerHeartbeatTime,
- OD_NMTStartup,
- OD_errorRegister,
- OD_errorBehavior,
- timerNext_us);
- #if CO_NO_TIME == 1
- /* TIME */
- CO_TIME_process(co->TIME,
- timeDifference_us);
- #endif
- /* Heartbeat consumer */
- CO_HBconsumer_process(co->HBcons,
- NMTisPreOrOperational,
- timeDifference_us,
- timerNext_us);
- #if (CO_CONFIG_GTW) & CO_CONFIG_GTW_ASCII
- /* Gateway-ascii */
- CO_GTWA_process(co->gtwa,
- CO_GTWA_ENABLE,
- timeDifference_us,
- timerNext_us);
- #endif
- return reset;
- }
- /******************************************************************************/
- #if CO_NO_SYNC == 1
- bool_t CO_process_SYNC(CO_t *co,
- uint32_t timeDifference_us,
- uint32_t *timerNext_us)
- {
- bool_t syncWas = false;
- #if CO_NO_LSS_SLAVE == 1
- if (co->nodeIdUnconfigured) {
- return syncWas;
- }
- #endif
- const CO_SYNC_status_t sync_process = CO_SYNC_process(co->SYNC,
- timeDifference_us,
- OD_synchronousWindowLength,
- timerNext_us);
- switch (sync_process) {
- case CO_SYNC_NONE:
- break;
- case CO_SYNC_RECEIVED:
- syncWas = true;
- break;
- case CO_SYNC_OUTSIDE_WINDOW:
- CO_CANclearPendingSyncPDOs(co->CANmodule[0]);
- break;
- }
- return syncWas;
- }
- #endif /* CO_NO_SYNC == 1 */
- /******************************************************************************/
- void CO_process_RPDO(CO_t *co,
- bool_t syncWas)
- {
- int16_t i;
- #if CO_NO_LSS_SLAVE == 1
- if (co->nodeIdUnconfigured) {
- return;
- }
- #endif
- for (i = 0; i < CO_NO_RPDO; i++) {
- CO_RPDO_process(co->RPDO[i], syncWas);
- }
- }
- /******************************************************************************/
- void CO_process_TPDO(CO_t *co,
- bool_t syncWas,
- uint32_t timeDifference_us,
- uint32_t *timerNext_us)
- {
- int16_t i;
- #if CO_NO_LSS_SLAVE == 1
- if (co->nodeIdUnconfigured) {
- return;
- }
- #endif
- /* Verify PDO Change Of State and process PDOs */
- for (i = 0; i < CO_NO_TPDO; i++) {
- if (!co->TPDO[i]->sendRequest)
- co->TPDO[i]->sendRequest = CO_TPDOisCOS(co->TPDO[i]);
- CO_TPDO_process(co->TPDO[i], syncWas, timeDifference_us, timerNext_us);
- }
- }
- /******************************************************************************/
- #if CO_NO_SRDO != 0
- void CO_process_SRDO(CO_t *co,
- uint32_t timeDifference_us,
- uint32_t *timerNext_us)
- {
- int16_t i;
- uint8_t firstOperational;
- #if CO_NO_LSS_SLAVE == 1
- if (co->nodeIdUnconfigured) {
- return;
- }
- #endif
- firstOperational = CO_SRDOGuard_process(co->SRDOGuard);
- /* Verify PDO Change Of State and process PDOs */
- for (i = 0; i < CO_NO_SRDO; i++) {
- CO_SRDO_process(co->SRDO[i], firstOperational, timeDifference_us, timerNext_us);
- }
- }
- #endif
|