Skip to content

Commit d11289b

Browse files
authored
Merge pull request #4165 from adustm/can_init
fix #3863 Add an mbed API that allows the init of the CAN at the bus frequency
2 parents 58e8881 + b6581d3 commit d11289b

File tree

16 files changed

+226
-42
lines changed

16 files changed

+226
-42
lines changed

drivers/CAN.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,17 @@ CAN::CAN(PinName rd, PinName td) : _can(), _irq() {
3434
can_irq_init(&_can, (&CAN::_irq_handler), (uint32_t)this);
3535
}
3636

37+
CAN::CAN(PinName rd, PinName td, int hz) : _can(), _irq() {
38+
// No lock needed in constructor
39+
40+
for (int i = 0; i < sizeof _irq / sizeof _irq[0]; i++) {
41+
_irq[i].attach(donothing);
42+
}
43+
44+
can_init_freq(&_can, rd, td, hz);
45+
can_irq_init(&_can, (&CAN::_irq_handler), (uint32_t)this);
46+
}
47+
3748
CAN::~CAN() {
3849
// No lock needed in destructor
3950
can_irq_free(&_can);

drivers/CAN.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,15 @@ class CAN {
111111
* @endcode
112112
*/
113113
CAN(PinName rd, PinName td);
114+
115+
/** Initialize CAN interface and set the frequency
116+
*
117+
* @param rd the rd pin
118+
* @param td the td pin
119+
* @param hz the bus frequency in hertz
120+
*/
121+
CAN(PinName rd, PinName td, int hz);
122+
114123
virtual ~CAN();
115124

116125
/** Set the frequency of the CAN interface
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 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 "mbed.h"
17+
#include "test_env.h"
18+
19+
#if !DEVICE_CAN
20+
#error [NOT_SUPPORTED] CAN not supported
21+
#endif
22+
23+
#if defined(TARGET_LPC1549)
24+
#define CAN_RD D9
25+
#define CAN_TD D8
26+
#elif defined(TARGET_LPC1768) || defined(TARGET_LPC4088)
27+
#define CAN_RD p9
28+
#define CAN_TD p10
29+
#elif defined(TARGET_B96B_F446VE)
30+
#define CAN_RD PD_0
31+
#define CAN_TD PD_1
32+
#elif defined(TARGET_VK_RZ_A1H)
33+
#define CAN_RD P5_9
34+
#define CAN_TD P5_10
35+
#elif defined(TARGET_NUCLEO_F042K6) || \
36+
defined(TARGET_NUCLEO_F072RB) || \
37+
defined(TARGET_NUCLEO_F091RC) || \
38+
defined(TARGET_NUCLEO_F302R8) || \
39+
defined(TARGET_NUCLEO_F303RE) || \
40+
defined(TARGET_NUCLEO_F303K8) || \
41+
defined(TARGET_NUCLEO_F334R8) || \
42+
defined(TARGET_NUCLEO_F412ZG) || \
43+
defined(TARGET_DISCO_F429ZI) || \
44+
defined(TARGET_NUCLEO_F446RE) || \
45+
defined(TARGET_NUCLEO_F746ZG) || \
46+
defined(TARGET_NUCLEO_L432KC) || \
47+
defined(TARGET_DISCO_L476VG) || \
48+
defined(TARGET_NUCLEO_L476RG)
49+
#define CAN_RD PA_11
50+
#define CAN_TD PA_12
51+
#elif defined(TARGET_NUCLEO_F103RB) || \
52+
defined(TARGET_NUCLEO_F207ZG) || \
53+
defined(TARGET_DISCO_F303VC) || \
54+
defined(TARGET_NUCLEO_F303ZE) || \
55+
defined(TARGET_NUCLEO_F412ZG) || \
56+
defined(TARGET_NUCLEO_F429ZI) || \
57+
defined(TARGET_NUCLEO_F439ZI) || \
58+
defined(TARGET_NUCLEO_F446ZE) || \
59+
defined(TARGET_DISCO_F469NI) || \
60+
defined(TARGET_DISCO_F746NG) || \
61+
defined(TARGET_NUCLEO_F756ZG) || \
62+
defined(TARGET_NUCLEO_F767ZI) || \
63+
defined(TARGET_DISCO_F769NI) || \
64+
defined(TARGET_NUCLEO_L486RG)
65+
#define CAN_RD PB_8
66+
#define CAN_TD PB_9
67+
#endif
68+
69+
int result = true;
70+
71+
void Check_CAN_Frequency(int CanFrequency)
72+
{
73+
printf("Init CAN at %d Hz\n", CanFrequency);
74+
75+
CAN can_object(CAN_RD, CAN_TD, CanFrequency);
76+
77+
#if !defined(TARGET_VK_RZ_A1H)
78+
can_object.mode(CAN::Reset);
79+
#endif
80+
81+
if (!can_object.mode(CAN::LocalTest)) {
82+
printf("CAN MODE_TEST_LOCAL failed\n");
83+
result = false;
84+
}
85+
}
86+
87+
int main()
88+
{
89+
MBED_HOSTTEST_TIMEOUT(20);
90+
MBED_HOSTTEST_SELECT(dev_null);
91+
MBED_HOSTTEST_DESCRIPTION(CAN API at different frequency);
92+
MBED_HOSTTEST_START("MBED_A30");
93+
94+
const int frequency_table[] = {10000, 50000, 100000, 500000, 1000000};
95+
for (uint32_t i = 0; i < sizeof(frequency_table)/sizeof(int); i++) {
96+
Check_CAN_Frequency(frequency_table[i]);
97+
}
98+
99+
MBED_HOSTTEST_RESULT(result);
100+
}

hal/can_api.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,10 @@ typedef void (*can_irq_handler)(uint32_t id, CanIrqType type);
5757

5858
typedef struct can_s can_t;
5959

60-
void can_init (can_t *obj, PinName rd, PinName td);
61-
void can_free (can_t *obj);
62-
int can_frequency(can_t *obj, int hz);
60+
void can_init (can_t *obj, PinName rd, PinName td);
61+
void can_init_freq (can_t *obj, PinName rd, PinName td, int hz);
62+
void can_free (can_t *obj);
63+
int can_frequency (can_t *obj, int hz);
6364

6465
void can_irq_init (can_t *obj, can_irq_handler handler, uint32_t id);
6566
void can_irq_free (can_t *obj);

targets/TARGET_NUVOTON/TARGET_M451/can_api.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@
4242
};
4343

4444

45-
void can_init(can_t *obj, PinName rd, PinName td)
46-
{
45+
void can_init_freq(can_t *obj, PinName rd, PinName td, int hz)
46+
{
4747
uint32_t can_td = (CANName)pinmap_peripheral(td, PinMap_CAN_TD);
4848
uint32_t can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RD);
4949
obj->can = (CANName)pinmap_merge(can_td, can_rd);
@@ -69,12 +69,18 @@
6969
PA0 = 0x00;
7070
PA1 = 0x00;
7171

72-
CAN_Open((CAN_T *)NU_MODBASE(obj->can), 500000, CAN_NORMAL_MODE);
72+
CAN_Open((CAN_T *)NU_MODBASE(obj->can), hz, CAN_NORMAL_MODE);
7373

7474
can_filter(obj, 0, 0, CANStandard, 0);
7575
}
76-
77-
76+
77+
78+
void can_init(can_t *obj, PinName rd, PinName td)
79+
{
80+
can_init_freq(obj, rd, td, 500000);
81+
}
82+
83+
7884
void can_free(can_t *obj)
7985
{
8086

targets/TARGET_NUVOTON/TARGET_NUC472/can_api.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@
4343
{NC, 0, 0, 0, 0, (IRQn_Type) 0, NULL}
4444
};
4545

46-
47-
void can_init(can_t *obj, PinName rd, PinName td)
46+
47+
void can_init_freq(can_t *obj, PinName rd, PinName td, int hz)
4848
{
4949
uint32_t can_td = (CANName)pinmap_peripheral(td, PinMap_CAN_TD);
5050
uint32_t can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RD);
@@ -75,12 +75,18 @@
7575
PA2 = 0x00;
7676
PA3 = 0x00;
7777

78-
CAN_Open((CAN_T *)NU_MODBASE(obj->can), 500000, CAN_NORMAL_MODE);
78+
CAN_Open((CAN_T *)NU_MODBASE(obj->can), hz, CAN_NORMAL_MODE);
7979

8080
can_filter(obj, 0, 0, CANStandard, 0);
8181
}
82-
83-
82+
83+
84+
void can_init(can_t *obj, PinName rd, PinName td)
85+
{
86+
can_init_freq(obj, rd, td, 500000);
87+
}
88+
89+
8490
void can_free(can_t *obj)
8591
{
8692

targets/TARGET_NXP/TARGET_LPC11XX_11CXX/TARGET_LPC11CXX/can_api.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -268,26 +268,30 @@ int can_config_rxmsgobj(can_t *obj) {
268268
}
269269

270270

271-
void can_init(can_t *obj, PinName rd, PinName td) {
271+
void can_init_freq(can_t *obj, PinName rd, PinName td, int hz) {
272272
// Enable power and clock
273273
LPC_SYSCON->PRESETCTRL |= PRESETCTRL_CAN_RST_N;
274274
LPC_SYSCON->SYSAHBCLKCTRL |= SYSAHBCLKCTRL_CAN;
275-
275+
276276
// Enable Initialization mode
277277
if (!(LPC_CAN->CNTL & CANCNTL_INIT)) {
278278
LPC_CAN->CNTL |= CANCNTL_INIT;
279279
}
280-
281-
can_frequency(obj, 125000);
282-
280+
281+
can_frequency(obj, hz);
282+
283283
// Resume operation
284284
LPC_CAN->CNTL &= ~CANCNTL_INIT;
285285
while ( LPC_CAN->CNTL & CANCNTL_INIT );
286-
286+
287287
// Initialize RX message object
288288
can_config_rxmsgobj(obj);
289289
}
290290

291+
void can_init(can_t *obj, PinName rd, PinName td) {
292+
can_init_freq(obj, rd, td, 125000);
293+
}
294+
291295
void can_free(can_t *obj) {
292296
LPC_SYSCON->SYSAHBCLKCTRL &= ~(SYSAHBCLKCTRL_CAN);
293297
LPC_SYSCON->PRESETCTRL &= ~(PRESETCTRL_CAN_RST_N);

targets/TARGET_NXP/TARGET_LPC15XX/can_api.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -415,8 +415,7 @@ int can_config_txmsgobj(can_t *obj) {
415415
return 1;
416416
}
417417

418-
419-
void can_init(can_t *obj, PinName rd, PinName td) {
418+
void can_init_freq(can_t *obj, PinName rd, PinName td, int hz) {
420419
// Enable power and clock
421420
LPC_SYSCON->SYSAHBCLKCTRL1 |= (1UL << 7);
422421
LPC_SYSCON->PRESETCTRL1 |= (1UL << 7);
@@ -430,7 +429,7 @@ void can_init(can_t *obj, PinName rd, PinName td) {
430429
LPC_SWM->PINASSIGN[6] &= ~(0x00FFFF00L);
431430
LPC_SWM->PINASSIGN[6] |= (rd << 16) | (td << 8);
432431

433-
can_frequency(obj, 100000);
432+
can_frequency(obj, hz);
434433

435434
// Resume operation
436435
LPC_C_CAN0->CANCNTL &= ~(1UL << 0);
@@ -442,6 +441,10 @@ void can_init(can_t *obj, PinName rd, PinName td) {
442441
can_config_txmsgobj(obj);
443442
}
444443

444+
void can_init(can_t *obj, PinName rd, PinName td) {
445+
can_init_freq(obj, rd, td, 100000);
446+
}
447+
445448
void can_free(can_t *obj) {
446449
LPC_SYSCON->SYSAHBCLKCTRL1 &= ~(1UL << 7);
447450
LPC_SYSCON->PRESETCTRL1 &= ~(1UL << 7);

targets/TARGET_NXP/TARGET_LPC176X/can_api.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ static unsigned int can_speed(unsigned int sclk, unsigned int pclk, unsigned int
292292

293293
}
294294

295-
void can_init(can_t *obj, PinName rd, PinName td) {
295+
void can_init_freq(can_t *obj, PinName rd, PinName td, int hz) {
296296
CANName can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RD);
297297
CANName can_td = (CANName)pinmap_peripheral(td, PinMap_CAN_TD);
298298
obj->dev = (LPC_CAN_TypeDef *)pinmap_merge(can_rd, can_td);
@@ -313,11 +313,15 @@ void can_init(can_t *obj, PinName rd, PinName td) {
313313

314314
can_reset(obj);
315315
obj->dev->IER = 0; // Disable Interrupts
316-
can_frequency(obj, 100000);
316+
can_frequency(obj, hz);
317317

318318
LPC_CANAF->AFMR = ACCF_BYPASS; // Bypass Filter
319319
}
320320

321+
void can_init(can_t *obj, PinName rd, PinName td) {
322+
can_init_freq(obj, rd, td, 100000);
323+
}
324+
321325
void can_free(can_t *obj) {
322326
switch ((int)obj->dev) {
323327
case CAN_1: LPC_SC->PCONP &= ~(1 << 13); break;

targets/TARGET_NXP/TARGET_LPC408X/TARGET_LPC4088/can_api.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ static unsigned int can_speed(unsigned int pclk, unsigned int cclk, unsigned cha
239239

240240
}
241241

242-
void can_init(can_t *obj, PinName rd, PinName td) {
242+
void can_init_freq(can_t *obj, PinName rd, PinName td, int hz) {
243243
CANName can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RD);
244244
CANName can_td = (CANName)pinmap_peripheral(td, PinMap_CAN_TD);
245245
obj->dev = (LPC_CAN_TypeDef *)pinmap_merge(can_rd, can_td);
@@ -252,19 +252,23 @@ void can_init(can_t *obj, PinName rd, PinName td) {
252252

253253
pinmap_pinout(rd, PinMap_CAN_RD);
254254
pinmap_pinout(td, PinMap_CAN_TD);
255-
255+
256256
switch ((int)obj->dev) {
257257
case CAN_1: obj->index = 0; break;
258258
case CAN_2: obj->index = 1; break;
259259
}
260-
260+
261261
can_reset(obj);
262262
obj->dev->IER = 0; // Disable Interrupts
263-
can_frequency(obj, 100000);
263+
can_frequency(obj, hz);
264264

265265
LPC_CANAF->AFMR = ACCF_BYPASS; // Bypass Filter
266266
}
267267

268+
void can_init(can_t *obj, PinName rd, PinName td) {
269+
can_init_freq(obj, rd, td, 100000);
270+
}
271+
268272
void can_free(can_t *obj) {
269273
switch ((int)obj->dev) {
270274
case CAN_1: LPC_SC->PCONP &= ~(1 << 13); break;

targets/TARGET_NXP/TARGET_LPC408X/TARGET_LPC4088_DM/can_api.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ static unsigned int can_speed(unsigned int pclk, unsigned int cclk, unsigned cha
236236

237237
}
238238

239-
void can_init(can_t *obj, PinName rd, PinName td) {
239+
void can_init_freq(can_t *obj, PinName rd, PinName td, int hz) {
240240
CANName can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RD);
241241
CANName can_td = (CANName)pinmap_peripheral(td, PinMap_CAN_TD);
242242
obj->dev = (LPC_CAN_TypeDef *)pinmap_merge(can_rd, can_td);
@@ -257,11 +257,15 @@ void can_init(can_t *obj, PinName rd, PinName td) {
257257

258258
can_reset(obj);
259259
obj->dev->IER = 0; // Disable Interrupts
260-
can_frequency(obj, 100000);
260+
can_frequency(obj, hz);
261261

262262
LPC_CANAF->AFMR = ACCF_BYPASS; // Bypass Filter
263263
}
264264

265+
void can_init(can_t *obj, PinName rd, PinName td) {
266+
can_init_freq(obj, rd, td, 100000);
267+
}
268+
265269
void can_free(can_t *obj) {
266270
switch ((int)obj->dev) {
267271
case CAN_1: LPC_SC->PCONP &= ~(1 << 13); break;

targets/TARGET_RENESAS/TARGET_RZ_A1H/can_api.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,7 @@ static void can4_bus_err_irq(void) {
539539
can_err_irq(CAN_4, IRQ_BUS);
540540
}
541541

542-
void can_init(can_t *obj, PinName rd, PinName td) {
542+
void can_init_freq(can_t *obj, PinName rd, PinName td, int hz) {
543543
__IO uint32_t *dmy_ctr;
544544

545545
/* determine the CAN to use */
@@ -573,6 +573,13 @@ void can_init(can_t *obj, PinName rd, PinName td) {
573573
/* pin out the can pins */
574574
pinmap_pinout(rd, PinMap_CAN_RD);
575575
pinmap_pinout(td, PinMap_CAN_TD);
576+
577+
/* set can frequency */
578+
can_frequency(obj, hz);
579+
}
580+
581+
void can_init(can_t *obj, PinName rd, PinName td) {
582+
can_init_freq(obj, rd, td, 100000);
576583
}
577584

578585
void can_free(can_t *obj) {

0 commit comments

Comments
 (0)