diff --git a/.gitignore b/.gitignore index 1dbc687d..4f119819 100644 --- a/.gitignore +++ b/.gitignore @@ -8,21 +8,21 @@ __pycache__/ # Distribution / packaging .Python -env/ -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -*.egg-info/ -.installed.cfg -*.egg +#env/ +#build/ +#develop-eggs/ +#dist/ +#downloads/ +#eggs/ +#.eggs/ +#lib/ +#lib64/ +#parts/ +#sdist/ +#var/ +#*.egg-info/ +#.installed.cfg +#*.egg # PyInstaller # Usually these files are written by a python script from a template @@ -60,3 +60,6 @@ target/ #Ipython Notebook .ipynb_checkpoints + +# Tup +.tup diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..531bce18 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,31 @@ +# adapted from https://github.com/andysworkshop/stm32plus/blob/master/.travis.yml + +language: c +sudo: false + +addons: + apt: + packages: + libc6-i386 + +cache: + directories: + - $HOME/dl + +install: + - export GCC_DIR=$HOME/dl/gcc-arm-none-eabi-5_2-2015q4 + - export GCC_ARCHIVE=$HOME/dl/gcc-arm-none-eabi-5_2-2015q4-20151219-linux.tar.bz2 + - export GCC_URL=https://launchpad.net/gcc-arm-embedded/5.0/5-2015-q4-major/+download/gcc-arm-none-eabi-5_2-2015q4-20151219-linux.tar.bz2 + - if [ ! -e $GCC_DIR/bin/arm-none-eabi-gcc ]; then wget $GCC_URL -O $GCC_ARCHIVE; tar xfj $GCC_ARCHIVE -C $HOME/dl; fi + - export PATH=$PATH:$GCC_DIR/bin + - export TUP_DIR=$HOME/dl/tup_0.7.2.12+ga582fee_amd64 + - export TUP_ARCHIVE=$HOME/dl/tup_0.7.2.12+ga582fee_amd64.deb + - export TUP_URL=http://ppa.launchpad.net/anatol/tup/ubuntu/pool/main/t/tup/tup_0.7.2.12+ga582fee_amd64.deb + - if [ ! -e $TUP_DIR/bin/tup ]; then wget $TUP_URL -O $TUP_ARCHIVE; dpkg-deb -R $TUP_ARCHIVE $TUP_DIR; fi + - export PATH=$PATH:$TUP_DIR/usr/bin + +script: + - cd Firmware + - mkdir -p build + - tup generate ./build.sh + - bash -xe ./build.sh diff --git a/Firmware/.vscode/c_cpp_properties.json b/Firmware/.vscode/c_cpp_properties.json index 691314ac..b337bc20 100644 --- a/Firmware/.vscode/c_cpp_properties.json +++ b/Firmware/.vscode/c_cpp_properties.json @@ -4,136 +4,114 @@ "name": "Win32", "includePath": [ "${workspaceRoot}", - "${workspaceRoot}/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F", - "${workspaceRoot}/Middlewares/Third_Party/FreeRTOS/Source/include", - "${workspaceRoot}/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS", - "${workspaceRoot}/Drivers/DRV8301", - "${workspaceRoot}/Middlewares/ST/STM32_USB_Device_Library/Core/Inc", - "${workspaceRoot}/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc", - "${workspaceRoot}/Drivers/STM32F4xx_HAL_Driver/Inc", - "${workspaceRoot}/Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", - "${workspaceRoot}/Drivers/CMSIS/Device/ST/STM32F4xx/Include", - "${workspaceRoot}/Drivers/CMSIS/Include", - "${workspaceRoot}/Inc", "${workspaceRoot}/MotorControl", - "C:/Program Files (x86)/GNU Tools ARM Embedded/6 2017-q1-update/arm-none-eabi/include/c++/6.3.1", - "C:/Program Files (x86)/GNU Tools ARM Embedded/6 2017-q1-update/arm-none-eabi/include/c++/6.3.1/arm-none-eabi", - "C:/Program Files (x86)/GNU Tools ARM Embedded/6 2017-q1-update/lib/gcc/arm-none-eabi/6.3.1/include", - "C:/Program Files (x86)/GNU Tools ARM Embedded/6 2017-q1-update/arm-none-eabi/include" + "${workspaceRoot}/Board/v3.3/Inc", + "${workspaceRoot}/Board/v3.3/Drivers/CMSIS/Include", + "${workspaceRoot}/Board/v3.3/Drivers/CMSIS/Device/ST/STM32F4xx/Include", + "${workspaceRoot}/Board/v3.3/Drivers/DRV8301", + "${workspaceRoot}/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc", + "${workspaceRoot}/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", + "${workspaceRoot}/Board/v3.3/Middlewares/ST/STM32_USB_Device_Library/Core/Inc", + "${workspaceRoot}/Board/v3.3/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc", + "${workspaceRoot}/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS", + "${workspaceRoot}/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/include", + "${workspaceRoot}/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F", + "c:/program files (x86)/gnu tools arm embedded/6 2017-q1-update/arm-none-eabi/include/c++/6.3.1", + "c:/program files (x86)/gnu tools arm embedded/6 2017-q1-update/arm-none-eabi/include/c++/6.3.1/arm-none-eabi", + "c:/program files (x86)/gnu tools arm embedded/6 2017-q1-update/arm-none-eabi/include/c++/6.3.1/backward", + "c:/program files (x86)/gnu tools arm embedded/6 2017-q1-update/lib/gcc/arm-none-eabi/6.3.1/include", + "c:/program files (x86)/gnu tools arm embedded/6 2017-q1-update/lib/gcc/arm-none-eabi/6.3.1/include-fixed", + "c:/program files (x86)/gnu tools arm embedded/6 2017-q1-update/arm-none-eabi/include" ], "defines": [ - "_DEBUG", - "UNICODE" + "STM32F405xx", + "USE_HAL_DRIVER", + "__weak=\"__attribute__((weak))\"", + "__packed=\"__attribute__((__packed__))\"", + "__GNUC__" ], "intelliSenseMode": "clang-x64", "browse": { "path": [ "${workspaceRoot}", - "${workspaceRoot}/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F", - "${workspaceRoot}/Middlewares/Third_Party/FreeRTOS/Source/include", - "${workspaceRoot}/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS", - "${workspaceRoot}/Drivers/DRV8301", - "${workspaceRoot}/Middlewares/ST/STM32_USB_Device_Library/Core/Inc", - "${workspaceRoot}/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc", - "${workspaceRoot}/Drivers/STM32F4xx_HAL_Driver/Inc", - "${workspaceRoot}/Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", - "${workspaceRoot}/Drivers/CMSIS/Device/ST/STM32F4xx/Include", - "${workspaceRoot}/Drivers/CMSIS/Include", - "${workspaceRoot}/Inc", - "${workspaceRoot}/MotorControl" + "C:/Program Files (x86)/GNU Tools ARM Embedded" ], - "limitSymbolsToIncludedHeaders": true, - "databaseFilename": "" + "limitSymbolsToIncludedHeaders": true } }, - { - "name": "Linux", - "includePath": [ - "${workspaceRoot}", - "${workspaceRoot}/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F", - "${workspaceRoot}/Middlewares/Third_Party/FreeRTOS/Source/include", - "${workspaceRoot}/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS", - "${workspaceRoot}/Drivers/DRV8301", - "${workspaceRoot}/Middlewares/ST/STM32_USB_Device_Library/Core/Inc", - "${workspaceRoot}/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc", - "${workspaceRoot}/Drivers/STM32F4xx_HAL_Driver/Inc", - "${workspaceRoot}/Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", - "${workspaceRoot}/Drivers/CMSIS/Device/ST/STM32F4xx/Include", - "${workspaceRoot}/Drivers/CMSIS/Include", - "${workspaceRoot}/Inc", - "${workspaceRoot}/MotorControl", - "/usr/lib/gcc/arm-none-eabi/4.9.3/include", - "/usr/lib/arm-none-eabi/include" - ], - "defines": [ - "_DEBUG", - "UNICODE" - ], - "intelliSenseMode": "clang-x64", - "browse": { - "path": [ + { + "name": "Linux", + "includePath": [ + "${workspaceRoot}", + "${workspaceRoot}/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F", + "${workspaceRoot}/Middlewares/Third_Party/FreeRTOS/Source/include", + "${workspaceRoot}/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS", + "${workspaceRoot}/Drivers/DRV8301", + "${workspaceRoot}/Middlewares/ST/STM32_USB_Device_Library/Core/Inc", + "${workspaceRoot}/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc", + "${workspaceRoot}/Drivers/STM32F4xx_HAL_Driver/Inc", + "${workspaceRoot}/Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", + "${workspaceRoot}/Drivers/CMSIS/Device/ST/STM32F4xx/Include", + "${workspaceRoot}/Drivers/CMSIS/Include", + "${workspaceRoot}/Inc", + "${workspaceRoot}/MotorControl", + "/usr/lib/gcc/arm-none-eabi/4.9.3/include", + "/usr/lib/arm-none-eabi/include" + ], + "defines": [ + "STM32F405xx", + "USE_HAL_DRIVER", + "__weak=\"__attribute__((weak))\"", + "__packed=\"__attribute__((__packed__))\"", + "__GNUC__" + ], + "intelliSenseMode": "clang-x64", + "browse": { + "path": [ "${workspaceRoot}", - "${workspaceRoot}/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F", - "${workspaceRoot}/Middlewares/Third_Party/FreeRTOS/Source/include", - "${workspaceRoot}/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS", - "${workspaceRoot}/Drivers/DRV8301", - "${workspaceRoot}/Middlewares/ST/STM32_USB_Device_Library/Core/Inc", - "${workspaceRoot}/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc", - "${workspaceRoot}/Drivers/STM32F4xx_HAL_Driver/Inc", - "${workspaceRoot}/Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", - "${workspaceRoot}/Drivers/CMSIS/Device/ST/STM32F4xx/Include", - "${workspaceRoot}/Drivers/CMSIS/Include", - "${workspaceRoot}/Inc", - "${workspaceRoot}/MotorControl" - ], - "limitSymbolsToIncludedHeaders": true, - "databaseFilename": "" - } - }, - { - "name": "MacOS", - "includePath": [ - "${workspaceRoot}", - "${workspaceRoot}/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F", - "${workspaceRoot}/Middlewares/Third_Party/FreeRTOS/Source/include", - "${workspaceRoot}/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS", - "${workspaceRoot}/Drivers/DRV8301", - "${workspaceRoot}/Middlewares/ST/STM32_USB_Device_Library/Core/Inc", - "${workspaceRoot}/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc", - "${workspaceRoot}/Drivers/STM32F4xx_HAL_Driver/Inc", - "${workspaceRoot}/Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", - "${workspaceRoot}/Drivers/CMSIS/Device/ST/STM32F4xx/Include", - "${workspaceRoot}/Drivers/CMSIS/Include", - "${workspaceRoot}/Inc", - "${workspaceRoot}/MotorControl", - "/usr/local/Caskroom/gcc-arm-embedded/6-2017-q2-update/gcc-arm-none-eabi-6-2017-q2-update/arm-none-eabi/include", - "/usr/local/Caskroom/gcc-arm-embedded/6-2017-q2-update/gcc-arm-none-eabi-6-2017-q2-update/arm-none-eabi/include/c++/6.3.1", - "/usr/local/Caskroom/gcc-arm-embedded/6-2017-q2-update/gcc-arm-none-eabi-6-2017-q2-update/arm-none-eabi/include/c++/6.3.1/arm-none-eabi", - "/usr/local/Caskroom/gcc-arm-embedded/6-2017-q2-update/gcc-arm-none-eabi-6-2017-q2-update/lib/gcc/arm-none-eabi/6.3.1/include" - ], - "defines": [ - "_DEBUG", - "UNICODE" - ], - "intelliSenseMode": "clang-x64", - "browse": { - "path": [ + "/usr/lib/gcc/arm-none-eabi/4.9.3/include", + "/usr/lib/arm-none-eabi/include" + ], + "limitSymbolsToIncludedHeaders": true, + "databaseFilename": "" + } + }, + { + "name": "Mac", + "includePath": [ + "${workspaceRoot}", + "${workspaceRoot}/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F", + "${workspaceRoot}/Middlewares/Third_Party/FreeRTOS/Source/include", + "${workspaceRoot}/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS", + "${workspaceRoot}/Drivers/DRV8301", + "${workspaceRoot}/Middlewares/ST/STM32_USB_Device_Library/Core/Inc", + "${workspaceRoot}/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc", + "${workspaceRoot}/Drivers/STM32F4xx_HAL_Driver/Inc", + "${workspaceRoot}/Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", + "${workspaceRoot}/Drivers/CMSIS/Device/ST/STM32F4xx/Include", + "${workspaceRoot}/Drivers/CMSIS/Include", + "${workspaceRoot}/Inc", + "${workspaceRoot}/MotorControl", + "/usr/local/Caskroom/gcc-arm-embedded/6-2017-q2-update/gcc-arm-none-eabi-6-2017-q2-update/arm-none-eabi/include", + "/usr/local/Caskroom/gcc-arm-embedded/6-2017-q2-update/gcc-arm-none-eabi-6-2017-q2-update/arm-none-eabi/include/c++/6.3.1", + "/usr/local/Caskroom/gcc-arm-embedded/6-2017-q2-update/gcc-arm-none-eabi-6-2017-q2-update/arm-none-eabi/include/c++/6.3.1/arm-none-eabi", + "/usr/local/Caskroom/gcc-arm-embedded/6-2017-q2-update/gcc-arm-none-eabi-6-2017-q2-update/lib/gcc/arm-none-eabi/6.3.1/include" + ], + "defines": [ + "STM32F405xx", + "USE_HAL_DRIVER", + "__weak=\"__attribute__((weak))\"", + "__packed=\"__attribute__((__packed__))\"", + "__GNUC__" + ], + "intelliSenseMode": "clang-x64", + "browse": { + "path": [ "${workspaceRoot}", - "${workspaceRoot}/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F", - "${workspaceRoot}/Middlewares/Third_Party/FreeRTOS/Source/include", - "${workspaceRoot}/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS", - "${workspaceRoot}/Drivers/DRV8301", - "${workspaceRoot}/Middlewares/ST/STM32_USB_Device_Library/Core/Inc", - "${workspaceRoot}/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc", - "${workspaceRoot}/Drivers/STM32F4xx_HAL_Driver/Inc", - "${workspaceRoot}/Drivers/STM32F4xx_HAL_Driver/Inc/Legacy", - "${workspaceRoot}/Drivers/CMSIS/Device/ST/STM32F4xx/Include", - "${workspaceRoot}/Drivers/CMSIS/Include", - "${workspaceRoot}/Inc", - "${workspaceRoot}/MotorControl" - ], - "limitSymbolsToIncludedHeaders": true, - "databaseFilename": "" + "/usr/local/Caskroom/gcc-arm-embedded/" + ], + "limitSymbolsToIncludedHeaders": true, + "databaseFilename": "" } } ], diff --git a/Firmware/.vscode/settings.json b/Firmware/.vscode/settings.json index 8f45c82a..63c1463b 100644 --- a/Firmware/.vscode/settings.json +++ b/Firmware/.vscode/settings.json @@ -1,5 +1,7 @@ { "C_Cpp.clang_format_style": "{ BasedOnStyle: Google, IndentWidth: 4, ColumnLimit: 0 }", + "C_Cpp.intelliSenseEngine": "Default", + "C_Cpp.intelliSenseEngineFallback": "Disabled", "files.exclude": { "build": true }, diff --git a/Firmware/.vscode/tasks.json b/Firmware/.vscode/tasks.json index 33956da9..2376b650 100644 --- a/Firmware/.vscode/tasks.json +++ b/Firmware/.vscode/tasks.json @@ -6,7 +6,7 @@ { "taskName": "build", "type": "shell", - "command": "make -j4", + "command": "make", "group": { "kind": "build", "isDefault": true diff --git a/Firmware/Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f405xx.h b/Firmware/Board/v3.3/Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f405xx.h similarity index 100% rename from Firmware/Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f405xx.h rename to Firmware/Board/v3.3/Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f405xx.h diff --git a/Firmware/Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h b/Firmware/Board/v3.3/Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h similarity index 100% rename from Firmware/Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h rename to Firmware/Board/v3.3/Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h diff --git a/Firmware/Drivers/CMSIS/Device/ST/STM32F4xx/Include/system_stm32f4xx.h b/Firmware/Board/v3.3/Drivers/CMSIS/Device/ST/STM32F4xx/Include/system_stm32f4xx.h similarity index 100% rename from Firmware/Drivers/CMSIS/Device/ST/STM32F4xx/Include/system_stm32f4xx.h rename to Firmware/Board/v3.3/Drivers/CMSIS/Device/ST/STM32F4xx/Include/system_stm32f4xx.h diff --git a/Firmware/Drivers/CMSIS/Include/arm_common_tables.h b/Firmware/Board/v3.3/Drivers/CMSIS/Include/arm_common_tables.h similarity index 100% rename from Firmware/Drivers/CMSIS/Include/arm_common_tables.h rename to Firmware/Board/v3.3/Drivers/CMSIS/Include/arm_common_tables.h diff --git a/Firmware/Drivers/CMSIS/Include/arm_const_structs.h b/Firmware/Board/v3.3/Drivers/CMSIS/Include/arm_const_structs.h similarity index 100% rename from Firmware/Drivers/CMSIS/Include/arm_const_structs.h rename to Firmware/Board/v3.3/Drivers/CMSIS/Include/arm_const_structs.h diff --git a/Firmware/Drivers/CMSIS/Include/arm_math.h b/Firmware/Board/v3.3/Drivers/CMSIS/Include/arm_math.h similarity index 100% rename from Firmware/Drivers/CMSIS/Include/arm_math.h rename to Firmware/Board/v3.3/Drivers/CMSIS/Include/arm_math.h diff --git a/Firmware/Drivers/CMSIS/Include/cmsis_armcc.h b/Firmware/Board/v3.3/Drivers/CMSIS/Include/cmsis_armcc.h similarity index 100% rename from Firmware/Drivers/CMSIS/Include/cmsis_armcc.h rename to Firmware/Board/v3.3/Drivers/CMSIS/Include/cmsis_armcc.h diff --git a/Firmware/Drivers/CMSIS/Include/cmsis_armcc_V6.h b/Firmware/Board/v3.3/Drivers/CMSIS/Include/cmsis_armcc_V6.h similarity index 100% rename from Firmware/Drivers/CMSIS/Include/cmsis_armcc_V6.h rename to Firmware/Board/v3.3/Drivers/CMSIS/Include/cmsis_armcc_V6.h diff --git a/Firmware/Drivers/CMSIS/Include/cmsis_gcc.h b/Firmware/Board/v3.3/Drivers/CMSIS/Include/cmsis_gcc.h similarity index 100% rename from Firmware/Drivers/CMSIS/Include/cmsis_gcc.h rename to Firmware/Board/v3.3/Drivers/CMSIS/Include/cmsis_gcc.h diff --git a/Firmware/Drivers/CMSIS/Include/core_cm0.h b/Firmware/Board/v3.3/Drivers/CMSIS/Include/core_cm0.h similarity index 100% rename from Firmware/Drivers/CMSIS/Include/core_cm0.h rename to Firmware/Board/v3.3/Drivers/CMSIS/Include/core_cm0.h diff --git a/Firmware/Drivers/CMSIS/Include/core_cm0plus.h b/Firmware/Board/v3.3/Drivers/CMSIS/Include/core_cm0plus.h similarity index 100% rename from Firmware/Drivers/CMSIS/Include/core_cm0plus.h rename to Firmware/Board/v3.3/Drivers/CMSIS/Include/core_cm0plus.h diff --git a/Firmware/Drivers/CMSIS/Include/core_cm3.h b/Firmware/Board/v3.3/Drivers/CMSIS/Include/core_cm3.h similarity index 100% rename from Firmware/Drivers/CMSIS/Include/core_cm3.h rename to Firmware/Board/v3.3/Drivers/CMSIS/Include/core_cm3.h diff --git a/Firmware/Drivers/CMSIS/Include/core_cm4.h b/Firmware/Board/v3.3/Drivers/CMSIS/Include/core_cm4.h similarity index 100% rename from Firmware/Drivers/CMSIS/Include/core_cm4.h rename to Firmware/Board/v3.3/Drivers/CMSIS/Include/core_cm4.h diff --git a/Firmware/Drivers/CMSIS/Include/core_cm7.h b/Firmware/Board/v3.3/Drivers/CMSIS/Include/core_cm7.h similarity index 100% rename from Firmware/Drivers/CMSIS/Include/core_cm7.h rename to Firmware/Board/v3.3/Drivers/CMSIS/Include/core_cm7.h diff --git a/Firmware/Drivers/CMSIS/Include/core_cmFunc.h b/Firmware/Board/v3.3/Drivers/CMSIS/Include/core_cmFunc.h similarity index 100% rename from Firmware/Drivers/CMSIS/Include/core_cmFunc.h rename to Firmware/Board/v3.3/Drivers/CMSIS/Include/core_cmFunc.h diff --git a/Firmware/Drivers/CMSIS/Include/core_cmInstr.h b/Firmware/Board/v3.3/Drivers/CMSIS/Include/core_cmInstr.h similarity index 100% rename from Firmware/Drivers/CMSIS/Include/core_cmInstr.h rename to Firmware/Board/v3.3/Drivers/CMSIS/Include/core_cmInstr.h diff --git a/Firmware/Drivers/CMSIS/Include/core_cmSimd.h b/Firmware/Board/v3.3/Drivers/CMSIS/Include/core_cmSimd.h similarity index 100% rename from Firmware/Drivers/CMSIS/Include/core_cmSimd.h rename to Firmware/Board/v3.3/Drivers/CMSIS/Include/core_cmSimd.h diff --git a/Firmware/Drivers/CMSIS/Include/core_sc000.h b/Firmware/Board/v3.3/Drivers/CMSIS/Include/core_sc000.h similarity index 100% rename from Firmware/Drivers/CMSIS/Include/core_sc000.h rename to Firmware/Board/v3.3/Drivers/CMSIS/Include/core_sc000.h diff --git a/Firmware/Drivers/CMSIS/Include/core_sc300.h b/Firmware/Board/v3.3/Drivers/CMSIS/Include/core_sc300.h similarity index 100% rename from Firmware/Drivers/CMSIS/Include/core_sc300.h rename to Firmware/Board/v3.3/Drivers/CMSIS/Include/core_sc300.h diff --git a/Firmware/Drivers/CMSIS/Lib/libarm_cortexM4lf_math.a b/Firmware/Board/v3.3/Drivers/CMSIS/Lib/libarm_cortexM4lf_math.a similarity index 100% rename from Firmware/Drivers/CMSIS/Lib/libarm_cortexM4lf_math.a rename to Firmware/Board/v3.3/Drivers/CMSIS/Lib/libarm_cortexM4lf_math.a diff --git a/Firmware/Drivers/DRV8301/drv8301.c b/Firmware/Board/v3.3/Drivers/DRV8301/drv8301.c similarity index 98% rename from Firmware/Drivers/DRV8301/drv8301.c rename to Firmware/Board/v3.3/Drivers/DRV8301/drv8301.c index db3a8081..0e90a652 100644 --- a/Firmware/Drivers/DRV8301/drv8301.c +++ b/Firmware/Board/v3.3/Drivers/DRV8301/drv8301.c @@ -45,6 +45,8 @@ // drivers #include "drv8301.h" +#include "utils.h" + // ************************************************************************** // the defines @@ -362,7 +364,7 @@ uint16_t DRV8301_readSpi(DRV8301_Handle handle, const DRV8301_RegName_e regName) // Actuate chipselect HAL_GPIO_WritePin(handle->nCSgpioHandle, handle->nCSgpioNumber, GPIO_PIN_RESET); - osDelay(1); + delay_us(1); // Do blocking read uint16_t zerobuff = 0; @@ -374,17 +376,17 @@ uint16_t DRV8301_readSpi(DRV8301_Handle handle, const DRV8301_RegName_e regName) // but for some reason you actually need to pulse it. // Actuate chipselect HAL_GPIO_WritePin(handle->nCSgpioHandle, handle->nCSgpioNumber, GPIO_PIN_SET); - osDelay(1); + delay_us(1); // Actuate chipselect HAL_GPIO_WritePin(handle->nCSgpioHandle, handle->nCSgpioNumber, GPIO_PIN_RESET); - osDelay(1); + delay_us(1); HAL_SPI_TransmitReceive(handle->spiHandle, (uint8_t*)(&zerobuff), (uint8_t*)(&recbuff), 1, 1000); - osDelay(1); + delay_us(1); // Actuate chipselect HAL_GPIO_WritePin(handle->nCSgpioHandle, handle->nCSgpioNumber, GPIO_PIN_SET); - osDelay(1); + delay_us(1); assert(recbuff != 0xbeef); @@ -590,16 +592,16 @@ void DRV8301_writeSpi(DRV8301_Handle handle, const DRV8301_RegName_e regName,con { // Actuate chipselect HAL_GPIO_WritePin(handle->nCSgpioHandle, handle->nCSgpioNumber, GPIO_PIN_RESET); - osDelay(1); + delay_us(1); // Do blocking write uint16_t controlword = (uint16_t)DRV8301_buildCtrlWord(DRV8301_CtrlMode_Write, regName, data); HAL_SPI_Transmit(handle->spiHandle, (uint8_t*)(&controlword), 1, 1000); - osDelay(1); + delay_us(1); // Actuate chipselect HAL_GPIO_WritePin(handle->nCSgpioHandle, handle->nCSgpioNumber, GPIO_PIN_SET); - osDelay(1); + delay_us(1); return; } // end of DRV8301_writeSpi() function @@ -659,12 +661,14 @@ void DRV8301_readData(DRV8301_Handle handle, DRV_SPI_8301_Vars_t *Spi_8301_Vars) Spi_8301_Vars->Stat_Reg_1.FETLB_OC = (bool)(drvDataNew & (uint16_t)DRV8301_STATUS1_FETLB_OC_BITS); Spi_8301_Vars->Stat_Reg_1.FETHC_OC = (bool)(drvDataNew & (uint16_t)DRV8301_STATUS1_FETHC_OC_BITS); Spi_8301_Vars->Stat_Reg_1.FETLC_OC = (bool)(drvDataNew & (uint16_t)DRV8301_STATUS1_FETLC_OC_BITS); + Spi_8301_Vars->Stat_Reg_1_Value = drvDataNew; // Update Status Register 2 drvRegName = DRV8301_RegName_Status_2; drvDataNew = DRV8301_readSpi(handle,drvRegName); Spi_8301_Vars->Stat_Reg_2.GVDD_OV = (bool)(drvDataNew & (uint16_t)DRV8301_STATUS2_GVDD_OV_BITS); Spi_8301_Vars->Stat_Reg_2.DeviceID = (uint16_t)(drvDataNew & (uint16_t)DRV8301_STATUS2_ID_BITS); + Spi_8301_Vars->Stat_Reg_2_Value = drvDataNew; // Update Control Register 1 drvRegName = DRV8301_RegName_Control_1; @@ -674,6 +678,7 @@ void DRV8301_readData(DRV8301_Handle handle, DRV_SPI_8301_Vars_t *Spi_8301_Vars) Spi_8301_Vars->Ctrl_Reg_1.PWM_MODE = (DRV8301_PwmMode_e)(drvDataNew & (uint16_t)DRV8301_CTRL1_PWM_MODE_BITS); Spi_8301_Vars->Ctrl_Reg_1.OC_MODE = (DRV8301_OcMode_e)(drvDataNew & (uint16_t)DRV8301_CTRL1_OC_MODE_BITS); Spi_8301_Vars->Ctrl_Reg_1.OC_ADJ_SET = (DRV8301_VdsLevel_e)(drvDataNew & (uint16_t)DRV8301_CTRL1_OC_ADJ_SET_BITS); + Spi_8301_Vars->Ctrl_Reg_1_Value = drvDataNew; // Update Control Register 2 drvRegName = DRV8301_RegName_Control_2; @@ -682,7 +687,7 @@ void DRV8301_readData(DRV8301_Handle handle, DRV_SPI_8301_Vars_t *Spi_8301_Vars) Spi_8301_Vars->Ctrl_Reg_2.GAIN = (DRV8301_ShuntAmpGain_e)(drvDataNew & (uint16_t)DRV8301_CTRL2_GAIN_BITS); Spi_8301_Vars->Ctrl_Reg_2.DC_CAL_CH1p2 = (DRV8301_DcCalMode_e)(drvDataNew & (uint16_t)(DRV8301_CTRL2_DC_CAL_1_BITS | DRV8301_CTRL2_DC_CAL_2_BITS)); Spi_8301_Vars->Ctrl_Reg_2.OC_TOFF = (DRV8301_OcOffTimeMode_e)(drvDataNew & (uint16_t)DRV8301_CTRL2_OC_TOFF_BITS); - + Spi_8301_Vars->Ctrl_Reg_2_Value = drvDataNew; Spi_8301_Vars->RcvCmd = false; } diff --git a/Firmware/Drivers/DRV8301/drv8301.h b/Firmware/Board/v3.3/Drivers/DRV8301/drv8301.h similarity index 99% rename from Firmware/Drivers/DRV8301/drv8301.h rename to Firmware/Board/v3.3/Drivers/DRV8301/drv8301.h index bdf9fa50..e3c3e3f3 100644 --- a/Firmware/Drivers/DRV8301/drv8301.h +++ b/Firmware/Board/v3.3/Drivers/DRV8301/drv8301.h @@ -412,8 +412,13 @@ typedef struct _DRV_SPI_8301_Vars_t_ DRV_SPI_8301_Stat2_t_ Stat_Reg_2; DRV_SPI_8301_CTRL1_t_ Ctrl_Reg_1; DRV_SPI_8301_CTRL2_t_ Ctrl_Reg_2; + uint16_t Stat_Reg_1_Value; + uint16_t Stat_Reg_2_Value; + uint16_t Ctrl_Reg_1_Value; + uint16_t Ctrl_Reg_2_Value; bool SndCmd; bool RcvCmd; + }DRV_SPI_8301_Vars_t; diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc.h b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc.h similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc.h rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc.h diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc_ex.h b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc_ex.h similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc_ex.h rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc_ex.h diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_can.h b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_can.h similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_can.h rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_can.h diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cortex.h b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cortex.h similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cortex.h rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cortex.h diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_def.h b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_def.h similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_def.h rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_def.h diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma.h b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma.h similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma.h rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma.h diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma_ex.h b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma_ex.h similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma_ex.h rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma_ex.h diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash.h b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash.h similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash.h rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash.h diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ex.h b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ex.h similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ex.h rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ex.h diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ramfunc.h b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ramfunc.h similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ramfunc.h rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ramfunc.h diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio.h b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio.h similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio.h rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio.h diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio_ex.h b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio_ex.h similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio_ex.h rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio_ex.h diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd.h b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd.h similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd.h rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd.h diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd_ex.h b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd_ex.h similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd_ex.h rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd_ex.h diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr.h b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr.h similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr.h rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr.h diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr_ex.h b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr_ex.h similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr_ex.h rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr_ex.h diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc.h b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc.h similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc.h rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc.h diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc_ex.h b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc_ex.h similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc_ex.h rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc_ex.h diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spi.h b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spi.h similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spi.h rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spi.h diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim_ex.h b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim_ex.h similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim_ex.h rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim_ex.h diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usb.h b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usb.h similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usb.h rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usb.h diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc.c b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc.c similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc.c rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc.c diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc_ex.c b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc_ex.c similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc_ex.c rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc_ex.c diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_can.c b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_can.c similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_can.c rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_can.c diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.c b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.c similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.c rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.c diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spi.c b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spi.c similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spi.c rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spi.c diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c b/Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c similarity index 100% rename from Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c rename to Firmware/Board/v3.3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c diff --git a/Firmware/Inc/FreeRTOSConfig.h b/Firmware/Board/v3.3/Inc/FreeRTOSConfig.h similarity index 100% rename from Firmware/Inc/FreeRTOSConfig.h rename to Firmware/Board/v3.3/Inc/FreeRTOSConfig.h diff --git a/Firmware/Inc/adc.h b/Firmware/Board/v3.3/Inc/adc.h similarity index 100% rename from Firmware/Inc/adc.h rename to Firmware/Board/v3.3/Inc/adc.h diff --git a/Firmware/Inc/can.h b/Firmware/Board/v3.3/Inc/can.h similarity index 100% rename from Firmware/Inc/can.h rename to Firmware/Board/v3.3/Inc/can.h diff --git a/Firmware/Inc/dma.h b/Firmware/Board/v3.3/Inc/dma.h similarity index 100% rename from Firmware/Inc/dma.h rename to Firmware/Board/v3.3/Inc/dma.h diff --git a/Firmware/Inc/freertos_vars.h b/Firmware/Board/v3.3/Inc/freertos_vars.h similarity index 100% rename from Firmware/Inc/freertos_vars.h rename to Firmware/Board/v3.3/Inc/freertos_vars.h diff --git a/Firmware/Inc/gpio.h b/Firmware/Board/v3.3/Inc/gpio.h similarity index 100% rename from Firmware/Inc/gpio.h rename to Firmware/Board/v3.3/Inc/gpio.h diff --git a/Firmware/Inc/main.h b/Firmware/Board/v3.3/Inc/main.h similarity index 100% rename from Firmware/Inc/main.h rename to Firmware/Board/v3.3/Inc/main.h diff --git a/Firmware/Inc/mxconstants.h b/Firmware/Board/v3.3/Inc/mxconstants.h similarity index 100% rename from Firmware/Inc/mxconstants.h rename to Firmware/Board/v3.3/Inc/mxconstants.h diff --git a/Firmware/Inc/prev_board_ver/main_V3_2.h b/Firmware/Board/v3.3/Inc/prev_board_ver/main_V3_2.h similarity index 100% rename from Firmware/Inc/prev_board_ver/main_V3_2.h rename to Firmware/Board/v3.3/Inc/prev_board_ver/main_V3_2.h diff --git a/Firmware/Inc/spi.h b/Firmware/Board/v3.3/Inc/spi.h similarity index 100% rename from Firmware/Inc/spi.h rename to Firmware/Board/v3.3/Inc/spi.h diff --git a/Firmware/Inc/stm32f4xx_hal_conf.h b/Firmware/Board/v3.3/Inc/stm32f4xx_hal_conf.h similarity index 100% rename from Firmware/Inc/stm32f4xx_hal_conf.h rename to Firmware/Board/v3.3/Inc/stm32f4xx_hal_conf.h diff --git a/Firmware/Inc/stm32f4xx_it.h b/Firmware/Board/v3.3/Inc/stm32f4xx_it.h similarity index 100% rename from Firmware/Inc/stm32f4xx_it.h rename to Firmware/Board/v3.3/Inc/stm32f4xx_it.h diff --git a/Firmware/Inc/tim.h b/Firmware/Board/v3.3/Inc/tim.h similarity index 100% rename from Firmware/Inc/tim.h rename to Firmware/Board/v3.3/Inc/tim.h diff --git a/Firmware/Inc/usart.h b/Firmware/Board/v3.3/Inc/usart.h similarity index 100% rename from Firmware/Inc/usart.h rename to Firmware/Board/v3.3/Inc/usart.h diff --git a/Firmware/Inc/usb_device.h b/Firmware/Board/v3.3/Inc/usb_device.h similarity index 100% rename from Firmware/Inc/usb_device.h rename to Firmware/Board/v3.3/Inc/usb_device.h diff --git a/Firmware/Inc/usbd_cdc_if.h b/Firmware/Board/v3.3/Inc/usbd_cdc_if.h similarity index 100% rename from Firmware/Inc/usbd_cdc_if.h rename to Firmware/Board/v3.3/Inc/usbd_cdc_if.h diff --git a/Firmware/Inc/usbd_conf.h b/Firmware/Board/v3.3/Inc/usbd_conf.h similarity index 100% rename from Firmware/Inc/usbd_conf.h rename to Firmware/Board/v3.3/Inc/usbd_conf.h diff --git a/Firmware/Inc/usbd_desc.h b/Firmware/Board/v3.3/Inc/usbd_desc.h similarity index 100% rename from Firmware/Inc/usbd_desc.h rename to Firmware/Board/v3.3/Inc/usbd_desc.h diff --git a/Firmware/Board/v3.3/Makefile b/Firmware/Board/v3.3/Makefile new file mode 100644 index 00000000..82cdc7d2 --- /dev/null +++ b/Firmware/Board/v3.3/Makefile @@ -0,0 +1,78 @@ + +###################################### +# source +###################################### +C_SOURCES = \ + Middlewares/Third_Party/FreeRTOS/Source/queue.c \ + Middlewares/Third_Party/FreeRTOS/Source/tasks.c \ + Middlewares/Third_Party/FreeRTOS/Source/list.c \ + Middlewares/Third_Party/FreeRTOS/Source/event_groups.c \ + Middlewares/Third_Party/FreeRTOS/Source/croutine.c \ + Middlewares/Third_Party/FreeRTOS/Source/timers.c \ + Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c \ + Middlewares/Third_Party/FreeRTOS/Source/portable/MemMang/heap_4.c \ + Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c \ + Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c \ + Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c \ + Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c \ + Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c \ + Src/system_stm32f4xx.c \ + Src/stm32f4xx_it.c \ + Src/stm32f4xx_hal_msp.c \ + Src/stm32f4xx_hal_timebase_TIM.c \ + Src/tim.c \ + Src/gpio.c \ + Src/main.c \ + Src/adc.c \ + Src/freertos.c \ + Src/spi.c \ + Src/can.c \ + Src/usart.c \ + Src/dma.c \ + Src/usbd_conf.c \ + Src/usbd_desc.c \ + Src/usb_device.c \ + Drivers/DRV8301/drv8301.c \ + Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c \ + Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c \ + Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c \ + Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c \ + Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spi.c \ + Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c \ + Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c \ + Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c \ + Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_can.c \ + Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc.c \ + Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c \ + Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c \ + Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c \ + Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c \ + Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c \ + Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c \ + Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c \ + Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc_ex.c \ + Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c \ + Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.c \ + Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c \ + Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c \ + Src/usbd_cdc_if.c \ + Src/syscalls.c +CPP_SOURCES = +ASM_SOURCES = \ + startup/startup_stm32f405xx.s + +####################################### +# Includes +####################################### +AS_INCLUDES = +C_INCLUDES = -IMiddlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F \ + -IMiddlewares/Third_Party/FreeRTOS/Source/include \ + -IMiddlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS \ + -IDrivers/DRV8301 \ + -IMiddlewares/ST/STM32_USB_Device_Library/Core/Inc \ + -IMiddlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc \ + -IDrivers/STM32F4xx_HAL_Driver/Inc \ + -IDrivers/STM32F4xx_HAL_Driver/Inc/Legacy \ + -IDrivers/CMSIS/Device/ST/STM32F4xx/Include \ + -IDrivers/CMSIS/Include \ + -IInc diff --git a/Firmware/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc/usbd_cdc.h b/Firmware/Board/v3.3/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc/usbd_cdc.h similarity index 100% rename from Firmware/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc/usbd_cdc.h rename to Firmware/Board/v3.3/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc/usbd_cdc.h diff --git a/Firmware/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c b/Firmware/Board/v3.3/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c similarity index 100% rename from Firmware/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c rename to Firmware/Board/v3.3/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c diff --git a/Firmware/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h b/Firmware/Board/v3.3/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h similarity index 100% rename from Firmware/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h rename to Firmware/Board/v3.3/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h diff --git a/Firmware/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h b/Firmware/Board/v3.3/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h similarity index 100% rename from Firmware/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h rename to Firmware/Board/v3.3/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h diff --git a/Firmware/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_def.h b/Firmware/Board/v3.3/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_def.h similarity index 100% rename from Firmware/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_def.h rename to Firmware/Board/v3.3/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_def.h diff --git a/Firmware/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ioreq.h b/Firmware/Board/v3.3/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ioreq.h similarity index 100% rename from Firmware/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ioreq.h rename to Firmware/Board/v3.3/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ioreq.h diff --git a/Firmware/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c b/Firmware/Board/v3.3/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c similarity index 100% rename from Firmware/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c rename to Firmware/Board/v3.3/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c diff --git a/Firmware/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c b/Firmware/Board/v3.3/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c similarity index 100% rename from Firmware/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c rename to Firmware/Board/v3.3/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c diff --git a/Firmware/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c b/Firmware/Board/v3.3/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c similarity index 100% rename from Firmware/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c rename to Firmware/Board/v3.3/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c diff --git a/Firmware/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c b/Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c similarity index 100% rename from Firmware/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c rename to Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c diff --git a/Firmware/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h b/Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h similarity index 100% rename from Firmware/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h rename to Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h diff --git a/Firmware/Middlewares/Third_Party/FreeRTOS/Source/croutine.c b/Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/croutine.c similarity index 100% rename from Firmware/Middlewares/Third_Party/FreeRTOS/Source/croutine.c rename to Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/croutine.c diff --git a/Firmware/Middlewares/Third_Party/FreeRTOS/Source/event_groups.c b/Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/event_groups.c similarity index 100% rename from Firmware/Middlewares/Third_Party/FreeRTOS/Source/event_groups.c rename to Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/event_groups.c diff --git a/Firmware/Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h b/Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h similarity index 100% rename from Firmware/Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h rename to Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h diff --git a/Firmware/Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOSConfig_template.h b/Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOSConfig_template.h similarity index 100% rename from Firmware/Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOSConfig_template.h rename to Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOSConfig_template.h diff --git a/Firmware/Middlewares/Third_Party/FreeRTOS/Source/include/StackMacros.h b/Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/include/StackMacros.h similarity index 100% rename from Firmware/Middlewares/Third_Party/FreeRTOS/Source/include/StackMacros.h rename to Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/include/StackMacros.h diff --git a/Firmware/Middlewares/Third_Party/FreeRTOS/Source/include/croutine.h b/Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/include/croutine.h similarity index 100% rename from Firmware/Middlewares/Third_Party/FreeRTOS/Source/include/croutine.h rename to Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/include/croutine.h diff --git a/Firmware/Middlewares/Third_Party/FreeRTOS/Source/include/deprecated_definitions.h b/Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/include/deprecated_definitions.h similarity index 100% rename from Firmware/Middlewares/Third_Party/FreeRTOS/Source/include/deprecated_definitions.h rename to Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/include/deprecated_definitions.h diff --git a/Firmware/Middlewares/Third_Party/FreeRTOS/Source/include/event_groups.h b/Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/include/event_groups.h similarity index 100% rename from Firmware/Middlewares/Third_Party/FreeRTOS/Source/include/event_groups.h rename to Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/include/event_groups.h diff --git a/Firmware/Middlewares/Third_Party/FreeRTOS/Source/include/list.h b/Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/include/list.h similarity index 100% rename from Firmware/Middlewares/Third_Party/FreeRTOS/Source/include/list.h rename to Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/include/list.h diff --git a/Firmware/Middlewares/Third_Party/FreeRTOS/Source/include/mpu_prototypes.h b/Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/include/mpu_prototypes.h similarity index 100% rename from Firmware/Middlewares/Third_Party/FreeRTOS/Source/include/mpu_prototypes.h rename to Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/include/mpu_prototypes.h diff --git a/Firmware/Middlewares/Third_Party/FreeRTOS/Source/include/mpu_wrappers.h b/Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/include/mpu_wrappers.h similarity index 100% rename from Firmware/Middlewares/Third_Party/FreeRTOS/Source/include/mpu_wrappers.h rename to Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/include/mpu_wrappers.h diff --git a/Firmware/Middlewares/Third_Party/FreeRTOS/Source/include/portable.h b/Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/include/portable.h similarity index 100% rename from Firmware/Middlewares/Third_Party/FreeRTOS/Source/include/portable.h rename to Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/include/portable.h diff --git a/Firmware/Middlewares/Third_Party/FreeRTOS/Source/include/projdefs.h b/Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/include/projdefs.h similarity index 100% rename from Firmware/Middlewares/Third_Party/FreeRTOS/Source/include/projdefs.h rename to Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/include/projdefs.h diff --git a/Firmware/Middlewares/Third_Party/FreeRTOS/Source/include/queue.h b/Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/include/queue.h similarity index 100% rename from Firmware/Middlewares/Third_Party/FreeRTOS/Source/include/queue.h rename to Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/include/queue.h diff --git a/Firmware/Middlewares/Third_Party/FreeRTOS/Source/include/semphr.h b/Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/include/semphr.h similarity index 100% rename from Firmware/Middlewares/Third_Party/FreeRTOS/Source/include/semphr.h rename to Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/include/semphr.h diff --git a/Firmware/Middlewares/Third_Party/FreeRTOS/Source/include/task.h b/Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/include/task.h similarity index 100% rename from Firmware/Middlewares/Third_Party/FreeRTOS/Source/include/task.h rename to Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/include/task.h diff --git a/Firmware/Middlewares/Third_Party/FreeRTOS/Source/include/timers.h b/Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/include/timers.h similarity index 100% rename from Firmware/Middlewares/Third_Party/FreeRTOS/Source/include/timers.h rename to Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/include/timers.h diff --git a/Firmware/Middlewares/Third_Party/FreeRTOS/Source/list.c b/Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/list.c similarity index 100% rename from Firmware/Middlewares/Third_Party/FreeRTOS/Source/list.c rename to Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/list.c diff --git a/Firmware/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c b/Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c similarity index 100% rename from Firmware/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c rename to Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c diff --git a/Firmware/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/portmacro.h b/Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/portmacro.h similarity index 100% rename from Firmware/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/portmacro.h rename to Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/portmacro.h diff --git a/Firmware/Middlewares/Third_Party/FreeRTOS/Source/portable/MemMang/heap_4.c b/Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/portable/MemMang/heap_4.c similarity index 100% rename from Firmware/Middlewares/Third_Party/FreeRTOS/Source/portable/MemMang/heap_4.c rename to Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/portable/MemMang/heap_4.c diff --git a/Firmware/Middlewares/Third_Party/FreeRTOS/Source/queue.c b/Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/queue.c similarity index 100% rename from Firmware/Middlewares/Third_Party/FreeRTOS/Source/queue.c rename to Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/queue.c diff --git a/Firmware/Middlewares/Third_Party/FreeRTOS/Source/tasks.c b/Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/tasks.c similarity index 100% rename from Firmware/Middlewares/Third_Party/FreeRTOS/Source/tasks.c rename to Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/tasks.c diff --git a/Firmware/Middlewares/Third_Party/FreeRTOS/Source/timers.c b/Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/timers.c similarity index 100% rename from Firmware/Middlewares/Third_Party/FreeRTOS/Source/timers.c rename to Firmware/Board/v3.3/Middlewares/Third_Party/FreeRTOS/Source/timers.c diff --git a/Firmware/Odrive.ioc b/Firmware/Board/v3.3/Odrive.ioc similarity index 100% rename from Firmware/Odrive.ioc rename to Firmware/Board/v3.3/Odrive.ioc diff --git a/Firmware/STM32F405RGTx_FLASH.ld b/Firmware/Board/v3.3/STM32F405RGTx_FLASH.ld similarity index 97% rename from Firmware/STM32F405RGTx_FLASH.ld rename to Firmware/Board/v3.3/STM32F405RGTx_FLASH.ld index 2685ffab..3b96fa83 100644 --- a/Firmware/STM32F405RGTx_FLASH.ld +++ b/Firmware/Board/v3.3/STM32F405RGTx_FLASH.ld @@ -43,7 +43,8 @@ MEMORY { RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K -FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K +FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 768K +NVM (r) : ORIGIN = 0x80C0000, LENGTH = 256K } /* Define output sections */ diff --git a/Firmware/Src/adc.c b/Firmware/Board/v3.3/Src/adc.c similarity index 100% rename from Firmware/Src/adc.c rename to Firmware/Board/v3.3/Src/adc.c diff --git a/Firmware/Src/can.c b/Firmware/Board/v3.3/Src/can.c similarity index 100% rename from Firmware/Src/can.c rename to Firmware/Board/v3.3/Src/can.c diff --git a/Firmware/Src/dma.c b/Firmware/Board/v3.3/Src/dma.c similarity index 100% rename from Firmware/Src/dma.c rename to Firmware/Board/v3.3/Src/dma.c diff --git a/Firmware/Src/freertos.c b/Firmware/Board/v3.3/Src/freertos.c similarity index 98% rename from Firmware/Src/freertos.c rename to Firmware/Board/v3.3/Src/freertos.c index 9e136bd6..7794558c 100644 --- a/Firmware/Src/freertos.c +++ b/Firmware/Board/v3.3/Src/freertos.c @@ -56,6 +56,7 @@ #include "low_level.h" #include "axis_c_interface.h" #include "commands.h" +#include "config.h" /* USER CODE END Includes */ /* Variables -----------------------------------------------------------------*/ @@ -141,6 +142,9 @@ void StartDefaultTask(void const * argument) /* USER CODE BEGIN StartDefaultTask */ + // Init and load persistent configuration + init_configuration(); + // Init communications init_communication(); diff --git a/Firmware/Src/gpio.c b/Firmware/Board/v3.3/Src/gpio.c similarity index 100% rename from Firmware/Src/gpio.c rename to Firmware/Board/v3.3/Src/gpio.c diff --git a/Firmware/Src/main.c b/Firmware/Board/v3.3/Src/main.c similarity index 100% rename from Firmware/Src/main.c rename to Firmware/Board/v3.3/Src/main.c diff --git a/Firmware/Src/prev_board_ver/adc_V3_2.c b/Firmware/Board/v3.3/Src/prev_board_ver/adc_V3_2.c similarity index 100% rename from Firmware/Src/prev_board_ver/adc_V3_2.c rename to Firmware/Board/v3.3/Src/prev_board_ver/adc_V3_2.c diff --git a/Firmware/Src/prev_board_ver/gpio_V3_2.c b/Firmware/Board/v3.3/Src/prev_board_ver/gpio_V3_2.c similarity index 100% rename from Firmware/Src/prev_board_ver/gpio_V3_2.c rename to Firmware/Board/v3.3/Src/prev_board_ver/gpio_V3_2.c diff --git a/Firmware/Src/spi.c b/Firmware/Board/v3.3/Src/spi.c similarity index 100% rename from Firmware/Src/spi.c rename to Firmware/Board/v3.3/Src/spi.c diff --git a/Firmware/Src/stm32f4xx_hal_msp.c b/Firmware/Board/v3.3/Src/stm32f4xx_hal_msp.c similarity index 100% rename from Firmware/Src/stm32f4xx_hal_msp.c rename to Firmware/Board/v3.3/Src/stm32f4xx_hal_msp.c diff --git a/Firmware/Src/stm32f4xx_hal_timebase_TIM.c b/Firmware/Board/v3.3/Src/stm32f4xx_hal_timebase_TIM.c similarity index 100% rename from Firmware/Src/stm32f4xx_hal_timebase_TIM.c rename to Firmware/Board/v3.3/Src/stm32f4xx_hal_timebase_TIM.c diff --git a/Firmware/Src/stm32f4xx_it.c b/Firmware/Board/v3.3/Src/stm32f4xx_it.c similarity index 100% rename from Firmware/Src/stm32f4xx_it.c rename to Firmware/Board/v3.3/Src/stm32f4xx_it.c diff --git a/Firmware/Src/syscalls.c b/Firmware/Board/v3.3/Src/syscalls.c similarity index 100% rename from Firmware/Src/syscalls.c rename to Firmware/Board/v3.3/Src/syscalls.c diff --git a/Firmware/Src/system_stm32f4xx.c b/Firmware/Board/v3.3/Src/system_stm32f4xx.c similarity index 100% rename from Firmware/Src/system_stm32f4xx.c rename to Firmware/Board/v3.3/Src/system_stm32f4xx.c diff --git a/Firmware/Src/tim.c b/Firmware/Board/v3.3/Src/tim.c similarity index 100% rename from Firmware/Src/tim.c rename to Firmware/Board/v3.3/Src/tim.c diff --git a/Firmware/Src/usart.c b/Firmware/Board/v3.3/Src/usart.c similarity index 100% rename from Firmware/Src/usart.c rename to Firmware/Board/v3.3/Src/usart.c diff --git a/Firmware/Src/usb_device.c b/Firmware/Board/v3.3/Src/usb_device.c similarity index 100% rename from Firmware/Src/usb_device.c rename to Firmware/Board/v3.3/Src/usb_device.c diff --git a/Firmware/Src/usbd_cdc_if.c b/Firmware/Board/v3.3/Src/usbd_cdc_if.c similarity index 100% rename from Firmware/Src/usbd_cdc_if.c rename to Firmware/Board/v3.3/Src/usbd_cdc_if.c diff --git a/Firmware/Src/usbd_conf.c b/Firmware/Board/v3.3/Src/usbd_conf.c similarity index 100% rename from Firmware/Src/usbd_conf.c rename to Firmware/Board/v3.3/Src/usbd_conf.c diff --git a/Firmware/Src/usbd_desc.c b/Firmware/Board/v3.3/Src/usbd_desc.c similarity index 100% rename from Firmware/Src/usbd_desc.c rename to Firmware/Board/v3.3/Src/usbd_desc.c diff --git a/Firmware/startup/startup_stm32f405xx.s b/Firmware/Board/v3.3/startup/startup_stm32f405xx.s similarity index 100% rename from Firmware/startup/startup_stm32f405xx.s rename to Firmware/Board/v3.3/startup/startup_stm32f405xx.s diff --git a/Firmware/CHANGELOG.md b/Firmware/CHANGELOG.md index c18f9960..9d3e620e 100644 --- a/Firmware/CHANGELOG.md +++ b/Firmware/CHANGELOG.md @@ -1,6 +1,18 @@ ## UNRELEASED Please add a note of your changes below this heading if you make a PR +### Added +* **Storing of configuration parameters to Non Volatile Memory** +* Reporting error if your encoder CPR is incorrect +* Reporting of DRV status/control registers and fault codes +* DRV status read script +* Microsecond delay function +* Ability to start anticogging calibration over USB protocol +* Travis-CI + +### Changed +* Build system is now tup instead of make + ## [0.3.4] - 2018-02-13 ### Fixed diff --git a/Firmware/Makefile b/Firmware/Makefile index 056443f5..05be1be6 100644 --- a/Firmware/Makefile +++ b/Firmware/Makefile @@ -1,217 +1,30 @@ -###################################### -# Makefile by CubeMX2Makefile.py -###################################### -###################################### -# target -###################################### -TARGET = ODriveFirmware +# This is only a stub for various commands. +# Tup is used for the actual compilation. -###################################### -# building variables -###################################### -# debug build? -DEBUG = 1 -# optimization -OPT = -Og -ffast-math - -####################################### -# pathes -####################################### -# Build path BUILD_DIR = build +FIRMWARE = $(BUILD_DIR)/ODriveFirmware.elf -###################################### -# source -###################################### -C_SOURCES = \ - Middlewares/Third_Party/FreeRTOS/Source/queue.c \ - Middlewares/Third_Party/FreeRTOS/Source/tasks.c \ - Middlewares/Third_Party/FreeRTOS/Source/list.c \ - Middlewares/Third_Party/FreeRTOS/Source/event_groups.c \ - Middlewares/Third_Party/FreeRTOS/Source/croutine.c \ - Middlewares/Third_Party/FreeRTOS/Source/timers.c \ - Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c \ - Middlewares/Third_Party/FreeRTOS/Source/portable/MemMang/heap_4.c \ - Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c \ - Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c \ - Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c \ - Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c \ - Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c \ - Src/system_stm32f4xx.c \ - Src/stm32f4xx_it.c \ - Src/stm32f4xx_hal_msp.c \ - Src/stm32f4xx_hal_timebase_TIM.c \ - Src/tim.c \ - Src/gpio.c \ - Src/main.c \ - Src/adc.c \ - Src/freertos.c \ - Src/spi.c \ - Src/can.c \ - Src/usart.c \ - Src/dma.c \ - Src/usbd_conf.c \ - Src/usbd_desc.c \ - Src/usb_device.c \ - Drivers/DRV8301/drv8301.c \ - Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c \ - Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c \ - Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c \ - Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c \ - Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spi.c \ - Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c \ - Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c \ - Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c \ - Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_can.c \ - Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc.c \ - Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c \ - Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c \ - Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c \ - Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c \ - Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c \ - Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c \ - Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c \ - Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc_ex.c \ - Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c \ - Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.c \ - Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c \ - Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c \ - Src/usbd_cdc_if.c \ - Src/syscalls.c \ - MotorControl/utils.c \ - MotorControl/legacy_commands.c \ - MotorControl/low_level.c -CPP_SOURCES = \ - MotorControl/axis.cpp \ - MotorControl/commands.cpp \ - MotorControl/protocol.cpp -ASM_SOURCES = \ - startup/startup_stm32f405xx.s +all: + @tup --quiet -####################################### -# binaries -####################################### -CC = arm-none-eabi-gcc -CXX = arm-none-eabi-g++ -AS = arm-none-eabi-gcc -x assembler-with-cpp -CP = arm-none-eabi-objcopy -AR = arm-none-eabi-ar -SZ = arm-none-eabi-size -HEX = $(CP) -O ihex -BIN = $(CP) -O binary -S - -####################################### -# CFLAGS -####################################### -# macros for gcc -AS_DEFS = -C_DEFS = -D__weak="__attribute__((weak))" -D__packed="__attribute__((__packed__))" -DUSE_HAL_DRIVER -DSTM32F405xx -# includes for gcc -AS_INCLUDES = -C_INCLUDES = -IMiddlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F -C_INCLUDES += -IMiddlewares/Third_Party/FreeRTOS/Source/include -C_INCLUDES += -IMiddlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS -C_INCLUDES += -IDrivers/DRV8301 -C_INCLUDES += -IMiddlewares/ST/STM32_USB_Device_Library/Core/Inc -C_INCLUDES += -IMiddlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc -C_INCLUDES += -IDrivers/STM32F4xx_HAL_Driver/Inc -C_INCLUDES += -IDrivers/STM32F4xx_HAL_Driver/Inc/Legacy -C_INCLUDES += -IDrivers/CMSIS/Device/ST/STM32F4xx/Include -C_INCLUDES += -IDrivers/CMSIS/Include -C_INCLUDES += -IInc -C_INCLUDES += -IMotorControl -# compile gcc flags -ASFLAGS = -mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard $(AS_DEFS) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections -CFLAGS = -mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard $(C_DEFS) $(C_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections -CXXFLAGS = -mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard $(C_DEFS) $(C_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections -ifeq ($(DEBUG), 1) -CFLAGS += -g -gdwarf-2 -CXXFLAGS += -g -gdwarf-2 -endif -# Generate dependency information -CFLAGS += -std=c99 -MD -MP -MF .dep/$(@F).d -CXXFLAGS += -std=c++14 -MD -MP -MF .dep/$(@F).d +flash: all + openocd -f interface/stlink-v2.cfg -f target/stm32f4x.cfg -c init -c reset\ halt -c flash\ write_image\ erase\ $(FIRMWARE) -c reset\ run -c exit -####################################### -# LDFLAGS -####################################### -# link script -LDSCRIPT = STM32F405RGTx_FLASH.ld -# libraries -LIBS = -lc -lm -lnosys -larm_cortexM4lf_math -LIBDIR = -LDrivers/CMSIS/Lib -LDFLAGS = -mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -specs=nosys.specs -specs=nano.specs -u _printf_float -u _scanf_float $(OPT) -T$(LDSCRIPT) $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections +gdb: all + arm-none-eabi-gdb $(FIRMWARE) -x openocd.gdbinit -# default action: build all -all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin - -####################################### -# build the application -####################################### -# list of objects -OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o))) -vpath %.c $(sort $(dir $(C_SOURCES))) -# list of C++ objects -OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(CPP_SOURCES:.cpp=.o))) -vpath %.cpp $(sort $(dir $(CPP_SOURCES))) -# list of ASM program objects -OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o))) -vpath %.s $(sort $(dir $(ASM_SOURCES))) - -$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR) - @$(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@ - -$(BUILD_DIR)/%.o: %.cpp Makefile | $(BUILD_DIR) - @$(CXX) -c $(CXXFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.cpp=.lst)) $< -o $@ - -$(BUILD_DIR)/%.o: %.s Makefile | $(BUILD_DIR) - @$(AS) -c $(CFLAGS) $< -o $@ - -$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) Makefile - @$(CXX) $(OBJECTS) $(LDFLAGS) -o $@ - $(SZ) $@ - -$(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.elf | $(BUILD_DIR) - @$(HEX) $< $@ - -$(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf | $(BUILD_DIR) - @$(BIN) $< $@ - -$(BUILD_DIR): - mkdir -p $@ - -####################################### -# clean up -####################################### -clean: - -rm -fR .dep $(BUILD_DIR) - -####################################### -# flashing / debug -####################################### - -flash: $(BUILD_DIR)/$(TARGET).elf - openocd -f interface/stlink-v2.cfg -f target/stm32f4x.cfg -c init -c reset\ halt -c flash\ write_image\ erase\ $(BUILD_DIR)/$(TARGET).elf -c reset\ run -c exit - -dfu: $(BUILD_DIR)/$(TARGET).hex +dfu: all ../tools/dfu.py $(if $(value SERIAL_NUMBER),--serial-number $(SERIAL_NUMBER),) $(BUILD_DIR)/$(TARGET).hex - -gdb: $(BUILD_DIR)/$(TARGET).elf - arm-none-eabi-gdb $(BUILD_DIR)/$(TARGET).elf -x openocd.gdbinit - -bmp: $(BUILD_DIR)/$(TARGET).elf +bmp: all arm-none-eabi-gdb --ex 'target extended-remote /dev/stlink' \ --ex 'monitor swdp_scan' \ --ex 'attach 1' \ - --ex 'load' $(BUILD_DIR)/$(TARGET).elf + --ex 'load' $(FIRMWARE) -####################################### -# dependencies -####################################### --include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*) +clean: + -rm -fR .dep $(BUILD_DIR) -.PHONY: clean all flash gdb +.PHONY: all flash gdb dfu bmp clean -# *** EOF *** diff --git a/Firmware/MotorControl/axis.cpp b/Firmware/MotorControl/axis.cpp index aaac53b5..553c7190 100644 --- a/Firmware/MotorControl/axis.cpp +++ b/Firmware/MotorControl/axis.cpp @@ -8,6 +8,9 @@ extern "C" { #include "low_level.h" } +//TODO: Make it really clear where this is loaded. +AxisConfig axis_configs[2]; //TODO: get a constexpr for num motors + // C interface extern "C" { void axis_thread_entry(void const* temp_motor_ptr) { @@ -19,9 +22,7 @@ void axis_thread_entry(void const* temp_motor_ptr) { while (&motors[ax_number] != motor) ++ax_number; - static const AxisConfig default_config; - - Axis axis(default_config, ax_number, motor); + Axis axis(axis_configs[ax_number], ax_number, motor); axis.StateMachineLoop(); } } // extern "C" @@ -36,10 +37,11 @@ void Axis::SetupLegacyMappings() { exposed_bools[4 * axis_number_ + 2] = &do_calibration_; } -Axis::Axis(const AxisConfig& config, uint8_t axis_number, Motor_t* legacy_motor_ref) +Axis::Axis(AxisConfig& config, uint8_t axis_number, Motor_t* legacy_motor_ref) : axis_number_(axis_number), enable_control_(config.enable_control_at_start), do_calibration_(config.do_calibration_at_start), + config_(config), legacy_motor_ref_(legacy_motor_ref) { SetupLegacyMappings(); } @@ -62,8 +64,8 @@ void Axis::StateMachineLoop() { for (;;) { // Keep rotor estimation up to date while idling osSignalWait(M_SIGNAL_PH_CURRENT_MEAS, osWaitForever); - update_rotor(legacy_motor_ref_); - + loop_updates(legacy_motor_ref_); + if (do_calibration_) { do_calibration_ = false; diff --git a/Firmware/MotorControl/axis.h b/Firmware/MotorControl/axis.h index b3cdf543..455515b1 100644 --- a/Firmware/MotorControl/axis.h +++ b/Firmware/MotorControl/axis.h @@ -15,6 +15,7 @@ struct AxisConfig { bool enable_control_at_start = true; bool do_calibration_at_start = true; }; +extern AxisConfig axis_configs[]; class Axis { public: @@ -40,7 +41,7 @@ public: //step/dir handler // Object operation requires ptr to legacy object for now, TODO: get rid of this dep - Axis(const AxisConfig& config, uint8_t axis_number, Motor_t* legacy_motor_ref); + Axis(AxisConfig& config, uint8_t axis_number, Motor_t* legacy_motor_ref); // Infinite loop that does calibration and enters main control loop as appropriate void StateMachineLoop(); @@ -50,6 +51,8 @@ public: bool enable_control_; bool do_calibration_; + AxisConfig& config_; + Motor_t* legacy_motor_ref_; private: diff --git a/Firmware/MotorControl/commands.cpp b/Firmware/MotorControl/commands.cpp index 6370e5b5..0084d9f4 100644 --- a/Firmware/MotorControl/commands.cpp +++ b/Firmware/MotorControl/commands.cpp @@ -8,9 +8,11 @@ #include "commands.h" #include "low_level.h" +#include "axis.h" #include "protocol.hpp" #include "freertos_vars.h" #include "utils.h" +#include "config.h" #ifdef ENABLE_LEGACY_PROTOCOL #include "legacy_commands.h" @@ -87,6 +89,14 @@ void motors_1_set_current_setpoint_func(void) { set_current_setpoint(&motors[1], motors[1].set_current_setpoint_args.current_setpoint); } +void motors_run_anticogging_calibration_func() { + for (uint8_t i = 0; i < num_motors; i++) { + // Ensure the cogging map was correctly allocated earlier and that the motor is capable of calibrating + if (motors[i].anticogging.cogging_map != NULL && motors[i].error == ERROR_NO_ERROR) { + motors[i].anticogging.calib_anticogging = true; + } + } +} void enter_dfu_mode() { *((unsigned long *)0x2001C000) = 0xDEADBEEF; @@ -98,36 +108,56 @@ void enter_dfu_mode() { // clang-format off const Endpoint endpoints[] = { Endpoint::make_property("vbus_voltage", const_cast(&vbus_voltage)), - Endpoint::make_property("elec_rad_per_enc", const_cast(&elec_rad_per_enc)), Endpoint::make_property("UUID_0", (const uint32_t*)(ID_UNIQUE_ADDRESS + 0*4)), Endpoint::make_property("UUID_1", (const uint32_t*)(ID_UNIQUE_ADDRESS + 1*4)), Endpoint::make_property("UUID_2", (const uint32_t*)(ID_UNIQUE_ADDRESS + 2*4)), + Endpoint::make_function("run_anticogging_calibration", &motors_run_anticogging_calibration_func), + // No parameters, but still requires a close_tree() + Endpoint::close_tree(), + Endpoint::make_object("config"), + Endpoint::make_property("brake_resistance", &brake_resistance), + Endpoint::close_tree(), + Endpoint::make_object("axis0"), + Endpoint::make_object("config"), + Endpoint::make_property("enable_control_at_start", &axis_configs[0].enable_control_at_start), + Endpoint::make_property("do_calibration_at_start", &axis_configs[0].do_calibration_at_start), + Endpoint::close_tree(), + Endpoint::close_tree(), Endpoint::make_object("motor0"), - Endpoint::make_property("control_mode", reinterpret_cast(&motors[0].control_mode)), + Endpoint::make_object("config"), + Endpoint::make_property("control_mode", reinterpret_cast(&motors[0].control_mode)), + Endpoint::make_property("counts_per_step", &motors[0].counts_per_step), + Endpoint::make_property("pole_pairs", &motors[0].pole_pairs), + Endpoint::make_property("pos_gain", &motors[0].pos_gain), + Endpoint::make_property("vel_gain", &motors[0].vel_gain), + Endpoint::make_property("vel_integrator_gain", &motors[0].vel_integrator_gain), + Endpoint::make_property("vel_limit", &motors[0].vel_limit), + Endpoint::make_property("calibration_current", &motors[0].calibration_current), + Endpoint::make_property("resistance_calib_max_voltage", &motors[0].resistance_calib_max_voltage), + Endpoint::make_property("phase_inductance", &motors[0].phase_inductance), + Endpoint::make_property("phase_resistance", &motors[0].phase_resistance), + Endpoint::make_property("motor_type", reinterpret_cast(&motors[0].motor_type)), + Endpoint::make_property("rotor_mode", reinterpret_cast(&motors[0].rotor_mode)), + Endpoint::close_tree(), Endpoint::make_property("error", reinterpret_cast(&motors[0].error)), Endpoint::make_property("pos_setpoint", &motors[0].pos_setpoint), - Endpoint::make_property("pos_gain", &motors[0].pos_gain), Endpoint::make_property("vel_setpoint", &motors[0].vel_setpoint), - Endpoint::make_property("vel_gain", &motors[0].vel_gain), - Endpoint::make_property("vel_integrator_gain", &motors[0].vel_integrator_gain), Endpoint::make_property("vel_integrator_current", &motors[0].vel_integrator_current), - Endpoint::make_property("vel_limit", &motors[0].vel_limit), Endpoint::make_property("current_setpoint", &motors[0].current_setpoint), - Endpoint::make_property("calibration_current", &motors[0].calibration_current), - Endpoint::make_property("phase_inductance", const_cast(&motors[0].phase_inductance)), - Endpoint::make_property("phase_resistance", const_cast(&motors[0].phase_resistance)), Endpoint::make_property("current_meas_phB", const_cast(&motors[0].current_meas.phB)), Endpoint::make_property("current_meas_phC", const_cast(&motors[0].current_meas.phC)), Endpoint::make_property("DC_calib.phB", &motors[0].DC_calib.phB), Endpoint::make_property("DC_calib.phC", &motors[0].DC_calib.phC), Endpoint::make_property("shunt_conductance", &motors[0].shunt_conductance), Endpoint::make_property("phase_current_rev_gain", &motors[0].phase_current_rev_gain), - Endpoint::make_property("thread_ready", reinterpret_cast(&motors[0].thread_ready)), + Endpoint::make_property("thread_ready", &motors[0].thread_ready), Endpoint::make_property("control_deadline", &motors[0].control_deadline), Endpoint::make_property("last_cpu_time", &motors[0].last_cpu_time), Endpoint::make_property("loop_counter", &motors[0].loop_counter), Endpoint::make_object("current_control"), - Endpoint::make_property("current_lim", &motors[0].current_control.current_lim), + Endpoint::make_object("config"), + Endpoint::make_property("current_lim", &motors[0].current_control.current_lim), + Endpoint::close_tree(), Endpoint::make_property("p_gain", &motors[0].current_control.p_gain), Endpoint::make_property("i_gain", &motors[0].current_control.i_gain), Endpoint::make_property("v_current_control_integral_d", &motors[0].current_control.v_current_control_integral_d), @@ -136,7 +166,22 @@ const Endpoint endpoints[] = { Endpoint::make_property("Iq_measured", &motors[0].current_control.Iq_measured), Endpoint::make_property("Ibus", const_cast(&motors[0].current_control.Ibus)), Endpoint::close_tree(), + Endpoint::make_object("gate_driver"), + Endpoint::make_property("drv_fault", reinterpret_cast(&motors[0].drv_fault)), + Endpoint::make_property("status_reg_1", (&motors[0].gate_driver_regs.Stat_Reg_1_Value)), + Endpoint::make_property("status_reg_2", (&motors[0].gate_driver_regs.Stat_Reg_2_Value)), + Endpoint::make_property("ctrl_reg_1", (&motors[0].gate_driver_regs.Ctrl_Reg_1_Value)), + Endpoint::make_property("ctrl_reg_2", (&motors[0].gate_driver_regs.Ctrl_Reg_2_Value)), + Endpoint::close_tree(), Endpoint::make_object("encoder"), + Endpoint::make_object("config"), + Endpoint::make_property("use_index", &motors[0].encoder.use_index), + Endpoint::make_property("manually_calibrated", &motors[0].encoder.manually_calibrated), + Endpoint::make_property("idx_search_speed", &motors[0].encoder.idx_search_speed), + Endpoint::make_property("cpr", &motors[0].encoder.encoder_cpr), + Endpoint::make_property("offset", &motors[0].encoder.encoder_offset), + Endpoint::make_property("motor_dir", &motors[0].encoder.motor_dir), + Endpoint::close_tree(), Endpoint::make_property("phase", const_cast(&motors[0].encoder.phase)), Endpoint::make_property("pll_pos", &motors[0].encoder.pll_pos), Endpoint::make_property("pll_vel", &motors[0].encoder.pll_vel), @@ -158,33 +203,61 @@ const Endpoint endpoints[] = { Endpoint::make_function("set_current_setpoint", &motors_0_set_current_setpoint_func), Endpoint::make_property("current_setpoint", &motors[0].set_current_setpoint_args.current_setpoint), Endpoint::close_tree(), + Endpoint::make_object("timing_log"), + Endpoint::make_property("TIMING_LOG_GENERAL", &motors[0].timing_log[TIMING_LOG_GENERAL]), + Endpoint::make_property("TIMING_LOG_ADC_CB_M0_I", &motors[0].timing_log[TIMING_LOG_ADC_CB_M0_I]), + Endpoint::make_property("TIMING_LOG_ADC_CB_M0_DC", &motors[0].timing_log[TIMING_LOG_ADC_CB_M0_DC]), + Endpoint::make_property("TIMING_LOG_ADC_CB_M1_I", &motors[0].timing_log[TIMING_LOG_ADC_CB_M1_I]), + Endpoint::make_property("TIMING_LOG_ADC_CB_M1_DC", &motors[0].timing_log[TIMING_LOG_ADC_CB_M1_DC]), + Endpoint::make_property("TIMING_LOG_MEAS_R", &motors[0].timing_log[TIMING_LOG_MEAS_R]), + Endpoint::make_property("TIMING_LOG_MEAS_L", &motors[0].timing_log[TIMING_LOG_MEAS_L]), + Endpoint::make_property("TIMING_LOG_ENC_CALIB", &motors[0].timing_log[TIMING_LOG_ENC_CALIB]), + Endpoint::make_property("TIMING_LOG_IDX_SEARCH", &motors[0].timing_log[TIMING_LOG_IDX_SEARCH]), + Endpoint::make_property("TIMING_LOG_FOC_VOLTAGE", &motors[0].timing_log[TIMING_LOG_FOC_VOLTAGE]), + Endpoint::make_property("TIMING_LOG_FOC_CURRENT", &motors[0].timing_log[TIMING_LOG_FOC_CURRENT]), + Endpoint::close_tree(), Endpoint::close_tree(), // motor0 + Endpoint::make_object("axis1"), + Endpoint::make_object("config"), + Endpoint::make_property("enable_control_at_start", &axis_configs[1].enable_control_at_start), + Endpoint::make_property("do_calibration_at_start", &axis_configs[1].do_calibration_at_start), + Endpoint::close_tree(), + Endpoint::close_tree(), Endpoint::make_object("motor1"), - Endpoint::make_property("control_mode", reinterpret_cast(&motors[1].control_mode)), + Endpoint::make_object("config"), + Endpoint::make_property("control_mode", reinterpret_cast(&motors[1].control_mode)), + Endpoint::make_property("counts_per_step", &motors[1].counts_per_step), + Endpoint::make_property("pole_pairs", &motors[1].pole_pairs), + Endpoint::make_property("pos_gain", &motors[1].pos_gain), + Endpoint::make_property("vel_gain", &motors[1].vel_gain), + Endpoint::make_property("vel_integrator_gain", &motors[1].vel_integrator_gain), + Endpoint::make_property("vel_limit", &motors[1].vel_limit), + Endpoint::make_property("calibration_current", &motors[1].calibration_current), + Endpoint::make_property("resistance_calib_max_voltage", &motors[1].resistance_calib_max_voltage), + Endpoint::make_property("phase_inductance", &motors[1].phase_inductance), + Endpoint::make_property("phase_resistance", &motors[1].phase_resistance), + Endpoint::make_property("motor_type", reinterpret_cast(&motors[1].motor_type)), + Endpoint::make_property("rotor_mode", reinterpret_cast(&motors[1].rotor_mode)), + Endpoint::close_tree(), Endpoint::make_property("error", reinterpret_cast(&motors[1].error)), Endpoint::make_property("pos_setpoint", &motors[1].pos_setpoint), - Endpoint::make_property("pos_gain", &motors[1].pos_gain), Endpoint::make_property("vel_setpoint", &motors[1].vel_setpoint), - Endpoint::make_property("vel_gain", &motors[1].vel_gain), - Endpoint::make_property("vel_integrator_gain", &motors[1].vel_integrator_gain), Endpoint::make_property("vel_integrator_current", &motors[1].vel_integrator_current), - Endpoint::make_property("vel_limit", &motors[1].vel_limit), Endpoint::make_property("current_setpoint", &motors[1].current_setpoint), - Endpoint::make_property("calibration_current", &motors[1].calibration_current), - Endpoint::make_property("phase_inductance", const_cast(&motors[1].phase_inductance)), - Endpoint::make_property("phase_resistance", const_cast(&motors[1].phase_resistance)), Endpoint::make_property("current_meas_phB", const_cast(&motors[1].current_meas.phB)), Endpoint::make_property("current_meas_phC", const_cast(&motors[1].current_meas.phC)), Endpoint::make_property("DC_calib.phB", &motors[1].DC_calib.phB), Endpoint::make_property("DC_calib.phC", &motors[1].DC_calib.phC), Endpoint::make_property("shunt_conductance", &motors[1].shunt_conductance), Endpoint::make_property("phase_current_rev_gain", &motors[1].phase_current_rev_gain), - Endpoint::make_property("thread_ready", reinterpret_cast(&motors[1].thread_ready)), + Endpoint::make_property("thread_ready", &motors[1].thread_ready), Endpoint::make_property("control_deadline", &motors[1].control_deadline), Endpoint::make_property("last_cpu_time", &motors[1].last_cpu_time), Endpoint::make_property("loop_counter", &motors[1].loop_counter), Endpoint::make_object("current_control"), - Endpoint::make_property("current_lim", &motors[1].current_control.current_lim), + Endpoint::make_object("config"), + Endpoint::make_property("current_lim", &motors[1].current_control.current_lim), + Endpoint::close_tree(), Endpoint::make_property("p_gain", &motors[1].current_control.p_gain), Endpoint::make_property("i_gain", &motors[1].current_control.i_gain), Endpoint::make_property("v_current_control_integral_d", &motors[1].current_control.v_current_control_integral_d), @@ -193,7 +266,22 @@ const Endpoint endpoints[] = { Endpoint::make_property("Iq_measured", &motors[1].current_control.Iq_measured), Endpoint::make_property("Ibus", const_cast(&motors[1].current_control.Ibus)), Endpoint::close_tree(), + Endpoint::make_object("gate_driver"), + Endpoint::make_property("drv_fault", reinterpret_cast(&motors[1].drv_fault)), + Endpoint::make_property("status_reg_1", (&motors[1].gate_driver_regs.Stat_Reg_1_Value)), + Endpoint::make_property("status_reg_2", (&motors[1].gate_driver_regs.Stat_Reg_2_Value)), + Endpoint::make_property("ctrl_reg_1", (&motors[1].gate_driver_regs.Ctrl_Reg_1_Value)), + Endpoint::make_property("ctrl_reg_2", (&motors[1].gate_driver_regs.Ctrl_Reg_2_Value)), + Endpoint::close_tree(), Endpoint::make_object("encoder"), + Endpoint::make_object("config"), + Endpoint::make_property("use_index", &motors[1].encoder.use_index), + Endpoint::make_property("manually_calibrated", &motors[1].encoder.manually_calibrated), + Endpoint::make_property("idx_search_speed", &motors[1].encoder.idx_search_speed), + Endpoint::make_property("cpr", &motors[1].encoder.encoder_cpr), + Endpoint::make_property("offset", &motors[1].encoder.encoder_offset), + Endpoint::make_property("motor_dir", &motors[1].encoder.motor_dir), + Endpoint::close_tree(), Endpoint::make_property("phase", const_cast(&motors[1].encoder.phase)), Endpoint::make_property("pll_pos", &motors[1].encoder.pll_pos), Endpoint::make_property("pll_vel", &motors[1].encoder.pll_vel), @@ -216,8 +304,31 @@ const Endpoint endpoints[] = { Endpoint::make_property("current_setpoint", &motors[1].set_current_setpoint_args.current_setpoint), Endpoint::close_tree(), Endpoint::close_tree(), // motor1 + Endpoint::make_function("save_configuration", &save_configuration), + // no arguments + Endpoint::close_tree(), + Endpoint::make_function("erase_configuration", &erase_configuration), + // no arguments + Endpoint::close_tree(), + Endpoint::make_function("reboot", &NVIC_SystemReset), + // no arguments + Endpoint::close_tree(), Endpoint::make_function("enter_dfu_mode", &enter_dfu_mode), - Endpoint::close_tree() // enter_dfu_mode + // no arguments + Endpoint::close_tree(), + Endpoint::make_object("timing_log"), + Endpoint::make_property("TIMING_LOG_GENERAL", &motors[1].timing_log[TIMING_LOG_GENERAL]), + Endpoint::make_property("TIMING_LOG_ADC_CB_M0_I", &motors[1].timing_log[TIMING_LOG_ADC_CB_M0_I]), + Endpoint::make_property("TIMING_LOG_ADC_CB_M0_DC", &motors[1].timing_log[TIMING_LOG_ADC_CB_M0_DC]), + Endpoint::make_property("TIMING_LOG_ADC_CB_M1_I", &motors[1].timing_log[TIMING_LOG_ADC_CB_M1_I]), + Endpoint::make_property("TIMING_LOG_ADC_CB_M1_DC", &motors[1].timing_log[TIMING_LOG_ADC_CB_M1_DC]), + Endpoint::make_property("TIMING_LOG_MEAS_R", &motors[1].timing_log[TIMING_LOG_MEAS_R]), + Endpoint::make_property("TIMING_LOG_MEAS_L", &motors[1].timing_log[TIMING_LOG_MEAS_L]), + Endpoint::make_property("TIMING_LOG_ENC_CALIB", &motors[1].timing_log[TIMING_LOG_ENC_CALIB]), + Endpoint::make_property("TIMING_LOG_IDX_SEARCH", &motors[1].timing_log[TIMING_LOG_IDX_SEARCH]), + Endpoint::make_property("TIMING_LOG_FOC_VOLTAGE", &motors[1].timing_log[TIMING_LOG_FOC_VOLTAGE]), + Endpoint::make_property("TIMING_LOG_FOC_CURRENT", &motors[1].timing_log[TIMING_LOG_FOC_CURRENT]), + Endpoint::close_tree(), }; // clang-format on diff --git a/Firmware/MotorControl/config.cpp b/Firmware/MotorControl/config.cpp new file mode 100644 index 00000000..e61a8102 --- /dev/null +++ b/Firmware/MotorControl/config.cpp @@ -0,0 +1,247 @@ + +/* Includes ------------------------------------------------------------------*/ + +#include "config.h" + +#include +#include +#include + +#include "nvm.h" +#include "crc.hpp" +#include "low_level.h" +#include "axis.h" + +// IMPORTANT: if you change, reorder or otherwise modify any of the fields in +// the config structs, make sure to increment this number: +uint16_t config_version = 0x0001; + +/* Private defines -----------------------------------------------------------*/ +#define CRC16_INIT 0xabcd + +/* Private macros ------------------------------------------------------------*/ +/* Private typedef -----------------------------------------------------------*/ + +typedef struct { + Motor_control_mode_t control_mode; + float counts_per_step; + int32_t pole_pairs; + float pos_gain; + float vel_gain; + float vel_integrator_gain; + float vel_limit; + float calibration_current; + float resistance_calib_max_voltage; + float phase_inductance; + float phase_resistance; + Motor_type_t motor_type; + Rotor_mode_t rotor_mode; + float current_control_current_lim; + bool encoder_use_index; + bool encoder_manually_calibrated; + float encoder_idx_search_speed; + int32_t encoder_cpr; + int32_t encoder_offset; + int32_t encoder_motor_dir; +} MotorConfig_t; + +/* Global constant data ------------------------------------------------------*/ +/* Global variables ----------------------------------------------------------*/ +/* Private constant data -----------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Function implementations --------------------------------------------------*/ + +// @brief Manages configuration load and store operations from and to NVM +// +// The NVM stores consecutive one-to-one copies of arbitrary objects. +// The types of these objects are passed as template arguments to Config. +// +// Config has two template specializations to implement template recursion: +// - Config handles loading/storing of the first object (type T) and leaves +// the rest of the objects to an "inner" class Config. +// - Config<> represents the leaf of the recursion. +template +struct Config; + +template<> +struct Config<> { + static size_t get_size() { + return 0; + } + static int load_config(size_t offset, uint16_t* crc16) { + return 0; + } + static int store_config(size_t offset, uint16_t* crc16) { + return 0; + } +}; + +template +struct Config { + static size_t get_size() { + return sizeof(T) + Config::get_size(); + } + + // @brief Loads one or more consecutive objects from the NVM. + // During loading this function also calculates the CRC over the loaded data. + // @param offset: 0 means that the function should start reading at the beginning + // of the last comitted NVM block + // @param crc16: the result of the CRC calculation is written to this address + // @param val0, vals: the values to be loaded + static int load_config(size_t offset, uint16_t* crc16, T* val0, Ts* ... vals) { + size_t size = sizeof(T); + // save current CRC (in case val0 and crc16 point to the same address) + size_t previous_crc16 = *crc16; + if (NVM_read(offset, (uint8_t *)val0, size)) + return -1; + *crc16 = calc_crc16(previous_crc16, (uint8_t *)val0, size); + if (Config::load_config(offset + size, crc16, vals...)) + return -1; + return 0; + } + + // @brief Stores one or more consecutive objects to the NVM. + // During storing this function also calculates the CRC over the stored data. + // @param offset: 0 means that the function should start writing at the beginning + // of the currently active NVM write block + // @param crc16: the result of the CRC calculation is written to this address + // @param val0, vals: the values to be stored + static int store_config(size_t offset, uint16_t* crc16, const T* val0, const Ts* ... vals) { + size_t size = sizeof(T); + if (NVM_write(offset, (uint8_t *)val0, size)) + return -1; + // update CRC _after_ writing (in case val0 and crc16 point to the same address) + if (crc16) + *crc16 = calc_crc16(*crc16, (uint8_t *)val0, size); + if (Config::store_config(offset + size, crc16, vals...)) + return -1; + return 0; + } + + // @brief Loads one or more consecutive objects from the NVM. The loaded data + // is validated using a CRC value that is stored at the beginning of the data. + static int load_config(T* val0, Ts* ... vals) { + //printf("have %d bytes\r\n", NVM_get_max_read_length()); osDelay(5); + if (Config::get_size() > NVM_get_max_read_length()) + return -1; + uint16_t crc16 = CRC16_INIT ^ config_version; + if (Config::load_config(0, &crc16, val0, vals..., &crc16)) + return -1; + if (crc16) + return -1; + return 0; + } + + // @brief Stores one or more consecutive objects to the NVM. In addition to the + // provided objects, a CRC of the data is stored. + // + // The CRC includes a version number and thus adds some protection against + // changes of the config structs during firmware update. Note that if the total + // config data length changes, the CRC validation will fail even if the developer + // forgets to update the config version number. + static int store_config(const T* val0, const Ts* ... vals) { + size_t size = Config::get_size() + 2; + //printf("config is %d bytes\r\n", size); osDelay(5); + if (size > NVM_get_max_write_length()) + return -1; + if (NVM_start_write(size)) + return -1; + uint16_t crc16 = CRC16_INIT ^ config_version; + if (Config::store_config(0, &crc16, val0, vals...)) + return -1; + if (Config::store_config(size - 2, nullptr, (uint8_t *)&crc16 + 1, (uint8_t *)&crc16)) + return -1; + if (NVM_commit()) + return -1; + return 0; + } +}; + +// This function is obviously stupid and should go away (make MotorConfig_t a member of Motor_t) +// TODO: make this go away as part of the C++ refactoring +void set_motor_config(const MotorConfig_t* config, Motor_t* motor) { + motor->control_mode = config->control_mode; + motor->counts_per_step = config->counts_per_step; + motor->pole_pairs = config->pole_pairs; + motor->pos_gain = config->pos_gain; + motor->vel_gain = config->vel_gain; + motor->vel_integrator_gain = config->vel_integrator_gain; + motor->vel_limit = config->vel_limit; + motor->calibration_current = config->calibration_current; + motor->resistance_calib_max_voltage = config->resistance_calib_max_voltage; + motor->phase_inductance = config->phase_inductance; + motor->phase_resistance = config->phase_resistance; + motor->motor_type = config->motor_type; + motor->rotor_mode = config->rotor_mode; + + motor->current_control.current_lim = config->current_control_current_lim; + + motor->encoder.use_index = config->encoder_use_index; + motor->encoder.manually_calibrated = config->encoder_manually_calibrated; + motor->encoder.idx_search_speed = config->encoder_idx_search_speed; + motor->encoder.encoder_cpr = config->encoder_cpr; + motor->encoder.encoder_offset = config->encoder_offset; + motor->encoder.motor_dir = config->encoder_motor_dir; +} + +// This function is obviously stupid and should go away (make MotorConfig_t a member of Motor_t) +// TODO: make this go away as part of the C++ refactoring +void get_motor_config(const Motor_t* motor, MotorConfig_t* config) { + config->control_mode = motor->control_mode; + config->counts_per_step = motor->counts_per_step; + config->pole_pairs = motor->pole_pairs; + config->pos_gain = motor->pos_gain; + config->vel_gain = motor->vel_gain; + config->vel_integrator_gain = motor->vel_integrator_gain; + config->vel_limit = motor->vel_limit; + config->calibration_current = motor->calibration_current; + config->resistance_calib_max_voltage = motor->resistance_calib_max_voltage; + config->phase_inductance = motor->phase_inductance; + config->phase_resistance = motor->phase_resistance; + config->motor_type = motor->motor_type; + config->rotor_mode = motor->rotor_mode; + + config->current_control_current_lim = motor->current_control.current_lim; + + config->encoder_use_index = motor->encoder.use_index; + config->encoder_manually_calibrated = motor->encoder.manually_calibrated; + config->encoder_idx_search_speed = motor->encoder.idx_search_speed; + config->encoder_cpr = motor->encoder.encoder_cpr; + config->encoder_offset = motor->encoder.encoder_offset; + config->encoder_motor_dir = motor->encoder.motor_dir; +} + + +void init_configuration(void) { + MotorConfig_t motor_config[2]; + //TODO: we really shouldn't be hardcoding like this + if (NVM_init() || Config::load_config(&motor_config[0], &motor_config[1], &axis_configs[0], &axis_configs[1], &brake_resistance)) { + //printf("no config found\r\n"); osDelay(5); + // load default config + // motor_config[0] = MotorConfig_t(); + // motor_config[1] = MotorConfig_t(); + + // Default config coming from flashed Motor_t + return; + } else { + //printf("load config successful\r\n"); osDelay(5); + } + + set_motor_config(&motor_config[0], &motors[0]); + set_motor_config(&motor_config[1], &motors[1]); +} + +void save_configuration(void) { + MotorConfig_t motor_config[2]; + get_motor_config(&motors[0], &motor_config[0]); + get_motor_config(&motors[1], &motor_config[1]); + //TODO: we really shouldn't be hardcoding like this + if (Config::store_config(&motor_config[0], &motor_config[1], &axis_configs[0], &axis_configs[1], &brake_resistance)) { + //printf("saving configuration failed\r\n"); osDelay(5); + } +} + +void erase_configuration(void) { + NVM_erase(); +} diff --git a/Firmware/MotorControl/config.h b/Firmware/MotorControl/config.h new file mode 100644 index 00000000..57fafcca --- /dev/null +++ b/Firmware/MotorControl/config.h @@ -0,0 +1,16 @@ +#ifndef __CONFIG_H +#define __CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +void init_configuration(void); +void save_configuration(void); +void erase_configuration(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __CONFIG_H */ diff --git a/Firmware/MotorControl/low_level.c b/Firmware/MotorControl/low_level.c index 96826b0d..c1e99742 100644 --- a/Firmware/MotorControl/low_level.c +++ b/Firmware/MotorControl/low_level.c @@ -33,11 +33,6 @@ // Arbitrary non-zero inital value to avoid division by zero if ADC reading is late float vbus_voltage = 12.0f; -// TODO stick parameter into struct -#define ENCODER_CPR (2048 * 4) // Default resolution of CUI-AMT102 encoder -#define POLE_PAIRS 7 // This value is correct for N5065 motors and Turnigy SK3 series. -const float elec_rad_per_enc = POLE_PAIRS * 2 * M_PI * (1.0f / (float)ENCODER_CPR); - #if HW_VERSION_MAJOR == 3 #if HW_VERSION_MINOR <= 3 #define SHUNT_RESISTANCE (675e-6f) @@ -59,6 +54,7 @@ Motor_t motors[] = { .enable_step_dir = false, //auto enabled after calibration .counts_per_step = 2.0f, .error = ERROR_NO_ERROR, + .pole_pairs = 7, // This value is correct for N5065 motors and Turnigy SK3 series. .pos_setpoint = 0.0f, .pos_gain = 20.0f, // [(counts/s) / counts] .vel_setpoint = 0.0f, @@ -72,6 +68,7 @@ Motor_t motors[] = { .current_setpoint = 0.0f, // [A] .calibration_current = 10.0f, // [A] .resistance_calib_max_voltage = 1.0f, // [V] - You may need to increase this if this voltage isn't sufficient to drive calibration_current through the motor. + .dc_bus_brownout_trip_level = 8.0f, // [V] .phase_inductance = 0.0f, // to be set by measure_phase_inductance .phase_resistance = 0.0f, // to be set by measure_phase_resistance .motor_thread = 0, @@ -123,12 +120,13 @@ Motor_t motors[] = { .encoder_timer = &htim3, .use_index = false, .index_found = false, - .calibrated = false, + .manually_calibrated = false, .idx_search_speed = 10.0f, // [rad/s electrical] - .encoder_cpr = ENCODER_CPR, + .encoder_cpr = (2048 * 4), // Default resolution of CUI-AMT102 encoder, .encoder_offset = 0, .encoder_state = 0, .motor_dir = 1, // 1 or -1 + .encoder_calib_range = 0.02, .phase = 0.0f, // [rad] .pll_pos = 0.0f, // [rad] .pll_vel = 0.0f, // [rad/s] @@ -151,7 +149,6 @@ Motor_t motors[] = { .spin_up_target_vel = 400.0f, // [rad/s] }, .loop_counter = 0, - .timing_log_index = 0, .timing_log = {0}, .anticogging = { .index = 0, @@ -161,12 +158,14 @@ Motor_t motors[] = { .calib_pos_threshold = 1.0f, .calib_vel_threshold = 1.0f, }, + .drv_fault = DRV8301_FaultType_NoFault, }, { // M1 .control_mode = CTRL_MODE_POSITION_CONTROL, //see: Motor_control_mode_t .enable_step_dir = false, //auto enabled after calibration .counts_per_step = 2.0f, .error = ERROR_NO_ERROR, + .pole_pairs = 7, // This value is correct for N5065 motors and Turnigy SK3 series. .pos_setpoint = 0.0f, .pos_gain = 20.0f, // [(counts/s) / counts] .vel_setpoint = 0.0f, @@ -177,6 +176,7 @@ Motor_t motors[] = { .current_setpoint = 0.0f, // [A] .calibration_current = 10.0f, // [A] .resistance_calib_max_voltage = 1.0f, // [V] - You may need to increase this if this voltage isn't sufficient to drive calibration_current through the motor. + .dc_bus_brownout_trip_level = 8.0f, // [V] .phase_inductance = 0.0f, // to be set by measure_phase_inductance .phase_resistance = 0.0f, // to be set by measure_phase_resistance .motor_thread = 0, @@ -225,12 +225,13 @@ Motor_t motors[] = { .encoder_timer = &htim4, .use_index = false, .index_found = false, - .calibrated = false, + .manually_calibrated = false, .idx_search_speed = 10.0f, // [rad/s electrical] - .encoder_cpr = ENCODER_CPR, + .encoder_cpr = (2048 * 4), // Default resolution of CUI-AMT102 encoder, .encoder_offset = 0, .encoder_state = 0, .motor_dir = 1, // 1 or -1 + .encoder_calib_range = 0.02, .phase = 0.0f, // [rad] .pll_pos = 0.0f, // [rad] .pll_vel = 0.0f, // [rad/s] @@ -253,7 +254,6 @@ Motor_t motors[] = { .spin_up_target_vel = 400.0f, // [rad/s] }, .loop_counter = 0, - .timing_log_index = 0, .timing_log = {0}, .anticogging = { .index = 0, @@ -262,11 +262,14 @@ Motor_t motors[] = { .calib_anticogging = false, .calib_pos_threshold = 1.0f, .calib_vel_threshold = 1.0f, - } + }, + .drv_fault = DRV8301_FaultType_NoFault, } }; const size_t num_motors = sizeof(motors) / sizeof(motors[0]); +float brake_resistance = 0.47f; // [ohm] + /* Private constant data -----------------------------------------------------*/ static const float one_by_sqrt3 = 0.57735026919f; static const float sqrt3_by_2 = 0.86602540378f; @@ -274,8 +277,6 @@ static const float current_meas_period = CURRENT_MEAS_PERIOD; static const int current_meas_hz = CURRENT_MEAS_HZ; /* Private variables ---------------------------------------------------------*/ -static float brake_resistance = 0.47f; // [ohm] - /* Function implementations --------------------------------------------------*/ //-------------------------------- @@ -313,7 +314,7 @@ void set_current_setpoint(Motor_t* motor, float current_setpoint) { // Utility //-------------------------------- -uint16_t check_timing(Motor_t* motor) { +uint16_t check_timing(Motor_t* motor, TimingLog_t log_idx) { TIM_HandleTypeDef* htim = motor->motor_timer; uint16_t timing = htim->Instance->CNT; bool down = htim->Instance->CR1 & TIM_CR1_DIR; @@ -322,10 +323,9 @@ uint16_t check_timing(Motor_t* motor) { timing = TIM_1_8_PERIOD_CLOCKS + delta; } - if (++(motor->timing_log_index) == TIMING_LOG_SIZE) { - motor->timing_log_index = 0; + if (log_idx < TIMING_LOG_SIZE) { + motor->timing_log[log_idx] = timing; } - motor->timing_log[motor->timing_log_index] = timing; return timing; } @@ -553,6 +553,7 @@ void step_cb(uint16_t GPIO_Pin) { } // Triggered when an encoder passes over the "Index" pin +// TODO: only arm index edge interrupt when we know encoder has powered up void enc_index_cb(uint16_t GPIO_Pin, uint8_t motor_index) { Motor_t* motor = &motors[motor_index]; if (!motor->encoder.index_found) { @@ -604,7 +605,7 @@ void pwm_trig_adc_cb(ADC_HandleTypeDef* hadc, bool injected) { motors[0].motor_timer->Instance->CCR3 = motors[0].next_timings[2]; } // Check the timing of the sequencing - check_timing(motor); + check_timing(motor, TIMING_LOG_ADC_CB_M1_DC); } else if (motor == &motors[0] && !counting_down) { // We are measuring M0 current here @@ -616,19 +617,19 @@ void pwm_trig_adc_cb(ADC_HandleTypeDef* hadc, bool injected) { motors[1].motor_timer->Instance->CCR3 = motors[1].next_timings[2]; } // Check the timing of the sequencing - check_timing(motor); + check_timing(motor, TIMING_LOG_ADC_CB_M0_I); } else if (motor == &motors[1] && !counting_down) { // We are measuring M1 current here current_meas_not_DC_CAL = true; // Check the timing of the sequencing - check_timing(motor); + check_timing(motor, TIMING_LOG_ADC_CB_M1_I); } else if (motor == &motors[0] && counting_down) { // We are measuring M0 DC_CAL here current_meas_not_DC_CAL = false; // Check the timing of the sequencing - check_timing(motor); + check_timing(motor, TIMING_LOG_ADC_CB_M0_DC); } else { global_fault(ERROR_PWM_SRC_FAIL); @@ -685,6 +686,9 @@ bool measure_phase_resistance(Motor_t* motor, float test_current, float max_volt motor->error = ERROR_PHASE_RESISTANCE_MEASUREMENT_TIMEOUT; return false; } + if (!do_checks(motor)) + return false; + float Ialpha = -(motor->current_meas.phB + motor->current_meas.phC); test_voltage += (kI * current_meas_period) * (test_current - Ialpha); if (test_voltage > max_voltage) test_voltage = max_voltage; @@ -694,7 +698,7 @@ bool measure_phase_resistance(Motor_t* motor, float test_current, float max_volt queue_voltage_timings(motor, test_voltage, 0.0f); // Check we meet deadlines after queueing - motor->last_cpu_time = check_timing(motor); + motor->last_cpu_time = check_timing(motor, TIMING_LOG_MEAS_R); if (!(motor->last_cpu_time < motor->control_deadline)) { motor->error = ERROR_PHASE_RESISTANCE_TIMING; return false; @@ -724,13 +728,16 @@ bool measure_phase_inductance(Motor_t* motor, float voltage_low, float voltage_h motor->error = ERROR_PHASE_INDUCTANCE_MEASUREMENT_TIMEOUT; return false; } + if (!do_checks(motor)) + return false; + Ialphas[i] += -motor->current_meas.phB - motor->current_meas.phC; // Test voltage along phase A queue_voltage_timings(motor, test_voltages[i], 0.0f); // Check we meet deadlines after queueing - motor->last_cpu_time = check_timing(motor); + motor->last_cpu_time = check_timing(motor, TIMING_LOG_MEAS_L); if (!(motor->last_cpu_time < motor->control_deadline)) { motor->error = ERROR_PHASE_INDUCTANCE_TIMING; return false; @@ -760,22 +767,25 @@ bool measure_phase_inductance(Motor_t* motor, float voltage_low, float voltage_h // TODO: add check_timing bool calib_enc_offset(Motor_t* motor, float voltage_magnitude) { static const float start_lock_duration = 1.0f; - static const int num_steps = 1024; + static const int num_steps = 1024*2; static const float dt_step = 1.0f / 500.0f; - static const float scan_range = 4.0f * M_PI; + static const float scan_range = 16.0f * M_PI; const float step_size = scan_range / (float)num_steps; // TODO handle const expressions better (maybe switch to C++ ?) - int32_t init_enc_val = (int16_t)motor->encoder.encoder_timer->Instance->CNT; - int32_t encvaluesum = 0; - // go to motor zero phase for start_lock_duration to get ready to scan for (int i = 0; i < start_lock_duration * current_meas_hz; ++i) { if (osSignalWait(M_SIGNAL_PH_CURRENT_MEAS, PH_CURRENT_MEAS_TIMEOUT).status != osEventSignal) { motor->error = ERROR_ENCODER_MEASUREMENT_TIMEOUT; return false; } + if (!do_checks(motor)) + return false; queue_voltage_timings(motor, voltage_magnitude, 0.0f); } + + int32_t init_enc_val = (int16_t)motor->encoder.encoder_timer->Instance->CNT; + int32_t encvaluesum = 0; + // scan forwards for (float ph = -scan_range / 2.0f; ph < scan_range / 2.0f; ph += step_size) { for (int i = 0; i < dt_step * (float)current_meas_hz; ++i) { @@ -783,12 +793,24 @@ bool calib_enc_offset(Motor_t* motor, float voltage_magnitude) { motor->error = ERROR_ENCODER_MEASUREMENT_TIMEOUT; return false; } + if (!do_checks(motor)) + return false; float v_alpha = voltage_magnitude * arm_cos_f32(ph); float v_beta = voltage_magnitude * arm_sin_f32(ph); queue_voltage_timings(motor, v_alpha, v_beta); } encvaluesum += (int16_t)motor->encoder.encoder_timer->Instance->CNT; } + + //TODO avoid recomputing elec_rad_per_enc every time + float elec_rad_per_enc = motor->pole_pairs * 2 * M_PI * (1.0f / (float)(motor->encoder.encoder_cpr)); + float expected_encoder_delta = scan_range / elec_rad_per_enc; + float actual_encoder_delta_abs = fabsf((int16_t)motor->encoder.encoder_timer->Instance->CNT-init_enc_val); + if(fabsf(actual_encoder_delta_abs - expected_encoder_delta)/expected_encoder_delta > motor->encoder.encoder_calib_range) + { + motor->error = ERROR_ENCODER_CPR_OUT_OF_RANGE; + return false; + } // check direction if ((int16_t)motor->encoder.encoder_timer->Instance->CNT > init_enc_val + 8) { // motor same dir as encoder @@ -808,6 +830,8 @@ bool calib_enc_offset(Motor_t* motor, float voltage_magnitude) { motor->error = ERROR_ENCODER_MEASUREMENT_TIMEOUT; return false; } + if (!do_checks(motor)) + return false; float v_alpha = voltage_magnitude * arm_cos_f32(ph); float v_beta = voltage_magnitude * arm_sin_f32(ph); queue_voltage_timings(motor, v_alpha, v_beta); @@ -817,7 +841,6 @@ bool calib_enc_offset(Motor_t* motor, float voltage_magnitude) { int offset = encvaluesum / (num_steps * 2); motor->encoder.encoder_offset = offset; - motor->encoder.calibrated = true; return true; } @@ -846,7 +869,7 @@ bool motor_calibration(Motor_t* motor) { (float)(motor->encoder.motor_dir) * motor->encoder.idx_search_speed, enc_calibration_voltage)) return false; - if (!motor->encoder.calibrated) + if (!motor->encoder.manually_calibrated) if (!calib_enc_offset(motor, enc_calibration_voltage)) return false; } @@ -889,7 +912,7 @@ bool anti_cogging_calibration(Motor_t* motor) { fabsf(motor->encoder.pll_vel) < motor->anticogging.calib_vel_threshold) { motor->anticogging.cogging_map[motor->anticogging.index++] = motor->vel_integrator_current; } - if (motor->anticogging.index < ENCODER_CPR) { + if (motor->anticogging.index < motor->encoder.encoder_cpr) { set_pos_setpoint(motor, motor->anticogging.index, 0.0f, 0.0f); return false; } else { @@ -911,6 +934,8 @@ bool scan_for_enc_idx(Motor_t* motor, float omega, float voltage_magnitude) { for (;;) { for (float ph = 0.0f; ph < 2.0f * M_PI; ph += omega * current_meas_period) { osSignalWait(M_SIGNAL_PH_CURRENT_MEAS, osWaitForever); + if (!do_checks(motor)) + return false; if (motor->encoder.index_found) return true; @@ -920,7 +945,7 @@ bool scan_for_enc_idx(Motor_t* motor, float omega, float voltage_magnitude) { queue_voltage_timings(motor, v_alpha, v_beta); // Check we meet deadlines after queueing - motor->last_cpu_time = check_timing(motor); + motor->last_cpu_time = check_timing(motor, TIMING_LOG_IDX_SEARCH); if (!(motor->last_cpu_time < motor->control_deadline)) { motor->error = ERROR_SCAN_MOTOR_TIMING; return false; @@ -945,9 +970,11 @@ void update_rotor(Motor_t* motor) { encoder->encoder_state += (int32_t)delta_enc; // compute electrical phase - int corrected_enc = encoder->encoder_state % ENCODER_CPR; + int corrected_enc = encoder->encoder_state % motor->encoder.encoder_cpr; corrected_enc -= encoder->encoder_offset; corrected_enc *= encoder->motor_dir; + //TODO avoid recomputing elec_rad_per_enc every time + float elec_rad_per_enc = motor->pole_pairs * 2 * M_PI * (1.0f / (float)(motor->encoder.encoder_cpr)); float ph = elec_rad_per_enc * (float)corrected_enc; // ph = fmodf(ph, 2*M_PI); encoder->phase = wrap_pm_pi(ph); @@ -1101,8 +1128,13 @@ bool spin_up_timestep(Motor_t* motor, float phase, float I_mag) { motor->error = ERROR_SPIN_UP_TIMEOUT; return false; } + + if (!do_checks(motor)) + return false; // run estimator - update_rotor(motor); + if (!loop_updates(motor)) + return false; + // override the phase during spinup motor->sensorless.phase = phase; // run current control (with the phase override) @@ -1191,6 +1223,8 @@ void queue_voltage_timings(Motor_t* motor, float v_alpha, float v_beta) { queue_modulation_timings(motor, mod_alpha, mod_beta); } +// TODO: This doesn't update brake current +// We should probably make FOC Current call FOC Voltage to avoid duplication. bool FOC_voltage(Motor_t* motor, float v_d, float v_q) { float phase = get_rotor_phase(motor); float c = arm_cos_f32(phase); @@ -1200,7 +1234,7 @@ bool FOC_voltage(Motor_t* motor, float v_d, float v_q) { queue_voltage_timings(motor, v_alpha, v_beta); // Check we meet deadlines after queueing - if (!(check_timing(motor) < motor->control_deadline)) { + if (!(check_timing(motor, TIMING_LOG_FOC_VOLTAGE) < motor->control_deadline)) { motor->error = ERROR_FOC_VOLTAGE_TIMING; return false; } @@ -1268,19 +1302,52 @@ bool FOC_current(Motor_t* motor, float Id_des, float Iq_des) { queue_modulation_timings(motor, mod_alpha, mod_beta); // Check we meet deadlines after queueing - motor->last_cpu_time = check_timing(motor); + motor->last_cpu_time = check_timing(motor, TIMING_LOG_FOC_CURRENT); if (!(motor->last_cpu_time < motor->control_deadline)) { motor->error = ERROR_FOC_TIMING; return false; } + + update_brake_current(); + return true; +} + +//Returns true if everything is OK (no fault) +bool check_DRV_fault(Motor_t* motor) { + //TODO: make this pin configurable per motor ch + GPIO_PinState nFAULT_state = HAL_GPIO_ReadPin(nFAULT_GPIO_Port, nFAULT_Pin); + return (nFAULT_state == GPIO_PIN_RESET) ? false : true; +} + +//Returns true if everything is OK (no fault) +bool check_PSU_brownout(Motor_t* motor) { + if(vbus_voltage < motor->dc_bus_brownout_trip_level) + return false; + return true; +} + +// Returns true if everything is ok. Sets motor->error and returns false otherwise. +bool do_checks(Motor_t* motor) { + if (!check_DRV_fault(motor)) { + motor->error = ERROR_DRV_FAULT; + // Update DRV Fault Code + motor->drv_fault = DRV8301_getFaultType(&motor->gate_driver); + // Update/Cache all SPI device registers + DRV_SPI_8301_Vars_t* local_regs = &motor->gate_driver_regs; + local_regs->RcvCmd = true; + DRV8301_readData(&motor->gate_driver, local_regs); + return false; + } + if (!check_PSU_brownout(motor)) { + motor->error = ERROR_DC_BUS_BROWNOUT; + return false; + } return true; } -//Returns true if the fault line is asserted -bool check_DRV_fault(Motor_t* motor) { - //TODO: make this pin configurable per motor ch - GPIO_PinState nFAULT_state = HAL_GPIO_ReadPin(nFAULT_GPIO_Port, nFAULT_Pin); - return (nFAULT_state == GPIO_PIN_RESET) ? true : false; +bool loop_updates(Motor_t* motor) { + update_rotor(motor); + return true; } void control_motor_loop(Motor_t* motor) { @@ -1289,12 +1356,14 @@ void control_motor_loop(Motor_t* motor) { motor->error = ERROR_FOC_MEASUREMENT_TIMEOUT; break; } - if (check_DRV_fault(motor)) { - motor->error = ERROR_DRV_FAULT; + + if (!do_checks(motor)) break; - } - update_rotor(motor); - anti_cogging_calibration(motor); // Only runs if anticogging.calib_anticogging is true; non-blocking + if (!loop_updates(motor)) + break; + + // Only runs if anticogging.calib_anticogging is true; non-blocking + anti_cogging_calibration(motor); // Position control // TODO Decide if we want to use encoder or pll position here @@ -1318,9 +1387,9 @@ void control_motor_loop(Motor_t* motor) { // Anti-cogging is enabled after calibration // We get the current position and apply a current feed-forward - // ensuring that we handle negative encoder positions properly (-1 == ENCODER_CPR - 1) + // ensuring that we handle negative encoder positions properly (-1 == motor->encoder.encoder_cpr - 1) if (motor->anticogging.use_anticogging) { - Iq += motor->anticogging.cogging_map[mod(motor->encoder.pll_pos, ENCODER_CPR)]; + Iq += motor->anticogging.cogging_map[mod(motor->encoder.pll_pos, motor->encoder.encoder_cpr)]; } float v_err = vel_des - get_pll_vel(motor); @@ -1377,7 +1446,6 @@ void control_motor_loop(Motor_t* motor) { break; } - update_brake_current(); ++(motor->loop_counter); } diff --git a/Firmware/MotorControl/low_level.h b/Firmware/MotorControl/low_level.h index 9045b1d9..e92774e4 100644 --- a/Firmware/MotorControl/low_level.h +++ b/Firmware/MotorControl/low_level.h @@ -50,21 +50,23 @@ typedef enum { ERROR_SPIN_UP_TIMEOUT, ERROR_DRV_FAULT, ERROR_NOT_IMPLEMENTED_MOTOR_TYPE, + ERROR_ENCODER_CPR_OUT_OF_RANGE, + ERROR_DC_BUS_BROWNOUT, } Error_t; // Note: these should be sorted from lowest level of control to // highest level of control, to allow "<" style comparisons. typedef enum { - CTRL_MODE_VOLTAGE_CONTROL, - CTRL_MODE_CURRENT_CONTROL, - CTRL_MODE_VELOCITY_CONTROL, - CTRL_MODE_POSITION_CONTROL + CTRL_MODE_VOLTAGE_CONTROL = 0, + CTRL_MODE_CURRENT_CONTROL = 1, + CTRL_MODE_VELOCITY_CONTROL = 2, + CTRL_MODE_POSITION_CONTROL = 3 } Motor_control_mode_t; typedef enum { - MOTOR_TYPE_HIGH_CURRENT, - // MOTOR_TYPE_LOW_CURRENT, //Not yet implemented - MOTOR_TYPE_GIMBAL + MOTOR_TYPE_HIGH_CURRENT = 0, + // MOTOR_TYPE_LOW_CURRENT = 1, //Not yet implemented + MOTOR_TYPE_GIMBAL = 2 } Motor_type_t; typedef struct { @@ -113,12 +115,13 @@ typedef struct { TIM_HandleTypeDef* encoder_timer; bool use_index; bool index_found; - bool calibrated; + bool manually_calibrated; float idx_search_speed; - int encoder_cpr; + int32_t encoder_cpr; int32_t encoder_offset; int32_t encoder_state; int32_t motor_dir; // 1/-1 for fwd/rev alignment to encoder. + float encoder_calib_range; float phase; float pll_pos; float pll_vel; @@ -137,6 +140,7 @@ typedef struct { bool enable_step_dir; float counts_per_step; Error_t error; + int32_t pole_pairs; float pos_setpoint; float pos_gain; float vel_setpoint; @@ -147,6 +151,7 @@ typedef struct { float current_setpoint; float calibration_current; float resistance_calib_max_voltage; + float dc_bus_brownout_trip_level; float phase_inductance; float phase_resistance; osThreadId motor_thread; @@ -170,7 +175,6 @@ typedef struct { Encoder_t encoder; Sensorless_t sensorless; uint32_t loop_counter; - int timing_log_index; uint16_t timing_log[TIMING_LOG_SIZE]; // Cache for remote procedure calls arguments struct { @@ -186,8 +190,23 @@ typedef struct { float current_setpoint; } set_current_setpoint_args; Anticogging_t anticogging; + DRV8301_FaultType_e drv_fault; } Motor_t; +typedef enum { + TIMING_LOG_GENERAL, + TIMING_LOG_ADC_CB_M0_I, + TIMING_LOG_ADC_CB_M0_DC, + TIMING_LOG_ADC_CB_M1_I, + TIMING_LOG_ADC_CB_M1_DC, + TIMING_LOG_MEAS_R, + TIMING_LOG_MEAS_L, + TIMING_LOG_ENC_CALIB, + TIMING_LOG_IDX_SEARCH, + TIMING_LOG_FOC_VOLTAGE, + TIMING_LOG_FOC_CURRENT, +} TimingLog_t; + typedef struct{ int type; int index; @@ -198,6 +217,7 @@ extern const size_t num_motors; extern const float elec_rad_per_enc; /* Exported variables --------------------------------------------------------*/ extern float vbus_voltage; +extern float brake_resistance; extern Motor_t motors[]; /* Exported macro ------------------------------------------------------------*/ /* Exported functions --------------------------------------------------------*/ @@ -223,7 +243,7 @@ bool motor_calibration(Motor_t* motor); //// Old private: // Utility -uint16_t check_timing(Motor_t* motor); +uint16_t check_timing(Motor_t* motor, TimingLog_t log_idx); void global_fault(int error); float phase_current_from_adcval(Motor_t* motor, uint32_t ADCValue); // Initalisation @@ -243,6 +263,8 @@ bool anti_cogging_calibration(Motor_t* motor); // Test functions void scan_motor_loop(Motor_t* motor, float omega, float voltage_magnitude); // Main motor control +bool do_checks(Motor_t* motor); +bool loop_updates(Motor_t* motor); void update_rotor(Motor_t* motor); bool using_encoder(Motor_t* motor); bool using_sensorless(Motor_t* motor); diff --git a/Firmware/MotorControl/nvm.c b/Firmware/MotorControl/nvm.c new file mode 100644 index 00000000..e581beee --- /dev/null +++ b/Firmware/MotorControl/nvm.c @@ -0,0 +1,451 @@ +/* +* Flash-based Non-Volatile Memory (NVM) +* +* This file supports storing and loading persistent configuration based on +* the STM32 builtin flash memory. +* +* The STM32F405xx has 12 flash sectors of heterogeneous size. We use the last +* two sectors for configuration data. These pages have a size of 128kB each. +* Setting any bit in these sectors to 0 is always possible, but setting them +* to 1 requires erasing the whole sector. +* +* We consider each sector as an array of 64-bit fields except the first N bytes, which we +* instead use as an allocation block. The allocation block is a compact bit-field (2 bit per entry) +* that keeps track of the state of each field (erased, invalid, valid). +* +* One sector is always considered the valid (read) sector and the other one is the +* target for the next write access: they can be considered to be ping-pong or double buffred. +* +* When writing a block of data, instead of always erasing the whole writable sector the +* new data is appended in the erased area. This presumably increases flash life span. +* The writable sector is only erased if there is not enough space for the new data. +* +* On startup, if there is exactly one sector +* whose last non-erased value has the state "valid" that sector is considered +* the valid sector. In any other case the selection is undefined. +* +* +* To write a new block of data atomically we first mark all associated fields +* as "invalid" (in the allocation table) then write the data and then mark the +* fields as "valid" (in the direction of increasing address). +*/ + +#include "nvm.h" + +#include +#include +#include + +#if defined(STM32F405xx) + +// refer to page 75 of datasheet: +// http://www.st.com/content/ccc/resource/technical/document/reference_manual/3d/6d/5a/66/b4/99/40/d4/DM00031020.pdf/files/DM00031020.pdf/jcr:content/translations/en.DM00031020.pdf +#define FLASH_SECTOR_10_BASE (const volatile uint8_t*)0x80C0000UL +#define FLASH_SECTOR_10_SIZE 0x20000UL +#define FLASH_SECTOR_11_BASE (const volatile uint8_t*)0x80E0000UL +#define FLASH_SECTOR_11_SIZE 0x20000UL + +#define HAL_FLASH_ClearError() __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGSERR | FLASH_FLAG_PGPERR) +#else +#error "unknown flash sector size" +#endif + +typedef enum { + VALID = 0, + INVALID = 1, + ERASED = 3 +} field_state_t; + +typedef struct { + size_t index; //!< next field to be written to (can be equal to n_data) + const uint32_t sector_id; //!< HAL ID of this sector + const size_t n_data; //!< number of 64-bit fields in this sector + const size_t n_reserved; //!< number of 64-bit fields in this sector that are reserved for the allocation table + const volatile uint8_t* const alloc_table; + const volatile uint64_t* const data; +} sector_t; + +sector_t sectors[] = { { + .sector_id = FLASH_SECTOR_10, + .n_data = FLASH_SECTOR_10_SIZE >> 3, + .n_reserved = (FLASH_SECTOR_10_SIZE >> 3) >> 5, + .alloc_table = FLASH_SECTOR_10_BASE, + .data = (uint64_t *)FLASH_SECTOR_10_BASE +}, { + .sector_id = FLASH_SECTOR_11, + .n_data = FLASH_SECTOR_11_SIZE >> 3, + .n_reserved = (FLASH_SECTOR_11_SIZE >> 3) >> 5, + .alloc_table = FLASH_SECTOR_11_BASE, + .data = (uint64_t *)FLASH_SECTOR_11_BASE +}}; + +uint8_t read_sector_; // 0 or 1 to indicate which sector to read from and which to write to +size_t n_staging_area_; // number of 64-bit values that were reserved using NVM_start_write +size_t n_valid_; // number of 64-bit fields that can be read + +// @brief Erases a flash sector. This sets all bits in the sector to 1. +// The sector's current index is reset to the minimum value (n_reserved). +// @returns 0 on success or a non-zero error code otherwise +int erase(sector_t *sector) { + FLASH_EraseInitTypeDef erase_struct = { + .TypeErase = FLASH_TYPEERASE_SECTORS, + .Banks = 0, // only used for mass erase + .Sector = sector->sector_id, + .NbSectors = 1, + .VoltageRange = FLASH_VOLTAGE_RANGE_3 + }; + HAL_FLASH_Unlock(); + HAL_FLASH_ClearError(); + uint32_t sector_error; + if (HAL_FLASHEx_Erase(&erase_struct, §or_error) != HAL_OK) + goto fail; + sector->index = sector->n_reserved; + + HAL_FLASH_Lock(); + return 0; +fail: + HAL_FLASH_Lock(); + //printf("erase failed: %u \r\n", HAL_FLASH_GetError()); + return HAL_FLASH_GetError(); // non-zero +} + + +// @brief Writes states into the allocation table. +// The write operation goes in the direction of increasing indices. +// @param state: 11: erased, 10: writing, 00: valid data +// @returns 0 on success or a non-zero error code otherwise +int set_allocation_state(sector_t *sector, size_t index, size_t count, field_state_t state) { + if (index < sector->n_reserved) + return -1; + if (index + count >= sector->n_data) + return -1; + + // expand state to state for 4 values + const uint8_t states = (state << 0) | (state << 2) | (state << 4) | (state << 6); + + // handle unaligned start + uint8_t mask = ~(0xff << ((index & 0x3) << 1)); + count += index & 0x3; + index -= index & 0x3; + + HAL_FLASH_Unlock(); + HAL_FLASH_ClearError(); + + // write states + for (; count >= 4; count -= 4, index += 4) { + if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, (uintptr_t)§or->alloc_table[index >> 2], states | mask) != HAL_OK) + goto fail; + mask = 0; + } + + // handle unaligned end + if (count) { + mask |= ~(0xff >> ((4 - count) << 1)); + if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, (uintptr_t)§or->alloc_table[index >> 2], states | mask) != HAL_OK) + goto fail; + } + + HAL_FLASH_Lock(); + return 0; +fail: + HAL_FLASH_Lock(); + return HAL_FLASH_GetError(); // non-zero +} + +// @brief Reads the allocation table from behind to determine how many fields match the +// reference state. +// @param sector: The sector on which to perform the search +// @param max_index: The maximum index that should be considered +// @param ref_state: The reference state +// @param state: Set to the first encountered state that is unequal to ref_state. +// Set to ref_state if all encountered states are equal to ref_state. +// @returns The smallest index that points to a field with ref_state. +// This value is at least sector->n_reserved and at most max_index. +size_t scan_allocation_table(sector_t *sector, size_t max_index, field_state_t ref_state, field_state_t *state) { + const uint8_t ref_states = (ref_state << 0) | (ref_state << 2) | (ref_state << 4) | (ref_state << 6); + size_t index = (((max_index + 3) >> 2) << 2); // start at the max index but round up to a multiple of 4 + size_t ignore = index - max_index; + uint8_t states = ref_states; + + //printf("scan from %08x to %08x for %02x\r\n", index, sector->n_reserved, ref_states); osDelay(5); + + // read 4 states at a time + for (; index >= (sector->n_reserved + 4); index -= 4) { + states = sector->alloc_table[(index - 1) >> 2]; + if (ignore) { // ignore the upper 1, 2 or 3 states if max_index was unaligned + uint8_t ignore_mask = ~(0xff >> (ignore << 1)); + states = (states & ~ignore_mask) | (ref_states & ignore_mask); + ignore = 0; + } + if (states != ref_states) + break; + } + + // once we encounterd a byte with any state mismatch determine which of the 4 states it is + for (; ((states >> 6) == (ref_states & 0x3)) && (index > sector->n_reserved); index--) { + states <<= 2; + } + + *state = states >> 6; + //printf("(it's %02x)\r\n", index); osDelay(5); + return index; +} + +// Loads the head of the NVM data. +// If this function fails subsequent calls to NVM functions (other than NVM_init or NVM_erase) +// cause undefined behavior. +// @returns 0 on success or a non-zero error code otherwise +int NVM_init(void) { + field_state_t sector0_state, sector1_state; + sectors[0].index = scan_allocation_table(§ors[0], sectors[0].n_data, + ERASED, §or0_state); + sectors[1].index = scan_allocation_table(§ors[1], sectors[1].n_data, + ERASED, §or1_state); + //printf("sector states: %02x, %02x\r\n", sector0_state, sector1_state); osDelay(5); + + // Select valid sector on a best effort basis + // (in unfortunate cases valid_sector might actually point + // to an invalid or erased sector) + read_sector_ = 0; + if (sector1_state == VALID) + read_sector_ = 1; + + // count the number of valid fields + sector_t *read_sector = §ors[read_sector_]; + uint8_t first_nonvalid_state; + size_t min_valid_index = scan_allocation_table(read_sector, read_sector->index, + VALID, &first_nonvalid_state); + n_valid_ = read_sector->index - min_valid_index; + + n_staging_area_ = 0; + + int status = 0; + /*// bring non-valid sectors into a known state + this is not absolutely required + if (sector0_state != VALID) + status |= erase(§ors[0]); + if (sector1_state != VALID) + status |= erase(§ors[1]); + */ + return status; +} + +// @brief Erases all data in the NVM. +// +// If this function fails subsequent calls to NVM functions (other than NVM_init or NVM_erase) +// cause undefined behavior. +// Caution: this function may take a long time (like 1 second) +// +// @returns 0 on success or a non-zero error code otherwise +int NVM_erase(void) { + read_sector_ = 0; + sectors[0].index = sectors[0].n_reserved; + sectors[1].index = sectors[1].n_reserved; + + int state = 0; + state |= erase(§ors[0]); + state |= erase(§ors[1]); + return state; +} + +// @brief Returns the maximum number of bytes that can be read using NVM_read. +// This holds until NVM_commit is called. +size_t NVM_get_max_read_length(void) { + return n_valid_ << 3; +} + +// @brief Returns the maximum length (in bytes) that can passed to NVM_start_write. +// This holds until NVM_commit is called. +size_t NVM_get_max_write_length(void) { + sector_t *target = §ors[1 - read_sector_]; + return (target->n_data - target->n_reserved) << 3; +} + +// @brief Reads from the latest committed block in the non-volatile memory. +// @param offset: offset in bytes (0 meaning the beginning of the valid area) +// @param data: buffer to write to +// @param length: length in bytes (if (offset + length) is out of range, the function fails) +// @returns 0 on success or a non-zero error code otherwise +int NVM_read(size_t offset, uint8_t *data, size_t length) { + if (offset + length > (n_valid_ << 3)) + return -1; + sector_t *read_sector = §ors[read_sector_]; + const uint8_t *src_ptr = ((const uint8_t *)&read_sector->data[read_sector->index - n_valid_]) + offset; + memcpy(data, src_ptr, length); + return 0; +} + +// @brief Starts an atomic write operation. +// +// The most recent valid NVM data is not modified or invalidated until NVM_commit is called. +// The length must be at most equal to the size indicated by NVM_get_max_write_length(). +// +// @param length: Length of the staging block that should be created +int NVM_start_write(size_t length) { + int status = 0; + sector_t *target = §ors[1 - read_sector_]; + + length = (length + 7) >> 3; // round to multiple of 64 bit + if (length > target->n_data - target->n_reserved) + return -1; + + // make room for the new data + if (length > target->n_data - target->index) + if ((status = erase(target))) + return status; + + // invalidate the fields we're about to write + status = set_allocation_state(target, target->index, length, INVALID); + if (status) + return status; + + n_staging_area_ = length; + return 0; +} + +// @brief Writes to the current data block that was opened with NVM_start_write. +// +// The operation fails if (offset + length) is larger than the length passed to NVM_start_write. +// The most recent valid NVM data is not modified or invalidated until NVM_commit is called. +// Warning: Writing different data to the same area multiple times during a single transaction +// will cause data corruption. +// +// @param offset: The offset in bytes, 0 being the beginning of the staging block. +// @param data: Pointer to the data that should be written +// @param length: Data length in bytes +int NVM_write(size_t offset, uint8_t *data, size_t length) { + if (offset + length > (n_staging_area_ << 3)) + return -1; + sector_t *target = §ors[1 - read_sector_]; + + HAL_FLASH_Unlock(); + HAL_FLASH_ClearError(); + + // handle unaligned start + for (; (offset & 0x3) && length; ++data, ++offset, --length) + if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, + ((uintptr_t)&target->data[target->index]) + offset, *data) != HAL_OK) + goto fail; + + // write 32-bit values (64-bit doesn't work) + for (; length >= 4; data += 4, offset += 4, length -=4) + if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, + ((uintptr_t)&target->data[target->index]) + offset, *(uint32_t*)data) != HAL_OK) + goto fail; + + // handle unaligned end + for (; length; ++data, ++offset, --length) + if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, + ((uintptr_t)&target->data[target->index]) + offset, *data) != HAL_OK) + goto fail; + + HAL_FLASH_Lock(); + return 0; +fail: + HAL_FLASH_Lock(); + return HAL_FLASH_GetError(); // non-zero +} + +// @brief Commits the new data to NVM atomically. +int NVM_commit(void) { + sector_t *read_sector = §ors[read_sector_]; + sector_t *write_sector = §ors[1 - read_sector_]; + + // mark the newly-written fields as valid + int status = set_allocation_state(write_sector, write_sector->index, n_staging_area_, VALID); + if (status) + return status; + + write_sector->index += n_staging_area_; + n_valid_ = n_staging_area_; + n_staging_area_ = 0; + read_sector_ = 1 - read_sector_; + + // invalidate the other sector + if (read_sector->index < read_sector->n_data) + status = set_allocation_state(read_sector, read_sector->index, 1, INVALID); + else + status = erase(read_sector); + + return status; +} + + +#include +/** @brief Call this at startup to test/demo the NVM driver + + Expected output when starting with a fully erased NVM + + [1st boot] + === NVM TEST === + NVM is empty + write 0x00, ..., 0x25 to NVM + new data committed to NVM + + [2nd boot] + === NVM TEST === + NVM contains 40 valid bytes: + 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f + 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f + 20 21 22 23 24 25 ff ff + write 0xbd, ..., 0xe2 to NVM + new data committed to NVM + + [3rd boot] + === NVM TEST === + NVM contains 40 valid bytes: + bd be bf c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc + cd ce cf d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc + dd de df e0 e1 e2 ff ff + write 0xcb, ..., 0xf0 to NVM + new data committed to NVM +*/ +void NVM_demo(void) { + const size_t len = 38; + uint8_t data[len]; + int progress = 0; + uint8_t seed = 0; + + osDelay(100); + printf("=== NVM TEST ===\r\n"); osDelay(5); + //NVM_erase(); + if (progress++, NVM_init() != 0) + goto fail; + + // load bytes from NVM and print them + size_t available = NVM_get_max_read_length(); + if (available) { + printf("NVM contains %d valid bytes:\r\n", available); osDelay(5); + uint8_t buf[available]; + if (progress++, NVM_read(0, buf, available) != 0) + goto fail; + for (size_t pos = 0; pos < available; ++pos) { + seed += buf[pos]; + printf(" %02x", buf[pos]); + if ((((pos + 1) % 16) == 0) || ((pos + 1) == available)) + printf("\r\n"); + osDelay(2); + } + } else { + printf("NVM is empty\r\n"); osDelay(5); + } + + // store new bytes in NVM (data based on seed) + printf("write 0x%02x, ..., 0x%02x to NVM\r\n", seed, seed + len - 1); osDelay(5); + for (size_t i = 0; i < len; i++) + data[i] = seed++; + if (progress++, NVM_start_write(len) != 0) + goto fail; + if (progress++, NVM_write(0, data, len / 2)) + goto fail; + if (progress++, NVM_write(len / 2, &data[len / 2], len - (len / 2))) + goto fail; + if (progress++, NVM_commit()) + goto fail; + printf("new data committed to NVM\r\n"); osDelay(5); + + return; + +fail: + printf("NVM test failed at %d!\r\n", progress); +} diff --git a/Firmware/MotorControl/nvm.h b/Firmware/MotorControl/nvm.h new file mode 100644 index 00000000..efffa174 --- /dev/null +++ b/Firmware/MotorControl/nvm.h @@ -0,0 +1,33 @@ +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __NVML_H +#define __NVM_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include +#include + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Exported variables --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +int NVM_init(void); +int NVM_erase(void); +size_t NVM_get_max_read_length(void); +size_t NVM_get_max_write_length(void); +int NVM_read(size_t offset, uint8_t *data, size_t length); +int NVM_start_write(size_t length); +int NVM_write(size_t offset, uint8_t *data, size_t length); +int NVM_commit(void); +void NVM_demo(void); + +#ifdef __cplusplus +} +#endif + +#endif //__NVM_H \ No newline at end of file diff --git a/Firmware/MotorControl/protocol.hpp b/Firmware/MotorControl/protocol.hpp index cde1e2ab..8b2e1edd 100644 --- a/Firmware/MotorControl/protocol.hpp +++ b/Firmware/MotorControl/protocol.hpp @@ -33,10 +33,16 @@ inline size_t write_le(T value, uint8_t* buffer); template inline size_t read_le(T* value, const uint8_t* buffer); +template<> +inline size_t write_le(bool value, uint8_t* buffer) { + buffer[0] = value ? 1 : 0; + return 1; +} + template<> inline size_t write_le(uint8_t value, uint8_t* buffer) { buffer[0] = value; - return 2; + return 1; } template<> @@ -71,10 +77,16 @@ inline size_t write_le(float value, uint8_t* buffer) { return write_le(*reinterpret_cast(&value), buffer); } +template<> +inline size_t read_le(bool* value, const uint8_t* buffer) { + *value = buffer[0]; + return 1; +} + template<> inline size_t read_le(uint8_t* value, const uint8_t* buffer) { *value = buffer[0]; - return 2; + return 1; } template<> @@ -358,6 +370,14 @@ template<> inline const char* get_default_json_modifier() { return "\"type\":\"uint8\",\"access\":\"rw\""; } +template<> +inline const char* get_default_json_modifier() { + return "\"type\":\"bool\",\"access\":\"r\""; +} +template<> +inline const char* get_default_json_modifier() { + return "\"type\":\"bool\",\"access\":\"rw\""; +} class Endpoint { public: diff --git a/Firmware/MotorControl/utils.c b/Firmware/MotorControl/utils.c index b6fbd0d5..032a996a 100644 --- a/Firmware/MotorControl/utils.c +++ b/Firmware/MotorControl/utils.c @@ -2,6 +2,7 @@ #include #include #include +#include static const float one_by_sqrt3 = 0.57735026919f; static const float two_by_sqrt3 = 1.15470053838f; @@ -183,3 +184,23 @@ uint32_t timeout_to_deadline(uint32_t timeout_ms) { uint32_t now_ms = (uint32_t)((1000ull * (uint64_t)osKernelSysTick()) / osKernelSysTickFrequency); return now_ms + timeout_ms; } + +// @brief: Returns number of microseconds since system startup +uint32_t micros(void) { + uint32_t usTicks = HAL_RCC_GetSysClockFreq() / 1000000; + register uint32_t ms, cycle_cnt; + do { + ms = HAL_GetTick(); + cycle_cnt = SysTick->VAL; + } while (ms != HAL_GetTick()); + return (ms * 1000) + (usTicks * 1000 - cycle_cnt) / usTicks; +} + +// @brief: Busy wait delay for given amount of microseconds (us) +void delay_us(uint32_t us) +{ + uint32_t start = micros(); + while (micros() - start < (uint32_t) us) { + __ASM("nop"); + } +} \ No newline at end of file diff --git a/Firmware/MotorControl/utils.h b/Firmware/MotorControl/utils.h index 92436b74..bf329605 100644 --- a/Firmware/MotorControl/utils.h +++ b/Firmware/MotorControl/utils.h @@ -70,9 +70,10 @@ extern "C" { */ #define STM_ID_GetUUID(x) ((x >= 0 && x < 3) ? (*(uint32_t *)(ID_UNIQUE_ADDRESS + 4 * (x))) : 0) -#ifndef M_PI -#define M_PI 3.14159265358979323846f +#ifdef M_PI +#undef M_PI #endif +#define M_PI 3.14159265358979323846f #define MACRO_MAX(x, y) (((x) > (y)) ? (x) : (y)) #define MACRO_MIN(x, y) (((x) < (y)) ? (x) : (y)) @@ -91,6 +92,10 @@ int mod(int dividend, int divisor); uint32_t deadline_to_timeout(uint32_t deadline_ms); uint32_t timeout_to_deadline(uint32_t timeout_ms); +uint32_t micros(void); + +void delay_us(uint32_t us); + #ifdef __cplusplus } #endif diff --git a/Firmware/README.md b/Firmware/README.md index cc15177d..872e9b7e 100644 --- a/Firmware/README.md +++ b/Firmware/README.md @@ -10,11 +10,11 @@ The project is under active development, so make sure to check the [Changelog](C -- [Configuring parameters](#configuring-parameters) +- [Configuring the build](#configuring-the-build) - [Compiling and downloading firmware](#compiling-and-downloading-firmware) -- [Setting up an IDE](#setting-up-an-ide) -- [Continuing without an IDE](#no-ide-instructions) +- [Setting up an IDE](#setting-up-an-ide) or [Continuing without an IDE](#no-ide-instructions) - [Communicating over USB or UART](#communicating-over-usb-or-uart) +- [Configuring parameters](#configuring-parameters) - [Encoder Calibration](#encoder-calibration) - [Checking for error codes](#checking-for-error-codes) - [Generating startup code](#generating-startup-code) @@ -22,8 +22,10 @@ The project is under active development, so make sure to check the [Changelog](C -## Configuring parameters -To correctly operate the ODrive, you need to supply some parameters. Some are mandatory, and if supplied incorrectly will cause the drive to malfunction. To get good performance you must also tune the drive. +

