⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdd_mem.c

📁 sd卡的高速读写程序 sd卡的高速读写程序
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Copyright 2002, ESS Technology, Inc.				*/
/* SCCSID @(#)sd_mem.c	1.40 08/10/04 */

#ifdef SD_MEMORY
#include "common.h"
#include "ioport.h"
#include "mvd.h"
#include "buffer.h"
#include "custmem.h"
#include "memmap.h"
#include "smfont.h"
#include "util.h"
#include "constvar.h"
#include "sd_mem.h"
#include "sysinfo.h"
#include "mem_dev.h"
#include "debug.h"


/*------------------------------------------------------------------------
 * Debugging macros
 *------------------------------------------------------------------------*/
#define CPRINTF(a) 
#define PRINTF(a) 
#define JPRINTF(a) 

#define SD_ENABLE_WRITE

#if 0
int bpt;
#define BREAKPOINT(x) {bpt=x;while(bpt) VCX_service();}
#else
#define BREAKPOINT(x)
#endif

/*------------------------------------------------------------------------
 * macros
 *------------------------------------------------------------------------*/
#define	USEC(x)			(cpuclk*x/10)
#define get_bigend32(pcbuf, off) ((uchar)pcbuf[off]|((uchar)pcbuf[off+1] << 8)| \
				( (uchar)pcbuf[off+2] << 16)|((uchar)pcbuf[off+3] <<24))


/*------------------------------------------------------------------------
 * Public variables
 *------------------------------------------------------------------------*/
SD_CINFO SD_card_info;
SD_XMIT_STATUS SD_xmit_info;


/*------------------------------------------------------------------------
 * Private variables
 *------------------------------------------------------------------------*/
static SD_CARD_STATUS *SD_card_status_ptr; /* R1 reply */
static SD_STATUS *SD_status_ptr;
static SD_OCR *SD_ocr_reg_ptr;
static SD_CID *SD_cid_reg_ptr;
static SD_CSD *SD_csd_reg_ptr;
static ushort SD_rca_reg; /* rel card address..ID for multi cards */
static SD_SCR *SD_scr_reg_ptr;
static uint SD_rdata32;
static int sd_is_mmc;
static int sd_io_status = 0;

static SD_CMD_Q SD_acmdq; /* SD command queue or appcmd */
static unsigned short sd_crc16_look_up_table[256];
static uchar  sd_crc7_look_up_table[256];

static int sdTotalBlockNo, sdPagePerBlock, sdEraseSecSize;

/* NOTE: move LUT's to rom later */
/* LUT for commands with responses: R1, R1b, R2, R3, R6 */
uchar SD_cmd2resp[64] = {
    /* CMD0 - CMD7 */
    SD_NR, SD_R3, SD_R2, SD_R6, SD_NR, SD_NR, SD_NR, SD_R1b,
    /* CMD8 - CMD15 */
    SD_NR, SD_R2, SD_R2, SD_R1_RD, SD_R1b,SD_R1, SD_NR, SD_NR,
    /* CMD16 - CMD23 */
    SD_R1, SD_R1_RD, SD_R1_RD, SD_NR, SD_NR, SD_NR, SD_NR, SD_R1,
    /* CMD24 - CMD31 */
    SD_R1_WR, SD_R1_WR, SD_NR, SD_R1, SD_R1b,SD_R1b,SD_R1, SD_NR,
    /* CMD32 - CMD39 */
    SD_R1, SD_R1, SD_NR, SD_NR, SD_NR, SD_NR, SD_R1b,SD_NR,
    /* CMD40 - CMD47 */
    SD_NR, SD_NR, SD_R1, SD_NR, SD_NR, SD_NR, SD_NR, SD_NR,
    /* CMD48 - CMD55 */
    SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_R1,
    /* CMD56 - CMD63 */
    SD_R1, SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_NR
};

