'Embedded Programming/ChibiOS'에 해당되는 글 3건

  1. 2018.02.25 ChibiOS/RT 설치 1
  2. 2018.02.25 ChibiOS/RT의 특징
  3. 2017.12.19 Cortex-M4 환경에서 ChibiOS 사용한 기초 예제


ChibiOS 다운로드

ChibiOS/RT는 http://sourceforge.net/projects/chibios/files에서 최신 버젼을 다운로드 받을 수 있습니다. 상업용 라이센스를 요청하기 전에 제품 평가를 위해서 GPL 버젼을 사용할 수 있으며, 코드는 정확하게 같습니다. 2018.2월 기준, 버젼은 ChibiOS_18.2.0이고 이를 기준으로 설명합니다.


다운로드 받은 ChibiOS_18.2.0을 압축해제 하면 ChibiOS 폴더 내에 아래와 같은 폴더 구조를 볼 수 있습니다.

demos/ -- 각 플랫폼에 따른 예제입니다.

docs/ -- 문서입니다. 

ext/ -- ChibiOS는 아니지만 외부 라이브러리입니다. 예) fat, tcp/ip 스택

os/ -- ChibiOS 소스 코드입니다.

test/ -- 커널 테스트를 위한 소스 코드입니다.

testhal/ -- HAL integration 테스트 예제입니다.

community/

testex/

tools/


ext에 마련된 모듈은 SD 카드를 지원하기 위한 FAT 파일시스템과 네트워크를 지원하기 위한 오픈 소스 스택인 lwip 등이 포함되어 있으며 필요시 사용할 수 있습니다. testhal의 경우 각 플랫폼에 따른 마이크로컨트롤러의 주변장치를 사용하기 위한 HAL 예제가 마련되어 있습니다. 필요한 경우 가져다 쓰면 됩니다. 예를 들어 ADC의 사용 예제를 참고하고 싶으면 testhal\STM32\STM32F4xx\ADC 폴더에 완전한 소스 코드를 확인할 수 있습니다.


한편 docs 내에 readme.txt 파일 내용과 같은 절차에 따라 documentation을 HTML 문서로 만들 수 있으며 ChibiOS 사용시 도움을 얻을 수 있습니다. 사실 컴파일 시 요구되는 폴더는 소스 코드인 os 폴더와 필요하다면 ext 폴더 정도를 사용할 수 있습니다.


새로운 프로젝트 작성

작업의 편의를 위해서 ChibiOS 폴더 아래에 원하는 폴더를 생성합니다. 예를 들어 저렴한 STM32F411RE-NUCLEO64 보드를 사용한다고 가정하여 ~/ChibiOS_18.2.0/myProject/LED로 폴더를 만들었습니다. 그리고 원하는 프로젝트와 가장 유사한 예제를 우선 demos 폴더에서 찾아 자신이 만든 새폴더로 복사합니다.



위 그림과 같은 STM32F411RE-NUCLEO64 보드를 사용할 경우, demos\STM32\RT-STM32F411RE-NUCLEO64 폴더에 이미 친절하게 준비되어 있습니다. 복사한 파일은 반드시 있어야 하는 3개의 헤더 파일인 chconf.h, halconf.h, mcuconf.h와 자신이 코딩할 main.c 그리고 리눅스/유닉스와 같은 커맨드라인 환경에서 개발하는데 필요한 Makefile입니다.


    • chconf.h - Kernel에 관련된 세팅이 포함되며 예를 들어 시스템 타이머와 Kernel 파라미터, 디버깅에 연관된 스위치 설정.

    • halconf.h - ChibiOS/HAL 드라이버에 관련된 설정. 예를 들어, PAL, CAN, ADC, DAC, PWM, Serial 등이며 사용하지 않는 드라이버는 disable 시킴.

    • mcuconf.h - MCU에 관련된 모든 설정. 예를 들어 Clock 트리, DMA, IRQ 우선순위 등.


Makefile 편집

