Skip to content

Air001 串口 _tx_complete_irq 返回0时,串口仍未完成最终发送 #110

@createskyblue

Description

@createskyblue

描述一下这个bug / Describe the bug

我想魔改HardwareSerial.cpp 以实现软件流控,发现函数_tx_complete_irq在返回0后,串口数据仍然没有传输完成,串口有波形输出

复现步骤 / To Reproduce

魔改HardwareSerial.cpp的部分内容如下:

int HardwareSerial::_tx_complete_irq(serial_t *obj)
{
  size_t remaining_data;
  // previous HAL transfer is finished, move tail pointer accordingly
  obj->tx_tail = (obj->tx_tail + obj->tx_size) % SERIAL_TX_BUFFER_SIZE;

  // If buffer is not empty (head != tail), send remaining data
  if (obj->tx_head != obj->tx_tail)
  {
    remaining_data = (SERIAL_TX_BUFFER_SIZE + obj->tx_head - obj->tx_tail) % SERIAL_TX_BUFFER_SIZE;
    // Limit the next transmission to the buffer end
    // because HAL is not able to manage rollover
    obj->tx_size = min(remaining_data,
                       (size_t)(SERIAL_TX_BUFFER_SIZE - obj->tx_tail));
                       //开启软流控信号
    uart_attach_tx_callback(obj, _tx_complete_irq, obj->tx_size);
    return -1;
  }

  //流控信号进入接收状态
  if (obj->pin_rts != NC)
    digitalWrite(obj->pin_rts, LOW);

  return 0;
}

size_t HardwareSerial::write(const uint8_t *buffer, size_t size)
{
  size_t size_intermediate;
  size_t ret = size;
  size_t available = availableForWrite();
  size_t available_till_buffer_end = SERIAL_TX_BUFFER_SIZE - _serial.tx_head;

  _written = true;
  if (isHalfDuplex())
  {
    if (_rx_enabled)
    {
      _rx_enabled = false;
      uart_enable_tx(&_serial);
    }
  }

  // If the output buffer is full, there's nothing for it other than to
  // wait for the interrupt handler to free space
  while (!availableForWrite())
  {
    // nop, the interrupt handler will free up space for us
  }

  // HAL doesn't manage rollover, so split transfer till end of TX buffer
  // Also, split transfer according to available space in buffer
  while ((size > available_till_buffer_end) || (size > available))
  {
    size_intermediate = min(available, available_till_buffer_end);
    write(buffer, size_intermediate);
    size -= size_intermediate;
    buffer += size_intermediate;
    available = availableForWrite();
    available_till_buffer_end = SERIAL_TX_BUFFER_SIZE - _serial.tx_head;
  }

  // Copy data to buffer. Take into account rollover if necessary.
  if (_serial.tx_head + size <= SERIAL_TX_BUFFER_SIZE)
  {
    memcpy(&_serial.tx_buff[_serial.tx_head], buffer, size);
    size_intermediate = size;
  }
  else
  {
    // memcpy till end of buffer then continue memcpy from beginning of buffer
    size_intermediate = SERIAL_TX_BUFFER_SIZE - _serial.tx_head;
    memcpy(&_serial.tx_buff[_serial.tx_head], buffer, size_intermediate);
    memcpy(&_serial.tx_buff[0], buffer + size_intermediate,
           size - size_intermediate);
  }

  // Data are copied to buffer, move head pointer accordingly
  _serial.tx_head = (_serial.tx_head + size) % SERIAL_TX_BUFFER_SIZE;

  //开启软流控信号
  if (_serial.pin_rts != NC)
    digitalWrite(_serial.pin_rts, HIGH);

  // Transfer data with HAL only is there is no TX data transfer ongoing
  // otherwise, data transfer will be done asynchronously from callback
  if (!serial_tx_active(&_serial))
  {
    // note: tx_size correspond to size of HAL data transfer,
    // not the total amount of data in the buffer.
    // To compute size of data in buffer compare head and tail
    _serial.tx_size = size_intermediate;
    uart_attach_tx_callback(&_serial, _tx_complete_irq, size_intermediate);
  }

  /* There is no real error management so just return transfer size requested*/
  return ret;
}

在setup()初始化串口的时候指定任意一个引脚作为rts引脚,比如:

Serial.begin(9600);
Serial.setRts(PB1);

最后发送任意数据,并观察流控信号和串口输出的波形

Serial.println("2333");

会发现“软流控”会在串口输出波形结束前,提前结束(具体查看截图)

如果正常,应该是什么样 / Expected behavior

如果正常,应该“软流控”应该在串口输出波形结束后从高电平变为低电平

截图 / Screenshots

PixPin_2024-06-28_21-13-48
PixPin_2024-06-28_21-13-32
image
image

日志 / Logs

不适用

系统 / System

Win10 22H2

PACK包版本 / Version

0.6.4

验证

  • 检查过该问题,之前没有人提过 / Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
  • 提供了最小可复现工程或详细的复现步骤,确保开发者可以复现 / The provided reproduction is a minimal reproducible example of the bug.
  • 已经提供了完整的报错信息、日志、截图,没有经过删减。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions