Compare commits

..

30 Commits

Author SHA1 Message Date
Hamish Willee
ea3f7bcfb2 Copilot Review instructions: Drivers 2026-02-11 10:45:28 +11:00
Eric Katzfey
64e3cb16fa Removed VOXL2_IO: tag from all voxl2_io debug messages as they are redundant 2026-02-10 15:45:40 -07:00
Eric Katzfey
77d8e4f213 VOXLPM: Updated driver to publish battery status at 20ms intervals. Changed printf to PX4_INFO. 2026-02-10 11:46:44 -07:00
Balduin
ecf8191aad Battery: Declare fault on overtemperature
If the measured temperature exceeds the fixed threshold of 100 degC, a
fault is declared, causing batteryCheck to show a failsafe warning to
the user.
2026-02-10 13:44:46 +01:00
Jacob Dahl
3fb1459c33
ManualControl: fix payload power switch state when mapped with RC (RC_MAP_PAY_SW) (#26357)
* ManualControl: Payload Power Switch: default PAYLOAD_POWER_EN false if RC_MAP_PAY_SW is configured. Apply initial switch state for Payload Power

* make format

* ManualControl: init power_en in init()

* ManualControl: Apply payload power state on first switch receipt if not armed

* simplfy

* fix idefs

* simplify
2026-02-09 21:36:35 -09:00
Jacob Dahl
ee196fadb8
gps: ubx: add output rate parameter (#26388)
* gps: ubx: add parameter to configure module measurement rate (GPS_UBX_RATE)

* gps: update submodule

* submodule
2026-02-09 22:49:40 -07:00
Julian Oes
fd9abf76fd Fixup docs 2026-02-10 15:47:31 +13:00
Julian Oes
a98d68f919 AirBrainH743: use /fs/flash instead of /fs/microsd 2026-02-10 15:47:31 +13:00
Julian Oes
7d2d85e6ac AirBrainH743: reformat littlefs if required 2026-02-10 15:47:31 +13:00
Julian Oes
34845a62b0 AirBrainH743: add external I2C
This is for future/later board revisions.
2026-02-10 15:47:31 +13:00
Julian Oes
7715a4ab4c AirBrainH743: configure for active buzzer
We can't use passive buzzers because the timer to drive the PWM would
conflict with the motor outputs M7 and M8.
2026-02-10 15:47:31 +13:00
Julian Oes
ea2ca45cf9 boards: add support for Gear Up AirBrainH743 2026-02-10 15:47:31 +13:00
Jacob Dahl
14864814ef
gps: ubx: added jamming sensitivity parameter (#26386)
* gps: ubx: added jamming sensitivity parameter GPS_UBX_JAM_DET

* submodule

* gps: submodule to main
2026-02-09 17:43:39 -09:00
Julian Oes
3a6a57bd45 kakuteh7v2: use /fs/flash instead of /fs/microsd 2026-02-10 15:23:51 +13:00
Julian Oes
e0af9f4ef4 boards: add NAND flash logging support to KakuteH7v2
- Initialize W25N01GV NAND flash on SPI1 with littlefs.
- Enable BOARD_SMALL_FLASH_LOGGING for small flash handling.
- Increase logger buffer size for flash write performance.
2026-02-10 15:23:51 +13:00
Julian Oes
0294d4a794 dataman: increase stack size for littlefs
Increase stack size when using littlefs filesystem, which requires
more stack space than traditional filesystems.
2026-02-10 15:23:51 +13:00
Julian Oes
d411e1c40d logger: increase stack size for littlefs 2026-02-10 15:23:51 +13:00
Julian Oes
833e4536b7 nuttx: add support for NAND flash
This cherry-picks upstream commits adding NAND flash support for the
Winbond W25N specifically W25N01GV chip.

NAND flash is used together with littlefs, hence I updated that to 2.5.1
to match upstream NuttX.
2026-02-10 15:23:51 +13:00
Eric Katzfey
1b7e12cf90 VOXL_ESC: bringing the driver up to date with ModalAI latest. Includes new open loop "PWM" command handling. 2026-02-09 16:38:53 -07:00
Eric Katzfey
aacb7e35dd For VOXL flight controllers, Use DSP clock directly on Posix for CLOCK_MONOTONIC 2026-02-09 15:22:36 -07:00
Eric Katzfey
1dbee4100a uORB: Added a new uorb_shutdown function that is called during normal shutdown procedures. It will only
call into a new UORB COMMUNICATOR ICHANNEL shutdown interface if it has been configured, otherwise it
does nothing. This allows ICHANNEL implementations to pass on a shutdown indication to a remote processor.
Implemented the shutdown interface in the muorb module for VOXL flight controllers.
2026-02-09 15:21:41 -07:00
Nick
dbb00d500f Update src/modules/commander/failure_detector/FailureDetector.cpp
Prevent Buffer overflow
2026-02-09 18:08:26 +01:00
Matthias Grob
61a8ae80a6 FailureDetector: implement upper and lower current limit with offset 2026-02-09 18:08:26 +01:00
Matthias Grob
f8329ff80d FailureDetector: rework motor status check 2026-02-09 18:08:26 +01:00
Matthias Grob
b4b1b44c6a FailureDetector: consistent timestamp naming 2026-02-09 18:08:26 +01:00
Matthias Grob
f5a56ae42f escCheck: rework online check to properly report offline ESCs
previous to this
09d79b221f274523349a029e63ab4462e41d0c1c
set `esc_online_flags` e.g. for UAVCAN ESCs which specific one is online and that then got compared to a mask where the first `esc_count` bits were set.

So if only ESC 5 is mapped and online you get the message "ESC 156 offline" because `esc_online_flags = 0b1000` gets compared to `online_bitmask = 0b1` based on `esc_count = 1` and the motor index is `esc[0].actuator_function = 0` wrapped using `0 - actuator_motors_s::ACTUATOR_FUNCTION_MOTOR1 + 1 = 156`.
2026-02-09 18:08:26 +01:00
Marco Hauswirth
c4535683a7 ekf2 unit-tests: adapt to strict GNSS checks on ground 2026-02-09 10:59:58 +01:00
Matthias Grob
f9cdd095b8 gnss_checks: always run strict checks on ground
With the goal to never take off if the GNSS solution is not fullfilling the configured requirements still not stopping to use it in case it degrades mid air.
2026-02-09 10:59:58 +01:00
Matthias Grob
61c990c5ee estimator_interface: remove unused getter 2026-02-09 10:59:58 +01:00
Beat Küng
8115cf2597 docs: update link for px4 ros2 interface lib python api docs 2026-02-09 10:03:55 +01:00
80 changed files with 3411 additions and 475 deletions

View File

@ -0,0 +1,212 @@
---
applyTo: "src/drivers/**"
---
# PX4 Driver Review Instructions
This file provides guidelines for reviewing driver files in the `src/drivers/` directory.
## Copyright Statements
### Required Files
All source files (`.cpp`, `.c`, `.hpp`, `.h`, `CMakeLists.txt`) MUST include a copyright statement at the top.
**Exceptions:**
- `Kconfig` files
- `module.yaml` files
### Copyright Format
**For new files (created in 2026):**
```cpp
/****************************************************************************
*
* Copyright (c) 2026 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.
*
****************************************************************************/
```
**For updated files (originally created in 2015, updated in 2026):**
```cpp
/****************************************************************************
*
* Copyright (c) 2015-2026 PX4 Development Team. All rights reserved.
*
* [... rest of copyright text ...]
*
****************************************************************************/
```
### Key Points
- First year should be the original creation year
- When updating an existing file, update the year range: `YYYY-2026`
- Use the current year (2026 in this case) for new files
- Maintain consistent formatting with other PX4 driver files
---
## Driver Self-Documentation
All drivers MUST be self-documenting through the `print_usage()` method.
### Required Implementation
Every driver `.cpp` file must implement a `print_usage()` method that includes:
1. **PRINT_MODULE_DESCRIPTION macro** - Contains markdown documentation
2. **Module identification** - Using PRINT_MODULE_USAGE_NAME and optionally PRINT_MODULE_USAGE_SUBCATEGORY
3. **Parameter documentation** - Relevant parameters, especially enablement parameters
### PRINT_MODULE_DESCRIPTION Structure
The description should follow this markdown format:
```cpp
PRINT_MODULE_DESCRIPTION(
R"DESCR_STR(
### Description
[Clear description of what the driver does and its primary functionality]
### Implementation
[Optional: High-level overview of how the driver works]
### Examples
[Optional: CLI usage examples if non-trivial]
$ module_name start -d /dev/ttyS1
$ module_name stop
)DESCR_STR");
```
### Required Sections
#### 1. Description Section
- Brief explanation of the driver's purpose
- Key features/capabilities
- Important parameters (especially enable parameters like `SENS_XX_CFG`)
#### 2. Documentation Links
When applicable, include links to user documentation:
```cpp
Setup/usage information: https://docs.px4.io/main/en/sensor/[sensor-name].html
```
#### 3. Examples Section (when relevant)
Provide CLI usage examples for non-trivial commands:
```cpp
### Examples
Attempt to start driver on a specified serial device.
$ vectornav start -d /dev/ttyS1
Stop driver
$ vectornav stop
```
### Complete Example
```cpp
int MyDriver::print_usage(const char *reason)
{
if (reason) {
PX4_WARN("%s\n", reason);
}
PRINT_MODULE_DESCRIPTION(
R"DESCR_STR(
### Description
This driver interfaces with the XYZ sensor via I2C/SPI. It provides
distance measurements and is automatically started when SENS_XYZ_CFG
is set to the appropriate value.
Key features:
- Distance range: 0.2m to 50m
- Update rate: up to 100Hz
- I2C and SPI support
Setup/usage information: https://docs.px4.io/main/en/sensor/xyz_sensor.html
### Examples
Start driver on I2C bus 1 with address 0x29:
$ xyz_sensor start -X -b 1 -a 0x29
)DESCR_STR");
PRINT_MODULE_USAGE_NAME("xyz_sensor", "driver");
PRINT_MODULE_USAGE_SUBCATEGORY("distance_sensor");
PRINT_MODULE_USAGE_COMMAND("start");
PRINT_MODULE_USAGE_PARAMS_I2C_SPI_DRIVER(true, true);
PRINT_MODULE_USAGE_PARAMS_I2C_ADDRESS(0x29);
PRINT_MODULE_USAGE_DEFAULT_COMMANDS();
return 0;
}
```
### Common Patterns by Driver Type
**For UART/Serial Drivers:**
```cpp
PRINT_MODULE_USAGE_PARAM_STRING('d', "/dev/ttyS3", "<file:dev>", "Serial device", true);
```
**For I2C/SPI Drivers:**
```cpp
PRINT_MODULE_USAGE_PARAMS_I2C_SPI_DRIVER(true, true);
PRINT_MODULE_USAGE_PARAMS_I2C_ADDRESS(0x76);
```
**For Sensor Drivers:**
```cpp
PRINT_MODULE_USAGE_SUBCATEGORY("distance_sensor"); // or imu, magnetometer, etc.
```
---
## Review Checklist
When reviewing driver files, verify:
- [ ] Copyright header is present (except Kconfig and module.yaml)
- [ ] Copyright year is correct (current year for new files, year range for updates)
- [ ] `print_usage()` method exists
- [ ] `PRINT_MODULE_DESCRIPTION` macro is present with markdown content
- [ ] Description section explains driver purpose clearly
- [ ] Relevant parameters are documented (especially enable parameters)
- [ ] Documentation links are included when available
- [ ] Examples are provided for complex CLI usage
- [ ] Module name and category are correctly specified
- [ ] Standard commands (start, stop, status) are documented
---
## Additional Resources
- Driver template examples: `src/drivers/*/` (various sensor types)
- Module macros: `platforms/common/include/px4_platform_common/module.h`
- Similar drivers for reference patterns (DShot, VectorNav, CrsfRc, etc.)

View File

@ -0,0 +1,3 @@
CONFIG_BOARD_TOOLCHAIN="arm-none-eabi"
CONFIG_BOARD_ARCHITECTURE="cortex-m7"
CONFIG_BOARD_ROMFSROOT=""

View File

@ -0,0 +1,86 @@
CONFIG_BOARD_TOOLCHAIN="arm-none-eabi"
CONFIG_BOARD_ARCHITECTURE="cortex-m7"
CONFIG_BOARD_ROOT_PATH="/fs/flash"
CONFIG_BOARD_SERIAL_GPS1="/dev/ttyS6"
CONFIG_BOARD_SERIAL_TEL1="/dev/ttyS3"
CONFIG_BOARD_SERIAL_TEL2="/dev/ttyS4"
CONFIG_BOARD_SERIAL_TEL3="/dev/ttyS5"
CONFIG_BOARD_SERIAL_TEL4="/dev/ttyS2"
CONFIG_BOARD_SERIAL_RC="/dev/ttyS1"
CONFIG_DRIVERS_ADC_BOARD_ADC=y
CONFIG_DRIVERS_BAROMETER_DPS310=y
CONFIG_DRIVERS_CDCACM_AUTOSTART=y
CONFIG_COMMON_DIFFERENTIAL_PRESSURE=y
CONFIG_COMMON_DISTANCE_SENSOR=y
CONFIG_DRIVERS_DSHOT=y
CONFIG_DRIVERS_GPS=y
CONFIG_DRIVERS_IMU_INVENSENSE_ICM42688P=y
CONFIG_COMMON_LIGHT=y
CONFIG_DRIVERS_MAGNETOMETER_HMC5883=y
CONFIG_DRIVERS_MAGNETOMETER_ISENTEK_IST8310=y
CONFIG_DRIVERS_MAGNETOMETER_LIS3MDL=y
CONFIG_DRIVERS_MAGNETOMETER_QMC5883L=y
CONFIG_DRIVERS_MAGNETOMETER_ST_IIS2MDC=y
CONFIG_DRIVERS_OSD_MSP_OSD=y
CONFIG_COMMON_OPTICAL_FLOW=y
CONFIG_DRIVERS_PWM_OUT=y
CONFIG_DRIVERS_RC_INPUT=y
CONFIG_COMMON_TELEMETRY=y
CONFIG_DRIVERS_TONE_ALARM=y
CONFIG_MODULES_ATTITUDE_ESTIMATOR_Q=y
CONFIG_MODULES_BATTERY_STATUS=y
CONFIG_MODULES_COMMANDER=y
CONFIG_MODULES_CONTROL_ALLOCATOR=y
CONFIG_MODULES_DATAMAN=y
CONFIG_MODULES_EKF2=y
# CONFIG_EKF2_AUX_GLOBAL_POSITION is not set
# CONFIG_EKF2_AUXVEL is not set
# CONFIG_EKF2_BARO_COMPENSATION is not set
# CONFIG_EKF2_DRAG_FUSION is not set
# CONFIG_EKF2_GNSS_YAW is not set
# CONFIG_EKF2_SIDESLIP is not set
CONFIG_MODULES_EVENTS=y
CONFIG_MODULES_FLIGHT_MODE_MANAGER=y
CONFIG_MODULES_FW_ATT_CONTROL=y
CONFIG_MODULES_FW_MODE_MANAGER=y
CONFIG_MODULES_FW_LATERAL_LONGITUDINAL_CONTROL=y
CONFIG_MODULES_FW_RATE_CONTROL=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_HOVER_THRUST_ESTIMATOR=y
CONFIG_MODULES_MC_POS_CONTROL=y
CONFIG_MODULES_MC_RATE_CONTROL=y
CONFIG_MODULES_NAVIGATOR=y
CONFIG_MODULES_RC_UPDATE=y
CONFIG_MODULES_SENSORS=y
CONFIG_MODULES_UXRCE_DDS_CLIENT=y
CONFIG_MODULES_VTOL_ATT_CONTROL=y
CONFIG_SYSTEMCMDS_ACTUATOR_TEST=y
CONFIG_SYSTEMCMDS_BSONDUMP=y
CONFIG_SYSTEMCMDS_DMESG=y
CONFIG_SYSTEMCMDS_GPIO=y
CONFIG_SYSTEMCMDS_HARDFAULT_LOG=y
CONFIG_SYSTEMCMDS_I2CDETECT=y
CONFIG_SYSTEMCMDS_LED_CONTROL=y
CONFIG_SYSTEMCMDS_MFT=y
CONFIG_SYSTEMCMDS_MTD=y
CONFIG_SYSTEMCMDS_NSHTERM=y
CONFIG_SYSTEMCMDS_PARAM=y
CONFIG_SYSTEMCMDS_PERF=y
CONFIG_SYSTEMCMDS_REBOOT=y
CONFIG_SYSTEMCMDS_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

View File

@ -0,0 +1,13 @@
{
"board_id": 1209,
"magic": "PX4FWv1",
"description": "Firmware for the AirBrainH743 by Gear Up",
"image": "",
"build_time": 0,
"summary": "AirBrainH743",
"version": "0.1",
"image_size": 0,
"image_maxsize": 1966080,
"git_identity": "",
"board_revision": 0
}

View File

@ -0,0 +1,17 @@
#!/bin/sh
#
# AirBrainH743 board specific defaults
#------------------------------------------------------------------------------
# Battery voltage divider and current scale
param set-default BAT1_V_DIV 15.0
param set-default BAT1_A_PER_V 101.0
# system_power unavailable
param set-default CBRK_SUPPLY_CHK 894281
param set-default IMU_GYRO_RATEMAX 2000
# W25N NAND flash with littlefs (128 MB): larger buffer, auto-rotate
set LOGGER_BUF 32
param set-default SDLOG_DIRS_MAX 3

View File

@ -0,0 +1,6 @@
#!/bin/sh
#
# AirBrainH743 specific board extras init
#------------------------------------------------------------------------------
# No extras configured by default

View File

@ -0,0 +1,16 @@
#!/bin/sh
#
# AirBrainH743 specific board sensors init
#------------------------------------------------------------------------------
board_adc start
# Internal SPI bus IMU - ICM42688P (Invensensev3)
icm42688p -R 2 -b 1 -s start
# Internal I2C bus barometer - DPS310 @ 0x76 (118 decimal)
dps310 -I -a 118 start
# Internal I2C bus magnetometer - LIS2MDL @ 0x1E (30 decimal)
# Using iis2mdc driver (functionally equivalent to LIS2MDL)
iis2mdc -I -R 2 -a 30 start

View File

@ -0,0 +1,3 @@
#
# Board-specific Kconfig for AirBrainH743
#

View File

@ -0,0 +1,89 @@
#
# This file is autogenerated: PLEASE DO NOT EDIT IT.
#
# You can use "make menuconfig" to make any modifications to the installed .config file.
# You can then do "make savedefconfig" to generate a new defconfig file that includes your
# modifications.
#
# CONFIG_DEV_CONSOLE is not set
# CONFIG_DISABLE_PSEUDOFS_OPERATIONS is not set
# CONFIG_SPI_EXCHANGE is not set
# CONFIG_STM32H7_SYSCFG is not set
CONFIG_ARCH="arm"
CONFIG_ARCH_BOARD_CUSTOM=y
CONFIG_ARCH_BOARD_CUSTOM_DIR="../../../../boards/gearup/airbrainh743/nuttx-config"
CONFIG_ARCH_BOARD_CUSTOM_DIR_RELPATH=y
CONFIG_ARCH_BOARD_CUSTOM_NAME="px4"
CONFIG_ARCH_CHIP="stm32h7"
CONFIG_ARCH_CHIP_STM32H743VI=y
CONFIG_ARCH_CHIP_STM32H7=y
CONFIG_ARCH_INTERRUPTSTACK=768
CONFIG_ARMV7M_BASEPRI_WAR=y
CONFIG_ARMV7M_ICACHE=y
CONFIG_ARMV7M_MEMCPY=y
CONFIG_ARMV7M_USEBASEPRI=y
CONFIG_BOARDCTL=y
CONFIG_BOARDCTL_RESET=y
CONFIG_BOARD_ASSERT_RESET_VALUE=0
CONFIG_BOARD_INITTHREAD_PRIORITY=254
CONFIG_BOARD_LATE_INITIALIZE=y
CONFIG_BOARD_LOOPSPERMSEC=22114
CONFIG_BOARD_RESET_ON_ASSERT=2
CONFIG_CDCACM=y
CONFIG_CDCACM_PRODUCTID=0x004b
CONFIG_CDCACM_PRODUCTSTR="AirBrainH743 BL"
CONFIG_CDCACM_RXBUFSIZE=600
CONFIG_CDCACM_TXBUFSIZE=12000
CONFIG_CDCACM_VENDORID=0x3162
CONFIG_CDCACM_VENDORSTR="Gear Up"
CONFIG_DEBUG_FULLOPT=y
CONFIG_DEBUG_SYMBOLS=y
CONFIG_DEBUG_TCBINFO=y
CONFIG_DEFAULT_SMALL=y
CONFIG_EXPERIMENTAL=y
CONFIG_FDCLONE_DISABLE=y
CONFIG_FDCLONE_STDIO=y
CONFIG_HAVE_CXX=y
CONFIG_HAVE_CXXINITIALIZE=y
CONFIG_IDLETHREAD_STACKSIZE=750
CONFIG_INIT_ENTRYPOINT="bootloader_main"
CONFIG_INIT_STACKSIZE=3194
CONFIG_LIBC_FLOATINGPOINT=y
CONFIG_LIBC_LONG_LONG=y
CONFIG_LIBC_STRERROR=y
CONFIG_MEMSET_64BIT=y
CONFIG_MEMSET_OPTSPEED=y
CONFIG_PREALLOC_TIMERS=50
CONFIG_PTHREAD_STACK_MIN=512
CONFIG_RAM_SIZE=245760
CONFIG_RAM_START=0x20010000
CONFIG_RAW_BINARY=y
CONFIG_SERIAL_TERMIOS=y
CONFIG_SIG_DEFAULT=y
CONFIG_SIG_SIGALRM_ACTION=y
CONFIG_SIG_SIGUSR1_ACTION=y
CONFIG_SIG_SIGUSR2_ACTION=y
CONFIG_SPI=y
CONFIG_STACK_COLORATION=y
CONFIG_START_DAY=30
CONFIG_START_MONTH=11
CONFIG_STDIO_BUFFER_SIZE=32
CONFIG_STM32H7_BKPSRAM=y
CONFIG_STM32H7_DMA1=y
CONFIG_STM32H7_OTGFS=y
CONFIG_STM32H7_PROGMEM=y
CONFIG_STM32H7_SERIAL_DISABLE_REORDERING=y
CONFIG_STM32H7_TIM1=y
CONFIG_STM32H7_USART1=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_USART1_RXBUFSIZE=600
CONFIG_USART1_TXBUFSIZE=300
CONFIG_USBDEV=y
CONFIG_USBDEV_BUSPOWERED=y
CONFIG_USBDEV_MAXPOWER=500
CONFIG_USEC_PER_TICK=1000

View File

@ -0,0 +1,346 @@
/************************************************************************************
* nuttx-config/include/board.h
*
* Copyright (C) 2026 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 NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
************************************************************************************/
#ifndef __NUTTX_CONFIG_AIRBRAINH743_INCLUDE_BOARD_H
#define __NUTTX_CONFIG_AIRBRAINH743_INCLUDE_BOARD_H
/************************************************************************************
* Included Files
************************************************************************************/
#include "board_dma_map.h"
#include <nuttx/config.h>
#ifndef __ASSEMBLY__
# include <stdint.h>
#endif
#include "stm32_rcc.h"
#include "stm32_sdmmc.h"
/************************************************************************************
* Pre-processor Definitions
************************************************************************************/
/* Clocking *************************************************************************/
/* The AirBrainH743 board provides the following clock sources:
*
* X1: 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
*
* SYSCLK = PLL_VCO / PLLP
* CPUCLK = SYSCLK / D1CPRE
*/
#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(5)
#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 / 5)
#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/2 (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 */
/* I2C123 clock source */
#define STM32_RCC_D2CCIP2R_I2C123SRC RCC_D2CCIP2R_I2C123SEL_HSI
/* I2C4 clock source */
#define STM32_RCC_D3CCIPR_I2C4SRC RCC_D3CCIPR_I2C4SEL_HSI
/* SPI123 clock source */
#define STM32_RCC_D2CCIP1R_SPI123SRC RCC_D2CCIP1R_SPI123SEL_PLL2
/* SPI45 clock source */
#define STM32_RCC_D2CCIP1R_SPI45SRC RCC_D2CCIP1R_SPI45SEL_PLL2
/* SPI6 clock source */
#define STM32_RCC_D3CCIPR_SPI6SRC RCC_D3CCIPR_SPI6SEL_PLL2
/* USB 1 and 2 clock source */
#define STM32_RCC_D2CCIP2R_USBSRC RCC_D2CCIP2R_USBSEL_PLL3
/* ADC 1 2 3 clock source */
#define STM32_RCC_D3CCIPR_ADCSRC RCC_D3CCIPR_ADCSEL_PLL2
/* FDCAN 1 clock source */
#define STM32_RCC_D2CCIP1R_FDCANSEL RCC_D2CCIP1R_FDCANSEL_HSE
#define STM32_FDCANCLK STM32_HSE_FREQUENCY
/* FLASH wait states */
#define BOARD_FLASH_WAITSTATES 2
/* LED definitions ******************************************************************/
#define BOARD_LED1 0
#define BOARD_LED2 1
#define BOARD_LED3 2
#define BOARD_NLEDS 3
#define BOARD_LED_RED BOARD_LED1
#define BOARD_LED_GREEN BOARD_LED2
#define BOARD_LED_BLUE BOARD_LED3
/* LED bits for use with board_userled_all() */
#define BOARD_LED1_BIT (1 << BOARD_LED1)
#define BOARD_LED2_BIT (1 << BOARD_LED2)
#define BOARD_LED3_BIT (1 << BOARD_LED3)
#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 */
/* Alternate function pin selections ************************************************/
/* USART1 - Debug (PA9 TX, PA10 RX) */
#define GPIO_USART1_RX GPIO_USART1_RX_2 /* PA10 */
#define GPIO_USART1_TX GPIO_USART1_TX_2 /* PA9 */
/* USART2 - RC input (PD5 TX, PD6 RX) */
#define GPIO_USART2_RX GPIO_USART2_RX_2 /* PD6 */
#define GPIO_USART2_TX GPIO_USART2_TX_2 /* PD5 */
/* USART3 - DJI/MSP (PD8 TX, PD9 RX) */
#define GPIO_USART3_RX GPIO_USART3_RX_3 /* PD9 */
#define GPIO_USART3_TX GPIO_USART3_TX_3 /* PD8 */
/* UART4 - General (PB9 TX, PB8 RX) */
#define GPIO_UART4_RX GPIO_UART4_RX_3 /* PB8 */
#define GPIO_UART4_TX GPIO_UART4_TX_3 /* PB9 */
/* UART5 - Companion (PB13 TX, PB12 RX) */
#define GPIO_UART5_RX GPIO_UART5_RX_1 /* PB12 */
#define GPIO_UART5_TX GPIO_UART5_TX_1 /* PB13 */
/* UART7 - ESC telemetry (PE8 TX, PE7 RX) */
#define GPIO_UART7_RX GPIO_UART7_RX_3 /* PE7 */
#define GPIO_UART7_TX GPIO_UART7_TX_3 /* PE8 */
/* UART8 - GPS (PE1 TX, PE0 RX) */
#define GPIO_UART8_RX GPIO_UART8_RX_1 /* PE0 */
#define GPIO_UART8_TX GPIO_UART8_TX_1 /* PE1 */
/* SPI
*
* SPI1: IMU (PA5 SCK, PA6 MISO, PA7 MOSI)
* SPI2: W25N Flash (PD3 SCK, PB14 MISO, PC3 MOSI)
* SPI4: External (PE12 SCK, PE5 MISO, PE6 MOSI)
*/
#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_3 /* PC3 */
#define GPIO_SPI2_SCK GPIO_SPI2_SCK_5 /* PD3 */
#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_1 /* PE12 */
/* I2C
*
* I2C1: Internal (PB6 SCL, PB7 SDA)
* I2C4: External (PD12 SCL, PD13 SDA)
*/
#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)
#define GPIO_I2C4_SCL GPIO_I2C4_SCL_1 /* PD12 */
#define GPIO_I2C4_SDA GPIO_I2C4_SDA_1 /* PD13 */
#define GPIO_I2C4_SCL_GPIO (GPIO_OUTPUT | GPIO_OPENDRAIN | GPIO_SPEED_50MHz | GPIO_OUTPUT_SET | GPIO_PORTD | GPIO_PIN12)
#define GPIO_I2C4_SDA_GPIO (GPIO_OUTPUT | GPIO_OPENDRAIN | GPIO_SPEED_50MHz | GPIO_OUTPUT_SET | GPIO_PORTD | GPIO_PIN13)
/* USB
*
* OTG_FS_DM PA11
* OTG_FS_DP PA12
* VBUS PD0
*/
#endif /*__NUTTX_CONFIG_AIRBRAINH743_INCLUDE_BOARD_H */

View File

@ -0,0 +1,42 @@
/****************************************************************************
*
* Copyright (c) 2026 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
/* DMA mapping for SPI1 (IMU) */
#define DMAMAP_SPI1_RX DMAMAP_DMA12_SPI1RX_0 /* DMA1:37 */
#define DMAMAP_SPI1_TX DMAMAP_DMA12_SPI1TX_0 /* DMA1:38 */
/* DMA mapping for SPI2 (W25N Flash) */
#define DMAMAP_SPI2_RX DMAMAP_DMA12_SPI2RX_0 /* DMA1:39 */
#define DMAMAP_SPI2_TX DMAMAP_DMA12_SPI2TX_0 /* DMA1:40 */

View File

@ -0,0 +1,258 @@
#
# 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_PRINTF 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/gearup/airbrainh743/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_ARCH_STACKDUMP=y
CONFIG_ARMV7M_BASEPRI_WAR=y
CONFIG_ARMV7M_DCACHE=y
CONFIG_ARMV7M_DTCM=y
CONFIG_ARMV7M_ICACHE=y
CONFIG_ARMV7M_MEMCPY=y
CONFIG_ARMV7M_USEBASEPRI=y
CONFIG_ARM_MPU_EARLY_RESET=y
CONFIG_BOARDCTL_RESET=y
CONFIG_BOARD_ASSERT_RESET_VALUE=0
CONFIG_BOARD_CRASHDUMP=y
CONFIG_BOARD_LOOPSPERMSEC=95150
CONFIG_BOARD_RESET_ON_ASSERT=2
CONFIG_BUILTIN=y
CONFIG_CDCACM=y
CONFIG_CDCACM_IFLOWCONTROL=y
CONFIG_CDCACM_PRODUCTID=0x0050
CONFIG_CDCACM_PRODUCTSTR="AirBrainH743"
CONFIG_CDCACM_RXBUFSIZE=600
CONFIG_CDCACM_TXBUFSIZE=12000
CONFIG_CDCACM_VENDORID=0x3162
CONFIG_CDCACM_VENDORSTR="Gear Up"
CONFIG_DEBUG_FULLOPT=y
CONFIG_DEBUG_HARDFAULT_ALERT=y
CONFIG_DEBUG_MEMFAULT=y
CONFIG_DEBUG_SYMBOLS=y
CONFIG_DEFAULT_SMALL=y
CONFIG_DEV_FIFO_SIZE=0
CONFIG_DEV_PIPE_MAXSIZE=1024
CONFIG_DEV_PIPE_SIZE=70
CONFIG_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_FS_LITTLEFS=y
CONFIG_FS_LITTLEFS_PROGRAM_SIZE_FACTOR=1
CONFIG_FS_LITTLEFS_READ_SIZE_FACTOR=1
CONFIG_FS_LITTLEFS_CACHE_SIZE_FACTOR=1
CONFIG_GRAN=y
CONFIG_GRAN_INTR=y
CONFIG_HAVE_CXX=y
CONFIG_HAVE_CXXINITIALIZE=y
CONFIG_I2C=y
CONFIG_I2C_RESET=y
CONFIG_IDLETHREAD_STACKSIZE=750
CONFIG_INIT_ENTRYPOINT="nsh_main"
CONFIG_INIT_STACKSIZE=3194
CONFIG_LIBC_FLOATINGPOINT=y
CONFIG_LIBC_LONG_LONG=y
CONFIG_LIBC_MAX_EXITFUNS=1
CONFIG_LIBC_STRERROR=y
CONFIG_MEMSET_64BIT=y
CONFIG_MEMSET_OPTSPEED=y
CONFIG_MM_REGIONS=4
CONFIG_MTD=y
CONFIG_MTD_BYTE_WRITE=y
CONFIG_MTD_PARTITION=y
CONFIG_MTD_PROGMEM=y
CONFIG_MTD_W25N=y
CONFIG_W25N_SPIFREQUENCY=104000000
CONFIG_NAME_MAX=40
CONFIG_NSH_ARCHINIT=y
CONFIG_NSH_ARGCAT=y
CONFIG_NSH_BUILTIN_APPS=y
CONFIG_NSH_CMDPARMS=y
CONFIG_NSH_CROMFSETC=y
CONFIG_NSH_LINELEN=128
CONFIG_NSH_MAXARGUMENTS=15
CONFIG_NSH_NESTDEPTH=8
CONFIG_NSH_QUOTE=y
CONFIG_NSH_ROMFSETC=y
CONFIG_NSH_ROMFSSECTSIZE=128
CONFIG_NSH_STRERROR=y
CONFIG_NSH_VARS=y
CONFIG_OTG_ID_GPIO_DISABLE=y
CONFIG_PIPES=y
CONFIG_PREALLOC_TIMERS=50
CONFIG_PRIORITY_INHERITANCE=y
CONFIG_PTHREAD_MUTEX_ROBUST=y
CONFIG_PTHREAD_STACK_MIN=512
CONFIG_RAM_SIZE=245760
CONFIG_RAM_START=0x20010000
CONFIG_RAW_BINARY=y
CONFIG_READLINE_CMD_HISTORY=y
CONFIG_READLINE_TABCOMPLETION=y
CONFIG_RTC_DATETIME=y
CONFIG_SCHED_HPWORK=y
CONFIG_SCHED_HPWORKPRIORITY=249
CONFIG_SCHED_HPWORKSTACKSIZE=1280
CONFIG_SCHED_INSTRUMENTATION=y
CONFIG_SCHED_INSTRUMENTATION_EXTERNAL=y
CONFIG_SCHED_INSTRUMENTATION_SWITCH=y
CONFIG_SCHED_LPWORK=y
CONFIG_SCHED_LPWORKPRIORITY=50
CONFIG_SCHED_LPWORKSTACKSIZE=1632
CONFIG_SCHED_WAITPID=y
CONFIG_SEM_PREALLOCHOLDERS=32
CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS=y
CONFIG_SERIAL_TERMIOS=y
CONFIG_SIG_DEFAULT=y
CONFIG_SIG_SIGALRM_ACTION=y
CONFIG_SIG_SIGUSR1_ACTION=y
CONFIG_SIG_SIGUSR2_ACTION=y
CONFIG_SIG_SIGWORK=4
CONFIG_STACK_COLORATION=y
CONFIG_START_DAY=30
CONFIG_START_MONTH=11
CONFIG_STDIO_BUFFER_SIZE=256
CONFIG_STM32H7_ADC1=y
CONFIG_STM32H7_ADC3=y
CONFIG_STM32H7_BBSRAM=y
CONFIG_STM32H7_BBSRAM_FILES=5
CONFIG_STM32H7_BDMA=y
CONFIG_STM32H7_BKPSRAM=y
CONFIG_STM32H7_DMA1=y
CONFIG_STM32H7_DMA2=y
CONFIG_STM32H7_DMACAPABLE=y
CONFIG_STM32H7_DMAMUX1=y
CONFIG_STM32H7_FLOWCONTROL_BROKEN=y
CONFIG_STM32H7_I2C1=y
CONFIG_STM32H7_I2C4=y
CONFIG_STM32H7_I2C_DYNTIMEO=y
CONFIG_STM32H7_I2C_DYNTIMEO_STARTSTOP=10
CONFIG_STM32H7_OTGFS=y
CONFIG_STM32H7_PROGMEM=y
CONFIG_STM32H7_RTC=y
CONFIG_STM32H7_RTC_HSECLOCK=y
CONFIG_STM32H7_RTC_MAGIC_REG=1
CONFIG_STM32H7_SAVE_CRASHDUMP=y
CONFIG_STM32H7_SERIALBRK_BSDCOMPAT=y
CONFIG_STM32H7_SERIAL_DISABLE_REORDERING=y
CONFIG_STM32H7_SPI1=y
CONFIG_STM32H7_SPI1_DMA=y
CONFIG_STM32H7_SPI1_DMA_BUFFER=4096
CONFIG_STM32H7_SPI2=y
CONFIG_STM32H7_SPI2_DMA=y
CONFIG_STM32H7_SPI2_DMA_BUFFER=4096
CONFIG_STM32H7_SPI4=y
CONFIG_STM32H7_TIM1=y
CONFIG_STM32H7_TIM2=y
CONFIG_STM32H7_TIM3=y
CONFIG_STM32H7_TIM5=y
CONFIG_STM32H7_TIM8=y
CONFIG_STM32H7_UART4=y
CONFIG_STM32H7_UART5=y
CONFIG_STM32H7_UART7=y
CONFIG_STM32H7_UART8=y
CONFIG_STM32H7_USART1=y
CONFIG_STM32H7_USART2=y
CONFIG_STM32H7_USART3=y
CONFIG_STM32H7_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_UART5_BAUD=57600
CONFIG_UART5_RXBUFSIZE=600
CONFIG_UART5_TXBUFSIZE=1500
CONFIG_UART7_BAUD=57600
CONFIG_UART7_RXBUFSIZE=600
CONFIG_UART7_TXBUFSIZE=1500
CONFIG_UART8_BAUD=57600
CONFIG_UART8_RXBUFSIZE=600
CONFIG_UART8_TXBUFSIZE=1500
CONFIG_USART1_BAUD=57600
CONFIG_USART1_RXBUFSIZE=600
CONFIG_USART1_SERIAL_CONSOLE=y
CONFIG_USART1_TXBUFSIZE=1500
CONFIG_USART2_BAUD=57600
CONFIG_USART2_RXBUFSIZE=600
CONFIG_USART2_TXBUFSIZE=1500
CONFIG_USART3_BAUD=57600
CONFIG_USART3_RXBUFSIZE=600
CONFIG_USART3_TXBUFSIZE=1500
CONFIG_USBDEV=y
CONFIG_USBDEV_BUSPOWERED=y
CONFIG_USBDEV_MAXPOWER=500
CONFIG_USEC_PER_TICK=1000
CONFIG_WATCHDOG=y

View File

@ -0,0 +1,213 @@
/****************************************************************************
* scripts/script.ld
*
* Copyright (C) 2016, 2019 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
*
* 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 Durandal-v1 uses an STM32H743II has 2048Kb of main FLASH memory.
* The flash memory is partitioned into a User Flash memory and a System
* Flash memory. Each of these memories has two banks:
*
* 1) User Flash memory:
*
* Bank 1: Start address 0x0800:0000 to 0x080F:FFFF with 8 sectors, 128Kb each
* Bank 2: Start address 0x0810:0000 to 0x081F:FFFF with 8 sectors, 128Kb each
*
* 2) System Flash memory:
*
* Bank 1: Start address 0x1FF0:0000 to 0x1FF1:FFFF with 1 x 128Kb sector
* Bank 1: Start address 0x1FF4:0000 to 0x1FF5:FFFF with 1 x 128Kb sector
*
* 3) User option bytes for user configuration, only in Bank 1.
*
* In the STM32H743II, two different boot spaces can be selected through
* the BOOT pin and the boot base address programmed in the BOOT_ADD0 and
* BOOT_ADD1 option bytes:
*
* 1) BOOT=0: Boot address defined by user option byte BOOT_ADD0[15:0].
* ST programmed value: Flash memory at 0x0800:0000
* 2) BOOT=1: Boot address defined by user option byte BOOT_ADD1[15:0].
* ST programmed value: System bootloader at 0x1FF0:0000
*
* The Durandal 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 swiutch is
* drepresed, then the boot will be from 0x1FF0:0000
*
* The STM32H743ZI 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 (rwx) : ORIGIN = 0x00000000, LENGTH = 64K
flash (rx) : ORIGIN = 0x08000000, LENGTH = 2048K
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) }
}

View File

@ -0,0 +1,228 @@
/****************************************************************************
* scripts/script.ld
*
* Copyright (C) 2016, 2019 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/* The board uses an STM32H743II and has 2048Kb of main FLASH memory.
* The flash memory is partitioned into a User Flash memory and a System
* Flash memory. Each of these memories has two banks:
*
* 1) User Flash memory:
*
* Bank 1: Start address 0x0800:0000 to 0x080F:FFFF with 8 sectors, 128Kb each
* Bank 2: Start address 0x0810:0000 to 0x081F:FFFF with 8 sectors, 128Kb each
*
* 2) System Flash memory:
*
* Bank 1: Start address 0x1FF0:0000 to 0x1FF1:FFFF with 1 x 128Kb sector
* Bank 1: Start address 0x1FF4:0000 to 0x1FF5:FFFF with 1 x 128Kb sector
*
* 3) User option bytes for user configuration, only in Bank 1.
*
* In the STM32H743II, two different boot spaces can be selected through
* the BOOT pin and the boot base address programmed in the BOOT_ADD0 and
* BOOT_ADD1 option bytes:
*
* 1) BOOT=0: Boot address defined by user option byte BOOT_ADD0[15:0].
* ST programmed value: Flash memory at 0x0800:0000
* 2) BOOT=1: Boot address defined by user option byte BOOT_ADD1[15:0].
* ST programmed value: System bootloader at 0x1FF0:0000
*
* There's a switch on board, the BOOT0 pin is at ground so by default,
* the STM32 will boot to address 0x0800:0000 in FLASH unless the switch is
* drepresed, then the boot will be from 0x1FF0:0000
*
* The STM32H743ZI 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) }
}

View File

@ -0,0 +1,67 @@
############################################################################
#
# Copyright (c) 2026 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# 3. Neither the name PX4 nor the names of its contributors may be
# used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
############################################################################
if("${PX4_BOARD_LABEL}" STREQUAL "bootloader")
add_library(drivers_board
bootloader_main.c
usb.c
)
target_link_libraries(drivers_board
PRIVATE
nuttx_arch
nuttx_drivers
bootloader
)
target_include_directories(drivers_board PRIVATE ${PX4_SOURCE_DIR}/platforms/nuttx/src/bootloader/common)
else()
add_library(drivers_board
i2c.cpp
init.c
led.c
spi.cpp
timer_config.cpp
usb.c
)
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
nuttx_arch
nuttx_drivers
px4_layer
)
endif()

View File

@ -0,0 +1,223 @@
/****************************************************************************
*
* Copyright (c) 2026 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
*
* AirBrainH743 (Gear Up) internal definitions
*/
#pragma once
/****************************************************************************************************
* Included Files
****************************************************************************************************/
#include <px4_platform_common/px4_config.h>
#include <nuttx/compiler.h>
#include <stdint.h>
#include <stm32_gpio.h>
/****************************************************************************************************
* Definitions
****************************************************************************************************/
/* Enable small flash logging support (for W25N NAND flash) */
#ifdef CONFIG_MTD_W25N
# define BOARD_SMALL_FLASH_LOGGING 1
#endif
/* LEDs are active low
* STAT RGB LED:
* PB15 = Blue
* PD11 = Green
* PD15 = Red
* BAT LED (orange): hardwired to power input
*/
#define GPIO_nLED_BLUE /* PB15 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_50MHz|GPIO_OUTPUT_SET|GPIO_PORTB|GPIO_PIN15)
#define GPIO_nLED_GREEN /* PD11 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_50MHz|GPIO_OUTPUT_SET|GPIO_PORTD|GPIO_PIN11)
#define GPIO_nLED_RED /* PD15 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_50MHz|GPIO_OUTPUT_SET|GPIO_PORTD|GPIO_PIN15)
#define BOARD_HAS_CONTROL_STATUS_LEDS 1
#define BOARD_OVERLOAD_LED LED_RED
#define BOARD_ARMED_STATE_LED LED_GREEN
/*
* 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 \
/* PC4 */ GPIO_ADC12_INP4, \
/* PC5 */ GPIO_ADC12_INP8
/* Define Channel numbers must match above GPIO pin IN(n)*/
#define ADC_BATTERY_VOLTAGE_CHANNEL /* PC4 */ ADC1_CH(4)
#define ADC_BATTERY_CURRENT_CHANNEL /* PC5 */ ADC1_CH(8)
#define ADC_CHANNELS \
((1 << ADC_BATTERY_VOLTAGE_CHANNEL) | \
(1 << ADC_BATTERY_CURRENT_CHANNEL))
/* Define Battery Voltage Divider and A per V
*/
#define BOARD_BATTERY1_V_DIV (15.0f)
#define BOARD_BATTERY1_A_PER_V (101.0f)
/* PWM
* 8 PWM outputs for motors + 1 for LED strip
*/
#define DIRECT_PWM_OUTPUT_CHANNELS 9
#define DIRECT_INPUT_TIMER_CHANNELS 9
#define BOARD_HAS_PWM DIRECT_PWM_OUTPUT_CHANNELS
/* Tone alarm output (directly connected to transistor switch of external buzzer)
*
* GPIO mode only (active buzzer) - passive buzzer with different tones is not
* supported because PA15 can only use TIM2, which is also used for motor outputs
* M7 (PB10, TIM2_CH3) and M8 (PB11, TIM2_CH4). The PWM tone alarm driver changes
* the timer's prescaler and auto-reload registers (shared across all channels),
* which would affect M7/M8 PWM frequency during tone playback.
*/
#define GPIO_TONE_ALARM_IDLE /* PA15 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTA|GPIO_PIN15)
#define GPIO_TONE_ALARM_GPIO /* PA15 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTA|GPIO_PIN15)
/* ICM42688P FSYNC - directly connected to IMU via GPIO (no timer).
* The driver clears TMST_FSYNC_EN and FIFO_TMST_FSYNC_EN, so FSYNC is unused.
* This GPIO is kept low to prevent spurious triggers.
*/
#define GPIO_42688P_FSYNC /* PC7 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTC|GPIO_PIN7)
/* USB OTG FS
*
* PD0 VBUS sensing (active high input)
*/
#define GPIO_OTGFS_VBUS /* PD0 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_SPEED_100MHz|GPIO_PORTD|GPIO_PIN0)
/* High-resolution timer */
#define HRT_TIMER 8 /* use timer8 for the HRT */
#define HRT_TIMER_CHANNEL 3 /* use capture/compare channel 3 */
/*
* Serial Port Mapping:
*
* UART Device Pins Function
* ---- ------ ---- --------
* USART1 /dev/ttyS0 PA9/PA10 Console/Debug
* USART2 /dev/ttyS1 PD5/PD6 RC Input
* USART3 /dev/ttyS2 PD8/PD9 TEL4 (DJI/MSP)
* UART4 /dev/ttyS3 PA0/PA1 TEL1
* UART5 /dev/ttyS4 PB13/PB12 TEL2
* UART7 /dev/ttyS5 PE8/PE7 TEL3 (ESC Telemetry)
* UART8 /dev/ttyS6 PE1/PE0 GPS1
*/
/* RC Serial port - USART2 (PD5/PD6) */
#define RC_SERIAL_PORT "/dev/ttyS1"
#define BOARD_SUPPORTS_RC_SERIAL_PORT_OUTPUT
/* 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_nLED_RED, \
GPIO_nLED_GREEN, \
GPIO_nLED_BLUE, \
GPIO_TONE_ALARM_IDLE, \
GPIO_42688P_FSYNC, \
}
#define BOARD_ENABLE_CONSOLE_BUFFER
#define BOARD_NUM_IO_TIMERS 4
__BEGIN_DECLS
/****************************************************************************************************
* Public Types
****************************************************************************************************/
/****************************************************************************************************
* Public data
****************************************************************************************************/
#ifndef __ASSEMBLY__
/****************************************************************************************************
* Public Functions
****************************************************************************************************/
/****************************************************************************
* Name: stm32_spiinitialize
*
* Description:
* Called to configure SPI chip select GPIO pins for the board.
*
****************************************************************************/
extern void stm32_spiinitialize(void);
extern void stm32_usbinitialize(void);
extern void board_peripheral_reset(int ms);
/* Parameters stored in internal flash */
#define FLASH_BASED_PARAMS
#include <px4_platform_common/board_common.h>
#endif /* __ASSEMBLY__ */
__END_DECLS

View File

@ -0,0 +1,75 @@
/****************************************************************************
*
* Copyright (c) 2026 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
*
* AirBrainH743-specific early startup code for bootloader
*/
#include "board_config.h"
#include "bl.h"
#include <nuttx/config.h>
#include <nuttx/board.h>
#include <chip.h>
#include <stm32_uart.h>
#include <arch/board/board.h>
#include "arm_internal.h"
#include <px4_platform_common/init.h>
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();
}

View File

@ -0,0 +1,85 @@
/****************************************************************************
*
* Copyright (C) 2026 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 APP_LOAD_ADDRESS 0x08020000
#define BOOTLOADER_DELAY 5000
#define INTERFACE_USB 1
#define INTERFACE_USB_CONFIG "/dev/ttyACM0"
#define BOARD_VBUS MK_GPIO_INPUT(GPIO_OTGFS_VBUS)
#define INTERFACE_USART 1
#define INTERFACE_USART_CONFIG "/dev/ttyS0,57600"
#define BOOT_DELAY_ADDRESS 0x000001a0
#define BOARD_TYPE 1209
#define _FLASH_KBYTES (*(uint32_t *)0x1FF1E880)
#define BOARD_FLASH_SECTORS (14)
#define BOARD_FLASH_SIZE (_FLASH_KBYTES * 1024)
#define OSC_FREQ 8
#define BOARD_PIN_LED_ACTIVITY GPIO_nLED_BLUE
#define BOARD_PIN_LED_BOOTLOADER GPIO_nLED_GREEN
#define BOARD_LED_ON 0
#define BOARD_LED_OFF 1
#define SERIAL_BREAK_DETECT_DISABLED 1
#if !defined(ARCH_SN_MAX_LENGTH)
# define ARCH_SN_MAX_LENGTH 12
#endif
/* Reserve 128KB (1 sector) at end of flash for parameters */
#define APP_RESERVATION_SIZE (1 * 128 * 1024)
#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
/* Boot device selection list*/
#define USB0_DEV 0x01
#define SERIAL0_DEV 0x02
#define SERIAL1_DEV 0x04

View File

@ -0,0 +1,47 @@
/****************************************************************************
*
* Copyright (C) 2026 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 <px4_arch/i2c_hw_description.h>
/*
* I2C bus configuration for AirBrainH743
*
* I2C1: Internal bus - PB6 (SCL), PB7 (SDA)
* Devices: DPS310 baro @ 0x76, LIS2MDL compass @ 0x1E
* I2C4: External bus - PD12 (SCL), PD13 (SDA)
*/
constexpr px4_i2c_bus_t px4_i2c_buses[I2C_BUS_MAX_BUS_ITEMS] = {
initI2CBusInternal(1),
initI2CBusExternal(4),
};

View File

@ -0,0 +1,249 @@
/****************************************************************************
*
* Copyright (c) 2026 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
*
* AirBrainH743-specific early startup code.
*/
#include "board_config.h"
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <debug.h>
#include <errno.h>
#include <syslog.h>
#include <fcntl.h>
#include <unistd.h>
#include <nuttx/config.h>
#include <nuttx/board.h>
#include <nuttx/spi/spi.h>
#include <nuttx/mtd/mtd.h>
#include <nuttx/fs/fs.h>
#include <arch/board/board.h>
#include "arm_internal.h"
#include <drivers/drv_hrt.h>
#include <drivers/drv_board_led.h>
#include <systemlib/px4_macros.h>
#include <px4_arch/io_timer.h>
#include <px4_platform_common/init.h>
#include <px4_platform/gpio.h>
#include <px4_platform/board_dma_alloc.h>
#if defined(FLASH_BASED_PARAMS)
#include <parameters/flashparams/flashfs.h>
#endif
#ifdef CONFIG_MTD_W25N
extern FAR struct mtd_dev_s *w25n_initialize(FAR struct spi_dev_s *dev, uint32_t spi_devid);
#endif
__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)
{
UNUSED(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(100);
}
}
/************************************************************************************
* Name: stm32_boardinitialize
*
* Description:
* All STM32 architectures must provide the following entry point.
*
************************************************************************************/
__EXPORT void stm32_boardinitialize(void)
{
/* Reset PWM first thing */
board_on_reset(-1);
/* configure LEDs */
board_autoled_initialize();
/* configure pins */
const uint32_t gpio[] = PX4_GPIO_INIT_LIST;
px4_gpio_init(gpio, arraySize(gpio));
/* configure USB interfaces */
stm32_usbinitialize();
}
/****************************************************************************
* Name: board_app_initialize
*
* Description:
* Perform application specific initialization.
*
****************************************************************************/
__EXPORT int board_app_initialize(uintptr_t arg)
{
/* 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");
}
/* initial LED state */
drv_led_start();
led_off(LED_RED);
led_off(LED_GREEN);
led_off(LED_BLUE);
if (board_hardfault_init(2, true) != 0) {
led_on(LED_RED);
}
#ifdef CONFIG_MTD_W25N
/* Initialize W25N01GV NAND Flash on SPI2 */
struct spi_dev_s *spi2 = stm32_spibus_initialize(2);
if (!spi2) {
syslog(LOG_ERR, "[boot] FAILED to initialize SPI2 for W25N\n");
led_on(LED_RED);
} else {
struct mtd_dev_s *mtd = w25n_initialize(spi2, 0);
if (!mtd) {
syslog(LOG_ERR, "[boot] FAILED to initialize W25N MTD driver\n");
led_on(LED_RED);
} else {
int ret = register_mtddriver("/dev/mtd0", mtd, 0755, NULL);
if (ret < 0) {
syslog(LOG_ERR, "[boot] FAILED to register MTD driver: %d\n", ret);
led_on(LED_RED);
} else {
syslog(LOG_INFO, "[boot] W25N MTD registered at /dev/mtd0\n");
#ifdef CONFIG_FS_LITTLEFS
ret = nx_mount("/dev/mtd0", CONFIG_BOARD_ROOT_PATH, "littlefs", 0, NULL);
if (ret == 0) {
/* Verify the filesystem is usable by creating a test file */
int fd = open(CONFIG_BOARD_ROOT_PATH "/.mount_test", O_CREAT | O_WRONLY | O_TRUNC);
if (fd >= 0) {
close(fd);
unlink(CONFIG_BOARD_ROOT_PATH "/.mount_test");
} else {
syslog(LOG_WARNING, "[boot] littlefs mounted but not usable, reformatting\n");
nx_umount2(CONFIG_BOARD_ROOT_PATH, 0);
ret = -1;
}
}
if (ret < 0) {
ret = nx_mount("/dev/mtd0", CONFIG_BOARD_ROOT_PATH, "littlefs", 0, "forceformat");
}
if (ret < 0) {
syslog(LOG_ERR, "[boot] FAILED to mount littlefs: %d\n", ret);
led_on(LED_RED);
} else {
syslog(LOG_INFO, "[boot] LittleFS mounted at %s\n", CONFIG_BOARD_ROOT_PATH);
}
#endif
}
}
}
#endif
#if defined(FLASH_BASED_PARAMS)
/* Initialize parameters in internal flash (sector 15, 128KB at 0x081E0000) */
static sector_descriptor_t params_sector_map[] = {
{15, 128 * 1024, 0x081E0000},
{0, 0, 0},
};
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_RED);
}
#endif
/* Configure the HW based on the manifest */
px4_platform_configure();
return OK;
}

