본문 바로가기
  • 경제적 자유를 얻는 그날까지
엔지니어링/드론

SwiftF4 FC 개발 프로젝트 (1) - 프로젝트 생성 및 디버그 환경 설정

by 베니스상인 2024. 3. 16.

 

swiftF4는 STM32F411CEU6 기반의 FC를 개발하는 프로젝트입니다.

 

하드웨어는 ATK-minifly 제품을 이용하고,

펌웨어는 Bitcraze사에서 나온 오픈소스 펌웨어 Crazyfile를 하드웨어에 맞도록 이식하여 개발할 예정입니다.

 

본 프로젝트를 하는 이유는 아래와 같습니다.

 

1) Crazyfile 기반의 오픈소스 펌웨어와 생태계 이해

2) 하드웨어에 맞는 이식성

3) 하드웨어 확장에 대한 개발 프로젝트 수행

 

 

본 프로젝트에서 나온 하드웨어에 대한 자료는 아래를 참고하면 됩니다.

https://ko.aliexpress.com/item/1005006306684091.html?gatewayAdapt=glo2kor

 

117085.0₩ 5% OFF|오픈 소스 쿼드콥터 미니플라이 UAV 비행 제어, STM32 DIY 키트, ATK MiniFly| | - AliExpress

Smarter Shopping, Better Living! Aliexpress.com

ko.aliexpress.com

 

 

Crazyflie의 펌웨어도 ST사의 프로세서를 사용하였지만, 드라이버 라이브러리가 STM32 Standard Peripheral Libraries를 사용하여 개발되어 있습니다. 해당 라이브러리는 본인은 STM32CubeIDE를 사용하여 HAL 드라이버 기반으로 개발할 예정이므로 이식 과정에서 드라이버를 수정하는 작업을 해주어야 합니다.

HAL 라이브러리를 사용하는 이유는 STM32CubeIDE 툴 내에서 하드웨어 설정에 맞도록 HAL 드라이버도 자동으로 생성해주기 때문에 라이브러리를 관리하기 편리합니다.

 

STM32CubeIDE는 1.14.1 Linux 버전을 사용하였다. 그리고 디버거는 J-link OB 디버거를 사용하였습니다.

 

J-Link OB 디버거의 정보는 아래와 같습니다.

 

https://ko.aliexpress.com/item/1005005483264513.html?gatewayAdapt=glo2kor

 

2356.0₩ |호환 j link OB ARM 시뮬레이션 디버거, SWD 프로그래머 STM32 다운로드, Jlink 세대 V8| | - AliExp

Smarter Shopping, Better Living! Aliexpress.com

ko.aliexpress.com

 

 

 

 

 

1. 프로젝트 생성

 

STM32CubeIDE를 실행합니다. New 에서 STM32 프로젝트를 생성합니다.

 

프로세서는 STM32F411CEU6를 선택합니다.

 

 

 

파일명을 작성하고 finish를 누르면 프로젝트가 생성됩니다.

 

 

 

2. 클럭 설정

프로젝트가 생성되면 GUI 기반으로 프로세서를 설정할 수 있는 IOC 창이 나타납니다.

 

프로젝트에서 가장 먼저 할 것은 클럭을 설정한다. 클럭 설정은 왼쪽 System Core 메뉴에서 RCC 항목을 선택하고 아래와 같이 설정합니다.

 

  • High Speed Clock: Cristal / Ceramic Resonator

 

 

 

상단 메뉴중 Clock Configuration 탭으로 넘어가면 상세하게 클럭을 설정하는 화면이 나타난다. 상세한 클럭은 아래와 같이 설정합니다.

  • Input Frequency: 8MHz
  • PLL Source MUX: HSE
  • System Clock MUX: PLLCLK
  • HCLK(MHz): 96

Input Frequency는 위에서 클럭 소스를 외부 입력으로 선택했기 때문에 외부 오실레이터 값을 입력해야 합니다. 현재 사용하는 하드웨어는 8MHz 외부 오실레이터를 사용하기 때문에 선택하였고, 사용자의 하드웨어에 맞는 클럭 주파수를 입력하면 됩니다.

 

 

 

상단 메뉴중 Project Manager에서 Code Generator에서 아래와 같이 설정합니다.

  • Generate peripheral initialzation ... 을 선택(초기화 함수를 생성)

 

Advanced  Settings를 보면 모두 HAL 타입으로 드라이버가 선택되어 있습니다.  프로젝트를 생성하면 HAL 기반의 드라이버가 생성됩니다.

 

 

 

