diff --git a/SerialPort.cpp b/SerialPort.cpp
index 180816d..ff07f7d 100644
--- a/SerialPort.cpp
+++ b/SerialPort.cpp
@@ -206,6 +206,21 @@ void SerialPort::process()
}
break;
+ case CMD_FLSH_READ:
+ flashRead();
+ break;
+
+ case CMD_FLSH_WRITE:
+ err = flashWrite(m_buffer + 3U, m_len - 3U);
+ if (err == RSN_OK) {
+ sendACK();
+ }
+ else {
+ DEBUG2("SerialPort: process(): received invalid data to write to flash", err);
+ sendNAK(err);
+ }
+ break;
+
/** CW */
case CMD_SEND_CWID:
err = RSN_RINGBUFF_FULL;
diff --git a/SerialPort.h b/SerialPort.h
index 0ea5795..85bc35d 100644
--- a/SerialPort.h
+++ b/SerialPort.h
@@ -95,6 +95,9 @@ enum DVM_COMMANDS {
CMD_ACK = 0x70U,
CMD_NAK = 0x7FU,
+ CMD_FLSH_READ = 0xE0U,
+ CMD_FLSH_WRITE = 0xE1U,
+
CMD_DEBUG1 = 0xF1U,
CMD_DEBUG2 = 0xF2U,
CMD_DEBUG3 = 0xF3U,
@@ -121,6 +124,11 @@ enum CMD_REASON_CODE {
RSN_INVALID_P25_CORR_COUNT = 16U,
+ RSN_NO_INTERNAL_FLASH = 20U,
+ RSN_FAILED_ERASE_FLASH = 21U,
+ RSN_FAILED_WRITE_FLASH = 22U,
+ RSN_FLASH_WRITE_TOO_BIG = 23U,
+
RSN_HS_NO_DUAL_MODE = 32U,
RSN_DMR_DISABLED = 63U,
@@ -207,6 +215,11 @@ private:
/// Sets the RF parameters.
uint8_t setRFParams(const uint8_t* data, uint8_t length);
+ ///
+ void flashRead();
+ ///
+ uint8_t flashWrite(const uint8_t* data, uint8_t length);
+
// Hardware specific routines
///
void beginInt(uint8_t n, int speed);
diff --git a/SerialSTM.cpp b/SerialSTM.cpp
index 3249a69..e969ca0 100644
--- a/SerialSTM.cpp
+++ b/SerialSTM.cpp
@@ -33,6 +33,24 @@
#include "SerialPort.h"
#include "STM_UART.h"
+#if defined(STM32F10X_MD)
+#include
+
+#if defined(STM32_USB_HOST)
+#include
+#endif
+
+#if defined(STM32_USART1_HOST) && defined(STM32_USB_HOST)
+#error "You have to select STM32_USART1_HOST or STM32_USB_HOST, but not both"
+#endif
+
+// ---------------------------------------------------------------------------
+// Constants
+// ---------------------------------------------------------------------------
+
+#define STM32_CNF_PAGE_ADDR (uint32_t)0x0800FC00
+#define STM32_CNF_PAGE ((uint32_t *)0x0800FC00)
+
/*
Pin definitions:
@@ -44,16 +62,6 @@
USART2 - TXD PA2 - RXD PA3
*/
-#if defined(STM32F10X_MD)
-
-#if defined(STM32_USB_HOST)
-#include
-#endif
-
-#if defined(STM32_USART1_HOST) && defined(STM32_USB_HOST)
-#error "You have to select STM32_USART1_HOST or STM32_USB_HOST, but not both"
-#endif
-
#if defined(STM32_USART1_HOST) || defined(SERIAL_REPEATER_USART1)
// ---------------------------------------------------------------------------
// Global Functions and Variables
@@ -195,6 +203,80 @@ void InitUSART2(int speed)
// ---------------------------------------------------------------------------
// Private Class Members
// ---------------------------------------------------------------------------
+///
+///
+///
+void SerialPort::flashRead()
+{
+ uint8_t reply[249U];
+
+ reply[0U] = DVM_FRAME_START;
+ reply[1U] = 249U;
+ reply[2U] = CMD_FLSH_READ;
+
+ ::memcpy(reply + 3U, (void*)STM32_CNF_PAGE, 246U);
+
+ DEBUG1("SerialPort: flashRead(): read bytes from flash");
+
+ writeInt(1U, reply, 249U);
+}
+
+///
+///
+///
+///
+///
+uint8_t SerialPort::flashWrite(const uint8_t* data, uint8_t length)
+{
+ if (length > 249U) {
+ return RSN_FLASH_WRITE_TOO_BIG;
+ }
+
+ DEBUG1("SerialPort: flashWrite(): unlocking flash");
+
+ FLASH_Unlock();
+ FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
+
+#if defined(STM32F4XX)
+ DEBUG1("SerialPort: flashWrite(): erasing flash sector");
+ if (FLASH_EraseSector(STM32_CNF_SECTOR, VoltageRange_3) != FLASH_COMPLETE) {
+ FLASH_Lock();
+ return RSN_FAILED_ERASE_FLASH;
+ }
+#elif defined(STM32F10X_MD)
+ DEBUG1("SerialPort: flashWrite(): erasing flash page");
+ if (FLASH_ErasePage(STM32_CNF_PAGE_ADDR) != FLASH_COMPLETE) {
+ FLASH_Lock();
+ return RSN_FAILED_ERASE_FLASH;
+ }
+#endif
+
+ // write data to the user flash area
+ uint32_t address = STM32_CNF_PAGE_ADDR;
+ uint8_t i = 0U;
+ while (i < length) {
+ uint32_t word =
+ (data[i + 3] << 24) +
+ (data[i + 2] << 16) +
+ (data[i + 1] << 8) +
+ (data[i + 0] << 0);
+
+ DEBUG3("SerialPort: flashWrite(): writing byte data", address, i);
+ if (FLASH_ProgramWord(address, word) == FLASH_COMPLETE) {
+ address += 4;
+ i += 4;
+ }
+ else {
+ FLASH_Lock();
+ return RSN_FAILED_WRITE_FLASH;
+ }
+ }
+
+ DEBUG1("SerialPort: flashWrite(): finished writing, locking flash");
+ FLASH_Lock();
+ return RSN_OK;
+}
+
///
///
///