X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/391a974f53b8344d2dd1e04dab382bb5d397916d..e73e717239300d6b47d5f5d81256d8feb493299f:/armsrc/fpgaloader.c diff --git a/armsrc/fpgaloader.c b/armsrc/fpgaloader.c new file mode 100644 index 00000000..e07c2542 --- /dev/null +++ b/armsrc/fpgaloader.c @@ -0,0 +1,332 @@ +//----------------------------------------------------------------------------- +// Routines to load the FPGA image, and then to configure the FPGA's major +// mode once it is configured. +// +// Jonathan Westhues, April 2006 +//----------------------------------------------------------------------------- +#include +#include "apps.h" + +//----------------------------------------------------------------------------- +// Set up the Serial Peripheral Interface as master +// Used to write the FPGA config word +// May also be used to write to other SPI attached devices like an LCD +//----------------------------------------------------------------------------- +void SetupSpi(int mode) +{ + // PA10 -> SPI_NCS2 chip select (LCD) + // PA11 -> SPI_NCS0 chip select (FPGA) + // PA12 -> SPI_MISO Master-In Slave-Out + // PA13 -> SPI_MOSI Master-Out Slave-In + // PA14 -> SPI_SPCK Serial Clock + + // Disable PIO control of the following pins, allows use by the SPI peripheral + PIO_DISABLE = (1 << GPIO_NCS0) | + (1 << GPIO_NCS2) | + (1 << GPIO_MISO) | + (1 << GPIO_MOSI) | + (1 << GPIO_SPCK); + + PIO_PERIPHERAL_A_SEL = (1 << GPIO_NCS0) | + (1 << GPIO_MISO) | + (1 << GPIO_MOSI) | + (1 << GPIO_SPCK); + + PIO_PERIPHERAL_B_SEL = (1 << GPIO_NCS2); + + //enable the SPI Peripheral clock + PMC_PERIPHERAL_CLK_ENABLE = (1<>(j*8); + else + w = v >>((3-j)*8); +#define SEND_BIT(x) { if(w & (1< bytes content. Except for section 'e' which has 4 bytes + * length. + */ +static const char _bitparse_fixed_header[] = {0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01}; +static int bitparse_init(void * start_address, void *end_address) +{ + bitparse_initialized = 0; + + if(memcmp(_bitparse_fixed_header, start_address, sizeof(_bitparse_fixed_header)) != 0) { + return 0; /* Not matched */ + } else { + bitparse_headers_start= ((char*)start_address) + sizeof(_bitparse_fixed_header); + bitparse_bitstream_end= (char*)end_address; + bitparse_initialized = 1; + return 1; + } +} + +int bitparse_find_section(char section_name, void **section_start, unsigned int *section_length) +{ + char *pos = bitparse_headers_start; + int result = 0; + + if(!bitparse_initialized) return 0; + + while(pos < bitparse_bitstream_end) { + char current_name = *pos++; + unsigned int current_length = 0; + if(current_name < 'a' || current_name > 'e') { + /* Strange section name, abort */ + break; + } + current_length = 0; + switch(current_name) { + case 'e': + /* Four byte length field */ + current_length += (*pos++) << 24; + current_length += (*pos++) << 16; + default: /* Fall through, two byte length field */ + current_length += (*pos++) << 8; + current_length += (*pos++) << 0; + } + + if(current_name != 'e' && current_length > 255) { + /* Maybe a parse error */ + break; + } + + if(current_name == section_name) { + /* Found it */ + *section_start = pos; + *section_length = current_length; + result = 1; + break; + } + + pos += current_length; /* Skip section */ + } + + return result; +} + +//----------------------------------------------------------------------------- +// Find out which FPGA image format is stored in flash, then call DownloadFPGA +// with the right parameters to download the image +//----------------------------------------------------------------------------- +extern char _binary_fpga_bit_start, _binary_fpga_bit_end; +void FpgaDownloadAndGo(void) +{ + /* Check for the new flash image format: Should have the .bit file at &_binary_fpga_bit_start + */ + if(bitparse_init(&_binary_fpga_bit_start, &_binary_fpga_bit_end)) { + /* Successfully initialized the .bit parser. Find the 'e' section and + * send its contents to the FPGA. + */ + void *bitstream_start; + unsigned int bitstream_length; + if(bitparse_find_section('e', &bitstream_start, &bitstream_length)) { + DownloadFPGA((DWORD *)bitstream_start, bitstream_length/4, 0); + + return; /* All done */ + } + } + + /* Fallback for the old flash image format: Check for the magic marker 0xFFFFFFFF + * 0xAA995566 at address 0x2000. This is raw bitstream with a size of 336,768 bits + * = 10,524 DWORDs, stored as DWORDS e.g. little-endian in memory, but each DWORD + * is still to be transmitted in MSBit first order. Set the invert flag to indicate + * that the DownloadFPGA function should invert every 4 byte sequence when doing + * the bytewise download. + */ + if( *(DWORD*)0x2000 == 0xFFFFFFFF && *(DWORD*)0x2004 == 0xAA995566 ) + DownloadFPGA((DWORD *)0x2000, 10524, 1); +} + +//----------------------------------------------------------------------------- +// Send a 16 bit command/data pair to the FPGA. +// The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 +// where C is the 4 bit command and D is the 12 bit data +//----------------------------------------------------------------------------- +void FpgaSendCommand(WORD cmd, WORD v) +{ + SetupSpi(SPI_FPGA_MODE); + while ((SPI_STATUS & SPI_STATUS_TX_EMPTY) == 0); // wait for the transfer to complete + SPI_TX_DATA = SPI_CONTROL_LAST_TRANSFER | cmd | v; // send the data +} +//----------------------------------------------------------------------------- +// Write the FPGA setup word (that determines what mode the logic is in, read +// vs. clone vs. etc.). This is now a special case of FpgaSendCommand() to +// avoid changing this function's occurence everywhere in the source code. +//----------------------------------------------------------------------------- +void FpgaWriteConfWord(BYTE v) +{ + FpgaSendCommand(FPGA_CMD_SET_CONFREG, v); +} + +//----------------------------------------------------------------------------- +// Set up the CMOS switches that mux the ADC: four switches, independently +// closable, but should only close one at a time. Not an FPGA thing, but +// the samples from the ADC always flow through the FPGA. +//----------------------------------------------------------------------------- +void SetAdcMuxFor(int whichGpio) +{ + PIO_OUTPUT_ENABLE = (1 << GPIO_MUXSEL_HIPKD) | + (1 << GPIO_MUXSEL_LOPKD) | + (1 << GPIO_MUXSEL_LORAW) | + (1 << GPIO_MUXSEL_HIRAW); + + PIO_ENABLE = (1 << GPIO_MUXSEL_HIPKD) | + (1 << GPIO_MUXSEL_LOPKD) | + (1 << GPIO_MUXSEL_LORAW) | + (1 << GPIO_MUXSEL_HIRAW); + + LOW(GPIO_MUXSEL_HIPKD); + LOW(GPIO_MUXSEL_HIRAW); + LOW(GPIO_MUXSEL_LORAW); + LOW(GPIO_MUXSEL_LOPKD); + + HIGH(whichGpio); +}