Lock SPI bus while in use by InkHUD (#6719)

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
This commit is contained in:
todd-herbert
2025-05-02 23:20:56 +12:00
committed by GitHub
parent 7da8aea1df
commit 10693c4569
4 changed files with 56 additions and 6 deletions

View File

@@ -1,9 +1,11 @@
#include "./LCMEN2R13EFC1.h"
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
#include "./LCMEN2R13EFC1.h"
#include <assert.h>
#include "SPILock.h"
using namespace NicheGraphics::Drivers;
// Look up table: fast refresh, common electrode
@@ -150,6 +152,9 @@ void LCMEN213EFC1::reset()
void LCMEN213EFC1::sendCommand(const uint8_t command)
{
// Take firmware's SPI lock
spiLock->lock();
spi->beginTransaction(spiSettings);
digitalWrite(pin_dc, LOW); // DC pin low indicates command
digitalWrite(pin_cs, LOW);
@@ -157,6 +162,8 @@ void LCMEN213EFC1::sendCommand(const uint8_t command)
digitalWrite(pin_cs, HIGH);
digitalWrite(pin_dc, HIGH);
spi->endTransaction();
spiLock->unlock();
}
void LCMEN213EFC1::sendData(uint8_t data)
@@ -166,6 +173,9 @@ void LCMEN213EFC1::sendData(uint8_t data)
void LCMEN213EFC1::sendData(const uint8_t *data, uint32_t size)
{
// Take firmware's SPI lock
spiLock->lock();
spi->beginTransaction(spiSettings);
digitalWrite(pin_dc, HIGH); // DC pin HIGH indicates data, instead of command
digitalWrite(pin_cs, LOW);
@@ -183,6 +193,8 @@ void LCMEN213EFC1::sendData(const uint8_t *data, uint32_t size)
digitalWrite(pin_cs, HIGH);
digitalWrite(pin_dc, HIGH);
spi->endTransaction();
spiLock->unlock();
}
void LCMEN213EFC1::configFull()

View File

@@ -1,6 +1,9 @@
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
#include "./SSD16XX.h"
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
#include "SPILock.h"
using namespace NicheGraphics::Drivers;
SSD16XX::SSD16XX(uint16_t width, uint16_t height, UpdateTypes supported, uint8_t bufferOffsetX)
@@ -82,6 +85,9 @@ void SSD16XX::sendCommand(const uint8_t command)
if (failed)
return;
// Take firmware's SPI lock
spiLock->lock();
spi->beginTransaction(spiSettings);
digitalWrite(pin_dc, LOW); // DC pin low indicates command
digitalWrite(pin_cs, LOW);
@@ -89,6 +95,8 @@ void SSD16XX::sendCommand(const uint8_t command)
digitalWrite(pin_cs, HIGH);
digitalWrite(pin_dc, HIGH);
spi->endTransaction();
spiLock->unlock();
}
void SSD16XX::sendData(uint8_t data)
@@ -103,6 +111,9 @@ void SSD16XX::sendData(const uint8_t *data, uint32_t size)
if (failed)
return;
// Take firmware's SPI lock
spiLock->lock();
spi->beginTransaction(spiSettings);
digitalWrite(pin_dc, HIGH); // DC pin HIGH indicates data, instead of command
digitalWrite(pin_cs, LOW);
@@ -119,6 +130,8 @@ void SSD16XX::sendData(const uint8_t *data, uint32_t size)
digitalWrite(pin_cs, HIGH);
digitalWrite(pin_dc, HIGH);
spi->endTransaction();
spiLock->unlock();
}
void SSD16XX::configFullscreen()

View File

