Skip to content

Commit bab78c6

Browse files
authored
Merge pull request #10468 from petroborys/master
Add support for CAN to SiLabs targets
2 parents 0ac1c97 + b635c02 commit bab78c6

File tree

5 files changed

+616
-255
lines changed

5 files changed

+616
-255
lines changed

targets/TARGET_Silicon_Labs/TARGET_EFM32/PeripheralNames.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,17 @@ typedef enum {
136136
} UARTName;
137137
#endif
138138

139+
#if DEVICE_CAN
140+
typedef enum {
141+
#ifdef CAN0_BASE
142+
CAN_0 = (int)CAN0_BASE,
143+
#endif
144+
#ifdef CAN1_BASE
145+
CAN_1 = (int)CAN1_BASE,
146+
#endif
147+
} CANName;
148+
#endif
149+
139150
#if DEVICE_QSPI
140151
typedef enum {
141152
#ifdef QSPI0_BASE
Lines changed: 331 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,331 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2019 ToolSense
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
#include "can_api.h"
17+
#include "clocking.h"
18+
19+
20+
#if DEVICE_CAN
21+
22+
#include "cmsis.h"
23+
#include "pinmap.h"
24+
#include "pinmap_function.h"
25+
#include "PeripheralPins.h"
26+
#include "mbed_assert.h"
27+
#include "em_cmu.h"
28+
#include "em_can.h"
29+
30+
static uint32_t can_irq_ids[CAN_COUNT] = {0};
31+
static can_irq_handler irq_handler;
32+
33+
// CAN bus interfaces
34+
#define CAN_TX_IF 0
35+
#define CAN_RX_IF 1
36+
37+
void can_init(can_t *obj, PinName rd, PinName td)
38+
{
39+
can_init_freq(obj, rd, td, 100000);
40+
}
41+
42+
void can_init_freq(can_t *obj, PinName rd, PinName td, int hz)
43+
{
44+
CANName can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RX);
45+
CANName can_td = (CANName)pinmap_peripheral(td, PinMap_CAN_TX);
46+
obj->instance = (CAN_TypeDef *)pinmap_merge(can_rd, can_td);
47+
48+
CMU_Clock_TypeDef cmuClock_number;
49+
switch ((CANName)obj->instance) {
50+
#ifdef CAN0
51+
case CAN_0:
52+
cmuClock_number = cmuClock_CAN0;
53+
break;
54+
#endif
55+
#ifdef CAN1
56+
case CAN_1:
57+
cmuClock_number = cmuClock_CAN1;
58+
break;
59+
#endif
60+
}
61+
62+
MBED_ASSERT((unsigned int)rd != NC);
63+
MBED_ASSERT((unsigned int)td != NC);
64+
65+
66+
// Configure CAN pins
67+
pinmap_pinout(rd, PinMap_CAN_RX);
68+
pinmap_pinout(td, PinMap_CAN_TX);
69+
70+
71+
CMU_ClockEnable(cmuClock_number, true);
72+
73+
CAN_Init_TypeDef CanInit = CAN_INIT_DEFAULT;
74+
CanInit.bitrate=hz;
75+
CAN_Init(obj->instance, &CanInit);
76+
CAN_SetMode(obj->instance, canModeNormal);
77+
78+
uint32_t loc_rd = pin_location(rd, PinMap_CAN_RX);
79+
uint32_t loc_td = pin_location(td, PinMap_CAN_TX);
80+
81+
CAN_SetRoute(obj->instance, true, loc_rd, loc_td);
82+
83+
84+
// Add pull-ups
85+
if (rd != NC) {
86+
pin_mode(rd, gpioModeInput);
87+
}
88+
if (td != NC) {
89+
pin_mode(td, gpioModePushPull);
90+
}
91+
92+
CAN_ConfigureMessageObject(obj->instance, CAN_TX_IF, 1, true, true, false, true, true);
93+
94+
CAN_ConfigureMessageObject(obj->instance, CAN_RX_IF, 2, true, false, false, true, true);
95+
96+
CAN_MessageObject_TypeDef receiver;
97+
98+
receiver.msgNum = 2;
99+
receiver.id = 0;
100+
receiver.mask = 0;
101+
receiver.extended = false;
102+
receiver.extendedMask = false;
103+
104+
CAN_SetIdAndFilter(obj->instance, CAN_RX_IF, true, &receiver, true);
105+
}
106+
107+
void can_irq_init(can_t *obj, can_irq_handler handler, uint32_t id)
108+
{
109+
int index = 0;
110+
111+
switch ((CANName)obj->instance) {
112+
#ifdef CAN0
113+
case CAN_0:
114+
index = 0;
115+
break;
116+
#endif
117+
#ifdef CAN1
118+
case CAN_1:
119+
index = 1;
120+
break;
121+
#endif
122+
}
123+
124+
irq_handler = handler;
125+
can_irq_ids[index] = id;
126+
}
127+
128+
void can_irq_free(can_t *obj)
129+
{
130+
CAN_MessageIntDisable(obj->instance, _CAN_IF0IEN_MESSAGE_MASK);
131+
CAN_MessageIntClear(obj->instance, 0xFFFFFFFF);
132+
133+
switch ((CANName)obj->instance) {
134+
#ifdef CAN0
135+
case CAN_0:
136+
NVIC_DisableIRQ(CAN0_IRQn);
137+
break;
138+
#endif
139+
#ifdef CAN1
140+
case CAN_1:
141+
NVIC_DisableIRQ(CAN1_IRQn);
142+
break;
143+
#endif
144+
}
145+
}
146+
147+
void can_free(can_t *obj)
148+
{
149+
CAN_Enable(obj->instance, false);
150+
}
151+
152+
int can_frequency(can_t *obj, int f)
153+
{
154+
CAN_Init_TypeDef CanInit = CAN_INIT_DEFAULT;
155+
CanInit.bitrate=f;
156+
157+
CAN_SetBitTiming(obj->instance,
158+
CanInit.bitrate,
159+
CanInit.propagationTimeSegment,
160+
CanInit.phaseBufferSegment1,
161+
CanInit.phaseBufferSegment2,
162+
CanInit.synchronisationJumpWidth);
163+
return 0;
164+
}
165+
166+
int can_write(can_t *obj, CAN_Message msg, int cc)
167+
{
168+
CAN_MessageObject_TypeDef message;
169+
170+
message.id = msg.id;
171+
message.msgNum = 1;
172+
173+
if (msg.format == 0) message.extended = false;
174+
else message.extended = true;
175+
176+
message.dlc = msg.len;
177+
178+
for (int i = 0; i < message.dlc; ++i) {
179+
message.data[i] = (uint32_t)msg.data[i];
180+
}
181+
182+
CAN_SendMessage(obj->instance, CAN_TX_IF, &message, true);
183+
184+
return 1;
185+
}
186+
187+
int can_read(can_t *obj, CAN_Message *msg, int handle)
188+
{
189+
CAN_MessageObject_TypeDef receiver;
190+
191+
if (CAN_HasNewdata(obj->instance)) {
192+
193+
receiver.msgNum = 2;
194+
receiver.extended = false;
195+
receiver.extendedMask = false;
196+
197+
CAN_ReadMessage(obj->instance, CAN_RX_IF, &receiver);
198+
199+
msg->id = receiver.id;
200+
msg->len = receiver.dlc;
201+
202+
for (int i = 0; i < receiver.dlc; ++i) {
203+
msg->data[i] = (unsigned char)receiver.data[i];
204+
}
205+
206+
return 1;
207+
}
208+
209+
return 0;
210+
}
211+
212+
void can_reset(can_t *obj)
213+
{
214+
CAN_Reset(obj->instance);
215+
}
216+
217+
unsigned char can_rderror(can_t *obj)
218+
{
219+
return ((obj->instance->ERRCNT>>_CAN_ERRCNT_REC_SHIFT)&0xFF);
220+
}
221+
222+
unsigned char can_tderror(can_t *obj)
223+
{
224+
return ((obj->instance->ERRCNT)&0xFF);
225+
}
226+
227+
void can_monitor(can_t *obj, int silent)
228+
{
229+
CanMode mode = MODE_NORMAL;
230+
231+
if (silent) {
232+
mode = MODE_SILENT;
233+
}
234+
235+
CAN_SetMode(obj->instance, mode);
236+
}
237+
238+
int can_mode(can_t *obj, CanMode mode)
239+
{
240+
CAN_SetMode(obj->instance, mode);
241+
return 1;
242+
}
243+
244+
int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle)
245+
{
246+
CAN_MessageObject_TypeDef message;
247+
248+
message.msgNum = 2;
249+
message.id = id;
250+
message.mask = mask;
251+
252+
if (format == CANStandard) {
253+
message.extended = false;
254+
message.extendedMask = false;
255+
} else {
256+
message.extended = true;
257+
message.extendedMask = true;
258+
}
259+
260+
CAN_SetIdAndFilter(obj->instance, CAN_RX_IF, true, &message, true);
261+
262+
return handle;
263+
}
264+
265+
void can_irq_set(can_t *obj, CanIrqType type, uint32_t enable)
266+
{
267+
uint32_t ier = _CAN_IF0IEN_MESSAGE_MASK;
268+
269+
if (enable) {
270+
CAN_MessageIntEnable(obj->instance, ier);
271+
} else {
272+
CAN_MessageIntDisable(obj->instance, ier);
273+
}
274+
275+
switch ((CANName)obj->instance) {
276+
#ifdef CAN0
277+
case CAN_0:
278+
NVIC_SetVector(CAN0_IRQn, (uint32_t)CAN0_IRQHandler);
279+
NVIC_EnableIRQ(CAN0_IRQn);
280+
break;
281+
#endif
282+
#ifdef CAN1
283+
case CAN_1:
284+
NVIC_SetVector(CAN1_IRQn, (uint32_t)CAN1_IRQHandler);
285+
NVIC_EnableIRQ(CAN1_IRQn);
286+
break;
287+
#endif
288+
}
289+
}
290+
291+
static void can_irq(CANName name, int id)
292+
{
293+
CAN_TypeDef *can;
294+
can = (CAN_TypeDef *)name;
295+
296+
if (can->STATUS & CAN_STATUS_RXOK) {
297+
irq_handler(can_irq_ids[id], IRQ_RX);
298+
CAN_MessageIntClear(can, 0xFFFFFFFF);
299+
}
300+
301+
if (can->STATUS & CAN_STATUS_TXOK) {
302+
irq_handler(can_irq_ids[id], IRQ_TX);
303+
CAN_MessageIntClear(can, 0xFFFFFFFF);
304+
}
305+
}
306+
307+
#ifdef CAN0
308+
void CAN0_IRQHandler(void)
309+
{
310+
can_irq(CAN_0, 0);
311+
}
312+
#endif
313+
314+
#ifdef CAN1
315+
void CAN1_IRQHandler(void)
316+
{
317+
can_irq(CAN_1, 1);
318+
}
319+
#endif
320+
321+
const PinMap *can_rd_pinmap()
322+
{
323+
return PinMap_CAN_TX;
324+
}
325+
326+
const PinMap *can_td_pinmap()
327+
{
328+
return PinMap_CAN_RX;
329+
}
330+
331+
#endif //DEVICE_CAN

0 commit comments

Comments
 (0)