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"
);
審核編輯:湯梓紅
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。
舉報投訴
-
嵌入式
+關注
關注
5072文章
19026瀏覽量
303517 -
Linux
+關注
關注
87文章
11232瀏覽量
208952 -
Uboot
+關注
關注
4文章
125瀏覽量
28168
發布評論請先 登錄
相關推薦
嵌入式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
?3830次閱讀
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
?875次閱讀
【嵌入式】構建嵌入式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,作用是用來引導操作系統,以及給開發人員提供測試調試工具。主要負責基本硬件初始化,導啟動內核啟動
評論