Add SPI NOR Flash driver, WIP.
This commit is contained in:
parent
f96c048deb
commit
0b8e6c3fa2
|
@ -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;
|
||||
|
|
29
src/drivers/Spi.cpp
Normal file
29
src/drivers/Spi.cpp
Normal 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
33
src/drivers/Spi.h
Normal 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;
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
36
src/drivers/SpiNorFlash.cpp
Normal file
36
src/drivers/SpiNorFlash.cpp
Normal 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
28
src/drivers/SpiNorFlash.h
Normal 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;
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
16
src/main.cpp
16
src/main.cpp
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue