can.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  1. /**
  2. * \file
  3. *
  4. * \brief SAM Control Area Network (CAN) Low Level Driver
  5. *
  6. * Copyright (C) 2015-2016 Atmel Corporation. All rights reserved.
  7. *
  8. * \asf_license_start
  9. *
  10. * \page License
  11. *
  12. * Redistribution and use in source and binary forms, with or without
  13. * modification, are permitted provided that the following conditions are met:
  14. *
  15. * 1. Redistributions of source code must retain the above copyright notice,
  16. * this list of conditions and the following disclaimer.
  17. *
  18. * 2. Redistributions in binary form must reproduce the above copyright notice,
  19. * this list of conditions and the following disclaimer in the documentation
  20. * and/or other materials provided with the distribution.
  21. *
  22. * 3. The name of Atmel may not be used to endorse or promote products derived
  23. * from this software without specific prior written permission.
  24. *
  25. * 4. This software may only be redistributed and used in connection with an
  26. * Atmel microcontroller product.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
  29. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  30. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
  31. * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
  32. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  33. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  34. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  36. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  37. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  38. * POSSIBILITY OF SUCH DAMAGE.
  39. *
  40. * \asf_license_stop
  41. *
  42. */
  43. /*
  44. * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
  45. */
  46. #include "can.h"
  47. #include <string.h>
  48. /* Instance for GCLK setting. */
  49. struct system_gclk_chan_config gclk_chan_conf;
  50. /* Message ram definition. */
  51. COMPILER_ALIGNED(4)
  52. static struct can_rx_element_buffer can0_rx_buffer[CONF_CAN0_RX_BUFFER_NUM];
  53. COMPILER_ALIGNED(4)
  54. static struct can_rx_element_fifo_0 can0_rx_fifo_0[CONF_CAN0_RX_FIFO_0_NUM];
  55. COMPILER_ALIGNED(4)
  56. static struct can_rx_element_fifo_1 can0_rx_fifo_1[CONF_CAN0_RX_FIFO_1_NUM];
  57. COMPILER_ALIGNED(4)
  58. static struct can_tx_element can0_tx_buffer[CONF_CAN0_TX_BUFFER_NUM + CONF_CAN0_TX_FIFO_QUEUE_NUM];
  59. COMPILER_ALIGNED(4)
  60. static struct can_tx_event_element can0_tx_event_fifo[CONF_CAN0_TX_EVENT_FIFO];
  61. COMPILER_ALIGNED(4)
  62. static struct can_standard_message_filter_element can0_rx_standard_filter[CONF_CAN0_RX_STANDARD_ID_FILTER_NUM];
  63. COMPILER_ALIGNED(4)
  64. static struct can_extended_message_filter_element can0_rx_extended_filter[CONF_CAN0_RX_EXTENDED_ID_FILTER_NUM];
  65. COMPILER_ALIGNED(4)
  66. static struct can_rx_element_buffer can1_rx_buffer[CONF_CAN1_RX_BUFFER_NUM];
  67. COMPILER_ALIGNED(4)
  68. static struct can_rx_element_fifo_0 can1_rx_fifo_0[CONF_CAN1_RX_FIFO_0_NUM];
  69. COMPILER_ALIGNED(4)
  70. static struct can_rx_element_fifo_1 can1_rx_fifo_1[CONF_CAN1_RX_FIFO_1_NUM];
  71. COMPILER_ALIGNED(4)
  72. static struct can_tx_element can1_tx_buffer[CONF_CAN1_TX_BUFFER_NUM + CONF_CAN1_TX_FIFO_QUEUE_NUM];
  73. COMPILER_ALIGNED(4)
  74. static struct can_tx_event_element can1_tx_event_fifo[CONF_CAN1_TX_EVENT_FIFO];
  75. COMPILER_ALIGNED(4)
  76. static struct can_standard_message_filter_element can1_rx_standard_filter[CONF_CAN1_RX_STANDARD_ID_FILTER_NUM];
  77. COMPILER_ALIGNED(4)
  78. static struct can_extended_message_filter_element can1_rx_extended_filter[CONF_CAN1_RX_EXTENDED_ID_FILTER_NUM];
  79. static void _can_message_memory_init(Can *hw)
  80. {
  81. if (hw == CAN0) {
  82. hw->SIDFC.reg = CAN_SIDFC_FLSSA((uint32_t)can0_rx_standard_filter) |
  83. CAN_SIDFC_LSS(CONF_CAN0_RX_STANDARD_ID_FILTER_NUM);
  84. hw->XIDFC.reg = CAN_XIDFC_FLESA((uint32_t)can0_rx_extended_filter) |
  85. CAN_XIDFC_LSE(CONF_CAN0_RX_EXTENDED_ID_FILTER_NUM);
  86. hw->RXF0C.reg = CAN_RXF0C_F0SA((uint32_t)can0_rx_fifo_0) |
  87. CAN_RXF0C_F0S(CONF_CAN0_RX_FIFO_0_NUM);
  88. hw->RXF1C.reg = CAN_RXF1C_F1SA((uint32_t)can0_rx_fifo_1) |
  89. CAN_RXF1C_F1S(CONF_CAN0_RX_FIFO_1_NUM);
  90. hw->RXBC.reg = CAN_RXBC_RBSA((uint32_t)can0_rx_buffer);
  91. hw->TXBC.reg = CAN_TXBC_TBSA((uint32_t)can0_tx_buffer) |
  92. CAN_TXBC_NDTB(CONF_CAN0_TX_BUFFER_NUM) |
  93. CAN_TXBC_TFQS(CONF_CAN0_TX_FIFO_QUEUE_NUM);
  94. hw->TXEFC.reg = CAN_TXEFC_EFSA((uint32_t)can0_tx_event_fifo) |
  95. CAN_TXEFC_EFS(CONF_CAN0_TX_EVENT_FIFO);
  96. } else if (hw == CAN1) {
  97. hw->SIDFC.reg = CAN_SIDFC_FLSSA((uint32_t)can1_rx_standard_filter) |
  98. CAN_SIDFC_LSS(CONF_CAN1_RX_STANDARD_ID_FILTER_NUM);
  99. hw->XIDFC.reg = CAN_XIDFC_FLESA((uint32_t)can1_rx_extended_filter) |
  100. CAN_XIDFC_LSE(CONF_CAN1_RX_EXTENDED_ID_FILTER_NUM);
  101. hw->RXF0C.reg = CAN_RXF0C_F0SA((uint32_t)can1_rx_fifo_0) |
  102. CAN_RXF0C_F0S(CONF_CAN1_RX_FIFO_0_NUM);
  103. hw->RXF1C.reg = CAN_RXF1C_F1SA((uint32_t)can1_rx_fifo_1) |
  104. CAN_RXF1C_F1S(CONF_CAN1_RX_FIFO_1_NUM);
  105. hw->RXBC.reg = CAN_RXBC_RBSA((uint32_t)can1_rx_buffer);
  106. hw->TXBC.reg = CAN_TXBC_TBSA((uint32_t)can1_tx_buffer) |
  107. CAN_TXBC_NDTB(CONF_CAN1_TX_BUFFER_NUM) |
  108. CAN_TXBC_TFQS(CONF_CAN1_TX_FIFO_QUEUE_NUM);
  109. hw->TXEFC.reg = CAN_TXEFC_EFSA((uint32_t)can1_tx_event_fifo) |
  110. CAN_TXEFC_EFS(CONF_CAN1_TX_EVENT_FIFO);
  111. }
  112. /**
  113. * The data size in conf_can.h should be 8/12/16/20/24/32/48/64,
  114. * The corresponding setting value in register is 0/1//2/3/4/5/6/7.
  115. * To simplify the calculation, seperate to two group 8/12/16/20/24 which
  116. * increased with 4 and 32/48/64 which increased with 16.
  117. */
  118. if (CONF_CAN_ELEMENT_DATA_SIZE <= 24) {
  119. hw->RXESC.reg = CAN_RXESC_RBDS((CONF_CAN_ELEMENT_DATA_SIZE - 8) / 4) |
  120. CAN_RXESC_F0DS((CONF_CAN_ELEMENT_DATA_SIZE - 8) / 4) |
  121. CAN_RXESC_F1DS((CONF_CAN_ELEMENT_DATA_SIZE - 8) / 4);
  122. hw->TXESC.reg = CAN_TXESC_TBDS((CONF_CAN_ELEMENT_DATA_SIZE - 8) / 4);
  123. } else {
  124. hw->RXESC.reg = CAN_RXESC_RBDS((CONF_CAN_ELEMENT_DATA_SIZE - 32) / 16 + 5) |
  125. CAN_RXESC_F0DS((CONF_CAN_ELEMENT_DATA_SIZE - 32) / 16 + 5) |
  126. CAN_RXESC_F1DS((CONF_CAN_ELEMENT_DATA_SIZE - 32) / 16 + 5);
  127. hw->TXESC.reg = CAN_TXESC_TBDS((CONF_CAN_ELEMENT_DATA_SIZE - 32) / 16 + 5);
  128. }
  129. }
  130. static void _can_set_configuration(Can *hw, struct can_config *config)
  131. {
  132. /* Timing setting. */
  133. hw->NBTP.reg = CAN_NBTP_NBRP(CONF_CAN_NBTP_NBRP_VALUE) |
  134. CAN_NBTP_NSJW(CONF_CAN_NBTP_NSJW_VALUE) |
  135. CAN_NBTP_NTSEG1(CONF_CAN_NBTP_NTSEG1_VALUE) |
  136. CAN_NBTP_NTSEG2(CONF_CAN_NBTP_NTSEG2_VALUE);
  137. hw->DBTP.reg = CAN_DBTP_DBRP(CONF_CAN_DBTP_DBRP_VALUE) |
  138. CAN_DBTP_DSJW(CONF_CAN_DBTP_DSJW_VALUE) |
  139. CAN_DBTP_DTSEG1(CONF_CAN_DBTP_DTSEG1_VALUE) |
  140. CAN_DBTP_DTSEG2(CONF_CAN_DBTP_DTSEG2_VALUE);
  141. if (config->tdc_enable) {
  142. hw->DBTP.reg |= CAN_DBTP_TDC;
  143. }
  144. if (config->run_in_standby) {
  145. hw->MRCFG.reg |= 0x01<<6;
  146. }
  147. hw->RWD.reg |= CAN_RWD_WDC(config->watchdog_configuration);
  148. if (config->transmit_pause) {
  149. hw->CCCR.reg |= CAN_CCCR_TXP;
  150. }
  151. if (config->edge_filtering) {
  152. hw->CCCR.reg |= CAN_CCCR_EFBI;
  153. }
  154. if (config->protocol_exception_handling) {
  155. hw->CCCR.reg |= CAN_CCCR_PXHD;
  156. }
  157. if (!config->automatic_retransmission) {
  158. hw->CCCR.reg |= CAN_CCCR_DAR;
  159. }
  160. if (config->clock_stop_request) {
  161. hw->CCCR.reg |= CAN_CCCR_CSR;
  162. }
  163. if (config->clock_stop_acknowledge) {
  164. hw->CCCR.reg |= CAN_CCCR_CSA;
  165. }
  166. hw->TSCC.reg = CAN_TSCC_TCP(config->timestamp_prescaler) |
  167. CAN_TSCC_TSS_INC_Val;
  168. hw->TOCC.reg = CAN_TOCC_TOP(config->timeout_period) |
  169. config->timeout_mode | config->timeout_enable;
  170. hw->TDCR.reg = CAN_TDCR_TDCO(config->delay_compensation_offset) |
  171. CAN_TDCR_TDCF(config->delay_compensation_filter_window_length);
  172. hw->GFC.reg = CAN_GFC_ANFS(config->nonmatching_frames_action_standard) |
  173. CAN_GFC_ANFE(config->nonmatching_frames_action_extended);
  174. if (config->remote_frames_standard_reject) {
  175. hw->GFC.reg |= CAN_GFC_RRFS;
  176. }
  177. if (config->remote_frames_extended_reject) {
  178. hw->GFC.reg |= CAN_GFC_RRFE;
  179. }
  180. hw->XIDAM.reg = config->extended_id_mask;
  181. if (config->rx_fifo_0_overwrite) {
  182. hw->RXF0C.reg |= CAN_RXF0C_F0OM;
  183. }
  184. hw->RXF0C.reg |= CAN_RXF0C_F0WM(config->rx_fifo_0_watermark);
  185. if (config->rx_fifo_1_overwrite) {
  186. hw->RXF1C.reg |= CAN_RXF1C_F1OM;
  187. }
  188. hw->RXF1C.reg |= CAN_RXF1C_F1WM(config->rx_fifo_1_watermark);
  189. if (config->tx_queue_mode) {
  190. hw->TXBC.reg |= CAN_TXBC_TFQM;
  191. }
  192. hw->TXEFC.reg |= CAN_TXEFC_EFWM(config->tx_event_fifo_watermark);
  193. }
  194. static void _can_enable_peripheral_clock(struct can_module *const module_inst)
  195. {
  196. if (module_inst->hw == CAN0) {
  197. /* Turn on the digital interface clock. */
  198. system_ahb_clock_set_mask(MCLK_AHBMASK_CAN0);
  199. } else if (module_inst->hw == CAN1) {
  200. /* Turn on the digital interface clock. */
  201. system_ahb_clock_set_mask(MCLK_AHBMASK_CAN1);
  202. }
  203. }
  204. void can_init(struct can_module *const module_inst, Can *hw,
  205. struct can_config *config)
  206. {
  207. /* Sanity check arguments */
  208. Assert(module_inst);
  209. Assert(hw);
  210. Assert(config);
  211. /* Associate the software module instance with the hardware module */
  212. module_inst->hw = hw;
  213. /* Enable peripheral clock */
  214. _can_enable_peripheral_clock(module_inst);
  215. /* Configure GCLK channel */
  216. system_gclk_chan_get_config_defaults(&gclk_chan_conf);
  217. gclk_chan_conf.source_generator = config->clock_source;
  218. if (hw == CAN0) {
  219. system_gclk_chan_set_config(CAN0_GCLK_ID, &gclk_chan_conf);
  220. system_gclk_chan_enable(CAN0_GCLK_ID);
  221. } else if (hw == CAN1) {
  222. system_gclk_chan_set_config(CAN1_GCLK_ID, &gclk_chan_conf);
  223. system_gclk_chan_enable(CAN1_GCLK_ID);
  224. }
  225. /* Configuration Change Enable. */
  226. hw->CCCR.reg |= CAN_CCCR_CCE;
  227. /* Initialize the message memory address. */
  228. _can_message_memory_init(hw);
  229. /* Set the configuration. */
  230. _can_set_configuration(hw, config);
  231. /* Enable the interrupt setting which no need change. */
  232. hw->ILE.reg = CAN_ILE_EINT0 | CAN_ILE_EINT1;
  233. hw->TXBTIE.reg = CAN_TXBTIE_MASK;
  234. hw->TXBCIE.reg = CAN_TXBCIE_MASK;
  235. }
  236. void can_set_baudrate(Can *hw, uint32_t baudrate)
  237. {
  238. uint32_t gclk_can_value = 0;
  239. uint32_t can_nbtp_nbrp_value;
  240. uint32_t can_nbtp_nsgw_value = 3, can_nbtp_ntseg1_value = 10, can_nbtp_ntseg2_value = 3;
  241. if (hw == CAN0) {
  242. gclk_can_value = system_gclk_chan_get_hz(CAN0_GCLK_ID);
  243. } else if (hw == CAN1) {
  244. gclk_can_value = system_gclk_chan_get_hz(CAN1_GCLK_ID);
  245. }
  246. can_nbtp_nbrp_value = gclk_can_value / baudrate / (3 + can_nbtp_ntseg1_value + can_nbtp_ntseg2_value);
  247. hw->NBTP.reg = CAN_NBTP_NBRP(can_nbtp_nbrp_value) |
  248. CAN_NBTP_NSJW(can_nbtp_nsgw_value) |
  249. CAN_NBTP_NTSEG1(can_nbtp_ntseg1_value) |
  250. CAN_NBTP_NTSEG2(can_nbtp_ntseg2_value);
  251. }
  252. void can_fd_set_baudrate(Can *hw, uint32_t baudrate)
  253. {
  254. uint32_t gclk_can_fd_value = 0;
  255. uint32_t can_fd_dbtp_dbrp_value;
  256. uint32_t can_fd_dbtp_dsgw_value = 3, can_fd_dbtp_dtseg1_value = 10, can_fd_dbtp_dtseg2_value = 3;
  257. if (hw == CAN0) {
  258. gclk_can_fd_value = system_gclk_chan_get_hz(CAN0_GCLK_ID);
  259. } else if (hw == CAN1) {
  260. gclk_can_fd_value = system_gclk_chan_get_hz(CAN1_GCLK_ID);
  261. }
  262. can_fd_dbtp_dbrp_value = gclk_can_fd_value / baudrate / (3 + can_fd_dbtp_dtseg1_value + can_fd_dbtp_dtseg2_value);
  263. hw->NBTP.reg = CAN_DBTP_DBRP(can_fd_dbtp_dbrp_value) |
  264. CAN_DBTP_DSJW(can_fd_dbtp_dsgw_value) |
  265. CAN_DBTP_DTSEG1(can_fd_dbtp_dtseg1_value) |
  266. CAN_DBTP_DTSEG2(can_fd_dbtp_dtseg2_value);
  267. }
  268. void can_start(struct can_module *const module_inst)
  269. {
  270. module_inst->hw->CCCR.reg &= ~CAN_CCCR_INIT;
  271. /* Wait for the sync. */
  272. while (module_inst->hw->CCCR.reg & CAN_CCCR_INIT);
  273. }
  274. void can_stop(struct can_module *const module_inst)
  275. {
  276. module_inst->hw->CCCR.reg |= CAN_CCCR_INIT;
  277. /* Wait for the sync. */
  278. while (!(module_inst->hw->CCCR.reg & CAN_CCCR_INIT));
  279. }
  280. void can_enable_fd_mode(struct can_module *const module_inst)
  281. {
  282. module_inst->hw->CCCR.reg |= CAN_CCCR_INIT;
  283. /* Wait for the sync. */
  284. while (!(module_inst->hw->CCCR.reg & CAN_CCCR_INIT));
  285. module_inst->hw->CCCR.reg |= CAN_CCCR_CCE;
  286. module_inst->hw->CCCR.reg |= CAN_CCCR_FDOE;
  287. module_inst->hw->CCCR.reg |= CAN_CCCR_BRSE;
  288. }
  289. void can_disable_fd_mode(struct can_module *const module_inst)
  290. {
  291. module_inst->hw->CCCR.reg &= ~CAN_CCCR_FDOE;
  292. }
  293. void can_enable_restricted_operation_mode(
  294. struct can_module *const module_inst)
  295. {
  296. module_inst->hw->CCCR.reg |= CAN_CCCR_INIT;
  297. /* Wait for the sync. */
  298. while (!(module_inst->hw->CCCR.reg & CAN_CCCR_INIT));
  299. module_inst->hw->CCCR.reg |= CAN_CCCR_CCE;
  300. module_inst->hw->CCCR.reg |= CAN_CCCR_ASM;
  301. }
  302. void can_disable_restricted_operation_mode(
  303. struct can_module *const module_inst)
  304. {
  305. module_inst->hw->CCCR.reg &= ~CAN_CCCR_ASM;
  306. }
  307. void can_enable_bus_monitor_mode(struct can_module *const module_inst)
  308. {
  309. module_inst->hw->CCCR.reg |= CAN_CCCR_INIT;
  310. /* Wait for the sync. */
  311. while (!(module_inst->hw->CCCR.reg & CAN_CCCR_INIT));
  312. module_inst->hw->CCCR.reg |= CAN_CCCR_CCE;
  313. module_inst->hw->CCCR.reg |= CAN_CCCR_MON;
  314. }
  315. void can_disable_bus_monitor_mode(struct can_module *const module_inst)
  316. {
  317. module_inst->hw->CCCR.reg &= ~CAN_CCCR_MON;
  318. }
  319. void can_enable_sleep_mode(struct can_module *const module_inst)
  320. {
  321. module_inst->hw->CCCR.reg |= CAN_CCCR_CSR;
  322. /* Wait for the sync. */
  323. while (!(module_inst->hw->CCCR.reg & CAN_CCCR_INIT));
  324. while (!(module_inst->hw->CCCR.reg & CAN_CCCR_CSA));
  325. }
  326. void can_disable_sleep_mode(struct can_module *const module_inst)
  327. {
  328. /* Enable peripheral clock */
  329. _can_enable_peripheral_clock(module_inst);
  330. if (module_inst->hw == CAN0) {
  331. system_gclk_chan_set_config(CAN0_GCLK_ID, &gclk_chan_conf);
  332. system_gclk_chan_enable(CAN0_GCLK_ID);
  333. }
  334. if (module_inst->hw == CAN1) {
  335. system_gclk_chan_set_config(CAN1_GCLK_ID, &gclk_chan_conf);
  336. system_gclk_chan_enable(CAN1_GCLK_ID);
  337. }
  338. module_inst->hw->CCCR.reg &= CAN_CCCR_CSR;
  339. while ((module_inst->hw->CCCR.reg & CAN_CCCR_CSA));
  340. }
  341. void can_enable_test_mode(struct can_module *const module_inst)
  342. {
  343. module_inst->hw->CCCR.reg |= CAN_CCCR_INIT;
  344. /* Wait for the sync. */
  345. while (!(module_inst->hw->CCCR.reg & CAN_CCCR_INIT));
  346. module_inst->hw->CCCR.reg |= CAN_CCCR_CCE;
  347. module_inst->hw->CCCR.reg |= CAN_CCCR_TEST;
  348. module_inst->hw->TEST.reg |= CAN_TEST_LBCK;
  349. }
  350. void can_disable_test_mode(struct can_module *const module_inst)
  351. {
  352. module_inst->hw->CCCR.reg &= ~CAN_CCCR_TEST;
  353. }
  354. enum status_code can_set_rx_standard_filter(
  355. struct can_module *const module_inst,
  356. struct can_standard_message_filter_element *sd_filter, uint32_t index)
  357. {
  358. if (module_inst->hw == CAN0) {
  359. can0_rx_standard_filter[index].S0.reg = sd_filter->S0.reg;
  360. return STATUS_OK;
  361. } else if (module_inst->hw == CAN1) {
  362. can1_rx_standard_filter[index].S0.reg = sd_filter->S0.reg;
  363. return STATUS_OK;
  364. }
  365. return STATUS_ERR_INVALID_ARG;
  366. }
  367. enum status_code can_set_rx_extended_filter(
  368. struct can_module *const module_inst,
  369. struct can_extended_message_filter_element *et_filter, uint32_t index)
  370. {
  371. if (module_inst->hw == CAN0) {
  372. can0_rx_extended_filter[index].F0.reg = et_filter->F0.reg;
  373. can0_rx_extended_filter[index].F1.reg = et_filter->F1.reg;
  374. return STATUS_OK;
  375. } else if (module_inst->hw == CAN1) {
  376. can1_rx_extended_filter[index].F0.reg = et_filter->F0.reg;
  377. can1_rx_extended_filter[index].F1.reg = et_filter->F1.reg;
  378. return STATUS_OK;
  379. }
  380. return STATUS_ERR_INVALID_ARG;
  381. }
  382. enum status_code can_get_rx_buffer_element(
  383. struct can_module *const module_inst,
  384. struct can_rx_element_buffer *rx_element, uint32_t index)
  385. {
  386. if (module_inst->hw == CAN0) {
  387. memcpy(rx_element, &can0_rx_buffer[index], sizeof(struct can_rx_element_buffer));
  388. return STATUS_OK;
  389. } else if (module_inst->hw == CAN1) {
  390. memcpy(rx_element, &can1_rx_buffer[index], sizeof(struct can_rx_element_buffer));
  391. return STATUS_OK;
  392. }
  393. return STATUS_ERR_INVALID_ARG;
  394. }
  395. enum status_code can_get_rx_fifo_0_element(
  396. struct can_module *const module_inst,
  397. struct can_rx_element_fifo_0 *rx_element, uint32_t index)
  398. {
  399. if (module_inst->hw == CAN0) {
  400. memcpy(rx_element, &can0_rx_fifo_0[index], sizeof(struct can_rx_element_buffer));
  401. return STATUS_OK;
  402. } else if (module_inst->hw == CAN1) {
  403. memcpy(rx_element, &can1_rx_fifo_0[index], sizeof(struct can_rx_element_buffer));
  404. return STATUS_OK;
  405. }
  406. return STATUS_ERR_INVALID_ARG;
  407. }
  408. enum status_code can_get_rx_fifo_1_element(
  409. struct can_module *const module_inst,
  410. struct can_rx_element_fifo_1 *rx_element, uint32_t index)
  411. {
  412. if (module_inst->hw == CAN0) {
  413. memcpy(rx_element, &can0_rx_fifo_1[index], sizeof(struct can_rx_element_buffer));
  414. return STATUS_OK;
  415. } else if (module_inst->hw == CAN1) {
  416. memcpy(rx_element, &can1_rx_fifo_1[index], sizeof(struct can_rx_element_buffer));
  417. return STATUS_OK;
  418. }
  419. return STATUS_ERR_INVALID_ARG;
  420. }
  421. enum status_code can_set_tx_buffer_element(
  422. struct can_module *const module_inst,
  423. struct can_tx_element *tx_element, uint32_t index)
  424. {
  425. uint32_t i;
  426. if (module_inst->hw == CAN0) {
  427. can0_tx_buffer[index].T0.reg = tx_element->T0.reg;
  428. can0_tx_buffer[index].T1.reg = tx_element->T1.reg;
  429. for (i = 0; i < CONF_CAN_ELEMENT_DATA_SIZE; i++) {
  430. can0_tx_buffer[index].data[i] = tx_element->data[i];
  431. }
  432. return STATUS_OK;
  433. } else if (module_inst->hw == CAN1) {
  434. can1_tx_buffer[index].T0.reg = tx_element->T0.reg;
  435. can1_tx_buffer[index].T1.reg = tx_element->T1.reg;
  436. for (i = 0; i < CONF_CAN_ELEMENT_DATA_SIZE; i++) {
  437. can1_tx_buffer[index].data[i] = tx_element->data[i];
  438. }
  439. return STATUS_OK;
  440. }
  441. return STATUS_ERR_INVALID_ARG;
  442. }
  443. enum status_code can_get_tx_event_fifo_element(
  444. struct can_module *const module_inst,
  445. struct can_tx_event_element *tx_event_element, uint32_t index)
  446. {
  447. if (module_inst->hw == CAN0) {
  448. tx_event_element->E0.reg = can0_tx_event_fifo[index].E0.reg;
  449. tx_event_element->E1.reg = can0_tx_event_fifo[index].E1.reg;
  450. return STATUS_OK;
  451. } else if (module_inst->hw == CAN1) {
  452. tx_event_element->E0.reg = can1_tx_event_fifo[index].E0.reg;
  453. tx_event_element->E1.reg = can1_tx_event_fifo[index].E1.reg;
  454. return STATUS_OK;
  455. }
  456. return STATUS_ERR_INVALID_ARG;
  457. }