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

📄 sdmmcboot.c

📁 PXA270 下用SD卡启动的代码,已在wince5.0的mainstoneii下测试通过
💻 C
📖 第 1 页 / 共 2 页
字号:
//
//
#include <windows.h>
#include <nkintr.h>
#include <bulverde.h>
#include <mainstoneii.h>
#include <oal_memory.h>
#include <pcireg.h>
#include <fmd.h>
#include <xllp_pccardsocket.h>
#include <bsp.h>
#include "loader.h"
#include "sd.h"
#include "fatsys.h"

#define   MSC_PASSED   1
#define   MSC_FAILED   0

#define   Log  EdbgOutputDebugString


//#define   USE_DMA_CHANNEL   2

#define   MAX_READ_BLOCK     0x800      // 1M size  Must < 16M since DMA
#define   MAX_SEC_PER_CLUS   0x8
#define   NK_FILENAME   "nk"
#define   NK_EXTNAME    "nb0"


unsigned int ReadDataBuf[0x80 * MAX_SEC_PER_CLUS], ReadFatBuf[0x80 * MAX_SEC_PER_CLUS];
unsigned int PartInfoBuf[0x100];

volatile BULVERDE_MMC_REG *pSDMMCRegisters;
volatile BULVERDE_CLKMGR_REG *pClkMgrRegisters;
volatile BULVERDE_GPIO_REG *pGPIORegisters;

void dump_sector (unsigned int *);
int send_command_to_cards (unsigned char cmd, unsigned int arg, unsigned int cmdat, 
						   unsigned int nob, unsigned wait, unsigned int slow);
unsigned int CardAddr, read_file = 0, datwidth = 0;
struct BootSec  *pBootSec;
struct PartInfo bootPartInfo;
struct FileInfo imagefile;

unsigned char nk_name[9] = NK_FILENAME;
unsigned char nk_ext[4]  = NK_EXTNAME;

void WRITE_MMC_REGISTER_DWORD(volatile BULVERDE_MMC_REG *pSDMMCRegisters, DWORD RegOffset, DWORD Value) 
{
    BYTE *pRegBaseAddr, *regAddr;
    volatile DWORD *pdwRegAddr;
    pRegBaseAddr = (BYTE*)pSDMMCRegisters;
    regAddr = pRegBaseAddr + RegOffset;
    pdwRegAddr = (DWORD*)regAddr;
    *pdwRegAddr = Value;
}

DWORD READ_MMC_REGISTER_DWORD(volatile BULVERDE_MMC_REG *pSDMMCRegisters, DWORD RegOffset)
{
    BYTE *pRegBaseAddr, *regAddr;
    volatile DWORD *pdwRegAddr;
    pRegBaseAddr = (BYTE*)pSDMMCRegisters;
    regAddr = pRegBaseAddr + RegOffset;
    pdwRegAddr = (DWORD*)regAddr;
    return (*pdwRegAddr);
}


