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, §or_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, §or_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, §or_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