Raspberry Pi GPIOを使用したシリアル通信

Raspberry Pi

はじめに

Raspberry PiのGPIOヘッダーに割り当てられているUARTピン(TXD0,RXD0)を使用して、センサーなどのIoTデバイスやルータなどの外部機器とシリアル通信を行う方法について記載します。
Raspberry Pi Foundationの公式ページ(https://www.raspberrypi.org/)にもとづいて記載しています。
(※)記載内容に誤り等ありましたら、ご連絡いただければ幸いです。

環境

  1. ボート
    Raspberry Pi 4 Model B
  2. OS
    Raspberry Pi OS (32-bit) Lite
    Minimal image based on Debian Buster
    Version: August 2020
    Release date: 2020-08-20
    Kernel version: 5.4
pi@raspberrypi:~ $ uname -a
Linux raspberrypi 5.4.51-v7l+ #1333 SMP Mon Aug 10 16:51:40 BST 2020 armv7l GNU/Linux
pi@raspberrypi:~ $

Raspberry PiのUARTについて

Raspberry Piで使用されているSoCには、PL011とminiUARTの2種類のUARTがあり、すべてのUARTは、3.3Vで駆動します。このため、5Vで駆動するシステムと接続する場合は、RS232Cレベル変換IC等を使用して、電圧レベルを変換して接続します。誤って5Vで稼働するシステムと接続すると破損するので注意が必要です。
Raspberry Pi 4には、4つのPL011が追加されています。デフォルトでは無効になっているため、使用する場合は有効化する必要があります。
次の表に、すべてのUARTの一覧を記載します。

名前タイプ
UART0PL011
UART1mini UART
UART2PL011
UART3PL011
UART4PL011
UART5PL011
UART 一覧

PL011(UART0、UART2~UART5)とmini UART(UART1)の違い

PL011とmini UARTの主な相違点について以下に記載します。

  1. 送受信用のFIFOバッファのサイズが小さくなっています。(8ビット)
  2. フロー制御機能がないため高いボーレートでは文字を失う傾向があります。
  3. クロックがVPUコアクロックにリンクされているため、VPUコアクロックの周波数が変化すると、mini UARTのボーレートが変化してしまいます。
    (※VPUコアクロックの周波数は、温度状況等により変化します。)
  4. break信号を検出できません。
  5. フレーミングエラーを検出できません。
  6. パリティビットが使用できません。
  7. 受信タイムアウト割り込みが使用できない。
  8. DCD, DSR, DTR, RI信号がありません。
  9. データ長が7ビット、8ビットしか使用できません。
  10. 1スタートビット、1ストップビットしか使用できません。

mini UARTの詳細については、SoC周辺機器のドキュメント(https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2835/BCM2835-ARM-Peripherals.pdf)を参照してください。

Primary UART及びSecondary UART

Raspberry Piでは、1つのUARTがGPIO 14(TXD)およびGPIO 15(RXD)に接続されており、このUARTがPrimary UARTになっています。
デフォルトでは、このUARTは、Linuxコンソールに接続されているUARTにもなっています。
(注:GPIO 14はGPIOヘッダーの8番ピンで、GPIO 15はGPIOヘッダーの10番ピンに対応します。)
Secondary UARTは、通常、GPIOコネクタには存在していません。デフォルトでは、Secondary UARTは Bluetoothモジュールに接続されています。
デフォルトでは、UART0のみが有効になっています。
次の表は、最初の2つのUART(UART0とmini UART)の割り当てをまとめたものです。

モデルUART0mini UART
Raspberry Pi Zeroprimarysecondary
Raspberry Pi Zero Wsecondary (Bluetoothに接続)primary
Raspberry Pi 1primarySecondary
Raspberry Pi 2primarysecondary
Raspberry Pi 3secondary (Bluetoothに接続)primary
Raspberry Pi 4secondary (Bluetoothに接続)primary
モデルごとのUARTの割り当て

注:Primary UARTとSecondary UARTのどちらが指定されている場合でも、デフォルトでは、mini UARTは、無効になっています。
次の表は、Raspberry Pi OSにおけるLinuxデバイスをまとめたものです。

Linuxデバイス説明
/dev/ttyS0mini UART
/dev/ttyAMA0UART0(1番目のPL011)
/dev/serial0Primary UART
/dev/serial1Secondary UART
各UARTのLinuxデバイスとの対応

使用した環境では、デフォルトではLinuxデバイスは以下のようになっていました。
上記の表のとおり、mini UART(/dev/ttyS0)は無効化されて存在しておらず、Primary UART(/dev/serial0)も存在しませんでした。また、Secondary UART(/dev/serial1)は、UART0(/dev/ttyAMA0)が使用されていました。

pi@raspberrypi:~ $ ls -l /dev
(略)
lrwxrwxrwx 1 root root           7 Sep  6 06:23 serial1 -> ttyAMA0
(略)
crw-rw---- 1 root dialout 204,  64 Sep  6 06:23 ttyAMA0
(略)
pi@raspberrypi:~ $

Raspberry Pi Fundationの公式ページの「UART configuration」ドキュメントに、以下のように記載されています。

On the Raspberry Pi, one UART is selected to be present on GPIO 14 (transmit) and 15 (receive) – this is the primary UART. By default, this will also be the UART on which a Linux console may be present.
Raspberry Piでは、あるUARTがGPIO 14(TXD)およびGPIO 15(RXD)に接続されている。ー このUARTがPrimary UARTです。
デフォルトでは、このUARTは、Linuxコンソールが存在する可能性があるUARTにもなっています。

使用した環境のデフォルトでは、Linuxコンソールで使用するシリアルデバイスは、以下のようにserial0(Primary UART)となっています。しかし、Linuxデバイスには、mni UART(/dev/ttyS0)は存在せず、Primary UART(/dev/serial0)も存在していませんので、Linuxコンソールは、使用できない状態でした。
代わりに、Bluetoothモジュールとの接続に使用されているUART0(/dev/ttyAMA0)が接続されているようです。

pi@raspberrypi:~ $ cat /boot/cmdline.txt
console=serial0,115200 console=tty1 root=PARTUUID=7d63f42a-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
pi@raspberrypi:~ $

GPIOヘッダーのUARTピンでUART0を使用する方法

上述のRaspberry Pi UARTのデフォルトの状態を踏まえ、GPIOヘッダーのUARTピンでUART0を使用して、シリアル通信を行う方法について記載します。

  1. Linuxシリアルコンソールの無効化(raspi-configを使用する場合)
    デフォルトでは、Primary UART(/dev/serial0)は、Linuxコンソールに割り当てられています。
    Primary UARTを他のシステムとのシリアル通信など他の目的で使用する場合は、Raspberry Pi OSを再構成し、Primary UARTをLinuxシリアルコンソールで使用しないようにする必要があります。再構成するには、次のようにraspi-configコマンド、あるいはDevice Tree Overlayを使用して行います。
    1. raspi-configを起動します。(sudo raspi-config)
    2. 「オプション5 – インターフェイスオプション」を選択します。
    3. 「オプションP6 – シリアル」を選択します。
    4. プロンプトに「シリアル経由でログインシェルにアクセスできるようにしますか?」と表示されるので、 「いいえ」と答えます。
    5. プロンプトに「シリアルポートハードウェアを有効にしますか?」と表示されるので、 「はい」と答えます。
    6. raspi-configを終了し、Raspberry Piを再起動して変更を有効にします。

以下のように、「console=serial0,115200」の記載が削除され、Primary UART(/dev/serial0)がLinuxコンソールとして使用されなくなります。

pi@raspberrypi:~ $ cat /boot/cmdline.txt
console=tty1 root=PARTUUID=7d63f42a-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
pi@raspberrypi:~ $
  1. Bluetoothモジュールの切り替え
    デフォルトでは、Bluetoothモジュールとの接続にSecandary UART(/dev/serial1)であるUART0(/dev/ttyAMA0)が使用されているため、切り替えを行う必要があります。
    様々なUARTに関するDevice Tree Overlayがkernel GitHub tree(https://github.com/raspberrypi/linux)で定義されており、この中に、Bluetoothモジュールに関する有用な「disable-bt」と「miniuart-bt」があります。
    このDevice Tree Overlayのいずれかを使用して、デフォルトでBluetoothモジュールとの接続で使用されているUART0をシリアル通信で使用できるように切り替えを行います。
  1. disable-btを使用する場合
    Bluetoothデバイスを無効にし、UART0(1番目のPL011)をPrimary UARTにします。
    加えて、「sudo systemctl disable hciuart」コマンドを使用して、モデムを初期化するシステムサービスを無効にして、モデムに接続しないようにする必要があります。
    「/boot/config.txt」ファイルを編集し、「dtoverlay=disable-bt」を末尾に追記します。
    その後、設定を反映するため、再起動を行います。
pi@raspberrypi:~ $ sudo vi /boot/config.txt
dtoverlay=disable-bt     <-- 末尾に追記
pi@raspberrypi:~ $

再起動後のLinuxデバイスは、以下のようになります。
Primary UART(/dev/serial0)として、UART0(/dev/ttyAMA0)が使用され、Secondary UART(/dev/serial1)としてmini UART(/dev/ttyS0)が使用されるようになります。

pi@raspberrypi:~ $ ls -l /dev
(略)
lrwxrwxrwx 1 root root           7 Sep  6 07:48 serial0 -> ttyAMA0
lrwxrwxrwx 1 root root           5 Sep  6 07:48 serial1 -> ttyS0
(略)
crw--w---- 1 root tty     204,  64 Sep  6 07:49 ttyAMA0
(略)
crw-rw---- 1 root dialout   4,  64 Sep  6 07:48 ttyS0
(略)
pi@raspberrypi:~ $
  1. miniuart-btを使用する場合
    Bluetooth機能を切り替えて、Bluetoothモジュールとの接続をUART0からmini UARTを使用するように切り替えを行い、UART0(1番目のPL011)をPrimary UARTにします。
    Bluetoothの機能を使用する場合は、この切り替えによりBluetoothデバイスとの接続にmini UARTが使用されるため、可能な最大ボーレートが低下する場合があることに注意してください。
    また、miniUARTのクロックがVPUコアクロックとリンクしているので、force_turbo = 1またはcore_freq = 250を使用して、VPUコアクロックを固定周波数に設定する必要があります。
    (※「PL011(UART0、UART2~UART5)とmini UART(UART1)の違い」を参照)
    「/boot/config.txt」ファイルを編集し、「dtoverlay=miniuart-bt」および「core_freq=250」を末尾に追記します。
    その後、設定を反映するため、再起動を行います。
pi@raspberrypi:~ $ sudo vi /boot/config.txt
dtoverlay=miniuart-bt     <-- 末尾に追記
core_freq=250             <-- 末尾に追記
pi@raspberrypi:~ $

再起動後のLinuxデバイスの状態は、以下のようになります。
Primary UART(/dev/serial0)として、UART0(/dev/ttyAMA0)が使用され、Secondary UART(/dev/serial1)としてmini UART(/dev/ttyS0)が使用されるようになります。

pi@raspberrypi:~ $ ls -l /dev
lrwxrwxrwx 1 root root           7 Sep  6 08:25 serial0 -> ttyAMA0
lrwxrwxrwx 1 root root           5 Sep  6 08:25 serial1 -> ttyS0
(略)
crw--w---- 1 root tty     204,  64 Sep  6 08:25 ttyAMA0
(略)
crw-rw---- 1 root dialout   4,  64 Sep  6 08:25 ttyS0
(略)
pi@raspberrypi:~ $

UART1~UART5の有効化

Raspberry Pi 4で追加された4つのUARTを有効化するには、uart2、uart3、uart4、およびuart5のDevice Tree Overlayを使用して行います。
デバイスツリーオーバーレイの詳細については、/boot/overlays/READMEを参照してください。
説明と使用方法については、「dtoverlay -h overlay-name」を実行してください。
デバイスツリーオーバーレイの使用方法の詳細については、このページ(https://www.raspberrypi.org/documentation/configuration/device-tree.md)を参照してください。
手短に言えば、「config.txt」ファイルに行を追加して、デバイスツリーオーバーレイを適用します。
ファイル名の「-overlay.dts」部分が削除されていることに注意してください。
例えば、以下のように記述します。
dtoverlay=disable-bt

以上です。

タイトルとURLをコピーしました