STM32F407_FreeRTOS Project 생성 및 디버깅
STM32F407_FreeRTOS Project 생성 및 디버깅
이번 포스팅은 STM32F407 Discovery kit를 이용한 FreeRTOS Project 생성과 디버깅 Setup에 대한 내용을 정리하였습니다.
Project 생성은 Code Generator인 STM32CubeMX를 활용하였습니다.
Project 생성 후 총 3개의 LED를 각 각의 Task로 제어하는 간단한 동작을 확인하였습니다.
Uart TTL to USB 를 이용한 Log 입출력을 이용한 디버깅과 Keil의 Logic Analyzer 를 이용한 디버깅이 동작됨을 확인하였습니다.
앞으로 FreeRTOS를 공부하면서 쭈욱 활용해야하기 때문에 따로 정리하고자합니다.
0. STM32F407_관련 라이브러리
- 아래의 링크 참고. STM32F4 계열 MCU로 개발 시 참고하면 좋은 라이브러리 모음들.
1. STM32F407_FreeRTOS Project 생성
따로 설치법 등에 대한 내용은 생략하였습니다.
1.1 STM32CubeMX
- 처음 ‘STM32CubeMX’를 실행하시면 아래와 같은 화면이 나옵니다.
- 아래의 사진과 같이 ‘File’ 탭의 ‘New Project…‘를 클릭합니다.
- 좌측 상단의 Board Selector를 누르시고 바로 아래에 있는 ‘Commercial Part Number’에 Discovery kit의 모델명을 입력합니다.
- 그러면 Boards List에 Discovery kit의 정보가 나타납니다.
- Boards List에 나타난 Discovery kit를 더블클릭하시면 위와 같은 창이 나오는데
- 모든 peripherals를 default Mode로 초기화의 여부를 뭍는 창이 나옵니다. Yes를 눌러줍니다.
- Yes를 누른 후 기다리시면 아래와 같은 창이 뜨면서 여러 요소들에 대해 Configuration을 시작할 수 있습니다.
- FreeRTOS를 Enable하기 위해 좌측 하단의 ‘Middleware’의 ‘FREERTOS’를 누르고 나타나는 화면의 중단 상단의 Interface를 ‘CMSIS_V1’으로 설정하시면 아래와 같이 FreeRTOS 사용을 위한 Configuration을 할 수 있습니다. 각 각의 요소들에 대한 설명은 추후 공부하면서 자세하게 다루어볼 것입니다.
- FreeRTOS의 기본 동작을 확인하기 위해 아래와 같이 3개의 Task를 생성하였습니다. Task에 대한 각 각의 요소들은 모두 기본적인 값들로 설정하였습니다.
- 추가적으로 FreeRTOS를 사용하고자한다면 Tick(Timebase)를 ‘systick’ 이 아닌 ‘TIM1’ 과 같은 Timer로 설정해야합니다.
- FreeRTOS의 스케쥴러는 ISR의 호출로 Context Switching을 해줘야하는데 여러 ISR 중 Tick(Timebase) ISR도 포함됩니다.
- 결론적으로, Tick(Timebase)를 이용해 주기적으로 ISR를 호출하고 Context Switching을 하여 Multitasking 기능을 수행할 수 있게 됩니다.
- systick를 사용하지 못하는 이유는 ARM-Cortex Achitecture에서의 대부분의 RTOS는 systick의 우선순위를 낮게 강제로 설정되기 때문입니다.(STM32CubeMX user manual의 ‘Setting HAL timebase source’ 항목 참고)
- 자세한 내용은 추후 FreeRTOS를 공부하면서 정리해보겠습니다.
- ‘Clock Configuration’ 의 내용입니다. 전체적인 Clock들에 대한 Setting Value를 보실 수 있습니다.
- XTAL 8Mhz를 입력 받아 PLL Source Mux를 통해 STM32F407에서 지원하는 최대 클럭인 168Mhz로 만들어지는 모습입니다.
- 항상 Timer,SPI,UART,ADC 등 과 같은 기능을 사용 시, 각 기능이 어떠한 클럭을 이용하고 그 클럭이 무슨 값인지 확인해야합니다.
- 마지막으로 ‘Project Manager’에서 저는 Keil MDK-ARM V5 IDE를 쓰기 때문에 ‘Generator’항목에 내용에 맞게 변경하였습니다.
- 우측 상단의 ‘GENERATE CODE’를 누르시면 Project가 생성 됩니다.
- 모두 완료 후 해당 폴더에 가면 Project가 생성된 것을 확인할 수 있습니다.
1.2 IDE(Keil)
- 아래의 사진은 Project가 생성되고 Keil로 실행한 모습입니다.
- NonRTOS Project에서 RTOS 구동을 위한 소스파일들이 추가된 구조입니다.
- 생성된 Project가 이상이 없는지 확인하기 위해 ‘Project’-> ‘Rebuild all target files’를 눌러 컴파일을 진행합니다.
- 아래와 같이 나오면서 정상적으로 컴파일을 성공하였습니다.
2. STM32F407_FreeRTOS Project 디버깅 Setup
본격적으로 FreeRTOS를 공부하면서 활용하는 디버깅에 대한 Setup을 진행합니다. STM32CubeMX를 추후 사용하지 않는 다면 상관없지만
코드를 수정하면서 STM32CubeMX를 활용하신다면, 아래의 규칙은 무조건 지켜주셔야합니다.
- 항상 내가 작성한 코드는 아래의 ‘USER CODE BEGIN’과 USER CODE END’ 사이에 넣기
/* USER CODE BEGIN ... */ (요기) /* USER CODE END ... */
2.1 Uart TTL to USB, printf()를 이용한 Log 입출력
- 시중에 아래의 사진과 비슷한 Uart TTL to USB tool을 구매할 수 있습니다.
- 총 4개의 선이 있는데 각 사양은 아래와 같습니다. ```
- 빨 : 5V
- 초 : (tool기준)TXD
- 흰 : (tool기준)RXD
- 검 : GND ```
- 연결 시, 주의사항
- 절대로 ‘빨’은 보드에 연결하시면 안됩니다. 보드의 TTL 레벨이 3.3V이기 때문입니다.
- ‘초’는 보드의 RXD핀, ‘흰’은 보드의 TXD핀에 연결해야합니다. 기본적으로 데이터의 흐름은 TXD–>RXD 입니다.
- 아래와 같이 소스코드를 추가하였습니다.
- printf()를 사용하기 위해 ‘main.h’에
헤더파일을 추가하였고 - ‘main.c’에 printf()안에서 사용되는 fputc() 선언 및 내용과 보드에 전원 인가 후, 경과 시간을 계산하기 위한 함수도 추가하였습니다.
- 경과 시간을 계산하기 위해 Tick ISR Handler에서 1ms단위로 계산하도록 작성하였습니다.
- main()에서 RTOS init 동작전에 printf()로 PCLK1과 PCLK2의 값을 출력하도록 작성하였고
- 보드의 User Button을 누를 시(Level LOW->HIGH, Rising Edge), 계산한 경과 시간을 출력하도록 작성하였습니다.
- 소스 작성 후, 컴파일 및 보드 다운로드 후 시리얼 터미널 창에서 동작됨을 확인하였습니다.
2.2 Keil의 logic analyzer를 이용한 디버깅
- ‘main.c’에서 아래의 사진과 같이 생성한 3개의 Task에 사용할 변수들을 선언해줬습니다.
- 아래의 변수들은 모두 logic analyzer에 출력할 변수들입니다.
- ‘main.c에서 각 각의 Task에 아래와 같이 소스코드를 작성하였습니다.
- 각 Task의 일정 시간 경과 후 LED Toggle 동작.
- 일정시간 경과 값 및 LED동작 값.
- 소스 작성 후, 컴파일 및 보드 다운로드 후 오실로스코프를 이용하여 LED의 동작을 확인하였습니다.
- 오실로스코프의 채널이 2개인 관계로, Task1(500ms)과 Task2(1000ms)만 측정하였습니다.
측정 값이 약간의 오차가 있는 것 같습니다. 스코프 측정 특성인지 보드 자체 오차인지는 추후 Scheduling Latency Test로 고찰해볼 계획입니다.
- 오실로스코프에서 확인한 바와 같이 logic analyzer에서도 측정되는지 확인해보겠습니다.
- 먼저, ST-LINK의 SWO를 사용 시, 아래의 파일을 작성하여 프로젝트 폴더 내에 ‘STM32_SWO.ini’ 파일로 저장합니다.
FUNC void DebugSetup (void) {
// <h> Debug MCU Configuration
// <o1.0> DBG_SLEEP <i> Debug Sleep Mode
// <o1.1> DBG_STOP <i> Debug Stop Mode
// <o1.2> DBG_STANDBY <i> Debug Standby Mode
// <o1.5> TRACE_IOEN <i> Trace I/O Enable
// <o1.6..7> TRACE_MODE <i> Trace Mode
// <0=> Asynchronous
// <1=> Synchronous: TRACEDATA Size 1
// <2=> Synchronous: TRACEDATA Size 2
// <3=> Synchronous: TRACEDATA Size 4
// <o1.8> DBG_IWDG_STOP <i> Independant Watchdog Stopped when Core is halted
// <o1.9> DBG_WWDG_STOP <i> Window Watchdog Stopped when Core is halted
// <o1.10> DBG_TIM1_STOP <i> Timer 1 Stopped when Core is halted
// <o1.11> DBG_TIM2_STOP <i> Timer 2 Stopped when Core is halted
// <o1.12> DBG_TIM3_STOP <i> Timer 3 Stopped when Core is halted
// <o1.13> DBG_TIM4_STOP <i> Timer 4 Stopped when Core is halted
// <o1.14> DBG_CAN_STOP <i> CAN Stopped when Core is halted
// </h>
_WDWORD(0xE0042004, 0x00004027); // DBGMCU_CR
}
DebugSetup(); // Debugger Setup
FUNC void OnResetExec (void) { // executes upon software RESET; Use the function name as is
DebugSetup(); // call the initialization function
}
- Keil 에서 ‘Flash’-> ‘Configure Flash Tools…‘을 클릭하면 아래와 같은 창이 뜹니다.
- 먼저 ‘output’탭에서 아래와 같이 되어 설정합니다.
- ‘Debug’탭에서 우측 상단의 ‘Settings’를 클릭하면 아래와 같은 창이 뜹니다.
- 아래의 사진과 똑같이 설정합니다.(SWV세팅)
- 좌측 상단의 ‘Trace’를 누르고 아래의 사진과 똑같이 설정합니다.
가끔가다가 Keil이 강제종료가 할 때가 있습니다. 그러면 꼭 위의 'Trace'의 설정이 맞게 되어있는지 확인해주세요.
-
설정 후 꼭 ‘확인’을 눌러줍니다.
-
다시 돌아와서 우측 중간에 ‘Edit…‘을 눌러 처음에 작성했던 ‘STM32_SWO.ini’을 추가해줍니다.
-
꼭 ‘OK’를 눌러 종료합니다. 여기까지가 logic analyzer 처음 사용 시, Setting 방법이였습니다.
-
Keil 에서 ‘Debug’-> ‘Start/Stop Debug Session’을 클릭하여 아래의 사진과 같이 Debug mode로 진입합니다.
- 아래의 사진과 같이 logic analyzer 버튼을 눌러줍니다.
- 아래의 사진과 같이 logic analyzer로 출력하고 싶은 변수를 추가해줍니다.
- logic analyzer창에서 좌측 상단의 Setup을 누릅니다.
- 각 변수에 대해 내가 보고싶은 Display type 및 Range, Masking 및 Shift하여 보고 싶은 지 등에 대한 내용을 설정합니다.
- 이제 F5를 눌러 시작하면 아래와 같이 측정이 되는 것을 확인할 수 있습니다.
-
가끔가다 제대로 동작을 안하는 경우가 있는데 이는 하단의 Trace overflow 현상 때문입니다. 위의 SWV세팅을 다시 맞게 하면 동작되는 것을 확인하였습니다.
-
확인이 끝났으면, 무조건 추가한 변수를 삭제 후 종료합니다.
3. 정리
FreeRTOS를 공부하기 위한 환경은 시작해도 될 정도는 되었습니다. 추후 공부하면서 사용했던 디버깅 방법 및 수정내용은 지속적으로 Update할 예정입니다.
댓글남기기