2014/10/30

ChibiOS/RT 설정

이전 포스트에서 ChibiOS/RT를 적용하는 방법을 알아봤습니다.

프로젝트 디렉토리를 만들고 제일 먼저 했던 일은 Makefile, chconf.h, halconf.h, mcuconf.h, main.c를 레퍼런스 디렉토리로부터 복사했던 것입니다.

Makefile에 대한 설명은 일반적이기도 하거니와 이전 포스트에서 이미 했었습니다.

1. chconf.h
chconf.h는 ChibiOS/RT 커널에 대한 설정을 가지고 있는 헤더입니다.

doxygen을 이용해서 문서를 생성했다면 해당 파일에 대한 내용을 브라우저에서 볼 수 있습니다.

간략하게 설명하자면 커널의 기본적인 설정과 여러 설비들에 대한 설정을 할 수 있는헤더입니다.
열어보면 CH_USE_xxxx 형태의 #define이 많이 있습니다.
xxxx는 내용만 딱 봐도 알 수 있도록 구성되어 있습니다. 세마포어를 사용할거냐, 뮤텍스를 사용할거냐 등등등.
이런 설비(대부분은 쓰레드간 통신을 위한 설비입니다.)를 사용하기 위해서 해당 #define을 TRUE로 변경하면 됩니다.

자세한 내용은 ChibiOS/RT의 문서 참고 바랍니다.

2. halconf.h
hal은 Hardware Abstract Layer의 약자이며 마이크로 컨트롤러의 여러 기능 들에 대해서 동일한 API를 제공하기 위한 모듈이라고 생각하면 됩니다.

열어보면 역시 HAL_USE_xxxx 형태로 구성되어 있으며 여기에서 정확하게 설정을 해야만 ChibiOS/RT에 이미 구현되어 있는 드라이버들이 활성화 됩니다.

예를 들어, GPIO(ARM Cortex에서는 PAL이라고 보통 부릅니다.)를 사용하기 위해서는 HAL_USE_PAL을 TRUE로 해야 컴파일은 물론이고 동작도 정상적으로 됩니다.

파일 자체가 설명이므로 사용하는 데 큰 어려움이 없을 것입니다.

3. mcuconf.h
halconf.h가 큰 카테고리라면 mcuconf.h는 좀 더 세밀한 카테고리라고 생각하면 됩니다.
mcuconf.h의 메인 주석에도 설명이 되어 있듯이, halconf.h에서 설정하지 않으면 mcuconf.h의 설정 내용이 적용되지 않습니다.

예를 들어, UART를 사용하고 싶다면 halconf.h에서 HAL_USE_UART를 먼저 활성화하고, mcuconf.h에서는 3개의 UART 중 어떤 것을 사용할 지 선택할 수 있습니다.

사용하지 않을 기능에 대해서는 애초에 비활성화하는 것이 크기, 사용성에 있어서 더 좋을 것입니다.



오늘은 간략하게 ChibiOS/RT의 설정에 대해서 알아봤습니다.
보다 자세한 내용은 제공되는 문서 또는 ChibiOS/RT 공식 홈페이지, 포럼 등을 참고 바랍니다.

ARM Cortex와 ChibiOS/RT

ARM Cortex M3에 마이크로 컨트롤러용 RTOS 중 제한적이긴 하지만 오픈 소스인 ChibiOS/RT를 적용하고자 합니다.

ChibiOS/RT에 대해 간략하게 설명하자면,
  • 선점형 커널
  • 다양한 플랫폼(마이크로 컨트롤러) 지원
  • 다양한 쓰레드간 통신 설비 지원 : semaphore, mutex, mailbox 등
  • HAL(Hardware Abstract Layer) 지원
  • 작은 크기와 빠른 문맥 전환
  • 다양한 라이센스
등이며, 상세 설명 및 성능 등에 대한 확인은 ChibiOS/RT 공식 홈페이지를 참고하시기 바랍니다.

이 작업은 우분투 리눅스 14.04에서 진행했으며 이전 포스트(링크 걸 것)에서 설명한 바와 같이 개발 환경이 구축되어 있다는 가정 하에 설명하겠습니다.
개발 보드는 IAR 사에서 판매하고 있는 STM32F107VC-SK입니다.
STM32F107VC는 ST에서 공급하는 Connectivity Line 중 하나의 모델이며 Cortex-M3입니다.


1. 내려 받기 및 압축 해제
http://sourceforge.net/projects/chibios/에서 최신 버전(2014.10 현재 2.6.6, ChibiOS_2.6.6.zip)을 내려 받습니다.
그리고 unzip 명령을 이용해서 적당한 위치에 압축 해제 합니다. 이후 ~/ChibiOS_2.6.6에 설치되어 있다고 가정하겠습니다.


