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