1 /*
2 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
3 *
4 * SPDX-License-Identifier: Apache-2.0.
5 *
6 * @Date: 2021-04-29 10:21:53
7 * @LastEditTime: 2021-05-25 16:41:38
8 * @Description: Description of file
9 * @Modify History:
10 * * * Ver Who Date Changes
11 * * ----- ------ -------- --------------------------------------
12 */
13
14 #include "ft_can.h"
15 #include "ft_can_hw.h"
16 #include "ft_assert.h"
17 #include "ft_debug.h"
18 #include "string.h"
19
20 #define FT_CAN_DEBUG_TAG "FT_CAN"
21
22 #define FT_CAN_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FT_CAN_DEBUG_TAG, format, ##__VA_ARGS__)
23 #define FT_CAN_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(FT_CAN_DEBUG_TAG, format, ##__VA_ARGS__)
24 #define FT_CAN_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FT_CAN_DEBUG_TAG, format, ##__VA_ARGS__)
25
26 ft_error_t
FCan_CfgInitialize(FCan_t * Can_p,FCan_Config_t * Config_p)27 FCan_CfgInitialize(FCan_t *Can_p, FCan_Config_t *Config_p)
28 {
29 Ft_assertNonvoid(Can_p != NULL);
30 Ft_assertNonvoid(Config_p != NULL);
31 Can_p->Config = *Config_p;
32 Can_p->IsReady = FT_COMPONENT_IS_READLY;
33 FCan_Reset(Can_p);
34 return FCAN_SUCCESS;
35 }
36
FCan_GetErrorCnt(FCan_t * Can_p,u32 * TxErr,u32 * RxErr)37 void FCan_GetErrorCnt(FCan_t *Can_p, u32 *TxErr, u32 *RxErr)
38 {
39 FCan_Config_t *Config_p;
40 Ft_assertVoid(Can_p != NULL);
41 Ft_assertVoid(Can_p->IsReady == FT_COMPONENT_IS_READLY);
42 Config_p = &Can_p->Config;
43
44 *RxErr = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_ERR_CNT_OFFSET) & FCAN_ERR_CNT_RFN_MASK;
45 *TxErr = (FCan_ReadReg(Config_p->CanBaseAddress, FCAN_ERR_CNT_OFFSET) & FCAN_ERR_CNT_TFN_MASK) >> FCAN_ERR_CNT_TFN_SHIFT;
46 }
47
FCan_RecvByIrq(FCan_t * Can_p,struct FCan_Frame * Frame_p,u32 FrameNumber)48 u32 FCan_RecvByIrq(FCan_t *Can_p, struct FCan_Frame *Frame_p, u32 FrameNumber)
49 {
50 u32 FifoCnt = 0;
51 FCan_Config_t *Config_p;
52 u32 CanId;
53 u32 Dlc;
54 u32 CanFrameIndex = 0;
55 u32 RxValue;
56 Ft_assertZeroNum(Can_p != NULL);
57 Ft_assertZeroNum(Can_p->IsReady == FT_COMPONENT_IS_READLY);
58 Config_p = &Can_p->Config;
59
60 FifoCnt = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_FIFO_CNT_OFFSET) & 0x3f;
61
62 if (0 == FifoCnt)
63 {
64 return 0;
65 }
66
67 FrameNumber = (FrameNumber > FifoCnt) ? FifoCnt : FrameNumber;
68
69 while (FrameNumber)
70 {
71 /* Read a frame from Phytium CAN */
72 CanId = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_RX_FIFO_OFFSET);
73 /* if CanId is big-endian ,use swap change to little-endian */
74 CanId = FT_SWAP32(CanId);
75 /* Identifier extension */
76 if (CanId & FCAN_IDR_IDE_MASK)
77 {
78 Dlc = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_RX_FIFO_OFFSET);
79 Dlc = FT_SWAP32(Dlc);
80 Dlc = ((Dlc & FCAN_IDR_EDLC_MASK) >> FCAN_IDR_EDLC_SHIFT);
81
82 Frame_p[CanFrameIndex].CanId = (CanId & FCAN_IDR_ID1_MASK) >> 3;
83 Frame_p[CanFrameIndex].CanId |= (CanId & FCAN_IDR_ID2_MASK) >> FCAN_IDR_ID2_SHIFT;
84 Frame_p[CanFrameIndex].CanId |= CAN_EFF_FLAG;
85
86 if (CanId & FCAN_IDR_RTR_MASK)
87 {
88 Frame_p[CanFrameIndex].CanId |= CAN_RTR_FLAG;
89 }
90 }
91 else
92 {
93 Dlc = ((CanId & FCAN_IDR_DLC_MASK) >> FCAN_IDR_SDLC_SHIFT);
94
95 /* The received frame is a standard format frame */
96 Frame_p[CanFrameIndex].CanId = (CanId & FCAN_IDR_ID1_MASK) >> FCAN_IDR_ID1_SHIFT;
97 if (CanId & FCAN_IDR_SRR_MASK)
98 {
99 Frame_p[CanFrameIndex].CanId |= CAN_RTR_FLAG;
100 }
101 }
102
103 Frame_p[CanFrameIndex].CanDlc = (Dlc > sizeof(Frame_p[CanFrameIndex].data)) ? sizeof(Frame_p[CanFrameIndex].data) : Dlc;
104
105 if (!(Frame_p[CanFrameIndex].CanId & CAN_RTR_FLAG))
106 {
107 if (Frame_p[CanFrameIndex].CanDlc > 0)
108 {
109 RxValue = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_RX_FIFO_OFFSET);
110 memcpy(Frame_p[CanFrameIndex].data, &RxValue, sizeof(RxValue));
111 }
112
113 if (Frame_p[CanFrameIndex].CanDlc > 4)
114 {
115 RxValue = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_RX_FIFO_OFFSET);
116 memcpy(&Frame_p[CanFrameIndex].data[4], &RxValue, sizeof(RxValue));
117 }
118 }
119 FrameNumber--;
120 CanFrameIndex++;
121 }
122
123 return (CanFrameIndex + 1);
124 }
125
FCan_SendFifo(FCan_t * Can_p,struct FCan_Frame * Frame_p)126 static void FCan_SendFifo(FCan_t *Can_p, struct FCan_Frame *Frame_p)
127 {
128 u32 Id, Dlc;
129 FCan_Config_t *Config_p;
130 u32 SendBuffer = 0;
131 Ft_assertVoid(Can_p != NULL);
132 Ft_assertVoid(Can_p->IsReady == FT_COMPONENT_IS_READLY);
133 Config_p = &Can_p->Config;
134 if (Frame_p->CanId & CAN_EFF_FLAG)
135 {
136 /* Extended CAN ID format */
137 Id = ((Frame_p->CanId & CAN_EFF_MASK) << FCAN_IDR_ID2_SHIFT) &
138 FCAN_IDR_ID2_MASK;
139 Id |= (((Frame_p->CanId & CAN_EFF_MASK) >>
140 (CAN_EFF_ID_BITS - CAN_SFF_ID_BITS))
141 << FCAN_IDR_ID1_SHIFT) &
142 FCAN_IDR_ID1_MASK;
143
144 Id |= FCAN_IDR_IDE_MASK | FCAN_IDR_SRR_MASK;
145 if (Frame_p->CanId & CAN_RTR_FLAG)
146 {
147 Id |= FCAN_IDR_RTR_MASK;
148 }
149
150 Dlc = Frame_p->CanDlc << FCAN_IDR_EDLC_SHIFT;
151
152 FCan_WriteReg(Config_p->CanBaseAddress, FCAN_TX_FIFO_OFFSET, FT_SWAP32(Id));
153 FCan_WriteReg(Config_p->CanBaseAddress, FCAN_TX_FIFO_OFFSET, FT_SWAP32(Dlc));
154 }
155 else
156 {
157 /* Standard CAN ID format */
158 Id = ((Frame_p->CanId & CAN_SFF_MASK) << FCAN_IDR_ID1_SHIFT) &
159 FCAN_IDR_ID1_MASK;
160 if (Frame_p->CanId & CAN_RTR_FLAG)
161 Id |= FCAN_IDR_SRR_MASK;
162
163 Dlc = ((Frame_p->CanDlc << FCAN_IDR_SDLC_SHIFT) | FCAN_IDR_PAD_MASK);
164 Id |= Dlc;
165 FCan_WriteReg(Config_p->CanBaseAddress, FCAN_TX_FIFO_OFFSET, FT_SWAP32(Id));
166 }
167
168 if (!(Frame_p->CanId & CAN_RTR_FLAG))
169 {
170 if (Frame_p->CanDlc > 0)
171 {
172 memcpy(&SendBuffer, Frame_p->data, 4);
173 FCan_WriteReg(Config_p->CanBaseAddress, FCAN_TX_FIFO_OFFSET, SendBuffer);
174 }
175
176 if (Frame_p->CanDlc > 4)
177 {
178 memcpy(&SendBuffer, &Frame_p->data[4], 4);
179 FCan_WriteReg(Config_p->CanBaseAddress, FCAN_TX_FIFO_OFFSET, SendBuffer);
180 }
181 }
182 }
183
FCan_SendByIrq(FCan_t * Can_p,struct FCan_Frame * Frame_p,u32 FrameNumber,void (* UserIrqWait)(void))184 u32 FCan_SendByIrq(FCan_t *Can_p,
185 struct FCan_Frame *Frame_p,
186 u32 FrameNumber, void (*UserIrqWait)(void))
187 {
188 FCan_Config_t *Config_p;
189 u32 FrameIndex = 0;
190 u32 NeedSendOnce;
191 u32 cnt = 0;
192 Ft_assertZeroNum(Can_p != NULL);
193 Ft_assertZeroNum(Can_p->IsReady == FT_COMPONENT_IS_READLY);
194 Config_p = &Can_p->Config;
195
196 if (NULL == Frame_p)
197 {
198 FT_CAN_DEBUG_E("Frame_p is NULL , %s: %d", __FILE__, __LINE__);
199 return 0;
200 }
201
202 if (0 == FrameNumber)
203 {
204 FT_CAN_DEBUG_E("FrameNumber is 0 , %s: %d", __FILE__, __LINE__);
205 return 0;
206 }
207
208 for (; 0 < FrameNumber;)
209 {
210 if (FrameNumber > Config_p->TxFifoDeepth)
211 {
212 NeedSendOnce = Config_p->TxFifoDeepth;
213 FrameNumber -= Config_p->TxFifoDeepth;
214 }
215 else
216 {
217 NeedSendOnce = FrameNumber;
218 FrameNumber = 0;
219 }
220 Ft_printf("shut down tranmission \r\n");
221 /*shut down tranmission*/
222 FCan_ClearBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
223 FCan_ClearBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_TXREQ_MASK);
224 FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
225 Ft_printf("NeedSendOnce %d \r\n", NeedSendOnce);
226 for (cnt = 0; cnt < NeedSendOnce; cnt++)
227 {
228 FCan_SendFifo(Can_p, &Frame_p[FrameIndex]);
229 FrameIndex++;
230 }
231 Can_p->TxFifoCnt = NeedSendOnce;
232
233 /* triggers tranmission */
234 FCan_ClearBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
235 FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_TXREQ_MASK);
236 FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_TXREQ_MASK | FCAN_CTRL_XFER_MASK);
237
238 if (UserIrqWait)
239 {
240 UserIrqWait();
241 }
242 else
243 {
244 while (0 != Can_p->TxFifoCnt)
245 {
246 };
247 }
248 }
249
250 return FrameIndex + 1;
251 }
252
FCan_SetTiming(FCan_t * Can_p,struct FCan_Bittiming * Bittiming_p)253 ft_error_t FCan_SetTiming(FCan_t *Can_p,
254 struct FCan_Bittiming *Bittiming_p)
255 {
256 u32 Btr = 0;
257 FCan_Config_t *Config_p;
258 u32 IsConfigMode;
259 Ft_assertNonvoid(Can_p != NULL);
260 Ft_assertNonvoid(Can_p->IsReady == FT_COMPONENT_IS_READLY);
261 Config_p = &Can_p->Config;
262
263 Ft_assertNonvoid(Bittiming_p->brp != 0);
264 Ft_assertNonvoid(Bittiming_p->prop_seg != 0);
265 Ft_assertNonvoid(Bittiming_p->phase_seg1 != 0);
266 Ft_assertNonvoid(Bittiming_p->phase_seg2 != 0);
267
268 /* Setting Baud Rate prescalar value in BRPR Register */
269 Btr = (Bittiming_p->brp - 1) << 16;
270 Btr |= (Bittiming_p->prop_seg - 1) << 2;
271 Btr |= (Bittiming_p->phase_seg1 - 1) << 5;
272 Btr |= (Bittiming_p->phase_seg2 - 1) << 8;
273 Btr |= (Bittiming_p->sjw - 1);
274
275 IsConfigMode = (FCan_ReadReg(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET) & FCAN_CTRL_XFER_MASK);
276
277 if (IsConfigMode)
278 {
279 FCan_WriteReg(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
280 }
281
282 FCan_WriteReg(Config_p->CanBaseAddress, FCAN_DAT_RATE_CTRL_OFFSET, Btr);
283 FCan_WriteReg(Config_p->CanBaseAddress, FCAN_ARB_RATE_CTRL_OFFSET, Btr);
284
285 /*Enable Transfer*/
286 FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
287
288 return FCAN_SUCCESS;
289 }
290
FCan_Enable(FCan_t * Can_p)291 void FCan_Enable(FCan_t *Can_p)
292 {
293 FCan_Config_t *Config_p;
294 Ft_assertVoid(Can_p != NULL);
295 Ft_assertVoid(Can_p->IsReady == FT_COMPONENT_IS_READLY);
296 Config_p = &Can_p->Config;
297
298 FCan_WriteReg(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
299 }
300