2017년 7월 30일 일요일

STM32F407 + IAR + FreeRTOS


[IAR 다운로드]
 : IAR_EWAM_7103_ST.zip



[IAR 설치]
(1) 다운받은 압축파일을 해제하고 exe 파일을 실행한다.


(2) 설치 메뉴에서 두번째 항목을 선택하여 설치를 진행한다.


(3) 크랙 폴더의 모든파일을 복사하여


(4) C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.0\arm\bin 경로에 붙여 넣는다.




[ST 표준 라이브러리 가져오기]
 : 작성일자(2017/07/31) 기준으로 정리한 내용임.
 : 직접 경로 링크(STM32F4 DSP and standard peripherals library)
 : 개인 사이트 파일 링크

(1) ST사이트(www.st.com)에 접속하여 좌측 상단의 [Products]를 선택하여 펼쳐지는 메뉴에서 [Microcontrollers]를 선택한다.


(2) 우측의 메뉴에서 [Tools & Software]를 선택한다.


(3) 확장된 메뉴에서 [Embedded Software]의 [Embedded Software]의 [STM32 Standard Peripheral Libraries(8)]을 선택한다.


(4) STM32F4에서 사용할 것이므로 [STSW-STM32065] 항목을 선택한다.


(5) [GET SOFTWARE]를 선택하고 [Get Software]를 선택하여 다운로드를 진행한다.
로그인 등의 귀찮은 절차가 있으므로 [여기]에서 직접 받아도 무관하다.




[기본 폴더 구조 설정]
표준 라이브러리와 FreeRTOS의 소스를 프로젝트 파일들과는 별도로 관리하기 위하여 편한 방법으로 폴더 구조를 설정한다.



나는 기본적으로

  • [WorkStm32F407]이라는 폴더를 기본으로 하여
    • [_FreeRTOSv9.0.0]라는 이름으로 FreeRTOS 소스 코드 폴더를 위치하고,
    • [_STM32F4xx_DSP_StdPeriph_Lib_V1.8.0] 이름으로 표준 라이브러리 폴더를 위치시켰다.
    • [MultiPlayController] 이름으로 새 프로젝트를 만들것이므로 폴더를 하나 만들었다.


_FreeRTOSv9.0.0 폴더의 내용은 다운받은 FreeRTOS파일인 FreeRTOSv9.0.0.exe를 압축해제 한 폴더이고, _STM32F4xx_DSP_StdPeriph_Lib_V1.8.0 폴더의 내용은 ST 표준라이브러리 압축 파일 en.stm32f4_dsp_stdperiph_lib.zip을 압축해제 한 폴더이다.



[프로젝트 만들기]
(1)먼저 [IAR Embedded Workbench] 아이콘으로 IAR IDE를 실행한다.


(2) IDE의 상단 메뉴에서 [Project]의 [Create New Project...]를 선택한다.


(3) STM32F407은 ARM 계열이므로 Tool chain은 [ARM]을 선택하고, [Empty project]를 선택하여 빈 프로젝트로 만든다.


(4) 위에서 [OK]를 누르면 아래 이미지와 같이 프로젝트 관리 파일을 저장하기 위한 폴더 지정과 파일명을 설정하도록 창이 뜬다. 설정해놓은 폴더 구조에서 프로젝트를 관리하기 위한 (나의경우) D:\WorkIAR\WorkStm32F407\MultiPlayController 폴더에 경로를 설정하고 프로젝트 폴더명과 같은 이름으로 프로젝트를 설정한다.


(5) 기본적으로 프로젝트가 생성되었고 Workspace에 무언가가 하나 생겨있다.


(6) 저장하기를 하면 프로젝트를 관리하는 파일을 저장하기 위한 창이 뜬다. 여기서도 프로젝트 폴더 아래 폴더명과 같은 이름으로 저장을 하자.

프로젝트 폴더로 가보면 다음과 같은 파일들이 저장되어 있다.




[소스 구조 설정]
(1) 개발환경을 설정하기 위한 첫번째는 내가 작업할 소스들을 저장할 폴더를 만든다.
  나의 경우 기본 프로젝트 폴더에 "user"라는 이름의 폴더를 만들고 그 안에 "inc"와 "src"를 만들었다.


