]> git.zerfleddert.de Git - proxmark3-svn/blobdiff - armsrc/fpgaloader.c
Small changes to some armsrc makefile to allow conditional compilation of various...
[proxmark3-svn] / armsrc / fpgaloader.c
index 88fdc4cfc08a6517e092ef2aa892936fdb447285..af2f02abaf6df550a9f93d2cf313a868bb16ddf5 100644 (file)
@@ -135,52 +135,96 @@ void FpgaSetupSscDma(BYTE *buf, int len)
        PDC_CONTROL(SSC_BASE) = PDC_RX_ENABLE;\r
 }\r
 \r
-// Download the fpga image starting at FpgaImage and with length FpgaImageLen DWORDs (e.g. 4 bytes)\r
+static void DownloadFPGA_byte(unsigned char w)\r
+{\r
+#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
+       SEND_BIT(7);\r
+       SEND_BIT(6);\r
+       SEND_BIT(5);\r
+       SEND_BIT(4);\r
+       SEND_BIT(3);\r
+       SEND_BIT(2);\r
+       SEND_BIT(1);\r
+       SEND_BIT(0);\r
+}\r
+\r
+// Download the fpga image starting at FpgaImage and with length FpgaImageLen bytes\r
 // If bytereversal is set: reverse the byte order in each 4-byte word\r
-static void DownloadFPGA(const DWORD *FpgaImage, DWORD FpgaImageLen, int bytereversal)\r
+static void DownloadFPGA(const char *FpgaImage, int FpgaImageLen, int bytereversal)\r
 {\r
-       int i, j;\r
+       int i=0;\r
 \r
        PIO_OUTPUT_ENABLE = (1 << GPIO_FPGA_ON);\r
        PIO_ENABLE = (1 << GPIO_FPGA_ON);\r
-       PIO_OUTPUT_DATA_SET = (1 << GPIO_FPGA_ON);\r
+       HIGH(GPIO_FPGA_ON);             // ensure everything is powered on\r
 \r
        SpinDelay(50);\r
 \r
        LED_D_ON();\r
 \r
+       // These pins are inputs\r
+    PIO_OUTPUT_DISABLE =     (1 << GPIO_FPGA_NINIT) | (1 << GPIO_FPGA_DONE);\r
+       // PIO controls the following pins\r
+    PIO_ENABLE =             (1 << GPIO_FPGA_NINIT) | (1 << GPIO_FPGA_DONE);\r
+       // Enable pull-ups\r
+       PIO_NO_PULL_UP_DISABLE = (1 << GPIO_FPGA_NINIT) | (1 << GPIO_FPGA_DONE);\r
+\r
+       // setup initial logic state\r
        HIGH(GPIO_FPGA_NPROGRAM);\r
        LOW(GPIO_FPGA_CCLK);\r
        LOW(GPIO_FPGA_DIN);\r
+       // These pins are outputs\r
        PIO_OUTPUT_ENABLE = (1 << GPIO_FPGA_NPROGRAM)   |\r
                                                (1 << GPIO_FPGA_CCLK)           |\r
                                                (1 << GPIO_FPGA_DIN);\r
-       SpinDelay(1);\r
 \r
+       // enter FPGA configuration mode\r
        LOW(GPIO_FPGA_NPROGRAM);\r
        SpinDelay(50);\r
        HIGH(GPIO_FPGA_NPROGRAM);\r
 \r
-       for(i = 0; i < FpgaImageLen; i++) {\r
-               DWORD v = FpgaImage[i];\r
-               unsigned char w;\r
-               for(j = 0; j < 4; j++) {\r
-                       if(!bytereversal) \r
-                               w = v >>(j*8);\r
-                       else\r
-                               w = v >>((3-j)*8);\r
-#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
-                       SEND_BIT(7);\r
-                       SEND_BIT(6);\r
-                       SEND_BIT(5);\r
-                       SEND_BIT(4);\r
-                       SEND_BIT(3);\r
-                       SEND_BIT(2);\r
-                       SEND_BIT(1);\r
-                       SEND_BIT(0);\r
+       i=100000;\r
+       // wait for FPGA ready to accept data signal\r
+       while ((i) && ( !(PIO_PIN_DATA_STATUS & (1<<GPIO_FPGA_NINIT) ) ) ) {\r
+               i--;\r
+       }\r
+\r
+       // crude error indicator, leave both red LEDs on and return\r
+       if (i==0){\r
+               LED_C_ON();\r
+               LED_D_ON();\r
+               return;\r
+       }\r
+\r
+       if(bytereversal) {\r
+               /* This is only supported for DWORD aligned images */\r
+               if( ((int)FpgaImage % sizeof(DWORD)) == 0 ) {\r
+                       i=0;\r
+                       while(FpgaImageLen-->0)\r
+                               DownloadFPGA_byte(FpgaImage[(i++)^0x3]);\r
+                       /* Explanation of the magic in the above line: \r
+                        * i^0x3 inverts the lower two bits of the integer i, counting backwards\r
+                        * for each 4 byte increment. The generated sequence of (i++)^3 is\r
+                        * 3 2 1 0 7 6 5 4 11 10 9 8 15 14 13 12 etc. pp. \r
+                        */\r
                }\r
+       } else {\r
+               while(FpgaImageLen-->0)\r
+                       DownloadFPGA_byte(*FpgaImage++);\r
        }\r
 \r
+       // continue to clock FPGA until ready signal goes high\r
+       i=100000;\r
+       while ( (i--) && ( !(PIO_PIN_DATA_STATUS & (1<<GPIO_FPGA_DONE) ) ) ) {\r
+               HIGH(GPIO_FPGA_CCLK);\r
+               LOW(GPIO_FPGA_CCLK);\r
+       }\r
+       // crude error indicator, leave both red LEDs on and return\r
+       if (i==0){\r
+               LED_C_ON();\r
+               LED_D_ON();\r
+               return;\r
+       }\r
        LED_D_OFF();\r
 }\r
 \r
@@ -208,7 +252,7 @@ static int bitparse_init(void * start_address, void *end_address)
        }\r
 }\r
 \r