+## Configuring the build +To correctly operate the ODrive, you need to supply some parameters. Some are mandatory, and if supplied incorrectly will cause the drive to malfunction. +In this section we will set the compile-time parameters, later we will also set the [run time parameters](#configuring-parameters). The first thing to set is your board hardware version, located at the top of [Inc/main.h](Inc/main.h). If, for example, you are using the hardware: ODrive v3.2, then you should set it like this: ```C @@ -61,54 +63,6 @@ Note that UART is only supported on ODrive v3.3 and higher. - `UART_PROTOCOL_NONE`: Ignore UART communication - `USE_GPIO_MODE_STEP_DIR`: Step/direction control mode (use in conjunction with `UART_PROTOCOL_NONE`) -### Motor control parameters -The rest of all the parameters are at the top of the [MotorControl/low_level.c](MotorControl/low_level.c) file. Please note that many parameters occur twice, once for each motor. -In it's current state, the motor structs contain both tuning parameters, meant to be set by the developer, and static variables, meant to be modified by the software. Unfortunatly these are mixed together right now, but cleaning this up is a high priority task. - -It may be helpful to know that the entry point of each of the motor threads is `void axis_thread_entry` at the top of [MotorControl/axis.cpp](MotorControl/axis.cpp). This is like `main` for each motor, and is probably where you should start reading the code. - -### Mandatory parameters -You must set: -* `ENCODER_CPR`: Encoder Count Per Revolution (CPR). This is 4x the Pulse Per Revolution (PPR) value. -* `POLE_PAIRS`: This is the number of magnet poles in the rotor, **divided by two**. You can simply count the number of permanent magnets in the rotor, if you can see them. Note: this is not the same as the number of coils in the stator. -* `brake_resistance`: This is the resistance of the brake resistor. If you are not using it, you may set it to 0.0f. -* `motor_type`: This is the type of motor being used. Currently two types of motors are supported -- High-current motors (`MOTOR_TYPE_HIGH_CURRENT`) and Gimbal motors (`MOTOR_TYPE_GIMBAL`). - -### Motor Modes -The firwmare currently supports two different types of motors, high-current motors, and Gimbal motors. If you're using a regular hobby brushless motor like [this](https://hobbyking.com/en_us/turnigy-aerodrive-sk3-5065-236kv-brushless-outrunner-motor.html) one, you should set `motor_mode` to `MOTOR_TYPE_HIGH_CURRENT`. For high-torque gimbal motors like [this](https://hobbyking.com/en_us/turnigy-hd-5208-brushless-gimbal-motor-bldc.html) one, you should choose `MOTOR_TYPE_GIMBAL`. - -**Further detail:** - -If 100's of mA of current noise is "small" for you, you can choose `MOTOR_TYPE_HIGH_CURRENT`. -If 100's of mA of current noise is "large" for you, and you do not intend to spin the motor very fast (omega * L << R), and the motor is fairly large resistance (1 ohm or larger), you can chose `MOTOR_TYPE_GIMBAL`. - -If 100's of mA current noise is "large" for you, and you intend to spin the motor fast, then you need to replace the shunt resistors on the ODrive. - -### Tuning parameters -The most important parameters are the limits: -* The current limit: `.current_lim = 75.0f, //[A] // Note: consistent with 40v/v gain`. The default current limit, for safety reasons, is set to 10A. This is quite weak, and good for making sure the drive is stable. Once you have tuned the drive, you can increase this to 75A to get some performance. Note that above 75A, you must change the current amplifier gains. - * Note: The motor current and the current drawn from the power supply is not the same in general. You should not look at the power supply current to see what is going on with the motor current. -* The velocity limit: `.vel_limit = 20000.0f, // [counts/s]`. The motor will be limited to this speed; again the default value is quite slow. -* You can change `.calibration_current` to the largest value you feel comfortable leaving running through the motor continously when the motor is stationary. - -The motion control gains are currently manually tuned: -* `.pos_gain = 20.0f, // [(counts/s) / counts]` -* `.vel_gain = 15.0f / 10000.0f, // [A/(counts/s)]` -* `.vel_integrator_gain = 10.0f / 10000.0f, // [A/(counts/s * s)]` - -An upcoming feature will enable automatic tuning. Until then, here is a rough tuning procedure: -* Set the integrator gain to 0 -* Make sure you have a stable system. If it is not, decrease all gains until you have one. -* Increase `vel_gain` by around 30% per iteration until the motor exhibits some vibration. -* Back down `vel_gain` to 50% of the vibrating value. -* Increase `pos_gain` by around 30% per iteration until you see some overshoot. -* Back down `pos_gain` until you do not have overshoot anymore. -* The integrator is not easily tuned, nor is it strictly required. Tune at your own discression. - -### Optional parameters -By default both motors are enabled, and the default control mode is position control. -If you want a different mode, you can change `.control_mode`. To disable a motor, set `.enable_control` and `.do_calibration` to false. -

