2020년 5월 29일 금요일

Linux Driver Development for Embedded Processors - 에피소드 1(보이지 않는 Board의 위협^^)

이번 posting 부터는 지난 1월에 공지했던 "Linux Driver Development for Embedded Processors(for short, LDD4EP)" 라는 주제에 대한 글을  연재해 보고자 한다. (매우 유감스럽게도) 당초 예상 보다 좀 늦어졌다^^.

  
LDD4EP2 book & Atmel SAMA5D3 Xplained 보드

(에피소드 1 - 부제) "Atmel SAMA5D3 Xplained 보드의 기본 환경 설정과 LDD4EP2 book의 예제 build해 보기"


LDD4EP  3부작 시리즈(Director: Slowboot) 👍🏼
에피소드 1(보이지 않는 Board의 위협) => 에피소드 2(Device Tree의 습격) => 에피소드 3(Device Driver의 복수)



Episode I. 보이지 않는 Board의 위협
목차
1. 머릿말
2. Atmel SAMA5D3 Xplained Reloaded
    - Prebuilt yocto image 설치(to NAND flash)
    - FIT 소개
    - UBI/UBIFS 소개
3. OpenWrt build 및 image 설치
    - Build 방법 소개
    - NAND flash image 설치 방법 소개
4. LDD4EP2 book 예제 build해 보기
     - 하나 하나 분석해 보는 것은 두번째 에피소드에서 ...
5. References
============

1. 머릿말
Embedded 제품 개발 회사에서는 대략 아래와 같은 일들을 진행한단다(?). 물론 실제 목표하는 제품이 뭐냐(예: car blackbox, car navigation, l2/l3 switch, smart phone, settop box ...)에 따라서 좀 더 심오한 일들이 진행되기도 하지만 말이다.

a) 보드 설계(H/W) 및 보드 bring-up(S/W) 관련 일
   - 보드 & Embedded processor에 대한 이해 필요
   - board bring-up: bootloader(u-boot), kernel, rootfs(특히, UBI/UBIFS, SquashFS) 초기 작업 필요
b) build system에 대한 이해 및 관련 작업
    - yocto project, openwrt, android, buildroot, armbian ...
c) 신규 device driver 개발 및 기존 코드 수정
   - device, device tree, device drivers(특히 platform device driver)에 대한 이해 필요
   - Pin muxing, GPIO, i2c, spi, uart, usb 등
d) rootfs를 구성하는 각종 system s/w 이해 & porting
   - 특정 s/w 추가 or 수정, 직접 개발 등.
   - android 등의 경우는 framework에 대한 이해 필요
e) UI
   - WebUI, Qt, Android app...

소위 BSP 혹은 kernel/device driver 개발자가 해야 하는 일이, 단순히 특정 device driver 만을 개발하는 것은 아니며, 위에 언급한 것과 같이 board bring-up에 관련된 일부터 시작해서 build system(yocto, openwrt 등) handling, rootfs(squashfs, ubi/ubifs) 제어 및 각종 system s/w(dnsmasq, iptables, sshd, lighttpd, ....) 안정화까지의 영역을 총 망라하는 것이라고 봐야 할 것이다.

편의 상, 이번 posting과 이어지는 posting에서는 주로 b와 (특히) c 항목에 해당하는 내용을 중점적으로 다뤄 볼 생각이다.

== == ==
이번 posting의 main text인 LDD4EP2 book에서는 아래 3가지 보드를 기준으로 device tree 및 device driver 예제를 소개하고 있다.

- NXP i.MX 7Dual Application Processor MCIMX7SABRE 보드
- Microchip SAMA5D2 Xplained Ultra 보드
- Raspberry Pi 3 Model B

