FreeRTOS-Plus-CLI使用笔记
一、简介
详细介绍可参考FreeRTOS-Plus-CLI官网地址入口
FreeRTOS+CLI(Command Line Interface, 命令行接口)提供了一种简单、小型、可扩展且RAM高效的方法,使FreeRTOS应用程序能够处理命令行输入。添加一条指令的步骤如下:
- 提供一个实现命令功能的函数
- 将命令映射到该功能函数
- 注册命令
- 运行命令解释器
命令行调试接口对于排查分析出现的问题提供了很好的接口,可以通过查看传感器信息判断传感器是否正常,可以查看内置的报警信息是否有触发等。
二、移植
环境:keil MDK
芯片:STM32F429
库类型:HAL
获取文件
首先需要获取FreeRTOS源码,移植FreeRTOS+CLI功能,首先要从源码中提取下列文件:
FreeRTOS-Plus/Source/FreeRTOS-Plus-CLI
文件夹下的FreeRTOS_CLI.c/h
文件。FreeRTOS-Plus/Demo/Common/FreeRTOS_Plus_CLI_Demos
文件夹下的Sample-CLI-commands.c
和UARTCommandConsole.c
文件。FreeRTOS/Demo/Common/include
文件夹下的serial.h
文件和FreeRTOS\Demo\CORTEX_STM32F103_Keil\serial
文件夹下的serial.c
文件
//移植文件夹结构
|-FreeRTOS-Plus-CLI
|---FreeRTOS_CLI.c //命令处理的核心
|---FreeRTOS_CLI.h
|---UARTCommandConsole.c //定义FreeRTOS上运行的任务
|---Sample-CLI-commands.c //命令定义及实现
|---serial.c //底层接口实现
|---serial.h
修改文件
将这些文件添加到工程中首要实现的便是底层接口,这里我才用的是串口DMA+IDLE中断的方式来接收数据,串口轮询的方式来发送数据。(单纯用串口RXNE中断的方式来接收,在发送较长指令的情况下可能会存在,发送和回显不一致的情况)。
serial.c
文件修改xSerialPortInitMinimal
函数,这里的bsp_usart3Init
函数为配置串口3通用配置和开启DMA接收和IDLE中断
xComPortHandle xSerialPortInitMinimal( unsigned long ulWantedBaud, unsigned portBASE_TYPE uxQueueLength )
{
xComPortHandle xReturn;
/* Create the queues used to hold Rx/Tx characters. */
xRxedChars = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed char ) );
xCharsForTx = xQueueCreate( uxQueueLength + 1, ( unsigned portBASE_TYPE ) sizeof( signed char ) );
/* If the queue/semaphore was created correctly then setup the serial port
hardware. */
if( ( xRxedChars != serINVALID_QUEUE ) && ( xCharsForTx != serINVALID_QUEUE ) )
{
/*修改:初始化串口3 */
bsp_usart3Init(115200);
}
else
{
xReturn = ( xComPortHandle ) 0;
}
/* This demo file only supports a single port but we have to return
something to comply with the standard demo header file. */
return xReturn;
}
serial.c
文件修改xSerialPutChar
函数,改为轮询的方式发送数据
signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed char cOutChar, TickType_t xBlockTime )
{
signed portBASE_TYPE xReturn;
if( xQueueSend( xCharsForTx, &cOutChar, xBlockTime ) == pdPASS )
{
xReturn = pdPASS;
uint8_t cChar;
/*修改:发送队列中有数据,通过轮询方式发送出去 */
if(xQueueReceive(xCharsForTx, &cChar, 0) == pdTRUE) {
if((HAL_UART_GetState(&huart3) & HAL_UART_STATE_BUSY_TX) != HAL_UART_STATE_BUSY_TX) {
HAL_UART_Transmit(&huart3, &cChar, 1, 1000); //轮询方式将数据发送出去
}
}
}
else
{
xReturn = pdFAIL;
}
return xReturn;
}
stm32f4xx_it.c
文件:实现串口3中断服务函数
void USART3_IRQHandler(void)
{
BaseType_t pxHigherPriorityTaskWoken = pdFALSE;
if(__HAL_UART_GET_FLAG(&huart3, UART_FLAG_IDLE) != RESET) { //IDLE中断(说明接收到了一帧数据)
__HAL_UART_CLEAR_IDLEFLAG(&huart3); //清除IDLE中断标志位
HAL_UART_DMAStop(&huart3);
usart3_rx_buffer.finish_flag = 1;
usart3_rx_buffer.len = USART_RX_BUFFER_SIZE - __HAL_DMA_GET_COUNTER(huart3.hdmarx);//hdma_usart1_rx.Instance->NDTR;
for(uint16_t i = 0; i < usart3_rx_buffer.len; ++i) {
xQueueSendFromISR(xRxedChars, &usart3_rx_buffer.data[i], &pxHigherPriorityTaskWoken);
}
HAL_UART_Receive_DMA(&huart3, usart3_rx_buffer.data, USART_RX_BUFFER_SIZE);
}
HAL_UART_IRQHandler(&huart3);
portYIELD_FROM_ISR(pxHigherPriorityTaskWoken);
}
FreeRTOSConfig.h
文件添加configCOMMAND_INT_MAX_OUTPUT_SIZE
宏的定义。
/****************************************************************
FreeRTOS Plus CLI相关的配置
****************************************************************/
#define configCOMMAND_INT_MAX_OUTPUT_SIZE 1024
main.c
文件中开启系统调度前添加如下语句:
vRegisterSampleCLICommands();
vUARTCommandConsoleStart( 512, 1 );
三、使用
连接串口助手通过输入help
可以答应帮助命令信息。
仿照Sample-CLI-commamnds.c
文件提供的示例,来设计符合自己需求的命令。
注意:
在实际使用中发现如果发送的命令长度超过50个字节,便会导致死机(程序进入hardfalt中断),通过调试发现是UARTCommandConsole.c
文件中prvUARTCommandConsoleTask
函数调用如下语句引起的问题:
strcpy( cLastInputString, cInputString );
因为指令长度的宏cmdMAX_INPUT_SIZE
被配置为50,当指令长度超过50时调用strcpy
函数便会访问非法地址,导致进入hardfalt
中断。这里需要将上述语句改为如下:
strncpy(cLastInputString, cInputString, cmdMAX_INPUT_SIZE);
只复制特定数目的数据,防止越界导致程序崩溃。
四、参考文档
https://blog.csdn.net/qq_41544116/article/details/105095063