flash_api.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. /* mbed Microcontroller Library
  2. * Copyright (c) 2017 ARM Limited
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "flash_api.h"
  17. #include "mbed_critical.h"
  18. #if DEVICE_FLASH
  19. #include "mbed_assert.h"
  20. #include "cmsis.h"
  21. /**
  22. * @brief Gets the page of a given address
  23. * @param Addr: Address of the FLASH Memory
  24. * @retval The page of a given address
  25. */
  26. static uint32_t GetPage(uint32_t Addr)
  27. {
  28. uint32_t page = 0;
  29. if (Addr < (FLASH_BASE + FLASH_BANK_SIZE)) {
  30. /* Bank 1 */
  31. page = (Addr - FLASH_BASE) / FLASH_PAGE_SIZE;
  32. } else {
  33. /* Bank 2 */
  34. page = (Addr - (FLASH_BASE + FLASH_BANK_SIZE)) / FLASH_PAGE_SIZE;
  35. }
  36. return page;
  37. }
  38. /**
  39. * @brief Gets the bank of a given address
  40. * @param Addr: Address of the FLASH Memory
  41. * @retval The bank of a given address
  42. */
  43. static uint32_t GetBank(uint32_t Addr)
  44. {
  45. uint32_t bank = 0;
  46. #if defined(SYSCFG_MEMRMP_FB_MODE)
  47. if (READ_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_FB_MODE) == 0) {
  48. /* No Bank swap */
  49. if (Addr < (FLASH_BASE + FLASH_BANK_SIZE)) {
  50. bank = FLASH_BANK_1;
  51. } else {
  52. bank = FLASH_BANK_2;
  53. }
  54. } else {
  55. /* Bank swap */
  56. if (Addr < (FLASH_BASE + FLASH_BANK_SIZE)) {
  57. bank = FLASH_BANK_2;
  58. } else {
  59. bank = FLASH_BANK_1;
  60. }
  61. }
  62. #else
  63. /* Device like L432KC */
  64. bank = FLASH_BANK_1;
  65. #endif
  66. return bank;
  67. }
  68. /** Initialize the flash peripheral and the flash_t object
  69. *
  70. * @param obj The flash object
  71. * @return 0 for success, -1 for error
  72. */
  73. int32_t flash_init(flash_t *obj)
  74. {
  75. return 0;
  76. }
  77. /** Uninitialize the flash peripheral and the flash_t object
  78. *
  79. * @param obj The flash object
  80. * @return 0 for success, -1 for error
  81. */
  82. int32_t flash_free(flash_t *obj)
  83. {
  84. return 0;
  85. }
  86. static int32_t flash_unlock(void)
  87. {
  88. /* Allow Access to Flash control registers and user Falsh */
  89. if (HAL_FLASH_Unlock()) {
  90. return -1;
  91. } else {
  92. return 0;
  93. }
  94. }
  95. static int32_t flash_lock(void)
  96. {
  97. /* Disable the Flash option control register access (recommended to protect
  98. the option Bytes against possible unwanted operations) */
  99. if (HAL_FLASH_Lock()) {
  100. return -1;
  101. } else {
  102. return 0;
  103. }
  104. }
  105. /** Erase one sector starting at defined address
  106. *
  107. * The address should be at sector boundary. This function does not do any check for address alignments
  108. * @param obj The flash object
  109. * @param address The sector starting address
  110. * @return 0 for success, -1 for error
  111. */
  112. int32_t flash_erase_sector(flash_t *obj, uint32_t address)
  113. {
  114. uint32_t FirstPage = 0, BankNumber = 0;
  115. uint32_t PAGEError = 0;
  116. FLASH_EraseInitTypeDef EraseInitStruct;
  117. int32_t status = 0;
  118. if ((address >= (FLASH_BASE + FLASH_SIZE)) || (address < FLASH_BASE)) {
  119. return -1;
  120. }
  121. if (flash_unlock() != HAL_OK) {
  122. return -1;
  123. }
  124. /* Clear OPTVERR bit set on virgin samples */
  125. __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
  126. /* Get the 1st page to erase */
  127. FirstPage = GetPage(address);
  128. /* MBED HAL erases 1 page / sector at a time */
  129. /* Get the bank */
  130. BankNumber = GetBank(address);
  131. /* Fill EraseInit structure*/
  132. EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
  133. EraseInitStruct.Banks = BankNumber;
  134. EraseInitStruct.Page = FirstPage;
  135. EraseInitStruct.NbPages = 1;
  136. /* Note: If an erase operation in Flash memory also concerns data in the data or instruction cache,
  137. you have to make sure that these data are rewritten before they are accessed during code
  138. execution. If this cannot be done safely, it is recommended to flush the caches by setting the
  139. DCRST and ICRST bits in the FLASH_CR register. */
  140. if (HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError) != HAL_OK) {
  141. status = -1;
  142. }
  143. flash_lock();
  144. return status;
  145. }
  146. /** Program one page starting at defined address
  147. *
  148. * The page should be at page boundary, should not cross multiple sectors.
  149. * This function does not do any check for address alignments or if size
  150. * is aligned to a page size.
  151. * @param obj The flash object
  152. * @param address The sector starting address
  153. * @param data The data buffer to be programmed
  154. * @param size The number of bytes to program
  155. * @return 0 for success, -1 for error
  156. */
  157. int32_t flash_program_page(flash_t *obj, uint32_t address,
  158. const uint8_t *data, uint32_t size)
  159. {
  160. uint32_t StartAddress = 0;
  161. int32_t status = 0;
  162. if ((address >= (FLASH_BASE + FLASH_SIZE)) || (address < FLASH_BASE)) {
  163. return -1;
  164. }
  165. if ((size % 8) != 0) {
  166. /* L4 flash devices can only be programmed 64bits/8 bytes at a time */
  167. return -1;
  168. }
  169. if (flash_unlock() != HAL_OK) {
  170. return -1;
  171. }
  172. /* Program the user Flash area word by word */
  173. StartAddress = address;
  174. /* HW needs an aligned address to program flash, which data
  175. * parameters doesn't ensure */
  176. if ((uint32_t) data % 4 != 0) {
  177. volatile uint64_t data64;
  178. while ((address < (StartAddress + size)) && (status == 0)) {
  179. for (uint8_t i = 0; i < 8; i++) {
  180. *(((uint8_t *) &data64) + i) = *(data + i);
  181. }
  182. if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, data64)
  183. == HAL_OK) {
  184. address = address + 8;
  185. data = data + 8;
  186. } else {
  187. status = -1;
  188. }
  189. }
  190. } else { /* case where data is aligned, so let's avoid any copy */
  191. while ((address < (StartAddress + size)) && (status == 0)) {
  192. if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address,
  193. *((uint64_t *) data))
  194. == HAL_OK) {
  195. address = address + 8;
  196. data = data + 8;
  197. } else {
  198. status = -1;
  199. }
  200. }
  201. }
  202. flash_lock();
  203. return status;
  204. }
  205. /** Get sector size
  206. *
  207. * @param obj The flash object
  208. * @param address The sector starting address
  209. * @return The size of a sector
  210. */
  211. uint32_t flash_get_sector_size(const flash_t *obj, uint32_t address)
  212. {
  213. /* considering 1 sector = 1 page */
  214. if ((address >= (FLASH_BASE + FLASH_SIZE)) || (address < FLASH_BASE)) {
  215. return MBED_FLASH_INVALID_SIZE;
  216. } else {
  217. return FLASH_PAGE_SIZE;
  218. }
  219. }
  220. /** Get page size
  221. *
  222. * @param obj The flash object
  223. * @param address The page starting address
  224. * @return The size of a page
  225. */
  226. uint32_t flash_get_page_size(const flash_t *obj)
  227. {
  228. /* Page size is the minimum programable size, which 8 bytes */
  229. return 8;
  230. }
  231. /** Get start address for the flash region
  232. *
  233. * @param obj The flash object
  234. * @return The start address for the flash region
  235. */
  236. uint32_t flash_get_start_address(const flash_t *obj)
  237. {
  238. return FLASH_BASE;
  239. }
  240. /** Get the flash region size
  241. *
  242. * @param obj The flash object
  243. * @return The flash region size
  244. */
  245. uint32_t flash_get_size(const flash_t *obj)
  246. {
  247. return FLASH_SIZE;
  248. }
  249. #endif