Rewritten SPI_CTRL using a bitfield instead of raw values for ease of documentation
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
28519977cf
commit
5e21afe140
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
/fm10k-dump
|
||||
/*.o
|
||||
/.idea
|
4
Makefile
4
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
|
||||
|
|
94
fm10k-dump.c
94
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){
|
||||
|
|
Loading…
Reference in a new issue