STM32 팁

Bootloader(DFU또는 IAP)에서 Application의 존재를 확인하는 방법

plainy 1 6,611 2017.04.06 00:15

Bootloader는 Application이 존재할 경우 Application으로 Jump하여 Application을 실행합니다.

만약 Application이 존재하지 않는 경우 Firmware를 Update하기 위한 동작을 수행하여야 합니다.

이를 위해서는 Application영역이 비어있는지, Application영역에 정상적인 Firmware가 들어있는지 확인하여야 합니다.

STM32의 대표적인 Bootloader인 DFU(Device Firmware Upgrade)와 IAP(In-Application Progrmming)에서는 Application의 존재여부 및 정상적인 Firmware인지 확인하기 위하여 아래와 같은 방법을 사용하고 있습니다.
  1. /* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */
  2. if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
  3. {
  4. /* Jump to user application */
  5. JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
  6. Jump_To_Application = (pFunction) JumpAddress;
  7. /* Initialize user application's Stack Pointer */
  8. __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
  9. Jump_To_Application();
  10. }

바로 Application이 저장된 첫번째 주소의 값을 0x2FFE0000으로 AND연산한 후 SRAM base address인 0x20000000과 비교하는 방법입니다.


STM32 Flash의 첫부분에는 Vector Table이 위치하고 있으며 그 뒤에 사용자가 작성한 Code와 Data들이 위치합니다.
Vector Table은 아래와 같으며 Interrupt Handler의 주소가 저장되어 있습니다.
예약(Reserved)되어있는 첫번째 주소에는 Stack Pointer가 저장됩니다.
Stack Pointer는 프로그램에서 사용되는 Stack의 크기에 따라 다양하게 지정될 수 있으나 최대 SRAM크기를 넘어설 수 없습니다.
그러므로 Stack Pointer가 STM32의 최대 SRAM크기를 넘어서거나 SRAM영역이 아닌 위치를 가르키고 있을 경우 정상적인 Firmware가 아니거나 Application이 존재하지 않는것으로 판단할 수 있습니다.

다시 위 코드를 살펴보겠습니다.

  1. /* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */
  2. if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)

Stack Pointer가 위치한 주소의 값을 0x2FFE0000으로 AND연산하고 있습니다.


STM32의 SRAM은 Device에 따라 4Kb부터 256Kb까지 다양하게 존재합니다. STM32F2 또는 F4의 경우 112Kb+16Kb+64Kb로 구성됩니다. Stack의 위치를 변경하지 않는 경우 112Kb SRAM에 Stack이 위치합니다.

따라서 최대 112Kb의 범위를 확인하기 위해 0x2FFE0000으로 AND연산을 하는 것입니다.
Stack Pointer의 값이 0x2000FFFF(64Kb)인 경우 0x2FFE0000으로 AND연산하면 0x20000000으로 SRAM범위 내에 있음을 확인할 수 있습니다.
Stack Pointer의 값이 0x2002FFFF(196Kb)인 경우 0x2FFE0000으로 AND연산하면 0x20020000으로 SRAM범위를 벗어난 것을 확인할 수 있습니다.

Mask값은 최대 SRAM크기에 1을 더한 값을 NOT연산 한 후 SRAM base address인 0x20000000을 넣어주면 됩니다.

최대 SRAM의 크기에 1을 더하는 이유는 STM32의 Stack이 descending stack이기 때문입니다. Stack에 Data를 Push하면 Stack pointer가 줄어든 후 Write동작을 수행합니다. 그러므로 Mask값은 Stack Pointer에 1을 더해야 합니다.
64Kb의 크기를 가진 SRAM은 0x20000000~0x2000FFFF의 주소에 위치합니다.
Stak Pointer는 0x20010000의 값이 될 수 있으므로 0x2000FFFF의 값을 확인하기 위한 Mask값은 0x2FFF0000이 아닌 0x2FFE0000이 되어야 합니다.

Comments

kwak 2018.11.29 15:11
STM 관련 자료 매우 유용하게 잘 보고 있습니다
제가 찾아본 자료 중 가장 깔끔하면서도 이해하기 쉽게 잘 정리하셨습니다
정말 소중한 자료 너무나 감사드리고 복 많이 받으시기 바랍니다
Category
Facebook Twitter GooglePlus KakaoStory NaverBand