/* LUT for app. commands with responses: R1, R1b, R2, R3, R6 */
uchar SD_acmd2resp[52] = {
    /* ACMD0 - ACMD7 */
    SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_R1, SD_NR,
    /* ACMD8 - ACMD15 */
    SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_R1_RD, SD_NR, SD_NR,
    /* ACMD16 - ACMD23 */
    SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_R1, SD_R1,
    /* ACMD24 - ACMD31 */
    SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_NR,
    /* ACMD32 - ACMD8 */
    SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_NR,
    /* ACMD40 - ACMD47 */
    SD_NR, SD_R3, SD_R1, SD_NR, SD_NR, SD_NR, SD_NR, SD_NR,
    /* ACMD48 - ACMD51 */
    SD_NR, SD_NR, SD_NR, SD_R1_RD
};

/* LUT for SD command classes */
uchar SD_cmd2class[64] = {
    /* CMD0 - CMD7 */
    SD_CL0,SD_CL0,SD_CL0,SD_CL0,SD_CL0,SD_CL0,SD_CL0,SD_CL0,
    /* CMD8 - CMD15 */
    SD_CL0,SD_CL0,SD_CL0,SD_CL1,SD_CL0,SD_CL0,SD_CL0,SD_CL0,
    /* CMD16 - CMD23 */
    SD_CL2,SD_CL2,SD_CL2,SD_CL2,SD_CL2,SD_CL2,SD_CL2,SD_CL2,
    /* CMD24 - CMD31 */
    SD_CL4,SD_CL4,SD_CL4,SD_CL4,SD_CL6,SD_CL6,SD_CL6,SD_CL6,
    /* CMD32 - CMD39 */
    SD_CL5,SD_CL5,SD_CL5,SD_CL5,SD_CL5,SD_CL5,SD_CL5,SD_CL5,
    /* CMD40 - CMD47 */
    SD_CL5,SD_CL5,SD_CL7,SD_CL7,SD_CL7,SD_CL7,SD_CL7,SD_CL7,
    /* CMD48 - CMD55 */
    SD_CL7,SD_CL7,SD_CL7,SD_CL7,SD_CL7,SD_CL7,SD_CL7,SD_CL8,
    /* CMD56 - CMD63 */
    SD_CL8,SD_CL8,SD_CL8,SD_CL8,SD_CL8,SD_CL8,SD_CL8,SD_CL8,
};

/* LUT for CSD's TAAC time value */
uchar SD_taac_valx10[16] = {
    00, 10, 12, 13, 15, 20, 25, 30,
    35, 40, 45, 50, 55, 60, 70, 80
};

#ifdef BANK2SPEEDUP
static unsigned old_wait_state;
#endif

/*------------------------------------------------------------------------
 * Private functions
 *------------------------------------------------------------------------*/
static int SD_set_cmd(int, uint);
static void SD_update_card_info(void);
static ushort SD_calc_crc16(uchar *, ushort);
static void SD_calc_crc16_table(ushort *);
static uchar SD_calc_crc7(uchar *, ushort);
static void SD_calc_crc7_table(uchar *);
static int  SD_write_blk(int, int, int, int *, int);

/*------------------------------------------------------------------------
 * Begin SD function listing
 *------------------------------------------------------------------------*/

/* 
  Function: Get partition boot record (PBR) address from master
	    boot record area.

  input:

  output: PBR start address as physical lba (physical sector number).

  side-effects:
*/
unsigned int SD_boot_setup(void)
{
   uchar *buff;
   uint PBR_start_psn;

   
   SD_enable_io(1); /* enable SD eaux pins */

   buff = (uchar *)dram_cached(SD_DATA_START);
   SD_read_sector_lba((short *)buff, 0, 1, 1); /* 512B per block */
   if (((buff[0x0] == 0xEB) && (buff[0x2] == 0x90))
         || (buff[0x0] == 0xE9)) {
        PBR_start_psn = 0;
   }else
       PBR_start_psn = get_bigend32(buff, 454);

   return(PBR_start_psn);
}
/*********************************************************************
    return:
          1: MMC
          0: SD or else
**********************************************************************/
int SD_is_mmc(void){
    if(SD_card_info.type == SD_MMC)
	return 1;
    else
	return 0;    
}
/* 
  Function: Reads from specified lba to designated buffer.

  input:
	buff: pointer for SD data destination.
	lba: physical logical block address.
	nblk: number of blocks to read.

  output: number of bytes read.

  side-effects:
*/
int SD_read_sector_lba(short *buff, int lba, int nblk, int immed)
{
    int i, start_lba = lba;
    short *pDest = buff;

    set_bank2_wait ();

    if (nblk == 1) {
	SD_read_blk(lba<<9, 9, (unsigned int *)buff, immed);
    } else {
	PRINTF(("SD_multi_block read: %d-->%x : nblk %d \n",
		 lba, buff, nblk));
	if(SD_card_info.type == SD_MMC){
	    for(i= 0; i<nblk; i++){
		SD_read_blk(start_lba<<9, 9, (unsigned int *)pDest, immed);
		pDest += 0x100;
		start_lba++;
	    }
	}else
	    SD_read_nblk(lba<<9, nblk, (unsigned int *)buff, immed);
    }

    restore_bank2_wait ();

    return (nblk*512);
}

