Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
3 tasks done
createskyblue opened this issue Jun 28, 2024 · 1 comment
Open
3 tasks done

Comments

@createskyblue
Copy link

描述一下这个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.
  • 已经提供了完整的报错信息、日志、截图,没有经过删减。
@LuaRobot
Copy link

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

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

  • ❌未提供出错时需要的日志文件 does not provide logs when bug happening

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants