|
@@ -0,0 +1,93 @@
|
|
|
|
+#include "utils.h"
|
|
|
|
+
|
|
|
|
+/* Defines */
|
|
|
|
+#define WRITE_KEY1 0x45670123
|
|
|
|
+#define WRITE_KEY2 0xCDEF89AB
|
|
|
|
+
|
|
|
|
+/* Functions */
|
|
|
|
+flash_result_t Flash_Write(uint64_t * data) {
|
|
|
|
+ nt64_t val;
|
|
|
|
+ flash_result_t res = Flash_Ok;
|
|
|
|
+ uint32_t address = FLASH_PAGE_START;
|
|
|
|
+
|
|
|
|
+ val.u64 = *data;
|
|
|
|
+
|
|
|
|
+ // search first free cell
|
|
|
|
+ while ((address < FLASH_PAGE_END) || ((*(__IO uint32_t*)address) != 0xffffffff)) {
|
|
|
|
+ address += 8;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Authorize the FLASH Registers access */
|
|
|
|
+ FLASH->KEYR = WRITE_KEY1;
|
|
|
|
+ FLASH->KEYR = WRITE_KEY2;
|
|
|
|
+
|
|
|
|
+ /* verify Flash is unlock */
|
|
|
|
+ if (READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0x00U) {
|
|
|
|
+ res = Flash_Error;
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ if (address > FLASH_PAGE_END) {
|
|
|
|
+ // no space, format flash page
|
|
|
|
+ uint32_t tmp;
|
|
|
|
+
|
|
|
|
+ /* Get configuration register, then clear page number */
|
|
|
|
+ tmp = (FLASH->CR & ~FLASH_CR_PNB);
|
|
|
|
+
|
|
|
|
+ /* Set page number, Page Erase bit & Start bit */
|
|
|
|
+ FLASH->CR = (tmp | (FLASH_CR_STRT | (FLASH_PAGE_NMB << FLASH_CR_PNB_Pos) | FLASH_CR_PER));
|
|
|
|
+
|
|
|
|
+ /* Wait for end of page erase */
|
|
|
|
+ while ((FLASH->CR & FLASH_CR_STRT) != 0) { __NOP(); }
|
|
|
|
+
|
|
|
|
+ address = FLASH_PAGE_START;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // write data from address
|
|
|
|
+ /* Set PG bit */
|
|
|
|
+ FLASH->CR |= FLASH_CR_PG;
|
|
|
|
+
|
|
|
|
+ /* Program first word */
|
|
|
|
+ *(uint32_t *)address = val.u32[0];
|
|
|
|
+
|
|
|
|
+ /* Barrier to ensure programming is performed in 2 steps, in right order
|
|
|
|
+ (independently of compiler optimization behavior) */
|
|
|
|
+ __ISB();
|
|
|
|
+
|
|
|
|
+ /* Program second word */
|
|
|
|
+ *(uint32_t *)(address + 4U) = val.u32[1];
|
|
|
|
+
|
|
|
|
+ /* Set the LOCK Bit to lock the FLASH Registers access */
|
|
|
|
+ SET_BIT(FLASH->CR, FLASH_CR_LOCK);
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return res;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * @brief Read fom flash latest actual data.
|
|
|
|
+ * @param data
|
|
|
|
+ * @return flash_result_t
|
|
|
|
+ */
|
|
|
|
+flash_result_t Flash_Read(uint64_t * data) {
|
|
|
|
+ nt64_t val;
|
|
|
|
+ flash_result_t res = Flash_Ok;
|
|
|
|
+ uint32_t address = FLASH_PAGE_START;
|
|
|
|
+
|
|
|
|
+ while ((address < FLASH_PAGE_END) || ((*(__IO uint32_t*)address) != 0xffffffff)) {
|
|
|
|
+ val.u32[0] = (*(__IO uint32_t*)address);
|
|
|
|
+ address += 4;
|
|
|
|
+ val.u32[1] = (*(__IO uint32_t*)address);
|
|
|
|
+ address += 4;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ *data = val.u64;
|
|
|
|
+
|
|
|
|
+ if (address == FLASH_PAGE_START) {
|
|
|
|
+ res = Flash_PG_Clear;
|
|
|
|
+ } else if (address > FLASH_PAGE_END) {
|
|
|
|
+ res = Flash_PG_End;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return res;
|
|
|
|
+}
|