硬汉嵌入式论坛

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

[STM32H7] stmh723的emmc读写测试 一直卡在这个函数里SDMMC_GetCmdResp1(),使用DMA进行读写,有大佬遇到过这种情况吗。debug单步调试可...

[复制链接]

1

主题

7

回帖

10

积分

新手上路

积分
10
发表于 2024-7-18 10:57:05 | 显示全部楼层 |阅读模式


emmc配置

读写测试
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115490
QQ
发表于 2024-7-18 11:03:18 | 显示全部楼层
改用eMMC的1线方式试试
回复

使用道具 举报

1

主题

7

回帖

10

积分

新手上路

积分
10
 楼主| 发表于 2024-7-18 11:18:41 | 显示全部楼层
eric2013 发表于 2024-7-18 11:03
改用eMMC的1线方式试试

[C] 纯文本查看 复制代码
/**
 * @file 
 * @author
 * @brief 
 * @version 1.0
 * @date 2024-06-24
 * @copyright Copyright (c) 
 * Provides a serial port service interface that supports multithreaded calls
 */

/***********************************************************************
 ** INCLUDE                                                           **
 **********************************************************************/
#include "cal_mmc.h"
#include "stm32h7xx_hal_sd.h"
#include "stm32h7xx_hal_mmc.h"
#include "ahd_tpv706sl1.h"
/***********************************************************************
 ** CONSTANT ( MACRO AND ENUM )                                       **
 **********************************************************************/
#define MMC1_D0_PORT 	GPIOC
#define MMC1_D0_PIN		CAL_GPIO_PIN_8

#define MMC1_D1_PORT 	GPIOC
#define MMC1_D1_PIN		CAL_GPIO_PIN_9

#define MMC1_D2_PORT 	GPIOC
#define MMC1_D2_PIN		CAL_GPIO_PIN_10

#define MMC1_D3_PORT 	GPIOC
#define MMC1_D3_PIN		CAL_GPIO_PIN_11

#define MMC1_CLK_PORT 	GPIOC
#define MMC1_CLK_PIN	CAL_GPIO_PIN_12

#define MMC1_CMD_PORT 	GPIOD
#define MMC1_CMD_PIN	CAL_GPIO_PIN_2

#define MMC1_RST_PORT 	GPIOG
#define MMC1_RST_PIN	CAL_GPIO_PIN_14

#define cal_sd_mcc1_set()	cal_gpio_write(MMC1_RST_PORT,MMC1_RST_PIN,CAL_GPIO_LEVEL_HIGH)
#define cal_sd_mcc1_reset()	cal_gpio_write(MMC1_RST_PORT,MMC1_RST_PIN,CAL_GPIO_LEVEL_LOW)

