STM32F103移植FreeRTOS-CLI

Posted 旧年不在666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STM32F103移植FreeRTOS-CLI相关的知识,希望对你有一定的参考价值。

STM32F103移植FreeRTOS-CLI

一、平台

  • 芯片:STM32F103RDT6
  • FreeRTOS版本:FreeRTOS V10.0.1
  • 开发工具:stm32cubemx V6.1.2 + keil MDK V5.27.1.0
  • 开发所用的库:HAL库

二、源码

FreeRTOS V10.0.1

三、串口配置

  • 采用USART1作为FreeRTOS-CLI中断命令行接口

在这里插入图片描述

  • 开启USART1全局中断

在这里插入图片描述

  • FreeRTOS以下三个配置,后面统计任务状态会用到

在这里插入图片描述

四、文件移植

  • 移植FreeRTOS-CLI的源码文件到工程中

在这里插入图片描述

  • 移植FreeRTOS提供的demo中的示例文件和串口终端文件到工程

在这里插入图片描述

  • 移植底层串口驱动文件serial.c和serial.h到工程

在这里插入图片描述

在这里插入图片描述

五、接口适配(以下只列出需要修改的地方)

  • 定义一个公共的头文件
#define __FreeRTOS_CLI_DEF_H__

#include "usart.h"
#include "log.h"
#include "FreeRTOS.h"

//FreeRTOS-CLI修改控制宏
#ifndef __FreeRTOS_CLI_RESTORE_EN__
#define __FreeRTOS_CLI_RESTORE_EN__                         0
#endif

//定义输出缓存大小
#ifndef configCOMMAND_INT_MAX_OUTPUT_SIZE
#define configCOMMAND_INT_MAX_OUTPUT_SIZE                   1024
#endif

#ifndef FreeRTOS_CLI_NEW_LINE
#define FreeRTOS_CLI_NEW_LINE                               "\\033[32mKavabot#\\033[0m"
#endif

#endif
  • 修改serial.c文件如下
//定义FreeRTOS-CLI全局串口接收缓存
uint8_t cli_rx_buff;
//定义FreeRTOS-CLI串口句柄
UART_HandleTypeDef *cli_com_handle = &huart1;


#if __FreeRTOS_CLI_RESTORE_EN__
/*-----------------------------------------------------------*/

/* UART interrupt handler. */
void vUARTInterruptHandler( void );

/*-----------------------------------------------------------*/
#endif


/*
 * See the serial2.h header file.
 */
xComPortHandle xSerialPortInitMinimal( unsigned long ulWantedBaud, unsigned portBASE_TYPE uxQueueLength )
{
xComPortHandle xReturn;

#if __FreeRTOS_CLI_RESTORE_EN__
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
#endif

	/* 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 ) )
	{
#if __FreeRTOS_CLI_RESTORE_EN__
		/* Enable USART1 clock */
		RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE );	

		/* Configure USART1 Rx (PA10) as input floating */
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
		GPIO_Init( GPIOA, &GPIO_InitStructure );
		
		/* Configure USART1 Tx (PA9) as alternate function push-pull */
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
		GPIO_Init( GPIOA, &GPIO_InitStructure );

		USART_InitStructure.USART_BaudRate = ulWantedBaud;
		USART_InitStructure.USART_WordLength = USART_WordLength_8b;
		USART_InitStructure.USART_StopBits = USART_StopBits_1;
		USART_InitStructure.USART_Parity = USART_Parity_No ;
		USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
		USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
		USART_InitStructure.USART_Clock = USART_Clock_Disable;
		USART_InitStructure.USART_CPOL = USART_CPOL_Low;
		USART_InitStructure.USART_CPHA = USART_CPHA_2Edge;
		USART_InitStructure.USART_LastBit = USART_LastBit_Disable;
		
		USART_Init( USART1, &USART_InitStructure );
		
		USART_ITConfig( USART1, USART_IT_RXNE, ENABLE );
		
		NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQChannel;
		NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = configLIBRARY_KERNEL_INTERRUPT_PRIORITY;
		NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
		NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
		NVIC_Init( &NVIC_InitStructure );
		
		USART_Cmd( USART1, ENABLE );		
#else

        HAL_UART_Receive_IT(cli_com_handle, &cli_rx_buff, 1);

#endif
	}
	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;
}


signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed char cOutChar, TickType_t xBlockTime )
{
signed portBASE_TYPE xReturn;

    //定义FreeRTOS-CLI串口发送缓存
    uint8_t cli_tx_buff;

	if( xQueueSend( xCharsForTx, &cOutChar, xBlockTime ) == pdPASS )
	{
		xReturn = pdPASS;
#if __FreeRTOS_CLI_RESTORE_EN__
		USART_ITConfig( USART1, USART_IT_TXE, ENABLE );
#else

        if (xQueueReceive(xCharsForTx, &cli_tx_buff, 0) == pdTRUE)
        {
            while(HAL_UART_Transmit_IT(cli_com_handle, &cli_tx_buff, 1) != HAL_OK);
        }

#endif
	}
	else
	{
		xReturn = pdFAIL;
	}

	return xReturn;
}