## Compiling and downloading firmware ### Getting a programmer @@ -123,31 +77,38 @@ To compile the program, you first need to install the prerequisite tools: #### Linux: * `gcc-arm-none-eabi`: GCC compilation toolchain for ARM microcontrollers. * Installing on Ubuntu: `sudo apt-get install gcc-arm-none-eabi` + * Installing on Arch Linux: `sudo pacman -S arm-none-eabi-gcc arm-none-eabi-binutils` * `gdb-arm-none-eabi`: GNU project debugger for ARM microcontrollers. * Installing on Ubuntu: `sudo apt-get install gdb-arm-none-eabi` + * Installing on Arch Linux: `sudo pacman -S arm-none-eabi-gdb` * `OpenOCD`: Open On-Chip Debugging tools. This is what we use to flash the code onto the microcontroller. * Installing on Ubuntu: `sudo apt-get install openocd` + * Installing on Arch Linux: build and install the [AUR package](https://aur.archlinux.org/packages/openocd/) +* `tup`: Used as a build tool + * Installing on Ubuntu: `sudo add-apt-repository ppa:jonathonf/tup; sudo apt-get update; sudo apt-get install tup` + * Installing on Arch Linux: `sudo pacman -S tup` * No additional USB CDC driver should be required on Linux. #### Mac: * `brew cask install gcc-arm-embedded`: GCC toolchain+debugger +* `brew tap homebrew/fuse; brew install homebrew/fuse/tup`: Build tool * `brew install openocd`: Programmer #### Windows: Install the following: * [Git for windows](https://git-scm.com/download/win). This intalls the Git Bash, which is a unix style command line interface that we will be using. * [GNU ARM Embedded Toolchain](https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads). The cross-compiler used to compile the code. Download and install the "Windows 32-bit" version. Make sure to tick the "add to path" option. -* [Make for Windows](http://gnuwin32.sourceforge.net/packages/make.htm). Make is used to script the compilation process. Download and run the complete package setup program. Add the path of the binaries to your PATH environment variable. For me this was at `C:\Program Files (x86)\GnuWin32\bin`. For details on how to set your path envirment in windows see [these instructions.](https://www.java.com/en/download/help/path.xml) +* [Tup](http://gittup.org/tup/index.html) is used to script the compilation process. Unpack the zip-folder. Then add the path that contains the executable (something like `C:\Users\yourname\the\place\you\unzipped\tup-latest`) to your PATH environment variable. For details on how to set your path envirment in windows see [these instructions.](https://www.java.com/en/download/help/path.xml) +* [Make for Windows](http://gnuwin32.sourceforge.net/packages/make.htm). This is optional and mainly used because commands are short and developers are used to it. If you don't want to use it, you can look at the Makefile to get the corresponding commands. Download and run the complete package setup program. Add the path of the binaries to your PATH environment variable. For me this was at `C:\Program Files (x86)\GnuWin32\bin`. * OpenOCD. Follow the instructions at [GNU ARM Eclipse - How to install the OpenOCD binaries](http://gnuarmeclipse.github.io/openocd/install/), including the part about ST-LINK/V2 drivers. Add the path of the binaries to your PATH environment variable. For me this was at `C:\Program Files\GNU ARM Eclipse\OpenOCD\0.10.0-201704182147-dev\bin`.

