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

2020년 5월 10일 일요일

Single Board Computer를 이용한 Embedded Linux 분석 및 Kernel Programming

본 blog에서는 아래 열거한 몇가지 single board computer(TI, Atmel/Microchip, Freescale/NXP, Allwinner, Qualcomm, Marvell, ST Micro, Rockchip, MediaTek 등)(가능한한 100$ 이하의 보드만을 대상으로 함)를 기초로 하여, bootloader, device tree, linux kernel & device driver, Buildroot, OpenWrt, Yocto project, Android, system programming 및 application programming 등과 관련된 내용을 지속적으로 분석해 봄으로써, 각종 embedded processor, embedded linux, RTOS 개발에 필요한 기초 지식을 정리 & 공유해 보고자 하고자 한다.


<주요 주제>
a) 다양한 SBC & embedded processor 검토(datasheet, schematics  등) - ARMv7-M/A, ARMv8-A, MIPS32, x86, PowerPC ...
b) Buildroot, Yocto project, OpenWRT, Android 등 적용
c) Bootloader(u-boot, Little Kernel 등), device tree, linux kernel 코드 분석
d) Linux kernel module, device driver programming, RTOS(RIOTZephyr and ARM Mbed OS) programming
e) Application programming(system programming, android app, Qt app, Python app, web programming)
f) Networks(TCP/IP, L2/L3, Wired/wireless, LTE), security(Wireguard, SoftEther VPN), LoRaWAN etc.





ARMv7-M Series(32 bits)
1) Nucleo F103RB - STM32F103RB ARM Cortex-M3 MCU
 

<특장점>
ST-Link/V2-1 programmer(debugger)가 on board되어 있어, 별도의 jtag debugger가 필요치 않다(console cable도 필요치 않음). ST micro 보드는 매우 널리 사용되고 있으며, 인터넷에서 관련 자료를 쉽게 찾을 수 있음. ARM Mbed OS, Zephyr Project, RIOT OS에서 지원하고 있는 보드임.

<my postings>
a) http://slowbootkernelhacks.blogspot.kr/2017/03/riot-os.html
b) http://slowbootkernelhacks.blogspot.kr/2017/03/riot-os-2.html
c) http://slowbootkernelhacks.blogspot.kr/2017/03/zephyr-project.html
d) https://slowbootkernelhacks.blogspot.com/2020/05/posting-linux-os-arm-mbed-os-disco.html


2) DISCO-L072CZ-LRWAN1 - B-L072Z-LRWAN1 LoRa Discovery Kit, ARM 32bit Cortex M0+ CPU

<특장점>
LoRaWAN 센서를 만들기에 적합한 보드이며, ARM Mbed OS를 지원한다. 원문 내용을 그대로 옮겨 보았다. 
"The B-L072Z-LRWAN1 LoRa®Discovery kit is a development tool to learn and develop solutions based on LoRa®and FSK/OOK technologies. This Discovery kit features an all-in-one open module CMWX1ZZABZ-091 (by Murata). The module is powered by an STM32L072CZ and an SX1276 transceiver."
<my postings>



ARMv7-A Series(32 bits)
3) BeagleBone Series - Sitara AM335x 1GHz ARM Cortex-A8 (***** Best website for developers)
<특장점>
현재 다른 보드에 비해 널리 알려져 있어, 관련 자료(book 포함)를 확보하기에 매우 유리하다. 2~3년 전에 BBB를 사용해 보았는데, 최근에 출시된 BB Green, BB Blue(Robot, Drone 용)도 사용해 보고 싶은 마음이다.

<my postings>
e) http://slowbootkernelhacks.blogspot.kr/2016/12/booting-beaglebone-black-with-yocto.html


4) SAMA5DX Series - Atmel ARM Cortex-A5 (536Mhz ~)  (***** Best website for developers)

<특장점>
Atmel 공식 site에 올라와 있는 내용이 매우 잘 정리되어 있어, 보고 따라 하는데 매우 효과적이다. 개인적으로 (여러가지 면에서) 매우 좋은 보드라고 생각한다 :)

<my postings>
5) RIoTBoard - Freescale(NXP) i.MX 6Solo, ARM Cortex-A9

<특장점>
Freescale(NXP를 거쳐 현재는 Qualcomm에 인수됨)보드가 대부분 가격이 비싼데 반해, 상대적으로 저렴한 편이다. 공식 site의 관련 내용이 상대적으로 빈약한 편이지만, freescale community site를 활용하면 충분할 것으로 보인다.

<my postings>
a) http://slowbootkernelhacks.blogspot.kr/2017/01/riot-board-based-on-freescale-imx-6solo.html
b) http://slowbootkernelhacks.blogspot.kr/2017/01/riot-board-device-tree-analysis.html
c) http://slowbootkernelhacks.blogspot.kr/2017/05/yocto-project-linux-device-driver.html
d) http://slowbootkernelhacks.blogspot.kr/2017/06/yocto-embedded-linux-systems-programming.html


6) UDOO NEO - Freescale(NXP) i.MX6 SoloX(ARM Cortex-A9 core + Cortex-M4 core)
<특장점>
ARM Cortex-A9와 Cortex-M4 I/O real-time co-processor(아두이노 용)를 통합한 processor를 사용. Freescale(NXP) chip을 사용하며, Wi-Fi/Bluetooth, 9 Axis sensor(accelerometer, Gyroscope, Magnetometer)를 장착하고 있음. 관련 website의 자료가 잘 정리되어 있어 개발자에게 충분한 도움이 될 것으로 보인다. 현재 Android 6.0.x Marshmallow version을 지원함.

<my postings>
a) http://slowbootkernelhacks.blogspot.kr/2017/02/how-to-build-android-sources-for-udoo.html
b) http://slowbootkernelhacks.blogspot.kr/2017/02/device-tree-analysis-for-udoo-neo-board.html
c) http://slowbootkernelhacks.blogspot.kr/2017/03/linux-kernel-programming-guide.html
d) http://slowbootkernelhacks.blogspot.kr/2017/03/efficient-linux-kernel-4x-programming.html
e) http://slowbootkernelhacks.blogspot.kr/2017/04/linux-device-driver-programming-using.html


7) NXP PICO-IMX6UL - Freescale(NXP) i.MX6UL(Cortex-A7) 528Mhz, hobbitboard

<특장점>
Android things(Android 기반의 IoT)를 지원하는 보드(이 밖에도 Google이 지원하는 Android things용 보드로는 Intel Edison, Raspberry Pi 3 등이 있음). Base board와 SOM board가 분리되어 있는 특징이 있음. Android 기반의 IoT를 생각하고 있다면 한번 써 보는 것도 좋을 듯 .. 근데, 아직은 Android things가 개발자 preview 상태인 듯 함(Brillo source를 내려 받았으나, build가 안됨).


8) MediaTek BPI-R2 - MediaTek MT7623N Quad-core ARM Cortex-A7, 2GB DDR3, 8GB eMMC, 5 10/100/1000 Ethernet Ports


<특장점>
Wi-Fi AP를 만들어 보는 시험을 하기에 적합할 듯 하다. BSP가 OpenWrt 기반으로 되어 있다. 같은 회사에서 만든 BPI-R64도 괜찮아 보인다.

<my postings>
a) https://slowbootkernelhacks.blogspot.com/2020/05/openwrt-access-point.html


9) ST STM32MP157C-DK2 - STM32MP157 ARM Cortex-A7(32 bit) + Cortex-M4(32 bit) MPU, ST PMIC STPMIC1, 4-Gbit DDR3L, 4" TFT 480x800 LCD, 5V/3A USB Type-C power supply ...

