From 5e21afe140d2b9c1ad325e8192bf8d09201d5a6d Mon Sep 17 00:00:00 2001 From: WeebDataHoarder <57538841+weebdatahoarder@users.noreply.github.com> Date: Sat, 19 Dec 2020 20:32:00 +0100 Subject: [PATCH] Rewritten SPI_CTRL using a bitfield instead of raw values for ease of documentation --- .gitignore | 3 ++ Makefile | 4 +-- fm10k-dump.c | 94 ++++++++++++++++++++++++++++++++++++---------------- 3 files changed, 70 insertions(+), 31 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d51bdbd --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/fm10k-dump +/*.o +/.idea \ No newline at end of file diff --git a/Makefile b/Makefile index 2b4dbec..dab6e5e 100644 --- a/Makefile +++ b/Makefile @@ -2,10 +2,10 @@ default: fm10k-dump fm10k-dump.o: fm10k-dump.c - gcc -c fm10k-dump.c -o fm10k-dump.o + gcc -c fm10k-dump.c -o fm10k-dump.o -Wall -Wno-packed-bitfield-compat fm10k-dump: fm10k-dump.o - gcc fm10k-dump.o -o fm10k-dump + gcc fm10k-dump.o -o fm10k-dump -Wall clean: -rm -f fm10k-dump diff --git a/fm10k-dump.c b/fm10k-dump.c index bc00a22..b0c210d 100644 --- a/fm10k-dump.c +++ b/fm10k-dump.c @@ -53,7 +53,31 @@ #define FM10K_SPI_FREQ_KHZ 50000 +#define FM10K_SPI_HEADER_COMMAND_READ_BYTES 0x3 +/* Test for GCC >= 4.4.0, see https://gcc.gnu.org/gcc-4.4/changes.html : Packed bit-fields of type char were not properly bit-packed on many targets prior to GCC 4.4 */ +#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 4)) +typedef union { + struct { + uint16_t Freq : 10; // Actual speed is PCIE_REFCLK/(2*(1+Freq)) + uint8_t Enable : 1; + uint8_t Command : 4; // 0b00 = reset + uint8_t HeaderSize : 2; // 0b00 = 4 bytes + uint8_t DataSize : 2; // 0b00 = 4 bytes + uint8_t DataShiftMethod : 2; // 0b00 = SINGLE, 0b01 = DUAL, 0b10 = QUAD, 0b11 = Reserved + uint8_t Busy : 1; // volatile ReadOnly + uint8_t Selected : 1; // volatile ReadOnly + uint8_t DirIO2 : 1; // 0b0 = Input, 0b1 = Output + uint8_t DirIO3 : 1; // 0b0 = Input, 0b1 = Output + uint8_t PinIO2 : 1; // volatile ReadWrite + uint8_t PinIO3 : 1; // volatile ReadWrite + uint8_t Reserved : 5; + } __attribute__((packed)) fields; + uint32_t value; +} SPI_CTRL; +#else +#error "Packed bit-fields of type char were not properly bit-packed on many targets prior to GCC 4.4, upgrade to GCC >= 4.4." +#endif void ReadRegister32(uintptr_t mem, uint32_t addr, uint32_t* value) { *value = *(((uint32_t*)mem) + addr); @@ -63,10 +87,13 @@ void WriteRegister32(uintptr_t mem, uint32_t addr, uint32_t value) { *(uint32_t volatile*)(((uint32_t*)mem) + addr) = value; //If returning instantly this will caused missed writes. nanosleep wait of 1 nsec was too much. Busy wait works +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" volatile uint32_t dummy; for(uint32_t i = 0; i < 100; ++i){ dummy = i; } +#pragma GCC diagnostic pop } uint32_t get_interval_diff(struct timeval *begin, struct timeval *end) { @@ -86,17 +113,18 @@ uint32_t get_interval_diff(struct timeval *begin, struct timeval *end) { return (diff.tv_sec * 1000 + diff.tv_usec / 1000); } -uint32_t fm10k_uio_spi_SetCtrlReg(uintptr_t mem, uint32_t value){ - uint32_t spiCtrl; +uint32_t fm10k_uio_spi_SetCtrlReg(uintptr_t mem, SPI_CTRL value){ struct timeval startTime; uint8_t isTimeout = 0; + SPI_CTRL spiCtrl; + spiCtrl.value = 0; - WriteRegister32(mem, FM10K_REGISTER_SPI_CTRL, value); + WriteRegister32(mem, FM10K_REGISTER_SPI_CTRL, value.value); gettimeofday(&startTime, NULL); do{ if(isTimeout){ - printf("Timeout waiting for SPI_CTRL Busy. 0x%02x\n", spiCtrl); + printf("Timeout waiting for SPI_CTRL.Busy 0x%02x\n", spiCtrl.value); return 1; } @@ -104,39 +132,46 @@ uint32_t fm10k_uio_spi_SetCtrlReg(uintptr_t mem, uint32_t value){ isTimeout = 1; } - ReadRegister32(mem, FM10K_REGISTER_SPI_CTRL, &spiCtrl); + ReadRegister32(mem, FM10K_REGISTER_SPI_CTRL, &spiCtrl.value); - } while ((spiCtrl >> 21) & 1); //While "Busy" + } while (spiCtrl.fields.Busy); /* write back SPI_CTRL with command = 0 */ - spiCtrl &= 0xffff87ff; - WriteRegister32(mem, FM10K_REGISTER_SPI_CTRL, spiCtrl); + spiCtrl.fields.Command = 0; + WriteRegister32(mem, FM10K_REGISTER_SPI_CTRL, spiCtrl.value); return 0; } void fm10k_uio_spi_Enable(uintptr_t mem){ //ENABLE SPI - uint32_t spiCtrl = 0; - ReadRegister32(mem, FM10K_REGISTER_SPI_CTRL, &spiCtrl); + SPI_CTRL spiCtrl; + ReadRegister32(mem, FM10K_REGISTER_SPI_CTRL, &spiCtrl.value); /* keep current freq setting and set SPI Enable */ - spiCtrl &= 0x3ff; - spiCtrl |= 1<<10; - WriteRegister32(mem, FM10K_REGISTER_SPI_CTRL, spiCtrl); + SPI_CTRL newSpiCtrl; + newSpiCtrl.value = 0; + newSpiCtrl.fields.Freq = spiCtrl.fields.Freq; + newSpiCtrl.fields.Enable = 1; + WriteRegister32(mem, FM10K_REGISTER_SPI_CTRL, newSpiCtrl.value); } void fm10k_uio_spi_Disable(uintptr_t mem){ //DISABLE SPI - uint32_t spiCtrl = 0; - ReadRegister32(mem, FM10K_REGISTER_SPI_CTRL, &spiCtrl); - /* keep current freq setting and set SPI Disable */ - spiCtrl &= 0x3ff; - WriteRegister32(mem, FM10K_REGISTER_SPI_CTRL, spiCtrl); + SPI_CTRL spiCtrl; + ReadRegister32(mem, FM10K_REGISTER_SPI_CTRL, &spiCtrl.value); + /* keep current freq setting and set SPI Enable = 0 */ + SPI_CTRL newSpiCtrl; + newSpiCtrl.value = 0; + newSpiCtrl.fields.Freq = spiCtrl.fields.Freq; + WriteRegister32(mem, FM10K_REGISTER_SPI_CTRL, newSpiCtrl.value); } uint32_t fm10k_uio_spi_ReadFlash(uintptr_t mem, uint32_t address, uint8_t* data, int32_t len){ - uint32_t spiCtrl; + SPI_CTRL currentSpiCtrl; + SPI_CTRL spiCtrl; + spiCtrl.value = 0; + uint32_t rxData; uint32_t header; int32_t freq; @@ -146,32 +181,32 @@ uint32_t fm10k_uio_spi_ReadFlash(uintptr_t mem, uint32_t address, uint8_t* data, fm10k_uio_spi_Enable(mem); - ReadRegister32(mem, FM10K_REGISTER_SPI_CTRL, &spiCtrl); + ReadRegister32(mem, FM10K_REGISTER_SPI_CTRL, ¤tSpiCtrl.value); if(FM10K_SPI_FREQ_KHZ > 0){ freq = ((100000 / (int)FM10K_SPI_FREQ_KHZ) / 2) - 1; if (freq < 0){ freq = 0; } - - spiCtrl ^= ((spiCtrl >> 0) ^ freq) & ((2 << 9) - 1); //Set Freq + spiCtrl.fields.Freq = freq; } - spiCtrl &= 0x7ff; + spiCtrl.fields.Enable = currentSpiCtrl.fields.Enable; /* header: command (1 byte: READ_BYTES) + address (3 bytes) */ - header = (0x3 << 24) | (address & 0xffffff); + header = (FM10K_SPI_HEADER_COMMAND_READ_BYTES << 24) | (address & 0xffffff); WriteRegister32(mem, FM10K_REGISTER_SPI_HEADER, header); /* first loop only: set send header flag. Following loops: shift only data. */ - spiCtrl |= (0x1 << 11); + spiCtrl.fields.Command |= 0b0001; cnt = 0; while (cnt < len){ /* determine the number of data bytes to read [1..4] */ numRead = (len - cnt) > 3 ? 4 : (len - cnt); /* set 'shift data' flag and number of data bytes */ - spiCtrl |= ((0x4 << 11) | ((numRead & 0x03) << 17)); + spiCtrl.fields.Command |= 0b0100; + spiCtrl.fields.DataSize = numRead & 0b11; if(fm10k_uio_spi_SetCtrlReg(mem, spiCtrl)){ return 1; @@ -186,11 +221,12 @@ uint32_t fm10k_uio_spi_ReadFlash(uintptr_t mem, uint32_t address, uint8_t* data, data[cnt++] = (rxData >> (numRead * 8)) & 0xff; } - spiCtrl &= 0x7ff; + spiCtrl.fields.Command = 0b0000; + spiCtrl.fields.DataSize = 0b0000; } /* release CS */ - spiCtrl |= (0x8 << 11); + spiCtrl.fields.Command = 0b1000; if(fm10k_uio_spi_SetCtrlReg(mem, spiCtrl)){ return 1; } @@ -233,7 +269,7 @@ int main(int argc, char** argv){ unsigned int mbToRead = 1; if(argc > 3){ - sscanf(argv[3], "%u", &mbToRead); + mbToRead = strtoul(argv[3], NULL, 10); } if(mbToRead > 128){