From 8224e284b0e8f3bd6012e080413172f330e20f8e Mon Sep 17 00:00:00 2001 From: Kristoffer Richardsson Date: Tue, 13 Nov 2018 16:25:45 +0100 Subject: [PATCH] #379 Added dynamic configurations Identifying the device type based on the device type string and choosing the correct configuration. --- Makefile | 5 +- src/init/main.c | 6 +- src/modules/src/system.c | 4 +- .../platform.c} | 36 ++++++-- src/platform/platform.h | 14 +++ src/platform/{cf2 => }/platform_cf2.c | 88 +++++++++++++++++-- .../platform_stm32.c} | 23 +++-- test/platform/Test_platform.c | 85 ++++++++++++++++++ .../Test_platform_stm32.c} | 27 +++--- tools/test/gcc.yml | 1 + tools/test/rakefile_helper.rb | 16 +++- 11 files changed, 259 insertions(+), 46 deletions(-) rename src/{drivers/interface/platform_info_stm32.h => platform/platform.c} (56%) rename src/platform/{cf2 => }/platform_cf2.c (53%) rename src/{drivers/src/platform_info_stm32.c => platform/platform_stm32.c} (76%) create mode 100644 test/platform/Test_platform.c rename test/{drivers/src/Test_platform_info_stm32.c => platform/Test_platform_stm32.c} (77%) diff --git a/Makefile b/Makefile index 248f57fed2..c3ad00b508 100644 --- a/Makefile +++ b/Makefile @@ -108,8 +108,7 @@ CFLAGS += -DUSD_RUN_DISKIO_FUNCTION_TESTS endif # Crazyflie sources -VPATH += src/init src/hal/src src/modules/src src/utils/src src/drivers/bosch/src src/drivers/src -VPATH_CF2 += src/platform/cf2 +VPATH += src/init src/hal/src src/modules/src src/utils/src src/drivers/bosch/src src/drivers/src src/platform ifeq ($(PLATFORM), CF2) VPATH +=$(VPATH_CF2) @@ -120,7 +119,7 @@ endif # Init PROJ_OBJ += main.o -PROJ_OBJ_CF2 += platform_cf2.o platform_info_stm32.o +PROJ_OBJ_CF2 += platform.o platform_cf2.o platform_stm32.o # Drivers PROJ_OBJ += exti.o nvic.o motors.o diff --git a/src/init/main.c b/src/init/main.c index 9db72a2d22..6d0f09dca1 100644 --- a/src/init/main.c +++ b/src/init/main.c @@ -45,7 +45,11 @@ int main() { //Initialize the platform. - platformInit(); + int err = platformInit(); + if (err != 0) { + // The firmware is running on the wrong hardware. Halt + while(1); + } //Launch the system task that will initialize and start everything systemLaunch(); diff --git a/src/modules/src/system.c b/src/modules/src/system.c index 97d1dd25b6..8327b3e694 100644 --- a/src/modules/src/system.c +++ b/src/modules/src/system.c @@ -96,12 +96,12 @@ void systemInit(void) usblinkInit(); sysLoadInit(); - /* Initialized hear and early so that DEBUG_PRINT (buffered) can be used early */ + /* Initialized here so that DEBUG_PRINT (buffered) can be used early */ crtpInit(); consoleInit(); DEBUG_PRINT("----------------------------\n"); - DEBUG_PRINT(P_NAME " is up and running!\n"); + DEBUG_PRINT("%s is up and running!\n", platformConfigGetDeviceTypeName()); DEBUG_PRINT("Build %s:%s (%s) %s\n", V_SLOCAL_REVISION, V_SREVISION, V_STAG, (V_MODIFIED)?"MODIFIED":"CLEAN"); DEBUG_PRINT("I am 0x%08X%08X%08X and I have %dKB of flash!\n", diff --git a/src/drivers/interface/platform_info_stm32.h b/src/platform/platform.c similarity index 56% rename from src/drivers/interface/platform_info_stm32.h rename to src/platform/platform.c index a167a4d159..5b2f5167b6 100644 --- a/src/drivers/interface/platform_info_stm32.h +++ b/src/platform/platform.c @@ -7,7 +7,7 @@ * * Crazyflie control firmware * - * Copyright (C) 2018 Bitcraze AB + * Copyright (C) 2011-2012 Bitcraze AB * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,15 +21,33 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . * - * platform_info_stm32.h - platform information driver for STM32 based platforms - * - * Platform information is used to identify the hardware platform the firmware - * is running on. + * Generic platform functionality * */ -#define PLATFORM_INFO_OTP_NR_OF_BLOCKS 16 -#define PLATFORM_INFO_OTP_BLOCK_LEN 32 -#define PLATFORM_INFO_MAX_PLATFORM_STRING_LEN (PLATFORM_INFO_OTP_BLOCK_LEN + 1) +#include +#include "platform.h" + +int platformParseDeviceTypeString(const char* deviceTypeString, char* deviceType) { + if (deviceTypeString[0] != '0' || deviceTypeString[1] != ';') { + return 1; + } + + const int start = 2; + const int last = start + PLATFORM_DEVICE_TYPE_MAX_LEN - 1; + int end = 0; + for (end = start; end <= last; end++) { + if (deviceTypeString[end] == '\0' || deviceTypeString[end] == ';') { + break; + } + } + + if (end > last) { + return 1; + } -void platformInfoGetPlatformString(char* buf); + int length = end - start; + memcpy(deviceType, &deviceTypeString[start], length); + deviceType[length] = '\0'; + return 0; +} diff --git a/src/platform/platform.h b/src/platform/platform.h index 46a665aaf2..021a5a2514 100644 --- a/src/platform/platform.h +++ b/src/platform/platform.h @@ -42,11 +42,25 @@ #ifndef PLATFORM_H_ #define PLATFORM_H_ +#include + +#define PLATFORM_DEVICE_TYPE_STRING_MAX_LEN (32 + 1) +#define PLATFORM_DEVICE_TYPE_MAX_LEN (4 + 1) + /** * Initilizes all platform specific things. */ int platformInit(void); +void platformGetDeviceTypeString(char* deviceTypeString); +int platformParseDeviceTypeString(const char* deviceTypeString, char* deviceType); + void platformSetLowInterferenceRadioMode(void); + +// Functions to read configuration +const char* platformConfigGetPlatformName(); +const char* platformConfigGetDeviceTypeName(); +// TODO Add relevant config functions + #endif /* PLATFORM_H_ */ diff --git a/src/platform/cf2/platform_cf2.c b/src/platform/platform_cf2.c similarity index 53% rename from src/platform/cf2/platform_cf2.c rename to src/platform/platform_cf2.c index 94d69be41e..4014387ce6 100644 --- a/src/platform/cf2/platform_cf2.c +++ b/src/platform/platform_cf2.c @@ -21,13 +21,14 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . * - * TODO: Add description + * Platform functionality for the CF2 platform */ #define DEBUG_MODULE "PLATFORM" -/* Personal configs */ -/* Project includes */ +#include + +#include "platform.h" #include "exti.h" #include "nvic.h" #include "debug.h" @@ -38,21 +39,90 @@ #define PLATFORM_NRF51_LOW_INTERFERENCE_TX_POWER_DBM (-12) #endif -// TODO: Implement! +static int initPlatformConfiguration(); +static void initHardware(); + + +typedef struct { + char deviceType[PLATFORM_DEVICE_TYPE_MAX_LEN]; + char deviceTypeName[14]; +} config_t; + +static config_t configs[] = { + { + .deviceType = "CF20", + .deviceTypeName = "Crazyflie 2.0", + }, + { + .deviceType = "CF21", + .deviceTypeName = "Crazyflie 2.1", + } +}; + +static config_t* active_config = 0; + + int platformInit(void) { - //Low level init: Clock and Interrupt controller - nvicInit(); - - //EXTI interrupts - extiInit(); + int err = initPlatformConfiguration(); + if (err != 0) + { + // This firmware is not compatible, abort init + return 1; + } + initHardware(); return 0; } + void platformSetLowInterferenceRadioMode(void) { // Decrease the nRF51 Tx power to reduce interference radiolinkSetPowerDbm(PLATFORM_NRF51_LOW_INTERFERENCE_TX_POWER_DBM); DEBUG_PRINT("Low interference mode. NRF51 TX power offset by %ddb.\r\n", PLATFORM_NRF51_LOW_INTERFERENCE_TX_POWER_DBM); } + + +static int initPlatformConfiguration() +{ + char deviceTypeString[PLATFORM_DEVICE_TYPE_STRING_MAX_LEN]; + char deviceType[PLATFORM_DEVICE_TYPE_MAX_LEN]; + + platformGetDeviceTypeString(deviceTypeString); + platformParseDeviceTypeString(deviceTypeString, deviceType); + + for (int i = 0; i < (sizeof(configs) / sizeof(config_t)); i++) { + config_t* config = &configs[i]; + if (strcmp(config->deviceType, deviceType) == 0) { + active_config = config; + return 0; + } + } + + return 1; +} + +static void initHardware() +{ + //Low level init: Clock and Interrupt controller + nvicInit(); + + //EXTI interrupts + extiInit(); +} + + +// Config functions ------------------------ + +const char* platformConfigGetPlatformName() +{ + return "cf2"; +} + +const char* platformConfigGetDeviceTypeName() +{ + return active_config->deviceTypeName; +} + + diff --git a/src/drivers/src/platform_info_stm32.c b/src/platform/platform_stm32.c similarity index 76% rename from src/drivers/src/platform_info_stm32.c rename to src/platform/platform_stm32.c index 805ac614ad..77f5072b04 100644 --- a/src/drivers/src/platform_info_stm32.c +++ b/src/platform/platform_stm32.c @@ -7,7 +7,7 @@ * * Crazyflie control firmware * - * Copyright (C) 2018 Bitcraze AB + * Copyright (C) 2011-2012 Bitcraze AB * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,18 +21,23 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . * - * platform_info_stm32.c - platform information driver for STM32 based platforms - * - * Platform information is used to identify the hardware platform the firmware - * is running on. + * Platform functionality for platforms using the STM32 * */ #include -#include "platform_info_stm32.h" +#include "platform.h" + +#define PLATFORM_INFO_OTP_NR_OF_BLOCKS 16 +#define PLATFORM_INFO_OTP_BLOCK_LEN 32 +#if PLATFORM_DEVICE_TYPE_STRING_MAX_LEN < (PLATFORM_INFO_OTP_BLOCK_LEN + 1) + #error +#endif + #define DEFAULT_PLATFORM_STRING "0;CF20" + #ifndef UNIT_TEST_MODE static char* getAddressOfOtpMemoryBlock(int blockNr) { return (char*)(0x1fff7800 + blockNr * 0x20); @@ -45,7 +50,7 @@ static char* getAddressOfOtpMemoryBlock(int blockNr) { -void platformInfoGetPlatformString(char* buf) { +void platformGetDeviceTypeString(char* deviceTypeString) { char* block = 0; for (int i = 0; i < PLATFORM_INFO_OTP_NR_OF_BLOCKS; i++) { @@ -60,6 +65,6 @@ void platformInfoGetPlatformString(char* buf) { block = DEFAULT_PLATFORM_STRING; } - strncpy(buf, block, PLATFORM_INFO_OTP_BLOCK_LEN); - buf[PLATFORM_INFO_OTP_BLOCK_LEN] = '\0'; + strncpy(deviceTypeString, block, PLATFORM_INFO_OTP_BLOCK_LEN); + deviceTypeString[PLATFORM_INFO_OTP_BLOCK_LEN] = '\0'; } diff --git a/test/platform/Test_platform.c b/test/platform/Test_platform.c new file mode 100644 index 0000000000..c6a17065d6 --- /dev/null +++ b/test/platform/Test_platform.c @@ -0,0 +1,85 @@ +// File under test platform.c +#include "platform.h" + +#include "unity.h" +#include + + +static char actualDeviceType[100]; + +void setUp(void) { + strcpy(actualDeviceType, "abcdefghijklmn"); +} + +void tearDown(void) { + // Empty +} + +void testThatDeviceTypeStringIsReturned() { + // Fixture + const char* deviceTypeString = "0;CF20"; + + // Test + int actual = platformParseDeviceTypeString(deviceTypeString, actualDeviceType); + + // Assert + TEST_ASSERT_EQUAL_STRING("CF20", actualDeviceType); + TEST_ASSERT_EQUAL(0, actual); +} + +void testThatDeviceTypeStringIsReturnedWithTrailingSemiColonAndKeyValues() { + // Fixture + const char* deviceTypeString = "0;CF21;R=C"; + + // Test + int actual = platformParseDeviceTypeString(deviceTypeString, actualDeviceType); + + // Assert + TEST_ASSERT_EQUAL_STRING("CF21", actualDeviceType); + TEST_ASSERT_EQUAL(0, actual); +} + +void testThatDeviceTypeStringIsReturnedWhenTypeIdentifierIsShorterThan4Chars() { + // Fixture + const char* deviceTypeString = "0;AB;R=C"; + + // Test + int actual = platformParseDeviceTypeString(deviceTypeString, actualDeviceType); + + // Assert + TEST_ASSERT_EQUAL_STRING("AB", actualDeviceType); + TEST_ASSERT_EQUAL(0, actual); +} + +void testThatDeviceTypeIsNotReturnedWhenTypeIdentifierIsTooLong() { + // Fixture + const char* deviceTypeString = "0;CF21XXX;R=C"; + + // Test + int actual = platformParseDeviceTypeString(deviceTypeString, actualDeviceType); + + // Assert + TEST_ASSERT_NOT_EQUAL(0, actual); +} + +void testThatDeviceTypeIsNotReturnedIfVersionIfNot0() { + // Fixture + const char* deviceTypeString = "1;CF21"; + + // Test + int actual = platformParseDeviceTypeString(deviceTypeString, actualDeviceType); + + // Assert + TEST_ASSERT_NOT_EQUAL(0, actual); +} + +void testThatDeviceTypeIsNotReturnedIfSecondCharIsNotSemicolon() { + // Fixture + const char* deviceTypeString = "0+CF21"; + + // Test + int actual = platformParseDeviceTypeString(deviceTypeString, actualDeviceType); + + // Assert + TEST_ASSERT_NOT_EQUAL(0, actual); +} diff --git a/test/drivers/src/Test_platform_info_stm32.c b/test/platform/Test_platform_stm32.c similarity index 77% rename from test/drivers/src/Test_platform_info_stm32.c rename to test/platform/Test_platform_stm32.c index c9cf102f0d..bd0b581619 100644 --- a/test/drivers/src/Test_platform_info_stm32.c +++ b/test/platform/Test_platform_stm32.c @@ -1,9 +1,14 @@ -// File under test platform_info_stm32.h -#include "platform_info_stm32.h" +// File under test platform_stm32.c + +// @MODULE "platform_stm32.c" +#include "platform.h" // @NO_MODULE #include "unity.h" #include + +#define PLATFORM_INFO_OTP_NR_OF_BLOCKS 16 +#define PLATFORM_INFO_OTP_BLOCK_LEN 32 static char mockOtpBlocks[PLATFORM_INFO_OTP_NR_OF_BLOCKS][PLATFORM_INFO_OTP_BLOCK_LEN]; static void fixtureInitOtpBlocks(); @@ -22,10 +27,10 @@ void testThatFirstBlockIsReturnedIfSet() { // Fixture fixtureSetOtpBlockString(0, "0;CF21"); - char actual[PLATFORM_INFO_MAX_PLATFORM_STRING_LEN]; + char actual[PLATFORM_DEVICE_TYPE_STRING_MAX_LEN]; // Test - platformInfoGetPlatformString(actual); + platformGetDeviceTypeString(actual); // Assert TEST_ASSERT_EQUAL_STRING("0;CF21", actual); @@ -38,10 +43,10 @@ void testThatLAterBlockIsReturnedIfEarlierBlockAreCleared() { fixtureClearOtpBlock(2); fixtureSetOtpBlockString(3, "0;CF21"); - char actual[PLATFORM_INFO_MAX_PLATFORM_STRING_LEN]; + char actual[PLATFORM_DEVICE_TYPE_STRING_MAX_LEN]; // Test - platformInfoGetPlatformString(actual); + platformGetDeviceTypeString(actual); // Assert TEST_ASSERT_EQUAL_STRING("0;CF21", actual); @@ -49,10 +54,10 @@ void testThatLAterBlockIsReturnedIfEarlierBlockAreCleared() { void testThatDefaultPlatformStringIsCF20IfNoInfoIsSet() { // Fixture - char actual[PLATFORM_INFO_MAX_PLATFORM_STRING_LEN]; + char actual[PLATFORM_DEVICE_TYPE_STRING_MAX_LEN]; // Test - platformInfoGetPlatformString(actual); + platformGetDeviceTypeString(actual); // Assert TEST_ASSERT_EQUAL_STRING("0;CF20", actual); @@ -62,10 +67,10 @@ void testThatDefaultPlatformStringIsCF20IfAllBlocksAreCleared() { // Fixture memset(mockOtpBlocks, 0x00, sizeof(mockOtpBlocks)); - char actual[PLATFORM_INFO_MAX_PLATFORM_STRING_LEN]; + char actual[PLATFORM_DEVICE_TYPE_STRING_MAX_LEN]; // Test - platformInfoGetPlatformString(actual); + platformGetDeviceTypeString(actual); // Assert TEST_ASSERT_EQUAL_STRING("0;CF20", actual); @@ -79,7 +84,7 @@ void testThatNoMoreThanTheBlockSizeIsCopiedIfTheBlockIsNotNullTerminated() { char actual[100]; // Test - platformInfoGetPlatformString(actual); + platformGetDeviceTypeString(actual); // Assert TEST_ASSERT_EQUAL_STRING("01234567890123456789012345678901", actual); diff --git a/tools/test/gcc.yml b/tools/test/gcc.yml index 91d55a55a8..48eaeedd90 100644 --- a/tools/test/gcc.yml +++ b/tools/test/gcc.yml @@ -36,6 +36,7 @@ compiler: - 'src/drivers/src/' - 'src/modules/interface/' - 'src/modules/src/' + - 'src/platform/' - 'src/lib/FreeRTOS/portable/GCC/ARM_CM4F/' - 'src/hal/interface/' - 'test/testSupport/' diff --git a/tools/test/rakefile_helper.rb b/tools/test/rakefile_helper.rb index f1855ad50c..303a68d591 100644 --- a/tools/test/rakefile_helper.rb +++ b/tools/test/rakefile_helper.rb @@ -40,9 +40,20 @@ def extract_headers(filename) includes = [] lines = File.readlines(filename) lines.each do |line| + # Check if there is an include that we should add m = line.match(/^\s*#include\s+\"\s*(.+\.[hH])\s*\"/) if not m.nil? - includes << m[1] + if !line.include? "@NO_MODULE" + includes << m[1] + end + end + + # Check if there is a module to add based on an annotation + m = line.match(/^\/\/\s*@MODULE\s+\"\s*(.+\.)[cC]\s*\"/) + if not m.nil? + # Fake that it is a .h file + h_file_name = m[1] + 'h' + includes << h_file_name end end return includes @@ -199,8 +210,9 @@ def run_tests(test_files, defines) test_files.each do |test| obj_list = [] - # Detect dependencies and build required required modules + # Detect dependencies and build required modules header_list = extract_headers(test) + ['cmock.h'] + header_list.each do |header| #create mocks if needed