linux Gcc下开发stm32的启动代码

linux Gcc下开发stm32的启动代码
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下载。

相关主题
相关文档
最新文档