将UBOOT命令行功能移植到STM32F407

2019-07-20 08:12发布

本帖最后由 屋脊雀 于 2018-5-15 11:03 编辑

今天开始移植uboot中的命令行功能到STM32上,使用的是MDK(KEIL)编译器。
其实以前移植过一次,平台是K21+IAR。由于代码中有部分与编译器有关,折腾了半天才实现。特地记录。
UBOOT CMDUBOOT CMD的代码中,有一个比较特殊的定义。
命令的定义通过一个宏声明一个结构体,这个结构体如下
  • #define REGISTER_CMD(name,maxargs,rep,cmd,usage,help)       __root  const cmd_tbl_t strcmd_##name @ ".cmd" =  {#name, maxargs, rep, cmd, usage,help}

[color=rgb(51, 102, 153) !important]复制代码


我们先分析这个宏的功能
- __root:
被修饰的变量或者函数在用户程序里面没有显式调用情况下,也不会被优化掉。
- const:
这个大家应该常用,就是将变量定义为常量,保存在FLASH,不占用RAM。
- cmd_tbl_t:
结构体定义
- strcmd_##name:
宏名字,例如宏第一个参数是test,编译后得结构体名字就是strcmd__test
- @ ".cmd":
定义的结构体保存在.cmd段,这个段是在IAR工程的.icf文件中定义。
剩下的就是赋值给结构体了。这样定义的结果就是:
定义了一个放在.cmd段的结构体,就算这个结构体没有显式调用,也不会被程序优化。
MDK(KEIL)定义那么在MDK下要怎么定义呢?
- 首先是如下,通过attribute 关键字将结构体放到cmd段中。
  • #define REGISTER_CMD(name,maxargs,rep,cmd,usage,help)             const cmd_tbl_t strcmd_##name __attribute__ ((section ("cmd"))) =  {#name, maxargs, rep, cmd, usage,help}

[color=rgb(51, 102, 153) !important]复制代码


  • 第二,就是要使用自定义的分散加载文件

    把左上角的use memory layout from target Dialog前面的勾去掉。
    然后点击右边中间的Edit按钮,关掉窗口,就可以编辑.sct文件了。

  • LR_IROM1 0x08000000 0x00100000  {    ; load region size_region
  •   ER_IROM1 0x08000000 0x000ff000  {  ; load address = execution address
  •    *.o (RESET, +First)
  •    *(InRoot$Sections)
  •    .ANY (+RO)
  •   }
  •   cmdreg +0
  •   {
  •         .ANY(cmd)
  •   }
  •   RW_IRAM1 0x20000000 0x00020000  {  ; RW data
  •    .ANY (+RW +ZI)
  •   }
  • }

[color=rgb(51, 102, 153) !important]复制代码



中间一段就是增加的
cmdreg区域名字。
+0的意思是紧跟着其他代码段。
.ANY(cmd) 这个比较关键,跟代码中的(section ("cmd"))对应。
也可以指定这个段的起始地址跟长度
cmdreg 0x080ff000 0x1000
{
.ANY(cmd)
}
  • 第三,就是要防止这些变量被优化
    在option中设置

    看下面,Misc controls中,添加一个宏“--keep=strcmd_*”,意思是所有strcmd_开头的变量跟函数,都不会被优化。
确认结果编译后,查看.map文件(通常在工程下的Listings文件夹下)
  • Execution Region cmdreg (Exec base: 0x08048efc, Load base: 0x08048efc, Size: 0x000000a8, Max: 0xffffffff, ABSOLUTE)
  • Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object
  • 0x08048efc   0x08048efc   0x0000001c   Data   RO        16605    cmd                 cmd_sys.o
  • 0x08048f18   0x08048f18   0x0000001c   Data   RO        16606    cmd                 cmd_sys.o
  • 0x08048f34   0x08048f34   0x0000001c   Data   RO        16607    cmd                 cmd_sys.o
  • 0x08048f50   0x08048f50   0x0000001c   Data   RO        16608    cmd                 cmd_sys.o
  • 0x08048f6c   0x08048f6c   0x0000001c   Data   RO        16685    cmd                 commnad.o
  • 0x08048f88   0x08048f88   0x0000001c   Data   RO        16686    cmd                 commnad.o

[color=rgb(51, 102, 153) !important]复制代码


从中也可以看到我们前面定义的意思
cmdreg是Execution Region名字
Base: 0x080ff000, Size: 0x000000a8, Max: 0x00001000
我们现在只用了0x000000a8字节
cmd 是E Section Name
代码中使用段地址跟长度好的,前面我们已经定义了一个命令段,那代码中怎么用这个段呢?
像下面这样使用即可。
  • extern unsigned char Load$cmdreg$Base[];
  • extern unsigned char Load$cmdreg$Length[];
  • unsigned long add = (unsigned long)Load$cmdreg$Base;
  • unsigned long len = (unsigned long)Load$cmdreg$Length;
  •         uart_printf("cmd addr:%08x, limit:%08x ", add, len);

[color=rgb(51, 102, 153) !important]复制代码


在网上查找如何引用段地址时,找到了这个网页:
https://www.cnblogs.com/Dreamxi/p/3507932.html
大家可以参考这个网页的做法。
问题--keep是在MDK设置中定义,能不能直接在代码中定义?
--keep=cmd_*会有匹问题,如果以后其他模块定义类似的变量或者函数,就同样不会被优化了。
能不能在代码中直接指定不优化的内容?不使用通配符。
不管了,暂时能用先。
通过shell交互安装Xshell 5软件,配置一个串口链接。

系统启动后,敲下回车,出现命令行,输入help,查看有多少命令。
输入命令systeminfo,查看系统信息。
增加命令可以随意添加命令,按照下面的个是注册命令就可以了,REGISTER_CMD(    systeminfo,2,1,do_system_info,    "systeminfo",    " display system info ");说明
  • 1
    本次测试命令行基于freertos。
    因为命令行程序内部是while(1)死循环,如果没有操作系统任务调度,很难实现。
    除非只有命令行功能,并且其他功能全部通过命令行调用或者是中断。
  • 2
    代码托管在github:https://github.com/wujique/stm32f407/tree/sw_arch
总结本文档指说明了移植过在MDK的细节,对于UBOOT命令行的具体实现,有兴趣自行研究。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。