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