## Setting up an IDE -ODrive is a Makefile project. It does not require an IDE, but the open-source IDE VSCode is recommended. It is also possible to use Eclipse. If you'd like to go that route, please see the respective configuration document: +For working with the ODrive code you don't need an IDE, but the open-source IDE VSCode is recommended. It is also possible to use Eclipse. If you'd like to go that route, please see the respective configuration document: * [Configuring VSCode](configuring-vscode.md) * [Configuring Eclipse](configuring-eclipse.md) -

## No IDE Instructions After installing all of the above, open a Git Bash shell. Continue at section [Building the firmware](#building-the-firmware). @@ -179,7 +140,7 @@ If the flashing worked, you can start sending commands. If you want to do that n ## Communicating over USB or UART Warning: If testing USB or UART communication for the first time it is recommend that your motors are free to spin continuously and are not connected to a drivetrain with limited travel. ### From Linux/Windows/macOS -There are two example python scripts to help you get started with controlling the ODrive using python. One will drop you into an interactive shell to query settings, parameters, and variables, and let you send setpoints manually ([tools/explore_odrive.py](tools/explore_odrive.py)). The other is a demo application to show you how to control the ODrive programmatically ([tools/demo.py](tools/demo.py)). Below follows a step-by-step guide on how to run these. +There are two example python scripts to help you get started with controlling the ODrive using python. One will drop you into an interactive shell to query settings, parameters, and variables, and let you send setpoints manually ([tools/explore_odrive.py](../tools/explore_odrive.py)). The other is a demo application to show you how to control the ODrive programmatically ([tools/demo.py](../tools/demo.py)). Below follows a step-by-step guide on how to run these. * __Windows__: It is recommended to use a Unix style command prompt, such as Git Bash that comes with [Git for windows](https://git-scm.com/download/win). @@ -215,12 +176,79 @@ pip install pyusb pyserial ### Other platforms See the [protocol specification](protocol.md) or the [legacy protocol specification](legacy-protocol.md). +

