From 014029c649f4ac28075921c0ebd567292c0c8f1c Mon Sep 17 00:00:00 2001 From: raiden00pl Date: Sat, 18 Nov 2023 10:37:10 +0100 Subject: [PATCH] boards: add support for ODrive V3.6 board --- .../applications/examples/foc/index.rst | 2 - .../arm/stm32f4/boards/odrive36/index.rst | 97 ++ boards/Kconfig | 12 + boards/arm/stm32/odrive36/CMakeLists.txt | 21 + boards/arm/stm32/odrive36/Kconfig | 48 + .../arm/stm32/odrive36/configs/nsh/defconfig | 44 + .../stm32/odrive36/configs/usbnsh/defconfig | 56 + boards/arm/stm32/odrive36/include/board.h | 210 ++++ boards/arm/stm32/odrive36/scripts/Make.defs | 40 + boards/arm/stm32/odrive36/scripts/ld.script | 123 +++ boards/arm/stm32/odrive36/src/CMakeLists.txt | 41 + boards/arm/stm32/odrive36/src/Make.defs | 43 + boards/arm/stm32/odrive36/src/odrive.h | 155 +++ boards/arm/stm32/odrive36/src/stm32_appinit.c | 71 ++ boards/arm/stm32/odrive36/src/stm32_boot.c | 105 ++ boards/arm/stm32/odrive36/src/stm32_bringup.c | 141 +++ boards/arm/stm32/odrive36/src/stm32_foc.c | 962 ++++++++++++++++++ boards/arm/stm32/odrive36/src/stm32_spi.c | 196 ++++ boards/arm/stm32/odrive36/src/stm32_usb.c | 103 ++ 19 files changed, 2468 insertions(+), 2 deletions(-) create mode 100644 Documentation/platforms/arm/stm32f4/boards/odrive36/index.rst create mode 100644 boards/arm/stm32/odrive36/CMakeLists.txt create mode 100644 boards/arm/stm32/odrive36/Kconfig create mode 100644 boards/arm/stm32/odrive36/configs/nsh/defconfig create mode 100644 boards/arm/stm32/odrive36/configs/usbnsh/defconfig create mode 100644 boards/arm/stm32/odrive36/include/board.h create mode 100644 boards/arm/stm32/odrive36/scripts/Make.defs create mode 100644 boards/arm/stm32/odrive36/scripts/ld.script create mode 100644 boards/arm/stm32/odrive36/src/CMakeLists.txt create mode 100644 boards/arm/stm32/odrive36/src/Make.defs create mode 100644 boards/arm/stm32/odrive36/src/odrive.h create mode 100644 boards/arm/stm32/odrive36/src/stm32_appinit.c create mode 100644 boards/arm/stm32/odrive36/src/stm32_boot.c create mode 100644 boards/arm/stm32/odrive36/src/stm32_bringup.c create mode 100644 boards/arm/stm32/odrive36/src/stm32_foc.c create mode 100644 boards/arm/stm32/odrive36/src/stm32_spi.c create mode 100644 boards/arm/stm32/odrive36/src/stm32_usb.c diff --git a/Documentation/applications/examples/foc/index.rst b/Documentation/applications/examples/foc/index.rst index 1ddc2e5835..995a19af6d 100644 --- a/Documentation/applications/examples/foc/index.rst +++ b/Documentation/applications/examples/foc/index.rst @@ -57,7 +57,6 @@ f_PWM f_notifier ccb Kp Ki 20kHz 10kHz 1000 0.0087 0.0025 ====== =========== ===== ======== ====== - * Linix 45ZWN24-40 (PMSM motor dedicated for NXP FRDM-MC-LVMTR kit) ====== =========== ===== ======== ====== @@ -74,7 +73,6 @@ f_PWM f_notifier ccb Kp Ki 20kHz 10kHz 200 0.036 0.022 ====== =========== ===== ======== ====== - * iPower GBM2804H-100T (gimbal motor provided with the ST P-NUCLEO-IHM03 kit) ====== =========== ===== ======== ====== diff --git a/Documentation/platforms/arm/stm32f4/boards/odrive36/index.rst b/Documentation/platforms/arm/stm32f4/boards/odrive36/index.rst new file mode 100644 index 0000000000..bd6d8817be --- /dev/null +++ b/Documentation/platforms/arm/stm32f4/boards/odrive36/index.rst @@ -0,0 +1,97 @@ +=========== +ODrive V3.6 +=========== + +ODrive V3.6 is an open-source dual-motor FOC controller based on +the STMicro STM32F405RG and TI DRV8301 gate drivers. + +See https://odriverobotics.com/shop/odrive-v36 for further information. + +For now we support only ODrive V3.6 56V. + +Pin configuration +================= + +========= ============== ========= ======================= +Board Pin Chip Function Chip Pin Notes +========= ============== ========= ======================= +GPIO_1 PA0 +GPIO_2 PA1 +GPIO_3 USART2_TX PA2 Serial TX +GPIO_4 USART2_RX PA3 Serial RX +M1_TEMP ADC1_IN4 PA4 +AUX_TEMP ADC1_IN5 PA5 +VBUS_S ADC1_IN6 PA6 +M1_AL TIM8 CH1N PA7 +M0_AH TIM1 CH1 PA8 +M0_BH TIM1 CH2 PA9 +M0_CH TIM1 CH3 PA10 +USB_DM USB DM PA11 +USB_DP USB DP PA12 +SWDIO PA13 +SWCLK PA14 +GPIO_7 PA15 +M0_SO1 ADC2_IN10 PC0 M0 current 1 +M0_SO2 ADC2_IN11 PC1 M0 current 2 +M1_SO2 ADC3_IN12 PC2 M1 current 2 +M1_SO1 ADC3_IN13 PC3 M1 current 1 +GPIO_5 PC4 +M0_TEMP ADC1_IN15 PC5 +M1_AH TIM8 CH1 PC6 +M1_BH TIM8 CH2 PC7 +M1_CH TIM8 CH3 PC8 +M0_ENC_Z PC9 +SPI_SCK SPI3_SCK PC10 DRV8301 M0/M1 +SPI_MISO SPI3_MISO PC11 DRV8301 M0/M1 +SPI_MOSI SPI3_MOSI PC12 DRV8301 M0/M1 +M0_NCS SPI CS PC13 DRV8301 M0 CS +M1_NCS SPI CS PC14 DRV8301 M1 CS +M1_ENC_Z PC15 +M1_BL TIM8 CH2N PB0 +M1_CL TIM8 CH3N PB1 +GPIO_6 PB2 +GPIO_8 PB3 +M0_ENC_A TIM3_CH1IN_2 PB4 +M0_ENC_B TIM3_CH2IN_2 PB5 +M1_ENC_A TIM4_CH1IN_1 PB6 +M1_ENC_B TIM4_CH2IN_1 PB7 +CAN_R CAN_R PB8 +CAN_D CAN_D PB9 +AUX_L PB10 +AUX_H PB11 +EN_GATE OUT PB12 M0/M1 DRV8301 +M0_AL TIM1 CH1N PB13 +M0_BL TIM1 CH2N PB14 +M0_CL TIM1 CH3N PB15 +N_FAULT PD2 M0/M1 DRV8301 N_FAULT +========= ============== ========= ======================= + +Board hardware configuration +============================ + +=========================== ================== +Current shunt resistance 0.0005 +Current sense gain 10/20/40/80 +Vbus min 12V +Vbus max 24V or 56V +Iout max 40A (no cooling for MOSFETs) +IPHASE_RATIO 1/(R_shunt*gain) +VBUS_RATIO = 1/VBUS_gain 11 or 19 +=========================== ================== + +Configurations +============== + +nsh +--- + +Configures the NuttShell (nsh) located at apps/examples/nsh. The +Configuration enables the serial interfaces on USART2. Support for +builtin applications is enabled, but in the base configuration no +builtin applications are selected. + +usbnsh +------ + +This is another NSH example. If differs from other 'nsh' configurations +in that this configurations uses a USB serial device for console I/O. diff --git a/boards/Kconfig b/boards/Kconfig index ccc24e665e..24417ad78b 100644 --- a/boards/Kconfig +++ b/boards/Kconfig @@ -1270,6 +1270,14 @@ config ARCH_BOARD_OLIMEX_STRP711 further information. STATUS: Configurations for the basic OS test and NSH are complete and verified. +config ARCH_BOARD_ODRIVE36 + bool "Odrive V3.6 board" + depends on ARCH_CHIP_STM32F405RG + ---help--- + This port uses the ODrive3.6 board. This is an open-source dual-motor + FOC controller based on the STMicro STM32F405RG and TI DRV8301 gate drivers. + See https://odriverobotics.com/shop/odrive-v36 for further information. + config ARCH_BOARD_OLIMEX_STM32H405 bool "Olimex STM32 H405 board" depends on ARCH_CHIP_STM32F405RG @@ -3198,6 +3206,7 @@ config ARCH_BOARD default "olimex-stm32-p207" if ARCH_BOARD_OLIMEX_STM32P207 default "olimex-stm32-p407" if ARCH_BOARD_OLIMEX_STM32P407 default "olimex-strp711" if ARCH_BOARD_OLIMEX_STRP711 + default "odrive36" if ARCH_BOARD_ODRIVE36 default "olimexino-stm32" if ARCH_BOARD_OLIMEXINO_STM32 default "omnibusf4" if ARCH_BOARD_OMNIBUSF4 default "open1788" if ARCH_BOARD_OPEN1788 @@ -3892,6 +3901,9 @@ endif if ARCH_BOARD_NUCLEO_L152RE source "boards/arm/stm32/nucleo-l152re/Kconfig" endif +if ARCH_BOARD_ODRIVE36 +source "boards/arm/stm32/odrive36/Kconfig" +endif if ARCH_BOARD_OLIMEX_STM32E407 source "boards/arm/stm32/olimex-stm32-e407/Kconfig" endif diff --git a/boards/arm/stm32/odrive36/CMakeLists.txt b/boards/arm/stm32/odrive36/CMakeLists.txt new file mode 100644 index 0000000000..9373cc6d3a --- /dev/null +++ b/boards/arm/stm32/odrive36/CMakeLists.txt @@ -0,0 +1,21 @@ +# ############################################################################## +# boards/arm/stm32/odrive36/CMakeLists.txt +# +# Licensed to the Apache Software Foundation (ASF) under one or more contributor +# license agreements. See the NOTICE file distributed with this work for +# additional information regarding copyright ownership. The ASF licenses this +# file to you under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +# +# ############################################################################## + +add_subdirectory(src) diff --git a/boards/arm/stm32/odrive36/Kconfig b/boards/arm/stm32/odrive36/Kconfig new file mode 100644 index 0000000000..42bd303046 --- /dev/null +++ b/boards/arm/stm32/odrive36/Kconfig @@ -0,0 +1,48 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +if ARCH_BOARD_ODRIVE36 + +choice + prompt "ODrive voltage version" + default ODRIVE_HW_VOLTAGE_56 + +config ODRIVE_HW_VOLTAGE_56 + bool "ODrive 56V version" + +config ODRIVE_HW_VOLTAGE_24 + bool "ODrive 24V version" + +endchoice # ODrive voltage version + +if MOTOR_FOC + +config ODRIVE_FOC_FOC0 + bool "ODrive enable support for FOC device 0" + default y + +if ODRIVE_FOC_FOC0 + +endif # ODRIVE_FOC_FOC0 + +config ODRIVE_FOC_FOC1 + bool "ODrive enable support for FOC device 1" + default y + +if ODRIVE_FOC_FOC1 + +endif # ODRIVE_FOC_FOC1 + +config ODRIVE_FOC_VBUS + bool "ODrive VBUS ADC support" + default n + +config ODRIVE_FOC_TEMP + bool "ODrive Temperature ADC support" + default n + +endif # MOTOR_FOC + +endif # ARCH_BOARD_ODRIVE diff --git a/boards/arm/stm32/odrive36/configs/nsh/defconfig b/boards/arm/stm32/odrive36/configs/nsh/defconfig new file mode 100644 index 0000000000..4078bf8976 --- /dev/null +++ b/boards/arm/stm32/odrive36/configs/nsh/defconfig @@ -0,0 +1,44 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_FPU is not set +# CONFIG_NSH_ARGCAT is not set +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +# CONFIG_STM32_USE_LEGACY_PINMAP is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="odrive36" +CONFIG_ARCH_BOARD_ODRIVE36=y +CONFIG_ARCH_CHIP="stm32" +CONFIG_ARCH_CHIP_STM32=y +CONFIG_ARCH_CHIP_STM32F405RG=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARD_LATE_INITIALIZE=y +CONFIG_BOARD_LOOPSPERMSEC=15272 +CONFIG_BUILTIN=y +CONFIG_EXAMPLES_HELLO=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_MM_REGIONS=2 +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=114688 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=6 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2011 +CONFIG_STM32_JTAG_SW_ENABLE=y +CONFIG_STM32_USART2=y +CONFIG_SYSTEM_NSH=y +CONFIG_USART2_SERIAL_CONSOLE=y diff --git a/boards/arm/stm32/odrive36/configs/usbnsh/defconfig b/boards/arm/stm32/odrive36/configs/usbnsh/defconfig new file mode 100644 index 0000000000..f96716467e --- /dev/null +++ b/boards/arm/stm32/odrive36/configs/usbnsh/defconfig @@ -0,0 +1,56 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_FPU is not set +# CONFIG_DEV_CONSOLE is not set +# CONFIG_STM32_USE_LEGACY_PINMAP is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="odrive36" +CONFIG_ARCH_BOARD_ODRIVE36=y +CONFIG_ARCH_CHIP="stm32" +CONFIG_ARCH_CHIP_STM32=y +CONFIG_ARCH_CHIP_STM32F405RG=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARDCTL_USBDEVCTRL=y +CONFIG_BOARD_LOOPSPERMSEC=15272 +CONFIG_BUILTIN=y +CONFIG_CDCACM=y +CONFIG_CDCACM_CONSOLE=y +CONFIG_CDCACM_RXBUFSIZE=256 +CONFIG_CDCACM_TXBUFSIZE=256 +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_EXAMPLES_HELLO=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_MM_REGIONS=2 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAMLOG=y +CONFIG_RAMLOG_BUFSIZE=4096 +CONFIG_RAMLOG_SYSLOG=y +CONFIG_RAM_SIZE=114688 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_STACK_COLORATION=y +CONFIG_START_DAY=27 +CONFIG_START_YEAR=2013 +CONFIG_STM32_JTAG_SW_ENABLE=y +CONFIG_STM32_OTGFS=y +CONFIG_STM32_PWR=y +CONFIG_STM32_USART2=y +CONFIG_SYSTEM_NSH=y +CONFIG_USBDEV=y diff --git a/boards/arm/stm32/odrive36/include/board.h b/boards/arm/stm32/odrive36/include/board.h new file mode 100644 index 0000000000..6c6eaf7ee4 --- /dev/null +++ b/boards/arm/stm32/odrive36/include/board.h @@ -0,0 +1,210 @@ +/**************************************************************************** + * boards/arm/stm32/odrive36/include/board.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __BOARDS_ARM_STM32_ODRIVE36_INCLUDE_BOARD_H +#define __BOARDS_ARM_STM32_ODRIVE36_INCLUDE_BOARD_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef __ASSEMBLY__ +# include +#endif +#include "stm32_rcc.h" +#include "stm32.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Clocking *****************************************************************/ + +/* HSI - 16 MHz RC factory-trimmed + * LSI - 32 KHz RC (30-60KHz, uncalibrated) + * HSE - On-board crystal frequency is 8MHz + * LSE - 32.768 kHz + */ + +#define STM32_BOARD_XTAL 8000000ul + +#define STM32_HSI_FREQUENCY 16000000ul +#define STM32_LSI_FREQUENCY 32000 +#define STM32_HSE_FREQUENCY STM32_BOARD_XTAL +#define STM32_LSE_FREQUENCY 32768 + +/* Main PLL Configuration. + * + * PLL source is HSE + * PLL_VCO = (STM32_HSE_FREQUENCY / PLLM) * PLLN + * = (8,000,000 / 8) * 336 + * = 336,000,000 + * SYSCLK = PLL_VCO / PLLP + * = 336,000,000 / 2 = 168,000,000 + * USB OTG FS, SDIO and RNG Clock + * = PLL_VCO / PLLQ + * = 48,000,000 + */ + +#define STM32_PLLCFG_PLLM RCC_PLLCFG_PLLM(8) +#define STM32_PLLCFG_PLLN RCC_PLLCFG_PLLN(336) +#define STM32_PLLCFG_PLLP RCC_PLLCFG_PLLP_2 +#define STM32_PLLCFG_PLLQ RCC_PLLCFG_PLLQ(7) + +#define STM32_SYSCLK_FREQUENCY 168000000ul + +/* AHB clock (HCLK) is SYSCLK (168MHz) */ + +#define STM32_RCC_CFGR_HPRE RCC_CFGR_HPRE_SYSCLK /* HCLK = SYSCLK / 1 */ +#define STM32_HCLK_FREQUENCY STM32_SYSCLK_FREQUENCY + +/* APB1 clock (PCLK1) is HCLK/4 (42MHz) */ + +#define STM32_RCC_CFGR_PPRE1 RCC_CFGR_PPRE1_HCLKd4 /* PCLK1 = HCLK / 4 */ +#define STM32_PCLK1_FREQUENCY (STM32_HCLK_FREQUENCY/4) + +/* Timers driven from APB1 will be twice PCLK1 */ + +#define STM32_APB1_TIM2_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM3_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM4_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM5_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM6_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM7_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM12_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM13_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM14_CLKIN (2*STM32_PCLK1_FREQUENCY) + +/* APB2 clock (PCLK2) is HCLK/2 (84MHz) */ + +#define STM32_RCC_CFGR_PPRE2 RCC_CFGR_PPRE2_HCLKd2 /* PCLK2 = HCLK / 2 */ +#define STM32_PCLK2_FREQUENCY (STM32_HCLK_FREQUENCY/2) + +/* Timers driven from APB2 will be twice PCLK2 */ + +#define STM32_APB2_TIM1_CLKIN (2*STM32_PCLK2_FREQUENCY) +#define STM32_APB2_TIM8_CLKIN (2*STM32_PCLK2_FREQUENCY) +#define STM32_APB2_TIM9_CLKIN (2*STM32_PCLK2_FREQUENCY) +#define STM32_APB2_TIM10_CLKIN (2*STM32_PCLK2_FREQUENCY) +#define STM32_APB2_TIM11_CLKIN (2*STM32_PCLK2_FREQUENCY) + +/* Timer Frequencies, if APBx is set to 1, frequency is same to APBx + * otherwise frequency is 2xAPBx. + * Note: TIM1,8 are on APB2, others on APB1 + */ + +#define BOARD_TIM1_FREQUENCY STM32_HCLK_FREQUENCY +#define BOARD_TIM2_FREQUENCY (STM32_HCLK_FREQUENCY / 2) +#define BOARD_TIM3_FREQUENCY (STM32_HCLK_FREQUENCY / 2) +#define BOARD_TIM4_FREQUENCY (STM32_HCLK_FREQUENCY / 2) +#define BOARD_TIM5_FREQUENCY (STM32_HCLK_FREQUENCY / 2) +#define BOARD_TIM6_FREQUENCY (STM32_HCLK_FREQUENCY / 2) +#define BOARD_TIM7_FREQUENCY (STM32_HCLK_FREQUENCY / 2) +#define BOARD_TIM8_FREQUENCY STM32_HCLK_FREQUENCY + +/* DMA Channel/Stream Selections ********************************************/ + +/* ADC 1 */ + +#define ADC1_DMA_CHAN DMAMAP_ADC1_1 + +/* Alternate function pin selections ****************************************/ + +/* ADC */ + +#define GPIO_ADC1_IN4 GPIO_ADC1_IN4_0 +#define GPIO_ADC1_IN5 GPIO_ADC1_IN5_0 +#define GPIO_ADC1_IN6 GPIO_ADC1_IN6_0 +#define GPIO_ADC1_IN15 GPIO_ADC1_IN15_0 + +#define GPIO_ADC2_IN10 GPIO_ADC2_IN10_0 +#define GPIO_ADC2_IN11 GPIO_ADC2_IN11_0 +#define GPIO_ADC2_IN12 GPIO_ADC2_IN13_0 + +#define GPIO_ADC3_IN12 GPIO_ADC3_IN12_0 +#define GPIO_ADC3_IN13 GPIO_ADC3_IN13_0 + +/* USART2: + * USART2_TX - PA2 - GPIO_3 + * USART2_RX - PA3 - GPIO_4 + */ + +#define GPIO_USART2_RX (GPIO_USART2_RX_1|GPIO_SPEED_100MHz) +#define GPIO_USART2_TX (GPIO_USART2_TX_1|GPIO_SPEED_100MHz) + +/* CAN: + * CAN_R - PB8 + * CAN_T - PB9 + */ + +#define GPIO_CAN1_RX (GPIO_CAN1_RX_2|GPIO_SPEED_50MHz) +#define GPIO_CAN1_TX (GPIO_CAN1_TX_2|GPIO_SPEED_50MHz) + +/* SPI3 - connected to DRV8301 + * SPI3_SCK - PC10 + * SPI3_MISO - PC11 + * SPI3_MOSI - PC12 + */ + +#define GPIO_SPI3_SCK (GPIO_SPI3_SCK_2|GPIO_SPEED_50MHz) +#define GPIO_SPI3_MISO (GPIO_SPI3_MISO_2|GPIO_SPEED_50MHz) +#define GPIO_SPI3_MOSI (GPIO_SPI3_MOSI_2|GPIO_SPEED_50MHz) + +/* USBDEV */ + +#define GPIO_OTGFS_DM (GPIO_OTGFS_DM_0|GPIO_SPEED_100MHz) +#define GPIO_OTGFS_DP (GPIO_OTGFS_DP_0|GPIO_SPEED_100MHz) +#define GPIO_OTGFS_ID (GPIO_OTGFS_ID_0|GPIO_SPEED_100MHz) + +/* Dual FOC configuration */ + +/* TIM1 configuration *******************************************************/ + +#define GPIO_TIM1_CH1OUT (GPIO_TIM1_CH1OUT_1|GPIO_SPEED_100MHz) /* TIM1 CH1 - PA8 - U high */ +#define GPIO_TIM1_CH1NOUT (GPIO_TIM1_CH1N_2|GPIO_SPEED_100MHz) /* TIM1 CH1N - PB13 - U low */ +#define GPIO_TIM1_CH2OUT (GPIO_TIM1_CH2OUT_1|GPIO_SPEED_100MHz) /* TIM1 CH2 - PA9 - V high */ +#define GPIO_TIM1_CH2NOUT (GPIO_TIM1_CH2N_2|GPIO_SPEED_100MHz) /* TIM1 CH2N - PB14 - V low */ +#define GPIO_TIM1_CH3OUT (GPIO_TIM1_CH3OUT_1|GPIO_SPEED_100MHz) /* TIM1 CH3 - PA10 - W high */ +#define GPIO_TIM1_CH3NOUT (GPIO_TIM1_CH3N_2|GPIO_SPEED_100MHz) /* TIM1 CH3N - PB15 - W low */ +#define GPIO_TIM1_CH4OUT 0 /* not used as output */ + +/* TIM8 configuration *******************************************************/ + +#define GPIO_TIM8_CH1OUT (GPIO_TIM8_CH1OUT_1|GPIO_SPEED_100MHz) /* TIM8 CH1 - PC6 - U high */ +#define GPIO_TIM8_CH1NOUT (GPIO_TIM8_CH1N_2|GPIO_SPEED_100MHz) /* TIM8 CH1N - PA7 - U low */ +#define GPIO_TIM8_CH2OUT (GPIO_TIM8_CH2OUT_1|GPIO_SPEED_100MHz) /* TIM8 CH2 - PC7 - V high */ +#define GPIO_TIM8_CH2NOUT (GPIO_TIM8_CH2N_1|GPIO_SPEED_100MHz) /* TIM8 CH2N - PB0 - V low */ +#define GPIO_TIM8_CH3OUT (GPIO_TIM8_CH3OUT_1|GPIO_SPEED_100MHz) /* TIM8 CH3 - PC8 - W high */ +#define GPIO_TIM8_CH3NOUT (GPIO_TIM8_CH3N_1|GPIO_SPEED_100MHz) /* TIM8 CH3N - PB1 - W low */ +#define GPIO_TIM8_CH4OUT 0 /* not used as output */ + +/* QEN3 configuration *******************************************************/ + +#define GPIO_TIM3_CH1IN (GPIO_TIM3_CH1IN_2|GPIO_SPEED_50MHz) /* TIM3 CH1IN - PB4 */ +#define GPIO_TIM3_CH2IN (GPIO_TIM3_CH2IN_2|GPIO_SPEED_50MHz) /* TIM3 CH2IN - PB5 */ + +/* QEN4 configuration *******************************************************/ + +#define GPIO_TIM4_CH1IN (GPIO_TIM4_CH1IN_1|GPIO_SPEED_50MHz) /* TIM4 CH1IN - PB6 */ +#define GPIO_TIM4_CH2IN (GPIO_TIM4_CH2IN_1|GPIO_SPEED_50MHz) /* TIM4 CH2IN - PB7 */ + +#endif /* __BOARDS_ARM_STM32_ODRIVE36_INCLUDE_BOARD_H */ diff --git a/boards/arm/stm32/odrive36/scripts/Make.defs b/boards/arm/stm32/odrive36/scripts/Make.defs new file mode 100644 index 0000000000..a04f8eea76 --- /dev/null +++ b/boards/arm/stm32/odrive36/scripts/Make.defs @@ -0,0 +1,40 @@ +############################################################################ +# boards/arm/stm32/odrive36/scripts/Make.defs +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include $(TOPDIR)/.config +include $(TOPDIR)/tools/Config.mk +include $(TOPDIR)/arch/arm/src/armv7-m/Toolchain.defs + +LDSCRIPT = ld.script + +ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDSCRIPT) + +ARCHPICFLAGS = -fpic -msingle-pic-base -mpic-register=r10 + +CFLAGS := $(ARCHCFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe +CPICFLAGS = $(ARCHPICFLAGS) $(CFLAGS) +CXXFLAGS := $(ARCHCXXFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe +CXXPICFLAGS = $(ARCHPICFLAGS) $(CXXFLAGS) +CPPFLAGS := $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) +AFLAGS := $(CFLAGS) -D__ASSEMBLY__ + +NXFLATLDFLAGS1 = -r -d -warn-common +NXFLATLDFLAGS2 = $(NXFLATLDFLAGS1) -T$(TOPDIR)/binfmt/libnxflat/gnu-nxflat-pcrel.ld -no-check-sections +LDNXFLATFLAGS = -e main -s 2048 diff --git a/boards/arm/stm32/odrive36/scripts/ld.script b/boards/arm/stm32/odrive36/scripts/ld.script new file mode 100644 index 0000000000..97b35c6685 --- /dev/null +++ b/boards/arm/stm32/odrive36/scripts/ld.script @@ -0,0 +1,123 @@ +/**************************************************************************** + * boards/arm/stm32/odrive36/scripts/ld.script + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* The STM32F405RGT6 has 1024Kb of FLASH beginning at address 0x0800:0000 and + * 192Kb of SRAM. SRAM is split up into two blocks: + * + * 1) 112Kb of SRAM beginning at address 0x2000:0000 + * 2) 16Kb of SRAM beginning at address 0x2001:c000 + * 3) 64Kb of SRAM beginning at address 0x2002:0000 + * + * When booting from FLASH, FLASH memory is aliased to address 0x0000:0000 + * where the code expects to begin execution by jumping to the entry point in + * the 0x0800:0000 address + * range. + */ + +MEMORY +{ + flash (rx) : ORIGIN = 0x08000000, LENGTH = 1024K + sram (rwx) : ORIGIN = 0x20000000, LENGTH = 112K +} + +OUTPUT_ARCH(arm) +EXTERN(_vectors) +ENTRY(_stext) +SECTIONS +{ + .text : { + _stext = ABSOLUTE(.); + *(.vectors) + *(.text .text.*) + *(.fixup) + *(.gnu.warning) + *(.rodata .rodata.*) + *(.gnu.linkonce.t.*) + *(.glue_7) + *(.glue_7t) + *(.got) + *(.gcc_except_table) + *(.gnu.linkonce.r.*) + _etext = ABSOLUTE(.); + } > flash + + .init_section : ALIGN(4) { + _sinit = ABSOLUTE(.); + KEEP(*(.init_array .init_array.*)) + _einit = ABSOLUTE(.); + } > flash + + .ARM.extab : ALIGN(4) { + *(.ARM.extab*) + } > flash + + .ARM.exidx : ALIGN(4) { + __exidx_start = ABSOLUTE(.); + *(.ARM.exidx*) + __exidx_end = ABSOLUTE(.); + } > flash + + .tdata : { + _stdata = ABSOLUTE(.); + *(.tdata .tdata.* .gnu.linkonce.td.*); + _etdata = ABSOLUTE(.); + } > flash + + .tbss : { + _stbss = ABSOLUTE(.); + *(.tbss .tbss.* .gnu.linkonce.tb.* .tcommon); + _etbss = ABSOLUTE(.); + } > flash + + _eronly = ABSOLUTE(.); + + .data : ALIGN(4) { + _sdata = ABSOLUTE(.); + *(.data .data.*) + *(.gnu.linkonce.d.*) + CONSTRUCTORS + . = ALIGN(4); + _edata = ABSOLUTE(.); + } > sram AT > flash + + .bss : ALIGN(4) { + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _ebss = ABSOLUTE(.); + } > sram + + /* Stabs debugging sections. */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/boards/arm/stm32/odrive36/src/CMakeLists.txt b/boards/arm/stm32/odrive36/src/CMakeLists.txt new file mode 100644 index 0000000000..bc726e4f3e --- /dev/null +++ b/boards/arm/stm32/odrive36/src/CMakeLists.txt @@ -0,0 +1,41 @@ +# ############################################################################## +# boards/arm/stm32/odrive36/src/CMakeLists.txt +# +# Licensed to the Apache Software Foundation (ASF) under one or more contributor +# license agreements. See the NOTICE file distributed with this work for +# additional information regarding copyright ownership. The ASF licenses this +# file to you under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +# +# ############################################################################## + +set(SRCS stm32_boot.c stm32_bringup.c) + +if(CONFIG_STM32_SPI) + list(APPEND SRCS stm32_spi.c) +endif() + +if(CONFIG_BOARDCTL) + list(APPEND SRCS stm32_appinit.c) +endif() + +if(CONFIG_STM32_FOC) + list(APPEND SRCS stm32_foc.c) +endif() + +if(CONFIG_STM32_OTGFS) + list(APPEND SRCS stm32_usb.c) +endif() + +target_sources(board PRIVATE ${SRCS}) + +set_property(GLOBAL PROPERTY LD_SCRIPT "${NUTTX_BOARD_DIR}/scripts/ld.script") diff --git a/boards/arm/stm32/odrive36/src/Make.defs b/boards/arm/stm32/odrive36/src/Make.defs new file mode 100644 index 0000000000..ce00b63072 --- /dev/null +++ b/boards/arm/stm32/odrive36/src/Make.defs @@ -0,0 +1,43 @@ +############################################################################ +# boards/arm/stm32/odrive36/src/Make.defs +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include $(TOPDIR)/Make.defs + +CSRCS = stm32_boot.c stm32_bringup.c + +ifeq ($(CONFIG_STM32_SPI),y) +CSRCS += stm32_spi.c +endif + +ifeq ($(CONFIG_BOARDCTL),y) +CSRCS += stm32_appinit.c +endif + +ifeq ($(CONFIG_STM32_FOC),y) +CSRCS += stm32_foc.c +endif + +ifeq ($(CONFIG_STM32_OTGFS),y) +CSRCS += stm32_usb.c +endif + +DEPPATH += --dep-path board +VPATH += :board +CFLAGS += $(shell $(INCDIR) "$(CC)" $(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src$(DELIM)board$(DELIM)board) \ No newline at end of file diff --git a/boards/arm/stm32/odrive36/src/odrive.h b/boards/arm/stm32/odrive36/src/odrive.h new file mode 100644 index 0000000000..ec0440ff6c --- /dev/null +++ b/boards/arm/stm32/odrive36/src/odrive.h @@ -0,0 +1,155 @@ +/**************************************************************************** + * boards/arm/stm32/odrive36/src/odrive.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __BOARDS_ARM_STM32_ODRIVE36_SRC_ODRIVE_H +#define __BOARDS_ARM_STM32_ODRIVE36_SRC_ODRIVE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* procfs File System */ + +#ifdef CONFIG_FS_PROCFS +# ifdef CONFIG_NSH_PROC_MOUNTPOINT +# define STM32_PROCFS_MOUNTPOINT CONFIG_NSH_PROC_MOUNTPOINT +# else +# define STM32_PROCFS_MOUNTPOINT "/proc" +# endif +#endif + +/* DRV8301 pins */ + +#define GPIO_DRV8301_ENGATE (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_50MHz| \ + GPIO_OUTPUT_CLEAR|GPIO_PORTB|GPIO_PIN12) +#define GPIO_DRV8301_NFAULT (GPIO_INPUT|GPIO_FLOAT|GPIO_EXTI|GPIO_PORTD| \ + GPIO_PIN2) + +/* SPI chip selects */ + +#define GPIO_GATEDRV0_CS (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_50MHz| \ + GPIO_OUTPUT_SET|GPIO_PORTC|GPIO_PIN13) +#define GPIO_GATEDRV1_CS (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_50MHz| \ + GPIO_OUTPUT_SET|GPIO_PORTC|GPIO_PIN14) + +/* QE index pins */ + +#define GPIO_QE3_INDEX (GPIO_INPUT | GPIO_FLOAT | \ + GPIO_EXTI | GPIO_PORTC | GPIO_PIN9) +#define GPIO_QE4_INDEX (GPIO_INPUT | GPIO_FLOAT | \ + GPIO_EXTI | GPIO_PORTC | GPIO_PIN15) + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_bringup + * + * Description: + * Perform architecture specific initialization + * + * CONFIG_LIB_BOARDCTL=y: + * If CONFIG_NSH_ARCHINITIALIZE=y: + * Called from the NSH library (or other application) + * Otherwise, assumed to be called from some other application. + * + * Otherwise CONFIG_BOARD_LATE_INITIALIZE=y: + * Called from board_late_initialize(). + * + * Otherwise, bad news: Never called + * + ****************************************************************************/ + +int stm32_bringup(void); + +/**************************************************************************** + * Name: stm32_spidev_initialize + * + * Description: + * Called to configure SPI chip select GPIO pins. + * + ****************************************************************************/ + +void stm32_spidev_initialize(void); + +/**************************************************************************** + * Name: stm32_adc_setup + * + * Description: + * Initialize ADC and register the ADC driver. + * + ****************************************************************************/ + +#ifdef CONFIG_ADC +int stm32_adc_setup(void); +#endif + +/**************************************************************************** + * Name: stm32_dac_setup + * + * Description: + * Initialize DAC and register the DAC driver. + * + ****************************************************************************/ + +#ifdef CONFIG_DAC +int stm32_dac_setup(void); +#endif + +/**************************************************************************** + * Name: stm32_foc_setup + * + * Description: + * Initialize FOC peripherals for the board. + * + ****************************************************************************/ + +#ifdef CONFIG_STM32_FOC +int stm32_foc_setup(void); +#endif + +/**************************************************************************** + * Name: stm32_usbinitialize + * + * Description: + * Called from stm32_usbinitialize very early in initialization to setup + * USB-related GPIO pins for the STM32F4Discovery board. + * + ****************************************************************************/ + +#ifdef CONFIG_STM32_OTGFS +void weak_function stm32_usbinitialize(void); +#endif + +#endif /* __BOARDS_ARM_STM32_ODRIVE36_SRC_ODRIVE_H */ diff --git a/boards/arm/stm32/odrive36/src/stm32_appinit.c b/boards/arm/stm32/odrive36/src/stm32_appinit.c new file mode 100644 index 0000000000..b000444492 --- /dev/null +++ b/boards/arm/stm32/odrive36/src/stm32_appinit.c @@ -0,0 +1,71 @@ +/**************************************************************************** + * boards/arm/stm32/odrive36/src/stm32_appinit.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "odrive.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_app_initialize + * + * Description: + * Perform application specific initialization. This function is never + * called directly from application code, but only indirectly via the + * (non-standard) boardctl() interface using the command BOARDIOC_INIT. + * + * Input Parameters: + * arg - The boardctl() argument is passed to the board_app_initialize() + * implementation without modification. The argument has no + * meaning to NuttX; the meaning of the argument is a contract + * between the board-specific initialization logic and the + * matching application logic. The value could be such things as a + * mode enumeration value, a set of DIP switch switch settings, a + * pointer to configuration data read from a file or serial FLASH, + * or whatever you would like to do with it. Every implementation + * should accept zero/NULL as a default configuration. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure to indicate the nature of the failure. + * + ****************************************************************************/ + +int board_app_initialize(uintptr_t arg) +{ +#ifdef CONFIG_BOARD_LATE_INITIALIZE + /* Board initialization already performed by board_late_initialize() */ + + return OK; +#else + /* Perform board-specific initialization */ + + return stm32_bringup(); +#endif +} diff --git a/boards/arm/stm32/odrive36/src/stm32_boot.c b/boards/arm/stm32/odrive36/src/stm32_boot.c new file mode 100644 index 0000000000..f2ef502508 --- /dev/null +++ b/boards/arm/stm32/odrive36/src/stm32_boot.c @@ -0,0 +1,105 @@ +/**************************************************************************** + * boards/arm/stm32/odrive36/src/stm32_boot.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include + +#include + +#include "arm_internal.h" +#include "odrive.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_boardinitialize + * + * Description: + * All STM32 architectures must provide the following entry point. This + * entry point is called early in the initialization -- after all memory + * has been configured and mapped but before any devices have been + * initialized. + * + ****************************************************************************/ + +void stm32_boardinitialize(void) +{ +#ifdef CONFIG_SEGGER_SYSVIEW + up_perf_init((void *)STM32_SYSCLK_FREQUENCY); +#endif + +#ifdef CONFIG_ARCH_LEDS + /* Configure on-board LEDs if LED support has been selected. */ + + board_autoled_initialize(); +#endif + +#if defined(CONFIG_STM32_SPI1) || defined(CONFIG_STM32_SPI2) || \ + defined(CONFIG_STM32_SPI3) + /* Configure SPI chip selects if 1) SP2 is not disabled, and 2) the weak + * function stm32_spidev_initialize() has been brought into the link. + */ + + stm32_spidev_initialize(); +#endif + +#ifdef CONFIG_STM32_OTGFS + /* Initialize USB is 1) USBDEV is selected, 2) the USB controller is not + * disabled, and 3) the weak function stm32_usbinitialize() has been + * brought into the build. + */ + + stm32_usbinitialize(); +#endif +} + +/**************************************************************************** + * Name: board_late_initialize + * + * Description: + * If CONFIG_BOARD_LATE_INITIALIZE is selected, then an additional + * initialization call will be performed in the boot-up sequence to a + * function called board_late_initialize(). board_late_initialize() will + * be called immediately after up_initialize() is called and just before + * the initial application is started. This additional initialization + * phase may be used, for example, to initialize board-specific device + * drivers. + * + ****************************************************************************/ + +#ifdef CONFIG_BOARD_LATE_INITIALIZE +void board_late_initialize(void) +{ + /* Perform board-specific initialization */ + + stm32_bringup(); +} +#endif diff --git a/boards/arm/stm32/odrive36/src/stm32_bringup.c b/boards/arm/stm32/odrive36/src/stm32_bringup.c new file mode 100644 index 0000000000..fc168f9194 --- /dev/null +++ b/boards/arm/stm32/odrive36/src/stm32_bringup.c @@ -0,0 +1,141 @@ +/**************************************************************************** + * boards/arm/stm32/odrive36/src/stm32_bringup.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +#include +#include + +#ifdef CONFIG_SENSORS_QENCODER +# include "board_qencoder.h" +# include "stm32_qencoder.h" +#endif + +#include "odrive.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_bringup + * + * Description: + * Perform architecture-specific initialization + * + * CONFIG_BOARD_LATE_INITIALIZE=y : + * Called from board_late_initialize(). + * + * CONFIG_BOARD_LATE_INITIALIZE=n && CONFIG_LIB_BOARDCTL=y : + * Called from the NSH library + * + ****************************************************************************/ + +int stm32_bringup(void) +{ + int ret = OK; + +#ifdef CONFIG_FS_PROCFS + /* Mount the procfs file system */ + + ret = nx_mount(NULL, STM32_PROCFS_MOUNTPOINT, "procfs", 0, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to mount the PROC filesystem: %d\n", + ret); + } +#endif /* CONFIG_FS_PROCFS */ + +#if defined(CONFIG_CDCACM) && !defined(CONFIG_CDCACM_CONSOLE) + /* Initialize CDCACM */ + + ret = cdcacm_initialize(0, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: cdcacm_initialize failed: %d\n", ret); + } +#endif /* CONFIG_CDCACM & !CONFIG_CDCACM_CONSOLE */ + +#if defined(CONFIG_STM32_TIM3_QE) && defined(CONFIG_SENSORS_QENCODER) + /* Initialize and register the qencoder driver - TIM3 */ + + ret = board_qencoder_initialize(0, 3); + if (ret != OK) + { + syslog(LOG_ERR, "ERROR: Failed to register the qencoder: %d\n", ret); + } + + /* Connect QE index pin */ + + ret = stm32_qe_index_init(3, GPIO_QE3_INDEX); + if (ret != OK) + { + syslog(LOG_ERR, "ERROR: Failed to register qe index pin: %d\n", ret); + } +#endif + +#if defined(CONFIG_STM32_TIM4_QE) && defined(CONFIG_SENSORS_QENCODER) + /* Initialize and register the qencoder driver - TIM4 */ + + ret = board_qencoder_initialize(1, 4); + if (ret != OK) + { + syslog(LOG_ERR, "ERROR: Failed to register the qencoder: %d\n", ret); + } + + /* Connect QE index pin */ + + ret = stm32_qe_index_init(4, GPIO_QE4_INDEX); + if (ret != OK) + { + syslog(LOG_ERR, "ERROR: Failed to register qe index pin: %d\n", ret); + } +#endif + +#ifdef CONFIG_ADC + /* Initialize ADC and register the ADC driver. */ + + ret = stm32_adc_setup(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: stm32_adc_setup failed: %d\n", ret); + } +#endif + +#ifdef CONFIG_STM32_FOC + /* Initialize and register FOC devices */ + + ret = stm32_foc_setup(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: stm32_foc_setup failed: %d\n", ret); + } +#endif + + return ret; +} diff --git a/boards/arm/stm32/odrive36/src/stm32_foc.c b/boards/arm/stm32/odrive36/src/stm32_foc.c new file mode 100644 index 0000000000..4b98a7cd36 --- /dev/null +++ b/boards/arm/stm32/odrive36/src/stm32_foc.c @@ -0,0 +1,962 @@ +/**************************************************************************** + * boards/arm/stm32/odrive36/src/stm32_foc.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include + +#include "stm32_foc.h" +#include "stm32_gpio.h" +#ifdef CONFIG_ADC +# include "stm32_adc.h" +#endif + +#include "odrive.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef CONFIG_ODRIVE_HW_VOLTAGE_56 +# error Tested only for ODrive 56V version +#endif + +/* Supported FOC instances */ + +#ifdef CONFIG_ODRIVE_FOC_FOC0 +# define ODRIVE_FOC_FOC0 1 +#else +# define ODRIVE_FOC_FOC0 0 +#endif + +#ifdef CONFIG_ODRIVE_FOC_FOC1 +# define ODRIVE_FOC_FOC1 1 +#else +# define ODRIVE_FOC_FOC1 0 +#endif + +#define ODRIVE_FOC_INST (ODRIVE_FOC_FOC0 + ODRIVE_FOC_FOC1) + +#ifdef CONFIG_ODRIVE_FOC_FOC0 +# define ODRIVE32_FOC0_DEVPATH "/dev/foc0" +# define ODRIVE32_FOC0_INST (0) +#endif + +#ifdef CONFIG_ODRIVE_FOC_FOC1 +# define ODRIVE32_FOC1_DEVPATH "/dev/foc1" +# define ODRIVE32_FOC1_INST (1) +#endif + +/* Must match upper-half configuration */ + +#if ODRIVE_FOC_INST != CONFIG_MOTOR_FOC_INST +# error Invalid configuration +#endif + +/* Only 2-shunt configuration supported by board */ + +#if CONFIG_MOTOR_FOC_SHUNTS != 2 +# error For now ony 2-shunts configuration is supported +#endif + +/* Configuration specific for DRV8301: + * 1. PWM channels must have positive polarity + * 2. PWM complementary channels must have positive polarity + */ + +#ifndef CONFIG_STM32_FOC_HAS_PWM_COMPLEMENTARY +# error +#endif + +#ifdef CONFIG_ODRIVE_FOC_FOC0 + +# if CONFIG_STM32_TIM1_CH1POL != 0 +# error +# endif +# if CONFIG_STM32_TIM1_CH2POL != 0 +# error +# endif +# if CONFIG_STM32_TIM1_CH3POL != 0 +# error +# endif +# if CONFIG_STM32_TIM1_CH1NPOL != 0 +# error +# endif +# if CONFIG_STM32_TIM1_CH2NPOL != 0 +# error +# endif +# if CONFIG_STM32_TIM1_CH3NPOL != 0 +# error +# endif + +/* FOC0 uses ADC2 */ + +# ifndef CONFIG_STM32_FOC_FOC0_ADC2 +# error +# endif + +# if CONFIG_STM32_ADC2_RESOLUTION != 0 +# error +# endif + +#endif /* CONFIG_ODRIVE_FOC_FOC0 */ + +#ifdef CONFIG_ODRIVE_FOC_FOC1 + +# if CONFIG_STM32_TIM8_CH1POL != 0 +# error +# endif +# if CONFIG_STM32_TIM8_CH2POL != 0 +# error +# endif +# if CONFIG_STM32_TIM8_CH3POL != 0 +# error +# endif +# if CONFIG_STM32_TIM8_CH1NPOL != 0 +# error +# endif +# if CONFIG_STM32_TIM8_CH2NPOL != 0 +# error +# endif +# if CONFIG_STM32_TIM8_CH3NPOL != 0 +# error +# endif + +/* FOC1 uses ADC3 */ + +# ifndef CONFIG_STM32_FOC_FOC1_ADC3 +# error +# endif + +# if CONFIG_STM32_ADC3_RESOLUTION != 0 +# error +# endif + +#endif /* CONFIG_ODRIVE_FOC_FOC1 */ + +/* Aux ADC needs DMA enabled */ + +#ifdef CONFIG_ADC +# ifndef CONFIG_STM32_ADC1_DMA +# error +# endif +# ifndef CONFIG_STM32_ADC1_SCAN +# error +# endif +#endif + +/* TODO: */ + +#define PWM_DEADTIME (50) +#define PWM_DEADTIME_NS (320) + +/* Board parameters: + * Current shunt resistance = 0.0005 + * Current sense gain = (10/20/40/80) + * Vbus min = 12V + * Vbus max = 24V or 56V + * Iout max = 40A (no cooling for + * MOSFETs) + * IPHASE_RATIO = 1/(R_shunt*gain) + * ADC_REF_VOLTAGE = 3.3 + * ADC_VAL_MAX = 4095 + * ADC_TO_VOLT = ADC_REF_VOLTAGE / ADC_VAL_MAX + * IPHASE_ADC = IPHASE_RATIO * ADC_TO_VOLT = 0.02014 (gain=80) + * VBUS_RATIO = 1/VBUS_gain = 11 or 19 + */ + +#define ADC_VOLT_REF 3300000 /* micro volt */ +#define ADC_VAL_MAX 4095 +#define R_SHUNT 500 /* micro ohm */ + +/* Center-aligned PWM duty cycle limits */ + +#define MAX_DUTY_B16 ftob16(0.95f) + +/* ADC configuration */ + +#define CURRENT_SAMPLE_TIME ADC_SMPR_3 +#define VBUS_SAMPLE_TIME ADC_SMPR_15 +#define TEMP_SAMPLE_TIME ADC_SMPR_15 + +#define ODRIVE_ADC_AUX (1) +#define ODRIVE_ADC_FOC0 (2) +#define ODRIVE_ADC_FOC1 (3) + +#ifdef CONFIG_ODRIVE_FOC_VBUS +# define ODRIVE_FOC_VBUS 1 +#else +# define ODRIVE_FOC_VBUS 0 +#endif +#ifdef CONFIG_ODRIVE_FOC_TEMP +# define ODRIVE_FOC_TEMP 3 +#else +# define ODRIVE_FOC_TEMP 0 +#endif + +#ifdef CONFIG_ADC +# define ODRIVE_ADC_AUX_DEVPATH "/dev/adc0" +# define ODRIVE_ADC_AUX_NCHAN (ODRIVE_FOC_VBUS + ODRIVE_FOC_TEMP) +#endif + +#define ADC1_INJECTED (0) +#define ADC1_REGULAR (0) +#define ADC1_NCHANNELS (ADC1_INJECTED + ADC1_REGULAR) + +#define ADC2_INJECTED (CONFIG_MOTOR_FOC_SHUNTS) +#define ADC2_REGULAR (0) +#define ADC2_NCHANNELS (ADC2_INJECTED + ADC2_REGULAR) + +#define ADC3_INJECTED (CONFIG_MOTOR_FOC_SHUNTS) +#define ADC3_REGULAR (0) +#define ADC3_NCHANNELS (ADC3_INJECTED + ADC3_REGULAR) + +#if ADC1_INJECTED != CONFIG_STM32_ADC1_INJECTED_CHAN +# error +#endif + +#if ADC2_INJECTED != CONFIG_STM32_ADC2_INJECTED_CHAN +# error +#endif + +#if ADC3_INJECTED != CONFIG_STM32_ADC3_INJECTED_CHAN +# error +#endif + +/* DRV8301 configuration */ + +#ifndef CONFIG_STM32_SPI3 +# error +#endif + +#define DRV8301_0_SPI (3) +#define DRV8301_1_SPI (3) + +#define DRV8301_FREQUENCY (500000) + +/* Qenco configuration */ + +#ifdef CONFIG_SENSORS_QENCODER +# ifndef CONFIG_STM32_QENCODER_DISABLE_EXTEND16BTIMERS +# error Invalid configuration +# endif +# ifndef CONFIG_STM32_QENCODER_INDEX_PIN +# error Invalid configuration +# endif +# ifdef CONFIG_STM32_TIM3_QE +# if CONFIG_STM32_TIM3_QEPSC != 0 +# error Invalid TIM3 QEPSC value +# endif +# endif +# ifdef CONFIG_STM32_TIM4_QE +# if CONFIG_STM32_TIM4_QEPSC != 0 +# error Invalid TIM4 QEPSC value +# endif +# endif +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Protototypes + ****************************************************************************/ + +static int board_foc_setup(struct foc_dev_s *dev); +static int board_foc_shutdown(struct foc_dev_s *dev); +static int board_foc_calibration(struct foc_dev_s *dev, bool state); +static int board_foc_fault_clear(struct foc_dev_s *dev); +static int board_foc_pwm_start(struct foc_dev_s *dev, bool state); +static int board_foc_current_get(struct foc_dev_s *dev, int16_t *curr_raw, + foc_current_t *curr); +static int board_foc_info_get(struct foc_dev_s *dev, + struct foc_info_s *info); +static int board_foc_ioctl(struct foc_dev_s *dev, int cmd, + unsigned long arg); +#ifdef CONFIG_MOTOR_FOC_TRACE +static int board_foc_trace_init(struct foc_dev_s *dev); +static void board_foc_trace(struct foc_dev_s *dev, int type, bool state); +#endif + +static int stm32_foc_drv8301_fault_attach(struct focpwr_dev_s *dev, + xcpt_t isr, void *arg); +static int stm32_foc_drv8301_gate_enable(struct focpwr_dev_s *dev, + bool enable); +static void stm32_foc_drv8301_fault_handle(struct focpwr_dev_s *dev); + +static int stm32_focdev_setup(int devno, int spino, + struct stm32_foc_board_s *board); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Board specific ops */ + +static struct stm32_foc_board_ops_s g_stm32_foc_board_ops = +{ + .setup = board_foc_setup, + .shutdown = board_foc_shutdown, + .calibration = board_foc_calibration, + .fault_clear = board_foc_fault_clear, + .pwm_start = board_foc_pwm_start, + .current_get = board_foc_current_get, + .info_get = board_foc_info_get, + .ioctl = board_foc_ioctl, +#ifdef CONFIG_MOTOR_FOC_TRACE + .trace_init = board_foc_trace_init, + .trace = board_foc_trace +#endif +}; + +/* Board specific ADC configuration + * + * AUX (only VBUS used): + * VBUS - ADC1 - ADC1_IN6 (PA6) + * M0_TEMP - ADC1 - ADC1_IN15 (PC5) + * M1_TEMP - ADC1 - ADC1_IN4 (PA4) + * AUX_TEMP - ADC1 - ADC1_IN5 (PA5) + * + * FOC device 0: + * Phase 1 - ADC2 - ADC2_IN10 (PC0) + * Phase 2 - ADC2 - ADC2_IN11 (PC1) + * + * FOC device 1: + * Phase 1 - ADC3 - ADC3_IN13 (PC3) + * Phase 2 - ADC3 - ADC3_IN12 (PC2) + * + */ + +#ifdef CONFIG_ADC + +/* AUX ADC configuration */ + +static uint8_t g_adc_aux_chan[] = +{ +#ifdef CONFIG_ODRIVE_FOC_VBUS + 6, +#endif +#ifdef ODRIVE_ADC_TEMP + 15, + 4, + 5 +#endif +}; + +static uint32_t g_adc_aux_pins[] = +{ +#ifdef CONFIG_ODRIVE_FOC_VBUS + GPIO_ADC1_IN6, +#endif +#ifdef ODRIVE_ADC_TEMP + GPIO_ADC1_IN15, + GPIO_ADC1_IN4, + GPIO_ADC1_IN5 +#endif +}; + +static adc_channel_t g_adc_aux_stime[] = +{ +#ifdef CONFIG_ODRIVE_FOC_VBUS + { + .channel = 6, + .sample_time = VBUS_SAMPLE_TIME + }, +#endif +#ifdef ODRIVE_ADC_TEMP + { + .channel = 15, + .sample_time = TEMP_SAMPLE_TIME + }, + { + .channel = 4, + .sample_time = TEMP_SAMPLE_TIME + }, + { + .channel = 5, + .sample_time = TEMP_SAMPLE_TIME + } +#endif +}; +#endif + +#ifdef CONFIG_ODRIVE_FOC_FOC0 +/* Board specific ADC configuration for FOC device 0 */ + +static uint8_t g_adc_foc0_chan[] = +{ + 10, + 11 +}; + +static uint32_t g_adc_foc0_pins[] = +{ + GPIO_ADC2_IN10, + GPIO_ADC2_IN11, +}; + +static adc_channel_t g_adc_foc0_stime[] = +{ + { + .channel = 10, + .sample_time = CURRENT_SAMPLE_TIME + }, + { + .channel = 11, + .sample_time = CURRENT_SAMPLE_TIME + } +}; + +static struct stm32_foc_adc_s g_adc_foc0_cfg = +{ + .chan = g_adc_foc0_chan, + .pins = g_adc_foc0_pins, + .stime = g_adc_foc0_stime, + .nchan = ADC2_NCHANNELS, + .regch = ADC2_REGULAR, + .intf = ODRIVE_ADC_FOC0 +}; +#endif + +#ifdef CONFIG_ODRIVE_FOC_FOC1 +/* Board specific ADC configuration for FOC device 1 */ + +static uint8_t g_adc_foc1_chan[] = +{ + 13, + 12 +}; + +static uint32_t g_adc_foc1_pins[] = +{ + GPIO_ADC3_IN13, + GPIO_ADC3_IN12, +}; + +static adc_channel_t g_adc_foc1_stime[] = +{ + { + .channel = 13, + .sample_time = CURRENT_SAMPLE_TIME + }, + { + .channel = 12, + .sample_time = CURRENT_SAMPLE_TIME + } +}; + +static struct stm32_foc_adc_s g_adc_foc1_cfg = +{ + .chan = g_adc_foc1_chan, + .pins = g_adc_foc1_pins, + .stime = g_adc_foc1_stime, + .nchan = ADC3_NCHANNELS, + .regch = ADC3_REGULAR, + .intf = ODRIVE_ADC_FOC1 +}; +#endif + +#ifdef CONFIG_ODRIVE_FOC_FOC0 +/* Board specific data - FOC 0 */ + +static struct stm32_foc_board_data_s g_stm32_foc0_board_data = +{ + .adc_cfg = &g_adc_foc0_cfg, + .pwm_dt = (PWM_DEADTIME), +}; + +/* Board specific configuration */ + +static struct stm32_foc_board_s g_stm32_foc0_board = +{ + .data = &g_stm32_foc0_board_data, + .ops = &g_stm32_foc_board_ops, +}; +#endif + +#ifdef CONFIG_ODRIVE_FOC_FOC1 +/* Board specific data - FOC 1 */ + +static struct stm32_foc_board_data_s g_stm32_foc1_board_data = +{ + .adc_cfg = &g_adc_foc1_cfg, + .pwm_dt = (PWM_DEADTIME), +}; + +/* Board specific configuration */ + +static struct stm32_foc_board_s g_stm32_foc1_board = +{ + .data = &g_stm32_foc1_board_data, + .ops = &g_stm32_foc_board_ops, +}; +#endif + +/* DRV8301 board ops */ + +static struct drv8301_ops_s g_drv8301_board_ops = +{ + .fault_attach = stm32_foc_drv8301_fault_attach, + .gate_enable = stm32_foc_drv8301_gate_enable, + .fault_handle = stm32_foc_drv8301_fault_handle +}; + +/* Global data */ + +static mutex_t g_common_lock = NXMUTEX_INITIALIZER; +static bool g_fault_attached = false; +static bool g_gate_enabled = false; + +static struct foc_dev_s *g_foc_dev[2] = +{ + NULL, + NULL +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_foc_setup + ****************************************************************************/ + +static int board_foc_setup(struct foc_dev_s *dev) +{ + DEBUGASSERT(dev); + DEBUGASSERT(dev->pwr); + + return dev->pwr->ops->setup(dev->pwr); +} + +/**************************************************************************** + * Name: board_foc_shutdown + ****************************************************************************/ + +static int board_foc_shutdown(struct foc_dev_s *dev) +{ + DEBUGASSERT(dev); + DEBUGASSERT(dev->pwr); + + return dev->pwr->ops->shutdown(dev->pwr); +} + +/**************************************************************************** + * Name: board_foc_calibration + ****************************************************************************/ + +static int board_foc_calibration(struct foc_dev_s *dev, bool state) +{ + DEBUGASSERT(dev); + DEBUGASSERT(dev->pwr); + + return dev->pwr->ops->calibration(dev->pwr, state); +} + +/**************************************************************************** + * Name: board_foc_fault_clear + ****************************************************************************/ + +static int board_foc_fault_clear(struct foc_dev_s *dev) +{ + DEBUGASSERT(dev); + + UNUSED(dev); + + /* TODO: clear DRV8301 faults */ + + return OK; +} + +/**************************************************************************** + * Name: board_foc_pwm_start + ****************************************************************************/ + +static int board_foc_pwm_start(struct foc_dev_s *dev, bool state) +{ + DEBUGASSERT(dev); + + return OK; +} + +/**************************************************************************** + * Name: board_foc_current_get + ****************************************************************************/ + +static int board_foc_current_get(struct foc_dev_s *dev, int16_t *curr_raw, + foc_current_t *curr) +{ + DEBUGASSERT(dev); + DEBUGASSERT(curr_raw); + DEBUGASSERT(curr); + + /* Get currents */ + + curr[1] = curr_raw[0]; + curr[2] = curr_raw[1]; + + /* From Kirchhoff's current law: ia = -(ib + ic) */ + + curr[0] = -(curr[1] + curr[2]); + + return OK; +} + +/**************************************************************************** + * Name: board_foc_info_get + ****************************************************************************/ + +static int board_foc_info_get(struct foc_dev_s *dev, + struct foc_info_s *info) +{ + struct foc_get_boardcfg_s cfg; + + DEBUGASSERT(dev); + DEBUGASSERT(info); + + UNUSED(dev); + + /* PWM */ + + info->hw_cfg.pwm_dt_ns = PWM_DEADTIME_NS; + info->hw_cfg.pwm_max = MAX_DUTY_B16; + + /* Get power stage configuration */ + + board_foc_ioctl(dev, MTRIOC_GET_BOARDCFG, (unsigned long)&cfg); + + /* ADC Current */ + + info->hw_cfg.iphase_max = 40000; + + info->hw_cfg.iphase_scale = ((100000ul * (ADC_VOLT_REF / ADC_VAL_MAX)) / + (cfg.gain * R_SHUNT)); + + return OK; +} + +/**************************************************************************** + * Name: board_foc_ioctl + ****************************************************************************/ + +static int board_foc_ioctl(struct foc_dev_s *dev, int cmd, unsigned long arg) +{ + DEBUGASSERT(dev); + DEBUGASSERT(dev->pwr); + + return dev->pwr->ops->ioctl(dev->pwr, cmd, arg); +} + +#ifdef CONFIG_MOTOR_FOC_TRACE +/**************************************************************************** + * Name: board_foc_trace_init + ****************************************************************************/ + +static int board_foc_trace_init(struct foc_dev_s *dev) +{ + DEBUGASSERT(dev); + + UNUSED(dev); + + /* Not supported */ + + return -1; +} + +/**************************************************************************** + * Name: board_foc_trace + ****************************************************************************/ + +static void board_foc_trace(struct foc_dev_s *dev, int type, bool state) +{ + DEBUGASSERT(dev); + + UNUSED(dev); +} +#endif + +/**************************************************************************** + * Name: stm32_foc_drv8301_fault_attach + ****************************************************************************/ + +static int stm32_foc_drv8301_fault_attach(struct focpwr_dev_s *dev, + xcpt_t isr, void *arg) +{ + int ret = OK; + + nxmutex_lock(&g_common_lock); + + /* nFAULT is common for both FOC instances */ + + if (g_fault_attached != (bool) isr) + { + ret = stm32_gpiosetevent(GPIO_DRV8301_NFAULT, false, true, false, + isr, arg); + + g_fault_attached = (bool) isr; + } + + nxmutex_unlock(&g_common_lock); + + return ret; +} + +/**************************************************************************** + * Name: stm32_foc_drv8301_gate_enable + ****************************************************************************/ + +static int stm32_foc_drv8301_gate_enable(struct focpwr_dev_s *dev, + bool enable) +{ + /* ENGATE is common for both FOC instances */ + + nxmutex_lock(&g_common_lock); + + if (enable != g_gate_enabled) + { + stm32_gpiowrite(GPIO_DRV8301_ENGATE, enable); + + g_gate_enabled = enable; + } + + nxmutex_unlock(&g_common_lock); + + return OK; +} + +/**************************************************************************** + * Name: stm32_foc_drv8301_fault_handle + ****************************************************************************/ + +static void stm32_foc_drv8301_fault_handle(struct focpwr_dev_s *dev) +{ + UNUSED(dev); + + /* Set fault state for both instances */ + +#ifdef CONFIG_ODRIVE_FOC_FOC0 + g_foc_dev[0]->state.fault |= FOC_FAULT_BOARD; +#endif + +#ifdef CONFIG_ODRIVE_FOC_FOC1 + g_foc_dev[1]->state.fault |= FOC_FAULT_BOARD; +#endif + + /* Disable gates for both instances */ + + stm32_gpiowrite(GPIO_DRV8301_ENGATE, false); +} + +/**************************************************************************** + * Name: stm32_focdev_setup + ****************************************************************************/ + +static int stm32_focdev_setup(int devno, int spino, + struct stm32_foc_board_s *board) +{ + struct drv8301_cfg_s drv8301_cfg; + struct drv8301_board_s drv8301_board; + struct spi_dev_s *spi = NULL; + struct foc_dev_s *foc = NULL; + int ret = OK; + char devpath[20]; + + /* Initialize arch specific FOC 0 lower-half */ + + foc = stm32_foc_initialize(devno, board); + if (foc == NULL) + { + ret = -errno; + mtrerr("Failed to initialize STM32 FOC: %d\n", ret); + goto errout; + } + + DEBUGASSERT(foc->lower); + + /* Get devpath */ + + snprintf(devpath, sizeof(devpath), "/dev/foc%d", devno); + + /* Get SPI device */ + + spi = stm32_spibus_initialize(spino); + if (spi == NULL) + { + ret = -errno; + goto errout; + } + + /* DRV8301 configuration */ + + drv8301_cfg.freq = DRV8301_FREQUENCY; + drv8301_cfg.gate_curr = DRV8301_GATECURR_1p7; + drv8301_cfg.gain = DRV8301_GAIN_80; + drv8301_cfg.pwm_mode = DRV8301_PWM_6IN; + drv8301_cfg.oc_adj = DRV8301_OCADJ_DEFAULT; + + /* DRV8301 board data */ + + drv8301_board.spi = spi; + drv8301_board.ops = &g_drv8301_board_ops; + drv8301_board.cfg = &drv8301_cfg; + drv8301_board.devno = devno; + + /* Register DRV8301 device */ + + ret = drv8301_register(devpath, foc, &drv8301_board); + if (ret < 0) + { + mtrerr("Failed to register drv8301 device: %d\n", ret); + goto errout; + } + +errout: + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_foc_setup + * + * Description: + * Setup FOC devices + * + * This function should be call by board_app_initialize(). + * + * Returned Value: + * 0 on success, a negated errno value on failure + * + ****************************************************************************/ + +int stm32_foc_setup(void) +{ + int ret = OK; + + /* Configure common EN_GATE */ + + stm32_configgpio(GPIO_DRV8301_ENGATE); + +#ifdef CONFIG_ODRIVE_FOC_FOC0 + ret = stm32_focdev_setup(0, DRV8301_0_SPI, &g_stm32_foc0_board); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: stm32_focdev_setup 0 failed: %d\n", ret); + goto errout; + } +#endif + +#ifdef CONFIG_ODRIVE_FOC_FOC1 + ret = stm32_focdev_setup(1, DRV8301_1_SPI, &g_stm32_foc1_board); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: stm32_focdev_setup 1 failed: %d\n", ret); + goto errout; + } +#endif + +errout: + return ret; +} + +#ifdef CONFIG_ADC +/**************************************************************************** + * Name: stm32_adc_setup + * + * Description: + * Initialize ADC and register the ADC driver. + * + ****************************************************************************/ + +int stm32_adc_setup(void) +{ + struct adc_dev_s *adc = NULL; + struct stm32_adc_dev_s *stm32_adc = NULL; + struct adc_sample_time_s stime; + int i = 0; + int ret = OK; + + /* Configure pins */ + + for (i = 0; i < ODRIVE_ADC_AUX_NCHAN; i += 1) + { + stm32_configgpio(g_adc_aux_pins[i]); + } + + /* Initialize ADC */ + + adc = stm32_adcinitialize(ODRIVE_ADC_AUX, g_adc_aux_chan, + ODRIVE_ADC_AUX_NCHAN); + if (adc == NULL) + { + aerr("ERROR: Failed to get ADC interface %d\n", ODRIVE_ADC_AUX); + ret = -ENODEV; + goto errout; + } + + /* Regsiter ADC */ + + ret = adc_register(ODRIVE_ADC_AUX_DEVPATH, adc); + if (ret < 0) + { + aerr("ERROR: adc_register %s failed: %d\n", + ODRIVE_ADC_AUX_DEVPATH, ret); + goto errout; + } + + /* Get lower-half ADC */ + + stm32_adc = (struct stm32_adc_dev_s *)adc->ad_priv; + DEBUGASSERT(stm32_adc); + + /* Configure ADC sample time */ + + memset(&stime, 0, sizeof(struct adc_sample_time_s)); + + stime.channels_nbr = ODRIVE_ADC_AUX_NCHAN; + stime.channel = g_adc_aux_stime; + + STM32_ADC_SAMPLETIME_SET(stm32_adc, &stime); + STM32_ADC_SAMPLETIME_WRITE(stm32_adc); + + ret = OK; + +errout: + return ret; +} +#endif diff --git a/boards/arm/stm32/odrive36/src/stm32_spi.c b/boards/arm/stm32/odrive36/src/stm32_spi.c new file mode 100644 index 0000000000..3455280431 --- /dev/null +++ b/boards/arm/stm32/odrive36/src/stm32_spi.c @@ -0,0 +1,196 @@ +/**************************************************************************** + * boards/arm/stm32/odrive36/src/stm32_spi.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include "arm_internal.h" +#include "chip.h" +#include "stm32.h" + +#include "odrive.h" + +#if defined(CONFIG_STM32_SPI1) || defined(CONFIG_STM32_SPI2) || defined(CONFIG_STM32_SPI3) + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_spidev_initialize + * + * Description: + * Called to configure SPI chip select GPIO pins for the stm32f4discovery + * board. + * + ****************************************************************************/ + +void weak_function stm32_spidev_initialize(void) +{ +#ifdef CONFIG_MOTOR_FOC +# ifdef CONFIG_ODRIVE_FOC_FOC0 + stm32_configgpio(GPIO_GATEDRV0_CS); +# endif +# ifdef CONFIG_ODRIVE_FOC_FOC1 + stm32_configgpio(GPIO_GATEDRV1_CS); +# endif +#endif /* CONFIG_MOTOR_FOC */ +} + +/**************************************************************************** + * Name: stm32_spi1/2/3select and stm32_spi1/2/3status + * + * Description: + * The external functions, stm32_spi1/2/3select and stm32_spi1/2/3status + * must be provided by board-specific logic. They are implementations of + * the select and status methods of the SPI interface defined by struct + * spi_ops_s (see include/nuttx/spi/spi.h). All other methods (including + * stm32_spibus_initialize()) are provided by common STM32 logic. To use + * this common SPI logic on your board: + * + * 1. Provide logic in stm32_boardinitialize() to configure SPI chip select + * pins. + * 2. Provide stm32_spi1/2/3select() and stm32_spi1/2/3status() functions + * in your board-specific logic. These functions will perform chip + * selection and status operations using GPIOs in the way your board + * is configured. + * 3. Add a calls to stm32_spibus_initialize() in your low level + * application initialization logic + * 4. The handle returned by stm32_spibus_initialize() may then be used to + * bind the SPI driver to higher level logic (e.g., calling + * mmcsd_spislotinitialize(), for example, will bind the SPI driver to + * the SPI MMC/SD driver). + * + ****************************************************************************/ + +#ifdef CONFIG_STM32_SPI1 +void stm32_spi1select(struct spi_dev_s *dev, uint32_t devid, bool selected) +{ + spiinfo("devid: %d CS: %s\n", + (int)devid, selected ? "assert" : "de-assert"); +} + +uint8_t stm32_spi1status(struct spi_dev_s *dev, uint32_t devid) +{ + return 0; +} +#endif + +#ifdef CONFIG_STM32_SPI2 +void stm32_spi2select(struct spi_dev_s *dev, uint32_t devid, + bool selected) +{ + spiinfo("devid: %d CS: %s\n", + (int)devid, selected ? "assert" : "de-assert"); +} + +uint8_t stm32_spi2status(struct spi_dev_s *dev, uint32_t devid) +{ + return 0; +} +#endif + +#ifdef CONFIG_STM32_SPI3 +void stm32_spi3select(struct spi_dev_s *dev, uint32_t devid, bool selected) +{ + spiinfo("devid: %d CS: %s\n", + (int)devid, selected ? "assert" : "de-assert"); + +#ifdef CONFIG_MOTOR_FOC +# ifdef CONFIG_ODRIVE_FOC_FOC0 + if (devid == SPIDEV_MOTOR(0)) + { + stm32_gpiowrite(GPIO_GATEDRV0_CS, !selected); + } +# endif + +# ifdef CONFIG_ODRIVE_FOC_FOC1 + if (devid == SPIDEV_MOTOR(1)) + { + stm32_gpiowrite(GPIO_GATEDRV1_CS, !selected); + } +# endif +#endif /* CONFIG_MOTOR_FOC */ +} + +uint8_t stm32_spi3status(struct spi_dev_s *dev, uint32_t devid) +{ + return 0; +} +#endif + +/**************************************************************************** + * Name: stm32_spi1cmddata + * + * Description: + * Set or clear the SH1101A A0 or SD1306 D/C n bit to select data (true) + * or command (false). This function must be provided by platform-specific + * logic. This is an implementation of the cmddata method of the SPI + * interface defined by struct spi_ops_s (see include/nuttx/spi/spi.h). + * + * Input Parameters: + * + * spi - SPI device that controls the bus the device that requires the CMD/ + * DATA selection. + * devid - If there are multiple devices on the bus, this selects which one + * to select cmd or data. NOTE: This design restricts, for example, + * one one SPI display per SPI bus. + * cmd - true: select command; false: select data + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_SPI_CMDDATA +#ifdef CONFIG_STM32_SPI1 +int stm32_spi1cmddata(struct spi_dev_s *dev, uint32_t devid, bool cmd) +{ + return -ENODEV; +} +#endif + +#ifdef CONFIG_STM32_SPI2 +int stm32_spi2cmddata(struct spi_dev_s *dev, uint32_t devid, bool cmd) +{ + return -ENODEV; +} +#endif + +#ifdef CONFIG_STM32_SPI3 +int stm32_spi3cmddata(struct spi_dev_s *dev, uint32_t devid, bool cmd) +{ + return -ENODEV; +} +#endif +#endif /* CONFIG_SPI_CMDDATA */ + +#endif /* CONFIG_STM32_SPI1 || CONFIG_STM32_SPI2 || CONFIG_STM32_SPI3 */ diff --git a/boards/arm/stm32/odrive36/src/stm32_usb.c b/boards/arm/stm32/odrive36/src/stm32_usb.c new file mode 100644 index 0000000000..8181c15340 --- /dev/null +++ b/boards/arm/stm32/odrive36/src/stm32_usb.c @@ -0,0 +1,103 @@ +/**************************************************************************** + * boards/arm/stm32/odrive36/src/stm32_usb.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "arm_internal.h" +#include "stm32.h" +#include "stm32_otgfs.h" +#include "odrive.h" + +#ifdef CONFIG_STM32_OTGFS + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#if defined(CONFIG_USBDEV) +# define HAVE_USB 1 +#else +# warning "CONFIG_STM32_OTGFS is enabled but neither CONFIG_USBDEV" +# undef HAVE_USB +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_usbinitialize + * + * Description: + * Called from stm32_usbinitialize very early in inialization to setup + * USB-related GPIO pins for the STM32F4Discovery board. + * + ****************************************************************************/ + +void stm32_usbinitialize(void) +{ + /* The OTG FS has an internal soft pull-up. + * No GPIO configuration is required + */ +} + +/**************************************************************************** + * Name: stm32_usbsuspend + * + * Description: + * Board logic must provide the stm32_usbsuspend logic if the USBDEV + * driver is used. This function is called whenever the USB enters or + * leaves suspend mode. This is an opportunity for the board logic to + * shutdown clocks, power, etc. while the USB is suspended. + * + ****************************************************************************/ + +#ifdef CONFIG_USBDEV +void stm32_usbsuspend(struct usbdev_s *dev, bool resume) +{ + uinfo("resume: %d\n", resume); +} +#endif + +#endif /* CONFIG_STM32_OTGFS */