* @brief Serial receive data routines, This function will receive * data by using fifo * * @note In blocking mode, the function will wait until the specified amount of data is received or until a timeout occurs. * In non-blocking mode, the function will immediately attempt to retrieve as much data as possible from the ring buffer and return. * * @param dev The pointer of d
| 472 | * @return Returns the actual length of data received. |
| 473 | */ |
| 474 | static rt_ssize_t _serial_fifo_rx(struct rt_device *dev, |
| 475 | rt_off_t pos, |
| 476 | void *buffer, |
| 477 | rt_size_t size) |
| 478 | { |
| 479 | struct rt_serial_device *serial; |
| 480 | struct rt_serial_rx_fifo *rx_fifo; |
| 481 | rt_base_t level; |
| 482 | rt_size_t recv_size = 0; |
| 483 | |
| 484 | if (size == 0) return 0; |
| 485 | RT_ASSERT(dev != RT_NULL && buffer != RT_NULL); |
| 486 | |
| 487 | serial = (struct rt_serial_device *)dev; |
| 488 | rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx; |
| 489 | |
| 490 | if (dev->open_flag & RT_SERIAL_RX_BLOCKING) |
| 491 | { |
| 492 | rt_size_t data_len; |
| 493 | rt_tick_t delta_tick; |
| 494 | rt_size_t rx_bufsz_third = serial->config.rx_bufsz / 2; |
| 495 | rt_int32_t base_rx_timeout = rt_atomic_load(&rx_fifo->rx_timeout); |
| 496 | rt_int32_t rx_timeout_left = base_rx_timeout; |
| 497 | rt_tick_t begin_tick = rt_tick_get(); |
| 498 | |
| 499 | while (1) |
| 500 | { |
| 501 | if (rx_timeout_left != RT_WAITING_NO) |
| 502 | { |
| 503 | level = rt_spin_lock_irqsave(&serial->spinlock); |
| 504 | data_len = rt_ringbuffer_data_len(&rx_fifo->rb); |
| 505 | if (data_len < size - recv_size) |
| 506 | { |
| 507 | if (size - (recv_size + data_len) >= rx_bufsz_third) |
| 508 | { |
| 509 | rx_fifo->rx_cpt_index = rx_bufsz_third; |
| 510 | } |
| 511 | else |
| 512 | { |
| 513 | rx_fifo->rx_cpt_index = size - (recv_size + data_len); |
| 514 | } |
| 515 | rt_completion_wait(&rx_fifo->rx_cpt, 0); |
| 516 | } |
| 517 | rt_spin_unlock_irqrestore(&serial->spinlock, level); |
| 518 | } |
| 519 | |
| 520 | level = RT_SERIAL_FIFO_LOCK(&serial->spinlock); |
| 521 | recv_size += rt_ringbuffer_get(&rx_fifo->rb, (rt_uint8_t *)buffer + recv_size, size - recv_size); |
| 522 | RT_SERIAL_FIFO_UNLOCK(&serial->spinlock, level); |
| 523 | if (recv_size == size || rx_timeout_left == RT_WAITING_NO) |
| 524 | { |
| 525 | break; |
| 526 | } |
| 527 | |
| 528 | rt_completion_wait(&rx_fifo->rx_cpt, rx_timeout_left); |
| 529 | if (rx_timeout_left != RT_WAITING_FOREVER) |
| 530 | { |
| 531 | delta_tick = rt_tick_get_delta(begin_tick); |
no test coverage detected