From 8db4be5a450d7decb8bc538fc0578c56c02575b2 Mon Sep 17 00:00:00 2001 From: neo Date: Fri, 3 May 2024 16:02:05 +0200 Subject: [PATCH] dev --- .ci/Jenkinsfile-compile | 1 + boards/px4/fts-can/bootloader.px4board | 3 + boards/px4/fts-can/default.px4board | 44 ++ .../fts-can/extras/px4_fmu-v6c_bootloader.bin | Bin 0 -> 46288 bytes .../px4/fts-can/extras/px4_io-v2_default.bin | Bin 0 -> 40140 bytes boards/px4/fts-can/firmware.prototype | 13 + boards/px4/fts-can/init/rc.board_defaults | 14 + boards/px4/fts-can/init/rc.board_sensors | 21 + boards/px4/fts-can/nuttx-config/Kconfig | 17 + .../fts-can/nuttx-config/bootloader/defconfig | 93 ++++ .../px4/fts-can/nuttx-config/include/board.h | 507 ++++++++++++++++++ .../nuttx-config/include/board_dma_map.h | 79 +++ boards/px4/fts-can/nuttx-config/nsh/defconfig | 266 +++++++++ .../nuttx-config/scripts/bootloader_script.ld | 215 ++++++++ .../fts-can/nuttx-config/scripts/script.ld | 229 ++++++++ boards/px4/fts-can/src/CMakeLists.txt | 75 +++ boards/px4/fts-can/src/board_config.h | 324 +++++++++++ boards/px4/fts-can/src/bootloader_main.c | 62 +++ boards/px4/fts-can/src/can.c | 128 +++++ boards/px4/fts-can/src/hw_config.h | 128 +++++ boards/px4/fts-can/src/i2c.cpp | 79 +++ boards/px4/fts-can/src/init.c | 259 +++++++++ boards/px4/fts-can/src/led.c | 235 ++++++++ boards/px4/fts-can/src/manifest.c | 155 ++++++ boards/px4/fts-can/src/mtd.cpp | 111 ++++ boards/px4/fts-can/src/sdio.c | 177 ++++++ boards/px4/fts-can/src/spi.cpp | 71 +++ boards/px4/fts-can/src/timer_config.cpp | 73 +++ boards/px4/fts-can/src/usb.c | 105 ++++ build.sh | 5 +- stflash.sh | 3 + upload.sh | 2 +- 32 files changed, 3491 insertions(+), 3 deletions(-) create mode 100644 boards/px4/fts-can/bootloader.px4board create mode 100644 boards/px4/fts-can/default.px4board create mode 100755 boards/px4/fts-can/extras/px4_fmu-v6c_bootloader.bin create mode 100755 boards/px4/fts-can/extras/px4_io-v2_default.bin create mode 100644 boards/px4/fts-can/firmware.prototype create mode 100644 boards/px4/fts-can/init/rc.board_defaults create mode 100644 boards/px4/fts-can/init/rc.board_sensors create mode 100644 boards/px4/fts-can/nuttx-config/Kconfig create mode 100644 boards/px4/fts-can/nuttx-config/bootloader/defconfig create mode 100644 boards/px4/fts-can/nuttx-config/include/board.h create mode 100644 boards/px4/fts-can/nuttx-config/include/board_dma_map.h create mode 100644 boards/px4/fts-can/nuttx-config/nsh/defconfig create mode 100644 boards/px4/fts-can/nuttx-config/scripts/bootloader_script.ld create mode 100644 boards/px4/fts-can/nuttx-config/scripts/script.ld create mode 100644 boards/px4/fts-can/src/CMakeLists.txt create mode 100644 boards/px4/fts-can/src/board_config.h create mode 100644 boards/px4/fts-can/src/bootloader_main.c create mode 100644 boards/px4/fts-can/src/can.c create mode 100644 boards/px4/fts-can/src/hw_config.h create mode 100644 boards/px4/fts-can/src/i2c.cpp create mode 100644 boards/px4/fts-can/src/init.c create mode 100644 boards/px4/fts-can/src/led.c create mode 100644 boards/px4/fts-can/src/manifest.c create mode 100644 boards/px4/fts-can/src/mtd.cpp create mode 100644 boards/px4/fts-can/src/sdio.c create mode 100644 boards/px4/fts-can/src/spi.cpp create mode 100644 boards/px4/fts-can/src/timer_config.cpp create mode 100644 boards/px4/fts-can/src/usb.c create mode 100755 stflash.sh diff --git a/.ci/Jenkinsfile-compile b/.ci/Jenkinsfile-compile index 2936194..718cd6e 100644 --- a/.ci/Jenkinsfile-compile +++ b/.ci/Jenkinsfile-compile @@ -35,6 +35,7 @@ pipeline { def nuttx_builds_archive = [ target: [ + "fts-can", "airmind_mindpx-v2_default", "ark_can-flow_canbootloader", "ark_can-flow_default", diff --git a/boards/px4/fts-can/bootloader.px4board b/boards/px4/fts-can/bootloader.px4board new file mode 100644 index 0000000..19b6e66 --- /dev/null +++ b/boards/px4/fts-can/bootloader.px4board @@ -0,0 +1,3 @@ +CONFIG_BOARD_TOOLCHAIN="arm-none-eabi" +CONFIG_BOARD_ARCHITECTURE="cortex-m7" +CONFIG_BOARD_ROMFSROOT="" diff --git a/boards/px4/fts-can/default.px4board b/boards/px4/fts-can/default.px4board new file mode 100644 index 0000000..cbae8d0 --- /dev/null +++ b/boards/px4/fts-can/default.px4board @@ -0,0 +1,44 @@ +CONFIG_BOARD_TOOLCHAIN="arm-none-eabi" +CONFIG_BOARD_ARCHITECTURE="cortex-m7" +CONFIG_BOARD_SERIAL_GPS1="/dev/ttyS0" +CONFIG_BOARD_SERIAL_GPS2="/dev/ttyS6" +CONFIG_BOARD_SERIAL_TEL1="/dev/ttyS5" +CONFIG_BOARD_SERIAL_TEL2="/dev/ttyS3" +CONFIG_BOARD_SERIAL_TEL3="/dev/ttyS1" +CONFIG_DRIVERS_ADC_BOARD_ADC=y +CONFIG_DRIVERS_DSHOT=y +CONFIG_COMMON_INS=y +CONFIG_COMMON_LIGHT=y +CONFIG_DRIVERS_PWM_OUT=y +CONFIG_COMMON_TELEMETRY=y +CONFIG_DRIVERS_TONE_ALARM=y +CONFIG_DRIVERS_UAVCAN=y +CONFIG_BOARD_UAVCAN_TIMER_OVERRIDE=2 +CONFIG_MODULES_BATTERY_STATUS=y +CONFIG_MODULES_CONTROL_ALLOCATOR=y +CONFIG_MODULES_DATAMAN=y +CONFIG_MODULES_ESC_BATTERY=y +CONFIG_MODULES_EVENTS=y +CONFIG_MODULES_LOAD_MON=y +CONFIG_MODULES_LOGGER=y +CONFIG_MODULES_MAVLINK=y +CONFIG_MODULES_UXRCE_DDS_CLIENT=y +CONFIG_SYSTEMCMDS_BSONDUMP=y +CONFIG_SYSTEMCMDS_DMESG=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_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_VER=y +CONFIG_SYSTEMCMDS_WORK_QUEUE=y diff --git a/boards/px4/fts-can/extras/px4_fmu-v6c_bootloader.bin b/boards/px4/fts-can/extras/px4_fmu-v6c_bootloader.bin new file mode 100755 index 0000000000000000000000000000000000000000..536dcc40aadf6d66a059507a3a23e55153c4fe6b GIT binary patch literal 46288 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 literal 0 HcmV?d00001 diff --git a/boards/px4/fts-can/extras/px4_io-v2_default.bin b/boards/px4/fts-can/extras/px4_io-v2_default.bin new file mode 100755 index 0000000000000000000000000000000000000000..957f0f13a12e8eb8a7979955f29ad98d82433933 GIT binary patch literal 40140 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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. + * + ************************************************************************************/ +#ifndef __NUTTX_CONFIG_PX4_FTS_CAN_INCLUDE_BOARD_H +#define __NUTTX_CONFIG_PX4_FTS_CAN_INCLUDE_BOARD_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include "board_dma_map.h" + +#include + +#ifndef __ASSEMBLY__ +# include +#endif + +#include "stm32_rcc.h" +#include "stm32_sdmmc.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Clocking *************************************************************************/ +/* The FTS_CAN board provides the following clock sources: + * + * X1: 16 MHz crystal for HSE + * + * So we have these clock source available within the STM32 + * + * HSI: 16 MHz RC factory-trimmed + * HSE: 16 MHz crystal for HSE + */ + +#define STM32_BOARD_XTAL 16000000ul + +#define STM32_HSI_FREQUENCY 16000000ul +#define STM32_LSI_FREQUENCY 32000 +#define STM32_HSE_FREQUENCY STM32_BOARD_XTAL +#define STM32_LSE_FREQUENCY 32768 + +/* Main PLL Configuration. + * + * PLL source is HSE = 16,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 + */ + +#define STM32_BOARD_USEHSI 1 +#define STM32_BOARD_HSIDIV 1 + +#define STM32_PLLCFG_PLLSRC RCC_PLLCKSELR_PLLSRC_HSI + +/* PLL1, wide 4 - 8 MHz input, enable DIVP, DIVQ, DIVR + * + * PLL1_VCO = (16,000,000 / 1) * 60 = 960 MHz + * + * PLL1P = PLL1_VCO/2 = 960 MHz / 2 = 480 MHz + * PLL1Q = PLL1_VCO/4 = 960 MHz / 4 = 240 MHz + * PLL1R = PLL1_VCO/8 = 960 MHz / 8 = 120 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(1) +#define STM32_PLLCFG_PLL1N RCC_PLL1DIVR_N1(60) +#define STM32_PLLCFG_PLL1P RCC_PLL1DIVR_P1(2) +#define STM32_PLLCFG_PLL1Q RCC_PLL1DIVR_Q1(4) +#define STM32_PLLCFG_PLL1R RCC_PLL1DIVR_R1(8) + +#define STM32_VCO1_FREQUENCY ((STM32_HSE_FREQUENCY / 1) * 60) +#define STM32_PLL1P_FREQUENCY (STM32_VCO1_FREQUENCY / 2) +#define STM32_PLL1Q_FREQUENCY (STM32_VCO1_FREQUENCY / 4) +#define STM32_PLL1R_FREQUENCY (STM32_VCO1_FREQUENCY / 8) + +/* 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(4) +#define STM32_PLLCFG_PLL2N RCC_PLL2DIVR_N2(48) +#define STM32_PLLCFG_PLL2P RCC_PLL2DIVR_P2(2) +#define STM32_PLLCFG_PLL2Q RCC_PLL2DIVR_Q2(2) +#define STM32_PLLCFG_PLL2R RCC_PLL2DIVR_R2(2) + +#define STM32_VCO2_FREQUENCY ((STM32_HSE_FREQUENCY / 4) * 48) +#define STM32_PLL2P_FREQUENCY (STM32_VCO2_FREQUENCY / 2) +#define STM32_PLL2Q_FREQUENCY (STM32_VCO2_FREQUENCY / 2) +#define STM32_PLL2R_FREQUENCY (STM32_VCO2_FREQUENCY / 2) + +/* 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(4) +#define STM32_PLLCFG_PLL3N RCC_PLL3DIVR_N3(48) +#define STM32_PLLCFG_PLL3P RCC_PLL3DIVR_P3(2) +#define STM32_PLLCFG_PLL3Q RCC_PLL3DIVR_Q3(4) +#define STM32_PLLCFG_PLL3R RCC_PLL3DIVR_R3(2) + +#define STM32_VCO3_FREQUENCY ((STM32_HSE_FREQUENCY / 4) * 48) +#define STM32_PLL3P_FREQUENCY (STM32_VCO3_FREQUENCY / 2) +#define STM32_PLL3Q_FREQUENCY (STM32_VCO3_FREQUENCY / 4) +#define STM32_PLL3R_FREQUENCY (STM32_VCO3_FREQUENCY / 2) + +/* SYSCLK = PLL1P = 480MHz + * CPUCLK = SYSCLK / 1 = 480 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 = 240 + */ + +#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/2 (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 + */ + +/* I2C123 clock source */ + +#define STM32_RCC_D2CCIP2R_I2C123SRC RCC_D2CCIP2R_I2C123SEL_HSI + +/* I2C4 clock source */ + +#define STM32_RCC_D3CCIPR_I2C4SRC RCC_D3CCIPR_I2C4SEL_HSI + +/* SPI123 clock source */ + +#define STM32_RCC_D2CCIP1R_SPI123SRC RCC_D2CCIP1R_SPI123SEL_PLL2 + +/* SPI45 clock source */ + +#define STM32_RCC_D2CCIP1R_SPI45SRC RCC_D2CCIP1R_SPI45SEL_PLL2 + +/* SPI6 clock source */ + +#define STM32_RCC_D3CCIPR_SPI6SRC RCC_D3CCIPR_SPI6SEL_PLL2 + +/* USB 1 and 2 clock source */ + +#define STM32_RCC_D2CCIP2R_USBSRC RCC_D2CCIP2R_USBSEL_PLL3 + +/* ADC 1 2 3 clock source */ + +#define STM32_RCC_D3CCIPR_ADCSEL RCC_D3CCIPR_ADCSEL_PLL2 + +/* FDCAN 1 2 clock source */ + +#define STM32_RCC_D2CCIP1R_FDCANSEL RCC_D2CCIP1R_FDCANSEL_HSE /* FDCAN 1 2 clock source */ + +#define STM32_FDCANCLK STM32_HSE_FREQUENCY + +/* FLASH wait states + * + * ------------ ---------- ----------- + * Vcore MAX ACLK WAIT STATES + * ------------ ---------- ----------- + * 1.15-1.26 V 70 MHz 0 + * (VOS1 level) 140 MHz 1 + * 210 MHz 2 + * 1.05-1.15 V 55 MHz 0 + * (VOS2 level) 110 MHz 1 + * 165 MHz 2 + * 220 MHz 3 + * 0.95-1.05 V 45 MHz 0 + * (VOS3 level) 90 MHz 1 + * 135 MHz 2 + * 180 MHz 3 + * 225 MHz 4 + * ------------ ---------- ----------- + */ + +#define BOARD_FLASH_WAITSTATES 2 + +/* SDMMC definitions ********************************************************/ + +/* Init 400kHz, freq = PLL1Q/(2*div) div = PLL1Q/(2*freq) */ + +#define STM32_SDMMC_INIT_CLKDIV (300 << STM32_SDMMC_CLKCR_CLKDIV_SHIFT) + +/* 25 MHz Max for now, 25 mHZ = PLL1Q/(2*div), div = PLL1Q/(2*freq) + * div = 4.8 = 240 / 50, So round up to 5 for default speed 24 MB/s + */ + +#if defined(CONFIG_STM32H7_SDMMC_XDMA) || defined(CONFIG_STM32H7_SDMMC_IDMA) +# define STM32_SDMMC_MMCXFR_CLKDIV (5 << STM32_SDMMC_CLKCR_CLKDIV_SHIFT) +#else +# define STM32_SDMMC_MMCXFR_CLKDIV (100 << STM32_SDMMC_CLKCR_CLKDIV_SHIFT) +#endif +#if defined(CONFIG_STM32H7_SDMMC_XDMA) || defined(CONFIG_STM32H7_SDMMC_IDMA) +# define STM32_SDMMC_SDXFR_CLKDIV (5 << STM32_SDMMC_CLKCR_CLKDIV_SHIFT) +#else +# define STM32_SDMMC_SDXFR_CLKDIV (100 << STM32_SDMMC_CLKCR_CLKDIV_SHIFT) +#endif + +#define STM32_SDMMC_CLKCR_EDGE STM32_SDMMC_CLKCR_NEGEDGE + +/* LED definitions ******************************************************************/ +/* The PX4 FMUV6C board has three, LED_GREEN a Green LED, LED_BLUE a Blue LED and + * LED_RED a Red LED, that can be controlled by software. + * + * If CONFIG_ARCH_LEDS is not defined, then the user can control the LEDs in any way. + * The following definitions are used to access individual LEDs. + */ + +/* LED index values for use with board_userled() */ + +/* LED definitions ******************************************************************/ +/* The px4_fmu-v6c board has three, LED_GREEN a Green LED, LED_BLUE a Blue LED and + * LED_RED a Red LED, that can be controlled by software. + * + * If CONFIG_ARCH_LEDS is not defined, then the user can control the LEDs in any way. + * The following definitions are used to access individual LEDs. + */ + +/* LED index values for use with board_userled() */ + +#define BOARD_LED1 0 +#define BOARD_LED2 1 +#define BOARD_LED3 2 +#define BOARD_NLEDS 3 + +#define BOARD_LED_RED BOARD_LED1 +#define BOARD_LED_GREEN BOARD_LED2 +#define BOARD_LED_BLUE BOARD_LED3 + +/* LED bits for use with board_userled_all() */ + +#define BOARD_LED1_BIT (1 << BOARD_LED1) +#define BOARD_LED2_BIT (1 << BOARD_LED2) +#define BOARD_LED3_BIT (1 << BOARD_LED3) + +/* If CONFIG_ARCH_LEDS is defined, the usage by the board port is defined in + * include/board.h and src/stm32_leds.c. The LEDs are used to encode OS-related + * events as follows: + * + * + * SYMBOL Meaning LED state + * Red Green Blue + * ---------------------- -------------------------- ------ ------ ----*/ + +#define LED_STARTED 0 /* NuttX has been started OFF OFF OFF */ +#define LED_HEAPALLOCATE 1 /* Heap has been allocated OFF OFF ON */ +#define LED_IRQSENABLED 2 /* Interrupts enabled OFF ON OFF */ +#define LED_STACKCREATED 3 /* Idle stack created OFF ON ON */ +#define LED_INIRQ 4 /* In an interrupt N/C N/C GLOW */ +#define LED_SIGNAL 5 /* In a signal handler N/C GLOW N/C */ +#define LED_ASSERTION 6 /* An assertion failed GLOW N/C GLOW */ +#define LED_PANIC 7 /* The system has crashed Blink OFF N/C */ +#define LED_IDLE 8 /* MCU is is sleep mode ON OFF OFF */ + +/* Thus if the Green LED is statically on, NuttX has successfully booted and + * is, apparently, running normally. If the Red LED is flashing at + * approximately 2Hz, then a fatal error has been detected and the system + * has halted. + */ + +/* Alternate function pin selections ************************************************/ + +#define GPIO_USART1_RX GPIO_USART1_RX_2 /* PA10 */ +#define GPIO_USART1_TX GPIO_USART1_TX_3 /* PB6 */ + +#define GPIO_USART2_RX GPIO_USART2_RX_1 /* PA3 */ +#define GPIO_USART2_TX GPIO_USART2_TX_2 /* PD5 */ + +#define GPIO_USART3_RX GPIO_USART3_RX_3 /* PD9 */ +#define GPIO_USART3_TX GPIO_USART3_TX_3 /* PD8 */ + +#define GPIO_UART5_RX GPIO_UART5_RX_3 /* PD2 */ +#define GPIO_UART5_TX GPIO_UART5_TX_3 /* PC12 */ +// GPIO_UART5_RTS no remap /* PC8 */ +#undef GPIO_UART5_CTS +#define GPIO_UART5_CTS ((GPIO_ALT|GPIO_AF8|GPIO_PORTC|GPIO_PIN9) | GPIO_PULLDOWN) /* PC9 */ + +#define GPIO_USART6_RX GPIO_USART6_RX_1 /* PC7 */ +#define GPIO_USART6_TX GPIO_USART6_TX_1 /* PC6 */ + +#define GPIO_UART7_RX GPIO_UART7_RX_3 /* PE7 */ +#define GPIO_UART7_TX GPIO_UART7_TX_3 /* PE8 */ +#define GPIO_UART7_RTS GPIO_UART7_RTS_1 /* PE9 */ +#define GPIO_UART7_CTS (GPIO_UART7_CTS_1 | GPIO_PULLDOWN) /* PE10 */ + +#define GPIO_UART8_RX GPIO_UART8_RX_1 /* PE0 */ +#define GPIO_UART8_TX GPIO_UART8_TX_1 /* PE1 */ + + +/* CAN + * + * CAN1 is routed to transceiver. + * CAN2 is routed to transceiver. + */ +#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_2 /* PB5 */ +#define GPIO_CAN2_TX GPIO_CAN2_TX_1 /* PB13 */ + +/* SPI + * SPI1 is sensors + * SPI2 is FRAM + * + */ + +#define ADJ_SLEW_RATE(p) (((p) & ~GPIO_SPEED_MASK) | (GPIO_SPEED_2MHz)) + +#define GPIO_SPI1_MISO GPIO_SPI1_MISO_1 /* PA6 */ +#define GPIO_SPI1_MOSI GPIO_SPI1_MOSI_1 /* PA7 */ +#define GPIO_SPI1_SCK ADJ_SLEW_RATE(GPIO_SPI1_SCK_1) /* PA5 */ + +#define GPIO_SPI2_MISO GPIO_SPI2_MISO_2 /* PC2 */ +#define GPIO_SPI2_MOSI GPIO_SPI2_MOSI_3 /* PC3 */ +#define GPIO_SPI2_SCK ADJ_SLEW_RATE(GPIO_SPI2_SCK_5) /* PD3 */ + +/* I2C + * + * The optional _GPIO configurations allow the I2C driver to manually + * reset the bus to clear stuck slaves. They match the pin configuration, + * but are normally-high GPIOs. + * + */ + +#define GPIO_I2C1_SCL GPIO_I2C1_SCL_2 /* PB8 */ +#define GPIO_I2C1_SDA GPIO_I2C1_SDA_1 /* PB7 */ + +#define GPIO_I2C1_SCL_GPIO (GPIO_OUTPUT | GPIO_OPENDRAIN |GPIO_SPEED_50MHz | GPIO_OUTPUT_SET | GPIO_PORTB | GPIO_PIN8) +#define GPIO_I2C1_SDA_GPIO (GPIO_OUTPUT | GPIO_OPENDRAIN |GPIO_SPEED_50MHz | GPIO_OUTPUT_SET | GPIO_PORTB | GPIO_PIN7) + +#define GPIO_I2C2_SCL GPIO_I2C2_SCL_1 /* PB10 */ +#define GPIO_I2C2_SDA GPIO_I2C2_SDA_1 /* PB11*/ + +#define GPIO_I2C2_SCL_GPIO (GPIO_OUTPUT | GPIO_OPENDRAIN |GPIO_SPEED_50MHz | GPIO_OUTPUT_SET | GPIO_PORTB | GPIO_PIN10) +#define GPIO_I2C2_SDA_GPIO (GPIO_OUTPUT | GPIO_OPENDRAIN |GPIO_SPEED_50MHz | GPIO_OUTPUT_SET | GPIO_PORTB | GPIO_PIN11) + +#define GPIO_I2C4_SCL GPIO_I2C4_SCL_1 /* PD12 */ +#define GPIO_I2C4_SDA GPIO_I2C4_SDA_1 /* PD13 */ + +#define GPIO_I2C4_SCL_GPIO (GPIO_OUTPUT | GPIO_OPENDRAIN | GPIO_SPEED_50MHz | GPIO_OUTPUT_SET | GPIO_PORTD | GPIO_PIN12) +#define GPIO_I2C4_SDA_GPIO (GPIO_OUTPUT | GPIO_OPENDRAIN | GPIO_SPEED_50MHz | GPIO_OUTPUT_SET | GPIO_PORTD | GPIO_PIN13) + +/* SDMMC2 + * + * VDD 3.3 + * GND + * SDMMC2_CK PD6 + * SDMMC2_CMD PD7 + * SDMMC2_D0 PB14 + * SDMMC2_D1 PB15 + * SDMMC2_D2 PB3 + * SDMMC2_D3 PB4 + */ + +#define GPIO_SDMMC2_CK GPIO_SDMMC2_CK_1 /* PD6 */ +#define GPIO_SDMMC2_CMD GPIO_SDMMC2_CMD_1 /* PD7 */ +// GPIO_SDMMC2_D0 No Remap /* PB14 */ +// GPIO_SDMMC2_D1 No Remap /* PB15 */ +#define GPIO_SDMMC2_D2 GPIO_SDMMC2_D2_2 /* PB3 */ +// GPIO_SDMMC2_D3 No Remap /* PB4 */ + +/* USB + * + * OTG_FS_DM PA11 + * OTG_FS_DP PA12 + * VBUS PA9 + */ + + +/* Board provides GPIO or other Hardware for signaling to timing analyzer */ + +#if defined(CONFIG_BOARD_USE_PROBES) +# include "stm32_gpio.h" +# define PROBE_N(n) (1<<((n)-1)) +# define PROBE_1 (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTA|GPIO_PIN8) /* PA8 AUX1 */ +# define PROBE_2 (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTE|GPIO_PIN11) /* PE11 AUX2 */ +# define PROBE_3 (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTE|GPIO_PIN13) /* PE13 AUX3 */ +# define PROBE_4 (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTE|GPIO_PIN14) /* PE14 AUX4 */ +# define PROBE_5 (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTD|GPIO_PIN14) /* PD14 AUX5 */ +# define PROBE_6 (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTD|GPIO_PIN15) /* PD15 AUX6 */ +# define PROBE_7 (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTA|GPIO_PIN0) /* PA0 AUX7 */ +# define PROBE_8 (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTA|GPIO_PIN2) /* PA1 AUX8 */ + +# define PROBE_INIT(mask) \ + do { \ + if ((mask)& PROBE_N(1)) { stm32_configgpio(PROBE_1); } \ + if ((mask)& PROBE_N(2)) { stm32_configgpio(PROBE_2); } \ + if ((mask)& PROBE_N(3)) { stm32_configgpio(PROBE_3); } \ + if ((mask)& PROBE_N(4)) { stm32_configgpio(PROBE_4); } \ + if ((mask)& PROBE_N(5)) { stm32_configgpio(PROBE_5); } \ + if ((mask)& PROBE_N(6)) { stm32_configgpio(PROBE_6); } \ + if ((mask)& PROBE_N(7)) { stm32_configgpio(PROBE_7); } \ + if ((mask)& PROBE_N(8)) { stm32_configgpio(PROBE_8); } \ + } while(0) + +# define PROBE(n,s) do {stm32_gpiowrite(PROBE_##n,(s));}while(0) +# define PROBE_MARK(n) PROBE(n,false);PROBE(n,true) +#else +# define PROBE_INIT(mask) +# define PROBE(n,s) +# define PROBE_MARK(n) +#endif + +#endif /*__NUTTX_CONFIG_PX4_FMU_V6C_INCLUDE_BOARD_H */ diff --git a/boards/px4/fts-can/nuttx-config/include/board_dma_map.h b/boards/px4/fts-can/nuttx-config/include/board_dma_map.h new file mode 100644 index 0000000..fb688dc --- /dev/null +++ b/boards/px4/fts-can/nuttx-config/include/board_dma_map.h @@ -0,0 +1,79 @@ +/**************************************************************************** + * + * 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 Using at most 8 Channels on DMA1 -------- Assigned +// V + +#define DMAMAP_SPI1_RX DMAMAP_DMA12_SPI1RX_0 /* 1 DMA1:37 BMI055, ICM-42688-P */ +#define DMAMAP_SPI1_TX DMAMAP_DMA12_SPI1TX_0 /* 2 DMA1:38 BMI055, ICM-42688-P */ + +#define DMAMAP_SPI2_RX DMAMAP_DMA12_SPI2RX_0 /* 3 DMA1:39 FRAM */ +#define DMAMAP_SPI2_TX DMAMAP_DMA12_SPI2TX_0 /* 4 DMA1:40 FRAM */ + +//#define DMAMAP_USART1_RX DMAMAP_DMA12_USART1RX_0 /* DMA1:41 GPS1 */ +//#define DMAMAP_USART1_TX DMAMAP_DMA12_USART1TX_0 /* DMA1:42 GPS1 */ + +//#define DMAMAP_USART2_RX DMAMAP_DMA12_USART2RX_0 /* DMA1:43 Telem3 */ +//#define DMAMAP_USART2_TX DMAMAP_DMA12_USART2TX_0 /* DMA1:44 Telem3 */ + +//#define DMAMAP_USART3_RX DMAMAP_DMA12_USART3RX_0 /* DMA1:45 DEBUG */ +//#define DMAMAP_USART3_TX DMAMAP_DMA12_USART3TX_0 /* DMA1:46 DEBUG */ + +//#define DMAMAP_UART4_RX DMAMAP_DMA12_UART4RX_0 /* DMA1:63 EXT2 */ +//#define DMAMAP_UART4_TX DMAMAP_DMA12_UART4TX_0 /* DMA1:64 EXT2 */ + +#define DMAMAP_USART6_RX DMAMAP_DMA12_USART6RX_0 /* 5 DMA1:71 PX4IO */ +#define DMAMAP_USART6_TX DMAMAP_DMA12_USART6TX_0 /* 6 DMA1:72 PX4IO */ + +// Assigned in timer_config.cpp + +// Timer 4 /* 7 DMA1:32 TIM4UP */ +// Timer 5 /* 8 DMA1:50 TIM5UP */ + +// DMAMUX2 Using at most 8 Channels on DMA2 -------- Assigned +// V + + +#define DMAMAP_USART3_RX DMAMAP_DMA12_USART3RX_1 /* 3 DMA2:45 DEBUG */ +#define DMAMAP_USART3_TX DMAMAP_DMA12_USART3TX_1 /* 4 DMA2:46 DEBUG */ + +#define DMAMAP_UART5_RX DMAMAP_DMA12_UART5RX_1 /* 5 DMA2:65 TELEM2 */ +#define DMAMAP_UART5_TX DMAMAP_DMA12_UART5TX_1 /* 6 DMA2:66 TELEM2 */ + +#define DMAMAP_UART7_RX DMAMAP_DMA12_UART7RX_1 /* 7 DMA1:79 TELEM1 */ +#define DMAMAP_UART7_TX DMAMAP_DMA12_UART7TX_1 /* 8 DMA1:80 TELEM1 */ + +//#define DMAMAP_UART8_RX DMAMAP_DMA12_UART8RX_1 /* DMA1:81 GPS2 */ +//#define DMAMAP_UART8_TX DMAMAP_DMA12_UART8TX_1 /* DMA1:82 GPS2 */ diff --git a/boards/px4/fts-can/nuttx-config/nsh/defconfig b/boards/px4/fts-can/nuttx-config/nsh/defconfig new file mode 100644 index 0000000..1fb11e7 --- /dev/null +++ b/boards/px4/fts-can/nuttx-config/nsh/defconfig @@ -0,0 +1,266 @@ +# +# 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_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/px4/fts-can/nuttx-config" +CONFIG_ARCH_BOARD_CUSTOM_DIR_RELPATH=y +CONFIG_ARCH_BOARD_CUSTOM_NAME="px4" +CONFIG_ARCH_CHIP="stm32h7" +CONFIG_ARCH_CHIP_STM32H743VI=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=95751 +CONFIG_BOARD_RESET_ON_ASSERT=2 +CONFIG_BUILTIN=y +CONFIG_CDCACM=y +CONFIG_CDCACM_IFLOWCONTROL=y +CONFIG_CDCACM_PRODUCTID=0x0038 +CONFIG_CDCACM_PRODUCTSTR="NIMBUS FTS-CAN" +CONFIG_CDCACM_RXBUFSIZE=600 +CONFIG_CDCACM_TXBUFSIZE=12000 +CONFIG_CDCACM_VENDORID=0x3185 +CONFIG_CDCACM_VENDORSTR="Auterion" +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_HARDFAULT_ALERT=y +CONFIG_DEBUG_MEMFAULT=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_IOB_NBUFFERS=24 +CONFIG_IOB_NCHAINS=24 +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_IOB=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_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_BDMA=y +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_I2C4=y +CONFIG_STM32H7_I2C_DYNTIMEO=y +CONFIG_STM32H7_I2C_DYNTIMEO_STARTSTOP=10 +CONFIG_STM32H7_OTGFS=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_SDMMC2=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_SPI2_DMA=y +CONFIG_STM32H7_SPI2_DMA_BUFFER=4096 +CONFIG_STM32H7_TIM12=y +CONFIG_STM32H7_TIM1=y +CONFIG_STM32H7_TIM4=y +CONFIG_STM32H7_TIM5=y +CONFIG_STM32H7_UART5=y +CONFIG_STM32H7_UART7=y +CONFIG_STM32H7_UART8=y +CONFIG_STM32H7_USART1=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_UART5_IFLOWCONTROL=y +CONFIG_UART5_OFLOWCONTROL=y +CONFIG_UART5_RXDMA=y +CONFIG_UART5_TXBUFSIZE=3000 +CONFIG_UART5_TXDMA=y +CONFIG_UART7_BAUD=57600 +CONFIG_UART7_IFLOWCONTROL=y +CONFIG_UART7_OFLOWCONTROL=y +CONFIG_UART7_RXBUFSIZE=600 +CONFIG_UART7_RXDMA=y +CONFIG_UART7_TXBUFSIZE=3000 +CONFIG_UART7_TXDMA=y +CONFIG_UART8_BAUD=57600 +CONFIG_UART8_RXBUFSIZE=600 +CONFIG_UART8_TXBUFSIZE=1500 +CONFIG_USART1_BAUD=57600 +CONFIG_USART1_RXBUFSIZE=600 +CONFIG_USART1_TXBUFSIZE=1500 +CONFIG_USART2_BAUD=57600 +CONFIG_USART2_RXBUFSIZE=600 +CONFIG_USART2_TXBUFSIZE=3000 +CONFIG_USART3_BAUD=57600 +CONFIG_USART3_RXBUFSIZE=180 +CONFIG_USART3_RXDMA=y +CONFIG_USART3_SERIAL_CONSOLE=y +CONFIG_USART3_TXBUFSIZE=1500 +CONFIG_USART3_TXDMA=y +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 +CONFIG_WQUEUE_NOTIFIER=y diff --git a/boards/px4/fts-can/nuttx-config/scripts/bootloader_script.ld b/boards/px4/fts-can/nuttx-config/scripts/bootloader_script.ld new file mode 100644 index 0000000..c10e790 --- /dev/null +++ b/boards/px4/fts-can/nuttx-config/scripts/bootloader_script.ld @@ -0,0 +1,215 @@ +/**************************************************************************** + * scripts/script.ld + * + * Copyright (C) 2016, 2019 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 PX4 FMUV6C uses an STM32H753II 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 STM32H743II, 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 + * + * The PX4 FMUV6C has a test point on board, the BOOT0 pin is at ground so by + * default, the STM32 will boot to address 0x0800:0000 in FLASH unless the test + * point is pulled to 3.3V.then the boot will be from 0x1FF0:0000 + * + * The STM32H743II 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. + * + * The bootloader uses the first sector of the flash, which is 128K in length. + */ + +MEMORY +{ + itcm (rwx) : ORIGIN = 0x00000000, LENGTH = 64K + flash (rx) : ORIGIN = 0x08000000, LENGTH = 128K + dtcm1 (rwx) : ORIGIN = 0x20000000, LENGTH = 64K + dtcm2 (rwx) : ORIGIN = 0x20010000, LENGTH = 64K + sram (rwx) : ORIGIN = 0x24000000, LENGTH = 512K + sram1 (rwx) : ORIGIN = 0x30000000, LENGTH = 128K + sram2 (rwx) : ORIGIN = 0x30020000, LENGTH = 128K + sram3 (rwx) : ORIGIN = 0x30040000, LENGTH = 32K + sram4 (rwx) : ORIGIN = 0x38000000, LENGTH = 64K + bbram (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(.); + } > sram AT > flash + + .bss : { + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _ebss = ABSOLUTE(.); + } > sram + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/boards/px4/fts-can/nuttx-config/scripts/script.ld b/boards/px4/fts-can/nuttx-config/scripts/script.ld new file mode 100644 index 0000000..fcc97ec --- /dev/null +++ b/boards/px4/fts-can/nuttx-config/scripts/script.ld @@ -0,0 +1,229 @@ +/**************************************************************************** + * scripts/script.ld + * + * Copyright (C) 2016, 2019 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 PX4 FMUV6C uses an STM32H753II 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 STM32H743II, 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 + * + * The PX4 FMUV6C has a test point on board, the BOOT0 pin is at ground so by + * default, the STM32 will boot to address 0x0800:0000 in FLASH unless the test + * point is pulled to 3.3V.then the boot will be from 0x1FF0:0000 + * + * The STM32H743II 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) +EXTERN(board_get_manifest) + +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/px4/fts-can/src/CMakeLists.txt b/boards/px4/fts-can/src/CMakeLists.txt new file mode 100644 index 0000000..d7b08bb --- /dev/null +++ b/boards/px4/fts-can/src/CMakeLists.txt @@ -0,0 +1,75 @@ +############################################################################ +# +# Copyright (c) 2016 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_compile_definitions(BOOTLOADER) + add_library(drivers_board + bootloader_main.c + init.c + usb.c + timer_config.cpp + ) + target_link_libraries(drivers_board + PRIVATE + nuttx_arch # sdio + nuttx_drivers # sdio + px4_layer #gpio + arch_io_pins # iotimer + bootloader + ) + target_include_directories(drivers_board PRIVATE ${PX4_SOURCE_DIR}/platforms/nuttx/src/bootloader/common) + +else() + add_library(drivers_board + can.c + i2c.cpp + init.c + led.c + mtd.cpp + manifest.c + sdio.c + spi.cpp + timer_config.cpp + usb.c + ) + add_dependencies(drivers_board arch_board_hw_info) + + target_link_libraries(drivers_board + PRIVATE + arch_spi + arch_board_hw_info + drivers__led # drv_led_start + nuttx_arch # sdio + nuttx_drivers # sdio + px4_layer + ) +endif() diff --git a/boards/px4/fts-can/src/board_config.h b/boards/px4/fts-can/src/board_config.h new file mode 100644 index 0000000..fb5382c --- /dev/null +++ b/boards/px4/fts-can/src/board_config.h @@ -0,0 +1,324 @@ +/**************************************************************************** + * + * Copyright (c) 2022 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 + * + * PX4FMU-v6c internal definitions + */ + +#pragma once + +/**************************************************************************************************** + * Included Files + ****************************************************************************************************/ + +#include +#include +#include + + +#include + +/**************************************************************************************************** + * Definitions + ****************************************************************************************************/ + +#undef TRACE_PINS + +/* PX4IO connection configuration */ + +#define BOARD_USES_PX4IO_VERSION 2 +#define PX4IO_SERIAL_DEVICE "/dev/ttyS4" +#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 */ + +/* PX4FMU GPIOs ***********************************************************************************/ + + +/* LEDs are driven with push pull Anodes to 3.3V */ + +#define GPIO_nLED_RED /* PD10 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_50MHz|GPIO_OUTPUT_SET|GPIO_PORTD|GPIO_PIN10) +#define GPIO_nLED_BLUE /* PD11 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_50MHz|GPIO_OUTPUT_SET|GPIO_PORTD|GPIO_PIN11) + +#define BOARD_HAS_CONTROL_STATUS_LEDS 1 +#define BOARD_OVERLOAD_LED LED_RED +#define BOARD_ARMED_STATE_LED LED_BLUE + +/* + * ADC channels + * + * These are the channel numbers of the ADCs of the microcontroller that + * can be used by the Px4 Firmware in the adc driver + */ + +/* ADC defines to be used in sensors.cpp to read from a particular channel */ + +#define ADC1_CH(n) (n) + +/* N.B. there is no offset mapping needed for ADC3 because */ +#define ADC3_CH(n) (n) + +/* We are only use ADC3 for REV/VER. */ + +/* Define GPIO pins used as ADC N.B. Channel numbers must match below */ + +#define PX4_ADC_GPIO \ + /* PC4 */ GPIO_ADC12_INP4, \ + /* PB1 */ GPIO_ADC12_INP5, \ + /* PC5 */ GPIO_ADC12_INP8, \ + /* PC0 */ GPIO_ADC123_INP10, \ + /* PC1 */ GPIO_ADC123_INP11, \ + /* PA2 */ GPIO_ADC12_INP14, \ + /* PA4 */ GPIO_ADC12_INP18 \ + +/* Define Channel numbers must match above GPIO pin IN(n)*/ +#define ADC_BATTERY1_CURRENT_CHANNEL /* PC4 */ ADC1_CH(4) +#define ADC_BATTERY2_VOLTAGE_CHANNEL /* PB1 */ ADC1_CH(5) +#define ADC_BATTERY1_VOLTAGE_CHANNEL /* PC5 */ ADC1_CH(8) +#define ADC_HW_REV_SENSE_CHANNEL /* PC0 */ ADC3_CH(10) +#define ADC_HW_VER_SENSE_CHANNEL /* PC1 */ ADC3_CH(11) +#define ADC_BATTERY2_CURRENT_CHANNEL /* PA2 */ ADC1_CH(14) +#define ADC_SCALED_V5_CHANNEL /* PA4 */ ADC1_CH(18) + +#define ADC_CHANNELS \ + ((1 << ADC_BATTERY1_CURRENT_CHANNEL) | \ + (1 << ADC_BATTERY2_VOLTAGE_CHANNEL) | \ + (1 << ADC_BATTERY1_VOLTAGE_CHANNEL) | \ + (1 << ADC_BATTERY2_CURRENT_CHANNEL) | \ + (1 << ADC_SCALED_V5_CHANNEL )) + +#define HW_REV_VER_ADC_BASE STM32_ADC3_BASE + +#define SYSTEM_ADC_BASE STM32_ADC1_BASE + +/* HW has to large of R termination on ADC todo:change when HW value is chosen */ +#define BOARD_ADC_OPEN_CIRCUIT_V (5.6f) + +/* HW Version and Revision drive signals Default to 1 to detect */ +#define BOARD_HAS_HW_VERSIONING + +#define GPIO_HW_VER_REV_DRIVE /* PE12 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTE|GPIO_PIN12) +#define GPIO_HW_REV_SENSE /* PC0 */ GPIO_ADC123_INP10 +#define GPIO_HW_VER_SENSE /* PC1 */ GPIO_ADC123_INP11 +#define HW_INFO_INIT_PREFIX "FTSCAN" + +#define BOARD_NUM_SPI_CFG_HW_VERSIONS 3 // Rev 0, 10 and Mini Sensor sets +// Base/FMUM +#define V6C00 HW_VER_REV(0x0,0x0) // FMUV6C, Rev 0 I2C4 External but with Internal devices +#define V6C01 HW_VER_REV(0x0,0x1) // FMUV6C, Rev 1 I2C4 Internal I2C2 External +#define V6C10 HW_VER_REV(0x1,0x0) // NO PX4IO, Rev 0 I2C4 External but with Internal devices +#define V6C11 HW_VER_REV(0x1,0x1) // NO PX4IO, Rev 1 I2C4 Internal I2C2 External +#define V6C21 HW_VER_REV(0x2,0x1) // FMUV6CMini, Rev 1 I2C4 Internal I2C2 External + + +/* HEATER + * PWM in future + */ +#define GPIO_HEATER_OUTPUT /* PB9 T17CH1 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTB|GPIO_PIN9) +#define HEATER_OUTPUT_EN(on_true) px4_arch_gpiowrite(GPIO_HEATER_OUTPUT, (on_true)) + +/* PWM + */ +#define DIRECT_PWM_OUTPUT_CHANNELS 8 + + +/* Power supply control and monitoring GPIOs */ + +#define GPIO_nPOWER_IN_A /* PA15 */ (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN15) +#define GPIO_nPOWER_IN_B /* PB12 */ (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN12) +#define GPIO_nPOWER_IN_C /* PE15 */ (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTE|GPIO_PIN15) + +#define GPIO_nVDD_BRICK1_VALID GPIO_nPOWER_IN_A /* Brick 1 Is Chosen */ +#define GPIO_nVDD_BRICK2_VALID GPIO_nPOWER_IN_B /* Brick 2 Is Chosen */ +#define BOARD_NUMBER_BRICKS 2 +#define GPIO_nVDD_USB_VALID GPIO_nPOWER_IN_C /* USB Is Chosen */ + +#define GPIO_VDD_5V_PERIPH_nEN /* PE2 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTE|GPIO_PIN2) +#define GPIO_VDD_5V_PERIPH_nOC /* PE3 */ (GPIO_INPUT |GPIO_FLOAT|GPIO_PORTE|GPIO_PIN3) +#define GPIO_VDD_5V_HIPOWER_nEN /* PC10 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTC|GPIO_PIN10) +#define GPIO_VDD_5V_HIPOWER_nOC /* PC11 */ (GPIO_INPUT |GPIO_FLOAT|GPIO_PORTC|GPIO_PIN11) +#define GPIO_VDD_3V3_SENSORS_EN /* PB2 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTB|GPIO_PIN2) + +/* Define True logic Power Control in arch agnostic form */ + +#define VDD_5V_PERIPH_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_5V_PERIPH_nEN, !(on_true)) +#define VDD_5V_HIPOWER_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_5V_HIPOWER_nEN, !(on_true)) +#define VDD_3V3_SENSORS_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_3V3_SENSORS4_EN, (on_true)) + +/* Tone alarm output */ + +#define TONE_ALARM_TIMER 3 /* Timer 3 */ +#define TONE_ALARM_CHANNEL 3 /* PB0 GPIO_TIM3_CH3OUT_1 */ + +#define GPIO_BUZZER_1 /* PPB0 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTB|GPIO_PIN0) + +#define GPIO_TONE_ALARM_IDLE GPIO_BUZZER_1 +#define GPIO_TONE_ALARM GPIO_TIM3_CH3OUT_1 + +/* 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 */ + +/* PWM input driver. Use FMU AUX5 pins attached to timer4 channel 3 */ +#define PWMIN_TIMER 4 +#define PWMIN_TIMER_CHANNEL /* T4C3 */ 3 +#define GPIO_PWM_IN /* PD14 */ GPIO_TIM4_CH3IN_2 + +#define SDIO_SLOTNO 0 /* Only one slot */ +#define SDIO_MINOR 0 + +/* SD card bringup does not work if performed on the IDLE thread because it + * will cause waiting. Use either: + * + * CONFIG_BOARDCTL=y, OR + * CONFIG_BOARD_INITIALIZE=y && CONFIG_BOARD_INITTHREAD=y + */ + +#if defined(CONFIG_BOARD_INITIALIZE) && !defined(CONFIG_BOARDCTL) && \ + !defined(CONFIG_BOARD_INITTHREAD) +# warning SDIO initialization cannot be perfomed on the IDLE thread +#endif + +/* 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)) + +/* FTS-CAN never powers off the Servo rail */ + +#define BOARD_ADC_SERVO_VALID (1) + +#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_VDD_5V_PERIPH_nOC)) +#define BOARD_ADC_HIPOWER_5V_OC (!px4_arch_gpioread(GPIO_VDD_5V_HIPOWER_nOC)) + + +/* 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 PX4_GPIO_INIT_LIST { \ + PX4_ADC_GPIO, \ + GPIO_HW_VER_REV_DRIVE, \ + GPIO_CAN1_TX, \ + GPIO_CAN1_RX, \ + GPIO_CAN2_TX, \ + GPIO_CAN2_RX, \ + GPIO_HEATER_OUTPUT, \ + GPIO_nPOWER_IN_A, \ + GPIO_nPOWER_IN_B, \ + GPIO_nPOWER_IN_C, \ + GPIO_VDD_5V_PERIPH_nEN, \ + GPIO_VDD_5V_PERIPH_nOC, \ + GPIO_VDD_5V_HIPOWER_nEN, \ + GPIO_VDD_5V_HIPOWER_nOC, \ + GPIO_VDD_3V3_SENSORS_EN, \ + GPIO_TONE_ALARM_IDLE, \ + } + +#define BOARD_ENABLE_CONSOLE_BUFFER + +#define PX4_I2C_BUS_MTD 4,5 + +#define BOARD_OVERRIDE_I2C_DEVICE_EXTERNAL + + +#define BOARD_NUM_IO_TIMERS 5 + +__BEGIN_DECLS + +/**************************************************************************************************** + * Public Types + ****************************************************************************************************/ + +/**************************************************************************************************** + * Public data + ****************************************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************************************** + * Public Functions + ****************************************************************************************************/ + +/**************************************************************************** + * Name: stm32_sdio_initialize + * + * Description: + * Initialize SDIO-based MMC/SD card support + * + ****************************************************************************/ + +int stm32_sdio_initialize(void); + +/**************************************************************************************************** + * Name: stm32_spiinitialize + * + * Description: + * Called to configure SPI chip select GPIO pins for the PX4FMU board. + * + ****************************************************************************************************/ + +extern void stm32_spiinitialize(void); + +extern void stm32_usbinitialize(void); + +extern void board_peripheral_reset(int ms); + +#include + +#endif /* __ASSEMBLY__ */ + +__END_DECLS diff --git a/boards/px4/fts-can/src/bootloader_main.c b/boards/px4/fts-can/src/bootloader_main.c new file mode 100644 index 0000000..77df9e7 --- /dev/null +++ b/boards/px4/fts-can/src/bootloader_main.c @@ -0,0 +1,62 @@ +/**************************************************************************** + * + * Copyright (c) 2019-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); + +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/px4/fts-can/src/can.c b/boards/px4/fts-can/src/can.c new file mode 100644 index 0000000..c71b2e8 --- /dev/null +++ b/boards/px4/fts-can/src/can.c @@ -0,0 +1,128 @@ +/**************************************************************************** + * + * Copyright (C) 2012 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 px4fmu_can.c + * + * Board-specific CAN functions. + */ + +#ifdef CONFIG_CAN + +#include +#include + +#include +#include + +#include "chip.h" +#include "arm_internal.h" + +#include "chip.h" +#include "stm32_can.h" +#include "board_config.h" + +#ifdef CONFIG_CAN + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ +/* Configuration ********************************************************************/ + +#if defined(CONFIG_STM32_CAN1) && defined(CONFIG_STM32_CAN2) +# warning "Both CAN1 and CAN2 are enabled. Assuming only CAN1." +# undef CONFIG_STM32_CAN2 +#endif + +#ifdef CONFIG_STM32_CAN1 +# define CAN_PORT 1 +#else +# define CAN_PORT 2 +#endif + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ +int can_devinit(void); + +/************************************************************************************ + * Name: can_devinit + * + * Description: + * All STM32 architectures must provide the following interface to work with + * examples/can. + * + ************************************************************************************/ + +int can_devinit(void) +{ + static bool initialized = false; + struct can_dev_s *can; + int ret; + + /* Check if we have already initialized */ + + if (!initialized) { + /* Call stm32_caninitialize() to get an instance of the CAN interface */ + + can = stm32_caninitialize(CAN_PORT); + + if (can == NULL) { + canerr("ERROR: Failed to get CAN interface\n"); + return -ENODEV; + } + + /* Register the CAN driver at "/dev/can0" */ + + ret = can_register("/dev/can0", can); + + if (ret < 0) { + canerr("ERROR: can_register failed: %d\n", ret); + return ret; + } + + /* Now we are initialized */ + + initialized = true; + } + + return OK; +} + +#endif + +#endif /* CONFIG_CAN */ diff --git a/boards/px4/fts-can/src/hw_config.h b/boards/px4/fts-can/src/hw_config.h new file mode 100644 index 0000000..07bf6f4 --- /dev/null +++ b/boards/px4/fts-can/src/hw_config.h @@ -0,0 +1,128 @@ +/* + * hw_config.h + * + * Created on: May 17, 2015 + * Author: david_s5 + */ + +#ifndef HW_CONFIG_H_ +#define HW_CONFIG_H_ + +/**************************************************************************** + * 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 56 +#define _FLASH_KBYTES (*(uint32_t *)0x1FF1E880) +#define BOARD_FLASH_SECTORS (15) +#define BOARD_FLASH_SIZE (_FLASH_KBYTES * 1024) + +#define OSC_FREQ 16 + +#define BOARD_PIN_LED_ACTIVITY GPIO_nLED_BLUE // BLUE +#define BOARD_PIN_LED_BOOTLOADER GPIO_nLED_RED // RED +#define BOARD_LED_ON 0 +#define BOARD_LED_OFF 1 + +#define SERIAL_BREAK_DETECT_DISABLED 1 + +/* + * Uncommenting this allows to force the bootloader through + * a PWM output pin. As this can accidentally initialize + * an ESC prematurely, it is not recommended. This feature + * has not been used and hence defaults now to off. + * + * # define BOARD_FORCE_BL_PIN_OUT (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTE|GPIO_PIN14) + * # define BOARD_FORCE_BL_PIN_IN (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTE|GPIO_PIN11) + * + * # define BOARD_POWER_PIN_OUT (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTA|GPIO_PIN4) + * # define BOARD_POWER_ON 1 + * # define BOARD_POWER_OFF 0 + * # undef BOARD_POWER_PIN_RELEASE // Leave pin enabling Power - un comment to release (disable power) + * +*/ + +#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 + +#endif /* HW_CONFIG_H_ */ diff --git a/boards/px4/fts-can/src/i2c.cpp b/boards/px4/fts-can/src/i2c.cpp new file mode 100644 index 0000000..ab0a2bb --- /dev/null +++ b/boards/px4/fts-can/src/i2c.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** + * + * 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_i2c_bus_t px4_i2c_buses[I2C_BUS_MAX_BUS_ITEMS] = { + initI2CBusExternal(1), + initI2CBusExternal(2), + initI2CBusExternal(4), +}; + +bool px4_i2c_device_external(const uint32_t device_id) +{ + { + // The internal baro and mag on Pixhawk 6C are on an external + // bus. On rev 0, the bus is actually exposed externally, on + // rev 1+, it is properly internal, however, still marked as + // external for compatibility. + + // device_id: 4028193 + device::Device::DeviceId device_id_baro{}; + device_id_baro.devid_s.bus_type = device::Device::DeviceBusType_I2C; + device_id_baro.devid_s.bus = 4; + device_id_baro.devid_s.address = 0x77; + device_id_baro.devid_s.devtype = DRV_BARO_DEVTYPE_MS5611; + + if (device_id_baro.devid == device_id) { + return false; + } + + // device_id: 396321 + device::Device::DeviceId device_id_mag{}; + device_id_mag.devid_s.bus_type = device::Device::DeviceBusType_I2C; + device_id_mag.devid_s.bus = 4; + device_id_mag.devid_s.address = 0xc; + device_id_mag.devid_s.devtype = DRV_MAG_DEVTYPE_IST8310; + + if (device_id_mag.devid == device_id) { + return false; + } + } + + device::Device::DeviceId dev_id{}; + dev_id.devid = device_id; + return px4_i2c_bus_external(dev_id.devid_s.bus); +} diff --git a/boards/px4/fts-can/src/init.c b/boards/px4/fts-can/src/init.c new file mode 100644 index 0000000..5a853b3 --- /dev/null +++ b/boards/px4/fts-can/src/init.c @@ -0,0 +1,259 @@ +/**************************************************************************** + * + * Copyright (c) 2012-2022 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 + * + * PX4FMU-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 initialization. + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "board_config.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "arm_internal.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* + * 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); +__END_DECLS + + +/************************************************************************************ + * Name: board_peripheral_reset + * + * Description: + * + ************************************************************************************/ +__EXPORT void board_peripheral_reset(int ms) +{ + /* set the peripheral rails off */ + + VDD_5V_PERIPH_EN(false); + board_control_spi_sensors_power(false, 0xffff); + + /* wait for the peripheral rail to reach GND */ + usleep(ms * 1000); + syslog(LOG_DEBUG, "reset done, %d ms\n", ms); + + /* re-enable power */ + + /* switch the peripheral rail back on */ + board_control_spi_sensors_power(true, 0xffff); + VDD_5V_PERIPH_EN(true); + +} + +/************************************************************************************ + * 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(io_timer_channel_get_gpio_output(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) +{ + board_on_reset(-1); /* Reset PWM first thing */ + + /* configure LEDs */ + + board_autoled_initialize(); + + /* configure pins */ + + const uint32_t gpio[] = PX4_GPIO_INIT_LIST; + px4_gpio_init(gpio, arraySize(gpio)); + + /* configure USB interfaces */ + + stm32_usbinitialize(); +} + +/**************************************************************************** + * Name: board_app_initialize + * + * Description: + * Perform application specific initialization. This function is never + * called directly from application code, but only indirectly via the + * (non-standard) boardctl() interface using the command BOARDIOC_INIT. + * + * Input Parameters: + * arg - The boardctl() argument is passed to the board_app_initialize() + * implementation without modification. The argument has no + * meaning to NuttX; the meaning of the argument is a contract + * between the board-specific initalization logic and the the + * matching application logic. The value cold be such things as a + * mode enumeration value, a set of DIP switch switch settings, a + * pointer to configuration data read from a file or serial FLASH, + * or whatever you would like to do with it. Every implementation + * should accept zero/NULL as a default configuration. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure to indicate the nature of the failure. + * + ****************************************************************************/ + +__EXPORT int board_app_initialize(uintptr_t arg) +{ +#if !defined(BOOTLOADER) + + /* Power on Interfaces */ + VDD_5V_PERIPH_EN(true); + VDD_5V_HIPOWER_EN(true); + + /* Need hrt running before using the ADC */ + + px4_platform_init(); + + + if (OK == board_determine_hw_info()) { + syslog(LOG_INFO, "[boot] Rev 0x%1x : Ver 0x%1x %s\n", board_get_hw_revision(), board_get_hw_version(), + board_get_hw_type_name()); + + } else { + syslog(LOG_ERR, "[boot] Failed to read HW revision and version\n"); + } + + stm32_spiinitialize(); + + board_spi_reset(10, 0xffff); + + /* configure the DMA allocator */ + + if (board_dma_alloc_init() < 0) { + syslog(LOG_ERR, "[boot] DMA alloc FAILED\n"); + } + +# if defined(SERIAL_HAVE_RXDMA) + // set up the serial DMA polling at 1ms intervals for received bytes that have not triggered a DMA event. + static struct hrt_call serial_dma_call; + hrt_call_every(&serial_dma_call, 1000, 1000, (hrt_callout)stm32_serial_dma_poll, NULL); +# endif + + /* initial LED state */ + drv_led_start(); + led_off(LED_RED); + led_off(LED_BLUE); + + if (board_hardfault_init(2, true) != 0) { + led_on(LED_RED); + } + +# ifdef CONFIG_MMCSD + int ret = stm32_sdio_initialize(); + + if (ret != OK) { + led_on(LED_RED); + } + +# endif /* CONFIG_MMCSD */ + + /* Configure the HW based on the manifest */ + + px4_platform_configure(); +#endif + return OK; +} diff --git a/boards/px4/fts-can/src/led.c b/boards/px4/fts-can/src/led.c new file mode 100644 index 0000000..442e763 --- /dev/null +++ b/boards/px4/fts-can/src/led.c @@ -0,0 +1,235 @@ +/**************************************************************************** + * + * Copyright (c) 2013 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 px4fmu2_led.c + * + * PX4FMU 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 + +#ifdef CONFIG_ARCH_LEDS +static bool nuttx_owns_leds = true; +// B R S G +// 0 1 2 3 +static const uint8_t xlatpx4[] = {1, 2, 4, 0}; +# define xlat(p) xlatpx4[(p)] +static uint32_t g_ledmap[] = { + GPIO_nLED_GREEN, // Indexed by BOARD_LED_GREEN + GPIO_nLED_BLUE, // Indexed by BOARD_LED_BLUE + GPIO_nLED_RED, // Indexed by BOARD_LED_RED + GPIO_nSAFETY_SWITCH_LED_OUT, // Indexed by LED_SAFETY by xlatpx4 +}; + +#else + +# define xlat(p) (p) +static uint32_t g_ledmap[] = { + GPIO_nLED_BLUE, // Indexed by LED_BLUE + GPIO_nLED_RED, // Indexed by LED_RED, LED_AMBER + 0, // Indexed by LED_SAFETY (defaulted to an input) + 0, // Indexed by LED_GREEN +}; + +#endif + +__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))); +} + +#ifdef CONFIG_ARCH_LEDS +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_autoled_initialize + ****************************************************************************/ + +void board_autoled_initialize(void) +{ + led_init(); +} + +/**************************************************************************** + * Name: board_autoled_on + ****************************************************************************/ + +void board_autoled_on(int led) +{ + if (!nuttx_owns_leds) { + return; + } + + switch (led) { + default: + break; + + case LED_HEAPALLOCATE: + phy_set_led(BOARD_LED_BLUE, true); + break; + + case LED_IRQSENABLED: + phy_set_led(BOARD_LED_BLUE, false); + phy_set_led(BOARD_LED_GREEN, true); + break; + + case LED_STACKCREATED: + phy_set_led(BOARD_LED_GREEN, true); + phy_set_led(BOARD_LED_BLUE, true); + break; + + case LED_INIRQ: + phy_set_led(BOARD_LED_BLUE, true); + break; + + case LED_SIGNAL: + phy_set_led(BOARD_LED_GREEN, true); + break; + + case LED_ASSERTION: + phy_set_led(BOARD_LED_RED, true); + phy_set_led(BOARD_LED_BLUE, true); + break; + + case LED_PANIC: + phy_set_led(BOARD_LED_RED, true); + break; + + case LED_IDLE : /* IDLE */ + phy_set_led(BOARD_LED_RED, true); + break; + } +} + +/**************************************************************************** + * Name: board_autoled_off + ****************************************************************************/ + +void board_autoled_off(int led) +{ + if (!nuttx_owns_leds) { + return; + } + + switch (led) { + default: + break; + + case LED_SIGNAL: + phy_set_led(BOARD_LED_GREEN, false); + break; + + case LED_INIRQ: + phy_set_led(BOARD_LED_BLUE, false); + break; + + case LED_ASSERTION: + phy_set_led(BOARD_LED_RED, false); + phy_set_led(BOARD_LED_BLUE, false); + break; + + case LED_PANIC: + phy_set_led(BOARD_LED_RED, false); + break; + + case LED_IDLE : /* IDLE */ + phy_set_led(BOARD_LED_RED, false); + break; + } +} + +#endif /* CONFIG_ARCH_LEDS */ diff --git a/boards/px4/fts-can/src/manifest.c b/boards/px4/fts-can/src/manifest.c new file mode 100644 index 0000000..4a0401b --- /dev/null +++ b/boards/px4/fts-can/src/manifest.c @@ -0,0 +1,155 @@ +/**************************************************************************** + * + * Copyright (c) 2018-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 manifest.c + * + * This module supplies the interface to the manifest of hardware that is + * optional and dependent on the HW REV and HW VER IDs + * + * The manifest allows the system to know whether a hardware option + * say for example the PX4IO is an no-pop option vs it is broken. + * + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include + +#include "systemlib/px4_macros.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +typedef struct { + uint32_t hw_ver_rev; /* the version and revision */ + const px4_hw_mft_item_t *mft; /* The first entry */ + uint32_t entries; /* the lenght of the list */ +} px4_hw_mft_list_entry_t; + +typedef px4_hw_mft_list_entry_t *px4_hw_mft_list_entry; +#define px4_hw_mft_list_uninitialized (px4_hw_mft_list_entry) -1 + +static const px4_hw_mft_item_t device_unsupported = {0, 0, 0}; + +// List of components on a specific board configuration +// The index of those components is given by the enum (px4_hw_mft_item_id_t) +// declared in board_common.h +static const px4_hw_mft_item_t hw_mft_list_v0600[] = { + { + .present = 1, + .mandatory = 1, + .connection = px4_hw_con_onboard, + }, + { + .present = 1, + .mandatory = 1, + .connection = px4_hw_con_onboard, + }, +}; + +static const px4_hw_mft_item_t hw_mft_list_v0610[] = { + { + .present = 0, + .mandatory = 0, + .connection = px4_hw_con_unknown, + }, + { + .present = 1, + .mandatory = 1, + .connection = px4_hw_con_onboard, + }, +}; + + +static px4_hw_mft_list_entry_t mft_lists[] = { +// ver_rev + {V6C00, hw_mft_list_v0600, arraySize(hw_mft_list_v0600)}, // Rev 0 + {V6C01, hw_mft_list_v0600, arraySize(hw_mft_list_v0600)}, // Rev 1 + {V6C10, hw_mft_list_v0610, arraySize(hw_mft_list_v0610)}, // Rev 0 No PX4IO + {V6C11, hw_mft_list_v0610, arraySize(hw_mft_list_v0610)}, // Rev 1 No PX4IO + {V6C21, hw_mft_list_v0600, arraySize(hw_mft_list_v0600)}, // Rev 1 MINI +}; + +/************************************************************************************ + * Name: board_query_manifest + * + * Description: + * Optional returns manifest item. + * + * Input Parameters: + * manifest_id - the ID for the manifest item to retrieve + * + * Returned Value: + * 0 - item is not in manifest => assume legacy operations + * pointer to a manifest item + * + ************************************************************************************/ + +__EXPORT px4_hw_mft_item board_query_manifest(px4_hw_mft_item_id_t id) +{ + static px4_hw_mft_list_entry boards_manifest = px4_hw_mft_list_uninitialized; + + if (boards_manifest == px4_hw_mft_list_uninitialized) { + uint32_t ver_rev = board_get_hw_version() << 16; + ver_rev |= board_get_hw_revision(); + + for (unsigned i = 0; i < arraySize(mft_lists); i++) { + if (mft_lists[i].hw_ver_rev == ver_rev) { + boards_manifest = &mft_lists[i]; + break; + } + } + + if (boards_manifest == px4_hw_mft_list_uninitialized) { + syslog(LOG_ERR, "[boot] Board %08" PRIx32 " is not supported!\n", ver_rev); + } + } + + px4_hw_mft_item rv = &device_unsupported; + + if (boards_manifest != px4_hw_mft_list_uninitialized && + id < boards_manifest->entries) { + rv = &boards_manifest->mft[id]; + } + + return rv; +} diff --git a/boards/px4/fts-can/src/mtd.cpp b/boards/px4/fts-can/src/mtd.cpp new file mode 100644 index 0000000..b315ff3 --- /dev/null +++ b/boards/px4/fts-can/src/mtd.cpp @@ -0,0 +1,111 @@ +/**************************************************************************** + * + * 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 +// KiB BS nB +static const px4_mft_device_t spi2 = { // FM25V02A on FMUM 32K 512 X 64 + .bus_type = px4_mft_device_t::SPI, + .devid = SPIDEV_FLASH(0) +}; + +static const px4_mft_device_t i2c4 = { // 24LC64T on IMU 8K 32 X 256 + .bus_type = px4_mft_device_t::I2C, + .devid = PX4_MK_I2C_DEVID(4, 0x50) +}; + + +static const px4_mtd_entry_t fmum_fram = { + .device = &spi2, + .npart = 2, + .partd = { + { + .type = MTD_PARAMETERS, + .path = "/fs/mtd_params", + .nblocks = 32 + }, + { + .type = MTD_WAYPOINTS, + .path = "/fs/mtd_waypoints", + .nblocks = 32 + + } + }, +}; + +static const px4_mtd_entry_t imu_eeprom = { + .device = &i2c4, + .npart = 3, + .partd = { + { + .type = MTD_CALDATA, + .path = "/fs/mtd_caldata", + .nblocks = 240 + }, + { + .type = MTD_MFT_REV, + .path = "/fs/mtd_mft_rev", + .nblocks = 8 + }, + { + .type = MTD_ID, + .path = "/fs/mtd_id", + .nblocks = 8 // 256 = 32 * 8 + } + }, +}; + +static const px4_mtd_manifest_t board_mtd_config = { + .nconfigs = 2, + .entries = { + &fmum_fram, + &imu_eeprom + } +}; + +static const px4_mft_entry_s mtd_mft = { + .type = MTD, + .pmft = (void *) &board_mtd_config, +}; + +static const px4_mft_s mft = { + .nmft = 1, + .mfts = { + &mtd_mft + } +}; + +const px4_mft_s *board_get_manifest(void) +{ + return &mft; +} diff --git a/boards/px4/fts-can/src/sdio.c b/boards/px4/fts-can/src/sdio.c new file mode 100644 index 0000000..869d757 --- /dev/null +++ b/boards/px4/fts-can/src/sdio.c @@ -0,0 +1,177 @@ +/**************************************************************************** + * + * Copyright (C) 2014, 2016 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "chip.h" +#include "board_config.h" +#include "stm32_gpio.h" +#include "stm32_sdmmc.h" + +#ifdef CONFIG_MMCSD + + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Card detections requires card support and a card detection GPIO */ + +#define HAVE_NCD 1 +#if !defined(GPIO_SDMMC1_NCD) +# undef HAVE_NCD +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static FAR struct sdio_dev_s *sdio_dev; +#ifdef HAVE_NCD +static bool g_sd_inserted = 0xff; /* Impossible value */ +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_ncd_interrupt + * + * Description: + * Card detect interrupt handler. + * + ****************************************************************************/ + +#ifdef HAVE_NCD +static int stm32_ncd_interrupt(int irq, FAR void *context) +{ + bool present; + + present = !stm32_gpioread(GPIO_SDMMC1_NCD); + + if (sdio_dev && present != g_sd_inserted) { + sdio_mediachange(sdio_dev, present); + g_sd_inserted = present; + } + + return OK; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_sdio_initialize + * + * Description: + * Initialize SDIO-based MMC/SD card support + * + ****************************************************************************/ + +int stm32_sdio_initialize(void) +{ + int ret; + +#ifdef HAVE_NCD + /* Card detect */ + + bool cd_status; + + /* Configure the card detect GPIO */ + + stm32_configgpio(GPIO_SDMMC1_NCD); + + /* Register an interrupt handler for the card detect pin */ + + stm32_gpiosetevent(GPIO_SDMMC1_NCD, true, true, true, stm32_ncd_interrupt); +#endif + + /* Mount the SDIO-based MMC/SD block driver */ + /* First, get an instance of the SDIO interface */ + + finfo("Initializing SDIO slot %d\n", SDIO_SLOTNO); + + sdio_dev = sdio_initialize(SDIO_SLOTNO); + + if (!sdio_dev) { + syslog(LOG_ERR, "[boot] Failed to initialize SDIO slot %d\n", SDIO_SLOTNO); + return -ENODEV; + } + + /* Now bind the SDIO interface to the MMC/SD driver */ + + finfo("Bind SDIO to the MMC/SD driver, minor=%d\n", SDIO_MINOR); + + ret = mmcsd_slotinitialize(SDIO_MINOR, sdio_dev); + + if (ret != OK) { + syslog(LOG_ERR, "[boot] Failed to bind SDIO to the MMC/SD driver: %d\n", ret); + return ret; + } + + finfo("Successfully bound SDIO to the MMC/SD driver\n"); + +#ifdef HAVE_NCD + /* Use SD card detect pin to check if a card is g_sd_inserted */ + + cd_status = !stm32_gpioread(GPIO_SDMMC1_NCD); + finfo("Card detect : %d\n", cd_status); + + sdio_mediachange(sdio_dev, cd_status); +#else + /* Assume that the SD card is inserted. What choice do we have? */ + + sdio_mediachange(sdio_dev, true); +#endif + + return OK; +} + +#endif /* CONFIG_MMCSD */ diff --git a/boards/px4/fts-can/src/spi.cpp b/boards/px4/fts-can/src/spi.cpp new file mode 100644 index 0000000..1cf3ece --- /dev/null +++ b/boards/px4/fts-can/src/spi.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** + * + * Copyright (C) 2020, 2022 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_all_hw_t px4_spi_buses_all_hw[BOARD_NUM_SPI_CFG_HW_VERSIONS] = { + initSPIHWVersion(V6C00, { + initSPIBus(SPI::Bus::SPI1, { + initSPIDevice(DRV_GYR_DEVTYPE_BMI055, SPI::CS{GPIO::PortC, GPIO::Pin14}, SPI::DRDY{GPIO::PortE, GPIO::Pin5}), + initSPIDevice(DRV_ACC_DEVTYPE_BMI055, SPI::CS{GPIO::PortC, GPIO::Pin15}, SPI::DRDY{GPIO::PortE, GPIO::Pin4}), + initSPIDevice(DRV_IMU_DEVTYPE_ICM42688P, SPI::CS{GPIO::PortC, GPIO::Pin13}, SPI::DRDY{GPIO::PortE, GPIO::Pin6}), + }, {GPIO::PortB, GPIO::Pin2}), + initSPIBus(SPI::Bus::SPI2, { + initSPIDevice(SPIDEV_FLASH(0), SPI::CS{GPIO::PortD, GPIO::Pin4}) + }), + }), + initSPIHWVersion(V6C01, { + initSPIBus(SPI::Bus::SPI1, { + initSPIDevice(DRV_GYR_DEVTYPE_BMI055, SPI::CS{GPIO::PortC, GPIO::Pin14}, SPI::DRDY{GPIO::PortE, GPIO::Pin5}), + initSPIDevice(DRV_ACC_DEVTYPE_BMI055, SPI::CS{GPIO::PortC, GPIO::Pin15}, SPI::DRDY{GPIO::PortE, GPIO::Pin4}), + initSPIDevice(DRV_IMU_DEVTYPE_ICM42688P, SPI::CS{GPIO::PortC, GPIO::Pin13}, SPI::DRDY{GPIO::PortE, GPIO::Pin6}), + }, {GPIO::PortB, GPIO::Pin2}), + initSPIBus(SPI::Bus::SPI2, { + initSPIDevice(SPIDEV_FLASH(0), SPI::CS{GPIO::PortD, GPIO::Pin4}) + }), + }), + initSPIHWVersion(V6C21, { + initSPIBus(SPI::Bus::SPI1, { + initSPIDevice(DRV_GYR_DEVTYPE_BMI055, SPI::CS{GPIO::PortC, GPIO::Pin14}, SPI::DRDY{GPIO::PortE, GPIO::Pin5}), + initSPIDevice(DRV_ACC_DEVTYPE_BMI055, SPI::CS{GPIO::PortC, GPIO::Pin15}, SPI::DRDY{GPIO::PortE, GPIO::Pin4}), + initSPIDevice(DRV_IMU_DEVTYPE_ICM42688P, SPI::CS{GPIO::PortC, GPIO::Pin13}, SPI::DRDY{GPIO::PortE, GPIO::Pin6}), + }, {GPIO::PortB, GPIO::Pin2}), + initSPIBus(SPI::Bus::SPI2, { + initSPIDevice(SPIDEV_FLASH(0), SPI::CS{GPIO::PortD, GPIO::Pin4}) + }), + }), +}; + +static constexpr bool unused = validateSPIConfig(px4_spi_buses_all_hw); diff --git a/boards/px4/fts-can/src/timer_config.cpp b/boards/px4/fts-can/src/timer_config.cpp new file mode 100644 index 0000000..e26a8c5 --- /dev/null +++ b/boards/px4/fts-can/src/timer_config.cpp @@ -0,0 +1,73 @@ +/**************************************************************************** + * + * Copyright (C) 2012 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 + +/* Timer allocation + * + * TIM1_CH1 T FMU_CH1 + * TIM1_CH2 T FMU_CH2 + * TIM1_CH3 T FMU_CH3 + * TIM1_CH4 T FMU_CH4 + * + * TIM4_CH3 T FMU_CH5 + * TIM4_CH4 T FMU_CH6 + * + * TIM5_CH1 T FMU_CH7 + * TIM5_CH2 T FMU_CH8 + * + * TIM17_CH1 T HEATER > PWM OUT or GPIO + * + * TIM3_CH3 T BUZZER_1 - Driven by other driver + */ + +constexpr io_timers_t io_timers[MAX_IO_TIMERS] = { + initIOTimer(Timer::Timer1, DMA{DMA::Index1}), + initIOTimer(Timer::Timer4, DMA{DMA::Index1}), + initIOTimer(Timer::Timer5), + initIOTimer(Timer::Timer17), +}; + +constexpr timer_io_channels_t timer_io_channels[MAX_TIMER_IO_CHANNELS] = { + initIOTimerChannel(io_timers, {Timer::Timer1, Timer::Channel1}, {GPIO::PortA, GPIO::Pin8}), + initIOTimerChannel(io_timers, {Timer::Timer1, Timer::Channel2}, {GPIO::PortE, GPIO::Pin11}), + initIOTimerChannel(io_timers, {Timer::Timer1, Timer::Channel3}, {GPIO::PortE, GPIO::Pin13}), + initIOTimerChannel(io_timers, {Timer::Timer1, Timer::Channel4}, {GPIO::PortE, GPIO::Pin14}), + initIOTimerChannel(io_timers, {Timer::Timer4, Timer::Channel3}, {GPIO::PortD, GPIO::Pin14}), + initIOTimerChannel(io_timers, {Timer::Timer4, Timer::Channel4}, {GPIO::PortD, GPIO::Pin15}), + initIOTimerChannel(io_timers, {Timer::Timer5, Timer::Channel1}, {GPIO::PortA, GPIO::Pin0}), + initIOTimerChannel(io_timers, {Timer::Timer5, Timer::Channel2}, {GPIO::PortA, GPIO::Pin1}), +}; + +constexpr io_timers_channel_mapping_t io_timers_channel_mapping = + initIOTimerChannelMapping(io_timers, timer_io_channels); diff --git a/boards/px4/fts-can/src/usb.c b/boards/px4/fts-can/src/usb.c new file mode 100644 index 0000000..6d42476 --- /dev/null +++ b/boards/px4/fts-can/src/usb.c @@ -0,0 +1,105 @@ +/**************************************************************************** + * + * Copyright (C) 2016 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 px4fmu_usb.c + * + * Board-specific USB functions. + */ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include "board_config.h" + +/************************************************************************************ + * Definitions + ************************************************************************************/ + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_usbinitialize + * + * Description: + * Called to setup USB-related GPIO pins for the PX4FMU board. + * + ************************************************************************************/ + +__EXPORT void stm32_usbinitialize(void) +{ + /* The OTG FS has an internal soft pull-up */ + + /* Configure the OTG FS VBUS sensing GPIO, Power On, and Overcurrent GPIOs */ + +#ifdef CONFIG_STM32H7_OTGFS + stm32_configgpio(GPIO_OTGFS_VBUS); +#endif +} + +/************************************************************************************ + * 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/build.sh b/build.sh index ba4ed28..a61da03 100755 --- a/build.sh +++ b/build.sh @@ -3,5 +3,6 @@ rm -rf build/ git submodule update --recursive #make px4_fmu-v6x_default -make px4_fmu-v6c_default -#make px4_fmu-v6c_bootloader \ No newline at end of file +#make px4_fmu-v6c_default +#make px4_fmu-v6c_bootloader +make px4_fts-can \ No newline at end of file diff --git a/stflash.sh b/stflash.sh new file mode 100755 index 0000000..4d8c783 --- /dev/null +++ b/stflash.sh @@ -0,0 +1,3 @@ +#!/bin/bash -xe + +st-flash \ No newline at end of file diff --git a/upload.sh b/upload.sh index c39d3cd..4d51965 100755 --- a/upload.sh +++ b/upload.sh @@ -2,4 +2,4 @@ rm -rf build/ git submodule update --recursive -make -j${nproc} px4_fmu-v6x_default upload \ No newline at end of file +make -j${nproc} px4_fts-can upload \ No newline at end of file