Sync inav to Gitea
Make sure docs are updated / settings_md (push) Canceled after 0s
Build firmware / test (push) Canceled after 0s
Build firmware / build-SITL-Windows (push) Canceled after 0s
Build firmware / build-SITL-Mac (push) Canceled after 0s
Build firmware / build-SITL-Linux (push) Canceled after 0s
Build firmware / build-SITL-Linux-arm64 (push) Canceled after 0s
Build firmware / upload-artifacts (push) Canceled after 0s
Build firmware / build-single-target (push) Canceled after 0s
Build firmware / build (9) (push) Canceled after 0s
Build firmware / build (8) (push) Canceled after 0s
Build firmware / build (7) (push) Canceled after 0s
Build firmware / build (6) (push) Canceled after 0s
Build firmware / build (5) (push) Canceled after 0s
Build firmware / build (4) (push) Canceled after 0s
Build firmware / build (3) (push) Canceled after 0s
Build firmware / build (2) (push) Canceled after 0s
Build firmware / build (14) (push) Canceled after 0s
Build firmware / build (13) (push) Canceled after 0s
Build firmware / build (12) (push) Canceled after 0s
Build firmware / build (11) (push) Canceled after 0s
Build firmware / build (10) (push) Canceled after 0s
Build firmware / build (1) (push) Canceled after 0s
Build firmware / build (0) (push) Canceled after 0s
Build firmware / detect (push) Canceled after 0s
Build pre-release / build (push) Canceled after 0s
Build pre-release / Release (push) Canceled after 0s
Make sure docs are updated / settings_md (push) Canceled after 0s
Build firmware / test (push) Canceled after 0s
Build firmware / build-SITL-Windows (push) Canceled after 0s
Build firmware / build-SITL-Mac (push) Canceled after 0s
Build firmware / build-SITL-Linux (push) Canceled after 0s
Build firmware / build-SITL-Linux-arm64 (push) Canceled after 0s
Build firmware / upload-artifacts (push) Canceled after 0s
Build firmware / build-single-target (push) Canceled after 0s
Build firmware / build (9) (push) Canceled after 0s
Build firmware / build (8) (push) Canceled after 0s
Build firmware / build (7) (push) Canceled after 0s
Build firmware / build (6) (push) Canceled after 0s
Build firmware / build (5) (push) Canceled after 0s
Build firmware / build (4) (push) Canceled after 0s
Build firmware / build (3) (push) Canceled after 0s
Build firmware / build (2) (push) Canceled after 0s
Build firmware / build (14) (push) Canceled after 0s
Build firmware / build (13) (push) Canceled after 0s
Build firmware / build (12) (push) Canceled after 0s
Build firmware / build (11) (push) Canceled after 0s
Build firmware / build (10) (push) Canceled after 0s
Build firmware / build (1) (push) Canceled after 0s
Build firmware / build (0) (push) Canceled after 0s
Build firmware / detect (push) Canceled after 0s
Build pre-release / build (push) Canceled after 0s
Build pre-release / Release (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
;;; Directory Local Variables -*- no-byte-compile: t -*-
|
||||
;;; For more information see (info "(emacs) Directory Variables")
|
||||
|
||||
((nil . ((c-basic-offset . 4)
|
||||
(c-default-style . "k&r"))))
|
||||
@@ -0,0 +1,7 @@
|
||||
.git/
|
||||
.vagrant/
|
||||
.vscode/
|
||||
/build/
|
||||
/obj/
|
||||
/tools/
|
||||
/downloads/
|
||||
@@ -0,0 +1,13 @@
|
||||
*.md text
|
||||
*.c text
|
||||
*.h text
|
||||
*.cc text
|
||||
*.S text
|
||||
*.s text
|
||||
*.hex -crlf -diff
|
||||
*.elf -crlf -diff
|
||||
*.ld text
|
||||
Makefile text
|
||||
*.bat eol=crlf
|
||||
*.txt text
|
||||
*.sh text eol=lf
|
||||
@@ -0,0 +1,49 @@
|
||||
---
|
||||
name: "\U0001F41B Bug report"
|
||||
about: Report an issue to help make INAV better
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**PLEASE MAKE SURE YOU READ AND UNDERSTAND THE SOCIAL MEDIA SUPPORT CHANNELS. QUESTIONS ABOUT FLASHING, CONFIGURING, PILOTING MAY BE CLOSED WITHOUT FURTHER INTERACTION.**
|
||||
|
||||
* [INAV Discord Server](https://discord.gg/peg2hhbYwN)
|
||||
* [INAV Official on Facebook](https://www.facebook.com/groups/INAVOfficial)
|
||||
* [INAV Official on Telegram](https://t.me/INAVFlight)
|
||||
|
||||
**Please double-check that nobody reported the issue before by using search in this bug tracker.**
|
||||
**For Bug-Reports, please use the following template and provide as much information as possible. Bug-Reports that don't follow the template, might be closed unanswered. If you are not sure if you found a bug, ask for further input in the community channels or open a Github discussion.**
|
||||
|
||||
**PLEASE DELETE THE TEXT ABOVE AFTER READING AND UNDERSTANDING IT**
|
||||
|
||||
****
|
||||
|
||||
|
||||
## Current Behavior
|
||||
<!-- If applicable, add screenshots, videos and blackbox logs to help explain your problem. -->
|
||||
|
||||
## Steps to Reproduce
|
||||
<!-- Steps to reproduce the behavior: -->
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
4.
|
||||
|
||||
## Expected behavior
|
||||
<!-- A clear and concise description of what you expected to happen. -->
|
||||
|
||||
## Suggested solution(s)
|
||||
<!-- How could we solve this issue? What changes would need to made to INAV? -->
|
||||
|
||||
## Additional context
|
||||
<!-- Add any other context about the problem here. -->
|
||||
<!-- Go to CLI, execute `diff` command copy its output to [PasteBin](https://pastebin.com) and provide a link to a paste here -->
|
||||
|
||||
---
|
||||
<!-- PLEASE FILL THIS OUT -->
|
||||
<!-- Use CLI 'version' command to get version string -->
|
||||
|
||||
- FC Board name and vendor:
|
||||
- INAV version string:
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
name: "\U0001F680Feature request"
|
||||
about: Suggest a new feature for INAV
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## Current Behavior
|
||||
<!-- A clear and concise description of what is the current behavior / usecase. -->
|
||||
|
||||
## Desired Behavior
|
||||
<!-- A clear and concise description of what you want to happen. -->
|
||||
|
||||
## Suggested Solution
|
||||
<!-- Suggest a solution that the community/maintainers/you may take to enable the desired behavior -->
|
||||
<!-- NOTE: Feature Requests without suggested solutions may not be addressed with the same level of urgency as those that have suggested solutions -->
|
||||
|
||||
## Who does this impact? Who is this for?
|
||||
<!-- Who is this for? All users? Airplane users? Beginners? Advanced? Yourself? People using X, Y, Z, etc.? -->
|
||||
|
||||
## Additional context
|
||||
<!-- Add any other context or links about the feature request here. -->
|
||||
@@ -0,0 +1,38 @@
|
||||
This pull requests adds support for ``$TARGET_NAME``
|
||||
|
||||
* [ ] Target complies with ``docs/policies/NEW_HARDWARE_POLICY.md``
|
||||
|
||||
The following items have been checked and confirmed working by an INAV developer on actual hardware: (feel free to remove non-relevant items)
|
||||
|
||||
* [ ] Samples received
|
||||
* [ ] Flash firmware
|
||||
* [ ] Calibrate
|
||||
* [ ] Orientation matches
|
||||
* [ ] Gyro working
|
||||
* [ ] Accel working
|
||||
* [ ] Voltage correct
|
||||
* [ ] Current correct
|
||||
* [ ] Baro working
|
||||
* [ ] Mag I2C Bus
|
||||
* [ ] Additional I2C2 Buses (Airspeed/other accessories)
|
||||
* [ ] UART1
|
||||
* [ ] UART2
|
||||
* [ ] UART3
|
||||
* [ ] UART4
|
||||
* [ ] UART5
|
||||
* [ ] UART6
|
||||
* [ ] UART7
|
||||
* [ ] UART8
|
||||
* [ ] Analog Camera working
|
||||
* [ ] Video Out working
|
||||
* [ ] OSD working
|
||||
* [ ] LEDs working
|
||||
* [ ] Buzzer working
|
||||
* [ ] Motor outputs
|
||||
* [ ] DShot support on m1-4
|
||||
* [ ] Servo outputs
|
||||
* [ ] Blackbox
|
||||
* [ ] PINIO1
|
||||
* [ ] PINIO2
|
||||
* [ ] PINIO3
|
||||
* [ ] PINIO4
|
||||
@@ -0,0 +1,4 @@
|
||||
label-alias:
|
||||
bug: 'BUG'
|
||||
feature_request: 'Feature request'
|
||||
question: 'Support'
|
||||
@@ -0,0 +1,12 @@
|
||||
# Configuration for probot-no-response - https://github.com/probot/no-response
|
||||
|
||||
# Number of days of inactivity before an Issue is closed for lack of response
|
||||
daysUntilClose: 3
|
||||
# Label requiring a response
|
||||
responseRequiredLabel: Missing Information
|
||||
# Comment to post when closing an Issue for lack of response. Set to `false` to disable
|
||||
closeComment: >
|
||||
This issue has been automatically closed because the information we asked
|
||||
to be provided when opening it was not supplied by the original author.
|
||||
With only the information that is currently in the issue, we don't have
|
||||
enough information to take action.
|
||||
Executable
+226
@@ -0,0 +1,226 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Check if parameter group struct modifications include version increments
|
||||
# This prevents settings corruption when struct layout changes without version bump
|
||||
#
|
||||
# Exit codes:
|
||||
# 0 - No issues found
|
||||
# 1 - Potential issues detected (will post comment)
|
||||
# 2 - Script error
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Output file for issues found
|
||||
ISSUES_FILE=$(mktemp)
|
||||
trap "rm -f $ISSUES_FILE" EXIT
|
||||
|
||||
# Color output for local testing
|
||||
if [ -t 1 ]; then
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
else
|
||||
RED=''
|
||||
GREEN=''
|
||||
YELLOW=''
|
||||
NC=''
|
||||
fi
|
||||
|
||||
echo "🔍 Checking for Parameter Group version updates..."
|
||||
|
||||
# Get base and head commits
|
||||
BASE_REF=${GITHUB_BASE_REF:-}
|
||||
HEAD_REF=${GITHUB_HEAD_REF:-}
|
||||
|
||||
if [ -z "$BASE_REF" ] || [ -z "$HEAD_REF" ]; then
|
||||
echo "⚠️ Warning: Not running in GitHub Actions PR context"
|
||||
echo "Using git diff against HEAD~1 for local testing"
|
||||
BASE_COMMIT="HEAD~1"
|
||||
HEAD_COMMIT="HEAD"
|
||||
else
|
||||
BASE_COMMIT="origin/$BASE_REF"
|
||||
HEAD_COMMIT="HEAD"
|
||||
fi
|
||||
|
||||
# Get list of changed files
|
||||
CHANGED_FILES=$(git diff --name-only $BASE_COMMIT..$HEAD_COMMIT | grep -E '\.(c|h)$' || true)
|
||||
|
||||
if [ -z "$CHANGED_FILES" ]; then
|
||||
echo "✅ No C/H files changed"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "📁 Changed files:"
|
||||
echo "$CHANGED_FILES" | sed 's/^/ /'
|
||||
|
||||
# Function to extract PG info from a file
|
||||
check_file_for_pg_changes() {
|
||||
local file=$1
|
||||
local diff_output=$(git diff $BASE_COMMIT..$HEAD_COMMIT -- "$file")
|
||||
|
||||
# Check if file contains PG_REGISTER in current version
|
||||
if ! git show $HEAD_COMMIT:"$file" 2>/dev/null | grep -q "PG_REGISTER"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo " 🔎 Checking $file (contains PG_REGISTER)"
|
||||
|
||||
# Extract all PG_REGISTER lines from the diff (both old and new)
|
||||
local pg_registers=$(echo "$diff_output" | grep -E "^[-+].*PG_REGISTER" || true)
|
||||
|
||||
if [ -z "$pg_registers" ]; then
|
||||
# PG_REGISTER exists but wasn't changed
|
||||
# Still need to check if the struct changed
|
||||
pg_registers=$(git show $HEAD_COMMIT:"$file" | grep "PG_REGISTER" || true)
|
||||
fi
|
||||
|
||||
# Process each PG registration
|
||||
while IFS= read -r pg_line; do
|
||||
[ -z "$pg_line" ] && continue
|
||||
|
||||
# Extract struct name and version
|
||||
# Pattern: PG_REGISTER.*\((\w+),\s*(\w+),\s*PG_\w+,\s*(\d+)\)
|
||||
if [[ $pg_line =~ PG_REGISTER[^(]*\(([^,]+),([^,]+),([^,]+),([^)]+)\) ]]; then
|
||||
local struct_type="${BASH_REMATCH[1]}"
|
||||
local pg_name="${BASH_REMATCH[2]}"
|
||||
local pg_id="${BASH_REMATCH[3]}"
|
||||
local version="${BASH_REMATCH[4]}"
|
||||
|
||||
# Clean up whitespace
|
||||
struct_type=$(echo "$struct_type" | xargs)
|
||||
version=$(echo "$version" | xargs)
|
||||
|
||||
echo " 📋 Found: $struct_type (version $version)"
|
||||
|
||||
# Check if this struct's typedef was modified in ANY changed file
|
||||
local struct_pattern="typedef struct ${struct_type%_t}_s"
|
||||
local struct_body_diff=""
|
||||
local struct_found_in=""
|
||||
|
||||
# Search all changed files for this struct definition
|
||||
while IFS= read -r changed_file; do
|
||||
[ -z "$changed_file" ] && continue
|
||||
|
||||
local file_diff=$(git diff $BASE_COMMIT..$HEAD_COMMIT -- "$changed_file")
|
||||
local struct_in_file=$(echo "$file_diff" | sed -n "/${struct_pattern}/,/\}.*${struct_type};/p")
|
||||
|
||||
if [ -n "$struct_in_file" ]; then
|
||||
struct_body_diff="$struct_in_file"
|
||||
struct_found_in="$changed_file"
|
||||
echo " 🔍 Found struct definition in $changed_file"
|
||||
break
|
||||
fi
|
||||
done <<< "$CHANGED_FILES"
|
||||
|
||||
local struct_changes=$(echo "$struct_body_diff" | grep -E "^[-+]" \
|
||||
| grep -v -E "^[-+]\s*(typedef struct|}|//|\*)" \
|
||||
| sed -E 's://.*$::' \
|
||||
| sed -E 's:/\*.*\*/::' \
|
||||
| tr -d '[:space:]')
|
||||
|
||||
if [ -n "$struct_changes" ]; then
|
||||
echo " ⚠️ Struct definition modified in $struct_found_in"
|
||||
|
||||
# Check if version was incremented in PG_REGISTER
|
||||
local old_version=$(echo "$diff_output" | grep "^-.*PG_REGISTER.*$struct_type" | grep -oP ',\s*\K\d+(?=\s*\))' || echo "")
|
||||
local new_version=$(echo "$diff_output" | grep "^+.*PG_REGISTER.*$struct_type" | grep -oP ',\s*\K\d+(?=\s*\))' || echo "")
|
||||
|
||||
# Find line number of PG_REGISTER for error reporting
|
||||
local line_num=$(git show $HEAD_COMMIT:"$file" | grep -n "PG_REGISTER.*$struct_type" | cut -d: -f1 | head -1)
|
||||
|
||||
if [ -n "$old_version" ] && [ -n "$new_version" ]; then
|
||||
# PG_REGISTER was modified - check if version increased
|
||||
if [ "$new_version" -le "$old_version" ]; then
|
||||
echo " ❌ Version NOT incremented ($old_version → $new_version)"
|
||||
cat >> $ISSUES_FILE << EOF
|
||||
### \`$struct_type\` ($file:$line_num)
|
||||
- **Struct modified:** Field changes detected in $struct_found_in
|
||||
- **Version status:** ❌ Not incremented (version $version)
|
||||
- **Recommendation:** Increment version from $old_version to $(($old_version + 1))
|
||||
|
||||
EOF
|
||||
else
|
||||
echo " ✅ Version incremented ($old_version → $new_version)"
|
||||
fi
|
||||
elif [ -z "$old_version" ] && [ -z "$new_version" ]; then
|
||||
# PG_REGISTER wasn't modified but struct was - THIS IS THE BUG!
|
||||
echo " ❌ PG_REGISTER not modified, version still $version"
|
||||
cat >> $ISSUES_FILE << EOF
|
||||
### \`$struct_type\` ($file:$line_num)
|
||||
- **Struct modified:** Field changes detected in $struct_found_in
|
||||
- **Version status:** ❌ Not incremented (still version $version)
|
||||
- **Recommendation:** Increment version to $(($version + 1)) in $file
|
||||
|
||||
EOF
|
||||
else
|
||||
# One exists but not the other - unusual edge case
|
||||
echo " ⚠️ Unusual version change pattern detected"
|
||||
cat >> $ISSUES_FILE << EOF
|
||||
### \`$struct_type\` ($file:$line_num)
|
||||
- **Struct modified:** Field changes detected in $struct_found_in
|
||||
- **Version status:** ⚠️ Unusual change pattern (old: ${old_version:-none}, new: ${new_version:-none})
|
||||
- **Current version:** $version
|
||||
- **Recommendation:** Manually verify version increment
|
||||
|
||||
EOF
|
||||
fi
|
||||
else
|
||||
echo " ✅ Struct unchanged"
|
||||
fi
|
||||
fi
|
||||
done <<< "$pg_registers"
|
||||
}
|
||||
|
||||
# Build list of files to check (changed files + companions with PG_REGISTER)
|
||||
echo "🔍 Building file list including companions with PG_REGISTER..."
|
||||
FILES_TO_CHECK=""
|
||||
ALREADY_ADDED=""
|
||||
|
||||
while IFS= read -r file; do
|
||||
[ -z "$file" ] && continue
|
||||
|
||||
# Add this file to check list
|
||||
if ! echo "$ALREADY_ADDED" | grep -qw "$file"; then
|
||||
FILES_TO_CHECK="$FILES_TO_CHECK$file"$'\n'
|
||||
ALREADY_ADDED="$ALREADY_ADDED $file"
|
||||
fi
|
||||
|
||||
# Determine companion file (.c <-> .h)
|
||||
local companion=""
|
||||
if [[ "$file" == *.c ]]; then
|
||||
companion="${file%.c}.h"
|
||||
elif [[ "$file" == *.h ]]; then
|
||||
companion="${file%.h}.c"
|
||||
fi
|
||||
|
||||
# If companion exists and contains PG_REGISTER, add it to check list
|
||||
if [ -n "$companion" ]; then
|
||||
if git show $HEAD_COMMIT:"$companion" 2>/dev/null | grep -q "PG_REGISTER"; then
|
||||
if ! echo "$ALREADY_ADDED" | grep -qw "$companion"; then
|
||||
echo " 📎 Adding $companion (companion of $file with PG_REGISTER)"
|
||||
FILES_TO_CHECK="$FILES_TO_CHECK$companion"$'\n'
|
||||
ALREADY_ADDED="$ALREADY_ADDED $companion"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done <<< "$CHANGED_FILES"
|
||||
|
||||
# Check each file (including companions)
|
||||
while IFS= read -r file; do
|
||||
[ -z "$file" ] && continue
|
||||
check_file_for_pg_changes "$file"
|
||||
done <<< "$FILES_TO_CHECK"
|
||||
|
||||
# Check if any issues were found
|
||||
if [ -s $ISSUES_FILE ]; then
|
||||
echo ""
|
||||
echo "${YELLOW}⚠️ Potential PG version issues detected${NC}"
|
||||
echo "Output saved to: $ISSUES_FILE"
|
||||
cat $ISSUES_FILE
|
||||
exit 1
|
||||
else
|
||||
echo ""
|
||||
echo "${GREEN}✅ No PG version issues detected${NC}"
|
||||
exit 0
|
||||
fi
|
||||
@@ -0,0 +1,58 @@
|
||||
# Configuration for probot-stale - https://github.com/probot/stale
|
||||
|
||||
# Number of days of inactivity before an Issue or Pull Request becomes stale
|
||||
daysUntilStale: 60
|
||||
|
||||
# Number of days of inactivity before a stale Issue or Pull Request is closed.
|
||||
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
|
||||
daysUntilClose: 14
|
||||
|
||||
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
|
||||
exemptLabels:
|
||||
- BUG
|
||||
- Feature Request
|
||||
- Pinned
|
||||
|
||||
# Set to true to ignore issues in a project (defaults to false)
|
||||
exemptProjects: false
|
||||
|
||||
# Set to true to ignore issues in a milestone (defaults to false)
|
||||
exemptMilestones: true
|
||||
|
||||
# Label to use when marking as stale
|
||||
staleLabel: Inactive
|
||||
|
||||
# Comment to post when marking as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue / pull request has been automatically marked as stale because it
|
||||
has not had any activity in 60 days. The resources of the INAV team are limited,
|
||||
and so we are asking for your help.
|
||||
|
||||
This issue / pull request will be closed if no further activity occurs within two weeks.
|
||||
|
||||
|
||||
# Comment to post when removing the stale label.
|
||||
# unmarkComment: >
|
||||
# Your comment here.
|
||||
|
||||
# Comment to post when closing a stale Issue or Pull Request.
|
||||
closeComment: >
|
||||
Automatically closing as inactive.
|
||||
|
||||
# Limit the number of actions per hour, from 1-30. Default is 30
|
||||
limitPerRun: 30
|
||||
|
||||
# Limit to only `issues` or `pulls`
|
||||
# only: issues
|
||||
|
||||
# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
|
||||
# pulls:
|
||||
# daysUntilStale: 30
|
||||
# markComment: >
|
||||
# This pull request has been automatically marked as stale because it has not had
|
||||
# recent activity. It will be closed if no further activity occurs. Thank you
|
||||
# for your contributions.
|
||||
|
||||
# issues:
|
||||
# exemptLabels:
|
||||
# - confirmed
|
||||
@@ -0,0 +1,127 @@
|
||||
# GitHub Actions Workflows
|
||||
|
||||
This directory contains automated CI/CD workflows for the INAV project.
|
||||
|
||||
## Active Workflows
|
||||
|
||||
### Build and Test
|
||||
|
||||
#### `ci.yml` - Build Firmware
|
||||
**Triggers:** Pull requests, pushes to maintenance branches
|
||||
**Purpose:** Compiles INAV firmware for all targets to verify builds succeed
|
||||
**Matrix:** 15 parallel build jobs for faster CI
|
||||
|
||||
#### `nightly-build.yml` - Nightly Builds
|
||||
**Triggers:** Scheduled nightly
|
||||
**Purpose:** Creates nightly development builds for testing
|
||||
|
||||
### Documentation
|
||||
|
||||
#### `docs.yml` - Documentation Build
|
||||
**Triggers:** Pull requests affecting documentation
|
||||
**Purpose:** Validates documentation builds correctly
|
||||
|
||||
### Code Quality
|
||||
|
||||
#### `pg-version-check.yml` - Parameter Group Version Check
|
||||
**Triggers:** Pull requests to maintenance-9.x and maintenance-10.x
|
||||
**Purpose:** Detects parameter group struct modifications and verifies version increments
|
||||
**Why:** Prevents settings corruption when struct layout changes without version bump
|
||||
|
||||
**How it works:**
|
||||
1. Scans changed .c/.h files for `PG_REGISTER` entries
|
||||
2. Detects if associated struct typedefs were modified
|
||||
3. Checks if the PG version parameter was incremented
|
||||
4. Posts helpful comment if version not incremented
|
||||
|
||||
**Reference:** See `docs/development/parameter_groups/` for PG system documentation
|
||||
|
||||
**Script:** `.github/scripts/check-pg-versions.sh`
|
||||
|
||||
**When to increment PG versions:**
|
||||
- ✅ Adding/removing fields from struct
|
||||
- ✅ Changing field types or sizes
|
||||
- ✅ Reordering fields
|
||||
- ✅ Adding/removing packing attributes
|
||||
- ❌ Only changing `PG_RESET_TEMPLATE` default values
|
||||
- ❌ Only changing comments
|
||||
|
||||
### Pull Request Helpers
|
||||
|
||||
#### `pr-branch-suggestion.yml` - Branch Targeting Suggestion
|
||||
**Triggers:** PRs targeting master branch
|
||||
**Purpose:** Suggests using maintenance-9.x or maintenance-10.x instead
|
||||
|
||||
#### `non-code-change.yaml` - Non-Code Change Detection
|
||||
**Triggers:** Pull requests
|
||||
**Purpose:** Detects PRs with only documentation/formatting changes
|
||||
|
||||
## Configuration Files
|
||||
|
||||
- `../.github/stale.yml` - Stale issue/PR management
|
||||
- `../.github/no-response.yml` - Auto-close issues without response
|
||||
- `../.github/issue_label_bot.yaml` - Automatic issue labeling
|
||||
|
||||
## Adding New Workflows
|
||||
|
||||
When adding workflows:
|
||||
|
||||
1. **Use descriptive names** - Make purpose clear from filename
|
||||
2. **Document in this README** - Add entry above with purpose and triggers
|
||||
3. **Set appropriate permissions** - Principle of least privilege
|
||||
4. **Test in fork first** - Verify before submitting to main repo
|
||||
5. **Handle errors gracefully** - Don't block CI unnecessarily
|
||||
|
||||
### Common Patterns
|
||||
|
||||
**Checkout with history:**
|
||||
```yaml
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
```
|
||||
|
||||
**Post PR comments:**
|
||||
```yaml
|
||||
- uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: 'Comment text'
|
||||
});
|
||||
```
|
||||
|
||||
**Run bash scripts:**
|
||||
```yaml
|
||||
- run: bash .github/scripts/script-name.sh
|
||||
env:
|
||||
GITHUB_BASE_REF: ${{ github.base_ref }}
|
||||
```
|
||||
|
||||
## Permissions
|
||||
|
||||
Workflows use GitHub's fine-grained permissions:
|
||||
|
||||
- `contents: read` - Read repository code
|
||||
- `pull-requests: write` - Post/update PR comments
|
||||
- `actions: read` - Read workflow run data
|
||||
|
||||
## Local Testing
|
||||
|
||||
Scripts in `.github/scripts/` can be run locally:
|
||||
|
||||
```bash
|
||||
cd inav
|
||||
export GITHUB_BASE_REF=maintenance-9.x
|
||||
export GITHUB_HEAD_REF=feature-branch
|
||||
bash .github/scripts/check-pg-versions.sh
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- [GitHub Actions Documentation](https://docs.github.com/en/actions)
|
||||
- [Workflow Syntax](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions)
|
||||
- [GitHub Script Action](https://github.com/actions/github-script)
|
||||
@@ -0,0 +1,382 @@
|
||||
name: Build firmware
|
||||
# Don't enable CI on push, just on PR. If you
|
||||
# are working on the main repo and want to trigger
|
||||
# a CI build submit a draft PR.
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '!maintenance-8.x.x'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'src/**'
|
||||
- '.github/**'
|
||||
- 'cmake/**'
|
||||
- 'lib/**'
|
||||
- 'docs/Settings.md'
|
||||
- 'CMakeLists.txt'
|
||||
- '*.sh'
|
||||
|
||||
workflow_call:
|
||||
#inputs:
|
||||
# release_build:
|
||||
# description: 'Specifies if it is a build that should include commit hash in hex file names or not'
|
||||
# default: false
|
||||
# required: false
|
||||
# type: boolean
|
||||
|
||||
|
||||
jobs:
|
||||
detect:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
single_target: ${{ steps.check.outputs.single_target }}
|
||||
target_names: ${{ steps.check.outputs.target_names }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Detect single-target PR
|
||||
id: check
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" != "pull_request" ]; then
|
||||
echo "single_target=false" >> $GITHUB_OUTPUT
|
||||
exit 0
|
||||
fi
|
||||
|
||||
CHANGED=$(git diff --name-only origin/${{ github.base_ref }}...HEAD)
|
||||
|
||||
if [ -z "$CHANGED" ]; then
|
||||
echo "single_target=false" >> $GITHUB_OUTPUT
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Fail fast if any changed file is outside src/main/target/<dir>/
|
||||
NON_TARGET=$(echo "$CHANGED" | grep -Ev '^src/main/target/[^/]+/.+' | head -1)
|
||||
if [ -n "$NON_TARGET" ]; then
|
||||
echo "Non-target file changed: $NON_TARGET — full build required"
|
||||
echo "single_target=false" >> $GITHUB_OUTPUT
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Count how many distinct target directories were touched
|
||||
TARGET_DIRS=$(echo "$CHANGED" | sed -n 's|^src/main/target/\([^/]*\)/.*|\1|p' | sort -u)
|
||||
DIR_COUNT=$(echo "$TARGET_DIRS" | wc -l)
|
||||
if [ "$DIR_COUNT" != "1" ]; then
|
||||
echo "$DIR_COUNT target directories changed — full build required"
|
||||
echo "single_target=false" >> $GITHUB_OUTPUT
|
||||
exit 0
|
||||
fi
|
||||
|
||||
TARGET_DIR="$TARGET_DIRS"
|
||||
CMAKE="src/main/target/${TARGET_DIR}/CMakeLists.txt"
|
||||
if [ ! -f "$CMAKE" ]; then
|
||||
echo "No CMakeLists.txt for $TARGET_DIR — full build required"
|
||||
echo "single_target=false" >> $GITHUB_OUTPUT
|
||||
exit 0
|
||||
fi
|
||||
|
||||
TARGET_NAMES=$(grep -oP '(?<=\()[^)]+' "$CMAKE" | tr '\n' ' ' | xargs)
|
||||
if [ -z "$TARGET_NAMES" ]; then
|
||||
echo "No target names in CMakeLists.txt — full build required"
|
||||
echo "single_target=false" >> $GITHUB_OUTPUT
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Single-target PR: building $TARGET_NAMES"
|
||||
echo "single_target=true" >> $GITHUB_OUTPUT
|
||||
echo "target_names=$TARGET_NAMES" >> $GITHUB_OUTPUT
|
||||
|
||||
build:
|
||||
needs: [detect]
|
||||
if: needs.detect.outputs.single_target != 'true'
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
id: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get update && sudo apt-get -y install ninja-build
|
||||
- name: Setup environment
|
||||
env:
|
||||
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
|
||||
run: |
|
||||
# This is the hash of the commit for the PR
|
||||
# when the action is triggered by PR, empty otherwise
|
||||
COMMIT_ID=${{ github.event.pull_request.head.sha }}
|
||||
# This is the hash of the commit when triggered by push
|
||||
# but the hash of refs/pull/<n>/merge, which is different
|
||||
# from the hash of the latest commit in the PR, that's
|
||||
# why we try github.event.pull_request.head.sha first
|
||||
COMMIT_ID=${COMMIT_ID:-${{ github.sha }}}
|
||||
BUILD_SUFFIX=ci-$(date '+%Y%m%d')-$(git rev-parse --short ${COMMIT_ID})
|
||||
VERSION=$(grep project CMakeLists.txt|awk -F VERSION '{ gsub(/[ \t)]/, "", $2); print $2 }')
|
||||
echo "BUILD_SUFFIX=${BUILD_SUFFIX}" >> $GITHUB_ENV
|
||||
echo "BUILD_NAME=inav-${VERSION}-${BUILD_SUFFIX}" >> $GITHUB_ENV
|
||||
echo "NUM_CORES=$(grep processor /proc/cpuinfo | wc -l)" >> $GITHUB_ENV
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: downloads
|
||||
key: ${{ runner.os }}-downloads-${{ hashFiles('CMakeLists.txt') }}-${{ hashFiles('**/cmake/*')}}
|
||||
- name: Build targets (${{ matrix.id }})
|
||||
run: mkdir -p build && cd build && cmake -DWARNINGS_AS_ERRORS=ON -DCI_JOB_INDEX=${{ matrix.id }} -DCI_JOB_COUNT=${{ strategy.job-total }} -DBUILD_SUFFIX=${{ env.BUILD_SUFFIX }} -DMAIN_COMPILE_OPTIONS=-pipe -G Ninja .. && ninja -j${{ env.NUM_CORES }} ci
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: matrix-${{ env.BUILD_NAME }}.${{ matrix.id }}
|
||||
path: ./build/*.hex
|
||||
retention-days: 1
|
||||
|
||||
build-single-target:
|
||||
needs: [detect]
|
||||
if: needs.detect.outputs.single_target == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get update && sudo apt-get -y install ninja-build
|
||||
- name: Setup environment
|
||||
env:
|
||||
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
|
||||
run: |
|
||||
COMMIT_ID=${{ github.event.pull_request.head.sha }}
|
||||
COMMIT_ID=${COMMIT_ID:-${{ github.sha }}}
|
||||
BUILD_SUFFIX=ci-$(date '+%Y%m%d')-$(git rev-parse --short ${COMMIT_ID})
|
||||
VERSION=$(grep project CMakeLists.txt|awk -F VERSION '{ gsub(/[ \t)]/, "", $2); print $2 }')
|
||||
echo "BUILD_SUFFIX=${BUILD_SUFFIX}" >> $GITHUB_ENV
|
||||
echo "BUILD_NAME=inav-${VERSION}-${BUILD_SUFFIX}" >> $GITHUB_ENV
|
||||
echo "NUM_CORES=$(grep processor /proc/cpuinfo | wc -l)" >> $GITHUB_ENV
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: downloads
|
||||
key: ${{ runner.os }}-downloads-${{ hashFiles('CMakeLists.txt') }}-${{ hashFiles('**/cmake/*')}}
|
||||
- name: Build targets (${{ needs.detect.outputs.target_names }})
|
||||
run: mkdir -p build && cd build && cmake -DWARNINGS_AS_ERRORS=ON -DBUILD_SUFFIX=${{ env.BUILD_SUFFIX }} -DMAIN_COMPILE_OPTIONS=-pipe -G Ninja .. && ninja -j${{ env.NUM_CORES }} ${{ needs.detect.outputs.target_names }}
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: matrix-${{ env.BUILD_NAME }}.single
|
||||
path: ./build/*.hex
|
||||
retention-days: 1
|
||||
|
||||
upload-artifacts:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build, build-single-target]
|
||||
if: always() && !cancelled() && (needs.build.result == 'success' || needs.build-single-target.result == 'success')
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup environment
|
||||
env:
|
||||
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
|
||||
run: |
|
||||
# This is the hash of the commit for the PR
|
||||
# when the action is triggered by PR, empty otherwise
|
||||
COMMIT_ID=${{ github.event.pull_request.head.sha }}
|
||||
# This is the hash of the commit when triggered by push
|
||||
# but the hash of refs/pull/<n>/merge, which is different
|
||||
# from the hash of the latest commit in the PR, that's
|
||||
# why we try github.event.pull_request.head.sha first
|
||||
COMMIT_ID=${COMMIT_ID:-${{ github.sha }}}
|
||||
BUILD_SUFFIX=ci-$(date '+%Y%m%d')-$(git rev-parse --short ${COMMIT_ID})
|
||||
VERSION=$(grep project CMakeLists.txt|awk -F VERSION '{ gsub(/[ \t)]/, "", $2); print $2 }')
|
||||
echo "BUILD_SUFFIX=${BUILD_SUFFIX}" >> $GITHUB_ENV
|
||||
echo "BUILD_NAME=inav-${VERSION}-${BUILD_SUFFIX}" >> $GITHUB_ENV
|
||||
echo "NUM_CORES=$(grep processor /proc/cpuinfo | wc -l)" >> $GITHUB_ENV
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: matrix-inav-*
|
||||
merge-multiple: true
|
||||
path: binaries
|
||||
- name: Build target list
|
||||
run: |
|
||||
ls -1 binaries/*.hex | cut -d/ -f2 > targets.txt
|
||||
- name: Upload firmware images
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ env.BUILD_NAME }}
|
||||
path: binaries/*.hex
|
||||
- name: Upload firmware images
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: targets
|
||||
path: targets.txt
|
||||
- name: Save PR number
|
||||
if: github.event_name == 'pull_request'
|
||||
run: echo "${{ github.event.pull_request.number }}" > pr_number.txt
|
||||
- name: Upload PR number
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: pr-number
|
||||
path: pr_number.txt
|
||||
retention-days: 1
|
||||
|
||||
build-SITL-Linux-arm64:
|
||||
runs-on: ubuntu-22.04-arm
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get update && sudo apt-get -y install ninja-build
|
||||
- name: Setup environment
|
||||
env:
|
||||
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
|
||||
run: |
|
||||
# This is the hash of the commit for the PR
|
||||
# when the action is triggered by PR, empty otherwise
|
||||
COMMIT_ID=${{ github.event.pull_request.head.sha }}
|
||||
# This is the hash of the commit when triggered by push
|
||||
# but the hash of refs/pull/<n>/merge, which is different
|
||||
# from the hash of the latest commit in the PR, that's
|
||||
# why we try github.event.pull_request.head.sha first
|
||||
COMMIT_ID=${COMMIT_ID:-${{ github.sha }}}
|
||||
BUILD_SUFFIX=ci-$(date '+%Y%m%d')-$(git rev-parse --short ${COMMIT_ID})
|
||||
VERSION=$(grep project CMakeLists.txt|awk -F VERSION '{ gsub(/[ \t)]/, "", $2); print $2 }')
|
||||
echo "BUILD_SUFFIX=${BUILD_SUFFIX}" >> $GITHUB_ENV
|
||||
echo "BUILD_NAME=inav-${VERSION}-${BUILD_SUFFIX}" >> $GITHUB_ENV
|
||||
echo "NUM_CORES=$(grep processor /proc/cpuinfo | wc -l)" >> $GITHUB_ENV
|
||||
- name: Build SITL
|
||||
run: mkdir -p build_SITL && cd build_SITL && cmake -DSITL=ON -DWARNINGS_AS_ERRORS=ON -G Ninja .. && ninja -j${{ env.NUM_CORES }}
|
||||
- name: Strip version number
|
||||
run: |
|
||||
for f in build_SITL/*_SITL; do
|
||||
mv $f $(echo $f | sed -e 's/_[0-9]\+\.[0-9]\+\.[0-9]\+//')
|
||||
done
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ env.BUILD_NAME }}_SITL-Linux-aarch64
|
||||
path: ./build_SITL/*_SITL
|
||||
|
||||
build-SITL-Linux:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get update && sudo apt-get -y install ninja-build
|
||||
- name: Setup environment
|
||||
env:
|
||||
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
|
||||
run: |
|
||||
# This is the hash of the commit for the PR
|
||||
# when the action is triggered by PR, empty otherwise
|
||||
COMMIT_ID=${{ github.event.pull_request.head.sha }}
|
||||
# This is the hash of the commit when triggered by push
|
||||
# but the hash of refs/pull/<n>/merge, which is different
|
||||
# from the hash of the latest commit in the PR, that's
|
||||
# why we try github.event.pull_request.head.sha first
|
||||
COMMIT_ID=${COMMIT_ID:-${{ github.sha }}}
|
||||
BUILD_SUFFIX=ci-$(date '+%Y%m%d')-$(git rev-parse --short ${COMMIT_ID})
|
||||
VERSION=$(grep project CMakeLists.txt|awk -F VERSION '{ gsub(/[ \t)]/, "", $2); print $2 }')
|
||||
echo "BUILD_SUFFIX=${BUILD_SUFFIX}" >> $GITHUB_ENV
|
||||
echo "BUILD_NAME=inav-${VERSION}-${BUILD_SUFFIX}" >> $GITHUB_ENV
|
||||
echo "NUM_CORES=$(grep processor /proc/cpuinfo | wc -l)" >> $GITHUB_ENV
|
||||
- name: Build SITL
|
||||
run: mkdir -p build_SITL && cd build_SITL && cmake -DSITL=ON -DWARNINGS_AS_ERRORS=ON -G Ninja .. && ninja -j${{ env.NUM_CORES }}
|
||||
- name: Strip version number
|
||||
run: |
|
||||
for f in build_SITL/*_SITL; do
|
||||
mv $f $(echo $f | sed -e 's/_[0-9]\+\.[0-9]\+\.[0-9]\+//')
|
||||
done
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ env.BUILD_NAME }}_SITL-Linux
|
||||
path: ./build_SITL/*_SITL
|
||||
|
||||
build-SITL-Mac:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
brew install ruby
|
||||
|
||||
- name: Setup environment
|
||||
env:
|
||||
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
|
||||
run: |
|
||||
# This is the hash of the commit for the PR
|
||||
# when the action is triggered by PR, empty otherwise
|
||||
COMMIT_ID=${{ github.event.pull_request.head.sha }}
|
||||
# This is the hash of the commit when triggered by push
|
||||
# but the hash of refs/pull/<n>/merge, which is different
|
||||
# from the hash of the latest commit in the PR, that's
|
||||
# why we try github.event.pull_request.head.sha first
|
||||
COMMIT_ID=${COMMIT_ID:-${{ github.sha }}}
|
||||
BUILD_SUFFIX=ci-$(date '+%Y%m%d')-$(git rev-parse --short ${COMMIT_ID})
|
||||
VERSION=$(grep project CMakeLists.txt|awk -F VERSION '{ gsub(/[ \t)]/, "", $2); print $2 }')
|
||||
echo "BUILD_SUFFIX=${BUILD_SUFFIX}" >> $GITHUB_ENV
|
||||
echo "BUILD_NAME=inav-${VERSION}-${BUILD_SUFFIX}" >> $GITHUB_ENV
|
||||
echo "NUM_CORES=$(grep processor /proc/cpuinfo | wc -l)" >> $GITHUB_ENV
|
||||
- name: Build SITL
|
||||
run: |
|
||||
mkdir -p build_SITL && cd build_SITL
|
||||
cmake -DSITL=ON -DWARNINGS_AS_ERRORS=ON -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" -G Ninja ..
|
||||
ninja -j4
|
||||
- name: Strip version number
|
||||
run: |
|
||||
for f in build_SITL/*_SITL; do
|
||||
mv -v $f $(echo $f | sed -Ee 's/_[0-9]+\.[0-9]+\.[0-9]+//')
|
||||
done
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ env.BUILD_NAME }}_SITL-MacOS
|
||||
path: ./build_SITL/*_SITL
|
||||
|
||||
build-SITL-Windows:
|
||||
runs-on: windows-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: C:\tools\cygwin\bin\bash.exe -o igncr '{0}'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Cygwin
|
||||
uses: egor-tensin/setup-cygwin@v4
|
||||
with:
|
||||
packages: cmake ruby ninja gcc-g++ rubygems
|
||||
- name: Setup environment
|
||||
env:
|
||||
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
|
||||
run: |
|
||||
# This is the hash of the commit for the PR
|
||||
# when the action is triggered by PR, empty otherwise
|
||||
COMMIT_ID=${{ github.event.pull_request.head.sha }}
|
||||
# This is the hash of the commit when triggered by push
|
||||
# but the hash of refs/pull/<n>/merge, which is different
|
||||
# from the hash of the latest commit in the PR, that's
|
||||
# why we try github.event.pull_request.head.sha first
|
||||
COMMIT_ID=${COMMIT_ID:-${{ github.sha }}}
|
||||
BUILD_SUFFIX=ci-$(date '+%Y%m%d')-$(git rev-parse --short ${COMMIT_ID})
|
||||
VERSION=$( grep project CMakeLists.txt|awk -F VERSION '{ gsub(/[ \t)]/, "", $2); print $2 }' )
|
||||
echo "BUILD_SUFFIX=${BUILD_SUFFIX}" >> $GITHUB_ENV
|
||||
echo "BUILD_NAME=inav-${VERSION}-${BUILD_SUFFIX}" >> $GITHUB_ENV
|
||||
|
||||
- name: Build SITL
|
||||
run: gem install getoptlong && mkdir -p build_SITL && cd build_SITL && cmake -DSITL=ON -DWARNINGS_AS_ERRORS=ON -G Ninja .. && ninja -j4
|
||||
- name: Strip version number
|
||||
run: |
|
||||
for f in ./build_SITL/*_SITL.exe; do
|
||||
mv $f $(echo $f | sed -e 's/_[0-9]\+\.[0-9]\+\.[0-9]\+//')
|
||||
done
|
||||
- name: Copy cygwin1.dll
|
||||
run: cp /bin/cygwin1.dll ./build_SITL/
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ env.BUILD_NAME }}_SITL-WIN
|
||||
path: |
|
||||
./build_SITL/*.exe
|
||||
./build_SITL/cygwin1.dll
|
||||
|
||||
test:
|
||||
#needs: [build]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get update && sudo apt-get -y install ninja-build
|
||||
- name: Run Tests
|
||||
run: mkdir -p build && cd build && cmake -DTOOLCHAIN=none -G Ninja .. && ninja check
|
||||
@@ -0,0 +1,27 @@
|
||||
name: Make sure docs are updated
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- src/main/fc/settings.yaml
|
||||
- docs/Settings.md
|
||||
push:
|
||||
paths:
|
||||
- src/main/fc/settings.yaml
|
||||
- docs/Settings.md
|
||||
|
||||
jobs:
|
||||
settings_md:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get update && sudo apt-get -y install python3-yaml
|
||||
- name: Check that Settings.md is up to date
|
||||
run: |
|
||||
cp docs/Settings.md{,.ci}
|
||||
python3 src/utils/update_cli_docs.py -q
|
||||
if ! diff -q docs/Settings.md{,.ci} >/dev/null; then
|
||||
echo "::error ::\"docs/Settings.md\" is not up to date, please run \"src/utils/update_cli_docs.py\""
|
||||
exit 1
|
||||
fi
|
||||
@@ -0,0 +1,105 @@
|
||||
name: Build pre-release
|
||||
# Don't enable CI on push, just on PR. If you
|
||||
# are working on the main repo and want to trigger
|
||||
# a CI build submit a draft PR.
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- maintenance-8.x.x
|
||||
- maintenance-9.x
|
||||
paths:
|
||||
- 'src/**'
|
||||
- '.github/**'
|
||||
- 'cmake/**'
|
||||
- 'lib/**'
|
||||
- 'docs/Settings.md'
|
||||
- 'CMakeLists.txt'
|
||||
- '*.sh'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: build
|
||||
uses: ./.github/workflows/ci.yml
|
||||
|
||||
release:
|
||||
name: Release
|
||||
needs: [build]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Get version
|
||||
id: version
|
||||
run: |
|
||||
VERSION=$(grep project CMakeLists.txt|awk -F VERSION '{ gsub(/[ \t\)]/, "", $2); print $2 }')
|
||||
echo "version=${VERSION}" >> $GITHUB_OUTPUT
|
||||
- name: Get current date
|
||||
id: date
|
||||
run: echo "today=$(date '+%Y%m%d')" >> $GITHUB_OUTPUT
|
||||
- name: download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: hexes
|
||||
pattern: matrix-inav-*
|
||||
merge-multiple: true
|
||||
- name: download sitl linux
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: resources/sitl/linux
|
||||
pattern: inav-*SITL-Linux
|
||||
merge-multiple: true
|
||||
- name: download sitl linux aarch64
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: resources/sitl/linux/arm64
|
||||
pattern: inav-*SITL-Linux-aarch64
|
||||
merge-multiple: true
|
||||
- name: download sitl windows
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: resources/sitl/windows
|
||||
pattern: inav-*SITL-WIN
|
||||
merge-multiple: true
|
||||
- name: download sitl mac
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: resources/sitl/macos
|
||||
pattern: inav-*SITL-MacOS
|
||||
merge-multiple: true
|
||||
- name: Consolidate sitl files
|
||||
run: |
|
||||
zip -r -9 sitl-resources.zip resources/
|
||||
- name: Upload release artifacts
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
name: inav-${{ steps.version.outputs.version }}-dev-${{ steps.date.outputs.today }}-${{ github.run_number }}-${{ github.sha }}
|
||||
tag_name: v${{ steps.version.outputs.version }}-${{ steps.date.outputs.today }}.${{ github.run_number }}
|
||||
# To create release on a different repo, we need a token setup
|
||||
token: ${{ secrets.NIGHTLY_TOKEN }}
|
||||
repository: iNavFlight/inav-nightly
|
||||
prerelease: true
|
||||
draft: false
|
||||
#generate_release_notes: true
|
||||
make_latest: false
|
||||
files: |
|
||||
hexes/*.hex
|
||||
sitl-resources.zip
|
||||
body: |
|
||||
${{ steps.notes.outputs.notes }}
|
||||
|
||||
### Flashing
|
||||
These are nightly builds and configuration settings can be added and removed often. Flashing with Full chip erase is strongly recommended to avoid issues.
|
||||
Firmware related issues should be opened in the iNavflight/inav repository, not in inav-nightly.
|
||||
|
||||
### Repository:
|
||||
${{ github.repository }} ([link](${{ github.event.repository.html_url }}))
|
||||
|
||||
### Branch:
|
||||
${{ github.ref_name }} ([link](${{ github.event.repository.html_url }}/tree/${{ github.ref_name }}))
|
||||
|
||||
### Latest changeset:
|
||||
${{ github.event.head_commit.id }} ([link](${{ github.event.head_commit.url }}))
|
||||
|
||||
### Changes:
|
||||
${{ github.event.head_commit.message }}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
name: Build firmware
|
||||
# Don't enable CI on push, just on PR. If you
|
||||
# are working on the main repo and want to trigger
|
||||
# a CI build submit a draft PR.
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'src/**'
|
||||
- '.github/**'
|
||||
- 'cmake/**'
|
||||
- 'lib/**'
|
||||
- 'docs/Settings.md'
|
||||
- 'CMakeLists.txt'
|
||||
- '*.sh'
|
||||
|
||||
jobs:
|
||||
test:
|
||||
#needs: [build]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get update && sudo apt-get -y install ninja-build
|
||||
- name: Run Tests
|
||||
run: mkdir -p build && cd build && cmake -DTOOLCHAIN=none -G Ninja .. && ninja check
|
||||
@@ -0,0 +1,128 @@
|
||||
name: Parameter Group Version Check
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
branches:
|
||||
- maintenance-9.x
|
||||
- maintenance-10.x
|
||||
paths:
|
||||
- 'src/**/*.c'
|
||||
- 'src/**/*.h'
|
||||
|
||||
jobs:
|
||||
check-pg-versions:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- name: Checkout PR code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # Need full history to compare with base branch
|
||||
|
||||
- name: Fetch base branch
|
||||
run: |
|
||||
git fetch origin ${{ github.base_ref }}:refs/remotes/origin/${{ github.base_ref }}
|
||||
|
||||
- name: Run PG version check script
|
||||
id: pg_check
|
||||
run: |
|
||||
set +e # Don't fail the workflow, just capture exit code
|
||||
# Run script and capture output. Exit code 1 is expected for issues.
|
||||
# The output is captured and encoded to be passed between steps.
|
||||
output=$(bash .github/scripts/check-pg-versions.sh 2>&1)
|
||||
exit_code=$?
|
||||
echo "exit_code=${exit_code}" >> $GITHUB_OUTPUT
|
||||
echo "output<<EOF" >> $GITHUB_OUTPUT
|
||||
echo "$output" >> $GITHUB_OUTPUT
|
||||
echo "EOF" >> $GITHUB_OUTPUT
|
||||
env:
|
||||
GITHUB_BASE_REF: ${{ github.base_ref }}
|
||||
GITHUB_HEAD_REF: ${{ github.head_ref }}
|
||||
|
||||
- name: Post comment if issues found
|
||||
if: steps.pg_check.outputs.exit_code == '1'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
// Use the captured output from the previous step
|
||||
const output = '${{ steps.pg_check.outputs.output }}';
|
||||
let issuesContent = '';
|
||||
|
||||
try {
|
||||
// Extract issues from output (everything after the warning line)
|
||||
const lines = output.split('\n');
|
||||
let capturing = false;
|
||||
let issues = [];
|
||||
|
||||
for (const line of lines) {
|
||||
if (line.includes('###')) {
|
||||
capturing = true;
|
||||
}
|
||||
if (capturing) {
|
||||
issues.push(line);
|
||||
}
|
||||
}
|
||||
|
||||
issuesContent = issues.join('\n');
|
||||
} catch (err) {
|
||||
console.log('Error capturing issues:', err);
|
||||
issuesContent = '*Unable to extract detailed issues*';
|
||||
}
|
||||
|
||||
const commentBody = '## ⚠️ Parameter Group Version Check\n\n' +
|
||||
'The following parameter groups may need version increments:\n\n' +
|
||||
issuesContent + '\n\n' +
|
||||
'**Why this matters:**\n' +
|
||||
'Modifying PG struct fields without incrementing the version can cause settings corruption when users flash new firmware. The `pgLoad()` function validates versions and will use defaults if there\'s a mismatch, preventing corruption.\n\n' +
|
||||
'**When to increment the version:**\n' +
|
||||
'- ✅ Adding/removing fields\n' +
|
||||
'- ✅ Changing field types or sizes\n' +
|
||||
'- ✅ Reordering fields\n' +
|
||||
'- ✅ Adding/removing packing attributes\n' +
|
||||
'- ❌ Only changing default values in `PG_RESET_TEMPLATE`\n' +
|
||||
'- ❌ Only changing comments\n\n' +
|
||||
'**Reference:**\n' +
|
||||
'- [Parameter Group Documentation](../docs/development/parameter_groups/)\n' +
|
||||
'- Example: [PR #11236](https://github.com/iNavFlight/inav/pull/11236) (field removal requiring version increment)\n\n' +
|
||||
'---\n' +
|
||||
'*This is an automated check. False positives are possible. If you believe the version increment is not needed, please explain in a comment.*';
|
||||
|
||||
try {
|
||||
// Check if we already commented
|
||||
const { data: comments } = await github.rest.issues.listComments({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
});
|
||||
|
||||
const botComment = comments.find(comment =>
|
||||
comment.user.login === 'github-actions[bot]' &&
|
||||
comment.body.includes('Parameter Group Version Check')
|
||||
);
|
||||
|
||||
if (botComment) {
|
||||
// Update existing comment
|
||||
await github.rest.issues.updateComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
comment_id: botComment.id,
|
||||
body: commentBody
|
||||
});
|
||||
console.log('Updated existing PG version check comment');
|
||||
} else {
|
||||
// Post new comment
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: commentBody
|
||||
});
|
||||
console.log('Posted new PG version check comment');
|
||||
}
|
||||
} catch (err) {
|
||||
core.setFailed(`Failed to post comment: ${err}`);
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
name: PR Branch Suggestion
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened]
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
suggest-branch:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Suggest maintenance branch
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const comment = `### Branch Targeting Suggestion
|
||||
|
||||
You've targeted the \`master\` branch with this PR. Please consider if a version branch might be more appropriate:
|
||||
|
||||
- **\`maintenance-9.x\`** - If your change is backward-compatible and won't create compatibility issues between INAV firmware and Configurator 9.x versions. This will allow your PR to be included in the next 9.x release.
|
||||
|
||||
- **\`maintenance-10.x\`** - If your change introduces compatibility requirements between firmware and configurator that would break 9.x compatibility. This is for PRs which will be included in INAV 10.x
|
||||
|
||||
If \`master\` is the correct target for this change, no action is needed.
|
||||
|
||||
---
|
||||
*This is an automated suggestion to help route contributions to the appropriate branch.*`;
|
||||
|
||||
try {
|
||||
await github.rest.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: comment
|
||||
});
|
||||
} catch (err) {
|
||||
core.setFailed(`Failed to post suggestion comment: ${err}`);
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
name: PR Test Builds
|
||||
|
||||
# Runs after "Build firmware" completes. Uses workflow_run (rather than
|
||||
# pull_request directly) so that secrets are available even for PRs from forks.
|
||||
#
|
||||
# Requires a repository secret PR_BUILDS_TOKEN with Contents: write access
|
||||
# to iNavFlight/pr-test-builds (fine-grained PAT or classic PAT with repo scope).
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["Build firmware"]
|
||||
types: [completed]
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
# Only act on pull_request-triggered runs that succeeded.
|
||||
if: >
|
||||
github.event.workflow_run.event == 'pull_request' &&
|
||||
github.event.workflow_run.conclusion == 'success'
|
||||
# Prevent concurrent runs for the same PR branch racing on the
|
||||
# release delete/create cycle.
|
||||
concurrency:
|
||||
group: pr-test-build-${{ github.event.workflow_run.head_repository.full_name }}-${{ github.event.workflow_run.head_branch }}
|
||||
cancel-in-progress: true
|
||||
permissions:
|
||||
actions: read # to download artifacts from the triggering workflow run
|
||||
issues: write # github.rest.issues.* endpoints used to post PR comments
|
||||
pull-requests: write # to post the PR comment
|
||||
|
||||
steps:
|
||||
- name: Download PR number
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: pr-number
|
||||
run-id: ${{ github.event.workflow_run.id }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Read PR number
|
||||
id: pr
|
||||
run: |
|
||||
PR_NUM=$(tr -dc '0-9' < pr_number.txt)
|
||||
if [ -z "$PR_NUM" ]; then
|
||||
echo "::error::Invalid PR number in artifact"
|
||||
exit 1
|
||||
fi
|
||||
echo "number=${PR_NUM}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Download firmware artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: matrix-inav-*
|
||||
merge-multiple: true
|
||||
path: hexes
|
||||
run-id: ${{ github.event.workflow_run.id }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Get build info
|
||||
id: info
|
||||
run: |
|
||||
COUNT=$(find hexes -name '*.hex' -type f | wc -l)
|
||||
if [ "$COUNT" -eq 0 ]; then
|
||||
echo "::error::No .hex files found in downloaded artifacts"
|
||||
exit 1
|
||||
fi
|
||||
echo "count=${COUNT}" >> $GITHUB_OUTPUT
|
||||
echo "short_sha=$(echo '${{ github.event.workflow_run.head_sha }}' | cut -c1-7)" >> $GITHUB_OUTPUT
|
||||
|
||||
# Delete the previous release for this PR (if any) so assets are replaced
|
||||
# cleanly on each new commit. --cleanup-tag removes the old tag so it is
|
||||
# recreated fresh pointing to the new commit.
|
||||
- name: Delete existing PR release
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.PR_BUILDS_TOKEN }}
|
||||
run: |
|
||||
gh release delete "pr-${{ steps.pr.outputs.number }}" \
|
||||
--repo iNavFlight/pr-test-builds --cleanup-tag --yes 2>/dev/null || true
|
||||
|
||||
- name: Create PR release
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.PR_BUILDS_TOKEN }}
|
||||
PR_NUMBER: ${{ steps.pr.outputs.number }}
|
||||
SHORT_SHA: ${{ steps.info.outputs.short_sha }}
|
||||
HEX_COUNT: ${{ steps.info.outputs.count }}
|
||||
REPO: ${{ github.repository }}
|
||||
run: |
|
||||
PR_URL="https://github.com/${REPO}/pull/${PR_NUMBER}"
|
||||
printf '%s\n\n%s\n\n%s\n' \
|
||||
"Test build for [PR #${PR_NUMBER}](${PR_URL}) — commit \`${SHORT_SHA}\`" \
|
||||
"**${HEX_COUNT} targets built.** Find your board's \`.hex\` file by name (e.g. \`MATEKF405SE.hex\`)." \
|
||||
"> Development build for testing only. Use Full Chip Erase when flashing." \
|
||||
> release-notes.md
|
||||
gh release create "pr-${PR_NUMBER}" hexes/*.hex \
|
||||
--repo iNavFlight/pr-test-builds \
|
||||
--prerelease \
|
||||
--title "PR #${PR_NUMBER} (${SHORT_SHA})" \
|
||||
--notes-file release-notes.md
|
||||
|
||||
- name: Post or update PR comment
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
PR_NUMBER: ${{ steps.pr.outputs.number }}
|
||||
SHORT_SHA: ${{ steps.info.outputs.short_sha }}
|
||||
HEX_COUNT: ${{ steps.info.outputs.count }}
|
||||
with:
|
||||
script: |
|
||||
const prNumber = parseInt(process.env.PR_NUMBER, 10);
|
||||
if (isNaN(prNumber)) throw new Error(`Invalid PR number: ${process.env.PR_NUMBER}`);
|
||||
const shortSha = process.env.SHORT_SHA;
|
||||
const count = process.env.HEX_COUNT;
|
||||
const releaseUrl = `https://github.com/iNavFlight/pr-test-builds/releases/tag/pr-${prNumber}`;
|
||||
|
||||
const body = [
|
||||
'<!-- pr-test-build -->',
|
||||
'**Test firmware build ready** — commit `' + shortSha + '`',
|
||||
'',
|
||||
`[Download firmware for PR #${prNumber}](${releaseUrl})`,
|
||||
'',
|
||||
`${count} targets built. Find your board's \`.hex\` file by name on that page ` +
|
||||
'(e.g. `MATEKF405SE.hex`). Files are individually downloadable — no GitHub login required.',
|
||||
'',
|
||||
'> Development build for testing only. Use Full Chip Erase when flashing.',
|
||||
].join('\n');
|
||||
|
||||
const comments = await github.paginate(
|
||||
github.rest.issues.listComments,
|
||||
{
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: prNumber,
|
||||
}
|
||||
);
|
||||
|
||||
const existing = comments.find(c =>
|
||||
c.user.type === 'Bot' && c.body.includes('<!-- pr-test-build -->')
|
||||
);
|
||||
|
||||
if (existing) {
|
||||
await github.rest.issues.updateComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
comment_id: existing.id,
|
||||
body,
|
||||
});
|
||||
} else {
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: prNumber,
|
||||
body,
|
||||
});
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
*.o
|
||||
.DS_Store
|
||||
*~
|
||||
*.swp
|
||||
*.uvopt
|
||||
*.dep
|
||||
*.bak
|
||||
*.uvgui.*
|
||||
*.ubx
|
||||
.project
|
||||
.settings
|
||||
.cproject
|
||||
.cache/
|
||||
__pycache__
|
||||
startup_stm32f10x_md_gcc.s
|
||||
.vagrant/
|
||||
#.vscode/
|
||||
cov-int*
|
||||
/build/
|
||||
/build_SITL/
|
||||
/[hs]itl/
|
||||
/ninja/
|
||||
/obj/
|
||||
/patches/
|
||||
/tools/
|
||||
/downloads/
|
||||
/debug/
|
||||
/release/
|
||||
/*_SITL/
|
||||
|
||||
# script-generated files
|
||||
docs/Manual.pdf
|
||||
README.pdf
|
||||
|
||||
# build generated files
|
||||
/settings.json
|
||||
|
||||
# local changes only
|
||||
make/local.mk
|
||||
launch.json
|
||||
.vscode/tasks.json
|
||||
.vscode/c_cpp_properties.json
|
||||
|
||||
/cmake-build-debug/
|
||||
|
||||
# Assitnow token and files for test script
|
||||
tokens.yaml
|
||||
*.ubx
|
||||
|
||||
# Local development files
|
||||
.semgrepignore
|
||||
build_sitl/
|
||||
Executable
+71
@@ -0,0 +1,71 @@
|
||||
#!/bin/bash
|
||||
|
||||
REVISION=$(git rev-parse --short HEAD)
|
||||
BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
||||
REVISION=$(git rev-parse --short HEAD)
|
||||
LAST_COMMIT_DATE=$(git log -1 --date=short --format="%cd")
|
||||
TARGET_FILE=obj/cleanflight_${TARGET}
|
||||
TRAVIS_REPO_SLUG=${TRAVIS_REPO_SLUG:=$USER/undefined}
|
||||
BUILDNAME=${BUILDNAME:=travis}
|
||||
TRAVIS_BUILD_NUMBER=${TRAVIS_BUILD_NUMBER:=undefined}
|
||||
|
||||
CURL_BASEOPTS=(
|
||||
"--retry" "10"
|
||||
"--retry-max-time" "120" )
|
||||
|
||||
CURL_PUB_BASEOPTS=(
|
||||
"--form" "revision=${REVISION}"
|
||||
"--form" "branch=${BRANCH}"
|
||||
"--form" "travis_build_number=${TRAVIS_BUILD_NUMBER}"
|
||||
"--form" "last_commit_date=${LAST_COMMIT_DATE}"
|
||||
"--form" "github_repo=${TRAVIS_REPO_SLUG}"
|
||||
"--form" "build_name=${BUILDNAME}" )
|
||||
|
||||
# A hacky way of running the unit tests at the same time as the normal builds.
|
||||
if [ $RUNTESTS ] ; then
|
||||
cd ./src/test && make test
|
||||
# A hacky way of building the docs at the same time as the normal builds.
|
||||
elif [ $PUBLISHDOCS ] ; then
|
||||
if [ $PUBLISH_URL ] ; then
|
||||
|
||||
# Patch Gimli to fix underscores_inside_words
|
||||
curl -L "${CURL_BASEOPTS[@]}" https://github.com/walle/gimli/archive/v0.5.9.tar.gz | tar zxf -
|
||||
|
||||
sed -i 's/).render(/, :no_intra_emphasis => true).render(/' gimli-0.5.9/ext/github_markup.rb
|
||||
|
||||
cd gimli-0.5.9/
|
||||
gem build gimli.gemspec && gem install gimli
|
||||
cd ../
|
||||
|
||||
./build_docs.sh
|
||||
|
||||
curl -k "${CURL_BASEOPTS[@]}" "${CURL_PUB_BASEOPTS[@]}" --form "manual=@docs/Manual.pdf" ${PUBLISH_URL} || true
|
||||
fi
|
||||
elif [ $PUBLISHMETA ] ; then
|
||||
if [ $PUBLISH_URL ] ; then
|
||||
RECENT_COMMITS=$(git shortlog -n25)
|
||||
curl -k "${CURL_BASEOPTS[@]}" "${CURL_PUB_BASEOPTS[@]}" --form "recent_commits=${RECENT_COMMITS}" ${PUBLISH_URL} || true
|
||||
fi
|
||||
elif [ $TARGET ] ; then
|
||||
if [ $PUBLISH_URL ] ; then
|
||||
make -j2
|
||||
if [ -f ${TARGET_FILE}.bin ] ; then
|
||||
TARGET_FILE=${TARGET_FILE}.bin
|
||||
elif [ -f ${TARGET_FILE}.hex ] ; then
|
||||
TARGET_FILE=${TARGET_FILE}.hex
|
||||
else
|
||||
echo "build artifact (hex or bin) for ${TARGET_FILE} not found, aborting";
|
||||
exit 1
|
||||
fi
|
||||
|
||||
curl -k "${CURL_BASEOPTS[@]}" "${CURL_PUB_BASEOPTS[@]}" --form "file=@${TARGET_FILE}" ${PUBLISH_URL} || true
|
||||
exit 0;
|
||||
else
|
||||
make -j2 $MAKEFILE
|
||||
fi
|
||||
elif [ $GOAL ] ; then
|
||||
make V=0 $GOAL
|
||||
else
|
||||
# No target specified, build all with very low verbosity.
|
||||
make V=0 all
|
||||
fi
|
||||
Executable
+58
@@ -0,0 +1,58 @@
|
||||
env:
|
||||
# Specify the main Mafile supported goals.
|
||||
- GOAL=test
|
||||
- GOAL=targets-group-1
|
||||
- GOAL=targets-group-2
|
||||
- GOAL=targets-group-3
|
||||
- GOAL=targets-group-4
|
||||
- GOAL=targets-group-5
|
||||
- GOAL=targets-group-6
|
||||
- GOAL=targets-group-7
|
||||
- GOAL=targets-group-8
|
||||
- GOAL=targets-group-rest
|
||||
|
||||
# use new docker environment
|
||||
sudo: false
|
||||
|
||||
git:
|
||||
depth: 5
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- build-essential
|
||||
- git
|
||||
- libc6-i386
|
||||
- time
|
||||
|
||||
# We use cpp for unit tests, and c for the main project.
|
||||
language: cpp
|
||||
compiler: clang
|
||||
|
||||
before_install:
|
||||
|
||||
install:
|
||||
- make arm_sdk_install
|
||||
|
||||
before_script:
|
||||
- make arm_sdk_version
|
||||
- clang --version
|
||||
- clang++ --version
|
||||
|
||||
script: ./.travis.sh
|
||||
|
||||
cache:
|
||||
timeout: 1000
|
||||
directories:
|
||||
- downloads
|
||||
- tools
|
||||
|
||||
notifications:
|
||||
#slack: inavflight:UWRoWFJ4cbbpHXT8HJJlAPXa
|
||||
email: false
|
||||
webhooks:
|
||||
urls:
|
||||
- https://webhooks.gitter.im/e/34e795df229478ac3a3b
|
||||
on_success: always
|
||||
on_failure: always
|
||||
on_start: never
|
||||
@@ -0,0 +1,10 @@
|
||||
filetype on
|
||||
filetype indent on
|
||||
|
||||
set expandtab
|
||||
set bs=2
|
||||
set sw=4
|
||||
set ts=4
|
||||
syn on
|
||||
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Linux",
|
||||
"includePath": [
|
||||
"${workspaceRoot}",
|
||||
"${workspaceRoot}/src/main/**"
|
||||
],
|
||||
"browse": {
|
||||
"limitSymbolsToIncludedHeaders": false,
|
||||
"path": [
|
||||
"${workspaceRoot}/**"
|
||||
]
|
||||
},
|
||||
"intelliSenseMode": "msvc-x64",
|
||||
"cStandard": "c11",
|
||||
"cppStandard": "c++17",
|
||||
"defines": [
|
||||
"USE_OSD",
|
||||
"USE_GYRO_NOTCH_1",
|
||||
"USE_GYRO_NOTCH_2",
|
||||
"USE_DTERM_NOTCH",
|
||||
"USE_ACC_NOTCH",
|
||||
"USE_GYRO_BIQUAD_RC_FIR2",
|
||||
"USE_D_BOOST",
|
||||
"USE_SERIALSHOT",
|
||||
"USE_ANTIGRAVITY",
|
||||
"USE_ASYNC_GYRO_PROCESSING",
|
||||
"USE_RPM_FILTER",
|
||||
"USE_GLOBAL_FUNCTIONS",
|
||||
"USE_DYNAMIC_FILTERS",
|
||||
"USE_DSHOT",
|
||||
"FLASH_SIZE 480",
|
||||
"USE_I2C_IO_EXPANDER",
|
||||
"USE_PCF8574",
|
||||
"USE_ESC_SENSOR",
|
||||
"USE_PROGRAMMING_FRAMEWORK",
|
||||
"USE_SERIALRX_GHST",
|
||||
"USE_TELEMETRY_GHST",
|
||||
"USE_CMS",
|
||||
"USE_DJI_HD_OSD",
|
||||
"USE_GYRO_KALMAN",
|
||||
"USE_RANGEFINDER",
|
||||
"USE_RATE_DYNAMICS",
|
||||
"USE_SMITH_PREDICTOR",
|
||||
"USE_ALPHA_BETA_GAMMA_FILTER",
|
||||
"USE_MAG_VCM5883",
|
||||
"USE_TELEMETRY_JETIEXBUS",
|
||||
"USE_NAV",
|
||||
"USE_SDCARD_SDIO",
|
||||
"USE_SDCARD",
|
||||
"USE_Q_TUNE",
|
||||
"USE_GYRO_FFT_FILTER",
|
||||
"USE_BARO_DPS310",
|
||||
"USE_ADAPTIVE_FILTER",
|
||||
"MCU_FLASH_SIZE 1024"
|
||||
],
|
||||
"configurationProvider": "ms-vscode.cmake-tools"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"chrono": "c",
|
||||
"cmath": "c",
|
||||
"ranges": "c",
|
||||
"navigation.h": "c",
|
||||
"rth_trackback.h": "c",
|
||||
"platform.h": "c",
|
||||
"timer.h": "c",
|
||||
"bus.h": "c",
|
||||
"io.h": "c",
|
||||
"fc_core.h": "c"
|
||||
},
|
||||
"editor.tabSize": 4,
|
||||
"editor.insertSpaces": true,
|
||||
"editor.detectIndentation": false,
|
||||
"editor.expandTabs": true,
|
||||
"C_Cpp.clang_format_fallbackStyle": "{ BasedOnStyle: Google, IndentWidth: 4, BreakBeforeBraces: Mozilla }"
|
||||
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Build AOCODARCH7DUAL",
|
||||
"type": "shell",
|
||||
"command": "make AOCODARCH7DUAL",
|
||||
"group": "build",
|
||||
"problemMatcher": [],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/build"
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Build AOCODARCH7DUAL",
|
||||
"type": "shell",
|
||||
"command": "make AOCODARCH7DUAL",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"problemMatcher": [],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/build"
|
||||
}
|
||||
}
|
||||
,
|
||||
{
|
||||
"label": "CMAKE Update",
|
||||
"type": "shell",
|
||||
"command": "cmake ..",
|
||||
"group": "build",
|
||||
"problemMatcher": [],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/build"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,461 @@
|
||||
# AGENT.md - Guide for AI Agents Working with INAV
|
||||
|
||||
## Project Overview
|
||||
|
||||
**INAV** is a navigation-capable flight controller firmware for multirotor, fixed-wing, and other RC vehicles. It is a community-driven project written primarily in C (C99/C11 standard) with support for STM32 F4, F7, H7, and AT32 microcontrollers.
|
||||
|
||||
### Key Characteristics
|
||||
- **Type**: Embedded firmware for flight controllers
|
||||
- **Language**: C (C99/C11), with some C++ for unit tests
|
||||
- **Build System**: CMake (version 3.13+)
|
||||
- **License**: GNU GPL v3
|
||||
- **Version**: 9.0.1 (as of this writing)
|
||||
- **Codebase History**: Evolved from Cleanflight/Baseflight
|
||||
|
||||
## Architecture and Structure
|
||||
|
||||
### Core Components
|
||||
|
||||
The INAV codebase is organized into the following major subsystems:
|
||||
|
||||
1. **Flight Control (`fc/`)**: Core flight controller logic, initialization, MSP protocol handling
|
||||
2. **Sensors (`sensors/`)**: Gyro, accelerometer, compass, barometer, GPS, rangefinder, pitot tube
|
||||
3. **Flight (`flight/`)**: PID controllers, mixers, altitude hold, position hold, navigation
|
||||
4. **Navigation (`navigation/`)**: Waypoint missions, RTH (Return to Home), position hold
|
||||
5. **Drivers (`drivers/`)**: Hardware abstraction layer for MCU peripherals (SPI, I2C, UART, timers, etc.)
|
||||
6. **IO (`io/`)**: Serial communication, OSD, LED strips, telemetry
|
||||
7. **RX (`rx/`)**: Radio receiver protocols (CRSF, SBUS, IBUS, etc.)
|
||||
8. **Scheduler (`scheduler/`)**: Real-time task scheduling
|
||||
9. **Configuration (`config/`)**: Parameter groups, EEPROM storage, settings management
|
||||
10. **MSP (`msp/`)**: MultiWii Serial Protocol implementation
|
||||
11. **Telemetry (`telemetry/`)**: SmartPort, FPort, MAVLink, LTM, CRSF telemetry
|
||||
12. **Blackbox (`blackbox/`)**: Flight data recorder
|
||||
13. **Programming (`programming/`)**: Logic conditions and global functions for in-flight programming
|
||||
|
||||
### Directory Structure
|
||||
|
||||
```
|
||||
/src/main/ - Main source code
|
||||
├── build/ - Build configuration and macros
|
||||
├── common/ - Common utilities (math, filters, utils)
|
||||
├── config/ - Configuration system (parameter groups)
|
||||
├── drivers/ - Hardware drivers (MCU-specific)
|
||||
├── fc/ - Flight controller core
|
||||
├── flight/ - Flight control algorithms
|
||||
├── io/ - Input/output (serial, OSD, LED)
|
||||
├── msp/ - MSP protocol
|
||||
├── navigation/ - Navigation and autopilot
|
||||
├── rx/ - Radio receiver protocols
|
||||
├── sensors/ - Sensor drivers and processing
|
||||
├── scheduler/ - Task scheduler
|
||||
├── telemetry/ - Telemetry protocols
|
||||
└── target/ - Board-specific configurations
|
||||
|
||||
/docs/ - Documentation
|
||||
└── development/ - Developer documentation
|
||||
|
||||
/cmake/ - CMake build scripts
|
||||
/lib/ - External libraries
|
||||
/tools/ - Build and utility tools
|
||||
```
|
||||
|
||||
## Coding Conventions
|
||||
|
||||
### Naming Conventions
|
||||
|
||||
1. **Types**: Use `_t` suffix for typedef'd types: `gyroConfig_t`, `pidController_t`
|
||||
2. **Enums**: Use `_e` suffix for enum types: `portMode_e`, `cfTaskPriority_e`
|
||||
3. **Functions**: Use camelCase with verb-phrase names: `gyroInit()`, `deleteAllPages()`
|
||||
4. **Variables**: Use camelCase nouns, avoid noise words like "data" or "info"
|
||||
5. **Booleans**: Question format: `isOkToArm()`, `canNavigate()`
|
||||
6. **Constants**: Upper case with underscores: `MAX_GYRO_COUNT`
|
||||
7. **Macros**: Upper case with underscores: `FASTRAM`, `STATIC_UNIT_TESTED`
|
||||
|
||||
### Code Style
|
||||
|
||||
- **Indentation**: 4 spaces (no tabs)
|
||||
- **Braces**: K&R style (opening brace on same line, except for functions)
|
||||
- **Line Length**: Keep reasonable (typically under 120 characters)
|
||||
- **Comments**: Explain WHY, not WHAT. Document variables at declaration, not at extern usage
|
||||
- **Header Guards**: Use `#pragma once` (modern convention used throughout codebase)
|
||||
|
||||
### Memory Attributes
|
||||
|
||||
INAV uses special memory attributes for performance-critical code on resource-constrained MCUs:
|
||||
|
||||
```c
|
||||
FASTRAM // Fast RAM section (aligned)
|
||||
EXTENDED_FASTRAM // Extended fast RAM (STM32F4/F7 only)
|
||||
DMA_RAM // DMA-accessible RAM (STM32H7, AT32F43x)
|
||||
SLOW_RAM // Slower external RAM - deprecated, o not use
|
||||
STATIC_FASTRAM // Static variable in fast RAM
|
||||
STATIC_FASTRAM_UNIT_TESTED // Static fast RAM variable visible in unit tests
|
||||
```
|
||||
|
||||
### Test Visibility Macros
|
||||
|
||||
```c
|
||||
STATIC_UNIT_TESTED // static in production, visible in unit tests
|
||||
STATIC_INLINE_UNIT_TESTED // static inline in production, visible in tests
|
||||
INLINE_UNIT_TESTED // inline in production, visible in tests
|
||||
UNIT_TESTED // Always visible (no storage class)
|
||||
```
|
||||
|
||||
## Build System
|
||||
|
||||
### CMake Build Process
|
||||
|
||||
INAV uses CMake with custom target definition functions:
|
||||
|
||||
1. **Target Definition**: Each board has a `target.h` and optionally `CMakeLists.txt`
|
||||
2. **Hardware Function**: `target_stm32f405xg(NAME optional_params)`
|
||||
3. **Build Directory**: Always use out-of-source builds in `/build` directory
|
||||
|
||||
### Building a Target
|
||||
|
||||
```bash
|
||||
# From workspace root
|
||||
cd build
|
||||
cmake ..
|
||||
make MATEKF722SE # Build specific target
|
||||
make # Build all targets
|
||||
```
|
||||
|
||||
### Target Configuration
|
||||
|
||||
Targets are defined in `/src/main/target/TARGETNAME/`:
|
||||
- `target.h`: Hardware pin definitions, feature enables, MCU configuration
|
||||
- `target.c`: Board-specific initialization code
|
||||
- `CMakeLists.txt`: Build configuration (optional)
|
||||
|
||||
Example target definition:
|
||||
```c
|
||||
#define TARGET_BOARD_IDENTIFIER "MF7S"
|
||||
#define LED0 PA14
|
||||
#define BEEPER PC13
|
||||
#define USE_SPI
|
||||
#define USE_SPI_DEVICE_1
|
||||
#define SPI1_SCK_PIN PA5
|
||||
```
|
||||
|
||||
### Conditional Compilation
|
||||
|
||||
Feature flags control code inclusion:
|
||||
```c
|
||||
#ifdef USE_GPS
|
||||
// GPS code
|
||||
#endif
|
||||
|
||||
#if defined(STM32F4)
|
||||
// F4-specific code
|
||||
#elif defined(STM32F7)
|
||||
// F7-specific code
|
||||
#endif
|
||||
```
|
||||
|
||||
## Key Concepts
|
||||
|
||||
### Parameter Groups (PG)
|
||||
|
||||
INAV uses a sophisticated configuration system called "Parameter Groups" for persistent storage:
|
||||
|
||||
```c
|
||||
// Define a configuration structure
|
||||
typedef struct {
|
||||
uint8_t gyro_lpf_hz;
|
||||
uint16_t gyro_kalman_q;
|
||||
// ...
|
||||
} gyroConfig_t;
|
||||
|
||||
// Register with reset template
|
||||
PG_REGISTER_WITH_RESET_TEMPLATE(gyroConfig_t, gyroConfig, PG_GYRO_CONFIG, 12);
|
||||
|
||||
// Define default values
|
||||
PG_RESET_TEMPLATE(gyroConfig_t, gyroConfig,
|
||||
.gyro_lpf_hz = 60,
|
||||
.gyro_kalman_q = 200,
|
||||
// ...
|
||||
);
|
||||
|
||||
// Access in code
|
||||
gyroConfig()->gyro_lpf_hz
|
||||
```
|
||||
|
||||
**Key Functions:**
|
||||
- `PG_REGISTER_WITH_RESET_TEMPLATE()`: Register with static defaults
|
||||
- `PG_REGISTER_WITH_RESET_FN()`: Register with function-based initialization
|
||||
- `PG_REGISTER_ARRAY()`: For arrays of configuration items
|
||||
- Parameter group IDs are in `config/parameter_group_ids.h`
|
||||
|
||||
### Scheduler
|
||||
|
||||
INAV uses a priority-based cooperative task scheduler:
|
||||
|
||||
```c
|
||||
typedef enum {
|
||||
TASK_PRIORITY_IDLE = 0,
|
||||
TASK_PRIORITY_LOW = 1,
|
||||
TASK_PRIORITY_MEDIUM = 3,
|
||||
TASK_PRIORITY_HIGH = 5,
|
||||
TASK_PRIORITY_REALTIME = 18,
|
||||
} cfTaskPriority_e;
|
||||
```
|
||||
|
||||
Tasks are defined in `fc/fc_tasks.c` with priority and desired execution period.
|
||||
|
||||
### Sensors and Calibration
|
||||
|
||||
Sensors use a common pattern:
|
||||
1. **Detection**: Auto-detect hardware at boot (`gyroDetect()`, `baroDetect()`)
|
||||
2. **Initialization**: Configure sensor parameters
|
||||
3. **Calibration**: Zero-offset calibration (gyro, accelerometer)
|
||||
4. **Data Processing**: Apply calibration, alignment, and filtering
|
||||
|
||||
### Flight Control Loop
|
||||
|
||||
The main control loop follows this pattern:
|
||||
1. **Gyro Task** (highest priority): Read gyro, apply filters
|
||||
2. **PID Task**: Calculate PID corrections
|
||||
3. **RX Task**: Process radio input
|
||||
4. **Other Tasks**: Sensors, telemetry, OSD, etc. (lower priority)
|
||||
|
||||
### MSP Protocol
|
||||
|
||||
MultiWii Serial Protocol is used for configuration and telemetry:
|
||||
- Request/response model
|
||||
- Message types defined in `msp/msp_protocol.h`
|
||||
- Handlers in `fc/fc_msp.c`
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Hardware Abstraction
|
||||
|
||||
INAV abstracts hardware through resource allocation:
|
||||
|
||||
```c
|
||||
// IO pins
|
||||
IO_t pin = IOGetByTag(IO_TAG(PA5));
|
||||
IOInit(pin, OWNER_SPI, RESOURCE_SPI_SCK, 1);
|
||||
|
||||
// Timers
|
||||
const timerHardware_t *timer = timerGetByTag(IO_TAG(PA8), TIM_USE_ANY);
|
||||
|
||||
// DMA
|
||||
dmaIdentifier_e dma = dmaGetIdentifier(DMA1_Stream0);
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
|
||||
INAV uses several approaches:
|
||||
1. **Return codes**: Boolean success/failure or error enums
|
||||
2. **Diagnostics**: `sensors/diagnostics.c` for sensor health
|
||||
3. **Status indicators**: Beeper codes, LED patterns for user feedback
|
||||
4. **Logging**: CLI-based logging system
|
||||
|
||||
### Filter Chains
|
||||
|
||||
Sensor data typically goes through multiple filtering stages:
|
||||
|
||||
```c
|
||||
// Low-pass filters
|
||||
gyroLpfApplyFn = lowpassFilterGetApplyFn(filterType);
|
||||
gyroLpfApplyFn(&gyroLpfState[axis], sample);
|
||||
|
||||
// Notch filters (for dynamic filtering)
|
||||
for (int i = 0; i < dynamicNotchCount; i++) {
|
||||
sample = biquadFilterApply(¬chFilter[i], sample);
|
||||
}
|
||||
```
|
||||
|
||||
### Board Alignment
|
||||
|
||||
All sensors go through board alignment transforms to correct for mounting orientation:
|
||||
|
||||
```c
|
||||
// Apply board alignment rotation matrix
|
||||
applySensorAlignment(gyroData, gyroData, gyroAlign);
|
||||
```
|
||||
|
||||
### SITL (Software In The Loop)
|
||||
|
||||
INAV can be compiled for host system simulation:
|
||||
```bash
|
||||
cmake -DSITL=ON ..
|
||||
make
|
||||
```
|
||||
|
||||
## Development Workflow
|
||||
|
||||
### Branching Strategy
|
||||
|
||||
- **`maintenance-X.x`**: Current version development (e.g., `maintenance-9.x`)
|
||||
- **`maintenance-Y.x`**: Next major version (e.g., `maintenance-10.x`)
|
||||
- **`master`**: Tracks current version, receives merges from maintenance branches
|
||||
|
||||
### Pull Request Guidelines
|
||||
|
||||
1. **Target Branch**:
|
||||
- Bug fixes and backward-compatible features → current maintenance branch
|
||||
- Breaking changes → next major version maintenance branch
|
||||
- **Never** target `master` directly
|
||||
|
||||
2. **Keep PRs Focused**: One feature/fix per PR
|
||||
|
||||
3. **Code Quality**:
|
||||
- Follow existing code style
|
||||
- Add unit tests where possible
|
||||
- Update documentation in `/docs`
|
||||
- Test on real hardware when possible
|
||||
|
||||
4. **Commit Messages**: Clear, descriptive messages
|
||||
|
||||
### Important Files to Check
|
||||
|
||||
Before making changes, review:
|
||||
- `docs/development/Development.md` - Development principles
|
||||
- `docs/development/Contributing.md` - Contribution guidelines
|
||||
- Target-specific files in `/src/main/target/`
|
||||
|
||||
## Important Files and Directories
|
||||
|
||||
### Configuration Files
|
||||
|
||||
- `platform.h`: Platform-specific includes and defines
|
||||
- `target.h`: Board-specific hardware configuration
|
||||
- `config/parameter_group.h`: Parameter group system
|
||||
- `config/parameter_group_ids.h`: PG ID definitions
|
||||
- `fc/settings.yaml`: CLI settings definitions
|
||||
|
||||
### Core Flight Control
|
||||
|
||||
- `fc/fc_core.c`: Main flight control loop
|
||||
- `fc/fc_init.c`: System initialization
|
||||
- `fc/fc_tasks.c`: Task scheduler configuration
|
||||
- `flight/pid.c`: PID controller implementation
|
||||
- `flight/mixer.c`: Motor mixing
|
||||
|
||||
### Key Headers
|
||||
|
||||
- `build/build_config.h`: Build-time configuration macros
|
||||
- `common/axis.h`: Axis definitions (X, Y, Z, ROLL, PITCH, YAW)
|
||||
- `common/maths.h`: Math utilities and constants
|
||||
- `common/filter.h`: Digital filter implementations
|
||||
- `drivers/accgyro/accgyro.h`: Gyro/accelerometer interface
|
||||
|
||||
## AI Agent Guidelines
|
||||
|
||||
### When Adding Features
|
||||
|
||||
1. **Understand the Module**: Read related files in the same directory
|
||||
2. **Check for Similar Code**: Search for similar features to maintain consistency
|
||||
3. **Follow Parameter Group Pattern**: New settings should use PG system
|
||||
4. **Add to Scheduler**: New periodic tasks go in `fc/fc_tasks.c`
|
||||
5. **Update Documentation**: Add/update files in `/docs`
|
||||
6. **Consider Target Support**: Use `#ifdef USE_FEATURE` for optional features
|
||||
7. **Generate CLI setting docs**: Remember to inform user to run `python src/utils/update_cli_docs.py`
|
||||
8. **Follow conding standard**: Follow MISRA C rules
|
||||
9. **Increase Paremeterer Group Version**: When changing PG structure, increase version corresponding in `PG_REGISTER`, `PG_REGISTER_WITH_RESET_FN`, `PG_REGISTER_WITH_RESET_TEMPLATE`, `PG_REGISTER_ARRAY` or `PG_REGISTER_ARRAY_WITH_RESET_FN`
|
||||
|
||||
### When Fixing Bugs
|
||||
|
||||
1. **Review Recent Changes**: Check git history for related modifications
|
||||
2. **Test Signal Path**: For sensor issues, trace from hardware through filters to consumer
|
||||
3. **Consider All Platforms**: STM32F4, F7, H7, and AT32 may behave differently
|
||||
4. **Check Memory Usage**: Embedded system has limited RAM/flash
|
||||
|
||||
### When Refactoring
|
||||
|
||||
1. **Maintain API Compatibility**: Unless targeting next major version
|
||||
2. **Preserve Unit Tests**: Update tests to match refactored code
|
||||
3. **Update Documentation**: Keep docs synchronized with code changes
|
||||
4. **Consider Performance**: Profile on target hardware, not just host compilation
|
||||
5. **Check All Callers**: Use grep/search to find all usage sites
|
||||
|
||||
### Common Pitfalls to Avoid
|
||||
|
||||
1. **Don't Ignore Memory Attributes**: FASTRAM placement affects real-time performance
|
||||
2. **Don't Break Parameter Groups**: Changing PG structure requires version bump
|
||||
3. **Don't Assume Hardware**: Always check feature flags (`#ifdef USE_GPS`)
|
||||
4. **Don't Break MSP**: Changes to MSP protocol affect configurator compatibility
|
||||
5. **Don't Commit Wrong Branch**: Target maintenance branch, not master
|
||||
6. **Don't Skip Documentation**: Code without docs increases support burden
|
||||
7. **Don't Hardcode Values**: Use parameter groups for configurable values
|
||||
|
||||
### Searching the Codebase
|
||||
|
||||
**Find definitions:**
|
||||
```bash
|
||||
grep -r "typedef.*_t" src/main/ # Find all type definitions
|
||||
grep -r "PG_REGISTER" src/main/ # Find parameter groups
|
||||
grep -r "TASK_" src/main/ # Find scheduled tasks
|
||||
```
|
||||
|
||||
**Find usage:**
|
||||
```bash
|
||||
grep -r "functionName" src/main/
|
||||
grep -r "USE_GPS" src/main/target/ # Feature support by target
|
||||
```
|
||||
|
||||
**Find similar code:**
|
||||
- Look in the same directory first
|
||||
- Check for similar sensor/peripheral implementations
|
||||
- Review git history: `git log --all --oneline --grep="keyword"`
|
||||
|
||||
### Understanding Control Flow
|
||||
|
||||
1. **Startup**: `main.c` → `fc_init.c:init()` → `fc_tasks.c:tasksInit()`
|
||||
2. **Main Loop**: `scheduler.c:scheduler()` executes tasks by priority
|
||||
3. **Critical Path**: Gyro → PID → Mixer → Motors (highest priority)
|
||||
4. **Configuration**: CLI/MSP → Parameter Groups → EEPROM
|
||||
|
||||
### Cross-Platform Considerations
|
||||
|
||||
Different MCU families have different characteristics:
|
||||
|
||||
- **STM32F4**: Most common, 84-168 MHz, FPU, no cache
|
||||
- **STM32F7**: Faster, 216 MHz, FPU, I/D cache, requires cache management
|
||||
- **STM32H7**: Fastest, 480 MHz, more RAM, complex memory architecture (DTCM, SRAM)
|
||||
- **AT32F43x**: Chinese MCU, STM32F4-compatible, different peripherals
|
||||
|
||||
Always test on target or use `#if defined()` guards for MCU-specific code.
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### File Naming Patterns
|
||||
|
||||
- `*_config.h`: Configuration structures (usually with PG)
|
||||
- `*_impl.h`: Implementation headers (MCU-specific)
|
||||
- `*_hal.h`: Hardware abstraction layer
|
||||
- `accgyro_*.c`: Gyro/accelerometer drivers
|
||||
- `bus_*.c`: Communication bus drivers (SPI, I2C)
|
||||
|
||||
### Common Abbreviations
|
||||
|
||||
- **FC**: Flight Controller
|
||||
- **PG**: Parameter Group
|
||||
- **MSP**: MultiWii Serial Protocol
|
||||
- **CLI**: Command Line Interface
|
||||
- **OSD**: On-Screen Display
|
||||
- **RTH**: Return to Home
|
||||
- **PID**: Proportional-Integral-Derivative (controller)
|
||||
- **IMU**: Inertial Measurement Unit (gyro + accel)
|
||||
- **AHRS**: Attitude and Heading Reference System
|
||||
- **ESC**: Electronic Speed Controller
|
||||
- **SITL**: Software In The Loop
|
||||
- **HITL**: Hardware In The Loop
|
||||
|
||||
## Resources
|
||||
|
||||
- **Main Repository**: https://github.com/iNavFlight/inav
|
||||
- **Configurator**: https://github.com/iNavFlight/inav-configurator
|
||||
- **Discord**: https://discord.gg/peg2hhbYwN
|
||||
- **Documentation**: https://github.com/iNavFlight/inav/wiki
|
||||
- **Release Notes**: https://github.com/iNavFlight/inav/releases
|
||||
|
||||
## Version Information
|
||||
|
||||
This document is accurate for INAV 9.0.1. As the project evolves, some details may change. Always refer to the latest documentation and code for authoritative information.
|
||||
|
||||
---
|
||||
|
||||
**Remember**: INAV flies aircraft that people build and fly. Code quality, safety, and reliability are paramount. When in doubt, ask the community or maintainers for guidance.
|
||||
@@ -0,0 +1,98 @@
|
||||
This is at least a partial credits-file of people that have contributed to the INAV project.
|
||||
If you believe you should be on this list - feel free to open a PR updating it. For faster
|
||||
inclusion into this list please provide information about which part of code belongs to you.
|
||||
|
||||
Albert Kravcov
|
||||
Alberto García Hierro
|
||||
Alex Gorbatchev
|
||||
Alex Zaitsev
|
||||
Alexander Fedorov
|
||||
Alexander van Saase
|
||||
Alexey Stankevich
|
||||
Andre Bernet
|
||||
Andreas Tacke
|
||||
Andrew Payne
|
||||
Austin St. Aubin
|
||||
Bas Huisman
|
||||
Ben Hitchcock
|
||||
Boris B
|
||||
Brnadon Miller
|
||||
ChiggerPepi
|
||||
Chris Campbell
|
||||
Chris Mavrakis
|
||||
Chris Nisbet
|
||||
Chris Penny
|
||||
Damjan Adamic
|
||||
Darren Lines (Mr.D - RC)
|
||||
Dave Pitman
|
||||
David Bieber
|
||||
Davide Bertola
|
||||
Denis Kisselev
|
||||
Dominic Clifton
|
||||
Frank Zhao
|
||||
Fredrik Steen
|
||||
Gareth Wilkins
|
||||
Gaël James
|
||||
Gregor Ottmann
|
||||
Google LLC
|
||||
Hyon Lim
|
||||
Hubert Jozwiak
|
||||
James Harrison
|
||||
Jan Staal
|
||||
Jeff Hendrix
|
||||
Jeremy Waters
|
||||
Joe Hermaszewski
|
||||
Joe Poser
|
||||
Joel Fuster
|
||||
Johannes Kasberger
|
||||
Jonas Harnesk
|
||||
Jonathan Hudson
|
||||
Joshua Bardwell
|
||||
Juan González
|
||||
Kemal Hadimli
|
||||
Kieran Moore
|
||||
Konstantin Sharlaimov
|
||||
Krzysztof Rosinski
|
||||
Kyle Manna
|
||||
Larry Davis
|
||||
Marc Egli
|
||||
Marcelo Bezerra
|
||||
Mark Williams
|
||||
Martin Budden
|
||||
Matthew Evans
|
||||
Mauro Mombelli
|
||||
Max Winterstein
|
||||
Michael Corcoran
|
||||
Michael Hope
|
||||
Michael Jakob
|
||||
Michel Pastor
|
||||
Miha Valencic
|
||||
Mikael Blomqvist
|
||||
Moritz Ulrich
|
||||
Moshen Chan
|
||||
Nathan Tsoi
|
||||
Nicholas Sherlock
|
||||
Paul Fertser
|
||||
Paul Rogalinski
|
||||
Pawel Spychalski
|
||||
Petr Ledvina
|
||||
Phillip Jones
|
||||
Pierre Hugo
|
||||
Richard Birkby
|
||||
Richard Lehey
|
||||
Richard Marko
|
||||
Ray Morris (Sensei)
|
||||
Rimas Avizienis
|
||||
Sam Cook
|
||||
Sami Korhonen
|
||||
Samuel Brucksch
|
||||
Scott Shawcroft
|
||||
Sean Vig
|
||||
Stefan Grufman
|
||||
Stefan Haubold
|
||||
Steve Amor
|
||||
Thomas Buck
|
||||
Tim Eckel
|
||||
Trey Marc
|
||||
Tuomas Kuosmanen
|
||||
Zap Andersson
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
cmake_minimum_required(VERSION 3.13...3.18)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
|
||||
set(MAIN_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
set(MAIN_LIB_DIR "${CMAKE_CURRENT_SOURCE_DIR}/lib")
|
||||
set(MAIN_UTILS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/utils")
|
||||
set(MAIN_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/main")
|
||||
set(SVD_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dev/svd")
|
||||
set(DOWNLOADS_DIR "${MAIN_DIR}/downloads")
|
||||
set(TOOLS_DIR "${MAIN_DIR}/tools")
|
||||
|
||||
option(SITL "SITL build for host system" OFF)
|
||||
|
||||
set(TOOLCHAIN_OPTIONS none arm-none-eabi host)
|
||||
if (SITL)
|
||||
if (CMAKE_HOST_APPLE)
|
||||
set(MACOSX TRUE)
|
||||
endif()
|
||||
set(TOOLCHAIN "host" CACHE STRING "Toolchain to use. Available: ${TOOLCHAIN_OPTIONS}")
|
||||
else()
|
||||
set(TOOLCHAIN "arm-none-eabi" CACHE STRING "Toolchain to use. Available: ${TOOLCHAIN_OPTIONS}")
|
||||
endif()
|
||||
|
||||
set_property(CACHE TOOLCHAIN PROPERTY STRINGS ${TOOLCHAIN_OPTIONS})
|
||||
if("" STREQUAL TOOLCHAIN)
|
||||
set(TOOLCHAIN none)
|
||||
endif()
|
||||
if (NOT ${TOOLCHAIN} IN_LIST TOOLCHAIN_OPTIONS)
|
||||
message(FATAL_ERROR "Invalid toolchain ${TOOLCHAIN}. Valid options are: ${TOOLCHAIN_OPTIONS}")
|
||||
endif()
|
||||
|
||||
option(COMPILER_VERSION_CHECK "Ensure the compiler matches the expected version" ON)
|
||||
|
||||
include(GetGitRevisionDescription)
|
||||
get_git_head_revision(GIT_REFSPEC GIT_SHA1)
|
||||
string(SUBSTRING ${GIT_SHA1} 0 8 GIT_REV)
|
||||
|
||||
# Load settings related functions, so the tests can use them
|
||||
include(main)
|
||||
include(settings)
|
||||
|
||||
if(TOOLCHAIN STREQUAL none)
|
||||
add_subdirectory(src/test)
|
||||
else()
|
||||
if (SITL)
|
||||
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/${TOOLCHAIN}.cmake")
|
||||
else()
|
||||
set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/cmake/${TOOLCHAIN}.cmake")
|
||||
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/${TOOLCHAIN}-checks.cmake")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
project(INAV VERSION 9.1.0)
|
||||
|
||||
|
||||
enable_language(ASM)
|
||||
|
||||
if(MACOSX AND SITL)
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
else()
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
endif()
|
||||
set(CMAKE_C_EXTENSIONS ON)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_EXTENSIONS ON)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
|
||||
set(IS_RELEASE_BUILD ON)
|
||||
endif()
|
||||
|
||||
set(FIRMWARE_VERSION ${PROJECT_VERSION})
|
||||
|
||||
option(WARNINGS_AS_ERRORS "Make all warnings into errors")
|
||||
message("-- toolchain: ${TOOLCHAIN}, WARNINGS_AS_ERRORS: ${WARNINGS_AS_ERRORS}")
|
||||
|
||||
set(COMMON_COMPILE_DEFINITIONS
|
||||
FC_VERSION_MAJOR=${CMAKE_PROJECT_VERSION_MAJOR}
|
||||
FC_VERSION_MINOR=${CMAKE_PROJECT_VERSION_MINOR}
|
||||
FC_VERSION_PATCH_LEVEL=${CMAKE_PROJECT_VERSION_PATCH}
|
||||
FC_VERSION_TYPE="${VERSION_TYPE}"
|
||||
)
|
||||
|
||||
if (NOT SITL)
|
||||
include(openocd)
|
||||
include(svd)
|
||||
endif()
|
||||
|
||||
include(stm32)
|
||||
include(at32)
|
||||
include(sitl)
|
||||
|
||||
add_subdirectory(src)
|
||||
|
||||
collect_targets()
|
||||
|
||||
message("-- Build type: ${CMAKE_BUILD_TYPE}")
|
||||
include(ci)
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
FROM ubuntu:jammy
|
||||
|
||||
ARG USER_ID
|
||||
ARG GROUP_ID
|
||||
ARG GDB
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt-get update && apt-get install -y git cmake make ruby gcc python3 python3-yaml ninja-build gcc-arm-none-eabi
|
||||
|
||||
RUN if [ "$GDB" = "yes" ]; then apt-get install -y gdb; fi
|
||||
|
||||
# If a group and user with the same IDs already exist, rename the group and recreate the user after deleting the existing one.
|
||||
RUN GROUP="$(id -n -g $GROUP_ID)"; if [ -n "$GROUP" ]; then groupmod -n inav "$GROUP"; else groupadd --gid $GROUP_ID inav; fi
|
||||
RUN USER="$(id -n -u $USER_ID)"; if [ -n "$USER" ]; then userdel -r "$USER"; fi && useradd -m --uid $USER_ID --gid $GROUP_ID inav
|
||||
|
||||
USER inav
|
||||
|
||||
RUN git config --global --add safe.directory /src
|
||||
|
||||
WORKDIR /src/build
|
||||
|
||||
ENTRYPOINT ["/src/cmake/docker.sh"]
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
[BREAKPOINTS]
|
||||
ShowInfoWin = 1
|
||||
EnableFlashBP = 2
|
||||
BPDuringExecution = 0
|
||||
[CFI]
|
||||
CFISize = 0x00
|
||||
CFIAddr = 0x00
|
||||
[CPU]
|
||||
OverrideMemMap = 0
|
||||
AllowSimulation = 1
|
||||
ScriptFile=""
|
||||
[FLASH]
|
||||
MinNumBytesFlashDL = 0
|
||||
SkipProgOnCRCMatch = 1
|
||||
VerifyDownload = 1
|
||||
AllowCaching = 1
|
||||
EnableFlashDL = 2
|
||||
Override = 0
|
||||
Device="AD7160"
|
||||
[GENERAL]
|
||||
WorkRAMSize = 0x00
|
||||
WorkRAMAddr = 0x00
|
||||
[SWO]
|
||||
SWOLogFile=""
|
||||
[MEM]
|
||||
RdOverrideOrMask = 0x00
|
||||
RdOverrideAndMask = 0xFFFFFFFF
|
||||
RdOverrideAddr = 0xFFFFFFFF
|
||||
WrOverrideOrMask = 0x00
|
||||
WrOverrideAndMask = 0xFFFFFFFF
|
||||
WrOverrideAddr = 0xFFFFFFFF
|
||||
@@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
Vendored
+32
@@ -0,0 +1,32 @@
|
||||
# -*- mode: ruby -*-
|
||||
# vi: set ft=ruby :
|
||||
|
||||
# All Vagrant configuration is done below. The "2" in Vagrant.configure
|
||||
# configures the configuration version (we support older styles for
|
||||
# backwards compatibility). Please don't change it unless you know what
|
||||
# you're doing.
|
||||
Vagrant.configure(2) do |config|
|
||||
# The most common configuration options are documented and commented below.
|
||||
# For a complete reference, please see the online documentation at
|
||||
# https://docs.vagrantup.com.
|
||||
|
||||
# Every Vagrant development environment requires a box. You can search for
|
||||
# boxes at https://atlas.hashicorp.com/search.
|
||||
config.vm.box = "ubuntu/trusty64"
|
||||
config.vm.synced_folder ".", "/home/vagrant/inav"
|
||||
config.vm.hostname = "iNavDev"
|
||||
config.vm.define "iNavDev"
|
||||
config.vm.provider :virtualbox do |vb|
|
||||
vb.name = "iNavDev"
|
||||
end
|
||||
# Enable provisioning with a shell script. Additional provisioners such as
|
||||
# Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the
|
||||
# documentation for more information about their specific syntax and use.
|
||||
config.vm.provision "shell", inline: <<-SHELL
|
||||
sudo apt-get remove -y --force-yes gcc-arm-none-eabi ruby
|
||||
sudo apt-add-repository ppa:brightbox/ruby-ng
|
||||
sudo add-apt-repository ppa:team-gcc-arm-embedded/ppa
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --force-yes git gcc-arm-embedded ruby2.4 ruby2.4-dev
|
||||
SHELL
|
||||
end
|
||||
@@ -0,0 +1,9 @@
|
||||
# Boardconfig for AT-LINK for AT32F4-FC
|
||||
|
||||
source [find interface/atlink.cfg]
|
||||
|
||||
#transport select hla_swd
|
||||
|
||||
source [find target/at32f437xM.cfg]
|
||||
|
||||
reset_config none separate
|
||||
@@ -0,0 +1,9 @@
|
||||
# Boardconfig for ST-Link/V2 with F4-FC
|
||||
|
||||
source [find interface/stlink.cfg]
|
||||
|
||||
transport select hla_swd
|
||||
|
||||
source [find target/stm32f4x.cfg]
|
||||
|
||||
reset_config none separate
|
||||
@@ -0,0 +1,9 @@
|
||||
# Boardconfig for ST-Link/V2 with F7-FC
|
||||
|
||||
source [find interface/stlink.cfg]
|
||||
|
||||
transport select hla_swd
|
||||
|
||||
source [find target/stm32f7x.cfg]
|
||||
|
||||
reset_config none separate
|
||||
@@ -0,0 +1,9 @@
|
||||
# Boardconfig for ST-Link/V2 with H7-FC
|
||||
|
||||
source [find interface/stlink.cfg]
|
||||
|
||||
transport select hla_swd
|
||||
|
||||
source [find target/stm32h7x_dual_bank.cfg]
|
||||
|
||||
reset_config none separate
|
||||
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
if [[ $# == 0 ]]; then
|
||||
echo -e "\
|
||||
Usage syntax: ./build.sh <TARGET>
|
||||
|
||||
Notes:
|
||||
* You can specify multiple targets.
|
||||
./build.sh <TARGET_1> <TARGET_2> <TARGET_N>
|
||||
* To get a list of release targets use \"release_targets\"
|
||||
./build.sh release_targets
|
||||
* To get a list of valid targets use \"valid_targets\"
|
||||
./build.sh valid_targets
|
||||
* To get a list of all targets use \"help\". Hint: pipe the output through a pager.
|
||||
./build.sh help | less
|
||||
* To build all targets use \"all\"
|
||||
./build.sh all
|
||||
* To clean a target prefix it with \"clean_\".
|
||||
./build.sh clean_MATEKF405SE
|
||||
* To clean all targets just use \"clean\".
|
||||
./build.sh clean"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
run_docker() {
|
||||
docker run --rm -it -v "$(pwd)":/src inav-build "$@"
|
||||
}
|
||||
|
||||
if [ -z "$(docker images -q inav-build)" ]; then
|
||||
echo "*** Building Docker image"
|
||||
docker build -t inav-build \
|
||||
--build-arg USER_ID="$(id -u)" \
|
||||
--build-arg GROUP_ID="$(id -g)" .
|
||||
else
|
||||
docker build -q -t inav-build \
|
||||
--build-arg USER_ID="$(id -u)" \
|
||||
--build-arg GROUP_ID="$(id -g)" . >/dev/null ||
|
||||
{ echo "*** Building Docker image: ERROR"; exit 1; }
|
||||
fi
|
||||
|
||||
if [ ! -d ./build ]; then
|
||||
echo -e "*** Creating build directory\n"
|
||||
mkdir ./build && chmod 777 ./build
|
||||
fi
|
||||
|
||||
if [ ! -d ./downloads ]; then
|
||||
echo -e "*** Creating downloads directory\n"
|
||||
mkdir ./downloads && chmod 777 ./downloads
|
||||
fi
|
||||
|
||||
if [ ! -d ./tools ]; then
|
||||
echo -e "*** Creating tools directory\n"
|
||||
mkdir ./tools && chmod 777 ./tools
|
||||
fi
|
||||
|
||||
case "$1" in
|
||||
release_targets)
|
||||
run_docker targets | sed -n 's/^Release targets: \(.*\)/\1/p'|tr ' ' '\n'
|
||||
;;
|
||||
valid_targets)
|
||||
run_docker targets | sed -n 's/^Valid targets: \(.*\)/\1/p'|tr ' ' '\n'
|
||||
;;
|
||||
*)
|
||||
echo -e "*** Building targets [$@]\n"
|
||||
run_docker "$@"
|
||||
if ls ./build/*.hex &> /dev/null; then
|
||||
echo -e "\n*** Built targets in ./build:"
|
||||
stat -c "%n (%.19y)" ./build/*.hex
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
Executable
+59
@@ -0,0 +1,59 @@
|
||||
#!/bin/bash
|
||||
|
||||
filename=Manual
|
||||
doc_files=(
|
||||
'Introduction.md'
|
||||
'Getting Started.md'
|
||||
'Safety.md'
|
||||
'Installation.md'
|
||||
'Configuration.md'
|
||||
'Cli.md'
|
||||
'Serial.md'
|
||||
'Rx.md'
|
||||
'Spektrum bind.md'
|
||||
'Failsafe.md'
|
||||
'Battery.md'
|
||||
'Gps.md'
|
||||
'Rssi.md'
|
||||
'Telemetry.md'
|
||||
'LedStrip.md'
|
||||
'Display.md'
|
||||
'Buzzer.md'
|
||||
'Sonar.md'
|
||||
'Profiles.md'
|
||||
'Inflight Adjustments.md'
|
||||
'Controls.md'
|
||||
'Gtune.md'
|
||||
'Blackbox.md'
|
||||
'Migrating from baseflight.md'
|
||||
'Boards.md'
|
||||
'Board - AlienFlight.md'
|
||||
'Board - ColibriRace.md'
|
||||
'Board - Motolab.md'
|
||||
'Board - Paris Air Hero 32.md'
|
||||
'Board - Sparky.md'
|
||||
'Board - RMDO.md'
|
||||
'Board - SPRacingF3.md'
|
||||
)
|
||||
|
||||
if which gimli >/dev/null; then
|
||||
echo "Building ${filename}.pdf"
|
||||
pushd . >/dev/null
|
||||
cd docs
|
||||
|
||||
rm -f ${filename}.md
|
||||
for i in "${doc_files[@]}"
|
||||
do
|
||||
cat "$i" >> ${filename}.md
|
||||
done
|
||||
rm -f ${filename}.pdf
|
||||
gimli -f ${filename}.md -stylesheet override.css \
|
||||
-w '--toc --title "INAV Manual" --footer-right "[page]" --toc-depth 1'
|
||||
rm ${filename}.md
|
||||
popd >/dev/null
|
||||
else
|
||||
echo -e "\nFAILED"
|
||||
echo "Install Gimli to build the PDF documentation"
|
||||
echo -e "https://github.com/walle/gimli\n"
|
||||
exit 1
|
||||
fi
|
||||
@@ -0,0 +1,172 @@
|
||||
# - Returns a version string from Git
|
||||
#
|
||||
# These functions force a re-configure on each git commit so that you can
|
||||
# trust the values of the variables in your build system.
|
||||
#
|
||||
# get_git_head_revision(<refspecvar> <hashvar> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the refspec and sha hash of the current head revision
|
||||
#
|
||||
# git_describe(<var> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the results of git describe on the source tree, and adjusting
|
||||
# the output so that it tests false if an error occurs.
|
||||
#
|
||||
# git_get_exact_tag(<var> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the results of git describe --exact-match on the source tree,
|
||||
# and adjusting the output so that it tests false if there was no exact
|
||||
# matching tag.
|
||||
#
|
||||
# git_local_changes(<var>)
|
||||
#
|
||||
# Returns either "CLEAN" or "DIRTY" with respect to uncommitted changes.
|
||||
# Uses the return code of "git diff-index --quiet HEAD --".
|
||||
# Does not regard untracked files.
|
||||
#
|
||||
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||
#
|
||||
# Original Author:
|
||||
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
|
||||
# http://academic.cleardefinition.com
|
||||
# Iowa State University HCI Graduate Program/VRAC
|
||||
#
|
||||
# Copyright Iowa State University 2009-2010.
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
if(__get_git_revision_description)
|
||||
return()
|
||||
endif()
|
||||
set(__get_git_revision_description YES)
|
||||
|
||||
# We must run the following at "include" time, not at function call time,
|
||||
# to find the path to this module rather than the path to a calling list file
|
||||
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
|
||||
|
||||
function(get_git_head_revision _refspecvar _hashvar)
|
||||
set(GIT_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
|
||||
while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories
|
||||
set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}")
|
||||
get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH)
|
||||
if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT)
|
||||
# We have reached the root directory, we are not in git
|
||||
set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
|
||||
set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
|
||||
endwhile()
|
||||
# check if this is a submodule
|
||||
if(NOT IS_DIRECTORY ${GIT_DIR})
|
||||
file(READ ${GIT_DIR} submodule)
|
||||
string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule})
|
||||
get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH)
|
||||
get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE)
|
||||
endif()
|
||||
if(NOT IS_DIRECTORY "${GIT_DIR}")
|
||||
file(READ ${GIT_DIR} worktree)
|
||||
string(REGEX REPLACE "gitdir: (.*)worktrees(.*)\n$" "\\1" GIT_DIR ${worktree})
|
||||
endif()
|
||||
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
|
||||
if(NOT EXISTS "${GIT_DATA}")
|
||||
file(MAKE_DIRECTORY "${GIT_DATA}")
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${GIT_DIR}/HEAD")
|
||||
return()
|
||||
endif()
|
||||
set(HEAD_FILE "${GIT_DATA}/HEAD")
|
||||
configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY)
|
||||
|
||||
configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
|
||||
"${GIT_DATA}/grabRef.cmake"
|
||||
@ONLY)
|
||||
include("${GIT_DATA}/grabRef.cmake")
|
||||
|
||||
set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE)
|
||||
set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(git_describe _var)
|
||||
if(NOT GIT_FOUND)
|
||||
find_package(Git QUIET)
|
||||
endif()
|
||||
get_git_head_revision(refspec hash)
|
||||
if(NOT GIT_FOUND)
|
||||
set(${_var} "GIT-NOTFOUND" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(NOT hash)
|
||||
set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# TODO sanitize
|
||||
#if((${ARGN}" MATCHES "&&") OR
|
||||
# (ARGN MATCHES "||") OR
|
||||
# (ARGN MATCHES "\\;"))
|
||||
# message("Please report the following error to the project!")
|
||||
# message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}")
|
||||
#endif()
|
||||
|
||||
#message(STATUS "Arguments to execute_process: ${ARGN}")
|
||||
|
||||
execute_process(COMMAND
|
||||
"${GIT_EXECUTABLE}"
|
||||
describe
|
||||
${hash}
|
||||
${ARGN}
|
||||
WORKING_DIRECTORY
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
RESULT_VARIABLE
|
||||
res
|
||||
OUTPUT_VARIABLE
|
||||
out
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(NOT res EQUAL 0)
|
||||
set(out "${out}-${res}-NOTFOUND")
|
||||
endif()
|
||||
|
||||
set(${_var} "${out}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(git_get_exact_tag _var)
|
||||
git_describe(out --exact-match ${ARGN})
|
||||
set(${_var} "${out}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(git_local_changes _var)
|
||||
if(NOT GIT_FOUND)
|
||||
find_package(Git QUIET)
|
||||
endif()
|
||||
get_git_head_revision(refspec hash)
|
||||
if(NOT GIT_FOUND)
|
||||
set(${_var} "GIT-NOTFOUND" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(NOT hash)
|
||||
set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
execute_process(COMMAND
|
||||
"${GIT_EXECUTABLE}"
|
||||
diff-index --quiet HEAD --
|
||||
WORKING_DIRECTORY
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
RESULT_VARIABLE
|
||||
res
|
||||
OUTPUT_VARIABLE
|
||||
out
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(res EQUAL 0)
|
||||
set(${_var} "CLEAN" PARENT_SCOPE)
|
||||
else()
|
||||
set(${_var} "DIRTY" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
@@ -0,0 +1,41 @@
|
||||
#
|
||||
# Internal file for GetGitRevisionDescription.cmake
|
||||
#
|
||||
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||
#
|
||||
# Original Author:
|
||||
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
|
||||
# http://academic.cleardefinition.com
|
||||
# Iowa State University HCI Graduate Program/VRAC
|
||||
#
|
||||
# Copyright Iowa State University 2009-2010.
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
set(HEAD_HASH)
|
||||
|
||||
file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024)
|
||||
|
||||
string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS)
|
||||
if(HEAD_CONTENTS MATCHES "ref")
|
||||
# named branch
|
||||
string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
|
||||
if(EXISTS "@GIT_DIR@/${HEAD_REF}")
|
||||
configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
|
||||
else()
|
||||
configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY)
|
||||
file(READ "@GIT_DATA@/packed-refs" PACKED_REFS)
|
||||
if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}")
|
||||
set(HEAD_HASH "${CMAKE_MATCH_1}")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
# detached HEAD
|
||||
configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
|
||||
endif()
|
||||
|
||||
if(NOT HEAD_HASH)
|
||||
file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
|
||||
string(STRIP "${HEAD_HASH}" HEAD_HASH)
|
||||
endif()
|
||||
@@ -0,0 +1,150 @@
|
||||
include(gcc)
|
||||
set(arm_none_eabi_triplet "arm-none-eabi")
|
||||
|
||||
# Keep version in sync with the distribution files below
|
||||
set(arm_none_eabi_gcc_version "13.2.1")
|
||||
# This is the output directory "pretty" name and URI name prefix
|
||||
set(base_dir_name "arm-gnu-toolchain-13.2.rel1")
|
||||
# This is the name inside the archive, which is no longer evincible from URI, alas
|
||||
set(archive_base_dir_name "arm-gnu-toolchain-13.2.Rel1")
|
||||
set(arm_none_eabi_base_url "https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/${base_dir_name}")
|
||||
# suffix and checksum
|
||||
set(arm_none_eabi_win32 "mingw-w64-i686-arm-none-eabi.zip" 7fd677088038cdf82f33f149e2e943ee)
|
||||
set(arm_none_eabi_linux_amd64 "x86_64-arm-none-eabi.tar.xz" 791754852f8c18ea04da7139f153a5b7)
|
||||
set(arm_none_eabi_linux_aarch64 "aarch64-arm-none-eabi.tar.xz" 5a08122e6d4caf97c6ccd1d29e62599c)
|
||||
set(arm_none_eabi_darwin_amd64 "darwin-x86_64-arm-none-eabi.tar.xz" 41d49840b0fc676d2ae35aab21a58693)
|
||||
set(arm_none_eabi_darwin_aarch64 "darwin-arm64-arm-none-eabi.tar.xz" 2c43e9d72206c1f81227b0a685df5ea6)
|
||||
|
||||
function(host_uname_machine var)
|
||||
# We need to call uname -m manually, since at the point
|
||||
# this file is included CMAKE_HOST_SYSTEM_PROCESSOR is
|
||||
# empty because we haven't called project() yet.
|
||||
execute_process(COMMAND uname -m
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
OUTPUT_VARIABLE machine)
|
||||
|
||||
set(${var} ${machine} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(arm_none_eabi_gcc_install)
|
||||
set(dist "")
|
||||
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
|
||||
set(dist ${arm_none_eabi_win32})
|
||||
elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_HOST_SYSTEM_NAME STREQUAL "FreeBSD")
|
||||
if(NOT CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
|
||||
message("-- no compiler binaries available for ${CMAKE_HOST_SYSTEM_NAME}, using Linux binaries as a fallback")
|
||||
endif()
|
||||
host_uname_machine(machine)
|
||||
# Linux returns x86_64, FreeBSD returns amd64
|
||||
if(machine STREQUAL "x86_64" OR machine STREQUAL "amd64")
|
||||
set(dist ${arm_none_eabi_linux_amd64})
|
||||
elseif(machine STREQUAL "aarch64")
|
||||
set(dist ${arm_none_eabi_linux_aarch64})
|
||||
else()
|
||||
message("-- no precompiled ${arm_none_eabi_triplet} toolchain for machine ${machine}")
|
||||
endif()
|
||||
elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
|
||||
host_uname_machine(machine)
|
||||
if(machine STREQUAL "x86_64" OR machine STREQUAL "amd64")
|
||||
set(dist ${arm_none_eabi_darwin_amd64})
|
||||
elseif(machine STREQUAL "aarch64" OR machine STREQUAL "arm64")
|
||||
set(dist ${arm_none_eabi_darwin_aarch64})
|
||||
else()
|
||||
message("-- no precompiled ${arm_none_eabi_triplet} toolchain for machine ${machine}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(dist STREQUAL "")
|
||||
message(FATAL_ERROR "could not install ${arm_none_eabi_triplet}-gcc automatically")
|
||||
endif()
|
||||
list(GET dist 0 dist_suffix)
|
||||
list(GET dist 1 dist_checksum)
|
||||
set(dist_url "${arm_none_eabi_base_url}-${dist_suffix}")
|
||||
string(REPLACE "/" ";" url_parts ${dist_url})
|
||||
list(LENGTH url_parts n)
|
||||
math(EXPR last "${n} - 1")
|
||||
list(GET url_parts ${last} basename)
|
||||
set(output "${DOWNLOADS_DIR}/${basename}")
|
||||
message("-- downloading ${arm_none_eabi_triplet}-gcc ${arm_none_eabi_gcc_version} from ${dist_url}")
|
||||
file(DOWNLOAD ${dist_url} ${output}
|
||||
INACTIVITY_TIMEOUT 30
|
||||
STATUS status
|
||||
SHOW_PROGRESS
|
||||
EXPECTED_HASH MD5=${dist_checksum}
|
||||
TLS_VERIFY ON
|
||||
)
|
||||
list(GET status 0 status_code)
|
||||
if(NOT status_code EQUAL 0)
|
||||
list(GET status 1 status_message)
|
||||
message(FATAL_ERROR "error downloading ${basename}: ${status_message}")
|
||||
endif()
|
||||
message("-- extracting ${basename}")
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${TOOLS_DIR})
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf ${output}
|
||||
RESULT_VARIABLE status
|
||||
WORKING_DIRECTORY ${TOOLS_DIR}
|
||||
)
|
||||
if(NOT status EQUAL 0)
|
||||
message(FATAL_ERROR "error extracting ${basename}: ${status}")
|
||||
endif()
|
||||
string(REPLACE "." ";" url_parts ${dist_suffix})
|
||||
list(GET url_parts 0 host_dir_name)
|
||||
set(dir_name "${archive_base_dir_name}-${host_dir_name}")
|
||||
file(REMOVE_RECURSE "${TOOLS_DIR}/${base_dir_name}")
|
||||
file(RENAME "${TOOLS_DIR}/${dir_name}" "${TOOLS_DIR}/${base_dir_name}")
|
||||
# This is **somewhat ugly**
|
||||
# the newlib distributed by ARM generates suprious warnings from re-entrant POSIX functions
|
||||
# that INAV doesn't use. These "harmless" warnings can be surpressed by removing the
|
||||
# errant section from the only libnosys used by INAV ...
|
||||
# So look the other way ... while this is "fixed"
|
||||
execute_process(COMMAND arm-none-eabi-objcopy -w -R .gnu.warning.* "${TOOLS_DIR}/${base_dir_name}/arm-none-eabi/lib/thumb/v7e-m+fp/hard/libnosys.a"
|
||||
RESULT_VARIABLE status
|
||||
WORKING_DIRECTORY ${TOOLS_DIR}
|
||||
)
|
||||
if(NOT status EQUAL 0)
|
||||
message(FATAL_ERROR "error fixing libnosys.a: ${status}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(arm_none_eabi_gcc_add_path)
|
||||
set(gcc_path "${TOOLS_DIR}/${base_dir_name}/bin")
|
||||
if(CMAKE_HOST_SYSTEM MATCHES ".*Windows.*")
|
||||
set(sep "\\;")
|
||||
else()
|
||||
set(sep ":")
|
||||
endif()
|
||||
set(ENV{PATH} "${gcc_path}${sep}$ENV{PATH}")
|
||||
endfunction()
|
||||
|
||||
function(arm_none_eabi_gcc_check)
|
||||
gcc_get_version(version
|
||||
TRIPLET ${arm_none_eabi_triplet}
|
||||
PROGRAM_NAME prog
|
||||
PROGRAM_PATH prog_path
|
||||
)
|
||||
if(NOT version)
|
||||
message("-- could not find ${prog}")
|
||||
arm_none_eabi_gcc_install()
|
||||
gcc_get_version(version
|
||||
TRIPLET ${arm_none_eabi_triplet}
|
||||
PROGRAM_NAME prog
|
||||
PROGRAM_PATH prog_path
|
||||
)
|
||||
return()
|
||||
endif()
|
||||
message("-- found ${prog} ${version} at ${prog_path}")
|
||||
if(COMPILER_VERSION_CHECK AND NOT arm_none_eabi_gcc_version STREQUAL version)
|
||||
message("-- expecting ${prog} version ${arm_none_eabi_gcc_version}, but got version ${version} instead")
|
||||
arm_none_eabi_gcc_install()
|
||||
unset(gcc CACHE)
|
||||
gcc_get_version(version
|
||||
TRIPLET ${arm_none_eabi_triplet}
|
||||
PROGRAM_NAME prog
|
||||
PROGRAM_PATH prog_path
|
||||
)
|
||||
return()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
arm_none_eabi_gcc_add_path()
|
||||
arm_none_eabi_gcc_check()
|
||||
@@ -0,0 +1,48 @@
|
||||
set(CMAKE_SYSTEM_NAME Generic)
|
||||
set(CMAKE_SYSTEM_PROCESSOR arm)
|
||||
|
||||
if(WIN32)
|
||||
set(TOOL_EXECUTABLE_SUFFIX ".exe")
|
||||
endif()
|
||||
|
||||
set(TARGET_TRIPLET "arm-none-eabi")
|
||||
|
||||
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
|
||||
set(CMAKE_ASM_COMPILER "${TARGET_TRIPLET}-gcc${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "asm compiler")
|
||||
set(CMAKE_C_COMPILER "${TARGET_TRIPLET}-gcc${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "c compiler")
|
||||
set(CMAKE_CXX_COMPILER "${TARGET_TRIPLET}-g++${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "c++ compiler")
|
||||
set(CMAKE_OBJCOPY "${TARGET_TRIPLET}-objcopy${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "objcopy tool")
|
||||
set(CMAKE_OBJDUMP "${TARGET_TRIPLET}-objdump${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "objdump tool")
|
||||
set(CMAKE_SIZE "${TARGET_TRIPLET}-size${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "size tool")
|
||||
set(CMAKE_DEBUGGER "${TARGET_TRIPLET}-gdb${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "debugger")
|
||||
set(CMAKE_CPPFILT "${TARGET_TRIPLET}-c++filt${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "c++filt")
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
set(CMAKE_EXECUTABLE_SUFFIX ".elf")
|
||||
|
||||
if(NOT CMAKE_CONFIGURATION_TYPES)
|
||||
set(CMAKE_CONFIGURATION_TYPES Debug Release RelWithDebInfo)
|
||||
endif()
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "")
|
||||
set(CMAKE_BUILD_TYPE RelWithDebInfo)
|
||||
endif()
|
||||
set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "Build Type" FORCE)
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${CMAKE_CONFIGURATION_TYPES})
|
||||
|
||||
set(arm_none_eabi_debug "-Og -g")
|
||||
# We set -Os or -O2 depending on the MCU family
|
||||
set(arm_none_eabi_release "-DNDEBUG")
|
||||
set(arm_none_eabi_relwithdebinfo "-ggdb3 ${arm_none_eabi_release}")
|
||||
|
||||
set(CMAKE_C_FLAGS_DEBUG ${arm_none_eabi_debug} CACHE INTERNAL "c compiler flags debug")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG ${arm_none_eabi_debug} CACHE INTERNAL "c++ compiler flags debug")
|
||||
set(CMAKE_ASM_FLAGS_DEBUG ${arm_none_eabi_debug} CACHE INTERNAL "asm compiler flags debug")
|
||||
|
||||
set(CMAKE_C_FLAGS_RELEASE ${arm_none_eabi_release} CACHE INTERNAL "c compiler flags release")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE ${arm_none_eabi_release} CACHE INTERNAL "cxx compiler flags release")
|
||||
set(CMAKE_ASM_FLAGS_RELEASE ${arm_none_eabi_release} CACHE INTERNAL "asm compiler flags release")
|
||||
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO ${arm_none_eabi_relwithdebinfo} CACHE INTERNAL "c compiler flags release")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO ${arm_none_eabi_relwithdebinfo} CACHE INTERNAL "cxx compiler flags release")
|
||||
set(CMAKE_ASM_FLAGS_RELWITHDEBINFO ${arm_none_eabi_relwithdebinfo} CACHE INTERNAL "asm compiler flags release")
|
||||
@@ -0,0 +1,33 @@
|
||||
main_sources(BOOTLOADER_SOURCES
|
||||
common/log.c
|
||||
common/log.h
|
||||
common/printf.c
|
||||
common/printf.h
|
||||
common/string_light.c
|
||||
common/string_light.h
|
||||
common/typeconversion.c
|
||||
common/typeconversion.h
|
||||
|
||||
drivers/bus.c
|
||||
drivers/bus_busdev_i2c.c
|
||||
drivers/bus_busdev_spi.c
|
||||
drivers/bus_i2c_soft.c
|
||||
drivers/io.c
|
||||
drivers/light_led.c
|
||||
drivers/persistent.c
|
||||
drivers/rcc.c
|
||||
drivers/serial.c
|
||||
drivers/system.c
|
||||
drivers/time.c
|
||||
drivers/timer.c
|
||||
drivers/flash_m25p16.c
|
||||
drivers/flash_w25n.c
|
||||
drivers/flash.c
|
||||
|
||||
fc/firmware_update_common.c
|
||||
fc/firmware_update_common.h
|
||||
|
||||
target/common_hardware.c
|
||||
)
|
||||
|
||||
list(APPEND BOOTLOADER_SOURCES ${MAIN_DIR}/src/bl/bl_main.c)
|
||||
@@ -0,0 +1,4 @@
|
||||
main_sources(AT32_STDPERIPH_SRC
|
||||
drivers/bus_spi_at32f43x.c
|
||||
drivers/serial_uart_hal_at32f43x.c
|
||||
)
|
||||
@@ -0,0 +1,442 @@
|
||||
include(at32-bootloader)
|
||||
include(at32f4)
|
||||
|
||||
include(CMakeParseArguments)
|
||||
|
||||
option(DEBUG_HARDFAULTS "Enable debugging of hard faults via custom handler")
|
||||
option(SEMIHOSTING "Enable semihosting")
|
||||
|
||||
message("-- DEBUG_HARDFAULTS: ${DEBUG_HARDFAULTS}, SEMIHOSTING: ${SEMIHOSTING}")
|
||||
|
||||
set(CMSIS_DIR "${MAIN_LIB_DIR}/lib/main/AT32F43x/Drivers/CMSIS")
|
||||
set(CMSIS_INCLUDE_DIR "${CMSIS_DIR}/cm4/core_support")
|
||||
# DSP use common
|
||||
set(CMSIS_DSP_DIR "${MAIN_LIB_DIR}/main/CMSIS/DSP")
|
||||
set(CMSIS_DSP_INCLUDE_DIR "${CMSIS_DSP_DIR}/Include")
|
||||
|
||||
set(CMSIS_DSP_SRC
|
||||
BasicMathFunctions/arm_scale_f32.c
|
||||
BasicMathFunctions/arm_sub_f32.c
|
||||
BasicMathFunctions/arm_mult_f32.c
|
||||
BasicMathFunctions/arm_offset_f32.c
|
||||
TransformFunctions/arm_rfft_fast_f32.c
|
||||
TransformFunctions/arm_cfft_f32.c
|
||||
TransformFunctions/arm_rfft_fast_init_f32.c
|
||||
TransformFunctions/arm_cfft_radix8_f32.c
|
||||
TransformFunctions/arm_bitreversal2.S
|
||||
CommonTables/arm_common_tables.c
|
||||
ComplexMathFunctions/arm_cmplx_mag_f32.c
|
||||
StatisticsFunctions/arm_max_f32.c
|
||||
StatisticsFunctions/arm_rms_f32.c
|
||||
StatisticsFunctions/arm_std_f32.c
|
||||
StatisticsFunctions/arm_mean_f32.c
|
||||
)
|
||||
list(TRANSFORM CMSIS_DSP_SRC PREPEND "${CMSIS_DSP_DIR}/Source/")
|
||||
|
||||
set(AT32_STARTUP_DIR "${MAIN_SRC_DIR}/startup")
|
||||
|
||||
main_sources(AT32_VCP_SRC
|
||||
drivers/serial_usb_vcp_at32f43x.c
|
||||
drivers/usb_io.c
|
||||
)
|
||||
# SDCARD not supported yet
|
||||
main_sources(AT32_SDCARD_SRC
|
||||
drivers/sdcard/sdcard.c
|
||||
drivers/sdcard/sdcard_spi.c
|
||||
drivers/sdcard/sdcard_sdio.c
|
||||
drivers/sdcard/sdcard_standard.c
|
||||
)
|
||||
|
||||
# XXX: This code is not STM32 specific
|
||||
main_sources(AT32_ASYNCFATFS_SRC
|
||||
io/asyncfatfs/asyncfatfs.c
|
||||
io/asyncfatfs/fat_standard.c
|
||||
)
|
||||
|
||||
main_sources(AT32_MSC_SRC
|
||||
msc/at32_msc_diskio.c
|
||||
msc/emfat.c
|
||||
msc/emfat_file.c
|
||||
)
|
||||
|
||||
set(AT32_INCLUDE_DIRS
|
||||
"${CMSIS_INCLUDE_DIR}"
|
||||
"${CMSIS_DSP_INCLUDE_DIR}"
|
||||
"${MAIN_SRC_DIR}/target"
|
||||
)
|
||||
|
||||
set(AT32_DEFINITIONS
|
||||
)
|
||||
set(AT32_DEFAULT_HSE_MHZ 8)
|
||||
set(AT32_LINKER_DIR "${MAIN_SRC_DIR}/target/link")
|
||||
set(AT32_COMPILE_OPTIONS
|
||||
-ffunction-sections
|
||||
-fdata-sections
|
||||
-fno-common
|
||||
)
|
||||
|
||||
set(AT32_LINK_LIBRARIES
|
||||
-lm
|
||||
-lc
|
||||
)
|
||||
|
||||
if(SEMIHOSTING)
|
||||
list(APPEND AT32_LINK_LIBRARIES --specs=rdimon.specs -lrdimon)
|
||||
list(APPEND AT32_DEFINITIONS SEMIHOSTING)
|
||||
else()
|
||||
list(APPEND AT32_LINK_LIBRARIES -lnosys)
|
||||
endif()
|
||||
|
||||
set(AT32_LINK_OPTIONS
|
||||
#-nostartfiles
|
||||
--specs=nano.specs
|
||||
-static
|
||||
-Wl,-gc-sections
|
||||
-Wl,-L${AT32_LINKER_DIR}
|
||||
-Wl,--cref
|
||||
-Wl,--no-wchar-size-warning
|
||||
-Wl,--print-memory-usage
|
||||
-Wl,--no-warn-rwx-segments
|
||||
)
|
||||
# Get target features
|
||||
macro(get_at32_target_features output_var dir target_name)
|
||||
execute_process(COMMAND "${CMAKE_C_COMPILER}" -E -dD -D${ARGV2} "${ARGV1}/target.h"
|
||||
ERROR_VARIABLE _errors
|
||||
RESULT_VARIABLE _result
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
OUTPUT_VARIABLE _contents)
|
||||
|
||||
if(NOT _result EQUAL 0)
|
||||
message(FATAL_ERROR "error extracting features for AT32 target ${ARGV2}: ${_errors}")
|
||||
endif()
|
||||
|
||||
string(REGEX MATCH "#define[\t ]+USE_VCP" HAS_VCP ${_contents})
|
||||
if(HAS_VCP)
|
||||
list(APPEND ${ARGV0} VCP)
|
||||
endif()
|
||||
string(REGEX MATCH "define[\t ]+USE_FLASHFS" HAS_FLASHFS ${_contents})
|
||||
if(HAS_FLASHFS)
|
||||
list(APPEND ${ARGV0} FLASHFS)
|
||||
endif()
|
||||
string(REGEX MATCH "define[\t ]+USE_SDCARD" HAS_SDCARD ${_contents})
|
||||
if (HAS_SDCARD)
|
||||
list(APPEND ${ARGV0} SDCARD)
|
||||
string(REGEX MATCH "define[\t ]+USE_SDCARD_SDIO" HAS_SDIO ${_contents})
|
||||
if (HAS_SDIO)
|
||||
list(APPEND ${ARGV0} SDIO)
|
||||
endif()
|
||||
endif()
|
||||
if(HAS_FLASHFS OR HAS_SDCARD)
|
||||
list(APPEND ${ARGV0} MSC)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
function(get_at32_flash_size out size)
|
||||
# 4: 16, 6: 32, 8: 64, B: 128, C: 256, D: 384, E: 512, F: 768, G: 1024, H: 1536, I: 2048 KiB
|
||||
string(TOUPPER ${size} s)
|
||||
if(${s} STREQUAL "4")
|
||||
set(${out} 16 PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(${s} STREQUAL "6")
|
||||
set(${out} 32 PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(${s} STREQUAL "8")
|
||||
set(${out} 64 PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(${s} STREQUAL "8")
|
||||
set(${out} 64 PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(${s} STREQUAL "B")
|
||||
set(${out} 128 PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(${s} STREQUAL "C")
|
||||
set(${out} 256 PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(${s} STREQUAL "D")
|
||||
set(${out} 384 PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(${s} STREQUAL "E")
|
||||
set(${out} 512 PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(${s} STREQUAL "F")
|
||||
set(${out} 768 PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(${s} STREQUAL "G")
|
||||
set(${out} 1024 PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(${s} STREQUAL "H")
|
||||
set(${out} 1536 PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(${s} STREQUAL "I")
|
||||
set(${out} 2048 PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(add_hex_target name exe hex)
|
||||
add_custom_target(${name} ALL
|
||||
cmake -E env PATH="$ENV{PATH}"
|
||||
# TODO: Overriding the start address with --set-start 0x08000000
|
||||
# seems to be required due to some incorrect assumptions about .hex
|
||||
# files in the configurator. Verify wether that's the case and fix
|
||||
# the bug in configurator or delete this comment.
|
||||
${CMAKE_OBJCOPY} -Oihex --set-start 0x08000000 $<TARGET_FILE:${exe}> ${hex}
|
||||
BYPRODUCTS ${hex}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
function(add_bin_target name exe bin)
|
||||
add_custom_target(${name}
|
||||
cmake -E env PATH="$ENV{PATH}"
|
||||
${CMAKE_OBJCOPY} -Obinary $<TARGET_FILE:${exe}> ${bin}
|
||||
BYPRODUCTS ${bin}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
function(generate_map_file target)
|
||||
if(CMAKE_VERSION VERSION_LESS 3.15)
|
||||
set(map "$<TARGET_FILE:${target}>.map")
|
||||
else()
|
||||
set(map "$<TARGET_FILE_DIR:${target}>/$<TARGET_FILE_BASE_NAME:${target}>.map")
|
||||
endif()
|
||||
target_link_options(${target} PRIVATE "-Wl,-Map,${map}")
|
||||
endfunction()
|
||||
|
||||
function(set_linker_script target script)
|
||||
set(script_path ${AT32_LINKER_DIR}/${args_LINKER_SCRIPT}.ld)
|
||||
if(NOT EXISTS ${script_path})
|
||||
message(FATAL_ERROR "linker script ${script_path} doesn't exist")
|
||||
endif()
|
||||
set_target_properties(${target} PROPERTIES LINK_DEPENDS ${script_path})
|
||||
target_link_options(${elf_target} PRIVATE -T${script_path})
|
||||
endfunction()
|
||||
|
||||
function(add_at32_executable)
|
||||
cmake_parse_arguments(
|
||||
args
|
||||
# Boolean arguments
|
||||
""
|
||||
# Single value arguments
|
||||
"FILENAME;NAME;OPTIMIZATION;OUTPUT_BIN_FILENAME;OUTPUT_HEX_FILENAME;OUTPUT_TARGET_NAME"
|
||||
# Multi-value arguments
|
||||
"COMPILE_DEFINITIONS;COMPILE_OPTIONS;INCLUDE_DIRECTORIES;LINK_OPTIONS;LINKER_SCRIPT;SOURCES"
|
||||
# Start parsing after the known arguments
|
||||
${ARGN}
|
||||
)
|
||||
set(elf_target ${args_NAME}.elf)
|
||||
add_executable(${elf_target})
|
||||
target_sources(${elf_target} PRIVATE ${args_SOURCES})
|
||||
target_include_directories(${elf_target} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${args_INCLUDE_DIRECTORIES} ${AT32_INCLUDE_DIRS})
|
||||
target_compile_definitions(${elf_target} PRIVATE ${args_COMPILE_DEFINITIONS})
|
||||
target_compile_options(${elf_target} PRIVATE ${AT32_COMPILE_OPTIONS} ${args_COMPILE_OPTIONS})
|
||||
if(WARNINGS_AS_ERRORS)
|
||||
target_compile_options(${elf_target} PRIVATE -Werror)
|
||||
endif()
|
||||
if (IS_RELEASE_BUILD)
|
||||
target_compile_options(${elf_target} PRIVATE ${args_OPTIMIZATION})
|
||||
target_link_options(${elf_target} PRIVATE ${args_OPTIMIZATION})
|
||||
endif()
|
||||
target_link_libraries(${elf_target} PRIVATE ${AT32_LINK_LIBRARIES})
|
||||
target_link_options(${elf_target} PRIVATE ${AT32_LINK_OPTIONS} ${args_LINK_OPTIONS})
|
||||
generate_map_file(${elf_target})
|
||||
set_linker_script(${elf_target} ${args_LINKER_SCRIPT})
|
||||
if(args_FILENAME)
|
||||
set(basename ${CMAKE_BINARY_DIR}/${args_FILENAME})
|
||||
set(hex_filename ${basename}.hex)
|
||||
add_hex_target(${args_NAME} ${elf_target} ${hex_filename})
|
||||
set(bin_filename ${basename}.bin)
|
||||
add_bin_target(${args_NAME}.bin ${elf_target} ${bin_filename})
|
||||
endif()
|
||||
if(args_OUTPUT_BIN_FILENAME)
|
||||
set(${args_OUTPUT_BIN_FILENAME} ${bin_filename} PARENT_SCOPE)
|
||||
endif()
|
||||
if(args_OUTPUT_TARGET_NAME)
|
||||
set(${args_OUTPUT_TARGET_NAME} ${elf_target} PARENT_SCOPE)
|
||||
endif()
|
||||
if(args_OUTPUT_HEX_FILENAME)
|
||||
set(${args_OUTPUT_HEX_FILENAME} ${hex_filename} PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Main function of AT32
|
||||
function(target_at32)
|
||||
if(NOT arm-none-eabi STREQUAL TOOLCHAIN)
|
||||
return()
|
||||
endif()
|
||||
# Parse keyword arguments
|
||||
cmake_parse_arguments(
|
||||
args
|
||||
# Boolean arguments
|
||||
"DISABLE_MSC;BOOTLOADER"
|
||||
# Single value arguments
|
||||
"HSE_MHZ;LINKER_SCRIPT;NAME;OPENOCD_TARGET;OPTIMIZATION;STARTUP;SVD"
|
||||
# Multi-value arguments
|
||||
"COMPILE_DEFINITIONS;COMPILE_OPTIONS;INCLUDE_DIRECTORIES;LINK_OPTIONS;SOURCES;MSC_SOURCES;MSC_INCLUDE_DIRECTORIES;VCP_SOURCES;VCP_INCLUDE_DIRECTORIES"
|
||||
# Start parsing after the known arguments
|
||||
${ARGN}
|
||||
)
|
||||
set(name ${args_NAME})
|
||||
|
||||
if (args_HSE_MHZ)
|
||||
set(hse_mhz ${args_HSE_MHZ})
|
||||
else()
|
||||
set(hse_mhz ${AT32_DEFAULT_HSE_MHZ})
|
||||
endif()
|
||||
|
||||
set(target_sources ${AT32_STARTUP_DIR}/${args_STARTUP})
|
||||
list(APPEND target_sources ${args_SOURCES})
|
||||
file(GLOB target_c_sources "${CMAKE_CURRENT_SOURCE_DIR}/*.c")
|
||||
file(GLOB target_h_sources "${CMAKE_CURRENT_SOURCE_DIR}/*.h")
|
||||
list(APPEND target_sources ${target_c_sources} ${target_h_sources})
|
||||
|
||||
set(target_include_directories ${args_INCLUDE_DIRECTORIES})
|
||||
|
||||
set(target_definitions ${AT32_DEFINITIONS} ${COMMON_COMPILE_DEFINITIONS})
|
||||
|
||||
get_at32_target_features(features "${CMAKE_CURRENT_SOURCE_DIR}" ${name})
|
||||
set_property(TARGET ${elf_target} PROPERTY FEATURES ${features})
|
||||
|
||||
if(VCP IN_LIST features)
|
||||
list(APPEND target_sources ${AT32_VCP_SRC} ${args_VCP_SOURCES})
|
||||
list(APPEND target_include_directories ${args_VCP_INCLUDE_DIRECTORIES})
|
||||
endif()
|
||||
if(SDCARD IN_LIST features)
|
||||
list(APPEND target_sources ${AT32_SDCARD_SRC} ${AT32_ASYNCFATFS_SRC})
|
||||
endif()
|
||||
|
||||
set(msc_sources)
|
||||
if(NOT args_DISABLE_MSC AND MSC IN_LIST features)
|
||||
list(APPEND target_include_directories ${args_MSC_INCLUDE_DIRECTORIES})
|
||||
list(APPEND msc_sources ${AT32_MSC_SRC} ${args_MSC_SOURCES})
|
||||
list(APPEND target_definitions USE_USB_MSC)
|
||||
if(FLASHFS IN_LIST features)
|
||||
list(APPEND msc_sources ${AT32_MSC_FLASH_SRC})
|
||||
endif()
|
||||
if (SDCARD IN_LIST features)
|
||||
list(APPEND msc_sources ${AT32_MSC_SDCARD_SRC})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
math(EXPR hse_value "${hse_mhz} * 1000000")
|
||||
list(APPEND target_definitions "HSE_VALUE=${hse_value}")
|
||||
|
||||
if (MSP_UART)
|
||||
list(APPEND target_definitions "MSP_UART=${MSP_UART}")
|
||||
endif()
|
||||
|
||||
if(args_COMPILE_DEFINITIONS)
|
||||
list(APPEND target_definitions ${args_COMPILE_DEFINITIONS})
|
||||
endif()
|
||||
if(DEBUG_HARDFAULTS)
|
||||
list(APPEND target_definitions DEBUG_HARDFAULTS)
|
||||
endif()
|
||||
|
||||
string(TOLOWER ${PROJECT_NAME} lowercase_project_name)
|
||||
set(binary_name ${lowercase_project_name}_${FIRMWARE_VERSION}_${name})
|
||||
if(DEFINED BUILD_SUFFIX AND NOT "" STREQUAL "${BUILD_SUFFIX}")
|
||||
set(binary_name "${binary_name}_${BUILD_SUFFIX}")
|
||||
endif()
|
||||
|
||||
# Main firmware
|
||||
add_at32_executable(
|
||||
NAME ${name}
|
||||
FILENAME ${binary_name}
|
||||
SOURCES ${target_sources} ${msc_sources} ${CMSIS_DSP_SRC} ${COMMON_SRC}
|
||||
COMPILE_DEFINITIONS ${target_definitions}
|
||||
COMPILE_OPTIONS ${args_COMPILE_OPTIONS}
|
||||
INCLUDE_DIRECTORIES ${target_include_directories}
|
||||
LINK_OPTIONS ${args_LINK_OPTIONS}
|
||||
LINKER_SCRIPT ${args_LINKER_SCRIPT}
|
||||
OPTIMIZATION ${args_OPTIMIZATION}
|
||||
|
||||
OUTPUT_BIN_FILENAME main_bin_filename
|
||||
OUTPUT_HEX_FILENAME main_hex_filename
|
||||
OUTPUT_TARGET_NAME main_target_name
|
||||
|
||||
)
|
||||
|
||||
set_property(TARGET ${main_target_name} PROPERTY OPENOCD_TARGET ${args_OPENOCD_TARGET})
|
||||
set_property(TARGET ${main_target_name} PROPERTY OPENOCD_DEFAULT_INTERFACE atlink)
|
||||
set_property(TARGET ${main_target_name} PROPERTY SVD ${args_SVD})
|
||||
|
||||
setup_firmware_target(${main_target_name} ${name} ${ARGN})
|
||||
|
||||
if(args_BOOTLOADER)
|
||||
# Bootloader for the target
|
||||
set(bl_suffix _bl)
|
||||
add_at32_executable(
|
||||
NAME ${name}${bl_suffix}
|
||||
FILENAME ${binary_name}${bl_suffix}
|
||||
SOURCES ${target_sources} ${BOOTLOADER_SOURCES}
|
||||
COMPILE_DEFINITIONS ${target_definitions} BOOTLOADER MSP_FIRMWARE_UPDATE
|
||||
COMPILE_OPTIONS ${args_COMPILE_OPTIONS}
|
||||
INCLUDE_DIRECTORIES ${target_include_directories}
|
||||
LINK_OPTIONS ${args_LINK_OPTIONS}
|
||||
LINKER_SCRIPT ${args_LINKER_SCRIPT}${bl_suffix}
|
||||
OPTIMIZATION ${args_OPTIMIZATION}
|
||||
|
||||
OUTPUT_BIN_FILENAME bl_bin_filename
|
||||
OUTPUT_HEX_FILENAME bl_hex_filename
|
||||
OUTPUT_TARGET_NAME bl_target_name
|
||||
)
|
||||
setup_executable(${bl_target_name} ${name})
|
||||
|
||||
# Main firmware, but for running with the bootloader
|
||||
set(for_bl_suffix _for_bl)
|
||||
add_at32_executable(
|
||||
NAME ${name}${for_bl_suffix}
|
||||
FILENAME ${binary_name}${for_bl_suffix}
|
||||
SOURCES ${target_sources} ${msc_sources} ${CMSIS_DSP_SRC} ${COMMON_SRC}
|
||||
COMPILE_DEFINITIONS ${target_definitions} MSP_FIRMWARE_UPDATE
|
||||
COMPILE_OPTIONS ${args_COMPILE_OPTIONS}
|
||||
INCLUDE_DIRECTORIES ${target_include_directories}
|
||||
LINK_OPTIONS ${args_LINK_OPTIONS}
|
||||
LINKER_SCRIPT ${args_LINKER_SCRIPT}${for_bl_suffix}
|
||||
OPTIMIZATION ${args_OPTIMIZATION}
|
||||
|
||||
OUTPUT_BIN_FILENAME for_bl_bin_filename
|
||||
OUTPUT_HEX_FILENAME for_bl_hex_filename
|
||||
OUTPUT_TARGET_NAME for_bl_target_name
|
||||
)
|
||||
setup_executable(${for_bl_target_name} ${name})
|
||||
|
||||
# Combined with bootloader and main firmware
|
||||
set(with_bl_suffix _with_bl)
|
||||
set(combined_hex ${CMAKE_BINARY_DIR}/${binary_name}${with_bl_suffix}.hex)
|
||||
set(with_bl_target ${name}${with_bl_suffix})
|
||||
add_custom_target(${with_bl_target}
|
||||
${CMAKE_SOURCE_DIR}/src/utils/combine_tool ${bl_bin_filename} ${for_bl_bin_filename} ${combined_hex}
|
||||
BYPRODUCTS ${combined_hex}
|
||||
)
|
||||
add_dependencies(${with_bl_target} ${bl_target_name} ${for_bl_target_name})
|
||||
endif()
|
||||
|
||||
# clean_<target>
|
||||
set(generator_cmd "")
|
||||
if (CMAKE_GENERATOR STREQUAL "Unix Makefiles")
|
||||
set(generator_cmd "make")
|
||||
elseif(CMAKE_GENERATOR STREQUAL "Ninja")
|
||||
set(generator_cmd "ninja")
|
||||
endif()
|
||||
if (NOT generator_cmd STREQUAL "")
|
||||
set(clean_target "clean_${name}")
|
||||
add_custom_target(${clean_target}
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMAND ${generator_cmd} clean
|
||||
COMMENT "Removing intermediate files for ${name}")
|
||||
set_property(TARGET ${clean_target} PROPERTY
|
||||
EXCLUDE_FROM_ALL 1
|
||||
EXCLUDE_FROM_DEFAULT_BUILD 1)
|
||||
endif()
|
||||
endfunction()
|
||||
@@ -0,0 +1,45 @@
|
||||
set(AT32_USBCORE_DIR "${MAIN_LIB_DIR}/main/AT32F43x/Middlewares/AT/AT32_USB_Device_Library/Core")
|
||||
set(AT32_USBCDC_DIR "${MAIN_LIB_DIR}/main/AT32F43x/Middlewares/AT/AT32_USB_Device_Library/Class/usbd_class/cdc")
|
||||
set(AT32_USBMSC_DIR "${MAIN_LIB_DIR}/main/AT32F43x/Middlewares/AT/AT32_USB_Device_Library/Class/usbd_class/msc")
|
||||
|
||||
set(AT32F4_USB_INCLUDE_DIRS
|
||||
"${AT32_USBCORE_DIR}/Inc"
|
||||
"${AT32_USBCDC_DIR}"
|
||||
"${AT32_USBMSC_DIR}"
|
||||
)
|
||||
|
||||
set(AT32_USBCORE_SRC
|
||||
usb_core.c
|
||||
usbd_core.c
|
||||
usbd_int.c
|
||||
usbd_sdr.c
|
||||
)
|
||||
list(TRANSFORM AT32_USBCORE_SRC PREPEND "${AT32_USBCORE_DIR}/Src/")
|
||||
|
||||
|
||||
set(AT32_USBCDC_SRC
|
||||
"${AT32_USBCDC_DIR}/cdc_class.c"
|
||||
"${AT32_USBCDC_DIR}/cdc_desc.c"
|
||||
)
|
||||
|
||||
main_sources(AT32F4_VCP_SRC
|
||||
drivers/serial_usb_vcp_at32f43x.c
|
||||
drivers/usb_io.c
|
||||
)
|
||||
|
||||
set(AT32F4_USBMSC_SRC
|
||||
msc_desc.c
|
||||
msc_class.c
|
||||
msc_bot_scsi.c
|
||||
)
|
||||
|
||||
main_sources(AT32F4_MSC_SRC
|
||||
drivers/usb_msc_at32f43x.c
|
||||
)
|
||||
|
||||
list(TRANSFORM AT32F4_USBMSC_SRC PREPEND "${AT32_USBMSC_DIR}/")
|
||||
list(APPEND AT32F4_USBMSC_SRC ${AT32F4_MSC_SRC})
|
||||
|
||||
list(APPEND AT32F4_USB_SRC ${AT32F4_VCP_SRC})
|
||||
list(APPEND AT32F4_USB_SRC ${AT32_USBCORE_SRC})
|
||||
list(APPEND AT32F4_USB_SRC ${AT32_USBCDC_SRC})
|
||||
@@ -0,0 +1,114 @@
|
||||
include(cortex-m4f)
|
||||
include(at32-stdperiph)
|
||||
include(at32f4-usb)
|
||||
|
||||
set(AT32F4_STDPERIPH_DIR "${MAIN_LIB_DIR}/main/AT32F43x/Drivers/AT32F43x_StdPeriph_Driver")
|
||||
set(AT32F4_CMSIS_DEVICE_DIR "${MAIN_LIB_DIR}/main/AT32F43x/Drivers/CMSIS/Device/ST/AT32F43x")
|
||||
set(AT32F4_CMSIS_DRIVERS_DIR "${MAIN_LIB_DIR}/main/AT32F43x/Drivers/CMSIS")
|
||||
|
||||
|
||||
set(AT32F4_STDPERIPH_SRC_EXCLUDES
|
||||
at32f435_437_can.c
|
||||
at32f435_437_dvp.c
|
||||
at32f435_437_emac
|
||||
at32f435_437_xmc.c
|
||||
)
|
||||
|
||||
set(AT32F4_STDPERIPH_SRC_DIR "${AT32F4_STDPERIPH_DIR}/src")
|
||||
glob_except(AT32F4_STDPERIPH_SRC "${AT32F4_STDPERIPH_SRC_DIR}/*.c" "${AT32F4_STDPERIPH_SRC_EXCLUDES}")
|
||||
|
||||
list(APPEND AT32F4_STDPERIPH_SRC "${AT32F4_CMSIS_DEVICE_DIR}/at32f435_437_clock.c" )
|
||||
|
||||
main_sources(AT32F4_SRC
|
||||
target/system_at32f435_437.c
|
||||
config/config_streamer_at32f43x.c
|
||||
config/config_streamer_ram.c
|
||||
config/config_streamer_extflash.c
|
||||
drivers/adc_at32f43x.c
|
||||
drivers/i2c_application.c
|
||||
drivers/bus_i2c_at32f43x.c
|
||||
drivers/bus_spi_at32f43x
|
||||
drivers/serial_uart_hal_at32f43x.c
|
||||
drivers/serial_uart_at32f43x.c
|
||||
|
||||
drivers/system_at32f43x.c
|
||||
drivers/timer.c
|
||||
drivers/timer_impl_stdperiph_at32.c
|
||||
drivers/timer_at32f43x.c
|
||||
drivers/uart_inverter.c
|
||||
drivers/dma_at32f43x.c
|
||||
)
|
||||
|
||||
set(AT32F4_INCLUDE_DIRS
|
||||
${CMSIS_INCLUDE_DIR}
|
||||
${CMSIS_DSP_INCLUDE_DIR}
|
||||
${AT32F4_CMSIS_DRIVERS_DIR}
|
||||
${AT32F4_STDPERIPH_DIR}/inc
|
||||
${AT32F4_CMSIS_DEVICE_DIR}
|
||||
#"${AT32F4_I2C_DIR}"
|
||||
)
|
||||
|
||||
set(AT32F4_DEFINITIONS
|
||||
${CORTEX_M4F_DEFINITIONS}
|
||||
AT32F43x
|
||||
USE_STDPERIPH_DRIVER
|
||||
)
|
||||
|
||||
function(target_at32f43x)
|
||||
target_at32(
|
||||
SOURCES ${AT32_STDPERIPH_SRC} ${AT32F4_SRC}
|
||||
COMPILE_DEFINITIONS ${AT32F4_DEFINITIONS}
|
||||
COMPILE_OPTIONS ${CORTEX_M4F_COMMON_OPTIONS} ${CORTEX_M4F_COMPILE_OPTIONS}
|
||||
INCLUDE_DIRECTORIES ${AT32F4_INCLUDE_DIRS}
|
||||
LINK_OPTIONS ${CORTEX_M4F_COMMON_OPTIONS} ${CORTEX_M4F_LINK_OPTIONS}
|
||||
|
||||
MSC_SOURCES ${AT32F4_USBMSC_SRC} ${AT32F4_MSC_SRC}
|
||||
VCP_SOURCES ${AT32F4_USB_SRC} ${AT32F4_VCP_SRC}
|
||||
VCP_INCLUDE_DIRECTORIES ${AT32F4_USB_INCLUDE_DIRS}
|
||||
|
||||
OPTIMIZATION -O2
|
||||
|
||||
OPENOCD_TARGET at32f437xx
|
||||
|
||||
${ARGN}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
#target_at32f43x_xMT7
|
||||
#target_at32f43x_xGT7
|
||||
|
||||
set(at32f43x_xMT7_COMPILE_DEFINITIONS
|
||||
AT32F437VMT7
|
||||
MCU_FLASH_SIZE=4032
|
||||
)
|
||||
|
||||
function(target_at32f43x_xMT7 name)
|
||||
target_at32f43x(
|
||||
NAME ${name}
|
||||
STARTUP startup_at32f435_437.s
|
||||
SOURCES ${AT32F4_STDPERIPH_SRC}
|
||||
COMPILE_DEFINITIONS ${at32f43x_xMT7_COMPILE_DEFINITIONS}
|
||||
LINKER_SCRIPT at32_flash_f43xM
|
||||
#BOOTLOADER
|
||||
SVD at32f43x_xMT7
|
||||
${ARGN}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
set(at32f43x_xGT7_COMPILE_DEFINITIONS
|
||||
AT32F435RGT7
|
||||
MCU_FLASH_SIZE=1024
|
||||
)
|
||||
|
||||
function(target_at32f43x_xGT7 name)
|
||||
target_at32f43x(
|
||||
NAME ${name}
|
||||
STARTUP startup_at32f435_437.s
|
||||
SOURCES ${AT32F4_STDPERIPH_SRC}
|
||||
COMPILE_DEFINITIONS ${at32f43x_xGT7_COMPILE_DEFINITIONS}
|
||||
LINKER_SCRIPT at32_flash_f43xG
|
||||
#BOOTLOADER
|
||||
SVD at32f43x_xGT7
|
||||
${ARGN}
|
||||
)
|
||||
endfunction()
|
||||
@@ -0,0 +1,22 @@
|
||||
if(DEFINED CI_JOB_INDEX AND DEFINED CI_JOB_COUNT)
|
||||
math(EXPR job_name "${CI_JOB_INDEX}+1")
|
||||
message("-- configuring CI job ${job_name}/${CI_JOB_COUNT}")
|
||||
get_property(targets GLOBAL PROPERTY RELEASE_TARGETS)
|
||||
list(LENGTH targets count)
|
||||
message("-- ${count} total targets")
|
||||
math(EXPR per_job "(${count}+${CI_JOB_COUNT}-1)/${CI_JOB_COUNT}")
|
||||
math(EXPR start "${CI_JOB_INDEX}*${per_job}")
|
||||
message("-- ${per_job} targets per job, starting at ${start}")
|
||||
if(${start} LESS ${count})
|
||||
list(SUBLIST targets ${start} ${per_job} ci_targets)
|
||||
message("-- will build targets: ${ci_targets}")
|
||||
add_custom_target(ci
|
||||
${CMAKE_COMMAND} -E true
|
||||
DEPENDS ${ci_targets}
|
||||
)
|
||||
else()
|
||||
add_custom_target(ci
|
||||
${CMAKE_COMMAND} -E true
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
@@ -0,0 +1,23 @@
|
||||
set(CORTEX_M4F_COMMON_OPTIONS
|
||||
-mthumb
|
||||
-mcpu=cortex-m4
|
||||
-march=armv7e-m
|
||||
-mfloat-abi=hard
|
||||
-mfpu=fpv4-sp-d16
|
||||
-fsingle-precision-constant
|
||||
-Wdouble-promotion
|
||||
)
|
||||
|
||||
set(CORTEX_M4F_COMPILE_OPTIONS
|
||||
)
|
||||
|
||||
set(CORTEX_M4F_LINK_OPTIONS
|
||||
)
|
||||
|
||||
set(CORTEX_M4F_DEFINITIONS
|
||||
__FPU_PRESENT=1
|
||||
ARM_MATH_CM4
|
||||
ARM_MATH_MATRIX_CHECK
|
||||
ARM_MATH_ROUNDING
|
||||
UNALIGNED_SUPPORT_DISABLE
|
||||
)
|
||||
@@ -0,0 +1,22 @@
|
||||
set(CORTEX_M7_COMMON_OPTIONS
|
||||
-mthumb
|
||||
-mcpu=cortex-m7
|
||||
-mfloat-abi=hard
|
||||
-mfpu=fpv5-sp-d16
|
||||
-fsingle-precision-constant
|
||||
-Wdouble-promotion
|
||||
)
|
||||
|
||||
set(CORTEX_M7_COMPILE_OPTIONS
|
||||
)
|
||||
|
||||
set(CORTEX_M7_LINK_OPTIONS
|
||||
)
|
||||
|
||||
set(CORTEX_M7_DEFINITIONS
|
||||
__FPU_PRESENT=1
|
||||
ARM_MATH_CM7
|
||||
ARM_MATH_MATRIX_CHECK
|
||||
ARM_MATH_ROUNDING
|
||||
UNALIGNED_SUPPORT_DISABLE
|
||||
)
|
||||
Executable
+29
@@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
LAST_CMAKE_AT_REV_FILE="docker_cmake.rev"
|
||||
CURR_REV="$(git rev-parse HEAD)"
|
||||
|
||||
initialize_cmake() {
|
||||
echo -e "*** CMake was not initialized yet, doing it now.\n"
|
||||
cmake -GNinja ..
|
||||
echo "$CURR_REV" > "$LAST_CMAKE_AT_REV_FILE"
|
||||
}
|
||||
|
||||
# Check if CMake has never been initialized
|
||||
if [ ! -f build.ninja ]; then
|
||||
initialize_cmake
|
||||
fi
|
||||
|
||||
# Check if CMake was initialized for a different Git revision (new targets may have been added)
|
||||
if [ -f "$LAST_CMAKE_AT_REV_FILE" ]; then
|
||||
LAST_CMAKE_AT_REV="$(cat $LAST_CMAKE_AT_REV_FILE)"
|
||||
if [[ "$LAST_CMAKE_AT_REV" != "SKIP" ]] && [[ "$LAST_CMAKE_AT_REV" != "$CURR_REV" ]]; then
|
||||
initialize_cmake
|
||||
fi
|
||||
else
|
||||
initialize_cmake
|
||||
fi
|
||||
|
||||
# Let Make handle the arguments coming from the build script
|
||||
ninja "$@"
|
||||
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
rm -r build_SITL
|
||||
mkdir -p build_SITL
|
||||
#cmake -DSITL=ON -DWARNINGS_AS_ERRORS=ON -GNinja -B build_SITL ..
|
||||
cmake -DSITL=ON -DDEBUG=ON -DWARNINGS_AS_ERRORS=ON -GNinja -B build_SITL ..
|
||||
cd build_SITL
|
||||
ninja
|
||||
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
cd /src/
|
||||
python3 src/utils/update_cli_docs.py
|
||||
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
cd build_SITL
|
||||
|
||||
#Lauch SITL - configurator only mode
|
||||
./inav_7.0.0_SITL
|
||||
|
||||
#Launch SITL - connect to X-Plane. IP address should be host IP address, not 127.0.0.1. Can be found in X-Plane "Network" tab.
|
||||
#./inav_7.0.0_SITL --sim=xp --simip=192.168.2.105 --simport=49000
|
||||
@@ -0,0 +1,34 @@
|
||||
function(gcc_get_version var)
|
||||
cmake_parse_arguments(args
|
||||
""
|
||||
"TRIPLET;PROGRAM_NAME;PROGRAM_PATH"
|
||||
""
|
||||
${ARGN}
|
||||
)
|
||||
set(prog "gcc")
|
||||
if(args_TRIPLET)
|
||||
set(prog "${args_TRIPLET}-${prog}")
|
||||
endif()
|
||||
if(args_PROGRAM_NAME)
|
||||
set(${args_PROGRAM_NAME} ${prog} PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
find_program(gcc ${prog})
|
||||
if (NOT gcc)
|
||||
set(${var} OFF PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
if(args_PROGRAM_PATH)
|
||||
set(${args_PROGRAM_PATH} ${gcc} PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
execute_process(COMMAND "${gcc}" -dumpversion
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
OUTPUT_VARIABLE version)
|
||||
|
||||
if("" STREQUAL version)
|
||||
set(${var} OFF PARENT_SCOPE)
|
||||
else()
|
||||
set(${var} ${version} PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
@@ -0,0 +1,47 @@
|
||||
|
||||
if(NOT CMAKE_CONFIGURATION_TYPES)
|
||||
set(CMAKE_CONFIGURATION_TYPES Debug Release RelWithDebInfo)
|
||||
endif()
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "")
|
||||
set(CMAKE_BUILD_TYPE RelWithDebInfo)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
set(TOOL_EXECUTABLE_SUFFIX ".exe")
|
||||
endif()
|
||||
|
||||
set(CMAKE_ASM_COMPILER "gcc${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "asm compiler")
|
||||
set(CMAKE_C_COMPILER "gcc${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "c compiler")
|
||||
set(CMAKE_CXX_COMPILER "g++${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "c++ compiler")
|
||||
set(CMAKE_OBJCOPY "objcopy${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "objcopy tool")
|
||||
set(CMAKE_OBJDUMP "objdump${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "objdump tool")
|
||||
set(CMAKE_SIZE "size${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "size tool")
|
||||
if(CMAKE_HOST_APPLE)
|
||||
set(CMAKE_DEBUGGER "lldb${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "debugger")
|
||||
else()
|
||||
set(CMAKE_DEBUGGER "gdb${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "debugger")
|
||||
endif()
|
||||
set(CMAKE_CPPFILT "c++filt${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "c++filt")
|
||||
|
||||
set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "Build Type" FORCE)
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${CMAKE_CONFIGURATION_TYPES})
|
||||
|
||||
set(debug_options "-Og -O0 -g")
|
||||
set(release_options "-Os -DNDEBUG")
|
||||
if(CMAKE_HOST_APPLE)
|
||||
set(relwithdebinfo_options "-g ${release_options}")
|
||||
else()
|
||||
set(relwithdebinfo_options "-ggdb3 ${release_options}")
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS_DEBUG ${debug_options} CACHE INTERNAL "c compiler flags debug")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG ${debug_options} CACHE INTERNAL "c++ compiler flags debug")
|
||||
set(CMAKE_ASM_FLAGS_DEBUG ${debug_options} CACHE INTERNAL "asm compiler flags debug")
|
||||
|
||||
set(CMAKE_C_FLAGS_RELEASE ${release_options} CACHE INTERNAL "c compiler flags release")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE ${release_options} CACHE INTERNAL "cxx compiler flags release")
|
||||
set(CMAKE_ASM_FLAGS_RELEASE ${release_options} CACHE INTERNAL "asm compiler flags release")
|
||||
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO ${relwithdebinfo_options} CACHE INTERNAL "c compiler flags release")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO ${relwithdebinfo_options} CACHE INTERNAL "cxx compiler flags release")
|
||||
set(CMAKE_ASM_FLAGS_RELWITHDEBINFO ${relwithdebinfo_options} CACHE INTERNAL "asm compiler flags release")
|
||||
@@ -0,0 +1,146 @@
|
||||
set(MAIN_INCLUDE_DIRS
|
||||
"${MAIN_LIB_DIR}"
|
||||
"${MAIN_SRC_DIR}"
|
||||
"${MAIN_LIB_DIR}/main/MAVLink"
|
||||
)
|
||||
|
||||
set(MAIN_DEFINITIONS
|
||||
__FORKNAME__=inav
|
||||
__REVISION__="${GIT_REV}"
|
||||
)
|
||||
|
||||
|
||||
# Can't check for OSX yet at this point
|
||||
if(SITL)
|
||||
set(MAIN_COMPILE_OPTIONS
|
||||
-Wall
|
||||
-Wextra
|
||||
-Wdouble-promotion
|
||||
-Wstrict-prototypes
|
||||
-Werror=switch
|
||||
#-Wno-unknown-warning-option
|
||||
)
|
||||
else()
|
||||
set(MAIN_COMPILE_OPTIONS
|
||||
-Wall
|
||||
-Wextra
|
||||
-Wunsafe-loop-optimizations
|
||||
-Wdouble-promotion
|
||||
-Wstrict-prototypes
|
||||
-Werror=switch
|
||||
)
|
||||
endif()
|
||||
|
||||
macro(main_sources var) # list-var src-1...src-n
|
||||
set(${var} ${ARGN})
|
||||
list(TRANSFORM ${var} PREPEND "${MAIN_SRC_DIR}/")
|
||||
endmacro()
|
||||
|
||||
function(exclude var excludes)
|
||||
set(filtered "")
|
||||
foreach(item ${${var}})
|
||||
if (NOT ${item} IN_LIST excludes)
|
||||
list(APPEND filtered ${item})
|
||||
endif()
|
||||
endforeach()
|
||||
set(${var} ${filtered} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(exclude_basenames var excludes)
|
||||
set(filtered "")
|
||||
foreach(item ${${var}})
|
||||
get_filename_component(basename ${item} NAME)
|
||||
if (NOT ${basename} IN_LIST excludes)
|
||||
list(APPEND filtered ${item})
|
||||
endif()
|
||||
endforeach()
|
||||
set(${var} ${filtered} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(glob_except var pattern excludes)
|
||||
file(GLOB results ${pattern})
|
||||
list(LENGTH results count)
|
||||
if(count EQUAL 0)
|
||||
message(FATAL_ERROR "glob with pattern '${pattern}' returned no results")
|
||||
endif()
|
||||
exclude_basenames(results "${excludes}")
|
||||
set(${var} ${results} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(get_generated_files_dir output target_name)
|
||||
set(${output} ${CMAKE_CURRENT_BINARY_DIR}/${target_name} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(setup_executable exe name)
|
||||
get_generated_files_dir(generated_dir ${name})
|
||||
target_compile_options(${exe} PRIVATE ${MAIN_COMPILE_OPTIONS})
|
||||
target_include_directories(${exe} PRIVATE ${generated_dir} ${MAIN_INCLUDE_DIRS})
|
||||
target_compile_definitions(${exe} PRIVATE ${MAIN_DEFINITIONS} __TARGET__="${name}" ${name})
|
||||
# XXX: Don't make SETTINGS_GENERATED_C part of the build,
|
||||
# since it's compiled via #include in settings.c. This will
|
||||
# change once we move off PGs
|
||||
target_sources(${exe} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/${name}/${SETTINGS_GENERATED_H}")
|
||||
set_target_properties(${exe} PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
|
||||
)
|
||||
if(IS_RELEASE_BUILD AND NOT (CMAKE_HOST_APPLE AND SITL))
|
||||
set_target_properties(${exe} PROPERTIES
|
||||
INTERPROCEDURAL_OPTIMIZATION ON
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(setup_firmware_target exe name)
|
||||
setup_executable(${exe} ${name})
|
||||
enable_settings(${exe} ${name})
|
||||
get_property(targets GLOBAL PROPERTY VALID_TARGETS)
|
||||
list(APPEND targets ${name})
|
||||
set_property(GLOBAL PROPERTY VALID_TARGETS "${targets}")
|
||||
if(NOT SITL)
|
||||
setup_openocd(${exe} ${name})
|
||||
setup_svd(${exe} ${name})
|
||||
endif()
|
||||
|
||||
cmake_parse_arguments(args "SKIP_RELEASES" "" "" ${ARGN})
|
||||
if(args_SKIP_RELEASES)
|
||||
set_target_properties(${exe} ${name} PROPERTIES SKIP_RELEASES ON)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(exclude_from_all target)
|
||||
set_target_properties(${target} PROPERTIES
|
||||
TARGET_MESSAGES OFF
|
||||
EXCLUDE_FROM_ALL ON
|
||||
EXCLUDE_FROM_DEFAULT_BUILD ON)
|
||||
endfunction()
|
||||
|
||||
function(collect_targets)
|
||||
get_property(targets GLOBAL PROPERTY VALID_TARGETS)
|
||||
list(SORT targets)
|
||||
set(release_targets)
|
||||
foreach(target ${targets})
|
||||
get_target_property(skip_releases ${target} SKIP_RELEASES)
|
||||
if(NOT skip_releases)
|
||||
list(APPEND release_targets ${target})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
list(JOIN targets " " target_names)
|
||||
list(JOIN release_targets " " release_targets_names)
|
||||
set_property(GLOBAL PROPERTY RELEASE_TARGETS ${release_targets})
|
||||
|
||||
set(list_target_name "targets")
|
||||
add_custom_target(${list_target_name}
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Valid targets: ${target_names}"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Release targets: ${release_targets_names}"
|
||||
)
|
||||
exclude_from_all(${list_target_name})
|
||||
set(release_target_name "release")
|
||||
add_custom_target(${release_target_name}
|
||||
${CMAKE_COMMAND} -E true
|
||||
DEPENDS ${release_targets}
|
||||
)
|
||||
list(LENGTH targets target_count)
|
||||
list(LENGTH release_targets release_target_count)
|
||||
message("-- ${target_count} targets (${release_target_count} for release) found for toolchain ${TOOLCHAIN}")
|
||||
endfunction()
|
||||
@@ -0,0 +1,84 @@
|
||||
set(OPENOCD "" CACHE STRING "path to openocd (default: search for it)")
|
||||
set(OPENOCD_CFG "" CACHE STRING "path to openocd configuration (default: generate automatically)")
|
||||
set(OPENOCD_INTERFACE "" CACHE STRING "openocd interface name (default: automatic depending on target)")
|
||||
|
||||
if (OPENOCD)
|
||||
set(OPENOCD_PATH ${OPENOCD})
|
||||
else()
|
||||
find_program(OPENOCD_FOUND_PATH NAMES openocd openocd.exe)
|
||||
if (NOT OPENOCD_FOUND_PATH)
|
||||
message(STATUS "Could not find openocd, debugging won't be available")
|
||||
else()
|
||||
set(OPENOCD_PATH ${OPENOCD_FOUND_PATH})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(OPENOCD_PATH)
|
||||
# Retrieve version number as a sanity check
|
||||
execute_process(COMMAND ${OPENOCD_PATH} -v
|
||||
OUTPUT_QUIET
|
||||
ERROR_VARIABLE OPENOCD_HELP
|
||||
RESULT_VARIABLE OPENOCD_RESULT)
|
||||
|
||||
string(REPLACE "\n" ";" OPENOCD_HELP_LINES ${OPENOCD_HELP})
|
||||
list(GET OPENOCD_HELP_LINES 0 OPENOCD_FIRST_HELP_LINE)
|
||||
string(REPLACE "\r" "" OPENOCD_HELP_LINE ${OPENOCD_FIRST_HELP_LINE})
|
||||
if (NOT OPENOCD_RESULT EQUAL 0)
|
||||
# User provided an incorrect path
|
||||
message(FATAL_ERROR "error executing ${OPENOCD_PATH} (${OPENOCD_RESULT})")
|
||||
endif()
|
||||
message(STATUS "using openocd: ${OPENOCD_HELP_LINE}")
|
||||
add_custom_target(openocd ${OPENOCD_PATH} -f ${OPENOCD_CFG}
|
||||
COMMENT "Run openocd using OPENOCD_CFG=(${OPENOCD_CFG}) as configuration"
|
||||
USES_TERMINAL
|
||||
)
|
||||
endif()
|
||||
|
||||
function(setup_openocd target_exe target_name)
|
||||
if(OPENOCD_INTERFACE)
|
||||
set(openocd_interface ${OPENOCD_INTERFACE})
|
||||
else()
|
||||
get_property(openocd_interface TARGET ${target_exe} PROPERTY OPENOCD_DEFAULT_INTERFACE)
|
||||
endif()
|
||||
get_property(openocd_target TARGET ${target_exe} PROPERTY OPENOCD_TARGET)
|
||||
if(OPENOCD_CFG OR (openocd_target AND openocd_interface))
|
||||
set(openocd_run_target "openocd_${target_name}")
|
||||
if (OPENOCD_CFG AND NOT OPENOCD_CFG STREQUAL "")
|
||||
get_filename_component(openocd_cfg_path ${OPENOCD_CFG}
|
||||
ABSOLUTE
|
||||
BASE_DIR ${CMAKE_BINARY_DIR})
|
||||
else()
|
||||
set(openocd_cfg_path ${CMAKE_BINARY_DIR}/openocd/${target_name}.cfg)
|
||||
add_custom_command(
|
||||
OUTPUT ${openocd_cfg_path}
|
||||
COMMENT "Generating openocd configuration for ${openocd_target} via ${openocd_interface}"
|
||||
COMMAND ${CMAKE_COMMAND} -P ${MAIN_DIR}/cmake/openocd_cfg.cmake
|
||||
${openocd_target} ${openocd_interface} ${openocd_cfg_path}
|
||||
)
|
||||
endif()
|
||||
|
||||
# Target for openocd configuration
|
||||
set(openocd_cfg_target "openocd_cfg_${target_name}")
|
||||
add_custom_target(${openocd_cfg_target} DEPENDS ${openocd_cfg_path})
|
||||
exclude_from_all(${openocd_cfg_target})
|
||||
|
||||
# Target for running openocd
|
||||
add_custom_target(${openocd_run_target} ${OPENOCD_PATH} -f ${openocd_cfg_path}
|
||||
COMMENT "Running openocd for target ${target_name} via ${openocd_interface}"
|
||||
DEPENDS ${openocd_cfg_path}
|
||||
USES_TERMINAL
|
||||
)
|
||||
exclude_from_all(${openocd_run_target})
|
||||
# Target for flashing via openocd
|
||||
set(openocd_flash_target "openocd_flash_${target_name}")
|
||||
add_custom_target(${openocd_flash_target} ${CMAKE_COMMAND} -E env
|
||||
OPENOCD_CMD=${OPENOCD_PATH}
|
||||
${MAIN_UTILS_DIR}/openocd_flash.py -f
|
||||
${openocd_cfg_path} $<TARGET_FILE:${target_exe}>
|
||||
|
||||
COMMENT "Flashing ${target_name} with openocd"
|
||||
DEPENDS ${openocd_cfg_path} ${target_exe}
|
||||
)
|
||||
exclude_from_all(${openocd_flash_target})
|
||||
endif()
|
||||
endfunction()
|
||||
@@ -0,0 +1,20 @@
|
||||
# This is called from the targets that build the
|
||||
# openocd.cfg file
|
||||
if(NOT CMAKE_ARGC EQUAL 6)
|
||||
message(FATAL_ERROR "usage: cmake -P openocd_cfg.cmake <target> <interface> <output>")
|
||||
endif()
|
||||
|
||||
set(OPENOCD_TARGET ${CMAKE_ARGV3})
|
||||
set(OPENOCD_INTERFACE ${CMAKE_ARGV4})
|
||||
set(OUTPUT ${CMAKE_ARGV5})
|
||||
|
||||
set(opencd_cfg)
|
||||
list(APPEND openocd_cfg "source [find interface/${OPENOCD_INTERFACE}.cfg]")
|
||||
list(APPEND openocd_cfg "source [find target/${OPENOCD_TARGET}.cfg]")
|
||||
list(APPEND openocd_cfg "init")
|
||||
list(APPEND openocd_cfg "arm semihosting enable")
|
||||
list(APPEND openocd_cfg "reset halt")
|
||||
list(JOIN openocd_cfg "\n" contents)
|
||||
set(contents "${contents}\n")
|
||||
|
||||
file(WRITE ${OUTPUT} ${contents})
|
||||
@@ -0,0 +1,50 @@
|
||||
adcChannelConfig_t 4 0
|
||||
armingConfig_t 6 3
|
||||
barometerConfig_t 8 5
|
||||
batteryMetersConfig_t 24 2
|
||||
beeperConfig_t 12 2
|
||||
blackboxConfig_t 16 4
|
||||
compassConfig_t 24 6
|
||||
displayConfig_t 1 0
|
||||
djiOsdConfig_t 6 3
|
||||
escSensorConfig_t 4 1
|
||||
ezTuneSettings_t 12 1
|
||||
failsafeConfig_t 22 3
|
||||
featureConfig_t 4 0
|
||||
generalSettings_t 1 0
|
||||
geozone_config_t 20 0
|
||||
gimbalConfig_t 10 1
|
||||
gimbalSerialConfig_t 1 0
|
||||
gpsConfig_t 11 5
|
||||
gyroConfig_t 64 12
|
||||
headTrackerConfig_t 16 1
|
||||
imuConfig_t 16 2
|
||||
ledPinConfig_t 1 0
|
||||
logConfig_t 8 0
|
||||
modeActivationOperatorConfig_t 1 0
|
||||
motorConfig_t 10 11
|
||||
navConfig_t 156 7
|
||||
navFwAutolandConfig_t 16 0
|
||||
opticalFlowConfig_t 8 2
|
||||
osdCommonConfig_t 1 0
|
||||
osdConfig_t 160 15
|
||||
osdJoystickConfig_t 6 0
|
||||
pidAutotuneConfig_t 10 2
|
||||
pidProfile_t 292 11
|
||||
pitotmeterConfig_t 8 2
|
||||
positionEstimationConfig_t 72 8
|
||||
powerLimitsConfig_t 8 1
|
||||
rangefinderConfig_t 2 3
|
||||
rcControlsConfig_t 10 4
|
||||
reversibleMotorsConfig_t 6 0
|
||||
rpmFilterConfig_t 10 1
|
||||
rxConfig_t 36 13
|
||||
servoConfig_t 12 3
|
||||
smartportMasterConfig_t 2 0
|
||||
statsConfig_t 20 2
|
||||
systemConfig_t 40 7
|
||||
telemetryConfig_t 58 8
|
||||
timeConfig_t 4 1
|
||||
vtxConfig_t 55 4
|
||||
vtxSettingsConfig_t 12 2
|
||||
pinioBoxConfig_t 4 1
|
||||
@@ -0,0 +1,49 @@
|
||||
set(SETTINGS_GENERATED "settings_generated")
|
||||
set(SETTINGS_GENERATED_C "${SETTINGS_GENERATED}.c")
|
||||
set(SETTINGS_GENERATED_H "${SETTINGS_GENERATED}.h")
|
||||
set(SETTINGS_FILE "${MAIN_SRC_DIR}/fc/settings.yaml")
|
||||
set(SETTINGS_GENERATOR "${MAIN_UTILS_DIR}/settings.rb")
|
||||
|
||||
include(CMakeParseArguments)
|
||||
|
||||
function(enable_settings exe name)
|
||||
get_generated_files_dir(dir ${name})
|
||||
get_target_property(options ${exe} COMPILE_OPTIONS)
|
||||
get_target_property(includes ${exe} INCLUDE_DIRECTORIES)
|
||||
list(TRANSFORM includes PREPEND "-I")
|
||||
get_target_property(defs ${exe} COMPILE_DEFINITIONS)
|
||||
list(TRANSFORM defs PREPEND "-D")
|
||||
list(APPEND cflags ${options})
|
||||
list(APPEND cflags ${includes})
|
||||
list(APPEND cflags ${defs})
|
||||
|
||||
cmake_parse_arguments(
|
||||
args
|
||||
# Boolean arguments
|
||||
""
|
||||
# Single value arguments
|
||||
"OUTPUTS;SETTINGS_CXX"
|
||||
# Multi-value arguments
|
||||
""
|
||||
# Start parsing after the known arguments
|
||||
${ARGN}
|
||||
)
|
||||
|
||||
find_program(RUBY_EXECUTABLE ruby)
|
||||
if (NOT RUBY_EXECUTABLE)
|
||||
message(FATAL_ERROR "Could not find ruby")
|
||||
endif()
|
||||
|
||||
if(host STREQUAL TOOLCHAIN)
|
||||
set(USE_HOST_GCC "-g")
|
||||
endif()
|
||||
set(output ${dir}/${SETTINGS_GENERATED_H} ${dir}/${SETTINGS_GENERATED_C})
|
||||
add_custom_command(
|
||||
OUTPUT ${output}
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E env CFLAGS="${cflags}" TARGET=${name} PATH="$ENV{PATH}" SETTINGS_CXX=${args_SETTINGS_CXX}
|
||||
${RUBY_EXECUTABLE} ${SETTINGS_GENERATOR} ${MAIN_DIR} ${SETTINGS_FILE} -o "${dir}" ${USE_HOST_GCC}
|
||||
DEPENDS ${SETTINGS_GENERATOR} ${SETTINGS_FILE}
|
||||
)
|
||||
set(${args_OUTPUTS} ${output} PARENT_SCOPE)
|
||||
endfunction()
|
||||
@@ -0,0 +1,176 @@
|
||||
|
||||
main_sources(SITL_COMMON_SRC_EXCLUDES
|
||||
build/atomic.h
|
||||
drivers/system.c
|
||||
drivers/time.c
|
||||
drivers/timer.c
|
||||
drivers/rcc.c
|
||||
drivers/persistent.c
|
||||
drivers/accgyro/accgyro_mpu.c
|
||||
drivers/display_ug2864hsweg01.c
|
||||
io/displayport_oled.c
|
||||
)
|
||||
|
||||
main_sources(SITL_SRC
|
||||
config/config_streamer_file.c
|
||||
drivers/serial_tcp.c
|
||||
drivers/serial_tcp.h
|
||||
target/SITL/sim/realFlight.c
|
||||
target/SITL/sim/realFlight.h
|
||||
target/SITL/sim/simHelper.c
|
||||
target/SITL/sim/simHelper.h
|
||||
target/SITL/sim/soap_client.c
|
||||
target/SITL/sim/soap_client.h
|
||||
target/SITL/sim/xplane.c
|
||||
target/SITL/sim/xplane.h
|
||||
)
|
||||
|
||||
|
||||
if(CMAKE_HOST_APPLE)
|
||||
set(MACOSX ON)
|
||||
endif()
|
||||
|
||||
set(SITL_LINK_OPTIONS
|
||||
-Wl,-L${STM32_LINKER_DIR}
|
||||
)
|
||||
|
||||
if(${CYGWIN})
|
||||
set(SITL_LINK_OPTIONS ${SITL_LINK_OPTIONS} "-static-libgcc")
|
||||
endif()
|
||||
|
||||
set(SITL_LINK_LIBRARIS
|
||||
-lpthread
|
||||
-lm
|
||||
-lc
|
||||
)
|
||||
|
||||
if(NOT MACOSX)
|
||||
set(SITL_LINK_LIBRARIS ${SITL_LINK_LIBRARIS} -lrt)
|
||||
endif()
|
||||
|
||||
set(SITL_COMPILE_OPTIONS
|
||||
-Wno-format #Fixme: Compile for 32bit, but settings.rb has to be adjusted
|
||||
-funsigned-char
|
||||
)
|
||||
|
||||
if(DEBUG)
|
||||
message(STATUS "Debug mode enabled. Adding -g to SITL_COMPILE_OPTIONS.")
|
||||
list(APPEND SITL_COMPILE_OPTIONS -g)
|
||||
endif()
|
||||
|
||||
if(ASAN)
|
||||
message(STATUS "AddressSanitizer enabled.")
|
||||
list(APPEND SITL_COMPILE_OPTIONS -fsanitize=address -fno-omit-frame-pointer)
|
||||
list(APPEND SITL_LINK_OPTIONS -fsanitize=address)
|
||||
endif()
|
||||
|
||||
if(NOT MACOSX)
|
||||
set(SITL_COMPILE_OPTIONS ${SITL_COMPILE_OPTIONS}
|
||||
-Wno-return-local-addr
|
||||
-Wno-error=maybe-uninitialized
|
||||
-fsingle-precision-constant
|
||||
)
|
||||
include(CheckLinkerFlag OPTIONAL)
|
||||
if(COMMAND check_linker_flag)
|
||||
check_linker_flag(C "-Wl,--no-warn-rwx-segments" LINKER_SUPPORTS_NO_RWX_WARNING)
|
||||
endif()
|
||||
if(LINKER_SUPPORTS_NO_RWX_WARNING)
|
||||
set(SITL_LINK_OPTIONS ${SITL_LINK_OPTIONS} "-Wl,--no-warn-rwx-segments")
|
||||
endif()
|
||||
else()
|
||||
set(SITL_COMPILE_OPTIONS ${SITL_COMPILE_OPTIONS}
|
||||
)
|
||||
endif()
|
||||
|
||||
set(SITL_DEFINITIONS
|
||||
SITL_BUILD
|
||||
)
|
||||
|
||||
function (target_sitl name)
|
||||
if(CMAKE_VERSION VERSION_GREATER 3.22)
|
||||
set(CMAKE_C_STANDARD 17)
|
||||
endif()
|
||||
|
||||
if(NOT host STREQUAL TOOLCHAIN)
|
||||
return()
|
||||
endif()
|
||||
|
||||
exclude(COMMON_SRC "${SITL_COMMON_SRC_EXCLUDES}")
|
||||
|
||||
set(target_sources)
|
||||
list(APPEND target_sources ${SITL_SRC})
|
||||
file(GLOB target_c_sources "${CMAKE_CURRENT_SOURCE_DIR}/*.c")
|
||||
file(GLOB target_h_sources "${CMAKE_CURRENT_SOURCE_DIR}/*.h")
|
||||
list(APPEND target_sources ${target_c_sources} ${target_h_sources})
|
||||
|
||||
set(target_definitions ${COMMON_COMPILE_DEFINITIONS})
|
||||
|
||||
set(hse_mhz ${STM32_DEFAULT_HSE_MHZ})
|
||||
math(EXPR hse_value "${hse_mhz} * 1000000")
|
||||
list(APPEND target_definitions "HSE_VALUE=${hse_value}")
|
||||
|
||||
if (MSP_UART)
|
||||
list(APPEND target_definitions "MSP_UART=${MSP_UART}")
|
||||
endif()
|
||||
|
||||
string(TOLOWER ${PROJECT_NAME} lowercase_project_name)
|
||||
set(binary_name ${lowercase_project_name}_${FIRMWARE_VERSION}_${name})
|
||||
if(DEFINED BUILD_SUFFIX AND NOT "" STREQUAL "${BUILD_SUFFIX}")
|
||||
set(binary_name "${binary_name}_${BUILD_SUFFIX}")
|
||||
endif()
|
||||
|
||||
list(APPEND target_definitions ${SITL_DEFINITIONS})
|
||||
set(exe_target ${name}.elf)
|
||||
add_executable(${exe_target})
|
||||
target_sources(${exe_target} PRIVATE ${target_sources} ${COMMON_SRC})
|
||||
target_include_directories(${exe_target} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_compile_definitions(${exe_target} PRIVATE ${target_definitions})
|
||||
|
||||
|
||||
if(WARNINGS_AS_ERRORS)
|
||||
target_compile_options(${exe_target} PRIVATE -Werror)
|
||||
endif()
|
||||
|
||||
target_compile_options(${exe_target} PRIVATE ${SITL_COMPILE_OPTIONS})
|
||||
|
||||
target_link_libraries(${exe_target} PRIVATE ${SITL_LINK_LIBRARIS})
|
||||
target_link_options(${exe_target} PRIVATE ${SITL_LINK_OPTIONS})
|
||||
|
||||
set(script_path ${MAIN_SRC_DIR}/target/link/sitl.ld)
|
||||
if(NOT EXISTS ${script_path})
|
||||
message(FATAL_ERROR "linker script ${script_path} doesn't exist")
|
||||
endif()
|
||||
set_target_properties(${exe_target} PROPERTIES LINK_DEPENDS ${script_path})
|
||||
if(NOT MACOSX)
|
||||
target_link_options(${exe_target} PRIVATE -T${script_path})
|
||||
endif()
|
||||
|
||||
if(${CYGWIN})
|
||||
set(exe_filename ${CMAKE_BINARY_DIR}/${binary_name}.exe)
|
||||
else()
|
||||
set(exe_filename ${CMAKE_BINARY_DIR}/${binary_name})
|
||||
endif()
|
||||
|
||||
add_custom_target(${name} ALL
|
||||
cmake -E copy $<TARGET_FILE:${exe_target}> ${exe_filename}
|
||||
)
|
||||
|
||||
setup_firmware_target(${exe_target} ${name} ${ARGN})
|
||||
#clean_<target>
|
||||
set(generator_cmd "")
|
||||
if (CMAKE_GENERATOR STREQUAL "Unix Makefiles")
|
||||
set(generator_cmd "make")
|
||||
elseif(CMAKE_GENERATOR STREQUAL "Ninja")
|
||||
set(generator_cmd "ninja")
|
||||
endif()
|
||||
if (NOT generator_cmd STREQUAL "")
|
||||
set(clean_target "clean_${name}")
|
||||
add_custom_target(${clean_target}
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMAND ${generator_cmd} clean
|
||||
COMMENT "Removing intermediate files for ${name}")
|
||||
set_target_properties(${clean_target} PROPERTIES
|
||||
EXCLUDE_FROM_ALL ON
|
||||
EXCLUDE_FROM_DEFAULT_BUILD ON)
|
||||
endif()
|
||||
endfunction()
|
||||
@@ -0,0 +1,30 @@
|
||||
main_sources(BOOTLOADER_SOURCES
|
||||
common/log.c
|
||||
common/log.h
|
||||
common/printf.c
|
||||
common/printf.h
|
||||
common/string_light.c
|
||||
common/string_light.h
|
||||
common/typeconversion.c
|
||||
common/typeconversion.h
|
||||
|
||||
drivers/bus.c
|
||||
drivers/bus_busdev_i2c.c
|
||||
drivers/bus_busdev_spi.c
|
||||
drivers/bus_i2c_soft.c
|
||||
drivers/io.c
|
||||
drivers/light_led.c
|
||||
drivers/persistent.c
|
||||
drivers/rcc.c
|
||||
drivers/serial.c
|
||||
drivers/system.c
|
||||
drivers/time.c
|
||||
drivers/timer.c
|
||||
|
||||
fc/firmware_update_common.c
|
||||
fc/firmware_update_common.h
|
||||
|
||||
target/common_hardware.c
|
||||
)
|
||||
|
||||
list(APPEND BOOTLOADER_SOURCES ${MAIN_DIR}/src/bl/bl_main.c)
|
||||
@@ -0,0 +1,4 @@
|
||||
main_sources(STM32_STDPERIPH_SRC
|
||||
drivers/bus_spi.c
|
||||
drivers/serial_uart.c
|
||||
)
|
||||
@@ -0,0 +1,447 @@
|
||||
include(stm32-bootloader)
|
||||
include(stm32f4)
|
||||
include(stm32f7)
|
||||
include(stm32h7)
|
||||
|
||||
include(CMakeParseArguments)
|
||||
|
||||
option(DEBUG_HARDFAULTS "Enable debugging of hard faults via custom handler")
|
||||
option(SEMIHOSTING "Enable semihosting")
|
||||
|
||||
message("-- DEBUG_HARDFAULTS: ${DEBUG_HARDFAULTS}, SEMIHOSTING: ${SEMIHOSTING}")
|
||||
|
||||
set(CMSIS_DIR "${MAIN_LIB_DIR}/main/CMSIS")
|
||||
set(CMSIS_INCLUDE_DIR "${CMSIS_DIR}/Core/Include")
|
||||
set(CMSIS_DSP_DIR "${MAIN_LIB_DIR}/main/CMSIS/DSP")
|
||||
set(CMSIS_DSP_INCLUDE_DIR "${CMSIS_DSP_DIR}/Include")
|
||||
|
||||
set(CMSIS_DSP_SRC
|
||||
BasicMathFunctions/arm_scale_f32.c
|
||||
BasicMathFunctions/arm_sub_f32.c
|
||||
BasicMathFunctions/arm_mult_f32.c
|
||||
BasicMathFunctions/arm_offset_f32.c
|
||||
TransformFunctions/arm_rfft_fast_f32.c
|
||||
TransformFunctions/arm_cfft_f32.c
|
||||
TransformFunctions/arm_rfft_fast_init_f32.c
|
||||
TransformFunctions/arm_cfft_radix8_f32.c
|
||||
TransformFunctions/arm_bitreversal2.S
|
||||
CommonTables/arm_common_tables.c
|
||||
ComplexMathFunctions/arm_cmplx_mag_f32.c
|
||||
StatisticsFunctions/arm_max_f32.c
|
||||
StatisticsFunctions/arm_rms_f32.c
|
||||
StatisticsFunctions/arm_std_f32.c
|
||||
StatisticsFunctions/arm_mean_f32.c
|
||||
)
|
||||
list(TRANSFORM CMSIS_DSP_SRC PREPEND "${CMSIS_DSP_DIR}/Source/")
|
||||
|
||||
set(STM32_STARTUP_DIR "${MAIN_SRC_DIR}/startup")
|
||||
|
||||
main_sources(STM32_VCP_SRC
|
||||
drivers/serial_usb_vcp.c
|
||||
drivers/usb_io.c
|
||||
)
|
||||
|
||||
main_sources(STM32_SDCARD_SRC
|
||||
drivers/sdcard/sdcard.c
|
||||
drivers/sdcard/sdcard_spi.c
|
||||
drivers/sdcard/sdcard_sdio.c
|
||||
drivers/sdcard/sdcard_standard.c
|
||||
)
|
||||
|
||||
# XXX: This code is not STM32 specific
|
||||
main_sources(STM32_ASYNCFATFS_SRC
|
||||
io/asyncfatfs/asyncfatfs.c
|
||||
io/asyncfatfs/fat_standard.c
|
||||
)
|
||||
|
||||
main_sources(STM32_MSC_SRC
|
||||
msc/usbd_storage.c
|
||||
)
|
||||
|
||||
main_sources(STM32_MSC_FLASH_SRC
|
||||
msc/usbd_storage_emfat.c
|
||||
msc/emfat.c
|
||||
msc/emfat_file.c
|
||||
)
|
||||
|
||||
main_sources(STM32_MSC_SDCARD_SRC
|
||||
msc/usbd_storage_sd_spi.c
|
||||
)
|
||||
|
||||
set(STM32_INCLUDE_DIRS
|
||||
"${CMSIS_INCLUDE_DIR}"
|
||||
"${CMSIS_DSP_INCLUDE_DIR}"
|
||||
"${MAIN_SRC_DIR}/target"
|
||||
)
|
||||
|
||||
set(STM32_DEFINITIONS
|
||||
)
|
||||
set(STM32_DEFAULT_HSE_MHZ 8)
|
||||
set(STM32_LINKER_DIR "${MAIN_SRC_DIR}/target/link")
|
||||
set(STM32_COMPILE_OPTIONS
|
||||
-ffunction-sections
|
||||
-fdata-sections
|
||||
-fno-common
|
||||
)
|
||||
|
||||
set(STM32_LINK_LIBRARIES
|
||||
-lm
|
||||
-lc
|
||||
)
|
||||
|
||||
if(SEMIHOSTING)
|
||||
list(APPEND STM32_LINK_LIBRARIES --specs=rdimon.specs -lrdimon)
|
||||
list(APPEND STM32_DEFINITIONS SEMIHOSTING)
|
||||
else()
|
||||
list(APPEND STM32_LINK_LIBRARIES -lnosys)
|
||||
endif()
|
||||
|
||||
set(STM32_LINK_OPTIONS
|
||||
-nostartfiles
|
||||
--specs=nano.specs
|
||||
-static
|
||||
-Wl,-gc-sections
|
||||
-Wl,-L${STM32_LINKER_DIR}
|
||||
-Wl,--cref
|
||||
-Wl,--no-wchar-size-warning
|
||||
-Wl,--print-memory-usage
|
||||
)
|
||||
|
||||
macro(get_stm32_target_features output_var dir target_name)
|
||||
execute_process(COMMAND "${CMAKE_C_COMPILER}" -E -dD -D${ARGV2} "${ARGV1}/target.h"
|
||||
ERROR_VARIABLE _errors
|
||||
RESULT_VARIABLE _result
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
OUTPUT_VARIABLE _contents)
|
||||
|
||||
if(NOT _result EQUAL 0)
|
||||
message(FATAL_ERROR "error extracting features for stm32 target ${ARGV2}: ${_errors}")
|
||||
endif()
|
||||
|
||||
string(REGEX MATCH "#define[\t ]+USE_VCP" HAS_VCP ${_contents})
|
||||
if(HAS_VCP)
|
||||
list(APPEND ${ARGV0} VCP)
|
||||
endif()
|
||||
string(REGEX MATCH "define[\t ]+USE_FLASHFS" HAS_FLASHFS ${_contents})
|
||||
if(HAS_FLASHFS)
|
||||
list(APPEND ${ARGV0} FLASHFS)
|
||||
endif()
|
||||
string(REGEX MATCH "define[\t ]+USE_SDCARD" HAS_SDCARD ${_contents})
|
||||
if (HAS_SDCARD)
|
||||
list(APPEND ${ARGV0} SDCARD)
|
||||
string(REGEX MATCH "define[\t ]+USE_SDCARD_SDIO" HAS_SDIO ${_contents})
|
||||
if (HAS_SDIO)
|
||||
list(APPEND ${ARGV0} SDIO)
|
||||
endif()
|
||||
endif()
|
||||
if(HAS_FLASHFS OR HAS_SDCARD)
|
||||
list(APPEND ${ARGV0} MSC)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
function(get_stm32_flash_size out size)
|
||||
# 4: 16, 6: 32, 8: 64, B: 128, C: 256, D: 384, E: 512, F: 768, G: 1024, H: 1536, I: 2048 KiB
|
||||
string(TOUPPER ${size} s)
|
||||
if(${s} STREQUAL "4")
|
||||
set(${out} 16 PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(${s} STREQUAL "6")
|
||||
set(${out} 32 PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(${s} STREQUAL "8")
|
||||
set(${out} 64 PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(${s} STREQUAL "8")
|
||||
set(${out} 64 PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(${s} STREQUAL "B")
|
||||
set(${out} 128 PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(${s} STREQUAL "C")
|
||||
set(${out} 256 PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(${s} STREQUAL "D")
|
||||
set(${out} 384 PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(${s} STREQUAL "E")
|
||||
set(${out} 512 PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(${s} STREQUAL "F")
|
||||
set(${out} 768 PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(${s} STREQUAL "G")
|
||||
set(${out} 1024 PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(${s} STREQUAL "H")
|
||||
set(${out} 1536 PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(${s} STREQUAL "I")
|
||||
set(${out} 2048 PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(add_hex_target name exe hex)
|
||||
add_custom_target(${name} ALL
|
||||
cmake -E env PATH="$ENV{PATH}"
|
||||
# TODO: Overriding the start address with --set-start 0x08000000
|
||||
# seems to be required due to some incorrect assumptions about .hex
|
||||
# files in the configurator. Verify wether that's the case and fix
|
||||
# the bug in configurator or delete this comment.
|
||||
${CMAKE_OBJCOPY} -Oihex --set-start 0x08000000 $<TARGET_FILE:${exe}> ${hex}
|
||||
BYPRODUCTS ${hex}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
function(add_bin_target name exe bin)
|
||||
add_custom_target(${name}
|
||||
cmake -E env PATH="$ENV{PATH}"
|
||||
${CMAKE_OBJCOPY} -Obinary $<TARGET_FILE:${exe}> ${bin}
|
||||
BYPRODUCTS ${bin}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
function(generate_map_file target)
|
||||
if(CMAKE_VERSION VERSION_LESS 3.15)
|
||||
set(map "$<TARGET_FILE:${target}>.map")
|
||||
else()
|
||||
set(map "$<TARGET_FILE_DIR:${target}>/$<TARGET_FILE_BASE_NAME:${target}>.map")
|
||||
endif()
|
||||
target_link_options(${target} PRIVATE "-Wl,-Map,${map}")
|
||||
endfunction()
|
||||
|
||||
function(set_linker_script target script)
|
||||
set(script_path ${STM32_LINKER_DIR}/${args_LINKER_SCRIPT}.ld)
|
||||
if(NOT EXISTS ${script_path})
|
||||
message(FATAL_ERROR "linker script ${script_path} doesn't exist")
|
||||
endif()
|
||||
set_target_properties(${target} PROPERTIES LINK_DEPENDS ${script_path})
|
||||
target_link_options(${elf_target} PRIVATE -T${script_path})
|
||||
endfunction()
|
||||
|
||||
function(add_stm32_executable)
|
||||
cmake_parse_arguments(
|
||||
args
|
||||
# Boolean arguments
|
||||
""
|
||||
# Single value arguments
|
||||
"FILENAME;NAME;OPTIMIZATION;OUTPUT_BIN_FILENAME;OUTPUT_HEX_FILENAME;OUTPUT_TARGET_NAME"
|
||||
# Multi-value arguments
|
||||
"COMPILE_DEFINITIONS;COMPILE_OPTIONS;INCLUDE_DIRECTORIES;LINK_OPTIONS;LINKER_SCRIPT;SOURCES"
|
||||
# Start parsing after the known arguments
|
||||
${ARGN}
|
||||
)
|
||||
set(elf_target ${args_NAME}.elf)
|
||||
add_executable(${elf_target})
|
||||
target_sources(${elf_target} PRIVATE ${args_SOURCES})
|
||||
target_include_directories(${elf_target} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${args_INCLUDE_DIRECTORIES} ${STM32_INCLUDE_DIRS})
|
||||
target_compile_definitions(${elf_target} PRIVATE ${args_COMPILE_DEFINITIONS})
|
||||
target_compile_options(${elf_target} PRIVATE ${STM32_COMPILE_OPTIONS} ${args_COMPILE_OPTIONS})
|
||||
if(WARNINGS_AS_ERRORS)
|
||||
target_compile_options(${elf_target} PRIVATE -Werror)
|
||||
endif()
|
||||
if (IS_RELEASE_BUILD)
|
||||
target_compile_options(${elf_target} PRIVATE ${args_OPTIMIZATION})
|
||||
target_link_options(${elf_target} PRIVATE ${args_OPTIMIZATION})
|
||||
endif()
|
||||
target_link_libraries(${elf_target} PRIVATE ${STM32_LINK_LIBRARIES})
|
||||
target_link_options(${elf_target} PRIVATE ${STM32_LINK_OPTIONS} ${args_LINK_OPTIONS})
|
||||
generate_map_file(${elf_target})
|
||||
set_linker_script(${elf_target} ${args_LINKER_SCRIPT})
|
||||
if(args_FILENAME)
|
||||
set(basename ${CMAKE_BINARY_DIR}/${args_FILENAME})
|
||||
set(hex_filename ${basename}.hex)
|
||||
add_hex_target(${args_NAME} ${elf_target} ${hex_filename})
|
||||
set(bin_filename ${basename}.bin)
|
||||
add_bin_target(${args_NAME}.bin ${elf_target} ${bin_filename})
|
||||
endif()
|
||||
if(args_OUTPUT_BIN_FILENAME)
|
||||
set(${args_OUTPUT_BIN_FILENAME} ${bin_filename} PARENT_SCOPE)
|
||||
endif()
|
||||
if(args_OUTPUT_TARGET_NAME)
|
||||
set(${args_OUTPUT_TARGET_NAME} ${elf_target} PARENT_SCOPE)
|
||||
endif()
|
||||
if(args_OUTPUT_HEX_FILENAME)
|
||||
set(${args_OUTPUT_HEX_FILENAME} ${hex_filename} PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(target_stm32)
|
||||
if(NOT arm-none-eabi STREQUAL TOOLCHAIN)
|
||||
return()
|
||||
endif()
|
||||
# Parse keyword arguments
|
||||
cmake_parse_arguments(
|
||||
args
|
||||
# Boolean arguments
|
||||
"DISABLE_MSC;BOOTLOADER;NO_BOOTLOADER"
|
||||
# Single value arguments
|
||||
"HSE_MHZ;LINKER_SCRIPT;NAME;OPENOCD_TARGET;OPTIMIZATION;STARTUP;SVD"
|
||||
# Multi-value arguments
|
||||
"COMPILE_DEFINITIONS;COMPILE_OPTIONS;INCLUDE_DIRECTORIES;LINK_OPTIONS;SOURCES;MSC_SOURCES;MSC_INCLUDE_DIRECTORIES;VCP_SOURCES;VCP_INCLUDE_DIRECTORIES"
|
||||
# Start parsing after the known arguments
|
||||
${ARGN}
|
||||
)
|
||||
set(name ${args_NAME})
|
||||
|
||||
if (args_HSE_MHZ)
|
||||
set(hse_mhz ${args_HSE_MHZ})
|
||||
else()
|
||||
set(hse_mhz ${STM32_DEFAULT_HSE_MHZ})
|
||||
endif()
|
||||
|
||||
set(target_sources ${STM32_STARTUP_DIR}/${args_STARTUP})
|
||||
list(APPEND target_sources ${args_SOURCES})
|
||||
file(GLOB target_c_sources "${CMAKE_CURRENT_SOURCE_DIR}/*.c")
|
||||
file(GLOB target_h_sources "${CMAKE_CURRENT_SOURCE_DIR}/*.h")
|
||||
list(APPEND target_sources ${target_c_sources} ${target_h_sources})
|
||||
|
||||
set(target_include_directories ${args_INCLUDE_DIRECTORIES})
|
||||
|
||||
set(target_definitions ${STM32_DEFINITIONS} ${COMMON_COMPILE_DEFINITIONS})
|
||||
|
||||
get_stm32_target_features(features "${CMAKE_CURRENT_SOURCE_DIR}" ${name})
|
||||
set_property(TARGET ${elf_target} PROPERTY FEATURES ${features})
|
||||
|
||||
if(VCP IN_LIST features)
|
||||
list(APPEND target_sources ${STM32_VCP_SRC} ${args_VCP_SOURCES})
|
||||
list(APPEND target_include_directories ${args_VCP_INCLUDE_DIRECTORIES})
|
||||
endif()
|
||||
if(SDCARD IN_LIST features)
|
||||
list(APPEND target_sources ${STM32_SDCARD_SRC} ${STM32_ASYNCFATFS_SRC})
|
||||
endif()
|
||||
|
||||
set(msc_sources)
|
||||
if(NOT args_DISABLE_MSC AND MSC IN_LIST features)
|
||||
list(APPEND target_include_directories ${args_MSC_INCLUDE_DIRECTORIES})
|
||||
list(APPEND msc_sources ${STM32_MSC_SRC} ${args_MSC_SOURCES})
|
||||
list(APPEND target_definitions USE_USB_MSC)
|
||||
if(FLASHFS IN_LIST features)
|
||||
list(APPEND msc_sources ${STM32_MSC_FLASH_SRC})
|
||||
endif()
|
||||
if (SDCARD IN_LIST features)
|
||||
list(APPEND msc_sources ${STM32_MSC_SDCARD_SRC})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
math(EXPR hse_value "${hse_mhz} * 1000000")
|
||||
list(APPEND target_definitions "HSE_VALUE=${hse_value}")
|
||||
|
||||
if (MSP_UART)
|
||||
list(APPEND target_definitions "MSP_UART=${MSP_UART}")
|
||||
endif()
|
||||
|
||||
if(args_COMPILE_DEFINITIONS)
|
||||
list(APPEND target_definitions ${args_COMPILE_DEFINITIONS})
|
||||
endif()
|
||||
if(DEBUG_HARDFAULTS)
|
||||
list(APPEND target_definitions DEBUG_HARDFAULTS)
|
||||
endif()
|
||||
|
||||
string(TOLOWER ${PROJECT_NAME} lowercase_project_name)
|
||||
set(binary_name ${lowercase_project_name}_${FIRMWARE_VERSION}_${name})
|
||||
if(DEFINED BUILD_SUFFIX AND NOT "" STREQUAL "${BUILD_SUFFIX}")
|
||||
set(binary_name "${binary_name}_${BUILD_SUFFIX}")
|
||||
endif()
|
||||
|
||||
# Main firmware
|
||||
add_stm32_executable(
|
||||
NAME ${name}
|
||||
FILENAME ${binary_name}
|
||||
SOURCES ${target_sources} ${msc_sources} ${CMSIS_DSP_SRC} ${COMMON_SRC}
|
||||
COMPILE_DEFINITIONS ${target_definitions}
|
||||
COMPILE_OPTIONS ${args_COMPILE_OPTIONS}
|
||||
INCLUDE_DIRECTORIES ${target_include_directories}
|
||||
LINK_OPTIONS ${args_LINK_OPTIONS}
|
||||
LINKER_SCRIPT ${args_LINKER_SCRIPT}
|
||||
OPTIMIZATION ${args_OPTIMIZATION}
|
||||
|
||||
OUTPUT_HEX_FILENAME main_hex_filename
|
||||
OUTPUT_TARGET_NAME main_target_name
|
||||
)
|
||||
|
||||
set_property(TARGET ${main_target_name} PROPERTY OPENOCD_TARGET ${args_OPENOCD_TARGET})
|
||||
set_property(TARGET ${main_target_name} PROPERTY OPENOCD_DEFAULT_INTERFACE stlink)
|
||||
set_property(TARGET ${main_target_name} PROPERTY SVD ${args_SVD})
|
||||
|
||||
setup_firmware_target(${main_target_name} ${name} ${ARGN})
|
||||
|
||||
if(args_BOOTLOADER AND NOT args_NO_BOOTLOADER)
|
||||
# Bootloader for the target
|
||||
set(bl_suffix _bl)
|
||||
add_stm32_executable(
|
||||
NAME ${name}${bl_suffix}
|
||||
FILENAME ${binary_name}${bl_suffix}
|
||||
SOURCES ${target_sources} ${BOOTLOADER_SOURCES}
|
||||
COMPILE_DEFINITIONS ${target_definitions} BOOTLOADER MSP_FIRMWARE_UPDATE
|
||||
COMPILE_OPTIONS ${args_COMPILE_OPTIONS}
|
||||
INCLUDE_DIRECTORIES ${target_include_directories}
|
||||
LINK_OPTIONS ${args_LINK_OPTIONS}
|
||||
LINKER_SCRIPT ${args_LINKER_SCRIPT}${bl_suffix}
|
||||
OPTIMIZATION ${args_OPTIMIZATION}
|
||||
|
||||
OUTPUT_BIN_FILENAME bl_bin_filename
|
||||
OUTPUT_HEX_FILENAME bl_hex_filename
|
||||
OUTPUT_TARGET_NAME bl_target_name
|
||||
)
|
||||
setup_executable(${bl_target_name} ${name})
|
||||
|
||||
# Main firmware, but for running with the bootloader
|
||||
set(for_bl_suffix _for_bl)
|
||||
add_stm32_executable(
|
||||
NAME ${name}${for_bl_suffix}
|
||||
FILENAME ${binary_name}${for_bl_suffix}
|
||||
SOURCES ${target_sources} ${msc_sources} ${CMSIS_DSP_SRC} ${COMMON_SRC}
|
||||
COMPILE_DEFINITIONS ${target_definitions} MSP_FIRMWARE_UPDATE
|
||||
COMPILE_OPTIONS ${args_COMPILE_OPTIONS}
|
||||
INCLUDE_DIRECTORIES ${target_include_directories}
|
||||
LINK_OPTIONS ${args_LINK_OPTIONS}
|
||||
LINKER_SCRIPT ${args_LINKER_SCRIPT}${for_bl_suffix}
|
||||
OPTIMIZATION ${args_OPTIMIZATION}
|
||||
|
||||
OUTPUT_BIN_FILENAME for_bl_bin_filename
|
||||
OUTPUT_HEX_FILENAME for_bl_hex_filename
|
||||
OUTPUT_TARGET_NAME for_bl_target_name
|
||||
)
|
||||
setup_executable(${for_bl_target_name} ${name})
|
||||
|
||||
# Combined with bootloader and main firmware
|
||||
set(with_bl_suffix _with_bl)
|
||||
set(combined_hex ${CMAKE_BINARY_DIR}/${binary_name}${with_bl_suffix}.hex)
|
||||
set(with_bl_target ${name}${with_bl_suffix})
|
||||
add_custom_target(${with_bl_target}
|
||||
${CMAKE_SOURCE_DIR}/src/utils/combine_tool ${bl_bin_filename} ${for_bl_bin_filename} ${combined_hex}
|
||||
BYPRODUCTS ${combined_hex}
|
||||
)
|
||||
add_dependencies(${with_bl_target} ${bl_target_name} ${for_bl_target_name})
|
||||
endif()
|
||||
|
||||
# clean_<target>
|
||||
set(generator_cmd "")
|
||||
if (CMAKE_GENERATOR STREQUAL "Unix Makefiles")
|
||||
set(generator_cmd "make")
|
||||
elseif(CMAKE_GENERATOR STREQUAL "Ninja")
|
||||
set(generator_cmd "ninja")
|
||||
endif()
|
||||
if (NOT generator_cmd STREQUAL "")
|
||||
set(clean_target "clean_${name}")
|
||||
add_custom_target(${clean_target}
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMAND ${generator_cmd} clean
|
||||
COMMENT "Removing intermediate files for ${name}")
|
||||
set_property(TARGET ${clean_target} PROPERTY
|
||||
EXCLUDE_FROM_ALL 1
|
||||
EXCLUDE_FROM_DEFAULT_BUILD 1)
|
||||
endif()
|
||||
endfunction()
|
||||
@@ -0,0 +1,59 @@
|
||||
set(STM32_USBOTG_DIR "${MAIN_LIB_DIR}/main/STM32_USB_OTG_Driver")
|
||||
set(STM32_USBCORE_DIR "${MAIN_LIB_DIR}/main/STM32_USB_Device_Library/Core")
|
||||
set(STM32_USBCDC_DIR "${MAIN_LIB_DIR}/main/STM32_USB_Device_Library/Class/cdc")
|
||||
set(STM32_USBHID_DIR "${MAIN_LIB_DIR}/main/STM32_USB_Device_Library/Class/hid")
|
||||
set(STM32_USBWRAPPER_DIR "${MAIN_LIB_DIR}/main/STM32_USB_Device_Library/Class/hid_cdc_wrapper")
|
||||
set(STM32_USBMSC_DIR "${MAIN_LIB_DIR}/main/STM32_USB_Device_Library/Class/msc")
|
||||
|
||||
set(STM32F4_USB_INCLUDE_DIRS
|
||||
"${STM32_USBOTG_DIR}/inc"
|
||||
"${STM32_USBCORE_DIR}/inc"
|
||||
"${STM32_USBCDC_DIR}/inc"
|
||||
"${STM32_USBHID_DIR}/inc"
|
||||
"${STM32_USBWRAPPER_DIR}/inc"
|
||||
"${STM32_USBMSC_DIR}/inc"
|
||||
)
|
||||
|
||||
set(STM32_USBOTG_SRC
|
||||
usb_core.c
|
||||
usb_dcd.c
|
||||
usb_dcd_int.c
|
||||
)
|
||||
list(TRANSFORM STM32_USBOTG_SRC PREPEND "${STM32_USBOTG_DIR}/src/")
|
||||
|
||||
set(STM32_USBCORE_SRC
|
||||
usbd_core.c
|
||||
usbd_ioreq.c
|
||||
usbd_req.c
|
||||
)
|
||||
list(TRANSFORM STM32_USBCORE_SRC PREPEND "${STM32_USBCORE_DIR}/src/")
|
||||
|
||||
set(STM32_USBCDC_SRC
|
||||
"${STM32_USBCDC_DIR}/src/usbd_cdc_core.c"
|
||||
)
|
||||
|
||||
set(STM32_USBHID_SRC
|
||||
"${STM32_USBHID_DIR}/src/usbd_hid_core.c"
|
||||
)
|
||||
|
||||
set(STM32_USBWRAPPER_SRC
|
||||
"${STM32_USBWRAPPER_DIR}/src/usbd_hid_cdc_wrapper.c"
|
||||
)
|
||||
|
||||
set(STM32F4_USBMSC_SRC
|
||||
usbd_msc_bot.c
|
||||
usbd_msc_core.c
|
||||
usbd_msc_data.c
|
||||
usbd_msc_scsi.c
|
||||
)
|
||||
main_sources(STM32F4_MSC_SRC
|
||||
msc/usbd_msc_desc.c
|
||||
)
|
||||
list(TRANSFORM STM32F4_USBMSC_SRC PREPEND "${STM32_USBMSC_DIR}/src/")
|
||||
list(APPEND STM32F4_USBMSC_SRC ${STM32F4_MSC_SRC})
|
||||
|
||||
list(APPEND STM32F4_USB_SRC ${STM32_USBOTG_SRC})
|
||||
list(APPEND STM32F4_USB_SRC ${STM32_USBCORE_SRC})
|
||||
list(APPEND STM32F4_USB_SRC ${STM32_USBCDC_SRC})
|
||||
list(APPEND STM32F4_USB_SRC ${STM32_USBHID_SRC})
|
||||
list(APPEND STM32F4_USB_SRC ${STM32_USBWRAPPER_SRC})
|
||||
@@ -0,0 +1,158 @@
|
||||
include(cortex-m4f)
|
||||
include(stm32-stdperiph)
|
||||
include(stm32f4-usb)
|
||||
|
||||
set(STM32F4_STDPERIPH_DIR "${MAIN_LIB_DIR}/main/STM32F4/Drivers/STM32F4xx_StdPeriph_Driver")
|
||||
set(STM32F4_CMSIS_DEVICE_DIR "${MAIN_LIB_DIR}/main/STM32F4/Drivers/CMSIS/Device/ST/STM32F4xx")
|
||||
set(STM32F4_CMSIS_DRIVERS_DIR "${MAIN_LIB_DIR}/main/STM32F4/Drivers/CMSIS")
|
||||
set(STM32F4_VCP_DIR "${MAIN_SRC_DIR}/vcpf4")
|
||||
|
||||
set(STM32F4_STDPERIPH_SRC_EXCLUDES
|
||||
stm32f4xx_can.c
|
||||
stm32f4xx_cec.c
|
||||
stm32f4xx_crc.c
|
||||
stm32f4xx_cryp.c
|
||||
stm32f4xx_cryp_aes.c
|
||||
stm32f4xx_cryp_des.c
|
||||
stm32f4xx_cryp_tdes.c
|
||||
stm32f4xx_dbgmcu.c
|
||||
stm32f4xx_dsi.c
|
||||
stm32f4xx_flash_ramfunc.c
|
||||
stm32f4xx_fmpi2c.c
|
||||
stm32f4xx_fmc.c
|
||||
stm32f4xx_hash.c
|
||||
stm32f4xx_hash_md5.c
|
||||
stm32f4xx_hash_sha1.c
|
||||
stm32f4xx_lptim.c
|
||||
stm32f4xx_qspi.c
|
||||
stm32f4xx_sai.c
|
||||
stm32f4xx_spdifrx.c
|
||||
)
|
||||
|
||||
set(STM32F4_STDPERIPH_SRC_DIR "${STM32F4_STDPERIPH_DIR}/src")
|
||||
glob_except(STM32F4_STDPERIPH_SRC "${STM32F4_STDPERIPH_SRC_DIR}/*.c" "${STM32F4_STDPERIPH_SRC_EXCLUDES}")
|
||||
|
||||
main_sources(STM32F4_SRC
|
||||
target/system_stm32f4xx.c
|
||||
|
||||
config/config_streamer_stm32f4.c
|
||||
config/config_streamer_ram.c
|
||||
config/config_streamer_extflash.c
|
||||
|
||||
drivers/adc_stm32f4xx.c
|
||||
drivers/adc_stm32f4xx.c
|
||||
drivers/bus_i2c_stm32f40x.c
|
||||
drivers/serial_uart_stm32f4xx.c
|
||||
drivers/system_stm32f4xx.c
|
||||
drivers/timer.c
|
||||
drivers/timer_impl_stdperiph.c
|
||||
drivers/timer_stm32f4xx.c
|
||||
drivers/uart_inverter.c
|
||||
drivers/dma_stm32f4xx.c
|
||||
drivers/sdcard/sdmmc_sdio_f4xx.c
|
||||
)
|
||||
|
||||
set(STM32F4_VCP_SRC
|
||||
stm32f4xx_it.c
|
||||
usb_bsp.c
|
||||
usbd_desc.c
|
||||
usbd_usr.c
|
||||
usbd_cdc_vcp.c
|
||||
)
|
||||
list(TRANSFORM STM32F4_VCP_SRC PREPEND "${STM32F4_VCP_DIR}/")
|
||||
|
||||
main_sources(STM32F4_MSC_SRC
|
||||
drivers/usb_msc_f4xx.c
|
||||
)
|
||||
|
||||
set(STM32F4_INCLUDE_DIRS
|
||||
"${CMSIS_INCLUDE_DIR}"
|
||||
"${CMSIS_DSP_INCLUDE_DIR}"
|
||||
"${STM32F4_STDPERIPH_DIR}/inc"
|
||||
"${STM32F4_CMSIS_DEVICE_DIR}"
|
||||
"${STM32F4_CMSIS_DRIVERS_DIR}"
|
||||
"${STM32F4_VCP_DIR}"
|
||||
)
|
||||
|
||||
set(STM32F4_DEFINITIONS
|
||||
${CORTEX_M4F_DEFINITIONS}
|
||||
STM32F4
|
||||
USE_STDPERIPH_DRIVER
|
||||
)
|
||||
|
||||
function(target_stm32f4xx)
|
||||
target_stm32(
|
||||
SOURCES ${STM32_STDPERIPH_SRC} ${STM32F4_SRC}
|
||||
COMPILE_DEFINITIONS ${STM32F4_DEFINITIONS}
|
||||
COMPILE_OPTIONS ${CORTEX_M4F_COMMON_OPTIONS} ${CORTEX_M4F_COMPILE_OPTIONS}
|
||||
INCLUDE_DIRECTORIES ${STM32F4_INCLUDE_DIRS}
|
||||
LINK_OPTIONS ${CORTEX_M4F_COMMON_OPTIONS} ${CORTEX_M4F_LINK_OPTIONS}
|
||||
|
||||
MSC_SOURCES ${STM32F4_USBMSC_SRC} ${STM32F4_MSC_SRC}
|
||||
VCP_SOURCES ${STM32F4_USB_SRC} ${STM32F4_VCP_SRC}
|
||||
VCP_INCLUDE_DIRECTORIES ${STM32F4_USB_INCLUDE_DIRS}
|
||||
|
||||
OPTIMIZATION -O2
|
||||
|
||||
OPENOCD_TARGET stm32f4x
|
||||
|
||||
${ARGN}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
set(STM32F405_COMPILE_DEFINITIONS
|
||||
STM32F40_41xxx
|
||||
STM32F405xx
|
||||
MCU_FLASH_SIZE=1024
|
||||
)
|
||||
|
||||
function(target_stm32f405xg name)
|
||||
target_stm32f4xx(
|
||||
NAME ${name}
|
||||
STARTUP startup_stm32f40xx.s
|
||||
SOURCES ${STM32F4_STDPERIPH_SRC}
|
||||
COMPILE_DEFINITIONS ${STM32F405_COMPILE_DEFINITIONS}
|
||||
LINKER_SCRIPT stm32_flash_f405xg
|
||||
SVD STM32F405
|
||||
BOOTLOADER
|
||||
${ARGN}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
set(STM32F411_OR_F427_STDPERIPH_SRC ${STM32F4_STDPERIPH_SRC})
|
||||
set(STM32F411_OR_F427_STDPERIPH_SRC_EXCLUDES "stm32f4xx_fsmc.c")
|
||||
exclude_basenames(STM32F411_OR_F427_STDPERIPH_SRC ${STM32F411_OR_F427_STDPERIPH_SRC_EXCLUDES})
|
||||
|
||||
set(STM32F411_COMPILE_DEFINITIONS
|
||||
STM32F411xE
|
||||
MCU_FLASH_SIZE=512
|
||||
OPTIMIZATION -Os
|
||||
)
|
||||
|
||||
function(target_stm32f411xe name)
|
||||
target_stm32f4xx(
|
||||
NAME ${name}
|
||||
STARTUP startup_stm32f411xe.s
|
||||
SOURCES ${STM32F411_OR_F427_STDPERIPH_SRC}
|
||||
COMPILE_DEFINITIONS ${STM32F411_COMPILE_DEFINITIONS}
|
||||
LINKER_SCRIPT stm32_flash_f411xe
|
||||
SVD STM32F411
|
||||
${ARGN}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
set(STM32F427_COMPILE_DEFINITIONS
|
||||
STM32F427_437xx
|
||||
MCU_FLASH_SIZE=1024
|
||||
)
|
||||
function(target_stm32f427xg name)
|
||||
target_stm32f4xx(
|
||||
NAME ${name}
|
||||
STARTUP startup_stm32f427xx.s
|
||||
SOURCES ${STM32F411_OR_F427_STDPERIPH_SRC}
|
||||
COMPILE_DEFINITIONS ${STM32F427_COMPILE_DEFINITIONS}
|
||||
LINKER_SCRIPT stm32_flash_f427xg
|
||||
SVD STM32F411
|
||||
${ARGN}
|
||||
)
|
||||
endfunction()
|
||||
@@ -0,0 +1,48 @@
|
||||
set(STM32F7_USBCORE_DIR "${MAIN_LIB_DIR}/main/STM32F7/Middlewares/ST/STM32_USB_Device_Library/Core")
|
||||
set(STM32F7_USBCORE_SRC
|
||||
usbd_core.c
|
||||
usbd_ctlreq.c
|
||||
usbd_ioreq.c
|
||||
)
|
||||
list(TRANSFORM STM32F7_USBCORE_SRC PREPEND "${STM32F7_USBCORE_DIR}/Src/")
|
||||
|
||||
set(STM32F7_USBCDC_DIR "${MAIN_LIB_DIR}/main/STM32F7/Middlewares/ST/STM32_USB_Device_Library/Class/CDC")
|
||||
set(STM32F7_USBCDC_SRC
|
||||
usbd_cdc.c
|
||||
)
|
||||
list(TRANSFORM STM32F7_USBCDC_SRC PREPEND "${STM32F7_USBCDC_DIR}/Src/")
|
||||
|
||||
set(STM32F7_USBHID_DIR "${MAIN_LIB_DIR}/main/STM32F7/Middlewares/ST/STM32_USB_Device_Library/Class/HID")
|
||||
set(STM32F7_USBHID_SRC
|
||||
usbd_hid.c
|
||||
)
|
||||
list(TRANSFORM STM32F7_USBHID_SRC PREPEND "${STM32F7_USBHID_DIR}/Src/")
|
||||
|
||||
set(STM32F7_USBCDCHID_DIR "${MAIN_LIB_DIR}/main/STM32F7/Middlewares/ST/STM32_USB_Device_Library/Class/CDC_HID")
|
||||
set(STM32F7_USBCDCHID_SRC
|
||||
usbd_cdc_hid.c
|
||||
)
|
||||
list(TRANSFORM STM32F7_USBCDCHID_SRC PREPEND "${STM32F7_USBCDCHID_DIR}/Src/")
|
||||
|
||||
set(STM32F7_USBMSC_DIR "${MAIN_LIB_DIR}/main/STM32F7/Middlewares/ST/STM32_USB_Device_Library/Class/MSC")
|
||||
set(STM32F7_USBMSC_SRC
|
||||
usbd_msc.c
|
||||
usbd_msc_bot.c
|
||||
usbd_msc_data.c
|
||||
usbd_msc_scsi.c
|
||||
)
|
||||
list(TRANSFORM STM32F7_USBMSC_SRC PREPEND "${STM32F7_USBMSC_DIR}/Src/")
|
||||
|
||||
set(STM32F7_USB_INCLUDE_DIRS
|
||||
"${STM32F7_USBCORE_DIR}/Inc"
|
||||
"${STM32F7_USBCDC_DIR}/Inc"
|
||||
"${STM32F7_USBHID_DIR}/Inc"
|
||||
"${STM32F7_USBCDCHID_DIR}/Inc"
|
||||
"${STM32F7_USBMSC_DIR}/Inc"
|
||||
)
|
||||
|
||||
list(APPEND STM32F7_USB_SRC ${STM32F7_USBCORE_SRC})
|
||||
list(APPEND STM32F7_USB_SRC ${STM32F7_USBCDC_SRC})
|
||||
list(APPEND STM32F7_USB_SRC ${STM32F7_USBHID_SRC})
|
||||
list(APPEND STM32F7_USB_SRC ${STM32F7_USBCDCHID_SRC})
|
||||
list(APPEND STM32F7_USB_SRC ${STM32F7_USBMSC_SRC})
|
||||
@@ -0,0 +1,144 @@
|
||||
include(cortex-m7)
|
||||
include(stm32f7-usb)
|
||||
|
||||
set(STM32F7_HAL_DIR "${MAIN_LIB_DIR}/main/STM32F7/Drivers/STM32F7xx_HAL_Driver")
|
||||
|
||||
set(STM32F7_HAL_SRC
|
||||
stm32f7xx_hal.c
|
||||
stm32f7xx_hal_adc.c
|
||||
stm32f7xx_hal_adc_ex.c
|
||||
stm32f7xx_hal_cortex.c
|
||||
stm32f7xx_hal_dac.c
|
||||
stm32f7xx_hal_dac_ex.c
|
||||
stm32f7xx_hal_dma.c
|
||||
stm32f7xx_hal_dma_ex.c
|
||||
stm32f7xx_hal_flash.c
|
||||
stm32f7xx_hal_flash_ex.c
|
||||
stm32f7xx_hal_gpio.c
|
||||
stm32f7xx_hal_i2c.c
|
||||
stm32f7xx_hal_i2c_ex.c
|
||||
stm32f7xx_hal_pcd.c
|
||||
stm32f7xx_hal_pcd_ex.c
|
||||
stm32f7xx_hal_pwr.c
|
||||
stm32f7xx_hal_pwr_ex.c
|
||||
stm32f7xx_hal_rcc.c
|
||||
stm32f7xx_hal_rcc_ex.c
|
||||
stm32f7xx_hal_rtc.c
|
||||
stm32f7xx_hal_rtc_ex.c
|
||||
stm32f7xx_hal_spi.c
|
||||
stm32f7xx_hal_tim.c
|
||||
stm32f7xx_hal_tim_ex.c
|
||||
stm32f7xx_hal_uart.c
|
||||
stm32f7xx_hal_usart.c
|
||||
stm32f7xx_ll_dma.c
|
||||
stm32f7xx_ll_dma2d.c
|
||||
stm32f7xx_ll_gpio.c
|
||||
stm32f7xx_ll_rcc.c
|
||||
stm32f7xx_ll_spi.c
|
||||
stm32f7xx_ll_tim.c
|
||||
stm32f7xx_ll_usb.c
|
||||
stm32f7xx_ll_utils.c
|
||||
stm32f7xx_hal_sd.c
|
||||
stm32f7xx_ll_sdmmc.c
|
||||
)
|
||||
list(TRANSFORM STM32F7_HAL_SRC PREPEND "${STM32F7_HAL_DIR}/Src/")
|
||||
|
||||
set(STM32F7_CMSIS_DEVICE_DIR "${MAIN_LIB_DIR}/main/STM32F7/Drivers/CMSIS/Device/ST/STM32F7xx")
|
||||
|
||||
set(STM32F7_VCP_DIR "${MAIN_SRC_DIR}/vcp_hal")
|
||||
|
||||
set(STM32F7_VCP_SRC
|
||||
usbd_desc.c
|
||||
usbd_conf_stm32f7xx.c
|
||||
usbd_cdc_interface.c
|
||||
)
|
||||
list(TRANSFORM STM32F7_VCP_SRC PREPEND "${STM32F7_VCP_DIR}/")
|
||||
|
||||
set(STM32F7_INCLUDE_DIRS
|
||||
${STM32F7_HAL_DIR}/Inc
|
||||
${STM32F7_CMSIS_DEVICE_DIR}/Include
|
||||
)
|
||||
|
||||
main_sources(STM32F7_SRC
|
||||
target/system_stm32f7xx.c
|
||||
|
||||
config/config_streamer_stm32f7.c
|
||||
config/config_streamer_ram.c
|
||||
config/config_streamer_extflash.c
|
||||
|
||||
drivers/adc_stm32f7xx.c
|
||||
drivers/bus_i2c_hal.c
|
||||
drivers/dma_stm32f7xx.c
|
||||
drivers/bus_spi_hal_ll.c
|
||||
drivers/timer.c
|
||||
drivers/timer_impl_hal.c
|
||||
drivers/timer_stm32f7xx.c
|
||||
drivers/system_stm32f7xx.c
|
||||
drivers/serial_uart_stm32f7xx.c
|
||||
drivers/serial_uart_hal.c
|
||||
drivers/sdcard/sdmmc_sdio_hal.c
|
||||
)
|
||||
|
||||
main_sources(STM32F7_MSC_SRC
|
||||
drivers/usb_msc_f7xx.c
|
||||
)
|
||||
|
||||
set(STM32F7_DEFINITIONS
|
||||
${CORTEX_M7_DEFINITIONS}
|
||||
USE_HAL_DRIVER
|
||||
USE_FULL_LL_DRIVER
|
||||
)
|
||||
|
||||
function(target_stm32f7xx)
|
||||
target_stm32(
|
||||
SOURCES ${STM32F7_HAL_SRC} ${STM32F7_SRC}
|
||||
COMPILE_DEFINITIONS ${STM32F7_DEFINITIONS}
|
||||
COMPILE_OPTIONS ${CORTEX_M7_COMMON_OPTIONS} ${CORTEX_M7_COMPILE_OPTIONS}
|
||||
INCLUDE_DIRECTORIES ${STM32F7_INCLUDE_DIRS}
|
||||
LINK_OPTIONS ${CORTEX_M7_COMMON_OPTIONS} ${CORTEX_M7_LINK_OPTIONS}
|
||||
|
||||
MSC_SOURCES ${STM32F7_USBMSC_SRC} ${STM32F7_MSC_SRC}
|
||||
VCP_SOURCES ${STM32F7_USB_SRC} ${STM32F7_VCP_SRC}
|
||||
VCP_INCLUDE_DIRECTORIES ${STM32F7_USB_INCLUDE_DIRS} ${STM32F7_VCP_DIR}
|
||||
|
||||
OPENOCD_TARGET stm32f7x
|
||||
|
||||
BOOTLOADER
|
||||
|
||||
${ARGN}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
macro(define_target_stm32f7 subfamily size)
|
||||
function(target_stm32f7${subfamily}x${size} name)
|
||||
set(func_ARGV ARGV)
|
||||
string(TOUPPER ${size} upper_size)
|
||||
get_stm32_flash_size(flash_size ${size})
|
||||
if(flash_size GREATER 512)
|
||||
set(opt -O2)
|
||||
else()
|
||||
set(opt -Os)
|
||||
endif()
|
||||
set(definitions
|
||||
STM32F7
|
||||
STM32F7${subfamily}xx
|
||||
STM32F7${subfamily}x${upper_size}
|
||||
MCU_FLASH_SIZE=${flash_size}
|
||||
)
|
||||
target_stm32f7xx(
|
||||
NAME ${name}
|
||||
STARTUP startup_stm32f7${subfamily}xx.s
|
||||
COMPILE_DEFINITIONS ${definitions}
|
||||
LINKER_SCRIPT stm32_flash_f7${subfamily}x${size}
|
||||
OPTIMIZATION ${opt}
|
||||
|
||||
${${func_ARGV}}
|
||||
)
|
||||
endfunction()
|
||||
endmacro()
|
||||
|
||||
define_target_stm32f7(22 e)
|
||||
define_target_stm32f7(45 g)
|
||||
define_target_stm32f7(46 g)
|
||||
define_target_stm32f7(65 g)
|
||||
define_target_stm32f7(65 i)
|
||||
@@ -0,0 +1,41 @@
|
||||
set(STM32H7_USBCORE_DIR "${MAIN_LIB_DIR}/main/STM32H7/Middlewares/ST/STM32_USB_Device_Library/Core")
|
||||
set(STM32H7_USBCORE_SRC
|
||||
usbd_core.c
|
||||
usbd_ctlreq.c
|
||||
usbd_ioreq.c
|
||||
)
|
||||
list(TRANSFORM STM32H7_USBCORE_SRC PREPEND "${STM32H7_USBCORE_DIR}/Src/")
|
||||
|
||||
set(STM32H7_USBCDC_DIR "${MAIN_LIB_DIR}/main/STM32H7/Middlewares/ST/STM32_USB_Device_Library/Class/CDC")
|
||||
set(STM32H7_USBCDC_SRC
|
||||
usbd_cdc.c
|
||||
)
|
||||
list(TRANSFORM STM32H7_USBCDC_SRC PREPEND "${STM32H7_USBCDC_DIR}/Src/")
|
||||
|
||||
set(STM32H7_USBHID_DIR "${MAIN_LIB_DIR}/main/STM32H7/Middlewares/ST/STM32_USB_Device_Library/Class/HID")
|
||||
set(STM32H7_USBHID_SRC
|
||||
usbd_hid.c
|
||||
)
|
||||
list(TRANSFORM STM32H7_USBHID_SRC PREPEND "${STM32H7_USBHID_DIR}/Src/")
|
||||
|
||||
set(STM32H7_USBMSC_DIR "${MAIN_LIB_DIR}/main/STM32H7/Middlewares/ST/STM32_USB_Device_Library/Class/MSC")
|
||||
set(STM32H7_USBMSC_SRC
|
||||
usbd_msc.c
|
||||
usbd_msc_bot.c
|
||||
usbd_msc_data.c
|
||||
usbd_msc_scsi.c
|
||||
)
|
||||
list(TRANSFORM STM32H7_USBMSC_SRC PREPEND "${STM32H7_USBMSC_DIR}/Src/")
|
||||
|
||||
set(STM32H7_USB_INCLUDE_DIRS
|
||||
"${STM32H7_USBCORE_DIR}/Inc"
|
||||
"${STM32H7_USBCDC_DIR}/Inc"
|
||||
"${STM32H7_USBHID_DIR}/Inc"
|
||||
"${STM32H7_USBMSC_DIR}/Inc"
|
||||
)
|
||||
|
||||
list(APPEND STM32H7_USB_SRC ${STM32H7_USBCORE_SRC})
|
||||
list(APPEND STM32H7_USB_SRC ${STM32H7_USBCDC_SRC})
|
||||
list(APPEND STM32H7_USB_SRC ${STM32H7_USBHID_SRC})
|
||||
#XXX: Not working yet
|
||||
#list(APPEND STM32H7_USB_SRC ${STM32H7_USBMSC_SRC})
|
||||
@@ -0,0 +1,225 @@
|
||||
include(cortex-m7)
|
||||
include(stm32h7-usb)
|
||||
|
||||
set(STM32H7_CMSIS_DEVICE_DIR "${MAIN_LIB_DIR}/main/STM32H7/Drivers/CMSIS/Device/ST/STM32H7xx")
|
||||
set(STM32H7_HAL_DIR "${MAIN_LIB_DIR}/main/STM32H7/Drivers/STM32H7xx_HAL_Driver")
|
||||
|
||||
set(STM32H7_HAL_SRC
|
||||
stm32h7xx_hal.c
|
||||
stm32h7xx_hal_adc.c
|
||||
stm32h7xx_hal_adc_ex.c
|
||||
# stm32h7xx_hal_cec.c
|
||||
# stm32h7xx_hal_comp.c
|
||||
stm32h7xx_hal_cortex.c
|
||||
# stm32h7xx_hal_crc.c
|
||||
# stm32h7xx_hal_crc_ex.c
|
||||
# stm32h7xx_hal_cryp.c
|
||||
# stm32h7xx_hal_cryp_ex.c
|
||||
stm32h7xx_hal_dac.c
|
||||
stm32h7xx_hal_dac_ex.c
|
||||
# stm32h7xx_hal_dcmi.c
|
||||
# stm32h7xx_hal_dfsdm.c
|
||||
# stm32h7xx_hal_dfsdm_ex.c
|
||||
stm32h7xx_hal_dma.c
|
||||
# stm32h7xx_hal_dma2d.c
|
||||
stm32h7xx_hal_dma_ex.c
|
||||
# stm32h7xx_hal_dsi.c
|
||||
stm32h7xx_hal_dts.c
|
||||
# stm32h7xx_hal_eth.c
|
||||
# stm32h7xx_hal_eth_ex.c
|
||||
stm32h7xx_hal_exti.c
|
||||
# stm32h7xx_hal_fdcan.c
|
||||
stm32h7xx_hal_flash.c
|
||||
stm32h7xx_hal_flash_ex.c
|
||||
stm32h7xx_hal_gfxmmu.c
|
||||
stm32h7xx_hal_gpio.c
|
||||
# stm32h7xx_hal_hash.c
|
||||
# stm32h7xx_hal_hash_ex.c
|
||||
# stm32h7xx_hal_hcd.c
|
||||
# stm32h7xx_hal_hrtim.c
|
||||
# stm32h7xx_hal_hsem.c
|
||||
stm32h7xx_hal_i2c.c
|
||||
stm32h7xx_hal_i2c_ex.c
|
||||
# stm32h7xx_hal_i2s.c
|
||||
# stm32h7xx_hal_i2s_ex.c
|
||||
# stm32h7xx_hal_irda.c
|
||||
# stm32h7xx_hal_iwdg.c
|
||||
# stm32h7xx_hal_jpeg.c
|
||||
# stm32h7xx_hal_lptim.c
|
||||
# stm32h7xx_hal_ltdc.c
|
||||
# stm32h7xx_hal_ltdc_ex.c
|
||||
# stm32h7xx_hal_mdios.c
|
||||
# stm32h7xx_hal_mdma.c
|
||||
# stm32h7xx_hal_mmc.c
|
||||
# stm32h7xx_hal_mmc_ex.c
|
||||
# stm32h7xx_hal_nand.c
|
||||
# stm32h7xx_hal_nor.c
|
||||
# stm32h7xx_hal_opamp.c
|
||||
# stm32h7xx_hal_opamp_ex.c
|
||||
stm32h7xx_hal_ospi.c
|
||||
stm32h7xx_hal_otfdec.c
|
||||
stm32h7xx_hal_pcd.c
|
||||
stm32h7xx_hal_pcd_ex.c
|
||||
stm32h7xx_hal_pssi.c
|
||||
stm32h7xx_hal_pwr.c
|
||||
stm32h7xx_hal_pwr_ex.c
|
||||
stm32h7xx_hal_qspi.c
|
||||
# stm32h7xx_hal_ramecc.c
|
||||
stm32h7xx_hal_rcc.c
|
||||
stm32h7xx_hal_rcc_ex.c
|
||||
# stm32h7xx_hal_rng.c
|
||||
# stm32h7xx_hal_rng_ex.c
|
||||
stm32h7xx_hal_rtc.c
|
||||
stm32h7xx_hal_rtc_ex.c
|
||||
# stm32h7xx_hal_sai.c
|
||||
# stm32h7xx_hal_sai_ex.c
|
||||
stm32h7xx_hal_sd.c
|
||||
stm32h7xx_hal_sd_ex.c
|
||||
# stm32h7xx_hal_sdram.c
|
||||
# stm32h7xx_hal_smartcard.c
|
||||
# stm32h7xx_hal_smartcard_ex.c
|
||||
# stm32h7xx_hal_smbus.c
|
||||
# stm32h7xx_hal_spdifrx.c
|
||||
stm32h7xx_hal_spi.c
|
||||
stm32h7xx_hal_spi_ex.c
|
||||
# stm32h7xx_hal_sram.c
|
||||
# stm32h7xx_hal_swpmi.c
|
||||
stm32h7xx_hal_tim.c
|
||||
stm32h7xx_hal_tim_ex.c
|
||||
stm32h7xx_hal_uart.c
|
||||
stm32h7xx_hal_uart_ex.c
|
||||
# stm32h7xx_hal_usart.c
|
||||
# stm32h7xx_hal_usart_ex.c
|
||||
# stm32h7xx_hal_wwdg.c
|
||||
# stm32h7xx_ll_adc.c
|
||||
# stm32h7xx_ll_bdma.c
|
||||
# stm32h7xx_ll_comp.c
|
||||
# stm32h7xx_ll_crc.c
|
||||
stm32h7xx_ll_crs.c
|
||||
# stm32h7xx_ll_dac.c
|
||||
# stm32h7xx_ll_delayblock.c
|
||||
stm32h7xx_ll_dma.c
|
||||
# stm32h7xx_ll_dma2d.c
|
||||
stm32h7xx_ll_exti.c
|
||||
# stm32h7xx_ll_fmc.c
|
||||
# stm32h7xx_ll_gpio.c
|
||||
# stm32h7xx_ll_hrtim.c
|
||||
stm32h7xx_ll_i2c.c
|
||||
# stm32h7xx_ll_lptim.c
|
||||
# stm32h7xx_ll_lpuart.c
|
||||
# stm32h7xx_ll_mdma.c
|
||||
# stm32h7xx_ll_opamp.c
|
||||
# stm32h7xx_ll_pwr.c
|
||||
# stm32h7xx_ll_rcc.c
|
||||
# stm32h7xx_ll_rng.c
|
||||
# stm32h7xx_ll_rtc.c
|
||||
stm32h7xx_ll_sdmmc.c
|
||||
stm32h7xx_ll_spi.c
|
||||
# stm32h7xx_ll_swpmi.c
|
||||
stm32h7xx_ll_tim.c
|
||||
# stm32h7xx_ll_usart.c
|
||||
stm32h7xx_ll_usb.c
|
||||
# stm32h7xx_ll_utils.c
|
||||
)
|
||||
|
||||
list(TRANSFORM STM32H7_HAL_SRC PREPEND "${STM32H7_HAL_DIR}/Src/")
|
||||
|
||||
set(STM32H7_VCP_DIR "${MAIN_SRC_DIR}/vcp_hal")
|
||||
|
||||
set(STM32H7_VCP_SRC
|
||||
usbd_desc.c
|
||||
usbd_conf_stm32h7xx.c
|
||||
usbd_cdc_interface.c
|
||||
)
|
||||
list(TRANSFORM STM32H7_VCP_SRC PREPEND "${STM32H7_VCP_DIR}/")
|
||||
|
||||
set(STM32H7_INCLUDE_DIRS
|
||||
${STM32H7_HAL_DIR}/Inc
|
||||
${STM32H7_CMSIS_DEVICE_DIR}/Include
|
||||
)
|
||||
|
||||
main_sources(STM32H7_SRC
|
||||
target/system_stm32h7xx.c
|
||||
|
||||
config/config_streamer_stm32h7.c
|
||||
config/config_streamer_ram.c
|
||||
config/config_streamer_extflash.c
|
||||
|
||||
drivers/adc_stm32h7xx.c
|
||||
drivers/bus_i2c_hal.c
|
||||
drivers/dma_stm32h7xx.c
|
||||
drivers/bus_spi_hal_ll.c
|
||||
drivers/bus_quadspi.c
|
||||
drivers/bus_quadspi_hal.c
|
||||
drivers/memprot.h
|
||||
drivers/memprot_hal.c
|
||||
drivers/memprot_stm32h7xx.c
|
||||
drivers/timer.c
|
||||
drivers/timer_impl_hal.c
|
||||
drivers/timer_stm32h7xx.c
|
||||
drivers/system_stm32h7xx.c
|
||||
drivers/serial_uart_stm32h7xx.c
|
||||
drivers/serial_uart_hal.c
|
||||
drivers/sdio.h
|
||||
drivers/sdcard/sdmmc_sdio_hal.c
|
||||
)
|
||||
|
||||
main_sources(STM32H7_MSC_SRC
|
||||
drivers/usb_msc_h7xx.c
|
||||
)
|
||||
|
||||
set(STM32H7_DEFINITIONS
|
||||
${CORTEX_M7_DEFINITIONS}
|
||||
USE_HAL_DRIVER
|
||||
USE_FULL_LL_DRIVER
|
||||
MAX_MPU_REGIONS=16
|
||||
)
|
||||
|
||||
function(target_stm32h7xx)
|
||||
target_stm32(
|
||||
SOURCES ${STM32H7_HAL_SRC} ${STM32H7_SRC}
|
||||
COMPILE_DEFINITIONS ${STM32H7_DEFINITIONS}
|
||||
COMPILE_OPTIONS ${CORTEX_M7_COMMON_OPTIONS} ${CORTEX_M7_COMPILE_OPTIONS}
|
||||
INCLUDE_DIRECTORIES ${STM32H7_INCLUDE_DIRS}
|
||||
LINK_OPTIONS ${CORTEX_M7_COMMON_OPTIONS} ${CORTEX_M7_LINK_OPTIONS}
|
||||
|
||||
MSC_SOURCES ${STM32H7_USBMSC_SRC} ${STM32H7_MSC_SRC}
|
||||
VCP_SOURCES ${STM32H7_USB_SRC} ${STM32H7_VCP_SRC}
|
||||
VCP_INCLUDE_DIRECTORIES ${STM32H7_USB_INCLUDE_DIRS} ${STM32H7_VCP_DIR}
|
||||
|
||||
OPTIMIZATION -O2
|
||||
|
||||
OPENOCD_TARGET stm32h7x
|
||||
|
||||
# BOOTLOADER
|
||||
|
||||
${ARGN}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
macro(define_target_stm32h7 subfamily size)
|
||||
function(target_stm32h7${subfamily}x${size} name)
|
||||
set(func_ARGV ARGV)
|
||||
string(TOUPPER ${size} upper_size)
|
||||
get_stm32_flash_size(flash_size ${size})
|
||||
set(definitions
|
||||
STM32H7
|
||||
STM32H7${subfamily}xx
|
||||
STM32H7${subfamily}x${upper_size}
|
||||
# stm32h743xx.h defined FLASH_SIZE, used by HAL, but in bytes
|
||||
# use MCU_FLASH_SIZE since we use KiB in our code
|
||||
MCU_FLASH_SIZE=${flash_size}
|
||||
)
|
||||
target_stm32h7xx(
|
||||
NAME ${name}
|
||||
STARTUP startup_stm32h7${subfamily}xx.s
|
||||
COMPILE_DEFINITIONS ${definitions}
|
||||
LINKER_SCRIPT stm32_flash_h7${subfamily}x${size}
|
||||
${${func_ARGV}}
|
||||
SVD STM32H7${subfamily}
|
||||
)
|
||||
endfunction()
|
||||
endmacro()
|
||||
|
||||
define_target_stm32h7(43 i)
|
||||
define_target_stm32h7(A3 i)
|
||||
@@ -0,0 +1,16 @@
|
||||
function(setup_svd target_exe target_name)
|
||||
get_property(svd_name TARGET ${target_exe} PROPERTY SVD)
|
||||
set(svd_target_name "svd_${target_name}")
|
||||
if (svd_name AND NOT svd_name STREQUAL "")
|
||||
add_custom_target(${svd_target_name}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy
|
||||
${SVD_DIR}/${svd_name}.svd
|
||||
${CMAKE_BINARY_DIR}/svd/${target_name}.svd
|
||||
)
|
||||
else()
|
||||
add_custom_target(${svd_target_name}
|
||||
${CMAKE_COMMAND} -E echo "target ${target_name} does not declare an SVD filename"
|
||||
COMMAND ${CMAKE_COMMAND} -E false)
|
||||
endif()
|
||||
exclude_from_all(${svd_target_name})
|
||||
endfunction()
|
||||
Executable
+224
@@ -0,0 +1,224 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# PG Validation for Release Preparation
|
||||
#
|
||||
# This script validates Parameter Group struct sizes against the reference
|
||||
# target (SPEEDYBEEF745AIO) to catch unversioned struct changes before release.
|
||||
#
|
||||
# Usage: ./cmake/validate-pg-for-release.sh
|
||||
#
|
||||
# Exit codes:
|
||||
# 0 - Validation passed
|
||||
# 1 - Validation failed (size changed without version increment)
|
||||
# 2 - Build or setup error
|
||||
#
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR=$(dirname "$0")
|
||||
REPO_ROOT=$(cd "$SCRIPT_DIR/.." && pwd)
|
||||
REFERENCE_TARGET="SPEEDYBEEF745AIO"
|
||||
BUILD_DIR="$REPO_ROOT/build"
|
||||
DB_FILE="$SCRIPT_DIR/pg_struct_sizes.reference.db"
|
||||
|
||||
echo "🔍 Validating PG struct sizes for release..."
|
||||
echo ""
|
||||
|
||||
# Check prerequisites
|
||||
if ! command -v arm-none-eabi-gcc &> /dev/null; then
|
||||
echo "❌ Error: arm-none-eabi-gcc not found" >&2
|
||||
echo " Install ARM toolchain first" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if ! command -v cmake &> /dev/null; then
|
||||
echo "❌ Error: cmake not found" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ ! -f "$DB_FILE" ]; then
|
||||
echo "❌ Error: Reference database not found: $DB_FILE" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Setup build directory
|
||||
if [ ! -d "$BUILD_DIR" ]; then
|
||||
echo "📁 Creating build directory..."
|
||||
mkdir -p "$BUILD_DIR"
|
||||
cd "$BUILD_DIR"
|
||||
cmake -G "Unix Makefiles" ..
|
||||
else
|
||||
echo "📁 Using existing build directory"
|
||||
cd "$BUILD_DIR"
|
||||
fi
|
||||
|
||||
# Build reference target
|
||||
echo "🔨 Building reference target: $REFERENCE_TARGET..."
|
||||
echo " (This may take a few minutes on first build)"
|
||||
echo ""
|
||||
|
||||
BUILD_LOG=$(mktemp)
|
||||
if ! make "$REFERENCE_TARGET.elf" > "$BUILD_LOG" 2>&1; then
|
||||
echo "❌ Build failed. See $BUILD_LOG for details" >&2
|
||||
tail -30 "$BUILD_LOG" >&2
|
||||
exit 2
|
||||
fi
|
||||
rm -f "$BUILD_LOG"
|
||||
|
||||
ELF_FILE="$BUILD_DIR/bin/$REFERENCE_TARGET.elf"
|
||||
|
||||
if [ ! -f "$ELF_FILE" ]; then
|
||||
echo "❌ Error: ELF file not found: $ELF_FILE" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
echo "✓ Build completed successfully"
|
||||
echo ""
|
||||
|
||||
# Extract PG struct sizes from ELF binary
|
||||
echo "📊 Extracting PG struct sizes from binary..."
|
||||
echo ""
|
||||
|
||||
# Detect architecture for correct nm command
|
||||
if command -v arm-none-eabi-nm &> /dev/null && [[ $(file "$ELF_FILE") == *"ARM"* ]]; then
|
||||
NM_CMD="arm-none-eabi-nm"
|
||||
else
|
||||
NM_CMD="nm"
|
||||
fi
|
||||
|
||||
# Extract current sizes and versions
|
||||
TEMP_CURRENT=$(mktemp)
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
$NM_CMD --print-size "$ELF_FILE" 2>/dev/null | grep "pgResetTemplate_" | \
|
||||
while read addr size_hex type symbol; do
|
||||
# Extract config name from symbol
|
||||
config_name="${symbol#pgResetTemplate_}"
|
||||
|
||||
# Convert hex size to decimal
|
||||
size_dec=$((16#$size_hex))
|
||||
|
||||
# Find corresponding struct type and version from PG_REGISTER
|
||||
pg_register_line=$(grep -rh "PG_REGISTER.*$config_name" src/main --include="*.c" 2>/dev/null | head -1)
|
||||
|
||||
struct_type=$(echo "$pg_register_line" | grep -oP 'PG_REGISTER[^(]*\(\K[^,]+' | head -1)
|
||||
|
||||
if [ -z "$struct_type" ]; then
|
||||
# Fallback: convert config name to struct type
|
||||
struct_type="${config_name}_t"
|
||||
fi
|
||||
|
||||
# Extract PG version (4th parameter in PG_REGISTER)
|
||||
version=$(echo "$pg_register_line" | grep -oP 'PG_REGISTER[^(]*\([^,]+,[^,]+,[^,]+,\s*\K\d+' | head -1)
|
||||
|
||||
if [ -z "$version" ]; then
|
||||
version="0"
|
||||
fi
|
||||
|
||||
printf "%-30s %3s %s\n" "$struct_type" "$size_dec" "$version"
|
||||
done | sort -u > "$TEMP_CURRENT"
|
||||
|
||||
# Validate against reference database
|
||||
echo "🔍 Validating against reference database..."
|
||||
echo ""
|
||||
|
||||
FAILED=0
|
||||
ISSUES=""
|
||||
UPDATED=""
|
||||
|
||||
# Check each struct in current binary
|
||||
while read -r struct_type current_size current_version; do
|
||||
[ -z "$struct_type" ] && continue
|
||||
|
||||
# Look up in database
|
||||
db_entry=$(grep "^$struct_type " "$DB_FILE" 2>/dev/null || echo "")
|
||||
|
||||
if [ -z "$db_entry" ]; then
|
||||
# New struct not in database - add it automatically
|
||||
if [ -z "$current_version" ]; then
|
||||
echo " ⚠️ Warning: Cannot find PG version for new struct $struct_type" >&2
|
||||
echo " ℹ️ New: $struct_type (${current_size}B) - skipping (no PG_REGISTER found)"
|
||||
continue
|
||||
fi
|
||||
|
||||
echo " ➕ New: $struct_type (${current_size}B, v$current_version)"
|
||||
|
||||
# Add to database
|
||||
printf "%-30s %3s %s\n" "$struct_type" "$current_size" "$current_version" >> "$DB_FILE"
|
||||
UPDATED="$UPDATED\n • $struct_type: NEW (${current_size}B, v$current_version)"
|
||||
continue
|
||||
fi
|
||||
|
||||
db_size=$(echo "$db_entry" | awk '{print $2}')
|
||||
db_version=$(echo "$db_entry" | awk '{print $3}')
|
||||
|
||||
if [ "$current_size" != "$db_size" ]; then
|
||||
# Size changed - check if version was incremented
|
||||
if [ -z "$current_version" ]; then
|
||||
echo " ⚠️ Warning: Cannot find PG version for $struct_type" >&2
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ "$current_version" -le "$db_version" ]; then
|
||||
# SIZE CHANGED BUT VERSION NOT INCREMENTED - FAIL BUILD
|
||||
echo " ❌ $struct_type: size changed ${db_size}B → ${current_size}B but version not incremented (still v$current_version)"
|
||||
ISSUES="$ISSUES\n • $struct_type: ${db_size}B → ${current_size}B (version $current_version should be $((current_version + 1)))"
|
||||
FAILED=1
|
||||
else
|
||||
# Version was incremented - this is valid, update database
|
||||
echo " ✅ $struct_type: size changed ${db_size}B → ${current_size}B with version increment v$db_version → v$current_version"
|
||||
|
||||
# Update database entry with new size and version
|
||||
sed -i "s|^$struct_type[[:space:]]\+[0-9]\+[[:space:]]\+[0-9]\+$|$(printf "%-30s %3s %s" "$struct_type" "$current_size" "$current_version")|" "$DB_FILE"
|
||||
UPDATED="$UPDATED\n • $struct_type: ${db_size}B → ${current_size}B (v$db_version → v$current_version)"
|
||||
fi
|
||||
else
|
||||
# Size unchanged
|
||||
echo " ✓ $struct_type (${current_size}B)"
|
||||
fi
|
||||
done < "$TEMP_CURRENT"
|
||||
|
||||
rm -f "$TEMP_CURRENT"
|
||||
|
||||
# Report results
|
||||
echo ""
|
||||
|
||||
if [ $FAILED -eq 1 ]; then
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
echo "❌ PG VALIDATION FAILED - DO NOT PROCEED WITH RELEASE"
|
||||
echo ""
|
||||
echo "The following structs changed size without version increments:"
|
||||
echo -e "$ISSUES"
|
||||
echo ""
|
||||
echo "Action required:"
|
||||
echo " 1. Identify which PR(s) changed the affected struct(s)"
|
||||
echo " 2. Create hotfix PR to increment PG version(s)"
|
||||
echo " 3. Merge hotfix to target branch"
|
||||
echo " 4. Re-run this validation"
|
||||
echo ""
|
||||
echo "Fix: Increment PG version in PG_REGISTER for affected structs"
|
||||
echo ""
|
||||
echo "See claude/release-manager/guides/7-pg-validation.md for details"
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -n "$UPDATED" ]; then
|
||||
echo "📝 Database auto-updated for structs with version increments:"
|
||||
echo -e "$UPDATED"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
echo "✅ PG VALIDATION PASSED"
|
||||
echo ""
|
||||
echo "All struct sizes validated successfully against reference target."
|
||||
echo "Safe to proceed with release preparation."
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
|
||||
exit 0
|
||||
File diff suppressed because it is too large
Load Diff
+61681
File diff suppressed because it is too large
Load Diff
+27110
File diff suppressed because it is too large
Load Diff
+63121
File diff suppressed because it is too large
Load Diff
+57155
File diff suppressed because it is too large
Load Diff
+61861
File diff suppressed because it is too large
Load Diff
+71136
File diff suppressed because it is too large
Load Diff
+70681
File diff suppressed because it is too large
Load Diff
+105015
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,28 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
|
||||
// ******* INAV ********
|
||||
// Define the following values in settings.json
|
||||
// - BUILD_DIR: Relative path to the build directory
|
||||
// - TARGET: Target name that you want to launch
|
||||
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Cortex Debug",
|
||||
"cwd": "${workspaceRoot}",
|
||||
"executable": "${config:BUILD_DIR}/bin/${config:TARGET}.elf",
|
||||
"request": "launch",
|
||||
"type": "cortex-debug",
|
||||
"servertype": "openocd",
|
||||
"device": "${config:TARGET}",
|
||||
"configFiles": [
|
||||
"${config:BUILD_DIR}/openocd/${config:TARGET}.cfg"
|
||||
],
|
||||
"preLaunchTask": "openocd-debug-prepare",
|
||||
"svdFile": "${config:BUILD_DIR}/svd/${config:TARGET}.svd",
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"options": {
|
||||
"env": {
|
||||
"TARGET": "${config:TARGET}",
|
||||
}
|
||||
},
|
||||
"tasks": [
|
||||
{
|
||||
"label": "target",
|
||||
"type": "shell",
|
||||
"command": "make", "args": ["-C", "${config:BUILD_DIR}", "${config:TARGET}"],
|
||||
"problemMatcher": "$gcc",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"presentation": {
|
||||
"echo": true,
|
||||
"reveal": "always",
|
||||
"focus": false,
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "flash",
|
||||
"type": "shell",
|
||||
"command": "make", "args": ["-C", "${config:BUILD_DIR}", "openocd_flash_${config:TARGET}"],
|
||||
"dependsOn": "elf"
|
||||
},
|
||||
{
|
||||
"label": "svd",
|
||||
"type": "shell",
|
||||
"command": "make", "args": ["-C", "${config:BUILD_DIR}", "svd_${config:TARGET}"],
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "openocd-cfg",
|
||||
"type": "shell",
|
||||
"command": "make", "args": ["-C", "${config:BUILD_DIR}", "openocd_cfg_${config:TARGET}"],
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "openocd-debug-prepare",
|
||||
"type": "shell",
|
||||
"dependsOn": ["svd", "openocd-cfg", "flash"],
|
||||
"problemMatcher": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
# 1-wire passthrough esc programming
|
||||
|
||||
### ESCs must have the BlHeli Bootloader.
|
||||
|
||||
If your ESCs didn't come with BlHeli Bootloader, you'll need to flash them with an ArduinoISP programmer first. [Here's a guide](http://bit.ly/blheli-f20).
|
||||
|
||||
This is the option you need to select for the bootloader:
|
||||
|
||||

|
||||
|
||||
Currently supported on all boards with at least 128kB of flash memory (all F3, F4 and F7).
|
||||
|
||||
## Usage
|
||||
|
||||
- Plug in the USB cable and connect to your board with the INAV configurator.
|
||||
|
||||
- Open the BlHeli Suite.
|
||||
|
||||
- Ensure you have selected the correct Atmel or SILABS "Cleanflight" option under the "Select ATMEL / SILABS Interface" menu option.
|
||||
|
||||
- Ensure you have port for your external USB/UART adapter selected, if you're using one, otherwise pick the same COM port that you normally use for INAV.
|
||||
|
||||
- Click "Connect" and wait for the connection to complete. If you get a COM error, hit connect again. It will probably work.
|
||||
|
||||
- Use the boxes at the bottom to select the ESCs you have connected. Note that the boxes correspond directly to the ports on your flight controller. For example if you have motors on ports 1-4, pick boxes 1-4 or in the case of a tri-copter that uses motors on ports 3, 4 and 5, select those ports in BlHeli.
|
||||
|
||||
- Click "Read Setup"
|
||||
|
||||
- Use BlHeli suite as normal.
|
||||
|
||||
- When you're finished with one ESC, click "Disconnect"
|
||||
|
||||
## Implementing and Configuring targets
|
||||
|
||||
The following parameters can be used to enable and configure this in the related target.h file:
|
||||
|
||||
USE_SERIAL_1WIRE Enables the 1wire code, defined in target.h
|
||||
|
||||
|
||||
- For new targets
|
||||
|
||||
- in `target.h`
|
||||
|
||||
```
|
||||
// Turn on serial 1wire passthrough
|
||||
#define USE_SERIAL_1WIRE
|
||||
// How many escs does this board support?
|
||||
#define ESC_COUNT 6
|
||||
// STM32F3DISCOVERY TX - PC3 connects to UART RX
|
||||
#define S1W_TX_GPIO GPIOC
|
||||
#define S1W_TX_PIN GPIO_Pin_3
|
||||
// STM32F3DISCOVERY RX - PC1 connects to UART TX
|
||||
#define S1W_RX_GPIO GPIOC
|
||||
#define S1W_RX_PIN GPIO_Pin_1
|
||||
```
|
||||
|
||||
- in `serial_1wire.c`
|
||||
|
||||
```
|
||||
// Define your esc hardware
|
||||
#if defined(STM32F3DISCOVERY)
|
||||
const escHardware_t escHardware[ESC_COUNT] = {
|
||||
{ GPIOD, 12 },
|
||||
{ GPIOD, 13 },
|
||||
{ GPIOD, 14 },
|
||||
{ GPIOD, 15 },
|
||||
{ GPIOA, 1 },
|
||||
{ GPIOA, 2 }
|
||||
};
|
||||
```
|
||||
|
||||
## Development Notes
|
||||
|
||||
On the STM32F3DISCOVERY, an external pullup on the ESC line may be necessary. I needed a 3v, 4.7k pullup.
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
# ADS-B
|
||||
|
||||
[Automatic Dependent Surveillance Broadcast](https://en.wikipedia.org/wiki/Automatic_Dependent_Surveillance%E2%80%93Broadcast)
|
||||
is an air traffic surveillance technology that enables aircraft to be accurately tracked by air traffic controllers and other pilots without the need for conventional radar.
|
||||
|
||||
## Current state
|
||||
|
||||
OSD can be configured to shows the closest aircraft.
|
||||
|
||||
## OSD ADSB Info element
|
||||
* "-" no ADSB device detected
|
||||
* "H" IMU heading is not valid
|
||||
* "G" no GPS fix or less than 4 stats
|
||||
* "[Number]" count of ADSB aircrafts
|
||||
|
||||
## OSD ADSB Warning element
|
||||
OSD can be configured to simple view (one line) or to extended view (two lines) by \
|
||||
`set osd_adsb_warning_style=EXTENDED`
|
||||
|
||||
### Simple view
|
||||
`{distance to vehicle} {direction to vehicle} {altitude diff}`
|
||||
|
||||
### Extended view
|
||||
`{distance to vehicle} {direction to vehicle} {altitude diff}` \
|
||||
`{Emiter Type} {Vehicle direction} {Vehicle Speed}`
|
||||
|
||||

|
||||
|
||||
|
||||
## Hardware
|
||||
|
||||
All ADSB receivers which can send Mavlink [ADSB_VEHICLE](https://mavlink.io/en/messages/common.html#ADSB_VEHICLE) message are supported
|
||||
|
||||
* [PINGRX](https://uavionix.com/product/pingrx-pro/) (not tested)
|
||||
* [TT-SC1](https://www.aerobits.pl/product/aero/) (tested)
|
||||
* [ADSBee1090](https://pantsforbirds.com/adsbee-1090/) (tested)
|
||||
* [SoftRF](https://github.com/lyusupov/SoftRF/wiki/Nano-Edition) (tested)
|
||||
|
||||
## TT-SC1 settings
|
||||
* download software for ADSB TT-SC1 from https://www.aerobits.pl/product/aero/ , file Micro_ADSB_App-vX.XX.X_win_setup.zip and install it
|
||||
* connect your ADSB to FC, connect both RX and TX pins
|
||||
* in INAV configurator ports TAB set telemetry MAVLINK, and baudrate 115200
|
||||
* go to CLI in inav configurator and set serialpassthrough for port you connected ADSB ```serialpassthrough [PORT_YOU_SELECTED - 1] 115200 rxtx``` and close configurator
|
||||
* open ADSB program you installed, got to settings and set "telemetry" = MAVLINK,
|
||||
|
||||
PCB board for TT-SC1-B module https://oshwlab.com/error414/adsb-power-board
|
||||

|
||||
|
||||
## ADSBee 1090 settings
|
||||
* connect to ADSBee1090 via USB and set COMMS_UART to mavlink2 \
|
||||
``
|
||||
AT+PROTOCOL=COMMS_UART,MAVLINK2
|
||||
``\
|
||||
``
|
||||
AT+BAUDRATE=COMMS_UART,115200
|
||||
``\
|
||||
It's recommended to turn of wifi \
|
||||
``
|
||||
AT+ESP32_ENABLE=0
|
||||
``\
|
||||
``
|
||||
AT+SETTINGS=SAVE
|
||||
``
|
||||
* in INAV configurator ports TAB set telemetry MAVLINK, and baudrate 115200
|
||||
* https://pantsforbirds.com/adsbee-1090/quick-start/
|
||||
|
||||
## SoftRF settings
|
||||
SoftRF supports only MAVLink version 1.
|
||||
```
|
||||
set mavlink_version = 1
|
||||
save
|
||||
```
|
||||
The baud rate for SoftRF is 57600. INAV provides minimal support for SoftRF and supports only
|
||||
the mandatory MAVLink messages: `MAVLINK_MSG_ID_HEARTBEAT`, `MAVLINK_MSG_ID_SYSTEM_TIME`, and `MAVLINK_MSG_ID_GPS_RAW_INT`.
|
||||
|
||||
The following messages are not supported: `MAVLINK_MSG_ID_SYS_STATUS`, `MAVLINK_MSG_ID_VFR_HUD`, and `MAVLINK_MSG_ID_ATTITUDE`.
|
||||
|
||||
## Alert and Warning
|
||||
The ADS-B warning/alert system supports two operating modes, controlled by the parameter osd_adsb_calculation_use_cpa (ON or OFF).
|
||||
|
||||
---
|
||||
|
||||
### ADS-B Warning and Alert Messages (CPA Mode OFF)
|
||||
The ADS-B warning/alert system supports two operating modes, controlled by the parameter **osd_adsb_calculation_use_cpa** (ON or OFF).
|
||||
|
||||
When **osd_adsb_calculation_use_cpa = OFF**, the system evaluates only the **current distance between the aircraft and the UAV**. The aircraft with the **shortest distance** is always selected for monitoring.
|
||||
|
||||
- If the aircraft enters the **warning zone** (`adsb_distance_warning`), the corresponding **OSD element is displayed**.
|
||||
- If the aircraft enters the **alert zone** (`adsb_distance_alert`), the **OSD element starts blinking**, indicating a higher-priority alert.
|
||||
|
||||
This mode therefore provides a simple proximity-based warning determined purely by real-time distance.
|
||||
|
||||
---
|
||||
|
||||
### ADS-B Warning and Alert Messages (CPA Mode ON)
|
||||
|
||||
When **osd_adsb_calculation_use_cpa = ON**, the system evaluates aircraft using the **Closest Point of Approach (CPA)** and predicted trajectories, not only the current distance.
|
||||
|
||||
1. **Aircraft already inside the alert zone**
|
||||
If one or more aircraft are currently inside the **alert zone** (`adsb_distance_alert`), the **closest aircraft** to the UAV is selected and the **OSD element blinks**.
|
||||
|
||||
2. **Aircraft in the warning zone, none predicted to enter the alert zone**
|
||||
If aircraft are present in the **warning zone** (`adsb_distance_warning`), but none of them are predicted to enter the **alert zone** (their CPA distance is greater than `adsb_distance_alert`), the **closest aircraft to the UAV** is selected and the **OSD element remains steady** (no blinking).
|
||||
|
||||
3. **Aircraft in the warning zone, one predicted to enter the alert zone**
|
||||
If at least one aircraft in the **warning zone** is predicted to enter the **alert zone**, that aircraft is selected and the **OSD element blinks**.
|
||||
|
||||
4. **Aircraft in the warning zone, multiple predicted to enter the alert zone**
|
||||
If multiple aircraft are predicted to enter the **alert zone**, the system selects the aircraft that will **reach the alert zone first**, and the **OSD element blinks**.
|
||||
|
||||

|
||||
@@ -0,0 +1,161 @@
|
||||
# MSP Extensions
|
||||
|
||||
INAV includes a number of extensions to the MultiWii Serial Protocol (MSP). This document describes
|
||||
those extensions in order that 3rd party tools may identify INAV firmware and react appropriately.
|
||||
|
||||
Issue the MSP_API_VERSION command to find out if the firmware supports them.
|
||||
|
||||
## Mode Ranges
|
||||
|
||||
### MSP\_MODE\_RANGES
|
||||
|
||||
The MSP\_MODE\_RANGES returns the current auxiliary mode settings from the flight controller. It should be invoked
|
||||
before any modification is made to the configuration.
|
||||
|
||||
The message returns a group of 4 unsigned bytes for each 'slot' available in the flight controller. The number of
|
||||
slots should be calculated from the size of the returned message.
|
||||
|
||||
| Command | Msg Id | Direction | Notes |
|
||||
|---------|--------|-----------|-------|
|
||||
| MSP\_MODE\_RANGES | 34 | to FC | Following this command, the FC returns a block of 4 bytes for each auxiliary mode 'slot'|
|
||||
|
||||
Unassigned slots have rangeStartStep == rangeEndStep. Each element contains the following fields.
|
||||
|
||||
| Data | Type | Notes |
|
||||
|------|------|-------|
|
||||
| permanentId | uint8 | See [Modes in the wiki](https://github.com/iNavFlight/inav/wiki/Modes) for a definition of the permanent ids |
|
||||
| auxChannelIndex | uint8 | The Aux switch number (indexed from 0) |
|
||||
| rangeStartStep | uint8 | The start value for this element in 'blocks' of 25 where 0 == 900 and 48 == 2100 |
|
||||
| rangeEndStep | uint8 | The end value for this element in 'blocks' of 25 where 0 == 900 and 48 == 2100 |
|
||||
|
||||
Thus, for a INAV firmware with 40 slots 160 bytes would be returned in response to MSP\_MODE\_RANGES,
|
||||
|
||||
### MSP\_SET\_MODE\_RANGE
|
||||
|
||||
The MSP\_SET\_MODE\_RANGE is used to inform the flight controller of
|
||||
auxiliary mode settings. The client *must* return all auxiliary
|
||||
elements, including those that have been disabled or are undefined, by
|
||||
sending this message for all auxiliary slots.
|
||||
|
||||
| Command | Msg Id | Direction |
|
||||
|---------|--------|-----------|
|
||||
| MSP\_SET\_MODE\_RANGE | 35 | to FC |
|
||||
|
||||
|
||||
| Data | Type | Notes |
|
||||
|------|------|-------|
|
||||
| sequence id | uint8 | A monotonically increasing ID, from 0 to the number of slots -1 |
|
||||
| permanentId | uint8 | See [Modes in the wiki](https://github.com/iNavFlight/inav/wiki/Modes) for a definition of the permanent ids |
|
||||
| auxChannelIndex | uint8 | The Aux channel number (indexed from 0) |
|
||||
| rangeStartStep | uint8 | The start value for this element in 'blocks' of 25 where 0 == 900 and 48 == 2100 |
|
||||
| rangeEndStep | uint8 | The end value for this element in 'blocks' of 25 where 0 == 900 and 48 == 2100 |
|
||||
|
||||
### Implementation Notes
|
||||
|
||||
* The client should make no assumptions about the number of slots available. Rather, the number should be computed
|
||||
from the size of the MSP\_MODE\_RANGES message divided by the size of the returned data element (4 bytes);
|
||||
* The client should ensure that all changed items are returned to the flight controller, including those where a
|
||||
switch or range has been disabled;
|
||||
* A 'null' return, with all values other than the sequence id set to 0, must be made for all unused slots, up to
|
||||
the maximum number of slots calculated from the initial message.
|
||||
|
||||
## Adjustment Ranges
|
||||
|
||||
### MSP\_ADJUSTMENT\_RANGES
|
||||
|
||||
The MSP\_ADJUSTMENT\_RANGES returns the current adjustment range settings from
|
||||
the flight controller. It should be invoked before any modification is
|
||||
made to the configuration.
|
||||
|
||||
The message returns a group of 6 unsigned bytes for each 'slot'
|
||||
available in the flight controller. The number of slots should be
|
||||
calculated from the size of the returned message.
|
||||
|
||||
| Command | Msg Id | Direction | Notes |
|
||||
|---------|--------|-----------|-------|
|
||||
| MSP\_ADJUSTMENT\_RANGES | 52 | to FC | Following this command, the FC returns a block of 6 bytes for each adjustment range 'slot'|
|
||||
|
||||
Unassigned slots have rangeStartStep == rangeEndStep. Each element contains the following fields.
|
||||
|
||||
| Data | Type | Notes |
|
||||
|------|------|-------|
|
||||
| adjustmentStateIndex | uint8 | See below |
|
||||
| auxChannelIndex | uint8 | The Aux channel number (indexed from 0) used to activate the adjustment |
|
||||
| rangeStartStep | uint8 | The start value for this element in 'blocks' of 25 where 0 == 900 and 48 == 2100 |
|
||||
| rangeEndStep | uint8 | The end value for this element in 'blocks' of 25 where 0 == 900 and 48 == 2100 |
|
||||
| adjustmentFunction | uint8 | See below |
|
||||
| auxSwitchChannelIndex | uint8 | The Aux channel number used to perform the function (indexed from 0) |
|
||||
|
||||
Thus, for a INAV firmware with 12 slots 72 bytes would be returned in response to MSP\_ADJUSTMENT\_RANGES,
|
||||
|
||||
### MSP\_SET\_ADJUSTMENT\_RANGE
|
||||
|
||||
The MSP\_SET\_ADJUSTMENT\_RANGE is used to inform the flight controller of
|
||||
adjustment range settings. The client *must* return all adjustment range
|
||||
elements, including those that have been disabled or are undefined, by
|
||||
sending this message for all adjustment range slots.
|
||||
|
||||
| Command | Msg Id | Direction |
|
||||
|---------|--------|-----------|
|
||||
| MSP\_SET\_ADJUSTMENT\_RANGE | 53 | to FC |
|
||||
|
||||
|
||||
| Data | Type | Notes |
|
||||
|------|------|-------|
|
||||
| sequence id | uint8 | A monotonically increasing ID, from 0 to the number of slots -1 |
|
||||
| adjustmentStateIndex | uint8 | See below |
|
||||
| auxChannelIndex | uint8 | The Aux channel number (indexed from 0) |
|
||||
| rangeStartStep | uint8 | The start value for this element in 'blocks' of 25 where 0 == 900 and 48 == 2100 |
|
||||
| rangeEndStep | uint8 | The end value for this element in 'blocks' of 25 where 0 == 900 and 48 == 2100 |
|
||||
| adjustmentFunction | uint8 | See below |
|
||||
| auxSwitchChannelIndex | uint8 | The Aux channel number used to perform the function (indexed from 0) |
|
||||
|
||||
### MSP\_SET\_1WIRE
|
||||
|
||||
The MSP\_SET\_1WIRE is used to enable serial1wire passthrough
|
||||
note: it would be ideal to disable this when armed
|
||||
|
||||
| Command | Msg Id | Direction |
|
||||
|---------|--------|-----------|
|
||||
| MSP\_SET\_1WIRE | 243 | to FC |
|
||||
|
||||
| Data | Type | Notes |
|
||||
|------|------|-------|
|
||||
| esc id | uint8 | A monotonically increasing ID, from 0 to the number of escs -1 |
|
||||
|
||||
#### AdjustmentIndex
|
||||
|
||||
The FC maintains internal state for each adjustmentStateIndex, currently 4 simultaneous adjustment states are maintained. Multiple adjustment ranges
|
||||
can be configured to use the same state but care should be taken not to send multiple adjustment ranges that when active would confict.
|
||||
|
||||
e.g. Configuring two identical adjustment ranges using the same slot would conflict, but configuring two adjustment ranges that used
|
||||
only one half of the possible channel range each but used the same adjustmentStateIndex would not conflict.
|
||||
|
||||
The FC does NOT check for conflicts.
|
||||
|
||||
#### AdjustmentFunction
|
||||
|
||||
There are many adjustments that can be made, the numbers of them and their use is found in the documentation of the cli `adjrange` command in the 'Inflight Adjustents' section.
|
||||
|
||||
### Implementation Notes
|
||||
|
||||
* The client should make no assumptions about the number of slots available. Rather, the number should be computed
|
||||
from the size of the MSP\_ADJUSTMENT\_RANGES message divided by the size of the returned data element (6 bytes);
|
||||
* The client should ensure that all changed items are returned to the flight controller, including those where a
|
||||
switch or range has been disabled;
|
||||
* A 'null' return, with all values except for the sequence id set to 0, must be made for all unused slots,
|
||||
up to the maximum number of slots calculated from the initial message.
|
||||
|
||||
## Deprecated MSP
|
||||
|
||||
The following MSP commands are replaced by the MSP\_MODE\_RANGES and
|
||||
MSP\_SET\_MODE\_RANGE extensions, and are not recognised by
|
||||
INAV.
|
||||
|
||||
* MSP\_BOX
|
||||
* MSP\_SET\_BOX
|
||||
|
||||
See also
|
||||
--------
|
||||
[The wiki](https://github.com/iNavFlight/inav/wiki/Modes) describes the user visible implementation for the INAV
|
||||
modes extension.
|
||||
Executable
+59
@@ -0,0 +1,59 @@
|
||||
# Airplane Autotune instructions
|
||||
|
||||
Airplane PIFF autotune is inspired by ArduPilot Plane firmware.
|
||||
|
||||
Getting a good set of roll/pitch/yaw PIFF parameters for your aircraft is essential for stable flight. To help with this it is highly recommended that you use the AUTOTUNE system described below.
|
||||
|
||||
## What AUTOTUNE does
|
||||
|
||||
The AUTOTUNE mode is a flight mode that acts on top of normal ANGLE/HORIZON/ACRO mode and uses changes in flight attitude input by the pilot to learn the tuning values for roll, pitch and yaw tuning.
|
||||
|
||||
In general pilot needs to activate AUTOTUNE mode while in the air and then fly the plane for a few minutes. While flying the pilot needs to input as many sharp attitude changes as possible so that the autotune code can learn how the aircraft responds and figure out PIFF gains.
|
||||
|
||||
## Before flying with AUTOTUNE
|
||||
|
||||
Before taking off you need to set up a few parameters for your airplane:
|
||||
|
||||
parameter | explanation
|
||||
--------- | -----------
|
||||
roll_rate | Maximum roll rate limit for your ariplane. Must not exceed physical limit of your plane
|
||||
pitch_rate | Maximum pitch rate limit for your ariplane. Must not exceed physical limit of your plane
|
||||
yaw_rate | Maximum yaw rate limit for your ariplane. Must not exceed physical limit of your plane
|
||||
fw_p_level | Self-leveling strength. Bigger value means sharper response
|
||||
fw_i_level | Self-leveling filtering. Usual value for airplanes is 1-5 Hz
|
||||
max_angle_inclination_rll | Maximum roll angle in [0.1 deg] units
|
||||
max_angle_inclination_pit | Maximum pitch angle in [0.1 deg] units
|
||||
tpa_breakpoint | Cruise throttle (expected throttle that you would be flying most of the time)
|
||||
tpa_rate | Amount of TPS curve to apply (usually should be in range 50-80 for most airplanes)
|
||||
|
||||
For most hobby-sized airplanes roll/pitch rate limits should be in range 70-120 deg/s (7-12 for `roll_rate` and `pitch_rate` values). Small and agile flying wings can reach 180-200 deg/s.
|
||||
|
||||
Other things to check:
|
||||
|
||||
* It's highly recommended that you fly in MANUAL and trim your servo midpoints for stable flight
|
||||
* Make sure you have center of gravity according to manual to your aircraft
|
||||
* Check that your failsafe activates correctly (test on the ground with propeller off for safety)
|
||||
|
||||
## Flying in AUTOTUNE
|
||||
|
||||
Once you are all setup you can take off normally and switch to AUTOTUNE mode once you have gained altitude.
|
||||
|
||||
When you engage AUTOTUNE mode a few things will happen:
|
||||
|
||||
* The autotune system will immediately setup some default values for your roll, pitch and yaw P and I gains
|
||||
* The autotune system will monitor requested roll and pitch rates (as determined by your transmitter stick movements). When the demanded roll or pitch rate exceeds certain threshold the autotune system will use the response of the aircraft to learn roll or pitch tuning values
|
||||
* Every 5 seconds the autotune system will store the snapshot of parameters you have. When you switch out of AUTOTUNE mode the last remembered parameters are restored
|
||||
* You may find the plane is quite sluggish when you first enter AUTOTUNE. You will find that as the tune progresses this will get better. Make sure your flight area has plenty of room for slow large-radius turns.
|
||||
* Don't land in AUTOTUNE mode - during landing airplane doesn't reach it full performance which may be read by autotune system as insufficient gains.
|
||||
|
||||
The key to a successful autotune is to input rapid movements with the transmitter sticks. You should only do one of either roll or pitch at a time, and you should move the stick rapidly to the maximum deflection.
|
||||
|
||||
## Don't stop too early
|
||||
|
||||
The more you fly the better it will get. Let autotune analyze how your airplane behaves and figure decent tune for you. Once you feel that airplane is flying good in AUTOTUNE - keep flying well past that point to finalize the tune.
|
||||
|
||||
## Completing the tune
|
||||
|
||||
Once you have tuned reasonable PIFF parameters with AUTOTUNE you should complete the tune by switching out of AUTOTUNE to ANGLE or MANUAL and landing the airplane.
|
||||
|
||||
Note that AUTOTUNE mode doesn't automatically save parameters to EEPROM. You need to disarm and issue a [stick command](Controls.md) to save configuration parameters.
|
||||
@@ -0,0 +1,107 @@
|
||||
# Backup and Restore
|
||||
|
||||
INAV Configurator can automatically back up your configuration before flashing firmware and offer to restore it afterwards. When upgrading across major versions (e.g. 7.x → 8.x → 9.x), settings are automatically migrated to the new firmware format.
|
||||
|
||||
For manual CLI-based backup and restore, see the [CLI documentation](Cli.md#backup-via-cli).
|
||||
|
||||
## Automatic Backup & Restore During Firmware Flash
|
||||
|
||||
### What happens automatically
|
||||
|
||||
1. **Before flashing** (with or without Full Chip Erase enabled): Your current CLI configuration (`diff all`) is automatically captured and saved to the backup directory.
|
||||
2. **After flashing**: Depending on the situation, the Configurator offers to restore your settings if Full Chip Erase was enabled:
|
||||
|
||||
| Scenario | Behavior |
|
||||
|----------|----------|
|
||||
| **Patch update** (e.g. 8.0.0 → 8.0.1) | Auto-restore offered immediately |
|
||||
| **Minor update** (e.g. 8.0.0 → 8.1.0) | Auto-restore offered immediately |
|
||||
| **Major upgrade** (e.g. 7.x → 8.x) with migration profile available | Migration preview shown — confirm to restore with converted settings |
|
||||
| **Major upgrade** without migration profile | Warning shown — restore still possible but some settings may fail |
|
||||
| **Major downgrade** (e.g. 9.x → 7.x) | Auto-restore blocked — manual restore only (settings may be incompatible) |
|
||||
| **Local firmware file** (loaded from disk) | No auto-restore offered — backup is still saved |
|
||||
| **Flash without Full Chip Erase** | Backup taken, no restore offered |
|
||||
|
||||
### Migration Preview
|
||||
|
||||
When updating across major versions (e.g. 7.x → 9.x), the Configurator shows a **migration preview overlay** before restoring. This lists:
|
||||
|
||||
- **Removed settings** — settings that no longer exist in the new firmware (will be skipped)
|
||||
- **Renamed settings** — settings whose name changed (automatically converted)
|
||||
- **Renamed commands** — CLI commands that were renamed (automatically converted)
|
||||
- **Value replacements** — setting values that changed meaning (automatically converted)
|
||||
- **Setting remappings** — numeric IDs that were renumbered (automatically converted)
|
||||
- **Warnings** — settings whose semantics changed and require manual review
|
||||
|
||||
You can review all changes before confirming or cancelling the restore.
|
||||
|
||||
Multi-step migrations are handled automatically. For example, a 7.x → 9.x upgrade applies migration profiles in sequence (7→8, then 8→9).
|
||||
|
||||
## Manual Backup & Restore
|
||||
|
||||
The Firmware Flasher tab provides three buttons:
|
||||
|
||||
- **Backup Config** — saves your current CLI configuration to a file (opens save dialog)
|
||||
- **Restore Config** — loads a backup file and restores it to your flight controller
|
||||
- If the backup is from a different major version, the migration preview is shown first
|
||||
- If no migration profile exists for the version gap, a warning is shown but you can still proceed
|
||||
- **Open Backups Folder** — opens the backup directory in your file manager
|
||||
|
||||
For CLI-based backup and restore procedures, see [Backup via CLI](Cli.md#backup-via-cli) and [Restore via CLI](Cli.md#restore-via-cli).
|
||||
|
||||
## Backup File Location
|
||||
|
||||
Backups are stored in your OS-specific application data directory:
|
||||
|
||||
| OS | Path |
|
||||
|----|------|
|
||||
| **Windows** | `%APPDATA%/inav-configurator/backups/` |
|
||||
| **macOS** | `~/Library/Application Support/inav-configurator/backups/` |
|
||||
| **Linux** | `~/.config/inav-configurator/backups/` |
|
||||
|
||||
Use the **Open Backups Folder** button in the Firmware Flasher tab to open this directory.
|
||||
|
||||
## Backup File Naming
|
||||
|
||||
| Type | Format |
|
||||
|------|--------|
|
||||
| Auto-backups | `UPDATE_inav_backup_{version}_{board}_{YYYY-MM-DD_HHMMSS}.txt` |
|
||||
| Manual backups | `inav_backup_{version}_{board}_{YYYY-MM-DD_HHMMSS}.txt` |
|
||||
|
||||
Auto-backups are pruned automatically — only the 10 most recent are kept. Files you rename are never pruned.
|
||||
|
||||
## Backup File Format
|
||||
|
||||
Backup files are plain-text CLI dumps with a metadata header:
|
||||
|
||||
```
|
||||
# INAV Backup
|
||||
# Version: 8.0.0
|
||||
# Board: SPEEDYBEEF405V4
|
||||
# Date: 2026-04-11T10:30:00.000Z
|
||||
# Craft: MyQuad
|
||||
#
|
||||
# INAV/SPEEDYBEEF405V4 8.0.0 Apr 1 2026 / 12:00:00 (abc1234)
|
||||
# GCC-13.2.1
|
||||
# ...
|
||||
set gyro_main_lpf_hz = 110
|
||||
set acc_hardware = AUTO
|
||||
...
|
||||
```
|
||||
|
||||
You can open and edit these files with any text editor.
|
||||
|
||||
## Restore Error Handling
|
||||
|
||||
If errors occur during restore (e.g. unknown settings, invalid values):
|
||||
|
||||
- An error dialog shows the affected lines
|
||||
- You can choose:
|
||||
- **Save anyway** — saves the successfully applied settings and reboots
|
||||
- **Abort** — discards all changes and exits CLI mode
|
||||
|
||||
## Tips
|
||||
|
||||
- **Always flash with Full Chip Erase** when upgrading to a new version. This ensures clean defaults and triggers automatic backup and restore.
|
||||
- **Review migration previews carefully** — especially the warnings section, which highlights settings whose meaning may have changed.
|
||||
- **Keep manual backups** before major upgrades. While auto-backup handles this, having an extra copy in a known location gives peace of mind.
|
||||
- **Use `diff` over `dump`** for backups. The `diff` format only stores settings that differ from defaults, which makes restoring safer across versions. The auto-backup feature already uses `diff all`.
|
||||
+509
@@ -0,0 +1,509 @@
|
||||
# Battery Monitoring
|
||||
|
||||
INAV has a battery monitoring feature. The voltage of the main battery can be measured by the system and used to trigger a low-battery warning [buzzer](Buzzer.md), on-board status LED flashing and LED strip patterns.
|
||||
|
||||
Low battery warnings can:
|
||||
|
||||
* Help ensure you have time to safely land the aircraft
|
||||
* Help maintain the life and safety of your LiPo/LiFe batteries, which should not be discharged below manufacturer recommendations
|
||||
|
||||
Minimum and maximum cell voltages can be set, and these voltages are used to auto-detect the number of cells in the battery when it is first connected.
|
||||
|
||||
Per-cell monitoring is not supported, as we only use one ADC to read the battery voltage.
|
||||
|
||||
## Supported targets
|
||||
|
||||
All targets support battery voltage monitoring unless stated.
|
||||
|
||||
## Connections
|
||||
|
||||
When dealing with batteries **ALWAYS CHECK POLARITY!**
|
||||
|
||||
Measure expected voltages **first** and then connect to the flight controller. Powering the flight controller with
|
||||
incorrect voltage or reversed polarity will likely fry your flight controller. Ensure your flight controller
|
||||
has a voltage divider capable of measuring your particular battery voltage.
|
||||
On the first battery connection is always advisable to use a current limiter device to limit damages if something is wrong in the setup.
|
||||
|
||||
### Sparky
|
||||
|
||||
See the [Sparky board chapter](Board%20-%20Sparky.md).
|
||||
|
||||
## Voltage measurement
|
||||
|
||||
Enable the `VBAT` feature to enable the measurement of the battery voltage and the use of the voltage based OSD battery gauge, voltage based and energy based battery alarms.
|
||||
|
||||
### Calibration
|
||||
|
||||
`vbat_scale` - Adjust this setting to match actual measured battery voltage to reported value. Increasing this value increases the measured voltage.
|
||||
|
||||
### Voltage measurement source
|
||||
|
||||
Two voltage sources are available: raw voltage and sag compensated voltage. The raw voltage is the voltage directly measured at the battery while the sag compensated voltage is calculated by an algorithm aiming to provide a stable voltage source for gauges, telemetry and alarms. When the current drawn from a battery varies the provided voltage also varies due to the internal resistance of the battery, it is called sag. The sag can often trigger the battery alarms before the battery is empty and if you are relying on the battery voltage to know the charge state of your battery you have to land or cut the throttle to know the real, without load, battery voltage. The sag compensation algorithm simulates a battery with zero internal resistance and provides a stable reading independent from the drawn current.
|
||||
|
||||
You can select the voltage source used for battery alarms and telemetry with the `bat_voltage_source` setting. It can be set to either `RAW` for using raw battery voltage or `SAG_COMP` for using the calculated sag compensated voltage.
|
||||
|
||||
You can see an illustration of the sag compensation algorithm in action in the following graph:
|
||||
|
||||

|
||||
|
||||
### Voltage based OSD gauge and alarms
|
||||
|
||||
Up to 3 battery profiles are supported. You can select the battery profile from the GUI, OSD menu, [stick commands](Controls.md) and CLI command `battery_profile n`. Each profile stores the following voltage settings:
|
||||
|
||||
`bat_cells` - Specify the number of cells of your battery. Allows the automatic selection of the battery profile when set to a value greater than 0. Set to 0 (default) for auto-detecting the number of cells (see next setting)
|
||||
|
||||
`vbat_cell_detect_voltage` - Maximum voltage per cell, used for auto-detecting the number of cells of the battery. Should be higher than maximum cell voltage to take into account possible drift in measured voltage and keep cell count detection accurate (0.01V unit, i.e. 430 = 4.30V)
|
||||
|
||||
`vbat_max_cell_voltage` - Maximum voltage per cell when the battery is fully charged. Used for the OSD voltage based battery gauge (0.01V unit, i.e. 420 = 4.20V)
|
||||
|
||||
`vbat_warning_cell_voltage` - Cell warning voltage. A cell voltage bellow this value triggers the first (short beeps) voltage based battery alarm if used and also the blinking of the OSD voltage indicator if the battery capacity is not used instead (see bellow) (0.01V unit, i.e. 370 = 3.70V)
|
||||
|
||||
`vbat_min_cell_voltage` - Cell minimum voltage. A cell voltage bellow this value triggers the second (long beeps) voltage based battery alarm if used and the OSD gauge will display 0% if the battery capacity is not used instead (see bellow) (0.01V unit, i.e. 350 = 3.50V)
|
||||
|
||||
e.g.
|
||||
|
||||
```
|
||||
battery_profile 1
|
||||
set vbat_scale = 1100
|
||||
set vbat_max_cell_voltage = 430
|
||||
set vbat_warning_cell_voltage = 340
|
||||
set vbat_min_cell_voltage = 330
|
||||
```
|
||||
|
||||
# Current Monitoring
|
||||
|
||||
Current monitoring (amperage) is supported by connecting a current meter to the appropriate current meter ADC input (see the documentation for your particular board).
|
||||
|
||||
When enabled, the following values calculated and used by the telemetry and OLED display subsystems:
|
||||
* Amps
|
||||
* mAh used
|
||||
* Capacity remaining
|
||||
|
||||
## Configuration
|
||||
|
||||
Enable current monitoring using the CLI command:
|
||||
|
||||
```
|
||||
feature CURRENT_METER
|
||||
```
|
||||
|
||||
Configure the current meter type using the `current_meter_type` settings here:
|
||||
|
||||
| Value | Sensor Type |
|
||||
| ----- | ---------------------- |
|
||||
| 0 | None |
|
||||
| 1 | ADC/hardware sensor |
|
||||
| 2 | Virtual sensor |
|
||||
|
||||
Configure capacity using the `battery_capacity` setting, in mAh units.
|
||||
|
||||
If you're using an OSD that expects the multiwii current meter output value, then set `multiwii_current_meter_output` to `1` (this multiplies amperage sent to MSP by 10).
|
||||
|
||||
### ADC Sensor
|
||||
|
||||
The current meter may need to be configured so the value read at the ADC input matches actual current draw. Just like you need a voltmeter to correctly calibrate your voltage reading you also need an ammeter to calibrate the current sensor.
|
||||
|
||||
Use the following settings to adjust calibration:
|
||||
|
||||
`current_meter_scale`
|
||||
`current_meter_offset`
|
||||
|
||||
### Virtual Sensor
|
||||
|
||||
The virtual sensor uses the throttle position to calculate an estimated current value. This is useful when a real sensor is not available. The following settings adjust the virtual sensor calibration:
|
||||
|
||||
| Setting | Description |
|
||||
| ----------------------------- | -------------------------------------------------------- |
|
||||
| `current_meter_scale` | The throttle scaling factor [centiamps, i.e. 1/100th A] |
|
||||
| `current_meter_offset` | The current at zero throttle (while disarmed) [centiamps, i.e. 1/100th A] |
|
||||
|
||||
There are two simple methods to tune these parameters: one uses a battery charger and another depends on actual current measurements.
|
||||
|
||||
#### Tuning Using Actual Current Measurements
|
||||
If you know your craft's current draw while disarmed (Imin) and at maximum throttle while armed (Imax), calculate the scaling factors as follows:
|
||||
```
|
||||
current_meter_scale = (Imax - Imin) * 100000 / (Tmax + (Tmax * Tmax / 50))
|
||||
current_meter_offset = Imin * 100
|
||||
```
|
||||
Note: Tmax is maximum throttle offset (i.e. for `max_throttle` = 1850, Tmax = 1850 - 1000 = 850)
|
||||
|
||||
For example, assuming a maximum current of 34.2A, a minimum current of 2.8A, and a Tmax `max_throttle` = 1850:
|
||||
```
|
||||
current_meter_scale = (Imax - Imin) * 100000 / (Tmax + (Tmax * Tmax / 50))
|
||||
= (34.2 - 2.8) * 100000 / (850 + (850 * 850 / 50))
|
||||
= 205
|
||||
current_meter_offset = Imin * 100 = 280
|
||||
```
|
||||
#### Tuning Using Battery Charger Measurement
|
||||
If you cannot measure current draw directly, you can approximate it indirectly using your battery charger.
|
||||
However, note it may be difficult to adjust `current_meter_offset` using this method unless you can
|
||||
measure the actual current draw with the craft disarmed.
|
||||
|
||||
Note:
|
||||
+ This method depends on the accuracy of your battery charger; results may vary.
|
||||
+ If you add or replace equipment that changes the in-flight current draw (e.g. video transmitter,
|
||||
camera, gimbal, motors, prop pitch/sizes, ESCs, etc.), you should recalibrate.
|
||||
|
||||
The general method is:
|
||||
|
||||
1. Fully charge your flight battery
|
||||
2. Fly your craft, using >50% of your battery pack capacity (estimated)
|
||||
3. Note INAV's reported mAh draw
|
||||
4. Re-charge your flight battery, noting the mAh charging data needed to restore the pack to fully charged
|
||||
5. Adjust `current_meter_scale` to according to the formula given below
|
||||
6. Repeat and test
|
||||
|
||||
Given (a) the reported mAh draw and the (b) mAh charging data, calculate a new `current_meter_scale` value as follows:
|
||||
```
|
||||
current_meter_scale = (reported_draw_mAh / charging_data_mAh) * old_current_meter_scale
|
||||
```
|
||||
For example, assuming:
|
||||
+ A INAV reported current draw of 1260 mAh
|
||||
+ Charging data to restore full charge of 1158 mAh
|
||||
+ A existing `current_meter_scale` value of 400 (the default)
|
||||
|
||||
Then the updated `current_meter_scale` is:
|
||||
```
|
||||
current_meter_scale = (reported_draw_mAh / charging_data_mAh) * old_current_meter_scale
|
||||
= (1260 / 1158) * 400
|
||||
= 435
|
||||
```
|
||||
|
||||
## Power and Current Limiting
|
||||
|
||||
INAV includes an advanced power and current limiting system to protect your battery and ESCs from excessive discharge rates. This feature automatically reduces throttle output when current or power draw exceeds configured limits.
|
||||
|
||||
### Why Use Power Limiting?
|
||||
|
||||
Power and current limiting helps:
|
||||
- **Protect batteries** from exceeding their C-rating and getting damaged
|
||||
- **Prevent voltage sag** and brown-outs during high-throttle maneuvers
|
||||
- **Extend battery lifespan** by avoiding excessive discharge rates
|
||||
- **Improve safety** by preventing ESC or battery overheating
|
||||
- **Comply with regulations** that may limit power output
|
||||
|
||||
### How It Works
|
||||
|
||||
The power limiter uses a PI (Proportional-Integral) controller to smoothly reduce throttle when current or power exceeds limits. It supports two operating modes:
|
||||
|
||||
1. **Continuous Limit**: The sustained current/power that can be drawn indefinitely
|
||||
2. **Burst Limit**: A higher current/power allowed for a short duration before falling back to the continuous limit
|
||||
|
||||
This burst mode allows brief high-power maneuvers (like punch-outs or quick climbs) while protecting the battery during sustained high-throttle flight.
|
||||
|
||||
### Configuration
|
||||
|
||||
Power limiting requires a current sensor (`CURRENT_METER` feature). Power-based limiting additionally requires voltage measurement (`VBAT` feature).
|
||||
|
||||
#### Basic Settings (per battery profile)
|
||||
|
||||
| Setting | Description | Unit | Range |
|
||||
|---------|-------------|------|-------|
|
||||
| `limit_cont_current` | Continuous current limit | dA (deci-amps) | 0-2000 (0-200A) |
|
||||
| `limit_burst_current` | Burst current limit | dA | 0-2000 (0-200A) |
|
||||
| `limit_burst_current_time` | Duration burst is allowed | ds (deci-seconds) | 0-600 (0-60s) |
|
||||
| `limit_burst_current_falldown_time` | Ramp-down duration from burst to continuous | ds | 0-600 (0-60s) |
|
||||
| `limit_cont_power` | Continuous power limit | dW (deci-watts) | 0-20000 (0-2000W) |
|
||||
| `limit_burst_power` | Burst power limit | dW | 0-20000 (0-2000W) |
|
||||
| `limit_burst_power_time` | Duration burst power is allowed | ds | 0-600 (0-60s) |
|
||||
| `limit_burst_power_falldown_time` | Ramp-down duration for power | ds | 0-600 (0-60s) |
|
||||
|
||||
**Note**: Set any limit to `0` to disable that specific limiter.
|
||||
|
||||
#### Advanced Tuning Settings
|
||||
|
||||
| Setting | Description | Default | Range |
|
||||
|---------|-------------|---------|-------|
|
||||
| `limit_pi_p` | Proportional gain for PI controller | 100 | 10-500 |
|
||||
| `limit_pi_i` | Integral gain for PI controller | 15 | 10-200 |
|
||||
| `limit_attn_filter_cutoff` | Low-pass filter cutoff frequency | 50 Hz | 10-200 |
|
||||
|
||||
### Example Configurations
|
||||
|
||||
#### Example 1: Simple Current Limiting (50A continuous)
|
||||
|
||||
Protect a 1500mAh 4S 50C battery (75A max burst, 50A continuous safe):
|
||||
|
||||
```
|
||||
battery_profile 1
|
||||
|
||||
set limit_cont_current = 500 # 50A continuous
|
||||
set limit_burst_current = 750 # 75A burst
|
||||
set limit_burst_current_time = 100 # 10 seconds
|
||||
set limit_burst_current_falldown_time = 20 # 2 second ramp-down
|
||||
```
|
||||
|
||||
#### Example 2: Power Limiting for Racing (500W limit)
|
||||
|
||||
Limit total system power for racing class restrictions:
|
||||
|
||||
```
|
||||
battery_profile 1
|
||||
|
||||
set limit_cont_power = 4500 # 450W continuous
|
||||
set limit_burst_power = 5000 # 500W burst
|
||||
set limit_burst_power_time = 50 # 5 seconds
|
||||
set limit_burst_power_falldown_time = 10 # 1 second ramp-down
|
||||
```
|
||||
|
||||
#### Example 3: Combined Current and Power Limiting
|
||||
|
||||
Protect both battery (current) and ESCs (power):
|
||||
|
||||
```
|
||||
battery_profile 1
|
||||
|
||||
# Current limits (battery protection)
|
||||
set limit_cont_current = 600 # 60A continuous
|
||||
set limit_burst_current = 800 # 80A burst
|
||||
set limit_burst_current_time = 100 # 10 seconds
|
||||
|
||||
# Power limits (ESC protection)
|
||||
set limit_cont_power = 8000 # 800W continuous
|
||||
set limit_burst_power = 10000 # 1000W burst
|
||||
set limit_burst_power_time = 100 # 10 seconds
|
||||
```
|
||||
|
||||
### Understanding Burst Mode
|
||||
|
||||
When you exceed the continuous limit, the system uses "burst reserve" (like a capacitor):
|
||||
- **Burst reserve** starts full and depletes when current/power exceeds the continuous limit
|
||||
- When reserve is empty, the limit drops to the continuous value
|
||||
- The `falldown_time` setting creates a smooth ramp-down instead of an abrupt drop
|
||||
- Reserve recharges when current/power drops below the continuous limit
|
||||
|
||||
**Example timeline** (60A continuous, 80A burst, 10s burst time, 2s falldown):
|
||||
```
|
||||
Time Limit Reason
|
||||
---- ----- ------
|
||||
0s 80A Full burst reserve
|
||||
5s 80A Still have reserve (using 5s of 10s)
|
||||
10s 80A Reserve depleted
|
||||
10-12s 80→60A Ramping down over 2 seconds
|
||||
12s+ 60A Continuous limit active
|
||||
```
|
||||
|
||||
### OSD Elements
|
||||
|
||||
Three OSD elements display power limiting status:
|
||||
|
||||
- **`OSD_PLIMIT_REMAINING_BURST_TIME`**: Shows remaining burst time in seconds
|
||||
- **`OSD_PLIMIT_ACTIVE_CURRENT_LIMIT`**: Shows current limit being enforced (blinks when limiting)
|
||||
- **`OSD_PLIMIT_ACTIVE_POWER_LIMIT`**: Shows power limit being enforced (blinks when limiting)
|
||||
|
||||
Enable these in the OSD tab to monitor limiting during flight.
|
||||
|
||||
### Calibration Tips
|
||||
|
||||
1. **Find your battery's limits**: Check manufacturer specifications for continuous and burst C-ratings
|
||||
- Continuous limit = `battery_capacity_mAh × continuous_C_rating / 100` (in dA)
|
||||
- Burst limit = `battery_capacity_mAh × burst_C_rating / 100` (in dA)
|
||||
|
||||
2. **Test incrementally**: Start with conservative limits and increase gradually
|
||||
|
||||
3. **Monitor in flight**: Use OSD elements to see when limiting activates
|
||||
|
||||
4. **Calibrate current sensor**: Accurate current readings are critical - see "Current Monitoring" section above
|
||||
|
||||
5. **Tune PI controller**: If limiting feels abrupt or causes oscillation, adjust `limit_pi_p` and `limit_pi_i`:
|
||||
- Increase P for faster response (may cause oscillation)
|
||||
- Increase I for better steady-state accuracy
|
||||
- Decrease if throttle oscillates during limiting
|
||||
|
||||
### Notes
|
||||
|
||||
- Power limiting is part of the battery profile system - each profile can have different limits
|
||||
- Both current and power limiting can be active simultaneously - the most restrictive applies
|
||||
- Limiting is applied smoothly via PI controller to avoid abrupt throttle cuts
|
||||
- The system uses instantaneous current/power readings for responsive limiting
|
||||
- Set limits to `0` to disable a specific limiter while keeping others active
|
||||
|
||||
## Battery capacity monitoring
|
||||
|
||||
For the capacity monitoring to work you need a current sensor (`CURRENT_METER` feature). For monitoring energy in milliWatt hour you also need voltage measurement (`VBAT` feature). For best results the current and voltage readings have to be calibrated.
|
||||
|
||||
It is possible to display the remaining battery capacity in the OSD and also use the battery capacity thresholds (`battery_capacity_warning` and `battery_capacity_critical`) for battery alarms.
|
||||
|
||||
For the remaining battery capacity to be displayed users need to set the `battery_capacity` setting (>0) and the battery to be full when plugged in. If the `battery_capacity` setting is set to 0 the remaining battery capacity item in the OSD will display `NA` and the battery gauge will use an estimation based on the battery voltage otherwise it will display the remaining battery capacity down to the `battery_capacity_critical` setting (battery considered empty) and the battery gauge will be based on the remaining capacity. For the capacity thresholds to be used for alarms the `battery_capacity_warning` and `battery_capacity_critical` settings also needs to be set (>0) and the plugged in battery to be full when plugged in. The battery capacity settings unit can be set using the `battery_capacity_unit`. MilliAmpere hour and milliWatt hour units are supported. The value are absolute meaning that `battery_capacity_warning` is the battery capacity left when the battery is entering the `warning` state and `battery_capacity_critical` is the battery capacity left when the battery is considered empty and entering the `critical` state.
|
||||
|
||||
For the battery to be considered full the mean cell voltage of the battery needs to be above `vbat_max_cell_voltage - 140mV` (by default 4.1V). So a 3S battery will be considered full above 12.3V and a 4S battery above 16.24V. If the battery plugged in is not considered full the remaining battery capacity OSD item will show `NF` (Not Full).
|
||||
|
||||
For the remaining battery capacity and battery gauge to be the most precise (linear relative to throttle from full to empty) when using battery capacity monitoring users should use the milliWatt hour unit for the battery capacity settings.
|
||||
|
||||
### Example configuration
|
||||
|
||||
```
|
||||
set battery_capacity_unit = MAH // battery capacity values are specified in milliAmpere hour
|
||||
set battery_capacity = 2200 // battery capacity is 2200mAh
|
||||
set battery_capacity_warning = 660 // the battery warning alarm will sound and the capacity related OSD items will blink when left capacity is less than 660 mAh (30% of battery capacity)
|
||||
set battery_capacity_critical = 440 // the battery critical alarm will sound and the OSD battery gauge and remaining capacity item will be empty when left capacity is less than 440 mAh (20% of battery capacity)
|
||||
```
|
||||
|
||||
Note that in this example even though your warning capacity (`battery_capacity_warning`) is set to 30% (660mAh), since 440mAh (`battery_capacity_critical`) is considered empty (0% left), the OSD capacity related items will only start to blink when the remaining battery percentage shown on the OSD is below 12%: (`battery_capacity_warning`-`battery_capacity_critical`)*100/(`battery_capacity`-`battery_capacity_critical`)=(660-440)*100/(2200-440)=12.5
|
||||
|
||||
|
||||
## Battery profiles
|
||||
|
||||
Up to 3 battery profiles are supported. You can select the battery profile from the GUI, OSD menu, [stick commands](Controls.md) and CLI command `battery_profile n`. Battery profiles store the following settings (see above for an explanation of each setting):
|
||||
- `bat_cells`
|
||||
- `vbat_cell_detect_voltage`
|
||||
- `vbat_max_cell_voltage`
|
||||
- `vbat_warning_cell_voltage`
|
||||
- `vbat_min_cell_voltage`
|
||||
- `battery_capacity`
|
||||
- `battery_capacity_warning`
|
||||
- `battery_capacity_critical`
|
||||
- `throttle_idle`
|
||||
- `throttle_scale`
|
||||
- `turtle_mode_power_factor`
|
||||
- `nav_fw_cruise_thr`
|
||||
- `nav_fw_min_thr`
|
||||
- `nav_fw_max_thr`
|
||||
- `nav_fw_pitch2thr`
|
||||
- `nav_fw_launch_thr`
|
||||
- `nav_fw_launch_idle_thr`
|
||||
- `failsafe_throttle`
|
||||
- `nav_mc_hover_thr`
|
||||
|
||||
To enable the automatic battery profile switching based on battery voltage enable the `BAT_PROF_AUTOSWITCH` feature. For a profile to be automatically selected the number of cells of the battery needs to be specified (>0).
|
||||
|
||||
### Battery profiles configuration examples
|
||||
|
||||
#### Simple example
|
||||
|
||||
In this example we want to use two different type of batteries for the same aircraft and switch manually between them. The first battery is a Li-Po (4.20V/cell) and the second battery is a Li-Ion (4.10V/cell).
|
||||
|
||||
```
|
||||
battery_profile 1
|
||||
|
||||
set bat_cells = 0
|
||||
set vbat_max_cell_voltage = 420
|
||||
set vbat_warning_cell_voltage = 370
|
||||
set vbat_min_cell_voltage = 340
|
||||
|
||||
|
||||
battery_profile 2
|
||||
|
||||
set bat_cells = 0
|
||||
set vbat_max_cell_voltage = 410
|
||||
set vbat_warning_cell_voltage = 280
|
||||
set vbat_min_cell_voltage = 250
|
||||
```
|
||||
|
||||
#### Simple example with automatic profile switching
|
||||
|
||||
In this example we want to use two different batteries for the same aircraft and automatically switch between them when the battery is plugged in. The first battery is a Li-Po 2200mAh 3S and the second battery is a LiPo 1500mAh 4S. Since the INAV defaults for the cell detection voltage and max voltage are adequate for standard LiPo batteries they will not be modified. The warning and minimum voltage are not modified either in this example but you can set them to the value you like. Since we are using battery capacities only the warning voltage (kept at default in this example) will be used and only for triggering the battery voltage indicator blinking in the OSD.
|
||||
|
||||
```
|
||||
feature BAT_PROF_AUTOSWITCH
|
||||
|
||||
|
||||
battery_profile 1
|
||||
|
||||
set bat_cells = 3
|
||||
set battery_capacity = 2200
|
||||
set battery_capacity_warning = 440
|
||||
set battery_capacity_critical = 220
|
||||
|
||||
|
||||
battery_profile 2
|
||||
|
||||
set bat_cells = 4
|
||||
set battery_capacity = 1500
|
||||
set battery_capacity_warning = 300
|
||||
set battery_capacity_critical = 150
|
||||
```
|
||||
|
||||
#### Advanced automatic switching example
|
||||
|
||||
Profile 1 is for a 3S 2200mAh Li-Po pack (max 4.20V/cell), profile 2 for a 3S 4000mAh Li-Ion pack (max 4.10V/cell) and profile 3 for a 4S 1500mAh Li-Po pack (max 4.20V/cell).
|
||||
With this configuration if the battery plugged in is less than 12.36V (3 x 4.12) the profile 2 will be automatically selected else if the battery voltage is less than 12.66V (3 x 4.22) the profile 1 will be automatically selected else if the battery voltage is less 17.20V (4 x 4.3) the profile 3 will be automatically selected. If a matching profile can't be found the last selected profile is used.
|
||||
|
||||
```
|
||||
feature BAT_PROF_AUTOSWITCH
|
||||
|
||||
|
||||
battery_profile 1
|
||||
|
||||
set bat_cells = 3
|
||||
set vbat_cell_detect_voltage = 422
|
||||
set vbat_max_cell_voltage = 420
|
||||
set vbat_warning_cell_voltage = 350
|
||||
set vbat_min_cell_voltage = 330
|
||||
set battery_capacity = 2200
|
||||
set battery_capacity_warning = 440
|
||||
set battery_capacity_critical = 220
|
||||
|
||||
|
||||
battery_profile 2
|
||||
|
||||
set bat_cells = 3
|
||||
set vbat_cell_detect_voltage = 412
|
||||
set vbat_max_cell_voltage = 410
|
||||
set vbat_warning_cell_voltage = 300
|
||||
set vbat_min_cell_voltage = 280
|
||||
set battery_capacity = 4000
|
||||
set battery_capacity_warning = 800
|
||||
set battery_capacity_critical = 400
|
||||
|
||||
|
||||
battery_profile 3
|
||||
|
||||
set bat_cells = 4
|
||||
set vbat_cell_detect_voltage = 430
|
||||
set vbat_max_cell_voltage = 420
|
||||
set vbat_warning_cell_voltage = 350
|
||||
set vbat_min_cell_voltage = 330
|
||||
set battery_capacity = 1500
|
||||
set battery_capacity_warning = 300
|
||||
set battery_capacity_critical = 150
|
||||
```
|
||||
|
||||
#### Change control profile based on battery profile
|
||||
|
||||
You can change the control profile, automatically, based on the battery profile. This allows for fine tuning of each power choice.
|
||||
|
||||
```
|
||||
feature BAT_PROF_AUTOSWITCH
|
||||
|
||||
|
||||
battery_profile 1
|
||||
|
||||
set bat_cells = 3
|
||||
set controlrate_profile = 1
|
||||
|
||||
battery_profile 2
|
||||
|
||||
set bat_cells = 4
|
||||
set controlrate_profile = 2
|
||||
```
|
||||
|
||||
## Remaining flight time and flight distance estimation
|
||||
|
||||
The estimated remaining flight time and flight distance estimations can be displayed on the OSD (for fixed wing only for the moment). They are calculated from the GPS distance from home, remaining battery capacity and average power draw. They are taking into account the requested altitude change and heading to home change after altitude change following the switch to RTH. They are also taking into account the estimated wind if `osd_estimations_wind_compensation` is set to `ON`. When the timer and distance indicator reach 0 they will blink and you need to go home in a straight line manually or by engaging RTH. You should be left with at least `rth_energy_margin`% of battery left when arriving home if the cruise speed and power are set correctly (see bellow).
|
||||
|
||||
To use this feature the following conditions need to be met:
|
||||
- The `VBAT`, `CURRENT_METER` and `GPS` features need to be enabled
|
||||
- The battery capacity needs to be specified in mWh (`battery_capacity` setting > 0 and `battery_capacity_unit` set to `MWH`)
|
||||
- The average ground speed of the aircraft without wind at cruise throttle needs to be set (`nav_fw_cruise_speed` setting in cm/s)
|
||||
- The average power draw at zero throttle needs to be specified (`idle_power` setting in 0.01W unit)
|
||||
- The average power draw at cruise throttle needs to be specified (`cruise_power` setting in 0.01W unit)
|
||||
- The battery needs to be full when plugged in (voltage >= (`vbat_max_cell_voltage` - 100mV) * cells)
|
||||
|
||||
It is advised to set `nav_fw_cruise_speed` a bit lower than the real speed and `cruise_power` 10% higher than the power at cruise throttle to ensure variations in throttle during cruise won't cause the aircraft to draw more energy than estimated.
|
||||
|
||||
If `---` is displayed during flight instead of the remaining flight time/distance it means at least one of the above conditions aren't met. If the OSD element is blinking and the digits are replaced by the horizontal wind symbol it means that the estimated horizontal wind is too strong to be able to return home at `nav_fw_cruise_speed`.
|
||||
|
||||
## Automatic throttle compensation based on battery voltage
|
||||
|
||||
This features aims to compensate the throttle to get constant thrust with the same throttle request despite the battery voltage going down during flight. It can be used by enabling the `THR_VBAT_COMP` feature. This feature needs the sag compensated voltage which needs a current sensor (real or virtual) to be calculated.
|
||||
|
||||
It is working like this: `used_throttle = requested_throttle * (1 + (battery_full_voltage / sag_compensated_voltage - 1) * thr_comp_weight)`.
|
||||
|
||||
The default `thr_comp_weight` of 1 should be close to ideal but if you want to tune this feature you need to find the difference in throttle value to achieve the same thrust (same power) when your battery is full and when your battery is almost empty then set `thr_comp_weight` to `(empty_battery_throttle / full_battery_throttle - 1) / (battery_full_voltage / battery_empty_sag_compensated_voltage - 1)`
|
||||
|
||||
Example:
|
||||
If the drawn power is 100W when the battery is full (12.6V) with 53% throttle and the drawn power is 100W with 58% throttle when the battery is almost empty with the sag compensated voltage being 11.0V `thr_comp_weight` needs to be set to this value to compensate the throttle automatically:
|
||||
`(58 / 53 - 1) / (12.6 / 11.0 - 1) = 0.649`
|
||||
|
||||
Known limitation: it doesn't work in 3D mode (3D feature)
|
||||
@@ -0,0 +1,240 @@
|
||||
# Blackbox flight data recorder
|
||||
|
||||

|
||||
|
||||
## Introduction
|
||||
|
||||
This feature transmits your flight data information on every control loop iteration over a serial port to an external logging device to be recorded, SD card, or to a dataflash chip which is present on some flight controllers.
|
||||
|
||||
After your flight, you can view the resulting logs using the interactive log viewer:
|
||||
|
||||
https://github.com/iNavFlight/blackbox-log-viewer
|
||||
|
||||
You can also use the `blackbox_decode` tool to turn the logs into CSV files for analysis, or render your flight log as a
|
||||
video using the `blackbox_render` tool. Those tools can be found in this repository:
|
||||
|
||||
https://github.com/iNavFlight/blackbox-tools
|
||||
|
||||
## Logged data
|
||||
The blackbox records flight data on every iteration of the flight control loop. It records the current time in microseconds, P, I and D corrections for each axis, your RC command stick positions (after applying expo curves), gyroscope data, accelerometer data (after your configured low-pass filtering), barometer and rangefinder readings, 3-axis magnetometer readings, raw VBAT and current measurements, RSSI, and the command being sent to each motor speed controller. This is all stored without any approximation or loss of precision, so even quite subtle problems should be
|
||||
detectable from the fight data log.
|
||||
|
||||
GPS data is logged whenever new GPS data is available. Although the CSV decoder will decode this data, the video renderer does not yet show any of the GPS information (this will be added later).
|
||||
|
||||
## Supported configurations
|
||||
|
||||
The maximum data rate that can be recorded to the flight log is fairly restricted, so anything that increases the load can cause the flight log to drop frames and contain errors.
|
||||
|
||||
The Blackbox is typically used on tricopters and quadcopters. Although it will work on hexacopters and octocopters, because these craft have more motors to record, they must transmit more data to the flight log. This can increase the number of dropped frames. Although the browser-based log viewer supports hexacopters and octocopters, the command-line `blackbox_render` tool currently only supports tri- and quadcopters.
|
||||
|
||||
INAV's `looptime` setting decides how frequently an update is saved to the flight log. The default looptime on INAV is 2000us. If you're using a looptime smaller than about 2400, you may experience some dropped frames due to the high required data rate. In that case you will need to reduce the sampling rate in the Blackbox settings, or increase your logger's baudrate to 250000. See the later section on configuring the Blackbox feature for details.
|
||||
|
||||
## Setting up logging
|
||||
|
||||
First, you must enable the Blackbox feature. In the [INAV Configurator][] enter the Configuration tab, tick the "BLACKBOX" feature at the bottom of the page, and click "Save and reboot"
|
||||
|
||||
Now you must decide which device to store your flight logs on. You can either transmit the log data over a serial port to an external logging device like the [OpenLog serial data logger][] to be recorded to a microSDHC card, or if you have a compatible flight controller you can store the logs on the onboard dataflash storage instead.
|
||||
|
||||
### OpenLog serial data logger
|
||||
|
||||
The OpenLog is a small logging device which attaches to your flight controller using a serial port and logs your flights to a MicroSD card.
|
||||
|
||||
The OpenLog ships from SparkFun with standard "OpenLog 3" firmware installed. Although this original OpenLog firmware will work with the Blackbox, in order to reduce the number of dropped frames it should be reflashed with the higher performance [OpenLog Blackbox firmware][]. The special Blackbox variant of the OpenLog firmware also ensures that the OpenLog is using INAV compatible settings, and defaults to 115200 baud.
|
||||
|
||||
You can find the Blackbox version of the OpenLog firmware [here](https://github.com/iNavFlight/openlog-blackbox-firmware), along with instructions for installing it onto your OpenLog.
|
||||
|
||||
[OpenLog serial data logger]: https://www.sparkfun.com/products/9530
|
||||
[OpenLog Blackbox firmware]: https://github.com/iNavFlight/openlog-blackbox-firmware
|
||||
|
||||
#### microSDHC
|
||||
|
||||
Your choice of microSDHC card is very important to the performance of the system. The OpenLog relies on being able to make many small writes to the card with minimal delay, which not every card is good at. A faster SD-card speed rating is not a guarantee of better performance.
|
||||
|
||||
##### microSDHC cards known to have poor performance
|
||||
|
||||
- Generic 4GB Class 4 microSDHC card - the rate of missing frames is about 1%, and is concentrated around the most interesting parts of the log!
|
||||
- Sandisk Ultra 32GB (unlike the smaller 16GB version, this version has poor write latency)
|
||||
|
||||
##### microSDHC cards known to have good performance
|
||||
|
||||
- Transcend 16GB Class 10 UHS-I microSDHC (typical error rate < 0.1%)
|
||||
- Sandisk Extreme 16GB Class 10 UHS-I microSDHC (typical error rate < 0.1%)
|
||||
- Sandisk Ultra 16GB (it performs only half as well as the Extreme in theory, but still very good)
|
||||
|
||||
You should format any card you use with the [SD Association's special formatting tool][] , as it will give the OpenLog the best chance of writing at high speed. You must format it with either FAT, or with FAT32 (recommended).
|
||||
|
||||
[SD Association's special formatting tool]: https://www.sdcard.org/downloads/formatter_4/
|
||||
|
||||
### Choosing a serial port for the OpenLog
|
||||
First, tell the Blackbox to log using a serial port (rather than to an onboard dataflash chip). Go to the Configurator's CLI tab, enter `set blackbox_device=SERIAL` to switch logging to serial, and save.
|
||||
|
||||
You need to let INAV know which of [your serial ports][] you connect your OpenLog to (i.e. the Blackbox port), which you can do on the Configurator's Ports tab.
|
||||
|
||||
You should use a hardware serial port. SoftSerial ports can be used for the Blackbox. However, because they are limited to 19200 baud, your logging rate will need to be severely reduced to compensate. Therefore the use of SoftSerial is not recommended.
|
||||
|
||||
When using a hardware serial port, Blackbox should be set to at least 115200 baud on that port. When using fast looptimes (<2500), a baud rate of 250000 should be used instead in order to reduce dropped frames.
|
||||
|
||||
The serial port used for Blackbox cannot be shared with any other function (e.g. GPS, telemetry) except the MSP protocol. If MSP is used on the same port as Blackbox, then MSP will be active when the board is disarmed, and Blackbox will be active when the board is armed. This will mean that you can't use the Configurator or any other function that requires MSP, such as an OSD or a Bluetooth wireless configuration app, while the board is armed.
|
||||
|
||||
Connect the "TX" pin of the serial port you've chosen to the OpenLog's "RXI" pin. Don't connect the serial port's RX pin to the OpenLog, as this will cause the OpenLog to interfere with any shared functions on the serial port while disarmed.
|
||||
|
||||
The key criteria to choose a serial port are:
|
||||
|
||||
* Should be a hardware serial port rather than SoftSerial.
|
||||
* Cannot be shared with any other function (GPS, telemetry) except MSP.
|
||||
* If MSP is used on the same UART, MSP will stop working when the board is armed.
|
||||
|
||||
#### OpenLog configuration
|
||||
|
||||
Power up the OpenLog with a microSD card inside, wait 10 seconds or so, then power it down and plug the microSD card into your computer. You should find a "CONFIG.TXT" file on the card, open it up in a text editor. You should see the baud rate that the OpenLog has been configured for (usually 115200 or 9600 from the factory). Set the baud rate to match the rate you entered for the Blackbox in the Configurator's Port tab (typically 115200 or 250000).
|
||||
|
||||
Save the file and put the card back into your OpenLog, it will use those settings from now on.
|
||||
|
||||
If your OpenLog didn't write a CONFIG.TXT file, create a CONFIG.TXT file with these contents and store it in the root of the MicroSD card:
|
||||
|
||||
```
|
||||
115200
|
||||
baud
|
||||
```
|
||||
|
||||
If you are using the original OpenLog firmware, use this configuration instead:
|
||||
|
||||
```
|
||||
115200,26,0,0,1,0,1
|
||||
baud,escape,esc#,mode,verb,echo,ignoreRX
|
||||
```
|
||||
|
||||
#### OpenLog protection
|
||||
|
||||
The OpenLog can be wrapped in black electrical tape or heat-shrink in order to insulate it from conductive frames (like carbon fibre), but this makes its status LEDs impossible to see. I recommend wrapping it with some clear heatshrink tubing instead.
|
||||
|
||||

|
||||
|
||||
### Onboard dataflash storage
|
||||
Some flight controllers have an onboard SPI NOR dataflash chip which can be used to store flight logs instead of using an OpenLog.
|
||||
|
||||
These chips are also supported:
|
||||
|
||||
* Micron/ST M25P16 - 16 Mbit / 2 MByte
|
||||
* Micron N25Q064 - 64 Mbit / 8 MByte
|
||||
* Winbond W25Q64 - 64 Mbit / 8 MByte
|
||||
* Micron N25Q0128 - 128 Mbit / 16 MByte
|
||||
* Winbond W25Q128 - 128 Mbit / 16 MByte
|
||||
* Puya PY25Q128HA - 128 Mbit / 16 MByte
|
||||
* Winbond W25N01 - 1 Gbit / 128 MByte
|
||||
* Winbond W25N02 - 2 Gbit / 256 MByte
|
||||
|
||||
#### Enable recording to dataflash
|
||||
On the Configurator's CLI tab, you must enter `set blackbox_device=SPIFLASH` to switch to logging to an onboard dataflash chip, then save.
|
||||
|
||||
[your serial ports]: https://github.com/iNavFlight/inav/blob/master/docs/Serial.md
|
||||
[INAV Configurator]: https://chrome.google.com/webstore/detail/inav-configurator/fmaidjmgkdkpafmbnmigkpdnpdhopgel
|
||||
|
||||
## Configuring the Blackbox
|
||||
|
||||
The Blackbox currently provides two settings (`blackbox_rate_num` and `blackbox_rate_denom`) that allow you to control the rate at which data is logged. These two together form a fraction (`blackbox_rate_num / blackbox_rate_denom`) which decides what portion of the flight controller's control loop iterations should be logged. The default is 1/1 which logs every iteration.
|
||||
|
||||
If you're using a slower MicroSD card, you may need to reduce your logging rate to reduce the number of corrupted logged frames that `blackbox_decode` complains about. A rate of 1/2 is likely to work for most craft.
|
||||
|
||||
You can change the logging rate settings by entering the CLI tab in the [INAV Configurator][] and using the `set` command, like so:
|
||||
|
||||
```
|
||||
set blackbox_rate_num = 1
|
||||
set blackbox_rate_denom = 2
|
||||
```
|
||||
|
||||
The data rate for my quadcopter using a looptime of 2400 and a rate of 1/1 is about 10.25kB/s. This allows about 18 days of flight logs to fit on my OpenLog's 16GB MicroSD card, which ought to be enough for anybody :).
|
||||
|
||||
If you are logging using SoftSerial, you will almost certainly need to reduce your logging rate to 1/32. Even at that logging rate, looptimes faster than about 1000 cannot be successfully logged.
|
||||
|
||||
If you're logging to an onboard dataflash chip instead of an OpenLog, be aware that the 2MB of storage space it offers is pretty small. At the default 1/1 logging rate, and a 2400 looptime, this is only enough for about 3 minutes of flight. This could be long enough for you to investigate some flying problem with your craft, but you may want to reduce the logging rate in order to extend your recording time.
|
||||
|
||||
To maximize your recording time, you could drop the rate all the way down to 1/32 which would result in a logging rate of about 10-20Hz and about 650 bytes/second of data. At that logging rate, a 2MB dataflash chip can store around 50 minutes of flight data, though the level of detail is severely reduced and you could not diagnose flight problems like vibration or PID setting issues.
|
||||
|
||||
The CLI command `blackbox` allows setting which Blackbox fields are recorded to conserve space and bandwidth. Possible fields are:
|
||||
|
||||
* `NAV_ACC` - Navigation accelerometer readouts
|
||||
* `NAV_PID` - Navigation PID debug
|
||||
* `NAV_POS` - Current and target position and altitude
|
||||
* `MAG` - Magnetometer raw values
|
||||
* `ACC` - Accelerometer raw values
|
||||
* `ATTI` - Attitude as computed by INAV position estimator
|
||||
* `RC_DATA` - RC channels 1-4 as returned by the radio receiver
|
||||
* `RC_COMMAND` - RC_DATA converted to [-500:500] scale (for A,E,R) with expo and deadband
|
||||
* `MOTORS` - motor output
|
||||
* `GYRO_RAW` - Raw Gyro data
|
||||
* `PEAKS_R` - Roll axis noise peak
|
||||
* `PEAKS_P` - Pitch axis noise peak
|
||||
* `PEAKS_Y` - Yaw axis noise peak
|
||||
* `SERVOS` - Servo outputs (for planes, tris, etc.)
|
||||
|
||||
Usage:
|
||||
|
||||
* `blackbox` currently enabled Blackbox fields
|
||||
* `blackbox list` all available fields
|
||||
* `blackbox -MOTORS` disable MOTORS logging
|
||||
* `blackbox MOTORS` enable MOTORS logging
|
||||
|
||||
### Debug Mode Logging
|
||||
|
||||
In addition to the standard blackbox fields above, INAV supports logging debug values for troubleshooting and analysis via the `debug_mode` setting. When a debug mode is active, it populates 8 debug values (`debug[0]` through `debug[7]`) with mode-specific data that gets logged to the blackbox.
|
||||
|
||||
Available debug modes include:
|
||||
- `FLOW_RAW` - Optical flow sensor raw data (useful for sensor alignment)
|
||||
- `LANDING` - Landing mode debugging
|
||||
- `POS_EST` - Position estimation debugging
|
||||
- `GPS` - GPS debugging
|
||||
- `ALTITUDE` - Altitude estimation debugging
|
||||
- And 20+ other modes for specific subsystems
|
||||
|
||||
To use debug mode logging:
|
||||
```
|
||||
set debug_mode = FLOW_RAW # Enable a specific debug mode
|
||||
set debug_mode = NONE # Disable debug mode (default)
|
||||
```
|
||||
|
||||
You can view current debug values in the CLI with the `debug` command, or display them in real-time on your OSD using the `OSD_DEBUG` element.
|
||||
|
||||
For technical details on debug logging and blackbox internals, see the [Blackbox Internals](development/Blackbox%20Internals.md) documentation.
|
||||
|
||||
## Usage
|
||||
|
||||
The Blackbox starts recording data as soon as you arm your craft, and stops when you disarm.
|
||||
|
||||
If your craft has a buzzer attached, you can use INAV's arming beep to synchronize your Blackbox log with your flight video. INAV's arming beep is a "long, short" pattern. The beginning of the first long beep will be shown as a blue line in the flight data log, which you can sync against your recorded audio track.
|
||||
|
||||
You should wait a few seconds after disarming your craft to allow the Blackbox to finish saving its data.
|
||||
|
||||
### Usage - OpenLog
|
||||
Each time the OpenLog is power-cycled, it begins a fresh new log file. If you arm and disarm several times without cycling the power (recording several flights), those logs will be combined together into one file. The command line tools will ask you to pick which one of these flights you want to display/decode.
|
||||
|
||||
Don't insert or remove the SD card while the OpenLog is powered up.
|
||||
|
||||
### Usage - Dataflash chip
|
||||
After your flights, you can use the [INAV Configurator][] to download the contents of the dataflash to your computer. Go to the "dataflash" tab and click the "save flash to file..." button. Saving the log can take 2 or 3 minutes.
|
||||
|
||||

|
||||
|
||||
After downloading the log, be sure to erase the chip to make it ready for reuse by clicking the "erase flash" button.
|
||||
|
||||
If you try to start recording a new flight when the dataflash is already full, Blackbox logging will be disabled and nothing will be recorded.
|
||||
|
||||
### Usage - Logging switch
|
||||
If you're recording to an onboard flash chip, you probably want to disable Blackbox recording when not required in order to save storage space. To do this, you can add a Blackbox flight mode to one of your AUX channels on the Configurator's modes tab. Once you've added a mode, Blackbox will only log flight data when the mode is active.
|
||||
|
||||
A log header will always be recorded at arming time, even if logging is paused. You can freely pause and resume logging while in flight.
|
||||
|
||||
## Viewing recorded logs
|
||||
After your flights, you'll have a series of flight log files with a .TXT extension.
|
||||
|
||||
You can view these .TXT flight log files interactively using your web browser with the INAV Blackbox Explorer:
|
||||
|
||||
https://github.com/iNavFlight/blackbox-log-viewer
|
||||
|
||||
This allows you to scroll around a graphed version of your log and examine your log in detail. You can also export a video of your log to share it with others!
|
||||
|
||||
You can decode your logs with the `blackbox_decode` tool to create CSV (comma-separated values) files for analysis, or render them into a series of PNG frames with `blackbox_render` tool, which you could then convert into a video using another software package.
|
||||
|
||||
You'll find those tools along with instructions for using them in this repository:
|
||||
|
||||
https://github.com/iNavFlight/blackbox-tools
|
||||
@@ -0,0 +1,36 @@
|
||||
# Flight controller hardware
|
||||
|
||||
### Recommended boards
|
||||
|
||||
These boards are well tested with INAV and are known to be of good quality and reliability.
|
||||
|
||||
| Board name | CPU Family | Target name(s) | GPS | Compass | Barometer | Telemetry | RX | Blackbox |
|
||||
|---------------------------|:----------:|:-------------------------:|:----:|:-------:|:--------------:|:---------:|:------------------------------:|:--------------------:|
|
||||
| [Diatone Mamba H743](https://inavflight.com/shop/s/bg/1929033) | H7 | MAMBAH743 | All | All | All | All | All | SERIAL, SD |
|
||||
| [Matek F765-WSE](https://inavflight.com/shop/s/bg/1890404) | F7 | MATEKF765SE | All | All | All | All | All | SERIAL, SD |
|
||||
| [Matek F722-SE](https://inavflight.com/shop/p/MATEKF722SE) | F7 | MATEKF722SE | All | All | All | All | All | SERIAL, SD |
|
||||
| [Holybro Kakute H7](https://inavflight.com/shop/s/bg/1914066) | H7 | KAKUTEH7 | All | All | All | All | All | SERIAL, SD |
|
||||
|
||||
It's possible to find more supported and tested boards [here](https://github.com/iNavFlight/inav/wiki/Welcome-to-INAV,-useful-links-and-products)
|
||||
|
||||
There is also a [full list of all supported boards](https://github.com/iNavFlight/inav/wiki/Boards,-Targets-and-PWM-allocations).
|
||||
|
||||
### Boards documentation
|
||||
|
||||
See the [docs/boards](https://github.com/iNavFlight/inav/tree/master/docs/boards) folder for additional information regards to many targets in INAV, to example help in finding pinout and features. _Feel free to help improve the docs._
|
||||
|
||||
### Boards based on F4/F7 CPUs
|
||||
|
||||
These boards are powerful and in general support everything INAV is capable of. Limitations are quite rare and are usually caused by hardware design issues.
|
||||
|
||||
### Boards based on F3 CPUs
|
||||
|
||||
Boards based on STM32F3 MCUs are no longer supported by latest INAV version. Last release is 2.6.1.
|
||||
|
||||
### Boards based on F1 CPUs
|
||||
|
||||
Boards based on STM32F1 CPUs are no longer supported by latest INAV version. Last release is 1.7.3
|
||||
|
||||
### Not recommended for new setups
|
||||
|
||||
F1 and F3 boards are no longer recommended. Users should choose a board from the supported F4 or F7 devices available in the latest release.
|
||||
@@ -0,0 +1,79 @@
|
||||
# Broken USB recovery
|
||||
|
||||
It is possible to flash INAV without USB over UART 1 or 3.
|
||||
|
||||
## Prerequisites:
|
||||
- USB/UART adapter (FT232, CP2102, etc.)
|
||||
- STM32 Cube Programmer (https://www.st.com/en/development-tools/stm32cubeprog.html)
|
||||
|
||||
To gain access to the FC via Configurator, MSP must be activated on a UART as standard. Some FCs already have this enabled by default, if not a custom firmware must be created.
|
||||
|
||||
The following targets have MSP activated on a UART by default:
|
||||
|
||||
| Target | Standard MSP Port |
|
||||
|-----------| ----------- |
|
||||
| AOCODARCF4V3 | UART5 |
|
||||
| ATOMRCF405NAVI_DELUXE | UART1 |
|
||||
| FF_F35_LIGHTNING | UART1 |
|
||||
| FLYCOLORF7V2 | UART4 |
|
||||
| GEPRCF405_BT_HD | UART5* |
|
||||
| GEPRCF722_BT_HD | UART4* |
|
||||
| IFLIGHT_BLITZ_F7_AIO | UART1 |
|
||||
| JHEMCUF405WING | UART6 |
|
||||
| JHEMCUH743HD | UART4 |
|
||||
| KAKUTEH7 | UART1 and UART2* |
|
||||
| KAKUTEH7WING | UART6 |
|
||||
| MAMBAF405_2022A | UART4 |
|
||||
| MAMBAF405US | UART4 |
|
||||
| MAMBAF722 | UART4 |
|
||||
| MAMBAF722 APP | UART4*|
|
||||
| MAMBAF722WING | UART4 |
|
||||
| MAMBAF722_X8 | UART4 |
|
||||
| MAMBAH743 | UART4* |
|
||||
| MATEKF405SE | UART1 |
|
||||
| NEUTRONRCH743BT | UART3* |
|
||||
| SDMODELH7V1 | UART1 and UART2 |
|
||||
| SKYSTARSH743HD | UART4 |
|
||||
| SPEEDYBEEF4 | UART5* |
|
||||
| SPEEDYBEEF405MINI | UART4* |
|
||||
| SPEEDYBEEF405V3 | UART4* |
|
||||
| SPEEDYBEEF405V4 | UART4* |
|
||||
| SPEEDYBEEF405WING | UART6 |
|
||||
| SPEEDYBEEF7 | UART6 |
|
||||
| SPRACINGF4EVO | UART1 |
|
||||
| TMOTORF7V2 | UART5 |
|
||||
|
||||
(*) No Pads/Pins, Port is used interally (Bluetooth)
|
||||
|
||||
## Custom firmware:
|
||||
|
||||
If the FC does not have MSP activated on a UART by default or does not have a connector for it, a custom firmware must be built.
|
||||
The following procedure describes the process under Windows 10/11:
|
||||
|
||||
Please read [Building in Windows 2010 or 11 with Linux Subsystem](https://github.com/iNavFlight/inav/blob/master/docs/development/Building%20in%20Windows%2010%20or%2011%20with%20Linux%20Subsystem.md)
|
||||
and follow the instructions up to "Building with Make".
|
||||
|
||||
In the step 'prepare build environment' add the option `-DMSP_UART=SERIAL_PORT_USARTX` to `cmake`
|
||||
|
||||
Replace the X in SERIAL_PORT_USARTX with the number of UART/serial port on which MSP is to be activated.
|
||||
|
||||
Example:
|
||||
For UART 2: `cmake -DMSP_UART=SERIAL_PORT_USART2 ..`
|
||||
For UART 3: `cmake -DMSP_UART=SERIAL_PORT_USART3 ..`
|
||||
etc.
|
||||
|
||||
Build the firmware as described in the document above (`make [YOUR_TARGET]`).
|
||||
|
||||
## Flashing via Uart:
|
||||
|
||||
1. Disconnect ALL peripherals and the USB Cable from the FC. To power the FC use a battery or use the 5V provided from the USB/Serial Converter.
|
||||
2. Connect UART 1 or 3 (other UARTS will not work) and GND to the USB/Serial converter (RX -> TX, TX -> RX)
|
||||
3. Keep the boot/dfu button pressed
|
||||
4. Switch on the FC / supply with power
|
||||
5. Start STM32 CubeProgrammer and go to "Erasing & Programming", second option in the menu.
|
||||
6. Select UART (blue dropdown field) and select the COM port of the USB/Serial adapter and press "Connect". The corresponding processor should now be displayed below.
|
||||
7. Click on "Full flash erase". This is also necessary if you are flashing the same firmware version that was previously on the FC, otherwise MSP may not be activated on the UART.
|
||||
8. Under "Download" load the previously created firmware (`INAV_X.X.X_[Your Target].hex`) or the standard firmware if UART is already activated there. The option "Verify programming" is optional but recommended. Make sure that "Skip flash erase while programming" is NOT activated.
|
||||
9. Click "Start Programming"
|
||||
|
||||
After the process is completed, switch the FC off and on again and then the Configurator can connect to the FC via USB/serial adapter and the previously configured UART.
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
# Buzzer
|
||||
|
||||
INAV supports a buzzer which is used for the following purposes:
|
||||
|
||||
* Low and critical battery alarms (when battery monitoring enabled)
|
||||
* Arm/disarm tones (and warning beeps while armed)
|
||||
* Notification of calibration complete status
|
||||
* TX-AUX operated beeping - useful for locating your aircraft after a crash
|
||||
* Failsafe status
|
||||
* Flight mode change
|
||||
* Rate profile change (via TX-AUX switch)
|
||||
|
||||
If the arm/disarm is via the control stick, holding the stick in the disarm position will sound a repeating tone. This can be used as a lost-model locator.
|
||||
|
||||
Three beeps immediately after powering the board means that the gyroscope calibration has completed successfully. INAV calibrates the gyro automatically upon every power-up. It is important that the copter stay still on the ground until the three beeps sound, so that gyro calibration isn't thrown off. If you move the copter significantly during calibration, INAV will detect this, and will automatically re-start the calibration once the copter is still again. This will delay the "three beeps" tone. If you move the copter just a little bit, the gyro calibration may be incorrect, and the copter may not fly correctly. In this case, the gyro calibration can be performed manually via [stick command](Controls.md), or you may simply power cycle the board.
|
||||
|
||||
There is a special arming tone used if a GPS fix has been attained, and there's a "ready" tone sounded after a GPS fix has been attained (only happens once). The tone sounded via the TX-AUX-switch will count out the number of satellites (if GPS fix).
|
||||
|
||||
The CLI command `play_sound` is useful for demonstrating the buzzer tones. Repeatedly entering the command will play the various tones in turn. Entering the command with a numeric-index parameter (see below) will play the associated tone.
|
||||
|
||||
Buzzer is enabled by default on platforms that have buzzer connections.
|
||||
|
||||
## Tone sequences
|
||||
|
||||
Buzzer tone sequences (square wave generation) are made so that : 1st, 3rd, 5th, .. are the delays how long the beeper is on and 2nd, 4th, 6th, .. are the delays how long beeper is off. Delays are in milliseconds/10 (i.e., 5 => 50ms).
|
||||
|
||||
Sequences:
|
||||
|
||||
0 GYRO_CALIBRATED 20, 10, 20, 10, 20, 10 Gyro is calibrated
|
||||
1 RX_LOST_LANDING 10, 10, 10, 10, 10, 40, 40, 10, 40, 10, 40, 40, 10, 10, 10, 10, 10, 70 SOS morse code
|
||||
2 RX_LOST 50, 50 TX off or signal lost (repeats until TX is okay)
|
||||
3 DISARMING 15, 5, 15, 5 Disarming the board
|
||||
4 ARMING 30, 5, 5, 5 Arming the board
|
||||
5 ARMING_GPS_FIX 5, 5, 15, 5, 5, 5, 15, 30 Arming and GPS has fix
|
||||
6 BAT_CRIT_LOW 50, 2 Battery is critically low (repeats)
|
||||
7 BAT_LOW 25, 50 Battery is getting low (repeats)
|
||||
8 NULL multi beeps GPS status (sat count)
|
||||
9 RX_SET 10, 10 RX is set (when aux channel is set for beep or beep sequence how many satellites has found if GPS enabled)
|
||||
10 ACC_CALIBRATION 5, 5, 5, 5 ACC inflight calibration completed
|
||||
11 ACC_CALIBRATION_FAIL 20, 15, 35, 5 ACC inflight calibration failed
|
||||
12 READY_BEEP 4, 5, 4, 5, 8, 5, 15, 5, 8, 5, 4, 5, 4, 5 GPS locked and copter ready
|
||||
13 NULL multi beeps Variable # of beeps (confirmation, GPS sat count, etc)
|
||||
14 DISARM_REPEAT 0, 100, 10 Stick held in disarm position (after pause)
|
||||
15 ARMED 0, 245, 10, 5 Board is armed (after pause ; repeats until board is disarmed or throttle is increased)
|
||||
|
||||
You can use [this tool](https://www.mrd-rc.com/tutorials-tools-and-testing/useful-tools/helpful-inav-buzzer-code-checker/) to hear current buzzer sequences or enter custom sequences.
|
||||
|
||||
## Controlling buzzer usage
|
||||
|
||||
The usage of the buzzer can be controlled by the CLI `beeper` command.
|
||||
|
||||
### List current usage
|
||||
|
||||
```
|
||||
beeper
|
||||
```
|
||||
### List all buzzer setting options
|
||||
|
||||
```
|
||||
beeper list
|
||||
```
|
||||
giving:
|
||||
|
||||
```
|
||||
Available: RUNTIME_CALIBRATION HW_FAILURE RX_LOST RX_LOST_LANDING DISARMING ARMING ARMING_GPS_FIX BAT_CRIT_LOW
|
||||
BAT_LOW GPS_STATUS RX_SET ACTION_SUCCESS ACTION_FAIL READY_BEEP MULTI_BEEPS DISARM_REPEAT ARMED SYSTEM_INIT
|
||||
ON_USB LAUNCH_MODE CAM_CONNECTION_OPEN CAM_CONNECTION_CLOSED ALL PREFERED
|
||||
```
|
||||
|
||||
The `beeper` command syntax follows that of the `feature` command; a minus (`-`) in front of a name disables that function.
|
||||
|
||||
So to disable the beeper / buzzer when powered by USB (may enhance domestic harmony):
|
||||
|
||||
```
|
||||
beeper -ON_USB
|
||||
```
|
||||
|
||||
Now the `beeper` command will show:
|
||||
|
||||
```
|
||||
# beeper
|
||||
Disabled: ON_USB
|
||||
```
|
||||
|
||||
*Note: SYSTEM_INIT sequence is not affected by ON_USB setting and will still be played on USB connection. Disable both ON_USB and SYSTEM_INIT to disable buzzer completely when FC is powered from USB.*
|
||||
|
||||
*Note: ON_USB setting requires present and configured battery voltage metter.*
|
||||
|
||||
To disable all features use:
|
||||
|
||||
```
|
||||
beeper -ALL
|
||||
```
|
||||
|
||||
To store current set to preferences use (preferences also require ```save```):
|
||||
|
||||
```
|
||||
beeper PREFERED
|
||||
```
|
||||
|
||||
To restore set from preferences use:
|
||||
|
||||
```
|
||||
beeper -PREFERED
|
||||
```
|
||||
|
||||
To activate an external beeper via aux channel switch, assign aux channel and set both:
|
||||
|
||||
```
|
||||
beeper RX_SET
|
||||
beeper MULTI_BEEPS
|
||||
```
|
||||
If MULTI_BEEPS is not set, the beeper will not sound after GPS lock.
|
||||
|
||||
As with other CLI commands, the `save` command is needed to save the new settings.
|
||||
|
||||
## Types of buzzer supported
|
||||
|
||||
Most FCs require ACTIVE buzzers. Active buzzers are enabled/disabled by simply enabling or disabling a GPIO output pin on the board.
|
||||
This means the buzzer must be able to generate its own tone simply by having power applied to it.
|
||||
|
||||
Passive buzzers that need an analog or PWM signal do not work and will make clicking noises or no sound at all.
|
||||
|
||||
Passive buzzers are supported on FCs which are designed to work with passive buzzers only (so far there is no available, except rare cases like Matek F765-WSE where passive buzzer is preinstalled).
|
||||
|
||||
Examples of a known-working buzzers.
|
||||
|
||||
* [Hcm1205x Miniature Buzzer 5v](http://www.rapidonline.com/Audio-Visual/Hcm1205x-Miniature-Buzzer-5v-35-0055)
|
||||
* [MultiComp MCKPX-G1205A-3700 TRANSDUCER, THRU-HOLE, 4V, 30MA](http://uk.farnell.com/multicomp/mckpx-g1205a-3700/transducer-thru-hole-4v-30ma/dp/2135914?CMP=i-bf9f-00001000)
|
||||
* [3-24V Piezo Electronic Tone Buzzer Alarm 95DB](https://inavflight.com/shop/s/bg/919348)
|
||||
@@ -0,0 +1,15 @@
|
||||
# Channel forwarding
|
||||
|
||||
Starting from INAV 2.0, _channel forwarding_ feature is removed. Channel forwarding functionality can be configured using _Mixer Configurator Tab_ instead.
|
||||
|
||||
Channel forwarding using mixer works for all flight controllers that supports servos in either multirotor or airplane configuration. Bear in mind, that some boards might not have any servo outputs in multirotor configuration. In this case, channel forwarding will just not work. Refer to the board documentation to find out if servos are available in multirotor configuration.
|
||||
|
||||
## How to setup channel forwarding
|
||||
|
||||

|
||||
|
||||
1. Open Mixer tab
|
||||
1. Add new _servo rule_ for given servo index
|
||||
1. Choose source as one of _RC Roll_, _RC Pitch_, _RC Yaw_, _RC Throttle_ or _RC Channel 5_ to _RC Channel 16_
|
||||
1. When required, servo direction can be modified by applying negative weight
|
||||
1. It is possible to limit servo speed. Refer to [Mixer documentation](Mixer.md)
|
||||
+251
@@ -0,0 +1,251 @@
|
||||
# Command Line Interface (CLI)
|
||||
|
||||
INAV has a command line interface (CLI) that can be used to change settings and configure the FC.
|
||||
|
||||
## Accessing the CLI.
|
||||
|
||||
The CLI can be accessed via the GUI tool or via a terminal emulator connected to the CLI serial port.
|
||||
|
||||
1. Connect your terminal emulator to the CLI serial port (which, by default, is the same as the MSP serial port)
|
||||
2. Use the baudrate specified by msp_baudrate (115200 by default).
|
||||
3. Send a `#` character.
|
||||
|
||||
To save your settings type in 'save', saving will reboot the flight controller.
|
||||
|
||||
To exit the CLI without saving power off the flight controller or type in 'exit'.
|
||||
|
||||
To see a list of other commands type in 'help' and press return.
|
||||
|
||||
To dump your configuration (including the current profile), use the 'dump' or 'diff' command.
|
||||
|
||||
See the other documentation sections for details of the cli commands and settings that are available.
|
||||
|
||||
## Backup via CLI
|
||||
|
||||
> **Note:** The INAV Configurator now performs automatic backups before flashing and can restore settings afterwards, including migration across major versions. See [Backup and Restore](Backup%20and%20Restore.md) for details. The CLI method below remains available for manual backup.
|
||||
|
||||
Disconnect main power, connect to cli via USB/FTDI.
|
||||
|
||||
dump using cli
|
||||
|
||||
```
|
||||
control_profile 0
|
||||
dump
|
||||
```
|
||||
|
||||
dump control_profiles using cli if you use them
|
||||
|
||||
```
|
||||
control_profile 1
|
||||
dump control_profile
|
||||
control_profile 2
|
||||
dump control_profile
|
||||
```
|
||||
|
||||
copy screen output to a file and save it.
|
||||
|
||||
Alternatively, use the `diff` command to dump only those settings that differ from their default values (those that have been changed).
|
||||
|
||||
|
||||
## Restore via CLI.
|
||||
|
||||
Use the cli `defaults` command first.
|
||||
|
||||
When restoring from backup it's a good idea to do a dump of the latest defaults so you know what has changed - if you do this each time a firmware release is created you will be able to see the cli changes between firmware versions. If you blindly restore your backup you would not benefit from these new defaults or may even end up with completely wrong settings in case some parameters changed semantics and/or value ranges.
|
||||
|
||||
It may be good idea to restore settings using the `diff` output rather than complete `dump`. This way you can have more control on what is restored and the risk of mistakenly restoring bad values if the semantics changes is minimised.
|
||||
|
||||
To perform the restore simply paste the saved commands in the Configurator CLI tab and then type `save`.
|
||||
|
||||
After restoring it's always a good idea to `dump` or `diff` the settings once again and compare the output with previous one to verify if everything is set as it should be.
|
||||
|
||||
## Flight Controller opereration while connected to the CLI
|
||||
|
||||
While connected to the CLI, all Logical Switches are temporarily disabled (5.1.0 onwards).
|
||||
|
||||
## CLI Command Reference
|
||||
|
||||
| `Command` | Description |
|
||||
|-----------| ----------- |
|
||||
| `adjrange` | Configure adjustment ranges |
|
||||
| `assert` | |
|
||||
| `aux` | Configure modes |
|
||||
| `batch` | Start or end a batch of commands |
|
||||
| `battery_profile` | Change battery profile |
|
||||
| `beeper` | Show/set beeper (buzzer) [usage](Buzzer.md) |
|
||||
| `bind_msp_rx` | Initiate binding for MSP receivers (mLRS) |
|
||||
| `bind_rx` | Initiate binding for SRXL2 or CRSF receivers |
|
||||
| `blackbox` | Configure blackbox fields |
|
||||
| `bootlog` | Show init logs from [serial_printf_debugging](./development/serial_printf_debugging.md) |
|
||||
| `color` | Configure colors |
|
||||
| `defaults` | Reset to defaults and reboot |
|
||||
| `dfu` | DFU mode on reboot |
|
||||
| `diff` | List configuration changes from default |
|
||||
| `dump` | Dump configuration |
|
||||
| `exit` | |
|
||||
| `feature` | List or enable <val> or disable <-val> |
|
||||
| `flash_erase` | Erase flash chip |
|
||||
| `flash_info` | Show flash chip info |
|
||||
| `flash_read` | |
|
||||
| `flash_write` | |
|
||||
| `get` | Get variable value |
|
||||
| `gpspassthrough` | Passthrough gps to serial |
|
||||
| `gvar` | Configure global variables |
|
||||
| `help` | Displays CLI help and command parameters / options |
|
||||
| `led` | Configure leds |
|
||||
| `logic` | Configure logic conditions |
|
||||
| `map` | Configure rc channel order |
|
||||
| `memory` | View memory usage |
|
||||
| `mmix` | Custom motor mixer |
|
||||
| `mode_color` | Configure mode and special colors |
|
||||
| `motor` | Get/set motor |
|
||||
| `msc` | Enter USB Mass storage mode. See [USB MSC documentation](USB_Mass_Storage_(MSC)_mode.md) for usage information. |
|
||||
| `osd_layout` | Get or set the layout of OSD items |
|
||||
| `pid` | Configurable PID controllers |
|
||||
| `play_sound` | `<index>`, or none for next item |
|
||||
| `control_profile` | Change profile |
|
||||
| `resource` | View currently used resources |
|
||||
| `rxrange` | Configure rx channel ranges |
|
||||
| `safehome` | Define safe home locations. See the [safehome documentation](Safehomes.md) for usage information. |
|
||||
| `save` | Save and reboot |
|
||||
| `sd_info` | Sdcard info |
|
||||
| `serial` | Configure serial ports. [Usage](Serial.md) |
|
||||
| `serialpassthrough` | Passthrough serial data to port, with `<id> <baud> <mode> <options>`, where `id` is the zero based port index, `baud` is a standard baud rate, mode is `rx`, `tx`, or both (`rxtx`), and options is a short string like `8N1` or `8E2` |
|
||||
| `servo` | Configure servos |
|
||||
| `set` | Change setting with name=value or blank or * for list |
|
||||
| `smix` | Custom servo mixer |
|
||||
| `status` | Show status. Error codes can be looked up [here](https://github.com/iNavFlight/inav/wiki/%22Something%22-is-disabled----Reasons) |
|
||||
| `tasks` | Show task stats |
|
||||
| `temp_sensor` | List or configure temperature sensor(s). See [temperature sensors documentation](Temperature-sensors.md) for more information. |
|
||||
| `timer_output_mode` | Override automatic timer / pwm function allocation. [Additional Information](#timer_outout_mode)|
|
||||
| `version` | Show version |
|
||||
| `wp` | List or configure waypoints. See the [navigation documentation](Navigation.md#cli-command-wp-to-manage-waypoints). |
|
||||
|
||||
Notes:
|
||||
|
||||
* Available commands depend upon hardware specific and debug build options. Not all commands are available in every FC.
|
||||
* The above list shows the output available in the CLI `help` command. This may also show additional information.
|
||||
|
||||
### serial
|
||||
|
||||
The syntax of the `serial` command is `serial <id> <function_value> <msp-baudrate> <gps-baudrate> <telemetry-baudate> <peripheral-baudrate>`.
|
||||
|
||||
A shorter form is also supported to enable and disable a single function using `serial <id> +n` and `serial <id> -n`, where n is the a serial function identifier. The following values are available:
|
||||
|
||||
| Function | Bit Identifier | Numeric value |
|
||||
|-----------------------|---------------|----------------|
|
||||
| MSP | 0 | 1 |
|
||||
| GPS | 1 | 2 |
|
||||
| TELEMETRY_FRSKY | 2 | 4 |
|
||||
| TELEMETRY_HOTT | 3 | 8 |
|
||||
| TELEMETRY_LTM | 4 | 16 |
|
||||
| TELEMETRY_SMARTPORT | 5 | 32 |
|
||||
| RX_SERIAL | 6 | 64 |
|
||||
| BLACKBOX | 7 | 128 |
|
||||
| TELEMETRY_MAVLINK | 8 | 256 |
|
||||
| TELEMETRY_IBUS | 9 | 512 |
|
||||
| RCDEVICE | 10 | 1024 |
|
||||
| VTX_SMARTAUDIO | 11 | 2048 |
|
||||
| VTX_TRAMP | 12 | 4096 |
|
||||
| UAV_INTERCONNECT | 13 | 8192 |
|
||||
| OPTICAL_FLOW | 14 | 16384 |
|
||||
| LOG | 15 | 32768 |
|
||||
| RANGEFINDER | 16 | 65536 |
|
||||
| VTX_FFPV | 17 | 131072 |
|
||||
| ESCSERIAL | 18 | 262144 |
|
||||
| TELEMETRY_SIM | 19 | 524288 |
|
||||
| FRSKY_OSD | 20 | 1048576 |
|
||||
| DJI_HD_OSD | 21 | 2097152 |
|
||||
| SERVO_SERIAL | 22 | 4194304 |
|
||||
| TELEMETRY_SMARTPORT_MASTER | 23 | 8388608 |
|
||||
| UNUSED | 24 | 16777216 |
|
||||
| MSP_DISPLAYPORT | 25 | 33554432 |
|
||||
| GIMBAL_SERIAL | 26 | 67108864 |
|
||||
| HEADTRACKER_SERIAL | 27 | 134217728 |
|
||||
|
||||
Thus, to enable MSP and LTM on a port, one would use the function **value** of 17 (1 << 0)+(1<<4), aka 1+16, aka 17.
|
||||
|
||||
```
|
||||
serial 0 17 57600 57600 57600 57600
|
||||
```
|
||||
but to remove LTM using the +/- shorthand, use the **bit Id** (4, TELEMETRY_LTM):
|
||||
|
||||
```
|
||||
serial 0 -4
|
||||
```
|
||||
|
||||
`serial` can also be used without any argument to print the current configuration of all the serial ports.
|
||||
|
||||
### `timer_output_mode`
|
||||
|
||||
Since INAV 7, the firmware can dynamically allocate servo and motor outputs. This removes the need for bespoke targets for special cases (e.g. `MATEKF405` and `MATEKF405_SERVOS6`).
|
||||
|
||||
#### Syntax
|
||||
|
||||
```
|
||||
timer_output_mode [timer [function]]
|
||||
```
|
||||
where:
|
||||
* Without parameters, lists the current timers and modes
|
||||
* With just a `timer` lists the mode for that timer
|
||||
* With both `timer` and `function`, sets the function for that timers
|
||||
|
||||
Note:
|
||||
|
||||
* `timer` identifies the timer **index** (from 0); thus is one less than the corresponding `TIMn` definition in a target's `target.c`.
|
||||
* The function is one of `AUTO` (the default), `MOTORS` or `SERVOS`.
|
||||
|
||||
Motors are allocated first, hence having a servo before a motor may require use of `timer_output_mode`.
|
||||
|
||||
#### Example
|
||||
|
||||
The original `MATEKF405` target defined a multi-rotor (MR) servo on output S1. The later `MATEKF405_SERVOS6` target defined (for MR) S1 as a motor and S6 as a servo. This was more logical, but annoying for anyone who had a legacy `MATEKF405` tricopter with the servo on S1.
|
||||
|
||||
#### Solution
|
||||
|
||||
There is now a single `MATEKF405` target. The `target.c` sets the relevant outputs as:
|
||||
|
||||
```
|
||||
DEF_TIM(TIM3, CH1, PC6, TIM_USE_OUTPUT_AUTO, 0, 0), // S1
|
||||
DEF_TIM(TIM8, CH2, PC7, TIM_USE_OUTPUT_AUTO, 0, 1), // S2 UP(2,1)
|
||||
DEF_TIM(TIM8, CH3, PC8, TIM_USE_OUTPUT_AUTO, 0, 1), // S3 UP(2,1)
|
||||
DEF_TIM(TIM8, CH4, PC9, TIM_USE_OUTPUT_AUTO, 0, 0), // S4 UP(2,1)
|
||||
DEF_TIM(TIM2, CH1, PA15, TIM_USE_MC_MOTOR | TIM_USE_LED, 0, 0), // S5 UP(1,7)
|
||||
DEF_TIM(TIM1, CH1, PA8, TIM_USE_OUTPUT_AUTO, 0, 0), // S6 UP(2,5)
|
||||
DEF_TIM(TIM4, CH3, PB8, TIM_USE_OUTPUT_AUTO, 0, 0), // S7 D(1,7)!S5 UP(2,6)
|
||||
```
|
||||
|
||||
Using the "motors first" allocation, the servo would end up on S6, which in the legacy "tricopter servo on S1" case is not desired.
|
||||
|
||||
Forcing the S1 output (`TIM3`) to servo is achieved by:
|
||||
|
||||
```
|
||||
timer_output_mode 2 SERVOS
|
||||
```
|
||||
|
||||
with resulting `resource` output:
|
||||
|
||||
```
|
||||
C06: SERVO4 OUT
|
||||
C07: MOTOR1 OUT
|
||||
C08: MOTOR2 OUT
|
||||
C09: MOTOR3 OUT
|
||||
```
|
||||
|
||||
Note that the `timer` **index** in the `timer_output_mode` line is one less than the mnemonic in `target.c`, `timer` of 2 for `TIM3`.
|
||||
|
||||
Note that the usual caveat that one should not share a timer with both a motor and a servo still apply.
|
||||
|
||||
## Flash chip management
|
||||
|
||||
For targets that have a flash data chip, typically used for blackbox logs, the following additional comamnds are provided.
|
||||
|
||||
| Command | Effect |
|
||||
| ------- | ------ |
|
||||
| `flash_erase` | Erases the flash chip |
|
||||
| `flash_info` | Displays flash chip information (used, free etc.) |
|
||||
| `flash_read <length> <address>` | Reads `length` bytes from `address` |
|
||||
| `flash_write <address> <data>` | Writes `data` to `address` |
|
||||
|
||||
## CLI Variable Reference
|
||||
See [Settings.md](Settings.md).
|
||||
@@ -0,0 +1,35 @@
|
||||
# Configuration
|
||||
|
||||
INAV is configured primarily using the INAV Configurator GUI.
|
||||
|
||||
Both the command line interface and GUI are accessible by connecting to a serial port on the target,
|
||||
be it a USB virtual serial port, physical hardware UART port or a SoftSerial port.
|
||||
|
||||
See the Serial section for more information and see the Board specific sections for details of the serial ports available on the board you are using.
|
||||
|
||||
The GUI cannot currently configure all aspects of the system, the CLI must be used to enable or configure
|
||||
some features and settings.
|
||||
|
||||
__The INAV Configurator now (versions after 9.0.x) automatically backs up your settings before flashing firmware and can restore them afterwards (when Full Chip Erase is enabled), including automatic migration across major versions. For details, see [Backup and Restore](Backup%20and%20Restore.md). You can also manually backup and restore settings using the [CLI](Cli.md#backup-via-cli).__
|
||||
|
||||
|
||||
## GUI
|
||||
|
||||

|
||||
|
||||
The GUI tool is the preferred way of configuration. The GUI tool also includes a terminal which
|
||||
can be used to interact with the CLI.
|
||||
|
||||
[INAV Configurator on Chrome store](https://chrome.google.com/webstore/detail/inav-configurator/fmaidjmgkdkpafmbnmigkpdnpdhopgel)
|
||||
|
||||
If you cannot use the latest version of the GUI to access the FC due to firmware compatibility issues you can still access the FC via the CLI to backup your settings, or you can install an old version of the configurator.
|
||||
|
||||
Old versions of the configurator can be downloaded from the configurator releases page: https://github.com/iNavFlight/inav-configurator/releases
|
||||
See the README file that comes with the configurator for installation instructions.
|
||||
|
||||
|
||||
## CLI
|
||||
|
||||
INAV can also be configured by a command line interface.
|
||||
|
||||
See the CLI section of the documentation for more details.
|
||||
@@ -0,0 +1,170 @@
|
||||
# Control Profiles
|
||||
|
||||
A profile is a set of configuration settings.
|
||||
|
||||
Currently, INAV gives you three control profiles. The default control profile is `1`.
|
||||
|
||||
## Changing control profiles
|
||||
### Stick Commands
|
||||
Control profiles can be selected using a GUI or the following stick combinations:
|
||||
|
||||
| Profile # | Throttle | Yaw | Pitch | Roll |
|
||||
| -------- | -------- | ----- | ------ | ------ |
|
||||
| 1 | Down | Left | Middle | Left |
|
||||
| 2 | Down | Left | Up | Middle |
|
||||
| 3 | Down | Left | Middle | Right |
|
||||
|
||||
### CLI
|
||||
The CLI `control_profile` command can also be used to change control profiles:
|
||||
|
||||
```
|
||||
control_profile <index>
|
||||
```
|
||||
|
||||
### Programming (4.0.0 onwards)
|
||||
You can change control profiles using the programming frame work. This allows a lot of flexability in how you change profiles.
|
||||
|
||||
For example, using a simple switch on channel 15.
|
||||
|
||||
[](https://i.imgur.com/SS9CaaO.png)
|
||||
|
||||
Or using the speed to change control profiles. In this example:
|
||||
- when lower than 25 cm/s (basically not flying), control profiles are not effected.
|
||||
- Below 2682 cm/s (60 mph | 97 Km/h) use control profile 1
|
||||
- Above 5364 cm/s (120 mph | 193 Km/h) use control profile 3
|
||||
- Between 2683 and 5364 cm/s, use control profile 2
|
||||
|
||||
[](https://i.imgur.com/WjkuhhW.png)
|
||||
|
||||
> [!NOTE]
|
||||
> From INAV 8.0, the programming framework operator is **Set Control Profile** and the **Flight** Operand is **Active Control Profile**. Pre-INAV 8.0, they were **Set Profile** and **Active Profile** respectively.
|
||||
|
||||
#### Configurator use with control profile changing logic.
|
||||
|
||||
If you have logic conditions that change the profiles. You may find that if you manually change the control profile; using the drop down boxes in the top right of Configurator. That they switch back to a different control profile. This is because the logic conditions are still running in the background. If this is the case, the simplest solutuion is to temporarily disable the switches that trigger the `Set Control Profile` operations. Remember to re-enable these switches after you have made your changes.
|
||||
|
||||
[](https://i.imgur.com/AeH9ll7.png)
|
||||
|
||||
## Profile Contents
|
||||
The values contained within a control profile can be seen by using the CLI `dump control_profile` command.
|
||||
|
||||
e.g
|
||||
```
|
||||
# dump control_profile
|
||||
|
||||
# control_profile
|
||||
control_profile 1
|
||||
|
||||
set mc_p_pitch = 40
|
||||
set mc_i_pitch = 30
|
||||
set mc_d_pitch = 23
|
||||
set mc_cd_pitch = 60
|
||||
set mc_p_roll = 40
|
||||
set mc_i_roll = 30
|
||||
set mc_d_roll = 23
|
||||
set mc_cd_roll = 60
|
||||
set mc_p_yaw = 85
|
||||
set mc_i_yaw = 45
|
||||
set mc_d_yaw = 0
|
||||
set mc_cd_yaw = 60
|
||||
set mc_p_level = 20
|
||||
set mc_i_level = 15
|
||||
set mc_d_level = 75
|
||||
set fw_p_pitch = 5
|
||||
set fw_i_pitch = 7
|
||||
set fw_d_pitch = 0
|
||||
set fw_ff_pitch = 50
|
||||
set fw_p_roll = 5
|
||||
set fw_i_roll = 7
|
||||
set fw_d_roll = 0
|
||||
set fw_ff_roll = 50
|
||||
set fw_p_yaw = 6
|
||||
set fw_i_yaw = 10
|
||||
set fw_d_yaw = 0
|
||||
set fw_ff_yaw = 60
|
||||
set fw_p_level = 20
|
||||
set fw_i_level = 5
|
||||
set fw_d_level = 75
|
||||
set max_angle_inclination_rll = 300
|
||||
set max_angle_inclination_pit = 300
|
||||
set dterm_lpf_hz = 110
|
||||
set dterm_lpf_type = PT2
|
||||
set yaw_lpf_hz = 0
|
||||
set fw_iterm_throw_limit = 165
|
||||
set fw_loiter_direction = RIGHT
|
||||
set fw_reference_airspeed = 1500.000
|
||||
set fw_turn_assist_yaw_gain = 1.000
|
||||
set fw_turn_assist_pitch_gain = 1.000
|
||||
set fw_iterm_limit_stick_position = 0.500
|
||||
set fw_yaw_iterm_freeze_bank_angle = 0
|
||||
set pidsum_limit = 500
|
||||
set pidsum_limit_yaw = 350
|
||||
set iterm_windup = 50
|
||||
set rate_accel_limit_roll_pitch = 0
|
||||
set rate_accel_limit_yaw = 10000
|
||||
set heading_hold_rate_limit = 90
|
||||
set nav_mc_pos_z_p = 50
|
||||
set nav_mc_vel_z_p = 100
|
||||
set nav_mc_vel_z_i = 50
|
||||
set nav_mc_vel_z_d = 10
|
||||
set nav_mc_pos_xy_p = 65
|
||||
set nav_mc_vel_xy_p = 40
|
||||
set nav_mc_vel_xy_i = 15
|
||||
set nav_mc_vel_xy_d = 100
|
||||
set nav_mc_vel_xy_ff = 40
|
||||
set nav_mc_heading_p = 60
|
||||
set nav_mc_vel_xy_dterm_lpf_hz = 2.000
|
||||
set nav_mc_vel_xy_dterm_attenuation = 90
|
||||
set nav_mc_vel_xy_dterm_attenuation_start = 10
|
||||
set nav_mc_vel_xy_dterm_attenuation_end = 60
|
||||
set nav_fw_pos_z_p = 40
|
||||
set nav_fw_pos_z_i = 5
|
||||
set nav_fw_pos_z_d = 10
|
||||
set nav_fw_pos_xy_p = 75
|
||||
set nav_fw_pos_xy_i = 5
|
||||
set nav_fw_pos_xy_d = 8
|
||||
set nav_fw_heading_p = 60
|
||||
set nav_fw_pos_hdg_p = 30
|
||||
set nav_fw_pos_hdg_i = 2
|
||||
set nav_fw_pos_hdg_d = 0
|
||||
set nav_fw_pos_hdg_pidsum_limit = 350
|
||||
set mc_iterm_relax = RP
|
||||
set mc_iterm_relax_cutoff = 15
|
||||
set d_boost_min = 0.500
|
||||
set d_boost_max = 1.250
|
||||
set d_boost_max_at_acceleration = 7500.000
|
||||
set d_boost_gyro_delta_lpf_hz = 80
|
||||
set antigravity_gain = 1.000
|
||||
set antigravity_accelerator = 1.000
|
||||
set antigravity_cutoff_lpf_hz = 15
|
||||
set pid_type = AUTO
|
||||
set mc_cd_lpf_hz = 30
|
||||
set fw_level_pitch_trim = 0.000
|
||||
set smith_predictor_strength = 0.500
|
||||
set smith_predictor_delay = 0.000
|
||||
set smith_predictor_lpf_hz = 50
|
||||
set fw_level_pitch_gain = 5.000
|
||||
set thr_mid = 50
|
||||
set thr_expo = 0
|
||||
set tpa_rate = 0
|
||||
set tpa_breakpoint = 1500
|
||||
set fw_tpa_time_constant = 0
|
||||
set rc_expo = 70
|
||||
set rc_yaw_expo = 20
|
||||
set roll_rate = 20
|
||||
set pitch_rate = 20
|
||||
set yaw_rate = 20
|
||||
set manual_rc_expo = 70
|
||||
set manual_rc_yaw_expo = 20
|
||||
set manual_roll_rate = 100
|
||||
set manual_pitch_rate = 100
|
||||
set manual_yaw_rate = 100
|
||||
set fpv_mix_degrees = 0
|
||||
set rate_dynamics_center_sensitivity = 100
|
||||
set rate_dynamics_end_sensitivity = 100
|
||||
set rate_dynamics_center_correction = 10
|
||||
set rate_dynamics_end_correction = 10
|
||||
set rate_dynamics_center_weight = 0
|
||||
set rate_dynamics_end_weight = 0
|
||||
|
||||
```
|
||||
@@ -0,0 +1,116 @@
|
||||
# Controls
|
||||
|
||||
## Arming
|
||||
|
||||
When armed, the aircraft is ready to fly and the motors will spin when throttle is applied. With multirotors, the motors will spin at a slow speed when armed (this feature may be disabled by setting MOTOR_STOP, but for safety reasons, that is not recommended).
|
||||
|
||||
Arming and disarming is done using a switch, set up on the modes page. (NOTE: Stick arming was removed in INAV 2.2)
|
||||
|
||||
**YAW STICK ARMING OVERRIDE:**
|
||||
Arming is disabled when Nav modes are configured and no GPS lock is available or if a WP mission is loaded but the first WP is farther than the `nav_wp_safe_distance` setting. This Arming block can be bypassed if need be by setting `nav_extra_arming_safety` to `ALLOW_BYPASS` and moving the Yaw stick to the high position when the Arm switch is used. This bypasses GPS Arm blocking pre INAV 4.0.0 and both GPS and "First WP too far" Arm blocking from INAV 4.0.0.
|
||||
|
||||
## Stick Positions
|
||||
|
||||
The three stick positions are:
|
||||
|
||||
|Position | Approx. Channel Input|
|
||||
|----------------|----------------------|
|
||||
|LOW | 1000 |
|
||||
|CENTER | 1500 |
|
||||
|HIGH | 2000 |
|
||||
|
||||
The stick positions are combined to activate different functions:
|
||||
|
||||
| Function | Throttle | Yaw | Pitch | Roll |
|
||||
| ----------------------------- | -------- | ------- | ------ | ------ |
|
||||
| Control Profile 1 | LOW | LOW | CENTER | LOW |
|
||||
| Control Profile 2 | LOW | LOW | HIGH | CENTER |
|
||||
| Control Profile 3 | LOW | LOW | CENTER | HIGH |
|
||||
| Battery profile 1 | HIGH | LOW | CENTER | LOW |
|
||||
| Battery profile 2 | HIGH | LOW | HIGH | CENTER |
|
||||
| Battery profile 3 | HIGH | LOW | CENTER | HIGH |
|
||||
| Calibrate Gyro | LOW | LOW | LOW | CENTER |
|
||||
| Calibrate Acc | HIGH | LOW | LOW | CENTER |
|
||||
| Calibrate Compass/Zero Yaw | HIGH | HIGH | LOW | CENTER |
|
||||
| Trim Acc Left | HIGH | CENTER | CENTER | LOW |
|
||||
| Trim Acc Right | HIGH | CENTER | CENTER | HIGH |
|
||||
| Trim Acc Forwards | HIGH | CENTER | HIGH | CENTER |
|
||||
| Trim Acc Backwards | HIGH | CENTER | LOW | CENTER |
|
||||
| Save current waypoint mission | LOW | CENTER | HIGH | LOW |
|
||||
| Load current waypoint mission | LOW | CENTER | HIGH | HIGH |
|
||||
| Unload waypoint mission | LOW | CENTER | LOW | HIGH |
|
||||
| Increase WP mission index | LOW | CENTER | CENTER | HIGH |
|
||||
| Decrease WP mission index | LOW | CENTER | CENTER | LOW |
|
||||
| Bypass Nav Arm disable | LOW | HIGH | CENTER | CENTER |
|
||||
| Save setting | LOW | LOW | LOW | HIGH |
|
||||
| Enter OSD Menu (CMS) | CENTER | LOW | HIGH | CENTER |
|
||||
| Enter Camera OSD(RuncamDevice)| CENTER | HIGH | CENTER | CENTER |
|
||||
| Exit Camera OSD (RuncamDevice)| CENTER | LOW | CENTER | CENTER |
|
||||
| Confirm - Camera OSD | CENTER | HIGH | CENTER | CENTER |
|
||||
| Navigation - Camera OSD | CENTER | CENTER | * | * |
|
||||
|
||||
For graphical stick position in all transmitter modes, check out [this page](https://www.mrd-rc.com/tutorials-tools-and-testing/inav-flight/inav-stick-commands-for-all-transmitter-modes/).
|
||||

|
||||
|
||||
## Compass Calibration and Yaw Zero Reset
|
||||
|
||||
The stick function `Calibrate Compass/Zero Yaw` provides 2 functions depending on whether or not a compass is available.
|
||||
|
||||
If a compass is available the stick function initiates the compass calibration routine.
|
||||
|
||||
If no compass is available the stick function will reset the current yaw/heading estimate to zero (North) and also set the heading as trusted. This is useful on multirotors, allowing the craft yaw/heading to be correctly aligned to actual North simply by physically pointing the craft North then using the stick function to zero the yaw estimate. Since this also sets the heading as trusted Nav modes reliant on heading will be available immediately after arming without the need to fly fast enough to obtain a valid heading from GPS ground course.
|
||||
|
||||
## Yaw control
|
||||
|
||||
While arming/disarming with sticks, your yaw stick will be moving to extreme values. In order to prevent your craft from trying to yaw during arming/disarming while on the ground, your yaw input will not cause the craft to yaw when the throttle is LOW (i.e. below the `min_check` setting).
|
||||
|
||||
For tricopters, you may want to retain the ability to yaw while on the ground, so that you can verify that your tail servo is working correctly before takeoff. You can do this by setting `tri_unarmed_servo` to `1` on the CLI (this is the default). If you are having issues with your tail rotor contacting the ground during arm/disarm, you can set this to `0` instead. Check this table to decide which setting will suit you:
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th colspan="5">Is yaw control of the tricopter allowed?</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th></th><th colspan="2">Disarmed</th><th colspan="2">Armed</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th></th><th>Throttle low</th><th>Throttle normal</th><th>Throttle low</th><th>Throttle normal</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="2">tri_unarmed_servo = 0</td><td>No</td><td>No</td><td>No</td><td>Yes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>No</td><td>No</td><td>No</td><td>Yes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="2">tri_unarmed_servo = 1</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## Throttle settings and their interaction
|
||||
|
||||
*Terminology. After INAV 2.3, the setting `min_throttle` was replaced with `throttle_idle` which is more appropriate to modern hardware. In this document `min_throttle` may be taken as either the older `min_throttle` value, or the throttle value calculated from the modern `throttle_idle` setting. The way that `throttle_idle` generates a throttle value is described in `Cli.md`.*
|
||||
|
||||
`min_command` -
|
||||
With motor stop enabled this is the command sent to the esc's when the throttle is below min_check or disarmed. With motor stop disabled, this is the command sent only when the copter is disarmed. This must be set well below motors spinning for safety.
|
||||
|
||||
`min_check` -
|
||||
With switch arming mode is in use, lowering your throttle below min_check will result in motors spinning at `throttle_idle` (min_throttle). When using the default stick arming, lowering your throttle below min_check will result in motors spinning at min_throttle and yaw being disabled so that you may arm/disarm. With motor stop enabled, lowering your throttle below min_check will also result in motors off and the esc's being sent min_command. Min_check must be set to a level that is 100% reliably met by the throttle throw. A setting too low may result in a dangerous condition where the copter can’t be disarmed. It is ok to set this below `throttle_idle` (min_throttle) because the FC will automaticly scale the output to the ESCs
|
||||
|
||||
`throttle_idle` (previously `min_throttle)` -
|
||||
Typically set to just above reliable spin up of all motors. Sometimes this is set slightly higher for prop stall prevention during advanced maneuvers or sometimes considerably higher to produce a desired result. When armed with motor stop off, your motors will spin at this command so keep that in mind from a safety stand point.
|
||||
|
||||
`max_check` -
|
||||
Throttle positions above this level will send max_command to the ESCs.
|
||||
|
||||
`max_throttle` -
|
||||
This is the max command to the ESCs from the flight controller.
|
||||
|
||||
In depth videos explaining these terms are available from Joshua Bardwell here:
|
||||
|
||||
https://www.youtube.com/watch?v=WFU3VewGbbA
|
||||
|
||||
https://www.youtube.com/watch?v=YNRl0OTKRGA
|
||||
@@ -0,0 +1,50 @@
|
||||
# DJI compatible MSP DisplayPort OSD (DJI O3 "Canvas Mode")
|
||||
|
||||
INAV 6.0 includes a special mode for MSP DisplayPort that supports DJI's incomplete implementations of MSP DisplayPort. This can be found on products like the DJI O3 Air Unit. INAV 6.1 expands this to include HD canvas sizes from BetaFlight 4.4.
|
||||
|
||||
Different flight controller firmware have different OSD symbols and elements and require different fonts. BetaFlight's font is a single page and supports a maximum of 256 glyphs, INAV's font is currently 2 pages and supports up to 512 different glyphs. DJI's font is single page and based, but not the same as, BetaFlight's font.
|
||||
|
||||
While there is some overlap between the glyphs in DJI and INAV, it is not possible to perform a 1 to 1 mapping for all the them. In cases where there is no suitable glyph in the DJI font, a question mark `?` will be displayed.
|
||||
|
||||
This mode can be enabled by selecting DJI43COMPAT or DJIHDCOMPAT as video format in the OSD tab of the configurator or by typing the following command on the CLI:
|
||||
|
||||
`set osd_video_system = DJI43COMPAT`
|
||||
|
||||
or
|
||||
|
||||
`set osd_video_system = DJIHDCOMPAT`
|
||||
|
||||
## Limitations
|
||||
|
||||
* Canvas size needs to be manually changed to HD on the Display menu in DJI's goggles (you may need a firmware update) and set as DJIHDCOMPAT in the OSD tab of the configurator.
|
||||
* Unsupported Glyphs show up as `?`
|
||||
|
||||
## FAQ
|
||||
|
||||
### I see a lot of `?` on my OSD.
|
||||
|
||||
That is expected. When your INAV OSD widgets use glyphs that don't have a suitable mapping in DJI's font.
|
||||
|
||||
### Does it work with the G2 and Original Air Unit/Vista?
|
||||
|
||||
Yes.
|
||||
|
||||
### Is this a replacement for WTFOS?
|
||||
|
||||
Not exactly. WTFOS is a full implementation of MSP-Displayport for rooted Air Unit/Vista/Googles V2 and actually works much better than DJI compatibility mode. It can use all of INAV's OSD elements as intended. If you have the option of WTFOS or DJI compatability mode. WTFOS is the best option.
|
||||
|
||||
### Can INAV fix DJI's product?
|
||||
|
||||
No. OSD renderinng happens on the googles/air unit side of things. Please ask DJI to fix their incomplete MSP DisplayPort implemenation. You can probably request it in [DJI's forum](https://forum.dji.com/forum.php?mod=forumdisplay&fid=129&filter=typeid&typeid=767). To see what you're missing out on with O3. Check out what WTFOS did with the original system. Not only could the pilots upload the fonts of their choosing (who doesn't want a cool SneakyFPV font on their OSD). But there were no problems supporting and firmware. Plus, there was even an option to save the OSD to a file and overlay that over your DVR video. If you're reading this far. Please recommend to DJI that they fix their product, to at least what was possible with WTFOS.
|
||||
|
||||
### DJI's font now has more symbols, can you update INAV?
|
||||
|
||||
Maybe. If a future version of DJI's font includes more Glyphs that can be mapped into INAV. It is fairly simple to add the mapping. However, the best solution would be full support of MSP DisplayPort by DJI. Then there will never be an issue with missing icons. As the latest INAV font would be able to be uploaded on to the goggles.
|
||||
|
||||
### Can you replace glyph `X` with text `x description`?
|
||||
|
||||
While it might technically be possible to replace some glyphs with text in multiple cells, it will introduce a lot of complexity in the OSD rendering and configuration for something we hope is a temporary workaround.
|
||||
|
||||
### Does DJI support Canvas Mode?
|
||||
|
||||
Actually, no. What DJI calls Canvas Mode is actually MSP DisplayPort and is a character based OSD. Currently, the only true implementaion of Canvas Mode is with FrSKY PixelOSD. This was found on some F722 flight controllers from Matek.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user