Arduino-AirMCU
Arduino-AirMCU copied to clipboard
Air001 串口 _tx_complete_irq 返回0时,串口仍未完成最终发送
描述一下这个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
日志 / Logs
不适用
系统 / System
Win10 22H2
PACK包版本 / Version
0.6.4
验证
- [X] 检查过该问题,之前没有人提过 / Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
- [X] 提供了最小可复现工程或详细的复现步骤,确保开发者可以复现 / The provided reproduction is a minimal reproducible example of the bug.
- [X] 已经提供了完整的报错信息、日志、截图,没有经过删减。