diff --git a/make/source.mk b/make/source.mk index c0e3b57d3c..2264597875 100644 --- a/make/source.mk +++ b/make/source.mk @@ -65,6 +65,7 @@ OSD_SLAVE_SRC = \ FC_SRC = \ fc/fc_init.c \ + fc/board_info.c \ fc/controlrate_profile.c \ drivers/camera_control.c \ drivers/accgyro/gyro_sync.c \ @@ -282,6 +283,7 @@ SIZE_OPTIMISED_SRC := $(SIZE_OPTIMISED_SRC) \ drivers/vtx_rtc6705.c \ drivers/vtx_common.c \ fc/fc_init.c \ + fc/board_info.c \ config/config_eeprom.c \ config/feature.c \ config/config_streamer.c \ diff --git a/src/main/fc/board_info.c b/src/main/fc/board_info.c new file mode 100644 index 0000000000..c703ec177e --- /dev/null +++ b/src/main/fc/board_info.c @@ -0,0 +1,94 @@ +/* + * This file is part of Cleanflight and Betaflight. + * + * Cleanflight and Betaflight are free software. You can redistribute + * this software and/or modify this software under the terms of the + * GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * Cleanflight and Betaflight are distributed in the hope that they + * will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software. + * + * If not, see . + */ + +#include +#include + +#include "platform.h" + +#include "pg/board.h" + +static bool boardInformationSet = false; +static char manufacturerId[MAX_MANUFACTURER_ID_LENGTH + 1]; +static char boardName[MAX_BOARD_NAME_LENGTH + 1]; + +void initBoardInformation(void) +{ + boardInformationSet = boardConfig()->boardInformationSet; + if (boardInformationSet) { + strncpy(manufacturerId, boardConfig()->manufacturerId, MAX_MANUFACTURER_ID_LENGTH); + strncpy(boardName, boardConfig()->boardName, MAX_BOARD_NAME_LENGTH); + } else { + strcpy(manufacturerId, ""); + strcpy(boardName, ""); + } +} + +char *getManufacturerId(void) +{ + return manufacturerId; +} + +char *getBoardName(void) +{ + return boardName; +} + +bool boardInformationIsSet(void) +{ + return boardInformationSet; +} + +bool setManufacturerId(char *newManufacturerId) +{ + if (!boardInformationSet) { + strncpy(manufacturerId, newManufacturerId, MAX_MANUFACTURER_ID_LENGTH); + + return true; + } else { + return false; + } +} + +bool setBoardName(char *newBoardName) +{ + if (!boardInformationSet) { + strncpy(boardName, newBoardName, MAX_BOARD_NAME_LENGTH); + + return true; + } else { + return false; + } +} + +bool persistBoardInformation(void) +{ + if (!boardInformationSet) { + strncpy(boardConfigMutable()->manufacturerId, manufacturerId, MAX_MANUFACTURER_ID_LENGTH); + strncpy(boardConfigMutable()->boardName, boardName, MAX_BOARD_NAME_LENGTH); + boardConfigMutable()->boardInformationSet = true; + + initBoardInformation(); + + return true; + } else { + return false; + } +} diff --git a/src/main/fc/board_info.h b/src/main/fc/board_info.h new file mode 100644 index 0000000000..e5f43f39d3 --- /dev/null +++ b/src/main/fc/board_info.h @@ -0,0 +1,31 @@ +/* + * This file is part of Cleanflight and Betaflight. + * + * Cleanflight and Betaflight are free software. You can redistribute + * this software and/or modify this software under the terms of the + * GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * Cleanflight and Betaflight are distributed in the hope that they + * will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software. + * + * If not, see . + */ + +#pragma once + +void initBoardInformation(void); + +char *getBoardName(void); +char *getManufacturerId(void); +bool boardInformationIsSet(void); + +bool setBoardName(char *newBoardName); +bool setManufacturerId(char *newManufacturerId); +bool persistBoardInformation(void); diff --git a/src/main/fc/fc_init.c b/src/main/fc/fc_init.c index cf6efc7863..f77a1b0c16 100644 --- a/src/main/fc/fc_init.c +++ b/src/main/fc/fc_init.c @@ -78,6 +78,7 @@ #include "drivers/usb_msc.h" #endif +#include "fc/board_info.h" #include "fc/config.h" #include "fc/fc_init.h" #include "fc/fc_tasks.h" @@ -241,6 +242,8 @@ void init(void) ensureEEPROMStructureIsValid(); bool readSuccess = readEEPROM(); + initBoardInformation(); + if (!readSuccess || strncasecmp(systemConfig()->boardIdentifier, TARGET_BOARD_IDENTIFIER, sizeof(TARGET_BOARD_IDENTIFIER))) { resetEEPROM(); diff --git a/src/main/interface/cli.c b/src/main/interface/cli.c index d3b87fbd0b..98751d1aec 100644 --- a/src/main/interface/cli.c +++ b/src/main/interface/cli.c @@ -84,6 +84,7 @@ extern uint8_t __config_end; #include "drivers/vtx_common.h" #include "drivers/usb_msc.h" +#include "fc/board_info.h" #include "fc/config.h" #include "fc/controlrate_profile.h" #include "fc/fc_core.h" @@ -171,6 +172,8 @@ static uint32_t bufferIndex = 0; static bool configIsInCopy = false; +static bool boardInformationUpdated = false; + static const char* const emptyName = "-"; static const char* const emptyString = ""; @@ -2229,6 +2232,49 @@ static void cliName(char *cmdline) printName(DUMP_MASTER, pilotConfig()); } +#define ERROR_MESSAGE "Error, %s is already set: %s" + +static void cliBoardName(char *cmdline) +{ + const unsigned int len = strlen(cmdline); + if (len > 0 && boardInformationIsSet() && strncmp(getBoardName(), cmdline, len)) { + cliPrintLinef(ERROR_MESSAGE, "board_name", getBoardName()); + } else { + if (len > 0) { + setBoardName(cmdline); + boardInformationUpdated = true; + } + cliPrintLinef("board_name %s", getBoardName()); + } +} + +static void cliManufacturerId(char *cmdline) +{ + const unsigned int len = strlen(cmdline); + if (len > 0 && boardInformationIsSet() && strncmp(getManufacturerId(), cmdline, len)) { + cliPrintLinef(ERROR_MESSAGE, "manufactuer_id", getManufacturerId()); + } else { + if (len > 0) { + setManufacturerId(cmdline); + boardInformationUpdated = true; + } + cliPrintLinef("manufacturer_id %s", getManufacturerId()); + } +} + +#undef ERROR_MESSAGE + +static void cliMcuId(char *cmdline) +{ + UNUSED(cmdline); + + cliPrint("mcu_id 0x"); + cliPrintf("%08x", U_ID_0); + cliPrintf("%08x", U_ID_1); + cliPrintf("%08x", U_ID_2); + cliPrintLinefeed(); +} + static void printFeature(uint8_t dumpMask, const featureConfig_t *featureConfig, const featureConfig_t *featureConfigDefault) { const uint32_t mask = featureConfig->enabledFeatures; @@ -3100,6 +3146,9 @@ static void cliSave(char *cmdline) UNUSED(cmdline); cliPrintHashLine("saving"); + if (boardInformationUpdated) { + persistBoardInformation(); + } writeEEPROM(); cliReboot(); } @@ -3973,6 +4022,13 @@ static void printConfig(char *cmdline, bool doDiff) if ((dumpMask & DUMP_MASTER) || (dumpMask & DUMP_ALL)) { cliPrintHashLine("version"); cliVersion(NULL); + cliPrintLinefeed(); + + cliBoardName(""); + cliManufacturerId(""); + if (dumpMask & DUMP_ALL) { + cliMcuId(NULL); + } if ((dumpMask & (DUMP_ALL | DO_DIFF)) == (DUMP_ALL | DO_DIFF)) { cliPrintHashLine("reset configuration to default settings"); @@ -4176,6 +4232,7 @@ const clicmd_t cmdTable[] = { "\t<+|->[name]", cliBeeper), #endif CLI_COMMAND_DEF("bl", "reboot into bootloader", NULL, cliBootloader), + CLI_COMMAND_DEF("board_name", "name of the board model", NULL, cliBoardName), #ifdef USE_LED_STRIP CLI_COMMAND_DEF("color", "configure colors", NULL, cliColor), #endif @@ -4218,7 +4275,9 @@ const clicmd_t cmdTable[] = { #ifdef USE_LED_STRIP CLI_COMMAND_DEF("led", "configure leds", NULL, cliLed), #endif + CLI_COMMAND_DEF("manufacturer_id", "id of the board manufacturer", NULL, cliManufacturerId), CLI_COMMAND_DEF("map", "configure rc channel order", "[]", cliMap), + CLI_COMMAND_DEF("mcu_id", "id of the microcontroller", NULL, cliMcuId), #ifndef USE_QUAD_MIXER_ONLY CLI_COMMAND_DEF("mixer", "configure mixer", "list\r\n\t", cliMixer), #endif diff --git a/src/main/interface/msp.c b/src/main/interface/msp.c index b325918438..7a39974ba1 100644 --- a/src/main/interface/msp.c +++ b/src/main/interface/msp.c @@ -62,6 +62,7 @@ #include "drivers/transponder_ir.h" #include "drivers/camera_control.h" +#include "fc/board_info.h" #include "fc/config.h" #include "fc/controlrate_profile.h" #include "fc/fc_core.h" @@ -101,6 +102,7 @@ #include "msp/msp_serial.h" +#include "pg/board.h" #include "pg/vcd.h" #include "rx/rx.h" @@ -457,6 +459,17 @@ static bool mspCommonProcessOutCommand(uint8_t cmdMSP, sbuf_t *dst, mspPostProce // Target name with explicit length sbufWriteU8(dst, strlen(targetName)); sbufWriteData(dst, targetName, strlen(targetName)); + + // Board name with explicit length + char *value = getBoardName(); + sbufWriteU8(dst, strlen(value)); + sbufWriteData(dst, value, strlen(value)); + + // Manufacturer id with explicit length + value = getManufacturerId(); + sbufWriteU8(dst, strlen(value)); + sbufWriteData(dst, value, strlen(value)); + break; } @@ -2054,6 +2067,29 @@ static mspResult_e mspProcessInCommand(uint8_t cmdMSP, sbuf_t *src) setRssiMsp(sbufReadU8(src)); break; + + case MSP_SET_BOARD_INFO: + if (!boardInformationIsSet()) { + char boardName[MAX_BOARD_NAME_LENGTH + 1] = {0}; + char manufacturerId[MAX_MANUFACTURER_ID_LENGTH + 1] = {0}; + uint8_t length = sbufReadU8(src); + for (unsigned int i = 0; i < length; i++) { + boardName[i] = sbufReadU8(src); + } + length = sbufReadU8(src); + for (unsigned int i = 0; i < length; i++) { + manufacturerId[i] = sbufReadU8(src); + } + + setBoardName(boardName); + setManufacturerId(manufacturerId); + persistBoardInformation(); + } else { + return MSP_RESULT_ERROR; + } + + break; + default: // we do not know how to handle the (valid) message, indicate error MSP $M! return MSP_RESULT_ERROR; diff --git a/src/main/interface/msp_protocol.h b/src/main/interface/msp_protocol.h index c04a5de57a..234efb28a2 100644 --- a/src/main/interface/msp_protocol.h +++ b/src/main/interface/msp_protocol.h @@ -329,3 +329,4 @@ #define MSP_SET_4WAY_IF 245 //in message Sets 4way interface #define MSP_SET_RTC 246 //in message Sets the RTC clock #define MSP_RTC 247 //out message Gets the RTC clock +#define MSP_SET_BOARD_INFO 248 //in message Sets the board information for this board diff --git a/src/main/pg/board.c b/src/main/pg/board.c new file mode 100644 index 0000000000..622a96c601 --- /dev/null +++ b/src/main/pg/board.c @@ -0,0 +1,56 @@ +/* + * This file is part of Cleanflight and Betaflight. + * + * Cleanflight and Betaflight are free software. You can redistribute + * this software and/or modify this software under the terms of the + * GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * Cleanflight and Betaflight are distributed in the hope that they + * will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software. + * + * If not, see . + */ + +#include +#include + +#include "platform.h" + +#include "build/version.h" + +#include "fc/board_info.h" + +#include "pg/pg.h" +#include "pg/pg_ids.h" + +#include "board.h" + +PG_REGISTER_WITH_RESET_FN(boardConfig_t, boardConfig, PG_BOARD_CONFIG, 0); + +void pgResetFn_boardConfig(boardConfig_t *boardConfig) +{ + if (boardInformationIsSet()) { + strncpy(boardConfig->manufacturerId, getManufacturerId(), MAX_MANUFACTURER_ID_LENGTH); + strncpy(boardConfig->boardName, getBoardName(), MAX_BOARD_NAME_LENGTH); + boardConfig->boardInformationSet = true; + } else { + +#if !defined(GENERIC_TARGET) + strncpy(boardConfig->boardName, targetName, MAX_BOARD_NAME_LENGTH); + +#if defined(TARGET_MANUFACTURER_IDENTIFIER) + strncpy(boardConfig->manufacturerId, TARGET_MANUFACTURER_IDENTIFIER, MAX_MANUFACTURER_ID_LENGTH); +#endif + boardConfig->boardInformationSet = true; +#else + boardConfig->boardInformationSet = false; +#endif // GENERIC_TARGET + } +} diff --git a/src/main/pg/board.h b/src/main/pg/board.h new file mode 100644 index 0000000000..6d70916c1e --- /dev/null +++ b/src/main/pg/board.h @@ -0,0 +1,39 @@ +/* + * This file is part of Cleanflight and Betaflight. + * + * Cleanflight and Betaflight are free software. You can redistribute + * this software and/or modify this software under the terms of the + * GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * Cleanflight and Betaflight are distributed in the hope that they + * will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software. + * + * If not, see . + */ + +#pragma once + +#include "pg/pg.h" + +#define MAX_MANUFACTURER_ID_LENGTH 4 +#define MAX_BOARD_NAME_LENGTH 20 + +// Warning: This configuration is meant to be applied when loading the initial +// configuration for a generic board, and stay fixed after this, to enable +// identification of the hardware that this is running on. +// Do not modify this parameter group directly, use 'fc/board_info.h' instead. + +typedef struct boardConfig_s { + uint8_t boardInformationSet; + char manufacturerId[MAX_MANUFACTURER_ID_LENGTH + 1]; + char boardName[MAX_BOARD_NAME_LENGTH + 1]; +} boardConfig_t; + +PG_DECLARE(boardConfig_t, boardConfig); diff --git a/src/main/pg/pg_ids.h b/src/main/pg/pg_ids.h index b2dd07403d..275b0a8e69 100644 --- a/src/main/pg/pg_ids.h +++ b/src/main/pg/pg_ids.h @@ -132,7 +132,8 @@ #define PG_SPI_PREINIT_IPU_CONFIG 535 #define PG_SPI_PREINIT_OPU_CONFIG 536 #define PG_RX_SPI_CONFIG 537 -#define PG_BETAFLIGHT_END 537 +#define PG_BOARD_CONFIG 538 +#define PG_BETAFLIGHT_END 538 // OSD configuration (subject to change) diff --git a/src/main/target/OMNIBUSF4/target.h b/src/main/target/OMNIBUSF4/target.h index 36e66dd89c..daea8a23a7 100644 --- a/src/main/target/OMNIBUSF4/target.h +++ b/src/main/target/OMNIBUSF4/target.h @@ -34,6 +34,8 @@ #define TARGET_BOARD_IDENTIFIER "EXF4" #else #define TARGET_BOARD_IDENTIFIER "OBF4" +// Example of a manufacturer ID to be persisted as part of the config: +#define TARGET_MANUFACTURER_IDENTIFIER "AIRB" #define OMNIBUSF4BASE // For config.c #endif diff --git a/src/main/target/STM32F7X2/target.h b/src/main/target/STM32F7X2/target.h index 01338d9a82..51c74e26c8 100644 --- a/src/main/target/STM32F7X2/target.h +++ b/src/main/target/STM32F7X2/target.h @@ -19,6 +19,11 @@ */ #pragma once + +// Treat the target as generic, and expect manufacturer id / board name +// to be supplied when the board is configured for the first time +#define GENERIC_TARGET + #define TARGET_BOARD_IDENTIFIER "S7X2" #define USBD_PRODUCT_STRING "S7X2"