0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

嵌入式Linux開發(fā)-編寫自定義uboot命令

DS小龍哥-嵌入式技術 ? 來源:DS小龍哥-嵌入式技術 ? 作者:DS小龍哥-嵌入式技 ? 2022-08-14 08:56 ? 次閱讀

1. 前言

U-Boot 是一個主要用于嵌入式系統(tǒng)的引導加載程序,可以支持多種不同的計算機系統(tǒng)結構。

U-Boot的命令為用戶提供了交互功能,并且已經實現(xiàn)了幾十個常用的命令,前面兩篇文章介紹了uboot自帶的常用命令使用。

如果開發(fā)板需要很特殊的操作,可以添加新的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}
復制代碼

參數(shù)介紹:

name:命令的名字,他不是一個字符串,不能用雙引號括起來
maxargs:最大的參數(shù)個數(shù)
command:對應的函數(shù)指針
usage:一個字符串,簡短的使用說明
help:一個字符串,比較詳細的使用說明
UBOOT命令文件命名規(guī)則:cmd_xxx.c
復制代碼

將寫好的命令.c文件放入UBOOT源碼頂層的/common目錄下,并且修改Makefile文件,將加入的.c文件添加到編譯選項中。

在Makefile文件大約50行出進行添加即可:

格式:COBJS-y += cmd_xxx.o
復制代碼

添加完畢,回到uboot頂層目錄下,重新生成u-boot.bin文件,再下載到開發(fā)板測試。

image-20220124142634948

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是比較字符串的函數(shù),如果傳進來的是on,就打開蜂鳴器
?        {
?            GPD0DAT|=(1<<0);    
?        }
?    if(!strcmp(argv[1],"off"))//strcmp是比較字符串的函數(shù),如果傳進來的是off,就關閉蜂鳴器
?        {
?            GPD0DAT&=~(1<<0);   
?        }
?    else
?        printf("Usage:beep !\n"); //如果不是on 也不是off  就輸出提示
?}
??
??
?U_BOOT_CMD( 
?    beep, ? ?//在u-boot命令行里顯示的命令名稱
?    2, ? ? ? //形參最大個數(shù)
?    1, ? ? ? //重復次數(shù) (按下回車--自動執(zhí)行上一次命令)
?    do_beep, //命令執(zhí)行函數(shù)(回調函數(shù)--)
?    "傳參格式: 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是比較字符串的函數(shù),如果傳進來的是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是比較字符串的函數(shù),如果傳進來的是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是比較字符串的函數(shù),如果傳進來的是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是比較字符串的函數(shù),如果傳進來的是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,    //形參最大個數(shù)
    1,    //重復次數(shù)
    do_led, //命令執(zhí)行函數(shù)
    "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. 燒寫數(shù)據(jù)*/
        /*5.1 BL1*/
        r_cnt=movi_read(0,1,16,(void*)0x40008000); //讀出SD卡里存放到所有數(shù)據(jù)到DDR指定地址
        w_cnt=movi_write(1,0,16,(void*)0x40008000);//將讀出的數(shù)據(jù)寫入到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卡里存放到所有數(shù)據(jù)到DDR指定地址
        w_cnt=movi_write(1,16,32,(void*)0x40008000);//將讀出的數(shù)據(jù)寫入到EMMC
        printf("BL2_r_cnt=%d\n",r_cnt);
        printf("BL2_w_cnt=%d\n",w_cnt);
?
     /*5.3 UBOOT\這里最好使用malloc申請空間,太大的地址可能會被其他數(shù)據(jù)覆蓋掉*/
        r_cnt=movi_read(0,49,656,(void*)0x40008000); //讀出SD卡里存放到所有數(shù)據(jù)到DDR指定地址
        w_cnt=movi_write(1,48,656,(void*)0x40008000);//將讀出的數(shù)據(jù)寫入到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卡里存放到所有數(shù)據(jù)到DDR指定地址
        w_cnt=movi_write(1,704,320,(void*)0x40008000);//將讀出的數(shù)據(jù)寫入到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卡里存放到所有數(shù)據(jù)到DDR指定地址
        w_cnt=movi_write(1,1057,12288,(void*)0x40008000);//將讀出的數(shù)據(jù)寫入到EMMC
        printf("Linux內核_r_cnt=%d\n",r_cnt);
        printf("Linux內核_w_cnt=%d\n",w_cnt);
    emmc_boot_close(mmc1); //關閉EMMC
    
    /*5.5 環(huán)境變量*/
    r_cnt=movi_read(0,1025,32,(void*)0x40008000); //讀出SD卡里存放到所有數(shù)據(jù)到DDR指定地址
    w_cnt=movi_write(1,1025,32,(void*)0x40008000);//將讀出的數(shù)據(jù)寫入到EMMC
    printf("環(huán)境變量_r_cnt=%d\n",r_cnt);
    printf("環(huán)境變量_w_cnt=%d\n",w_cnt);
    printf("環(huán)境變量拷貝成功!\n");
    return 0;
}
?
U_BOOT_CMD(
    mymovi,  /*命令的名稱*/
    1,     /*形參的最大個數(shù)*/
    0,     /*命令執(zhí)行重復次數(shù)*/
    do_mymovi,/*命令處理函數(shù)*/
    "將SD卡的BL1/BL2/uboot/簽名文件/內核拷貝到EMMC", /*簡短提示*/
    "\n"
    "將SD卡的BL1/BL2/uboot/簽名文件/內核拷貝到EMMC\n" /*完整提示*/
    "注意: 該命令在開發(fā)板以SD卡啟動方式時運用\n"
);
復制代碼

