前言
一个功能强大的嵌入式shell,您可以查看它的GitHub
letter_shell是一个C语言编写的,可以嵌入在程序中的嵌入式shell,主要面向嵌入式设备,以C语言函数为运行单位,可以通过命令行调用,运行程序中的函数。通过移植这个工具,方便我们进行模块的单元测试。
移植
我们得先下载的文件,可以通过下载ZIP文件或者通过git clone命令克隆它。
这里不在赘述。
关于Freertos移植这里也不在赘述,可以看往期博客。
- 1.要配置好UART和中断(不在赘述)
- 2.配置一个GPIO进行点亮LED(可选)
首先先将src文件夹里的文件导入到项目里。在dome文件夹里找到stm32-freertos并把里面的文件导入工程里。并把它们配置好Incldue Path 和 Source Path。
打开shell_port.c文件并修改一些代码
- 1.#include “serial.h”(注释掉) #include “cevent.h” #include “log.h”(可选择注释掉)
- 2.改userShellWrite函数和userShellRead函数,可以参考入校
short userShellWrite(char *data, unsigned short len)
{
// serialTransmit(&debugSerial, (uint8_t *)data, len, 0x1FF);
HAL_UART_Transmit(&huart1, (uint8_t *)data, len, 0x1FF);
return len;
}
short userShellRead(char *data, unsigned short len)
{
// return serialReceive(&debugSerial, (uint8_t *)data, len, 0);
if(HAL_UART_Receive(&huart1, (uint8_t*)data, len, 0xFFFF) != HAL_OK)
{
return 0;
}
else
{
return 1;
}
}
- 3.修改下述函数
/**
* @brief 用户shell上锁
*
* @param shell shell
*
* @return int 0
*/
int userShellLock(Shell *shell)
{
// xSemaphoreTakeRecursive(shellMutex, portMAX_DELAY);
xSemaphoreTake(shellMutex, portMAX_DELAY);
return 0;
}
/**
* @brief 用户shell解锁
*
* @param shell shell
*
* @return int 0
*/
int userShellUnlock(Shell *shell)
{
// xSemaphoreGiveRecursive(shellMutex);
xSemaphoreGive(shellMutex);
return 0;
}
void userShellInit(void)
{
shellMutex = xSemaphoreCreateMutex();
shell.write = userShellWrite;
shell.read = userShellRead;
shell.lock = userShellLock;
shell.unlock = userShellUnlock;
shellInit(&shell, shellBuffer, 512);
xTaskCreate(shellTask, "shell", 256, &shell, 5, NULL);
}
CEVENT_EXPORT(EVENT_INIT_STAGE2, userShellInit);
- 4.在freertos.c里导入shell_port.h头文件
- 5.配置中断回调函数和调用userShellInit()函数,整体文件代码如下
/* USER CODE BEGIN Header */
/**
******************************************************************************
* File Name : freertos.c
* Description : Code for freertos applications
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "shell_port.h"
#include "usart.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
uint8_t recv_buf = 0;
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
int LED_ON(int Time);
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */
/* USER CODE END Variables */
/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
.name = "defaultTask",
.stack_size = 128 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for myTask02 */
osThreadId_t myTask02Handle;
const osThreadAttr_t myTask02_attributes = {
.name = "myTask02",
.stack_size = 128 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
/* USER CODE END FunctionPrototypes */
void StartDefaultTask(void *argument);
void StartTask02(void *argument);
void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
/**
* @brief FreeRTOS initialization
* @param None
* @retval None
*/
void MX_FREERTOS_Init(void) {
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* USER CODE BEGIN RTOS_MUTEX */
/* add mutexes, ... */
/* USER CODE END RTOS_MUTEX */
/* USER CODE BEGIN RTOS_SEMAPHORES */
/* add semaphores, ... */
/* USER CODE END RTOS_SEMAPHORES */
/* USER CODE BEGIN RTOS_TIMERS */
/* start timers, add new ones, ... */
/* USER CODE END RTOS_TIMERS */
/* USER CODE BEGIN RTOS_QUEUES */
/* add queues, ... */
/* USER CODE END RTOS_QUEUES */
/* Create the thread(s) */
/* creation of defaultTask */
defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);
/* creation of myTask02 */
myTask02Handle = osThreadNew(StartTask02, NULL, &myTask02_attributes);
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
/* USER CODE END RTOS_THREADS */
/* USER CODE BEGIN RTOS_EVENTS */
/* add events, ... */
/* USER CODE END RTOS_EVENTS */
}
/* USER CODE BEGIN Header_StartDefaultTask */
/**
* @brief Function implementing the defaultTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
/* USER CODE BEGIN StartDefaultTask */
userShellInit();
HAL_UART_Receive_IT(&huart1, (uint8_t*)&recv_buf, 1);
while(1)
{
}
/* USER CODE END StartDefaultTask */
}
/* USER CODE BEGIN Header_StartTask02 */
/**
* @brief Function implementing the myTask02 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTask02 */
void StartTask02(void *argument)
{
/* USER CODE BEGIN StartTask02 */
while(1)
{
}
/* USER CODE END StartTask02 */
}
/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
int LED_ON(int Time)
{
HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_SET);
HAL_Delay(Time);
HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_RESET);
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC), LED_ON, LED_ON, LED_ON);
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
/* 判断是哪个串口触发的中断 */
if(huart ->Instance == USART1)
{
//调用shell处理数据的接收
shellHandler(&shell, recv_buf);
//使能串口中断接收
HAL_UART_Receive_IT(&huart1, (uint8_t*)&recv_buf, 1);
}
}
/* USER CODE END Application */
注意事项
1.在实现LED闪烁会调用HAL_Delay()函数要注意它的中断优先级。防止延迟函数卡死。
2.头文件的导入
3.配置uart中断回调函数
结尾
本教程由于时间问题所以比较粗略,请谅解。您可以在我的GitHub上找到完整代码。感谢您的观看!谢谢!