static int SD_find_free_block(int start_blk)
{
    int blk_no = start_blk, i, lba, cluster, pcluster;
    while(blk_no++<sdTotalBlockNo){
	pcluster = 0;
	for(i=0; i<sdPagePerBlock; i++){
	    lba = blk_no*sdPagePerBlock +i;
	    cluster = HD_lba_to_cluster(lba);
	    if(cluster == -1) continue;
	    if(cluster == pcluster)
		continue;
	    
	    pcluster = cluster;
	    if(!HD_cluster_is_free(cluster))
		break;
	}
	if(i<sdPagePerBlock)
	    continue;
	else{
	    JPRINTF(("found a free block: %d\n", blk_no));
	    return blk_no;
	}
    }
    return -1;
}

static int SD_erase_block(int start_lba, int nblk)
{
    int status, end_lba;
    end_lba = start_lba+nblk-1;
    status = SD_send_cmd(SD_CMD_ERASE_WR_BLK_START, start_lba<<9,1);
    if(status != 1)
	return -1;
    status = SD_send_cmd(SD_CMD_ERASE_WR_BLK_END, end_lba<<9,1);
    if(status != 1)
	return -1;
    status = SD_send_cmd(SD_CMD_ERASE, 0, 1);
    if(status != 1)
	return -1;
    else if(SD_xmit_info.result == 0)
	return 0;
    else{
	JPRINTF(("card status %x\n", *(int*)SD_card_status_ptr));
	return -1;
    }
}
int SD_write_sector_lba(short *buff, int lba, int nblk, int immed)
{
    int start_lba= lba,i, status;
    short *pSrc= buff;
    int free_blk;

#ifndef SD_ENABLE_WRITE
    return -1;
#endif
   
    if(SD_card_info.type == SD_MMC){
	for(i=0; i<nblk; i++){
	    status = SD_write_blk(start_lba<<9, 9, 1, (int *)pSrc, 1);
	    if(status){
		JPRINTF(("MMC writing error ...\n"));
		assert(0);
		return 0;
	    } 
	    pSrc += 0x100;
	    start_lba++;
	}
    }else{
	status = SD_write_blk(start_lba<<9, 9, nblk, (int *)pSrc, immed);
	if(status) 
	    return 0;
	if(nblk>1 && immed)
	    status = SD_send_cmd(SD_CMD_STOP_TRANSMIT, 0, 1); 
    }

    JPRINTF(("SD_write_sector_lba: data_cnt%d nblk %d, status %x\n",
	     SD_xmit_info.data_cnt, nblk, status));
    return (512*nblk);
}