Makefile은 전통적인 make 명령이 이해할 수 있는 문법으로 구성되어 있어 컴파일 및 링크 등이 일괄 처리되도록 규명한 일종의 배치 파일입니다. 다음은 demos\STM32\RT-STM32F411RE-NUCLEO64 폴더에서 복사해 온 Makefile의 내용입니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
##############################################################################
# Build global options
# NOTE: Can be overridden externally.
#
 
# Compiler options here.
ifeq ($(USE_OPT),)
  USE_OPT = -O2 -ggdb -fomit-frame-pointer -falign-functions=16
endif
 
# C specific options here (added to USE_OPT).
ifeq ($(USE_COPT),)
  USE_COPT = 
endif
 
# C++ specific options here (added to USE_OPT).
ifeq ($(USE_CPPOPT),)
  USE_CPPOPT = -fno-rtti
endif
 
# Enable this if you want the linker to remove unused code and data
ifeq ($(USE_LINK_GC),)
  USE_LINK_GC = yes
endif
 
# Linker extra options here.
ifeq ($(USE_LDOPT),)
  USE_LDOPT = 
endif
 
# Enable this if you want link time optimizations (LTO)
ifeq ($(USE_LTO),)
  USE_LTO = yes
endif
 
# If enabled, this option allows to compile the application in THUMB mode.
ifeq ($(USE_THUMB),)
  USE_THUMB = yes
endif
 
# Enable this if you want to see the full log while compiling.
ifeq ($(USE_VERBOSE_COMPILE),)
  USE_VERBOSE_COMPILE = no
endif
 
# If enabled, this option makes the build process faster by not compiling
# modules not used in the current configuration.
ifeq ($(USE_SMART_BUILD),)
  USE_SMART_BUILD = yes
endif
 
#
# Build global options
##############################################################################
 
##############################################################################
# Architecture or project specific options
#
 
# Stack size to be allocated to the Cortex-M process stack. This stack is
# the stack used by the main() thread.
ifeq ($(USE_PROCESS_STACKSIZE),)
  USE_PROCESS_STACKSIZE = 0x400
endif
 
# Stack size to the allocated to the Cortex-M main/exceptions stack. This
# stack is used for processing interrupts and exceptions.
ifeq ($(USE_EXCEPTIONS_STACKSIZE),)
  USE_EXCEPTIONS_STACKSIZE = 0x400
endif
 
# Enables the use of FPU (no, softfp, hard).
ifeq ($(USE_FPU),)
  USE_FPU = no
endif
 
#
# Architecture or project specific options
##############################################################################
 
##############################################################################
# Project, sources and paths
#
 
# Define project name here
PROJECT = ch
 
# Imported source files and paths
CHIBIOS = ../../..
# Startup files.
include $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f4xx.mk
# HAL-OSAL files (optional).
include $(CHIBIOS)/os/hal/hal.mk
include $(CHIBIOS)/os/hal/ports/STM32/STM32F4xx/platform.mk
include $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_F411RE/board.mk
include $(CHIBIOS)/os/hal/osal/rt/osal.mk
# RTOS files (optional).
include $(CHIBIOS)/os/rt/rt.mk
include $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk
# Other files (optional).
include $(CHIBIOS)/test/lib/test.mk
include $(CHIBIOS)/test/rt/rt_test.mk
include $(CHIBIOS)/test/oslib/oslib_test.mk
 
# Define linker script file here
LDSCRIPT= $(STARTUPLD)/STM32F411xE.ld
 
# C sources that can be compiled in ARM or THUMB mode depending on the global
# setting.
CSRC = $(STARTUPSRC) \
       $(KERNSRC) \
       $(PORTSRC) \
       $(OSALSRC) \
       $(HALSRC) \
       $(PLATFORMSRC) \
       $(BOARDSRC) \
       $(TESTSRC) \
       main.c
 
# C++ sources that can be compiled in ARM or THUMB mode depending on the global
# setting.
CPPSRC =
 
# C sources to be compiled in ARM mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
#       option that results in lower performance and larger code size.
ACSRC =
 
# C++ sources to be compiled in ARM mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
#       option that results in lower performance and larger code size.
ACPPSRC =
 
# C sources to be compiled in THUMB mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
#       option that results in lower performance and larger code size.
TCSRC =
 
# C sources to be compiled in THUMB mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
#       option that results in lower performance and larger code size.
TCPPSRC =
 
# List ASM source files here
ASMSRC =
ASMXSRC = $(STARTUPASM) $(PORTASM) $(OSALASM)
 
INCDIR = $(CHIBIOS)/os/license \
         $(STARTUPINC) $(KERNINC) $(PORTINC) $(OSALINC) \
         $(HALINC) $(PLATFORMINC) $(BOARDINC) $(TESTINC) \
         $(CHIBIOS)/os/various
 
#
# Project, sources and paths
##############################################################################
 
##############################################################################
# Compiler settings
#
 
MCU  = cortex-m4
 
#TRGT = arm-elf-
TRGT = arm-none-eabi-
CC   = $(TRGT)gcc
CPPC = $(TRGT)g++
# Enable loading with g++ only if you need C++ runtime support.
# NOTE: You can use C++ even without C++ support if you are careful. C++
#       runtime support makes code size explode.
LD   = $(TRGT)gcc
#LD   = $(TRGT)g++
CP   = $(TRGT)objcopy
AS   = $(TRGT)gcc -x assembler-with-cpp
AR   = $(TRGT)ar
OD   = $(TRGT)objdump
SZ   = $(TRGT)size
HEX  = $(CP) -O ihex
BIN  = $(CP) -O binary
 
# ARM-specific options here
AOPT =
 
# THUMB-specific options here
TOPT = -mthumb -DTHUMB
 
# Define C warning options here
CWARN = -Wall -Wextra -Wundef -Wstrict-prototypes
 
# Define C++ warning options here
CPPWARN = -Wall -Wextra -Wundef
 
#
# Compiler settings
##############################################################################
 
##############################################################################
# Start of user section
#
 
# List all user C define here, like -D_DEBUG=1
UDEFS =
 
# Define ASM defines here
UADEFS =
 
# List all user directories here
UINCDIR =
 
# List the user directory to look for the libraries here
ULIBDIR =
 
# List all user libraries here
ULIBS =
 
#
# End of user defines
##############################################################################
 
RULESPATH = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC
include $(RULESPATH)/rules.mk
 
cs


86번 라인의 PROJECT는 프로젝트의 이름이자 생성되는 파일명과 같습니다. 89번 라인은 ChibiOS 폴더의 절대 경로 또는 상대 경로입니다. '~/ChibiOS_18.2.0'이 추천됩니다. 161번 라인은 STM32F411RE-NUCLEO64 보드가 STM32F406 디바이스를 내장하므로 'cortex-m4'입니다. 164번은 사용하는 Toolchain을 지정하는 것으로 기본적으로 GNU Toolchain을 사용하도록 되어 있으므로 그냥 둡니다.


95번 라인의 'board.mk'는 사용하는 보드의 설정 정보를 담은 것으로 아래와 같습니다. 여기서는 'board.h'와 'board.c' 파일을 include 하게 합니다. 우선 board.h 파일의 정보는 보드에서 마이크로컨트롤러의 핀이 어떻게 사용되었는지에 관한 정보입니다. 예를 들어 핀인 GPIO는 아날로그와 디지털 모드로 사용될 수 있으며, 디지털 모드는 그 쓰임새에 따라 입력 혹은 출력, pull-up, PWM, CAN, UART 등등 여러가지의 모드로 사용되며 이를 일일이 지정하게 됩니다. board.c 파일은 board.h 파일에서 GPIO 사용을 매크로 지정한데로 초기화하는 함수가 구현되어 있습니다. 따라서 핀의 사용이 달라진다면 board.h는 반드시 수정되어야 합니다.


1
2
3
4
5
6
7
8
9
# List of all the board related files.
BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_F411RE/board.c
 
# Required include directories
BOARDINC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_F411RE
 
# Shared variables
ALLCSRC += $(BOARDSRC)
ALLINC  += $(BOARDINC)
cs


