drv_nand.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-09-28 mingmiaojing first version
  9. */
  10. #include <rtconfig.h>
  11. #ifdef BSP_USING_NAND1
  12. #include <board.h>
  13. #include "drv_nand.h"
  14. #include "drv_config.h"
  15. #include <lpm.h>
  16. #define NAND_PAGE_SIZE ((uint16_t)2048)
  17. #define NAND1_RW_TEST
  18. #ifndef RT_FIOGETXIPADDR
  19. #define RT_FIOGETXIPADDR 0x52540001U
  20. #endif
  21. struct rt_device _hw_nand1;
  22. NAND_HandleTypeDef hnand1;
  23. /* FSMC initialization function */
  24. static void rt_nand_init(void)
  25. {
  26. /* USER CODE BEGIN FSMC_Init 0 */
  27. /* USER CODE END FSMC_Init 0 */
  28. FSMC_NAND_PCC_TimingTypeDef ComSpaceTiming = {0};
  29. FSMC_NAND_PCC_TimingTypeDef AttSpaceTiming = {0};
  30. /* USER CODE BEGIN FSMC_Init 1 */
  31. /* USER CODE END FSMC_Init 1 */
  32. /** Perform the NAND1 memory initialization sequence
  33. */
  34. hnand1.Instance = FSMC_NAND_DEVICE;
  35. /* hnand1.Init */
  36. hnand1.Init.NandBank = FSMC_NAND_BANK2;
  37. hnand1.Init.Waitfeature = FSMC_NAND_PCC_WAIT_FEATURE_ENABLE;
  38. hnand1.Init.MemoryDataWidth = FSMC_NAND_PCC_MEM_BUS_WIDTH_8;
  39. hnand1.Init.EccComputation = FSMC_NAND_ECC_ENABLE;
  40. hnand1.Init.ECCPageSize = FSMC_NAND_ECC_PAGE_SIZE_512BYTE;
  41. hnand1.Init.TCLRSetupTime = 0;
  42. hnand1.Init.TARSetupTime = 0;
  43. /* hnand1.Config */
  44. hnand1.Config.PageSize = NAND_PAGE_SIZE;
  45. hnand1.Config.SpareAreaSize = 64;
  46. hnand1.Config.BlockSize = 64;
  47. hnand1.Config.BlockNbr = 1024;
  48. hnand1.Config.PlaneNbr = 1;
  49. hnand1.Config.PlaneSize = 1024;
  50. hnand1.Config.ExtraCommandEnable = DISABLE;
  51. /* ComSpaceTiming */
  52. ComSpaceTiming.SetupTime = 4;
  53. ComSpaceTiming.WaitSetupTime = 3;
  54. ComSpaceTiming.HoldSetupTime = 2;
  55. ComSpaceTiming.HiZSetupTime = 4;
  56. /* AttSpaceTiming */
  57. AttSpaceTiming.SetupTime = 4;
  58. AttSpaceTiming.WaitSetupTime = 3;
  59. AttSpaceTiming.HoldSetupTime = 2;
  60. AttSpaceTiming.HiZSetupTime = 4;
  61. if (HAL_NAND_Init(&hnand1, &ComSpaceTiming, &AttSpaceTiming) != HAL_OK)
  62. {
  63. Error_Handler( );
  64. }
  65. /** Disconnect NADV
  66. */
  67. __HAL_AFIO_FSMCNADV_DISCONNECTED();
  68. /* USER CODE BEGIN FSMC_Init 2 */
  69. /* USER CODE END FSMC_Init 2 */
  70. }
  71. rt_err_t rt_nand_open(rt_device_t dev, rt_uint16_t oflag)
  72. {
  73. return RT_EOK;
  74. }
  75. rt_err_t rt_nand_control(rt_device_t dev, int cmd, void *args)
  76. {
  77. if(RT_DEVICE_CTRL_BLK_GETGEOME == cmd)
  78. {
  79. struct rt_device_blk_geometry *geometry = (struct rt_device_blk_geometry *)args;
  80. geometry->bytes_per_sector = 2048;
  81. geometry->sector_count = 64 * 1024;
  82. geometry->block_size = 2048 * 64;
  83. return RT_EOK;
  84. }
  85. else if(RT_FIOGETXIPADDR == cmd)
  86. {
  87. uint32_t *start_addr = (uint32_t *)args;
  88. *start_addr = 0;
  89. return RT_EOK;
  90. }
  91. else if(RT_DEVICE_CTRL_BLK_ERASE == cmd)
  92. {
  93. uint32_t *blk = (uint32_t *)args;
  94. NAND_AddressTypeDef Addr;
  95. Addr.Plane = 0x00;
  96. Addr.Block = *blk;
  97. Addr.Page = 0x00;
  98. HAL_NAND_Erase_Block(&hnand1,&Addr);
  99. return RT_EOK;
  100. }
  101. return -RT_ERROR;
  102. }
  103. /*pos: sector offset size: page count*/
  104. rt_ssize_t rt_nand_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
  105. {
  106. uint32_t page_cnt = size;
  107. NAND_AddressTypeDef ReadAddr;
  108. ReadAddr.Page = pos%64;
  109. ReadAddr.Plane = 0;
  110. ReadAddr.Block = pos/64;
  111. HAL_NAND_Read_Page(&hnand1, &ReadAddr, (uint8_t *)buffer, page_cnt);
  112. return RT_EOK;
  113. }
  114. rt_ssize_t rt_nand_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
  115. {
  116. uint32_t page_cnt = size;
  117. NAND_AddressTypeDef WriteAddr;
  118. WriteAddr.Page = pos%64;
  119. WriteAddr.Plane = 0;
  120. WriteAddr.Block = pos/64;
  121. HAL_NAND_Write_Page(&hnand1, &WriteAddr, (uint8_t *)buffer, page_cnt);
  122. return RT_EOK;
  123. }
  124. static int stm32_nand1_init(void)
  125. {
  126. NAND_IDTypeDef NAND_ID;
  127. rt_nand_init();
  128. HAL_NAND_Read_ID(&hnand1, &NAND_ID);
  129. rt_kprintf("Nand Flash ID = 0x%02X,0x%02X,0x%02X,0x%02X",
  130. NAND_ID.Maker_Id, NAND_ID.Device_Id,
  131. NAND_ID.Third_Id, NAND_ID.Fourth_Id);
  132. #ifdef NAND1_RW_TEST
  133. uint32_t i = 0;
  134. static uint8_t TxBuffer [NAND_PAGE_SIZE];
  135. static uint8_t RxBuffer [NAND_PAGE_SIZE];
  136. NAND_AddressTypeDef WriteReadAddr;
  137. WriteReadAddr.Plane = 0x00;
  138. WriteReadAddr.Block = 0x00;
  139. WriteReadAddr.Page = 0x00;
  140. /* Erase the NAND first Block */
  141. for(i = 0; i < 64; i++)
  142. {
  143. WriteReadAddr.Block = i;
  144. HAL_NAND_Erase_Block(&hnand1,&WriteReadAddr);
  145. }
  146. // /* Fill the buffer to send */
  147. // for (i = 0; i < NAND_PAGE_SIZE; i++ )
  148. // {
  149. // TxBuffer[i] = i;
  150. // }
  151. //
  152. // /* Write data to FMC NAND memory */
  153. // HAL_NAND_Write_Page(&hnand1, &WriteReadAddr, TxBuffer, 1);
  154. // rt_kprintf("\r\nWritten to the number:\r\n");
  155. // for(i = 0; i < 2048; i++)
  156. // {
  157. // rt_kprintf("0x%02X \t",TxBuffer[i]);
  158. // }
  159. // rt_kprintf("\n");
  160. // HAL_Delay(100);
  161. /* Read data from FMC NAND memory */
  162. WriteReadAddr.Block = 0;
  163. HAL_NAND_Read_Page(&hnand1, &WriteReadAddr, RxBuffer, 1);
  164. rt_kprintf("\r\nRead receive: \r\n");
  165. for(i = 0; i < 16; i++)
  166. {
  167. rt_kprintf("0x%02X \t",RxBuffer[i]);
  168. }
  169. rt_kprintf("\n");
  170. #endif
  171. //_hw_nand1.ops = &_hw_nand1;
  172. _hw_nand1.type = RT_Device_Class_MTD;
  173. _hw_nand1.init = RT_NULL;//rt_nand_init
  174. _hw_nand1.open = rt_nand_open;
  175. _hw_nand1.close = RT_NULL;
  176. _hw_nand1.read = rt_nand_read;
  177. _hw_nand1.write = rt_nand_write;
  178. _hw_nand1.control = rt_nand_control;
  179. _hw_nand1.user_data = RT_NULL;
  180. rt_device_register(&_hw_nand1,"nand1", RT_DEVICE_FLAG_RDWR);
  181. rt_kprintf("nand1 init done\n");
  182. lpm_init();
  183. lpm_dev_blk_append(&_hw_nand1);
  184. return 0;
  185. }
  186. INIT_BOARD_EXPORT(stm32_nand1_init);
  187. #endif