LinuxシリアルポートRS232/485/GPSドライバ実験(移植ミニコム)

シリアル ポートは非​​常に一般的に使用される周辺機器です。Linux では通常、シリアル ポートを通じて他のデバイスやセンサーと通信します。
シリアル ポートはレベルに応じて TTL と RS232 に分けられます。インターフェイスレベルが何であってもドライバプログラムは同じであり、シリアル
ポートをRS485などの外部チップを接続することでRS485信号に変換できるのが
punctual atomのI.MX6U-ALPHA開発ボードです。Zhengdian Atom の I.MX6U-ALPHA 開発ボードの場合、RS232、RS485、および GPS モジュール
インターフェイスはすべて I.MX6U の UART3 インターフェイスに接続されているため、これらのペリフェラルは最終的には UART3 シリアル ポート ドライバーに帰属します
この章では、I.MX6U-ALPHA 開発ボード上の UART3 シリアル ポートを駆動する方法を学び、RS232、
RS485、および GSP ドライバーを実現します。

Linux での UART ドライバー フレームワーク

1. uart_driver の登録と登録解除I2C や SPI と同様に、Linux にもシリアル ポート ドライバー フレームワークが提供されており、対応するシリアル ポート フレームワークに従って
ドライバー プログラムを記述するだけで済みます。
シリアル ポート ドライバーのホスト側とデバイス側の区別はありません。シリアル ポート ドライバーは 1 つだけあり、このドライバーは
NXP によって正式に作成されています。実際に行う必要があるのは、シリアル ポート ノード情報を追加することです。デバイスツリーで使用されます
システムが起動すると、シリアル ポート ドライバーがデバイスと正常に一致し、対応するシリアル ポートが駆動されて /dev/ttymxcX(X=0….n
) ファイルが生成されます。
シリアル ポート ドライバーを作成する必要はありませんが、シリアル ポート ドライバーのフレームワークを理解する必要があります。uart_driver 構造体は UART ドライバーを表します。uart_driver は include
/linux/serial_core.h ファイルで定義されており、その内容は次のとおりです。次のように:

示例代码63.1.1 uart_driver 结构体
295 struct uart_driver {
    
    
296 struct module *owner; /* 模块所属者*/
297 const char *driver_name; /* 驱动名字*/
298 const char *dev_name; /* 设备名字*/
299 int major; /* 主设备号*/
300 int minor; /* 次设备号*/
301 int nr; /* 设备数*/
302 struct console *cons; /* 控制台*/
303
304 /*
305 * these are private; the low level driver should not
306 * touch these; they should be initialised to NULL
307 */
308 struct uart_state *state;
309 struct tty_driver *tty_driver;
310 };


各シリアル ポート ドライバーは uart_driver を定義する必要があります。ドライバーをロードするときに、uart_register_driver 関数を通じてこの uart_driver をシステムに登録します。この関数のプロトタイプは次のとおりです。

int uart_register_driver(struct uart_driver *drv)

関数のパラメータと戻り値の意味は以下のとおりです。
drv: 登録する uart_driver。
戻り値: 0、成功、負の値、失敗。
ドライバーの登録を解除する場合は、以前に登録した uart_driver も登録解除する必要があります。uart_unregister_driver 関数を使用する必要があります。
関数のプロトタイプは次のとおりです。

void uart_unregister_driver(struct uart_driver *drv)

関数のパラメータと戻り値の意味は以下のとおりです。
drv: 登録を解除する uart_driver。
戻り値: なし。
2. uart_port の追加と削除
uart_port は特定のポートを表し、uart_port は include/linux/serial_core.h ファイルで定義されます。内容は次のとおりです
(一部省略)。

示例代码63.1.2 uart_port 结构体
117 struct uart_port {
    
    
118 spinlock_t lock; /* port lock */
119 unsigned long iobase; /* in/out[bwl] */
120 unsigned char __iomem *membase; /* read/write[bwl] */
......
235 const struct uart_ops *ops;
236 unsigned int custom_divisor;
237 unsigned int line; /* port index */
238 unsigned int minor;
239 resource_size_t mapbase; /* for ioremap */
240 resource_size_t mapsize;
241 struct device *dev; /* parent device */
......
250 };

uart_port で最も重要なのは、235 行目の ops です。ops にはシリアル ポートの特定のドライバー関数が含まれていますが、これについては
後で説明します。すべての UART には uart_port がありますが、uart_port と uart_driver はどのように組み合わせるのでしょうか? ここでは
uart_add_one_port 関数が使用されており、関数のプロトタイプは次のとおりです。

int uart_add_one_port(struct uart_driver *drv,
struct uart_port *uport)

関数のパラメータと戻り値の意味は以下のとおりです。
drv: このポートに対応する uart_driver。
uport: uart_driver に追加されるポート。
戻り値: 0、成功、負の値、失敗。
UART ドライバーをアンインストールする場合は、対応する uart_driver から uart_port を削除する必要もあります。uart_remove_one_port 関数を使用する必要があります。
関数のプロトタイプは次のとおりです。

int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)

関数のパラメータと戻り値の意味は以下のとおりです。
drv: アンインストールするポートに対応する uart_driver。
uport: アンインストールする uart_port。
戻り値: 0、成功、負の値、失敗。
3. uart_ops の実装 uart_port の
説明で前述したように、uart_port の ops メンバー変数は非常に重要です。ops には
UART 用の特定のドライバー関数が含まれており、ops 内の関数はデータを送受信するために Linux システムによって最終的に呼び出されるからです。ops は
uart_ops 型の構造体ポインタ変数で、uart_ops は include/linux/serial_core.h ファイルで定義されており、内容は次のとおりです。