따라서 이 중 하나의 보드에서 device tree & device driver 예제를 실습해 보는 것이 신상(?)에 이로울 듯 하여, 하나를 구매할까도 생각해  보았으나, 사정상 (3년 전에 사용하던) Atmel SAMA5D3 Xplained board를 다시 사용하기로 결심하였다. 정말 다행인 것은 Linux4SAM community에서는 예전 보드에 대해서도 최신 BSP(Board Support Package) 지원을 매우 잘 해주고 있어, 요즘 유행(?)에 맞는 device tree & device driver study에 전혀 문제가 없을 듯 보인다. 


2. Atmel SAMA5D3 Xplained Reloaded
2.1 At91Bootstrap loader, u-boot bootloader, kernel 등 build해 보기
이와 관련해서는 아래 page에 자세히 소개되어 있으니, 여기서는 별도로 정리하지 않기로 하겠다.


다만, u-boot bootloader의 코드 흐름(시작 -> linux loading 까지) 정도 만이라도 간단히 살펴보고 넘어가기로 하겠다.

[그림 2.1] SAMA5D3 Booting Flow

<u-boot 주요 코드 검색>

uboot_codeflow0.png



<u-boot 코드 흐름 1>

uboot_codeflow1.png


<u-boot 코드 흐름 2>

uboot_codeflow2.png


u-boot 관련하여 보다 구체적인 내용을 알고 싶다면 아래 README 파일을 꼼꼼히 읽어보기 바란다.


[참고] u-boot은 보드 bring-up 과정에서 매우 중요한 역할을 차지하는 만큼, 추후 기회가 된다면 별도의 주제로 정리해 볼 생각이다.

2.2 Device Tree 분석
  SAMA5D3 Xplained board의 device tree(및 device tree 기초)와 관련해서는 이전 posting을 참조하기 바란다.


https://slowbootkernelhacks.blogspot.com/2016/11/atmel-sama5d3-xplained-board-i2c-device.html


https://slowbootkernelhacks.blogspot.com/2014/03/beaglebone-linux-kernel310x-programming.html


실제로 device tree 설정과 관련해서는 다음번 posting에서 좀 더 구체적으로 다시 살펴 볼 것이다.



2.3 NAND flash에 prebuilt image 설치하기
다음으로 할 일은 yocto project를 통해 사전에 생성해 둔 prebuilt image 파일을 가지고 nand 부팅을 시도해 보는 것이다. 이는 flash memory 파티션 구조(map), FIT, UBI/UBIFS 등을 파악하는 것과도 연관이 있다.


[그림 2.2] Demo용 nand flash image 파일

$ unzip linux4sam-poky-sama5d3_xplained-headless-6.2.zip

[그림 2.3] NAND flash 용 image 파일


NAND flash에 image를 writing(program)하기 위해서는 아래 그림 상단의 JP9: NAND chip select jumper를 제거(open)한 상태에서 그림 하단의 reset 버튼(BP2: Reset button)을 눌러 주어, RomBoot(SROM에 설치되어 있는 primary bootloader) 상태로 진입해 주어야 한다. 

[그림 2.4] SAMA5D3 Xplained 보드

Console(minicom: 115200, 8N1)에 "RomBoot" 메세지가 출력되면, 정상적으로 RomBoot 상태로 진입한 것이다.

[그림 2.5] RomBoot mode 진입 모습 - minicom console에서 확인

RomBoot 상태에서 NAND flash에 image writing을 하기 위해서는 다시 JP9: NAND chip select jumper를 꽂아(close) 주어야 한다.

<Firmware Writing 동작 원리>
[RomBoot] <============== USB <============== NAND flash용 image
        ||
        V
NAND writing

참고: 요즘 나오는 보드는 대개 이런식의 firmware writing 방법을 지원하고  있다.

$ sudo ./demo_linux_nandflash.sh 
=> sam-ba -x demo_linux_nandflash_usb.qml 2>&1 | tee logfile.log

