[Microbit-Python] SPI APIs on BBC micro:bit and ESP8266

M.-A. Lemburg mal at egenix.com
Mon Nov 21 07:29:48 EST 2016


On 21.11.2016 12:45, David Whale wrote:
> Hi there!
> 
> As Radomir says - that won't work, unfortunately.
> 
> SPI is a master/slave system, the master generates the clock, and the slave
> has to be synchronised to that clock. If both devices are generating a
> clock, you will get clock drift and therefore your data will become
> corrupted.

Yep and that's what we were seeing with the combination ESP/MB.
The combination MB/MB worked quite well with the limited testing
we did.

> In particular, if you look at the direction of the arrows on the first
> diagram on the wiki page, you'll see that SCLK is only driven from master
> to slave: https://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus
> 
> One end must be configured as master, the other end must be configured as
> slave. We don't have an SPI slave implementation on the micro:bit.
> 
> I'm also not quite sure I understand your questions about 'blocking API'.

The API calls for spi.read() and spi.write() do not return
until data is available/sent.

E.g. spi.read(3) will wait until it has received 3 bytes of
data. spi.write(b'abc') won't return until the receiving end
has done an spi.read(3).

> The SPI master will 'just blat out data blindly at it's configured clock
> rate', regardless of what the slave sends back. There is no inherent
> acknowledgement at the physical layer in SPI like there is in I2C (which
> uses a 9th ACK bit). If you tx a data payload of  0x12 0x34 0x56 0x78 on
> SPI into 'fresh air' you will always get back 0xFF 0xFF 0xFF 0xFF (assuming
> the bus is terminated and floats high).

Right and that's what you see on the ESP when doing a .read()
without the MB connected. Once connected, you get 0x00 bytes.

I believe the blocking has to do with the somewhat weird
SPI interface mbed has for the master. It provides a single
spi_master_write() API (and not _read() API), which writes out
data and then reads data:

/** Write a byte out in master mode and receive a value
 *
 * @param[in] obj   The SPI peripheral to use for sending
 * @param[in] value The value to send
 * @return Returns the value received during send
 */
int  spi_master_write(spi_t *obj, int value);

(Source:
https://developer.mbed.org/users/mbed_official/code/mbed-src/file/a11c0372f0ba/hal/spi_api.h)

In MicroPython, the code uses this in a loop:

.write():
    for (uint i = 0; i < bufinfo.len; ++i, ++buf) {
        spi_master_write(&self->spi, *buf);
    }

.read():
    for (uint i = 0; i < vstr.len; ++i) {
        vstr.buf[i] = spi_master_write(&self->spi, byte_out);
    }

(Source:
https://github.com/bbcmicrobit/micropython/blob/master/source/microbit/microbitspi.cpp)

I suppose the "read data" part is what's causing this
to block.

> We'd need to check the underlying mbed SPI driver, and the SPI peripheral
> on the nRF51 application processor, to see what could be causing it to
> 'lock up', as that sounds quite odd. Although if the peripheral in the
> master sets the clock high, and your other micro:bit (slave) pulls it low,
> the peripheral might be entering an error state because it thinks that it
> cannot drive the SCLK line correctly, and that may be stopping the transfer
> by entering an error state.
> 
> SPI is a really simple protocol to implement in software. It won't be
> quick, so you may have to slow down the master clock rate, but you could
> write a polled SPI slave at the receiving end that would work.
> 
> However, I think Damien is right here - it's so much easier to just use the
> UART between the two devices, that should just work out of the box.

Probably, yes, but we didn't want to give up the UART on the MB,
since we'd then no longer be able to monitor whether the script is
working correctly (via print() output). We had also run out
of time at the sprint to give this a try, after first
going with I2C and then SPI.

Cheers,
-- 
Marc-Andre Lemburg
eGenix.com

Professional Python Services directly from the Experts (#1, Nov 21 2016)
>>> Python Projects, Coaching and Consulting ...  http://www.egenix.com/
>>> Python Database Interfaces ...           http://products.egenix.com/
>>> Plone/Zope Database Interfaces ...           http://zope.egenix.com/
________________________________________________________________________

::: We implement business ideas - efficiently in both time and costs :::

   eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
    D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
           Registered at Amtsgericht Duesseldorf: HRB 46611
               http://www.egenix.com/company/contact/
                      http://www.malemburg.com/



More information about the Microbit mailing list