1 /**************************************************************************//**
2 * @file spim.c
3 * @version V1.00
4 * @brief M480 series SPIM driver
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 * @copyright (C) 2016-2020 Nuvoton Technology Corp. All rights reserved.
8 *****************************************************************************/
9
10 #include <stdio.h>
11 #include <string.h>
12 #include "NuMicro.h"
13
14
15 /** @addtogroup Standard_Driver Standard Driver
16 @{
17 */
18
19 /** @addtogroup SPIM_Driver SPIM Driver
20 @{
21 */
22
23 /** @addtogroup SPIM_EXPORTED_FUNCTIONS SPIM Exported Functions
24 @{
25 */
26
27
28 /** @cond HIDDEN_SYMBOLS */
29
30
31 #define ENABLE_DEBUG 0
32
33 #if ENABLE_DEBUG
34 #define SPIM_DBGMSG printf
35 #else
36 #define SPIM_DBGMSG(...) do { } while (0) /* disable debug */
37 #endif
38
39 static volatile uint8_t g_Supported_List[] =
40 {
41 MFGID_WINBOND,
42 MFGID_MXIC,
43 MFGID_EON,
44 MFGID_ISSI,
45 MFGID_SPANSION
46 };
47
48 static void N_delay(int n);
49 static void SwitchNBitOutput(uint32_t u32NBit);
50 static void SwitchNBitInput(uint32_t u32NBit);
51 static void spim_write(uint8_t pu8TxBuf[], uint32_t u32NTx);
52 static void spim_read(uint8_t pu8RxBuf[], uint32_t u32NRx);
53 static void SPIM_WriteStatusRegister(uint8_t dataBuf[], uint32_t u32NTx, uint32_t u32NBit);
54 static void SPIM_ReadStatusRegister(uint8_t dataBuf[], uint32_t u32NRx, uint32_t u32NBit);
55 static void SPIM_ReadStatusRegister2(uint8_t dataBuf[], uint32_t u32NRx, uint32_t u32NBit);
56 static void SPIM_WriteStatusRegister2(uint8_t dataBuf[], uint32_t u32NTx, uint32_t u32NBit);
57 static void SPIM_ReadStatusRegister3(uint8_t dataBuf[], uint32_t u32NRx, uint32_t u32NBit);
58 static void SPIM_ReadSecurityRegister(uint8_t dataBuf[], uint32_t u32NRx, uint32_t u32NBit);
59 static int spim_is_write_done(uint32_t u32NBit);
60 static int spim_wait_write_done(uint32_t u32NBit);
61 static void spim_set_write_enable(int isEn, uint32_t u32NBit);
62 static void spim_enable_spansion_quad_mode(int isEn);
63 static void spim_eon_set_qpi_mode(int isEn);
64 static void SPIM_SPANSION_4Bytes_Enable(int isEn, uint32_t u32NBit);
65 static void SPIM_WriteInPageDataByIo(uint32_t u32Addr, int is4ByteAddr, uint32_t u32NTx, uint8_t pu8TxBuf[], uint8_t wrCmd,
66 uint32_t u32NBitCmd, uint32_t u32NBitAddr, uint32_t u32NBitDat, int isSync);
67 static void SPIM_WriteInPageDataByPageWrite(uint32_t u32Addr, int is4ByteAddr, uint32_t u32NTx,
68 uint8_t pu8TxBuf[], uint32_t wrCmd, int isSync);
69
70
N_delay(int n)71 static void N_delay(int n)
72 {
73 while (n-- > 0)
74 {
75 __NOP();
76 }
77 }
78
SwitchNBitOutput(uint32_t u32NBit)79 static void SwitchNBitOutput(uint32_t u32NBit)
80 {
81 switch (u32NBit)
82 {
83 case 1UL:
84 SPIM_ENABLE_SING_OUTPUT_MODE(); /* 1-bit, Output. */
85 break;
86
87 case 2UL:
88 SPIM_ENABLE_DUAL_OUTPUT_MODE(); /* 2-bit, Output. */
89 break;
90
91 case 4UL:
92 SPIM_ENABLE_QUAD_OUTPUT_MODE(); /* 4-bit, Output. */
93 break;
94
95 default:
96 break;
97 }
98 }
99
SwitchNBitInput(uint32_t u32NBit)100 static void SwitchNBitInput(uint32_t u32NBit)
101 {
102 switch (u32NBit)
103 {
104 case 1UL:
105 SPIM_ENABLE_SING_INPUT_MODE(); /* 1-bit, Input. */
106 break;
107
108 case 2UL:
109 SPIM_ENABLE_DUAL_INPUT_MODE(); /* 2-bit, Input. */
110 break;
111
112 case 4UL:
113 SPIM_ENABLE_QUAD_INPUT_MODE(); /* 4-bit, Input. */
114 break;
115
116 default:
117 break;
118 }
119 }
120
121
122 /**
123 * @brief Write data to SPI slave.
124 * @param pu8TxBuf Transmit buffer.
125 * @param u32NTx Number of bytes to transmit.
126 * @return None.
127 */
spim_write(uint8_t pu8TxBuf[],uint32_t u32NTx)128 static void spim_write(uint8_t pu8TxBuf[], uint32_t u32NTx)
129 {
130 uint32_t buf_idx = 0UL;
131
132 while (u32NTx)
133 {
134 uint32_t dataNum = 0UL, dataNum2;
135
136 if (u32NTx >= 16UL)
137 {
138 dataNum = 4UL;
139 }
140 else if (u32NTx >= 12UL)
141 {
142 dataNum = 3UL;
143 }
144 else if (u32NTx >= 8UL)
145 {
146 dataNum = 2UL;
147 }
148 else if (u32NTx >= 4UL)
149 {
150 dataNum = 1UL;
151 }
152
153 dataNum2 = dataNum;
154 while (dataNum2)
155 {
156 uint32_t tmp;
157
158 memcpy(&tmp, &pu8TxBuf[buf_idx], 4U);
159 buf_idx += 4UL;
160 u32NTx -= 4UL;
161
162 dataNum2 --;
163 /* *((__O uint32_t *) &SPIM->TX0 + dataNum2) = tmp; */
164 SPIM->TX[dataNum2] = tmp;
165 }
166
167 if (dataNum)
168 {
169 SPIM_SET_OPMODE(SPIM_CTL0_OPMODE_IO); /* Switch to Normal mode. */
170 SPIM_SET_DATA_WIDTH(32UL);
171 SPIM_SET_DATA_NUM(dataNum);
172 SPIM_SET_GO();
173 SPIM_WAIT_FREE();
174 }
175
176 if (u32NTx && (u32NTx < 4UL))
177 {
178 uint32_t rnm, tmp;
179
180 rnm = u32NTx;
181 memcpy(&tmp, &pu8TxBuf[buf_idx], u32NTx);
182 buf_idx += u32NTx;
183 u32NTx = 0UL;
184 SPIM->TX[0] = tmp;
185
186 SPIM_SET_OPMODE(SPIM_CTL0_OPMODE_IO); /* Switch to Normal mode. */
187 SPIM_SET_DATA_WIDTH(rnm * 8UL);
188 SPIM_SET_DATA_NUM(1UL);
189 SPIM_SET_GO();
190 SPIM_WAIT_FREE();
191 }
192 }
193 }
194
195 /**
196 * @brief Read data from SPI slave.
197 * @param pu8TxBuf Receive buffer.
198 * @param u32NRx Size of receive buffer in bytes.
199 * @return None.
200 */
spim_read(uint8_t pu8RxBuf[],uint32_t u32NRx)201 static void spim_read(uint8_t pu8RxBuf[], uint32_t u32NRx)
202 {
203 uint32_t buf_idx = 0UL;
204
205 while (u32NRx)
206 {
207 uint32_t dataNum = 0UL; /* number of words */
208
209 if (u32NRx >= 16UL)
210 {
211 dataNum = 4UL;
212 }
213 else if (u32NRx >= 12UL)
214 {
215 dataNum = 3UL;
216 }
217 else if (u32NRx >= 8UL)
218 {
219 dataNum = 2UL;
220 }
221 else if (u32NRx >= 4UL)
222 {
223 dataNum = 1UL;
224 }
225
226 if (dataNum)
227 {
228 SPIM_SET_OPMODE(SPIM_CTL0_OPMODE_IO); /* Switch to Normal mode. */
229 SPIM_SET_DATA_WIDTH(32UL);
230 SPIM_SET_DATA_NUM(dataNum);
231 SPIM_SET_GO();
232 SPIM_WAIT_FREE();
233 }
234
235 while (dataNum)
236 {
237 uint32_t tmp;
238
239 tmp = SPIM->RX[dataNum-1UL];
240 memcpy(&pu8RxBuf[buf_idx], &tmp, 4U);
241 buf_idx += 4UL;
242 dataNum --;
243 u32NRx -= 4UL;
244 }
245
246 if (u32NRx && (u32NRx < 4UL))
247 {
248 uint32_t tmp;
249
250 SPIM_SET_OPMODE(SPIM_CTL0_OPMODE_IO); /* Switch to Normal mode. */
251 SPIM_SET_DATA_WIDTH(u32NRx * 8UL);
252 SPIM_SET_DATA_NUM(1UL);
253 SPIM_SET_GO();
254 SPIM_WAIT_FREE();
255
256 tmp = SPIM->RX[0];
257 memcpy(&pu8RxBuf[buf_idx], &tmp, u32NRx);
258 buf_idx += u32NRx;
259 u32NRx = 0UL;
260 }
261 }
262 }
263
264 /**
265 * @brief Issue Read Status Register #1 command.
266 * @param dataBuf Receive buffer.
267 * @param u32NRx Size of receive buffer.
268 * @param u32NBit N-bit transmit/receive.
269 * @return None.
270 */
SPIM_ReadStatusRegister(uint8_t dataBuf[],uint32_t u32NRx,uint32_t u32NBit)271 static void SPIM_ReadStatusRegister(uint8_t dataBuf[], uint32_t u32NRx, uint32_t u32NBit)
272 {
273 uint8_t cmdBuf[] = {OPCODE_RDSR}; /* 1-byte Read Status Register #1 command. */
274
275 SPIM_SET_SS_EN(1); /* CS activated. */
276 SwitchNBitOutput(u32NBit);
277 spim_write(cmdBuf, sizeof (cmdBuf));
278 SwitchNBitInput(u32NBit);
279 spim_read(dataBuf, u32NRx);
280 SPIM_SET_SS_EN(0); /* CS deactivated. */
281 }
282
283 /**
284 * @brief Issue Write Status Register #1 command.
285 * @param dataBuf Transmit buffer.
286 * @param u32NTx Size of transmit buffer.
287 * @param u32NBit N-bit transmit/receive.
288 * @return None.
289 */
SPIM_WriteStatusRegister(uint8_t dataBuf[],uint32_t u32NTx,uint32_t u32NBit)290 static void SPIM_WriteStatusRegister(uint8_t dataBuf[], uint32_t u32NTx, uint32_t u32NBit)
291 {
292 uint8_t cmdBuf[] = {OPCODE_WRSR, 0x00U}; /* 1-byte Write Status Register #1 command + 1-byte data. */
293
294 cmdBuf[1] = dataBuf[0];
295 SPIM_SET_SS_EN(1); /* CS activated. */
296 SwitchNBitOutput(u32NBit);
297 spim_write(cmdBuf, sizeof (cmdBuf));
298 SPIM_SET_SS_EN(0); /* CS deactivated. */
299 }
300
301 /**
302 * @brief Issue Read Status Register #2 command.
303 * @param dataBuf Receive buffer.
304 * @param u32NRx Size of receive buffer.
305 * @param u32NBit N-bit transmit/receive.
306 * @return None.
307 */
SPIM_ReadStatusRegister2(uint8_t dataBuf[],uint32_t u32NRx,uint32_t u32NBit)308 static void SPIM_ReadStatusRegister2(uint8_t dataBuf[], uint32_t u32NRx, uint32_t u32NBit)
309 {
310 uint8_t cmdBuf[] = {OPCODE_RDSR2}; /* 1-byte Read Status Register #1 command. */
311
312 SPIM_SET_SS_EN(1); /* CS activated. */
313 SwitchNBitOutput(u32NBit);
314 spim_write(cmdBuf, sizeof (cmdBuf));
315 SwitchNBitInput(u32NBit);
316 spim_read(dataBuf, u32NRx);
317 SPIM_SET_SS_EN(0); /* CS deactivated. */
318 }
319
320 /**
321 * @brief Issue Winbond Write Status Register command. This command write both Status Register-1
322 * and Status Register-2.
323 * @param dataBuf Transmit buffer.
324 * @param u32NTx Size of transmit buffer.
325 * @param u32NBit N-bit transmit/receive.
326 * @return None.
327 */
SPIM_WriteStatusRegister2(uint8_t dataBuf[],uint32_t u32NTx,uint32_t u32NBit)328 static void SPIM_WriteStatusRegister2(uint8_t dataBuf[], uint32_t u32NTx, uint32_t u32NBit)
329 {
330 uint8_t cmdBuf[3] = {OPCODE_WRSR, 0U, 0U};
331
332 cmdBuf[1] = dataBuf[0];
333 cmdBuf[2] = dataBuf[1];
334
335 SPIM_SET_SS_EN(1); /* CS activated. */
336 SwitchNBitOutput(u32NBit);
337 spim_write(cmdBuf, sizeof (cmdBuf));
338 SPIM_SET_SS_EN(0); /* CS deactivated. */
339 }
340
341 #if 0 /* not used */
342 /**
343 * @brief Issue Write Status Register #3 command.
344 * @param dataBuf Transmit buffer.
345 * @param u32NTx Size of transmit buffer.
346 * @param u32NBit N-bit transmit/receive.
347 * @return None.
348 */
349 static void SPIM_WriteStatusRegister3(uint8_t dataBuf[], uint32_t u32NTx, uint32_t u32NBit)
350 {
351 uint8_t cmdBuf[] = {OPCODE_WRSR3, 0x00U}; /* 1-byte Write Status Register #2 command + 1-byte data. */
352 cmdBuf[1] = dataBuf[0];
353
354 SPIM_SET_SS_EN(1); /* CS activated. */
355 SwitchNBitOutput(u32NBit);
356 spim_write(cmdBuf, sizeof (cmdBuf));
357 SPIM_SET_SS_EN(0); /* CS deactivated. */
358 }
359 #endif
360
361 /**
362 * @brief Issue Read Status Register #3 command.
363 * @param dataBuf Receive buffer.
364 * @param u32NRx Size of receive buffer.
365 * @param u32NBit N-bit transmit/receive.
366 * @return None.
367 */
SPIM_ReadStatusRegister3(uint8_t dataBuf[],uint32_t u32NRx,uint32_t u32NBit)368 static void SPIM_ReadStatusRegister3(uint8_t dataBuf[], uint32_t u32NRx, uint32_t u32NBit)
369 {
370 uint8_t cmdBuf[] = {OPCODE_RDSR3}; /* 1-byte Read Status Register #1 command. */
371
372 SPIM_SET_SS_EN(1); /* CS activated. */
373 SwitchNBitOutput(u32NBit);
374 spim_write(cmdBuf, sizeof (cmdBuf));
375 SwitchNBitInput(u32NBit);
376 spim_read(dataBuf, u32NRx);
377 SPIM_SET_SS_EN(0); /* CS deactivated. */
378 }
379
380 #if 0 /* not used */
381 /**
382 * @brief Issue Write Security Register command.
383 * @param dataBuf Transmit buffer.
384 * @param u32NTx Size of transmit buffer.
385 * @param u32NBit N-bit transmit/receive.
386 * @return None.
387 */
388 static void SPIM_WriteSecurityRegister(uint8_t dataBuf[], uint32_t u32NTx, uint32_t u32NBit)
389 {
390 uint8_t cmdBuf[] = {OPCODE_WRSCUR, 0x00U}; /* 1-byte Write Status Register #2 command + 1-byte data. */
391 cmdBuf[1] = dataBuf[0];
392
393 SPIM_SET_SS_EN(1); /* CS activated. */
394 SwitchNBitOutput(u32NBit);
395 spim_write(cmdBuf, sizeof (cmdBuf));
396 SPIM_SET_SS_EN(0); /* CS deactivated. */
397 }
398 #endif
399
400 /**
401 * @brief Issue Read Security Register command.
402 * @param dataBuf Receive buffer.
403 * @param u32NRx Size of receive buffer.
404 * @param u32NBit N-bit transmit/receive.
405 * @return None.
406 */
SPIM_ReadSecurityRegister(uint8_t dataBuf[],uint32_t u32NRx,uint32_t u32NBit)407 static void SPIM_ReadSecurityRegister(uint8_t dataBuf[], uint32_t u32NRx, uint32_t u32NBit)
408 {
409 uint8_t cmdBuf[] = {OPCODE_RDSCUR}; /* 1-byte Read Status Register #1 command. */
410
411 SPIM_SET_SS_EN(1); /* CS activated. */
412 SwitchNBitOutput(u32NBit);
413 spim_write(cmdBuf, sizeof (cmdBuf));
414 SwitchNBitInput(u32NBit);
415 spim_read(dataBuf, u32NRx);
416 SPIM_SET_SS_EN(0); /* CS deactivated. */
417 }
418
419 /**
420 * @brief Check if Erase/Write is done.
421 * @return 0: Not done. 1: Done.
422 */
spim_is_write_done(uint32_t u32NBit)423 static int spim_is_write_done(uint32_t u32NBit)
424 {
425 uint8_t status[1];
426 SPIM_ReadStatusRegister(status, sizeof (status), u32NBit);
427 return ! (status[0] & SR_WIP);
428 }
429
430 /**
431 * @brief Wait until Erase/Write done.
432 * @param u32NBit N-bit transmit/receive.
433 * @return 0 SPIM write done.
434 */
spim_wait_write_done(uint32_t u32NBit)435 static int spim_wait_write_done(uint32_t u32NBit)
436 {
437 uint32_t count;
438 int ret = -1;
439
440 for (count = 0UL; count < SystemCoreClock/1000UL; count++)
441 {
442 if (spim_is_write_done(u32NBit))
443 {
444 ret = 0;
445 break;
446 }
447 }
448 if (ret != 0)
449 {
450 SPIM_DBGMSG("spim_wait_write_done time-out!!\n");
451 }
452 return ret;
453 }
454
455 /**
456 * @brief Issue Write Enable/disable command.
457 * @param isEn Enable/disable.
458 * @param u32NBit N-bit transmit/receive.
459 * @return None.
460 */
spim_set_write_enable(int isEn,uint32_t u32NBit)461 static void spim_set_write_enable(int isEn, uint32_t u32NBit)
462 {
463 uint8_t cmdBuf[] = {0U}; /* 1-byte Write Enable command. */
464 cmdBuf[0] = isEn ? OPCODE_WREN : OPCODE_WRDI;
465
466 SPIM_SET_SS_EN(1); /* CS activated. */
467 SwitchNBitOutput(u32NBit);
468 spim_write(cmdBuf, sizeof (cmdBuf));
469 SPIM_SET_SS_EN(0); /* CS deactivated. */
470 }
471
472 /** @endcond HIDDEN_SYMBOLS */
473
474 /**
475 * @brief Get SPIM serial clock.
476 * @return SPI serial clock.
477 * @details This function calculates the serial clock of SPI in Hz.
478 */
SPIM_GetSClkFreq(void)479 uint32_t SPIM_GetSClkFreq(void)
480 {
481 uint32_t clkDiv = SPIM_GET_CLOCK_DIVIDER();
482
483 return clkDiv ? SystemCoreClock / (clkDiv * 2U) : SystemCoreClock;
484 }
485
486 /**
487 * @brief Initialize SPIM flash.
488 * @param clrWP Clear Write Protect or not.
489 * @return 0 Success.
490 * @return -1 Unrecognized manufacture ID or failed on reading manufacture ID.
491 */
SPIM_InitFlash(int clrWP)492 int SPIM_InitFlash(int clrWP)
493 {
494 uint8_t idBuf[3];
495 uint8_t cmdBuf[1];
496 uint32_t i;
497 int32_t ret = -1;
498
499 SPIM_SET_SS_ACTLVL(0);
500
501 /*
502 * Because not sure in SPI or QPI mode, do QPI reset and then SPI reset.
503 */
504 /* QPI Reset Enable */
505 cmdBuf[0] = OPCODE_RSTEN;
506 SPIM_SET_SS_EN(1); /* CS activated. */
507 SPIM_ENABLE_QUAD_OUTPUT_MODE(); /* 1-bit, Output. */
508 spim_write(cmdBuf, sizeof (cmdBuf));
509 SPIM_SET_SS_EN(0); /* CS deactivated. */
510
511 /* QPI Reset */
512 cmdBuf[0] = OPCODE_RST;
513 SPIM_SET_SS_EN(1); /* CS activated. */
514 SPIM_ENABLE_QUAD_OUTPUT_MODE(); /* 1-bit, Output. */
515 spim_write(cmdBuf, sizeof (cmdBuf));
516 SPIM_SET_SS_EN(0); /* CS deactivated. */
517
518 /* SPI ResetEnable */
519 cmdBuf[0] = OPCODE_RSTEN;
520 SPIM_SET_SS_EN(1); /* CS activated. */
521 SPIM_ENABLE_SING_OUTPUT_MODE(); /* 1-bit, Output. */
522 spim_write(cmdBuf, sizeof (cmdBuf));
523 SPIM_SET_SS_EN(0); /* CS deactivated. */
524
525 /* SPI Reset */
526 cmdBuf[0] = OPCODE_RST;
527 SPIM_SET_SS_EN(1); /* CS activated. */
528 SPIM_ENABLE_SING_OUTPUT_MODE(); /* 1-bit, Output. */
529 spim_write(cmdBuf, sizeof (cmdBuf));
530 SPIM_SET_SS_EN(0); /* CS deactivated. */
531
532 if (clrWP)
533 {
534 uint8_t dataBuf[] = {0x00U};
535
536 spim_set_write_enable(1, 1UL); /* Clear Block Protect. */
537 SPIM_WriteStatusRegister(dataBuf, sizeof (dataBuf), 1U);
538 spim_wait_write_done(1UL);
539 }
540
541 SPIM_ReadJedecId(idBuf, sizeof (idBuf), 1UL);
542
543 /* printf("ID: 0x%x, 0x%x, px%x\n", idBuf[0], idBuf[1], idBuf[2]); */
544
545 for (i = 0UL; i < sizeof(g_Supported_List)/sizeof(g_Supported_List[0]); i++)
546 {
547 if (idBuf[0] == g_Supported_List[i])
548 {
549 ret = 0;
550 }
551 }
552 if (ret != 0)
553 {
554 SPIM_DBGMSG("Flash initialize failed!! 0x%x\n", idBuf[0]);
555 }
556 return ret;
557 }
558
559 /**
560 * @brief Issue JEDEC ID command.
561 * @param idBuf ID buffer.
562 * @param u32NRx Size of ID buffer.
563 * @param u32NBit N-bit transmit/receive.
564 * @return None.
565 */
SPIM_ReadJedecId(uint8_t idBuf[],uint32_t u32NRx,uint32_t u32NBit)566 void SPIM_ReadJedecId(uint8_t idBuf[], uint32_t u32NRx, uint32_t u32NBit)
567 {
568 uint8_t cmdBuf[] = { OPCODE_RDID }; /* 1-byte JEDEC ID command. */
569
570 SPIM_SET_SS_EN(1); /* CS activated. */
571 SwitchNBitOutput(u32NBit);
572 spim_write(cmdBuf, sizeof (cmdBuf));
573 SwitchNBitInput(u32NBit);
574 spim_read(idBuf, u32NRx);
575 SPIM_SET_SS_EN(0); /* CS deactivated. */
576 }
577
578 /** @cond HIDDEN_SYMBOLS */
579
spim_enable_spansion_quad_mode(int isEn)580 static void spim_enable_spansion_quad_mode(int isEn)
581 {
582 uint8_t cmdBuf[3];
583 uint8_t dataBuf[1], status1;
584
585 cmdBuf[0] = 0x5U; /* Read Status Register-1 */
586
587 SPIM_SET_SS_EN(1);
588 SwitchNBitOutput(1UL);
589 spim_write(cmdBuf, sizeof (cmdBuf));
590 SwitchNBitInput(1UL);
591 spim_read(dataBuf, sizeof (dataBuf));
592 SPIM_SET_SS_EN(0);
593 /* SPIM_DBGMSG("SR1 = 0x%x\n", dataBuf[0]); */
594
595 status1 = dataBuf[0];
596
597 cmdBuf[0] = 0x35U; /* Read Configuration Register-1 */
598
599 SPIM_SET_SS_EN(1);
600 SwitchNBitOutput(1UL);
601 spim_write(cmdBuf, sizeof (cmdBuf));
602 SwitchNBitInput(1UL);
603 spim_read(dataBuf, sizeof (dataBuf));
604 SPIM_SET_SS_EN(0);
605 /* SPIM_DBGMSG("CR1 = 0x%x\n", dataBuf[0]); */
606
607 spim_set_write_enable(1, 1UL);
608
609 cmdBuf[0] = 0x1U; /* Write register */
610 cmdBuf[1] = status1;
611
612 if (isEn)
613 {
614 cmdBuf[2] = dataBuf[0] | 0x2U; /* set QUAD */
615 }
616 else
617 {
618 cmdBuf[2] = dataBuf[0] & ~0x2U; /* clear QUAD */
619 }
620
621 SPIM_SET_SS_EN(1);
622 SwitchNBitOutput(1UL);
623 spim_write(cmdBuf, 3UL);
624 SPIM_SET_SS_EN(0);
625
626 spim_set_write_enable(0, 1UL);
627
628
629 cmdBuf[0] = 0x35U; /* Read Configuration Register-1 */
630
631 SPIM_SET_SS_EN(1);
632 SwitchNBitOutput(1UL);
633 spim_write(cmdBuf, sizeof (cmdBuf));
634 SwitchNBitInput(1UL);
635 spim_read(dataBuf, sizeof (dataBuf));
636 SPIM_SET_SS_EN(0);
637
638 /* SPIM_DBGMSG("CR1 = 0x%x\n", dataBuf[0]); */
639 N_delay(10000);
640 }
641
642 /** @endcond HIDDEN_SYMBOLS */
643
644 /**
645 * @brief Set Quad Enable/disable.
646 * @param isEn Enable/disable.
647 * @param u32NBit N-bit transmit/receive.
648 * @return None.
649 */
SPIM_SetQuadEnable(int isEn,uint32_t u32NBit)650 void SPIM_SetQuadEnable(int isEn, uint32_t u32NBit)
651 {
652 uint8_t idBuf[3];
653 uint8_t dataBuf[2];
654
655 SPIM_ReadJedecId(idBuf, sizeof (idBuf), u32NBit);
656
657 SPIM_DBGMSG("SPIM_SetQuadEnable - Flash ID is 0x%x\n", idBuf[0]);
658
659 switch (idBuf[0])
660 {
661 case MFGID_WINBOND: /* Winbond SPI flash */
662 SPIM_ReadStatusRegister(&dataBuf[0], 1UL, u32NBit);
663 SPIM_ReadStatusRegister2(&dataBuf[1], 1UL, u32NBit);
664 SPIM_DBGMSG("Status Register: 0x%x - 0x%x\n", dataBuf[0], dataBuf[1]);
665 if (isEn)
666 {
667 dataBuf[1] |= SR2_QE;
668 }
669 else
670 {
671 dataBuf[1] &= ~SR2_QE;
672 }
673
674 spim_set_write_enable(1, u32NBit); /* Write Enable. */
675 SPIM_WriteStatusRegister2(dataBuf, sizeof (dataBuf), u32NBit);
676 spim_wait_write_done(u32NBit);
677
678 SPIM_ReadStatusRegister(&dataBuf[0], 1UL, u32NBit);
679 SPIM_ReadStatusRegister2(&dataBuf[1], 1UL, u32NBit);
680 SPIM_DBGMSG("Status Register: 0x%x - 0x%x\n", dataBuf[0], dataBuf[1]);
681 break;
682
683 case MFGID_MXIC: /* MXIC SPI flash. */
684 case MFGID_EON:
685 case MFGID_ISSI: /* ISSI SPI flash. */
686 spim_set_write_enable(1, u32NBit); /* Write Enable. */
687 dataBuf[0] = isEn ? SR_QE : 0U;
688 SPIM_WriteStatusRegister(dataBuf, sizeof (dataBuf), u32NBit);
689 spim_wait_write_done(u32NBit);
690 break;
691
692 case MFGID_SPANSION:
693 spim_enable_spansion_quad_mode(isEn);
694 break;
695
696 default:
697 break;
698 }
699 }
700
701 /**
702 * @brief Enter/exit QPI mode.
703 * @param isEn Enable/disable.
704 * @return None.
705 */
spim_eon_set_qpi_mode(int isEn)706 static void spim_eon_set_qpi_mode(int isEn)
707 {
708 uint8_t cmdBuf[1]; /* 1-byte command. */
709
710 uint8_t status[1];
711 SPIM_ReadStatusRegister(status, sizeof (status), 1UL);
712 SPIM_DBGMSG("Status: 0x%x\n", status[0]);
713
714 if (isEn) /* Assume in SPI mode. */
715 {
716 cmdBuf[0] = OPCODE_ENQPI;
717
718 SPIM_SET_SS_EN(1); /* CS activated. */
719 SwitchNBitOutput(1UL);
720 spim_write(cmdBuf, sizeof (cmdBuf));
721 SPIM_SET_SS_EN(0); /* CS deactivated. */
722 }
723 else /* Assume in QPI mode. */
724 {
725 cmdBuf[0] = OPCODE_EXQPI;
726
727 SPIM_SET_SS_EN(1); /* CS activated. */
728 SwitchNBitOutput(4UL);
729 spim_write(cmdBuf, sizeof (cmdBuf));
730 SPIM_SET_SS_EN(0); /* CS deactivated. */
731 }
732
733 SPIM_ReadStatusRegister(status, sizeof (status), 1UL);
734 SPIM_DBGMSG("Status: 0x%x\n", status[0]);
735 }
736
737
SPIM_SPANSION_4Bytes_Enable(int isEn,uint32_t u32NBit)738 static void SPIM_SPANSION_4Bytes_Enable(int isEn, uint32_t u32NBit)
739 {
740 uint8_t cmdBuf[2];
741 uint8_t dataBuf[1];
742
743 cmdBuf[0] = OPCODE_BRRD;
744 SPIM_SET_SS_EN(1); /* CS activated. */
745 SwitchNBitOutput(u32NBit);
746 spim_write(cmdBuf, 1UL);
747 SwitchNBitInput(1UL);
748 spim_read(dataBuf, 1UL);
749 SPIM_SET_SS_EN(0); /* CS deactivated. */
750
751 SPIM_DBGMSG("Bank Address register= 0x%x\n", dataBuf[0]);
752
753 cmdBuf[0] = OPCODE_BRWR;
754
755 if (isEn)
756 {
757 cmdBuf[1] = dataBuf[0] | 0x80U; /* set EXTADD */
758 }
759 else
760 {
761 cmdBuf[1] = dataBuf[0] & ~0x80U; /* clear EXTADD */
762 }
763
764 SPIM_SET_SS_EN(1); /* CS activated. */
765 SwitchNBitOutput(1UL);
766 spim_write(cmdBuf, 2UL);
767 SPIM_SET_SS_EN(0); /* CS deactivated. */
768 }
769
770 /** @cond HIDDEN_SYMBOLS */
771
772 /**
773 * @brief Query 4-byte address mode enabled or not.
774 * @param u32NBit N-bit transmit/receive.
775 * @return 0: 4-byte address mode disabled. 1: 4-byte address mode enabled.
776 */
SPIM_Is4ByteModeEnable(uint32_t u32NBit)777 int SPIM_Is4ByteModeEnable(uint32_t u32NBit)
778 {
779 int isEn = 0;
780 int isSupt = 0;
781 uint8_t idBuf[3];
782 uint8_t dataBuf[1];
783
784 SPIM_ReadJedecId(idBuf, sizeof (idBuf), u32NBit);
785
786 /* Based on Flash size, check if 4-byte address mode is supported. */
787 switch (idBuf[0])
788 {
789 case MFGID_WINBOND:
790 case MFGID_MXIC:
791 case MFGID_EON:
792 isSupt = (idBuf[2] < 0x19U) ? 0L : 1L;
793 break;
794
795 case MFGID_ISSI:
796 isSupt = (idBuf[2] < 0x49U) ? 0L : 1L;
797 break;
798
799 default:
800 break;
801 }
802
803 if (isSupt != 0)
804 {
805 if (idBuf[0] == MFGID_WINBOND)
806 {
807 /* Winbond SPI flash. */
808 SPIM_ReadStatusRegister3(dataBuf, sizeof (dataBuf), u32NBit);
809 isEn = !! (dataBuf[0] & SR3_ADR);
810 }
811 else if ((idBuf[0] == MFGID_MXIC) || (idBuf[0] ==MFGID_EON))
812 {
813 /* MXIC/EON SPI flash. */
814 SPIM_ReadSecurityRegister(dataBuf, sizeof (dataBuf), u32NBit);
815 isEn = !! (dataBuf[0] & SCUR_4BYTE);
816 }
817 }
818
819 return isEn;
820 }
821
822 /** @endcond HIDDEN_SYMBOLS */
823
824
825 /**
826 * @brief Enter/Exit 4-byte address mode.
827 * @param isEn Enable/disable.
828 * @param u32NBit N-bit transmit/receive.
829 * @return 0 success
830 * -1 failed
831 */
SPIM_Enable_4Bytes_Mode(int isEn,uint32_t u32NBit)832 int SPIM_Enable_4Bytes_Mode(int isEn, uint32_t u32NBit)
833 {
834 int isSupt = 0L, ret = -1;
835 uint8_t idBuf[3];
836 uint8_t cmdBuf[1]; /* 1-byte Enter/Exit 4-Byte Mode command. */
837
838 SPIM_ReadJedecId(idBuf, sizeof (idBuf), u32NBit);
839
840 /* Based on Flash size, check if 4-byte address mode is supported. */
841 switch (idBuf[0])
842 {
843 case MFGID_WINBOND:
844 case MFGID_MXIC:
845 case MFGID_EON:
846 isSupt = (idBuf[2] < 0x19U) ? 0L : 1L;
847 break;
848
849 case MFGID_ISSI:
850 isSupt = (idBuf[2] < 0x49U) ? 0L : 1L;
851 break;
852
853 case MFGID_SPANSION:
854 SPIM_SPANSION_4Bytes_Enable(isEn, u32NBit);
855 isSupt = 1L;
856 ret = 0L;
857 break;
858
859 default:
860 break;
861 }
862
863 if ((isSupt) && (idBuf[0] != MFGID_SPANSION))
864 {
865 cmdBuf[0] = isEn ? OPCODE_EN4B : OPCODE_EX4B;
866
867 SPIM_SET_SS_EN(1); /* CS activated. */
868 SwitchNBitOutput(u32NBit);
869 spim_write(cmdBuf, sizeof (cmdBuf));
870 SPIM_SET_SS_EN(0); /* CS deactivated. */
871
872 /*
873 * FIXME: Per test, 4BYTE Indicator bit doesn't set after EN4B, which
874 * doesn't match spec(MX25L25635E), so skip the check below.
875 */
876 if (idBuf[0] != MFGID_MXIC)
877 {
878 if (isEn)
879 {
880 while (! SPIM_Is4ByteModeEnable(u32NBit)) { }
881 }
882 else
883 {
884 while (SPIM_Is4ByteModeEnable(u32NBit)) { }
885 }
886 }
887 ret = 0;
888 }
889 return ret;
890 }
891
892
SPIM_WinbondUnlock(uint32_t u32NBit)893 void SPIM_WinbondUnlock(uint32_t u32NBit)
894 {
895 uint8_t idBuf[3];
896 uint8_t dataBuf[4];
897
898 SPIM_ReadJedecId(idBuf, sizeof (idBuf), u32NBit);
899
900 if ((idBuf[0] != MFGID_WINBOND) || (idBuf[1] != 0x40) || (idBuf[2] != 0x16))
901 {
902 SPIM_DBGMSG("SPIM_WinbondUnlock - Not W25Q32, do nothing.\n");
903 return;
904 }
905
906 SPIM_ReadStatusRegister(&dataBuf[0], 1UL, u32NBit);
907 SPIM_ReadStatusRegister2(&dataBuf[1], 1UL, u32NBit);
908 SPIM_DBGMSG("Status Register: 0x%x - 0x%x\n", dataBuf[0], dataBuf[1]);
909 dataBuf[1] &= ~0x40; /* clear Status Register-1 SEC bit */
910
911 spim_set_write_enable(1, u32NBit); /* Write Enable. */
912 SPIM_WriteStatusRegister2(dataBuf, sizeof (dataBuf), u32NBit);
913 spim_wait_write_done(u32NBit);
914
915 SPIM_ReadStatusRegister(&dataBuf[0], 1UL, u32NBit);
916 SPIM_ReadStatusRegister2(&dataBuf[1], 1UL, u32NBit);
917 SPIM_DBGMSG("Status Register (after unlock): 0x%x - 0x%x\n", dataBuf[0], dataBuf[1]);
918 }
919
920 /**
921 * @brief Erase whole chip.
922 * @param u32NBit N-bit transmit/receive.
923 * @param isSync Block or not.
924 * @return None.
925 */
SPIM_ChipErase(uint32_t u32NBit,int isSync)926 void SPIM_ChipErase(uint32_t u32NBit, int isSync)
927 {
928 uint8_t cmdBuf[] = { OPCODE_CHIP_ERASE }; /* 1-byte Chip Erase command. */
929
930 spim_set_write_enable(1, u32NBit); /* Write Enable. */
931
932 SPIM_SET_SS_EN(1); /* CS activated. */
933 SwitchNBitOutput(u32NBit);
934 spim_write(cmdBuf, sizeof (cmdBuf));
935 SPIM_SET_SS_EN(0); /* CS deactivated. */
936
937 if (isSync)
938 {
939 spim_wait_write_done(u32NBit);
940 }
941 }
942
943
944 /**
945 * @brief Erase one block.
946 * @param u32Addr Block to erase which contains the u32Addr.
947 * @param is4ByteAddr 4-byte u32Address or not.
948 * @param u8ErsCmd Erase command.
949 * @param u32NBit N-bit transmit/receive.
950 * @param isSync Block or not.
951 * @return None.
952 */
SPIM_EraseBlock(uint32_t u32Addr,int is4ByteAddr,uint8_t u8ErsCmd,uint32_t u32NBit,int isSync)953 void SPIM_EraseBlock(uint32_t u32Addr, int is4ByteAddr, uint8_t u8ErsCmd, uint32_t u32NBit, int isSync)
954 {
955 uint8_t cmdBuf[16];
956 uint32_t buf_idx = 0UL;
957
958 spim_set_write_enable(1, u32NBit); /* Write Enable. */
959
960 cmdBuf[buf_idx++] = u8ErsCmd;
961
962 if (is4ByteAddr)
963 {
964 cmdBuf[buf_idx++] = (uint8_t) (u32Addr >> 24);
965 cmdBuf[buf_idx++] = (uint8_t) (u32Addr >> 16);
966 cmdBuf[buf_idx++] = (uint8_t) (u32Addr >> 8);
967 cmdBuf[buf_idx++] = (uint8_t) (u32Addr & 0xFFUL);
968 }
969 else
970 {
971 cmdBuf[buf_idx++] = (uint8_t) (u32Addr >> 16);
972 cmdBuf[buf_idx++] = (uint8_t) (u32Addr >> 8);
973 cmdBuf[buf_idx++] = (uint8_t) (u32Addr & 0xFFUL);
974 }
975
976 SPIM_SET_SS_EN(1); /* CS activated. */
977 SwitchNBitOutput(u32NBit);
978 spim_write(cmdBuf, buf_idx);
979 SPIM_SET_SS_EN(0); /* CS deactivated. */
980
981 if (isSync)
982 {
983 spim_wait_write_done(u32NBit);
984 }
985 }
986
987
988 /** @cond HIDDEN_SYMBOLS */
989
990 /**
991 * @brief Write data in the same page by I/O mode.
992 * @param u32Addr Start u32Address to write.
993 * @param is4ByteAddr 4-byte u32Address or not.
994 * @param u32NTx Number of bytes to write.
995 * @param pu8TxBuf Transmit buffer.
996 * @param wrCmd Write command.
997 * @param u32NBitCmd N-bit transmit command.
998 * @param u32NBitAddr N-bit transmit u32Address.
999 * @param u32NBitDat N-bit transmit/receive data.
1000 * @param isSync Block or not.
1001 * @return None.
1002 */
SPIM_WriteInPageDataByIo(uint32_t u32Addr,int is4ByteAddr,uint32_t u32NTx,uint8_t pu8TxBuf[],uint8_t wrCmd,uint32_t u32NBitCmd,uint32_t u32NBitAddr,uint32_t u32NBitDat,int isSync)1003 static void SPIM_WriteInPageDataByIo(uint32_t u32Addr, int is4ByteAddr, uint32_t u32NTx, uint8_t pu8TxBuf[], uint8_t wrCmd,
1004 uint32_t u32NBitCmd, uint32_t u32NBitAddr, uint32_t u32NBitDat, int isSync)
1005 {
1006 uint8_t cmdBuf[16];
1007 uint32_t buf_idx;
1008
1009 spim_set_write_enable(1, u32NBitCmd); /* Write Enable. */
1010
1011 SPIM_SET_SS_EN(1); /* CS activated. */
1012
1013 SwitchNBitOutput(u32NBitCmd);
1014 cmdBuf[0] = wrCmd;
1015 spim_write(cmdBuf, 1UL); /* Write out command. */
1016
1017 buf_idx = 0UL;
1018 if (is4ByteAddr)
1019 {
1020 cmdBuf[buf_idx++] = (uint8_t) (u32Addr >> 24);
1021 cmdBuf[buf_idx++] = (uint8_t) (u32Addr >> 16);
1022 cmdBuf[buf_idx++] = (uint8_t) (u32Addr >> 8);
1023 cmdBuf[buf_idx++] = (uint8_t) u32Addr;
1024 }
1025 else
1026 {
1027 cmdBuf[buf_idx++] = (uint8_t) (u32Addr >> 16);
1028 cmdBuf[buf_idx++] = (uint8_t) (u32Addr >> 8);
1029 cmdBuf[buf_idx++] = (uint8_t) u32Addr;
1030 }
1031
1032 SwitchNBitOutput(u32NBitAddr);
1033 spim_write(cmdBuf, buf_idx); /* Write out u32Address. */
1034
1035 SwitchNBitOutput(u32NBitDat);
1036 spim_write(pu8TxBuf, u32NTx); /* Write out data. */
1037
1038 SPIM_SET_SS_EN(0); /* CS deactivated. */
1039
1040 if (isSync)
1041 {
1042 spim_wait_write_done(u32NBitCmd);
1043 }
1044 }
1045
1046 /**
1047 * @brief Write data in the same page by Page Write mode.
1048 * @param u32Addr Start u32Address to write.
1049 * @param is4ByteAddr 4-byte u32Address or not.
1050 * @param u32NTx Number of bytes to write.
1051 * @param pu8TxBuf Transmit buffer.
1052 * @param wrCmd Write command.
1053 * @param isSync Block or not.
1054 * @return None.
1055 */
SPIM_WriteInPageDataByPageWrite(uint32_t u32Addr,int is4ByteAddr,uint32_t u32NTx,uint8_t pu8TxBuf[],uint32_t wrCmd,int isSync)1056 static void SPIM_WriteInPageDataByPageWrite(uint32_t u32Addr, int is4ByteAddr, uint32_t u32NTx,
1057 uint8_t pu8TxBuf[], uint32_t wrCmd, int isSync)
1058 {
1059 if ((wrCmd == CMD_QUAD_PAGE_PROGRAM_WINBOND) ||
1060 (wrCmd == CMD_QUAD_PAGE_PROGRAM_MXIC))
1061 {
1062 SPIM_SetQuadEnable(1, 1UL); /* Set Quad Enable. */
1063 }
1064 else if (wrCmd == CMD_QUAD_PAGE_PROGRAM_EON)
1065 {
1066 SPIM_SetQuadEnable(1, 1UL); /* Set Quad Enable. */
1067 spim_eon_set_qpi_mode(1); /* Enter QPI mode. */
1068 }
1069
1070 SPIM_SET_OPMODE(SPIM_CTL0_OPMODE_PAGEWRITE);/* Switch to Page Write mode. */
1071 SPIM_SET_SPIM_MODE(wrCmd); /* SPIM mode. */
1072 SPIM_SET_4BYTE_ADDR_EN(is4ByteAddr); /* Enable/disable 4-Byte Address. */
1073
1074 SPIM->SRAMADDR = (uint32_t) pu8TxBuf; /* SRAM u32Address. */
1075 SPIM->DMACNT = u32NTx; /* Transfer length. */
1076 SPIM->FADDR = u32Addr; /* Flash u32Address.*/
1077 SPIM_SET_GO(); /* Go. */
1078
1079 if (isSync)
1080 {
1081 SPIM_WAIT_FREE();
1082 }
1083
1084 if (wrCmd == CMD_QUAD_PAGE_PROGRAM_EON)
1085 {
1086 spim_eon_set_qpi_mode(0); /* Exit QPI mode. */
1087 }
1088 }
1089
1090 /** @endcond HIDDEN_SYMBOLS */
1091
1092 /**
1093 * @brief Write data to SPI Flash by sending commands manually (I/O mode).
1094 * @param u32Addr: Start u32Address to write.
1095 * @param is4ByteAddr: 4-byte u32Address or not.
1096 * @param u32NTx: Number of bytes to write.
1097 * @param pu8TxBuf: Transmit buffer.
1098 * @param wrCmd: Write command.
1099 * @param u32NBitCmd: N-bit transmit command.
1100 * @param u32NBitAddr: N-bit transmit u32Address.
1101 * @param u32NBitDat: N-bit transmit/receive data.
1102 * @return None.
1103 */
SPIM_IO_Write(uint32_t u32Addr,int is4ByteAddr,uint32_t u32NTx,uint8_t pu8TxBuf[],uint8_t wrCmd,uint32_t u32NBitCmd,uint32_t u32NBitAddr,uint32_t u32NBitDat)1104 void SPIM_IO_Write(uint32_t u32Addr, int is4ByteAddr, uint32_t u32NTx, uint8_t pu8TxBuf[], uint8_t wrCmd,
1105 uint32_t u32NBitCmd, uint32_t u32NBitAddr, uint32_t u32NBitDat)
1106 {
1107 uint32_t pageOffset, toWr;
1108 uint32_t buf_idx = 0UL;
1109
1110 pageOffset = u32Addr % 256UL;
1111
1112 if ((pageOffset + u32NTx) <= 256UL) /* Do all the bytes fit onto one page ? */
1113 {
1114 SPIM_WriteInPageDataByIo(u32Addr, is4ByteAddr, u32NTx, &pu8TxBuf[buf_idx],
1115 wrCmd, u32NBitCmd, u32NBitAddr, u32NBitDat, 1);
1116 }
1117 else
1118 {
1119 toWr = 256UL - pageOffset; /* Size of data remaining on the first page. */
1120
1121 SPIM_WriteInPageDataByIo(u32Addr, is4ByteAddr, toWr, &pu8TxBuf[buf_idx],
1122 wrCmd, u32NBitCmd, u32NBitAddr, u32NBitDat, 1);
1123 u32Addr += toWr; /* Advance indicator. */
1124 u32NTx -= toWr;
1125 buf_idx += toWr;
1126
1127 while (u32NTx)
1128 {
1129 toWr = 256UL;
1130 if (toWr > u32NTx)
1131 {
1132 toWr = u32NTx;
1133 }
1134
1135 SPIM_WriteInPageDataByIo(u32Addr, is4ByteAddr, toWr, &pu8TxBuf[buf_idx],
1136 wrCmd, u32NBitCmd, u32NBitAddr, u32NBitDat, 1);
1137 u32Addr += toWr; /* Advance indicator. */
1138 u32NTx -= toWr;
1139 buf_idx += toWr;
1140 }
1141 }
1142 }
1143
1144 /**
1145 * @brief Read data from SPI Flash by sending commands manually (I/O mode).
1146 * @param u32Addr Start u32Address to read.
1147 * @param is4ByteAddr 4-byte u32Address or not.
1148 * @param u32NRx Number of bytes to read.
1149 * @param pu8RxBuf Receive buffer.
1150 * @param rdCmd Read command.
1151 * @param u32NBitCmd N-bit transmit command.
1152 * @param u32NBitAddr N-bit transmit u32Address.
1153 * @param u32NBitDat N-bit transmit/receive data.
1154 * @param u32NDummy Number of dummy bytes following address.
1155 * @return None.
1156 */
SPIM_IO_Read(uint32_t u32Addr,int is4ByteAddr,uint32_t u32NRx,uint8_t pu8RxBuf[],uint8_t rdCmd,uint32_t u32NBitCmd,uint32_t u32NBitAddr,uint32_t u32NBitDat,int u32NDummy)1157 void SPIM_IO_Read(uint32_t u32Addr, int is4ByteAddr, uint32_t u32NRx, uint8_t pu8RxBuf[], uint8_t rdCmd,
1158 uint32_t u32NBitCmd, uint32_t u32NBitAddr, uint32_t u32NBitDat, int u32NDummy)
1159 {
1160 uint8_t cmdBuf[16];
1161 uint32_t buf_idx;
1162
1163 SPIM_SET_SS_EN(1); /* CS activated. */
1164
1165 cmdBuf[0] = rdCmd;
1166 SwitchNBitOutput(u32NBitCmd);
1167 spim_write(cmdBuf, 1UL); /* Write out command. */
1168
1169 buf_idx = 0UL;
1170 if (is4ByteAddr)
1171 {
1172 cmdBuf[buf_idx++] = (uint8_t) (u32Addr >> 24);
1173 cmdBuf[buf_idx++] = (uint8_t) (u32Addr >> 16);
1174 cmdBuf[buf_idx++] = (uint8_t) (u32Addr >> 8);
1175 cmdBuf[buf_idx++] = (uint8_t) u32Addr;
1176 }
1177 else
1178 {
1179 cmdBuf[buf_idx++] = (uint8_t) (u32Addr >> 16);
1180 cmdBuf[buf_idx++] = (uint8_t) (u32Addr >> 8);
1181 cmdBuf[buf_idx++] = (uint8_t) u32Addr;
1182 }
1183 SwitchNBitOutput(u32NBitAddr);
1184 spim_write(cmdBuf, buf_idx); /* Write out u32Address. */
1185
1186 buf_idx = 0UL;
1187 while (u32NDummy --)
1188 {
1189 cmdBuf[buf_idx++] = 0x00U;
1190 }
1191
1192 /* Same bit mode as above. */
1193 spim_write(cmdBuf, buf_idx); /* Write out dummy bytes. */
1194
1195 SwitchNBitInput(u32NBitDat);
1196 spim_read(pu8RxBuf, u32NRx); /* Read back data. */
1197
1198 SPIM_SET_SS_EN(0); /* CS deactivated. */
1199 }
1200
1201 /**
1202 * @brief Write data to SPI Flash by Page Write mode.
1203 * @param u32Addr Start address to write.
1204 * @param is4ByteAddr 4-byte address or not.
1205 * @param u32NTx Number of bytes to write.
1206 * @param pu8TxBuf Transmit buffer.
1207 * @param wrCmd Write command.
1208 * @return None.
1209 */
SPIM_DMA_Write(uint32_t u32Addr,int is4ByteAddr,uint32_t u32NTx,uint8_t pu8TxBuf[],uint32_t wrCmd)1210 void SPIM_DMA_Write(uint32_t u32Addr, int is4ByteAddr, uint32_t u32NTx, uint8_t pu8TxBuf[], uint32_t wrCmd)
1211 {
1212 uint32_t pageOffset, toWr;
1213 uint32_t buf_idx = 0UL;
1214
1215 pageOffset = u32Addr % 256UL;
1216
1217 if ((pageOffset + u32NTx) <= 256UL)
1218 {
1219 /* Do all the bytes fit onto one page ? */
1220 SPIM_WriteInPageDataByPageWrite(u32Addr, is4ByteAddr, u32NTx, pu8TxBuf, wrCmd, 1);
1221 }
1222 else
1223 {
1224 toWr = 256UL - pageOffset; /* Size of data remaining on the first page. */
1225
1226 SPIM_WriteInPageDataByPageWrite(u32Addr, is4ByteAddr, toWr, &pu8TxBuf[buf_idx], wrCmd, 1);
1227
1228 u32Addr += toWr; /* Advance indicator. */
1229 u32NTx -= toWr;
1230 buf_idx += toWr;
1231
1232 while (u32NTx)
1233 {
1234 toWr = 256UL;
1235 if (toWr > u32NTx)
1236 {
1237 toWr = u32NTx;
1238 }
1239
1240 SPIM_WriteInPageDataByPageWrite(u32Addr, is4ByteAddr, toWr, &pu8TxBuf[buf_idx], wrCmd, 1);
1241
1242 u32Addr += toWr; /* Advance indicator. */
1243 u32NTx -= toWr;
1244 buf_idx += toWr;
1245 }
1246 }
1247 }
1248
1249 /**
1250 * @brief Read data from SPI Flash by Page Read mode.
1251 * @param u32Addr Start address to read.
1252 * @param is4ByteAddr 4-byte u32Address or not.
1253 * @param u32NRx Number of bytes to read.
1254 * @param pu8RxBuf Receive buffer.
1255 * @param u32RdCmd Read command.
1256 * @param isSync Block or not.
1257 * @return None.
1258 */
SPIM_DMA_Read(uint32_t u32Addr,int is4ByteAddr,uint32_t u32NRx,uint8_t pu8RxBuf[],uint32_t u32RdCmd,int isSync)1259 void SPIM_DMA_Read(uint32_t u32Addr, int is4ByteAddr, uint32_t u32NRx, uint8_t pu8RxBuf[],
1260 uint32_t u32RdCmd, int isSync)
1261 {
1262 SPIM_SET_OPMODE(SPIM_CTL0_OPMODE_PAGEREAD); /* Switch to Page Read mode. */
1263 SPIM_SET_SPIM_MODE(u32RdCmd); /* SPIM mode. */
1264 SPIM_SET_4BYTE_ADDR_EN(is4ByteAddr); /* Enable/disable 4-Byte Address. */
1265
1266 SPIM->SRAMADDR = (uint32_t) pu8RxBuf; /* SRAM u32Address. */
1267 SPIM->DMACNT = u32NRx; /* Transfer length. */
1268 SPIM->FADDR = u32Addr; /* Flash u32Address.*/
1269 SPIM_SET_GO(); /* Go. */
1270
1271 if (isSync)
1272 {
1273 SPIM_WAIT_FREE(); /* Wait for DMA done. */
1274 }
1275 }
1276
1277 /**
1278 * @brief Enter Direct Map mode.
1279 * @param is4ByteAddr 4-byte u32Address or not.
1280 * @param u32RdCmd Read command.
1281 * @param u32IdleIntvl Idle interval.
1282 * @return None.
1283 */
SPIM_EnterDirectMapMode(int is4ByteAddr,uint32_t u32RdCmd,uint32_t u32IdleIntvl)1284 void SPIM_EnterDirectMapMode(int is4ByteAddr, uint32_t u32RdCmd, uint32_t u32IdleIntvl)
1285 {
1286 SPIM_SET_4BYTE_ADDR_EN(is4ByteAddr); /* Enable/disable 4-byte u32Address. */
1287 SPIM_SET_SPIM_MODE(u32RdCmd); /* SPIM mode. */
1288 SPIM_SET_IDL_INTVL(u32IdleIntvl); /* Idle interval. */
1289 SPIM_SET_OPMODE(SPIM_CTL0_OPMODE_DIRECTMAP); /* Switch to Direct Map mode. */
1290 }
1291
1292 /**
1293 * @brief Exit Direct Map mode.
1294 * @return None.
1295 */
SPIM_ExitDirectMapMode(void)1296 void SPIM_ExitDirectMapMode(void)
1297 {
1298 SPIM_SET_OPMODE(SPIM_CTL0_OPMODE_IO); /* Switch back to Normal mode. */
1299 }
1300
1301
1302 /*@}*/ /* end of group SPIM_EXPORTED_FUNCTIONS */
1303
1304 /*@}*/ /* end of group SPIM_Driver */
1305
1306 /*@}*/ /* end of group Standard_Driver */
1307
1308 /*** (C) COPYRIGHT 2017 Nuvoton Technology Corp. ***/
1309