Petalinux2018.3でキャラクタLCD制御(ST7032i) のバックアップ(No.2)

更新


電気回路/zynq/Petalinux2018.3環境を整える

I2C 経由で繋いだキャラクタ型の液晶ディスプレイ(LCD)を制御する

繋いだのはこれ digikey:NHD-C0216CIZ-FSW-FBW-3V3-ND

16 文字 x 2 行 で白色バックライト付きの LCD

付属の PDF だけだといろいろ情報が足りなくて困るのだけれど、 どうやらこの LCD には ST7032i という有名なコントローラが載っているらしいので、 このキーワードで検索すればいろいろと情報が得られる。

環境

作業履歴 のように Petalinux 2018.3 を基本として作業しています。

LCD は i2c-1 に繋がっているはず。

Petalinux は i2c-1 を認識して dtb に反映してくれています。

Zynq 機器で動作する Ubuntu 18.04LTC のコンソールで、

LANG:console
$ less /boot/system.dts
 ...

 i2c1: i2c@e0005000 {
  compatible = "cdns,i2c-r1p10";
  status = "disabled";
  clocks = <&clkc 39>;
  interrupt-parent = <&intc>;
  interrupts = <0 48 4>;
  reg = <0xe0005000 0x1000>;
  #address-cells = <1>;
  #size-cells = <0>;
 };
 ...

$ sudo grep i2c /var/log/syslog
 Jan 28 15:58:20 zturn2018_3 kernel: i2c /dev entries driver
 Jan 28 15:58:20 zturn2018_3 kernel: cdns-i2c e0004000.i2c: 400 kHz mmio e0004000 irq 24
 Jan 28 15:58:20 zturn2018_3 kernel: cdns-i2c e0005000.i2c: 400 kHz mmio e0005000 irq 25
$ ls -l /dev | grep i2c
 crw------- 1 root     root     89,   0  1月 28 15:58 i2c-0
 crw------- 1 root     root     89,   1  1月 28 15:58 i2c-1

ちゃんと 400kHz クロックになっている。

まずはリセットピンを制御可能にする

axi_gpio の追加

CPU から axi_gpio 経由で制御する。

vivado の Block Diagram に axi_gpio を置き、ダブルクリック。 GPIO Width に適当な値を入れる。 (ここでは LCD_RST ピン以外も制御したかったため5を入れた)

axi_gpio-width.png

GPIO ポートの上で右クリック後 [Make External] する。

axi_gpio-make_external.png

追加された GPIO_1 ポートをクリックして、プロパティエディタで適当な名前に変更。

axi_gpio-port-rename.png

Diagram の右クリックから [Run Connection Automation] すると、

axi_gpio-connection.png

Processor System Reset および AXI Interconnect が追加され、接続が完了する。

design_1_wrapper の編集

design_1 は Dialog から生成されるのだけれど、 design_1_wrapper は手動で変更しなければならないらしい?

LANG:verilog
module design_1_wrapper(
    ...
    //user define io,
    DATAPINS,
    ...
);

    inout [4:0] DATAPINS;
    ....
// user wire define code       
     wire [4:0] DATAPINS_i, DATAPINS_o, DATAPINS_t;
     ...
//user logic example
    IOBUF DATAPINS_0_iobuf(.I(DATAPINS_o[0]),.IO(DATAPINS[0]),.O(DATAPINS_i[0]),.T(DATAPINS_t[0]));
    IOBUF DATAPINS_1_iobuf(.I(DATAPINS_o[1]),.IO(DATAPINS[1]),.O(DATAPINS_i[1]),.T(DATAPINS_t[1]));
    IOBUF DATAPINS_2_iobuf(.I(DATAPINS_o[2]),.IO(DATAPINS[2]),.O(DATAPINS_i[2]),.T(DATAPINS_t[2]));
    IOBUF DATAPINS_3_iobuf(.I(DATAPINS_o[3]),.IO(DATAPINS[3]),.O(DATAPINS_i[3]),.T(DATAPINS_t[3]));
    IOBUF DATAPINS_4_iobuf(.I(DATAPINS_o[4]),.IO(DATAPINS[4]),.O(DATAPINS_i[4]),.T(DATAPINS_t[4]));

