inand总结

1 inand的介绍

1.1 inand由接口电路和系统储存组成。
1.2 inand有8根IO线,一根命令线,一根时钟线。SD卡有四根IO线,一根命令线,一根时钟线。

1.3 inand接口电路的功能
1.3.1提供eMMC接口协议和SOC对接。
1.3.2提供eMMC校验的相关逻辑,简化了SOC的编程。
1.3.3 内部使用了MLC的储存颗粒,价格便宜,性价比高。
1.3.4 提供cache机制,所以inand的读取速度快。

2 inand的操作

2.1 支持1,4,8线并行传输
2.2 通过CMD线来传输命令,通过CLK线来传输时钟。
2.3 soc可以通过寻址或者广播向一个或者多个SD卡发送命令,SD卡接收到命令之后会返回一个响应。
在这里插入图片描述
2.4 soc也可以进行多块读写,soc先发送一个多块读写的命令,之后SD卡回应一个响应,当停止读写的时候,SOC会发送一个停止命令,之后SD卡发送一个响应,多块读写结束。如图

在这里插入图片描述
2.5 命令牌图

在这里插入图片描述
2.6 SD卡结构图
在这里插入图片描述

3 代码分析

3.1初始化流程图
在这里插入图片描述
3.2 传输图
在这里插入图片描述
3.3 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	8
	
typedef 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__*/

3.4 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 0x2F



static uint8_t CardType; // 卡类型
static uint32_t RCA; // 卡相对地址

static void Hsmmc_ClockOn(uint8_t On)
{
	uint32_t Timeout;
	if (On) {
		__REGw(HSMMC_BASE+CLKCON_OFFSET) |= (1<<2); // sd时钟使能
		Timeout = 1000; // Wait max 10 ms
		while (!(__REGw(HSMMC_BASE+CLKCON_OFFSET) & (1<<3))) {
			// 等待SD输出时钟稳定
			if (Timeout == 0) {
				return;
			}
			Timeout--;
			Delay_us(10);
		}
	} else {
		__REGw(HSMMC_BASE+CLKCON_OFFSET) &= ~(1<<2); // sd时钟禁止
	}
}

static void Hsmmc_SetClock(uint32_t Clock)
{
	uint32_t Temp;
	uint32_t Timeout;
	uint32_t i;
	Hsmmc_ClockOn(0); // 关闭时钟	
	Temp = __REG(HSMMC_BASE+CONTROL2_OFFSET);
	// Set SCLK_MMC(48M) from SYSCON as a clock source	
	Temp = (Temp & (~(3<<4))) | (2<<4);
	Temp |= (1u<<31) | (1u<<30) | (1<<8);
	if (Clock <= 500000) {
		Temp &= ~((1<<14) | (1<<15));
		__REG(HSMMC_BASE+CONTROL3_OFFSET) = 0;
	} else {
		Temp |= ((1<<14) | (1<<15));
		__REG(HSMMC_BASE+CONTROL3_OFFSET) = (1u<<31) | (1<<23);
	}
	__REG(HSMMC_BASE+CONTROL2_OFFSET) = Temp;
	
	for (i=0; i<=8; i++) {
		if (Clock >= (48000000/(1<<i))) {
			break;
		}
	}
	Temp = ((1<<i) / 2) << 8; // clock div
	Temp |= (1<<0); // Internal Clock Enable
	__REGw(HSMMC_BASE+CLKCON_OFFSET) = Temp;
	Timeout = 1000; // Wait max 10 ms
	while (!(__REGw(HSMMC_BASE+CLKCON_OFFSET) & (1<<1))) {
		// 等待内部时钟振荡稳定
		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_BASE+NORINTSTS_OFFSET) & (1<<15)) { // 出现错误
			break;
		}
		if (__REGw(HSMMC_BASE+NORINTSTS_OFFSET) & (1<<5)) { // 读缓存准备好
			__REGw(HSMMC_BASE+NORINTSTS_OFFSET) |&
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值