Armadilloフォーラム

Armadillo640用のデバイスドライバ

faxdfjk

2022年11月8日 17時08分

Armadillo640用のデバイスドライバの作成を試みております。
RasPi用の情報(#1)は見付けたのですが、Armadillo640で同様の情報はありますでしょうか。

(#1)https://qiita.com/iwatake2222/items/1fdd2e0faaaa868a2db2

コメント

at_akihito.irie

2022年11月9日 13時24分

入江です。

前提条件の確認なのですが、どのようなデバイスを接続するご予定でしょうか?
詳細を教えて頂けますと、適切なサポートが可能ですのでよろしくお願いいたします。

> 入江です。
> 前提条件の確認なのですが、どのようなデバイスを接続するご予定でしょうか?
> 詳細を教えて頂けますと、適切なサポートが可能ですのでよろしくお願いいたします。

弊社にて開発中のデバイスとなります。
a640からSPI経由で開発中デバイス(FPGA)にアクセスします。
検討しているドライバですが、ユーザアプリから/dev/spi_hogeのように見え、SPIバスとの仲介します。
リトライ処理必要な場合もありそれをドライバ内で吸収できたらと思いドライバ作成を検討しております。
よろしくお願いいたします。

引き続きデバイスドライバで質問です。

MyDeviceDriver.c(#1)のラズパイソース用ソースをMAKE(#2)でコンパイル、この段階ではコンパイルは完了。

モジュールをロードなど(#3)は成功。

デバイスのリード(#4)にてOSがフリーズしてしまう。

さて、この場合のデバッグはどう進めると良いのでしょうか。

(#1)ソース
https://qiita.com/iwatake2222/items/580ec7db2e88beeac3de

(#2)Makefile(前回の回答を参考にアレンジした)
obj-m := MyDeviceDriver.o

CC=arm-linux-gnueabihf-gcc

ARCH=arm

#KBUILD_DIR=/tmp/mod/lib/modules/4.14-at50/build
KBUILD_DIR = /lib/modules/4.14-at49/build

all:
# make -C /lib/modules/4.14-at49/build M=$(shell pwd) modules
make -C $(KBUILD_DIR) M=$(shell pwd) ARCH=$(ARCH) modules

clean:
# make -C /lib/modules/4.14-at49/build M=$(shell pwd) clean
make -C $(KBUILD_DIR) M=$(shell pwd) clean

(#3)コマンド
sudo insmod MyDeviceModule.ko
sudo mknod /dev/myDevice c 63 1
sudo chmod 666 /dev/myDevice
echo "a" > /dev/myDevice

(#4)コマンド
cat /dev/myDevice

ファイル ファイルの説明
MyDeviceDriver.c

いかのように作業してみました。
#1ではセルフコンパイル環境でMAKEFILEを作成していますが、ATDE環境に対応し書き換えが必要となります。
#1のMakefile内では「/lib/modules/$(shell uname -r)/builes」とやってて、ATDE内のフォルダに同じ効果の
内容が必要になると考え以下フォルダ「/lib/modules/4.14-at49/modules」を作成後
「build -> /home/atmark/a640/linux-v4.14-at49」のシンボリックリンクしました。
これに対応する形にMakefileを作成し・・・。

結果
makeするとエラー(#4)が出ます。

質問
どこかでミスがあるのでしょうきっと、作業の方向性は合ってますか?

(#1)https://qiita.com/iwatake2222/items/1fdd2e0faaaa868a2db2 [1回目]簡単なカーネルモジュールを作る

(#2)test.cの内容

atmark@atde8:~/a640/dev_drv_test/221108$ cat test.c
#include

static int test_init(void)
{
printk("Hello my module\n");
return 0;
}

static void test_exit(void)
{
printk("Bye bye my module\n");
}

module_init(test_init);
module_exit(test_exit);
MODULE_DESCRIPTION( "helloworld" );
MODULE_LICENSE( "GPL2" );
MODULE_AUTHOR("HOGE");

(#3)Makefileの内容

atmark@atde8:~/a640/dev_drv_test/221108$ cat Makefile
obj-m := test.o

CC=arm-linux-gnueabihf-gcc

all:
make -C /lib/modules/4.14-at49/build M=$(shell pwd) modules
clean:
make -C /lib/modules/4.14-at49/build M=$(shell pwd) clean

(#4)エラー内容

atmark@atde8:~/a640/dev_drv_test/221108$ make
make -C /lib/modules/4.14-at49/build M=/home/atmark/a640/dev_drv_test/221108 modules
make[1]: ディレクトリ '/home/atmark/a640/linux-v4.14-at49' に入ります
CC [M] /home/atmark/a640/dev_drv_test/221108/test.o
arm-linux-gnueabihf-gcc: error: unrecognized command line option ‘-mno-sse’; did you mean ‘-fno-dse’?
arm-linux-gnueabihf-gcc: error: unrecognized command line option ‘-mno-mmx’; did you mean ‘-gno-vms’?
arm-linux-gnueabihf-gcc: error: unrecognized command line option ‘-mno-sse2’; did you mean ‘-fno-dse’?
arm-linux-gnueabihf-gcc: error: unrecognized command line option ‘-mno-3dnow’; did you mean ‘-fno-doc’?
arm-linux-gnueabihf-gcc: error: unrecognized command line option ‘-m64’
arm-linux-gnueabihf-gcc: error: unrecognized command line option ‘-mno-red-zone’; did you mean ‘-fno-regmove’?
arm-linux-gnueabihf-gcc: error: unrecognized command line option ‘-mcmodel=kernel’
make[2]: *** [scripts/Makefile.build:336: /home/atmark/a640/dev_drv_test/221108/test.o] エラー 1
make[1]: *** [Makefile:1556: _module_/home/atmark/a640/dev_drv_test/221108] エラー 2
make[1]: ディレクトリ '/home/atmark/a640/linux-v4.14-at49' から出ます
make: *** [Makefile:6: all] エラー 2
atmark@atde8:~/a640/dev_drv_test/221108$

佐藤です。

前準備として、カーネルコンフィグの設定とカーネルビルドが必要になります。
下記マニュアルを参照してカーネルのビルドを行ってください。
https://manual.atmark-techno.com/armadillo-640/armadillo-640_product_ma…

上記マニュアルの手順の中の

[ATDE ~/linux-v4.14-at[version]]$ make ARCH=arm armadillo-640_defconfig

のあとに以下のように一部コンフィグを変更してください。

[ATDE ~/linux-v4.14-at[version]]$ make ARCH=arm menuconfig
General setup  --->
  [*] Enable loadable module support  --->  // スペースキーを押して [*] にする

Save して終了し、その後はマニュアル通りカーネルのビルドを完了させてください。

カーネルのビルドが終わったら、以下のコマンドを実行してください。

[ATDE ~/linux-v4.14-at[version]]$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=/tmp/mod modules_install

コンパイルしたいドライバの Makefile を以下のようにします。

obj-m := test.o
 
CC=arm-linux-gnueabihf-gcc
ARCH=arm
KBUILD_DIR=/tmp/mod/lib/modules/4.14-at50/build
 
all:
	make -C $(KBUILD_DIR) M=$(shell pwd) ARCH=$(ARCH) modules
clean:
	make -C $(KBUILD_DIR) M=$(shell pwd) clean

これで make するとサンプルのドライバがビルドできると思います。

複数ソース用に以下のようにmakefileをアレンジしてみましたがエラーになってしまいます。
複数ソース用makefileについてご指南ください。

<<<<<<<< 以下 makefile >>>>>>>>>>>>
obj-m := test.o
test-objs := main.o sub.o
CC=arm-linux-gnueabihf-gcc
ARCH=arm
KBUILD_DIR = /lib/modules/4.14-at49/build
all:
make -C $(KBUILD_DIR) M=$(shell pwd) ARCH=$(ARCH) modules
clean:
make -C $(KBUILD_DIR) M=$(shell pwd) clean

ご回答ありがとうございます。

test.koができたので、a640に転送し実行し実行、以下のようになりました。

atmark@armadillo:~/dev_drv_test$ sudo insmod test.ko
insmod: ERROR: could not insert module test.ko: Function not implemented

佐藤です。

以下のカーネルコンフィグも有効にしてみてください。
[*] Enable loadable module support --->
[*] Forced module loading
[*] Module unloading
[*] Forced module unloading
[*] Module versioning support

Saveしてビルドしたあとにできあがるカーネルイメージも以下を参照してa640へ転送してください。
https://manual.atmark-techno.com/armadillo-640/armadillo-640_product_ma…

そして、test.koを再ビルドしてください。
加えて

[ATDE ~/a640/linux-v4.14-at49]$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=/tmp/mod modules_install

を行い、 /tmp/mod/lib/modules も a640 の /lib 下に転送してください。

これで動作するかご確認ください。

ご回答ありがとうございます。
以下のようになりました。

atmark@armadillo:~/dev_drv_test$
atmark@armadillo:~/dev_drv_test$ sudo insmod test.ko
[sudo] password for atmark:
atmark@armadillo:~/dev_drv_test$ sudo rmmod test.ko
rmmod: ERROR: ../libkmod/libkmod.c:514 lookup_builtin_file() could not open builtin file '/lib/modules/4.14-at49/modules.builtin.bin'
atmark@armadillo:~/dev_drv_test$ dmesg
[ 0.000000] Booting Linux on physical CPU 0x0
<<<<< 省略 >>>>>
[ 57.647112] Hello my module
[ 67.341742] Bye bye my module

佐藤です。

a640 上に、/lib/modules/4.14-at49/modules.builtin.bin というファイルは存在していますでしょうか。
存在していないのであれば、ATDEの/tmp/mod/lib/modulesをa640に持っていけばERRORも消えると思います。

佐藤様ご回答ありがとうございます。

> a640 上に、/lib/modules/4.14-at49/modules.builtin.bin というファイルは存在していますでしょうか。

ありません。
atmark@armadillo:/$ ls /tmp
systemd-private-589402e9cacb4092aaf8474414dc93f9-systemd-timesyncd.service-8pllUn
atmark@armadillo:/$

> 存在していないのであれば、ATDEの/tmp/mod/lib/modulesをa640に持っていけばERRORも消えると思います。

これも、ありません。
atmark@atde8:~/a640/linux-v4.14-at49/lib$ ls /tmp
VMwareDnD
dbus-crx0KgAfLD
pulse-PKdhtXMmr18n
systemd-private-1c2026aa9b464dd7ba191021db4867ab-ModemManager.service-sAmjG8
systemd-private-1c2026aa9b464dd7ba191021db4867ab-apache2.service-vCw9sW
systemd-private-1c2026aa9b464dd7ba191021db4867ab-colord.service-9XmJFp
systemd-private-1c2026aa9b464dd7ba191021db4867ab-fwupd.service-roMM1V
systemd-private-1c2026aa9b464dd7ba191021db4867ab-rtkit-daemon.service-PNwq0i
systemd-private-1c2026aa9b464dd7ba191021db4867ab-systemd-timesyncd.service-xGnO2y
systemd-private-1c2026aa9b464dd7ba191021db4867ab-upower.service-OTdHtf
tracker-extract-files.1000
vmware-root_449-2092251648
atmark@atde8:~/a640/linux-v4.14-at49/lib$

以上よろしくお願いいたします。

佐藤です。

> > 存在していないのであれば、ATDEの/tmp/mod/lib/modulesをa640に持っていけばERRORも消えると思います。
>
> これも、ありません。
> atmark@atde8:~/a640/linux-v4.14-at49/lib$ ls /tmp
カーネルビルド後に以下を実行すると現れると思いますがどうでしょうか。

[ATDE ~/a640/linux-v4.14-at49]$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=/tmp/mod modules_install

佐藤様
エラー消えました。
これを追加ました。
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=/tmp/mod modules_install
ご指摘の操作を忘れていたようです。すいません。

自己レス
READ動作の時にフリーズするので調べていたら「copy_to_user()」を使用している例を見つけ変更し成功しました。

以下URL(#1)の「TestModB.c」にRead機能を追加したが(#2)Readするとシステムフリーズとなるが、
copy__to_userを使用すると(#3)期待通り動作した。

#1
https://stackoverflow.com/questions/21032073/how-to-copy-to-user-a-stri…

#2
動作しない
static ssize_t myDevice_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
printk("myDevice_read\n");
buf[0] = 'A';
return 1;
}

#3
動作した
static ssize_t myDevice_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
printk("myDevice_read\n");
//buf[0] = 'A';
copy_to_user(buf,"A",1);
return 1;
}