STM32H7 上 使用 DMA 但 Uart 無法接收訊息

Hi 有問題想請教大家:
使用 Keli5 開發(參考 CubeMX 設定)在 STM32H7 透過 DMA(normal mode) 使用 Uart 接收不定長度的訊息,但完全接收不到(可以傳送)
使用 HAL 函式庫,也嘗試過 LL 庫但也無法
未 access RTOS semaphores/queues,UART Tx 在 one task
目前確認 intialize 順序沒問題,DMA access 得到位置

/* 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);
} 

/* 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 */