spi_flash.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. #include "at32f403a_407.h"
  2. #include "spi_flash.h"
  3. #include "spi_common.h"
  4. #include "FreeRTOS.h"
  5. #include "task.h"
  6. #include "common_config.h"
  7. #include <string.h>
  8. #include <stdio.h>
  9. #define SPI_FLASH SPI3
  10. #define INCLUDE_SPI_TEST 0
  11. #define CMD_WREN 0x06 // +
  12. #define CMD_WRDI 0x04 // +
  13. #define CMD_WRSR 0x01 // +
  14. #define CMD_RDSR 0x05 // +
  15. #define CMD_READ 0x03 // +
  16. #define CMD_SE 0x20 // + Block Erse 4 Kbytes
  17. #define CMD_BE 0x52 // Block Erase 32 Kbytes
  18. #define CMD_CE 0x60 // + Chip Erase
  19. #define CMD_PP 0x02 // + Byte/Page Program (1 to 256 Bytes)
  20. #define CMD_RDSFDP 0x5A // - not used for FLASH_TYPE_AT25SF161
  21. #define SR_WIP (1 << 0)
  22. #define SR_WEL (1 << 1)
  23. #define SR_SRWD (1 << 7)
  24. spi_flash_desc_t spi_flash_desc;
  25. //
  26. static uint8_t spi_tx_rx(uint8_t byte)
  27. {
  28. return common_spi_tx_rx(SPI_FLASH, byte);
  29. }
  30. //
  31. static inline void wait_write_enable(void)
  32. {
  33. uint8_t status;
  34. SPI_FLASH_CS_L();
  35. spi_tx_rx(CMD_RDSR);
  36. do {
  37. status = spi_tx_rx(0);
  38. } while (!(status & SR_WEL));
  39. SPI_FLASH_CS_H();
  40. }
  41. //
  42. static inline void wait_write_end(void)
  43. {
  44. uint8_t status;
  45. SPI_FLASH_CS_L();
  46. spi_tx_rx(CMD_RDSR);
  47. do {
  48. status = spi_tx_rx(0);
  49. } while (status & SR_WIP);
  50. SPI_FLASH_CS_H();
  51. }
  52. //
  53. static inline void send_addr(int addr)
  54. {
  55. spi_tx_rx((addr >> 16) & 0xFF);
  56. spi_tx_rx((addr >> 8) & 0xFF);
  57. spi_tx_rx(addr & 0xFF);
  58. }
  59. //
  60. static int spi_flash_read_sfdp(int addr, void *buf, size_t len)
  61. {
  62. uint8_t *ptr = (uint8_t*)buf;
  63. SPI_FLASH_CS_L();
  64. spi_tx_rx(CMD_RDSFDP);
  65. send_addr(addr);
  66. spi_tx_rx(0);
  67. while (len--)
  68. *ptr++ = spi_tx_rx(0);
  69. SPI_FLASH_CS_H();
  70. return 0;
  71. }
  72. //
  73. ssize_t spi_flash_read(int addr, void *buf, size_t len, uint32_t timeout)
  74. {
  75. uint8_t *ptr = (uint8_t*)buf;
  76. (void)timeout;
  77. SPI_FLASH_CS_L();
  78. spi_tx_rx(CMD_READ);
  79. send_addr(addr);
  80. while (len--)
  81. *ptr++ = spi_tx_rx(0);
  82. SPI_FLASH_CS_H();
  83. return len;
  84. }
  85. #define TIMEOUT 10000
  86. uint16_t spi_flash_pp(int addr, const void *buf, size_t len, uint32_t timeout)
  87. {
  88. uint8_t *ptr = (uint8_t*)buf;
  89. (void)timeout;
  90. ssize_t ret = 0;
  91. if ((addr & 0xFF) + len > 0xFF)
  92. len = 0x100 - (addr & 0xFF);
  93. ret = len;
  94. SPI_FLASH_CS_L();
  95. spi_tx_rx(CMD_WREN);
  96. SPI_FLASH_CS_H();
  97. wait_write_enable();
  98. SPI_FLASH_CS_L();
  99. spi_tx_rx(CMD_PP);
  100. send_addr(addr);
  101. while (len--)
  102. spi_tx_rx(*ptr++);
  103. SPI_FLASH_CS_H();
  104. wait_write_end();
  105. return ret;
  106. }
  107. //
  108. ssize_t spi_flash_write(int addr, const void *buf, size_t len, uint32_t timeout)
  109. {
  110. (void)timeout;
  111. int ret = 0, offset = 0;
  112. do {
  113. ret = spi_flash_pp(addr + offset, (uint8_t*)buf + offset, len - offset, 0);
  114. offset += ret;
  115. } while (len - offset);
  116. return 0;
  117. }
  118. //
  119. int spi_flash_chip_erase(uint32_t timeout)
  120. {
  121. (void)timeout;
  122. SPI_FLASH_CS_L();
  123. spi_tx_rx(CMD_WREN);
  124. SPI_FLASH_CS_H();
  125. wait_write_enable();
  126. SPI_FLASH_CS_L();
  127. spi_tx_rx(CMD_CE);
  128. SPI_FLASH_CS_H();
  129. wait_write_end();
  130. return 0;
  131. }
  132. //
  133. int spi_flash_erase_sector(int addr, uint32_t timeout)
  134. {
  135. (void)timeout;
  136. SPI_FLASH_CS_L();
  137. spi_tx_rx(CMD_WREN);
  138. SPI_FLASH_CS_H();
  139. wait_write_enable();
  140. SPI_FLASH_CS_L();
  141. spi_tx_rx(CMD_SE);
  142. send_addr(addr);
  143. SPI_FLASH_CS_H();
  144. wait_write_end();
  145. return 0;
  146. }
  147. //
  148. unsigned int spi_flash_get_sector_size(void) {
  149. return spi_flash_desc.sector_size;
  150. }
  151. //
  152. unsigned int spi_flash_get_sector_count(void) {
  153. return spi_flash_desc.sector_count;
  154. }
  155. //
  156. unsigned int spi_flash_get_total_size(void) {
  157. return spi_flash_desc.sector_count * spi_flash_desc.sector_size;
  158. }
  159. //
  160. bool spi_flash_is_init(void) {
  161. return spi_flash_desc.present;
  162. }
  163. //
  164. bool spi_flash_init(void)
  165. {
  166. spi_flash_desc.sector_size = SPI_FLASH_SECTOR_SIZE;
  167. spi_flash_desc.sector_erase_op = 32;
  168. spi_flash_desc.sector_count = 512;
  169. spi_flash_desc.present = true;
  170. return true;
  171. }
  172. // -------------------------------------------------------------------------- //
  173. #if INCLUDE_SPI_TEST
  174. const uint8_t txbuf1[] = "This film came out on DVD yesterday and I rushed to buy it. \
  175. This version is the first to render all the detail and perfection \
  176. of Jack Cardiff's amazing compositions and brilliant, varied photography. \
  177. As a collection of memorable images, this film is better than any comparable \
  178. historical epic of the period and even gives GWTW a run for its money. \
  179. King Vidor's direction is a series of 'tableaux vivants' where the \
  180. characters are not posing but acting in a very natural, period-specific way. \
  181. I have never had a problem with this adaptation of Tolstoy's novel. \
  182. I think it is a wonderful introduction to the period and the novel and that \
  183. it is a very poetic, very original work in its own right. Henry Fonda's \
  184. characterization is especially moving, including great memorable interactions \
  185. with/reations to Mel Ferrer, Audrey Hepburn, Helmut Dantine and John Mills, but \
  186. all members of the cast are actually perfect. The harrowing last 45 minutes of \
  187. the film manage to convey a sense of history, a sense of grandeur as well as to \
  188. communicate very clearly Tolstoy's ideas about the meaning of life, by relying \
  189. mostly on the power of memorable images. The most conspicuous handicap of this movie, \
  190. in my opinion, is its soundtrack (in glorious mono). The barely hi-fi recording of \
  191. dialogues and music sounds pinched, hollow and tinny and it always has in very version \
  192. I have ever seen: in the theatres, on TV and on video. Even the soundtrack album is \
  193. an atrocity. In some scenes, before the necessary adjustments of bass and treble, \
  194. Audrey Hepburn's and Mel Ferrer's voices actually hurt your ear. Nino Rota's very \
  195. Russian-sounding score is serviceable and melodic, although rather sparse in its \
  196. orchestration and in the number of players. One can only wonder what 'War and Peace' \
  197. could have sounded like with a cohort of Hollywood arrangers, decent recording facilities \
  198. and lavish, varied orchestrations in true high fidelity and stereophonic sound. \
  199. According to Lukas Kendall of 'Film Score Monthly', the original recording elements \
  200. of the soundtrack have long ago disappeared, which is the common lot of international, \
  201. independent co-productions of the era. Someone somewhere is certainly guilty of \
  202. skimping on quality or embezzlement for this 1956 movie to sound so much worse \
  203. than a 1939, pre-hi-fi epic like GWTW. Like all VistaVision films, this one was \
  204. meant to be shown in Perspecta Stereophonic Sound where the mono dialog track was \
  205. meant to be channelled to three different directions, making it directional, while \
  206. the separate mono music + sound effects track was generally directed to all three \
  207. speakers at the same time. The results fooled the viewers into thinking everything \
  208. was in true stereo and the reproduction of the music was usually in very high fidelity. \
  209. Maybe the soundtrack used on the DVD is a mono reduction of those two separate tracks \
  210. that has squandered that fidelity and maybe the DVD can be issued again with better \
  211. results in some kind of 4.0 presentation. When they do, very little electronic \
  212. restoration work will be needed to make the image absolutely perfect. \
  213. But let's concentrate on the positive: This film is a summit of visual \
  214. splendour and its sets, costumes, colour photography, composition and lighting \
  215. achieve, in every single scene, wonders of artistry, creativity and delicacy \
  216. But let's concentrate on the positive: This film is a summit of visual \
  217. splendour and its sets, costumes, colour photography, composition and lighting \
  218. achieve, in every single scene, wonders of artistry, creativity and delicacy \
  219. that will probably never be equalled. Suffice it to say that it has, \
  220. among many other treasures, a sunrise duel scene in the snow that still has viewers \
  221. wondering whether it was shot outdoors or in a studio and that will have them wondering foreverhsgkhgkshgu.\r\n";
  222. #define countof(a) (sizeof(a) / sizeof(*(a)))
  223. #define bufsize1 (countof(txbuf1)-1)
  224. uint8_t rxbuf1[bufsize1] = {0};
  225. bool spi_flash_test(void) {
  226. if (!spi_flash_is_init()) {
  227. return false;
  228. }
  229. const unsigned int sector_count = spi_flash_get_sector_count();
  230. const unsigned int sector_size = spi_flash_get_sector_size();
  231. const unsigned int total_size = spi_flash_get_total_size();
  232. printf("Present: %u sectors, %u bytes per sector (%u bytes total)\r\n",
  233. sector_count, sector_size, total_size);
  234. for (uint16_t i = 0; i < sector_count; i++) {
  235. printf("sector: %u/%u ", i, sector_count);
  236. spi_flash_erase_sector(i * sector_size, 0);
  237. spi_flash_write(i * sector_size, txbuf1, bufsize1, 0);
  238. memset(rxbuf1, 0, bufsize1);
  239. spi_flash_read(i * sector_size, rxbuf1, bufsize1, 0);
  240. if (memcmp(txbuf1, rxbuf1, bufsize1) != 0) {
  241. printf("fail\r\n");
  242. return false;
  243. }
  244. printf("ok\r\n");
  245. }
  246. printf("\r\nDone\r\n");
  247. return true;
  248. }
  249. #endif