/* 
  Function: The faster CRC16 calculation procedure 
	uses 256 x 16-bit Look Up Table (8bit at a time)..
	more efficient than generating CRC 1bit at a time.
	(adapted from memstick.c version)

  input: 
	data: pointer to data to be protected by CRC.
	count: total bytes of data.

  output: CRC16

  side-effects:
*/
static ushort SD_calc_crc16(uchar *data, ushort count)
{
    ushort fcs = 0x0; /* initial FCS value */
    ushort i, t, tl, th;
    for (i=0; i<count; i++)
    {
        t = fcs;
        fcs = sd_crc16_look_up_table[(t>>8) ^ *data++];
        fcs = fcs ^ (t<<8);
    }
    return(fcs);
}
/* in case of 4-bit mode */
static ushort SD_calc_crc16_4_bit(int *data, ushort count, ushort *crc)
{
    ushort fcs0 = 0x0, fcs1=0, fcs2=0, fcs3=0; /* initial FCS value */
    ushort i, j ;
    int tmp, *pInt;
    uint filter;
    ushort d0,d1,d2,d3;
    ushort tt0,tt1,tt2,tt3;

    pInt = data;
    for (i=0; i<count; i++)
    {
        PRINTF(("data is %x\n", *pInt));
        tmp = *pInt++;
        d3  = ((tmp & 0x80000000) >> 24); /* 0 */
        d3 |= ((tmp & 0x08000000) >> 21); /* 1 */
        d3 |= ((tmp & 0x00800000) >> 18); /* 2 */
        d3 |= ((tmp & 0x00080000) >> 15); /* 3 */
        d3 |= ((tmp & 0x00008000) >> 12); /* 4 */
        d3 |= ((tmp & 0x00000800) >>  9); /* 5 */
        d3 |= ((tmp & 0x00000080) >>  6); /* 6 */
        d3 |= ((tmp & 0x00000008) >>  3);       /* 7 */
        d2  = ((tmp & 0x40000000) >> 23); /* 0 */
        d2 |= ((tmp & 0x04000000) >> 20); /* 1 */
        d2 |= ((tmp & 0x00400000) >> 17); /* 2 */
        d2 |= ((tmp & 0x00040000) >> 14); /* 3 */
        d2 |= ((tmp & 0x00004000) >> 11); /* 4 */
        d2 |= ((tmp & 0x00000400) >>  8); /* 5 */
        d2 |= ((tmp & 0x00000040) >>  5); /* 6 */
        d2 |= ((tmp & 0x00000004) >>  2); /* 7 */
        d1  = ((tmp & 0x20000000) >> 22); /* 0 */
        d1 |= ((tmp & 0x02000000) >> 19); /* 1 */
        d1 |= ((tmp & 0x00200000) >> 16); /* 2 */
        d1 |= ((tmp & 0x00020000) >> 13); /* 3 */
        d1 |= ((tmp & 0x00002000) >> 10); /* 4 */
        d1 |= ((tmp & 0x00000200) >>  7); /* 5 */
        d1 |= ((tmp & 0x00000020) >>  4); /* 6 */
        d1 |= ((tmp & 0x00000002) >>  1); /* 7 */
        d0  = ((tmp & 0x10000000) >> 21); /* 0 */
        d0 |= ((tmp & 0x01000000) >> 18); /* 1 */
        d0 |= ((tmp & 0x00100000) >> 15); /* 2 */
        d0 |= ((tmp & 0x00010000) >> 12); /* 3 */
        d0 |= ((tmp & 0x00001000) >>  9); /* 4 */
        d0 |= ((tmp & 0x00000100) >>  6); /* 5 */
        d0 |= ((tmp & 0x00000010) >>  3); /* 6 */
        d0 |= ((tmp & 0x00000001) );      /* 7 */

//        PRINTF(("wanted : %x tmp %x, filter %x\n",
//                 data_wanted, tmp, filter));
        tt0 = fcs0;
        tt1 = fcs1;
        tt2 = fcs2;
        tt3 = fcs3;
        fcs0 = sd_crc16_look_up_table[(tt0>>8) ^ d0];
        fcs1 = sd_crc16_look_up_table[(tt1>>8) ^ d1];
        fcs2 = sd_crc16_look_up_table[(tt2>>8) ^ d2];
        fcs3 = sd_crc16_look_up_table[(tt3>>8) ^ d3];
        fcs0 = fcs0 ^ (tt0<<8);
        fcs1 = fcs1 ^ (tt1<<8);
        fcs2 = fcs2 ^ (tt2<<8);
        fcs3 = fcs3 ^ (tt3<<8);

    }
    crc[0] = fcs0;
    crc[1] = fcs1;
    crc[2] = fcs2;
    crc[3] = fcs3;
    return(0);
}
static uchar SD_calc_crc7(uchar *data, ushort count)
{
    uchar fcs = 0x0; /* initial FCS value */
    ushort i;
    uchar  g = 0x9;
    uchar t;

    for (i=0; i<count; i++)
    {
        t = sd_crc7_look_up_table[fcs];
	t <<= 1;
	if(t&0x80) 
	    fcs = (t&0x7f)^g;
	else
	    fcs = t;
        t = sd_crc7_look_up_table[*data++];
	fcs ^= t;
    }
    return(fcs);
}
/*********************************************************** 
  Function: Generate look up table for CRC16 calculation. 
            G(x): x16+x12+x5+1
***********************************************************/

