硬件准备
ADSP-EDU-BF533:BF533开发板
AD-HP530ICE:ADI DSP仿真器
软件准备
Visual DSP++软件
硬件链接
功能介绍
ADSP-EDU-BF53x 板卡上设计了一个 SD/MMC 接口,可以通过该接口实现对 SD/MMC 卡数据的访问。
SD 卡有两种工作模式:SDIO 模式和 SPI 模式。SDIO 模式为半字节读写模式,该模式采用四根数据线,每次可对半个字节作操作。SPI 模式有 4 根控制线:MOSI,MISO,SPICLK,SPISS.因为每次只能对一位数据作操作。
SD/MMC 卡的寻址方式是按字节寻址的,为方便使用,将其寻址方式定义成连续的存储单元寻址方式。每个存储单元为 512 个字节。每个存储单元地址唯一,通过访问存储单元地址来读取数据。
ADSP-EDU-BF533板卡上采用 PF2 实现对 SPI 设备的控制,由于板卡上有 SD 卡和触摸屏控制器两个 SPI 设备,所以通过 CPLD 将 PF2 接口做了个 2 选 1 切换,通过配置 CPLD 的 DEVICE_OE 寄存器,来使能和选通 PF2 连接哪一个 SPI 设备。
SD 卡插入后,不会触发中断信号,但可以通过中断数据寄存器读取其插入信息。
DEVICE_OE 寄存器(读/写):
DEVICE_OE 寄存器地址:0x20320000
DEVICE_OE 寄存器设置硬件设备上一些控制管脚的电平状态。
DEVICE_OE 寄存器位功能:
SPI_SEL1~0:SPI 片选选择位
00:SPI_SEL 选通触摸屏模块
01:SPI_SEL 选通 SD 卡模块
10:SPI_SEL 选通外部 SPI0 模块
11:SPI_SEL 选通外部 SPI1 模块
在使用 SD/MMC 卡接口时时,需将 SPI_SEL0 位设置为 1,将 SPI_SEL1 位设置为 0。
硬件连接示意图
代码实现功能
代码实现了对 SD/MMC 卡扇区的写入和读取,并将读出的数据与写入的数据做比较,并打印比较结果。
测试步骤
1. 将仿真器(ICE)与 ADSP-EDU-BF53x 开发板和计算机连接好。
2. 将 SD 或 MMC 卡插入 SD 卡接口。
3. 先给 ADSP-EDU-BF53x 开发板上电,再为仿真器(ICE)上电。
4. 运行 VisualDSP++ 5.0 软件,选择合适的 BF533 的 session 将仿真器与软件连接。
5. 加载 VisualDSP++ 5.0 工程文件 BF53x_SD_MMC.dpj,编译并全速运行。
测试结果
在 VisualDSP++ 软件上打印校验数据的结果。
SD/MMC 卡校验完成
写入的数据和读出的数据内存比较。
程序源码
CPU.C
#include <cdefBF533.h>
void Init_SDRAM(void)
{
*pEBIU_SDRRC = 0x00000817;
*pEBIU_SDBCTL = 0x00000013;
*pEBIU_SDGCTL = 0x0091998d;
ssync();
}
void Init_EBIU(void)
{
*pEBIU_AMBCTL0 = 0x7bb07bb0;
*pEBIU_AMBCTL1 = 0xffc07bb0;
*pEBIU_AMGCTL = 0x000f;
}
void Set_PLL(int pmsel,int pssel)
{
int new_PLL_CTL;
*pPLL_DIV = pssel;
asm(“ssync;”);
new_PLL_CTL = (pmsel & 0x3f) << 9;
*pSIC_IWR |= 0xffffffff;
if (new_PLL_CTL != *pPLL_CTL)
{
*pPLL_CTL = new_PLL_CTL;
asm(“ssync;”);
asm(“idle;”);
}
}
SD_mmc.c
#include <cdefBF533.h>
#include “sd_mmc.h”
void MMC_HardwareInitial(void)
{
*pSPI_FLG = FLS2;
*pSPI_BAUD = 550;
*pSPI_CTL = 0x0000;
*pSPI_CTL = 0x0001 | MSTR ;
*pSPI_CTL = (*pSPI_CTL | SPE);
}
/****************************************************************************
-
名称 : SPI_TransferByte
-
功能 : 将数据value发出
-
入口参数 :value
-
出口参数 :无
****************************************************************************/
unsigned char SPI_TransferByte(unsigned char value)
{
unsigned char incoming=0;
while((*pSPI_STAT & TXS));
*pSPI_TDBR = value;while(*pSPI_STAT & RXS)
incoming = *pSPI_RDBR;return(incoming);
}
/**************************************************************************** -
名称 : MMC_Init
-
功能 : 初始化MMC Card
-
入口参数 :无
-
出口参数 :无
****************************************************************************/
void MMC_Init(void)
{
unsigned char retry,temp;
unsigned char i;
unsigned char r1;
tryagain:
for (i=0;i<10;i++)
{
SPI_TransferByte(0xff); //send 74 clock at least!!!
}
SPI_TransferByte(MMC_RESET);
SPI_TransferByte(0x00);
SPI_TransferByte(0x00);
SPI_TransferByte(0x00);
SPI_TransferByte(0x00);
SPI_TransferByte(0x95);
SPI_TransferByte(0xff);
SPI_TransferByte(0xff);
retry=0;
do{
temp=Write_Command_MMC(MMC_INIT,0);
retry++;
if(retry==100)
{
printf("SD/MMC_INIT is ERROR!\n ");
goto tryagain;
}
}while(temp!=0);
printf("SD/MMC_INIT is OK!\n");
}
/****************************************************************************
-
名称 : Write_Command_MMC
-
功能 : 向MCC卡写命令 ,将命令字cmd送入地址address,返回状态值tmp
-
入口参数 :cmd,address
-
出口参数 :tmp
****************************************************************************/
unsigned char Write_Command_MMC(unsigned int cmd, unsigned int address)
{
unsigned char tmp;
unsigned char retry=0;SPI_TransferByte(cmd);
SPI_TransferByte(address>>24);
SPI_TransferByte(address>>16);
SPI_TransferByte(address>>8);
SPI_TransferByte(address);
SPI_TransferByte(0xFF);do{
tmp = SPI_TransferByte(0xFF);
retry++;
}while((tmp==0xff)&&(retry<8));return(tmp);
}
/*********************************************************************************
-
名称 : Write_Command_MMCCRC
-
功能 : 向MCC卡写命令 ,将命令字cmd送入地址address,和crc,返回状态值tmp
-
入口参数 :cmd,address, crc
-
出口参数 :tmp
**********************************************************************************/
unsigned char Write_Command_MMCCRC(unsigned int cmd, unsigned int address,unsigned char crc)
{
unsigned char tmp;
unsigned char retry=0;
SPI_TransferByte(0xFF);SPI_TransferByte(cmd);
SPI_TransferByte(address>>24);
SPI_TransferByte(address>>16);
SPI_TransferByte(address>>8);
SPI_TransferByte(address);
SPI_TransferByte(crc);do{
tmp = SPI_TransferByte(0xFF);
retry++;
}while((tmp==0xff)&&(retry<0xfe));SPI_TransferByte(0xFF);
return(tmp);
}
/*********************************************************************************
-
名称 : Write_Command_MMCCRC_NoDeassert
-
功能 : 向MCC卡写命令 ,将命令字cmd送入地址address,和crc,返回状态值tmp
-
入口参数 :cmd,address, crc
-
出口参数 :tmp
**********************************************************************************/
unsigned char Write_Command_MMCCRC_NoDeassert(unsigned int cmd, unsigned int address,unsigned char crc)
{
unsigned char tmp;
unsigned char retry=0;
SPI_TransferByte(0xFF);SPI_TransferByte(cmd);
SPI_TransferByte(address>>24);
SPI_TransferByte(address>>16);
SPI_TransferByte(address>>8);
SPI_TransferByte(address);
SPI_TransferByte(crc);do{
tmp = SPI_TransferByte(0xFF);
retry++;
}while((tmp==0xff)&&(retry<0xfe));return(tmp);
}
/****************************************************************************
-
名称 : MMC_read_sector
-
功能 : 读取MMC卡扇区数据,指定要读的扇区号和将数据传入的buff地址
-
入口参数 :addrBuffer
-
出口参数 :1
****************************************************************************/
unsigned char MMC_read_sector(unsigned int addr,unsigned char *Buffer)
{
unsigned char temp;
unsigned int i;SPI_TransferByte(0xff);
temp = Write_Command_MMC(MMC_READ_BLOCK,addr<<9);
if(temp != 0x00)
{
return(READ_BLOCK_ERROR);
}while(SPI_TransferByte(0xff) != 0xfe);
for(i=0;i<512;i++)
{
*Buffer++ = SPI_TransferByte(0xff);
}
SPI_TransferByte(0xff);
SPI_TransferByte(0xff);return (1);
}
/**************************************************************************** -
名称 : MMC_Write_sector
-
功能 : 写MMC卡扇区,将BUF的数据写入扇区号sector
-
入口参数 :sector,buf
-
出口参数 :0
****************************************************************************/
unsigned char MMC_Write_sector(unsigned int sector, unsigned char *buf)
{
unsigned char *p, by;
unsigned int i,flag;
unsigned int startadr;p = buf;
startadr = sector*(unsigned int)BYTE_PER_SEC;
Write_Command_MMC (MMC_WRITE_BLOCK,startadr);SPI_TransferByte(0xFF);
SPI_TransferByte(0xFF);
SPI_TransferByte(0xFE);
for(i=0; i<BYTE_PER_SEC; i++)
{
SPI_TransferByte(*p++);
}
SPI_TransferByte(0xFF);
SPI_TransferByte(0xFF);
do
{
flag = SPI_TransferByte(0xFF);
by=flag & 0x1F;
}while(by != 0x05);do
{
flag = SPI_TransferByte(0xFF);
}while(flag !=0xFF);return 0;
}
main.c
#include <cdefBF533.h>
#include “sd_mmc.h”
unsigned char buff_w[512];
unsigned char buff_r[512];
/****************************************************************************
-
名称 : check_test
-
功能 : 校验写入数据的正确性,将写入的数据读出比较
-
入口参数 :无
-
出口参数 :无
****************************************************************************/
void check_test(void)
{
int i;for(i=0;i<512;i++)
buff_w[i] = i;MMC_Write_sector(1000,buff_w);
MMC_read_sector(1000,buff_r);for(i=0;i<512;i++)
{
if(buff_w[i] != buff_r[i])
{
printf(“SD/MMC TEST ERROR!\n”);
break;
}
}
printf(“SD/MMC TEST OK!\n”);
}
int main()
{
Set_PLL(16,4);
Init_EBIU();
SD_Enable();
MMC_HardwareInitial();
MMC_Init();
check_test();
printf("SD/MMC Check END!\r\n");
while(1);
}
我在程序里尽量写了一些我认为有必要的注释,还有看不明白的可以问我。