linux Gcc下开发stm32的启动代码
Gcc 环境下stm32开发笔记
最近在移植公司的系统到stm32中,发现该系统使用的是gcc 开发的,可是一般情况下stm32都是在集成环境下开发的,这时候就有很多以前集成开发环境做的事情需要我们自己编写makefile ,链接器脚本和启动代码。
由于公司的启动代码部分是采用C语言编写的,但是我不喜欢C的启动代码,所以我查阅了相关资料,把keil里面自带的启动代码,经过转换,转化成在gcc 下可以用的启动代码,本文中所有的代码经过编译,运行成功的,最后在C环境下点亮LED等来显示效果,需要完成这些功能至少需要以下几个文件Start.s main.c
system_stm32f10x.c stm32f10x_rcc.c stm32f10x_gpio.c,以及st标准库的所有头文件以防编译出错。
Gcc 开发最主要的要完成3个步骤,搭建起C语言的编程环境,其他的任何平台都是一样的。这3个步骤分别是,编写链接脚本,编写Makefile ,编写启动代码,这些完成了之后,以后的开发工作就都是一样的了。
闲话不说,首先我们把链接脚本贴上来。
/*宏定义处理器架构为arm*/
OUTPUT_ARCH(arm)
/*定义入口函数*/
ENTRY(Reset_Handler)
/*定义内存组织结构*/
MEMORY
{
/*我用的芯片是stm32f103 内存32K Flash 512K*/
RAM(xrw) : ORIGIN = 0x20000000,LENGTH = 32K
FLASH(rx): ORIGIN = 0x08000000,LENGTH = 512K
}
/*定义代码段*/
SECTIONS
{
/*代码最开头部分是中断向量表*/
. = ALIGN(4); /*4字节对齐*/
.text :
{
KEEP(*(.isr_vector))
*(.text)
} > FLASH
. = ALIGN(4);
__etext = .; /*代码段结束 . 代表单前地址*/ /*定义数据段*/
.data : AT (__etext)
{
__data_start__ = .;
*(vtable)
*(.data*)
. = ALIGN(4);
PROVIDE (__preinit_array_start = .);
*(.preinit_array)
PROVIDE (__preinit_array_end = .);
. = ALIGN(4);
PROVIDE (__init_array_start = .);
*(SORT(.init_array.*))
*(.init_array)
PROVIDE (__init_array_end = .);
. = ALIGN(4);
PROVIDE (__fini_array_start = .);
*(SORT(.fini_array.*))
*(.fini_array)
PROVIDE (__fini_array_end = .);
. = ALIGN(4);
__data_end__ = .;
} > RAM
/*定义bss 段 bss 为未初始化的变量*/ . = ALIGN(4);
.bss :
{
__bss_start__ = .;
*(.bss)
__bss_end__ = .;
} > RAM
/*定义堆区*/
. = ALIGN(4);
.heap :
{
__end__ = .;
end = __end__;
*(.heap*)
__HeapLimit = .;
} > RAM
/*定义栈区*/
.stack_dummy :
{
*(.stack)
} > RAM
__StackTop = ORIGIN(RAM) + LENGTH(RAM);
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
PROVIDE(__stack = __StackTop);
/*检查数据+堆+栈是否超出RAM*/
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") }
有了链接脚本我们就需要编写一个Makefile 了 ,Makefile的目录结构请各位自己定义,这里的目录结构仅供参考。
/*宏定义了使用的编译工具这里用的是windows 下的arm gcc 的编译器,当然可以换成Linux 下的gcc*/
CROSS_COMPILE ?= arm-none-eabi-
DIRECTORY ?= ./
SOURCEPATH := $(DIRECTORY)src/
INCLUDEPATH := $(DIRECTORY)include
INCLUDELIBPATH += $(DIRECTORY)lib
LIBARARY +=
DEFINE := USE_STDPERIPH_DRIVER STM32F10X_HD
/*添加源文件*/
SOURCES += Start.s main.c system_stm32f10x.c
stm32f10x_rcc.c stm32f10x_gpio.c
/*链接脚本的名字也就是调用刚刚上文的链接脚本文件*/
LD_FILE := $(DIRECTORY)Harbap_M3.lds
ELF_FILE := $(DIRECTORY)Harbap_M3.elf
BIN_FILE := $(DIRECTORY)Harbap_M3.bin
HEX_FILE := $(DIRECTORY)Harbap_M3.hex
SOURCE := $(addprefix $(SOURCEPATH),$(SOURCES)) INCLUDE := $(addprefix -I,$(INCLUDEPATH)) INCLUDELIB := $(addprefix -L,$(INCLUDELIBPATH))
LIBS := $(addprefix -l,$(LIBARARY))
OBJECTFILES :=
$(patsubst %.c,%.o,$(patsubst %.s,%.o,$(SOURCE)))
CLEAR := $(OBJECTFILES)
CC := $(CROSS_COMPILE)gcc
LD := $(CROSS_COMPILE)ld
OBJCOPY := $(CROSS_COMPILE)objcopy
DEFINE_FLAG := $(addprefix -D,$(DEFINE))
/*使用thumb指令集 O0 不做代码优化–Wall 打开警告功能*/
CC_FLAG := -g -O0 -Wall -mthumb
LD_FLAG := -g -O0 -nostartfiles -T$(LD_FILE)
/*所有的依赖文件 ,链接所有的 .o 文件*/
all:$(ELF_FILE)
$(ELF_FILE):$(OBJECTFILES)
$(LD) $(LD_FLAG) $(INCLUDE) $(LIBS) -o $@ $^
/*通过.elf 文件生成.bin 和 .hex 文件*/
$(OBJCOPY) -O binary $@ $(BIN_FILE)
$(OBJCOPY) -O ihex $@ $(HEX_FILE)
/*汇编文件编译*/
%.o : %.s
$(CC) -c $(CC_FLAG) -o $@ $<
/*C文件编译*/
%.o : %.c
$(CC) $(CC_FLAG) $(DEFINE_FLAG) $(INCLUDE) $(INCLUDELIB) -o $@ -c $<
/*Make clean 在Linux平台下把 erase 改为 rm 就可以了*/
.PHONY:clean
clean:
erase $(subst /,\,$(CLEAR)) *.hex *.bin
install:
到此为止Makefile 文件已经完成了,Makefile如果看不懂,请先熟悉Makefile 规则,本文不做这方面的描述
接下来就是我们的启动代码了。
.syntax unified
.arch armv7-m
/*定义栈大小*/
.section .stack
.align 3
.equ Stack_Size, 0xc00
/*在RAM启动模式有用到,本次没有用到这方面内容*/
.equ BootRAM, 0xF1E0F85F
.globl __StackTop
.globl __StackLimit
__StackLimit:
.space Stack_Size
.size __StackLimit, . - __StackLimit
__StackTop:
.size __StackTop, . - __StackTop
/*定义堆区大小*/
.section .heap
.align 3
.equ Heap_Size, 0x800
.globl __HeapBase
.globl __HeapLimit
__HeapBase:
.space Heap_Size
.size __HeapBase, . - __HeapBase
__HeapLimit:
.size __HeapLimit, . - __HeapLimit
/*定义中断向量表前面部分为ARM部分的异常向量表*/ .section .isr_vector
.align 2
.globl __isr_vector
__isr_vector:
.word __StackTop
.word Reset_Handler
.word NMI_Handler
.word HardFault_Handler
.word MemManage_Handler
.word BusFault_Handler
.word UsageFault_Handler
.word 0
.word 0
.word 0
.word 0
.word SVC_Handler
.word DebugMon_Handler
.word 0
.word PendSV_Handler
/* 外部中断向量表具体定义由厂商决定 */ .word WWDG_IRQHandler
.word PVD_IRQHandler
.word TAMPER_IRQHandler
.word RTC_IRQHandler
.word FLASH_IRQHandler
.word RCC_IRQHandler
.word EXTI0_IRQHandler
.word EXTI1_IRQHandler
.word EXTI2_IRQHandler
.word EXTI3_IRQHandler
.word EXTI4_IRQHandler
.word DMA1_Channel1_IRQHandler
.word DMA1_Channel2_IRQHandler
.word DMA1_Channel3_IRQHandler
.word DMA1_Channel4_IRQHandler
.word DMA1_Channel5_IRQHandler
.word DMA1_Channel6_IRQHandler
.word DMA1_Channel7_IRQHandler
.word ADC1_2_IRQHandler
.word USB_HP_CAN1_TX_IRQHandler .word USB_LP_CAN1_RX0_IRQHandler .word CAN1_RX1_IRQHandler
.word CAN1_SCE_IRQHandler
.word EXTI9_5_IRQHandler
.word TIM1_BRK_IRQHandler
.word TIM1_UP_IRQHandler
.word TIM1_TRG_COM_IRQHandler
.word TIM2_IRQHandler
.word TIM3_IRQHandler
.word TIM4_IRQHandler
.word I2C1_EV_IRQHandler
.word I2C1_ER_IRQHandler
.word I2C2_EV_IRQHandler
.word I2C2_ER_IRQHandler
.word SPI1_IRQHandler
.word SPI2_IRQHandler
.word USART1_IRQHandler
.word USART2_IRQHandler
.word USART3_IRQHandler
.word EXTI15_10_IRQHandler
.word RTCAlarm_IRQHandler
.word USBWakeUp_IRQHandler
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
/*计算中断向量表大小*/
.size __isr_vector, . - __isr_vector
/*代码最初从下面的Reset_Handler 处开始执行*/ .text
.thumb
.thumb_func
.align 2
.globl Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
/*拷贝数据到RAM __extex 代码段结尾,__data_start ,__data_end 数据段开头与结尾 */
ldr r1, =__etext
ldr r2, =__data_start__
ldr r3, =__data_end__
/*拷贝数据到 data 数据到RAM中*/
.flash_to_ram_loop:
cmp r2, r3
ittt lt
ldrlt r0, [r1], #4
strlt r0, [r2], #4
blt .flash_to_ram_loop
/*清除bss段*/
ldr r0, =0
ldr r1, =__bss_start__
ldr r2, =__bss_end__
clear_bss_loop:
cmp r1, r2
beq clear_bss_loop_end
str r0, [r1], #4
b clear_bss_loop
clear_bss_loop_end:
/*跳转到主函数*/
ldr r0, =SystemInit
blx r0
ldr r0, =main
bx r0
/*退出循环*/
exit_loop:
nop
b exit_loop
.pool
.size Reset_Handler, . - Reset_Handler
/*宏定义为弱定义,在外部没有定义的时候使用弱定义处理函数*/ .macro def_default_handler handler_name
.align 1
.thumb_func
.weak \handler_name
.type \handler_name, %function
\handler_name :
b .
.size \handler_name, . - \handler_name
.endm
def_default_handler NMI_Handler
def_default_handler HardFault_Handler
def_default_handler MemManage_Handler
def_default_handler BusFault_Handler
def_default_handler UsageFault_Handler
def_default_handler SVC_Handler
def_default_handler DebugMon_Handler
def_default_handler PendSV_Handler
def_default_handler SysTick_Handler
/*外部中断 */
def_default_handler WWDG_IRQHandler
def_default_handler PVD_IRQHandler
def_default_handler TAMPER_IRQHandler
def_default_handler RTC_IRQHandler
def_default_handler FLASH_IRQHandler
def_default_handler RCC_IRQHandler
def_default_handler EXTI0_IRQHandler
def_default_handler EXTI1_IRQHandler
def_default_handler EXTI2_IRQHandler
def_default_handler EXTI3_IRQHandler
def_default_handler EXTI4_IRQHandler
def_default_handler DMA1_Channel1_IRQHandler
def_default_handler DMA1_Channel2_IRQHandler
def_default_handler DMA1_Channel3_IRQHandler
def_default_handler DMA1_Channel4_IRQHandler
def_default_handler DMA1_Channel5_IRQHandler
def_default_handler DMA1_Channel6_IRQHandler
def_default_handler DMA1_Channel7_IRQHandler
def_default_handler ADC1_2_IRQHandler
def_default_handler USB_HP_CAN1_TX_IRQHandler def_default_handler USB_LP_CAN1_RX0_IRQHandler def_default_handler CAN1_RX1_IRQHandler
def_default_handler CAN1_SCE_IRQHandler
def_default_handler EXTI9_5_IRQHandler
def_default_handler TIM1_BRK_IRQHandler
def_default_handler TIM1_UP_IRQHandler
def_default_handler TIM1_TRG_COM_IRQHandler
def_default_handler TIM1_CC_IRQHandler
def_default_handler TIM2_IRQHandler
def_default_handler TIM3_IRQHandler
def_default_handler TIM4_IRQHandler
def_default_handler I2C1_EV_IRQHandler
def_default_handler I2C1_ER_IRQHandler
def_default_handler I2C2_EV_IRQHandler
def_default_handler I2C2_ER_IRQHandler
def_default_handler SPI1_IRQHandler
def_default_handler SPI2_IRQHandler
def_default_handler USART1_IRQHandler
def_default_handler USART2_IRQHandler
def_default_handler USART3_IRQHandler
def_default_handler EXTI15_10_IRQHandler
def_default_handler RTCAlarm_IRQHandler
def_default_handler USBWakeUp_IRQHandler
.end
住:如需要完整的工程可以从我的:
https://www.360docs.net/doc/da13604074.html,/detail/u014634615/8763871下载。