• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 ASR Microelectronics (Shanghai) Co., Ltd. All rights reserved.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <stdio.h>
17 #include <string.h>
18 #include <errno.h>
19 #include "duet_cm4.h"
20 #include "duet_flash_alg.h"
21 #include "duet_flash.h"
22 
23 #ifndef OS_NOT_SUPPORT
24 #ifdef ALIOS_SUPPORT
25 #include "lega_rhino.h"
26 #else
27 #include "lega_rtos.h"
28 #endif
29 #endif
30 #define FLASH_ACCESS_CONTROL0_DEFAULT_VALUE 0x37053977
31 #define FLASH_ACCESS_CONTROL1_DEFAULT_VALUE 0x000014e5
32 extern const duet_logic_partition_t duet_partitions[];
33 
34 #define WRITE_FLAG 1
35 #define ERASE_FLAG 0
36 #define ROUND_DOWN(x, align) ((unsigned long)(x) & ~((unsigned long)(align) - 1))
37 
flash_layout_judge(uint32_t addr)38 static duet_partition_t flash_layout_judge(uint32_t addr)
39 {
40     duet_partition_t out_partition;
41     if (addr < BOOTLOADER_FLASH_START_ADDR) {
42         out_partition = PARTITION_ERROR;
43     } else if (addr >= BOOTLOADER_FLASH_START_ADDR && addr < BOOTLOADER_FLASH_START_ADDR + BOOTLOADER_MAX_SIZE) {
44         out_partition = PARTITION_BOOTLOADER;
45     } else if (addr >= INFO_FLASH_START_ADDR && addr < INFO_FLASH_START_ADDR + INFO_MAX_SIZE) {
46         out_partition = PARTITION_PARAMETER_1;
47     }
48 #if (defined ALIOS_SUPPORT) || (defined _LEGA_BOOTLOADER_) || (defined HARMONYOS_SUPPORT)
49     else if (addr >= KV_FLASH_START_ADDR && addr < KV_FLASH_START_ADDR + KV_MAX_SIZE) {
50         out_partition = PARTITION_PARAMETER_2;
51     }
52 #else
53     else if (addr >= KV_FLASH_START_ADDR && addr < KV_FLASH_START_ADDR + KV_MAX_SIZE) {
54         out_partition = PARTITION_PARAMETER_2;
55     } else if (addr >= USER_FLASH_START_ADDR && addr < USER_FLASH_START_ADDR + USER_FLASH_MAX_SIZE) {
56         out_partition = PARTITION_PARAMETER_3;
57     }
58 #endif
59     else if ((addr >= CUST1_FLASH_START_ADDR) && (addr < CUST1_FLASH_START_ADDR + CUST1_MAX_SIZE)) {
60         out_partition = PARTITION_CUSTOM_1;
61     } else if (addr >= MIDEA_INFO_START_ADDR && addr < MIDEA_INFO_START_ADDR + MIDEA_INFO_MAX_SIZE) {
62         out_partition = PARTITION_PARAMETER_3;
63     } else if (addr >= MIDEA_INFO_BKUP_START_ADDR && addr < MIDEA_INFO_BKUP_START_ADDR + MIDEA_INFO_BKUP_MAX_SIZE) {
64         out_partition = PARTITION_PARAMETER_4;
65     } else if (addr >= APP_FLASH_START_ADDR && addr < APP_FLASH_START_ADDR + APP_MAX_SIZE) {
66         out_partition = PARTITION_APPLICATION;
67     } else if (addr >= OTA_FLASH_START_ADDR && addr < OTA_FLASH_START_ADDR + OTA_MAX_SIZE) {
68         out_partition = PARTITION_OTA_TEMP;
69     }
70 #ifdef MS_CONFIG_OTA_SUPPORT
71     else if (addr >= OTA_MCU_FLASH_START_ADDR && addr < OTA_MCU_FLASH_START_ADDR + OTA_MCU_MAX_SIZE) {
72         out_partition = PARTITION_OTA_MCU;
73     } else if (addr >= OTA_PARA_START_ADDR && addr < OTA_PARA_START_ADDR + OTA_PARA_MAX_SIZE) {
74         out_partition = PARTITION_OTA_PARA;
75     } else if (addr >= OTA_HEAD_PARA_START_ADDR && addr < OTA_HEAD_PARA_START_ADDR + OTA_HEAD_PARA_MAX_SIZE) {
76         out_partition = PARTITION_OTA_HEAD_PARA;
77     }
78 #endif
79     else if (addr >= NVDS_FLASH_START_ADDR && addr < NVDS_FLASH_START_ADDR + NVDS_MAX_SIZE) {
80         out_partition = PARTITION_PARAMETER_5;
81     } else {
82         out_partition = PARTITION_ERROR;
83     }
84     return out_partition;
85 }
refresh_flash_sector(duet_partition_t current_partition,uint32_t sector_offset,uint32_t start_offset,unsigned char * buf,uint32_t len,uint32_t flag)86 static int32_t refresh_flash_sector(duet_partition_t current_partition, uint32_t sector_offset, uint32_t start_offset,
87                                     unsigned char *buf, uint32_t len, uint32_t flag)
88 {
89     int32_t ret = 0;
90     duet_partition_t tran_partition;
91 #ifdef OS_NOT_SUPPORT
92     char tmpbuf[SPI_FLASH_SEC_SIZE] = {0};
93 #else
94     char *tmpbuf = (char *)lega_rtos_malloc((uint32_t)SPI_FLASH_SEC_SIZE);
95 #endif
96     char *pend = NULL;
97     uint32_t sector_start = sector_offset;
98     uint32_t end_offset = start_offset + len;
99     memset(tmpbuf, 0, SPI_FLASH_SEC_SIZE);
100     if ((FLASH_ACCESS_CONTROL0_DEFAULT_VALUE == FLASH_ACCESS_CONTROL0)
101         && (FLASH_ACCESS_CONTROL1_DEFAULT_VALUE == FLASH_ACCESS_CONTROL1)) { // default flash remapping
102         tran_partition = current_partition;
103     } else {
104         if (current_partition == PARTITION_OTA_TEMP) {
105             tran_partition = PARTITION_APPLICATION;
106         } else if (current_partition == PARTITION_APPLICATION) {
107             tran_partition = PARTITION_OTA_TEMP;
108         } else {
109             tran_partition = current_partition;
110         }
111     }
112     ret = duet_flash_read(tran_partition, &sector_start, tmpbuf, SPI_FLASH_SEC_SIZE);
113     if (ret != 0) {
114         printf("flash_read error\n");
115 #ifndef OS_NOT_SUPPORT
116         lega_rtos_free(tmpbuf);
117 #endif
118         return ret;
119     }
120     sector_start = sector_offset;
121     ret = duet_flash_erase(current_partition, sector_start, SPI_FLASH_SEC_SIZE);
122     if (ret != 0) {
123         printf("flash_erase error\n");
124 #ifndef OS_NOT_SUPPORT
125         lega_rtos_free(tmpbuf);
126 #endif
127         return ret;
128     }
129     if (flag == WRITE_FLAG) {
130         memcpy(tmpbuf + start_offset - sector_offset, buf, len);
131         sector_start = sector_offset;
132         ret = duet_flash_write(current_partition, &sector_start, tmpbuf, SPI_FLASH_SEC_SIZE);
133         if (ret != 0) {
134             printf("flash_write error\n");
135 #ifndef OS_NOT_SUPPORT
136             lega_rtos_free(tmpbuf);
137 #endif
138             return ret;
139         }
140     } else if (flag == ERASE_FLAG) {
141         if (sector_offset < start_offset) {
142             sector_start = sector_offset;
143             ret = duet_flash_write(current_partition, &sector_start, tmpbuf, start_offset - sector_offset);
144             if (ret != 0) {
145                 printf("flash_write error\n");
146 #ifndef OS_NOT_SUPPORT
147                 lega_rtos_free(tmpbuf);
148 #endif
149                 return ret;
150             }
151         }
152         if (end_offset - sector_offset < SPI_FLASH_SEC_SIZE) {
153             pend = tmpbuf + start_offset - sector_offset + len;
154             ret = duet_flash_write(current_partition, &end_offset, pend, SPI_FLASH_SEC_SIZE - (end_offset - sector_offset));
155             if (ret != 0) {
156                 printf("flash_write error\n");
157 #ifndef OS_NOT_SUPPORT
158                 lega_rtos_free(tmpbuf);
159 #endif
160                 return ret;
161             }
162         }
163     }
164 #ifndef OS_NOT_SUPPORT
165     lega_rtos_free(tmpbuf);
166 #endif
167     return ret;
168 }
169 /**
170  * lega flash init
171  *
172  * @note this function must be called before flash erase/write operation
173  *       also, this function must not be interrupted, it should be called
174  *       with interrupt disabled
175  * @param[in]  none
176  *
177  * @return     HAL_logi_partition struct
178  */
duet_flash_init(void)179 int32_t duet_flash_init(void)
180 {
181     return duet_flash_alg_init();
182 }
183 /**
184  * Get the infomation of the specified flash area
185  *
186  * @param[in]  in_partition  The target flash logical partition
187  *
188  * @return     HAL_logi_partition struct
189  */
duet_flash_get_info(duet_partition_t in_partition)190 duet_logic_partition_t *duet_flash_get_info(duet_partition_t in_partition)
191 {
192     duet_logic_partition_t *logic_partition;
193 
194     logic_partition = (duet_logic_partition_t *)&duet_partitions[ in_partition ];
195 
196     return logic_partition;
197 }
198 
199 /**
200  * Erase an area on a Flash logical partition
201  *
202  * @note  Erase on an address will erase all data on a sector that the
203  *        address is belonged to, this function does not save data that
204  *        beyond the address area but in the affected sector, the data
205  *        will be lost.
206  *        this function must not be interrupted, it should be called with
207  *        interrupt disabled
208  *
209  * @param[in]  in_partition  The target flash logical partition which should be erased
210  * @param[in]  off_set       Start address of the erased flash area
211  * @param[in]  size          Size of the erased flash area
212  *
213  * @return  0 : On success, EIO : If an error occurred with any step
214  */
duet_flash_erase(duet_partition_t in_partition,uint32_t off_set,uint32_t size)215 int32_t duet_flash_erase(duet_partition_t in_partition, uint32_t off_set, uint32_t size)
216 {
217     uint32_t addr;
218     uint32_t start_addr, end_addr;
219     int32_t ret = 0;
220     duet_logic_partition_t *partition_info;
221 
222     partition_info = duet_flash_get_info(in_partition);
223     if (size + off_set > partition_info->partition_length) {
224         return EIO;
225     }
226 
227     start_addr = ROUND_DOWN((partition_info->partition_start_addr + off_set), SPI_FLASH_SEC_SIZE);
228     end_addr = ROUND_DOWN((partition_info->partition_start_addr + off_set + size - 1), SPI_FLASH_SEC_SIZE);
229 
230     size = end_addr - start_addr + SPI_FLASH_SEC_SIZE;
231     addr = start_addr;
232     while (size) {
233         if (!(addr % SPI_FLASH_BLOCK_64K_SIZE) && (size > (SPI_FLASH_BLOCK_64K_SIZE - SPI_FLASH_SEC_SIZE))) {
234             ret = duet_flash_alg_erase(BLOCK64_ERASE_CMD, addr); // 250ms
235             if (ret != 0) {
236                 return ret;
237             }
238             addr += SPI_FLASH_BLOCK_64K_SIZE;
239             if (size > SPI_FLASH_BLOCK_64K_SIZE) {
240                 size -= SPI_FLASH_BLOCK_64K_SIZE;
241             } else {
242                 size = 0;
243             }
244         } else if (!(addr % SPI_FLASH_BLOCK_32K_SIZE) && (size > (SPI_FLASH_BLOCK_32K_SIZE - SPI_FLASH_SEC_SIZE))) {
245             ret = duet_flash_alg_erase(BLOCK32_ERASE_CMD, addr); // 170ms
246             if (ret != 0) {
247                 return ret;
248             }
249             addr += SPI_FLASH_BLOCK_32K_SIZE;
250             if (size > SPI_FLASH_BLOCK_32K_SIZE) {
251                 size -= SPI_FLASH_BLOCK_32K_SIZE;
252             } else {
253                 size = 0;
254             }
255         } else {
256             ret = duet_flash_alg_erase(SECTOR_ERASE_CMD, addr); // 100ms
257             if (ret != 0) {
258                 return ret;
259             }
260             addr += SPI_FLASH_SEC_SIZE;
261             if (size > SPI_FLASH_SEC_SIZE) {
262                 size -= SPI_FLASH_SEC_SIZE;
263             } else {
264                 size = 0;
265             }
266         }
267     }
268 
269     return 0;
270 }
271 
272 /**
273  * Write data to an area on a flash logical partition without erase
274  *
275  * @note this function must not be interrupted, it should be called with
276  *       interrupt disabled
277  *
278  * @param[in]  in_partition    The target flash logical partition which should be read which should be written
279  * @param[in]  off_set         Point to the start address that the data is written to, and
280  *                             point to the last unwritten address after this function is
281  *                             returned, so you can call this function serval times without
282  *                             update this start address.
283  * @param[in]  inBuffer        point to the data buffer that will be written to flash
284  * @param[in]  inBufferLength  The length of the buffer
285  *
286  * @return  0 : On success, EIO : If an error occurred with any step
287  */
duet_flash_write(duet_partition_t in_partition,uint32_t * off_set,const void * in_buf,uint32_t in_buf_len)288 int32_t duet_flash_write(duet_partition_t in_partition, uint32_t *off_set,
289                          const void *in_buf, uint32_t in_buf_len)
290 {
291     uint32_t start_addr, end_addr;
292     duet_logic_partition_t *partition_info;
293     uint8_t *p_buf = (uint8_t *)(in_buf);
294     uint32_t prg_size;
295     uint32_t left_buf_len = in_buf_len;
296 
297     partition_info = duet_flash_get_info(in_partition);
298     if (off_set == NULL || in_buf == NULL || ((*off_set + in_buf_len) > partition_info->partition_length)) {
299         // ptr and size over range check
300         return EIO;
301     }
302     start_addr = partition_info->partition_start_addr + *off_set;
303     end_addr = start_addr + left_buf_len;
304 
305     while (left_buf_len > 0) {
306         if ((end_addr / SPI_FLASH_PAGE_SIZE) > (start_addr / SPI_FLASH_PAGE_SIZE)) {
307             prg_size = SPI_FLASH_PAGE_SIZE - (start_addr % SPI_FLASH_PAGE_SIZE);
308         } else {
309             prg_size = left_buf_len;
310         }
311         duet_flash_alg_programpage(start_addr, prg_size, p_buf);
312         p_buf += prg_size;
313         start_addr += prg_size;
314         left_buf_len -= prg_size;
315     }
316 
317     *off_set += in_buf_len;
318     return 0;
319 }
320 
321 /**
322  * Write data to an area on a flash logical partition with erase first
323  *
324  * @note this function must not be interrupted, it should be called with
325  *       interrupt disabled
326  *
327  * @param[in]  in_partition    The target flash logical partition which should be read which should be written
328  * @param[in]  off_set         Point to the start address that the data is written to, and
329  *                             point to the last unwritten address after this function is
330  *                             returned, so you can call this function serval times without
331  *                             update this start address.
332  * @param[in]  inBuffer        point to the data buffer that will be written to flash
333  * @param[in]  inBufferLength  The length of the buffer
334  *
335  * @return  0 : On success, EIO : If an error occurred with any step
336  */
duet_flash_erase_write(duet_partition_t in_partition,uint32_t * off_set,const void * in_buf,uint32_t in_buf_len)337 int32_t duet_flash_erase_write(duet_partition_t in_partition, uint32_t *off_set,
338                                const void *in_buf, uint32_t in_buf_len)
339 {
340     int32_t ret = 0;
341     ret = duet_flash_erase(in_partition, *off_set, in_buf_len);
342     if (ret != 0) {
343         return ret;
344     }
345     return duet_flash_write(in_partition, off_set, in_buf, in_buf_len);
346 }
347 
348 /**
349  * Read data from an area on a Flash to data buffer in RAM
350  *
351  * @param[in]  in_partition    The target flash logical partition which should be read
352  * @param[in]  off_set         Point to the start address that the data is read, and
353  *                             point to the last unread address after this function is
354  *                             returned, so you can call this function serval times without
355  *                             update this start address.
356  * @param[in]  outBuffer       Point to the data buffer that stores the data read from flash
357  * @param[in]  inBufferLength  The length of the buffer
358  *
359  * @return  0 : On success, EIO : If an error occurred with any step
360  */
duet_flash_read(duet_partition_t in_partition,uint32_t * off_set,void * out_buf,uint32_t in_buf_len)361 int32_t duet_flash_read(duet_partition_t in_partition, uint32_t *off_set,
362                         void *out_buf, uint32_t in_buf_len)
363 {
364     int32_t ret = 0;
365     uint32_t start_addr;
366     duet_logic_partition_t *partition_info;
367 
368     partition_info = duet_flash_get_info(in_partition);
369 
370     if (off_set == NULL || out_buf == NULL || *off_set + in_buf_len > partition_info->partition_length) {
371         return EIO;
372     }
373     start_addr = partition_info->partition_start_addr + *off_set;
374     memcpy(out_buf, (void *)(start_addr), in_buf_len);
375     *off_set += in_buf_len;
376 
377     return ret;
378 }
379 
duet_flash_read_common(uint32_t addr,void * out_buf,uint32_t in_buf_len)380 int32_t duet_flash_read_common(uint32_t addr,
381                                void *out_buf, uint32_t in_buf_len)
382 {
383     int32_t ret = 0;
384     uint32_t start_addr;
385     uint32_t off_set = NULL;
386     duet_logic_partition_t *partition_info;
387     duet_partition_t current_partition = flash_layout_judge(addr);
388     if (current_partition == PARTITION_ERROR) {
389         return -1;
390     }
391     partition_info = duet_flash_get_info(current_partition);
392     if (addr == 0 || ((addr + in_buf_len) > (partition_info->partition_start_addr + partition_info->partition_length)) \
393         || (addr < partition_info->partition_start_addr)) {
394         return -1;
395     }
396     off_set = addr - partition_info->partition_start_addr;
397     if ((out_buf == NULL) || (off_set + in_buf_len > partition_info->partition_length)) {
398         return -1;
399     }
400     start_addr = partition_info->partition_start_addr + off_set;
401     memcpy(out_buf, (void *)(start_addr), in_buf_len);
402     return ret;
403 }
404 
405 /**  Erase internal flash
406  *
407  * This will erase the flash for the specified start address
408  * and size
409  *
410  * \param addr Start address in flash (*MUST* 4 KB alignment)
411  * \param len Number of bytes to be erased (*MUST* 4 KB alignment, erase must in one partition)
412  * \return 0 on success
413  */
duet_flash_erase_common(uint32_t addr,uint32_t len)414 int32_t duet_flash_erase_common(uint32_t addr, uint32_t len)
415 {
416     int32_t ret = 0;
417     uint32_t off_set = 0;
418     uint32_t sector_offset = 0;
419     uint32_t start_offset = 0;
420     uint32_t start_addr, end_addr;
421     uint32_t sec_num = 0;
422     int32_t i = 0;
423     unsigned char *tmpbuf = NULL;
424     duet_logic_partition_t *partition_info;
425     duet_partition_t current_partition = flash_layout_judge(addr);
426     if (current_partition == PARTITION_ERROR) {
427         return -1;
428     }
429     partition_info = duet_flash_get_info(current_partition);
430     if (addr == 0 || ((addr + len) > (partition_info->partition_start_addr + partition_info->partition_length)) \
431         || (addr < partition_info->partition_start_addr)) {
432         return -1;
433     }
434     off_set = addr - partition_info->partition_start_addr;
435     start_addr = ROUND_DOWN((partition_info->partition_start_addr + off_set), SPI_FLASH_SEC_SIZE);
436     end_addr = ROUND_DOWN((partition_info->partition_start_addr + off_set + len - 1), SPI_FLASH_SEC_SIZE);
437     sec_num = (end_addr - start_addr) / SPI_FLASH_SEC_SIZE;
438     if (sec_num > 0) {
439         for (i = 0; i <= sec_num; i++) {
440             if (i == 0) {
441                 sector_offset = start_addr - partition_info->partition_start_addr;
442                 start_offset = off_set;
443                 ret = refresh_flash_sector(current_partition, sector_offset, start_offset, tmpbuf,
444                                            SPI_FLASH_SEC_SIZE - (start_offset - sector_offset), ERASE_FLAG);
445                 if (ret != 0) {
446                     return ret;
447                 }
448             } else if (i == sec_num) {
449                 sector_offset = start_addr - partition_info->partition_start_addr + i * SPI_FLASH_SEC_SIZE;
450                 start_offset = sector_offset;
451                 ret = refresh_flash_sector(current_partition, sector_offset, start_offset, tmpbuf,
452                                            partition_info->partition_start_addr + off_set + len - end_addr, ERASE_FLAG);
453                 if (ret != 0) {
454                     return ret;
455                 }
456             } else {
457                 sector_offset = start_addr - partition_info->partition_start_addr + i * SPI_FLASH_SEC_SIZE;
458                 start_offset = sector_offset;
459                 ret = refresh_flash_sector(current_partition, sector_offset, start_offset, tmpbuf, SPI_FLASH_SEC_SIZE, ERASE_FLAG);
460                 if (ret != 0) {
461                     return ret;
462                 }
463             }
464         }
465     } else if (sec_num == 0) {
466         sector_offset = start_addr - partition_info->partition_start_addr;
467         ret = refresh_flash_sector(current_partition, sector_offset, off_set, tmpbuf, len, ERASE_FLAG);
468         if (ret != 0) {
469             return ret;
470         }
471     } else {
472         ret = -1;
473     }
474     return ret;
475 }
duet_flash_write_common(uint32_t addr,const void * in_buff,uint32_t len)476 int32_t duet_flash_write_common(uint32_t addr, const void *in_buff, uint32_t len)
477 {
478     int32_t ret = 0;
479     uint32_t off_set = 0;
480     uint32_t sector_offset = 0;
481     uint32_t start_offset = 0;
482     uint32_t start_addr, end_addr;
483     uint32_t sec_num = 0;
484     int32_t i = 0;
485     unsigned char *tmpbuf = NULL;
486     duet_logic_partition_t *partition_info;
487     duet_partition_t current_partition = flash_layout_judge(addr);
488     if (current_partition == PARTITION_ERROR) {
489         return -1;
490     }
491     partition_info = duet_flash_get_info(current_partition);
492     if (addr == 0 || in_buff == NULL
493         || ((addr + len) > (partition_info->partition_start_addr + partition_info->partition_length)) \
494         || (addr < partition_info->partition_start_addr)) {
495         return -1;
496     }
497     off_set = addr - partition_info->partition_start_addr;
498     start_addr = ROUND_DOWN((partition_info->partition_start_addr + off_set), SPI_FLASH_SEC_SIZE);
499     end_addr = ROUND_DOWN((partition_info->partition_start_addr + off_set + len - 1), SPI_FLASH_SEC_SIZE);
500     sec_num = (end_addr - start_addr) / SPI_FLASH_SEC_SIZE;
501     if (sec_num > 0) {
502         tmpbuf = (unsigned char *)in_buff;
503         for (i = 0; i <= sec_num; i++) {
504             if (i == 0) {
505                 sector_offset = start_addr - partition_info->partition_start_addr;
506                 start_offset = off_set;
507                 ret = refresh_flash_sector(current_partition, sector_offset, start_offset, tmpbuf,
508                                            SPI_FLASH_SEC_SIZE - (start_offset - sector_offset), WRITE_FLAG);
509                 tmpbuf = tmpbuf + SPI_FLASH_SEC_SIZE - (start_offset - sector_offset);
510                 if (ret != 0) {
511                     return ret;
512                 }
513             } else if (i == sec_num) {
514                 sector_offset = start_addr - partition_info->partition_start_addr + i * SPI_FLASH_SEC_SIZE;
515                 start_offset = sector_offset;
516                 ret = refresh_flash_sector(current_partition, sector_offset, start_offset, tmpbuf,
517                                            partition_info->partition_start_addr + off_set + len - end_addr, WRITE_FLAG);
518                 if (ret != 0) {
519                     return ret;
520                 }
521             } else {
522                 sector_offset = start_addr - partition_info->partition_start_addr + i * SPI_FLASH_SEC_SIZE;
523                 start_offset = sector_offset;
524                 ret = refresh_flash_sector(current_partition, sector_offset, start_offset, tmpbuf, SPI_FLASH_SEC_SIZE, WRITE_FLAG);
525                 tmpbuf = tmpbuf + SPI_FLASH_SEC_SIZE;
526                 if (ret != 0) {
527                     return ret;
528                 }
529             }
530         }
531     } else if (sec_num == 0) {
532         sector_offset = start_addr - partition_info->partition_start_addr;
533         ret = refresh_flash_sector(current_partition, sector_offset, off_set, (unsigned char *)in_buff, len, WRITE_FLAG);
534         if (ret != 0) {
535             return ret;
536         }
537     } else {
538         ret = -1;
539     }
540     return ret;
541 }
duet_flash_write_saved(duet_partition_t in_partition,uint32_t * off_set,const void * in_buf,uint32_t in_buf_len)542 int32_t duet_flash_write_saved(duet_partition_t in_partition, uint32_t *off_set,
543                                const void *in_buf, uint32_t in_buf_len)
544 {
545     uint32_t addr;
546     uint32_t start_addr, end_addr, start_sector, end_sector;
547     duet_logic_partition_t *partition_info;
548     uint8_t *p_buf = (uint8_t *)(in_buf);
549     uint32_t left_buf_len = in_buf_len;
550     uint8_t *buf_malloc = NULL;
551     uint32_t off_set_tmp = 0;
552     uint32_t len_tmp = 0;
553     partition_info = duet_flash_get_info(in_partition);
554     if (off_set == NULL || in_buf == NULL || ((*off_set + in_buf_len) > partition_info->partition_length)) {
555         return -1;
556     }
557     start_addr = partition_info->partition_start_addr + *off_set;
558     end_addr = start_addr + left_buf_len;
559     return duet_flash_write_common(start_addr, in_buf, in_buf_len);
560 }
561 
562 /**
563  * Set security options on a logical partition
564  *
565  * @param[in]  partition  The target flash logical partition
566  * @param[in]  offset     Point to the start address that the data is read, and
567  *                        point to the last unread address after this function is
568  *                        returned, so you can call this function serval times without
569  *                        update this start address.
570  * @param[in]  size       Size of enabled flash area
571  *
572  * @return  0 : On success, EIO : If an error occurred with any step
573  */
duet_flash_enable_secure(duet_partition_t partition,uint32_t off_set,uint32_t size)574 int32_t duet_flash_enable_secure(duet_partition_t partition, uint32_t off_set, uint32_t size)
575 {
576     return 0;
577 }
578 
579 /**
580  * Disable security options on a logical partition
581  *
582  * @param[in]  partition  The target flash logical partition
583  * @param[in]  offset     Point to the start address that the data is read, and
584  *                        point to the last unread address after this function is
585  *                        returned, so you can call this function serval times without
586  *                        update this start address.
587  * @param[in]  size       Size of disabled flash area
588  *
589  * @return  0 : On success, EIO : If an error occurred with any step
590  */
duet_flash_dis_secure(duet_partition_t partition,uint32_t off_set,uint32_t size)591 int32_t duet_flash_dis_secure(duet_partition_t partition, uint32_t off_set, uint32_t size)
592 {
593     return 0;
594 }
595 
596