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