(2) 소스 구조를 잡기 위해 workspace에서 구조를 구성한다. 기본적인 트리 구조로 만든다.
  ROOT인 프로젝트명을 오른쪽 클릭하여 [Add] -> [Add Group..]를 선택한다.


(3) 원하는 그룹명을 넣는다.


(4) 그룹명들을 넣어서 아래와 같이 코드 구조를 잡았다.
기본 라이브러리를 사용하기 위해 [STM32F4xx_DSP_StdPeriph_Lib_V1.8.0] 그룹과 사용자 소스 관리를 위해 [User] 그룹으로 구조를 구성한다.


(5) 각각의 그룹에 파일을 추가한다. 그룹을 오른쪽 클릭하여 [Add] -> [Add Files..]를 선택한다.


(6) 먼저 라이브러리 중에서 CMSIS 관련 라이브러리를 추가한다. IAR과 관련된 파일들만 추가를 한다.


(7) 기본 라이브러리 폴더의 "Libraries \ CMSIS \ Device \ ST \ STM32Fxx \ Source \ Templates \ iar "폴더에서 "startup_stm32f40_41xxx.s" 파일을 추가하였다.


(8) 다음 그림의 폴더 경로에서 "stm32f4xx.h"와 "system_stm32f4xx.h" 파일을 추가한다.


(9) 다음 그림의 폴더 경로에서 "system_stm32f4xx.c" 파일을 추가한다.


(10) [CMSIS] 그룹에는 다음 그림과 같이 네 개의 파일을 추가하였다.


(11) [STM32F4xx_StdPeriph_Driver] 그룹의 [inc] 그룹에는 다음 그림의 경로의 모든 파일을 추가한다.


(12) [STM32F4xx_StdPeriph_Driver] 그룹의 [src] 그룹에는 다음 그림의 경로의 모든 파일을 추가한다.


(13) 기본적인 라이브러리 구성은 완료하였고, 그림에서 보이는 아이콘을 클릭하여 새로운 파일을 하나 만들자.


(14) 저장하기나 Ctrl+S 로 파일을 저장하자. 저장 경로는 내가 소스를 저장하기 위한 "user" 폴더의 "src" 폴더 안에 "main.cpp"라는 파일명으로 저장을 한다.


(15) 저장된 main.cpp 파일을 소스 에디터에서 수정중인 상태에서 workspace의 [User]그룹의 [src] 그룹을 오른쪽 클릭하여 [Add] 를 선택하면 [Add "main.cpp"] 가 있으므로 선택하여 그룹에 파일을 추가한다.




[옵션 설정]
(1) 프로젝트의 옵션을 설정하기 위하여 workspace의 프로젝트 명을 오른쪽 클릭하여 [Options...] 을 선택한다.


(2) [General Options] 의 [Target]은 [Device]를 선택하고 우리가 사용하고자 하는 Device를 선택하여 준다. 나의 경우 STM32F407IG 칩을 사용하므로 그것을 선택해 주었다.


(3) [Library Configuration] 에서는 [Use CMSIS]를 선택해주어 CMSIS를 사용하도록 한다.


(4) [C/C++ Compiler]의 [Language 1]에서 언어는 [Auto]를 선택하여 c와 cpp를 다 사용하도록 한다.


(5) [List] 탭에서 컴파일 후 출력되는 리스트를 다음 그림과 같이 Output list file를 체크해준다.


(6) [Preprocessor]는 전처리를 위한 설정과 컴파일 및 링크 시 사용할 디렉토리를 설정한다.


(7) 위의 그림의 박스 안에서 오른쪽 [...] 버튼을 눌러 경로 편집을 하는 창을 띄운다.


(8) 위의 그림에서 박스 부분을 클릭하면 다음과 같이 경로를 선택하는 창이 뜬다.


(9) 추가해야 할 경로를 선택하여 추가하면 다음과 같이 추가된다.


(10) 추가된 경로의 오른쪽에 아래쪽 삼각형 아이콘의 버튼을 누르면 다음과 같이 절대경로와 상대경로를 선택하는 팝업이뜬다.


(11) 필요에 따라 상대경로로 설정해 주는 것이 더 좋다.


(12) [Preprocessor] 탭에서 처리 되어야 하는 내용은 다음과 같다.
경로 -

  • $PROJ_DIR$\..\_STM32F4xx_DSP_StdPeriph_Lib_V1.8.0\Libraries\CMSIS\Device\ST\STM32F4xx\Include
  • $PROJ_DIR$\..\_STM32F4xx_DSP_StdPeriph_Lib_V1.8.0\Libraries\CMSIS\Device\ST\STM32F4xx\Source\Templates
  • $PROJ_DIR$\..\_STM32F4xx_DSP_StdPeriph_Lib_V1.8.0\Libraries\CMSIS\Device\ST\STM32F4xx\Source\Templates\iar
  • $PROJ_DIR$\..\_STM32F4xx_DSP_StdPeriph_Lib_V1.8.0\Libraries\STM32F4xx_StdPeriph_Driver\inc
  • $PROJ_DIR$\..\_STM32F4xx_DSP_StdPeriph_Lib_V1.8.0\Libraries\STM32F4xx_StdPeriph_Driver\src
  • $PROJ_DIR$\user\inc
  • $PROJ_DIR$\user\src

Defined symbols -

  • USE_STDPERIPH_DRIVER
  • STM32F40_41xxx



(13) [Output Converter]의 생성 파일은 [binary] 로 선택한다.


(14) [Linker]의 [List]는 모두 체크 해준다.


(15) 기본 라이브러리를 사용하기 위해서는 기본 라이브러리의 프로젝트 템플릿에서 필요한 파일을 user에 복사해서 사용한다. 다음 그림의 경로의 세 파일을 복사한다.


(16) 위에서 복사한 파일을 src와 inc로 구분하여 붙여넣어준다.



(17) 각각 그룹에 파일을 추가하고 main.cpp 파일의 소스 코드를 다음 그림과 같이 작성한다.


(18) [F7]을 눌러 컴파일을 하면 에러가 날 것이다. 필요하지 않은 파일이 포함되어 있으므로 비활성화 해줘야 하겠다. 다음 그림과 같이 "stm32f4xx_fmc.h"와 C 파일을 비활성화 한다.


(19) 파일을 오른쪽 클릭하여 [Options...]을 선택하면 다음과 같은 창이 뜨고, [Exclude from build]를 선택하여 비활성화 한다.


(20) 다시 컴파일을 하면 다음과 같은 에러가 뜰 것이다. "main.h"가 없으므로 주석처리 하자.


(21) 또다시 [F7]로 컴파일을 하면 다음의 에러가 뜰 것이며, TimingDelay_Decrement() 함수가 없으므로 주석처리 한다.


(22) 이제 [F7]로 컴파일을 하면 에러와 경고가 없이 정상 컴파일이 된다.


(23) (추가적으로) 현재 보드에서 사용하고 있는 발진기가 8MHz 라면, 다음과 같이 코드를 수정해 주어야 한다. 기본적으로 25MHz가 사용된다는 가정하에 작성된 코드이므로 수정이 필요하다.


(24) 수정 후 저장이 되지 않는 경우 파일의 속성중 읽기 전용 속성을 해제한다.


(25) "stm32f4xx.h" 파일의 내용을 8MHz에 맞게 값을 수정하고 저장한다.


(26) "system_stm32f4xx.c" 파일의 PLL_M 값도 25 -> 8 로 수정해준다.


(27) 수정된 내용을 저장하고 컴파일 해서 문제가 없다면 정상적으로 기본 환경은 준비된 것이다.




[LED On/Off TEST]
(1) LED를 제어하는 것은 일반적으로 GPIO를 이용하여 제어를 한다. 현재 우리 보드에는 F포트를 사용하므로 다음과 같이 소스코드를 작성하여 LED를 켜거나 끄거나 하도록 한다.


(2) J-Link를 사용하여 다운로드를 하는 경우에는 프로젝트 옵션에서 [Debugger]에 [Driver]를 [J-Link/J-Trace]로 선택하여 준다.


(3) 다음 그림과 같이 IDE의 오른쪽 상단 툴바의 [Download and Debug]를 클릭하여 실행하고 디버그를 진행할 수 있다.


