diff --git a/Firmware/.vscode/c_cpp_properties.json b/Firmware/.vscode/c_cpp_properties.json index bd8d33ee0..2ebf2d390 100644 --- a/Firmware/.vscode/c_cpp_properties.json +++ b/Firmware/.vscode/c_cpp_properties.json @@ -15,7 +15,53 @@ "${workspaceRoot}/Drivers/CMSIS/Device/ST/STM32F4xx/Include", "${workspaceRoot}/Drivers/CMSIS/Include", "${workspaceRoot}/Inc", - "${workspaceRoot}/MotorControl" + "${workspaceRoot}/MotorControl", + "C:/Program Files (x86)/GNU Tools ARM Embedded/6 2017-q1-update/arm-none-eabi/include", + "C:/Program Files (x86)/GNU Tools ARM Embedded/6 2017-q1-update/lib/gcc/arm-none-eabi/6.3.1/include" + ], + "defines": [ + "_DEBUG", + "UNICODE" + ], + "intelliSenseMode": "msvc-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": "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", diff --git a/Firmware/CHANGELOG.md b/Firmware/CHANGELOG.md index 62e96abbe..3d928d832 100644 --- a/Firmware/CHANGELOG.md +++ b/Firmware/CHANGELOG.md @@ -1,5 +1,11 @@ -## [0.1] - UNRELEASED +## [0.2.0] - 2017-11-12 +### Added +* UART communication +* Setting to select UART or Step/dir on GIPIO 1,2 +* Basic Anti-cogging + +## [0.1.0] - 2017-08-26 ### Added * Step/Dir interface * this Changelog diff --git a/Firmware/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c b/Firmware/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c deleted file mode 100644 index 4064c2e1b..000000000 --- a/Firmware/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c +++ /dev/null @@ -1,763 +0,0 @@ -/** - ****************************************************************************** - * @file system_stm32f4xx.c - * @author MCD Application Team - * @version V2.6.1 - * @date 14-February-2017 - * @brief CMSIS Cortex-M4 Device Peripheral Access Layer System Source File. - * - * This file provides two functions and one global variable to be called from - * user application: - * - SystemInit(): This function is called at startup just after reset and - * before branch to main program. This call is made inside - * the "startup_stm32f4xx.s" file. - * - * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used - * by the user application to setup the SysTick - * timer or configure other parameters. - * - * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must - * be called whenever the core clock is changed - * during program execution. - * - * - ****************************************************************************** - * @attention - * - *

© COPYRIGHT 2017 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - -/** @addtogroup CMSIS - * @{ - */ - -/** @addtogroup stm32f4xx_system - * @{ - */ - -/** @addtogroup STM32F4xx_System_Private_Includes - * @{ - */ - - -#include "stm32f4xx.h" - -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)25000000) /*!< Default value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @} - */ - -/** @addtogroup STM32F4xx_System_Private_TypesDefinitions - * @{ - */ - -/** - * @} - */ - -/** @addtogroup STM32F4xx_System_Private_Defines - * @{ - */ - -/************************* Miscellaneous Configuration ************************/ -/*!< Uncomment the following line if you need to use external SRAM or SDRAM as data memory */ -#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)\ - || defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ - || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) -/* #define DATA_IN_ExtSRAM */ -#endif /* STM32F40xxx || STM32F41xxx || STM32F42xxx || STM32F43xxx || STM32F469xx || STM32F479xx ||\ - STM32F412Zx || STM32F412Vx */ - -#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ - || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) -/* #define DATA_IN_ExtSDRAM */ -#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx ||\ - STM32F479xx */ - -/*!< Uncomment the following line if you need to relocate your vector Table in - Internal SRAM. */ -/* #define VECT_TAB_SRAM */ -#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field. - This value must be a multiple of 0x200. */ -/******************************************************************************/ - -/** - * @} - */ - -/** @addtogroup STM32F4xx_System_Private_Macros - * @{ - */ - -/** - * @} - */ - -/** @addtogroup STM32F4xx_System_Private_Variables - * @{ - */ - /* This variable is updated in three ways: - 1) by calling CMSIS function SystemCoreClockUpdate() - 2) by calling HAL API function HAL_RCC_GetHCLKFreq() - 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency - Note: If you use this function to configure the system clock; then there - is no need to call the 2 first functions listed above, since SystemCoreClock - variable is updated automatically. - */ -uint32_t SystemCoreClock = 16000000; -const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; -const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4}; -/** - * @} - */ - -/** @addtogroup STM32F4xx_System_Private_FunctionPrototypes - * @{ - */ - -#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM) - static void SystemInit_ExtMemCtl(void); -#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */ - -/** - * @} - */ - -/** @addtogroup STM32F4xx_System_Private_Functions - * @{ - */ - -/** - * @brief Setup the microcontroller system - * Initialize the FPU setting, vector table location and External memory - * configuration. - * @param None - * @retval None - */ -void SystemInit(void) -{ - /* FPU settings ------------------------------------------------------------*/ - #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) - SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ - #endif - /* Reset the RCC clock configuration to the default reset state ------------*/ - /* Set HSION bit */ - RCC->CR |= (uint32_t)0x00000001; - - /* Reset CFGR register */ - RCC->CFGR = 0x00000000; - - /* Reset HSEON, CSSON and PLLON bits */ - RCC->CR &= (uint32_t)0xFEF6FFFF; - - /* Reset PLLCFGR register */ - RCC->PLLCFGR = 0x24003010; - - /* Reset HSEBYP bit */ - RCC->CR &= (uint32_t)0xFFFBFFFF; - - /* Disable all interrupts */ - RCC->CIR = 0x00000000; - -#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM) - SystemInit_ExtMemCtl(); -#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */ - - /* Configure the Vector Table location add offset address ------------------*/ -#ifdef VECT_TAB_SRAM - SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */ -#else - SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */ -#endif -} - -/** - * @brief Update SystemCoreClock variable according to Clock Register Values. - * The SystemCoreClock variable contains the core clock (HCLK), it can - * be used by the user application to setup the SysTick timer or configure - * other parameters. - * - * @note Each time the core clock (HCLK) changes, this function must be called - * to update SystemCoreClock variable value. Otherwise, any configuration - * based on this variable will be incorrect. - * - * @note - The system frequency computed by this function is not the real - * frequency in the chip. It is calculated based on the predefined - * constant and the selected clock source: - * - * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*) - * - * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**) - * - * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) - * or HSI_VALUE(*) multiplied/divided by the PLL factors. - * - * (*) HSI_VALUE is a constant defined in stm32f4xx_hal_conf.h file (default value - * 16 MHz) but the real value may vary depending on the variations - * in voltage and temperature. - * - * (**) HSE_VALUE is a constant defined in stm32f4xx_hal_conf.h file (its value - * depends on the application requirements), user has to ensure that HSE_VALUE - * is same as the real frequency of the crystal used. Otherwise, this function - * may have wrong result. - * - * - The result of this function could be not correct when using fractional - * value for HSE crystal. - * - * @param None - * @retval None - */ -void SystemCoreClockUpdate(void) -{ - uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2; - - /* Get SYSCLK source -------------------------------------------------------*/ - tmp = RCC->CFGR & RCC_CFGR_SWS; - - switch (tmp) - { - case 0x00: /* HSI used as system clock source */ - SystemCoreClock = HSI_VALUE; - break; - case 0x04: /* HSE used as system clock source */ - SystemCoreClock = HSE_VALUE; - break; - case 0x08: /* PLL used as system clock source */ - - /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N - SYSCLK = PLL_VCO / PLL_P - */ - pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22; - pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM; - - if (pllsource != 0) - { - /* HSE used as PLL clock source */ - pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); - } - else - { - /* HSI used as PLL clock source */ - pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); - } - - pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2; - SystemCoreClock = pllvco/pllp; - break; - default: - SystemCoreClock = HSI_VALUE; - break; - } - /* Compute HCLK frequency --------------------------------------------------*/ - /* Get HCLK prescaler */ - tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)]; - /* HCLK frequency */ - SystemCoreClock >>= tmp; -} - -#if defined (DATA_IN_ExtSRAM) && defined (DATA_IN_ExtSDRAM) -#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ - || defined(STM32F469xx) || defined(STM32F479xx) -/** - * @brief Setup the external memory controller. - * Called in startup_stm32f4xx.s before jump to main. - * This function configures the external memories (SRAM/SDRAM) - * This SRAM/SDRAM will be used as program data memory (including heap and stack). - * @param None - * @retval None - */ -void SystemInit_ExtMemCtl(void) -{ - __IO uint32_t tmp = 0x00; - - register uint32_t tmpreg = 0, timeout = 0xFFFF; - register __IO uint32_t index; - - /* Enable GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface clock */ - RCC->AHB1ENR |= 0x000001F8; - - /* Delay after an RCC peripheral clock enabling */ - tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN); - - /* Connect PDx pins to FMC Alternate function */ - GPIOD->AFR[0] = 0x00CCC0CC; - GPIOD->AFR[1] = 0xCCCCCCCC; - /* Configure PDx pins in Alternate function mode */ - GPIOD->MODER = 0xAAAA0A8A; - /* Configure PDx pins speed to 100 MHz */ - GPIOD->OSPEEDR = 0xFFFF0FCF; - /* Configure PDx pins Output type to push-pull */ - GPIOD->OTYPER = 0x00000000; - /* No pull-up, pull-down for PDx pins */ - GPIOD->PUPDR = 0x00000000; - - /* Connect PEx pins to FMC Alternate function */ - GPIOE->AFR[0] = 0xC00CC0CC; - GPIOE->AFR[1] = 0xCCCCCCCC; - /* Configure PEx pins in Alternate function mode */ - GPIOE->MODER = 0xAAAA828A; - /* Configure PEx pins speed to 100 MHz */ - GPIOE->OSPEEDR = 0xFFFFC3CF; - /* Configure PEx pins Output type to push-pull */ - GPIOE->OTYPER = 0x00000000; - /* No pull-up, pull-down for PEx pins */ - GPIOE->PUPDR = 0x00000000; - - /* Connect PFx pins to FMC Alternate function */ - GPIOF->AFR[0] = 0xCCCCCCCC; - GPIOF->AFR[1] = 0xCCCCCCCC; - /* Configure PFx pins in Alternate function mode */ - GPIOF->MODER = 0xAA800AAA; - /* Configure PFx pins speed to 50 MHz */ - GPIOF->OSPEEDR = 0xAA800AAA; - /* Configure PFx pins Output type to push-pull */ - GPIOF->OTYPER = 0x00000000; - /* No pull-up, pull-down for PFx pins */ - GPIOF->PUPDR = 0x00000000; - - /* Connect PGx pins to FMC Alternate function */ - GPIOG->AFR[0] = 0xCCCCCCCC; - GPIOG->AFR[1] = 0xCCCCCCCC; - /* Configure PGx pins in Alternate function mode */ - GPIOG->MODER = 0xAAAAAAAA; - /* Configure PGx pins speed to 50 MHz */ - GPIOG->OSPEEDR = 0xAAAAAAAA; - /* Configure PGx pins Output type to push-pull */ - GPIOG->OTYPER = 0x00000000; - /* No pull-up, pull-down for PGx pins */ - GPIOG->PUPDR = 0x00000000; - - /* Connect PHx pins to FMC Alternate function */ - GPIOH->AFR[0] = 0x00C0CC00; - GPIOH->AFR[1] = 0xCCCCCCCC; - /* Configure PHx pins in Alternate function mode */ - GPIOH->MODER = 0xAAAA08A0; - /* Configure PHx pins speed to 50 MHz */ - GPIOH->OSPEEDR = 0xAAAA08A0; - /* Configure PHx pins Output type to push-pull */ - GPIOH->OTYPER = 0x00000000; - /* No pull-up, pull-down for PHx pins */ - GPIOH->PUPDR = 0x00000000; - - /* Connect PIx pins to FMC Alternate function */ - GPIOI->AFR[0] = 0xCCCCCCCC; - GPIOI->AFR[1] = 0x00000CC0; - /* Configure PIx pins in Alternate function mode */ - GPIOI->MODER = 0x0028AAAA; - /* Configure PIx pins speed to 50 MHz */ - GPIOI->OSPEEDR = 0x0028AAAA; - /* Configure PIx pins Output type to push-pull */ - GPIOI->OTYPER = 0x00000000; - /* No pull-up, pull-down for PIx pins */ - GPIOI->PUPDR = 0x00000000; - -/*-- FMC Configuration -------------------------------------------------------*/ - /* Enable the FMC interface clock */ - RCC->AHB3ENR |= 0x00000001; - /* Delay after an RCC peripheral clock enabling */ - tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN); - - FMC_Bank5_6->SDCR[0] = 0x000019E4; - FMC_Bank5_6->SDTR[0] = 0x01115351; - - /* SDRAM initialization sequence */ - /* Clock enable command */ - FMC_Bank5_6->SDCMR = 0x00000011; - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; - while((tmpreg != 0) && (timeout-- > 0)) - { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; - } - - /* Delay */ - for (index = 0; index<1000; index++); - - /* PALL command */ - FMC_Bank5_6->SDCMR = 0x00000012; - timeout = 0xFFFF; - while((tmpreg != 0) && (timeout-- > 0)) - { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; - } - - /* Auto refresh command */ - FMC_Bank5_6->SDCMR = 0x00000073; - timeout = 0xFFFF; - while((tmpreg != 0) && (timeout-- > 0)) - { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; - } - - /* MRD register program */ - FMC_Bank5_6->SDCMR = 0x00046014; - timeout = 0xFFFF; - while((tmpreg != 0) && (timeout-- > 0)) - { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; - } - - /* Set refresh count */ - tmpreg = FMC_Bank5_6->SDRTR; - FMC_Bank5_6->SDRTR = (tmpreg | (0x0000027C<<1)); - - /* Disable write protection */ - tmpreg = FMC_Bank5_6->SDCR[0]; - FMC_Bank5_6->SDCR[0] = (tmpreg & 0xFFFFFDFF); - -#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) - /* Configure and enable Bank1_SRAM2 */ - FMC_Bank1->BTCR[2] = 0x00001011; - FMC_Bank1->BTCR[3] = 0x00000201; - FMC_Bank1E->BWTR[2] = 0x0fffffff; -#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */ -#if defined(STM32F469xx) || defined(STM32F479xx) - /* Configure and enable Bank1_SRAM2 */ - FMC_Bank1->BTCR[2] = 0x00001091; - FMC_Bank1->BTCR[3] = 0x00110212; - FMC_Bank1E->BWTR[2] = 0x0fffffff; -#endif /* STM32F469xx || STM32F479xx */ - - (void)(tmp); -} -#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */ -#elif defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM) -/** - * @brief Setup the external memory controller. - * Called in startup_stm32f4xx.s before jump to main. - * This function configures the external memories (SRAM/SDRAM) - * This SRAM/SDRAM will be used as program data memory (including heap and stack). - * @param None - * @retval None - */ -void SystemInit_ExtMemCtl(void) -{ - __IO uint32_t tmp = 0x00; -#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ - || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) -#if defined (DATA_IN_ExtSDRAM) - register uint32_t tmpreg = 0, timeout = 0xFFFF; - register __IO uint32_t index; - -#if defined(STM32F446xx) - /* Enable GPIOA, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG interface - clock */ - RCC->AHB1ENR |= 0x0000007D; -#else - /* Enable GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface - clock */ - RCC->AHB1ENR |= 0x000001F8; -#endif /* STM32F446xx */ - /* Delay after an RCC peripheral clock enabling */ - tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN); - -#if defined(STM32F446xx) - /* Connect PAx pins to FMC Alternate function */ - GPIOA->AFR[0] |= 0xC0000000; - GPIOA->AFR[1] |= 0x00000000; - /* Configure PDx pins in Alternate function mode */ - GPIOA->MODER |= 0x00008000; - /* Configure PDx pins speed to 50 MHz */ - GPIOA->OSPEEDR |= 0x00008000; - /* Configure PDx pins Output type to push-pull */ - GPIOA->OTYPER |= 0x00000000; - /* No pull-up, pull-down for PDx pins */ - GPIOA->PUPDR |= 0x00000000; - - /* Connect PCx pins to FMC Alternate function */ - GPIOC->AFR[0] |= 0x00CC0000; - GPIOC->AFR[1] |= 0x00000000; - /* Configure PDx pins in Alternate function mode */ - GPIOC->MODER |= 0x00000A00; - /* Configure PDx pins speed to 50 MHz */ - GPIOC->OSPEEDR |= 0x00000A00; - /* Configure PDx pins Output type to push-pull */ - GPIOC->OTYPER |= 0x00000000; - /* No pull-up, pull-down for PDx pins */ - GPIOC->PUPDR |= 0x00000000; -#endif /* STM32F446xx */ - - /* Connect PDx pins to FMC Alternate function */ - GPIOD->AFR[0] = 0x000000CC; - GPIOD->AFR[1] = 0xCC000CCC; - /* Configure PDx pins in Alternate function mode */ - GPIOD->MODER = 0xA02A000A; - /* Configure PDx pins speed to 50 MHz */ - GPIOD->OSPEEDR = 0xA02A000A; - /* Configure PDx pins Output type to push-pull */ - GPIOD->OTYPER = 0x00000000; - /* No pull-up, pull-down for PDx pins */ - GPIOD->PUPDR = 0x00000000; - - /* Connect PEx pins to FMC Alternate function */ - GPIOE->AFR[0] = 0xC00000CC; - GPIOE->AFR[1] = 0xCCCCCCCC; - /* Configure PEx pins in Alternate function mode */ - GPIOE->MODER = 0xAAAA800A; - /* Configure PEx pins speed to 50 MHz */ - GPIOE->OSPEEDR = 0xAAAA800A; - /* Configure PEx pins Output type to push-pull */ - GPIOE->OTYPER = 0x00000000; - /* No pull-up, pull-down for PEx pins */ - GPIOE->PUPDR = 0x00000000; - - /* Connect PFx pins to FMC Alternate function */ - GPIOF->AFR[0] = 0xCCCCCCCC; - GPIOF->AFR[1] = 0xCCCCCCCC; - /* Configure PFx pins in Alternate function mode */ - GPIOF->MODER = 0xAA800AAA; - /* Configure PFx pins speed to 50 MHz */ - GPIOF->OSPEEDR = 0xAA800AAA; - /* Configure PFx pins Output type to push-pull */ - GPIOF->OTYPER = 0x00000000; - /* No pull-up, pull-down for PFx pins */ - GPIOF->PUPDR = 0x00000000; - - /* Connect PGx pins to FMC Alternate function */ - GPIOG->AFR[0] = 0xCCCCCCCC; - GPIOG->AFR[1] = 0xCCCCCCCC; - /* Configure PGx pins in Alternate function mode */ - GPIOG->MODER = 0xAAAAAAAA; - /* Configure PGx pins speed to 50 MHz */ - GPIOG->OSPEEDR = 0xAAAAAAAA; - /* Configure PGx pins Output type to push-pull */ - GPIOG->OTYPER = 0x00000000; - /* No pull-up, pull-down for PGx pins */ - GPIOG->PUPDR = 0x00000000; - -#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ - || defined(STM32F469xx) || defined(STM32F479xx) - /* Connect PHx pins to FMC Alternate function */ - GPIOH->AFR[0] = 0x00C0CC00; - GPIOH->AFR[1] = 0xCCCCCCCC; - /* Configure PHx pins in Alternate function mode */ - GPIOH->MODER = 0xAAAA08A0; - /* Configure PHx pins speed to 50 MHz */ - GPIOH->OSPEEDR = 0xAAAA08A0; - /* Configure PHx pins Output type to push-pull */ - GPIOH->OTYPER = 0x00000000; - /* No pull-up, pull-down for PHx pins */ - GPIOH->PUPDR = 0x00000000; - - /* Connect PIx pins to FMC Alternate function */ - GPIOI->AFR[0] = 0xCCCCCCCC; - GPIOI->AFR[1] = 0x00000CC0; - /* Configure PIx pins in Alternate function mode */ - GPIOI->MODER = 0x0028AAAA; - /* Configure PIx pins speed to 50 MHz */ - GPIOI->OSPEEDR = 0x0028AAAA; - /* Configure PIx pins Output type to push-pull */ - GPIOI->OTYPER = 0x00000000; - /* No pull-up, pull-down for PIx pins */ - GPIOI->PUPDR = 0x00000000; -#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */ - -/*-- FMC Configuration -------------------------------------------------------*/ - /* Enable the FMC interface clock */ - RCC->AHB3ENR |= 0x00000001; - /* Delay after an RCC peripheral clock enabling */ - tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN); - - /* Configure and enable SDRAM bank1 */ -#if defined(STM32F446xx) - FMC_Bank5_6->SDCR[0] = 0x00001954; -#else - FMC_Bank5_6->SDCR[0] = 0x000019E4; -#endif /* STM32F446xx */ - FMC_Bank5_6->SDTR[0] = 0x01115351; - - /* SDRAM initialization sequence */ - /* Clock enable command */ - FMC_Bank5_6->SDCMR = 0x00000011; - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; - while((tmpreg != 0) && (timeout-- > 0)) - { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; - } - - /* Delay */ - for (index = 0; index<1000; index++); - - /* PALL command */ - FMC_Bank5_6->SDCMR = 0x00000012; - timeout = 0xFFFF; - while((tmpreg != 0) && (timeout-- > 0)) - { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; - } - - /* Auto refresh command */ -#if defined(STM32F446xx) - FMC_Bank5_6->SDCMR = 0x000000F3; -#else - FMC_Bank5_6->SDCMR = 0x00000073; -#endif /* STM32F446xx */ - timeout = 0xFFFF; - while((tmpreg != 0) && (timeout-- > 0)) - { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; - } - - /* MRD register program */ -#if defined(STM32F446xx) - FMC_Bank5_6->SDCMR = 0x00044014; -#else - FMC_Bank5_6->SDCMR = 0x00046014; -#endif /* STM32F446xx */ - timeout = 0xFFFF; - while((tmpreg != 0) && (timeout-- > 0)) - { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; - } - - /* Set refresh count */ - tmpreg = FMC_Bank5_6->SDRTR; -#if defined(STM32F446xx) - FMC_Bank5_6->SDRTR = (tmpreg | (0x0000050C<<1)); -#else - FMC_Bank5_6->SDRTR = (tmpreg | (0x0000027C<<1)); -#endif /* STM32F446xx */ - - /* Disable write protection */ - tmpreg = FMC_Bank5_6->SDCR[0]; - FMC_Bank5_6->SDCR[0] = (tmpreg & 0xFFFFFDFF); -#endif /* DATA_IN_ExtSDRAM */ -#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx */ - -#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)\ - || defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ - || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) - -#if defined(DATA_IN_ExtSRAM) -/*-- GPIOs Configuration -----------------------------------------------------*/ - /* Enable GPIOD, GPIOE, GPIOF and GPIOG interface clock */ - RCC->AHB1ENR |= 0x00000078; - /* Delay after an RCC peripheral clock enabling */ - tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIODEN); - - /* Connect PDx pins to FMC Alternate function */ - GPIOD->AFR[0] = 0x00CCC0CC; - GPIOD->AFR[1] = 0xCCCCCCCC; - /* Configure PDx pins in Alternate function mode */ - GPIOD->MODER = 0xAAAA0A8A; - /* Configure PDx pins speed to 100 MHz */ - GPIOD->OSPEEDR = 0xFFFF0FCF; - /* Configure PDx pins Output type to push-pull */ - GPIOD->OTYPER = 0x00000000; - /* No pull-up, pull-down for PDx pins */ - GPIOD->PUPDR = 0x00000000; - - /* Connect PEx pins to FMC Alternate function */ - GPIOE->AFR[0] = 0xC00CC0CC; - GPIOE->AFR[1] = 0xCCCCCCCC; - /* Configure PEx pins in Alternate function mode */ - GPIOE->MODER = 0xAAAA828A; - /* Configure PEx pins speed to 100 MHz */ - GPIOE->OSPEEDR = 0xFFFFC3CF; - /* Configure PEx pins Output type to push-pull */ - GPIOE->OTYPER = 0x00000000; - /* No pull-up, pull-down for PEx pins */ - GPIOE->PUPDR = 0x00000000; - - /* Connect PFx pins to FMC Alternate function */ - GPIOF->AFR[0] = 0x00CCCCCC; - GPIOF->AFR[1] = 0xCCCC0000; - /* Configure PFx pins in Alternate function mode */ - GPIOF->MODER = 0xAA000AAA; - /* Configure PFx pins speed to 100 MHz */ - GPIOF->OSPEEDR = 0xFF000FFF; - /* Configure PFx pins Output type to push-pull */ - GPIOF->OTYPER = 0x00000000; - /* No pull-up, pull-down for PFx pins */ - GPIOF->PUPDR = 0x00000000; - - /* Connect PGx pins to FMC Alternate function */ - GPIOG->AFR[0] = 0x00CCCCCC; - GPIOG->AFR[1] = 0x000000C0; - /* Configure PGx pins in Alternate function mode */ - GPIOG->MODER = 0x00085AAA; - /* Configure PGx pins speed to 100 MHz */ - GPIOG->OSPEEDR = 0x000CAFFF; - /* Configure PGx pins Output type to push-pull */ - GPIOG->OTYPER = 0x00000000; - /* No pull-up, pull-down for PGx pins */ - GPIOG->PUPDR = 0x00000000; - -/*-- FMC/FSMC Configuration --------------------------------------------------*/ - /* Enable the FMC/FSMC interface clock */ - RCC->AHB3ENR |= 0x00000001; - -#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) - /* Delay after an RCC peripheral clock enabling */ - tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN); - /* Configure and enable Bank1_SRAM2 */ - FMC_Bank1->BTCR[2] = 0x00001011; - FMC_Bank1->BTCR[3] = 0x00000201; - FMC_Bank1E->BWTR[2] = 0x0fffffff; -#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */ -#if defined(STM32F469xx) || defined(STM32F479xx) - /* Delay after an RCC peripheral clock enabling */ - tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN); - /* Configure and enable Bank1_SRAM2 */ - FMC_Bank1->BTCR[2] = 0x00001091; - FMC_Bank1->BTCR[3] = 0x00110212; - FMC_Bank1E->BWTR[2] = 0x0fffffff; -#endif /* STM32F469xx || STM32F479xx */ -#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx)|| defined(STM32F417xx)\ - || defined(STM32F412Zx) || defined(STM32F412Vx) - /* Delay after an RCC peripheral clock enabling */ - tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FSMCEN); - /* Configure and enable Bank1_SRAM2 */ - FSMC_Bank1->BTCR[2] = 0x00001011; - FSMC_Bank1->BTCR[3] = 0x00000201; - FSMC_Bank1E->BWTR[2] = 0x0FFFFFFF; -#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F412Zx || STM32F412Vx */ - -#endif /* DATA_IN_ExtSRAM */ -#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F427xx || STM32F437xx ||\ - STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx || STM32F412Zx || STM32F412Vx */ - (void)(tmp); -} -#endif /* DATA_IN_ExtSRAM && DATA_IN_ExtSDRAM */ -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h b/Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h new file mode 100644 index 000000000..ba2ed4f83 --- /dev/null +++ b/Firmware/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h @@ -0,0 +1,794 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_uart.h + * @author MCD Application Team + * @version V1.7.1 + * @date 14-April-2017 + * @brief Header file of UART HAL module. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F4xx_HAL_UART_H +#define __STM32F4xx_HAL_UART_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup UART + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup UART_Exported_Types UART Exported Types + * @{ + */ + +/** + * @brief UART Init Structure definition + */ +typedef struct +{ + uint32_t BaudRate; /*!< This member configures the UART communication baud rate. + The baud rate is computed using the following formula: + - IntegerDivider = ((PCLKx) / (8 * (OVR8+1) * (huart->Init.BaudRate))) + - FractionalDivider = ((IntegerDivider - ((uint32_t) IntegerDivider)) * 8 * (OVR8+1)) + 0.5 + Where OVR8 is the "oversampling by 8 mode" configuration bit in the CR1 register. */ + + uint32_t WordLength; /*!< Specifies the number of data bits transmitted or received in a frame. + This parameter can be a value of @ref UART_Word_Length */ + + uint32_t StopBits; /*!< Specifies the number of stop bits transmitted. + This parameter can be a value of @ref UART_Stop_Bits */ + + uint32_t Parity; /*!< Specifies the parity mode. + This parameter can be a value of @ref UART_Parity + @note When parity is enabled, the computed parity is inserted + at the MSB position of the transmitted data (9th bit when + the word length is set to 9 data bits; 8th bit when the + word length is set to 8 data bits). */ + + uint32_t Mode; /*!< Specifies whether the Receive or Transmit mode is enabled or disabled. + This parameter can be a value of @ref UART_Mode */ + + uint32_t HwFlowCtl; /*!< Specifies whether the hardware flow control mode is enabled + or disabled. + This parameter can be a value of @ref UART_Hardware_Flow_Control */ + + uint32_t OverSampling; /*!< Specifies whether the Over sampling 8 is enabled or disabled, to achieve higher speed (up to fPCLK/8). + This parameter can be a value of @ref UART_Over_Sampling */ +}UART_InitTypeDef; + +/** + * @brief HAL UART State structures definition + * @note HAL UART State value is a combination of 2 different substates: gState and RxState. + * - gState contains UART state information related to global Handle management + * and also information related to Tx operations. + * gState value coding follow below described bitmap : + * b7-b6 Error information + * 00 : No Error + * 01 : (Not Used) + * 10 : Timeout + * 11 : Error + * b5 IP initilisation status + * 0 : Reset (IP not initialized) + * 1 : Init done (IP not initialized. HAL UART Init function already called) + * b4-b3 (not used) + * xx : Should be set to 00 + * b2 Intrinsic process state + * 0 : Ready + * 1 : Busy (IP busy with some configuration or internal operations) + * b1 (not used) + * x : Should be set to 0 + * b0 Tx state + * 0 : Ready (no Tx operation ongoing) + * 1 : Busy (Tx operation ongoing) + * - RxState contains information related to Rx operations. + * RxState value coding follow below described bitmap : + * b7-b6 (not used) + * xx : Should be set to 00 + * b5 IP initilisation status + * 0 : Reset (IP not initialized) + * 1 : Init done (IP not initialized) + * b4-b2 (not used) + * xxx : Should be set to 000 + * b1 Rx state + * 0 : Ready (no Rx operation ongoing) + * 1 : Busy (Rx operation ongoing) + * b0 (not used) + * x : Should be set to 0. + */ +typedef enum +{ + HAL_UART_STATE_RESET = 0x00U, /*!< Peripheral is not yet Initialized + Value is allowed for gState and RxState */ + HAL_UART_STATE_READY = 0x20U, /*!< Peripheral Initialized and ready for use + Value is allowed for gState and RxState */ + HAL_UART_STATE_BUSY = 0x24U, /*!< an internal process is ongoing + Value is allowed for gState only */ + HAL_UART_STATE_BUSY_TX = 0x21U, /*!< Data Transmission process is ongoing + Value is allowed for gState only */ + HAL_UART_STATE_BUSY_RX = 0x22U, /*!< Data Reception process is ongoing + Value is allowed for RxState only */ + HAL_UART_STATE_BUSY_TX_RX = 0x23U, /*!< Data Transmission and Reception process is ongoing + Not to be used for neither gState nor RxState. + Value is result of combination (Or) between gState and RxState values */ + HAL_UART_STATE_TIMEOUT = 0xA0U, /*!< Timeout state + Value is allowed for gState only */ + HAL_UART_STATE_ERROR = 0xE0U /*!< Error + Value is allowed for gState only */ +}HAL_UART_StateTypeDef; + +/** + * @brief UART handle Structure definition + */ +typedef struct +{ + USART_TypeDef *Instance; /*!< UART registers base address */ + + UART_InitTypeDef Init; /*!< UART communication parameters */ + + uint8_t *pTxBuffPtr; /*!< Pointer to UART Tx transfer Buffer */ + + uint16_t TxXferSize; /*!< UART Tx Transfer size */ + + __IO uint16_t TxXferCount; /*!< UART Tx Transfer Counter */ + + uint8_t *pRxBuffPtr; /*!< Pointer to UART Rx transfer Buffer */ + + uint16_t RxXferSize; /*!< UART Rx Transfer size */ + + __IO uint16_t RxXferCount; /*!< UART Rx Transfer Counter */ + + DMA_HandleTypeDef *hdmatx; /*!< UART Tx DMA Handle parameters */ + + DMA_HandleTypeDef *hdmarx; /*!< UART Rx DMA Handle parameters */ + + HAL_LockTypeDef Lock; /*!< Locking object */ + + __IO HAL_UART_StateTypeDef gState; /*!< UART state information related to global Handle management + and also related to Tx operations. + This parameter can be a value of @ref HAL_UART_StateTypeDef */ + + __IO HAL_UART_StateTypeDef RxState; /*!< UART state information related to Rx operations. + This parameter can be a value of @ref HAL_UART_StateTypeDef */ + + __IO uint32_t ErrorCode; /*!< UART Error code */ + +}UART_HandleTypeDef; +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup UART_Exported_Constants UART Exported constants + * @{ + */ + +/** @defgroup UART_Error_Code UART Error Code + * @brief UART Error Code + * @{ + */ +#define HAL_UART_ERROR_NONE 0x00000000U /*!< No error */ +#define HAL_UART_ERROR_PE 0x00000001U /*!< Parity error */ +#define HAL_UART_ERROR_NE 0x00000002U /*!< Noise error */ +#define HAL_UART_ERROR_FE 0x00000004U /*!< Frame error */ +#define HAL_UART_ERROR_ORE 0x00000008U /*!< Overrun error */ +#define HAL_UART_ERROR_DMA 0x00000010U /*!< DMA transfer error */ +/** + * @} + */ + +/** @defgroup UART_Word_Length UART Word Length + * @{ + */ +#define UART_WORDLENGTH_8B 0x00000000U +#define UART_WORDLENGTH_9B ((uint32_t)USART_CR1_M) +/** + * @} + */ + +/** @defgroup UART_Stop_Bits UART Number of Stop Bits + * @{ + */ +#define UART_STOPBITS_1 0x00000000U +#define UART_STOPBITS_2 ((uint32_t)USART_CR2_STOP_1) +/** + * @} + */ + +/** @defgroup UART_Parity UART Parity + * @{ + */ +#define UART_PARITY_NONE 0x00000000U +#define UART_PARITY_EVEN ((uint32_t)USART_CR1_PCE) +#define UART_PARITY_ODD ((uint32_t)(USART_CR1_PCE | USART_CR1_PS)) +/** + * @} + */ + +/** @defgroup UART_Hardware_Flow_Control UART Hardware Flow Control + * @{ + */ +#define UART_HWCONTROL_NONE 0x00000000U +#define UART_HWCONTROL_RTS ((uint32_t)USART_CR3_RTSE) +#define UART_HWCONTROL_CTS ((uint32_t)USART_CR3_CTSE) +#define UART_HWCONTROL_RTS_CTS ((uint32_t)(USART_CR3_RTSE | USART_CR3_CTSE)) +/** + * @} + */ + +/** @defgroup UART_Mode UART Transfer Mode + * @{ + */ +#define UART_MODE_RX ((uint32_t)USART_CR1_RE) +#define UART_MODE_TX ((uint32_t)USART_CR1_TE) +#define UART_MODE_TX_RX ((uint32_t)(USART_CR1_TE |USART_CR1_RE)) +/** + * @} + */ + + /** @defgroup UART_State UART State + * @{ + */ +#define UART_STATE_DISABLE 0x00000000U +#define UART_STATE_ENABLE ((uint32_t)USART_CR1_UE) +/** + * @} + */ + +/** @defgroup UART_Over_Sampling UART Over Sampling + * @{ + */ +#define UART_OVERSAMPLING_16 0x00000000U +#define UART_OVERSAMPLING_8 ((uint32_t)USART_CR1_OVER8) +/** + * @} + */ + +/** @defgroup UART_LIN_Break_Detection_Length UART LIN Break Detection Length + * @{ + */ +#define UART_LINBREAKDETECTLENGTH_10B 0x00000000U +#define UART_LINBREAKDETECTLENGTH_11B 0x00000020U +/** + * @} + */ + +/** @defgroup UART_WakeUp_functions UART Wakeup Functions + * @{ + */ +#define UART_WAKEUPMETHOD_IDLELINE 0x00000000U +#define UART_WAKEUPMETHOD_ADDRESSMARK 0x00000800U +/** + * @} + */ + +/** @defgroup UART_Flags UART FLags + * Elements values convention: 0xXXXX + * - 0xXXXX : Flag mask in the SR register + * @{ + */ +#define UART_FLAG_CTS ((uint32_t)USART_SR_CTS) +#define UART_FLAG_LBD ((uint32_t)USART_SR_LBD) +#define UART_FLAG_TXE ((uint32_t)USART_SR_TXE) +#define UART_FLAG_TC ((uint32_t)USART_SR_TC) +#define UART_FLAG_RXNE ((uint32_t)USART_SR_RXNE) +#define UART_FLAG_IDLE ((uint32_t)USART_SR_IDLE) +#define UART_FLAG_ORE ((uint32_t)USART_SR_ORE) +#define UART_FLAG_NE ((uint32_t)USART_SR_NE) +#define UART_FLAG_FE ((uint32_t)USART_SR_FE) +#define UART_FLAG_PE ((uint32_t)USART_SR_PE) +/** + * @} + */ + +/** @defgroup UART_Interrupt_definition UART Interrupt Definitions + * Elements values convention: 0xY000XXXX + * - XXXX : Interrupt mask (16 bits) in the Y register + * - Y : Interrupt source register (2bits) + * - 0001: CR1 register + * - 0010: CR2 register + * - 0011: CR3 register + * + * @{ + */ + +#define UART_IT_PE ((uint32_t)(UART_CR1_REG_INDEX << 28U | USART_CR1_PEIE)) +#define UART_IT_TXE ((uint32_t)(UART_CR1_REG_INDEX << 28U | USART_CR1_TXEIE)) +#define UART_IT_TC ((uint32_t)(UART_CR1_REG_INDEX << 28U | USART_CR1_TCIE)) +#define UART_IT_RXNE ((uint32_t)(UART_CR1_REG_INDEX << 28U | USART_CR1_RXNEIE)) +#define UART_IT_IDLE ((uint32_t)(UART_CR1_REG_INDEX << 28U | USART_CR1_IDLEIE)) + +#define UART_IT_LBD ((uint32_t)(UART_CR2_REG_INDEX << 28U | USART_CR2_LBDIE)) + +#define UART_IT_CTS ((uint32_t)(UART_CR3_REG_INDEX << 28U | USART_CR3_CTSIE)) +#define UART_IT_ERR ((uint32_t)(UART_CR3_REG_INDEX << 28U | USART_CR3_EIE)) +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup UART_Exported_Macros UART Exported Macros + * @{ + */ + +/** @brief Reset UART handle gstate & RxState + * @param __HANDLE__: specifies the UART Handle. + * This parameter can be UARTx where x: 1, 2, 3, 4, 5, 6, 7 or 8 to select the USART or + * UART peripheral. + * @retval None + */ +#define __HAL_UART_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->gState = HAL_UART_STATE_RESET; \ + (__HANDLE__)->RxState = HAL_UART_STATE_RESET; \ + } while(0U) + +/** @brief Flushes the UART DR register + * @param __HANDLE__: specifies the UART Handle. + */ +#define __HAL_UART_FLUSH_DRREGISTER(__HANDLE__) ((__HANDLE__)->Instance->DR) + +/** @brief Checks whether the specified UART flag is set or not. + * @param __HANDLE__: specifies the UART Handle. + * This parameter can be UARTx where x: 1, 2, 3, 4, 5, 6, 7 or 8 to select the USART or + * UART peripheral. + * @param __FLAG__: specifies the flag to check. + * This parameter can be one of the following values: + * @arg UART_FLAG_CTS: CTS Change flag (not available for UART4 and UART5) + * @arg UART_FLAG_LBD: LIN Break detection flag + * @arg UART_FLAG_TXE: Transmit data register empty flag + * @arg UART_FLAG_TC: Transmission Complete flag + * @arg UART_FLAG_RXNE: Receive data register not empty flag + * @arg UART_FLAG_IDLE: Idle Line detection flag + * @arg UART_FLAG_ORE: Overrun Error flag + * @arg UART_FLAG_NE: Noise Error flag + * @arg UART_FLAG_FE: Framing Error flag + * @arg UART_FLAG_PE: Parity Error flag + * @retval The new state of __FLAG__ (TRUE or FALSE). + */ + +#define __HAL_UART_GET_FLAG(__HANDLE__, __FLAG__) (((__HANDLE__)->Instance->SR & (__FLAG__)) == (__FLAG__)) + +/** @brief Clears the specified UART pending flag. + * @param __HANDLE__: specifies the UART Handle. + * This parameter can be UARTx where x: 1, 2, 3, 4, 5, 6, 7 or 8 to select the USART or + * UART peripheral. + * @param __FLAG__: specifies the flag to check. + * This parameter can be any combination of the following values: + * @arg UART_FLAG_CTS: CTS Change flag (not available for UART4 and UART5). + * @arg UART_FLAG_LBD: LIN Break detection flag. + * @arg UART_FLAG_TC: Transmission Complete flag. + * @arg UART_FLAG_RXNE: Receive data register not empty flag. + * + * @note PE (Parity error), FE (Framing error), NE (Noise error), ORE (Overrun + * error) and IDLE (Idle line detected) flags are cleared by software + * sequence: a read operation to USART_SR register followed by a read + * operation to USART_DR register. + * @note RXNE flag can be also cleared by a read to the USART_DR register. + * @note TC flag can be also cleared by software sequence: a read operation to + * USART_SR register followed by a write operation to USART_DR register. + * @note TXE flag is cleared only by a write to the USART_DR register. + * + * @retval None + */ +#define __HAL_UART_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->SR = ~(__FLAG__)) + +/** @brief Clear the UART PE pending flag. + * @param __HANDLE__: specifies the UART Handle. + * This parameter can be UARTx where x: 1, 2, 3, 4, 5, 6, 7 or 8 to select the USART or + * UART peripheral. + * @retval None + */ +#define __HAL_UART_CLEAR_PEFLAG(__HANDLE__) \ + do{ \ + __IO uint32_t tmpreg = 0x00U; \ + tmpreg = (__HANDLE__)->Instance->SR; \ + tmpreg = (__HANDLE__)->Instance->DR; \ + UNUSED(tmpreg); \ + } while(0U) + +/** @brief Clear the UART FE pending flag. + * @param __HANDLE__: specifies the UART Handle. + * This parameter can be UARTx where x: 1, 2, 3, 4, 5, 6, 7 or 8 to select the USART or + * UART peripheral. + * @retval None + */ +#define __HAL_UART_CLEAR_FEFLAG(__HANDLE__) __HAL_UART_CLEAR_PEFLAG(__HANDLE__) + +/** @brief Clear the UART NE pending flag. + * @param __HANDLE__: specifies the UART Handle. + * This parameter can be UARTx where x: 1, 2, 3, 4, 5, 6, 7 or 8 to select the USART or + * UART peripheral. + * @retval None + */ +#define __HAL_UART_CLEAR_NEFLAG(__HANDLE__) __HAL_UART_CLEAR_PEFLAG(__HANDLE__) + +/** @brief Clear the UART ORE pending flag. + * @param __HANDLE__: specifies the UART Handle. + * This parameter can be UARTx where x: 1, 2, 3, 4, 5, 6, 7 or 8 to select the USART or + * UART peripheral. + * @retval None + */ +#define __HAL_UART_CLEAR_OREFLAG(__HANDLE__) __HAL_UART_CLEAR_PEFLAG(__HANDLE__) + +/** @brief Clear the UART IDLE pending flag. + * @param __HANDLE__: specifies the UART Handle. + * This parameter can be UARTx where x: 1, 2, 3, 4, 5, 6, 7 or 8 to select the USART or + * UART peripheral. + * @retval None + */ +#define __HAL_UART_CLEAR_IDLEFLAG(__HANDLE__) __HAL_UART_CLEAR_PEFLAG(__HANDLE__) + +/** @brief Enable the specified UART interrupt. + * @param __HANDLE__: specifies the UART Handle. + * This parameter can be UARTx where x: 1, 2, 3, 4, 5, 6, 7 or 8 to select the USART or + * UART peripheral. + * @param __INTERRUPT__: specifies the UART interrupt source to enable. + * This parameter can be one of the following values: + * @arg UART_IT_CTS: CTS change interrupt + * @arg UART_IT_LBD: LIN Break detection interrupt + * @arg UART_IT_TXE: Transmit Data Register empty interrupt + * @arg UART_IT_TC: Transmission complete interrupt + * @arg UART_IT_RXNE: Receive Data register not empty interrupt + * @arg UART_IT_IDLE: Idle line detection interrupt + * @arg UART_IT_PE: Parity Error interrupt + * @arg UART_IT_ERR: Error interrupt(Frame error, noise error, overrun error) + * @retval None + */ +#define UART_IT_MASK 0x0000FFFFU +#define __HAL_UART_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((((__INTERRUPT__) >> 28U) == 1U)? ((__HANDLE__)->Instance->CR1 |= ((__INTERRUPT__) & UART_IT_MASK)): \ + (((__INTERRUPT__) >> 28U) == 2U)? ((__HANDLE__)->Instance->CR2 |= ((__INTERRUPT__) & UART_IT_MASK)): \ + ((__HANDLE__)->Instance->CR3 |= ((__INTERRUPT__) & UART_IT_MASK))) +/** @brief Disable the specified UART interrupt. + * @param __HANDLE__: specifies the UART Handle. + * This parameter can be UARTx where x: 1, 2, 3, 4, 5, 6, 7 or 8 to select the USART or + * UART peripheral. + * @param __INTERRUPT__: specifies the UART interrupt source to disable. + * This parameter can be one of the following values: + * @arg UART_IT_CTS: CTS change interrupt + * @arg UART_IT_LBD: LIN Break detection interrupt + * @arg UART_IT_TXE: Transmit Data Register empty interrupt + * @arg UART_IT_TC: Transmission complete interrupt + * @arg UART_IT_RXNE: Receive Data register not empty interrupt + * @arg UART_IT_IDLE: Idle line detection interrupt + * @arg UART_IT_PE: Parity Error interrupt + * @arg UART_IT_ERR: Error interrupt(Frame error, noise error, overrun error) + * @retval None + */ +#define __HAL_UART_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((((__INTERRUPT__) >> 28U) == 1U)? ((__HANDLE__)->Instance->CR1 &= ~((__INTERRUPT__) & UART_IT_MASK)): \ + (((__INTERRUPT__) >> 28U) == 2U)? ((__HANDLE__)->Instance->CR2 &= ~((__INTERRUPT__) & UART_IT_MASK)): \ + ((__HANDLE__)->Instance->CR3 &= ~ ((__INTERRUPT__) & UART_IT_MASK))) + +/** @brief Checks whether the specified UART interrupt has occurred or not. + * @param __HANDLE__: specifies the UART Handle. + * This parameter can be UARTx where x: 1, 2, 3, 4, 5, 6, 7 or 8 to select the USART or + * UART peripheral. + * @param __IT__: specifies the UART interrupt source to check. + * This parameter can be one of the following values: + * @arg UART_IT_CTS: CTS change interrupt (not available for UART4 and UART5) + * @arg UART_IT_LBD: LIN Break detection interrupt + * @arg UART_IT_TXE: Transmit Data Register empty interrupt + * @arg UART_IT_TC: Transmission complete interrupt + * @arg UART_IT_RXNE: Receive Data register not empty interrupt + * @arg UART_IT_IDLE: Idle line detection interrupt + * @arg USART_IT_ERR: Error interrupt + * @retval The new state of __IT__ (TRUE or FALSE). + */ +#define __HAL_UART_GET_IT_SOURCE(__HANDLE__, __IT__) (((((__IT__) >> 28U) == 1U)? (__HANDLE__)->Instance->CR1:(((((uint32_t)(__IT__)) >> 28U) == 2U)? \ + (__HANDLE__)->Instance->CR2 : (__HANDLE__)->Instance->CR3)) & (((uint32_t)(__IT__)) & UART_IT_MASK)) + +/** @brief Enable CTS flow control + * This macro allows to enable CTS hardware flow control for a given UART instance, + * without need to call HAL_UART_Init() function. + * As involving direct access to UART registers, usage of this macro should be fully endorsed by user. + * @note As macro is expected to be used for modifying CTS Hw flow control feature activation, without need + * for USART instance Deinit/Init, following conditions for macro call should be fulfilled : + * - UART instance should have already been initialised (through call of HAL_UART_Init() ) + * - macro could only be called when corresponding UART instance is disabled (i.e __HAL_UART_DISABLE(__HANDLE__)) + * and should be followed by an Enable macro (i.e __HAL_UART_ENABLE(__HANDLE__)). + * @param __HANDLE__: specifies the UART Handle. + * The Handle Instance can be USART1, USART2 or LPUART. + * @retval None + */ +#define __HAL_UART_HWCONTROL_CTS_ENABLE(__HANDLE__) \ + do{ \ + SET_BIT((__HANDLE__)->Instance->CR3, USART_CR3_CTSE); \ + (__HANDLE__)->Init.HwFlowCtl |= USART_CR3_CTSE; \ + } while(0U) + +/** @brief Disable CTS flow control + * This macro allows to disable CTS hardware flow control for a given UART instance, + * without need to call HAL_UART_Init() function. + * As involving direct access to UART registers, usage of this macro should be fully endorsed by user. + * @note As macro is expected to be used for modifying CTS Hw flow control feature activation, without need + * for USART instance Deinit/Init, following conditions for macro call should be fulfilled : + * - UART instance should have already been initialised (through call of HAL_UART_Init() ) + * - macro could only be called when corresponding UART instance is disabled (i.e __HAL_UART_DISABLE(__HANDLE__)) + * and should be followed by an Enable macro (i.e __HAL_UART_ENABLE(__HANDLE__)). + * @param __HANDLE__: specifies the UART Handle. + * The Handle Instance can be USART1, USART2 or LPUART. + * @retval None + */ +#define __HAL_UART_HWCONTROL_CTS_DISABLE(__HANDLE__) \ + do{ \ + CLEAR_BIT((__HANDLE__)->Instance->CR3, USART_CR3_CTSE); \ + (__HANDLE__)->Init.HwFlowCtl &= ~(USART_CR3_CTSE); \ + } while(0U) + +/** @brief Enable RTS flow control + * This macro allows to enable RTS hardware flow control for a given UART instance, + * without need to call HAL_UART_Init() function. + * As involving direct access to UART registers, usage of this macro should be fully endorsed by user. + * @note As macro is expected to be used for modifying RTS Hw flow control feature activation, without need + * for USART instance Deinit/Init, following conditions for macro call should be fulfilled : + * - UART instance should have already been initialised (through call of HAL_UART_Init() ) + * - macro could only be called when corresponding UART instance is disabled (i.e __HAL_UART_DISABLE(__HANDLE__)) + * and should be followed by an Enable macro (i.e __HAL_UART_ENABLE(__HANDLE__)). + * @param __HANDLE__: specifies the UART Handle. + * The Handle Instance can be USART1, USART2 or LPUART. + * @retval None + */ +#define __HAL_UART_HWCONTROL_RTS_ENABLE(__HANDLE__) \ + do{ \ + SET_BIT((__HANDLE__)->Instance->CR3, USART_CR3_RTSE); \ + (__HANDLE__)->Init.HwFlowCtl |= USART_CR3_RTSE; \ + } while(0U) + +/** @brief Disable RTS flow control + * This macro allows to disable RTS hardware flow control for a given UART instance, + * without need to call HAL_UART_Init() function. + * As involving direct access to UART registers, usage of this macro should be fully endorsed by user. + * @note As macro is expected to be used for modifying RTS Hw flow control feature activation, without need + * for USART instance Deinit/Init, following conditions for macro call should be fulfilled : + * - UART instance should have already been initialised (through call of HAL_UART_Init() ) + * - macro could only be called when corresponding UART instance is disabled (i.e __HAL_UART_DISABLE(__HANDLE__)) + * and should be followed by an Enable macro (i.e __HAL_UART_ENABLE(__HANDLE__)). + * @param __HANDLE__: specifies the UART Handle. + * The Handle Instance can be USART1, USART2 or LPUART. + * @retval None + */ +#define __HAL_UART_HWCONTROL_RTS_DISABLE(__HANDLE__) \ + do{ \ + CLEAR_BIT((__HANDLE__)->Instance->CR3, USART_CR3_RTSE);\ + (__HANDLE__)->Init.HwFlowCtl &= ~(USART_CR3_RTSE); \ + } while(0U) + +/** @brief macros to enables the UART's one bit sample method + * @param __HANDLE__: specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_ONE_BIT_SAMPLE_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR3|= USART_CR3_ONEBIT) + +/** @brief macros to disables the UART's one bit sample method + * @param __HANDLE__: specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_ONE_BIT_SAMPLE_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR3 &= (uint16_t)~((uint16_t)USART_CR3_ONEBIT)) + +/** @brief Enable UART + * @param __HANDLE__: specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1 |= USART_CR1_UE) + +/** @brief Disable UART + * @param __HANDLE__: specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1 &= ~USART_CR1_UE) +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup UART_Exported_Functions + * @{ + */ + +/** @addtogroup UART_Exported_Functions_Group1 + * @{ + */ +/* Initialization/de-initialization functions **********************************/ +HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_HalfDuplex_Init(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_LIN_Init(UART_HandleTypeDef *huart, uint32_t BreakDetectLength); +HAL_StatusTypeDef HAL_MultiProcessor_Init(UART_HandleTypeDef *huart, uint8_t Address, uint32_t WakeUpMethod); +HAL_StatusTypeDef HAL_UART_DeInit (UART_HandleTypeDef *huart); +void HAL_UART_MspInit(UART_HandleTypeDef *huart); +void HAL_UART_MspDeInit(UART_HandleTypeDef *huart); +/** + * @} + */ + +/** @addtogroup UART_Exported_Functions_Group2 + * @{ + */ +/* IO operation functions *******************************************************/ +HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_UART_DMAPause(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UART_DMAResume(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UART_DMAStop(UART_HandleTypeDef *huart); +/* Transfer Abort functions */ +HAL_StatusTypeDef HAL_UART_Abort(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UART_AbortTransmit(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UART_AbortReceive(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UART_Abort_IT(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UART_AbortTransmit_IT(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UART_AbortReceive_IT(UART_HandleTypeDef *huart); + +void HAL_UART_IRQHandler(UART_HandleTypeDef *huart); +void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart); +void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart); +void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart); +void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart); +void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart); +void HAL_UART_AbortCpltCallback (UART_HandleTypeDef *huart); +void HAL_UART_AbortTransmitCpltCallback (UART_HandleTypeDef *huart); +void HAL_UART_AbortReceiveCpltCallback (UART_HandleTypeDef *huart); +/** + * @} + */ + +/** @addtogroup UART_Exported_Functions_Group3 + * @{ + */ +/* Peripheral Control functions ************************************************/ +HAL_StatusTypeDef HAL_LIN_SendBreak(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_MultiProcessor_EnterMuteMode(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_MultiProcessor_ExitMuteMode(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_HalfDuplex_EnableTransmitter(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_HalfDuplex_EnableReceiver(UART_HandleTypeDef *huart); +/** + * @} + */ + +/** @addtogroup UART_Exported_Functions_Group4 + * @{ + */ +/* Peripheral State functions **************************************************/ +HAL_UART_StateTypeDef HAL_UART_GetState(UART_HandleTypeDef *huart); +uint32_t HAL_UART_GetError(UART_HandleTypeDef *huart); +/** + * @} + */ + +/** + * @} + */ +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @defgroup UART_Private_Constants UART Private Constants + * @{ + */ +/** @brief UART interruptions flag mask + * + */ +#define UART_CR1_REG_INDEX 1U +#define UART_CR2_REG_INDEX 2U +#define UART_CR3_REG_INDEX 3U +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup UART_Private_Macros UART Private Macros + * @{ + */ +#define IS_UART_WORD_LENGTH(LENGTH) (((LENGTH) == UART_WORDLENGTH_8B) || \ + ((LENGTH) == UART_WORDLENGTH_9B)) +#define IS_UART_LIN_WORD_LENGTH(LENGTH) (((LENGTH) == UART_WORDLENGTH_8B)) +#define IS_UART_STOPBITS(STOPBITS) (((STOPBITS) == UART_STOPBITS_1) || \ + ((STOPBITS) == UART_STOPBITS_2)) +#define IS_UART_PARITY(PARITY) (((PARITY) == UART_PARITY_NONE) || \ + ((PARITY) == UART_PARITY_EVEN) || \ + ((PARITY) == UART_PARITY_ODD)) +#define IS_UART_HARDWARE_FLOW_CONTROL(CONTROL)\ + (((CONTROL) == UART_HWCONTROL_NONE) || \ + ((CONTROL) == UART_HWCONTROL_RTS) || \ + ((CONTROL) == UART_HWCONTROL_CTS) || \ + ((CONTROL) == UART_HWCONTROL_RTS_CTS)) +#define IS_UART_MODE(MODE) ((((MODE) & 0x0000FFF3U) == 0x00U) && ((MODE) != 0x00U)) +#define IS_UART_STATE(STATE) (((STATE) == UART_STATE_DISABLE) || \ + ((STATE) == UART_STATE_ENABLE)) +#define IS_UART_OVERSAMPLING(SAMPLING) (((SAMPLING) == UART_OVERSAMPLING_16) || \ + ((SAMPLING) == UART_OVERSAMPLING_8)) +#define IS_UART_LIN_OVERSAMPLING(SAMPLING) (((SAMPLING) == UART_OVERSAMPLING_16)) +#define IS_UART_LIN_BREAK_DETECT_LENGTH(LENGTH) (((LENGTH) == UART_LINBREAKDETECTLENGTH_10B) || \ + ((LENGTH) == UART_LINBREAKDETECTLENGTH_11B)) +#define IS_UART_WAKEUPMETHOD(WAKEUP) (((WAKEUP) == UART_WAKEUPMETHOD_IDLELINE) || \ + ((WAKEUP) == UART_WAKEUPMETHOD_ADDRESSMARK)) +#define IS_UART_BAUDRATE(BAUDRATE) ((BAUDRATE) < 10500001U) +#define IS_UART_ADDRESS(ADDRESS) ((ADDRESS) <= 0x0FU) + +#define UART_DIV_SAMPLING16(_PCLK_, _BAUD_) (((_PCLK_)*25U)/(4U*(_BAUD_))) +#define UART_DIVMANT_SAMPLING16(_PCLK_, _BAUD_) (UART_DIV_SAMPLING16((_PCLK_), (_BAUD_))/100U) +#define UART_DIVFRAQ_SAMPLING16(_PCLK_, _BAUD_) (((UART_DIV_SAMPLING16((_PCLK_), (_BAUD_)) - (UART_DIVMANT_SAMPLING16((_PCLK_), (_BAUD_)) * 100U)) * 16U + 50U) / 100U) +/* UART BRR = mantissa + overflow + fraction + = (UART DIVMANT << 4) + (UART DIVFRAQ & 0xF0) + (UART DIVFRAQ & 0x0FU) */ +#define UART_BRR_SAMPLING16(_PCLK_, _BAUD_) (((UART_DIVMANT_SAMPLING16((_PCLK_), (_BAUD_)) << 4U) + \ + (UART_DIVFRAQ_SAMPLING16((_PCLK_), (_BAUD_)) & 0xF0U)) + \ + (UART_DIVFRAQ_SAMPLING16((_PCLK_), (_BAUD_)) & 0x0FU)) + +#define UART_DIV_SAMPLING8(_PCLK_, _BAUD_) (((_PCLK_)*25U)/(2U*(_BAUD_))) +#define UART_DIVMANT_SAMPLING8(_PCLK_, _BAUD_) (UART_DIV_SAMPLING8((_PCLK_), (_BAUD_))/100U) +#define UART_DIVFRAQ_SAMPLING8(_PCLK_, _BAUD_) (((UART_DIV_SAMPLING8((_PCLK_), (_BAUD_)) - (UART_DIVMANT_SAMPLING8((_PCLK_), (_BAUD_)) * 100U)) * 8U + 50U) / 100U) +/* UART BRR = mantissa + overflow + fraction + = (UART DIVMANT << 4) + ((UART DIVFRAQ & 0xF8) << 1) + (UART DIVFRAQ & 0x07U) */ +#define UART_BRR_SAMPLING8(_PCLK_, _BAUD_) (((UART_DIVMANT_SAMPLING8((_PCLK_), (_BAUD_)) << 4U) + \ + ((UART_DIVFRAQ_SAMPLING8((_PCLK_), (_BAUD_)) & 0xF8U) << 1U)) + \ + (UART_DIVFRAQ_SAMPLING8((_PCLK_), (_BAUD_)) & 0x07U)) + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/** @defgroup UART_Private_Functions UART Private Functions + * @{ + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_HAL_UART_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c b/Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c new file mode 100644 index 000000000..40f28ea8e --- /dev/null +++ b/Firmware/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c @@ -0,0 +1,2539 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_uart.c + * @author MCD Application Team + * @version V1.7.1 + * @date 14-April-2017 + * @brief UART HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Universal Asynchronous Receiver Transmitter (UART) peripheral: + * + Initialization and de-initialization functions + * + IO operation functions + * + Peripheral Control functions + * + Peripheral State and Errors functions + * + @verbatim + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + [..] + The UART HAL driver can be used as follows: + + (#) Declare a UART_HandleTypeDef handle structure. + + (#) Initialize the UART low level resources by implementing the HAL_UART_MspInit() API: + (##) Enable the USARTx interface clock. + (##) UART pins configuration: + (+++) Enable the clock for the UART GPIOs. + (+++) Configure these UART pins as alternate function pull-up. + (##) NVIC configuration if you need to use interrupt process (HAL_UART_Transmit_IT() + and HAL_UART_Receive_IT() APIs): + (+++) Configure the USARTx interrupt priority. + (+++) Enable the NVIC USART IRQ handle. + (##) DMA Configuration if you need to use DMA process (HAL_UART_Transmit_DMA() + and HAL_UART_Receive_DMA() APIs): + (+++) Declare a DMA handle structure for the Tx/Rx stream. + (+++) Enable the DMAx interface clock. + (+++) Configure the declared DMA handle structure with the required + Tx/Rx parameters. + (+++) Configure the DMA Tx/Rx Stream. + (+++) Associate the initialized DMA handle to the UART DMA Tx/Rx handle. + (+++) Configure the priority and enable the NVIC for the transfer complete + interrupt on the DMA Tx/Rx Stream. + + (#) Program the Baud Rate, Word Length, Stop Bit, Parity, Hardware + flow control and Mode(Receiver/Transmitter) in the Init structure. + + (#) For the UART asynchronous mode, initialize the UART registers by calling + the HAL_UART_Init() API. + + (#) For the UART Half duplex mode, initialize the UART registers by calling + the HAL_HalfDuplex_Init() API. + + (#) For the LIN mode, initialize the UART registers by calling the HAL_LIN_Init() API. + + (#) For the Multi-Processor mode, initialize the UART registers by calling + the HAL_MultiProcessor_Init() API. + + [..] + (@) The specific UART interrupts (Transmission complete interrupt, + RXNE interrupt and Error Interrupts) will be managed using the macros + __HAL_UART_ENABLE_IT() and __HAL_UART_DISABLE_IT() inside the transmit + and receive process. + + [..] + (@) These APIs (HAL_UART_Init() and HAL_HalfDuplex_Init()) configure also the + low level Hardware GPIO, CLOCK, CORTEX...etc) by calling the customized + HAL_UART_MspInit() API. + + [..] + Three operation modes are available within this driver : + + *** Polling mode IO operation *** + ================================= + [..] + (+) Send an amount of data in blocking mode using HAL_UART_Transmit() + (+) Receive an amount of data in blocking mode using HAL_UART_Receive() + + *** Interrupt mode IO operation *** + =================================== + [..] + (+) Send an amount of data in non blocking mode using HAL_UART_Transmit_IT() + (+) At transmission end of transfer HAL_UART_TxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_UART_TxCpltCallback + (+) Receive an amount of data in non blocking mode using HAL_UART_Receive_IT() + (+) At reception end of transfer HAL_UART_RxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_UART_RxCpltCallback + (+) In case of transfer Error, HAL_UART_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_UART_ErrorCallback + + *** DMA mode IO operation *** + ============================== + [..] + (+) Send an amount of data in non blocking mode (DMA) using HAL_UART_Transmit_DMA() + (+) At transmission end of half transfer HAL_UART_TxHalfCpltCallback is executed and user can + add his own code by customization of function pointer HAL_UART_TxHalfCpltCallback + (+) At transmission end of transfer HAL_UART_TxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_UART_TxCpltCallback + (+) Receive an amount of data in non blocking mode (DMA) using HAL_UART_Receive_DMA() + (+) At reception end of half transfer HAL_UART_RxHalfCpltCallback is executed and user can + add his own code by customization of function pointer HAL_UART_RxHalfCpltCallback + (+) At reception end of transfer HAL_UART_RxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_UART_RxCpltCallback + (+) In case of transfer Error, HAL_UART_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_UART_ErrorCallback + (+) Pause the DMA Transfer using HAL_UART_DMAPause() + (+) Resume the DMA Transfer using HAL_UART_DMAResume() + (+) Stop the DMA Transfer using HAL_UART_DMAStop() + + *** UART HAL driver macros list *** + ============================================= + [..] + Below the list of most used macros in UART HAL driver. + + (+) __HAL_UART_ENABLE: Enable the UART peripheral + (+) __HAL_UART_DISABLE: Disable the UART peripheral + (+) __HAL_UART_GET_FLAG : Check whether the specified UART flag is set or not + (+) __HAL_UART_CLEAR_FLAG : Clear the specified UART pending flag + (+) __HAL_UART_ENABLE_IT: Enable the specified UART interrupt + (+) __HAL_UART_DISABLE_IT: Disable the specified UART interrupt + (+) __HAL_UART_GET_IT_SOURCE: Check whether the specified UART interrupt has occurred or not + + [..] + (@) You can refer to the UART HAL driver header file for more useful macros + + @endverbatim + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup UART UART + * @brief HAL UART module driver + * @{ + */ +#ifdef HAL_UART_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @addtogroup UART_Private_Constants + * @{ + */ +/** + * @} + */ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/** @addtogroup UART_Private_Functions UART Private Functions + * @{ + */ +static void UART_EndTxTransfer(UART_HandleTypeDef *huart); +static void UART_EndRxTransfer(UART_HandleTypeDef *huart); +static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma); +static void UART_DMAReceiveCplt(DMA_HandleTypeDef *hdma); +static void UART_DMATxHalfCplt(DMA_HandleTypeDef *hdma); +static void UART_DMARxHalfCplt(DMA_HandleTypeDef *hdma); +static void UART_DMAError(DMA_HandleTypeDef *hdma); +static void UART_DMAAbortOnError(DMA_HandleTypeDef *hdma); +static void UART_DMATxAbortCallback(DMA_HandleTypeDef *hdma); +static void UART_DMARxAbortCallback(DMA_HandleTypeDef *hdma); +static void UART_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma); +static void UART_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma); +static HAL_StatusTypeDef UART_Transmit_IT(UART_HandleTypeDef *huart); +static HAL_StatusTypeDef UART_EndTransmit_IT(UART_HandleTypeDef *huart); +static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart); +static HAL_StatusTypeDef UART_WaitOnFlagUntilTimeout(UART_HandleTypeDef *huart, uint32_t Flag, FlagStatus Status, uint32_t Tickstart, uint32_t Timeout); +static void UART_SetConfig (UART_HandleTypeDef *huart); +/** + * @} + */ + +/* Exported functions ---------------------------------------------------------*/ +/** @defgroup UART_Exported_Functions UART Exported Functions + * @{ + */ + +/** @defgroup UART_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim +=============================================================================== + ##### Initialization and Configuration functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to initialize the USARTx or the UARTy + in asynchronous mode. + (+) For the asynchronous mode only these parameters can be configured: + (++) Baud Rate + (++) Word Length + (++) Stop Bit + (++) Parity: If the parity is enabled, then the MSB bit of the data written + in the data register is transmitted but is changed by the parity bit. + Depending on the frame length defined by the M bit (8-bits or 9-bits), + please refer to Reference manual for possible UART frame formats. + (++) Hardware flow control + (++) Receiver/transmitter modes + (++) Over Sampling Method + [..] + The HAL_UART_Init(), HAL_HalfDuplex_Init(), HAL_LIN_Init() and HAL_MultiProcessor_Init() APIs + follow respectively the UART asynchronous, UART Half duplex, LIN and Multi-Processor + configuration procedures (details for the procedures are available in reference manual (RM0329)). + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the UART mode according to the specified parameters in + * the UART_InitTypeDef and create the associated handle. + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart) +{ + /* Check the UART handle allocation */ + if(huart == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + if(huart->Init.HwFlowCtl != UART_HWCONTROL_NONE) + { + /* The hardware flow control is available only for USART1, USART2, USART3 and USART6 */ + assert_param(IS_UART_HWFLOW_INSTANCE(huart->Instance)); + assert_param(IS_UART_HARDWARE_FLOW_CONTROL(huart->Init.HwFlowCtl)); + } + else + { + assert_param(IS_UART_INSTANCE(huart->Instance)); + } + assert_param(IS_UART_WORD_LENGTH(huart->Init.WordLength)); + assert_param(IS_UART_OVERSAMPLING(huart->Init.OverSampling)); + + if(huart->gState == HAL_UART_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + huart->Lock = HAL_UNLOCKED; + /* Init the low level hardware */ + HAL_UART_MspInit(huart); + } + + huart->gState = HAL_UART_STATE_BUSY; + + /* Disable the peripheral */ + __HAL_UART_DISABLE(huart); + + /* Set the UART Communication parameters */ + UART_SetConfig(huart); + + /* In asynchronous mode, the following bits must be kept cleared: + - LINEN and CLKEN bits in the USART_CR2 register, + - SCEN, HDSEL and IREN bits in the USART_CR3 register.*/ + CLEAR_BIT(huart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN)); + CLEAR_BIT(huart->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN)); + + /* Enable the peripheral */ + __HAL_UART_ENABLE(huart); + + /* Initialize the UART state */ + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->gState= HAL_UART_STATE_READY; + huart->RxState= HAL_UART_STATE_READY; + + return HAL_OK; +} + +/** + * @brief Initializes the half-duplex mode according to the specified + * parameters in the UART_InitTypeDef and create the associated handle. + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HalfDuplex_Init(UART_HandleTypeDef *huart) +{ + /* Check the UART handle allocation */ + if(huart == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_UART_INSTANCE(huart->Instance)); + assert_param(IS_UART_WORD_LENGTH(huart->Init.WordLength)); + assert_param(IS_UART_OVERSAMPLING(huart->Init.OverSampling)); + + if(huart->gState == HAL_UART_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + huart->Lock = HAL_UNLOCKED; + /* Init the low level hardware */ + HAL_UART_MspInit(huart); + } + + huart->gState = HAL_UART_STATE_BUSY; + + /* Disable the peripheral */ + __HAL_UART_DISABLE(huart); + + /* Set the UART Communication parameters */ + UART_SetConfig(huart); + + /* In half-duplex mode, the following bits must be kept cleared: + - LINEN and CLKEN bits in the USART_CR2 register, + - SCEN and IREN bits in the USART_CR3 register.*/ + CLEAR_BIT(huart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN)); + CLEAR_BIT(huart->Instance->CR3, (USART_CR3_IREN | USART_CR3_SCEN)); + + /* Enable the Half-Duplex mode by setting the HDSEL bit in the CR3 register */ + SET_BIT(huart->Instance->CR3, USART_CR3_HDSEL); + + /* Enable the peripheral */ + __HAL_UART_ENABLE(huart); + + /* Initialize the UART state*/ + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->gState= HAL_UART_STATE_READY; + huart->RxState= HAL_UART_STATE_READY; + + return HAL_OK; +} + +/** + * @brief Initializes the LIN mode according to the specified + * parameters in the UART_InitTypeDef and create the associated handle. + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @param BreakDetectLength: Specifies the LIN break detection length. + * This parameter can be one of the following values: + * @arg UART_LINBREAKDETECTLENGTH_10B: 10-bit break detection + * @arg UART_LINBREAKDETECTLENGTH_11B: 11-bit break detection + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LIN_Init(UART_HandleTypeDef *huart, uint32_t BreakDetectLength) +{ + /* Check the UART handle allocation */ + if(huart == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_UART_INSTANCE(huart->Instance)); + assert_param(IS_UART_LIN_BREAK_DETECT_LENGTH(BreakDetectLength)); + assert_param(IS_UART_LIN_WORD_LENGTH(huart->Init.WordLength)); + assert_param(IS_UART_LIN_OVERSAMPLING(huart->Init.OverSampling)); + + if(huart->gState == HAL_UART_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + huart->Lock = HAL_UNLOCKED; + /* Init the low level hardware */ + HAL_UART_MspInit(huart); + } + + huart->gState = HAL_UART_STATE_BUSY; + + /* Disable the peripheral */ + __HAL_UART_DISABLE(huart); + + /* Set the UART Communication parameters */ + UART_SetConfig(huart); + + /* In LIN mode, the following bits must be kept cleared: + - LINEN and CLKEN bits in the USART_CR2 register, + - SCEN and IREN bits in the USART_CR3 register.*/ + CLEAR_BIT(huart->Instance->CR2, USART_CR2_CLKEN); + CLEAR_BIT(huart->Instance->CR3, (USART_CR3_HDSEL | USART_CR3_IREN | USART_CR3_SCEN)); + + /* Enable the LIN mode by setting the LINEN bit in the CR2 register */ + SET_BIT(huart->Instance->CR2, USART_CR2_LINEN); + + /* Set the USART LIN Break detection length. */ + CLEAR_BIT(huart->Instance->CR2, USART_CR2_LBDL); + SET_BIT(huart->Instance->CR2, BreakDetectLength); + + /* Enable the peripheral */ + __HAL_UART_ENABLE(huart); + + /* Initialize the UART state*/ + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->gState= HAL_UART_STATE_READY; + huart->RxState= HAL_UART_STATE_READY; + + return HAL_OK; +} + +/** + * @brief Initializes the Multi-Processor mode according to the specified + * parameters in the UART_InitTypeDef and create the associated handle. + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @param Address: USART address + * @param WakeUpMethod: specifies the USART wake-up method. + * This parameter can be one of the following values: + * @arg UART_WAKEUPMETHOD_IDLELINE: Wake-up by an idle line detection + * @arg UART_WAKEUPMETHOD_ADDRESSMARK: Wake-up by an address mark + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MultiProcessor_Init(UART_HandleTypeDef *huart, uint8_t Address, uint32_t WakeUpMethod) +{ + /* Check the UART handle allocation */ + if(huart == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_UART_INSTANCE(huart->Instance)); + assert_param(IS_UART_WAKEUPMETHOD(WakeUpMethod)); + assert_param(IS_UART_ADDRESS(Address)); + assert_param(IS_UART_WORD_LENGTH(huart->Init.WordLength)); + assert_param(IS_UART_OVERSAMPLING(huart->Init.OverSampling)); + + if(huart->gState == HAL_UART_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + huart->Lock = HAL_UNLOCKED; + /* Init the low level hardware */ + HAL_UART_MspInit(huart); + } + + huart->gState = HAL_UART_STATE_BUSY; + + /* Disable the peripheral */ + __HAL_UART_DISABLE(huart); + + /* Set the UART Communication parameters */ + UART_SetConfig(huart); + + /* In Multi-Processor mode, the following bits must be kept cleared: + - LINEN and CLKEN bits in the USART_CR2 register, + - SCEN, HDSEL and IREN bits in the USART_CR3 register */ + CLEAR_BIT(huart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN)); + CLEAR_BIT(huart->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN)); + + /* Clear the USART address */ + CLEAR_BIT(huart->Instance->CR2, USART_CR2_ADD); + /* Set the USART address node */ + SET_BIT(huart->Instance->CR2, Address); + + /* Set the wake up method by setting the WAKE bit in the CR1 register */ + CLEAR_BIT(huart->Instance->CR1, USART_CR1_WAKE); + SET_BIT(huart->Instance->CR1, WakeUpMethod); + + /* Enable the peripheral */ + __HAL_UART_ENABLE(huart); + + /* Initialize the UART state */ + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->gState= HAL_UART_STATE_READY; + huart->RxState= HAL_UART_STATE_READY; + + return HAL_OK; +} + +/** + * @brief DeInitializes the UART peripheral. + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_DeInit(UART_HandleTypeDef *huart) +{ + /* Check the UART handle allocation */ + if(huart == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_UART_INSTANCE(huart->Instance)); + + huart->gState = HAL_UART_STATE_BUSY; + + /* DeInit the low level hardware */ + HAL_UART_MspDeInit(huart); + + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->gState = HAL_UART_STATE_RESET; + huart->RxState = HAL_UART_STATE_RESET; + + /* Process Lock */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief UART MSP Init. + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval None + */ + __weak void HAL_UART_MspInit(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + /* NOTE: This function Should not be modified, when the callback is needed, + the HAL_UART_MspInit could be implemented in the user file + */ +} + +/** + * @brief UART MSP DeInit. + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval None + */ + __weak void HAL_UART_MspDeInit(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + /* NOTE: This function Should not be modified, when the callback is needed, + the HAL_UART_MspDeInit could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup UART_Exported_Functions_Group2 IO operation functions + * @brief UART Transmit and Receive functions + * +@verbatim + ============================================================================== + ##### IO operation functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to manage the UART asynchronous + and Half duplex data transfers. + + (#) There are two modes of transfer: + (++) Blocking mode: The communication is performed in polling mode. + The HAL status of all data processing is returned by the same function + after finishing transfer. + (++) Non blocking mode: The communication is performed using Interrupts + or DMA, these APIs return the HAL status. + The end of the data processing will be indicated through the + dedicated UART IRQ when using Interrupt mode or the DMA IRQ when + using DMA mode. + The HAL_UART_TxCpltCallback(), HAL_UART_RxCpltCallback() user callbacks + will be executed respectively at the end of the transmit or receive process. + The HAL_UART_ErrorCallback() user callback will be executed when + a communication error is detected. + + (#) Blocking mode APIs are: + (++) HAL_UART_Transmit() + (++) HAL_UART_Receive() + + (#) Non Blocking mode APIs with Interrupt are: + (++) HAL_UART_Transmit_IT() + (++) HAL_UART_Receive_IT() + (++) HAL_UART_IRQHandler() + + (#) Non Blocking mode functions with DMA are: + (++) HAL_UART_Transmit_DMA() + (++) HAL_UART_Receive_DMA() + + (#) A set of Transfer Complete Callbacks are provided in non blocking mode: + (++) HAL_UART_TxCpltCallback() + (++) HAL_UART_RxCpltCallback() + (++) HAL_UART_ErrorCallback() + + [..] + (@) In the Half duplex communication, it is forbidden to run the transmit + and receive process in parallel, the UART state HAL_UART_STATE_BUSY_TX_RX + can't be useful. + +@endverbatim + * @{ + */ + +/** + * @brief Sends an amount of data in blocking mode. + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @param pData: Pointer to data buffer + * @param Size: Amount of data to be sent + * @param Timeout: Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint16_t* tmp; + uint32_t tickstart = 0U; + + /* Check that a Tx process is not already ongoing */ + if(huart->gState == HAL_UART_STATE_READY) + { + if((pData == NULL ) || (Size == 0)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->gState = HAL_UART_STATE_BUSY_TX; + + /* Init tickstart for timeout managment */ + tickstart = HAL_GetTick(); + + huart->TxXferSize = Size; + huart->TxXferCount = Size; + while(huart->TxXferCount > 0U) + { + huart->TxXferCount--; + if(huart->Init.WordLength == UART_WORDLENGTH_9B) + { + if(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + tmp = (uint16_t*) pData; + huart->Instance->DR = (*tmp & (uint16_t)0x01FF); + if(huart->Init.Parity == UART_PARITY_NONE) + { + pData +=2U; + } + else + { + pData +=1U; + } + } + else + { + if(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + huart->Instance->DR = (*pData++ & (uint8_t)0xFF); + } + } + + if(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* At end of Tx process, restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receives an amount of data in blocking mode. + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @param pData: Pointer to data buffer + * @param Size: Amount of data to be received + * @param Timeout: Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint16_t* tmp; + uint32_t tickstart = 0U; + + /* Check that a Rx process is not already ongoing */ + if(huart->RxState == HAL_UART_STATE_READY) + { + if((pData == NULL ) || (Size == 0)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->RxState = HAL_UART_STATE_BUSY_RX; + + /* Init tickstart for timeout managment */ + tickstart = HAL_GetTick(); + + huart->RxXferSize = Size; + huart->RxXferCount = Size; + + /* Check the remain data to be received */ + while(huart->RxXferCount > 0U) + { + huart->RxXferCount--; + if(huart->Init.WordLength == UART_WORDLENGTH_9B) + { + if(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + tmp = (uint16_t*) pData; + if(huart->Init.Parity == UART_PARITY_NONE) + { + *tmp = (uint16_t)(huart->Instance->DR & (uint16_t)0x01FF); + pData +=2U; + } + else + { + *tmp = (uint16_t)(huart->Instance->DR & (uint16_t)0x00FF); + pData +=1U; + } + + } + else + { + if(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + if(huart->Init.Parity == UART_PARITY_NONE) + { + *pData++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF); + } + else + { + *pData++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x007F); + } + + } + } + + /* At end of Rx process, restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Sends an amount of data in non blocking mode. + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @param pData: Pointer to data buffer + * @param Size: Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) +{ + /* Check that a Tx process is not already ongoing */ + if(huart->gState == HAL_UART_STATE_READY) + { + if((pData == NULL ) || (Size == 0)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->pTxBuffPtr = pData; + huart->TxXferSize = Size; + huart->TxXferCount = Size; + + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->gState = HAL_UART_STATE_BUSY_TX; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + /* Enable the UART Transmit data register empty Interrupt */ + SET_BIT(huart->Instance->CR1, USART_CR1_TXEIE); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receives an amount of data in non blocking mode + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @param pData: Pointer to data buffer + * @param Size: Amount of data to be received + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) +{ + /* Check that a Rx process is not already ongoing */ + if(huart->RxState == HAL_UART_STATE_READY) + { + if((pData == NULL ) || (Size == 0)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->pRxBuffPtr = pData; + huart->RxXferSize = Size; + huart->RxXferCount = Size; + + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->RxState = HAL_UART_STATE_BUSY_RX; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */ + SET_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Enable the UART Parity Error and Data Register not empty Interrupts */ + SET_BIT(huart->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Sends an amount of data in non blocking mode. + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @param pData: Pointer to data buffer + * @param Size: Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) +{ + uint32_t *tmp; + + /* Check that a Tx process is not already ongoing */ + if(huart->gState == HAL_UART_STATE_READY) + { + if((pData == NULL ) || (Size == 0)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->pTxBuffPtr = pData; + huart->TxXferSize = Size; + huart->TxXferCount = Size; + + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->gState = HAL_UART_STATE_BUSY_TX; + + /* Set the UART DMA transfer complete callback */ + huart->hdmatx->XferCpltCallback = UART_DMATransmitCplt; + + /* Set the UART DMA Half transfer complete callback */ + huart->hdmatx->XferHalfCpltCallback = UART_DMATxHalfCplt; + + /* Set the DMA error callback */ + huart->hdmatx->XferErrorCallback = UART_DMAError; + + /* Set the DMA abort callback */ + huart->hdmatx->XferAbortCallback = NULL; + + /* Enable the UART transmit DMA Stream */ + tmp = (uint32_t*)&pData; + HAL_DMA_Start_IT(huart->hdmatx, *(uint32_t*)tmp, (uint32_t)&huart->Instance->DR, Size); + + /* Clear the TC flag in the SR register by writing 0 to it */ + __HAL_UART_CLEAR_FLAG(huart, UART_FLAG_TC); + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + /* Enable the DMA transfer for transmit request by setting the DMAT bit + in the UART CR3 register */ + SET_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receives an amount of data in non blocking mode. + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @param pData: Pointer to data buffer + * @param Size: Amount of data to be received + * @note When the UART parity is enabled (PCE = 1) the data received contain the parity bit. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) +{ + uint32_t *tmp; + + /* Check that a Rx process is not already ongoing */ + if(huart->RxState == HAL_UART_STATE_READY) + { + if((pData == NULL ) || (Size == 0)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->pRxBuffPtr = pData; + huart->RxXferSize = Size; + + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->RxState = HAL_UART_STATE_BUSY_RX; + + /* Set the UART DMA transfer complete callback */ + huart->hdmarx->XferCpltCallback = UART_DMAReceiveCplt; + + /* Set the UART DMA Half transfer complete callback */ + huart->hdmarx->XferHalfCpltCallback = UART_DMARxHalfCplt; + + /* Set the DMA error callback */ + huart->hdmarx->XferErrorCallback = UART_DMAError; + + /* Set the DMA abort callback */ + huart->hdmarx->XferAbortCallback = NULL; + + /* Enable the DMA Stream */ + tmp = (uint32_t*)&pData; + HAL_DMA_Start_IT(huart->hdmarx, (uint32_t)&huart->Instance->DR, *(uint32_t*)tmp, Size); + + /* Clear the Overrun flag just before enabling the DMA Rx request: can be mandatory for the second transfer */ + __HAL_UART_CLEAR_OREFLAG(huart); + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + /* Enable the UART Parity Error Interrupt */ + SET_BIT(huart->Instance->CR1, USART_CR1_PEIE); + + /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */ + SET_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Enable the DMA transfer for the receiver request by setting the DMAR bit + in the UART CR3 register */ + SET_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Pauses the DMA Transfer. + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_DMAPause(UART_HandleTypeDef *huart) +{ + uint32_t dmarequest = 0x00U; + + /* Process Locked */ + __HAL_LOCK(huart); + dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT); + if((huart->gState == HAL_UART_STATE_BUSY_TX) && dmarequest) + { + /* Disable the UART DMA Tx request */ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + } + dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR); + if((huart->RxState == HAL_UART_STATE_BUSY_RX) && dmarequest) + { + /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(huart->Instance->CR1, USART_CR1_PEIE); + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Disable the UART DMA Rx request */ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + } + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Resumes the DMA Transfer. + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_DMAResume(UART_HandleTypeDef *huart) +{ + /* Process Locked */ + __HAL_LOCK(huart); + + if(huart->gState == HAL_UART_STATE_BUSY_TX) + { + /* Enable the UART DMA Tx request */ + SET_BIT(huart->Instance->CR3, USART_CR3_DMAT); + } + if(huart->RxState == HAL_UART_STATE_BUSY_RX) + { + /* Clear the Overrun flag before resuming the Rx transfer*/ + __HAL_UART_CLEAR_OREFLAG(huart); + + /* Reenable PE and ERR (Frame error, noise error, overrun error) interrupts */ + SET_BIT(huart->Instance->CR1, USART_CR1_PEIE); + SET_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Enable the UART DMA Rx request */ + SET_BIT(huart->Instance->CR3, USART_CR3_DMAR); + } + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Stops the DMA Transfer. + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_DMAStop(UART_HandleTypeDef *huart) +{ + uint32_t dmarequest = 0x00U; + /* The Lock is not implemented on this API to allow the user application + to call the HAL UART API under callbacks HAL_UART_TxCpltCallback() / HAL_UART_RxCpltCallback(): + when calling HAL_DMA_Abort() API the DMA TX/RX Transfer complete interrupt is generated + and the correspond call back is executed HAL_UART_TxCpltCallback() / HAL_UART_RxCpltCallback() + */ + + /* Stop UART DMA Tx request if ongoing */ + dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT); + if((huart->gState == HAL_UART_STATE_BUSY_TX) && dmarequest) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + /* Abort the UART DMA Tx channel */ + if(huart->hdmatx != NULL) + { + HAL_DMA_Abort(huart->hdmatx); + } + UART_EndTxTransfer(huart); + } + + /* Stop UART DMA Rx request if ongoing */ + dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR); + if((huart->RxState == HAL_UART_STATE_BUSY_RX) && dmarequest) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the UART DMA Rx channel */ + if(huart->hdmarx != NULL) + { + HAL_DMA_Abort(huart->hdmarx); + } + UART_EndRxTransfer(huart); + } + + return HAL_OK; +} + +/** + * @brief Abort ongoing transfers (blocking mode). + * @param huart UART handle. + * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable PPP Interrupts + * - Disable the DMA transfer in the peripheral register (if enabled) + * - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode) + * - Set handle State to READY + * @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed. + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_UART_Abort(UART_HandleTypeDef *huart) +{ + /* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE)); + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Disable the UART DMA Tx request if enabled */ + if(HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT)) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + /* Abort the UART DMA Tx channel: use blocking DMA Abort API (no callback) */ + if(huart->hdmatx != NULL) + { + /* Set the UART DMA Abort callback to Null. + No call back execution at end of DMA abort procedure */ + huart->hdmatx->XferAbortCallback = NULL; + + HAL_DMA_Abort(huart->hdmatx); + } + } + + /* Disable the UART DMA Rx request if enabled */ + if(HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the UART DMA Rx channel: use blocking DMA Abort API (no callback) */ + if(huart->hdmarx != NULL) + { + /* Set the UART DMA Abort callback to Null. + No call back execution at end of DMA abort procedure */ + huart->hdmarx->XferAbortCallback = NULL; + + HAL_DMA_Abort(huart->hdmarx); + } + } + + /* Reset Tx and Rx transfer counters */ + huart->TxXferCount = 0x00U; + huart->RxXferCount = 0x00U; + + /* Reset ErrorCode */ + huart->ErrorCode = HAL_UART_ERROR_NONE; + + /* Restore huart->RxState and huart->gState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + huart->gState = HAL_UART_STATE_READY; + + return HAL_OK; +} + +/** + * @brief Abort ongoing Transmit transfer (blocking mode). + * @param huart UART handle. + * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable PPP Interrupts + * - Disable the DMA transfer in the peripheral register (if enabled) + * - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode) + * - Set handle State to READY + * @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed. + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_UART_AbortTransmit(UART_HandleTypeDef *huart) +{ + /* Disable TXEIE and TCIE interrupts */ + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE)); + + /* Disable the UART DMA Tx request if enabled */ + if(HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT)) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + /* Abort the UART DMA Tx channel : use blocking DMA Abort API (no callback) */ + if(huart->hdmatx != NULL) + { + /* Set the UART DMA Abort callback to Null. + No call back execution at end of DMA abort procedure */ + huart->hdmatx->XferAbortCallback = NULL; + + HAL_DMA_Abort(huart->hdmatx); + } + } + + /* Reset Tx transfer counter */ + huart->TxXferCount = 0x00U; + + /* Restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; + + return HAL_OK; +} + +/** + * @brief Abort ongoing Receive transfer (blocking mode). + * @param huart UART handle. + * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable PPP Interrupts + * - Disable the DMA transfer in the peripheral register (if enabled) + * - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode) + * - Set handle State to READY + * @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed. + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_UART_AbortReceive(UART_HandleTypeDef *huart) +{ + /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Disable the UART DMA Rx request if enabled */ + if(HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the UART DMA Rx channel : use blocking DMA Abort API (no callback) */ + if(huart->hdmarx != NULL) + { + /* Set the UART DMA Abort callback to Null. + No call back execution at end of DMA abort procedure */ + huart->hdmarx->XferAbortCallback = NULL; + + HAL_DMA_Abort(huart->hdmarx); + } + } + + /* Reset Rx transfer counter */ + huart->RxXferCount = 0x00U; + + /* Restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + return HAL_OK; +} + +/** + * @brief Abort ongoing transfers (Interrupt mode). + * @param huart UART handle. + * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable PPP Interrupts + * - Disable the DMA transfer in the peripheral register (if enabled) + * - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode) + * - Set handle State to READY + * - At abort completion, call user abort complete callback + * @note This procedure is executed in Interrupt mode, meaning that abort procedure could be + * considered as completed only when user abort complete callback is executed (not when exiting function). + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_UART_Abort_IT(UART_HandleTypeDef *huart) +{ + uint32_t AbortCplt = 0x01U; + + /* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE)); + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* If DMA Tx and/or DMA Rx Handles are associated to UART Handle, DMA Abort complete callbacks should be initialised + before any call to DMA Abort functions */ + /* DMA Tx Handle is valid */ + if(huart->hdmatx != NULL) + { + /* Set DMA Abort Complete callback if UART DMA Tx request if enabled. + Otherwise, set it to NULL */ + if(HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT)) + { + huart->hdmatx->XferAbortCallback = UART_DMATxAbortCallback; + } + else + { + huart->hdmatx->XferAbortCallback = NULL; + } + } + /* DMA Rx Handle is valid */ + if(huart->hdmarx != NULL) + { + /* Set DMA Abort Complete callback if UART DMA Rx request if enabled. + Otherwise, set it to NULL */ + if(HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) + { + huart->hdmarx->XferAbortCallback = UART_DMARxAbortCallback; + } + else + { + huart->hdmarx->XferAbortCallback = NULL; + } + } + + /* Disable the UART DMA Tx request if enabled */ + if(HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT)) + { + /* Disable DMA Tx at UART level */ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + /* Abort the UART DMA Tx channel : use non blocking DMA Abort API (callback) */ + if(huart->hdmatx != NULL) + { + /* UART Tx DMA Abort callback has already been initialised : + will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */ + + /* Abort DMA TX */ + if(HAL_DMA_Abort_IT(huart->hdmatx) != HAL_OK) + { + huart->hdmatx->XferAbortCallback = NULL; + } + else + { + AbortCplt = 0x00U; + } + } + } + + /* Disable the UART DMA Rx request if enabled */ + if(HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the UART DMA Rx channel : use non blocking DMA Abort API (callback) */ + if(huart->hdmarx != NULL) + { + /* UART Rx DMA Abort callback has already been initialised : + will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */ + + /* Abort DMA RX */ + if(HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK) + { + huart->hdmarx->XferAbortCallback = NULL; + AbortCplt = 0x01U; + } + else + { + AbortCplt = 0x00U; + } + } + } + + /* if no DMA abort complete callback execution is required => call user Abort Complete callback */ + if(AbortCplt == 0x01U) + { + /* Reset Tx and Rx transfer counters */ + huart->TxXferCount = 0x00U; + huart->RxXferCount = 0x00U; + + /* Reset ErrorCode */ + huart->ErrorCode = HAL_UART_ERROR_NONE; + + /* Restore huart->gState and huart->RxState to Ready */ + huart->gState = HAL_UART_STATE_READY; + huart->RxState = HAL_UART_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ + HAL_UART_AbortCpltCallback(huart); + } + + return HAL_OK; +} + +/** + * @brief Abort ongoing Transmit transfer (Interrupt mode). + * @param huart UART handle. + * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable PPP Interrupts + * - Disable the DMA transfer in the peripheral register (if enabled) + * - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode) + * - Set handle State to READY + * - At abort completion, call user abort complete callback + * @note This procedure is executed in Interrupt mode, meaning that abort procedure could be + * considered as completed only when user abort complete callback is executed (not when exiting function). + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_UART_AbortTransmit_IT(UART_HandleTypeDef *huart) +{ + /* Disable TXEIE and TCIE interrupts */ + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE)); + + /* Disable the UART DMA Tx request if enabled */ + if(HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT)) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + /* Abort the UART DMA Tx channel : use blocking DMA Abort API (no callback) */ + if(huart->hdmatx != NULL) + { + /* Set the UART DMA Abort callback : + will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */ + huart->hdmatx->XferAbortCallback = UART_DMATxOnlyAbortCallback; + + /* Abort DMA TX */ + if(HAL_DMA_Abort_IT(huart->hdmatx) != HAL_OK) + { + /* Call Directly huart->hdmatx->XferAbortCallback function in case of error */ + huart->hdmatx->XferAbortCallback(huart->hdmatx); + } + } + else + { + /* Reset Tx transfer counter */ + huart->TxXferCount = 0x00U; + + /* Restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ + HAL_UART_AbortTransmitCpltCallback(huart); + } + } + else + { + /* Reset Tx transfer counter */ + huart->TxXferCount = 0x00U; + + /* Restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ + HAL_UART_AbortTransmitCpltCallback(huart); + } + + return HAL_OK; +} + +/** + * @brief Abort ongoing Receive transfer (Interrupt mode). + * @param huart UART handle. + * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable PPP Interrupts + * - Disable the DMA transfer in the peripheral register (if enabled) + * - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode) + * - Set handle State to READY + * - At abort completion, call user abort complete callback + * @note This procedure is executed in Interrupt mode, meaning that abort procedure could be + * considered as completed only when user abort complete callback is executed (not when exiting function). + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_UART_AbortReceive_IT(UART_HandleTypeDef *huart) +{ + /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Disable the UART DMA Rx request if enabled */ + if(HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the UART DMA Rx channel : use blocking DMA Abort API (no callback) */ + if(huart->hdmarx != NULL) + { + /* Set the UART DMA Abort callback : + will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */ + huart->hdmarx->XferAbortCallback = UART_DMARxOnlyAbortCallback; + + /* Abort DMA RX */ + if(HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK) + { + /* Call Directly huart->hdmarx->XferAbortCallback function in case of error */ + huart->hdmarx->XferAbortCallback(huart->hdmarx); + } + } + else + { + /* Reset Rx transfer counter */ + huart->RxXferCount = 0x00U; + + /* Restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ + HAL_UART_AbortReceiveCpltCallback(huart); + } + } + else + { + /* Reset Rx transfer counter */ + huart->RxXferCount = 0x00U; + + /* Restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ + HAL_UART_AbortReceiveCpltCallback(huart); + } + + return HAL_OK; +} + +/** + * @brief This function handles UART interrupt request. + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval None + */ +void HAL_UART_IRQHandler(UART_HandleTypeDef *huart) +{ + uint32_t isrflags = READ_REG(huart->Instance->SR); + uint32_t cr1its = READ_REG(huart->Instance->CR1); + uint32_t cr3its = READ_REG(huart->Instance->CR3); + uint32_t errorflags = 0x00U; + uint32_t dmarequest = 0x00U; + + /* If no error occurs */ + errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE)); + if(errorflags == RESET) + { + /* UART in mode Receiver -------------------------------------------------*/ + if(((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET)) + { + UART_Receive_IT(huart); + return; + } + } + + /* If some errors occur */ + if((errorflags != RESET) && (((cr3its & USART_CR3_EIE) != RESET) || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET))) + { + /* UART parity error interrupt occurred ----------------------------------*/ + if(((isrflags & USART_SR_PE) != RESET) && ((cr1its & USART_CR1_PEIE) != RESET)) + { + huart->ErrorCode |= HAL_UART_ERROR_PE; + } + + /* UART noise error interrupt occurred -----------------------------------*/ + if(((isrflags & USART_SR_NE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET)) + { + huart->ErrorCode |= HAL_UART_ERROR_NE; + } + + /* UART frame error interrupt occurred -----------------------------------*/ + if(((isrflags & USART_SR_FE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET)) + { + huart->ErrorCode |= HAL_UART_ERROR_FE; + } + + /* UART Over-Run interrupt occurred --------------------------------------*/ + if(((isrflags & USART_SR_ORE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET)) + { + huart->ErrorCode |= HAL_UART_ERROR_ORE; + } + + /* Call UART Error Call back function if need be --------------------------*/ + if(huart->ErrorCode != HAL_UART_ERROR_NONE) + { + /* UART in mode Receiver -----------------------------------------------*/ + if(((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET)) + { + UART_Receive_IT(huart); + } + + /* If Overrun error occurs, or if any error occurs in DMA mode reception, + consider error as blocking */ + dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR); + if(((huart->ErrorCode & HAL_UART_ERROR_ORE) != RESET) || dmarequest) + { + /* Blocking error : transfer is aborted + Set the UART state ready to be able to start again the process, + Disable Rx Interrupts, and disable Rx DMA request, if ongoing */ + UART_EndRxTransfer(huart); + + /* Disable the UART DMA Rx request if enabled */ + if(HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the UART DMA Rx channel */ + if(huart->hdmarx != NULL) + { + /* Set the UART DMA Abort callback : + will lead to call HAL_UART_ErrorCallback() at end of DMA abort procedure */ + huart->hdmarx->XferAbortCallback = UART_DMAAbortOnError; + if(HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK) + { + /* Call Directly XferAbortCallback function in case of error */ + huart->hdmarx->XferAbortCallback(huart->hdmarx); + } + } + else + { + /* Call user error callback */ + HAL_UART_ErrorCallback(huart); + } + } + else + { + /* Call user error callback */ + HAL_UART_ErrorCallback(huart); + } + } + else + { + /* Non Blocking error : transfer could go on. + Error is notified to user through user error callback */ + HAL_UART_ErrorCallback(huart); + huart->ErrorCode = HAL_UART_ERROR_NONE; + } + } + return; + } /* End if some error occurs */ + + /* UART in mode Transmitter ------------------------------------------------*/ + if(((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET)) + { + UART_Transmit_IT(huart); + return; + } + + /* UART in mode Transmitter end --------------------------------------------*/ + if(((isrflags & USART_SR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET)) + { + UART_EndTransmit_IT(huart); + return; + } +} + +/** + * @brief Tx Transfer completed callbacks. + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval None + */ + __weak void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + /* NOTE: This function Should not be modified, when the callback is needed, + the HAL_UART_TxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Tx Half Transfer completed callbacks. + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval None + */ + __weak void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + /* NOTE: This function Should not be modified, when the callback is needed, + the HAL_UART_TxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Rx Transfer completed callbacks. + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval None + */ +__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + /* NOTE: This function Should not be modified, when the callback is needed, + the HAL_UART_TxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Rx Half Transfer completed callbacks. + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval None + */ +__weak void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + /* NOTE: This function Should not be modified, when the callback is needed, + the HAL_UART_TxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief UART error callbacks. + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval None + */ + __weak void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + /* NOTE: This function Should not be modified, when the callback is needed, + the HAL_UART_ErrorCallback could be implemented in the user file + */ +} + +/** + * @brief UART Abort Complete callback. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UART_AbortCpltCallback (UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UART_AbortCpltCallback can be implemented in the user file. + */ +} +/** + * @brief UART Abort Complete callback. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UART_AbortTransmitCpltCallback (UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UART_AbortTransmitCpltCallback can be implemented in the user file. + */ +} + +/** + * @brief UART Abort Receive Complete callback. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UART_AbortReceiveCpltCallback (UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UART_AbortReceiveCpltCallback can be implemented in the user file. + */ +} + +/** + * @} + */ + +/** @defgroup UART_Exported_Functions_Group3 Peripheral Control functions + * @brief UART control functions + * +@verbatim + ============================================================================== + ##### Peripheral Control functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to control the UART: + (+) HAL_LIN_SendBreak() API can be helpful to transmit the break character. + (+) HAL_MultiProcessor_EnterMuteMode() API can be helpful to enter the UART in mute mode. + (+) HAL_MultiProcessor_ExitMuteMode() API can be helpful to exit the UART mute mode by software. + +@endverbatim + * @{ + */ + +/** + * @brief Transmits break characters. + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LIN_SendBreak(UART_HandleTypeDef *huart) +{ + /* Check the parameters */ + assert_param(IS_UART_INSTANCE(huart->Instance)); + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Send break characters */ + SET_BIT(huart->Instance->CR1, USART_CR1_SBK); + + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Enters the UART in mute mode. + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MultiProcessor_EnterMuteMode(UART_HandleTypeDef *huart) +{ + /* Check the parameters */ + assert_param(IS_UART_INSTANCE(huart->Instance)); + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Enable the USART mute mode by setting the RWU bit in the CR1 register */ + SET_BIT(huart->Instance->CR1, USART_CR1_RWU); + + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Exits the UART mute mode: wake up software. + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MultiProcessor_ExitMuteMode(UART_HandleTypeDef *huart) +{ + /* Check the parameters */ + assert_param(IS_UART_INSTANCE(huart->Instance)); + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Disable the USART mute mode by clearing the RWU bit in the CR1 register */ + CLEAR_BIT(huart->Instance->CR1, USART_CR1_RWU); + + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Enables the UART transmitter and disables the UART receiver. + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HalfDuplex_EnableTransmitter(UART_HandleTypeDef *huart) +{ + uint32_t tmpreg = 0x00U; + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /*-------------------------- USART CR1 Configuration -----------------------*/ + tmpreg = huart->Instance->CR1; + + /* Clear TE and RE bits */ + tmpreg &= (uint32_t)~((uint32_t)(USART_CR1_TE | USART_CR1_RE)); + + /* Enable the USART's transmit interface by setting the TE bit in the USART CR1 register */ + tmpreg |= (uint32_t)USART_CR1_TE; + + /* Write to USART CR1 */ + WRITE_REG(huart->Instance->CR1, (uint32_t)tmpreg); + + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Enables the UART receiver and disables the UART transmitter. + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HalfDuplex_EnableReceiver(UART_HandleTypeDef *huart) +{ + uint32_t tmpreg = 0x00U; + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /*-------------------------- USART CR1 Configuration -----------------------*/ + tmpreg = huart->Instance->CR1; + + /* Clear TE and RE bits */ + tmpreg &= (uint32_t)~((uint32_t)(USART_CR1_TE | USART_CR1_RE)); + + /* Enable the USART's receive interface by setting the RE bit in the USART CR1 register */ + tmpreg |= (uint32_t)USART_CR1_RE; + + /* Write to USART CR1 */ + WRITE_REG(huart->Instance->CR1, (uint32_t)tmpreg); + + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup UART_Exported_Functions_Group4 Peripheral State and Errors functions + * @brief UART State and Errors functions + * +@verbatim + ============================================================================== + ##### Peripheral State and Errors functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to return the State of + UART communication process, return Peripheral Errors occurred during communication + process + (+) HAL_UART_GetState() API can be helpful to check in run-time the state of the UART peripheral. + (+) HAL_UART_GetError() check in run-time errors that could be occurred during communication. + +@endverbatim + * @{ + */ + +/** + * @brief Returns the UART state. + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval HAL state + */ +HAL_UART_StateTypeDef HAL_UART_GetState(UART_HandleTypeDef *huart) +{ + uint32_t temp1= 0x00U, temp2 = 0x00U; + temp1 = huart->gState; + temp2 = huart->RxState; + + return (HAL_UART_StateTypeDef)(temp1 | temp2); +} + +/** + * @brief Return the UART error code + * @param huart : pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART. + * @retval UART Error Code + */ +uint32_t HAL_UART_GetError(UART_HandleTypeDef *huart) +{ + return huart->ErrorCode; +} + +/** + * @} + */ + +/** + * @brief DMA UART transmit process complete callback. + * @param hdma: DMA handle + * @retval None + */ +static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = ( UART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + /* DMA Normal mode*/ + if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0U) + { + huart->TxXferCount = 0U; + + /* Disable the DMA transfer for transmit request by setting the DMAT bit + in the UART CR3 register */ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + /* Enable the UART Transmit Complete Interrupt */ + SET_BIT(huart->Instance->CR1, USART_CR1_TCIE); + + } + /* DMA Circular mode */ + else + { + HAL_UART_TxCpltCallback(huart); + } +} + +/** + * @brief DMA UART transmit process half complete callback + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA module. + * @retval None + */ +static void UART_DMATxHalfCplt(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = (UART_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent; + + HAL_UART_TxHalfCpltCallback(huart); +} + +/** + * @brief DMA UART receive process complete callback. + * @param hdma: DMA handle + * @retval None + */ +static void UART_DMAReceiveCplt(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = ( UART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + /* DMA Normal mode*/ + if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0U) + { + huart->RxXferCount = 0U; + + /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(huart->Instance->CR1, USART_CR1_PEIE); + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Disable the DMA transfer for the receiver request by setting the DMAR bit + in the UART CR3 register */ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* At end of Rx process, restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + } + HAL_UART_RxCpltCallback(huart); +} + +/** + * @brief DMA UART receive process half complete callback + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA module. + * @retval None + */ +static void UART_DMARxHalfCplt(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = (UART_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent; + + HAL_UART_RxHalfCpltCallback(huart); +} + +/** + * @brief DMA UART communication error callback. + * @param hdma: DMA handle + * @retval None + */ +static void UART_DMAError(DMA_HandleTypeDef *hdma) +{ + uint32_t dmarequest = 0x00U; + UART_HandleTypeDef* huart = ( UART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + + /* Stop UART DMA Tx request if ongoing */ + dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT); + if((huart->gState == HAL_UART_STATE_BUSY_TX) && dmarequest) + { + huart->TxXferCount = 0U; + UART_EndTxTransfer(huart); + } + + /* Stop UART DMA Rx request if ongoing */ + dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR); + if((huart->RxState == HAL_UART_STATE_BUSY_RX) && dmarequest) + { + huart->RxXferCount = 0U; + UART_EndRxTransfer(huart); + } + + huart->ErrorCode |= HAL_UART_ERROR_DMA; + HAL_UART_ErrorCallback(huart); +} + +/** + * @brief This function handles UART Communication Timeout. + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @param Flag: specifies the UART flag to check. + * @param Status: The new Flag status (SET or RESET). + * @param Tickstart Tick start value + * @param Timeout: Timeout duration + * @retval HAL status + */ +static HAL_StatusTypeDef UART_WaitOnFlagUntilTimeout(UART_HandleTypeDef *huart, uint32_t Flag, FlagStatus Status, uint32_t Tickstart, uint32_t Timeout) +{ + /* Wait until flag is set */ + while((__HAL_UART_GET_FLAG(huart, Flag) ? SET : RESET) == Status) + { + /* Check for the Timeout */ + if(Timeout != HAL_MAX_DELAY) + { + if((Timeout == 0U)||((HAL_GetTick() - Tickstart ) > Timeout)) + { + /* Disable TXE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts for the interrupt process */ + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE)); + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + huart->gState = HAL_UART_STATE_READY; + huart->RxState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_TIMEOUT; + } + } + } + + return HAL_OK; +} + +/** + * @brief End ongoing Tx transfer on UART peripheral (following error detection or Transmit completion). + * @param huart: UART handle. + * @retval None + */ +static void UART_EndTxTransfer(UART_HandleTypeDef *huart) +{ + /* Disable TXEIE and TCIE interrupts */ + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE)); + + /* At end of Tx process, restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; +} + +/** + * @brief End ongoing Rx transfer on UART peripheral (following error detection or Reception completion). + * @param huart: UART handle. + * @retval None + */ +static void UART_EndRxTransfer(UART_HandleTypeDef *huart) +{ + /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* At end of Rx process, restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; +} + +/** + * @brief DMA UART communication abort callback, when initiated by HAL services on Error + * (To be called at end of DMA Abort procedure following error occurrence). + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMAAbortOnError(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = ( UART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + huart->RxXferCount = 0U; + huart->TxXferCount = 0U; + + HAL_UART_ErrorCallback(huart); +} + +/** + * @brief DMA UART Tx communication abort callback, when initiated by user + * (To be called at end of DMA Tx Abort procedure following user abort request). + * @note When this callback is executed, User Abort complete call back is called only if no + * Abort still ongoing for Rx DMA Handle. + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMATxAbortCallback(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = ( UART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + + huart->hdmatx->XferAbortCallback = NULL; + + /* Check if an Abort process is still ongoing */ + if(huart->hdmarx != NULL) + { + if(huart->hdmarx->XferAbortCallback != NULL) + { + return; + } + } + + /* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */ + huart->TxXferCount = 0x00U; + huart->RxXferCount = 0x00U; + + /* Reset ErrorCode */ + huart->ErrorCode = HAL_UART_ERROR_NONE; + + /* Restore huart->gState and huart->RxState to Ready */ + huart->gState = HAL_UART_STATE_READY; + huart->RxState = HAL_UART_STATE_READY; + + /* Call user Abort complete callback */ + HAL_UART_AbortCpltCallback(huart); +} + +/** + * @brief DMA UART Rx communication abort callback, when initiated by user + * (To be called at end of DMA Rx Abort procedure following user abort request). + * @note When this callback is executed, User Abort complete call back is called only if no + * Abort still ongoing for Tx DMA Handle. + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMARxAbortCallback(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = ( UART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + + huart->hdmarx->XferAbortCallback = NULL; + + /* Check if an Abort process is still ongoing */ + if(huart->hdmatx != NULL) + { + if(huart->hdmatx->XferAbortCallback != NULL) + { + return; + } + } + + /* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */ + huart->TxXferCount = 0x00U; + huart->RxXferCount = 0x00U; + + /* Reset ErrorCode */ + huart->ErrorCode = HAL_UART_ERROR_NONE; + + /* Restore huart->gState and huart->RxState to Ready */ + huart->gState = HAL_UART_STATE_READY; + huart->RxState = HAL_UART_STATE_READY; + + /* Call user Abort complete callback */ + HAL_UART_AbortCpltCallback(huart); +} + +/** + * @brief DMA UART Tx communication abort callback, when initiated by user by a call to + * HAL_UART_AbortTransmit_IT API (Abort only Tx transfer) + * (This callback is executed at end of DMA Tx Abort procedure following user abort request, + * and leads to user Tx Abort Complete callback execution). + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = ( UART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + + huart->TxXferCount = 0x00U; + + /* Restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; + + /* Call user Abort complete callback */ + HAL_UART_AbortTransmitCpltCallback(huart); +} + +/** + * @brief DMA UART Rx communication abort callback, when initiated by user by a call to + * HAL_UART_AbortReceive_IT API (Abort only Rx transfer) + * (This callback is executed at end of DMA Rx Abort procedure following user abort request, + * and leads to user Rx Abort Complete callback execution). + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = ( UART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + + huart->RxXferCount = 0x00U; + + /* Restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + /* Call user Abort complete callback */ + HAL_UART_AbortReceiveCpltCallback(huart); +} + +/** + * @brief Sends an amount of data in non blocking mode. + * @param huart: Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval HAL status + */ +static HAL_StatusTypeDef UART_Transmit_IT(UART_HandleTypeDef *huart) +{ + uint16_t* tmp; + + /* Check that a Tx process is ongoing */ + if(huart->gState == HAL_UART_STATE_BUSY_TX) + { + if(huart->Init.WordLength == UART_WORDLENGTH_9B) + { + tmp = (uint16_t*) huart->pTxBuffPtr; + huart->Instance->DR = (uint16_t)(*tmp & (uint16_t)0x01FF); + if(huart->Init.Parity == UART_PARITY_NONE) + { + huart->pTxBuffPtr += 2U; + } + else + { + huart->pTxBuffPtr += 1U; + } + } + else + { + huart->Instance->DR = (uint8_t)(*huart->pTxBuffPtr++ & (uint8_t)0x00FF); + } + + if(--huart->TxXferCount == 0U) + { + /* Disable the UART Transmit Complete Interrupt */ + CLEAR_BIT(huart->Instance->CR1, USART_CR1_TXEIE); + + /* Enable the UART Transmit Complete Interrupt */ + SET_BIT(huart->Instance->CR1, USART_CR1_TCIE); + } + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Wraps up transmission in non blocking mode. + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval HAL status + */ +static HAL_StatusTypeDef UART_EndTransmit_IT(UART_HandleTypeDef *huart) +{ + /* Disable the UART Transmit Complete Interrupt */ + CLEAR_BIT(huart->Instance->CR1, USART_CR1_TCIE); + + /* Tx process is ended, restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; + + HAL_UART_TxCpltCallback(huart); + + return HAL_OK; +} + +/** + * @brief Receives an amount of data in non blocking mode + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval HAL status + */ +static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart) +{ + uint16_t* tmp; + + /* Check that a Rx process is ongoing */ + if(huart->RxState == HAL_UART_STATE_BUSY_RX) + { + if(huart->Init.WordLength == UART_WORDLENGTH_9B) + { + tmp = (uint16_t*) huart->pRxBuffPtr; + if(huart->Init.Parity == UART_PARITY_NONE) + { + *tmp = (uint16_t)(huart->Instance->DR & (uint16_t)0x01FF); + huart->pRxBuffPtr += 2U; + } + else + { + *tmp = (uint16_t)(huart->Instance->DR & (uint16_t)0x00FF); + huart->pRxBuffPtr += 1U; + } + } + else + { + if(huart->Init.Parity == UART_PARITY_NONE) + { + *huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF); + } + else + { + *huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x007F); + } + } + + if(--huart->RxXferCount == 0U) + { + /* Disable the UART Parity Error Interrupt and RXNE interrupt*/ + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); + + /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Rx process is completed, restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + HAL_UART_RxCpltCallback(huart); + + return HAL_OK; + } + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Configures the UART peripheral. + * @param huart: pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval None + */ +static void UART_SetConfig(UART_HandleTypeDef *huart) +{ + uint32_t tmpreg = 0x00U; + + /* Check the parameters */ + assert_param(IS_UART_BAUDRATE(huart->Init.BaudRate)); + assert_param(IS_UART_STOPBITS(huart->Init.StopBits)); + assert_param(IS_UART_PARITY(huart->Init.Parity)); + assert_param(IS_UART_MODE(huart->Init.Mode)); + + /*-------------------------- USART CR2 Configuration -----------------------*/ + tmpreg = huart->Instance->CR2; + + /* Clear STOP[13:12] bits */ + tmpreg &= (uint32_t)~((uint32_t)USART_CR2_STOP); + + /* Configure the UART Stop Bits: Set STOP[13:12] bits according to huart->Init.StopBits value */ + tmpreg |= (uint32_t)huart->Init.StopBits; + + /* Write to USART CR2 */ + WRITE_REG(huart->Instance->CR2, (uint32_t)tmpreg); + + /*-------------------------- USART CR1 Configuration -----------------------*/ + tmpreg = huart->Instance->CR1; + + /* Clear M, PCE, PS, TE and RE bits */ + tmpreg &= (uint32_t)~((uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_TE | \ + USART_CR1_RE | USART_CR1_OVER8)); + + /* Configure the UART Word Length, Parity and mode: + Set the M bits according to huart->Init.WordLength value + Set PCE and PS bits according to huart->Init.Parity value + Set TE and RE bits according to huart->Init.Mode value + Set OVER8 bit according to huart->Init.OverSampling value */ + tmpreg |= (uint32_t)huart->Init.WordLength | huart->Init.Parity | huart->Init.Mode | huart->Init.OverSampling; + + /* Write to USART CR1 */ + WRITE_REG(huart->Instance->CR1, (uint32_t)tmpreg); + + /*-------------------------- USART CR3 Configuration -----------------------*/ + tmpreg = huart->Instance->CR3; + + /* Clear CTSE and RTSE bits */ + tmpreg &= (uint32_t)~((uint32_t)(USART_CR3_RTSE | USART_CR3_CTSE)); + + /* Configure the UART HFC: Set CTSE and RTSE bits according to huart->Init.HwFlowCtl value */ + tmpreg |= huart->Init.HwFlowCtl; + + /* Write to USART CR3 */ + WRITE_REG(huart->Instance->CR3, (uint32_t)tmpreg); + + /* Check the Over Sampling */ + if(huart->Init.OverSampling == UART_OVERSAMPLING_8) + { + /*-------------------------- USART BRR Configuration ---------------------*/ +#if defined(USART6) + if((huart->Instance == USART1) || (huart->Instance == USART6)) + { + huart->Instance->BRR = UART_BRR_SAMPLING8(HAL_RCC_GetPCLK2Freq(), huart->Init.BaudRate); + } +#else + if(huart->Instance == USART1) + { + huart->Instance->BRR = UART_BRR_SAMPLING8(HAL_RCC_GetPCLK2Freq(), huart->Init.BaudRate); + } +#endif /* USART6 */ + else + { + huart->Instance->BRR = UART_BRR_SAMPLING8(HAL_RCC_GetPCLK1Freq(), huart->Init.BaudRate); + } + } + else + { + /*-------------------------- USART BRR Configuration ---------------------*/ +#if defined(USART6) + if((huart->Instance == USART1) || (huart->Instance == USART6)) + { + huart->Instance->BRR = UART_BRR_SAMPLING16(HAL_RCC_GetPCLK2Freq(), huart->Init.BaudRate); + } +#else + if(huart->Instance == USART1) + { + huart->Instance->BRR = UART_BRR_SAMPLING16(HAL_RCC_GetPCLK2Freq(), huart->Init.BaudRate); + } +#endif /* USART6 */ + else + { + huart->Instance->BRR = UART_BRR_SAMPLING16(HAL_RCC_GetPCLK1Freq(), huart->Init.BaudRate); + } + } +} + +/** + * @} + */ + +#endif /* HAL_UART_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Firmware/Inc/dma.h b/Firmware/Inc/dma.h new file mode 100644 index 000000000..1d73731f5 --- /dev/null +++ b/Firmware/Inc/dma.h @@ -0,0 +1,88 @@ +/** + ****************************************************************************** + * File Name : dma.h + * Description : This file contains all the function prototypes for + * the dma.c file + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2017 STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted, provided that the following conditions are met: + * + * 1. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __dma_H +#define __dma_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" +#include "main.h" + +/* DMA memory to memory transfer handles -------------------------------------*/ +extern void _Error_Handler(char*, int); + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +void MX_DMA_Init(void); + +/* USER CODE BEGIN Prototypes */ + +/* USER CODE END Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif /* __dma_H */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Firmware/Inc/freertos_vars.h b/Firmware/Inc/freertos_vars.h index a0bc6d2b9..fd0bf85da 100644 --- a/Firmware/Inc/freertos_vars.h +++ b/Firmware/Inc/freertos_vars.h @@ -8,6 +8,6 @@ osSemaphoreId sem_usb_irq; // List of threads osThreadId thread_motor_0; osThreadId thread_motor_1; -osThreadId thread_usb_cmd; +osThreadId thread_cmd_parse; #endif /* __FREERTOS_H */ \ No newline at end of file diff --git a/Firmware/Inc/gpio.h b/Firmware/Inc/gpio.h index c83666043..280128eb9 100644 --- a/Firmware/Inc/gpio.h +++ b/Firmware/Inc/gpio.h @@ -70,6 +70,9 @@ void MX_GPIO_Init(void); /* USER CODE BEGIN Prototypes */ +void SetGPIO12toUART(); +void SetGPIO12toStepDir(); + /* USER CODE END Prototypes */ #ifdef __cplusplus diff --git a/Firmware/Inc/main.h b/Firmware/Inc/main.h index 1e7914326..911d81fe6 100644 --- a/Firmware/Inc/main.h +++ b/Firmware/Inc/main.h @@ -85,7 +85,6 @@ #define M1_IB_GPIO_Port GPIOC #define GPIO_1_Pin GPIO_PIN_0 #define GPIO_1_GPIO_Port GPIOA -#define GPIO_1_EXTI_IRQn EXTI0_IRQn #define GPIO_2_Pin GPIO_PIN_1 #define GPIO_2_GPIO_Port GPIOA #define GPIO_3_Pin GPIO_PIN_2 diff --git a/Firmware/Inc/stm32f4xx_hal_conf.h b/Firmware/Inc/stm32f4xx_hal_conf.h index 44ac9b1e5..ded408973 100644 --- a/Firmware/Inc/stm32f4xx_hal_conf.h +++ b/Firmware/Inc/stm32f4xx_hal_conf.h @@ -76,7 +76,7 @@ /* #define HAL_MMC_MODULE_ENABLED */ #define HAL_SPI_MODULE_ENABLED #define HAL_TIM_MODULE_ENABLED -/* #define HAL_UART_MODULE_ENABLED */ +#define HAL_UART_MODULE_ENABLED /* #define HAL_USART_MODULE_ENABLED */ /* #define HAL_IRDA_MODULE_ENABLED */ /* #define HAL_SMARTCARD_MODULE_ENABLED */ @@ -157,7 +157,7 @@ * @brief This is the HAL system configuration section */ #define VDD_VALUE ((uint32_t)3300U) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)15U) /*!< tick interrupt priority */ +#define TICK_INT_PRIORITY ((uint32_t)0U) /*!< tick interrupt priority */ #define USE_RTOS 0U #define PREFETCH_ENABLE 1U #define INSTRUCTION_CACHE_ENABLE 1U diff --git a/Firmware/Inc/stm32f4xx_it.h b/Firmware/Inc/stm32f4xx_it.h index b82d5c2ba..fd9b9628b 100644 --- a/Firmware/Inc/stm32f4xx_it.h +++ b/Firmware/Inc/stm32f4xx_it.h @@ -40,6 +40,8 @@ #endif /* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" +#include "main.h" /* Exported types ------------------------------------------------------------*/ /* Exported constants --------------------------------------------------------*/ /* Exported macro ------------------------------------------------------------*/ @@ -52,9 +54,11 @@ void BusFault_Handler(void); void UsageFault_Handler(void); void DebugMon_Handler(void); void SysTick_Handler(void); -void EXTI0_IRQHandler(void); -void EXTI2_IRQHandler(void); +void DMA1_Stream2_IRQHandler(void); +void DMA1_Stream4_IRQHandler(void); void ADC_IRQHandler(void); +void TIM8_TRG_COM_TIM14_IRQHandler(void); +void UART4_IRQHandler(void); void OTG_FS_IRQHandler(void); #ifdef __cplusplus diff --git a/Firmware/Inc/usart.h b/Firmware/Inc/usart.h new file mode 100644 index 000000000..808284cd3 --- /dev/null +++ b/Firmware/Inc/usart.h @@ -0,0 +1,91 @@ +/** + ****************************************************************************** + * File Name : USART.h + * Description : This file provides code for the configuration + * of the USART instances. + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2017 STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted, provided that the following conditions are met: + * + * 1. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __usart_H +#define __usart_H +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" +#include "main.h" + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +extern UART_HandleTypeDef huart4; + +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +extern void _Error_Handler(char *, int); + +void MX_UART4_Init(void); + +/* USER CODE BEGIN Prototypes */ + +/* USER CODE END Prototypes */ + +#ifdef __cplusplus +} +#endif +#endif /*__ usart_H */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Firmware/Makefile b/Firmware/Makefile index 081f17b8d..433895603 100644 --- a/Firmware/Makefile +++ b/Firmware/Makefile @@ -13,9 +13,7 @@ TARGET = ODriveFirmware # debug build? DEBUG = 1 # optimization -# OPT = -O3 -ffast-math -flto -# OPT = -O3 -ffast-math -OPT = -O0 -ffast-math -u _printf_float -u _scanf_float +OPT = -Og -ffast-math ####################################### # pathes @@ -42,14 +40,17 @@ C_SOURCES = \ 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/stm32f4xx_hal_msp.c \ Src/can.c \ + Src/usart.c \ + Src/dma.c \ Src/usbd_conf.c \ Src/usbd_desc.c \ Src/usb_device.c \ @@ -74,11 +75,13 @@ C_SOURCES = \ 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/low_level.c + MotorControl/commands.c \ + MotorControl/low_level.c ASM_SOURCES = \ startup/startup_stm32f405xx.s @@ -134,7 +137,7 @@ 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 $(OPT) -T$(LDSCRIPT) $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections +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 # default action: build all all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin @@ -152,7 +155,7 @@ vpath %.cpp $(sort $(dir $(CPP_SOURCES))) OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o))) vpath %.s $(sort $(dir $(ASM_SOURCES))) -$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR) +$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR) @$(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@ $(BUILD_DIR)/%.o: %.s Makefile | $(BUILD_DIR) diff --git a/Firmware/MotorControl/commands.c b/Firmware/MotorControl/commands.c new file mode 100644 index 000000000..0c01ccd9b --- /dev/null +++ b/Firmware/MotorControl/commands.c @@ -0,0 +1,355 @@ +/* Includes ------------------------------------------------------------------*/ +#include +#include +#include +#include +#include + +extern PCD_HandleTypeDef hpcd_USB_OTG_FS; + +/* Private macros ------------------------------------------------------------*/ +/* Private typedef -----------------------------------------------------------*/ +/* Global constant data ------------------------------------------------------*/ +/* Global variables ----------------------------------------------------------*/ +// This automatically updates to the interface that most +// recently recieved a command. In the future we may want to separate +// debug printf and the main serial comms. +SerialPrintf_t serial_printf_select = SERIAL_PRINTF_IS_NONE; + +/* Private constant data -----------------------------------------------------*/ +// TODO: make command to switch gpio_mode during run-time +static const GpioMode_t gpio_mode = GPIO_MODE_UART; //GPIO 1,2 is UART Tx,Rx +// static const GpioMode_t gpio_mode = GPIO_MODE_STEP_DIR; //GPIO 1,2 is M0 Step,Dir + +// variables exposed to usb/serial interface via set/get/monitor +// Note: this will be depricated soon +static float* const exposed_floats[] = { + &vbus_voltage, // ro + NULL, //&elec_rad_per_enc, // ro + &motors[0].pos_setpoint, // rw + &motors[0].pos_gain, // rw + &motors[0].vel_setpoint, // rw + &motors[0].vel_gain, // rw + &motors[0].vel_integrator_gain, // rw + &motors[0].vel_integrator_current, // rw + &motors[0].vel_limit, // rw + &motors[0].current_setpoint, // rw + &motors[0].calibration_current, // rw + &motors[0].phase_inductance, // ro + &motors[0].phase_resistance, // ro + &motors[0].current_meas.phB, // ro + &motors[0].current_meas.phC, // ro + &motors[0].DC_calib.phB, // rw + &motors[0].DC_calib.phC, // rw + &motors[0].shunt_conductance, // rw + &motors[0].phase_current_rev_gain, // rw + &motors[0].current_control.current_lim, // rw + &motors[0].current_control.p_gain, // rw + &motors[0].current_control.i_gain, // rw + &motors[0].current_control.v_current_control_integral_d, // rw + &motors[0].current_control.v_current_control_integral_q, // rw + &motors[0].current_control.Ibus, // ro + &motors[0].encoder.phase, // ro + &motors[0].encoder.pll_pos, // rw + &motors[0].encoder.pll_vel, // rw + &motors[0].encoder.pll_kp, // rw + &motors[0].encoder.pll_ki, // rw + &motors[1].pos_setpoint, // rw + &motors[1].pos_gain, // rw + &motors[1].vel_setpoint, // rw + &motors[1].vel_gain, // rw + &motors[1].vel_integrator_gain, // rw + &motors[1].vel_integrator_current, // rw + &motors[1].vel_limit, // rw + &motors[1].current_setpoint, // rw + &motors[1].calibration_current, // rw + &motors[1].phase_inductance, // ro + &motors[1].phase_resistance, // ro + &motors[1].current_meas.phB, // ro + &motors[1].current_meas.phC, // ro + &motors[1].DC_calib.phB, // rw + &motors[1].DC_calib.phC, // rw + &motors[1].shunt_conductance, // rw + &motors[1].phase_current_rev_gain, // rw + &motors[1].current_control.current_lim, // rw + &motors[1].current_control.p_gain, // rw + &motors[1].current_control.i_gain, // rw + &motors[1].current_control.v_current_control_integral_d, // rw + &motors[1].current_control.v_current_control_integral_q, // rw + &motors[1].current_control.Ibus, // ro + &motors[1].encoder.phase, // ro + &motors[1].encoder.pll_pos, // rw + &motors[1].encoder.pll_vel, // rw + &motors[1].encoder.pll_kp, // rw + &motors[1].encoder.pll_ki, // rw +}; + +static int* const exposed_ints[] = { + (int*)&motors[0].control_mode, // rw + &motors[0].encoder.encoder_offset, // rw + &motors[0].encoder.encoder_state, // ro + &motors[0].error, // rw + (int*)&motors[1].control_mode, // rw + &motors[1].encoder.encoder_offset, // rw + &motors[1].encoder.encoder_state, // ro + &motors[1].error, // rw +}; + +static bool* const exposed_bools[] = { + &motors[0].thread_ready, // ro + &motors[0].enable_control, // rw + &motors[0].do_calibration, // rw + &motors[0].calibration_ok, // ro + &motors[1].thread_ready, // ro + &motors[1].enable_control, // rw + &motors[1].do_calibration, // rw + &motors[1].calibration_ok, // ro +}; + +static uint16_t* const exposed_uint16[] = { + &motors[0].control_deadline, // rw + &motors[0].last_cpu_time, // ro + &motors[1].control_deadline, // rw + &motors[1].last_cpu_time, // ro +}; + +/* Private variables ---------------------------------------------------------*/ +monitoring_slot monitoring_slots[20] = {0}; +/* Private function prototypes -----------------------------------------------*/ +static void print_monitoring(int limit); + +/* Function implementations --------------------------------------------------*/ +void init_communication() { + switch (gpio_mode) { + case GPIO_MODE_UART: { + SetGPIO12toUART(); + } break; + case GPIO_MODE_STEP_DIR: { + SetGPIO12toStepDir(); + } + } +} + +void motor_parse_cmd(uint8_t* buffer, int len, SerialPrintf_t response_interface) { + // Set response interface + serial_printf_select = response_interface; + + // TODO very hacky way of terminating sscanf at end of buffer: + // We should do some proper struct packing instead of using sscanf altogether + buffer[len-1] = 0; + + // check incoming packet type + if (buffer[0] == 'p') { + // position control + unsigned motor_number; + float pos_setpoint, vel_feed_forward, current_feed_forward; + int numscan = sscanf((const char*)buffer, "p %u %f %f %f", &motor_number, &pos_setpoint, &vel_feed_forward, ¤t_feed_forward); + if (numscan == 4 && motor_number < num_motors) { + set_pos_setpoint(&motors[motor_number], pos_setpoint, vel_feed_forward, current_feed_forward); + } + } else if (buffer[0] == 'v') { + // velocity control + unsigned motor_number; + float vel_feed_forward, current_feed_forward; + int numscan = sscanf((const char*)buffer, "v %u %f %f", &motor_number, &vel_feed_forward, ¤t_feed_forward); + if (numscan == 3 && motor_number < num_motors) { + set_vel_setpoint(&motors[motor_number], vel_feed_forward, current_feed_forward); + } + } else if (buffer[0] == 'c') { + // current control + unsigned motor_number; + float current_feed_forward; + int numscan = sscanf((const char*)buffer, "c %u %f", &motor_number, ¤t_feed_forward); + if (numscan == 2 && motor_number < num_motors) { + set_current_setpoint(&motors[motor_number], current_feed_forward); + } + } else if (buffer[0] == 'g') { // GET + // g <0:float,1:int,2:bool,3:uint16> index + int type = 0; + int index = 0; + int numscan = sscanf((const char*)buffer, "g %u %u", &type, &index); + if (numscan == 2) { + switch(type){ + case 0: { + printf("%f\n",*exposed_floats[index]); + break; + }; + case 1: { + printf("%d\n",*exposed_ints[index]); + break; + }; + case 2: { + printf("%d\n",*exposed_bools[index]); + break; + }; + case 3: { + printf("%hu\n",*exposed_uint16[index]); + break; + }; + } + } + } else if (buffer[0] == 'h'){ // HALT + for(int i = 0; i < num_motors; i++){ + set_vel_setpoint(&motors[i], 0.0f, 0.0f); + } + } else if (buffer[0] == 's') { // SET + // s <0:float,1:int,2:bool,3:uint16> index value + int type = 0; + int index = 0; + int numscan = sscanf((const char*)buffer, "s %u %u", &type, &index); + if (numscan == 2) { + switch(type) { + case 0: { + sscanf((const char*)buffer, "s %u %u %f", &type, &index, exposed_floats[index]); + break; + }; + case 1: { + sscanf((const char*)buffer, "s %u %u %d", &type, &index, exposed_ints[index]); + break; + }; + case 2: { + int btmp = 0; + sscanf((const char*)buffer, "s %u %u %d", &type, &index, &btmp); + *exposed_bools[index] = btmp ? true : false; + break; + }; + case 3: { + sscanf((const char*)buffer, "s %u %u %hu", &type, &index, exposed_uint16[index]); + break; + }; + } + } + } else if (buffer[0] == 'm') { // Setup Monitor + // m <0:float,1:int,2:bool,3:uint16> index monitoring_slot + int type = 0; + int index = 0; + int slot = 0; + int numscan = sscanf((const char*)buffer, "m %u %u %u", &type, &index, &slot); + if (numscan == 3) { + monitoring_slots[slot].type = type; + monitoring_slots[slot].index = index; + } + } else if (buffer[0] == 'o') { // Output Monitor + int limit = 0; + int numscan = sscanf((const char*)buffer, "o %u", &limit); + if (numscan == 1) { + print_monitoring(limit); + } + } else if (buffer[0] == 't') { // Run Anti-Cogging Calibration + for (int 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; + } + } + } +} + +static void print_monitoring(int limit) { + for (int i=0;iInstance->NDTR; + // Re-run state-machine forever + for (;;) { + //Inialize recieve state machine + bool reset_read_state = false; + bool read_active = false; + uint32_t parse_buffer_idx = 0; + //Run state machine until reset + do { + // Check for UART errors and restart recieve DMA transfer if required + if (huart4.ErrorCode != HAL_UART_ERROR_NONE) { + HAL_UART_AbortReceive(&huart4); + HAL_UART_Receive_DMA(&huart4, dma_circ_buffer, sizeof(dma_circ_buffer)); + break; //reset state machine + } + // Fetch the circular buffer "write pointer", where it would write next + uint32_t rcv_idx = UART_RX_BUFFER_SIZE - huart4.hdmarx->Instance->NDTR; + // During sleeping, we may have fallen several characters behind, so we keep + // going until we are caught up, before we sleep again + while (rcv_idx != last_rcv_idx) { + // Fetch the next char, rotate read ptr + uint8_t c = dma_circ_buffer[last_rcv_idx]; + if (++last_rcv_idx == UART_RX_BUFFER_SIZE) + last_rcv_idx = 0; + // Look for start character + if (c == '$') { + read_active = true; + continue; // do not record start char + } + // Record into parse buffer when actively reading + if (read_active) { + parse_buffer[parse_buffer_idx++] = c; + if (c == '\r' || c == '\n' || c == '!') { + // End of command string: exchange end char with terminating null + parse_buffer[parse_buffer_idx-1] = '\0'; + motor_parse_cmd(parse_buffer, parse_buffer_idx, SERIAL_PRINTF_IS_UART); + // Reset receieve state machine + reset_read_state = true; + break; + } else if (parse_buffer_idx == UART_RX_BUFFER_SIZE - 1) { + // We are not at end of command, and receiving another character after this + // would go into the last slot, which is reserved for terminating null. + // We have effectively overflowed parse buffer: abort. + reset_read_state = true; + break; + } + } + } + // When we reach here, we are out of immediate characters to fetch out of UART buffer + // Now we check if there is any USB processing to do: we wait for up to 1 ms, + // before going back to checking UART again. + int USB_check_timeout = 1; + // Wait for signalling from USB interrupt (OTG_FS_IRQHandler) + osStatus semaphore_status = osSemaphoreWait(sem_usb_irq, USB_check_timeout); + if (semaphore_status == osOK) { + // We have a new incoming USB transmission: handle it + HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS); + // Let the irq (OTG_FS_IRQHandler) fire again. + HAL_NVIC_EnableIRQ(OTG_FS_IRQn); + } + } while (!reset_read_state); + } + + // If we get here, then this task is done + vTaskDelete(osThreadGetId()); +} \ No newline at end of file diff --git a/Firmware/MotorControl/commands.h b/Firmware/MotorControl/commands.h new file mode 100644 index 000000000..1483af9c3 --- /dev/null +++ b/Firmware/MotorControl/commands.h @@ -0,0 +1,30 @@ +#ifndef COMMANDS_H +#define COMMANDS_H + +/* Includes ------------------------------------------------------------------*/ +#include +/* Exported types ------------------------------------------------------------*/ + +typedef enum { + GPIO_MODE_UART, + GPIO_MODE_STEP_DIR, +} GpioMode_t; + +typedef enum { + SERIAL_PRINTF_IS_NONE, + SERIAL_PRINTF_IS_USB, + SERIAL_PRINTF_IS_UART, +} SerialPrintf_t; + +/* Exported constants --------------------------------------------------------*/ +/* Exported variables --------------------------------------------------------*/ +extern SerialPrintf_t serial_printf_select; +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +void init_communication(); +void cmd_parse_thread(void const * argument); +void motor_parse_cmd(uint8_t* buffer, int len, SerialPrintf_t response_interface); + +#endif /* COMMANDS_H */ diff --git a/Firmware/MotorControl/low_level.c b/Firmware/MotorControl/low_level.c index 1d1da1b62..c59042235 100644 --- a/Firmware/MotorControl/low_level.c +++ b/Firmware/MotorControl/low_level.c @@ -2,12 +2,14 @@ // Because of broken cmsis_os.h, we need to include arm_math first, // otherwise chip specific defines are ommited +#include #include // Sets up the correct chip specifc defines required by arm_math #define ARM_MATH_CM4 #include #include +#include #include #include #include @@ -93,6 +95,7 @@ Motor_t motors[] = { .Ibus = 0.0f, .final_v_alpha = 0.0f, .final_v_beta = 0.0f, + .Iq = 0.0f, }, // .rotor_mode = ROTOR_MODE_SENSORLESS, // .rotor_mode = ROTOR_MODE_RUN_ENCODER_TEST_SENSORLESS, @@ -125,6 +128,14 @@ Motor_t motors[] = { }, .timing_log_index = 0, .timing_log = {0}, + .anticogging = { + .index = 0, + .cogging_map = NULL, + .use_anticogging = false, + .calib_anticogging = false, + .calib_pos_threshold = 1.0f, + .calib_vel_threshold = 1.0f, + }, }, { // M1 .control_mode = CTRL_MODE_POSITION_CONTROL, //see: Motor_control_mode_t @@ -176,6 +187,7 @@ Motor_t motors[] = { .Ibus = 0.0f, .final_v_alpha = 0.0f, .final_v_beta = 0.0f, + .Iq = 0.0f, }, .rotor_mode = ROTOR_MODE_ENCODER, .encoder = { @@ -205,7 +217,15 @@ Motor_t motors[] = { .spin_up_target_vel = 400.0f, // [rad/s] }, .timing_log_index = 0, - .timing_log = {0} + .timing_log = {0}, + .anticogging = { + .index = 0, + .cogging_map = NULL, + .use_anticogging = false, + .calib_anticogging = false, + .calib_pos_threshold = 1.0f, + .calib_vel_threshold = 1.0f, + } } }; const int num_motors = sizeof(motors)/sizeof(motors[0]); @@ -219,107 +239,9 @@ static const int current_meas_hz = CURRENT_MEAS_HZ; /* Private variables ---------------------------------------------------------*/ static float brake_resistance = 0.47f; // [ohm] -/* Monitoring */ -monitoring_slot monitoring_slots[20] = {0}; - -/* variables exposed to usb interface via set/get/monitor - * If you change something here, don't forget to regenerate the python interface with generate_api.py - * ro/rw : read only/read write -> ro prevents the code generator from generating setter - * */ - -float* exposed_floats[] = { - &vbus_voltage, // ro - &elec_rad_per_enc, // ro - &motors[0].pos_setpoint, // rw - &motors[0].pos_gain, // rw - &motors[0].vel_setpoint, // rw - &motors[0].vel_gain, // rw - &motors[0].vel_integrator_gain, // rw - &motors[0].vel_integrator_current, // rw - &motors[0].vel_limit, // rw - &motors[0].current_setpoint, // rw - &motors[0].calibration_current, // rw - &motors[0].phase_inductance, // ro - &motors[0].phase_resistance, // ro - &motors[0].current_meas.phB, // ro - &motors[0].current_meas.phC, // ro - &motors[0].DC_calib.phB, // rw - &motors[0].DC_calib.phC, // rw - &motors[0].shunt_conductance, // rw - &motors[0].phase_current_rev_gain, // rw - &motors[0].current_control.current_lim, // rw - &motors[0].current_control.p_gain, // rw - &motors[0].current_control.i_gain, // rw - &motors[0].current_control.v_current_control_integral_d, // rw - &motors[0].current_control.v_current_control_integral_q, // rw - &motors[0].current_control.Ibus, // ro - &motors[0].encoder.phase, // ro - &motors[0].encoder.pll_pos, // rw - &motors[0].encoder.pll_vel, // rw - &motors[0].encoder.pll_kp, // rw - &motors[0].encoder.pll_ki, // rw - &motors[1].pos_setpoint, // rw - &motors[1].pos_gain, // rw - &motors[1].vel_setpoint, // rw - &motors[1].vel_gain, // rw - &motors[1].vel_integrator_gain, // rw - &motors[1].vel_integrator_current, // rw - &motors[1].vel_limit, // rw - &motors[1].current_setpoint, // rw - &motors[1].calibration_current, // rw - &motors[1].phase_inductance, // ro - &motors[1].phase_resistance, // ro - &motors[1].current_meas.phB, // ro - &motors[1].current_meas.phC, // ro - &motors[1].DC_calib.phB, // rw - &motors[1].DC_calib.phC, // rw - &motors[1].shunt_conductance, // rw - &motors[1].phase_current_rev_gain, // rw - &motors[1].current_control.current_lim, // rw - &motors[1].current_control.p_gain, // rw - &motors[1].current_control.i_gain, // rw - &motors[1].current_control.v_current_control_integral_d, // rw - &motors[1].current_control.v_current_control_integral_q, // rw - &motors[1].current_control.Ibus, // ro - &motors[1].encoder.phase, // ro - &motors[1].encoder.pll_pos, // rw - &motors[1].encoder.pll_vel, // rw - &motors[1].encoder.pll_kp, // rw - &motors[1].encoder.pll_ki, // rw -}; - -int* exposed_ints[] = { - (int*)&motors[0].control_mode, // rw - &motors[0].encoder.encoder_offset, // rw - &motors[0].encoder.encoder_state, // ro - &motors[0].error, // rw - (int*)&motors[1].control_mode, // rw - &motors[1].encoder.encoder_offset, // rw - &motors[1].encoder.encoder_state, // ro - &motors[1].error, // rw -}; - -bool* exposed_bools[] = { - &motors[0].thread_ready, // ro - &motors[0].enable_control, // rw - &motors[0].do_calibration, // rw - &motors[0].calibration_ok, // ro - &motors[1].thread_ready, // ro - &motors[1].enable_control, // rw - &motors[1].do_calibration, // rw - &motors[1].calibration_ok, // ro -}; - -uint16_t* exposed_uint16[] = { - &motors[0].control_deadline, // rw - &motors[0].last_cpu_time, // ro - &motors[1].control_deadline, // rw - &motors[1].last_cpu_time, // ro -}; - /* Private function prototypes -----------------------------------------------*/ // Command Handling -static void print_monitoring(int limit); + // Utility static uint16_t check_timing(Motor_t* motor); static void global_fault(int error); @@ -359,27 +281,7 @@ static void control_motor_loop(Motor_t* motor); // TODO move to different file //-------------------------------- -static void print_monitoring(int limit) { - for (int i=0;ipos_setpoint = pos_setpoint; @@ -408,109 +310,6 @@ void set_current_setpoint(Motor_t* motor, float current_setpoint) { #endif } -void motor_parse_cmd(uint8_t* buffer, int len) { - - // TODO very hacky way of terminating sscanf at end of buffer: - // We should do some proper struct packing instead of using sscanf altogether - buffer[len] = 0; - - // check incoming packet type - if (buffer[0] == 'p') { - // position control - unsigned motor_number; - float pos_setpoint, vel_feed_forward, current_feed_forward; - int numscan = sscanf((const char*)buffer, "p %u %f %f %f", &motor_number, &pos_setpoint, &vel_feed_forward, ¤t_feed_forward); - if (numscan == 4 && motor_number < num_motors) { - set_pos_setpoint(&motors[motor_number], pos_setpoint, vel_feed_forward, current_feed_forward); - } - } else if (buffer[0] == 'v') { - // velocity control - unsigned motor_number; - float vel_feed_forward, current_feed_forward; - int numscan = sscanf((const char*)buffer, "v %u %f %f", &motor_number, &vel_feed_forward, ¤t_feed_forward); - if (numscan == 3 && motor_number < num_motors) { - set_vel_setpoint(&motors[motor_number], vel_feed_forward, current_feed_forward); - } - } else if (buffer[0] == 'c') { - // current control - unsigned motor_number; - float current_feed_forward; - int numscan = sscanf((const char*)buffer, "c %u %f", &motor_number, ¤t_feed_forward); - if (numscan == 2 && motor_number < num_motors) { - set_current_setpoint(&motors[motor_number], current_feed_forward); - } - } else if (buffer[0] == 'g') { // GET - // g <0:float,1:int,2:bool,3:uint16> index - int type = 0; - int index = 0; - int numscan = sscanf((const char*)buffer, "g %u %u", &type, &index); - if (numscan == 2) { - switch(type){ - case 0: { - printf("%f\n",*exposed_floats[index]); - break; - }; - case 1: { - printf("%d\n",*exposed_ints[index]); - break; - }; - case 2: { - printf("%d\n",*exposed_bools[index]); - break; - }; - case 3: { - printf("%hu\n",*exposed_uint16[index]); - break; - }; - } - } - } else if (buffer[0] == 's') { // SET - // s <0:float,1:int,2:bool,3:uint16> index value - int type = 0; - int index = 0; - int numscan = sscanf((const char*)buffer, "s %u %u", &type, &index); - if (numscan == 2) { - switch(type) { - case 0: { - sscanf((const char*)buffer, "s %u %u %f", &type, &index, exposed_floats[index]); - break; - }; - case 1: { - sscanf((const char*)buffer, "s %u %u %d", &type, &index, exposed_ints[index]); - break; - }; - case 2: { - int btmp = 0; - sscanf((const char*)buffer, "s %u %u %d", &type, &index, &btmp); - *exposed_bools[index] = btmp ? true : false; - break; - }; - case 3: { - sscanf((const char*)buffer, "s %u %u %hu", &type, &index, exposed_uint16[index]); - break; - }; - } - } - } else if (buffer[0] == 'm') { // Setup Monitor - // m <0:float,1:int,2:bool,3:uint16> index monitoring_slot - int type = 0; - int index = 0; - int slot = 0; - int numscan = sscanf((const char*)buffer, "m %u %u %u", &type, &index, &slot); - if (numscan == 3) { - monitoring_slots[slot].type = type; - monitoring_slots[slot].index = index; - } - } else if (buffer[0] == 'o') { // Output Monitor - int limit = 0; - int numscan = sscanf((const char*)buffer, "o %u", &limit); - if (numscan == 1) { - print_monitoring(limit); - } - } -} - - //-------------------------------- // Utility //-------------------------------- @@ -1038,16 +837,44 @@ static bool motor_calibration(Motor_t* motor){ // sensorless pll same as encoder (for now) motor->sensorless.pll_kp = motor->encoder.pll_kp; motor->sensorless.pll_ki = motor->encoder.pll_ki; - + motor->calibration_ok = true; return true; } +/* + * This anti-cogging implementation iterates through each encoder position, + * waits for zero velocity & position error, + * then samples the current required to maintain that position. + * + * This holding current is added as a feedforward term in the control loop. + */ +bool anti_cogging_calibration(Motor_t* motor) { + if (motor->anticogging.calib_anticogging && motor->anticogging.cogging_map != NULL) { + float pos_err = motor->anticogging.index - motor->encoder.pll_pos; + if (fabsf(pos_err) <= motor->anticogging.calib_pos_threshold && + 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) { + set_pos_setpoint(motor, motor->anticogging.index, 0.0f, 0.0f); + return false; + } else { + motor->anticogging.index = 0; + set_pos_setpoint(motor, 0.0f, 0.0f, 0.0f); // Send the motor home + motor->anticogging.use_anticogging = true; // We're good to go, enable anti-cogging + motor->anticogging.calib_anticogging = false; + return true; + } + } + return false; +} //-------------------------------- // Test functions //-------------------------------- +__attribute__((unused)) static void scan_motor_loop(Motor_t* motor, float omega, float voltage_magnitude) { for (;;) { for (float ph = 0.0f; ph < 2.0f * M_PI; ph += omega * current_meas_period) { @@ -1067,6 +894,7 @@ static void scan_motor_loop(Motor_t* motor, float omega, float voltage_magnitude } //TODO integrate as mode in main control loop +__attribute__((unused)) static void FOC_voltage_loop(Motor_t* motor, float v_d, float v_q) { for (;;) { osSignalWait(M_SIGNAL_PH_CURRENT_MEAS, osWaitForever); @@ -1212,36 +1040,39 @@ static void update_rotor(Motor_t* motor) { } } +static bool using_encoder(Motor_t* motor) { + if (motor->rotor_mode == ROTOR_MODE_ENCODER || + motor->rotor_mode == ROTOR_MODE_RUN_ENCODER_TEST_SENSORLESS) + return true; + else + return false; +} + +static bool using_sensorless(Motor_t* motor) { + if (motor->rotor_mode == ROTOR_MODE_SENSORLESS) + return true; + else + return false; +} + static float get_rotor_phase(Motor_t* motor) { - switch (motor->rotor_mode) { - case ROTOR_MODE_ENCODER: - case ROTOR_MODE_RUN_ENCODER_TEST_SENSORLESS: - return motor->encoder.phase; - break; - case ROTOR_MODE_SENSORLESS: - return motor->sensorless.phase; - break; - default: - //TODO error handling - return 0.0f; - break; - } + if (using_encoder(motor)) + return motor->encoder.phase; + else if (using_sensorless(motor)) + return motor->sensorless.phase; + else + //TODO error handling + return 0.0f; } static float get_pll_vel(Motor_t* motor) { - switch (motor->rotor_mode) { - case ROTOR_MODE_ENCODER: - case ROTOR_MODE_RUN_ENCODER_TEST_SENSORLESS: - return motor->encoder.pll_vel; - break; - case ROTOR_MODE_SENSORLESS: - return motor->sensorless.pll_vel; - break; - default: - //TODO error handling - return 0.0f; - break; - } + if (using_encoder(motor)) + return motor->encoder.pll_vel; + else if (using_sensorless(motor)) + return motor->sensorless.pll_vel; + else + //TODO error handling + return 0.0f; } static bool spin_up_timestep(Motor_t* motor, float phase, float I_mag) { @@ -1418,6 +1249,7 @@ static void control_motor_loop(Motor_t* motor) { break; } update_rotor(motor); + anti_cogging_calibration(motor); // Only runs if anticogging.calib_anticogging is true; non-blocking // Position control // TODO Decide if we want to use encoder or pll position here @@ -1438,6 +1270,14 @@ static void control_motor_loop(Motor_t* motor) { // Velocity control float Iq = motor->current_setpoint; + + // 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) + if(motor->anticogging.use_anticogging){ + Iq += motor->anticogging.cogging_map[mod(motor->encoder.pll_pos, ENCODER_CPR)]; + } + float v_err = vel_des - get_pll_vel(motor); if (motor->control_mode >= CTRL_MODE_VELOCITY_CONTROL) { Iq += motor->vel_gain * v_err; @@ -1477,6 +1317,7 @@ static void control_motor_loop(Motor_t* motor) { } } + motor->current_control.Iq = Iq; // Execute current command if(!FOC_current(motor, 0.0f, Iq)){ break; // in case of error exit loop, motor->error has been set by FOC_current @@ -1494,6 +1335,15 @@ static void control_motor_loop(Motor_t* motor) { void motor_thread(void const * argument) { Motor_t* motor = (Motor_t*)argument; + + // Allocate the map for anti-cogging algorithm and initialize all values to 0.0f + motor->anticogging.cogging_map = (float*)malloc(ENCODER_CPR*sizeof(float)); + if(motor->anticogging.cogging_map != NULL){ + for(int i = 0; i < ENCODER_CPR; i++){ + motor->anticogging.cogging_map[i] = 0.0f; + } + } + motor->motor_thread = osThreadGetId(); motor->thread_ready = true; @@ -1504,7 +1354,7 @@ void motor_thread(void const * argument) { __HAL_TIM_MOE_DISABLE_UNCONDITIONALLY(motor->motor_timer);// disables pwm outputs motor->do_calibration = false; } - + if (motor->calibration_ok && motor->enable_control) { motor->enable_step_dir = true; __HAL_TIM_MOE_ENABLE(motor->motor_timer); diff --git a/Firmware/MotorControl/low_level.h b/Firmware/MotorControl/low_level.h index 5f0f7f801..12eac1ba1 100644 --- a/Firmware/MotorControl/low_level.h +++ b/Firmware/MotorControl/low_level.h @@ -14,6 +14,15 @@ typedef enum { M_SIGNAL_PH_CURRENT_MEAS = 1u << 0 } Motor_thread_signals_t; +typedef struct { + int index; + float *cogging_map; + bool use_anticogging; + bool calib_anticogging; + float calib_pos_threshold; + float calib_vel_threshold; +} Anticogging_t; + typedef enum { ERROR_NO_ERROR, ERROR_PHASE_RESISTANCE_TIMING, @@ -61,6 +70,7 @@ typedef struct { // Voltage applied at end of cycle: float final_v_alpha; // [V] float final_v_beta; // [V] + float Iq; } Current_control_t; typedef enum { @@ -135,6 +145,7 @@ typedef struct { Sensorless_t sensorless; int timing_log_index; uint16_t timing_log[TIMING_LOG_SIZE]; + Anticogging_t anticogging; } Motor_t; typedef struct{ @@ -143,11 +154,10 @@ typedef struct{ } monitoring_slot; /* Exported constants --------------------------------------------------------*/ -extern float vbus_voltage; -extern Motor_t motors[]; extern const int num_motors; - /* Exported variables --------------------------------------------------------*/ +extern float vbus_voltage; +extern Motor_t motors[]; /* Exported macro ------------------------------------------------------------*/ /* Exported functions --------------------------------------------------------*/ @@ -162,10 +172,9 @@ void step_cb(uint16_t GPIO_Pin); void pwm_trig_adc_cb(ADC_HandleTypeDef* hadc, bool injected); void vbus_sense_adc_cb(ADC_HandleTypeDef* hadc, bool injected); +bool anti_cogging_calibration(Motor_t* motor); + //@TODO move motor thread to high level file void motor_thread(void const * argument); -//@TODO move cmd parsing to high level file -void motor_parse_cmd(uint8_t* buffer, int len); - #endif //__LOW_LEVEL_H diff --git a/Firmware/MotorControl/utils.c b/Firmware/MotorControl/utils.c index 09a6dde22..e28d70a90 100644 --- a/Firmware/MotorControl/utils.c +++ b/Firmware/MotorControl/utils.c @@ -161,3 +161,9 @@ float fast_atan2(float y, float x) { return r; } + +// Modulo (as opposed to remainder), per https://stackoverflow.com/a/19288271 +int mod(int dividend, int divisor){ + int r = dividend % divisor; + return (r < 0) ? (r + divisor) : r; +} \ No newline at end of file diff --git a/Firmware/MotorControl/utils.h b/Firmware/MotorControl/utils.h index 1b605f8b0..7170b8cab 100644 --- a/Firmware/MotorControl/utils.h +++ b/Firmware/MotorControl/utils.h @@ -18,5 +18,6 @@ int SVM(float alpha, float beta, float* tA, float* tB, float* tC); //beware of inserting large angles! float wrap_pm_pi(float theta); float fast_atan2(float y, float x); +int mod(int dividend, int divisor); #endif //__UTILS_H diff --git a/Firmware/Odrive.ioc b/Firmware/Odrive.ioc index b7bd70f6c..b5f504d88 100644 --- a/Firmware/Odrive.ioc +++ b/Firmware/Odrive.ioc @@ -80,6 +80,29 @@ CAN1.BS2=CAN_BS2_1TQ CAN1.CalculateTimeBit=1142 CAN1.CalculateTimeQuantum=380.95238095238096 CAN1.IPParameters=CalculateTimeQuantum,CalculateTimeBit,BS1,BS2 +Dma.Request0=UART4_RX +Dma.Request1=UART4_TX +Dma.RequestsNb=2 +Dma.UART4_RX.0.Direction=DMA_PERIPH_TO_MEMORY +Dma.UART4_RX.0.FIFOMode=DMA_FIFOMODE_DISABLE +Dma.UART4_RX.0.Instance=DMA1_Stream2 +Dma.UART4_RX.0.MemDataAlignment=DMA_MDATAALIGN_BYTE +Dma.UART4_RX.0.MemInc=DMA_MINC_ENABLE +Dma.UART4_RX.0.Mode=DMA_CIRCULAR +Dma.UART4_RX.0.PeriphDataAlignment=DMA_PDATAALIGN_BYTE +Dma.UART4_RX.0.PeriphInc=DMA_PINC_DISABLE +Dma.UART4_RX.0.Priority=DMA_PRIORITY_LOW +Dma.UART4_RX.0.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode +Dma.UART4_TX.1.Direction=DMA_MEMORY_TO_PERIPH +Dma.UART4_TX.1.FIFOMode=DMA_FIFOMODE_DISABLE +Dma.UART4_TX.1.Instance=DMA1_Stream4 +Dma.UART4_TX.1.MemDataAlignment=DMA_MDATAALIGN_BYTE +Dma.UART4_TX.1.MemInc=DMA_MINC_ENABLE +Dma.UART4_TX.1.Mode=DMA_NORMAL +Dma.UART4_TX.1.PeriphDataAlignment=DMA_PDATAALIGN_BYTE +Dma.UART4_TX.1.PeriphInc=DMA_PINC_DISABLE +Dma.UART4_TX.1.Priority=DMA_PRIORITY_LOW +Dma.UART4_TX.1.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode FREERTOS.INCLUDE_vTaskDelayUntil=1 FREERTOS.IPParameters=Tasks01,INCLUDE_vTaskDelayUntil FREERTOS.Tasks01=defaultTask,-3,256,StartDefaultTask,Default @@ -88,21 +111,23 @@ KeepUserPlacement=true Mcu.Family=STM32F4 Mcu.IP0=ADC1 Mcu.IP1=ADC2 -Mcu.IP10=TIM2 -Mcu.IP11=TIM3 -Mcu.IP12=TIM4 -Mcu.IP13=TIM8 -Mcu.IP14=USB_DEVICE -Mcu.IP15=USB_OTG_FS +Mcu.IP10=TIM1 +Mcu.IP11=TIM2 +Mcu.IP12=TIM3 +Mcu.IP13=TIM4 +Mcu.IP14=TIM8 +Mcu.IP15=UART4 +Mcu.IP16=USB_DEVICE +Mcu.IP17=USB_OTG_FS Mcu.IP2=ADC3 Mcu.IP3=CAN1 -Mcu.IP4=FREERTOS -Mcu.IP5=NVIC -Mcu.IP6=RCC -Mcu.IP7=SPI3 -Mcu.IP8=SYS -Mcu.IP9=TIM1 -Mcu.IPNb=16 +Mcu.IP4=DMA +Mcu.IP5=FREERTOS +Mcu.IP6=NVIC +Mcu.IP7=RCC +Mcu.IP8=SPI3 +Mcu.IP9=SYS +Mcu.IPNb=18 Mcu.Name=STM32F405RGTx Mcu.Package=LQFP64 Mcu.Pin0=PC13-ANTI_TAMP @@ -153,7 +178,7 @@ Mcu.Pin49=PB8 Mcu.Pin5=PC0 Mcu.Pin50=PB9 Mcu.Pin51=VP_FREERTOS_VS_ENABLE -Mcu.Pin52=VP_SYS_VS_Systick +Mcu.Pin52=VP_SYS_VS_tim14 Mcu.Pin53=VP_TIM1_VS_ClockSourceINT Mcu.Pin54=VP_TIM1_VS_no_output4 Mcu.Pin55=VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS @@ -164,32 +189,39 @@ Mcu.Pin9=PA0-WKUP Mcu.PinsNb=56 Mcu.UserConstants=TIM_1_8_CLOCK_HZ,168000000;TIM_1_8_PERIOD_CLOCKS,10192;TIM_1_8_DEADTIME_CLOCKS,20;TIM_APB1_CLOCK_HZ,84000000;TIM_APB1_PERIOD_CLOCKS,4096;TIM_APB1_DEADTIME_CLOCKS,40 Mcu.UserName=STM32F405RGTx -MxCube.Version=4.22.0 -MxDb.Version=DB.4.0.220 -NVIC.ADC_IRQn=true\:5\:0\:false\:false\:true\:true -NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false -NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false -NVIC.EXTI0_IRQn=true\:0\:0\:false\:false\:true\:false -NVIC.EXTI2_IRQn=true\:0\:0\:false\:false\:true\:false -NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false -NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false -NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false -NVIC.OTG_FS_IRQn=true\:5\:0\:false\:false\:true\:true -NVIC.PendSV_IRQn=true\:15\:0\:false\:false\:false\:true +MxCube.Version=4.22.1 +MxDb.Version=DB.4.0.221 +NVIC.ADC_IRQn=true\:5\:0\:false\:false\:true\:true\:true +NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:true +NVIC.DMA1_Stream2_IRQn=true\:5\:0\:false\:false\:true\:true\:true +NVIC.DMA1_Stream4_IRQn=true\:5\:0\:false\:false\:true\:true\:false +NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:true +NVIC.EXTI2_IRQn=true\:0\:0\:false\:false\:false\:false\:true +NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:true +NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:true +NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:true +NVIC.OTG_FS_IRQn=true\:5\:0\:false\:false\:true\:true\:true +NVIC.PendSV_IRQn=true\:15\:0\:false\:false\:false\:true\:true NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 -NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:false\:false -NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:true\:true -NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false +NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:false\:false\:true +NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:true\:true\:true +NVIC.TIM8_TRG_COM_TIM14_IRQn=true\:0\:0\:false\:false\:true\:false\:false +NVIC.TimeBase=TIM8_TRG_COM_TIM14_IRQn +NVIC.TimeBaseIP=TIM14 +NVIC.UART4_IRQn=true\:5\:0\:false\:false\:true\:true\:true +NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:true PA0-WKUP.GPIOParameters=GPIO_PuPd,GPIO_Label PA0-WKUP.GPIO_Label=GPIO_1 PA0-WKUP.GPIO_PuPd=GPIO_PULLDOWN PA0-WKUP.Locked=true -PA0-WKUP.Signal=GPXTI0 +PA0-WKUP.Signal=SharedStack_PA0 +PA0-WKUP.Stacked=true PA1.GPIOParameters=GPIO_PuPd,GPIO_Label PA1.GPIO_Label=GPIO_2 PA1.GPIO_PuPd=GPIO_NOPULL PA1.Locked=true -PA1.Signal=GPIO_Input +PA1.Signal=SharedStack_PA1 +PA1.Stacked=true PA10.GPIOParameters=GPIO_Label PA10.GPIO_Label=M0_CH PA10.Locked=true @@ -398,7 +430,7 @@ ProjectManager.StackSize=0x800 ProjectManager.TargetToolchain=SW4STM32 ProjectManager.ToolChainLocation= ProjectManager.UnderRoot=true -ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL,2-MX_ADC1_Init-ADC1-false-HAL,3-MX_ADC2_Init-ADC2-false-HAL,4-MX_CAN1_Init-CAN1-false-HAL,5-MX_TIM1_Init-TIM1-false-HAL,6-MX_TIM8_Init-TIM8-false-HAL,7-MX_TIM3_Init-TIM3-false-HAL,8-MX_TIM4_Init-TIM4-false-HAL,9-MX_SPI3_Init-SPI3-false-HAL,10-MX_ADC3_Init-ADC3-false-HAL,11-SystemClock_Config-RCC-false-HAL,12-MX_TIM2_Init-TIM2-false-HAL,13-MX_USB_DEVICE_Init-USB_DEVICE-false-HAL +ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL,2-MX_DMA_Init-DMA-false-HAL,3-MX_ADC1_Init-ADC1-false-HAL,4-MX_ADC2_Init-ADC2-false-HAL,5-MX_CAN1_Init-CAN1-false-HAL,6-MX_TIM1_Init-TIM1-false-HAL,7-MX_TIM8_Init-TIM8-false-HAL,8-MX_TIM3_Init-TIM3-false-HAL,9-MX_TIM4_Init-TIM4-false-HAL,10-MX_SPI3_Init-SPI3-false-HAL,11-MX_ADC3_Init-ADC3-false-HAL,12-SystemClock_Config-RCC-false-HAL,13-MX_TIM2_Init-TIM2-false-HAL,14-MX_USB_DEVICE_Init-USB_DEVICE-false-HAL,15-MX_UART4_Init-UART4-false-HAL RCC.48MHZClocksFreq_Value=48000000 RCC.AHBFreq_Value=168000000 RCC.APB1CLKDivider=RCC_HCLK_DIV4 @@ -464,8 +496,6 @@ SH.ADCx_IN5.ConfNb=2 SH.ADCx_IN6.0=ADC1_IN6,IN6 SH.ADCx_IN6.1=ADC2_IN6,IN6 SH.ADCx_IN6.ConfNb=2 -SH.GPXTI0.0=GPIO_EXTI0 -SH.GPXTI0.ConfNb=1 SH.GPXTI2.0=GPIO_EXTI2 SH.GPXTI2.ConfNb=1 SH.S_TIM1_CH1.0=TIM1_CH1,PWM Generation1 CH1 CH1N @@ -492,6 +522,12 @@ SH.S_TIM8_CH2.0=TIM8_CH2,PWM Generation2 CH2 CH2N SH.S_TIM8_CH2.ConfNb=1 SH.S_TIM8_CH3.0=TIM8_CH3,PWM Generation3 CH3 CH3N SH.S_TIM8_CH3.ConfNb=1 +SH.SharedStack_PA0.0=GPIO_EXTI0+0 +SH.SharedStack_PA0.1=UART4_TX,Asynchronous +SH.SharedStack_PA0.ConfNb=2 +SH.SharedStack_PA1.0=GPIO_Input+0 +SH.SharedStack_PA1.1=UART4_RX,Asynchronous +SH.SharedStack_PA1.ConfNb=2 SPI3.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_16 SPI3.CLKPhase=SPI_PHASE_2EDGE SPI3.CalculateBaudRate=2.625 MBits/s @@ -555,11 +591,15 @@ TIM8.OffStateIDLEMode=TIM_OSSI_ENABLE TIM8.OffStateRunMode=TIM_OSSR_ENABLE TIM8.Period=TIM_1_8_PERIOD_CLOCKS TIM8.TIM_MasterOutputTrigger=TIM_TRGO_UPDATE +UART4.IPParameters=VirtualMode +UART4.VirtualMode=Asynchronous +USB_DEVICE.APP_RX_DATA_SIZE-CDC_FS=64 +USB_DEVICE.APP_TX_DATA_SIZE-CDC_FS=64 USB_DEVICE.CLASS_NAME_FS=CDC -USB_DEVICE.IPParameters=VirtualMode-CDC_FS,VirtualModeFS,CLASS_NAME_FS,MANUFACTURER_STRING-CDC_FS,PRODUCT_STRING_CDC_FS,VID-CDC_FS,PID_CDC_FS,SERIALNUMBER_STRING_CDC_FS -USB_DEVICE.MANUFACTURER_STRING-CDC_FS=ODrive -USB_DEVICE.PID_CDC_FS=0x0D31 -USB_DEVICE.PRODUCT_STRING_CDC_FS=ODrive rev 3.1 +USB_DEVICE.IPParameters=VirtualMode-CDC_FS,VirtualModeFS,CLASS_NAME_FS,MANUFACTURER_STRING-CDC_FS,PRODUCT_STRING_CDC_FS,VID-CDC_FS,PID_CDC_FS,SERIALNUMBER_STRING_CDC_FS,APP_RX_DATA_SIZE-CDC_FS,APP_TX_DATA_SIZE-CDC_FS +USB_DEVICE.MANUFACTURER_STRING-CDC_FS=ODrive Robotics +USB_DEVICE.PID_CDC_FS=0x0D33 +USB_DEVICE.PRODUCT_STRING_CDC_FS=ODrive v3.3 USB_DEVICE.SERIALNUMBER_STRING_CDC_FS=000000000001 USB_DEVICE.VID-CDC_FS=0x1209 USB_DEVICE.VirtualMode-CDC_FS=Cdc @@ -569,8 +609,8 @@ USB_OTG_FS.VirtualMode=Device_Only USB_OTG_FS.vbus_sensing_enable=DISABLE VP_FREERTOS_VS_ENABLE.Mode=Enabled VP_FREERTOS_VS_ENABLE.Signal=FREERTOS_VS_ENABLE -VP_SYS_VS_Systick.Mode=SysTick -VP_SYS_VS_Systick.Signal=SYS_VS_Systick +VP_SYS_VS_tim14.Mode=TIM14 +VP_SYS_VS_tim14.Signal=SYS_VS_tim14 VP_TIM1_VS_ClockSourceINT.Mode=Internal VP_TIM1_VS_ClockSourceINT.Signal=TIM1_VS_ClockSourceINT VP_TIM1_VS_no_output4.Mode=Output Compare4 No Output diff --git a/Firmware/README.md b/Firmware/README.md index 82e6258b0..ec5d96f62 100644 --- a/Firmware/README.md +++ b/Firmware/README.md @@ -10,7 +10,7 @@ If you are a developer, you are encouraged to use the `devel` branch, as it cont - [Configuring parameters](#configuring-parameters) - [Compiling and downloading firmware](#compiling-and-downloading-firmware) -- [Communicating over USB](#communicating-over-usb) +- [Communicating over USB and UART](#communicating-over-usb-and-uart) - [Generating startup code](#generating-startup-code) - [Setting up Eclipse development environment](#setting-up-eclipse-development-environment) - [Notes for Contributors](#notes-for-contributors) @@ -20,26 +20,34 @@ If you are a developer, you are encouraged to use the `devel` branch, as it cont ## 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. +### Hardware configuration 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 #define HW_VERSION_MAJOR 3 #define HW_VERSION_MINOR 2 ``` +### Communication configuration +If you are using USB only to communicate with the ODrive, you may skip this step. + +The GPIO 1,2 pins are configurable as either step/direction, or as UART. +In [MotorControl/commands.c](MotorControl/commands.c) please set `gpio_mode` to the corresponding value (`GPIO_MODE_UART` or `GPIO_MODE_STEP_DIR`). + +### 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 motor_thread` at the bottom of [MotorControl/low_level.c](MotorControl/low_level.c). This is like `main` for each motor, and is probably where you should start reading the code. -### Mandatory parameters +#### 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 magnets in the rotor, if you can see them. * `brake_resistance`: This is the resistance of the brake resistor. If you are not using it, you may set it to 0.0f. -### Tuning parameters +#### 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 should increase this to 75A to get some performance. Note that above 75A, you must change the current amplifier gains. +* 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. * The velocity limit: `.vel_limit = 20000.0f, // [counts/s]`. Does what it says on the tin. The motion control gains are currently manually tuned: @@ -56,7 +64,7 @@ An upcoming feature will enable automatic tuning. Until then, here is a rough tu * 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 +#### 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. @@ -77,18 +85,22 @@ To compile the program, you first need to install the prerequisite tools: * Installing on Ubuntu: `sudo apt-get install openocd` * No additional USB CDC driver should be required on Linux. +#### Mac: +* `brew cask install gcc-arm-embedded`: GCC toolchain+debugger +* `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`. +* [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) * 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`. After installing all of the above, open a Git Bash shell. Continue at section [Building the firmware](#building-the-firmware). ### Building the firmware * Make sure you have cloned the repository. -* Navigate your terminal (bash/cygwin) to the ODriveFirmware dir. +* Navigate your terminal (bash/cygwin) to the ODrive/Firmware dir. * Run `make` in the root of this repository. ### Flashing the firmware @@ -101,19 +113,25 @@ After installing all of the above, open a Git Bash shell. Continue at section [B Run `make gdb`. This will reset and halt at program start. Now you can set breakpoints and run the program. If you know how to use gdb, you are good to go. If you prefer to debug from eclipse, see [Setting up Eclipse development environment](#setting-up-eclipse-development-environment). -## Communicating over USB +## Communicating over USB and UART There is currently a very primitive method to read/write configuration, commands and errors from the ODrive over the USB. -Please use the `ODriveFirmware/tools/test_bulk.py` python script for this. It is written for Python 3. +Please use the `tools/test_communication.py` python script for this. It is written for [Python 3](https://www.python.org/downloads/) and so should be instlled first. Setup instructions as follows: -* Install PyUSB (pip install --pre pysusb) +* Install PyUSB (pip install --pre pyusb). This can be done using the [gitbash terminal](https://git-for-windows.github.io/) for windows users. * Plug in the STLink or another power source to power the ODrive board * Plug in a separate USB cable into the microUSB connector on ODrive -* On Windows, use the [Zadig](http://zadig.akeo.ie/) utility to set ODrive (not STLink!) driver to libusb -* Run test_bulk.py +* On Windows, use the [Zadig](http://zadig.akeo.ie/) utility to set ODrive (not STLink!) driver to libusb. If 'Odrive V3.x' is not in the list of devices upon opening Zadig check 'List All Devices' from the options menu. Connecting to the Odrive board directly and not over a usb hub may also help. With the Odrive selected in the device list choose 'libusb-win32' from the target driver list and select the large 'install driver' button. +* Run `tools/test_communication.py` ### Command set -The most accurate way to understand the commands is to read [the code](https://github.com/madcowswe/ODriveFirmware/blob/f19f1b78de4bd917284ff95bc61ca616ca9bacc4/MotorControl/low_level.c#L353) that parses the commands. +The most accurate way to understand the commands is to read [the code](MotorControl/commands.c) that parses the commands. Also you can have a look at the [ODrive Arduino library](https://github.com/madcowswe/ODriveArduino) that makes it easy to use the UART interface on Arduino. You can also look at it as an implementation example of how to talk to the ODrive over UART. + +#### UART framing +USB communicates with packets, so it is easy to frame a command as one command per packet. However, UART doesn't have any packeting, so we need a way to frame the commands. The start-of-packet symbol is `$` and the end-of-packet symbol is `!`, that is, something like this: `$command!`. An example of a valid UART position command: +``` +$p 0 10000 0 0! +``` #### Motor Position command ``` @@ -156,7 +174,7 @@ s type index value ** `0` is float ** `1` is int ** `2` is bool -* `index` is the index in the corresponding [exposed variable table](https://github.com/madcowswe/ODriveFirmware/blob/f19f1b78de4bd917284ff95bc61ca616ca9bacc4/MotorControl/low_level.c#L184-L265). +* `index` is the index in the corresponding [exposed variable table](MotorControl/commands.c). For example * `g 0 12` will return the phase resistance of M0 @@ -186,12 +204,6 @@ We also use a tool to generate the Makefile. The steps to do this are as follows * Press `Project -> Generate code` * You may need to let it download some drivers and such. -### Generate makefile -There is an excellent project called CubeMX2Makefile, originally from baoshi. This project is included as a submodule. -* Initialise and clone the submodules: `git submodule init; git submodule update` -* Generate makefile: `python2 CubeMX2Makefile/CubeMX2Makefile.py .` - - ## Setting up Eclipse development environment ### Install diff --git a/Firmware/STM32F405RGTx_FLASH.ld b/Firmware/STM32F405RGTx_FLASH.ld index 02984eb11..2685ffabc 100644 --- a/Firmware/STM32F405RGTx_FLASH.ld +++ b/Firmware/STM32F405RGTx_FLASH.ld @@ -18,32 +18,13 @@ ** Distribution: The file is distributed as is, without any warranty ** of any kind. ** -***************************************************************************** -** @attention -** -**

