硬汉嵌入式论坛

 找回密码
 立即注册
查看: 870|回复: 1
收起左侧

[UART] STM32H7 DMA 無法收到任何訊息

[复制链接]

1

主题

1

回帖

4

积分

新手上路

积分
4
发表于 2022-12-16 14:23:59 | 显示全部楼层 |阅读模式
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);
} 



回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106959
QQ
发表于 2022-12-17 11:03:42 | 显示全部楼层
1、你的主RAM空间用的那个,不是用的TCM RAM吧,这个空间不支持DMA。
然后就是使用其它空间RAM,注意Cache的处理
2、针对你说的不定长问题,先测试下DMA定长接收是否正常。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-12 06:15 , Processed in 0.182852 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表