Ctrl + S를 누르면 설정된 하드웨어 기반으로 프로젝트 파일이 생성됩니다.

 

 

 

Ctrl +B를 누르면 자동으로 빌드가 진행됩니다. 빌드가 완료되면 아래와 같이 elf 파일이 생성됩니다.

 

 

 

3. 디버그 환경 설정

 

상단 메뉴에서 Debug Configuration을 실행하면 아래와 같이 디버거 설정화면이 나타납니다. 

 

Application은 조금 전에 빌드된 elf 파일이 올라와야 합니다.

 

 

Debugger 탭으로 넘어가면 Debugger Probe 를 설정하는 곳이 있습니다. 사용하는 디버거를 설정해주면 됩니다. 주로 ST-Link 또는 J-link를 많이 사용하는데 본인은 J-link를 사용하므로 SEGGER J-Link로 설정을 변경합니다.

 

 

설정을 변경하여 디버그를 실행하면 아래와 같이 디버그가 프로그램을 다운로드하고 main 엔트리에서 자동으로 break point가 걸려있는 것을 확인하실 수 있습니다. 

 

 

 

※ J-Link debug console log

SEGGER J-Link GDB Server V7.92n Command Line Version

JLinkARM.dll V7.92n (DLL compiled Oct 31 2023 15:15:34)