<특장점>
ST의 장점을 살려 Cortex-M4 MPU(coprocessor)와 ARM Cortex-A7 MPU(main processor)를 하나로 통합하였으며, main processor에는 Yocto로 생성한 OpenSTLinux를 기본으로 탑재하고 있다. TFT LCD가 기본으로 장착되어 있어, GUI나 동영상 관련 app을 개발 & 실험하기에 적합하다. 뿐만아니라 (모양은 좀 허접해 보이지만) STM32 MPU wiki page의 내용이 아주 잘 정리되어 있어, 개발에 많은 도움이 될 것으로 보인다.


<my postings>






g) https://slowbootkernelhacks.blogspot.com/2020/07/linux-kernel-programming-gpio-interrupt.html


ARMv8-A Series(64 bits)
10) DragonBoard 410c - Qualcomm Snapdragon 410, Quad-core ARM Cortex A53, 1.2GHz, 64bit capable

<특장점>
휴대폰 시장의 최강자인 Qualcomm chip을 사용한다는 점... 관련 site의 내용이 그럭 저럭 잘 정리되어 있는 듯 보인다. 또한, ARM Cortex A53, 64bit라는 점도 특이점이다. 96board !


11) PINE64 - Allwinner A64, Quad-core ARM Cortex A53, 1.2GHz, 64bit capable

<특장점>
Mobile application processor 중, 나름 강자인 Allwinner 사의 A64 chip을 사용하고 있으며, 아주 저렴한 가격($15 ~  $29)을 자랑한다. 주변 accessory 가격(예: 7인치 LCD가 $35.99)도 대부분 저렴한 편이다. 다양한 OS 즉, Armbian, Android, Remix(PC용 android), Windows IoT 등을 지원한다. 뿐만아니라 같은 chip으로 PINEBOOK이라는 매우 탐나는 노트북을 만들어 판매(주문하면 2달후 쯤에 받을 수 있는 듯)하고 있는데 가격이 $99(14인치 LCD 기준)이다.

<my postings>
a) https://slowbootkernelhacks.blogspot.kr/2017/07/pine-a64-64-bit-arm-linux.html

ROCK64 - Rockchip  RK3328, Quad-core ARM Cortex A53, 64bit, 4GB DDR3, USB 3.0
같은 회사(Pine microsystems Inc.)에서 개발한 아래 보드도 관심이 간다.


12) ESPRESSObin - Marvell ARMADA 3700 chip, dual-core ARM Cortex A53, 1.2GHz, 64bit capable, Official website
<특장점>
Marvell이 network에서 강점을 보인다고 할 수 있는데, Marvell chip을 사용하고 있다는 점이 장점이라면 장점임. 또한 앞서 소개한 SBC에 비해 Router(Gateway)를 target으로 한다는 점이 특이하다고 볼 수 있음. 물론 ARM Cortex A53, 64bit라는 점도 특이점임 ...

<my postings>
a) https://slowbootkernelhacks.blogspot.com/2020/04/espressobin-wireguard-vpn.html


13) Gl-iNet MV1000 - Marvell ARMADA 88F3720 chip, dual-core ARM Cortex A53, 1.0GHz, 64bit capable, Official website

<특장점>
ESPRESSObin board 보드와 거의 동일 spec의 완제품임. OpenWrt가 기본으로 탑재되어 있으나, Ubuntu를 올릴 수도 있음.


<my postings>
a) https://slowbootkernelhacks.blogspot.com/2020/05/glinet-mv1000-softether-vpn.html


=========================================================================================



현재 예정은 이와 같으나, 상황(새로운 것, 사용해보고 싶은 것)에 따라 다른 board로 대체될 수 있음을 미리 밝힌다.

 Slowboot         

2020년 5월 4일 월요일

ARM Mbed OS 위에 LoRaWAN 코드 올리기

이번 posting에서는 머리도 식힐겸, 비 Linux OS인 ARM Mbed OS를 이용하여 DISCO-L072CZ-LRWAN1 보드 LoRaWAN 코드를 올리는 과정을 소개해 보고자 한다. 오래 전에 Google Docs로 작성했던 내용인데, ARM Mbed OS 관련 기초편 정도로 보면 될 듯 하다.


참고로 본 blog를 통해 이미 소개된 바 있는 RTOS는 다음과 같다.

<Zephyr Project>

<RIOT OS>

Contents

1. ARM Mbed OS 소개
2. Mbed CLI w/ STM32 Nucleo F103RB
3. Mbed Studio
4. Mbed Online Compiler
5. DISCO-L072CZ-LRWAN1 보드
6. LoRaWAN의 (진짜^^)모든 것



1. ARM Mbed OS 소개

ARM Mbed OS(이하 Mbed OS로 통칭)는 FreeRTOS(https://www.freertos.org/), Zephyr(https://www.zephyrproject.org/) 등과 견줄만한 open source IoT OS 이다(ARM 사가 밀고 있어 파급력이 매우 큰 느낌이다. 그래서 선택했다^^). Security, Connectivity, RTOS 적인 특징을 갖추고 있으며, 주로 ARM Cortex-M micro controller에 탑재하는 용도로 사용할 수 있다. 따라서 Arduino(AVR 계열) 등에 올리기에는 좀 덩치가 크다고 볼 수 있다~


[그림 1.1] ARM Mbed OS home page


Mbed OS가 활용되는 분야는 매우  다양하다. 이를 확인해 볼 수 있는 site가 아래에 있으니 한번 훑어 보시기 바란다. 재밌는 내용이 아주 많다~




[그림 1.2] ARM Mbed OS가 사용된 다양한 예


Mbed OS가 갖고 있는 가장 큰 장점은 뭐니 뭐니 해도 다양한 connectivity 환경을 지원한다는 점이 아닐까 싶다. 이 중 우리는 LoRaWAN에 관심이 큰 만큼 앞으로 이 부분을 집중적으로 살펴 보아야 할 것이다.


[그림 1.3] ARM Mbed OS Connectivity


Mbed OS의 전체 architecture는 다음과 같다. 이와 관련해서는 추후 하나씩 세세하게 뜯어 보아야 할 것이다.


[그림 1.4] ARM Mbed OS Architecture


먼저, Mbed OS를 사용하기 전에 자신의 계정을 등록(그림 1.1의 아래 버튼 선택) 하도록 하자. 계정 등록 방법은 아주 간단한 사항이라 여기서는 별도로 정리하지는 않겠다. 각자 시도해 보기 바란다~


[그림 1.5 계정 등록 버튼]
참고: Mbed OS 사용자 계정은 Mbed Studio, Mbed Online Compiler 사용시 반드시 필요하다.

[그림 1.6] Mbed OS 계정 등록 모습


<Mbed OS 교육 과정>
국내 ARM 교육 기관에서 시행하는 Mbed OS 교육 과정을 참고삼아 정리해 보았다. 앞으로 이런 정도의 내용을 파악해야 한다는 야그^^
1 일차 
1. Open-source Hardware Platform
  - Open source hardware 소개
  - mbed 소개
  - mbed를 이용한 개발 사례 소개
2. ARM Processor
  - Arm Processor 소개
  - Arm Processor 종류
  - Arm Interrupt Controller (GIC, NVIC)
  - Arm SysTick Timer
  - STM32 Cube & Hal Library 
  - Discussion
3. Mbed
  - Mbed ?
  - mbed 개발환경 소개
  - mbed 프로그래밍 흐름
  - mbed 시작하기 : 웹컴파일러를 이용한 예제 빌드 및 실행
  - mbed CLI : 환경 설정 및 예제 빌드 및 실행
  - mbed Studio 설치 및 기본예제 실행
 2 일차 
4. Mbed DataType
  - mbed 데이터형 
  - mbed.h 분석
5. Peripheral 이론 및 실습
  - GPIO (LED, Button)
  - GPIO BusOut (7Segment)
  - Analog Input/Output (가변저항, LED)
  - Timer & Interrupt
  - PWM (LED, Brightness)
  - I2C (STM Sensor Hub Control)
  - SPI (SD Block Driver)
  - QSPI, Little FileSystem
  - Watchdog & ResetReason
  - MbedCRC
 3 일차 
6. Mbed-OS
  - RTOS
  - mbed-os
  - mbed-os Thread
  - mbed-os Mutex
  - mbed-os Semaphore
  - mbed-os Queue
  - mbed-os MemoryPool
  - mbed-os Mail
  - mbed-os EventFlags
  - mbed-os ConditionVariable
  - mbed-os RtosTimer
 4 일차 
 - mbed-os EventQueue 인터럽트 처리
  - mbed-os EventQueue Shared Event
  - mbed-os Event
  - mbed-os Callback
7. Mbed-OS Configuration System
  - configuration parameter 정의
  - mbed_lib.json 분석
  - mbed_app.json 분석
 5 일차 
8. Pelion Device Management
  - Pelion Service ?
  - LWM2M
  - Pelion 계정생성
  - DISCO_L475E_IOT01A 보드를 사용하여 Pelion 연결하기


교육 기관에 불필요하게 돈을 기부(?)할 필요는 없다. 적당한 개발 보드를 하나 구입한 후, 아래 책 정도를 보면서 study를 진행하는 것으로 충분하다 :) 사실 Mbed OS와 같은 RTOS ~ 그렇게 어렵지 않다 ?! 그냥 하는 소리가 아니다 :) Linux가 (상대적으로) 훨씬 어렵다...


[그림 1.7] 참고 도서


2. Mbed CLI w/STM32 Nucleo F103RB

Mbed OS 환경에서 firmware를 개발하는데 사용되는 도구로는 "Mbed Studio”, “Mbed Online Compiler”, “Mbed CLI” 세 종류가 있다. 이를 하나씩 하나씩 사용해 보기로 하자.

먼저, 이번 절에서는 (linux 개발자를 위해)Mbed OS CLI를 이용하여 sample code(mbed-os 포함)를 build하는 과정을 소개해 보기로 하겠다. 동작 시험을 위해서는 아래 STM32 Nucleo-F103RB 보드를 사용하였다.


"Mbed CLI 만 있어도 개발하는데 아무런 문제가 없다 - chunghan.yi@gmail.com”


[그림 2.1] mbed CLI


[그림 2.2] Nucleo F103RB 보드


참고: Nucleo F103RB 보드는 가격이 저렴(만원이 조금 넘음)하다.


a) Ubuntu 18.04에 Mbed CLI 설치하기
지금부터 설명하는 내용은 Ubuntu 18.04 desktop을 기준으로 하며, 아래 site의 내용을 기초로 하였다.




<Install dependencies>
$ sudo apt install python2.7 python-pip git mercurial
  • 보통 이정도는 이미 설치되어 있다. 혹시 설치 되어 있지 않다면, 각자 설치하기 바란다.


<Install Mbed CLI>
$ pip install mbed-cli
  • Mbed CLI는 python으로 구현되어 있다.
$ mbed --help
  • mbed가 정상적으로 설치되었는지를 확인하기 위해 위의 명령 실행


<Install a compiler>
  • 헐, 여기서는 download할 수 가 없군...


  • 그럼 여기서 받도록 하자.
  • gcc-arm-none-eabi-9-2019-q4-major-x86_64-linux.tar.bz2


참고: ARM Mbed OS를 build하기 위해 사용 가능한 compiler로는 GCC Arm, Arm Compiler 5, Arm Compiler 6 or IAR 등을 생각해 볼 수 있다. 우리는 이중에서 open source인 GCC Arm compiler를 사용할 것이다.
[그림 2.3] GNU-RM Downloads site


$ cd ~/workspace/MbedOS
$ tar xvjf gcc-arm-none-eabi-9-2019-q4-major-x86_64-linux.tar.bz2
$ sudo mv ./gcc-arm-none-eabi-9-2019-q4-major  /opt
  • 반드시 /opt 아래로 이동시켜야 하는 것은 아니다.
$ vi ~/.bashrc
...
export MBED_GCC_ARM_PATH=/opt/gcc-arm-none-eabi-9-2019-q4-major/bin
export PATH=/opt/gcc-arm-none-eabi-9-2019-q4-major/bin:$PATH
~


$ source ~/.bashrc
  • 터미널을 다시 실행해도 된다.
참고: 이상의 내용은 (일반적으로) toolchain 설정시 공통적으로 수행하는 부분에 해당한다.


[그림 2.4] ARM gcc version - gcc 9.2.1 버젼


$ mbed config -G GCC_ARM_PATH /opt/gcc-arm-none-eabi-9-2019-q4-major/bin
  • Mbed CLI가 arm compiler의 위치를 알 수  있도록 해 줌.


<Bash completion>
  • mbed-cli bash completion(자동 완성 기능)을 설치하기 위해서는 아래 절차를 따른다.
참고: bash completion은 bash 환경에서 명령 전체를 입력할 필요 없이 <TAB> 키를 사용하여 명령을 좀 더 편하게 입력하는 방식을 말한다.


  • Mbed-cli를 내려 받는다.
'mbed-cli'에 복제합니다...
remote: Enumerating objects: 49, done.
remote: Counting objects: 100% (49/49), done.
remote: Compressing objects: 100% (39/39), done.
remote: Total 3693 (delta 23), reused 26 (delta 9), pack-reused 3644
오브젝트를 받는 중: 100% (3693/3693), 1.31 MiB | 1.40 MiB/s, 완료.
델타를 알아내는 중: 100% (2078/2078), 완료.


$ cd mbed-cli/tools/bash_completion
$ mkdir -p ~/.bash_completion.d/
$ cp mbed ~/.bash_completion.d/
  • 이후 터미널을 다시 실행해야 한다.


chyi@earth:~/workspace/MbedOS$ mbed config --list
[mbed] Global config:
GCC_ARM_PATH=/opt/gcc-arm-none-eabi-9-2019-q4-major/bin

[mbed] Local config (/home/chyi/workspace/MbedOS):
Couldn't find valid mbed program in /home/chyi/workspace/MbedOS


b) LED Blinky 예제 코드 돌려 보기


[그림 2.5] mbed-os 예제 코드(1)

[그림 2.6] mbed-os 예제 코드(2)


$ cd ~/workspace/MbedOS
$ mkdir projects; cd projects
$ mbed import https://github.com/ARMmbed/mbed-os-example-blinky#mbed-os-5.11.0


[mbed] Working path "/home/chyi/workspace/MbedOS/projects" (directory)
[mbed] Importing program "mbed-os-example-blinky" from "https://github.com/ARMmbed/mbed-os-example-blinky" at branch/tag "mbed-os-5.11.0"
[mbed] Adding library "mbed-os" from "https://github.com/ARMmbed/mbed-os" at rev #6a0a86538c0b


