|
作为Linux的忠实粉丝,依然热衷于VIM,喜欢纯命令行的模式写程序,并且STM32又是ARMv7-m架构,所以,想起来了使用vim+arm-linux-gcc的方式玩STM32.从网上还真不好找这种玩法.
玩耍环境:
上位机:UbuntuKylin 14.10 (内核版本3.13.0-44-generic)
交叉编译工具:arm-linux-gcc (版本:4.5.1,支持ARMv7-m架构的就行了)
编辑器:可爱的vim
下位机:STM32F103VCT6开发板
下载线:J-Link V8
备忘数据:
STM32的Flash起始地址为0x8000000 (6个0)
内部RAM地址0x20000000(7个0,当B0引脚接地时,这个地址被映射为0x00,当前我的环境是这样)
下面就是玩开发板的"HelloWorld"----也就是"点灯"
方式1:纯汇编(这个汇编语法是GNU的,和Exynos4412/S3C2440等ARM一样)
/******************* led.s文件从下面一行开始 **********************/
.equ S_P, 0x20000800 @这个是栈顶的位置
.text
.global _start
.code 16 @使用Thumb指令集,当然是16了
.syntax unified
_start:
.word S_P, start @STM32的中断向量表最前面放的是栈指针,不是ResetHandler
.type start, function
start: @中断向量表的第二个位置才是RestHandler
ldr r0, =#0x40021018 @这是APB2 外设时钟使能寄存器(RCC_APB2ENR),GPIO是挂在APB2总线上的,要先使能这个总线时钟
ldr r1, =#(1 <<5) @这个数值根据板子来写
str r1, [r0]
ldr r0, =#0x40011404 @GPD_CRH寄存器,配置引脚的功能
ldr r1, =#(3 << 16) @这个也是根据板子来的
str r1, [r0]
ldr r0, =#0x4001140c @GPD_ODR寄存器,设置引脚输出的高低电平
ldr r1, =#0 @不算那么具体了,太麻烦,根据原理图,低电平点亮LED
str r1, [r0]
b start
.end
/********************** led.s文件从上一行结束 *************************/
开始编译:
$> arm-linux-as -mcpu_cortex-m3 -mthumb led.s -o led.o
$> arm-linux-ld -Ttext 0 -o led.out led.o
$> arm-linux-objcopy -Obinary led.out led.bin
烧写:
$>JLinkExec (前提已经装好了Jlink驱动)
J-Link> exec device = STM32F103VC (这个根据板子的情况写)
J-Link> r (让CPU停止工作,我的板子可以省略这步)
J-Link> erase (擦除Flash,我的板子可以省略这步)
J-Link> loadbin led.bin 0x8000000 (把编译好的文件烧进Flash)
重启板子就行了.
下面是C语言版的程序
目录树是这样的:
.
├── include
│ └── common.h
├── lf.ld
├── main.c
└── Makefile
1 directory, 5 files
/****************** ./include/common.h文件从下面一行开始 *********************/
#define RCC_APB2ENR (*(volatile unsigned int *)0x40021018) //这个里面使用加减运算(BASE_ADDR+OFF_ADDR)的形式不能用
#define GPD_CRL (*(volatile unsigned int *)0x40011400) //具体原因有待研究
#define GPD_CRH (*(volatile unsigned int *)0x40011404) //反汇编的文件看不出任何差别,就是不能用.
#define GPD_IDR (*(volatile unsigned int *)0x40011408)
#define GPD_ODR (*(volatile unsigned int *)0x4001140c)
#define GPD_BSRR (*(volatile unsigned int *)0x40011410)
#define GPD_BRR (*(volatile unsigned int *)0x40011414)
#define GPD_CLKR (*(volatile unsigned int *)0x40011418)
#define S_P 0x20000800
/****************** ./include/common.h文件从上面一行结束 *********************/
/********************* ./mian.c文件从下面一行开始 *******************************/
#include <common.h>
void delay(unsigned int t)
{
volatile unsigned int i, j;
for (i = 0; i < t; i++)
for (j = 0; j < 1000; j++)
;
}
int main(void)
{
unsigned int tmp;
RCC_APB2ENR |= 1 << 5;
tmp = GPD_CRH;
tmp &= ~(0xf << 16);
tmp |= 0x3 << 16;
GPD_CRH = tmp;
while (1) {
GPD_ODR &= ~(1 << 12);
delay(10);
GPD_ODR |= 1 << 12;
delay(1000);
}
return 0;
}
__attribute__((section("vectors"))) void (* const v_A[])(void) = { //有了这个,就不需要汇编启动文件了
S_P,
main,
};
/********************* ./mian.c文件从上面一行结束 *******************************/
程序部分是写好了,为了方便还有可爱的Makefile
/************************** Makefile从下面一行开始 ******************************/
TARGET :=tst
START_OBJ :=main.o
###############################################
BIN :=$(TARGET).bin
NMFILE :=System.map
DUMPFILE :=$(TARGET).s
###############################################
CFLAGS += -march=armv7-m
CROSS_COMPILE :=arm-linux-
###############################################
CC :=$(CROSS_COMPILE)gcc
AS :=$(CROSS_COMPILE)as
LD :=$(CROSS_COMPILE)ld
OBJCOPY :=$(CROSS_COMPILE)objcopy
OBJDUMP :=$(CROSS_COMPILE)objdump
NM :=$(CROSS_COMPILE)nm
RM :=rm -rf
###############################################
all:$(TARGET)
$(OBJCOPY) -O binary $^ $(BIN)
$(OBJDUMP) -D $^ > $(DUMPFILE)
$(NM) $^ > $(NMFILE)
$(RM) $^
$(TARGET):$(START_OBJ) #$(OTHER_OBJ)
$(LD) -o $@ $^ -T lf.ld #$(LD_ADDR)
#%.o:%.s
# $(AS) -o $@ $^
%.o:%.c
$(CC) -c -o $@ $^ -nostartfiles -mthumb -I ./include -Wall
clean:
$(RM) $(START_OBJ) $(OTHER_OBJ) $(TARGET) $(BIN) $(DUMPFILE) $(NMFILE)
/************************** ./Makefile从上面一行结束 ******************************/
从Makefile文件中可以看出,还需要一个链接文件:
/******************************./lf.ld文件从下面一行开始 **************************/
MEMORY
{
rom (rx) : ORIGIN = 0, LENGTH = 2M
ram (rwx) : ORIGIN = 0X20000000, LENGTH = 4M
}
SECTIONS
{
. = 0x0;
.text : {
*(vectors)
*(.text)
*(.rodata)
}
. = 0x20000000;
.data : {
*(.data)
}
.bss : {
*(.bss)
}
}
/******************************./lf.ld文件从上面一行结束 **************************/
|
|