© COPYRIGHT(c) 2014 Ac6

-** -** Redistribution and use in source and binary forms, with or without modification, -** are permitted provided that the following conditions are met: -** 1. Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright notice, -** this list of conditions and the following disclaimer in the documentation -** and/or other materials provided with the distribution. -** 3. Neither the name of Ac6 nor the names of its contributors -** may be used to endorse or promote products derived from this software -** without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** (c)Copyright Ac6. +** You may use this file as-is or modify it according to the needs of your +** project. Distribution of this file (unmodified or modified) is not +** permitted. Ac6 permit registered System Workbench for MCU users the +** rights to distribute the assembled, compiled & linked contents of this +** file as part of an application binary file, provided that it is built +** using the System Workbench for MCU toolchain. ** ***************************************************************************** */ diff --git a/Firmware/Src/dma.c b/Firmware/Src/dma.c new file mode 100644 index 000000000..322d04abf --- /dev/null +++ b/Firmware/Src/dma.c @@ -0,0 +1,94 @@ +/** + ****************************************************************************** + * File Name : dma.c + * Description : This file provides code for the configuration + * of all the requested memory to memory DMA transfers. + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2017 STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted, provided that the following conditions are met: + * + * 1. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ +/* Includes ------------------------------------------------------------------*/ +#include "dma.h" + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/*----------------------------------------------------------------------------*/ +/* Configure DMA */ +/*----------------------------------------------------------------------------*/ + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ + +/** + * Enable DMA controller clock + */ +void MX_DMA_Init(void) +{ + /* DMA controller clock enable */ + __HAL_RCC_DMA1_CLK_ENABLE(); + + /* DMA interrupt init */ + /* DMA1_Stream2_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DMA1_Stream2_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(DMA1_Stream2_IRQn); + /* DMA1_Stream4_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DMA1_Stream4_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn); + +} + +/* USER CODE BEGIN 2 */ + +/* USER CODE END 2 */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Firmware/Src/freertos.c b/Firmware/Src/freertos.c index 077e6f1a5..da369f40e 100644 --- a/Firmware/Src/freertos.c +++ b/Firmware/Src/freertos.c @@ -54,14 +54,14 @@ /* USER CODE BEGIN Includes */ #include "freertos_vars.h" #include "low_level.h" -#include "version.h" +#include "commands.h" /* USER CODE END Includes */ /* Variables -----------------------------------------------------------------*/ osThreadId defaultTaskHandle; /* USER CODE BEGIN Variables */ -extern PCD_HandleTypeDef hpcd_USB_OTG_FS; + /* USER CODE END Variables */ /* Function prototypes -------------------------------------------------------*/ @@ -71,7 +71,6 @@ extern void MX_USB_DEVICE_Init(void); void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */ /* USER CODE BEGIN FunctionPrototypes */ -void usb_cmd_thread(void const * argument); /* USER CODE END FunctionPrototypes */ @@ -121,6 +120,9 @@ void StartDefaultTask(void const * argument) /* USER CODE BEGIN StartDefaultTask */ + // Init communications + init_communication(); + // Init motor control init_motor_control(); @@ -131,8 +133,8 @@ void StartDefaultTask(void const * argument) thread_motor_1 = osThreadCreate(osThread(task_motor_1), &motors[1]); // Start USB command handling thread - osThreadDef(task_usb_cmd, usb_cmd_thread, osPriorityNormal, 0, 512); - thread_usb_cmd = osThreadCreate(osThread(task_usb_cmd), NULL); + osThreadDef(task_cmd_parse, cmd_parse_thread, osPriorityNormal, 0, 512); + thread_cmd_parse = osThreadCreate(osThread(task_cmd_parse), NULL); //If we get to here, then the default task is done. vTaskDelete(defaultTaskHandle); @@ -142,24 +144,6 @@ void StartDefaultTask(void const * argument) /* USER CODE BEGIN Application */ -// Thread to handle deffered processing of USB interrupt -void usb_cmd_thread(void const * argument) { - - for (;;) { - // Wait for signalling from USB interrupt (OTG_FS_IRQHandler) - osSemaphoreWait(sem_usb_irq, osWaitForever); - // Irq processing loop - //while(HAL_NVIC_GetActive(OTG_FS_IRQn)) { - HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS); - //} - // Let the irq (OTG_FS_IRQHandler) fire again. - HAL_NVIC_EnableIRQ(OTG_FS_IRQn); - } - - // If we get here, then this task is done - vTaskDelete(osThreadGetId()); -} - /* USER CODE END Application */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Firmware/Src/gpio.c b/Firmware/Src/gpio.c index 75b4aa88b..e751fb614 100644 --- a/Firmware/Src/gpio.c +++ b/Firmware/Src/gpio.c @@ -71,6 +71,8 @@ * Output * EVENT_OUT * EXTI + PA0-WKUP ------> SharedStack_PA0 + PA1 ------> SharedStack_PA1 */ void MX_GPIO_Init(void) { @@ -100,14 +102,30 @@ void MX_GPIO_Init(void) GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); - /*Configure GPIO pins : PAPin PAPin */ - GPIO_InitStruct.Pin = GPIO_1_Pin|GPIO_3_Pin; + /*Configure GPIO pin : PtPin */ + GPIO_InitStruct.Pin = GPIO_1_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF8_UART4; + HAL_GPIO_Init(GPIO_1_GPIO_Port, &GPIO_InitStruct); + + /*Configure GPIO pin : PtPin */ + GPIO_InitStruct.Pin = GPIO_2_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF8_UART4; + HAL_GPIO_Init(GPIO_2_GPIO_Port, &GPIO_InitStruct); + + /*Configure GPIO pin : PtPin */ + GPIO_InitStruct.Pin = GPIO_3_Pin; GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; GPIO_InitStruct.Pull = GPIO_PULLDOWN; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + HAL_GPIO_Init(GPIO_3_GPIO_Port, &GPIO_InitStruct); - /*Configure GPIO pins : PAPin PAPin PAPin */ - GPIO_InitStruct.Pin = GPIO_2_Pin|GPIO_4_Pin|M0_ENC_Z_Pin; + /*Configure GPIO pins : PAPin PAPin */ + GPIO_InitStruct.Pin = GPIO_4_Pin|M0_ENC_Z_Pin; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); @@ -132,9 +150,6 @@ void MX_GPIO_Init(void) HAL_GPIO_Init(nFAULT_GPIO_Port, &GPIO_InitStruct); /* EXTI interrupt init*/ - HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0); - HAL_NVIC_EnableIRQ(EXTI0_IRQn); - HAL_NVIC_SetPriority(EXTI2_IRQn, 0, 0); HAL_NVIC_EnableIRQ(EXTI2_IRQn); @@ -143,6 +158,43 @@ void MX_GPIO_Init(void) /* USER CODE BEGIN 2 */ #endif // End GPIO Include +void SetGPIO12toUART() { + GPIO_InitTypeDef GPIO_InitStruct; + + HAL_NVIC_DisableIRQ(EXTI0_IRQn); + + GPIO_InitStruct.Pin = GPIO_1_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF8_UART4; + HAL_GPIO_Init(GPIO_1_GPIO_Port, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = GPIO_2_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF8_UART4; + HAL_GPIO_Init(GPIO_2_GPIO_Port, &GPIO_InitStruct); +} + +void SetGPIO12toStepDir() { + GPIO_InitTypeDef GPIO_InitStruct; + + GPIO_InitStruct.Pin = GPIO_1_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + HAL_GPIO_Init(GPIO_1_GPIO_Port, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = GPIO_2_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIO_2_GPIO_Port, &GPIO_InitStruct); + + HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(EXTI0_IRQn); +} + //Dispatch processing of external interrupts based on source void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { //Step signals for M0 and M1 diff --git a/Firmware/Src/main.c b/Firmware/Src/main.c index 5ec794e67..cb7e0490a 100644 --- a/Firmware/Src/main.c +++ b/Firmware/Src/main.c @@ -51,8 +51,10 @@ #include "cmsis_os.h" #include "adc.h" #include "can.h" +#include "dma.h" #include "spi.h" #include "tim.h" +#include "usart.h" #include "usb_device.h" #include "gpio.h" @@ -105,6 +107,7 @@ int main(void) /* Initialize all configured peripherals */ MX_GPIO_Init(); + MX_DMA_Init(); MX_ADC1_Init(); MX_ADC2_Init(); MX_CAN1_Init(); @@ -115,6 +118,7 @@ int main(void) MX_SPI3_Init(); MX_ADC3_Init(); MX_TIM2_Init(); + MX_UART4_Init(); /* USER CODE BEGIN 2 */ @@ -204,6 +208,27 @@ void SystemClock_Config(void) /* USER CODE END 4 */ +/** + * @brief Period elapsed callback in non blocking mode + * @note This function is called when TIM14 interrupt took place, inside + * HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment + * a global variable "uwTick" used as application time base. + * @param htim : TIM handle + * @retval None + */ +void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) +{ +/* USER CODE BEGIN Callback 0 */ + +/* USER CODE END Callback 0 */ + if (htim->Instance == TIM14) { + HAL_IncTick(); + } +/* USER CODE BEGIN Callback 1 */ + +/* USER CODE END Callback 1 */ +} + /** * @brief This function is executed in case of error occurrence. * @param None diff --git a/Firmware/Src/stm32f4xx_hal_timebase_TIM.c b/Firmware/Src/stm32f4xx_hal_timebase_TIM.c new file mode 100644 index 000000000..a74e47738 --- /dev/null +++ b/Firmware/Src/stm32f4xx_hal_timebase_TIM.c @@ -0,0 +1,158 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_timebase_TIM.c + * @brief HAL time base based on the hardware TIM. + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2017 STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted, provided that the following conditions are met: + * + * 1. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" +#include "stm32f4xx_hal_tim.h" +/** @addtogroup STM32F7xx_HAL_Examples + * @{ + */ + +/** @addtogroup HAL_TimeBase + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +TIM_HandleTypeDef htim14; +uint32_t uwIncrementState = 0; +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/** + * @brief This function configures the TIM14 as a time base source. + * The time source is configured to have 1ms time base with a dedicated + * Tick interrupt priority. + * @note This function is called automatically at the beginning of program after + * reset by HAL_Init() or at any time when clock is configured, by HAL_RCC_ClockConfig(). + * @param TickPriority: Tick interrupt priorty. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority) +{ + RCC_ClkInitTypeDef clkconfig; + uint32_t uwTimclock = 0; + uint32_t uwPrescalerValue = 0; + uint32_t pFLatency; + + /*Configure the TIM14 IRQ priority */ + HAL_NVIC_SetPriority(TIM8_TRG_COM_TIM14_IRQn, TickPriority ,0); + + /* Enable the TIM14 global Interrupt */ + HAL_NVIC_EnableIRQ(TIM8_TRG_COM_TIM14_IRQn); + + /* Enable TIM14 clock */ + __HAL_RCC_TIM14_CLK_ENABLE(); + + /* Get clock configuration */ + HAL_RCC_GetClockConfig(&clkconfig, &pFLatency); + + /* Compute TIM14 clock */ + uwTimclock = 2*HAL_RCC_GetPCLK1Freq(); + + /* Compute the prescaler value to have TIM14 counter clock equal to 1MHz */ + uwPrescalerValue = (uint32_t) ((uwTimclock / 1000000) - 1); + + /* Initialize TIM14 */ + htim14.Instance = TIM14; + + /* Initialize TIMx peripheral as follow: + + Period = [(TIM14CLK/1000) - 1]. to have a (1/1000) s time base. + + Prescaler = (uwTimclock/1000000 - 1) to have a 1MHz counter clock. + + ClockDivision = 0 + + Counter direction = Up + */ + htim14.Init.Period = (1000000 / 1000) - 1; + htim14.Init.Prescaler = uwPrescalerValue; + htim14.Init.ClockDivision = 0; + htim14.Init.CounterMode = TIM_COUNTERMODE_UP; + if(HAL_TIM_Base_Init(&htim14) == HAL_OK) + { + /* Start the TIM time Base generation in interrupt mode */ + return HAL_TIM_Base_Start_IT(&htim14); + } + + /* Return function status */ + return HAL_ERROR; +} + +/** + * @brief Suspend Tick increment. + * @note Disable the tick increment by disabling TIM14 update interrupt. + * @param None + * @retval None + */ +void HAL_SuspendTick(void) +{ + /* Disable TIM14 update Interrupt */ + __HAL_TIM_DISABLE_IT(&htim14, TIM_IT_UPDATE); +} + +/** + * @brief Resume Tick increment. + * @note Enable the tick increment by Enabling TIM14 update interrupt. + * @param None + * @retval None + */ +void HAL_ResumeTick(void) +{ + /* Enable TIM14 Update interrupt */ + __HAL_TIM_ENABLE_IT(&htim14, TIM_IT_UPDATE); +} + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Firmware/Src/stm32f4xx_it.c b/Firmware/Src/stm32f4xx_it.c index 449ac7fe1..a740268af 100644 --- a/Firmware/Src/stm32f4xx_it.c +++ b/Firmware/Src/stm32f4xx_it.c @@ -54,6 +54,12 @@ extern PCD_HandleTypeDef hpcd_USB_OTG_FS; extern ADC_HandleTypeDef hadc1; extern ADC_HandleTypeDef hadc2; extern ADC_HandleTypeDef hadc3; +extern TIM_HandleTypeDef htim8; +extern DMA_HandleTypeDef hdma_uart4_rx; +extern DMA_HandleTypeDef hdma_uart4_tx; +extern UART_HandleTypeDef huart4; + +extern TIM_HandleTypeDef htim14; /******************************************************************************/ /* Cortex-M4 Processor Interruption and Exception Handlers */ @@ -157,7 +163,6 @@ void SysTick_Handler(void) /* USER CODE BEGIN SysTick_IRQn 0 */ /* USER CODE END SysTick_IRQn 0 */ - HAL_IncTick(); osSystickHandler(); /* USER CODE BEGIN SysTick_IRQn 1 */ @@ -172,31 +177,31 @@ void SysTick_Handler(void) /******************************************************************************/ /** -* @brief This function handles EXTI line0 interrupt. +* @brief This function handles DMA1 stream2 global interrupt. */ -void EXTI0_IRQHandler(void) +void DMA1_Stream2_IRQHandler(void) { - /* USER CODE BEGIN EXTI0_IRQn 0 */ + /* USER CODE BEGIN DMA1_Stream2_IRQn 0 */ - /* USER CODE END EXTI0_IRQn 0 */ - HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0); - /* USER CODE BEGIN EXTI0_IRQn 1 */ + /* USER CODE END DMA1_Stream2_IRQn 0 */ + HAL_DMA_IRQHandler(&hdma_uart4_rx); + /* USER CODE BEGIN DMA1_Stream2_IRQn 1 */ - /* USER CODE END EXTI0_IRQn 1 */ + /* USER CODE END DMA1_Stream2_IRQn 1 */ } /** -* @brief This function handles EXTI line2 interrupt. +* @brief This function handles DMA1 stream4 global interrupt. */ -void EXTI2_IRQHandler(void) +void DMA1_Stream4_IRQHandler(void) { - /* USER CODE BEGIN EXTI2_IRQn 0 */ + /* USER CODE BEGIN DMA1_Stream4_IRQn 0 */ - /* USER CODE END EXTI2_IRQn 0 */ - HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2); - /* USER CODE BEGIN EXTI2_IRQn 1 */ + /* USER CODE END DMA1_Stream4_IRQn 0 */ + HAL_DMA_IRQHandler(&hdma_uart4_tx); + /* USER CODE BEGIN DMA1_Stream4_IRQn 1 */ - /* USER CODE END EXTI2_IRQn 1 */ + /* USER CODE END DMA1_Stream4_IRQn 1 */ } /** @@ -225,6 +230,35 @@ void ADC_IRQHandler(void) /* USER CODE END ADC_IRQn 1 */ } +/** +* @brief This function handles TIM8 trigger and commutation interrupts and TIM14 global interrupt. +*/ +void TIM8_TRG_COM_TIM14_IRQHandler(void) +{ + /* USER CODE BEGIN TIM8_TRG_COM_TIM14_IRQn 0 */ + + /* USER CODE END TIM8_TRG_COM_TIM14_IRQn 0 */ + HAL_TIM_IRQHandler(&htim8); + HAL_TIM_IRQHandler(&htim14); + /* USER CODE BEGIN TIM8_TRG_COM_TIM14_IRQn 1 */ + + /* USER CODE END TIM8_TRG_COM_TIM14_IRQn 1 */ +} + +/** +* @brief This function handles UART4 global interrupt. +*/ +void UART4_IRQHandler(void) +{ + /* USER CODE BEGIN UART4_IRQn 0 */ + + /* USER CODE END UART4_IRQn 0 */ + HAL_UART_IRQHandler(&huart4); + /* USER CODE BEGIN UART4_IRQn 1 */ + + /* USER CODE END UART4_IRQn 1 */ +} + /** * @brief This function handles USB On The Go FS global interrupt. */ @@ -267,5 +301,22 @@ void ADC_IRQ_Dispatch(ADC_HandleTypeDef* hadc, ADC_handler_t callback) { } } + +/** +* @brief This function handles EXTI line0 interrupt. +*/ +void EXTI0_IRQHandler(void) +{ + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0); +} + +/** +* @brief This function handles EXTI line2 interrupt. +*/ +void EXTI2_IRQHandler(void) +{ + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2); +} + /* USER CODE END 1 */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Firmware/Src/syscalls.c b/Firmware/Src/syscalls.c index 7a2e590a5..3cd2a073a 100644 --- a/Firmware/Src/syscalls.c +++ b/Firmware/Src/syscalls.c @@ -6,7 +6,10 @@ */ #include -#include "usbd_cdc_if.h" +#include +#include +#include + //int _read(int file, char *data, int len) {} //int _close(int file) {} @@ -14,11 +17,37 @@ //int _fstat(int file, struct stat *st) {} //int _isatty(int file) {} +#define UART_TX_BUFFER_SIZE 64 +static uint8_t uart_tx_buf[UART_TX_BUFFER_SIZE]; + int _write(int file, char *data, int len) { + //number of bytes written + int written = 0; + switch (serial_printf_select) { + + case SERIAL_PRINTF_IS_USB: { + // transmit over CDC + uint8_t status = CDC_Transmit_FS((uint8_t*)data, len); + written = (status == USBD_OK) ? len : 0; + } break; + + case SERIAL_PRINTF_IS_UART: { + //Check length + if (len > UART_TX_BUFFER_SIZE) + return 0; + // Check if transfer is already ongoing + if(huart4.gState != HAL_UART_STATE_READY) + return 0; + // memcpy data into uart_tx_buf + memcpy(uart_tx_buf, data, len); + // Start DMA background trasnfer + HAL_UART_Transmit_DMA(&huart4, uart_tx_buf, len); + } break; - // transmit over CDC - uint8_t status = CDC_Transmit_FS((uint8_t*)data, len); + default: { + written = 0; + } break; + } - // return number of bytes written - return (status == USBD_OK ? len : 0); + return written; } diff --git a/Firmware/Src/tim.c b/Firmware/Src/tim.c index 1497cd5bb..0589c3b0e 100644 --- a/Firmware/Src/tim.c +++ b/Firmware/Src/tim.c @@ -373,6 +373,10 @@ void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* tim_pwmHandle) /* USER CODE END TIM8_MspInit 0 */ /* TIM8 clock enable */ __HAL_RCC_TIM8_CLK_ENABLE(); + + /* TIM8 interrupt Init */ + HAL_NVIC_SetPriority(TIM8_TRG_COM_TIM14_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(TIM8_TRG_COM_TIM14_IRQn); /* USER CODE BEGIN TIM8_MspInit 1 */ /* USER CODE END TIM8_MspInit 1 */ @@ -565,6 +569,9 @@ void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef* tim_pwmHandle) /* USER CODE END TIM8_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_TIM8_CLK_DISABLE(); + + /* TIM8 interrupt Deinit */ + HAL_NVIC_DisableIRQ(TIM8_TRG_COM_TIM14_IRQn); /* USER CODE BEGIN TIM8_MspDeInit 1 */ /* USER CODE END TIM8_MspDeInit 1 */ diff --git a/Firmware/Src/usart.c b/Firmware/Src/usart.c new file mode 100644 index 000000000..1704d0122 --- /dev/null +++ b/Firmware/Src/usart.c @@ -0,0 +1,200 @@ +/** + ****************************************************************************** + * File Name : USART.c + * Description : This file provides code for the configuration + * of the USART instances. + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2017 STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted, provided that the following conditions are met: + * + * 1. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usart.h" + +#include "gpio.h" +#include "dma.h" + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +UART_HandleTypeDef huart4; +DMA_HandleTypeDef hdma_uart4_rx; +DMA_HandleTypeDef hdma_uart4_tx; + +/* UART4 init function */ +void MX_UART4_Init(void) +{ + + huart4.Instance = UART4; + huart4.Init.BaudRate = 115200; + huart4.Init.WordLength = UART_WORDLENGTH_8B; + huart4.Init.StopBits = UART_STOPBITS_1; + huart4.Init.Parity = UART_PARITY_NONE; + huart4.Init.Mode = UART_MODE_TX_RX; + huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE; + huart4.Init.OverSampling = UART_OVERSAMPLING_16; + if (HAL_UART_Init(&huart4) != HAL_OK) + { + _Error_Handler(__FILE__, __LINE__); + } + +} + +void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) +{ + + GPIO_InitTypeDef GPIO_InitStruct; + if(uartHandle->Instance==UART4) + { + /* USER CODE BEGIN UART4_MspInit 0 */ + + /* USER CODE END UART4_MspInit 0 */ + /* UART4 clock enable */ + __HAL_RCC_UART4_CLK_ENABLE(); + + /**UART4 GPIO Configuration + PA0-WKUP ------> UART4_TX + PA1 ------> UART4_RX + */ + GPIO_InitStruct.Pin = GPIO_1_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF8_UART4; + HAL_GPIO_Init(GPIO_1_GPIO_Port, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = GPIO_2_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF8_UART4; + HAL_GPIO_Init(GPIO_2_GPIO_Port, &GPIO_InitStruct); + + /* UART4 DMA Init */ + /* UART4_RX Init */ + hdma_uart4_rx.Instance = DMA1_Stream2; + hdma_uart4_rx.Init.Channel = DMA_CHANNEL_4; + hdma_uart4_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_uart4_rx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_uart4_rx.Init.MemInc = DMA_MINC_ENABLE; + hdma_uart4_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_uart4_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_uart4_rx.Init.Mode = DMA_CIRCULAR; + hdma_uart4_rx.Init.Priority = DMA_PRIORITY_LOW; + hdma_uart4_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + if (HAL_DMA_Init(&hdma_uart4_rx) != HAL_OK) + { + _Error_Handler(__FILE__, __LINE__); + } + + __HAL_LINKDMA(uartHandle,hdmarx,hdma_uart4_rx); + + /* UART4_TX Init */ + hdma_uart4_tx.Instance = DMA1_Stream4; + hdma_uart4_tx.Init.Channel = DMA_CHANNEL_4; + hdma_uart4_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_uart4_tx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_uart4_tx.Init.MemInc = DMA_MINC_ENABLE; + hdma_uart4_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_uart4_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_uart4_tx.Init.Mode = DMA_NORMAL; + hdma_uart4_tx.Init.Priority = DMA_PRIORITY_LOW; + hdma_uart4_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + if (HAL_DMA_Init(&hdma_uart4_tx) != HAL_OK) + { + _Error_Handler(__FILE__, __LINE__); + } + + __HAL_LINKDMA(uartHandle,hdmatx,hdma_uart4_tx); + + /* UART4 interrupt Init */ + HAL_NVIC_SetPriority(UART4_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(UART4_IRQn); + /* USER CODE BEGIN UART4_MspInit 1 */ + + /* USER CODE END UART4_MspInit 1 */ + } +} + +void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle) +{ + + if(uartHandle->Instance==UART4) + { + /* USER CODE BEGIN UART4_MspDeInit 0 */ + + /* USER CODE END UART4_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_UART4_CLK_DISABLE(); + + /**UART4 GPIO Configuration + PA0-WKUP ------> UART4_TX + PA1 ------> UART4_RX + */ + HAL_GPIO_DeInit(GPIOA, GPIO_1_Pin|GPIO_2_Pin); + + /* UART4 DMA DeInit */ + HAL_DMA_DeInit(uartHandle->hdmarx); + HAL_DMA_DeInit(uartHandle->hdmatx); + + /* UART4 interrupt Deinit */ + HAL_NVIC_DisableIRQ(UART4_IRQn); + /* USER CODE BEGIN UART4_MspDeInit 1 */ + + /* USER CODE END UART4_MspDeInit 1 */ + } +} + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Firmware/Src/usb_device.c b/Firmware/Src/usb_device.c index 4bd139a53..2c987f26e 100644 --- a/Firmware/Src/usb_device.c +++ b/Firmware/Src/usb_device.c @@ -58,9 +58,13 @@ /* USB Device Core handle declaration */ USBD_HandleTypeDef hUsbDeviceFS; -/* init function */ +/* init function */ void MX_USB_DEVICE_Init(void) { + /* USER CODE BEGIN USB_DEVICE_Init_PreTreatment */ + + /* USER CODE END USB_DEVICE_Init_PreTreatment */ + /* Init Device Library,Add Supported Class and Start the library*/ USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS); @@ -70,6 +74,9 @@ void MX_USB_DEVICE_Init(void) USBD_Start(&hUsbDeviceFS); + /* USER CODE BEGIN USB_DEVICE_Init_PostTreatment */ + + /* USER CODE END USB_DEVICE_Init_PostTreatment */ } /** * @} diff --git a/Firmware/Src/usbd_cdc_if.c b/Firmware/Src/usbd_cdc_if.c index 09b2fc81d..8f6b7317e 100644 --- a/Firmware/Src/usbd_cdc_if.c +++ b/Firmware/Src/usbd_cdc_if.c @@ -50,7 +50,7 @@ #include "usbd_cdc_if.h" /* USER CODE BEGIN INCLUDE */ #include "utils.h" -#include "low_level.h" +#include "commands.h" /* USER CODE END INCLUDE */ /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY @@ -268,14 +268,14 @@ static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length) static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len) { /* USER CODE BEGIN 6 */ - USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]); - USBD_CDC_ReceivePacket(&hUsbDeviceFS); - //Append null termination at end of string - int null_idx = MACRO_MIN(*Len, APP_RX_DATA_SIZE-1); - Buf[null_idx] = 0; + int modified_len = MACRO_MIN(*Len+1, APP_RX_DATA_SIZE); + Buf[modified_len-1] = 0; + + motor_parse_cmd(Buf, modified_len, SERIAL_PRINTF_IS_USB); - motor_parse_cmd(Buf, *Len); + // Allow next packet + USBD_CDC_ReceivePacket(&hUsbDeviceFS); return (USBD_OK); /* USER CODE END 6 */ @@ -296,11 +296,18 @@ uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len) { uint8_t result = USBD_OK; /* USER CODE BEGIN 7 */ - USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData; - if (hcdc->TxState != 0){ + + //Check length + if (Len > APP_TX_DATA_SIZE) + return USBD_FAIL; + // Check for ongoing transmission + USBD_CDC_HandleTypeDef* hcdc = (USBD_CDC_HandleTypeDef*) hUsbDeviceFS.pClassData; + if (hcdc->TxState != 0) return USBD_BUSY; - } - USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len); + // memcpy Buf into UserTxBufferFS + memcpy(UserTxBufferFS, Buf, Len); + // Update Len + USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBufferFS, Len); result = USBD_CDC_TransmitPacket(&hUsbDeviceFS); /* USER CODE END 7 */ return result; diff --git a/Firmware/Src/usbd_desc.c b/Firmware/Src/usbd_desc.c index 7c8549e5e..bd00de9a5 100644 --- a/Firmware/Src/usbd_desc.c +++ b/Firmware/Src/usbd_desc.c @@ -75,7 +75,7 @@ #define USBD_LANGID_STRING 1033 #define USBD_MANUFACTURER_STRING "ODrive" #define USBD_PID_FS 0x0D31 -#define USBD_PRODUCT_STRING_FS "ODrive rev 3.1" +#define USBD_PRODUCT_STRING_FS "ODrive v3.1" #define USBD_SERIALNUMBER_STRING_FS "000000000001" #define USBD_CONFIGURATION_STRING_FS "CDC Config" #define USBD_INTERFACE_STRING_FS "CDC Interface" diff --git a/Firmware/startup/startup_stm32f405xx.s b/Firmware/startup/startup_stm32f405xx.s index bd9ace651..3876f1c13 100644 --- a/Firmware/startup/startup_stm32f405xx.s +++ b/Firmware/startup/startup_stm32f405xx.s @@ -2,8 +2,8 @@ ****************************************************************************** * @file startup_stm32f405xx.s * @author MCD Application Team - * @version V2.6.0 - * @date 04-November-2016 + * @version V2.6.1 + * @date 14-February-2017 * @brief STM32F405xx Devices vector table for GCC based toolchains. * This module performs: * - Set the initial SP @@ -16,7 +16,7 @@ ****************************************************************************** * @attention * - *

