diff --git a/drivers/can/can_common.c b/drivers/can/can_common.c index eb49b4169ea93..c46dbc533a044 100644 --- a/drivers/can/can_common.c +++ b/drivers/can/can_common.c @@ -24,6 +24,14 @@ LOG_MODULE_REGISTER(can_driver); #define WORK_BUF_FULL 0xFFFF +void can_common_isr_callback_handler(u32_t err, void *cb_arg) +{ + struct can_send_wait *send_wait = (struct can_send_wait *) cb_arg; + + send_wait->err = err; + k_sem_give(&send_wait->sem); +} + static void can_msgq_put(struct zcan_frame *frame, void *arg) { struct k_msgq *msgq = (struct k_msgq *)arg; diff --git a/drivers/can/can_mcp2515.c b/drivers/can/can_mcp2515.c index 155be404ea07d..1c4870f4952b9 100644 --- a/drivers/can/can_mcp2515.c +++ b/drivers/can/can_mcp2515.c @@ -389,6 +389,8 @@ static int mcp2515_send(struct device *dev, const struct zcan_frame *msg, u8_t len; u8_t tx_frame[MCP2515_FRAME_LEN]; + __ASSERT(callback != NULL, "callback is null"); + if (msg->dlc > CAN_MAX_DLC) { LOG_ERR("DLC of %d exceeds maximum (%d)", msg->dlc, CAN_MAX_DLC); return CAN_TX_EINVAL; @@ -432,10 +434,6 @@ static int mcp2515_send(struct device *dev, const struct zcan_frame *msg, nnn = BIT(tx_idx); mcp2515_cmd_rts(dev, nnn); - if (callback == NULL) { - k_sem_take(&dev_data->tx_cb[tx_idx].sem, K_FOREVER); - } - return 0; } @@ -564,11 +562,7 @@ static void mcp2515_tx_done(struct device *dev, u8_t tx_idx) { struct mcp2515_data *dev_data = DEV_DATA(dev); - if (dev_data->tx_cb[tx_idx].cb == NULL) { - k_sem_give(&dev_data->tx_cb[tx_idx].sem); - } else { - dev_data->tx_cb[tx_idx].cb(0, dev_data->tx_cb[tx_idx].cb_arg); - } + dev_data->tx_cb[tx_idx].cb(CAN_TX_OK, dev_data->tx_cb[tx_idx].cb_arg); k_mutex_lock(&dev_data->mutex, K_FOREVER); dev_data->tx_busy_map &= ~BIT(tx_idx); @@ -745,9 +739,6 @@ static int mcp2515_init(struct device *dev) k_sem_init(&dev_data->int_sem, 0, 1); k_mutex_init(&dev_data->mutex); k_sem_init(&dev_data->tx_sem, MCP2515_TX_CNT, MCP2515_TX_CNT); - k_sem_init(&dev_data->tx_cb[0].sem, 0, 1); - k_sem_init(&dev_data->tx_cb[1].sem, 0, 1); - k_sem_init(&dev_data->tx_cb[2].sem, 0, 1); /* SPI config */ dev_data->spi_cfg.operation = SPI_WORD_SET(8); diff --git a/drivers/can/can_mcp2515.h b/drivers/can/can_mcp2515.h index bd64c57270238..1ea4666375a96 100644 --- a/drivers/can/can_mcp2515.h +++ b/drivers/can/can_mcp2515.h @@ -19,7 +19,6 @@ #define DEV_DATA(dev) ((struct mcp2515_data *const)(dev)->driver_data) struct mcp2515_tx_cb { - struct k_sem sem; can_tx_callback_t cb; void *cb_arg; }; diff --git a/drivers/can/can_mcux_flexcan.c b/drivers/can/can_mcux_flexcan.c index 8a2bd84bea602..dc286d8479677 100644 --- a/drivers/can/can_mcux_flexcan.c +++ b/drivers/can/can_mcux_flexcan.c @@ -69,8 +69,6 @@ struct mcux_flexcan_rx_callback { }; struct mcux_flexcan_tx_callback { - struct k_sem done; - int status; flexcan_frame_t frame; can_tx_callback_t function; void *arg; @@ -296,6 +294,8 @@ static int mcux_flexcan_send(struct device *dev, const struct zcan_frame *msg, status_t status; int alloc; + __ASSERT(callback_isr != NULL, "callback is null"); + if (msg->dlc > CAN_MAX_DLC) { LOG_ERR("DLC of %d exceeds maximum (%d)", msg->dlc, CAN_MAX_DLC); return CAN_TX_EINVAL; @@ -328,11 +328,6 @@ static int mcux_flexcan_send(struct device *dev, const struct zcan_frame *msg, return CAN_TX_ERR; } - if (callback_isr == NULL) { - k_sem_take(&data->tx_cbs[alloc].done, K_FOREVER); - return data->tx_cbs[alloc].status; - } - return CAN_TX_OK; } @@ -546,13 +541,8 @@ static inline void mcux_flexcan_transfer_error_status(struct device *dev, if (atomic_test_and_clear_bit(data->tx_allocs, alloc)) { FLEXCAN_TransferAbortSend(config->base, &data->handle, ALLOC_IDX_TO_TXMB_IDX(alloc)); - if (function != NULL) { - function(status, arg); - } else { - data->tx_cbs[alloc].status = status; - k_sem_give(&data->tx_cbs[alloc].done); - } + function(status, arg); k_sem_give(&data->tx_allocs_sem); } } @@ -573,12 +563,7 @@ static inline void mcux_flexcan_transfer_tx_idle(struct device *dev, arg = data->tx_cbs[alloc].arg; if (atomic_test_and_clear_bit(data->tx_allocs, alloc)) { - if (function != NULL) { - function(CAN_TX_OK, arg); - } else { - data->tx_cbs[alloc].status = CAN_TX_OK; - k_sem_give(&data->tx_cbs[alloc].done); - } + function(CAN_TX_OK, arg); k_sem_give(&data->tx_allocs_sem); } } @@ -658,15 +643,10 @@ static int mcux_flexcan_init(struct device *dev) const struct mcux_flexcan_config *config = dev->config->config_info; struct mcux_flexcan_data *data = dev->driver_data; int err; - int i; k_mutex_init(&data->rx_mutex); k_sem_init(&data->tx_allocs_sem, 0, 1); - for (i = 0; i < ARRAY_SIZE(data->tx_cbs); i++) { - k_sem_init(&data->tx_cbs[i].done, 0, 1); - } - err = mcux_flexcan_configure(dev, CAN_NORMAL_MODE, 0); if (err) { return err; diff --git a/drivers/can/can_stm32.c b/drivers/can/can_stm32.c index d97b4452bb3b1..88e806ac7d8f8 100644 --- a/drivers/can/can_stm32.c +++ b/drivers/can/can_stm32.c @@ -29,15 +29,6 @@ LOG_MODULE_DECLARE(can_driver, CONFIG_CAN_LOG_LEVEL); static const u8_t filter_in_bank[] = {2, 4, 1, 2}; static const u8_t reg_demand[] = {2, 1, 4, 2}; -static void can_stm32_signal_tx_complete(struct can_mailbox *mb) -{ - if (mb->tx_callback) { - mb->tx_callback(mb->error_flags, mb->callback_arg); - } else { - k_sem_give(&mb->tx_int_sem); - } -} - static void can_stm32_get_msg_fifo(CAN_FIFOMailBox_TypeDef *mbox, struct zcan_frame *msg) { @@ -123,43 +114,44 @@ static inline void can_stm32_tx_isr_handler(CAN_TypeDef *can, struct can_stm32_data *data) { u32_t bus_off; + int err; bus_off = can->ESR & CAN_ESR_BOFF; if ((can->TSR & CAN_TSR_RQCP0) | bus_off) { - data->mb0.error_flags = - can->TSR & CAN_TSR_TXOK0 ? CAN_TX_OK : - can->TSR & CAN_TSR_TERR0 ? CAN_TX_ERR : - can->TSR & CAN_TSR_ALST0 ? CAN_TX_ARB_LOST : - bus_off ? CAN_TX_BUS_OFF : - CAN_TX_UNKNOWN; + err = can->TSR & CAN_TSR_TXOK0 ? CAN_TX_OK : + can->TSR & CAN_TSR_TERR0 ? CAN_TX_ERR : + can->TSR & CAN_TSR_ALST0 ? CAN_TX_ARB_LOST : + bus_off ? CAN_TX_BUS_OFF : + CAN_TX_UNKNOWN; + + data->mb0.tx_callback(err, data->mb0.callback_arg); /* clear the request. */ can->TSR |= CAN_TSR_RQCP0; - can_stm32_signal_tx_complete(&data->mb0); } if ((can->TSR & CAN_TSR_RQCP1) | bus_off) { - data->mb1.error_flags = - can->TSR & CAN_TSR_TXOK1 ? CAN_TX_OK : - can->TSR & CAN_TSR_TERR1 ? CAN_TX_ERR : - can->TSR & CAN_TSR_ALST1 ? CAN_TX_ARB_LOST : - bus_off ? CAN_TX_BUS_OFF : - CAN_TX_UNKNOWN; + err = can->TSR & CAN_TSR_TXOK1 ? CAN_TX_OK : + can->TSR & CAN_TSR_TERR1 ? CAN_TX_ERR : + can->TSR & CAN_TSR_ALST1 ? CAN_TX_ARB_LOST : + bus_off ? CAN_TX_BUS_OFF : + CAN_TX_UNKNOWN; + + data->mb1.tx_callback(err, data->mb1.callback_arg); /* clear the request. */ can->TSR |= CAN_TSR_RQCP1; - can_stm32_signal_tx_complete(&data->mb1); } if ((can->TSR & CAN_TSR_RQCP2) | bus_off) { - data->mb2.error_flags = - can->TSR & CAN_TSR_TXOK2 ? CAN_TX_OK : - can->TSR & CAN_TSR_TERR2 ? CAN_TX_ERR : - can->TSR & CAN_TSR_ALST2 ? CAN_TX_ARB_LOST : - bus_off ? CAN_TX_BUS_OFF : - CAN_TX_UNKNOWN; + err = can->TSR & CAN_TSR_TXOK2 ? CAN_TX_OK : + can->TSR & CAN_TSR_TERR2 ? CAN_TX_ERR : + can->TSR & CAN_TSR_ALST2 ? CAN_TX_ARB_LOST : + bus_off ? CAN_TX_BUS_OFF : + CAN_TX_UNKNOWN; + + data->mb2.tx_callback(err, data->mb2.callback_arg); /* clear the request. */ can->TSR |= CAN_TSR_RQCP2; - can_stm32_signal_tx_complete(&data->mb2); } if (can->TSR & CAN_TSR_TME) { @@ -386,9 +378,6 @@ static int can_stm32_init(struct device *dev) k_mutex_init(&data->inst_mutex); k_sem_init(&data->tx_int_sem, 0, 1); - k_sem_init(&data->mb0.tx_int_sem, 0, 1); - k_sem_init(&data->mb1.tx_int_sem, 0, 1); - k_sem_init(&data->mb2.tx_int_sem, 0, 1); data->mb0.tx_callback = NULL; data->mb1.tx_callback = NULL; data->mb2.tx_callback = NULL; @@ -548,6 +537,7 @@ int can_stm32_send(struct device *dev, const struct zcan_frame *msg, , msg->rtr == CAN_DATAFRAME ? "no" : "yes"); __ASSERT(msg->dlc == 0U || msg->data != NULL, "Dataptr is null"); + __ASSERT(callback != NULL, "callback is null"); if (msg->dlc > CAN_MAX_DLC) { LOG_ERR("DLC of %d exceeds maximum (%d)", msg->dlc, CAN_MAX_DLC); @@ -587,7 +577,6 @@ int can_stm32_send(struct device *dev, const struct zcan_frame *msg, mb->tx_callback = callback; mb->callback_arg = callback_arg; - k_sem_reset(&mb->tx_int_sem); /* mailbix identifier register setup */ mailbox->TIR &= CAN_TI0R_TXRQ; @@ -612,11 +601,6 @@ int can_stm32_send(struct device *dev, const struct zcan_frame *msg, mailbox->TIR |= CAN_TI0R_TXRQ; k_mutex_unlock(&data->inst_mutex); - if (callback == NULL) { - k_sem_take(&mb->tx_int_sem, K_FOREVER); - return mb->error_flags; - } - return 0; } diff --git a/drivers/can/can_stm32.h b/drivers/can/can_stm32.h index 7e9b03a2694c8..67b3159c0dd26 100644 --- a/drivers/can/can_stm32.h +++ b/drivers/can/can_stm32.h @@ -42,8 +42,6 @@ struct can_mailbox { can_tx_callback_t tx_callback; void *callback_arg; - struct k_sem tx_int_sem; - u32_t error_flags; }; diff --git a/include/drivers/can.h b/include/drivers/can.h index 00410184d4a99..f7cbd11de8609 100644 --- a/include/drivers/can.h +++ b/include/drivers/can.h @@ -325,6 +325,14 @@ struct can_driver_api { }; +/** @cond INTERNAL_HIDDEN */ +void can_common_isr_callback_handler(u32_t err, void *cb_arg); +struct can_send_wait { + u32_t err; + struct k_sem sem; +}; +/** @endcond */ + /** * @brief Perform data transfer to CAN bus. * @@ -355,7 +363,22 @@ static inline int z_impl_can_send(struct device *dev, const struct can_driver_api *api = (const struct can_driver_api *)dev->driver_api; - return api->send(dev, msg, timeout, callback_isr, callback_arg); + if (callback_isr) { + return api->send(dev, msg, timeout, callback_isr, callback_arg); + } else { + struct can_send_wait send_wait; + int ret; + + k_sem_init(&send_wait.sem, 0, 1); + ret = api->send(dev, msg, timeout, + can_common_isr_callback_handler, &send_wait); + if (ret != CAN_TX_OK) { + return ret; + } + + k_sem_take(&send_wait.sem, K_FOREVER); + return send_wait.err; + } } /*