Browse Source

add lib/can.*

Signed-off-by: surenyi <surenyi82@163.com>
master
surenyi 5 years ago
parent
commit
a37643d3e3
  1. 291
      lib/can.c
  2. 36
      lib/can.h
  3. 8
      lib/config.h
  4. 1
      lib/lib.mk
  5. 2
      targets/xc_ppf1901/target.h

291
lib/can.c

@ -0,0 +1,291 @@
#include <stdint.h>
#include <string.h>
#include "stm32f4xx.h"
#include "can.h"
struct canbus {
CAN_TypeDef *base;
CAN_InitTypeDef conf;
CAN_FilterInitTypeDef filter;
uint32_t rcc;
int irq0;
int irq1;
void (*setup)(struct canbus *);
void *user;
void (*callback)(struct canbus *, void *user);
};
/* query APB1 clocks */
static uint32_t get_PCLK1_clocks()
{
RCC_ClocksTypeDef clks;
RCC_GetClocksFreq(&clks);
return clks.PCLK1_Frequency;
}
int can_set_baudrate(struct canbus *can, unsigned int baudrate)
{
int found = 0;
int calcBaudrate;
uint8_t sjw = 1, bs1 = 1, bs2 = 1;
uint16_t prescaler = 1;
uint32_t frequency;
CAN_InitTypeDef conf = can->conf;
frequency = get_PCLK1_clocks();
for (; sjw <= 4 && !found; ) {
for (; bs1 <= 16 && !found; ) {
for (; bs2 <= 8 && !found; ) {
for (; prescaler <= 1024 && !found; ) {
calcBaudrate = (int)(frequency / (prescaler * (sjw + bs1 + bs2)));
if (calcBaudrate == baudrate) {
if (sjw == 1)
conf.CAN_SJW = CAN_SJW_1tq;
else if (sjw == 2)
conf.CAN_SJW = CAN_SJW_2tq;
else if (sjw == 3)
conf.CAN_SJW = CAN_SJW_3tq;
else if (sjw == 4)
conf.CAN_SJW = CAN_SJW_4tq;
if (bs1 == 1)
conf.CAN_BS1 = CAN_BS1_1tq;
else if (bs1 == 2)
conf.CAN_BS1 = CAN_BS1_2tq;
else if (bs1 == 3)
conf.CAN_BS1 = CAN_BS1_3tq;
else if (bs1 == 4)
conf.CAN_BS1 = CAN_BS1_4tq;
else if (bs1 == 5)
conf.CAN_BS1 = CAN_BS1_5tq;
else if (bs1 == 6)
conf.CAN_BS1 = CAN_BS1_6tq;
else if (bs1 == 7)
conf.CAN_BS1 = CAN_BS1_7tq;
else if (bs1 == 8)
conf.CAN_BS1 = CAN_BS1_8tq;
else if (bs1 == 9)
conf.CAN_BS1 = CAN_BS1_9tq;
else if (bs1 == 10)
conf.CAN_BS1 = CAN_BS1_10tq;
else if (bs1 == 11)
conf.CAN_BS1 = CAN_BS1_11tq;
else if (bs1 == 12)
conf.CAN_BS1 = CAN_BS1_12tq;
else if (bs1 == 13)
conf.CAN_BS1 = CAN_BS1_13tq;
else if (bs1 == 14)
conf.CAN_BS1 = CAN_BS1_14tq;
else if (bs1 == 15)
conf.CAN_BS1 = CAN_BS1_15tq;
else if (bs1 == 16)
conf.CAN_BS1 = CAN_BS1_16tq;
if (bs2 == 1)
conf.CAN_BS2 = CAN_BS2_1tq;
else if (bs2 == 2)
conf.CAN_BS2 = CAN_BS2_2tq;
else if (bs2 == 3)
conf.CAN_BS2 = CAN_BS2_2tq;
else if (bs2 == 4)
conf.CAN_BS2 = CAN_BS2_2tq;
conf.CAN_Prescaler = prescaler;
found = 1;
}
prescaler++;
}
if (!found) {
prescaler = 1;
bs2++;
}
}
if (!found) {
bs2 = 1;
bs1++;
}
}
if (!found) {
bs1 = 1;
sjw++;
}
}
if (found) {
CAN_Init(can->base, &conf);
can->conf = conf;
return 0;
}
return -1;
}
static void __canx_init(struct canbus *can)
{
/* CAN register init */
CAN_DeInit(can->base);
/* CAN cell init */
CAN_StructInit(&can->conf);
CAN_Init(can->base, &can->conf);
/* 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_FilterInit(&can->filter);
}
void can_setup(struct canbus *can, int baudrate)
{
/* CANx Periph clock enable */
RCC_APB1PeriphClockCmd(can->rcc, ENABLE);
if (can->setup)
can->setup(can);
__canx_init(can);
if (baudrate > 0) {
can_set_baudrate(can, baudrate);
}
}
static int do_send_std_data(struct canbus *can, int remote, unsigned char id, const void *data, unsigned char len)
{
CanTxMsg tx;
uint8_t tbox;
int i;
#define RETRY_MAX (0xffff)
if (len > 8) {
len = 8;
}
/* transmit */
tx.StdId = id;
tx.RTR = remote ? CAN_RTR_REMOTE : CAN_RTR_DATA;
tx.IDE = CAN_ID_STD;
tx.DLC = len;
memcpy(tx.Data, data, len);
tbox = CAN_Transmit(can->base, &tx);
if (tbox == CAN_TxStatus_NoMailBox) {
return -2;
}
i = 0;
while((CAN_TransmitStatus(can->base, tbox) != CANTXOK) && (i != RETRY_MAX)) {
++i;
}
return (i == RETRY_MAX) ? -1 : len;
#undef RETRY_MAX
}
int can_send_std_data(struct canbus *can, unsigned char id, const void *data, unsigned char len)
{
return do_send_std_data(can, 0, id, data, len);
}
int can_send_std_remote(struct canbus *can, unsigned char id, const void *data, unsigned char len)
{
return do_send_std_data(can, 1, id, data, len);
}
void can_attach_rx(struct canbus *can, void *user, void (*rx)(struct canbus *can, void *user))
{
can->user = user;
can->callback = rx;
}
void can_close(struct canbus *can)
{
RCC_APB1PeriphClockCmd(can->rcc, DISABLE);
CAN_DeInit(can->base);
}
#if (TARGET_HAS_CAN0)
void __attribute__((weak)) target_can0_setup()
{
GPIO_InitTypeDef gpio_conf;
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_Speed = GPIO_Speed_100MHz;
gpio_conf.GPIO_OType = GPIO_OType_PP;
gpio_conf.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &gpio_conf);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_CAN1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_CAN1);
}
static void __can0_setup(struct canbus *can)
{
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,
.setup = __can0_setup,
};
#endif
#if (TARGET_HAS_CAN1)
void __attribute__((weak)) target_can1_setup()
{
}
static void __can1_setup(struct canbus *can)
{
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,
.setup = __can1_setup,
};
#endif

36
lib/can.h

@ -0,0 +1,36 @@
#ifndef __CAN_BUS_H____
#define __CAN_BUS_H____
#ifdef __cplusplus
extern "C" {
#endif
#include "config.h"
struct canbus;
/* can initialize */
void can_setup(struct canbus *can, int baudrate);
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);
void can_close(struct canbus *can);
#if (TARGET_HAS_CAN0)
extern struct canbus can0;
#endif
#if (TARGET_HAS_CAN1)
extern struct canbus can1;
#endif
#ifdef __cplusplus
}
#endif
#endif

8
lib/config.h

@ -87,6 +87,14 @@ extern "C" {
#define TARGET_CMD_MAXARGS (8)
#endif
#ifndef TARGET_HAS_CAN0
#define TARGET_HAS_CAN0 0
#endif
#ifndef TARGET_HAS_CAN1
#define TARGET_HAS_CAN1 0
#endif
#ifdef __cplusplus
}
#endif

1
lib/lib.mk

@ -19,6 +19,7 @@ lib_srcs += \
$(lib_dir)/i2c.c \
$(lib_dir)/iis.c \
$(lib_dir)/spi.c \
$(lib_dir)/can.c \
$(lib_dir)/spi_flash.c \
$(lib_dir)/at24c256_i2c.c \
$(lib_dir)/at24c256_iic.c \

2
targets/xc_ppf1901/target.h

@ -40,6 +40,8 @@
#define TARGET_USART7_RX_BUFFER_SIZE (2048)
#define TARGET_USART7_TX_BUFFER_SIZE (2048)
#define TARGET_HAS_CAN0 1
#define WDI (PA1)
#define JPB1_VCC18_EN (PC13)
#define JPB1_VCC13_PG (PA8)

Loading…
Cancel
Save