2.4 設計環(huán)境變量拷貝命令

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
?
/*
//以MMC方式啟動,運行下面命令即可完成環(huán)境變量拷貝(SD-->EMMC)
mmc read 1 40000000 401 20
mmc write 0 40000000 401 20
?
//以SD方式啟動,運行下面命令即可完成環(huán)境變量拷貝 (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 環(huán)境變量*/
    r_cnt=movi_read(0,1025,32,(void*)0x40000000); //讀出SD卡里存放到所有數(shù)據(jù)到DDR指定地址
    w_cnt=movi_write(1,1025,32,(void*)0x40000000);//將讀出的數(shù)據(jù)寫入到EMMC
    printf("環(huán)境變量_r_cnt=%d\n",r_cnt);
    printf("環(huán)境變量_w_cnt=%d\n",w_cnt);
    printf("環(huán)境變量拷貝成功!\n");
    return 0;
}
?
?
U_BOOT_CMD(
    copyenv,  /*命令的名稱*/
    1,     /*形參的最大個數(shù)*/
    0,     /*命令執(zhí)行重復次數(shù)*/
    do_copyenv,/*命令處理函數(shù)*/
    "將SD卡的環(huán)境變量拷貝到EMMC", /*簡短提示*/
    "\n"
    "將SD卡的環(huán)境變量拷貝到EMMC\n" /*完整提示*/
    "注意: 該命令在開發(fā)板以SD卡啟動方式時運用\n"
);

審核編輯:湯梓紅

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 嵌入式
    +關注

    關注

    5045

    文章

    18817

    瀏覽量

    298477
  • Linux
    +關注

    關注

    87

    文章

    11123

    瀏覽量

    207900
  • Uboot
    +關注

    關注

    4

    文章

    124

    瀏覽量

    28053
