Jump to content

C4 SPI problems


Recommended Posts

Hi all,

I have upgraded an Odroid C2 setup to C4, and encountered some strange issues.

The SPI interface of C2 is bit banging, while the C4 offers "real" hardware support for SPI.

I use a current kernel (5.10.102) with Bullseye.

I use two SPI /CS lines, while one SPI controller takes care of "user" interaction with the LatticeSemi MachXO2 FPGA on the addon board.

The other SPI controller is used to reflash the MachXO2 by the SPI.


On the C2, everything works fine (while slow, due to bitbanging).


On the C4, the same code on Odroid and FPGA fails - but only on the reflashing interface, not the user interface.

The user interface uses "short" SPI accesses with usually 7 bytes in a command.

The programming interface has long accesses with usually 16bytes++ for writing one 128bit FlashROM pages.

As first result, the last byte of  FlashROM page (16bytes) is usually fixed to zero. It seems to happen on readback.


Has anyone encountered similar problems?


Thanks in advance, Michael

Link to comment
Share on other sites

  • mboehmer changed the title to C4 SPI problems
Donate and support the project!

I can confirm now a bug in the SPI kernel driver (AFAIK)  for Odroid C4.

SPI transfers on Odroid C4 work only reliably with a transfer size of 15 bytes or less.

As soon as a transfer on SPI has more than 15 bytes (i.e. 16++), the last byte of the RX field of the transfer is overwritten by 0x00.

I can see that correct data is being returned by the connected SPI slave on my logic analyzer.


Same user code works without problems on C2 systems.


I can file a bug with extended documentation here.

Link to comment
Share on other sites

New information: the "last byte read fixed to 0x00" happens only on slow SPI speeds, to my best knowledge it starts with SPI frequencies slower than 300kHz.

SPI transmissions always work, correct data is sent out and received (according to logic analyzer).


If you want to test it on your own, connect a jumper between pins 19 and 21 on the 40pin expansion header, and use a simple SPI transmission to see if things work.

You need to open the SPI device first. SPI transmissions in my code are limited to 20bytes usually (one MachXO2 FlashROM page write/read).


uint8_t test_spi( int fd, uint8_t size, uint32_t speed )
  uint8_t tx[size];
  uint8_t rx[size];

  memset(tx, 0xaa, size);
  memset(rx, 0x55, size);

  struct spi_ioc_transfer tr = {
    .tx_buf = (unsigned long)tx,
    .rx_buf = (unsigned long)rx,
    .len = ARRAY_SIZE(tx),
    .delay_usecs = 0,
    .speed_hz = speed,
    .bits_per_word = 8,

  if( ioctl(fd, SPI_IOC_MESSAGE(1), &tr) == -1) {
    return OP_ERROR;

  /* print received data */
  for( uint8_t i = 0; i < size; i++ ) {
    printf("%02x ", rx[i]);

  /* print transmitted data */
  for( uint8_t i = 0; i < size; i++ ) {
    printf("%02x ", tx[i]);

  return OP_OK;


Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Create New...