项目硬件验证环境: STM32F205
项目码云git地址: https://gitee.com/liwandong/ShareRTOS
通常情况下可以直接使用ST公司提供的startup_stm32f2xx.s 这个文件进行mcu启动的引导,不是很喜欢汇编,所以将其启动过程改为使用C语言来实现,首先分析一下startup_stm32f2xx.s这个文件的启动流程大概如下所示:
其中大体的流程是系统上电之后会获取中断向量表,然后运行Rest_Handle函数,然后运行初始化时钟接口,最后在调用main函数,使用mdk等IDE时数据拷贝的工作被隐藏起来,可以通过查看map文件来进行分析,基于以上流程,写我们自己的启动文件过程如下:文件路径在mcudevice/src/stm32f205_startup.c
建立中断向量表,代码如下:
__attribute__ ((section("vectors"))) void (* const VectorArray[])(void)={
//内核中断
(void*)STACK_TOP,
Reset_Handler,
NMI_Handler,
HardFault_Handler,
MemManage_Handler,
BusFault_Handler,
UsageFault_Handler,
0,
0,
0,
0,
SVC_Handler,
DebugMon_Handler,
0,
PendSV_Handler,
SysTick_Handler
//外设中断
};
这里使用了两个知识点,一个是__attribute__ ((section(“vectors”))) 将部分内容定义为一个段,另一个使用函数指针数组包含多个函数,使其地址按照定义顺序排列。
拷贝数据和数据初始化的函数
void stm32_copydata(unsigned int *form,unsigned int *section_begin,unsigned int *section_end)
{
unsigned int *p;
p = section_begin;
while(p
{
*p++ = *form++;
}
}
void stm32_bssinit(unsigned int *startbss,unsigned int *endbss)
{
unsigned int *p;
p = startbss;
while(p
{
*p++ = 0;
}
有了基本的这些函数之后,就在Reset_Handler 函数中copy bbs,ro,rw数据,初始化时钟,调用main函数
void Reset_Handler(void){
stm32_copydata(&_sidata,&_sdata,&_edata);
stm32_bssinit(&__bss_start__,&__bss_end__);
SystemInit();
main();
}
数据段的来自链接脚本文件,脚本文件的情况如下:
/*
指定函数入口
*/
ENTRY(Reset_Handler)
/*定义堆和栈大小*/
_Min_Heap_Size = 0x0000;
_Min_Stack_Size = 0x10000;
/*flash和ram的分布情况*/
MEMORY
{
FLASH (rx): ORIGIN = 0x08000000, LENGTH = 1024K
RAM (rwx): ORIGIN = 0x20000000, LENGTH = 128K
}
SECTIONS
{
/*向量表放在最头部*/
.vectors :
{
. = ALIGN(4);
KEEP(*(vectors))
. = ALIGN(4);
} > FLASH
/*代码段*/
.text :
{
. = ALIGN(4);
*(.text);
*(.text*);
*(.rodata);
*(.rodata*);
*(.glue_7)
*(.glue_7t)
*(.eh_frame)
. = ALIGN(4);
_etext = .; /*代码段结束*/
}>FLASH
/*数据段*/
_sidata = .;
.data : AT ( _sidata )
{
. = ALIGN(4);
_sdata = .;
*(.data);
*(.data*);
. = ALIGN(4);
_edata = .;
}>RAM
. = ALIGN(4);
/*bss段*/
.bss :
{
_***ss = .;
__bss_start__ = _***ss;
*(.bss);
*(.bss*);
*(COMMON);
. = ALIGN(4);
_ebss = .;
__bss_end__ = _ebss;
}>RAM
/*导出符号可以在c中使用*/
PROVIDE ( end = _ebss );
PROVIDE ( _end = _ebss );
._user_heap_stack :
{
. = ALIGN(4);
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(4);
} >RAM
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
}
经过上面的步骤之后,stm32就可以被启动起来。
项目硬件验证环境: STM32F205
项目码云git地址: https://gitee.com/liwandong/ShareRTOS
通常情况下可以直接使用ST公司提供的startup_stm32f2xx.s 这个文件进行mcu启动的引导,不是很喜欢汇编,所以将其启动过程改为使用C语言来实现,首先分析一下startup_stm32f2xx.s这个文件的启动流程大概如下所示:
其中大体的流程是系统上电之后会获取中断向量表,然后运行Rest_Handle函数,然后运行初始化时钟接口,最后在调用main函数,使用mdk等IDE时数据拷贝的工作被隐藏起来,可以通过查看map文件来进行分析,基于以上流程,写我们自己的启动文件过程如下:文件路径在mcudevice/src/stm32f205_startup.c
建立中断向量表,代码如下:
__attribute__ ((section("vectors"))) void (* const VectorArray[])(void)={
//内核中断
(void*)STACK_TOP,
Reset_Handler,
NMI_Handler,
HardFault_Handler,
MemManage_Handler,
BusFault_Handler,
UsageFault_Handler,
0,
0,
0,
0,
SVC_Handler,
DebugMon_Handler,
0,
PendSV_Handler,
SysTick_Handler
//外设中断
};
这里使用了两个知识点,一个是__attribute__ ((section(“vectors”))) 将部分内容定义为一个段,另一个使用函数指针数组包含多个函数,使其地址按照定义顺序排列。
拷贝数据和数据初始化的函数
void stm32_copydata(unsigned int *form,unsigned int *section_begin,unsigned int *section_end)
{
unsigned int *p;
p = section_begin;
while(p
{
*p++ = *form++;
}
}
void stm32_bssinit(unsigned int *startbss,unsigned int *endbss)
{
unsigned int *p;
p = startbss;
while(p
{
*p++ = 0;
}
有了基本的这些函数之后,就在Reset_Handler 函数中copy bbs,ro,rw数据,初始化时钟,调用main函数
void Reset_Handler(void){
stm32_copydata(&_sidata,&_sdata,&_edata);
stm32_bssinit(&__bss_start__,&__bss_end__);
SystemInit();
main();
}
数据段的来自链接脚本文件,脚本文件的情况如下:
/*
指定函数入口
*/
ENTRY(Reset_Handler)
/*定义堆和栈大小*/
_Min_Heap_Size = 0x0000;
_Min_Stack_Size = 0x10000;
/*flash和ram的分布情况*/
MEMORY
{
FLASH (rx): ORIGIN = 0x08000000, LENGTH = 1024K
RAM (rwx): ORIGIN = 0x20000000, LENGTH = 128K
}
SECTIONS
{
/*向量表放在最头部*/
.vectors :
{
. = ALIGN(4);
KEEP(*(vectors))
. = ALIGN(4);
} > FLASH
/*代码段*/
.text :
{
. = ALIGN(4);
*(.text);
*(.text*);
*(.rodata);
*(.rodata*);
*(.glue_7)
*(.glue_7t)
*(.eh_frame)
. = ALIGN(4);
_etext = .; /*代码段结束*/
}>FLASH
/*数据段*/
_sidata = .;
.data : AT ( _sidata )
{
. = ALIGN(4);
_sdata = .;
*(.data);
*(.data*);
. = ALIGN(4);
_edata = .;
}>RAM
. = ALIGN(4);
/*bss段*/
.bss :
{
_***ss = .;
__bss_start__ = _***ss;
*(.bss);
*(.bss*);
*(COMMON);
. = ALIGN(4);
_ebss = .;
__bss_end__ = _ebss;
}>RAM
/*导出符号可以在c中使用*/
PROVIDE ( end = _ebss );
PROVIDE ( _end = _ebss );
._user_heap_stack :
{
. = ALIGN(4);
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(4);
} >RAM
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
}
经过上面的步骤之后,stm32就可以被启动起来。
举报