int send_command_to_cards (unsigned char cmd, unsigned int arg, unsigned int cmdat,
						   unsigned int nob, unsigned wait, unsigned int slow)
{
   volatile DWORD    mmc_stat;

   //stop the clock
   mmc_stat = READ_MMC_REGISTER_DWORD( pSDMMCRegisters, MMC_STAT );
   if (mmc_stat & MMC_STAT_CLOCK_ENABLED)
   {
     WRITE_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_STRPCL, MMC_STRPCL_STOP_CLOCK);
	 do {
	   mmc_stat = READ_MMC_REGISTER_DWORD( pSDMMCRegisters, MMC_STAT );
	 } while (mmc_stat & MMC_STAT_CLOCK_ENABLED);
	}

   if (slow)
     WRITE_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_CLKRT, 0x6);
   else
	 WRITE_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_CLKRT, 0x1);
	 
   if (datwidth)
   {
	 cmdat |= MMC_CMDAT_SD_4DAT;
	 //Log (" ***************** buswidth is 0x%x **********\n", datwidth);
   }

   WRITE_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_CMDAT, cmdat);
   WRITE_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_RESTO, 0x7f);
   WRITE_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_RDTO, 0xffff);

   if (cmd == 17 || cmd == 18)
     WRITE_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_BLKLEN, 0x200);
   else
	 WRITE_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_BLKLEN, 0);

   WRITE_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_NOB, nob);

   WRITE_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_IMASK, 0x1fff);

   WRITE_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_CMD, cmd);
   WRITE_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_ARGH, (arg >> 16));
   WRITE_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_ARGL, (arg & 0xffff));
 
   // clock is on
   mmc_stat = READ_MMC_REGISTER_DWORD( pSDMMCRegisters, MMC_STAT ); // & MMC_STAT_CLOCK_ENABLED

   if (! (mmc_stat & MMC_STAT_CLOCK_ENABLED))
   {
	 WRITE_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_STRPCL, MMC_STRPCL_START_CLOCK);
	 do {
	   mmc_stat = READ_MMC_REGISTER_DWORD( pSDMMCRegisters, MMC_STAT );
	 } while (! (mmc_stat & MMC_STAT_CLOCK_ENABLED));
	}

   if (wait)
   {
	// get respond complete
	do {
	  mmc_stat = READ_MMC_REGISTER_DWORD( pSDMMCRegisters, MMC_STAT );
	} while (! (mmc_stat & MMC_STAT_END_CMD_RES));

    if ((mmc_stat & 0x3f) != 0)
	{
	  Log ("!! Error !!: mmc_status is 0x%x\n", mmc_stat);
	  return MSC_FAILED;
	}
   }

   return MSC_PASSED;
}

int getrespondR1 (int dump)
{
  unsigned int respbuf[0x10], i, status;
  unsigned char *bufp;
  unsigned short val16;
  volatile DWORD    mmc_stat;

  mmc_stat = READ_MMC_REGISTER_DWORD( pSDMMCRegisters, MMC_STAT );
  if ((mmc_stat & 0x3f) != 0)
  {
	Log ("!! Error !!: status is 0x%x\n", mmc_stat);
	return MSC_FAILED;
  }

  // get respond with R1
  bufp = (unsigned char *)respbuf;
  for (i = 0; i < 3; i++)
  {
	val16 = (USHORT)(READ_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_RES));
	*bufp++ = (val16 >> 8) & 0xff;
	*bufp++ = val16 & 0xff;
  }

  bufp = (unsigned char *)respbuf;
  status = (bufp[1] << 24) | (bufp[2] << 16) | (bufp[3] << 8) | (bufp[4] << 0);

  imagefile.SDcardState = (status >> 8) & 0x0F;

  if (dump)
  {
	Log ("Get response <R1> (0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
		 bufp[0], bufp[1], bufp[2], bufp[3], bufp[4], bufp[5]);
  }
  else
  if ((status & 0xFFFFF000) != 0)
  {
	   Log ("!! Error !!: response <R1> (0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
	        bufp[0], bufp[1], bufp[2], bufp[3], bufp[4], bufp[5]);
	   return MSC_FAILED;
  }

  return MSC_PASSED;
}


