sddriver.c
上传用户:pudewen666
上传日期:2007-06-08
资源大小:75k
文件大小:19k
源码类别:

微处理器开发

开发平台:

Windows_Unix

  1. /****************************************Copyright (c)**************************************************
  2. **                               Guangzhou ZLG-MCU Development Co.,LTD.
  3. **                                      graduate school
  4. **                                 http://www.zlgmcu.com
  5. **
  6. **--------------File Info-------------------------------------------------------------------------------
  7. ** File name: sddriver.c
  8. ** Last modified Date: 2005-1-6
  9. ** Last Version: V1.0
  10. ** Descriptions: sd 卡驱动软件包: SD卡物理层 用户API函数
  11. ** Soft Packet of SD Card Driver: user API funciton
  12. **
  13. **------------------------------------------------------------------------------------------------------
  14. ** Created by: Ming Yuan Zheng
  15. ** Created date: 2005-1-6
  16. ** Version: V1.0
  17. ** Descriptions: The original version
  18. **
  19. **------------------------------------------------------------------------------------------------------
  20. ** Modified by:
  21. ** Modified date:
  22. ** Version:
  23. ** Descriptions:
  24. **
  25. **------------------------------------------------------------------------------------------------------
  26. ** Modified by: 
  27. ** Modified date:
  28. ** Version:
  29. ** Descriptions: 
  30. **
  31. ********************************************************************************************************/
  32. #include "config.h"
  33. #include "sdconfig.h"
  34. #include "sdhal.h"
  35. #include "SDCmd.h"
  36. #include "sddriver.h"
  37. /* SD卡信息结构体变量 the information structure variable of SD Card */
  38. sd_struct sds;
  39. /* 超时时间单位表(单位:0.000000001ns) timeout unit table */
  40. const INT32U time_unit[8] = {1000000000,100000000,10000000,
  41.  1000000,100000,10000,1000,100};
  42. /* 超时时间表 timeout value table */  
  43. const INT8U time_value[16] = {0,10,12,13,15,20,25,30,
  44.                               35,40,45,50,55,60,70,80};
  45.  
  46. /* 超时时间因数表 timeout factor table */                              
  47. const INT8U r2w_fator[6] = {1,2,4,8,16,32};                           
  48.     
  49. /*       
  50. ***************************************************************************************************
  51.      用户API函数:  初始化,读,写,擦 SD卡  User API Function: Initialize,read,write,erase SD Card 
  52. ***************************************************************************************************
  53. */
  54. /*******************************************************************************************************************
  55. ** 函数名称: INT8U SD_Initialize() Name:   INT8U SD_Initialize()
  56. ** 功能描述: 初始化SD卡 Function: initialize sd card
  57. ** 输   入: 无 Input:   NULL
  58. ** 输   出: 0:   正确    >0:   错误码    Output:   0:  right >0:  error code
  59. ********************************************************************************************************************/
  60. INT8U SD_Initialize(void)
  61. {
  62. INT8U recbuf[4],ret;
  63.     
  64.     SD_HardWareInit();      /* 初始化读写SD卡的硬件条件 Initialize the hardware that access SD Card */
  65.     
  66.     if (SD_ChkCard() != 1) /* 检查卡是否插入 check weather card is inserted */
  67.      return SD_ERR_NO_CARD;   
  68.          
  69.     SPI_CS_Assert(); /* 1. 置CS为低 assert CS */  
  70. SD_SPIDelay(25); /* 2. 至少延时 74 clock delay more than 74 clock */
  71.     SPI_CS_Deassert(); /* 3. 置CS为高 dessert CS */
  72.     SD_SPIDelay(2); /* 4. 延时2(8 clock) delay 2(8 clock) */
  73.     
  74.     ret = SD_ResetSD(); /* 5. 发出CMDO命令复位SD卡 send CMD0 command to reset sd card */
  75.     if (ret != SD_NO_ERR)
  76.         return ret;
  77.  
  78.   ret = SD_ActiveInit(); /* 6. 激活卡进入初始化过程. active card initialize process */
  79.   if (ret != SD_NO_ERR)
  80.   return ret;
  81.         
  82.     ret = SD_ReadOCR(4, recbuf);   /* 7. 读OCR寄存器,查询卡支持的电压值 read OCR register,get the supported voltage */
  83.     if (ret != SD_NO_ERR)
  84.         return ret;
  85.     
  86.     if ((recbuf[1] & MSK_OCR_33) != MSK_OCR_33)
  87.         return SD_ERR_VOL_NOTSUSP; /* 不支持3.3V,返回错误码  not support 3.3V,return error code */
  88.     
  89.     SPI_ClkToMax(); /* 8. 设置SPI时钟到最大值 set SPI clock to maximum */
  90.         
  91. #if SD_CRC_EN        
  92.     ret = SD_EnableCRC(1); /* 使能CRC校验 enable CRC check */
  93. if (ret != SD_NO_ERR)  
  94.    return ret;
  95. #endif
  96.     ret = SD_SetBlockLen(SD_BLOCKSIZE); /* 9. 设置块的长度: 512Bytes Set the block length: 512Bytes */
  97.     if (ret != SD_NO_ERR)  
  98.         return ret;
  99.         
  100. return (SD_GetCardInfo()); /* 10. 读CSD寄存器,获取SD卡信息 read CSD register, get the information of SD card */
  101. }
  102. /********************************************************************************************************************
  103. ** 函数名称: INT8U SD_ReadBlock() Name:   INT8U SD_ReadBlock()
  104. ** 功能描述: 从SD卡中读一个块 Function: read a single block from sd card
  105. ** 输   入: INT32U blockaddr: 块地址 Input:    INT32U blockaddr: address of block
  106.  INT8U *recbuf   : 接收缓冲区,长度512Bytes     INT8U *recbuf   : the buffer of receive,length is 512Bytes
  107. ** 输   出: 0:   正确    >0:   错误码    Output:   0:  right >0:  error code
  108. *********************************************************************************************************************/
  109. INT8U SD_ReadBlock(INT32U blockaddr, INT8U *recbuf)
  110. {
  111. INT8U ret; 
  112. if (blockaddr > sds.block_num)
  113. return SD_ERR_OVER_CARDRANGE; /* 操作超出卡容量范围 operate over the card range */
  114.   ret = SD_ReadSingleBlock(blockaddr); /* 读单块命令 read single blocks command */
  115.   if (ret != SD_NO_ERR)
  116.   return ret;
  117.  
  118.    return (SD_ReadBlockData(SD_BLOCKSIZE, recbuf));/* 读出数据 read data from sd card */
  119. }
  120. /********************************************************************************************************************
  121. ** 函数名称: INT8U SD_ReadMultiBlock() Name:   INT8U SD_ReadMultiBlock()
  122. ** 功能描述: 从SD卡中读多个块 Function: read multi blocks from sd card
  123. ** 输   入: INT32U blockaddr: 块地址 Input:   INT32U blockaddr: address of block
  124.  INT32U blocknum : 块数量   INT32U blocknum : the numbers of block
  125.  INT8U *recbuf   : 接收缓冲区,每块512字节   INT8U *recbuf   : the buffer of receive,each block length is 512Bytes
  126. ** 输   出: 0:   正确    >0:   错误码    Output:   0:  right >0:  error code
  127. *********************************************************************************************************************/
  128. #if SD_ReadMultiBlock_EN
  129. INT8U SD_ReadMultiBlock(INT32U blockaddr, INT32U blocknum, INT8U *recbuf)
  130. {
  131.     INT32U i;
  132.     INT8U ret;
  133.     
  134.     if ((blockaddr + blocknum) > sds.block_num)
  135. return SD_ERR_OVER_CARDRANGE; /* 操作超出卡容量范围 operate over the card range */
  136.     
  137. ret = SD_ReadMultipleBlock(blockaddr); /* 读多块命令 read multiple blocks command */
  138. if (ret != SD_NO_ERR)
  139. return ret;
  140.     
  141.     for (i = 0; i < blocknum; i++)
  142.     { /* 读出数据 read data from sd card */
  143.      ret = SD_ReadBlockData(SD_BLOCKSIZE, recbuf);
  144.      if (ret == SD_NO_ERR)
  145.         recbuf = recbuf + SD_BLOCKSIZE;
  146.      else
  147.      return ret;
  148.     }
  149.    
  150.   return (SD_StopTransmission());     /* 结束数据传输 stop transmission operation */
  151. }
  152. #endif
  153. /********************************************************************************************************************
  154. ** 函数名称: INT8U SD_WriteBlock() Name:   INT8U SD_WriteBlock()
  155. ** 功能描述: 向SD卡中写入一个块 Function: write a block to sd card
  156. ** 输   入: INT32U blockaddr: 块地址 Input:    INT32U blockaddr: address of block
  157.  INT8U *sendbuf  : 发送缓冲区,长度512Bytes      INT8U *sendbuf  : the buffer of send,length is 512Bytes
  158. ** 输   出: 0:   正确    >0:   错误码    Output:   0:  right >0:  error code
  159. *********************************************************************************************************************/
  160. INT8U SD_WriteBlock(INT32U blockaddr, INT8U *sendbuf)
  161. {
  162. INT8U ret,tmp[2];
  163. if (blockaddr > sds.block_num)
  164. return SD_ERR_OVER_CARDRANGE; /* 操作超出卡容量范围 operate over the card range */
  165. if (SD_ChkCardWP() == 1)
  166. return SD_ERR_WRITE_PROTECT; /* 卡有写保护 */
  167. ret = SD_WriteSingleBlock(blockaddr); /* 写单块命令 write single block */
  168. if (ret != SD_NO_ERR)
  169. return ret;
  170. ret = SD_WriteBlockData(0, SD_BLOCKSIZE, sendbuf); /* 写入数据 write data */
  171.   if (ret == SD_NO_ERR) /* 读Card Status寄存器, 检查写入是否成功 */
  172.   { /* read Card Status register to check write wheather sucessfully */
  173.   ret = SD_ReadCard_Status(2,tmp);
  174.   if (ret != SD_NO_ERR)
  175.   return ret; /* 读寄存器失败 read register fail */
  176.   if((tmp[0] != 0) || (tmp[1] != 0))
  177. ret = SD_ERR_WRITE_BLK;        /* 响应指示写失败 response indicate write fail */
  178.   }
  179.   
  180.   return ret; /* 返回写入结果 return the result of writing */
  181. }
  182. /**********************************************************************************************************************
  183. ** 函数名称: INT8U SD_WriteMultiBlock() Name:   INT8U SD_WriteMultiBlock()
  184. ** 功能描述: 向SD卡中写入多个块 Function: write multi blocks to sd card
  185. ** 输   入: INT32U blockaddr: 块地址 Input:   INT32U blockaddr: address of block
  186.  INT32U blocknum : 块数量   INT32U blocknum : the numbers of block
  187.  INT8U *sendbuf  : 发送缓冲区每块512字节       INT8U *sendbuf  : the send buffer,each block length is 512Bytes
  188. ** 输   出: 0:   正确    >0:   错误码    Output:   0:  right >0:  error code
  189. ***********************************************************************************************************************/
  190. #if SD_WriteMultiBlock_EN
  191. INT8U SD_WriteMultiBlock(INT32U blockaddr, INT32U blocknum, INT8U *sendbuf)
  192. {
  193. INT32U i;
  194. INT8U ret;
  195. if ((blockaddr + blocknum) > sds.block_num)
  196. return SD_ERR_OVER_CARDRANGE; /* 操作超出卡容量范围 operate over the card range */
  197. if (SD_ChkCardWP() == 1)
  198. return SD_ERR_WRITE_PROTECT; /* 卡有写保护 */
  199. ret = SD_WriteMultipleBlock(blockaddr); /* 写多块命令 write multiple blocks command */
  200. if (ret != SD_NO_ERR)
  201. return ret;
  202.     for (i = 0; i < blocknum; i++)
  203.     {
  204.   ret = SD_WriteBlockData(1, SD_BLOCKSIZE, sendbuf); /* 写入数据 write data */
  205.   if (ret == SD_NO_ERR)
  206.   sendbuf = sendbuf + SD_BLOCKSIZE;
  207.   else
  208.   { /* 写失败 write fail */
  209. SD_StopTransmission(); /* 停止数据传输 stop data transmission */
  210. SD_WaitBusy(SD_WAIT_WRITE); /* 等待 waiting */
  211. return ret;
  212. }
  213. }
  214.    
  215.     SD_StopMultiToken(); /* 发送数据停止令牌 send data stop token */
  216.       
  217.     ret = SD_WaitBusy(SD_WAIT_WRITE); /* 等待写入的完成 wait for finishing writing */
  218.     if (ret != SD_NO_ERR)
  219.      return SD_ERR_TIMEOUT_WRITE;
  220.     
  221.     ret = SD_GetNumWRBlcoks(&i); /* 读正确写入的块数 read the blocks that be written correctly */
  222.     if (ret != SD_NO_ERR)
  223.        return ret;
  224.       
  225.     if(i != blocknum) 
  226.       return SD_ERR_WRITE_BLKNUMS; /* 正确写入块数错误 the blocks that be written correctly is error */
  227.              
  228. return SD_NO_ERR; /* 返回写入成功 return write sucessfully */
  229. }
  230. #endif
  231. /*********************************************************************************************************************
  232. ** 函数名称: INT8U SD_EraseBlock() Name:   INT8U SD_EraseBlock()
  233. ** 功能描述: 擦除SD卡中的块 Function: Erase the block of sd card
  234. ** 输   入: INT32U startaddr: 起始地址 Input:    INT32U startaddr: start address
  235.  INT32U endaddr  : 终止地址   INT32U endaddr  : end address
  236. ** 输   出: 0:   正确    >0:   错误码    Output:   0:  right >0:  error code
  237. ** 注    意: startaddr 和 blocknum 建议为sds.erase_uint的整数倍, 因为有的卡只能以sds.erase_uint为单位进行擦除
  238. *********************************************************************************************************************/
  239. #if SD_EraseBlock_EN
  240. INT8U SD_EraseBlock(INT32U startaddr, INT32U blocknum)
  241. {
  242. INT32 tmp;
  243. INT8U ret;
  244. if ((startaddr + blocknum) > sds.block_num)
  245. return SD_ERR_OVER_CARDRANGE; /* 操作超出卡容量范围 operate over the card range */
  246. if (SD_ChkCardWP() == 1)
  247. return SD_ERR_WRITE_PROTECT; /* 卡有写保护 */
  248. tmp = blocknum - sds.erase_unit;
  249. while(tmp >= 0) /* 每次擦除扇区大小 once erase is sector size */
  250. {
  251. ret = SD_EraseStartBlock(startaddr); /* 选择起始块地址 select start address */
  252. if (ret != SD_NO_ERR)
  253. return ret;
  254. ret = SD_EraseEndBlock(startaddr + sds.erase_unit - 1); /* 选择终止块地址 select end address */
  255. if (ret != SD_NO_ERR)
  256. return ret;
  257. ret = SD_EraseSelectedBlock(); /* 擦除所选的块 erase blocks selected */
  258. if (ret != SD_NO_ERR)
  259. return ret;
  260. startaddr += sds.erase_unit; /* 起始地址递增 */
  261. blocknum  -= sds.erase_unit;
  262. tmp = blocknum - sds.erase_unit;
  263. };
  264. if (blocknum > 0) /* 擦除不够擦除扇区大小的块 */
  265. { /* erase blocks that numbers is not enough a sector */
  266. ret = SD_EraseStartBlock(startaddr);
  267. if (ret != SD_NO_ERR)
  268. return ret;
  269. ret = SD_EraseEndBlock(startaddr + blocknum - 1);
  270. if (ret != SD_NO_ERR)
  271. return ret;
  272. ret = SD_EraseSelectedBlock();
  273. if (ret != SD_NO_ERR)
  274. return ret;
  275. }
  276. return SD_NO_ERR; /* 返回擦除成功 return erase sucessfully */
  277. }
  278. #endif
  279. /*******************************************************************************************************************
  280. ** 函数名称: INT8U SD_GetCardInfo() Name:   INT8U SD_GetCardInfo()
  281. ** 功能描述: 获得SD卡的信息 Function: get the information of SD card
  282. ** 输   入: INT8U cardtype: 卡类型 Input:    INT8U cardtype: card type
  283. ** 输   出: 0:   正确    >0:   错误码    Output:   0:  right >0:  error code
  284. *******************************************************************************************************************/
  285. INT8U SD_GetCardInfo()
  286. {
  287. INT32U tmp;
  288. INT8U csdbuf[16],ret;
  289. ret = SD_ReadCSD(16,csdbuf);        /* 读CSD寄存器    read CSD register */
  290. if (ret != SD_NO_ERR)
  291. return ret;
  292. SD_CalTimeout(csdbuf); /* 计算超时时间值 calculate timeout value */
  293. /* 计算块的最大长度  */ /* calculate the size of a sector */
  294. sds.block_len = 1 << (csdbuf[READ_BL_LEN_POS] & READ_BL_LEN_MSK);   /* (2 ^ READ_BL_LEN) */
  295. /* 计算卡中块的个数 */ /* calculate the sector numbers of the SD Card */
  296. sds.block_num = ((csdbuf[C_SIZE_POS1] & C_SIZE_MSK1) << 10) +
  297.         (csdbuf[C_SIZE_POS2] << 2) +
  298.     ((csdbuf[C_SIZE_POS3] & C_SIZE_MSK3) >> 6) + 1; /* (C_SIZE + 1)*/
  299.     
  300. tmp = ((csdbuf[C_SIZE_MULT_POS1] & C_SIZE_MULT_MSK1) << 1) +   
  301.       ((csdbuf[C_SIZE_MULT_POS2] & C_SIZE_MULT_MSK2) >> 7) + 2; /* (C_SIZE_MULT + 2) */
  302.     
  303.     /* 获得卡中块的数量 */ /* get the block numbers in card */
  304. sds.block_num = sds.block_num * (1 << tmp); /* (C_SIZE + 1) * 2 ^ (C_SIZE_MULT + 2) */
  305. /* 计算扇区大小 */ /*calculate the size of sector */
  306. sds.erase_unit = ((csdbuf[SECTOR_SIZE_POS1] & SECTOR_SIZE_MSK1) << 1) +  
  307.                  ((csdbuf[SECTOR_SIZE_POS2] & SECTOR_SIZE_MSK2) >> 7) + 1; /* SD (SECTOR_SIZE + 1) */
  308.     
  309. return SD_NO_ERR; /* 返回执行成功 return perform sucessfully */
  310. }
  311. /*******************************************************************************************************************
  312. ** 函数名称: INT8U SD_CalTimeout() Name:   INT8U SD_CalTimeout()
  313. ** 功能描述: 计算读/写/擦超时时间 Function: get the information of SD card
  314. ** 输   入: INT8U cardtype: 卡类型 Input:    INT8U cardtype: card type
  315.  INT8U *csdbuf : CSD寄存器内容         INT8U *csdbuf : CSD register content
  316. ** 输   出: 0:   正确    >0:   错误码    Output:   0:  right >0:  error code
  317. *******************************************************************************************************************/
  318. void SD_CalTimeout(INT8U *csdbuf)
  319. {
  320. INT32U tmp;
  321. INT8U time_u,time_v,fator;
  322. sds.timeout_read = READ_TIMEOUT_100MS; /* 默认读超时为100ms */
  323. sds.timeout_write = WRITE_TIMEOUT_250MS; /* 默认写超时为250ms */
  324. sds.timeout_erase = WRITE_TIMEOUT_250MS;
  325. time_u = (csdbuf[TAAC_POS] & TAAC_MSK); /* 读超时时间单位 read timeout unit */
  326. time_v = (csdbuf[TAAC_POS] & NSAC_MSK) >> 3; /* 读超时时间值   read timeout value */
  327. fator = (csdbuf[R2WFACTOR_POS] & R2WFACTOR_MSK) >> 2; /* 写超时时间因数 write timeout factor */
  328. if(time_v == 0) return;
  329. if(fator >= 6) return;
  330. tmp = SPI_CLOCK * time_value[time_v] / 10 / time_unit[time_u]; /* TACC * f (单位 unit: clock) */
  331. tmp = tmp + csdbuf[NSAC_POS] * 100; /* TACC * f + NSAC * 100 (单位 unit: clock) */
  332. /* 计算得到的超时值 the timeout value of being calculated */
  333. sds.timeout_read = tmp;
  334. sds.timeout_write = tmp * r2w_fator[fator]; /* (TACC * f + NSAC * 100) * R2WFACTOR (单位 unit:clock)*/
  335. sds.timeout_read  = sds.timeout_read * 100 / 8; /* 实际值为计算值的100倍 */
  336. sds.timeout_write = sds.timeout_write * 100 / 8;
  337. if (sds.timeout_read > READ_TIMEOUT_100MS) /* 取计算值与默认值中的最小值 */
  338. sds.timeout_read = READ_TIMEOUT_100MS;
  339. if (sds.timeout_write > WRITE_TIMEOUT_250MS)
  340. sds.timeout_write = WRITE_TIMEOUT_250MS;
  341. sds.timeout_erase = sds.timeout_write;
  342. }
  343. /*******************************************************************************************************************
  344. ** 函数名称: INT8U SD_CalTimeout() Name:   INT8U SD_CalTimeout()
  345. ** 功能描述: 计算读/写/擦超时时间 Function: get the information of SD card
  346. ** 输   入: INT8U *cardtype: 卡类型接收缓冲  Input:    INT8U *cardtype: card type receive buff
  347. ** 输   出: 0:   正确    >0:   错误码    Output:   0:  right >0:  error code
  348. ** 函数说明: 该命令不断重复发送到SD卡,直到响应R1的Bit0(Idle)位为0,表示SD卡内部初始化处理完成。
  349.      当响应的Idle位为0时,SD卡就完全进入SPI模式了。当然重复发送命令CMD1是有次数限制的,
  350.      最大次数为宏定义SD_IDLE_WAIT_MAX.
  351. *******************************************************************************************************************/
  352. INT8U SD_ActiveInit(void)
  353. {
  354. INT8U param[4] = {0,0,0,0},resp[5],ret;
  355. INT32U i = 0;
  356.   do 
  357.     { /* 发出CMD1, 查询卡的状态, send CMD1 to poll card status */
  358.         ret = SD_SendCmd(CMD1, param, CMD1_R, resp);
  359.         if (ret != SD_NO_ERR)
  360.         return ret;
  361.   
  362.         i++;
  363.     }while (((resp[0] & MSK_IDLE) == MSK_IDLE) && (i < SD_IDLE_WAIT_MAX));
  364. /* 如果响应R1的最低位Idle位为1,则继续循环 */
  365.     if (i >= SD_IDLE_WAIT_MAX)
  366.         return SD_ERR_TIMEOUT_WAITIDLE; /* 超时,返回错误 time out,return error */
  367. return SD_NO_ERR;
  368. }
  369. /*******************************************************************************************************************
  370. ** 函数名称: INT16U SD_GetZLGSDVer() Name:   INT16U SD_GetZLGSDVer()
  371. ** 功能描述: 得到ZLG/SD的版本号 Function: get the version of ZLG/SD
  372. ** 输   入: 无 Input:    NULL
  373. ** 输   出: 版本号 Output:   Version
  374. *******************************************************************************************************************/
  375. INT16U SD_GetZLGSDVer(void)
  376. {
  377. return 0x0100; /* 版本号为 1.00 */
  378. }