]> git.zerfleddert.de Git - proxmark3-svn/blame - armsrc/fpgaloader.c
replaced strncasecmp with strcmp to get rid of compile errors
[proxmark3-svn] / armsrc / fpgaloader.c
CommitLineData
6658905f 1//-----------------------------------------------------------------------------\r
2// Routines to load the FPGA image, and then to configure the FPGA's major\r
3// mode once it is configured.\r
4//\r
5// Jonathan Westhues, April 2006\r
6//-----------------------------------------------------------------------------\r
7#include <proxmark3.h>\r
8#include "apps.h"\r
9\r
10//-----------------------------------------------------------------------------\r
11// Set up the Serial Peripheral Interface as master\r
12// Used to write the FPGA config word\r
13// May also be used to write to other SPI attached devices like an LCD\r
14//-----------------------------------------------------------------------------\r
15void SetupSpi(int mode)\r
16{\r
17 // PA10 -> SPI_NCS2 chip select (LCD)\r
18 // PA11 -> SPI_NCS0 chip select (FPGA)\r
19 // PA12 -> SPI_MISO Master-In Slave-Out\r
20 // PA13 -> SPI_MOSI Master-Out Slave-In\r
21 // PA14 -> SPI_SPCK Serial Clock\r
22\r
23 // Disable PIO control of the following pins, allows use by the SPI peripheral\r
6949aca9 24 AT91C_BASE_PIOA->PIO_PDR =\r
25 GPIO_NCS0 |\r
26 GPIO_NCS2 |\r
27 GPIO_MISO |\r
28 GPIO_MOSI |\r
29 GPIO_SPCK;\r
6658905f 30\r
6949aca9 31 AT91C_BASE_PIOA->PIO_ASR =\r
32 GPIO_NCS0 |\r
33 GPIO_MISO |\r
34 GPIO_MOSI |\r
35 GPIO_SPCK;\r
6658905f 36\r
6949aca9 37 AT91C_BASE_PIOA->PIO_BSR = GPIO_NCS2;\r
6658905f 38\r
39 //enable the SPI Peripheral clock\r
6949aca9 40 AT91C_BASE_PMC->PMC_PCER = (1<<AT91C_ID_SPI);\r
6658905f 41 // Enable SPI\r
6949aca9 42 AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN;\r
6658905f 43\r
44 switch (mode) {\r
45 case SPI_FPGA_MODE:\r
6949aca9 46 AT91C_BASE_SPI->SPI_MR =\r
6658905f 47 ( 0 << 24) | // Delay between chip selects (take default: 6 MCK periods)\r
48 (14 << 16) | // Peripheral Chip Select (selects FPGA SPI_NCS0 or PA11)\r
49 ( 0 << 7) | // Local Loopback Disabled\r
50 ( 1 << 4) | // Mode Fault Detection disabled\r
51 ( 0 << 2) | // Chip selects connected directly to peripheral\r
52 ( 0 << 1) | // Fixed Peripheral Select\r
53 ( 1 << 0); // Master Mode\r
6949aca9 54 AT91C_BASE_SPI->SPI_CSR[0] =\r
6658905f 55 ( 1 << 24) | // Delay between Consecutive Transfers (32 MCK periods)\r
56 ( 1 << 16) | // Delay Before SPCK (1 MCK period)\r
57 ( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud\r
30f2a7d3 58 ( 8 << 4) | // Bits per Transfer (16 bits)\r
6658905f 59 ( 0 << 3) | // Chip Select inactive after transfer\r
60 ( 1 << 1) | // Clock Phase data captured on leading edge, changes on following edge\r
61 ( 0 << 0); // Clock Polarity inactive state is logic 0\r
62 break;\r
63 case SPI_LCD_MODE:\r
6949aca9 64 AT91C_BASE_SPI->SPI_MR =\r
6658905f 65 ( 0 << 24) | // Delay between chip selects (take default: 6 MCK periods)\r
66 (11 << 16) | // Peripheral Chip Select (selects LCD SPI_NCS2 or PA10)\r
67 ( 0 << 7) | // Local Loopback Disabled\r
68 ( 1 << 4) | // Mode Fault Detection disabled\r
69 ( 0 << 2) | // Chip selects connected directly to peripheral\r
70 ( 0 << 1) | // Fixed Peripheral Select\r
71 ( 1 << 0); // Master Mode\r
6949aca9 72 AT91C_BASE_SPI->SPI_CSR[2] =\r
6658905f 73 ( 1 << 24) | // Delay between Consecutive Transfers (32 MCK periods)\r
74 ( 1 << 16) | // Delay Before SPCK (1 MCK period)\r
75 ( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud\r
76 ( 1 << 4) | // Bits per Transfer (9 bits)\r
77 ( 0 << 3) | // Chip Select inactive after transfer\r
78 ( 1 << 1) | // Clock Phase data captured on leading edge, changes on following edge\r
79 ( 0 << 0); // Clock Polarity inactive state is logic 0\r
80 break;\r
81 default: // Disable SPI\r
6949aca9 82 AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS;\r
6658905f 83 break;\r
84 }\r
85}\r
86\r
87//-----------------------------------------------------------------------------\r
88// Set up the synchronous serial port, with the one set of options that we\r
89// always use when we are talking to the FPGA. Both RX and TX are enabled.\r
90//-----------------------------------------------------------------------------\r
91void FpgaSetupSsc(void)\r
92{\r
93 // First configure the GPIOs, and get ourselves a clock.\r
6949aca9 94 AT91C_BASE_PIOA->PIO_ASR =\r
95 GPIO_SSC_FRAME |\r
96 GPIO_SSC_DIN |\r
97 GPIO_SSC_DOUT |\r
98 GPIO_SSC_CLK;\r
99 AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DOUT;\r
6658905f 100\r
6949aca9 101 AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SSC);\r
6658905f 102\r
103 // Now set up the SSC proper, starting from a known state.\r
6949aca9 104 AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST;\r
6658905f 105\r
106 // RX clock comes from TX clock, RX starts when TX starts, data changes\r
107 // on RX clock rising edge, sampled on falling edge\r
6949aca9 108 AT91C_BASE_SSC->SSC_RCMR = SSC_CLOCK_MODE_SELECT(1) | SSC_CLOCK_MODE_START(1);\r
6658905f 109\r
110 // 8 bits per transfer, no loopback, MSB first, 1 transfer per sync\r
111 // pulse, no output sync, start on positive-going edge of sync\r
6949aca9 112 AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) |\r
113 AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);\r
6658905f 114\r
115 // clock comes from TK pin, no clock output, outputs change on falling\r
116 // edge of TK, start on rising edge of TF\r
6949aca9 117 AT91C_BASE_SSC->SSC_TCMR = SSC_CLOCK_MODE_SELECT(2) |\r
6658905f 118 SSC_CLOCK_MODE_START(5);\r
119\r
120 // tx framing is the same as the rx framing\r
6949aca9 121 AT91C_BASE_SSC->SSC_TFMR = AT91C_BASE_SSC->SSC_RFMR;\r
6658905f 122\r
6949aca9 123 AT91C_BASE_SSC->SSC_CR = AT91C_SSC_RXEN | AT91C_SSC_TXEN;\r
6658905f 124}\r
125\r
126//-----------------------------------------------------------------------------\r
127// Set up DMA to receive samples from the FPGA. We will use the PDC, with\r
128// a single buffer as a circular buffer (so that we just chain back to\r
129// ourselves, not to another buffer). The stuff to manipulate those buffers\r
130// is in apps.h, because it should be inlined, for speed.\r
131//-----------------------------------------------------------------------------\r
132void FpgaSetupSscDma(BYTE *buf, int len)\r
133{\r
6949aca9 134 AT91C_BASE_PDC_SSC->PDC_RPR = (DWORD)buf;\r
135 AT91C_BASE_PDC_SSC->PDC_RCR = len;\r
136 AT91C_BASE_PDC_SSC->PDC_RNPR = (DWORD)buf;\r
137 AT91C_BASE_PDC_SSC->PDC_RNCR = len;\r
138 AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN;\r
6658905f 139}\r
140\r
bb031817 141static void DownloadFPGA_byte(unsigned char w)\r
142{\r
143#define SEND_BIT(x) { if(w & (1<<x) ) HIGH(GPIO_FPGA_DIN); else LOW(GPIO_FPGA_DIN); HIGH(GPIO_FPGA_CCLK); LOW(GPIO_FPGA_CCLK); }\r
144 SEND_BIT(7);\r
145 SEND_BIT(6);\r
146 SEND_BIT(5);\r
147 SEND_BIT(4);\r
148 SEND_BIT(3);\r
149 SEND_BIT(2);\r
150 SEND_BIT(1);\r
151 SEND_BIT(0);\r
152}\r
153\r
154// Download the fpga image starting at FpgaImage and with length FpgaImageLen bytes\r
e73e7172 155// If bytereversal is set: reverse the byte order in each 4-byte word\r
bb031817 156static void DownloadFPGA(const char *FpgaImage, int FpgaImageLen, int bytereversal)\r
6658905f 157{\r
d3ae0de7 158 int i=0;\r
6658905f 159\r
6949aca9 160 AT91C_BASE_PIOA->PIO_OER = GPIO_FPGA_ON;\r
161 AT91C_BASE_PIOA->PIO_PER = GPIO_FPGA_ON;\r
d3ae0de7 162 HIGH(GPIO_FPGA_ON); // ensure everything is powered on\r
6658905f 163\r
164 SpinDelay(50);\r
165\r
166 LED_D_ON();\r
167\r
d3ae0de7 168 // These pins are inputs\r
6949aca9 169 AT91C_BASE_PIOA->PIO_ODR =\r
170 GPIO_FPGA_NINIT |\r
171 GPIO_FPGA_DONE;\r
d3ae0de7 172 // PIO controls the following pins\r
6949aca9 173 AT91C_BASE_PIOA->PIO_PER =\r
174 GPIO_FPGA_NINIT |\r
175 GPIO_FPGA_DONE;\r
d3ae0de7 176 // Enable pull-ups\r
6949aca9 177 AT91C_BASE_PIOA->PIO_PPUER =\r
178 GPIO_FPGA_NINIT |\r
179 GPIO_FPGA_DONE;\r
d3ae0de7 180\r
181 // setup initial logic state\r
6658905f 182 HIGH(GPIO_FPGA_NPROGRAM);\r
183 LOW(GPIO_FPGA_CCLK);\r
184 LOW(GPIO_FPGA_DIN);\r
d3ae0de7 185 // These pins are outputs\r
6949aca9 186 AT91C_BASE_PIOA->PIO_OER =\r
187 GPIO_FPGA_NPROGRAM |\r
188 GPIO_FPGA_CCLK |\r
189 GPIO_FPGA_DIN;\r
6658905f 190\r
d3ae0de7 191 // enter FPGA configuration mode\r
6658905f 192 LOW(GPIO_FPGA_NPROGRAM);\r
193 SpinDelay(50);\r
194 HIGH(GPIO_FPGA_NPROGRAM);\r
195\r
d3ae0de7 196 i=100000;\r
197 // wait for FPGA ready to accept data signal\r
6949aca9 198 while ((i) && ( !(AT91C_BASE_PIOA->PIO_PDSR & GPIO_FPGA_NINIT ) ) ) {\r
d3ae0de7 199 i--;\r
200 }\r
201\r
202 // crude error indicator, leave both red LEDs on and return\r
203 if (i==0){\r
204 LED_C_ON();\r
205 LED_D_ON();\r
206 return;\r
207 }\r
208\r
bb031817 209 if(bytereversal) {\r
210 /* This is only supported for DWORD aligned images */\r
211 if( ((int)FpgaImage % sizeof(DWORD)) == 0 ) {\r
212 i=0;\r
213 while(FpgaImageLen-->0)\r
214 DownloadFPGA_byte(FpgaImage[(i++)^0x3]);\r
215 /* Explanation of the magic in the above line: \r
216 * i^0x3 inverts the lower two bits of the integer i, counting backwards\r
217 * for each 4 byte increment. The generated sequence of (i++)^3 is\r
d3ae0de7 218 * 3 2 1 0 7 6 5 4 11 10 9 8 15 14 13 12 etc. pp. \r
bb031817 219 */\r
6658905f 220 }\r
bb031817 221 } else {\r
222 while(FpgaImageLen-->0)\r
223 DownloadFPGA_byte(*FpgaImage++);\r
6658905f 224 }\r
225\r
d3ae0de7 226 // continue to clock FPGA until ready signal goes high\r
227 i=100000;\r
6949aca9 228 while ( (i--) && ( !(AT91C_BASE_PIOA->PIO_PDSR & GPIO_FPGA_DONE ) ) ) {\r
d3ae0de7 229 HIGH(GPIO_FPGA_CCLK);\r
230 LOW(GPIO_FPGA_CCLK);\r
231 }\r
232 // crude error indicator, leave both red LEDs on and return\r
233 if (i==0){\r
234 LED_C_ON();\r
235 LED_D_ON();\r
236 return;\r
237 }\r
6658905f 238 LED_D_OFF();\r
239}\r
240\r
e73e7172 241static char *bitparse_headers_start;\r
242static char *bitparse_bitstream_end;\r
243static int bitparse_initialized;\r
244/* Simple Xilinx .bit parser. The file starts with the fixed opaque byte sequence\r
245 * 00 09 0f f0 0f f0 0f f0 0f f0 00 00 01\r
246 * After that the format is 1 byte section type (ASCII character), 2 byte length\r
247 * (big endian), <length> bytes content. Except for section 'e' which has 4 bytes\r
6949aca9 248 * length.\r
e73e7172 249 */\r
250static const char _bitparse_fixed_header[] = {0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01};\r
251static int bitparse_init(void * start_address, void *end_address)\r
252{\r
253 bitparse_initialized = 0;\r
254 \r
255 if(memcmp(_bitparse_fixed_header, start_address, sizeof(_bitparse_fixed_header)) != 0) {\r
256 return 0; /* Not matched */\r
257 } else {\r
258 bitparse_headers_start= ((char*)start_address) + sizeof(_bitparse_fixed_header);\r
259 bitparse_bitstream_end= (char*)end_address;\r
260 bitparse_initialized = 1;\r
261 return 1;\r
262 }\r
263}\r
264\r
9dbe0941 265int bitparse_find_section(char section_name, char **section_start, unsigned int *section_length)\r
e73e7172 266{\r
267 char *pos = bitparse_headers_start;\r
268 int result = 0;\r
269\r
270 if(!bitparse_initialized) return 0;\r
271\r
272 while(pos < bitparse_bitstream_end) {\r
273 char current_name = *pos++;\r
274 unsigned int current_length = 0;\r
275 if(current_name < 'a' || current_name > 'e') {\r
276 /* Strange section name, abort */\r
277 break;\r
278 }\r
279 current_length = 0;\r
280 switch(current_name) {\r
281 case 'e':\r
282 /* Four byte length field */\r
283 current_length += (*pos++) << 24;\r
284 current_length += (*pos++) << 16;\r
285 default: /* Fall through, two byte length field */\r
286 current_length += (*pos++) << 8;\r
287 current_length += (*pos++) << 0;\r
288 }\r
289 \r
290 if(current_name != 'e' && current_length > 255) {\r
291 /* Maybe a parse error */\r
292 break;\r
293 }\r
294 \r
295 if(current_name == section_name) {\r
296 /* Found it */\r
297 *section_start = pos;\r
298 *section_length = current_length;\r
299 result = 1;\r
300 break;\r
301 }\r
302 \r
303 pos += current_length; /* Skip section */\r
304 }\r
305 \r
306 return result;\r
307}\r
308\r
309//-----------------------------------------------------------------------------\r
310// Find out which FPGA image format is stored in flash, then call DownloadFPGA\r
311// with the right parameters to download the image\r
312//-----------------------------------------------------------------------------\r
313extern char _binary_fpga_bit_start, _binary_fpga_bit_end;\r
314void FpgaDownloadAndGo(void)\r
315{\r
6949aca9 316 /* Check for the new flash image format: Should have the .bit file at &_binary_fpga_bit_start\r
e73e7172 317 */\r
318 if(bitparse_init(&_binary_fpga_bit_start, &_binary_fpga_bit_end)) {\r
319 /* Successfully initialized the .bit parser. Find the 'e' section and\r
6949aca9 320 * send its contents to the FPGA.\r
e73e7172 321 */\r
9dbe0941 322 char *bitstream_start;\r
e73e7172 323 unsigned int bitstream_length;\r
324 if(bitparse_find_section('e', &bitstream_start, &bitstream_length)) {\r
bb031817 325 DownloadFPGA(bitstream_start, bitstream_length, 0);\r
e73e7172 326 \r
327 return; /* All done */\r
328 }\r
329 }\r
330 \r
331 /* Fallback for the old flash image format: Check for the magic marker 0xFFFFFFFF\r
e3ae0257 332 * 0xAA995566 at address 0x102000. This is raw bitstream with a size of 336,768 bits \r
e73e7172 333 * = 10,524 DWORDs, stored as DWORDS e.g. little-endian in memory, but each DWORD\r
334 * is still to be transmitted in MSBit first order. Set the invert flag to indicate\r
335 * that the DownloadFPGA function should invert every 4 byte sequence when doing\r
6949aca9 336 * the bytewise download.\r
e73e7172 337 */\r
e3ae0257 338 if( *(DWORD*)0x102000 == 0xFFFFFFFF && *(DWORD*)0x102004 == 0xAA995566 )\r
bb031817 339 DownloadFPGA((char*)0x102000, 10524*4, 1);\r
e73e7172 340}\r
341\r
ba8a80b3 342void FpgaGatherVersion(char *dst, int len)\r
343{\r
344 char *fpga_info; \r
345 unsigned int fpga_info_len;\r
346 dst[0] = 0;\r
9dbe0941 347 if(!bitparse_find_section('e', &fpga_info, &fpga_info_len)) {\r
ba8a80b3 348 strncat(dst, "FPGA image: legacy image without version information", len-1);\r
349 } else {\r
350 strncat(dst, "FPGA image built", len-1);\r
351 /* USB packets only have 48 bytes data payload, so be terse */\r
352#if 0\r
9dbe0941 353 if(bitparse_find_section('a', &fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) {\r
ba8a80b3 354 strncat(dst, " from ", len-1);\r
355 strncat(dst, fpga_info, len-1);\r
356 }\r
9dbe0941 357 if(bitparse_find_section('b', &fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) {\r
ba8a80b3 358 strncat(dst, " for ", len-1);\r
359 strncat(dst, fpga_info, len-1);\r
360 }\r
361#endif\r
9dbe0941 362 if(bitparse_find_section('c', &fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) {\r
ba8a80b3 363 strncat(dst, " on ", len-1);\r
364 strncat(dst, fpga_info, len-1);\r
365 }\r
9dbe0941 366 if(bitparse_find_section('d', &fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) {\r
ba8a80b3 367 strncat(dst, " at ", len-1);\r
368 strncat(dst, fpga_info, len-1);\r
369 }\r
370 }\r
371}\r
372\r
30f2a7d3 373//-----------------------------------------------------------------------------\r
374// Send a 16 bit command/data pair to the FPGA.\r
375// The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0\r
376// where C is the 4 bit command and D is the 12 bit data\r
377//-----------------------------------------------------------------------------\r
378void FpgaSendCommand(WORD cmd, WORD v)\r
379{\r
380 SetupSpi(SPI_FPGA_MODE);\r
6949aca9 381 while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0); // wait for the transfer to complete\r
382 AT91C_BASE_SPI->SPI_TDR = AT91C_SPI_LASTXFER | cmd | v; // send the data\r
30f2a7d3 383}\r
6658905f 384//-----------------------------------------------------------------------------\r
385// Write the FPGA setup word (that determines what mode the logic is in, read\r
30f2a7d3 386// vs. clone vs. etc.). This is now a special case of FpgaSendCommand() to\r
387// avoid changing this function's occurence everywhere in the source code.\r
6658905f 388//-----------------------------------------------------------------------------\r
389void FpgaWriteConfWord(BYTE v)\r
390{\r
30f2a7d3 391 FpgaSendCommand(FPGA_CMD_SET_CONFREG, v);\r
6658905f 392}\r
393\r
394//-----------------------------------------------------------------------------\r
395// Set up the CMOS switches that mux the ADC: four switches, independently\r
396// closable, but should only close one at a time. Not an FPGA thing, but\r
397// the samples from the ADC always flow through the FPGA.\r
398//-----------------------------------------------------------------------------\r
6949aca9 399void SetAdcMuxFor(DWORD whichGpio)\r
6658905f 400{\r
6949aca9 401 AT91C_BASE_PIOA->PIO_OER =\r
402 GPIO_MUXSEL_HIPKD |\r
403 GPIO_MUXSEL_LOPKD |\r
404 GPIO_MUXSEL_LORAW |\r
405 GPIO_MUXSEL_HIRAW;\r
406\r
407 AT91C_BASE_PIOA->PIO_PER =\r
408 GPIO_MUXSEL_HIPKD |\r
409 GPIO_MUXSEL_LOPKD |\r
410 GPIO_MUXSEL_LORAW |\r
411 GPIO_MUXSEL_HIRAW;\r
6658905f 412\r
413 LOW(GPIO_MUXSEL_HIPKD);\r
414 LOW(GPIO_MUXSEL_HIRAW);\r
415 LOW(GPIO_MUXSEL_LORAW);\r
416 LOW(GPIO_MUXSEL_LOPKD);\r
417\r
418 HIGH(whichGpio);\r
419}\r
Impressum, Datenschutz