示例代码63.1.3 uart_ops 结构体
49 struct uart_ops {
    
    
50 unsigned int (*tx_empty)(struct uart_port *);
51 void (*set_mctrl)(struct uart_port *, unsigned int mctrl);
52 unsigned int (*get_mctrl)(struct uart_port *);
53 void (*stop_tx)(struct uart_port *);
54 void (*start_tx)(struct uart_port *);
55 void (*throttle)(struct uart_port *);
56 void (*unthrottle)(struct uart_port *);
57 void (*send_xchar)(struct uart_port *, char ch);
58 void (*stop_rx)(struct uart_port *);
59 void (*enable_ms)(struct uart_port *);
60 void (*break_ctl)(struct uart_port *, int ctl);
61 int (*startup)(struct uart_port *);
62 void (*shutdown)(struct uart_port *);
63 void (*flush_buffer)(struct uart_port *);
64 void (*set_termios)(struct uart_port *, struct ktermios *new,
65 struct ktermios *old);
66 void (*set_ldisc)(struct uart_port *, struct ktermios *);
67 void (*pm)(struct uart_port *, unsigned int state,
68 unsigned int oldstate);
69
70 /*
71 * Return a string describing the type of the port
72 */
73 const char *(*type)(struct uart_port *);
74
75 /*
76 * Release IO and memory resources used by the port.
77 * This includes iounmap if necessary.
78 */
79 void (*release_port)(struct uart_port *);
80
81 /*
82 * Request IO and memory resources used by the port.
83 * This includes iomapping the port if necessary.
84 */
85 int (*request_port)(struct uart_port *);
86 void (*config_port)(struct uart_port *, int);
87 int (*verify_port)(struct uart_port *, struct serial_struct *);
88 int (*ioctl)(struct uart_port *, unsigned int, unsigned long);
89 #ifdef CONFIG_CONSOLE_POLL
90 int (*poll_init)(struct uart_port *);
91 void (*poll_put_char)(struct uart_port *, unsigned char);
92 int (*poll_get_char)(struct uart_port *);
93 #endif
94 };

uart_ops は最低レベルの UART ドライバー インターフェイスであり、実際には UART レジスタを処理するため、
UART ドライバーの作成者は uart_ops を実装する必要があります。uart_ops 構造内のこれらの関数の具体的な意味については、
Documentation/serial/driver を参照してください。
UART ドライバーのフレームワークはおそらく次のとおりです。次に、理論と実践を組み合わせて、NXP の公式 UART ドライバー ファイルがどのように記述されているかを確認します。

I.MX6U UARTドライバーの解析

1. UART プラットフォーム ドライバー フレームワーク
imx6ull.dtsi ファイルを開き、UART3 に対応するサブノードを見つけます。サブノードの内容は次のとおりです。

示例代码63.2.1 uart3 设备节点
1 uart3: serial@021ec000 {
    
    
2 compatible = "fsl,imx6ul-uart",
3 "fsl,imx6q-uart", "fsl,imx21-uart";
4 reg = <0x021ec000 0x4000>;
5 interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
6 clocks = <&clks IMX6UL_CLK_UART3_IPG>,
7 <&clks IMX6UL_CLK_UART3_SERIAL>;
8 clock-names = "ipg", "per";
9 dmas = <&sdma 29 4 0>, <&sdma 30 4 0>;
10 dma-names = "rx", "tx";
11 status = "disabled";
12 };

2 行目と 3 行目の互換性属性に注目してください。ここには、「fsl,imx6ul-uart」、「fsl,imx6q-uar」、「fsl,imx21-
uart」の 3 つの値があります。Linux ソース コードでこれら 3 つの値を検索して、対応する UART ドライバー ファイルを見つけます。この
ファイルは drivers/tty/serial/imx.c です。このファイルには次の内容が含まれています。

示例代码63.2.2 UART platform 驱动框架
267 static struct platform_device_id imx_uart_devtype[] = {
    
    
268 {
    
    
269 .name = "imx1-uart",
270 .driver_data = (kernel_ulong_t) &imx_uart_devdata[IMX1_UART],
271 }, {
    
    
272 .name = "imx21-uart",
273 .driver_data = (kernel_ulong_t)
&imx_uart_devdata[IMX21_UART],
274 }, {
    
    
275 .name = "imx6q-uart",
276 .driver_data = (kernel_ulong_t)
&imx_uart_devdata[IMX6Q_UART],
277 }, {
    
    
278 /* sentinel */
279 }
280 };
281 MODULE_DEVICE_TABLE(platform, imx_uart_devtype);
282
283 static const struct of_device_id imx_uart_dt_ids[] = {
    
    
284 {
    
     .compatible = "fsl,imx6q-uart", .data =
&imx_uart_devdata[IMX6Q_UART], },
285 {
    
     .compatible = "fsl,imx1-uart", .data =
&imx_uart_devdata[IMX1_UART], },
286 {
    
     .compatible = "fsl,imx21-uart", .data =
&imx_uart_devdata[IMX21_UART], },
287 {
    
     /* sentinel */ }
288 };
......
2071 static struct platform_driver serial_imx_driver = {
    
    
2072 .probe = serial_imx_probe,
2073 .remove = serial_imx_remove,
2074
2075 .suspend = serial_imx_suspend,
2076 .resume = serial_imx_resume,
2077 .id_table = imx_uart_devtype,
2078 .driver = {
    
    
2079 .name = "imx-uart",
2080 .of_match_table = imx_uart_dt_ids,
2081 },
2082 };
2083
2084 static int __init imx_serial_init(void)
2085 {
    
    
2086 int ret = uart_register_driver(&imx_reg);
2087
2088 if (ret)
2089 return ret;
2090
2091 ret = platform_driver_register(&serial_imx_driver);
2092 if (ret != 0)
2093 uart_unregister_driver(&imx_reg);
2094
2095 return ret;
2096 }
2097
2098 static void __exit imx_serial_exit(void)
2099 {
    
    
2100 platform_driver_unregister(&serial_imx_driver);
2101 uart_unregister_driver(&imx_reg);
2102 }
2103
2104 module_init(imx_serial_init);
2105 module_exit(imx_serial_exit);