참고: Atmel에서는 sam-ba라는 firmware writing tool을 제공하고 있는데, 위의 shell script는 이를 이용하여 자동으로 NAND flash에 firmware image writing 을 수행해 주게 된다.
...
...
...
Wrote 18432 bytes at address 0x09c5b800 (99.83%)
Wrote 22528 bytes at address 0x09c60000 (99.85%)
Wrote 22528 bytes at address 0x09c65800 (99.86%)
Wrote 22528 bytes at address 0x09c6b000 (99.88%)
Wrote 22528 bytes at address 0x09c70800 (99.89%)
Wrote 22528 bytes at address 0x09c76000 (99.90%)
Wrote 18432 bytes at address 0x09c7b800 (99.92%)
Wrote 22528 bytes at address 0x09c80000 (99.93%)
Wrote 22528 bytes at address 0x09c85800 (99.94%)
Wrote 4096 bytes at address 0x09c8b000 (99.95%)
Skipped 40 empty page(s) at address 0x09c8c000
-I- === Done. ===
Connection closed.

정상적으로 writing이 진행된 후, u-boot config를 확인해 보면 다음과 같다.

<target board u-boot 설정 내용>
=> print
baudrate=115200
bootargs=console=ttyS0,115200 mtdparts=atmel_nand:256k(bootstrap)ro,768k(uboot)ro,256k(env_redundant),256k(env),6656k(itb)ro,-(rootfs) rootfstype=ubifs ubi.mtd=5 root=ubi0:rootfs rw
bootcmd=nand read 0x24000000 0x00180000 0x406730; bootm 0x24000000#kernel_dtb
bootdelay=1
fdtcontroladdr=2fb30b68
stderr=serial@ffffee00
stdin=serial@ffffee00
stdout=serial@ffffee00

Environment size: 381/131067 bytes

위의 demo script를 돌리고 나면, 아래와 같은 NAND flash 파티션 map이 그려지게 된다. 이 중 눈여겨 볼만한 부분은 dtb와 kernel image가 FIT(Flattened Image Tree) image 형태로 묶여 있다는 점과 rootfs로 UBIFS 파일 시스템이 사용되었다는 점일 것이다.

[그림 2.6] NAND flash partition map

참고: 요즘은 rootfs로 여러가지 장점이 있는 UBIFS를 사용하는 추세다. 즉, JFFS2나 YAFFS2 등은 잘 사용하지 않는다.

<여기서 잠깐 !>
SAMA5D2 Xplained board의 flash memory는 요즘 많이 사용하는 SPI flash(serial flash)와 eMMC로 구성되어 있음을 알 수 있다.

[그림 2.7] SAMA5D2 Xplained board의 flash map
==========

2.4 FIT(Flattened Image Trees) 소개
[그림 2.3]에서 보면, 확장자가 itb인 이상한(?) 파일이 하나 보인다.
sama5d3_xplained.itb

도대체 이 파일의 의미 & 용도가 무엇일까 ? 

