142 lines
3.6 KiB
C
142 lines
3.6 KiB
C
/**
|
||
* @file shell_port.c
|
||
*/
|
||
|
||
#include "FreeRTOS.h"
|
||
#include "task.h"
|
||
#include "shell.h"
|
||
|
||
#include "stm32f4xx_hal.h"
|
||
#include "usart.h"
|
||
|
||
#include "shell_port.h"
|
||
#include "semphr.h"
|
||
|
||
Shell shell;
|
||
char shellBuffer[512];
|
||
|
||
static SemaphoreHandle_t shellMutex;
|
||
|
||
// DMA接收缓冲区和shell环形缓冲区
|
||
#define SHELL_UART_DMA_BUF_SIZE 256
|
||
#define SHELL_UART_RX_BUF_SIZE 128
|
||
static uint8_t shell_uart_dma_buf[SHELL_UART_DMA_BUF_SIZE];
|
||
static uint8_t shell_uart_rx_buf[SHELL_UART_RX_BUF_SIZE];
|
||
static volatile uint16_t shell_uart_rx_head = 0;
|
||
static volatile uint16_t shell_uart_rx_tail = 0;
|
||
static volatile uint16_t shell_uart_dma_last_pos = 0;
|
||
|
||
/**
|
||
* @brief 用户shell写
|
||
*
|
||
* @param data 数据
|
||
* @param len 数据长度
|
||
*
|
||
* @return short 实际写入的数据长度
|
||
*/
|
||
short userShellWrite(char *data, unsigned short len)
|
||
{
|
||
HAL_UART_Transmit(&huart1, (uint8_t *)data, len, 0x1FF);
|
||
return len;
|
||
}
|
||
|
||
/**
|
||
* @brief 用户shell读
|
||
*
|
||
* @param data 数据
|
||
* @param len 数据长度
|
||
*
|
||
* @return short 实际读取到
|
||
*/
|
||
|
||
// 从环形缓冲区读取数据
|
||
short userShellRead(char *data, unsigned short len)
|
||
{
|
||
unsigned short count = 0;
|
||
while (count < len)
|
||
{
|
||
if (shell_uart_rx_head == shell_uart_rx_tail)
|
||
{
|
||
// 缓冲区无数据
|
||
break;
|
||
}
|
||
data[count++] = shell_uart_rx_buf[shell_uart_rx_tail];
|
||
shell_uart_rx_tail = (shell_uart_rx_tail + 1) % SHELL_UART_RX_BUF_SIZE;
|
||
}
|
||
return count;
|
||
}
|
||
|
||
/**
|
||
* @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;
|
||
}
|
||
|
||
/**
|
||
* @brief 用户shell初始化
|
||
*
|
||
*/
|
||
void userShellInit(void)
|
||
{
|
||
shellMutex = xSemaphoreCreateMutex();
|
||
|
||
shell.write = userShellWrite;
|
||
shell.read = userShellRead;
|
||
shell.lock = userShellLock;
|
||
shell.unlock = userShellUnlock;
|
||
shellInit(&shell, shellBuffer, 512);
|
||
|
||
// 启动DMA接收
|
||
HAL_UART_Receive_DMA(&huart1, shell_uart_dma_buf, SHELL_UART_DMA_BUF_SIZE);
|
||
// 使能空闲中断
|
||
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
|
||
|
||
xTaskCreate((TaskFunction_t)shellTask, // 任务入口函数
|
||
(const char *)"shell_task", // 任务名字
|
||
(uint16_t)1024, // 任务栈大小
|
||
(void *)&shell, // 任务入口函数参数(传递 shell 对象指针)
|
||
(UBaseType_t)1, // 任务优先级
|
||
NULL); // 任务句柄
|
||
}
|
||
|
||
// USART1 空闲中断处理(DMA新数据转入shell缓冲区)
|
||
void shell_uart_rx_idle_callback(void)
|
||
{
|
||
uint16_t dma_pos = SHELL_UART_DMA_BUF_SIZE - __HAL_DMA_GET_COUNTER(huart1.hdmarx);
|
||
uint16_t data_len = (dma_pos >= shell_uart_dma_last_pos) ? (dma_pos - shell_uart_dma_last_pos) : (SHELL_UART_DMA_BUF_SIZE - shell_uart_dma_last_pos + dma_pos);
|
||
for (uint16_t i = 0; i < data_len; i++)
|
||
{
|
||
uint8_t ch = shell_uart_dma_buf[(shell_uart_dma_last_pos + i) % SHELL_UART_DMA_BUF_SIZE];
|
||
uint16_t next = (shell_uart_rx_head + 1) % SHELL_UART_RX_BUF_SIZE;
|
||
if (next != shell_uart_rx_tail)
|
||
{
|
||
shell_uart_rx_buf[shell_uart_rx_head] = ch;
|
||
shell_uart_rx_head = next;
|
||
}
|
||
}
|
||
shell_uart_dma_last_pos = dma_pos;
|
||
}
|
||
// CEVENT_EXPORT(EVENT_INIT_STAGE2, userShellInit);
|