Encapsulate DFU Image buffering and writing into spi flash in DfuImage.
Add some const in SPI driver.
This commit is contained in:
parent
f6aa41c214
commit
de822cc3a2
|
@ -355,7 +355,6 @@ list(APPEND SOURCE_FILES
|
||||||
Components/Ble/DfuService.cpp
|
Components/Ble/DfuService.cpp
|
||||||
Components/Ble/CurrentTimeService.cpp
|
Components/Ble/CurrentTimeService.cpp
|
||||||
Components/Ble/AlertNotificationService.cpp
|
Components/Ble/AlertNotificationService.cpp
|
||||||
Components/Ble/DfuImage.cpp
|
|
||||||
drivers/Cst816s.cpp
|
drivers/Cst816s.cpp
|
||||||
FreeRTOS/port.c
|
FreeRTOS/port.c
|
||||||
FreeRTOS/port_cmsis_systick.c
|
FreeRTOS/port_cmsis_systick.c
|
||||||
|
@ -409,7 +408,6 @@ set(INCLUDE_FILES
|
||||||
Components/Ble/CurrentTimeClient.h
|
Components/Ble/CurrentTimeClient.h
|
||||||
Components/Ble/AlertNotificationClient.h
|
Components/Ble/AlertNotificationClient.h
|
||||||
Components/Ble/DfuService.h
|
Components/Ble/DfuService.h
|
||||||
Components/Ble/DfuImage.h
|
|
||||||
drivers/Cst816s.h
|
drivers/Cst816s.h
|
||||||
FreeRTOS/portmacro.h
|
FreeRTOS/portmacro.h
|
||||||
FreeRTOS/portmacro_cmsis.h
|
FreeRTOS/portmacro_cmsis.h
|
||||||
|
|
|
@ -30,7 +30,7 @@ DfuService::DfuService(Pinetime::System::SystemTask &systemTask, Pinetime::Contr
|
||||||
Pinetime::Drivers::SpiNorFlash &spiNorFlash) :
|
Pinetime::Drivers::SpiNorFlash &spiNorFlash) :
|
||||||
systemTask{systemTask},
|
systemTask{systemTask},
|
||||||
bleController{bleController},
|
bleController{bleController},
|
||||||
spiNorFlash{spiNorFlash},
|
dfuImage{spiNorFlash},
|
||||||
characteristicDefinition{
|
characteristicDefinition{
|
||||||
{
|
{
|
||||||
.uuid = (ble_uuid_t *) &packetCharacteristicUuid,
|
.uuid = (ble_uuid_t *) &packetCharacteristicUuid,
|
||||||
|
@ -124,11 +124,7 @@ int DfuService::WritePacketHandler(uint16_t connectionHandle, os_mbuf *om) {
|
||||||
NRF_LOG_INFO("[DFU] -> Start data received : SD size : %d, BT size : %d, app size : %d", softdeviceSize,
|
NRF_LOG_INFO("[DFU] -> Start data received : SD size : %d, BT size : %d, app size : %d", softdeviceSize,
|
||||||
bootloaderSize, applicationSize);
|
bootloaderSize, applicationSize);
|
||||||
|
|
||||||
for (int erased = 0; erased < maxImageSize; erased += 0x1000) {
|
dfuImage.Erase();
|
||||||
#if 1
|
|
||||||
spiNorFlash.SectorErase(writeOffset + erased);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t data[]{16, 1, 1};
|
uint8_t data[]{16, 1, 1};
|
||||||
notificationManager.Send(connectionHandle, controlPointCharacteristicHandle, data, 3);
|
notificationManager.Send(connectionHandle, controlPointCharacteristicHandle, data, 3);
|
||||||
|
@ -157,13 +153,7 @@ int DfuService::WritePacketHandler(uint16_t connectionHandle, os_mbuf *om) {
|
||||||
|
|
||||||
case States::Data: {
|
case States::Data: {
|
||||||
nbPacketReceived++;
|
nbPacketReceived++;
|
||||||
auto offset = ((nbPacketReceived - 1) % nbPacketsToNotify) * 20;
|
dfuImage.Append(om->om_data, om->om_len);
|
||||||
std::memcpy(tempBuffer + offset, om->om_data, om->om_len);
|
|
||||||
|
|
||||||
if (nbPacketReceived > 0 && (nbPacketReceived % nbPacketsToNotify) == 0) {
|
|
||||||
spiNorFlash.Write(writeOffset + ((nbPacketReceived - nbPacketsToNotify) * 20), tempBuffer, 200);
|
|
||||||
}
|
|
||||||
|
|
||||||
bytesReceived += om->om_len;
|
bytesReceived += om->om_len;
|
||||||
bleController.FirmwareUpdateCurrentBytes(bytesReceived);
|
bleController.FirmwareUpdateCurrentBytes(bytesReceived);
|
||||||
|
|
||||||
|
@ -174,15 +164,7 @@ int DfuService::WritePacketHandler(uint16_t connectionHandle, os_mbuf *om) {
|
||||||
NRF_LOG_INFO("[DFU] -> Send packet notification: %d bytes received", bytesReceived);
|
NRF_LOG_INFO("[DFU] -> Send packet notification: %d bytes received", bytesReceived);
|
||||||
notificationManager.Send(connectionHandle, controlPointCharacteristicHandle, data, 5);
|
notificationManager.Send(connectionHandle, controlPointCharacteristicHandle, data, 5);
|
||||||
}
|
}
|
||||||
if (bytesReceived == applicationSize) {
|
if (dfuImage.IsComplete()) {
|
||||||
if ((nbPacketReceived % nbPacketsToNotify) != 0) {
|
|
||||||
auto remaningPacket = nbPacketReceived % nbPacketsToNotify;
|
|
||||||
spiNorFlash.Write(writeOffset + ((nbPacketReceived - remaningPacket) * 20), tempBuffer, remaningPacket * 20);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (applicationSize < maxImageSize)
|
|
||||||
WriteMagicNumber();
|
|
||||||
|
|
||||||
uint8_t data[3]{static_cast<uint8_t>(Opcodes::Response),
|
uint8_t data[3]{static_cast<uint8_t>(Opcodes::Response),
|
||||||
static_cast<uint8_t>(Opcodes::ReceiveFirmwareImage),
|
static_cast<uint8_t>(Opcodes::ReceiveFirmwareImage),
|
||||||
static_cast<uint8_t>(ErrorCodes::NoError)};
|
static_cast<uint8_t>(ErrorCodes::NoError)};
|
||||||
|
@ -257,6 +239,8 @@ int DfuService::ControlPointHandler(uint16_t connectionHandle, os_mbuf *om) {
|
||||||
NRF_LOG_INFO("[DFU] -> Receive firmware image requested, but we are not in Start Init");
|
NRF_LOG_INFO("[DFU] -> Receive firmware image requested, but we are not in Start Init");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
// TODO the chunk size is dependant of the implementation of the host application...
|
||||||
|
dfuImage.Init(20, applicationSize, expectedCrc);
|
||||||
NRF_LOG_INFO("[DFU] -> Starting receive firmware");
|
NRF_LOG_INFO("[DFU] -> Starting receive firmware");
|
||||||
state = States::Data;
|
state = States::Data;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -268,8 +252,11 @@ int DfuService::ControlPointHandler(uint16_t connectionHandle, os_mbuf *om) {
|
||||||
|
|
||||||
NRF_LOG_INFO("[DFU] -> Validate firmware image requested -- %d", connectionHandle);
|
NRF_LOG_INFO("[DFU] -> Validate firmware image requested -- %d", connectionHandle);
|
||||||
|
|
||||||
if(Validate()){
|
if(dfuImage.Validate()){
|
||||||
state = States::Validated;
|
state = States::Validated;
|
||||||
|
bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Validated);
|
||||||
|
NRF_LOG_INFO("Image OK");
|
||||||
|
|
||||||
uint8_t data[3] {
|
uint8_t data[3] {
|
||||||
static_cast<uint8_t>(Opcodes::Response),
|
static_cast<uint8_t>(Opcodes::Response),
|
||||||
static_cast<uint8_t>(Opcodes::ValidateFirmware),
|
static_cast<uint8_t>(Opcodes::ValidateFirmware),
|
||||||
|
@ -277,6 +264,9 @@ int DfuService::ControlPointHandler(uint16_t connectionHandle, os_mbuf *om) {
|
||||||
};
|
};
|
||||||
notificationManager.AsyncSend(connectionHandle, controlPointCharacteristicHandle, data, 3);
|
notificationManager.AsyncSend(connectionHandle, controlPointCharacteristicHandle, data, 3);
|
||||||
} else {
|
} else {
|
||||||
|
bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Error);
|
||||||
|
NRF_LOG_INFO("Image Error : bad CRC");
|
||||||
|
|
||||||
uint8_t data[3] {
|
uint8_t data[3] {
|
||||||
static_cast<uint8_t>(Opcodes::Response),
|
static_cast<uint8_t>(Opcodes::Response),
|
||||||
static_cast<uint8_t>(Opcodes::ValidateFirmware),
|
static_cast<uint8_t>(Opcodes::ValidateFirmware),
|
||||||
|
@ -303,64 +293,6 @@ int DfuService::ControlPointHandler(uint16_t connectionHandle, os_mbuf *om) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uint16_t DfuService::ComputeCrc(uint8_t const *p_data, uint32_t size, uint16_t const *p_crc) {
|
|
||||||
uint16_t crc = (p_crc == NULL) ? 0xFFFF : *p_crc;
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < size; i++) {
|
|
||||||
crc = (uint8_t) (crc >> 8) | (crc << 8);
|
|
||||||
crc ^= p_data[i];
|
|
||||||
crc ^= (uint8_t) (crc & 0xFF) >> 4;
|
|
||||||
crc ^= (crc << 8) << 4;
|
|
||||||
crc ^= ((crc & 0xFF) << 4) << 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return crc;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DfuService::Validate() {
|
|
||||||
uint32_t chunkSize = 200;
|
|
||||||
int currentOffset = 0;
|
|
||||||
uint16_t crc = 0;
|
|
||||||
|
|
||||||
bool first = true;
|
|
||||||
while (currentOffset < applicationSize) {
|
|
||||||
uint32_t readSize = (applicationSize - currentOffset) > chunkSize ? chunkSize : (applicationSize - currentOffset);
|
|
||||||
|
|
||||||
spiNorFlash.Read(writeOffset + currentOffset, tempBuffer, readSize);
|
|
||||||
if (first) {
|
|
||||||
crc = ComputeCrc(tempBuffer, readSize, NULL);
|
|
||||||
first = false;
|
|
||||||
} else
|
|
||||||
crc = ComputeCrc(tempBuffer, readSize, &crc);
|
|
||||||
currentOffset += readSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
NRF_LOG_INFO("Expected CRC : %u - Processed CRC : %u", expectedCrc, crc);
|
|
||||||
bool crcOk = (crc == expectedCrc);
|
|
||||||
if (crcOk) {
|
|
||||||
bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Validated);
|
|
||||||
NRF_LOG_INFO("Image OK");
|
|
||||||
} else {
|
|
||||||
bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Error);
|
|
||||||
NRF_LOG_INFO("Image Error : bad CRC");
|
|
||||||
}
|
|
||||||
return crcOk;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DfuService::WriteMagicNumber() {
|
|
||||||
uint32_t magic[4] = {
|
|
||||||
0xf395c277,
|
|
||||||
0x7fefd260,
|
|
||||||
0x0f505235,
|
|
||||||
0x8079b62c,
|
|
||||||
};
|
|
||||||
|
|
||||||
uint32_t offset = writeOffset + (maxImageSize - (4 * sizeof(uint32_t)));
|
|
||||||
spiNorFlash.Write(offset, reinterpret_cast<uint8_t *>(magic), 4 * sizeof(uint32_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
void DfuService::OnTimeout() {
|
void DfuService::OnTimeout() {
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
|
@ -415,3 +347,90 @@ void DfuService::NotificationManager::Reset() {
|
||||||
size = 0;
|
size = 0;
|
||||||
xTimerStop(timer, 0);
|
xTimerStop(timer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DfuService::DfuImage::Init(size_t chunkSize, size_t totalSize, uint16_t expectedCrc) {
|
||||||
|
if(chunkSize != 20) return;
|
||||||
|
this->chunkSize = chunkSize;
|
||||||
|
this->totalSize = totalSize;
|
||||||
|
this->expectedCrc = expectedCrc;
|
||||||
|
this->ready = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DfuService::DfuImage::Append(uint8_t *data, size_t size) {
|
||||||
|
if(!ready) return;
|
||||||
|
ASSERT(size <= 20);
|
||||||
|
|
||||||
|
std::memcpy(tempBuffer + bufferWriteIndex, data, size);
|
||||||
|
bufferWriteIndex += size;
|
||||||
|
|
||||||
|
if(bufferWriteIndex == bufferSize) {
|
||||||
|
spiNorFlash.Write(writeOffset + totalWriteIndex, tempBuffer, bufferWriteIndex);
|
||||||
|
totalWriteIndex += bufferWriteIndex;
|
||||||
|
bufferWriteIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bufferWriteIndex > 0 && totalWriteIndex + bufferWriteIndex == totalSize) {
|
||||||
|
spiNorFlash.Write(writeOffset + totalWriteIndex, tempBuffer, bufferWriteIndex);
|
||||||
|
totalWriteIndex += bufferWriteIndex;
|
||||||
|
if (totalSize < maxSize);
|
||||||
|
WriteMagicNumber();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DfuService::DfuImage::WriteMagicNumber() {
|
||||||
|
static constexpr uint32_t magic[4] = {
|
||||||
|
0xf395c277,
|
||||||
|
0x7fefd260,
|
||||||
|
0x0f505235,
|
||||||
|
0x8079b62c,
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32_t offset = writeOffset + (maxSize - (4 * sizeof(uint32_t)));
|
||||||
|
spiNorFlash.Write(offset, reinterpret_cast<const uint8_t *>(magic), 4 * sizeof(uint32_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DfuService::DfuImage::Erase() {
|
||||||
|
for (int erased = 0; erased < maxSize; erased += 0x1000) {
|
||||||
|
spiNorFlash.SectorErase(writeOffset + erased);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DfuService::DfuImage::Validate() {
|
||||||
|
uint32_t chunkSize = 200;
|
||||||
|
int currentOffset = 0;
|
||||||
|
uint16_t crc = 0;
|
||||||
|
|
||||||
|
bool first = true;
|
||||||
|
while (currentOffset < totalSize) {
|
||||||
|
uint32_t readSize = (totalSize - currentOffset) > chunkSize ? chunkSize : (totalSize - currentOffset);
|
||||||
|
|
||||||
|
spiNorFlash.Read(writeOffset + currentOffset, tempBuffer, readSize);
|
||||||
|
if (first) {
|
||||||
|
crc = ComputeCrc(tempBuffer, readSize, NULL);
|
||||||
|
first = false;
|
||||||
|
} else
|
||||||
|
crc = ComputeCrc(tempBuffer, readSize, &crc);
|
||||||
|
currentOffset += readSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (crc == expectedCrc);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t DfuService::DfuImage::ComputeCrc(uint8_t const *p_data, uint32_t size, uint16_t const *p_crc) {
|
||||||
|
uint16_t crc = (p_crc == NULL) ? 0xFFFF : *p_crc;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < size; i++) {
|
||||||
|
crc = (uint8_t) (crc >> 8) | (crc << 8);
|
||||||
|
crc ^= p_data[i];
|
||||||
|
crc ^= (uint8_t) (crc & 0xFF) >> 4;
|
||||||
|
crc ^= (crc << 8) << 4;
|
||||||
|
crc ^= ((crc & 0xFF) << 4) << 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DfuService::DfuImage::IsComplete() {
|
||||||
|
if(!ready) return false;
|
||||||
|
return totalWriteIndex == totalSize;
|
||||||
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ namespace Pinetime {
|
||||||
DfuService(Pinetime::System::SystemTask &systemTask, Pinetime::Controllers::Ble &bleController,
|
DfuService(Pinetime::System::SystemTask &systemTask, Pinetime::Controllers::Ble &bleController,
|
||||||
Pinetime::Drivers::SpiNorFlash &spiNorFlash);
|
Pinetime::Drivers::SpiNorFlash &spiNorFlash);
|
||||||
void Init();
|
void Init();
|
||||||
bool Validate();
|
|
||||||
int OnServiceData(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt *context);
|
int OnServiceData(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt *context);
|
||||||
void OnTimeout();
|
void OnTimeout();
|
||||||
void Reset();
|
void Reset();
|
||||||
|
@ -40,11 +39,38 @@ namespace Pinetime {
|
||||||
void OnNotificationTimer();
|
void OnNotificationTimer();
|
||||||
void Reset();
|
void Reset();
|
||||||
};
|
};
|
||||||
|
class DfuImage {
|
||||||
|
public:
|
||||||
|
DfuImage(Pinetime::Drivers::SpiNorFlash& spiNorFlash) : spiNorFlash{spiNorFlash} {}
|
||||||
|
void Init(size_t chunkSize, size_t totalSize, uint16_t expectedCrc);
|
||||||
|
void Erase();
|
||||||
|
void Append(uint8_t* data, size_t size);
|
||||||
|
bool Validate();
|
||||||
|
bool IsComplete();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Pinetime::Drivers::SpiNorFlash& spiNorFlash;
|
||||||
|
static constexpr size_t bufferSize = 200;
|
||||||
|
bool ready = false;
|
||||||
|
size_t chunkSize = 0;
|
||||||
|
size_t totalSize = 0;
|
||||||
|
size_t maxSize = 475136;
|
||||||
|
size_t bufferWriteIndex = 0;
|
||||||
|
size_t totalWriteIndex = 0;
|
||||||
|
static constexpr size_t writeOffset = 0x40000;
|
||||||
|
uint8_t tempBuffer[bufferSize];
|
||||||
|
uint16_t expectedCrc = 0;
|
||||||
|
|
||||||
|
void WriteMagicNumber();
|
||||||
|
uint16_t ComputeCrc(uint8_t const *p_data, uint32_t size, uint16_t const *p_crc);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Pinetime::System::SystemTask &systemTask;
|
Pinetime::System::SystemTask &systemTask;
|
||||||
Pinetime::Controllers::Ble &bleController;
|
Pinetime::Controllers::Ble &bleController;
|
||||||
Pinetime::Drivers::SpiNorFlash &spiNorFlash;
|
DfuImage dfuImage;
|
||||||
|
NotificationManager notificationManager;
|
||||||
|
|
||||||
static constexpr uint16_t dfuServiceId{0x1530};
|
static constexpr uint16_t dfuServiceId{0x1530};
|
||||||
static constexpr uint16_t packetCharacteristicId{0x1532};
|
static constexpr uint16_t packetCharacteristicId{0x1532};
|
||||||
|
@ -119,22 +145,17 @@ namespace Pinetime {
|
||||||
uint8_t nbPacketsToNotify = 0;
|
uint8_t nbPacketsToNotify = 0;
|
||||||
uint32_t nbPacketReceived = 0;
|
uint32_t nbPacketReceived = 0;
|
||||||
uint32_t bytesReceived = 0;
|
uint32_t bytesReceived = 0;
|
||||||
uint32_t writeOffset = 0x40000;
|
|
||||||
|
|
||||||
uint32_t softdeviceSize = 0;
|
uint32_t softdeviceSize = 0;
|
||||||
uint32_t bootloaderSize = 0;
|
uint32_t bootloaderSize = 0;
|
||||||
uint32_t applicationSize = 0;
|
uint32_t applicationSize = 0;
|
||||||
static constexpr uint32_t maxImageSize = 475136;
|
|
||||||
uint16_t expectedCrc = 0;
|
uint16_t expectedCrc = 0;
|
||||||
|
|
||||||
int SendDfuRevision(os_mbuf *om) const;
|
int SendDfuRevision(os_mbuf *om) const;
|
||||||
int WritePacketHandler(uint16_t connectionHandle, os_mbuf *om);
|
int WritePacketHandler(uint16_t connectionHandle, os_mbuf *om);
|
||||||
int ControlPointHandler(uint16_t connectionHandle, os_mbuf *om);
|
int ControlPointHandler(uint16_t connectionHandle, os_mbuf *om);
|
||||||
uint8_t tempBuffer[200];
|
|
||||||
uint16_t ComputeCrc(uint8_t const *p_data, uint32_t size, uint16_t const *p_crc);
|
|
||||||
void WriteMagicNumber();
|
|
||||||
TimerHandle_t timeoutTimer;
|
TimerHandle_t timeoutTimer;
|
||||||
NotificationManager notificationManager;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -27,7 +27,7 @@ bool Spi::Init() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Spi::WriteCmdAndBuffer(uint8_t *cmd, size_t cmdSize, uint8_t *data, size_t dataSize) {
|
bool Spi::WriteCmdAndBuffer(const uint8_t *cmd, size_t cmdSize, const uint8_t *data, size_t dataSize) {
|
||||||
return spiMaster.WriteCmdAndBuffer(pinCsn, cmd, cmdSize, data, dataSize);
|
return spiMaster.WriteCmdAndBuffer(pinCsn, cmd, cmdSize, data, dataSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace Pinetime {
|
||||||
bool Init();
|
bool Init();
|
||||||
bool Write(const uint8_t* data, size_t size);
|
bool Write(const uint8_t* data, size_t size);
|
||||||
bool Read(uint8_t* cmd, size_t cmdSize, uint8_t *data, size_t dataSize);
|
bool Read(uint8_t* cmd, size_t cmdSize, uint8_t *data, size_t dataSize);
|
||||||
bool WriteCmdAndBuffer(uint8_t* cmd, size_t cmdSize, uint8_t *data, size_t dataSize);
|
bool WriteCmdAndBuffer(const uint8_t* cmd, size_t cmdSize, const uint8_t *data, size_t dataSize);
|
||||||
void Sleep();
|
void Sleep();
|
||||||
void Wakeup();
|
void Wakeup();
|
||||||
|
|
||||||
|
|
|
@ -239,7 +239,7 @@ void SpiMaster::Wakeup() {
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SpiMaster::WriteCmdAndBuffer(uint8_t pinCsn, uint8_t *cmd, size_t cmdSize, uint8_t *data, size_t dataSize) {
|
bool SpiMaster::WriteCmdAndBuffer(uint8_t pinCsn, const uint8_t *cmd, size_t cmdSize, const uint8_t *data, size_t dataSize) {
|
||||||
xSemaphoreTake(mutex, portMAX_DELAY);
|
xSemaphoreTake(mutex, portMAX_DELAY);
|
||||||
|
|
||||||
taskToNotify = nullptr;
|
taskToNotify = nullptr;
|
||||||
|
|
|
@ -37,7 +37,7 @@ namespace Pinetime {
|
||||||
bool Write(uint8_t pinCsn, 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* cmd, size_t cmdSize, uint8_t *data, size_t dataSize);
|
bool Read(uint8_t pinCsn, uint8_t* cmd, size_t cmdSize, uint8_t *data, size_t dataSize);
|
||||||
|
|
||||||
bool WriteCmdAndBuffer(uint8_t pinCsn, uint8_t* cmd, size_t cmdSize, uint8_t *data, size_t dataSize);
|
bool WriteCmdAndBuffer(uint8_t pinCsn, const uint8_t* cmd, size_t cmdSize, const uint8_t *data, size_t dataSize);
|
||||||
|
|
||||||
void OnStartedEvent();
|
void OnStartedEvent();
|
||||||
void OnEndEvent();
|
void OnEndEvent();
|
||||||
|
|
|
@ -96,12 +96,12 @@ bool SpiNorFlash::EraseFailed() {
|
||||||
return (ReadSecurityRegister() & 0x40u) == 0x40u;
|
return (ReadSecurityRegister() & 0x40u) == 0x40u;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpiNorFlash::Write(uint32_t address, uint8_t *buffer, size_t size) {
|
void SpiNorFlash::Write(uint32_t address, const uint8_t *buffer, size_t size) {
|
||||||
static constexpr uint8_t cmdSize = 4;
|
static constexpr uint8_t cmdSize = 4;
|
||||||
|
|
||||||
size_t len = size;
|
size_t len = size;
|
||||||
uint32_t addr = address;
|
uint32_t addr = address;
|
||||||
uint8_t* b = buffer;
|
const uint8_t* b = buffer;
|
||||||
while(len > 0) {
|
while(len > 0) {
|
||||||
uint32_t pageLimit = (addr & ~(pageSize - 1u)) + pageSize;
|
uint32_t pageLimit = (addr & ~(pageSize - 1u)) + pageSize;
|
||||||
uint32_t toWrite = pageLimit - addr > len ? len : pageLimit - addr;
|
uint32_t toWrite = pageLimit - addr > len ? len : pageLimit - addr;
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace Pinetime {
|
||||||
bool WriteEnabled();
|
bool WriteEnabled();
|
||||||
uint8_t ReadConfigurationRegister();
|
uint8_t ReadConfigurationRegister();
|
||||||
void Read(uint32_t address, uint8_t* buffer, size_t size);
|
void Read(uint32_t address, uint8_t* buffer, size_t size);
|
||||||
void Write(uint32_t address, uint8_t *buffer, size_t size);
|
void Write(uint32_t address, const uint8_t *buffer, size_t size);
|
||||||
void WriteEnable();
|
void WriteEnable();
|
||||||
void SectorErase(uint32_t sectorAddress);
|
void SectorErase(uint32_t sectorAddress);
|
||||||
uint8_t ReadSecurityRegister();
|
uint8_t ReadSecurityRegister();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user