嵌入式linux 控制台,嵌入式Linux 下 通用 console(控制台)的实现

前言:

当我们使用嵌入式linux 进行开发时,kernel 跑起来之后,我们希望能通过串口(标准输入、输出),在应用程序正在运行的过程中,进行一些调试工作,例如,对CPU一些寄存进行调整,以观测调整以后的结果,并且,当我们无法把我们的应用程序放在后台运行,那么我们就需要实现一个基础的控制台。

下文中的控制台,虽然简单,但完备的支持 上 下 左 右 backspace del 常用控制台操作,使用 上 下 键可以浏览已经输入过的命令(类似 doskey 这样的功能),支持 光标 左右移动 修改命令

一般我们在 main 函数最后 都会做 while(TRUE) sleep(1000) 这样 阻塞住主线程,用这个控制台的实现,替换这个过程,则应用程序可增加控制台应用功能,各部分的具体实现如下:

调用代码(main.c):

#include 

#include "app_console.h"

intmain(intargc,char*argv[])

{

// 之前的应用代码

....

....

....

App_Console_Start();

return0;

}

控制台头文件(app_console.h)

#ifndef __APP_CONSOLE_H__

#define __APP_CONSOLE_H__

#ifdef __cplusplus

extern"C"

{

#endif

#include "type_def.h"

voidApp_Console_Start();

#ifdef __cplusplus

}

#endif

#endif

控制台C文件(app_console.c)

#include "app_console.h"

#include "ctype.h"

#include "unistd.h"

#include "app_test.h"

// 说明

// read write 使用的是 POSIX 的标准文件读写函数

// unistd.h 包含了 STDIN_FILENO 等文件描述符的定义

// ctype.h 包含了 isprint 函数的声明

// 经过仔细考虑,决定不支持 ESC 键,因为ESC 键的键值为 0x1b 与 上下左右的键值重复

// 但可以考虑按2下ESC清除本行输入

// 对不可打印字符的处理仅限于以下已经列出的宏定义

// change:

// 放弃对 double ESC 的支持,因为可能出现按了 ESC 又按了 方向键 的情况

// 则用户输入编码为 '/x1b' '/x1b' '[' 'A' (按了ESC 又按了上键)

// change:

// 为了将应用与控制台应用剥离,则将 #define MAX_CMD_LEN 512 房到 app_test.h 中定义

// 二维数组作为参数进行传递时,需要明确第二个维度的大小,否则编译器无法正确定位地址

#define KEY_BACKSPACE    '/x08'    // back space

#define KEY_DEL          '/x7F'    // del

#define KEY_ENTER        '/x0A'    // 回车

// 以下为 0x1b 开头的键值

//#define KEY_DOUBLEESC    "/x1B/x1B"// ESC

//#define KEY_ARROW_UP     "/x1B[A"  // 上

//#define KEY_ARROW_DOWN   "/x1B[B"  // 下

//#define KEY_ARROW_LEFT   "/x1B[D"  // 左

//#define KEY_ARROW_RIGHT  "/x1B[C"  // 右

typedefenum

{

WKS_WAIT,

WKS_RECV1B,

WKS_UDLR,

}T_WaitKeyState;

#define MAX_CMD_HISTORY 32

#define MAX_PAR_COUNT 16

staticcharszPrompt[] = {"TR_Console> "};

staticT_WaitKeyState waitKeyState = WKS_WAIT;

staticcharszCmdHistory[MAX_CMD_HISTORY][MAX_CMD_LEN];

staticcharszCmdNow[MAX_CMD_LEN] = {0};

staticUINT32nCmdIndex = 0;

staticUINT32nCmdCursor = 0;

staticUINT32nCmdInputCount = 0;

staticUINT32nCmdInputCursor = 0;

staticvoidApp_Console_ParseCmd(constchar* pCmd);

staticUINT32App_Console_ReadInput(char*input)