그러나 사용하고자 하는 보드가 없거나 사용자가 직접 PCB를 제작하고 assemble 한 보드의 경우에는 가장 유사하다고 생각되는 demos 폴더 하에 보드 중에서 찾아보고 /os/hal/boards 폴더 하에 적당한 board.mk, board.h 그리고 board.c 파일을 자신이 생성한 폴더에 복사합니다. 그리고 board.mk 파일에서 경로를 수정하고 board.h 파일에서 GPIO를 수정해야 합니다.


애플리케이션 코딩

'main.c'에 사용자가 원하는 기능을 작성하면 됩니다. demos\STM32\RT-STM32F411RE-NUCLEO64 폴더에서 제공하는 예제인 main.c는 다음과 같습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/*
    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at
        http://www.apache.org/licenses/LICENSE-2.0
    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/
 
#include "ch.h"
#include "hal.h"
#include "rt_test_root.h"
#include "oslib_test_root.h"
 
/*
 * Green LED blinker thread, times are in milliseconds.
 */
static THD_WORKING_AREA(waThread1, 128);
static THD_FUNCTION(Thread1, arg) {
 
  (void)arg;
  chRegSetThreadName("blinker");
  while (true) {
    palClearPad(GPIOA, GPIOA_LED_GREEN);
    chThdSleepMilliseconds(500);
    palSetPad(GPIOA, GPIOA_LED_GREEN);
    chThdSleepMilliseconds(500);
  }
}
 
/*
 * Application entry point.
 */
int main(void) {
 
  /*
   * System initializations.
   * - HAL initialization, this also initializes the configured device drivers
   *   and performs the board-specific initializations.
   * - Kernel initialization, the main() function becomes a thread and the
   *   RTOS is active.
   */
  halInit();
  chSysInit();
 
  /*
   * Activates the serial driver 2 using the driver default configuration.
   */
  sdStart(&SD2, NULL);
 
  /*
   * Creates the blinker thread.
   */
  chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
 
  /*
   * Normal main() thread activity, in this demo it does nothing except
   * sleeping in a loop and check the button state.
   */
  while (true) {
    if (!palReadPad(GPIOC, GPIOC_BUTTON)) {
      test_execute((BaseSequentialStream *)&SD2, &rt_test_suite);
      test_execute((BaseSequentialStream *)&SD2, &oslib_test_suite);
    }
    chThdSleepMilliseconds(500);
  }
}
cs


ChibiOS는 멀티 쓰레드(multi-thread)를 지원하고 Thread1은 GPIOA의 5번 핀을 500ms 간격으로 컸다 켰다를 반복합니다. 여기서 chRegSetThreadName("blinker") 함수는 ChibiOS 이하의 os\rt\include\chregistry.h에 선언되어 있으며, chThdSleepMilliseconds() 함수는 ChibiOS 이하의 os\rt\include\chthreads.h에 선언되어 있고, palClearPad()와 palSetPad() 함수는 ChibiOS 이하의 os\hal\include\hal_pal.h에 선언되어 있습니다.


main() 함수에서 hallnit()는 ChibiOS/HAL과 HAL 서브 시스템을 초기화 하는 것이며, chSysInit()는 Kernel이 초기화되고 main 함수가 쓰레드가 되며 RTOS가 활성화되도록 합니다. 이후에는 main() 함수의 스레드와 다른 모든 스레드가 실행될 준비가 되지 않았을 때 실행되는 idle 스레드가 생성됩니다. 한편 halInit() 함수는 ChibiOS 이하의 os\hal\include\hal.h에 그리고 chSysInit() 함수는 ChibiOS 이하의 os\rt\include\chsys.h에 선언되어 있습니다.


sdStart(&SD2, NULL) 함수는 시리얼 드라이버 2를 디폴트 설정으로 활성화 하는 것으로 ChibiOS 이하의 os\hal\include\hal_serial.h에 정의되어 있습니다. chThdCreateStatic() 함수는 Thread1을 생성시키는 함수로 ChibiOS 이하의 os\rt\include\chthreads.h에 선언되어 있습니다.


