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; +} + /// /// ///