Skip to content

Commit 0a82591

Browse files
petroboryspetroborys
authored andcommitted
Add can_api.c for efm32
1 parent 6bdbe75 commit 0a82591

File tree

6 files changed

+623
-255
lines changed

6 files changed

+623
-255
lines changed

targets/TARGET_Silicon_Labs/TARGET_EFM32/PeripheralNames.h

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

139+
#if DEVICE_CAN
140+
typedef enum {
141+
CAN_0 = (int)CAN0_BASE,
142+
CAN_1 = (int)CAN1_BASE
143+
} CANName;
144+
#endif
145+
139146
#if DEVICE_QSPI
140147
typedef enum {
141148
#ifdef QSPI0_BASE
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2006-2017 ARM Limited
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+
#ifndef MBED_CAN_DEVICE_H
17+
#define MBED_CAN_DEVICE_H
18+
19+
#include "cmsis.h"
20+
21+
#ifdef __cplusplus
22+
extern "C" {
23+
#endif
24+
25+
#if DEVICE_CAN
26+
27+
#define CAN_COUNT 2 // Number of CAN peripherals
28+
29+
30+
#endif // DEVICE_CAN
31+
32+
#endif
Lines changed: 310 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,310 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2006-2017 ARM Limited
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 "can_device.h"
28+
#include "em_cmu.h"
29+
#include "em_can.h"
30+
31+
static uint32_t can_irq_ids[CAN_COUNT] = {0};
32+
static can_irq_handler irq_handler;
33+
34+
// CAN bus interfaces
35+
#define CAN_TX_IF 0
36+
#define CAN_RX_IF 1
37+
38+
void can_init(can_t *obj, PinName rd, PinName td)
39+
{
40+
can_init_freq(obj, rd, td, 100000);
41+
}
42+
43+
void can_init_freq(can_t *obj, PinName rd, PinName td, int hz)
44+
{
45+
CANName can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RX);
46+
CANName can_td = (CANName)pinmap_peripheral(td, PinMap_CAN_TX);
47+
obj->instance = (CAN_TypeDef *)pinmap_merge(can_rd, can_td);
48+
49+
CMU_Clock_TypeDef cmuClock_number;
50+
switch ((CANName)obj->instance) {
51+
case CAN_0:
52+
cmuClock_number = cmuClock_CAN0;
53+
break;
54+
case CAN_1:
55+
cmuClock_number = cmuClock_CAN1;
56+
break;
57+
}
58+
59+
MBED_ASSERT((unsigned int)rd != NC);
60+
MBED_ASSERT((unsigned int)td != NC);
61+
62+
63+
// Configure CAN pins
64+
pinmap_pinout(rd, PinMap_CAN_RX);
65+
pinmap_pinout(td, PinMap_CAN_TX);
66+
67+
68+
CMU_ClockEnable(cmuClock_number, true);
69+
70+
CAN_Init_TypeDef CanInit = CAN_INIT_DEFAULT;
71+
CanInit.bitrate=hz;
72+
CAN_Init(obj->instance, &CanInit);
73+
CAN_SetMode(obj->instance, canModeNormal);
74+
75+
uint32_t loc_rd = pin_location(rd, PinMap_CAN_RX);
76+
uint32_t loc_td = pin_location(td, PinMap_CAN_TX);
77+
78+
CAN_SetRoute(obj->instance, true, loc_rd, loc_td);
79+
80+
81+
// Add pull-ups
82+
if (rd != NC) {
83+
pin_mode(rd, gpioModeInput);
84+
}
85+
if (td != NC) {
86+
pin_mode(td, gpioModePushPull);
87+
}
88+
89+
CAN_ConfigureMessageObject(obj->instance, CAN_TX_IF, 1, true, true, false, true, true);
90+
91+
CAN_ConfigureMessageObject(obj->instance, CAN_RX_IF, 2, true, false, false, true, true);
92+
93+
CAN_MessageObject_TypeDef receiver;
94+
95+
receiver.msgNum = 2;
96+
receiver.id = 0;
97+
receiver.mask = 0;
98+
receiver.extended = false;
99+
receiver.extendedMask = false;
100+
101+
CAN_SetIdAndFilter(obj->instance, CAN_RX_IF, true, &receiver, true);
102+
}
103+
104+
void can_irq_init(can_t *obj, can_irq_handler handler, uint32_t id)
105+
{
106+
int index = 0;
107+
108+
switch ((CANName)obj->instance) {
109+
case CAN_0:
110+
index = 0;
111+
break;
112+
case CAN_1:
113+
index = 1;
114+
break;
115+
}
116+
117+
irq_handler = handler;
118+
can_irq_ids[index] = id;
119+
}
120+
121+
void can_irq_free(can_t *obj)
122+
{
123+
CAN_MessageIntDisable(obj->instance, _CAN_IF0IEN_MESSAGE_MASK);
124+
CAN_MessageIntClear(obj->instance, 0xFFFFFFFF);
125+
126+
switch ((CANName)obj->instance) {
127+
case CAN_0:
128+
NVIC_DisableIRQ(CAN0_IRQn);
129+
break;
130+
case CAN_1:
131+
NVIC_DisableIRQ(CAN1_IRQn);
132+
break;
133+
}
134+
}
135+
136+
void can_free(can_t *obj)
137+
{
138+
CAN_Enable(obj->instance, false);
139+
}
140+
141+
int can_frequency(can_t *obj, int f)
142+
{
143+
CAN_Init_TypeDef CanInit = CAN_INIT_DEFAULT;
144+
CanInit.bitrate=f;
145+
146+
CAN_SetBitTiming(obj->instance,
147+
CanInit.bitrate,
148+
CanInit.propagationTimeSegment,
149+
CanInit.phaseBufferSegment1,
150+
CanInit.phaseBufferSegment2,
151+
CanInit.synchronisationJumpWidth);
152+
}
153+
154+
int can_write(can_t *obj, CAN_Message msg, int cc)
155+
{
156+
CAN_MessageObject_TypeDef message;
157+
158+
message.id = msg.id;
159+
message.msgNum = 1;
160+
161+
if (msg.format == 0) message.extended = false;
162+
else message.extended = true;
163+
164+
message.dlc = msg.len;
165+
166+
for (int i = 0; i < message.dlc; ++i) {
167+
message.data[i] = (uint32_t)msg.data[i];
168+
}
169+
170+
CAN_SendMessage(obj->instance, CAN_TX_IF, &message, true);
171+
172+
return 1;
173+
}
174+
175+
int can_read(can_t *obj, CAN_Message *msg, int handle)
176+
{
177+
CAN_MessageObject_TypeDef receiver;
178+
179+
if (CAN_HasNewdata(obj->instance)) {
180+
181+
receiver.msgNum = 2;
182+
183+
CAN_ReadMessage(obj->instance, CAN_RX_IF, &receiver);
184+
185+
msg->id = receiver.id;
186+
msg->len = receiver.dlc;
187+
188+
for (int i = 0; i < receiver.dlc; ++i) {
189+
msg->data[i] = (unsigned char)receiver.data[i];
190+
}
191+
192+
return 1;
193+
}
194+
195+
return 0;
196+
}
197+
198+
void can_reset(can_t *obj)
199+
{
200+
CAN_Reset(obj->instance);
201+
}
202+
203+
unsigned char can_rderror(can_t *obj)
204+
{
205+
return ((obj->instance->ERRCNT>>_CAN_ERRCNT_REC_SHIFT)&0xFF);
206+
}
207+
208+
unsigned char can_tderror(can_t *obj)
209+
{
210+
return ((obj->instance->ERRCNT)&0xFF);
211+
}
212+
213+
void can_monitor(can_t *obj, int silent)
214+
{
215+
CanMode mode = MODE_NORMAL;
216+
217+
if (silent) {
218+
mode = MODE_SILENT;
219+
}
220+
221+
CAN_SetMode(obj->instance, mode);
222+
}
223+
224+
int can_mode(can_t *obj, CanMode mode)
225+
{
226+
CAN_SetMode(obj->instance, mode);
227+
return 1;
228+
}
229+
230+
int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle)
231+
{
232+
CAN_MessageObject_TypeDef message;
233+
234+
message.msgNum = 2;
235+
message.id = id;
236+
message.mask = mask;
237+
238+
if (format == CANStandard) {
239+
message.extended = false;
240+
message.extendedMask = false;
241+
} else {
242+
message.extended = true;
243+
message.extendedMask = true;
244+
}
245+
246+
CAN_SetIdAndFilter(obj->instance, CAN_RX_IF, true, &message, true);
247+
248+
return handle;
249+
}
250+
251+
void can_irq_set(can_t *obj, CanIrqType type, uint32_t enable)
252+
{
253+
uint32_t ier = _CAN_IF0IEN_MESSAGE_MASK;
254+
255+
if (enable) {
256+
CAN_MessageIntEnable(obj->instance, ier);
257+
} else {
258+
CAN_MessageIntDisable(obj->instance, ier);
259+
}
260+
261+
switch ((CANName)obj->instance) {
262+
case CAN_0:
263+
NVIC_SetVector(CAN0_IRQn, CAN0_IRQHandler);
264+
NVIC_EnableIRQ(CAN0_IRQn);
265+
break;
266+
case CAN_1:
267+
NVIC_SetVector(CAN1_IRQn, CAN1_IRQHandler);
268+
NVIC_EnableIRQ(CAN1_IRQn);
269+
break;
270+
}
271+
}
272+
273+
static void can_irq(CANName name, int id)
274+
{
275+
CAN_TypeDef *can;
276+
can = (CAN_TypeDef *)name;
277+
278+
if (can->STATUS & CAN_STATUS_RXOK) {
279+
irq_handler(can_irq_ids[id], IRQ_RX);
280+
CAN_MessageIntClear(can, 0xFFFFFFFF);
281+
}
282+
283+
if (can->STATUS & CAN_STATUS_TXOK) {
284+
irq_handler(can_irq_ids[id], IRQ_TX);
285+
CAN_MessageIntClear(can, 0xFFFFFFFF);
286+
}
287+
}
288+
289+
void CAN0_IRQHandler(void)
290+
{
291+
can_irq(CAN_0, 0);
292+
}
293+
294+
void CAN1_IRQHandler(void)
295+
{
296+
can_irq(CAN_1, 1);
297+
}
298+
299+
300+
const PinMap *can_rd_pinmap()
301+
{
302+
return PinMap_CAN_TX;
303+
}
304+
305+
const PinMap *can_td_pinmap()
306+
{
307+
return PinMap_CAN_RX;
308+
}
309+
310+
#endif // DEVICE_CAN

0 commit comments

Comments
 (0)