Skip to content
This repository has been archived by the owner on Jan 7, 2019. It is now read-only.

Support for half-duplex SPI #317

Open
genbattle opened this issue Dec 11, 2017 · 9 comments
Open

Support for half-duplex SPI #317

genbattle opened this issue Dec 11, 2017 · 9 comments

Comments

@genbattle
Copy link
Contributor

The STM32 MCUs support half-duplex SPI, which is needed to talk to some peripherals like the LSM303 magnetometer/accelerometer. It would be great if this were exposed via XPCC's SPI API.

@salkinium
Copy link
Member

I think the data API still works for Half-Duplex by sending dummy bytes (as done in several drivers already). So we need to add a function to the SpiMaster API to enable half-duplex mode in hardware, right?

@genbattle
Copy link
Contributor Author

That sounds right. Possibly you could automatically enable half-duplex mode when the MOSI and MISO pins are the same and keep the same API?

@genbattle
Copy link
Contributor Author

Note that I'm referring to multidirectional half-duplex transmission, not write-only or receive-only unidirectional half-duplex.

I'm not sure if the dummy byte approach would allow the user to send and receive data in the same transmission. It would be preferable to avoid releasing the slave select line in between the send and receive phases of the transmission, and you may need to have a different size for each buffer. For example, the common case for me with the LSM303C is to read the magnetometer values: I have to send one byte (the address + command) and then read 6 bytes of data back over the same line. I'm not sure how this could be accomplished with dummy bytes.

@genbattle
Copy link
Contributor Author

genbattle commented Dec 12, 2017

Looking into it further it seems that all the half duplex hardware mode does is tie the MOSI and MISO pins together internally, saving an external pin.

For a send transmission you would just ignore the received data. For a receive you would need to send dummy 0xFF bytes to put the output into open drain (assuming open drain I/O lines) and isolate the I/O line from ground on the receiving end. (diagram)

So I guess yes, it will work, provided just the right pin configuration and choice of dummy bytes.

@salkinium
Copy link
Member

Hah. I wrote a driver for the LSM303 accelerometer on the F3 Discovery some time ago. I knew it sounded familiar to me. This is a bit of a weird chip, it almost seems like ST just put two dies in there and connected their busses internally, but not quite.

These sensors all use a similar dual I2C/SPI interface, that is shared with a lot of other ST sensors.
This is abstracted in the Lis3Transport class, which drumroll always uses half-duplex transmissions in SPI mode by sending dummy-bytes on read and ignoring read bytes on write.

The dummy bytes are signalled with a nullptr I think because the value was platform dependent? Not sure, but it's abstracted already. I think this should just automagically work by adding a function to the SpiMaster to enable this hardware mode.

(I remember the magnetometer being very similar to some other magnetometer sensor driver in xpcc, which is why I didn't write a driver for it and then forgot…)

@genbattle
Copy link
Contributor Author

Wow now I really feel like an idiot, I've literally been writing my own drivers for the LSM303 and LIS3MDL for the last couple of months. I can't believe I missed that xpcc already has a driver for these devices.

Ok, so given that the only work that needs to be done is adding support for the hardware mode, what's the best way to do this? I like the idea of automatically enabling it if the MOSI and MISO pins are the same since it doesn't require modifying the existing interface at all, and it doesn't leave a useless method on other platforms. The disadvantage would be that it's somewhat unintuitive without clear documentation of this feature.

If all that is needed is adding the hardware support, this could be something I could get done over the Christmas holidays.

@chris-durand
Copy link
Member

chris-durand commented Dec 13, 2017

These sensors all use a similar dual I2C/SPI interface, that is shared with a lot of other ST sensors.
This is abstracted in the Lis3Transport class, which drumroll always uses half-duplex transmissions in SPI mode by sending dummy-bytes on read and ignoring read bytes on write.

I suppose this is not what @genbattle means. The LSM303 also supports a half-duplex 3-wire SPI mode which uses only one bidirectional data line (no MISO/MOSI; only SCK, CS and SDIO). The STM32 has hardware support for this. You have to set the BIDIMODE bit in SPI_CR1 to enable this mode. This will disable the MISO pin. The MOSI pin will be used as a bidirectional IO. The data direction can be controlled by setting the BIDIOE bit in SPI_CR1. It is not enough to change the device driver, this needs to be implemented in the stm32 spi driver. Maybe I'll find some time to look into it on sunday.

@salkinium
Copy link
Member

It is not enough to change the device driver, this needs to be implemented in the stm32 spi driver.

What I meant is that the sensor driver code doesn’t send and receive at the same time anyways. So the half-duplex operation should be transparent to the sensor driver and only exposed to the user as a peripheral driver config option (like setting the baudrate).

I like the idea of automatically enabling it if the MOSI and MISO pins are the same since it doesn't require modifying the existing interface at all, and it doesn't leave a useless method on other platforms.

Yes, that’s very neat, however the xpcc gpio multiplex API is very broken (see #178 for details and how it’s been fixed in modm), so this won’t easily be doable. Therefore, I recommend the extra API for now as a temp fix.

In modm, this can simply be implemented like so, incl. static compile time tests (ie. if SDIO is used, MISO and MOSI must not be used, and vice versa):

Spi3::SpiMaster::connect<GpioB5::Sck, GpioB6:Sdio>();

@salkinium
Copy link
Member

Wow now I really feel like an idiot,

Whoopsie 😛

I've literally been writing my own drivers for the LSM303 and LIS3MDL for the last couple of months. I can't believe I missed that xpcc already has a driver for these devices.

Better check how compatible these drivers really are. There are several “almost identical” sensors from ST that then still differ in memory map or transmission protocol. It’s really annoying.

@salkinium salkinium added this to the 2018q1 milestone Dec 15, 2017
@salkinium salkinium removed this from the 2018q1 milestone Apr 4, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants