Don't think! Just do it!

종합 IT 기술 정체성 카오스 블로그! 이... 이곳은 어디지?

임베디드 소프트웨어/Zephyr

[nRF52840 + Zephyr] #3. 디바이스 트리 1

방피터 2023. 5. 9. 23:10

2023.05.03 - [임베디드 소프트웨어/Zephyr] - [nRF52840 + Zephyr] #2. 뭘 공부해야 하나?

 

[nRF52840 + Zephyr] #2. 뭘 공부해야 하나?

2023.05.01 - [임베디드 소프트웨어/Zephyr] - Nordic NRF52840 + Zephyr 개발 환경 구축 Nordic NRF52840 + Zephyr 개발 환경 구축nrf52840을 위한 zephyr 개발 환경은 vscode에 nrf extension을 설치하는 방식으로 구축해. 공

engschool.tistory.com

저번 글에서 적어도 3가지는 공부해야 한다고 그랬어.

Device tree, Kconfig, zephyr kernel api.

이 중에 하드웨어 설정과 관련이 있는 Device tree부터 공부를 시작해보도록 하지! 훗.

자, 이제 게임을 시작하지 ㅋㅋㅋㅋ

리눅스를 커널 레벨에서 다루는 사람들이라면 디바이스 트리가 익숙하겠지만

non OS나 freeRTOS같은 RTOS를 다루던 임베디드 엔지니어들 입장에서는 생소한 단어야!

맞아! 생소한 건 무섭지! ㅋㅋㅋ

그래도 쫄거 없어 ㅋ 음~~~

내가 볼땐 하드웨어에 익숙한 임베디드 엔지니어들이 디바이스 트리를 훨씬 더 쉽게 이해할 수 있을 것 같아.(아님 말고 ㅋ)

디바이스 트리라는 건 말 그대로 디바이스들을 트리 형태로 나타낸 구조에 불과해.

그리고 각 트리 구조 안에 디바이스들의 정보가 담겨 있지.

그걸 디바이스 트리에서는 노드(Node)라고 불러.

👇👇

아래 실제 blinky 앱의 led 부분 디바이스 트리를 살펴보자구.

nRF52840 Device tree LED 부분

leds라는 노드가 있고 그 노드는 led_0부터 led_3까지의 서브 노드를 가지고 있어.

그리고 각 서브 노드들은 gpios와 label이라는 property(속성)을 가지고 있지.

gpios에서는 gpio 포트 번호랑 핀 번호,

그리고 어떤 상태가 led를 켜는지 나타내고 있고

label은 말 그대로 별칭이지.

그럼 이걸 blinky 앱에서는 어떻게 사용하고 있는지 보자구.

👇👇👇

#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>

#define SLEEP_TIME_MS   1000

/* The devicetree node identifier for the "led0" alias. */
#define LED0_NODE DT_ALIAS(led0)

static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);

void main(void)
{
	int ret;

	if (!device_is_ready(led.port)) {
		return;
	}

	ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
	if (ret < 0) {
		return;
	}

	while (1) {
		ret = gpio_pin_toggle_dt(&led);
		if (ret < 0) {
			return;
		}
		k_msleep(SLEEP_TIME_MS);
	}
}

여기서 보면 DT_ALIAS(led0)를 사용해서 노드 ID를 얻어오고 그 노드 ID로 gpio spec을 가져왔어.

그리고는 초기화 시키고 깜빡이는 코드가 이어지고 있지.

이게 순서라고 보면 돼.

 

1. 노드 ID 얻어오고

2. 노드 ID로 device reference 얻어와서

3. 사용

 

주의할 점!!!

노드 ID 얻어올 때 DT_ALIAS(led0) 를 사용했는데

여기서 led0는 디바이스 트리에서 led0 서브노드를 의미하는 게 아냐.

alias(별칭)을 의미하는 거임! ㅇㅇ!

dts 파일을 살펴보면 이 alias를 설정해 놓은 부분이 있어.

물론 alias led0가 leds의 서브노드인 led0를 가르키게 되어 있지만 말이야 ㅋㅋㅋ

dts 파일의 aliases

노드 ID를 얻어오는 방법은 DT_ALIAS 말고도 여러 가지가 있어.

Zephyr에서 소개하는 방법은 6개 정도가 있는데 DT_ALIAS()도 그중 하나일 뿐이야. 👇👇 

노드 ID를 얻어오는 6가지 매크로

만약 Alias가 설정이 안되어 있어서 node label을 이용해 노드 id를 얻어오고 싶다면

DT_NODELABEL()을 이용하면 되겠지?

그런데 blinky 앱에서는 led_0의 label이 alias와 동일하게 led0야 ㅎㅎㅎ

그래서 DT_ALIAS를 DT_NODELABEL로 변경해도 똑같이 동작해.

이 자식들! 헷갈리게 똑같은 걸로 해놨어 ㅋㅋㅋ

//여기서 led0는 alias를 의미!
#define LED0_NODE DT_ALIAS(led0)

//여기서 led0는 led_0의 노드 label을 의미!
#define LED0_NODE DT_NODELABEL(led0)

암튼 디바이스 트리에 어려움을 겪는 사람들이 많은지;;

nRF Extension에서는 디바이스 트리 GUI가 있네?

vscode의 nRF extension에서 Devicetree 메뉴를 선택하면 아래와 같은 화면을 볼 수가 있어.

👇👇👇

vsdoce nRF extension Devicetree 화면

가장 오른쪽에는 nRF52840 IC가 도면으로 그려져 있고

왼쪽에는 위에서 봤던 led들을 비롯해서 다양한 노드들이 보여.

alias같은 것들도 별도로 정리되어 있는 것도 볼 수 있고.

 

그리고 leds 노드를 펼쳐보면 아까 dts 파일의 설정과 똑같은 걸 볼 수 있어

👇👇👇

leds 노드와 서브노드들

이것 저것 살펴보면

dts를 약간 더 보기 좋게 만들어 놓은 것에 불과한데

클릭으로 정해진 것만 설정할 수 있으니 실수를 조금 줄일 수 있겠지.

led_0 서브노드 pin 설정

dts 파일이나 관련 매크로에 실수가 있으면 build 할 때 당연히 error 메세지가 나오는데 ㅎㅎㅎㅎ

그런데 그 error 메세지가 조금 눈이 아프더라고;;;

👇👇👇

alias led0를 led99로 변경 후 build.. 눈아팡.. ㅠㅠ 색좀 넣어주지

ㅇㅇ 꼴보기 싫음 ㅋㅋㅋ

 

이런 GUI를 사용하는 것도 좋지만

zephyr os를 잘 다루려면 GUI에 너무 의존하기 보다

dts 파일 위에서 여러가지를 다뤄보는게 좋을 듯 해.

그래야 전체적인 이해도가 높아질거야!!

그리고 nRF만 할거 아니잖아? ㅋㅋㅋ 다른 제조사들은 이런 gui 없다고 ㅋ

 

그럼 다음 시간에는 디바이스 트리의 unit address와 chosen을 다뤄보도록 할겨! 다들 수고! 안녕!!!!!👋👋👋

2023.05.11 - [전체] - [nRF52840 + Zephyr] #4. 디바이스 트리 2

 

[nRF52840 + Zephyr] #4. 디바이스 트리 2

2023.05.09 - [임베디드 소프트웨어/Zephyr] - [nRF52840 + Zephyr] #3. 디바이스 트리 1 [nRF52840 + Zephyr] #3. 디바이스 트리 1 2023.05.03 - [임베디드 소프트웨어/Zephyr] - [nRF52840 + Zephyr] #2. 뭘 공부해야 하나? [nRF52840

engschool.tistory.com

 

반응형