int checkSDcard (void)
{
  unsigned int respbuf[0x30];
  unsigned char *bufp;
  volatile unsigned int i;
  unsigned short val16;
/**********************************************************************************/
  DWORD dwRegVal;
  volatile DWORD  mmc_stat;

  datwidth = 0;

  pGPIORegisters = (volatile BULVERDE_GPIO_REG *) OALPAtoVA(BULVERDE_BASE_REG_PA_GPIO, FALSE);
  pClkMgrRegisters = (volatile BULVERDE_CLKMGR_REG *) OALPAtoVA(BULVERDE_BASE_REG_PA_CLKMGR, FALSE);
  pSDMMCRegisters = (volatile BULVERDE_MMC_REG *) OALPAtoVA (BULVERDE_BASE_REG_PA_MMC, FALSE);

  //////////////////////////////////////////////////////////
  // Configure GPIO_32 as Alternate Function 2 out (MMC_CLK)

    // assume that the MMC_CLK is active-low signal driven
    dwRegVal = pGPIORegisters->GPCR1;
    dwRegVal |= 0x00000001;
    pGPIORegisters->GPCR1 = dwRegVal;
    // change the direction to OUT
    dwRegVal = pGPIORegisters->GPDR1;
    dwRegVal |= 0x00000001;
    pGPIORegisters->GPDR1 = dwRegVal;
    // change to Alternate Function 2
    dwRegVal = pGPIORegisters->GAFR1_L;
    dwRegVal = ( dwRegVal & 0xfffffffc ) | 0x00000002;
    pGPIORegisters->GAFR1_L = dwRegVal;
    
    //////////////////////////////////////////////////////////
    // Configure GPIO_112 as Alternate Function 1 (MMC_CMD)

    // assume that the MMC_CLK is active-high signal driven
    dwRegVal = pGPIORegisters->GPSR3;
    dwRegVal |= 0x00010000;
    pGPIORegisters->GPSR3 = dwRegVal;
    // change the direction to OUT
    dwRegVal = pGPIORegisters->GPDR3;
    dwRegVal |= 0x00010000;
    pGPIORegisters->GPDR3 = dwRegVal;
    // change to Alternate Function 1
    dwRegVal = pGPIORegisters->GAFR3_U;
    dwRegVal = ( dwRegVal & 0xfffffffc ) | 0x00000001;
    pGPIORegisters->GAFR3_U = dwRegVal;
    
    //////////////////////////////////////////////////////////
    // Configure GPIO_92 as Alternate Function 1 (MMC_DAT0)
    
    // assume that the MMC_CLK is active-high signal driven
    dwRegVal = pGPIORegisters->GPSR2;
    dwRegVal |= 0x10000000;
    pGPIORegisters->GPSR2 = dwRegVal;
    // change the direction to OUT
    dwRegVal = pGPIORegisters->GPDR2;
    dwRegVal |= 0x10000000;
    pGPIORegisters->GPDR2 = dwRegVal;
    // change to Alternate Function 1
    dwRegVal = pGPIORegisters->GAFR2_U;
    dwRegVal = ( dwRegVal & 0xfcffffff ) | 0x01000000;
    pGPIORegisters->GAFR2_U = dwRegVal;
    
    //////////////////////////////////////////////////////////
    // Configure GPIO_109-GPIO_111 as Alternate Function 1 (MMC_DAT1-MMC_DAT3)

    // assume that the MMC_CLK is active-high signal driven
    dwRegVal = pGPIORegisters->GPSR3;
    dwRegVal |= 0x0000e000;
    pGPIORegisters->GPSR3 = dwRegVal;
    // change the direction to OUT
    dwRegVal = pGPIORegisters->GPDR3;
    dwRegVal |= 0x0000e000;
    pGPIORegisters->GPDR3 = dwRegVal;
    // change to Alternate Function 1
    dwRegVal = pGPIORegisters->GAFR3_L;
    dwRegVal = ( dwRegVal & 0x03ffffff ) | 0x54000000;
    pGPIORegisters->GAFR3_L = dwRegVal;


	// enable the MMC Unit Clock
    dwRegVal = pClkMgrRegisters->cken;
    dwRegVal |= (1 << 12);
    pClkMgrRegisters->cken = dwRegVal;

	//EdbgOutputDebugString("Address init complete\r\n");

	// Reset SD/MMC card (CMD0) (state 0: idle)
    Log ("Send command 0 to card (Reset SD/MMC).\n");
			
	if (send_command_to_cards (0, 0, (MMC_CMDAT_INIT | MMC_CMDAT_RESPONSE_NONE), 0, 0, 1) 
		!= MSC_PASSED)
	  return MSC_FAILED;

	// get respond complete
	do {
	  mmc_stat = READ_MMC_REGISTER_DWORD( pSDMMCRegisters, MMC_STAT );
	} while (! (mmc_stat & MMC_STAT_END_CMD_RES));

  // send ACMD41 (SD_SEND_OP_COND)  (01: redy)   ****************
  Log ("Send ACMD41 to card (Reset SD/MMC).\n");
  Log ("MMC stat is 0x%x\n", mmc_stat);

  while (1)
  {
	// send cmd55 with R1
	// send cmd55 with R1
	if (send_command_to_cards (55, 0, MMC_CMDAT_RESPONSE_R1, 0, 1, 1) != MSC_PASSED)
	  return MSC_FAILED;

	if (getrespondR1 (1) != MSC_PASSED)
	  return MSC_FAILED;

	// send acmd41 (SD_SEND_OP_COND) with R3
	if (send_command_to_cards (41, 0x00ff8000, MMC_CMDAT_RESPONSE_R3, 0, 1, 1) != MSC_PASSED)
	  return MSC_FAILED;

	// get respond with R3
	bufp = (unsigned char *)respbuf;
	for (i = 0; i < 3; i++)
	{
	  val16 = (USHORT)(READ_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_RES));
	  *bufp++ = (val16 >> 8) & 0xff;
	  *bufp++ = val16 & 0xff;
	}

	bufp = (unsigned char *)respbuf;
	if (bufp[1] & 0x80)
	  break;
  }

  Log ("SD card is reay for operation.\n");

  return MSC_PASSED;
}