View File

@ -0,0 +1,205 @@
/****************************************************************************
*
* Copyright (c) 2026 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 <px4_platform_common/px4_config.h>
#include <stdbool.h>
#include "chip.h"
#include "stm32_gpio.h"
#include "board_config.h"
#include <nuttx/board.h>
#include <arch/board/board.h>
__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;
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
GPIO_nLED_GREEN, // Indexed by BOARD_LED_GREEN
GPIO_nLED_BLUE, // Indexed by BOARD_LED_BLUE
};
#else
# define xlat(p) (p)
static uint32_t g_ledmap[] = {
GPIO_nLED_RED, // LED_RED
GPIO_nLED_GREEN, // LED_GREEN
GPIO_nLED_BLUE, // LED_BLUE
};
#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 (active low LEDs) */
if (led < (int)(sizeof(g_ledmap) / sizeof(g_ledmap[0])) && g_ledmap[led] != 0) {
stm32_gpiowrite(g_ledmap[led], !state);
}
}
static bool phy_get_led(int led)
{
/* If Low it is on */
if (led < (int)(sizeof(g_ledmap) / sizeof(g_ledmap[0])) && 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
****************************************************************************/
void board_autoled_initialize(void)
{
led_init();
}
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:
phy_set_led(BOARD_LED_RED, true);
break;
}
}
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:
phy_set_led(BOARD_LED_RED, false);
break;
}
}
#endif /* CONFIG_ARCH_LEDS */

