[mbed][CAN] Implement CAN::mode for C_CAN controllers

Implement all CAN modes except for GlobalTest on on the LPC11CXX
and LPC15XX targets which use the C_CAN controller
Fix swapped ordering between MODE_TEST_LOCAL and MODE_TEST_GLOBAL
in the HAL definition of CanMode.
pull/1059/head
Devan Lai 2015-04-07 00:33:26 -07:00
parent 29ab478a78
commit c233c88107
3 changed files with 88 additions and 3 deletions

View File

@ -45,8 +45,8 @@ typedef enum {
MODE_RESET,
MODE_NORMAL,
MODE_SILENT,
MODE_TEST_GLOBAL,
MODE_TEST_LOCAL,
MODE_TEST_GLOBAL,
MODE_TEST_SILENT
} CanMode;

View File

@ -45,7 +45,42 @@ static inline void can_enable(can_t *obj) {
}
int can_mode(can_t *obj, CanMode mode) {
return 0; // not implemented
int success = 0;
switch (mode) {
case MODE_RESET:
LPC_CAN->CNTL &=~CANCNTL_TEST;
can_disable(obj);
success = 1;
break;
case MODE_NORMAL:
LPC_CAN->CNTL &=~CANCNTL_TEST;
can_enable(obj);
success = 1;
break;
case MODE_SILENT:
LPC_CAN->CNTL |= CANCNTL_TEST;
LPC_CAN->TEST |= CANTEST_SILENT;
LPC_CAN->TEST &=~CANTEST_LBACK;
success = 1;
break;
case MODE_TEST_LOCAL:
LPC_CAN->CNTL |= CANCNTL_TEST;
LPC_CAN->TEST &=~CANTEST_SILENT;
LPC_CAN->TEST |= CANTEST_LBACK;
success = 1;
break;
case MODE_TEST_SILENT:
LPC_CAN->CNTL |= CANCNTL_TEST;
LPC_CAN->TEST |= (CANCNTL_LBACK | CANTEST_SILENT);
success = 1;
break;
case MODE_TEST_GLOBAL:
default:
success = 0;
break;
}
return success;
}
int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle) {

View File

@ -56,6 +56,21 @@
#define CANIFn_CMDMSK_RD (0UL << 7)
#define CANIFn_CMDREQ_BUSY (1UL << 15)
#define CANCNTL_INIT (1 << 0) // Initialization
#define CANCNTL_IE (1 << 1) // Module interrupt enable
#define CANCNTL_SIE (1 << 2) // Status change interrupt enable
#define CANCNTL_EIE (1 << 3) // Error interrupt enable
#define CANCNTL_DAR (1 << 5) // Disable automatic retransmission
#define CANCNTL_CCE (1 << 6) // Configuration change enable
#define CANCNTL_TEST (1 << 7) // Test mode enable
#define CANTEST_BASIC (1 << 2) // Basic mode
#define CANTEST_SILENT (1 << 3) // Silent mode
#define CANTEST_LBACK (1 << 4) // Loop back mode
#define CANTEST_TX_MASK 0x0060 // Control of CAN_TXD pins
#define CANTEST_TX_SHIFT 5
#define CANTEST_RX (1 << 7) // Monitors the actual value of the CAN_RXD pin.
static uint32_t can_irq_id = 0;
static can_irq_handler irq_handler;
@ -70,7 +85,42 @@ static inline void can_enable(can_t *obj) {
}
int can_mode(can_t *obj, CanMode mode) {
return 0; // not implemented
int success = 0;
switch (mode) {
case MODE_RESET:
LPC_C_CAN0->CANCNTL &=~CANCNTL_TEST;
can_disable(obj);
success = 1;
break;
case MODE_NORMAL:
LPC_C_CAN0->CANCNTL &=~CANCNTL_TEST;
can_enable(obj);
success = 1;
break;
case MODE_SILENT:
LPC_C_CAN0->CANCNTL |= CANCNTL_TEST;
LPC_C_CAN0->CANTEST |= CANTEST_SILENT;
LPC_C_CAN0->CANTEST &=~ CANTEST_LBACK;
success = 1;
break;
case MODE_TEST_LOCAL:
LPC_C_CAN0->CANCNTL |= CANCNTL_TEST;
LPC_C_CAN0->CANTEST &=~CANTEST_SILENT;
LPC_C_CAN0->CANTEST |= CANTEST_LBACK;
success = 1;
break;
case MODE_TEST_SILENT:
LPC_C_CAN0->CANCNTL |= CANCNTL_TEST;
LPC_C_CAN0->CANTEST |= (CANTEST_LBACK | CANTEST_SILENT);
success = 1;
break;
case MODE_TEST_GLOBAL:
default:
success = 0;
break;
}
return success;
}
int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle) {