int initSDcard (void)
{
  unsigned int respbuf[0x30];
  unsigned char *bufp;
  volatile unsigned int i;
  unsigned short val16;

// send CMD2 (ALL_SEND_CID) with R2  (02: ident)   ******************
  Log ("Begin send CMD2 (ALL_SEND_CID) to card.\n");
  if (send_command_to_cards (2, 0,MMC_CMDAT_RESPONSE_R2, 0, 1, 1) != MSC_PASSED)
	return MSC_FAILED;

  // get respond with R2
  bufp = (unsigned char *)respbuf;
  for (i = 0; i < 9; i++)
  {
	val16 = (USHORT)(READ_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_RES));
	*bufp++ = (val16 >> 8) & 0xff;
	*bufp++ = val16 & 0xff;
  }

// send CMD3 (SEND_RELATIVE_ADDR) with R6  (03: stdby)   ******************
  Log ("Begin send CMD3 (SEND_RELATIVE_ADDR) to card.\n");
  if (send_command_to_cards (3, 0, MMC_CMDAT_RESPONSE_R1/*CMDAT_RESP_R6*/, 0, 1, 1) != MSC_PASSED)
	return MSC_FAILED;

  // get respond with R6
  bufp = (unsigned char *)respbuf;
  for (i = 0; i < 3; i++)
  {
	val16 = (USHORT)(READ_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_RES));
	*bufp++ = (val16 >> 8) & 0xff;
	*bufp++ = val16 & 0xff;
  }

  bufp = (unsigned char *)respbuf;
  CardAddr = (bufp[1] << 8) | bufp[2];

// send CMD13 (SEND_STATUS) with R1  (03: stdby)   ******************
  Log ("Begin send CMD13 (SEND_STATUS) to card.\n");
  if (send_command_to_cards (13, CardAddr << 16, MMC_CMDAT_RESPONSE_R1, 0, 1, 1)
	   != MSC_PASSED)
	return MSC_FAILED;

  if (getrespondR1 (0) != MSC_PASSED)
	return MSC_FAILED;

// send CMD7 (Select/deselect_card) with R1  (04: trans)   ******************
  Log ("Begin send CMD7 (Select/deselect_card) to card.\n");

  if (send_command_to_cards (7, CardAddr << 16, 
	                          (MMC_CMDAT_EXPECT_BUSY | MMC_CMDAT_RESPONSE_R1), 0, 1, 0)
	   != MSC_PASSED)
	return MSC_FAILED;

  // get respond with R6
  bufp = (unsigned char *)respbuf;
  for (i = 0; i < 3; i++)
  {
	val16 = (USHORT)(READ_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_RES));
	*bufp++ = (val16 >> 8) & 0xff;
	*bufp++ = val16 & 0xff;
  }

