Avoid LED update glitches caused by flash access
Now any access to the flash, either through update writing or SPIFFS access, is blocked while the LED stripes are written. This is accomplished using a FreeRTOS semaphore.
This commit is contained in:
parent
9ddb2063bb
commit
8e9124c884
|
@ -2,6 +2,9 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include <FreeRTOS.h>
|
||||
#include <freertos/semphr.h>
|
||||
|
||||
#include "ChallengeResponse.h"
|
||||
|
||||
class UpdateServer
|
||||
|
@ -12,7 +15,7 @@ class UpdateServer
|
|||
UT_SPIFFS = 1
|
||||
};
|
||||
|
||||
UpdateServer(const std::string &pw);
|
||||
UpdateServer(const std::string &pw, SemaphoreHandle_t *ledLockoutMutex);
|
||||
|
||||
void start(void);
|
||||
|
||||
|
@ -20,4 +23,5 @@ class UpdateServer
|
|||
static void updateTask(void *arg);
|
||||
|
||||
ChallengeResponse m_cr;
|
||||
SemaphoreHandle_t *m_ledLockoutMutex;
|
||||
};
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
#include <HTTPResponse.hpp>
|
||||
#include <HTTPServer.hpp>
|
||||
|
||||
#include <FreeRTOS.h>
|
||||
#include <freertos/semphr.h>
|
||||
|
||||
#include "ChallengeResponse.h"
|
||||
|
||||
class Fader;
|
||||
|
@ -16,6 +19,7 @@ class WebServer
|
|||
|
||||
void setFader(Fader *fader) { m_fader = fader;}
|
||||
void setAnimationController(AnimationController *controller) { m_animController = controller;}
|
||||
void setLedLockoutMutex(SemaphoreHandle_t *ledLockoutMutex) { m_ledLockoutMutex = ledLockoutMutex; }
|
||||
|
||||
static WebServer &instance(void)
|
||||
{
|
||||
|
@ -30,6 +34,8 @@ class WebServer
|
|||
Fader *m_fader;
|
||||
AnimationController *m_animController;
|
||||
|
||||
SemaphoreHandle_t *m_ledLockoutMutex;
|
||||
|
||||
WebServer(void);
|
||||
|
||||
static void serverTask(void *arg);
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
|
||||
#include "coreids.h"
|
||||
|
||||
UpdateServer::UpdateServer(const std::string &pw)
|
||||
: m_cr(pw)
|
||||
UpdateServer::UpdateServer(const std::string &pw, SemaphoreHandle_t *ledLockoutMutex)
|
||||
: m_cr(pw), m_ledLockoutMutex(ledLockoutMutex)
|
||||
{}
|
||||
|
||||
void UpdateServer::start(void)
|
||||
|
@ -177,7 +177,11 @@ void UpdateServer::updateTask(void *arg)
|
|||
|
||||
if(client.available()) {
|
||||
size_t bytes_read = client.read(buf, 1024);
|
||||
|
||||
// block LED updates while writing flash
|
||||
xSemaphoreTake(*obj->m_ledLockoutMutex, portMAX_DELAY);
|
||||
Update.write(buf, bytes_read);
|
||||
xSemaphoreGive(*obj->m_ledLockoutMutex);
|
||||
|
||||
bytes_processed += bytes_read;
|
||||
}
|
||||
|
|
|
@ -22,11 +22,17 @@ bool WebServer::serveFile(String filename, httpsserver::HTTPResponse *res)
|
|||
{
|
||||
uint8_t buf[1024];
|
||||
|
||||
if(!SPIFFS.exists(filename)) {
|
||||
xSemaphoreTake(*instance().m_ledLockoutMutex, portMAX_DELAY);
|
||||
bool exists = SPIFFS.exists(filename);
|
||||
xSemaphoreGive(*instance().m_ledLockoutMutex);
|
||||
|
||||
if(!exists) {
|
||||
return false;
|
||||
}
|
||||
|
||||
xSemaphoreTake(*instance().m_ledLockoutMutex, portMAX_DELAY);
|
||||
File f = SPIFFS.open(filename.c_str(), "r");
|
||||
xSemaphoreGive(*instance().m_ledLockoutMutex);
|
||||
|
||||
if(!f) {
|
||||
return false;
|
||||
|
@ -36,7 +42,10 @@ bool WebServer::serveFile(String filename, httpsserver::HTTPResponse *res)
|
|||
|
||||
size_t nread = 1;
|
||||
while(nread > 0) {
|
||||
xSemaphoreTake(*instance().m_ledLockoutMutex, portMAX_DELAY);
|
||||
nread = f.readBytes(reinterpret_cast<char*>(buf), 1024);
|
||||
xSemaphoreGive(*instance().m_ledLockoutMutex);
|
||||
|
||||
if(nread <= 0) {
|
||||
break;
|
||||
}
|
||||
|
@ -44,7 +53,9 @@ bool WebServer::serveFile(String filename, httpsserver::HTTPResponse *res)
|
|||
res->write(buf, nread);
|
||||
}
|
||||
|
||||
xSemaphoreTake(*instance().m_ledLockoutMutex, portMAX_DELAY);
|
||||
f.close();
|
||||
xSemaphoreGive(*instance().m_ledLockoutMutex);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
18
src/main.cpp
18
src/main.cpp
|
@ -6,6 +6,9 @@
|
|||
#include <WiFiMulti.h>
|
||||
#include <SPIFFS.h>
|
||||
|
||||
#include <FreeRTOS.h>
|
||||
#include <freertos/semphr.h>
|
||||
|
||||
#include "WebServer.h"
|
||||
#include "Fader.h"
|
||||
#include "UDPProto.h"
|
||||
|
@ -34,6 +37,11 @@ bool led_on = false;
|
|||
size_t led_idx;
|
||||
WiFiMulti wiFiMulti;
|
||||
|
||||
// this mutex is locked while LEDs are written and must be also locked
|
||||
// by any task accessing the flash, as (probably) the interrupts
|
||||
// from the flash cause the LED update to be unreliable.
|
||||
SemaphoreHandle_t ledLockoutMutex;
|
||||
|
||||
Fader ledFader(NUM_STRIPS, NUM_LEDS, 1, FLIP_STRIPS_MASK);
|
||||
UDPProto udpProto(&ledFader);
|
||||
UpdateServer *updateServer;
|
||||
|
@ -207,9 +215,11 @@ static void ledTask( void * parameter )
|
|||
const Fader::Color &c = colors[i];
|
||||
STRANDS[0].pixels[i] = pixelFromRGBW(c.r, c.g, c.b, c.w);
|
||||
}
|
||||
}
|
||||
|
||||
xSemaphoreTake(ledLockoutMutex, portMAX_DELAY);
|
||||
digitalLeds_drawPixels(strands, 1);
|
||||
xSemaphoreGive(ledLockoutMutex);
|
||||
}
|
||||
|
||||
frame++;
|
||||
|
||||
|
@ -278,6 +288,9 @@ void setup()
|
|||
Serial.begin(115200);
|
||||
delay(10);
|
||||
|
||||
// initalize the semaphores before anything else
|
||||
ledLockoutMutex = xSemaphoreCreateMutex();
|
||||
|
||||
if(!initLEDs()) {
|
||||
Serial.println("LED setup failed!");
|
||||
while(true) {
|
||||
|
@ -326,11 +339,12 @@ void setup()
|
|||
|
||||
// start the web server
|
||||
WebServer::instance().setFader(&ledFader);
|
||||
WebServer::instance().setLedLockoutMutex(&ledLockoutMutex);
|
||||
WebServer::instance().setAnimationController(&animController);
|
||||
WebServer::instance().start();
|
||||
|
||||
// start the update server
|
||||
updateServer = new UpdateServer(Config::instance().getCRPassword());
|
||||
updateServer = new UpdateServer(Config::instance().getCRPassword(), &ledLockoutMutex);
|
||||
updateServer->start();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue