4 #include "proxmark3_arm.h"
9 /* here: use NCPS2 @ PA10: */
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);
28 bool FlashInit(void) {
29 FlashSetup(FLASHMEM_SPIBAUDRATE
);
33 if (Flash_CheckBusy(BUSY_TIMEOUT
)) {
41 void FlashSetup(uint32_t baudrate
) {
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
);
55 AT91C_BASE_PIOA
->PIO_PPUER
|= (GPIO_NCS0
| GPIO_MISO
| GPIO_MOSI
| GPIO_SPCK
| GPIO_NCS2
);
58 AT91C_BASE_PIOA
->PIO_ASR
|= (GPIO_NCS0
| GPIO_MISO
| GPIO_MOSI
| GPIO_SPCK
);
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
;
72 AT91C_BASE_SPI
->SPI_CR
= AT91C_SPI_SPIEN
;
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
91 if (baudrate
> FLASH_MINFAST
) {
92 baudrate
= FLASH_FASTBAUD
;
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
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
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) {
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;
156 AT91C_BASE_SPI
->SPI_CR
= AT91C_SPI_SPIDIS
;
158 if (DBGLEVEL
> 3) Dbprintf("FlashStop");
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) {};
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
);
196 uint32_t _time
= GetCountUS();
198 if (DBGLEVEL
> 3) Dbprintf("Checkbusy in...");
201 if (!(Flash_ReadStat1() & BUSY
)) {
204 } while ((GetCountUS() - _time
) < timeout
);
206 if (timeout
<= (GetCountUS() - _time
)) {
214 uint8_t Flash_ReadID(void) {
216 if (Flash_CheckBusy(BUSY_TIMEOUT
)) return 0;
218 // Manufacture ID / device ID
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
))
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
);
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
;
267 Flash_TransferAdresse(address
);
270 FlashSendByte(DUMMYBYTE
);
274 for (; i
< (len
- 1); i
++)
275 out
[i
] = FlashSendByte(0xFF);
277 out
[i
] = FlashSendLastByte(0xFF);
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
294 uint8_t cmd
= (FASTFLASH
) ? FASTREAD
: READDATA
;
297 Flash_TransferAdresse(address
);
300 FlashSendByte(DUMMYBYTE
);
304 for (; i
< (len
- 1); i
++)
305 out
[i
] = FlashSendByte(0xFF);
307 out
[i
] = FlashSendLastByte(0xFF);
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
321 // Max 256 bytes write
322 if (((address
& 0xFF) + len
) > 256) {
323 Dbprintf("Flash_WriteData 256 fail [ 0x%02x ] [ %u ]", (address
& 0xFF) + len
, len
);
328 if (((address
>> 16) & 0xFF) > MAX_BLOCKS
) {
329 Dbprintf("Flash_WriteData, block out-of-range");
334 if (DBGLEVEL
> 3) Dbprintf("Flash_WriteData init fail");
338 Flash_CheckBusy(BUSY_TIMEOUT
);
342 FlashSendByte(PAGEPROG
);
343 FlashSendByte((address
>> 16) & 0xFF);
344 FlashSendByte((address
>> 8) & 0xFF);
345 FlashSendByte((address
>> 0) & 0xFF);
348 for (; i
< (len
- 1); i
++)
349 FlashSendByte(in
[i
]);
351 FlashSendLastByte(in
[i
]);
358 // length should never be zero
359 // Max 256 bytes write
361 uint16_t Flash_WriteDataCont(uint32_t address
, uint8_t *in
, uint16_t len
) {
366 if (((address
& 0xFF) + len
) > 256) {
367 Dbprintf("Flash_WriteDataCont 256 fail [ 0x%02x ] [ %u ]", (address
& 0xFF) + len
, len
);
371 if (((address
>> 16) & 0xFF) > MAX_BLOCKS
) {
372 Dbprintf("Flash_WriteDataCont, block out-of-range");
376 FlashSendByte(PAGEPROG
);
377 FlashSendByte((address
>> 16) & 0xFF);
378 FlashSendByte((address
>> 8) & 0xFF);
379 FlashSendByte((address
>> 0) & 0xFF);
382 for (; i
< (len
- 1); i
++)
383 FlashSendByte(in
[i
]);
385 FlashSendLastByte(in
[i
]);
389 // assumes valid start 256 based 00 address
391 uint16_t Flash_Write(uint32_t address
, uint8_t *in
, uint16_t len
) {
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
);
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
);
422 bool Flash_WipeMemoryPage(uint8_t page
) {
424 if (DBGLEVEL
> 3) Dbprintf("Flash_WriteData init fail");
429 // Each block is 64Kb. One block erase takes 1s ( 1000ms )
431 Flash_Erase64k(page
);
432 Flash_CheckBusy(BUSY_TIMEOUT
);
437 // Wipes flash memory completely, fills with 0xFF
438 bool Flash_WipeMemory(void) {
440 if (DBGLEVEL
> 3) Dbprintf("Flash_WriteData init fail");
445 // Each block is 64Kb. Four blocks
446 // one block erase takes 1s ( 1000ms )
449 Flash_CheckBusy(BUSY_TIMEOUT
);
452 Flash_CheckBusy(BUSY_TIMEOUT
);
455 Flash_CheckBusy(BUSY_TIMEOUT
);
458 Flash_CheckBusy(BUSY_TIMEOUT
);
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);
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");
491 FlashSendByte(BLOCK32ERASE);
492 FlashSendByte((address >> 16) & 0xFF);
493 FlashSendByte((address >> 8) & 0xFF);
494 FlashSendLastByte((address >> 0) & 0xFF);
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
);
514 FlashSendLastByte(0x00);
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);
530 DbpString(" Init.................... " _RED_("FAILED"));
533 DbpString(" Init.................... " _GREEN_("OK"));
535 uint8_t dev_id
= Flash_ReadID();
538 DbpString(" Memory size............. " _YELLOW_("2 mbits / 256 kb"));
541 DbpString(" Memory size..... ....... " _YELLOW_("1 mbits / 128 kb"));
544 DbpString(" Memory size............. " _YELLOW_("512 kbits / 64 kb"));
547 DbpString(" Device ID............... " _YELLOW_(" --> Unknown <--"));
551 uint8_t uid
[8] = {0, 0, 0, 0, 0, 0, 0, 0};
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]
561 void Flashmem_print_info(void) {
563 if (!FlashInit()) return;
565 DbpString(_CYAN_("Flash memory dictionary loaded"));
567 // load dictionary offsets.
571 Flash_CheckBusy(BUSY_TIMEOUT
);
572 uint16_t isok
= Flash_ReadDataCont(DEFAULT_MF_KEYS_OFFSET
, keysum
, 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);
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);
590 num
= ((keysum
[1] << 8) | keysum
[0]);
591 if (num
!= 0xFFFF && num
!= 0x0)
592 Dbprintf(" iClass.................. "_YELLOW_("%d")" keys", num
);