[STM32] STM32 SDIO SD card read and write test (1) - SD card hardware design and software migration

related articles

"[SDIO] Index of articles related to SDIO, SD card, FatFs file system"

1. STM32 SDIO functional block diagram

The STM32 controller has an SDIO, which consists of two parts: SDIO adapter and APB2 interface , as shown in the figure below. SDIO adapter provides SDIO host function, can provide SD clock, send commands and perform data transmission. The APB2 interface is used by the controller to access SDIO adapter registers and can generate interrupts and DMA request signals.
Insert picture description here
SDIO using two clock signals, a clock is SDIO adapter ( SDIOCLK = 48MHz ), the other is APB2 bus clock ( PCLK2, typically 90MHz ).

The SDIO of the STM32 controller is the main device for MMC cards and SD cards, so 8 data lines are reserved, and up to four data lines are used for SD cards.

SDIO adapter consists of five units, namely the :( shown below)

  • control unit
  • Command path unit
  • Data path unit
  • Register unit
  • FIFO

Insert picture description here

2. STM32 SD card hardware design

The SDIO pin of the STM32 controller is designed to be fixed, and the development board design adopts the four data line mode. A pull-up resistor must be added to the command line and data line.
Insert picture description here

3. SD card read and write test migration

It is relatively simple to transplant the SD card reading and writing test on the STM32 platform. We can directly refer to the SDIO demo in the standard library for transplantation. Such as:STM32F4xx_DSP_StdPeriph_Lib_V1.8.0\Project\STM32F4xx_StdPeriph_Examples\SDIO\SDIO_uSDCard

  • Will be stm324x9i_eval_sdio_sd.ctransplanted to the current project, it provides SD_Init() , SD_WriteBlock() and SD_ReadBlock() and other SD card operation functions, which we can use directly.
    Insert picture description here
  • Write sd_test.cfiles to realize SD card erasure test , single block write operation test and multi-block write operation test .
/**
  * @brief  Configures SDIO IRQ channel.
  * @param  None
  * @retval None
  */
static void NVIC_Configuration(void)
{
    
    
  NVIC_InitTypeDef NVIC_InitStructure;

  /* Configure the NVIC Preemption Priority Bits */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

  NVIC_InitStructure.NVIC_IRQChannel = SDIO_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  NVIC_InitStructure.NVIC_IRQChannel = SD_SDIO_DMA_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_Init(&NVIC_InitStructure);  
}

/**
  * @brief  Tests the SD card erase operation.
  * @param  None
  * @retval None
  */
static void SD_EraseTest(void)
{
    
    
	printf("\r\n---->Erase test is starting...\r\n");

	/*------------------- Block Erase ------------------------------------------*/
	if (Status == SD_OK)
	{
    
    
		/* Erase NumberOfBlocks Blocks of WRITE_BL_LEN(512 Bytes) */
		Status = SD_Erase(0x00, (BLOCK_SIZE * NUMBER_OF_BLOCKS));
	}

	if (Status == SD_OK)
	{
    
    
		Status = SD_ReadMultiBlocks(aBuffer_MultiBlock_Rx, 0x00, BLOCK_SIZE, NUMBER_OF_BLOCKS);

		/* Check if the Transfer is finished */
		Status = SD_WaitReadOperation();

		/* Wait until end of DMA transfer */
		while(SD_GetStatus() != SD_TRANSFER_OK);
	}

	/* Check the correctness of erased blocks */
	if (Status == SD_OK)
	{
    
    
		EraseStatus = eBuffercmp(aBuffer_MultiBlock_Rx, MULTI_BUFFER_SIZE);
	}

	if(EraseStatus == PASSED)
	{
    
    
		LED1(ON);
		printf("\tThe earase is successful.\r\n");
	}
	else
	{
    
    
		LED1(OFF);
		LED3(ON);
		printf("\tThe earase is fail!!!\r\n");
	}

	printf("<----Erase test is end.\r\n");
}

/**
  * @brief  Tests the SD card Single Blocks operations.
  * @param  None
  * @retval None
  */