$ cd mbed-os-example-blinky
$ ls -la
합계 52
drwxr-xr-x  4 chyi chyi 4096 12월 14 17:27 .
drwxr-xr-x  6 chyi chyi 4096 12월 14 17:27 ..
drwxr-xr-x  8 chyi chyi 4096 12월 14 17:27 .git
-rw-r--r--  1 chyi chyi   32 12월 14 17:27 .gitignore
-rw-r--r--  1 chyi chyi    7 12월 14 17:27 .mbed
-rw-r--r--  1 chyi chyi 5942 12월 14 17:27 README.md
-rw-r--r--  1 chyi chyi  522 12월 14 17:27 main.cpp
drwxr-xr-x 18 chyi chyi 4096 12월 14 17:27 mbed-os
-rw-r--r--  1 chyi chyi   77 12월 14 17:27 mbed-os.lib
-rw-r--r--  1 chyi chyi  354 12월 14 17:27 mbed_app.json
-rw-r--r--  1 chyi chyi 1339 12월 14 17:27 mbed_settings.py
-rw-r--r--  1 chyi chyi 3699 12월 14 17:27 stats_report.h


[그림 2.7] LED blinky 예제 코드 - main.cpp


$ mbed compile -m K64F -t GCC_ARM
  • -m: target board, -t: toolchain
  • NXP K64F board(가격: $35정도 함)는 아래 그림과 같이 생겼는데, 여기서는 이 board에 올릴 수 있는 firmware image를 생성해 보도록 해 보겠다.
  • 참고: mbed OS 문서 내용이 이 보드를 기준으로 설명되어 있다.


[그림 2.8] NXP FRDM-K64F 보드


[mbed] Working path "/home/chyi/workspace/MbedOS/projects/mbed-os-example-blinky" (program)
Building project mbed-os-example-blinky (K64F, GCC_ARM)
Scan: mbed-os-example-blinky
Compile [  0.1%]: except.S
Compile [  0.3%]: mbed_tz_context.c
Compile [  0.4%]: rf_configuration.c
[Warning] rf_configuration.c@104,25: comparison of integer expressions of different signedness: 'uint32_t' {aka 'long unsigned int'} and 'int' [-Wsign-compare]
Compile [  0.5%]: MCR20Drv.c
Compile [  0.7%]: mbed_fault_handler.c
Compile [  0.8%]: at24mac.cpp
Compile [  0.9%]: psa_prot_internal_storage.cpp
Compile [  1.1%]: fslittle_test.c
Compile [  1.2%]: fsfat_test.c
Compile [  1.3%]: pits_impl.cpp
Compile [  1.5%]: main.cpp
Compile [  1.6%]: FlashIAPBlockDevice.cpp
Compile [  1.7%]: AnalogIn.cpp
Compile [  1.9%]: NanostackRfPhyMcr20a.cpp
Compile [  2.0%]: SDBlockDevice.cpp
[Warning] SDBlockDevice.cpp@794,24: this statement may fall through [-Wimplicit-fallthrough=]
Compile [  2.2%]: NanostackRfPhyAtmel.cpp
Compile [  2.3%]: NanostackRfPhys2lp.cpp
Compile [  2.4%]: BusIn.cpp
Compile [  2.6%]: CAN.cpp
Compile [  2.7%]: BusInOut.cpp
Compile [  2.8%]: ESP8266.cpp
[Warning] mbed_error.h@52,55: left shift of negative value [-Wshift-negative-value]
[Warning] mbed_error.h@52,55: left shift of negative value [-Wshift-negative-value]
Compile [  3.0%]: BusOut.cpp
Compile [  3.1%]: Ethernet.cpp
...[중간 생략]...
Compile [ 99.6%]: sleep.c
Compile [ 99.7%]: i2c_api.c
Compile [ 99.9%]: fsl_common.c
Compile [100.0%]: rtc_api.c
Link: mbed-os-example-blinky
Elf2Bin: mbed-os-example-blinky
| Module             |         .text |       .data |        .bss |
|--------------------|---------------|-------------|-------------|
| [fill]             |     160(+160) |       4(+4) | 2122(+2122) |
| [lib]/c.a          | 32042(+32042) | 2472(+2472) |     89(+89) |
| [lib]/gcc.a        |   3104(+3104) |       0(+0) |       0(+0) |
| [lib]/misc         |     180(+180) |       4(+4) |     28(+28) |
| [lib]/nosys.a      |       32(+32) |       0(+0) |       0(+0) |
| [lib]/stdc++.a     |         4(+4) |       0(+0) |       0(+0) |
| main.o             |     906(+906) |       0(+0) |     12(+12) |
| mbed-os/cmsis      |   1033(+1033) |       0(+0) |       0(+0) |
| mbed-os/components |     210(+210) |       0(+0) |       0(+0) |
| mbed-os/drivers    |     633(+633) |       0(+0) |       0(+0) |
| mbed-os/features   |     156(+156) |       0(+0) |   192(+192) |
| mbed-os/hal        |   2311(+2311) |       8(+8) |   152(+152) |
| mbed-os/platform   |   4507(+4507) |   260(+260) |   226(+226) |
| mbed-os/rtos       |   9379(+9379) |   168(+168) | 6029(+6029) |
| mbed-os/targets    |   9235(+9235) |     12(+12) |   382(+382) |
| Subtotals          | 63892(+63892) | 2928(+2928) | 9232(+9232) |
Total Static RAM memory (data + bss): 12160(+12160) bytes
Total Flash memory (text + data): 66820(+66820) bytes

Image: ./BUILD/K64F/GCC_ARM/mbed-os-example-blinky.bin


$ cd BUILD/
$ ls -la
합계 12
drwxr-xr-x 3 chyi chyi 4096 12월 14 17:28 .
drwxr-xr-x 3 chyi chyi 4096 12월 14 17:28 ..
drwxr-xr-x 3 chyi chyi 4096 12월 14 17:28 GCC_ARM
chyi@earth:~/workspace/MbedOS/projects/mbed-os-example-blinky/BUILD/K64F$ cd GCC_ARM/
chyi@earth:~/workspace/MbedOS/projects/mbed-os-example-blinky/BUILD/K64F/GCC_ARM$ ls -la
합계 5728
drwxr-xr-x  3 chyi chyi    4096 12월 14 17:28 .
drwxr-xr-x  3 chyi chyi    4096 12월 14 17:28 ..
-rw-r--r--  1 chyi chyi   13879 12월 14 17:28 .includes_90b1235f63435861e0c680c5463f9e2f.txt
-rw-r--r--  1 chyi chyi       0 12월 14 17:28 .includes_d41d8cd98f00b204e9800998ecf8427e.txt
-rw-r--r--  1 chyi chyi   62218 12월 14 17:28 .link_options.txt
-rw-r--r--  1 chyi chyi    4526 12월 14 17:28 .link_script.ld
-rw-r--r--  1 chyi chyi     356 12월 14 17:28 .profile-asm
-rw-r--r--  1 chyi chyi    2687 12월 14 17:28 .profile-c
-rw-r--r--  1 chyi chyi    2729 12월 14 17:28 .profile-cxx
-rw-r--r--  1 chyi chyi    2634 12월 14 17:28 .profile-ld
-rw-r--r--  1 chyi chyi   10111 12월 14 17:28 main.d
-rw-r--r--  1 chyi chyi   62912 12월 14 17:28 main.o
drwxr-xr-x 11 chyi chyi    4096 12월 14 17:28 mbed-os
-rwxr-xr-x  1 chyi chyi   67552 12월 14 17:28 mbed-os-example-blinky.bin  ⇐ 얘가 실제 board에 탑재될 firmware 이미지 파일임.
-rwxr-xr-x  1 chyi chyi 1548092 12월 14 17:28 mbed-os-example-blinky.elf
-rw-r--r--  1 chyi chyi 3946951 12월 14 17:28 mbed-os-example-blinky.map
-rw-r--r--  1 chyi chyi    2227 12월 14 17:28 mbed-os-example-blinky_map.csv
-rw-r--r--  1 chyi chyi   44670 12월 14 17:28 mbed-os-example-blinky_map.html
-rw-r--r--  1 chyi chyi    3935 12월 14 17:28 mbed-os-example-blinky_map.json
-rw-r--r--  1 chyi chyi   46172 12월 14 17:28 mbed_config.h

c) Nucleo F103RB 보드에 mbed-os(firmware) 올리기
(개인적으로) mbed-os를 지원하는 STM32 Nucleo F103RB 보드가 하나 있어, 여기에 mbed-os를 올려 보도록 하겠다.


$ cd ~/workspace/new_boards/MbedOS/mbed-os-example-blinky
$ mbed target NUCLEO_F103RB
  • Target을 지정한다.
or
$ mbed target detect
  • 특정 target 명을 알 수 없을 경우, 이렇게 할 수도 있다.
[mbed] Working path "/home/chyi/workspace/new_boards/MbedOS/mbed-os-example-blinky" (program)
[mbed] detect now set as default target in program "mbed-os-example-blinky"


$ mbed toolchain GCC_ARM
  • Toolchain을 지정한다. 이렇게 지정하는 이유는 compile 시 일일히 지정하지 않기 위함이다.


$ mbed compile -c
  • clean build를 한다.


$ mbed compile -f
  • flash writing을 한다.
[mbed] Working path "/home/chyi/workspace/new_boards/MbedOS/mbed-os-example-blinky" (program)
[mbed] Detected "NUCLEO_F103RB" connected to "/media/chyi/NODE_F103RB" and using com port "/dev/ttyACM0"
[Warning] @,: Compiler version mismatch: Have 9.2.1; expected version >= 6.0.0 and < 7.0.0
Building project mbed-os-example-blinky (NUCLEO_F103RB, GCC_ARM)
Scan: mbed-os-example-blinky
Link: mbed-os-example-blinky
Elf2Bin: mbed-os-example-blinky
| Module             |     .text |    .data |     .bss |
|--------------------|-----------|----------|----------|
| [fill]             |    92(+0) |   12(+0) |   32(+0) |
| [lib]/c.a          | 27650(+0) | 2472(+0) |   89(+0) |
| [lib]/gcc.a        |  4152(+0) |    0(+0) |    0(+0) |
| [lib]/misc         |   208(+0) |   12(+0) |   28(+0) |
| main.o             |   918(+0) |    4(+0) |   36(+0) |
| mbed-os/cmsis      |  1033(+0) |    0(+0) |   84(+0) |
| mbed-os/components |    70(+0) |    0(+0) |    0(+0) |
| mbed-os/drivers    |   855(+0) |    4(+0) |  100(+0) |
| mbed-os/features   |   172(+0) |    4(+0) |  192(+0) |
| mbed-os/hal        |  2067(+0) |    4(+0) |   68(+0) |
| mbed-os/platform   |  4027(+0) |  260(+0) |  210(+0) |
| mbed-os/rtos       |  8100(+0) |  168(+0) | 5969(+0) |
| mbed-os/targets    |  6774(+0) |    4(+0) |  368(+0) |
| Subtotals          | 56118(+0) | 2944(+0) | 7176(+0) |
Total Static RAM memory (data + bss): 10120(+0) bytes
Total Flash memory (text + data): 59062(+0) bytes

Image: ./BUILD/NUCLEO_F103RB/GCC_ARM/mbed-os-example-blinky.bin


자, flash writing에 성공하였다. F103RB 보드에 LED가 1초 간격으로 깜빡거린다.


[그림 2.9] Nucleo F103RB 보드에 firmware(mbed-os)를 올린 모습 - 가운데 녹색 LED blinking 중


$ mbed compile -f --sterm
  • Minicom 등과 같은 serial console emulator를 통해 board 상태를 확인하기 위해 설정해 준다.
[mbed] Working path "/home/chyi/workspace/new_boards/MbedOS/mbed-os-example-blinky" (program)
[mbed] Detected "NUCLEO_F103RB" connected to "/media/chyi/NODE_F103RB" and using com port "/dev/ttyACM0"
[Warning] @,: Compiler version mismatch: Have 9.2.1; expected version >= 6.0.0 and < 7.0.0
Building project mbed-os-example-blinky (NUCLEO_F103RB, GCC_ARM)
Scan: mbed-os-example-blinky
Link: mbed-os-example-blinky
Elf2Bin: mbed-os-example-blinky
| Module             |     .text |    .data |     .bss |
|--------------------|-----------|----------|----------|
| [fill]             |    92(+0) |   12(+0) |   32(+0) |
| [lib]/c.a          | 27650(+0) | 2472(+0) |   89(+0) |
| [lib]/gcc.a        |  4152(+0) |    0(+0) |    0(+0) |
| [lib]/misc         |   208(+0) |   12(+0) |   28(+0) |
| main.o             |   918(+0) |    4(+0) |   36(+0) |
| mbed-os/cmsis      |  1033(+0) |    0(+0) |   84(+0) |
| mbed-os/components |    70(+0) |    0(+0) |    0(+0) |
| mbed-os/drivers    |   855(+0) |    4(+0) |  100(+0) |
| mbed-os/features   |   172(+0) |    4(+0) |  192(+0) |
| mbed-os/hal        |  2067(+0) |    4(+0) |   68(+0) |
| mbed-os/platform   |  4027(+0) |  260(+0) |  210(+0) |
| mbed-os/rtos       |  8100(+0) |  168(+0) | 5969(+0) |
| mbed-os/targets    |  6774(+0) |    4(+0) |  368(+0) |
| Subtotals          | 56118(+0) | 2944(+0) | 7176(+0) |
Total Static RAM memory (data + bss): 10120(+0) bytes
Total Flash memory (text + data): 59062(+0) bytes
Image: ./BUILD/NUCLEO_F103RB/GCC_ARM/mbed-os-example-blinky.bin


$ sudo minicom -s
  • /dev/ttyACM0, 115200, 8N1


[그림 2.10] Nucleo F103RB 보드 - minicom 설정


어떤가 ? 간단하지 않은가 ?


3. Mbed Studio

Mbed Studio는 MS Visual Studio 처럼 IDE 환경에서 개발하고자 할 때 설치하여 사용한다. 현재는 Windows & MacOS 만을 지원한다. Linux 개발자라면 Mbed CLI를 이용하면 된다. 따라서 본 문서에서는 Mbed Studio 설치 과정만 간단히 정리해 보았다. 나머지 build 이후의 작업은 직접 해 보시길~




[그림 3.1] Mbed Studio 설치 Page


그럼, 이제 부터 Windows 10에 설치해 보도록 하겠다.


[그림 3.2] Mbed Studio 설치 과정(1)
[그림 3.3] Mbed Studio 설치 과정(2)


[그림 3.4] Mbed Studio 설치 과정(3) - 1장에서 등록한 사용자 계정 사용


[그림 3.5] Mbed Studio 실행 모습


Example code를 내려 받아 build해 보자. 어렵지 않으니 이부분은 독자 여러분의 몫으로 돌리겠다.


4. Mbed Online Compiler

지금 부터는 Mbed Online Compiler를 사용하여 firmware를 개발하는 방법을 소개해 보도록 하겠다. Web을 통해 개발을 할 수 있는 아주 편리한 방법이다 :)



[그림 4.1] Mbed OS Online Compiler - 사용하려는 보드 선택(검색)(1)


[그림 4.2] Mbed OS Online Compiler - 우측 "Add to your Mbed Compiler” 버튼 선택

[그림 4.3] Mbed OS Online Compiler - 우측 "Open Mbed Compiler” 버튼 선택


