[En-Nut-Discussion] SPI master mode Ethernut 5

Harald Kipp harald.kipp at egnite.de
Tue Dec 16 11:26:57 CET 2014

Hi Sergej,

On 12.12.2014 11:00, Sergej Schmidt wrote:
> Actually i'm using no specific device driver, so if i call: 
> NutRegisterSpiDevice(NULL, &spiBus1At91, 0);
> the OS suspends infinitely. 

Yes, I'd expect this. NutRegisterSpiDevice() calls NutRegisterDevice()
with a NULL pointer, which will crash.

Note, that Nut/OS intentionally does not check parameters for validity.
(At least it should not, although some parts of the code violate this
rule). The application is typically in a better position to make sure
that parameters are valid. Checking parameters on every system call
would significantly blow up the code.

During development however, it may be quite useful. You can enable
parameter checking by defining NUTDEBUG_USE_ASSERT, see


In that case NutRegisterSpiDevice(NULL, &spiBus1At91, 0) would have
called NUTFATAL().

> The code snipping I am actually using is:
> int MyTransfer(uint8_t *buf, int len) {

This seems to be unused. Always try to reduce your test samples to the
bare minimum.

> 	result = At91SpiBusTransfer(&my_node, &transfer, NULL, 1);

I was unable to build your sample, At91SpiBusTransfer() is undefined.

If you want a generic SPI driver, why not simply take over the required
SPI snippets from the Nut/OS code (or any other AT91 SPI code you can
find in the Internet) and place it in your application code? It may be
too much hassle trying to adapt the SPI bus driver to a generic
interface, without any specific SPI device driver.


    /* Enable peripherals. */
    outr(PIOA_PDR, _BV(PA0_SPI0_MISO_A) | _BV(PA1_SPI0_MOSI_A) |
    outr(PIOA_ASR, _BV(PA0_SPI0_MISO_A) | _BV(PA1_SPI0_MOSI_A) |
    /* Enable SPI. */
    outr(SPI0_CR, SPI_SPIEN);
    /* Set SPI mode. */
    outr(SPI0_MR, (1 << SPI_PCS_LSB) | SPI_MODFDIS | SPI_MSTR);
    outr(SPI0_CSR1, /* SPI_CPOL | */ SPI_NCPHA | (4 << SPI_SCBR_LSB));


    /* Transmission starts by writing the transmit data. */
    outr(SPI0_TDR, c);
    /* Wait for receiver data register full. */
    while((inr(SPI0_SR) & SPI_RDRF) == 0);
    /* Read incoming data. */
    return (uint8_t)inr(SPI0_RDR);

Note, that this code fragments are for SPI0. You need to change them to
use SPI1, e.g. replace PA0_SPI0_MISO_A with PB0_SPI1_MISO_A etc.

Use simple GPIO for your chip selects.

In any case you should read the related parts of the SAM9XE datasheet.




> Today's Topics:

The mailing list etiquette demands interleaved reply style, see
Please do not reply with the full digest. As a result your reply got
stuck in the mailing list processor and required manual approval.

More information about the En-Nut-Discussion mailing list