(4) 위의 실행에 의해 보드의 결과는 다음 그림과 같다. 두 개씩 켜지고 꺼지고를 반복한다.




[FreeRTOS 소스 가져오기]

(1) FreeRTOS 사이트(www.freertos.org)에 접속한다.


(2) 코드를 다운로드 한다. (직접링크)


다운받은 FreeRTOS 파일은 임의의 폴더에 압축을 해제한다.



[FreeRTOS 포팅]
(1) 프로젝트 폴더 아래의 user 폴더 아래에 "config" 폴더를 만든다.


(2) 임의의 폴더에 압축해제된 FreeRTOS의 "Demo" 폴더의 "CORTEX_M4F_STM32F407ZG-SK" 폴더에 있는 "FreeRTOSConfig.h" 파일을 복사한다.


(3) 복사한 "FreeRTOSConfig.h"파일을 위에서 생성한 "user \ config" 폴더에 붙여 넣는다.


(4) 프로젝트 상위의 Work 폴더에 FreeRTOS 소스를 보관하기 위해 "_FreeRTOSv9.0.0"으로 폴더를 만들었다. 임의의 명칭으로 만들어도 무관하다.


(5) 압축해제한 FreeRTOS 폴더 하위의 "Source" 폴더를 복사한다.


(6) 내가 만든 FreeRTOS 보관 폴더에 "Source"를 붙여넣고, 하위의 "portable" 폴더에는 "IAR"과 "MemMang" 폴더 외에는 삭제한다.


(7) "portable"폴더 하위의 "IAR" 폴더에서 "ARM_CM4F" 폴더 외에는 삭제한다.


(8) workspace에서 Root에서 [FreeRTOSv9.0.0]의 그룹을 만들고 다음의 그림과 같이 그룹 및 파일을 구성한다.


(9) [FreeRTOSv9.0.0]의 [src] 그룹에는 다음 그림과 같이 Source의 파일 6개를 추가한다.


(10) [FreeRTOSv9.0.0]의 [inc] 그룹에는 다음 그림과 같이 "Source \ include"의 모든 파일을 추가한다.


(11) [FreeRTOSv9.0.0]의 [portable]의 [src]에는 다음 그림과 같이 "port.c"와 "portasm.s" 파일을 추가한다. 그리고 "heap_2.c" 파일도 추가한다.



(12) [FreeRTOSv9.0.0]의 [portable]의 [inc]에는 "portmacro.h" 파일을 추가한다.


(13) 프로젝트 옵션에서 라이브러리를 다음 그림과 같이 "Full"로 설정한다.


(14) [C/C++ Compiler]의 [Preprocessor]에는

다음 그림과 같이 세 줄을 추가한다.


(15) [Assembler]의 [Preprocessor]에는 위에서의 내용과 같이 한다. (복사해서 붙여넣기 가능)


(16) 다음 그림과 같이 "stm32f4xx_it.c" 파일의 내용을 일부 수정하여야 한다.


void PendSV_Handler(void)
__weak void PendSV_Handler(void)
void SVC_Handler(void)
__weak void SVC_Handler(void)
void SysTick_Handler(void)
__weak void SysTick_Handler(void)
위의 함수들은 앞에 __weak를 붙여준다.

(17) 새로운 파일을 만들고 "user \ src" 폴더에 OS_Call.c 로 저장한다. workspace에 추가를 해주고 다음과 같이 소스코드를 작성한다.
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "semphr.h"

void vApplicationTickHook(void)
{
}

void vApplicationMallocFailedHook(void)
{
  taskDISABLE_INTERRUPTS();
  for(;;);
}

void vApplicationIdleHook(void)
{
}

void vApplicationStackOverflowHook(TaskHandle_t pxTask, char* pcTaskName)
{
  (void)pcTaskName;
  (void)pxTask;
  
  taskDISABLE_INTERRUPTS();
  for(;;);
}


컴파일 후 에러가 없으면 정상이다. (포팅 완료)



[FreeRTOS를 이용한 LED 깜빡이기]
main.cpp 파일을 다음과 같이 소스코드를 작성하여 Test를 진행하면 각각의 LED가 다른 Task에서 지연시간을 가지며 동작하는 것을 확인할 수 있다.