嵌入式Linux 下 通用 console(控制台)的达成
发布时间:2021-12-18 19:11:00 所属栏目:PHP教程 来源:互联网
导读:当我们使用嵌入式linux 进行开发时,kernel 跑起来之后,我们希望能通过串口(标准输入、输出),在应用程序正在运行的过程中,进行一些调试工作,例如,对CPU一些寄存进行调整,以观测调整以后的结果,并且,当我们无法把我们的应用程序放在后台运行,那么
当我们使用嵌入式linux 进行开发时,kernel 跑起来之后,我们希望能通过串口(标准输入、输出),在应用程序正在运行的过程中,进行一些调试工作,例如,对CPU一些寄存进行调整,以观测调整以后的结果,并且,当我们无法把我们的应用程序放在后台运行,那么我们就需要实现一个基础的控制台。 下文中的控制台,虽然简单,但完备的支持 上 下 左 右 backspace del 常用控制台操作,使用 上 下 键可以浏览已经输入过的命令(类似 doskey 这样的功能),支持 光标 左右移动 修改命令 一般我们在 main 函数最后 都会做 while(TRUE) sleep(1000) 这样 阻塞住主线程,用这个控制台的实现,替换这个过程,则应用程序可增加控制台应用功能,各部分的具体实现如下: 调用代码(main.c): #include <stdio.h> #include "app_console.h" int main(int argc, char *argv[]) { // 之前的应用代码 .... .... .... App_Console_Start(); return 0; } 控制台头文件(app_console.h) #ifndef __APP_CONSOLE_H__ #define __APP_CONSOLE_H__ #ifdef __cplusplus extern "C" { #endif #include "type_def.h" void App_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" // 右 typedef enum { WKS_WAIT, WKS_RECV1B, WKS_UDLR, }T_WaitKeyState; #define MAX_CMD_HISTORY 32 #define MAX_PAR_COUNT 16 static char szPrompt[] = {"TR_Console> "}; static T_WaitKeyState waitKeyState = WKS_WAIT; static char szCmdHistory[MAX_CMD_HISTORY][MAX_CMD_LEN]; static char szCmdNow[MAX_CMD_LEN] = {0}; static UINT32 nCmdIndex = 0; static UINT32 nCmdCursor = 0; static UINT32 nCmdInputCount = 0; static UINT32 nCmdInputCursor = 0; static void App_Console_ParseCmd(const char* pCmd); static UINT32 App_Console_ReadInput(char *input) { U32 nRead=0; struct pollfd p; struct termio 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); } static void App_Console_BSChar() { char szTemp[3]; szTemp[0] = '/b'; szTemp[1] = ' '; szTemp[2] = '/b'; write(STDOUT_FILENO,szTemp,3); } static void App_Console_OnPrintChar(char input) { if(nCmdInputCount == MAX_CMD_LEN) return; if(nCmdInputCursor < nCmdInputCount) // 光标不在末尾 { char szTemp[MAX_CMD_LEN] = {0}; char* pCmd = szCmdNow; int nBackCount = 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++; } static void App_Console_OnBackspace() { if(nCmdInputCursor > 0) { if(nCmdInputCursor == nCmdInputCount) // 光标在末尾 App_Console_BSChar(); else// 光标不在末尾 { char szTemp[MAX_CMD_LEN] = {0}; char* pCmd = szCmdNow; int nBackCount = 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--; } } static void App_Console_OnDel() { if(nCmdInputCursor < nCmdInputCount) // 光标不在末尾 { char szTemp[MAX_CMD_LEN] = {0}; char* pCmd = szCmdNow; int nBackCount = 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--; } } static void App_Console_OnDoubleEsc() { if(nCmdInputCount > 0) { char* pCmd = szCmdNow; // 将光标移动到最末尾 while(nCmdInputCursor < nCmdInputCount) { write(STDOUT_FILENO,&pCmd[nCmdInputCursor],1); nCmdInputCursor++; } // 清除所有输入的数据 int i=0; for(i=0;i<nCmdInputCount;i++) App_Console_BSChar(); nCmdInputCount = 0; nCmdInputCursor = 0; } } static void App_Console_OnUp() { if(nCmdCursor == 0) return; nCmdCursor --; // 清除掉现在所有的输入 App_Console_OnDoubleEsc(); char* pCmdHistory = &szCmdHistory[nCmdCursor][0]; memcpy(szCmdNow,pCmdHistory,MAX_CMD_LEN); nCmdInputCount = strlen(szCmdNow); nCmdInputCursor= nCmdInputCount; write(STDOUT_FILENO,szCmdNow,nCmdInputCount); } static void App_Console_OnDown() { if(nCmdCursor >= (nCmdIndex-1)) return; nCmdCursor ++; // 清除掉现在所有的输入 App_Console_OnDoubleEsc(); char* pCmdHistory = &szCmdHistory[nCmdCursor][0]; memcpy(szCmdNow,pCmdHistory,MAX_CMD_LEN); nCmdInputCount = strlen(szCmdNow); nCmdInputCursor= nCmdInputCount; write(STDOUT_FILENO,szCmdNow,nCmdInputCount); } static void App_Console_OnLeft() { if(nCmdInputCursor > 0) { char c = '/b'; write(STDOUT_FILENO,&c,1); nCmdInputCursor--; } } static void App_Console_OnRight() { if(nCmdInputCursor < nCmdInputCount) { char* pCmd = szCmdNow; char c = pCmd[nCmdInputCursor]; write(STDOUT_FILENO,&c,1); nCmdInputCursor++; } } static void App_Console_OnEnter() { szCmdNow[nCmdInputCount] = '/0'; char szTemp[] = {"/r/n"}; write(STDOUT_FILENO,szTemp,strlen(szTemp)); nCmdInputCount = 0; nCmdInputCursor = 0; if(strlen(szCmdNow) == 0) return; if(nCmdIndex == MAX_CMD_HISTORY) // 命令队列满了,移动 { char szTempCmd[MAX_CMD_HISTORY][MAX_CMD_LEN]; memcpy(szTempCmd,&szCmdHistory[1][0],MAX_CMD_LEN*(MAX_CMD_HISTORY-1)); memcpy(szCmdHistory,szTempCmd,MAX_CMD_LEN*(MAX_CMD_HISTORY-1)); nCmdIndex = MAX_CMD_HISTORY-1; nCmdCursor = nCmdIndex; } memcpy(szCmdHistory[nCmdIndex],szCmdNow,MAX_CMD_LEN); nCmdIndex++; nCmdCursor = nCmdIndex; // 解析命令 App_Console_ParseCmd(szCmdNow); } static void App_Console_CmdLoop() { BOOL bGetEnter = FALSE; while(TRUE) { // 读取一个console输入 UINT32 nReturn = 0; char input; nReturn = App_Console_ReadInput (&input); if(nReturn > 0) { switch(waitKeyState) { case WKS_WAIT : if(isprint(input))// 可打印字符 App_Console_OnPrintChar(input); else { if(input == KEY_BACKSPACE) App_Console_OnBackspace(); else if(input == KEY_DEL) App_Console_OnDel(); else if(input == KEY_ENTER) { App_Console_OnEnter(); bGetEnter = TRUE; } else if(input == '/x1b') waitKeyState = WKS_RECV1B; else waitKeyState = WKS_WAIT; } break; case WKS_RECV1B: if(input == '/x1b') // 按了ESC 又按了方向键,或者是 ESC { //App_Console_OnDoubleEsc(); waitKeyState = WKS_RECV1B; } else if(input == '[') //可能为 上下左右 4个键 waitKeyState = WKS_UDLR; else//下面的情况为 按了 ESC 键之后,按了其他的键的处理 { if(isprint(input)) App_Console_OnPrintChar(input); waitKeyState = WKS_WAIT; } break; case WKS_UDLR: if(input == 'A')// 上 App_Console_OnUp(); else if(input == 'B')// 下 App_Console_OnDown(); else if(input == 'D')// 左 App_Console_OnLeft(); else if(input == 'C')// 右 App_Console_OnRight(); else { if(isprint(input)) App_Console_OnPrintChar(input); } waitKeyState = WKS_WAIT; break; default: break; } } if(bGetEnter) { break; } } } void App_Console_Start() { // 清空 sdtout 缓冲 fflush(stdout); fflush(stdin); char szTemp[] = {"/r/nStart TR Console.../r/n/r/n"}; write(STDOUT_FILENO,szTemp,strlen(szTemp)); while(TRUE) { write(STDOUT_FILENO,szPrompt,strlen(szPrompt)); App_Console_CmdLoop(); } } // 解析命令 static void App_Console_ParseCmd(const char* pCmd) { int length = strlen(pCmd); // 全部转小写 int i=0; char szTempCmd[MAX_CMD_LEN]; for (i=0; i < length; i++) szTempCmd[i] = tolower(pCmd[i]); // 将输入的命令各个 part 分开 char szPart[MAX_PAR_COUNT][MAX_CMD_LEN]; int nPartCount = 0; int nPartCursor = 0; int nCmdCursor = 0; memset(szPart,0,sizeof(szPart)); while(TRUE) { if(nCmdCursor == length) { if(nPartCursor > 0) { nPartCount++; nPartCursor = 0; } break; } if( (szTempCmd[nCmdCursor] == ',') || (szTempCmd[nCmdCursor] == ' ') ) // part 分割符 { szPart[nPartCount][nPartCursor] = '/0'; nPartCount++; nPartCursor = 0; } else { szPart[nPartCount][nPartCursor] = szTempCmd[nCmdCursor]; nPartCursor++; } nCmdCursor++; } App_Test_OnCmd(szPart,nPartCount); } 命令实现头文件(app_test.h) view plaincopy to clipboardprint? #ifndef __APP_TEST_H__ #define __APP_TEST_H__ #ifdef __cplusplus extern "C" { #endif #include "type_def.h" #define MAX_CMD_LEN 512 void App_Test_OnCmd(char szPart[][MAX_CMD_LEN],int nPartCount); #ifdef __cplusplus } #endif #endif 命令实现c文件(app_test.c) view plaincopy to clipboardprint? #include "app_test.h" #include "stapp_main.h" #include "app_qam.h" #include "api_av.h" #include "api_video.h" #include "api_audio.h" #include "api_pcr.h" static void App_Test_OnHelp(); static void App_Test_OnWriteReg8(char szPart[][MAX_CMD_LEN],int nPartCount); static void App_Test_OnReadReg8(char szPart[][MAX_CMD_LEN],int nPartCount); static void App_Test_OnQamConnect(char szPart[][MAX_CMD_LEN],int nPartCount); static void App_Test_OnAVPlayMpeg(char szPart[][MAX_CMD_LEN],int nPartCount); static void App_Test_OnAVStop(); static void App_Test_OnVolumeSet(char szPart[][MAX_CMD_LEN],int nPartCount); static void App_Test_OnMute(); static void App_Test_OnUnmute(); static void App_Test_OnDENCRegDum(); static void App_Test_OnDENCRegSet(char szPart[][MAX_CMD_LEN],int nPartCount); void App_Test_OnCmd(char szPart[][MAX_CMD_LEN],int nPartCount) { // 这里处理私有的命令 if(nPartCount == 0) return; if( strcmp(szPart[0],"help") == 0) { App_Test_OnHelp(); } else if( strcmp(szPart[0],"writereg8") == 0) { if(nPartCount > 2) App_Test_OnWriteReg8(szPart,nPartCount); } else if( strcmp(szPart[0],"readreg8") == 0) { if(nPartCount > 1) App_Test_OnReadReg8(szPart,nPartCount); } else if( strcmp(szPart[0],"qamconnect") == 0) { if(nPartCount > 1) App_Test_OnQamConnect(szPart,nPartCount); } else if( strcmp(szPart[0],"avplaympeg") == 0) { if(nPartCount > 1) App_Test_OnAVPlayMpeg(szPart,nPartCount); } else if( strcmp(szPart[0],"avstop") == 0) { App_Test_OnAVStop(); } else if( strcmp(szPart[0],"volumeset") == 0) { if(nPartCount > 1) App_Test_OnVolumeSet(szPart,nPartCount); } else if( strcmp(szPart[0],"mute") == 0) { App_Test_OnMute(); } else if( strcmp(szPart[0],"unmute") == 0) { App_Test_OnUnmute(); } else if( strcmp(szPart[0],"dencregdump") == 0) { App_Test_OnDENCRegDum(); } else if( strcmp(szPart[0],"dencregset") == 0) { if(nPartCount > 1) App_Test_OnDENCRegSet(szPart,nPartCount); } } static void App_Test_OnHelp() { printf("**************************************************************/n"); printf("* Help PARAM MUST 0 MAX 0 Eg. help/n"); printf("* WriteReg8 PARAM MUST 2 MAX 2 Eg. WriteReg8 0x1920C114 128/n"); printf("* ReadReg8 PARAM MUST 1 MAX 1 Eg. ReadReg8 0x1920C114/n"); printf("* QamConnect PARAM MUST 1 MAX 3 Eg. QamConnect 546000/n"); printf("* AVPlayMpeg PARAM MUST 1 MAX 3 Eg. AVPlayMpeg 64 63 32/n"); printf("* AVStop PARAM MUST 0 MAX 0 Eg. AVStop/n"); printf("* VolumeSet PARAM MUST 1 MAX 1 Eg. VolumeSet 63/n"); printf("* Mute PARAM MUST 0 MAX 0 Eg. Mute/n"); printf("* Unmute PARAM MUST 0 MAX 0 Eg. Unmute/n"); printf("* DENCRegDump PARAM MUST 0 MAX 0 Eg. DENCRegDump/n"); printf("* DENCRegSet PARAM MUST 1 MAX 1 Eg. DENCRegSet 1/n"); printf("*************************************************************/n"); } static void App_Test_OnWriteReg8(char szPart[][MAX_CMD_LEN],int nPartCount) { char* pAddress = &szPart[1][0]; char* pValue = &szPart[2][0]; DWORD dwAddress = 0; UINT8 nValue = atoi(pValue); sscanf(pAddress,"0x%08x",&dwAddress); SYS_WriteRegDev8(dwAddress,nValue); } static void App_Test_OnQamConnect(char szPart[][MAX_CMD_LEN],int nPartCount) { char* pFreq = &szPart[1][0]; UINT32 nFreq = atoi(pFreq); UINT32 nSymbolRate = 6875; T_DMD_Modulation nQAMMode = QAM_64; if(nPartCount > 2) { char* pSymbolRate = &szPart[2][0]; nSymbolRate = atoi(pSymbolRate); } if(nPartCount > 3) { char* pQAMMode = &szPart[3][0]; nQAMMode = atoi(pQAMMode); } App_Qam_Locking(TRUE,nFreq,nSymbolRate,nQAMMode); } static void App_Test_OnAVPlayMpeg(char szPart[][MAX_CMD_LEN],int nPartCount) { UINT16 nVideoPid = 0xFFFF; UINT16 nAudioPid = 0xFFFF; UINT16 nPcrPid = 0xFFFF; char* pAudioPid = &szPart[1][0]; nAudioPid = atoi(pAudioPid); if(nPartCount > 2) { char* pVideoPid = &szPart[2][0]; nVideoPid = atoi(pVideoPid); } if(nPartCount > 3) { char* pPcr = &szPart[3][0]; nPcrPid = atoi(pPcr); } Api_Av_Stop(); Api_Av_Start(nAudioPid,STREAMTYPE_MP2A,nVideoPid,STREAMTYPE_MP2V,nPcrPid); } static void App_Test_OnVolumeSet(char szPart[][MAX_CMD_LEN],int nPartCount) { UINT16 nVolume = 0; char* pVolume = &szPart[1][0]; nVolume = atoi(pVolume); Api_Audio_Volume_Set(nVolume); } static void App_Test_OnMute() { Api_Audio_Mute(); } static void App_Test_OnUnmute() { Api_Audio_Unmute(); } static void App_Test_OnAVStop() { Api_Av_Stop(); } static void App_Test_OnDENCRegDum() { printf("* Brightness 0x1920C114 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C114)); printf("* Contrast 0x1920C118 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C118)); printf("* Saturation 0x1920C11c value is 0x%02x/n",SYS_ReadRegDev8(0x1920C11c)); printf("* CHROMA_COEF0 0x1920C120 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C120)); printf("* CHROMA_COEF1 0x1920C124 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C124)); printf("* CHROMA_COEF2 0x1920C128 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C128)); printf("* CHROMA_COEF3 0x1920C12c value is 0x%02x/n",SYS_ReadRegDev8(0x1920C12c)); printf("* CHROMA_COEF4 0x1920C130 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C130)); printf("* CHROMA_COEF5 0x1920C134 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C134)); printf("* CHROMA_COEF6 0x1920C138 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C138)); printf("* CHROMA_COEF7 0x1920C13c value is 0x%02x/n",SYS_ReadRegDev8(0x1920C13c)); printf("* CHROMA_COEF8 0x1920C140 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C140)); printf("* LUM_COEF0 0x1920C148 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C148)); printf("* LUM_COEF1 0x1920C14c value is 0x%02x/n",SYS_ReadRegDev8(0x1920C14c)); printf("* LUM_COEF2 0x1920C150 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C150)); printf("* LUM_COEF3 0x1920C154 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C154)); printf("* LUM_COEF4 0x1920C158 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C158)); printf("* LUM_COEF5 0x1920C15c value is 0x%02x/n",SYS_ReadRegDev8(0x1920C15c)); printf("* LUM_COEF6 0x1920C160 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C160)); printf("* LUM_COEF7 0x1920C164 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C164)); printf("* LUM_COEF8 0x1920C168 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C168)); printf("* LUM_COEF9 0x1920C16c value is 0x%02x/n",SYS_ReadRegDev8(0x1920C16c)); printf("* CFG9 0x1920C144 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C144)); } static void App_Test_OnDENCRegSet(char szPart[][MAX_CMD_LEN],int nPartCount) { UINT16 nScheme = 1; char* pScheme = &szPart[1][0]; nScheme = atoi(pScheme); switch(nScheme) { case 1: break; case 2: break; case 3: break; case 4: break; default: break; } } static void App_Test_OnReadReg8(char szPart[][MAX_CMD_LEN],int nPartCount) { char* pAddress = &szPart[1][0]; DWORD dwAddress = 0; sscanf(pAddress,"0x%08x",&dwAddress); printf("* 0x%08x value is 0x%02x/n",dwAddress,SYS_ReadRegDev8(dwAddress)); } ![]() (编辑:云计算网_泰州站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |