STM32F103RCT6 부트로더 펌웨어를 작성하고
부트로더 -> 어플리케이션으로 점프하는 과정을 정리해봄
별거 아닌것 같지만 잘 모르면 몇시간을 잡아먹는 부분이기에
내가 알아본걸 조금이나마 도움이 되게 끄적여봄
0x08000000 부트로더
0x08006000 어플리케이션
1.부트로더의 링커를 수정해준다.

2. 부트로더의 링커파일을 수정해준다. (stm32f103xe_flash.icf)
/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x08000000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x08000000;
define symbol __ICFEDIT_region_ROM_end__ = 0x08005FFF;
define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__ = 0x20003FFF;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x800;
define symbol __ICFEDIT_size_heap__ = 0x800;
/**** End of ICF editor section. ###ICF###*/
define memory mem with size = 4G;
define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__];
define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
define exported symbol app_vector = 0x08006000;
define exported symbol app_vector1 = 0x08016000;
initialize by copy { readwrite };
do not initialize { section .noinit };
"INTVEC":
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
"ROM":
place in ROM_region { readonly };
"RAM":
place in RAM_region { readwrite,
block CSTACK, block HEAP };
"APPLICATION":
place at address mem: app_vector { readonly section .APP };
"APPLICATION1":
place at address mem: app_vector1 { readonly section .APP1 };
define symbol __region_EEPROM_start__ = 0x08080000;
define symbol __region_EEPROM_end__ = 0x08080FFF;
define region EEPROM_region = mem:[from __region_EEPROM_start__ to __region_EEPROM_end__];
place in EEPROM_region { section .eeprom };
3. 부트로더 main.c 파일 수정
/* USER CODE BEGIN Includes */
#include <intrinsics.h> // 추가해줌
/* USER CODE END Includes */
//////////////////////////////////////////////////////////////////////////////////
/* USER CODE BEGIN PV */
typedef void (application_t) (void);
typedef struct vector
{
uint32_t stack_addr; // intvec[0] is initial Stack Pointer
application_t *func_p; // intvec[1] is initial Program Counter
} vector_t;
extern const uint32_t app_vector; // 어플리케이션 영역1
extern const uint32_t app_vector1; // 어플리케이션 영역2
USBD_HandleTypeDef USBD_Device; // 나중에 DFU할때 사용할것임
/* USER CODE END PV */
///////////////////////////////////////////////////////////////////////////////////
int main(void)
{
/* USER CODE BEGIN 1 */
typedef void (*pFunction)(void);
pFunction JumpToApplication;
uint32_t JumpAddress;
/* USER CODE END 1 */
.
....
.....
/* USER CODE BEGIN 2 */
if (HAL_GPIO_ReadPin(Firmup_Pin_GPIO_Port, Firmup_Pin_Pin) != GPIO_PIN_RESET)
{
const vector_t *vector_p = (vector_t*) &app_vector;
volatile uint32_t stack_arr[100] = {0}; // Allocate some stack
// just to show that
// the SP should be reset
// before the jump - or the
// stack won't be configured
// correctly.
__enable_interrupt();
// printf("Hello from bootloader!\n");
__disable_interrupt(); // 1. Disable interrupts
__set_SP(vector_p->stack_addr); // 2. Configure stack pointer
SCB->VTOR = (uint32_t) &app_vector; // 3. Configure VTOR
vector_p->func_p(); // 4. Jump to application
}
링커파일에서 define 한 app_vector를 불러옴
펌웨어 핀이 reset이면
USBD_DFU_APP_DEFAULT_ADD 주소로 점프 뜀

USBD_DFU_APP_DEFAULT_ADD 가 아닌 0x08006000으로 해도됨.
나는 나중에 usb dfu를 할것이기에 저렇게 해놓음.
4. 어플리케이션 main.c 수정
부트로더와 마찮가지로
#include <intrinsics.h>
를 include 해준다. 이는
_enable_interrupt();
while (1)
{
}
부트로더에서 disable 한 interrupt를 enable 하는 과정임
5.어플리케이션의 링커파일 수정
/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x08006000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x08006000;
define symbol __ICFEDIT_region_ROM_end__ = 0x0803FFFF;
define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__ = 0x20003FFF;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x800;
define symbol __ICFEDIT_size_heap__ = 0x800;
/**** End of ICF editor section. ###ICF###*/
define memory mem with size = 4G;
define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__];
define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
initialize by copy { readwrite };
do not initialize { section .noinit };
"INTVEC":
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
"ROM":
place in ROM_region { readonly };
"RAM":
place in RAM_region { readwrite,
block CSTACK, block HEAP };
define symbol __region_EEPROM_start__ = 0x08080000;
define symbol __region_EEPROM_end__ = 0x08080FFF;
define region EEPROM_region = mem:[from __region_EEPROM_start__ to __region_EEPROM_end__];
place in EEPROM_region { section .eeprom };
이렇게 하면 bootloader -> application으로 점프를 뛰며 app에서 원하는 코딩을 하면 된다.
그럼 이만
'임베디드 > STM32' 카테고리의 다른 글
| DFU 이용할때 추가 해야 하는것 (0) | 2023.09.04 |
|---|---|
| bootloader 추가.. (0) | 2023.09.04 |