1. STM32 Cube IDE 설치하기

2. Workspace 생성 및 설정하기

2.1. Workspace 생성

Untitled

  • Workspace 설정 후 Launch 버튼을 누른다. 이때 경로는 무조건 영어로 설정한다.

Untitled

Untitled

  • Impormation Center를 닫으면 빈 Workspcace가 나타난다.
  • Workspace 안에선 여러 개의 프로젝트를 관리할 수 있다.

2.2. Text file Encoding 설정

Untitled

Untitled

  • Window → Preferences → General → Workspace 클릭
  • 오픈 소스를 활용할 때 한글이 존재하면 문제가 발생할 수 있으므로 Text file encoding을 항상 UTF-8로 설정한다.

2.3. Coding Style 설정

Untitled

  • C/C++ → Coding Style → Formatter → New 버튼 클릭

Untitled

  • 이름은 아무거나 적고, 베이스로 할 것을 GNU로 설정한다.

Untitled

Untitled

  • Indentation → General settings에서 Tab policy는 Spaces only, Indentation size는 2로 변경한다.
  • Braces → Brace positions에서 마지막 설정을 제외하고 모두 Next line으로 변경한다.

2.4. Launch Operation 설정

Untitled

  • Run/Debug → Launching → Launch Operation에서 Always launch the previously launched application으로 변경한다.
  • 이후 Apply and Close 클릭

3. Project 생성 및 설정하기

3.1. Project 생성

Untitled

  • File → New → STM32 Project 클릭

Untitled

  • STM32F401RET6 선택 후 Next 클릭

Untitled

  • Project Name에 MCU 이름을 바탕으로 설정하고, Location에 Project Name을 뒤에 적는다. 자동으로 해당 폴더가 생성된다.
  • Targeted Project Type을 Empty로 설정한다.

Untitled

  • 프로젝트를 생성하면 위와 같은 구조로 파일을 자동으로 생성한다.
  • main 함수(main.c), 스타터 코드(startup_stm32f401retx.s), 시스템 콜백 함수(syscalls.c, sysmem.c), 링커 스크립트 파일(STM32F401RETX_FLASH.ld, STM32F401RETX_RAM.ld)로 구성된다.

3.2. 파일 구성 변경하기

Untitled

  • 우선 위와 같이 파일 구조를 바꾸자

Untitled

Untitled

  • 가장 위에 존재하는 stm32f401_fw 프로젝트에 src 폴더를 생성한다.
- stm32f401_fw
	- src
		- ap
		- bsp
			- ldscript
				- STM32F401RETX_FLASH.ld
				- STM32F401RETX_RAM.ld
			- startup
				- startup_stm32f401retx.s
			- syscalls.c
			- sysmem.c
		- common
		- hw
		- lib

Untitled

  • main.c 파일을 삭제하고 위와 같이 폴더 및 파일을 구성한다. 폴더만 생성하고 파일은 새롭게 생성하지 않았다.
- stm32f401_fw
	- src
		- ap
			- ap.c
			- ap.h
		- bsp
			- ldscript
				- STM32F401RETX_FLASH.ld
				- STM32F401RETX_RAM.ld
			- startup
				- startup_stm32f401retx.s
			- bsp.c
			- bsp.h
			- syscalls.c
			- sysmem.c
		- common
			- def.h
		- hw
			- hw_def.h
			- hw.c
			- hw.h
		- lib
		- main.c
		- main.h

Untitled

  • 각 폴더에 맞게 파일을 생성한다.
  • 파일의 기본적인 구성은 끝났다.

4. 기본적인 코드 작성하기

  • ap.h

      #ifndef SRC_AP_AP_H_
      #define SRC_AP_AP_H_
        
      #include "hw.h"
        
      void apInit(void);
      void apMain(void);
        
      #endif /* SRC_AP_AP_H_ */
    
  • ap.c

      #include "ap.h"
        
      void apInit(void)
      {
        
      }
        
      void apMain(void)
      {
        while(1)
        {
        
        }
      }
    

    ap.capMain 함수에 무한 루프(while)을 넣는 이유는 main.c의 내용을 간소화하기 위함이다. apMain 함수가 진짜 main이 될 예정이다.

  • bsp.h

      #ifndef SRC_BSP_BSP_H_
      #define SRC_BSP_BSP_H_
        
      #include "def.h" // common/def.h 가져오기
        
      void bspInit(void);
        
      // 공동으로 사용하는 함수들 정리
      void delay(uint32_t ms); // ms 단위로 시간 지연하는 함수
      uint32_t millis(void);  // ms 단위로 count 하는 함수
        
      #endif /* SRC_BSP_BSP_H_ */
    
  • bsp.c

      #include "bsp.h"
        
      void bspInit(void)
      {
        
      }
        
      void delay(uint32_t ms)
      {
        
      }
        
      uint32_t millis(void)
      {
        return 0;
      }
    
  • def.h

      #ifndef SRC_COMMON_DEF_H_
      #define SRC_COMMON_DEF_H_
        
      #include <stdio.h>
      #include <stdint.h>
      #include <stdbool.h>
        
      #endif /* SRC_COMMON_DEF_H_ */
    

    공통으로 사용할 것들을 작성한다. 전체적인 수정이 필요할 때 def.h에서 수정하면 전체가 바뀌도록 코드를 작성한다. 유지보수를 쉽게 할 수 있다.

  • hw_def.h

      #ifndef SRC_HW_HW_DEF_H_
      #define SRC_HW_HW_DEF_H_
        
      // hw 폴더 내에서 공통적으로 사용하게 될 것을 작성한다.
      #include "def.h"
      #include "bsp.h"
        
      #endif /* SRC_HW_HW_DEF_H_ */
    
  • hw.h

      #ifndef SRC_HW_HW_H_
      #define SRC_HW_HW_H_
        
      #include "hw_def.h"
        
      void hwInit(void);
        
      #endif /* SRC_HW_HW_H_ */
    
  • hw.c

      #include "hw.h"
        
      void hwInit(void)
      {
        bspInit();
      }
    
  • main.h

      #ifndef SRC_MAIN_H_
      #define SRC_MAIN_H_
        
      #include "ap.h"
        
      #endif /* SRC_MAIN_H_ */
    
  • main.c

      #include "main.h"
        
      int main(void)
      {
        hwInit();
        apInit();
        
        apMain();
        
        return 0;
      }
    

