summaryrefslogtreecommitdiff
path: root/src/drivers/SpiNorFlash.cpp
diff options
context:
space:
mode:
authorJF <jf@codingfield.com>2020-05-11 16:50:37 (GMT)
committerJF <jf@codingfield.com>2020-05-11 16:50:37 (GMT)
commitee05577dd62c64d0e6a2e497b75710c7a1351557 (patch)
tree36d36462bd1c3aaa06df46b0bf6086111c83df2b /src/drivers/SpiNorFlash.cpp
parent0b8e6c3fa20457bce931b1d289f187e46fc68307 (diff)
Fix race conditions on SPI and integrate the SPI NOR Flash driver into DFUService (WIP)
Diffstat (limited to 'src/drivers/SpiNorFlash.cpp')
-rw-r--r--src/drivers/SpiNorFlash.cpp108
1 files changed, 98 insertions, 10 deletions
diff --git a/src/drivers/SpiNorFlash.cpp b/src/drivers/SpiNorFlash.cpp
index d19548e..8fbb53a 100644
--- a/src/drivers/SpiNorFlash.cpp
+++ b/src/drivers/SpiNorFlash.cpp
@@ -11,16 +11,8 @@ 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)));
+ auto id = ReadIdentificaion();
+ NRF_LOG_INFO("[SPI FLASH] Manufacturer : %d, Memory type : %d, memory density : %d", id.manufacturer, id.type, id.density);
}
void SpiNorFlash::Uninit() {
@@ -34,3 +26,99 @@ void SpiNorFlash::Sleep() {
void SpiNorFlash::Wakeup() {
}
+
+SpiNorFlash::Identification SpiNorFlash::ReadIdentificaion() {
+ auto cmd = static_cast<uint8_t>(Commands::ReadIdentification);
+ Identification identification;
+ spi.Read(&cmd, 1, reinterpret_cast<uint8_t *>(&identification), sizeof(Identification));
+ return identification;
+}
+
+uint8_t SpiNorFlash::ReadStatusRegister() {
+ auto cmd = static_cast<uint8_t>(Commands::ReadStatusRegister);
+ uint8_t status;
+ spi.Read(&cmd, sizeof(cmd), &status, sizeof(uint8_t));
+ return status;
+}
+
+bool SpiNorFlash::WriteInProgress() {
+ return (ReadStatusRegister() & 0x01u) == 0x01u;
+}
+
+bool SpiNorFlash::WriteEnabled() {
+ return (ReadStatusRegister() & 0x02u) == 0x02u;
+}
+
+uint8_t SpiNorFlash::ReadConfigurationRegister() {
+ auto cmd = static_cast<uint8_t>(Commands::ReadConfigurationRegister);
+ uint8_t status;
+ spi.Read(&cmd, sizeof(cmd), &status, sizeof(uint8_t));
+ return status;
+}
+
+void SpiNorFlash::Read(uint32_t address, uint8_t *buffer, size_t size) {
+ static constexpr uint8_t cmdSize = 4;
+ uint8_t cmd[cmdSize] = { static_cast<uint8_t>(Commands::Read), (uint8_t)(address >> 16U), (uint8_t)(address >> 8U),
+ (uint8_t)address };
+ spi.Read(reinterpret_cast<uint8_t *>(&cmd), cmdSize, buffer, size);
+}
+
+void SpiNorFlash::WriteEnable() {
+ auto cmd = static_cast<uint8_t>(Commands::WriteEnable);
+ spi.Read(&cmd, sizeof(cmd), nullptr, 0);
+}
+
+void SpiNorFlash::SectorErase(uint32_t sectorAddress) {
+ static constexpr uint8_t cmdSize = 4;
+ uint8_t cmd[cmdSize] = { static_cast<uint8_t>(Commands::SectorErase), (uint8_t)(sectorAddress >> 16U), (uint8_t)(sectorAddress >> 8U),
+ (uint8_t)sectorAddress };
+
+ WriteEnable();
+ while(!WriteEnabled()) vTaskDelay(1);
+
+ spi.Read(reinterpret_cast<uint8_t *>(&cmd), cmdSize, nullptr, 0);
+
+ while(WriteInProgress()) vTaskDelay(1);
+}
+
+uint8_t SpiNorFlash::ReadSecurityRegister() {
+ auto cmd = static_cast<uint8_t>(Commands::ReadSecurityRegister);
+ uint8_t status;
+ spi.Read(&cmd, sizeof(cmd), &status, sizeof(uint8_t));
+ return status;
+}
+
+bool SpiNorFlash::ProgramFailed() {
+ return (ReadSecurityRegister() & 0x20u) == 0x20u;
+}
+
+bool SpiNorFlash::EraseFailed() {
+ return (ReadSecurityRegister() & 0x40u) == 0x40u;
+}
+
+void SpiNorFlash::Write(uint32_t address, uint8_t *buffer, size_t size) {
+ static constexpr uint8_t cmdSize = 4;
+
+ size_t len = size;
+ uint32_t addr = address;
+ uint8_t* b = buffer;
+ while(len > 0) {
+ uint32_t pageLimit = (addr & ~(pageSize - 1u)) + pageSize;
+ uint32_t toWrite = pageLimit - addr > len ? len : pageLimit - addr;
+
+ uint8_t cmd[cmdSize] = { static_cast<uint8_t>(Commands::PageProgram), (uint8_t)(addr >> 16U), (uint8_t)(addr >> 8U),
+ (uint8_t)addr };
+
+ WriteEnable();
+ while(!WriteEnabled()) vTaskDelay(1);
+
+ spi.WriteCmdAndBuffer(cmd, cmdSize, b, toWrite);
+
+ while(WriteInProgress()) vTaskDelay(1);
+
+ addr += toWrite;
+ b += toWrite;
+ len -= toWrite;
+ }
+
+}