design_1 design_1_i(
       ...
       .DATAPINS_tri_i(DATAPINS_i),
       .DATAPINS_tri_o(DATAPINS_o),
       .DATAPINS_tri_t(DATAPINS_i),
       ...
);

ピン配置の指定

xdc ファイルの中で PACKAGE_PIN を指定する。

LANG:xdc
set_property PACKAGE_PIN A20 [get_ports {DATAPINS[4]}] ;# IO_B35_LN[2]
set_property IOSTANDARD LVCMOS33 [get_ports {DATAPINS[4]}] ;# IO_B35_LN[2]
  • コメントは # の前に ; を付けておかないとエラーになるらしい

https://japan.xilinx.com/support/answers/51613.html

vivado 上でビルド

vivado 上で Generate Block Design 後、Generate Bitstream する。

あれ?

[Synth 8-439] module 'design_1_processing_system7_0_0' not found ["(snip).srcs/sources_1/bd/design_1/synth/design_1.v":239]

のエラーが出た。

[Design Sources]-[design_1_wrapper]-[design_1_i] の上で右クリックから、 [Reset Output Products] してからビルドしたところうまくいった。

design-reset-output.png

PL をプログラムする

(project).runs\impl_1\design_1_wrapper.bit を ~/lcd-control/design_1_wrapper.bit にコピーする

LANG:console
$ sudo fpga-bit-to-bin.py --flip design_1_wrapper.bit /lib/firmware/bit.bin/gpio1.bit.bin
$ sudo mkdir -p /sys/kernel/config/device-tree/overlays/fpga-region
$ cat << EOT | dtc -I dts -O dtb | sudo tee /sys/kernel/config/device-tree/overlays/fpga-region/dtbo
 > // Device Tree File for FPGA Region:   fpga_reg.dts
 > /dts-v1/;
 > /plugin/;
 > / {
 >     fragment@0 {
 >         target-path = "/fpga-full";
 >         #address-cells = <1>;
 >         #size-cells = <1>;
 >         __overlay__ {
 >             #address-cells = <1>;
 >             #size-cells = <1>;
 >             firmware-name = "bit.bin/gpio1.bit.bin";
 >         };
 >     };
 > };
 > EOT

devicetree.dtb の更新

上のようにして追加した axi_gpio は petalinux の作る system.dtb に現れるんだろうか?

試してみたいところだが、system.dtb のみをビルドする方法が分からない

普通にやるなら hdf を petalinux へ持って行って、 もう一度 petalinux-configure してから petalinux-build だけど、 これをやると小一時間かかるのでいくらなんでも・・・

そこで zynq 上で 電気回路/zynq/Petalinux2018.3でPLとDevice Treeを動的に変更する#fc20918e で作成した /boot/system.dts を見ながら対応する overlay を作成する。

