Merge pull request #2616 from jmichelp/fix14b
[RRG-proxmark3.git] / common_arm / flashmem.c
blob33d7db2adf9ba2f4485a8dee05f7bf76f76c4add
1 //-----------------------------------------------------------------------------
2 // Borrowed initially from Arduino SPIFlash Library v.2.5.0
3 // Copyright (C) 2015 by Prajwal Bhattaram.
4 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
5 //
6 // This program is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // See LICENSE.txt for the text of the license.
17 //-----------------------------------------------------------------------------
18 #include "flashmem.h"
19 #include "pmflash.h"
21 #include "proxmark3_arm.h"
22 #include "ticks.h"
24 #ifndef AS_BOOTROM
25 #include "dbprint.h"
26 #endif // AS_BOOTROM
28 #include "string.h"
29 #include "usb_cdc.h"
31 /* here: use NCPS2 @ PA10: */
32 #define SPI_CSR_NUM 2
33 #define SPI_PCS(npcs) ((~(1 << (npcs)) & 0xF) << 16)
34 /// Calculates the value of the CSR SCBR field given the baudrate and MCK.
35 #define SPI_SCBR(baudrate, masterClock) ((uint32_t) ((masterClock) / (baudrate)) << 8)
36 /// Calculates the value of the CSR DLYBS field given the desired delay (in ns)
37 #define SPI_DLYBS(delay, masterClock) ((uint32_t) ((((masterClock) / 1000000) * (delay)) / 1000) << 16)
38 /// Calculates the value of the CSR DLYBCT field given the desired delay (in ns)
39 #define SPI_DLYBCT(delay, masterClock) ((uint32_t) ((((masterClock) / 1000000) * (delay)) / 32000) << 24)
41 static uint32_t FLASHMEM_SPIBAUDRATE = FLASH_BAUD;
42 #define FASTFLASH (FLASHMEM_SPIBAUDRATE > FLASH_MINFAST)
44 #ifndef AS_BOOTROM
46 void FlashmemSetSpiBaudrate(uint32_t baudrate) {
47 FLASHMEM_SPIBAUDRATE = baudrate;
48 Dbprintf("Spi Baudrate : %dMHz", FLASHMEM_SPIBAUDRATE / 1000000);
51 // read ID out
52 bool Flash_ReadID(flash_device_type_t *result, bool read_jedec) {
54 if (Flash_CheckBusy(BUSY_TIMEOUT)) return false;
57 if (read_jedec) {
58 // 0x9F JEDEC
59 FlashSendByte(JEDECID);
61 result->manufacturer_id = FlashSendByte(0xFF);
62 result->device_id = FlashSendByte(0xFF);
63 result->device_id2 = FlashSendLastByte(0xFF);
64 } else {
65 // 0x90 Manufacture ID / device ID
66 FlashSendByte(ID);
67 FlashSendByte(0x00);
68 FlashSendByte(0x00);
69 FlashSendByte(0x00);
71 result->manufacturer_id = FlashSendByte(0xFF);
72 result->device_id = FlashSendLastByte(0xFF);
75 return true;
78 uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) {
80 if (!FlashInit()) return 0;
82 // length should never be zero
83 if (!len || Flash_CheckBusy(BUSY_TIMEOUT)) return 0;
85 uint8_t cmd = (FASTFLASH) ? FASTREAD : READDATA;
87 FlashSendByte(cmd);
88 Flash_TransferAdresse(address);
90 if (FASTFLASH) {
91 FlashSendByte(DUMMYBYTE);
94 uint16_t i = 0;
95 for (; i < (len - 1); i++)
96 out[i] = FlashSendByte(0xFF);
98 out[i] = FlashSendLastByte(0xFF);
99 FlashStop();
100 return len;
103 void Flash_TransferAdresse(uint32_t address) {
104 FlashSendByte((address >> 16) & 0xFF);
105 FlashSendByte((address >> 8) & 0xFF);
106 FlashSendByte((address >> 0) & 0xFF);
109 /* This ensures we can ReadData without having to cycle through initialization every time */
110 uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len) {
112 // length should never be zero
113 if (!len) return 0;
115 uint8_t cmd = (FASTFLASH) ? FASTREAD : READDATA;
117 FlashSendByte(cmd);
118 Flash_TransferAdresse(address);
120 if (FASTFLASH) {
121 FlashSendByte(DUMMYBYTE);
124 uint16_t i = 0;
125 for (; i < (len - 1); i++)
126 out[i] = FlashSendByte(0xFF);
128 out[i] = FlashSendLastByte(0xFF);
129 return len;
132 ////////////////////////////////////////
133 // Write data can only program one page. A page has 256 bytes.
134 // if len > 256, it might wrap around and overwrite pos 0.
135 uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) {
137 // length should never be zero
138 if (!len)
139 return 0;
141 // Max 256 bytes write
142 if (((address & 0xFF) + len) > 256) {
143 Dbprintf("Flash_WriteData 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF) + len, len);
144 return 0;
147 // out-of-range
148 if (((address >> 16) & 0xFF) > MAX_BLOCKS) {
149 Dbprintf("Flash_WriteData, block out-of-range");
150 return 0;
153 if (!FlashInit()) {
154 if (g_dbglevel > 3) Dbprintf("Flash_WriteData init fail");
155 return 0;
158 Flash_CheckBusy(BUSY_TIMEOUT);
160 Flash_WriteEnable();
162 FlashSendByte(PAGEPROG);
163 FlashSendByte((address >> 16) & 0xFF);
164 FlashSendByte((address >> 8) & 0xFF);
165 FlashSendByte((address >> 0) & 0xFF);
167 uint16_t i = 0;
168 for (; i < (len - 1); i++)
169 FlashSendByte(in[i]);
171 FlashSendLastByte(in[i]);
173 FlashStop();
174 return len;
177 // length should never be zero
178 // Max 256 bytes write
179 // out-of-range
180 uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len) {
182 if (!len)
183 return 0;
185 if (((address & 0xFF) + len) > 256) {
186 Dbprintf("Flash_WriteDataCont 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF) + len, len);
187 return 0;
190 if (((address >> 16) & 0xFF) > MAX_BLOCKS) {
191 Dbprintf("Flash_WriteDataCont, block out-of-range");
192 return 0;
195 FlashSendByte(PAGEPROG);
196 FlashSendByte((address >> 16) & 0xFF);
197 FlashSendByte((address >> 8) & 0xFF);
198 FlashSendByte((address >> 0) & 0xFF);
200 uint16_t i = 0;
201 for (; i < (len - 1); i++)
202 FlashSendByte(in[i]);
204 FlashSendLastByte(in[i]);
205 return len;
208 // assumes valid start 256 based 00 address
210 uint16_t Flash_Write(uint32_t address, uint8_t *in, uint16_t len) {
212 bool isok;
213 uint16_t res, bytes_sent = 0, bytes_remaining = len;
214 uint8_t buf[FLASH_MEM_BLOCK_SIZE];
215 while (bytes_remaining > 0) {
217 Flash_CheckBusy(BUSY_TIMEOUT);
218 Flash_WriteEnable();
220 uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining);
222 memcpy(buf, in + bytes_sent, bytes_in_packet);
224 res = Flash_WriteDataCont(address + bytes_sent, buf, bytes_in_packet);
226 bytes_remaining -= bytes_in_packet;
227 bytes_sent += bytes_in_packet;
229 isok = (res == bytes_in_packet);
231 if (!isok)
232 goto out;
235 out:
236 FlashStop();
237 return len;
240 // WARNING -- if callers are using a file system (such as SPIFFS),
241 // they should inform the file system of this change
242 // e.g., rdv40_spiffs_check()
243 bool Flash_WipeMemoryPage(uint8_t page) {
244 if (!FlashInit()) {
245 if (g_dbglevel > 3) Dbprintf("Flash_WriteData init fail");
246 return false;
248 Flash_ReadStat1();
250 // Each block is 64Kb. One block erase takes 1s ( 1000ms )
251 Flash_WriteEnable();
252 Flash_Erase64k(page);
253 Flash_CheckBusy(BUSY_TIMEOUT);
255 FlashStop();
257 return true;
259 // Wipes flash memory completely, fills with 0xFF
260 bool Flash_WipeMemory(void) {
261 if (!FlashInit()) {
262 if (g_dbglevel > 3) Dbprintf("Flash_WriteData init fail");
263 return false;
265 Flash_ReadStat1();
267 // Each block is 64Kb. Four blocks
268 // one block erase takes 1s ( 1000ms )
269 Flash_WriteEnable();
270 Flash_Erase64k(0);
271 Flash_CheckBusy(BUSY_TIMEOUT);
272 Flash_WriteEnable();
273 Flash_Erase64k(1);
274 Flash_CheckBusy(BUSY_TIMEOUT);
275 Flash_WriteEnable();
276 Flash_Erase64k(2);
277 Flash_CheckBusy(BUSY_TIMEOUT);
278 Flash_WriteEnable();
279 Flash_Erase64k(3);
280 Flash_CheckBusy(BUSY_TIMEOUT);
282 FlashStop();
283 return true;
286 // enable the flash write
287 void Flash_WriteEnable(void) {
288 FlashSendLastByte(WRITEENABLE);
289 if (g_dbglevel > 3) Dbprintf("Flash Write enabled");
292 // erase 4K at one time
293 // execution time: 0.8ms / 800us
294 bool Flash_Erase4k(uint8_t block, uint8_t sector) {
296 if (block > MAX_BLOCKS || sector > MAX_SECTORS) return false;
298 FlashSendByte(SECTORERASE);
299 FlashSendByte(block);
300 FlashSendByte(sector << 4);
301 FlashSendLastByte(00);
302 return true;
306 // erase 32K at one time
307 // execution time: 0,3s / 300ms
308 bool Flash_Erase32k(uint32_t address) {
309 if (address & (32*1024 - 1)) {
310 if ( g_dbglevel > 1 ) Dbprintf("Flash_Erase32k : Address is not align at 4096");
311 return false;
313 FlashSendByte(BLOCK32ERASE);
314 FlashSendByte((address >> 16) & 0xFF);
315 FlashSendByte((address >> 8) & 0xFF);
316 FlashSendLastByte((address >> 0) & 0xFF);
317 return true;
321 // erase 64k at one time
322 // since a block is 64kb, and there is four blocks.
323 // we only need block number, as MSB
324 // execution time: 1s / 1000ms
325 // 0x00 00 00 -- 0x 00 FF FF == block 0
326 // 0x01 00 00 -- 0x 01 FF FF == block 1
327 // 0x02 00 00 -- 0x 02 FF FF == block 2
328 // 0x03 00 00 -- 0x 03 FF FF == block 3
329 bool Flash_Erase64k(uint8_t block) {
331 if (block > MAX_BLOCKS) return false;
333 FlashSendByte(BLOCK64ERASE);
334 FlashSendByte(block);
335 FlashSendByte(0x00);
336 FlashSendLastByte(0x00);
337 return true;
341 // Erase chip
342 void Flash_EraseChip(void) {
343 FlashSendLastByte(CHIPERASE);
347 void Flashmem_print_status(void) {
348 DbpString(_CYAN_("Flash memory"));
349 Dbprintf(" Baudrate................ " _GREEN_("%d MHz"), FLASHMEM_SPIBAUDRATE / 1000000);
351 if (!FlashInit()) {
352 DbpString(" Init.................... " _RED_("failed"));
353 return;
355 DbpString(" Init.................... " _GREEN_("ok"));
357 // NOTE: It would likely be more useful to use JDEC ID command 9F,
358 // as it provides a third byte indicative of capacity.
359 flash_device_type_t device_type = {0};
360 if (!Flash_ReadID(&device_type, false)) {
361 DbpString(" Device ID............... " _RED_(" --> Not Found <--"));
362 } else {
363 if (device_type.manufacturer_id == WINBOND_MANID) {
364 switch (device_type.device_id) {
365 case WINBOND_32MB_DEVID:
366 DbpString(" Memory size............. " _YELLOW_("32 mbits / 4 MB"));
367 break;
368 case WINBOND_16MB_DEVID:
369 DbpString(" Memory size............. " _YELLOW_("16 mbits / 2 MB"));
370 break;
371 case WINBOND_8MB_DEVID:
372 DbpString(" Memory size............. " _YELLOW_("8 mbits / 1 MB"));
373 break;
374 case WINBOND_4MB_DEVID:
375 DbpString(" Memory size............. " _YELLOW_("4 mbits / 512 kb"));
376 break;
377 case WINBOND_2MB_DEVID:
378 DbpString(" Memory size............. " _YELLOW_("2 mbits / 256 kb"));
379 break;
380 case WINBOND_1MB_DEVID:
381 DbpString(" Memory size..... ....... " _YELLOW_("1 mbits / 128 kb"));
382 break;
383 case WINBOND_512KB_DEVID:
384 DbpString(" Memory size............. " _YELLOW_("512 kbits / 64 kb"));
385 break;
386 default:
387 Dbprintf(" Device ID............... " _YELLOW_("%02X / %02X (Winbond)"),
388 device_type.manufacturer_id,
389 device_type.device_id
391 break;
393 } else {
394 Dbprintf(" Device ID............... " _YELLOW_("%02X / %02X (unknown)"),
395 device_type.manufacturer_id,
396 device_type.device_id
399 if (Flash_ReadID(&device_type, true)) {
400 Dbprintf(" JEDEC Mfr ID / Dev ID... " _YELLOW_("%02X / %02X%02X"),
401 device_type.manufacturer_id,
402 device_type.device_id,
403 device_type.device_id2
408 uint8_t uid[8] = {0, 0, 0, 0, 0, 0, 0, 0};
409 Flash_UniqueID(uid);
410 Dbprintf(" Unique ID (be).......... " _YELLOW_("0x%02X%02X%02X%02X%02X%02X%02X%02X"),
411 uid[0], uid[1], uid[2], uid[3],
412 uid[4], uid[5], uid[6], uid[7]
414 if (g_dbglevel > 3) {
415 Dbprintf(" Unique ID (le).......... " _YELLOW_("0x%02X%02X%02X%02X%02X%02X%02X%02X"),
416 uid[7], uid[6], uid[5], uid[4],
417 uid[3], uid[2], uid[1], uid[0]
420 FlashStop();
423 void Flashmem_print_info(void) {
425 if (!FlashInit()) return;
427 DbpString(_CYAN_("Flash memory dictionary loaded"));
429 // load dictionary offsets.
430 uint8_t keysum[2];
431 uint16_t num;
433 Flash_CheckBusy(BUSY_TIMEOUT);
434 uint16_t isok = Flash_ReadDataCont(DEFAULT_MF_KEYS_OFFSET, keysum, 2);
435 if (isok == 2) {
436 num = ((keysum[1] << 8) | keysum[0]);
437 if (num != 0xFFFF && num != 0x0)
438 Dbprintf(" Mifare.................. "_YELLOW_("%u")" / "_GREEN_("%u")" keys", num, DEFAULT_MF_KEYS_MAX);
441 Flash_CheckBusy(BUSY_TIMEOUT);
442 isok = Flash_ReadDataCont(DEFAULT_T55XX_KEYS_OFFSET, keysum, 2);
443 if (isok == 2) {
444 num = ((keysum[1] << 8) | keysum[0]);
445 if (num != 0xFFFF && num != 0x0)
446 Dbprintf(" T55x7................... "_YELLOW_("%u")" / "_GREEN_("%u")" keys", num, DEFAULT_T55XX_KEYS_MAX);
449 Flash_CheckBusy(BUSY_TIMEOUT);
450 isok = Flash_ReadDataCont(DEFAULT_ICLASS_KEYS_OFFSET, keysum, 2);
451 if (isok == 2) {
452 num = ((keysum[1] << 8) | keysum[0]);
453 if (num != 0xFFFF && num != 0x0)
454 Dbprintf(" iClass.................. "_YELLOW_("%u")" / "_GREEN_("%u")" keys", num, DEFAULT_ICLASS_KEYS_MAX);
457 FlashStop();
460 #endif // #ifndef AS_BOOTROM
463 // initialize
464 bool FlashInit(void) {
465 FlashSetup(FLASHMEM_SPIBAUDRATE);
467 StartTicks();
469 if (Flash_CheckBusy(BUSY_TIMEOUT)) {
470 StopTicks();
471 return false;
474 return true;
477 // read unique id for chip.
478 void Flash_UniqueID(uint8_t *uid) {
480 if (Flash_CheckBusy(BUSY_TIMEOUT)) return;
482 // reading unique serial number
483 FlashSendByte(UNIQUE_ID);
484 FlashSendByte(0xFF);
485 FlashSendByte(0xFF);
486 FlashSendByte(0xFF);
487 FlashSendByte(0xFF);
489 uid[7] = FlashSendByte(0xFF);
490 uid[6] = FlashSendByte(0xFF);
491 uid[5] = FlashSendByte(0xFF);
492 uid[4] = FlashSendByte(0xFF);
493 uid[3] = FlashSendByte(0xFF);
494 uid[2] = FlashSendByte(0xFF);
495 uid[1] = FlashSendByte(0xFF);
496 uid[0] = FlashSendLastByte(0xFF);
499 void FlashStop(void) {
500 //Bof
501 //* Reset all the Chip Select register
502 AT91C_BASE_SPI->SPI_CSR[0] = 0;
503 AT91C_BASE_SPI->SPI_CSR[1] = 0;
504 AT91C_BASE_SPI->SPI_CSR[2] = 0;
505 AT91C_BASE_SPI->SPI_CSR[3] = 0;
507 // Reset the SPI mode
508 AT91C_BASE_SPI->SPI_MR = 0;
510 // Disable all interrupts
511 AT91C_BASE_SPI->SPI_IDR = 0xFFFFFFFF;
513 // SPI disable
514 AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS;
516 #ifndef AS_BOOTROM
517 if (g_dbglevel > 3) Dbprintf("FlashStop");
518 #endif // AS_BOOTROM
520 StopTicks();
523 void FlashSetup(uint32_t baudrate) {
524 //WDT_DISABLE
525 AT91C_BASE_WDTC->WDTC_WDMR = AT91C_WDTC_WDDIS;
527 // PA10 -> SPI_NCS2 chip select (FLASHMEM)
528 // PA11 -> SPI_NCS0 chip select (FPGA)
529 // PA12 -> SPI_MISO Master-In Slave-Out
530 // PA13 -> SPI_MOSI Master-Out Slave-In
531 // PA14 -> SPI_SPCK Serial Clock
533 // Disable PIO control of the following pins, allows use by the SPI peripheral
534 AT91C_BASE_PIOA->PIO_PDR |= (GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK | GPIO_NCS2);
536 // Pull-up Enable
537 AT91C_BASE_PIOA->PIO_PPUER |= (GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK | GPIO_NCS2);
539 // Peripheral A
540 AT91C_BASE_PIOA->PIO_ASR |= (GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK);
542 // Peripheral B
543 AT91C_BASE_PIOA->PIO_BSR |= GPIO_NCS2;
545 //enable the SPI Peripheral clock
546 AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SPI);
549 //reset spi needs double SWRST, see atmel's errata on this case
550 AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST;
551 AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST;
553 // Enable SPI
554 AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN;
556 // NPCS2 Mode 0
557 AT91C_BASE_SPI->SPI_MR =
558 (0 << 24) | // Delay between chip selects = DYLBCS/MCK BUT:
559 // If DLYBCS is less than or equal to six, six MCK periods
560 // will be inserted by default.
561 SPI_PCS(SPI_CSR_NUM) | // Peripheral Chip Select (selects SPI_NCS2 or PA10)
562 (0 << 7) | // Disable LLB (1=MOSI2MISO test mode)
563 (1 << 4) | // Disable ModeFault Protection
564 (0 << 3) | // makes spi operate at MCK (1 is MCK/2)
565 (0 << 2) | // Chip selects connected directly to peripheral
566 AT91C_SPI_PS_FIXED | // Fixed Peripheral Select
567 AT91C_SPI_MSTR; // Master Mode
569 uint8_t csaat = 1;
570 uint32_t dlybct = 0;
571 uint8_t ncpha = 1;
572 uint8_t cpol = 0;
573 if (baudrate > FLASH_MINFAST) {
574 baudrate = FLASH_FASTBAUD;
575 //csaat = 0;
576 dlybct = 1500;
577 ncpha = 0;
578 cpol = 0;
581 AT91C_BASE_SPI->SPI_CSR[2] =
582 SPI_DLYBCT(dlybct, MCK) | // Delay between Consecutive Transfers (32 MCK periods)
583 SPI_DLYBS(0, MCK) | // Delay Beforce SPCK CLock
584 SPI_SCBR(baudrate, MCK) | // SPI Baudrate Selection
585 AT91C_SPI_BITS_8 | // Bits per Transfer (8 bits)
586 //AT91C_SPI_CSAAT | // Chip Select inactive after transfer
587 // 40.4.6.2 SPI: Bad tx_ready Behavior when CSAAT = 1 and SCBR = 1
588 // If the SPI is programmed with CSAAT = 1, SCBR(baudrate) = 1 and two transfers are performed consecutively on
589 // the same slave with an IDLE state between them, the tx_ready signal does not rise after the second data has been
590 // transferred in the shifter. This can imply for example, that the second data is sent twice.
591 // COLIN :: For now we STILL use CSAAT=1 to avoid having to (de)assert NPCS manually via PIO lines and we deal with delay
592 (csaat << 3) |
593 /* Spi modes:
594 Mode CPOL CPHA NCPHA
595 0 0 0 1 clock normally low read on rising edge
596 1 0 1 0 clock normally low read on falling edge
597 2 1 0 1 clock normally high read on falling edge
598 3 1 1 0 clock normally high read on rising edge
599 However, page 512 of the AT91SAM7Sx datasheet say "Note that in SPI
600 master mode the ATSAM7S512/256/128/64/321/32 does not sample the data
601 (MISO) on the opposite edge where data clocks out (MOSI) but the same
602 edge is used as shown in Figure 36-3 and Figure 36-4." Figure 36-3
603 shows that CPOL=NCPHA=0 or CPOL=NCPHA=1 samples on the rising edge and
604 that the data changes sometime after the rising edge (about 2 ns). To
605 be consistent with normal SPI operation, it is probably safe to say
606 that the data changes on the falling edge and should be sampled on the
607 rising edge. Therefore, it appears that NCPHA should be treated the
608 same as CPHA. Thus:
609 Mode CPOL CPHA NCPHA
610 0 0 0 0 clock normally low read on rising edge
611 1 0 1 1 clock normally low read on falling edge
612 2 1 0 0 clock normally high read on falling edge
613 3 1 1 1 clock normally high read on rising edge
614 Update: for 24MHz, writing is more stable with ncpha=1, else bitflips occur.
616 (ncpha << 1) | // Clock Phase data captured on leading edge, changes on following edge
617 (cpol << 0); // Clock Polarity inactive state is logic 0
619 // read first, empty buffer
620 if (AT91C_BASE_SPI->SPI_RDR == 0) {};
623 bool Flash_CheckBusy(uint32_t timeout) {
624 WaitUS(WINBOND_WRITE_DELAY);
625 StartCountUS();
626 uint32_t _time = GetCountUS();
628 do {
629 if (!(Flash_ReadStat1() & BUSY)) {
630 return false;
632 } while ((GetCountUS() - _time) < timeout);
634 if (timeout <= (GetCountUS() - _time)) {
635 return true;
638 return false;
641 // read state register 1
642 uint8_t Flash_ReadStat1(void) {
643 FlashSendByte(READSTAT1);
644 return FlashSendLastByte(0xFF);
647 // send one byte over SPI
648 uint16_t FlashSendByte(uint32_t data) {
650 // wait until SPI is ready for transfer
651 //if you are checking for incoming data returned then the TXEMPTY flag is redundant
652 //while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0) {};
654 // send the data
655 AT91C_BASE_SPI->SPI_TDR = data;
657 //while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TDRE) == 0){};
659 // wait receive transfer is complete
660 while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF) == 0) {};
662 // reading incoming data
663 return ((AT91C_BASE_SPI->SPI_RDR) & 0xFFFF);
666 // send last byte over SPI
667 uint16_t FlashSendLastByte(uint32_t data) {
668 return FlashSendByte(data | AT91C_SPI_LASTXFER);