1 /******************************************************************************
2 *
3 * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. (now owned by
4 * Analog Devices, Inc.),
5 * Copyright (C) 2023-2024 Analog Devices, Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 ******************************************************************************/
20
21 #include "can_reva.h"
22
23 /*********** Macros ***********/
24 #define MAJOR_VERSION_SHIFT 8
25 #define MAJOR_VERSION_CMSIS 2
26 #define MINOR_VERSION_CMSIS 8
27 #define MAJOR_VERSION_MSDK 1
28 #define MINOR_VERSION_MSDK 0
29
30 // Prefix these with MXC_CAN_ and put in can.h?
31 #define SINGLE_FILT_STD_ID_RTR_SHIFT (4U)
32 #define SINGLE_FILT_STD_ID_SHIFT (5U)
33 #define SINGLE_FILT_STD_ID_MASK (0x7FFU)
34 #define SINGLE_FILT_STD_ID(id) ((SINGLE_FILT_STD_ID_MASK & (id)) << SINGLE_FILT_STD_ID_SHIFT)
35 #define SINGLE_FILT_EXT_ID_RTR_SHIFT (2U)
36 #define SINGLE_FILT_EXT_ID_SHIFT (3U)
37 #define SINGLE_FILT_EXT_ID_MASK (0x1FFFFFFFU)
38 #define SINGLE_FILT_EXT_ID(id) ((SINGLE_FILT_EXT_ID_MASK & (id)) << SINGLE_FILT_EXT_ID_SHIFT)
39
40 #define DUAL_FILT_STD_ID_RTR_SHIFT (4U)
41 #define DUAL_FILT_STD_ID_SHIFT (5U)
42 #define DUAL_FILT_STD_ID_MASK (0x7FFU)
43 #define DUAL_FILT_STD_ID(id) ((DUAL_FILT_STD_ID_MASK & (id)) << DUAL_FILT_STD_ID_SHIFT)
44 #define DUAL_FILT_EXT_ID_SHIFT (13U)
45 #define DUAL_FILT_EXT_ID_MASK (0x1FFFE000U)
46 #define DUAL_FILT_EXT_ID(id) ((DUAL_FILT_EXT_ID_MASK & (id)) >> DUAL_FILT_EXT_ID_SHIFT);
47
48 #define HALFWORD_BYTESWAP(half_wd) ((half_wd & 0xFF00) >> 8) | ((half_wd & 0xFF) << 8)
49 #define WORD_BYTESWAP(wd) \
50 ((wd & 0xFF000000) >> 24) | ((wd & 0xFF0000) >> 8) | ((wd & 0xFF00) << 8) | ((wd & 0xFF) << 24)
51
52 /*********** Global Variables ***********/
53 mxc_can_object_event_cb_t obj_evt_cb[MXC_CAN_INSTANCES] = { NULL };
54 mxc_can_unit_event_cb_t unit_evt_cb[MXC_CAN_INSTANCES] = { NULL };
55
56 static uint32_t filt_in_use[MXC_CAN_INSTANCES] = { 0 };
57 static mxc_can_obj_cfg_t obj_state[MXC_CAN_INSTANCES] = { MXC_CAN_OBJ_CFG_INACTIVE };
58
59 static mxc_can_req_t *rx_req[MXC_CAN_INSTANCES];
60 static uint32_t rx_lock[MXC_CAN_INSTANCES] = { 0 };
61 static uint32_t tx_lock[MXC_CAN_INSTANCES] = { 0 };
62
63 static uint32_t dma_rx0[18] = { 0 };
64 static uint32_t dma_rx1[18] = { 0 };
65 static uint32_t rx_dma_lock[MXC_CAN_INSTANCES] = { 0 };
66
67 /*********** Functions ***********/
getNumBytes(uint32_t dlc,uint32_t fdf,uint32_t rtr)68 static int getNumBytes(uint32_t dlc, uint32_t fdf, uint32_t rtr)
69 {
70 int num_bytes = 0;
71 if (rtr) {
72 return 0;
73 } else if (dlc > 8 && fdf) {
74 // CAN FD message with more than 8 bytes of data
75 switch (dlc & 0xF) {
76 case 9:
77 case 10:
78 case 11:
79 case 12:
80 num_bytes = 8 + (dlc & 0x7) * 4;
81 break;
82 case 13:
83 num_bytes = 32;
84 break;
85 case 14:
86 num_bytes = 48;
87 break;
88 case 15:
89 num_bytes = 64;
90 break;
91 }
92 } else if (dlc > 8 && !fdf) {
93 // Normal CAN message with DLC greater than maximum number of data bytes, set to maximum
94 num_bytes = 8;
95 } else {
96 // Normal CAN or CAN FD message with less than or equal to 8 bytes
97 num_bytes = dlc;
98 }
99
100 return num_bytes;
101 }
102
103 /**********************************************************************************************************************************************************************/
MXC_CAN_RevA_GetVersion(void)104 mxc_can_drv_version_t MXC_CAN_RevA_GetVersion(void)
105 {
106 mxc_can_drv_version_t version;
107 version.api = (MAJOR_VERSION_CMSIS << MAJOR_VERSION_SHIFT) | MINOR_VERSION_CMSIS;
108 version.drv = (MAJOR_VERSION_MSDK << MAJOR_VERSION_SHIFT) | MINOR_VERSION_MSDK;
109 return version;
110 }
111
112 /**********************************************************************************************************************************************************************/
MXC_CAN_RevA_GetCapabilities(void)113 mxc_can_capabilities_t MXC_CAN_RevA_GetCapabilities(void)
114 {
115 mxc_can_capabilities_t capabilities;
116 capabilities.num_objects = MXC_CAN_INSTANCES;
117 capabilities.reentrant_operation = 1;
118 capabilities.fd_mode = 1;
119 capabilities.restricted_mode = 1;
120 capabilities.monitor_mode = 1;
121 capabilities.internal_loopback = 1;
122 capabilities.external_loopback = 0;
123 capabilities.rsv = 0;
124 return capabilities;
125 }
126
127 /**********************************************************************************************************************************************************************/
MXC_CAN_RevA_Init(mxc_can_reva_regs_t * can,mxc_can_unit_event_cb_t unit_cb,mxc_can_object_event_cb_t obj_cb)128 int MXC_CAN_RevA_Init(mxc_can_reva_regs_t *can, mxc_can_unit_event_cb_t unit_cb,
129 mxc_can_object_event_cb_t obj_cb)
130 {
131 int can_idx;
132
133 can_idx = MXC_CAN_GET_IDX((mxc_can_regs_t *)can);
134 MXC_ASSERT(can_idx >= 0);
135
136 obj_evt_cb[can_idx] = obj_cb; // Set callback function pointers
137 unit_evt_cb[can_idx] = unit_cb;
138
139 MXC_FreeLock(&tx_lock[can_idx]); // Free CAN resources
140 MXC_FreeLock(&rx_lock[can_idx]);
141 MXC_FreeLock(&rx_dma_lock[can_idx]);
142
143 return E_NO_ERROR;
144 }
145
146 /**********************************************************************************************************************************************************************/
MXC_CAN_RevA_UnInit(mxc_can_reva_regs_t * can)147 int MXC_CAN_RevA_UnInit(mxc_can_reva_regs_t *can)
148 {
149 int can_idx;
150
151 can_idx = MXC_CAN_GET_IDX((mxc_can_regs_t *)can);
152 MXC_ASSERT(can_idx >= 0);
153
154 obj_evt_cb[can_idx] = NULL; // Clear callback function pointers
155 unit_evt_cb[can_idx] = NULL;
156
157 MXC_FreeLock(&tx_lock[can_idx]); // Free CAN resources
158 MXC_FreeLock(&rx_lock[can_idx]);
159 MXC_FreeLock(&rx_dma_lock[can_idx]);
160
161 return E_NO_ERROR;
162 }
163
164 /**********************************************************************************************************************************************************************/
MXC_CAN_RevA_PowerControl(mxc_can_reva_regs_t * can,mxc_can_pwr_ctrl_t pwr)165 int MXC_CAN_RevA_PowerControl(mxc_can_reva_regs_t *can, mxc_can_pwr_ctrl_t pwr)
166 {
167 int can_idx;
168
169 can_idx = MXC_CAN_GET_IDX((mxc_can_regs_t *)can);
170 MXC_ASSERT(can_idx >= 0);
171
172 if (pwr == MXC_CAN_PWR_CTRL_SLEEP) {
173 // CAN periph able to go into sleep mode?
174 if (can->stat & MXC_F_CAN_REVA_STAT_TX || can->intfl || can->eintfl || !can->wupclkdiv) {
175 return E_BAD_STATE;
176 }
177
178 MXC_CAN_SetMode(can_idx, MXC_CAN_MODE_NORMAL);
179 can->mode |= MXC_F_CAN_REVA_MODE_SLP; // Enable CAN sleep mode
180 while (!(can->mode & MXC_F_CAN_REVA_MODE_SLP)) {}
181
182 // wait for any pending transactions to finish
183 MXC_CAN_SignalUnitEvent(can_idx, MXC_CAN_UNIT_EVT_INACTIVE);
184 } else if (pwr == MXC_CAN_PWR_CTRL_FULL) {
185 can->mode &= ~MXC_F_CAN_REVA_MODE_SLP; // Disable CAN sleep mode
186 MXC_CAN_SignalUnitEvent(can_idx, MXC_CAN_UNIT_EVT_ACTIVE);
187 }
188
189 return E_NO_ERROR;
190 }
191
192 /**********************************************************************************************************************************************************************/
MXC_CAN_RevA_EnableInt(mxc_can_reva_regs_t * can,uint8_t en,uint8_t ext_en)193 int MXC_CAN_RevA_EnableInt(mxc_can_reva_regs_t *can, uint8_t en, uint8_t ext_en)
194 {
195 // Enable interrupts in INTFL register
196 can->inten |= en;
197 // Enable interrupts in extended INTFL register
198 can->einten |= (ext_en & (MXC_F_CAN_REVA_EINTEN_RX_TO | MXC_F_CAN_REVA_EINTEN_RX_THD));
199
200 return E_NO_ERROR;
201 }
202
203 /**********************************************************************************************************************************************************************/
MXC_CAN_RevA_DisableInt(mxc_can_reva_regs_t * can,uint8_t dis,uint8_t ext_dis)204 int MXC_CAN_RevA_DisableInt(mxc_can_reva_regs_t *can, uint8_t dis, uint8_t ext_dis)
205 {
206 // Disable interrupts in INTFL register
207 can->inten &= ~dis;
208 // Disable interrupts in extended INTFL register
209 can->einten &= ~(ext_dis & (MXC_F_CAN_REVA_EINTEN_RX_TO | MXC_F_CAN_REVA_EINTEN_RX_THD));
210
211 return E_NO_ERROR;
212 }
213
214 /**********************************************************************************************************************************************************************/
MXC_CAN_RevA_GetFlags(mxc_can_reva_regs_t * can,uint8_t * flags,uint8_t * ext_flags)215 int MXC_CAN_RevA_GetFlags(mxc_can_reva_regs_t *can, uint8_t *flags, uint8_t *ext_flags)
216 {
217 *flags = can->intfl; // Get flags in INTFL register
218 *ext_flags = can->eintfl; // Get flags in extended INTFL register
219
220 return E_NO_ERROR;
221 }
222
223 /**********************************************************************************************************************************************************************/
MXC_CAN_RevA_ClearFlags(mxc_can_reva_regs_t * can,uint8_t flags,uint8_t ext_flags)224 int MXC_CAN_RevA_ClearFlags(mxc_can_reva_regs_t *can, uint8_t flags, uint8_t ext_flags)
225 {
226 // Clear flags in INTFL register
227 can->intfl = flags;
228 // Clear flags in Extended INTFL register
229 can->eintfl = (ext_flags & (MXC_F_CAN_REVA_EINTFL_RX_TO | MXC_F_CAN_REVA_EINTFL_RX_THD));
230
231 return E_NO_ERROR;
232 }
233
234 /**********************************************************************************************************************************************************************/
MXC_CAN_RevA_GetBitRate(mxc_can_reva_regs_t * can,mxc_can_bitrate_sel_t sel,int can_clk)235 int MXC_CAN_RevA_GetBitRate(mxc_can_reva_regs_t *can, mxc_can_bitrate_sel_t sel, int can_clk)
236 {
237 int num_tq = 1;
238 int prescaler;
239
240 // Get prescaler and total number of time quata
241 switch (sel) {
242 case MXC_CAN_BITRATE_SEL_NOMINAL:
243 prescaler = ((can->nbt & MXC_F_CAN_REVA_NBT_NBRP) >> MXC_F_CAN_REVA_NBT_NBRP_POS) + 1;
244 num_tq += ((can->nbt & MXC_F_CAN_REVA_NBT_NSEG1) >> MXC_F_CAN_REVA_NBT_NSEG1_POS) + 1;
245 num_tq += ((can->nbt & MXC_F_CAN_REVA_NBT_NSEG2) >> MXC_F_CAN_REVA_NBT_NSEG2_POS) + 1;
246 break;
247 case MXC_CAN_BITRATE_SEL_FD_DATA:
248 prescaler =
249 ((can->dbt_sspp & MXC_F_CAN_REVA_DBT_SSPP_DBRP) >> MXC_F_CAN_REVA_DBT_SSPP_DBRP_POS) +
250 1;
251 num_tq +=
252 ((can->dbt_sspp & MXC_F_CAN_REVA_DBT_SSPP_DSEG1) >> MXC_F_CAN_REVA_DBT_SSPP_DSEG1_POS) +
253 1;
254 num_tq +=
255 ((can->dbt_sspp & MXC_F_CAN_REVA_DBT_SSPP_DSEG2) >> MXC_F_CAN_REVA_DBT_SSPP_DSEG2_POS) +
256 1;
257 break;
258 default:
259 return E_BAD_PARAM;
260 }
261
262 return (can_clk / prescaler) /
263 num_tq; // bitrate = (src_clk_freq / prescaler) / total_num_time_quanta
264 }
265
266 /**********************************************************************************************************************************************************************/
MXC_CAN_RevA_SetBitRate(mxc_can_reva_regs_t * can,int can_clk,mxc_can_bitrate_sel_t sel,uint32_t bitrate,uint8_t seg1,uint8_t seg2,uint8_t sjw)267 int MXC_CAN_RevA_SetBitRate(mxc_can_reva_regs_t *can, int can_clk, mxc_can_bitrate_sel_t sel,
268 uint32_t bitrate, uint8_t seg1, uint8_t seg2, uint8_t sjw)
269 {
270 uint32_t num_tq = 1;
271 uint32_t prescaler = 1;
272 int rv = E_NO_ERROR;
273
274 can->mode |= MXC_F_CAN_REVA_MODE_RST;
275 switch (sel) {
276 case MXC_CAN_BITRATE_SEL_NOMINAL:
277 // Check that desired time quatum in each segment doesn't exceed the maximum
278 if (seg1 > MXC_CAN_NOMINAL_MAX_SEG1TQ || seg2 > MXC_CAN_NOMINAL_MAX_SEG2TQ ||
279 sjw > MXC_CAN_NOMINAL_MAX_SJWTQ) {
280 rv = E_BAD_PARAM;
281 break;
282 }
283
284 num_tq += seg1 + seg2;
285 prescaler = can_clk / (bitrate * num_tq);
286
287 // Check that prescaler doesn't exceed maximum value
288 if (prescaler > MXC_CAN_NOMINAL_MAX_PRESCALER) {
289 rv = E_INVALID;
290 break;
291 }
292
293 // Set prescaler and number of time quata in each segment
294 MXC_SETFIELD(can->nbt, MXC_F_CAN_REVA_NBT_NBRP,
295 ((prescaler - 1) << MXC_F_CAN_REVA_NBT_NBRP_POS));
296 MXC_SETFIELD(can->nbt, MXC_F_CAN_REVA_NBT_NSEG1,
297 ((seg1 - 1) << MXC_F_CAN_REVA_NBT_NSEG1_POS));
298 MXC_SETFIELD(can->nbt, MXC_F_CAN_REVA_NBT_NSEG2,
299 ((seg2 - 1) << MXC_F_CAN_REVA_NBT_NSEG2_POS));
300 MXC_SETFIELD(can->nbt, MXC_F_CAN_REVA_NBT_NSJW, ((sjw - 1) << MXC_F_CAN_REVA_NBT_NSJW_POS));
301 break;
302 case MXC_CAN_BITRATE_SEL_FD_DATA:
303 if (seg1 > MXC_CAN_FD_DATA_MAX_SEG1TQ || seg2 > MXC_CAN_FD_DATA_MAX_SEG2TQ ||
304 sjw > MXC_CAN_FD_DATA_MAX_SJWTQ) {
305 rv = E_BAD_PARAM;
306 break;
307 }
308
309 num_tq += seg1 + seg2;
310 prescaler = can_clk / (bitrate * num_tq);
311 if (prescaler > MXC_CAN_FD_DATA_MAX_PRESCALER) {
312 rv = E_INVALID;
313 break;
314 }
315
316 MXC_SETFIELD(can->dbt_sspp, MXC_F_CAN_REVA_DBT_SSPP_DBRP,
317 ((prescaler - 1) << MXC_F_CAN_REVA_DBT_SSPP_DBRP_POS));
318 MXC_SETFIELD(can->dbt_sspp, MXC_F_CAN_REVA_DBT_SSPP_DSEG1,
319 ((seg1 - 1) << MXC_F_CAN_REVA_DBT_SSPP_DSEG1_POS));
320 MXC_SETFIELD(can->dbt_sspp, MXC_F_CAN_REVA_DBT_SSPP_DSEG2,
321 ((seg2 - 1) << MXC_F_CAN_REVA_DBT_SSPP_DSEG2_POS));
322 MXC_SETFIELD(can->dbt_sspp, MXC_F_CAN_REVA_DBT_SSPP_DSJW,
323 ((sjw - 1) << MXC_F_CAN_REVA_DBT_SSPP_DSJW_POS));
324 break;
325 default:
326 rv = E_BAD_PARAM;
327 }
328 can->mode &= ~MXC_F_CAN_REVA_MODE_RST;
329
330 return rv;
331 }
332
333 /**********************************************************************************************************************************************************************/
MXC_CAN_RevA_SetMode(mxc_can_reva_regs_t * can,mxc_can_mode_t mode)334 int MXC_CAN_RevA_SetMode(mxc_can_reva_regs_t *can, mxc_can_mode_t mode)
335 {
336 // Ensure valid mode
337 if (mode > MXC_CAN_MODE_LOOPBACK_W_TXD) {
338 return E_BAD_PARAM;
339 }
340
341 can->mode |= MXC_F_CAN_REVA_MODE_RST;
342
343 // Clear any existing operating modes
344 can->fdctrl &= ~MXC_F_CAN_REVA_FDCTRL_REOM;
345 can->mode &= ~MXC_F_CAN_REVA_MODE_LOM;
346 can->test &= ~(MXC_F_CAN_REVA_TEST_LBEN | MXC_F_CAN_REVA_TEST_TXC);
347
348 switch (mode) {
349 case MXC_CAN_MODE_INITIALIZATION: // Reset mode
350 return E_NO_ERROR;
351 case MXC_CAN_MODE_NORMAL: // Normal mode
352 break;
353 case MXC_CAN_MODE_RESTRICTED: // Restriced mode
354 can->fdctrl |= MXC_F_CAN_REVA_FDCTRL_REOM;
355 break;
356 case MXC_CAN_MODE_MONITOR: // Listen-only mode
357 can->mode |= MXC_F_CAN_REVA_MODE_LOM;
358 break;
359 case MXC_CAN_MODE_LOOPBACK: // Internal loopback mode
360 can->test |= MXC_F_CAN_REVA_TEST_LBEN;
361 break;
362 case MXC_CAN_MODE_LOOPBACK_W_TXD: // Internal loopback mode with TX pin disconnected
363 can->test |= MXC_F_CAN_REVA_TEST_LBEN | MXC_F_CAN_REVA_TEST_TXC;
364 break;
365 default:
366 can->mode &= ~MXC_F_CAN_REVA_MODE_RST;
367 return E_BAD_PARAM;
368 }
369
370 can->mode &= ~MXC_F_CAN_REVA_MODE_RST;
371
372 return E_NO_ERROR;
373 }
374
375 /**********************************************************************************************************************************************************************/
MXC_CAN_RevA_ObjectGetCapabilities(mxc_can_reva_regs_t * can)376 mxc_can_obj_capabilities_t MXC_CAN_RevA_ObjectGetCapabilities(mxc_can_reva_regs_t *can)
377 {
378 mxc_can_obj_capabilities_t obj_cap;
379 obj_cap.tx = 1; // Transmitting messages supported
380 obj_cap.rx = 1; // Receiveiving messages supported
381 obj_cap.rx_rtr_tx_data = 0; // Auto TX on RTR reception not supported
382 obj_cap.tx_rtr_rx_data = 1; // Auto RX on RTR transmit supported
383 obj_cap.multiple_filters = 1; // Multiple filters supported
384 obj_cap.exact_filtering = 1; // Exact filtering supported
385 obj_cap.mask_filtering = 1; // Mask filtering supported
386 obj_cap.range_filtering = 0; // Range filtering supported
387 obj_cap.message_depth = 1; // MXC_CAN TX FIFO depth is 1
388 obj_cap.reserved = 0;
389 return obj_cap;
390 }
391
392 /**********************************************************************************************************************************************************************/
MXC_CAN_RevA_ObjectSetFilter(mxc_can_reva_regs_t * can,mxc_can_filt_cfg_t cfg,uint32_t id,uint32_t arg)393 int MXC_CAN_RevA_ObjectSetFilter(mxc_can_reva_regs_t *can, mxc_can_filt_cfg_t cfg, uint32_t id,
394 uint32_t arg)
395 {
396 uint32_t op_type = (cfg & MXC_CAN_FILT_OP_TYPE_MASK);
397 uint32_t filt_sel = (cfg & MXC_CAN_FILT_SEL_MASK);
398 uint32_t dual_filt_sel;
399 int can_idx;
400
401 can_idx = MXC_CAN_GET_IDX((mxc_can_regs_t *)can);
402 MXC_ASSERT(can_idx >= 0);
403
404 if (filt_sel ==
405 MXC_CAN_FILT_CFG_DUAL_GEN) { // If using middleware dual filter select, figure out which filter to set
406 if (op_type == MXC_CAN_FILT_CFG_EXACT_ADD || op_type == MXC_CAN_FILT_CFG_MASK_ADD) {
407 filt_sel = ((filt_in_use[can_idx] + 1) * 2) << MXC_CAN_FILT_SEL_SHIFT;
408 } else if (op_type == MXC_CAN_FILT_CFG_EXACT_DEL || op_type == MXC_CAN_FILT_CFG_MASK_DEL) {
409 filt_sel = (filt_in_use[can_idx] * 2) << MXC_CAN_FILT_SEL_SHIFT;
410 }
411 }
412
413 can->mode |= MXC_F_CAN_REVA_MODE_RST;
414
415 if (op_type == MXC_CAN_FILT_CFG_EXACT_ADD || op_type == MXC_CAN_FILT_CFG_MASK_ADD) {
416 // Create filter selected
417 if (filt_in_use[can_idx] >= MXC_CAN_FILT_PER_OBJ) {
418 // Filter not available --> return error
419 can->mode &= ~MXC_F_CAN_REVA_MODE_RST;
420 return E_NONE_AVAIL;
421 }
422
423 if (op_type == MXC_CAN_FILT_CFG_EXACT_ADD) {
424 arg = 0xFFFFFFFF;
425 }
426
427 dual_filt_sel = 1;
428 switch (filt_sel) {
429 case MXC_CAN_FILT_CFG_DUAL1_STD_ID: // Set dual filter with standard, 11-bit ID length
430 dual_filt_sel = 0; //Fall through
431 case MXC_CAN_FILT_CFG_DUAL2_STD_ID:
432 can->mode &= ~MXC_F_CAN_REVA_MODE_AFM;
433 id = DUAL_FILT_STD_ID(id);
434 can->acr16[dual_filt_sel] = HALFWORD_BYTESWAP(id);
435 arg = DUAL_FILT_STD_ID((~arg)) | (1 << DUAL_FILT_STD_ID_RTR_SHIFT);
436 can->amr16[dual_filt_sel] = HALFWORD_BYTESWAP(arg);
437 can->amr8[1] |= 0x0F; // Set data byte filtering to don't care
438 can->amr8[3] |= 0x0F;
439 break;
440
441 case MXC_CAN_FILT_CFG_DUAL1_EXT_ID: // Set dual filter with extended, 29-bit ID
442 dual_filt_sel = 0; //Fall through
443 case MXC_CAN_FILT_CFG_DUAL2_EXT_ID:
444 can->mode &= ~MXC_F_CAN_REVA_MODE_AFM;
445 id = DUAL_FILT_EXT_ID(id);
446 can->acr16[dual_filt_sel] = HALFWORD_BYTESWAP(id);
447 arg = DUAL_FILT_EXT_ID((~arg));
448 can->amr16[dual_filt_sel] = HALFWORD_BYTESWAP(arg);
449 break;
450
451 case MXC_CAN_FILT_CFG_SINGLE_STD_ID: // Set single filter wit standard, 11-bit ID
452 can->mode |= MXC_F_CAN_REVA_MODE_AFM;
453 id = SINGLE_FILT_STD_ID(id);
454 can->acr16[0] = HALFWORD_BYTESWAP(id);
455 arg = SINGLE_FILT_STD_ID((~arg)) | (1 << SINGLE_FILT_STD_ID_RTR_SHIFT);
456 can->amr16[0] = HALFWORD_BYTESWAP(arg);
457 can->acr16[1] = 0xFFFF; // Set data byte filtering to don't care.
458 can->amr16[1] = 0xFFFF;
459 break;
460
461 case MXC_CAN_FILT_CFG_SINGLE_EXT_ID: // Set single filter for extended, 29-bit ID
462 can->mode |= MXC_F_CAN_REVA_MODE_AFM;
463 id = SINGLE_FILT_EXT_ID(id);
464 can->acr32 = WORD_BYTESWAP(id);
465 arg = SINGLE_FILT_EXT_ID(~arg) | (1 << SINGLE_FILT_EXT_ID_RTR_SHIFT);
466 can->amr32 = WORD_BYTESWAP(arg);
467 break;
468
469 default:
470 can->mode &= ~MXC_F_CAN_REVA_MODE_RST;
471 return E_BAD_PARAM;
472 }
473
474 filt_in_use[can_idx]++;
475 } else if (op_type == MXC_CAN_FILT_CFG_EXACT_DEL || op_type == MXC_CAN_FILT_CFG_MASK_DEL) {
476 // Deleting filter
477 if (filt_in_use[can_idx] == 0) {
478 can->mode &= ~MXC_F_CAN_REVA_MODE_RST;
479 return E_NONE_AVAIL;
480 }
481
482 switch (filt_sel) {
483 case MXC_CAN_FILT_CFG_DUAL1_STD_ID: // Clear dual filter 1
484 case MXC_CAN_FILT_CFG_DUAL1_EXT_ID:
485 can->mode &= ~MXC_F_CAN_REVA_MODE_AFM;
486 can->acr16[0] = 0;
487 can->amr16[0] = 0;
488 break;
489 case MXC_CAN_FILT_CFG_DUAL2_STD_ID: // Clear dual filter 2
490 case MXC_CAN_FILT_CFG_DUAL2_EXT_ID:
491 can->mode &= ~MXC_F_CAN_REVA_MODE_AFM;
492 can->acr16[1] = 0;
493 can->amr16[1] = 0;
494 break;
495 case MXC_CAN_FILT_CFG_SINGLE_STD_ID: // Clear single filter
496 case MXC_CAN_FILT_CFG_SINGLE_EXT_ID:
497 can->mode |= MXC_F_CAN_REVA_MODE_AFM;
498 can->acr32 = 0;
499 can->amr32 = 0;
500 break;
501 default:
502 can->mode &= ~MXC_F_CAN_REVA_MODE_RST;
503 return E_BAD_PARAM;
504 }
505
506 filt_in_use[can_idx]--;
507 } else {
508 can->mode &= ~MXC_F_CAN_REVA_MODE_RST;
509 return E_BAD_PARAM;
510 }
511 can->mode &= ~MXC_F_CAN_REVA_MODE_RST;
512
513 return E_NO_ERROR;
514 }
515
516 /**********************************************************************************************************************************************************************/
MXC_CAN_RevA_ObjectConfigure(mxc_can_reva_regs_t * can,mxc_can_obj_cfg_t cfg)517 int MXC_CAN_RevA_ObjectConfigure(mxc_can_reva_regs_t *can, mxc_can_obj_cfg_t cfg)
518 {
519 int can_idx;
520
521 can_idx = MXC_CAN_GET_IDX((mxc_can_regs_t *)can);
522 MXC_ASSERT(can_idx >= 0);
523
524 switch (cfg) {
525 case MXC_CAN_OBJ_CFG_INACTIVE: // Configure object as inactive
526 MXC_CAN_PowerControl(can_idx, MXC_CAN_PWR_CTRL_SLEEP);
527 break;
528 case MXC_CAN_OBJ_CFG_TXRX: // Configure object to transmit and/or receive data
529 case MXC_CAN_OBJ_CFG_RSV:
530 case MXC_CAN_OBJ_CFG_TX_RTR_RX_DATA: // Configure object to receive message after sending RTR frames (RX always enabled when CAN is on, as long as MSG ID is accepted)
531 MXC_CAN_PowerControl(can_idx, MXC_CAN_PWR_CTRL_FULL);
532 can->mode |= MXC_F_CAN_REVA_MODE_RST;
533 can->mode |= MXC_F_CAN_REVA_MODE_DMA;
534 can->fdctrl |= MXC_F_CAN_REVA_FDCTRL_EXTBT;
535 can->mode &= ~MXC_F_CAN_REVA_MODE_RST;
536 break;
537 case MXC_CAN_OBJ_CFG_RX_RTR_TX_DATA: // Configure object to auto TX on RTR frames not allowed
538 default:
539 return E_BAD_PARAM;
540 }
541 obj_state[can_idx] = cfg;
542 return E_NO_ERROR;
543 }
544
545 /**********************************************************************************************************************************************************************/
MXC_CAN_RevA_WriteTXFIFO(mxc_can_reva_regs_t * can,mxc_can_msg_info_t * info,const uint8_t * data,uint8_t size)546 int MXC_CAN_RevA_WriteTXFIFO(mxc_can_reva_regs_t *can, mxc_can_msg_info_t *info,
547 const uint8_t *data, uint8_t size)
548 {
549 uint8_t txbuf_idx = 0;
550 uint32_t txbuf_data = 0;
551 int num_bytes = getNumBytes(info->dlc, info->fdf, info->rtr);
552
553 if (info == NULL) { // Check if desired format is valid
554 return E_NULL_PTR;
555 } else if (info->rtr && (info->fdf || info->brs || info->esi)) {
556 return E_INVALID;
557 } else if (!info->fdf && (info->brs || info->esi)) {
558 return E_INVALID;
559 } else if (can->txscnt < (num_bytes + 5)) {
560 return E_BAD_STATE;
561 }
562
563 txbuf_data = MXC_CAN_BUF_CFG_RTR(info->rtr) | MXC_CAN_BUF_CFG_FDF(info->fdf) |
564 MXC_CAN_BUF_CFG_BRS(info->brs) | MXC_CAN_BUF_CFG_DLC(info->dlc);
565 if (info->msg_id & MXC_CAN_MSG_INFO_IDE_BIT) { // Configure message for extended ID
566 txbuf_data |= MXC_CAN_BUF_CFG_IDE;
567 txbuf_data |= MXC_CAN_BUF_CFG_EXT_ID_TX1(info->msg_id) << 8;
568 txbuf_data |= MXC_CAN_BUF_CFG_EXT_ID_TX2(info->msg_id) << 16;
569 txbuf_data |= MXC_CAN_BUF_CFG_EXT_ID_TX3(info->msg_id) << 24;
570 can->txfifo32 = txbuf_data;
571
572 txbuf_data = MXC_CAN_BUF_CFG_EXT_ID_TX4(info->msg_id) |
573 MXC_CAN_BUF_CFG_EXT_ID_ESI(info->esi);
574 txbuf_idx = 1;
575 } else { // Configure message for standard ID
576 txbuf_data |= MXC_CAN_BUF_CFG_STD_ID_TX1(info->msg_id) << 8;
577 txbuf_data |=
578 (MXC_CAN_BUF_CFG_STD_ID_TX2(info->msg_id) | MXC_CAN_BUF_CFG_STD_ID_ESI(info->esi))
579 << 16;
580 txbuf_idx = 3;
581 }
582
583 if (info->rtr || data == NULL) { // No data bytes in RTR frames
584 can->txfifo32 = txbuf_data;
585
586 return E_NO_ERROR;
587 }
588
589 for (int i = 0; i < num_bytes; i++) { // Add data bytes to FIFO
590 if (txbuf_idx == 0) {
591 can->txfifo32 = txbuf_data;
592 txbuf_data = 0;
593 }
594
595 if (i < size) {
596 // We have exceeded the size of the data buffer passed in, write zeros to remaining bytes
597 txbuf_data |= data[i] << (txbuf_idx << 3);
598 }
599
600 txbuf_idx = (txbuf_idx + 1) & 0x3;
601 }
602 can->txfifo32 = txbuf_data;
603
604 return num_bytes;
605 }
606
607 /**********************************************************************************************************************************************************************/
MXC_CAN_RevA_ReadRXFIFO(mxc_can_reva_regs_t * can,mxc_can_msg_info_t * info,uint8_t * data,uint8_t size,bool dma)608 int MXC_CAN_RevA_ReadRXFIFO(mxc_can_reva_regs_t *can, mxc_can_msg_info_t *info, uint8_t *data,
609 uint8_t size, bool dma)
610 {
611 uint8_t rxfifo_idx = 0, rxbuf_parse = 0, dma_buf_idx = 0;
612 uint32_t rx_data = 0;
613 uint32_t *dma_buf = dma_rx0;
614 int can_idx;
615
616 can_idx = MXC_CAN_GET_IDX((mxc_can_regs_t *)can);
617 MXC_ASSERT(can_idx >= 0);
618
619 if (info == NULL || data == NULL) {
620 return E_NULL_PTR;
621 } else if (!dma && can->rxdcnt == 0) {
622 // RX FIFO empty for non-DMA transaction
623 return E_BAD_STATE;
624 }
625
626 // Select appropriate DMA buffer to read from if DMA read
627 if (dma && can_idx == 0) {
628 dma_buf = dma_rx0;
629 } else if (dma && can_idx == 1) {
630 dma_buf = dma_rx1;
631 }
632
633 if (dma) { // Get next word in RX FIFO
634 rx_data = dma_buf[dma_buf_idx++];
635 } else {
636 rx_data = can->rxfifo32;
637 }
638 rxbuf_parse = rx_data & 0xFF;
639 info->dlc = rxbuf_parse & MXC_CAN_BUF_CFG_DLC(0xF);
640 info->brs = !!(rxbuf_parse & MXC_CAN_BUF_CFG_BRS(1));
641 info->fdf = !!(rxbuf_parse & MXC_CAN_BUF_CFG_FDF(1));
642
643 if (rx_data & MXC_CAN_BUF_CFG_IDE) {
644 // Parse Message Header for extended ID format
645 info->msg_id = MXC_CAN_MSG_INFO_IDE_BIT;
646
647 rxbuf_parse = (rx_data & 0xFF00) >> 8;
648 info->msg_id |= MXC_CAN_BUF_CFG_EXT_ID_RX1(rxbuf_parse);
649
650 rxbuf_parse = (rx_data & 0xFF0000) >> 16;
651 info->msg_id |= MXC_CAN_BUF_CFG_EXT_ID_RX2(rxbuf_parse);
652
653 rxbuf_parse = (rx_data & 0xFF000000) >> 24;
654 info->msg_id |= MXC_CAN_BUF_CFG_EXT_ID_RX3(rxbuf_parse);
655
656 if (dma) {
657 rx_data = dma_buf[dma_buf_idx++];
658 } else {
659 rx_data = can->rxfifo32;
660 }
661 rxbuf_parse = rx_data & 0xFF;
662 info->msg_id |= MXC_CAN_BUF_CFG_EXT_ID_RX4(rxbuf_parse);
663 info->rtr = !!(rxbuf_parse & MXC_CAN_BUF_CFG_EXT_ID_RTR(1));
664 info->esi = !!(rxbuf_parse & MXC_CAN_BUF_CFG_EXT_ID_ESI(1));
665 rxfifo_idx = 1;
666 } else {
667 // Parse Header for Standard ID Format
668 info->rtr = !!(rxbuf_parse & MXC_CAN_BUF_CFG_STD_ID_RTR(1));
669
670 rxbuf_parse = (rx_data & 0xFF00) >> 8;
671 info->msg_id = MXC_CAN_BUF_CFG_STD_ID_RX1(rxbuf_parse);
672
673 rxbuf_parse = (rx_data & 0xFF0000) >> 16;
674 info->msg_id |= MXC_CAN_BUF_CFG_STD_ID_RX2(rxbuf_parse);
675 info->esi = !!(rxbuf_parse & MXC_CAN_BUF_CFG_STD_ID_ESI(1));
676 rxfifo_idx = 3;
677 }
678
679 if (info->rtr) { // No data bytes in RTR frames
680 return E_NO_ERROR;
681 }
682
683 // Get number of data bytes to read
684 int num_bytes = getNumBytes(info->dlc, info->fdf, info->rtr);
685 int rv = num_bytes;
686
687 // Read data bytes
688 for (int i = 0; i < num_bytes; i++) {
689 if (rxfifo_idx == 0) {
690 if (dma) {
691 rx_data = dma_buf[dma_buf_idx++];
692 } else {
693 rx_data = can->rxfifo32;
694 }
695 }
696
697 if (i < size) {
698 // Mask off next byte in word
699 data[i] = (rx_data & (0xFF << (rxfifo_idx << 3))) >> (rxfifo_idx << 3);
700 } else {
701 rv = size;
702 }
703
704 rxfifo_idx = (rxfifo_idx + 1) & 0x3;
705 }
706
707 return rv;
708 }
709
710 /**********************************************************************************************************************************************************************/
MXC_CAN_RevA_MessageSend(mxc_can_reva_regs_t * can,mxc_can_req_t * req)711 int MXC_CAN_RevA_MessageSend(mxc_can_reva_regs_t *can, mxc_can_req_t *req)
712 {
713 int err;
714 uint8_t flags, ext_flags;
715 int can_idx;
716
717 can_idx = MXC_CAN_GET_IDX((mxc_can_regs_t *)can);
718 MXC_ASSERT(can_idx >= 0);
719
720 if (req == NULL) {
721 return E_NULL_PTR;
722 } else if (MXC_GetLock(&tx_lock[can_idx], 1)) {
723 // TX lock already taken
724 return E_BAD_STATE;
725 }
726
727 // Format and write message to FIFO
728 if ((err = MXC_CAN_WriteTXFIFO(can_idx, req->msg_info, req->data, req->data_sz)) < E_NO_ERROR) {
729 return err;
730 }
731
732 MXC_CAN_ClearFlags(
733 can_idx,
734 (MXC_F_CAN_REVA_INTFL_ERWARN | MXC_F_CAN_REVA_INTFL_ERPSV | MXC_F_CAN_REVA_INTFL_TX), 0);
735 can->cmd = MXC_F_CAN_REVA_CMD_TXREQ; // Send TX request
736
737 // Wait for TX to complete
738 do {
739 // Check for errors
740 if ((err = MXC_CAN_RevA_Handler(can, &flags, &ext_flags)) != E_NO_ERROR) {
741 MXC_FreeLock(&tx_lock[can_idx]);
742 return err;
743 }
744 } while (!(flags & MXC_F_CAN_REVA_INTFL_TX));
745
746 if (flags & MXC_F_CAN_REVA_INTFL_TX) { // If TX complete call callback function
747 MXC_CAN_SignalObjectEvent(can_idx, MXC_CAN_OBJ_EVT_TX_COMPLETE);
748 }
749
750 MXC_FreeLock(&tx_lock[can_idx]); // Free TX lock
751
752 return E_NO_ERROR;
753 }
754
755 /**********************************************************************************************************************************************************************/
MXC_CAN_RevA_MessageSendAsync(mxc_can_reva_regs_t * can,mxc_can_req_t * req)756 int MXC_CAN_RevA_MessageSendAsync(mxc_can_reva_regs_t *can, mxc_can_req_t *req)
757 {
758 int err;
759 int can_idx;
760
761 can_idx = MXC_CAN_GET_IDX((mxc_can_regs_t *)can);
762 MXC_ASSERT(can_idx >= 0);
763
764 if (req == NULL) {
765 return E_NULL_PTR;
766 } else if (MXC_GetLock(&tx_lock[can_idx], 1)) {
767 // TX lock already acquired
768 return E_BAD_STATE;
769 }
770
771 // Format and write message to TX FIFO
772 if ((err = MXC_CAN_WriteTXFIFO(can_idx, req->msg_info, req->data, req->data_sz)) < E_NO_ERROR) {
773 MXC_FreeLock(&tx_lock[can_idx]);
774 return err;
775 }
776
777 MXC_CAN_ClearFlags(
778 can_idx,
779 (MXC_F_CAN_REVA_INTFL_ERWARN | MXC_F_CAN_REVA_INTFL_ERPSV | MXC_F_CAN_REVA_INTFL_TX), 0);
780 MXC_CAN_EnableInt(
781 can_idx,
782 (MXC_F_CAN_REVA_INTEN_ERWARN | MXC_F_CAN_REVA_INTEN_ERPSV | MXC_F_CAN_REVA_INTEN_TX), 0);
783
784 can->cmd = MXC_F_CAN_REVA_CMD_TXREQ; // Assert TX request
785
786 return err;
787 }
788
789 /**********************************************************************************************************************************************************************/
MXC_CAN_RevA_MessageSendDMA(mxc_can_reva_regs_t * can,mxc_can_req_t * req)790 int MXC_CAN_RevA_MessageSendDMA(mxc_can_reva_regs_t *can, mxc_can_req_t *req)
791 {
792 // No performance improvements using DMA transmit since CAN FIFO can only hold one message to transmit at a time
793 return MXC_CAN_RevA_MessageSendAsync(can, req);
794 }
795
796 /**********************************************************************************************************************************************************************/
MXC_CAN_RevA_MessageRead(mxc_can_reva_regs_t * can,mxc_can_req_t * req)797 int MXC_CAN_RevA_MessageRead(mxc_can_reva_regs_t *can, mxc_can_req_t *req)
798 {
799 int err = 0;
800 uint8_t flags = 0, ext_flags = 0;
801 int can_idx;
802
803 can_idx = MXC_CAN_GET_IDX((mxc_can_regs_t *)can);
804 MXC_ASSERT(can_idx >= 0);
805
806 // Check for bad parameters
807 if (req == NULL) {
808 return E_NULL_PTR;
809 } else if (MXC_GetLock(&rx_lock[can_idx], 1)) {
810 // RX lock already taken
811 return E_BUSY;
812 }
813
814 // Wait to receive message
815 do {
816 // Check for errors
817 if ((err = MXC_CAN_RevA_Handler(can, &flags, &ext_flags)) != E_NO_ERROR) {
818 break;
819 }
820 } while (!(flags & (MXC_F_CAN_REVA_INTFL_RX | MXC_F_CAN_REVA_INTFL_DOR)));
821
822 if (flags & MXC_F_CAN_REVA_INTFL_DOR) {
823 MXC_CAN_SignalObjectEvent(can_idx, MXC_CAN_OBJ_EVT_RX_OVERRUN);
824 }
825
826 if (flags & MXC_F_CAN_REVA_INTFL_RX) {
827 // Read data from FIFO
828 if ((err = MXC_CAN_ReadRXFIFO(can_idx, req->msg_info, req->data, req->data_sz)) <
829 E_NO_ERROR) {
830 MXC_FreeLock(&rx_lock[can_idx]);
831 return err;
832 }
833 MXC_CAN_SignalObjectEvent(can_idx, MXC_CAN_OBJ_EVT_RX);
834 }
835
836 MXC_FreeLock(&rx_lock[can_idx]); // Free RX lock
837
838 return err;
839 }
840
841 /**********************************************************************************************************************************************************************/
MXC_CAN_RevA_MessageReadAsync(mxc_can_reva_regs_t * can,mxc_can_req_t * req)842 int MXC_CAN_RevA_MessageReadAsync(mxc_can_reva_regs_t *can, mxc_can_req_t *req)
843 {
844 int can_idx;
845
846 can_idx = MXC_CAN_GET_IDX((mxc_can_regs_t *)can);
847 MXC_ASSERT(can_idx >= 0);
848
849 if (req == NULL) {
850 return E_NULL_PTR;
851 } else if (MXC_GetLock(&rx_lock[can_idx], 1)) {
852 // RX lock already taken
853 return E_BUSY;
854 }
855
856 rx_req[can_idx] = req; // Store message read request
857
858 MXC_CAN_ClearFlags(can_idx,
859 (MXC_F_CAN_REVA_INTFL_ERWARN | MXC_F_CAN_REVA_INTFL_ERPSV |
860 MXC_F_CAN_REVA_INTFL_RX | MXC_F_CAN_REVA_INTFL_DOR),
861 0);
862 MXC_CAN_EnableInt(can_idx,
863 (MXC_F_CAN_REVA_INTEN_ERWARN | MXC_F_CAN_REVA_INTEN_ERPSV |
864 MXC_F_CAN_REVA_INTEN_RX | MXC_F_CAN_REVA_INTEN_DOR),
865 0);
866
867 return E_NO_ERROR;
868 }
869
870 /**********************************************************************************************************************************************************************/
MXC_CAN_RevA_MessageReadDMA(mxc_can_reva_regs_t * can,mxc_can_req_t * req,mxc_dma_reqsel_t reqsel,void (* dma_cb)(int,int))871 int MXC_CAN_RevA_MessageReadDMA(mxc_can_reva_regs_t *can, mxc_can_req_t *req,
872 mxc_dma_reqsel_t reqsel, void (*dma_cb)(int, int))
873 {
874 int ch;
875 mxc_dma_config_t config;
876 mxc_dma_srcdst_t srcdst;
877 int can_idx;
878
879 can_idx = MXC_CAN_GET_IDX((mxc_can_regs_t *)can);
880 MXC_ASSERT(can_idx >= 0);
881
882 if (req == NULL) {
883 return E_NULL_PTR;
884 } else if (MXC_GetLock(&rx_lock[can_idx], 1)) {
885 // RX lock already taken
886 return E_BUSY;
887 } else if (MXC_GetLock(&rx_dma_lock[can_idx], 1)) {
888 // DMA lock already taken
889 MXC_FreeLock(&rx_lock[can_idx]);
890 return E_BUSY;
891 }
892
893 rx_req[can_idx] = req; // Save RX request
894
895 if ((ch = MXC_DMA_AcquireChannel()) < E_NO_ERROR) { // Acquire DMA Channel
896 return ch;
897 }
898
899 if (dma_cb != NULL) { // Set DMA callback
900 MXC_DMA_SetCallback(ch, dma_cb);
901 }
902
903 if (can_idx == 0) { // Configure DMA Channel
904 srcdst.dest = dma_rx0;
905 } else if (can_idx == 1) {
906 srcdst.dest = dma_rx1;
907 }
908
909 config.reqsel = reqsel;
910 config.ch = ch;
911 config.srcwd = MXC_DMA_WIDTH_WORD;
912 config.dstwd = MXC_DMA_WIDTH_WORD;
913 config.srcinc_en = 0;
914 config.dstinc_en = 1;
915
916 srcdst.ch = ch;
917 srcdst.len = getNumBytes((req->msg_info)->dlc, (req->msg_info)->fdf, (req->msg_info)->rtr) +
918 MXC_CAN_DMA_LEN((req->msg_info)->msg_id);
919 if (srcdst.len & 0x3) {
920 srcdst.len += (4 - (srcdst.len & 0x3));
921 }
922 MXC_DMA_ConfigChannel(config, srcdst);
923
924 mxc_dma_adv_config_t advConfig;
925 advConfig.ch = ch;
926 advConfig.prio = MXC_DMA_PRIO_HIGH;
927 advConfig.reqwait_en = 0;
928 advConfig.tosel = MXC_DMA_TIMEOUT_4_CLK; // 0
929 advConfig.pssel = MXC_DMA_PRESCALE_DISABLE; // 0
930 advConfig.burst_size = 4;
931 MXC_DMA_AdvConfigChannel(advConfig);
932
933 // Set RX DMA trigger to one word
934 MXC_SETFIELD(can->mode, MXC_F_CAN_REVA_MODE_RXTRIG, MXC_S_CAN_REVA_MODE_RXTRIG_1W);
935
936 MXC_DMA_EnableInt(ch); // Enable DMA
937 MXC_DMA_SetChannelInterruptEn(ch, 0, 1);
938 MXC_DMA_Start(ch);
939
940 return E_NO_ERROR;
941 }
942
943 /**********************************************************************************************************************************************************************/
MXC_CAN_RevA_Handler(mxc_can_reva_regs_t * can,uint8_t * intfl,uint8_t * eintfl)944 int MXC_CAN_RevA_Handler(mxc_can_reva_regs_t *can, uint8_t *intfl, uint8_t *eintfl)
945 {
946 uint8_t flg, ext_flg;
947 int can_idx;
948
949 can_idx = MXC_CAN_GET_IDX((mxc_can_regs_t *)can);
950 MXC_ASSERT(can_idx >= 0);
951
952 MXC_CAN_GetFlags(can_idx, &flg, &ext_flg); // Get and clear flags
953 MXC_CAN_ClearFlags(can_idx, flg, ext_flg);
954
955 if (intfl != NULL && eintfl != NULL) { // Return flags if able to
956 *intfl = flg;
957 *eintfl = ext_flg;
958 }
959
960 if (flg & MXC_F_CAN_REVA_INTFL_ERWARN) {
961 if (can->stat & MXC_F_CAN_REVA_STAT_BUS_OFF) {
962 // Bus entered bus off state
963 MXC_CAN_SignalUnitEvent(can_idx, MXC_CAN_UNIT_EVT_BUS_OFF);
964
965 if (tx_lock[can_idx]) {
966 MXC_FreeLock(&tx_lock[can_idx]);
967 }
968 return E_COMM_ERR;
969 } else if (can->stat & MXC_F_CAN_REVA_STAT_ERR) {
970 // Bus entered err warning state (> 127 errs)
971 MXC_CAN_SignalUnitEvent(can_idx, MXC_CAN_UNIT_EVT_WARNING);
972 }
973 }
974
975 if (flg & MXC_F_CAN_REVA_INTFL_ERPSV) {
976 if (can->txerr > MXC_CAN_ERRPSV_THRESH || can->rxerr > MXC_CAN_ERRPSV_THRESH) {
977 // Bus entered error passive state
978 MXC_CAN_SignalUnitEvent(can_idx, MXC_CAN_UNIT_EVT_PASSIVE);
979 } else {
980 // Bus exited from error passive state
981 MXC_CAN_SignalUnitEvent(can_idx, MXC_CAN_UNIT_EVT_ACTIVE);
982 }
983 }
984
985 if ((flg & MXC_F_CAN_REVA_INTFL_TX) && (can->inten & MXC_F_CAN_REVA_INTEN_TX)) {
986 // TX completed
987 MXC_FreeLock(&tx_lock[can_idx]);
988 MXC_CAN_SignalObjectEvent(can_idx, MXC_CAN_OBJ_EVT_TX_COMPLETE);
989 }
990
991 if ((flg & MXC_F_CAN_REVA_INTFL_RX) &&
992 ((can->inten & MXC_F_CAN_REVA_INTEN_RX) || rx_dma_lock[can_idx])) {
993 // RX completed
994 mxc_can_req_t *msg_req = rx_req[can_idx];
995
996 if (rx_dma_lock[can_idx]) {
997 // Read from DMA RX Buffers for transactions
998 MXC_CAN_RevA_ReadRXFIFO(can, msg_req->msg_info, msg_req->data, msg_req->data_sz, true);
999 MXC_FreeLock(&rx_dma_lock[can_idx]);
1000 } else {
1001 // Read CAN message
1002 MXC_CAN_RevA_ReadRXFIFO(can, msg_req->msg_info, msg_req->data, msg_req->data_sz, false);
1003 }
1004 MXC_FreeLock(&rx_lock[can_idx]);
1005
1006 MXC_CAN_SignalObjectEvent(can_idx, MXC_CAN_OBJ_EVT_RX);
1007 }
1008
1009 // Data overrun
1010 if (flg & MXC_F_CAN_REVA_INTFL_DOR) {
1011 MXC_CAN_SignalObjectEvent(can_idx, MXC_CAN_OBJ_EVT_RX_OVERRUN);
1012 }
1013
1014 return E_NO_ERROR;
1015 }
1016
1017 /**********************************************************************************************************************************************************************/
MXC_CAN_RevA_Control(mxc_can_reva_regs_t * can,mxc_can_ctrl_t ctrl,uint32_t ctrl_arg)1018 int MXC_CAN_RevA_Control(mxc_can_reva_regs_t *can, mxc_can_ctrl_t ctrl, uint32_t ctrl_arg)
1019 {
1020 if (ctrl == MXC_CAN_CTRL_SET_FD_MODE) { // Set FD Mode
1021 can->mode |= MXC_F_CAN_REVA_MODE_RST;
1022 can->fdctrl |= MXC_F_CAN_REVA_FDCTRL_FDEN | MXC_F_CAN_REVA_FDCTRL_BRSEN |
1023 MXC_F_CAN_REVA_FDCTRL_ISO;
1024 can->mode &= ~MXC_F_CAN_REVA_MODE_RST;
1025 } else if (ctrl == MXC_CAN_CTRL_ABORT_TX) { // Abort transmission
1026 can->cmd = MXC_F_CAN_REVA_CMD_ABORT;
1027 } else if (ctrl == MXC_CAN_CTRL_RETRANSMISSION) { // Enable/disable auto retransmission
1028 can->mode |= MXC_F_CAN_REVA_MODE_RST;
1029 if (ctrl_arg) { // Enable
1030 can->fdctrl &= ~MXC_F_CAN_REVA_FDCTRL_DAR;
1031 } else { // Disable
1032 can->fdctrl |= MXC_F_CAN_REVA_FDCTRL_DAR;
1033 }
1034 can->mode &= ~MXC_F_CAN_REVA_MODE_RST;
1035 } else if (ctrl == MXC_CAN_CTRL_TRANSCEIVER_DLY) { // Set transceiver delay
1036 can->mode |= MXC_F_CAN_REVA_MODE_RST;
1037 can->txdecmp = MXC_F_CAN_REVA_TXDECMP_TDCEN | (ctrl_arg & MXC_F_CAN_REVA_TXDECMP_TDCO);
1038 can->mode &= ~MXC_F_CAN_REVA_MODE_RST;
1039 } else {
1040 return E_BAD_PARAM;
1041 }
1042
1043 return E_NO_ERROR;
1044 }
1045
1046 /**********************************************************************************************************************************************************************/
MXC_CAN_RevA_SetWakeupTimer(mxc_can_reva_regs_t * can,uint8_t prescaler,uint16_t wup_filter_tm,uint32_t wup_expire_tm)1047 int MXC_CAN_RevA_SetWakeupTimer(mxc_can_reva_regs_t *can, uint8_t prescaler, uint16_t wup_filter_tm,
1048 uint32_t wup_expire_tm)
1049 {
1050 can->mode |= MXC_F_CAN_REVA_MODE_RST;
1051
1052 // Set wake up values: clock divider, filter time, expire time
1053 MXC_SETFIELD(can->wupclkdiv, MXC_F_CAN_REVA_WUPCLKDIV_WUPDIV, prescaler);
1054 MXC_SETFIELD(can->wupft, MXC_F_CAN_REVA_WUPFT_WUPFT, wup_filter_tm);
1055 MXC_SETFIELD(can->wupet, MXC_F_CAN_REVA_WUPET_WUPET, wup_expire_tm);
1056 can->mode &= ~MXC_F_CAN_REVA_MODE_RST;
1057
1058 return E_NO_ERROR;
1059 }
1060
1061 /**********************************************************************************************************************************************************************/
MXC_CAN_RevA_GetStatus(mxc_can_reva_regs_t * can)1062 mxc_can_stat_t MXC_CAN_RevA_GetStatus(mxc_can_reva_regs_t *can)
1063 {
1064 mxc_can_stat_t stat;
1065 int can_idx;
1066
1067 can_idx = MXC_CAN_GET_IDX((mxc_can_regs_t *)can);
1068 MXC_ASSERT(can_idx >= 0);
1069
1070 // Get unit state
1071 if (obj_state[can_idx] == MXC_CAN_OBJ_CFG_INACTIVE) {
1072 stat.unit_state = MXC_CAN_UNIT_STATE_INACTIVE;
1073 } else if (can->stat & MXC_F_CAN_REVA_STAT_BUS_OFF) {
1074 stat.unit_state = MXC_CAN_UNIT_STATE_BUS_OFF;
1075 } else if ((can->mode & MXC_F_CAN_REVA_MODE_LOM) ||
1076 (can->fdctrl & MXC_F_CAN_REVA_FDCTRL_REOM)) {
1077 stat.unit_state = MXC_CAN_UNIT_STATE_PASSIVE;
1078 } else {
1079 stat.unit_state = MXC_CAN_UNIT_STATE_ACTIVE;
1080 }
1081
1082 stat.tx_err_cnt = can->txerr; // Get TX error count
1083 stat.rx_err_cnt = can->rxerr; // Get RX error count
1084
1085 stat.last_error_code = can->ecc; // Get last error code
1086 switch (stat.last_error_code & MXC_CAN_ECC_ERROR_CODE_MASK) {
1087 case MXC_F_CAN_REVA_ECC_BER:
1088 stat.last_error_code = MXC_CAN_LEC_BIT_ERR;
1089 break;
1090 case MXC_F_CAN_REVA_ECC_STFER:
1091 stat.last_error_code = MXC_CAN_LEC_STUFF_ERR;
1092 break;
1093 case MXC_F_CAN_REVA_ECC_CRCER:
1094 stat.last_error_code = MXC_CAN_LEC_CRC_ERR;
1095 break;
1096 case MXC_F_CAN_REVA_ECC_FRMER:
1097 stat.last_error_code = MXC_CAN_LEC_FORM_ERR;
1098 break;
1099 case MXC_F_CAN_REVA_ECC_ACKER:
1100 stat.last_error_code = MXC_CAN_LEC_ACK_ERR;
1101 break;
1102 default:
1103 stat.last_error_code = MXC_CAN_LEC_NO_ERR;
1104 }
1105
1106 return stat;
1107 }
1108
1109 /**********************************************************************************************************************************************************************/
MXC_CAN_RevA_SignalUnitEvent(uint32_t can_idx,mxc_can_unit_evt_t event)1110 void MXC_CAN_RevA_SignalUnitEvent(uint32_t can_idx, mxc_can_unit_evt_t event)
1111 {
1112 mxc_can_object_event_cb_t evt_cb = unit_evt_cb[can_idx];
1113 if (evt_cb != NULL) {
1114 evt_cb(can_idx, event); // Call unit event callback
1115 }
1116 }
1117
1118 /**********************************************************************************************************************************************************************/
MXC_CAN_RevA_SignalObjectEvent(uint32_t can_idx,mxc_can_obj_evt_t event)1119 void MXC_CAN_RevA_SignalObjectEvent(uint32_t can_idx, mxc_can_obj_evt_t event)
1120 {
1121 mxc_can_object_event_cb_t evt_cb = obj_evt_cb[can_idx];
1122 if (evt_cb != NULL) {
1123 evt_cb(can_idx, event); // Call object event callback
1124 }
1125 }
1126