static void SD_calc_crc16_table(ushort *table)
{
	int d, i, k;
	ushort g = 0x1021; /* x16+ x12 +x5+1 */

	for (i=0; i<256; i++)
	{
		d = i<<8;
		for (k=0; k<8; k++)
		{
			d <<= 1;
			if(d&0x10000)
				d ^= g;
		}
		table[i] = d&0xffff;
	}
}
/*********************************************************** 
  Function: Generate look up table for CRC7 calculation. 
            G(x): x7+x3+1
***********************************************************/
static void SD_calc_crc7_table(uchar *table)
{
    int i, k, d;
    uchar g = 0x9; /* x7+ x3 +1 */
    
    PRINTF(("SD_fcs_table_calc_crc7 ...\n"));
    for (i=0; i<256; i++){
        d = i;
        for (k=0; k<7; k++){
	    if(d&0x80)
		d ^= g;
	    d <<= 1;
        }
        if(d&0x80)
	    d ^= g;
        table[i] = d&0x7f;
    }    
}


/* 
  Function: Update SD_card_info from SD_csd_register..
	    calculate some card information.
	    (ref. pp.63-71..SD Physical Layer)

  input: (none..but assumes CSD register is updated)

  side-effects:		      
	SD_card_info members are updated:
		1. card's read access time (n_ac_max)  
		2. card's write access time (n_wr_max)
		3. card's memory capacity.
*/
static void SD_update_card_info(void)
{
    int cnt, mmc_ac, sd_ac;
    uint data;
    int nwrmax;
    

    /* calculate access times */
    /* data = taac = ((value*CPUCLK)/4) * 10^cnt */
    data = cpuclk*SD_taac_valx10[SD_csd_reg_ptr->taac_value];
    data >>= 2; /* WS = 4 */
    cnt = SD_csd_reg_ptr->taac_unit - 5; /* n power of 10 */
    if (cnt < 0) {
	do {
	    data /= 10;
	    cnt++;
	} while (cnt);
    } else {
	while (cnt) {
	    data *= 10;
	    cnt--;
	};
    }
    /* read access time */
    SD_card_info.n_ac_max = SD_NAC_MIN + data +
	(100 * SD_csd_reg_ptr->nsac); 
    mmc_ac = 10*(data+100*SD_csd_reg_ptr->nsac);
    if(sd_is_mmc)
	SD_card_info.n_ac_max  = mmc_ac;
    JPRINTF(("n_ac_max: sd: %d, mmc %d \n",
	     SD_card_info.n_ac_max, mmc_ac));

    /* write access time */
    nwrmax = (SD_card_info.n_ac_max)<<(SD_csd_reg_ptr->r2w_factor);
    /*prevent short var n_wr_max overflow*/
    if (nwrmax > 0xffff) nwrmax = 0xffff;
    SD_card_info.n_wr_max = nwrmax;

    /* calculate card capacity = BLOCKNR * BLOCK_LEN */
    data = ((SD_csd_reg_ptr->c_size_11_2<<2) |
	SD_csd_reg_ptr->c_size_1_0) + 1;
    cnt = 1 << (SD_csd_reg_ptr->c_size_mult + 2);
    data = data * cnt; /* BLOCKNR */
    sdTotalBlockNo = data;
    cnt = 1 << (SD_csd_reg_ptr->rd_blk_len); /* BLOCK_LEN */
    sdPagePerBlock = cnt/512;
    sdEraseSecSize = SD_csd_reg_ptr->sector_size+1;
    SD_card_info.capacity = data * cnt; /* in Bytes */
}


/* 
  Function: Initialize SD related buffers, structure members and
	    and IO pins.

  input:

  output:		      

  side-effects:
*/
void SD_init(void)
{
    unsigned sclk_high, sclk_low;



dawei(("SD_init()\n"));
    SD_GET_SCLK_VAL(sclk_high, sclk_low);

    /* initialization */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -