1. 前言
U-Boot 是一个主要用于嵌入式系统的引导加载程序,可以支持多种不同的计算机系统结构。
U-Boot的命令为用户提供了交互功能,并且已经实现了几十个常用的命令,前面两篇文章介绍了uboot自带的常用命令使用。
如果开发板需要很特殊的操作,可以添加新的U-Boot命令。U-Boot的每一个命令都是通过U_Boot_CMD宏定义的。
这个宏在头文件中定义。
#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \
cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage}
复制代码
参数介绍:
name:命令的名字,他不是一个字符串,不能用双引号括起来
maxargs:最大的参数个数
command:对应的函数指针
usage:一个字符串,简短的使用说明
help:一个字符串,比较详细的使用说明
UBOOT命令文件命名规则:cmd_xxx.c
复制代码
将写好的命令.c文件放入UBOOT源码顶层的/common目录下,并且修改Makefile文件,将加入的.c文件添加到编译选项中。
在Makefile文件大约50行出进行添加即可:
格式:COBJS-y += cmd_xxx.o
复制代码
添加完毕,回到uboot顶层目录下,重新生成u-boot.bin文件,再下载到开发板测试。
2. 自定义UBOOT命令代码
2.1 编写蜂鸣器控制命令
#include
#include
#define GPD0CON (*(volatile unsigned int *)0x114000A0) //定义蜂鸣器IO口的地址
#define GPD0DAT (*(volatile unsigned int *)0x114000A4)
int do_beep( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
GPD0CON&=~(0xf<<0);
GPD0CON|=(0x1<<0);
if(!strcmp(argv[1],"on")) //strcmp是比较字符串的函数,如果传进来的是on,就打开蜂鸣器
{
GPD0DAT|=(1<<0);
}
if(!strcmp(argv[1],"off"))//strcmp是比较字符串的函数,如果传进来的是off,就关闭蜂鸣器
{
GPD0DAT&=~(1<<0);
}
else
printf("Usage:beep !\n"); //如果不是on 也不是off 就输出提示
}
U_BOOT_CMD(
beep, //在u-boot命令行里显示的命令名称
2, //形参最大个数
1, //重复次数 (按下回车--自动执行上一次命令)
do_beep, //命令执行函数(回调函数--)
"传参格式: beep ", //用法提示
"传承示例:beep on 或者 beep off......." //帮助命令的提示信息
);
复制代码|off>|off>
2.2 编写LED灯控制命令
#include
#include
/* 1、LED灯接口配置寄存器 */
#define GPM4CON (*(volatile unsigned int *)0x110002E0)
#define GPM4DAT (*(volatile unsigned int *)0x110002E4)
int do_led(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
// led 1 on
// led 1 off
GPM4CON &= ~(0xf << 0 * 4); //清除寄存器1
GPM4CON |= (1 << 0 * 4); //输出模式
GPM4CON &= ~(0xf << 1 * 4); //清除寄存器2
GPM4CON |= (1 << 1 * 4); //输出模式
GPM4CON &= ~(0xf << 2 * 4); //清除寄存器3
GPM4CON |= (1 << 2 * 4); //输出模式
GPM4CON &= ~(0xf << 3 * 4); //清除寄存器4
GPM4CON |= (1 << 3 * 4); //输出模式
/*第一盏灯*/
if(!strcmp(argv[1],"1")) //strcmp是比较字符串的函数,如果传进来的是on,就打开蜂鸣器
{
if(!strcmp(argv[2],"on"))
{
GPM4DAT &= ~(1 << 0); //点亮第一个灯
}
else if(!strcmp(argv[2],"off"))
{
GPM4DAT |=1 << 0; //关闭第一个灯
}
}
/*第二盏灯*/
else if(!strcmp(argv[1],"2")) //strcmp是比较字符串的函数,如果传进来的是on,就打开蜂鸣器
{
if(!strcmp(argv[2],"on"))
{
GPM4DAT &= ~(1 << 1); //点亮第二个灯
}
else if(!strcmp(argv[2],"off"))
{
GPM4DAT |=1 << 1; //关闭第二个灯
}
}
/*第三盏灯*/
else if(!strcmp(argv[1],"3")) //strcmp是比较字符串的函数,如果传进来的是on,就打开蜂鸣器
{
if(!strcmp(argv[2],"on"))
{
GPM4DAT &= ~(1 << 2); //点亮第三个灯
}
else if(!strcmp(argv[2],"off"))
{
GPM4DAT |=1 << 2; //关闭第三个灯
}
}
/*第四盏灯*/
else if(!strcmp(argv[1],"4")) //strcmp是比较字符串的函数,如果传进来的是on,就打开蜂鸣器
{
if(!strcmp(argv[2],"on"))
{
GPM4DAT &= ~(1 << 3); //点亮第四个灯
}
else if(!strcmp(argv[2],"off"))
{
GPM4DAT |=1 << 3; //关闭第四个灯
}
}
else
printf("Usage:led <1~4> \n"); //如果不是on 也不是off 就输出提示
}
U_BOOT_CMD(
led, //在u-boot命令行里显示的命令名称
3, //形参最大个数
1, //重复次数
do_led, //命令执行函数
"user: LED count ", //用法提示
"cmd : (1)led 1 on (2)led 1 off...." //帮助命令的提示信息
);
复制代码|off>|off>
2.3 设计自己的movi命令
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int do_mymovi(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
{
int r_cnt,w_cnt;
/*1. 查找设备0-SD卡*/
struct mmc *mmc0 = find_mmc_device(0);
if(mmc0==NULL)
{
printf("设备0查找失败!\n");
return 0;
}
/*2. 查找设备1--MMC*/
struct mmc *mmc1 = find_mmc_device(1);
if(mmc1==NULL)
{
printf("设备1查找失败!\n");
return 0;
}
/*3. 初始化SD卡*/
mmc_init(mmc0); /*设备0初始化--SD卡*/
/*4. 初始化EMMC*/
mmc_init(mmc1); /*设备1初始化--EMMC卡*/
emmc_boot_open(mmc1); /*设备1打开---EMMC*/
/*5. 烧写数据*/
/*5.1 BL1*/
r_cnt=movi_read(0,1,16,(void*)0x40008000); //读出SD卡里存放到所有数据到DDR指定地址
w_cnt=movi_write(1,0,16,(void*)0x40008000);//将读出的数据写入到EMMC
printf("BL1_r_cnt=%d\n",r_cnt);
printf("BL1_w_cnt=%d\n",w_cnt);
/*5.2 BL2*/
r_cnt=movi_read(0,17,32,(void*)0x40008000); //读出SD卡里存放到所有数据到DDR指定地址
w_cnt=movi_write(1,16,32,(void*)0x40008000);//将读出的数据写入到EMMC
printf("BL2_r_cnt=%d\n",r_cnt);
printf("BL2_w_cnt=%d\n",w_cnt);
/*5.3 UBOOT\这里最好使用malloc申请空间,太大的地址可能会被其他数据覆盖掉*/
r_cnt=movi_read(0,49,656,(void*)0x40008000); //读出SD卡里存放到所有数据到DDR指定地址
w_cnt=movi_write(1,48,656,(void*)0x40008000);//将读出的数据写入到EMMC
printf("UBOOT_r_cnt=%d\n",r_cnt);
printf("UBOOT_w_cnt=%d\n",w_cnt);
/*5.4 TZSW*/
r_cnt=movi_read(0,705,320,(void*)0x40008000); //读出SD卡里存放到所有数据到DDR指定地址
w_cnt=movi_write(1,704,320,(void*)0x40008000);//将读出的数据写入到EMMC
printf("TZSW_r_cnt=%d\n",r_cnt);
printf("TZSW_w_cnt=%d\n",w_cnt);
/*5.5 Linux内核*/
r_cnt=movi_read(0,1057,12288,(void*)0x40008000); //读出SD卡里存放到所有数据到DDR指定地址
w_cnt=movi_write(1,1057,12288,(void*)0x40008000);//将读出的数据写入到EMMC
printf("Linux内核_r_cnt=%d\n",r_cnt);
printf("Linux内核_w_cnt=%d\n",w_cnt);
emmc_boot_close(mmc1); //关闭EMMC
/*5.5 环境变量*/
r_cnt=movi_read(0,1025,32,(void*)0x40008000); //读出SD卡里存放到所有数据到DDR指定地址
w_cnt=movi_write(1,1025,32,(void*)0x40008000);//将读出的数据写入到EMMC
printf("环境变量_r_cnt=%d\n",r_cnt);
printf("环境变量_w_cnt=%d\n",w_cnt);
printf("环境变量拷贝成功!\n");
return 0;
}
U_BOOT_CMD(
mymovi, /*命令的名称*/
1, /*形参的最大个数*/
0, /*命令执行重复次数*/
do_mymovi,/*命令处理函数*/
"将SD卡的BL1/BL2/uboot/签名文件/内核拷贝到EMMC", /*简短提示*/
"\n"
"将SD卡的BL1/BL2/uboot/签名文件/内核拷贝到EMMC\n" /*完整提示*/
"注意: 该命令在开发板以SD卡启动方式时运用\n"
);
复制代码
2.4 设计环境变量拷贝命令
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/*
//以MMC方式启动,运行下面命令即可完成环境变量拷贝(SD-->EMMC)
mmc read 1 40000000 401 20
mmc write 0 40000000 401 20
//以SD方式启动,运行下面命令即可完成环境变量拷贝 (SD--->EMMC)
mmc read 0 40000000 401 20
mmc write 1 40000000 401 20
*/
int do_copyenv(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
{
int r_cnt,w_cnt;
mmc_init(find_mmc_device(0)); /*设备0初始化--SD卡*/
mmc_init(find_mmc_device(1)); /*设备1初始化--EMMC卡*/
/*5.5 环境变量*/
r_cnt=movi_read(0,1025,32,(void*)0x40000000); //读出SD卡里存放到所有数据到DDR指定地址
w_cnt=movi_write(1,1025,32,(void*)0x40000000);//将读出的数据写入到EMMC
printf("环境变量_r_cnt=%d\n",r_cnt);
printf("环境变量_w_cnt=%d\n",w_cnt);
printf("环境变量拷贝成功!\n");
return 0;
}
U_BOOT_CMD(
copyenv, /*命令的名称*/
1, /*形参的最大个数*/
0, /*命令执行重复次数*/
do_copyenv,/*命令处理函数*/
"将SD卡的环境变量拷贝到EMMC", /*简短提示*/
"\n"
"将SD卡的环境变量拷贝到EMMC\n" /*完整提示*/
"注意: 该命令在开发板以SD卡启动方式时运用\n"
);
审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。
举报投诉
-
嵌入式
+关注
关注
5082文章
19104浏览量
304779 -
Linux
+关注
关注
87文章
11292浏览量
209317 -
Uboot
+关注
关注
4文章
125浏览量
28213
发布评论请先 登录
相关推荐
嵌入式Linux学习引导-Uboot移植之添加自定义命令
。但是,根据某些开发板的特殊操作和用户的特定需求,还是不得不在uboot中,添加一些供自己调试和开发的命令,这样会更方便快捷的开展工作。本文将用实例为大家介绍如何为
发表于 02-16 17:19
嵌入式开发中自定义协议的解析与组包相关案例分享
1、嵌入式开发中自定义协议的解析与组包 在嵌入式产品开发中,经常会遇到两个设备之间的通信、设备与服务器的通信、设备和上位机的通信等,很多时候通信协议都是
发表于 10-27 17:01
Zybo全栈开发入门教程(基于Linux嵌入式系统):10个步骤自定义IP模块
可以说zybo是mini-zedboard。Zybo全栈开发教程共分为三部分:自定义IP、移植Linux操作系统、编写驱动模块和应用。通过这三部分你将能够全面熟悉Zynq AP SoC
发表于 11-10 14:49
•3848次阅读
AM335x如何在Uboot时增加自定义的命令控制LCD功能中文概述
图片生成十六进制的数据数组四. 在新版本的processor SDK v3.0中,在uboot阶段如何实现增加LCD logo的显示五. 基于第四点内容,增加Uboot的命令,效果是在Uboo
发表于 04-23 17:09
•10次下载
英创信息技术嵌入式Linux工控主板uboot命令简介
成都英利公司提供的EM9X60系列嵌入式Linux工控主板,均预装了Linux2.6.30内核操作系统及根文件系统,包括bootstrap、uboot、uImage及根文件系统,用户可
基于嵌入式中央处理单元(CPU)的自定义指令
Arm启用了用于嵌入式中央处理单元(CPU)的自定义指令,以在不断变化的世界中为芯片制造商提供更大的灵活性。新的自定义说明将使那些获得Arm架构许可并设计自己的芯片的合作伙伴能够将其片上系统(SoC)产品与
发表于 10-09 14:19
•889次阅读
【嵌入式】构建嵌入式Linux系统(uboot、内核、文件系统)
嵌入式Linux系统知识架构及层次嵌入式Linux系统构成及启动略析嵌入式Linux三剑客之
发表于 10-20 18:20
•42次下载
嵌入式Linux开发教程:Linux常见命令(上篇)
摘要:这是对周立功编著的《嵌入式Linux开发教程》的第7期连载。本期刊载内容有关LinuxLinux常见命令中的导航命令、目录
发表于 10-21 13:36
•11次下载
嵌入式开发中自定义协议的解析与组包
在嵌入式产品开发中,经常会遇到两个设备之间的通信、设备与服务器的通信、设备和上位机的通信等,很多时候通信协议都是自定义的,所以...
发表于 01-25 11:14
•5次下载
uboot自定义命令
U-Boot本质是一个裸机程序,是一种普遍用于嵌入式系统中的开源的Bootloader,作用是用来引导操作系统,以及给开发人员提供测试调试工具。主要负责基本硬件初始化,导启动内核启动
评论