#define ABLOCK_SIZE 512
#define EMMC_WAIT_CNT  0xFFFF
//MMC_HandleTypeDef uSdHandle;
__attribute__((section(".Mmc_Struct_Section"))) MMC_HandleTypeDef uSdHandle;;
__attribute__((section(".Mmc_Tx_Section"))) uint8_t g_mmc_tx_buf[2048];
__attribute__((section(".Mmc_Rx_Section"))) uint8_t g_mmc_rx_buf[2048];
void cal_emmc_init(void)
{
	uint16_t i = 0xFFFF;
	RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
	PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SDMMC;
	PeriphClkInitStruct.SdmmcClockSelection = RCC_SDMMCCLKSOURCE_PLL;
	HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
	
	uSdHandle.Instance = SDMMC1;	
	uSdHandle.Init.ClockDiv = 4;
	uSdHandle.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
	uSdHandle.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
	uSdHandle.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;//SDMMC_HARDWARE_FLOW_CONTROL_ENABLE;
	uSdHandle.Init.BusWide = SDMMC_BUS_WIDE_4B;
	
	__HAL_RCC_SDMMC1_CLK_ENABLE();
	__HAL_RCC_GPIOC_CLK_ENABLE();
	__HAL_RCC_GPIOD_CLK_ENABLE();
	__HAL_RCC_GPIOG_CLK_ENABLE();
	
			/**SDMMC1 GPIO Configuration
		PC8     ------> SDMMC1_D0
		PC9     ------> SDMMC1_D1
		PC10     ------> SDMMC1_D2
		PC11     ------> SDMMC1_D3
		PC12     ------> SDMMC1_CK
		PD2     ------> SDMMC1_CMD
		*/
	cal_gpio_init(MMC1_D0_PORT,MMC1_D0_PIN,CAL_GPIO_MODE_AF_PP,CAL_GPIO_PULLUP,CAL_GPIO_AF_12);	
	cal_gpio_init(MMC1_D1_PORT,MMC1_D1_PIN,CAL_GPIO_MODE_AF_PP,CAL_GPIO_NOPULL,CAL_GPIO_AF_12);
	cal_gpio_init(MMC1_D2_PORT,MMC1_D2_PIN,CAL_GPIO_MODE_AF_PP,CAL_GPIO_NOPULL,CAL_GPIO_AF_12);
	cal_gpio_init(MMC1_D3_PORT,MMC1_D3_PIN,CAL_GPIO_MODE_AF_PP,CAL_GPIO_NOPULL,CAL_GPIO_AF_12);
	cal_gpio_init(MMC1_CMD_PORT,MMC1_CMD_PIN,CAL_GPIO_MODE_AF_PP,CAL_GPIO_NOPULL,CAL_GPIO_AF_12);
	cal_gpio_init(MMC1_CLK_PORT,MMC1_CLK_PIN,CAL_GPIO_MODE_AF_PP,CAL_GPIO_NOPULL,CAL_GPIO_AF_12);
	cal_gpio_init(MMC1_RST_PORT,MMC1_RST_PIN,CAL_GPIO_MODE_OUTPUT_PP,CAL_GPIO_NOPULL,CAL_GPIO_AF_0);

	HAL_NVIC_SetPriority(SDMMC1_IRQn,3,1);  //配置SDMMC1中断
	HAL_NVIC_EnableIRQ(SDMMC1_IRQn);        //使能SDMMC1中断
	HAL_MMC_Init(&uSdHandle);
	HAL_MMC_ConfigWideBusOperation(&uSdHandle,SDMMC_BUS_WIDE_1B);
	
	cal_sd_mcc1_reset();
	while(i--);
	cal_sd_mcc1_set();
	i = 0xFFFF;
	while(i--);
}


/**
  * @brief  Reads block(s) from a specified address in an MMC card, in polling mode.
  * @param  pData: Pointer to the buffer that will contain the data to transmit
  * @param  ReadAddr: Address from where data is to be read
  * @param  NumOfBlocks: Number of MMC blocks to read
  * @param  Timeout: Timeout for read operation
  * @retval MMC status
  */
uint8_t cal_mmc_readblock(uint8_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout)
{

	if(NumOfBlocks > sizeof(g_mmc_rx_buf)/ABLOCK_SIZE)
	{
		return HAL_ERROR;
	}
	if (HAL_MMC_ReadBlocks(&uSdHandle, g_mmc_rx_buf, ReadAddr, NumOfBlocks, Timeout) == HAL_OK)
	{
		memcpy(pData,g_mmc_rx_buf,NumOfBlocks*ABLOCK_SIZE);
		return HAL_OK;
	}
	else
	{
		return HAL_ERROR;
	}
}

/**
  * @brief  Writes block(s) to a specified address in an MMC card, in polling mode.
  * @param  pData: Pointer to the buffer that will contain the data to transmit
  * @param  WriteAddr: Address from where data is to be written
  * @param  NumOfBlocks: Number of MMC blocks to write
  * @param  Timeout: Timeout for write operation
  * @retval MMC status
  */
