* @internal * @brief Internal implementation of non-blocking CAN transmission. * * This function iterates through a buffer of CAN messages and attempts to send each one * using a non-blocking strategy. It first tries to send directly via hardware (fast path). * If the hardware is busy, it enqueues the message into a software ring buffer (slow path). * This function is thread-safe and ISR-saf
| 336 | * @return The number of bytes successfully sent or enqueued for later transmission. |
| 337 | */ |
| 338 | static rt_ssize_t _can_nonblocking_tx(struct rt_can_device *can, const struct rt_can_msg *pmsg, rt_size_t size) |
| 339 | { |
| 340 | rt_ssize_t sent_size = 0; |
| 341 | rt_base_t level; |
| 342 | |
| 343 | if (can->ops->sendmsg_nonblocking == RT_NULL) |
| 344 | { |
| 345 | return -RT_EINVAL; |
| 346 | } |
| 347 | |
| 348 | while (sent_size < size) |
| 349 | { |
| 350 | if (can->ops->sendmsg_nonblocking(can, pmsg) == RT_EOK) |
| 351 | { |
| 352 | pmsg++; |
| 353 | sent_size += sizeof(struct rt_can_msg); |
| 354 | continue; |
| 355 | } |
| 356 | |
| 357 | level = rt_hw_local_irq_disable(); |
| 358 | if (rt_ringbuffer_space_len(&can->nb_tx_rb) >= sizeof(struct rt_can_msg)) |
| 359 | { |
| 360 | rt_ringbuffer_put(&can->nb_tx_rb, (rt_uint8_t *)pmsg, sizeof(struct rt_can_msg)); |
| 361 | rt_hw_local_irq_enable(level); |
| 362 | |
| 363 | pmsg++; |
| 364 | sent_size += sizeof(struct rt_can_msg); |
| 365 | } |
| 366 | else |
| 367 | { |
| 368 | /* Buffer is full, cannot process this message or subsequent ones. */ |
| 369 | can->status.dropedsndpkg += (size - sent_size) / sizeof(struct rt_can_msg); |
| 370 | rt_hw_local_irq_enable(level); |
| 371 | break; |
| 372 | } |
| 373 | } |
| 374 | |
| 375 | return sent_size; |
| 376 | } |
| 377 | |
| 378 | /** |
| 379 | * @internal |
no test coverage detected