2013-01-08 22:40:58 +08:00
|
|
|
|
/*
|
|
|
|
|
* File : sdcard.c
|
|
|
|
|
* This file is part of RT-Thread RTOS
|
|
|
|
|
* COPYRIGHT (C) 2007 - 2012, RT-Thread Development Team
|
|
|
|
|
*
|
|
|
|
|
* The license and distribution terms for this file may be
|
|
|
|
|
* found in the file LICENSE in this distribution or at
|
|
|
|
|
* http://www.rt-thread.org/license/LICENSE
|
|
|
|
|
*
|
|
|
|
|
* Change Logs:
|
|
|
|
|
* Date Author Notes
|
|
|
|
|
* 2007-12-02 Yi.Qiu the first version
|
|
|
|
|
* 2010-01-01 Bernard Modify for mini2440
|
|
|
|
|
* 2010-10-13 Wangmeng Added sep4020 support
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "sdcard.h"
|
|
|
|
|
//#include <dfs_config.h>
|
|
|
|
|
|
|
|
|
|
volatile rt_int32_t RCA;
|
|
|
|
|
|
|
|
|
|
#ifdef RT_USING_DFS
|
|
|
|
|
|
|
|
|
|
/* RT-Thread Device Driver Interface */
|
|
|
|
|
#include <rtthread.h>
|
|
|
|
|
#include <dfs_fs.h>
|
|
|
|
|
|
|
|
|
|
/*GLOBAL SD DEVICE PONITER*/
|
|
|
|
|
static struct sd_device *ptr_sddev;
|
|
|
|
|
static rt_uint8_t gsec_buf[SECTOR_SIZE];
|
|
|
|
|
|
|
|
|
|
#define USE_TIMEOUT
|
|
|
|
|
|
|
|
|
|
/*This file is to power on/off the SEP4020 SDC*/
|
2011-02-26 16:25:33 +08:00
|
|
|
|
/**
|
|
|
|
|
* This function will power on/off the SEP4020 SDC
|
|
|
|
|
*
|
|
|
|
|
* @param sd_ctl: 0/power on; 1/power off
|
|
|
|
|
* @return none
|
|
|
|
|
*
|
2013-01-08 22:40:58 +08:00
|
|
|
|
*/
|
|
|
|
|
static void sd_pwr(int sd_ctl)
|
|
|
|
|
{
|
|
|
|
|
if (sd_ctl)
|
|
|
|
|
{
|
|
|
|
|
*(RP)GPIO_PORTA_SEL |= 0x0200;
|
|
|
|
|
*(RP)GPIO_PORTA_DIR &= (~0x0200);
|
|
|
|
|
*(RP)GPIO_PORTA_DATA |= 0x0200;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
*(RP)GPIO_PORTA_SEL |= 0x0200;
|
|
|
|
|
*(RP)GPIO_PORTA_DIR &= (~0x0200);
|
|
|
|
|
*(RP)GPIO_PORTA_DATA &= (~0x0200);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*a nop operation to delay*/
|
|
|
|
|
static void delay (U32 j)
|
|
|
|
|
{
|
|
|
|
|
U32 i;
|
|
|
|
|
|
|
|
|
|
for (i=0;i<j;i++)
|
|
|
|
|
{};
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
* Send the command to set the data transfer mode
|
|
|
|
|
* @param cmd:the command to sent
|
|
|
|
|
* @param arg:the argument of the command
|
|
|
|
|
* @param mode:SDC transfer mode
|
|
|
|
|
* @param blk_len:the block size of each data
|
|
|
|
|
* @param num:number of blocks
|
|
|
|
|
* @param mask:sdc interrupt mask
|
|
|
|
|
*/
|
|
|
|
|
static rt_err_t cmd_data(U16 cmd,U32 arg,U16 mode,U16 blk_len,U16 num,U16 mask)
|
|
|
|
|
{
|
|
|
|
|
U32 i;
|
|
|
|
|
#ifdef USE_TIMEOUT
|
|
|
|
|
U32 to = 10000;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
*(RP)SDC_CLOCK_CONTROL = 0Xff00; //<2F><><EFBFBD><EFBFBD>SDʱ<44>ӣ<EFBFBD>512<31><32>Ƶ,<2C>ر<EFBFBD>SD ʱ<><CAB1>
|
|
|
|
|
*(RP)SDC_CLOCK_CONTROL = 0Xff04; //<2F><><EFBFBD><EFBFBD>SDʱ<44>ӣ<EFBFBD>512<31><32>Ƶ,<2C><><EFBFBD><EFBFBD>SD ʱ<><CAB1>
|
|
|
|
|
*(RP)SDC_INTERRUPT_STATUS_MASK = mask; //<2F>ж<EFBFBD>״̬<D7B4><CCAC><EFBFBD>μĴ<CEBC><C4B4><EFBFBD><EFBFBD><EFBFBD>ֵ
|
|
|
|
|
|
|
|
|
|
*(RP)SDC_TRANSFER_MODE = mode; //<2F><><EFBFBD><EFBFBD>ģʽѡ<CABD><D1A1><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD>ֵ
|
|
|
|
|
|
|
|
|
|
*(RP)SDC_BLOCK_SIZE = blk_len; //<2F><><EFBFBD>ݿ鳤<DDBF>ȼĴ<C8BC><C4B4><EFBFBD><EFBFBD><EFBFBD>ֵ
|
|
|
|
|
*(RP)SDC_BLOCK_COUNT = num; //<2F><><EFBFBD>ݿ<EFBFBD><DDBF><EFBFBD>Ŀ<EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD>ֵ
|
|
|
|
|
*(RP)SDC_ARGUMENT = arg; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD>ֵ
|
|
|
|
|
*(RP)SDC_COMMAND = cmd; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƼĴ<C6BC><C4B4><EFBFBD><EFBFBD><EFBFBD>ֵ
|
|
|
|
|
|
|
|
|
|
delay(10);
|
|
|
|
|
|
|
|
|
|
i = *(RP)SDC_INTERRUPT_STATUS & 0x1000;
|
|
|
|
|
|
|
|
|
|
while(i != 0x1000) //<2F>жϣ<D0B6><CFA3>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EEB7A2><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD><CFA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD><D5B5><EFBFBD>Ӧ
|
|
|
|
|
{
|
|
|
|
|
i = *(RP)SDC_INTERRUPT_STATUS & 0x1000;
|
|
|
|
|
#ifdef USE_TIMEOUT
|
|
|
|
|
to --;
|
|
|
|
|
if(!to)
|
|
|
|
|
{
|
|
|
|
|
EOUT("%s TIMEOUT\n",__FUNCTION__);
|
|
|
|
|
return RT_ETIMEOUT;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
delay(160);
|
|
|
|
|
|
|
|
|
|
#ifdef USE_TIMEOUT
|
|
|
|
|
//DBOUT("cmd_data TO is %d\n",to);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return *(RP)SDC_RESPONSE0; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EEB7B4><EFBFBD><EFBFBD>Ϣ
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static rt_err_t cmd_response(U16 Cmd,U32 Arg,U16 TransMode,U16 BlkLen,U16 Nob,U16 IntMask)
|
|
|
|
|
{
|
|
|
|
|
U32 i;
|
|
|
|
|
#ifdef USE_TIMEOUT
|
|
|
|
|
U32 to = 50000;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
*(RP)SDC_CLOCK_CONTROL=0Xff00; //<2F><><EFBFBD><EFBFBD>SDʱ<44><CAB1>
|
|
|
|
|
|
|
|
|
|
*(RP)SDC_CLOCK_CONTROL=0Xff04; //<2F><><EFBFBD><EFBFBD>SDʱ<44><CAB1>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*(RP)SDC_INTERRUPT_STATUS_MASK=IntMask; //<2F>ж<EFBFBD>״̬<D7B4><CCAC><EFBFBD>μĴ<CEBC><C4B4><EFBFBD><EFBFBD><EFBFBD>ֵ
|
|
|
|
|
*(RP)SDC_TRANSFER_MODE=TransMode; //<2F><><EFBFBD><EFBFBD>ģʽѡ<CABD><D1A1><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD>ֵ
|
|
|
|
|
*(RP)SDC_BLOCK_SIZE=BlkLen; //<2F><><EFBFBD>ݿ鳤<DDBF>ȼĴ<C8BC><C4B4><EFBFBD><EFBFBD><EFBFBD>ֵ
|
|
|
|
|
*(RP)SDC_BLOCK_COUNT=Nob; //<2F><><EFBFBD>ݿ<EFBFBD><DDBF><EFBFBD>Ŀ<EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD>ֵ
|
|
|
|
|
*(RP)SDC_ARGUMENT=Arg; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD>ֵ
|
|
|
|
|
*(RP)SDC_COMMAND=Cmd; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƼĴ<C6BC><C4B4><EFBFBD><EFBFBD><EFBFBD>ֵ
|
|
|
|
|
|
|
|
|
|
delay(10);
|
|
|
|
|
|
|
|
|
|
i = *(RP)SDC_INTERRUPT_STATUS & 0x1040;
|
|
|
|
|
|
|
|
|
|
while(i != 0x1040) //<2F>жϣ<D0B6><CFA3><EFBFBD><EFBFBD><EFBFBD><EEB7A2><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD><CFA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD><D5B5><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD>ݴ<EFBFBD><DDB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϡ<EFBFBD><CFA1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7>Ѿ<EFBFBD><D1BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɡ<EFBFBD>
|
|
|
|
|
{
|
|
|
|
|
i = *(RP)SDC_INTERRUPT_STATUS & 0x1040;
|
|
|
|
|
#ifdef USE_TIMEOUT
|
|
|
|
|
to--;
|
|
|
|
|
if(!to)
|
|
|
|
|
{
|
|
|
|
|
EOUT("%s Timeout\n",__FUNCTION__);
|
|
|
|
|
return RT_ETIMEOUT;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//DBOUT("cmd_response TO is %d\n",to);
|
|
|
|
|
delay(100);
|
|
|
|
|
|
|
|
|
|
return RT_EOK; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EEB7B4><EFBFBD><EFBFBD>Ϣ
|
|
|
|
|
}
|
|
|
|
|
static rt_err_t cmd_wait(U16 Cmd,U32 Arg,U16 IntMask )
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
#ifdef USE_TIMEOUT
|
|
|
|
|
U32 to=200000;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
*(RP)SDC_CLOCK_CONTROL=0Xff00; //<2F><><EFBFBD><EFBFBD>SDʱ<44><CAB1>
|
|
|
|
|
|
|
|
|
|
*(RP)SDC_CLOCK_CONTROL=0Xff04; //<2F><><EFBFBD><EFBFBD>SDʱ<44><CAB1>
|
|
|
|
|
|
|
|
|
|
*(RP)SDC_COMMAND=Cmd; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƼĴ<C6BC><C4B4><EFBFBD><EFBFBD><EFBFBD>ֵ
|
|
|
|
|
|
|
|
|
|
*(RP)SDC_INTERRUPT_STATUS_MASK=IntMask; //<2F>ж<EFBFBD>״̬<D7B4><CCAC><EFBFBD>μĴ<CEBC><C4B4><EFBFBD><EFBFBD><EFBFBD>ֵ
|
|
|
|
|
|
|
|
|
|
*(RP)SDC_ARGUMENT=Arg; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD>ֵ
|
|
|
|
|
|
|
|
|
|
i = *(RP)SDC_INTERRUPT_STATUS & 0x1000;
|
|
|
|
|
|
|
|
|
|
while(i != 0x1000) //<2F>жϣ<D0B6><CFA3>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EEB7A2><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD><CFA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD><D5B5><EFBFBD>Ӧ
|
|
|
|
|
{
|
|
|
|
|
i = *(RP)SDC_INTERRUPT_STATUS & 0x1000;
|
|
|
|
|
#ifdef USE_TIMEOUT
|
|
|
|
|
to--;
|
|
|
|
|
if(!to)
|
|
|
|
|
{
|
|
|
|
|
EOUT("%s Timeout\n",__FUNCTION__);
|
|
|
|
|
return RT_ETIMEOUT;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//DBOUT("cmd_wait TO is %d\n",to);
|
|
|
|
|
|
|
|
|
|
delay(10);
|
|
|
|
|
|
|
|
|
|
return RT_EOK; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EEB7B4><EFBFBD><EFBFBD>Ϣ<EFBFBD>Լ<EFBFBD><D4BC><EFBFBD>ֵ1
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* This function will set a hook function, which will be invoked when a memory
|
|
|
|
|
* block is allocated from heap memory.
|
|
|
|
|
*
|
|
|
|
|
* @param hook the hook function
|
|
|
|
|
*/
|
|
|
|
|
static rt_err_t sd_init(void)
|
|
|
|
|
{
|
|
|
|
|
rt_err_t err;
|
|
|
|
|
#ifdef USE_TIMEOUT
|
|
|
|
|
rt_uint32_t to=1000;
|
|
|
|
|
#endif
|
|
|
|
|
sd_pwr(1);
|
|
|
|
|
|
|
|
|
|
*(RP)SDC_SOFTWARE_RESET=0x0; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ,<2C><><EFBFBD><EFBFBD>д0<D0B4>ǽ<EFBFBD><C7BD><EFBFBD>reset
|
|
|
|
|
delay(200);
|
|
|
|
|
*(RP)SDC_SOFTWARE_RESET=0x1; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ
|
|
|
|
|
delay(200);
|
|
|
|
|
|
|
|
|
|
cmd_wait(0x08,0x0,0xfff); //CMD0<44><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EEB7A2>ʹ<EFBFBD><CAB9>
|
|
|
|
|
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
err = cmd_wait(0x6ea,0x0,0xfff); //CMD55,<2C><><EFBFBD>л<EFBFBD><D0BB><EFBFBD>ACMD<4D><44><EFBFBD><EFBFBD>
|
|
|
|
|
|
|
|
|
|
#ifdef USE_TIMEOUT
|
|
|
|
|
if(err != RT_EOK)
|
|
|
|
|
{
|
|
|
|
|
EOUT("cmd_wait err in %s\n",__FUNCTION__);
|
|
|
|
|
return RT_ETIMEOUT;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
delay(3);
|
|
|
|
|
err = cmd_wait(0x52a,0x80ff8000,0xfff); //ACMD41<34><31><EFBFBD><EFBFBD>SD<53><44><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȴ<EFBFBD>SD<53><44><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
if(err != RT_EOK)
|
|
|
|
|
{
|
|
|
|
|
EOUT("cmd_wait err in %s\n",__FUNCTION__);
|
|
|
|
|
return RT_ETIMEOUT;
|
|
|
|
|
}
|
|
|
|
|
#ifdef USE_TIMEOUT
|
|
|
|
|
to--;
|
|
|
|
|
if(!to)
|
|
|
|
|
{
|
|
|
|
|
EOUT("%s timeout\n",__FUNCTION__);
|
|
|
|
|
return RT_ETIMEOUT;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
}while(*(RP)SDC_RESPONSE0<0X80008000);
|
|
|
|
|
|
|
|
|
|
#ifdef USE_TIMEOUT
|
|
|
|
|
//DBOUT("%s TO is %d\n",__FUNCTION__,to);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
cmd_data(0x49,0X0,0X0,0x0,0x0,0Xfff);//CMD2<44><32><EFBFBD><EFBFBD><EFBFBD><EFBFBD>CID
|
|
|
|
|
cmd_data(0x6a,0X0,0X0,0x0,0x0,0Xfff);//CMD3<44><33>ѯ<EFBFBD>ʿ<EFBFBD>Ƭ<EFBFBD><C6AC><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD><C2B5><EFBFBD><EFBFBD>ص<EFBFBD>ַ
|
|
|
|
|
RCA = *(RP)SDC_RESPONSE0;
|
|
|
|
|
cmd_data(0xea,RCA,0X0,0x0,0x0,0Xfff);//CMD7<44><37><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD>Ե<EFBFBD><D4B5><EFBFBD><EFBFBD>ز<EFBFBD><D8B2><EFBFBD>
|
|
|
|
|
|
|
|
|
|
return RT_EOK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This function will set a hook function, which will be invoked when a memory
|
|
|
|
|
* block is allocated from heap memory.
|
|
|
|
|
*
|
|
|
|
|
* @param hook the hook function
|
|
|
|
|
*/
|
|
|
|
|
static rt_err_t sd_readblock(rt_uint32_t address, rt_uint8_t* buf)
|
|
|
|
|
{
|
|
|
|
|
U32 complete,i;
|
|
|
|
|
rt_uint8_t temp;
|
|
|
|
|
rt_err_t err;
|
2015-08-09 11:34:41 +08:00
|
|
|
|
RT_UNUSED rt_uint32_t discard;
|
2013-01-08 22:40:58 +08:00
|
|
|
|
#ifdef USE_TIMEOUT
|
|
|
|
|
rt_uint32_t to = 10;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//rt_kprintf("in readblock:%x\n",address);
|
|
|
|
|
//Clear all the errors & interrups
|
|
|
|
|
*(RP)DMAC_INTINTERRCLR |= 0x1;
|
|
|
|
|
*(RP)DMAC_INTINTERRCLR &= ~0x1;
|
|
|
|
|
*(RP)DMAC_INTTCCLEAR |= 0x1;
|
|
|
|
|
*(RP)DMAC_INTTCCLEAR &= ~0x1;
|
|
|
|
|
|
|
|
|
|
/*Clear read fifo*/
|
|
|
|
|
*(RP)(SDC_INTERRUPT_STATUS_MASK) = ~(0x1<<9); //don't mask fifo empty
|
|
|
|
|
while((*(RP)SDC_INTERRUPT_STATUS)&0x200 != 0x200)
|
|
|
|
|
discard = *(RP)SDC_READ_BUFER_ACCESS;
|
|
|
|
|
|
|
|
|
|
/*DMAC2,word,size=0x80*/
|
|
|
|
|
*(RP)DMAC_C2SRCADDR = SDC_READ_BUFER_ACCESS;
|
|
|
|
|
*(RP)DMAC_C2DESTADDR = (rt_uint32_t)buf;
|
|
|
|
|
*(RP)DMAC_C2CONTROL =0x20249b;
|
|
|
|
|
*(RP)DMAC_C2CONFIGURATION = 0x38d;
|
|
|
|
|
|
|
|
|
|
err = cmd_wait(0x6ea,RCA,0xfff);
|
|
|
|
|
if(err != RT_EOK)
|
|
|
|
|
{
|
|
|
|
|
rt_set_errno(err);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = cmd_wait(0xca,0x2,0xfff);
|
|
|
|
|
if(err != RT_EOK)
|
|
|
|
|
{
|
|
|
|
|
rt_set_errno(err);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = cmd_response(0x22e,address,0X1,0x0200,0x1,0Xfff); //CMD17 4bit mode
|
|
|
|
|
if(err != RT_EOK)
|
|
|
|
|
{
|
|
|
|
|
rt_set_errno(err);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
complete = *(RP)SDC_INTERRUPT_STATUS;
|
|
|
|
|
|
|
|
|
|
/*CRC*/
|
|
|
|
|
if((complete |0xfffffffd) !=0xfffffffd)
|
|
|
|
|
{
|
|
|
|
|
rt_kprintf("CRC ERROR!!!\n");
|
|
|
|
|
complete = *(RP)SDC_INTERRUPT_STATUS;
|
|
|
|
|
}
|
|
|
|
|
while(((*(RP)( DMAC_INTTCSTATUS)) & 0x4) != 0x4 )
|
|
|
|
|
{
|
|
|
|
|
delay(10);
|
|
|
|
|
#ifdef USE_TIMEOUT
|
|
|
|
|
to--;
|
|
|
|
|
if(!to)
|
|
|
|
|
{
|
|
|
|
|
EOUT("%s TIMEOUT\n",__FUNCTION__);
|
|
|
|
|
return RT_ETIMEOUT;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
#ifdef USE_TIMEOUT
|
|
|
|
|
//DBOUT("%s timeout is %d\n",__FUNCTION__,to);
|
|
|
|
|
#endif
|
|
|
|
|
/*for the buf is big-endian we must reverse it*/
|
|
|
|
|
for(i = 0;i<0x80;i++)
|
|
|
|
|
{
|
|
|
|
|
temp = buf[0];
|
|
|
|
|
buf[0] = buf[3];
|
|
|
|
|
buf[3] = temp;
|
|
|
|
|
|
|
|
|
|
temp = buf[1];
|
|
|
|
|
buf[1] = buf[2];
|
|
|
|
|
buf[2] = temp;
|
|
|
|
|
|
|
|
|
|
buf += 4;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return RT_EOK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static rt_uint8_t sd_readmultiblock(rt_uint32_t address, rt_uint8_t* buf,rt_uint32_t size)
|
|
|
|
|
{
|
|
|
|
|
rt_int32_t index;
|
|
|
|
|
rt_uint8_t status=RT_EOK;
|
|
|
|
|
|
|
|
|
|
for(index = 0;index < size;index++)
|
|
|
|
|
{
|
|
|
|
|
status = sd_readblock(address+index*SECTOR_SIZE,buf+index*SECTOR_SIZE);
|
|
|
|
|
if(status!=RT_EOK)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This function will set a hook function, which will be invoked when a memory
|
|
|
|
|
* block is allocated from heap memory.
|
|
|
|
|
*
|
|
|
|
|
* @param hook the hook function
|
|
|
|
|
*/
|
|
|
|
|
static rt_uint8_t sd_writeblock(rt_uint32_t address, rt_uint8_t* buf)
|
|
|
|
|
{
|
|
|
|
|
U32 complete;
|
|
|
|
|
rt_uint8_t temp;
|
|
|
|
|
rt_uint8_t *ptr = buf;
|
|
|
|
|
rt_err_t err;
|
|
|
|
|
#ifdef USE_TIMEOUT
|
|
|
|
|
rt_uint32_t to = 10;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
rt_kprintf("in writeblock:%x\n",address);
|
|
|
|
|
|
|
|
|
|
/*for the buf is big-endian we must reverse it*/
|
|
|
|
|
for(i = 0;i<0x80;i++)
|
|
|
|
|
{
|
|
|
|
|
temp = ptr[0];
|
|
|
|
|
ptr[0] = ptr[3];
|
|
|
|
|
ptr[3] = temp;
|
|
|
|
|
|
|
|
|
|
temp = ptr[1];
|
|
|
|
|
ptr[1] = ptr[2];
|
|
|
|
|
ptr[2] = temp;
|
|
|
|
|
|
|
|
|
|
ptr += 4;
|
|
|
|
|
}
|
|
|
|
|
//Clear all the errors & interrups
|
|
|
|
|
*(RP)DMAC_INTINTERRCLR |= 0x1;
|
|
|
|
|
*(RP)DMAC_INTINTERRCLR &= ~0x1;
|
|
|
|
|
*(RP)DMAC_INTTCCLEAR |= 0x1;
|
|
|
|
|
*(RP)DMAC_INTTCCLEAR &= ~0x1;
|
|
|
|
|
|
|
|
|
|
//***********************<2A><><EFBFBD><EFBFBD>DMA2<41><32><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λд*************************
|
|
|
|
|
*(RP)DMAC_C2SRCADDR = (U32)buf; //DMAC<41><43>2Դ<32><D4B4>ַ<EFBFBD><D6B7>Ϊ0x30200000
|
|
|
|
|
*(RP)DMAC_C2DESTADDR = SDC_WRITE_BUFER_ACCESS; //DMAC<41><43>2Ŀ<32>ĵ<EFBFBD>ַ<EFBFBD><D6B7>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>FIFO<46>ĵ<EFBFBD>ַ
|
|
|
|
|
*(RP)DMAC_C2CONTROL = 0x20149b; //<2F><><EFBFBD><EFBFBD><EFBFBD>ߴ<EFBFBD>0x080,Դ<><D4B4>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD>Ŀ<EFBFBD>ĵ<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>ӣ<EFBFBD><D3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>32bit<69><74><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ4
|
|
|
|
|
*(RP)DMAC_C2CONFIGURATION = 0x380b; //<2F><><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><CEB4><EFBFBD><EFBFBD>жϣ<D0B6><CFA3><EFBFBD><EFBFBD>δ<EFBFBD><CEB4><EFBFBD><EFBFBD>жϣ<D0B6>ͨ<EFBFBD><CDA8>ʹ<EFBFBD>ܣ<EFBFBD><DCA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD><CDA3>洢<EFBFBD><E6B4A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
err = cmd_wait(0x6ea,RCA,0xfff); //CMD55<35><35><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><D0BB><EFBFBD>ACMD<4D><44><EFBFBD><EFBFBD>
|
|
|
|
|
if(err != RT_EOK)
|
|
|
|
|
{
|
|
|
|
|
rt_set_errno(err);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = cmd_wait(0xca,0x2,0xfff); //ACMD6<44><36><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߿<EFBFBD><DFBF>ȣ<EFBFBD>48 λ<>̷<EFBFBD><CCB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݴ<EFBFBD><DDB4><EFBFBD>
|
|
|
|
|
if(err != RT_EOK)
|
|
|
|
|
{
|
|
|
|
|
rt_set_errno(err);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = cmd_response(0x30e,address,0X3,0x0200,0x1,0Xfff); //CMD24 1bit mode
|
|
|
|
|
if(err != RT_EOK)
|
|
|
|
|
{
|
|
|
|
|
rt_set_errno(err);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
complete = *(RP)SDC_INTERRUPT_STATUS;
|
|
|
|
|
|
|
|
|
|
if((complete |0xfffffffe) !=0xfffffffe) //<2F><>Ӧ<EFBFBD><D3A6>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>
|
|
|
|
|
{
|
|
|
|
|
//printf("CRC ERROR");
|
|
|
|
|
complete = *(RP)SDC_INTERRUPT_STATUS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while(((*(RP)( DMAC_INTTCSTATUS)) & 0x4) != 0x4 )
|
|
|
|
|
{
|
|
|
|
|
delay(10);
|
|
|
|
|
#ifdef USE_TIMEOUT
|
|
|
|
|
to--;
|
|
|
|
|
if(!to)
|
|
|
|
|
{
|
|
|
|
|
EOUT("%s TIMEOUT\n",__FUNCTION__);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
#ifdef USE_TIMEOUT
|
|
|
|
|
//DBOUT("%s timeout is %d\n",__FUNCTION__,to);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return RT_EOK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This function will set a hook function, which will be invoked when a memory
|
|
|
|
|
* block is allocated from heap memory.
|
|
|
|
|
*
|
|
|
|
|
* @param hook the hook function
|
|
|
|
|
*/
|
|
|
|
|
static rt_err_t rt_sdcard_init(rt_device_t dev)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This function will set a hook function, which will be invoked when a memory
|
|
|
|
|
* block is allocated from heap memory.
|
|
|
|
|
*
|
|
|
|
|
* @param hook the hook function
|
|
|
|
|
*/
|
|
|
|
|
static rt_err_t rt_sdcard_open(rt_device_t dev, rt_uint16_t oflag)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This function will set a hook function, which will be invoked when a memory
|
|
|
|
|
* block is allocated from heap memory.
|
|
|
|
|
*
|
|
|
|
|
* @param hook the hook function
|
|
|
|
|
*/
|
|
|
|
|
static rt_err_t rt_sdcard_close(rt_device_t dev)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This function will set a hook function, which will be invoked when a memory
|
|
|
|
|
* block is allocated from heap memory.
|
|
|
|
|
*
|
|
|
|
|
* @param hook the hook function
|
|
|
|
|
*/
|
|
|
|
|
static rt_err_t rt_sdcard_control(rt_device_t dev, rt_uint8_t cmd, void *args)
|
|
|
|
|
{
|
|
|
|
|
rt_kprintf("cmd = %d\n",cmd);
|
|
|
|
|
RT_ASSERT(dev != RT_NULL);
|
|
|
|
|
|
|
|
|
|
if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME)
|
|
|
|
|
{
|
|
|
|
|
struct rt_device_blk_geometry *geometry;
|
|
|
|
|
|
|
|
|
|
geometry = (struct rt_device_blk_geometry *)args;
|
|
|
|
|
if (geometry == RT_NULL) return -RT_ERROR;
|
|
|
|
|
|
|
|
|
|
geometry->bytes_per_sector = 512;
|
|
|
|
|
geometry->block_size = 0x200000;
|
|
|
|
|
//if (CardType == SDIO_HIGH_CAPACITY_SD_CARD)
|
|
|
|
|
// geometry->sector_count = (SDCardInfo.SD_csd.DeviceSize + 1) * 1024;
|
|
|
|
|
//else
|
|
|
|
|
geometry->sector_count = 0x200000;//SDCardInfo.CardCapacity/SDCardInfo.CardBlockSize;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return RT_EOK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This function will set a hook function, which will be invoked when a memory
|
|
|
|
|
* block is allocated from heap memory.
|
|
|
|
|
*
|
|
|
|
|
* @param hook the hook function
|
|
|
|
|
*/
|
|
|
|
|
static rt_size_t rt_sdcard_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
|
|
|
|
|
{
|
|
|
|
|
rt_uint32_t retry = 3;
|
|
|
|
|
rt_uint8_t status;
|
|
|
|
|
rt_uint32_t index;
|
|
|
|
|
|
|
|
|
|
///*take the semaphore
|
|
|
|
|
struct dfs_partition *part = (struct dfs_partition *)dev->user_data;
|
|
|
|
|
rt_sem_take(part->lock, RT_WAITING_FOREVER);
|
|
|
|
|
while(retry--)
|
|
|
|
|
{
|
|
|
|
|
if (((rt_uint32_t)buffer % 4 != 0) ||
|
|
|
|
|
((rt_uint32_t)buffer > 0x20080000))
|
|
|
|
|
{
|
|
|
|
|
for(index = 0;index < size;index++)
|
|
|
|
|
{
|
|
|
|
|
status = sd_readblock((part->offset + pos) * SECTOR_SIZE,ptr_sddev->sec_buf);
|
|
|
|
|
if(status != RT_EOK)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
rt_memcpy((rt_uint8_t *)buffer + (index * SECTOR_SIZE),ptr_sddev->sec_buf,SECTOR_SIZE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for(index = 0;index<size;index++)
|
|
|
|
|
{
|
|
|
|
|
status = sd_readblock((pos) * SECTOR_SIZE,(rt_uint8_t*)buffer + index * SECTOR_SIZE);
|
|
|
|
|
if(status != RT_EOK)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
rt_sem_release(part->lock);
|
|
|
|
|
|
|
|
|
|
if (status == RT_EOK)
|
|
|
|
|
return size;
|
|
|
|
|
|
|
|
|
|
rt_kprintf("read failed: %d, buffer 0x%08x\n", status, buffer);
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This function will set a hook function, which will be invoked when a memory
|
|
|
|
|
* block is allocated from heap memory.
|
|
|
|
|
*
|
|
|
|
|
* @param hook the hook function
|
|
|
|
|
*/
|
|
|
|
|
static rt_size_t rt_sdcard_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
rt_uint8_t status;
|
|
|
|
|
|
|
|
|
|
struct dfs_partition *part = (struct dfs_partition *)dev->user_data;
|
|
|
|
|
|
|
|
|
|
if ( dev == RT_NULL )
|
|
|
|
|
{
|
|
|
|
|
rt_set_errno(-DFS_STATUS_EINVAL);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rt_sem_take(part->lock, RT_WAITING_FOREVER);
|
|
|
|
|
|
|
|
|
|
if (((rt_uint32_t)buffer % 4 != 0) ||
|
|
|
|
|
((rt_uint32_t)buffer > 0x20080000))
|
|
|
|
|
{
|
|
|
|
|
rt_uint32_t index;
|
|
|
|
|
|
|
|
|
|
for(index=0;index<size;index++)
|
|
|
|
|
{
|
|
|
|
|
rt_memcpy(ptr_sddev->sec_buf, ((rt_uint8_t*)buffer + index * SECTOR_SIZE), SECTOR_SIZE);
|
|
|
|
|
status = sd_writeblock((part->offset + index + pos)*SECTOR_SIZE,ptr_sddev->sec_buf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
for(i=0;i<size;i++)
|
|
|
|
|
{
|
|
|
|
|
status = sd_writeblock((part->offset + i + pos)*SECTOR_SIZE,
|
|
|
|
|
(rt_uint8_t*)((rt_uint8_t*)buffer + i * SECTOR_SIZE));
|
|
|
|
|
if (status != RT_EOK) break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rt_sem_release(part->lock);
|
|
|
|
|
|
|
|
|
|
if (status == RT_EOK)
|
|
|
|
|
return size;
|
|
|
|
|
|
|
|
|
|
rt_kprintf("read failed: %d, buffer 0x%08x\n", status, buffer);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rt_err_t rt_hw_sdcard_exit()
|
|
|
|
|
{
|
|
|
|
|
if(ptr_sddev->device != RT_NULL)
|
|
|
|
|
rt_free(ptr_sddev->device);
|
|
|
|
|
if(ptr_sddev->part != RT_NULL)
|
|
|
|
|
rt_free(ptr_sddev->part);
|
|
|
|
|
if(ptr_sddev != RT_NULL)
|
|
|
|
|
rt_free(ptr_sddev);
|
|
|
|
|
|
|
|
|
|
return RT_EOK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This function will init sd card
|
|
|
|
|
*
|
|
|
|
|
* @param void
|
|
|
|
|
*/
|
|
|
|
|
rt_err_t rt_hw_sdcard_init()
|
|
|
|
|
{
|
|
|
|
|
/*For test*/
|
|
|
|
|
rt_err_t err;
|
|
|
|
|
rt_int32_t i;
|
|
|
|
|
|
|
|
|
|
char dname[4];
|
|
|
|
|
char sname[8];
|
|
|
|
|
|
|
|
|
|
/*Initialize structure*/
|
|
|
|
|
|
|
|
|
|
ptr_sddev = (struct sd_device*)rt_malloc(sizeof(struct sd_device));
|
|
|
|
|
if(ptr_sddev == RT_NULL)
|
|
|
|
|
{
|
|
|
|
|
EOUT("Failed to allocate sdcard device structure\n");
|
|
|
|
|
return RT_ENOMEM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*sdcard intialize*/
|
|
|
|
|
err = sd_init();
|
|
|
|
|
if(err != RT_EOK)
|
|
|
|
|
goto FAIL2;
|
|
|
|
|
|
|
|
|
|
/*set sector buffer*/
|
|
|
|
|
ptr_sddev->sec_buf = gsec_buf;
|
|
|
|
|
ptr_sddev->buf_size = SECTOR_SIZE;
|
|
|
|
|
ptr_sddev->sdc = (struct sd_c*)SD_BASE;
|
|
|
|
|
|
|
|
|
|
//DBOUT("allocate partition sector buffer OK!");
|
|
|
|
|
|
|
|
|
|
err = sd_readblock(0,ptr_sddev->sec_buf);
|
|
|
|
|
if(err != RT_EOK)
|
|
|
|
|
{
|
|
|
|
|
EOUT("read first block error\n");
|
|
|
|
|
goto FAIL2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*sdcard driver initialize*/
|
|
|
|
|
ptr_sddev->part = (struct dfs_partition*)rt_malloc(4 * sizeof(struct dfs_partition));
|
|
|
|
|
if(ptr_sddev->part == RT_NULL)
|
|
|
|
|
{
|
|
|
|
|
EOUT("allocate partition failed\n");
|
|
|
|
|
err = RT_ENOMEM;
|
|
|
|
|
goto FAIL2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*alloc device buffer*/
|
|
|
|
|
ptr_sddev->device = (struct rt_device*)rt_malloc(4 * sizeof(struct rt_device));
|
|
|
|
|
if(ptr_sddev->device == RT_NULL)
|
|
|
|
|
{
|
|
|
|
|
EOUT("allocate device failed\n");
|
|
|
|
|
err = RT_ENOMEM;
|
|
|
|
|
goto FAIL1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ptr_sddev->part_num = 0;
|
|
|
|
|
|
|
|
|
|
err = sd_readblock(0,ptr_sddev->sec_buf);
|
|
|
|
|
|
|
|
|
|
if(err != RT_EOK)
|
|
|
|
|
{
|
|
|
|
|
EOUT("Read block 0 to initialize ERROR\n");
|
|
|
|
|
goto FAIL1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(i=0; i<4; i++)
|
|
|
|
|
{
|
|
|
|
|
/* get the first partition */
|
|
|
|
|
err = dfs_filesystem_get_partition(&(ptr_sddev->part[i]), ptr_sddev->sec_buf, i);
|
|
|
|
|
if (err == RT_EOK)
|
|
|
|
|
{
|
|
|
|
|
rt_snprintf(dname, 4, "sd%d", i);
|
|
|
|
|
rt_snprintf(sname, 8, "sem_sd%d", i);
|
|
|
|
|
ptr_sddev->part[i].lock = rt_sem_create(sname, 1, RT_IPC_FLAG_FIFO);
|
|
|
|
|
|
|
|
|
|
/* register sdcard device */
|
|
|
|
|
ptr_sddev->device[i].init = rt_sdcard_init;
|
|
|
|
|
ptr_sddev->device[i].open = rt_sdcard_open;
|
|
|
|
|
ptr_sddev->device[i].close = rt_sdcard_close;
|
|
|
|
|
ptr_sddev->device[i].read = rt_sdcard_read;
|
|
|
|
|
ptr_sddev->device[i].write = rt_sdcard_write;
|
|
|
|
|
ptr_sddev->device[i].control = rt_sdcard_control;
|
|
|
|
|
ptr_sddev->device[i].user_data= &ptr_sddev->part[i];
|
|
|
|
|
|
|
|
|
|
err = rt_device_register(&ptr_sddev->device[i], dname,
|
|
|
|
|
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
|
|
|
|
|
|
|
|
|
|
if(err == RT_EOK)
|
|
|
|
|
ptr_sddev->part_num++;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if(i == 0)
|
|
|
|
|
{
|
|
|
|
|
/* there is no partition table */
|
|
|
|
|
ptr_sddev->part[0].offset = 0;
|
|
|
|
|
ptr_sddev->part[0].size = 0;
|
|
|
|
|
ptr_sddev->part[0].lock = rt_sem_create("sem_sd0", 1, RT_IPC_FLAG_FIFO);
|
|
|
|
|
|
|
|
|
|
/* register sdcard device */
|
|
|
|
|
ptr_sddev->device[0].init = rt_sdcard_init;
|
|
|
|
|
ptr_sddev->device[0].open = rt_sdcard_open;
|
|
|
|
|
ptr_sddev->device[0].close = rt_sdcard_close;
|
|
|
|
|
ptr_sddev->device[0].read = rt_sdcard_read;
|
|
|
|
|
ptr_sddev->device[0].write = rt_sdcard_write;
|
|
|
|
|
ptr_sddev->device[0].control = rt_sdcard_control;
|
|
|
|
|
ptr_sddev->device[0].user_data= &ptr_sddev->part[0];
|
|
|
|
|
|
|
|
|
|
err = rt_device_register(&ptr_sddev->device[0], "sd0",
|
|
|
|
|
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
|
|
|
|
|
|
|
|
|
|
if(err == RT_EOK)
|
|
|
|
|
ptr_sddev->part_num++;
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(ptr_sddev->part_num == 0)
|
|
|
|
|
goto FAIL0;
|
|
|
|
|
|
|
|
|
|
return err;
|
|
|
|
|
|
|
|
|
|
FAIL0:
|
|
|
|
|
rt_free(ptr_sddev->device);
|
|
|
|
|
ptr_sddev->device = RT_NULL;
|
|
|
|
|
|
|
|
|
|
FAIL1:
|
|
|
|
|
rt_free(ptr_sddev->part);
|
|
|
|
|
ptr_sddev->part = RT_NULL;
|
|
|
|
|
|
|
|
|
|
FAIL2:
|
|
|
|
|
rt_free(ptr_sddev);
|
|
|
|
|
ptr_sddev = RT_NULL;
|
|
|
|
|
|
|
|
|
|
return err;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|