[그림 4.4] Mbed OS Online Compiler 화면


[그림 4.5] Mbed OS Online Compiler - Compile 모습


참고: Compile이 정상적으로 완료되면 bin 파일이 자동으로 download 된다.


<firmware writing하기>
Online compiler에서 compile하여  생성한 bin 파일을 Mbed 보드의 USB device folder로 복사한 후, reset 해 주면 된다.
  • F103RB 상에서 이렇게 했는데, 잘 안되는 것 같다(물론 LED Blinky code를 테스트해 봄)… 나중에 다시 시도해 보기로 하자.

5. DISCO-L072CZ-LRWAN1 보드

이번 장에서는 DISCO_L072CZ-LRWAN1 보드에 lorawan firmware를 올려 보도록 하겠다.


a) STM32 LoRa and Sigfox Discovery Kit




[그림 5.1] DISCO_L072CZ-LRWAN1 보드


https://kr.mouser.com/ProductDetail/STMicroelectronics/B-L072Z-LRWAN1?qs=PzRbFReKxL2UVPVODSIYig%3D%3D&gclid=EAIaIQobChMI9bXag6m55gIVy2kqCh0uSAiwEAQYASABEgL7BPD_BwE
참고(가격): ₩60,915 (좀 비싸다)


아래에 Microcontroller(줄여서 micom)와 보드의 주요 특징을 열거해 보았다.




다음 4개의 그림은 실제 programming 시 중요한 부분(센서 연결시 필요)이라고 할 수 있는 확장 pin header에 대한 pin map 정보를 표현한 것이다.


[그림 5.2] Arduino-compatible pin header(보드 top 왼쪽 pin - CN4, CN6)
참고: 위의 그림은 Antenna가 아래 방향에 있는 그림이다.
[그림 5.3] Arduino-compatible pin header(보드 top 오른쪽 pin - CN1)

[그림 5.4] Morpho pin header(보드 top 왼쪽 pin - CN2)


[그림 5.5] Morpho pin header(보드 top 왼쪽 pin - CN3)


b) lorawan example build하기
지금 부터 설명하는 내용은 아래 site를 기초로 한다.


$ cd ~/workspace/new_boards/MbedOS
$ mbed import mbed-os-example-lorawan
[mbed] Working path "/home/chyi/workspace/new_boards/MbedOS" (directory)
[mbed] Importing program "mbed-os-example-lorawan" from "https://github.com/ARMmbed/mbed-os-example-lorawan" at latest revision in the current branch
[mbed] Adding library "mbed-lora-radio-drv" from "https://github.com/ARMmbed/mbed-semtech-lora-rf-drivers" at rev #6012fa43cf9f
[mbed] Adding library "mbed-os" from "https://github.com/ARMmbed/mbed-os" at rev #b6e5a0a8afa3
[mbed] Auto-installing missing Python modules (pycryptodome, psutil, click)...
[mbed] ERROR: Missing Python modules were not auto-installed.
       The Mbed OS tools in this program require the following Python modules: pycryptodome, psutil, click
       You can install all missing modules by running "pip install -r requirements.txt" in "/home/chyi/workspace/new_boards/MbedOS/mbed-os-example-lorawan/mbed-os"
       On Posix systems (Linux, etc) you might have to switch to superuser account or use "sudo"
---


$ cd mbed-os-example-lorawan/mbed-os
$ sudo pip install -r requirements.txt
  • pycryptodome, psutil, click 등 필요한 python package를 자동으로 설치해 준다.


