#define _IN_CONSOLE_C #include "console.h" #include "serial.h" #include "trigger.h" #include "cpuid.h" //--------------------------------------------------------------------------------------------- int g_useQueue = 1; // = 0, 不使用队列输出,同步等待串口发送完成。= 1,使用队列输入输出 //--------------------------------------------------------------------------------------------- void SetConsoleOutType(int type) { if (type != 0) { g_useQueue = 1; } else { g_useQueue = 0; } } //--------------------------------------------------------------------------------------------- int SendData(u8 * pDatBuf, int len) { if (g_useQueue == 1) { #if (CONSOLE_PORT == COMM_USART1) return Usart1SendData(pDatBuf, len); #elif (CONSOLE_PORT == COMM_USART2) return Usart2SendData(pDatBuf, len); #elif (CONSOLE_PORT == COMM_USART3) return Usart3SendData(pDatBuf, len); #elif (CONSOLE_PORT == COMM_USART4) return Usart4SendData(pDatBuf, len); #elif (CONSOLE_PORT == COMM_USART5) return Usart5SendData(pDatBuf, len); #elif (CONSOLE_PORT == COMM_USART6) return Usart6SendData(pDatBuf, len); #else return 0; #endif } else { #if (CONSOLE_PORT == COMM_USART1) return Usart1SendDataSync(pDatBuf, len); #elif (CONSOLE_PORT == COMM_USART2) return Usart2SendDataSync(pDatBuf, len); #elif (CONSOLE_PORT == COMM_USART3) return Usart3SendDataSync(pDatBuf, len); #elif (CONSOLE_PORT == COMM_USART4) return Usart4SendDataSync(pDatBuf, len); #elif (CONSOLE_PORT == COMM_USART5) return Usart5SendDataSync(pDatBuf, len); #elif (CONSOLE_PORT == COMM_USART6) return Usart6SendDataSync(pDatBuf, len); #else return 0; #endif } } int ResvData(u8 * pDat, int expectLen) { if (g_useQueue == 1) { #if (CONSOLE_PORT == COMM_USART1) return Usart1GetData(pDat, expectLen); #elif (CONSOLE_PORT == COMM_USART2) return Usart2GetData(pDat, expectLen); #elif (CONSOLE_PORT == COMM_USART3) return Usart3GetData(pDat, expectLen); #elif (CONSOLE_PORT == COMM_USART4) return Usart4GetData(pDat, expectLen); #elif (CONSOLE_PORT == COMM_USART5) return Usart5GetData(pDat, expectLen); #elif (CONSOLE_PORT == COMM_USART6) return Usart6GetData(pDat, expectLen); #else return 0; #endif } else { #if (CONSOLE_PORT == COMM_USART1) return Usart1GetDataSync(pDat, expectLen); #elif (CONSOLE_PORT == COMM_USART2) return Usart2GetDataSync(pDat, expectLen); #elif (CONSOLE_PORT == COMM_USART3) return Usart3GetDataSync(pDat, expectLen); #elif (CONSOLE_PORT == COMM_USART4) return Usart4GetDataSync(pDat, expectLen); #elif (CONSOLE_PORT == COMM_USART5) return Usart5GetDataSync(pDat, expectLen); #elif (CONSOLE_PORT == COMM_USART6) return Usart6GetDataSync(pDat, expectLen); #else return 0; #endif } } // 串口选择 #if (CONSOLE_PORT == COMM_USART1) #define INIT_USART InitUsart1 #elif (CONSOLE_PORT == COMM_USART2) #define INIT_USART InitUsart2 #elif (CONSOLE_PORT == COMM_USART3) #define INIT_USART InitUsart3 #elif (CONSOLE_PORT == COMM_USART4) #define INIT_USART InitUsart4 #elif (CONSOLE_PORT == COMM_USART5) #define INIT_USART InitUsart5 #elif (CONSOLE_PORT == COMM_USART6) #define INIT_USART InitUsart6 #else #endif //--------------------------------------------------------------------------------------------- // 输入输出支持 #include #include #if defined ( __CC_ARM ) #pragma import(__use_no_semihosting_swi) //标准库需要的支持函数 struct __FILE { int handle; }; FILE __stdout; FILE __stdin; // 重定义 fputc 函数 int fputc(int ch, FILE *f) { u8 c = (u8)ch; SendData(&c, 1); return ch; } // 重定义 fgetc 函数 int fgetc(FILE *f) { int ch; u8 c; ch = ResvData(&c, 1); if (ch == 1) { #if (0) // 回显 SendData(&c, 1); #endif return c; } return -1; } int ferror(FILE *f) { // 添加代码 return EOF; } void _ttywrch(int ch) { u8 c = (u8)ch; SendData(&c, 1); } void _sys_exit(int return_code) { while (1); } #define GETCHAR getchar #define PUTCHAR putchar #elif defined ( __GNUC__ ) int __io_putchar(int ch) { u8 c; c = ch; SendData(&c, 1); return ch; } int __io_getchar(void) { int ch; u8 c; ch = ResvData(&c, 1); if (ch == 1) { ch = (int)c; return ch; } return 0; } int _read(int file, char *ptr, int len) { int rslt; rslt = ResvData((u8*)ptr, len); return rslt; } int _write(int file, char *ptr, int len) { SendData((u8*)ptr, len); return len; } #define PUTCHAR __io_putchar #define GETCHAR __io_getchar #endif int PutChar(int ch) { return PUTCHAR(ch); } int GetChar(void) { return GETCHAR(); } //--------------------------------------------------------------------------------------------- typedef struct { int pause; // 暂停 int newCmd; // 新命令标志 int cmdExec; // 命令执行标志 int cancel; // 请求退出执行标志 char command[MAX_CMD_LINE]; // 命令行内容 int cmdInCtrl; // 控制命令状态 int cmdPointer; // 命令行指针 int cmdLen; // 命令长度 char cmdBuf[MAX_CMD_LINE]; // 命令行缓存 }CmdLine; CmdLine g_cmdLine; //--------------------------------------------------------------------------------------------- int IsNewCommand(void) { return g_cmdLine.newCmd; } int LockExecAndGetCmdStr(char*pBuf) { int len; EnterCritical(); len = g_cmdLine.cmdLen; g_cmdLine.cmdExec = 1; g_cmdLine.newCmd = 0; ExitCritical(); memcpy(pBuf, g_cmdLine.command, len); return len; } void UnlockExec(void) { g_cmdLine.cmdExec = 0; } void SetPauseStatus(int sta) { if (sta != 0) { g_cmdLine.pause = 1; } else { g_cmdLine.pause = 0; } } //--------------------------------------------------------------------------------------------- // 循环队列保存历史命令 #define HISTORY_CMD_NUM 10 // 历史命令存储个数 char g_cmdHistory[HISTORY_CMD_NUM][MAX_CMD_LINE]; int g_cmdHisIdx = 0; // 历史命令指针 int g_cmdHisNum = 0; // 历史命令个数 int g_cmdHisSer = -1; // 历史命令遍历 int g_cursorNum = 0; // 20220412 void InitHistory(void) { g_cmdHisIdx = 0; // 历史命令指针 g_cmdHisNum = 0; // 历史命令个数 g_cmdHisSer = -1; // 历史命令遍历 g_cursorNum = 0; memset(g_cmdHistory, 0, HISTORY_CMD_NUM*MAX_CMD_LINE); } void AddNewCmdToHistory(char * pCmd) { if (pCmd != NULL) { // 判断当前命令是否已经存放在历史命令中,如果已存放,将其提取到队列尾部 for (int i = 0; i < g_cmdHisNum; i++) { if (strcmp(&(g_cmdHistory[i][0]), pCmd) == 0) // 已存放 { int temp1, temp2; int count; // 计算提取到队列尾部所需次数 if (i >= g_cmdHisIdx) { count = g_cmdHisNum - (i - g_cmdHisIdx); } else { count = g_cmdHisIdx - i; } count--; // 提取过程 for (int j = 0; j < count; j++) { temp1 = i + j; temp2 = temp1 + 1; if (temp1 >= g_cmdHisNum) { temp1 -= g_cmdHisNum; } if (temp2 >= g_cmdHisNum) { temp2 -= g_cmdHisNum; } memset(&(g_cmdHistory[temp1][0]), 0, MAX_CMD_LINE); strcpy(&(g_cmdHistory[temp1][0]), &(g_cmdHistory[temp2][0])); if (j == (count - 1)) { memset(&(g_cmdHistory[temp2][0]), 0, MAX_CMD_LINE); strcpy(&(g_cmdHistory[temp2][0]), pCmd); } } return; } } if (g_cmdHisIdx >= HISTORY_CMD_NUM) { g_cmdHisIdx = 0; } memset(&(g_cmdHistory[g_cmdHisIdx][0]), 0, MAX_CMD_LINE); strcpy(&(g_cmdHistory[g_cmdHisIdx][0]), pCmd); g_cmdHisIdx++; if (g_cmdHisNum < HISTORY_CMD_NUM) { g_cmdHisNum++; } } } // 上光标处理 void UpCursorProc(void) { if (g_cursorNum > 0) { g_cursorNum--; } else { return; } g_cmdHisSer--; if (g_cmdHisSer < 0) { g_cmdHisSer = g_cmdHisNum - 1; } if (1) { // 输出退格,清空所有 while (g_cmdLine.cmdPointer != 0) { PUTCHAR(0x08); // 输出退格 PUTCHAR(' '); // 输出空格 PUTCHAR(0x08); // 输出退格 g_cmdLine.cmdPointer--; } // 显示历史命令 if (g_cmdLine.cmdExec == 0 && g_cmdLine.newCmd == 0) { char ch; for (int i = 0; i < MAX_CMD_LINE; i++) { ch = g_cmdHistory[g_cmdHisSer][i]; if (ch > 0x1F && ch < 0x7F) // 添加字符到命令行中 { if (g_cmdLine.cmdPointer < MAX_CMD_LINE-1) { PUTCHAR(ch); // 回显示 g_cmdLine.cmdBuf[g_cmdLine.cmdPointer] = ch; g_cmdLine.cmdPointer++; } } } } else { g_cmdLine.cmdPointer = 0; g_cmdLine.cmdBuf[0] = 0; } } } // 下光标处理 void DownCursorProc(void) { if (g_cursorNum < g_cmdHisNum) { g_cursorNum++; } else { return; } g_cmdHisSer++; if (g_cursorNum == g_cmdHisNum) { // 输出退格,清空所有 while (g_cmdLine.cmdPointer != 0) { PUTCHAR(0x08); // 输出退格 PUTCHAR(' '); // 输出空格 PUTCHAR(0x08); // 输出退格 g_cmdLine.cmdPointer--; } return; } if (g_cmdHisSer >= g_cmdHisNum) { g_cmdHisSer = 0; } if (1) { // 输出退格,清空所有 while (g_cmdLine.cmdPointer != 0) { PUTCHAR(0x08); // 输出退格 PUTCHAR(' '); // 输出空格 PUTCHAR(0x08); // 输出退格 g_cmdLine.cmdPointer--; } // 显示历史命令 if (g_cmdLine.cmdExec == 0 && g_cmdLine.newCmd == 0) { char ch; for (int i = 0; i < MAX_CMD_LINE; i++) { ch = g_cmdHistory[g_cmdHisSer][i]; if (ch > 0x1F && ch < 0x7F) // 添加字符到命令行中 { if (g_cmdLine.cmdPointer < MAX_CMD_LINE-1) { PUTCHAR(ch); // 回显示 g_cmdLine.cmdBuf[g_cmdLine.cmdPointer] = ch; g_cmdLine.cmdPointer++; } } } } else { g_cmdLine.cmdPointer = 0; g_cmdLine.cmdBuf[0] = 0; } } } //--------------------------------------------------------------------------------------------- void OutNewCmdLine(void) { g_cmdLine.cmdPointer = 0; // 命令行指针 g_cmdLine.cmdLen = 0; // 命令长度 PUTCHAR(0x0D); // 回车 PUTCHAR(0x0A); // 换行 PUTCHAR('C'); PUTCHAR('M'); PUTCHAR('D'); PUTCHAR(':'); PUTCHAR('>'); } //--------------------------------------------------------------------------------------------- void InitConsole(void) { InitTrigger(); #if (CONSOLE_PORT != COMM_NONE) INIT_USART(B115200, '8', 'N', '1'); #endif AddTriggerToList(10, ConsoleCmdScan, NULL); // 10ms 响应控制台 printf("\x0c"); // 超级终端清屏 printf("\033[1;40;32m"); // 设置超级终端背景为黑色,字符为绿色 printf("\x0c"); // 超级终端清屏 memset(&g_cmdLine, 0, sizeof(CmdLine)); g_useQueue = 1; // = 0, 不使用队列输出,同步等待串口发送完成。= 1,使用队列输入输出 InitHistory(); } // 定时器处理回显和检测命令输入 void ConsoleCmdScan() { int ch; if (g_cmdLine.pause != 0) { return; } ch = GETCHAR(); if (ch < 0) { g_cmdLine.cmdInCtrl = 0; return; } // 命令处理 switch(ch) { case 0x00: // NUL (Null char) case 0x01: // SOH (Start of Header) 发送文件首 case 0x02: // STX (Start of Text) 文本开始 ch = ch; break; case 0x03: // ETX (End of Text) 文本尾 if (g_cmdLine.cmdExec == TRUE) // ctrl+C 为终止命令 { OutNewCmdLine(); g_cmdLine.cancel = 1; } break; case 0x04: // EOT (End of Transmission) 发送结束 case 0x05: // ENQ (Enquiry) case 0x06: // ACK (Acknowledgment) 确认 case 0x07: // BEL (Bell) 蜂鸣 ch = ch; break; case 0x08: // BS (Backspace) 退格 if (g_cmdLine.cmdPointer != 0) { PUTCHAR(0x08); // 输出退格 PUTCHAR(' '); // 输出空格 PUTCHAR(0x08); // 输出退格 g_cmdLine.cmdPointer--; } break; case 0x09: // HT (Horizontal Tab) // 自动命令补全...... break; case 0x0A: // LF (Line Feed) 换行 case 0x0B: // VT (Vertical Tab) case 0x0C: // FF (Form Feed) 换页/清屏 ch = ch; break; case 0x0D: // CR (Carriage Return) 回车 { if (g_cmdLine.newCmd == 0 && g_cmdLine.cmdExec == 0) { PUTCHAR(0x0D); // 增加回车 PUTCHAR(0x0A); // 增加换行 g_cmdLine.cmdBuf[g_cmdLine.cmdPointer] = 0; // 字符串尾 g_cmdLine.cmdLen = g_cmdLine.cmdPointer; // 长度 strcpy(g_cmdLine.command, g_cmdLine.cmdBuf); // 拷贝新命令 if (g_cmdLine.cmdLen != 0) // 20220412 命令长度不为0,才存入历史命令 { AddNewCmdToHistory(g_cmdLine.cmdBuf); // 命令行内容 } g_cmdHisSer = g_cmdHisIdx; // 20220412 g_cursorNum = g_cmdHisNum; g_cmdLine.newCmd = 1; // 新命令 } break; } case 0x0E: // SO (Shift Out)SHIFT 松开 case 0x0F: // SI (Shift In) 按下 case 0x10: // DLE (Data Link Escape) 清除 case 0x11: // DC1 (XON) (Device Control 1) case 0x12: // DC2 (Device Control 2) case 0x13: // DC3 (XOFF)(Device Control 3) case 0x14: // DC4 (Device Control 4) case 0x15: // NAK (Negative Acknowledgement) case 0x16: // SYN (Synchronous Idle) case 0x17: // ETB (End of Trans. Block) case 0x18: // CAN (Cancel) case 0x19: // EM (End of Medium) case 0x1A: // SUB (Substitute) // pause 键 ch = ch; break; case 0x1B: // ESC (Escape) 退出 g_cmdLine.cmdInCtrl = 1; break; case 0x1C: // FS (File Separator) case 0x1D: // GS (Group Separator) case 0x1E: // RS (Request to Send/Record Separator) case 0x1F: // US (Unit Separator) ch = ch; break; case 0x7F: if (g_cmdLine.cmdPointer != 0) { PUTCHAR(0x08); // 输出退格 PUTCHAR(' '); // 输出空格 PUTCHAR(0x08); // 输出退格 g_cmdLine.cmdPointer--; if (g_cmdLine.cmdLen != 0) { g_cmdLine.cmdLen--; } } break; default: break; } if (ch != 0x1B && g_cmdLine.cmdInCtrl != 0) { if (g_cmdLine.cmdInCtrl == 1 && ch == 0x5B) { ch = GETCHAR(); switch(ch) { case 0x41: // 上光标 ch = 'u'; // 上翻历史命令记录 UpCursorProc(); // 20220412 break; case 0x42: // 下光标 ch = 'd'; DownCursorProc(); // 下翻历史命令记录 break; case 0x43: // 右光标 ch = 'r'; break; case 0x44: // 左光标 ch = 'l'; break; case 0x31: { ch = GETCHAR(); if (ch == 0x7E) // HOME 键 { ch = 'h'; } else if (ch == 0x31) { ch = GETCHAR(); if (ch == 0x7E) // F1 键 { ch = '1'; } } else if (ch == 0x32) { ch = GETCHAR(); if (ch == 0x7E) // F2 键 { ch = '2'; } } else if (ch == 0x33) { ch = GETCHAR(); if (ch == 0x7E) // F3 键 { ch = '3'; } } else if (ch == 0x34) { ch = GETCHAR(); if (ch == 0x7E) // F4 键 { ch = '4'; } } else if (ch == 0x35) { ch = GETCHAR(); if (ch == 0x7E) // F5 键 { ch = '5'; } } else if (ch == 0x37) { ch = GETCHAR(); if (ch == 0x7E) // F6 键 { ch = '6'; } } else if (ch == 0x38) { ch = GETCHAR(); if (ch == 0x7E) // F7 键 { ch = '7'; } } else if (ch == 0x39) { ch = GETCHAR(); if (ch == 0x7E) // F8 键 { ch = '8'; } } break; } case 0x32: { ch = GETCHAR(); if (ch == 0x7E) // INS 键 { ch = 'i'; } else if (ch == 0x30) { ch = GETCHAR(); if (ch == 0x7E) // F9 键 { ch = '9'; } } else if (ch == 0x31) { ch = GETCHAR(); if (ch == 0x7E) // F10 键 { ch = 'a'; } } else if (ch == 0x33) { ch = GETCHAR(); if (ch == 0x7E) // F11 键 { ch = 'b'; } } else if (ch == 0x34) { ch = GETCHAR(); if (ch == 0x7E) // F12 键 { ch = 'c'; } } break; } case 0x33: ch = GETCHAR(); if (ch == 0x7E) // DEL 键 { ch = 'd'; } break; case 0x34: ch = GETCHAR(); if (ch == 0x7E) // END 键 { ch = 'e'; } break; case 0x35: ch = GETCHAR(); if (ch == 0x7E) // PAGE UP 键 { ch = 'u'; } break; case 0x36: ch = GETCHAR(); if (ch == 0x7E) // PAGE DOWN 键 { ch = 'd'; } break; default: g_cmdLine.cmdInCtrl = 0; break; } } else { g_cmdLine.cmdInCtrl = 0; } if (g_cmdLine.cmdInCtrl != 0) { ch = 0; g_cmdLine.cmdInCtrl = 0; } } if (g_cmdLine.cmdExec == 0 && g_cmdLine.newCmd == 0) { if (ch > 0x1F && ch < 0x7F) // 添加字符到命令行中 { if (g_cmdLine.cmdPointer < MAX_CMD_LINE-1) { PUTCHAR(ch); // 回显示 g_cmdLine.cmdBuf[g_cmdLine.cmdPointer] = ch; g_cmdLine.cmdPointer++; } } } else { g_cmdLine.cmdPointer = 0; g_cmdLine.cmdBuf[0] = 0; } } int IsConsoleCancel(void) { int rslt = g_cmdLine.cancel; g_cmdLine.cancel = 0; return rslt; } // 20220412 提供一个外部接口,用于获取存储的历史命令 int GetHistoryCmd(int hisIdx, char * pch) { if (hisIdx < 0 || hisIdx > HISTORY_CMD_NUM || pch == NULL) { return -1; } strncpy(pch, &(g_cmdHistory[hisIdx][0]), MAX_CMD_LINE); return 0; } int GetHistoryNum(void) { return g_cmdHisNum; } int GetHistoryMaxNum(void) { return HISTORY_CMD_NUM; } int GetHistoryIdx(void) { return g_cmdHisIdx; } //--------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------