267 ~ 280 行目で、I.MX6U の UART は本質的にプラットフォーム ドライバーであることがわかります。imx_uart_devtype は
従来のマッチング テーブルです。
283~288行目、デバイスツリーで使用するマッチングテーブル、284行目の互換属性値は「fsl,imx6q-uart」です。
行 2071 ~ 2082、プラットフォーム ドライバーのフレーム構造体、serial_imx_driver。
2084 ~ 2096 行目はドライバエントリ関数で、2086 行目は uart_register_driver 関数を呼び出して、
uart_driver を Linux カーネル (ここでは imx_reg) に登録します。
2098 ~ 2102 行目はドライバー終了関数で、2101 行目は uart_unregister_driver 関数を呼び出して、以前に登録された
uart_driver、つまり imx_reg の登録を解除します。
2. uart_driver の初期化
imx_serial_init 関数では、
uart_driver 型の構造体変数 imx_reg を Linux カーネルに登録します。

示例代码63.2.3 imx_reg 结构体变量
1836 static struct uart_driver imx_reg = {
    
    
1837 .owner = THIS_MODULE,
1838 .driver_name = DRIVER_NAME,
1839 .dev_name = DEV_NAME,
1840 .major = SERIAL_IMX_MAJOR,
1841 .minor = MINOR_START,
1842 .nr = ARRAY_SIZE(imx_ports),
1843 .cons = IMX_CONSOLE,
1844 };

3. uart_port の初期化と追加
UART デバイスとドライバーが正常に一致すると、serial_imx_probe 関数が実行されます。この関数の主要な作業は、
uart_port を初期化し、それを対応する uart_driver に追加することです。Serial_imx_probe 関数を見る前に、
imx_port 構造体を見てみましょう。imx_port は、I.MX シリーズ SOC 用に NXP によって定義されたデバイス構造体です。この構造体には、
uart_port メンバー変数が含まれています。imx_port 構造体の内容は次のとおりです (省略形付き):

示例代码63.2.4 imx_port 结构体
216 struct imx_port {
    
    
217 struct uart_port port;
218 struct timer_list timer;
219 unsigned int old_status;
220 unsigned int have_rtscts:1;
221 unsigned int dte_mode:1;
222 unsigned int irda_inv_rx:1;
223 unsigned int irda_inv_tx:1;
224 unsigned short trcv_delay; /* transceiver delay */
......
243 unsigned long flags;
245 };

217 行目、uart_port メンバー変数のポート。
次に、serial_imx_probe 関数を見てみましょう。関数の内容は次のとおりです。

示例代码63.2.5 serial_imx_probe 函数
1969 static int serial_imx_probe(struct platform_device *pdev)
1970 {
    
    
1971 struct imx_port *sport;
1972 void __iomem *base;
1973 int ret = 0;
1974 struct resource *res;
1975 int txirq, rxirq, rtsirq;
1976
1977 sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL);
1978 if (!sport)
1979 return -ENOMEM;
1980
1981 ret = serial_imx_probe_dt(sport, pdev);
1982 if (ret > 0)
1983 serial_imx_probe_pdata(sport, pdev);
1984 else if (ret < 0)
1985 return ret;
1986
1987 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1988 base = devm_ioremap_resource(&pdev->dev, res);
1989 if (IS_ERR(base))
1990 return PTR_ERR(base);
1991
1992 rxirq = platform_get_irq(pdev, 0);
1993 txirq = platform_get_irq(pdev, 1);
1994 rtsirq = platform_get_irq(pdev, 2);
1995
1996 sport->port.dev = &pdev->dev;
1997 sport->port.mapbase = res->start;
1998 sport->port.membase = base;
1999 sport->port.type = PORT_IMX,
2000 sport->port.iotype = UPIO_MEM;
2001 sport->port.irq = rxirq;
2002 sport->port.fifosize = 32;
2003 sport->port.ops = &imx_pops;
2004 sport->port.rs485_config = imx_rs485_config;
2005 sport->port.rs485.flags =
2006 SER_RS485_RTS_ON_SEND | SER_RS485_RX_DURING_TX;
2007 sport->port.flags = UPF_BOOT_AUTOCONF;
2008 init_timer(&sport->timer);
2009 sport->timer.function = imx_timeout;
2010 sport->timer.data = (unsigned long)sport;
2011
2012 sport->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
2013 if (IS_ERR(sport->clk_ipg)) {
    
    
2014 ret = PTR_ERR(sport->clk_ipg);
2015 dev_err(&pdev->dev, "failed to get ipg clk: %d\n", ret);
2016 return ret;
2017 }
2018
2019 sport->clk_per = devm_clk_get(&pdev->dev, "per");
2020 if (IS_ERR(sport->clk_per)) {
    
    
2021 ret = PTR_ERR(sport->clk_per);
2022 dev_err(&pdev->dev, "failed to get per clk: %d\n", ret);
2023 return ret;
2024 }
2025
2026 sport->port.uartclk = clk_get_rate(sport->clk_per);
2027 if (sport->port.uartclk > IMX_MODULE_MAX_CLK_RATE) {
    
    
2028 ret = clk_set_rate(sport->clk_per, IMX_MODULE_MAX_CLK_RATE);
2029 if (ret < 0) {
    
    
2030 dev_err(&pdev->dev, "clk_set_rate() failed\n");
2031 return ret;
2032 }
2033 }
2034 sport->port.uartclk = clk_get_rate(sport->clk_per);
2035
2036 /*
2037 * Allocate the IRQ(s) i.MX1 has three interrupts whereas later
2038 * chips only have one interrupt.
2039 */
2040 if (txirq > 0) {
    
    
2041 ret = devm_request_irq(&pdev->dev, rxirq, imx_rxint, 0,
2042 dev_name(&pdev->dev), sport);
2043 if (ret)
2044 return ret;
2045
2046 ret = devm_request_irq(&pdev->dev, txirq, imx_txint, 0,
2047 dev_name(&pdev->dev), sport);
2048 if (ret)
2049 return ret;
2050 } else {
    
    
2051 ret = devm_request_irq(&pdev->dev, rxirq, imx_int, 0,
2052 dev_name(&pdev->dev), sport);
2053 if (ret)
2054 return ret;
2055 }
2056
2057 imx_ports[sport->port.line] = sport;
2058
2059 platform_set_drvdata(pdev, sport);
2060
2061 return uart_add_one_port(&imx_reg, &sport->port);
2062 }

1971行目ではimx_port型の構造体ポインタ変数sportを定義しています。
1977 行目、スポーツの記憶を申請します。
1987 ~ 1988 行目では、デバイス ツリーから I.MX シリーズ SOC UART ペリフェラル レジスタの最初のアドレスを取得します。これは、
I.MX6ULL の UART3 の場合は 0X021EC000 です。レジスタの最初のアドレスが取得された後、メモリ マップされて、
対応する仮想アドレスが取得されます。
1992~1994行目、割り込み情報を取得します。
1996 ~ 2034 行目は、sport の初期化です。2003 行目に注目して、 Sport のポート メンバー変数を初期化します。
つまり、uart_ops を imx_pops に設定します。imx_pops は、I.MX6ULL の最下位ドライバー関数コレクションです。後で参照してください

2040~2055行目、割り込み申請。
2061 行目、uart_add_one_port を使用して uart_port を uart_driver に追加します。ここでは、
sport->port を imx_reg に追加します。
4. imx_pops 構造体変数
imx_pops は、I.MX6ULL シリアルポートの最下位演算関数を保存する uart_ops 型の構造体変数であり、
imx_pops の定義は以下のとおりです。

示例代码63.2.6 imx_pops 结构体
1611 static struct uart_ops imx_pops = {
    
    
1612 .tx_empty = imx_tx_empty,
1613 .set_mctrl = imx_set_mctrl,
1614 .get_mctrl = imx_get_mctrl,
1615 .stop_tx = imx_stop_tx,
1616 .start_tx = imx_start_tx,
1617 .stop_rx = imx_stop_rx,
1618 .enable_ms = imx_enable_ms,
1619 .break_ctl = imx_break_ctl,
1620 .startup = imx_startup,
1621 .shutdown = imx_shutdown,
1622 .flush_buffer = imx_flush_buffer,
1623 .set_termios = imx_set_termios,
1624 .type = imx_type,
1625 .config_port = imx_config_port,
1626 .verify_port = imx_verify_port,
1627 #if defined(CONFIG_CONSOLE_POLL)
1628 .poll_init = imx_poll_init,
1629 .poll_get_char = imx_poll_get_char,
1630 .poll_put_char = imx_poll_put_char,
1631 #endif
1632 };

imx_pops の関数は基本的に I.MX6ULL の UART レジスタを扱うため、
ここでは詳しく分析しません。
I.MX6U の UART ドライバーを簡単に理解した後、時間厳守 Atom I.MX6U-ALPHA 開発ボードで UART3 インターフェイスを駆動する方法を学びましょう。

ハードウェア回路図解析

