wokwi / rp2040js

A Raspberry Pi Pico Emulator in JavaScript
MIT License
384 stars 40 forks source link

SPI burst read/write #105

Open mingpepe opened 1 year ago

mingpepe commented 1 year ago

The onTransmit has no information about if it's the same transfer (chip select pin keep low). For my case, I need to simulate a SPI slave which has different behavior for different transfer length. The CS pin is controlled directly by hardware, currently I have no idea how to fix it. Any suggestion?

https://github.com/wokwi/rp2040js/blob/cac702d96ba358d73da4226b6259488c4671fd59/src/peripherals/spi.ts#L112-L119

urish commented 1 year ago

The CS pin is controlled directly by hardware

How is it controlled directly? I couldn't spot any SPI register that controls the CS pin?

mingpepe commented 1 year ago

I guess SPI hardware output CS low when TX fifo is not empty, and output high CS high after TX fifo is empty for a peroid of time. Currently I did not find detail document about it.

urish commented 1 year ago

Couldn't find any documentation either.

Quick googling shows that SS might always be low when SPI is enabled:

image

Source: https://developer.arm.com/documentation/ddi0194/h/functional-overview/primecell-ssp-operation/examples-of-master-and-slave-configurations

mingpepe commented 1 year ago

The name of pin is misleading. I mean SSPFSSOUT.

active low chip select or frame sync ss_n (referred to as SSPFSSOUT in the following sections)

https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf p504

For my case, frame format is Motorola SPI with SPO=1, SPH=1. I'm pretty sure CS pin will toggle.

urish commented 1 year ago

Good job on finding it!

image

Yes, we are definitely missing this functionality. I don't have the bandwidth to work on it in the near future, but if you are up to working on a pull-request, I suggest adding a callback, onCSChange, that will be called whenever the CS pin value needs to change, and another read-only property that will return the current value of the CS pin.

mingpepe commented 1 year ago

The problem is when onCSChange is called, it's not controlled by register. When reading or writing SPI, only the DR register is read or wirtten.

https://github.com/raspberrypi/pico-sdk/blob/2e6142b15b8a75c1227dd3edbe839193b2bf9041/src/rp2_common/hardware_spi/spi.c#L84-L93

urish commented 1 year ago

Yes, it's not trivial. If I understand correctly, the logic behind onCSChange() should more or less reflect the value of the busy flag we already have?

mingpepe commented 1 year ago

My understanding it's not the same with the busy flag. Write data to SSPDR push data to FIFO, then call doTX Then it set the busy flag then call user callback, and once user callback call completeTransmit, the busy flag is off. And user callback must call completeTransmit, otherwise RX has no data to read. User will see the busy flag on -> user callback -> flag off, only 1 byte is transfered.