while 문 내에 palReadPad(GPIOC, GPIOC_BUTTON)) 함수는 GPIOC의 13번 핀에 연결된 버튼 값을 읽어오는 것으로 ChibiOS 이하의 os\hal\include\hal_pal.h에 선언되어 있으며, 버튼이 눌러지면 조건 문 아래의 연속된 test_execute() 함수가 실행되고 이는 500ms 간격으로 버튼을 조사하게 됩니다. 이 test_execute()는 ChibiOS 이하의 test\lib\ch_test.h에 정의된 함수로 두번째 인자인 문자열을 시리얼 드라이버 2에 보내게 됩니다.


빌드

작성이 완료되었으며 make 명령으로 컴파일 합니다. 만일 헤더 파일이 수정되었다면 처음부터 다시 컴파일을 진행할 것이고 오류없이 컴파일이 성공하였다면 ~/ChibiOS_18.2.0/myProject/LED/build 폴더 안에 'ch.elf'를 확인할 수 있을 것입니다.



'Embedded Programming > ChibiOS' 카테고리의 다른 글

ChibiOS/RT의 특징  (0) 2018.02.25
Cortex-M4 환경에서 ChibiOS 사용한 기초 예제  (0) 2017.12.19
Posted by Nature & Life


ChibiOS/RT는 Giovanni Di Sirio에 의해서 개발하였으며, 임베디드(embedded) 애플리케이션을 위한 무료이자 효율적이고, 컴팩트하며 빠른 RTOS(Real Time Operating System)입니다. Kernel primitive의 이해가 쉬운 세트를 제공하며 다양한 아키텍처(ARM7, Cortex-M0, Cortex-M3, Cortex-M4, PowerPC e200z, STM8, AVR, MSP430, ColdFire, H8S, x86)를 지원합니다. ChibiOS/RT는 RTOS로 GPL3 라이센스 하에서 배포됩니다.


ChibiOS/RT는 8, 16, 32-bit 마이크로컨트롤러의 임베디드 애플리케이션을 위해서 설계되었습니다; 사이즈와 실행 효율이 주요 프로젝트의 목표입니다. 참고로 커널 사이즈는 STM32 Cortex-M3 프로세스에서 활성화된 모든 서브시스템에서 최소 1.2KB에서 최대 5.5KB입니다. 커널은 초당 220,000 이상의 스레딩을 생성시키거나 종료할 수 있고, 72MHz의 STM32에서 1.2ms 내에 컨텍스트 스위칭(context switch)을 실행할 수 있습니다.


특징

  • Tiny memory footprint, 고성능, 쉬운 이식성(portable), 깔끔하고 이해가 쉽습니다.

  • 선점형 마이크로커널이자 멀티스레딩(multithreading), 128 우선 순위 레벨, 신뢰성 있고 정적 아키텍처.

  • Semaphores, Mutexes, CondVars, Messages, Event Flags, Mailboxes, Virtual Timers를 위한 커널 지원.

      • Counting semaphores

      • Mutexes with support for the priority inheritance algorithm

      • Condition variables

      • Synchronous and asynchronous Messages

      • Event flags and handlers

  • IRQ abstraction, non-OS fast IRQ sources(zero latency buzzword) 지원.

  • ARM, ARM-CM0, ARM-CM3, ARM-CM4, PowerPC, STM8, MSP430, AVR, ColdFire, H8S, Linux/Win32/MacOS 시뮬레이터를 지원.

  • HAL(Hardware Abstraction Layer) 컴포넌트는 지원되는 플랫폼 간에 애플리케이션의 이식이 가능.

  • Port(GPIO), Serial, ADC, CAN, DAC, EXT, GPT(general-purpose timer), I2C, I2S, ICU, MAC, MMC/SD, PAL, PWM, RTC, SDC, SPI, UART, USB, WDG 디바이스 드라이버 모델을 위한 HAL 지원.

  • uIP과 lwIP TCP/IP stacks(demo 포함)를 위한 지원.

  • FatFS 파일 시스템 라이브러리(demo 포함)를 지원.

  • 동일한 우선 순위 레벨에서 스레드를 위해서 Round-robin 스케쥴링

  • Software timers

  • Queues

  • Synchronous and asynchronous I/O with timeout capability

  • Thread-safe memory heap and memory pool allocators.


