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 
19 /********************************************************************************************************
20  * @file	flash.c
21  *
22  * @brief	This is the source file for B91
23  *
24  * @author	Driver Group
25  *
26  *******************************************************************************************************/
27 #include "flash.h"
28 #include "mspi.h"
29 #include "plic.h"
30 #include "timer.h"
31 #include "sys.h"
32 #include "core.h"
33 #include "stimer.h"
34 
35 #if (CONFIG_BT_B91)
36 #include "stack/ble/controller/ble_controller.h"
37 #endif /* CONFIG_BT_B91 */
38 
39 #define DISABLE_BTB     __asm__("csrci 	0x7D0,8")
40 #define ENABLE_BTB      __asm__("csrsi 	0x7D0,8")
41 
42 volatile unsigned char flash_cnt = 1;
43 
44 static preempt_config_t s_flash_preempt_config =
45 {
46 	.preempt_en =0,
47 	.threshold  =1,
48 };
49 
50 /**
51  * @brief 		This function serves to set priority threshold. when the interrupt priority > Threshold flash process will disturb by interrupt.
52  * @param[in]   preempt_en	- 1 can disturb by interrupt, 0 can disturb by interrupt.
53  * @param[in]	threshold	- priority Threshold.
54  * @return    	none.
55  */
flash_plic_preempt_config(unsigned char preempt_en,unsigned char threshold)56 void flash_plic_preempt_config(unsigned char preempt_en,unsigned char threshold)
57 {
58 	s_flash_preempt_config.preempt_en=preempt_en;
59 	s_flash_preempt_config.threshold=threshold;
60 }
61 
62 /********************************************************************************************************
63  *								Functions for internal use in flash,
64  *		There is no need to add an evasion solution to solve the problem of access flash conflicts.
65  *******************************************************************************************************/
66 /**
67  * @brief		This function to determine whether the flash is busy..
68  * @return		1:Indicates that the flash is busy. 0:Indicates that the flash is free
69  */
flash_is_busy(void)70 static inline int flash_is_busy(void)
71 {
72 	return mspi_read() & 0x01;				//  the busy bit, pls check flash spec
73 }
74 
75 /**
76  * @brief		This function serves to set flash write command.This function interface is only used internally by flash,
77  * 				and is currently included in the H file for compatibility with other SDKs. When using this interface,
78  * 				please ensure that you understand the precautions of flash before using it.
79  * @param[in]	cmd	- set command.
80  * @return		none.
81  */
flash_send_cmd(unsigned char cmd)82 _attribute_ram_code_sec_noinline_ void flash_send_cmd(unsigned char cmd)
83 {
84 	mspi_high();
85 	CLOCK_DLY_10_CYC;
86 	mspi_low();
87 	mspi_write(cmd);
88 	mspi_wait();
89 }
90 
91 /**
92  * @brief		This function serves to send flash address.
93  * @param[in]	addr	- the flash address.
94  * @return		none.
95  */
flash_send_addr(unsigned int addr)96 _attribute_ram_code_sec_noinline_ static void flash_send_addr(unsigned int addr)
97 {
98 	mspi_write((unsigned char)(addr>>16));
99 	mspi_wait();
100 	mspi_write((unsigned char)(addr>>8));
101 	mspi_wait();
102 	mspi_write((unsigned char)(addr));
103 	mspi_wait();
104 }
105 
106 /**
107  * @brief     This function serves to wait flash done.(make this a asynchorous version).
108  * @return    none.
109  */
flash_wait_done(void)110 _attribute_ram_code_sec_noinline_ static void flash_wait_done(void)
111 {
112 	flash_send_cmd(FLASH_READ_STATUS_CMD);
113 
114 	int i;
115 	for(i = 0; i < 10000000; ++i){
116 		if(!flash_is_busy()){
117 			flash_cnt++;
118 			break;
119 		}
120 #if (CONFIG_BT_B91)
121 		blc_sdk_irq_handler();
122 #endif /* CONFIG_BT_B91 */
123 	}
124 	mspi_high();
125 }
126 
127 
128 /********************************************************************************************************
129  *		It is necessary to add an evasion plan to solve the problem of access flash conflict.
130  *******************************************************************************************************/
131 /**
132  * @brief 		This function serves to erase a sector.
133  * @param[in]   addr	- the start address of the sector needs to erase.
134  * @return 		none.
135  */
flash_erase_sector_ram(unsigned long addr)136 _attribute_ram_code_sec_noinline_ void flash_erase_sector_ram(unsigned long addr)
137 {
138 	unsigned int r=plic_enter_critical_sec(s_flash_preempt_config.preempt_en,s_flash_preempt_config.threshold);
139 	mspi_stop_xip();
140 	flash_send_cmd(FLASH_WRITE_ENABLE_CMD);
141 	flash_send_cmd(FLASH_SECT_ERASE_CMD);
142 	flash_send_addr(addr);
143 	mspi_high();
144 	flash_wait_done();
145 	CLOCK_DLY_5_CYC;
146 	plic_exit_critical_sec(s_flash_preempt_config.preempt_en,r);
147 }
flash_erase_sector(unsigned long addr)148 _attribute_text_sec_ void flash_erase_sector(unsigned long addr)
149 {
150 	DISABLE_BTB;
151 	flash_erase_sector_ram(addr);
152 	ENABLE_BTB;
153 }
154 
155 /**
156  * @brief 		This function writes the buffer's content to a page.
157  * @param[in]   addr	- the start address of the page.
158  * @param[in]   len		- the length(in byte) of content needs to write into the page.
159  * @param[in]   buf		- the start address of the content needs to write into.
160  * @return 		none.
161  */
flash_write_page_ram(unsigned long addr,unsigned long len,unsigned char * buf)162 _attribute_ram_code_sec_noinline_ void flash_write_page_ram(unsigned long addr, unsigned long len, unsigned char *buf)
163 {
164 	unsigned int r=plic_enter_critical_sec(s_flash_preempt_config.preempt_en,s_flash_preempt_config.threshold);
165 	mspi_stop_xip();
166 	flash_send_cmd(FLASH_WRITE_ENABLE_CMD);
167 	flash_send_cmd(FLASH_WRITE_CMD);
168 	flash_send_addr(addr);
169 
170 	unsigned int i;
171 	for(i = 0; i < len; ++i){
172 		mspi_write(buf[i]);			/* write data */
173 		mspi_wait();
174 	}
175 	mspi_high();
176 	flash_wait_done();
177 	CLOCK_DLY_5_CYC;
178 	plic_exit_critical_sec(s_flash_preempt_config.preempt_en,r);
179 }
flash_write_page(unsigned long addr,unsigned long len,unsigned char * buf)180 _attribute_text_sec_ void flash_write_page(unsigned long addr, unsigned long len, unsigned char *buf)
181 {
182 	unsigned int ns = PAGE_SIZE - (addr & 0xff);
183 	int nw = 0;
184 
185 	do{
186 		nw = len > ns ? ns : len;
187 		DISABLE_BTB;
188 		flash_write_page_ram(addr,nw,buf);
189 		ENABLE_BTB;
190 		ns = PAGE_SIZE;
191 		addr += nw;
192 		buf += nw;
193 		len -= nw;
194 	}while(len > 0);
195 }
196 
197 /**
198  * @brief 		This function reads the content from a page to the buf.
199  * @param[in]   addr	- the start address of the page.
200  * @param[in]   len		- the length(in byte) of content needs to read out from the page.
201  * @param[out]  buf		- the start address of the buffer.
202  * @return 		none.
203  */
flash_read_page_ram(unsigned long addr,unsigned long len,unsigned char * buf)204 _attribute_ram_code_sec_noinline_ void flash_read_page_ram(unsigned long addr, unsigned long len, unsigned char *buf)
205 {
206 	unsigned int r=plic_enter_critical_sec(s_flash_preempt_config.preempt_en,s_flash_preempt_config.threshold);
207 	mspi_stop_xip();
208 	flash_send_cmd(FLASH_READ_CMD);
209 	flash_send_addr(addr);
210 
211 	mspi_write(0x00);			/* dummy,  to issue clock */
212 	mspi_wait();
213 	mspi_fm_rd_en();			/* auto mode, mspi_get() automatically triggers mspi_write(0x00) once. */
214 	mspi_wait();
215 	/* get data */
216 	for(unsigned int i = 0; i < len; ++i){
217 		*buf++ = mspi_get();
218 		mspi_wait();
219 	}
220 	mspi_fm_rd_dis();			/* off read auto mode */
221 	mspi_high();
222 	CLOCK_DLY_5_CYC;
223 	plic_exit_critical_sec(s_flash_preempt_config.preempt_en,r);
224 }
flash_read_page(unsigned long addr,unsigned long len,unsigned char * buf)225 _attribute_text_sec_ void flash_read_page(unsigned long addr, unsigned long len, unsigned char *buf)
226 {
227 	DISABLE_BTB;
228 	flash_read_page_ram(addr,len,buf);
229 	ENABLE_BTB;
230 }
231 
232 /**
233  * @brief     	This function serves to erase a chip.
234  * @return    	none.
235  */
flash_erase_chip_ram(void)236 _attribute_ram_code_sec_noinline_ void flash_erase_chip_ram(void)
237 {
238 	unsigned int r=plic_enter_critical_sec(s_flash_preempt_config.preempt_en,s_flash_preempt_config.threshold);
239 	mspi_stop_xip();
240 	flash_send_cmd(FLASH_WRITE_ENABLE_CMD);
241 	flash_send_cmd(FLASH_CHIP_ERASE_CMD);
242 	mspi_high();
243 	flash_wait_done();
244 	CLOCK_DLY_5_CYC;
245 	plic_exit_critical_sec(s_flash_preempt_config.preempt_en,r);
246 }
flash_erase_chip(void)247 _attribute_text_sec_ void flash_erase_chip(void)
248 {
249 	DISABLE_BTB;
250 	flash_erase_chip_ram();
251 	ENABLE_BTB;
252 }
253 
254 /**
255  * @brief     	This function serves to erase a page(256 bytes).
256  * @param[in] 	addr	- the start address of the page needs to erase.
257  * @return    	none.
258  */
flash_erase_page_ram(unsigned int addr)259 _attribute_ram_code_sec_noinline_ void flash_erase_page_ram(unsigned int addr)
260 {
261 	unsigned int r=plic_enter_critical_sec(s_flash_preempt_config.preempt_en,s_flash_preempt_config.threshold);
262 
263 	mspi_stop_xip();
264 	flash_send_cmd(FLASH_WRITE_ENABLE_CMD);
265 	flash_send_cmd(FLASH_PAGE_ERASE_CMD);
266 	flash_send_addr(addr);
267 	mspi_high();
268 	flash_wait_done();
269 	CLOCK_DLY_5_CYC;
270 	plic_exit_critical_sec(s_flash_preempt_config.preempt_en,r);
271 }
flash_erase_page(unsigned int addr)272 _attribute_text_sec_ void flash_erase_page(unsigned int addr)
273 {
274 	DISABLE_BTB;
275 	flash_erase_page_ram(addr);
276 	ENABLE_BTB;
277 }
278 
279 /**
280  * @brief 		This function serves to erase a block(32k).
281  * @param[in]   addr	- the start address of the block needs to erase.
282  * @return 		none.
283  */
flash_erase_32kblock_ram(unsigned int addr)284 _attribute_ram_code_sec_noinline_ void flash_erase_32kblock_ram(unsigned int addr)
285 {
286 	unsigned int r=plic_enter_critical_sec(s_flash_preempt_config.preempt_en,s_flash_preempt_config.threshold);
287 	mspi_stop_xip();
288 	flash_send_cmd(FLASH_WRITE_ENABLE_CMD);
289 	flash_send_cmd(FLASH_32KBLK_ERASE_CMD);
290 	flash_send_addr(addr);
291 	mspi_high();
292 	flash_wait_done();
293 	CLOCK_DLY_5_CYC;
294 	plic_exit_critical_sec(s_flash_preempt_config.preempt_en,r);
295 }
flash_erase_32kblock(unsigned int addr)296 _attribute_text_sec_ void flash_erase_32kblock(unsigned int addr)
297 {
298 	DISABLE_BTB;
299 	flash_erase_32kblock_ram(addr);
300 	ENABLE_BTB;
301 }
302 
303 /**
304  * @brief 		This function serves to erase a block(64k).
305  * @param[in]   addr	- the start address of the block needs to erase.
306  * @return 		none.
307  */
flash_erase_64kblock_ram(unsigned int addr)308 _attribute_ram_code_sec_noinline_ void flash_erase_64kblock_ram(unsigned int addr)
309 {
310 	unsigned int r=plic_enter_critical_sec(s_flash_preempt_config.preempt_en,s_flash_preempt_config.threshold);
311 	mspi_stop_xip();
312 	flash_send_cmd(FLASH_WRITE_ENABLE_CMD);
313 	flash_send_cmd(FLASH_64KBLK_ERASE_CMD);
314 	flash_send_addr(addr);
315 	mspi_high();
316 	flash_wait_done();
317 	CLOCK_DLY_5_CYC;
318 	plic_exit_critical_sec(s_flash_preempt_config.preempt_en,r);
319 }
flash_erase_64kblock(unsigned int addr)320 _attribute_text_sec_ void flash_erase_64kblock(unsigned int addr)
321 {
322 	DISABLE_BTB;
323 	flash_erase_64kblock_ram(addr);
324 	ENABLE_BTB;
325 }
326 
327 /**
328  * @brief 		This function write the status of flash.
329  * @param[in]  	data	- the value of status.
330  * @return 		none.
331  */
flash_write_status_ram(unsigned short data)332 _attribute_ram_code_sec_noinline_ void flash_write_status_ram(unsigned short data)
333 {
334 	unsigned int r=plic_enter_critical_sec(s_flash_preempt_config.preempt_en,s_flash_preempt_config.threshold);
335 	mspi_stop_xip();
336 	flash_send_cmd(FLASH_WRITE_ENABLE_CMD);
337 	flash_send_cmd(FLASH_WRITE_STATUS_CMD);
338 	mspi_write((unsigned char)data);
339 	mspi_wait();
340 	mspi_write((unsigned char)(data>>8));
341 	mspi_wait();
342 	mspi_high();
343 	flash_wait_done();
344 	mspi_high();
345 	CLOCK_DLY_5_CYC;
346 	plic_exit_critical_sec(s_flash_preempt_config.preempt_en,r);
347 }
flash_write_status(unsigned short data)348 _attribute_text_sec_ void flash_write_status(unsigned short data)
349 {
350 	DISABLE_BTB;
351 	flash_write_status_ram(data);
352 	ENABLE_BTB;
353 }
354 
355 /**
356  * @brief 		This function reads the status of flash.
357  * @return 		the value of status.
358  */
flash_read_status_ram(void)359 _attribute_ram_code_sec_noinline_ unsigned short flash_read_status_ram(void)
360 {
361 	unsigned short status = 0;
362 	unsigned int r=plic_enter_critical_sec(s_flash_preempt_config.preempt_en,s_flash_preempt_config.threshold);
363 
364 	mspi_stop_xip();
365 	flash_send_cmd(FLASH_READ_STATUS_1_CMD);	/* get high 8 bit status */
366 	status = (mspi_read()<<8);
367 	mspi_high();
368 	flash_send_cmd(FLASH_READ_STATUS_CMD);		/* get low 8 bit status */
369 	status |= mspi_read();
370 	mspi_high();
371 	CLOCK_DLY_5_CYC;
372 
373 	plic_exit_critical_sec(s_flash_preempt_config.preempt_en,r);
374 	return status;
375 }
flash_read_status(void)376 _attribute_text_sec_  unsigned short flash_read_status(void)
377 {
378 	DISABLE_BTB;
379 	unsigned short status = flash_read_status_ram();
380 	ENABLE_BTB;
381 	return status;
382 }
383 
384 /**
385  * @brief		Deep Power Down mode to put the device in the lowest consumption mode
386  * 				it can be used as an extra software protection mechanism,while the device
387  * 				is not in active use,since in the mode,  all write,Program and Erase commands
388  * 				are ignored,except the Release from Deep Power-Down and Read Device ID(RDI)
389  * 				command.This release the device from this mode
390  * @return 		none.
391  */
flash_deep_powerdown_ram(void)392 _attribute_ram_code_sec_noinline_ void flash_deep_powerdown_ram(void)
393 {
394 	unsigned int r=plic_enter_critical_sec(s_flash_preempt_config.preempt_en,s_flash_preempt_config.threshold);
395 
396 	mspi_stop_xip();
397 	flash_send_cmd(FLASH_POWER_DOWN);
398 	mspi_high();
399 	delay_us(1);
400 	CLOCK_DLY_5_CYC;
401 
402 	plic_exit_critical_sec(s_flash_preempt_config.preempt_en,r);
403 }
flash_deep_powerdown(void)404 _attribute_text_sec_ void flash_deep_powerdown(void)
405 {
406 	DISABLE_BTB;
407 	flash_deep_powerdown_ram();
408 	ENABLE_BTB;
409 }
410 
411 /**
412  * @brief		The Release from Power-Down or High Performance Mode/Device ID command is a
413  * 				Multi-purpose command.it can be used to release the device from the power-Down
414  * 				State or High Performance Mode or obtain the devices electronic identification
415  * 				(ID)number.Release from Power-Down will take the time duration of tRES1 before
416  * 				the device will resume normal operation and other command are accepted.The CS#
417  * 				pin must remain high during the tRES1(8us) time duration.
418  * @return      none.
419  */
flash_release_deep_powerdown_ram(void)420 _attribute_ram_code_sec_noinline_ void flash_release_deep_powerdown_ram(void)
421 {
422 	unsigned int r=plic_enter_critical_sec(s_flash_preempt_config.preempt_en,s_flash_preempt_config.threshold);
423 
424 	mspi_stop_xip();
425 	flash_send_cmd(FLASH_POWER_DOWN_RELEASE);
426 	mspi_high();
427 	flash_wait_done();
428 	mspi_high();
429 	CLOCK_DLY_5_CYC;
430 
431 	plic_exit_critical_sec(s_flash_preempt_config.preempt_en,r);
432 }
flash_release_deep_powerdown(void)433 _attribute_text_sec_ void flash_release_deep_powerdown(void)
434 {
435 	DISABLE_BTB;
436 	flash_release_deep_powerdown_ram();
437 	ENABLE_BTB;
438 }
439 
440 /**
441  * @brief	  	This function serves to read MID of flash(MAC id). Before reading UID of flash,
442  * 				you must read MID of flash. and then you can look up the related table to select
443  * 				the idcmd and read UID of flash
444  * @return    	MID of the flash(4 bytes).
445  */
flash_read_mid_ram(void)446 _attribute_ram_code_sec_noinline_ unsigned int flash_read_mid_ram(void){
447 
448 	unsigned char j = 0;
449 	unsigned int flash_mid = 0;
450 	unsigned int r=plic_enter_critical_sec(s_flash_preempt_config.preempt_en,s_flash_preempt_config.threshold);
451 
452 	mspi_stop_xip();
453 	flash_send_cmd(FLASH_GET_JEDEC_ID);
454 	mspi_write(0x00);			/* dummy,  to issue clock */
455 	mspi_wait();
456 	mspi_fm_rd_en();			/* auto mode, mspi_get() automatically triggers mspi_write(0x00) once. */
457 	mspi_wait();
458 
459 	for(j = 0; j < 3; ++j){
460 		((unsigned char*)(&flash_mid))[j] = mspi_get();
461 		mspi_wait();
462 	}
463 	mspi_fm_rd_dis();			/* off read auto mode */
464 	mspi_high();
465 	CLOCK_DLY_5_CYC;
466 
467 	plic_exit_critical_sec(s_flash_preempt_config.preempt_en,r);
468 	return flash_mid;
469 }
flash_read_mid(void)470 _attribute_text_sec_ unsigned int flash_read_mid(void){
471 
472 	unsigned int flash_mid = 0;
473 	DISABLE_BTB;
474 	flash_mid = flash_read_mid_ram();
475 	ENABLE_BTB;
476 	return flash_mid;
477 }
478 
479 /**
480  * @brief	  	This function serves to read UID of flash
481  * @param[in] 	idcmd	- different flash vendor have different read-uid command. E.g: GD/PUYA:0x4B; XTX: 0x5A
482  * @param[in] 	buf		- store UID of flash
483  * @return    	none.
484  */
flash_read_uid_ram(unsigned char idcmd,unsigned char * buf)485 _attribute_ram_code_sec_noinline_ void flash_read_uid_ram(unsigned char idcmd,unsigned char *buf)
486 {
487 	unsigned char j = 0;
488 	unsigned int r=plic_enter_critical_sec(s_flash_preempt_config.preempt_en,s_flash_preempt_config.threshold);
489 
490 	mspi_stop_xip();
491 	flash_send_cmd(idcmd);
492 	if(idcmd==FLASH_GD_PUYA_READ_UID_CMD)		//< GD/puya
493 	{
494 		flash_send_addr(0x00);
495 		mspi_write(0x00);			/* dummy,  to issue clock */
496 		mspi_wait();
497 	}
498 	else if (idcmd==FLASH_XTX_READ_UID_CMD)		//< XTX
499 	{
500 		flash_send_addr(0x80);
501 		mspi_write(0x00);			/* dummy,  to issue clock */
502 		mspi_wait();
503 
504 	}
505 	mspi_write(0x00);				/* dummy,  to issue clock */
506 	mspi_wait();
507 	mspi_fm_rd_en();				/* auto mode, mspi_get() automatically triggers mspi_write(0x00) once. */
508 	mspi_wait();
509 
510 	for(j = 0; j < 16; ++j){
511 		*buf++ = mspi_get();
512 		mspi_wait();
513 	}
514 	mspi_fm_rd_dis();				/* off read auto mode */
515 	mspi_high();
516 	CLOCK_DLY_5_CYC;
517 
518 	plic_exit_critical_sec(s_flash_preempt_config.preempt_en,r);
519 }
flash_read_uid(unsigned char idcmd,unsigned char * buf)520 _attribute_text_sec_ void flash_read_uid(unsigned char idcmd,unsigned char *buf)
521 {
522 	DISABLE_BTB;
523 	flash_read_uid_ram(idcmd,buf);
524 	ENABLE_BTB;
525 }
526 
527 
528 /**
529  * @brief 		This function serves to set the protection area of the flash.
530  * @param[in]   type	- flash type include Puya.
531  * @param[in]   data	- refer to Driver API Doc.
532  * @return 		none.
533  */
flash_lock_ram(flash_type_e type,unsigned short data)534 _attribute_ram_code_sec_noinline_ void flash_lock_ram(flash_type_e type , unsigned short data)
535 {
536 	unsigned int r=plic_enter_critical_sec(s_flash_preempt_config.preempt_en,s_flash_preempt_config.threshold);
537 
538 	mspi_stop_xip();
539 	flash_send_cmd(FLASH_WRITE_ENABLE_CMD);
540 	flash_send_cmd(FLASH_WRITE_STATUS_CMD);
541 	if(type == FLASH_TYPE_PUYA)
542 	{
543 		mspi_write((unsigned char)data);
544 		mspi_wait();
545 		mspi_write((unsigned char)(data>>8));//16bit status
546 
547 	}
548 	mspi_wait();
549 	mspi_high();
550 	flash_wait_done();
551 	mspi_high();
552 	CLOCK_DLY_5_CYC;
553 
554 	plic_exit_critical_sec(s_flash_preempt_config.preempt_en,r);
555 }
flash_lock(flash_type_e type,unsigned short data)556 _attribute_text_sec_ void flash_lock(flash_type_e type , unsigned short data)
557 {
558 	DISABLE_BTB;
559 	flash_lock_ram(type,data);
560 	ENABLE_BTB;
561 }
562 
563 /**
564  * @brief 		This function serves to flash release protection.
565  * @param[in]   type	- flash type include Puya.
566  * @return 		none.
567  */
flash_unlock_ram(flash_type_e type)568 _attribute_ram_code_sec_noinline_ void flash_unlock_ram(flash_type_e type)
569 {
570 	unsigned int r=plic_enter_critical_sec(s_flash_preempt_config.preempt_en,s_flash_preempt_config.threshold);
571 
572 	mspi_stop_xip();
573 	flash_send_cmd(FLASH_WRITE_ENABLE_CMD);
574 	flash_send_cmd(FLASH_WRITE_STATUS_CMD);
575 	if(type == FLASH_TYPE_PUYA)
576 	{
577 		mspi_write(0);
578 		mspi_wait();
579 		mspi_write(0);//16bit status
580 	}
581 	mspi_wait();
582 	mspi_high();
583 	flash_wait_done();
584 	mspi_high();
585 	CLOCK_DLY_5_CYC;
586 
587 	plic_exit_critical_sec(s_flash_preempt_config.preempt_en,r);
588 }
flash_unlock(flash_type_e type)589 _attribute_text_sec_ void flash_unlock(flash_type_e type)
590 {
591 	DISABLE_BTB;
592 	flash_unlock_ram(type);
593 	ENABLE_BTB;
594 }
595 /**
596  * @brief 		This function is used to update the configuration parameters of xip(eXecute In Place),
597  * 				this configuration will affect the speed of MCU fetching,
598  * 				this parameter needs to be consistent with the corresponding parameters in the flash datasheet.
599  * @param[in]	config	- xip configuration,reference structure flash_xip_config_t
600  * @return none
601  */
flash_set_xip_config_sram(flash_xip_config_t config)602 _attribute_ram_code_sec_noinline_ void flash_set_xip_config_sram(flash_xip_config_t config)
603 {
604 	unsigned int r=plic_enter_critical_sec(s_flash_preempt_config.preempt_en,s_flash_preempt_config.threshold);
605 
606 	mspi_stop_xip();
607 	reg_mspi_xip_config = *((unsigned short*)(&config));
608 	CLOCK_DLY_5_CYC;
609 
610 	plic_exit_critical_sec(s_flash_preempt_config.preempt_en,r);
611 }
flash_set_xip_config(flash_xip_config_t config)612 _attribute_text_sec_ void flash_set_xip_config(flash_xip_config_t config)
613 {
614 	DISABLE_BTB;
615 	flash_set_xip_config_sram(config);
616 	ENABLE_BTB;
617 }
618 
619 /********************************************************************************************************
620  *									secondary calling function,
621  *	there is no need to add an circumvention solution to solve the problem of access flash conflicts.
622  *******************************************************************************************************/
623 /**
624  * @brief		This function serves to read flash mid and uid,and check the correctness of mid and uid.
625  * @param[out]	flash_mid	- Flash Manufacturer ID
626  * @param[out]	flash_uid	- Flash Unique ID
627  * @return		0: flash no uid or not a known flash model 	 1:the flash model is known and the uid is read.
628  */
flash_read_mid_uid_with_check(unsigned int * flash_mid,unsigned char * flash_uid)629 _attribute_text_sec_ int flash_read_mid_uid_with_check( unsigned int *flash_mid ,unsigned char *flash_uid){
630 
631 	unsigned char no_uid[16]={0x51,0x01,0x51,0x01,0x51,0x01,0x51,0x01,0x51,0x01,0x51,0x01,0x51,0x01,0x51,0x01};
632 	int i,f_cnt=0;
633 	unsigned int mid;
634 
635 	mid = flash_read_mid();
636 	mid = mid&0xffff;
637 	*flash_mid = mid;
638 	//     	  			CMD         MID
639 	//  P25Q80U			0x4b		0x6085
640 	if(mid == 0x6085){
641 		flash_read_uid(FLASH_GD_PUYA_READ_UID_CMD,(unsigned char *)flash_uid);
642 	}else{
643 		return 0;
644 	}
645 	for(i=0;i<16;i++){
646 		if(flash_uid[i]==no_uid[i]){
647 			f_cnt++;
648 		}
649 	}
650 	if(f_cnt==16){		//no uid flash
651 		return 0;
652 	}else{
653 		return  1;
654 	}
655 }
656 
657