/* Set busWidth as 4. */
  Log ("Begin send ACMD6 (SET_BUS_WIDTH) to card.\n");
  if (send_command_to_cards (55, CardAddr << 16, MMC_CMDAT_RESPONSE_R1, 0, 1, 0) != MSC_PASSED)
	return MSC_FAILED;
  if (getrespondR1 (0) != MSC_PASSED)
	return MSC_FAILED;

 if (send_command_to_cards (6, 0x2, MMC_CMDAT_RESPONSE_R1, 0, 1, 1) != MSC_PASSED)
   return MSC_FAILED;
 if (getrespondR1 (0) != MSC_PASSED)
   return MSC_FAILED;

 datwidth = 4;

// send CMD13 (SEND_STATUS) with R1  (04: trans)   ******************
  Log ("Begin send CMD13 (SEND_STATUS) to card.\n");
  if (send_command_to_cards (13, CardAddr << 16, MMC_CMDAT_RESPONSE_R1, 0, 1, 0)
	   != MSC_PASSED)
	return MSC_FAILED;

  if (getrespondR1 (0) != MSC_PASSED)
	return MSC_FAILED;

  return MSC_PASSED;
}


void dump_copying_process ()
{
  int len;

  if (imagefile.BlockCnt < MAX_READ_BLOCK)
	return;
		
  imagefile.OutCnt++;
  imagefile.BlockCnt -= MAX_READ_BLOCK;
  len = (imagefile.OutCnt * MAX_READ_BLOCK * bootPartInfo.BytesPerSec);
  Log ("--- Reading file: 0x%x (%d) completed !! \n", len, len);
}


int ReadBlocks (unsigned int *DataBuf, unsigned int BlockAddr, unsigned int blocks)
{
  unsigned int i, j, blk, base, total_blocks = blocks;
  volatile DWORD mmc_ireg, mmc_stat;
  volatile UCHAR *pMMC_RX_Fifo = (volatile UCHAR *)&(pSDMMCRegisters->rxfifo);
  UINT8  *pBufPtr;

  pBufPtr = (UINT8 *)DataBuf;

  if (blocks == 1)   //Single block Read
  {
	if (send_command_to_cards (17, (BlockAddr * 0x200), 
		                        (MMC_CMDAT_DATA_EN | MMC_CMDAT_RESPONSE_R1), blocks, 1, 0)
		 != MSC_PASSED)
	  return MSC_FAILED;
	if (getrespondR1 (0) != MSC_PASSED)
	  return MSC_FAILED;

	i = 0;
	while (i < 0x200)
	{
			do {
		     mmc_ireg = READ_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_IREG);
			}  while(! (mmc_ireg & MMC_IREG_RXFIFO_REQ));
	  if (mmc_ireg & MMC_IREG_RXFIFO_REQ)
	  {
		for (j = 0; j < 32; j++)
	      pBufPtr[i++] = *pMMC_RX_Fifo;
	  }
	}

	pBufPtr += i;

	//dump_sector (DataBuf);

	 

	do {
	  mmc_stat = READ_MMC_REGISTER_DWORD( pSDMMCRegisters, MMC_STAT);
	} while (!(mmc_stat & MMC_STAT_DATA_TRANSFER_DONE)) ;

	// Dump the message about reading process.
	if (read_file)
	{
	  imagefile.BlockCnt++;
	  dump_copying_process ();
	}
  }
  else //Multiple block Read
  {
#ifdef USE_DMA_CHANNEL
	unsigned int addr;
	addr = (unsigned int)&(msc_reg->rxfifo_w32);
    dmac_reg->channel[USE_DMA_CHANNEL].dma_sar = addr & 0x1FFFFFFF;
	dmac_reg->channel[USE_DMA_CHANNEL].dma_rsr = DMA_DRSR_MSC_IN;
#endif
	base = 0;

	while (blocks > 0)
	{
	  blk = (blocks > MAX_READ_BLOCK) ? MAX_READ_BLOCK : blocks;

#ifdef USE_DMA_CHANNEL

⌨️ 快捷键说明

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