5. Build 및 include 경로 설정하기

5.1. Build

Untitled

  • 첫 번째 방법은 위 카테고리를 활용하는 것이다. Project → Build Project 클릭

Untitled

  • 두 번째 방법은 Project Explorer를 활용하는 것이다. Project Explorer에서 프로젝트(stm32f401_fw)를 우클릭 한 후 Build Project를 클릭한다.

5.2. include 경로 설정

Untitled

  • build를 하게 되면 아래 Console 창에 결과가 나타난다. 위 사진을 보면 오류가 많이 발생한 것을 볼 수 있다. 이는 include 경로를 설정하지 않아 발생한 것이다.

Untitled

  • Project → Properties를 클릭한다.

Untitled

Untitled

  • C/C++ Build → Settings → Tool Settings → MCU GCC Complier → Preprocessor를 클릭한다.
  • Define symbols에 저장된 것을 모두 삭제한다.

Untitled

Untitled

  • C/C++ Build → Settings → Tool Settings → MCU GCC Complier → include paths를 클릭한다.
  • Include paths에 존재하는 것을 모두 삭제한다.

Untitled

Untitled

Untitled

Untitled

  • Add 버튼을 클릭하여 코드를 작성한 모든 폴더의 경로를 추가한다.

5.3. Linker Script 경로 설정

Untitled

  • 위 과정에서 링커 스크립트 파일을 옮겼기 때문에 경로 설정을 추가로 진행해야 한다.
  • C/C++ → Settings → Tool Settings → MCU GCC Linker → General을 클릭한다.
  • Linker Script를 ${workspace_loc:/${ProjName}/src/bsp/ldscript/STM32F401RETX_FLASH.ld} 로 변경한다.
  • 이후 빌드를 진행한다.

Untitled

  • 에러 없이 build 된 것을 확인할 수 있다.
  • Console 오른쪽을 보면 Build Analyzer가 있다. build 진행 후 다양한 정보를 보여준다.

5.4. Build Analyzer

Untitled

  • Memory Regions는 메모리의 사용량을 보여준다.

Untitled

  • Memory Details는 각 메모리의 섹션을 보여준다.
  • .isr_vector: FlASH의 시작 주소와 같다. 스타터 코드에 정의되어 있다.
  • .bss: 전역 변수를 의미한다.
  • ._user_heap_stack: 힙의 시작 주소를 의미한다.

6. 디버깅

6.1. Debug Configurations

Untitled

  • Run → Debug Configurations 클릭하기

Untitled

  • STM32 C/C++ Application을 더블 클릭하면 자동으로 프로젝트가 적용된다.
  • Browse 버튼을 눌러 수동으로 프로젝트를 선택한다.
  • Browse 버튼을 눌렀는데 프로젝트가 하나도 존재하지 않는다면? 프로젝트를 다시 build 한 후 확인해본다.

이후 Apply 버튼을 누르고 Debug 버튼을 클릭한다.

Untitled

  • 디버깅을 처음하게 되면 뜨는 창이다. 디버깅 시 프로그램 메뉴 구성이 변하는데 이것을 바꿀 거냐는 뜻이다. 체크 박스를 클릭하여 항상 바뀌도록 설정한다.

6.2. 디버깅 오류

Untitled

  • ST-LINK를 찾을 수 없다는 오류와 함께 디버깅이 되지 않는다.
  • 펌웨어 업데이트가 필요하다는 것을 깨닫게 되었다. (오제이 튜브)

Untitled

Untitled

  • STM을 노트북과 연결한 상태에서 ‘STM32 ST-LINK Utility’ 프로그램을 실행한다.
  • Target → Connect 를 클릭하여 연결한다.

Untitled

  • ST-LINK → Firmware update 클릭

Untitled

  • Device Connect 버튼 클릭

Untitled

  • Device 정보가 뜨면, Yes 버튼을 클릭한다.

Untitled

  • 펌웨어가 업데이트 되었다.
  • 이제 다시 STM32 Cube IDE로 돌아간다.

Untitled

  • build 후 디버깅을 시도하면 펌웨어 업데이트를 하라고 한다. 분명 ‘STM32 ST-LINK Utility’ 프로그램에서 업데이트를 진행하였지만 다시 해준다.
  • 이후 다시 디버깅을 시도하면 hwInit 함수에서 브레이크 포인트가 걸린 것을 확인할 수 있다.

7. 참고 문헌