View File

@ -0,0 +1,58 @@
/****************************************************************************
*
* Copyright (C) 2026 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 <px4_arch/spi_hw_description.h>
#include <drivers/drv_sensor.h>
#include <nuttx/spi/spi.h>
/*
* SPI bus configuration for AirBrainH743
*
* SPI1: IMU (Invensensev3/ICM42688P) - PA5 SCK, PA6 MISO, PA7 MOSI, PA3 CS
* SPI2: W25N Flash - PD3 SCK, PB14 MISO, PC3 MOSI, PD4 CS
* SPI4: External/AUX - PE12 SCK, PE5 MISO, PE6 MOSI
*/
constexpr px4_spi_bus_t px4_spi_buses[SPI_BUS_MAX_BUS_ITEMS] = {
initSPIBus(SPI::Bus::SPI1, {
initSPIDevice(DRV_IMU_DEVTYPE_ICM42688P, SPI::CS{GPIO::PortA, GPIO::Pin3}),
}),
initSPIBus(SPI::Bus::SPI2, {
initSPIDevice(SPIDEV_FLASH(0), SPI::CS{GPIO::PortD, GPIO::Pin4}), // W25N Flash
}),
initSPIBusExternal(SPI::Bus::SPI4, {
initSPIConfigExternal(SPI::CS{GPIO::PortB, GPIO::Pin3}), // User 1 GPIO as chip select
}),
};
static constexpr bool unused = validateSPIConfig(px4_spi_buses);

View File

@ -0,0 +1,74 @@
/****************************************************************************
*
* Copyright (C) 2026 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 <px4_arch/io_timer_hw_description.h>
/*
* PWM output configuration for AirBrainH743
*
* M1: PE14 (TIM1_CH4)
* M2: PE13 (TIM1_CH3)
* M3: PE11 (TIM1_CH2)
* M4: PE9 (TIM1_CH1)
* M5: PB0 (TIM3_CH3)
* M6: PB1 (TIM3_CH4)
* M7: PB10 (TIM2_CH3)
* M8: PB11 (TIM2_CH4)
* M9: PA2 (TIM5_CH3) - LED strip
*
* Note: TIM2 is shared with buzzer pin PA15 (TIM2_CH1). The buzzer is disabled
* by default because the tone alarm driver would change the timer prescaler/ARR
* which affects M7/M8 PWM frequency. See board_config.h for details.
*/
constexpr io_timers_t io_timers[MAX_IO_TIMERS] = {
initIOTimer(Timer::Timer1, DMA{DMA::Index1, DMA::Stream0, DMA::Channel6}),
initIOTimer(Timer::Timer3, DMA{DMA::Index1, DMA::Stream2, DMA::Channel5}),
initIOTimer(Timer::Timer2, DMA{DMA::Index1, DMA::Stream6, DMA::Channel3}),
initIOTimer(Timer::Timer5),
};
constexpr timer_io_channels_t timer_io_channels[MAX_TIMER_IO_CHANNELS] = {
initIOTimerChannel(io_timers, {Timer::Timer1, Timer::Channel4}, {GPIO::PortE, GPIO::Pin14}), // M1
initIOTimerChannel(io_timers, {Timer::Timer1, Timer::Channel3}, {GPIO::PortE, GPIO::Pin13}), // M2
initIOTimerChannel(io_timers, {Timer::Timer1, Timer::Channel2}, {GPIO::PortE, GPIO::Pin11}), // M3
initIOTimerChannel(io_timers, {Timer::Timer1, Timer::Channel1}, {GPIO::PortE, GPIO::Pin9}), // M4
initIOTimerChannel(io_timers, {Timer::Timer3, Timer::Channel3}, {GPIO::PortB, GPIO::Pin0}), // M5
initIOTimerChannel(io_timers, {Timer::Timer3, Timer::Channel4}, {GPIO::PortB, GPIO::Pin1}), // M6
initIOTimerChannel(io_timers, {Timer::Timer2, Timer::Channel3}, {GPIO::PortB, GPIO::Pin10}), // M7
initIOTimerChannel(io_timers, {Timer::Timer2, Timer::Channel4}, {GPIO::PortB, GPIO::Pin11}), // M8
initIOTimerChannel(io_timers, {Timer::Timer5, Timer::Channel3}, {GPIO::PortA, GPIO::Pin2}), // M9 (LED)
};
constexpr io_timers_channel_mapping_t io_timers_channel_mapping =
initIOTimerChannelMapping(io_timers, timer_io_channels);

View File

