From e122277a95410bbf291e74b7464e9d2c7c6d8b85 Mon Sep 17 00:00:00 2001 From: surenyi Date: Mon, 24 Jun 2019 13:44:04 +0800 Subject: [PATCH] update lib/can.* Signed-off-by: surenyi --- lib/can.c | 187 ++++++++++++++++++++++++++++++++++++--------------- lib/can.h | 21 +++++- lib/config.h | 8 +++ 3 files changed, 158 insertions(+), 58 deletions(-) diff --git a/lib/can.c b/lib/can.c index 4a2c277..281688f 100644 --- a/lib/can.c +++ b/lib/can.c @@ -10,12 +10,14 @@ struct canbus { uint32_t rcc; - int irq0; - int irq1; + uint8_t irq; + + uint8_t fifo; + void (*setup)(struct canbus *); void *user; - void (*callback)(struct canbus *, void *user); + void (*callback)(struct canbus *, void *user, struct canrx_msg *msg); }; /* query APB1 clocks */ @@ -122,27 +124,42 @@ int can_set_baudrate(struct canbus *can, unsigned int baudrate) can->conf = conf; return 0; } + return -1; } -static void __canx_init(struct canbus *can) +static void __canx_init(struct canbus *can, int baudrate) { - /* CAN register init */ + /* CAN register init */ CAN_DeInit(can->base); + NVIC_DisableIRQ(can->irq); /* CAN cell init */ CAN_StructInit(&can->conf); CAN_Init(can->base, &can->conf); + if (baudrate > 0) { + can_set_baudrate(can, baudrate); + } + /* CAN filter init */ -#if 0 -#ifdef USE_CAN1 - can->filter.CAN_FilterNumber = 0; -#else /* USE_CAN2 */ - can->filter.CAN_FilterNumber = 14; -#endif /* USE_CAN1 */ -#endif + can->filter.CAN_FilterNumber = can->base == CAN1 ? 0 : 14; /* can0 use [0, 13], can1 use [14, 27] */ + can->filter.CAN_FilterMode = CAN_FilterMode_IdMask; + can->filter.CAN_FilterScale = CAN_FilterScale_32bit; + can->filter.CAN_FilterIdHigh = 0x0000; + can->filter.CAN_FilterIdLow = 0x0000; + can->filter.CAN_FilterMaskIdHigh = 0x0000; + can->filter.CAN_FilterMaskIdLow = 0x0000; + + if (can->fifo == 0) { + can->filter.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0; /* fifo 0 */ + } else { + can->filter.CAN_FilterFIFOAssignment = CAN_Filter_FIFO1; /* fifo 1 */ + } + + can->filter.CAN_FilterActivation = ENABLE; + CAN_FilterInit(&can->filter); } @@ -154,14 +171,16 @@ void can_setup(struct canbus *can, int baudrate) if (can->setup) can->setup(can); - __canx_init(can); + __canx_init(can, baudrate); - if (baudrate > 0) { - can_set_baudrate(can, baudrate); + if (can->fifo == 0) { + CAN_ITConfig(can->base, CAN_IT_FMP0, ENABLE); + } else { + CAN_ITConfig(can->base, CAN_IT_FMP1, ENABLE); } } -static int do_send_std_data(struct canbus *can, int remote, unsigned char id, const void *data, unsigned char len) +static int __do_send_data(struct canbus *can, int is_extend, int remote, unsigned char id, const void *data, unsigned char len) { CanTxMsg tx; uint8_t tbox; @@ -173,9 +192,14 @@ static int do_send_std_data(struct canbus *can, int remote, unsigned char id, co } /* transmit */ - tx.StdId = id; + if (is_extend) { + tx.ExtId = id; + tx.IDE = CAN_ID_EXT; + } else { + tx.StdId = id; + tx.IDE = CAN_ID_STD; + } tx.RTR = remote ? CAN_RTR_REMOTE : CAN_RTR_DATA; - tx.IDE = CAN_ID_STD; tx.DLC = len; memcpy(tx.Data, data, len); @@ -192,43 +216,79 @@ static int do_send_std_data(struct canbus *can, int remote, unsigned char id, co #undef RETRY_MAX } -int can_send_std_data(struct canbus *can, unsigned char id, const void *data, unsigned char len) +int can_send_std_data(struct canbus *can, int is_extend, unsigned int id, const void *data, unsigned char len) { - return do_send_std_data(can, 0, id, data, len); + return __do_send_data(can, is_extend, 0, id, data, len); } -int can_send_std_remote(struct canbus *can, unsigned char id, const void *data, unsigned char len) +int can_send_std_remote(struct canbus *can, int is_extend, unsigned int id, const void *data, unsigned char len) { - return do_send_std_data(can, 1, id, data, len); + return __do_send_data(can, is_extend, 1, id, data, len); } -void can_attach_rx(struct canbus *can, void *user, void (*rx)(struct canbus *can, void *user)) +void can_attach_rx(struct canbus *can, void *user, void (*rx)(struct canbus *can, void *user, struct canrx_msg *msg)) { + NVIC_DisableIRQ(can->irq); can->user = user; can->callback = rx; + NVIC_EnableIRQ(can->irq); } void can_close(struct canbus *can) { RCC_APB1PeriphClockCmd(can->rcc, DISABLE); + + CAN_ITConfig(can->base, CAN_IT_FMP0, DISABLE); + CAN_ITConfig(can->base, CAN_IT_FMP1, DISABLE); + + NVIC_DisableIRQ(can->irq); + CAN_DeInit(can->base); } +void __do_rx_isr(struct canbus *can, int fifo) +{ + CanRxMsg msg; + struct canrx_msg rx; + + while(CAN_MessagePending(can->base, fifo) > 0) { + CAN_Receive(can->base, fifo, &msg); + if (can->callback) { + rx.is_std = msg.IDE == CAN_ID_STD; + rx.is_data = msg.RTR == CAN_RTR_Data; + rx.data = msg.Data; + rx.len = msg.DLC; + can->callback(can, can->user, &rx); + } + } +} + #if (TARGET_HAS_CAN0) + +void CAN1_RX0_IRQHandler() /* CAN1 RX0 */ +{ + __do_rx_isr(&can0, CAN_FIFO0); +} + +void CAN1_RX1_IRQHandler() /* CAN1 RX1 */ +{ + __do_rx_isr(&can0, CAN_FIFO1); +} + void __attribute__((weak)) target_can0_setup() { GPIO_InitTypeDef gpio_conf; - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); GPIO_StructInit(&gpio_conf); gpio_conf.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12; /* PA 11(CAN1 RX) and PA 12 (CAN1 TX) */ - gpio_conf.GPIO_Mode = GPIO_Mode_AF; + gpio_conf.GPIO_Mode = GPIO_Mode_AF; gpio_conf.GPIO_Speed = GPIO_Speed_100MHz; gpio_conf.GPIO_OType = GPIO_OType_PP; gpio_conf.GPIO_PuPd = GPIO_PuPd_UP; - GPIO_Init(GPIOA, &gpio_conf); + GPIO_Init(GPIOA, &gpio_conf); GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_CAN1); GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_CAN1); @@ -236,55 +296,70 @@ void __attribute__((weak)) target_can0_setup() static void __can0_setup(struct canbus *can) { + if (can->fifo == 0) { + can->irq = CAN1_RX0_IRQn; + } else { + can->irq = CAN1_RX1_IRQn; + } + target_can0_setup(); + } struct canbus can0 = { - .base = CAN1, - .filter = { - .CAN_FilterNumber = 0, - .CAN_FilterMode = CAN_FilterMode_IdMask, - .CAN_FilterScale = CAN_FilterScale_32bit, - .CAN_FilterIdHigh = 0x0000, - .CAN_FilterIdLow = 0x0000, - .CAN_FilterMaskIdHigh = 0x0000, - .CAN_FilterMaskIdLow = 0x0000, - .CAN_FilterFIFOAssignment = CAN_Filter_FIFO0, - .CAN_FilterActivation = ENABLE, - }, - .irq0 = CAN1_RX0_IRQn, - .irq1 = CAN1_RX1_IRQn, - .rcc = RCC_APB1Periph_CAN1, + .base = CAN1, + .fifo = TARGET_CAN0_FIFO, + .rcc = RCC_APB1Periph_CAN1, .setup = __can0_setup, }; #endif #if (TARGET_HAS_CAN1) + +void CAN2_RX0_IRQHandler() /* CAN2 RX0 */ +{ + __do_rx_isr(&can1, CAN_FIFO0); +} + +void CAN2_RX1_IRQHandler() /* CAN2 RX1 */ +{ + __do_rx_isr(&can1, CAN_FIFO1); +} + void __attribute__((weak)) target_can1_setup() { + GPIO_InitTypeDef gpio_conf; + + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); + + GPIO_StructInit(&gpio_conf); + + gpio_conf.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13; /* PB 12(CAN2 RX) and PB 13 (CAN2 TX) */ + gpio_conf.GPIO_Mode = GPIO_Mode_AF; + gpio_conf.GPIO_Speed = GPIO_Speed_100MHz; + gpio_conf.GPIO_OType = GPIO_OType_PP; + gpio_conf.GPIO_PuPd = GPIO_PuPd_UP; + GPIO_Init(GPIOB, &gpio_conf); + + GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_CAN2); + GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_CAN2); } static void __can1_setup(struct canbus *can) { + if (can->fifo == 0) { + can->irq = CAN2_RX0_IRQn; + } else { + can->irq = CAN2_RX1_IRQn; + } + target_can1_setup(); } struct canbus can1 = { - .base = CAN2, - .filter = { - .CAN_FilterNumber = 14, - .CAN_FilterMode = CAN_FilterMode_IdMask, - .CAN_FilterScale = CAN_FilterScale_32bit, - .CAN_FilterIdHigh = 0x0000, - .CAN_FilterIdLow = 0x0000, - .CAN_FilterMaskIdHigh = 0x0000, - .CAN_FilterMaskIdLow = 0x0000, - .CAN_FilterFIFOAssignment = CAN_Filter_FIFO0, /* fifo 0 or 1 */ - .CAN_FilterActivation = ENABLE, - }, - .irq0 = CAN2_RX0_IRQn, - .irq1 = CAN2_RX1_IRQn, - .rcc = RCC_APB1Periph_CAN2, + .base = CAN2, + .fifo = TARGET_CAN1_FIFO, + .rcc = RCC_APB1Periph_CAN2, .setup = __can1_setup, }; #endif diff --git a/lib/can.h b/lib/can.h index 8faecee..fb34fe5 100644 --- a/lib/can.h +++ b/lib/can.h @@ -16,8 +16,25 @@ int can_set_baudrate(struct canbus *can, unsigned int baudrate); * send standard can frame. * return > 0 on success. */ -int can_send_std_data(struct canbus *can, unsigned char id, const void *data, unsigned char len); -int can_send_std_remote(struct canbus *can, unsigned char id, const void *data, unsigned char len); +int can_send_std_data(struct canbus *can, int is_extend, unsigned int id, const void *data, unsigned char len); +int can_send_std_remote(struct canbus *can, int is_extend, unsigned int id, const void *data, unsigned char len); + +/* + * set receive rx handler + * + * rx: must not sleep, must not execute too long. + */ +struct canrx_msg { + uint32_t id; + + int is_std; + int is_data; + + int len; + const void *data; +}; + +void can_attach_rx(struct canbus *can, void *user, void (*rx)(struct canbus *can, void *user, struct canrx_msg *msg)); void can_close(struct canbus *can); diff --git a/lib/config.h b/lib/config.h index 38b2706..fa3499f 100644 --- a/lib/config.h +++ b/lib/config.h @@ -91,10 +91,18 @@ extern "C" { #define TARGET_HAS_CAN0 0 #endif +#ifndef TARGET_CAN0_FIFO +#define TARGET_CAN0_FIFO 0 +#endif + #ifndef TARGET_HAS_CAN1 #define TARGET_HAS_CAN1 0 #endif +#ifndef TARGET_CAN1_FIFO +#define TARGET_CAN1_FIFO 1 +#endif + #ifdef __cplusplus } #endif