Add SPI NOR Flash driver, WIP.

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

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

@ -122,14 +122,14 @@ void NimbleController::StartAdvertising() {
int res;
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);
ASSERT(res == 0);
// ASSERT(res == 0);
res = ble_gap_adv_start(addrType, NULL, 10000,
&adv_params, GAPEventCallback, this);
ASSERT(res == 0);
// ASSERT(res == 0);
}
int OnAllSvrDisco(uint16_t conn_handle,

@ -14,12 +14,13 @@
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,
Controllers::Battery &batteryController, Controllers::Ble &bleController,
Controllers::DateTime &dateTimeController,
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},
watchdog{}, watchdogView{watchdog}, notificationManager{notificationManager},
nimbleController(*this, bleController,dateTimeController, notificationManager) {
@ -50,6 +51,7 @@ void SystemTask::Work() {
spi.Init();
lcd.Init();
spiNorFlash.Init();
touchPanel.Init();
batteryController.Init();

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

@ -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;
}

@ -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;
};
}
}

@ -19,8 +19,8 @@ bool SpiMaster::Init() {
nrf_gpio_pin_clear(params.pinMOSI);
nrf_gpio_cfg_output(params.pinMOSI);
nrf_gpio_cfg_input(params.pinMISO, NRF_GPIO_PIN_NOPULL);
nrf_gpio_cfg_output(params.pinCSN);
pinCsn = params.pinCSN;
// nrf_gpio_cfg_output(params.pinCSN);
// pinCsn = params.pinCSN;
switch(spi) {
case SpiModule::SPI0: spiBaseAddress = NRF_SPIM0; break;
@ -32,7 +32,6 @@ bool SpiMaster::Init() {
spiBaseAddress->PSELSCK = params.pinSCK;
spiBaseAddress->PSELMOSI = params.pinMOSI;
spiBaseAddress->PSELMISO = params.pinMISO;
nrf_gpio_pin_set(pinCsn); /* disable Set slave select (inactive high) */
uint32_t frequency;
switch(params.Frequency) {
@ -122,7 +121,7 @@ void SpiMaster::OnEndEvent() {
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;
}
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;
taskToNotify = xTaskGetCurrentTaskHandle();
while(busy) {
asm("nop");
}
this->pinCsn = pinCsn;
if(size == 1) {
SetupWorkaroundForFtpan58(spiBaseAddress, 0,0);
} else {
DisableWorkaroundForFtpan58(spiBaseAddress, 0, 0);
}
nrf_gpio_pin_clear(pinCsn);
nrf_gpio_pin_clear(this->pinCsn);
currentBufferAddr = (uint32_t)data;
currentBufferSize = size;
@ -173,6 +185,33 @@ bool SpiMaster::Write(const uint8_t *data, size_t size) {
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() {
while(spiBaseAddress->ENABLE != 0) {
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.pinMOSI);
nrf_gpio_cfg_default(params.pinMISO);
nrf_gpio_cfg_default(params.pinCSN);
}
void SpiMaster::Wakeup() {
@ -188,3 +226,4 @@ void SpiMaster::Wakeup() {
}

@ -22,7 +22,6 @@ namespace Pinetime {
uint8_t pinSCK;
uint8_t pinMOSI;
uint8_t pinMISO;
uint8_t pinCSN;
};
SpiMaster(const SpiModule spi, const Parameters& params);
@ -32,7 +31,8 @@ namespace Pinetime {
SpiMaster& operator=(SpiMaster&&) = delete;
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 OnEndEvent();
@ -44,6 +44,7 @@ namespace Pinetime {
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 bufferAddress, const volatile size_t size);
NRF_SPIM_Type * spiBaseAddress;
uint8_t pinCsn;

@ -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() {
}

@ -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;
};
}
}

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

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

@ -12,6 +12,7 @@
#include "Components/Ble/BleController.h"
#include <drivers/St7789.h>
#include <drivers/SpiMaster.h>
#include <drivers/Spi.h>
#include <DisplayApp/LittleVgl.h>
#include <SystemTask/SystemTask.h>
#include <Components/Ble/NotificationManager.h>
@ -38,7 +39,8 @@ Pinetime::Logging::DummyLogger logger;
static constexpr uint8_t pinSpiSck = 2;
static constexpr uint8_t pinSpiMosi = 3;
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;
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,
pinSpiSck,
pinSpiMosi,
pinSpiMiso,
pinSpiCsn
pinSpiMiso
}
};
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::Components::LittleVgl lvgl {lcd, touchPanel};
@ -207,7 +213,7 @@ int main(void) {
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));
systemTask->Start();
nimble_port_init();

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