From 1c63d5666bab6875f828a1a334328a99bea9743c Mon Sep 17 00:00:00 2001 From: Siddharth Bharat Purohit Date: Wed, 18 Jan 2023 12:55:57 +1100 Subject: [PATCH] boards: add support for CubeOrange+ (#20304) Co-authored-by: Julian Oes --- .../cubeorangeplus/bootloader.px4board | 3 + .../cubepilot/cubeorangeplus/default.px4board | 97 +++++++ .../cubepilot_cubeorangeplus_bootloader.bin | Bin 0 -> 43624 bytes .../extras/cubepilot_io-v2_default.bin | Bin 0 -> 39704 bytes .../cubeorangeplus/firmware.prototype | 13 + .../cubeorangeplus/init/rc.board_defaults | 19 ++ .../cubeorangeplus/init/rc.board_mavlink | 10 + .../cubeorangeplus/init/rc.board_sensors | 15 + .../nuttx-config/bootloader/defconfig | 93 ++++++ .../nuttx-config/include/board.h | 266 ++++++++++++++++++ .../nuttx-config/include/board_dma_map.h | 44 +++ .../cubeorangeplus/nuttx-config/nsh/defconfig | 256 +++++++++++++++++ .../nuttx-config/scripts/bootloader_script.ld | 223 +++++++++++++++ .../nuttx-config/scripts/script.ld | 228 +++++++++++++++ .../nuttx-config/test/defconfig | 235 ++++++++++++++++ .../cubeorangeplus/src/CMakeLists.txt | 65 +++++ .../cubeorangeplus/src/board_config.h | 190 +++++++++++++ .../cubeorangeplus/src/bootloader_main.c | 75 +++++ .../cubepilot/cubeorangeplus/src/hw_config.h | 135 +++++++++ boards/cubepilot/cubeorangeplus/src/i2c.cpp | 39 +++ boards/cubepilot/cubeorangeplus/src/init.c | 199 +++++++++++++ boards/cubepilot/cubeorangeplus/src/led.c | 110 ++++++++ boards/cubepilot/cubeorangeplus/src/spi.cpp | 55 ++++ .../cubeorangeplus/src/timer_config.cpp | 51 ++++ boards/cubepilot/cubeorangeplus/src/usb.c | 60 ++++ boards/cubepilot/cubeorangeplus/test.px4board | 15 + platforms/nuttx/NuttX/nuttx | 2 +- .../driver/include/uavcan_stm32h7/fdcan.hpp | 2 +- 28 files changed, 2498 insertions(+), 2 deletions(-) create mode 100644 boards/cubepilot/cubeorangeplus/bootloader.px4board create mode 100644 boards/cubepilot/cubeorangeplus/default.px4board create mode 100755 boards/cubepilot/cubeorangeplus/extras/cubepilot_cubeorangeplus_bootloader.bin create mode 100755 boards/cubepilot/cubeorangeplus/extras/cubepilot_io-v2_default.bin create mode 100644 boards/cubepilot/cubeorangeplus/firmware.prototype create mode 100644 boards/cubepilot/cubeorangeplus/init/rc.board_defaults create mode 100644 boards/cubepilot/cubeorangeplus/init/rc.board_mavlink create mode 100644 boards/cubepilot/cubeorangeplus/init/rc.board_sensors create mode 100644 boards/cubepilot/cubeorangeplus/nuttx-config/bootloader/defconfig create mode 100644 boards/cubepilot/cubeorangeplus/nuttx-config/include/board.h create mode 100644 boards/cubepilot/cubeorangeplus/nuttx-config/include/board_dma_map.h create mode 100644 boards/cubepilot/cubeorangeplus/nuttx-config/nsh/defconfig create mode 100644 boards/cubepilot/cubeorangeplus/nuttx-config/scripts/bootloader_script.ld create mode 100644 boards/cubepilot/cubeorangeplus/nuttx-config/scripts/script.ld create mode 100644 boards/cubepilot/cubeorangeplus/nuttx-config/test/defconfig create mode 100644 boards/cubepilot/cubeorangeplus/src/CMakeLists.txt create mode 100644 boards/cubepilot/cubeorangeplus/src/board_config.h create mode 100644 boards/cubepilot/cubeorangeplus/src/bootloader_main.c create mode 100644 boards/cubepilot/cubeorangeplus/src/hw_config.h create mode 100644 boards/cubepilot/cubeorangeplus/src/i2c.cpp create mode 100644 boards/cubepilot/cubeorangeplus/src/init.c create mode 100644 boards/cubepilot/cubeorangeplus/src/led.c create mode 100644 boards/cubepilot/cubeorangeplus/src/spi.cpp create mode 100644 boards/cubepilot/cubeorangeplus/src/timer_config.cpp create mode 100644 boards/cubepilot/cubeorangeplus/src/usb.c create mode 100644 boards/cubepilot/cubeorangeplus/test.px4board diff --git a/boards/cubepilot/cubeorangeplus/bootloader.px4board b/boards/cubepilot/cubeorangeplus/bootloader.px4board new file mode 100644 index 00000000000..19b6e662be6 --- /dev/null +++ b/boards/cubepilot/cubeorangeplus/bootloader.px4board @@ -0,0 +1,3 @@ +CONFIG_BOARD_TOOLCHAIN="arm-none-eabi" +CONFIG_BOARD_ARCHITECTURE="cortex-m7" +CONFIG_BOARD_ROMFSROOT="" diff --git a/boards/cubepilot/cubeorangeplus/default.px4board b/boards/cubepilot/cubeorangeplus/default.px4board new file mode 100644 index 00000000000..4fbc1c34d87 --- /dev/null +++ b/boards/cubepilot/cubeorangeplus/default.px4board @@ -0,0 +1,97 @@ +CONFIG_BOARD_TOOLCHAIN="arm-none-eabi" +CONFIG_BOARD_ARCHITECTURE="cortex-m7" +CONFIG_BOARD_IO="cubepilot_io-v2_default" +CONFIG_BOARD_SERIAL_GPS1="/dev/ttyS2" +CONFIG_BOARD_SERIAL_GPS2="/dev/ttyS5" +CONFIG_BOARD_SERIAL_TEL1="/dev/ttyS0" +CONFIG_BOARD_SERIAL_TEL2="/dev/ttyS1" +CONFIG_DRIVERS_ADC_ADS1115=y +CONFIG_DRIVERS_ADC_BOARD_ADC=y +CONFIG_DRIVERS_BAROMETER_MS5611=y +CONFIG_DRIVERS_BATT_SMBUS=y +CONFIG_DRIVERS_CAMERA_CAPTURE=y +CONFIG_DRIVERS_CAMERA_TRIGGER=y +CONFIG_COMMON_DIFFERENTIAL_PRESSURE=y +CONFIG_COMMON_DISTANCE_SENSOR=y +CONFIG_DRIVERS_DSHOT=y +CONFIG_DRIVERS_GPS=y +CONFIG_DRIVERS_IMU_ANALOG_DEVICES_ADIS16448=y +CONFIG_DRIVERS_IMU_INVENSENSE_ICM42688P=y +CONFIG_DRIVERS_IMU_INVENSENSE_ICM20649=y +CONFIG_DRIVERS_IMU_INVENSENSE_ICM20948=y +CONFIG_DRIVERS_IRLOCK=y +CONFIG_COMMON_LIGHT=y +CONFIG_COMMON_MAGNETOMETER=y +CONFIG_COMMON_OPTICAL_FLOW=y +CONFIG_DRIVERS_PCA9685_PWM_OUT=y +CONFIG_DRIVERS_POWER_MONITOR_INA226=y +CONFIG_DRIVERS_PWM_INPUT=y +CONFIG_DRIVERS_PWM_OUT=y +CONFIG_DRIVERS_PX4IO=y +CONFIG_DRIVERS_SMART_BATTERY_BATMON=y +CONFIG_COMMON_TELEMETRY=y +CONFIG_DRIVERS_TONE_ALARM=y +CONFIG_DRIVERS_TRANSPONDER_SAGETECH_MXS=y +CONFIG_DRIVERS_UAVCAN=y +CONFIG_MODULES_AIRSPEED_SELECTOR=y +CONFIG_MODULES_BATTERY_STATUS=y +CONFIG_MODULES_CAMERA_FEEDBACK=y +CONFIG_MODULES_COMMANDER=y +CONFIG_MODULES_CONTROL_ALLOCATOR=y +CONFIG_MODULES_DATAMAN=y +CONFIG_MODULES_EKF2=y +CONFIG_MODULES_ESC_BATTERY=y +CONFIG_MODULES_EVENTS=y +CONFIG_MODULES_FLIGHT_MODE_MANAGER=y +CONFIG_MODULES_FW_ATT_CONTROL=y +CONFIG_MODULES_FW_AUTOTUNE_ATTITUDE_CONTROL=y +CONFIG_MODULES_FW_POS_CONTROL_L1=y +CONFIG_MODULES_FW_RATE_CONTROL=y +CONFIG_MODULES_GIMBAL=y +CONFIG_MODULES_GYRO_CALIBRATION=y +CONFIG_MODULES_GYRO_FFT=y +CONFIG_MODULES_LAND_DETECTOR=y +CONFIG_MODULES_LANDING_TARGET_ESTIMATOR=y +CONFIG_MODULES_LOAD_MON=y +CONFIG_MODULES_LOGGER=y +CONFIG_MODULES_MAG_BIAS_ESTIMATOR=y +CONFIG_MODULES_MANUAL_CONTROL=y +CONFIG_MODULES_MAVLINK=y +CONFIG_MODULES_MC_ATT_CONTROL=y +CONFIG_MODULES_MC_AUTOTUNE_ATTITUDE_CONTROL=y +CONFIG_MODULES_MC_HOVER_THRUST_ESTIMATOR=y +CONFIG_MODULES_MC_POS_CONTROL=y +CONFIG_MODULES_MC_RATE_CONTROL=y +CONFIG_MODULES_MICRODDS_CLIENT=y +CONFIG_MODULES_NAVIGATOR=y +CONFIG_MODULES_RC_UPDATE=y +CONFIG_MODULES_ROVER_POS_CONTROL=y +CONFIG_MODULES_SENSORS=y +CONFIG_MODULES_SIMULATION_SIMULATOR_SIH=y +CONFIG_MODULES_TEMPERATURE_COMPENSATION=y +CONFIG_MODULES_VTOL_ATT_CONTROL=y +CONFIG_SYSTEMCMDS_ACTUATOR_TEST=y +CONFIG_SYSTEMCMDS_BL_UPDATE=y +CONFIG_SYSTEMCMDS_BSONDUMP=y +CONFIG_SYSTEMCMDS_DMESG=y +CONFIG_SYSTEMCMDS_DUMPFILE=y +CONFIG_SYSTEMCMDS_GPIO=y +CONFIG_SYSTEMCMDS_HARDFAULT_LOG=y +CONFIG_SYSTEMCMDS_I2CDETECT=y +CONFIG_SYSTEMCMDS_LED_CONTROL=y +CONFIG_SYSTEMCMDS_MFT=y +CONFIG_SYSTEMCMDS_MTD=y +CONFIG_SYSTEMCMDS_NSHTERM=y +CONFIG_SYSTEMCMDS_PARAM=y +CONFIG_SYSTEMCMDS_PERF=y +CONFIG_SYSTEMCMDS_REBOOT=y +CONFIG_SYSTEMCMDS_REFLECT=y +CONFIG_SYSTEMCMDS_SD_BENCH=y +CONFIG_SYSTEMCMDS_SYSTEM_TIME=y +CONFIG_SYSTEMCMDS_TOP=y +CONFIG_SYSTEMCMDS_TOPIC_LISTENER=y +CONFIG_SYSTEMCMDS_TUNE_CONTROL=y +CONFIG_SYSTEMCMDS_UORB=y +CONFIG_SYSTEMCMDS_USB_CONNECTED=y +CONFIG_SYSTEMCMDS_VER=y +CONFIG_SYSTEMCMDS_WORK_QUEUE=y diff --git a/boards/cubepilot/cubeorangeplus/extras/cubepilot_cubeorangeplus_bootloader.bin b/boards/cubepilot/cubeorangeplus/extras/cubepilot_cubeorangeplus_bootloader.bin new file mode 100755 index 0000000000000000000000000000000000000000..fef54cd6d8a7f8e611b26e924b1b5305a6a32217 GIT binary patch literal 43624 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 + * + * 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 NuttX 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 OWNER 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. + * + ************************************************************************************/ +#pragma once + +#include "board_dma_map.h" + +#include + +#ifndef __ASSEMBLY__ +# include +#endif + +#include "stm32_rcc.h" +#include "stm32_sdmmc.h" + +/* Clocking *************************************************************************/ +/* The board provides the following clock sources: + * + * X1: 24 MHz crystal for HSE + * + * So we have these clock source available within the STM32 + * + * HSI: 16 MHz RC factory-trimmed internal oscillator + * HSE: 24 MHz crystal for HSE + */ +#define STM32_BOARD_XTAL 24000000ul + +#define STM32_HSI_FREQUENCY 16000000ul +#define STM32_LSI_FREQUENCY 32000 +#define STM32_HSE_FREQUENCY STM32_BOARD_XTAL + +/* Main PLL Configuration. + * + * PLL source is HSE = 24,000,000 + * + * PLL_VCOx = (STM32_HSE_FREQUENCY / PLLM) * PLLN + * Subject to: + * + * 1 <= PLLM <= 63 + * 4 <= PLLN <= 512 + * 150 MHz <= PLL_VCOL <= 420MHz + * 192 MHz <= PLL_VCOH <= 836MHz + * + * SYSCLK = PLL_VCO / PLLP + * CPUCLK = SYSCLK / D1CPRE + * Subject to + * + * PLLP1 = {2, 4, 6, 8, ..., 128} + * PLLP2,3 = {2, 3, 4, ..., 128} + * CPUCLK <= 480 MHz + */ + +/* PLL1, wide 4 - 8 MHz input, enable DIVP, DIVQ, DIVR + * + * PLL1_VCO = (24,000,000 / 3) * 100 = 800 MHz + * + * PLL1P = PLL1_VCO/2 = 800 MHz / 2 = 400 MHz + * PLL1Q = PLL1_VCO/8 = 800 MHz / 8 = 100 MHz + * PLL1R = PLL1_VCO/2 = 800 MHz / 2 = 400 MHz + */ +#define STM32_PLLCFG_PLL1CFG (RCC_PLLCFGR_PLL1VCOSEL_WIDE|RCC_PLLCFGR_PLL1RGE_4_8_MHZ|RCC_PLLCFGR_DIVP1EN|RCC_PLLCFGR_DIVQ1EN|RCC_PLLCFGR_DIVR1EN) +#define STM32_PLLCFG_PLL1M RCC_PLLCKSELR_DIVM1(3) +#define STM32_PLLCFG_PLL1N RCC_PLL1DIVR_N1(100) +#define STM32_PLLCFG_PLL1P RCC_PLL1DIVR_P1(2) +#define STM32_PLLCFG_PLL1Q RCC_PLL1DIVR_Q1(8) +#define STM32_PLLCFG_PLL1R RCC_PLL1DIVR_R1(2) + +#define STM32_VCO1_FREQUENCY ((STM32_HSE_FREQUENCY / 3) * 100) +#define STM32_PLL1P_FREQUENCY (STM32_VCO1_FREQUENCY / 2) +#define STM32_PLL1Q_FREQUENCY (STM32_VCO1_FREQUENCY / 8) +#define STM32_PLL1R_FREQUENCY (STM32_VCO1_FREQUENCY / 2) + +/* PLL2 */ +#define STM32_PLLCFG_PLL2CFG (RCC_PLLCFGR_PLL2VCOSEL_WIDE|RCC_PLLCFGR_PLL2RGE_4_8_MHZ|RCC_PLLCFGR_DIVP2EN|RCC_PLLCFGR_DIVQ2EN|RCC_PLLCFGR_DIVR2EN) +#define STM32_PLLCFG_PLL2M RCC_PLLCKSELR_DIVM2(2) +#define STM32_PLLCFG_PLL2N RCC_PLL2DIVR_N2(30) +#define STM32_PLLCFG_PLL2P RCC_PLL2DIVR_P2(4) +#define STM32_PLLCFG_PLL2Q RCC_PLL2DIVR_Q2(5) +#define STM32_PLLCFG_PLL2R RCC_PLL2DIVR_R2(1) + +#define STM32_VCO2_FREQUENCY ((STM32_HSE_FREQUENCY / 2) * 30) +#define STM32_PLL2P_FREQUENCY (STM32_VCO2_FREQUENCY / 4) +#define STM32_PLL2Q_FREQUENCY (STM32_VCO2_FREQUENCY / 5) +#define STM32_PLL2R_FREQUENCY (STM32_VCO2_FREQUENCY / 1) + +/* PLL3 */ +#define STM32_PLLCFG_PLL3CFG (RCC_PLLCFGR_PLL3VCOSEL_WIDE|RCC_PLLCFGR_PLL3RGE_4_8_MHZ|RCC_PLLCFGR_DIVQ3EN) +#define STM32_PLLCFG_PLL3M RCC_PLLCKSELR_DIVM3(6) +#define STM32_PLLCFG_PLL3N RCC_PLL3DIVR_N3(72) +#define STM32_PLLCFG_PLL3P RCC_PLL3DIVR_P3(3) +#define STM32_PLLCFG_PLL3Q RCC_PLL3DIVR_Q3(6) +#define STM32_PLLCFG_PLL3R RCC_PLL3DIVR_R3(9) + +#define STM32_VCO3_FREQUENCY ((STM32_HSE_FREQUENCY / 6) * 72) +#define STM32_PLL3P_FREQUENCY (STM32_VCO3_FREQUENCY / 3) +#define STM32_PLL3Q_FREQUENCY (STM32_VCO3_FREQUENCY / 6) +#define STM32_PLL3R_FREQUENCY (STM32_VCO3_FREQUENCY / 9) + +/* SYSCLK = PLL1P = 400MHz + * CPUCLK = SYSCLK / 1 = 400 MHz + */ +#define STM32_RCC_D1CFGR_D1CPRE (RCC_D1CFGR_D1CPRE_SYSCLK) +#define STM32_SYSCLK_FREQUENCY (STM32_PLL1P_FREQUENCY) +#define STM32_CPUCLK_FREQUENCY (STM32_SYSCLK_FREQUENCY / 1) + +/* Configure Clock Assignments */ + +/* AHB clock (HCLK) is SYSCLK/2 (240 MHz max) + * HCLK1 = HCLK2 = HCLK3 = HCLK4 = 200 + */ +#define STM32_RCC_D1CFGR_HPRE RCC_D1CFGR_HPRE_SYSCLKd2 /* HCLK = SYSCLK / 2 */ +#define STM32_ACLK_FREQUENCY (STM32_CPUCLK_FREQUENCY / 2) /* ACLK in D1, HCLK3 in D1 */ +#define STM32_HCLK_FREQUENCY (STM32_CPUCLK_FREQUENCY / 2) /* HCLK in D2, HCLK4 in D3 */ +#define STM32_BOARD_HCLK STM32_HCLK_FREQUENCY /* same as above, to satisfy compiler */ + +/* APB1 clock (PCLK1) is HCLK/4 (120 MHz) */ +#define STM32_RCC_D2CFGR_D2PPRE1 RCC_D2CFGR_D2PPRE1_HCLKd2 /* PCLK1 = HCLK / 2 */ +#define STM32_PCLK1_FREQUENCY (STM32_HCLK_FREQUENCY/2) + +/* APB2 clock (PCLK2) is HCLK/2 (120 MHz) */ +#define STM32_RCC_D2CFGR_D2PPRE2 RCC_D2CFGR_D2PPRE2_HCLKd2 /* PCLK2 = HCLK / 2 */ +#define STM32_PCLK2_FREQUENCY (STM32_HCLK_FREQUENCY/2) + +/* APB3 clock (PCLK3) is HCLK/2 (120 MHz) */ +#define STM32_RCC_D1CFGR_D1PPRE RCC_D1CFGR_D1PPRE_HCLKd2 /* PCLK3 = HCLK / 2 */ +#define STM32_PCLK3_FREQUENCY (STM32_HCLK_FREQUENCY/2) + +/* APB4 clock (PCLK4) is HCLK/4 (120 MHz) */ +#define STM32_RCC_D3CFGR_D3PPRE RCC_D3CFGR_D3PPRE_HCLKd2 /* PCLK4 = HCLK / 2 */ +#define STM32_PCLK4_FREQUENCY (STM32_HCLK_FREQUENCY/2) + +/* Timer clock frequencies */ + +/* 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) + +/* 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_TIM15_CLKIN (2*STM32_PCLK2_FREQUENCY) +#define STM32_APB2_TIM16_CLKIN (2*STM32_PCLK2_FREQUENCY) +#define STM32_APB2_TIM17_CLKIN (2*STM32_PCLK2_FREQUENCY) + +/* Kernel Clock Configuration + * Note: look at Table 54 in ST Manual + */ +#define STM32_RCC_D1CCIPR_SDMMCSEL RCC_D1CCIPR_SDMMC_PLL1 + +#define STM32_RCC_D2CCIP2R_I2C123SRC RCC_D2CCIP2R_I2C123SEL_HSI /* I2C123 clock source */ +#define STM32_RCC_D2CCIP1R_SPI123SRC RCC_D2CCIP1R_SPI123SEL_PLL2 /* SPI123 clock source */ +#define STM32_RCC_D2CCIP1R_SPI45SRC RCC_D2CCIP1R_SPI45SEL_PLL2 /* SPI45 clock source */ +#define STM32_RCC_D2CCIP2R_USBSRC RCC_D2CCIP2R_USBSEL_PLL3 /* USB 1 and 2 clock source */ +#define STM32_RCC_D2CCIP1R_FDCANSEL RCC_D2CCIP1R_FDCANSEL_HSE /* FDCAN 1 2 clock source */ + +#define STM32_RCC_D3CCIPR_ADCSEL RCC_D3CCIPR_ADCSEL_PLL2 /* ADC 1 2 3 clock source */ + +/* FLASH wait states */ +#define BOARD_FLASH_WAITSTATES 2 + +/* SDMMC definitions ********************************************************/ +/* Init 400kHz, freq = PLL1Q/(2*div) div = PLL1Q/(2*freq) */ +#define STM32_SDMMC_INIT_CLKDIV (125 << STM32_SDMMC_CLKCR_CLKDIV_SHIFT) + +/* 25 MHz Max for now, 25 mHZ = PLL1Q/(2*div), div = PLL1Q/(2*freq) + * div = 100 / (2*25) + */ +#define STM32_SDMMC_MMCXFR_CLKDIV (2 << STM32_SDMMC_CLKCR_CLKDIV_SHIFT) +#define STM32_SDMMC_SDXFR_CLKDIV (2 << STM32_SDMMC_CLKCR_CLKDIV_SHIFT) + +#define STM32_SDMMC_CLKCR_EDGE STM32_SDMMC_CLKCR_NEGEDGE + + +/* UART/USART */ +#define GPIO_USART2_TX GPIO_USART2_TX_2 /* PD5 */ +#define GPIO_USART2_RX GPIO_USART2_RX_2 /* PD6 */ +#define GPIO_USART2_CTS GPIO_USART2_CTS_NSS_2 /* PD3 */ +#define GPIO_USART2_RTS GPIO_USART2_RTS_2 /* PD4 */ + +#define GPIO_USART3_TX GPIO_USART3_TX_3 /* PD8 */ +#define GPIO_USART3_RX GPIO_USART3_RX_3 /* PD9 */ +#define GPIO_USART3_CTS GPIO_USART3_CTS_NSS_2 /* PD11 */ +#define GPIO_USART3_RTS GPIO_USART3_RTS_2 /* PD12 */ + +#define GPIO_UART4_TX GPIO_UART4_TX_2 /* PA0 */ +#define GPIO_UART4_RX GPIO_UART4_RX_2 /* PA1 */ + +#define GPIO_USART6_TX GPIO_USART6_TX_1 /* PC6 */ +#define GPIO_USART6_RX GPIO_USART6_RX_1 /* PC7 */ + +#define GPIO_UART7_TX GPIO_UART7_TX_3 /* PE8 */ +#define GPIO_UART7_RX GPIO_UART7_RX_3 /* PE7 */ + +#define GPIO_UART8_TX GPIO_UART8_TX_1 /* PE1 */ +#define GPIO_UART8_RX GPIO_UART8_RX_1 /* PE0 */ + + +/* CAN */ +#define GPIO_CAN1_RX GPIO_CAN1_RX_3 /* PD0 */ +#define GPIO_CAN1_TX GPIO_CAN1_TX_3 /* PD1 */ + +#define GPIO_CAN2_RX GPIO_CAN2_RX_1 /* PB12 */ +#define GPIO_CAN2_TX GPIO_CAN2_TX_2 /* PB6 */ + + +/* SPI */ +#define ADJ_SLEW_RATE(p) (((p) & ~GPIO_SPEED_MASK) | (GPIO_SPEED_2MHz)) + +#define GPIO_SPI1_SCK ADJ_SLEW_RATE(GPIO_SPI1_SCK_1) /* PA5 */ +#define GPIO_SPI1_MISO GPIO_SPI1_MISO_1 /* PA6 */ +#define GPIO_SPI1_MOSI GPIO_SPI1_MOSI_1 /* PA7 */ + +#define GPIO_SPI2_SCK ADJ_SLEW_RATE(GPIO_SPI2_SCK_4) /* PB13 */ +#define GPIO_SPI2_MISO GPIO_SPI2_MISO_1 /* PB14 */ +#define GPIO_SPI2_MOSI GPIO_SPI2_MOSI_1 /* PB15 */ + +#define GPIO_SPI4_SCK ADJ_SLEW_RATE(GPIO_SPI4_SCK_2) /* PE2 */ +#define GPIO_SPI4_MISO GPIO_SPI4_MISO_2 /* PE5 */ +#define GPIO_SPI4_MOSI GPIO_SPI4_MOSI_2 /* PE6 */ + + +/* I2C */ +#define GPIO_I2C1_SCL GPIO_I2C1_SCL_2 /* PB8 */ +#define GPIO_I2C1_SDA GPIO_I2C1_SDA_2 /* PB9 */ + +#define GPIO_I2C2_SCL GPIO_I2C2_SCL_1 /* PB10 */ +#define GPIO_I2C2_SDA GPIO_I2C2_SDA_1 /* PB11 */ diff --git a/boards/cubepilot/cubeorangeplus/nuttx-config/include/board_dma_map.h b/boards/cubepilot/cubeorangeplus/nuttx-config/include/board_dma_map.h new file mode 100644 index 00000000000..050ae597d95 --- /dev/null +++ b/boards/cubepilot/cubeorangeplus/nuttx-config/include/board_dma_map.h @@ -0,0 +1,44 @@ +/**************************************************************************** + * + * Copyright (c) 2020 PX4 Development Team. 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. 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 PX4 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 OWNER 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. + * + ****************************************************************************/ + +#pragma once + +// DMAMUX1 +#define DMAMAP_SPI1_RX DMAMAP_DMA12_SPI1RX_0 /* DMA1:37 */ +#define DMAMAP_SPI1_TX DMAMAP_DMA12_SPI1TX_0 /* DMA1:38 */ + +#define DMAMAP_USART6_RX DMAMAP_DMA12_USART6RX_1 /* DMA1:71 */ +#define DMAMAP_USART6_TX DMAMAP_DMA12_USART6TX_1 /* DMA1:72 */ + +#define DMAMAP_SPI4_RX DMAMAP_DMA12_SPI4RX_0 /* DMA1:83 */ +#define DMAMAP_SPI4_TX DMAMAP_DMA12_SPI4TX_0 /* DMA1:84 */ diff --git a/boards/cubepilot/cubeorangeplus/nuttx-config/nsh/defconfig b/boards/cubepilot/cubeorangeplus/nuttx-config/nsh/defconfig new file mode 100644 index 00000000000..ebacd19ef59 --- /dev/null +++ b/boards/cubepilot/cubeorangeplus/nuttx-config/nsh/defconfig @@ -0,0 +1,256 @@ +# +# 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_DEV_CONSOLE is not set +# CONFIG_DISABLE_ENVIRON is not set +# CONFIG_DISABLE_PSEUDOFS_OPERATIONS is not set +# CONFIG_DISABLE_PTHREAD is not set +# CONFIG_MMCSD_HAVE_CARDDETECT is not set +# CONFIG_MMCSD_HAVE_WRITEPROTECT is not set +# CONFIG_MMCSD_MMCSUPPORT is not set +# CONFIG_MMCSD_SPI is not set +# CONFIG_NSH_DISABLEBG is not set +# CONFIG_NSH_DISABLESCRIPT is not set +# CONFIG_NSH_DISABLE_CAT is not set +# CONFIG_NSH_DISABLE_CD is not set +# CONFIG_NSH_DISABLE_CP is not set +# CONFIG_NSH_DISABLE_DATE is not set +# CONFIG_NSH_DISABLE_DF is not set +# CONFIG_NSH_DISABLE_ECHO is not set +# CONFIG_NSH_DISABLE_ENV is not set +# CONFIG_NSH_DISABLE_EXEC is not set +# CONFIG_NSH_DISABLE_EXIT is not set +# CONFIG_NSH_DISABLE_EXPORT is not set +# CONFIG_NSH_DISABLE_FREE is not set +# CONFIG_NSH_DISABLE_GET is not set +# CONFIG_NSH_DISABLE_HELP is not set +# CONFIG_NSH_DISABLE_ITEF is not set +# CONFIG_NSH_DISABLE_KILL is not set +# CONFIG_NSH_DISABLE_LOOPS is not set +# CONFIG_NSH_DISABLE_LS is not set +# CONFIG_NSH_DISABLE_MKDIR is not set +# CONFIG_NSH_DISABLE_MKFATFS is not set +# CONFIG_NSH_DISABLE_MOUNT is not set +# CONFIG_NSH_DISABLE_MV is not set +# CONFIG_NSH_DISABLE_PS is not set +# CONFIG_NSH_DISABLE_PSSTACKUSAGE is not set +# CONFIG_NSH_DISABLE_PWD is not set +# CONFIG_NSH_DISABLE_RM is not set +# CONFIG_NSH_DISABLE_RMDIR is not set +# CONFIG_NSH_DISABLE_SEMICOLON is not set +# CONFIG_NSH_DISABLE_SET is not set +# CONFIG_NSH_DISABLE_SLEEP is not set +# CONFIG_NSH_DISABLE_SOURCE is not set +# CONFIG_NSH_DISABLE_TEST is not set +# CONFIG_NSH_DISABLE_TIME is not set +# CONFIG_NSH_DISABLE_UMOUNT is not set +# CONFIG_NSH_DISABLE_UNSET is not set +# CONFIG_NSH_DISABLE_USLEEP is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD_CUSTOM=y +CONFIG_ARCH_BOARD_CUSTOM_DIR="../../../../boards/cubepilot/cubeorangeplus/nuttx-config" +CONFIG_ARCH_BOARD_CUSTOM_DIR_RELPATH=y +CONFIG_ARCH_BOARD_CUSTOM_NAME="px4" +CONFIG_ARCH_CHIP="stm32h7" +CONFIG_ARCH_CHIP_STM32H747XI=y +CONFIG_ARCH_CHIP_STM32H7=y +CONFIG_ARCH_INTERRUPTSTACK=768 +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARMV7M_BASEPRI_WAR=y +CONFIG_ARMV7M_DCACHE=y +CONFIG_ARMV7M_DTCM=y +CONFIG_ARMV7M_ICACHE=y +CONFIG_ARMV7M_MEMCPY=y +CONFIG_ARMV7M_USEBASEPRI=y +CONFIG_ARM_MPU_EARLY_RESET=y +CONFIG_BOARDCTL_RESET=y +CONFIG_BOARD_ASSERT_RESET_VALUE=0 +CONFIG_BOARD_CRASHDUMP=y +CONFIG_BOARD_LOOPSPERMSEC=79954 +CONFIG_BOARD_RESET_ON_ASSERT=2 +CONFIG_BUILTIN=y +CONFIG_CDCACM=y +CONFIG_CDCACM_IFLOWCONTROL=y +CONFIG_CDCACM_PRODUCTID=0x1058 +CONFIG_CDCACM_PRODUCTSTR="CubeOrange+" +CONFIG_CDCACM_RXBUFSIZE=600 +CONFIG_CDCACM_TXBUFSIZE=12000 +CONFIG_CDCACM_VENDORID=0x2DAE +CONFIG_CDCACM_VENDORSTR="CubePilot" +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_HARDFAULT_ALERT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEBUG_TCBINFO=y +CONFIG_DEFAULT_SMALL=y +CONFIG_DEV_FIFO_SIZE=0 +CONFIG_DEV_PIPE_MAXSIZE=1024 +CONFIG_DEV_PIPE_SIZE=70 +CONFIG_EXPERIMENTAL=y +CONFIG_FAT_DMAMEMORY=y +CONFIG_FAT_LCNAMES=y +CONFIG_FAT_LFN=y +CONFIG_FAT_LFN_ALIAS_HASH=y +CONFIG_FDCLONE_STDIO=y +CONFIG_FS_BINFS=y +CONFIG_FS_CROMFS=y +CONFIG_FS_FAT=y +CONFIG_FS_FATTIME=y +CONFIG_FS_PROCFS=y +CONFIG_FS_PROCFS_INCLUDE_PROGMEM=y +CONFIG_FS_PROCFS_MAX_TASKS=64 +CONFIG_FS_PROCFS_REGISTER=y +CONFIG_FS_ROMFS=y +CONFIG_GRAN=y +CONFIG_GRAN_INTR=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_I2C=y +CONFIG_I2C_RESET=y +CONFIG_IDLETHREAD_STACKSIZE=750 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INIT_STACKSIZE=2944 +CONFIG_LIBC_FLOATINGPOINT=y +CONFIG_LIBC_LONG_LONG=y +CONFIG_LIBC_MAX_EXITFUNS=1 +CONFIG_LIBC_STRERROR=y +CONFIG_MEMSET_64BIT=y +CONFIG_MEMSET_OPTSPEED=y +CONFIG_MMCSD=y +CONFIG_MMCSD_SDIO=y +CONFIG_MMCSD_SDIOWAIT_WRCOMPLETE=y +CONFIG_MM_REGIONS=4 +CONFIG_MTD=y +CONFIG_MTD_BYTE_WRITE=y +CONFIG_MTD_PARTITION=y +CONFIG_MTD_PROGMEM=y +CONFIG_MTD_RAMTRON=y +CONFIG_NAME_MAX=40 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_ARGCAT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_CMDPARMS=y +CONFIG_NSH_CROMFSETC=y +CONFIG_NSH_LINELEN=128 +CONFIG_NSH_MAXARGUMENTS=15 +CONFIG_NSH_NESTDEPTH=8 +CONFIG_NSH_QUOTE=y +CONFIG_NSH_ROMFSETC=y +CONFIG_NSH_ROMFSSECTSIZE=128 +CONFIG_NSH_STRERROR=y +CONFIG_NSH_VARS=y +CONFIG_OTG_ID_GPIO_DISABLE=y +CONFIG_PIPES=y +CONFIG_PREALLOC_TIMERS=50 +CONFIG_PRIORITY_INHERITANCE=y +CONFIG_PTHREAD_MUTEX_ROBUST=y +CONFIG_PTHREAD_STACK_MIN=512 +CONFIG_RAMTRON_SETSPEED=y +CONFIG_RAM_SIZE=245760 +CONFIG_RAM_START=0x20010000 +CONFIG_RAW_BINARY=y +CONFIG_READLINE_CMD_HISTORY=y +CONFIG_READLINE_TABCOMPLETION=y +CONFIG_RTC_DATETIME=y +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_HPWORKPRIORITY=249 +CONFIG_SCHED_HPWORKSTACKSIZE=1280 +CONFIG_SCHED_INSTRUMENTATION=y +CONFIG_SCHED_INSTRUMENTATION_EXTERNAL=y +CONFIG_SCHED_INSTRUMENTATION_SWITCH=y +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_LPWORKPRIORITY=50 +CONFIG_SCHED_LPWORKSTACKSIZE=1632 +CONFIG_SCHED_WAITPID=y +CONFIG_SDMMC1_SDIO_PULLUP=y +CONFIG_SEM_PREALLOCHOLDERS=32 +CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS=y +CONFIG_SERIAL_TERMIOS=y +CONFIG_SIG_DEFAULT=y +CONFIG_SIG_SIGALRM_ACTION=y +CONFIG_SIG_SIGUSR1_ACTION=y +CONFIG_SIG_SIGUSR2_ACTION=y +CONFIG_SIG_SIGWORK=4 +CONFIG_STACK_COLORATION=y +CONFIG_START_DAY=30 +CONFIG_START_MONTH=11 +CONFIG_STDIO_BUFFER_SIZE=256 +CONFIG_STM32H7_ADC1=y +CONFIG_STM32H7_ADC3=y +CONFIG_STM32H7_BBSRAM=y +CONFIG_STM32H7_BBSRAM_FILES=5 +CONFIG_STM32H7_BKPSRAM=y +CONFIG_STM32H7_DMA1=y +CONFIG_STM32H7_DMA2=y +CONFIG_STM32H7_DMACAPABLE=y +CONFIG_STM32H7_FLOWCONTROL_BROKEN=y +CONFIG_STM32H7_I2C1=y +CONFIG_STM32H7_I2C2=y +CONFIG_STM32H7_I2C_DYNTIMEO=y +CONFIG_STM32H7_I2C_DYNTIMEO_STARTSTOP=10 +CONFIG_STM32H7_OTGFS=y +CONFIG_STM32H7_PWR_DIRECT_SMPS_SUPPLY=y +CONFIG_STM32H7_PROGMEM=y +CONFIG_STM32H7_RTC=y +CONFIG_STM32H7_RTC_HSECLOCK=y +CONFIG_STM32H7_RTC_MAGIC_REG=1 +CONFIG_STM32H7_SAVE_CRASHDUMP=y +CONFIG_STM32H7_SDMMC1=y +CONFIG_STM32H7_SERIALBRK_BSDCOMPAT=y +CONFIG_STM32H7_SERIAL_DISABLE_REORDERING=y +CONFIG_STM32H7_SPI1=y +CONFIG_STM32H7_SPI1_DMA=y +CONFIG_STM32H7_SPI1_DMA_BUFFER=1024 +CONFIG_STM32H7_SPI2=y +CONFIG_STM32H7_SPI4=y +CONFIG_STM32H7_SPI4_DMA=y +CONFIG_STM32H7_SPI4_DMA_BUFFER=1024 +CONFIG_STM32H7_TIM1=y +CONFIG_STM32H7_TIM3=y +CONFIG_STM32H7_TIM4=y +CONFIG_STM32H7_UART4=y +CONFIG_STM32H7_UART7=y +CONFIG_STM32H7_UART8=y +CONFIG_STM32H7_USART2=y +CONFIG_STM32H7_USART3=y +CONFIG_STM32H7_USART6=y +CONFIG_STM32H7_USART_BREAKS=y +CONFIG_STM32H7_USART_INVERT=y +CONFIG_STM32H7_USART_SINGLEWIRE=y +CONFIG_STM32H7_USART_SWAP=y +CONFIG_SYSTEM_CDCACM=y +CONFIG_SYSTEM_NSH=y +CONFIG_TASK_NAME_SIZE=24 +CONFIG_TTY_SIGINT=y +CONFIG_TTY_SIGINT_CHAR=0x03 +CONFIG_TTY_SIGTSTP=y +CONFIG_UART4_BAUD=57600 +CONFIG_UART4_RXBUFSIZE=600 +CONFIG_UART4_TXBUFSIZE=1500 +CONFIG_UART7_BAUD=57600 +CONFIG_UART7_RXBUFSIZE=600 +CONFIG_UART7_TXBUFSIZE=1500 +CONFIG_UART8_BAUD=57600 +CONFIG_UART8_RXBUFSIZE=600 +CONFIG_UART8_TXBUFSIZE=1500 +CONFIG_USART2_BAUD=57600 +CONFIG_USART2_IFLOWCONTROL=y +CONFIG_USART2_OFLOWCONTROL=y +CONFIG_USART2_RXBUFSIZE=600 +CONFIG_USART2_TXBUFSIZE=1500 +CONFIG_USART3_BAUD=57600 +CONFIG_USART3_IFLOWCONTROL=y +CONFIG_USART3_OFLOWCONTROL=y +CONFIG_USART3_RXBUFSIZE=600 +CONFIG_USART3_TXBUFSIZE=3000 +CONFIG_USART6_BAUD=57600 +CONFIG_USART6_RXBUFSIZE=600 +CONFIG_USART6_TXBUFSIZE=1500 +CONFIG_USBDEV=y +CONFIG_USBDEV_BUSPOWERED=y +CONFIG_USBDEV_MAXPOWER=500 +CONFIG_USEC_PER_TICK=1000 +CONFIG_WATCHDOG=y diff --git a/boards/cubepilot/cubeorangeplus/nuttx-config/scripts/bootloader_script.ld b/boards/cubepilot/cubeorangeplus/nuttx-config/scripts/bootloader_script.ld new file mode 100644 index 00000000000..4a255ada187 --- /dev/null +++ b/boards/cubepilot/cubeorangeplus/nuttx-config/scripts/bootloader_script.ld @@ -0,0 +1,223 @@ +/**************************************************************************** + * scripts/script.ld + * + * Copyright (C) 2020 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * + * 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 NuttX 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 OWNER 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. + * + ****************************************************************************/ + +/* The board uses an STM32H757ZI has 2048Kb of main FLASH memory. + * The flash memory is partitioned into a User Flash memory and a System + * Flash memory. Each of these memories has two banks: + * + * 1) User Flash memory: + * + * Bank 1: Start address 0x0800:0000 to 0x080F:FFFF with 8 sectors, 128Kb each + * Bank 2: Start address 0x0810:0000 to 0x081F:FFFF with 8 sectors, 128Kb each + * + * 2) System Flash memory: + * + * Bank 1: Start address 0x1FF0:0000 to 0x1FF1:FFFF with 1 x 128Kb sector + * Bank 1: Start address 0x1FF4:0000 to 0x1FF5:FFFF with 1 x 128Kb sector + * + * 3) User option bytes for user configuration, only in Bank 1. + * + * In the STM32H757ZI, two different boot spaces can be selected through + * the BOOT pin and the boot base address programmed in the BOOT_ADD0 and + * BOOT_ADD1 option bytes: + * + * 1) BOOT=0: Boot address defined by user option byte BOOT_ADD0[15:0]. + * ST programmed value: Flash memory at 0x0800:0000 + * 2) BOOT=1: Boot address defined by user option byte BOOT_ADD1[15:0]. + * ST programmed value: System bootloader at 0x1FF0:0000 + * + * There's a switch on board, the BOOT0 pin is at ground so by default, + * the STM32 will boot to address 0x0800:0000 in FLASH unless the switch is + * drepresed, then the boot will be from 0x1FF0:0000 + * + * The STM32H757ZI also has 1024Kb of data SRAM. + * SRAM is split up into several blocks and into three power domains: + * + * 1) TCM SRAMs are dedicated to the Cortex-M7 and are accessible with + * 0 wait states by the Cortex-M7 and by MDMA through AHBS slave bus + * + * 1.1) 128Kb of DTCM-RAM beginning at address 0x2000:0000 + * + * The DTCM-RAM is organized as 2 x 64Kb DTCM-RAMs on 2 x 32 bit + * DTCM ports. The DTCM-RAM could be used for critical real-time + * data, such as interrupt service routines or stack / heap memory. + * Both DTCM-RAMs can be used in parallel (for load/store operations) + * thanks to the Cortex-M7 dual issue capability. + * + * 1.2) 64Kb of ITCM-RAM beginning at address 0x0000:0000 + * + * This RAM is connected to ITCM 64-bit interface designed for + * execution of critical real-times routines by the CPU. + * + * 2) AXI SRAM (D1 domain) accessible by all system masters except BDMA + * through D1 domain AXI bus matrix + * + * 2.1) 512Kb of SRAM beginning at address 0x2400:0000 + * + * 3) AHB SRAM (D2 domain) accessible by all system masters except BDMA + * through D2 domain AHB bus matrix + * + * 3.1) 128Kb of SRAM1 beginning at address 0x3000:0000 + * 3.2) 128Kb of SRAM2 beginning at address 0x3002:0000 + * 3.3) 32Kb of SRAM3 beginning at address 0x3004:0000 + * + * SRAM1 - SRAM3 are one contiguous block: 288Kb at address 0x3000:0000 + * + * 4) AHB SRAM (D3 domain) accessible by most of system masters + * through D3 domain AHB bus matrix + * + * 4.1) 64Kb of SRAM4 beginning at address 0x3800:0000 + * 4.1) 4Kb of backup RAM beginning at address 0x3880: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 = 2048K + DTCM1 (rwx) : ORIGIN = 0x20000000, LENGTH = 64K + DTCM2 (rwx) : ORIGIN = 0x20010000, LENGTH = 64K + + ITCM_RAM (rwx) : ORIGIN = 0x00000000, LENGTH = 64K + DTCM_RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128K + AXI_SRAM (rwx) : ORIGIN = 0x24000000, LENGTH = 512K /* D1 domain AXI bus */ + SRAM1 (rwx) : ORIGIN = 0x30000000, LENGTH = 128K /* D2 domain AHB bus */ + SRAM2 (rwx) : ORIGIN = 0x30020000, LENGTH = 128K /* D2 domain AHB bus */ + SRAM3 (rwx) : ORIGIN = 0x30040000, LENGTH = 32K /* D2 domain AHB bus */ + SRAM4 (rwx) : ORIGIN = 0x38000000, LENGTH = 64K /* D3 domain */ + BKPRAM (rwx) : ORIGIN = 0x38800000, LENGTH = 4K +} + +OUTPUT_ARCH(arm) +EXTERN(_vectors) +ENTRY(_stext) + +/* + * Ensure that abort() is present in the final object. The exception handling + * code pulled in by libgcc.a requires it (and that code cannot be easily avoided). + */ +EXTERN(abort) +EXTERN(_bootdelay_signature) + +SECTIONS +{ + .text : { + _stext = ABSOLUTE(.); + *(.vectors) + . = ALIGN(32); + /* + This signature provides the bootloader with a way to delay booting + */ + _bootdelay_signature = ABSOLUTE(.); + FILL(0xffecc2925d7d05c5) + . += 8; + *(.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 functions (static constructors and the like) + */ + .init_section : { + _sinit = ABSOLUTE(.); + KEEP(*(.init_array .init_array.*)) + _einit = ABSOLUTE(.); + } > FLASH + + .ARM.extab : { + *(.ARM.extab*) + } > FLASH + + __exidx_start = ABSOLUTE(.); + .ARM.exidx : { + *(.ARM.exidx*) + } > FLASH + __exidx_end = ABSOLUTE(.); + + _eronly = ABSOLUTE(.); + + .data : { + _sdata = ABSOLUTE(.); + *(.data .data.*) + *(.gnu.linkonce.d.*) + CONSTRUCTORS + _edata = ABSOLUTE(.); + } > AXI_SRAM AT > FLASH + + .bss : { + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _ebss = ABSOLUTE(.); + } > AXI_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) } + + .ramfunc : { + _sramfuncs = .; + *(.ramfunc .ramfunc.*) + . = ALIGN(4); + _eramfuncs = .; + } > ITCM_RAM AT > FLASH + + _framfuncs = LOADADDR(.ramfunc); +} diff --git a/boards/cubepilot/cubeorangeplus/nuttx-config/scripts/script.ld b/boards/cubepilot/cubeorangeplus/nuttx-config/scripts/script.ld new file mode 100644 index 00000000000..f4aa39bdb83 --- /dev/null +++ b/boards/cubepilot/cubeorangeplus/nuttx-config/scripts/script.ld @@ -0,0 +1,228 @@ +/**************************************************************************** + * scripts/script.ld + * + * Copyright (C) 2020 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * + * 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 NuttX 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 OWNER 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. + * + ****************************************************************************/ + +/* The board uses an STM32H757ZI and has 2048Kb of main FLASH memory. + * The flash memory is partitioned into a User Flash memory and a System + * Flash memory. Each of these memories has two banks: + * + * 1) User Flash memory: + * + * Bank 1: Start address 0x0800:0000 to 0x080F:FFFF with 8 sectors, 128Kb each + * Bank 2: Start address 0x0810:0000 to 0x081F:FFFF with 8 sectors, 128Kb each + * + * 2) System Flash memory: + * + * Bank 1: Start address 0x1FF0:0000 to 0x1FF1:FFFF with 1 x 128Kb sector + * Bank 1: Start address 0x1FF4:0000 to 0x1FF5:FFFF with 1 x 128Kb sector + * + * 3) User option bytes for user configuration, only in Bank 1. + * + * In the STM32H757ZI, two different boot spaces can be selected through + * the BOOT pin and the boot base address programmed in the BOOT_ADD0 and + * BOOT_ADD1 option bytes: + * + * 1) BOOT=0: Boot address defined by user option byte BOOT_ADD0[15:0]. + * ST programmed value: Flash memory at 0x0800:0000 + * 2) BOOT=1: Boot address defined by user option byte BOOT_ADD1[15:0]. + * ST programmed value: System bootloader at 0x1FF0:0000 + * + * There's a switch on board, the BOOT0 pin is at ground so by default, + * the STM32 will boot to address 0x0800:0000 in FLASH unless the switch is + * drepresed, then the boot will be from 0x1FF0:0000 + * + * The STM32H757ZI also has 1024Kb of data SRAM. + * SRAM is split up into several blocks and into three power domains: + * + * 1) TCM SRAMs are dedicated to the Cortex-M7 and are accessible with + * 0 wait states by the Cortex-M7 and by MDMA through AHBS slave bus + * + * 1.1) 128Kb of DTCM-RAM beginning at address 0x2000:0000 + * + * The DTCM-RAM is organized as 2 x 64Kb DTCM-RAMs on 2 x 32 bit + * DTCM ports. The DTCM-RAM could be used for critical real-time + * data, such as interrupt service routines or stack / heap memory. + * Both DTCM-RAMs can be used in parallel (for load/store operations) + * thanks to the Cortex-M7 dual issue capability. + * + * 1.2) 64Kb of ITCM-RAM beginning at address 0x0000:0000 + * + * This RAM is connected to ITCM 64-bit interface designed for + * execution of critical real-times routines by the CPU. + * + * 2) AXI SRAM (D1 domain) accessible by all system masters except BDMA + * through D1 domain AXI bus matrix + * + * 2.1) 512Kb of SRAM beginning at address 0x2400:0000 + * + * 3) AHB SRAM (D2 domain) accessible by all system masters except BDMA + * through D2 domain AHB bus matrix + * + * 3.1) 128Kb of SRAM1 beginning at address 0x3000:0000 + * 3.2) 128Kb of SRAM2 beginning at address 0x3002:0000 + * 3.3) 32Kb of SRAM3 beginning at address 0x3004:0000 + * + * SRAM1 - SRAM3 are one contiguous block: 288Kb at address 0x3000:0000 + * + * 4) AHB SRAM (D3 domain) accessible by most of system masters + * through D3 domain AHB bus matrix + * + * 4.1) 64Kb of SRAM4 beginning at address 0x3800:0000 + * 4.1) 4Kb of backup RAM beginning at address 0x3880: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 +{ + ITCM_RAM (rwx) : ORIGIN = 0x00000000, LENGTH = 64K + FLASH (rx) : ORIGIN = 0x08020000, LENGTH = 1920K + + DTCM1_RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 64K + DTCM2_RAM (rwx) : ORIGIN = 0x20010000, LENGTH = 64K + AXI_SRAM (rwx) : ORIGIN = 0x24000000, LENGTH = 512K /* D1 domain AXI bus */ + SRAM1 (rwx) : ORIGIN = 0x30000000, LENGTH = 128K /* D2 domain AHB bus */ + SRAM2 (rwx) : ORIGIN = 0x30020000, LENGTH = 128K /* D2 domain AHB bus */ + SRAM3 (rwx) : ORIGIN = 0x30040000, LENGTH = 32K /* D2 domain AHB bus */ + SRAM4 (rwx) : ORIGIN = 0x38000000, LENGTH = 64K /* D3 domain */ + BKPRAM (rwx) : ORIGIN = 0x38800000, LENGTH = 4K +} + +OUTPUT_ARCH(arm) +EXTERN(_vectors) +ENTRY(_stext) + +/* + * Ensure that abort() is present in the final object. The exception handling + * code pulled in by libgcc.a requires it (and that code cannot be easily avoided). + */ +EXTERN(abort) +EXTERN(_bootdelay_signature) + +SECTIONS +{ + .text : { + _stext = ABSOLUTE(.); + *(.vectors) + . = ALIGN(32); + /* + This signature provides the bootloader with a way to delay booting + */ + _bootdelay_signature = ABSOLUTE(.); + FILL(0xffecc2925d7d05c5) + . += 8; + *(.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 functions (static constructors and the like) + */ + .init_section : { + _sinit = ABSOLUTE(.); + KEEP(*(.init_array .init_array.*)) + _einit = ABSOLUTE(.); + } > FLASH + + + .ARM.extab : { + *(.ARM.extab*) + } > FLASH + + __exidx_start = ABSOLUTE(.); + .ARM.exidx : { + *(.ARM.exidx*) + } > FLASH + __exidx_end = ABSOLUTE(.); + + _eronly = ABSOLUTE(.); + + .data : { + _sdata = ABSOLUTE(.); + *(.data .data.*) + *(.gnu.linkonce.d.*) + CONSTRUCTORS + _edata = ABSOLUTE(.); + + /* Pad out last section as the STM32H7 Flash write size is 256 bits. 32 bytes */ + . = ALIGN(16); + FILL(0xffff) + . += 16; + } > AXI_SRAM AT > FLASH = 0xffff + + .bss : { + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _ebss = ABSOLUTE(.); + } > AXI_SRAM + + /* Emit the the D3 power domain section for locating BDMA data */ + + .sram4_reserve (NOLOAD) : + { + *(.sram4) + . = ALIGN(4); + _sram4_heap_start = ABSOLUTE(.); + } > SRAM4 + + /* 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/cubepilot/cubeorangeplus/nuttx-config/test/defconfig b/boards/cubepilot/cubeorangeplus/nuttx-config/test/defconfig new file mode 100644 index 00000000000..bbf04319404 --- /dev/null +++ b/boards/cubepilot/cubeorangeplus/nuttx-config/test/defconfig @@ -0,0 +1,235 @@ +# +# 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_DISABLE_ENVIRON is not set +# CONFIG_DISABLE_PSEUDOFS_OPERATIONS is not set +# CONFIG_MMCSD_HAVE_CARDDETECT is not set +# CONFIG_MMCSD_HAVE_WRITEPROTECT is not set +# CONFIG_MMCSD_MMCSUPPORT is not set +# CONFIG_MMCSD_SPI is not set +# CONFIG_NSH_DISABLEBG is not set +# CONFIG_NSH_DISABLESCRIPT is not set +# CONFIG_NSH_DISABLE_DF is not set +# CONFIG_NSH_DISABLE_EXEC is not set +# CONFIG_NSH_DISABLE_EXIT is not set +# CONFIG_NSH_DISABLE_GET is not set +# CONFIG_NSH_DISABLE_ITEF is not set +# CONFIG_NSH_DISABLE_LOOPS is not set +# CONFIG_NSH_DISABLE_MKFATFS is not set +# CONFIG_NSH_DISABLE_SEMICOLON is not set +# CONFIG_NSH_DISABLE_TIME is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD_CUSTOM=y +CONFIG_ARCH_BOARD_CUSTOM_DIR="../../../../boards/cubepilot/cubeorangeplus/nuttx-config" +CONFIG_ARCH_BOARD_CUSTOM_DIR_RELPATH=y +CONFIG_ARCH_BOARD_CUSTOM_NAME="px4" +CONFIG_ARCH_CHIP="stm32h7" +CONFIG_ARCH_CHIP_STM32H747XI=y +CONFIG_ARCH_CHIP_STM32H7=y +CONFIG_ARCH_INTERRUPTSTACK=512 +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARMV7M_BASEPRI_WAR=y +CONFIG_ARMV7M_DCACHE=y +CONFIG_ARMV7M_DTCM=y +CONFIG_ARMV7M_ICACHE=y +CONFIG_ARMV7M_MEMCPY=y +CONFIG_ARMV7M_USEBASEPRI=y +CONFIG_ARM_MPU_EARLY_RESET=y +CONFIG_BOARDCTL_RESET=y +CONFIG_BOARD_CRASHDUMP=y +CONFIG_BOARD_LOOPSPERMSEC=79954 +CONFIG_BOARD_RESET_ON_ASSERT=2 +CONFIG_BUILTIN=y +CONFIG_C99_BOOL8=y +CONFIG_CDCACM=y +CONFIG_CDCACM_IFLOWCONTROL=y +CONFIG_CDCACM_PRODUCTID=0x1058 +CONFIG_CDCACM_PRODUCTSTR="CubeOrange+" +CONFIG_CDCACM_RXBUFSIZE=600 +CONFIG_CDCACM_TXBUFSIZE=12000 +CONFIG_CDCACM_VENDORID=0x2DAE +CONFIG_CDCACM_VENDORSTR="CubePilot" +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_HARDFAULT_ALERT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEFAULT_SMALL=y +CONFIG_DEV_FIFO_SIZE=0 +CONFIG_DEV_PIPE_MAXSIZE=1024 +CONFIG_DEV_PIPE_SIZE=70 +CONFIG_DISABLE_MQUEUE=y +CONFIG_EXAMPLES_CALIB_UDELAY=y +CONFIG_EXPERIMENTAL=y +CONFIG_FAT_DMAMEMORY=y +CONFIG_FAT_LCNAMES=y +CONFIG_FAT_LFN=y +CONFIG_FAT_LFN_ALIAS_HASH=y +CONFIG_FDCLONE_STDIO=y +CONFIG_FS_BINFS=y +CONFIG_FS_CROMFS=y +CONFIG_FS_FAT=y +CONFIG_FS_FATTIME=y +CONFIG_FS_PROCFS=y +CONFIG_FS_PROCFS_INCLUDE_PROGMEM=y +CONFIG_FS_PROCFS_MAX_TASKS=64 +CONFIG_FS_PROCFS_REGISTER=y +CONFIG_FS_ROMFS=y +CONFIG_GRAN=y +CONFIG_GRAN_INTR=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_I2C=y +CONFIG_I2C_RESET=y +CONFIG_IDLETHREAD_STACKSIZE=750 +CONFIG_LIBC_LONG_LONG=y +CONFIG_LIBC_STRERROR=y +CONFIG_MEMSET_64BIT=y +CONFIG_MEMSET_OPTSPEED=y +CONFIG_MMCSD=y +CONFIG_MMCSD_SDIO=y +CONFIG_MMCSD_SDIOWAIT_WRCOMPLETE=y +CONFIG_MM_REGIONS=4 +CONFIG_MTD=y +CONFIG_MTD_BYTE_WRITE=y +CONFIG_MTD_PARTITION=y +CONFIG_MTD_PROGMEM=y +CONFIG_MTD_RAMTRON=y +CONFIG_NAME_MAX=40 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_ARGCAT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_CMDPARMS=y +CONFIG_NSH_CROMFSETC=y +CONFIG_NSH_DISABLE_IFCONFIG=y +CONFIG_NSH_DISABLE_IFUPDOWN=y +CONFIG_NSH_DISABLE_TELNETD=y +CONFIG_NSH_LINELEN=128 +CONFIG_NSH_MAXARGUMENTS=15 +CONFIG_NSH_NESTDEPTH=8 +CONFIG_NSH_QUOTE=y +CONFIG_NSH_ROMFSETC=y +CONFIG_NSH_ROMFSSECTSIZE=128 +CONFIG_NSH_STRERROR=y +CONFIG_NSH_VARS=y +CONFIG_OTG_ID_GPIO_DISABLE=y +CONFIG_PIPES=y +CONFIG_PREALLOC_TIMERS=50 +CONFIG_PRIORITY_INHERITANCE=y +CONFIG_PTHREAD_MUTEX_ROBUST=y +CONFIG_PTHREAD_STACK_MIN=512 +CONFIG_RAMTRON_SETSPEED=y +CONFIG_RAM_SIZE=245760 +CONFIG_RAM_START=0x20010000 +CONFIG_RAW_BINARY=y +CONFIG_READLINE_CMD_HISTORY=y +CONFIG_READLINE_TABCOMPLETION=y +CONFIG_RTC_DATETIME=y +CONFIG_SCHED_ATEXIT=y +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_HPWORKPRIORITY=249 +CONFIG_SCHED_HPWORKSTACKSIZE=1280 +CONFIG_SCHED_INSTRUMENTATION=y +CONFIG_SCHED_INSTRUMENTATION_EXTERNAL=y +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_LPWORKPRIORITY=50 +CONFIG_SCHED_LPWORKSTACKSIZE=1632 +CONFIG_SCHED_WAITPID=y +CONFIG_SDCLONE_DISABLE=y +CONFIG_SDMMC1_SDIO_PULLUP=y +CONFIG_SEM_PREALLOCHOLDERS=32 +CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS=y +CONFIG_SERIAL_TERMIOS=y +CONFIG_SIG_DEFAULT=y +CONFIG_SIG_SIGALRM_ACTION=y +CONFIG_SIG_SIGUSR1_ACTION=y +CONFIG_SIG_SIGUSR2_ACTION=y +CONFIG_SIG_SIGWORK=4 +CONFIG_STACK_COLORATION=y +CONFIG_START_DAY=30 +CONFIG_START_MONTH=11 +CONFIG_STDIO_BUFFER_SIZE=256 +CONFIG_STM32H7_ADC1=y +CONFIG_STM32H7_ADC3=y +CONFIG_STM32H7_BBSRAM=y +CONFIG_STM32H7_BBSRAM_FILES=5 +CONFIG_STM32H7_BKPSRAM=y +CONFIG_STM32H7_DMA1=y +CONFIG_STM32H7_DMA2=y +CONFIG_STM32H7_DMACAPABLE=y +CONFIG_STM32H7_FLOWCONTROL_BROKEN=y +CONFIG_STM32H7_I2C1=y +CONFIG_STM32H7_I2C2=y +CONFIG_STM32H7_I2C_DYNTIMEO=y +CONFIG_STM32H7_I2C_DYNTIMEO_STARTSTOP=10 +CONFIG_STM32H7_OTGFS=y +CONFIG_STM32H7_PROGMEM=y +CONFIG_STM32H7_PWR_DIRECT_SMPS_SUPPLY=y +CONFIG_STM32H7_RTC=y +CONFIG_STM32H7_RTC_HSECLOCK=y +CONFIG_STM32H7_RTC_MAGIC_REG=1 +CONFIG_STM32H7_SAVE_CRASHDUMP=y +CONFIG_STM32H7_SDMMC1=y +CONFIG_STM32H7_SERIALBRK_BSDCOMPAT=y +CONFIG_STM32H7_SERIAL_DISABLE_REORDERING=y +CONFIG_STM32H7_SPI1=y +CONFIG_STM32H7_SPI1_DMA=y +CONFIG_STM32H7_SPI1_DMA_BUFFER=1024 +CONFIG_STM32H7_SPI2=y +CONFIG_STM32H7_SPI4=y +CONFIG_STM32H7_SPI4_DMA=y +CONFIG_STM32H7_SPI4_DMA_BUFFER=1024 +CONFIG_STM32H7_SPI_DMA=y +CONFIG_STM32H7_TIM1=y +CONFIG_STM32H7_TIM3=y +CONFIG_STM32H7_TIM4=y +CONFIG_STM32H7_UART4=y +CONFIG_STM32H7_UART7=y +CONFIG_STM32H7_UART8=y +CONFIG_STM32H7_USART2=y +CONFIG_STM32H7_USART3=y +CONFIG_STM32H7_USART6=y +CONFIG_STM32H7_USART_BREAKS=y +CONFIG_STM32H7_USART_INVERT=y +CONFIG_STM32H7_USART_SINGLEWIRE=y +CONFIG_STM32H7_USART_SWAP=y +CONFIG_SYSTEM_CDCACM=y +CONFIG_SYSTEM_NSH=y +CONFIG_TASK_NAME_SIZE=24 +CONFIG_TESTING_OSTEST=y +CONFIG_TESTING_OSTEST_FPUTESTDISABLE=y +CONFIG_TESTING_OSTEST_STACKSIZE=10240 +CONFIG_TTY_SIGINT=y +CONFIG_TTY_SIGTSTP=y +CONFIG_UART4_BAUD=57600 +CONFIG_UART4_RXBUFSIZE=600 +CONFIG_UART4_TXBUFSIZE=1500 +CONFIG_UART7_BAUD=57600 +CONFIG_UART7_RXBUFSIZE=600 +CONFIG_UART7_SERIAL_CONSOLE=y +CONFIG_UART7_TXBUFSIZE=1500 +CONFIG_UART8_BAUD=57600 +CONFIG_UART8_RXBUFSIZE=600 +CONFIG_UART8_TXBUFSIZE=1500 +CONFIG_USART2_BAUD=57600 +CONFIG_USART2_IFLOWCONTROL=y +CONFIG_USART2_OFLOWCONTROL=y +CONFIG_USART2_RXBUFSIZE=600 +CONFIG_USART2_TXBUFSIZE=1500 +CONFIG_USART3_BAUD=57600 +CONFIG_USART3_IFLOWCONTROL=y +CONFIG_USART3_OFLOWCONTROL=y +CONFIG_USART3_RXBUFSIZE=600 +CONFIG_USART3_TXBUFSIZE=3000 +CONFIG_USART6_BAUD=57600 +CONFIG_USART6_RXBUFSIZE=600 +CONFIG_USART6_TXBUFSIZE=1500 +CONFIG_USBDEV=y +CONFIG_USBDEV_BUSPOWERED=y +CONFIG_USBDEV_MAXPOWER=500 +CONFIG_USEC_PER_TICK=1000 +CONFIG_USERMAIN_STACKSIZE=2944 +CONFIG_USER_ENTRYPOINT="nsh_main" +CONFIG_WATCHDOG=y diff --git a/boards/cubepilot/cubeorangeplus/src/CMakeLists.txt b/boards/cubepilot/cubeorangeplus/src/CMakeLists.txt new file mode 100644 index 00000000000..c8e76990465 --- /dev/null +++ b/boards/cubepilot/cubeorangeplus/src/CMakeLists.txt @@ -0,0 +1,65 @@ +############################################################################ +# +# Copyright (c) 2020 PX4 Development Team. 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. 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 PX4 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 OWNER 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. +# +############################################################################ +if("${PX4_BOARD_LABEL}" STREQUAL "bootloader") + add_library(drivers_board + bootloader_main.c + usb.c + ) + target_link_libraries(drivers_board + PRIVATE + nuttx_arch + nuttx_drivers + bootloader + ) + target_include_directories(drivers_board PRIVATE ${PX4_SOURCE_DIR}/platforms/nuttx/src/bootloader/common) + +else() + add_library(drivers_board + i2c.cpp + init.c + led.c + spi.cpp + timer_config.cpp + usb.c + ) + + target_link_libraries(drivers_board + PRIVATE + arch_io_pins + arch_spi + drivers__led + nuttx_arch + nuttx_drivers + px4_layer + ) +endif() diff --git a/boards/cubepilot/cubeorangeplus/src/board_config.h b/boards/cubepilot/cubeorangeplus/src/board_config.h new file mode 100644 index 00000000000..5cab2c5f82f --- /dev/null +++ b/boards/cubepilot/cubeorangeplus/src/board_config.h @@ -0,0 +1,190 @@ +/**************************************************************************** + * + * Copyright (c) 2020 PX4 Development Team. 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. 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 PX4 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 OWNER 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. + * + ****************************************************************************/ + +/** + * @file board_config.h + * + * Board internal definitions + */ + +#pragma once + +#include +#include +#include +#include + +/* PX4IO connection configuration */ +#define BOARD_USES_PX4IO_VERSION 2 +#define PX4IO_SERIAL_DEVICE "/dev/ttyS3" +#define PX4IO_SERIAL_TX_GPIO GPIO_USART6_TX +#define PX4IO_SERIAL_RX_GPIO GPIO_USART6_RX +#define PX4IO_SERIAL_BASE STM32_USART6_BASE +#define PX4IO_SERIAL_VECTOR STM32_IRQ_USART6 +#define PX4IO_SERIAL_TX_DMAMAP DMAMAP_USART6_TX +#define PX4IO_SERIAL_RX_DMAMAP DMAMAP_USART6_RX +#define PX4IO_SERIAL_RCC_REG STM32_RCC_APB2ENR +#define PX4IO_SERIAL_RCC_EN RCC_APB2ENR_USART6EN +#define PX4IO_SERIAL_CLOCK STM32_PCLK2_FREQUENCY +#define PX4IO_SERIAL_BITRATE 1500000 /* 1.5Mbps -> max rate for IO */ + +/* LEDs */ +#define GPIO_nLED_AMBER /* PE12 */ (GPIO_OUTPUT|GPIO_OPENDRAIN|GPIO_SPEED_50MHz|GPIO_OUTPUT_SET|GPIO_PORTE|GPIO_PIN12) + +#define BOARD_HAS_CONTROL_STATUS_LEDS 1 +#define BOARD_ARMED_LED LED_AMBER + +/* ADC channels */ +#define PX4_ADC_GPIO \ + /* PA2 */ GPIO_ADC12_INP14, \ + /* PA3 */ GPIO_ADC12_INP15, \ + /* PA4 */ GPIO_ADC12_INP18, \ + /* PC3 */ GPIO_ADC12_INP13, \ + /* PC4 */ GPIO_ADC12_INP4, \ + /* PC5 */ GPIO_ADC12_INP8 + +/* Define Channel numbers must match above GPIO pins */ +#define ADC_BATTERY1_VOLTAGE_CHANNEL 14 /* PA2: BATT_VOLTAGE_SENS */ +#define ADC_BATTERY1_CURRENT_CHANNEL 15 /* PA3: BATT_CURRENT_SENS */ +#define ADC_SCALED_V5_CHANNEL 18 /* PA4: VDD_5V_SENS */ +#define ADC_BATTERY2_VOLTAGE_CHANNEL 13 /* PC3: FMU_AUX_POWER_ADC1 */ +#define ADC_BATTERY2_CURRENT_CHANNEL 4 /* PC4: FMU_AUX_ADC2 */ +#define ADC_AIRSPEED_VOLTAGE_CHANNEL 8 /* PC5: PRESSURE_SENS */ + +#define ADC_CHANNELS \ + ((1 << ADC_BATTERY1_VOLTAGE_CHANNEL) | \ + (1 << ADC_BATTERY1_CURRENT_CHANNEL) | \ + (1 << ADC_SCALED_V5_CHANNEL) | \ + (1 << ADC_BATTERY2_VOLTAGE_CHANNEL) | \ + (1 << ADC_BATTERY2_CURRENT_CHANNEL) | \ + (1 << ADC_AIRSPEED_VOLTAGE_CHANNEL)) + +/* HW has to large of R termination on ADC todo:change when HW value is chosen */ +#define BOARD_ADC_OPEN_CIRCUIT_V (5.6f) + +/* PWM */ +#define DIRECT_PWM_OUTPUT_CHANNELS 6 +#define GPIO_PWM_VOLT_SEL /* PB4 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTB|GPIO_PIN4) + +/* Power supply control and monitoring GPIOs */ +#define BOARD_NUMBER_BRICKS 2 +#define GPIO_nVDD_BRICK1_VALID /* PB5 */ (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN5) // VDD_BRICK_VALID +#define GPIO_nVDD_BRICK2_VALID /* PB7 */ (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN7) // VDD_BACKUP_VALID +#define GPIO_nVDD_USB_VALID /* PC0 */ (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTC|GPIO_PIN0) // VBUS_VALID +#define GPIO_VDD_3V3_SENSORS_EN /* PE3 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTE|GPIO_PIN3) // VDD_3V3_SENSORS_EN +#define GPIO_nVDD_5V_PERIPH_EN /* PA8 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTA|GPIO_PIN8) // VDD_5V_PERIPH_EN +#define GPIO_nVDD_5V_PERIPH_OC /* PE15 */ (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTE|GPIO_PIN15) // VDD_5V_PERIPH_OC +#define GPIO_nVDD_5V_HIPOWER_OC /* PE10 */ (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTE|GPIO_PIN10) // VDD_5V_HIPOWER_OC + +/* Tone alarm output */ +#define TONE_ALARM_TIMER 2 /* timer 2 */ +#define TONE_ALARM_CHANNEL 1 /* PA15 TIM2_CH1 */ + +#define GPIO_BUZZER_1 /* PA15 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTA|GPIO_PIN15) // ALARM + +#define GPIO_TONE_ALARM_IDLE GPIO_BUZZER_1 +#define GPIO_TONE_ALARM GPIO_TIM2_CH1OUT_2 + +/* PWM input driver. Use FMU AUX5 pins attached to timer4 channel 2 */ +#define PWMIN_TIMER 4 +#define PWMIN_TIMER_CHANNEL /* T4C2 */ 2 +#define GPIO_PWM_IN /* PD13 */ GPIO_TIM4_CH2IN_2 + +/* USB + * OTG FS: PA9 OTG_FS_VBUS VBUS sensing + */ +#define GPIO_OTGFS_VBUS /* PA9 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_SPEED_100MHz|GPIO_PORTA|GPIO_PIN9) + +/* High-resolution timer */ +#define HRT_TIMER 8 /* use timer8 for the HRT */ +#define HRT_TIMER_CHANNEL 3 /* use capture/compare channel 3 */ + +/* By Providing BOARD_ADC_USB_CONNECTED (using the px4_arch abstraction) + * this board support the ADC system_power interface, and therefore + * provides the true logic GPIO BOARD_ADC_xxxx macros. + */ +#define BOARD_ADC_USB_CONNECTED (px4_arch_gpioread(GPIO_OTGFS_VBUS)) +#define BOARD_ADC_USB_VALID (!px4_arch_gpioread(GPIO_nVDD_USB_VALID)) +#define BOARD_ADC_BRICK1_VALID (!px4_arch_gpioread(GPIO_nVDD_BRICK1_VALID)) +#define BOARD_ADC_BRICK2_VALID (!px4_arch_gpioread(GPIO_nVDD_BRICK2_VALID)) +#define BOARD_ADC_PERIPH_5V_OC (!px4_arch_gpioread(GPIO_nVDD_5V_PERIPH_OC)) +#define BOARD_ADC_HIPOWER_5V_OC (!px4_arch_gpioread(GPIO_nVDD_5V_HIPOWER_OC)) + +/* This board provides a DMA pool and APIs */ +#define BOARD_DMA_ALLOC_POOL_SIZE 5120 + +/* This board provides the board_on_reset interface */ +#define BOARD_HAS_ON_RESET 1 + +#define BOARD_HAS_STATIC_MANIFEST 1 + + + +#define BOARD_ENABLE_CONSOLE_BUFFER + +#define PX4_GPIO_INIT_LIST { \ + PX4_ADC_GPIO, \ + GPIO_CAN1_TX, \ + GPIO_CAN1_RX, \ + GPIO_CAN2_TX, \ + GPIO_CAN2_RX, \ + GPIO_PWM_VOLT_SEL, \ + GPIO_nVDD_BRICK1_VALID, \ + GPIO_nVDD_BRICK1_VALID, \ + GPIO_nVDD_USB_VALID, \ + GPIO_VDD_3V3_SENSORS_EN, \ + GPIO_nVDD_5V_PERIPH_EN, \ + GPIO_nVDD_5V_PERIPH_OC, \ + GPIO_nVDD_5V_HIPOWER_OC, \ + PX4_MAKE_GPIO_OUTPUT_CLEAR(GPIO_I2C1_SCL), \ + PX4_MAKE_GPIO_OUTPUT_CLEAR(GPIO_I2C1_SDA), \ + PX4_MAKE_GPIO_OUTPUT_CLEAR(GPIO_I2C2_SCL), \ + PX4_MAKE_GPIO_OUTPUT_CLEAR(GPIO_I2C2_SDA), \ + PX4_GPIO_PIN_OFF(GPIO_SDMMC1_D0), \ + PX4_GPIO_PIN_OFF(GPIO_SDMMC1_D1), \ + PX4_GPIO_PIN_OFF(GPIO_SDMMC1_D2), \ + PX4_GPIO_PIN_OFF(GPIO_SDMMC1_D3), \ + PX4_GPIO_PIN_OFF(GPIO_SDMMC1_CMD),\ + GPIO_TONE_ALARM_IDLE, \ + GPIO_OTGFS_VBUS, \ + } + +__BEGIN_DECLS +#ifndef __ASSEMBLY__ + +extern void stm32_spiinitialize(void); +extern void board_peripheral_reset(int ms); + +#include +#endif /* __ASSEMBLY__ */ +__END_DECLS diff --git a/boards/cubepilot/cubeorangeplus/src/bootloader_main.c b/boards/cubepilot/cubeorangeplus/src/bootloader_main.c new file mode 100644 index 00000000000..bb6b4dc23aa --- /dev/null +++ b/boards/cubepilot/cubeorangeplus/src/bootloader_main.c @@ -0,0 +1,75 @@ +/**************************************************************************** + * + * Copyright (c) 2020, 2021 PX4 Development Team. 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. 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 PX4 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 OWNER 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. + * + ****************************************************************************/ + +/** + * @file bootloader_main.c + * + * FMU-specific early startup code for bootloader +*/ + +#include "board_config.h" +#include "bl.h" + +#include +#include +#include +#include +#include +#include "arm_internal.h" +#include + +extern int sercon_main(int c, char **argv); + +__EXPORT void board_on_reset(int status) {} + +__EXPORT void stm32_boardinitialize(void) +{ + /* configure USB interfaces */ + stm32_configgpio(GPIO_OTGFS_VBUS); +} + +__EXPORT int board_app_initialize(uintptr_t arg) +{ + return 0; +} + +void board_late_initialize(void) +{ + sercon_main(0, NULL); +} + +extern void sys_tick_handler(void); +void board_timerhook(void) +{ + sys_tick_handler(); +} diff --git a/boards/cubepilot/cubeorangeplus/src/hw_config.h b/boards/cubepilot/cubeorangeplus/src/hw_config.h new file mode 100644 index 00000000000..dbe6581acb8 --- /dev/null +++ b/boards/cubepilot/cubeorangeplus/src/hw_config.h @@ -0,0 +1,135 @@ +/**************************************************************************** + * + * Copyright (C) 2020 PX4 Development Team. 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. 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 PX4 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 OWNER 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. + * + ****************************************************************************/ + +#pragma once + +/**************************************************************************** + * 10-8--2016: + * To simplify the ripple effect on the tools, we will be using + * /dev/serial/by-id/PX4 to locate PX4 devices. Therefore + * moving forward all Bootloaders must contain the prefix "PX4 BL " + * in the USBDEVICESTRING + * This Change will be made in an upcoming BL release + ****************************************************************************/ +/* + * Define usage to configure a bootloader + * + * + * Constant example Usage + * APP_LOAD_ADDRESS 0x08004000 - The address in Linker Script, where the app fw is org-ed + * BOOTLOADER_DELAY 5000 - Ms to wait while under USB pwr or bootloader request + * BOARD_FMUV2 + * INTERFACE_USB 1 - (Optional) Scan and use the USB interface for bootloading + * INTERFACE_USART 1 - (Optional) Scan and use the Serial interface for bootloading + * USBDEVICESTRING "PX4 BL FMU v2.x" - USB id string + * USBPRODUCTID 0x0011 - PID Should match defconfig + * BOOT_DELAY_ADDRESS 0x000001a0 - (Optional) From the linker script from Linker Script to get a custom + * delay provided by an APP FW + * BOARD_TYPE 9 - Must match .prototype boad_id + * _FLASH_KBYTES (*(uint16_t *)0x1fff7a22) - Run time flash size detection + * BOARD_FLASH_SECTORS ((_FLASH_KBYTES == 0x400) ? 11 : 23) - Run time determine the physical last sector + * BOARD_FLASH_SECTORS 11 - Hard coded zero based last sector + * BOARD_FLASH_SIZE (_FLASH_KBYTES*1024)- Total Flash size of device, determined at run time. + * (1024 * 1024) - Hard coded Total Flash of device - The bootloader and app reserved will be deducted + * programmatically + * + * BOARD_FIRST_FLASH_SECTOR_TO_ERASE 2 - Optional sectors index in the flash_sectors table (F4 only), to begin erasing. + * This is to allow sectors to be reserved for app fw usage. That will NOT be erased + * during a FW upgrade. + * The default is 0, and selects the first sector to be erased, as the 0th entry in the + * flash_sectors table. Which is the second physical sector of FLASH in the device. + * The first physical sector of FLASH is used by the bootloader, and is not defined + * in the table. + * + * APP_RESERVATION_SIZE (BOARD_FIRST_FLASH_SECTOR_TO_ERASE * 16 * 1024) - Number of bytes reserved by the APP FW. This number plus + * BOOTLOADER_RESERVATION_SIZE will be deducted from + * BOARD_FLASH_SIZE to determine the size of the App FW + * and hence the address space of FLASH to erase and program. + * USBMFGSTRING "PX4 AP" - Optional USB MFG string (default is '3D Robotics' if not defined.) + * SERIAL_BREAK_DETECT_DISABLED - Optional prevent break selection on Serial port from entering or staying in BL + * + * * Other defines are somewhat self explanatory. + */ + +/* Boot device selection list*/ +#define USB0_DEV 0x01 +#define SERIAL0_DEV 0x02 +#define SERIAL1_DEV 0x04 + +#define APP_LOAD_ADDRESS 0x08020000 +#define BOOTLOADER_DELAY 5000 +#define INTERFACE_USB 1 +#define INTERFACE_USB_CONFIG "/dev/ttyACM0" +#define BOARD_VBUS MK_GPIO_INPUT(GPIO_OTGFS_VBUS) + +//#define USE_VBUS_PULL_DOWN +#define INTERFACE_USART 1 +#define INTERFACE_USART_CONFIG "/dev/ttyS0,115200" +#define BOOT_DELAY_ADDRESS 0x000001a0 +#define BOARD_TYPE 1063 +#define _FLASH_KBYTES (*(uint32_t *)0x1FF1E880) +#define BOARD_FLASH_SECTORS (15) +#define BOARD_FLASH_SIZE (_FLASH_KBYTES * 1024) + +#define OSC_FREQ 24 + +#define BOARD_PIN_LED_ACTIVITY GPIO_nLED_AMBER +#define BOARD_PIN_LED_BOOTLOADER GPIO_nLED_AMBER +#define BOARD_LED_ON 0 +#define BOARD_LED_OFF 1 + +#define SERIAL_BREAK_DETECT_DISABLED 1 + +#if !defined(ARCH_SN_MAX_LENGTH) +# define ARCH_SN_MAX_LENGTH 12 +#endif + +#if !defined(APP_RESERVATION_SIZE) +# define APP_RESERVATION_SIZE 0 +#endif + +#if !defined(BOARD_FIRST_FLASH_SECTOR_TO_ERASE) +# define BOARD_FIRST_FLASH_SECTOR_TO_ERASE 1 +#endif + +#if !defined(USB_DATA_ALIGN) +# define USB_DATA_ALIGN +#endif + +#ifndef BOOT_DEVICES_SELECTION +# define BOOT_DEVICES_SELECTION USB0_DEV|SERIAL0_DEV|SERIAL1_DEV +#endif + +#ifndef BOOT_DEVICES_FILTER_ONUSB +# define BOOT_DEVICES_FILTER_ONUSB USB0_DEV|SERIAL0_DEV|SERIAL1_DEV +#endif diff --git a/boards/cubepilot/cubeorangeplus/src/i2c.cpp b/boards/cubepilot/cubeorangeplus/src/i2c.cpp new file mode 100644 index 00000000000..5625423e377 --- /dev/null +++ b/boards/cubepilot/cubeorangeplus/src/i2c.cpp @@ -0,0 +1,39 @@ +/**************************************************************************** + * + * Copyright (C) 2020 PX4 Development Team. 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. 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 PX4 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 OWNER 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. + * + ****************************************************************************/ + +#include + +constexpr px4_i2c_bus_t px4_i2c_buses[I2C_BUS_MAX_BUS_ITEMS] = { + initI2CBusExternal(2), + initI2CBusExternal(1), +}; diff --git a/boards/cubepilot/cubeorangeplus/src/init.c b/boards/cubepilot/cubeorangeplus/src/init.c new file mode 100644 index 00000000000..f7e1b3ca779 --- /dev/null +++ b/boards/cubepilot/cubeorangeplus/src/init.c @@ -0,0 +1,199 @@ +/**************************************************************************** + * + * Copyright (c) 2020 PX4 Development Team. 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. 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 PX4 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 OWNER 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. + * + ****************************************************************************/ + +/** + * @file init.c + * + * board-specific early startup code. This file implements the + * board_app_initialize() function that is called early by nsh during startup. + * + * Code here is run before the rcS script is invoked; it should start required + * subsystems and perform board-specific initialisation. + */ + +#include "board_config.h" + +#include + +#include +#include +#include +#include +#include +#include "arm_internal.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +__BEGIN_DECLS +extern void led_init(void); +extern void led_on(int led); +extern void led_off(int led); +__END_DECLS + +/************************************************************************************ + * Name: board_peripheral_reset + * + * Description: + * + ************************************************************************************/ +__EXPORT void board_peripheral_reset(int ms) +{ + /* Power off Interfaces */ + stm32_gpiowrite(GPIO_nVDD_5V_PERIPH_EN, true); + + /* wait for the peripheral rail to reach GND */ + usleep(ms * 1000); + syslog(LOG_DEBUG, "reset done, %d ms\n", ms); + + /* re-enable power */ + stm32_gpiowrite(GPIO_nVDD_5V_PERIPH_EN, false); +} + +/************************************************************************************ + * Name: board_on_reset + * + * Description: + * Optionally provided function called on entry to board_system_reset + * It should perform any house keeping prior to the rest. + * + * status - 1 if resetting to boot loader + * 0 if just resetting + * + ************************************************************************************/ +__EXPORT void board_on_reset(int status) +{ + for (int i = 0; i < DIRECT_PWM_OUTPUT_CHANNELS; ++i) { + px4_arch_configgpio(PX4_MAKE_GPIO_INPUT(io_timer_channel_get_as_pwm_input(i))); + } + + if (status >= 0) { + up_mdelay(6); + } +} + +/************************************************************************************ + * 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. + * + ************************************************************************************/ +__EXPORT void stm32_boardinitialize(void) +{ + /* Reset PWM first thing */ + board_on_reset(-1); + + /* configure pins */ + const uint32_t gpio[] = PX4_GPIO_INIT_LIST; + px4_gpio_init(gpio, arraySize(gpio)); + board_control_spi_sensors_power_configgpio(); + + /* configure LEDs */ + board_autoled_initialize(); +} + +/**************************************************************************** + * 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; + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure to indicate the nature of the failure. + * + ****************************************************************************/ +__EXPORT int board_app_initialize(uintptr_t arg) +{ + /* Power on Interfaces */ + stm32_gpiowrite(GPIO_VDD_3V3_SENSORS_EN, true); + stm32_gpiowrite(GPIO_nVDD_5V_PERIPH_EN, false); + board_control_spi_sensors_power(true, 0xffff); + + px4_platform_init(); + + stm32_spiinitialize(); + + /* configure the DMA allocator */ + if (board_dma_alloc_init() < 0) { + syslog(LOG_ERR, "[boot] DMA alloc FAILED\n"); + } + + /* initial LED state */ + drv_led_start(); + led_off(LED_AMBER); + + if (board_hardfault_init(2, true) != 0) { + led_on(LED_AMBER); + } + +#ifdef CONFIG_MMCSD + /* Mount the SDIO-based MMC/SD block driver */ + /* First, get an instance of the SDIO interface */ + struct sdio_dev_s *sdio_dev = sdio_initialize(0); // SDIO_SLOTNO 0 Only one slot + + if (!sdio_dev) { + syslog(LOG_ERR, "[boot] Failed to initialize SDIO slot %d\n", 0); + } + + if (mmcsd_slotinitialize(0, sdio_dev) != OK) { + syslog(LOG_ERR, "[boot] Failed to bind SDIO to the MMC/SD driver\n"); + } + + /* Assume that the SD card is inserted. What choice do we have? */ + sdio_mediachange(sdio_dev, true); +#endif /* CONFIG_MMCSD */ + + /* Configure the HW based on the manifest */ + + px4_platform_configure(); + + return OK; +} diff --git a/boards/cubepilot/cubeorangeplus/src/led.c b/boards/cubepilot/cubeorangeplus/src/led.c new file mode 100644 index 00000000000..f3c25469c40 --- /dev/null +++ b/boards/cubepilot/cubeorangeplus/src/led.c @@ -0,0 +1,110 @@ +/**************************************************************************** + * + * Copyright (c) 2020 PX4 Development Team. 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. 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 PX4 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 OWNER 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. + * + ****************************************************************************/ + +/** + * @file led.c + * + * LED backend. + */ + +#include + +#include + +#include "chip.h" +#include "stm32_gpio.h" +#include "board_config.h" + +#include +#include + +/* + * Ideally we'd be able to get these from arm_internal.h, + * but since we want to be able to disable the NuttX use + * of leds for system indication at will and there is no + * separate switch, we need to build independent of the + * CONFIG_ARCH_LEDS configuration switch. + */ +__BEGIN_DECLS +extern void led_init(void); +extern void led_on(int led); +extern void led_off(int led); +extern void led_toggle(int led); +__END_DECLS + +# define xlat(p) (p) +static uint32_t g_ledmap[] = { + GPIO_nLED_AMBER, +}; + +__EXPORT void led_init(void) +{ + for (size_t l = 0; l < (sizeof(g_ledmap) / sizeof(g_ledmap[0])); l++) { + if (g_ledmap[l] != 0) { + stm32_configgpio(g_ledmap[l]); + } + } +} + +static void phy_set_led(int led, bool state) +{ + /* Drive Low to switch on */ + if (g_ledmap[led] != 0) { + stm32_gpiowrite(g_ledmap[led], !state); + } +} + +static bool phy_get_led(int led) +{ + /* If Low it is on */ + if (g_ledmap[led] != 0) { + return !stm32_gpioread(g_ledmap[led]); + } + + return false; +} + +__EXPORT void led_on(int led) +{ + phy_set_led(xlat(led), true); +} + +__EXPORT void led_off(int led) +{ + phy_set_led(xlat(led), false); +} + +__EXPORT void led_toggle(int led) +{ + phy_set_led(xlat(led), !phy_get_led(xlat(led))); +} diff --git a/boards/cubepilot/cubeorangeplus/src/spi.cpp b/boards/cubepilot/cubeorangeplus/src/spi.cpp new file mode 100644 index 00000000000..adcf762c004 --- /dev/null +++ b/boards/cubepilot/cubeorangeplus/src/spi.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** + * + * Copyright (C) 2020 PX4 Development Team. 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. 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 PX4 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 OWNER 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. + * + ****************************************************************************/ + +#include +#include +#include + +constexpr px4_spi_bus_t px4_spi_buses[SPI_BUS_MAX_BUS_ITEMS] = { + initSPIBus(SPI::Bus::SPI1, { + initSPIDevice(DRV_IMU_DEVTYPE_ICM20649, SPI::CS{GPIO::PortC, GPIO::Pin2}, SPI::DRDY{GPIO::PortD, GPIO::Pin15}), // MPU_CS, MPU_DRDY + initSPIDevice(DRV_BARO_DEVTYPE_MS5611, SPI::CS{GPIO::PortD, GPIO::Pin7}), // BARO_CS + }), + + initSPIBus(SPI::Bus::SPI2, { + initSPIDevice(SPIDEV_FLASH(0), SPI::CS{GPIO::PortD, GPIO::Pin10}) // FRAM_CS + }), + + initSPIBus(SPI::Bus::SPI4, { + initSPIDevice(DRV_IMU_DEVTYPE_ICM20948, SPI::CS{GPIO::PortE, GPIO::Pin4}), // MPU_EXT_CS + initSPIDevice(DRV_IMU_DEVTYPE_ICM42688P, SPI::CS{GPIO::PortC, GPIO::Pin15}), // ACCEL_EXT_CS + initSPIDevice(DRV_BARO_DEVTYPE_MS5611, SPI::CS{GPIO::PortC, GPIO::Pin14}), // BARO_EXT_CS + }), +}; + +static constexpr bool unused = validateSPIConfig(px4_spi_buses); diff --git a/boards/cubepilot/cubeorangeplus/src/timer_config.cpp b/boards/cubepilot/cubeorangeplus/src/timer_config.cpp new file mode 100644 index 00000000000..293a74de86f --- /dev/null +++ b/boards/cubepilot/cubeorangeplus/src/timer_config.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** + * + * Copyright (C) 2020 PX4 Development Team. 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. 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 PX4 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 OWNER 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. + * + ****************************************************************************/ + +#include + +constexpr io_timers_t io_timers[MAX_IO_TIMERS] = { + initIOTimer(Timer::Timer1, DMA{DMA::Index1}), + initIOTimer(Timer::Timer4, DMA{DMA::Index1}), +}; + +constexpr timer_io_channels_t timer_io_channels[MAX_TIMER_IO_CHANNELS] = { + initIOTimerChannel(io_timers, {Timer::Timer1, Timer::Channel4}, {GPIO::PortE, GPIO::Pin14}), + initIOTimerChannel(io_timers, {Timer::Timer1, Timer::Channel3}, {GPIO::PortE, GPIO::Pin13}), + initIOTimerChannel(io_timers, {Timer::Timer1, Timer::Channel2}, {GPIO::PortE, GPIO::Pin11}), + initIOTimerChannel(io_timers, {Timer::Timer1, Timer::Channel1}, {GPIO::PortE, GPIO::Pin9}), + initIOTimerChannel(io_timers, {Timer::Timer4, Timer::Channel2}, {GPIO::PortD, GPIO::Pin13}), + initIOTimerChannel(io_timers, {Timer::Timer4, Timer::Channel3}, {GPIO::PortD, GPIO::Pin14}), +}; + +constexpr io_timers_channel_mapping_t io_timers_channel_mapping = + initIOTimerChannelMapping(io_timers, timer_io_channels); diff --git a/boards/cubepilot/cubeorangeplus/src/usb.c b/boards/cubepilot/cubeorangeplus/src/usb.c new file mode 100644 index 00000000000..fae2e76255f --- /dev/null +++ b/boards/cubepilot/cubeorangeplus/src/usb.c @@ -0,0 +1,60 @@ +/**************************************************************************** + * + * Copyright (C) 2020 PX4 Development Team. 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. 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 PX4 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 OWNER 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. + * + ****************************************************************************/ + +/** + * @file usb.c + * + * Board-specific USB functions. + */ + +#include "board_config.h" +#include +#include +#include +#include +#include + +/************************************************************************************ + * 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. + * + ************************************************************************************/ +__EXPORT void stm32_usbsuspend(FAR struct usbdev_s *dev, bool resume) +{ + uinfo("resume: %d\n", resume); +} diff --git a/boards/cubepilot/cubeorangeplus/test.px4board b/boards/cubepilot/cubeorangeplus/test.px4board new file mode 100644 index 00000000000..e56c5bdd32a --- /dev/null +++ b/boards/cubepilot/cubeorangeplus/test.px4board @@ -0,0 +1,15 @@ +CONFIG_DRIVERS_ADC_ADS1115=n +CONFIG_DRIVERS_IMU_ANALOG_DEVICES_ADIS16448=n +CONFIG_DRIVERS_IRLOCK=n +CONFIG_DRIVERS_PCA9685=n +CONFIG_DRIVERS_PCA9685_PWM_OUT=n +CONFIG_DRIVERS_RPM=n +CONFIG_DRIVERS_UAVCAN=n +CONFIG_MODULES_ATTITUDE_ESTIMATOR_Q=n +CONFIG_MODULES_LOCAL_POSITION_ESTIMATOR=n +CONFIG_MODULES_ROVER_POS_CONTROL=n +CONFIG_MODULES_TEMPERATURE_COMPENSATION=n +CONFIG_BOARD_TESTING=y +CONFIG_DRIVERS_TEST_PPM=y +CONFIG_SYSTEMCMDS_MICROBENCH=y +CONFIG_SYSTEMCMDS_SD_STRESS=y diff --git a/platforms/nuttx/NuttX/nuttx b/platforms/nuttx/NuttX/nuttx index 211dd7dc110..d43edd7879f 160000 --- a/platforms/nuttx/NuttX/nuttx +++ b/platforms/nuttx/NuttX/nuttx @@ -1 +1 @@ -Subproject commit 211dd7dc110dcaaa2eb9d414d5d4e5a9a7ae5f43 +Subproject commit d43edd7879fb398de9abcc9d58e8a65c9ed254db diff --git a/src/drivers/uavcan/uavcan_drivers/stm32h7/driver/include/uavcan_stm32h7/fdcan.hpp b/src/drivers/uavcan/uavcan_drivers/stm32h7/driver/include/uavcan_stm32h7/fdcan.hpp index 077e47c06f1..2d0d831d482 100644 --- a/src/drivers/uavcan/uavcan_drivers/stm32h7/driver/include/uavcan_stm32h7/fdcan.hpp +++ b/src/drivers/uavcan/uavcan_drivers/stm32h7/driver/include/uavcan_stm32h7/fdcan.hpp @@ -23,7 +23,7 @@ namespace uavcan_stm32h7 { namespace fdcan { -#ifdef CONFIG_STM32H7_STM32H7X3XX +#if defined(CONFIG_STM32H7_STM32H7X3XX) || defined(CONFIG_STM32H7_STM32H7X7XX) #include "fdcan_h7x3xx.h" #else # error "Unsupported STM32H7 MCU"