Board bring-up을 하다 보면, dtb(device tree blob)를 별도로 관리하기 보다는 kernel image 뒤에 붙여서 하나의 이미지로 만들고 싶다거나 dtb를 용도에 맞게 여러 개 만들어 두고, 부팅 시에 원하는 것으로 선택(실제로 # 으로 선택함)해  사용하고 싶은 경우가 있다. 아니면, android boot.img style로 (recovery 목적으로) initial ramdisk image를 kernel image에 붙여야 하는 상황도 생각해 볼 수 있다. 

[그림 2.8] kernel, ramdisk, dtb를 하나의 이미지로 만들기

FDT는 Flattened Device Tree(device driver와 맞물려 있음)를 뜻하며, FIT(Flattened Image Tree)는 kernel, dtb, ramdisk fs(initrd)등을 여러개 묶을 수 있는 device tree 기반의 이미지 생성 방식으로 보면 될 것 같다. 아래에 FIT source(its file) 예제 하나를 소개해 보았다.


[그림 2.9] single kernel, single DTB FIT source(kernel_fdt.its 파일)

itb(FIT blob) 파일 생성은 uImage를 생성할 때 사용했던 mkimage로 하게 된다.
$ mkimage -f kernel_fdt.its kernel_fdt.itb

그렇다면 부팅은 어떻게 할까 ? (편의상, 앞선 예제하고는 무관하게) SAMA5D3 Xplained board를 가지고 직접 확인해 보도록 하자.

[그림 2.10] FIT 관련 u-boot config

다른 부분은 크게 차이가 없고, 단 하나 bootm 0x24000000#kernel_dtb  표현식 부분이 그간 못 보던 내용이다.

다음은 kernel booting 모습이다. 이 부분도 기존에 보던 것과는 사뭇 다르다. 내용을 보면 알겠지만, FIT image 중에서 kernel을 찾아 loading 하고, 이어서 dtb를 찾아 loading을 하고 있다.

[그림 2.11] FIT를 이용한 booting

참고: 위에서 소개한 its 예제와 위의 그림 2.11의 내용은 서로 아무런 관련이 없다.

FIT 관련 내용은 앞서 언급한 것 보다 훨씬 더 많은 내용을 담고 있는데, 보다 자세한 사항은 아래 site 내용을 참고하기 바란다.



2.5 UBI/UBIFS 소개
UBIFS는 현재 가장 활발하게 사용하는 file system 중 하나이다. UBIFS는 MTD device의 추상화 layer인 UBI(Unsorted Block Images)를 기반으로 하고 있다. UBI는 아래 그림에서 보는 것 처럼 PEB(Physical Erase Blocks)와 LEB(Logical Erase Blocks)를 서로 mapping해 주는 역할을 담당한다.
참고: UBI와 UBIFS는 서로 다른 사람이 개발한 것이다.

<몇가지 용어 정리>
UBI(Unsorted Block Image)
   => bad block handling 및 wear leveling을 담당하는 volume manager
UBIFS(UBI File System)
   => UBI 개념을 활용한 file system
MTD(Memory Technology Devices)
   => sector 단위가 아니라 page 단위(or erase block이라고도 함)로 read/write하기 위해 나온 개념.
   => JFFS2, YAFFS2, UBIFS 등은 모두 MTD layer 위에 존재함.
Wear Leveling
   => flash memory를 구성하는 cell을 골고루 돌아 가며 읽기/쓰기를 할 수 있도록 하는 기능. 
   => flash memory의 수명을 연장시키키기 위한 기술.
   => wear leveling이 가능하도록 하기 위해 몇번 erase되었는지를 표시하는 count 값을 flash memory 앞 부분에 저장해 둠.

참고: 모든 출발점은 NAND flash의 수명을 연장시키기 위한 방법(wear leveling)과 bad block을 어찌 처리할 것인가에 있다.


[그림 2.12] UBI <=> MTD 간의 관계도 -  LEB and PEB mapping

[그림 2.13] PEB vs LEB의 차이점

[그림 2.14] Flash device => MTD => UBI => UBIFS 관계도(계층도)

UBI file system을 만들기 위해서는 NAND flash 관련 parameter의 정확한 값을 사전에 알 수 있어야만 한다(이 값들은 datasheet를 통해 알 수 있는데, 사실 이 부분을 파악하는 것이 좀 어렵게 느껴질 수  있다 - 일전에 굉장히 고생했던 기억이 있다 :().

- PEB (physical erase blocks) size
- LEB (logical erase blocks) size
       => PEB size - (int((Subpage_size + Page_size) / Page_size)) * Page_size
=> 대략적으로 LEB size는 PEB size 보다 1 page 적다고 보면 됨.
- page size(minimum input/out size)
- sub pages size
- maximum erase block counts

UBIFS 파일을 생성 및 운용하는 방법 또한 좀 복잡한데, 가장 간단한 방법을 소개하면 다음과 같다.
1) mkfs.ubifs 명령을 사용하여 ubifs raw image 파일을 만들고,
2) ubinize 명령을 사용하여 volume을 지정하는 과정을 통해 최종 file system image를 만들어 낸다. 이때 ubinize.cfg 라는 파일(설정해 주어야 함)이 별도로 필요하다.
3) 마지막으로, ubifs image 파일을 nand flash에 write한 후, u-boot 설정을 변경하여 ubifs image로 부팅(rootfs mount)이 가능하도록 만든다.

<mkfs.ubifs 명령 사용법>
# mkfs.ubifs -r </path/to/your/rootfs/tree> -m <min io size>
  -e <LEB size> -c <Eraseblocks count>
  -o </path/to/output/ubifs.img>
<ubinize.cfg 파일 구성 방법>
[rootfs_volume]
mode=ubi
image=rootfs.ubifs
vol_id=1
vol_type=static
vol_name=rootfs
vol_alignment=1

[rwdata_volume]
mode=ubi
image=data.ubifs
vol_id=2
vol_type=dynamic
vol_name=data
vol_alignment=1
vol_flags=autoresize
<ubinize 명령 사용 방법>
# ubinize -vv -o <output image> -m <min io size>
  -p <PEB size>KiB <configuration file>
<u-boot config 설정 방법>
ubi.mtd=<mtd partition number>
root=<ubi device>:<volume>
rootfstype=ubifs
그럼 예를 하나 들어 보도록 하겠다.
$ mkfs.ubifs -m 2048 -e 129024 -c 1996 -o ubifs.img -r ./rootfs
$ vi ubinize.cfg
[ubifs]
mode=ubi
image=ubifs.img
vol_id=0
vol_size=200MiB
vol_type=dynamic
vol_name=rootfs
~
$ ubinize -m 2048 -p 128KiB -s 512 -o ubi.img ubinize.cfg
[참고] ubi.img 파일을 XXX.ubi 형태로 변경해도 된다.

<u-boot config>
ubi.mtd=4 root=ubi0:rootfs rw rootfstype=ubifs
[참고] 당연히, 위의 설정과 함께 앞서 생성한 ubi.img 파일을 nand flash 파티션(여기서는 mtd=4이므로 5번째 파티션)에 write해 주어야 부팅이 가능하다.

글로써 많은 내용을 설명하려니, 좀 어렵다^^. 암튼 UBI/UBIFS는 현재 가장 hot한  file system임에 틀림 없으나, 정확한 사용을 하기 위해서는 분명히 몇가지 넘어야 할 장벽이 좀 있는 것 같다. 보다 자세한 사항은 아래 site 내용을 참조해 주기 바란다.


마지막으로 아래 그림은 (독자 여러분의 이해를 돕기 위해) SAMA5D3 board를 위한 UBIFS 설정 관련 파라미터를 Buildroot menuconfig 통해 보여주기 위해 캡쳐한 것이다.

[그림 2.15] buildroot menuconfig - SAMA5D3 UBIFS 설정 값


3. OpenWrt build 및 Image 설치
Yocto project와 Buildroot를 이용한 방법은 그 동안 여러 차례 설명하였으니, 오늘은 OpenWrt 환경을 소개해 보고자 한다.

3.1 OpenWrt build 하기
$ git clone https://github.com/linux4sam/openwrt-at91.git
'openwrt-at91'에 복제합니다...
remote: Enumerating objects: 13, done.
remote: Counting objects: 100% (13/13), done.
remote: Compressing objects: 100% (13/13), done.
remote: Total 470521 (delta 0), reused 0 (delta 0), pack-reused 470508
오브젝트를 받는 중: 100% (470521/470521), 165.95 MiB | 2.24 MiB/s, 완료.
델타를 알아내는 중: 100% (319691/319691), 완료.

$ cd openwrt-at91/
$ ./scripts/feeds update  -a
$ ./scripts/feeds install  -a

$ cp configs/sama5d3_xplained_defconfig .config
$ make defconfig

$ make menuconfig

[그림 3.1] OpenWrt menuconfig


$ make V=s -j1
or
$ make -j4

$ cd bin/targets/at91/sama5d3-glibc; ls -la

[그림 3.2] OpenWrt build 결과물