Command line: -port 2331 -s -device STM32F411CE -endian little -speed 4000 -if swd -vd
-----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:               on
Init regs on start:            off
Silent mode:                   off
Single run mode:               on
Target connection timeout:     0 ms
------J-Link related settings------
J-Link Host interface:         USB
J-Link script:                 none
J-Link settings file:          none
------Target related settings------
Target device:                 STM32F411CE
Target device parameters:      none
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: 20090928
Feature(s): RDI,FlashDL,FlashBP,JFlash,GDB
Checking target voltage...
Target voltage: 3.30 V
Listening on TCP/IP port 2331
Connecting to target...
Halting core...
Connected to target
Waiting for GDB connection...Connected to 127.0.0.1
GDB client (conn. 13) requested target.xml from GDB Server
Reading common registers: Read register 'r0' (4 bytes) from hardware: 0x00000000
Read register 'r1' (4 bytes) from hardware: 0x00ED00E0
Read register 'r2' (4 bytes) from hardware: 0x00380240
Read register 'r3' (4 bytes) from hardware: 0x80000000
Read register 'r4' (4 bytes) from hardware: 0x2C000020
Read register 'r5' (4 bytes) from hardware: 0x00000000
Read register 'r6' (4 bytes) from hardware: 0x00000000
Read register 'r7' (4 bytes) from hardware: 0xF8FF0120
Read register 'r8' (4 bytes) from hardware: 0x00000000
Read register 'r9' (4 bytes) from hardware: 0x00000000
Read register 'r10' (4 bytes) from hardware: 0x00000000
Read register 'r11' (4 bytes) from hardware: 0x00000000
Read register 'r12' (4 bytes) from hardware: 0x00000080
Read register 'sp' (4 bytes) from hardware: 0xF8FF0120
Read register 'lr' (4 bytes) from hardware: 0x19050008
Read register 'pc' (4 bytes) from hardware: 0x18050008
Read register 'xpsr' (4 bytes) from hardware: 0x00000001
Read 4 bytes @ address 0x08000518 (Data = 0x0000E7FE)
Received monitor command: ReadAPEx 0x0 0xF8
O.K.:0xE00FF003
Received monitor command: ReadMemAP 0x0 0xE00FFFD0 0x8 0x0
O.K.:0x00000000,0x00000000,0x00000000,0x00000000,0x00000011,0x00000004,0x0000000A,0x00000000
Connected to 127.0.0.1
GDB client (conn. 14) requested target.xml from GDB Server
Reading common registers: Read register 'r0' (4 bytes) from hardware: 0x00000000
Read register 'r1' (4 bytes) from hardware: 0x00ED00E0
Read register 'r2' (4 bytes) from hardware: 0x00380240
Read register 'r3' (4 bytes) from hardware: 0x80000000
Read register 'r4' (4 bytes) from hardware: 0x2C000020
Read register 'r5' (4 bytes) from hardware: 0x00000000
Read register 'r6' (4 bytes) from hardware: 0x00000000
Read register 'r7' (4 bytes) from hardware: 0xF8FF0120
Read register 'r8' (4 bytes) from hardware: 0x00000000
Read register 'r9' (4 bytes) from hardware: 0x00000000
Read register 'r10' (4 bytes) from hardware: 0x00000000
Read register 'r11' (4 bytes) from hardware: 0x00000000
Read register 'r12' (4 bytes) from hardware: 0x00000080
Read register 'sp' (4 bytes) from hardware: 0xF8FF0120
Read register 'lr' (4 bytes) from hardware: 0x19050008
Read register 'pc' (4 bytes) from hardware: 0x18050008
Read register 'xpsr' (4 bytes) from hardware: 0x00000001
Read 4 bytes @ address 0x08000518 (Data = 0x0000E7FE)
Received monitor command: reset
Resetting target
Downloading 408 bytes @ address 0x08000000 - Verified OK
Downloading 4452 bytes @ address 0x08000198 - Verified OK
Downloading 16 bytes @ address 0x080012FC - Verified OK
Downloading 8 bytes @ address 0x0800130C - Verified OK
Downloading 4 bytes @ address 0x08001314 - Verified OK
Downloading 4 bytes @ address 0x08001318 - Verified OK
Downloading 12 bytes @ address 0x0800131C - Verified OK
Writing register 'pc' = 0x080006C0
Read 4 bytes @ address 0x080006C0 (Data = 0xD034F8DF)
Read 2 bytes @ address 0x080006C0 (Data = 0xF8DF)
Read 2 bytes @ address 0x080006C2 (Data = 0xD034)
Read 4 bytes @ address 0xE000ED14 (Data = 0x00000200)
Reading register 'msp' = 0x20020000
Reading register 'psp' = 0x00000000
Downloading 4 bytes @ address 0xE000ED14 - Verified OK
Reading common registers: Read register 'r0' (4 bytes) from hardware: 0x00000000
Read register 'r1' (4 bytes) from hardware: 0x00000000
Read register 'r2' (4 bytes) from hardware: 0x00000000
Read register 'r3' (4 bytes) from hardware: 0x00000000
Read register 'r4' (4 bytes) from hardware: 0x00000000
Read register 'r5' (4 bytes) from hardware: 0x00000000
Read register 'r6' (4 bytes) from hardware: 0x00000000
Read register 'r7' (4 bytes) from hardware: 0x00000000
Read register 'r8' (4 bytes) from hardware: 0x00000000
Read register 'r9' (4 bytes) from hardware: 0x00000000
Read register 'r10' (4 bytes) from hardware: 0x00000000
Read register 'r11' (4 bytes) from hardware: 0x00000000
Read register 'r12' (4 bytes) from hardware: 0x00000000
Read register 'sp' (4 bytes) from hardware: 0x00000220
Read register 'lr' (4 bytes) from hardware: 0xFFFFFFFF
Read register 'pc' (4 bytes) from hardware: 0xC0060008
Read register 'xpsr' (4 bytes) from hardware: 0x00000001
Read 4 bytes @ address 0x080006C0 (Data = 0xD034F8DF)
Read 2 bytes @ address 0x080006C0 (Data = 0xF8DF)
Read 2 bytes @ address 0x080006C2 (Data = 0xD034)
Reading register 'msp' = 0x20020000
Reading register 'psp' = 0x00000000
Read 4 bytes @ address 0xE000EDFC (Data = 0x01000000)
Downloading 4 bytes @ address 0xE000EDFC - Verified OK
Reading common registers: Read register 'r0' (4 bytes) from hardware: 0x00000000
Read register 'r1' (4 bytes) from hardware: 0x00000000
Read register 'r2' (4 bytes) from hardware: 0x00000000
Read register 'r3' (4 bytes) from hardware: 0x00000000
Read register 'r4' (4 bytes) from hardware: 0x00000000
Read register 'r5' (4 bytes) from hardware: 0x00000000
Read register 'r6' (4 bytes) from hardware: 0x00000000
Read register 'r7' (4 bytes) from hardware: 0x00000000
Read register 'r8' (4 bytes) from hardware: 0x00000000
Read register 'r9' (4 bytes) from hardware: 0x00000000
Read register 'r10' (4 bytes) from hardware: 0x00000000
Read register 'r11' (4 bytes) from hardware: 0x00000000
Read register 'r12' (4 bytes) from hardware: 0x00000000
Read register 'sp' (4 bytes) from hardware: 0x00000220
Read register 'lr' (4 bytes) from hardware: 0xFFFFFFFF
Read register 'pc' (4 bytes) from hardware: 0xC0060008
Read register 'xpsr' (4 bytes) from hardware: 0x00000001
Read 4 bytes @ address 0x080006C0 (Data = 0xD034F8DF)
Read 2 bytes @ address 0x080006C0 (Data = 0xF8DF)
Read 2 bytes @ address 0x080006C2 (Data = 0xD034)
Reading register 'msp' = 0x20020000
Reading register 'psp' = 0x00000000
Reading 64 bytes @ address 0x08000500
Read 2 bytes @ address 0x0800050C (Data = 0xF000)
Setting breakpoint @ address 0x0800050C, Kind = 2, Type = THUMB, BPHandle = 0x0001
Starting target CPU...
...Breakpoint (set by 'GDB') reached @ address 0x0800050C
Reading common registers: Read register 'r0' (4 bytes) from hardware: 0x00000020
Read register 'r1' (4 bytes) from hardware: 0x0C000020
Read register 'r2' (4 bytes) from hardware: 0x2C000020
Read register 'r3' (4 bytes) from hardware: 0xBD010008
Read register 'r4' (4 bytes) from hardware: 0x2C000020
Read register 'r5' (4 bytes) from hardware: 0x00000000
Read register 'r6' (4 bytes) from hardware: 0x00000000
Read register 'r7' (4 bytes) from hardware: 0xF8FF0120
Read register 'r8' (4 bytes) from hardware: 0x00000000
Read register 'r9' (4 bytes) from hardware: 0x00000000
Read register 'r10' (4 bytes) from hardware: 0x00000000
Read register 'r11' (4 bytes) from hardware: 0x00000000
Read register 'r12' (4 bytes) from hardware: 0x00000000
Read register 'sp' (4 bytes) from hardware: 0xF8FF0120
Read register 'lr' (4 bytes) from hardware: 0xF7060008
Read register 'pc' (4 bytes) from hardware: 0x0C050008
Read register 'xpsr' (4 bytes) from hardware: 0x00000061
Removing breakpoint @ address 0x0800050C, Size = 2
Read 4 bytes @ address 0x0800050C (Data = 0xF902F000)

 

 

 

