From 0ce76679b7e4f5104886a64ae3a906f1c0e249da Mon Sep 17 00:00:00 2001 From: Alex Klimaj Date: Thu, 15 Sep 2022 11:13:49 -0600 Subject: [PATCH] boards: add new ARKV6X (#20191) --- .ci/Jenkinsfile-compile | 2 + .github/workflows/compile_nuttx.yml | 1 + .vscode/cmake-variants.yaml | 10 + Makefile | 3 +- Tools/upload.sh | 2 +- boards/ark/fmu-v6x/bootloader.px4board | 3 + boards/ark/fmu-v6x/default.px4board | 89 +++ .../fmu-v6x/extras/ark_fmu-v6x_bootloader.bin | Bin 0 -> 45172 bytes .../ark/fmu-v6x/extras/px4_io-v2_default.bin | Bin 0 -> 39924 bytes boards/ark/fmu-v6x/firmware.prototype | 13 + boards/ark/fmu-v6x/init/rc.board_defaults | 21 + boards/ark/fmu-v6x/init/rc.board_sensors | 71 +++ boards/ark/fmu-v6x/nuttx-config/Kconfig | 17 + .../fmu-v6x/nuttx-config/bootloader/defconfig | 96 +++ .../ark/fmu-v6x/nuttx-config/include/board.h | 558 ++++++++++++++++++ .../nuttx-config/include/board_dma_map.h | 87 +++ boards/ark/fmu-v6x/nuttx-config/nsh/defconfig | 295 +++++++++ .../nuttx-config/scripts/bootloader_script.ld | 215 +++++++ .../fmu-v6x/nuttx-config/scripts/script.ld | 229 +++++++ boards/ark/fmu-v6x/src/CMakeLists.txt | 71 +++ boards/ark/fmu-v6x/src/board_config.h | 524 ++++++++++++++++ boards/ark/fmu-v6x/src/bootloader_main.c | 75 +++ boards/ark/fmu-v6x/src/can.c | 142 +++++ boards/ark/fmu-v6x/src/hw_config.h | 128 ++++ boards/ark/fmu-v6x/src/i2c.cpp | 41 ++ boards/ark/fmu-v6x/src/init.c | 282 +++++++++ boards/ark/fmu-v6x/src/led.c | 235 ++++++++ boards/ark/fmu-v6x/src/manifest.c | 223 +++++++ boards/ark/fmu-v6x/src/mtd.cpp | 128 ++++ boards/ark/fmu-v6x/src/sdio.c | 177 ++++++ boards/ark/fmu-v6x/src/spi.cpp | 86 +++ boards/ark/fmu-v6x/src/timer_config.cpp | 80 +++ boards/ark/fmu-v6x/src/usb.c | 105 ++++ 33 files changed, 4007 insertions(+), 2 deletions(-) create mode 100644 boards/ark/fmu-v6x/bootloader.px4board create mode 100644 boards/ark/fmu-v6x/default.px4board create mode 100755 boards/ark/fmu-v6x/extras/ark_fmu-v6x_bootloader.bin create mode 100755 boards/ark/fmu-v6x/extras/px4_io-v2_default.bin create mode 100644 boards/ark/fmu-v6x/firmware.prototype create mode 100644 boards/ark/fmu-v6x/init/rc.board_defaults create mode 100644 boards/ark/fmu-v6x/init/rc.board_sensors create mode 100644 boards/ark/fmu-v6x/nuttx-config/Kconfig create mode 100644 boards/ark/fmu-v6x/nuttx-config/bootloader/defconfig create mode 100644 boards/ark/fmu-v6x/nuttx-config/include/board.h create mode 100644 boards/ark/fmu-v6x/nuttx-config/include/board_dma_map.h create mode 100644 boards/ark/fmu-v6x/nuttx-config/nsh/defconfig create mode 100644 boards/ark/fmu-v6x/nuttx-config/scripts/bootloader_script.ld create mode 100644 boards/ark/fmu-v6x/nuttx-config/scripts/script.ld create mode 100644 boards/ark/fmu-v6x/src/CMakeLists.txt create mode 100644 boards/ark/fmu-v6x/src/board_config.h create mode 100644 boards/ark/fmu-v6x/src/bootloader_main.c create mode 100644 boards/ark/fmu-v6x/src/can.c create mode 100644 boards/ark/fmu-v6x/src/hw_config.h create mode 100644 boards/ark/fmu-v6x/src/i2c.cpp create mode 100644 boards/ark/fmu-v6x/src/init.c create mode 100644 boards/ark/fmu-v6x/src/led.c create mode 100644 boards/ark/fmu-v6x/src/manifest.c create mode 100644 boards/ark/fmu-v6x/src/mtd.cpp create mode 100644 boards/ark/fmu-v6x/src/sdio.c create mode 100644 boards/ark/fmu-v6x/src/spi.cpp create mode 100644 boards/ark/fmu-v6x/src/timer_config.cpp create mode 100644 boards/ark/fmu-v6x/src/usb.c diff --git a/.ci/Jenkinsfile-compile b/.ci/Jenkinsfile-compile index 4e61920c58..5401956ecd 100644 --- a/.ci/Jenkinsfile-compile +++ b/.ci/Jenkinsfile-compile @@ -42,6 +42,8 @@ pipeline { "ark_can-gps_default", "ark_can-rtk-gps_canbootloader", "ark_can-rtk-gps_default", + "ark_fmu-v6x_bootloader", + "ark_fmu-v6x_default", "atl_mantis-edu_default", "av_x-v1_default", "bitcraze_crazyflie_default", diff --git a/.github/workflows/compile_nuttx.yml b/.github/workflows/compile_nuttx.yml index 16351fb82c..2b7828cc5d 100644 --- a/.github/workflows/compile_nuttx.yml +++ b/.github/workflows/compile_nuttx.yml @@ -21,6 +21,7 @@ jobs: ark_can-gps, ark_can-rtk-gps, ark_cannode, + ark_fmu-v6x, atl_mantis-edu, av_x-v1, bitcraze_crazyflie, diff --git a/.vscode/cmake-variants.yaml b/.vscode/cmake-variants.yaml index d114782ddf..e074000428 100644 --- a/.vscode/cmake-variants.yaml +++ b/.vscode/cmake-variants.yaml @@ -131,6 +131,16 @@ CONFIG: buildType: MinSizeRel settings: CONFIG: ark_cannode_canbootloader + ark_fmu-v6x_bootloader: + short: ark_fmu-v6x_bootloader + buildType: MinSizeRel + settings: + CONFIG: ark_fmu-v6x_bootloader + ark_fmu-v6x_default: + short: ark_fmu-v6x_default + buildType: MinSizeRel + settings: + CONFIG: ark_fmu-v6x_default atl_mantis-edu_default: short: atl_mantis-edu buildType: MinSizeRel diff --git a/Makefile b/Makefile index 5d5943dde7..856e7bb883 100644 --- a/Makefile +++ b/Makefile @@ -320,6 +320,7 @@ px4io_update: @$(MAKE) --no-print-directory px4_io-v2_default @$(MAKE) --no-print-directory cubepilot_io-v2_default # px4_io-v2_default + cp build/px4_io-v2_default/px4_io-v2_default.bin boards/ark/fmu-v6x/extras/px4_io-v2_default.bin cp build/px4_io-v2_default/px4_io-v2_default.bin boards/holybro/durandal-v1/extras/px4_io-v2_default.bin cp build/px4_io-v2_default/px4_io-v2_default.bin boards/holybro/pix32v5/extras/px4_io-v2_default.bin cp build/px4_io-v2_default/px4_io-v2_default.bin boards/mro/x21/extras/px4_io-v2_default.bin @@ -336,7 +337,7 @@ px4io_update: cp build/cubepilot_io-v2_default/cubepilot_io-v2_default.bin boards/cubepilot/cubeyellow/extras/cubepilot_io-v2_default.bin git status -bootloaders_update: cuav_nora_bootloader cuav_x7pro_bootloader cubepilot_cubeorange_bootloader holybro_durandal-v1_bootloader holybro_kakuteh7_bootloader matek_h743_bootloader matek_h743-mini_bootloader matek_h743-slim_bootloader modalai_fc-v2_bootloader mro_ctrl-zero-classic_bootloader mro_ctrl-zero-h7_bootloader mro_ctrl-zero-h7-oem_bootloader mro_pixracerpro_bootloader px4_fmu-v6c_bootloader px4_fmu-v6u_bootloader px4_fmu-v6x_bootloader +bootloaders_update: ark_fmu-v6x_bootloader cuav_nora_bootloader cuav_x7pro_bootloader cubepilot_cubeorange_bootloader holybro_durandal-v1_bootloader holybro_kakuteh7_bootloader matek_h743_bootloader matek_h743-mini_bootloader matek_h743-slim_bootloader modalai_fc-v2_bootloader mro_ctrl-zero-classic_bootloader mro_ctrl-zero-h7_bootloader mro_ctrl-zero-h7-oem_bootloader mro_pixracerpro_bootloader px4_fmu-v6c_bootloader px4_fmu-v6u_bootloader px4_fmu-v6x_bootloader git status .PHONY: coverity_scan diff --git a/Tools/upload.sh b/Tools/upload.sh index fe466da36b..25d41e389f 100755 --- a/Tools/upload.sh +++ b/Tools/upload.sh @@ -15,7 +15,7 @@ SERIAL_PORTS="/dev/tty.usbmodemPX*,/dev/tty.usbmodem*" fi if [ $SYSTYPE = "Linux" ]; then -SERIAL_PORTS="/dev/serial/by-id/*_PX4_*,/dev/serial/by-id/usb-3D_Robotics*,/dev/serial/by-id/usb-The_Autopilot*,/dev/serial/by-id/usb-Bitcraze*,/dev/serial/by-id/pci-Bitcraze*,/dev/serial/by-id/usb-Gumstix*,/dev/serial/by-id/usb-UVify*,/dev/serial/by-id/usb-ArduPilot*," +SERIAL_PORTS="/dev/serial/by-id/*_PX4_*,/dev/serial/by-id/usb-3D_Robotics*,/dev/serial/by-id/usb-The_Autopilot*,/dev/serial/by-id/usb-Bitcraze*,/dev/serial/by-id/pci-Bitcraze*,/dev/serial/by-id/usb-Gumstix*,/dev/serial/by-id/usb-UVify*,/dev/serial/by-id/usb-ArduPilot*,/dev/serial/by-id/ARK*," fi if [[ $SYSTYPE = *"CYGWIN"* ]]; then diff --git a/boards/ark/fmu-v6x/bootloader.px4board b/boards/ark/fmu-v6x/bootloader.px4board new file mode 100644 index 0000000000..19b6e662be --- /dev/null +++ b/boards/ark/fmu-v6x/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/fmu-v6x/default.px4board b/boards/ark/fmu-v6x/default.px4board new file mode 100644 index 0000000000..9068b52bd9 --- /dev/null +++ b/boards/ark/fmu-v6x/default.px4board @@ -0,0 +1,89 @@ +CONFIG_BOARD_TOOLCHAIN="arm-none-eabi" +CONFIG_BOARD_ARCHITECTURE="cortex-m7" +CONFIG_BOARD_ETHERNET=y +CONFIG_BOARD_SERIAL_GPS1="/dev/ttyS0" +CONFIG_BOARD_SERIAL_GPS2="/dev/ttyS7" +CONFIG_BOARD_SERIAL_TEL1="/dev/ttyS6" +CONFIG_BOARD_SERIAL_TEL2="/dev/ttyS4" +CONFIG_BOARD_SERIAL_TEL3="/dev/ttyS1" +CONFIG_DRIVERS_ADC_BOARD_ADC=y +CONFIG_DRIVERS_BAROMETER_BMP388=y +CONFIG_DRIVERS_BAROMETER_MS5611=y +CONFIG_DRIVERS_BATT_SMBUS=y +CONFIG_DRIVERS_CAMERA_CAPTURE=y +CONFIG_DRIVERS_CAMERA_TRIGGER=y +CONFIG_COMMON_DIFFERENTIAL_PRESSURE=y +CONFIG_COMMON_DISTANCE_SENSOR=y +CONFIG_DRIVERS_DSHOT=y +CONFIG_DRIVERS_GPS=y +CONFIG_DRIVERS_HEATER=y +CONFIG_DRIVERS_IMU_INVENSENSE_ICM42688P=y +CONFIG_DRIVERS_IMU_INVENSENSE_IIM42652=y +CONFIG_COMMON_LIGHT=y +CONFIG_COMMON_MAGNETOMETER=y +CONFIG_COMMON_OPTICAL_FLOW=y +CONFIG_DRIVERS_POWER_MONITOR_INA226=y +CONFIG_DRIVERS_POWER_MONITOR_INA228=y +CONFIG_DRIVERS_POWER_MONITOR_INA238=y +CONFIG_DRIVERS_PWM_OUT=y +CONFIG_DRIVERS_PX4IO=y +CONFIG_DRIVERS_RC_INPUT=y +CONFIG_DRIVERS_SAFETY_BUTTON=y +CONFIG_DRIVERS_TONE_ALARM=y +CONFIG_DRIVERS_UAVCAN=y +CONFIG_BOARD_UAVCAN_TIMER_OVERRIDE=2 +CONFIG_MODULES_AIRSPEED_SELECTOR=y +CONFIG_MODULES_CAMERA_FEEDBACK=y +CONFIG_MODULES_COMMANDER=y +CONFIG_MODULES_CONTROL_ALLOCATOR=y +CONFIG_MODULES_DATAMAN=y +CONFIG_MODULES_EKF2=y +CONFIG_MODULES_ESC_BATTERY=y +CONFIG_MODULES_EVENTS=y +CONFIG_MODULES_FLIGHT_MODE_MANAGER=y +CONFIG_MODULES_FW_ATT_CONTROL=y +CONFIG_MODULES_FW_AUTOTUNE_ATTITUDE_CONTROL=y +CONFIG_MODULES_FW_POS_CONTROL_L1=y +CONFIG_MODULES_GIMBAL=y +CONFIG_MODULES_GYRO_CALIBRATION=y +CONFIG_MODULES_GYRO_FFT=y +CONFIG_MODULES_LAND_DETECTOR=y +CONFIG_MODULES_LANDING_TARGET_ESTIMATOR=y +CONFIG_MODULES_LOAD_MON=y +CONFIG_MODULES_LOGGER=y +CONFIG_MODULES_MAG_BIAS_ESTIMATOR=y +CONFIG_MODULES_MANUAL_CONTROL=y +CONFIG_MODULES_MAVLINK=y +CONFIG_MODULES_MC_ATT_CONTROL=y +CONFIG_MODULES_MC_AUTOTUNE_ATTITUDE_CONTROL=y +CONFIG_MODULES_MC_HOVER_THRUST_ESTIMATOR=y +CONFIG_MODULES_MC_POS_CONTROL=y +CONFIG_MODULES_MC_RATE_CONTROL=y +CONFIG_MODULES_NAVIGATOR=y +CONFIG_MODULES_RC_UPDATE=y +CONFIG_MODULES_ROVER_POS_CONTROL=y +CONFIG_MODULES_SENSORS=y +CONFIG_MODULES_SIMULATION_PWM_OUT_SIM=y +CONFIG_MODULES_SIMULATION_SIMULATOR_SIH=y +CONFIG_MODULES_TEMPERATURE_COMPENSATION=y +CONFIG_MODULES_VTOL_ATT_CONTROL=y +CONFIG_SYSTEMCMDS_ACTUATOR_TEST=y +CONFIG_SYSTEMCMDS_BL_UPDATE=y +CONFIG_SYSTEMCMDS_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_NETMAN=y +CONFIG_SYSTEMCMDS_NSHTERM=y +CONFIG_SYSTEMCMDS_PARAM=y +CONFIG_SYSTEMCMDS_PERF=y +CONFIG_SYSTEMCMDS_REBOOT=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/fmu-v6x/extras/ark_fmu-v6x_bootloader.bin b/boards/ark/fmu-v6x/extras/ark_fmu-v6x_bootloader.bin new file mode 100755 index 0000000000000000000000000000000000000000..cdf31e487d31ca35d180d2339648cffed0d9e229 GIT binary patch literal 45172 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 R{OQju_{@w{2q>Zbe*l><7ta6y literal 0 HcmV?d00001 diff --git a/boards/ark/fmu-v6x/extras/px4_io-v2_default.bin b/boards/ark/fmu-v6x/extras/px4_io-v2_default.bin new file mode 100755 index 0000000000000000000000000000000000000000..51403914013d2f9cecc849dfda750db977a95303 GIT binary patch literal 39924 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 literal 0 HcmV?d00001 diff --git a/boards/ark/fmu-v6x/firmware.prototype b/boards/ark/fmu-v6x/firmware.prototype new file mode 100644 index 0000000000..39718c37a3 --- /dev/null +++ b/boards/ark/fmu-v6x/firmware.prototype @@ -0,0 +1,13 @@ +{ + "board_id": 57, + "magic": "ARKFWv1", + "description": "Firmware for the ARKFMUv6X board", + "image": "", + "build_time": 0, + "summary": "ARKFMUv6X", + "version": "0.1", + "image_size": 0, + "image_maxsize": 1966080, + "git_identity": "", + "board_revision": 0 +} diff --git a/boards/ark/fmu-v6x/init/rc.board_defaults b/boards/ark/fmu-v6x/init/rc.board_defaults new file mode 100644 index 0000000000..ba812e4b7b --- /dev/null +++ b/boards/ark/fmu-v6x/init/rc.board_defaults @@ -0,0 +1,21 @@ +#!/bin/sh +# +# board specific defaults +#------------------------------------------------------------------------------ + +# Mavlink ethernet (CFG 1000) +param set-default MAV_2_CONFIG 1000 +param set-default MAV_2_BROADCAST 1 +param set-default MAV_2_MODE 0 +param set-default MAV_2_RADIO_CTL 0 +param set-default MAV_2_RATE 100000 +param set-default MAV_2_REMOTE_PRT 14550 +param set-default MAV_2_UDP_PRT 14550 + +param set-default SENS_EN_INA238 0 +param set-default SENS_EN_INA228 0 +param set-default SENS_EN_INA226 1 + +param set-default SYS_USE_IO 1 + +safety_button start diff --git a/boards/ark/fmu-v6x/init/rc.board_sensors b/boards/ark/fmu-v6x/init/rc.board_sensors new file mode 100644 index 0000000000..2b66a4d021 --- /dev/null +++ b/boards/ark/fmu-v6x/init/rc.board_sensors @@ -0,0 +1,71 @@ +#!/bin/sh +# +# ARK FMUARKV6X specific board sensors init +#------------------------------------------------------------------------------ +set HAVE_PM2 yes + +if ver hwtypecmp ARKV6X005000 ARKV6X005001 ARKV6X005002 ARKV6X005003 ARKV6X005004 +then + set HAVE_PM2 no +fi +if param compare -s ADC_ADS1115_EN 1 +then + ads1115 start -X +else + board_adc start +fi + + +if param compare SENS_EN_INA226 1 +then + # Start Digital power monitors + ina226 -X -b 1 -t 1 -k start + + if [ $HAVE_PM2 = yes ] + then + ina226 -X -b 2 -t 2 -k start + fi +fi + +if param compare SENS_EN_INA228 1 +then + # Start Digital power monitors + ina228 -X -b 1 -t 1 -k start + if [ $HAVE_PM2 = yes ] + then + ina228 -X -b 2 -t 2 -k start + fi +fi + +if param compare SENS_EN_INA238 1 +then + # Start Digital power monitors + ina238 -X -b 1 -t 1 -k start + if [ $HAVE_PM2 = yes ] + then + ina238 -X -b 2 -t 2 -k start + fi +fi + +# Internal SPI bus IIM42652 +iim42652 -R 3 -s -b 1 start + +# Internal SPI bus ICM42688p +icm42688p -R 9 -s -b 2 start + +# Internal SPI bus ICM42688p +icm42688p -R 6 -s -b 3 start + +# Internal magnetometer on I2c +bmm150 -I start + +# External compass on GPS1/I2C1 (the 3rd external bus): standard Holybro Pixhawk 4 or CUAV V5 GPS/compass puck (with lights, safety button, and buzzer) +ist8310 -X -b 1 -R 10 start + +# Possible internal Baro +bmp388 -I start + +# Baro on I2C3 +ms5611 -X start + +unset HAVE_PM2 diff --git a/boards/ark/fmu-v6x/nuttx-config/Kconfig b/boards/ark/fmu-v6x/nuttx-config/Kconfig new file mode 100644 index 0000000000..bb33d3cfda --- /dev/null +++ b/boards/ark/fmu-v6x/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/fmu-v6x/nuttx-config/bootloader/defconfig b/boards/ark/fmu-v6x/nuttx-config/bootloader/defconfig new file mode 100644 index 0000000000..c74d5c18b1 --- /dev/null +++ b/boards/ark/fmu-v6x/nuttx-config/bootloader/defconfig @@ -0,0 +1,96 @@ +# +# 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_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/fmu-v6x/nuttx-config" +CONFIG_ARCH_BOARD_CUSTOM_DIR_RELPATH=y +CONFIG_ARCH_BOARD_CUSTOM_NAME="ark" +CONFIG_ARCH_CHIP="stm32h7" +CONFIG_ARCH_CHIP_STM32H753II=y +CONFIG_ARCH_CHIP_STM32H7=y +CONFIG_ARCH_INTERRUPTSTACK=512 +CONFIG_ARMV7M_BASEPRI_WAR=y +CONFIG_ARMV7M_ICACHE=y +CONFIG_ARMV7M_MEMCPY=y +CONFIG_ARMV7M_USEBASEPRI=y +CONFIG_BOARDCTL_RESET=y +CONFIG_BOARD_INITTHREAD_PRIORITY=254 +CONFIG_BOARD_LATE_INITIALIZE=y +CONFIG_BOARD_LOOPSPERMSEC=95150 +CONFIG_BOARD_RESET_ON_ASSERT=2 +CONFIG_C99_BOOL8=y +CONFIG_CDCACM=y +CONFIG_CDCACM_IFLOWCONTROL=y +CONFIG_CDCACM_PRODUCTID=0x0039 +CONFIG_CDCACM_PRODUCTSTR="ARK BL FMU v6X.x" +CONFIG_CDCACM_RXBUFSIZE=600 +CONFIG_CDCACM_TXBUFSIZE=12000 +CONFIG_CDCACM_VENDORID=0x3185 +CONFIG_CDCACM_VENDORSTR="ARK" +CONFIG_CLOCK_MONOTONIC=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEFAULT_SMALL=y +CONFIG_DISABLE_MQUEUE=y +CONFIG_DISABLE_PTHREAD=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_LIBC_FLOATINGPOINT=y +CONFIG_LIBC_LONG_LONG=y +CONFIG_LIBC_STRERROR=y +CONFIG_LIB_BOARDCTL=y +CONFIG_MEMSET_64BIT=y +CONFIG_MEMSET_OPTSPEED=y +CONFIG_PREALLOC_TIMERS=50 +CONFIG_PTHREAD_STACK_MIN=512 +CONFIG_RAM_SIZE=245760 +CONFIG_RAM_START=0x20010000 +CONFIG_RAW_BINARY=y +CONFIG_SDCLONE_DISABLE=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 +CONFIG_USERMAIN_STACKSIZE=2944 +CONFIG_USER_ENTRYPOINT="bootloader_main" diff --git a/boards/ark/fmu-v6x/nuttx-config/include/board.h b/boards/ark/fmu-v6x/nuttx-config/include/board.h new file mode 100644 index 0000000000..e4146c3237 --- /dev/null +++ b/boards/ark/fmu-v6x/nuttx-config/include/board.h @@ -0,0 +1,558 @@ +/************************************************************************************ + * nuttx-configs/px4_fmu-v6x/include/board.h + * + * Copyright (C) 2016-2022 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) * 60 = 960 MHz + * + * PLL1P = PLL1_VCO/2 = 960 MHz / 2 = 480 MHz + * PLL1Q = PLL1_VCO/4 = 960 MHz / 4 = 240 MHz + * PLL1R = PLL1_VCO/8 = 960 MHz / 8 = 120 MHz + */ + +#define STM32_PLLCFG_PLL1CFG (RCC_PLLCFGR_PLL1VCOSEL_WIDE | \ + RCC_PLLCFGR_PLL1RGE_4_8_MHZ | \ + RCC_PLLCFGR_DIVP1EN | \ + RCC_PLLCFGR_DIVQ1EN | \ + RCC_PLLCFGR_DIVR1EN) +#define STM32_PLLCFG_PLL1M RCC_PLLCKSELR_DIVM1(1) +#define STM32_PLLCFG_PLL1N RCC_PLL1DIVR_N1(60) +#define STM32_PLLCFG_PLL1P RCC_PLL1DIVR_P1(2) +#define STM32_PLLCFG_PLL1Q RCC_PLL1DIVR_Q1(4) +#define STM32_PLLCFG_PLL1R RCC_PLL1DIVR_R1(8) + +#define STM32_VCO1_FREQUENCY ((STM32_HSE_FREQUENCY / 1) * 60) +#define STM32_PLL1P_FREQUENCY (STM32_VCO1_FREQUENCY / 2) +#define STM32_PLL1Q_FREQUENCY (STM32_VCO1_FREQUENCY / 4) +#define STM32_PLL1R_FREQUENCY (STM32_VCO1_FREQUENCY / 8) + +/* PLL2 */ + +#define STM32_PLLCFG_PLL2CFG (RCC_PLLCFGR_PLL2VCOSEL_WIDE | \ + RCC_PLLCFGR_PLL2RGE_4_8_MHZ | \ + RCC_PLLCFGR_DIVP2EN | \ + RCC_PLLCFGR_DIVQ2EN | \ + RCC_PLLCFGR_DIVR2EN) +#define STM32_PLLCFG_PLL2M RCC_PLLCKSELR_DIVM2(4) +#define STM32_PLLCFG_PLL2N RCC_PLL2DIVR_N2(48) +#define STM32_PLLCFG_PLL2P RCC_PLL2DIVR_P2(2) +#define STM32_PLLCFG_PLL2Q RCC_PLL2DIVR_Q2(2) +#define STM32_PLLCFG_PLL2R RCC_PLL2DIVR_R2(2) + +#define STM32_VCO2_FREQUENCY ((STM32_HSE_FREQUENCY / 4) * 48) +#define STM32_PLL2P_FREQUENCY (STM32_VCO2_FREQUENCY / 2) +#define STM32_PLL2Q_FREQUENCY (STM32_VCO2_FREQUENCY / 2) +#define STM32_PLL2R_FREQUENCY (STM32_VCO2_FREQUENCY / 2) + +/* PLL3 */ + +#define STM32_PLLCFG_PLL3CFG (RCC_PLLCFGR_PLL3VCOSEL_WIDE | \ + RCC_PLLCFGR_PLL3RGE_4_8_MHZ | \ + RCC_PLLCFGR_DIVQ3EN) +#define STM32_PLLCFG_PLL3M RCC_PLLCKSELR_DIVM3(4) +#define STM32_PLLCFG_PLL3N RCC_PLL3DIVR_N3(48) +#define STM32_PLLCFG_PLL3P RCC_PLL3DIVR_P3(2) +#define STM32_PLLCFG_PLL3Q RCC_PLL3DIVR_Q3(4) +#define STM32_PLLCFG_PLL3R RCC_PLL3DIVR_R3(2) + +#define STM32_VCO3_FREQUENCY ((STM32_HSE_FREQUENCY / 4) * 48) +#define STM32_PLL3P_FREQUENCY (STM32_VCO3_FREQUENCY / 2) +#define STM32_PLL3Q_FREQUENCY (STM32_VCO3_FREQUENCY / 4) +#define STM32_PLL3R_FREQUENCY (STM32_VCO3_FREQUENCY / 2) + +/* SYSCLK = PLL1P = 480MHz + * CPUCLK = SYSCLK / 1 = 480 MHz + */ + +#define STM32_RCC_D1CFGR_D1CPRE (RCC_D1CFGR_D1CPRE_SYSCLK) +#define STM32_SYSCLK_FREQUENCY (STM32_PLL1P_FREQUENCY) +#define STM32_CPUCLK_FREQUENCY (STM32_SYSCLK_FREQUENCY / 1) + +/* Configure Clock Assignments */ + +/* AHB clock (HCLK) is SYSCLK/2 (240 MHz max) + * HCLK1 = HCLK2 = HCLK3 = HCLK4 = 240 + */ + +#define STM32_RCC_D1CFGR_HPRE RCC_D1CFGR_HPRE_SYSCLKd2 /* HCLK = SYSCLK / 2 */ +#define STM32_ACLK_FREQUENCY (STM32_CPUCLK_FREQUENCY / 2) /* ACLK in D1, HCLK3 in D1 */ +#define STM32_HCLK_FREQUENCY (STM32_CPUCLK_FREQUENCY / 2) /* HCLK in D2, HCLK4 in D3 */ +#define STM32_BOARD_HCLK STM32_HCLK_FREQUENCY /* same as above, to satisfy compiler */ + +/* APB1 clock (PCLK1) is HCLK/2 (120 MHz) */ + +#define STM32_RCC_D2CFGR_D2PPRE1 RCC_D2CFGR_D2PPRE1_HCLKd2 /* PCLK1 = HCLK / 2 */ +#define STM32_PCLK1_FREQUENCY (STM32_HCLK_FREQUENCY/2) + +/* APB2 clock (PCLK2) is HCLK/2 (120 MHz) */ + +#define STM32_RCC_D2CFGR_D2PPRE2 RCC_D2CFGR_D2PPRE2_HCLKd2 /* PCLK2 = HCLK / 2 */ +#define STM32_PCLK2_FREQUENCY (STM32_HCLK_FREQUENCY/2) + +/* APB3 clock (PCLK3) is HCLK/2 (120 MHz) */ + +#define STM32_RCC_D1CFGR_D1PPRE RCC_D1CFGR_D1PPRE_HCLKd2 /* PCLK3 = HCLK / 2 */ +#define STM32_PCLK3_FREQUENCY (STM32_HCLK_FREQUENCY/2) + +/* APB4 clock (PCLK4) is HCLK/4 (120 MHz) */ + +#define STM32_RCC_D3CFGR_D3PPRE RCC_D3CFGR_D3PPRE_HCLKd2 /* PCLK4 = HCLK / 2 */ +#define STM32_PCLK4_FREQUENCY (STM32_HCLK_FREQUENCY/2) + +/* Timer clock frequencies */ + +/* Timers driven from APB1 will be twice PCLK1 */ + +#define STM32_APB1_TIM2_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM3_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM4_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM5_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM6_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM7_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM12_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM13_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_APB1_TIM14_CLKIN (2*STM32_PCLK1_FREQUENCY) + +/* Timers driven from APB2 will be twice PCLK2 */ + +#define STM32_APB2_TIM1_CLKIN (2*STM32_PCLK2_FREQUENCY) +#define STM32_APB2_TIM8_CLKIN (2*STM32_PCLK2_FREQUENCY) +#define STM32_APB2_TIM15_CLKIN (2*STM32_PCLK2_FREQUENCY) +#define STM32_APB2_TIM16_CLKIN (2*STM32_PCLK2_FREQUENCY) +#define STM32_APB2_TIM17_CLKIN (2*STM32_PCLK2_FREQUENCY) + +/* Kernel Clock Configuration + * + * Note: look at Table 54 in ST Manual + */ + +/* I2C123 clock source */ + +#define STM32_RCC_D2CCIP2R_I2C123SRC RCC_D2CCIP2R_I2C123SEL_HSI + +/* I2C4 clock source */ + +#define STM32_RCC_D3CCIPR_I2C4SRC RCC_D3CCIPR_I2C4SEL_HSI + +/* SPI123 clock source */ + +#define STM32_RCC_D2CCIP1R_SPI123SRC RCC_D2CCIP1R_SPI123SEL_PLL2 + +/* SPI45 clock source */ + +#define STM32_RCC_D2CCIP1R_SPI45SRC RCC_D2CCIP1R_SPI45SEL_PLL2 + +/* SPI6 clock source */ + +#define STM32_RCC_D3CCIPR_SPI6SRC RCC_D3CCIPR_SPI6SEL_PLL2 + +/* USB 1 and 2 clock source */ + +#define STM32_RCC_D2CCIP2R_USBSRC RCC_D2CCIP2R_USBSEL_PLL3 + +/* ADC 1 2 3 clock source */ + +#define STM32_RCC_D3CCIPR_ADCSEL RCC_D3CCIPR_ADCSEL_PLL2 + +/* FDCAN 1 2 clock source */ + +#define STM32_RCC_D2CCIP1R_FDCANSEL RCC_D2CCIP1R_FDCANSEL_HSE /* FDCAN 1 2 clock source */ + +#define STM32_FDCANCLK STM32_HSE_FREQUENCY + +/* FLASH wait states + * + * ------------ ---------- ----------- + * Vcore MAX ACLK WAIT STATES + * ------------ ---------- ----------- + * 1.15-1.26 V 70 MHz 0 + * (VOS1 level) 140 MHz 1 + * 210 MHz 2 + * 1.05-1.15 V 55 MHz 0 + * (VOS2 level) 110 MHz 1 + * 165 MHz 2 + * 220 MHz 3 + * 0.95-1.05 V 45 MHz 0 + * (VOS3 level) 90 MHz 1 + * 135 MHz 2 + * 180 MHz 3 + * 225 MHz 4 + * ------------ ---------- ----------- + */ + +#define BOARD_FLASH_WAITSTATES 2 + +/* SDMMC definitions ********************************************************/ + +/* Init 400kHz, freq = PLL1Q/(2*div) div = PLL1Q/(2*freq) */ + +#define STM32_SDMMC_INIT_CLKDIV (300 << STM32_SDMMC_CLKCR_CLKDIV_SHIFT) + +/* 25 MHz Max for now, 25 mHZ = PLL1Q/(2*div), div = PLL1Q/(2*freq) + * div = 4.8 = 240 / 50, So round up to 5 for default speed 24 MB/s + */ + +#if defined(CONFIG_STM32H7_SDMMC_XDMA) || defined(CONFIG_STM32H7_SDMMC_IDMA) +# define STM32_SDMMC_MMCXFR_CLKDIV (5 << STM32_SDMMC_CLKCR_CLKDIV_SHIFT) +#else +# define STM32_SDMMC_MMCXFR_CLKDIV (100 << STM32_SDMMC_CLKCR_CLKDIV_SHIFT) +#endif +#if defined(CONFIG_STM32H7_SDMMC_XDMA) || defined(CONFIG_STM32H7_SDMMC_IDMA) +# define STM32_SDMMC_SDXFR_CLKDIV (5 << STM32_SDMMC_CLKCR_CLKDIV_SHIFT) +#else +# define STM32_SDMMC_SDXFR_CLKDIV (100 << STM32_SDMMC_CLKCR_CLKDIV_SHIFT) +#endif + +#define STM32_SDMMC_CLKCR_EDGE STM32_SDMMC_CLKCR_NEGEDGE + +/* LED definitions ******************************************************************/ +/* The 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_USART2_RTS GPIO_USART2_RTS_2 /* PD4 */ +#define GPIO_USART2_CTS GPIO_USART2_CTS_NSS_2 /* PD3 */ + +#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 */ +// GPIO_UART5_CTS No remap /* 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 /* PE10 */ + +#define GPIO_UART8_RX GPIO_UART8_RX_1 /* PE0 */ +#define GPIO_UART8_TX GPIO_UART8_TX_1 /* PE1 */ + + +/* CAN + * + * CAN1 is routed to transceiver. + * CAN2 is routed to transceiver. + */ +#define GPIO_CAN1_RX GPIO_CAN1_RX_3 /* PD0 */ +#define GPIO_CAN1_TX GPIO_CAN1_TX_3 /* PD1 */ +#define GPIO_CAN2_RX GPIO_CAN2_RX_1 /* PB12 */ +#define GPIO_CAN2_TX GPIO_CAN2_TX_1 /* PB13 */ + +/* SPI + * SPI1 is sensors1 + * SPI2 is sensors2 + * SPI3 is sensors3 + * SPI4 is Not Used + * SPI5 is FRAM + * 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_SPI2_MISO GPIO_SPI2_MISO_3 /* PI2 */ +#define GPIO_SPI2_MOSI GPIO_SPI2_MOSI_4 /* PI3 */ +#define GPIO_SPI2_SCK ADJ_SLEW_RATE(GPIO_SPI2_SCK_6) /* PI1 */ + +#define GPIO_SPI3_MISO GPIO_SPI3_MISO_2 /* PC11 */ +#define GPIO_SPI3_MOSI GPIO_SPI3_MOSI_3 /* PB2 */ +#define GPIO_SPI3_SCK ADJ_SLEW_RATE(GPIO_SPI3_SCK_2) /* PC10 */ + +#define GPIO_SPI5_MISO GPIO_SPI5_MISO_2 /* PH7 */ +#define GPIO_SPI5_MOSI GPIO_SPI5_MOSI_1 /* PF11 */ +#define GPIO_SPI5_SCK ADJ_SLEW_RATE(GPIO_SPI5_SCK_1) /* PF7 */ + +#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_I2C3_SCL GPIO_I2C3_SCL_1 /* PA8 */ +#define GPIO_I2C3_SDA GPIO_I2C3_SDA_2 /* PH8 */ + +#define GPIO_I2C3_SCL_GPIO (GPIO_OUTPUT | GPIO_OPENDRAIN |GPIO_SPEED_50MHz | GPIO_OUTPUT_SET | GPIO_PORTA | GPIO_PIN8) +#define GPIO_I2C3_SDA_GPIO (GPIO_OUTPUT | GPIO_OPENDRAIN |GPIO_SPEED_50MHz | GPIO_OUTPUT_SET | GPIO_PORTH | GPIO_PIN8) + +#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 */ + +/* The STM32 H7 connects to a TI DP83848TSQ/NOPB + * using RMII + * + * STM32 H7 BOARD DP83848TSQ/NOPB + * GPIO SIGNAL PIN NAME + * -------- ------------ ------------- + * PA7 ETH_CRS_DV CRS_DV + * PC1 ETH_MDC MDC + * PA2 ETH_MDIO MDIO + * PA1 ETH_REF_CL X1 + * PC4 ETH_RXD0 RX_D0 + * PC5 ETH_RXD1 RX_D1 + * PB11 ETH_TX_EN TX_EN + * PG13 ETH_TXD0 TX_D0 + * PG12 ETH_TXD1 TX_D1 + * + * The PHY address is 1, since COL/PHYAD0 features a pull up. + */ + +#define GPIO_ETH_RMII_TX_EN GPIO_ETH_RMII_TX_EN_1 /* PB11 */ +#define GPIO_ETH_RMII_TXD0 GPIO_ETH_RMII_TXD0_2 /* PG13 */ +#define GPIO_ETH_RMII_TXD1 GPIO_ETH_RMII_TXD1_2 /* PG12 */ + + +/* 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_9 (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTE|GPIO_PIN11) /* PE11 CAP1 */ + +# 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/fmu-v6x/nuttx-config/include/board_dma_map.h b/boards/ark/fmu-v6x/nuttx-config/include/board_dma_map.h new file mode 100644 index 0000000000..f1a94934de --- /dev/null +++ b/boards/ark/fmu-v6x/nuttx-config/include/board_dma_map.h @@ -0,0 +1,87 @@ +/**************************************************************************** + * + * 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. + * + ****************************************************************************/ + +#pragma once + +// DMAMUX1 Using at most 8 Channels on DMA1 -------- Assigned +// V + +#define DMAMAP_SPI1_RX DMAMAP_DMA12_SPI1RX_0 /* 1 DMA1:37 ICM-20649 */ +#define DMAMAP_SPI1_TX DMAMAP_DMA12_SPI1TX_0 /* 2 DMA1:38 ICM-20649 */ + +#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_USART2_RX DMAMAP_DMA12_USART2RX_0 /* DMA1:43 Telem3 */ +//#define DMAMAP_USART2_TX DMAMAP_DMA12_USART2TX_0 /* DMA1:44 Telem3 */ + +//#define DMAMAP_USART3_RX DMAMAP_DMA12_USART3RX_0 /* DMA1:45 DEBUG */ +//#define DMAMAP_USART3_TX DMAMAP_DMA12_USART3TX_0 /* DMA1:46 DEBUG */ + +//#define DMAMAP_UART4_RX DMAMAP_DMA12_UART4RX_0 /* DMA1:63 EXT2 */ +//#define DMAMAP_UART4_TX DMAMAP_DMA12_UART4TX_0 /* DMA1:64 EXT2 */ + +#define DMAMAP_USART6_RX DMAMAP_DMA12_USART6RX_0 /* 5 DMA1:71 PX4IO */ +#define DMAMAP_USART6_TX DMAMAP_DMA12_USART6TX_0 /* 6 DMA1:72 PX4IO */ + +// Assigned in timer_config.cpp + +// Timer 4 /* 7 DMA1:32 TIM4UP */ +// Timer 5 /* 8 DMA1:50 TIM5UP */ + +// DMAMUX2 Using at most 8 Channels on DMA2 -------- Assigned +// V + +#define DMAMAP_SPI3_RX DMAMAP_DMA12_SPI3RX_1 /* 1 DMA2:61 BMI088 */ +#define DMAMAP_SPI3_TX DMAMAP_DMA12_SPI3TX_1 /* 2 DMA2:62 BMI088 */ + +#define DMAMAP_USART3_RX DMAMAP_DMA12_USART3RX_1 /* 3 DMA2:45 DEBUG */ +#define DMAMAP_USART3_TX DMAMAP_DMA12_USART3TX_1 /* 4 DMA2:46 DEBUG */ + +#define DMAMAP_UART5_RX DMAMAP_DMA12_UART5RX_1 /* 5 DMA2:65 TELEM2 */ +#define DMAMAP_UART5_TX DMAMAP_DMA12_UART5TX_1 /* 6 DMA2:66 TELEM2 */ + +#define DMAMAP_UART7_RX DMAMAP_DMA12_UART7RX_1 /* 7 DMA1:79 TELEM1 */ +#define DMAMAP_UART7_TX DMAMAP_DMA12_UART7TX_1 /* 8 DMA1:80 TELEM1 */ + +//#define DMAMAP_UART8_RX DMAMAP_DMA12_UART8RX_1 /* DMA1:81 GPS2 */ +//#define DMAMAP_UART8_TX DMAMAP_DMA12_UART8TX_1 /* DMA1:82 GPS2 */ + +// 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/fmu-v6x/nuttx-config/nsh/defconfig b/boards/ark/fmu-v6x/nuttx-config/nsh/defconfig new file mode 100644 index 0000000000..d7d30f72c2 --- /dev/null +++ b/boards/ark/fmu-v6x/nuttx-config/nsh/defconfig @@ -0,0 +1,295 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_DISABLE_ENVIRON is not set +# CONFIG_DISABLE_PSEUDOFS_OPERATIONS is not set +# CONFIG_MMCSD_HAVE_CARDDETECT is not set +# CONFIG_MMCSD_HAVE_WRITEPROTECT is not set +# CONFIG_MMCSD_MMCSUPPORT is not set +# CONFIG_MMCSD_SPI is not set +# CONFIG_NSH_DISABLEBG is not set +# CONFIG_NSH_DISABLESCRIPT is not set +# CONFIG_NSH_DISABLE_ARP is not set +# CONFIG_NSH_DISABLE_DF is not set +# CONFIG_NSH_DISABLE_EXEC is not set +# CONFIG_NSH_DISABLE_GET is not set +# CONFIG_NSH_DISABLE_ITEF is not set +# CONFIG_NSH_DISABLE_LOOPS is not set +# CONFIG_NSH_DISABLE_MKFATFS is not set +# CONFIG_NSH_DISABLE_SEMICOLON is not set +# CONFIG_NSH_DISABLE_TIME is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD_CUSTOM=y +CONFIG_ARCH_BOARD_CUSTOM_DIR="../../../../boards/ark/fmu-v6x/nuttx-config" +CONFIG_ARCH_BOARD_CUSTOM_DIR_RELPATH=y +CONFIG_ARCH_BOARD_CUSTOM_NAME="ark" +CONFIG_ARCH_CHIP="stm32h7" +CONFIG_ARCH_CHIP_STM32H753II=y +CONFIG_ARCH_CHIP_STM32H7=y +CONFIG_ARCH_INTERRUPTSTACK=512 +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARMV7M_BASEPRI_WAR=y +CONFIG_ARMV7M_DCACHE=y +CONFIG_ARMV7M_DTCM=y +CONFIG_ARMV7M_ICACHE=y +CONFIG_ARMV7M_MEMCPY=y +CONFIG_ARMV7M_USEBASEPRI=y +CONFIG_ARM_MPU_EARLY_RESET=y +CONFIG_BOARDCTL_RESET=y +CONFIG_BOARD_CRASHDUMP=y +CONFIG_BOARD_LOOPSPERMSEC=95751 +CONFIG_BOARD_RESET_ON_ASSERT=2 +CONFIG_BUILTIN=y +CONFIG_C99_BOOL8=y +CONFIG_CDCACM=y +CONFIG_CDCACM_IFLOWCONTROL=y +CONFIG_CDCACM_PRODUCTID=0x0039 +CONFIG_CDCACM_PRODUCTSTR="ARK FMU v6X.x" +CONFIG_CDCACM_RXBUFSIZE=600 +CONFIG_CDCACM_TXBUFSIZE=12000 +CONFIG_CDCACM_VENDORID=0x3185 +CONFIG_CDCACM_VENDORSTR="ARK" +CONFIG_CLOCK_MONOTONIC=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_HARDFAULT_ALERT=y +CONFIG_DEBUG_MEMFAULT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEFAULT_SMALL=y +CONFIG_DEV_FIFO_SIZE=0 +CONFIG_DEV_PIPE_MAXSIZE=1024 +CONFIG_DEV_PIPE_SIZE=70 +CONFIG_ETH0_PHY_LAN8742A=y +CONFIG_EXPERIMENTAL=y +CONFIG_FAT_DMAMEMORY=y +CONFIG_FAT_LCNAMES=y +CONFIG_FAT_LFN=y +CONFIG_FAT_LFN_ALIAS_HASH=y +CONFIG_FDCLONE_STDIO=y +CONFIG_FSUTILS_IPCFG=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_IOB_NBUFFERS=24 +CONFIG_IOB_THROTTLE=0 +CONFIG_IPCFG_BINARY=y +CONFIG_IPCFG_CHARDEV=y +CONFIG_IPCFG_PATH="/fs/mtd_net" +CONFIG_LIBC_FLOATINGPOINT=y +CONFIG_LIBC_LONG_LONG=y +CONFIG_LIBC_STRERROR=y +CONFIG_MEMSET_64BIT=y +CONFIG_MEMSET_OPTSPEED=y +CONFIG_MMCSD=y +CONFIG_MMCSD_SDIO=y +CONFIG_MMCSD_SDIOWAIT_WRCOMPLETE=y +CONFIG_MM_REGIONS=4 +CONFIG_MTD=y +CONFIG_MTD_BYTE_WRITE=y +CONFIG_MTD_PARTITION=y +CONFIG_MTD_PROGMEM=y +CONFIG_MTD_RAMTRON=y +CONFIG_NAME_MAX=40 +CONFIG_NET=y +CONFIG_NETDB_DNSCLIENT=y +CONFIG_NETDB_DNSCLIENT_ENTRIES=8 +CONFIG_NETDB_DNSSERVER_NOADDR=y +CONFIG_NETDEV_PHY_IOCTL=y +CONFIG_NETINIT_DHCPC=y +CONFIG_NETINIT_DNS=y +CONFIG_NETINIT_DNSIPADDR=0XC0A800FE +CONFIG_NETINIT_DRIPADDR=0XC0A800FE +CONFIG_NETINIT_THREAD=y +CONFIG_NETINIT_THREAD_PRIORITY=49 +CONFIG_NETUTILS_TELNETD=y +CONFIG_NET_ARP_IPIN=y +CONFIG_NET_ARP_SEND=y +CONFIG_NET_BROADCAST=y +CONFIG_NET_ETH_PKTSIZE=1518 +CONFIG_NET_ICMP=y +CONFIG_NET_ICMP_SOCKET=y +CONFIG_NET_SOLINGER=y +CONFIG_NET_TCP=y +CONFIG_NET_TCPBACKLOG=y +CONFIG_NET_TCP_DELAYED_ACK=y +CONFIG_NET_TCP_WRITE_BUFFERS=y +CONFIG_NET_UDP=y +CONFIG_NET_UDP_CHECKSUMS=y +CONFIG_NET_UDP_WRITE_BUFFERS=y +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_TELNET=y +CONFIG_NSH_TELNET_LOGIN=y +CONFIG_NSH_VARS=y +CONFIG_OTG_ID_GPIO_DISABLE=y +CONFIG_PIPES=y +CONFIG_PREALLOC_TIMERS=50 +CONFIG_PRIORITY_INHERITANCE=y +CONFIG_PTHREAD_MUTEX_ROBUST=y +CONFIG_PTHREAD_STACK_MIN=512 +CONFIG_RAMTRON_SETSPEED=y +CONFIG_RAM_SIZE=245760 +CONFIG_RAM_START=0x20010000 +CONFIG_RAW_BINARY=y +CONFIG_READLINE_CMD_HISTORY=y +CONFIG_READLINE_TABCOMPLETION=y +CONFIG_RTC_DATETIME=y +CONFIG_SCHED_ATEXIT=y +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_HPWORKPRIORITY=249 +CONFIG_SCHED_HPWORKSTACKSIZE=1280 +CONFIG_SCHED_INSTRUMENTATION=y +CONFIG_SCHED_INSTRUMENTATION_EXTERNAL=y +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_LPWORKPRIORITY=50 +CONFIG_SCHED_LPWORKSTACKSIZE=1632 +CONFIG_SCHED_WAITPID=y +CONFIG_SDCLONE_DISABLE=y +CONFIG_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_ETHMAC=y +CONFIG_STM32H7_FLASH_OVERRIDE_I=y +CONFIG_STM32H7_FLOWCONTROL_BROKEN=y +CONFIG_STM32H7_I2C1=y +CONFIG_STM32H7_I2C2=y +CONFIG_STM32H7_I2C3=y +CONFIG_STM32H7_I2C4=y +CONFIG_STM32H7_I2C_DYNTIMEO=y +CONFIG_STM32H7_I2C_DYNTIMEO_STARTSTOP=10 +CONFIG_STM32H7_OTGFS=y +CONFIG_STM32H7_PHYSR=31 +CONFIG_STM32H7_PHYSR_100MBPS=0x8 +CONFIG_STM32H7_PHYSR_FULLDUPLEX=0x10 +CONFIG_STM32H7_PHYSR_MODE=0x10 +CONFIG_STM32H7_PHYSR_SPEED=0x8 +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_SPI2=y +CONFIG_STM32H7_SPI2_DMA=y +CONFIG_STM32H7_SPI2_DMA_BUFFER=4096 +CONFIG_STM32H7_SPI3=y +CONFIG_STM32H7_SPI3_DMA=y +CONFIG_STM32H7_SPI3_DMA_BUFFER=1024 +CONFIG_STM32H7_SPI5=y +CONFIG_STM32H7_SPI6=y +CONFIG_STM32H7_SPI6_DMA=y +CONFIG_STM32H7_SPI6_DMA_BUFFER=1024 +CONFIG_STM32H7_SPI_DMA=y +CONFIG_STM32H7_TIM12=y +CONFIG_STM32H7_TIM1=y +CONFIG_STM32H7_TIM4=y +CONFIG_STM32H7_TIM5=y +CONFIG_STM32H7_UART4=y +CONFIG_STM32H7_UART5=y +CONFIG_STM32H7_UART7=y +CONFIG_STM32H7_UART8=y +CONFIG_STM32H7_USART1=y +CONFIG_STM32H7_USART2=y +CONFIG_STM32H7_USART3=y +CONFIG_STM32H7_USART6=y +CONFIG_STM32H7_USART_BREAKS=y +CONFIG_STM32H7_USART_INVERT=y +CONFIG_STM32H7_USART_SINGLEWIRE=y +CONFIG_STM32H7_USART_SWAP=y +CONFIG_SYSTEM_CDCACM=y +CONFIG_SYSTEM_DHCPC_RENEW=y +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_PING=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_TXBUFSIZE=3000 +CONFIG_UART5_TXDMA=y +CONFIG_UART7_BAUD=57600 +CONFIG_UART7_IFLOWCONTROL=y +CONFIG_UART7_OFLOWCONTROL=y +CONFIG_UART7_RXBUFSIZE=600 +CONFIG_UART7_RXDMA=y +CONFIG_UART7_TXBUFSIZE=3000 +CONFIG_UART7_TXDMA=y +CONFIG_UART8_BAUD=57600 +CONFIG_UART8_RXBUFSIZE=600 +CONFIG_UART8_TXBUFSIZE=1500 +CONFIG_USART1_BAUD=57600 +CONFIG_USART1_RXBUFSIZE=600 +CONFIG_USART1_TXBUFSIZE=1500 +CONFIG_USART2_BAUD=57600 +CONFIG_USART2_IFLOWCONTROL=y +CONFIG_USART2_OFLOWCONTROL=y +CONFIG_USART2_RXBUFSIZE=600 +CONFIG_USART2_TXBUFSIZE=3000 +CONFIG_USART3_BAUD=57600 +CONFIG_USART3_RXBUFSIZE=180 +CONFIG_USART3_RXDMA=y +CONFIG_USART3_SERIAL_CONSOLE=y +CONFIG_USART3_TXBUFSIZE=1500 +CONFIG_USART3_TXDMA=y +CONFIG_USART6_BAUD=57600 +CONFIG_USART6_RXBUFSIZE=600 +CONFIG_USART6_TXBUFSIZE=1500 +CONFIG_USBDEV=y +CONFIG_USBDEV_BUSPOWERED=y +CONFIG_USBDEV_MAXPOWER=500 +CONFIG_USEC_PER_TICK=1000 +CONFIG_USERMAIN_STACKSIZE=2944 +CONFIG_USER_ENTRYPOINT="nsh_main" +CONFIG_WATCHDOG=y diff --git a/boards/ark/fmu-v6x/nuttx-config/scripts/bootloader_script.ld b/boards/ark/fmu-v6x/nuttx-config/scripts/bootloader_script.ld new file mode 100644 index 0000000000..5b1bb4cb05 --- /dev/null +++ b/boards/ark/fmu-v6x/nuttx-config/scripts/bootloader_script.ld @@ -0,0 +1,215 @@ +/**************************************************************************** + * scripts/script.ld + * + * Copyright (C) 2016, 2022 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 STM32H753II has 2048Kb of main FLASH memory. + * The flash memory is partitioned into a User Flash memory and a System + * Flash memory. Each of these memories has two banks: + * + * 1) User Flash memory: + * + * Bank 1: Start address 0x0800:0000 to 0x080F:FFFF with 8 sectors, 128Kb each + * Bank 2: Start address 0x0810:0000 to 0x081F:FFFF with 8 sectors, 128Kb each + * + * 2) System Flash memory: + * + * Bank 1: Start address 0x1FF0:0000 to 0x1FF1:FFFF with 1 x 128Kb sector + * Bank 1: Start address 0x1FF4:0000 to 0x1FF5:FFFF with 1 x 128Kb sector + * + * 3) User option bytes for user configuration, only in Bank 1. + * + * In the STM32H743II, two different boot spaces can be selected through + * the BOOT pin and the boot base address programmed in the BOOT_ADD0 and + * BOOT_ADD1 option bytes: + * + * 1) BOOT=0: Boot address defined by user option byte BOOT_ADD0[15:0]. + * ST programmed value: Flash memory at 0x0800:0000 + * 2) BOOT=1: Boot address defined by user option byte BOOT_ADD1[15:0]. + * ST programmed value: System bootloader at 0x1FF0:0000 + * + * The 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/fmu-v6x/nuttx-config/scripts/script.ld b/boards/ark/fmu-v6x/nuttx-config/scripts/script.ld new file mode 100644 index 0000000000..d06a7d7aa7 --- /dev/null +++ b/boards/ark/fmu-v6x/nuttx-config/scripts/script.ld @@ -0,0 +1,229 @@ +/**************************************************************************** + * scripts/script.ld + * + * Copyright (C) 2016, 2022 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 STM32H753II has 2048Kb of main FLASH memory. + * The flash memory is partitioned into a User Flash memory and a System + * Flash memory. Each of these memories has two banks: + * + * 1) User Flash memory: + * + * Bank 1: Start address 0x0800:0000 to 0x080F:FFFF with 8 sectors, 128Kb each + * Bank 2: Start address 0x0810:0000 to 0x081F:FFFF with 8 sectors, 128Kb each + * + * 2) System Flash memory: + * + * Bank 1: Start address 0x1FF0:0000 to 0x1FF1:FFFF with 1 x 128Kb sector + * Bank 1: Start address 0x1FF4:0000 to 0x1FF5:FFFF with 1 x 128Kb sector + * + * 3) User option bytes for user configuration, only in Bank 1. + * + * In the STM32H743II, two different boot spaces can be selected through + * the BOOT pin and the boot base address programmed in the BOOT_ADD0 and + * BOOT_ADD1 option bytes: + * + * 1) BOOT=0: Boot address defined by user option byte BOOT_ADD0[15:0]. + * ST programmed value: Flash memory at 0x0800:0000 + * 2) BOOT=1: Boot address defined by user option byte BOOT_ADD1[15:0]. + * ST programmed value: System bootloader at 0x1FF0:0000 + * + * The 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 = 1920K + + DTCM1_RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 64K + DTCM2_RAM (rwx) : ORIGIN = 0x20010000, LENGTH = 64K + AXI_SRAM (rwx) : ORIGIN = 0x24000000, LENGTH = 512K /* D1 domain AXI bus */ + SRAM1 (rwx) : ORIGIN = 0x30000000, LENGTH = 128K /* D2 domain AHB bus */ + SRAM2 (rwx) : ORIGIN = 0x30020000, LENGTH = 128K /* D2 domain AHB bus */ + SRAM3 (rwx) : ORIGIN = 0x30040000, LENGTH = 32K /* D2 domain AHB bus */ + SRAM4 (rwx) : ORIGIN = 0x38000000, LENGTH = 64K /* D3 domain */ + BKPRAM (rwx) : ORIGIN = 0x38800000, LENGTH = 4K +} + +OUTPUT_ARCH(arm) +EXTERN(_vectors) +ENTRY(_stext) + +/* + * Ensure that abort() is present in the final object. The exception handling + * code pulled in by libgcc.a requires it (and that code cannot be easily avoided). + */ +EXTERN(abort) +EXTERN(_bootdelay_signature) +EXTERN(board_get_manifest) + +SECTIONS +{ + .text : { + _stext = ABSOLUTE(.); + *(.vectors) + . = ALIGN(32); + /* + This signature provides the bootloader with a way to delay booting + */ + _bootdelay_signature = ABSOLUTE(.); + FILL(0xffecc2925d7d05c5) + . += 8; + *(.text .text.*) + *(.fixup) + *(.gnu.warning) + *(.rodata .rodata.*) + *(.gnu.linkonce.t.*) + *(.glue_7) + *(.glue_7t) + *(.got) + *(.gcc_except_table) + *(.gnu.linkonce.r.*) + _etext = ABSOLUTE(.); + + } > FLASH + + /* + * Init functions (static constructors and the like) + */ + .init_section : { + _sinit = ABSOLUTE(.); + KEEP(*(.init_array .init_array.*)) + _einit = ABSOLUTE(.); + } > FLASH + + + .ARM.extab : { + *(.ARM.extab*) + } > FLASH + + __exidx_start = ABSOLUTE(.); + .ARM.exidx : { + *(.ARM.exidx*) + } > FLASH + __exidx_end = ABSOLUTE(.); + + _eronly = ABSOLUTE(.); + + .data : { + _sdata = ABSOLUTE(.); + *(.data .data.*) + *(.gnu.linkonce.d.*) + CONSTRUCTORS + _edata = ABSOLUTE(.); + + /* Pad out last section as the STM32H7 Flash write size is 256 bits. 32 bytes */ + . = ALIGN(16); + FILL(0xffff) + . += 16; + } > AXI_SRAM AT > FLASH = 0xffff + + .bss : { + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _ebss = ABSOLUTE(.); + } > AXI_SRAM + + /* Emit the the D3 power domain section for locating BDMA data */ + + .sram4_reserve (NOLOAD) : + { + *(.sram4) + . = ALIGN(4); + _sram4_heap_start = ABSOLUTE(.); + } > SRAM4 + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/boards/ark/fmu-v6x/src/CMakeLists.txt b/boards/ark/fmu-v6x/src/CMakeLists.txt new file mode 100644 index 0000000000..c84d6f291c --- /dev/null +++ b/boards/ark/fmu-v6x/src/CMakeLists.txt @@ -0,0 +1,71 @@ +############################################################################ +# +# 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_library(drivers_board + bootloader_main.c + usb.c + ) + target_link_libraries(drivers_board + PRIVATE + nuttx_arch # sdio + nuttx_drivers # sdio + bootloader + ) + target_include_directories(drivers_board PRIVATE ${PX4_SOURCE_DIR}/platforms/nuttx/src/bootloader/common) + +else() + add_library(drivers_board + can.c + i2c.cpp + init.c + led.c + mtd.cpp + manifest.c + sdio.c + spi.cpp + timer_config.cpp + usb.c + ) + add_dependencies(drivers_board arch_board_hw_info) + + target_link_libraries(drivers_board + PRIVATE + arch_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/fmu-v6x/src/board_config.h b/boards/ark/fmu-v6x/src/board_config.h new file mode 100644 index 0000000000..12d526f142 --- /dev/null +++ b/boards/ark/fmu-v6x/src/board_config.h @@ -0,0 +1,524 @@ +/**************************************************************************** + * + * Copyright (c) 2016-2022 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file board_config.h + * + * ARKFMU-v6x internal definitions + */ + +#pragma once + +/**************************************************************************************************** + * Included Files + ****************************************************************************************************/ + +#include +#include +#include + + +#include + +/**************************************************************************************************** + * Definitions + ****************************************************************************************************/ + +#undef TRACE_PINS + +/* PX4IO connection configuration */ + +#define BOARD_USES_PX4IO_VERSION 2 +#define PX4IO_SERIAL_DEVICE "/dev/ttyS5" +#define PX4IO_SERIAL_TX_GPIO GPIO_USART6_TX +#define PX4IO_SERIAL_RX_GPIO GPIO_USART6_RX +#define PX4IO_SERIAL_BASE STM32_USART6_BASE +#define PX4IO_SERIAL_VECTOR STM32_IRQ_USART6 +#define PX4IO_SERIAL_TX_DMAMAP DMAMAP_USART6_TX +#define PX4IO_SERIAL_RX_DMAMAP DMAMAP_USART6_RX +#define PX4IO_SERIAL_RCC_REG STM32_RCC_APB2ENR +#define PX4IO_SERIAL_RCC_EN RCC_APB2ENR_USART6EN +#define PX4IO_SERIAL_CLOCK STM32_PCLK2_FREQUENCY +#define PX4IO_SERIAL_BITRATE 1500000 /* 1.5Mbps -> max rate for IO */ + +/* Configuration ************************************************************************************/ + +#define BOARD_HAS_LTC44XX_VALIDS 2 // N Bricks +#define BOARD_HAS_USB_VALID 1 // LTC Has USB valid +#define BOARD_HAS_NBAT_V 2d // 2 Digital Voltage +#define BOARD_HAS_NBAT_I 2d // 2 Digital Current + +/* 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 + + +/* SPI */ + +#define SPI6_nRESET_EXTERNAL1 /* PF10 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTF|GPIO_PIN10) +#define GPIO_SYNC /* PE9 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_100MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTE|GPIO_PIN9) + +/* 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_SCALED_VDD_3V3_SENSORS1_CHANNEL /* PA0 */ ADC1_CH(16) +#define ADC_SCALED_VDD_3V3_SENSORS2_CHANNEL /* PA4 */ ADC1_CH(18) +#define ADC_SCALED_VDD_3V3_SENSORS3_CHANNEL /* PB0 */ ADC1_CH(9) +#define ADC_SCALED_V5_CHANNEL /* PB1 */ ADC1_CH(5) +#define ADC_ADC3_6V6_CHANNEL /* PC2 */ ADC3_CH(12) +#define ADC_ADC3_3V3_CHANNEL /* PC3 */ ADC3_CH(13) +#define ADC_SCALED_VDD_3V3_SENSORS4_CHANNEL /* PF12 */ ADC1_CH(6) +#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_SCALED_VDD_3V3_SENSORS1_CHANNEL) | \ + (1 << ADC_SCALED_VDD_3V3_SENSORS2_CHANNEL) | \ + (1 << ADC_SCALED_VDD_3V3_SENSORS3_CHANNEL) | \ + (1 << ADC_SCALED_V5_CHANNEL) | \ + (1 << ADC_ADC3_6V6_CHANNEL) | \ + (1 << ADC_ADC3_3V3_CHANNEL)) | \ + (1 << ADC_SCALED_VDD_3V3_SENSORS4_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_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 "ARKV6X" + +#define BOARD_NUM_SPI_CFG_HW_VERSIONS 2 // Rev 0 and Rev 3,4 Sensor sets +// Base/FMUM +#define ARKV6X00 HW_VER_REV(0x0,0x0) // ARKV6X, Rev 0 +#define ARKV6X01 HW_VER_REV(0x0,0x1) // ARKV6X, BMI388 I2C2 Rev 1 +#define ARKV6X03 HW_VER_REV(0x0,0x3) // ARKV6X, Sensor Set Rev 3 +#define ARKV6X04 HW_VER_REV(0x0,0x4) // ARKV6X, Sensor Set Rev 4 +#define ARKV6X10 HW_VER_REV(0x1,0x0) // NO PX4IO, Rev 0 +#define ARKV6X13 HW_VER_REV(0x1,0x3) // NO PX4IO, Sensor Set Rev 3 +#define ARKV6X14 HW_VER_REV(0x1,0x4) // NO PX4IO, Sensor Set Rev 4 +//#define ARKV6X40 HW_VER_REV(0x4,0x0) // ARKV6X, HB CM4 base Rev 0 // never shipped +//#define ARKV6X41 HW_VER_REV(0x4,0x1) // ARKV6X, BMI388 I2C2 HB CM4 base Rev 1 // never shipped +#define ARKV6X43 HW_VER_REV(0x4,0x3) // ARKV6X, Sensor Set HB CM4 base Rev 3 +#define ARKV6X44 HW_VER_REV(0x4,0x4) // ARKV6X, Sensor Set HB CM4 base Rev 4 +#define ARKV6X50 HW_VER_REV(0x5,0x0) // ARKV6X, ARKV6X Rev 0 with HB Mini Rev 5 +//#define ARKV6X51 HW_VER_REV(0x5,0x1) // ARKV6X, BMI388 I2C2 HB Mini Rev 1 // never shipped +#define ARKV6X53 HW_VER_REV(0x5,0x3) // ARKV6X, Sensor Set HB Mini Rev 3 +#define ARKV6X54 HW_VER_REV(0x5,0x4) // ARKV6X, Sensor Set HB Mini Rev 4 + +#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 + + +/* Power supply control and monitoring GPIOs */ + +#define GPIO_nPOWER_IN_A /* PG1 */ (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTG|GPIO_PIN1) +#define GPIO_nPOWER_IN_B /* PG2 */ (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTG|GPIO_PIN2) +#define GPIO_nPOWER_IN_C /* PG3 */ (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTG|GPIO_PIN3) + +#define GPIO_nVDD_BRICK1_VALID GPIO_nPOWER_IN_A /* Brick 1 Is Chosen */ +#define GPIO_nVDD_BRICK2_VALID GPIO_nPOWER_IN_B /* Brick 2 Is Chosen */ +#define BOARD_NUMBER_BRICKS 2 +#define BOARD_NUMBER_DIGITAL_BRICKS 2 +#define GPIO_nVDD_USB_VALID GPIO_nPOWER_IN_C /* USB Is Chosen */ + +#define GPIO_VDD_5V_PERIPH_nEN /* PG4 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTG|GPIO_PIN4) +#define GPIO_VDD_5V_PERIPH_nOC /* PE15 */ (GPIO_INPUT |GPIO_FLOAT|GPIO_PORTE|GPIO_PIN15) +#define GPIO_VDD_5V_HIPOWER_nEN /* PG10 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTG|GPIO_PIN10) +#define GPIO_VDD_5V_HIPOWER_nOC /* PF13 */ (GPIO_INPUT |GPIO_FLOAT|GPIO_PORTF|GPIO_PIN13) +#define GPIO_VDD_3V3_SENSORS4_EN /* PG8 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTG|GPIO_PIN8) +#define GPIO_VDD_3V3_SPEKTRUM_POWER_EN /* PH2 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTH|GPIO_PIN2) +#define GPIO_VDD_3V3_SD_CARD_EN /* PC13 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTC|GPIO_PIN13) + +/* Spare GPIO */ + +#define GPIO_PG6 /* PG6 */ (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTG|GPIO_PIN6) +#define GPIO_PD15 /* PD15 */ (GPIO_INPUT|GPIO_FLOAT|GPIO_PORTD|GPIO_PIN15) + +/* ETHERNET GPIO */ + +#define GPIO_ETH_POWER_EN /* PG15 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTG|GPIO_PIN15) + +/* NFC GPIO */ + +#define GPIO_NFC_GPIO /* PC0 */ (GPIO_INPUT|GPIO_FLOAT|GPIO_EXTI|GPIO_PORTC|GPIO_PIN0) + + +/* Define True logic Power Control in arch agnostic form */ + +#define VDD_5V_PERIPH_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_5V_PERIPH_nEN, !(on_true)) +#define VDD_5V_HIPOWER_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_5V_HIPOWER_nEN, !(on_true)) +#define VDD_3V3_SENSORS4_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_3V3_SENSORS4_EN, (on_true)) +#define VDD_3V3_SPEKTRUM_POWER_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_3V3_SPEKTRUM_POWER_EN, (on_true)) +#define READ_VDD_3V3_SPEKTRUM_POWER_EN() px4_arch_gpioread(GPIO_VDD_3V3_SPEKTRUM_POWER_EN) +#define VDD_3V3_SD_CARD_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_3V3_SD_CARD_EN, (on_true)) +#define VDD_3V3_ETH_POWER_EN(on_true) px4_arch_gpiowrite(GPIO_ETH_POWER_EN, (on_true)) + + +/* Tone alarm output */ + +#define TONE_ALARM_TIMER 14 /* Timer 14 */ +#define TONE_ALARM_CHANNEL 1 /* PF9 GPIO_TIM14_CH1OUT_2 */ + +#define GPIO_BUZZER_1 /* PF9 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTF|GPIO_PIN9) + +#define GPIO_TONE_ALARM_IDLE GPIO_BUZZER_1 +#define GPIO_TONE_ALARM GPIO_TIM14_CH1OUT_2 + +/* USB OTG FS + * + * PA9 OTG_FS_VBUS VBUS sensing + */ +#define GPIO_OTGFS_VBUS /* PA9 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_SPEED_100MHz|GPIO_PORTA|GPIO_PIN9) + +/* High-resolution timer */ +#define HRT_TIMER 8 /* use timer8 for the HRT */ +#define HRT_TIMER_CHANNEL 3 /* use capture/compare channel 3 */ + +#define HRT_PPM_CHANNEL /* T8C1 */ 1 /* use capture/compare channel 1 */ +#define GPIO_PPM_IN /* PI5 T8C1 */ GPIO_TIM8_CH1IN_2 + +/* RC Serial port */ + +#define RC_SERIAL_PORT "/dev/ttyS5" +#define RC_SERIAL_SINGLEWIRE + +/* Input Capture Channels. */ +#define INPUT_CAP1_TIMER 1 +#define INPUT_CAP1_CHANNEL /* T1C2 */ 2 +#define GPIO_INPUT_CAP1 /* PE11 */ GPIO_TIM1_CH2IN + +/* 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 + +/* Safety Switch is HW version dependent on having an PX4IO + * So we init to a benign state with the _INIT definition + * and provide the the non _INIT one for the driver to make a run time + * decision to use it. + */ +#define GPIO_nSAFETY_SWITCH_LED_OUT_INIT /* PD10 */ (GPIO_INPUT|GPIO_FLOAT|GPIO_PORTD|GPIO_PIN10) +#define GPIO_nSAFETY_SWITCH_LED_OUT /* PD10 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTD|GPIO_PIN10) + +/* Enable the FMU to control it if there is no px4io fixme:This should be BOARD_SAFETY_LED(__ontrue) */ +#define GPIO_LED_SAFETY GPIO_nSAFETY_SWITCH_LED_OUT + +#define GPIO_SAFETY_SWITCH_IN /* PF5 */ (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTF|GPIO_PIN5) +/* Enable the FMU to use the switch it if there is no px4io fixme:This should be BOARD_SAFTY_BUTTON() */ +#define GPIO_BTN_SAFETY GPIO_SAFETY_SWITCH_IN /* Enable the FMU to control it if there is no px4io */ + +/* Power switch controls ******************************************************/ + +#define SPEKTRUM_POWER(_on_true) VDD_3V3_SPEKTRUM_POWER_EN(_on_true) + +/* + * ARKV6X has a separate RC_IN + * + * GPIO PPM_IN on PI5 T8CH1 + * SPEKTRUM_RX (it's TX or RX in Bind) on UART6 PC7 + * Inversion is possible in the UART and can drive GPIO PPM_IN as an output + */ + +#define GPIO_PPM_IN_AS_OUT (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTI|GPIO_PIN5) +#define SPEKTRUM_RX_AS_GPIO_OUTPUT() px4_arch_configgpio(GPIO_PPM_IN_AS_OUT) +#define SPEKTRUM_RX_AS_UART() /* Can be left as uart */ +#define SPEKTRUM_OUT(_one_true) px4_arch_gpiowrite(GPIO_PPM_IN_AS_OUT, (_one_true)) + +#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_LIB_BOARDCTL=y, OR + * CONFIG_BOARD_INITIALIZE=y && CONFIG_BOARD_INITTHREAD=y + */ + +#if defined(CONFIG_BOARD_INITIALIZE) && !defined(CONFIG_LIB_BOARDCTL) && \ + !defined(CONFIG_BOARD_INITTHREAD) +# warning SDIO initialization cannot be perfomed on the IDLE thread +#endif + +/* By Providing BOARD_ADC_USB_CONNECTED (using the px4_arch abstraction) + * this board support the ADC system_power interface, and therefore + * provides the true logic GPIO BOARD_ADC_xxxx macros. + */ +#define BOARD_ADC_USB_CONNECTED (px4_arch_gpioread(GPIO_OTGFS_VBUS)) +#define BOARD_ADC_USB_VALID (!px4_arch_gpioread(GPIO_nVDD_USB_VALID)) + +/* ARKV6X never powers off the Servo rail */ + +#define BOARD_ADC_SERVO_VALID (1) + +#if !defined(BOARD_HAS_LTC44XX_VALIDS) || BOARD_HAS_LTC44XX_VALIDS == 0 +# define BOARD_ADC_BRICK1_VALID (1) +# define BOARD_ADC_BRICK2_VALID (0) +#elif BOARD_HAS_LTC44XX_VALIDS == 1 +# define BOARD_ADC_BRICK1_VALID (!px4_arch_gpioread(GPIO_nVDD_BRICK1_VALID)) +# define BOARD_ADC_BRICK2_VALID (0) +#elif BOARD_HAS_LTC44XX_VALIDS == 2 +# define BOARD_ADC_BRICK1_VALID (!px4_arch_gpioread(GPIO_nVDD_BRICK1_VALID)) +# define BOARD_ADC_BRICK2_VALID (!px4_arch_gpioread(GPIO_nVDD_BRICK2_VALID)) +#elif BOARD_HAS_LTC44XX_VALIDS == 3 +# define BOARD_ADC_BRICK1_VALID (!px4_arch_gpioread(GPIO_nVDD_BRICK1_VALID)) +# define BOARD_ADC_BRICK2_VALID (!px4_arch_gpioread(GPIO_nVDD_BRICK2_VALID)) +# define BOARD_ADC_BRICK3_VALID (!px4_arch_gpioread(GPIO_nVDD_BRICK3_VALID)) +#elif BOARD_HAS_LTC44XX_VALIDS == 4 +# define BOARD_ADC_BRICK1_VALID (!px4_arch_gpioread(GPIO_nVDD_BRICK1_VALID)) +# define BOARD_ADC_BRICK2_VALID (!px4_arch_gpioread(GPIO_nVDD_BRICK2_VALID)) +# define BOARD_ADC_BRICK3_VALID (!px4_arch_gpioread(GPIO_nVDD_BRICK3_VALID)) +# define BOARD_ADC_BRICK4_VALID (!px4_arch_gpioread(GPIO_nVDD_BRICK4_VALID)) +#else +# error Unsupported BOARD_HAS_LTC44XX_VALIDS value +#endif + +#define BOARD_ADC_PERIPH_5V_OC (!px4_arch_gpioread(GPIO_VDD_5V_PERIPH_nOC)) +#define BOARD_ADC_HIPOWER_5V_OC (!px4_arch_gpioread(GPIO_VDD_5V_HIPOWER_nOC)) + + +/* This board provides a DMA pool and APIs */ +#define BOARD_DMA_ALLOC_POOL_SIZE 5120 + +/* This board provides the board_on_reset interface */ + +#define BOARD_HAS_ON_RESET 1 + +#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_CAN2_TX, \ + GPIO_CAN2_RX, \ + GPIO_HEATER_OUTPUT, \ + GPIO_nPOWER_IN_A, \ + GPIO_nPOWER_IN_B, \ + GPIO_nPOWER_IN_C, \ + GPIO_VDD_5V_PERIPH_nEN, \ + GPIO_VDD_5V_PERIPH_nOC, \ + GPIO_VDD_5V_HIPOWER_nEN, \ + GPIO_VDD_5V_HIPOWER_nOC, \ + GPIO_VDD_3V3_SENSORS4_EN, \ + GPIO_VDD_3V3_SPEKTRUM_POWER_EN, \ + GPIO_VDD_3V3_SD_CARD_EN, \ + GPIO_PD15, \ + GPIO_SYNC, \ + SPI6_nRESET_EXTERNAL1, \ + GPIO_ETH_POWER_EN, \ + GPIO_NFC_GPIO, \ + GPIO_TONE_ALARM_IDLE, \ + GPIO_nSAFETY_SWITCH_LED_OUT_INIT, \ + GPIO_SAFETY_SWITCH_IN, \ + GPIO_PG6, \ + GPIO_nARMED_INIT \ + } + +#define BOARD_ENABLE_CONSOLE_BUFFER + +#define PX4_I2C_BUS_MTD 4,5 + + +#define BOARD_NUM_IO_TIMERS 5 + +__BEGIN_DECLS + +/**************************************************************************************************** + * Public Types + ****************************************************************************************************/ + +/**************************************************************************************************** + * Public data + ****************************************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************************************** + * Public Functions + ****************************************************************************************************/ + +/**************************************************************************** + * Name: stm32_sdio_initialize + * + * Description: + * Initialize SDIO-based MMC/SD card support + * + ****************************************************************************/ + +int stm32_sdio_initialize(void); + +/**************************************************************************************************** + * Name: stm32_spiinitialize + * + * Description: + * Called to configure SPI chip select GPIO pins for the PX4FMU board. + * + ****************************************************************************************************/ + +extern void stm32_spiinitialize(void); + +extern void stm32_usbinitialize(void); + +extern void board_peripheral_reset(int ms); + +#include + +#endif /* __ASSEMBLY__ */ + +__END_DECLS diff --git a/boards/ark/fmu-v6x/src/bootloader_main.c b/boards/ark/fmu-v6x/src/bootloader_main.c new file mode 100644 index 0000000000..8c2ab001f7 --- /dev/null +++ b/boards/ark/fmu-v6x/src/bootloader_main.c @@ -0,0 +1,75 @@ +/**************************************************************************** + * + * 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 + +extern int sercon_main(int c, char **argv); + +__EXPORT void board_on_reset(int status) {} + +__EXPORT void stm32_boardinitialize(void) +{ + /* 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/fmu-v6x/src/can.c b/boards/ark/fmu-v6x/src/can.c new file mode 100644 index 0000000000..f4c59012fb --- /dev/null +++ b/boards/ark/fmu-v6x/src/can.c @@ -0,0 +1,142 @@ +/**************************************************************************** + * + * 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; + + if (!PX4_MFT_HW_SUPPORTED(PX4_MFT_CAN2)) { + enabled_interfaces &= ~(1 << 1); + } + + return enabled_interfaces; +} + +#else + +#include +#include + +#include +#include + +#include "chip.h" +#include "arm_arch.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/fmu-v6x/src/hw_config.h b/boards/ark/fmu-v6x/src/hw_config.h new file mode 100644 index 0000000000..3a0205c87b --- /dev/null +++ b/boards/ark/fmu-v6x/src/hw_config.h @@ -0,0 +1,128 @@ +/* + * hw_config.h + * + * Created on: May 17, 2015 + * Author: david_s5 + */ + +#ifndef HW_CONFIG_H_ +#define HW_CONFIG_H_ + +/**************************************************************************** + * 10-8--2016: + * To simplify the ripple effect on the tools, we will be using + * /dev/serial/by-id/PX4 to locate PX4 devices. Therefore + * moving forward all Bootloaders must contain the prefix "PX4 BL " + * in the USBDEVICESTRING + * This Change will be made in an upcoming BL release + ****************************************************************************/ +/* + * Define usage to configure a bootloader + * + * + * Constant example Usage + * APP_LOAD_ADDRESS 0x08004000 - The address in Linker Script, where the app fw is org-ed + * BOOTLOADER_DELAY 5000 - Ms to wait while under USB pwr or bootloader request + * BOARD_FMUV2 + * INTERFACE_USB 1 - (Optional) Scan and use the USB interface for bootloading + * INTERFACE_USART 1 - (Optional) Scan and use the Serial interface for bootloading + * USBDEVICESTRING "PX4 BL FMU v2.x" - USB id string + * USBPRODUCTID 0x0011 - PID Should match defconfig + * BOOT_DELAY_ADDRESS 0x000001a0 - (Optional) From the linker script from Linker Script to get a custom + * delay provided by an APP FW + * BOARD_TYPE 9 - Must match .prototype boad_id + * _FLASH_KBYTES (*(uint16_t *)0x1fff7a22) - Run time flash size detection + * BOARD_FLASH_SECTORS ((_FLASH_KBYTES == 0x400) ? 11 : 23) - Run time determine the physical last sector + * BOARD_FLASH_SECTORS 11 - Hard coded zero based last sector + * BOARD_FLASH_SIZE (_FLASH_KBYTES*1024)- Total Flash size of device, determined at run time. + * (1024 * 1024) - Hard coded Total Flash of device - The bootloader and app reserved will be deducted + * programmatically + * + * BOARD_FIRST_FLASH_SECTOR_TO_ERASE 2 - Optional sectors index in the flash_sectors table (F4 only), to begin erasing. + * This is to allow sectors to be reserved for app fw usage. That will NOT be erased + * during a FW upgrade. + * The default is 0, and selects the first sector to be erased, as the 0th entry in the + * flash_sectors table. Which is the second physical sector of FLASH in the device. + * The first physical sector of FLASH is used by the bootloader, and is not defined + * in the table. + * + * APP_RESERVATION_SIZE (BOARD_FIRST_FLASH_SECTOR_TO_ERASE * 16 * 1024) - Number of bytes reserved by the APP FW. This number plus + * BOOTLOADER_RESERVATION_SIZE will be deducted from + * BOARD_FLASH_SIZE to determine the size of the App FW + * and hence the address space of FLASH to erase and program. + * USBMFGSTRING "PX4 AP" - Optional USB MFG string (default is '3D Robotics' if not defined.) + * SERIAL_BREAK_DETECT_DISABLED - Optional prevent break selection on Serial port from entering or staying in BL + * + * * Other defines are somewhat self explanatory. + */ + +/* Boot device selection list*/ +#define USB0_DEV 0x01 +#define SERIAL0_DEV 0x02 +#define SERIAL1_DEV 0x04 + +#define APP_LOAD_ADDRESS 0x08020000 +#define BOOTLOADER_DELAY 5000 +#define INTERFACE_USB 1 +#define INTERFACE_USB_CONFIG "/dev/ttyACM0" +#define BOARD_VBUS MK_GPIO_INPUT(GPIO_OTGFS_VBUS) + +//#define USE_VBUS_PULL_DOWN +#define INTERFACE_USART 1 +#define INTERFACE_USART_CONFIG "/dev/ttyS0,115200" +#define BOOT_DELAY_ADDRESS 0x000001a0 +#define BOARD_TYPE 57 +#define _FLASH_KBYTES (*(uint32_t *)0x1FF1E880) +#define BOARD_FLASH_SECTORS (15) +#define BOARD_FLASH_SIZE (_FLASH_KBYTES * 1024) + +#define OSC_FREQ 16 + +#define BOARD_PIN_LED_ACTIVITY GPIO_nLED_BLUE // BLUE +#define BOARD_PIN_LED_BOOTLOADER GPIO_nLED_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/fmu-v6x/src/i2c.cpp b/boards/ark/fmu-v6x/src/i2c.cpp new file mode 100644 index 0000000000..eb200ca932 --- /dev/null +++ b/boards/ark/fmu-v6x/src/i2c.cpp @@ -0,0 +1,41 @@ +/**************************************************************************** + * + * 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), + initI2CBusExternal(2), + initI2CBusExternal(3), + initI2CBusInternal(4), +}; diff --git a/boards/ark/fmu-v6x/src/init.c b/boards/ark/fmu-v6x/src/init.c new file mode 100644 index 0000000000..9032b1531e --- /dev/null +++ b/boards/ark/fmu-v6x/src/init.c @@ -0,0 +1,282 @@ +/**************************************************************************** + * + * 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 +#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 + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* + * Ideally we'd be able to get these from arm_internal.h, + * but since we want to be able to disable the NuttX use + * of leds for system indication at will and there is no + * separate switch, we need to build independent of the + * CONFIG_ARCH_LEDS configuration switch. + */ +__BEGIN_DECLS +extern void led_init(void); +extern void led_on(int led); +extern void led_off(int led); +__END_DECLS + + +/************************************************************************************ + * Name: board_peripheral_reset + * + * Description: + * + ************************************************************************************/ +__EXPORT void board_peripheral_reset(int ms) +{ + /* set the peripheral rails off */ + + VDD_5V_PERIPH_EN(false); + board_control_spi_sensors_power(false, 0xffff); + VDD_3V3_SENSORS4_EN(false); + + bool last = READ_VDD_3V3_SPEKTRUM_POWER_EN(); + /* Keep Spektum on to discharge rail*/ + VDD_3V3_SPEKTRUM_POWER_EN(false); + + /* 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 */ + VDD_3V3_SPEKTRUM_POWER_EN(last); + board_control_spi_sensors_power(true, 0xffff); + VDD_3V3_SENSORS4_EN(true); + VDD_5V_PERIPH_EN(true); + +} + +/************************************************************************************ + * Name: board_on_reset + * + * Description: + * Optionally provided function called on entry to board_system_reset + * It should perform any house keeping prior to the rest. + * + * status - 1 if resetting to boot loader + * 0 if just resetting + * + ************************************************************************************/ +__EXPORT void board_on_reset(int status) +{ + for (int i = 0; i < DIRECT_PWM_OUTPUT_CHANNELS; ++i) { + px4_arch_configgpio(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(); + + VDD_3V3_ETH_POWER_EN(true); + +} + +/**************************************************************************** + * 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 */ + VDD_3V3_SD_CARD_EN(true); + VDD_5V_PERIPH_EN(true); + VDD_5V_HIPOWER_EN(true); + VDD_3V3_SENSORS4_EN(true); + VDD_3V3_SPEKTRUM_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(); + + /* 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 */ + + return OK; +} diff --git a/boards/ark/fmu-v6x/src/led.c b/boards/ark/fmu-v6x/src/led.c new file mode 100644 index 0000000000..7730150731 --- /dev/null +++ b/boards/ark/fmu-v6x/src/led.c @@ -0,0 +1,235 @@ +/**************************************************************************** + * + * Copyright (c) 2013 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file 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 + GPIO_nSAFETY_SWITCH_LED_OUT, // Indexed by LED_SAFETY by xlatpx4 +}; + +#else + +# define xlat(p) (p) +static uint32_t g_ledmap[] = { + GPIO_nLED_BLUE, // Indexed by LED_BLUE + GPIO_nLED_RED, // Indexed by LED_RED, LED_AMBER + 0, // Indexed by LED_SAFETY (defaulted to an input) + 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/fmu-v6x/src/manifest.c b/boards/ark/fmu-v6x/src/manifest.c new file mode 100644 index 0000000000..6b8405bcf5 --- /dev/null +++ b/boards/ark/fmu-v6x/src/manifest.c @@ -0,0 +1,223 @@ +/**************************************************************************** + * + * 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 manifest.c + * + * This module supplies the interface to the manifest of hardware that is + * optional and dependent on the HW REV and HW VER IDs + * + * The manifest allows the system to know whether a hardware option + * say for example the PX4IO is an no-pop option vs it is broken. + * + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include + +#include "systemlib/px4_macros.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +typedef struct { + uint32_t hw_ver_rev; /* the version and revision */ + const px4_hw_mft_item_t *mft; /* The first entry */ + uint32_t entries; /* the lenght of the list */ +} px4_hw_mft_list_entry_t; + +typedef px4_hw_mft_list_entry_t *px4_hw_mft_list_entry; +#define px4_hw_mft_list_uninitialized (px4_hw_mft_list_entry) -1 + +static const px4_hw_mft_item_t device_unsupported = {0, 0, 0}; + +// List of components on a specific board configuration +// The index of those components is given by the enum (px4_hw_mft_item_id_t) +// declared in board_common.h +static const px4_hw_mft_item_t hw_mft_list_v0600[] = { + { + // PX4_MFT_PX4IO + .present = 1, + .mandatory = 1, + .connection = px4_hw_con_onboard, + }, + { + // PX4_MFT_USB + .present = 1, + .mandatory = 1, + .connection = px4_hw_con_onboard, + }, + { + // PX4_MFT_CAN2 + .present = 1, + .mandatory = 1, + .connection = px4_hw_con_onboard, + }, +}; + +static const px4_hw_mft_item_t hw_mft_list_v0610[] = { + { + // PX4_MFT_PX4IO + .present = 0, + .mandatory = 0, + .connection = px4_hw_con_unknown, + }, + { + // PX4_MFT_USB + .present = 1, + .mandatory = 1, + .connection = px4_hw_con_onboard, + }, + { + // PX4_MFT_CAN2 + .present = 1, + .mandatory = 1, + .connection = px4_hw_con_onboard, + }, +}; + +static const px4_hw_mft_item_t hw_mft_list_v0640[] = { + { + // PX4_MFT_PX4IO + .present = 1, + .mandatory = 1, + .connection = px4_hw_con_onboard, + }, + { + // PX4_MFT_USB + .present = 1, + .mandatory = 1, + .connection = px4_hw_con_onboard, + }, + { + // PX4_MFT_CAN2 + .present = 1, + .mandatory = 1, + .connection = px4_hw_con_onboard, + }, +}; + +static const px4_hw_mft_item_t hw_mft_list_v0650[] = { + { + // PX4_MFT_PX4IO + .present = 1, + .mandatory = 1, + .connection = px4_hw_con_unknown, + }, + { + // PX4_MFT_USB + .present = 1, + .mandatory = 1, + .connection = px4_hw_con_onboard, + }, + { + // PX4_MFT_CAN2 + .present = 0, + .mandatory = 0, + .connection = px4_hw_con_unknown, + }, +}; + + +static px4_hw_mft_list_entry_t mft_lists[] = { +// ver_rev + {ARKV6X00, hw_mft_list_v0600, arraySize(hw_mft_list_v0600)}, + {ARKV6X01, hw_mft_list_v0600, arraySize(hw_mft_list_v0600)}, // BMP388 moved to I2C2 + {ARKV6X03, hw_mft_list_v0600, arraySize(hw_mft_list_v0600)}, // BMP388 moved to I2C2, Sensor Set 3 + //{ARKV6X40, hw_mft_list_v0640, arraySize(hw_mft_list_v0640)}, // HB CM4 base // never shipped + //{ARKV6X41, hw_mft_list_v0640, arraySize(hw_mft_list_v0640)}, // BMP388 moved to I2C2 HB CM4 base // never shipped + {ARKV6X43, hw_mft_list_v0640, arraySize(hw_mft_list_v0640)}, // BMP388 moved to I2C2, HB CM4 base Sensor Set 3 + {ARKV6X44, hw_mft_list_v0640, arraySize(hw_mft_list_v0640)}, // BMP388 moved to I2C2, HB CM4 base Sensor Set 4 + {ARKV6X50, hw_mft_list_v0650, arraySize(hw_mft_list_v0650)}, // ARKV6X Rev 0 with HB Mini Rev 5 + //{ARKV6X51, hw_mft_list_v0650, arraySize(hw_mft_list_v0650)}, // BMP388 moved to I2C2 HB Mini // never shipped + {ARKV6X53, hw_mft_list_v0650, arraySize(hw_mft_list_v0650)}, // BMP388 moved to I2C2, HB Mini Sensor Set 3 + {ARKV6X54, hw_mft_list_v0650, arraySize(hw_mft_list_v0650)}, // BMP388 moved to I2C2, HB Mini Sensor Set 4 + {ARKV6X10, hw_mft_list_v0610, arraySize(hw_mft_list_v0610)}, // No PX4IO + {ARKV6X13, hw_mft_list_v0610, arraySize(hw_mft_list_v0610)}, // No PX4IO BMP388 moved to I2C2, Sensor Set 3 + {ARKV6X04, hw_mft_list_v0600, arraySize(hw_mft_list_v0600)}, // BMP388 moved to I2C2, Sensor Set 4 + {ARKV6X14, hw_mft_list_v0610, arraySize(hw_mft_list_v0610)}, // No PX4IO BMP388 moved to I2C2, Sensor Set 4 +}; + +/************************************************************************************ + * Name: board_query_manifest + * + * Description: + * Optional returns manifest item. + * + * Input Parameters: + * manifest_id - the ID for the manifest item to retrieve + * + * Returned Value: + * 0 - item is not in manifest => assume legacy operations + * pointer to a manifest item + * + ************************************************************************************/ + +__EXPORT px4_hw_mft_item board_query_manifest(px4_hw_mft_item_id_t id) +{ + static px4_hw_mft_list_entry boards_manifest = px4_hw_mft_list_uninitialized; + + if (boards_manifest == px4_hw_mft_list_uninitialized) { + uint32_t ver_rev = board_get_hw_version() << 16; + ver_rev |= board_get_hw_revision(); + + for (unsigned i = 0; i < arraySize(mft_lists); i++) { + if (mft_lists[i].hw_ver_rev == ver_rev) { + boards_manifest = &mft_lists[i]; + break; + } + } + + if (boards_manifest == px4_hw_mft_list_uninitialized) { + syslog(LOG_ERR, "[boot] Board %08" PRIx32 " is not supported!\n", ver_rev); + } + } + + px4_hw_mft_item rv = &device_unsupported; + + if (boards_manifest != px4_hw_mft_list_uninitialized && + id < boards_manifest->entries) { + rv = &boards_manifest->mft[id]; + } + + return rv; +} diff --git a/boards/ark/fmu-v6x/src/mtd.cpp b/boards/ark/fmu-v6x/src/mtd.cpp new file mode 100644 index 0000000000..e697ddc9d9 --- /dev/null +++ b/boards/ark/fmu-v6x/src/mtd.cpp @@ -0,0 +1,128 @@ +/**************************************************************************** + * + * 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 +#include +// KiB BS nB +static const px4_mft_device_t spi5 = { // FM25V02A on FMUM 32K 512 X 64 + .bus_type = px4_mft_device_t::SPI, + .devid = SPIDEV_FLASH(0) +}; +static const px4_mft_device_t i2c3 = { // 24LC64T on Base 8K 32 X 256 + .bus_type = px4_mft_device_t::I2C, + .devid = PX4_MK_I2C_DEVID(3, 0x51) +}; +static const px4_mft_device_t i2c4 = { // 24LC64T on IMU 8K 32 X 256 + .bus_type = px4_mft_device_t::I2C, + .devid = PX4_MK_I2C_DEVID(4, 0x50) +}; + + +static const px4_mtd_entry_t fmum_fram = { + .device = &spi5, + .npart = 2, + .partd = { + { + .type = MTD_PARAMETERS, + .path = "/fs/mtd_params", + .nblocks = 32 + }, + { + .type = MTD_WAYPOINTS, + .path = "/fs/mtd_waypoints", + .nblocks = 32 + + } + }, +}; + +static const px4_mtd_entry_t base_eeprom = { + .device = &i2c3, + .npart = 2, + .partd = { + { + .type = MTD_MFT, + .path = "/fs/mtd_mft", + .nblocks = 248 + }, + { + .type = MTD_NET, + .path = "/fs/mtd_net", + .nblocks = 8 // 256 = 32 * 8 + + } + }, +}; + +static const px4_mtd_entry_t imu_eeprom = { + .device = &i2c4, + .npart = 2, + .partd = { + { + .type = MTD_CALDATA, + .path = "/fs/mtd_caldata", + .nblocks = 248 + }, + { + .type = MTD_ID, + .path = "/fs/mtd_id", + .nblocks = 8 // 256 = 32 * 8 + } + }, +}; + +static const px4_mtd_manifest_t board_mtd_config = { + .nconfigs = 3, + .entries = { + &fmum_fram, + &base_eeprom, + &imu_eeprom + } +}; + +static const px4_mft_entry_s mtd_mft = { + .type = MTD, + .pmft = (void *) &board_mtd_config, +}; + +static const px4_mft_s mft = { + .nmft = 1, + .mfts = { + &mtd_mft + } +}; + +const px4_mft_s *board_get_manifest(void) +{ + return &mft; +} diff --git a/boards/ark/fmu-v6x/src/sdio.c b/boards/ark/fmu-v6x/src/sdio.c new file mode 100644 index 0000000000..869d757756 --- /dev/null +++ b/boards/ark/fmu-v6x/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/fmu-v6x/src/spi.cpp b/boards/ark/fmu-v6x/src/spi.cpp new file mode 100644 index 0000000000..2d047cff1d --- /dev/null +++ b/boards/ark/fmu-v6x/src/spi.cpp @@ -0,0 +1,86 @@ +/**************************************************************************** + * + * 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 +#include +#include + +constexpr px4_spi_bus_all_hw_t px4_spi_buses_all_hw[BOARD_NUM_SPI_CFG_HW_VERSIONS] = { + initSPIHWVersion(ARKV6X00, { + initSPIBus(SPI::Bus::SPI1, { + initSPIDevice(DRV_IMU_DEVTYPE_IIM42652, SPI::CS{GPIO::PortI, GPIO::Pin9}, SPI::DRDY{GPIO::PortF, GPIO::Pin2}), + }, {GPIO::PortI, GPIO::Pin11}), + initSPIBus(SPI::Bus::SPI2, { + initSPIDevice(DRV_IMU_DEVTYPE_ICM42688P, SPI::CS{GPIO::PortH, GPIO::Pin5}, SPI::DRDY{GPIO::PortA, GPIO::Pin10}), + }, {GPIO::PortF, GPIO::Pin4}), + initSPIBus(SPI::Bus::SPI3, { + initSPIDevice(DRV_IMU_DEVTYPE_ICM42688P, SPI::CS{GPIO::PortI, GPIO::Pin4}, SPI::DRDY{GPIO::PortI, GPIO::Pin6}), + }, {GPIO::PortE, GPIO::Pin7}), + // initSPIBus(SPI::Bus::SPI4, { + // // no devices + // TODO: if enabled, remove GPIO_VDD_3V3_SENSORS4_EN from board_config.h + // }, {GPIO::PortG, GPIO::Pin8}), + initSPIBus(SPI::Bus::SPI5, { + initSPIDevice(SPIDEV_FLASH(0), SPI::CS{GPIO::PortG, GPIO::Pin7}) + }), + initSPIBusExternal(SPI::Bus::SPI6, { + initSPIConfigExternal(SPI::CS{GPIO::PortI, GPIO::Pin10}, SPI::DRDY{GPIO::PortD, GPIO::Pin11}), + initSPIConfigExternal(SPI::CS{GPIO::PortA, GPIO::Pin15}, SPI::DRDY{GPIO::PortD, GPIO::Pin12}), + }), + }), + + initSPIHWVersion(ARKV6X01, { // Placeholder + initSPIBus(SPI::Bus::SPI1, { + initSPIDevice(DRV_IMU_DEVTYPE_IIM42652, SPI::CS{GPIO::PortI, GPIO::Pin9}, SPI::DRDY{GPIO::PortF, GPIO::Pin2}), + }, {GPIO::PortI, GPIO::Pin11}), + initSPIBus(SPI::Bus::SPI2, { + initSPIDevice(DRV_IMU_DEVTYPE_ICM42688P, SPI::CS{GPIO::PortH, GPIO::Pin5}, SPI::DRDY{GPIO::PortA, GPIO::Pin10}), + }, {GPIO::PortF, GPIO::Pin4}), + initSPIBus(SPI::Bus::SPI3, { + initSPIDevice(DRV_IMU_DEVTYPE_ICM42688P, SPI::CS{GPIO::PortI, GPIO::Pin4}, SPI::DRDY{GPIO::PortI, GPIO::Pin6}), + }, {GPIO::PortE, GPIO::Pin7}), + // initSPIBus(SPI::Bus::SPI4, { + // // no devices + // TODO: if enabled, remove GPIO_VDD_3V3_SENSORS4_EN from board_config.h + // }, {GPIO::PortG, GPIO::Pin8}), + initSPIBus(SPI::Bus::SPI5, { + initSPIDevice(SPIDEV_FLASH(0), SPI::CS{GPIO::PortG, GPIO::Pin7}) + }), + initSPIBusExternal(SPI::Bus::SPI6, { + initSPIConfigExternal(SPI::CS{GPIO::PortI, GPIO::Pin10}, SPI::DRDY{GPIO::PortD, GPIO::Pin11}), + initSPIConfigExternal(SPI::CS{GPIO::PortA, GPIO::Pin15}, SPI::DRDY{GPIO::PortD, GPIO::Pin12}), + }), + }), +}; + +static constexpr bool unused = validateSPIConfig(px4_spi_buses_all_hw); diff --git a/boards/ark/fmu-v6x/src/timer_config.cpp b/boards/ark/fmu-v6x/src/timer_config.cpp new file mode 100644 index 0000000000..928f4916f0 --- /dev/null +++ b/boards/ark/fmu-v6x/src/timer_config.cpp @@ -0,0 +1,80 @@ +/**************************************************************************** + * + * 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 + * + * TIM4_CH2 T FMU_CH5 + * TIM4_CH3 T FMU_CH6 + * + * TIM12_CH1 T FMU_CH7 + * TIM12_CH2 T FMU_CH8 + * + * TIM1_CH2 T FMU_CAP1 < Capture + * TIM1_CH3 T SPI2_DRDY2_ISM330_INT2 < Capture or GPIO INT + * TIM1_CH1 T SPIX_SYNC > Pulse or GPIO strobe + * + * TIM2_CH3 T HEATER > PWM OUT or GPIO + * + * TIM14_CH1 T BUZZER_1 - Driven by other driver + * TIM8_CH1_IN T FMU_PPM_INPUT - Sampled byt HRT by other driver + */ + +constexpr io_timers_t io_timers[MAX_IO_TIMERS] = { + initIOTimer(Timer::Timer5, DMA{DMA::Index1}), + initIOTimer(Timer::Timer4, DMA{DMA::Index1}), + initIOTimer(Timer::Timer12), + initIOTimer(Timer::Timer1), + initIOTimer(Timer::Timer2), +}; + +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::Timer4, Timer::Channel2}, {GPIO::PortD, GPIO::Pin13}), + initIOTimerChannel(io_timers, {Timer::Timer4, Timer::Channel3}, {GPIO::PortD, GPIO::Pin14}), + initIOTimerChannel(io_timers, {Timer::Timer12, Timer::Channel1}, {GPIO::PortH, GPIO::Pin6}), + initIOTimerChannel(io_timers, {Timer::Timer12, Timer::Channel2}, {GPIO::PortH, GPIO::Pin9}), + initIOTimerChannelCapture(io_timers, {Timer::Timer1, Timer::Channel2}, {GPIO::PortE, GPIO::Pin11}), +}; + +constexpr io_timers_channel_mapping_t io_timers_channel_mapping = + initIOTimerChannelMapping(io_timers, timer_io_channels); diff --git a/boards/ark/fmu-v6x/src/usb.c b/boards/ark/fmu-v6x/src/usb.c new file mode 100644 index 0000000000..92b6d33eb6 --- /dev/null +++ b/boards/ark/fmu-v6x/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 +#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); +}