Skip to content

Commit 334b341

Browse files
committed
Merge pull request #1059 from devanlai/can-loopback-wip
Implement some CAN modes for the LPC1549/LPC11Cxx/LPC1768
2 parents 23cde3b + fe04561 commit 334b341

File tree

6 files changed

+198
-5
lines changed

6 files changed

+198
-5
lines changed

libraries/mbed/hal/can_api.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ typedef enum {
4545
MODE_RESET,
4646
MODE_NORMAL,
4747
MODE_SILENT,
48-
MODE_TEST_GLOBAL,
4948
MODE_TEST_LOCAL,
49+
MODE_TEST_GLOBAL,
5050
MODE_TEST_SILENT
5151
} CanMode;
5252

libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11XX_11CXX/TARGET_LPC11CXX/can_api.c

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,42 @@ static inline void can_enable(can_t *obj) {
4545
}
4646

4747
int can_mode(can_t *obj, CanMode mode) {
48-
return 0; // not implemented
48+
int success = 0;
49+
switch (mode) {
50+
case MODE_RESET:
51+
LPC_CAN->CNTL &=~CANCNTL_TEST;
52+
can_disable(obj);
53+
success = 1;
54+
break;
55+
case MODE_NORMAL:
56+
LPC_CAN->CNTL &=~CANCNTL_TEST;
57+
can_enable(obj);
58+
success = 1;
59+
break;
60+
case MODE_SILENT:
61+
LPC_CAN->CNTL |= CANCNTL_TEST;
62+
LPC_CAN->TEST |= CANTEST_SILENT;
63+
LPC_CAN->TEST &=~CANTEST_LBACK;
64+
success = 1;
65+
break;
66+
case MODE_TEST_LOCAL:
67+
LPC_CAN->CNTL |= CANCNTL_TEST;
68+
LPC_CAN->TEST &=~CANTEST_SILENT;
69+
LPC_CAN->TEST |= CANTEST_LBACK;
70+
success = 1;
71+
break;
72+
case MODE_TEST_SILENT:
73+
LPC_CAN->CNTL |= CANCNTL_TEST;
74+
LPC_CAN->TEST |= (CANCNTL_LBACK | CANTEST_SILENT);
75+
success = 1;
76+
break;
77+
case MODE_TEST_GLOBAL:
78+
default:
79+
success = 0;
80+
break;
81+
}
82+
83+
return success;
4984
}
5085