LANG:console
$ less /boot/system.dts
 ...
 amba: amba {
   ...
   gpio0: gpio@e000a000 {
     compatible = "xlnx,zynq-gpio-1.0";
     #gpio-cells = <2>;
     clocks = <&clkc 42>;
     gpio-controller;
     interrupt-controller;
     #interrupt-cells = <2>;
     interrupt-parent = <&intc>;
     interrupts = <0 20 4>;
     reg = <0xe000a000 0x1000>;
   };
   ...
$ cat << EOT > gpio1.dtso
 > // Device Tree File for gpio1
 > /dts-v1/;
 > /plugin/;
 > / {
 >   fragment@0 {
 >     target-path = "/amba";
 >     __overlay__ {
 >       #address-cells = <1>;
 >       #size-cells = <1>;
 >       gpio1: gpio@41200000 {
 >         compatible = "xlnx,zynq-gpio-1.0";
 >         #gpio-cells = <2>;
 >         clocks = <1 42>;
 >         gpio-controller;
 >         interrupt-controller;
 >         #interrupt-cells = <2>;
 >         interrupt-parent = <4>;
 >         interrupts = <0 20 4>;
 >         reg = <0x41200000 0x1000>;
 >       };
 >     };
 >   };
 > };
 > EOT
$ dtc -o dtb gpio1.dtso -o gpio1.dtbo
 gpio1.dtbo: Warning (unit_address_vs_reg): Node /fragment@0 has a unit name, but no reg property
 gpio1.dtbo: Warning (clocks_property): Could not get phandle node for /fragment@0/__overlay__/gpio@41200000:clocks(cell 0)
 gpio1.dtbo: Warning (interrupts_property): Bad interrupt-parent phandle for /fragment@0/__overlay__/gpio@41200000
$ ls /sys/kernel/config/device-tree/overlays/
$ sudo mkdir -p /sys/kernel/config/device-tree/overlays/gpio1
$ ls /sys/kernel/config/device-tree/overlays/gpio1
 dtbo  path  status
$ sudo dtc -o dtb gpio1.dtso -o /sys/kernel/config/device-tree/overlays/gpio1/dtbo
$ ls -l /proc/device-tree/amba/gpi*
 /proc/device-tree/amba/gpio@41200000:
 total 0
 -r--r--r-- 1 root root  4  3月 22 16:21 '#gpio-cells'
 -r--r--r-- 1 root root  4  3月 22 16:21 '#interrupt-cells'
 -r--r--r-- 1 root root  8  3月 22 16:21  clocks
 -r--r--r-- 1 root root 19  3月 22 16:20  compatible
 -r--r--r-- 1 root root  0  3月 22 16:21  gpio-controller
 -r--r--r-- 1 root root  0  3月 22 16:21  interrupt-controller
 -r--r--r-- 1 root root  4  3月 22 16:21  interrupt-parent
 -r--r--r-- 1 root root 12  3月 22 16:21  interrupts
 -r--r--r-- 1 root root  5  3月 22 16:21  name
 -r--r--r-- 1 root root  8  3月 22 16:21  reg
 
 /proc/device-tree/amba/gpio@e000a000:
 total 0
 -r--r--r-- 1 root root  4  3月 22 16:21 '#gpio-cells'
 -r--r--r-- 1 root root  4  3月 22 16:21 '#interrupt-cells'
 -r--r--r-- 1 root root  8  3月 22 16:21  clocks
 -r--r--r-- 1 root root 19  3月 22 16:21  compatible
 -r--r--r-- 1 root root  4  3月 22 16:18  emio-gpio-width
 -r--r--r-- 1 root root  0  3月 22 16:21  gpio-controller
 -r--r--r-- 1 root root  4  3月 22 16:21  gpio-mask-high
 -r--r--r-- 1 root root  4  3月 22 16:21  gpio-mask-low
 -r--r--r-- 1 root root  0  3月 22 16:21  interrupt-controller
 -r--r--r-- 1 root root  4  3月 22 16:21  interrupt-parent
 -r--r--r-- 1 root root 12  3月 22 16:21  interrupts
 -r--r--r-- 1 root root  5  3月 22 16:21  name
 -r--r--r-- 1 root root  4  3月 22 16:21  phandle
 -r--r--r-- 1 root root  8  3月 22 16:21  reg
$ # 登録できたのは良いけれど、gpio@e000a000 に比べると項目が少ない?
$ cat /proc/device-tree/amba/gpio@41200000/compatible
 xlnx,zynq-gpio-1.0
$ od -tx1z /proc/device-tree/amba/gpio@e000a000/emio-gpio-width
 0000000 00 00 00 40                                      >...@<
 0000004
$ od -tx1z /proc/device-tree/amba/gpio@e000a000/gpio-mask-high
 0000000 00 00 00 00                                      >....<
 0000004
$ od -tx1z /proc/device-tree/amba/gpio@e000a000/gpio-mask-low
 0000000 00 00 56 00                                      >..V.<
 0000004
$ od -tx1z /proc/device-tree/amba/gpio@e000a000/phandle
 0000000 00 00 00 06                                      >....<
 0000004

LCD との通信

LCD のアドレスは 0x7c だそうで、

$ mkdir lcd-control
$ cd lcd-control
$ git init
$ jed lcd-control.c

Counter: 3309 (from 2010/06/03), today: 1, yesterday: 3