Add SPI NOR Flash driver, WIP.

This commit is contained in:
JF 2020-05-07 19:53:51 +02:00
parent f96c048deb
commit 0b8e6c3fa2
14 changed files with 212 additions and 30 deletions

View file

@ -308,7 +308,9 @@ list(APPEND SOURCE_FILES
DisplayApp/Screens/FirmwareUpdate.cpp DisplayApp/Screens/FirmwareUpdate.cpp
main.cpp main.cpp
drivers/St7789.cpp drivers/St7789.cpp
drivers/SpiNorFlash.cpp
drivers/SpiMaster.cpp drivers/SpiMaster.cpp
drivers/Spi.cpp
drivers/Watchdog.cpp drivers/Watchdog.cpp
drivers/DebugPins.cpp drivers/DebugPins.cpp
Components/Battery/BatteryController.cpp Components/Battery/BatteryController.cpp
@ -357,7 +359,9 @@ set(INCLUDE_FILES
DisplayApp/Screens/Label.h DisplayApp/Screens/Label.h
DisplayApp/Screens/FirmwareUpdate.h DisplayApp/Screens/FirmwareUpdate.h
drivers/St7789.h drivers/St7789.h
drivers/SpiNorFlash.h
drivers/SpiMaster.h drivers/SpiMaster.h
drivers/Spi.h
drivers/Watchdog.h drivers/Watchdog.h
drivers/DebugPins.h drivers/DebugPins.h
Components/Battery/BatteryController.h Components/Battery/BatteryController.h

View file

@ -122,14 +122,14 @@ void NimbleController::StartAdvertising() {
int res; int res;
res = ble_gap_adv_set_fields(&fields); res = ble_gap_adv_set_fields(&fields);
ASSERT(res == 0); // ASSERT(res == 0); // TODO this one sometimes fails with error 22 (notsync)
res = ble_gap_adv_rsp_set_fields(&rsp_fields); res = ble_gap_adv_rsp_set_fields(&rsp_fields);
ASSERT(res == 0); // ASSERT(res == 0);
res = ble_gap_adv_start(addrType, NULL, 10000, res = ble_gap_adv_start(addrType, NULL, 10000,
&adv_params, GAPEventCallback, this); &adv_params, GAPEventCallback, this);
ASSERT(res == 0); // ASSERT(res == 0);
} }
int OnAllSvrDisco(uint16_t conn_handle, int OnAllSvrDisco(uint16_t conn_handle,

View file

@ -14,12 +14,13 @@
using namespace Pinetime::System; using namespace Pinetime::System;
SystemTask::SystemTask(Drivers::SpiMaster &spi, Drivers::St7789 &lcd, Drivers::Cst816S &touchPanel, SystemTask::SystemTask(Drivers::SpiMaster &spi, Drivers::St7789 &lcd,
Pinetime::Drivers::SpiNorFlash& spiNorFlash, Drivers::Cst816S &touchPanel,
Components::LittleVgl &lvgl, Components::LittleVgl &lvgl,
Controllers::Battery &batteryController, Controllers::Ble &bleController, Controllers::Battery &batteryController, Controllers::Ble &bleController,
Controllers::DateTime &dateTimeController, Controllers::DateTime &dateTimeController,
Pinetime::Controllers::NotificationManager& notificationManager) : Pinetime::Controllers::NotificationManager& notificationManager) :
spi{spi}, lcd{lcd}, touchPanel{touchPanel}, lvgl{lvgl}, batteryController{batteryController}, spi{spi}, lcd{lcd}, spiNorFlash{spiNorFlash}, touchPanel{touchPanel}, lvgl{lvgl}, batteryController{batteryController},
bleController{bleController}, dateTimeController{dateTimeController}, bleController{bleController}, dateTimeController{dateTimeController},
watchdog{}, watchdogView{watchdog}, notificationManager{notificationManager}, watchdog{}, watchdogView{watchdog}, notificationManager{notificationManager},
nimbleController(*this, bleController,dateTimeController, notificationManager) { nimbleController(*this, bleController,dateTimeController, notificationManager) {
@ -50,6 +51,7 @@ void SystemTask::Work() {
spi.Init(); spi.Init();
lcd.Init(); lcd.Init();
spiNorFlash.Init();
touchPanel.Init(); touchPanel.Init();
batteryController.Init(); batteryController.Init();

View file

@ -9,6 +9,7 @@
#include <DisplayApp/DisplayApp.h> #include <DisplayApp/DisplayApp.h>
#include <drivers/Watchdog.h> #include <drivers/Watchdog.h>
#include <Components/Ble/NimbleController.h> #include <Components/Ble/NimbleController.h>
#include <drivers/SpiNorFlash.h>
namespace Pinetime { namespace Pinetime {
namespace System { namespace System {
@ -18,7 +19,8 @@ namespace Pinetime {
BleFirmwareUpdateStarted, BleFirmwareUpdateFinished BleFirmwareUpdateStarted, BleFirmwareUpdateFinished
}; };
SystemTask(Drivers::SpiMaster &spi, Drivers::St7789 &lcd, Drivers::Cst816S &touchPanel, SystemTask(Drivers::SpiMaster &spi, Drivers::St7789 &lcd,
Pinetime::Drivers::SpiNorFlash& spiNorFlash, Drivers::Cst816S &touchPanel,
Components::LittleVgl &lvgl, Components::LittleVgl &lvgl,
Controllers::Battery &batteryController, Controllers::Ble &bleController, Controllers::Battery &batteryController, Controllers::Ble &bleController,
Controllers::DateTime &dateTimeController, Controllers::DateTime &dateTimeController,
@ -35,6 +37,7 @@ namespace Pinetime {
Pinetime::Drivers::SpiMaster& spi; Pinetime::Drivers::SpiMaster& spi;
Pinetime::Drivers::St7789& lcd; Pinetime::Drivers::St7789& lcd;
Pinetime::Drivers::SpiNorFlash& spiNorFlash;
Pinetime::Drivers::Cst816S& touchPanel; Pinetime::Drivers::Cst816S& touchPanel;
Pinetime::Components::LittleVgl& lvgl; Pinetime::Components::LittleVgl& lvgl;
Pinetime::Controllers::Battery& batteryController; Pinetime::Controllers::Battery& batteryController;

29
src/drivers/Spi.cpp Normal file
View file

@ -0,0 +1,29 @@
#include <hal/nrf_gpio.h>
#include "Spi.h"
using namespace Pinetime::Drivers;
Spi::Spi(SpiMaster& spiMaster, uint8_t pinCsn) :
spiMaster{spiMaster}, pinCsn{pinCsn} {
}
bool Spi::Write(const uint8_t *data, size_t size) {
return spiMaster.Write(pinCsn, data, size);
}
bool Spi::Read(uint8_t *data, size_t size) {
return spiMaster.Read(pinCsn, data, size);
}
void Spi::Sleep() {
// TODO sleep spi
nrf_gpio_cfg_default(pinCsn);
}
bool Spi::Init() {
nrf_gpio_pin_set(pinCsn); /* disable Set slave select (inactive high) */
return true;
}

33
src/drivers/Spi.h Normal file
View file

@ -0,0 +1,33 @@
#pragma once
#include <FreeRTOS.h>
#include <cstdint>
#include <cstddef>
#include <array>
#include <atomic>
#include <task.h>
#include "BufferProvider.h"
#include "SpiMaster.h"
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* data, size_t size);
void Sleep();
void Wakeup();
private:
SpiMaster& spiMaster;
uint8_t pinCsn;
};
}
}

View file

@ -19,8 +19,8 @@ bool SpiMaster::Init() {
nrf_gpio_pin_clear(params.pinMOSI); nrf_gpio_pin_clear(params.pinMOSI);
nrf_gpio_cfg_output(params.pinMOSI); nrf_gpio_cfg_output(params.pinMOSI);
nrf_gpio_cfg_input(params.pinMISO, NRF_GPIO_PIN_NOPULL); nrf_gpio_cfg_input(params.pinMISO, NRF_GPIO_PIN_NOPULL);
nrf_gpio_cfg_output(params.pinCSN); // nrf_gpio_cfg_output(params.pinCSN);
pinCsn = params.pinCSN; // pinCsn = params.pinCSN;
switch(spi) { switch(spi) {
case SpiModule::SPI0: spiBaseAddress = NRF_SPIM0; break; case SpiModule::SPI0: spiBaseAddress = NRF_SPIM0; break;
@ -32,7 +32,6 @@ bool SpiMaster::Init() {
spiBaseAddress->PSELSCK = params.pinSCK; spiBaseAddress->PSELSCK = params.pinSCK;
spiBaseAddress->PSELMOSI = params.pinMOSI; spiBaseAddress->PSELMOSI = params.pinMOSI;
spiBaseAddress->PSELMISO = params.pinMISO; spiBaseAddress->PSELMISO = params.pinMISO;
nrf_gpio_pin_set(pinCsn); /* disable Set slave select (inactive high) */
uint32_t frequency; uint32_t frequency;
switch(params.Frequency) { switch(params.Frequency) {
@ -122,7 +121,7 @@ void SpiMaster::OnEndEvent() {
portYIELD_FROM_ISR(xHigherPriorityTaskWoken); portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
} }
nrf_gpio_pin_set(pinCsn); nrf_gpio_pin_set(this->pinCsn);
} }
} }
@ -140,20 +139,33 @@ void SpiMaster::PrepareTx(const volatile uint32_t bufferAddress, const volatile
spiBaseAddress->EVENTS_END = 0; spiBaseAddress->EVENTS_END = 0;
} }
bool SpiMaster::Write(const uint8_t *data, size_t size) { void SpiMaster::PrepareRx(const volatile uint32_t bufferAddress, const volatile size_t size) {
spiBaseAddress->TXD.PTR = 0;
spiBaseAddress->TXD.MAXCNT = 0;
spiBaseAddress->TXD.LIST = 0;
spiBaseAddress->RXD.PTR = bufferAddress;
spiBaseAddress->RXD.MAXCNT = size;
spiBaseAddress->RXD.LIST = 0;
spiBaseAddress->EVENTS_END = 0;
}
bool SpiMaster::Write(uint8_t pinCsn, const uint8_t *data, size_t size) {
if(data == nullptr) return false; if(data == nullptr) return false;
taskToNotify = xTaskGetCurrentTaskHandle(); taskToNotify = xTaskGetCurrentTaskHandle();
while(busy) { while(busy) {
asm("nop"); asm("nop");
} }
this->pinCsn = pinCsn;
if(size == 1) { if(size == 1) {
SetupWorkaroundForFtpan58(spiBaseAddress, 0,0); SetupWorkaroundForFtpan58(spiBaseAddress, 0,0);
} else { } else {
DisableWorkaroundForFtpan58(spiBaseAddress, 0, 0); DisableWorkaroundForFtpan58(spiBaseAddress, 0, 0);
} }
nrf_gpio_pin_clear(pinCsn); nrf_gpio_pin_clear(this->pinCsn);
currentBufferAddr = (uint32_t)data; currentBufferAddr = (uint32_t)data;
currentBufferSize = size; currentBufferSize = size;
@ -173,6 +185,33 @@ bool SpiMaster::Write(const uint8_t *data, size_t size) {
return true; return true;
} }
bool SpiMaster::Read(uint8_t pinCsn, uint8_t *data, size_t size) {
while(busy) {
asm("nop");
}
taskToNotify = nullptr;
this->pinCsn = pinCsn;
SetupWorkaroundForFtpan58(spiBaseAddress, 0,0);
nrf_gpio_pin_clear(this->pinCsn);
currentBufferAddr = 0;
currentBufferSize = 0;
busy = true;
PrepareRx((uint32_t)data, size);
spiBaseAddress->TASKS_START = 1;
while (spiBaseAddress->EVENTS_END == 0);
nrf_gpio_pin_set(this->pinCsn);
busy = false;
return true;
}
void SpiMaster::Sleep() { void SpiMaster::Sleep() {
while(spiBaseAddress->ENABLE != 0) { while(spiBaseAddress->ENABLE != 0) {
spiBaseAddress->ENABLE = (SPIM_ENABLE_ENABLE_Disabled << SPIM_ENABLE_ENABLE_Pos); spiBaseAddress->ENABLE = (SPIM_ENABLE_ENABLE_Disabled << SPIM_ENABLE_ENABLE_Pos);
@ -180,7 +219,6 @@ void SpiMaster::Sleep() {
nrf_gpio_cfg_default(params.pinSCK); nrf_gpio_cfg_default(params.pinSCK);
nrf_gpio_cfg_default(params.pinMOSI); nrf_gpio_cfg_default(params.pinMOSI);
nrf_gpio_cfg_default(params.pinMISO); nrf_gpio_cfg_default(params.pinMISO);
nrf_gpio_cfg_default(params.pinCSN);
} }
void SpiMaster::Wakeup() { void SpiMaster::Wakeup() {
@ -188,3 +226,4 @@ void SpiMaster::Wakeup() {
} }

View file

@ -22,7 +22,6 @@ namespace Pinetime {
uint8_t pinSCK; uint8_t pinSCK;
uint8_t pinMOSI; uint8_t pinMOSI;
uint8_t pinMISO; uint8_t pinMISO;
uint8_t pinCSN;
}; };
SpiMaster(const SpiModule spi, const Parameters& params); SpiMaster(const SpiModule spi, const Parameters& params);
@ -32,7 +31,8 @@ namespace Pinetime {
SpiMaster& operator=(SpiMaster&&) = delete; SpiMaster& operator=(SpiMaster&&) = delete;
bool Init(); bool Init();
bool Write(const uint8_t* data, size_t size); bool Write(uint8_t pinCsn, const uint8_t* data, size_t size);
bool Read(uint8_t pinCsn, uint8_t* data, size_t size);
void OnStartedEvent(); void OnStartedEvent();
void OnEndEvent(); void OnEndEvent();
@ -44,6 +44,7 @@ namespace Pinetime {
void SetupWorkaroundForFtpan58(NRF_SPIM_Type *spim, uint32_t ppi_channel, uint32_t gpiote_channel); 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 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 PrepareTx(const volatile uint32_t bufferAddress, const volatile size_t size);
void PrepareRx(const volatile uint32_t bufferAddress, const volatile size_t size);
NRF_SPIM_Type * spiBaseAddress; NRF_SPIM_Type * spiBaseAddress;
uint8_t pinCsn; uint8_t pinCsn;

View file

@ -0,0 +1,36 @@
#include <hal/nrf_gpio.h>
#include <libraries/delay/nrf_delay.h>
#include <libraries/log/nrf_log.h>
#include "SpiNorFlash.h"
#include "Spi.h"
using namespace Pinetime::Drivers;
SpiNorFlash::SpiNorFlash(Spi& spi) : spi{spi} {
}
void SpiNorFlash::Init() {
uint8_t cmd = 0x9F;
spi.Write(&cmd, 1);
uint8_t data[3];
data[0] = 0;
data[1] = 0;
data[2] = 0;
spi.Read(data, 3);
NRF_LOG_INFO("Manufacturer : %d, Device : %d", data[0], (data[1] + (data[2]<<8)));
}
void SpiNorFlash::Uninit() {
}
void SpiNorFlash::Sleep() {
}
void SpiNorFlash::Wakeup() {
}

28
src/drivers/SpiNorFlash.h Normal file
View file

@ -0,0 +1,28 @@
#pragma once
#include <cstddef>
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;
void Init();
void Uninit();
void Sleep();
void Wakeup();
private:
Spi& spi;
};
}
}

View file

@ -1,16 +1,17 @@
#include <hal/nrf_gpio.h> #include <hal/nrf_gpio.h>
#include <libraries/delay/nrf_delay.h> #include <libraries/delay/nrf_delay.h>
#include "St7789.h" #include "St7789.h"
#include "SpiMaster.h" #include "Spi.h"
using namespace Pinetime::Drivers; using namespace Pinetime::Drivers;
St7789::St7789(SpiMaster &spiMaster, uint8_t pinDataCommand) : spi{spiMaster}, pinDataCommand{pinDataCommand} { St7789::St7789(Spi &spi, uint8_t pinDataCommand) : spi{spi}, pinDataCommand{pinDataCommand} {
} }
void St7789::Init() { void St7789::Init() {
spi.Init();
nrf_gpio_cfg_output(pinDataCommand); nrf_gpio_cfg_output(pinDataCommand);
nrf_gpio_cfg_output(26); nrf_gpio_cfg_output(26);
nrf_gpio_pin_set(26); nrf_gpio_pin_set(26);
@ -173,11 +174,11 @@ void St7789::HardwareReset() {
void St7789::Sleep() { void St7789::Sleep() {
SleepIn(); SleepIn();
nrf_gpio_cfg_default(pinDataCommand); nrf_gpio_cfg_default(pinDataCommand);
spi.Sleep(); // spi.Sleep(); // TODO sleep SPI
} }
void St7789::Wakeup() { void St7789::Wakeup() {
spi.Wakeup(); // spi.Wakeup(); // TODO wake up SPI
nrf_gpio_cfg_output(pinDataCommand); nrf_gpio_cfg_output(pinDataCommand);
// TODO why do we need to reset the controller? // TODO why do we need to reset the controller?

View file

@ -3,10 +3,10 @@
namespace Pinetime { namespace Pinetime {
namespace Drivers { namespace Drivers {
class SpiMaster; class Spi;
class St7789 { class St7789 {
public: public:
explicit St7789(SpiMaster& spiMaster, uint8_t pinDataCommand); explicit St7789(Spi& spi, uint8_t pinDataCommand);
St7789(const St7789&) = delete; St7789(const St7789&) = delete;
St7789& operator=(const St7789&) = delete; St7789& operator=(const St7789&) = delete;
St7789(St7789&&) = delete; St7789(St7789&&) = delete;
@ -29,7 +29,7 @@ namespace Pinetime {
void Sleep(); void Sleep();
void Wakeup(); void Wakeup();
private: private:
SpiMaster& spi; Spi& spi;
uint8_t pinDataCommand; uint8_t pinDataCommand;
uint8_t verticalScrollingStartAddress = 0; uint8_t verticalScrollingStartAddress = 0;

View file

@ -12,6 +12,7 @@
#include "Components/Ble/BleController.h" #include "Components/Ble/BleController.h"
#include <drivers/St7789.h> #include <drivers/St7789.h>
#include <drivers/SpiMaster.h> #include <drivers/SpiMaster.h>
#include <drivers/Spi.h>
#include <DisplayApp/LittleVgl.h> #include <DisplayApp/LittleVgl.h>
#include <SystemTask/SystemTask.h> #include <SystemTask/SystemTask.h>
#include <Components/Ble/NotificationManager.h> #include <Components/Ble/NotificationManager.h>
@ -38,7 +39,8 @@ Pinetime::Logging::DummyLogger logger;
static constexpr uint8_t pinSpiSck = 2; static constexpr uint8_t pinSpiSck = 2;
static constexpr uint8_t pinSpiMosi = 3; static constexpr uint8_t pinSpiMosi = 3;
static constexpr uint8_t pinSpiMiso = 4; static constexpr uint8_t pinSpiMiso = 4;
static constexpr uint8_t pinSpiCsn = 25; static constexpr uint8_t pinSpiFlashCsn = 5;
static constexpr uint8_t pinLcdCsn = 25;
static constexpr uint8_t pinLcdDataCommand = 18; static constexpr uint8_t pinLcdDataCommand = 18;
Pinetime::Drivers::SpiMaster spi{Pinetime::Drivers::SpiMaster::SpiModule::SPI0, { Pinetime::Drivers::SpiMaster spi{Pinetime::Drivers::SpiMaster::SpiModule::SPI0, {
@ -47,11 +49,15 @@ Pinetime::Drivers::SpiMaster spi{Pinetime::Drivers::SpiMaster::SpiModule::SPI0,
Pinetime::Drivers::SpiMaster::Frequencies::Freq8Mhz, Pinetime::Drivers::SpiMaster::Frequencies::Freq8Mhz,
pinSpiSck, pinSpiSck,
pinSpiMosi, pinSpiMosi,
pinSpiMiso, pinSpiMiso
pinSpiCsn
} }
}; };
Pinetime::Drivers::St7789 lcd {spi, pinLcdDataCommand};
Pinetime::Drivers::Spi lcdSpi {spi, pinLcdCsn};
Pinetime::Drivers::St7789 lcd {lcdSpi, pinLcdDataCommand};
Pinetime::Drivers::Spi flashSpi {spi, pinSpiFlashCsn};
Pinetime::Drivers::SpiNorFlash spiNorFlash {flashSpi};
Pinetime::Drivers::Cst816S touchPanel {}; Pinetime::Drivers::Cst816S touchPanel {};
Pinetime::Components::LittleVgl lvgl {lcd, touchPanel}; Pinetime::Components::LittleVgl lvgl {lcd, touchPanel};
@ -207,7 +213,7 @@ int main(void) {
debounceTimer = xTimerCreate ("debounceTimer", 200, pdFALSE, (void *) 0, DebounceTimerCallback); debounceTimer = xTimerCreate ("debounceTimer", 200, pdFALSE, (void *) 0, DebounceTimerCallback);
systemTask.reset(new Pinetime::System::SystemTask(spi, lcd, touchPanel, lvgl, batteryController, bleController, systemTask.reset(new Pinetime::System::SystemTask(spi, lcd, spiNorFlash, touchPanel, lvgl, batteryController, bleController,
dateTimeController, notificationManager)); dateTimeController, notificationManager));
systemTask->Start(); systemTask->Start();
nimble_port_init(); nimble_port_init();

View file

@ -8460,15 +8460,15 @@
// <e> NRF_LOG_ENABLED - nrf_log - Logger // <e> NRF_LOG_ENABLED - nrf_log - Logger
//========================================================== //==========================================================
#ifndef NRF_LOG_ENABLED #ifndef NRF_LOG_ENABLED
#define NRF_LOG_ENABLED 0 #define NRF_LOG_ENABLED 1
#endif #endif
#ifndef NRF_LOG_BACKEND_RTT_ENABLED #ifndef NRF_LOG_BACKEND_RTT_ENABLED
#define NRF_LOG_BACKEND_RTT_ENABLED 0 #define NRF_LOG_BACKEND_RTT_ENABLED 1
#endif #endif
#ifndef NRF_LOG_BACKEND_SERIAL_USES_RTT #ifndef NRF_LOG_BACKEND_SERIAL_USES_RTT
#define NRF_LOG_BACKEND_SERIAL_USES_RTT 0 #define NRF_LOG_BACKEND_SERIAL_USES_RTT 1
#endif #endif
// <h> Log message pool - Configuration of log message pool // <h> Log message pool - Configuration of log message pool