This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Best way to do high frequency writes to SPI - using ticker?

I'm using the mbed platform and have been battling hard faults as I try to find the best way to write with high frequency to SPI to update a series of LEDs while still allowing for intermittent data to come in on BLE to change settings for the LEDs, (color, speed, etc).

After quite a bit of experimentation I’m doing this by setting up a ticker in the main loop of the program which consistently calls the LEDupdate function that sends LED data via SPI. In my BLE onDataWrittenCallback the very first line uses a pointer to my ticker to disable the ticker. Then I parse the data written, put it in the correct spots so that it can change whatever LED settings it needs to change and set a flag that my ticker needs to be turned back on. Once I hit the main BLE wait loop again the ticker is re attached, the ticker flag is set to false since the ticker is now active and my LEDs resume updating.

The issue at first was that if I had my ticker on too short an interval then trying to write to the BLE would hard fault the chip. By making the ticker a longer interval I was able to get things to stabilize, but I would have thought there would be no default since the ticker isnt turned back on until the data has been processed.

  • My question then is whether this is the best approach to writing at high frequency to the SPI?

  • Furthermore, are the hard faults because when I restart my ticker the soft device is not quite done doing what it needs to do behind the scenes after receiving data and so my ticker is bumping into the soft device?

Along those lines I had a relatively stable implementation of this setup working but then I added another characteristic to my service and it caused the chip to lock after receiving data via BLE. After many tests I was able to solve this by making the ticker interval much slower. To me this is strange, the new characteristic is never referenced or written too, just initialized, but still it seems to be slowing down how quickly the soft device finishes its work after getting data and forces me to slow my ticker. Additionally writing one byte to the BLE device or writing a full 20 bytes didn't seem to make any difference to locking the chip up, while simply having the extra characteristic made a big difference.

Here is the simple code I'm using

void onDataWrittenCallback(const GattWriteCallbackParams *params) {

ptrTicker->detach();

if (params->handle == ledServicePtr->getColorHandle()) {
    currentSettings.color[0].r = params->data[0];
    currentSettings.color[0].g = params->data[1];
    currentSettings.color[0].b = params->data[2];
} else if (params->handle == ledServicePtr->getColorRawHandle()) {
    currentSettings.color[0].r = params->data[0];
    currentSettings.color[0].g = params->data[1];
    currentSettings.color[0].b = params->data[2];    
}
OLEDdirty = true; 
TICKERdirty = true;}



Ticker ticker;
ptrTicker = &ticker;     

while (true) {
    if (OLEDdirty) {redrawOled();}
    if (LEDdirty) {
        LEDdirty = false;
        LEDs.update();
        }
    if (TICKERdirty) {    
         TICKERdirty = false;
         ticker.attach_us(LEDupdate, 8000);  //8ms ticker
       }  
    ble.waitForEvent();
}}

A couple weird formatting issues with the code embed but this is the gist of it, I can get it to be stable but when I am right on the edge of too short a ticker interval I'll lock up after a couple writes. I'll report back if I get any traction on the mbed forum or if I discover a solution.

Parents
  • The actual LEDupdate function that the ticker is pointing to is very quick, just moving some data around in an array. The SPI write where I actually push that data to a strip of LEDs happens in the LEDs.update(); call which is in the main loop. Basically the ticker updates the LED data then sets a flag so that the next time you hit the main loop the function to push that data to the SPI is called.

    I haven't had a chance to remove the SPI writes that are in the main loop, but I will do that now to see if I can still get a hardfault there. I also need to figure out why adding a characteristic to my service causes the a fault where the code was stable before. I'll report back with anything I find.

Reply
  • The actual LEDupdate function that the ticker is pointing to is very quick, just moving some data around in an array. The SPI write where I actually push that data to a strip of LEDs happens in the LEDs.update(); call which is in the main loop. Basically the ticker updates the LED data then sets a flag so that the next time you hit the main loop the function to push that data to the SPI is called.

    I haven't had a chance to remove the SPI writes that are in the main loop, but I will do that now to see if I can still get a hardfault there. I also need to figure out why adding a characteristic to my service causes the a fault where the code was stable before. I'll report back with anything I find.

Children
No Data
Related