Raspberry pi で AP のレジスタをC言語で直接変更して GPIO を操作する

やること

Raspberry Pi 用の特別なライブラリとドライバを利用せずにGPIOをC言語で操作する。

その他の普通の手段

注意点

Linuxシステムコールを含む(mmap関数)ので、root 権限が必要なため sudo コマンドを利用する必要があります。 プログラム名を sample.c とするならば、

 $ gcc sample.c
 $ sudo ./a.out

のように実行してください。

main()

IC 20pin (RaspberryPi の端子だと 38pin) を操作して、High/Low をずっと繰り返す。

アドレスをいちいち addr/4 していますが、仕様書に記載されている byte アドレスを 32bit(4byte)アドレスに変換しているためです。 C言語の int は今回 32bitなので、アドレスを保持しているポインタに 1 を加算すると 32bit 分ポインタがずれます。

void main()
{
  int count;
  volatile unsigned *addr;

  gpio = io_mapping(GPIO_BASE);

  // set GPIO20 to output mode ( bit[2:0] ). offset is 0x8( byte address ) .
  *( gpio + 0x8/4 ) = (*( gpio + 0x8/4 ) & ~(0x7)) | (0x1 << 0);

  for( count = 0 ; ; count++){
    usleep(1000); 
    addr = ( count % 2 ) ? gpio + 0x1C/4 :  gpio + 0x28/4 ;
    *addr = 0x1 << 20;
  }
}

物理アドレスのアクセス用マッピング

過去記事を参照してください。

katogiso-tech.hatenablog.com

使っているレジスタ

ADDRESS Name Description Size Read/Write
0x3F20_0008 GPFSEL2 GPIO Function Select 2 32 R/W
0x3F20_001C GPSET0 GPIO Pin Output Set 0 32 W
0x3F20_0028 GPCLR0 GPIO Pin Output Clear 0 32 W

GPFSELn

SoC の端子は色々な機能を切り替えられるようになっていて、 RaspberryPi も同じようになっている。 今回は output モードに切り替えていて、GPFSEL2 の bit[2:0] に 1 を書き込んでいます。

GPSETn

Write Only のレジスタで、1 の書き込みで対応するGPIOが High になる。

GPCLRn

Write Only のレジスタで、1 の書き込みで対応するGPIOが Low になる。

その他

レジスタの値をそのまま反映する GPLEVn もあるが、他のGPIOの値を含めてレジスタReadして対応するbitだけ変更する必要がり(Read modified write)、少し手数が増えて複雑となります。

全容

RaspberryPi gpio sample