(12)从1开始写一个操作系统

第十二章

Shell移植

命令行外壳(shell),提供一套供用户在命令行的操作接口,主要用于调试、查看系统信息。在大部分嵌入式系统中,一般开发调试都使用硬件调试器和printf日志打印,在有些情况下,这两种方式并不是那么好用。比如对于多任务系统,我们想知道某个时刻系统中的任务运行状态、手动控制系统状态。如果有一个shell,就可以输入命令,直接相应的函数执行获得需要的信息,或者控制程序的行为。这无疑会十分方便。

接下来我们就要通过移植的方式实现两种shell。

第一种是我从rtthread中精简下来,原来在STC12C系列的裸机上运行的Wing。

第二种是我从网上找到的在STM32裸机和ucos上运行的Qshell。

 

Wing

Wing是我在学习rtthread的finsh的时候看懂了原理,照着写的一个非常小,动能非常简单的shell工具,需要使用超级终端来进行交互,普通的串口工具坑能不太好用。

它的原理就是在串口每次接收到字符时进行相应的处理,比如tab或者回车键等,调用RTWingProcess函数来进行具体逻辑处理。

当遇到回车键时就将buff中的字符串进行对比,如果有与RTWfunc.c中相同的字符串就调用相应的函数指针,实现shell的简单功能。

最初的wing中只实现了hello和version的功能,就是打印hello和版本信息,后来我又写了一个status的函数,就是打印当前的系统信息。

int status(int argc, char *argv[])
{
    u8 i;
    OS_SS *ss = get_sys_statistics();
    argc = argc;
    argv = argv;
    printf("\r\nID\tCPU\tSTATUS\tUSED STACK\r\n");
    for (i=0; i<TASK_SIZE; i++) {
        if (ss[i].OSSSStatus != OS_STAT_DEFAULT) {//任务已
            printf("%bu\t%bu%%\t", i, ss[i].OSSSCyclesTot);
            switch (ss[i].OSSSStatus) {
            case OS_STAT_RUNNING:
                printf("RUN");
                break;
            case OS_STAT_RDY:
                printf("RDY");
                break;
            case OS_STAT_SLEEP:
                printf("SLEEP");
                break;
            case OS_STAT_SUSPEND:
                printf("SUSPEND");
                break;
            case OS_STAT_DEAD:
                printf("DEAD");
                break;
            case OS_STAT_MUTEX:
                printf("MUTEX");
                break;
            case OS_STAT_SEM:
                printf("SEM");
                break;
            case OS_STAT_MSGQ:
                printf("MSGQ");
                break;
            case OS_STAT_FLAG:
                printf("FLAG");
                break;
            default:
                printf("unknown");
            }
            printf("\t%bu\r\n", ss[i].OSSSMaxUsedStk);
        }
    }
    return 0;
}

并且注册到数组中

const struct CLI_RTWING rtwing_syscall[] = {
    RTWING_FUNCTION_EXPORT(hello, hello rtwing!),
    RTWING_FUNCTION_EXPORT(version, rtwing version!),
    RTWING_FUNCTION_EXPORT(status, get tasks status!),
};

这样就可以在超级终端中使用status查看系统信息了。

SecureCRT的输出如下:

STC15F2K60S2 RT-OS Test Prgramme!

RTWing 0.0.2 Bulid Sep 21 2019 10:35:31
2014 Develop RZ
[RTWing]:
hello           hello rtwing!
version         rtwing version!
status          get tasks status!

[RTWing]: status
ID      CPU     STATUS  USED STACK
0       100%    RUN     19
1       0%      SLEEP   19

return 0x0000
[RTWing]:

这样一来你可以根据自己的需要写一些与任务交互的函数,用来测试或者调试。

Qshell

移植失败,原因是这个工程最大的亮点是函数或者变量不需要自己去创建数组或者链表,因为他是用了keil MDK的绝对段定位(__attribute__ section),这样就可以把需要定位的变量保存到这个段中,然后通过段名$$Base就能找到段的起始位置,这样就可以一个一个的遍历所有数据。

但是在keil C51中只是找到了几种绝对定位的方法,并不能满足这个工程的需求,如果像上一个那样用数组实现又难免有点重复工作。

所以到这里全部的工作基本完成,如果从头学习的人会发现这里有一个大大的问题就是没有处理中断嵌套和中断中任务相关函数的实现,在这里就不一一讲解了,因为大体与函数中基本相同,只要弄明白中断上下文环境能做什么不能做什么,这些函数都是重复劳动了。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章