From 2e1227fab2971286bf2b2bf59b36ebde253f4bc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Milants?= Date: Sun, 23 Oct 2022 19:01:32 +0200 Subject: [PATCH] This commit improves the hardware abstraction by integrating the Concepts features of C++20 for Spi, SpiMaster and SpiNorFlash. The 'interface' of the drivers are defined in `Pinetime::Drivers::Interface::Spi`, `Pinetime::Drivers::Interface::SpiMaster` and `Pinetime::Drivers::Interface::SpiNorFlash`. The actual implementation will be injected via the template parameter `T`. T is required to conform to the corresponding concepts `IsSpi`, `IsSpiMaster` and `IsFlashMemory`. This implementation should be practically free in terms of memory and cpu resource usage, but it provides way to implement multiple variations of the same driver. It also describes very clearly the interface of the drivers thanks to the concepts. This will allow us to support more easily other hardwares : different SoC, different sensors and memory chips. It'll also make the implemenation of InfiniSim much easier. --- CMakeLists.txt | 2 +- src/CMakeLists.txt | 23 +-- src/components/ble/DfuService.h | 6 +- src/components/ble/NimbleController.h | 4 - src/components/fs/FS.h | 1 + src/drivers/Spi.h | 66 ++++++--- src/drivers/SpiMaster.h | 101 ++++++------- src/drivers/SpiNorFlash.h | 158 ++++++++++++++------- src/drivers/St7789.h | 4 +- src/drivers/{ => nrf52}/Spi.cpp | 4 +- src/drivers/nrf52/Spi.h | 30 ++++ src/drivers/{ => nrf52}/SpiMaster.cpp | 4 +- src/drivers/nrf52/SpiMaster.h | 67 +++++++++ src/drivers/{ => spiFlash}/SpiNorFlash.cpp | 12 +- src/drivers/spiFlash/SpiNorFlash.h | 62 ++++++++ src/main.cpp | 27 ++-- src/port/infinitime.h | 24 ++++ src/systemtask/SystemTask.h | 4 +- 18 files changed, 440 insertions(+), 159 deletions(-) rename src/drivers/{ => nrf52}/Spi.cpp (94%) create mode 100644 src/drivers/nrf52/Spi.h rename src/drivers/{ => nrf52}/SpiMaster.cpp (99%) create mode 100644 src/drivers/nrf52/SpiMaster.h rename src/drivers/{ => spiFlash}/SpiNorFlash.cpp (93%) create mode 100644 src/drivers/spiFlash/SpiNorFlash.h create mode 100644 src/port/infinitime.h diff --git a/CMakeLists.txt b/CMakeLists.txt index adb1754b..a215180d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e59c0d81..c3848a62 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -687,6 +687,7 @@ include_directories( . ../ libs/ + port/ FreeRTOS/ libs/date/include libs/mynewt-nimble/porting/npl/freertos/include diff --git a/src/components/ble/DfuService.h b/src/components/ble/DfuService.h index 4708a4a6..93d5ccf7 100644 --- a/src/components/ble/DfuService.h +++ b/src/components/ble/DfuService.h @@ -9,13 +9,13 @@ #undef max #undef min +#include +#include "infinitime.h" + namespace Pinetime { namespace System { class SystemTask; } - namespace Drivers { - class SpiNorFlash; - } namespace Controllers { class Ble; diff --git a/src/components/ble/NimbleController.h b/src/components/ble/NimbleController.h index 000231fe..e323461a 100644 --- a/src/components/ble/NimbleController.h +++ b/src/components/ble/NimbleController.h @@ -25,10 +25,6 @@ #include "components/fs/FS.h" namespace Pinetime { - namespace Drivers { - class SpiNorFlash; - } - namespace System { class SystemTask; } diff --git a/src/components/fs/FS.h b/src/components/fs/FS.h index 87fcdc23..31e59986 100644 --- a/src/components/fs/FS.h +++ b/src/components/fs/FS.h @@ -2,6 +2,7 @@ #include #include "drivers/SpiNorFlash.h" +#include "port/infinitime.h" #include namespace Pinetime { diff --git a/src/drivers/Spi.h b/src/drivers/Spi.h index 9b6a30f4..77b37a7a 100644 --- a/src/drivers/Spi.h +++ b/src/drivers/Spi.h @@ -1,28 +1,56 @@ #pragma once #include #include -#include "drivers/SpiMaster.h" +#include +#include 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; + template + 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; + { s.Read(command, size, data, size) } -> std::same_as; + }; - 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(); + namespace Interface { + template + requires IsSpi + class Spi { + public: + Spi(T& spi) : impl {spi} { + } + Spi(const Spi&) = delete; + Spi& operator=(const Spi&) = delete; + Spi(Spi&&) = delete; + Spi& operator=(Spi&&) = delete; - private: - SpiMaster& spiMaster; - uint8_t pinCsn; - }; + 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; + }; + } } -} +} \ No newline at end of file diff --git a/src/drivers/SpiMaster.h b/src/drivers/SpiMaster.h index 5ea624f2..45b57d1f 100644 --- a/src/drivers/SpiMaster.h +++ b/src/drivers/SpiMaster.h @@ -1,65 +1,70 @@ #pragma once #include #include - -#include -#include -#include +#include 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 + concept IsSpiMaster = + 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; + { spi.Write(pin, constData, size) } -> std::same_as; + { spi.Read(pin, command, size, data, size) } -> std::same_as; + { spi.WriteCmdAndBuffer(pin, constCommand, size, constData, size) } -> std::same_as; + { 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 + requires IsSpiMaster + 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(); - 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 Init() { + return impl.Init(); + } - bool WriteCmdAndBuffer(uint8_t pinCsn, const uint8_t* cmd, size_t cmdSize, const uint8_t* data, size_t dataSize); + bool Write(uint8_t pinCsn, const uint8_t* data, size_t size) { + return impl.Write(pinCsn, data, size); + } - void OnStartedEvent(); - void OnEndEvent(); + 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 Sleep(); - void Wakeup(); + 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); + } - 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 OnStartedEvent() { + impl.OnStartedEvent(); + } - NRF_SPIM_Type* spiBaseAddress; - uint8_t pinCsn; + void OnEndEvent() { + impl.OnEndEvent(); + } - SpiMaster::SpiModule spi; - SpiMaster::Parameters params; + void Sleep() { + impl.Sleep(); + } - volatile uint32_t currentBufferAddr = 0; - volatile size_t currentBufferSize = 0; - volatile TaskHandle_t taskToNotify; - SemaphoreHandle_t mutex = nullptr; - }; + void Wakeup() { + impl.Wakeup(); + } + + private: + T& impl; + }; + } } -} +} \ No newline at end of file diff --git a/src/drivers/SpiNorFlash.h b/src/drivers/SpiNorFlash.h index ad4d0907..ecea0a35 100644 --- a/src/drivers/SpiNorFlash.h +++ b/src/drivers/SpiNorFlash.h @@ -1,60 +1,116 @@ #pragma once + #include #include +#include namespace Pinetime { namespace Drivers { - class Spi; - class SpiNorFlash { - public: - explicit SpiNorFlash(Spi& spi); - SpiNorFlash(const SpiNorFlash&) = delete; - SpiNorFlash& operator=(const SpiNorFlash&) = delete; - SpiNorFlash(SpiNorFlash&&) = delete; - SpiNorFlash& operator=(SpiNorFlash&&) = delete; + template + concept IsFlashMemory = requires(T memory, uint32_t address, uint8_t* buffer, const uint8_t* constBuffer, size_t size) { + { memory.ReadIdentification() }; + { memory.ReadStatusRegister() } -> std::same_as; + { memory.ReadConfigurationRegister() } -> std::same_as; + { memory.WriteInProgress() } -> std::same_as; + { memory.WriteEnabled() } -> std::same_as; + { memory.Read(address, buffer, size) }; + { memory.Write(address, constBuffer, size) }; + { memory.WriteEnable() }; + { memory.SectorErase(address) }; + { memory.ReadSecurityRegister() } -> std::same_as; + { memory.ProgramFailed() } -> std::same_as; + { memory.EraseFailed() } -> std::same_as; + { memory.Init() }; + { memory.Uninit() }; + { memory.Sleep() }; + { memory.Wakeup() }; + }; - struct __attribute__((packed)) Identification { - uint8_t manufacturer = 0; - uint8_t type = 0; - uint8_t density = 0; + namespace Interface { + template + requires IsFlashMemory + class SpiNorFlash { + public: + explicit SpiNorFlash(T& spi) : impl {spi} { + } + SpiNorFlash(const SpiNorFlash&) = delete; + SpiNorFlash& operator=(const SpiNorFlash&) = delete; + SpiNorFlash(SpiNorFlash&&) = delete; + SpiNorFlash& operator=(SpiNorFlash&&) = delete; + + struct __attribute__((packed)) Identification { + uint8_t manufacturer = 0; + uint8_t type = 0; + uint8_t density = 0; + }; + + Identification ReadIdentificaion() { + return impl.ReadIdentificaion(); + } + + uint8_t ReadStatusRegister() { + return impl.ReadStatusRegister(); + } + + bool WriteInProgress() { + return impl.WriteInProgress(); + } + + bool WriteEnabled() { + return impl.WriteEnabled(); + } + + uint8_t ReadConfigurationRegister() { + return impl.ReadConfigurationRegister(); + } + + void Read(uint32_t address, uint8_t* buffer, size_t size) { + impl.Read(address, buffer, size); + } + + void Write(uint32_t address, const uint8_t* buffer, size_t size) { + impl.Write(address, buffer, size); + } + + void WriteEnable() { + return impl.WriteEnable(); + } + + void SectorErase(uint32_t sectorAddress) { + impl.SectorErase(sectorAddress); + } + + uint8_t ReadSecurityRegister() { + return impl.ReadSecurityRegister(); + } + + bool ProgramFailed() { + return impl.ProgramFailed(); + } + + bool EraseFailed() { + return impl.EraseFailed(); + } + + void Init() { + impl.Init(); + } + + void Uninit() { + impl.Uninit(); + } + + void Sleep() { + impl.Sleep(); + } + + void Wakeup() { + impl.Wakeup(); + } + + private: + T& impl; }; - - Identification ReadIdentificaion(); - uint8_t ReadStatusRegister(); - bool WriteInProgress(); - bool WriteEnabled(); - uint8_t ReadConfigurationRegister(); - void Read(uint32_t address, uint8_t* buffer, size_t size); - void Write(uint32_t address, const uint8_t* buffer, size_t size); - void WriteEnable(); - void SectorErase(uint32_t sectorAddress); - uint8_t ReadSecurityRegister(); - bool ProgramFailed(); - bool EraseFailed(); - - void Init(); - void Uninit(); - - void Sleep(); - void Wakeup(); - - private: - enum class Commands : uint8_t { - PageProgram = 0x02, - Read = 0x03, - ReadStatusRegister = 0x05, - WriteEnable = 0x06, - ReadConfigurationRegister = 0x15, - SectorErase = 0x20, - ReadSecurityRegister = 0x2B, - ReadIdentification = 0x9F, - ReleaseFromDeepPowerDown = 0xAB, - DeepPowerDown = 0xB9 - }; - static constexpr uint16_t pageSize = 256; - - Spi& spi; - Identification device_id; - }; + } } -} +} \ No newline at end of file diff --git a/src/drivers/St7789.h b/src/drivers/St7789.h index 8c2ac093..026f4fab 100644 --- a/src/drivers/St7789.h +++ b/src/drivers/St7789.h @@ -1,10 +1,12 @@ #pragma once +#include "Spi.h" #include #include +#include "port/infinitime.h" namespace Pinetime { namespace Drivers { - class Spi; + class St7789 { public: explicit St7789(Spi& spi, uint8_t pinDataCommand); diff --git a/src/drivers/Spi.cpp b/src/drivers/nrf52/Spi.cpp similarity index 94% rename from src/drivers/Spi.cpp rename to src/drivers/nrf52/Spi.cpp index e477622b..437fce9f 100644 --- a/src/drivers/Spi.cpp +++ b/src/drivers/nrf52/Spi.cpp @@ -1,8 +1,8 @@ -#include "drivers/Spi.h" +#include "Spi.h" #include #include -using namespace Pinetime::Drivers; +using namespace Pinetime::Drivers::Nrf52; Spi::Spi(SpiMaster& spiMaster, uint8_t pinCsn) : spiMaster {spiMaster}, pinCsn {pinCsn} { nrf_gpio_cfg_output(pinCsn); diff --git a/src/drivers/nrf52/Spi.h b/src/drivers/nrf52/Spi.h new file mode 100644 index 00000000..8072c77a --- /dev/null +++ b/src/drivers/nrf52/Spi.h @@ -0,0 +1,30 @@ +#pragma once +#include +#include +#include "drivers/nrf52/SpiMaster.h" + +namespace Pinetime { + namespace Drivers { + namespace Nrf52 { + class Spi { + public: + Spi(Pinetime::Drivers::Nrf52::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: + Pinetime::Drivers::Nrf52::SpiMaster& spiMaster; + uint8_t pinCsn; + }; + } + } +} \ No newline at end of file diff --git a/src/drivers/SpiMaster.cpp b/src/drivers/nrf52/SpiMaster.cpp similarity index 99% rename from src/drivers/SpiMaster.cpp rename to src/drivers/nrf52/SpiMaster.cpp index 38f72fee..2f4da4b9 100644 --- a/src/drivers/SpiMaster.cpp +++ b/src/drivers/nrf52/SpiMaster.cpp @@ -1,10 +1,10 @@ -#include "drivers/SpiMaster.h" +#include "SpiMaster.h" #include #include #include #include -using namespace Pinetime::Drivers; +using namespace Pinetime::Drivers::Nrf52; SpiMaster::SpiMaster(const SpiMaster::SpiModule spi, const SpiMaster::Parameters& params) : spi {spi}, params {params} { } diff --git a/src/drivers/nrf52/SpiMaster.h b/src/drivers/nrf52/SpiMaster.h new file mode 100644 index 00000000..9d88b2bb --- /dev/null +++ b/src/drivers/nrf52/SpiMaster.h @@ -0,0 +1,67 @@ +#pragma once +#include +#include + +#include +#include +#include + +namespace Pinetime { + namespace Drivers { + namespace Nrf52 { + 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; + }; + + SpiMaster(const SpiModule spi, const Parameters& params); + SpiMaster(const SpiMaster&) = delete; + SpiMaster& operator=(const SpiMaster&) = delete; + SpiMaster(SpiMaster&&) = delete; + SpiMaster& operator=(SpiMaster&&) = delete; + + 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 WriteCmdAndBuffer(uint8_t pinCsn, const uint8_t* cmd, size_t cmdSize, const uint8_t* data, size_t dataSize); + + void OnStartedEvent(); + void OnEndEvent(); + + void Sleep(); + void Wakeup(); + + 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); + + NRF_SPIM_Type* spiBaseAddress; + uint8_t pinCsn; + + SpiMaster::SpiModule spi; + SpiMaster::Parameters params; + + volatile uint32_t currentBufferAddr = 0; + volatile size_t currentBufferSize = 0; + volatile TaskHandle_t taskToNotify; + SemaphoreHandle_t mutex = nullptr; + }; + } + } +} \ No newline at end of file diff --git a/src/drivers/SpiNorFlash.cpp b/src/drivers/spiFlash/SpiNorFlash.cpp similarity index 93% rename from src/drivers/SpiNorFlash.cpp rename to src/drivers/spiFlash/SpiNorFlash.cpp index 28f82fe6..51944dbc 100644 --- a/src/drivers/SpiNorFlash.cpp +++ b/src/drivers/spiFlash/SpiNorFlash.cpp @@ -1,16 +1,16 @@ -#include "drivers/SpiNorFlash.h" +#include "drivers/spiFlash/SpiNorFlash.h" #include #include #include #include "drivers/Spi.h" -using namespace Pinetime::Drivers; +using namespace Pinetime::Drivers::SpiFlash; -SpiNorFlash::SpiNorFlash(Spi& spi) : spi {spi} { +SpiNorFlash::SpiNorFlash(Pinetime::Drivers::Nrf52::Spi& spi) : spi {spi} { } void SpiNorFlash::Init() { - device_id = ReadIdentificaion(); + device_id = ReadIdentification(); NRF_LOG_INFO("[SpiNorFlash] Manufacturer : %d, Memory type : %d, memory density : %d", device_id.manufacturer, device_id.type, @@ -32,7 +32,7 @@ void SpiNorFlash::Wakeup() { uint8_t cmd[cmdSize] = {static_cast(Commands::ReleaseFromDeepPowerDown), 0x01, 0x02, 0x03}; uint8_t id = 0; spi.Read(reinterpret_cast(&cmd), cmdSize, &id, 1); - auto devId = device_id = ReadIdentificaion(); + auto devId = device_id = ReadIdentification(); if (devId.type != device_id.type) { NRF_LOG_INFO("[SpiNorFlash] ID on Wakeup: Failed"); } else { @@ -41,7 +41,7 @@ void SpiNorFlash::Wakeup() { NRF_LOG_INFO("[SpiNorFlash] Wakeup") } -SpiNorFlash::Identification SpiNorFlash::ReadIdentificaion() { +SpiNorFlash::Identification SpiNorFlash::ReadIdentification() { auto cmd = static_cast(Commands::ReadIdentification); Identification identification; spi.Read(&cmd, 1, reinterpret_cast(&identification), sizeof(Identification)); diff --git a/src/drivers/spiFlash/SpiNorFlash.h b/src/drivers/spiFlash/SpiNorFlash.h new file mode 100644 index 00000000..7beadd71 --- /dev/null +++ b/src/drivers/spiFlash/SpiNorFlash.h @@ -0,0 +1,62 @@ +#pragma once +#include "drivers/nrf52/Spi.h" +#include +#include + +namespace Pinetime { + namespace Drivers { + namespace SpiFlash { + class SpiNorFlash { + public: + explicit SpiNorFlash(Pinetime::Drivers::Nrf52::Spi& spi); + SpiNorFlash(const SpiNorFlash&) = delete; + SpiNorFlash& operator=(const SpiNorFlash&) = delete; + SpiNorFlash(SpiNorFlash&&) = delete; + SpiNorFlash& operator=(SpiNorFlash&&) = delete; + + struct __attribute__((packed)) Identification { + uint8_t manufacturer = 0; + uint8_t type = 0; + uint8_t density = 0; + }; + + Identification ReadIdentification(); + uint8_t ReadStatusRegister(); + bool WriteInProgress(); + bool WriteEnabled(); + uint8_t ReadConfigurationRegister(); + void Read(uint32_t address, uint8_t* buffer, size_t size); + void Write(uint32_t address, const uint8_t* buffer, size_t size); + void WriteEnable(); + void SectorErase(uint32_t sectorAddress); + uint8_t ReadSecurityRegister(); + bool ProgramFailed(); + bool EraseFailed(); + + void Init(); + void Uninit(); + + void Sleep(); + void Wakeup(); + + private: + enum class Commands : uint8_t { + PageProgram = 0x02, + Read = 0x03, + ReadStatusRegister = 0x05, + WriteEnable = 0x06, + ReadConfigurationRegister = 0x15, + SectorErase = 0x20, + ReadSecurityRegister = 0x2B, + ReadIdentification = 0x9F, + ReleaseFromDeepPowerDown = 0xAB, + DeepPowerDown = 0xB9 + }; + static constexpr uint16_t pageSize = 256; + + Pinetime::Drivers::Nrf52::Spi& spi; + Identification device_id; + }; + } + } +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index ad7a07dc..12a3f593 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include "BootloaderVersion.h" #include "components/battery/BatteryController.h" @@ -37,8 +38,8 @@ #include "components/datetime/DateTimeController.h" #include "components/heartrate/HeartRateController.h" #include "components/fs/FS.h" -#include "drivers/Spi.h" -#include "drivers/SpiMaster.h" +#include "drivers/nrf52/Spi.h" +#include "drivers/nrf52/SpiMaster.h" #include "drivers/SpiNorFlash.h" #include "drivers/St7789.h" #include "drivers/TwiMaster.h" @@ -57,23 +58,31 @@ Pinetime::Logging::NrfLogger logger; Pinetime::Logging::DummyLogger logger; #endif +#include "port/infinitime.h" + static constexpr uint8_t touchPanelTwiAddress = 0x15; static constexpr uint8_t motionSensorTwiAddress = 0x18; static constexpr uint8_t heartRateSensorTwiAddress = 0x44; -Pinetime::Drivers::SpiMaster spi {Pinetime::Drivers::SpiMaster::SpiModule::SPI0, - {Pinetime::Drivers::SpiMaster::BitOrder::Msb_Lsb, - Pinetime::Drivers::SpiMaster::Modes::Mode3, - Pinetime::Drivers::SpiMaster::Frequencies::Freq8Mhz, +Pinetime::Drivers::Nrf52::SpiMaster spiImpl {Pinetime::Drivers::Nrf52::SpiMaster::SpiModule::SPI0, + {Pinetime::Drivers::Nrf52::SpiMaster::BitOrder::Msb_Lsb, + Pinetime::Drivers::Nrf52::SpiMaster::Modes::Mode3, + Pinetime::Drivers::Nrf52::SpiMaster::Frequencies::Freq8Mhz, Pinetime::PinMap::SpiSck, Pinetime::PinMap::SpiMosi, Pinetime::PinMap::SpiMiso}}; -Pinetime::Drivers::Spi lcdSpi {spi, Pinetime::PinMap::SpiLcdCsn}; +Pinetime::Drivers::SpiMaster spi {spiImpl}; + +Pinetime::Drivers::Nrf52::Spi lcdSpiIpmpl {spiImpl, Pinetime::PinMap::SpiLcdCsn}; +Pinetime::Drivers::Spi lcdSpi {lcdSpiIpmpl}; Pinetime::Drivers::St7789 lcd {lcdSpi, Pinetime::PinMap::LcdDataCommand}; -Pinetime::Drivers::Spi flashSpi {spi, Pinetime::PinMap::SpiFlashCsn}; -Pinetime::Drivers::SpiNorFlash spiNorFlash {flashSpi}; +Pinetime::Drivers::Nrf52::Spi flashSpiImpl {spiImpl, Pinetime::PinMap::SpiFlashCsn}; +Pinetime::Drivers::Spi flashSpi {flashSpiImpl}; + +Pinetime::Drivers::SpiFlash::SpiNorFlash spiNorFlashImpl{flashSpiImpl}; +Pinetime::Drivers::SpiNorFlash spiNorFlash {spiNorFlashImpl}; // The TWI device should work @ up to 400Khz but there is a HW bug which prevent it from // respecting correct timings. According to erratas heet, this magic value makes it run diff --git a/src/port/infinitime.h b/src/port/infinitime.h new file mode 100644 index 00000000..a0297e96 --- /dev/null +++ b/src/port/infinitime.h @@ -0,0 +1,24 @@ +#pragma once +#include "drivers/Spi.h" +#include "drivers/SpiMaster.h" +#include +#include + +#ifdef TARGET_DEVICE_PINETIME +#include +#include +#include +#endif + +// #error "Do not include this" +namespace Pinetime { + namespace Drivers { +#ifdef TARGET_DEVICE_PINETIME + using SpiMaster = Interface::SpiMaster; + using Spi = Interface::Spi; + using SpiNorFlash = Interface::SpiNorFlash; +#else + #error "No target device specified!" +#endif + } +} \ No newline at end of file diff --git a/src/systemtask/SystemTask.h b/src/systemtask/SystemTask.h index d1e4a004..9eb7f78a 100644 --- a/src/systemtask/SystemTask.h +++ b/src/systemtask/SystemTask.h @@ -11,6 +11,7 @@ #include #include #include +#include #include "systemtask/SystemMonitor.h" #include "components/ble/NimbleController.h" @@ -34,13 +35,12 @@ #include "drivers/Watchdog.h" #include "systemtask/Messages.h" +#include "port/infinitime.h" extern std::chrono::time_point NoInit_BackUpTime; namespace Pinetime { namespace Drivers { class Cst816S; - class SpiMaster; - class SpiNorFlash; class St7789; class TwiMaster; class Hrs3300;