Представляет интерфейс и использование драйвера UART в ядре Linux и предоставляет справку для пользователей устройств UART.
Таблица 1-1: Список применимой продукции
Версия ядра | файл драйвера |
---|---|
Linux-4.9 и выше | sunxi-uart.c |
Драйвер UART и разработчики/сопровождающие прикладного уровня.
В ядре Linux структура драйвера UART показана на рисунке 1, который можно разделить на три уровня:
Рисунок 2-1: Схема архитектуры UART Linux.
Таблица 2-1: Знакомство с терминами, относящимися к модулю UART
термин | Объяснение |
---|---|
Sunxi | Относится к серии аппаратных платформ SoC Allwinner. |
UART | Универсальный асинхронный приемник/передатчик, Универсальный асинхронный приемник и передатчик |
Console | Консоль — устройство TTY, используемое в ядре Linux для вывода отладочной информации. |
TTY | TeleType/TeleTypewriters — это старая аббревиатура, которая первоначально относилась к телетайпам, а теперь обычно относится к терминальному оборудованию, подключенному к последовательному порту компьютера. К устройствам TTY также относятся виртуальные консоли, последовательные порты и псевдотерминальные устройства. |
linux4.9
|-- drivers
| |-- tty
| | |-- serial
| | |-- serial_core.c
| | |-- sunxi-uart.c
| | |-- sunxi-uart.h
В каталоге верхнего уровня Longan выполните ./build.sh menuconfig (сначала вам необходимо выполнить ./build.sh config), чтобы войти в основной интерфейс конфигурации, и выполните следующие шаги: Сначала выберите параметр «Драйверы устройств», чтобы войти Конфигурация следующего уровня, как показано на рисунке ниже:
Рисунок 3-1: Корневое меню конфигурации ядра.
Выберите Символьные устройства и введите конфигурацию нижнего уровня, как показано на рисунке ниже:
Рисунок 3-2: Меню драйверов устройств меню конфигурации ядра
Выберите «Последовательные драйверы» и введите конфигурацию нижнего уровня, как показано на рисунке ниже:
Рисунок 3-3. Меню конфигурации ядра. Меню символьных драйверов.
Выберите контроллер SUNXI UART и консоль на параметрах порта SUNXI UART, как показано ниже:
Рисунок 3-4: Меню конфигурации ядра sunxi uart
Если вам нужен UART для поддержки передачи DMA, вы можете включить опцию SUNXI UART USE DMA.
• Конфигурация файла дерева устройств SoC Общая конфигурация для всех сценариев, для ARM64 CPU Например, путь к дереву устройств находится в каталоге ядра: Arch/arm64/boot/dts/sunxi/sun*.dtsi.
• Конфигурация файла дерева устройств SoC Общая конфигурация для всех сценариев, для ARM32 CPU Например, путь к дереву устройств находится в каталоге ядра: Arch/arm/boot/dts/sun*.dtsi.
• Дерево устройств уровня платы (board.dts) Путь:/device/config/chips/{IC}/configs/{BOARD}/board.dts. устройство tree Взаимосвязь структуры исходного кода следующая:
device tree Взаимосвязь структуры исходного кода следующая:
linux-4.9
board.dts
|--------sun*.dtsi
|------sun*-pinctrl.dtsi
|------sun*-clk.dtsi
linux-5.4
board.dts
|-------sun*.dtsi
Общая конфигурация Linux-4.9 выглядит следующим образом:
/ {
model = "sun*";
compatible = "arm,sun*";
interrupt-parent = <&wakeupgen>;
#address-cells = <2>;
#size-cells = <2>;
aliases {
serial0 = &uart0;
serial1 = &uart1;
serial2 = &uart2;
serial3 = &uart3;
serial4 = &uart4;
serial5 = &uart5;
...
};
uart0: uart@05000000 {
compatible = "allwinner,sun50i-uart"; /* Для вождения иоборудование обязательное */
device_type = "uart0"; /* оборудованиетип*/
reg = <0x0 0x05000000 0x0 0x400>; /* оборудованиеиспользоватьиз базовый адрес и диапазон регистров */
interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>; /* оборудованиеиспользоватьиз Номер аппаратного прерывания*/ clocks = <&clk_uart0>; /* оборудованиеиспользоватьизчасы*/ pinctrl-names = "default", "sleep";
pinctrl-0 = <&uart0_pins_a>; /* оборудование В нормальных условияхиспользоватьизpinступня*/ pinctrl-1 = <&uart0_pins_b>; /* оборудованиев состоянии снаиспользоватьизpinступня*/ uart0_port = <0>; /* Контроллер uart должен иметь уникальный номер порта, который не может повторяться с другими контроллерами uart*/
uart0_type = <2>; /* номер линии контроллера UART, значение 2/4/8*/
use_dma = <0>; /* Использовать ли DMA Способ передачи, 0: Не давать. возможность,1:Толькодавать возможностьTX,2:Толькодавать возможностьRX,3: начать Использовать передачу с приемом*/
status = "okay"; /* Включить ли этот узел*/
};
Общая конфигурация Linux-5.4 выглядит следующим образом:
uart0: uart@5000000 {
compatible = "allwinner,sun50i-uart";
device_type = "uart0";
reg = <0x0 0x05000000 0x0 0x400>;
interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
sunxi,uart-fifosize = <64>;
clocks = <&ccu CLK_BUS_UART0>; /* оборудованиеиспользоватьизчасы */
clock-names = "uart0";
resets = <&ccu RST_BUS_UART0>; /* оборудованиеresetчасы */
pinctrl-names = "default", "sleep";
pinctrl-0 = <&uart0_pins_a>;
pinctrl-1 = <&uart0_pins_b>;
uart0_port = <0>;
uart0_type = <2>;
dmas = <&dma 14>; /* 14поверхность ПоказыватьDRQ */
dma-names = "tx";
use_dma = <0>; /* Использовать ли DMA Способ передачи, 0: Не давать. возможность,1:Толькодавать возможностьTX,2:Толькодавать возможностьRX,3:давать возможностьTX с приемом */
};
Настройте каждый контроллер UART в дереве устройств. Контроллер UART соответствует узлу UART. Значение атрибутов узла см. в примечаниях. Чтобы отличить каждый контроллер UART в коде драйвера UART, вам необходимо отличить каждый из них в узле псевдонимов в дереве устройств. Узлы UART определяют псевдонимы, как показано в узле псевдонимов выше. Форма псевдонима — строка «serial» плюс последовательный номер. В драйвере UART вы можете получить цифровой номер соответствующего контроллера UART через функцию of_alias_get_id(), тем самым различая каждый контроллер UART.
board.dts используется для сохранения информации об устройстве каждой платформы уровня платы (например, демонстрационная плата, плата demo2.0 и т. д.). Путь board.dts следующий: /device/config/chips/{IC}. /configs/{BOARD}/board.dts.
Если информация о конфигурации в Board.dts существует в *.dtsi (например, sun50iw9p1.dtsi и т. д.), будут существовать следующие правила переопределения:
Простая настройка uart в board.dts выглядит следующим образом:
soc@03000000 {
...
&uart0 {
uart-supply = <reg_dcdc1>; /* IOиспользоватьизэлектричество */
status = "okay";
};
&uart1 {
status = "okay";
};
...
}
Рисунок 3-5: Меню конфигурации ядра sunxi uart
Конфигурация Linux-4.9 следующая:
uart1: uart@05000400 {
...
use_dma = <3>; /* Использовать ли DMA Способ передачи, 0: Не давать. возможность,1:Толькодавать возможностьTX,2:Толькодавать возможностьRX,3:давать возможностьTX с приемом */
status = "okay";
};
Конфигурация Linux-5.4 следующая:
uart0: uart@5000000 {
...
dmas = <&dma 14>; /* 14поверхность ПоказыватьDRQ, Посмотреть ДМА spec */
dma-names = "tx";
use_dma = <0>; /* Использовать ли DMA Способ передачи, 0: Не давать. возможность,1:Толькодавать возможностьTX,2:Толькодавать возможностьRX,3:давать возможностьTX с приемом
*/
};
uart1: uart@05000400 {
compatible = "allwinner,sun50i-uart";
device_type = "uart1";
reg = <0x0 0x05000400 0x0 0x400>;
interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk_uart1>;
pinctrl-names = "default", "sleep";
pinctrl-0 = <&uart1_pins_a>;
pinctrl-1 = <&uart1_pins_b>;
uart1_port = <1>;
uart1_type = <4>;
status = "okay"; /* УбедитьсяUart включен */
};
console=ttyS1,115200
иллюстрировать:
ttyS0 <===> uart0
ttyS1 <===> uart1
...
3.2.5 Установка скорости передачи данных UART
На разных аппаратных платформах Sunxi выбор источника синхронизации и конфигурация контроллера UART немного различаются. Общая зависимость тактовой частоты следующая:
Рисунок 3-6: Описание часов
Контроллер UART разделит входной источник тактовой частоты и, наконец, выдаст тактовый сигнал с частотой, которая соответствует (или приблизительно соответствует) скорости передачи данных UART. Обычно используемые стандартные скорости передачи данных для UART:
#define B4800 0000014
#define B9600 0000015
#define B19200 0000016
#define B38400 0000017
#define B57600 0010001
#define B115200 0010002
#define B230400 0010003
#define B460800 0010004
#define B500000 0010005
#define B576000 0010006
#define B921600 0010007
#define B1000000 0010010
#define B1152000 0010011
#define B1500000 0010012
#define B2000000 0010013
#define B2500000 0010014
#define B3000000 0010015
#define B3500000 0010016
#define B4000000 0010017
Коэффициент деления частоты тактового сигнала UART является целым числом, кратным 16, и в делении частоты неизбежно будут возникать ошибки. Следовательно, достаточно ли точна скорость передачи данных выходного устройства UART, в значительной степени зависит от входного тактового сигнала. частота источника. Что касается энергопотребления, драйверы UART обычно используют источник синхронизации 24M по умолчанию. Однако, в зависимости от сценария приложения, иногда нам необходимо переключиться на другие источники синхронизации по двум причинам:
Соотношение между соответствующими частотными точками каждой скорости передачи данных UART следующее:
Рисунок 3-7: Зависимость скорости передачи данных
Например, вам необходимо настроить скорость передачи данных uart2 на 460800. Как видно из приведенной выше таблицы взаимосвязей, соответствующие часы составляют 30M, 37,5M, 42,857M, 46,153M и 50M и т. д., поэтому вам необходимо изменить часы uart2 в дереве устройств:
linux-4.9 меняет скорость передачи данных следующим образом:
device_type = "uart2";
reg = <0x0 0x05000800 0x0 0x400>;
interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk_uart2>;
+ clocks = <&clk_uart2>, <&clk_apb2>, <&clk_psi>;
+ clock-frequency = <50000000>;
pinctrl-names = "default", "sleep";
В некоторых случаях APB2 может быть не в состоянии точно разделить тактовую частоту 30M или 37,5M, поэтому здесь мы выбираем настройку тактовой частоты 50M.
Если мы изменим тактовую частоту APB2, это может повлиять на uart0, и при запуске последовательного порта появятся искаженные символы, поэтому нам лучше настроить тактовую частоту uart0 на частоту 50M.
device_type = "uart0";
reg = <0x0 0x05000000 0x0 0x400>;
interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk_uart0>;
+ clocks = <&clk_uart0>, <&clk_apb2>, <&clk_psi>;
+ clock-frequency = <50000000>;
pinctrl-names = "default", "sleep";
linux-5.4 меняет скорость передачи следующим образом:
device_type = "uart2";
reg = <0x0 0x05000800 0x0 0x400>;
interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk_uart2>;
+ clocks = <&ccu CLK_BUS_UART0>,
+ <&ccu CLK_APB2>,
+ <&ccu CLK_PSI_AHB1_AHB2>;
+ clock-frequency = <50000000>;
pinctrl-names = "default", "sleep";
иллюстрировать
Исправлять APB2 автобусные часы, повлияет на использование APB2 Соответствующий модуль для шинных часов.
На разных аппаратных платформах Sunxi контроллер UART разделен на домен CPUX и домен CPUS в соответствии с доменом питания. Система по умолчанию настроит контроллер uart домена CPUX, но может не поддерживать контроллер uart CPUS. Если вы хотите использовать UART домена CPUS через CPUX, выполните следующие действия для получения поддержки:
/ {
soc@03000000{
r_pio: pinctrl@07022000 {
...
/* КонфигурацияCPUSдоменuart контактная информация */
s_uart0_pins_a: s_uart0@0 {
allwinner,pins = "PL2", "PL3";
allwinner,function = "s_uart0";
allwinner,muxsel = <2>;
allwinner,drive = <1>;
allwinner,pull = <1>;
};
...
};
...
};
clk_suart0: suart0 {
#clock-cells = <0>;
compatible = "allwinner,periph-cpus-clock";
clock-output-names = "suart0";
};
aliases {
serial0 = &uart0;
...
serial5 = &uart5; //Добавляем псевдоним uart5из, необходимо добавить
};
uart0:uart@05000000 {
};
....
/* Добавить uartИнформация о контроллере , необходимо добавить, конкретное значение атрибута см. выше */
uart5: uart@07080000 {
compatible = "allwinner,sun8i-uart";
device_type = "uart5";
reg = <0x0 0x07080000 0x0 0x400>;
interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk_suart0>;
pinctrl-names = "default", "sleep";
pinctrl-1 = <&s_uart0_pins_a>;
uart5_port = <5>;
uart5_type = <2>;
status = "okay";
};
static const struct sunxi_desc_pin *_r_pins[] = {
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 0),
...
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 2),
...
SUNXI_FUNCTION(0x2, "s_uart0"), //Если нет, добавляем его
...
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 3),
...
SUNXI_FUNCTION(0x2, "s_uart0"), //Если нет, добавляем его
...
};
/* clk-*.h */
#define CPUS_UART_GATE 0x018C
/* clk-*.c */
static const char *suart_parents[] = {"cpurapbs2"};
SUNXI_CLK_PERIPH(suart0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
CPUS_UART_GATE, CPUS_UART_GATE, 0, 0, 16, 0,
0, &clk_lock, NULL, 0);
struct periph_init_data sunxi_periphs_cpus_init[] = {
...
{"suart0", 0, suart_parents,
ARRAY_SIZE(suart_parents), &sunxi_clk_periph_suart0 },
};
Драйвер UART зарегистрирует и сгенерирует устройство последовательного порта /dev/ttySx. Чтобы использовать уровень приложения, вам нужно всего лишь следовать стандартному методу программирования последовательного порта в системе Linux.
Используйте стандартные функции открытия файлов:
int open(const char *pathname, int flags);
int close(int fd);
Заголовочные файлы должны быть заключены в кавычки:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
Также используйте стандартные функции чтения и записи файлов:
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
Заголовочные файлы должны быть заключены в кавычки:
#include <unistd.h>
Атрибуты последовательного порта включают скорость передачи данных, биты данных, стоповые биты, биты четности, управление потоком и т. д. Эта часть представляет собой уникальный интерфейс устройства последовательного порта. Структура данных termios атрибутов последовательного порта определяется следующим образом: (terminos.h).
#define NCCS 19
struct termios {
tcflag_t c_iflag; /* input mode flags */
tcflag_t c_oflag; /* output mode flags */
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_line; /* line discipline */
cc_t c_cc[NCCS]; /* control characters */
};
Среди них константа флага c_iflag определяется следующим образом:
логотип | иллюстрировать |
---|---|
IGNBRK | Игнорировать статус BREAK на входе. |
BRKINT | Если установлен IGNBRK, BREAK будет игнорироваться. Если он не установлен, но установлен BRKINT, то BREAK приведет к очистке очередей ввода и вывода. Если терминал является управляющим терминалом группы процессов переднего плана, все процессы в этой группе процессов получат сигнал SIGINT. Если ни IGNBRK, ни BRKINT не установлены, BREAK рассматривается как синоним символа NUL, если только не установлен PARMRK, и в этом случае он рассматривается как последовательность \377 \0 \0. |
IGNPAR | Ошибки кадра и ошибки четности игнорируются. |
PARMRK | Если IGNPAR не установлен, \377 \0 вставляется перед символами с ошибками четности или кадра. Если ни IGNPAR, ни PARMRK не установлены, символы с ошибками четности или ошибками кадра обрабатываются как \0. |
INPCK | Включить определение входной четности. |
ISTRIP | Удалите восьмой бит. |
INLCR | Переведите NL на входе в CR. |
IGNCR | Игнорировать возврат каретки при вводе. |
ICRNL | Перевести возвраты каретки во входных данных на новые строки (если не установлен IGNCR). |
IUCLC | (Не POSIX) Сопоставляет входные прописные буквы со строчными. |
IXON | Включает управление потоком вывода XON/XOFF. |
IXANY | (Не является частью POSIX.1; XSI) Позволяет любому символу перезапустить вывод. |
IXOFF | Включает управление потоком ввода XON/XOFF. |
IMAXBEL | (Не POSIX) Вызов нуля, когда входная очередь заполнена. Linux не реализует этот бит и всегда считает его установленным. |
Константа излоготип c_oflag определяется следующим образом:
логотип | иллюстрировать |
---|---|
OLCUC | (Не POSIX) Сопоставляет строчные буквы в выводе с прописными буквами. |
ONLCR | (XSI) Сопоставляет символы новой строки в выводе с переводами строк с возвратом каретки. |
OCRNL | Сопоставляет возврат каретки при выводе с символами новой строки. |
ONOCR | Не печатайте возврат каретки в столбце 0. |
ONLRET | Возврат каретки не выводится. |
OFILL | Отправляйте символы заполнения в качестве задержки вместо использования времени для задержки. |
OFDEL | (Не POSIX) Символ заполнения — ASCII DEL (0177). Если не установлено, символом заполнения будет ASCII NUL. |
NLDLY | Маска задержки новой строки. Значения NL0 и NL1. |
CRDLY | Маска задержки возврата каретки. Значение: CR0, CR1, CR2 или CR3. |
TABDLY | Маска задержки горизонтальной табуляции. Значения: TAB0, TAB1, TAB2, TAB3 (или XTABS). Значением является TAB3, то есть XTABS, при котором табуляция будет расширяться до пробелов (каждый символ табуляции заполняется 8 пробелами). |
BSDLY | Маска задержки возврата. Значение — BS0 или BS1. (Никогда не реализовано). |
VTDLY | Маска задержки вертикальной табуляции. Значение VT0 или VT1. |
FFDLY | Маска задержки ввода таблицы. Значение — FF0 или FF1. |
Константа излоготип c_cflag определяется следующим образом:
логотип | иллюстрировать |
---|---|
CBAUD | (Не POSIX) Маска скорости передачи данных (4+1 бит). |
CBAUDEX | (Не POSIX) Расширенная маска скорости передачи данных (1 бит), содержащаяся в CBAUD. (POSIX указывает, что скорость передачи данных хранится в структуре termios, и не указывает точное ее местоположение, но предоставляет функции cfgetispeed() и cfsetispeed() для доступа к ней. Некоторые системы используют выбранный бит CBAUD в c_cflag, другие системы используют отдельные переменные, такие как sg_ispeed и sg_ospeed). |
CSIZE | Маска длины символов. Значение: CS5, CS6, CS7 или CS8. |
CSTOPB | Установите два стоповых бита вместо одного. |
CREAD | Откройте ресивер. |
PARENB | Позволяет выходным данным генерировать информацию о четности, а также информацию о четности входных данных. |
PARODD | Вход и выход имеют нечетную четность. |
HUPCL | После того, как последний процесс завершит работу устройства, опустите линию управления модемом (повесьте трубку). |
CLOCAL | Игнорируйте линии управления модемом. |
LOBLK | (Не POSIX) Блокировать вывод из слоев, отличных от текущей оболочки (для shl). |
CIBAUD | (Не POSIX) Маска скорости ввода. Биты CIBAUD имеют то же значение, что и биты CBAUD, но сдвинуты влево на биты IBSHIFT. |
CRTSCTS | (не POSIX) Включить управление потоком RTS/CTS (аппаратное) |
Константа излоготип c_lflag определяется следующим образом:
логотип | иллюстрировать |
---|---|
ISIG | При получении символа INTR, QUIT, SUSP или DSUSP генерируется соответствующий сигнал. |
ICANON | Включите канонический режим. Допускаются специальные символы EOF, EOL, EOL2, ERASE, KILL, LNEXT, REPRINT, STATUS и WERASE, а также построчная буферизация. |
XCASE | (Не POSIX; не поддерживается в Linux). Если также установлен ICANON, терминал записывается только в верхнем регистре. Ввод преобразуется в нижний регистр, за исключением символов с префиксом . При выводе символы верхнего регистра имеют префикс, а символы нижнего регистра преобразуются в верхний регистр. |
ECHO | Повторите вводимые символы. |
ECHOE | Если также установлен ICANON, символы ERASE стирают предыдущий введенный символ, а символы WERASE стирают предыдущее слово. |
ECHOK | Если также установлен ICANON, символ KILL удаляет текущую строку. |
ECHONL | Если также установлен ICANON, символы NL отображаются, даже если ECHO не установлен. |
ECHOCTL | (Не является частью POSIX) Если также установлено ECHO, управляющие сигналы ASCII, отличные от TAB, NL, START и STOP, отображаются как ˆX, где X — это код ASCII, на 0x40 больший, чем управляющий сигнал. Например, символ 0x08 (BS) отображается как ˆH. |
ECHOPRT | (Не POSIX) Если установлены и ICANON, и IECHO, символы печатаются по мере их удаления. |
ECHOKE | (Не POSIX) Если также установлен ICANON, при выполнении команды echo KILL будет удален каждый символ в строке, как если бы были указаны ECHOE и ECHOPRT. |
DEFECHO | (Не POSIX) Отображается только при чтении процесса. |
FLUSHO | (не принадлежит POSIX; Linux Не поддерживается ниже) Вывод сбрасывается. Этот логотип может содержать печатные символы DISCARD Давай, переключись. |
NOFLSH | Отключает очистку очередей ввода и вывода при генерации сигналов SIGINT, SIGQUIT и SIGSUSP. |
PENDIN | (не принадлежит POSIX; Linux Не поддерживается ниже) Когда считывается следующий символ, все символы во входной очереди выводятся повторно. (ударить использовать его для обработки typeahead) |
TOSTOP | Отправляет сигнал SIGTTOU группе фоновых процессов, пытающейся выполнить запись на управляющий терминал. |
IEXTEN | давать Возможность реализует пользовательскую обработку ввода. Этот логотип должен сочетаться с ICANON Используйте оба одновременно для интерпретации специальных символов. EOL2,LNEXT,REPRINT и WERASE,IUCLC логотип только эффективен. |
c_cc Массив определяет специальные управляющие символы. Индекс символа (начальное значение) изначениедля:
логотип | иллюстрировать |
---|---|
VINTR | (003, ETX, Ctrl-C, а также 0177, DEL, рубаут) Символ разрыва. Отправьте сигнал SIGINT. Распознается, когда установлен ISIG, и больше не передается в качестве входных данных. |
VQUIT | (034, FS, Ctrl-) символ выхода. Отправьте сигнал SIGQUIT. Распознается, когда установлен ISIG, и больше не передается в качестве входных данных. |
VERASE | (0177, DEL, Rubout или 010, BS, Ctrl-H или также #) Удаление символов. Удалите последний символ, который не был удален, но не удаляйте предыдущий EOF или начало строки. Распознается, когда установлен ICANON, и больше не передается в качестве входных данных. |
VKILL | (025, NAK, Ctrl-U или Ctrl-X, а также @) завершающий символ. Удалить ввод с момента последнего EOF или начала строки. Распознается, когда установлен ICANON, и больше не передается в качестве входных данных. |
VEOF | (004, EOT, Ctrl-D) Символ конца файла. Точнее, этот символ вызывает отправку содержимого буфера tty в пользовательскую программу, ожидающую ввода, без необходимости ожидания EOL. Если это первый символ строки, функция read() пользовательской программы вернет 0, указывая, что EOF был прочитан. Распознается, когда установлен ICANON, и больше не передается в качестве входных данных. |
VMIN | Минимальное количество символов для чтения в неканоническом режиме. |
VEOL | (0, NUL) Дополнительные символы конца строки. Распознается, когда установлен ICANON. |
VTIME | Задержка в неканоническом режиме читается в десятых долях секунды. |
VEOL2 | (нет в POSIX; 0, NUL) Еще один символ конца строки. Распознается, когда установлен ICANON. |
VSTART | (021, DC1, Ctrl-Q) начальный символ. Возобновляет вывод, прерванный символом остановки. Распознается, когда установлен IXON, и больше не передается в качестве входных данных. |
VSTOP | (023, DC3, Ctrl-S) Стоп-символ. Останавливает вывод до тех пор, пока не будет введен начальный символ. Распознается, когда установлен IXON, и больше не передается в качестве входных данных. |
VSUSP | (032, SUB, Ctrl-Z) Приостановить персонаж. Отправьте сигнал SIGTSTP. Распознается, когда установлен ISIG, и больше не передается в качестве входных данных. |
VLNEXT | (нет в POSIX; 026, SYN, Ctrl-V) Буквально дальше. Заключает в кавычки следующий входной символ, аннулируя любое его специальное значение. Распознается, когда установлен IEXTEN, и больше не передается в качестве входных данных. |
VSTART | (021, DC1, Ctrl-Q) начальный символ. Возобновляет вывод, прерванный символом остановки. Распознается, когда установлен IXON, и больше не передается в качестве входных данных. |
VSTOP | (023, DC3, Ctrl-S) Стоп-символ. Останавливает вывод до тех пор, пока не будет введен начальный символ. Распознается, когда установлен IXON, и больше не передается в качестве входных данных. |
VSUSP | (032, SUB, Ctrl-Z) Приостановить персонаж. Отправьте сигнал SIGTSTP. Распознается, когда установлен ISIG, и больше не передается в качестве входных данных. |
VLNEXT | (нет в POSIX; 026, SYN, Ctrl-V) Буквально дальше. Заключает в кавычки следующий входной символ, аннулируя любое его специальное значение. Распознается, когда установлен IEXTEN, и больше не передается в качестве входных данных. |
VWERASE | (not in POSIX; 027, ETB, Ctrl-W) Удалить слова. При настройке ICANON и IEXTEN может быть распознан и больше не может быть передан в качестве входных данных. |
VREPRINT | (not in POSIX; 022, DC2, Ctrl-R) Перепечатка непрочитанного характера. При настройке ICANONи IEXTEN может быть распознан и больше не может быть передан в качестве входных данных. |
• Функция: Получить свойства устройства последовательного порта.
• параметр:
• fd, файловый дескриптор последовательного устройства.
• termios_p, используемый для сохранения атрибутов последовательного порта.
• возвращаться:
• Успех, возвращение 0。
• Ошибка, возвращает -1, ошибка Дайте конкретный код ошибки.
• Функция: установка свойств устройства последовательного порта.
• параметр:
• fd, файловый дескриптор последовательного устройства.
• option_actions, когда этот параметр вступит в силу?
• termios_p указывает на структуру атрибутов, которую необходимо установить.
• возвращаться:
• Успех, возвращение 0。
• Ошибка, возвращает -1, ошибка Укажите конкретный код ошибки
иллюстрировать
Среди них значения option_actions:
TCSANOW: Вступит в силу немедленно.
TCSADRAIN: Текущие выходные данные вступят в силу после завершения передачи и применимы к выходному параметру «Исправлять».
TCSAFLUSH: текущие выходные данные были переданы. Если входные данные доступны для чтения, но не читаются, они будут отброшены.
• Функция: Возвращает входную скорость передачи данных в свойствах последовательного порта.
• параметр:
• termios_p указывает на структуру, содержащую атрибуты последовательного порта.
• возвращаться:
• Успех, возвращениескорость передачи данных, значение представляет собой набор макросов, определенных существующим terminos.h。
• Ошибка, возвращает -1, ошибка Дайте конкретный код ошибки.
иллюстрировать
Определение скорости передачи данных следующее:
#define B0 0000000
#define B50 0000001
#define B75 0000002
#define B110 0000003
#define B134 0000004
#define B150 0000005
#define B200 0000006
#define B300 0000007
#define B600 0000010
#define B1200 0000011
#define B1800 0000012
#define B2400 0000013
#define B4800 0000014
#define B9600 0000015
#define B19200 0000016
#define B38400 0000017
#define B57600 0010001
#define B115200 0010002
#define B230400 0010003
#define B460800 0010004
#define B500000 0010005
#define B576000 0010006
#define B921600 0010007
#define B1000000 0010010
#define B1152000 0010011
#define B1500000 0010012
#define B2000000 0010013
#define B2500000 0010014
#define B3000000 0010015
#define B3500000 0010016
#define B4000000 0010017
• Функция: Возвращает выходную скорость передачи данных в свойствах последовательного порта.
• параметр:
• termios_p указывает на структуру, содержащую атрибуты последовательного порта.
• возвращаться:
• Успех, возвращениескорость передачи данных, значение представляет собой набор макросов, определенных существующим terminos.h, см. 4.3.3
• Ошибка, возвращает -1, ошибка Дайте конкретный код ошибки.
• Функция: Установите входную скорость передачи данных в структуру атрибутов.
• параметр:
• termios_p указывает на структуру, содержащую атрибуты последовательного порта.
• скорость, скорость передачи данных, значение такое же, как 4.3.3。
• возвращаться:
• Успех, возвращение 0。
• Ошибка, возвращает -1, ошибка Укажите конкретный код ошибки
• Функция: Установите выходную скорость передачи данных в структуру атрибутов.
• параметр:
• termios_p указывает на структуру, содержащую атрибуты последовательного порта.
• скорость, скорость передачи данных, значение такое же, как 4.3.3。
• возвращаться:
• Успех, возвращение 0。
• Ошибка, возвращает -1, ошибка Укажите конкретный код ошибки
• Функция: Одновременная настройка входной и выходной скорости. передачи данные в атрибутную структуру.
• параметр:
• termios_p указывает на структуру, содержащую атрибуты последовательного порта.
• скорость, скорость передачи данных, значение такое же, как 4.3.3。
• возвращаться:
• Успех, возвращение 0。
• Ошибка, возвращает -1, ошибка Укажите конкретный код ошибки
• Функция: Очистить данные в выходном или входном буфере, в зависимости от параметров. queue_selector。
• параметр:
• fd, файловый дескриптор последовательного устройства.
• очередь_селектор, операция очистки данных.
• возвращаться:
• Успех, возвращение 0。
• Ошибка, возвращает -1, ошибка Дайте конкретный код ошибки.
иллюстрировать
Параметрqueue_selector имеет три значения:
TCIFLUSH: Очистить данные во входном буфере.
TCOFLUSH: Очистить данные в выходном буфере.
TCIOFLUSH: одновременная очистка данных буфера ввода/вывода.
Эта демонстрационная программа открывает устройство последовательного порта, а затем прослушивает устройство. Если есть читаемые данные, считайте их и распечатайте. Имя устройства и количество циклов прослушивания можно указать с помощью параметров.
#include <stdio.h> /*Стандартное определение ввода и вывода*/
#include <stdlib.h> /*Определение стандартной библиотеки функций*/
#include <unistd.h> /*Unix Стандартное определение функции*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> /*определение управления документом*/
#include <termios.h> /*PPSIX Определение управления терминалом*/
#include <errno.h> /*Определение номера ошибки*/
#include <string.h>
enum parameter_type {
PT_PROGRAM_NAME = 0,
PT_DEV_NAME,
PT_CYCLE,
PT_NUM
};
#define DBG(string, args...) \
do { \
printf("%s, %s()%u---", __FILE__, __FUNCTION__, __LINE__); \
printf(string, _00args); \
printf("\n"); \
} while (0)
void usage(void)
{
printf("You should input as: \n");
printf("\t select_test [/dev/name] [Cycle Cnt]\n");
}
int OpenDev(char *name)
{
int fd = open(name, O_RDWR ); //| O_NOCTTY | O_NDELAY
if (-1 == fd)
DBG("Can't Open(%s)!", name);
return fd;
}
/**
* @brief настройки Скорость последовательной связи
* @param fd тип int Дескриптор документа открытого последовательного порта
* @param speed тип int Скорость последовательного порта
* @return void
*/
void set_speed(int fd, int speed)
{
int i;
int status;
struct termios Opt = {0};
int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300,
B38400, B19200, B9600, B4800, B2400, B1200, B300, };
int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300, 38400,
19200, 9600, 4800, 2400, 1200, 300, };
tcgetattr(fd, &Opt);
for ( i= 0; i < sizeof(speed_arr) / sizeof(int); i++) {
if (speed == name_arr[i])
break;
}
tcflush(fd, TCIOFLUSH);
cfsetispeed(&Opt, speed_arr[i]);
cfsetospeed(&Opt, speed_arr[i]);
Opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/
Opt.c_oflag &= ~OPOST; /*Output*/
status = tcsetattr(fd, TCSANOW, &Opt);
if (status != 0) {
DBG("tcsetattr fd");
return;
}
tcflush(fd, TCIOFLUSH);
}
/**
*@brief настройка битов данных последовательного порта, стоповых битов и битов четности
*@param fd тип int Откройте дескриптор документа последовательного порта.
*@param databits тип int биты данных ценить для 7 или ВОЗ8 *@param stopbits тип int Стоп-бит ценитьдля 1 или ВОЗ2 *@param parity тип int Эффективность ценитьдляN,E,O,,S
*/
int set_Parity(int fd,int databits,int stopbits,int parity)
{
struct termios options;
if ( tcgetattr(fd, &options) != 0) {
perror("SetupSerial 1");
return -1;
}
options.c_cflag &= ~CSIZE;
switch (databits) /*настраиватьбиты данныхчисло*/
{
case 7:
options.c_cflag |= CS7;
break;
case 8:
options.c_cflag |= CS8;
break;
default:
fprintf(stderr,"Unsupported data size\n");
return -1;
}
switch (parity)
{
case 'n':
case 'N':
options.c_cflag &= ~PARENB; /* Clear parity enable */
options.c_iflag &= ~INPCK; /* Enable parity checking */
break;
case 'o':
case 'O':
options.c_cflag |= (PARODD | PARENB); /* настраиватьдля Чудесный эффект*/ options.c_iflag |= INPCK; /* Disnable parity checking */
break;
case 'e':
case 'E':
options.c_cflag |= PARENB; /* Enable parity */
options.c_cflag &= ~PARODD; /* Конвертировать для равномерного эффекта*/
options.c_iflag |= INPCK; /* Disnable parity checking */
break;
case 'S':
case 's': /*as no parity*/
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;break;
default:
fprintf(stderr,"Unsupported parity\n");
return -1;
}
/* настраивать Стоп-бит*/
switch (stopbits)
{
case 1:
options.c_cflag &= ~CSTOPB;
break;
case 2:
options.c_cflag |= CSTOPB;
break;
default:
fprintf(stderr,"Unsupported stop bits\n");
return -1;
}
/* Set input parity option */
if (parity != 'n')
options.c_iflag |= INPCK;
tcflush(fd,ЦИФЛУШ);
options.c_cc[VTIME] = 150; /* настройка занимает 15 секунд*/
options.c_cc[VMIN] = 0; /* Обновите параметры и сделайте это СЕЙЧАС */
если (tcsetattr(fd,TCSANOW,&options) != 0)
{
perror("SetupSerial 3");
return -1;
}
return 0;
}
void str_print(char *buf, int len)
{
int i;
for (i=0; i<len; i++) {
if (i%10 == 0)
printf("\n");
printf("0x%02x ", buf[i]);
}
printf("\n");
}
int main(int argc, char **argv)
{
int i = 0;
int fd = 0;
int cnt = 0;
char buf[256];
int ret;
fd_set rd_fdset;
struct timeval dly_tm; // delay time in select()
if (argc != PT_NUM) {
usage();
return -1;
}
sscanf(argv[PT_CYCLE], "%d", &cnt);
if (cnt == 0)
cnt = 0xFFFF;
fd = OpenDev(argv[PT_DEV_NAME]);
if (fd < 0)
return -1;
set_speed(fd,19200);
if (set_Parity(fd,8,1,'N') == -1) {
printf("Set Parity Error\n");
exit (0);
}
printf("Select(%s), Cnt %d. \n", argv[PT_DEV_NAME], cnt);
while (i<cnt) {
FD_ZERO(&rd_fdset);
FD_SET(fd, &rd_fdset);
dly_tm.tv_sec = 5;
dly_tm.tv_usec = 0;
memset(buf, 0, 256);
ret = select(fd+1, &rd_fdset, NULL, NULL, &dly_tm);
// DBG("select() return %d, fd = %d", ret, fd);
if (ret == 0)
continue;
if (ret < 0) {
printf("select(%s) return %d. [%d]: %s \n", argv[PT_DEV_NAME], ret, errno,
strerror(errno));
continue;
}
i++;
ret = read(fd, buf, 256);
printf("Cnt%d: read(%s) return %d.\n", i, argv[PT_DEV_NAME], ret);
str_print(buf, ret);
}
close(fd);
return 0;
}
Примечание. Ядру необходимо открыть определение макроса CONFIG_DYNAMIC_DEBUG.
1. Смонтируйте debugfs.
mount -t debugfs none /sys/kernel/debug
2. Включите всю печать в модуле uart.
echo "module sunxi_uart +p" > /mnt/dynamic_debug/control
3.Открытьобратитесь к ОПРЕДЕЛЕНИЕ документиз ВСЕХ ПЕЧАТНЫХ СРЕДСТВ.
echo "file sunxi-uart.c +p" > /mnt/dynamic_debug/control
4.Открытьобратитесь к Конечнодокументобратитесь обязательно распечатаю.
echo "file sunxi-uart.c line 615 +p" > /mnt/dynamic_debug/control
5.Открытьобратитесь ªОпределите имя функции и распечатайте его.
echo "func sw_uart_set_termios +p" > /mnt/dynamic_debug/control
6. Выключите печать.
Введите соответствующую команду выше из+p Исправлятьдля-p Вот и все.
Для получения дополнительной информации, пожалуйста, обратитесь к Linux Ядро Документация: linux-3.10/Documentation/dynamic-debug-howto.txt.
1. Определите макрос CONFIG_SERIAL_DEBUG.
linux-4.9 Версия CONFIG_SERIAL_DEBUG по умолчанию не определен в ядре. , нуждатьсяхотетьсамоходныйсуществовать
drivers/tty/serial/Kconfig Добавьте CONFIG_SERIAL_DEBUG в Определение, затем добавьте код ccflags-$(CONFIG_SERIAL_DEBUG) в файл driver/tty/serial/Makefiledocument. := -DDEBUG。
Примечание: использовать этот макрос требует, чтобы Ядро отключил макрос CONFIG_DYNAMIC_DEBUG.
Драйвер UART предоставляет несколько интерфейсов онлайн-отладки через узел sysfs.
1./sys/devices/platform/soc/uart0/dev_info
cupid-p2:/ # cat /sys/devices/platform/soc/uart0/dev_info
id = 0
name = uart0
irq = 247
io_num = 2
port->mapbase = 0x0000000005000000
port->membase = 0xffffff800b005000
port->iobase = 0x00000000
pdata->regulator = 0x (null)
pdata->regulator_id =
Узел может видеть порт UART и некоторую информацию об аппаратных ресурсах.
2./sys/devices/platform/soc/uart0/ctrl_info
cupid-p2:/ # cat /sys/devices/platform/soc/uart0/ctrl_info
ier : 0x05
lcr : 0x13
mcr : 0x03
fcr : 0xb1
dll : 0x0d
dlh : 0x00
last baud : 115384 (dl = 13)
TxRx Statistics:
tx : 61123
rx : 351
parity : 0
frame : 0
overrun: 0
Этот узел может распечатывать некоторую управляющую информацию, сохраненную в программном обеспечении, например текущий UART. Порт из значения регистра, отправка и получение данных из статистики и т.д.
3./sys/devices/platform/soc/uart0/status
cupid-p2:/ # cat /sys/devices/platform/soc/uart0/status
uartclk = 24000000
The Uart controller register[Base: 0xffffff800b005000]:
[RTX] 0x00 = 0x0000000d, [IER] 0x04 = 0x00000005, [FCR] 0x08 = 0x000000c1
[LCR] 0x0c = 0x00000013, [MCR] 0x10 = 0x00000003, [LSR] 0x14 = 0x00000060
[MSR] 0x18 = 0x00000000, [SCH] 0x1c = 0x00000000, [USR] 0x7c = 0x00000006
[TFL] 0x80 = 0x00000000, [RFL] 0x84 = 0x00000000, [HALT] 0xa4 = 0x00000002
этот узел может распечатать текущий UART Порт — некоторая информация о рабочем состоянии,включать Контроллер Каждое значение регистра。