diff --git a/latest/Firmware/Inc/CommandProcessor.hpp b/latest/Firmware/Inc/CommandProcessor.hpp index b1dd6b7..3c425f4 100644 --- a/latest/Firmware/Inc/CommandProcessor.hpp +++ b/latest/Firmware/Inc/CommandProcessor.hpp @@ -36,6 +36,8 @@ public: private: void processCommand(const char *); void jumpToBootloader(); + void dumpOTPData(); + void writeOTPData(const std::string &cmd); void enterCLIMode(); CommandProcessor(); }; diff --git a/latest/Firmware/Inc/Configuration.hpp b/latest/Firmware/Inc/Configuration.hpp index 9016416..18ee018 100644 --- a/latest/Firmware/Inc/Configuration.hpp +++ b/latest/Firmware/Inc/Configuration.hpp @@ -21,6 +21,7 @@ #define CONFIGURATION_HPP_ #include "StationData.h" +#include "OTPData.h" // This should be plenty big (no need to be a whole flash page though) typedef union @@ -29,6 +30,7 @@ typedef union uint64_t dw[128]; } ConfigPage; + class Configuration { public: @@ -40,10 +42,15 @@ public: bool readStationData(StationData &data); void resetToDefaults(); void reportStationData(); + + void reportOTPData(); + const OTPData *readOTP(); + bool writeOTP(const OTPData &data); private: Configuration(); bool erasePage(); bool writePage(); + uint32_t nextAvailableOTPSlot(); }; #endif /* CONFIGURATION_HPP_ */ diff --git a/latest/Firmware/Inc/OTPData.h b/latest/Firmware/Inc/OTPData.h new file mode 100644 index 0000000..a71bd52 --- /dev/null +++ b/latest/Firmware/Inc/OTPData.h @@ -0,0 +1,28 @@ +/* + * OTPData.h + * + * Created on: Apr 5, 2021 + * Author: peter + */ + +#ifndef INC_OTPDATA_H_ +#define INC_OTPDATA_H_ + +#include + +#define OTP_MAGIC 0x913A6D0C +#define OTP_REV 0x00000001 + +// This structure must be double-word aligned + +typedef struct +{ + uint32_t magic; + uint32_t rev; + char serialnum[32]; + char hwrev[16]; + uint8_t reserved[8]; +} OTPData; + + +#endif /* INC_OTPDATA_H_ */ diff --git a/latest/Firmware/Inc/bsp/bsp.hpp b/latest/Firmware/Inc/bsp/bsp.hpp index b8fae8c..acd3c4f 100644 --- a/latest/Firmware/Inc/bsp/bsp.hpp +++ b/latest/Firmware/Inc/bsp/bsp.hpp @@ -27,7 +27,7 @@ // Either modify this header or define a different symbol in the preprocessor to build for a different board #ifndef BOARD_REV -#define BOARD_REV 100 +#define BOARD_REV 105 #endif /** diff --git a/latest/Firmware/Src/CommandProcessor.cpp b/latest/Firmware/Src/CommandProcessor.cpp index 2ea624a..4ce613d 100644 --- a/latest/Firmware/Src/CommandProcessor.cpp +++ b/latest/Firmware/Src/CommandProcessor.cpp @@ -157,6 +157,14 @@ void CommandProcessor::processCommand(const char *buff) { TXScheduler::instance().queueMessage24(CH_87); } + else if ( s.find("otp?") == 0 ) + { + dumpOTPData(); + } + else if ( s.find("otp ") == 0 ) + { + writeOTPData(s); + } } void CommandProcessor::enterCLIMode() @@ -170,4 +178,31 @@ void CommandProcessor::jumpToBootloader() bsp_enter_dfu(); } +void CommandProcessor::dumpOTPData() +{ + Configuration::instance().reportOTPData(); +} + +void CommandProcessor::writeOTPData(const std::string &s) +{ + string params = s.substr(4); + if (params.empty()) + return; + + vector tokens; + Utils::tokenize(params, ' ', tokens); + if ( tokens.size() < 2 ) + return; + + OTPData data; + data.magic = OTP_MAGIC; + data.rev = OTP_REV; + strlcpy(data.serialnum, tokens[0].c_str(), sizeof data.serialnum); + strlcpy(data.hwrev, tokens[1].c_str(), sizeof data.hwrev); + + bool result = Configuration::instance().writeOTP(data); + if ( result ) + dumpOTPData(); +} + diff --git a/latest/Firmware/Src/Configuration.cpp b/latest/Firmware/Src/Configuration.cpp index b2d0a2a..8aab48a 100644 --- a/latest/Firmware/Src/Configuration.cpp +++ b/latest/Firmware/Src/Configuration.cpp @@ -24,6 +24,10 @@ #include "EventQueue.hpp" #include +// These are not defined in ANY CMSIS or HAL header, WTF ST??? +#define OTP_ADDRESS 0x1FFF7000 +#define OTP_SIZE 0x00000400 + #if 0 static StationData __THIS_STATION__ = { STATION_DATA_MAGIC, @@ -55,7 +59,10 @@ void Configuration::init() { bool cliBootMode = *(uint32_t*)BOOTMODE_ADDRESS == CLI_FLAG_MAGIC; if ( !cliBootMode ) - reportStationData(); + { + reportOTPData(); + reportStationData(); + } } void Configuration::reportStationData() @@ -80,6 +87,24 @@ void Configuration::reportStationData() EventQueue::instance().push(e); } +void Configuration::reportOTPData() +{ + const OTPData *data = readOTP(); + Event *e = EventPool::instance().newEvent(PROPR_NMEA_SENTENCE); + + if ( data == nullptr ) + { + strcpy(e->nmeaBuffer.sentence, "$PAISYS,,*"); + } + else + { + sprintf(e->nmeaBuffer.sentence, "$PAISYS,%s,%s*", data->serialnum, data->hwrev); + } + + Utils::completeNMEA(e->nmeaBuffer.sentence); + EventQueue::instance().push(e); +} + bool Configuration::erasePage() { uint32_t page = (CONFIGURATION_ADDRESS - FLASH_BASE) / FLASH_PAGE_SIZE; @@ -153,5 +178,53 @@ bool Configuration::readStationData(StationData &data) return data.magic == STATION_DATA_MAGIC; } +const OTPData *Configuration::readOTP() +{ + uint32_t address = nextAvailableOTPSlot(); + if ( address == OTP_ADDRESS ) + // There's nothing written! + return nullptr; + + address -= sizeof(OTPData); + if ( IS_FLASH_OTP_ADDRESS(address) ) + return (const OTPData*)address; + + return nullptr; +} + +bool Configuration::writeOTP(const OTPData &data) +{ + uint32_t address = nextAvailableOTPSlot(); + if ( !IS_FLASH_OTP_ADDRESS(address) ) + return false; + + uint64_t *d = (uint64_t*)&data; + + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); + HAL_FLASH_Unlock(); + HAL_StatusTypeDef status = HAL_OK; + for ( uint32_t dw = 0; dw < sizeof data/8; ++dw, ++d ) + { + status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address + dw*8, *d); + if ( status != HAL_OK ) + break; + } + HAL_FLASH_Lock(); + + return true; +} + +uint32_t Configuration::nextAvailableOTPSlot() +{ + for ( uint32_t p = OTP_ADDRESS; p < OTP_ADDRESS+OTP_SIZE; p += sizeof (OTPData) ) + { + OTPData *d = (OTPData*)p; + if ( d->magic == 0xFFFFFFFF ) + return p; + } + + return OTP_ADDRESS+OTP_SIZE; +} + diff --git a/latest/Firmware/Src/Transceiver.cpp b/latest/Firmware/Src/Transceiver.cpp index 46284c5..88c2364 100644 --- a/latest/Firmware/Src/Transceiver.cpp +++ b/latest/Firmware/Src/Transceiver.cpp @@ -84,6 +84,11 @@ void Transceiver::configure() pwr.pa_level = 0x10; pwr.pa_bias_clkduty = 0x00; break; + case 0x4467: + pwr.pa_mode = 0x48; + pwr.pa_level = 0x1C; + pwr.pa_bias_clkduty = 0x00; + break; default: pwr.pa_mode = 0x48; pwr.pa_level = 0x20; diff --git a/latest/Firmware/Src/bsp/bsp_10_5.cpp b/latest/Firmware/Src/bsp/bsp_10_5.cpp index dc51a32..e24d996 100644 --- a/latest/Firmware/Src/bsp/bsp_10_5.cpp +++ b/latest/Firmware/Src/bsp/bsp_10_5.cpp @@ -74,7 +74,7 @@ static const GPIO __gpios[] = { {RX_IC_CLK_PORT, {RX_IC_CLK_PIN, GPIO_MODE_IT_RISING, GPIO_NOPULL, GPIO_SPEED_LOW, 0}, GPIO_PIN_RESET}, {RX_IC_DATA_PORT, {RX_IC_DATA_PIN, GPIO_MODE_INPUT, GPIO_NOPULL, GPIO_SPEED_LOW, 0}, GPIO_PIN_RESET}, {TX_CTRL_PORT, {TX_CTRL_PIN, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_SPEED_LOW, 0}, GPIO_PIN_RESET}, - {RX_EN_PORT, {RX_EN_PIN, GPIO_MODE_AF_PP, GPIO_NOPULL, GPIO_SPEED_LOW, 0}, GPIO_PIN_SET}, + {RX_EN_PORT, {RX_EN_PIN, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_SPEED_LOW, 0}, GPIO_PIN_SET}, }; extern "C"