© COPYRIGHT 2016 STMicroelectronics

+ *

© COPYRIGHT 2017 STMicroelectronics

* * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/Firmware/tools/.gitignore b/Firmware/tools/.gitignore deleted file mode 100644 index 9886e1ed4..000000000 --- a/Firmware/tools/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.py[cod] diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 9eeab46be..000000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2016 Oskar Weigl (madcowswe) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/README.md b/README.md index 2e062f062..9ed8752cc 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ The startup procedure is demonstrated [here](https://www.youtube.com/watch?v=VCX Note: 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. Also note that in the video, the motors spin after initalisation, but in the current software the default behaviour is to do position control to position 0 (i.e. the position at startup) ### Sending commands -Sending USB and UART commands is documented [here].(Firmware/README.md#communicating-over-usb-and-uart) +Sending USB and UART commands is documented [here](Firmware/README.md#communicating-over-usb-and-uart). You can also have a look at the [ODrive Arduino library](https://github.com/madcowswe/ODriveArduino) that makes it easy to use the UART interface on Arduino. You can also look at it as an implementation example of how to talk to the ODrive over UART. ### Setting up UART Baud rate: 115200 diff --git a/analysis/cogging_torque/cogging_harmonics.py b/analysis/cogging_torque/cogging_harmonics.py new file mode 100644 index 000000000..3b9805961 --- /dev/null +++ b/analysis/cogging_torque/cogging_harmonics.py @@ -0,0 +1,52 @@ + +import numpy as np +import matplotlib.pyplot as plt + +encoder_cpr = 2400 +stator_slots = 12 +pole_pairs = 7 + +N = data.size +fft = np.fft.rfft(data) +freq = np.fft.rfftfreq(N, d=1./encoder_cpr) + +harmonics = [0] +harmonics += [(i+1)*stator_slots for i in range(pole_pairs)] +harmonics += [pole_pairs] +harmonics += [(i+1)*2*pole_pairs for i in range(int(stator_slots/4))] + + +fft_sparse = fft.copy() +indicies = np.arange(fft_sparse.size) +mask = [i not in harmonics for i in indicies] +fft_sparse[mask] = 0.0 +interp_data = np.fft.irfft(fft_sparse) + +#%% + +#plt.figure() +plt.subplot(3, 1, 1) +plt.plot(data, label='raw') +plt.plot(interp_data, label='selected harmonics IFFT') +plt.title('cogging map') +plt.xlabel('counts') +plt.ylabel('A') +plt.legend(loc='best') + +#plt.figure() +plt.subplot(3, 1, 2) +plt.stem(freq, np.abs(fft)/N, label='raw') +plt.stem(freq[harmonics], np.abs(fft_sparse[harmonics])/N, markerfmt='ro', label='selected harmonics') +plt.title('cogging map spectrum') +plt.xlabel('cycles/turn') +plt.ylabel('A') +plt.legend(loc='best') + +#plt.figure() +plt.subplot(3, 1, 3) +plt.stem(freq, np.abs(fft)/N, label='raw') +plt.stem(freq[harmonics], np.abs(fft_sparse[harmonics])/N, markerfmt='ro', label='selected harmonics') +plt.title('cogging map spectrum') +plt.xlabel('cycles/turn') +plt.ylabel('A') +plt.legend(loc='best') \ No newline at end of file diff --git a/motor_analysis/350kvTP.PNG b/analysis/motor_analysis/350kvTP.PNG similarity index 100% rename from motor_analysis/350kvTP.PNG rename to analysis/motor_analysis/350kvTP.PNG diff --git a/motor_analysis/350kvVelli.PNG b/analysis/motor_analysis/350kvVelli.PNG similarity index 100% rename from motor_analysis/350kvVelli.PNG rename to analysis/motor_analysis/350kvVelli.PNG diff --git a/motor_analysis/VelliPlot.m b/analysis/motor_analysis/VelliPlot.m similarity index 100% rename from motor_analysis/VelliPlot.m rename to analysis/motor_analysis/VelliPlot.m diff --git a/numeric_path_opt/Main.m b/analysis/numeric_path_opt/Main.m similarity index 100% rename from numeric_path_opt/Main.m rename to analysis/numeric_path_opt/Main.m diff --git a/numeric_path_opt/predictionmatrices.m b/analysis/numeric_path_opt/predictionmatrices.m similarity index 100% rename from numeric_path_opt/predictionmatrices.m rename to analysis/numeric_path_opt/predictionmatrices.m diff --git a/Firmware/tools/odrive/__init__.py b/tools/odrive/__init__.py similarity index 100% rename from Firmware/tools/odrive/__init__.py rename to tools/odrive/__init__.py diff --git a/Firmware/tools/odrive/usbbulk.py b/tools/odrive/usbbulk.py similarity index 97% rename from Firmware/tools/odrive/usbbulk.py rename to tools/odrive/usbbulk.py index e2c2d66c9..cdda7641d 100644 --- a/Firmware/tools/odrive/usbbulk.py +++ b/tools/odrive/usbbulk.py @@ -108,9 +108,9 @@ def send(self, usbBuffer): #return -1 raise - def recieve(self, bufferLen): + def receive(self, bufferLen): try: - ret = self.epr.read(bufferLen, 0) + ret = self.epr.read(bufferLen, 100) return ret except usb.core.USBError: #return -1 @@ -119,5 +119,5 @@ def recieve(self, bufferLen): def send_max(self): return 64 - def recieve_max(self): + def receive_max(self): return 64 diff --git a/Firmware/tools/odrive/util.py b/tools/odrive/util.py similarity index 100% rename from Firmware/tools/odrive/util.py rename to tools/odrive/util.py diff --git a/Firmware/tools/test_bulk.py b/tools/test_communication.py similarity index 81% rename from Firmware/tools/test_bulk.py rename to tools/test_communication.py index 6b348f435..0a24fef18 100644 --- a/Firmware/tools/test_bulk.py +++ b/tools/test_communication.py @@ -26,28 +26,35 @@ def main(args): print("\tPOSITION_CONTROL:\n\t\tp MOTOR_NUMBER POSITION VELOCITY CURRENT") print("\tVELOCITY_CONTROL:\n\t\tv MOTOR_NUMBER VELOCITY CURRENT") print("\tCURRENT_CONTROL:\n\t\tc MOTOR_NUMBER CURRENT") + print("\tHALT:\n\t\th") + print("\tQuit Python Script:\n\t\tq") print("---------------------------------------------------------------------") # query device dev = usbbulk.poll_odrive_bulk_device(printer=print) print (dev.info()) print (dev.init()) # thread - thread = threading.Thread(target=recieve_thread, args=[dev]) + thread = threading.Thread(target=receive_thread, args=[dev]) thread.start() while running: time.sleep(0.1) try: command = input("Enter ODrive command:\n") - dev.send(command) + if 'q' in command: + running = False + sys.exit() + else: + dev.send(command) except: running = False -def recieve_thread(dev): +def receive_thread(dev): global ready + while running: time.sleep(0.1) try: - message = dev.recieve(dev.recieve_max()) + message = dev.receive(dev.receive_max()) message_ascii = bytes(message).decode('ascii') print(message_ascii, end='') if "ODrive Firmware" in message_ascii: diff --git a/various/path.c b/various/path.c deleted file mode 100644 index 341e5c4b7..000000000 --- a/various/path.c +++ /dev/null @@ -1,47 +0,0 @@ -#include - -#include - -void output(float x, float y, float str, float param) { - printf("{ %05.1ff, %05.1ff, %1.1ff, %06.1ff },\n", (x+1)*75, (y+1)*75, str, param); -} - -void searchat(float x, float y) { - output(x, y, 0.4, 500); - //output(x+0.02, y, 0.4, 1000); - //output(x, y+0.02, 0.4, 1000); - //output(x-0.02, y, 0.4, 1000); - //output(x, y-0.02, 0.4, 1000); -} - -void pickupto(float x, float y) { - output(x, y, 0.4, 0); - //output(x, y, 0.4, 1000); - output(x, y, 0, 1000); -} - -void moveto(float x, float y) { - output(x, y, 0, 0); -} - -#define POINTS 15 -#define TWOPI (3.1415*2.0) - -int main(int argc, char** argv) { - moveto(-1,-1); - - for (int j=0; j<2; j++) - for (int i=0; i