vivado使用的编译器是gcc,因此zynq的链接脚本如同其他使用gcc编译的项目一样。这里使用u-boot的链接脚本为例,简单描述怎么使用链接脚本增加cli的功能。
这里不描述链接脚本的语法等内容。
在u-boot中,使用频率颇高的宏类似:
U_BOOT_CMD(
bootm, CONFIG_SYS_MAXARGS, 1, do_bootm,
"boot application image from memory", bootm_help_text
);
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}
#define Struct_Section __attribute__ ((unused,section (".u_boot_cmd")))
struct cmd_tbl_s {
char *name; /* Command Name */
int maxargs; /* maximum number of arguments */
int repeatable; /* autorepeat allowed? */
/* Implementation function */
int (*cmd)(struct cmd_tbl_s *, int, int, char *[]);
char *usage; /* Usage message (short) */
};
可知, U_BOOT_CMD展开后即是cmd_tbl_s 结构体, 名称是__u_boot_cmd_xxx,而他指定的链接段是
".u_boot_cmd"
在u-boot链接脚本里面有如下一段
. = .;
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .;
由此可知,对于链接在.u_boot_cmd,其起始地址是__u_boot_cmd_start, 结束是__u_boot_cmd_end
那么u-boot是怎么使用这些的,比如扫描这个段里面的命令呢?
最簡單的例子, 根據命令名,判斷是否支持
cmd_tbl_t *find_cmd (const char *cmd)
{
cmd_tbl_t *cmdtp;
cmd_tbl_t *cmdtp_temp = &__u_boot_cmd_start; /*Init value */
const char *p;
int len;
int n_found = 0;
/*
* Some commands allow length modifiers (like "cp.b");
* compare command name only until first dot.
*/
len = ((p = strchr(cmd, '.')) == NULL) ? strlen (cmd) : (p - cmd);
/* 扫描整个段 */
for (cmdtp = &__u_boot_cmd_start;
cmdtp != &__u_boot_cmd_end;
cmdtp++) {
if (strncmp (cmd, cmdtp->name, len) == 0) {
if (len == strlen (cmdtp->name))
return cmdtp; /* full match */
cmdtp_temp = cmdtp; /* abbreviated command ? */
n_found++;
}
}
if (n_found == 1) { /* exactly one match */
return cmdtp_temp;
}
return NULL; /* not found or ambiguous command */
}
由上可以得到基于vivado的zynq链接脚本的使用
扫描二维码关注公众号,回复:
6085251 查看本文章
添加.cli_cmd字段
. = .;
__cli_cmd_start = .;
.cli_cmd : { *(.cli_cmd) } > ps7_ddr_0 // > ps7_ddr_0这个根据硬件适配,参考上下文可以得到
__cli_cmd_end = .;
怎么引用__cli_cmd_start和__cli_cmd_end呢,很简单
extern cmd_tbl_t __cli_cmd_start,__cli_cmd_end;
扫描呢?
static int GetCmd(const char *name, cmd_tbl_t **cmd)
{
int found = FALSE;
cmd_tbl_t *cmdtp;
int len = __cli_cmd_end - __cli_cmd_start;
for (cmdtp = __cli_cmd_start; cmdtp != __cli_cmd_start+ len; cmdtp++)
{
if(0 == strcmp(name, cmdtp->name))
{
*cmd = cmdtp;
found = TRUE;
break;
}
}
return found;
}
在elf文件里面可以看到:
最终得到类似命令行效果如下: