From 4d1c65d7224a6b7b5c10f40cda992dfc7e39ed78 Mon Sep 17 00:00:00 2001 From: Alex Klimaj Date: Wed, 30 Oct 2024 09:35:35 -0600 Subject: [PATCH] boards: new ARK FPV FC (#23830) * add new payload power switch (RC_MAP_PAY_SW) --- .ci/Jenkinsfile-compile | 2 + .vscode/cmake-variants.yaml | 10 + Makefile | 1 + boards/ark/fpv/bootloader.px4board | 3 + boards/ark/fpv/default.px4board | 73 +++ boards/ark/fpv/extras/ark_fpv_bootloader.bin | Bin 0 -> 46260 bytes boards/ark/fpv/firmware.prototype | 13 + boards/ark/fpv/init/rc.board_defaults | 37 ++ boards/ark/fpv/init/rc.board_sensors | 18 + boards/ark/fpv/nuttx-config/Kconfig | 17 + .../ark/fpv/nuttx-config/bootloader/defconfig | 95 ++++ boards/ark/fpv/nuttx-config/include/board.h | 507 ++++++++++++++++++ .../fpv/nuttx-config/include/board_dma_map.h | 108 ++++ boards/ark/fpv/nuttx-config/nsh/defconfig | 279 ++++++++++ .../nuttx-config/scripts/bootloader_script.ld | 215 ++++++++ boards/ark/fpv/nuttx-config/scripts/script.ld | 229 ++++++++ boards/ark/fpv/src/CMakeLists.txt | 77 +++ boards/ark/fpv/src/board_config.h | 391 ++++++++++++++ boards/ark/fpv/src/bootloader_main.c | 85 +++ boards/ark/fpv/src/can.c | 140 +++++ boards/ark/fpv/src/hw_config.h | 129 +++++ boards/ark/fpv/src/i2c.cpp | 40 ++ boards/ark/fpv/src/init.c | 293 ++++++++++ boards/ark/fpv/src/led.c | 234 ++++++++ boards/ark/fpv/src/mtd.cpp | 55 ++ boards/ark/fpv/src/sdio.c | 177 ++++++ boards/ark/fpv/src/spi.cpp | 57 ++ boards/ark/fpv/src/spix_sync.c | 309 +++++++++++ boards/ark/fpv/src/spix_sync.h | 42 ++ boards/ark/fpv/src/timer_config.cpp | 86 +++ boards/ark/fpv/src/usb.c | 105 ++++ msg/ManualControlSwitches.msg | 2 + msg/RcChannels.msg | 3 +- msg/SystemPower.msg | 2 + .../px4_platform_common/board_common.h | 7 + src/drivers/adc/board_adc/ADC.cpp | 16 + src/modules/manual_control/ManualControl.cpp | 13 + src/modules/rc_update/params.c | 45 ++ src/modules/rc_update/rc_update.cpp | 8 + src/modules/rc_update/rc_update.h | 3 + 40 files changed, 3925 insertions(+), 1 deletion(-) create mode 100644 boards/ark/fpv/bootloader.px4board create mode 100644 boards/ark/fpv/default.px4board create mode 100755 boards/ark/fpv/extras/ark_fpv_bootloader.bin create mode 100644 boards/ark/fpv/firmware.prototype create mode 100644 boards/ark/fpv/init/rc.board_defaults create mode 100644 boards/ark/fpv/init/rc.board_sensors create mode 100644 boards/ark/fpv/nuttx-config/Kconfig create mode 100644 boards/ark/fpv/nuttx-config/bootloader/defconfig create mode 100644 boards/ark/fpv/nuttx-config/include/board.h create mode 100644 boards/ark/fpv/nuttx-config/include/board_dma_map.h create mode 100644 boards/ark/fpv/nuttx-config/nsh/defconfig create mode 100644 boards/ark/fpv/nuttx-config/scripts/bootloader_script.ld create mode 100644 boards/ark/fpv/nuttx-config/scripts/script.ld create mode 100644 boards/ark/fpv/src/CMakeLists.txt create mode 100644 boards/ark/fpv/src/board_config.h create mode 100644 boards/ark/fpv/src/bootloader_main.c create mode 100644 boards/ark/fpv/src/can.c create mode 100644 boards/ark/fpv/src/hw_config.h create mode 100644 boards/ark/fpv/src/i2c.cpp create mode 100644 boards/ark/fpv/src/init.c create mode 100644 boards/ark/fpv/src/led.c create mode 100644 boards/ark/fpv/src/mtd.cpp create mode 100644 boards/ark/fpv/src/sdio.c create mode 100644 boards/ark/fpv/src/spi.cpp create mode 100644 boards/ark/fpv/src/spix_sync.c create mode 100644 boards/ark/fpv/src/spix_sync.h create mode 100644 boards/ark/fpv/src/timer_config.cpp create mode 100644 boards/ark/fpv/src/usb.c diff --git a/.ci/Jenkinsfile-compile b/.ci/Jenkinsfile-compile index e8a97b48e6..cad2b8df3a 100644 --- a/.ci/Jenkinsfile-compile +++ b/.ci/Jenkinsfile-compile @@ -47,6 +47,8 @@ pipeline { "ark_cannode_default", "ark_fmu-v6x_bootloader", "ark_fmu-v6x_default", + "ark_fpv_bootloader", + "ark_fpv_default", "ark_pi6x_bootloader", "ark_pi6x_default", "atl_mantis-edu_default", diff --git a/.vscode/cmake-variants.yaml b/.vscode/cmake-variants.yaml index 02d4b3f36e..96331bb145 100644 --- a/.vscode/cmake-variants.yaml +++ b/.vscode/cmake-variants.yaml @@ -186,6 +186,16 @@ CONFIG: buildType: MinSizeRel settings: CONFIG: ark_fmu-v6x_default + ark_fpv_bootloader: + short: ark_fpv_bootloader + buildType: MinSizeRel + settings: + CONFIG: ark_fpv_bootloader + ark_fpv_default: + short: ark_fpv_default + buildType: MinSizeRel + settings: + CONFIG: ark_fpv_default ark_pi6x_bootloader: short: ark_pi6x_bootloader buildType: MinSizeRel diff --git a/Makefile b/Makefile index 5ef162fc3a..fa055bf13d 100644 --- a/Makefile +++ b/Makefile @@ -326,6 +326,7 @@ px4io_update: bootloaders_update: \ 3dr_ctrl-zero-h7-oem-revg_bootloader \ ark_fmu-v6x_bootloader \ + ark_fpv_bootloader \ ark_pi6x_bootloader \ cuav_nora_bootloader \ cuav_x7pro_bootloader \ diff --git a/boards/ark/fpv/bootloader.px4board b/boards/ark/fpv/bootloader.px4board new file mode 100644 index 0000000000..19b6e662be --- /dev/null +++ b/boards/ark/fpv/bootloader.px4board @@ -0,0 +1,3 @@ +CONFIG_BOARD_TOOLCHAIN="arm-none-eabi" +CONFIG_BOARD_ARCHITECTURE="cortex-m7" +CONFIG_BOARD_ROMFSROOT="" diff --git a/boards/ark/fpv/default.px4board b/boards/ark/fpv/default.px4board new file mode 100644 index 0000000000..af69fd3691 --- /dev/null +++ b/boards/ark/fpv/default.px4board @@ -0,0 +1,73 @@ +CONFIG_BOARD_TOOLCHAIN="arm-none-eabi" +CONFIG_BOARD_ARCHITECTURE="cortex-m7" +CONFIG_BOARD_SERIAL_GPS1="/dev/ttyS0" +CONFIG_BOARD_SERIAL_TEL3="/dev/ttyS1" +CONFIG_BOARD_SERIAL_TEL4="/dev/ttyS3" +CONFIG_BOARD_SERIAL_TEL2="/dev/ttyS4" +CONFIG_BOARD_SERIAL_RC="/dev/ttyS5" +CONFIG_BOARD_SERIAL_TEL1="/dev/ttyS6" +CONFIG_DRIVERS_ADC_BOARD_ADC=y +CONFIG_DRIVERS_BAROMETER_BMP388=y +CONFIG_DRIVERS_CDCACM_AUTOSTART=y +CONFIG_COMMON_DIFFERENTIAL_PRESSURE=y +CONFIG_COMMON_DISTANCE_SENSOR=y +CONFIG_DRIVERS_DISTANCE_SENSOR_VL53L0X=y +CONFIG_DRIVERS_DSHOT=y +CONFIG_DRIVERS_GPS=y +CONFIG_DRIVERS_HEATER=y +CONFIG_DRIVERS_IMU_INVENSENSE_IIM42653=y +CONFIG_COMMON_LIGHT=y +CONFIG_COMMON_MAGNETOMETER=y +CONFIG_DRIVERS_PWM_OUT=y +CONFIG_COMMON_RC=y +CONFIG_DRIVERS_UAVCAN=y +CONFIG_BOARD_UAVCAN_TIMER_OVERRIDE=2 +CONFIG_MODULES_AIRSPEED_SELECTOR=y +CONFIG_MODULES_BATTERY_STATUS=y +CONFIG_MODULES_COMMANDER=y +CONFIG_MODULES_CONTROL_ALLOCATOR=y +CONFIG_MODULES_DATAMAN=y +CONFIG_MODULES_EKF2=y +CONFIG_MODULES_ESC_BATTERY=y +CONFIG_MODULES_EVENTS=y +CONFIG_MODULES_FLIGHT_MODE_MANAGER=y +CONFIG_MODULES_GYRO_CALIBRATION=y +CONFIG_MODULES_GYRO_FFT=y +CONFIG_MODULES_LAND_DETECTOR=y +CONFIG_MODULES_LANDING_TARGET_ESTIMATOR=y +CONFIG_MODULES_LOAD_MON=y +CONFIG_MODULES_LOGGER=y +CONFIG_MODULES_MAG_BIAS_ESTIMATOR=y +CONFIG_MODULES_MANUAL_CONTROL=y +CONFIG_MODULES_MAVLINK=y +CONFIG_MAVLINK_DIALECT="development" +CONFIG_MODULES_MC_ATT_CONTROL=y +CONFIG_MODULES_MC_AUTOTUNE_ATTITUDE_CONTROL=y +CONFIG_MODULES_MC_HOVER_THRUST_ESTIMATOR=y +CONFIG_MODULES_MC_POS_CONTROL=y +CONFIG_MODULES_MC_RATE_CONTROL=y +CONFIG_MODULES_NAVIGATOR=y +CONFIG_MODULES_RC_UPDATE=y +CONFIG_MODULES_SENSORS=y +CONFIG_MODULES_UXRCE_DDS_CLIENT=y +CONFIG_SYSTEMCMDS_ACTUATOR_TEST=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_SD_STRESS=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/ark/fpv/extras/ark_fpv_bootloader.bin b/boards/ark/fpv/extras/ark_fpv_bootloader.bin new file mode 100755 index 0000000000000000000000000000000000000000..73a4ffe8fb7b742cdaa5749ee81cd8db5b342e6a GIT binary patch literal 46260 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 H-$?%gy4bhN literal 0 HcmV?d00001 diff --git a/boards/ark/fpv/firmware.prototype b/boards/ark/fpv/firmware.prototype new file mode 100644 index 0000000000..f75702a85e --- /dev/null +++ b/boards/ark/fpv/firmware.prototype @@ -0,0 +1,13 @@ +{ + "board_id": 59, + "magic": "ARKFPVFWv1", + "description": "Firmware for the ARKFPV board", + "image": "", + "build_time": 0, + "summary": "ARKFPV", + "version": "0.1", + "image_size": 0, + "image_maxsize": 1835008, + "git_identity": "", + "board_revision": 0 +} diff --git a/boards/ark/fpv/init/rc.board_defaults b/boards/ark/fpv/init/rc.board_defaults new file mode 100644 index 0000000000..5605f60d02 --- /dev/null +++ b/boards/ark/fpv/init/rc.board_defaults @@ -0,0 +1,37 @@ +#!/bin/sh +# +# board specific defaults +#------------------------------------------------------------------------------ + +# transision from params file to flash-based params (2022-08) +if [ -f $PARAM_FILE ] +then + param load $PARAM_FILE + param save + # create a backup + mv $PARAM_FILE ${PARAM_FILE}.bak + reboot +fi + +# TODO: Tune the following parameters +param set-default SENS_EN_THERMAL 1 +param set-default SENS_IMU_TEMP 10.0 +#param set-default SENS_IMU_TEMP_FF 0.0 +#param set-default SENS_IMU_TEMP_I 0.025 +#param set-default SENS_IMU_TEMP_P 1.0 + +if ver hwtypecmp ARKFPV000 +then + param set-default SENS_TEMP_ID 3014666 +fi + +param set-default BAT1_V_DIV 21.0 + +param set-default RC_CRSF_PRT_CFG 300 +param set-default RC_SBUS_PRT_CFG 0 + +param set-default IMU_GYRO_DNF_EN 3 + +# Single IMU +param set-default EKF2_MULTI_IMU 0 +param set-default SENS_IMU_MODE 1 diff --git a/boards/ark/fpv/init/rc.board_sensors b/boards/ark/fpv/init/rc.board_sensors new file mode 100644 index 0000000000..896b9ffd7d --- /dev/null +++ b/boards/ark/fpv/init/rc.board_sensors @@ -0,0 +1,18 @@ +#!/bin/sh +# +# ARKFPV specific board sensors init +#------------------------------------------------------------------------------ + +board_adc start + +if ver hwtypecmp ARKFPV000 +then + # Internal SPI bus IIM42653 + iim42653 -R 14 -s -b 1 start +fi + +# Internal magnetometer on I2C +iis2mdc -R 0 -I -b 4 start + +# Internal Baro on I2C +bmp388 -I -b 2 start diff --git a/boards/ark/fpv/nuttx-config/Kconfig b/boards/ark/fpv/nuttx-config/Kconfig new file mode 100644 index 0000000000..bb33d3cfda --- /dev/null +++ b/boards/ark/fpv/nuttx-config/Kconfig @@ -0,0 +1,17 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# +config BOARD_HAS_PROBES + bool "Board provides GPIO or other Hardware for signaling to timing analyze." + default y + ---help--- + This board provides GPIO FMU-CH1-5, CAP1-6 as PROBE_1-11 to provide timing signals from selected drivers. + +config BOARD_USE_PROBES + bool "Enable the use the board provided FMU-CH1-5, CAP1-6 as PROBE_1-11" + default n + depends on BOARD_HAS_PROBES + + ---help--- + Select to use GPIO FMU-CH1-5, CAP1-6 to provide timing signals from selected drivers. diff --git a/boards/ark/fpv/nuttx-config/bootloader/defconfig b/boards/ark/fpv/nuttx-config/bootloader/defconfig new file mode 100644 index 0000000000..70c6114fea --- /dev/null +++ b/boards/ark/fpv/nuttx-config/bootloader/defconfig @@ -0,0 +1,95 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_DEV_CONSOLE is not set +# CONFIG_DISABLE_PSEUDOFS_OPERATIONS is not set +# CONFIG_DISABLE_PTHREAD is not set +# CONFIG_SPI_EXCHANGE is not set +# CONFIG_STM32H7_SYSCFG is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD_CUSTOM=y +CONFIG_ARCH_BOARD_CUSTOM_DIR="../../../../boards/ark/fpv/nuttx-config" +CONFIG_ARCH_BOARD_CUSTOM_DIR_RELPATH=y +CONFIG_ARCH_BOARD_CUSTOM_NAME="ark" +CONFIG_ARCH_CHIP="stm32h7" +CONFIG_ARCH_CHIP_STM32H743II=y +CONFIG_ARCH_CHIP_STM32H7=y +CONFIG_ARCH_INTERRUPTSTACK=768 +CONFIG_ARMV7M_BASEPRI_WAR=y +CONFIG_ARMV7M_ICACHE=y +CONFIG_ARMV7M_MEMCPY=y +CONFIG_ARMV7M_USEBASEPRI=y +CONFIG_BOARDCTL=y +CONFIG_BOARDCTL_RESET=y +CONFIG_BOARD_ASSERT_RESET_VALUE=0 +CONFIG_BOARD_INITTHREAD_PRIORITY=254 +CONFIG_BOARD_LATE_INITIALIZE=y +CONFIG_BOARD_LOOPSPERMSEC=95150 +CONFIG_BOARD_RESET_ON_ASSERT=2 +CONFIG_CDCACM=y +CONFIG_CDCACM_IFLOWCONTROL=y +CONFIG_CDCACM_PRODUCTID=0x003B +CONFIG_CDCACM_PRODUCTSTR="ARK BL FPV.x" +CONFIG_CDCACM_RXBUFSIZE=600 +CONFIG_CDCACM_TXBUFSIZE=12000 +CONFIG_CDCACM_VENDORID=0x3185 +CONFIG_CDCACM_VENDORSTR="ARK" +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEBUG_TCBINFO=y +CONFIG_DEFAULT_SMALL=y +CONFIG_EXPERIMENTAL=y +CONFIG_FDCLONE_DISABLE=y +CONFIG_FDCLONE_STDIO=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_IDLETHREAD_STACKSIZE=750 +CONFIG_INIT_ENTRYPOINT="bootloader_main" +CONFIG_INIT_STACKSIZE=3194 +CONFIG_LIBC_FLOATINGPOINT=y +CONFIG_LIBC_LONG_LONG=y +CONFIG_LIBC_STRERROR=y +CONFIG_MEMSET_64BIT=y +CONFIG_MEMSET_OPTSPEED=y +CONFIG_PREALLOC_TIMERS=50 +CONFIG_PTHREAD_MUTEX_ROBUST=y +CONFIG_PTHREAD_STACK_MIN=512 +CONFIG_RAM_SIZE=245760 +CONFIG_RAM_START=0x20010000 +CONFIG_RAW_BINARY=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_SPI=y +CONFIG_STACK_COLORATION=y +CONFIG_START_DAY=30 +CONFIG_START_MONTH=11 +CONFIG_STDIO_BUFFER_SIZE=32 +CONFIG_STM32H7_BKPSRAM=y +CONFIG_STM32H7_DMA1=y +CONFIG_STM32H7_DMA2=y +CONFIG_STM32H7_OTGFS=y +CONFIG_STM32H7_PROGMEM=y +CONFIG_STM32H7_SERIAL_DISABLE_REORDERING=y +CONFIG_STM32H7_TIM1=y +CONFIG_STM32H7_UART7=y +CONFIG_SYSTEMTICK_HOOK=y +CONFIG_SYSTEM_CDCACM=y +CONFIG_TASK_NAME_SIZE=24 +CONFIG_TTY_SIGINT=y +CONFIG_TTY_SIGINT_CHAR=0x03 +CONFIG_TTY_SIGTSTP=y +CONFIG_UART7_RXBUFSIZE=512 +CONFIG_UART7_RXDMA=y +CONFIG_UART7_TXBUFSIZE=512 +CONFIG_UART7_TXDMA=y +CONFIG_USBDEV=y +CONFIG_USBDEV_BUSPOWERED=y +CONFIG_USBDEV_MAXPOWER=500 +CONFIG_USEC_PER_TICK=1000 diff --git a/boards/ark/fpv/nuttx-config/include/board.h b/boards/ark/fpv/nuttx-config/include/board.h new file mode 100644 index 0000000000..bfa2887b66 --- /dev/null +++ b/boards/ark/fpv/nuttx-config/include/board.h @@ -0,0 +1,507 @@ +/************************************************************************************ + * nuttx-configs/px4_fmu-v6x/include/board.h + * + * Copyright (C) 2016-2024 Gregory Nutt. All rights reserved. + * Authors: David Sidrane + * + * 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_FMU_V6X_INCLUDE_BOARD_H +#define __NUTTX_CONFIG_PX4_FMU_V6X_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 px4_fmu-v6X 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_USEHSE + +#define STM32_PLLCFG_PLLSRC RCC_PLLCKSELR_PLLSRC_HSE + +/* PLL1, wide 4 - 8 MHz input, enable DIVP, DIVQ, DIVR + * + * PLL1_VCO = (16,000,000 / 1) * 40 = 640 MHz + * + * PLL1P = PLL1_VCO/2 = 640 MHz / 2 = 320 MHz + * PLL1Q = PLL1_VCO/4 = 640 MHz / 4 = 160 MHz + * PLL1R = PLL1_VCO/8 = 640 MHz / 8 = 80 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(40) +#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) * 40) +#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 = 160 + */ + +#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 (80 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 (80 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 (80 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 (80 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_ADCSRC 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 ARKV6X 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-v6x 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_3 /* PB7 */ +#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_UART4_RX GPIO_UART4_RX_6 /* PH14 */ +#define GPIO_UART4_TX GPIO_UART4_TX_6 /* PH13 */ + +#define GPIO_UART5_RX GPIO_UART5_RX_3 /* PD2 */ +#define GPIO_UART5_TX GPIO_UART5_TX_3 /* PC12 */ +// GPIO_UART5_RTS No remap /* PC8 */ +//#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_4 /* PF6 */ +#define GPIO_UART7_TX GPIO_UART7_TX_3 /* PE8 */ +#define GPIO_UART7_RTS GPIO_UART7_RTS_2 /* PF8 */ +#define GPIO_UART7_CTS (GPIO_UART7_CTS_1 | GPIO_PULLDOWN) /* PE10 */ + + +/* CAN + * + * CAN1 is routed to transceiver. + */ +#define GPIO_CAN1_RX GPIO_CAN1_RX_3 /* PD0 */ +#define GPIO_CAN1_TX GPIO_CAN1_TX_3 /* PD1 */ + +/* SPI + * SPI1 is sensors1 + * SPI2 is sensors2 + * SPI3 is sensors3 + * SPI4 is Not Used + * SPI5 is Not Used + * SPI6 is EXTERNAL1 + * + */ + +#define ADJ_SLEW_RATE(p) (((p) & ~GPIO_SPEED_MASK) | (GPIO_SPEED_2MHz)) + +#define GPIO_SPI1_MISO GPIO_SPI1_MISO_3 /* PG9 */ +#define GPIO_SPI1_MOSI GPIO_SPI1_MOSI_2 /* PB5 */ +#define GPIO_SPI1_SCK ADJ_SLEW_RATE(GPIO_SPI1_SCK_1) /* PA5 */ + +#define GPIO_SPI6_MISO GPIO_SPI6_MISO_2 /* PA6 */ +#define GPIO_SPI6_MOSI GPIO_SPI6_MOSI_1 /* PG14 */ +#define GPIO_SPI6_SCK ADJ_SLEW_RATE(GPIO_SPI6_SCK_3) /* PB3 */ + +/* 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_2 /* PB9 */ + +#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_PIN9) + +#define GPIO_I2C2_SCL GPIO_I2C2_SCL_2 /* PF1 */ +#define GPIO_I2C2_SDA GPIO_I2C2_SDA_2 /* PF0 */ + +#define GPIO_I2C2_SCL_GPIO (GPIO_OUTPUT | GPIO_OPENDRAIN |GPIO_SPEED_50MHz | GPIO_OUTPUT_SET | GPIO_PORTF | GPIO_PIN1) +#define GPIO_I2C2_SDA_GPIO (GPIO_OUTPUT | GPIO_OPENDRAIN |GPIO_SPEED_50MHz | GPIO_OUTPUT_SET | GPIO_PORTF | GPIO_PIN0) + +#define GPIO_I2C4_SCL GPIO_I2C4_SCL_2 /* PF14 */ +#define GPIO_I2C4_SDA GPIO_I2C4_SDA_2 /* PF15 */ + +#define GPIO_I2C4_SCL_GPIO (GPIO_OUTPUT | GPIO_OPENDRAIN | GPIO_SPEED_50MHz | GPIO_OUTPUT_SET | GPIO_PORTF | GPIO_PIN14) +#define GPIO_I2C4_SDA_GPIO (GPIO_OUTPUT | GPIO_OPENDRAIN | GPIO_SPEED_50MHz | GPIO_OUTPUT_SET | GPIO_PORTF | GPIO_PIN15) + +/* SDMMC2 + * + * VDD 3.3 + * GND + * SDMMC2_CK PD6 + * SDMMC2_CMD PD7 + * SDMMC2_D0 PB14 + * SDMMC2_D1 PB15 + * SDMMC2_D2 PG11 + * 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_1 /* PG11 */ +// 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_PORTI|GPIO_PIN0) /* PI0 AUX1 */ +# define PROBE_2 (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTH|GPIO_PIN12) /* PH12 AUX2 */ +# define PROBE_3 (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTH|GPIO_PIN11) /* PH11 AUX3 */ +# define PROBE_4 (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTH|GPIO_PIN10) /* PH10 AUX4 */ +# define PROBE_5 (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTD|GPIO_PIN13) /* PD13 AUX5 */ +# define PROBE_6 (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTD|GPIO_PIN14) /* PD14 AUX6 */ +# define PROBE_7 (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTH|GPIO_PIN6) /* PH6 AUX7 */ +# define PROBE_8 (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTH|GPIO_PIN9) /* PH9 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); } \ + if ((mask)& PROBE_N(9)) { stm32_configgpio(PROBE_9); } \ + } 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_V6X_INCLUDE_BOARD_H */ diff --git a/boards/ark/fpv/nuttx-config/include/board_dma_map.h b/boards/ark/fpv/nuttx-config/include/board_dma_map.h new file mode 100644 index 0000000000..adbaaffc20 --- /dev/null +++ b/boards/ark/fpv/nuttx-config/include/board_dma_map.h @@ -0,0 +1,108 @@ +/**************************************************************************** + * + * Copyright (c) 2024 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 + +// Timer 4 Channel 1 /* DMA1:29 TIM4CH1 */ + +#define DMAMAP_SPI1_RX DMAMAP_DMA12_SPI1RX_0 /* 1 DMA1:37 IIM-42653 */ +#define DMAMAP_SPI1_TX DMAMAP_DMA12_SPI1TX_0 /* 2 DMA1:38 IIM-42653 */ + +//#define DMAMAP_SPI2_RX DMAMAP_DMA12_SPI2RX_0 /* 3 DMA1:39 ICM-42688-P */ +//#define DMAMAP_SPI2_TX DMAMAP_DMA12_SPI2TX_0 /* 4 DMA1:40 ICM-42688-P */ + +#define DMAMAP_USART1_RX DMAMAP_DMA12_USART1RX_0 /* DMA1:41 GPS1 */ +#define DMAMAP_USART1_TX DMAMAP_DMA12_USART1TX_0 /* DMA1:42 GPS1 */ + +//#define DMAMAP_USART3_RX DMAMAP_DMA12_USART3RX_0 /* DMA1:45 DEBUG */ +//#define DMAMAP_USART3_TX DMAMAP_DMA12_USART3TX_0 /* DMA1:46 DEBUG */ + +// Timer 8 Channel 1 /* DMA1:47 TIM8CH1 */ +// Timer 8 Channel 2 /* DMA1:48 TIM8CH2 */ +// Timer 8 Channel 3 /* DMA1:49 TIM8CH3 */ +// Timer 8 Channel 4 /* DMA1:50 TIM8CH4 */ + +// Timer 5 Channel 1 /* DMA1:55 TIM5CH1 */ +// Timer 5 Channel 2 /* DMA1:56 TIM5CH2 */ +// Timer 5 Channel 3 /* DMA1:57 TIM5CH3 */ +// Timer 5 Channel 4 /* DMA1:58 TIM5CH4 */ + +// #define DMAMAP_UART4_RX DMAMAP_DMA12_UART4RX_0 /* DMA1:63 UART4 */ +// #define DMAMAP_UART4_TX DMAMAP_DMA12_UART4TX_0 /* DMA1:64 UART4 */ + +#define DMAMAP_USART6_RX DMAMAP_DMA12_USART6RX_0 /* 5 DMA1:71 RC */ +// #define DMAMAP_USART6_TX DMAMAP_DMA12_USART6TX_0 /* 6 DMA1:72 RC */ + +// 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 + +// Timer 4 Channel 1 /* DMA2:29 TIM4CH1 */ + +#define DMAMAP_USART2_RX DMAMAP_DMA12_USART2RX_1 /* 3 DMA2:43 TELEM3 */ +#define DMAMAP_USART2_TX DMAMAP_DMA12_USART2TX_1 /* 4 DMA2:44 TELEM3 */ + +#define DMAMAP_USART3_RX DMAMAP_DMA12_USART3RX_1 /* 3 DMA2:45 DEBUG */ +#define DMAMAP_USART3_TX DMAMAP_DMA12_USART3TX_1 /* 4 DMA2:46 DEBUG */ + +// Timer 8 Channel 1 /* DMA2:47 TIM8CH1 */ +// Timer 8 Channel 2 /* DMA2:48 TIM8CH2 */ +// Timer 8 Channel 3 /* DMA2:49 TIM8CH3 */ +// Timer 8 Channel 4 /* DMA2:50 TIM8CH4 */ + +// Timer 5 Channel 1 /* DMA2:55 TIM5CH1 */ +// Timer 5 Channel 2 /* DMA2:56 TIM5CH2 */ +// Timer 5 Channel 3 /* DMA2:57 TIM5CH3 */ +// Timer 5 Channel 4 /* DMA2:58 TIM5CH4 */ + +//#define DMAMAP_SPI3_RX DMAMAP_DMA12_SPI3RX_1 /* 1 DMA2:61 BMI088 */ +//#define DMAMAP_SPI3_TX DMAMAP_DMA12_SPI3TX_1 /* 2 DMA2:62 BMI088 */ + +#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 */ + +// DMAMUX2 Using at most 8 Channels on BDMA -------- Assigned +// V + +#define DMAMAP_SPI6_RX DMAMAP_BDMA_SPI6_RX /* 1 BDMA:11 SPI J11 */ +#define DMAMAP_SPI6_TX DMAMAP_BDMA_SPI6_TX /* 2 BDMA:12 SPI J11 */ diff --git a/boards/ark/fpv/nuttx-config/nsh/defconfig b/boards/ark/fpv/nuttx-config/nsh/defconfig new file mode 100644 index 0000000000..9a213aca47 --- /dev/null +++ b/boards/ark/fpv/nuttx-config/nsh/defconfig @@ -0,0 +1,279 @@ +# +# 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_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_IFCONFIG is not set +# CONFIG_NSH_DISABLE_IFUPDOWN 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_TELNETD 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/ark/fpv/nuttx-config" +CONFIG_ARCH_BOARD_CUSTOM_DIR_RELPATH=y +CONFIG_ARCH_BOARD_CUSTOM_NAME="ark" +CONFIG_ARCH_CHIP="stm32h7" +CONFIG_ARCH_CHIP_STM32H743II=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=0x003B +CONFIG_CDCACM_PRODUCTSTR="ARK FPV.x" +CONFIG_CDCACM_RXBUFSIZE=600 +CONFIG_CDCACM_TXBUFSIZE=12000 +CONFIG_CDCACM_VENDORID=0x3185 +CONFIG_CDCACM_VENDORSTR="ARK" +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=3194 +CONFIG_LIBC_FLOATINGPOINT=y +CONFIG_LIBC_LONG_LONG=y +CONFIG_LIBC_MAX_EXITFUNS=1 +CONFIG_LIBC_STRERROR=y +CONFIG_MEMSET_64BIT=y +CONFIG_MEMSET_OPTSPEED=y +CONFIG_MMCSD=y +CONFIG_MMCSD_SDIO=y +CONFIG_MMCSD_SDIOWAIT_WRCOMPLETE=y +CONFIG_MM_REGIONS=4 +CONFIG_MTD=y +CONFIG_MTD_BYTE_WRITE=y +CONFIG_MTD_PARTITION=y +CONFIG_MTD_PROGMEM=y +CONFIG_MTD_RAMTRON=y +CONFIG_NAME_MAX=40 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_ARGCAT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_CMDPARMS=y +CONFIG_NSH_CROMFSETC=y +CONFIG_NSH_LINELEN=128 +CONFIG_NSH_MAXARGUMENTS=15 +CONFIG_NSH_NESTDEPTH=8 +CONFIG_NSH_QUOTE=y +CONFIG_NSH_ROMFSETC=y +CONFIG_NSH_ROMFSSECTSIZE=128 +CONFIG_NSH_STRERROR=y +CONFIG_NSH_VARS=y +CONFIG_OTG_ID_GPIO_DISABLE=y +CONFIG_PIPES=y +CONFIG_PREALLOC_TIMERS=50 +CONFIG_PRIORITY_INHERITANCE=y +CONFIG_PTHREAD_MUTEX_ROBUST=y +CONFIG_PTHREAD_STACK_MIN=512 +CONFIG_RAMTRON_EMULATE_PAGE_SHIFT=5 +CONFIG_RAMTRON_EMULATE_SECTOR_SHIFT=5 +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_SDMMC2_SDIO_PULLUP=y +CONFIG_SEM_PREALLOCHOLDERS=32 +CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS=y +CONFIG_SERIAL_TERMIOS=y +CONFIG_SIG_DEFAULT=y +CONFIG_SIG_SIGALRM_ACTION=y +CONFIG_SIG_SIGUSR1_ACTION=y +CONFIG_SIG_SIGUSR2_ACTION=y +CONFIG_SIG_SIGWORK=4 +CONFIG_STACK_COLORATION=y +CONFIG_START_DAY=30 +CONFIG_START_MONTH=11 +CONFIG_STDIO_BUFFER_SIZE=256 +CONFIG_STM32H7_ADC1=y +CONFIG_STM32H7_ADC3=y +CONFIG_STM32H7_BBSRAM=y +CONFIG_STM32H7_BBSRAM_FILES=5 +CONFIG_STM32H7_BDMA=y +CONFIG_STM32H7_BKPSRAM=y +CONFIG_STM32H7_DMA1=y +CONFIG_STM32H7_DMA2=y +CONFIG_STM32H7_DMACAPABLE=y +CONFIG_STM32H7_FLASH_OVERRIDE_I=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_AUTO_LSECLOCK_START_DRV_CAPABILITY=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_SPI6=y +CONFIG_STM32H7_SPI6_DMA=y +CONFIG_STM32H7_SPI6_DMA_BUFFER=1024 +CONFIG_STM32H7_TIM1=y +CONFIG_STM32H7_TIM2=y +CONFIG_STM32H7_TIM3=y +CONFIG_STM32H7_TIM4=y +CONFIG_STM32H7_TIM5=y +CONFIG_STM32H7_TIM8=y +CONFIG_STM32H7_TIM12=y +CONFIG_STM32H7_UART4=y +CONFIG_STM32H7_UART5=y +CONFIG_STM32H7_UART7=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_UART4_BAUD=57600 +CONFIG_UART4_RXBUFSIZE=600 +CONFIG_UART4_TXBUFSIZE=1500 +CONFIG_UART5_IFLOWCONTROL=y +CONFIG_UART5_OFLOWCONTROL=y +CONFIG_UART5_RXDMA=y +CONFIG_UART5_RXBUFSIZE=600 +CONFIG_UART5_TXBUFSIZE=10000 +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_USART1_BAUD=57600 +CONFIG_USART1_RXDMA=y +CONFIG_USART1_TXDMA=y +CONFIG_USART1_RXBUFSIZE=600 +CONFIG_USART1_TXBUFSIZE=1500 +CONFIG_USART2_BAUD=57600 +CONFIG_USART2_RXDMA=y +CONFIG_USART2_TXDMA=y +CONFIG_USART2_RXBUFSIZE=600 +CONFIG_USART2_TXBUFSIZE=1500 +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_RXDMA=y +CONFIG_USART6_RXBUFSIZE=600 +CONFIG_USART6_TXBUFSIZE=1500 +CONFIG_USART6_RXBUFSIZE=600 +CONFIG_USART6_TXBUFSIZE=1500 +CONFIG_USBDEV=y +CONFIG_USBDEV_BUSPOWERED=y +CONFIG_USBDEV_MAXPOWER=500 +CONFIG_USEC_PER_TICK=1000 +CONFIG_WATCHDOG=y diff --git a/boards/ark/fpv/nuttx-config/scripts/bootloader_script.ld b/boards/ark/fpv/nuttx-config/scripts/bootloader_script.ld new file mode 100644 index 0000000000..b0515c91c7 --- /dev/null +++ b/boards/ark/fpv/nuttx-config/scripts/bootloader_script.ld @@ -0,0 +1,215 @@ +/**************************************************************************** + * scripts/script.ld + * + * Copyright (C) 2016, 2024 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 ARKV6X uses an STM32H743II 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 ARKV6X 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/ark/fpv/nuttx-config/scripts/script.ld b/boards/ark/fpv/nuttx-config/scripts/script.ld new file mode 100644 index 0000000000..8e6dca3e49 --- /dev/null +++ b/boards/ark/fpv/nuttx-config/scripts/script.ld @@ -0,0 +1,229 @@ +/**************************************************************************** + * scripts/script.ld + * + * Copyright (C) 2016, 2024 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 ARKV6X uses an STM32H743II 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 ARKV6X 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 = 1792K /* params in last sector */ + + 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/ark/fpv/src/CMakeLists.txt b/boards/ark/fpv/src/CMakeLists.txt new file mode 100644 index 0000000000..78b8222f19 --- /dev/null +++ b/boards/ark/fpv/src/CMakeLists.txt @@ -0,0 +1,77 @@ +############################################################################ +# +# 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 + sdio.c + spi.cpp + spix_sync.c + spix_sync.h + timer_config.cpp + usb.c + ) + add_dependencies(drivers_board arch_board_hw_info) + + target_link_libraries(drivers_board + PRIVATE + arch_io_pins + arch_spi + arch_board_hw_info + drivers__led # drv_led_start + nuttx_arch # sdio + nuttx_drivers # sdio + px4_layer + ) +endif() diff --git a/boards/ark/fpv/src/board_config.h b/boards/ark/fpv/src/board_config.h new file mode 100644 index 0000000000..26bf670ac8 --- /dev/null +++ b/boards/ark/fpv/src/board_config.h @@ -0,0 +1,391 @@ +/**************************************************************************** + * + * Copyright (c) 2016-2024 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 + * + * ARK FPV internal definitions + */ + +#pragma once + +/**************************************************************************************************** + * Included Files + ****************************************************************************************************/ + +#include +#include +#include + + +#include + +/**************************************************************************************************** + * Definitions + ****************************************************************************************************/ + +#undef TRACE_PINS + +/* Configuration ************************************************************************************/ + +# define BOARD_HAS_USB_VALID 1 +# define BOARD_HAS_NBAT_V 1 +# define BOARD_HAS_NBAT_I 1 + +/* PX4FMU GPIOs ***********************************************************************************/ + +/* Trace Clock and D0-D3 are available on the trace connector + * + * TRACECLK PE2 - Dedicated - Trace Connector Pin 1 + * TRACED0 PE3 - nLED_RED - Trace Connector Pin 3 + * TRACED1 PE4 - nLED_GREEN - Trace Connector Pin 5 + * TRACED2 PE5 - nLED_BLUE - Trace Connector Pin 7 + * TRACED3 PE6 - nARMED - Trace Connector Pin 8 + + */ + +/* LEDs are driven with push open drain to support Anode to 5V or 3.3V or used as TRACE0-2 */ + +#if !defined(TRACE_PINS) +# define GPIO_nLED_RED /* PE3 */ (GPIO_OUTPUT|GPIO_OPENDRAIN|GPIO_SPEED_50MHz|GPIO_OUTPUT_SET|GPIO_PORTE|GPIO_PIN3) +# define GPIO_nLED_GREEN /* PE4 */ (GPIO_OUTPUT|GPIO_OPENDRAIN|GPIO_SPEED_50MHz|GPIO_OUTPUT_SET|GPIO_PORTE|GPIO_PIN4) +# define GPIO_nLED_BLUE /* PE5 */ (GPIO_OUTPUT|GPIO_OPENDRAIN|GPIO_SPEED_50MHz|GPIO_OUTPUT_SET|GPIO_PORTE|GPIO_PIN5) + +# define BOARD_HAS_CONTROL_STATUS_LEDS 1 +# define BOARD_OVERLOAD_LED LED_RED +# define BOARD_ARMED_STATE_LED LED_BLUE + +#else + +# define GPIO_TRACECLK1 (GPIO_TRACECLK |GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL) //(GPIO_ALT|GPIO_AF0|GPIO_PORTE|GPIO_PIN2) +# define GPIO_TRACED0 (GPIO_TRACED0_2|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL) //(GPIO_ALT|GPIO_AF0|GPIO_PORTE|GPIO_PIN3) +# define GPIO_TRACED1 (GPIO_TRACED1_2|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL) //(GPIO_ALT|GPIO_AF0|GPIO_PORTE|GPIO_PIN4) +# define GPIO_TRACED2 (GPIO_TRACED2_2|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL) //(GPIO_ALT|GPIO_AF0|GPIO_PORTE|GPIO_PIN5) +# define GPIO_TRACED3 (GPIO_TRACED3_2|GPIO_PULLUP|GPIO_SPEED_100MHz|GPIO_PUSHPULL) //(GPIO_ALT|GPIO_AF0|GPIO_PORTE|GPIO_PIN6) +//#define GPIO_TRACESWO //(GPIO_ALT|GPIO_AF0|GPIO_PORTB|GPIO_PIN3) + +# undef BOARD_HAS_CONTROL_STATUS_LEDS +# undef BOARD_OVERLOAD_LED +# undef BOARD_ARMED_STATE_LED + +# define GPIO_nLED_RED GPIO_TRACED0 +# define GPIO_nLED_GREEN GPIO_TRACED1 +# define GPIO_nLED_BLUE GPIO_TRACED2 +# define GPIO_nARMED GPIO_TRACED3 +# define GPIO_nARMED_INIT GPIO_TRACED3 +#endif + +/* I2C busses */ + +/* Devices on the onboard buses. + * + * Note that these are unshifted addresses. + */ +#define PX4_I2C_OBDEV_SE050 0x48 + +/* + * 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. + * ADC3_6V6 and ADC3_3V3 are mapped back to ADC1 + * To do this We are relying on PC2_C, PC3_C being connected to PC2, PC3 + * respectively by the SYSCFG_PMCR default of setting for PC3SO PC2SO PA1SO + * PA0SO of 0. + * + * 0 Analog switch closed (pads are connected through the analog switch) + * + * So ADC3_INP0 is GPIO_ADC123_INP12 + * ADC3_INP1 is GPIO_ADC12_INP13 + */ + +/* Define GPIO pins used as ADC N.B. Channel numbers must match below */ + +#define PX4_ADC_GPIO \ + /* PA0 */ GPIO_ADC1_INP16, \ + /* PA4 */ GPIO_ADC12_INP18, \ + /* PB0 */ GPIO_ADC12_INP9, \ + /* PB1 */ GPIO_ADC12_INP5, \ + /* PC2 */ GPIO_ADC123_INP12, \ + /* PC3 */ GPIO_ADC12_INP13, \ + /* PF12 */ GPIO_ADC1_INP6, \ + /* PH3 */ GPIO_ADC3_INP14, \ + /* PH4 */ GPIO_ADC3_INP15 + +/* Define Channel numbers must match above GPIO pin IN(n)*/ +#define ADC_BATTERY_VOLTAGE_CHANNEL /* PB0 */ ADC1_CH(9) +#define ADC_BATTERY_CURRENT_CHANNEL /* PC2 */ ADC3_CH(0) +#define ADC_SCALED_12V_CHANNEL /* PA4 */ ADC1_CH(18) +#define ADC_SCALED_VDD_3V3_SENSORS_CHANNEL /* PA0 */ ADC1_CH(16) +#define ADC_SCALED_V5_CHANNEL /* PB1 */ ADC1_CH(5) +#define ADC_HW_VER_SENSE_CHANNEL /* PH3 */ ADC3_CH(14) +#define ADC_HW_REV_SENSE_CHANNEL /* PH4 */ ADC3_CH(15) + +#define ADC_CHANNELS \ + ((1 << ADC_BATTERY_VOLTAGE_CHANNEL) | \ + (1 << ADC_BATTERY_CURRENT_CHANNEL) | \ + (1 << ADC_SCALED_VDD_3V3_SENSORS_CHANNEL) | \ + (1 << ADC_SCALED_V5_CHANNEL) | \ + (1 << ADC_SCALED_12V_CHANNEL)) + + +#define BOARD_BATTERY1_V_DIV (21.0f) // (20k + 1k) / 1k = 21 + +#define ADC_SCALED_PAYLOAD_SENSE ADC_SCALED_12V_CHANNEL + +/* HW has to large of R termination on ADC todo:change when HW value is chosen */ + +#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_SPLIT_VERSIONING + +#define GPIO_HW_VER_REV_DRIVE /* PG0 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTG|GPIO_PIN0) +#define GPIO_HW_REV_SENSE /* PH4 */ GPIO_ADC3_INP15 +#define GPIO_HW_VER_SENSE /* PH3 */ GPIO_ADC3_INP14 +#define HW_INFO_INIT_PREFIX "ARKFPV" + +#define BOARD_NUM_SPI_CFG_HW_VERSIONS 2 +// Base/FMUM +#define ARKFPV_0 HW_FMUM_ID(0x0) // ARKFPV, Sensor Set Rev 0 +#define ARKFPV_1 HW_FMUM_ID(0x1) // ARKFPV, Sensor Set Rev 1 + +#define UAVCAN_NUM_IFACES_RUNTIME 1 + +/* HEATER + * PWM in future + */ +#define GPIO_HEATER_OUTPUT /* PB10 T2CH3 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTB|GPIO_PIN10) +#define HEATER_OUTPUT_EN(on_true) px4_arch_gpiowrite(GPIO_HEATER_OUTPUT, (on_true)) + +/* PE6 is nARMED + * The GPIO will be set as input while not armed HW will have external HW Pull UP. + * While armed it shall be configured at a GPIO OUT set LOW + */ +#if !defined(TRACE_PINS) +#define GPIO_nARMED_INIT /* PE6 */ (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTE|GPIO_PIN6) +#define GPIO_nARMED /* PE6 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTE|GPIO_PIN6) +#define BOARD_INDICATE_EXTERNAL_LOCKOUT_STATE(enabled) px4_arch_configgpio((enabled) ? GPIO_nARMED : GPIO_nARMED_INIT) +#define BOARD_GET_EXTERNAL_LOCKOUT_STATE() px4_arch_gpioread(GPIO_nARMED) +#endif + +/* PWM + */ +#define DIRECT_PWM_OUTPUT_CHANNELS 9 + +#define GPIO_FMU_CH1 /* PI0 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTI|GPIO_PIN0) +#define GPIO_FMU_CH2 /* PH12 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTH|GPIO_PIN12) +#define GPIO_FMU_CH3 /* PH11 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTH|GPIO_PIN11) +#define GPIO_FMU_CH4 /* PH10 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTH|GPIO_PIN10) +#define GPIO_FMU_CH5 /* PI5 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTI|GPIO_PIN5) +#define GPIO_FMU_CH6 /* PI6 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTI|GPIO_PIN6) +#define GPIO_FMU_CH7 /* PI7 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTI|GPIO_PIN7) +#define GPIO_FMU_CH8 /* PI2 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTI|GPIO_PIN2) +#define GPIO_FMU_CH9 /* PD12 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTD|GPIO_PIN12) + +#define GPIO_SPIX_SYNC /* PE9 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTE|GPIO_PIN9) + +/* Power supply control and monitoring GPIOs */ + +#define GPIO_VDD_5V_PGOOD /* PF13 */ (GPIO_INPUT |GPIO_FLOAT|GPIO_PORTF|GPIO_PIN13) +#define GPIO_VDD_12V_PGOOD /* PE15 */ (GPIO_INPUT |GPIO_FLOAT|GPIO_PORTE|GPIO_PIN15) +#define GPIO_5V_ON_BATTERY /* PG1 */ (GPIO_INPUT |GPIO_FLOAT|GPIO_PORTG|GPIO_PIN1) +#define GPIO_VDD_12V_EN /* PG4 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTG|GPIO_PIN4) + +#define GPIO_VDD_3V3_SD_CARD_EN /* PC13 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTC|GPIO_PIN13) + + +#define BOARD_NUMBER_BRICKS 1 + +/* Define True logic Power Control in arch agnostic form */ + +#define VDD_3V3_SD_CARD_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_3V3_SD_CARD_EN, (on_true)) +#define PAYLOAD_POWER_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_12V_EN, (on_true)) + +/* 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) + +#define FLASH_BASED_PARAMS + +/* High-resolution timer */ +#define HRT_TIMER 3 /* use timer3 for the HRT */ +#define HRT_TIMER_CHANNEL 1 /* use capture/compare channel 1 */ + +/* RC Serial port */ + +#define RC_SERIAL_PORT "/dev/ttyS4" + +/* PWM input driver. Use FMU AUX5 pins attached to timer4 channel 2 */ +#define PWMIN_TIMER 4 +#define PWMIN_TIMER_CHANNEL /* T4C2 */ 2 +#define GPIO_PWM_IN /* PD13 */ GPIO_TIM4_CH2IN_2 + +#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)) + +/* ARKFPV never powers off the Servo rail */ + +#define BOARD_ADC_SERVO_VALID (1) + +#define BOARD_ADC_BRICK_VALID (px4_arch_gpioread(GPIO_VDD_5V_PGOOD)) +#define BOARD_GPIO_PAYOLOAD_V_VALID (px4_arch_gpioread(GPIO_VDD_12V_PGOOD)) + +/* 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 + +#if defined(TRACE_PINS) +#define GPIO_TRACE \ + GPIO_TRACECLK1, \ + GPIO_TRACED0, \ + GPIO_TRACED1, \ + GPIO_TRACED2, \ + GPIO_TRACED3 +#else +#define GPIO_TRACE (GPIO_OUTPUT|GPIO_OUTPUT_SET|GPIO_PORTE|GPIO_PIN2) +#endif + +#define PX4_GPIO_INIT_LIST { \ + GPIO_TRACE, \ + PX4_ADC_GPIO, \ + GPIO_HW_VER_REV_DRIVE, \ + GPIO_CAN1_TX, \ + GPIO_CAN1_RX, \ + GPIO_HEATER_OUTPUT, \ + GPIO_VDD_5V_PGOOD, \ + GPIO_VDD_12V_PGOOD, \ + GPIO_VDD_12V_EN, \ + GPIO_5V_ON_BATTERY, \ + GPIO_VDD_3V3_SD_CARD_EN, \ + GPIO_nARMED_INIT, \ + GPIO_FMU_CH1, \ + GPIO_FMU_CH2, \ + GPIO_FMU_CH3, \ + GPIO_FMU_CH4, \ + GPIO_FMU_CH5, \ + GPIO_FMU_CH6, \ + GPIO_FMU_CH7, \ + GPIO_FMU_CH8, \ + GPIO_FMU_CH9, \ + GPIO_SPIX_SYNC \ + } + +#define BOARD_ENABLE_CONSOLE_BUFFER + +#define BOARD_NUM_IO_TIMERS 3 +#define BOARD_SPIX_SYNC_FREQ 32000 + +__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/ark/fpv/src/bootloader_main.c b/boards/ark/fpv/src/bootloader_main.c new file mode 100644 index 0000000000..7a3ef5e019 --- /dev/null +++ b/boards/ark/fpv/src/bootloader_main.c @@ -0,0 +1,85 @@ +/**************************************************************************** + * + * 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 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 +#include + +extern int sercon_main(int c, char **argv); + +__EXPORT void board_on_reset(int status) {} + +__EXPORT void stm32_boardinitialize(void) +{ + /* configure pins */ + const uint32_t list[] = PX4_GPIO_INIT_LIST; + + for (size_t gpio = 0; gpio < arraySize(list); gpio++) { + if (list[gpio] != 0) { + px4_arch_configgpio(list[gpio]); + } + } + + /* configure USB interfaces */ + stm32_usbinitialize(); +} + +__EXPORT int board_app_initialize(uintptr_t arg) +{ + return 0; +} + +void board_late_initialize(void) +{ + sercon_main(0, NULL); +} + +extern void sys_tick_handler(void); +void board_timerhook(void) +{ + sys_tick_handler(); +} diff --git a/boards/ark/fpv/src/can.c b/boards/ark/fpv/src/can.c new file mode 100644 index 0000000000..a586a64814 --- /dev/null +++ b/boards/ark/fpv/src/can.c @@ -0,0 +1,140 @@ +/**************************************************************************** + * + * 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 can.c + * + * Board-specific CAN functions. + */ + +#if !defined(CONFIG_CAN) + +#include + +#include "board_config.h" + + +__EXPORT +uint16_t board_get_can_interfaces(void) +{ + uint16_t enabled_interfaces = 0x3; + + enabled_interfaces &= ~(1 << 1); + + return enabled_interfaces; +} + +#else + +#include +#include + +#include +#include + +#include "chip.h" +#include "arm_internal.h" + +#include "chip.h" +#include "stm32_can.h" +#include "board_config.h" + +/************************************************************************************ + * 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 /* CONFIG_CAN */ diff --git a/boards/ark/fpv/src/hw_config.h b/boards/ark/fpv/src/hw_config.h new file mode 100644 index 0000000000..8ee7550795 --- /dev/null +++ b/boards/ark/fpv/src/hw_config.h @@ -0,0 +1,129 @@ +/* + * 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/ttyS5,921600" +#define BOOT_DELAY_ADDRESS 0x000001a0 +#define BOARD_TYPE 59 +#define _FLASH_KBYTES (*(uint32_t *)0x1FF1E880) +#define BOARD_FLASH_SECTORS (14) +#define BOARD_FLASH_SIZE (_FLASH_KBYTES * 1024) +#define APP_RESERVATION_SIZE (1 * 128 * 1024) + +#define OSC_FREQ 16 + +#define BOARD_PIN_LED_ACTIVITY GPIO_nLED_BLUE // BLUE +#define BOARD_PIN_LED_BOOTLOADER GPIO_nLED_GREEN // GREEN +#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/ark/fpv/src/i2c.cpp b/boards/ark/fpv/src/i2c.cpp new file mode 100644 index 0000000000..8add5e64f7 --- /dev/null +++ b/boards/ark/fpv/src/i2c.cpp @@ -0,0 +1,40 @@ +/**************************************************************************** + * + * 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. + * + ****************************************************************************/ + +#include + +constexpr px4_i2c_bus_t px4_i2c_buses[I2C_BUS_MAX_BUS_ITEMS] = { + initI2CBusExternal(1), + initI2CBusInternal(2), + initI2CBusInternal(4), +}; diff --git a/boards/ark/fpv/src/init.c b/boards/ark/fpv/src/init.c new file mode 100644 index 0000000000..f97fb7d8aa --- /dev/null +++ b/boards/ark/fpv/src/init.c @@ -0,0 +1,293 @@ +/**************************************************************************** + * + * 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 + * + * ARKFMU-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 "spix_sync.h" + +#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 +#include + +# if defined(FLASH_BASED_PARAMS) +# include +#endif + +/**************************************************************************** + * 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 */ + + PAYLOAD_POWER_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); + PAYLOAD_POWER_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(PX4_MAKE_GPIO_INPUT(io_timer_channel_get_as_pwm_input(i))); + } + + if (status >= 0) { + up_mdelay(6); + } +} + +/************************************************************************************ + * Name: stm32_boardinitialize + * + * Description: + * All STM32 architectures must provide the following entry point. This entry point + * is called early in the initialization -- after all memory has been configured + * and mapped but before any devices have been initialized. + * + ************************************************************************************/ + +__EXPORT void +stm32_boardinitialize(void) +{ + 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) +{ + /* Power on Interfaces */ + PAYLOAD_POWER_EN(true); + + /* Need hrt running before using the ADC */ + + px4_platform_init(); + + // Use the default HW_VER_REV(0x0,0x0) for Ramtron + + stm32_spiinitialize(); + +#if defined(FLASH_BASED_PARAMS) + static sector_descriptor_t params_sector_map[] = { + {15, 128 * 1024, 0x081E0000}, + {0, 0, 0}, + }; + + /* Initialize the flashfs layer to use heap allocated memory */ + int result = parameter_flashfs_init(params_sector_map, NULL, 0); + + if (result != OK) { + syslog(LOG_ERR, "[boot] FAILED to init params in FLASH %d\n", result); + led_on(LED_AMBER); + } + +#endif // FLASH_BASED_PARAMS + + /* Configure the HW based on the manifest */ + + px4_platform_configure(); + + 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"); + } + + /* Configure the Actual SPI interfaces (after we determined the HW version) */ + + 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_on(LED_GREEN); // Indicate Power. + led_off(LED_BLUE); + + if (board_hardfault_init(2, true) != 0) { + led_on(LED_RED); + } + + // Ensure Power is off for > 10 mS + usleep(15 * 1000); + VDD_3V3_SD_CARD_EN(true); + usleep(500 * 1000); + +#ifdef CONFIG_MMCSD + int ret = stm32_sdio_initialize(); + + if (ret != OK) { + led_on(LED_RED); + return ret; + } + +#endif /* CONFIG_MMCSD */ + + /* Configure the SPIX_SYNC output */ + spix_sync_servo_init(BOARD_SPIX_SYNC_FREQ); + spix_sync_servo_set(0, 150); + + return OK; +} diff --git a/boards/ark/fpv/src/led.c b/boards/ark/fpv/src/led.c new file mode 100644 index 0000000000..b629ade32c --- /dev/null +++ b/boards/ark/fpv/src/led.c @@ -0,0 +1,234 @@ +/**************************************************************************** + * + * 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 led.c + * + * ARKFMU 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 +}; + +#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) + GPIO_nLED_GREEN, // 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/ark/fpv/src/mtd.cpp b/boards/ark/fpv/src/mtd.cpp new file mode 100644 index 0000000000..bd74d551ee --- /dev/null +++ b/boards/ark/fpv/src/mtd.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** + * + * Copyright (C) 2024 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 +#include + +static const px4_mft_entry_s mft_mft = { + .type = MFT, + .pmft = (void *) system_query_manifest, +}; + +static const px4_mft_s mft = { + .nmft = 1, + .mfts = { + &mft_mft, + } +}; + +const px4_mft_s *board_get_manifest(void) +{ + return &mft; +} diff --git a/boards/ark/fpv/src/sdio.c b/boards/ark/fpv/src/sdio.c new file mode 100644 index 0000000000..869d757756 --- /dev/null +++ b/boards/ark/fpv/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/ark/fpv/src/spi.cpp b/boards/ark/fpv/src/spi.cpp new file mode 100644 index 0000000000..424eafedd6 --- /dev/null +++ b/boards/ark/fpv/src/spi.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** + * + * Copyright (C) 2024 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] = { + initSPIFmumID(ARKFPV_0, { + initSPIBus(SPI::Bus::SPI1, { + initSPIDevice(DRV_IMU_DEVTYPE_IIM42653, SPI::CS{GPIO::PortI, GPIO::Pin9}, SPI::DRDY{GPIO::PortF, GPIO::Pin2}), + }, {GPIO::PortI, GPIO::Pin11}), + initSPIBus(SPI::Bus::SPI6, { + initSPIDevice(DRV_DEVTYPE_UNUSED, SPI::CS{GPIO::PortI, GPIO::Pin10}, SPI::DRDY{GPIO::PortD, GPIO::Pin11}) + }), + }), + initSPIFmumID(ARKFPV_1, { // Placeholder + initSPIBus(SPI::Bus::SPI1, { + initSPIDevice(DRV_IMU_DEVTYPE_IIM42653, SPI::CS{GPIO::PortI, GPIO::Pin9}, SPI::DRDY{GPIO::PortF, GPIO::Pin2}), + }, {GPIO::PortI, GPIO::Pin11}), + initSPIBus(SPI::Bus::SPI6, { + initSPIDevice(DRV_DEVTYPE_UNUSED, SPI::CS{GPIO::PortI, GPIO::Pin10}, SPI::DRDY{GPIO::PortD, GPIO::Pin11}) + }), + }), +}; + +static constexpr bool unused = validateSPIConfig(px4_spi_buses_all_hw); diff --git a/boards/ark/fpv/src/spix_sync.c b/boards/ark/fpv/src/spix_sync.c new file mode 100644 index 0000000000..056e38e75f --- /dev/null +++ b/boards/ark/fpv/src/spix_sync.c @@ -0,0 +1,309 @@ +/**************************************************************************** + * + * Copyright (C) 2023 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 Airmind 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 spix_sync.c +* +* +*/ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include + +#include + +#include "spix_sync.h" + +#define REG(_tmr, _reg) (*(volatile uint32_t *)(spix_sync_timers[_tmr].base + _reg)) + +#define rCR1(_tmr) REG(_tmr, STM32_GTIM_CR1_OFFSET) +#define rCR2(_tmr) REG(_tmr, STM32_GTIM_CR2_OFFSET) +#define rSMCR(_tmr) REG(_tmr, STM32_GTIM_SMCR_OFFSET) +#define rDIER(_tmr) REG(_tmr, STM32_GTIM_DIER_OFFSET) +#define rSR(_tmr) REG(_tmr, STM32_GTIM_SR_OFFSET) +#define rEGR(_tmr) REG(_tmr, STM32_GTIM_EGR_OFFSET) +#define rCCMR1(_tmr) REG(_tmr, STM32_GTIM_CCMR1_OFFSET) +#define rCCMR2(_tmr) REG(_tmr, STM32_GTIM_CCMR2_OFFSET) +#define rCCER(_tmr) REG(_tmr, STM32_GTIM_CCER_OFFSET) +#define rCNT(_tmr) REG(_tmr, STM32_GTIM_CNT_OFFSET) +#define rPSC(_tmr) REG(_tmr, STM32_GTIM_PSC_OFFSET) +#define rARR(_tmr) REG(_tmr, STM32_GTIM_ARR_OFFSET) +#define rCCR1(_tmr) REG(_tmr, STM32_GTIM_CCR1_OFFSET) +#define rCCR2(_tmr) REG(_tmr, STM32_GTIM_CCR2_OFFSET) +#define rCCR3(_tmr) REG(_tmr, STM32_GTIM_CCR3_OFFSET) +#define rCCR4(_tmr) REG(_tmr, STM32_GTIM_CCR4_OFFSET) +#define rDCR(_tmr) REG(_tmr, STM32_GTIM_DCR_OFFSET) +#define rDMAR(_tmr) REG(_tmr, STM32_GTIM_DMAR_OFFSET) +#define rBDTR(_tmr) REG(_tmr, STM32_ATIM_BDTR_OFFSET) + +#define BOARD_SPIX_SYNC_PWM_FREQ 1024000 + +unsigned +spix_sync_timer_get_period(unsigned timer) +{ + return (rARR(timer)); +} + +static void spix_sync_timer_init_timer(unsigned timer, unsigned rate) +{ + if (spix_sync_timers[timer].base) { + + irqstate_t flags = px4_enter_critical_section(); + + /* enable the timer clock before we try to talk to it */ + + modifyreg32(spix_sync_timers[timer].clock_register, 0, spix_sync_timers[timer].clock_bit); + + /* disable and configure the timer */ + rCR1(timer) = 0; + rCR2(timer) = 0; + rSMCR(timer) = 0; + rDIER(timer) = 0; + rCCER(timer) = 0; + rCCMR1(timer) = 0; + rCCMR2(timer) = 0; + rCCR1(timer) = 0; + rCCR2(timer) = 0; + rCCR3(timer) = 0; + rCCR4(timer) = 0; + rCCER(timer) = 0; + rDCR(timer) = 0; + + if ((spix_sync_timers[timer].base == STM32_TIM1_BASE) || (spix_sync_timers[timer].base == STM32_TIM8_BASE)) { + + /* master output enable = on */ + + rBDTR(timer) = ATIM_BDTR_MOE; + } + + /* If the timer clock source provided as clock_freq is the STM32_APBx_TIMx_CLKIN + * then configure the timer to free-run at 1MHz. + * Otherwise, other frequencies are attainable by adjusting .clock_freq accordingly. + */ + + rPSC(timer) = (spix_sync_timers[timer].clock_freq / BOARD_SPIX_SYNC_PWM_FREQ) - 1; + + /* configure the timer to update at the desired rate */ + + rARR(timer) = (BOARD_SPIX_SYNC_PWM_FREQ / rate) - 1; + + /* generate an update event; reloads the counter and all registers */ + rEGR(timer) = GTIM_EGR_UG; + + px4_leave_critical_section(flags); + } + +} + +void spix_sync_channel_init(unsigned channel) +{ + /* Only initialize used channels */ + + if (spix_sync_channels[channel].timer_channel) { + + unsigned timer = spix_sync_channels[channel].timer_index; + + /* configure the GPIO first */ + px4_arch_configgpio(spix_sync_channels[channel].gpio_out); + + uint16_t polarity = spix_sync_channels[channel].masks; + + /* configure the channel */ + switch (spix_sync_channels[channel].timer_channel) { + case 1: + rCCMR1(timer) |= (GTIM_CCMR_MODE_PWM1 << GTIM_CCMR1_OC1M_SHIFT) | GTIM_CCMR1_OC1PE; + rCCER(timer) |= polarity | GTIM_CCER_CC1E; + break; + + case 2: + rCCMR1(timer) |= (GTIM_CCMR_MODE_PWM1 << GTIM_CCMR1_OC2M_SHIFT) | GTIM_CCMR1_OC2PE; + rCCER(timer) |= polarity | GTIM_CCER_CC2E; + break; + + case 3: + rCCMR2(timer) |= (GTIM_CCMR_MODE_PWM1 << GTIM_CCMR2_OC3M_SHIFT) | GTIM_CCMR2_OC3PE; + rCCER(timer) |= polarity | GTIM_CCER_CC3E; + break; + + case 4: + rCCMR2(timer) |= (GTIM_CCMR_MODE_PWM1 << GTIM_CCMR2_OC4M_SHIFT) | GTIM_CCMR2_OC4PE; + rCCER(timer) |= polarity | GTIM_CCER_CC4E; + break; + } + } +} + +int +spix_sync_servo_set(unsigned channel, uint8_t cvalue) +{ + if (channel >= arraySize(spix_sync_channels)) { + return -1; + } + + unsigned timer = spix_sync_channels[channel].timer_index; + + /* test timer for validity */ + if ((spix_sync_timers[timer].base == 0) || + (spix_sync_channels[channel].gpio_out == 0)) { + return -1; + } + + unsigned period = spix_sync_timer_get_period(timer); + + unsigned value = (unsigned)cvalue * period / 255; + + /* configure the channel */ + if (value > 0) { + value--; + } + + + switch (spix_sync_channels[channel].timer_channel) { + case 1: + rCCR1(timer) = value; + break; + + case 2: + rCCR2(timer) = value; + break; + + case 3: + rCCR3(timer) = value; + break; + + case 4: + rCCR4(timer) = value; + break; + + default: + return -1; + } + + return 0; +} + +unsigned spix_sync_servo_get(unsigned channel) +{ + if (channel >= 3) { + return 0; + } + + unsigned timer = spix_sync_channels[channel].timer_index; + uint16_t value = 0; + + /* test timer for validity */ + if ((spix_sync_timers[timer].base == 0) || + (spix_sync_channels[channel].timer_channel == 0)) { + return 0; + } + + /* configure the channel */ + switch (spix_sync_channels[channel].timer_channel) { + case 1: + value = rCCR1(timer); + break; + + case 2: + value = rCCR2(timer); + break; + + case 3: + value = rCCR3(timer); + break; + + case 4: + value = rCCR4(timer); + break; + } + + unsigned period = spix_sync_timer_get_period(timer); + return ((value + 1) * 255 / period); +} + +int spix_sync_servo_init(unsigned rate) +{ + /* do basic timer initialisation first */ + for (unsigned i = 0; i < arraySize(spix_sync_timers); i++) { + spix_sync_timer_init_timer(i, rate); + } + + /* now init channels */ + for (unsigned i = 0; i < arraySize(spix_sync_channels); i++) { + spix_sync_channel_init(i); + } + + spix_sync_servo_arm(true); + return OK; +} + +void +spix_sync_servo_deinit(void) +{ + /* disable the timers */ + spix_sync_servo_arm(false); +} +void +spix_sync_servo_arm(bool armed) +{ + /* iterate timers and arm/disarm appropriately */ + for (unsigned i = 0; i < arraySize(spix_sync_timers); i++) { + if (spix_sync_timers[i].base != 0) { + if (armed) { + /* force an update to preload all registers */ + rEGR(i) = GTIM_EGR_UG; + + /* arm requires the timer be enabled */ + rCR1(i) |= GTIM_CR1_CEN | GTIM_CR1_ARPE; + + } else { + rCR1(i) = 0; + } + } + } +} diff --git a/boards/ark/fpv/src/spix_sync.h b/boards/ark/fpv/src/spix_sync.h new file mode 100644 index 0000000000..2e37c89086 --- /dev/null +++ b/boards/ark/fpv/src/spix_sync.h @@ -0,0 +1,42 @@ +/**************************************************************************** + * + * Copyright (C) 2023 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. + * + ****************************************************************************/ + +__BEGIN_DECLS +void spix_sync_channel_init(unsigned channel); +int spix_sync_servo_set(unsigned channel, uint8_t value); +unsigned spix_sync_servo_get(unsigned channel); +int spix_sync_servo_init(unsigned rate); +void spix_sync_servo_deinit(void); +void spix_sync_servo_arm(bool armed); +unsigned spix_sync_timer_get_period(unsigned timer); +__END_DECLS diff --git a/boards/ark/fpv/src/timer_config.cpp b/boards/ark/fpv/src/timer_config.cpp new file mode 100644 index 0000000000..623aad1f06 --- /dev/null +++ b/boards/ark/fpv/src/timer_config.cpp @@ -0,0 +1,86 @@ +/**************************************************************************** + * + * 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 + * + * TIM5_CH4 T FMU_CH1 + * TIM5_CH3 T FMU_CH2 + * TIM5_CH2 T FMU_CH3 + * TIM5_CH1 T FMU_CH4 + * + * TIM8_CH1 T FMU_CH5 + * TIM8_CH2 T FMU_CH6 + * TIM8_CH3 T FMU_CH7 + * TIM8_CH4 T FMU_CH8 + * + * TIM4_CH1 T FMU_CH9 + * + * TIM1_CH1 T SPIX_SYNC > Pulse or GPIO strobe + * + * TIM2_CH3 T HEATER > PWM OUT or GPIO + * + * TIM3_CH1 T HRT_TIMER + * + */ + +constexpr io_timers_t io_timers[MAX_IO_TIMERS] = { + initIOTimer(Timer::Timer5, DMA{DMA::Index1}), + initIOTimer(Timer::Timer8, DMA{DMA::Index1}), + initIOTimer(Timer::Timer4, DMA{DMA::Index1}), +}; + +constexpr timer_io_channels_t timer_io_channels[MAX_TIMER_IO_CHANNELS] = { + initIOTimerChannel(io_timers, {Timer::Timer5, Timer::Channel4}, {GPIO::PortI, GPIO::Pin0}), + initIOTimerChannel(io_timers, {Timer::Timer5, Timer::Channel3}, {GPIO::PortH, GPIO::Pin12}), + initIOTimerChannel(io_timers, {Timer::Timer5, Timer::Channel2}, {GPIO::PortH, GPIO::Pin11}), + initIOTimerChannel(io_timers, {Timer::Timer5, Timer::Channel1}, {GPIO::PortH, GPIO::Pin10}), + initIOTimerChannel(io_timers, {Timer::Timer8, Timer::Channel1}, {GPIO::PortI, GPIO::Pin5}), + initIOTimerChannel(io_timers, {Timer::Timer8, Timer::Channel2}, {GPIO::PortI, GPIO::Pin6}), + initIOTimerChannel(io_timers, {Timer::Timer8, Timer::Channel3}, {GPIO::PortI, GPIO::Pin7}), + initIOTimerChannel(io_timers, {Timer::Timer8, Timer::Channel4}, {GPIO::PortI, GPIO::Pin2}), + initIOTimerChannel(io_timers, {Timer::Timer4, Timer::Channel1}, {GPIO::PortD, GPIO::Pin12}), +}; + +constexpr io_timers_channel_mapping_t io_timers_channel_mapping = + initIOTimerChannelMapping(io_timers, timer_io_channels); + + +constexpr io_timers_t spix_sync_timers[MAX_SPIX_SYNC_TIMERS] = { + initIOTimer(Timer::Timer1), +}; + +constexpr timer_io_channels_t spix_sync_channels[MAX_SPIX_SYNC_TIMERS] = { + initIOTimerChannel(spix_sync_timers, {Timer::Timer1, Timer::Channel1}, {GPIO::PortE, GPIO::Pin9}), +}; diff --git a/boards/ark/fpv/src/usb.c b/boards/ark/fpv/src/usb.c new file mode 100644 index 0000000000..1c64e94ba1 --- /dev/null +++ b/boards/ark/fpv/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 usb.c + * + * Board-specific USB functions. + */ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include "arm_internal.h" +#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 ARKFMU 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/msg/ManualControlSwitches.msg b/msg/ManualControlSwitches.msg index 4d1cbab232..39b6efe71f 100644 --- a/msg/ManualControlSwitches.msg +++ b/msg/ManualControlSwitches.msg @@ -29,6 +29,8 @@ uint8 transition_switch # VTOL transition switch: _HOVER, FORWARD_FLIGH uint8 photo_switch # Photo trigger switch uint8 video_switch # Photo trigger switch +uint8 payload_power_switch # Payload power switch + uint8 engage_main_motor_switch # Engage the main motor (for helicopters) uint32 switch_changes # number of switch changes diff --git a/msg/RcChannels.msg b/msg/RcChannels.msg index 546755f66f..b932dfd33b 100644 --- a/msg/RcChannels.msg +++ b/msg/RcChannels.msg @@ -28,13 +28,14 @@ uint8 FUNCTION_FLTBTN_SLOT_4 = 24 uint8 FUNCTION_FLTBTN_SLOT_5 = 25 uint8 FUNCTION_FLTBTN_SLOT_6 = 26 uint8 FUNCTION_ENGAGE_MAIN_MOTOR = 27 +uint8 FUNCTION_PAYLOAD_POWER = 28 uint8 FUNCTION_FLTBTN_SLOT_COUNT = 6 uint64 timestamp_last_valid # Timestamp of last valid RC signal float32[18] channels # Scaled to -1..1 (throttle: 0..1) uint8 channel_count # Number of valid channels -int8[28] function # Functions mapping +int8[29] function # Functions mapping uint8 rssi # Receive signal strength index bool signal_lost # Control signal lost, should be checked together with topic timeout uint32 frame_drop_count # Number of dropped frames diff --git a/msg/SystemPower.msg b/msg/SystemPower.msg index 21b35ba1dc..05754dab0e 100644 --- a/msg/SystemPower.msg +++ b/msg/SystemPower.msg @@ -1,5 +1,6 @@ uint64 timestamp # time since system start (microseconds) float32 voltage5v_v # peripheral 5V rail voltage +float32 voltage_payload_v # payload rail voltage float32[4] sensors3v3 # Sensors 3V3 rail voltage uint8 sensors3v3_valid # Sensors 3V3 rail voltage was read (bitfield). uint8 usb_connected # USB is connected when 1 @@ -10,6 +11,7 @@ uint8 periph_5v_oc # peripheral overcurrent when 1 uint8 hipower_5v_oc # high power peripheral overcurrent when 1 uint8 comp_5v_valid # 5V to companion valid uint8 can1_gps1_5v_valid # 5V for CAN1/GPS1 valid +uint8 payload_v_valid # payload rail voltage is valid uint8 BRICK1_VALID_SHIFTS=0 uint8 BRICK1_VALID_MASK=1 diff --git a/platforms/common/include/px4_platform_common/board_common.h b/platforms/common/include/px4_platform_common/board_common.h index 4dff12c1b2..763b09994c 100644 --- a/platforms/common/include/px4_platform_common/board_common.h +++ b/platforms/common/include/px4_platform_common/board_common.h @@ -106,6 +106,13 @@ #define ADC_V5_SCALE (2.0f) // The scale factor defined by HW's resistive divider (Rt+Rb)/ Rb #endif +#if !defined(ADC_PAYLOAD_V_FULL_SCALE) +#define ADC_PAYLOAD_V_FULL_SCALE (25.3f) // Payload volt Rail full scale voltage +#endif +#if !defined(ADC_PAYLOAD_SCALE) +#define ADC_PAYLOAD_SCALE (7.667f) // The scale factor defined by HW's resistive divider (Rt+Rb)/ Rb +#endif + #if !defined(ADC_3V3_V_FULL_SCALE) #define ADC_3V3_V_FULL_SCALE (3.6f) // 3.3V volt Rail full scale voltage #endif diff --git a/src/drivers/adc/board_adc/ADC.cpp b/src/drivers/adc/board_adc/ADC.cpp index 906af69959..7bf553f9b4 100644 --- a/src/drivers/adc/board_adc/ADC.cpp +++ b/src/drivers/adc/board_adc/ADC.cpp @@ -204,6 +204,9 @@ void ADC::update_system_power(hrt_abstime now) # if defined(ADC_SCALED_V5_SENSE) && defined(ADC_SCALED_V3V3_SENSORS_SENSE) cnt += ADC_SCALED_V3V3_SENSORS_COUNT; # endif +# if defined(ADC_SCALED_PAYLOAD_SENSE) + cnt++; +# endif for (unsigned i = 0; i < _channel_count; i++) { # if defined(ADC_SCALED_V5_SENSE) @@ -234,6 +237,16 @@ void ADC::update_system_power(hrt_abstime now) } # endif +# if defined(ADC_SCALED_PAYLOAD_SENSE) + + if (_samples[i].am_channel == ADC_SCALED_PAYLOAD_SENSE) { + system_power.voltage_payload_v = _samples[i].am_data * ((ADC_PAYLOAD_V_FULL_SCALE / 3.3f) * + (px4_arch_adc_reference_v() / + px4_arch_adc_dn_fullcount())); + cnt--; + } + +# endif if (cnt == 0) { break; @@ -285,6 +298,9 @@ void ADC::update_system_power(hrt_abstime now) #ifdef BOARD_GPIO_VDD_5V_CAN1_GPS1_VALID system_power.can1_gps1_5v_valid = read_gpio_value(_5v_can1_gps1_valid_fd); #endif +#ifdef BOARD_GPIO_PAYOLOAD_V_VALID + system_power.payload_v_valid = BOARD_GPIO_PAYOLOAD_V_VALID; +#endif system_power.timestamp = hrt_absolute_time(); _to_system_power.publish(system_power); diff --git a/src/modules/manual_control/ManualControl.cpp b/src/modules/manual_control/ManualControl.cpp index 2c98f108a0..a927035f93 100644 --- a/src/modules/manual_control/ManualControl.cpp +++ b/src/modules/manual_control/ManualControl.cpp @@ -271,6 +271,19 @@ void ManualControl::processSwitches(hrt_abstime &now) } } +#if defined(PAYLOAD_POWER_EN) + + if (switches.payload_power_switch != _previous_switches.payload_power_switch) { + if (switches.payload_power_switch == manual_control_switches_s::SWITCH_POS_ON) { + PAYLOAD_POWER_EN(true); + + } else if (switches.payload_power_switch == manual_control_switches_s::SWITCH_POS_OFF) { + PAYLOAD_POWER_EN(false); + } + } + +#endif // PAYLOAD_POWER_EN + } else if (!_armed) { // Directly initialize mode using RC switch but only before arming evaluateModeSlot(switches.mode_slot); diff --git a/src/modules/rc_update/params.c b/src/modules/rc_update/params.c index 91f884eb9a..7f8a21605c 100644 --- a/src/modules/rc_update/params.c +++ b/src/modules/rc_update/params.c @@ -1762,6 +1762,35 @@ PARAM_DEFINE_INT32(RC_MAP_AUX5, 0); * @value 18 Channel 18 */ PARAM_DEFINE_INT32(RC_MAP_AUX6, 0); + +/** + * Payload Power Switch RC channel + * + * @min 0 + * @max 18 + * @group Radio Switches + * @value 0 Unassigned + * @value 1 Channel 1 + * @value 2 Channel 2 + * @value 3 Channel 3 + * @value 4 Channel 4 + * @value 5 Channel 5 + * @value 6 Channel 6 + * @value 7 Channel 7 + * @value 8 Channel 8 + * @value 9 Channel 9 + * @value 10 Channel 10 + * @value 11 Channel 11 + * @value 12 Channel 12 + * @value 13 Channel 13 + * @value 14 Channel 14 + * @value 15 Channel 15 + * @value 16 Channel 16 + * @value 17 Channel 17 + * @value 18 Channel 18 + */ +PARAM_DEFINE_INT32(RC_MAP_PAY_SW, 0); + /** * PARAM1 tuning channel * @@ -2029,6 +2058,22 @@ PARAM_DEFINE_FLOAT(RC_GEAR_TH, 0.75f); */ PARAM_DEFINE_FLOAT(RC_ENG_MOT_TH, 0.75f); +/** + * Threshold for selecting payload power switch + * + * 0-1 indicate where in the full channel range the threshold sits + * 0 : min + * 1 : max + * sign indicates polarity of comparison + * positive : true when channel>th + * negative : true when channel) _param_rc_fails_thr, + (ParamInt) _param_rc_map_payload_sw, + (ParamFloat) _param_rc_loiter_th, (ParamFloat) _param_rc_offb_th, (ParamFloat) _param_rc_killswitch_th, @@ -238,6 +240,7 @@ protected: (ParamFloat) _param_rc_gear_th, (ParamFloat) _param_rc_return_th, (ParamFloat) _param_rc_eng_mot_th, + (ParamFloat) _param_rc_payload_th, (ParamInt) _param_rc_chan_cnt )