この実験で使用した I.MX6U の UART3 インターフェイス、
I.MX6U-ALPHA 開発ボード上の RS232、RS485、GPS の 3 つのインターフェイスはすべて UART3 に接続されています。これら 3 つのモジュールの回路図を順番に見てみましょう。 。
1. RS232 の概略図
RS232 の概略図を図 63.3.1 に示します。図 63.3.1 から、RS232 レベルはチップ SP3232 を通じて実現され、RS232 はI の UART3 インターフェイス
ここに画像の説明を挿入
に接続されていることがわかります。
MX6Uですが、JP1経由で接続する必要があります。 このジャンパキャップがセットされています。JP1の1-3と2-4を接続した後、SP3232
とUART3を接続します。
2. RS485 の回路図
RS485 の回路図を図 63.3.2 に示します。RS485 は
ここに画像の説明を挿入
SP3485 チップによって実現され、RO はデータ出力端子、RI はデータ入力端子、RE は受信イネーブル
信号 (アクティブ ロー) 、DE は送信イネーブル信号 (アクティブ High) です。図 63.3.2 では、RE と DE が一連の回路を通過し
、最終的に RS485_RX によって制御されるため、RS485 トランシーバー制御 IO を保存し、
RS485 をシリアル ポートとして使用できるため、ドライバーを作成するのに便利です。 。
3. GPS 原理図
Zhengdian Atom は GPS + 北斗測位モジュールを備えており、モデルは ATK1218-BD であり、I.MX6U-ALPHA 開発ボードは
この GPS 測位モジュールのインターフェイスを予約しています。インターフェイス原理図は図 63.3 に示されています。 .3:
ここに画像の説明を挿入
from 図 63.3.3 から、GPS モジュールも UART3 を使用していることがわかり、
UART3 が正常に駆動された後、GPS モジュールのデータを直接読み取ることができます。

RS232ドライバの書き込み

前にも述べたように、I.MX6U の UART ドライバーは NXP によって書かれているため、私たちがそれを書く必要はありません。
必要なのは、デバイス ツリーに UART3 に対応するデバイス ノードを追加することだけです。imx6ull-alientek-emmc.dts
ファイルを開くと、このファイルには UART1 に対応する uart1 ノードのみが存在し、UART3 に対応するノードがないため、
uart1 ノードを参照して uart3 ノードを作成できます。
1. UART3 IO ノード UART3 の作成では、 2 つの IO UART3_TXD と UART3_RXD を使用するため、最初に UART3に対応する pinctrl サブノードを
iomuxc に作成し、次の内容を iomuxc に追加します。

示例代码63.4.1 UART3 引脚pinctrl 节点
1 pinctrl_uart3: uart3grp {
    
    
2 fsl,pins = <
3 MX6UL_PAD_UART3_TX_DATA__UART3_DCE_TX 0X1b0b1
4 MX6UL_PAD_UART3_RX_DATA__UART3_DCE_RX 0X1b0b1
5 >;
6 };

最後に、2 つのピン UART3_TX と UART3_RX が他の機能に使用されているかどうかを確認し、使用されている場合は、
それらの 2 つの IO が UART3 としてのみ使用されるようにシールドしてください。
2. uart3 ノードの追加
図 63.4.1 に示すように、デフォルトでは、imx6ull-alientek-emmc.dts には uart1 と uart2 の 2 つのノードしかありません。uart1 は、時間
ここに画像の説明を挿入
厳守アトム UART2 の I.MX6U-ALPHA 開発ボード上の UART1 です。は使用されず、UART2 は
デフォルトで UART3 の IO を使用するため、ノード uart2 を削除してから、UART3 に対応する uart3 を追加する必要があります。uart3
ノードの内容は次のとおりです。

示例代码63.4.2 UART3 对应的uart3 节点
1 &uart3 {
    
    
2 pinctrl-names = "default";
3 pinctrl-0 = <&pinctrl_uart3>;
4 status = "okay";
5 };

完了後、デバイス ツリーを再コンパイルし、新しいデバイス ツリーを使用して Linux を起動します。デバイス ツリーの変更が成功すると、
システム起動後に「/dev/ttymxc2」という名前のデバイス ファイルが生成されます。ttymxc2 は、対応するデバイス
ファイルアプリケーションプログラムは ttymxc2 にアクセスすることでUART3上の動作を実現できます。

ミニコムの移植

Minicom は、一般的に使用されているシリアル ポート デバッグ アシスタントに似ています。Linux で非常に一般的に使用されているシリアル ポート ツールです。minicom を
開発ボードに移植して、minicom を使用してシリアル ポートの読み書きができるようにします。
1. ncurses の移植
minicom には ncurses が必要なので、最初に ncurses を移植する必要があります。以前に ncurses が移植されている場合は、
ここで再度移植する必要はありません。minicom のコンパイル時に ncurses ライブラリとヘッダー ファイル ディレクトリを指定するだけで済みます。
まず、移植するファイルを保存するためのディレクトリを ubuntu に作成します。たとえば、
/home/zuozhongkai/linux/IMX6ULL ディレクトリに「tool」という名前のディレクトリを作成し、移植されたすべてのファイルを保存します
次に、ncurses ソース コードをダウンロードします。ncurses ソース コードを開発ボード CD に配置しました。パスは次のとおりです: 1、ルーチン
ソース コード -ライブラリ ソース コード -」ncurses-6.0.tar.gz 、ncurses-6.0.tar .gz ファイルを Ubuntu で作成したツール ディレクトリにコピーし
、解凍します。解凍コマンドは次のとおりです。

tar -vxzf ncurses-6.0.tar.gz

解凍が完了すると、「ncurses-6.0」という名前のフォルダが生成されます。これが ncurse のソースコードフォルダです
ツール ディレクトリの下に「ncurses」という名前の新しいディレクトリを作成し、ncurses のコンパイル結果を保存します。すべての準備が完了したら、
ncurses ライブラリをコンパイルできます。ncureses ソース コード ディレクトリ、つまり解凍したばかりの ncurses-6.0 ディレクトリに移動し
、まず ncureses を設定して、次のコマンドを入力します。

./configure --prefix=/home/zuozhongkai/linux/IMX6ULL/tool/ncurses --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf --with-shared --without-profile --disable-stripping --without-progs --with-manpages --without-tests

