概述
由于工作需要,使用到rtos,现将遇到的问题总结如下:很多东西先记在这里,后面有空整理
1.实现类似于linux shell的交互工具。
实现基本思路是初始化一个shell线程,然后接收用户的输入,然后parse用户的命令。当然,支持的命令需要提前实现,比如要实现ls的命令,需要实现ls命令的函数,然后该函数注册到一个数组中,当接收到用户输入ls命令时,遍历函数数组中的注册函数,找到相应的命令,然后执行。
1.首先利用.lds.S文件指定一块存储空间,用来存放struct数组,该struct中存放了每个命令的name,description,function address。每个命令注册一个struct,放置在指定的内存的地方。
//每个命令的struct的定义
#define SECTION(x) __attribute__((section(x)))//将指定的变量放置在x指定的段地址上。
typedef int (*sh_func)(int argc, char **argv);//函数指针。要实现的shell命令的函数就要定义为该样式。
struct sh_func_call//每个命令的struct。每个命令都需要初始化一个该struct,然后放到上面section指定的地址。
{
const char *name;
const char *desc;
ant_sh_func func;
const char *reserved;
};
/*这里就是定义了一个宏,当实现了一个shell命令,就利用这个宏来声明一下,这个宏就会自动声明一个该函数对应的struct,放置到指定的内存位置,后面接收到shell的命令名字,就去该地址去匹配,匹配到之后就可以利用存储的函数指针调用该命令对应的函数。*/
#define FUNCTION_EXPORT_ALIAS(function, alias, description)
const char __sh_func_##alias##_name[] = #alias;
const char __sh_func_##alias##_desc[] = description;
const struct sh_func_call __sh_func_call_##alias SECTION("AMBSyscallTab") =
{
__sh_func_##alias##_name,
__sh_func_##alias##_desc,
(sh_func)&function //这里的&可以要,也可以不要。c语言都允许。
};
#define FUNCTION_EXPORT(function, description)
FUNCTION_EXPORT_ALIAS(function, function, description)
//example
static int print_hello(int argc, char **argv)
{
for (int i = 0; i < argc; ++i) {
printk("arg[%d]: %sn", i, argv[i]);
}
return 0;
}
FUNCTION_EXPORT(print_hello, "This function can print hello")
2.定义好了上面的基础之后,就要定义一个线程的主函数,暂时先使用一个线程实现shell功能(最终需要多线程,就是shell为一个主线程,当接收到命令之后,要另起一个线程来执行这个命令,主线程要等待执行线程的结果,并且能根据用户的命令来终止执行线程。)
首先定义一个shell的context,用来指定该shell的一些功能,比如read和write函数是从串口来获取和打印到串口还是从telnet获取或打印到telnet。还要存放该shell接收到的命令名称,该命令的参数等信息,因为是利用c语言来实现,所以很多函数都需要传入该context。
typedef int (*console_read_write_func)(char *buf, int size);
struct sh_context
{
int line_pos;
char line[512];
int x;
int y;
int argc;
char *argv[128];
ant_console_read_write_func read;
ant_console_read_write_func write;
};
然后定义线程主函数
static struct sh_context antshell_context;
static void tx_task_toy(void)//在系统初始函数中调用此函数,就会创建一个shell线程。
{
shell_context.read = uart_read;//指定read函数使用uart_read函数,即从串口read
shell_context.write = uart_write;//打印到串口
//创建shell线程。
if (KAL_TaskCreate(&task0, "ant_shell", KAL_TASK_LOWEST_PRIORITY - 2,
shell_task, (unsigned int)&shell_context,
task0_stack, 8192, KAL_AUTO_START)) {
printk("%s: Bug !!!", __func__);
return;
}
return;
}
//shell线程的主函数
void shell_task(unsigned int arg)
{
struct sh_context *context = (struct sh_context*)arg;//传入context
sh_show_welcome(context);//显示一个欢迎内容
while (1) {
int ch = sh_read_char(context);//读取命令字符。
sh_parse_input(ch, context);//parse命令字符,
}
}
//根据用户在串口输入的命令,去上面section指定的内存区域去匹配对应的命令,找到后,执行对应的函数。
void sh_parse_input(char ch, struct sh_context *context)
{
if (ch == 'r') { //end of the line
context->line[context->line_pos] = '