nuttx에 예제 애플리케이션과 직접 만든 애플리케이션을 포함해 빌드하는 방법

nuttx 애플리케이션 작성하기

제 환경은 윈도우 10 빌드 2004 + Cygwin, 타겟 보드는 nucleo-l432kc(stm32l432kc)입니다. nuttx OS 개발환경 구축과 바이너리 플래시 방법은 전 포스트를 참고해주세요.

helloworld 예제 빌드해보기

OS 경로에서 make menuconfigApplication ConfigurationExamples"Hello, World!" example"Y를 눌러 추가하고 Save한 후 빠져나옵니다. 이제 make -j4를 실행해 빌드하고 openocd를 이용해 nuttx.hex 파일을 플래시해줍니다. 이후 타겟 보드와 시리얼 연결을 열고 nsh에서 help를 실행하면 아래와 같이 우리가 추가한 애플리케이션이 추가된 것을 확인할 수 있습니다.

nsh> help
help usage:  help [-v] [<cmd>]

  .         cd        echo      kill      mount     set       uname
  [         cp        exec      ls        mv        sleep     umount
  ?         cmp       exit      mb        mw        source    unset
  basename  dirname   false     mkdir     pwd       test      usleep
  break     date      help      mkrd      rm        time      xd
  cat       dd        hexdump   mh        rmdir     true

Builtin Apps:
  alarm   hello   nsh     ostest  rand    sh

그럼, nsh에서 우리가 추가한 앱을 실행시켜봅시다.

nsh> hello
Hello, World!!

잘 실행되는걸 확인할 수 있는데요. 그럼 앱 구조를 분석해볼까요. <APPS 폴더 경로>/examples/hello로 들어가시면, 크게 3가지 파일을 확인하실 수 있습니다. 실제 소스를 담고 있는 hello_main.c, Kconfig(우리가 주로 menuconfig라는 프론트엔드로 접하는) 설정 내용을 담고 있는 Kconfig, 빌드 방법과 세부 사항을 담고 있는 Makefile입니다. 각각 내용을 살펴보면,

//hello_main.c
#include <nuttx/config.h>
#include <stdio.h>

int main(int argc, FAR char *argv[])
{
  printf("Hello, World!!\n");
  return 0;
}

hello_main.c은 정말 진입점 함수 int main(...)과 동작을 기술하고 있습니다. <nuttx/config.h>는 일반적으로 모든 nuttx 앱에 포함되어야 합니다. 그다음으로,

config EXAMPLES_HELLO
	tristate "\"Hello, World!\" example"
	default n
	---help---
		Enable the \"Hello, World!\" example

if EXAMPLES_HELLO

config EXAMPLES_HELLO_PROGNAME
	string "Program name"
	default "hello"
	---help---
		This is the name of the program that will be used when the NSH ELF
		program is installed.

config EXAMPLES_HELLO_PRIORITY
	int "Hello task priority"
	default 100

config EXAMPLES_HELLO_STACKSIZE
	int "Hello stack size"
	default DEFAULT_TASK_STACKSIZE

endif

Kconfig 파일은 프로그램 빌드 시 적용될 매개변수들을 알려주고 있습니다. kconfig의 프론트앤드가 이 파일을 읽어 빌드시 지정하는 역할을 맡는데요, 크게 이 앱을 빌드 시 포함할지 여부인 EXAMPLES_HELLO, 앱의 이름을 결정하는 EXAMPLES_HELLO_PROGNAME, Task의 우선 순위를 결정하는 EXAMPLES_HELLO_PRIORITY와 Task의 스택 크기를 결정하는 EXAMPLES_HELLO_STACKSIZE의 4개의 변수가 정의되어 있습니다. 이 변수들은 Makefile에서 불러와 사용하는데요,

include $(APPDIR)/Make.defs

PROGNAME  = $(CONFIG_EXAMPLES_HELLO_PROGNAME)
PRIORITY  = $(CONFIG_EXAMPLES_HELLO_PRIORITY)
STACKSIZE = $(CONFIG_EXAMPLES_HELLO_STACKSIZE)
MODULE    = $(CONFIG_EXAMPLES_HELLO)

MAINSRC = hello_main.c

include $(APPDIR)/Application.mk

MakefileKconfig에서 선언한 변수를 빌드시 같이 붙여서 적용합니다. $(APPDIR)/Make.defs, $(APPDIR)/Application.mk는 전역 make 설정과 매크로를 포함하는 구문이고 여기서 hello/Make.defs를 포함하는데, CONFIG_EXAMPLES_HELLO가 참이면 CONFIGURED_APPS += $(APPDIR)/examples/hello를 정의하여 빌드할 앱에 자신을 추가합니다. 이후 PROGNAME, PRIORITY, STACKSIZE로 각각 속성을 정의하고, OS 빌드시 포함 여부인 MODULE (빌트인 | 모듈 | 미포함)와 앱의 주 진입점 소스파일인 MAINSRC를 설정하는 구조입니다.

직접 앱 만들어보기

APP 경로 최상위에 직접 나만의 어플리케이션을 만들어봅니다. <APP 경로>/myapp 디렉터리를 추가해주시고 아래와 같은 내용의 파일 4개를 생성해주세요.

# myapp/Kconfig

config MY_APP
	tristate "my app"
	default n
	---help---
		Enable the my app
# myapp/Make.defs
ifneq ($(CONFIG_MY_APP),)
CONFIGURED_APPS += $(APPDIR)/myapp
endif
# myapp/Makefile
include $(APPDIR)/Make.defs

PROGNAME  = myapp
PRIORITY  = 100
STACKSIZE = CONFIG_DEFAULT_TASK_STACKSIZE
MODULE    = $(CONFIG_MY_APP)

MAINSRC = my_app_main.c

include $(APPDIR)/Application.mk
// myapp/my_app_main.c
#include <nuttx/config.h>
#include <stdio.h>

int main(int argc, FAR char *argv[])
{
  printf("Hello my app!!!\n");
  return 0;
}

그리고 <APP 경로>/Kconfig 파일 마지막줄에 source "<APP 경로까지의 절대경로>/myapp/Kconfig"을 추가해 우리 앱의 Kconfig 위치를 알려줍시다. 이제 터미널에서 OS 경로로 들어가 make menuconfig를 실행하고 Application Configuration → my app을 선택하고 y키를 입력해 빌드 결과물에 포함시켜주고 <Save>를 선택해서 저장하고 나오면 설정은 끝입니다. 이제 make를 입력해 빌드하고 openocd를 이용해 플래시한후 nsh에서 확인하보면 우리의 앱이 추가된 것을 확인할 수 있습니다.

nsh> help
help usage:  help [-v] [<cmd>]

  .         cd        echo      kill      mount     set       uname
  [         cp        exec      ls        mv        sleep     umount
  ?         cmp       exit      mb        mw        source    unset
  basename  dirname   false     mkdir     pwd       test      usleep
  break     date      help      mkrd      rm        time      xd
  cat       dd        hexdump   mh        rmdir     true

Builtin Apps:
  alarm   hello   myapp   nsh     ostest  rand    sh
nsh> myapp
Hello my app!!!
comments powered by Disqus