LoginSignup
6
8

More than 5 years have passed since last update.

ZYBO (Zynq) 初心者ガイド (12) LinuxカーネルモジュールでLチカ

Last updated at Posted at 2018-01-12

環境

  • 開発用PC: Windows 10 64-bit
    • Vivado 2017.4 WebPACKライセンス
    • Xilinx SDK 2017.4 <- 今回は使わない
  • 開発用PC (Linux): Ubuntu 16.04 本家 (日本語版じゃない) (on VirtualBox 5.2.4)
    • PetaLinux 2017.4
  • ターゲットボード: ZYBO (Z7-20)

Windows環境は1回目、Linux環境は8回目を参照。
使用するハードウェア(hdf)は8回目を参照。

LinuxカーネルモジュールでLチカ

前回は、Linuxユーザ空間で動くアプリケーションを作成して、そこからLチカを行いました。今回は、Linuxのカーネル空間で動くモジュールを作成して、そこからLチカを行います。
面倒なので、/devや/sysといったインターフェースは作りませんが、デバイスドライバとして使う際には必要になります。詳しくはこちら(https://qiita.com/take-iwiw/items/1fdd2e0faaaa868a2db2 )の記事をご参考ください。
「Lチカ」と言いましたが、実際には、ロード時にLED点灯、アンロード時にLED消灯、という簡単な仕様のカーネルモジュールを作ります。

プロジェクトの準備

新規PetaLinuxプロジェクトの作成からやります。とりあえず、下記操作でBOOT.binとimage.ubを作成して、ちゃんと起動できることを確認します。これはいつも通りの手順で、8回目と同じです。

開発PCのターミナル
cd ~/work/peta
petalinux-create --type project --template zynq --name SimplePS
cd SimplePS/
petalinux-config --get-hw-description=../project_1.sdk
petalinux-build
petalinux-package --boot --force --fsbl images/linux/zynq_fsbl.elf --fpga images/linux/design_1_wrapper.bit --u-boot

カーネルモジュールを作成する

下記コマンドで、mymoduleというLinuxのカーネル空間で動くモジュールを作成します。コードは、project-spec/meta-user/recipes-modules/mymoduleに作られます。後で編集しますが、ひとまずはこのままにします。petalinux-build -x packageでこのアプリケーションを含むimage.ubが再作成されます。

(ug1144-petalinux-tools-reference-guide.pdfによると、petalinux-build -x packageの前にpetalinux-build -c rootfsが必要らしいが、無くても動いた)

開発PCのターミナル
petalinux-create -t modules --name mymodule --enable
petalinux-build -x package

作成されたimage/linux/image.ubをSDカードに上書きコピーしてZyboを起動します。(BOOT.binはそのまま)
すると、作成したカーネルモジュールが/lib/modules/4.9.0-xilinx-v2017.4/extra/mymodule.koにインストールされており、modprobe(ロード)すると、Hello world的なメッセージが出力されていることが分かります。

Zyboのターミナル
root@SimplePS:~# ls /lib/modules/4.9.0-xilinx-v2017.4/extra/mymodule.ko
/lib/modules/4.9.0-xilinx-v2017.4/extra/mymodule.ko
root@SimplePS:~# modprobe mymodule
mymodule: loading out-of-tree module taints kernel.
<1>Hello module world.
<1>Module parameters were (0xdeadbeef) and "default"

コードを編集して、再ビルドする

コードを編集して、ビルド、image.ubを再作成するには、以下のようにします(エディタは適当に置き換えてください)。どういうコードにするかは後述。

開発PCのターミナル
code project-spec/meta-user/recipes-modules/mymodule/files/mymodule.c &
petalinux-build -c mymodule -x do_install
petalinux-build -x package

petalinux-build -c mymodule -x do_installは省略可能。バイナリ(.ko)自体は、下記に作成される。違いはおそらくstripの有無

  • build/tmp/work/plnx_arm-xilinx-linux-gnueabi/mymodule/1.0-r0/mymodule.ko
  • build/tmp/work/plnx_arm-xilinx-linux-gnueabi/mymodule/1.0-r0/package/lib/modules/4.9.0-xilinx-v2017.4/extra/mymodule.ko

レジスタ直叩きでLチカ

モジュールロード(mymodule_init)のタイミングで、GPIOの設定と、High出力をします。モジュールアンロード(mymodule_exit)のタイミングで、Low出力をします。レジスタを叩くために、ioremap_nocache()で物理アドレス->仮想アドレスに変換しています。

project-spec/meta-user/recipes-modules/mymodule/files/mymodule.c
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/io.h>

/* Standard module information, edit as appropriate */
MODULE_LICENSE("GPL");
MODULE_AUTHOR
    ("Xilinx Inc.");
MODULE_DESCRIPTION
    ("mymodule - loadable module template generated by petalinux-create -t modules");


#define REG(address) *(volatile unsigned int*)(address)
#define GPIOPS_BASE   (0xE000A000)
#define GPIOPS_DATA_0 (0x0040)
#define GPIOPS_DIRM_0 (0x0204)
#define GPIOPS_OEN_0  (0x0208)

static int __init mymodule_init(void)
{
    printk("mymodule_init\n");
    int address;
    address = (int)ioremap_nocache(GPIOPS_BASE, 0x1000);

    /* Set MIO7 as output */
    REG(address + GPIOPS_DIRM_0) |= 1 << 7;
    REG(address + GPIOPS_OEN_0)  |= 1 << 7;

    /* Set MIO7 as High */
    REG(address + GPIOPS_DATA_0) |= 1 << 7;

    iounmap((void*)address);
    return 0;
}


static void __exit mymodule_exit(void)
{
    printk("mymodule_exit\n");

    int address;
    address = (int)ioremap_nocache(GPIOPS_BASE, 0x1000);

    /* Set MIO7 as Low */
    REG(address + GPIOPS_DATA_0) &= ~(1 << 7);

    iounmap((void*)address);
}

module_init(mymodule_init);
module_exit(mymodule_exit);

image.ubを再作成して、SDカードに入れて起動します。そして、MIO7に相当するGPIOを有効にします。その後、mymodule.koをロード、アンロードします。そのタイミングでLED(LD4)がチカチカするはずです。

Zyboターミナル
root@SimplePS:~# echo 913 > /sys/class/gpio/export
root@SimplePS:~# modprobe mymodule
mymodule: loading out-of-tree module taints kernel.
mymodule_init
root@SimplePS:~# modprobe -r mymodule
mymodule_exit
root@SimplePS:~# modprobe mymodule
mymodule_init

GPIO制御関数でLチカ

カーネル空間で使用できる、GPIO制御関数を使用してLEDを制御します。

project-spec/meta-user/recipes-modules/mymodule/files/mymodule.c
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/gpio.h>

/* Standard module information, edit as appropriate */
MODULE_LICENSE("GPL");
MODULE_AUTHOR
    ("Xilinx Inc.");
MODULE_DESCRIPTION
    ("mymodule - loadable module template generated by petalinux-create -t modules");

static int __init mymodule_init(void)
{
    printk("mymodule_init\n");

    /* LED用のGPIO913(MIO7)を使用する */
    gpio_request(913, NULL);
    gpio_export(913, true);

    /* LED用のGPIO913(MIO7)を出力にする。初期値は1(High) */
    gpio_direction_output(913, 1);

    /* LED用のGPIO913(MIO7)に1(High)を出力にする */
    gpio_set_value(913, 1);

    return 0;
}


static void __exit mymodule_exit(void)
{
    printk("mymodule_exit\n");

    /* LED用のGPIO913(MIO7)に0(Low)を出力にする */
    gpio_set_value(913, 0);
}

module_init(mymodule_init);
module_exit(mymodule_exit);

image.ubを再作成して、SDカードに入れて起動します。mymodule.koをロード、アンロードします。そのタイミングでLED(LD4)がチカチカするはずです。今回は、手動でGPIOを有効にする必要はありません。

Zyboターミナル
root@SimplePS:~# modprobe mymodule
mymodule: loading out-of-tree module taints kernel.
mymodule_init
root@SimplePS:~# modprobe -r mymodule
mymodule_exit
root@SimplePS:~# modprobe mymodule
mymodule_init

おわりに

ここまでで、Zybo(Zynq)の基本的な使い方を理解できました。ひとまずこの連載を終わりにしようと思います。引き続きやるべき内容としては以下がありますが、どれもハマりそうなので、この「初心者ガイド」のスコープ外としました。

  • LANを使えるようにする
  • Linuxアプリのデバッグ環境
  • デバイスツリーの設定

LAN設定が出来たので、やっぱり続く ⇒ https://qiita.com/take-iwiw/items/ac489acaca1ab54d7ce8

6
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
8