5186
int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle) {

libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/can_api.c

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,21 @@
5656
#define CANIFn_CMDMSK_RD (0UL << 7)
5757
#define CANIFn_CMDREQ_BUSY (1UL << 15)
5858

59+
#define CANCNTL_INIT (1 << 0) // Initialization
60+
#define CANCNTL_IE (1 << 1) // Module interrupt enable
61+
#define CANCNTL_SIE (1 << 2) // Status change interrupt enable
62+
#define CANCNTL_EIE (1 << 3) // Error interrupt enable
63+
#define CANCNTL_DAR (1 << 5) // Disable automatic retransmission
64+
#define CANCNTL_CCE (1 << 6) // Configuration change enable
65+
#define CANCNTL_TEST (1 << 7) // Test mode enable
66+
67+
#define CANTEST_BASIC (1 << 2) // Basic mode
68+
#define CANTEST_SILENT (1 << 3) // Silent mode
69+
#define CANTEST_LBACK (1 << 4) // Loop back mode
70+
#define CANTEST_TX_MASK 0x0060 // Control of CAN_TXD pins
71+
#define CANTEST_TX_SHIFT 5
72+
#define CANTEST_RX (1 << 7) // Monitors the actual value of the CAN_RXD pin.
73+
5974
static uint32_t can_irq_id = 0;
6075
static can_irq_handler irq_handler;
6176

@@ -70,7 +85,42 @@ static inline void can_enable(can_t *obj) {
7085
}
7186

7287
int can_mode(can_t *obj, CanMode mode) {
73-
return 0; // not implemented
88+
int success = 0;
89+
switch (mode) {
90+
case MODE_RESET:
91+
LPC_C_CAN0->CANCNTL &=~CANCNTL_TEST;
92+
can_disable(obj);
93+
success = 1;
94+
break;
95+
case MODE_NORMAL:
96+
LPC_C_CAN0->CANCNTL &=~CANCNTL_TEST;
97+
can_enable(obj);
98+
success = 1;
99+
break;
100+
case MODE_SILENT:
101+
LPC_C_CAN0->CANCNTL |= CANCNTL_TEST;
102+
LPC_C_CAN0->CANTEST |= CANTEST_SILENT;
103+
LPC_C_CAN0->CANTEST &=~ CANTEST_LBACK;
104+
success = 1;
105+
break;
106+
case MODE_TEST_LOCAL:
107+
LPC_C_CAN0->CANCNTL |= CANCNTL_TEST;
108+
LPC_C_CAN0->CANTEST &=~CANTEST_SILENT;
109+
LPC_C_CAN0->CANTEST |= CANTEST_LBACK;
110+
success = 1;
111+
break;
112+
case MODE_TEST_SILENT:
113+
LPC_C_CAN0->CANCNTL |= CANCNTL_TEST;
114+
LPC_C_CAN0->CANTEST |= (CANTEST_LBACK | CANTEST_SILENT);
115+
success = 1;
116+
break;
117+
case MODE_TEST_GLOBAL:
118+
default:
119+
success = 0;
120+
break;
121+
}
122+
123+
return success;
74124
}
75125

76126
int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle) {

libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC176X/can_api.c

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,45 @@ static inline void can_enable(can_t *obj) {
7979
}
8080

8181
int can_mode(can_t *obj, CanMode mode) {
82-
return 0; // not implemented
82+
int success = 0;
83+
switch (mode) {
84+
case MODE_RESET:
85+
// Clear all special modes
86+
can_reset(obj);
87+
obj->dev->MOD &=~ 0x06;
88+
success = 1;
89+
break;
90+
case MODE_NORMAL:
91+
// Clear all special modes
92+
can_disable(obj);
93+
obj->dev->MOD &=~ 0x06;
94+
can_enable(obj);
95+
success = 1;
96+
break;
97+
case MODE_SILENT:
98+
// Set listen-only mode and clear self-test mode
99+
can_disable(obj);
100+
obj->dev->MOD |= 0x02;
101+
obj->dev->MOD &=~ 0x04;
102+
can_enable(obj);
103+
success = 1;
104+
break;
105+
case MODE_TEST_LOCAL:
106+
// Set self-test mode and clear listen-only mode
107+
can_disable(obj);
108+
obj->dev->MOD |= 0x04;
109+
obj->dev->MOD &=~ 0x02;
110+
can_enable(obj);
111+
success = 1;
112+
break;
113+
case MODE_TEST_SILENT:
114+
case MODE_TEST_GLOBAL:
115+
default:
116+
success = 0;
117+
break;
118+
}
119+
120+
return success;
83121
}
84122

85123
int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle) {
@@ -316,6 +354,12 @@ int can_write(can_t *obj, CAN_Message msg, int cc) {
316354
const unsigned int *buf = (const unsigned int *)&m;
317355

318356
CANStatus = obj->dev->SR;
357+
358+
// Send the message to ourself if in a test mode
359+
if (obj->dev->MOD & 0x04) {
360+
cc = 1;
361+
}
362+
319363
if (CANStatus & 0x00000004) {
320364
obj->dev->TFI1 = buf[0] & 0xC00F0000;
321365
obj->dev->TID1 = buf[1];
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#include "mbed.h"
2+
#include "test_env.h"
3+
4+
#if defined(TARGET_LPC1549)
5+
CAN can1(D9, D8);
6+
#elif defined(TARGET_LPC1768) || defined(TARGET_LPC4088)
7+
CAN can1(p9, p10);
8+
#endif
9+
10+
#define TEST_ITERATIONS 127
11+
12+
int main() {
13+
MBED_HOSTTEST_TIMEOUT(20);
14+
MBED_HOSTTEST_SELECT(dev_null);
15+
MBED_HOSTTEST_DESCRIPTION(CAN Loopback);
16+
MBED_HOSTTEST_START("MBED_A27");
17+
18+
can1.mode(CAN::Reset);
19+
20+
if (!can1.mode(CAN::LocalTest)) {
21+
printf("Mode change failed\n");
22+
}
23+
24+
char success_count = 0;
25+
for (char i=0; i < TEST_ITERATIONS; i++) {
26+
unsigned int id = 1337;
27+
CANMessage tx_msg(id, &i, sizeof(i));
28+
bool sent = false;
29+
if (can1.write(tx_msg)) {
30+
printf("Sent %u: %d\n", id, i);
31+
sent = true;
32+
}
33+
wait_ms(50);
34+
35+
bool read = false;
36+
CANMessage rx_msg;
37+
if (can1.read(rx_msg)) {
38+
printf("Read %u: %d\n", rx_msg.id, rx_msg.data[0]);
39+
read = (rx_msg.id == id) && (rx_msg.data[0] == i);
40+
}
41+
42+
bool success = sent && read;
43+
44+
if (success) {
45+
success_count++;
46+
}
47+
}
48+
49+
MBED_HOSTTEST_RESULT(success_count == TEST_ITERATIONS);
50+
}

workspace_tools/tests.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,12 @@
8080
* i2c_eeprom:
8181
* LPC1*: (SDA=p28 , SCL=p27)
8282
* KL25Z: (SDA=PTE0, SCL=PTE1)
83-
83+
84+
* can_transceiver:
85+
* LPC1768: (RX=p9, TX=p10)
86+
* LPC1549: (RX=D9, TX=D8)
87+
* LPC4088: (RX=p9, TX=p10)
88+
8489
"""
8590
TESTS = [
8691
# Automated MBED tests
@@ -270,6 +275,15 @@
270275
"automated": True,
271276
"duration": 10,
272277
},
278+
{
279+
"id": "MBED_A27", "description": "CAN loopback test",
280+
"source_dir": join(TEST_DIR, "mbed", "can_loopback"),
281+
"dependencies": [MBED_LIBRARIES, TEST_MBED_LIB],
282+
"automated": True,
283+
"duration": 20,
284+
"peripherals": ["can_transceiver"],
285+
"mcu": ["LPC1549", "LPC1768"],
286+
},
273287
{
274288
"id": "MBED_BLINKY", "description": "Blinky",
275289
"source_dir": join(TEST_DIR, "mbed", "blinky"),

0 commit comments

Comments
 (0)