drv_nand.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  1. /*
  2. * Copyright (c) 2006-2018, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2017-04-10 lizhen9880 the first version
  9. */
  10. #include "drv_nand.h"
  11. #include <rtdevice.h>
  12. #include <string.h>
  13. #ifdef RT_USING_NFTL
  14. #include <nftl.h>
  15. #endif
  16. #define NAND_DEBUG rt_kprintf
  17. /* nandflash confg */
  18. #define PAGES_PER_BLOCK 64
  19. #define PAGE_DATA_SIZE 2048
  20. #define PAGE_OOB_SIZE 64
  21. #define ECC_SIZE 4
  22. #define SET_NAND_CMD(_c) do{*(volatile rt_uint8_t*)(NAND_ADDRESS|NAND_CMD) = _c;}while(0)
  23. #define SET_NAND_ADD(_a) do{*(volatile rt_uint8_t*)(NAND_ADDRESS|NAND_ADDR) = _a;}while(0)
  24. #define SET_NAND_DAT(_d) do{*(volatile rt_uint8_t*)NAND_ADDRESS = _d;}while(0)
  25. #define GET_NAND_DAT(_d) do{_d = *(volatile rt_uint8_t*)NAND_ADDRESS;}while(0)
  26. static struct stm32f4_nand _device;
  27. static rt_bool_t read_status(rt_uint8_t cmd);
  28. NAND_HandleTypeDef NAND_Handler; //NAND FLASH句柄
  29. //NAND延时
  30. void NAND_Delay(volatile rt_uint32_t i)
  31. {
  32. while(i>0)i--;
  33. }
  34. //等待RB信号为某个电平
  35. //rb:0,等待RB==0
  36. // 1,等待RB==1
  37. //返回值:0,成功
  38. // 1,超时
  39. rt_uint8_t NAND_WaitRB(volatile rt_uint8_t rb)
  40. {
  41. volatile rt_uint16_t time=0;
  42. while(time<10000)
  43. {
  44. time++;
  45. if(NAND_RB==rb)
  46. {
  47. // NAND_DEBUG("time:%d/%d R/B:%d\n",time,10000,rb);
  48. return 0;
  49. }
  50. }
  51. // NAND_DEBUG("timeOUT\n");
  52. return 1;
  53. }
  54. //读NAND状态
  55. //返回值:NAND状态值
  56. //bit0:0,成功;1,错误(编程/擦除/READ)
  57. //bit6:0,Busy;1,Ready
  58. rt_uint8_t NAND_ReadStatus(void)
  59. {
  60. volatile rt_uint8_t data=0;
  61. SET_NAND_CMD(NAND_READSTA);//发送读状态命令
  62. data++;data++;data++;data++;data++; //加延时,防止-O2优化,导致的错误.
  63. data=*(volatile rt_uint8_t*)NAND_ADDRESS; //读取状态值
  64. return data;
  65. }
  66. //等待NAND准备好
  67. //返回值:NSTA_TIMEOUT 等待超时了
  68. // NSTA_READY 已经准备好
  69. static rt_uint8_t wait_for_ready(void)
  70. {
  71. rt_uint8_t status=0;
  72. volatile rt_uint32_t time=0;
  73. while(1) //等待ready
  74. {
  75. status=NAND_ReadStatus(); //获取状态值
  76. if(status&NSTA_READY)break;
  77. time++;
  78. if(time>=0X1FFFF)return NSTA_TIMEOUT;//超时
  79. }
  80. return NSTA_READY;//准备好
  81. }
  82. //复位NAND
  83. //返回值:0,成功;
  84. // 其他,失败
  85. static rt_uint8_t nand_reset(void)
  86. {
  87. SET_NAND_CMD(NAND_RESET);//复位NAND
  88. if(wait_for_ready()==NSTA_READY)return 0;//复位成功
  89. else return 1; //复位失败
  90. }
  91. //读取NAND FLASH的ID
  92. //返回值:0,成功;
  93. // 其他,失败
  94. rt_uint8_t NAND_ModeSet(rt_uint8_t mode)
  95. {
  96. SET_NAND_CMD(NAND_FEATURE);
  97. SET_NAND_ADD(0X01);
  98. SET_NAND_DAT(mode);
  99. SET_NAND_DAT(0);
  100. SET_NAND_DAT(0);
  101. SET_NAND_DAT(0);
  102. if(wait_for_ready()==NSTA_READY)return 0;//成功
  103. else return 1; //失败
  104. }
  105. //初始化NAND FLASH
  106. void NAND_Init(void)
  107. {
  108. FMC_NAND_PCC_TimingTypeDef ComSpaceTiming,AttSpaceTiming;
  109. NAND_Handler.Instance=FMC_NAND_DEVICE;
  110. NAND_Handler.Init.NandBank=FMC_NAND_BANK3; //NAND挂在BANK3上
  111. NAND_Handler.Init.Waitfeature=FMC_NAND_PCC_WAIT_FEATURE_DISABLE; //关闭等待特性
  112. NAND_Handler.Init.MemoryDataWidth=FMC_NAND_PCC_MEM_BUS_WIDTH_8; //8位数据宽度
  113. NAND_Handler.Init.EccComputation=FMC_NAND_ECC_DISABLE; //不使用ECC
  114. NAND_Handler.Init.ECCPageSize=FMC_NAND_ECC_PAGE_SIZE_2048BYTE; //ECC页大小为2k
  115. NAND_Handler.Init.TCLRSetupTime=0; //设置TCLR(tCLR=CLE到RE的延时)=(TCLR+TSET+2)*THCLK,THCLK=1/180M=5.5ns
  116. NAND_Handler.Init.TARSetupTime=1; //设置TAR(tAR=ALE到RE的延时)=(TAR+TSET+2)*THCLK,THCLK=1/180M=5.5n。
  117. ComSpaceTiming.SetupTime=2; //建立时间
  118. ComSpaceTiming.WaitSetupTime=3; //等待时间
  119. ComSpaceTiming.HoldSetupTime=2; //保持时间
  120. ComSpaceTiming.HiZSetupTime=1; //高阻态时间
  121. AttSpaceTiming.SetupTime=2; //建立时间
  122. AttSpaceTiming.WaitSetupTime=3; //等待时间
  123. AttSpaceTiming.HoldSetupTime=2; //保持时间
  124. AttSpaceTiming.HiZSetupTime=1; //高阻态时间
  125. HAL_NAND_Init(&NAND_Handler,&ComSpaceTiming,&AttSpaceTiming);
  126. nand_reset(); //复位NAND
  127. // delay_ms(100);
  128. wait_for_ready();
  129. NAND_ModeSet(4); //设置为MODE4,高速模式
  130. }
  131. //NAND FALSH底层驱动,引脚配置,时钟使能
  132. //此函数会被HAL_NAND_Init()调用
  133. void HAL_NAND_MspInit(NAND_HandleTypeDef *hnand)
  134. {
  135. GPIO_InitTypeDef GPIO_Initure;
  136. __HAL_RCC_FMC_CLK_ENABLE(); //使能FMC时钟
  137. __HAL_RCC_GPIOD_CLK_ENABLE(); //使能GPIOD时钟
  138. __HAL_RCC_GPIOE_CLK_ENABLE(); //使能GPIOE时钟
  139. __HAL_RCC_GPIOG_CLK_ENABLE(); //使能GPIOG时钟
  140. //初始化PD6 R/B引脚
  141. GPIO_Initure.Pin=GPIO_PIN_6;
  142. GPIO_Initure.Mode=GPIO_MODE_INPUT; //输入
  143. GPIO_Initure.Pull=GPIO_PULLUP; //上拉
  144. GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速
  145. HAL_GPIO_Init(GPIOD,&GPIO_Initure);
  146. //初始化PG9 NCE3引脚
  147. GPIO_Initure.Pin=GPIO_PIN_9;
  148. GPIO_Initure.Mode=GPIO_MODE_AF_PP; //输入
  149. GPIO_Initure.Pull=GPIO_NOPULL; //上拉
  150. GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速
  151. GPIO_Initure.Alternate=GPIO_AF12_FMC; //复用为FMC
  152. HAL_GPIO_Init(GPIOG,&GPIO_Initure);
  153. //初始化PD0,1,4,5,11,12,14,15
  154. GPIO_Initure.Pin=GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5|\
  155. GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_14|GPIO_PIN_15;
  156. GPIO_Initure.Pull=GPIO_NOPULL;
  157. HAL_GPIO_Init(GPIOD,&GPIO_Initure);
  158. //初始化PE7,8,9,10
  159. GPIO_Initure.Pin=GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10;
  160. HAL_GPIO_Init(GPIOE,&GPIO_Initure);
  161. }
  162. //读NAND状态
  163. //返回值:NAND状态值
  164. //bit0:0,成功;1,错误(编程/擦除/READ)
  165. //bit6:0,Busy;1,Ready
  166. static rt_bool_t read_status(rt_uint8_t cmd)
  167. {
  168. volatile rt_uint8_t value=0;
  169. SET_NAND_CMD(NAND_READSTA);//发送读状态命令
  170. value++;value++;value++;value++;value++; //加延时,防止-O2优化,导致的错误.
  171. value=*(volatile rt_uint8_t*)NAND_ADDRESS; //读取状态值
  172. switch (cmd)
  173. {
  174. case NAND_WRITE0:
  175. case NAND_ERASE1:
  176. if (value & 0x01) /* Erase/Program failure(1) or pass(0) */
  177. return (RT_FALSE);
  178. else
  179. return (RT_TRUE);
  180. case NAND_AREA_TRUE1: /* bit 5 and 6, Read busy(0) or ready(1) */
  181. return (RT_TRUE);
  182. default:
  183. break;
  184. }
  185. return (RT_FALSE);
  186. }
  187. static rt_err_t nand_MT29F4G08_readid(struct rt_mtd_nand_device *device)
  188. {
  189. rt_uint32_t id;
  190. SET_NAND_CMD(NAND_READID); //发送读取ID命令
  191. SET_NAND_ADD(0X00);
  192. GET_NAND_DAT(_device.id[0]);//ID一共有5个字节
  193. GET_NAND_DAT(_device.id[1]);
  194. GET_NAND_DAT(_device.id[2]);
  195. GET_NAND_DAT(_device.id[3]);
  196. GET_NAND_DAT(_device.id[4]);
  197. //镁光的NAND FLASH的ID一共5个字节,但是为了方便我们只取4个字节组成一个32位的ID值
  198. //根据NAND FLASH的数据手册,只要是镁光的NAND FLASH,那么一个字节ID的第一个字节都是0X2C
  199. //所以我们就可以抛弃这个0X2C,只取后面四字节的ID值。
  200. id=((rt_uint32_t)_device.id[1])<<24|((rt_uint32_t)_device.id[2])<<16|((rt_uint32_t)_device.id[3])<<8|_device.id[4];
  201. rt_kprintf("\nNAND ID: 0x%08X\n", id);
  202. return RT_EOK;
  203. }
  204. static rt_err_t nand_datacorrect(uint32_t generatedEcc, uint32_t readEcc, uint8_t *data)
  205. {
  206. #define ECC_MASK28 0x0FFFFFFF /* 28 valid ECC parity bits. */
  207. #define ECC_MASK 0x05555555 /* 14 ECC parity bits. */
  208. rt_uint32_t count, bitNum, byteAddr;
  209. rt_uint32_t mask;
  210. rt_uint32_t syndrome;
  211. rt_uint32_t eccP; /* 14 even ECC parity bits. */
  212. rt_uint32_t eccPn; /* 14 odd ECC parity bits. */
  213. syndrome = (generatedEcc ^ readEcc) & ECC_MASK28;
  214. if (syndrome == 0)
  215. return (RT_MTD_EOK); /* No errors in data. */
  216. eccPn = syndrome & ECC_MASK; /* Get 14 odd parity bits. */
  217. eccP = (syndrome >> 1) & ECC_MASK; /* Get 14 even parity bits. */
  218. if ((eccPn ^ eccP) == ECC_MASK) /* 1-bit correctable error ? */
  219. {
  220. bitNum = (eccP & 0x01) |
  221. ((eccP >> 1) & 0x02) |
  222. ((eccP >> 2) & 0x04);
  223. NAND_DEBUG("ECC bit %d\n",bitNum);
  224. byteAddr = ((eccP >> 6) & 0x001) |
  225. ((eccP >> 7) & 0x002) |
  226. ((eccP >> 8) & 0x004) |
  227. ((eccP >> 9) & 0x008) |
  228. ((eccP >> 10) & 0x010) |
  229. ((eccP >> 11) & 0x020) |
  230. ((eccP >> 12) & 0x040) |
  231. ((eccP >> 13) & 0x080) |
  232. ((eccP >> 14) & 0x100) |
  233. ((eccP >> 15) & 0x200) |
  234. ((eccP >> 16) & 0x400) ;
  235. data[ byteAddr ] ^= 1 << bitNum;
  236. return RT_MTD_EOK;
  237. }
  238. /* Count number of one's in the syndrome. */
  239. count = 0;
  240. mask = 0x00800000;
  241. while (mask)
  242. {
  243. if (syndrome & mask)
  244. count++;
  245. mask >>= 1;
  246. }
  247. if (count == 1) /* Error in the ECC itself. */
  248. return RT_MTD_EECC;
  249. return -RT_MTD_EECC; /* Unable to correct data. */
  250. #undef ECC_MASK
  251. #undef ECC_MASK24
  252. }
  253. static rt_err_t nand_MT29F4G08_readpage(struct rt_mtd_nand_device *device,
  254. rt_off_t page,
  255. rt_uint8_t *data,
  256. rt_uint32_t data_len,
  257. rt_uint8_t *spare,
  258. rt_uint32_t spare_len)
  259. {
  260. rt_uint32_t index;
  261. rt_uint32_t gecc, recc;
  262. rt_uint8_t tmp[4];
  263. rt_err_t result;
  264. rt_uint32_t i;
  265. page = page + device->block_start * device->pages_per_block;
  266. if (page/device->pages_per_block > device->block_end)
  267. {
  268. return -RT_MTD_EIO;
  269. }
  270. result = RT_MTD_EOK;
  271. rt_mutex_take(&_device.lock, RT_WAITING_FOREVER);
  272. if (data && data_len)
  273. {
  274. SET_NAND_CMD(NAND_AREA_A); //发送地址
  275. SET_NAND_ADD((rt_uint8_t)(0&0xFF));
  276. SET_NAND_ADD((rt_uint8_t)(0>>8));
  277. SET_NAND_ADD((rt_uint8_t)(page & 0xFF));
  278. SET_NAND_ADD((rt_uint8_t)(page >> 8));
  279. SET_NAND_ADD((rt_uint8_t)(page >> 16));
  280. SET_NAND_CMD(NAND_AREA_TRUE1);
  281. //下面两行代码是等待R/B引脚变为低电平,其实主要起延时作用的,等待NAND操作R/B引脚。因为我们是通过
  282. //将STM32的NWAIT引脚(NAND的R/B引脚)配置为普通IO,代码中通过读取NWAIT引脚的电平来判断NAND是否准备
  283. //就绪的。这个也就是模拟的方法,所以在速度很快的时候有可能NAND还没来得及操作R/B引脚来表示NAND的忙
  284. //闲状态,就读取了R/B引脚,这个时候肯定会出错的,事实上确实是会出错!
  285. NAND_WaitRB(0); //等待RB=0
  286. //下面2行代码是真正判断NAND是否准备好的
  287. NAND_WaitRB(1); //等待RB=1
  288. FMC_NAND_ECC_Enable(NAND_Handler.Instance,FMC_NAND_BANK3);
  289. for (i = 0; i < data_len; i ++)
  290. {
  291. GET_NAND_DAT(data[i]);
  292. }
  293. gecc = FMC_NAND_GetECC(NAND_Handler.Instance,(uint32_t*)&gecc,FMC_NAND_BANK3,10);
  294. if (data_len == PAGE_DATA_SIZE)
  295. {
  296. for (index = 0; index < ECC_SIZE; index ++)
  297. {
  298. GET_NAND_DAT(tmp[index]);
  299. }
  300. if (spare && spare_len)
  301. {
  302. for (i = ECC_SIZE; i < spare_len; i ++)
  303. {
  304. GET_NAND_DAT(spare[i]);
  305. }
  306. rt_memcpy(spare, tmp , ECC_SIZE);
  307. }
  308. recc = (tmp[3] << 24) | (tmp[2] << 16) | (tmp[1] << 8) | tmp[0];
  309. if (recc != 0xFFFFFFFF && gecc != 0)
  310. result = nand_datacorrect(gecc, recc, data);
  311. if (result != RT_MTD_EOK)
  312. NAND_DEBUG("page: %d, gecc %X, recc %X>",page, gecc, recc);
  313. goto _exit;
  314. }
  315. }
  316. if (spare && spare_len)
  317. {
  318. SET_NAND_CMD(NAND_AREA_A); //发送地址
  319. SET_NAND_ADD((rt_uint8_t)(PAGE_DATA_SIZE&0xFF));
  320. SET_NAND_ADD((rt_uint8_t)(PAGE_DATA_SIZE>>8));
  321. SET_NAND_ADD((rt_uint8_t)(page & 0xFF));
  322. SET_NAND_ADD((rt_uint8_t)(page >> 8));
  323. SET_NAND_ADD((rt_uint8_t)(page >> 16));
  324. SET_NAND_CMD(NAND_AREA_TRUE1);
  325. //下面两行代码是等待R/B引脚变为低电平,其实主要起延时作用的,等待NAND操作R/B引脚。因为我们是通过
  326. //将STM32的NWAIT引脚(NAND的R/B引脚)配置为普通IO,代码中通过读取NWAIT引脚的电平来判断NAND是否准备
  327. //就绪的。这个也就是模拟的方法,所以在速度很快的时候有可能NAND还没来得及操作R/B引脚来表示NAND的忙
  328. //闲状态,就读取了R/B引脚,这个时候肯定会出错的,事实上确实是会出错!
  329. NAND_WaitRB(0); //等待RB=0
  330. //下面2行代码是真正判断NAND是否准备好的
  331. NAND_WaitRB(1); //等待RB=1
  332. for (i = 0; i < spare_len; i ++)
  333. {
  334. GET_NAND_DAT(spare[i]);
  335. }
  336. }
  337. _exit:
  338. rt_mutex_release(&_device.lock);
  339. return (result);
  340. }
  341. static rt_err_t nand_MT29F4G08_writepage(struct rt_mtd_nand_device *device,
  342. rt_off_t page,
  343. const rt_uint8_t *data,
  344. rt_uint32_t data_len,
  345. const rt_uint8_t *spare,
  346. rt_uint32_t spare_len)
  347. {
  348. rt_err_t result;
  349. rt_uint32_t gecc;
  350. rt_uint32_t i;
  351. page = page + device->block_start * device->pages_per_block;
  352. if (page/device->pages_per_block > device->block_end)
  353. {
  354. return -RT_MTD_EIO;
  355. }
  356. result = RT_MTD_EOK;
  357. rt_mutex_take(&_device.lock, RT_WAITING_FOREVER);
  358. if (data && data_len)
  359. {
  360. SET_NAND_CMD(NAND_WRITE0); //发送地址
  361. SET_NAND_ADD((rt_uint8_t)(0&0xFF));
  362. SET_NAND_ADD((rt_uint8_t)(0>>8));
  363. SET_NAND_ADD((rt_uint8_t)(page & 0xFF));
  364. SET_NAND_ADD((rt_uint8_t)(page >> 8));
  365. SET_NAND_ADD((rt_uint8_t)(page >> 16));
  366. FMC_NAND_ECC_Enable(NAND_Handler.Instance,FMC_NAND_BANK3);
  367. for (i = 0; i < data_len; i ++)
  368. {
  369. SET_NAND_DAT(data[i]);
  370. }
  371. gecc = FMC_NAND_GetECC(NAND_Handler.Instance,(uint32_t*)&gecc,FMC_NAND_BANK3,10);
  372. FMC_NAND_ECC_Disable(NAND_Handler.Instance,FMC_NAND_BANK3);
  373. if (data_len == PAGE_DATA_SIZE)
  374. {
  375. SET_NAND_DAT((uint8_t)gecc);
  376. SET_NAND_DAT((uint8_t)(gecc >> 8));
  377. SET_NAND_DAT((uint8_t)(gecc >> 16));
  378. SET_NAND_DAT((uint8_t)(gecc >> 24));
  379. if (spare && spare_len)
  380. {
  381. for (i = ECC_SIZE; i < spare_len; i ++)
  382. {
  383. SET_NAND_DAT(spare[i]);
  384. }
  385. }
  386. }
  387. SET_NAND_CMD(NAND_WRITE_TURE1);
  388. if(wait_for_ready()!=NSTA_READY)
  389. {
  390. nand_reset();
  391. result = -RT_MTD_EIO;//失败
  392. }
  393. goto _exit;
  394. }
  395. if (spare && spare_len)
  396. {
  397. SET_NAND_CMD(NAND_WRITE0); //发送地址
  398. SET_NAND_ADD((rt_uint8_t)(PAGE_DATA_SIZE&0xFF));
  399. SET_NAND_ADD((rt_uint8_t)(PAGE_DATA_SIZE>>8));
  400. SET_NAND_ADD((rt_uint8_t)(page & 0xFF));
  401. SET_NAND_ADD((rt_uint8_t)(page >> 8));
  402. SET_NAND_ADD((rt_uint8_t)(page >> 16));
  403. if (spare && spare_len)
  404. for (i = ECC_SIZE; i < spare_len; i ++)
  405. {
  406. SET_NAND_DAT(spare[i]);
  407. }
  408. SET_NAND_CMD(NAND_WRITE_TURE1);
  409. if(wait_for_ready()!=NSTA_READY)
  410. {
  411. nand_reset();
  412. result = -RT_MTD_EIO;//失败
  413. }
  414. }
  415. _exit:
  416. rt_mutex_release(&_device.lock);
  417. return (result);
  418. }
  419. static rt_err_t nand_MT29F4G08_eraseblock(struct rt_mtd_nand_device *device,
  420. rt_uint32_t block)
  421. {
  422. unsigned int blockPage;
  423. rt_err_t result;
  424. /* add the start blocks */
  425. block = block + device->block_start;
  426. blockPage = (block << 6);
  427. result = RT_MTD_EOK;
  428. rt_mutex_take(&_device.lock, RT_WAITING_FOREVER);
  429. SET_NAND_CMD(NAND_ERASE0); //发送地址
  430. SET_NAND_ADD((rt_uint8_t)blockPage);
  431. SET_NAND_ADD((rt_uint8_t)(blockPage>>8));
  432. SET_NAND_ADD((rt_uint8_t)(blockPage>>16));
  433. SET_NAND_CMD(NAND_ERASE1);
  434. if(wait_for_ready()!=NSTA_READY)
  435. {
  436. nand_reset();
  437. result = -RT_MTD_EIO;//失败
  438. }
  439. rt_mutex_release(&_device.lock);
  440. return result;
  441. }
  442. static rt_err_t nand_MT29F4G08_pagecopy(struct rt_mtd_nand_device *device,
  443. rt_off_t src_page,
  444. rt_off_t dst_page)
  445. {
  446. rt_err_t result = RT_MTD_EOK;
  447. rt_uint32_t source_block=0,dest_block=0;
  448. src_page = src_page + device->block_start * device->pages_per_block;
  449. dst_page = dst_page + device->block_start * device->pages_per_block;
  450. //判断源页和目的页是否在同一个plane中
  451. source_block=src_page/device->pages_per_block;
  452. dest_block=dst_page/device->pages_per_block;
  453. if((source_block%2)!=(dest_block%2))return RT_MTD_ESRC; //不在同一个plane内
  454. SET_NAND_CMD(NAND_MOVEDATA_CMD0);//发送命令0X00
  455. SET_NAND_ADD((rt_uint8_t)(0&0xFF)); //发送源页地址
  456. SET_NAND_ADD((rt_uint8_t)(0>>8));
  457. SET_NAND_ADD((rt_uint8_t)(src_page & 0xFF));
  458. SET_NAND_ADD((rt_uint8_t)(src_page >> 8));
  459. SET_NAND_ADD((rt_uint8_t)(src_page >> 16));
  460. SET_NAND_CMD(NAND_MOVEDATA_CMD1);//发送命令0X35
  461. //下面两行代码是等待R/B引脚变为低电平,其实主要起延时作用的,等待NAND操作R/B引脚。因为我们是通过
  462. //将STM32的NWAIT引脚(NAND的R/B引脚)配置为普通IO,代码中通过读取NWAIT引脚的电平来判断NAND是否准备
  463. //就绪的。这个也就是模拟的方法,所以在速度很快的时候有可能NAND还没来得及操作R/B引脚来表示NAND的忙
  464. //闲状态,结果我们就读取了R/B引脚,这个时候肯定会出错的,事实上确实是会出错!大家也可以将下面两行
  465. //代码换成延时函数,只不过这里我们为了效率所以没有用延时函数。
  466. result=NAND_WaitRB(0); //等待RB=0
  467. if(result)return -RT_MTD_EIO; //超时退出
  468. //下面2行代码是真正判断NAND是否准备好的
  469. result=NAND_WaitRB(1); //等待RB=1
  470. if(result)return -RT_MTD_EIO; //超时退出
  471. SET_NAND_CMD(NAND_MOVEDATA_CMD2);//发送命令0X85
  472. SET_NAND_ADD((rt_uint8_t)(0&0xFF)); //发送目的页地址
  473. SET_NAND_ADD((rt_uint8_t)(0>>8));
  474. SET_NAND_ADD((rt_uint8_t)(dst_page & 0xFF));
  475. SET_NAND_ADD((rt_uint8_t)(dst_page >> 8));
  476. SET_NAND_ADD((rt_uint8_t)(dst_page >> 16));
  477. SET_NAND_CMD(NAND_MOVEDATA_CMD3);//发送命令0X10
  478. if(wait_for_ready()!=NSTA_READY)
  479. {
  480. nand_reset();
  481. return -RT_MTD_EIO;//失败
  482. }
  483. return RT_MTD_EOK;
  484. }
  485. static rt_err_t nand_MT29F4G08_checkblock(struct rt_mtd_nand_device* device, rt_uint32_t block)
  486. {
  487. return (RT_MTD_EOK);
  488. }
  489. static rt_err_t nand_MT29F4G08_markbad(struct rt_mtd_nand_device* device, rt_uint32_t block)
  490. {
  491. return (RT_MTD_EOK);
  492. }
  493. static const struct rt_mtd_nand_driver_ops ops =
  494. {
  495. nand_MT29F4G08_readid,
  496. nand_MT29F4G08_readpage,
  497. nand_MT29F4G08_writepage,
  498. nand_MT29F4G08_pagecopy,
  499. nand_MT29F4G08_eraseblock,
  500. nand_MT29F4G08_checkblock,
  501. nand_MT29F4G08_markbad,
  502. };
  503. static struct rt_mtd_nand_device _partition[1];
  504. int nand_MT29F4G08_hw_init(void)
  505. {
  506. NAND_Init();
  507. rt_mutex_init(&_device.lock, "nand", RT_IPC_FLAG_FIFO);
  508. /* register nand0 */
  509. _partition[0].page_size = PAGE_DATA_SIZE;
  510. _partition[0].pages_per_block = PAGES_PER_BLOCK;
  511. _partition[0].plane_num = 2;
  512. _partition[0].oob_size = PAGE_OOB_SIZE;
  513. _partition[0].oob_free = PAGE_OOB_SIZE - ((PAGE_DATA_SIZE) * 3 / 256);
  514. _partition[0].block_start = 0;
  515. _partition[0].block_end = 4095;
  516. _partition[0].block_total = _partition[0].block_end - _partition[0].block_start;
  517. _partition[0].ops = &ops;
  518. rt_mtd_nand_register_device("nand0", &_partition[0]);
  519. nand_MT29F4G08_readid(&_partition[0]);
  520. return RT_EOK;
  521. }
  522. INIT_BOARD_EXPORT(nand_MT29F4G08_hw_init);