CO_driver.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717
  1. /*
  2. * Copyright (c) 2019 Vestas Wind Systems A/S
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <canopennode.h>
  7. #include "hpm_canopen.h"
  8. #ifdef HPMSOC_HAS_HPMSDK_MCAN
  9. #include "hpm_canopen_mcan.h"
  10. #else
  11. #include "hpm_canopen_can.h"
  12. #endif
  13. #include "can.h"
  14. #include "CO_driver.h"
  15. #define SAMPLE_POINT_MARGIN 50
  16. #define CAN_SYNC_SEG 1
  17. inline void canopen_emcy_lock(void)
  18. {
  19. }
  20. inline void canopen_emcy_unlock(void)
  21. {
  22. }
  23. inline void canopen_od_lock(void)
  24. {
  25. }
  26. inline void canopen_od_unlock(void)
  27. {
  28. }
  29. static void canopen_detach_all_rx_filters(CO_CANmodule_t *CANmodule)
  30. {
  31. uint16_t i;
  32. if (!CANmodule || !CANmodule->rxArray || !CANmodule->configured) {
  33. return;
  34. }
  35. for (i = 0U; i < CANmodule->rxSize; i++) {
  36. if (CANmodule->rxArray[i].filter_id != -ENOSPC) {
  37. can_remove_rx_filter(CANmodule->CANptr,
  38. CANmodule->rxArray[i].filter_id);
  39. CANmodule->rxArray[i].filter_id = -ENOSPC;
  40. }
  41. }
  42. }
  43. static void canopen_rx_callback(const struct device *dev, struct can_frame *frame, void *user_data)
  44. {
  45. CO_CANmodule_t *CANmodule = (CO_CANmodule_t *)user_data;
  46. CO_CANrxMsg_t rxMsg;
  47. CO_CANrx_t *buffer;
  48. int i;
  49. ARG_UNUSED(dev);
  50. /* Loop through registered rx buffers in priority order */
  51. for (i = 0; i < CANmodule->rxSize; i++) {
  52. buffer = &CANmodule->rxArray[i];
  53. if (buffer->ident == -ENOSPC || buffer->CANrx_callback == NULL) {
  54. continue;
  55. }
  56. if (((frame->id ^ buffer->ident) & buffer->mask) == 0U) {
  57. #ifdef CONFIG_CAN_ACCEPT_RTR
  58. if (buffer->rtr && ((frame->flags & CAN_FRAME_RTR) == 0U)) {
  59. continue;
  60. }
  61. #endif /* CONFIG_CAN_ACCEPT_RTR */
  62. rxMsg.ident = frame->id;
  63. rxMsg.DLC = frame->dlc;
  64. memcpy(rxMsg.data, frame->data, frame->dlc);
  65. buffer->CANrx_callback(buffer->object, &rxMsg);
  66. break;
  67. }
  68. }
  69. }
  70. void CO_CANsetConfigurationMode(void *CANdriverState)
  71. {
  72. struct canopen_context *ctx = (struct canopen_context *)CANdriverState;
  73. int err;
  74. err = can_stop(ctx->dev);
  75. if (err != 0 && err != -EALREADY) {
  76. printf("failed to stop CAN interface (err %d)\n", err);
  77. }
  78. }
  79. void CO_CANsetNormalMode(CO_CANmodule_t *CANmodule)
  80. {
  81. int err;
  82. err = can_start(CANmodule->CANptr);
  83. if (err != 0 && err != -EALREADY) {
  84. printf("failed to start CAN interface (err %d)\n", err);
  85. return;
  86. }
  87. CANmodule->CANnormal = true;
  88. }
  89. static uint16_t sample_point_for_bitrate(uint32_t bitrate)
  90. {
  91. uint16_t sample_pnt;
  92. if (bitrate > 800000) {
  93. /* 75.0% */
  94. sample_pnt = 750;
  95. } else if (bitrate > 500000) {
  96. /* 80.0% */
  97. sample_pnt = 800;
  98. } else {
  99. /* 87.5% */
  100. sample_pnt = 875;
  101. }
  102. return sample_pnt;
  103. }
  104. int update_sample_pnt(uint32_t total_tq, uint32_t sample_pnt, struct can_timing *res,
  105. const struct can_timing *min, const struct can_timing *max)
  106. {
  107. uint16_t tseg1_max = max->phase_seg1 + max->prop_seg;
  108. uint16_t tseg1_min = min->phase_seg1 + min->prop_seg;
  109. uint32_t sample_pnt_res;
  110. uint16_t tseg1, tseg2;
  111. /* Calculate number of time quanta in tseg2 for given sample point */
  112. tseg2 = total_tq - (total_tq * sample_pnt) / 1000;
  113. tseg2 = CLAMP(tseg2, min->phase_seg2, max->phase_seg2);
  114. /* Calculate number of time quanta in tseg1 */
  115. tseg1 = total_tq - CAN_SYNC_SEG - tseg2;
  116. if (tseg1 > tseg1_max) {
  117. /* Sample point location must be decreased */
  118. tseg1 = tseg1_max;
  119. tseg2 = total_tq - CAN_SYNC_SEG - tseg1;
  120. if (tseg2 > max->phase_seg2) {
  121. return -ENOTSUP;
  122. }
  123. } else if (tseg1 < tseg1_min) {
  124. /* Sample point location must be increased */
  125. tseg1 = tseg1_min;
  126. tseg2 = total_tq - CAN_SYNC_SEG - tseg1;
  127. if (tseg2 < min->phase_seg2) {
  128. return -ENOTSUP;
  129. }
  130. }
  131. res->phase_seg2 = tseg2;
  132. /* Attempt to distribute tseg1 evenly between prop_seq and phase_seg1 */
  133. res->prop_seg = CLAMP(tseg1 / 2, min->prop_seg, max->prop_seg);
  134. res->phase_seg1 = tseg1 - res->prop_seg;
  135. if (res->phase_seg1 > max->phase_seg1) {
  136. /* Even tseg1 distribution not possible, decrease phase_seg1 */
  137. res->phase_seg1 = max->phase_seg1;
  138. res->prop_seg = tseg1 - res->phase_seg1;
  139. } else if (res->phase_seg1 < min->phase_seg1) {
  140. /* Even tseg1 distribution not possible, increase phase_seg1 */
  141. res->phase_seg1 = min->phase_seg1;
  142. res->prop_seg = tseg1 - res->phase_seg1;
  143. }
  144. /* Calculate the resulting sample point */
  145. sample_pnt_res = (CAN_SYNC_SEG + tseg1) * 1000 / total_tq;
  146. /* Return the absolute sample point error */
  147. return sample_pnt_res > sample_pnt ?
  148. sample_pnt_res - sample_pnt :
  149. sample_pnt - sample_pnt_res;
  150. }
  151. int can_calc_timing_internal(const struct device *dev, struct can_timing *res,
  152. const struct can_timing *min, const struct can_timing *max,
  153. uint32_t bitrate, uint16_t sample_pnt)
  154. {
  155. uint32_t total_tq = CAN_SYNC_SEG + max->prop_seg + max->phase_seg1 + max->phase_seg2;
  156. struct can_timing tmp_res = { 0 };
  157. int err_min = INT_MAX;
  158. uint32_t core_clock;
  159. int prescaler;
  160. int err;
  161. if (bitrate == 0 || sample_pnt >= 1000) {
  162. return -EINVAL;
  163. }
  164. err = can_get_core_clock(dev, &core_clock);
  165. if (err != 0) {
  166. return -EIO;
  167. }
  168. if (sample_pnt == 0U) {
  169. sample_pnt = sample_point_for_bitrate(bitrate);
  170. }
  171. for (prescaler = MAX(core_clock / (total_tq * bitrate), min->prescaler);
  172. prescaler <= max->prescaler;
  173. prescaler++) {
  174. if (core_clock % (prescaler * bitrate)) {
  175. /* No integer total_tq for this prescaler setting */
  176. continue;
  177. }
  178. total_tq = core_clock / (prescaler * bitrate);
  179. err = update_sample_pnt(total_tq, sample_pnt, &tmp_res, min, max);
  180. if (err < 0) {
  181. /* Sample point cannot be met for this prescaler setting */
  182. continue;
  183. }
  184. if (err < err_min) {
  185. /* Improved sample point match */
  186. err_min = err;
  187. res->prop_seg = tmp_res.prop_seg;
  188. res->phase_seg1 = tmp_res.phase_seg1;
  189. res->phase_seg2 = tmp_res.phase_seg2;
  190. res->prescaler = (uint16_t)prescaler;
  191. if (err == 0) {
  192. /* Perfect sample point match */
  193. break;
  194. }
  195. }
  196. }
  197. if (err_min != 0U) {
  198. printf("Sample point error: %d 1/1000\n", err_min);
  199. }
  200. /* Calculate default sjw as phase_seg2 / 2 and clamp the result */
  201. res->sjw = MIN(res->phase_seg1, res->phase_seg2 / 2);
  202. res->sjw = CLAMP(res->sjw, min->sjw, max->sjw);
  203. return err_min == INT_MAX ? -ENOTSUP : err_min;
  204. }
  205. int can_calc_timing(const struct device *dev, struct can_timing *res,
  206. uint32_t bitrate, uint16_t sample_pnt)
  207. {
  208. const struct can_timing *min = can_get_timing_min(dev);
  209. const struct can_timing *max = can_get_timing_max(dev);
  210. if (bitrate > 1000000) {
  211. return -EINVAL;
  212. }
  213. return can_calc_timing_internal(dev, res, min, max, bitrate, sample_pnt);
  214. }
  215. int check_timing_in_range(const struct can_timing *timing,
  216. const struct can_timing *min,
  217. const struct can_timing *max)
  218. {
  219. if (!IN_RANGE(timing->sjw, min->sjw, max->sjw) ||
  220. !IN_RANGE(timing->prop_seg, min->prop_seg, max->prop_seg) ||
  221. !IN_RANGE(timing->phase_seg1, min->phase_seg1, max->phase_seg1) ||
  222. !IN_RANGE(timing->phase_seg2, min->phase_seg2, max->phase_seg2) ||
  223. !IN_RANGE(timing->prescaler, min->prescaler, max->prescaler)) {
  224. return -ENOTSUP;
  225. }
  226. if ((timing->sjw > timing->phase_seg1) || (timing->sjw > timing->phase_seg2)) {
  227. return -ENOTSUP;
  228. }
  229. return 0;
  230. }
  231. int can_set_timing(const struct device *dev,
  232. const struct can_timing *timing)
  233. {
  234. const struct can_driver_api *api = (const struct can_driver_api *)dev->api;
  235. const struct can_timing *min = can_get_timing_min(dev);
  236. const struct can_timing *max = can_get_timing_max(dev);
  237. int err;
  238. err = check_timing_in_range(timing, min, max);
  239. if (err != 0) {
  240. return err;
  241. }
  242. return api->set_timing(dev, timing);
  243. }
  244. int can_set_bitrate(const struct device *dev, uint32_t bitrate)
  245. {
  246. struct can_timing timing = { 0 };
  247. uint32_t min = can_get_bitrate_min(dev);
  248. uint32_t max = can_get_bitrate_max(dev);
  249. uint16_t sample_pnt;
  250. int ret;
  251. if ((bitrate < min) || (bitrate > max)) {
  252. return -ENOTSUP;
  253. }
  254. sample_pnt = sample_point_for_bitrate(bitrate);
  255. ret = can_calc_timing(dev, &timing, bitrate, sample_pnt);
  256. if (ret < 0) {
  257. return ret;
  258. }
  259. if (ret > SAMPLE_POINT_MARGIN) {
  260. return -ERANGE;
  261. }
  262. return can_set_timing(dev, &timing);
  263. }
  264. CO_ReturnError_t CO_CANmodule_init(CO_CANmodule_t *CANmodule,
  265. void *CANdriverState,
  266. CO_CANrx_t rxArray[], uint16_t rxSize,
  267. CO_CANtx_t txArray[], uint16_t txSize,
  268. uint16_t CANbitRate)
  269. {
  270. struct canopen_context *ctx = (struct canopen_context *)CANdriverState;
  271. uint16_t i;
  272. int err;
  273. int max_filters;
  274. printf("rxSize = %d, txSize = %d\n", rxSize, txSize);
  275. if (!CANmodule || !rxArray || !txArray || !CANdriverState) {
  276. printf("failed to initialize CAN module\n");
  277. return CO_ERROR_ILLEGAL_ARGUMENT;
  278. }
  279. max_filters = can_get_max_filters(ctx->dev, false);
  280. if (max_filters != -1) {
  281. if (max_filters < 0) {
  282. printf("unable to determine number of CAN RX filters\n");
  283. return CO_ERROR_SYSCALL;
  284. }
  285. if (rxSize > max_filters) {
  286. printf("insufficient number of concurrent CAN RX filters"
  287. " (needs %d, %d available)\n", rxSize, max_filters);
  288. return CO_ERROR_OUT_OF_MEMORY;
  289. } else if (rxSize < max_filters) {
  290. printf("excessive number of concurrent CAN RX filters enabled"
  291. " (needs %d, %d available)\n", rxSize, max_filters);
  292. }
  293. }
  294. canopen_detach_all_rx_filters(CANmodule);
  295. CANmodule->CANptr = ctx->dev;
  296. CANmodule->rxArray = rxArray;
  297. CANmodule->rxSize = rxSize;
  298. CANmodule->txArray = txArray;
  299. CANmodule->txSize = txSize;
  300. CANmodule->CANnormal = false;
  301. CANmodule->firstCANtxMessage = true;
  302. CANmodule->errinfo = 0;
  303. for (i = 0U; i < rxSize; i++) {
  304. rxArray[i].ident = 0U;
  305. rxArray[i].CANrx_callback = NULL;
  306. rxArray[i].filter_id = -ENOSPC;
  307. }
  308. for (i = 0U; i < txSize; i++) {
  309. txArray[i].bufferFull = false;
  310. }
  311. CANmodule->configured = true;
  312. return CO_ERROR_NO;
  313. }
  314. void CO_CANmodule_disable(CO_CANmodule_t *CANmodule)
  315. {
  316. int err;
  317. if (!CANmodule || !CANmodule->CANptr) {
  318. return;
  319. }
  320. canopen_detach_all_rx_filters(CANmodule);
  321. err = can_stop(CANmodule->CANptr);
  322. if (err != 0 && err != -EALREADY) {
  323. printf("failed to disable CAN interface (err %d)\n", err);
  324. }
  325. }
  326. int can_add_rx_filter(const struct device *dev, can_rx_callback_t callback,
  327. void *user_data, const struct can_filter *filter)
  328. {
  329. const struct can_driver_api *api = (const struct can_driver_api *)dev->api;
  330. uint32_t id_mask;
  331. if (callback == NULL || filter == NULL) {
  332. return -EINVAL;
  333. }
  334. if ((filter->flags & CAN_FILTER_IDE) != 0U) {
  335. id_mask = CAN_EXT_ID_MASK;
  336. } else {
  337. id_mask = CAN_STD_ID_MASK;
  338. }
  339. if (((filter->id & ~(id_mask)) != 0U) || ((filter->mask & ~(id_mask)) != 0U)) {
  340. return -EINVAL;
  341. }
  342. return api->add_rx_filter(dev, callback, user_data, filter);
  343. }
  344. uint16_t CO_CANrxMsg_readIdent(CO_CANrxMsg_t *rxMsg)
  345. {
  346. return rxMsg->ident;
  347. }
  348. uint8_t CO_CANrxMsg_readDLC(CO_CANrxMsg_t *rxMsg)
  349. {
  350. return rxMsg->DLC;
  351. }
  352. uint8_t *CO_CANrxMsg_readData(CO_CANrxMsg_t *rxMsg)
  353. {
  354. return rxMsg->data;
  355. }
  356. CO_ReturnError_t CO_CANrxBufferInit(CO_CANmodule_t *CANmodule, uint16_t index,
  357. uint16_t ident, uint16_t mask, bool_t rtr,
  358. void *object,
  359. void (*CANrx_callback)(void *object, void *message))
  360. {
  361. struct can_filter filter;
  362. CO_CANrx_t *buffer;
  363. if (CANmodule == NULL || !CANrx_callback || (index >= CANmodule->rxSize)) {
  364. return CO_ERROR_ILLEGAL_ARGUMENT;
  365. }
  366. buffer = &CANmodule->rxArray[index];
  367. buffer->object = object;
  368. buffer->CANrx_callback = CANrx_callback;
  369. buffer->ident = ident;
  370. buffer->mask = mask;
  371. #ifndef CONFIG_CAN_ACCEPT_RTR
  372. if (rtr) {
  373. printf("request for RTR frames, but RTR frames are rejected\n");
  374. CO_errorReport(CO->em, CO_EM_GENERIC_SOFTWARE_ERROR,
  375. CO_EMC_SOFTWARE_INTERNAL, 0);
  376. return CO_ERROR_ILLEGAL_ARGUMENT;
  377. }
  378. #else /* !CONFIG_CAN_ACCEPT_RTR */
  379. buffer->rtr = rtr;
  380. #endif /* CONFIG_CAN_ACCEPT_RTR */
  381. filter.flags = 0U;
  382. filter.id = ident;
  383. filter.mask = mask;
  384. if (buffer->filter_id != -ENOSPC) {
  385. can_remove_rx_filter(CANmodule->CANptr, buffer->filter_id);
  386. }
  387. buffer->filter_id = can_add_rx_filter(CANmodule->CANptr,
  388. canopen_rx_callback,
  389. CANmodule, &filter);
  390. if (buffer->filter_id == -ENOSPC) {
  391. printf("failed to add CAN rx callback, no free filter\n");
  392. return CO_ERROR_OUT_OF_MEMORY;
  393. }
  394. return CO_ERROR_NO;
  395. }
  396. CO_CANtx_t *CO_CANtxBufferInit(CO_CANmodule_t *CANmodule, uint16_t index,
  397. uint16_t ident, bool_t rtr, uint8_t noOfBytes,
  398. bool_t syncFlag)
  399. {
  400. CO_CANtx_t *buffer;
  401. if (CANmodule == NULL || index >= CANmodule->txSize) {
  402. return NULL;
  403. }
  404. buffer = &CANmodule->txArray[index];
  405. buffer->ident = ident;
  406. buffer->rtr = rtr;
  407. buffer->DLC = noOfBytes;
  408. buffer->bufferFull = false;
  409. buffer->syncFlag = syncFlag;
  410. return buffer;
  411. }
  412. int can_send(const struct device *dev, const struct can_frame *frame,
  413. k_timeout_t timeout, can_tx_callback_t callback,
  414. void *user_data)
  415. {
  416. const struct can_driver_api *api = (const struct can_driver_api *)dev->api;
  417. uint32_t id_mask;
  418. if (frame == NULL) {
  419. return -EINVAL;
  420. }
  421. if ((frame->flags & CAN_FRAME_IDE) != 0U) {
  422. id_mask = CAN_EXT_ID_MASK;
  423. } else {
  424. id_mask = CAN_STD_ID_MASK;
  425. }
  426. if ((frame->id & ~(id_mask)) != 0U) {
  427. return -EINVAL;
  428. }
  429. return api->send(dev, frame, timeout, callback, user_data);
  430. }
  431. CO_ReturnError_t CO_CANsend(CO_CANmodule_t *CANmodule, CO_CANtx_t *buffer)
  432. {
  433. CO_ReturnError_t ret = CO_ERROR_NO;
  434. struct can_frame frame;
  435. int err;
  436. if (!CANmodule || !CANmodule->CANptr || !buffer) {
  437. return CO_ERROR_ILLEGAL_ARGUMENT;
  438. }
  439. memset(&frame, 0, sizeof(frame));
  440. if (buffer->bufferFull) {
  441. buffer->bufferFull = false;
  442. ret = CO_ERROR_TX_OVERFLOW;
  443. }
  444. frame.id = buffer->ident;
  445. frame.dlc = buffer->DLC;
  446. frame.flags = (buffer->rtr ? CAN_FRAME_RTR : 0);
  447. memcpy(frame.data, buffer->data, buffer->DLC);
  448. err = can_send(CANmodule->CANptr, &frame, K_NO_WAIT, NULL, CANmodule);
  449. if (err == -EAGAIN) {
  450. buffer->bufferFull = true;
  451. } else if (err != 0) {
  452. ret = CO_ERROR_TX_UNCONFIGURED;
  453. }
  454. return ret;
  455. }
  456. void CO_CANclearPendingSyncPDOs(CO_CANmodule_t *CANmodule)
  457. {
  458. bool_t tpdoDeleted = false;
  459. CO_CANtx_t *buffer;
  460. uint16_t i;
  461. if (!CANmodule) {
  462. return;
  463. }
  464. for (i = 0; i < CANmodule->txSize; i++) {
  465. buffer = &CANmodule->txArray[i];
  466. if (buffer->bufferFull && buffer->syncFlag) {
  467. buffer->bufferFull = false;
  468. tpdoDeleted = true;
  469. }
  470. }
  471. if (tpdoDeleted) {
  472. CO_errorReport(CO->em, CO_EM_TPDO_OUTSIDE_WINDOW,
  473. CO_EMC_COMMUNICATION, 0);
  474. }
  475. }
  476. void CO_CANverifyErrors(CO_CANmodule_t *CANmodule)
  477. {
  478. CO_EM_t *em = (CO_EM_t *)CO->em;
  479. struct can_bus_err_cnt err_cnt;
  480. enum can_state state;
  481. uint8_t rx_overflows;
  482. uint32_t errors;
  483. int err;
  484. /*
  485. * TODO: Zephyr lacks an API for reading the rx mailbox
  486. * overflow counter.
  487. */
  488. rx_overflows = 0;
  489. err = can_get_state(CANmodule->CANptr, &state, &err_cnt);
  490. if (err != 0) {
  491. printf("failed to get CAN controller state (err %d)\n", err);
  492. return;
  493. }
  494. errors = ((uint32_t)err_cnt.tx_err_cnt << 16) |
  495. ((uint32_t)err_cnt.rx_err_cnt << 8) |
  496. rx_overflows;
  497. if (errors != CANmodule->errinfo) {
  498. CANmodule->errinfo = errors;
  499. if (state == CAN_STATE_BUS_OFF) {
  500. /* Bus off */
  501. CO_errorReport(em, CO_EM_CAN_TX_BUS_OFF,
  502. CO_EMC_BUS_OFF_RECOVERED, errors);
  503. } else {
  504. /* Bus not off */
  505. CO_errorReset(em, CO_EM_CAN_TX_BUS_OFF, errors);
  506. if ((err_cnt.rx_err_cnt >= 96U) ||
  507. (err_cnt.tx_err_cnt >= 96U)) {
  508. /* Bus warning */
  509. CO_errorReport(em, CO_EM_CAN_BUS_WARNING,
  510. CO_EMC_NO_ERROR, errors);
  511. } else {
  512. /* Bus not warning */
  513. CO_errorReset(em, CO_EM_CAN_BUS_WARNING,
  514. errors);
  515. }
  516. if (err_cnt.rx_err_cnt >= 128U) {
  517. /* Bus rx passive */
  518. CO_errorReport(em, CO_EM_CAN_RX_BUS_PASSIVE,
  519. CO_EMC_CAN_PASSIVE, errors);
  520. } else {
  521. /* Bus not rx passive */
  522. CO_errorReset(em, CO_EM_CAN_RX_BUS_PASSIVE,
  523. errors);
  524. }
  525. if (err_cnt.tx_err_cnt >= 128U &&
  526. !CANmodule->firstCANtxMessage) {
  527. /* Bus tx passive */
  528. CO_errorReport(em, CO_EM_CAN_TX_BUS_PASSIVE,
  529. CO_EMC_CAN_PASSIVE, errors);
  530. } else if (CO_isError(em, CO_EM_CAN_TX_BUS_PASSIVE)) {
  531. /* Bus not tx passive */
  532. CO_errorReset(em, CO_EM_CAN_TX_BUS_PASSIVE,
  533. errors);
  534. CO_errorReset(em, CO_EM_CAN_TX_OVERFLOW,
  535. errors);
  536. }
  537. }
  538. /* This code can be activated if we can read the overflows*/
  539. if (false && rx_overflows != 0U) {
  540. CO_errorReport(em, CO_EM_CAN_RXB_OVERFLOW,
  541. CO_EMC_CAN_OVERRUN, errors);
  542. }
  543. }
  544. }
  545. /******************************************************************************/
  546. /* Get error counters from the module. If necessary, function may use different way to determine errors. */
  547. static uint16_t rxErrors = 0, txErrors = 0, overflow = 0;
  548. void CO_CANmodule_process(CO_CANmodule_t *CANmodule)
  549. {
  550. uint32_t err;
  551. err = ((uint32_t)txErrors << 16) | ((uint32_t)rxErrors << 8) | overflow;
  552. if (CANmodule->errOld != err) {
  553. uint16_t status = CANmodule->CANerrorStatus;
  554. CANmodule->errOld = err;
  555. if (txErrors >= 256U) {
  556. /* bus off */
  557. status |= CO_CAN_ERRTX_BUS_OFF;
  558. } else {
  559. /* recalculate CANerrorStatus, first clear some flags */
  560. status &= 0xFFFF ^ (CO_CAN_ERRTX_BUS_OFF |
  561. CO_CAN_ERRRX_WARNING | CO_CAN_ERRRX_PASSIVE |
  562. CO_CAN_ERRTX_WARNING | CO_CAN_ERRTX_PASSIVE);
  563. /* rx bus warning or passive */
  564. if (rxErrors >= 128) {
  565. status |= CO_CAN_ERRRX_WARNING | CO_CAN_ERRRX_PASSIVE;
  566. } else if (rxErrors >= 96) {
  567. status |= CO_CAN_ERRRX_WARNING;
  568. }
  569. /* tx bus warning or passive */
  570. if (txErrors >= 128) {
  571. status |= CO_CAN_ERRTX_WARNING | CO_CAN_ERRTX_PASSIVE;
  572. } else if (rxErrors >= 96) {
  573. status |= CO_CAN_ERRTX_WARNING;
  574. }
  575. /* if not tx passive clear also overflow */
  576. if ((status & CO_CAN_ERRTX_PASSIVE) == 0) {
  577. status &= 0xFFFF ^ CO_CAN_ERRTX_OVERFLOW;
  578. }
  579. }
  580. if (overflow != 0) {
  581. /* CAN RX bus overflow */
  582. status |= CO_CAN_ERRRX_OVERFLOW;
  583. }
  584. CANmodule->CANerrorStatus = status;
  585. }
  586. }