static void SD_SingleBlockTest(void)
{
    
    
	printf("\r\n---->Single block test is starting...\r\n");

	/*------------------- Block Read/Write --------------------------*/
	/* Fill the buffer to send */
	Fill_Buffer(aBuffer_Block_Tx, BLOCK_SIZE, 0x320F);

	if (Status == SD_OK)
	{
    
    
		/* Write block of 512 bytes on address 0 */
		Status = SD_WriteBlock(aBuffer_Block_Tx, 0x00, BLOCK_SIZE);
		/* Check if the Transfer is finished */
		Status = SD_WaitWriteOperation();
		while(SD_GetStatus() != SD_TRANSFER_OK);
	}

	if (Status == SD_OK)
	{
    
    
		/* Read block of 512 bytes from address 0 */
		Status = SD_ReadBlock(aBuffer_Block_Rx, 0x00, BLOCK_SIZE);
		/* Check if the Transfer is finished */
		Status = SD_WaitReadOperation();
		while(SD_GetStatus() != SD_TRANSFER_OK);
	}

	/* Check the correctness of written data */
	if (Status == SD_OK)
	{
    
    
		TransferStatus1 = Buffercmp(aBuffer_Block_Tx, aBuffer_Block_Rx, BLOCK_SIZE);
	}

	if(TransferStatus1 == PASSED)
	{
    
    
		LED1(ON);
		printf("\tThe test is successful.\r\n");
	}
	else
	{
    
    
		LED1(OFF);
		LED3(ON);
		printf("\tThe test is fail!!!\r\n");
	}

	printf("<----Single block test is end.\r\n");

}

/**
  * @brief  Tests the SD card Multiple Blocks operations.
  * @param  None
  * @retval None
  */
static void SD_MultiBlockTest(void)
{
    
    
	printf("\r\n---->Multi block test is starting...\r\n");

	/* Fill the buffer to send */
	Fill_Buffer(aBuffer_MultiBlock_Tx, MULTI_BUFFER_SIZE, 0x0);

	if (Status == SD_OK)
	{
    
    
		/* Write multiple block of many bytes on address 0 */
		Status = SD_WriteMultiBlocks(aBuffer_MultiBlock_Tx, 0, BLOCK_SIZE, NUMBER_OF_BLOCKS);

		/* Check if the Transfer is finished */
		Status = SD_WaitWriteOperation();
		while(SD_GetStatus() != SD_TRANSFER_OK);
	}

	if (Status == SD_OK)
	{
    
    
		/* Read block of many bytes from address 0 */
		Status = SD_ReadMultiBlocks(aBuffer_MultiBlock_Rx, 0, BLOCK_SIZE, NUMBER_OF_BLOCKS);

		/* Check if the Transfer is finished */
		Status = SD_WaitReadOperation();
		while(SD_GetStatus() != SD_TRANSFER_OK);
	}

	/* Check the correctness of written data */
	if (Status == SD_OK)
	{
    
    
		TransferStatus2 = Buffercmp(aBuffer_MultiBlock_Tx, aBuffer_MultiBlock_Rx, MULTI_BUFFER_SIZE);
	}

	if(TransferStatus2 == PASSED)
	{
    
    
		LED1(ON);
		printf("\tThe test is successful.\r\n");
	}
	else
	{
    
    
		LED1(OFF);
		LED3(ON);
		printf("\tThe test is fail!!!\r\n");
	}

	printf("<----Multi block test is end.\r\n");

}


void SD_Test_Start(void)
{
    
    
	if(Status != SD_OK){
    
    
		return;		
	}

	/*-------------------------- SD Erase Test ---------------------------- */
	SD_EraseTest();

	/*-------------------------- SD Single Block Test --------------------- */
	SD_SingleBlockTest();

	/*-------------------------- SD Multi Blocks Test --------------------- */
	SD_MultiBlockTest();
}

void SD_Test_Init(void)
{
    
    
	/* NVIC Configuration */
	NVIC_Configuration();

	/*------------------------------ SD Init ---------------------------------- */
	if((Status = SD_Init()) == SD_OK)
	{
    
    
		printf("The SD Card is successfully initialized!!!\r\n");
	}else{
    
    
		LED3(ON);
		printf("The SD Card is fail initialized!!!\r\n");
	}
}
  • In the main.ccall to SD card reading and writing tests.
int main(void)
{
    
    
	// ...

	SD_Test_Init();
	SD_Test_Start();

	while(1){
    
    		
		// Do nothing!!!
	}

	//return 0;
}

4. Verification Test

Finally, the verification test is successful, as follows:
Insert picture description here

5. Data download address

The complete code download address for successful transplantation is as follows:
https://download.csdn.net/download/ZHONGCAI0901/15265756

Guess you like

Origin blog.csdn.net/ZHONGCAI0901/article/details/113772681