OpenWrt와 관련해서는 본 저자의 아래 posting도 참조해 보기 바란다.


3.2 NAND flash에 image 설치하기
OpenWrt를 통해 build한 결과물 중, NAND flash writing에 사용할 파일을 추려 보면 다음과 같다.

- at91bootstrap-sama5d3_xplainednf_uboot
- openwrt-18.06.2-linux4sam-6.2-at91-sama5d3-at91-sama5d3_xplained-ubifs-root.ubi
- openwrt-18.06.2-linux4sam-6.2-at91-sama5d3-at91-sama5d3_xplained-ubifs-zImage
- openwrt-18.06.2-linux4sam-6.2-at91-sama5d3-at91-sama5d3_xplained.dtb
- u-boot-sama5d3_xplained_nandflash/u-boot.bin
- uboot.env

[그림 2.6]의 NAND flash 파티션 map은 FIT image 관련 부분이 반영되어 있으나, 위의 openwrt image에서는 이를 사용하지 않고, dtb와 zImage(kernel)를 별도의 파티션으로 분리할 생각이다. 따라서 아래와 같은 새로운 partition map을 생각해 볼 수가 있다.

[그림 3.3] New NAND flash partition map

<u-boot config 조정>
=> setenv bootargs 'console=ttyS0,115200 mtdparts=atmel_nand:256k(bootstrap)ro,768k(uboot)ro,256k(env_redundant),256k(env),128k(dtb)ro,6528k(kernel)ro,-(rootfs) rootfstype=ubifs ubi.mtd=6 root=ubi0:rootfs rw'
참고: dtb, kernel 영역이 새로 추가되었고, ubifs root file system은 mtd 6(0부터 시작)에 위치하도록  수정되었다.

=> setenv bootcmd 'nand read 0x22000000 0x00180000 0x20000; nand read 0x21000000 0x1a0000 0x660000; bootz 0x21000000 - 0x22000000'
참고: nand read 0x22000000 0x00180000 0x20000 명령은 NAND flash 0x00180000 번지의 내용을 0x20000 크기 만큼 읽어서 RAM 0x22000000에 load하라는 의미이다.

<Desktop PC>
$ cd ~/workspace/Boards/SAMA5D3/openwrt/openwrt-at91/bin/targets/at91/sama5d3-glibc

<u-boot.bin writing>
$ sudo sam-ba -p serial -b sama5d3-xplained -a nandflash -c erase:0x040000:0x100000 -c write:u-boot-sama5d3_xplained_nandflash/u-boot.bin:0x040000
참고: 위 명령의 의미는 0x040000:0x100000 구간을 우선 erase  한  후, u-boot-sama5d3_xplained_nandflash/u-boot.bin(u-boot) 파일의 내용을 0x040000 번지에서 부터 write하라는 뜻이다.

<Target board>
=> RomBOOT

Applet 'NAND Flash' from softpack 2.17 (v2.17).
Initializing NAND ioSet1 Bus Width 8
PMECC configuration: 0xc0902405
Sector size: 512
Sectors per page: 4
Spare size: 64
ECC bits: 4
ECC offset: 36
ECC size: 28
PMECC enabled
Buffer Address: 0x0030a4a0
Buffer Size: 22528 bytes
NAND applet initialized successfully.

<dtb 파일 writing>
$ sudo sam-ba -p serial -b sama5d3-xplained -a nandflash -c erase:0x180000:0x1a0000 -c write:openwrt-18.06.2-linux4sam-6.2-at91-sama5d3-at91-sama5d3_xplained.dtb:0x180000
참고: 위 명령의 의미는 0x180000:0x1a0000 구간을 우선 erase  한  후, openwrt-18.06.2-linux4sam-6.2-at91-sama5d3-at91-sama5d3_xplained.dtb(device tree blob) 파일의 내용을 0x180000 번지에서 부터 write하라는 뜻이다.

<Target board>
Applet 'NAND Flash' from softpack 2.17 (v2.17).
Initializing NAND ioSet1 Bus Width 8
PMECC configuration: 0xc0902405
Sector size: 512
Sectors per page: 4
Spare size: 64
ECC bits: 4
ECC offset: 36
ECC size: 28
PMECC enabled
Buffer Address: 0x0030a4a0
Buffer Size: 22528 bytes
NAND applet initialized successfully.

<kernel image writing>
$ sudo sam-ba -p serial -b sama5d3-xplained -a nandflash -c erase:0x1a0000:0x800000 -c write:openwrt-18.06.2-linux4sam-6.2-at91-sama5d3-at91-sama5d3_xplained-ubifs-zImage:0x1a0000
참고: 위 명령의 의미는 0x1a0000:0x800000 구간을 우선 erase  한  후, openwrt-18.06.2-linux4sam-6.2-at91-sama5d3-at91-sama5d3_xplained-ubifs-zImage(kernel image) 파일의 내용을 0x180000 번지에서 부터 write하라는 뜻이다.

<Target board>
Applet 'NAND Flash' from softpack 2.17 (v2.17).
Initializing NAND ioSet1 Bus Width 8
PMECC configuration: 0xc0902405
Sector size: 512
Sectors per page: 4
Spare size: 64
ECC bits: 4
ECC offset: 36
ECC size: 28
PMECC enabled
Buffer Address: 0x0030a4a0
Buffer Size: 22528 bytes
NAND applet initialized successfully.


<rootfs ubifs image writing>
$ sudo sam-ba -p serial -b sama5d3-xplained -a nandflash -c erase:0x800000: -c write:openwrt-18.06.2-linux4sam-6.2-at91-sama5d3-at91-sama5d3_xplained-ubifs-root.ubi:0x800000
참고: 위 명령의 의미는 0x800000:끝까지 구간을 우선 erase  한  후, openwrt-18.06.2-linux4sam-6.2-at91-sama5d3-at91-sama5d3_xplained-ubifs-root.ubi(ubifs image) 파일의 내용을 0x800000번지에서 부터 write하라는 뜻이다.

<Target board>
Applet 'NAND Flash' from softpack 2.17 (v2.17).
Initializing NAND ioSet1 Bus Width 8
PMECC configuration: 0xc0902405
Sector size: 512
Sectors per page: 4
Spare size: 64
ECC bits: 4
ECC offset: 36
ECC size: 28
PMECC enabled
Buffer Address: 0x0030a4a0
Buffer Size: 22528 bytes
NAND applet initialized successfully.


[그림 3.4] 수정된 u-boot config 모습
참고: 위의 설정 내용 중, NFS 관련 설정은 이후에 별도로 추가해 본 것이다. 무시하기 바란다.


주요 파티션에 대한 erase 및 writing이 모두 정상적으로 진행되었으니, reset 버튼을 눌러 target board를 재부팅해 주도록 하자.


[그림 3.5] Openwrt image booting 모습

[그림 3.6] Openwrt login 후 ps 명령 실행 모습

3.3 OpenWrt WebUI 및 ssh login
OpenWrt에는 (모양은 좀 떨어지지만) Lua를 기반으로 만들어진 LuCI라는 webUI가 기본적으로 탑재되어 있다. 따라서 기본적인 설정(예: ssh port open)은 모두 여기서 할 수가 있다.

[그림 3.7] Openwrt WebUI - LuCI 화면


마지막으로 4장에서 device driver 시험을 진행하기 전에 ssh login이 가능하도록 만들어 두도록 하자.

<target board>
root@OpenWrt:/# passwd
Changing password for root
New password: 
Bad password: similar to username
Retype password: 
passwd: password for root changed by root

<Desktop PC>
$ ssh root@192.168.1.1
The authenticity of host '192.168.1.1 (192.168.1.1)' can't be established.
RSA key fingerprint is SHA256:NdTf/DCS1As/QQ+QoUrtBfIpgGRYq+x5ukAtdpI/zVs.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.1.1' (RSA) to the list of known hosts.
root@192.168.1.1's password:

root@OpenWrt:~# mkdir workspace
앞으로 이 디렉토리에 device driver 예제 파일을 올려 둘 생각이다.


4. LDD4EP2 book 예제 build해 보기
앞선 과정을 통해 device driver 개발을 위한 환경 설정이 마무리되었으니, 이번 장(실제로는 다음번 posting) 부터는 LDD4EP2 book의 예제를 SAMA5D3 Xplained 보드에서 하나씩 돌려 보고, 주요 사항을 분석해 보도록 하겠다.

4.1 LDD4EP2 book 목차
LDD4EP2 book의 목차는 대략 아래와 같다. 이중 5 ~ 12장이 핵심 장이라고 볼 수 있는데, 각 장에서는 device tree와 이와 연결될 device driver 예제를 상세히 설명해 주고 있다.

1장: Build system 소개 - Yocto project를 이용한 build 방법 및 kernel 단독 build 방법 등 소개
2장: linux device driver model 소개
3장: hello world string을 출력하는 device driver 예 소개
4장: character driver 예 소개
5장: platform driver 소개
6장: i2c client driver 소개
7장: interrupt handling driver 소개
8장: MMU의 원리를 설명하고 간단한 예제 소개
9장: DMA의 동작 원리를 설명하고 관련 예제 소개
10장: Input subsystem 소개 및 관련 driver 예제 소개
11장: IIO(Industrial  IO) subsystem 소개 및 관련 driver 예제 소개
12장: Regmap API 사용 예제 driver 소개

아래 site에 가 보면, 이 책에서 언급하고 있는 예제 source와 practical lab 문서 등을 확인해 볼 수가 있다.


한가지 더, LDD4EP2 book과 더불어 반드시 함께 살펴 보아야 할 문서가 있다. 바로 Bootlin에서 작성한 아래 파일이다.



4.2 LDD4EP2 예제 build 하기
<target board>
root@OpenWrt:/# uname -a
Linux OpenWrt 4.19.78-linux4sam-6.2 #0 Wed Jan 30 12:21:02 2019 armv7l GNU/Linux

<Linux Desktop PC>
$ export PATH=~/workspace/Boards/SAMA5D3/openwrt/openwrt-at91/staging_dir/toolchain-arm_cortex-a5+vfpv4_gcc-7.4.0_glibc_eabi/bin:$PATH
$ export STAGING_DIR=~/workspace/Boards/SAMA5D3/openwrt/openwrt-at91/staging_dir
$ export ARCH=arm
$ export CROSS_COMPILE=arm-openwrt-linux-

$ cd linux_4.14_sama5d27-SOM_drivers
$ make clean
$ make
  -> 4.14 version 기준으로 되어 있어 OpenWrt kernel(4.19.78 version) 환경에서 build 시, 몇가지 compile error  발생함(적절히 수정함).

$ scp ./helloworld_sam.ko root@192.168.1.1:~/workspace
root@192.168.1.1's password: 
helloworld_sam.ko                                                       100%   27KB   2.0MB/s   00:00 


<target board>



4.3 Platform driver 예제 소개
TODO: 다음번 posting에서 ...

==========
(뭔가 좀 아쉬운 부분이 남긴 하지만) 이상으로 LDD4EP 에피소드 1 "Atmel SAMA5D3 Xplained 보드의 기본 환경 설정과 LDD4EP2 book의 예제 build해 보기" 편의 내용을 마치고자 한다.
다음 편에서는 4장 LDD4EP2 book 예제를 중심으로 보다 구체적인 device tree & device driver programming에 대해 알아보도록 하겠다.

To be continued ...


5. References
1. Linux Driver Development for Embedded Processors, 2nd edition, Alberto Liberal de los Rios.
7. Embedded Linux Primer, 2nd Edition, Christopher Hallinan
8. Mastering Embedded Linux Programing, Chris Simmonds


Slowboot

댓글 없음:

댓글 쓰기