스레드, semaphore, 타이머와 같은 모든 시스템 객체는 실행 중에 생성되고 삭제될 수 있습니다. 가능한 메모리를 제외하고 어떤 상한이 없습니다. 시스템 신뢰성을 개선하기 위해서, 커널 아키텍처는 전체적으로 정적이고, memory allocator가 요구되지 않습니다(그러나 옵션으로 가능합니다). 그리고 테이블 혹은 배열과 같은 상한 사이즈 제한과 함께 어떠한 데이터 구조가 존재하지 않습니다. 시스템 API는 에러 코드나 예외와 같은 에러 조건을 갖지 않도록 설계되었습니다.


RTOS는 임베디드 디바이스 애플리케이션을 위해서 설계되었고 다양한 마이크로컨트롤러를 위한 데모 애플리케이션을 포함합니다:

  • ST STM32F1xx, STM32F2xx, STM32F3xx, STM32F4xx, STM32L1xx, STM32F0xx

  • ST STM8S208x, STM8S105x, STM8L152x

  • ST/Freescale SPC56x / MPC56xx

  • NXP LPC11xx, LPC11Uxx, LPC13xx

  • NXP LPC2148

  • Atmel AT91SAM7S, AT91SAM7X

  • Atmel Mega AVR

  • TI MSP430x1611

  • TI TM4C123G and TM4C1294

  • Microchip PIC32MX


소프트웨어 I/O 에뮬레이션(emulation) 모드로 Win32 프로세스에서 커널을 실행시키는 것이 가능합니다. 이는 물리적인 하드웨어의 요구 없이 쉬운 애플리케이션 개발을 허용합니다.




'Embedded Programming > ChibiOS' 카테고리의 다른 글

ChibiOS/RT 설치  (1) 2018.02.25
Cortex-M4 환경에서 ChibiOS 사용한 기초 예제  (0) 2017.12.19
Posted by Nature & Life
Embedded Programming/ChibiOS2017. 12. 19. 19:29


http://www.playembedded.org/blog/en/2017/08/24/demos-chibios-stm32/

http://www.playembedded.org/blog/en/2016/10/29/explanation-multithreading-chibios/


Cortex-M4 MCU(ST32F4)를 환경에서 Real Time OS(RTOS)인 ChibiOS를 이용한 임베디드(embedded) 시스템의 코딩의 예제입니다. 참고하시기 바랍니다.

 

주요 헤더 파일입니다.

chconf.h

Kernel에 관련된 세팅이 포함되며 예를 들어 시스템 Timer와 Kernel 파라미터, 디버깅에 연관된 스위치 등입니다.

/*===========================================================================*/
/**
* @name Debug options
* @{
*/
/*===========================================================================*/
 
/**
* @brief   Debug option, kernel statistics.
*
* @note    The default is @p FALSE.
*/
#define CH_DBG_STATISTICS                   FALSE
 
/**
* @brief   Debug option, system state check.
* @details If enabled the correct call protocol for system APIs is checked
*          at runtime.
*
* @note    The default is @p FALSE.
*/
#define CH_DBG_SYSTEM_STATE_CHECK           FALSE
 
/**
* @brief   Debug option, parameters checks.
* @details If enabled then the checks on the API functions input
*          parameters are activated.
*
* @note    The default is @p FALSE.
*/
#define CH_DBG_ENABLE_CHECKS                FALSE
 
/**
* @brief   Debug option, consistency checks.
* @details If enabled then all the assertions in the kernel code are
*          activated. This includes consistency checks inside the kernel,
*          runtime anomalies and port-defined checks.
*
* @note    The default is @p FALSE.
*/
#define CH_DBG_ENABLE_ASSERTS               FALSE
 
/**
* @brief   Debug option, trace buffer.
* @details If enabled then the trace buffer is activated.
*
* @note    The default is @p CH_DBG_TRACE_MASK_DISABLED.
*/
#define CH_DBG_TRACE_MASK                   CH_DBG_TRACE_MASK_DISABLED
 
