前言
在使用freertos的过程中,逐渐发现其自带的cli终端组件真是一个好好东西,非常方便调试。直接可以使用串口终端助手与mcu进行交互。类似于linux中的终端,可以执行一些命令,看系统堆栈状态,任务状态等等。
同时也发现一个用起来不太友好的地方,定义命令的回调函数过于复杂,与cli中断勾连太多,不够简洁易懂。
优化前
比如上图中的sum命令,在原版的cli组件中,定义该命名的函数如下:
static BaseType_t prvsumCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
{
const char *pcParameter;
BaseType_t xParameterStringLength, xReturn;
static UBaseType_t uxParameterNumber = 1;
static uint32_t sum_num = 0;
/* Remove compile time warnings about unused parameters, and check the
write buffer is not NULL. NOTE - for simplicity, this example assumes the
write buffer length is adequate, so does not check for buffer overflows. */
( void ) pcCommandString;
( void ) xWriteBufferLen;
configASSERT( pcWriteBuffer );
/* Obtain the parameter string. */
pcParameter = FreeRTOS_CLIGetParameter
(
pcCommandString, /* The command string itself. */
uxParameterNumber, /* Return the next parameter. */
&xParameterStringLength /* Store the parameter string length. */
);
if( pcParameter != NULL )
{
pcWriteBuffer[ 0 ] = 0x00; //ćŻć?ĄčżčĄŒĺ?‚ćžœä¸éœ€čŚčž“ĺ‡şďźŒĺ°ąč?ĺ°†pcWriteBufferć¸?0ďźŒč‡łĺ°‘ç??一ä¸?ĺ—节ć¸?0
sum_num += atoi(pcParameter);
/* There might be more parameters to return after this one. */
xReturn = pdTRUE;
uxParameterNumber++;
}
else
{
if(uxParameterNumber == 1)
{
memset( pcWriteBuffer, 0x00, xWriteBufferLen );
strcpy( pcWriteBuffer, "no parameters!\r\n" );
}
else
{
memset( pcWriteBuffer, 0x00, xWriteBufferLen );
sprintf( pcWriteBuffer, "sum = %d \r\n", sum_num );
sum_num = 0;
}
/* No more parameters were found. Make sure the write buffer does
not contain a valid string. */
// pcWriteBuffer[ 0 ] = 0x00;
/* Start over the next time this command is executed. */
uxParameterNumber = 1;
/* No more data to return. */
xReturn = pdFALSE;
}
return xReturn;
}
比较复杂,与cli组件耦合太深,还需要调用内部函数来获取命令行输入的参数。每次写一个新的命令,总是要参考之前的命令是怎么写,生怕搞错。
有没有办法把命令的回调函数整成类似main函数的写法
int main(int argc,char* argv[])
当执行这个函数的时候,直接传递的是当前的形参的个数,已经形参的数组呢?研究了一下发现确实可以。这里看下优化后的sum命令的回调函数写法。
优化后
优化后的sum命令回调函数如下:
static int sum_callback( int argc, char **argv)
{
int sum = atoi(argv[1])+atoi(argv[2])+atoi(argv[3]);
printf("sum = %d \r\n",sum);
return 0;
}
看,就是如此简洁,如此优雅,根本不需要调用任何cli中断组件的函数,耦合程度低。这样定义新的命令根本不需要看下之前的命令都是怎么写的。直接像定义main函数的方式来定义。so easy。
实现原理简述
参照了其他的开源终端组件,实现方式也不难,比如终端输入sum 1 2 3 回车。cli组件会输入的数据存放在一个字符串数组中。在原版的cli终端中,是采用轮询执行sum回调函数的方式,一个一个的读取输入的数据,这就造成回调函数必须要调用cli终端的获取参数的函数,并一个一个判断。比较麻烦。
改进后,在获取到"sum 1 2 3"这个字符串数组后,将其拆分为"sum", “1”, “2” ,"3"这4个字符串,将拆分后得到的字符串数量赋值给argc变量。将拆分后的字符串赋值给 *argv[] 字符串数据指针。最后调用回调函数,并且将argc,argv作为参数传递给回调函数。
代码下载
https://download.csdn.net/download/sinat_36568888/88041073