2. ChibiOS/RT의 폴더 구조
압축을 해제한 폴더를 보면 다음과 같이 구성되어 있습니다.

  • boards : 현재 ChibiOS/RT를 적용하고 테스트가 완료된 대표적인 개발 보드
  • demos : 플랫폼별 예제
  • docs : API 등에 대한 문서 소스
  • ext : 부가 모듈(fat, tcp/ip 스택) 소스
  • os : ChibiOS/RT 소스
  • test : 기본 제공 설비(특히 IPC) 테스트 소스
  • testhal : 플랫폼 별 HAL 예제
ext 가 부가 모듈이라고 되어 있는데 SD 카드를 지원하기 위해서 FAT(도스 및 윈도우 파일 시스템입니다.)과 네트워크를 지원하기 위해서 오픈 소스 스택인 lwip와 uip가 포함되어 있습니다. 필요한 경우 압축 해제하고 사용하면 됩니다.

실제 컴파일에 필요한 폴더는 boards, os, 필요에 따라 ext 정도가 전부입니다.

test 폴더는 거의 필요가 없으며 testhal의 경우 플랫폼별로, HAL별로 구분해서 예제가 탑재되어 있으므로 필요한 경우 가져다 쓰면 됩니다. 예를 들어 UART 통신을 하고 싶은 경우 testhal/플랫폼/UART 폴더를 참고하면 ChibiOS/RT에서 UART를 사용하는 코드를 알 수 있습니다.

docs 폴더의 경우 처음 압축을 해제하면 doxygen에 필요한 파일 외에는 없습니다. API에 대한 설명들이 있으므로 doxygen을 설치해서 HTML 문서를 생성하는 것이 좋습니다. 자세한 내용은 docs/readme.txt를 읽어보시면 됩니다. 간략하게 설명하자면 doxywizard와 graphviz 패키지를 설치하고 doxywizard에서 Doxyfile_html을 로드해서 HTML을 생성하면 됩니다. 그러면 html 폴더가 생성되고 index.html을 브라우저에서 열면 ChibiOS/RT의 잘 정리된 문서를 확인할 수 있습니다.
더불어 ChibiOS/RT의 포럼 ChibiOS/RT 홈페이지에 정리되어 있는 문서들도 참고 바랍니다.


3. 새로운 프로젝트 생성
이제 ChibiOS/RT를 적용할 준비가 되었습니다.

나만의 새로운 프로젝트를 생성해서 컴파일도 해보고, 작동도 시켜봐야 하겠죠.

1) 폴더 생성 및 필요 파일 복사
ChibiOS/RT의 루트 폴더에 적당한 이름으로 폴더를 만듭니다. 하위 폴더를 더 생성해도 됩니다.
저는 ~/ChibiOS_2.6.6/myProjects/sample이라고 만들었습니다.

그 리고 ~/ChibiOS_2.6.6/demos 폴더 중 자신이 적용하려고 하는 플랫폼과 가장 비슷한 폴더를 찾아서 그 폴더 안의 내용 중 Makefile, chconf.h, halconf.h, main.c mcuconf.h를 방금 만든 폴더로 복사합니다.
제 경우 적용하려고 하는 데모 보드가 STM32F107VC-SK라고 하는 IAR에서 제공하는 보드라서 demos/ARMCM3-STM32F107 폴더에서 복사했습니다. ARM Cortex M3이며, STM32F107이라는 마이크로 컨트롤러를 사용하기 때문입니다.
(같은 플랫폼이라면 작업이 훨씬 수월합니다.)

이제 sample 폴더에는 Makefile, chconf.h, halconf.h, main.c mcuconf.h 이렇게 다섯 개의 파일이 있습니다.

Makefile은 전통적인 Unix/Linux Makefile이며, 설정에 필요한 헤더 파일 세 개, 그리고 애플리케이션 소스인 main.c가 있습니다.

2) Makefile 수정
Makefile은 make 명령이 알아들을 수 있는 문법으로 구성되어 있으며 컴파일 및 링킹 등의 역할에 대해서 규명해놓은 파일입니다.
열어보면 컴파일러 옵션, 링커 옵션, 소스 및 헤더 파일의 위치, 컴파일러에 대한 설정 등을 할 수 있습니다.
(Makefile의 문법이라든지 원리, 각종 세부 옵션 등은 이 포스트의 범위를 벗어나는 것이므로 따로 설명하지 않겠습니다.)

다른 부분은 손댈 부분이 없으며 다음 부분만 수정하면 됩니다.


063  PROJECT = ch
066  CHIBIOS = ../..
128  MCU = cortex-m3
131  TRGT = arm-none-eabi-
(왼 편의 숫자는 해당 라인이 있는 곳의 줄 번호 입니다.)

PROJECT는 이 프로젝트의 이름이며 컴파일 후 생성되는 파일명에도 관계가 있으므로 적절한 이름으로 변경하는 것이 좋습니다. 이번 포스트에서는 일단 그대로 사용하겠습니다.

CHIBIOS는 내려 받은 ChibiOS/RT의 폴더를 절대 경로 또는 상대 경로로 정확하게 지정하면 됩니다. ~/ChibiOS_2.6.6 이라고 해 놓으면 가장 좋을 것 같습니다.

MCU는 말 그대로 MCU의 종류를 의미합니다. 만약 STM32F407 플랫폼에 적용하려고 한다면 MCU = cortex-m4가 될 것입니다.

TRGT는 Toolchain의 접두어를 적어주면 됩니다. 기본적으로 GNU Toolchain을 사용하도록 되어 있으므로 다른 Toolchain을 사용한다면 적절히 수정해야 합니다.

3) 일단 컴파일!!!
Makefile에 대한 수정도 완료했으므로 make 명령을 내려서 정상적으로 컴파일되는 지 확인하면 됩니다.

다음과 같이 나오면 정상적으로 컴파일된 것입니다.


Compiler Options
arm-none-eabi-gcc -c -mcpu=cortex-m3 -O2 -ggdb -fomit-frame-pointer -falign-functions=16 -ffunction-sections -fdata-sections -fno-common -Wall -Wextra -Wstrict-prototypes -Wa,-alms=build/lst/ -DCORTEX_USE_FPU=FALSE -DTHUMB_PRESENT -mno-thumb-interwork -DTHUMB_NO_INTERWORKING -MD -MP -MF .dep/build.d -I. -I../../os/ports/common/ARMCMx/CMSIS/include -I../../os/ports/common/ARMCMx -I../../os/ports/GCC/ARMCMx -I../../os/ports/GCC/ARMCMx/STM32F1xx -I../../os/kernel/include -I../../test -I../../os/hal/include -I../../os/hal/platforms/STM32F1xx -I../../os/hal/platforms/STM32 -I../../os/hal/platforms/STM32/GPIOv1 -I../../os/hal/platforms/STM32/I2Cv1 -I../../os/hal/platforms/STM32/RTCv1 -I../../os/hal/platforms/STM32/SPIv1 -I../../os/hal/platforms/STM32/TIMv1 -I../../os/hal/platforms/STM32/USARTv1 -I../../os/hal/platforms/STM32/OTGv1 -I../../boards/OLIMEX_STM32_P107 -I../../os/various main.c -o main.o

mkdir -p build/obj
mkdir -p build/lst
Compiling crt0.c
Compiling vectors.c
Compiling chcore.c
Compiling chcore_v7m.c
Compiling nvic.c


      ... 중략 ...

Compiling uart_lld.c
Compiling usb_lld.c
Compiling board.c
Compiling evtimer.c
Compiling syscalls.c
Compiling main.c
main.c: In function 'Thread1':
main.c:35:1: warning: no return statement in function returning non-void [-Wreturn-type]
 }
 ^
Linking build/ch.elf
Creating build/ch.hex
Creating build/ch.bin
Creating build/ch.dmp

     text       data        bss        dec        hex    filename
  27272        520      4848      32640      7f80    build/ch.elf

Done


컴파일까지 이상없이 되면 이미 반 이상 온 겁니다.
돈 한푼 들이지 않고, Cortex M3에서 아주 잘 돌아가는 RTOS를 손에 넣었습니다!!


4. 내 보드에 맞도록 수정
생성된 파일을 개발 보드에 넣어서 LED라도 동작시켜볼려고 해도 컴파일시 적용한 보드와 실제 보드가 다를 경우 동작하지 않을 겁니다.
개발 보드 구성은 메이커마다 다르기 때문입니다. 레퍼런스 보드는 PORTC의 0번 핀을 출력으로 사용하지만 내가 가지고 있는 개발 보드는 입력으로 구성되어 있다든지 이런 경우를 의미합니다.


Makefile을 자세히 들여다봤다면 알 수 있지만 67번 라인 정도에 다음과 같은 내용이 있습니다.


067  include $(CHIBIOS)/boards/OLIMEX_STM32_P107/board.mk

보드의 구성은 위에 명시된 폴더의 내용을 참고한다는 의미입니다.
만약 가지고 있는 개발 보드가 OLIMEX에서 만든 STM32P107이라면 아무런 수정없이 바로 동작 가능합니다.
(참고로 OLIMEX사에 가면 Cortex-M3 레퍼런스 보드들이 있습니다.)

그러나 여러 가지 이유로 다른 구성의 보드를 가지고 있다면 해당 보드의 구성에 맞도록 수정할 필요가 있습니다.

boards 폴더를 보면 다양한 제조사의 보드들이 있습니다. OLIMEX, Nucleo, 유명한 Discovery도 보이네요.
그러나 제가 가지고 있는 IAR 보드는 없기 때문에 IAR_STM32F107VC_SK라는 이름으로 폴더를 새로 만들었습니다. (이름은 어떤 이름을 줘도 상관없습니다.)
그리고 MCU가 같은 폴더(OLIMEX_STM32_P107)에서 board.c, board.h, board.mk 파일을 복사했습니다.

이제 ~/ChibiOS_2.6.6/boards/IAR_STM32F107VC_SK 폴더에 board.c, board.h, board.mk가 있습니다.

우선 board.mk 파일을 수정합니다. 이 파일은 애플리케이션을 빌드할 때 Makefile이 참조하므로 반드시 내용에 맞도록 수정해야 정상적으로 컴파일됩니다.



# List of all the board related files.
BOARDSRC = ${CHIBIOS}/boards/OLIMEX_STM32_P107/board.c

# Required include directories
BOARDINC = ${CHIBIOS}/boards/OLIMEX_STM32_P107

이런 식으로 되어 있는데 boards/ 다음의 폴더 이름을 현재 폴더 이름으로 변경하면 됩니다. 이런 식으로 변경되겠죠.



# List of all the board related files.
BOARDSRC = ${CHIBIOS}/boards/IAR_STM32F107VC_SK/board.c

# Required include directories
BOARDINC = ${CHIBIOS}/boards/IAR_STM32F107VC_SK

보드의 소스(BOARDSRC)는 명시된 폴더의 board.c이고 보드의 헤더 파일(BOARDINC)은 명시된 폴더에 있는 것을 참조하겠다는 의미입니다.

저장하고 종료합니다.

board.c는 거의 수정할 내용이 없습니다. 이미 STM32F107에 맞는 파일을 복사해서 사용하고 있으므로 내용이 거의 비슷합니다. 특별한 초기와 과정이 필요하다던지 그럴 경우 이 파일에 소스 코드를 작성하면 됩니다.

board.h는 개발 보드의 IO Port 설정에 대한 내용을 기록하면 됩니다.
ARM Cortex를 비롯해서 대부분의 마이크로 컨트롤러는 하나의 핀으로 여러 가지 기능을 수행할 수 있습니다. LED를 제어하기 위해서 일반적인 GPIO의 Output으로 사용할 수도 있고, 스위치 입력을 받을 수 있도록 GPIO의 input으로 설정할 수도 있습니다. 또는 ADC를 위한 input으로도 사용할 수 있고, UART로도 사용할 수 있습니다.
이런 부분을 설정하는 곳이 board.h입니다.
물론, 동작 중에 이 설정을 변경할 수 있으므로 보드에 전원 투입 시 문제없을 정도로만 설정하면 됩니다.
(예 를 들자면 PWM 출력으로 사용할 수 있는 핀에 모터같은 걸 연결해뒀는데 초기화 때 여기에 1이라는 값을 주게 되면 모터가 최대 속도로 돌아갈 수 있습니다. 안전 문제라든지, 보드의 정격 등에 영향을 미칠 수 있으므로 이 부분에 대한 설정이 필요할 것입니다.)


이미 만들어져 있는 파일을 복사해서 사용하고 있고 원본 파일에 주석이 친절하게 달려 있으므로 큰 어려움 없이 설정할 수 있습니다. 각 포트의 각각의 핀에 대한 입/출력 설정, 초기값을 설정합니다.

그 외에 필요한 개인적인 정의문이나, 보드의 이름 등을 수정하면 됩니다.


다만, 보드의 클럭(STM32_LSECLK, STM32_HSECLK)과 STM32의 경우 마이크로 컨트롤러의 라인을 의미하는 정의문(#define STM32F10X_CL)은 주의깊게 살펴야 합니다.

더 이상 수정할 내용이 없다면 저장하고 종료합니다.


5. 다시 컴파일!!
이제 가지고 있는 보드에 맞도록 수정했으므로 생성한 프로젝트에서 해당 파일을 이용하도록 해야 합니다.

새로 생성한 프로젝트(sample이었죠?)의 Makefile을 열고 67번 라인 근처를 보면 다음과 같은 부분이 있습니다.



067  include $(CHIBIOS)/boards/OLIMEX_STM32_P107/board.mk

이전에 컴파일할 때에는 boards/OLIMEX_STM32_P107에 저장되어 있는 파일들을 이용했지만 이제 내 보드에 맞는 설정 파일 들이 있으니까 위치를 변경해야겠죠?



067  include $(CHIBIOS)/boards/IAR_STM32F107VC_SK/board.mk

로 변경한 후 저장합니다.

바로 아래를 보면 다음처럼 플랫폼에 맞도록 이미 정의되어 있는 파일들도 include하게 설정되어 있습니다.
이 부분은 거의 손댈 일이 없지만 만약 필요하다면 아래 파일도 수정하고 저장합니다.



068  include $(CHIBIOS)/os/hal/platforms/STM32F1xx/platform_f105_f107.mk


이제 make 명령을 내려서 컴파일해봅니다.
새로운 헤더 파일 등을 참조하기 때문에 처음부터 다시 컴파일을 진행할 것이고 앞에서 설명한 바와 같이 오류없이 컴파일 완료되면 이제 기본적인 설정은 모두 완료한 상태입니다.


멋진 애플리케이션만 작성하면 됩니다. ^^

6. 애플리케이션 작성
main.c를 열어보면 알 수 없는 함수들과 헤더 파일 등으로 구성되어 있는 애플리케이션이 구현되어 있습니다.
각 함수에 대한 자세한 내용은 doxygen으로 생성한 html/index.html 파일이나 ChibiOS/RT 공식 홈페이지의 문서 등에서 확인하면 됩니다.

ChibiOS/RT는 멀티 쓰레드를 지원하는 OS이므로 쓰레드를 생성하고 main() 함수에서는 해당 쓰레드를 생성하면 됩니다.
main.c에 구현되어 있는 쓰레드는 보드에 연결되어 있는 LED를 0.5초 간격으로 깜빡이게 하는 쓰레드입니다.

24번 라인 근처를 보면 다음과 같은 코드가 있습니다.


024  static WORKING_AREA(waThread1, 128);
025  static msg_t Thread1(void *arg) {
026
027      (void)arg;
028      chRegSetThreadName("blinker");
029      while (TRUE) {
030          palClearPad(GPIOC, GPIOC_LED_STATUS1);
031          chThdSleepMilliseconds(500);
032          palSetPad(GPIOC, GPIOC_LED_STATUS1);
033          chThdSleepMilliseconds(500);
034      }
035  }

ChibiOS/RT의 가장 기본이 되는 쓰레드입니다.

palClearPad() 함수에 의해서 해당 포트의 핀에 0을 출력하고 chThdSleepMilliseconds() 함수를 이용해서 delay를 생성한 후 palSetPad() 함수로 해당 핀에 1을 출력하고 다시 delay를 가집니다.
즉, GPIOC, GPIOC_LED_STATUS1 이 두 부분만 수정하면 내가 가지고 있는 보드에서 LED를 깜빡이게 할 수 있습니다.
GPIOC는 기본적으로 정의되어 있는 것이며 PORTC를 의미합니다.
GPIOC_LED_STATUS1 은 앞에서 수정한 적이 있는 board.h에 정의하면 됩니다. 아니면 핀 순서를 바로 적으면 됩니다. 만약 LED가 PORT C의 3번 핀에 연결되어 있다면 palClearPad() 함수와 palSetPad() 함수 인자는 각각 GPIOC, 3이라고 하면 됩니다.

chTdhSleepMilliseconds() 함수의 인자를 mS 단위로 지정하면 지정한 만큼의 delay가 발생합니다.

main() 함수에서는 chThdCreateStatic() 함수로 이 쓰레드를 생성하고 실행합니다.

make 하고 디버거를 통해서 실행시켜보면 원하는 대로 동작하는 것을 확인할 수 있습니다.


make 후에 생성되는 파일은 build에 있으며 이번 예제의 경우 build/ch.elf가 됩니다.

7. 디버거(Debugger) 사용
디버거는 말 그대로 프로그램 동작 상의 오류를 발견하는 도구입니다. 동작 중의 오류를 발견하기 위한 도구이니까 당연히 프로그램을 실행하는 기능도 가지고 있어야 합니다.
여기에 마이크로 컨트롤러라는 특수성까지 더해지면 마이크로 컨트롤러의 내부 메모리 영역에 실행 코드를 다운로드하고, 그 코드를 실행하는 도구가 됩니다.
따라서 디버거는 사용하려고 하는 마이크로 컨트롤러마다 다르며 제가 사용하고 있는 SMT32F107VC-SK 보드에는 J-Link가 기본적으로 장착되어 있습니다.
그래서 J-Link 관련 드라이버와 프로그램을 설치했으며 여기를 참조하시기 바랍니다.

GNU에서 제공하는 Toolchain을 사용할 경우 일반적으로 GDB라는 디버거를 사용합니다.
조금 특이한 점이 있다면 원격 접속을 통한 디버깅도 허용한다는 것입니다.

J-Link를 사용할 경우 JLinkGDBServer가 이 역할을 수행하는 프로그램입니다.
JLinkGDBServer는 연결된 클라이언트인 GDB로부터 명령을 받아서 이를 현재 연결되어 있는 보드에 전달하는 역할을 수행합니다.
이 과정에서 마이크로 컨트롤러를 직접 제어하게 되므로 다운로드가 가능하며 동작 중 잠시 멈추게 한다거나 다시 동작하게 하고, 사용자가 필요한 내용을 볼 수 있도록 해줍니다.

이 포스트에서는 J-Link에 대한 프로그램이 정상적으로 설치되어 있고, 리눅스에서 개발 중이라고 가정합니다.

프 로그램이 정상적으로 설치되어 있고, 개발 보드 역시 정상적으로 연결되어 있다면 터미널에서 JLinkGDBServer라고 명령을 내리면 실행됩니다. 만약 명령이 없으면 /opt/SEGGER/J-Link/JLinkGDBServer라고 실행합니다.
그러나 이렇게 실행하게 되면 이 프로그램은 어떤 장치에 연결되었는지 알 수 없기 때문에 적절하게 옵션을 줘야 합니다.
보통 마이크로 컨트롤러의 이름, 동작 속도, 인터페이스 정도만 지정하면 됩니다. 자세한 내용은 J-Link가 설치되어 있는 폴더의 Docs 문서를 참고하시기 바랍니다.


JLinkGDBServer -Device STM32F107VC -If SWD -Speed 4000 이라고 명령을 내리면 다음과 같이 출력하면서 클라이언트가 연결되길 기다립니다.


SEGGER J-Link GDB Server V4.90b Command Line Version

JLinkARM.dll V4.90b (DLL compiled Aug 14 2014 11:20:48)

-----GDB Server start settings-----
GDBInit file:                  none
GDB Server Listening port:     2331
SWO raw output listening port: 2332
Terminal I/O port:             2333
Accept remote connection:      yes
Generate logfile:              off
Verify download:               off
Init regs on start:            on
Silent mode:                   off
Single run mode:               off
Target connection timeout:     5 sec.
------J-Link related settings------
J-Link Host interface:         USB
J-Link script:                 none
J-Link settings file:          none
------Target related settings------
Target device:                 STM32F107VC
Target interface:              SWD
Target interface speed:        4000kHz
Target endian:                 little

Connecting to J-Link...
J-Link is connected.
Firmware: J-Link ARM-OB STM32 compiled Aug 22 2012 19:52:04
Hardware: V7.00
S/N:         (S/N은 일부러 지웠습니다.)
Checking target voltage...
Target voltage: 3.30 V
Listening on TCP/IP port 2331
Connecting to target...Connected to target
Waiting for GDB connection...

현재 작업 중인 위치에서 다른 터미널을 이용하여 다음과 같이 연결합니다.


GNU Toolchain을 사용하고 있으므로 여기에서 제공하는 gdb인 arm-none-eabi-gdb를 이용하고 컴파일의 결과물인 build/ch.elf를 디버깅하겠다는 의미입니다.

arm-none-eabi-gdb build/ch.elf

뭔가 설명이 나오고 덩그러니 (gdb) 라는 프롬프트만 보이면 정상입니다.

이 후에는 gdb 명령어를 통해서 디버깅이 가능합니다.


(gdb) tar ext :2331
Remote debugging using :2331
0x00000000 in ?? ()

JLinkGDBServer와 연결하기 위해서 tar ext :2331이라는 명령을 내렸습니다.
tar는 target을 의미하며 타켓 보드에 연결하겠다는 명령입니다.
ext는 extended-remote의 줄임말이며 시리얼(여기서는 USB)로 연결된 보드를 의미합니다.
2331은 JLinkGDBServer의 listening port입니다.

위 명령을 수행하면 JLinkGDBServer의 메시지가 아래와 같이 변경되는 것을 확인할 수 있습니다.


Waiting for GDB connection...Connected to 127.0.0.1
Reading all registers
Read 4 bytes @ address 0x00000000 (Data = 0x20000400)

이후 load와 run 명령을 이용해서 생성한 파일을 다운로드하고 실행할 수 있습니다.


(gdb) load
Loading section startup, size 0x150 lma 0x8000000
Loading section .text, size 0x14604 lma 0x8000150
Loading section .data, size 0x20 lma 0x8014758
Start address 0x8001b70, load size 83828
Transfer rate: 10232 KB/sec, 10478 bytes/write.
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y

r 명령은 run이며 프로그램을 실행하는 명령입니다. 이미 실행되고 있는 프로그램이 있다는 메시지가 나오는데 무시하고 y를 입력하면 프로그램이 돌기 시작합니다!!
LED 깜빡이는 게 보이면 성공입니다.

동작을 시작하면 무한 루프로 들어가므로 Ctrl+C를 눌러야만 멈춥니다.

GDB 종료는 quit 명령입니다.

gdb는 GNU Toolchain에서 사용하는 프로그램이므로 인터넷 상에 많은 자료가 있으므로 별도로 설명하지 않겠습니다.




이상으로 ARM Cortex-M3에 ChibiOS/RT를 이용한 애플리케이션을 만드는 방법을 알아보았습니다. 다음에는 궁극적인 목적이었던 uGFX에 대해서 알아보도록 하겠습니다.

ChibiOS/RT는 이미 충분한 기능을 가지고 있는 마이크로 컨트롤러용 RTOS입니다. 게다가 추가적인 모듈을 사용하면 tcp/ip 스택을 구현할 수 있기 때문에 자그마한 웹 서버로의 기능도 가능합니다.
UI 가 필요없는 장치를 개발한다면 ChibiOS/RT 만으로도 충분할 것으로 보이며 커뮤니티를 중심으로 활발하게 진행하고 있는 오픈 소스이므로 더욱 발전한 모습을 볼 수 있을 것으로 기대됩니다. (내년이면 3.x 대 커널과 HAL을 배포할 것으로 보입니다)

ARM Cortex 개발 환경 구축

ARM Cortex를 이용해서 개발을 진행하기 위해서는 우선 개발 환경을 구축해야 합니다.

개발 환경을 적용하기 위한 OS가 윈도우냐 리눅스냐에 따라서 설치가 조금 달라집니다만, 가장 중요한 컴파일러, 링커 등의 기본적인 Toolchain은 같은 곳에서 배포하는 패키지를 사용하면 됩니다.
나머지는 이 Toolchain을 어떻게 이용하느냐와 관련된 부분입니다.

윈도우에 eclipse를 설치해서 개발을 진행할 수도 있고, 리눅스에서 편집기와 Makefile 만을 이용해서 개발할 수도 있습니다. 물론 윈도우에서 cygwin이나 mingw를 설치해서 Makefile을 이용할 수 있는 환경을 구축하고 자신이 사용하기 편리한 편집기로 소스 편집하면서 개발할 수도 있고, 리눅스에 eclipse를 설치하고 개발을 진행하는 것도 가능합니다.  Toolchain이 맥을 지원한다면 맥에서도 당연히 개발이 가능합니다. (다만, 저는 맥을 사용해본 적도 없고, 사용할 계획도 없기 때문에 잘 모릅니다. 윈도우처럼 eclipse를 사용하면 되지 않을까 합니다.)

어떤 방법이든 Toolchain은 같은 것을 사용하면 되므로 문제가 없습니다.


주목할 부분은 eclipse를 사용한다고 하더라도 그 자체만으로는 아무 것도 할 수 없다는 것입니다. eclipse는 단지(물론 아주 잘 만들어졌고, 웬만한 상용 IDE보다도 더 많은 기능을 가지고 있습니다) IDE일 뿐이며, 실제 컴파일에 사용되는 도구는 Toolchain과 Build Tools(make, rm과 같은)이기 때문에 eclipse를 사용하든 그렇지 않든 Toolchain과 Build Tools는 설치가 되어 있어야 한다는 것입니다. 제가 링크 걸어둔 싸이트의 설명을 보면 알 수 있듯이 eclipse에서는 ARM Cortex용 컴파일러와 링커의 경로를 설정하고, 디버거를 적용할 수 있는 설정만 할 뿐입니다.

물론 상용 컴파일러와 개발 환경(IAR 시리즈, Keil 등과 같은)을 구매한다면 이 포스트는 의미 없습니다.

오늘 포스트에서 언급할 내용은 누구나 사용할 수 있도록 공개되어 있는 도구입니다. (다시 말해서 구입이 필요없다는 의미입니다. 단, 윈도우나 맥 OS는 정식 라이센스가 필요합니다.)

ARM Cortex 개발 환경 구축을 위해서는 다음을 준비해야 합니다.


  • Toolchain 설치

  • 작업 환경 구축

  • 디버거/다운로더 준비

영어긴 하지만 아래 싸이트가 개발 환경 구축과 관련해서 자세하고 정확하게 정리해놓은 곳입니다.

GNU ARM Eclipse : http://gnuarmeclipse.livius.net/blog/

제 목에서도 확인할 수 있듯이 ARM(Cortex를 포함한 ARM Core를 사용하는 거의 모든 CPU)을 개발할 때 Eclipse를 사용하기 위한 방법을 정리하고 있습니다. 여기에서 eclipse용 플러그인도 개발해서 제공하고 있습니다.


싸이트 메뉴 중 INSTALL 부분을 순서대로 읽어서 설치할 수 있으며 윈도우/리눅스/맥 모두 정리되어 있습니다.
어차피 eclipse는 Java만 설치되어 있으면 구동 가능한 프로그램이라서 OS에 제한적이지 않습니다.


eclipse를 사용할 계획이라면 Eclipse Plug-ins부터 시작하면 됩니다. 그 다음에 차례로 Tool Chains, Build Tools, Debugger 순서대로 설치하면 됩니다.

개략적으로 정리하자면,
  • java 설치 : eclipse를 구동하기 위해서 입니다.
  • eclipse 및 cdt 설치 : eclipse는 기본적으로 자바 개발 환경이므로 C 개발을 위해서 CDT를 설치해야 합니다.
  • GNU ARM Eclipse Plug-ins 설치 : ARM 개발에 필요한 환경을 구현하기 위해서 입니다.
  • Toolchain 설치 : ARM용 컴파일러 및 링커 등을 설치합니다. 설치 과정은 간단해서 내려받고 압축 해제하면 됩니다. GNU Tools for ARM Embedded Processors
  • Build Toos 설치 : make, rm 등 컴파일러와 링커 등을 제외한 개발 환경에 필요한 도구들을 설치합니다. eclipse를 사용한다고 하더라도 결국 make(빌드할 때)와 rm(빌드를 새로 하기 위해서 기존 결과물을 제거할 때)을 이용해야 하므로 반드시 필요합니다. 링크에서는 윈도우를 사용하고 있다는 가정하에서 make, rm 등을 설치하는 방법을 기술하고 있으며 리눅스나 맥OS의 경우에는 배포판에 이미 들어가 있으므로 적절한 명령을 통해서 설치하면 됩니다. 우분투 리눅스라면 apt-get install make 정도가 되겠죠.
  • Debugger 설치 : 컴파일되어서 나온 파일을 ARM 보드에 넣어서 실행하고 디버깅을 하기 위해서는 특별한 장비가 필요합니다. 보통은 J-Link, ST-Link 등을 많이 쓰며, 국내에서도 쉽게 구할 수 있습니다. 또는 OpenOCD라고 해서 오픈 소스로 공개되어 있는 디버거를 사용할 수 있습니다. 이를 OS가 인식할 수 있도록 드라이버를 설치하고 개발 환경에서 설정해야 ARM 보드를 디버깅할 수 있습니다.

eclipse를 사용하지 않을 계획이라면 java/eclipse/플러그인 설치는 제외해도 됩니다.

그런데, 아무래도 윈도우 환경에서는 콘솔로 작업하는 게 어려울 테니 윈도우에서 개발을 진행한다면 eclipse를 사용하는 게 조금 더 편할 것으로 보입니다. 아니면 cygwin이나 mingw를 설치하고 잘 설정해두면 윈도우에서도 리눅스 콘솔처럼 작업이 가능합니다.

단, 주의해야할 부분이 있습니다.
  • Tool Chain 설치 후 실행 파일이 있는 폴더의 경로를 환경 변수에 추가하지 말라고 되어 있는데 만약 eclipse를 사용할 계획이 아니라면 실행 파일의 경로를 환경 변수에 추가하는 것이 좋습니다. (환경 변수를 설정하는 방법은 구글링~)
  • 개인적으로 ARM Cortex 개발 보드에 Chibi-OSuGFX를 이식하기 위해서는 eclipse보다는 Makefile을 이용한 개발 환경이 더 편했습니다. 그래서 저는 익숙한 리눅스 환경(정확히는 ubuntu 14.04 64-bit)에 Makefile을 이용해서 개발 진행하고 있습니다.
  • 리 눅스를 OS로 사용할 경우 배포판에서 기본적으로 arm-none-eabi-gcc, arm-none-eabi-gdb 등을 제공하지만 테스트해본 결과 정상적으로 동작하지 않았습니다. 위에서 정리한 Toolchain을 사용하면 아무 문제 없습니다.
이미 정리가 잘 되어 있는 싸이트가 있어서 링크를 많이 활용했습니다. 이 외에도 구글에서 arm gcc 로 검색하면 좋은 싸이트들이 많습니다.

이상입니다.

2014/10/15

시작

나이를 자꾸 먹어가면서 내가 했던 일들에 대한 정리가 필요할 것 같아서, 예전에 만들어두고 쓰지 않았던 블로그를 시작하려고 합니다.

신변 잡기는 딱히 적을 것도 없고, 지식도 얇은 편이라 내가 잘 알고, 잘 하던 것만 기록할 것 같습니다.
아마도 다음 주제가 대부분이 될 것 같습니다.

  • 마이크로 컨트롤러 프로그래밍 : AVR, ARM Cortex, DSP, PIC 등등
  • 안드로이드 앱 개발 중 외부 장치 제어 등(예를 들자면, UART와 같은)에 필요한 특별한 내용
  • 지금까지 내가 작업한 것들

그럼, 시작합니다.