Air-duino / Arduino-AirMCU

Arduino core for the Air MCU.
https://arduino.luatos.com/
MIT License
69 stars 21 forks source link

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

Open createskyblue opened 3 months ago

createskyblue commented 3 months ago

描述一下这个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

验证

LuaRobot commented 3 months ago

⚠ 你的Issue可能缺少了一些信息,请自觉补全,以证明issue内容的真实性:

⚠ Your issue may be missing some information, please complete it to prove the authenticity of the content of the issue: