• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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