@ -0,0 +1,75 @@
/****************************************************************************
*
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file usb.c
*
* Board-specific USB functions.
*/
#include "board_config.h"
#include <nuttx/usb/usbdev.h>
#include <nuttx/usb/usbdev_trace.h>
#include <stm32_otg.h>
#include <debug.h>
/************************************************************************************
* Name: stm32_usbinitialize
*
* Description:
* Called to setup USB-related GPIO pins for the board.
*
************************************************************************************/
__EXPORT void stm32_usbinitialize(void)
{
/* The OTG FS has an internal soft pull-up */
/* Configure the OTG FS VBUS sensing GPIO */
#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.
*
************************************************************************************/
__EXPORT void stm32_usbsuspend(FAR struct usbdev_s *dev, bool resume)
{
uinfo("resume: %d\n", resume);
}

View File

@ -1,5 +1,6 @@
CONFIG_BOARD_TOOLCHAIN="arm-none-eabi"
CONFIG_BOARD_ARCHITECTURE="cortex-m7"
CONFIG_BOARD_ROOT_PATH="/fs/flash"
CONFIG_BOARD_SERIAL_GPS1="/dev/ttyS3"
CONFIG_BOARD_SERIAL_TEL1="/dev/ttyS0"
CONFIG_BOARD_SERIAL_TEL2="/dev/ttyS1"

View File

@ -38,5 +38,6 @@ param set-default SYS_DM_BACKEND 1
# Ignore that there is no SD card
param set-default COM_ARM_SDCARD 0
# Disable logging
param set-default SDLOG_BACKEND 0
# W25N NAND flash with littlefs (128 MB): larger buffer, auto-rotate
set LOGGER_BUF 32
param set-default SDLOG_DIRS_MAX 3

View File

@ -99,7 +99,7 @@
* 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
* PLL1Q = PLL1_VCO/5 = 960 MHz / 5 = 192 MHz (SPI123 clock, max 200 MHz)
* PLL1R = PLL1_VCO/8 = 960 MHz / 8 = 120 MHz
*/
@ -111,12 +111,12 @@
#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_PLL1Q RCC_PLL1DIVR_Q1(5)
#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_PLL1Q_FREQUENCY (STM32_VCO1_FREQUENCY / 5)
#define STM32_PLL1R_FREQUENCY (STM32_VCO1_FREQUENCY / 8)
/* PLL2 */
@ -227,9 +227,9 @@
#define STM32_RCC_D3CCIPR_I2C4SRC RCC_D3CCIPR_I2C4SEL_HSI
/* SPI123 clock source */
/* SPI123 clock source - PLL1Q = 192 MHz for W25N NAND flash (max 104 MHz) */
#define STM32_RCC_D2CCIP1R_SPI123SRC RCC_D2CCIP1R_SPI123SEL_PLL2
#define STM32_RCC_D2CCIP1R_SPI123SRC RCC_D2CCIP1R_SPI123SEL_PLL1
/* SPI45 clock source */
@ -281,17 +281,17 @@
#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
/* 25 MHz Max for now, 25 mHz = PLL1Q/(2*div), div = PLL1Q/(2*freq)
* PLL1Q = 192 MHz, div = 192 / 50 = 3.84, round up to 4 for 24 MHz
*/
#if defined(CONFIG_STM32H7_SDMMC_XDMA) || defined(CONFIG_STM32H7_SDMMC_IDMA)
# define STM32_SDMMC_MMCXFR_CLKDIV (5 << STM32_SDMMC_CLKCR_CLKDIV_SHIFT)
# define STM32_SDMMC_MMCXFR_CLKDIV (4 << 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)
# define STM32_SDMMC_SDXFR_CLKDIV (4 << STM32_SDMMC_CLKCR_CLKDIV_SHIFT)
#else
# define STM32_SDMMC_SDXFR_CLKDIV (100 << STM32_SDMMC_CLKCR_CLKDIV_SHIFT)
#endif

View File

@ -33,6 +33,10 @@
#pragma once
/* SPI1 DMA for W25N NAND Flash */
#define DMAMAP_SPI1_RX DMAMAP_DMA12_SPI1RX_0 /* DMA1 */
#define DMAMAP_SPI1_TX DMAMAP_DMA12_SPI1TX_0 /* DMA1 */
#define DMAMAP_SPI4_RX DMAMAP_DMA12_SPI4RX_1 /* DMA2 */
#define DMAMAP_SPI4_TX DMAMAP_DMA12_SPI4TX_1 /* DMA2 */

View File

@ -104,6 +104,10 @@ CONFIG_FS_PROCFS_INCLUDE_PROGMEM=y
CONFIG_FS_PROCFS_MAX_TASKS=64
CONFIG_FS_PROCFS_REGISTER=y
CONFIG_FS_ROMFS=y
CONFIG_FS_LITTLEFS=y
CONFIG_FS_LITTLEFS_PROGRAM_SIZE_FACTOR=1
CONFIG_FS_LITTLEFS_READ_SIZE_FACTOR=1
CONFIG_FS_LITTLEFS_CACHE_SIZE_FACTOR=1
CONFIG_GRAN=y
CONFIG_GRAN_INTR=y
CONFIG_HAVE_CXX=y
@ -126,7 +130,9 @@ CONFIG_MTD=y
CONFIG_MTD_BYTE_WRITE=y
CONFIG_MTD_PARTITION=y
CONFIG_MTD_PROGMEM=y
CONFIG_MTD_RAMTRON=y
# CONFIG_MTD_RAMTRON is not set
CONFIG_MTD_W25N=y
CONFIG_W25N_SPIFREQUENCY=104000000
CONFIG_NAME_MAX=40
CONFIG_NSH_ARCHINIT=y
CONFIG_NSH_ARGCAT=y
@ -135,7 +141,7 @@ CONFIG_NSH_CMDPARMS=y
CONFIG_NSH_CROMFSETC=y
CONFIG_NSH_LINELEN=128
CONFIG_NSH_MAXARGUMENTS=15
CONFIG_NSH_MMCSDSPIPORTNO=1
# CONFIG_NSH_MMCSDSPIPORTNO is not set
CONFIG_NSH_NESTDEPTH=8
CONFIG_NSH_QUOTE=y
CONFIG_NSH_ROMFSETC=y
@ -148,9 +154,6 @@ CONFIG_PREALLOC_TIMERS=50
CONFIG_PRIORITY_INHERITANCE=y
CONFIG_PTHREAD_MUTEX_ROBUST=y
CONFIG_PTHREAD_STACK_MIN=512
CONFIG_RAMTRON_EMULATE_PAGE_SHIFT=5
CONFIG_RAMTRON_EMULATE_SECTOR_SHIFT=5
CONFIG_RAMTRON_SETSPEED=y
CONFIG_RAM_SIZE=245760
CONFIG_RAM_START=0x20010000
CONFIG_RAW_BINARY=y
@ -188,6 +191,7 @@ CONFIG_STM32H7_BKPSRAM=y
CONFIG_STM32H7_DMA1=y
CONFIG_STM32H7_DMA2=y
CONFIG_STM32H7_DMACAPABLE=y
CONFIG_STM32H7_DMAMUX1=y
CONFIG_STM32H7_FLOWCONTROL_BROKEN=y
CONFIG_STM32H7_I2C1=y
CONFIG_STM32H7_I2C_DYNTIMEO=y
@ -202,6 +206,8 @@ CONFIG_STM32H7_SDMMC1=y
CONFIG_STM32H7_SERIALBRK_BSDCOMPAT=y
CONFIG_STM32H7_SERIAL_DISABLE_REORDERING=y
CONFIG_STM32H7_SPI1=y
CONFIG_STM32H7_SPI1_DMA=y
CONFIG_STM32H7_SPI1_DMA_BUFFER=4096
CONFIG_STM32H7_SPI2=y
CONFIG_STM32H7_SPI4=y
CONFIG_STM32H7_SPI4_DMA=y

View File

@ -59,6 +59,11 @@
# define BOARD_HAS_NBAT_V 1
# define BOARD_HAS_NBAT_I 1
/* Enable small flash logging support (for W25N NAND flash) */
#ifdef CONFIG_MTD_W25N
# define BOARD_SMALL_FLASH_LOGGING 1
#endif
/* Holybro KakuteH7 GPIOs ************************************************************************/
/* LEDs are driven with push open drain to support Anode to 5V or 3.3V */

View File

@ -59,6 +59,8 @@
#include <nuttx/spi/spi.h>
#include <nuttx/analog/adc.h>
#include <nuttx/mm/gran.h>
#include <nuttx/mtd/mtd.h>
#include <nuttx/fs/fs.h>
#include <chip.h>
#include <stm32_uart.h>
#include <arch/board/board.h>
@ -79,6 +81,10 @@
# include <parameters/flashparams/flashfs.h>
#endif
#ifdef CONFIG_MTD_W25N
extern FAR struct mtd_dev_s *w25n_initialize(FAR struct spi_dev_s *dev, uint32_t spi_devid);
#endif
/****************************************************************************
* Pre-Processor Definitions
@ -231,14 +237,49 @@ __EXPORT int board_app_initialize(uintptr_t arg)
led_on(LED_RED);
}
/* Get the SPI port for the microSD slot */
struct spi_dev_s *spi_dev = stm32_spibus_initialize(CONFIG_NSH_MMCSDSPIPORTNO);
#ifdef CONFIG_MTD_W25N
/* Initialize W25N01GV NAND Flash on SPI1 */
struct spi_dev_s *spi1 = stm32_spibus_initialize(1);
if (!spi_dev) {
syslog(LOG_ERR, "[boot] FAILED to initialize SPI port %d\n", CONFIG_NSH_MMCSDSPIPORTNO);
led_on(LED_BLUE);
if (!spi1) {
syslog(LOG_ERR, "[boot] FAILED to initialize SPI1 for W25N\n");
led_on(LED_RED);
} else {
struct mtd_dev_s *mtd = w25n_initialize(spi1, 0);
if (!mtd) {
syslog(LOG_ERR, "[boot] FAILED to initialize W25N MTD driver\n");
led_on(LED_RED);
} else {
int ret = register_mtddriver("/dev/mtd0", mtd, 0755, NULL);
if (ret < 0) {
syslog(LOG_ERR, "[boot] FAILED to register MTD driver: %d\n", ret);
led_on(LED_RED);
} else {
syslog(LOG_INFO, "[boot] W25N MTD registered at /dev/mtd0\n");
#ifdef CONFIG_FS_LITTLEFS
ret = nx_mount("/dev/mtd0", CONFIG_BOARD_ROOT_PATH, "littlefs", 0, "autoformat");
if (ret < 0) {
syslog(LOG_ERR, "[boot] FAILED to mount littlefs: %d\n", ret);
led_on(LED_RED);
} else {
syslog(LOG_INFO, "[boot] LittleFS mounted at %s\n", CONFIG_BOARD_ROOT_PATH);
}
#endif
}
}
}
#endif
up_udelay(20);

View File

@ -37,7 +37,7 @@
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})
initSPIDevice(SPIDEV_FLASH(0), SPI::CS{GPIO::PortA, GPIO::Pin4}) // W25N01GV NAND Flash
}),
initSPIBus(SPI::Bus::SPI2, {
initSPIDevice(DRV_OSD_DEVTYPE_ATXXXX, SPI::CS{GPIO::PortB, GPIO::Pin12}),

@ -1 +1 @@
Subproject commit 85151aaf6ba8b24ce82b387e088452c63f7e2096
Subproject commit d5abf9cbbf07711db2a9166c2eec4a4a7682f921

View File

@ -178,6 +178,7 @@
- [CubePilot Cube Orange (CubePilot)](flight_controller/cubepilot_cube_orange.md)
- [CubePilot Cube Yellow (CubePilot)](flight_controller/cubepilot_cube_yellow.md)
- [Cube Wiring Quickstart](assembly/quick_start_cube.md)
- [Gear Up AirBrainH743](flight_controller/gearup_airbrainh743.md)
- [Holybro Kakute H7v2](flight_controller/kakuteh7v2.md)
- [Holybro Kakute H7mini](flight_controller/kakuteh7mini.md)
- [Holybro Kakute H7](flight_controller/kakuteh7.md)

View File

@ -25,6 +25,7 @@ The boards in this category are:
- [CubePilot Cube Orange+](../flight_controller/cubepilot_cube_orangeplus.md)
- [CubePilot Cube Orange](../flight_controller/cubepilot_cube_orange.md)
- [CubePilot Cube Yellow](../flight_controller/cubepilot_cube_yellow.md)
- [Gear Up AirBrainH743](../flight_controller/gearup_airbrainh743.md)
- [Holybro Kakute H7v2](../flight_controller/kakuteh7v2.md)
- [Holybro Kakute H7mini](../flight_controller/kakuteh7mini.md)
- [Holybro Kakute H7](../flight_controller/kakuteh7.md)

View File

@ -0,0 +1,96 @@
# Gear Up AirBrainH743
:::warning
PX4 does not manufacture this (or any) autopilot.
Contact the [manufacturer](https://takeyourgear.com/) for hardware support.
:::
::: info
This flight controller is [manufacturer supported](../flight_controller/autopilot_manufacturer_supported.md).
:::
Purchase from [takeyourgear.com](https://takeyourgear.com/pages/products/airbrain).
For more information and pinout, check the [GitHub documentation](https://github.com/GearUp-Company/AirBrainH743).
## Key Features
- MCU: STM32H743 32-bit processor running at 480 MHz
- IMU: ICM42688P
- Barometer: DPS310
- Magnetometer: LIS2MDL (internal)
- 128MB NAND Flash for logging (W25N)
- 7x UARTs
- I2C, SPI
- 9x PWM Outputs (8 Motor outputs, 1 LED strip)
- Battery input voltage: 3S-10S
- Battery voltage/current monitoring
- 5V@2A and 10V@2.5A BEC outputs
- USB Type-C (IP68)
- EMC and ESD protection
## Connectors and Pins
:::warning
The pin order is different from the Pixhawk standard (compatible to the Betaflight standard).
:::
### UARTs
Current UART configuration:
| UART | Device | Function |
| ------ | ---------- | ---------------------------- |
| USART1 | /dev/ttyS0 | Console/Debug |
| USART2 | /dev/ttyS1 | RC Input |
| USART3 | /dev/ttyS2 | TEL4 (DJI/MSP) |
| UART4 | /dev/ttyS3 | TEL1 |
| UART5 | /dev/ttyS4 | TEL2 |
| UART7 | /dev/ttyS5 | TEL3 (ESC Telemetry) |
| UART8 | /dev/ttyS6 | GPS1 |
### Motor/Servo Outputs
| Connector | Pin | Function |
| ----------| ------------------ |
| ESC | M1 | Motor 1 |
| ESC | M2 | Motor 2 |
| ESC | M3 | Motor 3 |
| ESC | M4 | Motor 4 |
| PWM | M5 | Motor 5 |
| PWM | M6 | Motor 6 |
| PWM | M7 | Motor 7 |
| PWM | M8 | Motor 8 |
| AUX | M9 | LED/PWM/etc. |
<a id="bootloader"></a>
## PX4 Bootloader Update
Before PX4 firmware can be installed, the _PX4 bootloader_ must be flashed.
Download the [gearup_airbrainh743_bootloader.bin](https://github.com/PX4/PX4-Autopilot/blob/main/boards/gearup/airbrainh743/extras/gearup_airbrainh743_bootloader.bin) bootloader binary and read [this page](../advanced_config/bootloader_update_from_betaflight.md) for flashing instructions.
## Building Firmware
To [build PX4](../dev_setup/building_px4.md) for this target:
```
make gearup_airbrainh743_default
```
## Installing PX4 Firmware
Firmware can be installed in any of the normal ways:
- Build and upload the source:
```
make gearup_airbrainh743_default upload
```
- [Load the firmware](../config/firmware.md) using _QGroundControl_.
You can use either pre-built firmware or your own custom firmware.
### System Console
UART1 (ttyS0) is configured for use as the [System Console](../debug/system_console.md).

View File

@ -27,7 +27,7 @@ Unless the mode is safety-critical, requires strict timing or very high update r
::: tip
If you want to use Python, check out the [examples in the repository](https://github.com/Auterion/px4-ros2-interface-lib/tree/main/examples/python).
Not all classes have Python bindings yet — the [supported bindings are here](https://github.com/Auterion/px4-ros2-interface-lib/tree/main/px4_ros2_py/src/px4_ros2).
Not all classes have Python bindings yet — the [supported bindings are here](https://auterion.github.io/px4-ros2-interface-lib/python/index.html).
You are welcome to add and contribute missing classes.
:::

View File

@ -73,22 +73,6 @@ uint32 SYSTEM_ERROR_CPU_OVERLOAD = 32
uint32 SYSTEM_ERROR_OUTPUT_CONGESTION = 64
uint32 system_error # General errors with the connected GPS receiver
uint16 diff_age # Differential correction age [seconds]. 0xFFFF = unavailable.
uint8 ANTENNA_STATUS_UNKNOWN = 0
uint8 ANTENNA_STATUS_INIT = 1
uint8 ANTENNA_STATUS_OK = 2
uint8 ANTENNA_STATUS_SHORT = 3
uint8 ANTENNA_STATUS_OPEN = 4
uint8 antenna_status # Antenna supervisor state
uint8 ANTENNA_POWER_UNKNOWN = 0
uint8 ANTENNA_POWER_OFF = 1
uint8 ANTENNA_POWER_ON = 2
uint8 antenna_power # Antenna power status
uint8 fix_quality # Fix quality/confidence indicator [0-100]. 0 = no confidence, 100 = full confidence.
float32 heading # heading angle of XYZ body frame rel to NED. Set to NaN if not available and updated (used for dual antenna GPS), (rad, [-PI, PI])
float32 heading_offset # heading offset of dual antenna array in body frame. Set to NaN if not applicable. (rad, [-PI, PI])
float32 heading_accuracy # heading accuracy (rad, [0, 2PI])

View File

@ -2,6 +2,7 @@
#include <px4_platform_common/time.h>
#include <px4_platform_common/posix.h>
#include <px4_platform_common/log.h>
#include <uORB/uORB.h>
#include "apps.h"
@ -43,6 +44,7 @@ void list_builtins(apps_map_type &apps)
int shutdown_main(int argc, char *argv[])
{
printf("Exiting NOW.\n");
uorb_shutdown();
system_exit(0);
}

View File

@ -49,6 +49,7 @@
#include <px4_platform_common/external_reset_lockout.h>
#include <px4_platform_common/log.h>
#include <uORB/uORB.h>
#include <stdint.h>
#include <errno.h>
@ -173,6 +174,8 @@ static void shutdown_worker(void *arg)
const bool delay_elapsed = (now > shutdown_time_us);
if (delay_elapsed && ((done && shutdown_lock_counter == 0) || (now > (shutdown_time_us + shutdown_timeout_us)))) {
uorb_shutdown();
if (shutdown_args & SHUTDOWN_ARG_REBOOT) {
#if defined(CONFIG_BOARDCTL_RESET)
PX4_INFO_RAW("Reboot NOW.");

View File

@ -51,6 +51,7 @@
#include <sys/boardctl.h>
#endif
static uORB::DeviceMaster *g_dev = nullptr;
int uorb_start(void)
@ -113,6 +114,18 @@ int uorb_top(char **topic_filter, int num_filters)
return OK;
}
void uorb_shutdown(void)
{
#ifdef CONFIG_ORB_COMMUNICATOR
uORBCommunicator::IChannel *ch = uORB::Manager::get_instance()->get_uorb_communicator();
if (ch) {
ch->shutdown();
}
#endif /* CONFIG_ORB_COMMUNICATOR */
}
orb_advert_t orb_advertise(const struct orb_metadata *meta, const void *data)
{
return uORB::Manager::get_instance()->orb_advertise(meta, data);

View File

@ -121,6 +121,7 @@ __BEGIN_DECLS
int uorb_start(void);
int uorb_status(void);
int uorb_top(char **topic_filter, int num_filters);
void uorb_shutdown(void);
/**
* ORB topic advertiser handle.

View File

@ -129,6 +129,22 @@ public:
virtual int16_t send_message(const char *messageName, int32_t length, uint8_t *data) = 0;
//=========================================================================
// INTERFACES FOR Lifecycle messages
//=========================================================================
/**
* @brief Interface to notify the remote entity of a shutdown.
*
* @return
* 0 = success; This means the shutdown is successfully sent to the receiver
* Note: This does not mean that the receiver has received it.
* otherwise = failure.
*/
virtual int16_t shutdown() { return 0; }
};
/**

@ -1 +1 @@
Subproject commit 201d8b01f14269a9647ef6da499214ffd39ff8f0
Subproject commit f34ff89edf9764fdd177f3faa616d85ebf2778f2

View File

@ -51,7 +51,7 @@
#include <errno.h>
#include "hrt_work.h"
// Voxl2 board specific API definitions to get time offset
// Voxl board specific API definitions to get time
#if defined(CONFIG_MUORB_APPS_SYNC_TIMESTAMP)
#include "fc_sensor.h"
#endif
@ -112,29 +112,6 @@ hrt_abstime hrt_absolute_time()
#else // defined(ENABLE_LOCKSTEP_SCHEDULER)
struct timespec ts;
px4_clock_gettime(CLOCK_MONOTONIC, &ts);
# if defined(CONFIG_MUORB_APPS_SYNC_TIMESTAMP)
hrt_abstime temp_abstime = ts_to_abstime(&ts);
int apps_time_offset = fc_sensor_get_time_offset();
if (apps_time_offset < 0) {
hrt_abstime temp_offset = -apps_time_offset;
if (temp_offset >= temp_abstime) {
temp_abstime = 0;
} else {
temp_abstime -= temp_offset;
}
} else {
temp_abstime += (hrt_abstime) apps_time_offset;
}
ts.tv_sec = temp_abstime / 1000000;
ts.tv_nsec = (temp_abstime % 1000000) * 1000;
# endif // defined(CONFIG_MUORB_APPS_SYNC_TIMESTAMP)
return ts_to_abstime(&ts);
#endif // defined(ENABLE_LOCKSTEP_SCHEDULER)
}
@ -476,8 +453,21 @@ int px4_clock_gettime(clockid_t clk_id, struct timespec *tp)
}
#endif // defined(ENABLE_LOCKSTEP_SCHEDULER)
return system_clock_gettime(clk_id, tp);
int rv = system_clock_gettime(clk_id, tp);
# if defined(CONFIG_MUORB_APPS_SYNC_TIMESTAMP)
// On VOXL use DSP clock as reference for MONOTONIC
if (clk_id == CLOCK_MONOTONIC) {
hrt_abstime temp_abstime = fc_sensor_get_dsp_timestamp_us();
tp->tv_sec = temp_abstime / 1000000;
tp->tv_nsec = (temp_abstime % 1000000) * 1000;
}
# endif // defined(CONFIG_MUORB_APPS_SYNC_TIMESTAMP)
return rv;
}
#if defined(ENABLE_LOCKSTEP_SCHEDULER)

View File

@ -73,6 +73,7 @@
#include <px4_platform_common/getopt.h>
#include <px4_platform_common/tasks.h>
#include <px4_platform_common/posix.h>
#include <uORB/uORB.h>
#include "apps.h"
#include "px4_daemon/client.h"
@ -505,6 +506,7 @@ void sig_int_handler(int sig_num)
fflush(stdout);
printf("\nPX4 Exiting...\n");
fflush(stdout);
uorb_shutdown();
px4_daemon::Pxh::stop();
_exit_requested = true;
}

View File

@ -19,6 +19,10 @@ actuator_output:
label: 'ESC 3 Spin Direction'
- param: 'VOXL_ESC_SDIR4'
label: 'ESC 4 Spin Direction'
- param: 'VOXL_ESC_CMD'
label: 'ESC Command Type'
- param: 'VOXL_ESC_PWR_MIN'
label: 'ESC Minimum Power With PWM Command Type'
output_groups:
- param_prefix: VOXL_ESC
group_label: 'ESCs'

View File

@ -300,6 +300,7 @@ int VoxlEsc::load_params(voxl_esc_params_t *params, ch_assign_t *map)
param_get(param_find("VOXL_ESC_SDIR3"), &params->direction_map[2]);
param_get(param_find("VOXL_ESC_SDIR4"), &params->direction_map[3]);
param_get(param_find("VOXL_ESC_PWR_MIN"), &params->pwr_min);
param_get(param_find("VOXL_ESC_RPM_MIN"), &params->rpm_min);
param_get(param_find("VOXL_ESC_RPM_MAX"), &params->rpm_max);
@ -311,10 +312,23 @@ int VoxlEsc::load_params(voxl_esc_params_t *params, ch_assign_t *map)
param_get(param_find("VOXL_ESC_GPIO_CH"), &params->gpio_ctl_channel);
if (params->rpm_min >= params->rpm_max) {
PX4_ERR("Invalid parameter VOXL_ESC_RPM_MIN. Please verify parameters.");
params->rpm_min = 0;
ret = PX4_ERROR;
param_get(param_find("VOXL_ESC_CMD"), &params->cmd_type);
if (params->cmd_type > VOXL_ESC_PWM_CMDS) {
PX4_WARN("Warning, VOXL_ESC_CMD set to invalid value %d. Using 1 instead", (int) params->cmd_type);
params->cmd_type = VOXL_ESC_PWM_CMDS;
} else if (params->cmd_type < VOXL_ESC_RPM_CMDS) {
PX4_WARN("Warning, VOXL_ESC_CMD set to invalid value %d. Using 0 instead", (int) params->cmd_type);
params->cmd_type = VOXL_ESC_RPM_CMDS;
}
if (params->cmd_type == VOXL_ESC_RPM_CMDS) {
if (params->rpm_min >= params->rpm_max) {
PX4_ERR("Invalid parameter VOXL_ESC_RPM_MIN. Please verify parameters.");
params->rpm_min = 0;
ret = PX4_ERROR;
}
}
if (params->turtle_motor_percent < 0 || params->turtle_motor_percent > 100) {
@ -392,19 +406,24 @@ int VoxlEsc::task_spawn(int argc, char *argv[])
int ch;
const char *myoptarg = nullptr;
while ((ch = px4_getopt(argc, argv, "dv", &myoptind, &myoptarg)) != EOF) {
switch (ch) {
case 'd':
_device = argv[myoptind];
break;
VoxlEsc *instance = new VoxlEsc();
default:
break;
// Parse any passed in options
if ((argc > 1) && (argv[1] != nullptr)) {
while ((ch = px4_getopt(argc - 1, &argv[1], "d:", &myoptind, &myoptarg)) != EOF) {
switch (ch) {
case 'd':
_device = argv[myoptind];
PX4_INFO("Configuring device as %s", _device);
break;
default:
PX4_ERR("Unknown option: %c", ch);
break;
}
}
}
VoxlEsc *instance = new VoxlEsc();
if (instance) {
_object.store(instance);
_task_id = task_id_is_work_queue;
@ -571,6 +590,8 @@ int VoxlEsc::parse_response(uint8_t *buf, uint8_t len, bool print_feedback)
QC_ESC_FB_POWER_STATUS packet;
memcpy(&packet, _fb_packet.buffer, packet_size);
_rx_power_status_count++;
float voltage = packet.voltage * 0.001f; // Voltage is reported at 1 mV resolution
float current = packet.current * 0.008f; // Total current is reported at 8mA resolution
@ -907,8 +928,19 @@ int VoxlEsc::update_params()
if (ret == PX4_OK) {
_mixing_output.setAllDisarmedValues(0);
_mixing_output.setAllFailsafeValues(0);
_mixing_output.setAllMinValues(_parameters.rpm_min);
_mixing_output.setAllMaxValues(_parameters.rpm_max);
if (_parameters.cmd_type == VOXL_ESC_RPM_CMDS) {
_mixing_output.setAllMinValues(_parameters.rpm_min);
_mixing_output.setAllMaxValues(_parameters.rpm_max);
} else if (_parameters.cmd_type == VOXL_ESC_PWM_CMDS) {
// we use a minimum value of 1, since 0 is for disarmed
_min_active_pwm = math::constrain(static_cast<int>((_parameters.pwr_min *
static_cast<float>(VOXL_ESC_PWM_MAX))),
VOXL_ESC_PWM_MIN, VOXL_ESC_PWM_MAX);
_mixing_output.setAllMinValues(_min_active_pwm);
_mixing_output.setAllMaxValues(VOXL_ESC_PWM_MAX);
}
_rpm_fullscale = _parameters.rpm_max - _parameters.rpm_min;
}
@ -1216,11 +1248,18 @@ bool VoxlEsc::updateOutputs(uint16_t outputs[MAX_ACTUATORS],
_esc_chans[i].rate_req = 0;
} else {
if (_extended_rpm) {
if (outputs[i] > VOXL_ESC_RPM_MAX_EXT) { outputs[i] = VOXL_ESC_RPM_MAX_EXT; }
if ((_turtle_mode_en) || (_parameters.cmd_type == VOXL_ESC_RPM_CMDS)) {
if (_extended_rpm) {
if (outputs[i] > VOXL_ESC_RPM_MAX_EXT) { outputs[i] = VOXL_ESC_RPM_MAX_EXT; }
} else {
if (outputs[i] > VOXL_ESC_RPM_MAX) { outputs[i] = VOXL_ESC_RPM_MAX; }
} else {
if (outputs[i] > VOXL_ESC_RPM_MAX) { outputs[i] = VOXL_ESC_RPM_MAX; }
}
} else if (_parameters.cmd_type == VOXL_ESC_PWM_CMDS) {
if (outputs[i] > VOXL_ESC_PWM_MAX) { outputs[i] = VOXL_ESC_PWM_MAX; }
else if (outputs[i] < _min_active_pwm) { outputs[i] = _min_active_pwm; }
}
if (!_turtle_mode_en) {
@ -1235,18 +1274,34 @@ bool VoxlEsc::updateOutputs(uint16_t outputs[MAX_ACTUATORS],
Command cmd;
cmd.len = qc_esc_create_rpm_packet4_fb(_esc_chans[0].rate_req,
_esc_chans[1].rate_req,
_esc_chans[2].rate_req,
_esc_chans[3].rate_req,
_esc_chans[0].led,
_esc_chans[1].led,
_esc_chans[2].led,
_esc_chans[3].led,
_fb_idx,
cmd.buf,
sizeof(cmd.buf),
_extended_rpm);
if (_parameters.cmd_type == VOXL_ESC_RPM_CMDS) {
cmd.len = qc_esc_create_rpm_packet4_fb(_esc_chans[0].rate_req,
_esc_chans[1].rate_req,
_esc_chans[2].rate_req,
_esc_chans[3].rate_req,
_esc_chans[0].led,
_esc_chans[1].led,
_esc_chans[2].led,
_esc_chans[3].led,
_fb_idx,
cmd.buf,
sizeof(cmd.buf),
_extended_rpm);
} else if (_parameters.cmd_type == VOXL_ESC_PWM_CMDS) {
cmd.len = qc_esc_create_pwm_packet4_fb(_esc_chans[0].rate_req,
_esc_chans[1].rate_req,
_esc_chans[2].rate_req,
_esc_chans[3].rate_req,
_esc_chans[0].led,
_esc_chans[1].led,
_esc_chans[2].led,
_esc_chans[3].led,
_fb_idx,
cmd.buf,
sizeof(cmd.buf));
}
if (_uart_port.write(cmd.buf, cmd.len) != cmd.len) {
PX4_ERR("Failed to send packet");
@ -1631,6 +1686,8 @@ void VoxlEsc::print_params()
PX4_INFO("Params: VOXL_ESC_SDIR3: %" PRId32, _parameters.direction_map[2]);
PX4_INFO("Params: VOXL_ESC_SDIR4: %" PRId32, _parameters.direction_map[3]);
PX4_INFO("Params: VOXL_ESC_PWR_MIN: %f", (double) _parameters.pwr_min);
PX4_INFO("Params: VOXL_ESC_RPM_MIN: %" PRId32, _parameters.rpm_min);
PX4_INFO("Params: VOXL_ESC_RPM_MAX: %" PRId32, _parameters.rpm_max);
@ -1647,6 +1704,8 @@ void VoxlEsc::print_params()
PX4_INFO("Params: VOXL_ESC_T_OVER: %" PRId32, _parameters.esc_over_temp_threshold);
PX4_INFO("Params: VOXL_ESC_GPIO_CH: %" PRId32, _parameters.gpio_ctl_channel);
PX4_INFO("Params: VOXL_ESC_CMD: %" PRId32, _parameters.cmd_type);
}
int VoxlEsc::print_status()
@ -1656,6 +1715,10 @@ int VoxlEsc::print_status()
PX4_INFO("UART port: %s", _device);
PX4_INFO("UART open: %s", _uart_port.isOpen() ? "yes" : "no");
PX4_INFO("CRC error count: %lu", (long unsigned int) _rx_crc_error_count);
PX4_INFO("Packet RX count: %lu", (long unsigned int) _rx_packet_count);
PX4_INFO("Power status count: %lu", (long unsigned int) _rx_power_status_count);
PX4_INFO("");
print_params();
PX4_INFO("");
@ -1695,6 +1758,7 @@ const char * VoxlEsc::board_id_to_name(int board_id)
case 40: return "ModalAi 4-in-1 ESC (M0129-3)";
case 41: return "ModalAi 4-in-1 ESC (M0134-6)";
case 42: return "ModalAi 4-in-1 ESC (M0138-1)";
case 44: return "ModalAi 4-in-1 ESC (M0129-6)";
default: return "Unknown Board";
}
}

View File

@ -117,8 +117,8 @@ private:
static constexpr uint16_t DISARMED_VALUE = 0;
static constexpr uint16_t VOXL_ESC_PWM_MIN = 0;
static constexpr uint16_t VOXL_ESC_PWM_MAX = 800;
static constexpr int VOXL_ESC_PWM_MIN = 1;
static constexpr int VOXL_ESC_PWM_MAX = 800;
static constexpr uint16_t VOXL_ESC_DEFAULT_RPM_MIN = 5000;
static constexpr uint16_t VOXL_ESC_DEFAULT_RPM_MAX = 17000;
@ -148,6 +148,9 @@ private:
static constexpr uint32_t VOXL_ESC_GPIO_CTL_AUX5 = 5;
static constexpr uint32_t VOXL_ESC_GPIO_CTL_AUX6 = 6;
static constexpr int32_t VOXL_ESC_RPM_CMDS = 0;
static constexpr int32_t VOXL_ESC_PWM_CMDS = 1;
Serial _uart_port{};
typedef struct {
@ -159,6 +162,7 @@ private:
float turtle_stick_minf{0.15f};
float turtle_cosphi{0.99f};
int32_t baud_rate{VOXL_ESC_DEFAULT_BAUD};
float pwr_min{0.05f};
int32_t rpm_min{VOXL_ESC_DEFAULT_RPM_MIN};
int32_t rpm_max{VOXL_ESC_DEFAULT_RPM_MAX};
int32_t function_map[VOXL_ESC_OUTPUT_CHANNELS] {0, 0, 0, 0};
@ -169,6 +173,7 @@ private:
int32_t esc_warn_temp_threshold{0};
int32_t esc_over_temp_threshold{0};
int32_t gpio_ctl_channel{0};
int32_t cmd_type{0};
} voxl_esc_params_t;
struct EscChan {
@ -222,6 +227,8 @@ private:
bool _need_version_info{true};
QC_ESC_EXTENDED_VERSION_INFO _version_info[VOXL_ESC_OUTPUT_CHANNELS];
int _min_active_pwm{1};
voxl_esc_params_t _parameters;
int update_params();
int load_params(voxl_esc_params_t *params, ch_assign_t *map);
@ -250,12 +257,13 @@ private:
int _fb_idx;
uint32_t _rx_crc_error_count{0};
uint32_t _rx_packet_count{0};
uint32_t _rx_power_status_count{0};
static const uint8_t READ_BUF_SIZE = 128;
uint8_t _read_buf[READ_BUF_SIZE];
Battery _battery;
static constexpr unsigned _battery_report_interval{100_ms};
static constexpr unsigned _battery_report_interval{20_ms};
hrt_abstime _last_battery_report_time;
hrt_abstime _last_uart_passthru{0};

View File

@ -276,3 +276,31 @@ PARAM_DEFINE_INT32(VOXL_ESC_T_OVER, 0);
* @max 6
*/
PARAM_DEFINE_INT32(VOXL_ESC_GPIO_CH, 0);
/**
* UART ESC command type
*
* Selects between RPM or PWM commands
*
* @reboot_required true
*
* @group VOXL ESC
* @value 0 - RPM
* @value 1 - PWM
* @min 0
* @max 1
*/
PARAM_DEFINE_INT32(VOXL_ESC_CMD, 0);
/**
* UART ESC Minimum motor power
*
* Minimum motor power for ESC when VOXL_ESC_CMD is set for PWM.
* Make sure to set this high enough so that the motors are always spinning
* while armed.
*
* @group VOXL ESC
* @min 0.0
* @max 1.0
*/
PARAM_DEFINE_FLOAT(VOXL_ESC_PWR_MIN, 0.05);

@ -1 +1 @@
Subproject commit 99427567b66a4ddd01384ed24097014a02acc70f
Subproject commit 5ed844c374646bfa2b41461c909a3b4df1a17233

View File

@ -786,6 +786,13 @@ GPS::run()
param_get(handle, &gps_ubx_min_elev);
}
int32_t gps_ubx_rate = 0;
handle = param_find("GPS_UBX_RATE");
if (handle != PARAM_INVALID) {
param_get(handle, &gps_ubx_rate);
}
handle = param_find("GPS_UBX_MODE");
GPSDriverUBX::UBXMode ubx_mode{GPSDriverUBX::UBXMode::Normal};
@ -851,6 +858,13 @@ GPS::run()
param_get(handle, &ppk_output);
}
handle = param_find("GPS_UBX_JAM_DET");
int32_t jam_det_sensitivity_hi = 1;
if (handle != PARAM_INVALID) {
param_get(handle, &jam_det_sensitivity_hi);
}
int32_t gnssSystemsParam = static_cast<int32_t>(GPSHelper::GNSSSystemsMask::RECEIVER_DEFAULTS);
if (_instance == Instance::Main) {
@ -938,9 +952,11 @@ GPS::run()
.dgnss_timeout = (uint8_t)gps_ubx_dgnss_to,
.min_cno = (uint8_t)gps_ubx_min_cno,
.min_elev = (int8_t)gps_ubx_min_elev,
.output_rate = (uint8_t)gps_ubx_rate,
.heading_offset = heading_offset,
.uart2_baudrate = f9p_uart2_baudrate,
.ppk_output = ppk_output > 0,
.jam_det_sensitivity_hi = jam_det_sensitivity_hi > 0,
.mode = ubx_mode,
};

View File

@ -114,6 +114,25 @@ PARAM_DEFINE_INT32(GPS_UBX_MIN_CNO, 0);
*/
PARAM_DEFINE_INT32(GPS_UBX_MIN_ELEV, 0);
/**
* u-blox GPS output rate
*
* Configure the output rate of u-blox GPS receivers (protocol v27+).
* When set to 0, automatic rate selection is used based on the receiver model.
* Default rates: M9N=8Hz, F9P L1L2=5Hz, F9P L1L5=5Hz, Others=10Hz.
*
* Note: Higher rates reduce satellite count (e.g., >8Hz limits to 16 SVs on M9N).
* Max rates vary by model and RTK mode: F9P L1L2=5-7Hz, F9P L1L5=7-8Hz, X20=25Hz.
* High rates at 115200 baud may cause dropouts.
*
* @min 0
* @max 25
* @unit Hz
* @reboot_required true
* @group GPS
*/
PARAM_DEFINE_INT32(GPS_UBX_RATE, 0);
/**
* Enable sat info (if available)
*
@ -198,6 +217,20 @@ PARAM_DEFINE_INT32(GPS_UBX_CFG_INTF, 0);
*/
PARAM_DEFINE_INT32(GPS_UBX_PPK, 0);
/**
* u-blox GPS jamming detection high sensitivity mode
*
* Enables or disables the high sensitivity mode for the u-blox jamming detection
* (CFG-SEC-JAMDET_SENSITIVITY_HI). When enabled, the receiver uses a
* more sensitive algorithm to detect jamming. Disabling this may reduce false
* positives in electrically noisy environments.
*
* @boolean
* @reboot_required true
* @group GPS
*/
PARAM_DEFINE_INT32(GPS_UBX_JAM_DET, 1);
/**
* Wipes the flash config of UBX modules.
*

View File

@ -254,11 +254,11 @@ VOXLPM::print_status()
switch (_pm_type) {
case VOXLPM_TYPE_V2_LTC:
printf("- V2 (LTC2964)\n");
PX4_INFO("- V2 (LTC2964)");
break;
case VOXLPM_TYPE_V3_INA:
printf("- V3 (INA231)\n");
PX4_INFO("- V3 (INA231)");
break;
default:
@ -267,27 +267,27 @@ VOXLPM::print_status()
switch (_ch_type) {
case VOXLPM_CH_TYPE_VBATT:
printf("- type: BATT\n");
PX4_INFO("- type: BATT");
break;
case VOXLPM_CH_TYPE_P5VDC:
printf("- type: P5VDC\n");
PX4_INFO("- type: P5VDC");
break;
case VOXLPM_CH_TYPE_P12VDC:
printf("- type: P12VDC\n");
PX4_INFO("- type: P12VDC");
break;
default:
printf("- type: UNKOWN\n");
PX4_INFO("- type: UNKOWN");
break;
}
printf(" - voltage: %9.4f VDC \n", (double)_voltage);
printf(" - current: %9.4f ADC \n", (double)_amperage);
printf(" - shunt: %9.4f mV, %9.4f mA\n", (double)_vshunt * 1000, (double)_vshuntamps * 1000);
printf(" - rsense: %9.6f ohm, cal: %i\n", (double)_rshunt, _cal);
printf(" - meas interval: %u us \n", _meas_interval_us);
PX4_INFO(" - voltage: %9.4f VDC ", (double)_voltage);
PX4_INFO(" - current: %9.4f ADC ", (double)_amperage);
PX4_INFO(" - shunt: %9.4f mV, %9.4f mA", (double)_vshunt * 1000, (double)_vshuntamps * 1000);
PX4_INFO(" - rsense: %9.6f ohm, cal: %i", (double)_rshunt, _cal);
PX4_INFO(" - meas interval: %u us ", _meas_interval_us);
}
void

View File

@ -246,7 +246,7 @@ private:
int measure_ina231();
bool _initialized;
static constexpr unsigned _meas_interval_us{100_ms};
static constexpr unsigned _meas_interval_us{20_ms};
perf_counter_t _sample_perf;
perf_counter_t _comms_errors;

@ -1 +1 @@
Subproject commit 6035657d000b4d7f414243d3a9b15f71ae634631
Subproject commit 993be80a62ec957c01fb41115b83663959a49f46

View File

@ -57,7 +57,6 @@ UavcanGnssBridge::UavcanGnssBridge(uavcan::INode &node, NodeInfoPublisher *node_
UavcanSensorBridgeBase("uavcan_gnss", ORB_ID(sensor_gps), node_info_publisher),
_node(node),
_sub_auxiliary(node),
_sub_quality(node),
_sub_fix(node),
_sub_fix2(node),
_sub_gnss_heading(node),
@ -91,13 +90,6 @@ UavcanGnssBridge::init()
return res;
}
res = _sub_quality.start(QualityCbBinder(this, &UavcanGnssBridge::gnss_quality_sub_cb));
if (res < 0) {
PX4_WARN("GNSS quality sub failed %i", res);
return res;
}
res = _sub_fix.start(FixCbBinder(this, &UavcanGnssBridge::gnss_fix_sub_cb));
if (res < 0) {
@ -160,13 +152,6 @@ UavcanGnssBridge::gnss_auxiliary_sub_cb(const uavcan::ReceivedDataStructure<uavc
_last_gnss_auxiliary_vdop = msg.vdop;
}
void
UavcanGnssBridge::gnss_quality_sub_cb(const uavcan::ReceivedDataStructure<uavcan::equipment::gnss::Quality> &msg)
{
_last_gnss_quality_timestamp = hrt_absolute_time();
_last_quality = msg;
}
void
UavcanGnssBridge::gnss_fix_sub_cb(const uavcan::ReceivedDataStructure<uavcan::equipment::gnss::Fix> &msg)
{
@ -572,21 +557,6 @@ void UavcanGnssBridge::process_fixx(const uavcan::ReceivedDataStructure<FixType>
sensor_gps.selected_rtcm_instance = _selected_rtcm_instance;
sensor_gps.rtcm_injection_rate = _rtcm_injection_rate;
// Apply cached Quality message fields (if received within last 2s)
if (hrt_elapsed_time(&_last_gnss_quality_timestamp) < 2_s) {
sensor_gps.noise_per_ms = _last_quality.noise;
sensor_gps.automatic_gain_control = _last_quality.agc;
sensor_gps.jamming_state = _last_quality.jamming_state;
sensor_gps.jamming_indicator = _last_quality.jamming_indicator;
sensor_gps.spoofing_state = _last_quality.spoofing_state;
sensor_gps.authentication_state = _last_quality.auth_state;
sensor_gps.diff_age = _last_quality.diff_age;
sensor_gps.antenna_status = _last_quality.antenna_status;
sensor_gps.antenna_power = _last_quality.antenna_power;
sensor_gps.fix_quality = _last_quality.fix_quality;
sensor_gps.system_error = _last_quality.system_errors;
}
publish(msg.getSrcNodeID().get(), &sensor_gps);
}

View File

@ -55,7 +55,6 @@
#include <uavcan/equipment/gnss/Auxiliary.hpp>
#include <uavcan/equipment/gnss/Fix.hpp>
#include <uavcan/equipment/gnss/Fix2.hpp>
#include <uavcan/equipment/gnss/Quality.hpp>
#include <ardupilot/gnss/MovingBaselineData.hpp>
#include <ardupilot/gnss/RelPosHeading.hpp>
#include <uavcan/equipment/gnss/RTCMStream.hpp>
@ -83,7 +82,6 @@ private:
* GNSS fix message will be reported via this callback.
*/
void gnss_auxiliary_sub_cb(const uavcan::ReceivedDataStructure<uavcan::equipment::gnss::Auxiliary> &msg);
void gnss_quality_sub_cb(const uavcan::ReceivedDataStructure<uavcan::equipment::gnss::Quality> &msg);
void gnss_fix_sub_cb(const uavcan::ReceivedDataStructure<uavcan::equipment::gnss::Fix> &msg);
void gnss_fix2_sub_cb(const uavcan::ReceivedDataStructure<uavcan::equipment::gnss::Fix2> &msg);
void gnss_relative_sub_cb(const uavcan::ReceivedDataStructure<ardupilot::gnss::RelPosHeading> &msg);
@ -108,10 +106,6 @@ private:
void (UavcanGnssBridge::*)(const uavcan::ReceivedDataStructure<uavcan::equipment::gnss::Auxiliary> &) >
AuxiliaryCbBinder;
typedef uavcan::MethodBinder < UavcanGnssBridge *,
void (UavcanGnssBridge::*)(const uavcan::ReceivedDataStructure<uavcan::equipment::gnss::Quality> &) >
QualityCbBinder;
typedef uavcan::MethodBinder < UavcanGnssBridge *,
void (UavcanGnssBridge::*)(const uavcan::ReceivedDataStructure<uavcan::equipment::gnss::Fix> &) >
FixCbBinder;
@ -135,7 +129,6 @@ private:
uavcan::INode &_node;
uavcan::Subscriber<uavcan::equipment::gnss::Auxiliary, AuxiliaryCbBinder> _sub_auxiliary;
uavcan::Subscriber<uavcan::equipment::gnss::Quality, QualityCbBinder> _sub_quality;
uavcan::Subscriber<uavcan::equipment::gnss::Fix, FixCbBinder> _sub_fix;
uavcan::Subscriber<uavcan::equipment::gnss::Fix2, Fix2CbBinder> _sub_fix2;
uavcan::Subscriber<ardupilot::gnss::RelPosHeading, RelPosHeadingCbBinder> _sub_gnss_heading;
@ -150,9 +143,6 @@ private:
float _last_gnss_auxiliary_hdop{0.0f};
float _last_gnss_auxiliary_vdop{0.0f};
uint64_t _last_gnss_quality_timestamp{0};
uavcan::equipment::gnss::Quality _last_quality{};
uORB::SubscriptionMultiArray<gps_inject_data_s, gps_inject_data_s::MAX_INSTANCES> _orb_inject_data_sub{ORB_ID::gps_inject_data};
hrt_abstime _last_rtcm_injection_time{0}; ///< time of last rtcm injection
uint8_t _selected_rtcm_instance{0}; ///< uorb instance that is being used for RTCM corrections

View File

@ -1,99 +0,0 @@
/****************************************************************************
*
* Copyright (c) 2024 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#pragma once
#include "UavcanPublisherBase.hpp"
#include <uavcan/equipment/gnss/Quality.hpp>
#include <uORB/SubscriptionCallback.hpp>
#include <uORB/topics/sensor_gps.h>
namespace uavcannode
{
class GnssQuality :
public UavcanPublisherBase,
public uORB::SubscriptionCallbackWorkItem,
private uavcan::Publisher<uavcan::equipment::gnss::Quality>
{
public:
GnssQuality(px4::WorkItem *work_item, uavcan::INode &node) :
UavcanPublisherBase(uavcan::equipment::gnss::Quality::DefaultDataTypeID),
uORB::SubscriptionCallbackWorkItem(work_item, ORB_ID(sensor_gps)),
uavcan::Publisher<uavcan::equipment::gnss::Quality>(node)
{
this->setPriority(uavcan::TransferPriority::Default);
}
void PrintInfo() override
{
if (uORB::SubscriptionCallbackWorkItem::advertised()) {
printf("\t%s -> %s:%d\n",
uORB::SubscriptionCallbackWorkItem::get_topic()->o_name,
uavcan::equipment::gnss::Quality::getDataTypeFullName(),
id());
}
}
void BroadcastAnyUpdates() override
{
using uavcan::equipment::gnss::Quality;
// sensor_gps -> uavcan::equipment::gnss::Quality
sensor_gps_s gps;
if (uORB::SubscriptionCallbackWorkItem::update(&gps)) {
uavcan::equipment::gnss::Quality quality{};
quality.noise = gps.noise_per_ms;
quality.agc = gps.automatic_gain_control;
quality.jamming_state = gps.jamming_state;
quality.jamming_indicator = gps.jamming_indicator;
quality.spoofing_state = gps.spoofing_state;
quality.auth_state = gps.authentication_state;
quality.diff_age = gps.diff_age;
quality.antenna_status = gps.antenna_status;
quality.antenna_power = gps.antenna_power;
quality.fix_quality = gps.fix_quality;
quality.system_errors = gps.system_error;
uavcan::Publisher<uavcan::equipment::gnss::Quality>::broadcast(quality);
// ensure callback is registered
uORB::SubscriptionCallbackWorkItem::registerCallback();
}
}
};
} // namespace uavcannode

View File

@ -59,7 +59,6 @@
#if defined(CONFIG_UAVCANNODE_GNSS_FIX)
#include "Publishers/GnssFix2.hpp"
#include "Publishers/GnssAuxiliary.hpp"
#include "Publishers/GnssQuality.hpp"
#endif // CONFIG_UAVCANNODE_GNSS_FIX
#if defined(CONFIG_UAVCANNODE_INDICATED_AIR_SPEED)
@ -386,7 +385,6 @@ int UavcanNode::init(uavcan::NodeID node_id, UAVCAN_DRIVER::BusEvent &bus_events
#if defined(CONFIG_UAVCANNODE_GNSS_FIX)
_publisher_list.add(new GnssFix2(this, _node));
_publisher_list.add(new GnssAuxiliary(this, _node));
_publisher_list.add(new GnssQuality(this, _node));
#endif // CONFIG_UAVCANNODE_GNSS_FIX
#if defined(CONFIG_UAVCANNODE_MAGNETIC_FIELD_STRENGTH)

View File

@ -58,7 +58,7 @@ Voxl2IO::~Voxl2IO()
int Voxl2IO::init()
{
PX4_INFO("VOXL2_IO: Driver starting");
PX4_INFO("Driver starting");
int ret = PX4_OK;
@ -66,18 +66,16 @@ int Voxl2IO::init()
ret = update_params();
if (ret != OK) {
PX4_ERR("VOXL2_IO: Failed to update params during init");
PX4_ERR("Failed to update params during init");
return ret;
}
// Print initial param values
print_params();
PX4_INFO("VOXL2_IO: ");
// Open serial port
if (!_uart_port.isOpen()) {
PX4_INFO("VOXL2_IO: Opening UART ESC device %s, baud rate %" PRIi32, _device, _parameters.baud_rate);
PX4_INFO("Opening UART ESC device %s, baud rate %" PRIi32, _device, _parameters.baud_rate);
// Configure UART port
if (! _uart_port.setPort(_device)) {
@ -101,11 +99,11 @@ int Voxl2IO::init()
ret = get_version_info();
if (ret != 0) {
PX4_ERR("VOXL2_IO: Could not detect the board");
PX4_ERR("VOXL2_IO: Driver initialization failed. Exiting");
PX4_ERR("Could not detect the board");
PX4_ERR("Driver initialization failed. Exiting");
if (_uart_port.open()) {
PX4_INFO("VOXL2_IO: Closing uart port");
PX4_INFO("Closing uart port");
_uart_port.close();
}
@ -115,7 +113,7 @@ int Voxl2IO::init()
//ScheduleOnInterval(_current_update_interval);
ScheduleNow();
PX4_INFO("VOXL2_IO: Driver initialization succeeded");
PX4_INFO("Driver initialization succeeded");
return ret;
}
@ -171,7 +169,7 @@ int Voxl2IO::load_params(voxl2_io_params_t *params)
// Validate PWM min and max values
if (params->pwm_min > params->pwm_max) {
PX4_ERR("VOXL2_IO: Invalid parameter VOXL2_IO_MIN. Please verify parameters.");
PX4_ERR("Invalid parameter VOXL2_IO_MIN. Please verify parameters.");
params->pwm_min = 0;
ret = PX4_ERROR;
}
@ -181,7 +179,7 @@ int Voxl2IO::load_params(voxl2_io_params_t *params)
int Voxl2IO::get_version_info()
{
PX4_INFO("VOXL2_IO: Detecting M0065 board...");
PX4_INFO("Detecting M0065 board...");
voxl2_io_packet_init(&_voxl2_io_packet);
Command cmd;
@ -195,7 +193,7 @@ int Voxl2IO::get_version_info()
//send the version request command to the board
if (_uart_port.write(cmd.buf, cmd.len) != cmd.len) {
PX4_ERR("VOXL2_IO: Could not write version request packet to UART port");
PX4_ERR("Could not write version request packet to UART port");
return -1;
}
@ -226,31 +224,31 @@ int Voxl2IO::get_version_info()
VOXL2_IO_EXTENDED_VERSION_INFO ver;
memcpy(&ver, _voxl2_io_packet.buffer, packet_size);
PX4_INFO("VOXL2_IO: \tVOXL2_IO ID: %i", ver.id);
PX4_INFO("VOXL2_IO: \tBoard Type : %i: %s", ver.hw_version, board_id_to_name(ver.hw_version).c_str());
PX4_INFO("\tVOXL2_IO ID: %i", ver.id);
PX4_INFO("\tBoard Type : %i: %s", ver.hw_version, board_id_to_name(ver.hw_version).c_str());
uint8_t *u = &ver.unique_id[0];
PX4_INFO("VOXL2_IO: \tUnique ID : 0x%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
PX4_INFO("\tUnique ID : 0x%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
u[11], u[10], u[9], u[8], u[7], u[6], u[5], u[4], u[3], u[2], u[1], u[0]);
PX4_INFO("VOXL2_IO: \tFirmware : version %4d, hash %.12s", ver.sw_version, ver.firmware_git_version);
PX4_INFO("VOXL2_IO: \tBootloader : version %4d, hash %.12s", ver.bootloader_version, ver.bootloader_git_version);
PX4_INFO("VOXL2_IO: \tReply time : %uus", (uint32_t)response_time);
PX4_INFO("\tFirmware : version %4d, hash %.12s", ver.sw_version, ver.firmware_git_version);
PX4_INFO("\tBootloader : version %4d, hash %.12s", ver.bootloader_version, ver.bootloader_git_version);
PX4_INFO("\tReply time : %uus", (uint32_t)response_time);
//we requested response from ID 0, so it should match
if (ver.id != 0) {
PX4_ERR("VOXL2_IO: Invalid id: %d", ver.id);
PX4_ERR("Invalid id: %d", ver.id);
}
//check HW (board version)
else if (ver.hw_version != VOXL2_IO_HW_VERSION) {
PX4_ERR("VOXL2_IO: Invalid HW version : %d (expected %d)", ver.hw_version, VOXL2_IO_HW_VERSION);
PX4_ERR("Invalid HW version : %d (expected %d)", ver.hw_version, VOXL2_IO_HW_VERSION);
return -1;
}
//check firmware version running on the board
else if (ver.sw_version != VOXL2_IO_SW_VERSION) {
PX4_ERR("VOXL2_IO: Invalid FW version : %d (expected %d)", ver.sw_version, VOXL2_IO_SW_VERSION);
PX4_ERR("Invalid FW version : %d (expected %d)", ver.sw_version, VOXL2_IO_SW_VERSION);
return -1;
} else {
@ -269,7 +267,7 @@ int Voxl2IO::get_version_info()
if (!got_response) {
PX4_ERR("VOXL2_IO: Board version info response timeout (%d retries left)", retries_left);
PX4_ERR("Board version info response timeout (%d retries left)", retries_left);
}
}
@ -309,14 +307,14 @@ bool Voxl2IO::updateOutputs(uint16_t outputs[input_rc_s::RC_INPUT_MAX_CHANNELS],
return 0;
}
//PX4_INFO("VOXL2_IO: Mixer output: %u, %u, %u, %u", outputs[0], outputs[1], outputs[2], outputs[3]);
//PX4_INFO("Mixer output: %u, %u, %u, %u", outputs[0], outputs[1], outputs[2], outputs[3]);
//in Run() we call _mixing_output.update(), which calls MixingOutput::limitAndUpdateOutputs which calls _interface.updateOutputs (this function)
//So, if Run() is blocked by a custom command, this function will not be called until Run is running again
uint32_t output_cmds[VOXL2_IO_OUTPUT_CHANNELS] = {0, 0, 0, 0, 0, 0, 0, 0};
if (num_outputs != VOXL2_IO_OUTPUT_CHANNELS) {
PX4_ERR("VOXL2_IO: Num outputs != VOXL2_IO_OUTPUT_CHANNELS!");
PX4_ERR("Num outputs != VOXL2_IO_OUTPUT_CHANNELS!");
return false;
}
@ -337,7 +335,7 @@ bool Voxl2IO::updateOutputs(uint16_t outputs[input_rc_s::RC_INPUT_MAX_CHANNELS],
cmd.len = voxl2_io_create_hires_pwm_packet(output_cmds, VOXL2_IO_OUTPUT_CHANNELS, cmd.buf, sizeof(cmd.buf));
if (_uart_port.write(cmd.buf, cmd.len) != cmd.len) {
PX4_ERR("VOXL2_IO: Failed to send packet");
PX4_ERR("Failed to send packet");
return false;
} else {
@ -347,7 +345,7 @@ bool Voxl2IO::updateOutputs(uint16_t outputs[input_rc_s::RC_INPUT_MAX_CHANNELS],
//if (_pwm_on && _debug){
if (_debug) {
PX4_INFO("VOXL2_IO: Mixer outputs: [%u, %u, %u, %u, %u, %u, %u, %u]",
PX4_INFO("Mixer outputs: [%u, %u, %u, %u, %u, %u, %u, %u]",
outputs[0], outputs[1], outputs[2], outputs[3],
outputs[4], outputs[5], outputs[6], outputs[7]);
}
@ -385,23 +383,23 @@ int Voxl2IO::parse_response(uint8_t *buf, uint8_t len)
} else { //parser error
switch (ret) {
case VOXL2_IO_ERROR_BAD_CHECKSUM:
if(_pwm_on && _debug) PX4_WARN("VOXL2_IO: BAD packet checksum");
if(_pwm_on && _debug) PX4_WARN("BAD packet checksum");
break;
case VOXL2_IO_ERROR_BAD_LENGTH:
if(_pwm_on && _debug) PX4_WARN("VOXL2_IO: BAD packet length");
if(_pwm_on && _debug) PX4_WARN("BAD packet length");
break;
case VOXL2_IO_ERROR_BAD_HEADER:
if(_pwm_on && _debug) PX4_WARN("VOXL2_IO: BAD packet header");
if(_pwm_on && _debug) PX4_WARN("BAD packet header");
break;
case VOXL2_IO_NO_PACKET:
// if(_pwm_on) PX4_WARN("VOXL2_IO: NO packet");
// if(_pwm_on) PX4_WARN("NO packet");
break;
default:
if(_pwm_on && _debug) PX4_WARN("VOXL2_IO: Unknown error: %i", ret);
if(_pwm_on && _debug) PX4_WARN("Unknown error: %i", ret);
break;
}
}
@ -482,8 +480,8 @@ int Voxl2IO::parse_sbus_packet(uint8_t *raw_data, uint32_t data_len)
if (rc_updated) {
//if (_pwm_on && _debug){
if (_debug) {
//PX4_INFO("VOXL2_IO: Decoded packet, header pos: %i", header);
PX4_INFO("VOXL2_IO: [%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u]",
//PX4_INFO("Decoded packet, header pos: %i", header);
PX4_INFO("[%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u]",
_raw_rc_values[0], _raw_rc_values[1], _raw_rc_values[2],
_raw_rc_values[3], _raw_rc_values[4], _raw_rc_values[5],
_raw_rc_values[6], _raw_rc_values[7], _raw_rc_values[8],
@ -493,7 +491,7 @@ int Voxl2IO::parse_sbus_packet(uint8_t *raw_data, uint32_t data_len)
);
if (sbus_frame_drop) {
PX4_WARN("VOXL2_IO: SBUS frame dropped");
PX4_WARN("SBUS frame dropped");
}
}
@ -508,7 +506,7 @@ int Voxl2IO::parse_sbus_packet(uint8_t *raw_data, uint32_t data_len)
_rc_pub.publish(input_rc);
if (_rc_mode == RC_MODE::SCAN) {
PX4_INFO("VOXL2_IO: Detected VOXL2 IO SBUS RC");
PX4_INFO("Detected VOXL2 IO SBUS RC");
_rc_mode = RC_MODE::SBUS;
}
}
@ -523,7 +521,7 @@ int Voxl2IO::receive_uart_packets()
if (nread > 0) {
if (_debug) {
PX4_INFO("VOXL2_IO: receive_uart_packets read %d bytes", nread);
PX4_INFO("receive_uart_packets read %d bytes", nread);
}
_bytes_received += nread;
@ -612,17 +610,17 @@ int Voxl2IO::task_spawn(int argc, char *argv[])
while ((ch = px4_getopt(argc - 1, argv, "vdep:", &myoptind, &myoptarg)) != EOF) {
switch (ch) {
case 'v':
PX4_INFO("VOXL2_IO: Verbose mode enabled");
PX4_INFO("Verbose mode enabled");
get_instance()->_debug = true;
break;
case 'd':
PX4_INFO("VOXL2_IO: M0065 PWM outputs disabled");
PX4_INFO("M0065 PWM outputs disabled");
get_instance()->_outputs_disabled = true;
break;
case 'e':
PX4_INFO("VOXL2_IO: M0065 using external RC");
PX4_INFO("M0065 using external RC");
get_instance()->_rc_mode = RC_MODE::EXTERNAL;
break;
@ -631,7 +629,7 @@ int Voxl2IO::task_spawn(int argc, char *argv[])
snprintf(get_instance()->_device, 2, "%s", myoptarg);
} else {
PX4_ERR("VOXL2_IO: Bad UART port number: %s (must be 2, 6, or 7).", myoptarg);
PX4_ERR("Bad UART port number: %s (must be 2, 6, or 7).", myoptarg);
_object.store(nullptr);
_task_id = -1;
return PX4_ERROR;
@ -640,7 +638,7 @@ int Voxl2IO::task_spawn(int argc, char *argv[])
break;
default:
print_usage("VOXL2_IO: Unknown command, parsing flags");
print_usage("Unknown command, parsing flags");
break;
}
}
@ -650,7 +648,7 @@ int Voxl2IO::task_spawn(int argc, char *argv[])
}
} else {
PX4_ERR("VOXL2_IO: alloc failed");
PX4_ERR("alloc failed");
}
_object.store(nullptr);
@ -668,13 +666,13 @@ int Voxl2IO::calibrate_escs()
Command cmd;
PX4_INFO("VOXL2_IO: PWM ESC calibration is starting!");
PX4_INFO("PWM ESC calibration is starting!");
// Give user 10 seconds to plug in PWM cable for ESCs
PX4_INFO("VOXL2_IO: MIN PWM used for ESC Calibration : %" PRId32, _parameters.pwm_cal_min);
PX4_INFO("VOXL2_IO: MAX PWM used for ESC Calibration : %" PRId32, _parameters.pwm_cal_max);
PX4_INFO("MIN PWM used for ESC Calibration : %" PRId32, _parameters.pwm_cal_min);
PX4_INFO("MAX PWM used for ESC Calibration : %" PRId32, _parameters.pwm_cal_max);
PX4_INFO("VOXL2_IO:");
PX4_INFO("VOXL2_IO: Connect your ESCs! (Calibration will start in ~10 seconds)");
PX4_INFO("Connect your ESCs! (Calibration will start in ~10 seconds)");
px4_usleep(10000000);
@ -690,7 +688,7 @@ int Voxl2IO::calibrate_escs()
}
if (_debug) {
PX4_INFO("VOXL2_IO: Scaled max pwms: %u %u %u %u %u %u %u %u",
PX4_INFO("Scaled max pwms: %u %u %u %u %u %u %u %u",
max_pwm_cmds[0], max_pwm_cmds[1], max_pwm_cmds[2], max_pwm_cmds[3],
max_pwm_cmds[4], max_pwm_cmds[5], max_pwm_cmds[6], max_pwm_cmds[7]);
}
@ -698,13 +696,13 @@ int Voxl2IO::calibrate_escs()
hrt_abstime start;
// Send PWM max every 2.5ms for 5 seconds
PX4_INFO("VOXL2_IO: Sending PWM MAX (%dus) for 5 seconds!", _parameters.pwm_cal_max);
PX4_INFO("Sending PWM MAX (%dus) for 5 seconds!", _parameters.pwm_cal_max);
cmd.len = voxl2_io_create_hires_pwm_packet(max_pwm_cmds, VOXL2_IO_OUTPUT_CHANNELS, cmd.buf, sizeof(cmd.buf));
start = hrt_absolute_time();
while (hrt_elapsed_time(&start) < 5000000) {
if (_uart_port.write(cmd.buf, cmd.len) != cmd.len) {
PX4_ERR("VOXL2_IO: ESC Calibration failed: Failed to send PWM MAX packet");
PX4_ERR("ESC Calibration failed: Failed to send PWM MAX packet");
_outputs_disabled = false;
return -1;
}
@ -713,10 +711,10 @@ int Voxl2IO::calibrate_escs()
}
// Send PWM min every 2.5ms for 5 seconds
PX4_INFO("VOXL2_IO: Sending PWM MIN (%dus) for 5 seconds!", _parameters.pwm_cal_min);
PX4_INFO("Sending PWM MIN (%dus) for 5 seconds!", _parameters.pwm_cal_min);
if (_debug) {
PX4_INFO("VOXL2_IO: Scaled min pwms: %u %u %u %u %u %u %u %u",
PX4_INFO("Scaled min pwms: %u %u %u %u %u %u %u %u",
min_pwm_cmds[0], min_pwm_cmds[1], min_pwm_cmds[2], min_pwm_cmds[3],
min_pwm_cmds[4], min_pwm_cmds[5], min_pwm_cmds[6], min_pwm_cmds[7]);
}
@ -728,7 +726,7 @@ int Voxl2IO::calibrate_escs()
while (hrt_elapsed_time(&start) < 5000000) {
if (_uart_port.write(cmd.buf, cmd.len) != cmd.len) {
PX4_ERR("VOXL2_IO: ESC Calibration failed: Failed to send PWM MIN packet");
PX4_ERR("ESC Calibration failed: Failed to send PWM MIN packet");
_outputs_disabled = false;
return -1;
}
@ -736,10 +734,10 @@ int Voxl2IO::calibrate_escs()
px4_usleep(2500);
}
PX4_INFO("VOXL2_IO: Waiting 5 seconds to finish the calibration (no PWM output)");
PX4_INFO("Waiting 5 seconds to finish the calibration (no PWM output)");
px4_usleep(5000000);
PX4_INFO("VOXL2_IO: ESC Calibration complete");
PX4_INFO("ESC Calibration complete");
_outputs_disabled = false;
return 0;
}
@ -752,7 +750,7 @@ int Voxl2IO::custom_command(int argc, char *argv[])
return print_usage("unknown command: missing args");
}
PX4_INFO("VOXL2_IO: Executing the following command: %s", verb);
PX4_INFO("Executing the following command: %s", verb);
/* start if not running */
if (!strcmp(verb, "start")) {
@ -760,12 +758,12 @@ int Voxl2IO::custom_command(int argc, char *argv[])
return Voxl2IO::task_spawn(argc, argv);
}
PX4_INFO("VOXL2_IO: Already running");
PX4_INFO("Already running");
return 0;
}
if (!is_running()) {
PX4_INFO("VOXL2_IO: Not running");
PX4_INFO("Not running");
return -1;
}
@ -776,7 +774,7 @@ int Voxl2IO::custom_command(int argc, char *argv[])
if (!strcmp(verb, "calibrate_escs")) {
if (get_instance()->_outputs_disabled) {
PX4_WARN("VOXL2_IO: Can't calibrate ESCs while outputs are disabled.");
PX4_WARN("Can't calibrate ESCs while outputs are disabled.");
return -1;
}
@ -792,19 +790,19 @@ int Voxl2IO::custom_command(int argc, char *argv[])
int Voxl2IO::print_status()
{
//PX4_INFO("VOXL2_IO: Max update rate: %u Hz", 1000000/_current_update_interval);
//PX4_INFO("VOXL2_IO: PWM Rate: 400 Hz"); // Only support 400 Hz for now
PX4_INFO("VOXL2_IO: Outputs on : %s", _pwm_on ? "yes" : "no");
PX4_INFO("VOXL2_IO: SW version : %u", _version_info.sw_version);
PX4_INFO("VOXL2_IO: HW version : %u: %s", _version_info.hw_version,
//PX4_INFO("Max update rate: %u Hz", 1000000/_current_update_interval);
//PX4_INFO("PWM Rate: 400 Hz"); // Only support 400 Hz for now
PX4_INFO("Outputs on : %s", _pwm_on ? "yes" : "no");
PX4_INFO("SW version : %u", _version_info.sw_version);
PX4_INFO("HW version : %u: %s", _version_info.hw_version,
board_id_to_name(_version_info.hw_version).c_str());
PX4_INFO("VOXL2_IO: RC Type : SBUS"); // Only support SBUS through M0065 for now
PX4_INFO("VOXL2_IO: RC Connected : %s", hrt_absolute_time() - _rc_last_valid_time > 500000 ? "no" : "yes");
PX4_INFO("VOXL2_IO: RC Packets Rxd : %" PRIu16, _sbus_total_frames);
PX4_INFO("VOXL2_IO: UART port : %s", _device);
PX4_INFO("VOXL2_IO: UART open : %s", _uart_port.open() ? "yes" : "no");
PX4_INFO("VOXL2_IO: Packets sent : %" PRIu32, _packets_sent);
PX4_INFO("VOXL2_IO: ");
PX4_INFO("RC Type : SBUS"); // Only support SBUS through M0065 for now
PX4_INFO("RC Connected : %s", hrt_absolute_time() - _rc_last_valid_time > 500000 ? "no" : "yes");
PX4_INFO("RC Packets Rxd : %" PRIu16, _sbus_total_frames);
PX4_INFO("UART port : %s", _device);
PX4_INFO("UART open : %s", _uart_port.open() ? "yes" : "no");
PX4_INFO("Packets sent : %" PRIu32, _packets_sent);
PX4_INFO("");
print_params();
perf_print_counter(_cycle_perf);
@ -863,20 +861,20 @@ std::string Voxl2IO::board_id_to_name(int board_id)
void Voxl2IO::print_params()
{
PX4_INFO("VOXL2_IO: Params: VOXL2_IO_BAUD : %" PRId32, _parameters.baud_rate);
PX4_INFO("VOXL2_IO: Params: VOXL2_IO_FUNC1 : %" PRId32, _parameters.function_map[0]);
PX4_INFO("VOXL2_IO: Params: VOXL2_IO_FUNC2 : %" PRId32, _parameters.function_map[1]);
PX4_INFO("VOXL2_IO: Params: VOXL2_IO_FUNC3 : %" PRId32, _parameters.function_map[2]);
PX4_INFO("VOXL2_IO: Params: VOXL2_IO_FUNC4 : %" PRId32, _parameters.function_map[3]);
PX4_INFO("VOXL2_IO: Params: VOXL2_IO_FUNC5 : %" PRId32, _parameters.function_map[4]);
PX4_INFO("VOXL2_IO: Params: VOXL2_IO_FUNC6 : %" PRId32, _parameters.function_map[5]);
PX4_INFO("VOXL2_IO: Params: VOXL2_IO_FUNC7 : %" PRId32, _parameters.function_map[6]);
PX4_INFO("VOXL2_IO: Params: VOXL2_IO_FUNC8 : %" PRId32, _parameters.function_map[7]);
PX4_INFO("VOXL2_IO: Params: VOXL2_IO_DIS : %" PRId32, _parameters.pwm_dis);
PX4_INFO("VOXL2_IO: Params: VOXL2_IO_MIN : %" PRId32, _parameters.pwm_min);
PX4_INFO("VOXL2_IO: Params: VOXL2_IO_MAX : %" PRId32, _parameters.pwm_max);
PX4_INFO("VOXL2_IO: Params: VOXL2_IO_CMIN : %" PRId32, _parameters.pwm_cal_min);
PX4_INFO("VOXL2_IO: Params: VOXL2_IO_CMAX : %" PRId32, _parameters.pwm_cal_max);
PX4_INFO("Params: VOXL2_IO_BAUD : %" PRId32, _parameters.baud_rate);
PX4_INFO("Params: VOXL2_IO_FUNC1 : %" PRId32, _parameters.function_map[0]);
PX4_INFO("Params: VOXL2_IO_FUNC2 : %" PRId32, _parameters.function_map[1]);
PX4_INFO("Params: VOXL2_IO_FUNC3 : %" PRId32, _parameters.function_map[2]);
PX4_INFO("Params: VOXL2_IO_FUNC4 : %" PRId32, _parameters.function_map[3]);
PX4_INFO("Params: VOXL2_IO_FUNC5 : %" PRId32, _parameters.function_map[4]);
PX4_INFO("Params: VOXL2_IO_FUNC6 : %" PRId32, _parameters.function_map[5]);
PX4_INFO("Params: VOXL2_IO_FUNC7 : %" PRId32, _parameters.function_map[6]);
PX4_INFO("Params: VOXL2_IO_FUNC8 : %" PRId32, _parameters.function_map[7]);
PX4_INFO("Params: VOXL2_IO_DIS : %" PRId32, _parameters.pwm_dis);
PX4_INFO("Params: VOXL2_IO_MIN : %" PRId32, _parameters.pwm_min);
PX4_INFO("Params: VOXL2_IO_MAX : %" PRId32, _parameters.pwm_max);
PX4_INFO("Params: VOXL2_IO_CMIN : %" PRId32, _parameters.pwm_cal_min);
PX4_INFO("Params: VOXL2_IO_CMAX : %" PRId32, _parameters.pwm_cal_max);
}
extern "C" __EXPORT int voxl2_io_main(int argc, char *argv[]);

View File

@ -330,6 +330,10 @@ uint16_t Battery::determineFaults()
faults |= (1 << battery_status_s::FAULT_SPIKES);
}
if (PX4_ISFINITE(_temperature_c) && _temperature_c > BAT_TEMP_MAX) {
faults |= (1 << battery_status_s::FAULT_OVER_TEMPERATURE);
}
return faults;
}

View File

@ -217,4 +217,10 @@ private:
static constexpr float OCV_DEFAULT = 4.2f; // [V] Initial per cell estimate of the open circuit voltage
static constexpr float R_COVARIANCE = 0.1f; // Initial per cell covariance of the internal resistance
static constexpr float OCV_COVARIANCE = 1.5f; // Initial per cell covariance of the open circuit voltage
// Temperature [degC] above which an overtemperature fault is declared,
// leading to a failsafe warning recommending immediate landing. Note
// that depending on the setup this may be measured in/close to the
// battery (smart battery) or from a separate power monitor module.
static constexpr float BAT_TEMP_MAX = 100.0f;
};

View File

@ -82,7 +82,7 @@ void EscChecks::checkAndReport(const Context &context, Report &reporter)
checkEscStatus(context, reporter, esc_status);
reporter.setIsPresent(health_component_t::motors_escs);
} else if (_param_escs_checks_required.get()
} else if (_param_com_arm_chk_escs.get()
&& now - _start_time > 5_s) { // Wait a bit after startup to allow esc's to init
/* EVENT
@ -102,40 +102,37 @@ void EscChecks::checkAndReport(const Context &context, Report &reporter)
void EscChecks::checkEscStatus(const Context &context, Report &reporter, const esc_status_s &esc_status)
{
const NavModes required_modes = _param_escs_checks_required.get() ? NavModes::All : NavModes::None;
const NavModes required_modes = _param_com_arm_chk_escs.get() ? NavModes::All : NavModes::None;
if (esc_status.esc_count > 0) {
// Check if one or more the ESCs are offline
char esc_fail_msg[50];
esc_fail_msg[0] = '\0';
int online_bitmask = (1 << esc_status.esc_count) - 1;
for (int i = 0; i < esc_status_s::CONNECTED_ESC_MAX; ++i) {
const bool mapped = math::isInRange(esc_status.esc[i].actuator_function, actuator_motors_s::ACTUATOR_FUNCTION_MOTOR1,
uint8_t(actuator_motors_s::ACTUATOR_FUNCTION_MOTOR1 + actuator_motors_s::NUM_CONTROLS - 1));
const bool offline = (esc_status.esc_online_flags & (1 << i)) == 0;
// Check if one or more the ESCs are offline
if (online_bitmask != esc_status.esc_online_flags) {
for (int index = 0; index < esc_status.esc_count; index++) {
if ((esc_status.esc_online_flags & (1 << index)) == 0) {
uint8_t motor_index = esc_status.esc[index].actuator_function - actuator_motors_s::ACTUATOR_FUNCTION_MOTOR1 + 1;
/* EVENT
* @description
* <profile name="dev">
* This check can be configured via <param>COM_ARM_CHK_ESCS</param> parameter.
* </profile>
*/
reporter.healthFailure<uint8_t>(required_modes, health_component_t::motors_escs, events::ID("check_escs_offline"),
events::Log::Critical, "ESC {1} offline", motor_index);
snprintf(esc_fail_msg + strlen(esc_fail_msg), sizeof(esc_fail_msg) - strlen(esc_fail_msg), "ESC%d ", motor_index);
esc_fail_msg[sizeof(esc_fail_msg) - 1] = '\0';
}
}
if (reporter.mavlink_log_pub()) {
mavlink_log_critical(reporter.mavlink_log_pub(), "%soffline. %s\t", esc_fail_msg, context.isArmed() ? "Land now!" : "");
if (mapped && offline) {
/* EVENT
* @description
* <profile name="dev">
* This check can be configured via <param>COM_ARM_CHK_ESCS</param> parameter.
* </profile>
*/
reporter.healthFailure<uint8_t>(required_modes, health_component_t::motors_escs, events::ID("check_escs_offline"),
events::Log::Critical, "ESC {1} offline", i + 1);
snprintf(esc_fail_msg + strlen(esc_fail_msg), sizeof(esc_fail_msg) - strlen(esc_fail_msg), "ESC%d ", i + 1);
esc_fail_msg[sizeof(esc_fail_msg) - 1] = '\0';
}
}
for (int index = 0; index < esc_status.esc_count; index++) {
if ((esc_fail_msg[0] != '\0') && reporter.mavlink_log_pub()) {
mavlink_log_critical(reporter.mavlink_log_pub(), "%soffline. %s\t", esc_fail_msg, context.isArmed() ? "Land now!" : "");
}
for (int index = 0; index < math::min(esc_status.esc_count, esc_status_s::CONNECTED_ESC_MAX); ++index) {
if (esc_status.esc[index].failures != 0) {

View File

@ -54,6 +54,6 @@ private:
const hrt_abstime _start_time{hrt_absolute_time()};
DEFINE_PARAMETERS_CUSTOM_PARENT(HealthAndArmingCheckBase,
(ParamBool<px4::params::COM_ARM_CHK_ESCS>) _param_escs_checks_required
(ParamBool<px4::params::COM_ARM_CHK_ESCS>) _param_com_arm_chk_escs
)
};

View File

@ -101,7 +101,7 @@ void FailureDetector::publishStatus()
failure_detector_status.fd_imbalanced_prop = _failure_detector_status.flags.imbalanced_prop;
failure_detector_status.fd_motor = _failure_detector_status.flags.motor;
failure_detector_status.imbalanced_prop_metric = _imbalanced_prop_lpf.getState();
failure_detector_status.motor_failure_mask = _motor_failure_esc_timed_out_mask | _motor_failure_esc_under_current_mask;
failure_detector_status.motor_failure_mask = _motor_failure_mask;
failure_detector_status.motor_stop_mask = _failure_injector.getMotorStopMask();
failure_detector_status.timestamp = hrt_absolute_time();
_failure_detector_status_pub.publish(failure_detector_status);
@ -141,13 +141,13 @@ void FailureDetector::updateAttitudeStatus(const vehicle_status_s &vehicle_statu
const bool roll_status = (max_roll > FLT_EPSILON) && (fabsf(roll) > max_roll);
const bool pitch_status = (max_pitch > FLT_EPSILON) && (fabsf(pitch) > max_pitch);
hrt_abstime time_now = hrt_absolute_time();
hrt_abstime now = hrt_absolute_time();
// Update hysteresis
_roll_failure_hysteresis.set_hysteresis_time_from(false, (hrt_abstime)(1_s * _param_fd_fail_r_ttri.get()));
_pitch_failure_hysteresis.set_hysteresis_time_from(false, (hrt_abstime)(1_s * _param_fd_fail_p_ttri.get()));
_roll_failure_hysteresis.set_state_and_update(roll_status, time_now);
_pitch_failure_hysteresis.set_state_and_update(pitch_status, time_now);
_roll_failure_hysteresis.set_state_and_update(roll_status, now);
_pitch_failure_hysteresis.set_state_and_update(pitch_status, now);
// Update status
_failure_detector_status.flags.roll = _roll_failure_hysteresis.get_state();
@ -164,11 +164,9 @@ void FailureDetector::updateExternalAtsStatus()
uint32_t pulse_width = pwm_input.pulse_width;
bool ats_trigger_status = (pulse_width >= (uint32_t)_param_fd_ext_ats_trig.get()) && (pulse_width < 3_ms);
hrt_abstime time_now = hrt_absolute_time();
// Update hysteresis
_ext_ats_failure_hysteresis.set_hysteresis_time_from(false, 100_ms); // 5 consecutive pulses at 50hz
_ext_ats_failure_hysteresis.set_state_and_update(ats_trigger_status, time_now);
_ext_ats_failure_hysteresis.set_state_and_update(ats_trigger_status, hrt_absolute_time());
_failure_detector_status.flags.ext = _ext_ats_failure_hysteresis.get_state();
}
@ -176,7 +174,7 @@ void FailureDetector::updateExternalAtsStatus()
void FailureDetector::updateEscsStatus(const vehicle_status_s &vehicle_status, const esc_status_s &esc_status)
{
hrt_abstime time_now = hrt_absolute_time();
hrt_abstime now = hrt_absolute_time();
if (vehicle_status.arming_state == vehicle_status_s::ARMING_STATE_ARMED) {
const int limited_esc_count = math::min(esc_status.esc_count, esc_status_s::CONNECTED_ESC_MAX);
@ -190,7 +188,7 @@ void FailureDetector::updateEscsStatus(const vehicle_status_s &vehicle_status, c
}
_esc_failure_hysteresis.set_hysteresis_time_from(false, 300_ms);
_esc_failure_hysteresis.set_state_and_update(is_esc_failure, time_now);
_esc_failure_hysteresis.set_state_and_update(is_esc_failure, now);
if (_esc_failure_hysteresis.get_state()) {
_failure_detector_status.flags.arm_escs = true;
@ -198,7 +196,7 @@ void FailureDetector::updateEscsStatus(const vehicle_status_s &vehicle_status, c
} else {
// reset ESC bitfield
_esc_failure_hysteresis.set_state_and_update(false, time_now);
_esc_failure_hysteresis.set_state_and_update(false, now);
_failure_detector_status.flags.arm_escs = false;
}
}
@ -263,110 +261,79 @@ void FailureDetector::updateImbalancedPropStatus()
void FailureDetector::updateMotorStatus(const vehicle_status_s &vehicle_status, const esc_status_s &esc_status)
{
// What need to be checked:
//
// 1. ESC telemetry disappears completely -> dead ESC or power loss on that ESC
// 2. ESC failures like overvoltage, overcurrent etc. But DShot driver for example is not populating the field 'esc_report.failures'
// 3. Motor current too low. Compare drawn motor current to expected value from a parameter
// -- ESC voltage does not really make sense and is highly dependent on the setup
// 1. Telemetry times out -> communication or power lost on that ESC
// 2. Too low current draw compared to commanded thrust
// Overvoltage, overcurrent do not have checks yet esc_report.failures are handled separately
// First wait for some ESC telemetry that has the required fields. Before that happens, don't check this ESC
// Then check
const hrt_abstime now = hrt_absolute_time();
// Only check while armed
if (vehicle_status.arming_state == vehicle_status_s::ARMING_STATE_ARMED) {
const hrt_abstime now = hrt_absolute_time();
const int limited_esc_count = math::min(esc_status.esc_count, esc_status_s::CONNECTED_ESC_MAX);
actuator_motors_s actuator_motors{};
_actuator_motors_sub.copy(&actuator_motors);
// Check individual ESC reports
for (int esc_status_idx = 0; esc_status_idx < limited_esc_count; esc_status_idx++) {
const esc_report_s &cur_esc_report = esc_status.esc[esc_status_idx];
for (uint8_t i = 0; i < esc_status_s::CONNECTED_ESC_MAX; ++i) {
// Map the esc status index to the actuator function index
const unsigned i_esc = cur_esc_report.actuator_function - actuator_motors_s::ACTUATOR_FUNCTION_MOTOR1;
const uint8_t actuator_function_index =
esc_status.esc[i].actuator_function - actuator_motors_s::ACTUATOR_FUNCTION_MOTOR1;
if (i_esc >= actuator_motors_s::NUM_CONTROLS) {
if (actuator_function_index >= actuator_motors_s::NUM_CONTROLS) {
continue; // Invalid mapping
}
const bool timeout = now > esc_status.esc[i].timestamp + 300_ms;
const float current = esc_status.esc[i].esc_current;
// First wait for ESC telemetry reporting non-zero current. Before that happens, don't check it.
if (current > FLT_EPSILON) {
_esc_has_reported_current[i] = true;
}
if (!_esc_has_reported_current[i]) {
continue;
}
// Check if ESC telemetry was available and valid at some point. This is a prerequisite for the failure detection.
if (!(_motor_failure_esc_valid_current_mask & (1 << i_esc)) && cur_esc_report.esc_current > 0.0f) {
_motor_failure_esc_valid_current_mask |= (1 << i_esc);
_motor_failure_mask &= ~(1u << actuator_function_index); // Reset bit in mask to accumulate failures again
_motor_failure_mask |= (static_cast<uint16_t>(timeout) << actuator_function_index); // Telemetry timeout
// Current limits
float thrust = 0.f;
if (PX4_ISFINITE(actuator_motors.control[actuator_function_index])) {
// Normalized motor thrust commands before thrust model factor is applied, NAN means motor is turned off -> 0 thrust
thrust = fabsf(actuator_motors.control[actuator_function_index]);
}
// Check for telemetry timeout
const bool esc_timed_out = now > cur_esc_report.timestamp + 300_ms;
const bool esc_was_valid = _motor_failure_esc_valid_current_mask & (1 << i_esc);
const bool esc_timeout_currently_flagged = _motor_failure_esc_timed_out_mask & (1 << i_esc);
bool thrust_above_threshold = thrust > _param_fd_act_mot_thr.get();
bool current_too_low = current < (thrust * _param_fd_act_mot_c2t.get()) - _param_fd_act_low_off.get();
bool current_too_high = current > (thrust * _param_fd_act_mot_c2t.get()) + _param_fd_act_high_off.get();
if (esc_was_valid && esc_timed_out && !esc_timeout_currently_flagged) {
// Set flag
_motor_failure_esc_timed_out_mask |= (1 << i_esc);
_esc_undercurrent_hysteresis[i].set_hysteresis_time_from(false, _param_fd_act_mot_tout.get() * 1_ms);
_esc_overcurrent_hysteresis[i].set_hysteresis_time_from(false, _param_fd_act_mot_tout.get() * 1_ms);
} else if (!esc_timed_out && esc_timeout_currently_flagged) {
// Reset flag
_motor_failure_esc_timed_out_mask &= ~(1 << i_esc);
if (!_esc_undercurrent_hysteresis[i].get_state()) {
// Do not clear mid operation because a reaction could be to stop the motor and that would be conidered healthy again
_esc_undercurrent_hysteresis[i].set_state_and_update(thrust_above_threshold && current_too_low && !timeout, now);
}
// Check if ESC current is too low
if (cur_esc_report.esc_current > FLT_EPSILON) {
_motor_failure_esc_has_current[i_esc] = true;
if (!_esc_overcurrent_hysteresis[i].get_state()) {
// Do not clear mid operation because a reaction could be to stop the motor and that would be conidered healthy again
_esc_overcurrent_hysteresis[i].set_state_and_update(current_too_high && !timeout, now);
}
if (_motor_failure_esc_has_current[i_esc]) {
float esc_throttle = 0.f;
if (PX4_ISFINITE(actuator_motors.control[i_esc])) {
esc_throttle = fabsf(actuator_motors.control[i_esc]);
}
const bool throttle_above_threshold = esc_throttle > _param_fd_act_mot_thr.get();
const bool current_too_low = cur_esc_report.esc_current < esc_throttle *
_param_fd_act_mot_c2t.get();
if (throttle_above_threshold && current_too_low && !esc_timed_out) {
if (_motor_failure_undercurrent_start_time[i_esc] == 0) {
_motor_failure_undercurrent_start_time[i_esc] = now;
}
} else {
if (_motor_failure_undercurrent_start_time[i_esc] != 0) {
_motor_failure_undercurrent_start_time[i_esc] = 0;
}
}
if (_motor_failure_undercurrent_start_time[i_esc] != 0
&& now > (_motor_failure_undercurrent_start_time[i_esc] + (_param_fd_act_mot_tout.get() * 1_ms))
&& (_motor_failure_esc_under_current_mask & (1 << i_esc)) == 0) {
// Set flag
_motor_failure_esc_under_current_mask |= (1 << i_esc);
} // else: this flag is never cleared, as the motor is stopped, so throttle < threshold
}
_motor_failure_mask |= (static_cast<uint16_t>(_esc_undercurrent_hysteresis[i].get_state()) << actuator_function_index);
_motor_failure_mask |= (static_cast<uint16_t>(_esc_overcurrent_hysteresis[i].get_state()) << actuator_function_index);
}
bool critical_esc_failure = (_motor_failure_esc_timed_out_mask != 0 || _motor_failure_esc_under_current_mask != 0);
if (critical_esc_failure && !(_failure_detector_status.flags.motor)) {
// Add motor failure flag to bitfield
_failure_detector_status.flags.motor = true;
} else if (!critical_esc_failure && _failure_detector_status.flags.motor) {
// Reset motor failure flag
_failure_detector_status.flags.motor = false;
}
_failure_detector_status.flags.motor = (_motor_failure_mask != 0u);
} else { // Disarmed
// reset ESC bitfield
for (int i_esc = 0; i_esc < actuator_motors_s::NUM_CONTROLS; i_esc++) {
_motor_failure_undercurrent_start_time[i_esc] = 0;
for (uint8_t i = 0; i < esc_status_s::CONNECTED_ESC_MAX; ++i) {
_esc_undercurrent_hysteresis[i].set_state_and_update(false, now);
_esc_overcurrent_hysteresis[i].set_state_and_update(false, now);
}
_motor_failure_esc_under_current_mask = 0;
_failure_detector_status.flags.motor = false;
}
}

View File

@ -111,11 +111,10 @@ private:
hrt_abstime _imu_status_timestamp_prev{0};
// Motor failure check
uint8_t _motor_failure_esc_valid_current_mask{}; // ESC 1-8, true if ESC telemetry was valid at some point
uint8_t _motor_failure_esc_timed_out_mask{}; // ESC telemetry no longer available -> failure
uint8_t _motor_failure_esc_under_current_mask{}; // ESC drawing too little current -> failure
bool _motor_failure_esc_has_current[actuator_motors_s::NUM_CONTROLS] {false}; // true if some ESC had non-zero current (some don't support it)
hrt_abstime _motor_failure_undercurrent_start_time[actuator_motors_s::NUM_CONTROLS] {};
bool _esc_has_reported_current[esc_status_s::CONNECTED_ESC_MAX] {}; // true if ESC reported non-zero current before (some never report any)
systemlib::Hysteresis _esc_undercurrent_hysteresis[esc_status_s::CONNECTED_ESC_MAX];
systemlib::Hysteresis _esc_overcurrent_hysteresis[esc_status_s::CONNECTED_ESC_MAX];
uint16_t _motor_failure_mask = 0; // actuator function indexed
uORB::Subscription _vehicle_attitude_sub{ORB_ID(vehicle_attitude)};
uORB::Subscription _esc_status_sub{ORB_ID(esc_status)}; // TODO: multi-instance
@ -142,6 +141,8 @@ private:
(ParamBool<px4::params::FD_ACT_EN>) _param_fd_act_en,
(ParamFloat<px4::params::FD_ACT_MOT_THR>) _param_fd_act_mot_thr,
(ParamFloat<px4::params::FD_ACT_MOT_C2T>) _param_fd_act_mot_c2t,
(ParamInt<px4::params::FD_ACT_MOT_TOUT>) _param_fd_act_mot_tout
(ParamInt<px4::params::FD_ACT_MOT_TOUT>) _param_fd_act_mot_tout,
(ParamFloat<px4::params::FD_ACT_LOW_OFF>) _param_fd_act_low_off,
(ParamFloat<px4::params::FD_ACT_HIGH_OFF>) _param_fd_act_high_off
)
};

View File

@ -169,12 +169,13 @@ PARAM_DEFINE_INT32(FD_IMB_PROP_THR, 30);
*
* @group Failure Detector
*/
PARAM_DEFINE_INT32(FD_ACT_EN, 1);
PARAM_DEFINE_INT32(FD_ACT_EN, 0);
/**
* Motor Failure Throttle Threshold
* Motor Failure Thrust Threshold
*
* Motor failure triggers only above this throttle value.
* Failure detection per motor only triggers above this thrust value.
* Set to 1 to disable the detection.
*
* @group Failure Detector
* @unit norm
@ -186,9 +187,11 @@ PARAM_DEFINE_INT32(FD_ACT_EN, 1);
PARAM_DEFINE_FLOAT(FD_ACT_MOT_THR, 0.2f);
/**
* Motor Failure Current/Throttle Threshold
* Motor Failure Current/Throttle Scale
*
* Motor failure triggers only below this current value
* Determines the slope between expected steady state current and linearized, normalized thrust command.
* E.g. FD_ACT_MOT_C2T A represents the expected steady state current at 100%.
* FD_ACT_LOW_OFF and FD_ACT_HIGH_OFF offset the threshold from that slope.
*
* @group Failure Detector
* @min 0.0
@ -197,13 +200,12 @@ PARAM_DEFINE_FLOAT(FD_ACT_MOT_THR, 0.2f);
* @decimal 2
* @increment 1
*/
PARAM_DEFINE_FLOAT(FD_ACT_MOT_C2T, 2.0f);
PARAM_DEFINE_FLOAT(FD_ACT_MOT_C2T, 35.f);
/**
* Motor Failure Time Threshold
* Motor Failure Hysteresis Time
*
* Motor failure triggers only if the throttle threshold and the
* current to throttle threshold are violated for this time.
* Motor failure only triggers after current thresholds are exceeded for this time.
*
* @group Failure Detector
* @unit ms
@ -211,4 +213,32 @@ PARAM_DEFINE_FLOAT(FD_ACT_MOT_C2T, 2.0f);
* @max 10000
* @increment 100
*/
PARAM_DEFINE_INT32(FD_ACT_MOT_TOUT, 100);
PARAM_DEFINE_INT32(FD_ACT_MOT_TOUT, 1000);
/**
* Undercurrent motor failure limit offset
*
* threshold = FD_ACT_MOT_C2T * thrust - FD_ACT_LOW_OFF
*
* @group Failure Detector
* @min 0
* @max 30
* @unit A
* @decimal 2
* @increment 1
*/
PARAM_DEFINE_FLOAT(FD_ACT_LOW_OFF, 10.f);
/**
* Overcurrent motor failure limit offset
*
* threshold = FD_ACT_MOT_C2T * thrust + FD_ACT_HIGH_OFF
*
* @group Failure Detector
* @min 0
* @max 30
* @unit A
* @decimal 2
* @increment 1
*/
PARAM_DEFINE_FLOAT(FD_ACT_HIGH_OFF, 10.f);

View File

@ -63,7 +63,11 @@ __BEGIN_DECLS
__EXPORT int dataman_main(int argc, char *argv[]);
__END_DECLS
#ifdef CONFIG_FS_LITTLEFS
static constexpr int TASK_STACK_SIZE = 2000; /* littlefs needs more stack */
#else
static constexpr int TASK_STACK_SIZE = 1420;
#endif
#ifdef CONFIG_DATAMAN_PERSISTENT_STORAGE
/* Private File based Operations */

View File

@ -49,6 +49,11 @@ bool GnssChecks::run(const gnssSample &gnss, uint64_t time_us)
bool passed = false;
// Run strict checks while not flying yet
if (!_control_status.flags.in_air) {
_initial_checks_passed = false;
}
if (_initial_checks_passed) {
if (runSimplifiedChecks(gnss)) {
_time_last_pass_us = time_us;

View File

@ -190,9 +190,6 @@ public:
// return true if the attitude is usable
bool attitude_valid() const { return _control_status.flags.tilt_align; }
// get vehicle landed status data
bool get_in_air_status() const { return _control_status.flags.in_air; }
#if defined(CONFIG_EKF2_WIND)
bool get_wind_status() const { return _control_status.flags.wind || _external_wind_init; }
#endif // CONFIG_EKF2_WIND

View File

@ -281,7 +281,8 @@ TEST_F(EkfGpsHeadingTest, yawJmpOnGround)
EXPECT_EQ(_ekf_wrapper.getQuaternionResetCounter(), initial_quat_reset_counter + 1);
// AND THEN: restart GNSS yaw fusion
_sensor_simulator.runSeconds(5);
// The strict checks on ground require min_health_time_us (10s) to pass again.
_sensor_simulator.runSeconds(11);
EXPECT_TRUE(_ekf_wrapper.isIntendingGpsHeadingFusion());
EXPECT_EQ(_ekf_wrapper.getQuaternionResetCounter(), initial_quat_reset_counter + 2);
EXPECT_LT(fabsf(matrix::wrap_pi(_ekf_wrapper.getYawAngle() - gps_heading)), math::radians(1.f));

View File

@ -81,6 +81,10 @@ TEST_F(EkfGpsTest, gpsTimeout)
// GIVEN:EKF that fuses GPS
EXPECT_TRUE(_ekf_wrapper.isIntendingGpsFusion());
// In air the simplified checks are used which do not include satellite count
_ekf->set_in_air_status(true);
_ekf->set_vehicle_at_rest(false);
// WHEN: the number of satellites drops below the minimum
_sensor_simulator._gps.setNumberOfSatellites(3);
@ -174,7 +178,7 @@ TEST_F(EkfGpsTest, resetToGpsPosition)
const Vector3f simulated_position_change(20.0f, -1.0f, 0.f);
_sensor_simulator._gps.stepHorizontalPositionByMeters(
Vector2f(simulated_position_change));
_sensor_simulator.runSeconds(6);
_sensor_simulator.runSeconds(11);
// THEN: a reset to the new GPS position should be done
const Vector3f estimated_position = _ekf->getPosition();

View File

@ -291,7 +291,11 @@ int LogWriterFile::thread_start()
param.sched_priority = SCHED_PRIORITY_DEFAULT - 40;
(void)pthread_attr_setschedparam(&thr_attr, &param);
#ifdef CONFIG_FS_LITTLEFS
pthread_attr_setstacksize(&thr_attr, PX4_STACK_ADJUSTED(1800)); /* littlefs needs more stack */
#else
pthread_attr_setstacksize(&thr_attr, PX4_STACK_ADJUSTED(1170));
#endif
int ret = pthread_create(&_thread, &thr_attr, &LogWriterFile::run_helper, this);
pthread_attr_destroy(&thr_attr);

View File

@ -52,6 +52,15 @@ ManualControl::~ManualControl()
bool ManualControl::init()
{
#if defined(PAYLOAD_POWER_EN)
// If the payload power switch is mapped, default to power off until the RC switch explicitly commands it on.
if (_param_rc_map_pay_sw.get()) {
PAYLOAD_POWER_EN(false);
}
#endif // PAYLOAD_POWER_EN
ScheduleNow();
return true;
}
@ -293,6 +302,18 @@ void ManualControl::processSwitches(hrt_abstime &now)
} else if (!_armed) {
// Directly initialize mode using RC switch but only before arming
evaluateModeSlot(switches.mode_slot);
#if defined(PAYLOAD_POWER_EN)
// Apply payload power state on first switch receipt if not armed
if (switches.payload_power_switch == manual_control_switches_s::SWITCH_POS_ON) {
PAYLOAD_POWER_EN(true);
} else if (switches.payload_power_switch == manual_control_switches_s::SWITCH_POS_OFF
|| switches.payload_power_switch == manual_control_switches_s::SWITCH_POS_MIDDLE) {
PAYLOAD_POWER_EN(false);
}
#endif // PAYLOAD_POWER_EN
}
_previous_switches = switches;

View File

@ -149,6 +149,7 @@ private:
(ParamBool<px4::params::MAN_ARM_GESTURE>) _param_man_arm_gesture,
(ParamFloat<px4::params::MAN_KILL_GEST_T>) _param_man_kill_gest_t,
(ParamBool<px4::params::COM_ARM_SWISBTN>) _param_com_arm_swisbtn,
(ParamInt<px4::params::RC_MAP_PAY_SW>) _param_rc_map_pay_sw,
(ParamInt<px4::params::COM_FLTMODE1>) _param_fltmode_1,
(ParamInt<px4::params::COM_FLTMODE2>) _param_fltmode_2,
(ParamInt<px4::params::COM_FLTMODE3>) _param_fltmode_3,

View File

@ -58,7 +58,9 @@ muorb_init()
if (channel && channel->Initialize(enable_debug)) {
uORB::Manager::get_instance()->set_uorb_communicator(channel);
if (channel->Test()) { return OK; }
if (channel->Test()) {
return OK;
}
}
return -EINVAL;

View File

@ -291,6 +291,20 @@ int16_t uORB::AppsProtobufChannel::register_handler(uORBCommunicator::IChannelRx
return 0;
}
int16_t uORB::AppsProtobufChannel::shutdown()
{
if (_ShutdownRequested) {
return 0;
}
_ShutdownRequested = true;
PX4_ERR("Sending kill command to SLPI!!!");
fc_sensor_kill_slpi();
sleep(1);
return 0;
}
int16_t uORB::AppsProtobufChannel::send_message(const char *messageName, int length, uint8_t *data)
{
// This is done to slow down high rate debug messages.

View File

@ -147,6 +147,16 @@ public:
*/
int16_t send_message(const char *messageName, int length, uint8_t *data);
/**
* @brief Interface to notify the remote entity of a shutdown.
*
* @return
* 0 = success; This means the shutdown is successfully sent to the receiver
* Note: This does not mean that the receiver has received it.
* otherwise = failure.
*/
int16_t shutdown();
/**
* @brief Interface to test the functions of the protobuf channel.
*
@ -169,6 +179,7 @@ private:
static bool _Debug;
bool _Initialized;
bool _ShutdownRequested{false};
uint32_t _MessageCounter;
private: