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

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

View File

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

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 <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?

View File

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