Open kalj opened 4 years ago
Sorry it's not working! There's been some discussion over on the embedded_hal
repo about how the spi::FullDuplex
trait is not very well defined with respect to hardware FIFOs, and so sometimes there are interoperability problems. I haven't checked if there's been any progress on that. I may need to just make a blocking interface (and possibly remove the async support) so it works more reliably with other HAL crates.
Were you able to tell if it's just spinning in that loop, or if the .read()
call is blocked? The latter should not happen because it's supposed to be async, but anything is possible :)
Which crate are you using to get an implementation of embedded_hal::spi::FullDuplex
on your RPi? I mostly tested this on STM32, so it would be nice to get it working elsewhere.
Sorry for the bad response back.
It is spinning in the loop; the read()
call is not blocked.
I am using rppal
and I am using a Raspberry Pi Zero W.
Can I give you any other information?
I think this might be caused by mismatched assumptions between what ssd1322
expects from a FullDuplex
, and what the rppal
implementation provides. In the absence of guidance from the embedded_hal
definition/documentation, I am unfortunately not sure which libraries need fixing.
The rrpal
impl unconditionally returns Ok(v)
where v
is the last byte shifted in on MISO, even if v
has already been returned before, a.k.a. even if no new transfer has occurred. It will never return nb::Error::WouldBlock
when there is no more data to read, which is what that while-let in send_command
is expecting.
Despite the fact that the SSD1322 does not have a MISO line to return data back to the master, the FullDuplex
trait is documented as requiring one read
call for every send
call, or the hardware may overflow the receive buffer (in this case, with garbage from a floating or tied MISO line). As the comment alludes, the loop on read
is intended to prevent this and also to detect that all FIFOs on the SPI master are empty before changing the state of the D/C line. Without some way to synchronize this, the driver can toggle the D/C line while the hardware is still shifting one or more bytes out on MOSI, which violates the timing requirements for the SSD1322.
As I mentioned previously, there has been some debate about whether FullDuplex
trait is well-specified enough to be interoperable, and I think this is another example of that: the documentation for FullDuplex::read
actually doesn't say that rppal
's implementation is incorrect, because it doesn't require implementors to provide the behavior I'm relying on -- namely that it should only return each incoming word once, and that it should return nb::Error::WouldBlock
if the receive FIFO is empty.
There is a tracking issue for FullDuplex
trait's problems already; let me try to catch up on any developments there and figure out what to do.
Tracking bugs on FullDuplex
that I know of:
Thanks for your answers. Unfortunately, the complex interplay between the rust type system and the full duplex SPI protocol makes this a bit too complicated for me to fully grasp. If I understand you correctly, there is no simple workaround for this issue when using rppal
/ embedded_hal
? I found the alternative SPI crate https://github.com/rust-embedded/rust-spidev -- can I use that somehow or do I need something which implements the embedded_hal
traits?
Another problem I am experiencing is that each spi.send
inside send_data_async
takes way too long time and cpu resources. Checking with an oscilloscope, data is in fact sent out at the configured 10MHz, but it takes 40µs between each byte sent to the display, time which is spent busy inside spi.send
. Perhaps this is completely unrelated, or due to other problems in rppal
, but do you have any feeling for what might be going on there?
When trying out the basic example code (adapted for a raspberry pi), the program hangs at the call to
init
. Looking further, it seems every call tosend_command
hangs in the while loop preceded by this comment:The explanation can be found in the data sheet (e.g. http://www.newhavendisplay.com/specs/NHD-3.12-25664UCY2.pdf page 11): "Note: Read is not available in serial mode."
By commenting out the while loop, everything seems to work fine. I don't really know what the solution is, since that seems to non-standard SPI behavior. Perhaps it needs to implement another, more restricted SPI interface with no
send
function?