Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose Debug or Release")
project(pinetime VERSION 1.11.0 LANGUAGES C CXX ASM)

set(CMAKE_C_STANDARD 99)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD 20)

# set(CMAKE_GENERATOR "Unix Makefiles")
set(CMAKE_C_EXTENSIONS OFF)
Expand Down
23 changes: 12 additions & 11 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -436,9 +436,9 @@ list(APPEND SOURCE_FILES

main.cpp
drivers/St7789.cpp
drivers/SpiNorFlash.cpp
drivers/SpiMaster.cpp
drivers/Spi.cpp
drivers/nrf52/SpiMaster.cpp
drivers/nrf52/Spi.cpp
drivers/spiFlash/SpiNorFlash.cpp
drivers/Watchdog.cpp
drivers/DebugPins.cpp
drivers/InternalFlash.cpp
Expand Down Expand Up @@ -503,9 +503,8 @@ list(APPEND RECOVERY_SOURCE_FILES

main.cpp
drivers/St7789.cpp
drivers/SpiNorFlash.cpp
drivers/SpiMaster.cpp
drivers/Spi.cpp
drivers/nrf52/SpiMaster.cpp
drivers/nrf52/Spi.cpp
drivers/Watchdog.cpp
drivers/DebugPins.cpp
drivers/InternalFlash.cpp
Expand Down Expand Up @@ -566,9 +565,8 @@ list(APPEND RECOVERYLOADER_SOURCE_FILES
FreeRTOS/port_cmsis_systick.c
FreeRTOS/port_cmsis.c

drivers/SpiNorFlash.cpp
drivers/SpiMaster.cpp
drivers/Spi.cpp
drivers/nrf52/SpiMaster.cpp
drivers/nrf52/Spi.cpp
logging/NrfLogger.cpp

components/rle/RleDecoder.cpp
Expand All @@ -587,6 +585,7 @@ set(INCLUDE_FILES
BootloaderVersion.h
logging/Logger.h
logging/NrfLogger.h
port/infinitime.h
displayapp/DisplayApp.h
displayapp/Messages.h
displayapp/TouchEvents.h
Expand Down Expand Up @@ -619,8 +618,9 @@ set(INCLUDE_FILES
displayapp/widgets/StatusIcons.h
drivers/St7789.h
drivers/SpiNorFlash.h
drivers/SpiMaster.h
drivers/Spi.h
drivers/nrf52/SpiMaster.h
drivers/nrf52/Spi.h
drivers/spiFlash/SpiNorFlash.h
drivers/Watchdog.h
drivers/DebugPins.h
drivers/InternalFlash.h
Expand Down Expand Up @@ -687,6 +687,7 @@ include_directories(
.
../
libs/
port/
FreeRTOS/
libs/date/include
libs/mynewt-nimble/porting/npl/freertos/include
Expand Down
6 changes: 3 additions & 3 deletions src/components/ble/DfuService.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
#undef max
#undef min

#include <drivers/SpiNorFlash.h>
#include "infinitime.h"

namespace Pinetime {
namespace System {
class SystemTask;
}
namespace Drivers {
class SpiNorFlash;
}
namespace Controllers {
class Ble;

Expand Down
4 changes: 0 additions & 4 deletions src/components/ble/NimbleController.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@
#include "components/fs/FS.h"

namespace Pinetime {
namespace Drivers {
class SpiNorFlash;
}

namespace System {
class SystemTask;
}
Expand Down
1 change: 1 addition & 0 deletions src/components/fs/FS.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <cstdint>
#include "drivers/SpiNorFlash.h"
#include "port/infinitime.h"
#include <littlefs/lfs.h>

namespace Pinetime {
Expand Down
70 changes: 49 additions & 21 deletions src/drivers/Spi.h
Original file line number Diff line number Diff line change
@@ -1,28 +1,56 @@
#pragma once
#include <cstdint>
#include <cstddef>
#include "drivers/SpiMaster.h"
#include <utility>
#include <concepts>

namespace Pinetime {
namespace Drivers {
class Spi {
public:
Spi(SpiMaster& spiMaster, uint8_t pinCsn);
Spi(const Spi&) = delete;
Spi& operator=(const Spi&) = delete;
Spi(Spi&&) = delete;
Spi& operator=(Spi&&) = delete;

bool Init();
bool Write(const uint8_t* data, size_t size);
bool Read(uint8_t* cmd, size_t cmdSize, uint8_t* data, size_t dataSize);
bool WriteCmdAndBuffer(const uint8_t* cmd, size_t cmdSize, const uint8_t* data, size_t dataSize);
void Sleep();
void Wakeup();

private:
SpiMaster& spiMaster;
uint8_t pinCsn;
};
template <typename T>
concept IsSpi = requires(T s, const uint8_t* constData, uint8_t* data, const uint8_t* constCommand, uint8_t* command, size_t size) {
{ s.Write(constData, size) } -> std::same_as<bool>;
{ s.Read(command, size, data, size) } -> std::same_as<bool>;
};

namespace Interface {
template <class T>
requires IsSpi<T>
class Spi {
public:
Spi(T& spi) : impl {spi} {
}
Spi(const Spi&) = delete;
Spi& operator=(const Spi&) = delete;
Spi(Spi&&) = delete;
Spi& operator=(Spi&&) = delete;

bool Init() {
return impl.Init();
}

bool Write(const uint8_t* data, size_t size) {
return impl.Write(data, size);
}

bool Read(uint8_t* cmd, size_t cmdSize, uint8_t* data, size_t dataSize) {
return impl.Read(cmd, cmdSize, data, dataSize);
}

bool WriteCmdAndBuffer(const uint8_t* cmd, size_t cmdSize, const uint8_t* data, size_t dataSize) {
return impl.WriteCmdAndBuffer(cmd, cmdSize, data, dataSize);
}

void Sleep() {
impl.Sleep();
}

void Wakeup() {
impl.Wakeup();
}

private:
T& impl;
};
}
}
}
}
101 changes: 53 additions & 48 deletions src/drivers/SpiMaster.h
Original file line number Diff line number Diff line change
@@ -1,65 +1,70 @@
#pragma once
#include <cstddef>
#include <cstdint>

#include <FreeRTOS.h>
#include <semphr.h>
#include <task.h>
#include <algorithm>

namespace Pinetime {
namespace Drivers {
class SpiMaster {
public:
enum class SpiModule : uint8_t { SPI0, SPI1 };
enum class BitOrder : uint8_t { Msb_Lsb, Lsb_Msb };
enum class Modes : uint8_t { Mode0, Mode1, Mode2, Mode3 };
enum class Frequencies : uint8_t { Freq8Mhz };
struct Parameters {
BitOrder bitOrder;
Modes mode;
Frequencies Frequency;
uint8_t pinSCK;
uint8_t pinMOSI;
uint8_t pinMISO;
template <typename T>
concept IsSpiMaster =

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(outsider suggestion) (ditto for other places) Concepts should be named like adjectives rather than predicates, i.e. SpiMaster rather than IsSpiMaster. This convention is established in the standard (same_as, derived_from, destructible, regular, ...) and is in line with how other languages treat traits and trait-like features

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with this. However... this rule is not easy to apply here :

  • in drivers/SpiMaster.h, there's Pinetime::Drivers::IsSpiMaster, the concept definition
  • in drivers/SpiMaster.h, there's also Pinetime::Drivers::Interface::SpiMaster, the actual driver, that owns an impl of type IsSpiMaster.
  • in port/infinitime.h, we declare PineTime::Drivers::SpiMaster, the type that will be used in the rest of the code.

Renaming the concept from IsSpiMaster to SpiMaster will conflict with SpiMaster in InfiniTime.h. I'm open to suggestions regarding the naming of the types and namespaces, though!

requires(T spi, uint8_t pin, const uint8_t* constData, uint8_t* data, const uint8_t* constCommand, uint8_t* command, size_t size) {
{ spi.Init() } -> std::same_as<bool>;
{ spi.Write(pin, constData, size) } -> std::same_as<bool>;
{ spi.Read(pin, command, size, data, size) } -> std::same_as<bool>;
{ spi.WriteCmdAndBuffer(pin, constCommand, size, constData, size) } -> std::same_as<bool>;
{ spi.OnStartedEvent() };
{ spi.OnEndEvent() };
{ spi.Sleep() };
{ spi.Wakeup() };
};

SpiMaster(const SpiModule spi, const Parameters& params);
SpiMaster(const SpiMaster&) = delete;
SpiMaster& operator=(const SpiMaster&) = delete;
SpiMaster(SpiMaster&&) = delete;
SpiMaster& operator=(SpiMaster&&) = delete;
namespace Interface {
template <class T>
requires IsSpiMaster<T>
class SpiMaster {
public:
SpiMaster(T& spiMaster) : impl {spiMaster} {
}
SpiMaster(const SpiMaster&) = delete;
SpiMaster& operator=(const SpiMaster&) = delete;
SpiMaster(SpiMaster&&) = delete;
SpiMaster& operator=(SpiMaster&&) = delete;

bool Init() {
return impl.Init();
}

bool Init();
bool Write(uint8_t pinCsn, const uint8_t* data, size_t size);
bool Read(uint8_t pinCsn, uint8_t* cmd, size_t cmdSize, uint8_t* data, size_t dataSize);
bool Write(uint8_t pinCsn, const uint8_t* data, size_t size) {
return impl.Write(pinCsn, data, size);
}

bool WriteCmdAndBuffer(uint8_t pinCsn, const uint8_t* cmd, size_t cmdSize, const uint8_t* data, size_t dataSize);
bool Read(uint8_t pinCsn, uint8_t* cmd, size_t cmdSize, uint8_t* data, size_t dataSize) {
return impl.Read(pinCsn, cmd, cmdSize, data, dataSize);
}

void OnStartedEvent();
void OnEndEvent();
bool WriteCmdAndBuffer(uint8_t pinCsn, const uint8_t* cmd, size_t cmdSize, const uint8_t* data, size_t dataSize) {
return impl.WriteCmdAndBuffer(pinCsn, cmd, cmdSize, data, dataSize);
}

void Sleep();
void Wakeup();
void OnStartedEvent() {
impl.OnStartedEvent();
}

private:
void SetupWorkaroundForFtpan58(NRF_SPIM_Type* spim, uint32_t ppi_channel, uint32_t gpiote_channel);
void DisableWorkaroundForFtpan58(NRF_SPIM_Type* spim, uint32_t ppi_channel, uint32_t gpiote_channel);
void PrepareTx(const volatile uint32_t bufferAddress, const volatile size_t size);
void PrepareRx(const volatile uint32_t cmdAddress,
const volatile size_t cmdSize,
const volatile uint32_t bufferAddress,
const volatile size_t size);
void OnEndEvent() {
impl.OnEndEvent();
}

NRF_SPIM_Type* spiBaseAddress;
uint8_t pinCsn;
void Sleep() {
impl.Sleep();
}

SpiMaster::SpiModule spi;
SpiMaster::Parameters params;
void Wakeup() {
impl.Wakeup();
}

volatile uint32_t currentBufferAddr = 0;
volatile size_t currentBufferSize = 0;
volatile TaskHandle_t taskToNotify;
SemaphoreHandle_t mutex = nullptr;
};
private:
T& impl;
};
}
}
}
}
Loading