想做一个赌钱网站怎么做,红玫瑰直播免费版视频,网站顶部地图代码怎么做的,最新国际新闻热点本文主要探讨210Nand和iNand相关知识。
NandFlash 型号与命 K9F2G08#xff1a;K9F为发行商,2G为Nand大小是2Gbit(256MB),08为Nand是8位(8数据线即接口为8位:传输数据,地址,命令) 功能 Nand是矩阵式存储,每块可存1bit位 … 本文主要探讨210Nand和iNand相关知识。
NandFlash 型号与命 K9F2G08K9F为发行商,2G为Nand大小是2Gbit(256MB),08为Nand是8位(8数据线即接口为8位:传输数据,地址,命令) 功能 Nand是矩阵式存储,每块可存1bit位 Nand单次访问最小单元为Page,Page大小是2KB64B,每次读写n*2KB,random read模式可读1字节 210中 1 block 64 page,1 Device 2028 block 2048 × 64 × 2K 256MB Page是读写最小单位Block是擦除最小单位 Nand芯片Nand存储 Nand接口 Nand读写时地址通过IO线发送,地址有30位而IO只有8位,需要多个cycle才能完成 SoC通过发送命令、地址、数据等信给Nand控制器来访问Nand(接口) I/O8~15用在X16设备且仅用于输入命令和地址,用于数据输入和接口输出 ECC(软件或硬件寄存器) 2KB存储数据,64用于管理功能(存储ECC数据、存储坏块标志···), 读取或写入前后会做校验,校验不通过则证明已损坏,会将坏块信息存储信息到Nand时会产生 ECC(校验信息)存储到64字节内,下次读写跳过坏块 Nand操作流程 坏块检查 nand使用前要擦除(块单位),擦除完后全是1,擦除后检测是否为0xff可知是否为坏块 页写 写前需要擦除 SoC写Flash通过命令线在IO线依次发送写入开始命令、要写入的页地址、要写入数据,写入结束命令 SOC与Nand建立写入连接后,写入一页数据发给Nand接口,接口接收数据缓冲区,再写入Nand存储区 nand接收和写入数据需要延时,通过状态寄存器判断是否写完,写完后再发送写入结束命令,再做ECC校验写入是否正常 擦除 擦除读写要发送对齐地址 页读 210Nand相关寄存器 gpio nand configure demo1: nand功能
nand.h
void nand_init(void);void nand_read_id(void);int nand_block_erase(unsigned long block_num);int copy_nand_to_sdram(unsigned char *sdram_addr, unsigned long nand_addr, unsigned long length);int copy_sdram_to_nand(unsigned char *sdram_addr, unsigned long nand_addr, unsigned long length);int nand_page_read(unsigned int pgaddr, unsigned char *buf, unsigned int length);int nand_page_write(unsigned int pgaddr, const unsigned char *buf, unsigned int length);int nand_random_read(unsigned long pgaddr,unsigned short offset, unsigned char *data);int nand_random_write(unsigned long pgaddr,unsigned short offset,unsigned char wrdata);
nand.c
#include nand.h
#include stdio.h#define rNFCONF ( *((volatile unsigned long *)0xB0E00000) )
#define rNFCONT ( *((volatile unsigned long *)0xB0E00004) )
#define rNFCMMD ( *((volatile unsigned long *)0xB0E00008) )
#define rNFADDR ( *((volatile unsigned long *)0xB0E0000C) )
#define rNFDATA ( *((volatile unsigned long *)0xB0E00010) )
#define rNFDATA8 ( *((volatile unsigned char *)0xB0E00010) )
#define rNFSTAT ( *((volatile unsigned long *)0xB0E00028) )#define rMP0_1CON ( *((volatile unsigned long *)0xE02002E0) )
#define rMP0_2CON ( *((volatile unsigned long *)0xE0200300) )
#define rMP0_3CON ( *((volatile unsigned long *)0xE0200320) )#define MAX_NAND_BLOCK 8192
#define NAND_PAGE_SIZE 2048
#define NAND_BLOCK_SIZE 64 //dealy time(12ns)
#define TACLS 1
#define TWRPH0 4
#define TWRPH1 1//command
#define NAND_CMD_READ_1st 0x00
#define NAND_CMD_READ_2st 0x30#define NAND_CMD_READ_CB_1st 0x00
#define NAND_CMD_READ_CB_2st 0x35#define NAND_CMD_RANDOM_WRITE 0x85
#define NAND_CMD_RANDOM_READ_1st 0x05
#define NAND_CMD_RANDOM_READ_2st 0xe0#define NAND_CMD_READ_ID 0x90
#define NAND_CMD_RESET 0xff
#define NAND_CMD_READ_STATUS 0x70#define NAND_CMD_WRITE_PAGE_1st 0x80
#define NAND_CMD_WRITE_PAGE_2st 0x10#define NAND_CMD_BLOCK_ERASE_1st 0x60
#define NAND_CMD_BLOCK_ERASE_2st 0xd0#define ECC_EN (14)
#define CONTROL_EN (10)static void nand_reset(void);
static void nand_wait_idle(void);
static void nand_select_chip(void);
static void nand_deselect_chip(void);
static void nand_send_cmd(unsigned long cmd);
static void nand_send_addr(unsigned long addr);
static unsigned char nand_read8(void);
static void nand_write8(unsigned char data);
static unsigned int nand_read32(void);
static void nand_write32(unsigned int data);typedef struct nand_id_info
{//marker codeunsigned char IDm; //device codeunsigned char IDd; unsigned char ID3rd;unsigned char ID4th;unsigned char ID5th;
}nand_id_info;//reset
void nand_reset(void)
{nand_select_chip();nand_send_cmd(NAND_CMD_RESET);nand_wait_idle();nand_deselect_chip();
}//waite busy or read status over
void nand_wait_idle(void)
{unsigned long i;while( !(rNFSTAT (14)) )for(i0; i10; i);
}//connect nand
void nand_select_chip(void)
{unsigned long i;rNFCONT ~(11);for(i0; i10; i);
}//disconnect nand
void nand_deselect_chip(void)
{unsigned long i 0;rNFCONT | (11);for(i0; i10; i);
}//send command
void nand_send_cmd(unsigned long cmd)
{unsigned long i 0;rNFCMMD cmd;for(i0; i10; i);
}//send address
void nand_send_addr(unsigned long addr)
{unsigned long i;unsigned long col, row;//address of interior page col addr % NAND_PAGE_SIZE; //address of page row addr / NAND_PAGE_SIZE;//write Column Address A0~A7 rNFADDR col 0xff; for(i0; i10; i); //write Column Address A8~A11 rNFADDR (col 8) 0x0f; for(i0; i10; i);//write Row Address A12~A19 rNFADDR row 0xff; for(i0; i10; i);//write Row Address A20~A27 rNFADDR (row 8) 0xff;for(i0; i10; i);//write Row Address A28~A30(A28,low level) rNFADDR (row 16) 0xff;for(i0; i10; i);
}//read nand(word)
unsigned int nand_read32(void)
{return rNFDATA;
}//write nand(word)
void nand_write32(unsigned int data)
{rNFDATA data;
}//read nand(half word)
unsigned char nand_read8(void)
{return rNFDATA8;
}//write nand(half word)
void nand_write8(unsigned char data)
{rNFDATA8 data;
}//get nand status
unsigned char nand_read_status(void)
{unsigned char ch;int i;//connect nand nand_select_chip();//get nand status nand_send_cmd(NAND_CMD_READ_STATUS);for(i0; i10; i);//read nandch nand_read8();//disconnect nandnand_deselect_chip();return ch;
}// nand init
void nand_init(void)
{//set read nand signal dealy rNFCONF (TACLS12)|(TWRPH08)|(TWRPH14)|(03)|(02)|(11)|(00);//set nand control,chip,set ECC,close read/busy status interrupt,close soft lockrNFCONT (018)|(017)|(016)|(010)|(09)|(08)|(07)|(06)|(0x31)|(10);//set gpio nandflashrMP0_1CON 0x22333322;rMP0_2CON 0x00002222;rMP0_3CON 0x22222222;//reset nand_reset();
}//get nand id
void nand_read_id(void)
{nand_id_info nand_id;//connect nand nand_select_chip();//get nand id nand_send_cmd(NAND_CMD_READ_ID);nand_send_addr(0x00);nand_wait_idle();nand_id.IDm nand_read8();nand_id.IDd nand_read8();nand_id.ID3rd nand_read8();nand_id.ID4th nand_read8();nand_id.ID5th nand_read8();printf(nandflash: makercode %x\r\n devicecode %x\r\n ID3rd %x\r\n ID4rd %x\r\n ID5rd %x\r\n, nand_id.IDm, nand_id.IDd, nand_id.ID3rd, nand_id.ID4th, nand_id.ID5th);//disconnect nandnand_deselect_chip();
}//earse the num of block0 ~ MAX_NAND_BLOCK-1
int nand_block_erase(unsigned long block_num)
{unsigned long i 0;//get the starting page address of block(block starting address) unsigned long row block_num * NAND_BLOCK_SIZE;//connect nand nand_select_chip();//send earse command (0x60) nand_send_cmd(NAND_CMD_BLOCK_ERASE_1st);//dealy timefor(i0; i10; i);//set erase address//Row Address A12~A19 rNFADDR row 0xff; for(i0; i10; i);// Row Address A20~A27 rNFADDR (row 8) 0xff;for(i0; i10; i);// Row Address A28~A30 rNFADDR (row 16) 0xff; //clear RnB bit,aim to send second commandrNFSTAT | (14); //send second command(0xd0)nand_send_cmd(NAND_CMD_BLOCK_ERASE_2st);for(i0; i10; i);//waite busy or read status over nand_wait_idle();//judge read/busy status,0 earse success unsigned char status nand_read_status();if (status 1 ){//disconnect nandnand_deselect_chip(); printf(masking bad block %d\r\n, block_num);return -1;}else{nand_deselect_chip();return 0;}
}//erase the address of nand
int nand_erase(unsigned long block_addr)
{int i 0;//judge write protect if((nand_read_status() 0x80) 0) {printf(Write protected.\n);return -1;}unsigned long row block_addr 18;//connect nand nand_select_chip();// send erase command(0x60)nand_send_cmd(NAND_CMD_BLOCK_ERASE_1st);//dealy timefor(i0; i10; i);//set erase address// Row Address A12~A19 rNFADDR row 0xff; for(i0; i10; i);// Row Address A20~A27 rNFADDR (row 8) 0xff;for(i0; i10; i);// Row Address A28~A30 rNFADDR (row 16) 0x01; for(i0; i10; i);//clear RnB bit,aim to send second commandrNFSTAT | (14); //send second command(0xd0)nand_send_cmd(NAND_CMD_BLOCK_ERASE_2st);for(i0; i10; i);//waite busy or read status over nand_wait_idle();//judge erase ,0 sucess unsigned char status nand_read_status();if (status 1){nand_deselect_chip(); printf(masking bad block %d\r\n, block_addr);return -1;}else{nand_deselect_chip();return 0;}
}//copy nand to sdram
int copy_nand_to_sdram(unsigned char *sdram_addr, unsigned long nand_addr, unsigned long length)
{unsigned long i 0;//connect nandnand_select_chip();while(length){//send read command(0x00)nand_send_cmd(NAND_CMD_READ_1st);//send read starting addressnand_send_addr(nand_addr);//clear RnB bit,aim to send second commandrNFSTAT (rNFSTAT)|(14);//send second command (0x30)nand_send_cmd(NAND_CMD_READ_2st);//waite busy or read status over nand_wait_idle();//get the address of start pageunsigned long col nand_addr % NAND_PAGE_SIZE;i col;//read one page,pre one time copy 1byte,need 2048 times,when length equal 0 over for(; iNAND_PAGE_SIZE length!0; i,length--){*sdram_addr nand_read8();sdram_addr;nand_addr;}}//judge copy result unsigned char status nand_read_status();if (status 1 ){nand_deselect_chip();printf(copy nand to sdram fail\r\n);return -1;}else{nand_deselect_chip();return 0;}
}//copy sdram to nand
int copy_sdram_to_nand(unsigned char *sdram_addr, unsigned long nand_addr, unsigned long length)
{unsigned long i 0;//connect nand nand_select_chip();while(length){//send write command(0x80) nand_send_cmd(NAND_CMD_WRITE_PAGE_1st);//send read starting addressnand_send_addr(nand_addr);//get the address of start page unsigned long col nand_addr % NAND_PAGE_SIZE;i col;//write one page,pre one time write 1byte,need 2048 times,when length equal 0 overfor(; iNAND_PAGE_SIZE length!0; i,length--){nand_write8(*sdram_addr);sdram_addr;nand_addr;}//clear RnB bit,aim to send second commandrNFSTAT (rNFSTAT)|(14);//send second command (0x10)nand_send_cmd(NAND_CMD_WRITE_PAGE_2st);//waite busy or read status overnand_wait_idle();}//judge copy result unsigned char status nand_read_status();if (status 1 ){nand_deselect_chip();printf(copy sdram to nand fail\r\n);return -1;}else{nand_deselect_chip();return 0;}
}//read bit on page
int nand_page_read(unsigned int pgaddr, unsigned char *buf, unsigned int length)
{int i 0;//connect nand nand_select_chip();//send read command(0x00) nand_send_cmd(NAND_CMD_READ_1st);//set read addressrNFADDR 0; rNFADDR 0;rNFADDR pgaddr0xff;rNFADDR (pgaddr8)0xff;rNFADDR (pgaddr16)0xff;//clear RnB bit,aim to send second commandrNFSTAT | (14);//send second command(0x30) nand_send_cmd(NAND_CMD_READ_2st);//waite busy or read status overnand_wait_idle();//read 2KB data area and 64 spare area(1byte)for (i0; (iNAND_PAGE_SIZE) (length!0); i,length--)*buf nand_read8();//judge read resultunsigned char status nand_read_status();if (status 1 ){ nand_deselect_chip();printf(nand random read fail\r\n);return -1;}else{nand_deselect_chip();return 0;}
}//read word on page
int nand_page_read32(unsigned int pgaddr, unsigned int *buf, unsigned int lengthB)
{int i 0;//connect nandnand_select_chip();//send read command nand_send_cmd(NAND_CMD_READ_1st);//write read starting addressrNFADDR 0; rNFADDR 0;rNFADDR pgaddr0xff;rNFADDR (pgaddr8)0xff;rNFADDR (pgaddr16)0xff;//clear RnB bit,aim to send second commandrNFSTAT | (14);//send second command(0x30) nand_send_cmd(NAND_CMD_READ_2st);//waite busy or read status overnand_wait_idle();//read 2KB 64B spare area(1 word)for (i0; (iNAND_PAGE_SIZE/4) (lengthB!0); i,lengthB--)*buf nand_read32();//judge read result unsigned char status nand_read_status();if (status 1 ){ nand_deselect_chip();printf(nand random read fail\r\n);return -1;}else{nand_deselect_chip();return 0;}
}//write page
int nand_page_write(unsigned int pgaddr, const unsigned char *buf, unsigned int length)
{int i 0;//connect nandnand_select_chip();//send write command(0x80) nand_send_cmd(NAND_CMD_WRITE_PAGE_1st);//write start addressrNFADDR 0;rNFADDR 0;rNFADDR pgaddr0xff;rNFADDR (pgaddr8)0xff;rNFADDR (pgaddr16)0xff;//write page(1byte)for(; iNAND_PAGE_SIZE length!0; i,length--)nand_write8(*buf);//clear RnB bit,aim to send second commandrNFSTAT (rNFSTAT)|(14);//sens second commandnand_send_cmd(NAND_CMD_WRITE_PAGE_2st);//wait busy or read status overnand_wait_idle();//judge write result unsigned char status nand_read_status();if (status 1 ){nand_deselect_chip();printf(nand random write fail\r\n);return -1;}else{nand_deselect_chip();return 0;}}//read random
int nand_random_read(unsigned long pgaddr,unsigned short offset, unsigned char *data)
{unsigned char readdata;//connect nand nand_select_chip();//send read command(0x00)nand_send_cmd(NAND_CMD_READ_1st);//write start addressrNFADDR 0; rNFADDR 0;rNFADDR pgaddr0xff;rNFADDR (pgaddr8)0xff;rNFADDR (pgaddr16)0xff;//clear RnB bit,aim to send second commandrNFSTAT | (14);//second second commandnand_send_cmd(NAND_CMD_READ_2st);//wait busy or read status overnand_wait_idle();//send read command(0x05)nand_send_cmd(NAND_CMD_RANDOM_READ_1st);//write the address of page that offset addressrNFADDR offset0xff; rNFADDR (offset8)0xff;//clear RnB bit,aim to send second command rNFSTAT (rNFSTAT)|(14);//second second command(0xe0)nand_send_cmd(NAND_CMD_RANDOM_READ_2st);//read datareaddata nand_read8();//judge read result unsigned char status nand_read_status();if (status 1 ){nand_deselect_chip();printf(nand random read fail\r\n);return -1;}else{nand_deselect_chip();*data readdata;return 0;}
}//random write
int nand_random_write(unsigned long pgaddr,unsigned short offset,unsigned char wrdata)
{//connect nandnand_select_chip();//send write command(0x80) nand_send_cmd(NAND_CMD_WRITE_PAGE_1st);//write start addressrNFADDR 0;rNFADDR 0;rNFADDR pgaddr0xff;rNFADDR (pgaddr8)0xff;rNFADDR (pgaddr16)0xff;//send write command (0x80)nand_send_cmd(NAND_CMD_RANDOM_WRITE);//write the address of page that offset addressrNFADDR offset0xff; rNFADDR (offset8)0xff;//write data(1byte)nand_write8(wrdata);//clear RnB bit,aim to send second commandrNFSTAT (rNFSTAT)|(14);//send second commandnand_send_cmd(NAND_CMD_WRITE_PAGE_2st);//wait busy or read status overnand_wait_idle();//judge write result unsigned char status nand_read_status();if (status 1 ){ nand_deselect_chip();printf(nand random write fail\r\n);return -1;}else{nand_deselect_chip();return 0;}
}iNand iNand/eMMC/SDCard/MMCCard mmc对于nandflash的优势:卡片化便于拆装,接口协议Hmmc协议)统一便于封装 SD卡(SD协议、SPI协议)兼容性好且有写保护、速率快、容量大 iNand/eMMC与NandFlash iNand和nand内部由存储和接口组成 iNand接口支持eMMC协议、ECC校验,使用ML,有cache 机制,速度快 NandFlashSLC 更稳定,容量小价格高;MLC易出错容量大价格低 SD/iNand/eMMC 210是4通道SD/MMC,SD/MMC0接iNand,SD/MMC2-3接SD卡 SD卡是4IO线支持1、4、8线并行传输,iNand是8IO线支持1、4线并行传输 硬件接口DATA(数据)、CLK(时钟,25Mhz)、CMD(命令) SD协议是多标准命令,命令有使用条件和响应,少数命令没有响应 SD卡命令是周期性组合(组合命令),在命令周期中,发送CMD到SD卡,SD卡执行命令并且返回响应,主机接收响应后再发下一条 CMD和ACMD:SD协议命令CMDx、ACMDx;CMD是单命令,ACMDy CMDy CMDz(y一般是55) SD卡处于某种状态(空闲状态、准备好状态、读写状态、出错状态····),接受某种执行命令(跳转命令)并返回响应,跳转到另一状态 210SD/iNand寄存器 RCA(相对地址寄存器) gpio 设置时钟 状态寄存器命令写入读取中断... cmd 命令参数 错误状态 设置每次读取block大小 设置每次读取block数量 配置数据传输 命令控制寄存器 32位数据端口寄存器访问内部缓冲区 sd响应 设置中断状态 sd命令参数 设置软件功能是SD不是soc 设置超时 设置错误中断状态 demo2: sd/emmc功能
Hsmmc.h
#ifndef __HSMMC_H__
#define __HSMMC_H__#ifdef __cplusplus
extern C {
#endif#include stdint.h// SD协议规定的命令码
#define CMD0 0
#define CMD1 1
#define CMD2 2
#define CMD3 3
#define CMD6 6
#define CMD7 7
#define CMD8 8
#define CMD9 9
#define CMD13 13
#define CMD16 16
#define CMD17 17
#define CMD18 18
#define CMD23 23
#define CMD24 24
#define CMD25 25
#define CMD32 32
#define CMD33 33
#define CMD38 38
#define CMD41 41
#define CMD51 51
#define CMD55 55 // 卡类型
#define UNUSABLE 0
#define SD_V1 1
#define SD_V2 2
#define SD_HC 3
#define MMC 4// 卡状态
#define CARD_IDLE 0 // 空闲态
#define CARD_READY 1 // 准备好
#define CARD_IDENT 2
#define CARD_STBY 3
#define CARD_TRAN 4
#define CARD_DATA 5
#define CARD_RCV 6
#define CARD_PRG 7 // 卡编程状态
#define CARD_DIS 8 // 断开连接// 卡回复类型
#define CMD_RESP_NONE 0 // 无回复
#define CMD_RESP_R1 1
#define CMD_RESP_R2 2
#define CMD_RESP_R3 3
#define CMD_RESP_R4 4
#define CMD_RESP_R5 5
#define CMD_RESP_R6 6
#define CMD_RESP_R7 7
#define CMD_RESP_R1B 8typedef struct {uint32_t RESERVED1;uint32_t RESERVED2 : 16; uint32_t SD_BUS_WIDTHS : 4;uint32_t SD_SECURITY : 3; uint32_t DATA_STAT_AFTER_ERASE : 1;uint32_t SD_SPEC : 4; uint32_t SCR_STRUCTURE : 4;
} SD_SCR; int32_t Hsmmc_Init(void);
int32_t Hsmmc_GetCardState(void);
int32_t Hsmmc_GetSdState(uint8_t *pStatus);
int32_t Hsmmc_Get_SCR(SD_SCR *pSCR);
int32_t Hsmmc_Get_CSD(uint8_t *pCSD);
int32_t Hsmmc_EraseBlock(uint32_t StartBlock, uint32_t EndBlock);
int32_t Hsmmc_WriteBlock(uint8_t *pBuffer, uint32_t BlockAddr, uint32_t BlockNumber);
int32_t Hsmmc_ReadBlock(uint8_t *pBuffer, uint32_t BlockAddr, uint32_t BlockNumber);#ifdef __cplusplus
}
#endif#endif /*__HSMMC_H__*/Hsmmc.c
#include ProjectConfig.h
#include Hsmmc.h#define HSMMC_NUM 2#if (HSMMC_NUM 0)
#define HSMMC_BASE (0xEB000000)
#elif (HSMMC_NUM 1)
#define HSMMC_BASE (0xEB100000)
#elif (HSMMC_NUM 2)
#define HSMMC_BASE (0xEB200000)
#elif (HSMMC_NUM 3)
#define HSMMC_BASE (0xEB300000)
#else
#error Configure HSMMC: HSMMC0 ~ HSMM3(0 ~ 3)
#endif#define MAX_BLOCK 65535#define SWRST_OFFSET 0x2Fstatic uint8_t CardType; // 卡类型
static uint32_t RCA; // 卡相对地址static void Hsmmc_ClockOn(uint8_t On)
{uint32_t Timeout;if (On) {__REGw(HSMMC_BASECLKCON_OFFSET) | (12); // sd时钟使能Timeout 1000; // Wait max 10 mswhile (!(__REGw(HSMMC_BASECLKCON_OFFSET) (13))) {// 等待SD输出时钟稳定if (Timeout 0) {return;}Timeout--;Delay_us(10);}} else {__REGw(HSMMC_BASECLKCON_OFFSET) ~(12); // sd时钟禁止}
}static void Hsmmc_SetClock(uint32_t Clock)
{uint32_t Temp;uint32_t Timeout;uint32_t i;Hsmmc_ClockOn(0); // 关闭时钟 Temp __REG(HSMMC_BASECONTROL2_OFFSET);// Set SCLK_MMC(48M) from SYSCON as a clock source Temp (Temp (~(34))) | (24);Temp | (1u31) | (1u30) | (18);if (Clock 500000) {Temp ~((114) | (115));__REG(HSMMC_BASECONTROL3_OFFSET) 0;} else {Temp | ((114) | (115));__REG(HSMMC_BASECONTROL3_OFFSET) (1u31) | (123);}__REG(HSMMC_BASECONTROL2_OFFSET) Temp;for (i0; i8; i) {if (Clock (48000000/(1i))) {break;}}Temp ((1i) / 2) 8; // clock divTemp | (10); // Internal Clock Enable__REGw(HSMMC_BASECLKCON_OFFSET) Temp;Timeout 1000; // Wait max 10 mswhile (!(__REGw(HSMMC_BASECLKCON_OFFSET) (11))) {// 等待内部时钟振荡稳定if (Timeout 0) {return;}Timeout--;Delay_us(10);}Hsmmc_ClockOn(1); // 使能时钟
}static int32_t Hsmmc_WaitForBufferReadReady(void)
{ int32_t ErrorState;while (1) {if (__REGw(HSMMC_BASENORINTSTS_OFFSET) (115)) { // 出现错误break;}if (__REGw(HSMMC_BASENORINTSTS_OFFSET) (15)) { // 读缓存准备好__REGw(HSMMC_BASENORINTSTS_OFFSET) | (15); // 清除准备好标志return 0;} }ErrorState __REGw(HSMMC_BASEERRINTSTS_OFFSET) 0x1ff; // 可能通信错误,CRC检验错误,超时等__REGw(HSMMC_BASENORINTSTS_OFFSET) __REGw(HSMMC_BASENORINTSTS_OFFSET); // 清除中断标志 __REGw(HSMMC_BASEERRINTSTS_OFFSET) __REGw(HSMMC_BASEERRINTSTS_OFFSET); // 清除错误中断标志Debug(Read buffer error, NORINTSTS: %04x\r\n, ErrorState);return ErrorState;
}static int32_t Hsmmc_WaitForBufferWriteReady(void)
{int32_t ErrorState;while (1) {if (__REGw(HSMMC_BASENORINTSTS_OFFSET) (115)) { // 出现错误break;}if (__REGw(HSMMC_BASENORINTSTS_OFFSET) (14)) { // 写缓存准备好__REGw(HSMMC_BASENORINTSTS_OFFSET) | (14); // 清除准备好标志return 0;} }ErrorState __REGw(HSMMC_BASEERRINTSTS_OFFSET) 0x1ff; // 可能通信错误,CRC检验错误,超时等__REGw(HSMMC_BASENORINTSTS_OFFSET) __REGw(HSMMC_BASENORINTSTS_OFFSET); // 清除中断标志__REGw(HSMMC_BASEERRINTSTS_OFFSET) __REGw(HSMMC_BASEERRINTSTS_OFFSET); // 清除错误中断标志Debug(Write buffer error, NORINTSTS: %04x\r\n, ErrorState);return ErrorState;
}static int32_t Hsmmc_WaitForCommandDone(void)
{uint32_t i; int32_t ErrorState;// 等待命令发送完成for (i0; i0x20000000; i) {if (__REGw(HSMMC_BASENORINTSTS_OFFSET) (115)) { // 出现错误break;}if (__REGw(HSMMC_BASENORINTSTS_OFFSET) (10)) {do {__REGw(HSMMC_BASENORINTSTS_OFFSET) (10); // 清除命令完成位} while (__REGw(HSMMC_BASENORINTSTS_OFFSET) (10)); return 0; // 命令发送成功}}ErrorState __REGw(HSMMC_BASEERRINTSTS_OFFSET) 0x1ff; // 可能通信错误,CRC检验错误,超时等__REGw(HSMMC_BASENORINTSTS_OFFSET) __REGw(HSMMC_BASENORINTSTS_OFFSET); // 清除中断标志__REGw(HSMMC_BASEERRINTSTS_OFFSET) __REGw(HSMMC_BASEERRINTSTS_OFFSET); // 清除错误中断标志 do {__REGw(HSMMC_BASENORINTSTS_OFFSET) (10); // 清除命令完成位} while (__REGw(HSMMC_BASENORINTSTS_OFFSET) (10));Debug(Command error, ERRINTSTS 0x%x , ErrorState); return ErrorState; // 命令发送出错
}static int32_t Hsmmc_WaitForTransferDone(void)
{int32_t ErrorState;uint32_t i;// 等待数据传输完成for (i0; i0x20000000; i) {if (__REGw(HSMMC_BASENORINTSTS_OFFSET) (115)) { // 出现错误break;} if (__REGw(HSMMC_BASENORINTSTS_OFFSET) (11)) { // 数据传输完 do {__REGw(HSMMC_BASENORINTSTS_OFFSET) | (11); // 清除传输完成位} while (__REGw(HSMMC_BASENORINTSTS_OFFSET) (11)); return 0;}}ErrorState __REGw(HSMMC_BASEERRINTSTS_OFFSET) 0x1ff; // 可能通信错误,CRC检验错误,超时等__REGw(HSMMC_BASENORINTSTS_OFFSET) __REGw(HSMMC_BASENORINTSTS_OFFSET); // 清除中断标志__REGw(HSMMC_BASEERRINTSTS_OFFSET) __REGw(HSMMC_BASEERRINTSTS_OFFSET); // 清除错误中断标志Debug(Transfer error, rHM1_ERRINTSTS 0x%04x\r\n, ErrorState); do {__REGw(HSMMC_BASENORINTSTS_OFFSET) (11); // 出错后清除数据完成位} while (__REGw(HSMMC_BASENORINTSTS_OFFSET) (11));return ErrorState; // 数据传输出错
}static int32_t Hsmmc_IssueCommand(uint8_t Cmd, uint32_t Arg, uint8_t Data, uint8_t Response)
{uint32_t i;uint32_t Value;uint32_t ErrorState;// 检查CMD线是否准备好发送命令for (i0; i0x1000000; i) {if (!(__REG(HSMMC_BASEPRNSTS_OFFSET) (10))) {break;}}if (i 0x1000000) {Debug(CMD line time out, PRNSTS: %04x\r\n, __REG(HSMMC_BASEPRNSTS_OFFSET));return -1; // 命令超时}// 检查DAT线是否准备好if (Response CMD_RESP_R1B) { // R1b回复通过DAT0反馈忙信号for (i0; i0x10000000; i) {if (!(__REG(HSMMC_BASEPRNSTS_OFFSET) (11))) {break;} }if (i 0x10000000) {Debug(Data line time out, PRNSTS: %04x\r\n, __REG(HSMMC_BASEPRNSTS_OFFSET)); return -2;} }__REG(HSMMC_BASEARGUMENT_OFFSET) Arg; // 写入命令参数Value (Cmd 8); // command index// CMD12可终止传输if (Cmd 0x12) {Value | (0x3 6); // command type}if (Data) {Value | (1 5); // 需使用DAT线作为传输等} switch (Response) {case CMD_RESP_NONE:Value | (04) | (03) | 0x0; // 没有回复,不检查命令及CRCbreak;case CMD_RESP_R1:case CMD_RESP_R5:case CMD_RESP_R6:case CMD_RESP_R7: Value | (14) | (13) | 0x2; // 检查回复中的命令,CRCbreak;case CMD_RESP_R2:Value | (04) | (13) | 0x1; // 回复长度为136位,包含CRCbreak;case CMD_RESP_R3:case CMD_RESP_R4:Value | (04) | (03) | 0x2; // 回复长度48位,不包含命令及CRCbreak;case CMD_RESP_R1B:Value | (14) | (13) | 0x3; // 回复带忙信号,会占用Data[0]线break;default:break; }__REGw(HSMMC_BASECMDREG_OFFSET) Value;ErrorState Hsmmc_WaitForCommandDone();if (ErrorState) {Debug(Command %d\r\n, Cmd);} return ErrorState; // 命令发送出错
}int32_t Hsmmc_Switch(uint8_t Mode, int32_t Group, int32_t Function, uint8_t *pStatus)
{int32_t ErrorState;int32_t Temp;uint32_t i;__REGw(HSMMC_BASEBLKSIZE_OFFSET) (712) | (640); // 最大DMA缓存大小,block为512位64字节 __REGw(HSMMC_BASEBLKCNT_OFFSET) 1; // 写入这次读1 block的sd状态数据Temp (Mode 31U) | 0xffffff;Temp ~(0xf(Group * 4));Temp | Function (Group * 4);__REG(HSMMC_BASEARGUMENT_OFFSET) Temp; // 写入命令参数 // DMA禁能,读单块 __REGw(HSMMC_BASETRNMOD_OFFSET) (05) | (14) | (02) | (11) | (00); // 设置命令寄存器,SWITCH_FUNC CMD6,R1回复__REGw(HSMMC_BASECMDREG_OFFSET) (CMD68)|(15)|(14)|(13)|0x2;ErrorState Hsmmc_WaitForCommandDone();if (ErrorState) {Debug(CMD6 error\r\n);return ErrorState;}ErrorState Hsmmc_WaitForBufferReadReady();if (ErrorState) {return ErrorState;}pStatus 64 - 1;for (i0; i64/4; i) {Temp __REG(HSMMC_BASEBDATA_OFFSET);*pStatus-- (uint8_t)Temp;*pStatus-- (uint8_t)(Temp8);*pStatus-- (uint8_t)(Temp16);*pStatus-- (uint8_t)(Temp24); }ErrorState Hsmmc_WaitForTransferDone();if (ErrorState) {Debug(Get sd status error\r\n);return ErrorState;} return 0;
}// 512位的sd卡扩展状态位
int32_t Hsmmc_GetSdState(uint8_t *pStatus)
{int32_t ErrorState;uint32_t Temp;uint32_t i;if (CardType SD_HC || CardType SD_V2 || CardType SD_V1) {if (Hsmmc_GetCardState() ! CARD_TRAN) { // 必需在transfer statusreturn -1; // 卡状态错误} Hsmmc_IssueCommand(CMD55, RCA16, 0, CMD_RESP_R1);__REGw(HSMMC_BASEBLKSIZE_OFFSET) (712) | (640); // 最大DMA缓存大小,block为512位64字节 __REGw(HSMMC_BASEBLKCNT_OFFSET) 1; // 写入这次读1 block的sd状态数据__REG(HSMMC_BASEARGUMENT_OFFSET) 0; // 写入命令参数 // DMA禁能,读单块 __REGw(HSMMC_BASETRNMOD_OFFSET) (05) | (14) | (02) | (11) | (00); // 设置命令寄存器,读状态命令CMD13,R1回复__REGw(HSMMC_BASECMDREG_OFFSET) (CMD138)|(15)|(14)|(13)|0x2;ErrorState Hsmmc_WaitForCommandDone();if (ErrorState) {Debug(CMD13 error\r\n);return ErrorState;}ErrorState Hsmmc_WaitForBufferReadReady();if (ErrorState) {return ErrorState;}pStatus 64 - 1;for (i0; i64/4; i) {Temp __REG(HSMMC_BASEBDATA_OFFSET);*pStatus-- (uint8_t)Temp;*pStatus-- (uint8_t)(Temp8);*pStatus-- (uint8_t)(Temp16);*pStatus-- (uint8_t)(Temp24); }ErrorState Hsmmc_WaitForTransferDone();if (ErrorState) {Debug(Get sd status error\r\n);return ErrorState;}return 0;}return -1; // 非sd卡
}// Reads the SD Configuration Register (SCR).
int32_t Hsmmc_Get_SCR(SD_SCR *pSCR)
{uint8_t *pBuffer;int32_t ErrorState;uint32_t Temp;uint32_t i;Hsmmc_IssueCommand(CMD55, RCA16, 0, CMD_RESP_R1); __REGw(HSMMC_BASEBLKSIZE_OFFSET) (712) | (80); // 最大DMA缓存大小,block为64位8字节 __REGw(HSMMC_BASEBLKCNT_OFFSET) 1; // 写入这次读1 block的sd状态数据__REG(HSMMC_BASEARGUMENT_OFFSET) 0; // 写入命令参数 // DMA禁能,读单块 __REGw(HSMMC_BASETRNMOD_OFFSET) (05) | (14) | (02) | (11) | (00); // 设置命令寄存器,read SD Configuration CMD51,R1回复__REGw(HSMMC_BASECMDREG_OFFSET) (CMD518)|(15)|(14)|(13)|0x2;ErrorState Hsmmc_WaitForCommandDone();if (ErrorState) {Debug(CMD51 error\r\n);return ErrorState;}ErrorState Hsmmc_WaitForBufferReadReady();if (ErrorState) {return ErrorState;}// Wide width data (SD Memory Register)pBuffer (uint8_t *)pSCR sizeof(SD_SCR) - 1;for (i0; i8/4; i) {Temp __REG(HSMMC_BASEBDATA_OFFSET);*pBuffer-- (uint8_t)Temp;*pBuffer-- (uint8_t)(Temp8);*pBuffer-- (uint8_t)(Temp16);*pBuffer-- (uint8_t)(Temp24); }ErrorState Hsmmc_WaitForTransferDone();if (ErrorState) {Debug(Get SCR register error\r\n);return ErrorState;}return 0;
}// Asks the selected card to send its cardspecific data
int32_t Hsmmc_Get_CSD(uint8_t *pCSD)
{uint32_t i;uint32_t Response[4];int32_t State -1;if (CardType ! SD_HC CardType ! SD_V1 CardType ! SD_V2) {return State; // 未识别的卡}// 取消卡选择,任何卡均不回复,已选择的卡通过RCA0取消选择,// 卡回到stand-by状态Hsmmc_IssueCommand(CMD7, 0, 0, CMD_RESP_NONE);for (i0; i1000; i) {if (Hsmmc_GetCardState() CARD_STBY) { // CMD9命令需在standy-by status break; // 状态正确}Delay_us(100);}if (i 1000) {return State; // 状态错误} // 请求已标记卡发送卡特定数据(CSD),获得卡信息if (!Hsmmc_IssueCommand(CMD9, RCA16, 0, CMD_RESP_R2)) {pCSD; // 跳过第一字节,CSD中[127:8]位对位寄存器中的[119:0]Response[0] __REG(HSMMC_BASERSPREG0_OFFSET);Response[1] __REG(HSMMC_BASERSPREG1_OFFSET);Response[2] __REG(HSMMC_BASERSPREG2_OFFSET);Response[3] __REG(HSMMC_BASERSPREG3_OFFSET); for (i0; i15; i) { // 拷贝回复寄存器中的[119:0]到pCSD中*pCSD ((uint8_t *)Response)[i];} State 0; // CSD获取成功}Hsmmc_IssueCommand(CMD7, RCA16, 0, CMD_RESP_R1); // 选择卡,卡回到transfer状态return State;
}// R1回复中包含了32位的card state,卡识别后,可在任一状态通过CMD13获得卡状态
int32_t Hsmmc_GetCardState(void)
{if (Hsmmc_IssueCommand(CMD13, RCA16, 0, CMD_RESP_R1)) {return -1; // 卡出错} else {return ((__REG(HSMMC_BASERSPREG0_OFFSET)9) 0xf); // 返回R1回复中的[12:9]卡状态}
}static int32_t Hsmmc_SetBusWidth(uint8_t Width)
{int32_t State;if ((Width ! 1) || (Width ! 4)) {return -1;}State -1; // 设置初始为未成功__REGw(HSMMC_BASENORINTSTSEN_OFFSET) ~(18); // 关闭卡中断Hsmmc_IssueCommand(CMD55, RCA16, 0, CMD_RESP_R1);if (Width 1) {if (!Hsmmc_IssueCommand(CMD6, 0, 0, CMD_RESP_R1)) { // 1位宽__REGb(HSMMC_BASEHOSTCTL_OFFSET) ~(11);State 0; // 命令成功}} else {if (!Hsmmc_IssueCommand(CMD6, 2, 0, CMD_RESP_R1)) { // 4位宽__REGb(HSMMC_BASEHOSTCTL_OFFSET) | (11);State 0; // 命令成功}}__REGw(HSMMC_BASENORINTSTSEN_OFFSET) | (18); // 打开卡中断 return State; // 返回0为成功
}int32_t Hsmmc_EraseBlock(uint32_t StartBlock, uint32_t EndBlock)
{uint32_t i;if (CardType SD_V1 || CardType SD_V2) {StartBlock 9; // 标准卡为字节地址EndBlock 9;} else if (CardType ! SD_HC) {return -1; // 未识别的卡} Hsmmc_IssueCommand(CMD32, StartBlock, 0, CMD_RESP_R1);Hsmmc_IssueCommand(CMD33, EndBlock, 0, CMD_RESP_R1);if (!Hsmmc_IssueCommand(CMD38, 0, 0, CMD_RESP_R1B)) {for (i0; i0x10000; i) {if (Hsmmc_GetCardState() CARD_TRAN) { // 擦除完成后返回到transfer状态Debug(Erasing complete!\r\n);return 0; // 擦除成功 }Delay_us(1000); } } Debug(Erase block failed\r\n);return -1; // 擦除失败
}int32_t Hsmmc_ReadBlock(uint8_t *pBuffer, uint32_t BlockAddr, uint32_t BlockNumber)
{uint32_t Address 0;uint32_t ReadBlock;uint32_t i;uint32_t j;int32_t ErrorState;uint32_t Temp;if (pBuffer 0 || BlockNumber 0) {return -1;}__REGw(HSMMC_BASENORINTSTS_OFFSET) __REGw(HSMMC_BASENORINTSTS_OFFSET); // 清除中断标志__REGw(HSMMC_BASEERRINTSTS_OFFSET) __REGw(HSMMC_BASEERRINTSTS_OFFSET); // 清除错误中断标志 while (BlockNumber 0) {if (BlockNumber MAX_BLOCK) {ReadBlock BlockNumber; // 读取的块数小于65536 BlockBlockNumber 0; // 剩余读取块数为0} else {ReadBlock MAX_BLOCK; // 读取的块数大于65536 Block,分多次读BlockNumber - ReadBlock;}// 根据sd主机控制器标准,按顺序写入主机控制器相应的寄存器 __REGw(HSMMC_BASEBLKSIZE_OFFSET) (712) | (5120); // 最大DMA缓存大小,block为512字节 __REGw(HSMMC_BASEBLKCNT_OFFSET) ReadBlock; // 写入这次读block数目if (CardType SD_HC) {Address BlockAddr; // SDHC卡写入地址为block地址} else if (CardType SD_V1 || CardType SD_V2) {Address BlockAddr 9; // 标准卡写入地址为字节地址} BlockAddr ReadBlock; // 下一次读块的地址__REG(HSMMC_BASEARGUMENT_OFFSET) Address; // 写入命令参数 if (ReadBlock 1) {// 设置传输模式,DMA禁能,读单块__REGw(HSMMC_BASETRNMOD_OFFSET) (05) | (14) | (02) | (11) | (00);// 设置命令寄存器,单块读CMD17,R1回复__REGw(HSMMC_BASECMDREG_OFFSET) (CMD178)|(15)|(14)|(13)|0x2;} else {// 设置传输模式,DMA禁能,读多块 __REGw(HSMMC_BASETRNMOD_OFFSET) (15) | (14) | (12) | (11) | (00);// 设置命令寄存器,多块读CMD18,R1回复 __REGw(HSMMC_BASECMDREG_OFFSET) (CMD188)|(15)|(14)|(13)|0x2; } ErrorState Hsmmc_WaitForCommandDone();if (ErrorState) {Debug(Read Command error\r\n);return ErrorState;} for (i0; iReadBlock; i) {ErrorState Hsmmc_WaitForBufferReadReady();if (ErrorState) {return ErrorState;}if (((uint32_t)pBuffer 0x3) 0) { for (j0; j512/4; j) {*(uint32_t *)pBuffer __REG(HSMMC_BASEBDATA_OFFSET);pBuffer 4;}} else {for (j0; j512/4; j) {Temp __REG(HSMMC_BASEBDATA_OFFSET);*pBuffer (uint8_t)Temp;*pBuffer (uint8_t)(Temp8);*pBuffer (uint8_t)(Temp16);*pBuffer (uint8_t)(Temp24);}} }ErrorState Hsmmc_WaitForTransferDone();if (ErrorState) {Debug(Read block error\r\n);return ErrorState;} }return 0; // 所有块读完
}int32_t Hsmmc_WriteBlock(uint8_t *pBuffer, uint32_t BlockAddr, uint32_t BlockNumber)
{uint32_t Address 0;uint32_t WriteBlock;uint32_t i;uint32_t j;int32_t ErrorState;if (pBuffer 0 || BlockNumber 0) {return -1; // 参数错误} __REGw(HSMMC_BASENORINTSTS_OFFSET) __REGw(HSMMC_BASENORINTSTS_OFFSET); // 清除中断标志__REGw(HSMMC_BASEERRINTSTS_OFFSET) __REGw(HSMMC_BASEERRINTSTS_OFFSET); // 清除错误中断标志while (BlockNumber 0) { if (BlockNumber MAX_BLOCK) {WriteBlock BlockNumber;// 写入的块数小于65536 BlockBlockNumber 0; // 剩余写入块数为0} else {WriteBlock MAX_BLOCK; // 写入的块数大于65536 Block,分多次写BlockNumber - WriteBlock;}if (WriteBlock 1) { // 多块写,发送ACMD23先设置预擦除块数Hsmmc_IssueCommand(CMD55, RCA16, 0, CMD_RESP_R1);Hsmmc_IssueCommand(CMD23, WriteBlock, 0, CMD_RESP_R1);}// 根据sd主机控制器标准,按顺序写入主机控制器相应的寄存器 __REGw(HSMMC_BASEBLKSIZE_OFFSET) (712) | (5120); // 最大DMA缓存大小,block为512字节 __REGw(HSMMC_BASEBLKCNT_OFFSET) WriteBlock; // 写入block数目 if (CardType SD_HC) {Address BlockAddr; // SDHC卡写入地址为block地址} else if (CardType SD_V1 || CardType SD_V2) {Address BlockAddr 9; // 标准卡写入地址为字节地址}BlockAddr WriteBlock; // 下一次写地址__REG(HSMMC_BASEARGUMENT_OFFSET) Address; // 写入命令参数 if (WriteBlock 1) {// 设置传输模式,DMA禁能写单块__REGw(HSMMC_BASETRNMOD_OFFSET) (05) | (04) | (02) | (11) | (00);// 设置命令寄存器,单块写CMD24,R1回复__REGw(HSMMC_BASECMDREG_OFFSET) (CMD248)|(15)|(14)|(13)|0x2; } else {// 设置传输模式,DMA禁能写多块__REGw(HSMMC_BASETRNMOD_OFFSET) (15) | (04) | (12) | (11) | (00);// 设置命令寄存器,多块写CMD25,R1回复__REGw(HSMMC_BASECMDREG_OFFSET) (CMD258)|(15)|(14)|(13)|0x2; }ErrorState Hsmmc_WaitForCommandDone();if (ErrorState) {Debug(Write Command error\r\n);return ErrorState;} for (i0; iWriteBlock; i) {ErrorState Hsmmc_WaitForBufferWriteReady();if (ErrorState) {return ErrorState;}if (((uint32_t)pBuffer 0x3) 0) {for (j0; j512/4; j) {__REG(HSMMC_BASEBDATA_OFFSET) *(uint32_t *)pBuffer;pBuffer 4;}} else {for (j0; j512/4; j) {__REG(HSMMC_BASEBDATA_OFFSET) pBuffer[0] ((uint32_t)pBuffer[1]8) ((uint32_t)pBuffer[2]16) ((uint32_t)pBuffer[3]24);pBuffer 4;}} }ErrorState Hsmmc_WaitForTransferDone();if (ErrorState) {Debug(Write block error\r\n);return ErrorState;}for (i0; i0x10000000; i) {if (Hsmmc_GetCardState() CARD_TRAN) { // 需在transfer statusbreak; // 状态正确}}if (i 0x10000000) {return -3; // 状态错误或Programming超时} }return 0; // 写完所有数据
}int Hsmmc_Init(void)
{int32_t Timeout;uint32_t Capacity;uint32_t i;uint32_t OCR;uint32_t Temp;uint8_t SwitchStatus[64];SD_SCR SCR;uint8_t CSD[16];uint32_t c_size, c_size_multi, read_bl_len; // 设置HSMMC的接口引脚配置
#if (HSMMC_NUM 0)// channel 0,GPG0[0:6] CLK, CMD, CDn, DAT[0:3]GPG0CON_REG 0x2222222;// pull up enableGPG0PUD_REG 0x2aaa;GPG0DRV_REG 0x3fff;// channel 0 clock src SCLKEPLL 96MCLK_SRC4_REG (CLK_SRC4_REG (~(0xf0))) | (0x70);// channel 0 clock SCLKEPLL/2 48MCLK_DIV4_REG (CLK_DIV4_REG (~(0xf0))) | (0x10); #elif (HSMMC_NUM 1)// channel 1,GPG1[0:6] CLK, CMD, CDn, DAT[0:3]GPG1CON_REG 0x2222222;// pull up enableGPG1PUD_REG 0x2aaa;GPG1DRV_REG 0x3fff;// channel 1 clock src SCLKEPLL 96MCLK_SRC4_REG (CLK_SRC4_REG (~(0xf4))) | (0x74);// channel 1 clock SCLKEPLL/2 48MCLK_DIV4_REG (CLK_DIV4_REG (~(0xf4))) | (0x14);#elif (HSMMC_NUM 2)// channel 2,GPG2[0:6] CLK, CMD, CDn, DAT[0:3]GPG2CON_REG 0x2222222;// pull up enableGPG2PUD_REG 0x2aaa;GPG2DRV_REG 0x3fff;// channel 2 clock src SCLKEPLL 96MCLK_SRC4_REG (CLK_SRC4_REG (~(0xf8))) | (0x78);// channel 2 clock SCLKEPLL/2 48MCLK_DIV4_REG (CLK_DIV4_REG (~(0xf8))) | (0x18); #elif (HSMMC_NUM 3)// channel 3,GPG3[0:6] CLK, CMD, CDn, DAT[0:3]GPG3CON_REG 0x2222222;// pull up enableGPG3PUD_REG 0x2aaa;GPG3DRV_REG 0x3fff;// channel 3 clock src SCLKEPLL 96MCLK_SRC4_REG (CLK_SRC4_REG (~(0xf12))) | (0x712);// channel 3 clock SCLKEPLL/2 48MCLK_DIV4_REG (CLK_DIV4_REG (~(0xf12))) | (0x112); #endif// software reset for all 复位主机SoC控制器而不是复位SD卡__REGb(HSMMC_BASESWRST_OFFSET) 0x1;Timeout 1000; // Wait max 10 mswhile (__REGb(HSMMC_BASESWRST_OFFSET) (10)) {if (Timeout 0) {return -1; // reset timeout}Timeout--;Delay_us(10);} // 上面设置的是SoC的SD控制器的时钟现在设置的是SD卡的时钟Hsmmc_SetClock(400000); // 400k__REGb(HSMMC_BASETIMEOUTCON_OFFSET) 0xe; // 最大超时时间__REGb(HSMMC_BASEHOSTCTL_OFFSET) ~(12); // 正常速度模式// 清除正常中断状态标志__REGw(HSMMC_BASENORINTSTS_OFFSET) __REGw(HSMMC_BASENORINTSTS_OFFSET);// 清除错误中断状态标志__REGw(HSMMC_BASEERRINTSTS_OFFSET) __REGw(HSMMC_BASEERRINTSTS_OFFSET);__REGw(HSMMC_BASENORINTSTSEN_OFFSET) 0x7fff; // [14:0]中断状态使能__REGw(HSMMC_BASEERRINTSTSEN_OFFSET) 0x3ff; // [9:0]错误中断状态使能__REGw(HSMMC_BASENORINTSIGEN_OFFSET) 0x7fff; // [14:0]中断信号使能 __REGw(HSMMC_BASEERRINTSIGEN_OFFSET) 0x3ff; // [9:0]错误中断信号使能// 从这里开始和SD卡通信通信其实就是发命令然后收响应Hsmmc_IssueCommand(CMD0, 0, 0, CMD_RESP_NONE); // 复位所有卡到空闲状态 CardType UNUSABLE; // 卡类型初始化不可用if (Hsmmc_IssueCommand(CMD8, 0x1aa, 0, CMD_RESP_R7)) { // 没有回复,MMC/sd v1.x/not cardfor (i0; i100; i) {// CMD55 CMD41 ACMD41Hsmmc_IssueCommand(CMD55, 0, 0, CMD_RESP_R1);if (!Hsmmc_IssueCommand(CMD41, 0, 0, CMD_RESP_R3)) { // CMD41有回复说明为sd卡OCR __REG(HSMMC_BASERSPREG0_OFFSET); // 获得回复的OCR(操作条件寄存器)值if (OCR 0x80000000) { // 卡上电是否完成上电流程,是否busyCardType SD_V1; // 正确识别出sd v1.x卡Debug(SD card version 1.x is detected\r\n);break;}} else {// MMC卡识别Debug(MMC card is not supported\r\n);return -1;}Delay_us(1000); }} else { // sd v2.0Temp __REG(HSMMC_BASERSPREG0_OFFSET);if (((Temp0xff) 0xaa) (((Temp8)0xf) 0x1)) { // 判断卡是否支持2.7~3.3v电压OCR 0;for (i0; i100; i) {OCR | (130);Hsmmc_IssueCommand(CMD55, 0, 0, CMD_RESP_R1);Hsmmc_IssueCommand(CMD41, OCR, 0, CMD_RESP_R3); // reday态OCR __REG(HSMMC_BASERSPREG0_OFFSET);if (OCR 0x80000000) { // 卡上电是否完成上电流程,是否busyif (OCR (130)) { // 判断卡为标准卡还是高容量卡CardType SD_HC; // 高容量卡Debug(SDHC card is detected\r\n);} else {CardType SD_V2; // 标准卡Debug(SD version 2.0 standard card is detected\r\n);}break;}Delay_us(1000);}}}if (CardType SD_HC || CardType SD_V1 || CardType SD_V2) {Hsmmc_IssueCommand(CMD2, 0, 0, CMD_RESP_R2); // 请求卡发送CID(卡ID寄存器)号,进入identHsmmc_IssueCommand(CMD3, 0, 0, CMD_RESP_R6); // 请求卡发布新的RCA(卡相对地址),Stand-by状态RCA (__REG(HSMMC_BASERSPREG0_OFFSET) 16) 0xffff; // 从卡回复中得到卡相对地址Hsmmc_IssueCommand(CMD7, RCA16, 0, CMD_RESP_R1); // 选择已标记的卡,transfer状态Hsmmc_Get_SCR(SCR);if (SCR.SD_SPEC 0) { // sd 1.0 - sd 1.01// Version 1.0 doesnt support switchingHsmmc_SetClock(24000000); // 设置SDCLK 48M/2 24M } else { // sd 1.10 / sd 2.0Temp 0;for (i0; i4; i) {if (Hsmmc_Switch(0, 0, 1, SwitchStatus) 0) { // switch checkif (!(SwitchStatus[34] (11))) { // Group 1, function 1 high-speed bit 273 // The high-speed function is readyif (SwitchStatus[50] (11)) { // Group, function 1 high-speed support bit 401// high-speed is supportedif (Hsmmc_Switch(1, 0, 1, SwitchStatus) 0) { // switchif ((SwitchStatus[47] 0xf) 1) { // function switch in group 1 is ok?// result of the switch high-speed in function group 1Debug(Switch to high speed mode: CLK 50M\r\n);Hsmmc_SetClock(48000000); // 设置SDCLK 48M Temp 1; }}}break;}} }if (Temp 0) {Hsmmc_SetClock(24000000); // 设置SDCLK 48M/2 24M}}if (!Hsmmc_SetBusWidth(4)) {Debug(Set bus width error\r\n);return -1; // 位宽设置出错}if (Hsmmc_GetCardState() CARD_TRAN) { // 此时卡应在transfer态if (!Hsmmc_IssueCommand(CMD16, 512, 0, CMD_RESP_R1)) { // 设置块长度为512字节__REGw(HSMMC_BASENORINTSTS_OFFSET) 0xffff; // 清除中断标志Hsmmc_Get_CSD(CSD);if ((CSD[15]6) 0) { // CSD v1.0-sd V1.x, sd v2.00 standarread_bl_len CSD[10] 0xf; // [83:80]c_size_multi ((CSD[6] 0x3) 1) ((CSD[5] 0x80) 7); // [49:47]c_size ((int32_t)(CSD[9]0x3) 10) ((int32_t)CSD[8]2) (CSD[7]6); // [73:62] Capacity (c_size 1) ((c_size_multi 2) (read_bl_len-9)); // block(512 byte)} else {c_size ((CSD[8]0x3f) 16) (CSD[7]8) CSD[6]; // [69:48]// 卡容量为字节(c_size1)*512K byte,以1扇区512 byte字,卡的扇区数为 Capacity (c_size1) 10;// block (512 byte)}Debug(Card Initialization succeed\r\n); Debug(Capacity: %ldMB\r\n, Capacity / (1024*1024 / 512));return 0; // 初始化成功 }}}Debug(Card Initialization failed\r\n);return -1; // 卡工作异常
}