C言語でRaspberry Piを操作しよう

# はじめに
本記事はC言語でRaspberry Piを操作することを目的に、ライブラリの導入方法やLチカについて記載しています。

Raspberry Piで電子回路を用いた開発を行う場合はPythonによる開発が多いですが、C言語でも簡単に制御することができます。また、コンパイル言語なので実行速度が早いため、組み込みに最適です。

## WiringPi
[WiringPi](http://wiringpi.com/)はRaspberry Pi用のGPIOインターフェイスライブラリになります。

C言語で記述されているため、BCM2835、BCM2836、およびBCM2837 SoCデバイス用で使用できます。

### WiringPiの導入
WiringPiの導入方法はパッケージインストールか、ソースからインストールすることで導入できます。

なお、ソースインストールは初心者にはライブラリの依存関係の理解が必要になってくるため、パッケージインストールをおすすめします。どうしても最新のバージョンを使用したい場合はソースからインストールしてください。

パッケージインストールは以下のコマンドでインストールできます。

- インストール  
`$ sudo apt --purge remove wiringpi`
- パッケージの確認   
`$ dpkg -l | grep  wiringpi`

```console
ii  wiringpi                              2.46                              armhf        Raspberry Pi GPIO libraries, headers and gpio command
```

ソースでインストールする場合は以下のコマンドを実行して、最新のソースをダウンロードします。

- ソースのダウンロード   
`$ wget https://project-downloads.drogon.net/wiringpi-latest.deb`
- ソースのインストール   
`$ sudo dpkg -i wiringpi-latest.deb`

## C言語でLチカ
### 電子回路図

Fritzingで作成した画像を例に解説します。

本記事ではGPIO制御するためにRaspberry Pi側はGPIOの端子番号7を入力に使用しています。LEDは端子の長いアノード側を電源の+側に接続し、端子の短いカソード側を抵抗と接続します。抵抗は100Ωを使用しています。

![Lチカ_ブレッドボード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221759/82322800-b82b-2e85-9d9a-53f8ee0cd241.png)


### 実装
[Blink](http://wiringpi.com/examples/blink/)を参考に、以下の`blink.c`ファイルを作成します。

本記事の環境では利用するGPO端子の番号として**7**を使用しています。

- blink.c

```c
#include <wiringPi.h>
#define pin 7 
int main (void)
{
  wiringPiSetup () ;
  pinMode (pin, OUTPUT) ;
  for (;;)
  {
    digitalWrite (pin, HIGH) ; delay (500) ;
    digitalWrite (pin,  LOW) ; delay (500) ;
  }
  return 0 ;
}
```

`blink.c`ファイル作成後、以下のコマンを実行し、コンパイルを行います。

`$ gcc -Wall -o blink blink.c -lwiringPi`

コンパイルを実行すると実行形式ファイルが作成されます。
以下のコマンドを実行し、Lチカを行います。0.5秒毎に点灯します。

`$  ./blink `


![写真 2020-05-17 23 18 33.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221759/8393340a-f010-ae56-e5de-60c8ef56a89b.jpeg)


### コンパイルエラー
ソースからのインストールの場合、コンパイル実行時に以下の様なエラーが発生する場合があります。以下の場合はリンク時にエラーが発生していて、fcntlという関数が見当たらないというエラーになります。

調査方法について解説します。

```console
/usr/lib/gcc/arm-linux-gnueabihf/6/../../../libwiringPi.so: `fcntl@GLIBC_2.28' に対する定義されていない参照です
collect2: error: ld returned 1 exit status
```

まずはfindコマンドなどで、`libwiringPi.so`ファイルを検索します。

`$ find / -name libwiringPi.so`

ファイルのパスが判明したら`ldd`コマンドでリンクを確認します。

- ldd   
`$ ldd /usr/lib/libwiringPi.so`

```cosnole
/usr/lib/libwiringPi.so: /lib/arm-linux-gnueabihf/libc.so.6: version `GLIBC_2.28' not found (required by /usr/lib/libwiringPi.so)
	linux-vdso.so.1 (0x7eff4000)
	/usr/lib/arm-linux-gnueabihf/libarmmem.so (0x76f5c000)
	libm.so.6 => /lib/arm-linux-gnueabihf/libm.so.6 (0x76ec9000)
	libpthread.so.0 => /lib/arm-linux-gnueabihf/libpthread.so.0 (0x76ea0000)
	librt.so.1 => /lib/arm-linux-gnueabihf/librt.so.1 (0x76e89000)
	libcrypt.so.1 => /lib/arm-linux-gnueabihf/libcrypt.so.1 (0x76e4a000)
	libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0x76d0b000)
	/lib/ld-linux-armhf.so.3 (0x76f90000)
```

コマンド実行結果から`libc.so.6`ファルがglibcバージョン2.28に対してコンパイルされていることが分かります。実行するにはそのバージョンが必要ですが、古いバージョンがインストールされていると考えられるため、現在のglibcのバージョンに対してプログラムを再コンパイルするか、新しいバージョンのglibcをインストールする必要があります。

`objdump`コマンドはコンパイルエラーなどの調査で重宝します。
コマンドを実行すると、オブジェクトファイルの情報を出力します。

- ダンプ   
`$ objdump -T /lib/arm-linux-gnueabihf/libc.so.6`

```console

/lib/arm-linux-gnueabihf/libc.so.6:     ファイル形式 elf32-littlearm

DYNAMIC SYMBOL TABLE:
00015fe0 l    d  .text	00000000              .text
00139710 l    d  .tdata	00000000              .tdata
00000000      DO *UND*	00000000  GLIBC_PRIVATE _rtld_global
00000000      DO *UND*	00000000  GLIBC_PRIVATE __libc_enable_secure
00000000      DF *UND*	00000000  GLIBC_2.4   __tls_get_addr
00000000      DO *UND*	00000000  GLIBC_PRIVATE _rtld_global_ro
00000000      DO *UND*	00000000  GLIBC_PRIVATE __pointer_chk_guard
00000000      DF *UND*	00000000  GLIBC_PRIVATE _dl_find_dso_for_object
00000000  w   D  *UND*	00000000              _dl_starting_up
00000000      DO *UND*	00000000  GLIBC_PRIVATE _dl_argv
0005f848 g    DF .text	000001c0  GLIBC_2.4   putwchar
000e1994 g    DF .text	00000014  GLIBC_2.4   __gethostname_chk
0007daec g    DF .text	00000030 (GLIBC_2.4)  __strspn_c1
0007db1c g    DF .text	00000040 (GLIBC_2.4)  __strspn_c2
00016a2c g    DF .text	00000024  GLIBC_2.4   __aeabi_MB_CUR_MAX
000f9614 g    DF .text	00000104  GLIBC_2.4   setrpcent
```

# おわりに
LED1本光らすだけでも何かの通知に利用したり色々応用ができます。
Raspberry PiはC言語の勉強にも最適ですね。