Задать вопрос
@Rarebeast666

В чем возникает проблема при работе с драйвером порта — UART4?

Драйвер последовательно порта UART4 (w-apb-uart) - UART4 имеет только две линии - Rx и Tx.

Используется ядро 6.5.8.

Процессор Allwinner A40i.

Это именно RS485, UART подключен к микросхеме трансивера RS485. Пин RTS используется для организации полудуплексной передачи.

TxRx Diagram - https://postimg.cc/BjVnxhD0

DTS:
В DTS файле он UART переопределен:
&uart4 {
pinctrl-names = "default";
compatible = "snps,dw-apb-uart";
pinctrl-0 = <&uart4_ph_pins>;
rts-gpios = <&pio 7 13 GPIO_ACTIVE_HIGH>; //PH13
//rs485-rts-delay = <0 200>;
linux,rs485-enabled-at-boot-time;
status = "okay";
};

Порт GPIO PH13 используется в качестве RTS пина (это не аппаратный RTS).

В дереве устройств на четвертом порту мы включаем режим (linux,rs485-enabled-at-boot-time).

НАШИ ДЕЙСТВИЯ:
Открываем порт (с помощью SCREEN) - прием происходит нормально.
Но как только отсылаем первую строку или символ, происходит зависание порта, сразу после первой отсылки (она успешная, она приходит).
При отсылке порт становится в положение HIGH, но после неё не возвращается в положение LOW. Порт перестает работать и на прием и на передачу.

Скорости использовали разные - 9600 до 115200, не влияет на поведение порта.

При копании в глубинах драйвера порта (/linux-6.5.8/drivers/tty/serial/8250/8250_dw.c) и попытках отладить, выяснилось, что если вставить вывод в консоль //dev_err() или dev_info() - всё начинает работать, но при этом начинают приходить сообщения в консоль от портов.

Функция static int dw8250_handle_irq(struct uart_port *p) вызывает:
int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
{
struct uart_8250_port *up = up_to_u8250p(port);
struct tty_port *tport = &port->state->port;
bool skip_rx = false;
unsigned long flags;
u16 status;

if (iir & UART_IIR_NO_INT)
return 0;

//dev_err(port->dev, "Handle irq before breakpoint \n");//qq

spin_lock_irqsave(&port->lock, flags);

status = serial_lsr_in(up);

/*
* If port is stopped and there are no error conditions in the
* FIFO, then don't drain the FIFO, as this may lead to TTY buffer
* overflow. Not servicing, RX FIFO would trigger auto HW flow
* control when FIFO occupancy reaches preset threshold, thus
* halting RX. This only works when auto HW flow control is
* available.
*/
if (!(status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS)) &&
(port->status & (UPSTAT_AUTOCTS | UPSTAT_AUTORTS)) &&
!(port->read_status_mask & UART_LSR_DR))
skip_rx = true;

if (status & (UART_LSR_DR | UART_LSR_BI) && !skip_rx) {
if (irqd_is_wakeup_set(irq_get_irq_data(port->irq)))
pm_wakeup_event(tport->tty->dev, 0);
if (!up->dma handle_rx_dma(up, iir))
status = serial8250_rx_chars(up, status);
}

serial8250_modem_status(up);
if ((status & UART_LSR_THRE) && (up->ier & UART_IER_THRI)) {
if (!up->dma up->dma->tx_err)
serial8250_tx_chars(up);
else if (!up->dma->tx_running)
__stop_tx(up);
}

uart_unlock_and_check_sysrq_irqrestore(port, flags);

return 1;
}

Если вывод dev_err() поставить перед spin_lock_irqsave(&port->lock, flags); то всё работает. Если после - то не работает, происходит spin_lock порта и в дальнейшем он не освобождается, происходит dead_lock.
uart_unlock_and_check_sysrq_irqrestore(port, flags); - не отрабатывает.

ВОПРОС:
Как решить проблему, чтобы порт работал адекватно, без отправок в консоль сообщений от портов? Виноват драйвер?
  • Вопрос задан
  • 478 просмотров
Подписаться 3 Сложный Комментировать
Пригласить эксперта
Ответы на вопрос 2
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
Речь идет именно о RS485, UART подключен к микросхеме трансивера RS485. Пин RTS используется для организации полудуплексной передачи.

Ок, я проглядел это место, давай попробуем ещё раз.

Если вывод dev_err() поставить перед spin_lock_irqsave(&port->lock, flags); то всё работает.

Верно ли, что когда всё работает (со вставленным dev_err), serial8250_em485_stop_tx вызывается после передачи только из serial8250_console_write, а когда всё не работает эта функция не вызывается вообще?

Глядя в функцию serial8250_handle_irq я вижу, что обработка окончания передачи зависит от того, используется DMA или нет. Используется ли в вашей конфигурации DMA? Работает ли передача, если DMA отключить?
Ответ написан
@pfg21
ex-турист
вообще зачем использовать пин RTS для управления передаче 485 ?? у него несколько другое предназначение согласно 232 протоколу и реакция драйвера соответвующая.
его используют при работе с COM-портом обычного компутера, просто потому что gpio в обычном компутере просто нет.

не проще ли использовать отдельный пин, который включать перед передачей и выключать сразу после окончания передачи.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы