CO_Emergency.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. /*
  2. * CANopen Emergency object.
  3. *
  4. * @file CO_Emergency.c
  5. * @ingroup CO_Emergency
  6. * @author Janez Paternoster
  7. * @copyright 2004 - 2020 Janez Paternoster
  8. *
  9. * This file is part of CANopenNode, an opensource CANopen Stack.
  10. * Project home page is <https://github.com/CANopenNode/CANopenNode>.
  11. * For more information on CANopen see <http://www.can-cia.org/>.
  12. *
  13. * Licensed under the Apache License, Version 2.0 (the "License");
  14. * you may not use this file except in compliance with the License.
  15. * You may obtain a copy of the License at
  16. *
  17. * http://www.apache.org/licenses/LICENSE-2.0
  18. *
  19. * Unless required by applicable law or agreed to in writing, software
  20. * distributed under the License is distributed on an "AS IS" BASIS,
  21. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  22. * See the License for the specific language governing permissions and
  23. * limitations under the License.
  24. */
  25. #include <string.h>
  26. #include "301/CO_SDOserver.h"
  27. #include "301/CO_Emergency.h"
  28. /* verify configuration */
  29. #if CO_CONFIG_EM_ERR_STATUS_BITS_COUNT < (6*8) \
  30. || CO_CONFIG_EM_ERR_STATUS_BITS_COUNT > 256
  31. #error CO_CONFIG_EM_ERR_STATUS_BITS_COUNT is not correct
  32. #endif
  33. #if (CO_CONFIG_EM) & CO_CONFIG_EM_CONSUMER
  34. /*
  35. * Read received message from CAN module.
  36. *
  37. * Function will be called (by CAN receive interrupt) every time, when CAN
  38. * message with correct identifier will be received. For more information and
  39. * description of parameters see file CO_driver.h.
  40. */
  41. static void CO_EM_receive(void *object, void *msg) {
  42. CO_EM_t *em;
  43. em = (CO_EM_t*)object;
  44. if (em!=NULL && em->pFunctSignalRx!=NULL){
  45. uint16_t ident = CO_CANrxMsg_readIdent(msg);
  46. if (ident != 0x80) {
  47. /* ignore sync messages (necessary if sync object is not used) */
  48. uint8_t *data = CO_CANrxMsg_readData(msg);
  49. uint16_t errorCode;
  50. uint32_t infoCode;
  51. memcpy(&errorCode, &data[0], sizeof(errorCode));
  52. memcpy(&infoCode, &data[4], sizeof(infoCode));
  53. em->pFunctSignalRx(ident,
  54. CO_SWAP_16(errorCode),
  55. data[2],
  56. data[3],
  57. CO_SWAP_32(infoCode));
  58. }
  59. }
  60. }
  61. #endif
  62. /*
  63. * Function for accessing _Pre-Defined Error Field_ (index 0x1003) from SDO server.
  64. *
  65. * For more information see file CO_SDOserver.h.
  66. */
  67. static CO_SDO_abortCode_t CO_ODF_1003(CO_ODF_arg_t *ODF_arg);
  68. static CO_SDO_abortCode_t CO_ODF_1003(CO_ODF_arg_t *ODF_arg){
  69. CO_EMpr_t *emPr;
  70. uint8_t value;
  71. CO_SDO_abortCode_t ret = CO_SDO_AB_NONE;
  72. emPr = (CO_EMpr_t*) ODF_arg->object;
  73. value = ODF_arg->data[0];
  74. if (ODF_arg->reading){
  75. uint8_t noOfErrors;
  76. noOfErrors = emPr->preDefErrNoOfErrors;
  77. if (ODF_arg->subIndex == 0U){
  78. ODF_arg->data[0] = noOfErrors;
  79. }
  80. else if (ODF_arg->subIndex > noOfErrors){
  81. ret = CO_SDO_AB_NO_DATA;
  82. }
  83. else{
  84. ret = CO_SDO_AB_NONE;
  85. }
  86. }
  87. else{
  88. /* only '0' may be written to subIndex 0 */
  89. if (ODF_arg->subIndex == 0U){
  90. if (value == 0U){
  91. emPr->preDefErrNoOfErrors = 0U;
  92. }
  93. else{
  94. ret = CO_SDO_AB_INVALID_VALUE;
  95. }
  96. }
  97. else{
  98. ret = CO_SDO_AB_READONLY;
  99. }
  100. }
  101. return ret;
  102. }
  103. /*
  104. * Function for accessing _COB ID EMCY_ (index 0x1014) from SDO server.
  105. *
  106. * For more information see file CO_SDOserver.h.
  107. */
  108. static CO_SDO_abortCode_t CO_ODF_1014(CO_ODF_arg_t *ODF_arg);
  109. static CO_SDO_abortCode_t CO_ODF_1014(CO_ODF_arg_t *ODF_arg){
  110. uint8_t *nodeId;
  111. uint32_t value;
  112. CO_SDO_abortCode_t ret = CO_SDO_AB_NONE;
  113. nodeId = (uint8_t*) ODF_arg->object;
  114. value = CO_getUint32(ODF_arg->data);
  115. /* add nodeId to the value */
  116. if (ODF_arg->reading){
  117. CO_setUint32(ODF_arg->data, value + *nodeId);
  118. }
  119. return ret;
  120. }
  121. /******************************************************************************/
  122. CO_ReturnError_t CO_EM_init(
  123. CO_EM_t *em,
  124. CO_EMpr_t *emPr,
  125. CO_SDO_t *SDO,
  126. uint8_t *errorStatusBits,
  127. uint8_t errorStatusBitsSize,
  128. uint8_t *errorRegister,
  129. uint32_t *preDefErr,
  130. uint8_t preDefErrSize,
  131. CO_CANmodule_t *CANdevRx,
  132. uint16_t CANdevRxIdx,
  133. CO_CANmodule_t *CANdevTx,
  134. uint16_t CANdevTxIdx,
  135. uint16_t CANidTxEM)
  136. {
  137. uint8_t i;
  138. CO_ReturnError_t ret = CO_ERROR_NO;
  139. /* verify arguments */
  140. if (em==NULL || emPr==NULL || SDO==NULL || errorStatusBits==NULL || errorStatusBitsSize<6U ||
  141. errorRegister==NULL || preDefErr==NULL || CANdevTx==NULL
  142. #if (CO_CONFIG_EM) & CO_CONFIG_EM_CONSUMER
  143. || CANdevRx==NULL
  144. #endif
  145. ){
  146. return CO_ERROR_ILLEGAL_ARGUMENT;
  147. }
  148. /* Configure object variables */
  149. em->errorStatusBits = errorStatusBits;
  150. em->errorStatusBitsSize = errorStatusBitsSize;
  151. em->bufEnd = em->buf + (CO_EM_INTERNAL_BUFFER_SIZE * 8);
  152. em->bufWritePtr = em->buf;
  153. em->bufReadPtr = em->buf;
  154. em->bufFull = 0U;
  155. em->wrongErrorReport = 0U;
  156. #if (CO_CONFIG_EM) & CO_CONFIG_FLAG_CALLBACK_PRE
  157. em->pFunctSignalPre = NULL;
  158. em->functSignalObjectPre = NULL;
  159. #endif
  160. #if (CO_CONFIG_EM) & CO_CONFIG_EM_CONSUMER
  161. em->pFunctSignalRx = NULL;
  162. #endif
  163. emPr->em = em;
  164. emPr->errorRegister = errorRegister;
  165. emPr->preDefErr = preDefErr;
  166. emPr->preDefErrSize = preDefErrSize;
  167. emPr->preDefErrNoOfErrors = 0U;
  168. emPr->inhibitEmTimer = 0U;
  169. emPr->CANerrorStatusOld = 0U;
  170. /* clear error status bits */
  171. for(i=0U; i<errorStatusBitsSize; i++){
  172. em->errorStatusBits[i] = 0U;
  173. }
  174. /* Configure Object dictionary entry at index 0x1003 and 0x1014 */
  175. CO_OD_configure(SDO, OD_H1003_PREDEF_ERR_FIELD, CO_ODF_1003, (void*)emPr, 0, 0U);
  176. CO_OD_configure(SDO, OD_H1014_COBID_EMERGENCY, CO_ODF_1014, (void*)&SDO->nodeId, 0, 0U);
  177. #if (CO_CONFIG_EM) & CO_CONFIG_EM_CONSUMER
  178. /* configure SDO server CAN reception */
  179. ret = CO_CANrxBufferInit(
  180. CANdevRx, /* CAN device */
  181. CANdevRxIdx, /* rx buffer index */
  182. CO_CAN_ID_EMERGENCY, /* CAN identifier */
  183. 0x780, /* mask */
  184. 0, /* rtr */
  185. (void*)em, /* object passed to receive function */
  186. CO_EM_receive); /* this function will process received message */
  187. #endif
  188. /* configure emergency message CAN transmission */
  189. emPr->CANdev = CANdevTx;
  190. emPr->CANtxBuff = CO_CANtxBufferInit(
  191. CANdevTx, /* CAN device */
  192. CANdevTxIdx, /* index of specific buffer inside CAN module */
  193. CANidTxEM, /* CAN identifier */
  194. 0, /* rtr */
  195. 8U, /* number of data bytes */
  196. 0); /* synchronous message flag bit */
  197. if (emPr->CANtxBuff == NULL) {
  198. ret = CO_ERROR_ILLEGAL_ARGUMENT;
  199. }
  200. return ret;
  201. }
  202. #if (CO_CONFIG_EM) & CO_CONFIG_FLAG_CALLBACK_PRE
  203. /******************************************************************************/
  204. void CO_EM_initCallbackPre(
  205. CO_EM_t *em,
  206. void *object,
  207. void (*pFunctSignal)(void *object))
  208. {
  209. if (em != NULL){
  210. em->functSignalObjectPre = object;
  211. em->pFunctSignalPre = pFunctSignal;
  212. }
  213. }
  214. #endif
  215. #if (CO_CONFIG_EM) & CO_CONFIG_EM_CONSUMER
  216. /******************************************************************************/
  217. void CO_EM_initCallbackRx(
  218. CO_EM_t *em,
  219. void (*pFunctSignalRx)(const uint16_t ident,
  220. const uint16_t errorCode,
  221. const uint8_t errorRegister,
  222. const uint8_t errorBit,
  223. const uint32_t infoCode))
  224. {
  225. if (em != NULL){
  226. em->pFunctSignalRx = pFunctSignalRx;
  227. }
  228. }
  229. #endif
  230. /******************************************************************************/
  231. void CO_EM_process(
  232. CO_EMpr_t *emPr,
  233. bool_t NMTisPreOrOperational,
  234. uint32_t timeDifference_us,
  235. uint16_t emInhTime_100us,
  236. uint32_t *timerNext_us)
  237. {
  238. (void)timerNext_us; /* may be unused */
  239. CO_EM_t *em = emPr->em;
  240. uint8_t errorRegister;
  241. uint8_t errorMask;
  242. uint8_t i;
  243. uint32_t emInhTime_us = (uint32_t)emInhTime_100us * 100;
  244. uint16_t CANerrSt = emPr->CANdev->CANerrorStatus;
  245. /* verify errors from driver */
  246. if (CANerrSt != emPr->CANerrorStatusOld) {
  247. uint16_t CANerrStChanged = CANerrSt ^ emPr->CANerrorStatusOld;
  248. emPr->CANerrorStatusOld = CANerrSt;
  249. if (CANerrStChanged & (CO_CAN_ERRTX_WARNING | CO_CAN_ERRRX_WARNING)) {
  250. if (CANerrSt & (CO_CAN_ERRTX_WARNING | CO_CAN_ERRRX_WARNING))
  251. CO_errorReport(em, CO_EM_CAN_BUS_WARNING, CO_EMC_NO_ERROR, 0);
  252. else
  253. CO_errorReset(em, CO_EM_CAN_BUS_WARNING, 0);
  254. }
  255. if (CANerrStChanged & CO_CAN_ERRTX_PASSIVE) {
  256. if (CANerrSt & CO_CAN_ERRTX_PASSIVE)
  257. CO_errorReport(em, CO_EM_CAN_TX_BUS_PASSIVE,
  258. CO_EMC_CAN_PASSIVE, 0);
  259. else
  260. CO_errorReset(em, CO_EM_CAN_TX_BUS_PASSIVE, 0);
  261. }
  262. if (CANerrStChanged & CO_CAN_ERRTX_BUS_OFF) {
  263. if (CANerrSt & CO_CAN_ERRTX_BUS_OFF)
  264. CO_errorReport(em, CO_EM_CAN_TX_BUS_OFF,
  265. CO_EMC_BUS_OFF_RECOVERED, 0);
  266. else
  267. CO_errorReset(em, CO_EM_CAN_TX_BUS_OFF, 0);
  268. }
  269. if (CANerrStChanged & CO_CAN_ERRTX_OVERFLOW) {
  270. if (CANerrSt & CO_CAN_ERRTX_OVERFLOW)
  271. CO_errorReport(em, CO_EM_CAN_TX_OVERFLOW,
  272. CO_EMC_CAN_OVERRUN, 0);
  273. else
  274. CO_errorReset(em, CO_EM_CAN_TX_OVERFLOW, 0);
  275. }
  276. if (CANerrStChanged & CO_CAN_ERRTX_PDO_LATE) {
  277. if (CANerrSt & CO_CAN_ERRTX_PDO_LATE)
  278. CO_errorReport(em, CO_EM_TPDO_OUTSIDE_WINDOW,
  279. CO_EMC_COMMUNICATION, 0);
  280. else
  281. CO_errorReset(em, CO_EM_TPDO_OUTSIDE_WINDOW, 0);
  282. }
  283. if (CANerrStChanged & CO_CAN_ERRRX_PASSIVE) {
  284. if (CANerrSt & CO_CAN_ERRRX_PASSIVE)
  285. CO_errorReport(em, CO_EM_CAN_RX_BUS_PASSIVE,
  286. CO_EMC_CAN_PASSIVE, 0);
  287. else
  288. CO_errorReset(em, CO_EM_CAN_RX_BUS_PASSIVE, 0);
  289. }
  290. if (CANerrStChanged & CO_CAN_ERRRX_OVERFLOW) {
  291. if (CANerrSt & CO_CAN_ERRRX_OVERFLOW)
  292. CO_errorReport(em, CO_EM_CAN_RXB_OVERFLOW,
  293. CO_EMC_CAN_OVERRUN, 0);
  294. else
  295. CO_errorReset(em, CO_EM_CAN_RXB_OVERFLOW, 0);
  296. }
  297. }
  298. /* verify other errors */
  299. if (em->wrongErrorReport != 0U){
  300. CO_errorReport(em, CO_EM_WRONG_ERROR_REPORT, CO_EMC_SOFTWARE_INTERNAL, (uint32_t)em->wrongErrorReport);
  301. em->wrongErrorReport = 0U;
  302. }
  303. /* calculate Error register */
  304. errorRegister = 0U;
  305. errorMask = (uint8_t)~(CO_ERR_REG_GENERIC_ERR | CO_ERR_REG_COMM_ERR | CO_ERR_REG_MANUFACTURER);
  306. /* generic error */
  307. if (em->errorStatusBits[5]){
  308. errorRegister |= CO_ERR_REG_GENERIC_ERR;
  309. }
  310. /* communication error (overrun, error state) */
  311. if (em->errorStatusBits[2] || em->errorStatusBits[3]){
  312. errorRegister |= CO_ERR_REG_COMM_ERR;
  313. }
  314. /* Manufacturer */
  315. for(i=6; i<em->errorStatusBitsSize; i++) {
  316. if (em->errorStatusBits[i]) {
  317. errorRegister |= CO_ERR_REG_MANUFACTURER;
  318. }
  319. }
  320. *emPr->errorRegister = (*emPr->errorRegister & errorMask) | errorRegister;
  321. /* inhibit time */
  322. if (emPr->inhibitEmTimer < emInhTime_us) {
  323. emPr->inhibitEmTimer += timeDifference_us;
  324. }
  325. /* send Emergency message. */
  326. if ( NMTisPreOrOperational &&
  327. !emPr->CANtxBuff->bufferFull &&
  328. (em->bufReadPtr != em->bufWritePtr || em->bufFull))
  329. {
  330. uint32_t preDEF; /* preDefinedErrorField */
  331. if (emPr->inhibitEmTimer >= emInhTime_us) {
  332. /* inhibit time elapsed, send message */
  333. /* add error register */
  334. em->bufReadPtr[2] = *emPr->errorRegister;
  335. #if (CO_CONFIG_EM) & CO_CONFIG_EM_CONSUMER
  336. /* report also own emergency messages */
  337. if (em->pFunctSignalRx != NULL) {
  338. uint16_t errorCode;
  339. uint32_t infoCode;
  340. memcpy(&errorCode, &em->bufReadPtr[0], sizeof(errorCode));
  341. memcpy(&infoCode, &em->bufReadPtr[4], sizeof(infoCode));
  342. em->pFunctSignalRx(0,
  343. CO_SWAP_16(errorCode),
  344. em->bufReadPtr[2],
  345. em->bufReadPtr[3],
  346. CO_SWAP_32(infoCode));
  347. }
  348. #endif
  349. /* copy data to CAN emergency message */
  350. memcpy(emPr->CANtxBuff->data, em->bufReadPtr, sizeof(emPr->CANtxBuff->data));
  351. memcpy(&preDEF, em->bufReadPtr, sizeof(preDEF));
  352. em->bufReadPtr += 8;
  353. /* Update read buffer pointer and reset inhibit timer */
  354. if (em->bufReadPtr == em->bufEnd){
  355. em->bufReadPtr = em->buf;
  356. }
  357. emPr->inhibitEmTimer = 0U;
  358. /* verify message buffer overflow, then clear full flag */
  359. if (em->bufFull == 2U){
  360. em->bufFull = 0U; /* will be updated below */
  361. CO_errorReport(em, CO_EM_EMERGENCY_BUFFER_FULL, CO_EMC_GENERIC, 0U);
  362. }
  363. else{
  364. em->bufFull = 0;
  365. CO_errorReset(em, CO_EM_EMERGENCY_BUFFER_FULL, 0);
  366. }
  367. /* write to 'pre-defined error field' (object dictionary, index 0x1003) */
  368. if (emPr->preDefErr){
  369. uint8_t j;
  370. if (emPr->preDefErrNoOfErrors < emPr->preDefErrSize)
  371. emPr->preDefErrNoOfErrors++;
  372. for(j=emPr->preDefErrNoOfErrors-1; j>0; j--)
  373. emPr->preDefErr[j] = emPr->preDefErr[j-1];
  374. emPr->preDefErr[0] = preDEF;
  375. }
  376. /* send CAN message */
  377. CO_CANsend(emPr->CANdev, emPr->CANtxBuff);
  378. }
  379. #if (CO_CONFIG_EM) & CO_CONFIG_FLAG_TIMERNEXT
  380. else if (timerNext_us != NULL) {
  381. uint32_t diff;
  382. /* check again after inhibit time elapsed */
  383. diff = emInhTime_us - emPr->inhibitEmTimer;
  384. if (*timerNext_us > diff) {
  385. *timerNext_us = diff;
  386. }
  387. }
  388. #endif
  389. }
  390. return;
  391. }
  392. /******************************************************************************/
  393. void CO_errorReport(CO_EM_t *em, const uint8_t errorBit, const uint16_t errorCode, const uint32_t infoCode){
  394. uint8_t index = errorBit >> 3;
  395. uint8_t bitmask = 1 << (errorBit & 0x7);
  396. uint8_t *errorStatusBits = 0;
  397. bool_t sendEmergency = true;
  398. if (em == NULL){
  399. sendEmergency = false;
  400. }
  401. else if (index >= em->errorStatusBitsSize){
  402. /* if errorBit value not supported, send emergency 'CO_EM_WRONG_ERROR_REPORT' */
  403. em->wrongErrorReport = errorBit;
  404. sendEmergency = false;
  405. }
  406. else{
  407. errorStatusBits = &em->errorStatusBits[index];
  408. /* if error was already reported, do nothing */
  409. if ((*errorStatusBits & bitmask) != 0){
  410. sendEmergency = false;
  411. }
  412. }
  413. if (sendEmergency){
  414. /* set error bit */
  415. if (errorBit){
  416. /* any error except NO_ERROR */
  417. *errorStatusBits |= bitmask;
  418. }
  419. /* verify buffer full, set overflow */
  420. if (em->bufFull){
  421. em->bufFull = 2;
  422. }
  423. else{
  424. uint8_t bufCopy[8];
  425. uint16_t errorCodeSw = CO_SWAP_16(errorCode);
  426. uint32_t infoCodeSw = CO_SWAP_32(infoCode);
  427. /* prepare data for emergency message */
  428. memcpy(&bufCopy[0], &errorCodeSw, sizeof(errorCodeSw));
  429. bufCopy[2] = 0; /* error register will be set later */
  430. bufCopy[3] = errorBit;
  431. memcpy(&bufCopy[4], &infoCodeSw, sizeof(infoCodeSw));
  432. /* copy data to the buffer, increment writePtr and verify buffer full */
  433. CO_LOCK_EMCY();
  434. memcpy(em->bufWritePtr, bufCopy, sizeof(bufCopy));
  435. em->bufWritePtr += 8;
  436. if (em->bufWritePtr == em->bufEnd) em->bufWritePtr = em->buf;
  437. if (em->bufWritePtr == em->bufReadPtr) em->bufFull = 1;
  438. CO_UNLOCK_EMCY();
  439. #if (CO_CONFIG_EM) & CO_CONFIG_FLAG_CALLBACK_PRE
  440. /* Optional signal to RTOS, which can resume task, which handles CO_EM_process */
  441. if (em->pFunctSignalPre != NULL) {
  442. em->pFunctSignalPre(em->functSignalObjectPre);
  443. }
  444. #endif
  445. }
  446. }
  447. }
  448. /******************************************************************************/
  449. void CO_errorReset(CO_EM_t *em, const uint8_t errorBit, const uint32_t infoCode){
  450. uint8_t index = errorBit >> 3;
  451. uint8_t bitmask = 1 << (errorBit & 0x7);
  452. uint8_t *errorStatusBits = 0;
  453. bool_t sendEmergency = true;
  454. if (em == NULL){
  455. sendEmergency = false;
  456. }
  457. else if (index >= em->errorStatusBitsSize){
  458. /* if errorBit value not supported, send emergency 'CO_EM_WRONG_ERROR_REPORT' */
  459. em->wrongErrorReport = errorBit;
  460. sendEmergency = false;
  461. }
  462. else{
  463. errorStatusBits = &em->errorStatusBits[index];
  464. /* if error was allready cleared, do nothing */
  465. if ((*errorStatusBits & bitmask) == 0){
  466. sendEmergency = false;
  467. }
  468. }
  469. if (sendEmergency){
  470. /* erase error bit */
  471. *errorStatusBits &= ~bitmask;
  472. /* verify buffer full */
  473. if (em->bufFull){
  474. em->bufFull = 2;
  475. }
  476. else{
  477. uint8_t bufCopy[8];
  478. uint32_t infoCodeSw = CO_SWAP_32(infoCode);
  479. /* prepare data for emergency message */
  480. bufCopy[0] = 0;
  481. bufCopy[1] = 0;
  482. bufCopy[2] = 0; /* error register will be set later */
  483. bufCopy[3] = errorBit;
  484. memcpy(&bufCopy[4], &infoCodeSw, sizeof(infoCodeSw));
  485. /* copy data to the buffer, increment writePtr and verify buffer full */
  486. CO_LOCK_EMCY();
  487. memcpy(em->bufWritePtr, bufCopy, sizeof(bufCopy));
  488. em->bufWritePtr += 8;
  489. if (em->bufWritePtr == em->bufEnd) em->bufWritePtr = em->buf;
  490. if (em->bufWritePtr == em->bufReadPtr) em->bufFull = 1;
  491. CO_UNLOCK_EMCY();
  492. #if (CO_CONFIG_EM) & CO_CONFIG_FLAG_CALLBACK_PRE
  493. /* Optional signal to RTOS, which can resume task, which handles CO_EM_process */
  494. if (em->pFunctSignalPre != NULL) {
  495. em->pFunctSignalPre(em->functSignalObjectPre);
  496. }
  497. #endif
  498. }
  499. }
  500. }
  501. /******************************************************************************/
  502. bool_t CO_isError(CO_EM_t *em, const uint8_t errorBit){
  503. uint8_t index = errorBit >> 3;
  504. uint8_t bitmask = 1 << (errorBit & 0x7);
  505. bool_t ret = false;
  506. if (em != NULL && index < em->errorStatusBitsSize){
  507. if ((em->errorStatusBits[index] & bitmask) != 0){
  508. ret = true;
  509. }
  510. }
  511. return ret;
  512. }