SPI TransferFullDuplex writeBuffer Exception

I am migrating a driver for the TinyFileSystem from NETMF to TinyCLR OS, and have come up with a problem on SPI code using the WriteRead() in NETMF, where I can not seem to find an equivalent in TinyCLR, or at least is not working for me.

In the read method, the NETMF code is:

public void ReadData(int address, byte[] array, int index, int count)
            if ((array.Length - index) < count) throw new ArgumentException("Invalid index + count");
            if ((MaxAddress - count) < address) throw new ArgumentException("Invalid address + count");

            while (WriteEnable() == false) Thread.Sleep(0);

            data4[0] = CMD_READ;
            data4[1] = (byte) (address >> 16);
            data4[2] = (byte) (address >> 8);
            data4[3] = (byte) (address >> 0);
            _spi.WriteRead(data4, 0, 4, array, index, count, 4);


To clarify, that is this overload:

spi.WriteRead(writeBuffer, writeOffset, writeCount, readBuffer, readOffset, readCount, startReadOffset);

The best I can come up in TinyCLR is:

spi.TransferFullDuplex(data4, 0, array, index, count);

But this then throws an exception about writeBuffer, see below.

Not sure about the error, so any hints or pointers?

1 Like

Can we see the SPI initilization code?

yes, here it is… This is running on a G120 based board. Just to clarify again, all is perfect on the same board under NETMF.

    var spiConfig = new SpiConnectionSettings(G120.GpioPin.P3_25);
    spiConfig.Mode = SpiMode.Mode0;
    spiConfig.ClockFrequency = 10000000; //10Mhz
    spiConfig.DataBitLength = 8;
    spiConfig.SharingMode = SpiSharingMode.Shared;
    spi = SpiDevice.FromId(G120.SpiBus.Spi0, spiConfig);

Also the init under NETMF

var spiConfig = new SPI.Configuration(Pins.FlashSPIChipSelect_P3_25, false, 0, 0, true, true, 10000, Pins.SpiBus.FlashSPI1);
spi = new SPI(spiConfig);

Quickly looking into this, I think you need a write followed by a read. Do not use full duplex.

Wire the 4 byes then read “count” byes.

Ok thanks, will try that.

Just to clarify, does the TransferFullDuplex(…) expect both the write/read buffers to be of the same size? Seems that needs to be the case?

Yes mostly

I believe you want TransferSequential instead, it writes the write buffer then reads into the read buffer whereas TransferFullDuplex writes and reads at the same time, which is why their buffers are required to be the same size.

Isn’t TransferSequential simply a write followed by a read? I guess the difference is chip select will be asserted through both transactions.

I found a good explanation of the differences from a Microsoft, and Gus is correct. The details are as follows:

"TransferSequential will first transmit the send byte, then clock in the receive byte, for a total of two bytes transferred.

TransferSequential will keep the CS line asserted through the transmission of both bytes. Calling Write and then Read will cause the CS line to be deasserted, then reasserted between the write and read.

TransferSequential(S, R);
MOSI —S[0]— -----------
MISO ------------- —R[0]—
CS --_________________–

and a Write/Read combo…

Write(S); Read®;
MOSI —S[0]----- ----------
MISO -------------- -----R[0]—
CS --_________—_________–


Will try transfersequential…