1 /******************************************************************************
2 * Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
3 * All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *****************************************************************************/
18 #include "flash.h"
19 #include "core.h"
20 #include "ext_driver/ext_misc.h"
21 #include "mspi.h"
22 #include "plic.h"
23 #include "stimer.h"
24 #include "sys.h"
25 #include "timer.h"
26 #include "watchdog.h"
27
28 #include "los_timer.h"
29 #include "los_task.h"
30
31 #define RAMCODE_OPTIMIZE_UNUSED_FLASH_API_NOT_IMPLEMENT 1
32
33 _attribute_data_retention_sec_ volatile unsigned char flash_cnt = 1;
34
35 static preempt_config_t s_flash_preempt_config = {
36 .preempt_en = 0,
37 .threshold = 1,
38 };
39
40 /**
41 * @brief This function serves to set priority threshold.
42 * when the interrupt priority > Threshold flash process will disturb by interrupt.
43 * @param[in] preempt_en - 1 can disturb by interrupt, 0 can disturb by interrupt.
44 * @param[in] threshold - priority Threshold.
45 * @return none.
46 */
flash_plic_preempt_config(unsigned char preempt_en,unsigned char threshold)47 void flash_plic_preempt_config(unsigned char preempt_en, unsigned char threshold)
48 {
49 s_flash_preempt_config.preempt_en = preempt_en;
50 s_flash_preempt_config.threshold = threshold;
51 }
52
53 /**
54 * @brief This function to determine whether the flash is busy..
55 * @return 1:Indicates that the flash is busy. 0:Indicates that the flash is free
56 */
flash_is_busy(void)57 static inline int flash_is_busy(void)
58 {
59 return mspi_read() & 0x01; // the busy bit, pls check flash spec
60 }
61
62 /**
63 * @brief This function serves to set flash write command.
64 * This function interface is only used internally by flash,
65 * and is currently included in the H file for compatibility with other SDKs. When using this interface,
66 * please ensure that you understand the precautions of flash before using it.
67 * @param[in] cmd - set command.
68 * @return none.
69 */
flash_send_cmd(unsigned char cmd)70 _attribute_ram_code_sec_noinline_ void flash_send_cmd(unsigned char cmd)
71 {
72 mspi_high();
73 CLOCK_DLY_10_CYC;
74 mspi_low();
75 mspi_write(cmd);
76 mspi_wait();
77 }
78
79 /**
80 * @brief This function serves to send flash address.
81 * @param[in] addr - the flash address.
82 * @return none.
83 */
flash_send_addr(unsigned int addr)84 _attribute_ram_code_sec_noinline_ static void flash_send_addr(unsigned int addr)
85 {
86 mspi_write((unsigned char)(addr >> 16));
87 mspi_wait();
88 mspi_write((unsigned char)(addr >> 8));
89 mspi_wait();
90 mspi_write((unsigned char)(addr));
91 mspi_wait();
92 }
93
94 /**
95 * @brief This function serves to wait flash done.(make this a asynchorous version).
96 * @return none.
97 */
flash_wait_done(void)98 _attribute_ram_code_sec_noinline_ static void flash_wait_done(void)
99 {
100 flash_send_cmd(FLASH_READ_STATUS_CMD);
101
102 int i;
103 for (i = 0; i < 10000000; ++i) {
104 if (!flash_is_busy()) {
105 flash_cnt++;
106 break;
107 }
108 }
109 mspi_high();
110 }
111
112 /**
113 * @brief This function serves to erase a sector.
114 * @param[in] addr - the start address of the sector needs to erase.
115 * @return none.
116 */
flash_erase_sector_ram(unsigned long addr)117 _attribute_ram_code_sec_noinline_ void flash_erase_sector_ram(unsigned long addr)
118 {
119 LOS_SysTickTimerGet()->lock();
120 LOS_TaskLock();
121 #if SUPPORT_PFT_ARCH
122 unsigned int r = core_interrupt_disable();
123 reg_irq_threshold = 1;
124 core_restore_interrupt(r);
125 #else
126 unsigned int r = core_interrupt_disable();
127 #endif
128 mspi_stop_xip();
129 flash_send_cmd(FLASH_WRITE_ENABLE_CMD);
130 flash_send_cmd(FLASH_SECT_ERASE_CMD);
131 flash_send_addr(addr);
132 mspi_high();
133 flash_wait_done();
134 CLOCK_DLY_5_CYC;
135 #if SUPPORT_PFT_ARCH
136 r = core_interrupt_disable();
137 reg_irq_threshold = 0;
138 core_restore_interrupt(r);
139 #else
140 core_restore_interrupt(r);
141 #endif
142 LOS_SysTickTimerGet()->unlock();
143 LOS_TaskUnlock();
144 }
flash_erase_sector(unsigned long addr)145 _attribute_text_sec_ void flash_erase_sector(unsigned long addr)
146 {
147 wd_clear(); // clear watch dog (ble team add code)
148 __asm__("csrci mmisc_ctl,8"); // disable BTB
149 flash_erase_sector_ram(addr);
150 __asm__("csrsi mmisc_ctl,8"); // enable BTB
151 }
152
153 /**
154 * @brief This function writes the buffer's content to a page.
155 * @param[in] addr - the start address of the page.
156 * @param[in] len - the length(in byte) of content needs to write into the page.
157 * @param[in] buf - the start address of the content needs to write into.
158 * @return none.
159 */
flash_write_page_ram(unsigned long addr,unsigned long len,unsigned char * buf)160 _attribute_ram_code_sec_noinline_ void flash_write_page_ram(unsigned long addr, unsigned long len, unsigned char *buf)
161 {
162 LOS_SysTickTimerGet()->lock();
163 LOS_TaskLock();
164 #if SUPPORT_PFT_ARCH
165 unsigned int r = core_interrupt_disable();
166 reg_irq_threshold = 1;
167 core_restore_interrupt(r);
168 #else
169 unsigned int r = core_interrupt_disable(); // ???irq_disable();
170 #endif
171 mspi_stop_xip();
172 flash_send_cmd(FLASH_WRITE_ENABLE_CMD);
173 flash_send_cmd(FLASH_WRITE_CMD);
174 flash_send_addr(addr);
175
176 unsigned int i;
177 for (i = 0; i < len; ++i) {
178 mspi_write(buf[i]); /* write data */
179 mspi_wait();
180 }
181 mspi_high();
182 flash_wait_done();
183 CLOCK_DLY_5_CYC;
184
185 #if SUPPORT_PFT_ARCH
186 r = core_interrupt_disable();
187 reg_irq_threshold = 0;
188 core_restore_interrupt(r);
189 #else
190 core_restore_interrupt(r); // ???irq_restore(r);
191 #endif
192 LOS_SysTickTimerGet()->unlock();
193 LOS_TaskUnlock();
194 }
flash_write_page(unsigned long addr,unsigned long len,unsigned char * buf)195 _attribute_text_sec_ void flash_write_page(unsigned long addr, unsigned long len, unsigned char *buf)
196 {
197 unsigned int ns = PAGE_SIZE - (addr & 0xff);
198 int nw = 0;
199
200 do {
201 nw = len > ns ? ns : len;
202 __asm__("csrci mmisc_ctl,8"); // disable BTB
203 flash_write_page_ram(addr, nw, buf);
204 __asm__("csrsi mmisc_ctl,8"); // enable BTB
205 ns = PAGE_SIZE;
206 addr += nw;
207 buf += nw;
208 len -= nw;
209 } while (len > 0);
210 }
211
212 /**
213 * @brief This function reads the content from a page to the buf.
214 * @param[in] addr - the start address of the page.
215 * @param[in] len - the length(in byte) of content needs to read out from the page.
216 * @param[out] buf - the start address of the buffer.
217 * @return none.
218 */
flash_read_page_ram(unsigned long addr,unsigned long len,unsigned char * buf)219 _attribute_ram_code_sec_noinline_ void flash_read_page_ram(unsigned long addr, unsigned long len, unsigned char *buf)
220 {
221 LOS_SysTickTimerGet()->lock();
222 LOS_TaskLock();
223 #if SUPPORT_PFT_ARCH
224 unsigned int r = core_interrupt_disable();
225 reg_irq_threshold = 1;
226 core_restore_interrupt(r);
227 #else
228 unsigned int r = core_interrupt_disable(); // ???irq_disable();
229 #endif
230 mspi_stop_xip();
231 flash_send_cmd(FLASH_READ_CMD);
232 flash_send_addr(addr);
233
234 mspi_write(0x00); /* dummy, to issue clock */
235 mspi_wait();
236 mspi_fm_rd_en(); /* auto mode, mspi_get() automatically triggers mspi_write(0x00) once. */
237 mspi_wait();
238 /* get data */
239 for (unsigned int i = 0; i < len; ++i) {
240 *buf++ = mspi_get();
241 mspi_wait();
242 }
243 mspi_fm_rd_dis(); /* off read auto mode */
244 mspi_high();
245 CLOCK_DLY_5_CYC;
246 #if SUPPORT_PFT_ARCH
247 r = core_interrupt_disable();
248 reg_irq_threshold = 0;
249 core_restore_interrupt(r);
250 #else
251 core_restore_interrupt(r); // ???irq_restore(r);
252 #endif
253 LOS_SysTickTimerGet()->unlock();
254 LOS_TaskUnlock();
255 }
flash_read_page(unsigned long addr,unsigned long len,unsigned char * buf)256 _attribute_text_sec_ void flash_read_page(unsigned long addr, unsigned long len, unsigned char *buf)
257 {
258 __asm__("csrci mmisc_ctl,8"); // disable BTB
259 flash_read_page_ram(addr, len, buf);
260 __asm__("csrsi mmisc_ctl,8"); // enable BTB
261 }
262
263 /**
264 * @brief This function serves to erase a chip.
265 * @return none.
266 */
flash_erase_chip_ram(void)267 _attribute_ram_code_sec_noinline_ void flash_erase_chip_ram(void)
268 {
269 LOS_SysTickTimerGet()->lock();
270 LOS_TaskLock();
271 #if SUPPORT_PFT_ARCH
272 unsigned int r = core_interrupt_disable();
273 reg_irq_threshold = 1;
274 core_restore_interrupt(r);
275 #else
276 unsigned int r = core_interrupt_disable();
277 #endif
278 mspi_stop_xip();
279 flash_send_cmd(FLASH_WRITE_ENABLE_CMD);
280 flash_send_cmd(FLASH_CHIP_ERASE_CMD);
281 mspi_high();
282 flash_wait_done();
283 CLOCK_DLY_5_CYC;
284 #if SUPPORT_PFT_ARCH
285 r = core_interrupt_disable();
286 reg_irq_threshold = 0;
287 core_restore_interrupt(r);
288 #else
289 core_restore_interrupt(r);
290 #endif
291 LOS_SysTickTimerGet()->unlock();
292 LOS_TaskUnlock();
293 }
flash_erase_chip(void)294 _attribute_text_sec_ void flash_erase_chip(void)
295 {
296 __asm__("csrci mmisc_ctl,8"); // disable BTB
297 flash_erase_chip_ram();
298 __asm__("csrsi mmisc_ctl,8"); // enable BTB
299 }
300
301 /**
302 * @brief This function serves to erase a page(256 bytes).
303 * @param[in] addr - the start address of the page needs to erase.
304 * @return none.
305 */
flash_erase_page_ram(unsigned int addr)306 _attribute_ram_code_sec_noinline_ void flash_erase_page_ram(unsigned int addr)
307 {
308 #if SUPPORT_PFT_ARCH
309 unsigned int r = core_interrupt_disable();
310 reg_irq_threshold = 1;
311 core_restore_interrupt(r);
312 #else
313 unsigned int r = core_interrupt_disable();
314 #endif
315
316 mspi_stop_xip();
317 flash_send_cmd(FLASH_WRITE_ENABLE_CMD);
318 flash_send_cmd(FLASH_PAGE_ERASE_CMD);
319 flash_send_addr(addr);
320 mspi_high();
321 flash_wait_done();
322 CLOCK_DLY_5_CYC;
323 #if SUPPORT_PFT_ARCH
324 r = core_interrupt_disable();
325 reg_irq_threshold = 0;
326 core_restore_interrupt(r);
327 #else
328 core_restore_interrupt(r); // ???irq_restore(r);
329 #endif
330 }
flash_erase_page(unsigned int addr)331 _attribute_text_sec_ void flash_erase_page(unsigned int addr)
332 {
333 __asm__("csrci mmisc_ctl,8"); // disable BTB
334 flash_erase_page_ram(addr);
335 __asm__("csrsi mmisc_ctl,8"); // enable BTB
336 }
337
338 /**
339 * @brief This function serves to erase a block(64k).
340 * @param[in] addr - the start address of the block needs to erase.
341 * @return none.
342 */
flash_erase_64kblock_ram(unsigned int addr)343 _attribute_ram_code_sec_noinline_ void flash_erase_64kblock_ram(unsigned int addr)
344 {
345 #if SUPPORT_PFT_ARCH
346 unsigned int r = core_interrupt_disable();
347 reg_irq_threshold = 1;
348 core_restore_interrupt(r);
349 #else
350 unsigned int r = core_interrupt_disable();
351 #endif
352
353 mspi_stop_xip();
354 flash_send_cmd(FLASH_WRITE_ENABLE_CMD);
355 flash_send_cmd(FLASH_64KBLK_ERASE_CMD);
356 flash_send_addr(addr);
357 mspi_high();
358 flash_wait_done();
359 CLOCK_DLY_5_CYC;
360 #if SUPPORT_PFT_ARCH
361 r = core_interrupt_disable();
362 reg_irq_threshold = 0;
363 core_restore_interrupt(r);
364 #else
365 core_restore_interrupt(r); // ???irq_restore(r);
366 #endif
367 }
flash_erase_64kblock(unsigned int addr)368 _attribute_text_sec_ void flash_erase_64kblock(unsigned int addr)
369 {
370 __asm__("csrci mmisc_ctl,8"); // disable BTB
371 flash_erase_64kblock_ram(addr);
372 __asm__("csrsi mmisc_ctl,8"); // enable BTB
373 }
374
375 #if (!RAMCODE_OPTIMIZE_UNUSED_FLASH_API_NOT_IMPLEMENT)
376 /**
377 * @brief This function serves to erase a block(32k).
378 * @param[in] addr - the start address of the block needs to erase.
379 * @return none.
380 */
flash_erase_32kblock_ram(unsigned int addr)381 _attribute_ram_code_sec_noinline_ void flash_erase_32kblock_ram(unsigned int addr)
382 {
383 #if SUPPORT_PFT_ARCH
384 unsigned int r = core_interrupt_disable();
385 reg_irq_threshold = 1;
386 core_restore_interrupt(r);
387 #else
388 unsigned int r = core_interrupt_disable();
389 #endif
390
391 mspi_stop_xip();
392 flash_send_cmd(FLASH_WRITE_ENABLE_CMD);
393 flash_send_cmd(FLASH_32KBLK_ERASE_CMD);
394 flash_send_addr(addr);
395 mspi_high();
396 flash_wait_done();
397 CLOCK_DLY_5_CYC;
398 #if SUPPORT_PFT_ARCH
399 r = core_interrupt_disable();
400 reg_irq_threshold = 0;
401 core_restore_interrupt(r);
402 #else
403 core_restore_interrupt(r); // ???irq_restore(r);
404 #endif
405 }
flash_erase_32kblock(unsigned int addr)406 _attribute_text_sec_ void flash_erase_32kblock(unsigned int addr)
407 {
408 __asm__("csrci mmisc_ctl,8"); // disable BTB
409 flash_erase_32kblock_ram(addr);
410 __asm__("csrsi mmisc_ctl,8"); // enable BTB
411 }
412
413 /**
414 * @brief This function write the status of flash.
415 * @param[in] data - the value of status.
416 * @return none.
417 */
flash_write_status_ram(unsigned short data)418 _attribute_ram_code_sec_noinline_ void flash_write_status_ram(unsigned short data)
419 {
420 #if SUPPORT_PFT_ARCH
421 unsigned int r = core_interrupt_disable();
422 reg_irq_threshold = 1;
423 core_restore_interrupt(r);
424 #else
425 unsigned int r = core_interrupt_disable();
426 #endif
427 mspi_stop_xip();
428 flash_send_cmd(FLASH_WRITE_ENABLE_CMD);
429 flash_send_cmd(FLASH_WRITE_STATUS_CMD);
430 mspi_write((unsigned char)data);
431 mspi_wait();
432 mspi_write((unsigned char)(data >> 8));
433 mspi_wait();
434 mspi_high();
435 flash_wait_done();
436 mspi_high();
437 CLOCK_DLY_5_CYC;
438 #if SUPPORT_PFT_ARCH
439 r = core_interrupt_disable();
440 reg_irq_threshold = 0;
441 core_restore_interrupt(r);
442 #else
443 core_restore_interrupt(r); // ???irq_restore(r);
444 #endif
445 }
flash_write_status(unsigned short data)446 _attribute_text_sec_ void flash_write_status(unsigned short data)
447 {
448 __asm__("csrci mmisc_ctl,8"); // disable BTB
449 flash_write_status_ram(data);
450 __asm__("csrsi mmisc_ctl,8"); // enable BTB
451 }
452
453 /**
454 * @brief This function reads the status of flash.
455 * @return the value of status.
456 */
flash_read_status_ram(void)457 _attribute_ram_code_sec_noinline_ unsigned short flash_read_status_ram(void)
458 {
459 unsigned short status = 0;
460 #if SUPPORT_PFT_ARCH
461 unsigned int r = core_interrupt_disable();
462 reg_irq_threshold = 1;
463 core_restore_interrupt(r);
464 #else
465 unsigned int r = core_interrupt_disable();
466 #endif
467
468 mspi_stop_xip();
469 flash_send_cmd(FLASH_READ_STATUS_1_CMD); /* get high 8 bit status */
470 status = (mspi_read() << 8);
471 mspi_high();
472 flash_send_cmd(FLASH_READ_STATUS_CMD); /* get low 8 bit status */
473 status |= mspi_read();
474 mspi_high();
475 CLOCK_DLY_5_CYC;
476
477 #if SUPPORT_PFT_ARCH
478 r = core_interrupt_disable();
479 reg_irq_threshold = 0;
480 core_restore_interrupt(r);
481 #else
482 core_restore_interrupt(r); // ???irq_restore(r);
483 #endif
484 return status;
485 }
flash_read_status(void)486 _attribute_text_sec_ unsigned short flash_read_status(void)
487 {
488 __asm__("csrci mmisc_ctl,8"); // disable BTB
489 unsigned short status = flash_read_status_ram();
490 __asm__("csrsi mmisc_ctl,8"); // enable BTB
491 return status;
492 }
493
494 /**
495 * @brief Deep Power Down mode to put the device in the lowest consumption mode
496 * it can be used as an extra software protection mechanism,while the device
497 * is not in active use,since in the mode, all write,Program and Erase commands
498 * are ignored,except the Release from Deep Power-Down and Read Device ID(RDI)
499 * command.This release the device from this mode
500 * @return none.
501 */
flash_deep_powerdown_ram(void)502 _attribute_ram_code_sec_noinline_ void flash_deep_powerdown_ram(void)
503 {
504 #if SUPPORT_PFT_ARCH
505 unsigned int r = core_interrupt_disable();
506 reg_irq_threshold = 1;
507 core_restore_interrupt(r);
508 #else
509 unsigned int r = core_interrupt_disable();
510 #endif
511
512 mspi_stop_xip();
513 flash_send_cmd(FLASH_POWER_DOWN);
514 mspi_high();
515 delay_us(1);
516 CLOCK_DLY_5_CYC;
517
518 #if SUPPORT_PFT_ARCH
519 r = core_interrupt_disable();
520 reg_irq_threshold = 0;
521 core_restore_interrupt(r);
522 #else
523 core_restore_interrupt(r); // ???irq_restore(r);
524 #endif
525 }
flash_deep_powerdown(void)526 _attribute_text_sec_ void flash_deep_powerdown(void)
527 {
528 __asm__("csrci mmisc_ctl,8"); // disable BTB
529 flash_deep_powerdown_ram();
530 __asm__("csrsi mmisc_ctl,8"); // enable BTB
531 }
532
533 /**
534 * @brief The Release from Power-Down or High Performance Mode/Device ID command is a
535 * Multi-purpose command.it can be used to release the device from the power-Down
536 * State or High Performance Mode or obtain the devices electronic identification
537 * (ID)number.Release from Power-Down will take the time duration of tRES1 before
538 * the device will resume normal operation and other command are accepted.The CS#
539 * pin must remain high during the tRES1(8us) time duration.
540 * @return none.
541 */
flash_release_deep_powerdown_ram(void)542 _attribute_ram_code_sec_noinline_ void flash_release_deep_powerdown_ram(void)
543 {
544 #if SUPPORT_PFT_ARCH
545 unsigned int r = core_interrupt_disable();
546 reg_irq_threshold = 1;
547 core_restore_interrupt(r);
548 #else
549 unsigned int r = core_interrupt_disable();
550 #endif
551
552 mspi_stop_xip();
553 flash_send_cmd(FLASH_POWER_DOWN_RELEASE);
554 mspi_high();
555 flash_wait_done();
556 mspi_high();
557 CLOCK_DLY_5_CYC;
558
559 #if SUPPORT_PFT_ARCH
560 r = core_interrupt_disable();
561 reg_irq_threshold = 0;
562 core_restore_interrupt(r);
563 #else
564 core_restore_interrupt(r); // ???irq_restore(r);
565 #endif
566 }
flash_release_deep_powerdown(void)567 _attribute_text_sec_ void flash_release_deep_powerdown(void)
568 {
569 __asm__("csrci mmisc_ctl,8"); // disable BTB
570 flash_release_deep_powerdown_ram();
571 __asm__("csrsi mmisc_ctl,8"); // enable BTB
572 }
573
574 #endif
575
576 /**
577 * @brief This function serves to read MID of flash(MAC id). Before reading UID of flash,
578 * you must read MID of flash. and then you can look up the related table to select
579 * the idcmd and read UID of flash
580 * @param[in] buf - store MID of flash
581 * @return none.
582 */
flash_read_mid_ram(unsigned char * buf)583 _attribute_ram_code_sec_noinline_ void flash_read_mid_ram(unsigned char *buf)
584 {
585 unsigned char j = 0;
586 #if SUPPORT_PFT_ARCH
587 unsigned int r = core_interrupt_disable();
588 reg_irq_threshold = 1;
589 core_restore_interrupt(r);
590 #else
591 unsigned int r = core_interrupt_disable();
592 #endif
593
594 mspi_stop_xip();
595 flash_send_cmd(FLASH_GET_JEDEC_ID);
596 mspi_write(0x00); /* dummy, to issue clock */
597 mspi_wait();
598 mspi_fm_rd_en(); /* auto mode, mspi_get() automatically triggers mspi_write(0x00) once. */
599 mspi_wait();
600
601 for (j = 0; j < 3; ++j) {
602 *buf++ = mspi_get();
603 mspi_wait();
604 }
605 mspi_fm_rd_dis(); /* off read auto mode */
606 mspi_high();
607 CLOCK_DLY_5_CYC;
608
609 #if SUPPORT_PFT_ARCH
610 r = core_interrupt_disable();
611 reg_irq_threshold = 0;
612 core_restore_interrupt(r);
613 #else
614 core_restore_interrupt(r); // ???irq_restore(r);
615 #endif
616 }
flash_read_mid(unsigned char * buf)617 _attribute_text_sec_ void flash_read_mid(unsigned char *buf)
618 {
619 __asm__("csrci mmisc_ctl,8"); // disable BTB
620 flash_read_mid_ram(buf);
621 __asm__("csrsi mmisc_ctl,8"); // enable BTB
622 }
623
624 /**
625 * @brief This function serves to read UID of flash
626 * @param[in] idcmd - different flash vendor have different read-uid command. E.g: GD/PUYA:0x4B; XTX: 0x5A
627 * @param[in] buf - store UID of flash
628 * @return none.
629 */
flash_read_uid_ram(unsigned char idcmd,unsigned char * buf)630 _attribute_ram_code_sec_noinline_ void flash_read_uid_ram(unsigned char idcmd, unsigned char *buf)
631 {
632 unsigned char j = 0;
633 #if SUPPORT_PFT_ARCH
634 unsigned int r = core_interrupt_disable();
635 reg_irq_threshold = 1;
636 core_restore_interrupt(r);
637 #else
638 unsigned int r = core_interrupt_disable();
639 #endif
640
641 mspi_stop_xip();
642 flash_send_cmd(idcmd);
643 if (idcmd == FLASH_GD_PUYA_READ_UID_CMD) { // < GD/puya
644 flash_send_addr(0x00);
645 mspi_write(0x00); /* dummy, to issue clock */
646 mspi_wait();
647 } else if (idcmd == FLASH_XTX_READ_UID_CMD) { // < XTX
648 flash_send_addr(0x80);
649 mspi_write(0x00); /* dummy, to issue clock */
650 mspi_wait();
651 }
652 mspi_write(0x00); /* dummy, to issue clock */
653 mspi_wait();
654 mspi_fm_rd_en(); /* auto mode, mspi_get() automatically triggers mspi_write(0x00) once. */
655 mspi_wait();
656
657 for (j = 0; j < 16; ++j) {
658 *buf++ = mspi_get();
659 mspi_wait();
660 }
661 mspi_fm_rd_dis(); /* off read auto mode */
662 mspi_high();
663 CLOCK_DLY_5_CYC;
664
665 #if SUPPORT_PFT_ARCH
666 r = core_interrupt_disable();
667 reg_irq_threshold = 0;
668 core_restore_interrupt(r);
669 #else
670 core_restore_interrupt(r); // ???irq_restore(r);
671 #endif
672 }
flash_read_uid(unsigned char idcmd,unsigned char * buf)673 _attribute_text_sec_ void flash_read_uid(unsigned char idcmd, unsigned char *buf)
674 {
675 __asm__("csrci mmisc_ctl,8"); // disable BTB
676 flash_read_uid_ram(idcmd, buf);
677 __asm__("csrsi mmisc_ctl,8"); // enable BTB
678 }
679
680 /**
681 * @brief This function serves to read flash mid and uid,and check the correctness of mid and uid.
682 * @param[out] flash_mid - Flash Manufacturer ID
683 * @param[out] flash_uid - Flash Unique ID
684 * @return 0:error 1:ok
685 */
flash_read_mid_uid_with_check_ram(unsigned int * flash_mid,unsigned char * flash_uid)686 _attribute_ram_code_sec_noinline_ int flash_read_mid_uid_with_check_ram(unsigned int *flash_mid,
687 unsigned char *flash_uid)
688 {
689 unsigned char no_uid[16] = {0x51, 0x01, 0x51, 0x01, 0x51, 0x01, 0x51, 0x01,
690 0x51, 0x01, 0x51, 0x01, 0x51, 0x01, 0x51, 0x01};
691 int i, f_cnt = 0;
692 unsigned int mid;
693
694 mspi_stop_xip();
695 flash_read_mid((unsigned char *)&mid);
696 mid = mid & 0xffff;
697 *flash_mid = mid;
698 // CMD MID
699 // GD25LD40C 0x4b 0x60c8
700 // GD25LD05C 0x4b 0x60c8
701 // P25Q40L 0x4b 0x6085
702 // MD25D40DGIG 0x4b 0x4051
703 if ((mid == 0x60C8) || (mid == 0x6085) || (mid == 0x4051)) {
704 flash_read_uid(FLASH_GD_PUYA_READ_UID_CMD, (unsigned char *)flash_uid);
705 } else {
706 return 0;
707 }
708 for (i = 0; i < 16; i++) {
709 if (flash_uid[i] == no_uid[i]) {
710 f_cnt++;
711 }
712 }
713 if (f_cnt == 16) { // no uid flash
714 return 0;
715 } else {
716 return 1;
717 }
718 CLOCK_DLY_5_CYC;
719 }
flash_read_mid_uid_with_check(unsigned int * flash_mid,unsigned char * flash_uid)720 _attribute_text_sec_ int flash_read_mid_uid_with_check(unsigned int *flash_mid, unsigned char *flash_uid)
721 {
722 __asm__("csrci mmisc_ctl,8"); // disable BTB
723 int result = flash_read_mid_uid_with_check_ram(flash_mid, flash_uid);
724 __asm__("csrsi mmisc_ctl,8"); // enable BTB
725 return result;
726 }
727
728 #if (!RAMCODE_OPTIMIZE_UNUSED_FLASH_API_NOT_IMPLEMENT)
729 /**
730 * @brief This function serves to set the protection area of the flash.
731 * @param[in] type - flash type include Puya.
732 * @param[in] data - refer to Driver API Doc.
733 * @return none.
734 */
flash_lock_ram(flash_type_e type,unsigned short data)735 _attribute_ram_code_sec_noinline_ void flash_lock_ram(flash_type_e type, unsigned short data)
736 {
737 #if SUPPORT_PFT_ARCH
738 unsigned int r = core_interrupt_disable();
739 reg_irq_threshold = 1;
740 core_restore_interrupt(r);
741 #else
742 unsigned int r = core_interrupt_disable();
743 #endif
744
745 mspi_stop_xip();
746 flash_send_cmd(FLASH_WRITE_ENABLE_CMD);
747 flash_send_cmd(FLASH_WRITE_STATUS_CMD);
748 if (type == FLASH_TYPE_PUYA) {
749 mspi_write((unsigned char)data);
750 mspi_wait();
751 mspi_write((unsigned char)(data >> 8)); // 16bit status
752 }
753 mspi_wait();
754 mspi_high();
755 flash_wait_done();
756 mspi_high();
757 CLOCK_DLY_5_CYC;
758
759 #if SUPPORT_PFT_ARCH
760 r = core_interrupt_disable();
761 reg_irq_threshold = 0;
762 core_restore_interrupt(r);
763 #else
764 core_restore_interrupt(r); // ???irq_restore(r);
765 #endif
766 }
flash_lock(flash_type_e type,unsigned short data)767 _attribute_text_sec_ void flash_lock(flash_type_e type, unsigned short data)
768 {
769 __asm__("csrci mmisc_ctl,8"); // disable BTB
770 flash_lock_ram(type, data);
771 __asm__("csrsi mmisc_ctl,8"); // enable BTB
772 }
773
774 /**
775 * @brief This function serves to flash release protection.
776 * @param[in] type - flash type include Puya.
777 * @return none.
778 */
flash_unlock_ram(flash_type_e type)779 _attribute_ram_code_sec_noinline_ void flash_unlock_ram(flash_type_e type)
780 {
781 #if SUPPORT_PFT_ARCH
782 unsigned int r = core_interrupt_disable();
783 reg_irq_threshold = 1;
784 core_restore_interrupt(r);
785 #else
786 unsigned int r = core_interrupt_disable();
787 #endif
788
789 mspi_stop_xip();
790 flash_send_cmd(FLASH_WRITE_ENABLE_CMD);
791 flash_send_cmd(FLASH_WRITE_STATUS_CMD);
792 if (type == FLASH_TYPE_PUYA) {
793 mspi_write(0);
794 mspi_wait();
795 mspi_write(0); // 16bit status
796 }
797 mspi_wait();
798 mspi_high();
799 flash_wait_done();
800 mspi_high();
801 CLOCK_DLY_5_CYC;
802 #if SUPPORT_PFT_ARCH
803 r = core_interrupt_disable();
804 reg_irq_threshold = 0;
805 core_restore_interrupt(r);
806 #else
807 core_restore_interrupt(r); // ???irq_restore(r);
808 #endif
809 }
flash_unlock(flash_type_e type)810 _attribute_text_sec_ void flash_unlock(flash_type_e type)
811 {
812 __asm__("csrci mmisc_ctl,8"); // disable BTB
813 flash_unlock_ram(type);
814 __asm__("csrsi mmisc_ctl,8"); // enable BTB
815 }
816
817 #endif
818