From c31867f104abc4fde1a771d8b21295326f1fba87 Mon Sep 17 00:00:00 2001 From: Jiangxuan Chen <89390126+j-chen-opteran@users.noreply.github.com> Date: Mon, 23 Jan 2023 00:41:39 +0000 Subject: [PATCH] support for KakuteH7v2, KakuteH7mini, and BMI270 IMU driver (#20545) Signed-off-by: Julian Oes --- .../kakutef7/nuttx-config/nsh/defconfig | 2 +- boards/holybro/kakuteh7/default.px4board | 1 + boards/holybro/kakuteh7/init/rc.board_sensors | 5 +- .../kakuteh7/nuttx-config/nsh/defconfig | 2 +- .../nuttx-config/scripts/bootloader_script.ld | 10 +- .../kakuteh7/nuttx-config/scripts/script.ld | 6 +- boards/holybro/kakuteh7/src/init.c | 3 +- boards/holybro/kakuteh7/src/spi.cpp | 1 + .../holybro/kakuteh7mini/bootloader.px4board | 3 + boards/holybro/kakuteh7mini/default.px4board | 95 ++ .../holybro_kakuteh7mini_bootloader.bin | Bin 0 -> 41736 bytes .../holybro/kakuteh7mini/firmware.prototype | 13 + .../kakuteh7mini/init/rc.board_defaults | 51 + .../holybro/kakuteh7mini/init/rc.board_extras | 13 + .../kakuteh7mini/init/rc.board_sensors | 9 + .../nuttx-config/bootloader/defconfig | 114 +++ .../kakuteh7mini/nuttx-config/include/board.h | 419 ++++++++ .../nuttx-config/include/board_dma_map.h | 40 + .../kakuteh7mini/nuttx-config/nsh/defconfig | 272 ++++++ .../nuttx-config/scripts/bootloader_script.ld | 215 +++++ .../nuttx-config/scripts/script.ld | 228 +++++ .../holybro/kakuteh7mini/src/CMakeLists.txt | 67 ++ .../holybro/kakuteh7mini/src/board_config.h | 214 +++++ .../kakuteh7mini/src/bootloader_main.c | 75 ++ boards/holybro/kakuteh7mini/src/hw_config.h | 125 +++ boards/holybro/kakuteh7mini/src/i2c.cpp | 38 + boards/holybro/kakuteh7mini/src/init.c | 261 +++++ boards/holybro/kakuteh7mini/src/led.c | 223 +++++ boards/holybro/kakuteh7mini/src/spi.cpp | 52 + .../holybro/kakuteh7mini/src/timer_config.cpp | 55 ++ boards/holybro/kakuteh7mini/src/usb.c | 105 +++ boards/holybro/kakuteh7v2/bootloader.px4board | 3 + boards/holybro/kakuteh7v2/default.px4board | 96 ++ .../extras/holybro_kakuteh7v2_bootloader.bin | Bin 0 -> 41736 bytes boards/holybro/kakuteh7v2/firmware.prototype | 13 + .../holybro/kakuteh7v2/init/rc.board_defaults | 45 + .../holybro/kakuteh7v2/init/rc.board_extras | 13 + .../holybro/kakuteh7v2/init/rc.board_sensors | 9 + .../nuttx-config/bootloader/defconfig | 114 +++ .../kakuteh7v2/nuttx-config/include/board.h | 419 ++++++++ .../nuttx-config/include/board_dma_map.h | 40 + .../kakuteh7v2/nuttx-config/nsh/defconfig | 272 ++++++ .../nuttx-config/scripts/bootloader_script.ld | 215 +++++ .../kakuteh7v2/nuttx-config/scripts/script.ld | 228 +++++ boards/holybro/kakuteh7v2/src/CMakeLists.txt | 67 ++ boards/holybro/kakuteh7v2/src/board_config.h | 213 +++++ .../holybro/kakuteh7v2/src/bootloader_main.c | 75 ++ boards/holybro/kakuteh7v2/src/hw_config.h | 125 +++ boards/holybro/kakuteh7v2/src/i2c.cpp | 38 + boards/holybro/kakuteh7v2/src/init.c | 261 +++++ boards/holybro/kakuteh7v2/src/led.c | 223 +++++ boards/holybro/kakuteh7v2/src/spi.cpp | 52 + .../holybro/kakuteh7v2/src/timer_config.cpp | 55 ++ boards/holybro/kakuteh7v2/src/usb.c | 105 +++ src/drivers/drv_sensor.h | 2 +- src/drivers/imu/bosch/bmi270/BMI270.cpp | 891 ++++++++++++++++++ src/drivers/imu/bosch/bmi270/BMI270.hpp | 193 ++++ .../bosch/bmi270/Bosch_BMI270_registers.hpp | 206 ++++ src/drivers/imu/bosch/bmi270/CMakeLists.txt | 48 + src/drivers/imu/bosch/bmi270/Kconfig | 5 + src/drivers/imu/bosch/bmi270/bmi270_main.cpp | 85 ++ 61 files changed, 6814 insertions(+), 14 deletions(-) create mode 100644 boards/holybro/kakuteh7mini/bootloader.px4board create mode 100644 boards/holybro/kakuteh7mini/default.px4board create mode 100755 boards/holybro/kakuteh7mini/extras/holybro_kakuteh7mini_bootloader.bin create mode 100644 boards/holybro/kakuteh7mini/firmware.prototype create mode 100644 boards/holybro/kakuteh7mini/init/rc.board_defaults create mode 100644 boards/holybro/kakuteh7mini/init/rc.board_extras create mode 100644 boards/holybro/kakuteh7mini/init/rc.board_sensors create mode 100644 boards/holybro/kakuteh7mini/nuttx-config/bootloader/defconfig create mode 100644 boards/holybro/kakuteh7mini/nuttx-config/include/board.h create mode 100644 boards/holybro/kakuteh7mini/nuttx-config/include/board_dma_map.h create mode 100644 boards/holybro/kakuteh7mini/nuttx-config/nsh/defconfig create mode 100644 boards/holybro/kakuteh7mini/nuttx-config/scripts/bootloader_script.ld create mode 100644 boards/holybro/kakuteh7mini/nuttx-config/scripts/script.ld create mode 100644 boards/holybro/kakuteh7mini/src/CMakeLists.txt create mode 100644 boards/holybro/kakuteh7mini/src/board_config.h create mode 100644 boards/holybro/kakuteh7mini/src/bootloader_main.c create mode 100644 boards/holybro/kakuteh7mini/src/hw_config.h create mode 100644 boards/holybro/kakuteh7mini/src/i2c.cpp create mode 100644 boards/holybro/kakuteh7mini/src/init.c create mode 100644 boards/holybro/kakuteh7mini/src/led.c create mode 100644 boards/holybro/kakuteh7mini/src/spi.cpp create mode 100644 boards/holybro/kakuteh7mini/src/timer_config.cpp create mode 100644 boards/holybro/kakuteh7mini/src/usb.c create mode 100644 boards/holybro/kakuteh7v2/bootloader.px4board create mode 100644 boards/holybro/kakuteh7v2/default.px4board create mode 100755 boards/holybro/kakuteh7v2/extras/holybro_kakuteh7v2_bootloader.bin create mode 100644 boards/holybro/kakuteh7v2/firmware.prototype create mode 100644 boards/holybro/kakuteh7v2/init/rc.board_defaults create mode 100644 boards/holybro/kakuteh7v2/init/rc.board_extras create mode 100644 boards/holybro/kakuteh7v2/init/rc.board_sensors create mode 100644 boards/holybro/kakuteh7v2/nuttx-config/bootloader/defconfig create mode 100644 boards/holybro/kakuteh7v2/nuttx-config/include/board.h create mode 100644 boards/holybro/kakuteh7v2/nuttx-config/include/board_dma_map.h create mode 100644 boards/holybro/kakuteh7v2/nuttx-config/nsh/defconfig create mode 100644 boards/holybro/kakuteh7v2/nuttx-config/scripts/bootloader_script.ld create mode 100644 boards/holybro/kakuteh7v2/nuttx-config/scripts/script.ld create mode 100644 boards/holybro/kakuteh7v2/src/CMakeLists.txt create mode 100644 boards/holybro/kakuteh7v2/src/board_config.h create mode 100644 boards/holybro/kakuteh7v2/src/bootloader_main.c create mode 100644 boards/holybro/kakuteh7v2/src/hw_config.h create mode 100644 boards/holybro/kakuteh7v2/src/i2c.cpp create mode 100644 boards/holybro/kakuteh7v2/src/init.c create mode 100644 boards/holybro/kakuteh7v2/src/led.c create mode 100644 boards/holybro/kakuteh7v2/src/spi.cpp create mode 100644 boards/holybro/kakuteh7v2/src/timer_config.cpp create mode 100644 boards/holybro/kakuteh7v2/src/usb.c create mode 100644 src/drivers/imu/bosch/bmi270/BMI270.cpp create mode 100644 src/drivers/imu/bosch/bmi270/BMI270.hpp create mode 100644 src/drivers/imu/bosch/bmi270/Bosch_BMI270_registers.hpp create mode 100644 src/drivers/imu/bosch/bmi270/CMakeLists.txt create mode 100644 src/drivers/imu/bosch/bmi270/Kconfig create mode 100644 src/drivers/imu/bosch/bmi270/bmi270_main.cpp diff --git a/boards/holybro/kakutef7/nuttx-config/nsh/defconfig b/boards/holybro/kakutef7/nuttx-config/nsh/defconfig index 95d1117245..faf8655412 100644 --- a/boards/holybro/kakutef7/nuttx-config/nsh/defconfig +++ b/boards/holybro/kakutef7/nuttx-config/nsh/defconfig @@ -75,7 +75,7 @@ CONFIG_BOARD_RESET_ON_ASSERT=2 CONFIG_BUILTIN=y CONFIG_CDCACM=y CONFIG_CDCACM_IFLOWCONTROL=y -CONFIG_CDCACM_PRODUCTID=0x0016 +CONFIG_CDCACM_PRODUCTID=0x0050 CONFIG_CDCACM_PRODUCTSTR="PX4 KakuteF7" CONFIG_CDCACM_RXBUFSIZE=600 CONFIG_CDCACM_TXBUFSIZE=12000 diff --git a/boards/holybro/kakuteh7/default.px4board b/boards/holybro/kakuteh7/default.px4board index d3b5c29ce3..d1b4ff6007 100644 --- a/boards/holybro/kakuteh7/default.px4board +++ b/boards/holybro/kakuteh7/default.px4board @@ -15,6 +15,7 @@ CONFIG_DRIVERS_DSHOT=y CONFIG_DRIVERS_GPS=y CONFIG_DRIVERS_IMU_INVENSENSE_ICM20689=y CONFIG_DRIVERS_IMU_INVENSENSE_MPU6000=y +CONFIG_DRIVERS_IMU_BOSCH_BMI270=y CONFIG_COMMON_LIGHT=y CONFIG_COMMON_MAGNETOMETER=y CONFIG_COMMON_OPTICAL_FLOW=y diff --git a/boards/holybro/kakuteh7/init/rc.board_sensors b/boards/holybro/kakuteh7/init/rc.board_sensors index 2711927fe3..c6c9960c39 100644 --- a/boards/holybro/kakuteh7/init/rc.board_sensors +++ b/boards/holybro/kakuteh7/init/rc.board_sensors @@ -1,10 +1,11 @@ #!/bin/sh # -# Holybro KakuteH7 specific board sensors init +# Holybro KakuteH7v1 specific board sensors init #------------------------------------------------------------------------------ board_adc start -# The default IMU is an ICM20689, but there might also be an MPU6000 +# The KakuteH7 v1 comes by default with an ICM20689, +# but there might also be an MPU6000 if ! mpu6000 -R 6 -s start then icm20689 -R 6 -s start diff --git a/boards/holybro/kakuteh7/nuttx-config/nsh/defconfig b/boards/holybro/kakuteh7/nuttx-config/nsh/defconfig index 7cb5571c4f..c7d29ddb92 100644 --- a/boards/holybro/kakuteh7/nuttx-config/nsh/defconfig +++ b/boards/holybro/kakuteh7/nuttx-config/nsh/defconfig @@ -75,7 +75,7 @@ CONFIG_BOARD_RESET_ON_ASSERT=2 CONFIG_BUILTIN=y CONFIG_CDCACM=y CONFIG_CDCACM_IFLOWCONTROL=y -CONFIG_CDCACM_PRODUCTID=0x004b +CONFIG_CDCACM_PRODUCTID=0x0050 CONFIG_CDCACM_PRODUCTSTR="PX4 KakuteH7" CONFIG_CDCACM_RXBUFSIZE=600 CONFIG_CDCACM_TXBUFSIZE=12000 diff --git a/boards/holybro/kakuteh7/nuttx-config/scripts/bootloader_script.ld b/boards/holybro/kakuteh7/nuttx-config/scripts/bootloader_script.ld index 6f9f9e1b5f..fc0a5589be 100644 --- a/boards/holybro/kakuteh7/nuttx-config/scripts/bootloader_script.ld +++ b/boards/holybro/kakuteh7/nuttx-config/scripts/bootloader_script.ld @@ -59,9 +59,9 @@ * 2) BOOT=1: Boot address defined by user option byte BOOT_ADD1[15:0]. * ST programmed value: System bootloader at 0x1FF0:0000 * - * The KakuteH7 has a Swtich on board, the BOOT0 pin is at ground so by default, - * the STM32 will boot to address 0x0800:0000 in FLASH unless the swiutch is - * drepresed, then the boot will be from 0x1FF0:0000 + * The KakuteH7 has a switch on board, the BOOT0 pin is at ground so by default, + * the STM32 will boot to address 0x0800:0000 in FLASH unless the switch is + * depressed, then the boot will be from 0x1FF0:0000 * * The STM32H743VI also has 1024Kb of data SRAM. * SRAM is split up into several blocks and into three power domains: @@ -105,12 +105,14 @@ * 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 = 2048K + flash (rx) : ORIGIN = 0x08000000, LENGTH = 128K dtcm1 (rwx) : ORIGIN = 0x20000000, LENGTH = 64K dtcm2 (rwx) : ORIGIN = 0x20010000, LENGTH = 64K sram (rwx) : ORIGIN = 0x24000000, LENGTH = 512K diff --git a/boards/holybro/kakuteh7/nuttx-config/scripts/script.ld b/boards/holybro/kakuteh7/nuttx-config/scripts/script.ld index aa5405fd5f..ae07f4bfca 100644 --- a/boards/holybro/kakuteh7/nuttx-config/scripts/script.ld +++ b/boards/holybro/kakuteh7/nuttx-config/scripts/script.ld @@ -59,9 +59,9 @@ * 2) BOOT=1: Boot address defined by user option byte BOOT_ADD1[15:0]. * ST programmed value: System bootloader at 0x1FF0:0000 * - * The KakuteH7 has a Swtich on board, the BOOT0 pin is at ground so by default, - * the STM32 will boot to address 0x0800:0000 in FLASH unless the swiutch is - * drepresed, then the boot will be from 0x1FF0:0000 + * The KakuteH7 has a switch on board, the BOOT0 pin is at ground so by default, + * the STM32 will boot to address 0x0800:0000 in FLASH unless the switch is + * depressed, then the boot will be from 0x1FF0:0000 * * The STM32H743VI also has 1024Kb of data SRAM. * SRAM is split up into several blocks and into three power domains: diff --git a/boards/holybro/kakuteh7/src/init.c b/boards/holybro/kakuteh7/src/init.c index a9fe66548e..cf73735aed 100644 --- a/boards/holybro/kakuteh7/src/init.c +++ b/boards/holybro/kakuteh7/src/init.c @@ -240,8 +240,7 @@ __EXPORT int board_app_initialize(uintptr_t arg) int result = mmcsd_spislotinitialize(CONFIG_NSH_MMCSDMINOR, CONFIG_NSH_MMCSDSLOTNO, spi_dev); if (result != OK) { - led_on(LED_BLUE); - syslog(LOG_ERR, "[boot] FAILED to bind SPI port 1 to the MMCSD driver\n"); + syslog(LOG_ERR, "[boot] Could not bind MMCSD driver, expected on Kakute H7 V2\n"); } up_udelay(20); diff --git a/boards/holybro/kakuteh7/src/spi.cpp b/boards/holybro/kakuteh7/src/spi.cpp index cb19b56827..1ff5b7f35c 100644 --- a/boards/holybro/kakuteh7/src/spi.cpp +++ b/boards/holybro/kakuteh7/src/spi.cpp @@ -45,6 +45,7 @@ constexpr px4_spi_bus_t px4_spi_buses[SPI_BUS_MAX_BUS_ITEMS] = { initSPIBus(SPI::Bus::SPI4, { initSPIDevice(DRV_IMU_DEVTYPE_ICM20689, SPI::CS{GPIO::PortE, GPIO::Pin4}, SPI::DRDY{GPIO::PortE, GPIO::Pin1}), initSPIDevice(DRV_IMU_DEVTYPE_MPU6000, SPI::CS{GPIO::PortE, GPIO::Pin4}, SPI::DRDY{GPIO::PortE, GPIO::Pin1}), + initSPIDevice(DRV_IMU_DEVTYPE_BMI270, SPI::CS{GPIO::PortE, GPIO::Pin4}, SPI::DRDY{GPIO::PortE, GPIO::Pin1}), }), }; diff --git a/boards/holybro/kakuteh7mini/bootloader.px4board b/boards/holybro/kakuteh7mini/bootloader.px4board new file mode 100644 index 0000000000..19b6e662be --- /dev/null +++ b/boards/holybro/kakuteh7mini/bootloader.px4board @@ -0,0 +1,3 @@ +CONFIG_BOARD_TOOLCHAIN="arm-none-eabi" +CONFIG_BOARD_ARCHITECTURE="cortex-m7" +CONFIG_BOARD_ROMFSROOT="" diff --git a/boards/holybro/kakuteh7mini/default.px4board b/boards/holybro/kakuteh7mini/default.px4board new file mode 100644 index 0000000000..d58d3ca941 --- /dev/null +++ b/boards/holybro/kakuteh7mini/default.px4board @@ -0,0 +1,95 @@ +CONFIG_BOARD_TOOLCHAIN="arm-none-eabi" +CONFIG_BOARD_ARCHITECTURE="cortex-m7" +CONFIG_BOARD_SERIAL_GPS1="/dev/ttyS3" +CONFIG_BOARD_SERIAL_TEL1="/dev/ttyS0" +CONFIG_BOARD_SERIAL_TEL2="/dev/ttyS1" +CONFIG_BOARD_SERIAL_RC="/dev/ttyS4" +CONFIG_DRIVERS_ADC_BOARD_ADC=y +CONFIG_COMMON_BAROMETERS=y +CONFIG_DRIVERS_BATT_SMBUS=y +CONFIG_DRIVERS_CAMERA_CAPTURE=y +CONFIG_DRIVERS_CAMERA_TRIGGER=y +CONFIG_COMMON_DIFFERENTIAL_PRESSURE=y +CONFIG_COMMON_DISTANCE_SENSOR=y +CONFIG_DRIVERS_DSHOT=y +CONFIG_DRIVERS_GPS=y +CONFIG_DRIVERS_IMU_INVENSENSE_ICM20689=n +CONFIG_DRIVERS_IMU_INVENSENSE_MPU6000=y +CONFIG_DRIVERS_IMU_BOSCH_BMI270=y +CONFIG_COMMON_LIGHT=y +CONFIG_COMMON_MAGNETOMETER=y +CONFIG_COMMON_OPTICAL_FLOW=y +CONFIG_DRIVERS_OSD=y +CONFIG_DRIVERS_POWER_MONITOR_INA226=y +CONFIG_DRIVERS_PWM_OUT=y +CONFIG_MODULES_SIMULATION_PWM_OUT_SIM=y +CONFIG_DRIVERS_RC_INPUT=y +CONFIG_DRIVERS_ROBOCLAW=y +CONFIG_DRIVERS_RPM=y +CONFIG_DRIVERS_SMART_BATTERY_BATMON=y +CONFIG_COMMON_TELEMETRY=y +CONFIG_DRIVERS_TONE_ALARM=y +CONFIG_MODULES_AIRSPEED_SELECTOR=y +CONFIG_MODULES_ATTITUDE_ESTIMATOR_Q=y +CONFIG_MODULES_BATTERY_STATUS=y +CONFIG_MODULES_CAMERA_FEEDBACK=y +CONFIG_MODULES_COMMANDER=y +CONFIG_MODULES_CONTROL_ALLOCATOR=y +CONFIG_MODULES_DATAMAN=y +CONFIG_MODULES_EKF2=y +CONFIG_MODULES_ESC_BATTERY=y +CONFIG_MODULES_EVENTS=y +CONFIG_MODULES_FLIGHT_MODE_MANAGER=y +CONFIG_MODULES_FW_ATT_CONTROL=y +CONFIG_MODULES_FW_AUTOTUNE_ATTITUDE_CONTROL=y +CONFIG_MODULES_FW_POS_CONTROL_L1=y +CONFIG_MODULES_FW_RATE_CONTROL=y +CONFIG_MODULES_GIMBAL=y +CONFIG_MODULES_GYRO_CALIBRATION=y +CONFIG_MODULES_GYRO_FFT=y +CONFIG_MODULES_LAND_DETECTOR=y +CONFIG_MODULES_LANDING_TARGET_ESTIMATOR=y +CONFIG_MODULES_LOAD_MON=y +CONFIG_MODULES_LOGGER=y +CONFIG_MODULES_MAG_BIAS_ESTIMATOR=y +CONFIG_MODULES_MANUAL_CONTROL=y +CONFIG_MODULES_MAVLINK=y +CONFIG_MODULES_MC_ATT_CONTROL=y +CONFIG_MODULES_MC_AUTOTUNE_ATTITUDE_CONTROL=y +CONFIG_MODULES_MC_HOVER_THRUST_ESTIMATOR=y +CONFIG_MODULES_MC_POS_CONTROL=y +CONFIG_MODULES_MC_RATE_CONTROL=y +CONFIG_MODULES_NAVIGATOR=y +CONFIG_MODULES_RC_UPDATE=y +CONFIG_MODULES_ROVER_POS_CONTROL=y +CONFIG_MODULES_SENSORS=y +# CONFIG_SENSORS_VEHICLE_AIRSPEED is not set +CONFIG_MODULES_SIMULATION_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_DUMPFILE=y +CONFIG_SYSTEMCMDS_GPIO=y +CONFIG_SYSTEMCMDS_HARDFAULT_LOG=y +CONFIG_SYSTEMCMDS_I2CDETECT=y +CONFIG_SYSTEMCMDS_LED_CONTROL=y +CONFIG_SYSTEMCMDS_MFT=y +CONFIG_SYSTEMCMDS_MIXER=y +CONFIG_SYSTEMCMDS_MOTOR_TEST=y +CONFIG_SYSTEMCMDS_NSHTERM=y +CONFIG_SYSTEMCMDS_PARAM=y +CONFIG_SYSTEMCMDS_PERF=y +CONFIG_SYSTEMCMDS_PWM=y +CONFIG_SYSTEMCMDS_REBOOT=y +CONFIG_SYSTEMCMDS_SD_BENCH=y +CONFIG_SYSTEMCMDS_SD_STRESS=y +CONFIG_SYSTEMCMDS_SYSTEM_TIME=y +CONFIG_SYSTEMCMDS_TOP=y +CONFIG_SYSTEMCMDS_TOPIC_LISTENER=y +CONFIG_SYSTEMCMDS_TUNE_CONTROL=y +CONFIG_SYSTEMCMDS_UORB=y +CONFIG_SYSTEMCMDS_USB_CONNECTED=y +CONFIG_SYSTEMCMDS_VER=y +CONFIG_SYSTEMCMDS_WORK_QUEUE=y diff --git a/boards/holybro/kakuteh7mini/extras/holybro_kakuteh7mini_bootloader.bin b/boards/holybro/kakuteh7mini/extras/holybro_kakuteh7mini_bootloader.bin new file mode 100755 index 0000000000000000000000000000000000000000..fca97ea49d7c894d56529048ab9297e29299d66e GIT binary patch literal 41736 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 literal 0 HcmV?d00001 diff --git a/boards/holybro/kakuteh7mini/firmware.prototype b/boards/holybro/kakuteh7mini/firmware.prototype new file mode 100644 index 0000000000..369843379f --- /dev/null +++ b/boards/holybro/kakuteh7mini/firmware.prototype @@ -0,0 +1,13 @@ +{ + "board_id": 1054, + "magic": "PX4FWv1", + "description": "Firmware for the KakuteH7Mini board", + "image": "", + "build_time": 0, + "summary": "KAKUTEH7MINI-NAND", + "version": "0.1", + "image_size": 0, + "image_maxsize": 1835008, + "git_identity": "", + "board_revision": 0 +} diff --git a/boards/holybro/kakuteh7mini/init/rc.board_defaults b/boards/holybro/kakuteh7mini/init/rc.board_defaults new file mode 100644 index 0000000000..e1c52182b5 --- /dev/null +++ b/boards/holybro/kakuteh7mini/init/rc.board_defaults @@ -0,0 +1,51 @@ +#!/bin/sh +# +# board specific defaults +#------------------------------------------------------------------------------ + +# transision from params file to flash-based params (2022-08) +if [ -f $PARAM_FILE ] +then + param load $PARAM_FILE + param save + # create a backup + mv $PARAM_FILE ${PARAM_FILE}.bak + reboot +fi + +param set-default BAT1_V_DIV 11.2 +param set-default BAT1_A_PER_V 59.5 + +# system_power unavailable +param set-default CBRK_SUPPLY_CHK 894281 + +# Select the Generic 250 Racer by default +param set-default SYS_AUTOSTART 4050 + +# use the Q attitude estimator, it works w/o mag or GPS. +param set-default SYS_MC_EST_GROUP 3 +param set-default ATT_ACC_COMP 0 +param set-default ATT_W_ACC 0.4000 +param set-default ATT_W_GYRO_BIAS 0.0000 + +param set-default SYS_HAS_MAG 0 + +# the startup tune is not great on a binary output buzzer, so disable it +param set-default CBRK_BUZZER 782090 + +param set-default IMU_GYRO_RATEMAX 2000 + +# Store missions in RAM +param set-default SYS_DM_BACKEND 1 + +# Ignore that there is no SD card +param set-default COM_ARM_SDCARD 0 + +# Store missions in RAM +param set-default SYS_DM_BACKEND 1 + +# Ignore that there is no SD card +param set-default COM_ARM_SDCARD 0 + +# Don't try to log onto SD card +param set-default SDLOG_MODE -1 diff --git a/boards/holybro/kakuteh7mini/init/rc.board_extras b/boards/holybro/kakuteh7mini/init/rc.board_extras new file mode 100644 index 0000000000..256633f33c --- /dev/null +++ b/boards/holybro/kakuteh7mini/init/rc.board_extras @@ -0,0 +1,13 @@ +#!/bin/sh +# +# KakuteH7 specific board extras init +#------------------------------------------------------------------------------ + +if ! param compare OSD_ATXXXX_CFG 0 +then + atxxxx start -s +fi + +# DShot telemetry is always on UART7 +dshot telemetry /dev/ttyS5 + diff --git a/boards/holybro/kakuteh7mini/init/rc.board_sensors b/boards/holybro/kakuteh7mini/init/rc.board_sensors new file mode 100644 index 0000000000..89a18f52b5 --- /dev/null +++ b/boards/holybro/kakuteh7mini/init/rc.board_sensors @@ -0,0 +1,9 @@ +#!/bin/sh +# +# Holybro KakuteH7Mini specific board sensors init +#------------------------------------------------------------------------------ +board_adc start + +bmi270 -R 6 -s start + +bmp280 -X start diff --git a/boards/holybro/kakuteh7mini/nuttx-config/bootloader/defconfig b/boards/holybro/kakuteh7mini/nuttx-config/bootloader/defconfig new file mode 100644 index 0000000000..608b1b03d5 --- /dev/null +++ b/boards/holybro/kakuteh7mini/nuttx-config/bootloader/defconfig @@ -0,0 +1,114 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_DEV_CONSOLE is not set +# CONFIG_DISABLE_PSEUDOFS_OPERATIONS is not set +# CONFIG_DISABLE_PTHREAD is not set +# CONFIG_SPI_EXCHANGE is not set +# CONFIG_STM32H7_SYSCFG is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD_CUSTOM=y +CONFIG_ARCH_BOARD_CUSTOM_DIR="../../../../boards/holybro/kakuteh7mini/nuttx-config" +CONFIG_ARCH_BOARD_CUSTOM_DIR_RELPATH=y +CONFIG_ARCH_BOARD_CUSTOM_NAME="px4" +CONFIG_ARCH_CHIP="stm32h7" +CONFIG_ARCH_CHIP_STM32H743VI=y +CONFIG_ARCH_CHIP_STM32H7=y +CONFIG_ARCH_INTERRUPTSTACK=512 +CONFIG_ARMV7M_BASEPRI_WAR=y +CONFIG_ARMV7M_ICACHE=y +CONFIG_ARMV7M_MEMCPY=y +CONFIG_ARMV7M_USEBASEPRI=y +CONFIG_BOARDCTL_RESET=y +CONFIG_BOARDCTL=y +CONFIG_BOARD_INITTHREAD_PRIORITY=254 +CONFIG_BOARD_LATE_INITIALIZE=y +CONFIG_BOARD_LOOPSPERMSEC=22114 +CONFIG_BOARD_RESET_ON_ASSERT=2 +CONFIG_BOARD_ASSERT_RESET_VALUE=0 +CONFIG_C99_BOOL8=y +CONFIG_CDCACM=y +CONFIG_CDCACM_IFLOWCONTROL=y +CONFIG_CDCACM_PRODUCTID=0x0050 +CONFIG_CDCACM_PRODUCTSTR="PX4 BL Holybro KakuteH7Mini" +CONFIG_CDCACM_RXBUFSIZE=600 +CONFIG_CDCACM_TXBUFSIZE=12000 +CONFIG_CDCACM_VENDORID=0x3162 +CONFIG_CDCACM_VENDORSTR="Holybro" +CONFIG_CLOCK_MONOTONIC=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEFAULT_SMALL=y +# CONFIG_NSH_DISABLE_ECHO is not set +# CONFIG_NSH_DISABLE_ENV is not set +# CONFIG_NSH_DISABLE_FREE is not set +# CONFIG_NSH_DISABLE_HELP is not set +# CONFIG_NSH_DISABLE_KILL is not set +# CONFIG_NSH_DISABLE_LS is not set +# CONFIG_NSH_DISABLE_MKDIR is not set +# CONFIG_NSH_DISABLE_MODCMDS is not set +# CONFIG_NSH_DISABLE_MOUNT is not set +# CONFIG_NSH_DISABLE_MV is not set +# CONFIG_NSH_DISABLE_PRINTF is not set +# CONFIG_NSH_DISABLE_PSSTACKUSAGE +# CONFIG_NSH_DISABLE_PWD is not set +# CONFIG_NSH_DISABLE_SOURCE is not set +# CONFIG_NSH_DISABLE_SLEEP is not set +# CONFIG_NSH_DISABLE_TEST is not set +# CONFIG_NSH_DISABLE_UMOUNT is not set +# CONFIG_NSH_DISABLE_UNSET is not set +# CONFIG_NSH_DISABLE_USLEEP is not set +CONFIG_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_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_OTGFS=y +CONFIG_STM32H7_PROGMEM=y +CONFIG_STM32H7_SERIAL_DISABLE_REORDERING=y +CONFIG_STM32H7_TIM1=y +CONFIG_STM32H7_USART3=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_USART3_RXBUFSIZE=600 +CONFIG_USART3_TXBUFSIZE=300 +CONFIG_USBDEV=y +CONFIG_USBDEV_BUSPOWERED=y +CONFIG_USBDEV_MAXPOWER=500 +CONFIG_USEC_PER_TICK=1000 +CONFIG_INIT_STACKSIZE=2944 +CONFIG_INIT_ENTRYPOINT="bootloader_main" diff --git a/boards/holybro/kakuteh7mini/nuttx-config/include/board.h b/boards/holybro/kakuteh7mini/nuttx-config/include/board.h new file mode 100644 index 0000000000..83245ff925 --- /dev/null +++ b/boards/holybro/kakuteh7mini/nuttx-config/include/board.h @@ -0,0 +1,419 @@ +/************************************************************************************ + * + * Copyright (C) 2016-2019 Gregory Nutt. 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 NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ +#pragma once + +/************************************************************************************ + * 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 holybro KakuteH7 board provides the following clock sources: + * + * X1: 8 MHz crystal for HSE + * + * So we have these clock source available within the STM32 + * + * HSI: 16 MHz RC factory-trimmed + * HSE: 8 MHz crystal for HSE + */ + +#define STM32_BOARD_XTAL 8000000ul + +#define STM32_HSI_FREQUENCY 16000000ul +#define STM32_LSI_FREQUENCY 32000 +#define STM32_HSE_FREQUENCY STM32_BOARD_XTAL +#define STM32_LSE_FREQUENCY 32768 + +/* Main PLL Configuration. + * + * PLL source is HSE = 8,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 = (8,000,000 / 1) * 120 = 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(120) +#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) * 120) +#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(2) +#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 / 2) * 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(2) +#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 / 2) * 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 holybro KakuteH7 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_NLEDS 1 + +#define BOARD_LED_RED BOARD_LED1 + +/* LED bits for use with board_userled_all() */ + +#define BOARD_LED1_BIT (1 << BOARD_LED1) + +/* If CONFIG_ARCH_LEDS is defined, the usage by the board port is defined in + * include/board.h and src/stm32_leds.c. The LEDs are used to encode OS-related + * events as follows: + * + * + * SYMBOL Meaning LED state + * Red Green Blue + * ---------------------- -------------------------- ------ ------ ----*/ + +#define LED_STARTED 0 /* NuttX has been started OFF OFF OFF */ +#define LED_HEAPALLOCATE 1 /* Heap has been allocated OFF OFF ON */ +#define LED_IRQSENABLED 2 /* Interrupts enabled OFF ON OFF */ +#define LED_STACKCREATED 3 /* Idle stack created OFF ON ON */ +#define LED_INIRQ 4 /* In an interrupt N/C N/C GLOW */ +#define LED_SIGNAL 5 /* In a signal handler N/C GLOW N/C */ +#define LED_ASSERTION 6 /* An assertion failed GLOW N/C GLOW */ +#define LED_PANIC 7 /* The system has crashed Blink OFF N/C */ +#define LED_IDLE 8 /* MCU is is sleep mode ON OFF OFF */ + +/* Thus if the Green LED is statically on, NuttX has successfully booted and + * is, apparently, running normally. If the Red LED is flashing at + * approximately 2Hz, then a fatal error has been detected and the system + * has halted. + */ + +/* Alternate function pin selections ************************************************/ + + +#define GPIO_USART1_RX GPIO_USART1_RX_2 /* PA10 */ +#define GPIO_USART1_TX GPIO_USART1_TX_2 /* PA9 */ + +#define GPIO_USART2_RX GPIO_USART2_RX_2 /* PD6 */ +#define GPIO_USART2_TX GPIO_USART2_TX_2 /* PD5 */ + +#define GPIO_USART3_RX GPIO_USART3_RX_3 /* PD9 */ +#define GPIO_USART3_TX GPIO_USART3_TX_3 /* PD8 */ + +#define GPIO_UART4_RX GPIO_UART4_RX_5 /* PD0 */ +#define GPIO_UART4_TX GPIO_UART4_TX_5 /* PD1 */ + +#define GPIO_USART6_RX GPIO_USART6_RX_1 /* PC7 */ +#define GPIO_USART6_TX GPIO_USART6_TX_1 /* PC6 */ + +#define GPIO_UART7_RX GPIO_UART7_RX_3 /* PE7 */ +#define GPIO_UART7_TX GPIO_UART7_TX_3 /* PE8 */ + +/* SPI + * SPI1 SD Card + * SPI2 is OSD AT7456E + * SPI4 is IMU + */ + +#define GPIO_SPI1_MISO GPIO_SPI1_MISO_1 /* PA6 */ +#define GPIO_SPI1_MOSI GPIO_SPI1_MOSI_1 /* PA7 */ +#define GPIO_SPI1_SCK GPIO_SPI1_SCK_1 /* PA5 */ + +#define GPIO_SPI2_MISO GPIO_SPI2_MISO_1 /* PB14 */ +#define GPIO_SPI2_MOSI GPIO_SPI2_MOSI_1 /* PB15 */ +#define GPIO_SPI2_SCK GPIO_SPI2_SCK_4 /* PB13 */ + +#define GPIO_SPI4_MISO GPIO_SPI4_MISO_2 /* PE5 */ +#define GPIO_SPI4_MOSI GPIO_SPI4_MOSI_2 /* PE6 */ +#define GPIO_SPI4_SCK GPIO_SPI4_SCK_2 /* PE2 */ + +/* I2C + */ + +#define GPIO_I2C1_SCL GPIO_I2C1_SCL_1 /* PB6 */ +#define GPIO_I2C1_SDA GPIO_I2C1_SDA_1 /* PB7 */ + +#define GPIO_I2C1_SCL_GPIO (GPIO_OUTPUT | GPIO_OPENDRAIN |GPIO_SPEED_50MHz | GPIO_OUTPUT_SET | GPIO_PORTB | GPIO_PIN6) +#define GPIO_I2C1_SDA_GPIO (GPIO_OUTPUT | GPIO_OPENDRAIN |GPIO_SPEED_50MHz | GPIO_OUTPUT_SET | GPIO_PORTB | GPIO_PIN7) + +/* SDMMC1 + * + * VDD 3.3 + * GND + * SDMMC1_CK PC12 + * SDMMC1_CMD PD2 + * SDMMC1_D0 PC8 + * SDMMC1_D1 PC9 + * SDMMC1_D2 PC10 + * SDMMC1_D3 PC11 + * GPIO_SDMMC1_NCD PG0 + */ + +/* USB + * + * OTG_FS_DM PA11 + * OTG_FS_DP PA12 + * VBUS PA9 + */ + + +/* Board provides GPIO or other Hardware for signaling to timing analyzer */ + +# define PROBE_INIT(mask) +# define PROBE(n,s) +# define PROBE_MARK(n) + diff --git a/boards/holybro/kakuteh7mini/nuttx-config/include/board_dma_map.h b/boards/holybro/kakuteh7mini/nuttx-config/include/board_dma_map.h new file mode 100644 index 0000000000..1954ce3e68 --- /dev/null +++ b/boards/holybro/kakuteh7mini/nuttx-config/include/board_dma_map.h @@ -0,0 +1,40 @@ +/**************************************************************************** + * + * Copyright (c) 2020 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#pragma once + +#define DMAMAP_SPI4_RX DMAMAP_DMA12_SPI4RX_1 /* DMA2 */ +#define DMAMAP_SPI4_TX DMAMAP_DMA12_SPI4TX_1 /* DMA2 */ + +#define DMAMAP_USART2_RX DMAMAP_DMA12_USART2RX_1 /* DMA2 */ + diff --git a/boards/holybro/kakuteh7mini/nuttx-config/nsh/defconfig b/boards/holybro/kakuteh7mini/nuttx-config/nsh/defconfig new file mode 100644 index 0000000000..c22da0c8a0 --- /dev/null +++ b/boards/holybro/kakuteh7mini/nuttx-config/nsh/defconfig @@ -0,0 +1,272 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_DISABLE_ENVIRON is not set +# CONFIG_DISABLE_PSEUDOFS_OPERATIONS is not set +# CONFIG_DISABLE_PTHREAD is not set +# CONFIG_MMCSD_HAVE_CARDDETECT is not set +# CONFIG_MMCSD_HAVE_WRITEPROTECT is not set +# CONFIG_MMCSD_MMCSUPPORT is not set +# CONFIG_NSH_DISABLEBG is not set +# CONFIG_NSH_DISABLESCRIPT is not set +# CONFIG_NSH_DISABLE_CAT is not set +# CONFIG_NSH_DISABLE_CD is not set +# CONFIG_NSH_DISABLE_CP is not set +# CONFIG_NSH_DISABLE_DATE is not set +# CONFIG_NSH_DISABLE_DF is not set +# CONFIG_NSH_DISABLE_ECHO is not set +# CONFIG_NSH_DISABLE_ENV is not set +# CONFIG_NSH_DISABLE_EXEC is not set +# CONFIG_NSH_DISABLE_EXIT is not set +# CONFIG_NSH_DISABLE_EXPORT is not set +# CONFIG_NSH_DISABLE_FREE is not set +# CONFIG_NSH_DISABLE_GET is not set +# CONFIG_NSH_DISABLE_HELP is not set +# CONFIG_NSH_DISABLE_ITEF is not set +# CONFIG_NSH_DISABLE_KILL is not set +# CONFIG_NSH_DISABLE_LOOPS is not set +# CONFIG_NSH_DISABLE_LS is not set +# CONFIG_NSH_DISABLE_MKDIR is not set +# CONFIG_NSH_DISABLE_MKFATFS is not set +# CONFIG_NSH_DISABLE_MOUNT is not set +# CONFIG_NSH_DISABLE_MV is not set +# CONFIG_NSH_DISABLE_PS is not set +# CONFIG_NSH_DISABLE_PSSTACKUSAGE is not set +# CONFIG_NSH_DISABLE_PWD is not set +# CONFIG_NSH_DISABLE_RM is not set +# CONFIG_NSH_DISABLE_RMDIR is not set +# CONFIG_NSH_DISABLE_SEMICOLON is not set +# CONFIG_NSH_DISABLE_SET is not set +# CONFIG_NSH_DISABLE_SLEEP is not set +# CONFIG_NSH_DISABLE_SOURCE is not set +# CONFIG_NSH_DISABLE_TEST is not set +# CONFIG_NSH_DISABLE_TIME is not set +# CONFIG_NSH_DISABLE_UMOUNT is not set +# CONFIG_NSH_DISABLE_UNSET is not set +# CONFIG_NSH_DISABLE_USLEEP is not set +# CONFIG_SPI_CALLBACK is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD_CUSTOM=y +CONFIG_ARCH_BOARD_CUSTOM_DIR="../../../../boards/holybro/kakuteh7mini/nuttx-config" +CONFIG_ARCH_BOARD_CUSTOM_DIR_RELPATH=y +CONFIG_ARCH_BOARD_CUSTOM_NAME="px4" +CONFIG_ARCH_CHIP="stm32h7" +CONFIG_ARCH_CHIP_STM32H743II=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_BOARDCTL=y +CONFIG_BOARD_CRASHDUMP=y +CONFIG_BOARD_LOOPSPERMSEC=95150 +CONFIG_BOARD_RESET_ON_ASSERT=2 +CONFIG_BOARD_ASSERT_RESET_VALUE=0 +CONFIG_BUILTIN=y +CONFIG_C99_BOOL8=y +CONFIG_CDCACM=y +CONFIG_CDCACM_IFLOWCONTROL=y +CONFIG_CDCACM_PRODUCTID=0x0050 +CONFIG_CDCACM_PRODUCTSTR="PX4 KakuteH7Mini-nand" +CONFIG_CDCACM_RXBUFSIZE=600 +CONFIG_CDCACM_TXBUFSIZE=12000 +CONFIG_CDCACM_VENDORID=0x3162 +CONFIG_CDCACM_VENDORSTR="Holybro" +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_NSH_DISABLE_ECHO is not set +# CONFIG_NSH_DISABLE_ENV is not set +# CONFIG_NSH_DISABLE_FREE is not set +# CONFIG_NSH_DISABLE_HELP is not set +# CONFIG_NSH_DISABLE_KILL is not set +# CONFIG_NSH_DISABLE_LS is not set +# CONFIG_NSH_DISABLE_MKDIR is not set +# CONFIG_NSH_DISABLE_MODCMDS is not set +# CONFIG_NSH_DISABLE_MOUNT is not set +# CONFIG_NSH_DISABLE_MV is not set +# CONFIG_NSH_DISABLE_PRINTF is not set +# CONFIG_NSH_DISABLE_PSSTACKUSAGE +# CONFIG_NSH_DISABLE_PWD is not set +# CONFIG_NSH_DISABLE_SOURCE is not set +# CONFIG_NSH_DISABLE_SLEEP is not set +# CONFIG_NSH_DISABLE_TEST is not set +# CONFIG_NSH_DISABLE_UMOUNT is not set +# CONFIG_NSH_DISABLE_UNSET is not set +# CONFIG_NSH_DISABLE_USLEEP is not set +CONFIG_DEV_FIFO_SIZE=0 +CONFIG_DEV_PIPE_MAXSIZE=1024 +CONFIG_DEV_PIPE_SIZE=70 +CONFIG_EXPERIMENTAL=y +CONFIG_FAT_DMAMEMORY=y +CONFIG_FAT_LCNAMES=y +CONFIG_FAT_LFN=y +CONFIG_FAT_LFN_ALIAS_HASH=y +CONFIG_FDCLONE_STDIO=y +CONFIG_FS_BINFS=y +CONFIG_FS_CROMFS=y +CONFIG_FS_FAT=y +CONFIG_FS_FATTIME=y +CONFIG_FS_PROCFS=y +CONFIG_FS_PROCFS_INCLUDE_PROGMEM=y +CONFIG_FS_PROCFS_MAX_TASKS=64 +CONFIG_FS_PROCFS_REGISTER=y +CONFIG_FS_ROMFS=y +CONFIG_GRAN=y +CONFIG_GRAN_INTR=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_I2C=y +CONFIG_I2C_RESET=y +CONFIG_IDLETHREAD_STACKSIZE=750 +CONFIG_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_MM_REGIONS=4 +CONFIG_MTD=y +CONFIG_MTD_BYTE_WRITE=y +CONFIG_MTD_PARTITION=y +CONFIG_MTD_PROGMEM=y +CONFIG_MTD_RAMTRON=y +CONFIG_NAME_MAX=40 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_ARGCAT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_CMDPARMS=y +CONFIG_NSH_CROMFSETC=y +CONFIG_NSH_DISABLE_IFCONFIG=y +CONFIG_NSH_DISABLE_IFUPDOWN=y +CONFIG_NSH_DISABLE_TELNETD=y +CONFIG_NSH_LINELEN=128 +CONFIG_NSH_MAXARGUMENTS=15 +CONFIG_NSH_MMCSDSPIPORTNO=1 +CONFIG_NSH_NESTDEPTH=8 +CONFIG_NSH_QUOTE=y +CONFIG_NSH_ROMFSETC=y +CONFIG_NSH_ROMFSSECTSIZE=128 +CONFIG_NSH_STRERROR=y +CONFIG_NSH_VARS=y +CONFIG_OTG_ID_GPIO_DISABLE=y +CONFIG_PIPES=y +CONFIG_PREALLOC_TIMERS=50 +CONFIG_PRIORITY_INHERITANCE=y +CONFIG_PTHREAD_MUTEX_ROBUST=y +CONFIG_PTHREAD_STACK_MIN=512 +CONFIG_RAMTRON_SETSPEED=y +CONFIG_RAM_SIZE=245760 +CONFIG_RAM_START=0x20010000 +CONFIG_RAW_BINARY=y +CONFIG_READLINE_CMD_HISTORY=y +CONFIG_READLINE_TABCOMPLETION=y +CONFIG_RTC_DATETIME=y +CONFIG_LIBC_MAX_EXITFUNS=1 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_HPWORKPRIORITY=249 +CONFIG_SCHED_HPWORKSTACKSIZE=1280 +CONFIG_SCHED_INSTRUMENTATION=y +CONFIG_SCHED_INSTRUMENTATION_EXTERNAL=y +CONFIG_SCHED_INSTRUMENTATION_SWITCH=y +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_LPWORKPRIORITY=50 +CONFIG_SCHED_LPWORKSTACKSIZE=1632 +CONFIG_SCHED_WAITPID=y +CONFIG_SDCLONE_DISABLE=y +CONFIG_SEM_PREALLOCHOLDERS=32 +CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS=y +CONFIG_SERIAL_TERMIOS=y +CONFIG_SIG_DEFAULT=y +CONFIG_SIG_SIGALRM_ACTION=y +CONFIG_SIG_SIGUSR1_ACTION=y +CONFIG_SIG_SIGUSR2_ACTION=y +CONFIG_SIG_SIGWORK=4 +CONFIG_STACK_COLORATION=y +CONFIG_START_DAY=30 +CONFIG_START_MONTH=11 +CONFIG_STDIO_BUFFER_SIZE=256 +CONFIG_STM32H7_ADC1=y +CONFIG_STM32H7_ADC3=y +CONFIG_STM32H7_BBSRAM=y +CONFIG_STM32H7_BBSRAM_FILES=5 +CONFIG_STM32H7_BDMA=y +CONFIG_STM32H7_BKPSRAM=y +CONFIG_STM32H7_DMA1=y +CONFIG_STM32H7_DMA2=y +CONFIG_STM32H7_DMACAPABLE=y +CONFIG_STM32H7_FLOWCONTROL_BROKEN=y +CONFIG_STM32H7_I2C1=y +CONFIG_STM32H7_I2C_DYNTIMEO=y +CONFIG_STM32H7_I2C_DYNTIMEO_STARTSTOP=10 +CONFIG_STM32H7_OTGFS=y +CONFIG_STM32H7_PROGMEM=y +CONFIG_STM32H7_RTC=y +CONFIG_STM32H7_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY=y +CONFIG_STM32H7_RTC_MAGIC_REG=1 +CONFIG_STM32H7_SAVE_CRASHDUMP=y +CONFIG_STM32H7_SDMMC1=y +CONFIG_STM32H7_SERIALBRK_BSDCOMPAT=y +CONFIG_STM32H7_SERIAL_DISABLE_REORDERING=y +CONFIG_STM32H7_SPI1=y +CONFIG_STM32H7_SPI2=y +CONFIG_STM32H7_SPI4=y +CONFIG_STM32H7_SPI4_DMA=y +CONFIG_STM32H7_SPI4_DMA_BUFFER=1024 +CONFIG_STM32H7_SPI_DMA=y +CONFIG_STM32H7_UART4=y +CONFIG_STM32H7_UART7=y +CONFIG_STM32H7_USART1=y +CONFIG_STM32H7_USART2=y +CONFIG_STM32H7_USART3=y +CONFIG_STM32H7_USART6=y +CONFIG_STM32H7_USART_BREAKS=y +CONFIG_STM32H7_USART_INVERT=y +CONFIG_STM32H7_USART_SINGLEWIRE=y +CONFIG_STM32H7_USART_SWAP=y +CONFIG_SYSTEM_CDCACM=y +CONFIG_SYSTEM_NSH=y +CONFIG_TASK_NAME_SIZE=24 +CONFIG_TTY_SIGINT=y +CONFIG_TTY_SIGTSTP=y +CONFIG_UART4_BAUD=57600 +CONFIG_UART4_RXBUFSIZE=600 +CONFIG_UART4_TXBUFSIZE=1500 +CONFIG_UART7_BAUD=57600 +CONFIG_UART7_RXBUFSIZE=600 +CONFIG_UART7_TXBUFSIZE=1500 +CONFIG_USART1_BAUD=57600 +CONFIG_USART1_RXBUFSIZE=600 +CONFIG_USART1_TXBUFSIZE=1500 +CONFIG_USART2_BAUD=57600 +CONFIG_USART2_RXBUFSIZE=600 +CONFIG_USART2_RXDMA=y +CONFIG_USART2_TXBUFSIZE=2500 +CONFIG_USART3_BAUD=57600 +CONFIG_USART3_RXBUFSIZE=600 +CONFIG_USART3_SERIAL_CONSOLE=y +CONFIG_USART3_TXBUFSIZE=1500 +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_INIT_STACKSIZE=2944 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_WATCHDOG=y diff --git a/boards/holybro/kakuteh7mini/nuttx-config/scripts/bootloader_script.ld b/boards/holybro/kakuteh7mini/nuttx-config/scripts/bootloader_script.ld new file mode 100644 index 0000000000..fc0a5589be --- /dev/null +++ b/boards/holybro/kakuteh7mini/nuttx-config/scripts/bootloader_script.ld @@ -0,0 +1,215 @@ +/**************************************************************************** + * scripts/script.ld + * + * Copyright (C) 2016, 2019 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* The KakuteH7 uses an STM32H743VI 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 STM32H743VI, 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 KakuteH7 has a switch on board, the BOOT0 pin is at ground so by default, + * the STM32 will boot to address 0x0800:0000 in FLASH unless the switch is + * depressed, then the boot will be from 0x1FF0:0000 + * + * The STM32H743VI 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/holybro/kakuteh7mini/nuttx-config/scripts/script.ld b/boards/holybro/kakuteh7mini/nuttx-config/scripts/script.ld new file mode 100644 index 0000000000..ae07f4bfca --- /dev/null +++ b/boards/holybro/kakuteh7mini/nuttx-config/scripts/script.ld @@ -0,0 +1,228 @@ +/**************************************************************************** + * scripts/script.ld + * + * Copyright (C) 2016, 2019 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* The KakuteH7 uses an STM32H743VI 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 STM32H743VI, 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 KakuteH7 has a switch on board, the BOOT0 pin is at ground so by default, + * the STM32 will boot to address 0x0800:0000 in FLASH unless the switch is + * depressed, then the boot will be from 0x1FF0:0000 + * + * The STM32H743VI also has 1024Kb of data SRAM. + * SRAM is split up into several blocks and into three power domains: + * + * 1) TCM SRAMs are dedicated to the Cortex-M7 and are accessible with + * 0 wait states by the Cortex-M7 and by MDMA through AHBS slave bus + * + * 1.1) 128Kb of DTCM-RAM beginning at address 0x2000:0000 + * + * The DTCM-RAM is organized as 2 x 64Kb DTCM-RAMs on 2 x 32 bit + * DTCM ports. The DTCM-RAM could be used for critical real-time + * data, such as interrupt service routines or stack / heap memory. + * Both DTCM-RAMs can be used in parallel (for load/store operations) + * thanks to the Cortex-M7 dual issue capability. + * + * 1.2) 64Kb of ITCM-RAM beginning at address 0x0000:0000 + * + * This RAM is connected to ITCM 64-bit interface designed for + * execution of critical real-times routines by the CPU. + * + * 2) AXI SRAM (D1 domain) accessible by all system masters except BDMA + * through D1 domain AXI bus matrix + * + * 2.1) 512Kb of SRAM beginning at address 0x2400:0000 + * + * 3) AHB SRAM (D2 domain) accessible by all system masters except BDMA + * through D2 domain AHB bus matrix + * + * 3.1) 128Kb of SRAM1 beginning at address 0x3000:0000 + * 3.2) 128Kb of SRAM2 beginning at address 0x3002:0000 + * 3.3) 32Kb of SRAM3 beginning at address 0x3004:0000 + * + * SRAM1 - SRAM3 are one contiguous block: 288Kb at address 0x3000:0000 + * + * 4) AHB SRAM (D3 domain) accessible by most of system masters + * through D3 domain AHB bus matrix + * + * 4.1) 64Kb of SRAM4 beginning at address 0x3800:0000 + * 4.1) 4Kb of backup RAM beginning at address 0x3880:0000 + * + * When booting from FLASH, FLASH memory is aliased to address 0x0000:0000 + * where the code expects to begin execution by jumping to the entry point in + * the 0x0800:0000 address range. + */ + +MEMORY +{ + ITCM_RAM (rwx) : ORIGIN = 0x00000000, LENGTH = 64K + FLASH (rx) : ORIGIN = 0x08020000, LENGTH = 1792K /* params in last sector */ + + DTCM1_RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 64K + DTCM2_RAM (rwx) : ORIGIN = 0x20010000, LENGTH = 64K + AXI_SRAM (rwx) : ORIGIN = 0x24000000, LENGTH = 512K /* D1 domain AXI bus */ + SRAM1 (rwx) : ORIGIN = 0x30000000, LENGTH = 128K /* D2 domain AHB bus */ + SRAM2 (rwx) : ORIGIN = 0x30020000, LENGTH = 128K /* D2 domain AHB bus */ + SRAM3 (rwx) : ORIGIN = 0x30040000, LENGTH = 32K /* D2 domain AHB bus */ + SRAM4 (rwx) : ORIGIN = 0x38000000, LENGTH = 64K /* D3 domain */ + BKPRAM (rwx) : ORIGIN = 0x38800000, LENGTH = 4K +} + +OUTPUT_ARCH(arm) +EXTERN(_vectors) +ENTRY(_stext) + +/* + * Ensure that abort() is present in the final object. The exception handling + * code pulled in by libgcc.a requires it (and that code cannot be easily avoided). + */ +EXTERN(abort) +EXTERN(_bootdelay_signature) + +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/holybro/kakuteh7mini/src/CMakeLists.txt b/boards/holybro/kakuteh7mini/src/CMakeLists.txt new file mode 100644 index 0000000000..220642b2a5 --- /dev/null +++ b/boards/holybro/kakuteh7mini/src/CMakeLists.txt @@ -0,0 +1,67 @@ +############################################################################ +# +# 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 + i2c.cpp + init.c + led.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/holybro/kakuteh7mini/src/board_config.h b/boards/holybro/kakuteh7mini/src/board_config.h new file mode 100644 index 0000000000..a96e548476 --- /dev/null +++ b/boards/holybro/kakuteh7mini/src/board_config.h @@ -0,0 +1,214 @@ +/**************************************************************************** + * + * Copyright (c) 2019 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 + * + * holybro KakuteH7 internal definitions + */ + +#pragma once + +/**************************************************************************************************** + * Included Files + ****************************************************************************************************/ + +#include +#include +#include + +#include + +/**************************************************************************************************** + * Definitions + ****************************************************************************************************/ + +/* Configuration ************************************************************************************/ + +# define BOARD_HAS_USB_VALID 1 +# define BOARD_HAS_NBAT_V 1 +# define BOARD_HAS_NBAT_I 1 + +/* Holybro KakuteH7 GPIOs ************************************************************************/ + +/* LEDs are driven with push open drain to support Anode to 5V or 3.3V */ + +#define GPIO_nLED_RED /* PC2 */ (GPIO_OUTPUT|GPIO_OPENDRAIN|GPIO_SPEED_50MHz|GPIO_OUTPUT_SET|GPIO_PORTC|GPIO_PIN2) + +#define BOARD_HAS_CONTROL_STATUS_LEDS 1 +#define BOARD_OVERLOAD_LED LED_RED + +/* + * 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) + +/* Define GPIO pins used as ADC N.B. Channel numbers must match below */ + +#define PX4_ADC_GPIO \ + /* PC0 */ GPIO_ADC123_INP10, \ + /* PC1 */ GPIO_ADC123_INP11, \ + /* PC5 */ GPIO_ADC12_INP8 + +/* Define Channel numbers must match above GPIO pin IN(n)*/ + +#define ADC_BATTERY_VOLTAGE_CHANNEL /* PC0 */ ADC1_CH(10) +#define ADC_BATTERY_CURRENT_CHANNEL /* PC1 */ ADC1_CH(11) +#define ADC_RSSI_IN_CHANNEL /* PC5 */ ADC1_CH(8) + +#define ADC_CHANNELS \ + ((1 << ADC_BATTERY_VOLTAGE_CHANNEL) | \ + (1 << ADC_BATTERY_CURRENT_CHANNEL) | \ + (1 << ADC_RSSI_IN_CHANNEL)) + +#define BOARD_ADC_OPEN_CIRCUIT_V (5.6f) + + + +/* PWM + */ +#define DIRECT_PWM_OUTPUT_CHANNELS 8 + +#define BOARD_NUM_IO_TIMERS 4 + + +/* Tone alarm output */ + +#define GPIO_TONE_ALARM_IDLE /* PC13 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTC|GPIO_PIN13) +#define GPIO_TONE_ALARM_GPIO /* PC13 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTC|GPIO_PIN13) + +/* USB OTG FS + * + * PA9 OTG_FS_VBUS VBUS sensing + */ +#define GPIO_OTGFS_VBUS /* PA8 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_SPEED_100MHz|GPIO_PORTA|GPIO_PIN8) + +/* High-resolution timer */ +#define HRT_TIMER 4 /* use timer3 for the HRT */ +#define HRT_TIMER_CHANNEL 1 /* use capture/compare channel 1 */ + +// So we can run CRSF on ttyS4, which corresponds to the TX6/RX6 pins +/* RC Serial port */ +#define RC_SERIAL_PORT "/dev/ttyS4" +#define BOARD_SUPPORTS_RC_SERIAL_PORT_OUTPUT + +/* PWM input driver. Use FMU AUX5 pins attached to timer4 channel 2 */ + +#define PWMIN_TIMER 5 +#define PWMIN_TIMER_CHANNEL /* T5C1 */ 1 +#define GPIO_PWM_IN /* PA0 */ GPIO_TIM5_CH1IN + +#define GPIO_RSSI_IN /* PC5 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTC|GPIO_PIN5) + +#define GPIO_RF_SWITCH /* PE13 */ (GPIO_OUTPUT|GPIO_PULLDOWN|GPIO_PORTE|GPIO_PIN13) + +/* Power switch controls ******************************************************/ + +#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)) + +/* Board never powers off the Servo rail */ + +#define BOARD_ADC_SERVO_VALID (1) + +#define BOARD_ADC_BRICK1_VALID (1) + +/* This board provides a DMA pool and APIs */ +#define BOARD_DMA_ALLOC_POOL_SIZE 5120 + +/* This board provides the board_on_reset interface */ + +#define BOARD_HAS_ON_RESET 1 + +#define PX4_GPIO_INIT_LIST { \ + PX4_ADC_GPIO, \ + GPIO_TONE_ALARM_IDLE, \ + GPIO_RSSI_IN, \ + GPIO_RF_SWITCH, \ + } + +#define BOARD_ENABLE_CONSOLE_BUFFER + +#define FLASH_BASED_PARAMS + +__BEGIN_DECLS + +/**************************************************************************************************** + * Public Types + ****************************************************************************************************/ + +/**************************************************************************************************** + * Public data + ****************************************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************************************** + * Public Functions + ****************************************************************************************************/ + +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/holybro/kakuteh7mini/src/bootloader_main.c b/boards/holybro/kakuteh7mini/src/bootloader_main.c new file mode 100644 index 0000000000..915b7f3d29 --- /dev/null +++ b/boards/holybro/kakuteh7mini/src/bootloader_main.c @@ -0,0 +1,75 @@ +/**************************************************************************** + * + * Copyright (c) 2019, 2021 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file bootloader_main.c + * + * FMU-specific early startup code for bootloader +*/ + +#include "board_config.h" +#include "bl.h" + +#include +#include +#include +#include +#include +#include "arm_internal.h" +#include + +extern int sercon_main(int c, char **argv); + +__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/holybro/kakuteh7mini/src/hw_config.h b/boards/holybro/kakuteh7mini/src/hw_config.h new file mode 100644 index 0000000000..1ad290fd6c --- /dev/null +++ b/boards/holybro/kakuteh7mini/src/hw_config.h @@ -0,0 +1,125 @@ +/* + * 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 3000 +#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 BOOT_DELAY_ADDRESS 0x000001a0 +#define BOARD_TYPE 1054 +#define BOARD_FLASH_SECTORS (14) +#define BOARD_FLASH_SIZE (16 * 128 * 1024) +#define APP_RESERVATION_SIZE (1 * 128 * 1024) + +#define OSC_FREQ 8 + +#define BOARD_PIN_LED_ACTIVITY GPIO_nLED_RED +#define BOARD_LED_ON 0 +#define BOARD_LED_OFF 1 + +#define SERIAL_BREAK_DETECT_DISABLED 1 + +/* + * Uncommenting this allows to force the bootloader through + * a PWM output pin. As this can accidentally initialize + * an ESC prematurely, it is not recommended. This feature + * has not been used and hence defaults now to off. + * + * # define BOARD_FORCE_BL_PIN_OUT (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTE|GPIO_PIN14) + * # define BOARD_FORCE_BL_PIN_IN (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTE|GPIO_PIN11) + * + * # define BOARD_POWER_PIN_OUT (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTA|GPIO_PIN4) + * # define BOARD_POWER_ON 1 + * # define BOARD_POWER_OFF 0 + * # undef BOARD_POWER_PIN_RELEASE // Leave pin enabling Power - un comment to release (disable power) + * +*/ + +#if !defined(ARCH_SN_MAX_LENGTH) +# define ARCH_SN_MAX_LENGTH 12 +#endif + +#if !defined(APP_RESERVATION_SIZE) +# define APP_RESERVATION_SIZE 0 +#endif + +#if !defined(BOARD_FIRST_FLASH_SECTOR_TO_ERASE) +# define BOARD_FIRST_FLASH_SECTOR_TO_ERASE 1 +#endif + +#if !defined(USB_DATA_ALIGN) +# define USB_DATA_ALIGN +#endif + +#ifndef BOOT_DEVICES_SELECTION +# define BOOT_DEVICES_SELECTION USB0_DEV|SERIAL0_DEV|SERIAL1_DEV +#endif + +#ifndef BOOT_DEVICES_FILTER_ONUSB +# define BOOT_DEVICES_FILTER_ONUSB USB0_DEV|SERIAL0_DEV|SERIAL1_DEV +#endif + +#endif /* HW_CONFIG_H_ */ diff --git a/boards/holybro/kakuteh7mini/src/i2c.cpp b/boards/holybro/kakuteh7mini/src/i2c.cpp new file mode 100644 index 0000000000..e9f26f9a9e --- /dev/null +++ b/boards/holybro/kakuteh7mini/src/i2c.cpp @@ -0,0 +1,38 @@ +/**************************************************************************** + * + * Copyright (C) 2020 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#include + +constexpr px4_i2c_bus_t px4_i2c_buses[I2C_BUS_MAX_BUS_ITEMS] = { + initI2CBusExternal(1), +}; diff --git a/boards/holybro/kakuteh7mini/src/init.c b/boards/holybro/kakuteh7mini/src/init.c new file mode 100644 index 0000000000..c8f19df734 --- /dev/null +++ b/boards/holybro/kakuteh7mini/src/init.c @@ -0,0 +1,261 @@ +/**************************************************************************** + * + * Copyright (c) 2012-2019 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file init.c + * + * PX4FMU-specific early startup code. This file implements the + * board_app_initialize() function that is called early by nsh during startup. + * + * Code here is run before the rcS script is invoked; it should start required + * subsystems and perform board-specific initialisation. + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "board_config.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "arm_internal.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +# if defined(FLASH_BASED_PARAMS) +# include +#endif + + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* + * Ideally we'd be able to get these from arm_internal.h, + * but since we want to be able to disable the NuttX use + * of leds for system indication at will and there is no + * separate switch, we need to build independent of the + * CONFIG_ARCH_LEDS configuration switch. + */ +__BEGIN_DECLS +extern void led_init(void); +extern void led_on(int led); +extern void led_off(int led); +__END_DECLS + + +/************************************************************************************ + * Name: board_peripheral_reset + * + * Description: + * + ************************************************************************************/ +__EXPORT void board_peripheral_reset(int ms) +{ +} + +/************************************************************************************ + * 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)); + + board_control_spi_sensors_power_configgpio(); + + /* Turn bluetooth off by default (no mavlink support yet) */ + px4_arch_gpiowrite(GPIO_RF_SWITCH, 0); + + /* configure USB interfaces */ + + stm32_usbinitialize(); + +} + +/**************************************************************************** + * Name: board_app_initialize + * + * Description: + * Perform application specific initialization. This function is never + * called directly from application code, but only indirectly via the + * (non-standard) boardctl() interface using the command BOARDIOC_INIT. + * + * Input Parameters: + * arg - The boardctl() argument is passed to the board_app_initialize() + * implementation without modification. The argument has no + * meaning to NuttX; the meaning of the argument is a contract + * between the board-specific initalization logic and the the + * matching application logic. The value cold be such things as a + * mode enumeration value, a set of DIP switch switch settings, a + * pointer to configuration data read from a file or serial FLASH, + * or whatever you would like to do with it. Every implementation + * should accept zero/NULL as a default configuration. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure to indicate the nature of the failure. + * + ****************************************************************************/ + + +__EXPORT int board_app_initialize(uintptr_t arg) +{ + /* Power on Interfaces */ + board_control_spi_sensors_power(true, 0xffff); + + /* Need hrt running before using the ADC */ + + px4_platform_init(); + + /* configure SPI interfaces */ + + stm32_spiinitialize(); + + /* 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); + + if (board_hardfault_init(2, true) != 0) { + led_on(LED_RED); + } + + // MARK: this will *not* work as the minis have a W25N NAND flash chip + /* Get the SPI port for the microSD slot */ + struct spi_dev_s *spi_dev = stm32_spibus_initialize(CONFIG_NSH_MMCSDSPIPORTNO); + + if (!spi_dev) { + syslog(LOG_ERR, "[boot] FAILED to initialize SPI port %d\n", CONFIG_NSH_MMCSDSPIPORTNO); + led_on(LED_BLUE); + } + + up_udelay(20); + +#if defined(FLASH_BASED_PARAMS) + static sector_descriptor_t params_sector_map[] = { + {15, 128 * 1024, 0x081E0000}, + {0, 0, 0}, + }; + + /* Initialize the flashfs layer to use heap allocated memory */ + int result = parameter_flashfs_init(params_sector_map, NULL, 0); + + if (result != OK) { + syslog(LOG_ERR, "[boot] FAILED to init params in FLASH %d\n", result); + led_on(LED_AMBER); + } + +#endif + + /* Configure the HW based on the manifest */ + + px4_platform_configure(); + + return OK; +} diff --git a/boards/holybro/kakuteh7mini/src/led.c b/boards/holybro/kakuteh7mini/src/led.c new file mode 100644 index 0000000000..945c383eb7 --- /dev/null +++ b/boards/holybro/kakuteh7mini/src/led.c @@ -0,0 +1,223 @@ +/**************************************************************************** + * + * 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. + * + ****************************************************************************/ + +#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_RED, // Indexed by BOARD_LED_RED +}; + +#else + +# define xlat(p) (p) +static uint32_t g_ledmap[] = { + GPIO_nLED_RED, // Indexed by LED_RED, LED_AMBER +}; + +#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/holybro/kakuteh7mini/src/spi.cpp b/boards/holybro/kakuteh7mini/src/spi.cpp new file mode 100644 index 0000000000..1f47a54022 --- /dev/null +++ b/boards/holybro/kakuteh7mini/src/spi.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** + * + * Copyright (C) 2020, 2021 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#include +#include +#include + +constexpr px4_spi_bus_t px4_spi_buses[SPI_BUS_MAX_BUS_ITEMS] = { + initSPIBus(SPI::Bus::SPI1, { + initSPIDevice(SPIDEV_MMCSD(0), SPI::CS{GPIO::PortA, GPIO::Pin4}) + }), + initSPIBus(SPI::Bus::SPI2, { + initSPIDevice(DRV_OSD_DEVTYPE_ATXXXX, SPI::CS{GPIO::PortB, GPIO::Pin12}), + }), + initSPIBus(SPI::Bus::SPI4, { + // + +constexpr io_timers_t io_timers[MAX_IO_TIMERS] = { + initIOTimer(Timer::Timer3, DMA{DMA::Index1}), + initIOTimer(Timer::Timer2, DMA{DMA::Index1}), + initIOTimer(Timer::Timer5, DMA{DMA::Index1}), + initIOTimer(Timer::Timer8, DMA{DMA::Index1}), +}; + +constexpr timer_io_channels_t timer_io_channels[MAX_TIMER_IO_CHANNELS] = { + initIOTimerChannel(io_timers, {Timer::Timer3, Timer::Channel3}, {GPIO::PortB, GPIO::Pin0}), + initIOTimerChannel(io_timers, {Timer::Timer3, Timer::Channel4}, {GPIO::PortB, GPIO::Pin1}), + initIOTimerChannel(io_timers, {Timer::Timer2, Timer::Channel2}, {GPIO::PortB, GPIO::Pin3}), + initIOTimerChannel(io_timers, {Timer::Timer2, Timer::Channel3}, {GPIO::PortB, GPIO::Pin10}), + initIOTimerChannel(io_timers, {Timer::Timer5, Timer::Channel1}, {GPIO::PortA, GPIO::Pin0}), + initIOTimerChannel(io_timers, {Timer::Timer5, Timer::Channel3}, {GPIO::PortA, GPIO::Pin2}), + initIOTimerChannel(io_timers, {Timer::Timer8, Timer::Channel3}, {GPIO::PortC, GPIO::Pin8}), + initIOTimerChannel(io_timers, {Timer::Timer8, Timer::Channel4}, {GPIO::PortC, GPIO::Pin9}), +}; + +constexpr io_timers_channel_mapping_t io_timers_channel_mapping = + initIOTimerChannelMapping(io_timers, timer_io_channels); diff --git a/boards/holybro/kakuteh7mini/src/usb.c b/boards/holybro/kakuteh7mini/src/usb.c new file mode 100644 index 0000000000..6d42476b71 --- /dev/null +++ b/boards/holybro/kakuteh7mini/src/usb.c @@ -0,0 +1,105 @@ +/**************************************************************************** + * + * Copyright (C) 2016 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file px4fmu_usb.c + * + * Board-specific USB functions. + */ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include "board_config.h" + +/************************************************************************************ + * Definitions + ************************************************************************************/ + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_usbinitialize + * + * Description: + * Called to setup USB-related GPIO pins for the PX4FMU board. + * + ************************************************************************************/ + +__EXPORT void stm32_usbinitialize(void) +{ + /* The OTG FS has an internal soft pull-up */ + + /* Configure the OTG FS VBUS sensing GPIO, Power On, and Overcurrent GPIOs */ + +#ifdef CONFIG_STM32H7_OTGFS + stm32_configgpio(GPIO_OTGFS_VBUS); +#endif +} + +/************************************************************************************ + * Name: stm32_usbsuspend + * + * Description: + * Board logic must provide the stm32_usbsuspend logic if the USBDEV driver is + * used. This function is called whenever the USB enters or leaves suspend mode. + * This is an opportunity for the board logic to shutdown clocks, power, etc. + * while the USB is suspended. + * + ************************************************************************************/ + +__EXPORT void stm32_usbsuspend(FAR struct usbdev_s *dev, bool resume) +{ + uinfo("resume: %d\n", resume); +} diff --git a/boards/holybro/kakuteh7v2/bootloader.px4board b/boards/holybro/kakuteh7v2/bootloader.px4board new file mode 100644 index 0000000000..19b6e662be --- /dev/null +++ b/boards/holybro/kakuteh7v2/bootloader.px4board @@ -0,0 +1,3 @@ +CONFIG_BOARD_TOOLCHAIN="arm-none-eabi" +CONFIG_BOARD_ARCHITECTURE="cortex-m7" +CONFIG_BOARD_ROMFSROOT="" diff --git a/boards/holybro/kakuteh7v2/default.px4board b/boards/holybro/kakuteh7v2/default.px4board new file mode 100644 index 0000000000..6590eba150 --- /dev/null +++ b/boards/holybro/kakuteh7v2/default.px4board @@ -0,0 +1,96 @@ +CONFIG_BOARD_TOOLCHAIN="arm-none-eabi" +CONFIG_BOARD_ARCHITECTURE="cortex-m7" +CONFIG_BOARD_SERIAL_GPS1="/dev/ttyS3" +CONFIG_BOARD_SERIAL_TEL1="/dev/ttyS0" +CONFIG_BOARD_SERIAL_TEL2="/dev/ttyS1" +CONFIG_BOARD_SERIAL_RC="/dev/ttyS4" +CONFIG_DRIVERS_ADC_BOARD_ADC=y +CONFIG_COMMON_BAROMETERS=y +CONFIG_DRIVERS_BATT_SMBUS=y +CONFIG_DRIVERS_CAMERA_CAPTURE=y +CONFIG_DRIVERS_CAMERA_TRIGGER=y +CONFIG_COMMON_DIFFERENTIAL_PRESSURE=y +CONFIG_COMMON_DISTANCE_SENSOR=y +CONFIG_DRIVERS_DSHOT=y +CONFIG_DRIVERS_GPS=y +CONFIG_DRIVERS_IMU_INVENSENSE_ICM20689=y +CONFIG_DRIVERS_IMU_INVENSENSE_MPU6000=y +CONFIG_DRIVERS_IMU_BOSCH_BMI270=y +CONFIG_COMMON_LIGHT=y +CONFIG_COMMON_MAGNETOMETER=y +CONFIG_COMMON_OPTICAL_FLOW=y +CONFIG_DRIVERS_OSD=y +CONFIG_DRIVERS_POWER_MONITOR_INA226=y +CONFIG_DRIVERS_PWM_OUT=y +CONFIG_DRIVERS_RC_INPUT=y +CONFIG_DRIVERS_ROBOCLAW=y +CONFIG_DRIVERS_RPM=y +CONFIG_DRIVERS_SMART_BATTERY_BATMON=y +CONFIG_COMMON_TELEMETRY=y +CONFIG_DRIVERS_TONE_ALARM=y +CONFIG_MODULES_AIRSPEED_SELECTOR=y +CONFIG_MODULES_ATTITUDE_ESTIMATOR_Q=y +CONFIG_MODULES_BATTERY_STATUS=y +CONFIG_MODULES_CAMERA_FEEDBACK=y +CONFIG_MODULES_COMMANDER=y +CONFIG_MODULES_CONTROL_ALLOCATOR=y +CONFIG_MODULES_DATAMAN=y +CONFIG_MODULES_EKF2=y +CONFIG_MODULES_ESC_BATTERY=y +CONFIG_MODULES_EVENTS=y +CONFIG_MODULES_FLIGHT_MODE_MANAGER=y +CONFIG_MODULES_FW_ATT_CONTROL=y +CONFIG_MODULES_FW_AUTOTUNE_ATTITUDE_CONTROL=y +CONFIG_MODULES_FW_POS_CONTROL_L1=y +CONFIG_MODULES_FW_RATE_CONTROL=y +CONFIG_MODULES_GIMBAL=y +CONFIG_MODULES_GYRO_CALIBRATION=y +CONFIG_MODULES_GYRO_FFT=y +CONFIG_MODULES_LAND_DETECTOR=y +CONFIG_MODULES_LANDING_TARGET_ESTIMATOR=y +CONFIG_MODULES_LOAD_MON=y +CONFIG_MODULES_LOGGER=y +CONFIG_MODULES_MAG_BIAS_ESTIMATOR=y +CONFIG_MODULES_MANUAL_CONTROL=y +CONFIG_MODULES_MAVLINK=y +CONFIG_MODULES_MC_ATT_CONTROL=y +CONFIG_MODULES_MC_AUTOTUNE_ATTITUDE_CONTROL=y +CONFIG_MODULES_MC_HOVER_THRUST_ESTIMATOR=y +CONFIG_MODULES_MC_POS_CONTROL=y +CONFIG_MODULES_MC_RATE_CONTROL=y +CONFIG_MODULES_MICRODDS_CLIENT=y +CONFIG_MODULES_NAVIGATOR=y +CONFIG_MODULES_RC_UPDATE=y +CONFIG_MODULES_ROVER_POS_CONTROL=y +CONFIG_MODULES_SENSORS=y +# CONFIG_SENSORS_VEHICLE_AIRSPEED is not set +CONFIG_MODULES_SIMULATION_PWM_OUT_SIM=y +CONFIG_MODULES_SIMULATION_SENSOR_BARO_SIM=y +CONFIG_MODULES_SIMULATION_SENSOR_GPS_SIM=y +CONFIG_MODULES_SIMULATION_SENSOR_MAG_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_DUMPFILE=y +CONFIG_SYSTEMCMDS_GPIO=y +CONFIG_SYSTEMCMDS_HARDFAULT_LOG=y +CONFIG_SYSTEMCMDS_I2CDETECT=y +CONFIG_SYSTEMCMDS_LED_CONTROL=y +CONFIG_SYSTEMCMDS_MFT=y +CONFIG_SYSTEMCMDS_NSHTERM=y +CONFIG_SYSTEMCMDS_PARAM=y +CONFIG_SYSTEMCMDS_PERF=y +CONFIG_SYSTEMCMDS_REBOOT=y +CONFIG_SYSTEMCMDS_SD_BENCH=y +CONFIG_SYSTEMCMDS_SD_STRESS=y +CONFIG_SYSTEMCMDS_SYSTEM_TIME=y +CONFIG_SYSTEMCMDS_TOP=y +CONFIG_SYSTEMCMDS_TOPIC_LISTENER=y +CONFIG_SYSTEMCMDS_TUNE_CONTROL=y +CONFIG_SYSTEMCMDS_UORB=y +CONFIG_SYSTEMCMDS_USB_CONNECTED=y +CONFIG_SYSTEMCMDS_VER=y +CONFIG_SYSTEMCMDS_WORK_QUEUE=y diff --git a/boards/holybro/kakuteh7v2/extras/holybro_kakuteh7v2_bootloader.bin b/boards/holybro/kakuteh7v2/extras/holybro_kakuteh7v2_bootloader.bin new file mode 100755 index 0000000000000000000000000000000000000000..7ed8c65c2f539aedb05b3a3ee7a5ea7db243885d GIT binary patch literal 41736 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
<9cA6YoEN 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 literal 0 HcmV?d00001 diff --git a/boards/holybro/kakuteh7v2/firmware.prototype b/boards/holybro/kakuteh7v2/firmware.prototype new file mode 100644 index 0000000000..8a69c40d30 --- /dev/null +++ b/boards/holybro/kakuteh7v2/firmware.prototype @@ -0,0 +1,13 @@ +{ + "board_id": 1053, + "magic": "PX4FWv1", + "description": "Firmware for the KakuteH7v2 board", + "image": "", + "build_time": 0, + "summary": "KAKUTEH7V2", + "version": "0.1", + "image_size": 0, + "image_maxsize": 1835008, + "git_identity": "", + "board_revision": 0 +} diff --git a/boards/holybro/kakuteh7v2/init/rc.board_defaults b/boards/holybro/kakuteh7v2/init/rc.board_defaults new file mode 100644 index 0000000000..3e02f07f5c --- /dev/null +++ b/boards/holybro/kakuteh7v2/init/rc.board_defaults @@ -0,0 +1,45 @@ +#!/bin/sh +# +# board specific defaults +#------------------------------------------------------------------------------ + +# transision from params file to flash-based params (2022-08) +if [ -f $PARAM_FILE ] +then + param load $PARAM_FILE + param save + # create a backup + mv $PARAM_FILE ${PARAM_FILE}.bak + reboot +fi + +param set-default BAT1_V_DIV 11.2 +param set-default BAT1_A_PER_V 59.5 + +# system_power unavailable +param set-default CBRK_SUPPLY_CHK 894281 + +# Select the Generic 250 Racer by default +param set-default SYS_AUTOSTART 4050 + +# use the Q attitude estimator, it works w/o mag or GPS. +param set-default SYS_MC_EST_GROUP 3 +param set-default ATT_ACC_COMP 0 +param set-default ATT_W_ACC 0.4000 +param set-default ATT_W_GYRO_BIAS 0.0000 + +param set-default SYS_HAS_MAG 0 + +# the startup tune is not great on a binary output buzzer, so disable it +param set-default CBRK_BUZZER 782090 + +param set-default IMU_GYRO_RATEMAX 2000 + +# Store missions in RAM +param set-default SYS_DM_BACKEND 1 + +# Ignore that there is no SD card +param set-default COM_ARM_SDCARD 0 + +# Don't try to log onto SD card +param set-default SDLOG_MODE -1 diff --git a/boards/holybro/kakuteh7v2/init/rc.board_extras b/boards/holybro/kakuteh7v2/init/rc.board_extras new file mode 100644 index 0000000000..256633f33c --- /dev/null +++ b/boards/holybro/kakuteh7v2/init/rc.board_extras @@ -0,0 +1,13 @@ +#!/bin/sh +# +# KakuteH7 specific board extras init +#------------------------------------------------------------------------------ + +if ! param compare OSD_ATXXXX_CFG 0 +then + atxxxx start -s +fi + +# DShot telemetry is always on UART7 +dshot telemetry /dev/ttyS5 + diff --git a/boards/holybro/kakuteh7v2/init/rc.board_sensors b/boards/holybro/kakuteh7v2/init/rc.board_sensors new file mode 100644 index 0000000000..221983e789 --- /dev/null +++ b/boards/holybro/kakuteh7v2/init/rc.board_sensors @@ -0,0 +1,9 @@ +#!/bin/sh +# +# Holybro KakuteH7v2 specific board sensors init +#------------------------------------------------------------------------------ +board_adc start + +bmi270 -s start + +bmp280 -X start diff --git a/boards/holybro/kakuteh7v2/nuttx-config/bootloader/defconfig b/boards/holybro/kakuteh7v2/nuttx-config/bootloader/defconfig new file mode 100644 index 0000000000..c1438ff2b6 --- /dev/null +++ b/boards/holybro/kakuteh7v2/nuttx-config/bootloader/defconfig @@ -0,0 +1,114 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_DEV_CONSOLE is not set +# CONFIG_DISABLE_PSEUDOFS_OPERATIONS is not set +# CONFIG_DISABLE_PTHREAD is not set +# CONFIG_SPI_EXCHANGE is not set +# CONFIG_STM32H7_SYSCFG is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD_CUSTOM=y +CONFIG_ARCH_BOARD_CUSTOM_DIR="../../../../boards/holybro/kakuteh7v2/nuttx-config" +CONFIG_ARCH_BOARD_CUSTOM_DIR_RELPATH=y +CONFIG_ARCH_BOARD_CUSTOM_NAME="px4" +CONFIG_ARCH_CHIP="stm32h7" +CONFIG_ARCH_CHIP_STM32H743VI=y +CONFIG_ARCH_CHIP_STM32H7=y +CONFIG_ARCH_INTERRUPTSTACK=512 +CONFIG_ARMV7M_BASEPRI_WAR=y +CONFIG_ARMV7M_ICACHE=y +CONFIG_ARMV7M_MEMCPY=y +CONFIG_ARMV7M_USEBASEPRI=y +CONFIG_BOARDCTL_RESET=y +CONFIG_BOARDCTL=y +CONFIG_BOARD_INITTHREAD_PRIORITY=254 +CONFIG_BOARD_LATE_INITIALIZE=y +CONFIG_BOARD_LOOPSPERMSEC=22114 +CONFIG_BOARD_RESET_ON_ASSERT=2 +CONFIG_BOARD_ASSERT_RESET_VALUE=0 +CONFIG_C99_BOOL8=y +CONFIG_CDCACM=y +CONFIG_CDCACM_IFLOWCONTROL=y +CONFIG_CDCACM_PRODUCTID=0x0050 +CONFIG_CDCACM_PRODUCTSTR="PX4 BL Holybro KakuteH7v2" +CONFIG_CDCACM_RXBUFSIZE=600 +CONFIG_CDCACM_TXBUFSIZE=12000 +CONFIG_CDCACM_VENDORID=0x3162 +CONFIG_CDCACM_VENDORSTR="Holybro" +CONFIG_CLOCK_MONOTONIC=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEFAULT_SMALL=y +# CONFIG_NSH_DISABLE_ECHO is not set +# CONFIG_NSH_DISABLE_ENV is not set +# CONFIG_NSH_DISABLE_FREE is not set +# CONFIG_NSH_DISABLE_HELP is not set +# CONFIG_NSH_DISABLE_KILL is not set +# CONFIG_NSH_DISABLE_LS is not set +# CONFIG_NSH_DISABLE_MKDIR is not set +# CONFIG_NSH_DISABLE_MODCMDS is not set +# CONFIG_NSH_DISABLE_MOUNT is not set +# CONFIG_NSH_DISABLE_MV is not set +# CONFIG_NSH_DISABLE_PRINTF is not set +# CONFIG_NSH_DISABLE_PSSTACKUSAGE +# CONFIG_NSH_DISABLE_PWD is not set +# CONFIG_NSH_DISABLE_SOURCE is not set +# CONFIG_NSH_DISABLE_SLEEP is not set +# CONFIG_NSH_DISABLE_TEST is not set +# CONFIG_NSH_DISABLE_UMOUNT is not set +# CONFIG_NSH_DISABLE_UNSET is not set +# CONFIG_NSH_DISABLE_USLEEP is not set +CONFIG_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_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_OTGFS=y +CONFIG_STM32H7_PROGMEM=y +CONFIG_STM32H7_SERIAL_DISABLE_REORDERING=y +CONFIG_STM32H7_TIM1=y +CONFIG_STM32H7_USART3=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_USART3_RXBUFSIZE=600 +CONFIG_USART3_TXBUFSIZE=300 +CONFIG_USBDEV=y +CONFIG_USBDEV_BUSPOWERED=y +CONFIG_USBDEV_MAXPOWER=500 +CONFIG_USEC_PER_TICK=1000 +CONFIG_INIT_STACKSIZE=2944 +CONFIG_INIT_ENTRYPOINT="bootloader_main" diff --git a/boards/holybro/kakuteh7v2/nuttx-config/include/board.h b/boards/holybro/kakuteh7v2/nuttx-config/include/board.h new file mode 100644 index 0000000000..83245ff925 --- /dev/null +++ b/boards/holybro/kakuteh7v2/nuttx-config/include/board.h @@ -0,0 +1,419 @@ +/************************************************************************************ + * + * Copyright (C) 2016-2019 Gregory Nutt. 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 NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ +#pragma once + +/************************************************************************************ + * 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 holybro KakuteH7 board provides the following clock sources: + * + * X1: 8 MHz crystal for HSE + * + * So we have these clock source available within the STM32 + * + * HSI: 16 MHz RC factory-trimmed + * HSE: 8 MHz crystal for HSE + */ + +#define STM32_BOARD_XTAL 8000000ul + +#define STM32_HSI_FREQUENCY 16000000ul +#define STM32_LSI_FREQUENCY 32000 +#define STM32_HSE_FREQUENCY STM32_BOARD_XTAL +#define STM32_LSE_FREQUENCY 32768 + +/* Main PLL Configuration. + * + * PLL source is HSE = 8,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 = (8,000,000 / 1) * 120 = 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(120) +#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) * 120) +#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(2) +#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 / 2) * 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(2) +#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 / 2) * 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 holybro KakuteH7 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_NLEDS 1 + +#define BOARD_LED_RED BOARD_LED1 + +/* LED bits for use with board_userled_all() */ + +#define BOARD_LED1_BIT (1 << BOARD_LED1) + +/* If CONFIG_ARCH_LEDS is defined, the usage by the board port is defined in + * include/board.h and src/stm32_leds.c. The LEDs are used to encode OS-related + * events as follows: + * + * + * SYMBOL Meaning LED state + * Red Green Blue + * ---------------------- -------------------------- ------ ------ ----*/ + +#define LED_STARTED 0 /* NuttX has been started OFF OFF OFF */ +#define LED_HEAPALLOCATE 1 /* Heap has been allocated OFF OFF ON */ +#define LED_IRQSENABLED 2 /* Interrupts enabled OFF ON OFF */ +#define LED_STACKCREATED 3 /* Idle stack created OFF ON ON */ +#define LED_INIRQ 4 /* In an interrupt N/C N/C GLOW */ +#define LED_SIGNAL 5 /* In a signal handler N/C GLOW N/C */ +#define LED_ASSERTION 6 /* An assertion failed GLOW N/C GLOW */ +#define LED_PANIC 7 /* The system has crashed Blink OFF N/C */ +#define LED_IDLE 8 /* MCU is is sleep mode ON OFF OFF */ + +/* Thus if the Green LED is statically on, NuttX has successfully booted and + * is, apparently, running normally. If the Red LED is flashing at + * approximately 2Hz, then a fatal error has been detected and the system + * has halted. + */ + +/* Alternate function pin selections ************************************************/ + + +#define GPIO_USART1_RX GPIO_USART1_RX_2 /* PA10 */ +#define GPIO_USART1_TX GPIO_USART1_TX_2 /* PA9 */ + +#define GPIO_USART2_RX GPIO_USART2_RX_2 /* PD6 */ +#define GPIO_USART2_TX GPIO_USART2_TX_2 /* PD5 */ + +#define GPIO_USART3_RX GPIO_USART3_RX_3 /* PD9 */ +#define GPIO_USART3_TX GPIO_USART3_TX_3 /* PD8 */ + +#define GPIO_UART4_RX GPIO_UART4_RX_5 /* PD0 */ +#define GPIO_UART4_TX GPIO_UART4_TX_5 /* PD1 */ + +#define GPIO_USART6_RX GPIO_USART6_RX_1 /* PC7 */ +#define GPIO_USART6_TX GPIO_USART6_TX_1 /* PC6 */ + +#define GPIO_UART7_RX GPIO_UART7_RX_3 /* PE7 */ +#define GPIO_UART7_TX GPIO_UART7_TX_3 /* PE8 */ + +/* SPI + * SPI1 SD Card + * SPI2 is OSD AT7456E + * SPI4 is IMU + */ + +#define GPIO_SPI1_MISO GPIO_SPI1_MISO_1 /* PA6 */ +#define GPIO_SPI1_MOSI GPIO_SPI1_MOSI_1 /* PA7 */ +#define GPIO_SPI1_SCK GPIO_SPI1_SCK_1 /* PA5 */ + +#define GPIO_SPI2_MISO GPIO_SPI2_MISO_1 /* PB14 */ +#define GPIO_SPI2_MOSI GPIO_SPI2_MOSI_1 /* PB15 */ +#define GPIO_SPI2_SCK GPIO_SPI2_SCK_4 /* PB13 */ + +#define GPIO_SPI4_MISO GPIO_SPI4_MISO_2 /* PE5 */ +#define GPIO_SPI4_MOSI GPIO_SPI4_MOSI_2 /* PE6 */ +#define GPIO_SPI4_SCK GPIO_SPI4_SCK_2 /* PE2 */ + +/* I2C + */ + +#define GPIO_I2C1_SCL GPIO_I2C1_SCL_1 /* PB6 */ +#define GPIO_I2C1_SDA GPIO_I2C1_SDA_1 /* PB7 */ + +#define GPIO_I2C1_SCL_GPIO (GPIO_OUTPUT | GPIO_OPENDRAIN |GPIO_SPEED_50MHz | GPIO_OUTPUT_SET | GPIO_PORTB | GPIO_PIN6) +#define GPIO_I2C1_SDA_GPIO (GPIO_OUTPUT | GPIO_OPENDRAIN |GPIO_SPEED_50MHz | GPIO_OUTPUT_SET | GPIO_PORTB | GPIO_PIN7) + +/* SDMMC1 + * + * VDD 3.3 + * GND + * SDMMC1_CK PC12 + * SDMMC1_CMD PD2 + * SDMMC1_D0 PC8 + * SDMMC1_D1 PC9 + * SDMMC1_D2 PC10 + * SDMMC1_D3 PC11 + * GPIO_SDMMC1_NCD PG0 + */ + +/* USB + * + * OTG_FS_DM PA11 + * OTG_FS_DP PA12 + * VBUS PA9 + */ + + +/* Board provides GPIO or other Hardware for signaling to timing analyzer */ + +# define PROBE_INIT(mask) +# define PROBE(n,s) +# define PROBE_MARK(n) + diff --git a/boards/holybro/kakuteh7v2/nuttx-config/include/board_dma_map.h b/boards/holybro/kakuteh7v2/nuttx-config/include/board_dma_map.h new file mode 100644 index 0000000000..1954ce3e68 --- /dev/null +++ b/boards/holybro/kakuteh7v2/nuttx-config/include/board_dma_map.h @@ -0,0 +1,40 @@ +/**************************************************************************** + * + * Copyright (c) 2020 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#pragma once + +#define DMAMAP_SPI4_RX DMAMAP_DMA12_SPI4RX_1 /* DMA2 */ +#define DMAMAP_SPI4_TX DMAMAP_DMA12_SPI4TX_1 /* DMA2 */ + +#define DMAMAP_USART2_RX DMAMAP_DMA12_USART2RX_1 /* DMA2 */ + diff --git a/boards/holybro/kakuteh7v2/nuttx-config/nsh/defconfig b/boards/holybro/kakuteh7v2/nuttx-config/nsh/defconfig new file mode 100644 index 0000000000..be0c62cbbc --- /dev/null +++ b/boards/holybro/kakuteh7v2/nuttx-config/nsh/defconfig @@ -0,0 +1,272 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_DISABLE_ENVIRON is not set +# CONFIG_DISABLE_PSEUDOFS_OPERATIONS is not set +# CONFIG_DISABLE_PTHREAD is not set +# CONFIG_MMCSD_HAVE_CARDDETECT is not set +# CONFIG_MMCSD_HAVE_WRITEPROTECT is not set +# CONFIG_MMCSD_MMCSUPPORT is not set +# CONFIG_NSH_DISABLEBG is not set +# CONFIG_NSH_DISABLESCRIPT is not set +# CONFIG_NSH_DISABLE_CAT is not set +# CONFIG_NSH_DISABLE_CD is not set +# CONFIG_NSH_DISABLE_CP is not set +# CONFIG_NSH_DISABLE_DATE is not set +# CONFIG_NSH_DISABLE_DF is not set +# CONFIG_NSH_DISABLE_ECHO is not set +# CONFIG_NSH_DISABLE_ENV is not set +# CONFIG_NSH_DISABLE_EXEC is not set +# CONFIG_NSH_DISABLE_EXIT is not set +# CONFIG_NSH_DISABLE_EXPORT is not set +# CONFIG_NSH_DISABLE_FREE is not set +# CONFIG_NSH_DISABLE_GET is not set +# CONFIG_NSH_DISABLE_HELP is not set +# CONFIG_NSH_DISABLE_ITEF is not set +# CONFIG_NSH_DISABLE_KILL is not set +# CONFIG_NSH_DISABLE_LOOPS is not set +# CONFIG_NSH_DISABLE_LS is not set +# CONFIG_NSH_DISABLE_MKDIR is not set +# CONFIG_NSH_DISABLE_MKFATFS is not set +# CONFIG_NSH_DISABLE_MOUNT is not set +# CONFIG_NSH_DISABLE_MV is not set +# CONFIG_NSH_DISABLE_PS is not set +# CONFIG_NSH_DISABLE_PSSTACKUSAGE is not set +# CONFIG_NSH_DISABLE_PWD is not set +# CONFIG_NSH_DISABLE_RM is not set +# CONFIG_NSH_DISABLE_RMDIR is not set +# CONFIG_NSH_DISABLE_SEMICOLON is not set +# CONFIG_NSH_DISABLE_SET is not set +# CONFIG_NSH_DISABLE_SLEEP is not set +# CONFIG_NSH_DISABLE_SOURCE is not set +# CONFIG_NSH_DISABLE_TEST is not set +# CONFIG_NSH_DISABLE_TIME is not set +# CONFIG_NSH_DISABLE_UMOUNT is not set +# CONFIG_NSH_DISABLE_UNSET is not set +# CONFIG_NSH_DISABLE_USLEEP is not set +# CONFIG_SPI_CALLBACK is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD_CUSTOM=y +CONFIG_ARCH_BOARD_CUSTOM_DIR="../../../../boards/holybro/kakuteh7v2/nuttx-config" +CONFIG_ARCH_BOARD_CUSTOM_DIR_RELPATH=y +CONFIG_ARCH_BOARD_CUSTOM_NAME="px4" +CONFIG_ARCH_CHIP="stm32h7" +CONFIG_ARCH_CHIP_STM32H743II=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_BOARDCTL=y +CONFIG_BOARD_CRASHDUMP=y +CONFIG_BOARD_LOOPSPERMSEC=95150 +CONFIG_BOARD_RESET_ON_ASSERT=2 +CONFIG_BOARD_ASSERT_RESET_VALUE=0 +CONFIG_BUILTIN=y +CONFIG_C99_BOOL8=y +CONFIG_CDCACM=y +CONFIG_CDCACM_IFLOWCONTROL=y +CONFIG_CDCACM_PRODUCTID=0x0050 +CONFIG_CDCACM_PRODUCTSTR="PX4 KakuteH7v2" +CONFIG_CDCACM_RXBUFSIZE=600 +CONFIG_CDCACM_TXBUFSIZE=12000 +CONFIG_CDCACM_VENDORID=0x3162 +CONFIG_CDCACM_VENDORSTR="Holybro" +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_NSH_DISABLE_ECHO is not set +# CONFIG_NSH_DISABLE_ENV is not set +# CONFIG_NSH_DISABLE_FREE is not set +# CONFIG_NSH_DISABLE_HELP is not set +# CONFIG_NSH_DISABLE_KILL is not set +# CONFIG_NSH_DISABLE_LS is not set +# CONFIG_NSH_DISABLE_MKDIR is not set +# CONFIG_NSH_DISABLE_MODCMDS is not set +# CONFIG_NSH_DISABLE_MOUNT is not set +# CONFIG_NSH_DISABLE_MV is not set +# CONFIG_NSH_DISABLE_PRINTF is not set +# CONFIG_NSH_DISABLE_PSSTACKUSAGE +# CONFIG_NSH_DISABLE_PWD is not set +# CONFIG_NSH_DISABLE_SOURCE is not set +# CONFIG_NSH_DISABLE_SLEEP is not set +# CONFIG_NSH_DISABLE_TEST is not set +# CONFIG_NSH_DISABLE_UMOUNT is not set +# CONFIG_NSH_DISABLE_UNSET is not set +# CONFIG_NSH_DISABLE_USLEEP is not set +CONFIG_DEV_FIFO_SIZE=0 +CONFIG_DEV_PIPE_MAXSIZE=1024 +CONFIG_DEV_PIPE_SIZE=70 +CONFIG_EXPERIMENTAL=y +CONFIG_FAT_DMAMEMORY=y +CONFIG_FAT_LCNAMES=y +CONFIG_FAT_LFN=y +CONFIG_FAT_LFN_ALIAS_HASH=y +CONFIG_FDCLONE_STDIO=y +CONFIG_FS_BINFS=y +CONFIG_FS_CROMFS=y +CONFIG_FS_FAT=y +CONFIG_FS_FATTIME=y +CONFIG_FS_PROCFS=y +CONFIG_FS_PROCFS_INCLUDE_PROGMEM=y +CONFIG_FS_PROCFS_MAX_TASKS=64 +CONFIG_FS_PROCFS_REGISTER=y +CONFIG_FS_ROMFS=y +CONFIG_GRAN=y +CONFIG_GRAN_INTR=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_I2C=y +CONFIG_I2C_RESET=y +CONFIG_IDLETHREAD_STACKSIZE=750 +CONFIG_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_MM_REGIONS=4 +CONFIG_MTD=y +CONFIG_MTD_BYTE_WRITE=y +CONFIG_MTD_PARTITION=y +CONFIG_MTD_PROGMEM=y +CONFIG_MTD_RAMTRON=y +CONFIG_NAME_MAX=40 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_ARGCAT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_CMDPARMS=y +CONFIG_NSH_CROMFSETC=y +CONFIG_NSH_DISABLE_IFCONFIG=y +CONFIG_NSH_DISABLE_IFUPDOWN=y +CONFIG_NSH_DISABLE_TELNETD=y +CONFIG_NSH_LINELEN=128 +CONFIG_NSH_MAXARGUMENTS=15 +CONFIG_NSH_MMCSDSPIPORTNO=1 +CONFIG_NSH_NESTDEPTH=8 +CONFIG_NSH_QUOTE=y +CONFIG_NSH_ROMFSETC=y +CONFIG_NSH_ROMFSSECTSIZE=128 +CONFIG_NSH_STRERROR=y +CONFIG_NSH_VARS=y +CONFIG_OTG_ID_GPIO_DISABLE=y +CONFIG_PIPES=y +CONFIG_PREALLOC_TIMERS=50 +CONFIG_PRIORITY_INHERITANCE=y +CONFIG_PTHREAD_MUTEX_ROBUST=y +CONFIG_PTHREAD_STACK_MIN=512 +CONFIG_RAMTRON_SETSPEED=y +CONFIG_RAM_SIZE=245760 +CONFIG_RAM_START=0x20010000 +CONFIG_RAW_BINARY=y +CONFIG_READLINE_CMD_HISTORY=y +CONFIG_READLINE_TABCOMPLETION=y +CONFIG_RTC_DATETIME=y +CONFIG_LIBC_MAX_EXITFUNS=1 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_HPWORKPRIORITY=249 +CONFIG_SCHED_HPWORKSTACKSIZE=1280 +CONFIG_SCHED_INSTRUMENTATION=y +CONFIG_SCHED_INSTRUMENTATION_EXTERNAL=y +CONFIG_SCHED_INSTRUMENTATION_SWITCH=y +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_LPWORKPRIORITY=50 +CONFIG_SCHED_LPWORKSTACKSIZE=1632 +CONFIG_SCHED_WAITPID=y +CONFIG_SDCLONE_DISABLE=y +CONFIG_SEM_PREALLOCHOLDERS=32 +CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS=y +CONFIG_SERIAL_TERMIOS=y +CONFIG_SIG_DEFAULT=y +CONFIG_SIG_SIGALRM_ACTION=y +CONFIG_SIG_SIGUSR1_ACTION=y +CONFIG_SIG_SIGUSR2_ACTION=y +CONFIG_SIG_SIGWORK=4 +CONFIG_STACK_COLORATION=y +CONFIG_START_DAY=30 +CONFIG_START_MONTH=11 +CONFIG_STDIO_BUFFER_SIZE=256 +CONFIG_STM32H7_ADC1=y +CONFIG_STM32H7_ADC3=y +CONFIG_STM32H7_BBSRAM=y +CONFIG_STM32H7_BBSRAM_FILES=5 +CONFIG_STM32H7_BDMA=y +CONFIG_STM32H7_BKPSRAM=y +CONFIG_STM32H7_DMA1=y +CONFIG_STM32H7_DMA2=y +CONFIG_STM32H7_DMACAPABLE=y +CONFIG_STM32H7_FLOWCONTROL_BROKEN=y +CONFIG_STM32H7_I2C1=y +CONFIG_STM32H7_I2C_DYNTIMEO=y +CONFIG_STM32H7_I2C_DYNTIMEO_STARTSTOP=10 +CONFIG_STM32H7_OTGFS=y +CONFIG_STM32H7_PROGMEM=y +CONFIG_STM32H7_RTC=y +CONFIG_STM32H7_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY=y +CONFIG_STM32H7_RTC_MAGIC_REG=1 +CONFIG_STM32H7_SAVE_CRASHDUMP=y +CONFIG_STM32H7_SDMMC1=y +CONFIG_STM32H7_SERIALBRK_BSDCOMPAT=y +CONFIG_STM32H7_SERIAL_DISABLE_REORDERING=y +CONFIG_STM32H7_SPI1=y +CONFIG_STM32H7_SPI2=y +CONFIG_STM32H7_SPI4=y +CONFIG_STM32H7_SPI4_DMA=y +CONFIG_STM32H7_SPI4_DMA_BUFFER=1024 +CONFIG_STM32H7_SPI_DMA=y +CONFIG_STM32H7_UART4=y +CONFIG_STM32H7_UART7=y +CONFIG_STM32H7_USART1=y +CONFIG_STM32H7_USART2=y +CONFIG_STM32H7_USART3=y +CONFIG_STM32H7_USART6=y +CONFIG_STM32H7_USART_BREAKS=y +CONFIG_STM32H7_USART_INVERT=y +CONFIG_STM32H7_USART_SINGLEWIRE=y +CONFIG_STM32H7_USART_SWAP=y +CONFIG_SYSTEM_CDCACM=y +CONFIG_SYSTEM_NSH=y +CONFIG_TASK_NAME_SIZE=24 +CONFIG_TTY_SIGINT=y +CONFIG_TTY_SIGTSTP=y +CONFIG_UART4_BAUD=57600 +CONFIG_UART4_RXBUFSIZE=600 +CONFIG_UART4_TXBUFSIZE=1500 +CONFIG_UART7_BAUD=57600 +CONFIG_UART7_RXBUFSIZE=600 +CONFIG_UART7_TXBUFSIZE=1500 +CONFIG_USART1_BAUD=57600 +CONFIG_USART1_RXBUFSIZE=600 +CONFIG_USART1_TXBUFSIZE=1500 +CONFIG_USART2_BAUD=57600 +CONFIG_USART2_RXBUFSIZE=600 +CONFIG_USART2_RXDMA=y +CONFIG_USART2_TXBUFSIZE=2500 +CONFIG_USART3_BAUD=57600 +CONFIG_USART3_RXBUFSIZE=600 +CONFIG_USART3_SERIAL_CONSOLE=y +CONFIG_USART3_TXBUFSIZE=1500 +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_INIT_STACKSIZE=2944 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_WATCHDOG=y diff --git a/boards/holybro/kakuteh7v2/nuttx-config/scripts/bootloader_script.ld b/boards/holybro/kakuteh7v2/nuttx-config/scripts/bootloader_script.ld new file mode 100644 index 0000000000..fc0a5589be --- /dev/null +++ b/boards/holybro/kakuteh7v2/nuttx-config/scripts/bootloader_script.ld @@ -0,0 +1,215 @@ +/**************************************************************************** + * scripts/script.ld + * + * Copyright (C) 2016, 2019 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* The KakuteH7 uses an STM32H743VI 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 STM32H743VI, 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 KakuteH7 has a switch on board, the BOOT0 pin is at ground so by default, + * the STM32 will boot to address 0x0800:0000 in FLASH unless the switch is + * depressed, then the boot will be from 0x1FF0:0000 + * + * The STM32H743VI 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/holybro/kakuteh7v2/nuttx-config/scripts/script.ld b/boards/holybro/kakuteh7v2/nuttx-config/scripts/script.ld new file mode 100644 index 0000000000..ae07f4bfca --- /dev/null +++ b/boards/holybro/kakuteh7v2/nuttx-config/scripts/script.ld @@ -0,0 +1,228 @@ +/**************************************************************************** + * scripts/script.ld + * + * Copyright (C) 2016, 2019 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* The KakuteH7 uses an STM32H743VI 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 STM32H743VI, 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 KakuteH7 has a switch on board, the BOOT0 pin is at ground so by default, + * the STM32 will boot to address 0x0800:0000 in FLASH unless the switch is + * depressed, then the boot will be from 0x1FF0:0000 + * + * The STM32H743VI also has 1024Kb of data SRAM. + * SRAM is split up into several blocks and into three power domains: + * + * 1) TCM SRAMs are dedicated to the Cortex-M7 and are accessible with + * 0 wait states by the Cortex-M7 and by MDMA through AHBS slave bus + * + * 1.1) 128Kb of DTCM-RAM beginning at address 0x2000:0000 + * + * The DTCM-RAM is organized as 2 x 64Kb DTCM-RAMs on 2 x 32 bit + * DTCM ports. The DTCM-RAM could be used for critical real-time + * data, such as interrupt service routines or stack / heap memory. + * Both DTCM-RAMs can be used in parallel (for load/store operations) + * thanks to the Cortex-M7 dual issue capability. + * + * 1.2) 64Kb of ITCM-RAM beginning at address 0x0000:0000 + * + * This RAM is connected to ITCM 64-bit interface designed for + * execution of critical real-times routines by the CPU. + * + * 2) AXI SRAM (D1 domain) accessible by all system masters except BDMA + * through D1 domain AXI bus matrix + * + * 2.1) 512Kb of SRAM beginning at address 0x2400:0000 + * + * 3) AHB SRAM (D2 domain) accessible by all system masters except BDMA + * through D2 domain AHB bus matrix + * + * 3.1) 128Kb of SRAM1 beginning at address 0x3000:0000 + * 3.2) 128Kb of SRAM2 beginning at address 0x3002:0000 + * 3.3) 32Kb of SRAM3 beginning at address 0x3004:0000 + * + * SRAM1 - SRAM3 are one contiguous block: 288Kb at address 0x3000:0000 + * + * 4) AHB SRAM (D3 domain) accessible by most of system masters + * through D3 domain AHB bus matrix + * + * 4.1) 64Kb of SRAM4 beginning at address 0x3800:0000 + * 4.1) 4Kb of backup RAM beginning at address 0x3880:0000 + * + * When booting from FLASH, FLASH memory is aliased to address 0x0000:0000 + * where the code expects to begin execution by jumping to the entry point in + * the 0x0800:0000 address range. + */ + +MEMORY +{ + ITCM_RAM (rwx) : ORIGIN = 0x00000000, LENGTH = 64K + FLASH (rx) : ORIGIN = 0x08020000, LENGTH = 1792K /* params in last sector */ + + DTCM1_RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 64K + DTCM2_RAM (rwx) : ORIGIN = 0x20010000, LENGTH = 64K + AXI_SRAM (rwx) : ORIGIN = 0x24000000, LENGTH = 512K /* D1 domain AXI bus */ + SRAM1 (rwx) : ORIGIN = 0x30000000, LENGTH = 128K /* D2 domain AHB bus */ + SRAM2 (rwx) : ORIGIN = 0x30020000, LENGTH = 128K /* D2 domain AHB bus */ + SRAM3 (rwx) : ORIGIN = 0x30040000, LENGTH = 32K /* D2 domain AHB bus */ + SRAM4 (rwx) : ORIGIN = 0x38000000, LENGTH = 64K /* D3 domain */ + BKPRAM (rwx) : ORIGIN = 0x38800000, LENGTH = 4K +} + +OUTPUT_ARCH(arm) +EXTERN(_vectors) +ENTRY(_stext) + +/* + * Ensure that abort() is present in the final object. The exception handling + * code pulled in by libgcc.a requires it (and that code cannot be easily avoided). + */ +EXTERN(abort) +EXTERN(_bootdelay_signature) + +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/holybro/kakuteh7v2/src/CMakeLists.txt b/boards/holybro/kakuteh7v2/src/CMakeLists.txt new file mode 100644 index 0000000000..220642b2a5 --- /dev/null +++ b/boards/holybro/kakuteh7v2/src/CMakeLists.txt @@ -0,0 +1,67 @@ +############################################################################ +# +# 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 + i2c.cpp + init.c + led.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/holybro/kakuteh7v2/src/board_config.h b/boards/holybro/kakuteh7v2/src/board_config.h new file mode 100644 index 0000000000..99395eabb9 --- /dev/null +++ b/boards/holybro/kakuteh7v2/src/board_config.h @@ -0,0 +1,213 @@ +/**************************************************************************** + * + * Copyright (c) 2019 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 + * + * holybro KakuteH7 internal definitions + */ + +#pragma once + +/**************************************************************************************************** + * Included Files + ****************************************************************************************************/ + +#include +#include +#include + +#include + +/**************************************************************************************************** + * Definitions + ****************************************************************************************************/ + +/* Configuration ************************************************************************************/ + +# define BOARD_HAS_USB_VALID 1 +# define BOARD_HAS_NBAT_V 1 +# define BOARD_HAS_NBAT_I 1 + +/* Holybro KakuteH7 GPIOs ************************************************************************/ + +/* LEDs are driven with push open drain to support Anode to 5V or 3.3V */ + +#define GPIO_nLED_RED /* PC2 */ (GPIO_OUTPUT|GPIO_OPENDRAIN|GPIO_SPEED_50MHz|GPIO_OUTPUT_SET|GPIO_PORTC|GPIO_PIN2) + +#define BOARD_HAS_CONTROL_STATUS_LEDS 1 +#define BOARD_OVERLOAD_LED LED_RED + +/* + * 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) + +/* Define GPIO pins used as ADC N.B. Channel numbers must match below */ + +#define PX4_ADC_GPIO \ + /* PC0 */ GPIO_ADC123_INP10, \ + /* PC1 */ GPIO_ADC123_INP11, \ + /* PC5 */ GPIO_ADC12_INP8 + +/* Define Channel numbers must match above GPIO pin IN(n)*/ + +#define ADC_BATTERY_VOLTAGE_CHANNEL /* PC0 */ ADC1_CH(10) +#define ADC_BATTERY_CURRENT_CHANNEL /* PC1 */ ADC1_CH(11) +#define ADC_RSSI_IN_CHANNEL /* PC5 */ ADC1_CH(8) + +#define ADC_CHANNELS \ + ((1 << ADC_BATTERY_VOLTAGE_CHANNEL) | \ + (1 << ADC_BATTERY_CURRENT_CHANNEL) | \ + (1 << ADC_RSSI_IN_CHANNEL)) + +#define BOARD_ADC_OPEN_CIRCUIT_V (5.6f) + + + +/* PWM + */ +#define DIRECT_PWM_OUTPUT_CHANNELS 8 + +#define BOARD_NUM_IO_TIMERS 4 + + +/* Tone alarm output */ + +#define GPIO_TONE_ALARM_IDLE /* PC13 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTC|GPIO_PIN13) +#define GPIO_TONE_ALARM_GPIO /* PC13 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTC|GPIO_PIN13) + +/* USB OTG FS + * + * PA9 OTG_FS_VBUS VBUS sensing + */ +#define GPIO_OTGFS_VBUS /* PA8 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_SPEED_100MHz|GPIO_PORTA|GPIO_PIN8) + +/* High-resolution timer */ +#define HRT_TIMER 4 /* use timer3 for the HRT */ +#define HRT_TIMER_CHANNEL 1 /* use capture/compare channel 1 */ + +/* RC Serial port */ + +/* PWM input driver. Use FMU AUX5 pins attached to timer4 channel 2 */ + +#define PWMIN_TIMER 5 +#define PWMIN_TIMER_CHANNEL /* T5C1 */ 1 +#define GPIO_PWM_IN /* PA0 */ GPIO_TIM5_CH1IN + +#define GPIO_RSSI_IN /* PC5 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTC|GPIO_PIN5) + +#define GPIO_RF_SWITCH /* PE13 */ (GPIO_OUTPUT|GPIO_PULLDOWN|GPIO_PORTE|GPIO_PIN13) + +/* Power switch controls ******************************************************/ + +#define SDIO_SLOTNO 0 /* Only one slot */ +#define SDIO_MINOR 0 + +/* SD card bringup does not work if performed on the IDLE thread because it + * will cause waiting. Use either: + * + * CONFIG_BOARDCTL=y, OR + * CONFIG_BOARD_INITIALIZE=y && CONFIG_BOARD_INITTHREAD=y + */ + +#if defined(CONFIG_BOARD_INITIALIZE) && !defined(CONFIG_BOARDCTL) && \ + !defined(CONFIG_BOARD_INITTHREAD) +# warning SDIO initialization cannot be perfomed on the IDLE thread +#endif + +/* By Providing BOARD_ADC_USB_CONNECTED (using the px4_arch abstraction) + * this board support the ADC system_power interface, and therefore + * provides the true logic GPIO BOARD_ADC_xxxx macros. + */ +#define BOARD_ADC_USB_CONNECTED (px4_arch_gpioread(GPIO_OTGFS_VBUS)) + +/* Board never powers off the Servo rail */ + +#define BOARD_ADC_SERVO_VALID (1) + +#define BOARD_ADC_BRICK1_VALID (1) + + + +/* This board provides a DMA pool and APIs */ +#define BOARD_DMA_ALLOC_POOL_SIZE 5120 + +/* This board provides the board_on_reset interface */ + +#define BOARD_HAS_ON_RESET 1 + +#define PX4_GPIO_INIT_LIST { \ + PX4_ADC_GPIO, \ + GPIO_TONE_ALARM_IDLE, \ + GPIO_RSSI_IN, \ + GPIO_RF_SWITCH, \ + } + +#define BOARD_ENABLE_CONSOLE_BUFFER + +#define FLASH_BASED_PARAMS + +__BEGIN_DECLS + +/**************************************************************************************************** + * Public Types + ****************************************************************************************************/ + +/**************************************************************************************************** + * Public data + ****************************************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************************************** + * Public Functions + ****************************************************************************************************/ + +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/holybro/kakuteh7v2/src/bootloader_main.c b/boards/holybro/kakuteh7v2/src/bootloader_main.c new file mode 100644 index 0000000000..915b7f3d29 --- /dev/null +++ b/boards/holybro/kakuteh7v2/src/bootloader_main.c @@ -0,0 +1,75 @@ +/**************************************************************************** + * + * Copyright (c) 2019, 2021 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file bootloader_main.c + * + * FMU-specific early startup code for bootloader +*/ + +#include "board_config.h" +#include "bl.h" + +#include +#include +#include +#include +#include +#include "arm_internal.h" +#include + +extern int sercon_main(int c, char **argv); + +__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/holybro/kakuteh7v2/src/hw_config.h b/boards/holybro/kakuteh7v2/src/hw_config.h new file mode 100644 index 0000000000..72b3d6ac6c --- /dev/null +++ b/boards/holybro/kakuteh7v2/src/hw_config.h @@ -0,0 +1,125 @@ +/* + * 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 3000 +#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 BOOT_DELAY_ADDRESS 0x000001a0 +#define BOARD_TYPE 1053 +#define BOARD_FLASH_SECTORS (14) +#define BOARD_FLASH_SIZE (16 * 128 * 1024) +#define APP_RESERVATION_SIZE (1 * 128 * 1024) + +#define OSC_FREQ 8 + +#define BOARD_PIN_LED_ACTIVITY GPIO_nLED_RED +#define BOARD_LED_ON 0 +#define BOARD_LED_OFF 1 + +#define SERIAL_BREAK_DETECT_DISABLED 1 + +/* + * Uncommenting this allows to force the bootloader through + * a PWM output pin. As this can accidentally initialize + * an ESC prematurely, it is not recommended. This feature + * has not been used and hence defaults now to off. + * + * # define BOARD_FORCE_BL_PIN_OUT (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTE|GPIO_PIN14) + * # define BOARD_FORCE_BL_PIN_IN (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTE|GPIO_PIN11) + * + * # define BOARD_POWER_PIN_OUT (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTA|GPIO_PIN4) + * # define BOARD_POWER_ON 1 + * # define BOARD_POWER_OFF 0 + * # undef BOARD_POWER_PIN_RELEASE // Leave pin enabling Power - un comment to release (disable power) + * +*/ + +#if !defined(ARCH_SN_MAX_LENGTH) +# define ARCH_SN_MAX_LENGTH 12 +#endif + +#if !defined(APP_RESERVATION_SIZE) +# define APP_RESERVATION_SIZE 0 +#endif + +#if !defined(BOARD_FIRST_FLASH_SECTOR_TO_ERASE) +# define BOARD_FIRST_FLASH_SECTOR_TO_ERASE 1 +#endif + +#if !defined(USB_DATA_ALIGN) +# define USB_DATA_ALIGN +#endif + +#ifndef BOOT_DEVICES_SELECTION +# define BOOT_DEVICES_SELECTION USB0_DEV|SERIAL0_DEV|SERIAL1_DEV +#endif + +#ifndef BOOT_DEVICES_FILTER_ONUSB +# define BOOT_DEVICES_FILTER_ONUSB USB0_DEV|SERIAL0_DEV|SERIAL1_DEV +#endif + +#endif /* HW_CONFIG_H_ */ diff --git a/boards/holybro/kakuteh7v2/src/i2c.cpp b/boards/holybro/kakuteh7v2/src/i2c.cpp new file mode 100644 index 0000000000..e9f26f9a9e --- /dev/null +++ b/boards/holybro/kakuteh7v2/src/i2c.cpp @@ -0,0 +1,38 @@ +/**************************************************************************** + * + * Copyright (C) 2020 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#include + +constexpr px4_i2c_bus_t px4_i2c_buses[I2C_BUS_MAX_BUS_ITEMS] = { + initI2CBusExternal(1), +}; diff --git a/boards/holybro/kakuteh7v2/src/init.c b/boards/holybro/kakuteh7v2/src/init.c new file mode 100644 index 0000000000..7e55cc1770 --- /dev/null +++ b/boards/holybro/kakuteh7v2/src/init.c @@ -0,0 +1,261 @@ +/**************************************************************************** + * + * Copyright (c) 2012-2019 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file init.c + * + * PX4FMU-specific early startup code. This file implements the + * board_app_initialize() function that is called early by nsh during startup. + * + * Code here is run before the rcS script is invoked; it should start required + * subsystems and perform board-specific initialisation. + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "board_config.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "arm_internal.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +# if defined(FLASH_BASED_PARAMS) +# include +#endif + + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* + * Ideally we'd be able to get these from arm_internal.h, + * but since we want to be able to disable the NuttX use + * of leds for system indication at will and there is no + * separate switch, we need to build independent of the + * CONFIG_ARCH_LEDS configuration switch. + */ +__BEGIN_DECLS +extern void led_init(void); +extern void led_on(int led); +extern void led_off(int led); +__END_DECLS + + +/************************************************************************************ + * Name: board_peripheral_reset + * + * Description: + * + ************************************************************************************/ +__EXPORT void board_peripheral_reset(int ms) +{ +} + +/************************************************************************************ + * 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)); + + board_control_spi_sensors_power_configgpio(); + + /* Turn bluetooth off by default (no mavlink support yet) */ + px4_arch_gpiowrite(GPIO_RF_SWITCH, 0); + + /* configure USB interfaces */ + + stm32_usbinitialize(); + +} + +/**************************************************************************** + * Name: board_app_initialize + * + * Description: + * Perform application specific initialization. This function is never + * called directly from application code, but only indirectly via the + * (non-standard) boardctl() interface using the command BOARDIOC_INIT. + * + * Input Parameters: + * arg - The boardctl() argument is passed to the board_app_initialize() + * implementation without modification. The argument has no + * meaning to NuttX; the meaning of the argument is a contract + * between the board-specific initalization logic and the the + * matching application logic. The value cold be such things as a + * mode enumeration value, a set of DIP switch switch settings, a + * pointer to configuration data read from a file or serial FLASH, + * or whatever you would like to do with it. Every implementation + * should accept zero/NULL as a default configuration. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure to indicate the nature of the failure. + * + ****************************************************************************/ + + +__EXPORT int board_app_initialize(uintptr_t arg) +{ + /* Power on Interfaces */ + board_control_spi_sensors_power(true, 0xffff); + + /* Need hrt running before using the ADC */ + + px4_platform_init(); + + /* configure SPI interfaces */ + + stm32_spiinitialize(); + + /* 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); + + if (board_hardfault_init(2, true) != 0) { + led_on(LED_RED); + } + + /* Get the SPI port for the microSD slot */ + struct spi_dev_s *spi_dev = stm32_spibus_initialize(CONFIG_NSH_MMCSDSPIPORTNO); + + if (!spi_dev) { + syslog(LOG_ERR, "[boot] FAILED to initialize SPI port %d\n", CONFIG_NSH_MMCSDSPIPORTNO); + led_on(LED_BLUE); + } + + up_udelay(20); + + +#if defined(FLASH_BASED_PARAMS) + static sector_descriptor_t params_sector_map[] = { + {15, 128 * 1024, 0x081E0000}, + {0, 0, 0}, + }; + + /* Initialize the flashfs layer to use heap allocated memory */ + int result = parameter_flashfs_init(params_sector_map, NULL, 0); + + if (result != OK) { + syslog(LOG_ERR, "[boot] FAILED to init params in FLASH %d\n", result); + led_on(LED_AMBER); + } + +#endif + + /* Configure the HW based on the manifest */ + + px4_platform_configure(); + + return OK; +} diff --git a/boards/holybro/kakuteh7v2/src/led.c b/boards/holybro/kakuteh7v2/src/led.c new file mode 100644 index 0000000000..945c383eb7 --- /dev/null +++ b/boards/holybro/kakuteh7v2/src/led.c @@ -0,0 +1,223 @@ +/**************************************************************************** + * + * 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. + * + ****************************************************************************/ + +#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_RED, // Indexed by BOARD_LED_RED +}; + +#else + +# define xlat(p) (p) +static uint32_t g_ledmap[] = { + GPIO_nLED_RED, // Indexed by LED_RED, LED_AMBER +}; + +#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/holybro/kakuteh7v2/src/spi.cpp b/boards/holybro/kakuteh7v2/src/spi.cpp new file mode 100644 index 0000000000..a8ce482c5d --- /dev/null +++ b/boards/holybro/kakuteh7v2/src/spi.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** + * + * Copyright (C) 2020, 2021 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#include +#include +#include + +constexpr px4_spi_bus_t px4_spi_buses[SPI_BUS_MAX_BUS_ITEMS] = { + initSPIBus(SPI::Bus::SPI1, { + initSPIDevice(SPIDEV_MMCSD(0), SPI::CS{GPIO::PortA, GPIO::Pin4}) + }), + initSPIBus(SPI::Bus::SPI2, { + initSPIDevice(DRV_OSD_DEVTYPE_ATXXXX, SPI::CS{GPIO::PortB, GPIO::Pin12}), + }), + initSPIBus(SPI::Bus::SPI4, { + initSPIDevice(DRV_IMU_DEVTYPE_ICM20689, SPI::CS{GPIO::PortE, GPIO::Pin4}, SPI::DRDY{GPIO::PortE, GPIO::Pin1}), + initSPIDevice(DRV_IMU_DEVTYPE_MPU6000, SPI::CS{GPIO::PortE, GPIO::Pin4}, SPI::DRDY{GPIO::PortE, GPIO::Pin1}), + initSPIDevice(DRV_IMU_DEVTYPE_BMI270, SPI::CS{GPIO::PortE, GPIO::Pin4}, SPI::DRDY{GPIO::PortE, GPIO::Pin1}), + }), +}; + +static constexpr bool unused = validateSPIConfig(px4_spi_buses); diff --git a/boards/holybro/kakuteh7v2/src/timer_config.cpp b/boards/holybro/kakuteh7v2/src/timer_config.cpp new file mode 100644 index 0000000000..20eb0f15d8 --- /dev/null +++ b/boards/holybro/kakuteh7v2/src/timer_config.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** + * + * 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 + +constexpr io_timers_t io_timers[MAX_IO_TIMERS] = { + initIOTimer(Timer::Timer3, DMA{DMA::Index1}), + initIOTimer(Timer::Timer2, DMA{DMA::Index1}), + initIOTimer(Timer::Timer5, DMA{DMA::Index1}), + initIOTimer(Timer::Timer8, DMA{DMA::Index1}), +}; + +constexpr timer_io_channels_t timer_io_channels[MAX_TIMER_IO_CHANNELS] = { + initIOTimerChannel(io_timers, {Timer::Timer3, Timer::Channel3}, {GPIO::PortB, GPIO::Pin0}), + initIOTimerChannel(io_timers, {Timer::Timer3, Timer::Channel4}, {GPIO::PortB, GPIO::Pin1}), + initIOTimerChannel(io_timers, {Timer::Timer2, Timer::Channel2}, {GPIO::PortB, GPIO::Pin3}), + initIOTimerChannel(io_timers, {Timer::Timer2, Timer::Channel3}, {GPIO::PortB, GPIO::Pin10}), + initIOTimerChannel(io_timers, {Timer::Timer5, Timer::Channel1}, {GPIO::PortA, GPIO::Pin0}), + initIOTimerChannel(io_timers, {Timer::Timer5, Timer::Channel3}, {GPIO::PortA, GPIO::Pin2}), + initIOTimerChannel(io_timers, {Timer::Timer8, Timer::Channel3}, {GPIO::PortC, GPIO::Pin8}), + initIOTimerChannel(io_timers, {Timer::Timer8, Timer::Channel4}, {GPIO::PortC, GPIO::Pin9}), +}; + +constexpr io_timers_channel_mapping_t io_timers_channel_mapping = + initIOTimerChannelMapping(io_timers, timer_io_channels); diff --git a/boards/holybro/kakuteh7v2/src/usb.c b/boards/holybro/kakuteh7v2/src/usb.c new file mode 100644 index 0000000000..6d42476b71 --- /dev/null +++ b/boards/holybro/kakuteh7v2/src/usb.c @@ -0,0 +1,105 @@ +/**************************************************************************** + * + * Copyright (C) 2016 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file px4fmu_usb.c + * + * Board-specific USB functions. + */ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include "board_config.h" + +/************************************************************************************ + * Definitions + ************************************************************************************/ + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_usbinitialize + * + * Description: + * Called to setup USB-related GPIO pins for the PX4FMU board. + * + ************************************************************************************/ + +__EXPORT void stm32_usbinitialize(void) +{ + /* The OTG FS has an internal soft pull-up */ + + /* Configure the OTG FS VBUS sensing GPIO, Power On, and Overcurrent GPIOs */ + +#ifdef CONFIG_STM32H7_OTGFS + stm32_configgpio(GPIO_OTGFS_VBUS); +#endif +} + +/************************************************************************************ + * Name: stm32_usbsuspend + * + * Description: + * Board logic must provide the stm32_usbsuspend logic if the USBDEV driver is + * used. This function is called whenever the USB enters or leaves suspend mode. + * This is an opportunity for the board logic to shutdown clocks, power, etc. + * while the USB is suspended. + * + ************************************************************************************/ + +__EXPORT void stm32_usbsuspend(FAR struct usbdev_s *dev, bool resume) +{ + uinfo("resume: %d\n", resume); +} diff --git a/src/drivers/drv_sensor.h b/src/drivers/drv_sensor.h index b264086bd6..df21cd8875 100644 --- a/src/drivers/drv_sensor.h +++ b/src/drivers/drv_sensor.h @@ -87,7 +87,7 @@ #define DRV_GYR_DEVTYPE_MPU6050 0x35 #define DRV_IMU_DEVTYPE_MPU6500 0x36 - +#define DRV_IMU_DEVTYPE_BMI270 0x37 #define DRV_IMU_DEVTYPE_ICM20602 0x38 #define DRV_IMU_DEVTYPE_ICM20608G 0x3A diff --git a/src/drivers/imu/bosch/bmi270/BMI270.cpp b/src/drivers/imu/bosch/bmi270/BMI270.cpp new file mode 100644 index 0000000000..34e4b3d31f --- /dev/null +++ b/src/drivers/imu/bosch/bmi270/BMI270.cpp @@ -0,0 +1,891 @@ +/**************************************************************************** + * + * 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 "BMI270.hpp" +#define BMI270_DEBUG +#define BMI270_MAX_FIFO_SAMPLES 8 + +using namespace time_literals; + +static constexpr int16_t combine(uint8_t msb, uint8_t lsb) +{ + return (msb << 8u) | lsb; +} + +/** +* The following device config microcode has the following copyright: +* +* Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. +* +* BSD-3-Clause +* +* 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 of the copyright holder 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 HOLDER 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. +*/ +uint8_t maximum_fifo_config_file[] = { 0x5E, + 0xc8, 0x2e, 0x00, 0x2e, 0x80, 0x2e, 0x1a, 0x00, 0xc8, 0x2e, 0x00, 0x2e, 0xc8, 0x2e, 0x00, 0x2e, 0xc8, 0x2e, 0x00, + 0x2e, 0xc8, 0x2e, 0x00, 0x2e, 0xc8, 0x2e, 0x00, 0x2e, 0xc8, 0x2e, 0x00, 0x2e, 0x90, 0x32, 0x21, 0x2e, 0x59, 0xf5, + 0x10, 0x30, 0x21, 0x2e, 0x6a, 0xf5, 0x1a, 0x24, 0x22, 0x00, 0x80, 0x2e, 0x3b, 0x00, 0xc8, 0x2e, 0x44, 0x47, 0x22, + 0x00, 0x37, 0x00, 0xa4, 0x00, 0xff, 0x0f, 0xd1, 0x00, 0x07, 0xad, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, + 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, + 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x11, 0x24, 0xfc, 0xf5, 0x80, 0x30, 0x40, 0x42, 0x50, 0x50, 0x00, 0x30, 0x12, 0x24, 0xeb, + 0x00, 0x03, 0x30, 0x00, 0x2e, 0xc1, 0x86, 0x5a, 0x0e, 0xfb, 0x2f, 0x21, 0x2e, 0xfc, 0xf5, 0x13, 0x24, 0x63, 0xf5, + 0xe0, 0x3c, 0x48, 0x00, 0x22, 0x30, 0xf7, 0x80, 0xc2, 0x42, 0xe1, 0x7f, 0x3a, 0x25, 0xfc, 0x86, 0xf0, 0x7f, 0x41, + 0x33, 0x98, 0x2e, 0xc2, 0xc4, 0xd6, 0x6f, 0xf1, 0x30, 0xf1, 0x08, 0xc4, 0x6f, 0x11, 0x24, 0xff, 0x03, 0x12, 0x24, + 0x00, 0xfc, 0x61, 0x09, 0xa2, 0x08, 0x36, 0xbe, 0x2a, 0xb9, 0x13, 0x24, 0x38, 0x00, 0x64, 0xbb, 0xd1, 0xbe, 0x94, + 0x0a, 0x71, 0x08, 0xd5, 0x42, 0x21, 0xbd, 0x91, 0xbc, 0xd2, 0x42, 0xc1, 0x42, 0x00, 0xb2, 0xfe, 0x82, 0x05, 0x2f, + 0x50, 0x30, 0x21, 0x2e, 0x21, 0xf2, 0x00, 0x2e, 0x00, 0x2e, 0xd0, 0x2e, 0xf0, 0x6f, 0x02, 0x30, 0x02, 0x42, 0x20, + 0x26, 0xe0, 0x6f, 0x02, 0x31, 0x03, 0x40, 0x9a, 0x0a, 0x02, 0x42, 0xf0, 0x37, 0x05, 0x2e, 0x5e, 0xf7, 0x10, 0x08, + 0x12, 0x24, 0x1e, 0xf2, 0x80, 0x42, 0x83, 0x84, 0xf1, 0x7f, 0x0a, 0x25, 0x13, 0x30, 0x83, 0x42, 0x3b, 0x82, 0xf0, + 0x6f, 0x00, 0x2e, 0x00, 0x2e, 0xd0, 0x2e, 0x12, 0x40, 0x52, 0x42, 0x00, 0x2e, 0x12, 0x40, 0x52, 0x42, 0x3e, 0x84, + 0x00, 0x40, 0x40, 0x42, 0x7e, 0x82, 0xe1, 0x7f, 0xf2, 0x7f, 0x98, 0x2e, 0x6a, 0xd6, 0x21, 0x30, 0x23, 0x2e, 0x61, + 0xf5, 0xeb, 0x2c, 0xe1, 0x6f + }; +// end of Bosch microcode copyright + + +BMI270::BMI270(const I2CSPIDriverConfig &config) : + SPI(config), + I2CSPIDriver(config), + _drdy_gpio(config.drdy_gpio), + _px4_accel(get_device_id(), config.rotation), + _px4_gyro(get_device_id(), config.rotation) +{ + if (_drdy_gpio != 0) { + _drdy_missed_perf = perf_alloc(PC_COUNT, MODULE_NAME": DRDY missed"); + } + + ConfigureSampleRate(_px4_gyro.get_max_rate_hz()); +} + +BMI270::~BMI270() +{ + perf_free(_bad_register_perf); + perf_free(_bad_transfer_perf); + perf_free(_fifo_empty_perf); + perf_free(_fifo_overflow_perf); + perf_free(_fifo_reset_perf); + perf_free(_drdy_missed_perf); +} + +int BMI270::init() +{ + int ret = SPI::init(); + + if (ret != PX4_OK) { + DEVICE_DEBUG("SPI::init failed (%i)", ret); + return ret; + } + + PX4_DEBUG("init function called, resetting..."); + + + return Reset() ? 0 : -1; +} + +bool BMI270::Reset() +{ + _state = STATE::RESET; + DataReadyInterruptDisable(); + ScheduleClear(); + ScheduleNow(); + return true; +} + +// Debug function that Ardupilot is equipped with +void BMI270::CheckErrorRegister() +{ +#ifdef BMI270_DEBUG + uint8_t err = RegisterRead(Register::ERR_REG); + + if (err) { + if ((err & 1) == 1) { + uint8_t status = RegisterRead(Register::INTERNAL_STATUS); + + switch (status & 0xF) { + case 0: + PX4_DEBUG("BMI270: not_init"); + break; + + case 2: + PX4_DEBUG("BMI270: init_err"); + break; + + case 3: + PX4_DEBUG("BMI270: drv_err"); + break; + + case 4: + PX4_DEBUG("BMI270: sns_stop"); + break; + + case 5: + PX4_DEBUG("BMI270: nvm_error"); + break; + + case 6: + PX4_DEBUG("BMI270: start_up_error"); + break; + + case 7: + PX4_DEBUG("BMI270: compat_error"); + break; + + case 1: // init ok + if ((status >> 5 & 1) == 1) { + PX4_DEBUG("BMI270: axes_remap_error"); + + } else if ((status >> 6 & 1) == 1) { + PX4_DEBUG("BMI270: odr_50hz_error"); + } + + break; + } + + } else if ((err >> 6 & 1) == 1) { + PX4_DEBUG("BMI270: fifo_err"); + + } else if ((err >> 7 & 1) == 1) { + PX4_DEBUG("BMI270: aux_err"); + + } else { + PX4_DEBUG("BMI270: internal error detected %d", err >> 1 & 0xF); + } + } + +#endif + +} + +void BMI270::exit_and_cleanup() +{ + DataReadyInterruptDisable(); + I2CSPIDriverBase::exit_and_cleanup(); +} + +void BMI270::print_status() +{ + I2CSPIDriverBase::print_status(); + + PX4_INFO("FIFO empty interval: %d us (%.1f Hz)", _fifo_empty_interval_us, 1e6 / _fifo_empty_interval_us); + + perf_print_counter(_bad_register_perf); + perf_print_counter(_bad_transfer_perf); + perf_print_counter(_fifo_empty_perf); + perf_print_counter(_fifo_overflow_perf); + perf_print_counter(_fifo_reset_perf); + perf_print_counter(_drdy_missed_perf); +} + +int BMI270::probe() +{ + // When starting communication with the BMI270, according page 123 of the + // datasheet a rising edge on CSB is required to start SPI. + // It is recommended to just read the CHIP_ID register once to do that + // but ignore the result. + RegisterRead(Register::CHIP_ID); + + // It takes 200us for the device to start SPI communication. + px4_usleep(200); + + const uint8_t CHIP_ID = RegisterRead(Register::CHIP_ID); + + if (CHIP_ID != chip_id) { + DEVICE_DEBUG("unexpected CHIP_ID 0x%02x", CHIP_ID); + return PX4_ERROR; + } + + return PX4_OK; +} + +void BMI270::RunImpl() +{ + const hrt_abstime now = hrt_absolute_time(); + + switch (_state) { + case STATE::RESET: + + // 0xB6 is written to the CMD register for a soft reset + RegisterWrite(Register::CMD, 0xB6); + _reset_timestamp = now; + _failure_count = 0; + _state = STATE::WAIT_FOR_RESET; + ScheduleDelayed(1_ms); // Following a delay of 1 ms, all configuration settings are overwritten with their reset value. + break; + + case STATE::WAIT_FOR_RESET: + + /* + Hardware initialization steps according to datasheet: + 1. Disable PWR_CONF.adv_power_save and wait for 450us + 2. Write 0x00 to INIT_CTRL + 3. Burst write initialization file to INIT_DATA + 4. Write 0x01 to INIT_CTRL + 5. Wait 150ms and read register INTERNAL_STATUS for value 0b001 + 6. If step 5 passed, enter configure state + + + */ + if ((RegisterRead(Register::CHIP_ID) == chip_id)) { + PX4_DEBUG("Read from CHIP_ID register and the IDs match"); + + // 1. Disable PWR_CONF.adv_power_save and wait for 450us + + RegisterWrite(Register::PWR_CONF, 0x00); + _state = STATE::MICROCODE_LOAD; + ScheduleDelayed(450_us); + + } else { + // RESET not complete + if (hrt_elapsed_time(&_reset_timestamp) > 1000_ms) { + PX4_DEBUG("Reset failed, retrying"); + _state = STATE::RESET; + ScheduleDelayed(100_ms); + + } else { + PX4_DEBUG("Reset not complete, check again in 10 ms"); + ScheduleDelayed(10_ms); + } + } + + break; + + case STATE::MICROCODE_LOAD: + + { + + // 2. Write 0x00 to INIT_CTRL + + RegisterWrite(Register::CONFIG1, 0x00); + // give it the maximum FIFO config file + PX4_DEBUG("attempting to upload initialization file onto BMI270"); + + // 3. Burst write initialization file to INIT_DATA + + int res = transfer(maximum_fifo_config_file, nullptr, sizeof(maximum_fifo_config_file)); + + if (res == PX4_OK) { + RegisterWrite(Register::CONFIG1, 1); + PX4_DEBUG("Successfully uploaded initialization file onto BMI270"); + PX4_DEBUG("Preparing to read INTERNAL_STATUS register"); + _state = STATE::CONFIGURE; + ScheduleDelayed(150_ms); + + + } else { + PX4_DEBUG("Failed to upload initialization file onto BMI270, resetting"); + _state = STATE::RESET; + ScheduleDelayed(10_ms); + } + + break; + } + + case STATE::CONFIGURE: + + PX4_DEBUG("IMU now in configure state"); + + if (Configure()) { + + // if configure succeeded then start reading from FIFO + + if (DataReadyInterruptConfigure()) { + _data_ready_interrupt_enabled = true; + + // backup schedule as a watchdog timeout + ScheduleDelayed(100_ms); + + } else { + _data_ready_interrupt_enabled = false; + ScheduleOnInterval(_fifo_empty_interval_us, _fifo_empty_interval_us); + } + + FIFOReset(); + _state = STATE::FIFO_READ; + + + } else { + // CONFIGURE not complete + if (hrt_elapsed_time(&_reset_timestamp) > 1000_ms) { + PX4_DEBUG("Configure failed, resetting"); + _state = STATE::RESET; + + } else { + PX4_DEBUG("Configure failed, retrying"); + } + + ScheduleDelayed(100_ms); + } + + break; + + case STATE::FIFO_READ: { + + PX4_DEBUG("reading from FIFO"); + + hrt_abstime timestamp_sample = now; + + if (_data_ready_interrupt_enabled) { + PX4_DEBUG("data ready interrupt enabled"); + // scheduled from interrupt if _drdy_timestamp_sample was set as expected + const hrt_abstime drdy_timestamp_sample = _drdy_timestamp_sample.fetch_and(0); + + if ((now - drdy_timestamp_sample) < _fifo_empty_interval_us) { + timestamp_sample = drdy_timestamp_sample; + + } else { + perf_count(_drdy_missed_perf); + } + + // push backup schedule back + ScheduleDelayed(_fifo_empty_interval_us * 2); + } + + + + bool success = false; + const uint16_t fifo_count = FIFOReadCount(); + + // more bytes than what the buffer takes so an overflow + if (fifo_count >= FIFO::SIZE) { + FIFOReset(); + perf_count(_fifo_overflow_perf); + + } else if (fifo_count == 0) { + perf_count(_fifo_empty_perf); + + } else { + + uint8_t samples = fifo_count / sizeof(FIFO::Data); + + // tolerate minor jitter, leave sample to next iteration if behind by only 1 + if (samples == _fifo_gyro_samples + 1) { + timestamp_sample -= static_cast(FIFO_SAMPLE_DT); + samples--; + } + + if (samples > FIFO_MAX_SAMPLES) { + // not technically an overflow, but more samples than we expected or can publish + FIFOReset(); + perf_count(_fifo_overflow_perf); + + } else if (samples >= _fifo_gyro_samples) { + if (FIFORead(timestamp_sample, fifo_count)) { + success = true; + + if (_failure_count > 0) { + _failure_count--; + } + } + } + + } + + if (!success) { + _failure_count++; + + // full reset if things are failing consistently + if (_failure_count > 10) { + PX4_DEBUG("failure count > 10, resetting..."); + Reset(); + return; + } + } + + if (!success || hrt_elapsed_time(&_last_config_check_timestamp) > 100_ms) { + // check configuration registers periodically or immediately following any failure + if (RegisterCheck(_register_cfg[_checked_register])) { + _last_config_check_timestamp = now; + _checked_register = (_checked_register + 1) % size_register_cfg; + + } else { + PX4_DEBUG("register check failed, resetting..."); + + // register check failed, force reset + perf_count(_bad_register_perf); + // Reset(); + } + + } else { + // periodically update temperature (~1 Hz) + if (hrt_elapsed_time(&_temperature_update_timestamp) >= 1_s) { + UpdateTemperature(); + _temperature_update_timestamp = now; + } + } + + } + + break; + } +} + +void BMI270::SetAccelScaleAndRange() +{ + const uint8_t ACC_RANGE = RegisterRead(Register::ACC_RANGE) & (Bit1 | Bit0); + + switch (ACC_RANGE) { + case acc_range_2g: + _px4_accel.set_scale(2.f * CONSTANTS_ONE_G / 32768.f); + _px4_accel.set_range(2.f * CONSTANTS_ONE_G); + break; + + case acc_range_4g: + _px4_accel.set_scale(4.f * CONSTANTS_ONE_G / 32768.f); + _px4_accel.set_range(4.f * CONSTANTS_ONE_G); + break; + + case acc_range_8g: + _px4_accel.set_scale(8.f * CONSTANTS_ONE_G / 32768.f); + _px4_accel.set_range(8.f * CONSTANTS_ONE_G); + break; + + case acc_range_16g: + _px4_accel.set_scale(16.f * CONSTANTS_ONE_G / 32768.f); + _px4_accel.set_range(16.f * CONSTANTS_ONE_G); + break; + } +} + +void BMI270::SetGyroScale() +{ + // data is 16 bits with 2000dps range + const float scale = math::radians(2000.0f) / 32767.0f; + _px4_gyro.set_scale(scale); + +} + +void BMI270::ConfigureSampleRate(int sample_rate) +{ + // round down to nearest FIFO sample dt * SAMPLES_PER_TRANSFER + const float min_interval = FIFO_SAMPLE_DT; + _fifo_empty_interval_us = math::max(roundf((1e6f / (float)sample_rate) / min_interval) * min_interval, min_interval); + + // works out to be 2 ... + _fifo_gyro_samples = math::min((float)_fifo_empty_interval_us / (1e6f / RATE), (float)FIFO_MAX_SAMPLES); + + // recompute FIFO empty interval (us) with actual sample limit + _fifo_empty_interval_us = _fifo_gyro_samples * (1e6f / RATE); + + ConfigureFIFOWatermark(_fifo_gyro_samples); +} + + +// when this register is set an interrupt is triggered when the FIFO reaches this many samples +void BMI270::ConfigureFIFOWatermark(uint8_t samples) +{ + // FIFO_WTM: 13 bit FIFO watermark level value + // unit of the fifo watermark is one byte + const uint16_t fifo_watermark_threshold = samples * sizeof(FIFO::Data); + + for (auto &r : _register_cfg) { + if (r.reg == Register::FIFO_WTM_0) { + // fifo_water_mark[7:0] + r.set_bits = fifo_watermark_threshold & 0x00FF; + r.clear_bits = ~r.set_bits; + + } else if (r.reg == Register::FIFO_WTM_1) { + // fifo_water_mark[12:8] + r.set_bits = (fifo_watermark_threshold & 0x0700) >> 8; + r.clear_bits = ~r.set_bits; + } + } +} + +bool BMI270::Configure() +{ + + bool success = false; + + // check internal status first as per datasheet + uint8_t internal_status = RegisterRead(Register::INTERNAL_STATUS); + PX4_DEBUG("Internal status register value: 0x%02hhX", internal_status); + + if ((internal_status & 1) == 1) { + PX4_DEBUG("INTERNAL_STATUS 0x01, ready for configure"); + + } else { + + PX4_DEBUG("INTERNAL_STATUS check failed, resetting"); + _state = STATE::RESET; + ScheduleDelayed(10_ms); + + }; + + + // first set and clear all configured register bits + for (const auto ®_cfg : _register_cfg) { + RegisterSetAndClearBits(reg_cfg.reg, reg_cfg.set_bits, reg_cfg.clear_bits); + } + + // now check that all are configured + + for (const auto ®_cfg : _register_cfg) { + if (!RegisterCheck(reg_cfg)) { + success = false; + } + } + + SetAccelScaleAndRange(); + SetGyroScale(); + + success = true; + return success; +} + +int BMI270::DataReadyInterruptCallback(int irq, void *context, void *arg) +{ + PX4_DEBUG("actual data ready interrupt called"); + static_cast(arg)->DataReady(); + return 0; +} + +void BMI270::DataReady() +{ + _drdy_timestamp_sample.store(hrt_absolute_time()); + ScheduleNow(); +} + +bool BMI270::DataReadyInterruptConfigure() +{ + if (_drdy_gpio == 0) { + return false; + } + + // Setup data ready on falling edge + return px4_arch_gpiosetevent(_drdy_gpio, false, true, true, &DataReadyInterruptCallback, this) == 0; +} + +bool BMI270::DataReadyInterruptDisable() +{ + if (_drdy_gpio == 0) { + return false; + } + + return px4_arch_gpiosetevent(_drdy_gpio, false, false, false, nullptr, nullptr) == 0; +} + +bool BMI270::RegisterCheck(const register_config_t ®_cfg) +{ + bool success = true; + + const uint8_t reg_value = RegisterRead(reg_cfg.reg); + + PX4_DEBUG("0x%02hhX: 0x%02hhX", (uint8_t)reg_cfg.reg, reg_value); + + if (reg_cfg.set_bits && ((reg_value & reg_cfg.set_bits) != reg_cfg.set_bits)) { + PX4_DEBUG("0x%02hhX: 0x%02hhX (0x%02hhX not set)", (uint8_t)reg_cfg.reg, reg_value, reg_cfg.set_bits); + success = false; + } + + if (reg_cfg.clear_bits && ((reg_value & reg_cfg.clear_bits) != 0)) { + PX4_DEBUG("0x%02hhX: 0x%02hhX (0x%02hhX not cleared)", (uint8_t)reg_cfg.reg, reg_value, reg_cfg.clear_bits); + success = false; + } + + return success; +} + +uint8_t BMI270::RegisterRead(Register reg) +{ + // 6.1.2 SPI interface of accelerometer part + // + // In case of read operations of the accelerometer part, the requested data + // is not sent immediately, but instead first a dummy byte is sent, and + // after this dummy byte the actual requested register content is transmitted. + uint8_t cmd[3] {}; + cmd[0] = static_cast(reg) | DIR_READ; + // cmd[1] dummy byte + transfer(cmd, cmd, sizeof(cmd)); + return cmd[2]; +} + +void BMI270::RegisterWrite(Register reg, uint8_t value) +{ + uint8_t cmd[2] { (uint8_t)reg, value }; + transfer(cmd, cmd, sizeof(cmd)); +} + +void BMI270::RegisterSetAndClearBits(Register reg, uint8_t setbits, uint8_t clearbits) +{ + const uint8_t orig_val = RegisterRead(reg); + + uint8_t val = (orig_val & ~clearbits) | setbits; + + if (orig_val != val) { + RegisterWrite(reg, val); + } +} + + +// Checks how many bytes are in the FIFO +uint16_t BMI270::FIFOReadCount() +{ + CheckErrorRegister(); + PX4_DEBUG("Attempting to determine FIFO fill level"); + + // FIFO length registers FIFO_LENGTH_1 and FIFO_LENGTH_0 contain the 14 bit FIFO byte + FIFOLengthReadBuffer buffer {}; + + if (transfer((uint8_t *)&buffer, (uint8_t *)&buffer, sizeof(buffer)) != PX4_OK) { + PX4_DEBUG("Bad transfer"); + perf_count(_bad_transfer_perf); + return 0; + } + + uint16_t fifo_fill_level = combine(buffer.FIFO_LENGTH_1 & 0x3F, buffer.FIFO_LENGTH_0); + + return fifo_fill_level; +} + + +// writes a gyro frame into the FIFO buffer the first argument points to +void BMI270::ProcessGyro(sensor_gyro_fifo_s *gyro, FIFO::Data *frame) +{ + const uint8_t samples = gyro->samples; + + const int16_t gyro_x = combine(frame->x_msb, frame->x_lsb); + const int16_t gyro_y = combine(frame->y_msb, frame->y_lsb); + const int16_t gyro_z = combine(frame->z_msb, frame->z_lsb); + + // Rotate from FLU to NED + gyro->x[samples] = gyro_x; + gyro->y[samples] = (gyro_y == INT16_MIN) ? INT16_MAX : -gyro_y; + gyro->z[samples] = (gyro_z == INT16_MIN) ? INT16_MAX : -gyro_z; + + gyro->samples++; +} + +// writes an accelerometer frame into the FIFO buffer the first argument points to +void BMI270::ProcessAccel(sensor_accel_fifo_s *accel, FIFO::Data *frame) +{ + + const uint8_t samples = accel->samples; + + const int16_t accel_x = combine(frame->x_msb, frame->x_lsb); + const int16_t accel_y = combine(frame->y_msb, frame->y_lsb); + const int16_t accel_z = combine(frame->z_msb, frame->z_lsb); + + // Rotate from FLU to NED + accel->x[samples] = accel_x; + accel->y[samples] = (accel_y == INT16_MIN) ? INT16_MAX : -accel_y; + accel->z[samples] = (accel_z == INT16_MIN) ? INT16_MAX : -accel_z; + + accel->samples++; +} + + +bool BMI270::FIFORead(const hrt_abstime ×tamp_sample, uint16_t fifo_bytes) +{ + + uint8_t err = RegisterRead(Register::ERR_REG); + + if ((err >> 6 & 1) == 1) { + FIFOReset(); + return false; + } + + FIFOReadBuffer buffer{}; + + // Reads from the FIFO_DATA register as much data as is available, + // plus 2 bytes for the sent command and dummy byte. + if (transfer((uint8_t *)&buffer, (uint8_t *)&buffer, fifo_bytes + 2) != PX4_OK) { + PX4_DEBUG("buffer transfer failed"); + perf_count(_bad_transfer_perf); + return false; + } + + sensor_accel_fifo_s accel_buffer{}; + accel_buffer.timestamp_sample = timestamp_sample; + accel_buffer.dt = FIFO_SAMPLE_DT; + + sensor_gyro_fifo_s gyro_buffer{}; + gyro_buffer.timestamp_sample = timestamp_sample; + gyro_buffer.dt = FIFO_SAMPLE_DT; + + uint8_t *data_buffer = (uint8_t *)&buffer.f[0]; + unsigned fifo_buffer_index = 0; // start of buffer + + while (fifo_buffer_index < fifo_bytes) { + // look for header signature (first 6 bits) followed by two bits indicating the status of INT1 and INT2 + switch (data_buffer[fifo_buffer_index]) { + case ((uint8_t)FIFO::Header::sensor_accel_frame | (uint8_t)FIFO::Header::sensor_gyro_frame): { + // Move past header and padding for Aux + fifo_buffer_index += 1; + BMI270::ProcessGyro(&gyro_buffer, (FIFO::Data *)&data_buffer[fifo_buffer_index]); + // Move forward to next record + fifo_buffer_index += 6; + BMI270::ProcessAccel(&accel_buffer, (FIFO::Data *)&data_buffer[fifo_buffer_index]); + // Move forward to next record + fifo_buffer_index += 6; + } + break; + + case (uint8_t)FIFO::Header::sensor_gyro_frame: { + // Move past header. + fifo_buffer_index += 1; + BMI270::ProcessGyro(&gyro_buffer, (FIFO::Data *)&data_buffer[fifo_buffer_index]); + // Move forward to next record + fifo_buffer_index += 6; + } + break; + + case (uint8_t)FIFO::Header::sensor_accel_frame: { + // Move past header. + fifo_buffer_index += 1; + BMI270::ProcessAccel(&accel_buffer, (FIFO::Data *)&data_buffer[fifo_buffer_index]); + // Move forward to next record + fifo_buffer_index += 6; + } + break; + + case (uint8_t)FIFO::Header::skip_frame: + // Skip Frame + // Frame length: 2 bytes (1 byte header + 1 byte payload) + PX4_DEBUG("Skip Frame"); + fifo_buffer_index += 2; + break; + + case (uint8_t)FIFO::Header::sensor_time_frame: + // Sensortime Frame + // Frame length: 4 bytes (1 byte header + 3 bytes payload) + PX4_DEBUG("Sensortime Frame"); + fifo_buffer_index += 4; + break; + + case (uint8_t)FIFO::Header::FIFO_input_config_frame: + // FIFO input config Frame + // Frame length: 2 bytes (1 byte header + 1 byte payload) + PX4_DEBUG("FIFO input config Frame"); + fifo_buffer_index += 2; + break; + + case (uint8_t)FIFO::Header::sample_drop_frame: + // Sample drop Frame + // Frame length: 2 bytes (1 byte header + 1 byte payload) + PX4_DEBUG("Sample drop Frame"); + fifo_buffer_index += 2; + break; + + default: + fifo_buffer_index++; + break; + } + } + + _px4_accel.set_error_count(perf_event_count(_bad_register_perf) + perf_event_count(_bad_transfer_perf) + + perf_event_count(_fifo_empty_perf) + perf_event_count(_fifo_overflow_perf)); + + + if ((accel_buffer.samples == 0) && (gyro_buffer.samples == 0)) { + + return false; + + } else { + if (accel_buffer.samples > 0) { + _px4_accel.updateFIFO(accel_buffer); + } + + if (gyro_buffer.samples > 0) { + _px4_gyro.updateFIFO(gyro_buffer); + } + + return true; + } + +} + + + +void BMI270::FIFOReset() +{ + PX4_DEBUG("Resetting FIFO..."); + perf_count(_fifo_reset_perf); + + // ACC_SOFTRESET: trigger a FIFO reset by writing 0xB0 to ACC_SOFTRESET (register 0x7E). + RegisterWrite(Register::CMD, 0xB0); + + // reset while FIFO is disabled + _drdy_timestamp_sample.store(0); +} + +void BMI270::UpdateTemperature() +{ + uint8_t temperature_buf[4] {}; + temperature_buf[0] = static_cast(Register::TEMP_MSB) | DIR_READ; + + if (transfer(&temperature_buf[0], &temperature_buf[0], sizeof(temperature_buf)) != PX4_OK) { + perf_count(_bad_transfer_perf); + return; + } + + const uint16_t temp = temperature_buf[2] | (temperature_buf[3] << 8); + + float temperature; + + if (temp == 0x8000) { + // invalid + temperature = NAN; + + } else { + constexpr float lsb = 0.001953125f; // 1/2^9 + temperature = 23.0f + (int16_t)temp * lsb; + } + + _px4_accel.set_temperature(temperature); + _px4_gyro.set_temperature(temperature); +} diff --git a/src/drivers/imu/bosch/bmi270/BMI270.hpp b/src/drivers/imu/bosch/bmi270/BMI270.hpp new file mode 100644 index 0000000000..5f3add8078 --- /dev/null +++ b/src/drivers/imu/bosch/bmi270/BMI270.hpp @@ -0,0 +1,193 @@ +/**************************************************************************** + * + * 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 BMI270.hpp + * + * Driver for the Bosch BMI270 connected via SPI. + * + */ + +#pragma once + +#include "Bosch_BMI270_registers.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Bosch_BMI270; + +class BMI270 : public device::SPI, public I2CSPIDriver +{ +public: + BMI270(const I2CSPIDriverConfig &config); + ~BMI270() override; + + static void print_usage(); + + void RunImpl(); + + int init() override; + void print_status() override; + +private: + void exit_and_cleanup() override; + + // Sensor Configuration + static constexpr uint32_t RATE{1600}; // 1600 Hz + static constexpr float FIFO_SAMPLE_DT{1e6f / RATE}; + + static constexpr uint8_t ID_088 = 0x1E; + static constexpr uint8_t ID_090L = 0x1A; + + static constexpr int32_t FIFO_MAX_SAMPLES{math::min(FIFO::SIZE / sizeof(FIFO::Data), sizeof(sensor_accel_fifo_s::x) / sizeof(sensor_accel_fifo_s::x[0]))}; + + + hrt_abstime _temperature_update_timestamp{0}; + + struct FIFOLengthReadBuffer { + uint8_t cmd{static_cast(Register::FIFO_LENGTH_0) | DIR_READ}; + uint8_t dummy{0}; + uint8_t FIFO_LENGTH_0{0}; + uint8_t FIFO_LENGTH_1{0}; + }; + + struct FIFOReadBuffer { + uint8_t cmd{static_cast(Register::FIFO_DATA) | DIR_READ}; + uint8_t dummy{0}; + FIFO::Data f[FIFO_MAX_SAMPLES] {}; + }; + + // ensure no struct padding + static_assert(sizeof(FIFOReadBuffer) == (2 + FIFO_MAX_SAMPLES *sizeof(FIFO::Data))); + + struct register_config_t { + Register reg; + uint8_t set_bits{0}; + uint8_t clear_bits{0}; + }; + + int probe() override; + + bool Reset(); + + bool Configure(); + + void ProcessGyro(sensor_gyro_fifo_s *gyro, FIFO::Data *gyro_frame); + void ProcessAccel(sensor_accel_fifo_s *accel, FIFO::Data *accel_frame); + + bool readAccelFrame(FIFO::Data *accel_frame); + bool readGyroFrame(FIFO::Data *gyro_frame); + + void ConfigurePwr(); + void SetAccelScaleAndRange(); + void SetGyroScale(); + + void CheckErrorRegister(); + + void ConfigureFifo(); + void ConfigureSampleRate(int sample_rate = 0); + void ConfigureFIFOWatermark(uint8_t samples); + + static int DataReadyInterruptCallback(int irq, void *context, void *arg); + void DataReady(); + bool DataReadyInterruptConfigure(); + bool DataReadyInterruptDisable(); + + bool RegisterCheck(const register_config_t ®_cfg); + + uint8_t RegisterRead(Register reg); + void RegisterWrite(Register reg, uint8_t value); + void RegisterSetAndClearBits(Register reg, uint8_t setbits, uint8_t clearbits); + + uint16_t FIFOReadCount(); + //bool FIFORead(const hrt_abstime ×tamp_sample, uint8_t samples); + bool FIFORead(const hrt_abstime ×tamp_sample, uint16_t fifo_bytes); + void FIFOReset(); + + void UpdateTemperature(); + + const spi_drdy_gpio_t _drdy_gpio; + + PX4Accelerometer _px4_accel; + PX4Gyroscope _px4_gyro; + + perf_counter_t _bad_register_perf{perf_alloc(PC_COUNT, MODULE_NAME": bad register")}; + perf_counter_t _bad_transfer_perf{perf_alloc(PC_COUNT, MODULE_NAME": bad transfer")}; + perf_counter_t _fifo_empty_perf{perf_alloc(PC_COUNT, MODULE_NAME": FIFO empty")}; + perf_counter_t _fifo_overflow_perf{perf_alloc(PC_COUNT, MODULE_NAME": FIFO overflow")}; + perf_counter_t _fifo_reset_perf{perf_alloc(PC_COUNT, MODULE_NAME": FIFO reset")}; + + perf_counter_t _drdy_missed_perf{nullptr}; + + hrt_abstime _reset_timestamp{0}; + hrt_abstime _last_config_check_timestamp{0}; + int _failure_count{0}; + + px4::atomic _drdy_timestamp_sample{0}; + bool _data_ready_interrupt_enabled{false}; + + enum class STATE : uint8_t { + WAIT_FOR_RESET, + RESET, + MICROCODE_LOAD, + CONFIGURE, + FIFO_READ, + } _state{STATE::RESET}; + + uint16_t _fifo_empty_interval_us{1250}; // default 1250 us / 800 Hz transfer interval + int32_t _fifo_gyro_samples{static_cast(_fifo_empty_interval_us / (1000000 / RATE))}; // checks out to be 2 ... + + uint8_t _checked_register{0}; + static constexpr uint8_t size_register_cfg{11}; + register_config_t _register_cfg[size_register_cfg] { + // Register | Set bits, Clear bits + { Register::PWR_CONF, 0, ACC_PWR_CONF_BIT::acc_pwr_save }, + { Register::PWR_CTRL, PWR_CTRL_BIT::accel_en | PWR_CTRL_BIT::gyr_en | PWR_CTRL_BIT::temp_en, 0 }, + { Register::ACC_CONF, ACC_CONF_BIT::acc_bwp_Normal | ACC_CONF_BIT::acc_odr_1600, Bit1 | Bit0 }, + { Register::GYR_CONF, GYR_CONF_BIT::gyr_odr_1k6 | GYR_CONF_BIT::gyr_flt_mode_normal | GYR_CONF_BIT::gyr_noise_hp | GYR_CONF_BIT::gyr_flt_hp, Bit0 | Bit1 | Bit4}, + { Register::ACC_RANGE, ACC_RANGE_BIT::acc_range_16g, 0 }, + { Register::FIFO_WTM_0, 0, 0 }, + { Register::FIFO_WTM_1, 0, 0 }, + { Register::FIFO_CONFIG_0, FIFO_CONFIG_0_BIT::BIT1_ALWAYS | FIFO_CONFIG_0_BIT::FIFO_mode, 0 }, + { Register::FIFO_CONFIG_1, FIFO_CONFIG_1_BIT::BIT4_ALWAYS | FIFO_CONFIG_1_BIT::Acc_en | FIFO_CONFIG_1_BIT::Gyr_en, 0 }, + { Register::INT1_IO_CTRL, INT1_IO_CONF_BIT::int1_out, 0 }, + { Register::INT_MAP_DATA, INT1_INT2_MAP_DATA_BIT::int1_fwm, 0}, + }; +}; diff --git a/src/drivers/imu/bosch/bmi270/Bosch_BMI270_registers.hpp b/src/drivers/imu/bosch/bmi270/Bosch_BMI270_registers.hpp new file mode 100644 index 0000000000..29e008b627 --- /dev/null +++ b/src/drivers/imu/bosch/bmi270/Bosch_BMI270_registers.hpp @@ -0,0 +1,206 @@ +/**************************************************************************** + * + * 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 Bosch_BMI270_registers.hpp + * + * Bosch BMI270 registers. + * + */ + +#pragma once + +#include +#include + +// TODO: move to a central header +static constexpr uint8_t Bit0 = (1 << 0); +static constexpr uint8_t Bit1 = (1 << 1); +static constexpr uint8_t Bit2 = (1 << 2); +static constexpr uint8_t Bit3 = (1 << 3); +static constexpr uint8_t Bit4 = (1 << 4); +static constexpr uint8_t Bit5 = (1 << 5); +static constexpr uint8_t Bit6 = (1 << 6); +static constexpr uint8_t Bit7 = (1 << 7); + +namespace Bosch_BMI270 +{ +static constexpr uint32_t SPI_SPEED = 10 * 1000 * 1000; // 10MHz SPI serial interface +static constexpr uint8_t DIR_READ = 0x80; + +static constexpr uint8_t chip_id = 0x24; + +enum class Register : uint8_t { + CHIP_ID = 0x00, + + ERR_REG = 0x02, + STATUS = 0x03, + + EVENT = 0x1B, + + INTERNAL_STATUS = 0X21, + TEMP_MSB = 0x22, + TEMP_LSB = 0x23, + FIFO_LENGTH_0 = 0x24, + FIFO_LENGTH_1 = 0x25, + FIFO_DATA = 0x26, + + ACC_CONF = 0x40, + ACC_RANGE = 0x41, + GYR_CONF = 0x42, + + FIFO_DOWNS = 0x45, + FIFO_WTM_0 = 0x46, + FIFO_WTM_1 = 0x47, + FIFO_CONFIG_0 = 0x48, + FIFO_CONFIG_1 = 0x49, + + // controls interrupt pin behaviour + INT1_IO_CTRL = 0x53, + + INT_MAP_DATA = 0x58, + CONFIG1 = 0x59, + + CONFIG2 = 0x5E, + PWR_CONF = 0x7C, + PWR_CTRL = 0x7D, + CMD = 0x7E, + + + +}; + +enum GYR_CONF_BIT : uint8_t { + // 1.6 or 3.2kHz sample rate + gyr_odr_1k6 = Bit3 | Bit2, + gyr_odr_3k2 = Bit3 | Bit2 | Bit0, + // set LPF to normal mode + gyr_flt_mode_normal = Bit5, + // set noise profile to high performance mode + gyr_noise_hp = Bit6, + // set filter profile to high performance mode + gyr_flt_hp = Bit7 +}; + +enum PWR_CTRL_BIT : uint8_t { + gyr_en = Bit1, + accel_en = Bit2, + temp_en = Bit3, +}; + +// ACC_CONF +enum ACC_CONF_BIT : uint8_t { + // [7:4] acc_bwp + acc_bwp_Normal = Bit7 | Bit5, // Filter setting normal + + // [3:0] acc_odr + acc_odr_1600 = Bit3 | Bit2, // ODR 1600 Hz +}; + +// ACC_RANGE +enum ACC_RANGE_BIT : uint8_t { + acc_range_2g = 0, // ±2g + acc_range_4g = Bit0, // ±4g + acc_range_8g = Bit1, // ±8g + acc_range_16g = Bit1 | Bit0, // ±16g +}; + +// FIFO_CONFIG_0 +enum FIFO_CONFIG_0_BIT : uint8_t { + BIT1_ALWAYS = Bit1, // This bit must always be ‘1’. + FIFO_mode = Bit0, +}; + +// FIFO_CONFIG_1 +enum FIFO_CONFIG_1_BIT : uint8_t { + Acc_en = Bit6, + Gyr_en = Bit7, + BIT4_ALWAYS = Bit4, // This bit must always be ‘1’. +}; + +// INT1_IO_CONF +enum INT1_IO_CONF_BIT : uint8_t { + int1_in = Bit4, + int1_out = Bit3, + + int1_lvl = Bit1, +}; + +// INT1_INT2_MAP_DATA +enum INT1_INT2_MAP_DATA_BIT : uint8_t { + int2_drdy = Bit6, + int2_fwm = Bit5, + int2_ffull = Bit4, + + int1_drdy = Bit2, + int1_fwm = Bit1, + int1_ffull = Bit0, +}; + +// ACC_PWR_CONF +enum ACC_PWR_CONF_BIT : uint8_t { + acc_pwr_save = 0x03 +}; + +// ACC_PWR_CTRL +enum ACC_PWR_CTRL_BIT : uint8_t { + acc_enable = 0x04 +}; + + +namespace FIFO +{ +static constexpr size_t SIZE = 1024; + +struct Data { + uint8_t x_lsb; + uint8_t x_msb; + uint8_t y_lsb; + uint8_t y_msb; + uint8_t z_lsb; + uint8_t z_msb; +}; + + +enum class Header : uint8_t { + sensor_accel_frame = 0b10000100, + sensor_gyro_frame = 0b10001000, + skip_frame = 0b01000000, + sensor_time_frame = 0b01000100, + FIFO_input_config_frame = 0b01001000, + sample_drop_frame = 0b01010000, +}; + +} // namespace FIFO + +} // namespace Bosch_BMI270 diff --git a/src/drivers/imu/bosch/bmi270/CMakeLists.txt b/src/drivers/imu/bosch/bmi270/CMakeLists.txt new file mode 100644 index 0000000000..8769054263 --- /dev/null +++ b/src/drivers/imu/bosch/bmi270/CMakeLists.txt @@ -0,0 +1,48 @@ +############################################################################ +# +# 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. +# +############################################################################ + +px4_add_module( + MODULE drivers__imu__bosch__bmi270 + MAIN bmi270 + COMPILE_FLAGS + #-DDEBUG_BUILD + SRCS + bmi270_main.cpp + BMI270.cpp + BMI270.hpp + Bosch_BMI270_registers.hpp + DEPENDS + drivers_accelerometer + drivers_gyroscope + px4_work_queue + ) diff --git a/src/drivers/imu/bosch/bmi270/Kconfig b/src/drivers/imu/bosch/bmi270/Kconfig new file mode 100644 index 0000000000..3d8d82c5a4 --- /dev/null +++ b/src/drivers/imu/bosch/bmi270/Kconfig @@ -0,0 +1,5 @@ +menuconfig DRIVERS_IMU_BOSCH_BMI270 + bool "bosch bmi270" + default n + ---help--- + Enable support for bosch bmi270 diff --git a/src/drivers/imu/bosch/bmi270/bmi270_main.cpp b/src/drivers/imu/bosch/bmi270/bmi270_main.cpp new file mode 100644 index 0000000000..efdf50e5c0 --- /dev/null +++ b/src/drivers/imu/bosch/bmi270/bmi270_main.cpp @@ -0,0 +1,85 @@ +/**************************************************************************** + * + * Copyright (c) 2022 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#include "BMI270.hpp" + +#include +#include + +void BMI270::print_usage() +{ + PRINT_MODULE_USAGE_NAME("bmi270", "driver"); + PRINT_MODULE_USAGE_SUBCATEGORY("imu"); + PRINT_MODULE_USAGE_COMMAND("start"); + PRINT_MODULE_USAGE_PARAMS_I2C_SPI_DRIVER(false, true); + PRINT_MODULE_USAGE_PARAM_INT('R', 0, 0, 35, "Rotation", true); + PRINT_MODULE_USAGE_DEFAULT_COMMANDS(); +} + +extern "C" int bmi270_main(int argc, char *argv[]) +{ + int ch; + using ThisDriver = BMI270; + BusCLIArguments cli{false, true}; + cli.default_spi_frequency = SPI_SPEED; + + while ((ch = cli.getOpt(argc, argv, "R:")) != EOF) { + switch (ch) { + case 'R': + cli.rotation = (enum Rotation)atoi(cli.optArg()); + break; + } + } + + const char *verb = cli.optArg(); + + if (!verb) { + ThisDriver::print_usage(); + return -1; + } + + BusInstanceIterator iterator(MODULE_NAME, cli, DRV_IMU_DEVTYPE_BMI270); + + if (!strcmp(verb, "start")) { + return ThisDriver::module_start(cli, iterator); + + } else if (!strcmp(verb, "stop")) { + return ThisDriver::module_stop(iterator); + + } else if (!strcmp(verb, "status")) { + return ThisDriver::module_status(iterator); + } + + ThisDriver::print_usage(); + return -1; +}