• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 ASR Microelectronics (Shanghai) Co., Ltd. All rights reserved.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <stdlib.h>
17 #include <string.h>
18 #include "duet_flash_alg.h"        // FlashOS Structures
19 #include "duet_cm4.h"
20 #include "duet.h"
21 
duet_flash_alg_cache_flush(void)22 FLASH_DRIVER_SEG void duet_flash_alg_cache_flush(void)
23 {
24     SCB_InvalidateICache();
25     SCB_InvalidateDCache();
26 }
27 
duet_flash_alg_cache_flush_by_Addr(uint32_t * addr,int32_t dsize)28 FLASH_DRIVER_SEG void duet_flash_alg_cache_flush_by_Addr(uint32_t *addr, int32_t dsize)
29 {
30     if (dsize < 0x4000) {
31         uint32_t off_set = (uint32_t)addr & 0x1F;
32         addr -= off_set;
33         dsize += off_set;
34         SCB_InvalidateDCache_by_Addr(addr, dsize);
35     } else {
36         SCB_InvalidateDCache();
37     }
38 }
39 
duet_flash_alg_f_delay(unsigned char cycle)40 FLASH_DRIVER_SEG void duet_flash_alg_f_delay(unsigned char cycle)
41 {
42     while (cycle--) {
43         __asm("nop");
44     }
45 }
46 
duet_flash_alg_check_busy(void)47 FLASH_DRIVER_SEG int duet_flash_alg_check_busy (void)
48 {
49 
50     int var_rdata = 0;
51     int cnt = 0;
52     /* Add your Code */
53     var_rdata = FLASH->QSPI_SR; // read back
54 
55     while (((var_rdata >> 5) & 0x01) == 1) {
56         var_rdata = FLASH->QSPI_SR; // read back
57         if (cnt < 80000000) { // erase chip time(10s)/(160MHz*2cycle)
58             cnt = cnt + 1;
59         } else {
60             return (1);
61         }
62     }
63 
64     return (0);                                  // Finished without Errors
65 }
66 
duet_flash_alg_check_abort_busy(void)67 FLASH_DRIVER_SEG int duet_flash_alg_check_abort_busy (void)
68 {
69     int var_rdata = 0;
70     int cnt = 0;
71     /* Add your Code */
72     var_rdata = FLASH->QSPI_SR; // read back
73 
74     while (((var_rdata >> 6) & 0x01) == 1) {
75         var_rdata = FLASH->QSPI_SR; // read back
76         if (cnt < 200) { // /160MHz*10cycled
77             cnt = cnt + 1;
78         } else {
79             return (1);
80         }
81     }
82 
83     return (0);                                  // Finished without Errors
84 }
85 
duet_flash_alg_clr_flg(void)86 FLASH_DRIVER_SEG int duet_flash_alg_clr_flg (void)
87 {
88     /* Add your Code */
89     FLASH->QSPI_FCR = 0xF001B; // 0x1F;
90     FLASH->QSPI_FCR = 0x0;
91 
92     return (0);                                  // Finished without Errors
93 }
94 
duet_flash_alg_abort_en(void)95 FLASH_DRIVER_SEG int duet_flash_alg_abort_en (void)
96 {
97     /* Add your Code */
98     int var_rdata;
99     var_rdata = FLASH->QSPI_CR;
100     FLASH->QSPI_CR = (var_rdata & 0xFFFFFFFD) + 0x2;
101     FLASH->QSPI_CR = var_rdata & 0xFFFFFFFD;
102 
103     return (0);                                  // Finished without Errors
104 }
105 
duet_flash_alg_polling_wip(void)106 FLASH_DRIVER_SEG int duet_flash_alg_polling_wip (void)
107 {
108 
109     int var_rdata = 0;
110     // dumode=2'b00,fmode=2'b10,dmode=2'b01,reserved=1'b0,dcyc=5'h0,absize=2'b00,abmode=2'b00,adsize=2'b00,admode=2'b00,imode=2'b01,instruction=8'h05;
111     FLASH->QSPI_CCR = 0x9000105;
112     var_rdata = FLASH->QSPI_CR;
113     FLASH->QSPI_CR = (var_rdata & 0xFFBFFFFF) + 0x400000; // QSPI_CR[22],apms= 1'b1;
114     FLASH->QSPI_DLR = 0x0; // one byte
115     FLASH->QSPI_PSMKR = 0x1; // mask = 0x1;
116     FLASH->QSPI_PSMAR = 0x0; // match = 0x0;
117     FLASH->SBUS_START = 0x1;
118     duet_flash_alg_f_delay(10);
119     duet_flash_alg_check_busy();
120     duet_flash_alg_clr_flg();
121 
122     return (0);                                  // Finished without Errors
123 }
124 
duet_flash_alg_polling_wel(void)125 FLASH_DRIVER_SEG int duet_flash_alg_polling_wel (void)
126 {
127     int var_rdata = 0;
128     // dumode=2'b00,fmode=2'b10,dmode=2'b01,reserved=1'b0,dcyc=5'h0,absize=2'b00,abmode=2'b00,adsize=2'b00,admode=2'b00,imode=2'b01,instruction=8'h05;
129     FLASH->QSPI_CCR = 0x9000105;
130     var_rdata = FLASH->QSPI_CR;
131     FLASH->QSPI_CR = (var_rdata & 0xFFBFFFFF) + 0x400000; // QSPI_CR[22],apms= 1'b1;
132     FLASH->QSPI_DLR = 0x0; // one byte
133     FLASH->QSPI_PSMKR = 0x2; // mask = 0x1;
134     FLASH->QSPI_PSMAR = 0x2; // match = 0x0;
135     FLASH->SBUS_START = 0x1;
136     duet_flash_alg_f_delay(10);
137     duet_flash_alg_check_busy();
138     duet_flash_alg_clr_flg();
139 
140     return (0);                                  // Finished without Errors
141 }
142 
duet_flash_alg_setqe(unsigned char quad)143 FLASH_DRIVER_SEG int duet_flash_alg_setqe (unsigned char quad)
144 {
145 
146     // bypass enable 0x4000308C bit10 set 1
147     // *((volatile unsigned int *)(0x4000308C)) |= (1 << 10);
148     FLASH->QSPI_CFGR |= (1 << 10);
149     duet_flash_alg_abort_en();
150     duet_flash_alg_check_abort_busy();
151 
152     FLASH->QSPI_CCR = 0x106; // IMODE=2'b01,INSTRUCTION=WREN
153     duet_flash_alg_clr_flg();
154     FLASH->SBUS_START = 0x1;
155     duet_flash_alg_f_delay(10);
156     duet_flash_alg_check_busy();
157     duet_flash_alg_polling_wel();
158 
159     FLASH->QSPI_CCR =
160         0x01000101; // dumode=2'b00,fmode=2'b00,dmode=2'b01,reserved=1'b0,dcyc=5'h0,absize=2'b00,abmode=2'b00,adsize=2'b00,admode=2'b00,imode=2'b01,instruction=8'h01;
161     FLASH->QSPI_DLR = 0x1; // two byte
162     if (quad == 0x1) {
163         FLASH->QSPI_DR = 0x200;
164     } else {
165         FLASH->QSPI_DR = 0x0; // 0x200;
166     }
167     duet_flash_alg_clr_flg();
168     FLASH->SBUS_START = 0x1;
169     duet_flash_alg_f_delay(10);
170     duet_flash_alg_check_busy();
171     duet_flash_alg_clr_flg();
172     duet_flash_alg_polling_wip();
173     // bypass disable 0x4000308C bit10 clr
174     // *((volatile unsigned int *)(0x4000308C)) &= ~(1 << 10);
175     FLASH->QSPI_CFGR &= ~(1 << 10);
176     /* Add your Code */
177 
178     return (0);                                  // Finished without Errors
179 }
180 
181 // use in unencryption
duet_flash_alg_check_setqe(void)182 FLASH_DRIVER_SEG int duet_flash_alg_check_setqe (void)
183 {
184 
185     volatile int var_rdata = 0;
186 
187     duet_flash_alg_abort_en();
188     duet_flash_alg_check_abort_busy();
189     duet_flash_alg_check_busy();
190     FLASH->QSPI_DLR = 0x0;
191     FLASH->QSPI_CCR =
192         0x5000135; // dumode=2'b00,fmode=2'b01,dmode=2'b01,reserved=1'b0,dcyc=5'h0,absize=2'b00,abmode=2'b00,adsize=2'b00,admode=2'b00,imode=2'b01,instruction=8'h35;
193     duet_flash_alg_clr_flg();
194     FLASH->SBUS_START = 0x1;
195     duet_flash_alg_f_delay(10);
196     duet_flash_alg_check_busy();
197     var_rdata = FLASH->QSPI_DR & 0xFF;
198     return var_rdata;
199 }
200 
201 vu32 duet_flash_line_cfg = 0; // flash line number config
202 vu32 duet_flash_size_cfg = 0; // flash size config
203 vu32 duet_flash_clk_cfg = 52; // flash clock config, default 52MHz
duet_flash_alg_load_cfg(void)204 FLASH_DRIVER_SEG void duet_flash_alg_load_cfg (void)
205 {
206 
207     duet_flash_alg_abort_en();
208     duet_flash_alg_check_abort_busy();
209 #ifdef _SPI_FLASH_240MHz_
210     if (duet_flash_clk_cfg == 240) {
211         FLASH->QSPI_CR    = FLASH_QSPI_DIV3;       // div3, // offset 0x00
212         FLASH->QSPI_CR      |= 0x20;               // set loop back en bit 5=1
213         FLASH->QSPI_CR      &= ~(7 << 13);
214         FLASH->QSPI_CR      |= (5 << 13);          // ds = 5
215 
216         FLASH->QSPI_DCR   = 0x00150000  ;          // offset 0x04
217         FLASH->QSPI_FCR   = 0x0  ;                 // offset 0x0C
218         FLASH->QSPI_DLR   = 0x0  ;                 // offset 0x10
219         FLASH->QSPI_CCR   =
220             duet_flash_line_cfg;   // dumode=2'b10,,sio=1'b0,fmode=2'b11,dmode=2'b10,reserved=1'b0,dcyc=5'h7,absize=2'b00,abmode=2'b00,adsize=2'b10,admode=2'b01,imode=2'b01,instruction=8'h3B;
221         FLASH->QSPI_AR    = 0x0  ;                 // offset 0x18
222         FLASH->QSPI_ABR   = 0x0  ;                 // offset 0x1C
223         FLASH->QSPI_DR    = 0x0  ;                 // offset 0x20
224         FLASH->QSPI_PSMKR = 0x0  ;                 // offset 0x24
225         FLASH->QSPI_PSMAR = 0x0 ;                  // offset 0x28
226         FLASH->QSPI_PIR   = 0x0 ;                  // offset 0x2C
227         FLASH->QSPI_TOR   = 0x12FFFF ;             // offset 0x30
228         FLASH->QSPI_CFGR = 0x7202;                 // offset 0x8C [15:12] set loop back delay=7
229     } else
230 #endif
231     {
232         FLASH->QSPI_CR    = FLASH_QSPI_DIV2;       // div2, // offset 0x00
233         FLASH->QSPI_DCR   = 0x00150000  ;          // offset 0x04
234         FLASH->QSPI_FCR   = 0x0  ;                 // offset 0x0C
235         FLASH->QSPI_DLR   = 0x0  ;                 // offset 0x10
236         FLASH->QSPI_CCR   =
237             duet_flash_line_cfg;   // dumode=2'b10,,sio=1'b0,fmode=2'b11,dmode=2'b10,reserved=1'b0,dcyc=5'h7,absize=2'b00,abmode=2'b00,adsize=2'b10,admode=2'b01,imode=2'b01,instruction=8'h3B;
238         FLASH->QSPI_AR    = 0x0  ;                 // offset 0x18
239         FLASH->QSPI_ABR   = 0x0  ;                 // offset 0x1C
240         FLASH->QSPI_DR    = 0x0  ;                 // offset 0x20
241         FLASH->QSPI_PSMKR = 0x0  ;                 // offset 0x24
242         FLASH->QSPI_PSMAR = 0x0 ;                  // offset 0x28
243         FLASH->QSPI_PIR   = 0x0 ;                  // offset 0x2C
244         FLASH->QSPI_TOR   = 0x12FFFF ;             // offset 0x30
245         FLASH->QSPI_CFGR  = 0x202 ;                // offset 0x8C bit1:direct access optimization enable
246     }
247 
248 }
249 
250 // flash crypt bypass test
duet_flash_alg_init(void)251 FLASH_DRIVER_SEG int duet_flash_alg_init (void)
252 {
253 
254     // add delay to avoid confilict between flash cfg and instruction fetch by cache
255     duet_flash_alg_f_delay(32);
256     duet_flash_line_cfg = FLASH_QSPI_L4; // config flash line here
257     duet_flash_size_cfg = FLASH_QSPI_DCR_4M; // config flash size here
258     duet_flash_alg_abort_en();
259     duet_flash_alg_check_abort_busy();
260     if (duet_flash_line_cfg == FLASH_QSPI_L4) {
261         duet_flash_alg_setqe(1);
262     } else {
263         duet_flash_alg_setqe(0);
264     }
265 
266     duet_flash_alg_load_cfg();
267 
268     // flush cache after flash operation
269     duet_flash_alg_cache_flush();
270 
271     return (0);                                  // Finished without Errors
272 }
273 
274 /*
275  *  cmd: CHIP_ERASE_CMD or SECTOR_ERASE_CMD or BLOCK32_ERASE_CMD or BLOCK64_ERASE_CMD
276  *  adr: not used for CHIP_ERASE_CMD
277  */
duet_flash_alg_erase(unsigned int cmd,unsigned long adr)278 FLASH_DRIVER_SEG int duet_flash_alg_erase(unsigned int cmd, unsigned long adr)
279 {
280 
281     // add delay to avoid confilict between flash cfg and instruction fetch by cache
282     duet_flash_alg_f_delay(32);
283 
284     duet_flash_alg_abort_en();
285     duet_flash_alg_check_abort_busy();
286 
287     FLASH->QSPI_CCR = 0x106; // IMODE=2'b01,INSTRUCTION=WREN
288     duet_flash_alg_clr_flg();
289     FLASH->SBUS_START = 0x1;
290     duet_flash_alg_f_delay(10);
291     duet_flash_alg_check_busy();
292     duet_flash_alg_polling_wel();
293 
294     FLASH->QSPI_CCR = cmd;
295     if (CHIP_ERASE_CMD != cmd) {
296         FLASH->QSPI_AR = adr;
297     }
298     duet_flash_alg_clr_flg();
299     FLASH->SBUS_START = 0x1;
300     duet_flash_alg_f_delay(10);
301     duet_flash_alg_check_busy();
302     duet_flash_alg_clr_flg();
303     duet_flash_alg_polling_wip();
304     duet_flash_alg_f_delay(10);
305     duet_flash_alg_clr_flg();
306     duet_flash_alg_load_cfg();
307 
308     // flush cache after flash operation
309     duet_flash_alg_cache_flush();
310     /* Add your Code */
311 
312     return (0);                                  // Finished without Errors
313 }
314 
315 /*
316  *  Program Page in Flash Memory
317  *    Parameter:      adr:  Page Start Address
318  *                    sz:   Page Size
319  *                    buf:  Page Data
320  *    Return Value:   0 - OK,  1 - Failed
321  */
322 
duet_flash_alg_programpage(unsigned long adr,unsigned long sz,unsigned char * buf)323 FLASH_DRIVER_SEG int duet_flash_alg_programpage(unsigned long adr, unsigned long sz, unsigned char *buf)
324 {
325 
326     unsigned long sz_temp;
327     // volatile int cycle_count = 0;
328     int var_rdata = 0;
329     int fthres = 8;
330     int cnt = 0;
331     unsigned long ram_buf[SPI_FLASH_PAGE_SIZE / 4] = {0};
332 
333     if ((0 == sz) || (NULL == buf)) {
334         return 1;
335     }
336 
337     if (((uint32_t)buf >= SPI_FLASH_ADDR_START && (uint32_t)buf <= SPI_FLASH_ADDR_END) || ((uint32_t)buf & 0x3)) {
338         memcpy(ram_buf, buf, sz);
339         buf = (unsigned char *)ram_buf;
340     }
341 
342     sz_temp = sz - 1;
343     sz = (sz + 3) & ~3;                           // Adjust size for Words
344 
345     // add delay to avoid confilict between flash cfg and instruction fetch by cache
346     duet_flash_alg_f_delay(32);
347 
348     duet_flash_alg_abort_en();
349     duet_flash_alg_check_abort_busy();
350 
351     FLASH->QSPI_CCR = 0x106; // IMODE=2'b01,INSTRUCTION=WREN
352     duet_flash_alg_clr_flg();
353     FLASH->SBUS_START = 0x1;
354     duet_flash_alg_f_delay(10);
355     duet_flash_alg_check_busy();
356     duet_flash_alg_polling_wel();
357 
358     FLASH->QSPI_CCR =
359         0x1002502; // fmode=2'b00,dmode=2'b01,reserved=1'b0,dcyc=5'h0,absize=2'b00,abmode=2'b00,adsize=2'b10,admode=2'b01,imode=2'b01,instruction=8'h02;
360     FLASH->QSPI_DLR = sz_temp;
361     FLASH->QSPI_AR = adr;
362     while ((sz > 0) && (cnt < fthres)) {
363         var_rdata = FLASH->QSPI_SR;
364         var_rdata = (var_rdata >> 8) & 0x3F;
365         if (var_rdata < fthres) {
366             FLASH->QSPI_DR = *((unsigned long *)buf);        // Program Word
367             cnt += 1;
368             buf += 4;
369             sz  -= 4;
370         }
371     }
372     duet_flash_alg_f_delay(10);
373     duet_flash_alg_check_busy();
374     FLASH->SBUS_START = 0x01; // WRITE
375     duet_flash_alg_f_delay(10);
376     while (sz) {
377         var_rdata = FLASH->QSPI_SR;
378         var_rdata = (var_rdata >> 8) & 0x3F;
379         if (var_rdata < fthres) {
380             FLASH->QSPI_DR = *((unsigned long *)buf);        // Program Word
381             buf += 4;
382             sz  -= 4;
383         }
384     }
385     duet_flash_alg_f_delay(10);
386     duet_flash_alg_check_busy();
387     duet_flash_alg_polling_wip();
388     duet_flash_alg_load_cfg ();
389 
390     // flush cache after flash operation
391     // lega_flash_alg_cache_flush_by_Addr(adr,sz);
392     duet_flash_alg_cache_flush();
393 
394     return (0);                                  // Finished without Errors
395 }
396 
duet_flash_alg_read_buf_clr(void)397 FLASH_DRIVER_SEG void duet_flash_alg_read_buf_clr(void)
398 {
399 
400 #if 0
401     unsigned int tmp = REG_RD(FLASH_BASE);
402     REG_WR(FLASH_BASE, tmp & (~0x1));
403     REG_WR(FLASH_BASE, tmp);
404 #else
405     unsigned int tmp = FLASH->QSPI_CR;
406     FLASH->QSPI_CR = tmp & (~0x1);
407     FLASH->QSPI_CR = tmp;
408 #endif
409 
410 }
411 
412 #ifdef _SPI_FLASH_120MHz_
duet_flash_alg_set_clk_120(unsigned char en_120m)413 FLASH_DRIVER_SEG void duet_flash_alg_set_clk_120(unsigned char en_120m)
414 {
415     if (en_120m) {
416         // flash clock is source/4
417         REG_WR(APB_PERI_CLK_CTRL_REG, ((REG_RD(APB_PERI_CLK_CTRL_REG) & ~(0x3)) | 0x2));
418         // switch flash clock source to RF 480M
419         REG_WR(WIFI_BLE_FLASH_CLK_CTRL_REG, (REG_RD(WIFI_BLE_FLASH_CLK_CTRL_REG) | (1 << 7)));
420     } else {
421         // switch flash clock source to XO 52M
422         REG_WR(WIFI_BLE_FLASH_CLK_CTRL_REG, (REG_RD(WIFI_BLE_FLASH_CLK_CTRL_REG) & (~(1 << 7))));
423     }
424 }
425 #endif
426 
427 #ifdef _SPI_FLASH_240MHz_
duet_flash_alg_set_clk_240(unsigned char en_240m)428 FLASH_DRIVER_SEG void duet_flash_alg_set_clk_240(unsigned char en_240m)
429 {
430     if (en_240m) {
431         duet_flash_clk_cfg = 240;
432         duet_flash_alg_load_cfg();
433         duet_flash_alg_cache_flush();
434 
435         // 0x0:flash clock = source APLL 480MHZ / 2
436         REG_WR(APB_PERI_CLK_CTRL_REG, ((REG_RD(APB_PERI_CLK_CTRL_REG) & ~(0x3)) | 0x0));
437         // switch flash clock source to RF 480M
438         REG_WR(WIFI_BLE_FLASH_CLK_CTRL_REG, (REG_RD(WIFI_BLE_FLASH_CLK_CTRL_REG) | (1 << 7)));
439     } else {
440         // switch flash clock source to XO 52M
441         REG_WR(WIFI_BLE_FLASH_CLK_CTRL_REG, (REG_RD(WIFI_BLE_FLASH_CLK_CTRL_REG) & (~(1 << 7))));
442 
443         duet_flash_clk_cfg = 52;
444         duet_flash_alg_load_cfg();
445         duet_flash_alg_cache_flush();
446     }
447 
448 }
449 
450 #if 0
451 FLASH_DRIVER_SEG int duet_flash_alg_read_id(void)
452 {
453 
454     int var_rdata;
455     int dshift;
456     duet_flash_alg_abort_en();
457     duet_flash_alg_check_abort_busy();
458 
459     FLASH->QSPI_CCR =
460         0x500019F; // fmode=2'b01,dmode=2'b01,reserved=1'b0,dcyc=5'h0,absize=2'b00,abmode=2'b00,adsize=2'b00,admode=2'b00,imode=2'b01,instruction=8'h9F;
461     FLASH->QSPI_DLR = 0x2;
462     duet_flash_alg_clr_flg();
463     FLASH->SBUS_START = 0x1;
464 
465     duet_flash_alg_f_delay(10);
466     duet_flash_alg_check_busy();
467     var_rdata = FLASH->QSPI_CR;
468     dshift = (var_rdata >> 13) & 0x7;
469     duet_flash_alg_f_delay(dshift);
470 
471     var_rdata = FLASH->QSPI_DR;
472 
473     duet_flash_alg_load_cfg();
474     return (var_rdata);
475 
476 }
477 
478 FLASH_DRIVER_SEG void duet_flash_alg_calibrate_shift(int prescaler)
479 {
480     volatile int delay_shift = 0;
481     volatile int sshift = 0;
482     unsigned int rdata;
483     unsigned int wdata;
484     unsigned int identi;
485     volatile int id, mem_type, capacity;
486     int i = 0;
487     int sshift_max[8] = {0};
488     int sshift_min[8] = {0};
489     int match_flag[8] = {0};
490     int match_interval[8] = {0};
491 
492     // *(volatile int *)(0x40000808) = 0x2;
493     REG_WR(CLK_FLASH_SEL, FLASH_240_CLK);
494 
495     for (delay_shift = 0; delay_shift < 8; delay_shift = delay_shift + 1) {
496         sshift_max[delay_shift] = 0;
497         sshift_min[delay_shift] = 0;
498         for (sshift = 0; sshift < prescaler; sshift = sshift + 1) {
499             rdata = FLASH->QSPI_CR;
500             wdata = rdata & 0x87FF1FFF;
501             wdata |= (sshift & 0xF) << 27;
502             wdata |= (delay_shift & 0x7) << 13;
503             FLASH->QSPI_CR = wdata;
504             // read_id
505             identi = duet_flash_alg_read_id();
506 
507             id = identi & 0xFF;
508             mem_type = (identi & 0xFF00) >> 8;
509             capacity = (identi & 0xFF0000) >> 16;
510 
511             if (id == 0x0B && mem_type == 0x40 && capacity == 0x15) {
512                 match_flag[delay_shift] = 0x1;
513                 if (sshift_max[delay_shift] < sshift) {
514                     sshift_max[delay_shift] = sshift;
515                 }
516                 if (sshift_min[delay_shift] > sshift) {
517                     sshift_min[delay_shift] = sshift;
518                 }
519             } else {
520                 sshift_min[delay_shift] = sshift + 1;
521                 if (sshift_min[delay_shift] == prescaler) {
522                     sshift_min[delay_shift] = 0;
523                 }
524             }
525         }
526     }
527 
528     for (i = 0; i < 8; i++) {
529         if (match_flag[i] == 1) {
530             match_interval[i] = sshift_max[i] - sshift_min[i] + 1;
531         } else {
532             match_interval[i] = 0;
533         }
534     }
535     // get the best delay_shift(means max mactch_interval
536     delay_shift = 0;
537     for (i = 1; i < 8; i = i + 1) {
538         if (match_interval[i] > match_interval[delay_shift]) {
539             delay_shift = i;
540         }
541     }
542     sshift = (sshift_max[delay_shift] + sshift_min[delay_shift]) / 2 + (sshift_max[delay_shift] + sshift_min[delay_shift]) %
543              2;
544     rdata = FLASH->QSPI_CR;
545     wdata = rdata & 0x87FF1FFF;
546     wdata |= (sshift & 0xF) << 27;
547     wdata |= (delay_shift & 0x7) << 13;
548     FLASH->QSPI_CR = wdata;
549 
550 }
551 #endif
552 #endif
553