|
Hi 有問題想請教大家:
使用 Keli5 開發(參考 CubeMX 設定)在 STM32H7 透過 DMA(normal mode) 使用 Uart 接收不定長度的訊息,但完全接收不到(可以傳送)
使用 HAL 函式庫,也嘗試過 LL 庫但也無法
未 access RTOS semaphores/queues,UART Tx 在 one task
目前確認 intialize 順序沒問題,DMA access 得到位置
不知道有沒有人有什麼想法
[C] 纯文本查看 复制代码 /* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __FWUART_H
#define __FWUART_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32h7xx_hal.h"
#include "stdio.h"
/* Exported types ------------------------------------------------------------*/
#define USART_DEBUG USART1
#define USART_DEBUG_TX_PIN GPIO_PIN_14
#define USART_DEBUG_RX_PIN GPIO_PIN_15
#define USART_DEBUG_GPIO_PORT GPIOB
#define USART_DEBUG_AF GPIO_AF4_USART1
#define USART_DEBUG_IRQn USART1_IRQn
#define USART_DEBUG_IRQHandler USART1_IRQHandler
#define USART_DEBUG_CLK_ENABLE() __HAL_RCC_USART1_CLK_ENABLE()
#define USART_DEBUG_FORCE_RESET() __HAL_RCC_USART1_FORCE_RESET()
#define USART_DEBUG_RELEASE_RESET() __HAL_RCC_USART1_RELEASE_RESET()
#define USART_DEBUG_TX_DMA_STREAM DMA1_Stream0
#define USART_DEBUG_RX_DMA_STREAM DMA1_Stream1
#define USART_DEBUG_TX_DMA_REQUEST DMA_REQUEST_USART1_TX
#define USART_DEBUG_RX_DMA_REQUEST DMA_REQUEST_USART1_RX
#define USART_DEBUG_DMA_TX_IRQ DMA1_Stream0_IRQn
#define USART_DEBUG_DMA_RX_IRQ DMA1_Stream1_IRQn
#define USART_DEBUG_DMA_TX_IRQHandler DMA1_Stream0_IRQHandler
#define USART_DEBUG_DMA_RX_IRQHandler DMA1_Stream1_IRQHandler
#define USART_WIFI USART2
#define USART_WIFI_TX_PIN GPIO_PIN_2
#define USART_WIFI_RX_PIN GPIO_PIN_3
#define USART_WIFI_GPIO_PORT GPIOA
#define USART_WIFI_AF GPIO_AF7_USART2
#define USART_WIFI_IRQn USART2_IRQn
#define USART_WIFI_IRQHandler USART2_IRQHandler
#define USART_WIFI_CLK_ENABLE() __HAL_RCC_USART2_CLK_ENABLE()
#define USART_WIFI_FORCE_RESET() __HAL_RCC_USART2_FORCE_RESET()
#define USART_WIFI_RELEASE_RESET() __HAL_RCC_USART2_RELEASE_RESET()
#define USART_WIFI_TX_DMA_STREAM DMA1_Stream2
#define USART_WIFI_RX_DMA_STREAM DMA1_Stream3
#define USART_WIFI_TX_DMA_REQUEST DMA_REQUEST_USART2_TX
#define USART_WIFI_RX_DMA_REQUEST DMA_REQUEST_USART2_RX
#define USART_WIFI_DMA_TX_IRQ DMA1_Stream2_IRQn
#define USART_WIFI_DMA_RX_IRQ DMA1_Stream3_IRQn
#define USART_WIFI_DMA_TX_IRQHandler DMA1_Stream2_IRQHandler
#define USART_WIFI_DMA_RX_IRQHandler DMA1_Stream3_IRQHandler
typedef enum uartSource_e {
UART_SOURCE_DEBUG,
UART_SOURCE_WIFI
}uartSource_t;
typedef enum fwUartChannel_e{
UART_CHANNEL_START,
UART_CHANNEL_DEBUG = UART_CHANNEL_START,
UART_CHANNEL_WIFI,
UART_CHANNEL_NUM
}fwUartChannel_t;
typedef enum fwUartDmaMoving_e {
UART_DMA_IDLE,
UART_DMA_MOVING
}fwUartDmaMoving_t;
typedef struct fwUartHandler_s{
UART_HandleTypeDef uartHandle;
DMA_HandleTypeDef txDmaH;
DMA_HandleTypeDef rxDmaH;
dmaBuf_t txDmaB;
dmaBuf_t rxDmaB;
queueIndex_t txBufQ;
queueIndex_t rxBufQ;
}fwUartHandler_t;
/* Exported constants --------------------------------------------------------*/
/* Exported macro ----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
void fwUartThreadInit(void);
void fwUartInit(UART_HandleTypeDef *UartHandle);
void fwUartReceiveData(uartSource_t utSource, uint8_t u8tData);
bool fwUartGetData(uartSource_t utSource, uint8_t *u8tData);
void fwUartTxWrite(fwUartChannel_t aUartCh, uint8_t u8tData);
extern fwUartHandler_t uartList[UART_CHANNEL_NUM];
#ifdef __cplusplus
}
#endif
#endif /* __FWUART_H */
[C] 纯文本查看 复制代码 /* Includes ------------------------------------------------------------------*/
#include <general.h>
#include <globalV.h>
#include "cmsis_os.h"
#include "fwUart.h"
#include <main.h>
#include "cmdline.h"
#include "fwWifi.h"
#include "fwWatchbox.h"
/* Private define ------------------------------------------------------------*/
#define DEBUG_DMA_TX_BUFF_SIZE QUEUE_SIZE_SET(7) // 2^7 = 128
#define DEBUG_DMA_RX_BUFF_SIZE QUEUE_SIZE_SET(6) // 2^6 = 64
#define DEBUG_UART_TX_BUFF_SIZE QUEUE_SIZE_SET(9) // 2^9 = 512
#define DEBUG_UART_RX_BUFF_SIZE QUEUE_SIZE_SET(7) // 2^7 = 128
#define WIFI_DMA_TX_BUFF_SIZE QUEUE_SIZE_SET(10) // 2^10 = 1024
#define WIFI_DMA_RX_BUFF_SIZE QUEUE_SIZE_SET(8) // 2^8 = 256
#define WIFI_UART_TX_BUFF_SIZE QUEUE_SIZE_SET(10) // 2^10 = 1024
#define WIFI_UART_RX_BUFF_SIZE QUEUE_SIZE_SET(9) // 2^9 = 512
/* Private typedef -----------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
static void fwUartThread(void const *argument);
void fwUartWathThread(void);
void fwUartTxCheck(void);
fwUartChannel_t fwUartSearchChannel(UART_HandleTypeDef *huart);
void fwUartTxDmaTouch(UART_HandleTypeDef *huart);
void fwUartTxDmaDone(UART_HandleTypeDef *huart);
void fwUartRxDmaReceive(UART_HandleTypeDef *huart, uint16_t Size);
/* Private variables ---------------------------------------------------------*/
osThreadId tidUartHandle;
SECTION_RAM_DMA static uint8_t dmaDebugTxbuf[DEBUG_DMA_TX_BUFF_SIZE];
SECTION_RAM_DMA static uint8_t dmaDebugRxbuf[DEBUG_DMA_RX_BUFF_SIZE];
uint8_t uartDebugTxbuf[DEBUG_UART_TX_BUFF_SIZE];
uint8_t uartDebugRxbuf[DEBUG_UART_RX_BUFF_SIZE];
SECTION_RAM_DMA static uint8_t dmaWifiTxbuf[WIFI_DMA_TX_BUFF_SIZE];
SECTION_RAM_DMA static uint8_t dmaWifiRxbuf[WIFI_DMA_RX_BUFF_SIZE];
uint8_t uartWifiTxbuf[WIFI_UART_TX_BUFF_SIZE];
uint8_t uartWifiRxbuf[WIFI_UART_RX_BUFF_SIZE];
SECTION_RAM_DMA static uint8_t testRx;
fwUartHandler_t uartList[UART_CHANNEL_NUM] = {
[UART_CHANNEL_DEBUG] = {
.uartHandle.Instance = USART_DEBUG,
.txDmaB = {
.flagMoving = UART_DMA_IDLE,
.dataLen = 0,
.size = DEBUG_DMA_TX_BUFF_SIZE,
.buf = dmaDebugTxbuf,
},
.rxDmaB = {
.flagMoving = UART_DMA_IDLE,
.dataLen = 0,
.size = DEBUG_DMA_RX_BUFF_SIZE,
.buf = dmaDebugRxbuf,
},
.txBufQ = {
.put = 0,
.get = 0,
.size = DEBUG_UART_TX_BUFF_SIZE,
.buf = uartDebugTxbuf,
},
.rxBufQ = {
.put = 0,
.get = 0,
.size = DEBUG_UART_RX_BUFF_SIZE,
.buf = uartDebugRxbuf,
},
},
[UART_CHANNEL_WIFI] = {
.uartHandle.Instance = USART_WIFI,
.txDmaB = {
.flagMoving = UART_DMA_IDLE,
.dataLen = 0,
.size = WIFI_DMA_TX_BUFF_SIZE,
.buf = dmaWifiTxbuf,
},
.rxDmaB = {
.flagMoving = UART_DMA_IDLE,
.dataLen = 0,
.size = WIFI_DMA_RX_BUFF_SIZE,
.buf = dmaWifiRxbuf,
},
.txBufQ = {
.put = 0,
.get = 0,
.size = WIFI_UART_TX_BUFF_SIZE,
.buf = uartWifiTxbuf,
},
.rxBufQ = {
.put = 0,
.get = 0,
.size = WIFI_UART_RX_BUFF_SIZE,
.buf = uartWifiRxbuf,
},
},
};
/* Private functions ---------------------------------------------------------*/
/******************************************************************************
* @brief UART thread initial function
*****************************************************************************/
void fwUartThreadInit(void)
{
fwUartInit(&(uartList[UART_CHANNEL_DEBUG].uartHandle));
fwUartInit(&(uartList[UART_CHANNEL_WIFI].uartHandle));
fwWifiInit();
osThreadDef(nameUartThread, fwUartThread, osPriorityNormal, 0, configMINIMAL_STACK_SIZE);
tidUartHandle = osThreadCreate(osThread(nameUartThread), NULL);
}
/******************************************************************************
* @brief UART thread function
*****************************************************************************/
static void fwUartThread(void const *argument)
{
(void) argument;
cmdlineInit();
switch_log(systemConfig.log.items.general, "> Uart thread start\r\n");
for (;;)
{
cmdlineThread();
fwWifiThread();
fwUartTxCheck();
osDelay(1);
}
}
/******************************************************************************
* @brief UART driver initial function
*****************************************************************************/
void fwUartInit(UART_HandleTypeDef *UartHandle)
{
if(UartHandle->Instance == USART_DEBUG)
{
UartHandle->Init.BaudRate = 115200;
UartHandle->Init.WordLength = UART_WORDLENGTH_8B;
UartHandle->Init.StopBits = UART_STOPBITS_1;
UartHandle->Init.Parity = UART_PARITY_NONE;
UartHandle->Init.Mode = UART_MODE_TX_RX;
UartHandle->Init.HwFlowCtl = UART_HWCONTROL_NONE;
UartHandle->Init.OverSampling = UART_OVERSAMPLING_16;
UartHandle->Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
UartHandle->Init.ClockPrescaler = UART_PRESCALER_DIV1;
UartHandle->AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
HAL_UART_Init(UartHandle);
HAL_UARTEx_SetTxFifoThreshold(UartHandle, UART_TXFIFO_THRESHOLD_1_8);
HAL_UARTEx_SetRxFifoThreshold(UartHandle, UART_RXFIFO_THRESHOLD_1_8);
HAL_UARTEx_DisableFifoMode(UartHandle);
HAL_UARTEx_ReceiveToIdle_DMA(UartHandle, uartList[UART_CHANNEL_DEBUG].rxDmaB.buf, uartList[UART_CHANNEL_DEBUG].rxDmaB.size);
}
else if(UartHandle->Instance == USART_WIFI)
{
UartHandle->Init.BaudRate = 115200;
UartHandle->Init.WordLength = UART_WORDLENGTH_8B;
UartHandle->Init.StopBits = UART_STOPBITS_1;
UartHandle->Init.Parity = UART_PARITY_NONE;
UartHandle->Init.Mode = UART_MODE_TX_RX;
UartHandle->Init.HwFlowCtl = UART_HWCONTROL_NONE;
UartHandle->Init.OverSampling = UART_OVERSAMPLING_16;
UartHandle->Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
UartHandle->Init.ClockPrescaler = UART_PRESCALER_DIV1;
UartHandle->AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
HAL_UART_Init(UartHandle);
HAL_UARTEx_SetTxFifoThreshold(UartHandle, UART_TXFIFO_THRESHOLD_1_8);
HAL_UARTEx_SetRxFifoThreshold(UartHandle, UART_RXFIFO_THRESHOLD_1_8);
HAL_UARTEx_DisableFifoMode(UartHandle);
HAL_UARTEx_ReceiveToIdle_DMA(UartHandle, uartList[UART_CHANNEL_WIFI].rxDmaB.buf, uartList[UART_CHANNEL_WIFI].rxDmaB.size);
}
}
/******************************************************************************
* @brief Retargets the C library printf function to the USART.
*****************************************************************************/
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf set to 'Yes') calls __io_putchar() */
int __io_putchar(int ch)
#else
int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
{
/* Place your implementation of fputc here */
/* e.g. write a character to the USART1 and Loop until the end of transmission */
fwUartTxWrite(UART_CHANNEL_DEBUG, (uint8_t)ch);
return ch;
}
/******************************************************************************
* @brief UART firmware get data.
*****************************************************************************/
bool fwUartGetData(uartSource_t utSource, uint8_t *u8tData)
{
switch(utSource)
{
case UART_SOURCE_DEBUG:
{
if(QUEUE_CHECK_NOT_EMPTY(uartList[UART_CHANNEL_DEBUG].rxBufQ))
{
*u8tData = uartList[UART_CHANNEL_DEBUG].rxBufQ.buf[QUEUE_GET_GET_INDEX(uartList[UART_CHANNEL_DEBUG].rxBufQ)];
QUEUE_ADD_GET_INDEX(uartList[UART_CHANNEL_DEBUG].rxBufQ);
return true;
}
else {
return false;
}
}
break;
case UART_SOURCE_WIFI:
{
if(QUEUE_CHECK_NOT_EMPTY(uartList[UART_CHANNEL_WIFI].rxBufQ))
{
*u8tData = uartList[UART_CHANNEL_WIFI].rxBufQ.buf[QUEUE_GET_GET_INDEX(uartList[UART_CHANNEL_WIFI].rxBufQ)];
QUEUE_ADD_GET_INDEX(uartList[UART_CHANNEL_WIFI].rxBufQ);
return true;
}
else {
return false;
}
}
break;
default:
{
}
break;
}
return false;
}
/******************************************************************************
* @brief UART Tx write function
*****************************************************************************/
void fwUartTxWrite(fwUartChannel_t aUartCh, uint8_t u8tData)
{
if(QUEUE_CHECK_NOT_FULL(uartList[aUartCh].txBufQ))
{
uartList[aUartCh].txBufQ.buf[QUEUE_GET_PUT_INDEX(uartList[aUartCh].txBufQ)] = u8tData;
QUEUE_ADD_PUT_INDEX(uartList[aUartCh].txBufQ);
}
}
/******************************************************************************
* @brief UART Tx check function
*****************************************************************************/
void fwUartTxCheck(void)
{
fwUartChannel_t tUartChannel;
for(tUartChannel = UART_CHANNEL_START ; tUartChannel < UART_CHANNEL_NUM ; tUartChannel++)
{
if(uartList[tUartChannel].txDmaB.flagMoving == UART_DMA_IDLE) {
fwUartTxDmaTouch(&(uartList[tUartChannel].uartHandle));
}
}
}
/******************************************************************************
* @brief UART search function
*****************************************************************************/
fwUartChannel_t fwUartSearchChannel(UART_HandleTypeDef *huart)
{
fwUartChannel_t tSearchUartCh;
for(tSearchUartCh = UART_CHANNEL_START ; tSearchUartCh < UART_CHANNEL_NUM ; tSearchUartCh++)
{
if(uartList[tSearchUartCh].uartHandle.Instance == huart->Instance) {
break;
}
}
return tSearchUartCh;
}
/******************************************************************************
* @brief UART Tx DMA done function
*****************************************************************************/
void fwUartTxDmaDone(UART_HandleTypeDef *huart)
{
fwUartChannel_t tUartChannel = fwUartSearchChannel(huart);
uartList[tUartChannel].txDmaB.flagMoving = UART_DMA_IDLE;
}
/******************************************************************************
* @brief UART Tx DMA Touch function
*****************************************************************************/
void fwUartTxDmaTouch(UART_HandleTypeDef *huart)
{
fwUartChannel_t tUartChannel = fwUartSearchChannel(huart);
if(uartList[tUartChannel].txDmaB.flagMoving == UART_DMA_MOVING) {
return;
}
if(QUEUE_CHECK_NOT_EMPTY(uartList[tUartChannel].txBufQ))
{
uartList[tUartChannel].txDmaB.dataLen = 0;
while(QUEUE_CHECK_NOT_EMPTY(uartList[tUartChannel].txBufQ))
{
if(uartList[tUartChannel].txDmaB.dataLen < uartList[tUartChannel].txDmaB.size)
{
uartList[tUartChannel].txDmaB.buf[uartList[tUartChannel].txDmaB.dataLen] = uartList[tUartChannel].txBufQ.buf[QUEUE_GET_GET_INDEX(uartList[tUartChannel].txBufQ)];
QUEUE_ADD_GET_INDEX(uartList[tUartChannel].txBufQ);
(uartList[tUartChannel].txDmaB.dataLen)++;
}
else {
break;
}
}
uartList[tUartChannel].txDmaB.flagMoving = UART_DMA_MOVING;
HAL_UART_Transmit_DMA(&(uartList[tUartChannel].uartHandle), uartList[tUartChannel].txDmaB.buf, uartList[tUartChannel].txDmaB.dataLen);
}
}
/******************************************************************************
* @brief UART Rx DMA Receive function
*****************************************************************************/
void fwUartRxDmaReceive(UART_HandleTypeDef *huart, uint16_t Size)
{
fwUartChannel_t tUartChannel = fwUartSearchChannel(huart);
uint16_t u16tIndex;
for(u16tIndex = 0 ; (u16tIndex < Size) && (QUEUE_CHECK_NOT_FULL(uartList[tUartChannel].rxBufQ)) ; u16tIndex++)
{
uartList[tUartChannel].rxBufQ.buf[QUEUE_GET_PUT_INDEX(uartList[tUartChannel].rxBufQ)] = huart->pRxBuffPtr[u16tIndex];
QUEUE_ADD_PUT_INDEX(uartList[tUartChannel].rxBufQ);
}
//if(tUartChannel == UART_CHANNEL_DEBUG)
HAL_UARTEx_ReceiveToIdle_DMA(&(uartList[tUartChannel].uartHandle), uartList[tUartChannel].rxDmaB.buf, uartList[tUartChannel].rxDmaB.size);
}
/**
* @brief Tx Transfer completed callback.
* @param huart UART handle.
* @retval None
*/
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
//__disable_irq();
fwUartTxDmaDone(huart);
fwUartTxDmaTouch(huart);
//__enable_irq();
}
/**
* @brief Reception Event Callback (Rx event notification called after use of advanced reception service).
* @param huart UART handle
* @param Size Number of data available in application reception buffer (indicates a position in
* reception buffer until which, data are available)
* @retval None
*/
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
fwUartRxDmaReceive(huart, Size);
}
|
|