Slow SPI on Artemis ATP

I am communicating with an ADS7961 16 channel A/D using the Artemis ATP running Arduino code and using the SPI.h library.

Each read requires 16 clock cycles and I am running the clock at 10 MHz so I should be able to get about half of the 1 MSPS rate the device offers. However, the SPI library is horribly slow, it takes approximately 30us to set up an 8 bit read and another 30us for the second 8 bit read to make the 16 bit transfer, with other delays in setting and releasing CS means that I’m running at about 1/50th of the speed I should be able to achieve.

Is there any solution to this? Is there a faster SPI library? Would moving to Mbed lead to significant speed-up?

Hi, is your power supply sufficient?

MBED brings a lot of overhead. I have seen that in other places with GPIO handling. Just to check that it is MBED (or just for the fun), install the library version 1.2.3 instead of the current V2.2.1. This library is much faster and then check whether you get the expected performance

Thanks for the replies - power shouldn’t be an issue as I’m powering over USB, only drawing a few 10s of mA and I’m not seeing any power supply dips.

To clarify I’m not using MBED at the moment, I’m using the Arduino SPI library, I was considering moving to MBED if it would speed things up, but from the sound of things it won’t. What other options are there? Is this where I need to write bespoke SPI routines in C++?

If you use the library 2.x.x. it includes/uses MBED. Next to a few more pass-on calls in between, with every click MBED-OS performs some housekeeping checks. Even if nothing is used. As a test, I have used a BME280 on SPI with the Arduino SPI library. With Artemis library 2.2.1 the SPI results take 2.5 to 2.7 times LONGER than with Artemis library version 1.2.3. Hence my proposal to look at version 1.2.3

Paul,

Tanks for clarifying - I misunderstood what you were suggesting. I’ll implement that as it sounds like a good way to get some low-cost speed-up, but it still seems a long way short of what the system should be able to achieve.

you might get an error message on that some functions are not available. If you run into that there is an easy fix to work around that.

To your point of speed, MBED can work as an real time operating system (RTOS). As such it does a lot of housekeeping in the background, which brings overhead. Most of that is not needed for a simple solution but you can not turn it off.

paulvha, how would you resolve the issue of a missing function error?

I assume you got a larger number of errors during compile with the 1.2.3 version like

/home/paul/Arduino/libraries/Adafruit_BusIO/Adafruit_SPIDevice.cpp: In constructor 'Adafruit_SPIDevice::Adafruit_SPIDevice(int8_t, int8_t, int8_t, int8_t, uint32_t, BusIOBitOrder, uint8_t)':
/home/paul/Arduino/libraries/Adafruit_BusIO/Adafruit_SPIDevice.cpp:53:48: error: 'digitalPinToPort' was not declared in this scope
   csPort = (BusIO_PortReg *)portOutputRegister(digitalPinToPort(cspin));

The root cause is because ‘BUSIO_USE_FAST_PINIO’ is defined in Adafruit_SPIDevice.h by an incomplete check.

You can adjust that check (around line 65 in the header-file) or the easiest way around to test is in the top of Adafruit_SPIDevice.cpp, just after the include, add an undef like :

#include "Adafruit_SPIDevice.h"
#undef BUSIO_USE_FAST_PINIO   // needed for Artemis