diff options
| author | wdfk-prog <[email protected]> | 2025-09-27 09:42:02 +0800 |
|---|---|---|
| committer | R b b666 <[email protected]> | 2025-09-28 11:17:21 +0800 |
| commit | 11156de0de6bea4eb9090d162152caf2b352b232 (patch) | |
| tree | e0d564de7da98d2a8b2b9b068dd8c0dbcb82423c /bsp | |
| parent | ed574f693f512fbbeff994d494e36952e0659f07 (diff) | |
feat[can]: Implement non-blocking send mechanism and enhance CAN driver functionality
- Added support for non-blocking mode CAN message sending, including software ring buffer management and dynamic memory allocation options.
- Improved related comments and error handling.
- Updated example code to demonstrate the usage of both blocking and non-blocking sending modes, and corrected some structure field naming and macro definitions.
Diffstat (limited to 'bsp')
| -rw-r--r-- | bsp/stm32/libraries/HAL_Drivers/drivers/drv_can.c | 90 |
1 files changed, 85 insertions, 5 deletions
diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_can.c b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_can.c index da748590b0..196cc94a52 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_can.c +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_can.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2024 RT-Thread Development Team + * Copyright (c) 2006-2025, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -14,6 +14,7 @@ * 2021-02-02 YuZhe XU fix bug in filter config * 2021-8-25 SVCHAO The baud rate is configured according to the different APB1 frequencies. f4-series only. + * 2025-09-20 wdfk_prog Implemented sendmsg_nonblocking op to support framework's async TX. */ #include "drv_can.h" @@ -484,6 +485,21 @@ static rt_err_t _can_control(struct rt_can_device *can, int cmd, void *arg) return RT_EOK; } +/** + * @internal + * @brief Low-level function to send a CAN message to a specific hardware mailbox. + * + * This function is part of the **blocking** send mechanism. It is called by + * `_can_int_tx` after a hardware mailbox has already been acquired. Its role is + * to format the message according to the STM32 hardware requirements and place + * it into the specified mailbox for transmission. + * + * @param[in] can A pointer to the CAN device structure. + * @param[in] buf A pointer to the `rt_can_msg` to be sent. + * @param[in] box_num The specific hardware mailbox index (0, 1, or 2) to use for this tran + * + * @return `RT_EOK` on success, or an error code on failure. + */ static int _can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t box_num) { CAN_HandleTypeDef *hcan; @@ -586,6 +602,53 @@ static int _can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t } } +/** + * @internal + * @brief Low-level, hardware-specific non-blocking function to send a CAN message. + * + * This function interacts directly with the STM32 HAL library to add a message + * to a hardware TX mailbox. It returns immediately and does not wait for the + * transmission to complete. + * + * @param[in] can A pointer to the CAN device structure. + * @param[in] buf A pointer to the `rt_can_msg` to be sent. + * + * @return + * - `RT_EOK` if the message was successfully accepted by the hardware. + * - `-RT_EBUSY` if all hardware mailboxes are currently full. + * - `-RT_ERROR` on other HAL failures. + */ +static rt_ssize_t _can_sendmsg_nonblocking(struct rt_can_device *can, const void *buf) +{ + CAN_HandleTypeDef *hcan = &((struct stm32_can *) can->parent.user_data)->CanHandle; + struct rt_can_msg *pmsg = (struct rt_can_msg *) buf; + CAN_TxHeaderTypeDef txheader = {0}; + uint32_t tx_mailbox; + + if ((hcan->State != HAL_CAN_STATE_READY) && (hcan->State != HAL_CAN_STATE_LISTENING)) + return -RT_ERROR; + + if (HAL_CAN_GetTxMailboxesFreeLevel(hcan) == 0) + return -RT_EBUSY; + + txheader.DLC = pmsg->len; + txheader.RTR = (pmsg->rtr == RT_CAN_RTR) ? CAN_RTR_REMOTE : CAN_RTR_DATA; + txheader.IDE = (pmsg->ide == RT_CAN_STDID) ? CAN_ID_STD : CAN_ID_EXT; + if (txheader.IDE == CAN_ID_STD) + txheader.StdId = pmsg->id; + else + txheader.ExtId = pmsg->id; + + HAL_StatusTypeDef status = HAL_CAN_AddTxMessage(hcan, &txheader, pmsg->data, &tx_mailbox); + if (status != HAL_OK) + { + LOG_W("can sendmsg nonblocking send error %d", status); + return -RT_ERROR; + } + + return RT_EOK; +} + static int _can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t fifo) { HAL_StatusTypeDef status; @@ -645,10 +708,11 @@ static int _can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t fifo) static const struct rt_can_ops _can_ops = { - _can_config, - _can_control, - _can_sendmsg, - _can_recvmsg, + .configure = _can_config, + .control = _can_control, + .sendmsg = _can_sendmsg, + .recvmsg = _can_recvmsg, + .sendmsg_nonblocking = _can_sendmsg_nonblocking, }; static void _can_rx_isr(struct rt_can_device *can, rt_uint32_t fifo) @@ -788,6 +852,22 @@ static void _can_sce_isr(struct rt_can_device *can) hcan->Instance->MSR |= CAN_MSR_ERRI; } +/** + * @internal + * @brief The low-level ISR for CAN TX events on STM32. + * + * This function's sole responsibility is to check the hardware status flags + * to determine which mailbox completed a transmission and whether it was + * successful or failed. It then reports the specific event to the upper + * framework layer via `rt_hw_can_isr()`. + * + * @note This ISR contains NO framework-level logic (e.g., buffer handling). + * It is a pure hardware event reporter, ensuring a clean separation + * of concerns between the driver and the framework. + * + * @param[in] can A pointer to the CAN device structure. + * @return void + */ static void _can_tx_isr(struct rt_can_device *can) { CAN_HandleTypeDef *hcan; |