configureは設定スクリプト、--prefixはコンパイル結果の保存ディレクトリを指定するもので、コンパイル結果は
先ほど作成した「ncurses」ディレクトリに保存する必要があります。–host はコンパイラ プレフィックスの指定に使用され、
ここでは「arm-linux-gnueabihf」に設定され、-target はターゲットの指定に使用され、これもここでは「arm-linux-gnueabihf」に設定されています。設定コマンドを記述したら、
Enter キーをクリックして設定が完了するまで待ちます。設定が成功すると、図 63.5.1 のようになります。設定が成功したら、
ここに画像の説明を挿入
make コマンドを入力してコンパイルを開始します。コンパイルが成功すると、図 63.5.2: コンパイルが成功したように表示されます。
ここに画像の説明を挿入
次に、「make install」コマンドを入力してインストールします。インストールの意味は、コンパイル結果を –pfefix で指定されたディレクトリにコピーすることです。図 63.5.3 に示すように、インストールが成功すると、次のようになります。

ここに画像の説明を挿入

インストールが成功した後、前に作成した「ncurses」フォルダーを確認すると、図 63.5.4 に示すように、その中にさらにいくつかのものが含まれていることがわかります。ファイルは、lib、lib、および の 3 つのディレクトリに保存する必要があります
ここに画像の説明を挿入

図 63.5.4 の share 開発ボードのルート ファイル システムにある /usr/include、/usr/lib、/usr/share の 3 つのディレクトリにファイルをコピーします。ディレクトリが存在しない場合は、自分で作成してください
コピーコマンドは次のとおりです。

