hf seos - added the skeleton for future use
[RRG-proxmark3.git] / armsrc / flashmem.c
bloba1329244241f7ee9079ebbe68ff248387b3b9d84
1 #include "flashmem.h"
2 #include "pmflash.h"
4 #include "proxmark3_arm.h"
5 #include "ticks.h"
6 #include "dbprint.h"
7 #include "string.h"
9 /* here: use NCPS2 @ PA10: */
10 #define SPI_CSR_NUM 2
11 #define SPI_PCS(npcs) ((~(1 << (npcs)) & 0xF) << 16)
12 /// Calculates the value of the CSR SCBR field given the baudrate and MCK.
13 #define SPI_SCBR(baudrate, masterClock) ((uint32_t) ((masterClock) / (baudrate)) << 8)
14 /// Calculates the value of the CSR DLYBS field given the desired delay (in ns)
15 #define SPI_DLYBS(delay, masterClock) ((uint32_t) ((((masterClock) / 1000000) * (delay)) / 1000) << 16)
16 /// Calculates the value of the CSR DLYBCT field given the desired delay (in ns)
17 #define SPI_DLYBCT(delay, masterClock) ((uint32_t) ((((masterClock) / 1000000) * (delay)) / 32000) << 24)
19 static uint32_t FLASHMEM_SPIBAUDRATE = FLASH_BAUD;
20 #define FASTFLASH (FLASHMEM_SPIBAUDRATE > FLASH_MINFAST)
22 void FlashmemSetSpiBaudrate(uint32_t baudrate) {
23 FLASHMEM_SPIBAUDRATE = baudrate;
24 Dbprintf("Spi Baudrate : %dMHz", FLASHMEM_SPIBAUDRATE / 1000000);
27 // initialize
28 bool FlashInit(void) {
29 FlashSetup(FLASHMEM_SPIBAUDRATE);
31 StartTicks();
33 if (Flash_CheckBusy(BUSY_TIMEOUT)) {
34 StopTicks();
35 return false;
38 return true;
41 void FlashSetup(uint32_t baudrate) {
42 //WDT_DISABLE
43 AT91C_BASE_WDTC->WDTC_WDMR = AT91C_WDTC_WDDIS;
45 // PA10 -> SPI_NCS2 chip select (FLASHMEM)
46 // PA11 -> SPI_NCS0 chip select (FPGA)
47 // PA12 -> SPI_MISO Master-In Slave-Out
48 // PA13 -> SPI_MOSI Master-Out Slave-In
49 // PA14 -> SPI_SPCK Serial Clock
51 // Disable PIO control of the following pins, allows use by the SPI peripheral
52 AT91C_BASE_PIOA->PIO_PDR |= (GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK | GPIO_NCS2);
54 // Pull-up Enable
55 AT91C_BASE_PIOA->PIO_PPUER |= (GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK | GPIO_NCS2);
57 // Peripheral A
58 AT91C_BASE_PIOA->PIO_ASR |= (GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK);
60 // Peripheral B
61 AT91C_BASE_PIOA->PIO_BSR |= GPIO_NCS2;
63 //enable the SPI Peripheral clock
64 AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SPI);
67 //reset spi needs double SWRST, see atmel's errata on this case
68 AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST;
69 AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST;
71 // Enable SPI
72 AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN;
74 // NPCS2 Mode 0
75 AT91C_BASE_SPI->SPI_MR =
76 (0 << 24) | // Delay between chip selects = DYLBCS/MCK BUT:
77 // If DLYBCS is less than or equal to six, six MCK periods
78 // will be inserted by default.
79 SPI_PCS(SPI_CSR_NUM) | // Peripheral Chip Select (selects SPI_NCS2 or PA10)
80 (0 << 7) | // Disable LLB (1=MOSI2MISO test mode)
81 (1 << 4) | // Disable ModeFault Protection
82 (0 << 3) | // makes spi operate at MCK (1 is MCK/2)
83 (0 << 2) | // Chip selects connected directly to peripheral
84 AT91C_SPI_PS_FIXED | // Fixed Peripheral Select
85 AT91C_SPI_MSTR; // Master Mode
87 uint8_t csaat = 1;
88 uint32_t dlybct = 0;
89 uint8_t ncpha = 1;
90 uint8_t cpol = 0;
91 if (baudrate > FLASH_MINFAST) {
92 baudrate = FLASH_FASTBAUD;
93 //csaat = 0;
94 dlybct = 1500;
95 ncpha = 0;
96 cpol = 0;
99 AT91C_BASE_SPI->SPI_CSR[2] =
100 SPI_DLYBCT(dlybct, MCK) | // Delay between Consecutive Transfers (32 MCK periods)
101 SPI_DLYBS(0, MCK) | // Delay Beforce SPCK CLock
102 SPI_SCBR(baudrate, MCK) | // SPI Baudrate Selection
103 AT91C_SPI_BITS_8 | // Bits per Transfer (8 bits)
104 //AT91C_SPI_CSAAT | // Chip Select inactive after transfer
105 // 40.4.6.2 SPI: Bad tx_ready Behavior when CSAAT = 1 and SCBR = 1
106 // If the SPI is programmed with CSAAT = 1, SCBR(baudrate) = 1 and two transfers are performed consecutively on
107 // the same slave with an IDLE state between them, the tx_ready signal does not rise after the second data has been
108 // transferred in the shifter. This can imply for example, that the second data is sent twice.
109 // COLIN :: For now we STILL use CSAAT=1 to avoid having to (de)assert NPCS manually via PIO lines and we deal with delay
110 (csaat << 3) |
111 /* Spi modes:
112 Mode CPOL CPHA NCPHA
113 0 0 0 1 clock normally low read on rising edge
114 1 0 1 0 clock normally low read on falling edge
115 2 1 0 1 clock normally high read on falling edge
116 3 1 1 0 clock normally high read on rising edge
117 However, page 512 of the AT91SAM7Sx datasheet say "Note that in SPI
118 master mode the ATSAM7S512/256/128/64/321/32 does not sample the data
119 (MISO) on the opposite edge where data clocks out (MOSI) but the same
120 edge is used as shown in Figure 36-3 and Figure 36-4." Figure 36-3
121 shows that CPOL=NCPHA=0 or CPOL=NCPHA=1 samples on the rising edge and
122 that the data changes sometime after the rising edge (about 2 ns). To
123 be consistent with normal SPI operation, it is probably safe to say
124 that the data changes on the falling edge and should be sampled on the
125 rising edge. Therefore, it appears that NCPHA should be treated the
126 same as CPHA. Thus:
127 Mode CPOL CPHA NCPHA
128 0 0 0 0 clock normally low read on rising edge
129 1 0 1 1 clock normally low read on falling edge
130 2 1 0 0 clock normally high read on falling edge
131 3 1 1 1 clock normally high read on rising edge
132 Update: for 24MHz, writing is more stable with ncpha=1, else bitflips occur.
134 (ncpha << 1) | // Clock Phase data captured on leading edge, changes on following edge
135 (cpol << 0); // Clock Polarity inactive state is logic 0
137 // read first, empty buffer
138 if (AT91C_BASE_SPI->SPI_RDR == 0) {};
141 void FlashStop(void) {
142 //Bof
143 //* Reset all the Chip Select register
144 AT91C_BASE_SPI->SPI_CSR[0] = 0;
145 AT91C_BASE_SPI->SPI_CSR[1] = 0;
146 AT91C_BASE_SPI->SPI_CSR[2] = 0;
147 AT91C_BASE_SPI->SPI_CSR[3] = 0;
149 // Reset the SPI mode
150 AT91C_BASE_SPI->SPI_MR = 0;
152 // Disable all interrupts
153 AT91C_BASE_SPI->SPI_IDR = 0xFFFFFFFF;
155 // SPI disable
156 AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS;
158 if (DBGLEVEL > 3) Dbprintf("FlashStop");
160 StopTicks();
163 // send one byte over SPI
164 uint16_t FlashSendByte(uint32_t data) {
166 // wait until SPI is ready for transfer
167 //if you are checking for incoming data returned then the TXEMPTY flag is redundant
168 //while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0) {};
170 // send the data
171 AT91C_BASE_SPI->SPI_TDR = data;
173 //while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TDRE) == 0){};
175 // wait recive transfer is complete
176 while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF) == 0) {};
178 // reading incoming data
179 return ((AT91C_BASE_SPI->SPI_RDR) & 0xFFFF);
182 // send last byte over SPI
183 uint16_t FlashSendLastByte(uint32_t data) {
184 return FlashSendByte(data | AT91C_SPI_LASTXFER);
187 // read state register 1
188 uint8_t Flash_ReadStat1(void) {
189 FlashSendByte(READSTAT1);
190 return FlashSendLastByte(0xFF);
193 bool Flash_CheckBusy(uint32_t timeout) {
194 WaitUS(WINBOND_WRITE_DELAY);
195 StartCountUS();
196 uint32_t _time = GetCountUS();
198 if (DBGLEVEL > 3) Dbprintf("Checkbusy in...");
200 do {
201 if (!(Flash_ReadStat1() & BUSY)) {
202 return false;
204 } while ((GetCountUS() - _time) < timeout);
206 if (timeout <= (GetCountUS() - _time)) {
207 return true;
210 return false;
213 // read ID out
214 uint8_t Flash_ReadID(void) {
216 if (Flash_CheckBusy(BUSY_TIMEOUT)) return 0;
218 // Manufacture ID / device ID
219 FlashSendByte(ID);
220 FlashSendByte(0x00);
221 FlashSendByte(0x00);
222 FlashSendByte(0x00);
224 uint8_t man_id = FlashSendByte(0xFF);
225 uint8_t dev_id = FlashSendLastByte(0xFF);
227 if (DBGLEVEL > 3) Dbprintf("Flash ReadID | Man ID %02x | Device ID %02x", man_id, dev_id);
229 if ((man_id == WINBOND_MANID) && (dev_id == WINBOND_DEVID))
230 return dev_id;
232 return 0;
235 // read unique id for chip.
236 void Flash_UniqueID(uint8_t *uid) {
238 if (Flash_CheckBusy(BUSY_TIMEOUT)) return;
240 // reading unique serial number
241 FlashSendByte(UNIQUE_ID);
242 FlashSendByte(0xFF);
243 FlashSendByte(0xFF);
244 FlashSendByte(0xFF);
245 FlashSendByte(0xFF);
247 uid[7] = FlashSendByte(0xFF);
248 uid[6] = FlashSendByte(0xFF);
249 uid[5] = FlashSendByte(0xFF);
250 uid[4] = FlashSendByte(0xFF);
251 uid[3] = FlashSendByte(0xFF);
252 uid[2] = FlashSendByte(0xFF);
253 uid[1] = FlashSendByte(0xFF);
254 uid[0] = FlashSendLastByte(0xFF);
257 uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) {
259 if (!FlashInit()) return 0;
261 // length should never be zero
262 if (!len || Flash_CheckBusy(BUSY_TIMEOUT)) return 0;
264 uint8_t cmd = (FASTFLASH) ? FASTREAD : READDATA;
266 FlashSendByte(cmd);
267 Flash_TransferAdresse(address);
269 if (FASTFLASH) {
270 FlashSendByte(DUMMYBYTE);
273 uint16_t i = 0;
274 for (; i < (len - 1); i++)
275 out[i] = FlashSendByte(0xFF);
277 out[i] = FlashSendLastByte(0xFF);
278 FlashStop();
279 return len;
282 void Flash_TransferAdresse(uint32_t address) {
283 FlashSendByte((address >> 16) & 0xFF);
284 FlashSendByte((address >> 8) & 0xFF);
285 FlashSendByte((address >> 0) & 0xFF);
288 /* This ensure we can ReadData without having to cycle through initialization everytime */
289 uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len) {
291 // length should never be zero
292 if (!len) return 0;
294 uint8_t cmd = (FASTFLASH) ? FASTREAD : READDATA;
296 FlashSendByte(cmd);
297 Flash_TransferAdresse(address);
299 if (FASTFLASH) {
300 FlashSendByte(DUMMYBYTE);
303 uint16_t i = 0;
304 for (; i < (len - 1); i++)
305 out[i] = FlashSendByte(0xFF);
307 out[i] = FlashSendLastByte(0xFF);
308 return len;
312 ////////////////////////////////////////
313 // Write data can only program one page. A page has 256 bytes.
314 // if len > 256, it might wrap around and overwrite pos 0.
315 uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) {
317 // length should never be zero
318 if (!len)
319 return 0;
321 // Max 256 bytes write
322 if (((address & 0xFF) + len) > 256) {
323 Dbprintf("Flash_WriteData 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF) + len, len);
324 return 0;
327 // out-of-range
328 if (((address >> 16) & 0xFF) > MAX_BLOCKS) {
329 Dbprintf("Flash_WriteData, block out-of-range");
330 return 0;
333 if (!FlashInit()) {
334 if (DBGLEVEL > 3) Dbprintf("Flash_WriteData init fail");
335 return 0;
338 Flash_CheckBusy(BUSY_TIMEOUT);
340 Flash_WriteEnable();
342 FlashSendByte(PAGEPROG);
343 FlashSendByte((address >> 16) & 0xFF);
344 FlashSendByte((address >> 8) & 0xFF);
345 FlashSendByte((address >> 0) & 0xFF);
347 uint16_t i = 0;
348 for (; i < (len - 1); i++)
349 FlashSendByte(in[i]);
351 FlashSendLastByte(in[i]);
353 FlashStop();
354 return len;
358 // length should never be zero
359 // Max 256 bytes write
360 // out-of-range
361 uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len) {
363 if (!len)
364 return 0;
366 if (((address & 0xFF) + len) > 256) {
367 Dbprintf("Flash_WriteDataCont 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF) + len, len);
368 return 0;
371 if (((address >> 16) & 0xFF) > MAX_BLOCKS) {
372 Dbprintf("Flash_WriteDataCont, block out-of-range");
373 return 0;
376 FlashSendByte(PAGEPROG);
377 FlashSendByte((address >> 16) & 0xFF);
378 FlashSendByte((address >> 8) & 0xFF);
379 FlashSendByte((address >> 0) & 0xFF);
381 uint16_t i = 0;
382 for (; i < (len - 1); i++)
383 FlashSendByte(in[i]);
385 FlashSendLastByte(in[i]);
386 return len;
389 // assumes valid start 256 based 00 address
391 uint16_t Flash_Write(uint32_t address, uint8_t *in, uint16_t len) {
393 bool isok;
394 uint16_t res, bytes_sent = 0, bytes_remaining = len;
395 uint8_t buf[FLASH_MEM_BLOCK_SIZE];
396 while (bytes_remaining > 0) {
398 Flash_CheckBusy(BUSY_TIMEOUT);
399 Flash_WriteEnable();
401 uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining);
403 memcpy(buf, in + bytes_sent, bytes_in_packet);
405 res = Flash_WriteDataCont(address + bytes_sent, buf, bytes_in_packet);
407 bytes_remaining -= bytes_in_packet;
408 bytes_sent += bytes_in_packet;
410 isok = (res == bytes_in_packet);
412 if (!isok)
413 goto out;
416 out:
417 FlashStop();
418 return len;
422 bool Flash_WipeMemoryPage(uint8_t page) {
423 if (!FlashInit()) {
424 if (DBGLEVEL > 3) Dbprintf("Flash_WriteData init fail");
425 return false;
427 Flash_ReadStat1();
429 // Each block is 64Kb. One block erase takes 1s ( 1000ms )
430 Flash_WriteEnable();
431 Flash_Erase64k(page);
432 Flash_CheckBusy(BUSY_TIMEOUT);
434 FlashStop();
435 return true;
437 // Wipes flash memory completely, fills with 0xFF
438 bool Flash_WipeMemory(void) {
439 if (!FlashInit()) {
440 if (DBGLEVEL > 3) Dbprintf("Flash_WriteData init fail");
441 return false;
443 Flash_ReadStat1();
445 // Each block is 64Kb. Four blocks
446 // one block erase takes 1s ( 1000ms )
447 Flash_WriteEnable();
448 Flash_Erase64k(0);
449 Flash_CheckBusy(BUSY_TIMEOUT);
450 Flash_WriteEnable();
451 Flash_Erase64k(1);
452 Flash_CheckBusy(BUSY_TIMEOUT);
453 Flash_WriteEnable();
454 Flash_Erase64k(2);
455 Flash_CheckBusy(BUSY_TIMEOUT);
456 Flash_WriteEnable();
457 Flash_Erase64k(3);
458 Flash_CheckBusy(BUSY_TIMEOUT);
460 FlashStop();
461 return true;
464 // enable the flash write
465 void Flash_WriteEnable(void) {
466 FlashSendLastByte(WRITEENABLE);
467 if (DBGLEVEL > 3) Dbprintf("Flash Write enabled");
470 // erase 4K at one time
471 // execution time: 0.8ms / 800us
472 bool Flash_Erase4k(uint8_t block, uint8_t sector) {
474 if (block > MAX_BLOCKS || sector > MAX_SECTORS) return false;
476 FlashSendByte(SECTORERASE);
477 FlashSendByte(block);
478 FlashSendByte(sector << 4);
479 FlashSendLastByte(00);
480 return true;
484 // erase 32K at one time
485 // execution time: 0,3s / 300ms
486 bool Flash_Erase32k(uint32_t address) {
487 if (address & (32*1024 - 1)) {
488 if ( DBGLEVEL > 1 ) Dbprintf("Flash_Erase32k : Address is not align at 4096");
489 return false;
491 FlashSendByte(BLOCK32ERASE);
492 FlashSendByte((address >> 16) & 0xFF);
493 FlashSendByte((address >> 8) & 0xFF);
494 FlashSendLastByte((address >> 0) & 0xFF);
495 return true;
499 // erase 64k at one time
500 // since a block is 64kb, and there is four blocks.
501 // we only need block number, as MSB
502 // execution time: 1s / 1000ms
503 // 0x00 00 00 -- 0x 00 FF FF == block 0
504 // 0x01 00 00 -- 0x 01 FF FF == block 1
505 // 0x02 00 00 -- 0x 02 FF FF == block 2
506 // 0x03 00 00 -- 0x 03 FF FF == block 3
507 bool Flash_Erase64k(uint8_t block) {
509 if (block > MAX_BLOCKS) return false;
511 FlashSendByte(BLOCK64ERASE);
512 FlashSendByte(block);
513 FlashSendByte(0x00);
514 FlashSendLastByte(0x00);
515 return true;
519 // Erase chip
520 void Flash_EraseChip(void) {
521 FlashSendLastByte(CHIPERASE);
525 void Flashmem_print_status(void) {
526 DbpString(_CYAN_("Flash memory"));
527 Dbprintf(" Baudrate................ " _GREEN_("%d MHz"), FLASHMEM_SPIBAUDRATE / 1000000);
529 if (!FlashInit()) {
530 DbpString(" Init.................... " _RED_("FAILED"));
531 return;
533 DbpString(" Init.................... " _GREEN_("OK"));
535 uint8_t dev_id = Flash_ReadID();
536 switch (dev_id) {
537 case 0x11 :
538 DbpString(" Memory size............. " _YELLOW_("2 mbits / 256 kb"));
539 break;
540 case 0x10 :
541 DbpString(" Memory size..... ....... " _YELLOW_("1 mbits / 128 kb"));
542 break;
543 case 0x05 :
544 DbpString(" Memory size............. " _YELLOW_("512 kbits / 64 kb"));
545 break;
546 default :
547 DbpString(" Device ID............... " _YELLOW_(" --> Unknown <--"));
548 break;
551 uint8_t uid[8] = {0, 0, 0, 0, 0, 0, 0, 0};
552 Flash_UniqueID(uid);
553 Dbprintf(" Unique ID............... 0x%02X%02X%02X%02X%02X%02X%02X%02X",
554 uid[7], uid[6], uid[5], uid[4],
555 uid[3], uid[2], uid[1], uid[0]
558 FlashStop();
561 void Flashmem_print_info(void) {
563 if (!FlashInit()) return;
565 DbpString(_CYAN_("Flash memory dictionary loaded"));
567 // load dictionary offsets.
568 uint8_t keysum[2];
569 uint16_t num;
571 Flash_CheckBusy(BUSY_TIMEOUT);
572 uint16_t isok = Flash_ReadDataCont(DEFAULT_MF_KEYS_OFFSET, keysum, 2);
573 if (isok == 2) {
574 num = ((keysum[1] << 8) | keysum[0]);
575 if (num != 0xFFFF && num != 0x0)
576 Dbprintf(" Mifare.................. "_YELLOW_("%d")" keys", num);
579 Flash_CheckBusy(BUSY_TIMEOUT);
580 isok = Flash_ReadDataCont(DEFAULT_T55XX_KEYS_OFFSET, keysum, 2);
581 if (isok == 2) {
582 num = ((keysum[1] << 8) | keysum[0]);
583 if (num != 0xFFFF && num != 0x0)
584 Dbprintf(" T55x7................... "_YELLOW_("%d")" keys", num);
587 Flash_CheckBusy(BUSY_TIMEOUT);
588 isok = Flash_ReadDataCont(DEFAULT_ICLASS_KEYS_OFFSET, keysum, 2);
589 if (isok == 2) {
590 num = ((keysum[1] << 8) | keysum[0]);
591 if (num != 0xFFFF && num != 0x0)
592 Dbprintf(" iClass.................. "_YELLOW_("%d")" keys", num);
595 FlashStop();