/**
* @brief   Trace buffer entries.
* @note    The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is
*          different from @p CH_DBG_TRACE_MASK_DISABLED.
*/
#define CH_DBG_TRACE_BUFFER_SIZE            128
 
/**
* @brief   Debug option, stack checks.
* @details If enabled then a runtime stack check is performed.
*
* @note    The default is @p FALSE.
* @note    The stack check is performed in a architecture/port dependent way.
*          It may not be implemented or some ports.
* @note    The default failure mode is to halt the system with the global
*          @p panic_msg variable set to @p NULL.
*/
#define CH_DBG_ENABLE_STACK_CHECK           FALSE
 
/**
* @brief   Debug option, stacks initialization.
* @details If enabled then the threads working area is filled with a byte
*          value when a thread is created. This can be useful for the
*          runtime measurement of the used stack.
*
* @note    The default is @p FALSE.
*/
#define CH_DBG_FILL_THREADS                 FALSE
 
/**
* @brief   Debug option, threads profiling.
* @details If enabled then a field is added to the @p thread_t structure that
*          counts the system ticks occurred while executing the thread.
*
* @note    The default is @p FALSE.
* @note    This debug option is not currently compatible with the
*          tickless mode.
*/
#define CH_DBG_THREADS_PROFILING            FALSE
 

/** @} */


halconf.h

ChibiOS/HAL 드라이버에 관련된 특성을 포함합니다. 예를 들어, PAL, CAN, ADC, DAC, PWM, Serial 드라이버 등이 해당됩니다. 참고로 사용하지 않는 드라이버는 disable 시켜야 합니다.


/**
* @brief   Enables the PAL subsystem.
*/
#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__)
#define HAL_USE_PAL                 TRUE
#endif
 
/**
* @brief   Enables the ADC subsystem.
*/
#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__)
#define HAL_USE_ADC                 FALSE
#endif
 
/**
* @brief   Enables the CAN subsystem.
*/
#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__)
#define HAL_USE_CAN                 TRUE
#endif
 
/**
* @brief   Enables the DAC subsystem.
*/
#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__)
#define HAL_USE_DAC                 FALSE

#endif


mcuconf.h

MCU에 관련된 모든 설정을 포함합니다. 따라서 MCU에 따라 다릅니다. Clock 트리, DMA, IRQ 우선순위 등이 예입니다.


ChibiOS의 가장 중요한 특성 중의 하나는 멀티스레딩(multi-threading)입니다. 이는 Kernel이 한가지 이상의 스레드를 독립적으로 나란히 동시에 실행하는 것입니다. 스레드는 실제의 함수이고 시작되었을 때 우선순위 레벨(priority level)과 working area에 연관됩니다. Working area는 스레드에 할당된 메모리의 부분이고 우선 순위는 상대적인 숫자로 나타냅니다.


모든 스레드는 그 루프 내에 sleep과 suspending 함수를 가져야 합니다. 이런 방식으로 CPU의 소유권은 여러 스레드 사이에서 스위치 되고 스케쥴은 진행될 수 있습니다. ChibiOS는 다른 sleep 함수를 제공합니다. 다음 함수는 XXX [ms] 시간 동안 스레드를 suspending 합니다. 이 함수는 ChibiOS 이하의 os\rt\include\chthreads.h에 선언되어 있습니다.


chThdSleepMilliseconds(<xxx>);


Makefile

Embitz와 같은 IDE 환경을 사용시 일일이 지정해야 하고 IDE 툴마다 다를 수 있지만, 전통적인 Unix 환경에서 Makefile을 이용한 방법이 일목요연하고 유지관리가 용이하기 때문에 Makefile을 이용한 빌드 기준으로 설명합니다.


ChibiOS를 사용하기 위해서는 ChibiOS가 설치된 상대 경로의 지정이 필요합니다. 

# Imported source files and paths
PROJECT = build
CHIBIOS = ../../..
MCU = cortex-m4
TRGT = arm-none-eabi-


참고로 'build'는 프로젝트 이름이며 MCU는 cortex-m4이고 TRGT는 GNU Toolchain을 사용함을 의미합니다.