uint8_t cal_mmc_writeblocks(uint8_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout)
{
	if(NumOfBlocks > sizeof(g_mmc_tx_buf)/ABLOCK_SIZE)
	{
		return HAL_ERROR;
	}
	memcpy(g_mmc_tx_buf,pData,NumOfBlocks*ABLOCK_SIZE);
	if (HAL_MMC_WriteBlocks(&uSdHandle, g_mmc_tx_buf, WriteAddr, NumOfBlocks, Timeout) == HAL_OK)
	{
		return HAL_OK;
	}
	else
	{
		return HAL_ERROR;
	}
}
/**
  * @brief  在DMA模式下,从MMC卡的指定地址读取数据
  * @param  pData:指向将包含要传输的数据的缓冲区的指针
  * @param  ReadAddr:要读取数据的地址
  * @param  NumOfBlocks:要读取的MMC块数量
  * @retval eMMC状态
  */
uint8_t cal_mmc_readblocks_dma(uint8_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks)
{
	uint32_t loop = EMMC_WAIT_CNT;
	if(NumOfBlocks > sizeof(g_mmc_rx_buf)/ABLOCK_SIZE)
	{
		return HAL_ERROR;
	}
	HAL_MMC_ReadBlocks_DMA(&uSdHandle, g_mmc_rx_buf, ReadAddr, NumOfBlocks);
	while(loop > 0)
	{
		loop--;
		if(HAL_MMC_GetCardState(&uSdHandle) == HAL_MMC_CARD_TRANSFER)
		{
			memcpy(pData,g_mmc_rx_buf,NumOfBlocks*ABLOCK_SIZE);
			return HAL_OK;
		}
	}
	return HAL_ERROR;
}


/**
  * @brief  在DMA模式下,向MMC卡的指定地址写入数据; 
  * @param  pData:指向将包含要传输的数据的缓冲区的指针
  * @param  WriteAddr:要写入数据的地址
  * @param  NumOfBlocks:要写的MMC块的数量 
  * @retval MMC状态4 
  */
uint8_t cal_mmc_writeblocks_dma(uint8_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)
{
	uint32_t loop = EMMC_WAIT_CNT;
	if(NumOfBlocks > sizeof(g_mmc_tx_buf)/ABLOCK_SIZE)
	{
		return HAL_ERROR;
	}
	memcpy(g_mmc_tx_buf,pData,NumOfBlocks*ABLOCK_SIZE);
	/* Write block(s) in DMA transfer mode */
	HAL_MMC_WriteBlocks_DMA(&uSdHandle, g_mmc_tx_buf, WriteAddr, NumOfBlocks);
	while(loop > 0)
	{
		loop--;
		if(HAL_MMC_GetCardState(&uSdHandle) == HAL_MMC_CARD_TRANSFER)
		{
			return HAL_OK;
		}
	}
	return HAL_ERROR;
}

/**
  * @brief  Erases the specified memory area of the given MMC card.
  * @param  StartAddr: Start byte address
  * @param  EndAddr: End byte address
  * @retval MMC status
  */
uint8_t cal_mmc_erase(uint32_t StartAddr, uint32_t EndAddr)
{
	uint32_t loop = EMMC_WAIT_CNT;
	HAL_MMC_Erase(&uSdHandle, StartAddr, EndAddr);
	while(loop > 0)
	{
		loop--;
		if(HAL_MMC_GetCardState(&uSdHandle) == HAL_MMC_CARD_TRANSFER)
		{
			return HAL_OK;
		}
	}

	return HAL_ERROR;
}


