On our custom i.MX6Q based board we use the SPI controller as slave.
Since we are running under Linux, we had to write a custom SPI slave driver.
This driver is very lean. It's basically just bare metal register configuration and IRQ handling - no unneccessary overhead.
The driver seems to work pretty good, because the master can communicate with our board and we can answer.
However occasionally the SPI controller seems to be missing SPI bursts from the master.
My test environment:
Even though the IRQ load on the i.MX6 is extremely low, about 0.5% of all SPI bursts are not recognized/lost by the i.MX6 SPI controller.
Things get worse as we increase the clock speed.
I read about the silicon SPI bug on the i.MX6, but as far I understood this only applies to burst lengths of (32 * n) + 1.
Does anyone have an idea what might be going wrong?
My relevant source code:
SPI Master main loop:
uint8_t i = 0;
while ( 1 ) {
tx_buffer = i++;
rc = ioctl(fd, SPI_IOC_MESSAGE(1), &transfer);
if ( rc < 0 ) {
printf("Error transmitting SPI frame\n");
exit(255);
}
fprintf(f, "Sent: 0x%.2X - Received: 0x%.2X\n", tx_buffer, rx_buffer);
usleep(100 * 1000);
}
Slave Kernel configuration code:
reg = 0x70f4e1; // 7629Hz 8bpw
writel(reg, slave->io_base + OFFSET_CONREG);
reg = 0;
writel(reg, slave->io_base + OFFSET_CONFIGREG);
reg = 0;
reg |= MX51_ECSPI_INT_RREN;
writel(reg, slave->io_base + OFFSET_INTREG);
Slave ISR code:
static irqreturn_t spi_slave_isr(int irq, void *dev_id) {
struct spi_slave_data* slave = dev_id;
unsigned value;
unsigned rxcnt;
value = readl(slave->io_base + OFFSET_TESTREG);
rxcnt = (value & MASK_RX_FIFO_COUNT) >> SHIFT_RX_FIFO_COUNT;
for ( ; rxcnt; --rxcnt ) {
value = readl(slave->io_base + OFFSET_RXDATA);
writel((uint32_t)value, slave->io_base + OFFSET_TXDATA); // just resend what we just received
printk(KERN_INFO "rx: 0x%.2X\n", value); // not a problem here because we have 100ms delay
}
return IRQ_HANDLED;
}
Erroneous console output on the slave:
rx: 0x91
rx: 0x92
rx: 0x93
rx: 0x94
rx: 0x95
rx: 0x96
rx: 0x98
rx: 0x99
rx: 0x9A
rx: 0x9B
Note that 0x97 is missing
Corresponding output on the master:
Sent: 0x92 - Received: 0x91
Sent: 0x93 - Received: 0x92
Sent: 0x94 - Received: 0x93
Sent: 0x95 - Received: 0x94
Sent: 0x96 - Received: 0x95
Sent: 0x97 - Received: 0x95
Sent: 0x98 - Received: 0x56
Sent: 0x99 - Received: 0x98
Sent: 0x9A - Received: 0x99
Sent: 0x9B - Received: 0x9A
Sent: 0x9C - Received: 0x9B
Thanks for any help in advance.
Chris
Hi,
I have not tried to implement a driver for the ECSPI module as slave in Linux. But you may find useful the below document:
i.MX6 ESPI slave mode support patch based on rel_imx_3.0.35_4.1.0
The driver is non-dtb compatible, so you will have to perform a few changes. I believe it´s worth taking a look at it.
Best Regards,
Alejandro