收藏 人收藏

    評論

    相關推薦

    嵌入式Linux學習引導-Uboot移植之添加自定義命令

    。但是,根據(jù)某些開發(fā)板的特殊操作和用戶的特定需求,還是不得不在uboot中,添加一些供自己調試和開發(fā)命令,這樣會更方便快捷的開展工作。本文將用實例為大家介紹如何為
    發(fā)表于 02-16 17:19

    嵌入式開發(fā)自定義協(xié)議的解析與組包相關案例分享

    1、嵌入式開發(fā)自定義協(xié)議的解析與組包  在嵌入式產品開發(fā)中,經常會遇到兩個設備之間的通信、設備與服務器的通信、設備和上位機的通信等,很多時候通信協(xié)議都是
    發(fā)表于 10-27 17:01

    Zybo全棧開發(fā)入門教程(基于Linux嵌入式系統(tǒng)):10個步驟自定義IP模塊

    可以說zybo是mini-zedboard。Zybo全棧開發(fā)教程共分為三部分:自定義IP、移植Linux操作系統(tǒng)、編寫驅動模塊和應用。通過這三部分你將能夠全面熟悉Zynq AP SoC
    發(fā)表于 11-10 14:49 ?3716次閱讀
    Zybo全棧<b class='flag-5'>開發(fā)</b>入門教程(基于<b class='flag-5'>Linux</b><b class='flag-5'>嵌入式</b>系統(tǒng)):10個步驟<b class='flag-5'>自定義</b>IP模塊

    AVR編寫1602自定義字符

    AVR編寫自定義字符不錯的練習題目
    發(fā)表于 03-20 14:21 ?1次下載

    基于linux自定義一個腳本來替代rm命令

    linux下的rm命令,功能太強,同時又沒法撤消,為了避免誤操作,可以自定義一個腳本來替代rm命令。
    的頭像 發(fā)表于 02-01 18:08 ?3662次閱讀
    基于<b class='flag-5'>linux</b>下<b class='flag-5'>自定義</b>一個腳本來替代rm<b class='flag-5'>命令</b>

    AM335x如何在Uboot時增加自定義命令控制LCD功能中文概述

    圖片生成十六進制的數(shù)據(jù)數(shù)組四. 在新版本的processor SDK v3.0中,在uboot階段如何實現(xiàn)增加LCD logo的顯示五. 基于第四點內容,增加Uboot命令,效果是在Uboo
    發(fā)表于 04-23 17:09 ?10次下載
    AM335x如何在<b class='flag-5'>Uboot</b>時增加<b class='flag-5'>自定義</b>的<b class='flag-5'>命令</b>控制LCD功能中文概述

    英創(chuàng)信息技術嵌入式Linux工控主板uboot命令簡介

    成都英利公司提供的EM9X60系列嵌入式Linux工控主板,均預裝了Linux2.6.30內核操作系統(tǒng)及根文件系統(tǒng),包括bootstrap、uboot、uImage及根文件系統(tǒng),用戶可
    的頭像 發(fā)表于 01-15 14:01 ?1284次閱讀
    英創(chuàng)信息技術<b class='flag-5'>嵌入式</b><b class='flag-5'>Linux</b>工控主板<b class='flag-5'>uboot</b><b class='flag-5'>命令</b>簡介

    基于嵌入式中央處理單元(CPU)的自定義指令

    Arm啟用了用于嵌入式中央處理單元(CPU)的自定義指令,以在不斷變化的世界中為芯片制造商提供更大的靈活性。新的自定義說明將使那些獲得Arm架構許可并設計自己的芯片的合作伙伴能夠將其片上系統(tǒng)(SoC)產品與
    發(fā)表于 10-09 14:19 ?828次閱讀

    嵌入式】構建嵌入式Linux系統(tǒng)(uboot、內核、文件系統(tǒng))

    嵌入式Linux系統(tǒng)知識架構及層次嵌入式Linux系統(tǒng)構成及啟動略析嵌入式Linux三劍客之
    發(fā)表于 10-20 18:20 ?41次下載
    【<b class='flag-5'>嵌入式</b>】構建<b class='flag-5'>嵌入式</b><b class='flag-5'>Linux</b>系統(tǒng)(<b class='flag-5'>uboot</b>、內核、文件系統(tǒng))

    嵌入式Linux開發(fā)教程:Linux常見命令(上篇)

    摘要:這是對周立功編著的《嵌入式Linux開發(fā)教程》的第7期連載。本期刊載內容有關LinuxLinux常見命令中的導航命令、目錄
    發(fā)表于 10-21 13:36 ?11次下載
    <b class='flag-5'>嵌入式</b><b class='flag-5'>Linux</b><b class='flag-5'>開發(fā)</b>教程:<b class='flag-5'>Linux</b>常見<b class='flag-5'>命令</b>(上篇)

    嵌入式linux開發(fā)的學習之路

    嵌入式linux開發(fā)的學習之路linux操作系統(tǒng)的基本使用以及常見指令;linux環(huán)境下的c語言編寫
    發(fā)表于 11-01 17:59 ?15次下載
    <b class='flag-5'>嵌入式</b><b class='flag-5'>linux</b><b class='flag-5'>開發(fā)</b>的學習之路

    嵌入式linux學習 Day1 uboot基礎

    嵌入式linux學習 Day1 uboot基礎
    發(fā)表于 12-05 20:51 ?7次下載
    <b class='flag-5'>嵌入式</b><b class='flag-5'>linux</b>學習 Day1 <b class='flag-5'>uboot</b>基礎

    嵌入式開發(fā)自定義協(xié)議的解析與組包

    嵌入式產品開發(fā)中,經常會遇到兩個設備之間的通信、設備與服務器的通信、設備和上位機的通信等,很多時候通信協(xié)議都是自定義的,所以...
    發(fā)表于 01-25 11:14 ?5次下載
    <b class='flag-5'>嵌入式開發(fā)</b>中<b class='flag-5'>自定義</b>協(xié)議的解析與組包

    uboot自定義命令

    U-Boot本質是一個裸機程序,是一種普遍用于嵌入式系統(tǒng)中的開源的Bootloader,作用是用來引導操作系統(tǒng),以及給開發(fā)人員提供測試調試工具。主要負責基本硬件初始化,導啟動內核啟動
    的頭像 發(fā)表于 09-17 09:59 ?1107次閱讀

    一個小而巧的自定義嵌入式軟件通信協(xié)議

    嵌入式開發(fā)中,常常會自定義一些協(xié)議格式,比如用于板與板之間的通信、客戶端與服務端之間的通信等。
    的頭像 發(fā)表于 04-21 09:16 ?761次閱讀