void cal_emmc_rw_test(void)
{
	uint16_t i = 0;
	static uint8_t first = 1;
	HAL_StatusTypeDef FlashStatus=HAL_OK;
//	HAL_MMC_CardInfoTypeDef test;
//	//ceshi
//	HAL_MMC_CardCIDTypeDef PCID;
//	HAL_MMC_CardCSDTypeDef PCSD;
//	HAL_MMC_GetCardCID(&uSdHandle,&PCID);
//	HAL_MMC_GetCardCSD(&uSdHandle,&PCSD);
//	HAL_MMC_GetCardInfo(&uSdHandle, &test);

	FlashStatus = cal_mmc_erase(0x08,0x10);
	if(first)
	{
		for(i = 0;i < sizeof(g_mmc_tx_buf);i++)
		{
			g_mmc_tx_buf[i] = i;
		}	
		first = 0;
	}

	FlashStatus = cal_mmc_writeblocks_dma(g_mmc_tx_buf,1,1);
////	//cal_mmc_writeblocks(g_mmc_tx_buf,1,1,0xFFFFFFFF);
////	memset(g_mmc_tx_buf,0,sizeof(g_mmc_tx_buf));
	FlashStatus = cal_mmc_readblocks_dma(g_mmc_rx_buf,1,1);
////	cal_mmc_readblock(g_mmc_rx_buf,1,1,0xFFFFFFFF);
	memset(g_mmc_rx_buf,0,sizeof(g_mmc_rx_buf));
	
}

void SDMMC1_IRQHandler(void)
{
	HAL_MMC_IRQHandler(&uSdHandle);
}
回复

使用道具 举报

1

主题

7

回帖

10

积分

新手上路

积分
10
 楼主| 发表于 2024-7-18 11:27:00 | 显示全部楼层
改成了一线模式还不行、感觉是我读写太快的原因 我是在一个任务里测试读写的,代码是移植了H7_TOOL里的驱动 稍微封装了一下
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115490
QQ
发表于 2024-7-18 16:05:39 | 显示全部楼层
xwgwudi 发表于 2024-7-18 11:27
改成了一线模式还不行、感觉是我读写太快的原因 我是在一个任务里测试读写的,代码是移植了H7_TOOL里的驱动 ...

降低SDMMC时钟速度也测试过了没
回复

使用道具 举报

1

主题

7

回帖

10

积分

新手上路

积分
10
 楼主| 发表于 2024-7-19 09:49:19 | 显示全部楼层
eric2013 发表于 2024-7-18 16:05
降低SDMMC时钟速度也测试过了没

降低SDMCC的时钟频率测试了 发现和频率没关系 把初始化里的硬件控制流使能了,发现不使用IDMA可以正常读写了,进一步调试发现 官方的驱动代码里没有对IDMA的相关配置,相关的寄存器值都是复位值 这样可以直接使用IDMA的读写接口应该会有问题吧
回复

使用道具 举报

1

主题

7

回帖

10

积分

新手上路

积分
10
 楼主| 发表于 2024-7-19 09:51:28 | 显示全部楼层
对比了一下DMA读写接口 和不使用DMA的读写接口函数 发现DMA的读写接口函数里使能了中断
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115490
QQ
发表于 2024-7-20 09:01:20 | 显示全部楼层
xwgwudi 发表于 2024-7-19 09:49
降低SDMCC的时钟频率测试了 发现和频率没关系 把初始化里的硬件控制流使能了,发现不使用IDMA可以正常读 ...

有的,这个IDMA是SDMMC自带的DMA,这个不想通用DMA,IDMA仅需使能下就可以使用了。
回复

使用道具 举报

1

主题

7

回帖

10

积分

新手上路

积分
10
 楼主| 发表于 2024-7-23 13:42:00 | 显示全部楼层
eric2013 发表于 2024-7-20 09:01
有的,这个IDMA是SDMMC自带的DMA,这个不想通用DMA,IDMA仅需使能下就可以使用了。

问题解决了 使用IDMA是不用配置的 直接调用读写接口就行了 H7的驱动代码在IDMA发送完成回调和接收完成回调里写了一个标志位 用来标志发送完成和接收完成
我测试的时候没有等标志位 一直在读写 导致溢出错误 不使用DMA读写可以正常的原因是它的读写接口是阻塞的,直接就写了,不用在中断里判断是否发送和接收完成了
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-4-29 06:17 , Processed in 0.494953 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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