sudo cp lib/* /home/zuozhongkai/linux/nfs/rootfs/usr/lib/ -rfa
sudo cp share/* /home/zuozhongkai/linux/nfs/rootfs/usr/share/ -rfa
sudo cp include/* /home/zuozhongkai/linux/nfs/rootfs/usr/include/ -rfa

次に、開発ボードのルート ディレクトリにある /etc/profile ファイル (ない場合は自分で作成します) に次の内容を追加します。

示例代码63.5.1 /etc/profile 文件
1 #!/bin/sh
2 LD_LIBRARY_PATH=/lib:/usr/lib:$LD_LIBRARY_PATH
3 export LD_LIBRARY_PATH
4
5 export TERM=vt100
6 export TERMINFO=/usr/share/terminfo

2. minicom の移植 minicom の
移植を続けて、開発ボード CD に収めた minicom ソース コードを取得します。パスは次のとおりです。 1. ルーチン
ソース コード - "7. サードパーティ ライブラリ ソース コード - "minicom-2.7.1 .tar.gz。minicom-2.7.1.tar.gz を
ubuntu の /home/zuozhongkai/linux/IMX6ULL/tool ディレクトリにコピーし、
minicom のコンパイル結果を保存するために、tool ディレクトリの下に「minicom」という名前のサブディレクトリを作成します。すべての準備ができたら、minicom をコンパイルし、まず minicom を解凍します。
コマンドは次のとおりです。

tar -vxzf minicom-2.7.1.tar.gz

解凍が完了すると、minicom-2.7.1 というフォルダが生成されます。これが minicom のソースコードです。
このディレクトリに入って、minicom を設定します。設定コマンドは次のとおりです。

cd minicom-2.7.1/ //进入minicom 源码目录
./configure CC=arm-linux-gnueabihf-gcc --prefix=/home/zuozhongkai/linux/IMX6ULL/tool/
minicom --host=arm-linux-gnueabihf CPPFLAGS=-I/home/zuozhongkai/linux/IMX6ULL/tool/
ncurses/include LDFLAGS=-L/home/zuozhongkai/linux/IMX6ULL/tool/ncurses/lib -enable-cfg-dir=/etc/minicom //配置


CC は使用する gcc クロスコンパイラーを示し、--prefix はコンパイルされたファイルの保存ディレクトリを指定します。コンパイルされたファイルは、前に作成した minicom ディレクトリに保存する必要があります。–host はクロスコンパイラのプレフィックスを指定し、CPPFLAGS は ncurses のヘッダー ファイル パスを指定し、LDFLAGS は ncurses のライブラリ パスを指定します。
図 63.5.5 に示すように、構成が成功すると、次のようになります。

ここに画像の説明を挿入
構成が成功したら、次のコマンドを実行してコンパイルしてインストールします。

make
make install

コンパイルおよびインストール後、前に作成した minicom ディレクトリの内容が図 63.5.6 に示されています。
ここに画像の説明を挿入
minicom ディレクトリの bin サブディレクトリにあるすべてのファイルを開発ボードのルート ディレクトリの /usr/bin ディレクトリにコピーします。コマンドは
次のとおりです。

sudo cp bin/* /home/zuozhongkai/linux/nfs/rootfs/usr/bin/

完了後、開発ボードで「minicom -v」と入力して、minicom が正常に動作するかどうかを確認します。結果は図 63.5.7 に示されています。 図 63.5.7 から、minicom のバージョン番号が 2.7.1 であることがわかります

ここに画像の説明を挿入
minicom のバージョン番号は 2.7.1 です。通常どおり表示します。次の
コマンドを入力して、minicom 構成インターフェイスを開きます。

minicom -s

その結果、minicom 設定インターフェイスを開くことができなくなり、図 63.5.8 に示す情報が表示されます: 図 63.5.8
ここに画像の説明を挿入
から、minicom が非常に傲慢で、「立ち去ってください」と要求していることがわかります。許容されるのか?それは
治らなければなりません。解決策は非常に簡単で、新しい /etc/passwd ファイルを作成し、次の内容を passwd ファイルに入力します。

示例代码63.5.2 /etc/passwd 文件
1 root:x:0:0:root:/root:/bin/sh

完了したらボードを再起動してください。
完了したらボードを再起動してください。開発ボードを再起動した後、「minicom -s」コマンドを実行すると、図 63.5.9 に示す
ように、minicom 設定インターフェイスを開くことができます。 図63.5.9 に示すインターフェイスが表示された場合は、mincom が正常に動作していることを意味します。 。

ここに画像の説明を挿入

RS232ドライブテスト

RS232接続設定


テストの前に、I.MX6U-ALPHA 開発ボードの RS232 をコンピュータに接続し、図 63.6.1.1 に示すように、まず JP1 ジャンパ キャップを設定します。ジャンパ
ここに画像の説明を挿入
キャップを設定した後、RS232 ラインを使用して開発ボードを接続します。図 63.6.1.2 に示す
ように、ここでは、Zhengdian Atom が販売する CH340 ソリューションの USB - オス DB9 データ ケーブルなど、USB - DB9 (RS232) データ ケーブルを使用することをお勧めします。図 63.6.1.2 は CH340 チップを搭載しているため、コンピュータに接続すると COM ポートが表示され、この COM ポートが使用する COM ポートになります。たとえば、私のコンピュータでは COM9 で、SecureCRT で新しい接続を作成し、シリアル ポートは COM9、ボー レートは 115200 です。

ここに画像の説明を挿入


ミニコム設定


図 63.6.2.1に示すように、開発ボードに「minicom -s」と入力して minicom 構成インターフェイスを開き、「シリアル ポート セットアップ」を選択します。「シリアル ポート セットアップ」を選択した後、
ここに画像の説明を挿入
Enter をクリックしてセットアップ メニューに入ります。図 63.6 に示すように .2.2 に示すように:図 63.6.2.2 には 7 つの設定項目があり
ここに画像の説明を挿入
、それぞれ A、B...G に対応します。
UART3 のポート ファイルは /dev/ttymxc2 であるため、シリアル ポート デバイスは /dev/ttymxc2 に設定する必要があります。
設定方法は、図 63.6.2.3 に示すように、キーボードの「A」を押して「/dev/ttymxc2」と入力します
ここに画像の説明を挿入
。設定後、Enter キーを押して確認すると、他の構成項目を設定できます。例えば、E はボーレート、
データビット、ストップビットを設定し、F はハードウェアフロー制御を設定します。設定方法は同じで、設定後は図 63.6.2.4 のようになります
ここに画像の説明を挿入
。 Enter キーを押して確認して終了します。この時点で、図 63.6.2.1 に示すインターフェースに戻ります
。ESC キーを押して、図 63.6.2.1 に示す構成インターフェースを終了します。終了すると、図 63.6 に示されます。 .2.5: 図 63.6.2.2
ここに画像の説明を挿入
はシリアル ポート デバッグ インターフェイスです。現在のシリアル ポート ファイルが /dev/ttymxc2 であることがわかります。CTRL-
A を押してから Z を押して、次に示すように minicom ヘルプ情報インターフェイスを開きます。図 63.6.2.6:
ここに画像の説明を挿入
図 63.6.2.6 から、minicom には多くのショートカット キーがあることがわかります。この実験では、minicom のエコー機能をオンにします。エコー機能の設定項目は「ローカル
エコー オン/オフ」です。 .E」と表示されているので、Eを押してエコー機能のオン/オフを切り替えます。

RS232トランシーバーテスト

1. 送信テスト
まず、UART3 を介してコンピューターにデータを送信する開発ボードの機能をテストします。minicom のエコー機能を開く必要があります (
開くこと )、エコー機能をオンにした後、
図 63.6.3.1 に示すように「AAAA」と入力します。
ここに画像の説明を挿入


図 63.6.3.1 の「AAAA」は、開発ボードが UART3 経由でコンピュータに「AAAA」を送信し、その後 COM9が「AAAA」を受信することと同等です。SecureCRT の COM9 が受信したデータを図 63.6.3.2 に示します
ここに画像の説明を挿入
。ご覧のとおり、開発ボードは通常どおり UART3 経由でコンピュータにデータを送信し、
開発ボードのデータ受信機能をテストします。
2. 受信テスト
次に、開発ボードの UART3 受信機能をテストします。同様に、最初に SecureCRT 上の COM9 のローカル エコーを有効にする必要があります。そうしないと、
COM9 に出力は表示されませんが、実際には開発ボードに送信されています。 。図 63.6.3.3 に示すように、 [オプション] -> [セッション オプション] -> [SecureCRT の詳細] を選択
し、セッション設定インターフェイスを開き、[ローカル エコー] を選択します。SecureCRT を設定した後、開発ボードに「BBBB」を送信します。図 63.6.3.3 に示すように、SecureCRT の COM9 は「BBBB」を入力します。このとき、図 63.6.3.4 に示すように、開発ボードの minicom は送信された「BBBB」を受信します。UART3 の送信には問題ありません。テストを受信し、UART3 ドライバーが正常に動作することを示しています。minicom を終了する場合は、minicom 通信インターフェイスで CRTL+A を押し、X を押して minicom を閉じます。ここでのminicom の使用は非常に簡単で、インターネット上でさらに詳細な minicom チュートリアルを見つけることができます。

ここに画像の説明を挿入


ここに画像の説明を挿入

ここに画像の説明を挿入


RS485テスト

前述したように、I.MX6U-ALPHA 開発ボードの RS485 インターフェイスは UART3 に接続されているため、
本質的にはシリアル ポートです。
RS232 実験用に UART3 ドライバーを作成したため、 RS485 実験用にドライバーを作成する必要はなく、minicom を直接使用してテストできます。

RS485接続設定

1 つ目は、図 63.7.1.1 に示すように、JP1 ジャンパ キャップを設定して 3-5 と 4-6 を接続します。1
ここに画像の説明を挿入
つのボードでは RS485 通信テストを実行できず、別の I.MX6U -ALPHA などの別の RS485 デバイスが必要です。開発ボード。
ここでは、図 63.7.1.2 に示すように、USB to TTL、RS232、および RS485 をサポートする Zhengdian Atom 製の USB スリーインワン シリアル コンバータを使用することをお勧めします。USB
ここに画像の説明を挿入
シリアルの RS485 インターフェイスに接続するには Dupont ケーブルを使用します。 I.MX6U-ALPHA へのコンバータ 開発ボードの RS485 が接続されています
。A は A に接続され、B は B に接続されます。間違って接続することはできません。接続が完了すると、図 63.7.1.3 に示すように、
ここに画像の説明を挿入
シリアル ポート コンバータが USB ケーブルを介してコンピュータに接続されます。私は CH340 バージョンを使用しているため、ドライバーをインストールする必要はありません。FT232 バージョンを使用している場合は
、 、対応するドライブをインストールする必要があります。接続が成功すると、コンピュータには対応する COM
ポートが割り当てられます。たとえば、私のコンピュータには COM10 があり、次のステップはテストです。

RS485トランシーバーテスト

RS485 のテストは RS232 のテストとまったく同じです。USB オールインワン コンバータの COM ポートは 10 なので、SecureCRT を使用して
COM10 接続を作成します。開発ボードは UART3 を使用し、対応するシリアル ポート デバイス ファイルは /dev/ttymxc2 であるため、開発
ボードは minicom を使用して /dev/ttymxc2 のシリアル ポート接続を作成します。シリアル ポートのボー レートは 115200、8 データ ビット、1
ストップ ビット、ハードウェアおよびソフトウェアのフロー制御はオフになっています。
1. RS485 送信テスト
まず、開発ボードが RS485 を介してデータを送信することをテストします。minicom を設定した後、「AAAA」も入力します。つまり、
「AAAA」の文字列を RS485 を介してコンピュータに送信します。
RS485 ドライバが正常に動作している場合、図 63.7.2.1 に示すように、コンピュータは開発ボードから送信された「AAAA」を受信します
ここに画像の説明を挿入
。 図 63.7.2.1 から、開発ボードが「AAAA」を正常に送信したことがわかります。これは、RS485 データが
正常に送信されたことを意味します。
2. RS485 受信テスト
次に、RS485 データの受信テストを行い、コンピュータが RS485 経由で開発ボードに「BBBB」を送信し、
minicom が「BBBB」を受信できるかどうかを観察します。結果を図 63.7.2.2 に示します。
ここに画像の説明を挿入
図 63.7.2.1 から、RS485 経由でコンピュータから送信された「BBBB」を開発ボードが受信していることがわかります。これは、RS485 データ受信も正常であることを示しています

GPSテスト

GPS接続設定

ほとんどの GPS モジュールはシリアル ポートによって出力されます。ここでは、Zhengdian Atom が製造した ATK1218-BD モジュールを例に挙げます。これは
GSP+ 北斗測位モジュールです。モジュールは図 63.8.1.1 に示されています
ここに画像の説明を挿入
: ジャンパ キャップを引き抜きます開発ボード上の JP1 の場合は、RS232 または RS485 を接続しないでください。接続しないと、
GSP モジュールに干渉します。UART3_TX と UART3_RX は開発ボード上の ATK MODULE に接続されています。ATK1218
-BD モジュールを開発ボード上の ATK MODULE インターフェイスに直接接続するだけです。開発ボード上の ATK MODULE インターフェイスは
6 ピンですが、ATK1218-BD モジュールは 6 ピンです。 BD モジュールは 5 ピンなので、左側に挿入する必要があります。その場合、GPS をアンテナに接続する必要があり、
アンテナの受信ヘッドを屋外に配置する必要があるため、通常、屋内には GPS 信号がありません。図 63.8.1.2 に示すように、接続が完了すると、次のようになります

ここに画像の説明を挿入

GPSデータ受信テスト

私たちは皆、GPS の測位データを受動的に受信するので、minicom を開き、/dev/ttymxc2 を設定し、シリアル ポートの設定要件は次のとおりです: ①.
ATK1218
-BD モジュールのデフォルトのボー レートは 38400 に設定されているため、ボー レートは 38400 に設定されます。時間厳守のアトムは 38400 です。
②、8データビット、1ストップビット。
③. ハードウェアおよびソフトウェアのフロー制御をオフにします。
設定後は、図 63.8.2.1 に示すように
ここに画像の説明を挿入
、GPS データの出力を静かに待つことができます。GPS モジュールが初めて衛星を検索し、測位データが出力されるまでに数分かかる場合があります
。衛星が見つかった後にのみ。衛星が見つかった後、GPS モジュールによって出力される位置データは
図 63.8.2.2 に示されています。
ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/zhuguanlin121/article/details/129894275