2015年6月13日土曜日

Raspberry Pi2でws2812bを使う






この人のライブラリを使えば動くけど、レジスタアクセスは多分volatileを追加したほうが将来コンパイラが変わっても安心。


https://github.com/richardghirst/rpi_ws281x#


C-cで終了すると終了処理が走らないのでmain.cにSIGINTを追加。ついでにSIGTERMも。


ほかにもmailbox.cにおいてレジスタをmmapでマッピングするのは正しく動くけどunmapにバグがあるので修正して使っています。


差分はこんな感じ。


RPi2からWS2812Bへの接続は直接接続でやってます。安全のため100Ωの抵抗を直列に挟んでいます。(抵抗による電圧降下はなかったです)



diff rpi_ws281x-master/dma.h rpi_ws281x-master_new/dma.h
42,48c42,48
< uint32_t ti;
< uint32_t source_ad;
< uint32_t dest_ad;
< uint32_t txfr_len;
< uint32_t stride;
< uint32_t nextconbk;
< uint32_t resvd_0x18[2];
---
> volatile uint32_t ti;
> volatile uint32_t source_ad;
> volatile uint32_t dest_ad;
> volatile uint32_t txfr_len;
> volatile uint32_t stride;
> volatile uint32_t nextconbk;
> volatile uint32_t resvd_0x18[2];
55,56c55,56
< {
< uint32_t cs;
---
> {
> volatile uint32_t cs;
71,72c71,72
< uint32_t conblk_ad;
< uint32_t ti;
---
> volatile uint32_t conblk_ad;
> volatile uint32_t ti;
88,90c88,90
< uint32_t source_ad;
< uint32_t dest_ad;
< uint32_t txfr_len;
---
> volatile uint32_t source_ad;
> volatile uint32_t dest_ad;
> volatile uint32_t txfr_len;
93c93
< uint32_t stride;
---
> volatile uint32_t stride;
96,97c96,97
< uint32_t nextconbk;
< uint32_t debug;
---
> volatile uint32_t nextconbk;
> volatile uint32_t debug;
rpi_ws281x-master_new/だけに発見: dma.h~
rpi_ws281x-master_new/だけに発見: dma.o
diff rpi_ws281x-master/gpio.h rpi_ws281x-master_new/gpio.h
36,61c36,61
< uint32_t fsel[6]; // GPIO Function Select
< uint32_t resvd_0x18;
< uint32_t set[2]; // GPIO Pin Output Set
< uint32_t resvd_0x24;
< uint32_t clr[2]; // GPIO Pin Output Clear
< uint32_t resvd_0x30;
< uint32_t lev[2]; // GPIO Pin Level
< uint32_t resvd_0x3c;
< uint32_t eds[2]; // GPIO Pin Event Detect Status
< uint32_t resvd_0x48;
< uint32_t ren[2]; // GPIO Pin Rising Edge Detect Enable
< uint32_t resvd_0x54;
< uint32_t fen[2]; // GPIO Pin Falling Edge Detect Enable
< uint32_t resvd_0x60;
< uint32_t hen[2]; // GPIO Pin High Detect Enable
< uint32_t resvd_0x6c;
< uint32_t len[2]; // GPIO Pin Low Detect Enable
< uint32_t resvd_0x78;
< uint32_t aren[2]; // GPIO Pin Async Rising Edge Detect
< uint32_t resvd_0x84;
< uint32_t afen[2]; // GPIO Pin Async Falling Edge Detect
< uint32_t resvd_0x90;
< uint32_t pud; // GPIO Pin Pull up/down Enable
< uint32_t pudclk[2]; // GPIO Pin Pull up/down Enable Clock
< uint32_t resvd_0xa0[4];
< uint32_t test;
---
> volatile uint32_t fsel[6]; // GPIO Function Select
> volatile uint32_t resvd_0x18;
> volatile uint32_t set[2]; // GPIO Pin Output Set
> volatile uint32_t resvd_0x24;
> volatile uint32_t clr[2]; // GPIO Pin Output Clear
> volatile uint32_t resvd_0x30;
> volatile uint32_t lev[2]; // GPIO Pin Level
> volatile uint32_t resvd_0x3c;
> volatile uint32_t eds[2]; // GPIO Pin Event Detect Status
> volatile uint32_t resvd_0x48;
> volatile uint32_t ren[2]; // GPIO Pin Rising Edge Detect Enable
> volatile uint32_t resvd_0x54;
> volatile uint32_t fen[2]; // GPIO Pin Falling Edge Detect Enable
> volatile uint32_t resvd_0x60;
> volatile uint32_t hen[2]; // GPIO Pin High Detect Enable
> volatile uint32_t resvd_0x6c;
> volatile uint32_t len[2]; // GPIO Pin Low Detect Enable
> volatile uint32_t resvd_0x78;
> volatile uint32_t aren[2]; // GPIO Pin Async Rising Edge Detect
> volatile uint32_t resvd_0x84;
> volatile uint32_t afen[2]; // GPIO Pin Async Falling Edge Detect
> volatile uint32_t resvd_0x90;
> volatile uint32_t pud; // GPIO Pin Pull up/down Enable
> volatile uint32_t pudclk[2]; // GPIO Pin Pull up/down Enable Clock
> volatile uint32_t resvd_0xa0[4];
> volatile uint32_t test;
rpi_ws281x-master_new/だけに発見: gpio.h~
rpi_ws281x-master_new/だけに発見: libws2811.a
rpi_ws281x-master_new/だけに発見: linux.pyc
diff rpi_ws281x-master/mailbox.c rpi_ws281x-master_new/mailbox.c
76a77,78
> unsigned offset = (unsigned)addr % PAGE_SIZE;
> addr-=offset;size+=offset;
rpi_ws281x-master_new/だけに発見: mailbox.c~
rpi_ws281x-master_new/だけに発見: mailbox.o
diff rpi_ws281x-master/main.c rpi_ws281x-master_new/main.c
150a151,152
> sigaction(SIGINT , &sa, NULL);
> sigaction(SIGTERM, &sa, NULL);
194c196
< usleep(500000);
---
> usleep(1000*1000/15);