#if __FreeRTOS_CLI_RESTORE_EN__
void vUARTInterruptHandler( void )
{
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
char cChar;

	if( USART_GetITStatus( USART1, USART_IT_TXE ) == SET )
	{
		/* The interrupt was caused by the THR becoming empty.  Are there any
		more characters to transmit? */
		if( xQueueReceiveFromISR( xCharsForTx, &cChar, &xHigherPriorityTaskWoken ) == pdTRUE )
		{
			/* A character was retrieved from the queue so can be sent to the
			THR now. */
			USART_SendData( USART1, cChar );
		}
		else
		{
			USART_ITConfig( USART1, USART_IT_TXE, DISABLE );		
		}		
	}
	
	if( USART_GetITStatus( USART1, USART_IT_RXNE ) == SET )
	{
		cChar = USART_ReceiveData( USART1 );
		xQueueSendFromISR( xRxedChars, &cChar, &xHigherPriorityTaskWoken );
	}	
	
	portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
}
#else

/******************************************************************************
 * @Function: FreeRTOS_CLI_USART_RXNE_Callback
 * @Description: CLI串口接收中断回调函数
 * @Input: void
 * @Output: None
 * @Return: void
 * @Others: 此函数需要在USART1接收中断回调函数中调用
 * @param {UART_HandleTypeDef} *huart
*******************************************************************************/
void FreeRTOS_CLI_USART_RXNE_Callback(UART_HandleTypeDef *huart)
{
    portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;

    xQueueSendFromISR(xRxedChars, &cli_rx_buff, &xHigherPriorityTaskWoken);

    HAL_UART_Receive_IT(huart, &cli_rx_buff, 1);
}

#endif
  • 修改serial.h,增加以下内容
//添加FreeRTOS-CLI公共头文件
#include "FreeRTOS_CLI_def.h"

//声明FreeRTOS-CLI串口接收中断回调函数
void FreeRTOS_CLI_USART_RXNE_Callback(UART_HandleTypeDef *huart);
  • 修改UARTCommandConsole.c文件
#if __FreeRTOS_CLI_RESTORE_EN__
/*-----------------------------------------------------------*/

/*
 * The task that implements the command console processing.
 */
static void prvUARTCommandConsoleTask( void *pvParameters );
void vUARTCommandConsoleStart( uint16_t usStackSize, UBaseType_t uxPriority );

/*-----------------------------------------------------------*/
#endif


#if __FreeRTOS_CLI_RESTORE_EN__
/*-----------------------------------------------------------*/

void vUARTCommandConsoleStart( uint16_t usStackSize, UBaseType_t uxPriority )
{
	/* Create the semaphore used to access the UART Tx. */
	xTxMutex = xSemaphoreCreateMutex();
	configASSERT( xTxMutex );

	/* Create that task that handles the console itself. */
	xTaskCreate( 	prvUARTCommandConsoleTask,	/* The task that implements the command console. */
					"CLI",						/* Text name assigned to the task.  This is just to assist debugging.  The kernel does not use this name itself. */
					usStackSize,				/* The size of the stack allocated to the task. */
					NULL,						/* The parameter is not used, so NULL is passed. */
					uxPriority,					/* The priority allocated to the task. */
					NULL );						/* A handle is not required, so just pass NULL. */
}
/*-----------------------------------------------------------*/
#endif

#if __FreeRTOS_CLI_RESTORE_EN__
static void prvUARTCommandConsoleTask( void *pvParameters )
#else
void prvUARTCommandConsoleTask( void *pvParameters )
#endif
{

/* Create the semaphore used to access the UART Tx. */
xTxMutex = xSemaphoreCreateMutex();
configASSERT( xTxMutex );

六、使用

  • 按照以上的移植,基本可以正常工作了,下面直接调用接口来注册命令
/******************************************************************************
 * @Function: task_shell_run
 * @Description: SHELL任务函数入口
 * @Input: void
 * @Output: None
 * @Return: void
 * @Others: None
 * @param {void} *pvParameters
*******************************************************************************/
void task_shell_run(void *pvParameters)
{
    //这里会把示例命令注册
    vRegisterSampleCLICommands();

    while(1)
    {
        //这里会不断接收中断输入的命令进行处理
        prvUARTCommandConsoleTask(NULL);

        osDelay(2);
    }
}
  • 最终效果如下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yILxN0qN-1622434375337)(images/image-20210531121043288.png)]

七、至于如何添加自己的命令,后面再讲

以上是关于STM32F103移植FreeRTOS-CLI的主要内容,如果未能解决你的问题,请参考以下文章

GD32F103学习笔记——在GD32F103移植STM32F103代码

STM32F103R8T6系统移植到STM32F103RCT6

STM32F103移植freeRTOS(使用官方源码)

uC/OS-II在STM32F103上的移植

OLED程序在stm32f103上的移植

RTX移植STM32F103,超详细~