+## Configuring parameters +The majority of the important parameters you would want to set after flashing the ODrive with firmware are configurable over the USB communication interface. These include some mandatory parameters that you must set for correct operation, as well as tuning and optional parameters. +To start the configuration session: + +* Launch `./tools/explore_odrive.py`. This will give you a command prompt where you can modify using simple assignments. +* Configure parameters of the `my_odrive.[...].config` objects. + * For example to adjust the position gain: `my_odrive.motor0.config.pos_gain = 30` Enter. + * The complete list of configurable parameters is: + * `my_odrive.motorN.config.*` + * `my_odrive.axisN.config.*` + * where N is a valid motor number (0 or 1). +* Save the configuration into non-volatile memory: `my_odrive.save_configuration()` Enter + * This will save the properties of all the `[...].config` objects and no other parameters. +* Reboot the drive: `my_odrive.reboot()` Enter + +Note that a firmware upgrade at this point will preserve the configuration if and only if the parameters of both firmware versions are identical. Should you need to reset the configuration, you can run `my_odrive.erase_configuration()`. + +__Developers__: Be aware that you can also modify the compile-time defaults for all of these parameters. Most of them you will find at the top of [MotorControl/low_level.c](MotorControl/low_level.c#L50). Note that the configuration parameters there are somewhat intertwined with runtime variables and hardware specific configuration that should not be changed. Also note that all parameters occur twice. + +### Mandatory parameters +You must set for every motor: +* `my_odrive.motorN.encoder.config.cpr`: Encoder Count Per Revolution (CPR). This is 4x the Pulse Per Revolution (PPR) value. +* `my_odrive.motorN.config.pole_pairs`: This is the number of magnet poles in the rotor, **divided by two**. You can simply count the number of permanent magnets in the rotor, if you can see them. Note: this is not the same as the number of coils in the stator. +* `my_odrive.config.brake_resistance` [Ohm]: This is the resistance of the brake resistor. If you are not using it, you may set it to 0.0f. +* `my_odrive.motorN.config.motor_type`: This is the type of motor being used. Currently two types of motors are supported -- High-current motors (`MOTOR_TYPE_HIGH_CURRENT`) and Gimbal motors (`MOTOR_TYPE_GIMBAL`). + +#### Motor Modes +The firwmare currently supports two different types of motors, high-current motors, and Gimbal motors. If you're using a regular hobby brushless motor like [this](https://hobbyking.com/en_us/turnigy-aerodrive-sk3-5065-236kv-brushless-outrunner-motor.html) one, you should set `my_odrive.motorN.config.motor_type` to `MOTOR_TYPE_HIGH_CURRENT`. For high-torque gimbal motors like [this](https://hobbyking.com/en_us/turnigy-hd-5208-brushless-gimbal-motor-bldc.html) one, you should choose `MOTOR_TYPE_GIMBAL`. + +**Further detail:** +If 100's of mA of current noise is "small" for you, you can choose `MOTOR_TYPE_HIGH_CURRENT`. +If 100's of mA of current noise is "large" for you, and you do not intend to spin the motor very fast (omega * L << R), and the motor is fairly large resistance (1 ohm or larger), you can chose `MOTOR_TYPE_GIMBAL`. +If 100's of mA current noise is "large" for you, and you intend to spin the motor fast, then you need to replace the shunt resistors on the ODrive. + +### Tuning parameters +The most important parameters are the limits: +* The current limit: `my_odrive.motorN.current_control.config.current_lim` [A]. The default current limit, for safety reasons, is set to 10A. This is quite weak, and good for making sure the drive is stable. Once you have tuned the drive, you can increase this to 75A to get some performance. Note that above 75A, you must change the current amplifier gains. + * Note: The motor current and the current drawn from the power supply is not the same in general. You should not look at the power supply current to see what is going on with the motor current. +* The velocity limit: `my_odrive.motorN.config.vel_limit` [counts/s]. The motor will be limited to this speed; again the default value is quite slow. +* You can change `my_odrive.motorN.config.calibration_current` [A] to the largest value you feel comfortable leaving running through the motor continously when the motor is stationary. + +The motion control gains are currently manually tuned: +* `my_odrive.motorN.config.pos_gain = 20.0f` [(counts/s) / counts] +* `my_odrive.motorN.config.vel_gain = 15.0f / 10000.0f` [A/(counts/s)] +* `my_odrive.motorN.config.vel_integrator_gain = 10.0f / 10000.0f` [A/(counts/s * s)] + +An upcoming feature will enable automatic tuning. Until then, here is a rough tuning procedure: +* Set the integrator gain to 0 +* Make sure you have a stable system. If it is not, decrease all gains until you have one. +* Increase `vel_gain` by around 30% per iteration until the motor exhibits some vibration. +* Back down `vel_gain` to 50% of the vibrating value. +* Increase `pos_gain` by around 30% per iteration until you see some overshoot. +* Back down `pos_gain` until you do not have overshoot anymore. +* The integrator is not easily tuned, nor is it strictly required. Tune at your own discression. + +### Optional parameters +By default both motors are enabled, and the default control mode is position control. +If you want a different mode, you can change `my_odrive.motorN.config.control_mode`. +Possible values are: +* `CTRL_MODE_POSITION_CONTROL` +* `CTRL_MODE_VELOCITY_CONTROL` +* `CTRL_MODE_CURRENT_CONTROL` +* `CTRL_MODE_VOLTAGE_CONTROL` - this one is not normally used. + +To disable a motor at startup, set `my_odrive.axisN.config.enable_control` and `my_odrive.axisN.config.do_calibration` to `False`. +

## Encoder Calibration By default the encoder-to-motor calibration will run on every startup. During encoder calibration the rotor must be allowed to rotate without any biased load during startup. That means mass and weak friction loads are fine, but gravity or spring loads are not okay. ### Encoder with Index signal -If you have an encoder with an index (Z) signal, you may avoid having to do the calibration on every startup, and instead use the index signal to re-sync the encoder to a stored calibration. Bleow are the steps to do the one-time calibration and configuration. Note that you can follow these steps with one motor at a time, or all motors together, as you wish. +If you have an encoder with an index (Z) signal, you may avoid having to do the calibration on every startup, and instead use the index signal to re-sync the encoder to a stored calibration. Below are the steps to do the one-time calibration and configuration. Note that you can follow these steps with one motor at a time, or all motors together, as you wish. * Since you will only do this once, it is recommended that you mechanically disengage the motor from anything other than the encoder, so it can spin freely. * All the parameters we will be modifying are in the motor structs at the top of [MotorControl/low_level.c](MotorControl/low_level.c). @@ -265,6 +293,8 @@ The error nummber corresponds to the following: 19. `ERROR_SPIN_UP_TIMEOUT` 20. `ERROR_DRV_FAULT` 21. `ERROR_NOT_IMPLEMENTED_MOTOR_TYPE` +22. `ERROR_ENCODER_CPR_OUT_OF_RANGE` +23. `ERROR_DC_BUS_BROWNOUT` If you get an error code larger than this, it may be the case that someone added a code and forgot to update the documentation. In that case, please check [MotorControl/low_level.h](MotorControl/low_level.h) for the full enum. diff --git a/Firmware/Tupfile.lua b/Firmware/Tupfile.lua new file mode 100644 index 00000000..a4e8dd03 --- /dev/null +++ b/Firmware/Tupfile.lua @@ -0,0 +1,76 @@ + +tup.include('build.lua') + +boarddir = 'Board/v3.3' + + +-- C-specific flags +FLAGS += '-D__weak="__attribute__((weak))"' +FLAGS += '-D__packed="__attribute__((__packed__))"' +FLAGS += '-DUSE_HAL_DRIVER' +FLAGS += '-DSTM32F405xx' + +FLAGS += '-mthumb' +FLAGS += '-mcpu=cortex-m4' +FLAGS += '-mfpu=fpv4-sp-d16' +FLAGS += '-mfloat-abi=hard' +FLAGS += { '-Wall', '-fdata-sections', '-ffunction-sections'} + +FLAGS += '-g -gdwarf-2' + + +-- linker flags +LDFLAGS += '-T'..boarddir..'/STM32F405RGTx_FLASH.ld' +LDFLAGS += '-L'..boarddir..'/Drivers/CMSIS/Lib' -- lib dir +LDFLAGS += '-lc -lm -lnosys -larm_cortexM4lf_math' -- libs +LDFLAGS += '-mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -specs=nosys.specs -specs=nano.specs -u _printf_float -u _scanf_float -Wl,--cref -Wl,--gc-sections' + + +-- common flags for ASM, C and C++ +OPT += '-Og' +OPT += '-ffast-math' +tup.append_table(FLAGS, OPT) +tup.append_table(LDFLAGS, OPT) + +toolchain = GCCToolchain('arm-none-eabi-', 'build', FLAGS, LDFLAGS) + + +-- Load list of source files Makefile that was autogenerated by CubeMX +vars = parse_makefile_vars(boarddir..'/Makefile') +all_stm_sources = (vars['C_SOURCES'] or '')..' '..(vars['CPP_SOURCES'] or '')..' '..(vars['ASM_SOURCES'] or '') +for src in string.gmatch(all_stm_sources, "%S+") do + stm_sources += boarddir..'/'..src +end +for src in string.gmatch(vars['C_INCLUDES'] or '', "%S+") do + stm_includes += boarddir..'/'..string.sub(src, 3, -1) -- remove "-I" from each include path +end + +stm_includes += 'MotorControl' +build{ + name='stm_platform', + type='objects', + toolchains={toolchain}, + packages={}, + sources=stm_sources, + includes=stm_includes +} + +build{ + name='ODriveFirmware', + toolchains={toolchain}, + --toolchains={LLVMToolchain('x86_64', {'-Ofast'}, {'-flto'})}, + packages={'stm_platform'}, + sources={ + 'MotorControl/utils.c', + 'MotorControl/legacy_commands.c', + 'MotorControl/low_level.c', + 'MotorControl/nvm.c', + 'MotorControl/axis.cpp', + 'MotorControl/commands.cpp', + 'MotorControl/protocol.cpp', + 'MotorControl/config.cpp' + }, + includes={ + 'MotorControl' + } +} diff --git a/Firmware/build.lua b/Firmware/build.lua new file mode 100644 index 00000000..ba5ecc30 --- /dev/null +++ b/Firmware/build.lua @@ -0,0 +1,168 @@ + +-- This file contains support functions for Tupfile.lua + +function trim(s) + return (s:gsub("^%s*(.-)%s*$", "%1")) +end + +function string:split(sep) + local sep, fields = sep or ":", {} + local pattern = string.format("([^%s]+)", sep) + self:gsub(pattern, function(c) fields[#fields+1] = c end) + return fields +end + +-- Very basic parser to retrieve variables from a Makefile +function parse_makefile_vars(makefile) + vars = {} + current_var = nil + for line in io.lines(tup.getcwd()..'/'..makefile) do + if current_var == nil then + i,j = string.find(line, "+=") + if not i then + i,j = string.find(line, "=") + end + if i then + current_var = trim(string.sub(line, 1, i-1)) + vars[current_var] = vars[current_var] or '' + line = string.sub(line, j+1, -1) + --print("varname: "..varname.." the rest: "..line) + end + end + + if current_var != nil then + --print("append chunk "..trim(line).." to "..current_var) + vars[current_var] = vars[current_var]..' '..trim(line) + if string.sub(vars[current_var], -1) == '\\' then + vars[current_var] = string.sub(vars[current_var], 1, -2) + else + current_var = nil + end + end + end + return vars +end + + + + +function GCCToolchain(prefix, builddir, compiler_flags, linker_flags) + + -- add some default compiler flags + compiler_flags += '-fstack-usage' + + gcc_generic_compiler = function(compiler, compiler_flags, gen_su_file, src, flags, includes, outputs) + -- convert include list to flags + inc_flags = {} + for _,inc in pairs(includes) do + inc_flags += "-I"..inc + end + -- todo: vary build directory + obj_file = builddir.."/"..src:gsub("/","_")..".o" + outputs.object_files += obj_file + if gen_su_file then + su_file = builddir.."/"..src:gsub("/","_")..".su" + extra_outputs = { su_file } + outputs.su_files += su_file + else + extra_outputs = {} + end + tup.frule{ + inputs= { src }, + command=compiler..' -c %f '.. + tostring(compiler_flags)..' '.. -- CFLAGS for this compiler + tostring(inc_flags)..' '.. -- CFLAGS for this translation unit + tostring(flags).. -- CFLAGS for this translation unit + ' -o %o', + outputs={obj_file,extra_outputs=extra_outputs} + } + end + return { + compile_c = function(src, flags, includes, outputs) gcc_generic_compiler(prefix..'gcc -std=c99', compiler_flags, true, src, flags, includes, outputs) end, + compile_cpp = function(src, flags, includes, outputs) gcc_generic_compiler(prefix..'g++ -std=c++14', compiler_flags, true, src, flags, includes, outputs) end, + compile_asm = function(src, flags, includes, outputs) gcc_generic_compiler(prefix..'gcc -x assembler-with-cpp', compiler_flags, false, src, flags, includes, outputs) end, + link = function(objects, output_name) + output_name = builddir..'/'..output_name + tup.frule{ + inputs=objects, + command=prefix..'g++ %f '.. + tostring(linker_flags)..' '.. + '-Wl,-Map=%O.map'.. + ' -o %o', + outputs={output_name..'.elf', extra_outputs={output_name..'.map'}} + } + -- display the size + tup.frule{inputs={output_name..'.elf'}, command=prefix..'size %f'} + -- create *.hex and *.bin output formats + tup.frule{inputs={output_name..'.elf'}, command=prefix..'objcopy -O ihex %f %o', outputs={output_name..'.hex'}} + tup.frule{inputs={output_name..'.elf'}, command=prefix..'objcopy -O binary -S %f %o', outputs={output_name..'.bin'}} + end + } +end + +all_packages = {} + +-- toolchains: Each element of this list is a collection of functions, such as compile_c, link, ... +-- You can create a new toolchain object for each platform you want to build for. +function build(args) + if args.toolchain == nil then args.toolchain = {} end + if args.sources == nil then args.sources = {} end + if args.includes == nil then args.includes = {} end + if args.packages == nil then args.packages = {} end + if args.c_flags == nil then args.c_flags = {} end + if args.cpp_flags == nil then args.cpp_flags = {} end + if args.asm_flags == nil then args.asm_flags = {} end + if args.ld_flags == nil then args.ld_flags = {} end + if args.linker_objects == nil then args.linker_objects = {} end + + -- add includes of other packages + for _,pkg_name in pairs(args.packages) do + --print('depend on package '..pkg_name) + pkg = all_packages[pkg_name] + if pkg == nil then + error("unknown package "..pkg_name) + end + -- add path of each include + for _,inc in pairs(pkg.includes or {}) do + args.includes += tostring(inc) + end + tup.append_table(args.linker_objects, pkg.object_files) + end + + -- run everything once for every toolchain + for _,toolchain in pairs(args.toolchains) do + -- compile + outputs = {} + for _,src in pairs(args.sources) do + --print("compile "..src) + if tup.ext(src) == 'c' then + toolchain.compile_c(src, args.c_flags, args.includes, outputs) + elseif tup.ext(src) == 'cpp' then + toolchain.compile_cpp(src, args.cpp_flags, args.includes, outputs) + elseif tup.ext(src) == 's' or tup.ext(src) == 'asm' then + toolchain.compile_asm(src, args.asm_flags, args.includes, outputs) + else + error('unrecognized file ending') + end + end + + -- link + if outputs.object_files != nil and args.type != 'objects' then + tup.append_table(args.linker_objects, outputs.object_files) + toolchain.link(args.linker_objects, args.name) + end + + outputs.includes = {} + for _,inc in pairs(args.includes) do + table.insert(outputs.includes, tup.nodevariable(inc)) + end + if args.name != nil then + all_packages[args.name] = outputs + end + end + + --for k,v in pairs(all_packages) do + -- print('have package '..k) + --end +end + diff --git a/Firmware/configuring-vscode.md b/Firmware/configuring-vscode.md index ec9b0adb..add9ff45 100644 --- a/Firmware/configuring-vscode.md +++ b/Firmware/configuring-vscode.md @@ -19,7 +19,7 @@ Before doing the VSCode setup, make sure you've installed all of your [prerequis * Path Autocomplete * Auto Comment Blocks 1. Restart VSCode -1. Open the VSCode Workspace file, which is located in the root of the ODrive repository. It is called `VSCodeWorkspace.code-workspace`. The first time you open it, VSCode will install some dependencies. If it fails, you may need to [change your proxy settings](https://code.visualstudio.com/docs/getstarted/settings). +1. Open the VSCode Workspace file, which is located in the root of the ODrive repository. It is called `ODrive_Workspace.code-workspace`. The first time you open it, VSCode will install some dependencies. If it fails, you may need to [change your proxy settings](https://code.visualstudio.com/docs/getstarted/settings). You should now be ready to compile and test the ODrive project. diff --git a/Firmware/legacy-protocol.md b/Firmware/legacy-protocol.md index 5693a039..2898432f 100644 --- a/Firmware/legacy-protocol.md +++ b/Firmware/legacy-protocol.md @@ -52,7 +52,7 @@ s type index value ** `0` is float ** `1` is int ** `2` is bool -* `index` is the index in the corresponding [exposed variable table](MotorControl/commands.c). +* `index` is the index in the corresponding [exposed variable table](MotorControl/legacy_commands.c). For example * `g 0 12` will return the phase resistance of M0 diff --git a/VSCodeWorkspace.code-workspace b/ODrive_Workspace.code-workspace similarity index 100% rename from VSCodeWorkspace.code-workspace rename to ODrive_Workspace.code-workspace diff --git a/README.md b/README.md index 2c93fd63..192a3c6b 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,11 @@ This project is all about accurately driving brushless motors, for cheap. The aim is to make it possible to use inexpensive brushless motors in high performance robotics projects, like [this](https://www.youtube.com/watch?v=WT4E5nb3KtY). +| Branch | Build Status | +|--------|--------------| +| master | [![Build Status](https://travis-ci.org/madcowswe/ODrive.png?branch=master)](https://travis-ci.org/madcowswe/ODrive) | +| devel | [![Build Status](https://travis-ci.org/madcowswe/ODrive.png?branch=devel)](https://travis-ci.org/madcowswe/ODrive) | + ## Getting Started It is perfectly fine, and even recommended, to start testing with just a single motor and encoder. Make sure you have a good mechanical connection between the encoder and the motor, slip can cause disasterous oscillations. diff --git a/Tupfile.ini b/Tupfile.ini new file mode 100644 index 00000000..e69de29b diff --git a/tools/drv_status.py b/tools/drv_status.py new file mode 100644 index 00000000..fda6c292 --- /dev/null +++ b/tools/drv_status.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 +""" +Example usage of the ODrive python library to monitor and control ODrive devices +""" + +from __future__ import print_function + +import odrive.core +import time +import math + +# Find a connected ODrive (this will block until you connect one) +my_drive = odrive.core.find_any(consider_usb=True, consider_serial=False, printer=print) + +# Print DRV device regs for Motor 0 +fault = my_drive.motor0.gate_driver.drv_fault +status_reg_1 = my_drive.motor0.gate_driver.status_reg_1 +status_reg_2 = my_drive.motor0.gate_driver.status_reg_2 +ctrl_reg_1 = my_drive.motor0.gate_driver.ctrl_reg_1 +ctrl_reg_2 = my_drive.motor0.gate_driver.ctrl_reg_2 + +print("DRV Fault Code: " + str(fault)) +print("Status Reg 1: " + str(status_reg_1) + " (" + format(status_reg_1, '#010b') + ")") +print("Status Reg 2: " + str(status_reg_2) + " (" + format(status_reg_2, '#010b') + ")") +print("Control Reg 1: " + str(ctrl_reg_1) + " (" + format(ctrl_reg_1, '#010b') + ")") +print("Control Reg 2: " + str(ctrl_reg_2) + " (" + format(ctrl_reg_2, '#010b') + ")") + + diff --git a/tools/explore_odrive.py b/tools/explore_odrive.py index 7afb8009..59492a30 100755 --- a/tools/explore_odrive.py +++ b/tools/explore_odrive.py @@ -7,6 +7,17 @@ import odrive.core import argparse import sys +# some enums described in the README +# TODO: transmit as part of the JSON +MOTOR_TYPE_HIGH_CURRENT = 0 +#MOTOR_TYPE_LOW_CURRENT = 1 +MOTOR_TYPE_GIMBAL = 2 + +CTRL_MODE_VOLTAGE_CONTROL = 0, +CTRL_MODE_CURRENT_CONTROL = 1, +CTRL_MODE_VELOCITY_CONTROL = 2, +CTRL_MODE_POSITION_CONTROL = 3 + # Parse arguments parser = argparse.ArgumentParser(description='Load an odrive object to play with in the IPython interactive shell.') diff --git a/tools/usbpermission b/tools/usbpermission new file mode 100755 index 00000000..5ea6d8e9 --- /dev/null +++ b/tools/usbpermission @@ -0,0 +1 @@ +sudo udevadm control --reload-rules && sudo service udev restart && sudo udevadm trigger