at45db041.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  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. }
  221. void at45db_read_continuous(uint32_t addr, uint8_t *buffer, uint32_t size)
  222. {
  223. uint8_t cmd[8];
  224. /*Preparing the command*/
  225. cmd[0] = 0xE8; //Opcode
  226. cmd[1] = (addr >> 16) & 0xFF; // Address byte 1
  227. cmd[2] = (addr >> 8) & 0xFF; // Address byte 2
  228. cmd[3] = addr & 0xFF; // Address byte 3
  229. cmd[4] = 0x00; // Dummy byte 1
  230. cmd[5] = 0x00; // Dummy byte 2
  231. cmd[6] = 0x00; // Dummy byte 3
  232. cmd[7] = 0x00; // Dummy byte 4
  233. /*Select the external flash memory*/
  234. FLASH_CS_ENABLE();
  235. /*Send the proper commands to load data to the internal buffer 1*/
  236. HAL_SPI_Transmit(&hspi2, cmd, sizeof(cmd), HAL_MAX_DELAY);
  237. /*Receive the data*/
  238. HAL_SPI_Receive(&hspi2, buffer, size, HAL_MAX_DELAY);
  239. /*Deselect the external flash memory*/
  240. FLASH_CS_DISABLE();
  241. }
  242. /**
  243. * @brief Configure page size. Careful you only have 10000 times to do that.
  244. * @param mode : Set 1 for DataFlash (264 bytes), 2 for Binary (256 bytes).
  245. * @retval None.
  246. */
  247. void at45db_page_size_conf(uint16_t mode)
  248. {
  249. uint8_t cmd[4] = {0};
  250. cmd[0] = 0x3D;
  251. cmd[1] = 0x2A;
  252. cmd[2] = 0x80;
  253. /*Check user input*/
  254. if (mode == 1)
  255. {
  256. /*Data flash page size*/
  257. cmd[3] = 0xA7;
  258. FLASH_CS_ENABLE();
  259. HAL_SPI_Transmit(&hspi2, cmd, sizeof(cmd), HAL_MAX_DELAY);
  260. FLASH_CS_DISABLE();
  261. }
  262. else if (mode == 2)
  263. {
  264. /*Binary page size*/
  265. cmd[3] = 0xA6;
  266. FLASH_CS_ENABLE();
  267. HAL_SPI_Transmit(&hspi2, cmd, sizeof(cmd), HAL_MAX_DELAY);
  268. FLASH_CS_DISABLE();
  269. }
  270. }
  271. /**
  272. * @brief Perform chip erase. This command erase the entire main memory.
  273. * @retval None.
  274. */
  275. void at45db_chip_erase(void)
  276. {
  277. uint8_t cmd[4] = {0};
  278. int res = -1;
  279. cmd[0] = CHIP_ERASE_1;
  280. cmd[1] = CHIP_ERASE_2;
  281. cmd[2] = CHIP_ERASE_3;
  282. cmd[3] = CHIP_ERASE_4;
  283. FLASH_CS_ENABLE();
  284. HAL_SPI_Transmit(&hspi2, cmd, 4, HAL_MAX_DELAY);
  285. FLASH_CS_DISABLE();
  286. /*Check for fault operation*/
  287. res = at45db_fault_check();
  288. if (res == 1) {
  289. printf("There was a fault in erase operation...\n\r");
  290. }
  291. else if (res == 0) {
  292. printf("Successful, erase operation...\n\r");
  293. }
  294. }
  295. /**
  296. * @brief Checks if a fault erased after an erase or program operation.
  297. * @retval 1 if an error is detected, 0 otherwise.
  298. */
  299. uint16_t at45db_fault_check(void)
  300. {
  301. uint8_t status_register[2];
  302. uint8_t opcode = STATUS_REGISTER;
  303. FLASH_CS_ENABLE();
  304. HAL_SPI_Transmit(&hspi2, &opcode, 1, HAL_MAX_DELAY);
  305. HAL_SPI_Receive(&hspi2, status_register, 2, HAL_MAX_DELAY);
  306. FLASH_CS_DISABLE();
  307. /*Check the 5th bit of the second byte EPE bit*/
  308. if ((status_register[1] & EPE_BIT)) {
  309. /*Error detected*/
  310. return 1;
  311. }
  312. /*Success, in erasing external flash memory*/
  313. return 0;
  314. }
  315. /**
  316. * @brief This function erases a sector inside the external memory.
  317. * @param sector_num : This is the number of the sector you need to erase.
  318. * @retval None.
  319. */
  320. void at45db_sector_erase(uint8_t sector_num)
  321. {
  322. uint8_t opcode = SECTOR_ERASE;
  323. uint8_t address_byte[3];
  324. address_byte[0] = ((sector_num) << 3) & 0xF8;
  325. address_byte[1] = 0x00;
  326. address_byte[2] = 0x00;
  327. FLASH_CS_ENABLE();
  328. HAL_SPI_Transmit(&hspi2, &opcode, 1, HAL_MAX_DELAY);
  329. HAL_SPI_Transmit(&hspi2, address_byte, 3, HAL_MAX_DELAY);
  330. FLASH_CS_DISABLE();
  331. }
  332. /**
  333. * @brief Erases a specific page inside the main memory.
  334. * @reval None.
  335. */
  336. void at45db_page_erase(uint16_t page)
  337. {
  338. uint8_t cmd[3] = {0};
  339. uint8_t opcode = PAGE_ERASE_CMD;
  340. page = page << 9;
  341. FLASH_CS_ENABLE();
  342. HAL_SPI_Transmit(&hspi2, &opcode, 1, HAL_MAX_DELAY);
  343. /*Modify the proper data bits*/
  344. cmd[0] = (page >> 16) & 0xFF;
  345. cmd[1] = (page >> 8) & 0xFF;
  346. cmd[2] = page & 0xFF;
  347. HAL_SPI_Transmit(&hspi2, cmd, 3, HAL_MAX_DELAY);
  348. FLASH_CS_DISABLE();
  349. }
  350. /**
  351. * @brief Enter flash into deep sleep mode.
  352. * @param info : Structure information about the external flash operation.
  353. * @retval None.
  354. */
  355. void at45db_deep_sleep(at45db_t *info)
  356. {
  357. uint8_t opcode = DEEP_SLEEP;
  358. /*Select the device*/
  359. FLASH_CS_ENABLE();
  360. /*Transmit the command the external FLASH memory*/
  361. HAL_SPI_Transmit(&hspi2, &opcode, 1, HAL_MAX_DELAY);
  362. /*Give some time to process*/
  363. HAL_Delay(100);
  364. /*Release the slave device*/
  365. FLASH_CS_DISABLE();
  366. /*Give some time to the system*/
  367. HAL_Delay(2);
  368. //TODO: fix
  369. /*Make the MISO pin analog, for power saving*/
  370. // SET_BIT(GPIO_SPIx->MODER, (1U<<(SPIx_GPIO_MISO_PIN*2+1)));
  371. // SET_BIT(GPIO_SPIx->MODER, (1U<<(SPIx_GPIO_MISO_PIN*2)));
  372. }
  373. void at45db_wait_ready(void)
  374. {
  375. while (!(at45db_get_status() & 0x80)) {
  376. HAL_Delay(1);
  377. }
  378. }