4. 디버그 콘솔 연결

다음은 디버그에서 가장 많이 사용하는 printf와 같은 문자열을 출력해보겠습니다. printf 문자열을 출력하는 방법은 여러가지가 있지만 J-Link에서는 JLinkRTTViewer를 이용해서 문자열을 출력할 수 있습니다.

 

우선 J-Link에서 지원하는 SEGGER_RTT 소스코드들을 추가해야 합니다. 본인은 헤더파일은 Inc 안에 Utils라는 폴더를 별로도 만들어서 헤더파일을 추가하고 소스코드는  Src 안에 Utils라는 폴더를 만들어서 소스코드를 추가해주었습니다.

 

Inc\Utils

  • SEGGER_RTT_Conf.h
  • SEGGER_RTT.h

Src\Utils

  • SEGGER_RTT.c
  • SEGGER_RTT_printf.c

 

 

 

 

그리고 헤더 파일의 Utils 폴더는 경로를 지정해줍니다. 경로 지정은 메뉴중 Project -> Properties에 들어가면 C/C++ Build -> Setting 에서 설정할 수 있습니다. Tool Settings에서 MCU GCC Compiler의 Include paths 부분에 아래와 같이 폴더 경로를 추가하면 됩니다.

 

 

 

그리고 main.c의 main 엔트리 부분 안쪽 User Code 영역에 아래와 같이 예제코드를 삽입해줍니다.

SEGGER_RTT_printf(0, "Hello World!\n");

 

 

 

 

사용하는 환경이 우분투 환경이면, Ctrl + Alt + T를 눌러 터미널 창을 새로 엽니다. 터미널에서 아래 명령어를 실행합니다. 물론 JLinkRTTViewer가 미리 설치가 되어 있어야 하는데 STM32CubeIDE를 설치하면 함께 설치가 되어 있습니다.

$ JLinkRTTViewer

 

 

 

툴을 실행하면 우선 설정화면이 나옵니다. 설정은 아래와 같이 설정하면 됩니다.

  • Connection to J-link: USB
  • Target Device: STM32F411CE

 

 

 

 

그리고 OK를 누르면 J-Link RTT가 디바이스와 연결됨을 확인할 수 있습니다.

 

 

 

 

STM32CubeIDE로 가서 빌드후 코드를 다운로드하면 아래와 같이 RTT 창에서 디버그 메시지가 출력되는 것을 확인할 수 있습니다.

 

 

이제 디버깅을 위한 모든 환경이 설정되었으니 디버깅을 세계로 들어가면 됩니다. Hello World!!!

728x90

댓글