RIOT-OS / RIOT

RIOT - The friendly OS for IoT
https://riot-os.org
GNU Lesser General Public License v2.1
4.87k stars 1.98k forks source link

periph/spi: Switching between CPOL=0,1 problems on Kinetis with software CS #6567

Open jnohlgard opened 7 years ago

jnohlgard commented 7 years ago

(I did not yet verify this with a scope) The software CS is causing problems when moving between different clock polarity settings. We discovered that the LIS3DH driver on mulle requires setting the SPI mode to 0, but it should be using mode 3 according to the data sheet, as well as when using the old SPI driver and when using a different driver in Contiki. Clearly there is something different with the new RIOT SPI driver.

The current driver also works in mode 3 if the LIS3DH configuration is changed to use hardware CS on Mulle (PR #6572).

I believe that the problem arises from the fact that the CS pin is asserted before the new clock polarity setting is applied to the SPI module, resulting in the device picking up the clock polarity change as a normal clock pulse, when in fact it should be ignored. However, this does not explain why it used to work in the old periph driver, which also was using software CS where the CS pin was managed by the LIS3DH driver itself instead of deferred to the SPI bus driver.

This needs investigation with a scope or logic analyzer.

jnohlgard commented 7 years ago

Also, the LIS3DH driver works if we retry the who am I query during init, but that's just hiding the problem because the first transfer will have placed the bus in the correct clock polarity for the second transfer.

haukepetersen commented 7 years ago

Will look into this as soon as I can.

miri64 commented 6 years ago

@haukepetersen did you?

PeterKietzmann commented 5 years ago

@MrKevinWeiss I just wanted you to be aware of this issue.

MrKevinWeiss commented 5 years ago

Thanks, I have kinetis boards and a scope. I will check it out!

stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you want me to ignore this issue, please mark it with the "State: don't stale" label. Thank you for your contributions.

kaspar030 commented 4 years ago

ping @MrKevinWeiss

MrKevinWeiss commented 4 years ago

Darn, I will try to remember when I'm back from vacation.

PeterKietzmann commented 4 years ago

@MrKevinWeiss obviously you didn't

MrKevinWeiss commented 4 years ago

True... I'll check it out, thanks!

MrKevinWeiss commented 4 years ago

I tested on the frdm-kw41z using test/periph_spi at 100 kHz The procedure is:

> reboot
> init <args>
> send 123

args = init 0 0 0 -1 0 -> Mode 0, hw cs spi0h

args = init 0 0 0 2 19 -> Mode 0, sw cs spi0s

args = init 0 1 0 -1 0 -> Mode 1, hw cs spi1h

args = init 0 1 0 2 19 -> Mode 1, sw cs spi1s

args = init 0 2 0 -1 0 -> Mode 2, hw cs spi2h

args = init 0 2 0 2 19 -> Mode 2, sw cs spi2s

args = init 0 3 0 -1 0 -> Mode 3, hw cs spi3h

args = init 0 3 0 2 19 -> Mode 3, sw cs spi3s

PeterKietzmann commented 4 years ago

@MrKevinWeiss many thanks! What is your interpretation of the results? On first sight CS behavior looks normal to me, although it returns to high very fast in some configurations. Furthermore, the logic analyzer didn't decode all cases correctly. Did you just miss to switch the decoder mode?

MrKevinWeiss commented 4 years ago

I think there could be the problem when using soft CS and low power mode that @MichelRottleuthner pointed out on another platform (clock ends in the wrong polarity).

My interpretation is: Mode0: POL=0 PHA=0 Mode1: POL=0 PHA=1 Mode2: POL=1 PHA=0 Mode3: POL=1 PHA=1

Which matches, the decoding was probably just a setting on the scope. My intention wasn't to show the decoding but the signals. Mode 0 and mode 3 both trigger the first rising edge, the only difference is the initial clock level, mode 3 starts high and mode 0 starts low.

I may have missed the initial capture of some of these actually and remember some problems that resulted in sending the command twice.

This may be because in mode 3, the clock pin starts low and when the CS pin goes low the device sees a clock pulse as the clock tries to go to its desired starting position. We don't see this the second time around because the SW CS leaves the clock high.

I would suggest setting the SCK based on the polarity setting during init.

miri64 commented 4 years ago

So... is this a bug? Can it be fixed? Did we fix it?