(二)arm裸机开发---c语言led驱动程序

上一节,我们提到了为什么使用汇编来写点亮led的驱动程序。因为没有c语言的运行环境,本节我们就来配置c语言的运行环境,毕竟c语言看起来还是舒服的。具体的寄存器地址和值请见上一节。

一.配置C语言的运行环境

C语言的运行环境包括:
1.处理器模式的选择
2.堆栈指针(sp)的设置
3.转到C语言的入口程序main

1.处理器模式的选择

我们用的是arm-cortexA7的芯片有9种处理器模式,简单起见,我们选择超级管理员模式。接下查看reference sheet。处理器模式在寄存器CPSR的M[4:0]设置。可以看到我们使用超级管理员权限,即SVC模式。所以设置为10011。即0x13。
在这里插入图片描述

2.堆栈指针(sp)的设置

DDR开始的地址是0x80000000,因为堆栈是从大到小分配内存的,所以SP指针设置为0x80200000,大小为2M。

3.编写汇编程序

start.s

.global _start

 _start :
@设置cpu为超级管理员模式
    /*读取cspr的内容,用到的函数是MRS*/
    MRS r0,cpsr
    /*将r0中的M[4:0]清空*/
    BIC r0,r0,#0x1f
    /*将r0与0x13按位或*/
    ORR r0,r0,#0x13
    /*将r0中的数据写道cspr中 */
    MSR cpsr,r0

@设置sp指针
    LDR sp ,=0x80200000

@跳转到main函数
    B main
    

二.编写c语言led驱动程序

我们将寄存器地址写在main.h文件中。

1.main.h

#ifndef __MIAN_H
#define __MIAN_H

/*CCM时钟寄存器的地址*/
#define CCM_CCGR0 *((volatile unsigned int*)0x020C4068)
#define CCM_CCGR1 *((volatile unsigned int*)0x020C406c)
#define CCM_CCGR2 *((volatile unsigned int*)0x020C4070)
#define CCM_CCGR3 *((volatile unsigned int*)0x020C4074)
#define CCM_CCGR4 *((volatile unsigned int*)0x020C4078)
#define CCM_CCGR5 *((volatile unsigned int*)0x020C407c)
#define CCM_CCGR6 *((volatile unsigned int*)0x020C4080)

/*复用功能和电器属性*/

#define MUX_GPIO1_IO03 *((volatile unsigned int*)0x020E0068)
#define PAD_GPIO1_IO03 *((volatile unsigned int*)0x020E02F4)

/*设置GPIO的输入输出*/
#define GPIO1_DR       *((volatile unsigned int*)0x0209C000)
#define GPIO1_GDIR     *((volatile unsigned int*)0x0209C004)

#endif 

2.main.c

#include "main.h"

//使能时钟
int enable_clock(){
    CCM_CCGR0 = 0xffffffff;
    CCM_CCGR1 = 0xffffffff;
    CCM_CCGR2 = 0xffffffff;
    CCM_CCGR3 = 0xffffffff;
    CCM_CCGR4 = 0xffffffff;
    CCM_CCGR5 = 0xffffffff;
    CCM_CCGR6 = 0xffffffff;

    return 0;
}

//设置复用功能和电器属性和输入输出
int led_init(){
    MUX_GPIO1_IO03 = 0x5;
    PAD_GPIO1_IO03 = 0x000010B0;
    GPIO1_GDIR = 0x8;
    GPIO1_DR = 0x0;

    return 0;
}

void led_on(){
    GPIO1_DR &= ~(1<<3);
}

void led_off(){
    GPIO1_DR |= 1<<3;
}

//一个短的延时
void delay_short(volatile unsigned int n){
    while (n--) {}
}

//大约n ms的延时
void delay(int n){
    while (n--){
        delay_short(0x7ff);
    }
}
int main(void){
    //使能时钟
    enable_clock();
    //设置复用功能和电器属性和输入输出
    led_init();
    while (1)
    {
        led_on();
        delay(500);
        led_off();
        delay(500);
    }
    
return 0;
}

3.Makefile

obj = start.o main.o

led.bin : $(obj)
	arm-linux-gnueabihf-ld -Ttext 0x87800000 $^ -o led.elf
	arm-linux-gnueabihf-objcopy -O binary -S led.elf $@
	arm-linux-gnueabihf-objdump -D -m arm led.elf > led.dis

%.o : %.c
	arm-linux-gnueabihf-gcc -Wall -nostdlib -c $< -o $@ 

%.o : %.s
	arm-linux-gnueabihf-gcc -Wall -nostdlib -c $< -o $@

.PHONY:clean
clean:
	-rm -r main.o start.o led.bin led.dis led.elf load.imx

.PHONY:load
load:
	./imxdownload led.bin /dev/sdb

4.链接文件的编写

      因为我们指定start.o文件(汇编配置c语言环境的文件)必须放在0x87800000地址上,即必须放在开头的地方。而在上面的链接方式中,是不固定那个文件在前面的,所以我们需要自己写链接文件,将指定的文件放在指定的段里面。
imx6ull.lds文件

SECTIONS{
    . = 0x87800000;
    .text :
    {
        start.o
        main.o
       *(.text)
    }
    
    .rodata ALIGN(4) : {*(.rodata)}
    .data ALIGN(4) : {*(.data)}

    _bss_start = .;
    .bss ALIGN(4) : {*(.bss) *(.COMMON)}
    _bss_end = .;
}

#修改Makefile
arm-linux-gnueabihf-ld -Timx6ull.lds $^ -o led.elf

总结

本节内容只是将上一节的汇编语言实现变成了c语言实现,还是往相同的寄存器里写值。汇编语言只是为c语言配置好环境,跳转到c语言的main函数。至此,敬礼。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值