main.c

static THD_WORKING_AREA(waThread1, 128);
static THD_FUNCTION(Thread1, arg) {
 
  (void)arg;
  chRegSetThreadName("Thread1");
  while (true) {
    palTogglePad(GPIOA, GPIOA_LED_GREEN);
    chThdSleepMilliseconds(200);
  }
}
 
int main(void) {
  halInit();
  chSysInit();
 
  chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO + 1, Thread1, NULL);
  while (true) {
    palTogglePad(GPIOA, GPIOA_LED_RED);
    chThdSleepMilliseconds(375);
  }

}


위의 예제에서 128byte의 크기를 갖는 waThread1라는 이름의 working area를 선언하고 Thread1이라는 함수를 선언합니다. 위의 두 라인은 단지 메모리와 함수를 선언한 것이며 main() 함수에서 thread 생성을 시켜야 사용할 수 있습니다. THE_FUNCTION의 arg는 함수 내부 코드로 전달되는 인자입니다.


chRegSetThreadName("blinker");


위 함수는 루프 이전에 단 한번 실행됩니다. 이 함수는 ChibiOS 이하의 os\rt\include\chregistry.h에 선언되어 있습니다.



main()함수 내의 2가지 함수가 실행되는데 이는 시스템 초기화를 실행하는 것으로, hallnit()는 ChibiOS/HAL과 HAL 서브 시스템을 초기화 하는 것이며 chSysInit()는 ChibiOS/RT의 API와 Kernel을 초기화합니다. 이후에는 main() 함수의 스레드와 다른 모든 스레드가 실행될 준비가 되지 않았을 때 실행되는 idle 스레드가 생성됩니다. 또한 이들 초기화 이전에 어떤 API의 실행은 하지 말아야 합니다. ChibiOS/RT 그리고 ChibiOS/HAL에 근거한 모든 프로그램은 위와 동일한 방식으로 시작합니다. 여기서 halInit() 함수는 ChibiOS 이하의 os\hal\include\hal.h에 그리고 chSysInit() 함수는 ChibiOS 이하의 os\rt\include\chsys.h에 선언되어 있습니다.


palTogglePad() 함수는 ChibiOS 이하의 os\hal\include\hal_pal.h에 선언되어 있으며, 첫번째 인자는 포트이고 두번째 인자는 그 포트 내에서의 패드 숫자입니다. 따라서 이 함수는 해당 포트의 해당 패드에 그 논리적인 상태 즉, LED를 토글(toggle)합니다.



chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO + 1, Thread1, NULL);


위의 스레드의 생성 함수는 5개의 인자가 필요하며 첫번째는 working area의 포인트이며 마지막 인자는 Thread1 함수로 전달될 파라미터로 이 경우에는 아무것도 보내지 않습니다. 이 함수는 ChibiOS 이하의 os\rt\include\chthreads.h에 선언되어 있습니다.


이 경우에 3개의 스레드인, Thead1, main, idle가 있으며 즉, Kernel은 3가지 스레드를 관리게 되는데 개념적인 timing 플로우는 다음과 같습니다.



위 그림에서 스레드는 y축 상에 우선순위에 따라 실행되고 x축은 시간이 됩니다. chSysInit()이 실행될 때 main() 함수는 main이라는 스레드가 되고 Thread1의 생성될 때까지 실행됩니다. Thread1이 생성된 후에는 main와 Thread1이 준비된 상태가 됩니다. 


ChibiOS의 우선순위는 정수이고 LOWPRIO와 HIGHPRIO의 범위를 가지며 main 스레드는 NORMALPRIO의 우선 순위를 가지며 전체 범위의 중간 값을 가집니다. Thread1과 main() 함수 내에 chThdSleepMilliseconds() 함수는 시간을 지연시키지만 그 동안 CPU의 소유권을 다음의 우선순위 스레드에 넘기게 됩니다.



'Embedded Programming > ChibiOS' 카테고리의 다른 글

ChibiOS/RT 설치  (1) 2018.02.25
ChibiOS/RT의 특징  (0) 2018.02.25
Posted by Nature & Life