{

U32    nRead=0;

structpollfd p;

structtermio term,term_old;

/* Get control of the terminal */

ioctl(STDIN_FILENO,TCGETA,(void*)&term);

term_old = term;

term.c_lflag &= ~ICANON;

term.c_lflag &= ~ECHO;

ioctl(STDIN_FILENO,TCSETAW,(void*)&term);

/* Get event we want to know */

p.fd     = STDIN_FILENO;

p.events = POLLIN;

/* If we receive one thing, get the byte now */

if(poll(&p,1,-1)>0)

{

if(p.revents==POLLIN)

{

nRead=read(STDIN_FILENO,input,1);

}

}

/* Purge the byte */

/* tcflush(0,TCIOFLUSH); */

/* Leave control */

ioctl(STDIN_FILENO,TCSETAW,(void*)&term_old);

return(nRead);

}

staticvoidApp_Console_BSChar()

{

charszTemp[3];

szTemp[0] ='/b';

szTemp[1] =' ';

szTemp[2] ='/b';

write(STDOUT_FILENO,szTemp,3);

}

staticvoidApp_Console_OnPrintChar(charinput)

{

if(nCmdInputCount == MAX_CMD_LEN)return;

if(nCmdInputCursor 

{

charszTemp[MAX_CMD_LEN] = {0};

char* pCmd = szCmdNow;

intnBackCount = nCmdInputCount-nCmdInputCursor;

szTemp[0] = input;

memcpy(&szTemp[1],&pCmd[nCmdInputCursor],nBackCount);

write(STDOUT_FILENO,szTemp,nBackCount+1);

memcpy(&pCmd[nCmdInputCursor],&szTemp,nBackCount+1);

memset(szTemp,'/b',nBackCount);

write(STDOUT_FILENO,szTemp,nBackCount);

}

else

{

write(STDOUT_FILENO,&input,1);

szCmdNow[nCmdInputCount] = input;

}

nCmdInputCursor++;

nCmdInputCount++;

}

staticvoidApp_Console_OnBackspace()

{

if(nCmdInputCursor > 0)

{

if(nCmdInputCursor == nCmdInputCount)// 光标在末尾

App_Console_BSChar();

else// 光标不在末尾

{

charszTemp[MAX_CMD_LEN] = {0};

char* pCmd = szCmdNow;

intnBackCount = nCmdInputCount-nCmdInputCursor;

szTemp[0] ='/b';

memcpy(&szTemp[1],&pCmd[nCmdInputCursor],nBackCount);

szTemp[nBackCount+1] =' ';

write(STDOUT_FILENO,szTemp,nBackCount+2);

memcpy(&pCmd[nCmdInputCursor-1],&szTemp[1],nBackCount);

memset(szTemp,'/b',nBackCount+1);

write(STDOUT_FILENO,szTemp,nBackCount+1);

}

nCmdInputCount --;

nCmdInputCursor--;

}

}

staticvoidApp_Console_OnDel()

{

if(nCmdInputCursor 

{

charszTemp[MAX_CMD_LEN] = {0};

char* pCmd = szCmdNow;

intnBackCount = nCmdInputCount-nCmdInputCursor-1;

memcpy(szTemp,&pCmd[nCmdInputCursor+1],nBackCount);

szTemp[nBackCount] =' ';

write(STDOUT_FILENO,szTemp,nBackCount+1);

memcpy(&pCmd[nCmdInputCursor],szTemp,nBackCount);

memset(szTemp,'/b',nBackCount+1);

write(STDOUT_FILENO,szTemp,nBackCount+1);

nCmdInputCount--;

}

}

staticvoidApp_Console_OnDoubleEsc()

{

if(nCmdInputCount > 0)

{

char* pCmd = szCmdNow;

// 将光标移动到最末尾

while(nCmdInputCursor 

{

write(STDOUT_FILENO,&pCmd[nCmdInputCursor],1);

nCmdInputCursor++;

}

// 清除所有输入的数据

inti=0;

for(i=0;i

nCmdInputCount = 0;

nCmdInputCursor = 0;

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值