Main Site Documentation

Issue with two SPI devices on same bus

Hello all,

I am using two devices on the same SPI bus and am having issue because one of the device is using

ChipSelectType = SpiChipSelectType.None

Consider the following code :

private static void TestSPI()
        {
            var settings1 = new SpiConnectionSettings()
            {
                Mode = SpiMode.Mode0,
                ChipSelectType = SpiChipSelectType.Gpio,
                ChipSelectLine = Pin.PA13,
                ClockFrequency = 8000000,
                DataBitLength = 8
            };
            var device1 = SpiController.FromName("GHIElectronics.TinyCLR.NativeApis.STM32F4.SpiController\\2").GetDevice(settings1);

            var settings2 = new SpiConnectionSettings()
            {
                Mode = SpiMode.Mode0,
                ChipSelectType = SpiChipSelectType.None,
                ClockFrequency = 8000000,
                DataBitLength = 8
            };
            var device2 = SpiController.FromName("GHIElectronics.TinyCLR.NativeApis.STM32F4.SpiController\\2").GetDevice(settings2);
            // Initialize device2's CS line
            var _cs = GpioController.GetDefault().OpenPin(Pin.PD11);
            _cs.SetDriveMode(GpioPinDriveMode.Output);
            _cs.Write(GpioPinValue.High);

            // Sending data to device 1, result OK
            device1.Write(new byte[] { 0x06 });
            
            // Sending data to device 2, result OK
            _cs.Write(GpioPinValue.Low);
            device2.Write(new byte[] { 0x06 });
            _cs.Write(GpioPinValue.High);

            // Sending data to device 1 again, result NOK
            // This line throws InvalidOperationException during the SetActive() call
            device1.Write(new byte[] { 0x06 });

            // If you comment the line above, the following code also throws the same exception
            // Sending data to device2, then to device1 and finally to device2 again
            _cs.Write(GpioPinValue.Low);
            device2.Write(new byte[] { 0x06 });
            device1.Write(new byte[] { 0x06 });     // This line throws InvalidOperationException during the SetActive() call
            device2.Write(new byte[] { 0x07 });
            _cs.Write(GpioPinValue.High);
        }

As soon as I send data to device2, I can’t write to device1 anymore.

Am I doing something wrong, here ?

Ignore the software, you can not use multiple SPI devices without having multiple cop select pins. So what you are doing will simply not work.

Sorry Gus, but I don’t understand what you are saying :frowning:

I am using different cs pins (PA13 & PD11, namely).

EDIT: btw, even if both devices on the same bus are using SpiChipSelectType.Gpio with a different cs line for each device, I still get the exception when I try to write to device1 again.

The following sequence produces an exception :
device1.Write is ok
device2.Write is ok
device1.Write is NOK

If I replace the last line with “device2.Write” then it’s ok. But I can’t write to device1 anymore.

EDIT 2 : if both devices are on a different bus, then everything is fine. So it seems that we cannot use more than one device on a bus. Am I right ?

Hang on, you said first up that one of them does not use a CS. Then you say

Why don’t you tell us which it is?

A device that doesn’t use a CS will always assume it has exclusive use of the bus. it will read every command on the bus and write when it likes. What devices are you testing with? Even if you take the time to connect a CS to a device that doesn’t use it, it won’t change the fact that the device doesn’t care about the CS

It looks like my words were not chosen wisely :frowning: I should have said that one of them was not using a CS pin in its SpiConnectionSettings.

I want to control a SPI device (FT800 chip) on which I need to control the way its cs pin is set. That way, I can send data that needs calculations before releasing this pin and terminate the transaction.
The only way to do this with TinyCLR (unless I missed something) is to use ChipSelectPin.None and manually control the CS pin as a standard gpio pin, setting it to low when starting a transaction and setting back to high when I’m done.
This alone works perfectly. The FT800 demo I’ve published a few days ago is using this technique.

Now, I want to send data from a SPI flash memory to the FT800 memory during the transaction. This is where problems arise.
My first assumption regarding the ChipSelectPin.None seems to be wrong as I get the same exception if I use ChipSelectPin.Gpio on both devices (each with different cs pins, of course). So I 'm not in the case you talk about (exclusive access).

I would even say that what I see is the opposite of what you say : it seems that TinyClr does care about the cs otherwise it would not complain with such exception when trying to set another cs active.

Have you tried to (EDIT) write to two different SPI devices on the same bus ? If yes, did you get this exception ?

Ah ok. You do have 2 chip select pins but you want to control one of them manually.

Why not set them both to none and control both of them manually?

I am sure we didn’t test having both ship select options simultaneously as the us an unusual situation but we will look into it in the future for sure.

By the way, I spent my weekend with FT800. I finally understand the internals of this chip. Very cool.

1 Like