1 /*
2  * Copyright (c) 2015-2020 Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Licensed under the Apache License, Version 2.0 (the License); you may
7  * not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #include "Driver_CAN.h"
20 
21 #define ARM_CAN_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1,0) // CAN driver version
22 
23 // Driver Version
24 static const ARM_DRIVER_VERSION can_driver_version = { ARM_CAN_API_VERSION, ARM_CAN_DRV_VERSION };
25 
26 // Driver Capabilities
27 static const ARM_CAN_CAPABILITIES can_driver_capabilities = {
28   32U,  // Number of CAN Objects available
29   0U,   // Does not support reentrant calls to ARM_CAN_MessageSend, ARM_CAN_MessageRead, ARM_CAN_ObjectConfigure and abort message sending used by ARM_CAN_Control.
30   0U,   // Does not support CAN with Flexible Data-rate mode (CAN_FD)
31   0U,   // Does not support restricted operation mode
32   0U,   // Does not support bus monitoring mode
33   0U,   // Does not support internal loopback mode
34   0U,   // Does not support external loopback mode
35   0U    // Reserved (must be zero)
36 };
37 
38 // Object Capabilities
39 static const ARM_CAN_OBJ_CAPABILITIES can_object_capabilities = {
40   1U,   // Object supports transmission
41   1U,   // Object supports reception
42   0U,   // Object does not support RTR reception and automatic Data transmission
43   0U,   // Object does not support RTR transmission and automatic Data reception
44   0U,   // Object does not allow assignment of multiple filters to it
45   0U,   // Object does not support exact identifier filtering
46   0U,   // Object does not support range identifier filtering
47   0U,   // Object does not support mask identifier filtering
48   0U,   // Object can not buffer messages
49   0U    // Reserved (must be zero)
50 };
51 
52 static uint8_t                     can_driver_powered     = 0U;
53 static uint8_t                     can_driver_initialized = 0U;
54 static ARM_CAN_SignalUnitEvent_t   CAN_SignalUnitEvent    = NULL;
55 static ARM_CAN_SignalObjectEvent_t CAN_SignalObjectEvent  = NULL;
56 
57 //
58 //   Functions
59 //
60 
ARM_CAN_GetVersion(void)61 static ARM_DRIVER_VERSION ARM_CAN_GetVersion (void) {
62   // Return driver version
63   return can_driver_version;
64 }
65 
ARM_CAN_GetCapabilities(void)66 static ARM_CAN_CAPABILITIES ARM_CAN_GetCapabilities (void) {
67   // Return driver capabilities
68   return can_driver_capabilities;
69 }
70 
ARM_CAN_Initialize(ARM_CAN_SignalUnitEvent_t cb_unit_event,ARM_CAN_SignalObjectEvent_t cb_object_event)71 static int32_t ARM_CAN_Initialize (ARM_CAN_SignalUnitEvent_t   cb_unit_event,
72                                    ARM_CAN_SignalObjectEvent_t cb_object_event) {
73 
74   if (can_driver_initialized != 0U) { return ARM_DRIVER_OK; }
75 
76   CAN_SignalUnitEvent   = cb_unit_event;
77   CAN_SignalObjectEvent = cb_object_event;
78 
79   // Add code for pin, memory, RTX objects initialization
80   // ..
81 
82   can_driver_initialized = 1U;
83 
84   return ARM_DRIVER_OK;
85 }
86 
ARM_CAN_Uninitialize(void)87 static int32_t ARM_CAN_Uninitialize (void) {
88 
89   // Add code for pin, memory, RTX objects de-initialization
90   // ..
91 
92   can_driver_initialized = 0U;
93 
94   return ARM_DRIVER_OK;
95 }
96 
ARM_CAN_PowerControl(ARM_POWER_STATE state)97 static int32_t ARM_CAN_PowerControl (ARM_POWER_STATE state) {
98   switch (state) {
99     case ARM_POWER_OFF:
100       can_driver_powered = 0U;
101       // Add code to disable interrupts and put peripheral into reset mode,
102       // and if possible disable clock
103       // ..
104 
105       break;
106 
107     case ARM_POWER_FULL:
108       if (can_driver_initialized == 0U) { return ARM_DRIVER_ERROR; }
109       if (can_driver_powered     != 0U) { return ARM_DRIVER_OK;    }
110 
111       // Add code to enable clocks, reset variables enable interrupts
112       // and put peripheral into operational
113       // ..
114 
115       can_driver_powered = 1U;
116       break;
117 
118     case ARM_POWER_LOW:
119       return ARM_DRIVER_ERROR_UNSUPPORTED;
120   }
121 
122   return ARM_DRIVER_OK;
123 }
124 
ARM_CAN_GetClock(void)125 static uint32_t ARM_CAN_GetClock (void) {
126 
127   // Add code to return peripheral clock frequency
128   // ..
129 }
130 
ARM_CAN_SetBitrate(ARM_CAN_BITRATE_SELECT select,uint32_t bitrate,uint32_t bit_segments)131 static int32_t ARM_CAN_SetBitrate (ARM_CAN_BITRATE_SELECT select, uint32_t bitrate, uint32_t bit_segments) {
132 
133   if (can_driver_powered == 0U) { return ARM_DRIVER_ERROR; }
134 
135   // Add code to setup peripheral parameters to generate specified bitrate
136   // with specified bit segments
137   // ..
138 
139   return ARM_DRIVER_OK;
140 }
141 
ARM_CAN_SetMode(ARM_CAN_MODE mode)142 static int32_t ARM_CAN_SetMode (ARM_CAN_MODE mode) {
143 
144   if (can_driver_powered == 0U) { return ARM_DRIVER_ERROR; }
145 
146   switch (mode) {
147     case ARM_CAN_MODE_INITIALIZATION:
148       // Add code to put peripheral into initialization mode
149       // ..
150       break;
151     case ARM_CAN_MODE_NORMAL:
152       // Add code to put peripheral into normal operation mode
153       // ..
154       break;
155     case ARM_CAN_MODE_RESTRICTED:
156       // Add code to put peripheral into restricted operation mode
157       // ..
158       break;
159     case ARM_CAN_MODE_MONITOR:
160       // Add code to put peripheral into bus monitoring mode
161       // ..
162       break;
163     case ARM_CAN_MODE_LOOPBACK_INTERNAL:
164       // Add code to put peripheral into internal loopback mode
165       // ..
166       break;
167     case ARM_CAN_MODE_LOOPBACK_EXTERNAL:
168       // Add code to put peripheral into external loopback mode
169       // ..
170       break;
171   }
172 
173   return ARM_DRIVER_OK;
174 }
175 
ARM_CAN_ObjectGetCapabilities(uint32_t obj_idx)176 static ARM_CAN_OBJ_CAPABILITIES ARM_CAN_ObjectGetCapabilities (uint32_t obj_idx) {
177   // Return object capabilities
178   return can_object_capabilities;
179 }
180 
ARM_CAN_ObjectSetFilter(uint32_t obj_idx,ARM_CAN_FILTER_OPERATION operation,uint32_t id,uint32_t arg)181 static int32_t ARM_CAN_ObjectSetFilter (uint32_t obj_idx, ARM_CAN_FILTER_OPERATION operation, uint32_t id, uint32_t arg) {
182 
183   if (can_driver_powered == 0U) { return ARM_DRIVER_ERROR; }
184 
185   switch (operation) {
186     case ARM_CAN_FILTER_ID_EXACT_ADD:
187       // Add code to setup peripheral to receive messages with specified exact ID
188       break;
189     case ARM_CAN_FILTER_ID_MASKABLE_ADD:
190       // Add code to setup peripheral to receive messages with specified maskable ID
191       break;
192     case ARM_CAN_FILTER_ID_RANGE_ADD:
193       // Add code to setup peripheral to receive messages within specified range of IDs
194       break;
195     case ARM_CAN_FILTER_ID_EXACT_REMOVE:
196       // Add code to remove specified exact ID from being received by peripheral
197       break;
198     case ARM_CAN_FILTER_ID_MASKABLE_REMOVE:
199       // Add code to remove specified maskable ID from being received by peripheral
200       break;
201     case ARM_CAN_FILTER_ID_RANGE_REMOVE:
202       // Add code to remove specified range of IDs from being received by peripheral
203       break;
204   }
205 
206   return ARM_DRIVER_OK;
207 }
208 
ARM_CAN_ObjectConfigure(uint32_t obj_idx,ARM_CAN_OBJ_CONFIG obj_cfg)209 static int32_t ARM_CAN_ObjectConfigure (uint32_t obj_idx, ARM_CAN_OBJ_CONFIG obj_cfg) {
210 
211   if (can_driver_powered == 0U) { return ARM_DRIVER_ERROR; }
212 
213   switch (obj_cfg) {
214     case ARM_CAN_OBJ_INACTIVE:
215       // Deactivate object
216       // ..
217       break;
218     case ARM_CAN_OBJ_RX_RTR_TX_DATA:
219       // Setup object to automatically return data when RTR with it's ID is received
220       // ..
221       break;
222     case ARM_CAN_OBJ_TX_RTR_RX_DATA:
223       // Setup object to send RTR and receive data response
224       // ..
225       break;
226     case ARM_CAN_OBJ_TX:
227       // Setup object to be used for sending messages
228       // ..
229       break;
230     case ARM_CAN_OBJ_RX:
231       // Setup object to be used for receiving messages
232       // ..
233       break;
234   }
235 
236   return ARM_DRIVER_OK;
237 }
238 
ARM_CAN_MessageSend(uint32_t obj_idx,ARM_CAN_MSG_INFO * msg_info,const uint8_t * data,uint8_t size)239 static int32_t ARM_CAN_MessageSend (uint32_t obj_idx, ARM_CAN_MSG_INFO *msg_info, const uint8_t *data, uint8_t size) {
240 
241   if (can_driver_powered == 0U) { return ARM_DRIVER_ERROR; }
242 
243   // Add code to send requested message
244   // ..
245 
246   return ((int32_t)size);
247 }
248 
ARM_CAN_MessageRead(uint32_t obj_idx,ARM_CAN_MSG_INFO * msg_info,uint8_t * data,uint8_t size)249 static int32_t ARM_CAN_MessageRead (uint32_t obj_idx, ARM_CAN_MSG_INFO *msg_info, uint8_t *data, uint8_t size) {
250 
251   if (can_driver_powered == 0U) { return ARM_DRIVER_ERROR;  }
252 
253   // Add code to read previously received message
254   // (reception was started when object was configured for reception)
255   // ..
256 
257   return ((int32_t)size);
258 }
259 
ARM_CAN_Control(uint32_t control,uint32_t arg)260 static int32_t ARM_CAN_Control (uint32_t control, uint32_t arg) {
261 
262   if (can_driver_powered == 0U) { return ARM_DRIVER_ERROR; }
263 
264   switch (control & ARM_CAN_CONTROL_Msk) {
265     case ARM_CAN_ABORT_MESSAGE_SEND:
266       // Add code to abort message pending to be sent
267       // ..
268       break;
269     case ARM_CAN_SET_FD_MODE:
270       // Add code to enable Flexible Data-rate mode
271       // ..
272       break;
273     case ARM_CAN_SET_TRANSCEIVER_DELAY:
274       // Add code to set transceiver delay
275       // ..
276       break;
277     default:
278       // Handle unknown control code
279       return ARM_DRIVER_ERROR_UNSUPPORTED;
280   }
281 
282   return ARM_DRIVER_OK;
283 }
284 
ARM_CAN_GetStatus(void)285 static ARM_CAN_STATUS ARM_CAN_GetStatus (void) {
286 
287   // Add code to return device bus and error status
288   // ..
289 }
290 
291 
292 // IRQ handlers
293 // Add interrupt routines to handle transmission, reception, error and status interrupts
294 // ..
295 
296 // CAN driver functions structure
297 
298 extern \
299 ARM_DRIVER_CAN Driver_CAN0;
300 ARM_DRIVER_CAN Driver_CAN0 = {
301   ARM_CAN_GetVersion,
302   ARM_CAN_GetCapabilities,
303   ARM_CAN_Initialize,
304   ARM_CAN_Uninitialize,
305   ARM_CAN_PowerControl,
306   ARM_CAN_GetClock,
307   ARM_CAN_SetBitrate,
308   ARM_CAN_SetMode,
309   ARM_CAN_ObjectGetCapabilities,
310   ARM_CAN_ObjectSetFilter,
311   ARM_CAN_ObjectConfigure,
312   ARM_CAN_MessageSend,
313   ARM_CAN_MessageRead,
314   ARM_CAN_Control,
315   ARM_CAN_GetStatus
316 };
317 
318