이전에 올린 글 STM32F103 DFU BOOTLOADER로 펌웨어 업데이트하기의 내용을 수정했습니다.
STM32CubeMx의 버전이 바뀌면서 STM32CubeMx가 만들어 주는 코드가 달라져서, 이전의 방법대로 만든 프로젝트는 제대로 실행되지 않았습니다. 그동안 저의 글을 보고 따라 하다가 안 되어서 고생하신 분들께 사과드립니다.
1. 부트로더 만들기
STM32F103 DFU BOOTLOADER 만들기에서 부트로더를 만드는 과정은 큰 차이가 없습니다.
다만, 부트로더를 완성한 다음의 코드가 커져서, 펌웨어의 시작 번지와 인터럽트벡터 테이블의 주소를 더 뒤로 옮겨야 하는 점이 달라졌습니다. 컴파일러의 Optimizing 옵션을 -Os로 주고 컴파일한 경우 14KB가 좀 안되는 정도의 크기입니다. 이전의 코드보다 약 2KB 정도 더 커집니다. 따라서 펌웨어 프로그램은 최소한 0x8003800 이후에 위치하도록 하고, 인터럽트 벡터 테이블로 그 위치로 옮겨야 합니다.
부트로더의 크기가 커졌기 때문에 USBD_DFU_MEDIA Interface에 입력하는 내용도 조금 달라져야 합니다. 부트로더 영역으로 12KB를 할당한 때에는 @Internal Flash /0x08000000/12*001Ka,52*001Kg,64*001Kg를 입력했지만, 14KB를할당할 때에는 @Internal Flash /0x08000000/14*001Ka,50*001Kg,64*001Kg 등과 같이 해야할 것 같습니다.
2. 펌웨어 만들기
STM32F103 DFU BOOTLOADER로 펌웨어 업데이트하기에서는 인터럽트 벡터를 옮기는 방법이 달라졌습니다.
버전 업되기 이전의 STM32CubeMx가 만들어 주는 소스 프로그램 system_stm32f1xx.c의 95행에서 다음 그림의 빨간색 사각형 표시한 부분에 새로운 인터럽트 벡터가 위치할 주소를 지정하면 되었습니다.

최근의 STM32CubeMx가 만들어 주는 코드도 system_st32f1xx.c에 있습니다. 다음의 사진에서 처럼 두 군데를 수정해야 합니다.

① 97행의 주석 처리를풀어 준다.
② 111행의 주소를 수정한다. 위 예의 경우 0x0001000으로 수정했습니다.
인터럽트 벡터를 SRAM 영역으로 옮길 경우에는 102행의 주석 처리도 풀고, 106행에 옮길 SRAM의 주소를 지정합니다.
<<위 내용들은 해당 글에도 비슷하게 언급했습니다.>>
3. 그리고 더 해야함.
2. 펌웨어 만들기의 수정까지 하고, 펌웨어를 다운로드시키니까 잘 되었습니다. 다 끝난 줄 알았습니다. 그런데, STM32F103의 전원을 끊었다가 다시 켜니 펌웨어 프로그램이 동작하지 않습니다. [RESET] 버튼을 눌러도 마찬가지로 펌웨어 프로그램이 동작하지 않습니다.
하드웨어적 이상이 발생했는지 일일이 확인했습니다만, STM32CubeIDE에서 펌웨어 프로그램을 다운로드시키면 그 때에는 잘됩니다. 원인을 찾지 못해 꽤 오랜 시간을 보냈습니다. STM32의 부트로더 관련해서 검색하여 인터넷을 뒤지다가 다음과 같은 내용을 찾았습니다.
- Find system memory location for specific STM32 in AN2606
- Set RCC to default values (the same as on startup) [Internal clock, no PLL, etc.)
- Disable SysTick interrupt and reset it to default
- Disable all interrupts
- Map system memory to 0x00000000 location
- Set jump location to memory location + 4 bytes offset
- Set main stack pointer to value stored at system memory location address
- Call virtual function assigned before
[출처 stm32f4-discovery.net/2017/04/tutorial-jump-system-memory-software-stm32/]
위 내용은 원래 다른 시스템 메모리로 점프할 때에 지켜야 할사항들입니다.
① RCC를 디폴트 값으로 바꾸어 주고
② 인터럽트 발생한 것 모두 없애고
③ 인터럽트를 발생하지 않게 한 후에
스택 포인터 상한값을 기록하고 그 4바이트 뒤에 기록된 번지수로 점프하라는 내용입니다.
본 사이트에서 제작한 부트로더 프로그램에서는 위의 ①, ②, ③을 하지 않고 펌웨어 프로그램으로 점프합니다.
STM32CubeMx에서 자동으로 작성한 부트로더 프로그램에서 인터럽트는 사용하지 않는 것 같습니다. 따라서 ②, ③은 할 필요가 없을 듯합니다. 반면에 부트로더에서 RCC 설정은 분명히 했으므로 펌웨어 프로그램에서 이것을 초기화하는 과정을 실행해야 할 것 같습니다.
STM32CubeMx 버전업되기 이전에는 system_stm32f1xx.c 안의 SystemInit() 함수에서 이 작업을 했습니다. 그런데 어떤 이유에서인지 현재 버전의 STM32CubeMx에서 만든 system_stm32f1xx.c의 SystemInit() 함수에는 이 작업을 하는 루틴이 없어졌습니다. 그래서 다음과 같은 내용을 SystemInit() 함수에 추가해야 합니다.
/* Reset the RCC clock configuration to the default reset state(for debug purpose) */ /* Set HSION bit */ RCC->CR |= 0x00000001U; /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */ #if !defined(STM32F105xC) && !defined(STM32F107xC) RCC->CFGR &= 0xF8FF0000U; #else RCC->CFGR &= 0xF0FF0000U; #endif /* STM32F105xC */ /* Reset HSEON, CSSON and PLLON bits */ RCC->CR &= 0xFEF6FFFFU; /* Reset HSEBYP bit */ RCC->CR &= 0xFFFBFFFFU; /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */ RCC->CFGR &= 0xFF80FFFFU;
왜 저 루틴을 제거했는지 모르겠지만 저 루틴을 넣어야 펌웨어 프로그램이 정상적으로 동작합니다.
'STM32F103' 카테고리의 다른 글
STM32F103으로 ESP8266을 이용한 소켓 통신하기 - 제5편 (0) | 2020.02.25 |
---|---|
STM32F103으로 ESP8266을 이용한 소켓 통신하기 - 제4편 (0) | 2020.02.24 |
STM32F103으로 ESP8266을 이용한 소켓 통신하기 - 제3편 (1) | 2020.01.28 |
STM32F103으로 ESP8266을 이용한 소켓 통신하기 - 제2편 (3) | 2020.01.20 |
STM32F103으로 ESP8266을 이용한 소켓 통신하기 - 제1편 (2) | 2020.01.11 |