【兆易GD32H759I-EVAL】 SDIO接口TF卡读写测试
[复制链接]
测试板卡SDIO接口的TF卡读写测试。
一、电路图部分
1.1、板卡上SDIO接口
1.2、SDIO端口连接选择
SDIO支持总线模式有1位模式和4位模式。
1.2.1、1位总线模式
1位总线模式只需要连接SDIO0_D0端口到SDIO。
1.2.2、4位总线模式
4线总线模式需要连接下面跳线
SDIO0_D0~SDIO0_D3都需要连接到SDIO。
二、程序部分
2.1、sd.c
#include "main.h"
sd_card_info_struct sd_cardinfo; /* information of SD card */
uint32_t __attribute__((aligned(32))) buf_write[512]; /* store the data written to the card */
uint32_t __attribute__((aligned(32))) buf_read[512]; /* store the data read from the card */
__align(4) uint8_t sd_data_buf[512];
__asm void INTX_DISABLE(void)
{
CPSID I
BX LR
}
__asm void INTX_ENABLE(void)
{
CPSIE I
BX LR
}
void nvic_config(void)
{
nvic_priority_group_set(NVIC_PRIGROUP_PRE1_SUB3);
nvic_irq_enable(SDIO0_IRQn, 2U, 0);
}
sd_error_enum sd_io_init(void)
{
sd_error_enum status = SD_OK;
uint32_t cardstate = 0;
status = sd_init();
if(SD_OK == status) {
status = sd_card_information_get(&sd_cardinfo);
}
if(SD_OK == status) {
status = sd_card_select_deselect(sd_cardinfo.card_rca);
}
status = sd_cardstatus_get(&cardstate);
if(cardstate & 0x02000000) {
printf("\r\n the card is locked!");
status = sd_lock_unlock(SD_UNLOCK);
if(status != SD_OK) {
return SD_LOCK_UNLOCK_FAILED;
} else {
printf("\r\n the card is unlocked successfully!");
}
}
if((SD_OK == status) && (!(cardstate & 0x02000000))) {
/* set bus mode */
#if (SDIO_BUSMODE == BUSMODE_4BIT)
status = sd_bus_mode_config(SDIO_BUSMODE_4BIT, SDIO_SPEEDMODE);
#else
status = sd_bus_mode_config(SDIO_BUSMODE_1BIT, SDIO_SPEEDMODE);
#endif
}
if(SD_OK == status) {
/* set data transfer mode */
status = sd_transfer_mode_config(SDIO_DTMODE);
}
return status;
}
void card_info_get(void)
{
uint8_t sd_spec, sd_spec3, sd_spec4, sd_security;
uint32_t block_count, block_size;
uint16_t temp_ccc;
printf("\r\n Card information:");
sd_spec = (sd_scr[1] & 0x0F000000) >> 24;
sd_spec3 = (sd_scr[1] & 0x00008000) >> 15;
sd_spec4 = (sd_scr[1] & 0x00000400) >> 10;
if(2 == sd_spec) {
if(1 == sd_spec3) {
if(1 == sd_spec4) {
printf("\r\n## Card version 4.xx ##");
} else {
printf("\r\n## Card version 3.0x ##");
}
} else {
printf("\r\n## Card version 2.00 ##");
}
} else if(1 == sd_spec) {
printf("\r\n## Card version 1.10 ##");
} else if(0 == sd_spec) {
printf("\r\n## Card version 1.0x ##");
}
sd_security = (sd_scr[1] & 0x00700000) >> 20;
if(2 == sd_security) {
printf("\r\n## security v1.01 ##");
} else if(3 == sd_security) {
printf("\r\n## security v2.00 ##");
} else if(4 == sd_security) {
printf("\r\n## security v3.00 ##");
}
block_count = (sd_cardinfo.card_csd.c_size + 1) * 1024;
block_size = 512;
printf("\r\n## Device size is %dKB ##", sd_card_capacity_get());
printf("\r\n## Block size is %dB ##", block_size);
printf("\r\n## Block count is %d ##", block_count);
if(sd_cardinfo.card_csd.read_bl_partial) {
printf("\r\n## Partial blocks for read allowed ##");
}
if(sd_cardinfo.card_csd.write_bl_partial) {
printf("\r\n## Partial blocks for write allowed ##");
}
temp_ccc = sd_cardinfo.card_csd.ccc;
printf("\r\n## CardCommandClasses is: %x ##", temp_ccc);
if((SD_CCC_BLOCK_READ & temp_ccc) && (SD_CCC_BLOCK_WRITE & temp_ccc)) {
printf("\r\n## Block operation supported ##");
}
if(SD_CCC_ERASE & temp_ccc) {
printf("\r\n## Erase supported ##");
}
if(SD_CCC_WRITE_PROTECTION & temp_ccc) {
printf("\r\n## Write protection supported ##");
}
if(SD_CCC_LOCK_CARD & temp_ccc) {
printf("\r\n## Lock unlock supported ##");
}
if(SD_CCC_APPLICATION_SPECIFIC & temp_ccc) {
printf("\r\n## Application specific supported ##");
}
if(SD_CCC_IO_MODE & temp_ccc) {
printf("\r\n## I/O mode supported ##");
}
if(SD_CCC_SWITCH & temp_ccc) {
printf("\r\n## Switch function supported ##");
}
}
void clear_buf(void)
{
uint16_t i;
for(i = 0; i < 512; i++) {
buf_write[i] = i;
}
/* clean and invalidate buffer in D-Cache */
SCB_CleanInvalidateDCache_by_Addr(buf_write, 512 * 4);
}
uint8_t sd_readdisk(uint8_t* buf,uint32_t sector,uint32_t cnt)
{
uint8_t sta=SD_OK;
uint8_t n;
long long lsector=sector;
lsector<<=9;
INTX_DISABLE();
if((uint32_t)buf%4!=0)
{
for(n=0;n<cnt;n++)
{
sta = sd_multiblocks_read((uint32_t*)sd_data_buf, lsector+512*n, 512, 1);
memcpy(buf,sd_data_buf,512);
buf+=512;
}
}else
{
sta = sd_multiblocks_read((uint32_t*)sd_data_buf, lsector+512*n, 512, cnt);
}
INTX_ENABLE();
return sta;
}
uint8_t sd_writedisk(uint8_t *buf,uint32_t sector,uint32_t cnt)
{
uint8_t sta=SD_OK;
long long lsector=sector;
uint8_t n;
lsector<<=9;
INTX_DISABLE();
if((uint32_t)buf%4!=0)
{
for(n=0;n<cnt;n++)
{
memcpy(sd_data_buf,buf,512);
sta = sd_multiblocks_write((uint32_t*)sd_data_buf, lsector+512*n, 512, 1);
buf += 512;
}
}else
{
sta = sd_multiblocks_write((uint32_t*)sd_data_buf, lsector+512*n, 512, cnt);
}
INTX_ENABLE();
return sta;
}
uint8_t init_sd(void)
{
sd_error_enum sd_error;
uint16_t i = 5;
do {
sd_error = sd_io_init();
} while((SD_OK != sd_error) && (--i));
if(i)
{
printf("\r\n Card init success!\r\n");
return i;
}
else
{
printf("\r\n Card init failed!\r\n");
return 0;
}
}
void sd_test(void)
{
uint8_t buf[512];
uint16_t sd_size;
sd_error_enum sd_error;
printf("\r\n\r\n Card test:");
/* single block operation test */
sd_error = sd_block_write(buf_write, 100, 512);
if(SD_OK != sd_error)
{
printf("\r\n Block write fail!");
while(1)
{
}
}
else
{
printf("\r\n Block write success!");
}
sd_error = sd_block_read(buf_read, 100, 512);
if(SD_OK != sd_error)
{
printf("\r\n Block read fail!");
while(1)
{
}
}
else
{
printf("\r\n Block read success!");
}
if(sd_readdisk(buf,0,1)==SD_OK)
{
printf("\r\n read sector 0 data:\r\n");
for(sd_size=0;sd_size<512;sd_size++)
{
if(sd_size%32==0)
{
printf("\r\n ");
}
printf("%02x ",buf[sd_size]);
}
}
else
{
printf("sector read fail!\r\n");
}
}
2.3、sd.h
#ifndef SD_H
#define SD_H
#include "stdint.h"
#define BUSMODE_1BIT 1
#define BUSMODE_4BIT 0
/* SDIO bus switch */
/* config SDIO bus mode, select: BUSMODE_1BIT/BUSMODE_4BIT */
#define SDIO_BUSMODE BUSMODE_1BIT
/* config SDIO speed mode, select: SD_SPEED_DEFAULT/SD_SPEED_HIGH */
#define SDIO_SPEEDMODE SD_SPEED_HIGH
/* config data transfer mode, select: SD_POLLING_MODE/SD_DMA_MODE */
#define SDIO_DTMODE SD_DMA_MODE //SD_POLLING_MODE
void nvic_config(void);
uint8_t init_sd(void);
void card_info_get(void);
void clear_buf(void);
void sd_test(void);
uint8_t sd_readdisk(uint8_t* buf,uint32_t sector,uint32_t cnt);
uint8_t sd_writedisk(uint8_t *buf,uint32_t sector,uint32_t cnt);
#endif
2.4、main.c
#include "main.h"
void cache_enable(void);
int main(void)
{
uint8_t x=0;
uint32_t sd=0;
uint32_t yd=0;
uint8_t tx_dat[8];
cache_enable();
nvic_config();
systick_config();
init_usart(115200);
init_led();
while(init_sd()==0)
{
led2_on();
delay_1ms(500);
led2_off();
delay_1ms(500);
}
card_info_get();
clear_buf();
sd_test();
while(1)
{
}
}
void cache_enable(void)
{
/* enable i-cache */
SCB_EnableICache();
/* enable d-cache */
SCB_EnableDCache();
}
三、运行结果
插入TF卡,容量2G,上电后,串口输出:
测试读写一个块的数据和读取扇区0的数据。
四、附件
程序源码:
|