at45db041.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. #include "at45db041.h"
  2. #include "periph.h"
  3. #include <memory.h>
  4. #include <stdio.h>
  5. /*Make the buffer visible for the external flash*/
  6. extern uint8_t SPI_REC_BUF[512];
  7. /*Information structure*/
  8. at45db_t AT45DB;
  9. /**
  10. * @brief Initialize the external flash, with basic parameters and checks its availability.
  11. * @retval None.
  12. */
  13. void at45db_init()
  14. {
  15. memset(&AT45DB, 0, sizeof(AT45DB));
  16. uint16_t res = -1;
  17. uint8_t status_register[2] = {0};
  18. /*Check if the external flash memory is accessible*/
  19. res = at45db_read_man_id();
  20. printf("device.man.id: 0x%02X\r\n", res);
  21. if (!res)
  22. {
  23. /*External flash memory is not accessible*/
  24. printf("Unable to communicate with external flash. Initiate wake up process!\r\n");
  25. /*Wake up process*/
  26. res = at45db_wake_up_from_deep_sleep(AT45DB);
  27. if (!res)
  28. {
  29. /*Device could be in ultra deep sleep*/
  30. res = at45db_wake_up_from_ultra_deep_sleep(AT45DB);
  31. if (!res)
  32. {
  33. printf("Cannot wake up the external flash from ultra deep sleep\r\n");
  34. }
  35. else if (res)
  36. {
  37. printf("External flash memory woke up from ultra deep sleep\r\n");
  38. }
  39. }
  40. else if (res)
  41. {
  42. printf("External flash memory wake up from power down mode\r\n");
  43. }
  44. }
  45. else if (res)
  46. {
  47. printf("Correct device ID, external flash memory is accessible\r\n");
  48. }
  49. HAL_Delay(100);
  50. /*Initializa information structure*/
  51. #ifdef BINARY_PAGE_SIZE
  52. AT45DB.block_size = 2048;
  53. AT45DB.blocks = 256;
  54. AT45DB.flash_mbit = 4;
  55. AT45DB.page_size = 256;
  56. #endif
  57. #ifdef DATAFLASH_PAGE_SIZE
  58. AT45DB.block_size = 2112;
  59. AT45DB.blocks = 256;
  60. AT45DB.flash_mbit = 4;
  61. AT45DB.page_size = 264;
  62. #endif
  63. }
  64. /**
  65. * @brief Считывает один байт статус-регистра AT45DB041E.
  66. * @retval 1 байт статуса.
  67. *
  68. * Бит 7 (0x80) — RDY/BUSY: 1 = готов, 0 = занят
  69. * Бит 0 (0x01) — Page Size: 1 = binary (256 байт), 0 = standard (264 байта)
  70. */
  71. uint8_t at45db_get_status(void)
  72. {
  73. uint8_t cmd = STATUS_REGISTER;
  74. uint8_t status = 0;
  75. FLASH_CS_ENABLE();
  76. HAL_SPI_Transmit(&hspi2, &cmd, 1, HAL_MAX_DELAY);
  77. HAL_SPI_Receive(&hspi2, &status, 1, HAL_MAX_DELAY);
  78. FLASH_CS_DISABLE();
  79. return status;
  80. }
  81. /**
  82. * @brief Читает Manufacturer + Device ID.
  83. * @retval DEV_ID_OK или DEV_ID_ERROR.
  84. */
  85. dev_id_t at45db_read_man_id(void)
  86. {
  87. uint8_t opcode = MAN_ID_OPCD;
  88. uint8_t rec_buf[4] = {0};
  89. FLASH_CS_ENABLE();
  90. HAL_SPI_Transmit(&hspi2, &opcode, 1, HAL_MAX_DELAY);
  91. HAL_SPI_Receive(&hspi2, rec_buf, 4, HAL_MAX_DELAY);
  92. FLASH_CS_DISABLE();
  93. if (rec_buf[0] != 0x1F || rec_buf[1] != 0x24)
  94. return DEV_ID_ERROR;
  95. return DEV_ID_OK;
  96. }
  97. /**
  98. * @brief Проверяет текущий режим размера страницы.
  99. * @retval 256 если включён binary mode, 264 — если стандартный.
  100. */
  101. uint16_t at45db_get_page_size(void)
  102. {
  103. return (at45db_get_status() & 0x01) ? 256 : 264;
  104. }
  105. /**
  106. * @brief Проверяет, готов ли чип к новой операции.
  107. * @retval 1 — готов, 0 — занят.
  108. */
  109. int at45db_is_ready(void)
  110. {
  111. return (at45db_get_status() & 0x80) ? 1 : 0;
  112. }
  113. /**
  114. * @brief Wakes up external flash from deep sleep mode.
  115. * @param info : Structure information about the external flash operation.
  116. * @retval 1 for success, 0 on failure.
  117. */
  118. uint16_t at45db_wake_up_from_deep_sleep(at45db_t info)
  119. {
  120. uint16_t res = -1;
  121. uint8_t cmd = WAKE_UP_DEEP_SLEEP;
  122. FLASH_CS_ENABLE();
  123. HAL_SPI_Transmit(&hspi2, &cmd, 1, HAL_MAX_DELAY);
  124. FLASH_CS_DISABLE();
  125. // TODO: fix
  126. /*Return the MISO pin to its initial state*/
  127. // SET_BIT(GPIO_SPIx->MODER, (1U<<(SPIx_GPIO_MISO_PIN*2+1)));
  128. // CLEAR_BIT(GPIO_SPIx->MODER, (1U<<SPIx_GPIO_MISO_PIN*2));
  129. /*Read MAN-ID*/
  130. res = at45db_read_man_id();
  131. if (!res)
  132. {
  133. return 0;
  134. }
  135. info.state = _NORMAL_MODE;
  136. return 1;
  137. }
  138. /**
  139. * @brief Exit from ultra deep sleep.
  140. * @param info : Structure information about the external flash operation.
  141. * @retval 1 for success, 0 on failure.
  142. */
  143. uint16_t at45db_wake_up_from_ultra_deep_sleep(at45db_t info)
  144. {
  145. uint16_t res = -1;
  146. /*Select the device*/
  147. FLASH_CS_ENABLE();
  148. HAL_Delay(2);
  149. /*Release the device*/
  150. FLASH_CS_DISABLE();
  151. // TODO: fix
  152. /*Return the MISO pin to its initial state*/
  153. // SET_BIT(GPIO_SPIx->MODER, (1U<<(SPIx_GPIO_MISO_PIN*2+1)));
  154. // CLEAR_BIT(GPIO_SPIx->MODER, (1U<<SPIx_GPIO_MISO_PIN*2));
  155. /*Try to read MAD-ID*/
  156. res = at45db_read_man_id();
  157. if (!res)
  158. {
  159. /*Failure*/
  160. return 0;
  161. }
  162. /*Success*/
  163. info.state = _NORMAL_MODE;
  164. return 1;
  165. }
  166. void at45db_read(uint16_t page, uint8_t *data, uint16_t size)
  167. {
  168. uint8_t cmd[5];
  169. uint32_t addr = (uint32_t)page << 8;
  170. cmd[0] = 0x0B; // high-speed read
  171. cmd[1] = (addr >> 16) & 0xFF;
  172. cmd[2] = (addr >> 8) & 0xFF;
  173. cmd[3] = addr & 0xFF;
  174. cmd[4] = 0x00; // dummy
  175. FLASH_CS_ENABLE();
  176. HAL_SPI_Transmit(&hspi2, cmd, 5, HAL_MAX_DELAY);
  177. HAL_SPI_Receive(&hspi2, data, size, HAL_MAX_DELAY);
  178. FLASH_CS_DISABLE();
  179. }
  180. /**
  181. * @brief Enter flash into ultra deep sleep.
  182. * @param info : Structure information about the external flash operation.
  183. * @retval None.
  184. */
  185. void at45db_ultra_deep_sleep(at45db_t info)
  186. {
  187. uint8_t opcode = ULTRA_DEEP_SLEEP;
  188. /*Select the slave device*/
  189. FLASH_CS_ENABLE();
  190. /*Transmit the proper opcode*/
  191. HAL_SPI_Transmit(&hspi2, &opcode, 1, HAL_MAX_DELAY);
  192. /*Give some time to the system*/
  193. HAL_Delay(100);
  194. /*Release the device*/
  195. FLASH_CS_DISABLE();
  196. // TODO: fix
  197. /*Make the MISO pin analog, for power saving*/
  198. // SET_BIT(GPIO_SPIx->MODER, (1U<<(SPIx_GPIO_MISO_PIN*2+1)));
  199. // SET_BIT(GPIO_SPIx->MODER, (1U<<(SPIx_GPIO_MISO_PIN*2)));
  200. info.state = _U_DEEP_SLEEP;
  201. }
  202. void at45db_write(uint16_t page, uint8_t *data, uint16_t size)
  203. {
  204. uint8_t cmd[4];
  205. uint32_t addr = (uint32_t)page << 8;
  206. // 1. Запись во внутренний буфер
  207. cmd[0] = 0x84; cmd[1] = 0; cmd[2] = 0; cmd[3] = 0;
  208. FLASH_CS_ENABLE();
  209. HAL_SPI_Transmit(&hspi2, cmd, 4, HAL_MAX_DELAY);
  210. HAL_SPI_Transmit(&hspi2, data, size, HAL_MAX_DELAY);
  211. FLASH_CS_DISABLE();
  212. // 2. Перенос буфера в нужную страницу
  213. cmd[0] = 0x83;
  214. cmd[1] = (addr >> 16) & 0xFF;
  215. cmd[2] = (addr >> 8) & 0xFF;
  216. cmd[3] = addr & 0xFF;
  217. FLASH_CS_ENABLE();
  218. HAL_SPI_Transmit(&hspi2, cmd, 4, HAL_MAX_DELAY);
  219. FLASH_CS_DISABLE();
  220. // 3. Ждём готовности
  221. while (!(at45db_get_status() & 0x80))
  222. HAL_Delay(1);
  223. }
  224. void at45db_read_continuous(uint32_t addr, uint8_t *buffer, uint32_t size)
  225. {
  226. uint8_t cmd[8];
  227. /*Preparing the command*/
  228. cmd[0] = 0xE8; //Opcode
  229. cmd[1] = (addr >> 16) & 0xFF; // Address byte 1
  230. cmd[2] = (addr >> 8) & 0xFF; // Address byte 2
  231. cmd[3] = addr & 0xFF; // Address byte 3
  232. cmd[4] = 0x00; // Dummy byte 1
  233. cmd[5] = 0x00; // Dummy byte 2
  234. cmd[6] = 0x00; // Dummy byte 3
  235. cmd[7] = 0x00; // Dummy byte 4
  236. /*Select the external flash memory*/
  237. FLASH_CS_ENABLE();
  238. /*Send the proper commands to load data to the internal buffer 1*/
  239. HAL_SPI_Transmit(&hspi2, cmd, sizeof(cmd), HAL_MAX_DELAY);
  240. /*Receive the data*/
  241. HAL_SPI_Receive(&hspi2, buffer, size, HAL_MAX_DELAY);
  242. /*Deselect the external flash memory*/
  243. FLASH_CS_DISABLE();
  244. }
  245. /**
  246. * @brief Configure page size. Careful you only have 10000 times to do that.
  247. * @param mode : Set 1 for DataFlash (264 bytes), 2 for Binary (256 bytes).
  248. * @retval None.
  249. */
  250. void at45db_page_size_conf(uint16_t mode)
  251. {
  252. uint8_t cmd[4] = {0};
  253. cmd[0] = 0x3D;
  254. cmd[1] = 0x2A;
  255. cmd[2] = 0x80;
  256. /*Check user input*/
  257. if (mode == 1)
  258. {
  259. /*Data flash page size*/
  260. cmd[3] = 0xA7;
  261. FLASH_CS_ENABLE();
  262. HAL_SPI_Transmit(&hspi2, cmd, sizeof(cmd), HAL_MAX_DELAY);
  263. FLASH_CS_DISABLE();
  264. }
  265. else if (mode == 2)
  266. {
  267. /*Binary page size*/
  268. cmd[3] = 0xA6;
  269. FLASH_CS_ENABLE();
  270. HAL_SPI_Transmit(&hspi2, cmd, sizeof(cmd), HAL_MAX_DELAY);
  271. FLASH_CS_DISABLE();
  272. }
  273. }
  274. /**
  275. * @brief Perform chip erase. This command erase the entire main memory.
  276. * @retval None.
  277. */
  278. void at45db_chip_erase(void)
  279. {
  280. uint8_t cmd[4] = {0};
  281. int res = -1;
  282. cmd[0] = CHIP_ERASE_1;
  283. cmd[1] = CHIP_ERASE_2;
  284. cmd[2] = CHIP_ERASE_3;
  285. cmd[3] = CHIP_ERASE_4;
  286. FLASH_CS_ENABLE();
  287. HAL_SPI_Transmit(&hspi2, cmd, 4, HAL_MAX_DELAY);
  288. FLASH_CS_DISABLE();
  289. /*Check for fault operation*/
  290. res = at45db_fault_check();
  291. if (res == 1) {
  292. printf("There was a fault in erase operation...\n\r");
  293. }
  294. else if (res == 0) {
  295. printf("Successful, erase operation...\n\r");
  296. }
  297. }
  298. /**
  299. * @brief Checks if a fault erased after an erase or program operation.
  300. * @retval 1 if an error is detected, 0 otherwise.
  301. */
  302. uint16_t at45db_fault_check(void)
  303. {
  304. uint8_t status_register[2];
  305. uint8_t opcode = STATUS_REGISTER;
  306. FLASH_CS_ENABLE();
  307. HAL_SPI_Transmit(&hspi2, &opcode, 1, HAL_MAX_DELAY);
  308. HAL_SPI_Receive(&hspi2, status_register, 2, HAL_MAX_DELAY);
  309. FLASH_CS_DISABLE();
  310. /*Check the 5th bit of the second byte EPE bit*/
  311. if ((status_register[1] & EPE_BIT)) {
  312. /*Error detected*/
  313. return 1;
  314. }
  315. /*Success, in erasing external flash memory*/
  316. return 0;
  317. }
  318. /**
  319. * @brief This function erases a sector inside the external memory.
  320. * @param sector_num : This is the number of the sector you need to erase.
  321. * @retval None.
  322. */
  323. void at45db_sector_erase(uint8_t sector_num)
  324. {
  325. uint8_t opcode = SECTOR_ERASE;
  326. uint8_t address_byte[3];
  327. address_byte[0] = ((sector_num) << 3) & 0xF8;
  328. address_byte[1] = 0x00;
  329. address_byte[2] = 0x00;
  330. FLASH_CS_ENABLE();
  331. HAL_SPI_Transmit(&hspi2, &opcode, 1, HAL_MAX_DELAY);
  332. HAL_SPI_Transmit(&hspi2, address_byte, 3, HAL_MAX_DELAY);
  333. FLASH_CS_DISABLE();
  334. }
  335. /**
  336. * @brief Erases a specific page inside the main memory.
  337. * @reval None.
  338. */
  339. void at45db_page_erase(uint16_t page)
  340. {
  341. uint8_t cmd[3] = {0};
  342. uint8_t opcode = PAGE_ERASE_CMD;
  343. page = page << 9;
  344. FLASH_CS_ENABLE();
  345. HAL_SPI_Transmit(&hspi2, &opcode, 1, HAL_MAX_DELAY);
  346. /*Modify the proper data bits*/
  347. cmd[0] = (page >> 16) & 0xFF;
  348. cmd[1] = (page >> 8) & 0xFF;
  349. cmd[2] = page & 0xFF;
  350. HAL_SPI_Transmit(&hspi2, cmd, 3, HAL_MAX_DELAY);
  351. FLASH_CS_DISABLE();
  352. }
  353. /**
  354. * @brief Enter flash into deep sleep mode.
  355. * @param info : Structure information about the external flash operation.
  356. * @retval None.
  357. */
  358. void at45db_deep_sleep(at45db_t *info)
  359. {
  360. uint8_t opcode = DEEP_SLEEP;
  361. /*Select the device*/
  362. FLASH_CS_ENABLE();
  363. /*Transmit the command the external FLASH memory*/
  364. HAL_SPI_Transmit(&hspi2, &opcode, 1, HAL_MAX_DELAY);
  365. /*Give some time to process*/
  366. HAL_Delay(100);
  367. /*Release the slave device*/
  368. FLASH_CS_DISABLE();
  369. /*Give some time to the system*/
  370. HAL_Delay(2);
  371. //TODO: fix
  372. /*Make the MISO pin analog, for power saving*/
  373. // SET_BIT(GPIO_SPIx->MODER, (1U<<(SPIx_GPIO_MISO_PIN*2+1)));
  374. // SET_BIT(GPIO_SPIx->MODER, (1U<<(SPIx_GPIO_MISO_PIN*2)));
  375. }
  376. void at45db_wait_ready(void)
  377. {
  378. while (!(at45db_get_status() & 0x80)) {
  379. HAL_Delay(1);
  380. }
  381. }