@@ -13,6 +13,7 @@ Avoid bloating everyone's protobuf code for our one-off UI implementations
#include "configuration.h"
#include "SPILock.h"
#include "SafeFile.h"
namespace NicheGraphics
@@ -46,6 +47,9 @@ template <typename T> class FlashData
public:
static bool load(T *data, const char *label)
{
// Take firmware's SPI lock
concurrency::LockGuard guard(spiLock);
// Set false if we run into issues
bool okay = true;
@@ -103,14 +107,18 @@ template <typename T> class FlashData
return okay;
}
// Save module's custom data (settings?) to flash. Does use protobufs
// Save module's custom data (settings?) to flash. Doesn't use protobufs
// Takes the firmware's SPI lock, in case the files are stored on SD card
// Need to lock and unlock around specific FS methods, as the SafeFile class takes the lock for itself internally.
static void save(T *data, const char *label)
{
// Get a filename based on the label
std::string filename = getFilename(label);
#ifdef FSCom
spiLock->lock();
FSCom.mkdir("/NicheGraphics");
spiLock->unlock();
auto f = SafeFile(filename.c_str(), true); // "true": full atomic. Write new data to temp file, then rename.
@@ -119,10 +127,10 @@ template <typename T> class FlashData
// Calculate a hash of the data
uint32_t hash = getHash(data);
spiLock->lock();
f.write((uint8_t *)data, sizeof(T)); // Write the actual data
f.write((uint8_t *)&hash, sizeof(hash)); // Append the hash
// f.flush();
spiLock->unlock();
bool writeSucceeded = f.close();
@@ -139,6 +147,9 @@ template <typename T> class FlashData
inline void clearFlashData()
{
// Take firmware's SPI lock, in case the files are stored on SD card
concurrency::LockGuard guard(spiLock);
#ifdef FSCom
File dir = FSCom.open("/NicheGraphics"); // Open the directory
File file = dir.openNextFile(); // Attempt to open the first file in the directory

View File

@@ -22,6 +22,8 @@ InkHUD::MessageStore::MessageStore(std::string label)
}
// Write the contents of the MessageStore::messages object to flash
// Takes the firmware's SPI lock during FS operations. Implemented for consistency, but only relevant when using SD card.
// Need to lock and unlock around specific FS methods, as the SafeFile class takes the lock for itself internally
void InkHUD::MessageStore::saveToFlash()
{
assert(!filename.empty());
@@ -29,7 +31,9 @@ void InkHUD::MessageStore::saveToFlash()
#ifdef FSCom
// Make the directory, if doesn't already exist
// This is the same directory accessed by NicheGraphics::FlashData
spiLock->lock();
FSCom.mkdir("/NicheGraphics");
spiLock->unlock();
// Open or create the file
// No "full atomic": don't save then rename
@@ -37,6 +41,9 @@ void InkHUD::MessageStore::saveToFlash()
LOG_INFO("Saving messages in %s", filename.c_str());
// Take firmware's SPI Lock while writing
spiLock->lock();
// 1st byte: how many messages will be written to store
f.write(messages.size());
@@ -51,6 +58,9 @@ void InkHUD::MessageStore::saveToFlash()
LOG_DEBUG("Wrote message %u, length %u, text \"%s\"", (uint32_t)i, min(MAX_MESSAGE_SIZE, m.text.size()), m.text.c_str());
}
// Release firmware's SPI lock, because SafeFile::close needs it
spiLock->unlock();
bool writeSucceeded = f.close();
if (!writeSucceeded) {
@@ -63,6 +73,7 @@ void InkHUD::MessageStore::saveToFlash()
// Attempt to load the previous contents of the MessageStore:message deque from flash.
// Filename is controlled by the "label" parameter
// Takes the firmware's SPI lock during FS operations. Implemented for consistency, but only relevant when using SD card.
void InkHUD::MessageStore::loadFromFlash()
{
// Hopefully redundant. Initial intention is to only load / save once per boot.
@@ -70,6 +81,9 @@ void InkHUD::MessageStore::loadFromFlash()
#ifdef FSCom
// Take the firmware's SPI Lock, in case filesystem is on SD card
concurrency::LockGuard guard(spiLock);
// Check that the file *does* actually exist
if (!FSCom.exists(filename.c_str())) {
LOG_WARN("'%s' not found. Using default values", filename.c_str());