drivers: can: Prepare STM32 driver for other series than STM32F0

This commit splits the common interrupt into rx and tx parts because
only STM32F0 series has a common interrupt.
Moved clock source definition to device-tree.

Signed-off-by: Alexander Wachter <alexander.wachter@student.tugraz.at>
This commit is contained in:
Alexander Wachter 2018-05-23 10:54:56 +02:00 committed by Anas Nashif
commit ebc31f6235
3 changed files with 115 additions and 45 deletions

View file

@ -43,18 +43,47 @@ static inline void can_stm32_get_msg_fifo(CAN_FIFOMailBox_TypeDef *mbox,
msg->data_32[1] = mbox->RDHR; msg->data_32[1] = mbox->RDHR;
} }
static void can_stm32_isr(void *arg) static inline
void can_stm32_rx_isr_handler(CAN_TypeDef *can, struct can_stm32_data *data)
{ {
struct device *dev; CAN_FIFOMailBox_TypeDef *mbox;
struct can_stm32_data *data; int filter_match_index;
const struct can_stm32_config *cfg; struct can_msg msg;
CAN_TypeDef *can;
u32_t bus_off;
dev = (struct device *)arg; while (can->RF0R & CAN_RF0R_FMP0) {
data = DEV_DATA(dev); mbox = &can->sFIFOMailBox[0];
cfg = DEV_CFG(dev); filter_match_index = ((mbox->RDTR & CAN_RDT0R_FMI)
can = cfg->can; >> CAN_RDT0R_FMI_Pos);
if (filter_match_index >= CONFIG_CAN_MAX_FILTER) {
break;
}
SYS_LOG_DBG("Message on filter index %d", filter_match_index);
can_stm32_get_msg_fifo(mbox, &msg);
if (data->rx_response[filter_match_index]) {
if (data->response_type & (1ULL << filter_match_index)) {
struct k_msgq *msg_q =
data->rx_response[filter_match_index];
k_msgq_put(msg_q, &msg, K_NO_WAIT);
} else {
can_rx_callback_t callback =
data->rx_response[filter_match_index];
callback(&msg);
}
}
/* Release message */
can->RF0R |= CAN_RF0R_RFOM0;
}
}
static inline
void can_stm32_tx_isr_handler(CAN_TypeDef *can, struct can_stm32_data *data)
{
u32_t bus_off;
bus_off = can->ESR & CAN_ESR_BOFF; bus_off = can->ESR & CAN_ESR_BOFF;
@ -97,41 +126,61 @@ static void can_stm32_isr(void *arg)
if (can->TSR & CAN_TSR_TME) { if (can->TSR & CAN_TSR_TME) {
k_sem_give(&data->tx_int_sem); k_sem_give(&data->tx_int_sem);
} }
while (can->RF0R & CAN_RF0R_FMP0) {
CAN_FIFOMailBox_TypeDef *mbox;
int filter_match_index;
struct can_msg msg;
mbox = &can->sFIFOMailBox[0];
filter_match_index = ((mbox->RDTR & CAN_RDT0R_FMI)
>> CAN_RDT0R_FMI_Pos);
if (filter_match_index >= CONFIG_CAN_MAX_FILTER) {
break;
} }
SYS_LOG_DBG("Message on filter index %d", filter_match_index); #ifdef CONFIG_SOC_SERIES_STM32F0X
can_stm32_get_msg_fifo(mbox, &msg);
if (data->rx_response[filter_match_index]) { static void can_stm32_isr(void *arg)
if (data->response_type & (1ULL << filter_match_index)) { {
struct k_msgq *msg_q = struct device *dev;
data->rx_response[filter_match_index]; struct can_stm32_data *data;
const struct can_stm32_config *cfg;
CAN_TypeDef *can;
dev = (struct device *)arg;
data = DEV_DATA(dev);
cfg = DEV_CFG(dev);
can = cfg->can;
can_stm32_tx_isr_handler(can, data);
can_stm32_rx_isr_handler(can, data);
k_msgq_put(msg_q, &msg, K_NO_WAIT);
} else {
can_rx_callback_t callback =
data->rx_response[filter_match_index];
callback(&msg);
}
} }
/* Release message */ #else
can->RF0R |= CAN_RF0R_RFOM0;
static void can_stm32_rx_isr(void *arg)
{
struct device *dev;
struct can_stm32_data *data;
const struct can_stm32_config *cfg;
CAN_TypeDef *can;
dev = (struct device *)arg;
data = DEV_DATA(dev);
cfg = DEV_CFG(dev);
can = cfg->can;
can_stm32_rx_isr_handler(can, data);
} }
static void can_stm32_tx_isr(void *arg)
{
struct device *dev;
struct can_stm32_data *data;
const struct can_stm32_config *cfg;
CAN_TypeDef *can;
dev = (struct device *)arg;
data = DEV_DATA(dev);
cfg = DEV_CFG(dev);
can = cfg->can;
can_stm32_tx_isr_handler(can, data);
} }
#endif
void HAL_CAN_MspInit(CAN_HandleTypeDef *hcan) void HAL_CAN_MspInit(CAN_HandleTypeDef *hcan)
{ {
ARG_UNUSED(hcan); ARG_UNUSED(hcan);
@ -798,8 +847,8 @@ static const struct can_stm32_config can_stm32_cfg_1 = {
.prop_bs1 = CONFIG_CAN_1_PROP_SEG_PHASE_SEG1, .prop_bs1 = CONFIG_CAN_1_PROP_SEG_PHASE_SEG1,
.bs2 = CONFIG_CAN_1_PHASE_SEG2, .bs2 = CONFIG_CAN_1_PHASE_SEG2,
.pclken = { .pclken = {
.enr = RCC_APB1ENR_CANEN, .enr = CONFIG_CAN_1_CLOCK_BITS,
.bus = STM32_CLOCK_BUS_APB1, .bus = CONFIG_CAN_1_CLOCK_BUS,
}, },
.config_irq = config_can_1_irq .config_irq = config_can_1_irq
}; };
@ -814,9 +863,23 @@ DEVICE_AND_API_INIT(can_stm32_1, CONFIG_CAN_1_NAME, &can_stm32_init,
static void config_can_1_irq(CAN_TypeDef *can) static void config_can_1_irq(CAN_TypeDef *can)
{ {
SYS_LOG_DBG("Enable CAN1 IRQ"); SYS_LOG_DBG("Enable CAN1 IRQ");
#ifdef CONFIG_SOC_SERIES_STM32F0X
IRQ_CONNECT(CONFIG_CAN_1_IRQ, CONFIG_CAN_1_IRQ_PRIORITY, can_stm32_isr, IRQ_CONNECT(CONFIG_CAN_1_IRQ, CONFIG_CAN_1_IRQ_PRIORITY, can_stm32_isr,
DEVICE_GET(can_stm32_1), 0); DEVICE_GET(can_stm32_1), 0);
irq_enable(CONFIG_CAN_1_IRQ); irq_enable(CONFIG_CAN_1_IRQ);
#else
IRQ_CONNECT(CONFIG_CAN_1_IRQ_RX0, CONFIG_CAN_1_IRQ_PRIORITY,
can_stm32_rx_isr, DEVICE_GET(can_stm32_1), 0);
irq_enable(CONFIG_CAN_1_IRQ_RX0);
IRQ_CONNECT(CONFIG_CAN_1_IRQ_TX, CONFIG_CAN_1_IRQ_PRIORITY,
can_stm32_tx_isr, DEVICE_GET(can_stm32_1), 0);
irq_enable(CONFIG_CAN_1_IRQ_TX);
IRQ_CONNECT(CONFIG_CAN_1_IRQ_SCE, CONFIG_CAN_1_IRQ_PRIORITY,
can_stm32_tx_isr, DEVICE_GET(can_stm32_1), 0);
irq_enable(CONFIG_CAN_1_IRQ_SCE);
#endif
can->IER |= CAN_IT_TME | CAN_IT_ERR | CAN_IT_FMP0 | CAN_IT_FMP1; can->IER |= CAN_IT_TME | CAN_IT_ERR | CAN_IT_FMP0 | CAN_IT_FMP1;
} }

View file

@ -64,6 +64,7 @@
#size-cells = <0>; #size-cells = <0>;
reg = <0x40006400 0x400>; reg = <0x40006400 0x400>;
interrupts = <30 0>; interrupts = <30 0>;
clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>;
status = "disabled"; status = "disabled";
label = "CAN_1"; label = "CAN_1";
bus-speed = <250000>; bus-speed = <250000>;

View file

@ -45,4 +45,10 @@ properties:
category: required category: required
description: tx pin name description: tx pin name
generation: define generation: define
clocks:
type: array
category: required
description: Clock gate control information
generation: define
... ...