<Supported MCUs>
ARCH_BLE,              ARCH_BLE_BOOT,         ARCH_BLE_OTA, 
ARCH_GPRS,             ARCH_LINK,             ARCH_LINK_BOOT, 
ARCH_LINK_OTA,         ARCH_MAX,              ARCH_PRO, 
ARDUINO_NANO33BLE,     ARM_CM3DS_MPS2,        ARM_IOTSS_BEID, 
ARM_MPS2_M0,           ARM_MPS2_M0P,          ARM_MPS2_M3, 
ARM_MPS2_M4,           ARM_MPS2_M7,           ARM_MUSCA_A1_NS, 
ARM_MUSCA_A1_S,        B96B_F446VE,           BLUEPILL_F103C8, 
CC3220SF_LAUNCHXL,     CY8CKIT_062S2_43012,   CY8CKIT_062_BLE, 
CY8CKIT_062_WIFI_BT,   CY8CPROTO_062_4343W,   CY8CPROTO_064_SB, 
CYW943012P6EVB_01,     DELTA_DFBM_NQ620,      DELTA_DFCM_NNN40, 
DELTA_DFCM_NNN40_BOOT, DELTA_DFCM_NNN40_OTA,  DELTA_DFCM_NNN50, 
DELTA_DFCM_NNN50_BOOT, DELTA_DFCM_NNN50_OTA,  DISCO_F051R8, 
DISCO_F100RB,          DISCO_F303VC,          DISCO_F334C8, 
DISCO_F401VC,          DISCO_F407VG,          DISCO_F413ZH, 
DISCO_F429ZI,          DISCO_F469NI,          DISCO_F746NG, 
DISCO_F769NI,          DISCO_L053C8,          DISCO_L072CZ_LRWAN1,     ⇐ 이거네 ...
DISCO_L475VG_IOT01A,   DISCO_L476VG,          DISCO_L496AG, 
DISCO_L4R9I,           EFM32GG11_STK3701,     EFM32GG_STK3700, 
EFM32HG_STK3400,       EFM32LG_STK3600,       EFM32PG12_STK3402, 
EFM32PG_STK3401,       EFM32WG_STK3800,       EFM32ZG_STK3200, 
ELEKTOR_COCORICO,      ELMO_F411RE,           EP_AGORA, 
EV_COG_AD3029LZ,       EV_COG_AD4050LZ,       FF1705_L151CC, 
FF_LPC546XX,           FUTURE_SEQUANA,        FUTURE_SEQUANA_M0, 
FVP_MPS2_M0,           FVP_MPS2_M0P,          FVP_MPS2_M3, 
FVP_MPS2_M4,           FVP_MPS2_M7,           GD32_E103VB, 
GD32_F307VG,           GD32_F450ZI,           GR_LYCHEE, 
HEXIWEAR,              HRM1017,               HRM1017_BOOT, 
HRM1017_OTA,           IM880B,                K20D50M, 
K22F,                  K64F,                  K66F, 
K82F,                  KL05Z,                 KL25Z, 
KL26Z,                 KL27Z,                 KL43Z, 
KL46Z,                 KL82Z,                 KW24D, 
KW41Z,                 LPC1114,               LPC11C24, 
LPC11U24,              LPC11U24_301,          LPC11U34_421, 
LPC11U35_401,          LPC11U35_501,          LPC11U35_501_IBDAP, 
LPC11U35_Y5_MBUG,      LPC11U37H_401,         LPC11U37_501, 
LPC11U68,              LPC1347,               LPC1549, 
LPC1768,               LPC1769,               LPC4088, 
LPC4088_DM,            LPC4330_M0,            LPC4330_M4, 
LPC4337,               LPC54114,              LPC546XX, 
LPC55S69_NS,           LPC55S69_S,            LPC810, 
LPC812,                LPC824,                LPCCAPPUCCINO, 
MAX32600MBED,          MAX32620FTHR,          MAX32620HSP, 
MAX32625MBED,          MAX32625NEXPAQ,        MAX32625PICO, 
MAX32630FTHR,          MAXWSNENV,             MBED_CONNECT_ODIN, 
MCU_LPC4088,           MICRONFCBOARD,         MIMXRT1050_EVK, 
MOTE_L152RC,           MTB_ACONNO_ACN52832,   MTB_ADV_WISE_1510, 
MTB_ADV_WISE_1530,     MTB_ADV_WISE_1570,     MTB_LAIRD_BL600, 
MTB_LAIRD_BL652,       MTB_LAIRD_BL654,       MTB_MTS_DRAGONFLY, 
MTB_MTS_XDOT,          MTB_MURATA_ABZ,        MTB_MURATA_WSM_BL241, 
MTB_MXCHIP_EMW3166,    MTB_RAK811,            MTB_STM32_F439, 
MTB_STM_L475,          MTB_STM_S2LP,          MTB_UBLOX_NINA_B1, 
MTB_UBLOX_ODIN_W2,     MTB_USI_WM_BN_BM_22,   MTM_MTCONNECT04S, 
MTM_MTCONNECT04S_BOOT, MTM_MTCONNECT04S_OTA,  MTS_DRAGONFLY_F411RE, 
MTS_DRAGONFLY_L471QG,  MTS_GAMBIT,            MTS_MDOT_F405RG, 
MTS_MDOT_F411RE,       NCS36510,              NRF51822, 
NRF51822_BOOT,         NRF51822_OTA,          NRF51822_Y5_MBUG, 
NRF51_DK,              NRF51_DK_BOOT,         NRF51_DK_LEGACY, 
NRF51_DK_OTA,          NRF51_DONGLE,          NRF51_DONGLE_BOOT, 
NRF51_DONGLE_LEGACY,   NRF51_DONGLE_OTA,      NRF51_MICROBIT, 
NRF51_MICROBIT_B,      NRF51_MICROBIT_BOOT,   NRF51_MICROBIT_B_BOOT, 
NRF51_MICROBIT_B_OTA,  NRF51_MICROBIT_OTA,    NRF52840_DK, 
NRF52_DK,              NUCLEO_F030R8,         NUCLEO_F031K6, 
NUCLEO_F042K6,         NUCLEO_F070RB,         NUCLEO_F072RB, 
NUCLEO_F091RC,         NUCLEO_F103RB,         NUCLEO_F207ZG, 
NUCLEO_F302R8,         NUCLEO_F303K8,         NUCLEO_F303RE, 
NUCLEO_F303ZE,         NUCLEO_F334R8,         NUCLEO_F401RE, 
NUCLEO_F410RB,         NUCLEO_F411RE,         NUCLEO_F412ZG, 
NUCLEO_F413ZH,         NUCLEO_F429ZI,         NUCLEO_F439ZI, 
NUCLEO_F446RE,         NUCLEO_F446ZE,         NUCLEO_F746ZG, 
NUCLEO_F756ZG,         NUCLEO_F767ZI,         NUCLEO_H743ZI, 
NUCLEO_H743ZI2,        NUCLEO_L011K4,         NUCLEO_L031K6, 
NUCLEO_L053R8,         NUCLEO_L073RZ,         NUCLEO_L152RE, 
NUCLEO_L432KC,         NUCLEO_L433RC_P,       NUCLEO_L476RG, 
NUCLEO_L486RG,         NUCLEO_L496ZG,         NUCLEO_L496ZG_P, 
NUCLEO_L4R5ZI,         NUCLEO_L4R5ZI_P,       NUCLEO_WB55RG, 
NUMAKER_IOT_M263A,     NUMAKER_IOT_M487,      NUMAKER_PFM_M453, 
NUMAKER_PFM_M487,      NUMAKER_PFM_NANO130,   NUMAKER_PFM_NUC472, 
NU_PFM_M2351_NPSA_NS,  NU_PFM_M2351_NPSA_S,   NZ32_SC151, 
OC_MBUINO,             OSHCHIP,               RAPIDIOT_K64F, 
RAPIDIOT_KW41Z,        RBLAB_BLENANO,         RBLAB_BLENANO2, 
RBLAB_BLENANO_BOOT,    RBLAB_BLENANO_OTA,     RBLAB_NRF51822, 
RBLAB_NRF51822_BOOT,   RBLAB_NRF51822_OTA,    RDA5981X, 
REALTEK_RTL8195AM,     RHOMBIO_L476DMW1K,     RM6100, 
RM7100,                RO359B,                RZ_A1H, 
RZ_A1XX,               SAKURAIO_EVB_01,       SAMD21G18A, 
SAMD21J18A,            SAMG55J19,             SAML21J18A, 
SAMR21G18A,            SARA_NBIOT_EVK,        SDP_K1, 
SDT32620B,             SDT32625B,             SDT51822B, 
SDT52832B,             SDT64B,                SEEED_TINY_BLE, 
SEEED_TINY_BLE_BOOT,   SEEED_TINY_BLE_OTA,    SILICA_SENSOR_NODE, 
SSCI824,               STEVAL_3DP001V1,       TB_SENSE_1, 
TB_SENSE_12,           TEENSY3_1,             TMPM066, 
TMPM3H6,               TMPM3HQ,               TMPM46B, 
TMPM4G9,               TT_M3HQ,               TT_M4G9, 
TY51822R3,             TY51822R3_BOOT,        TY51822R3_OTA, 
UBLOX_C027,            UBLOX_C030_N211,       UBLOX_C030_R410M, 
UBLOX_C030_R412M,      UBLOX_C030_R41XM,      UBLOX_C030_U201, 
UBLOX_EVA_NINA,        UBLOX_EVK_NINA_B1,     UBLOX_EVK_ODIN_W2, 
UBRIDGE,               UHURU_RAVEN,           UNO_91H, 
USENSE,                VBLUNO51,              VBLUNO51_BOOT, 
VBLUNO51_LEGACY,       VBLUNO51_OTA,          VBLUNO52, 
VK_RZ_A1H,             WALLBOT_BLE,           WALLBOT_BLE_BOOT, 
WALLBOT_BLE_OTA,       WIO_3G,                WIO_BG96, 
WIZWIKI_W7500,         WIZWIKI_W7500ECO,      WIZWIKI_W7500P, 
XADOW_M0,              XBED_LPC1768,          XDOT_L151CC


$ cd ..
$ mbed compile -m DISCO_L072CZ_LRWAN1 -t GCC_ARM


[mbed] Working path "/home/chyi/workspace/new_boards/MbedOS/mbed-os-example-lorawan" (program)
[Warning] @,: Compiler version mismatch: Have 9.2.1; expected version >= 6.0.0 and < 7.0.0
Building project mbed-os-example-lorawan (DISCO_L072CZ_LRWAN1, GCC_ARM)
Scan: mbed-os-example-lorawan
Compile [  0.1%]: mbed_tz_context.c
Compile [  0.2%]: MCR20Drv.c
Compile [  0.3%]: at24mac.cpp
Compile [  0.5%]: main.cpp
[Warning] main.cpp@160,44: format '%d' expects argument of type 'int', but argument 2 has type 'int32_t' {aka 'long int'} [-Wformat=]
[Warning] main.cpp@167,70: format '%d' expects argument of type 'int', but argument 3 has type 'int32_t' {aka 'long int'} [-Wformat=]
[Warning] main.cpp@167,25: '%d' directive writing between 1 and 11 bytes into a region of size 8 [-Wformat-overflow=]
Compile [  0.6%]: rf_configuration.c
Compile [  0.7%]: NanostackRfPhyMcr20a.cpp
Compile [  0.8%]: SX126X_LoRaRadio.cpp
...[중간 생략]...
Compile [ 99.2%]: rtc_api.c
Compile [ 99.3%]: trace_helper.cpp
Compile [ 99.4%]: serial_api.c
Compile [ 99.5%]: sleep.c
Compile [ 99.7%]: trng_api.c
Compile [ 99.8%]: watchdog_api.c
Compile [ 99.9%]: us_ticker.c
Compile [100.0%]: stm_spi_api.c
Link: mbed-os-example-lorawan
Elf2Bin: mbed-os-example-lorawan
| Module                     |           .text |       .data |        .bss |
|----------------------------|-----------------|-------------|-------------|
| [fill]                     |       126(+126) |       8(+8) |     27(+27) |
| [lib]/c.a                  |   29124(+29124) | 2472(+2472) |     89(+89) |
| [lib]/gcc.a                |   12740(+12740) |       0(+0) |       0(+0) |
| [lib]/m.a                  |       552(+552) |       0(+0) |       0(+0) |
| [lib]/misc                 |       192(+192) |       4(+4) |     28(+28) |
| main.o                     |       978(+978) |       0(+0) | 4020(+4020) |
| mbed-lora-radio-drv/SX126X |         54(+54) |       0(+0) |       0(+0) |
| mbed-lora-radio-drv/SX1272 |       292(+292) |       0(+0) |       0(+0) |
| mbed-lora-radio-drv/SX1276 |     8474(+8474) |       0(+0) |       0(+0) |
| mbed-os/components         |         80(+80) |       0(+0) |       0(+0) |
| mbed-os/drivers            |     2192(+2192) |       0(+0) |   596(+596) |
| mbed-os/events             |     1560(+1560) |       0(+0) |       0(+0) |
| mbed-os/features           |   26910(+26910) |       4(+4) |       0(+0) |
| mbed-os/hal                |     1732(+1732) |       8(+8) |   130(+130) |
| mbed-os/platform           |     4714(+4714) |   260(+260) |   412(+412) |
| mbed-os/rtos               |   10598(+10598) |   168(+168) | 3164(+3164) |
| mbed-os/targets            |   13180(+13180) |       4(+4) | 1230(+1230) |
| trace_helper.o             |           2(+2) |       0(+0) |       0(+0) |
| Subtotals                  | 113500(+113500) | 2928(+2928) | 9696(+9696) |
Total Static RAM memory (data + bss): 12624(+12624) bytes
Total Flash memory (text + data): 116428(+116428) bytes

Image: ./BUILD/DISCO_L072CZ_LRWAN1/GCC_ARM/mbed-os-example-lorawan.bin


c) lorawan firmware 수정해서 보드에 올리기
보드(이하 disco 보드로 통칭)가 도착했으니, 이제 부터 firmware를 올려 보도록 하자. :)


[그림 5.6] DISCO_L072CZ-LRWAN1 보드 전원 연결 모습


먼저 mbed-os-example-lorawan/mbed_app.json 파일을 열고, KR920 주파수 설정 및 OTAA 설정 변경을 해 보자.


[그림 5.7] mbed_app.json 파일 내용


[그림 5.8] mbed_app.json 파일 수정
참고: LoRaServer에서는 application-eui를 사용하지 않는다.


수정한 내용을 반영하기 위해 코드를 재 build해 보도록 하자.
$ mbed compile -m DISCO_L072CZ_LRWAN1 -t GCC_ARM


Build에 문제가 없으니, 바로 flash writing을 해 보기로 하자.
chyi@mars:~/workspace/new_boards/MbedOS/mbed-os-example-lorawan$ mbed compile -m DISCO_L072CZ_LRWAN1 -t GCC_ARM -f
  • Flash에 write하자.
[mbed] Working path "/home/chyi/workspace/new_boards/MbedOS/mbed-os-example-lorawan" (program)
[Warning] @,: Compiler version mismatch: Have 9.2.1; expected version >= 6.0.0 and < 7.0.0
Building project mbed-os-example-lorawan (DISCO_L072CZ_LRWAN1, GCC_ARM)
Scan: mbed-os-example-lorawan
Link: mbed-os-example-lorawan
Elf2Bin: mbed-os-example-lorawan
| Module                     |      .text |    .data |     .bss |
|----------------------------|------------|----------|----------|
| [fill]                     |    126(+0) |    8(+0) |   27(+0) |
| [lib]/c.a                  |  29124(+0) | 2472(+0) |   89(+0) |
| [lib]/gcc.a                |  12740(+0) |    0(+0) |    0(+0) |
| [lib]/m.a                  |    552(+0) |    0(+0) |    0(+0) |
| [lib]/misc                 |    192(+0) |    4(+0) |   28(+0) |
| main.o                     |    978(+0) |    0(+0) | 4020(+0) |
| mbed-lora-radio-drv/SX126X |     54(+0) |    0(+0) |    0(+0) |
| mbed-lora-radio-drv/SX1272 |    292(+0) |    0(+0) |    0(+0) |
| mbed-lora-radio-drv/SX1276 |   8474(+0) |    0(+0) |    0(+0) |
| mbed-os/components         |     80(+0) |    0(+0) |    0(+0) |
| mbed-os/drivers            |   2192(+0) |    0(+0) |  596(+0) |
| mbed-os/events             |   1560(+0) |    0(+0) |    0(+0) |
| mbed-os/features           |  27678(+0) |    4(+0) |    0(+0) |
| mbed-os/hal                |   1732(+0) |    8(+0) |  130(+0) |
| mbed-os/platform           |   4714(+0) |  260(+0) |  412(+0) |
| mbed-os/rtos               |  10598(+0) |  168(+0) | 3164(+0) |
| mbed-os/targets            |  13180(+0) |    4(+0) | 1230(+0) |
| trace_helper.o             |      2(+0) |    0(+0) |    0(+0) |
| Subtotals                  | 114268(+0) | 2928(+0) | 9696(+0) |
Total Static RAM memory (data + bss): 12624(+0) bytes
Total Flash memory (text + data): 117196(+0) bytes

Image: ./BUILD/DISCO_L072CZ_LRWAN1/GCC_ARM/mbed-os-example-lorawan.bin
주의: 장치를 PC에서 인식 못할 경우, PC를 재 부팅해 주면 해결될 수 있다.


Flash에 writing은 정상적으로 진행된 듯 한데, LoRaWAN 연결(<=> LoRaServer)이 안되는 것 같다.
참고: LoRaServer에 disco board를 Application으로 등록하는 절차는 (반복되는 내용이라) 별도로 정리하지 않았다.
[그림 5.9] minicom(/dev/ttyACM0, 115200, 8N1) 실행 모습


어라, LoRaServer application key 설정이 잘 못 되었다. 아래와 같이 다시 조정해 보니, 정상 동작한다.
[그림 5.10] LoRaServer OTAA 설정 변경


[그림 5.11] minicom(/dev/ttyACM0, 115200, 8N1) 실행 모습 - OK


[그림 5.12] LoRaServer application page 모습


근데, 왜 에러 packet이 보일까 ?
[그림 5.13] LoRaServer application page - error packet


내용을 보니, error:"invalid data type: 117" 인데 ...   실제 sensor를 달지 않아서 제대로 된 data가 없어서 그런가 ? 아직은 정확한 이유를 알 수 없으니, 좀 더 두고 볼  일이다. :(
[나중에 정리한  것임] ThingsBoard로 전달할 message format(Codec 설정)이 안 맞아서 발생한 에러이다.



6. LoRaWAN의 모든 것

이번 장에서는 LoRaWAN 관련하여 필자가 작성한 몇가지 문서를 소개하고자 한다. 아래 4개의 문서에서는 LoRaWAN Sensor(Node) => Gateway => LoRa Server => Application Server에 이르는 전반적인 내용을 다루고 있으니, 관심있는 분들은 한번 읽어보시기 바란다.



Slowboot