Browse Source

Merge branch 'master' of 192.168.0.201:/backup/git/repositories/mcu/stm32f4

master
zhaijunyuan 5 years ago
parent
commit
6eb4ed9948
  1. 169
      lib/can.c
  2. 24
      lib/can.h
  3. 8
      lib/config.h

169
lib/can.c

@ -10,12 +10,14 @@ struct canbus {
uint32_t rcc; uint32_t rcc;
int irq0; uint8_t irq;
int irq1;
uint8_t fifo;
void (*setup)(struct canbus *); void (*setup)(struct canbus *);
void *user; void *user;
void (*callback)(struct canbus *, void *user); void (*callback)(struct canbus *, void *user, struct canrx_msg *msg);
}; };
/* query APB1 clocks */ /* query APB1 clocks */
@ -122,27 +124,42 @@ int can_set_baudrate(struct canbus *can, unsigned int baudrate)
can->conf = conf; can->conf = conf;
return 0; return 0;
} }
return -1; 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); CAN_DeInit(can->base);
NVIC_DisableIRQ(can->irq);
/* CAN cell init */ /* CAN cell init */
CAN_StructInit(&can->conf); CAN_StructInit(&can->conf);
CAN_Init(can->base, &can->conf); CAN_Init(can->base, &can->conf);
if (baudrate > 0) {
can_set_baudrate(can, baudrate);
}
/* CAN filter init */ /* CAN filter init */
#if 0 can->filter.CAN_FilterNumber = can->base == CAN1 ? 0 : 14; /* can0 use [0, 13], can1 use [14, 27] */
#ifdef USE_CAN1 can->filter.CAN_FilterMode = CAN_FilterMode_IdMask;
can->filter.CAN_FilterNumber = 0; can->filter.CAN_FilterScale = CAN_FilterScale_32bit;
#else /* USE_CAN2 */ can->filter.CAN_FilterIdHigh = 0x0000;
can->filter.CAN_FilterNumber = 14; can->filter.CAN_FilterIdLow = 0x0000;
#endif /* USE_CAN1 */ can->filter.CAN_FilterMaskIdHigh = 0x0000;
#endif 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); CAN_FilterInit(&can->filter);
} }
@ -154,14 +171,16 @@ void can_setup(struct canbus *can, int baudrate)
if (can->setup) if (can->setup)
can->setup(can); can->setup(can);
__canx_init(can); __canx_init(can, baudrate);
if (baudrate > 0) { if (can->fifo == 0) {
can_set_baudrate(can, baudrate); 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; CanTxMsg tx;
uint8_t tbox; uint8_t tbox;
@ -173,9 +192,14 @@ static int do_send_std_data(struct canbus *can, int remote, unsigned char id, co
} }
/* transmit */ /* transmit */
if (is_extend) {
tx.ExtId = id;
tx.IDE = CAN_ID_EXT;
} else {
tx.StdId = id; tx.StdId = id;
tx.RTR = remote ? CAN_RTR_REMOTE : CAN_RTR_DATA;
tx.IDE = CAN_ID_STD; tx.IDE = CAN_ID_STD;
}
tx.RTR = remote ? CAN_RTR_REMOTE : CAN_RTR_DATA;
tx.DLC = len; tx.DLC = len;
memcpy(tx.Data, data, len); memcpy(tx.Data, data, len);
@ -192,29 +216,65 @@ static int do_send_std_data(struct canbus *can, int remote, unsigned char id, co
#undef RETRY_MAX #undef RETRY_MAX
} }
int can_send_std_data(struct canbus *can, unsigned char id, const void *data, unsigned char len) int can_send_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_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->user = user;
can->callback = rx; can->callback = rx;
NVIC_EnableIRQ(can->irq);
} }
void can_close(struct canbus *can) void can_close(struct canbus *can)
{ {
RCC_APB1PeriphClockCmd(can->rcc, DISABLE); 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); 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) #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() void __attribute__((weak)) target_can0_setup()
{ {
GPIO_InitTypeDef gpio_conf; GPIO_InitTypeDef gpio_conf;
@ -236,54 +296,69 @@ void __attribute__((weak)) target_can0_setup()
static void __can0_setup(struct canbus *can) 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(); target_can0_setup();
} }
struct canbus can0 = { struct canbus can0 = {
.base = CAN1, .base = CAN1,
.filter = { .fifo = TARGET_CAN0_FIFO,
.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, .rcc = RCC_APB1Periph_CAN1,
.setup = __can0_setup, .setup = __can0_setup,
}; };
#endif #endif
#if (TARGET_HAS_CAN1) #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() 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) 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(); target_can1_setup();
} }
struct canbus can1 = { struct canbus can1 = {
.base = CAN2, .base = CAN2,
.filter = { .fifo = TARGET_CAN1_FIFO,
.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, .rcc = RCC_APB1Periph_CAN2,
.setup = __can1_setup, .setup = __can1_setup,
}; };

24
lib/can.h

@ -13,11 +13,29 @@ void can_setup(struct canbus *can, int baudrate);
int can_set_baudrate(struct canbus *can, unsigned int baudrate); int can_set_baudrate(struct canbus *can, unsigned int baudrate);
/* /*
* send standard can frame. * send can frame.
*
* return > 0 on success. * return > 0 on success.
*/ */
int can_send_std_data(struct canbus *can, unsigned char id, const void *data, unsigned char len); int can_send_data(struct canbus *can, int is_extend, unsigned int 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_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); void can_close(struct canbus *can);

8
lib/config.h

@ -91,10 +91,18 @@ extern "C" {
#define TARGET_HAS_CAN0 0 #define TARGET_HAS_CAN0 0
#endif #endif
#ifndef TARGET_CAN0_FIFO
#define TARGET_CAN0_FIFO 0
#endif
#ifndef TARGET_HAS_CAN1 #ifndef TARGET_HAS_CAN1
#define TARGET_HAS_CAN1 0 #define TARGET_HAS_CAN1 0
#endif #endif
#ifndef TARGET_CAN1_FIFO
#define TARGET_CAN1_FIFO 1
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

Loading…
Cancel
Save