3 led程序编写和交叉编译器

3 led程序编写和交叉编译器

1、明确:下位机运行的软件类型

嵌入式软件分两类:裸板程序和基于操作系统程序

裸板程序的特点:

单文件:可执行程序只有一个

单任务: 运行的程序就一个

运行环境不是基于操作系统(例如:linux/winodows/ios等)

不允许使用标准C库的内容(例如:printf)

切记:裸板程序的编程框架

void abc(void)

 {

xyz_init();

/*

led_init(); //初始化LED

uart_init(); //初始化UART串口

lcd_init();//初始化LCD显示屏

net_init(); //初始化网卡

usb_init(); //初始化USB

emmc_init();//初始化EMMC

nand_init(); //初始化nadflash

norflash_init();//初始化norflash

...

*/

while(1)

{

//根据用户需求来操作访问硬件

/*

led_on(); //开灯

delay(); //延时一段时间

led_off(); //关灯

                  delay(); //延时一段时间

*/

}

}

 

说明:

1.裸板程序的入口函数名不一定叫main,随便叫,例如abc

2.裸板程序上来首先做各种硬件初始化工作,例如xyz_init初始化函数

"硬件初始化":硬件外设正式使用操作之前,将它的工作状态指定一个合适的状态下

例如LED灯:首先应该把LED1对应的处理器的引脚的功能配置为GPIO功能

还要配置为输出模式,只有这两个做好了,才能输出0和输出1,不能上来就输出1或者0

                                                                            

基于操作系统程序特点:

多文件

多任务

可以使用标准C库的内容(例如:printf)

应用程序编程框架

int main(int argc, char *argv[])

{

/*根据用户需求完成业务*/

return 0;

}

                                                                     

结论:目前此LED程序采用裸板程序来实现      

led.h
#ifndef __LED_H
#define __LED_H

/*寄存器的定义*/
#define GPIOCOUT    (*(volatile unsigned long *)0xC001C000)
#define GPIOCOUTENB    (*(volatile unsigned long *)0xC001C004)
#define GPIOCALTFN0    (*(volatile unsigned long *)0xC001C020)

/*声明LED操作函数*/
extern void led_init(void);
extern void led_on(void);
extern void led_off(void);

#endif
led.c
#include "led.h"

//声明延时函数
extern void delay(int n);

/*裸板程序的入口函数*/
void led_test(void)
{
    /*1.初始化LED*/
    led_init();

    //2.根据用户需求重复开关灯
    while(1) {
        led_on(); //开
        delay(0x1000000); //延时
        led_off(); //关
        delay(0x1000000); //延时
    }
}

//初始化函数定义
void led_init(void)
{
    //1.配置LED1对应的CPU引脚功能为GPIO
    GPIOCALTFN0 &= ~(3 << 24);
    GPIOCALTFN0 |= (1 << 24);

    //2.配置为输出功能
    GPIOCOUTENB |= (1 << 12);
}

//开灯函数定义
void led_on(void)
{
    GPIOCOUT &= ~(1 << 12);
}

//关灯函数定义
void led_off(void)
{
    GPIOCOUT |= (1 << 12);
}

//延时函数
void delay(int n)
{
    int i = n;
    for(; i != 0; i--);
}











    

                                  

2、上位机开始编辑编译LED的裸板程序

上位机的操作步骤如下:

    1)上位机添加部署交叉编译器

"交叉编译器":本身运行在上位机,而它编译出来的二进制文件运行在下位机

获取交叉编译器:resource.rar/编译器/arm-cortex_a9-eabi-4.7-eglibc-2.18.tar.gz

sudo chown baby/opt -R

sudo chgrp baby /opt -R

cp arm-cortex_a9-eabi-4.7-eglibc-2.18.tar.gz /opt/

cd /opt/

tar -xvf arm-cortex_a9-eabi-4.7-eglibc-2.18.tar.gz

ls

arm-cortex_a9-eabi-4.7-eglibc-2.18 //交叉编译器目录

mv arm-cortex_a9-eabi-4.7-eglibc-2.18 toolchains

sudo vim /etc/environment //打开此文件,添加交叉编译器的路径

PATH="/opt/toolchains/bin:..." //在PATH中添加交叉编译器的路径

保存退出

重启上位机linux系统

验证交叉编译器,上位机执行:

arm-cortex_a9-linux-gnueabi-gcc -v //查看交叉编译器是否正常运行和查看版本

                 

2)编辑,交叉编译LED裸板程序    

mkdir /opt/arm/03/1.0 -p

cd /opt/arm/day03/1.0

vim led.h

vim led.c

arm-cortex_a9-linux-gnueabi-gcc -nostdlib -c -o led.o led.c

说明:

-nostdlib:由于此程序led.c为裸板程序,不允许使用标准C库的内容

添加-nostdlib告诉编译器不会使用标准C库的内容

-c:只编译不链接

            

arm-cortex_a9-linux-gnueabi-ld -nostartfiles -nostdlib -Ttext=0x48000000-o led.elf led.o

说明:

arm...ld:链接器

-nostartfiles:链接时无需链接启动文件

-nostdlib:不允许使用标准C库的内容

-Ttext:代码段

-Tdata:数据段

-Ttext=0x48000000:指定代码段的起始地址为0x480000000(下位机内存的地址)

led.elf:生成ELF格式的二进制文件,但是ELF格式的二进制文件只能运行在操作系统下

            

arm-cortex_a9-linux-gnueabi-objcopy -O binary led.elf led.bin

说明:

arm...objcopy:将ELF格式的二进制文件生成对应的纯正的二进制文件

例如:

led.elf:整个橘子

led.bin:果肉

objcopy:去皮工具

led.bin:纯正的二进制文件可以运行在裸板上

                                                                         

cp led.bin /tftpboot  //拷贝tftp服务的下载目录

     

下位机测试:

重启下位机,进入uboot的命令行模式,执行:

tftp 0x48000000 led.bin

go 0x48000000 //观察灯的闪烁

     

vim操作技巧:

左右分屏:vs 文件名

上下分屏:sp 文件名

屏幕切换:ctrl +ww

一个终端中创建子终端:ctrl+shift+t

终端切换:alt+终端的编号

建议:一个终端编辑保存代码(不用退出),另一个终端编译代码

     

案例:反汇编裸板代码

上位机实施步骤:

cd /opt/arm/03/1.0

arm-cortex_a9-linux-gnueabi-objdump -D led.elf > led.dis

说明:

arm-cortex_a9-linux-gnueabi-objdump:反汇编命令,将elf可执行文件生成对应的汇编文件

led.elf:反汇编的二进制文件

led.dis:反汇编以后的汇编文件

     

vim led.dis //打开反汇编文件

目前只需看一条信息即可:

48000000 <led_test>: //led_test函数对应的地址为0x48000000

每次go0x48000000:让CPU跑到0x48000000运行,本质就是让CPU执行led_test函数

//继续验证反汇编

cd /opt/arm/03/1.0

vim led.c //将delay函数的定义放在led_test函数定义的前面

保存退出

arm-cortex_a9-linux-gnueabi-gcc -nostdlib -c -o led.o led.c

arm-cortex_a9-linux-gnueabi-ld -nostartfiles -nostdlib-Ttext=0x48000000 -o led.elf led.o

arm-cortex_a9-linux-gnueabi-objdump -D led.elf > led.dis

 

vim led.dis

获得以下信息

48000000 <delay>: //0x48000000这个地址对应的函数为delay函数

也就是将来go0x48000000,是让CPU执行delay函数

结论:链接(ld)的时候从文件的开头开始链接!

切记:将来最好用objdump反汇编确保入口函数的地址是否是0x48000000

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值