-int bitparse_find_section(char section_name, void **section_start, unsigned int *section_length)\r
+int bitparse_find_section(char section_name, char **section_start, unsigned int *section_length)\r
 {\r
        char *pos = bitparse_headers_start;\r
        int result = 0;\r
@@ -265,24 +309,24 @@ void FpgaDownloadAndGo(void)
                /* Successfully initialized the .bit parser. Find the 'e' section and\r
                 * send its contents to the FPGA.
                 */\r
-               void *bitstream_start;\r
+               char *bitstream_start;\r
                unsigned int bitstream_length;\r
                if(bitparse_find_section('e', &bitstream_start, &bitstream_length)) {\r
-                       DownloadFPGA((DWORD *)bitstream_start, bitstream_length/4, 0);\r
+                       DownloadFPGA(bitstream_start, bitstream_length, 0);\r
                        \r
                        return; /* All done */\r
                }\r
        }\r
        \r
        /* Fallback for the old flash image format: Check for the magic marker 0xFFFFFFFF\r
-        * 0xAA995566 at address 0x2000. This is raw bitstream with a size of 336,768 bits \r
+        * 0xAA995566 at address 0x102000. This is raw bitstream with a size of 336,768 bits \r
         * = 10,524 DWORDs, stored as DWORDS e.g. little-endian in memory, but each DWORD\r
         * is still to be transmitted in MSBit first order. Set the invert flag to indicate\r
         * that the DownloadFPGA function should invert every 4 byte sequence when doing\r
         * the bytewise download.
         */\r
-       if( *(DWORD*)0x2000 == 0xFFFFFFFF && *(DWORD*)0x2004 == 0xAA995566 )\r
-               DownloadFPGA((DWORD *)0x2000, 10524, 1);\r
+       if( *(DWORD*)0x102000 == 0xFFFFFFFF && *(DWORD*)0x102004 == 0xAA995566 )\r
+               DownloadFPGA((char*)0x102000, 10524*4, 1);\r
 }\r
 \r
 void FpgaGatherVersion(char *dst, int len)\r
@@ -290,26 +334,26 @@ void FpgaGatherVersion(char *dst, int len)
        char *fpga_info; \r
        unsigned int fpga_info_len;\r
        dst[0] = 0;\r
-       if(!bitparse_find_section('e', (void**)&fpga_info, &fpga_info_len)) {\r
+       if(!bitparse_find_section('e', &fpga_info, &fpga_info_len)) {\r
                strncat(dst, "FPGA image: legacy image without version information", len-1);\r
        } else {\r
                strncat(dst, "FPGA image built", len-1);\r
                /* USB packets only have 48 bytes data payload, so be terse */\r
 #if 0\r
-               if(bitparse_find_section('a', (void**)&fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) {\r
+               if(bitparse_find_section('a', &fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) {\r
                        strncat(dst, " from ", len-1);\r
                        strncat(dst, fpga_info, len-1);\r
                }\r
-               if(bitparse_find_section('b', (void**)&fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) {\r
+               if(bitparse_find_section('b', &fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) {\r
                        strncat(dst, " for ", len-1);\r
                        strncat(dst, fpga_info, len-1);\r
                }\r
 #endif\r
-               if(bitparse_find_section('c', (void**)&fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) {\r
+               if(bitparse_find_section('c', &fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) {\r
                        strncat(dst, " on ", len-1);\r
                        strncat(dst, fpga_info, len-1);\r
                }\r
-               if(bitparse_find_section('d', (void**)&fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) {\r
+               if(bitparse_find_section('d', &fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) {\r
                        strncat(dst, " at ", len-1);\r
                        strncat(dst, fpga_info, len-1);\r
                }\r
Impressum, Datenschutz