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
}\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
/* 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
* the bytewise download.
*/\r
if( *(DWORD*)0x102000 == 0xFFFFFFFF && *(DWORD*)0x102004 == 0xAA995566 )\r
- DownloadFPGA((DWORD *)0x102000, 10524, 1);\r
+ DownloadFPGA((char*)0x102000, 10524*4, 1);\r
}\r
\r
void FpgaGatherVersion(char *dst, int len)\r
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