Compare commits

...

56 Commits

Author SHA1 Message Date
Ramon Roche 1cf7d75525 fix(ci): lint test files on PRs without breaking push-to-main
The pr-review-poster was flagging `gtest/gtest.h file not found` on any
PR that added or modified a test file, because clang-tidy-diff-18.py
ran against files that weren't in the compilation database. PR #27004
and PR #26233 both hit this. The root cause is that test TUs only
enter compile_commands.json when BUILD_TESTING is ON, which the
historical clang-tidy build does not enable.

This PR fixes both halves of the problem:

1. Add a second make target `px4_sitl_default-clang-test` that configures
   a separate build dir with -DCMAKE_TESTING=ON. Test TUs land in its
   compile_commands.json with resolved gtest/fuzztest include paths.

2. Add an umbrella `clang-ci` target that depends on both
   `px4_sitl_default-clang` and `px4_sitl_default-clang-test` so the PR
   job prepares both build dirs with one make invocation.

3. On PR events the workflow uses `make clang-ci`, installs
   libclang-rt-18-dev (needed so fuzztest's FUZZTEST_FUZZING_MODE flags
   do not fail the abseil try_compile with a misleading "pthreads not
   found" error), and routes the clang-tidy-diff producer at the
   test-enabled build dir.

4. Push-to-main is left entirely alone: same single build dir, same
   `make px4_sitl_default-clang`, same `make clang-tidy`. Test files
   are not in that DB so run-clang-tidy.py keeps ignoring them exactly
   as before. This preserves green main while ~189 pre-existing
   clang-tidy issues in test files remain untouched; fixing those is
   out of scope for this change.

5. Replace the fragile `:!*/test/*` pathspec filter (which missed flat
   `*Test.cpp` files in module roots) with
   `Tools/ci/clang-tidy-diff-filter.py`, which reads the compilation
   database and drops any changed source file that is not a TU.
   Headers always pass through. Production code that happens to use
   test-like names (src/systemcmds/actuator_test, src/drivers/test_ppm,
   etc.) stays analyzed because those are real px4_add_module targets.

Verified in the ghcr.io/px4/px4-dev:v1.17.0-rc2 container and on the
real CI runner:
- cmake configure with CMAKE_TESTING=ON succeeds after installing
  libclang-rt-18-dev (Found Threads: TRUE)
- compile_commands.json grows from 1333 to 1521 TUs
- Modifying HysteresisTest.cpp with a new `const char *p = NULL`
  correctly flags hicpp-use-nullptr and
  clang-diagnostic-unused-variable on the new line, while pre-existing
  issues on other lines of the same file stay suppressed by
  clang-tidy-diff-18.py's line filter ("Suppressed ... 1 due to line
  filter")
- No gtest/gtest.h false positives
- Push-to-main path unchanged, still green

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-04-11 10:03:51 -06:00
Ramon Roche 9dd434f441 ci(compile-ubuntu): replace quick_check with targeted SITL and NuttX builds
Replace make quick_check with two explicit build targets:
px4_sitl_default (validates native SITL toolchain) and
px4_fmu-v5_default (validates NuttX cross-compile toolchain).

quick_check built four targets: px4_sitl_test, px4_fmu-v5_default,
tests, and check_format. The tests and check_format targets are
redundant with checks.yml which already runs them on 8cpu RunsOn
with ccache.

The purpose of this workflow is to validate that PX4 builds from a
fresh ubuntu.sh install on both Ubuntu 22.04 and 24.04, not to run
tests or check formatting. Two targeted builds are sufficient.

px4_fmu-v5_default is kept as the hardware target (same as
quick_check) since it builds with the arm-none-eabi-gcc version
that ubuntu.sh installs on both 22.04 and 24.04.

Expected duration drop from 16-17 min to 6-8 min per matrix entry.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-04-11 09:57:02 -06:00
Ramon Roche 958688f36d fix(fuzzing): revert to old container image
The v1.17.0-rc2 container's clang 18 + cmake 3.28 combination fails
abseil's cmake try_compile tests for C++17 and pthreads. This breaks
the fuzztest build which depends on abseil. Verified locally:

- px4io/px4-dev:v1.16.0-rc2 + apt install clang: cmake configure passes
- ghcr.io/px4/px4-dev:v1.17.0-rc2 (clang 18 pre-installed): cmake
  configure fails with "ABSL_INTERNAL_AT_LEAST_CXX17 - Failed" and
  "Could NOT find Threads"
- apt install clang on v1.17.0-rc2 is a no-op (already installed)

Revert to the old container image which has a working clang+cmake
combination. The apt install clang step (already in the workflow)
installs clang on the old container which doesn't ship it by default.

Remove the explicit fetch-depth: 0 added in the previous fix attempt
since the original workflow used the default depth (1) and it worked.

Fixes #27060

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-04-11 09:45:14 -06:00
Ramon Roche c515f81298 fix(ci): stop pr-review-poster from spamming REQUEST_CHANGES on every push
Branch protection rules block the GITHUB_TOKEN from dismissing reviews
(HTTP 403), so every push added another undismissable REQUEST_CHANGES
review. PR #27004 accumulated 12 identical blocking reviews.

Switch to COMMENT-only reviews. Findings still show inline on the diff
but don't create blocking reviews that require manual maintainer
dismissal. The CI check status (pass/fail) gates merging, not the
review state.

Also enable CMAKE_TESTING=ON in the clang-tidy build so test files get
proper include paths in compile_commands.json. Without this,
clang-tidy-diff runs on test files from the PR diff but can't resolve
gtest headers, producing false positives.

Fixes #27004

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-04-10 20:33:34 -06:00
Ramon Roche c0a45cef70 ci(build-all): MCU-based groups, cache seeders, build infra overhaul (#27050)
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-04-10 18:49:53 -07:00
Ramon Roche d52fbd9707 fix(ci): remove accidentally committed local settings file
.claude/settings.local.json contains user-specific Claude Code
permissions and should never be in the repo. Remove it and add
a .gitignore entry to prevent it from being committed again.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-04-10 15:58:34 -06:00
Julian Oes 5f56589b6d fix(boards): update bootloader binary
The bootloader binary's board IDs were out of sync. This fixes it.
2026-04-10 15:21:41 -06:00
Silvan 557f693246 fix(battery): copy vehicle status states at central place to avoid logic not executed due to previous read
Signed-off-by: Silvan <silvan@auterion.com>
2026-04-10 15:17:45 -06:00
丁勇 ca96106f7d style(PID): remove unnecessary semicolons and ensure proper formatting (#27049) 2026-04-10 14:16:32 -07:00
Julian Oes ed0b9d7d3a fix(boards): remove xc-fly board
This board is not available for purchase online and the author confirmed
that it is "only used for research and educational purposes". Given
there are no docs about it, we should just remove it.
2026-04-10 15:14:56 -06:00
Ramon Roche 0e31dd560d ci(fuzzing): migrate to RunsOn with ccache and bump container
Migrate the fuzzing workflow from GitHub-hosted ubuntu-latest to
RunsOn 4cpu with s3-cache. Bump the container from the stale
px4io/px4-dev:v1.16.0-rc2 to ghcr.io/px4/px4-dev:v1.17.0-rc2.

Wire setup-ccache / save-ccache with cache-key-prefix ccache-sitl
and max-size 300M, sharing the SITL build cache with checks:tests.
Both build px4_sitl_test/px4_sitl_default so the ccache contents
overlap significantly.

Drop the manual apt install clang step since the v1.17.0-rc2
container already ships clang. Replace the git config --global
safe.directory workaround with --system to match the repo convention.
Add runs-on/action@v2 for the S3 cache proxy. Add fetch-depth: 1
since the fuzzer doesn't need git history.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-04-10 09:52:01 -06:00
Ramon Roche ae47d69f50 ci(checks): merge EKF change indicators into tests job
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-04-10 08:42:40 -06:00
PX4BuildBot eed4457d71 docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-04-10 13:39:00 +00:00
Ramon Roche a0e42f2032 ci(workflows): bump all action versions to latest majors
Bump every GitHub Action in the repository to its latest major
version, addressing the upcoming Node.js 20 deprecation. Several
of the old versions (checkout v4, cache v4, setup-node v4,
labeler v5) use the Node 20 runtime which GitHub is deprecating.
The new versions use Node 22.

- actions/checkout v4/v5 to v6
- actions/upload-artifact v4 to v7
- actions/download-artifact v4 to v8
- actions/cache, cache/restore, cache/save v4 to v5
- actions/setup-node v4 to v6
- actions/setup-python v5 to v6
- actions/github-script v7/v8 to v9
- actions/labeler v5 to v6
- peter-evans/find-comment v3 to v4
- dorny/paths-filter v3 to v4
- codecov/codecov-action v4 to v6
- docker/setup-buildx-action v3 to v4
- docker/build-push-action v6 to v7
- tj-actions/changed-files v46 to v47

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-04-10 07:30:50 -06:00
Ramon Roche 0f15eea283 ci(mavros): merge mission+offboard into one workflow, migrate to noetic and Python 3
Consolidate mavros_mission_tests.yml and mavros_offboard_tests.yml into a
single mavros_tests.yml with a matrix strategy. Switch from docker-in-docker
with px4-dev-ros-melodic to a native container using px4-dev-ros-noetic,
enabling ccache and composite actions (setup-ccache, build-gazebo-sitl,
save-ccache). Migrate all five MAVROS Python test files from Python 2 to
Python 3 (remove six/xrange, from __future__ imports, replace px4tools
with pyulog for estimator analysis). Bump git-auto-commit-action from v4
to v7 in ekf_update_change_indicator.yml.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-04-10 00:47:17 -06:00
PX4BuildBot 9eddd0cdbc docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-04-10 04:58:41 +00:00
Ramon Roche 5d5d9e399b ci(workflows): wire ccache and caches across ci (#27036)
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-04-09 21:51:25 -07:00
Ramon Roche a3ad956394 ci(stale): bump operations-per-run and add manual trigger
The stale workflow was hitting its 250 operations-per-run cap every
daily run, causing the "No more operations left! Exiting..." warning
and leaving a growing backlog of stale-labeled items that were never
being closed. GitHub API headroom is plentiful (250 ops uses ~1.6% of
the 15k/hour bucket), so raising to 1500 drains the backlog without
any rate-limit risk.

Also adds workflow_dispatch so maintainers can trigger the workflow
from the Actions tab or via gh workflow run stale.yml.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-04-09 20:40:07 -06:00
PX4BuildBot c72a11fe9f docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-04-09 23:46:48 +00:00
murata,katsutoshi fc53da51fa refactor(bmp388): refactor variable declaration and initialization
Co-authored-by: Jacob Dahl <dahl.jakejacob@gmail.com>
2026-04-09 15:38:17 -08:00
Ramon Roche a49cffb09f ci(checks): trim matrix, ccache tests, modernize python_checks
Port the checks.yml and python_checks.yml improvements from the CI
orchestrator branch (mrpollo/ci_orchestration, PR #26257) without
doing the full T1/T2 split.

checks.yml:
- Drop 5 matrix entries the orchestrator removed:
  tests_coverage, px4_fmu-v2_default stack_check,
  NO_NINJA_BUILD=1 px4_fmu-v5_default,
  NO_NINJA_BUILD=1 px4_sitl_default, px4_sitl_allyes.
- Remove the codecov/codecov-action@v1 step (deprecated, only ran
  for the dropped tests_coverage entry).
- Wire the setup-ccache / save-ccache composite actions around
  make tests (cache-key-prefix ccache-sitl, max-size 300M) so
  repeat runs reuse the SITL build tree. Matches the orchestrator
  basic-tests job 1:1.

python_checks.yml:
- Replace the apt-get install python3 + pip install
  --break-system-packages + hardcoded $HOME/.local/bin paths with
  actions/setup-python@v5 pinned to 3.10 and plain pip install.
- Linters now run from PATH instead of $HOME/.local/bin.

Stacks on top of mrpollo/ci-checkout-hygiene (#27032) which shipped
fail-fast: true, fetch-depth: 1, and the safe.directory step
extraction.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-04-09 16:46:31 -06:00
Ramon Roche 8552465408 ci(workflows): shallow checkout and fail-fast in checks
Port checkout hygiene from the CI orchestrator branch
(mrpollo/ci_orchestration) to current workflows without merging the
orchestrator itself.

- checks.yml: enable fail-fast (99% success rate observed, cancel on
  first failure saves runner time), switch to fetch-depth 1, extract
  safe.directory to its own step
- itcm_check.yml: fetch-depth 1, drop submodules: recursive (the
  Makefile bootstraps submodules as a prerequisite of board targets)
- sitl_tests.yml, ros_integration_tests.yml, mavros_mission_tests.yml,
  mavros_offboard_tests.yml, python_checks.yml: fetch-depth 1

Each change matches the corresponding job in ci-orchestrator.yml on
mrpollo/ci_orchestration 1:1. Workflows that legitimately need history
(clang-tidy, flash_analysis, failsafe_sim, ros_translation_node,
ekf_*_change_indicator, build_all_targets) are left alone.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-04-09 15:57:34 -06:00
Ramon Roche 100d9c97fb ci(workflows): remove nuttx_env_config
Delete the nuttx_env_config workflow. It validated the
PX4_EXTRA_NUTTX_CONFIG env var handling in
platforms/nuttx/NuttX/CMakeLists.txt by building px4_fmu-v5_default
with CONFIG_NSH_LOGIN_PASSWORD injected at configure time.

The CI orchestrator rewrite (mrpollo/ci_orchestration, PR #26257) drops
this workflow entirely. The cmake feature itself remains; only the CI
gate is removed.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-04-09 15:57:12 -06:00
Ramon Roche 5db3060c2a ci(workflows): upgrade SITL and ROS integration runners to 8cpu
Upgrade the RunsOn runner for sitl_tests and ros_integration_tests
from 4cpu-linux-x64 / ubuntu22-full-x64 to 8cpu-linux-x64 /
ubuntu24-full-x64 with extras=s3-cache.

Matches the runner_medium spec used by the sitl-tests and
ros-integration-tests jobs in the CI orchestrator branch
(mrpollo/ci_orchestration). Both jobs are compile-heavy and benefit
from the 2x core count. The ubuntu24 image and s3-cache extras align
with the house style already used by clang-tidy, dev_container,
docs_deploy, docs-orchestrator, and build_deb_package.

No other changes (speed factor unchanged, container images unchanged).

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-04-09 15:57:00 -06:00
Ramon Roche 9e93fd753e ci(pr-review-poster): add line-anchored review poster and migrate clang-tidy (#27028)
* ci(pr-review-poster): add line-anchored review poster and migrate clang-tidy

Adds a generic PR review-comment poster as a sibling of the issue-comment
poster from #27021. Replaces platisd/clang-tidy-pr-comments@v1 in the
Static Analysis workflow with an in-tree, fork-friendly producer + poster
pair so fork PRs get inline clang-tidy annotations on the Files changed
tab without trusting a third-party action with a write token.

Architecture mirrors pr-comment-poster: a producer (clang-tidy.yml) runs
inside the px4-dev container and writes a `pr-review` artifact containing
manifest.json and a baked comments.json. A separate workflow_run-triggered
poster runs on ubuntu-latest with the base-repo write token, validates the
artifact, dismisses any stale matching review, and posts a fresh review
on the target PR. The poster never checks out PR code and only ever reads
two opaque JSON files from the artifact.

Stale-review dismissal is restricted to reviews authored by
github-actions[bot] AND whose body contains the producer's marker. A fork
cannot impersonate the bot login or inject the marker into a human
reviewer's body, so the poster can never dismiss a human review. APPROVE
events are explicitly forbidden so a bot cannot approve a pull request.

To avoid duplicating ~120 lines of HTTP plumbing between the two posters,
the GitHub REST helpers (single-request, pagination, error handling) are
extracted into Tools/ci/_github_helpers.py with a small GitHubClient
class. The existing pr-comment-poster.py is refactored to use it; net
change is roughly -80 lines on that script. The shared module is
sparse-checked-out alongside each poster script and is stdlib only.

The clang-tidy producer reuses MIT-licensed translation logic from
platisd/clang-tidy-pr-comments (generate_review_comments,
reorder_diagnostics, get_diff_line_ranges_per_file and helpers) under a
preserved attribution header. The HTTP layer is rewritten on top of
_github_helpers so the producer does not pull in `requests`. Conversation
resolution (the GraphQL path) is intentionally dropped for v1.

clang-tidy.yml now produces the pr-review artifact in the same job as
the build, so the cross-runner compile_commands.json hand-off and
workspace-path rewriting are no longer needed and the
post_clang_tidy_comments job is removed.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>

* ci(workflows): bump action versions to clear Node 20 deprecation

GitHub has deprecated the Node 20 runtime for Actions as of
September 16, 2026. Bump the pinned action versions in the three poster
workflows to the latest majors, all of which run on Node 24:

  actions/checkout         v4 -> v6
  actions/github-script    v7 -> v8
  actions/upload-artifact  v4 -> v7

No behavior changes on our side: upload-artifact v5/v6/v7 only added an
optional direct-file-upload mode we do not use, and checkout v5/v6 are
runtime-only bumps. The security-invariant comment headers in both
poster workflows are updated to reference the new version so they stay
accurate.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>

* ci(pr-posters): skip job when producer was not a pull_request event

Both poster workflows previously ran on every workflow_run completion of
their listed producers and then silently no-oped inside the script when
the triggering producer run was a push-to-main (or any other non-PR
event). That made the UI ambiguous: the job was always green, never
showed the reason it did nothing, and looked like a failure whenever
someone clicked in looking for the comment that was never there.

Gate the job at the workflow level on
github.event.workflow_run.event == 'pull_request'. Non-PR producer runs
now surface as a clean "Skipped" entry in the run list, which is
self-explanatory and needs no in-script summary plumbing.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>

---------

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-04-09 10:54:29 -07:00
Ramon Roche e8c19a2006 build(cmake): bump lockstep_scheduler minimum to 3.10 (#27017)
CMake 3.27+ warns on cmake_minimum_required(VERSION < 3.10), and CMake
4.x will make it a hard error. Align the lockstep_scheduler subdir with
the root CMakeLists.txt, which is already at 3.10.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-04-09 09:14:15 -08:00
PX4BuildBot 1777d6bcd2 docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-04-09 15:59:01 +00:00
Ramon Roche 9adda29da2 docs(sim): add Try PX4 quick-start and pre-built packages reference (#26957)
Adds documentation for the SITL containers and .deb packages introduced in #26495. The containers are now live on Docker Hub: [`px4io/px4-sitl:latest`](https://hub.docker.com/r/px4io/px4-sitl) and [`px4io/px4-sitl-gazebo:latest`](https://hub.docker.com/r/px4io/px4-sitl-gazebo).

The main addition is a [Try PX4 Simulation](https://docs.px4.io/main/en/dev_setup/try_px4) page that leads with a single `docker run` command and gets someone flying in under a minute. It lives in Getting Started, right after Recommended Hardware/Setup, so it's one of the first things new users see.

The existing `.deb` package reference has been moved from `packaging/px4_sitl_deb.md` to `simulation/px4_sitl.md` and expanded to cover both containers and `.deb` packages on one page. Sections are ordered by how people use them: what's available, install, configure, connect QGC/MAVSDK, connect ROS 2.

Other changes:
- README now has a "Try PX4" section with the docker one-liner above "Build from Source"
- Landing page (`index.md`) reworked to lead with "Try PX4" before "For Developers"
- Toolchain page (`dev_env.md`) gets a tip redirecting simulation-only users to pre-built packages
- `getting_started.md` and `SUMMARY.md` updated with links to the new pages
- Simulation index tip updated to mention containers alongside `.deb` packages

The SIH container image is published as `px4io/px4-sitl` (renamed from `px4io/px4-sitl-sih`) so the default lightweight option carries the simplest name. The Gazebo image remains `px4io/px4-sitl-gazebo`.

Also upgrades all GitHub Actions in the SITL workflow to Node.js 24 compatible versions (`actions/checkout@v6`, `actions/cache@v5`, `actions/upload-artifact@v7`, `actions/download-artifact@v8`, `docker/setup-buildx-action@v4`, `docker/build-push-action@v7`) to fix the Node.js 20 deprecation warning ahead of the June 2026 deadline.

---------

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
Co-authored-by: Hamish Willee <hamishwillee@gmail.com>
2026-04-09 08:51:22 -07:00
Jacob Dahl e34cb8ccb5 docs(maintainers): add Onur Ozkan as Reviewer (#27016)
Co-authored-by: Ramon Roche <mrpollo@gmail.com>
Co-authored-by: Onur Özkan <work@onurozkan.dev>
2026-04-09 08:39:12 -07:00
AdamWuAccton 2557a7441c Add support for DPS310/DPS368 barometers for GA1 board. (#27023) 2026-04-09 10:10:22 -04:00
PX4BuildBot c4abeed3a4 docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-04-09 09:30:09 +00:00
alexcekay 20cad48707 rcS: fine-grained storage settings 2026-04-09 11:22:43 +02:00
Ashwani Sihag 0954e43708 fix(saampixv1_1): use board vendor USB string 2026-04-09 04:47:47 -04:00
Ashwani Sihag b53036c2d7 fix(pr26902): scope cleanup and copyright attribution 2026-04-09 04:47:47 -04:00
Ashwani Sihag fffd434068 fix(boards/saampixv1_1): update bootloader artifact board identity 2026-04-09 04:47:47 -04:00
Ashwani Sihag a74076e539 fix: update stale file path comment in board.h to correct saampixv1_1 path 2026-04-09 04:47:47 -04:00
Ashwani Sihag 00d3c4badc fix: assign unique USB product ID 0x008E for saampixv1_1 board 2026-04-09 04:47:47 -04:00
Ashwani Sihag 397a54abc1 fix: correct USB vendor string to PX4 for saampixv1_1 board 2026-04-09 04:47:47 -04:00
Ashwani Sihag bd5cdd3276 fix: update copyright years to 2020-2026 for all SaamPixV1_1 board files 2026-04-09 04:47:47 -04:00
Ashwani Sihag ff31d5a04f boards: fix reviewer feedback for saampixv1_1 board
- Replace all MINDPX/MINDPXv2/PX4FMU board references with SaamPixV1_1
- Update Airmind Development Team to Saam Drones Development Team in copyright headers
- Update PX4 copyright year range to 2020-2026 on all C/C++ files
- Rename bootloader binary to match board version (v1_1)
- Remove untracked backup files
2026-04-09 04:47:47 -04:00
Ashwani Sihag fc11c207b9 boards: add saampixv1_1 target for firmware release 2026-04-09 04:47:47 -04:00
PX4BuildBot 104e7f2a9c docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-04-09 06:26:14 +00:00
tompsontan a3d51a62a2 boards:x-mav:ap-h743r1:Switch to SPL06 Only Due to Indistinguishable DPS310 and SPL06 IDs. (#26791) 2026-04-09 16:18:56 +10:00
PX4BuildBot d09b3abcf9 docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-04-09 05:56:38 +00:00
Ramon Roche 8c4b703103 ci(pr-comment-poster): add generic PR comment poster and migrate producers
Adds a stand-alone workflow that posts or updates sticky PR comments on
behalf of any analysis workflow, including those triggered by fork PRs.
The poster runs on `workflow_run` in the base repo context, which is the
standard GitHub-sanctioned way to get a write token on events that
originate from untrusted forks without ever checking out fork code.

All validation, GitHub API interaction, and upsert logic lives in
Tools/ci/pr-comment-poster.py (Python 3 stdlib only, two subcommands:
`validate` and `post`). The workflow file itself is a thin orchestrator:
sparse-checkout the script, download the pr-comment artifact via
github-script, unzip, then invoke the script twice. No inline jq, no
inline bash validation, no shell-interpolated marker strings. The
sparse-checkout ensures only Tools/ci/pr-comment-poster.py lands in the
workspace, never the rest of the repo.

Artifact contract: a producer uploads an artifact named exactly
`pr-comment` containing `manifest.json` (with `pr_number`, `marker`, and
optional `mode`) and `body.md`. The script validates the manifest
(positive integer pr_number, printable-ASCII marker bounded 1..200
chars, UTF-8 body under 60000 bytes, mode in an allowlist), finds any
existing comment containing the marker via the comments REST API, and
either edits it in place or creates a new one.

The workflow file header documents six security invariants that any
future change MUST preserve, most importantly: NEVER check out PR code,
NEVER execute anything from the artifact, and treat all artifact
contents as opaque data.

Why a generic poster and not `pull_request_target`: `pull_request_target`
is the tool people reach for first and the one that most often turns
into a supply-chain vulnerability, because it hands a write token to a
workflow that is then tempted to check out the PR head. `workflow_run`
gives the same write token without any check-out temptation, because
the only input is a pre-produced artifact treated as opaque data.

Producer migrations
===================

flash_analysis.yml:
- Drop the fork gate on the `post_pr_comment` job.
- Drop the obsolete TODO pointing at issue #24408 (the fork-comment
  workflow does not error anymore; it just no-ops).
- Keep the existing "comment only if threshold crossed or previous
  comment exists" behaviour verbatim. peter-evans/find-comment@v3
  stays as a read-only probe (forks can read issue comments just fine);
  its body-includes is updated to search for the new marker
  `<!-- pr-comment-poster:flash-analysis -->` instead of the old
  "FLASH Analysis" heading substring.
- Replace the peter-evans/create-or-update-comment@v4 step with two
  new steps that write pr-comment/manifest.json and pr-comment/body.md
  and then upload them as artifact pr-comment. The body markdown is
  byte-for-byte identical to the previous heredoc, with the marker
  prepended as the first line so subsequent runs can find it.
- The threshold-or-existing-comment gate is preserved on both new
  steps. When the gate does not fire no artifact is uploaded and the
  poster no-ops.

docs-orchestrator.yml (link-check job):
- Drop the fork gate on the sticky-comment step.
- Replace marocchino/sticky-pull-request-comment@v2 with two new steps
  that copy logs/filtered-link-check-results.md into pr-comment/body.md,
  write a pr-comment/manifest.json with the marker
  `<!-- pr-comment-poster:docs-link-check -->`, and upload the directory
  as artifact pr-comment.
- The prepare step checks `test -s` on the results file and emits a
  prepared step output; the upload step is gated on that output. In
  practice the existing link-check step always writes a placeholder
  ("No broken links found in changed files.") into the file when empty,
  so the guard is defensive but not load-bearing today.
- Tighten the link-check job's permissions from `pull-requests: write`
  down to `contents: read`; writing PR comments now happens in the
  poster workflow.

The poster's workflows allowlist is seeded with the two active
producers: "FLASH usage analysis" and "Docs - Orchestrator".
clang-tidy (workflow name "Static Analysis") is not in the list because
platisd/clang-tidy-pr-comments posts line-level review comments, a
different REST API from issue comments that the poster script does not
handle. Extending the poster to cover review comments is a follow-up.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-04-08 23:49:56 -06:00
Ramon Roche c9f1d2ab0f build(cmake): silence benign macOS ranlib and ld warnings
POSIX/SITL builds on macOS produce two classes of benign warnings that
clutter output and obscure real issues:

  ranlib: warning: 'lib*.a(foo.o)' has no symbols
  ld: warning: ignoring duplicate libraries: ...

The ranlib warnings come from sources wrapped in #if defined(CONFIG_*)
guards (i2c.cpp, spi.cpp, board_common.c, pab_manifest.c,
px4_log_history.cpp) and dummy.cpp placeholders, which legitimately
compile to empty object files on POSIX. GNU ranlib ignores this;
Apple's warns. The warning is emitted by 'ar qc' (which implicitly
builds a symbol table), not by ranlib itself, so overriding only
ARCHIVE_FINISH is insufficient. Use 'ar qcS' to skip the implicit
symbol table, then let ranlib -no_warning_for_no_symbols build it
quietly via ARCHIVE_FINISH.

The duplicate-library warnings come from CMake intentionally
re-emitting static libraries on the link line to resolve circular
dependencies between px4_layer, px4_work_queue, px4_daemon and
lockstep_scheduler. GNU ld silently dedupes; Apple's ld-prime
(Xcode 15+) warns. Pass -no_warn_duplicate_libraries to the linker.

Both fixes are Darwin-only and have no effect on Linux CI or NuttX
builds.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-04-08 22:45:28 -06:00
Ramon Roche 4c8c9a1e0f ci(clang-tidy): run incrementally on PRs and post inline annotations
Switch the Static Analysis workflow to two modes:
- Push to main: run the full "make clang-tidy" target as before.
- Pull request: build the clang compile database with
  "make px4_sitl_default-clang", then call Tools/ci/run-clang-tidy-pr.py
  (already in-tree) to compute the translation units actually affected
  by the PR diff and run clang-tidy only on that subset. PRs that touch
  no C++ files exit silently; the large majority of PRs will skip the
  slow full analysis entirely.

Replace the inline ccache restore/config/save steps with the composite
actions from .github/actions/setup-ccache and .github/actions/save-ccache,
which use content-hash cache keys (prefix-ref-sha with ref and base_ref
fallbacks), compression, and compiler_check=content. Same 120M cap.

Add a second job, post_clang_tidy_comments, that runs on a GitHub-hosted
runner when the analysis job reports has_findings=true. It downloads the
compile_commands.json artifact produced by the analysis job, rewrites
the AWS RunsOn workspace prefix (/__w/PX4-Autopilot/PX4-Autopilot) to the
GitHub-hosted runner workspace so clang-tidy can chdir into the build
directory, runs clang-tidy-diff-18 to export fixes, and posts inline
review annotations via platisd/clang-tidy-pr-comments@v1.

Annotations are set to request changes (request_changes: true), so a PR
with new clang-tidy findings will be blocked until they are addressed or
waived. suggestions_per_comment is capped at 10. Annotations are gated
to same-repo PRs only; forks skip the annotation job because GITHUB_TOKEN
has no write access there.

The post_clang_tidy_comments job uses if: always() && ... so it runs
whether the analysis job succeeded or failed (findings still need to be
surfaced when the analysis exits non-zero).

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-04-08 22:45:03 -06:00
PX4BuildBot 35391ed8d0 docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-04-09 03:53:39 +00:00
Ramon Roche 48b04b1c81 ci(container): bump px4-dev to ghcr.io/px4/px4-dev:v1.17.0-rc2
Standardize on the GitHub Container Registry copy of px4-dev:v1.17.0-rc2
across workflows still pulling the old dockerhub v1.16.0-rc1 image, and
move the workflows that were already on v1.17.0-beta1 from docker.io to
ghcr.io so the whole repo pulls from one registry at the same version.

Also modernize the "git ownership workaround" in the touched workflows
that still used `git config --global --add safe.directory "$GITHUB_WORKSPACE"`
to the `--system --add safe.directory '*'` form already in use by
clang-tidy, flash_analysis, failsafe_sim, itcm_check, and docs-orchestrator.

Updated workflows:
- checks.yml
- clang-tidy.yml (was on v1.17.0-beta1, now on rc2)
- docs-orchestrator.yml (was on v1.17.0-beta1, two jobs)
- ekf_functional_change_indicator.yml
- ekf_update_change_indicator.yml
- failsafe_sim.yml
- flash_analysis.yml
- itcm_check.yml
- nuttx_env_config.yml

Deliberately out of scope for this PR and deferred to focused follow-ups:
- fetch-depth: 0 to 1 (firmware builds and flash_analysis base-ref
  checkout need git history)
- PX4_SBOM_DISABLE removal in checks.yml (behavioral change)
- fail-fast: false to true (behavioral change)
- codecov-action upgrade

No other workflows touched. compile_ubuntu.yml, ros_integration_tests.yml,
sitl_tests.yml, mavros_*_tests.yml, fuzzing.yml, build_deb_package.yml,
dev_container.yml all use different image families or serve different
purposes and are not part of this sweep.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-04-08 21:46:07 -06:00
PX4BuildBot 3ab7895af7 docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-04-08 23:04:38 +00:00
Ramon Roche 3c5574c051 feat(sih): add propeller model with advance ratio (#26720)
---------

Signed-off-by: romain-chiap <romain.chiap@gmail.com>
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
Co-authored-by: romain-chiap <romain.chiap@gmail.com>
2026-04-08 15:57:17 -07:00
Ramon Roche eb9a76cfaf ci(actions): add composite actions and clang-tidy PR helper
Add four reusable building blocks that upcoming CI optimization PRs will
consume. No existing workflow is modified; these files are dormant until
referenced.

- .github/actions/setup-ccache: restore ~/.ccache with content-hash keys,
  write ccache.conf with compression and content-based compiler check
- .github/actions/save-ccache: print stats and save the cache under the
  primary key produced by setup-ccache
- .github/actions/build-gazebo-sitl: build px4_sitl_default plus the
  Gazebo Classic plugins with ccache stats between stages
- Tools/ci/run-clang-tidy-pr.py: compute the translation units affected
  by a PR diff and invoke Tools/run-clang-tidy.py on that subset only,
  exiting silently when no C++ files changed

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-04-08 13:14:16 -06:00
PX4BuildBot f545f2227d docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-04-08 19:14:03 +00:00
Ramon Roche 4e5c0fac7a docs(maintainers): introduce Code Owner and Reviewer maintainer types (#27010)
Split the maintainer role into two types to make it easier to grow the
bench without asking new contributors to commit to a specific component
up front. Code Owners keep their existing scoped responsibility for a
category, while Reviewers help across the project without ownership of
any specific area. Both are full maintainers, share the @PX4/dev-team
GitHub team, and have the same write access and voting rights.

Rename the Active Maintainers table to Code Owners with no change to
the current roster. Add an empty Reviewers table so future nominations
land in their own PRs. Update the contributor docs to describe the two
types, cover both in the recruitment and onboarding flow, and note the
promotion path from Reviewer to Code Owner.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-04-08 12:06:29 -07:00
Nick fa0618463d fix(uavcan): increase stack size (#27009) 2026-04-08 11:06:02 -08:00
palvarben f025bb42eb fix(boards/nxp/tropic-community): correct LPUART4 mapping (#27008) 2026-04-08 11:04:39 -08:00
168 changed files with 6218 additions and 7562 deletions
+3 -3
View File
@@ -20,7 +20,7 @@ runs:
steps:
- name: Restore ccache
id: ccache-restore
uses: actions/cache/restore@v4
uses: actions/cache/restore@v5
with:
path: ~/.ccache
key: ${{ inputs.ccache-key-prefix }}-${{ github.ref_name }}-${{ github.sha }}
@@ -52,7 +52,7 @@ runs:
run: ccache -s
- name: Save ccache
uses: actions/cache/save@v4
uses: actions/cache/save@v5
if: always()
with:
path: ~/.ccache
@@ -108,7 +108,7 @@ runs:
echo "PASS: gazebo package validation successful"
- name: Upload .deb artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: ${{ inputs.artifact-name }}
path: build/px4_sitl_${{ inputs.target }}/*.deb
@@ -0,0 +1,21 @@
name: Build Gazebo Classic SITL
description: Build PX4 firmware and Gazebo Classic plugins with ccache stats
runs:
using: composite
steps:
- name: Build - PX4 Firmware (SITL)
shell: bash
run: make px4_sitl_default
- name: Cache - Stats after PX4 Firmware
shell: bash
run: ccache -s
- name: Build - Gazebo Classic Plugins
shell: bash
run: make px4_sitl_default sitl_gazebo-classic
- name: Cache - Stats after Gazebo Plugins
shell: bash
run: ccache -s
+22
View File
@@ -0,0 +1,22 @@
name: Save ccache
description: Print ccache stats and save to cache
inputs:
cache-primary-key:
description: Primary cache key from setup-ccache output
required: true
runs:
using: composite
steps:
- name: Cache - Stats
if: always()
shell: bash
run: ccache -s
- name: Cache - Save ccache
if: always()
uses: actions/cache/save@v5
with:
path: ~/.ccache
key: ${{ inputs.cache-primary-key }}
+56
View File
@@ -0,0 +1,56 @@
name: Setup ccache
description: Restore ccache from cache and configure ccache.conf
inputs:
cache-key-prefix:
description: Cache key prefix (e.g. ccache-sitl)
required: true
max-size:
description: Max ccache size (e.g. 300M)
required: false
default: '300M'
base-dir:
description: ccache base_dir value
required: false
default: '${GITHUB_WORKSPACE}'
install-ccache:
description: Install ccache via apt before configuring
required: false
default: 'false'
outputs:
cache-primary-key:
description: Primary cache key (pass to save-ccache)
value: ${{ steps.restore.outputs.cache-primary-key }}
runs:
using: composite
steps:
- name: Cache - Install ccache
if: inputs.install-ccache == 'true'
shell: bash
run: apt-get update && apt-get install -y ccache
- name: Cache - Restore ccache
id: restore
uses: actions/cache/restore@v5
with:
path: ~/.ccache
key: ${{ inputs.cache-key-prefix }}-${{ github.ref_name }}-${{ github.sha }}
restore-keys: |
${{ inputs.cache-key-prefix }}-${{ github.ref_name }}-
${{ inputs.cache-key-prefix }}-${{ github.base_ref || 'main' }}-
${{ inputs.cache-key-prefix }}-
- name: Cache - Configure ccache
shell: bash
run: |
mkdir -p ~/.ccache
echo "base_dir = ${{ inputs.base-dir }}" > ~/.ccache/ccache.conf
echo "compression = true" >> ~/.ccache/ccache.conf
echo "compression_level = 6" >> ~/.ccache/ccache.conf
echo "max_size = ${{ inputs.max-size }}" >> ~/.ccache/ccache.conf
echo "hash_dir = false" >> ~/.ccache/ccache.conf
echo "compiler_check = content" >> ~/.ccache/ccache.conf
ccache -s
ccache -z
+76 -50
View File
@@ -69,32 +69,31 @@ jobs:
runs-on: [runs-on,runner=1cpu-linux-x64,image=ubuntu24-full-x64,"run-id=${{ github.run_id }}",spot=false]
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
seeders: ${{ steps.set-seeders.outputs.seeders }}
timestamp: ${{ steps.set-timestamp.outputs.timestamp }}
branchname: ${{ steps.set-branch.outputs.branchname }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Cache Python pip
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**./Tools/setup/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Update python packaging to avoid canonicalize_version() error
run: |
pip3 install -U packaging
- name: Install Python Dependencies
uses: py-actions/py-dependency-install@v4
with:
path: "./Tools/setup/requirements.txt"
run: pip3 install -U packaging -r ./Tools/setup/requirements.txt
- id: set-matrix
name: Generate Build Matrix
run: echo "matrix=$(./Tools/ci/generate_board_targets_json.py --group)" >> $GITHUB_OUTPUT
- id: set-seeders
name: Generate Seeder Matrix
run: echo "seeders=$(./Tools/ci/generate_board_targets_json.py --group --seeders)" >> $GITHUB_OUTPUT
- id: set-timestamp
name: Save Current Timestamp
run: echo "timestamp=$(date +"%Y%m%d%H%M%S")" >> $GITHUB_OUTPUT
@@ -116,11 +115,52 @@ jobs:
echo "${{ steps.set-branch.outputs.branchname }}"
echo "$(./Tools/ci/generate_board_targets_json.py --group --verbose)"
# ===========================================================================
# CACHE SEEDER JOBS
# ===========================================================================
# Build one representative target per chip family to warm the ccache.
# Matrix jobs fall back to these caches via restore-keys when no
# group-specific cache exists yet. If any seeder fails, the build matrix
# does not start, catching common build errors early.
# ===========================================================================
seed:
name: Seed [${{ matrix.chip_family }}]
needs: group_targets
runs-on: [runs-on,"runner=8cpu-linux-${{ matrix.runner }}","image=ubuntu24-full-${{ matrix.runner }}","run-id=${{ github.run_id }}",spot=false,extras=s3-cache]
strategy:
matrix: ${{ fromJson(needs.group_targets.outputs.seeders) }}
fail-fast: false
container:
image: ${{ matrix.container }}
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: runs-on/action@v2
- uses: actions/checkout@v6
with:
fetch-depth: 1
- name: Configure Git Safe Directory
run: git config --system --add safe.directory '*'
- uses: ./.github/actions/setup-ccache
id: ccache
with:
cache-key-prefix: ccache-${{ matrix.chip_family }}-${{ matrix.runner }}-seeder
max-size: 400M
- name: Build seed target
run: make ${{ matrix.target }}
- uses: ./.github/actions/save-ccache
if: always()
with:
cache-primary-key: ${{ steps.ccache.outputs.cache-primary-key }}
setup:
name: Build [${{ matrix.runner }}][${{ matrix.group }}]
# runs-on: ubuntu-latest
runs-on: [runs-on,"runner=8cpu-linux-${{ matrix.runner }}","image=ubuntu24-full-${{ matrix.runner }}","run-id=${{ github.run_id }}",spot=false]
needs: group_targets
runs-on: [runs-on,"runner=4cpu-linux-${{ matrix.runner }}","image=ubuntu24-full-${{ matrix.runner }}","run-id=${{ github.run_id }}",spot=false,extras=s3-cache]
needs: [group_targets, seed]
if: "!failure() && !cancelled()"
strategy:
matrix: ${{ fromJson(needs.group_targets.outputs.matrix) }}
fail-fast: false
@@ -131,41 +171,35 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: runs-on/action@v2
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Git ownership workaround
- name: Configure Git Safe Directory
run: git config --system --add safe.directory '*'
# ccache key breakdown:
# ccache-<system os>-<system arch>-<builder group>-
# ccache-<linux>-<arm64>-<aarch64-0>-
# ccache-<linux>-<x64>-<nuttx-0>-
- name: Cache Restore from Key
id: cc_restore
uses: actions/cache/restore@v4
- name: Cache - Restore ccache
id: ccache-restore
uses: actions/cache/restore@v5
with:
path: ~/.ccache
key: ${{ format('ccache-{0}-{1}-{2}', runner.os, matrix.runner, matrix.group) }}
key: ccache-${{ matrix.chip_family }}-${{ matrix.runner }}-${{ matrix.group }}-${{ github.ref_name }}-${{ github.sha }}
restore-keys: |
ccache-${{ runner.os }}-${{ matrix.runner }}-${{ matrix.group }}-
ccache-${{ runner.os }}-${{ matrix.runner }}-
ccache-${{ runner.os }}-${{ matrix.runner }}-
ccache-${{ runner.os }}-
ccache-
ccache-${{ matrix.chip_family }}-${{ matrix.runner }}-${{ matrix.group }}-${{ github.ref_name }}-
ccache-${{ matrix.chip_family }}-${{ matrix.runner }}-${{ matrix.group }}-${{ github.base_ref || 'main' }}-
ccache-${{ matrix.chip_family }}-${{ matrix.runner }}-${{ matrix.group }}-
ccache-${{ matrix.chip_family }}-${{ matrix.runner }}-
- name: Cache Config and Stats
- name: Cache - Configure ccache
run: |
mkdir -p ~/.ccache
echo "base_dir = ${GITHUB_WORKSPACE}" > ~/.ccache/ccache.conf
echo "compression = true" >> ~/.ccache/ccache.conf
echo "compression_level = 6" >> ~/.ccache/ccache.conf
echo "max_size = 120M" >> ~/.ccache/ccache.conf
echo "hash_dir = false" >> ~/.ccache/ccache.conf
echo "compiler_check = content" >> ~/.ccache/ccache.conf
ccache -s
ccache -z
mkdir -p ~/.ccache
echo "base_dir = ${GITHUB_WORKSPACE}" > ~/.ccache/ccache.conf
echo "compression = true" >> ~/.ccache/ccache.conf
echo "compression_level = 6" >> ~/.ccache/ccache.conf
echo "max_size = ${{ matrix.cache_size }}" >> ~/.ccache/ccache.conf
echo "hash_dir = false" >> ~/.ccache/ccache.conf
echo "compiler_check = content" >> ~/.ccache/ccache.conf
ccache -s
ccache -z
- name: Building Artifacts for [${{ matrix.targets }}]
run: |
@@ -176,23 +210,15 @@ jobs:
./Tools/ci/package_build_artifacts.sh
- name: Upload Build Artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: px4_${{matrix.group}}_build_artifacts
path: artifacts/
- name: Cache Post Build Stats
if: always()
run: |
ccache -s
ccache -z
- name: Cache Save
if: always()
uses: actions/cache/save@v4
- uses: ./.github/actions/save-ccache
if: success()
with:
path: ~/.ccache
key: ${{ steps.cc_restore.outputs.cache-primary-key }}
cache-primary-key: ${{ steps.ccache-restore.outputs.cache-primary-key }}
# ===========================================================================
# ARTIFACT UPLOAD JOB
@@ -211,7 +237,7 @@ jobs:
uploadlocation: ${{ steps.upload-location.outputs.uploadlocation }}
steps:
- name: Download Artifacts
uses: actions/download-artifact@v4
uses: actions/download-artifact@v8
with:
path: artifacts/
merge-multiple: true
+8 -10
View File
@@ -40,11 +40,10 @@ jobs:
should_push: ${{ steps.push.outputs.should_push }}
steps:
- uses: runs-on/action@v2
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-tags: true
submodules: false
fetch-depth: 0
fetch-tags: true
- name: Set PX4 version
id: version
@@ -93,7 +92,7 @@ jobs:
apt-get update && apt-get install -y git
git config --global --add safe.directory $(realpath .)
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
fetch-tags: true
@@ -103,7 +102,7 @@ jobs:
run: ./Tools/ci/use_aws_apt_mirror.sh
- name: Cache apt packages
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: /var/cache/apt/archives
key: apt-${{ matrix.target }}-${{ matrix.codename }}-${{ matrix.arch }}-${{ hashFiles('Tools/setup/ubuntu.sh') }}
@@ -136,13 +135,12 @@ jobs:
- { image: gazebo, repo: px4-sitl-gazebo, target: default, arch: arm64, runner: arm64, platform: "linux/arm64", dockerfile: Dockerfile.gazebo }
steps:
- uses: runs-on/action@v2
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
submodules: false
fetch-depth: 1
- name: Download Noble .deb artifact
uses: actions/download-artifact@v4
uses: actions/download-artifact@v8
with:
name: px4-sitl-debs-${{ matrix.target }}-noble-${{ matrix.arch }}
path: docker-context
@@ -157,13 +155,13 @@ jobs:
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v4
with:
driver: docker-container
platforms: ${{ matrix.platform }}
- name: Build and push container image
uses: docker/build-push-action@v6
uses: docker/build-push-action@v7
with:
context: docker-context
file: Tools/packaging/${{ matrix.dockerfile }}
+62 -25
View File
@@ -12,51 +12,88 @@ on:
paths-ignore:
- 'docs/**'
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
gate_checks:
name: Gate Checks [${{ matrix.check }}]
runs-on: [runs-on,runner=2cpu-linux-x64,image=ubuntu24-full-x64,"run-id=${{ github.run_id }}",spot=false,extras=s3-cache]
container:
image: px4io/px4-dev:v1.16.0-rc1-258-g0369abd556
image: ghcr.io/px4/px4-dev:v1.17.0-rc2
strategy:
fail-fast: false
fail-fast: true
matrix:
check: [
"check_format",
"check_newlines",
"tests",
"tests_coverage",
"px4_fmu-v2_default stack_check",
"validate_module_configs",
"shellcheck_all",
"NO_NINJA_BUILD=1 px4_fmu-v5_default",
"NO_NINJA_BUILD=1 px4_sitl_default",
"px4_sitl_allyes",
"module_documentation",
]
steps:
- uses: actions/checkout@v4
- uses: runs-on/action@v2
- uses: actions/checkout@v6
with:
fetch-depth: 0
fetch-depth: 1
- name: Configure Git Safe Directory
run: git config --system --add safe.directory '*'
- name: Building [${{ matrix.check }}]
env:
PX4_SBOM_DISABLE: 1
run: |
cd "$GITHUB_WORKSPACE"
git config --global --add safe.directory "$GITHUB_WORKSPACE"
make ${{ matrix.check }}
run: make ${{ matrix.check }}
- name: Uploading Coverage to Codecov.io
if: contains(matrix.check, 'coverage')
uses: codecov/codecov-action@v1
tests:
name: Unit Tests
runs-on: [runs-on,runner=8cpu-linux-x64,image=ubuntu24-full-x64,"run-id=${{ github.run_id }}",spot=false,extras=s3-cache]
container:
image: ghcr.io/px4/px4-dev:v1.17.0-rc2
permissions:
contents: write
env:
GIT_COMMITTER_EMAIL: bot@px4.io
GIT_COMMITTER_NAME: PX4BuildBot
steps:
- uses: runs-on/action@v2
- uses: actions/checkout@v6
with:
token: ${{ secrets.CODECOV_TOKEN }}
flags: unittests
file: coverage/lcov.info
fetch-depth: 1
- name: Configure Git Safe Directory
run: git config --system --add safe.directory '*'
- uses: ./.github/actions/setup-ccache
id: ccache
with:
cache-key-prefix: ccache-sitl
max-size: 300M
- name: Build and run unit tests
env:
PX4_SBOM_DISABLE: 1
run: make tests
- uses: ./.github/actions/save-ccache
if: always()
with:
cache-primary-key: ${{ steps.ccache.outputs.cache-primary-key }}
- name: Auto-update EKF change indication baselines
if: github.event_name == 'push'
uses: stefanzweifel/git-auto-commit-action@v7
with:
file_pattern: 'src/modules/ekf2/test/change_indication/*.csv'
commit_user_name: ${{ env.GIT_COMMITTER_NAME }}
commit_user_email: ${{ env.GIT_COMMITTER_EMAIL }}
commit_message: |
[AUTO COMMIT] update EKF change indication
See .github/workflows/checks.yml for more details
- name: Check for EKF functional changes
run: git diff --exit-code
working-directory: src/modules/ekf2/test/change_indication
+121 -29
View File
@@ -16,14 +16,21 @@ permissions:
contents: read
jobs:
clang_tidy:
# Push-to-main: unchanged historical behavior. Single clang build dir
# with BUILD_TESTING=OFF. `make clang-tidy` builds and analyzes every
# TU in compile_commands.json. Test files are not in the DB and
# therefore never analyzed.
clang_tidy_push:
name: Clang-Tidy
if: github.event_name != 'pull_request'
runs-on: [runs-on, runner=16cpu-linux-x64, "run-id=${{ github.run_id }}", "extras=s3-cache"]
container:
image: px4io/px4-dev:v1.17.0-beta1
image: ghcr.io/px4/px4-dev:v1.17.0-rc2
permissions:
contents: read
steps:
- uses: runs-on/action@v2
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
fetch-tags: true
@@ -31,39 +38,124 @@ jobs:
- name: Configure Git Safe Directory
run: git config --system --add safe.directory '*'
- name: Restore Compiler Cache
id: cc_restore
uses: actions/cache/restore@v4
- uses: ./.github/actions/setup-ccache
id: ccache
with:
path: ~/.ccache
key: ccache-clang-tidy-${{ github.head_ref || github.ref_name }}
restore-keys: |
ccache-clang-tidy-${{ github.head_ref || github.ref_name }}-
ccache-clang-tidy-main-
ccache-clang-tidy-
cache-key-prefix: ccache-clang-tidy
max-size: 150M
- name: Configure Compiler Cache
- name: Build and Analyze - Clang-Tidy
run: make -j$(nproc) clang-tidy
- uses: ./.github/actions/save-ccache
if: always()
with:
cache-primary-key: ${{ steps.ccache.outputs.cache-primary-key }}
# Pull request: diff-based analysis with a second BUILD_TESTING=ON
# build dir so test files in the PR diff can be linted by
# clang-tidy-diff-18.py with resolved gtest/fuzztest includes.
# Results are uploaded as a `pr-review` artifact for the PR Review
# Poster workflow to post as inline comments.
clang_tidy_pr:
name: Clang-Tidy
if: github.event_name == 'pull_request'
runs-on: [runs-on, runner=8cpu-linux-x64, "run-id=${{ github.run_id }}", "extras=s3-cache"]
container:
image: ghcr.io/px4/px4-dev:v1.17.0-rc2
permissions:
contents: read
pull-requests: read
steps:
- uses: runs-on/action@v2
- uses: actions/checkout@v6
with:
fetch-depth: 0
fetch-tags: true
- name: Configure Git Safe Directory
run: git config --system --add safe.directory '*'
- uses: ./.github/actions/setup-ccache
id: ccache
with:
cache-key-prefix: ccache-clang-tidy
max-size: 150M
# fuzztest (enabled via BUILD_TESTING in the -test build dir) pulls
# in abseil via FetchContent, and abseil runs a try_compile with
# fuzztest's -fsanitize=address flags. The px4-dev container ships
# clang but not the clang compiler-rt runtime, so that link fails
# and the configure reports a misleading "pthreads not found".
# libclang-rt-18-dev provides libclang_rt.asan and friends.
- name: Install clang compiler-rt
run: |
mkdir -p ~/.ccache
echo "base_dir = ${GITHUB_WORKSPACE}" > ~/.ccache/ccache.conf
echo "compression = true" >> ~/.ccache/ccache.conf
echo "compression_level = 6" >> ~/.ccache/ccache.conf
echo "max_size = 120M" >> ~/.ccache/ccache.conf
echo "hash_dir = false" >> ~/.ccache/ccache.conf
echo "compiler_check = content" >> ~/.ccache/ccache.conf
ccache -s
ccache -z
apt-get update
apt-get install -y --no-install-recommends libclang-rt-18-dev
# `make clang-ci` prepares both clang build directories:
# - build/px4_sitl_default-clang: full build, BUILD_TESTING=OFF
# (used by run-clang-tidy-pr.py for whole-file analysis of
# changed production code)
# - build/px4_sitl_default-clang-test: configure-only, BUILD_TESTING=ON
# (used by clang-tidy-diff-18.py so test files are in the
# compilation database with resolved gtest/fuzztest includes)
- name: Build clang SITL
run: make -j$(nproc) clang-ci
- name: Run Clang-Tidy Analysis
run: make -j16 clang-tidy
run: python3 Tools/ci/run-clang-tidy-pr.py origin/${{ github.base_ref }}
- name: Compiler Cache Stats
# Produce a `pr-review` artifact for the PR Review Poster workflow
# to consume. clang-tidy-diff-18 emits a unified fixes.yml that
# the producer script translates into line-anchored review comments.
- name: Export clang-tidy fixes for PR review
if: always()
run: ccache -s
run: |
mkdir -p pr-review
# Drop changed C/C++ source files that are not in
# compile_commands.json for the test-enabled build. Files not
# in the DB are platform-specific sources, vendored code, or
# submodule code we don't own. Feeding them to clang-tidy-diff
# produces false positives from unresolved headers.
python3 Tools/ci/clang-tidy-diff-filter.py \
--build-dir build/px4_sitl_default-clang-test \
--base-ref origin/${{ github.base_ref }} \
--out pr-review/diff.patch
if [ -s pr-review/diff.patch ]; then
clang-tidy-diff-18.py -p1 \
-path build/px4_sitl_default-clang-test \
-export-fixes pr-review/fixes.yml \
-j0 < pr-review/diff.patch || true
else
echo "No analyzable files in diff; skipping clang-tidy-diff"
fi
- name: Save Compiler Cache
- name: Build pr-review artifact
if: always()
uses: actions/cache/save@v4
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
python3 Tools/ci/clang-tidy-fixes-to-review.py \
--fixes pr-review/fixes.yml \
--repo-root "$GITHUB_WORKSPACE" \
--repo "$GITHUB_REPOSITORY" \
--pr-number "${{ github.event.pull_request.number }}" \
--commit-sha "${{ github.event.pull_request.head.sha }}" \
--out-dir pr-review \
--event COMMENT
- name: Upload pr-review artifact
if: always()
uses: actions/upload-artifact@v7
with:
path: ~/.ccache
key: ${{ steps.cc_restore.outputs.cache-primary-key }}
name: pr-review
path: |
pr-review/manifest.json
pr-review/comments.json
retention-days: 1
- uses: ./.github/actions/save-ccache
if: always()
with:
cache-primary-key: ${{ steps.ccache.outputs.cache-primary-key }}
+3 -3
View File
@@ -23,7 +23,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
sparse-checkout: Tools/ci
fetch-depth: 1
@@ -56,7 +56,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
sparse-checkout: Tools/ci
fetch-depth: 1
@@ -102,7 +102,7 @@ jobs:
steps:
- name: Checkout
if: env.IS_FORK == 'false'
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
sparse-checkout: Tools/ci
fetch-depth: 1
+36 -36
View File
@@ -19,49 +19,49 @@ concurrency:
jobs:
build:
runs-on: macos-latest
strategy:
matrix:
config: [
px4_fmu-v5_default,
px4_sitl
]
steps:
- name: install Python 3.10
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: "3.10"
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Cache - Restore Homebrew Packages
uses: actions/cache@v5
with:
path: ~/Library/Caches/Homebrew/downloads
key: macos-homebrew-${{ runner.arch }}-${{ hashFiles('Tools/setup/macos.sh') }}
restore-keys: |
macos-homebrew-${{ runner.arch }}-
- name: Cache - Restore pip Packages
uses: actions/cache@v5
with:
path: ~/Library/Caches/pip
key: macos-pip-${{ runner.arch }}-${{ hashFiles('Tools/setup/requirements.txt') }}
restore-keys: |
macos-pip-${{ runner.arch }}-
- name: setup
run: |
./Tools/setup/macos.sh
run: ./Tools/setup/macos.sh
- name: Prepare ccache timestamp
id: ccache_cache_timestamp
shell: cmake -P {0}
run: |
string(TIMESTAMP current_date "%Y-%m-%d-%H;%M;%S" UTC)
file(APPEND "$ENV{GITHUB_OUTPUT}" "timestamp=${current_date}\n")
- name: ccache cache files
uses: actions/cache@v4
- uses: ./.github/actions/setup-ccache
id: ccache
with:
path: ~/.ccache
key: macos_${{matrix.config}}-ccache-${{steps.ccache_cache_timestamp.outputs.timestamp}}
restore-keys: macos_${{matrix.config}}-ccache-
- name: setup ccache
run: |
mkdir -p ~/.ccache
echo "base_dir = ${GITHUB_WORKSPACE}" > ~/.ccache/ccache.conf
echo "compression = true" >> ~/.ccache/ccache.conf
echo "compression_level = 6" >> ~/.ccache/ccache.conf
echo "max_size = 40M" >> ~/.ccache/ccache.conf
echo "hash_dir = false" >> ~/.ccache/ccache.conf
ccache -s
ccache -z
cache-key-prefix: ccache-macos
max-size: 200M
- name: make ${{matrix.config}}
run: |
ccache -z
make ${{matrix.config}}
ccache -s
- name: Build px4_sitl
run: make px4_sitl
- name: Cache - Stats after px4_sitl
run: ccache -s
- name: Build px4_fmu-v5_default
run: make px4_fmu-v5_default
- uses: ./.github/actions/save-ccache
if: always()
with:
cache-primary-key: ${{ steps.ccache.outputs.cache-primary-key }}
+22 -8
View File
@@ -29,12 +29,13 @@ jobs:
fail-fast: false
matrix:
version: ['ubuntu:22.04', 'ubuntu:24.04']
runs-on: [runs-on,runner=4cpu-linux-x64,"image=ubuntu24-full-x64","run-id=${{ github.run_id }}",spot=false]
runs-on: [runs-on,runner=4cpu-linux-x64,"image=ubuntu24-full-x64","run-id=${{ github.run_id }}",spot=false,extras=s3-cache]
container:
image: ${{ matrix.version }}
volumes:
- /github/workspace:/github/workspace
steps:
- uses: runs-on/action@v2
- name: Fix git in container
run: |
@@ -47,15 +48,28 @@ jobs:
apt update && apt install git -y
git config --global --add safe.directory $(realpath .)
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Use AWS regional apt mirror
if: startsWith(runner.name, 'runs-on--')
run: ./Tools/ci/use_aws_apt_mirror.sh
- name: Install Deps, Build, and Make Quick Check
run: |
# we need to install dependencies and build on the same step
# given the stateless nature of docker images
./Tools/setup/ubuntu.sh
make quick_check
- name: Install Deps
run: ./Tools/setup/ubuntu.sh
- uses: ./.github/actions/setup-ccache
id: ccache
with:
cache-key-prefix: ccache-ubuntu-${{ matrix.version }}
max-size: 200M
- name: Build px4_sitl_default
run: make px4_sitl_default
- name: Build px4_fmu-v5_default
run: make px4_fmu-v5_default
- uses: ./.github/actions/save-ccache
if: always()
with:
cache-primary-key: ${{ steps.ccache.outputs.cache-primary-key }}
+6 -9
View File
@@ -51,12 +51,11 @@ jobs:
meta_labels: ${{ steps.meta.outputs.labels }}
steps:
- uses: runs-on/action@v2
- uses: actions/checkout@v5
- uses: actions/checkout@v6
with:
ref: ${{ github.event.inputs.build_ref || github.ref }}
fetch-tags: true
submodules: false
fetch-depth: 0
fetch-tags: true
# If manual dispatch, take the userprovided input
- name: Set PX4 Tag Version
@@ -96,12 +95,11 @@ jobs:
runs-on: [runs-on,"runner=4cpu-linux-${{ matrix.runner }}","image=ubuntu24-full-${{ matrix.runner }}","run-id=${{ github.run_id }}",extras=s3-cache,spot=false]
steps:
- uses: runs-on/action@v2
- uses: actions/checkout@v5
- uses: actions/checkout@v6
with:
ref: ${{ github.event.inputs.build_ref || github.ref }}
fetch-tags: true
submodules: false
fetch-depth: 0
fetch-tags: true
- name: Login to Docker Hub
uses: docker/login-action@v4
@@ -153,12 +151,11 @@ jobs:
(startsWith(github.ref, 'refs/tags/') || (github.event_name == 'workflow_dispatch' && github.event.inputs.deploy_to_registry == 'true'))
steps:
- uses: runs-on/action@v2
- uses: actions/checkout@v5
- uses: actions/checkout@v6
with:
ref: ${{ github.event.inputs.build_ref || github.ref }}
fetch-tags: true
submodules: false
fetch-depth: 0
fetch-tags: true
- name: Login to Docker Hub
uses: docker/login-action@v4
+50 -36
View File
@@ -46,8 +46,8 @@ jobs:
source_changed: ${{ steps.changes.outputs.source }}
docs_changed: ${{ steps.changes.outputs.docs }}
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v3
- uses: actions/checkout@v6
- uses: dorny/paths-filter@v4
id: changes
with:
filters: |
@@ -70,22 +70,19 @@ jobs:
contents: read
runs-on: [runs-on,runner=4cpu-linux-x64,image=ubuntu24-full-x64,"run-id=${{ github.run_id }}",spot=false,extras=s3-cache]
container:
image: px4io/px4-dev:v1.17.0-beta1
image: ghcr.io/px4/px4-dev:v1.17.0-rc2
steps:
- uses: runs-on/action@v1
- name: Checkout
uses: actions/checkout@v4
- uses: runs-on/action@v2
- uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
- name: Git ownership workaround
- name: Configure Git Safe Directory
run: git config --system --add safe.directory '*'
- name: Cache Restore - ccache
id: cache-ccache
uses: actions/cache/restore@v4
uses: actions/cache/restore@v5
with:
path: ~/.ccache
key: ccache-docs-metadata-${{ github.sha }}
@@ -104,7 +101,7 @@ jobs:
CCACHE_DIR: ~/.ccache
- name: Cache Save - ccache
uses: actions/cache/save@v4
uses: actions/cache/save@v5
if: always()
with:
path: ~/.ccache
@@ -116,7 +113,7 @@ jobs:
CCACHE_DIR: ~/.ccache
- name: Upload metadata artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: pr-metadata
path: docs/
@@ -132,12 +129,12 @@ jobs:
contents: write
runs-on: [runs-on,runner=4cpu-linux-x64,image=ubuntu24-full-x64,"run-id=${{ github.run_id }}",spot=false,extras=s3-cache]
container:
image: px4io/px4-dev:v1.17.0-beta1
image: ghcr.io/px4/px4-dev:v1.17.0-rc2
steps:
- uses: runs-on/action@v1
- uses: runs-on/action@v2
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
@@ -148,7 +145,7 @@ jobs:
- name: Cache Restore - ccache
id: cache-ccache
uses: actions/cache/restore@v4
uses: actions/cache/restore@v5
with:
path: ~/.ccache
key: ccache-docs-metadata-${{ github.sha }}
@@ -167,7 +164,7 @@ jobs:
CCACHE_DIR: ~/.ccache
- name: Cache Save - ccache
uses: actions/cache/save@v4
uses: actions/cache/save@v5
if: always()
with:
path: ~/.ccache
@@ -213,25 +210,24 @@ jobs:
if: always() && (github.event_name == 'pull_request')
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
- name: Download metadata artifact
if: needs.pr-metadata-regen.result == 'success'
uses: actions/download-artifact@v4
uses: actions/download-artifact@v8
with:
name: pr-metadata
path: docs/
- name: Get changed doc files
id: changed-files
uses: tj-actions/changed-files@v46.0.5
uses: tj-actions/changed-files@v47
with:
json: true
write_output_files: true
@@ -248,7 +244,7 @@ jobs:
cat ./logs/prFiles.json
- name: Setup Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: 20
@@ -281,15 +277,35 @@ jobs:
> ./logs/link-check-results.md || true
cat ./logs/link-check-results.md
- name: Post PR comment with link check results
if: github.event.pull_request.head.repo.full_name == github.repository
uses: marocchino/sticky-pull-request-comment@v2
- name: Prepare pr-comment artifact
id: prepare-pr-comment
run: |
if [ ! -s ./logs/filtered-link-check-results.md ]; then
echo "No link-check results file; skipping pr-comment artifact."
echo "prepared=false" >> "$GITHUB_OUTPUT"
exit 0
fi
mkdir -p pr-comment
cp ./logs/filtered-link-check-results.md pr-comment/body.md
cat > pr-comment/manifest.json <<EOF
{
"pr_number": ${{ github.event.pull_request.number }},
"marker": "<!-- pr-comment-poster:docs-link-check -->",
"mode": "upsert"
}
EOF
echo "prepared=true" >> "$GITHUB_OUTPUT"
- name: Upload pr-comment artifact
if: steps.prepare-pr-comment.outputs.prepared == 'true'
uses: actions/upload-artifact@v7
with:
header: flaws
path: ./logs/filtered-link-check-results.md
name: pr-comment
path: pr-comment/
retention-days: 1
- name: Upload link check results
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: link-check-results
path: logs/
@@ -313,16 +329,14 @@ jobs:
branchname: ${{ steps.set-branch.outputs.branchname }}
releaseversion: ${{ steps.set-version.outputs.releaseversion }}
steps:
- uses: runs-on/action@v1
- name: Checkout
uses: actions/checkout@v4
- uses: runs-on/action@v2
- uses: actions/checkout@v6
with:
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
- name: Download metadata artifact (PR)
if: github.event_name == 'pull_request' && needs.pr-metadata-regen.result == 'success'
uses: actions/download-artifact@v4
uses: actions/download-artifact@v8
with:
name: pr-metadata
path: docs/
@@ -346,7 +360,7 @@ jobs:
echo "releaseversion=$version" >> $GITHUB_OUTPUT
- name: Setup Node
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: 20
cache: npm
@@ -365,7 +379,7 @@ jobs:
npm run docs:sitemap
- name: Upload artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: px4_docs_build
path: docs/.vitepress/dist/
@@ -387,7 +401,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Download Artifact
uses: actions/download-artifact@v4
uses: actions/download-artifact@v8
with:
name: px4_docs_build
path: ~/_book
+1 -1
View File
@@ -22,7 +22,7 @@ jobs:
lc: [ko, uk, zh-CN] # Target languages https://developer.crowdin.com/language-codes/
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Debug Environment Variables
run: |
echo "CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_DOCS_PROJECT_ID }}"
+1 -1
View File
@@ -24,7 +24,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: crowdin push
uses: crowdin/github-action@v2
with:
+5 -6
View File
@@ -22,12 +22,11 @@ jobs:
build:
runs-on: [runs-on,runner=4cpu-linux-x64,image=ubuntu24-full-x64,"run-id=${{ github.run_id }}",extras=s3-cache,spot=false]
steps:
- uses: runs-on/action@v1
- name: Checkout
uses: actions/checkout@v4
- uses: runs-on/action@v2
- uses: actions/checkout@v6
- name: Setup Node
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: 20
cache: npm
@@ -46,7 +45,7 @@ jobs:
- name: Upload artifact
if: ${{ github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.merged) || github.event_name == 'workflow_dispatch' }}
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: px4_docs_build
path: docs/.vitepress/dist/
@@ -59,7 +58,7 @@ jobs:
steps:
- name: Download Artifact
uses: actions/download-artifact@v4
uses: actions/download-artifact@v8
with:
name: px4_docs_build
path: ~/_book
@@ -1,35 +0,0 @@
name: EKF Change Indicator
on:
pull_request:
branches:
- '**'
paths-ignore:
- 'docs/**'
# If two events are triggered within a short time in the same PR, cancel the run of the oldest event
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
unit_tests:
runs-on: ubuntu-latest
container:
image: px4io/px4-dev:v1.16.0-rc1-258-g0369abd556
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: main test
run: |
cd "$GITHUB_WORKSPACE"
git config --global --add safe.directory "$GITHUB_WORKSPACE"
make tests TESTFILTER=EKF
- name: Check if there is a functional change
run: git diff --exit-code
working-directory: src/modules/ekf2/test/change_indication
@@ -1,54 +0,0 @@
name: EKF Update Change Indicator
on:
push:
paths-ignore:
- 'docs/**'
jobs:
unit_tests:
runs-on: ubuntu-latest
container:
image: px4io/px4-dev:v1.16.0-rc1-258-g0369abd556
env:
GIT_COMMITTER_EMAIL: bot@px4.io
GIT_COMMITTER_NAME: PX4BuildBot
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: main test
run: |
cd "$GITHUB_WORKSPACE"
git config --global --add safe.directory "$GITHUB_WORKSPACE"
make tests TESTFILTER=EKF
- name: Check if there exists diff and save result in variable
id: diff-check
working-directory: src/modules/ekf2/test/change_indication
run: |
if git diff --quiet; then
echo "CHANGE_INDICATED=false" >> $GITHUB_OUTPUT
else
echo "CHANGE_INDICATED=true" >> $GITHUB_OUTPUT
fi
- name: auto-commit any changes to change indication
if: steps.diff-check.outputs.CHANGE_INDICATED == 'true'
uses: stefanzweifel/git-auto-commit-action@v4
with:
file_pattern: 'src/modules/ekf2/test/change_indication/*.csv'
commit_user_name: ${{ env.GIT_COMMITTER_NAME }}
commit_user_email: ${{ env.GIT_COMMITTER_EMAIL }}
commit_message: |
[AUTO COMMIT] update change indication
See .github/workflows/ekf_update_change_indicator.yml for more details
- name: if there is a functional change, fail check
if: steps.diff-check.outputs.CHANGE_INDICATED == 'true'
run: exit 1
+16 -8
View File
@@ -18,7 +18,7 @@ concurrency:
jobs:
build:
runs-on: ubuntu-latest
runs-on: [runs-on,runner=4cpu-linux-x64,image=ubuntu24-full-x64,"run-id=${{ github.run_id }}",spot=false,extras=s3-cache]
defaults:
run:
shell: bash
@@ -29,22 +29,30 @@ jobs:
"failsafe_web",
]
container:
image: px4io/px4-dev:v1.16.0-rc1-258-g0369abd556
image: ghcr.io/px4/px4-dev:v1.17.0-rc2
options: --privileged --ulimit core=-1 --security-opt seccomp=unconfined
steps:
- uses: runs-on/action@v2
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Configure Git Safe Directory
run: git config --system --add safe.directory '*'
- name: Install Node v20.18.0
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: 20.18.0
- uses: actions/checkout@v4
- name: Cache - Restore Emscripten SDK
id: cache-emsdk
uses: actions/cache@v5
with:
fetch-depth: 0
- name: Git ownership workaround
run: git config --system --add safe.directory '*'
path: _emscripten_sdk
key: emsdk-4.0.15
- name: Install empscripten
if: steps.cache-emsdk.outputs.cache-hit != 'true'
run: |
git clone https://github.com/emscripten-core/emsdk.git _emscripten_sdk
cd _emscripten_sdk
+106 -35
View File
@@ -24,9 +24,9 @@ env:
jobs:
analyze_flash:
name: Analyzing ${{ matrix.target }}
runs-on: [runs-on,runner=4cpu-linux-x64,image=ubuntu24-full-x64,"run-id=${{ github.run_id }}",spot=false]
runs-on: [runs-on,runner=4cpu-linux-x64,image=ubuntu24-full-x64,"run-id=${{ github.run_id }}",spot=false,extras=s3-cache]
container:
image: px4io/px4-dev:v1.16.0-rc1-258-g0369abd556
image: ghcr.io/px4/px4-dev:v1.17.0-rc2
strategy:
matrix:
target: [px4_fmu-v5x, px4_fmu-v6x]
@@ -36,25 +36,58 @@ jobs:
px4_fmu-v6x-bloaty-output: ${{ steps.gen-output.outputs.px4_fmu-v6x-bloaty-output }}
px4_fmu-v6x-bloaty-summary-map: ${{ steps.gen-output.outputs.px4_fmu-v6x-bloaty-summary-map }}
steps:
- uses: actions/checkout@v4
- uses: runs-on/action@v2
- uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
- name: Git ownership workaround
- name: Configure Git Safe Directory
run: git config --system --add safe.directory '*'
- name: Cache - Restore ccache (current)
id: cache_current
uses: actions/cache/restore@v5
with:
path: ~/.ccache
key: ccache-flash-${{ matrix.target }}-current-${{ github.ref_name }}-${{ github.sha }}
restore-keys: |
ccache-flash-${{ matrix.target }}-current-${{ github.ref_name }}-
ccache-flash-${{ matrix.target }}-current-
- name: Cache - Configure ccache
run: |
mkdir -p ~/.ccache
echo "base_dir = ${GITHUB_WORKSPACE}" > ~/.ccache/ccache.conf
echo "compression = true" >> ~/.ccache/ccache.conf
echo "compression_level = 6" >> ~/.ccache/ccache.conf
echo "max_size = 200M" >> ~/.ccache/ccache.conf
echo "hash_dir = false" >> ~/.ccache/ccache.conf
echo "compiler_check = content" >> ~/.ccache/ccache.conf
ccache -s
ccache -z
- name: Build Target
run: make ${{ matrix.target }}_flash-analysis
- name: Store the ELF with the change
run: cp ./build/**/*.elf ./with-change.elf
- name: Cache - Stats after Current Build
run: ccache -s
- name: Cache - Save ccache (current)
if: always()
uses: actions/cache/save@v5
with:
path: ~/.ccache
key: ${{ steps.cache_current.outputs.cache-primary-key }}
- name: Clean previous build
run: |
make clean
make distclean
make submodulesclean
ccache -C
- name: If it's a PR checkout the base branch
if: ${{ github.event.pull_request }}
@@ -68,12 +101,34 @@ jobs:
- name: Update submodules
run: make submodulesupdate
- name: Cache - Restore ccache (baseline)
id: cache_baseline
uses: actions/cache/restore@v5
with:
path: ~/.ccache
key: ccache-flash-${{ matrix.target }}-baseline-${{ github.sha }}
restore-keys: |
ccache-flash-${{ matrix.target }}-baseline-
- name: Cache - Reset ccache stats
run: ccache -z
- name: Build
run: make ${{ matrix.target }}_flash-analysis
- name: Store the ELF before the change
run: cp ./build/**/*.elf ./before-change.elf
- name: Cache - Stats after Baseline Build
run: ccache -s
- name: Cache - Save ccache (baseline)
if: always()
uses: actions/cache/save@v5
with:
path: ~/.ccache
key: ${{ steps.cache_baseline.outputs.cache-primary-key }}
- name: bloaty-action
uses: PX4/bloaty-action@v1.0.0
id: bloaty-step
@@ -93,9 +148,6 @@ jobs:
echo '${{ steps.bloaty-step.outputs.bloaty-summary-map }}' >> $GITHUB_OUTPUT
echo "$EOF" >> $GITHUB_OUTPUT
# TODO:
# This part of the workflow is causing errors for forks. We should find a way to fix this and enable it again for forks.
# Track this issue https://github.com/PX4/PX4-Autopilot/issues/24408
post_pr_comment:
name: Publish Results
runs-on: [runs-on,runner=1cpu-linux-x64,image=ubuntu24-full-x64,"run-id=${{ github.run_id }}"]
@@ -105,22 +157,22 @@ jobs:
V5X-SUMMARY-MAP-PERC: ${{ fromJSON(fromJSON(needs.analyze_flash.outputs.px4_fmu-v5x-bloaty-summary-map).vm-percentage) }}
V6X-SUMMARY-MAP-ABS: ${{ fromJSON(fromJSON(needs.analyze_flash.outputs.px4_fmu-v6x-bloaty-summary-map).vm-absolute) }}
V6X-SUMMARY-MAP-PERC: ${{ fromJSON(fromJSON(needs.analyze_flash.outputs.px4_fmu-v6x-bloaty-summary-map).vm-percentage) }}
if: github.event.pull_request && github.event.pull_request.head.repo.full_name == github.repository
if: github.event.pull_request
steps:
- name: Find Comment
uses: peter-evans/find-comment@v3
uses: peter-evans/find-comment@v4
id: fc
with:
issue-number: ${{ github.event.pull_request.number }}
comment-author: 'github-actions[bot]'
body-includes: FLASH Analysis
body-includes: '<!-- pr-comment-poster:flash-analysis -->'
- name: Set Build Time
id: bt
run: |
echo "timestamp=$(date +'%Y-%m-%dT%H:%M:%S')" >> $GITHUB_OUTPUT
- name: Create or update comment
- name: Write pr-comment artifact
# This can't be moved to the job-level conditions, as GH actions don't allow a job-level if condition to access the env.
if: |
steps.fc.outputs.comment-id != '' ||
@@ -128,27 +180,46 @@ jobs:
env.V5X-SUMMARY-MAP-ABS <= fromJSON(env.MIN_FLASH_NEG_DIFF_FOR_COMMENT) ||
env.V6X-SUMMARY-MAP-ABS >= fromJSON(env.MIN_FLASH_POS_DIFF_FOR_COMMENT) ||
env.V6X-SUMMARY-MAP-ABS <= fromJSON(env.MIN_FLASH_NEG_DIFF_FOR_COMMENT)
uses: peter-evans/create-or-update-comment@v4
run: |
mkdir -p pr-comment
cat > pr-comment/manifest.json <<EOF
{
"pr_number": ${{ github.event.pull_request.number }},
"marker": "<!-- pr-comment-poster:flash-analysis -->",
"mode": "upsert"
}
EOF
cat > pr-comment/body.md <<'PR_COMMENT_BODY_EOF'
<!-- pr-comment-poster:flash-analysis -->
## 🔎 FLASH Analysis
<details>
<summary>px4_fmu-v5x [Total VM Diff: ${{ env.V5X-SUMMARY-MAP-ABS }} byte (${{ env.V5X-SUMMARY-MAP-PERC}} %)]</summary>
```
${{ needs.analyze_flash.outputs.px4_fmu-v5x-bloaty-output }}
```
</details>
<details>
<summary>px4_fmu-v6x [Total VM Diff: ${{ env.V6X-SUMMARY-MAP-ABS }} byte (${{ env.V6X-SUMMARY-MAP-PERC }} %)]</summary>
```
${{ needs.analyze_flash.outputs.px4_fmu-v6x-bloaty-output }}
```
</details>
**Updated: _${{ steps.bt.outputs.timestamp }}_**
PR_COMMENT_BODY_EOF
- name: Upload pr-comment artifact
if: |
steps.fc.outputs.comment-id != '' ||
env.V5X-SUMMARY-MAP-ABS >= fromJSON(env.MIN_FLASH_POS_DIFF_FOR_COMMENT) ||
env.V5X-SUMMARY-MAP-ABS <= fromJSON(env.MIN_FLASH_NEG_DIFF_FOR_COMMENT) ||
env.V6X-SUMMARY-MAP-ABS >= fromJSON(env.MIN_FLASH_POS_DIFF_FOR_COMMENT) ||
env.V6X-SUMMARY-MAP-ABS <= fromJSON(env.MIN_FLASH_NEG_DIFF_FOR_COMMENT)
uses: actions/upload-artifact@v7
with:
comment-id: ${{ steps.fc.outputs.comment-id }}
issue-number: ${{ github.event.pull_request.number }}
body: |
## 🔎 FLASH Analysis
<details>
<summary>px4_fmu-v5x [Total VM Diff: ${{ env.V5X-SUMMARY-MAP-ABS }} byte (${{ env.V5X-SUMMARY-MAP-PERC}} %)]</summary>
```
${{ needs.analyze_flash.outputs.px4_fmu-v5x-bloaty-output }}
```
</details>
<details>
<summary>px4_fmu-v6x [Total VM Diff: ${{ env.V6X-SUMMARY-MAP-ABS }} byte (${{ env.V6X-SUMMARY-MAP-PERC }} %)]</summary>
```
${{ needs.analyze_flash.outputs.px4_fmu-v6x-bloaty-output }}
```
</details>
**Updated: _${{ steps.bt.outputs.timestamp }}_**
edit-mode: replace
name: pr-comment
path: pr-comment/
retention-days: 1
+19 -9
View File
@@ -12,19 +12,25 @@ env:
jobs:
Fuzzing:
runs-on: ubuntu-latest
runs-on: [runs-on,runner=4cpu-linux-x64,image=ubuntu24-full-x64,"run-id=${{ github.run_id }}",spot=false,extras=s3-cache]
container:
image: px4io/px4-dev:v1.16.0-rc2-4-gb67c65bfe6
steps:
- name: Install Dependencies
run: |
apt update && apt install -y clang
- uses: runs-on/action@v2
- name: Fix git in Container
run: |
git config --global --add safe.directory $(realpath .)
- uses: actions/checkout@v6
- uses: actions/checkout@v4
- name: Configure Git Safe Directory
run: git config --system --add safe.directory '*'
- name: Install clang
run: apt-get update && apt-get install -y clang
- uses: ./.github/actions/setup-ccache
id: ccache
with:
cache-key-prefix: ccache-sitl
max-size: 300M
- name: Build and Run Fuzz Tests
run: |
@@ -38,7 +44,11 @@ jobs:
./Tools/ci/run_fuzz_tests.sh $fuzz_binary 15m
done
# Create a github issue in case of a failure
- uses: ./.github/actions/save-ccache
if: always()
with:
cache-primary-key: ${{ steps.ccache.outputs.cache-primary-key }}
- name: Create Issue
if: ${{ failure() }}
uses: JasonEtco/create-an-issue@v2
+17 -7
View File
@@ -22,9 +22,9 @@ concurrency:
jobs:
check_itcm:
name: Checking ${{ matrix.target }}
runs-on: [runs-on,runner=4cpu-linux-x64,image=ubuntu24-full-x64,"run-id=${{ github.run_id }}",spot=false]
runs-on: [runs-on,runner=4cpu-linux-x64,image=ubuntu24-full-x64,"run-id=${{ github.run_id }}",spot=false,extras=s3-cache]
container:
image: px4io/px4-dev:v1.16.0-rc1-258-g0369abd556
image: ghcr.io/px4/px4-dev:v1.17.0-rc2
strategy:
fail-fast: false
matrix:
@@ -46,14 +46,19 @@ jobs:
boards/nxp/mr-tropic/nuttx-config/scripts/itcm_functions_includes.ld
boards/nxp/mr-tropic/nuttx-config/scripts/itcm_static_functions.ld
steps:
- uses: actions/checkout@v4
- uses: runs-on/action@v2
- uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
- name: Git ownership workaround
fetch-depth: 1
- name: Configure Git Safe Directory
run: git config --system --add safe.directory '*'
- uses: ./.github/actions/setup-ccache
id: ccache
with:
cache-key-prefix: ccache-itcm-${{ matrix.target }}
max-size: 200M
- name: Build Target
run: make ${{ matrix.target }}
@@ -65,3 +70,8 @@ jobs:
- name: Execute the itcm-check
run: python3 Tools/itcm_check.py --elf-file built.elf --script-files ${{ matrix.scripts }}
- uses: ./.github/actions/save-ccache
if: always()
with:
cache-primary-key: ${{ steps.ccache.outputs.cache-primary-key }}
+1 -1
View File
@@ -16,6 +16,6 @@ jobs:
pull-requests: write
steps:
- uses: actions/labeler@v5
- uses: actions/labeler@v6
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
@@ -1,45 +0,0 @@
name: MAVROS Mission Tests
on:
push:
branches:
- 'main'
paths-ignore:
- 'docs/**'
pull_request:
branches:
- '**'
paths-ignore:
- 'docs/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Build SITL and Run Tests (inside old ROS container)
run: |
docker run --rm \
-v "${GITHUB_WORKSPACE}:/workspace" \
-w /workspace \
px4io/px4-dev-ros-melodic:2021-09-08 \
bash -c '
git config --global --add safe.directory /workspace
PX4_SBOM_DISABLE=1 make px4_sitl_default
PX4_SBOM_DISABLE=1 make px4_sitl_default sitl_gazebo-classic
./test/rostest_px4_run.sh \
mavros_posix_test_mission.test \
mission:=MC_mission_box \
vehicle:=iris
'
@@ -1,44 +0,0 @@
name: MAVROS Offboard Tests
on:
push:
branches:
- 'main'
paths-ignore:
- 'docs/**'
pull_request:
branches:
- '**'
paths-ignore:
- 'docs/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Build SITL and Run Tests (inside old ROS container)
run: |
docker run --rm \
-v "${GITHUB_WORKSPACE}:/workspace" \
-w /workspace \
px4io/px4-dev-ros-melodic:2021-09-08 \
bash -c '
git config --global --add safe.directory /workspace
PX4_SBOM_DISABLE=1 make px4_sitl_default
PX4_SBOM_DISABLE=1 make px4_sitl_default sitl_gazebo-classic
./test/rostest_px4_run.sh \
mavros_posix_tests_offboard_posctl.test \
vehicle:=iris
'
+73
View File
@@ -0,0 +1,73 @@
name: MAVROS Tests
on:
push:
branches:
- 'main'
paths-ignore:
- 'docs/**'
pull_request:
branches:
- '**'
paths-ignore:
- 'docs/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
name: "MAVROS ${{ matrix.config.name }}"
runs-on: [runs-on,runner=4cpu-linux-x64,image=ubuntu24-full-x64,"run-id=${{ github.run_id }}",spot=false,extras=s3-cache]
permissions:
contents: read
container:
image: px4io/px4-dev-ros-noetic:2021-09-08
env:
PX4_SBOM_DISABLE: 1
strategy:
fail-fast: false
matrix:
config:
- {name: "Mission", test_file: "mavros_posix_test_mission.test", params: "mission:=MC_mission_box vehicle:=iris"}
- {name: "Offboard", test_file: "mavros_posix_tests_offboard_posctl.test", params: "vehicle:=iris"}
steps:
- uses: runs-on/action@v2
- uses: actions/checkout@v6
with:
fetch-depth: 1
- name: Configure Git Safe Directory
run: git config --system --add safe.directory '*'
- name: Setup - Install Python Test Dependencies
run: pip3 install -r Tools/setup/requirements.txt
- uses: ./.github/actions/setup-ccache
id: ccache
with:
cache-key-prefix: ccache-sitl-gazebo-classic
max-size: 350M
- uses: ./.github/actions/build-gazebo-sitl
- name: Test - MAVROS ${{ matrix.config.name }}
run: |
./test/rostest_px4_run.sh \
${{ matrix.config.test_file }} \
${{ matrix.config.params }}
timeout-minutes: 10
- uses: ./.github/actions/save-ccache
if: always()
with:
cache-primary-key: ${{ steps.ccache.outputs.cache-primary-key }}
- name: Upload - Failed Test Logs
if: failure()
uses: actions/upload-artifact@v7
with:
name: failed-mavros-${{ matrix.config.name }}-logs.zip
path: |
logs/**/**/**/*.log
logs/**/**/**/*.ulg
-46
View File
@@ -1,46 +0,0 @@
name: Nuttx Target with extra env config
on:
push:
branches:
- 'main'
paths-ignore:
- 'docs/**'
pull_request:
branches:
- '**'
paths-ignore:
- 'docs/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
container:
image: px4io/px4-dev:v1.16.0-rc1-258-g0369abd556
strategy:
matrix:
config:
- px4_fmu-v5_default
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Build PX4 and Run Test [${{ matrix.config }}]
run: |
cd "$GITHUB_WORKSPACE"
git config --global --add safe.directory "$GITHUB_WORKSPACE"
export PX4_EXTRA_NUTTX_CONFIG='CONFIG_NSH_LOGIN_PASSWORD="test";CONFIG_NSH_CONSOLE_LOGIN=y'
echo "PX4_EXTRA_NUTTX_CONFIG: $PX4_EXTRA_NUTTX_CONFIG"
make ${{ matrix.config }} nuttx_context
echo "Check that the config option is set"
grep CONFIG_NSH_LOGIN_PASSWORD build/${{ matrix.config }}/NuttX/nuttx/.config
+155
View File
@@ -0,0 +1,155 @@
name: PR Comment Poster
# Generic PR comment poster. Any analysis workflow (clang-tidy, flash_analysis,
# fuzz coverage, SITL perf, etc.) can produce a `pr-comment` artifact and this
# workflow will post or update a sticky PR comment with its contents. Designed
# so that analysis jobs running on untrusted fork PRs can still get their
# results posted back to the PR.
#
# ==============================================================================
# SECURITY INVARIANTS
# ==============================================================================
# This workflow runs on `workflow_run` which means it runs in the BASE REPO
# context with a WRITE token, even when the triggering PR comes from a fork.
# That is the entire reason it exists, and also the reason it is a loaded
# footgun. Anyone modifying this file MUST preserve the following invariants:
#
# 1. NEVER check out PR code. No `actions/checkout` with a ref. No git clone
# of a fork branch. No execution of scripts from the downloaded artifact.
# The ONLY things read from the artifact are `manifest.json` and `body.md`,
# and both are treated as opaque data (JSON parsed by the poster script
# and markdown posted verbatim via the GitHub API).
#
# 2. `pr_number` is validated to be a positive integer before use.
# `marker` is validated to be printable ASCII only before use. Validation
# happens inside Tools/ci/pr-comment-poster.py which is checked out from
# the base branch, not from the artifact.
#
# 3. The comment body is passed to the GitHub API as a JSON field, never
# interpolated into a shell command string.
#
# 4. This workflow file lives on the default branch. `workflow_run` only
# loads workflow files from the default branch, so a fork cannot modify
# THIS file as part of a PR. The fork CAN cause this workflow to fire
# by triggering a producer workflow that uploads a `pr-comment` artifact.
# That is intended.
#
# 5. The artifact-name filter (`pr-comment`) is the only gate on which
# workflow runs get processed. Any workflow in this repo that uploads
# an artifact named `pr-comment` is trusted to have written the
# manifest and body itself, NOT copied fork-controlled content into
# them. Producer workflows are responsible for that.
#
# 6. `actions/checkout@v6` below uses NO ref (so it pulls the base branch,
# the default-branch commit this workflow file was loaded from) AND uses
# sparse-checkout to materialize ONLY Tools/ci/pr-comment-poster.py and
# its stdlib-only helper module Tools/ci/_github_helpers.py. The rest of
# the repo never touches the workspace. This is safe: the only files the
# job executes are base-repo Python scripts that were reviewed through
# normal code review, never anything from the PR.
#
# ==============================================================================
# ARTIFACT CONTRACT
# ==============================================================================
# Producers upload an artifact named exactly `pr-comment` containing:
#
# manifest.json:
# {
# "pr_number": 12345, // required, int > 0
# "marker": "<!-- pr-comment-poster:flash-analysis -->", // required, printable ASCII
# "mode": "upsert" // optional, default "upsert"
# }
#
# body.md: the markdown content of the comment. Posted verbatim.
#
# The `marker` string is used to find an existing comment to update. It MUST
# be unique per producer (e.g. include the producer name). If no existing
# comment contains the marker, a new one is created. If the marker is found
# in an existing comment, that comment is edited in place.
#
# Producers MUST write `pr_number` from their own workflow context
# (`github.event.pull_request.number`) and MUST NOT read it from any
# fork-controlled source.
on:
workflow_run:
# Producers that may upload a `pr-comment` artifact. When a new producer
# is wired up, add its workflow name here. Runs of workflows not in this
# list will never trigger the poster. Every run of a listed workflow will
# trigger the poster, which will no-op if no `pr-comment` artifact exists.
workflows:
- "FLASH usage analysis"
- "Docs - Orchestrator"
types:
- completed
permissions:
pull-requests: write
actions: read
contents: read
jobs:
post:
name: Post PR Comment
runs-on: ubuntu-latest
# Only run for pull_request producer runs. Push-to-main and other
# non-PR triggers would have no comment to post, and silently no-oping
# inside the script made it look like the poster was broken. Gating at
# the job level surfaces those as a clean "Skipped" in the UI instead.
if: >-
github.event.workflow_run.conclusion != 'cancelled'
&& github.event.workflow_run.event == 'pull_request'
steps:
# Checkout runs first so the poster script is available AND so that
# actions/checkout@v6's default clean step does not delete the artifact
# zip that the next step writes into the workspace. Sparse-checkout
# restricts the materialized tree to just the poster script.
- name: Checkout poster script only
uses: actions/checkout@v6
with:
sparse-checkout: |
Tools/ci/pr-comment-poster.py
Tools/ci/_github_helpers.py
sparse-checkout-cone-mode: false
- name: Download pr-comment artifact
id: download
uses: actions/github-script@v9
with:
script: |
const artifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.payload.workflow_run.id,
});
const match = artifacts.data.artifacts.find(a => a.name === 'pr-comment');
if (!match) {
core.info('No pr-comment artifact on this run; nothing to post.');
core.setOutput('found', 'false');
return;
}
const download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: match.id,
archive_format: 'zip',
});
const fs = require('fs');
fs.writeFileSync('pr-comment.zip', Buffer.from(download.data));
core.setOutput('found', 'true');
- name: Unpack artifact
if: steps.download.outputs.found == 'true'
run: |
mkdir -p pr-comment
unzip -q pr-comment.zip -d pr-comment
- name: Validate artifact
if: steps.download.outputs.found == 'true'
run: python3 Tools/ci/pr-comment-poster.py validate pr-comment
- name: Upsert sticky comment
if: steps.download.outputs.found == 'true'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: python3 Tools/ci/pr-comment-poster.py post pr-comment
+179
View File
@@ -0,0 +1,179 @@
name: PR Review Poster
# Generic PR review-comment poster. Sibling of "PR Comment Poster": that
# workflow posts sticky issue-style comments, this one posts line-anchored
# review comments on the "Files changed" tab. Any analysis workflow that
# wants to flag specific lines can produce a `pr-review` artifact and this
# workflow will dismiss any stale matching review and post a fresh one.
# Designed so analysis jobs running on untrusted fork PRs can still get
# their inline annotations posted back to the PR.
#
# ==============================================================================
# SECURITY INVARIANTS
# ==============================================================================
# This workflow runs on `workflow_run` which means it runs in the BASE REPO
# context with a WRITE token, even when the triggering PR comes from a fork.
# That is the entire reason it exists, and also the reason it is a loaded
# footgun. Anyone modifying this file MUST preserve the following invariants:
#
# 1. NEVER check out PR code. No `actions/checkout` with a ref. No git clone
# of a fork branch. No execution of scripts from the downloaded artifact.
# The ONLY things read from the artifact are `manifest.json` and
# `comments.json`, and both are treated as opaque data (JSON parsed by
# the poster script and the comment fields posted via the GitHub API).
#
# 2. `pr_number` is validated to be a positive integer before use.
# `marker` is validated to be printable ASCII only before use.
# `commit_sha` is validated to be 40 lowercase hex characters.
# `event` is validated against an allowlist of `COMMENT` only.
# `APPROVE` and `REQUEST_CHANGES` are intentionally forbidden:
# bots should not approve PRs, and REQUEST_CHANGES reviews cannot
# be dismissed by the GITHUB_TOKEN under branch protection rules.
# Validation happens inside
# Tools/ci/pr-review-poster.py which is checked out from the base
# branch, not from the artifact.
#
# 3. Comment bodies and the optional summary are passed to the GitHub API
# as JSON fields, never interpolated into a shell command string.
#
# 4. This workflow file lives on the default branch. `workflow_run` only
# loads workflow files from the default branch, so a fork cannot modify
# THIS file as part of a PR. The fork CAN cause this workflow to fire
# by triggering a producer workflow that uploads a `pr-review`
# artifact. That is intended.
#
# 5. The artifact-name filter (`pr-review`) is the only gate on which
# workflow runs get processed. Any workflow in this repo that uploads
# an artifact named `pr-review` is trusted to have written the
# manifest and comments itself, NOT copied fork-controlled content
# into them. Producer workflows are responsible for that.
#
# 6. `actions/checkout@v6` below uses NO ref (so it pulls the base branch,
# the default-branch commit this workflow file was loaded from) AND
# uses sparse-checkout to materialize ONLY
# Tools/ci/pr-review-poster.py and its stdlib-only helper module
# Tools/ci/_github_helpers.py. The rest of the repo never touches the
# workspace. This is safe: the only files the job executes are
# base-repo Python scripts that were reviewed through normal code
# review, never anything from the PR.
#
# 7. Stale-review dismissal is restricted to reviews whose AUTHOR is
# `github-actions[bot]` AND whose body contains the producer's
# marker. A fork PR cannot impersonate the bot login, and cannot
# inject the marker into a human reviewer's body without API
# access. Both filters together prevent the poster from ever
# dismissing a human review.
#
# ==============================================================================
# ARTIFACT CONTRACT
# ==============================================================================
# Producers upload an artifact named exactly `pr-review` containing:
#
# manifest.json:
# {
# "pr_number": 12345, // required, int > 0
# "marker": "<!-- pr-review-poster:clang-tidy -->", // required, printable ASCII
# "event": "COMMENT", // required, "COMMENT" only
# "commit_sha": "0123456789abcdef0123456789abcdef01234567", // required, 40 hex chars
# "summary": "Optional review summary text" // optional
# }
#
# comments.json: JSON array of line-anchored review comment objects:
# [
# {"path": "src/foo.cpp", "line": 42, "side": "RIGHT", "body": "..."},
# {"path": "src/bar.hpp", "start_line": 10, "line": 15,
# "side": "RIGHT", "start_side": "RIGHT", "body": "..."}
# ]
#
# The `marker` string is used to find an existing matching review to
# dismiss before posting a new one. It MUST be unique per producer (e.g.
# include the producer name).
#
# Producers MUST write `pr_number` and `commit_sha` from their own
# workflow context (`github.event.pull_request.number` and
# `github.event.pull_request.head.sha`) and MUST NOT read either from any
# fork-controlled source.
on:
workflow_run:
# Producers that may upload a `pr-review` artifact. When a new
# producer is wired up, add its workflow name here. Runs of workflows
# not in this list will never trigger the poster. Every run of a
# listed workflow will trigger the poster, which will no-op if no
# `pr-review` artifact exists.
workflows:
- "Static Analysis"
types:
- completed
permissions:
pull-requests: write
actions: read
contents: read
jobs:
post:
name: Post PR Review
runs-on: ubuntu-latest
# Only run for pull_request producer runs. Push-to-main and other
# non-PR triggers have no review to post, so gating at the job level
# surfaces those as a clean "Skipped" in the UI instead of a
# silent no-op buried inside the script.
if: >-
github.event.workflow_run.conclusion != 'cancelled'
&& github.event.workflow_run.event == 'pull_request'
steps:
# Checkout runs first so the poster scripts are available AND so
# that actions/checkout@v6's default clean step does not delete the
# artifact zip that the next step writes into the workspace.
# Sparse-checkout restricts the materialized tree to just the
# poster script and its stdlib helper module.
- name: Checkout poster script only
uses: actions/checkout@v6
with:
sparse-checkout: |
Tools/ci/pr-review-poster.py
Tools/ci/_github_helpers.py
sparse-checkout-cone-mode: false
- name: Download pr-review artifact
id: download
uses: actions/github-script@v9
with:
script: |
const artifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.payload.workflow_run.id,
});
const match = artifacts.data.artifacts.find(a => a.name === 'pr-review');
if (!match) {
core.info('No pr-review artifact on this run; nothing to post.');
core.setOutput('found', 'false');
return;
}
const download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: match.id,
archive_format: 'zip',
});
const fs = require('fs');
fs.writeFileSync('pr-review.zip', Buffer.from(download.data));
core.setOutput('found', 'true');
- name: Unpack artifact
if: steps.download.outputs.found == 'true'
run: |
mkdir -p pr-review
unzip -q pr-review.zip -d pr-review
- name: Validate artifact
if: steps.download.outputs.found == 'true'
run: python3 Tools/ci/pr-review-poster.py validate pr-review
- name: Post PR review
if: steps.download.outputs.found == 'true'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: python3 Tools/ci/pr-review-poster.py post pr-review
+11 -8
View File
@@ -14,20 +14,23 @@ on:
jobs:
build:
runs-on: ubuntu-24.04
runs-on: [runs-on,runner=1cpu-linux-x64,image=ubuntu24-full-x64,"run-id=${{ github.run_id }}"]
steps:
- uses: actions/checkout@v4
- uses: runs-on/action@v2
- uses: actions/checkout@v6
with:
fetch-depth: 0
fetch-depth: 1
- name: Install Python3
run: sudo apt-get install python3 python3-setuptools python3-pip -y
- name: Setup Python
uses: actions/setup-python@v6
with:
python-version: "3.10"
- name: Install tools
run: python3 -m pip install mypy types-requests flake8 --break-system-packages
run: pip install mypy types-requests flake8
- name: Check MAVSDK test scripts with mypy
run: $HOME/.local/bin/mypy --strict test/mavsdk_tests/*.py
run: mypy --strict test/mavsdk_tests/*.py
- name: Check MAVSDK test scripts with flake8
run: $HOME/.local/bin/flake8 test/mavsdk_tests/*.py
run: flake8 test/mavsdk_tests/*.py
+38 -43
View File
@@ -23,16 +23,18 @@ concurrency:
jobs:
build:
runs-on: [runs-on,runner=4cpu-linux-x64,image=ubuntu22-full-x64,"run-id=${{ github.run_id }}",spot=false]
runs-on: [runs-on,runner=8cpu-linux-x64,image=ubuntu24-full-x64,"run-id=${{ github.run_id }}",spot=false,extras=s3-cache]
container:
image: px4io/px4-dev-ros2-galactic:2021-09-08
options: --privileged --ulimit core=-1 --security-opt seccomp=unconfined
env:
PX4_SBOM_DISABLE: 1
steps:
- uses: actions/checkout@v4
- uses: runs-on/action@v2
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Git Ownership Workaround
fetch-depth: 1
- name: Configure Git Safe Directory
run: git config --system --add safe.directory '*'
- name: Update ROS Keys
@@ -45,30 +47,21 @@ jobs:
run: |
apt update && apt install -y gazebo11 libgazebo11-dev gstreamer1.0-plugins-bad gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-ugly libgstreamer-plugins-base1.0-dev
- name: Prepare ccache timestamp
id: ccache_cache_timestamp
shell: cmake -P {0}
run: |
string(TIMESTAMP current_date "%Y-%m-%d-%H;%M;%S" UTC)
message("::set-output name=timestamp::${current_date}")
- name: ccache cache files
uses: actions/cache@v4
- uses: ./.github/actions/setup-ccache
id: ccache
with:
path: ~/.ccache
key: ros_integration_tests-${{matrix.config.build_type}}-ccache-${{steps.ccache_cache_timestamp.outputs.timestamp}}
restore-keys: ros_integration_tests-${{matrix.config.build_type}}-ccache-
- name: setup ccache
run: |
mkdir -p ~/.ccache
echo "base_dir = ${GITHUB_WORKSPACE}" > ~/.ccache/ccache.conf
echo "compression = true" >> ~/.ccache/ccache.conf
echo "compression_level = 6" >> ~/.ccache/ccache.conf
echo "max_size = 300M" >> ~/.ccache/ccache.conf
echo "hash_dir = false" >> ~/.ccache/ccache.conf
ccache -s
ccache -z
cache-key-prefix: ccache-ros-integration
max-size: 400M
- name: Get and build micro-xrce-dds-agent
- name: Cache - Restore Micro-XRCE-DDS Agent
id: cache-xrce-agent
uses: actions/cache@v5
with:
path: /opt/Micro-XRCE-DDS-Agent
key: xrce-agent-v2.2.1-fastdds-2.8.2-galactic-2021-09-08
- name: Build - Micro-XRCE-DDS Agent (v2.2.1)
if: steps.cache-xrce-agent.outputs.cache-hit != 'true'
run: |
cd /opt
git clone --recursive https://github.com/eProsima/Micro-XRCE-DDS-Agent.git
@@ -79,10 +72,18 @@ jobs:
cd build
cmake ..
make -j2
- name: ccache post-run micro-xrce-dds-agent
run: ccache -s
- name: Get and build the ros2 interface library
- name: Cache - Restore PX4 ROS 2 Interface Library Workspace
id: cache-px4-ros2-ws
uses: actions/cache@v5
with:
path: /opt/px4_ws
# Bump 'v1' when the cached workspace layout changes in a way
# that is not captured by the message/service hash below.
key: px4-ros2-ws-v1-galactic-2021-09-08-${{ hashFiles('msg/*.msg', 'msg/versioned/*.msg', 'srv/*.srv') }}
- name: Build - PX4 ROS 2 Interface Library
if: steps.cache-px4-ros2-ws.outputs.cache-hit != 'true'
shell: bash
run: |
PX4_DIR="$(pwd)"
@@ -108,19 +109,8 @@ jobs:
"${PX4_DIR}/Tools/copy_to_ros_ws.sh" "$(pwd)"
rm -rf src/translation_node src/px4_msgs_old
colcon build --symlink-install
- name: ccache post-run ros workspace
run: ccache -s
- name: Build PX4
env:
PX4_SBOM_DISABLE: 1
run: make px4_sitl_default
- name: ccache post-run px4/firmware
run: ccache -s
- name: Build SITL Gazebo
run: make px4_sitl_default sitl_gazebo-classic
- name: ccache post-run sitl_gazebo-classic
run: ccache -s
- uses: ./.github/actions/build-gazebo-sitl
- name: Core dump settings
run: |
@@ -135,9 +125,14 @@ jobs:
test/ros_test_runner.py --verbose --model iris --force-color
timeout-minutes: 45
- uses: ./.github/actions/save-ccache
if: always()
with:
cache-primary-key: ${{ steps.ccache.outputs.cache-primary-key }}
- name: Upload failed logs
if: failure()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: failed-logs.zip
path: |
+29 -16
View File
@@ -10,6 +10,9 @@ on:
- '**'
paths-ignore:
- 'docs/**'
permissions:
contents: read
defaults:
run:
shell: bash
@@ -20,8 +23,8 @@ concurrency:
jobs:
build_and_test:
name: Build and test
runs-on: [runs-on,runner=4cpu-linux-x64,image=ubuntu24-full-x64,"run-id=${{ github.run_id }}",spot=false]
name: Build and test [${{ matrix.config.ros_version }}]
runs-on: [runs-on,runner=4cpu-linux-x64,image=ubuntu24-full-x64,"run-id=${{ github.run_id }}",spot=false,extras=s3-cache]
strategy:
fail-fast: false
matrix:
@@ -29,33 +32,43 @@ jobs:
- {ros_version: "humble", ubuntu: "jammy"}
- {ros_version: "jazzy", ubuntu: "noble"}
container:
image: rostooling/setup-ros-docker:ubuntu-${{ matrix.config.ubuntu }}-latest
image: ros:${{ matrix.config.ros_version }}-ros-base-${{ matrix.config.ubuntu }}
steps:
- name: Setup ROS 2 (${{ matrix.config.ros_version }})
uses: ros-tooling/setup-ros@v0.7
with:
required-ros-distributions: ${{ matrix.config.ros_version }}
- name: Checkout repository
uses: actions/checkout@v4
- uses: runs-on/action@v2
- uses: actions/checkout@v6
with:
fetch-depth: 0
# Workaround for https://github.com/actions/runner/issues/2033
- name: ownership workaround
- name: Configure Git Safe Directory
run: git config --system --add safe.directory '*'
- uses: ./.github/actions/setup-ccache
id: ccache
with:
cache-key-prefix: ccache-ros-translation-${{ matrix.config.ros_version }}
max-size: 150M
base-dir: /ros_ws
install-ccache: 'true'
- name: Check .msg file versioning
if: github.event_name == 'pull_request'
run: |
./Tools/ci/check_msg_versioning.sh ${{ github.event.pull_request.base.sha }} ${{github.event.pull_request.head.sha}}
- name: Build and test
- name: Build - Translation Node
run: |
ros_ws=/ros_ws
mkdir -p $ros_ws/src
./Tools/copy_to_ros_ws.sh $ros_ws
cd $ros_ws
source /opt/ros/${{ matrix.config.ros_version }}/setup.sh
colcon build --cmake-args -DCMAKE_BUILD_TYPE=Release --symlink-install --event-handlers=console_cohesion+
source ./install/setup.sh
./build/translation_node/translation_node_unit_tests
colcon build --cmake-args -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_C_COMPILER_LAUNCHER=ccache --symlink-install --event-handlers=console_cohesion+
- name: Test - Translation Node Unit Tests
run: |
source /ros_ws/install/setup.sh
/ros_ws/build/translation_node/translation_node_unit_tests
- uses: ./.github/actions/save-ccache
if: always()
with:
cache-primary-key: ${{ steps.ccache.outputs.cache-primary-key }}
+1 -1
View File
@@ -30,7 +30,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 1
submodules: false
+2 -2
View File
@@ -20,7 +20,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
ref: ${{ inputs.branch || github.ref }}
fetch-depth: 1
@@ -51,7 +51,7 @@ jobs:
- name: Create issue if problems found
if: steps.check.outputs.has_issues == 'true'
uses: actions/github-script@v7
uses: actions/github-script@v9
with:
script: |
const fs = require('fs');
+20 -49
View File
@@ -24,7 +24,7 @@ concurrency:
jobs:
build:
name: Testing PX4 ${{ matrix.config.model }}
runs-on: [runs-on,runner=4cpu-linux-x64,image=ubuntu22-full-x64,"run-id=${{ github.run_id }}",spot=false]
runs-on: [runs-on,runner=8cpu-linux-x64,image=ubuntu24-full-x64,"run-id=${{ github.run_id }}",spot=false,extras=s3-cache]
container:
image: px4io/px4-dev-simulation-focal:2021-09-08
options: --privileged --ulimit core=-1 --security-opt seccomp=unconfined
@@ -37,53 +37,25 @@ jobs:
# transitions). Re-enable once the test infrastructure is stabilized.
# - {model: "tailsitter" , latitude: "29.660316", longitude: "-82.316658", altitude: "30", build_type: "RelWithDebInfo" } # Florida
# - {model: "standard_vtol", latitude: "47.397742", longitude: "8.545594", altitude: "488", build_type: "Coverage" } # Zurich
env:
PX4_CMAKE_BUILD_TYPE: ${{ matrix.config.build_type }}
PX4_SBOM_DISABLE: 1
steps:
- uses: actions/checkout@v4
- uses: runs-on/action@v2
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Git Ownership Workaround
fetch-depth: 1
- name: Configure Git Safe Directory
run: git config --system --add safe.directory '*'
- id: set-timestamp
name: Set timestamp for cache
run: echo "::set-output name=timestamp::$(date +"%Y%m%d%H%M%S")"
- name: Cache Key Config
uses: actions/cache@v4
- uses: ./.github/actions/setup-ccache
id: ccache
with:
path: ~/.ccache
key: sitl-ccache-${{ steps.set-timestamp.outputs.timestamp }}
restore-keys: sitl-ccache-${{ steps.set-timestamp.outputs.timestamp }}
cache-key-prefix: ccache-sitl-gazebo-classic
max-size: 350M
- name: Cache Conf Config
run: |
mkdir -p ~/.ccache
echo "base_dir = ${GITHUB_WORKSPACE}" > ~/.ccache/ccache.conf
echo "compression = true" >> ~/.ccache/ccache.conf
echo "compression_level = 6" >> ~/.ccache/ccache.conf
echo "max_size = 120M" >> ~/.ccache/ccache.conf
echo "hash_dir = false" >> ~/.ccache/ccache.conf
ccache -s
ccache -z
- name: Build PX4
env:
PX4_CMAKE_BUILD_TYPE: ${{matrix.config.build_type}}
PX4_SBOM_DISABLE: 1
run: make px4_sitl_default
- name: Cache Post-Run [px4_sitl_default]
run: ccache -s
- name: Build SITL Gazebo
env:
PX4_CMAKE_BUILD_TYPE: ${{matrix.config.build_type}}
run: make px4_sitl_default sitl_gazebo-classic
- name: Cache Post-Run [sitl_gazebo-classic]
run: ccache -s
- uses: ./.github/actions/build-gazebo-sitl
- name: Download MAVSDK
run: wget "https://github.com/mavlink/MAVSDK/releases/download/v$(cat test/mavsdk_tests/MAVSDK_VERSION)/libmavsdk-dev_$(cat test/mavsdk_tests/MAVSDK_VERSION)_ubuntu20.04_amd64.deb"
@@ -96,19 +68,19 @@ jobs:
PX4_HOME_LAT: ${{matrix.config.latitude}}
PX4_HOME_LON: ${{matrix.config.longitude}}
PX4_HOME_ALT: ${{matrix.config.altitude}}
PX4_CMAKE_BUILD_TYPE: ${{matrix.config.build_type}}
run: |
export
ulimit -a
- name: Build PX4 / MAVSDK tests
env:
PX4_CMAKE_BUILD_TYPE: ${{matrix.config.build_type}}
DONT_RUN: 1
run: make px4_sitl_default sitl_gazebo-classic mavsdk_tests
- name: Cache Post-Run [px4_sitl_default sitl_gazebo-classic mavsdk_tests]
run: ccache -s
- uses: ./.github/actions/save-ccache
if: always()
with:
cache-primary-key: ${{ steps.ccache.outputs.cache-primary-key }}
- name: Core Dump Settings
run: |
@@ -120,13 +92,12 @@ jobs:
PX4_HOME_LAT: ${{matrix.config.latitude}}
PX4_HOME_LON: ${{matrix.config.longitude}}
PX4_HOME_ALT: ${{matrix.config.altitude}}
PX4_CMAKE_BUILD_TYPE: ${{matrix.config.build_type}}
run: test/mavsdk_tests/mavsdk_test_runner.py --speed-factor 10 --abort-early --model ${{matrix.config.model}} test/mavsdk_tests/configs/sitl.json --verbose --force-color
timeout-minutes: 45
- name: Upload failed logs
if: failure()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: failed-${{matrix.config.model}}-logs.zip
path: |
@@ -140,7 +111,7 @@ jobs:
- name: Upload PX4 coredump
if: failure() && ${{ hashFiles('px4.core') != '' }}
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: coredump
path: px4.core
@@ -157,7 +128,7 @@ jobs:
- name: Upload Coverage Information to Codecov
if: contains(matrix.config.build_type, 'Coverage')
uses: codecov/codecov-action@v4
uses: codecov/codecov-action@v6
with:
token: ${{ secrets.CODECOV_TOKEN }}
flags: mavsdk
+2 -1
View File
@@ -2,6 +2,7 @@ name: 'Handle stale issues and PRs'
on:
schedule:
- cron: '30 1 * * *'
workflow_dispatch:
jobs:
stale:
@@ -9,7 +10,7 @@ jobs:
steps:
- uses: actions/stale@v10
with:
operations-per-run: 250
operations-per-run: 1500
days-before-stale: 90
days-before-close: 30
stale-issue-label: 'stale'
+1 -1
View File
@@ -20,7 +20,7 @@ jobs:
runs-on: [runs-on,runner=4cpu-linux-x64,image=ubuntu22-full-x64,"run-id=${{ github.run_id }}",spot=false]
steps:
- name: Checkout PX4 repo
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Setup git credentials
run: |
@@ -22,7 +22,7 @@ jobs:
TAG_NAME: ${{ github.event_name == 'workflow_dispatch' && inputs.tag_name || github.ref_name }}
steps:
- name: Checkout PX4 repo
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
fetch-depth: 0
fetch-tags: true
+3
View File
@@ -115,3 +115,6 @@ _emscripten_sdk/
# virtual Python environment
.venv
# Claude Code local settings
.claude/settings.local.json
+22
View File
@@ -229,6 +229,28 @@ endif()
#
project(px4 CXX C ASM)
# Silence Apple ranlib "has no symbols" warnings. Several PX4 sources are
# wrapped in #if defined(CONFIG_*) guards (e.g. platforms/common/i2c.cpp,
# spi.cpp, board_common.c, pab_manifest.c, px4_log_history.cpp) and some
# libraries carry a dummy.cpp placeholder, all of which legitimately produce
# empty object files on POSIX/SITL. GNU ranlib ignores this; Apple's warns.
#
# The warning is actually emitted by `ar qc` (which implicitly builds a symbol
# table), not by the standalone ranlib call. So we use `ar qcS` to skip the
# implicit symbol table, then let CMAKE_*_ARCHIVE_FINISH run ranlib with the
# -no_warning_for_no_symbols flag to add it quietly.
if(APPLE)
set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> qcS <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> qcS <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_ASM_ARCHIVE_CREATE "<CMAKE_AR> qcS <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_C_ARCHIVE_APPEND "<CMAKE_AR> qS <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_CXX_ARCHIVE_APPEND "<CMAKE_AR> qS <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_ASM_ARCHIVE_APPEND "<CMAKE_AR> qS <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_C_ARCHIVE_FINISH "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>")
set(CMAKE_CXX_ARCHIVE_FINISH "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>")
set(CMAKE_ASM_ARCHIVE_FINISH "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>")
endif()
# CMake build type (Debug Release RelWithDebInfo MinSizeRel Coverage)
if(NOT CMAKE_BUILD_TYPE)
if(${PX4_PLATFORM} STREQUAL "nuttx")
+13 -2
View File
@@ -1,9 +1,11 @@
Maintainers
===========
See [the documentation on Maintainers](https://docs.px4.io/main/en/contribute/maintainers.html) to learn about the role of the maintainers and the process to become one.
PX4 is maintained by a group of contributors trusted to steward the project. All maintainers listed below are members of the @PX4/dev-team, have write access, and participate in maintainer decisions. We recognize two types: **Code Owners**, responsible for specific components, and **Reviewers**, who help across the project without a fixed component.
**Active Maintainers**
See [the documentation on Maintainers](https://docs.px4.io/main/en/contribute/maintainers) to learn about the role of the maintainers and the process to become one.
**Code Owners**
| Name | Sector | GitHub | Chat | email
|-------------------------|--------|--------|------|----------------
@@ -23,6 +25,15 @@ See [the documentation on Maintainers](https://docs.px4.io/main/en/contribute/ma
| Jacob Dahl | Simulation | [@dakejahl](https://github.com/dakejahl) | dakejahl | <dahl.jakejacob@gmail.com>
**Reviewers**
Reviewers help maintain PX4 across the project without ownership of a specific component.
| Name | GitHub | Chat | email
|------|--------|------|----------------------
| Onur Ozkan | [@onur-ozkan](https://github.com/onur-ozkan) | onur_ozkan0126 | <onur@orkavian.com>
**Documentation Maintainers**
| Name | GitHub | Chat | email
+21 -1
View File
@@ -494,7 +494,7 @@ python_coverage:
# static analyzers (scan-build, clang-tidy, cppcheck)
# --------------------------------------------------------------------
.PHONY: scan-build px4_sitl_default-clang clang-tidy clang-tidy-fix
.PHONY: scan-build px4_sitl_default-clang px4_sitl_default-clang-test clang-ci clang-tidy clang-tidy-fix
.PHONY: cppcheck shellcheck_all validate_module_configs
scan-build:
@@ -512,6 +512,26 @@ px4_sitl_default-clang:
@cd "$(SRC_DIR)"/build/px4_sitl_default-clang && cmake "$(SRC_DIR)" $(CMAKE_ARGS) -G"$(PX4_CMAKE_GENERATOR)" -DCONFIG=px4_sitl_default -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
@$(PX4_MAKE) -C "$(SRC_DIR)"/build/px4_sitl_default-clang
# Clang SITL configure with BUILD_TESTING=ON so test files land in
# compile_commands.json with resolved gtest/fuzztest includes. Used by CI
# to produce a compilation database for diff-based clang-tidy that can
# lint test files. Configure only: we don't build the test binaries here,
# just generate the database.
px4_sitl_default-clang-test:
@mkdir -p "$(SRC_DIR)"/build/px4_sitl_default-clang-test
@cd "$(SRC_DIR)"/build/px4_sitl_default-clang-test && cmake "$(SRC_DIR)" $(CMAKE_ARGS) -G"$(PX4_CMAKE_GENERATOR)" -DCONFIG=px4_sitl_default -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_TESTING=ON
# CI-oriented target that prepares both clang build directories used by
# the Static Analysis workflow:
# - px4_sitl_default-clang: full build, BUILD_TESTING=OFF.
# Used by `make clang-tidy` (push-to-main) and run-clang-tidy-pr.py.
# - px4_sitl_default-clang-test: configure-only, BUILD_TESTING=ON.
# Used by clang-tidy-diff-18.py so test files are in the
# compilation database with resolved gtest/fuzztest includes.
# Running one target ensures both dirs exist before any clang-tidy
# variant runs, and keeps the workflow free of raw cmake invocations.
clang-ci: px4_sitl_default-clang px4_sitl_default-clang-test
# Paths to exclude from clang-tidy (auto-generated from .gitmodules + manual additions):
# - All submodules (external code we consume, not edit)
# - Test code (allowed looser style)
+11 -1
View File
@@ -70,7 +70,17 @@ PX4 is an open-source autopilot stack for drones and unmanned vehicles. It suppo
<sub>…and many more: helicopters, autogyros, airships, submarines, boats, and other experimental platforms. These frames have basic support but are not part of the regular flight-test program. See the <a href="https://docs.px4.io/main/en/airframes/airframe_reference.html">full airframe reference</a>.</sub>
## Quick Start
## Try PX4
Run PX4 in simulation with a single command. No build tools, no dependencies beyond Docker:
```bash
docker run --rm -it -p 14550:14550/udp px4io/px4-sitl:latest
```
Open [QGroundControl](https://qgroundcontrol.com) and fly. See [PX4 Simulation Quickstart](../dev_setup/px4_simulation_quickstart.md) for more options.
## Build from Source
```bash
git clone https://github.com/PX4/PX4-Autopilot.git --recursive
+1
View File
@@ -193,6 +193,7 @@ endif()
# board custom init files
set(OPTIONAL_BOARD_RC)
list(APPEND OPTIONAL_BOARD_RC
rc.board_early
rc.board_defaults
rc.board_sensors
rc.board_extras
@@ -14,6 +14,7 @@
param set UAVCAN_ENABLE 0
param set-default CA_AIRFRAME 1
param set-default CA_ROTOR_COUNT 1
param set-default CA_ROTOR0_PX 0.3
@@ -38,7 +39,6 @@ param set-default SYS_HITL 2
# - without real battery
param set-default CBRK_SUPPLY_CHK 894281
param set SIH_T_MAX 6
param set SIH_MASS 0.3
param set SIH_IXX 0.00402
param set SIH_IYY 0.0144
@@ -48,3 +48,21 @@ param set SIH_KDV 0.2
param set SIH_VEHICLE_TYPE 1 # sih as fixed wing
param set RWTO_TKOFF 1 # enable takeoff from runway (as opposed to launched)
# pusher propeller model with advance ratio, model from UIUC APC 8x6"
param set SIH_F_T_MAX 6
param set SIH_F_Q_MAX 0.03
# if SIH_F_CT0 > 0, SIH_F_T_MAX and SIH_F_Q_MAX will be overridden
param set SIH_F_CT0 0.131
param set SIH_F_CT1 0.004
param set SIH_F_CT2 -0.146
param set SIH_F_CP0 0.0777
param set SIH_F_CP1 0.0498
param set SIH_F_CP2 -0.11
param set SIH_F_DIA_INCH 8
param set SIH_F_RPM_MAX 9000
param set-default FW_AIRSPD_MIN 7
param set-default FW_AIRSPD_TRIM 10
param set-default FW_AIRSPD_MAX 12
param set-default FW_PSP_OFF 0.5
@@ -28,6 +28,7 @@ param set-default VT_FW_DIFTHR_EN 1
param set-default VT_FW_DIFTHR_S_Y 0.3
param set-default MPC_MAN_Y_MAX 60
param set-default MC_PITCH_P 5
param set-default FW_PSP_OFF 5
param set-default CA_AIRFRAME 4
param set-default CA_ROTOR_COUNT 2
@@ -56,7 +57,6 @@ param set-default HIL_ACT_REV 32
param set-default MAV_TYPE 19
# set SYS_HITL to 2 to start the SIH and avoid sensors startup
param set-default SYS_HITL 2
@@ -66,8 +66,9 @@ param set-default CBRK_SUPPLY_CHK 894281
param set-default SENS_DPRES_OFF 0.001
param set SIH_T_MAX 2.0
param set SIH_Q_MAX 0.0165
# tailsitter is equipped with two forward propellers
param set SIH_F_T_MAX 2
param set SIH_F_Q_MAX 0.0165
param set SIH_MASS 0.2
# IXX and IZZ are inverted from the thesis as the body frame is pitched by 90 deg
param set SIH_IXX 0.00354
@@ -77,6 +78,19 @@ param set SIH_IXZ 0
param set SIH_KDV 0.2
param set SIH_L_ROLL 0.145
# propeller diameter, rpm, and coeffs coming from the thesis
# Modeling and control of a flying wing tailsitter unmanned aerial vehicle."
# Chiappinelli, Romain, supervised by Nahon, Meyer, McGill University, Masters thesis, 2018.
# if SIH_F_CT0 > 0, SIH_F_T_MAX and SIH_F_Q_MAX will be overridden
param set SIH_F_CT0 0.1342
param set SIH_F_CT1 -0.1196
param set SIH_F_CT2 -0.1281
param set SIH_F_CP0 0.0522
param set SIH_F_CP1 -0.0146
param set SIH_F_CP2 -0.0602
param set SIH_F_DIA_INCH 5
param set SIH_F_RPM_MAX 14000
# sih as tailsitter
param set SIH_VEHICLE_TYPE 2
@@ -56,6 +56,7 @@ param set-default CA_SV_CS2_TYPE 4 # rudder
param set-default FW_AIRSPD_MIN 7
param set-default FW_AIRSPD_TRIM 10
param set-default FW_AIRSPD_MAX 12
param set-default VT_FWD_THRUST_EN 1
param set-default HIL_ACT_FUNC1 101
param set-default HIL_ACT_FUNC2 102
@@ -77,6 +78,7 @@ param set-default CBRK_SUPPLY_CHK 894281
param set-default SENS_DPRES_OFF 0.001
# quadrotor propellers
param set SIH_T_MAX 2.0
param set SIH_Q_MAX 0.0165
param set SIH_MASS 0.2
@@ -88,5 +90,18 @@ param set SIH_IXZ 0
param set SIH_KDV 0.2
param set SIH_L_ROLL 0.2
# pusher propeller model with advance ratio, model from UIUC APC 8x6"
param set SIH_F_T_MAX 6
param set SIH_F_Q_MAX 0.03
# if SIH_F_CT0 > 0, SIH_F_T_MAX and SIH_F_Q_MAX will be overridden
param set SIH_F_CT0 0.131
param set SIH_F_CT1 0.004
param set SIH_F_CT2 -0.146
param set SIH_F_CP0 0.0777
param set SIH_F_CP1 0.0498
param set SIH_F_CP2 -0.11
param set SIH_F_DIA_INCH 8
param set SIH_F_RPM_MAX 9000
# sih as standard vtol
param set SIH_VEHICLE_TYPE 3
@@ -0,0 +1,49 @@
#!/bin/sh
#
# @name SIH Hexacopter X
#
# @type Simulation
# @class Copter
#
# @maintainer Romain Chiappinelli <romain.chiap@gmail.com>
#
# @board px4_fmu-v2 exclude
#
. ${R}etc/init.d/rc.mc_defaults
param set UAVCAN_ENABLE 0
# set SYS_HITL to 2 to start the SIH and avoid sensors startup
param set SYS_HITL 2
# disable some checks to allow to fly:
# - without real battery
param set-default CBRK_SUPPLY_CHK 894281
param set SIH_VEHICLE_TYPE 4
# Symmetric hexacopter X clockwise motor numbering
param set-default CA_ROTOR_COUNT 6
param set-default CA_ROTOR0_PX 0.866
param set-default CA_ROTOR0_PY 0.5
param set-default CA_ROTOR1_PX 0
param set-default CA_ROTOR1_PY 1
param set-default CA_ROTOR1_KM -0.05
param set-default CA_ROTOR2_PX -0.866
param set-default CA_ROTOR2_PY 0.5
param set-default CA_ROTOR3_PX -0.866
param set-default CA_ROTOR3_PY -0.5
param set-default CA_ROTOR3_KM -0.05
param set-default CA_ROTOR4_PX 0
param set-default CA_ROTOR4_PY -1
param set-default CA_ROTOR5_PX 0.866
param set-default CA_ROTOR5_PY -0.5
param set-default CA_ROTOR5_KM -0.05
param set-default HIL_ACT_FUNC1 101
param set-default HIL_ACT_FUNC2 102
param set-default HIL_ACT_FUNC3 103
param set-default HIL_ACT_FUNC4 104
param set-default HIL_ACT_FUNC5 105
param set-default HIL_ACT_FUNC6 106
@@ -49,6 +49,7 @@ if(CONFIG_MODULES_SIMULATION_PWM_OUT_SIM)
1101_rc_plane_sih.hil
1102_tailsitter_duo_sih.hil
1103_standard_vtol_sih.hil
1105_rc_hexa_x_sih.hil
)
if(CONFIG_MODULES_ROVER_ACKERMANN)
px4_add_romfs_files(
+103 -48
View File
@@ -31,11 +31,20 @@ set PARAM_FILE ""
set PARAM_BACKUP_FILE ""
set RC_INPUT_ARGS ""
set STORAGE_AVAILABLE no
set STORAGE_CHECK yes
set SDCARD_EXT_PATH /fs/microsd/ext_autostart
set SDCARD_FORMAT no
set STARTUP_TUNE 1
set VEHICLE_TYPE none
# Fine-grained feature gates.
set USE_HARDFAULT_LOG no
set USE_EXTERNAL_AIRFRAMES no
set USE_PARAM_BACKUPS no
set USE_PARAM_IMPORT_DEBUG no
set USE_TASK_WATCHDOG no
set USE_ALT_UPDATE_DIRS no
# Airframe parameter versioning
# Value set to 1 by default but can optionally be overridden in the airframe configuration startup script.
# Airframe maintainers can ensure a reset to the airframe defaults during an update by increasing by one.
@@ -48,53 +57,81 @@ set PARAM_DEFAULTS_VER 1
ver all
#
# Try to mount the microSD card.
# Optional early board init: rc.board_early
# Can be used for setting env vars for rcS.
#
if [ -b "/dev/mmcsd0" ]
set BOARD_RC_EARLY ${R}etc/init.d/rc.board_early
if [ -f $BOARD_RC_EARLY ]
then
if mount -t vfat /dev/mmcsd0 /fs/microsd
then
if [ -f "/fs/microsd/.format" ]
then
echo "INFO [init] format /dev/mmcsd0 requested (/fs/microsd/.format)"
set SDCARD_FORMAT yes
rm /fs/microsd/.format
umount /fs/microsd
. $BOARD_RC_EARLY
fi
unset BOARD_RC_EARLY
else
#
# Try to mount/check storage (rc.board_early can disable this).
#
if [ $STORAGE_CHECK = yes ]
then
#
# Try to mount the microSD card.
#
if [ -b "/dev/mmcsd0" ]
then
if mount -t vfat /dev/mmcsd0 /fs/microsd
then
if [ -f "/fs/microsd/.format" ]
then
echo "INFO [init] format /dev/mmcsd0 requested (/fs/microsd/.format)"
set SDCARD_FORMAT yes
rm /fs/microsd/.format
umount /fs/microsd
else
set STORAGE_AVAILABLE yes
fi
fi
if [ $STORAGE_AVAILABLE = no -o $SDCARD_FORMAT = yes ]
then
echo "INFO [init] formatting /dev/mmcsd0"
set STARTUP_TUNE 15 # tune 15 = SD_ERROR (overridden to SD_INIT if format + mount succeeds)
if mkfatfs -F 32 /dev/mmcsd0
then
echo "INFO [init] card formatted"
if mount -t vfat /dev/mmcsd0 /fs/microsd
then
set STORAGE_AVAILABLE yes
set STARTUP_TUNE 14 # tune 14 = SD_INIT
else
echo "ERROR [init] card mount failed"
fi
else
echo "ERROR [init] format failed"
fi
fi
else
# Is there a device mounted for storage
if mft query -q -k MTD -s MTD_PARAMETERS -v /mnt/microsd
then
set STORAGE_AVAILABLE yes
fi
fi
if [ $STORAGE_AVAILABLE = no -o $SDCARD_FORMAT = yes ]
then
echo "INFO [init] formatting /dev/mmcsd0"
set STARTUP_TUNE 15 # tune 15 = SD_ERROR (overridden to SD_INIT if format + mount succeeds)
if mkfatfs -F 32 /dev/mmcsd0
then
echo "INFO [init] card formatted"
if mount -t vfat /dev/mmcsd0 /fs/microsd
then
set STORAGE_AVAILABLE yes
set STARTUP_TUNE 14 # tune 14 = SD_INIT
else
echo "ERROR [init] card mount failed"
fi
else
echo "ERROR [init] format failed"
fi
fi
else
# Is there a device mounted for storage
if mft query -q -k MTD -s MTD_PARAMETERS -v /mnt/microsd
then
set STORAGE_AVAILABLE yes
fi
fi
if [ $STORAGE_AVAILABLE = yes ]
then
set USE_HARDFAULT_LOG yes
set USE_EXTERNAL_AIRFRAMES yes
set USE_PARAM_BACKUPS yes
set USE_PARAM_IMPORT_DEBUG yes
set USE_ALT_UPDATE_DIRS yes
set PARAM_FILE /fs/microsd/params
set PARAM_BACKUP_FILE "/fs/microsd/parameters_backup.bson"
fi
if [ $USE_HARDFAULT_LOG = yes ]
then
if hardfault_log check
then
@@ -104,7 +141,15 @@ then
hardfault_log reset
fi
fi
fi
if [ $USE_TASK_WATCHDOG = yes ]
then
task_watchdog start
fi
if [ $USE_ALT_UPDATE_DIRS = yes ]
then
# Check for an update of the ext_autostart folder, and replace the old one with it
if [ -e /fs/microsd/ext_autostart_new ]
then
@@ -112,9 +157,6 @@ then
rm -r $SDCARD_EXT_PATH
mv /fs/microsd/ext_autostart_new $SDCARD_EXT_PATH
fi
set PARAM_FILE /fs/microsd/params
set PARAM_BACKUP_FILE "/fs/microsd/parameters_backup.bson"
fi
#
@@ -155,8 +197,11 @@ else
if [ -d "/fs/microsd" ]
then
# try to make a backup copy
cp $PARAM_FILE /fs/microsd/param_import_fail.bson
if [ $USE_PARAM_IMPORT_DEBUG = yes ]
then
# save copy of the failed param file for debugging
cp $PARAM_FILE /fs/microsd/param_import_fail.bson
fi
# try importing from backup file
if [ -f $PARAM_BACKUP_FILE ]
@@ -174,11 +219,14 @@ else
param status
dmesg >> /fs/microsd/param_import_fail.txt &
if [ $USE_PARAM_IMPORT_DEBUG = yes ]
then
dmesg >> /fs/microsd/param_import_fail.txt &
fi
fi
fi
if [ $STORAGE_AVAILABLE = yes ]
if [ $USE_PARAM_BACKUPS = yes ]
then
param select-backup $PARAM_BACKUP_FILE
fi
@@ -234,12 +282,12 @@ else
if [ ${VEHICLE_TYPE} = none ]
then
# Run external airframe script on SD card
if [ $STORAGE_AVAILABLE = yes ]
# Run external airframe script on SD card or EEPROM-backed storage
if [ $USE_EXTERNAL_AIRFRAMES = yes ]
then
. ${R}etc/init.d/rc.autostart_ext
else
echo "ERROR [init] SD not mounted, skipping external airframe"
echo "ERROR [init] no external airframe storage, skipping"
fi
fi
@@ -679,9 +727,16 @@ unset PARAM_BACKUP_FILE
unset PARAM_DEFAULTS_VER
unset RC_INPUT_ARGS
unset STORAGE_AVAILABLE
unset STORAGE_CHECK
unset SDCARD_EXT_PATH
unset SDCARD_FORMAT
unset STARTUP_TUNE
unset USE_HARDFAULT_LOG
unset USE_EXTERNAL_AIRFRAMES
unset USE_PARAM_BACKUPS
unset USE_PARAM_IMPORT_DEBUG
unset USE_TASK_WATCHDOG
unset USE_ALT_UPDATE_DIRS
unset VEHICLE_TYPE
#
+172
View File
@@ -0,0 +1,172 @@
#!/usr/bin/env python3
"""
Shared GitHub REST helpers for PX4 CI scripts.
This module is imported by the PR poster scripts under Tools/ci/. It is
NOT an executable entry point; do not run it directly.
Provides:
- fail(msg) terminates the caller with a clear error
- GitHubClient(token) thin stdlib-only GitHub REST client with
single-request and paginated helpers
Python stdlib only. No third-party dependencies.
History: extracted from Tools/ci/pr-comment-poster.py so that
pr-comment-poster.py and pr-review-poster.py share the same HTTP plumbing
without duplicating ~100 lines of request/pagination/error-handling code.
"""
import json
import sys
import typing
import urllib.error
import urllib.request
GITHUB_API = 'https://api.github.com'
DEFAULT_USER_AGENT = 'px4-ci'
API_VERSION = '2022-11-28'
def fail(msg: str) -> typing.NoReturn:
"""Print an error to stderr and exit with status 1.
Annotated NoReturn so static checkers understand control does not
continue past a fail() call.
"""
print('error: {}'.format(msg), file=sys.stderr)
sys.exit(1)
def _parse_next_link(link_header):
"""Return the URL for rel="next" from an RFC 5988 Link header, or None.
The Link header is comma-separated entries of the form:
<https://...?page=2>; rel="next", <https://...?page=5>; rel="last"
We walk each entry and return the URL of the one whose rel attribute is
"next". Accept single-quoted rel values for robustness even though
GitHub always emits double quotes.
"""
if not link_header:
return None
for part in link_header.split(','):
segs = part.strip().split(';')
if len(segs) < 2:
continue
url_seg = segs[0].strip()
if not (url_seg.startswith('<') and url_seg.endswith('>')):
continue
url = url_seg[1:-1]
for attr in segs[1:]:
attr = attr.strip()
if attr == 'rel="next"' or attr == "rel='next'":
return url
return None
class GitHubClient:
"""Minimal GitHub REST client backed by the Python stdlib.
Each instance holds a token and a user-agent so callers do not have to
thread them through every call. Methods return parsed JSON (or None for
empty responses) and raise RuntimeError with the server response body on
HTTP errors, so CI logs show what the API actually objected to.
Usage:
client = GitHubClient(token, user_agent='px4-pr-comment-poster')
body, headers = client.request('GET', 'repos/{o}/{r}/pulls/123')
for item in client.paginated('repos/{o}/{r}/pulls/123/reviews'):
...
"""
def __init__(self, token, user_agent=DEFAULT_USER_AGENT):
if not token:
raise ValueError('GitHub token is required')
self._token = token
self._user_agent = user_agent
def request(self, method, path_or_url, json_body=None):
"""GET/POST/PATCH/PUT/DELETE a single API path or absolute URL.
`path_or_url` may be either a relative API path (e.g.
"repos/PX4/PX4-Autopilot/pulls/123") or an absolute URL such as the
next-page URL returned from paginated results. Relative paths are
prefixed with the GitHub API base.
Returns (parsed_json_or_none, headers_dict). Raises RuntimeError
on HTTP or transport errors.
"""
url = self._resolve(path_or_url)
return self._do_request(method, url, json_body)
def paginated(self, path, per_page=100):
"""GET a path and follow rel="next" Link headers.
Yields items from each page's JSON array. Bumps per_page to 100
(GitHub's max) so large result sets take fewer round-trips.
Raises RuntimeError if any page response is not a JSON array.
"""
url = self._resolve(path)
sep = '&' if '?' in url else '?'
url = '{}{}per_page={}'.format(url, sep, per_page)
while url is not None:
body, headers = self._do_request('GET', url, None)
if body is None:
return
if not isinstance(body, list):
raise RuntimeError(
'expected JSON array from {}, got {}'.format(
url, type(body).__name__))
for item in body:
yield item
url = _parse_next_link(headers.get('Link'))
def _resolve(self, path_or_url):
if path_or_url.startswith('http://') or path_or_url.startswith('https://'):
return path_or_url
return '{}/{}'.format(GITHUB_API.rstrip('/'), path_or_url.lstrip('/'))
def _do_request(self, method, url, json_body):
data = None
headers = {
'Authorization': 'Bearer {}'.format(self._token),
'Accept': 'application/vnd.github+json',
# Pin the API version so GitHub deprecations don't silently
# change the response shape under us.
'X-GitHub-Api-Version': API_VERSION,
'User-Agent': self._user_agent,
}
if json_body is not None:
data = json.dumps(json_body).encode('utf-8')
headers['Content-Type'] = 'application/json; charset=utf-8'
req = urllib.request.Request(
url, data=data, method=method, headers=headers)
try:
with urllib.request.urlopen(req) as resp:
raw = resp.read()
# HTTPMessage is case-insensitive on lookup but its items()
# preserves the original case. GitHub sends "Link" with a
# capital L, which is what _parse_next_link expects.
resp_headers = dict(resp.headers.items())
if not raw:
return None, resp_headers
return json.loads(raw.decode('utf-8')), resp_headers
except urllib.error.HTTPError as e:
# GitHub error bodies are JSON with a "message" field and often
# a "documentation_url". Dump the raw body into the exception so
# the CI log shows exactly what the API objected to. A bare
# "HTTP 422" tells us nothing useful.
try:
err_body = e.read().decode('utf-8', errors='replace')
except Exception:
err_body = '(no body)'
raise RuntimeError(
'GitHub API {} {} failed: HTTP {} {}\n{}'.format(
method, url, e.code, e.reason, err_body))
except urllib.error.URLError as e:
# Network layer failure (DNS, TLS, connection reset). No HTTP
# response to parse; just surface the transport reason.
raise RuntimeError(
'GitHub API {} {} failed: {}'.format(method, url, e.reason))
+71
View File
@@ -0,0 +1,71 @@
# Build All Targets CI Configuration
#
# Controls board grouping, cache sizes, runner specs, and seeder targets
# for the build_all_targets workflow. Forks can customize this file to
# adjust for their infrastructure (e.g., lower cache sizes for GitHub's
# 10GB cache limit, fewer CPU cores for smaller runners).
# Container images
containers:
default: "ghcr.io/px4/px4-dev:v1.17.0-rc2"
voxl2: "ghcr.io/px4/px4-dev-voxl2:v1.7"
# Runner specs
runners:
seeder_cpu: 8
matrix_cpu: 4
# Default ccache max-size for build groups
cache:
default_size: "400M"
# Per-chip overrides for groups with many diverse boards
chip_sizes:
stm32h7: "800M"
stm32f4: "800M"
stm32f7: "800M"
imxrt: "800M"
# Board grouping limits
grouping:
# Max targets per group, tuned for ~10 min wall-clock with warm cache
chip_split_limits:
stm32h7: 10
stm32f7: 12
stm32f4: 20
stm32f1: 39
imxrt: 12
kinetis: 14
s32k: 17
rp2040: 10
special: 10
native: 17
default_split_limit: 12
# Minimum targets for a manufacturer to get a named group
lower_limit: 3
# If last chunk has fewer targets than this, merge into previous chunk
merge_back_threshold: 5
# Labels that isolate builds into the "special" group
special_labels:
- lto
- protected
# NXP chip families are pooled under "nxp-{chip}" regardless of board directory
nxp_chip_families:
- imxrt
- kinetis
- s32k
# Seeder targets: one representative build per chip family
seeders:
stm32h7: "px4_fmu-v6x_default"
stm32f7: "px4_fmu-v5_default"
stm32f4: "px4_fmu-v4_default"
stm32f1: "px4_io-v2_default"
imxrt: "nxp_mr-tropic_default"
kinetis: "nxp_fmuk66-v3_default"
s32k: "nxp_mr-canhubk3_default"
rp2040: "raspberrypi_pico_default"
special: "px4_fmu-v6x_default"
native: "px4_sitl_default"
voxl2: "modalai_voxl2_default"
-2
View File
@@ -3,7 +3,6 @@
# Please only modify if you know what you are doing
set -e
echo "### :clock1: Build Times" >> $GITHUB_STEP_SUMMARY
targets=$1
for target in ${targets//,/ }
do
@@ -14,6 +13,5 @@ do
diff=$(($stop-$start))
build_time="$(($diff /60/60))h $(($diff /60))m $(($diff % 60))s elapsed"
echo -e "\033[0;32mBuild Time: [$build_time]"
echo "* **$target** - $build_time" >> $GITHUB_STEP_SUMMARY
echo "::endgroup::"
done
+111
View File
@@ -0,0 +1,111 @@
#!/usr/bin/env python3
"""
Filter a git diff for consumption by clang-tidy-diff.
Produces a unified diff containing only files that clang-tidy can
actually analyze against the current compilation database:
- C/C++ source files (.c, .cpp, .cc, .cxx, .m, .mm) must be present
in compile_commands.json. Files absent from the database are test
files, excluded code, or platform-specific sources that were not
compiled. Feeding them to clang-tidy-diff produces spurious
"header not found" errors (gtest/gtest.h in particular).
- Header files (.h, .hpp, .hxx) always pass through. clang-tidy
analyzes header changes via the TUs that include them; there is
no separate TU for a header to match against the database.
- All other files (CMakeLists.txt, .yml, .md, etc.) are dropped.
Output is a unified diff suitable for piping into clang-tidy-diff.py.
If nothing remains, the output file is empty.
Used by .github/workflows/clang-tidy.yml as a pre-filter for the
`pr-review` artifact producer. Python stdlib only.
"""
import argparse
import json
import os
import subprocess
import sys
SOURCE_EXTS = {'.c', '.cpp', '.cc', '.cxx', '.m', '.mm'}
HEADER_EXTS = {'.h', '.hpp', '.hxx'}
def load_db_files(build_dir):
"""Return the set of source paths (repo-relative) in compile_commands.json."""
path = os.path.join(build_dir, 'compile_commands.json')
with open(path) as f:
db = json.load(f)
root = os.path.abspath('.')
prefix = root + os.sep
paths = set()
for entry in db:
p = entry.get('file', '')
if p.startswith(prefix):
paths.add(p[len(prefix):])
else:
# Relative or external path; record as-is
paths.add(p)
return paths
def changed_files(base_ref):
out = subprocess.check_output(
['git', 'diff', '--name-only', '{}...HEAD'.format(base_ref)],
text=True,
)
return [line.strip() for line in out.splitlines() if line.strip()]
def keep_file(path, db_files):
"""Decide whether to keep this path in the filtered diff."""
ext = os.path.splitext(path)[1].lower()
if ext in HEADER_EXTS:
return True
if ext in SOURCE_EXTS:
return path in db_files
return False
def filtered_diff(base_ref, keep_paths):
if not keep_paths:
return ''
cmd = ['git', 'diff', '-U0', '{}...HEAD'.format(base_ref), '--'] + sorted(keep_paths)
return subprocess.check_output(cmd, text=True)
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--build-dir', required=True,
help='CMake build dir containing compile_commands.json')
parser.add_argument('--base-ref', required=True,
help='Git ref to diff against (e.g. origin/main)')
parser.add_argument('--out', required=True,
help='Output path for the filtered unified diff')
args = parser.parse_args()
db_files = load_db_files(args.build_dir)
changed = changed_files(args.base_ref)
keep = [p for p in changed if keep_file(p, db_files)]
dropped = [p for p in changed if p not in keep]
print('clang-tidy-diff-filter: kept {} of {} changed files'.format(
len(keep), len(changed)))
if dropped:
print(' dropped (not in compile_commands.json or not source/header):')
for p in dropped:
print(' {}'.format(p))
diff = filtered_diff(args.base_ref, keep)
with open(args.out, 'w') as f:
f.write(diff)
return 0
if __name__ == '__main__':
sys.exit(main())
+539
View File
@@ -0,0 +1,539 @@
#!/usr/bin/env python3
#
# clang-tidy-fixes-to-review.py
#
# Producer-side helper that converts a clang-tidy fixes.yml file into a
# pr-review artifact (manifest.json + comments.json) suitable for
# Tools/ci/pr-review-poster.py.
#
# This script runs inside the clang-tidy job's px4-dev container so it can
# read the source tree directly and look up byte offsets in the original
# files. The output it writes is a fully-baked array of review comments;
# the poster never reads source files or fixes.yml.
#
# ----------------------------------------------------------------------------
# ATTRIBUTION
# ----------------------------------------------------------------------------
# This script reuses the diagnostic-to-review-comment translation logic
# from platisd/clang-tidy-pr-comments. The original work is:
#
# MIT License
#
# Copyright (c) 2021 Dimitris Platis
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Adapted parts:
# - get_diff_line_ranges_per_file() and its inner change_to_line_range()
# - generate_review_comments() and its nested helpers
# (get_line_by_offset, validate_warning_applicability,
# calculate_replacements_diff, markdown, markdown_url,
# diagnostic_name_visual, generate_single_comment)
# - reorder_diagnostics()
#
# Removed parts (handled by Tools/ci/pr-review-poster.py instead):
# - post_review_comments / dismiss_change_requests / resolve_conversations
# - the original argparse main and the requests-based HTTP layer
#
# Adaptation notes:
# - The HTTP layer is rewritten on top of Tools/ci/_github_helpers.py so
# this script does not depend on the third-party `requests` package.
# - Conversation resolution (the GraphQL path) is intentionally dropped
# for v1; revisit if it turns out to be missed.
# - Clang-Tidy 8 upconvert is preserved verbatim.
#
# ----------------------------------------------------------------------------
# Bounded assumptions (documented for future maintainers):
# - Source files are UTF-8 (we read them as latin_1, matching clang-tidy's
# own byte-offset model, and the offsets we surface are line counts)
# - Source files use LF line endings
# - Malformed entries in fixes.yml are skipped with a warning rather than
# crashing the job
#
# Dependencies: pyyaml + Tools/ci/_github_helpers.py.
# pyyaml is preinstalled in the px4-dev container; this script is intended
# to run there, not on bare ubuntu-latest.
"""Convert a clang-tidy fixes.yml into a pr-review artifact."""
import argparse
import difflib
import json
import os
import posixpath
import re
import sys
import urllib.parse
import yaml
import _github_helpers
from _github_helpers import fail as _fail
# Markers used inside the per-comment body to call out severity. Plain
# strings rather than emojis to keep the file emoji-free per project
# preferences; the rendered Markdown is unaffected.
SINGLE_COMMENT_MARKERS = {
'Error': '**[error]**',
'Warning': '**[warning]**',
'Remark': '**[remark]**',
'fallback': '**[note]**',
}
# ---------------------------------------------------------------------------
# Diff-range parsing (adapted from platisd)
# ---------------------------------------------------------------------------
def get_diff_line_ranges_per_file(pr_files):
"""Return a dict mapping each PR file path to a list of line ranges
(the +new-side hunks) parsed from its patch."""
def change_to_line_range(change):
split_change = change.split(',')
start = int(split_change[0])
size = int(split_change[1]) if len(split_change) > 1 else 1
return range(start, start + size)
result = {}
for pr_file in pr_files:
# Removed binary files etc. have no patch section.
if 'patch' not in pr_file:
continue
file_name = pr_file['filename']
# Match lines like '@@ -101,8 +102,11 @@'
git_line_tags = re.findall(
r'^@@ -.*? +.*? @@', pr_file['patch'], re.MULTILINE)
changes = [
tag.replace('@@', '').strip().split()[1].replace('+', '')
for tag in git_line_tags
]
result[file_name] = [
change_to_line_range(change) for change in changes
]
return result
def fetch_pull_request_files(client, repo, pr_number):
"""Yield file metadata objects for each file modified by the PR."""
path = 'repos/{}/pulls/{}/files'.format(repo, pr_number)
for entry in client.paginated(path):
yield entry
# ---------------------------------------------------------------------------
# Diagnostic ordering (adapted from platisd)
# ---------------------------------------------------------------------------
def reorder_diagnostics(diags):
"""Return diagnostics ordered Error -> Warning -> Remark -> other."""
errors = [d for d in diags if d.get('Level') == 'Error']
warnings = [d for d in diags if d.get('Level') == 'Warning']
remarks = [d for d in diags if d.get('Level') == 'Remark']
others = [
d for d in diags
if d.get('Level') not in {'Error', 'Warning', 'Remark'}
]
if others:
print(
'warning: some fixes have an unexpected Level (not Error, '
'Warning, or Remark)', file=sys.stderr)
return errors + warnings + remarks + others
# ---------------------------------------------------------------------------
# Comment generation (adapted from platisd)
# ---------------------------------------------------------------------------
def generate_review_comments(clang_tidy_fixes, repository_root,
diff_line_ranges_per_file,
single_comment_markers):
"""Yield review comment dicts for each clang-tidy diagnostic that
intersects the PR diff."""
def get_line_by_offset(file_path, offset):
# Clang-Tidy doesn't support multibyte encodings and measures
# offsets in bytes; latin_1 makes byte offsets and string offsets
# equivalent.
with open(repository_root + file_path, encoding='latin_1') as fh:
source = fh.read()
return source[:offset].count('\n') + 1
def validate_warning_applicability(file_path, start_line_num, end_line_num):
assert end_line_num >= start_line_num
for line_range in diff_line_ranges_per_file[file_path]:
assert line_range.step == 1
if (line_range.start <= start_line_num
and end_line_num < line_range.stop):
return True
return False
def calculate_replacements_diff(file_path, replacements):
# Apply replacements in reverse order so subsequent offsets do not
# shift.
replacements.sort(key=lambda item: (-item['Offset']))
with open(repository_root + file_path, encoding='latin_1') as fh:
source = fh.read()
changed = source
for replacement in replacements:
changed = (
changed[:replacement['Offset']]
+ replacement['ReplacementText']
+ changed[replacement['Offset'] + replacement['Length']:]
)
return difflib.Differ().compare(
source.splitlines(keepends=True),
changed.splitlines(keepends=True),
)
def markdown(s):
md_chars = '\\`*_{}[]<>()#+-.!|'
def escape_chars(s):
for ch in md_chars:
s = s.replace(ch, '\\' + ch)
return s
def unescape_chars(s):
for ch in md_chars:
s = s.replace('\\' + ch, ch)
return s
s = escape_chars(s)
s = re.sub(
"'([^']*)'",
lambda m: '`` ' + unescape_chars(m.group(1)) + ' ``',
s,
)
return s
def markdown_url(label, url):
return '[{}]({})'.format(label, url)
def diagnostic_name_visual(diagnostic_name):
visual = '**{}**'.format(markdown(diagnostic_name))
try:
first_dash_idx = diagnostic_name.index('-')
except ValueError:
return visual
namespace = urllib.parse.quote_plus(diagnostic_name[:first_dash_idx])
check_name = urllib.parse.quote_plus(
diagnostic_name[first_dash_idx + 1:])
return markdown_url(
visual,
'https://clang.llvm.org/extra/clang-tidy/checks/{}/{}.html'.format(
namespace, check_name),
)
def generate_single_comment(file_path, start_line_num, end_line_num,
name, message, single_comment_marker,
replacement_text=None):
result = {
'path': file_path,
'line': end_line_num,
'side': 'RIGHT',
'body': '{} {} {}\n{}'.format(
single_comment_marker,
diagnostic_name_visual(name),
single_comment_marker,
markdown(message),
),
}
if start_line_num != end_line_num:
result['start_line'] = start_line_num
result['start_side'] = 'RIGHT'
if replacement_text is not None:
if not replacement_text or replacement_text[-1] != '\n':
replacement_text += '\n'
result['body'] += '\n```suggestion\n{}```'.format(replacement_text)
return result
for diag in clang_tidy_fixes['Diagnostics']:
# Upconvert clang-tidy 8 format to 9+
if 'DiagnosticMessage' not in diag:
diag['DiagnosticMessage'] = {
'FileOffset': diag.get('FileOffset'),
'FilePath': diag.get('FilePath'),
'Message': diag.get('Message'),
'Replacements': diag.get('Replacements', []),
}
diag_message = diag['DiagnosticMessage']
diag_message['FilePath'] = posixpath.normpath(
(diag_message.get('FilePath') or '').replace(repository_root, ''))
for replacement in diag_message.get('Replacements') or []:
replacement['FilePath'] = posixpath.normpath(
replacement['FilePath'].replace(repository_root, ''))
diag_name = diag.get('DiagnosticName', '<unknown>')
diag_message_msg = diag_message.get('Message', '')
level = diag.get('Level', 'Warning')
single_comment_marker = single_comment_markers.get(
level, single_comment_markers['fallback'])
replacements = diag_message.get('Replacements') or []
if not replacements:
file_path = diag_message['FilePath']
offset = diag_message.get('FileOffset')
if offset is None:
print('warning: skipping {!r}: missing FileOffset'.format(
diag_name), file=sys.stderr)
continue
if file_path not in diff_line_ranges_per_file:
print(
"'{}' for {} does not apply to the files changed in "
'this PR'.format(diag_name, file_path))
continue
try:
line_num = get_line_by_offset(file_path, offset)
except (OSError, ValueError) as e:
print('warning: skipping {!r} on {}: {}'.format(
diag_name, file_path, e), file=sys.stderr)
continue
print("Processing '{}' at line {} of {}...".format(
diag_name, line_num, file_path))
if validate_warning_applicability(file_path, line_num, line_num):
yield generate_single_comment(
file_path,
line_num,
line_num,
diag_name,
diag_message_msg,
single_comment_marker=single_comment_marker,
)
else:
print('This warning does not apply to the lines changed '
'in this PR')
else:
for file_path in {item['FilePath'] for item in replacements}:
if file_path not in diff_line_ranges_per_file:
print(
"'{}' for {} does not apply to the files changed "
'in this PR'.format(diag_name, file_path))
continue
line_num = 1
start_line_num = None
end_line_num = None
replacement_text = None
try:
diff_iter = calculate_replacements_diff(
file_path,
[r for r in replacements if r['FilePath'] == file_path],
)
except (OSError, ValueError) as e:
print('warning: skipping {!r} on {}: {}'.format(
diag_name, file_path, e), file=sys.stderr)
continue
for line in diff_iter:
# Comment line, ignore.
if line.startswith('? '):
continue
# A '-' line is the start or continuation of a region
# to replace.
if line.startswith('- '):
if start_line_num is None:
start_line_num = line_num
end_line_num = line_num
else:
end_line_num = line_num
if replacement_text is None:
replacement_text = ''
line_num += 1
# A '+' line is part of the replacement text.
elif line.startswith('+ '):
if replacement_text is None:
replacement_text = line[2:]
else:
replacement_text += line[2:]
# A context line marks the end of a replacement region.
elif line.startswith(' '):
if replacement_text is not None:
if start_line_num is None:
# Pure addition: synthesize a one-line
# range and append the context line to
# the replacement.
start_line_num = line_num
end_line_num = line_num
replacement_text += line[2:]
print("Processing '{}' at lines {}-{} of {}...".format(
diag_name, start_line_num, end_line_num, file_path))
if validate_warning_applicability(
file_path, start_line_num, end_line_num):
yield generate_single_comment(
file_path,
start_line_num,
end_line_num,
diag_name,
diag_message_msg,
single_comment_marker=single_comment_marker,
replacement_text=replacement_text,
)
else:
print(
'This warning does not apply to the '
'lines changed in this PR')
start_line_num = None
end_line_num = None
replacement_text = None
line_num += 1
else:
# Unknown difflib prefix; skip rather than abort.
print('warning: unexpected diff prefix {!r}; '
'skipping diagnostic'.format(line[:2]),
file=sys.stderr)
break
# End of file with a pending replacement region.
if replacement_text is not None and start_line_num is not None:
print("Processing '{}' at lines {}-{} of {}...".format(
diag_name, start_line_num, end_line_num, file_path))
if validate_warning_applicability(
file_path, start_line_num, end_line_num):
yield generate_single_comment(
file_path,
start_line_num,
end_line_num,
diag_name,
diag_message_msg,
single_comment_marker=single_comment_marker,
replacement_text=replacement_text,
)
else:
print('This warning does not apply to the lines '
'changed in this PR')
# ---------------------------------------------------------------------------
# Entry point
# ---------------------------------------------------------------------------
def main(argv=None):
parser = argparse.ArgumentParser(
description='Convert a clang-tidy fixes.yml into a pr-review '
'artifact (manifest.json + comments.json).',
)
parser.add_argument('--fixes', required=True,
help='Path to fixes.yml from clang-tidy')
parser.add_argument('--repo-root', required=True,
help='Path to the repository root containing the '
'source files referenced by fixes.yml')
parser.add_argument('--repo', required=True,
help='owner/name of the repository')
parser.add_argument('--pr-number', required=True, type=int,
help='Pull request number')
parser.add_argument('--commit-sha', required=True,
help='40-char hex commit SHA the review will pin to')
parser.add_argument('--out-dir', required=True,
help='Directory to write manifest.json and '
'comments.json')
parser.add_argument(
'--marker',
default='<!-- pr-review-poster:clang-tidy -->',
help='Marker string embedded in the review body so the poster '
'can find and dismiss stale runs')
parser.add_argument(
'--event',
default='REQUEST_CHANGES',
choices=('COMMENT', 'REQUEST_CHANGES'),
help='GitHub review event type')
parser.add_argument(
'--summary', default='',
help='Optional review summary text appended to the review body')
args = parser.parse_args(argv)
if args.pr_number <= 0:
_fail('--pr-number must be > 0')
if not re.match(r'^[0-9a-f]{40}$', args.commit_sha):
_fail('--commit-sha must be a 40-char lowercase hex string')
token = os.environ.get('GITHUB_TOKEN')
if not token:
_fail('GITHUB_TOKEN is not set')
# Normalize the repo root with a trailing slash so the platisd-style
# str.replace() trick still strips it cleanly.
repo_root = args.repo_root
if not repo_root.endswith(os.sep):
repo_root = repo_root + os.sep
os.makedirs(args.out_dir, exist_ok=True)
client = _github_helpers.GitHubClient(token, user_agent='px4-clang-tidy-fixes-to-review')
print('Fetching PR file list from GitHub...')
pr_files = list(fetch_pull_request_files(client, args.repo, args.pr_number))
diff_line_ranges_per_file = get_diff_line_ranges_per_file(pr_files)
print('Loading clang-tidy fixes from {}...'.format(args.fixes))
if not os.path.isfile(args.fixes):
# No fixes file means clang-tidy ran cleanly. Emit an empty
# comments.json so the poster can short-circuit.
comments = []
else:
with open(args.fixes, encoding='utf-8') as fh:
clang_tidy_fixes = yaml.safe_load(fh)
if (not clang_tidy_fixes
or 'Diagnostics' not in clang_tidy_fixes
or not clang_tidy_fixes['Diagnostics']):
comments = []
else:
clang_tidy_fixes['Diagnostics'] = reorder_diagnostics(
clang_tidy_fixes['Diagnostics'])
comments = list(generate_review_comments(
clang_tidy_fixes,
repo_root,
diff_line_ranges_per_file,
single_comment_markers=SINGLE_COMMENT_MARKERS,
))
print('Generated {} review comment(s)'.format(len(comments)))
manifest = {
'pr_number': args.pr_number,
'marker': args.marker,
'event': args.event,
'commit_sha': args.commit_sha,
}
if args.summary:
manifest['summary'] = args.summary
manifest_path = os.path.join(args.out_dir, 'manifest.json')
comments_path = os.path.join(args.out_dir, 'comments.json')
with open(manifest_path, 'w', encoding='utf-8') as fh:
json.dump(manifest, fh, indent=2)
fh.write('\n')
with open(comments_path, 'w', encoding='utf-8') as fh:
json.dump(comments, fh, indent=2)
fh.write('\n')
print('Wrote {} and {}'.format(manifest_path, comments_path))
return 0
if __name__ == '__main__':
sys.exit(main())
+360 -87
View File
@@ -16,6 +16,7 @@ kconf.warn_assign_override = False
kconf.warn_assign_redun = False
source_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..')
boards_dir = os.path.join(source_dir, '..', 'boards')
parser = argparse.ArgumentParser(description='Generate build targets')
@@ -26,6 +27,8 @@ parser.add_argument('-p', '--pretty', dest='pretty', action='store_true',
parser.add_argument('-g', '--groups', dest='group', action='store_true',
help='Groups targets')
parser.add_argument('-f', '--filter', dest='filter', help='comma separated list of build target name prefixes to include instead of all e.g. "px4_fmu-v5_"')
parser.add_argument('-s', '--seeders', dest='seeders', action='store_true',
help='Output seeder matrix JSON (one entry per chip family)')
args = parser.parse_args()
verbose = args.verbose
@@ -35,8 +38,14 @@ if args.filter:
for target in args.filter.split(','):
target_filter.append(target)
default_container = 'ghcr.io/px4/px4-dev:v1.16.0-rc1-258-g0369abd556'
voxl2_container = 'ghcr.io/px4/px4-dev-voxl2:v1.5'
# Load CI configuration from YAML
import yaml
ci_config_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'build_all_config.yml')
with open(ci_config_path) as f:
ci_config = yaml.safe_load(f)
default_container = ci_config['containers']['default']
voxl2_container = ci_config['containers']['voxl2']
build_configs = []
grouped_targets = {}
excluded_boards = ['px4_ros2', 'espressif_esp32'] # TODO: fix and enable
@@ -56,6 +65,71 @@ excluded_labels = [
'uavcanv1', # TODO: fix and enable
]
# Labels that mark isolated/special builds (poor cache reuse with normal builds)
special_labels = ci_config.get('special_labels', ['lto', 'protected'])
def detect_chip_family(manufacturer_name, board_name, label):
"""Detect the chip family for a board by reading its NuttX defconfig.
Returns a chip family string used for cache grouping:
stm32h7, stm32f7, stm32f4, stm32f1, imxrt, kinetis, s32k, rp2040, native, special
"""
# Special labels get their own group regardless of chip
if label in special_labels:
return 'special'
board_path = os.path.join(boards_dir, manufacturer_name, board_name)
nsh_defconfig = os.path.join(board_path, 'nuttx-config', 'nsh', 'defconfig')
if not os.path.exists(nsh_defconfig):
# Try bootloader defconfig as fallback
bl_defconfig = os.path.join(board_path, 'nuttx-config', 'bootloader', 'defconfig')
if os.path.exists(bl_defconfig):
nsh_defconfig = bl_defconfig
else:
return 'native'
arch_chip = None
specific_chip = None
with open(nsh_defconfig) as f:
for line in f:
line = line.strip()
if line.startswith('CONFIG_ARCH_CHIP='):
arch_chip = line.split('=')[1].strip('"')
elif line.startswith('CONFIG_ARCH_CHIP_STM32F') and line.endswith('=y'):
specific_chip = line.split('=')[0].replace('CONFIG_ARCH_CHIP_', '')
if arch_chip is None:
return 'native'
# Direct matches for chips that have unique CONFIG_ARCH_CHIP values
if arch_chip == 'stm32h7':
return 'stm32h7'
elif arch_chip == 'stm32f7':
return 'stm32f7'
elif arch_chip == 'imxrt':
return 'imxrt'
elif arch_chip == 'kinetis':
return 'kinetis'
elif arch_chip.startswith('s32k'):
return 's32k'
elif arch_chip == 'rp2040':
return 'rp2040'
elif arch_chip == 'stm32':
# Disambiguate STM32 sub-families using specific chip define
if specific_chip:
if specific_chip.startswith('STM32F1'):
return 'stm32f1'
elif specific_chip.startswith('STM32F4'):
return 'stm32f4'
else:
return 'stm32f4' # Default STM32 to F4
return 'stm32f4'
else:
return 'native'
target_chip_families = {} # target_name -> chip_family mapping
github_action_config = { 'include': build_configs }
extra_args = {}
if args.pretty:
@@ -66,11 +140,21 @@ def chunks(arr, size):
for i in range(0, len(arr), size):
yield arr[i:i + size]
MERGE_BACK_THRESHOLD = 5
def chunks_merged(arr, size):
"""Split array into chunks, merging the last chunk back if it's too small."""
result = list(chunks(arr, size))
if len(result) > 1 and len(result[-1]) < MERGE_BACK_THRESHOLD:
result[-2] = result[-2] + result[-1]
result.pop()
return result
def comma_targets(targets):
# turns array of targets into a comma split string
return ",".join(targets)
def process_target(px4board_file, target_name):
def process_target(px4board_file, target_name, manufacturer_name=None, board_dir_name=None, label=None):
# reads through the board file and grabs
# useful information for building
ret = None
@@ -107,6 +191,16 @@ def process_target(px4board_file, target_name):
if board_name in board_container_overrides:
container = board_container_overrides[board_name]
# Detect chip family for cache grouping
chip_family = 'native'
if manufacturer_name and board_dir_name:
if platform == 'nuttx':
chip_family = detect_chip_family(manufacturer_name, board_dir_name, label or '')
elif board_name in board_container_overrides or platform in platform_container_overrides:
chip_family = 'native' # voxl2/qurt targets
else:
chip_family = 'native'
# Boards with container overrides get their own group
if board_name in board_container_overrides or platform in platform_container_overrides:
group = 'voxl2'
@@ -124,7 +218,7 @@ def process_target(px4board_file, target_name):
else:
if verbose: print(f'unmatched platform: {platform}')
ret = {'target': target_name, 'container': container}
ret = {'target': target_name, 'container': container, 'chip_family': chip_family}
if(args.group):
ret['arch'] = group
@@ -147,6 +241,8 @@ grouped_targets['base']['container'] = default_container
grouped_targets['base']['manufacturers'] = {}
grouped_targets['base']['manufacturers']['px4'] = []
grouped_targets['base']['manufacturers']['px4'] += metadata_targets
for mt in metadata_targets:
target_chip_families[mt] = 'native'
for manufacturer in sorted(os.scandir(os.path.join(source_dir, '../boards')), key=lambda e: e.name):
if not manufacturer.is_dir():
@@ -177,7 +273,10 @@ for manufacturer in sorted(os.scandir(os.path.join(source_dir, '../boards')), ke
if label in excluded_labels:
if verbose: print(f'excluding label {label} ({target_name})')
continue
target = process_target(files.path, target_name)
target = process_target(files.path, target_name,
manufacturer_name=manufacturer.name,
board_dir_name=board.name,
label=label)
if (args.group and target is not None):
if (target['arch'] not in grouped_targets):
grouped_targets[target['arch']] = {}
@@ -186,6 +285,7 @@ for manufacturer in sorted(os.scandir(os.path.join(source_dir, '../boards')), ke
if(manufacturer.name not in grouped_targets[target['arch']]['manufacturers']):
grouped_targets[target['arch']]['manufacturers'][manufacturer.name] = []
grouped_targets[target['arch']]['manufacturers'][manufacturer.name].append(target_name)
target_chip_families[target_name] = target['chip_family']
if target is not None:
build_configs.append(target)
@@ -246,6 +346,9 @@ for manufacturer in sorted(os.scandir(os.path.join(source_dir, '../boards')), ke
if manufacturer.name not in grouped_targets[group]['manufacturers']:
grouped_targets[group]['manufacturers'][manufacturer.name] = []
grouped_targets[group]['manufacturers'][manufacturer.name].append(deb_target)
# Inherit chip_family from the default target
default_chip = target_chip_families.get(default_target, 'native')
target_chip_families[deb_target] = default_chip
build_configs.append(target_entry)
if(verbose):
@@ -261,109 +364,227 @@ if(verbose):
print("===================")
if (args.group):
# if we are using this script for grouping builds
# we loop trough the manufacturers list and split their targets
# if a manufacturer has more than a LIMIT of boards then we split that
# into sub groups such as "arch-manufacturer name-index"
# example:
# nuttx-px4-0
# nuttx-px4-1
# nuttx-px4-2
# nuttx-ark-0
# nuttx-ark-1
# if the manufacturer doesn't have more targets than LIMIT then we add
# them to a generic group with the following structure "arch-index"
# example:
# nuttx-0
# nuttx-1
# Group targets by chip family for better ccache reuse.
# Targets sharing the same MCU family (e.g. stm32h7) benefit from
# a shared ccache seed since they compile the same NuttX kernel and HAL.
#
# Grouping strategy:
# 1. Collect all targets per (arch, chip_family, manufacturer)
# 2. Within each chip_family, large manufacturers get their own groups
# named "{manufacturer}-{chip_family}[-N]"
# 3. Small manufacturers are merged into "misc-{chip_family}[-N]"
# 4. Special groups: "special" (lto/protected/allyes), "io" (stm32f1),
# "voxl2-0" (unchanged)
# 5. Non-NuttX groups: "base-N", "aarch64-N", "armhf-N" (unchanged)
final_groups = []
last_man = ''
last_arch = ''
SPLIT_LIMIT = 10
LOWER_LIMIT = 5
# Load grouping and cache config
grouping_config = ci_config.get('grouping', {})
CHIP_SPLIT_LIMITS = grouping_config.get('chip_split_limits', {})
DEFAULT_SPLIT_LIMIT = grouping_config.get('default_split_limit', 12)
LOWER_LIMIT = grouping_config.get('lower_limit', 3)
cache_config = ci_config.get('cache', {})
DEFAULT_CACHE_SIZE = cache_config.get('default_size', '400M')
CHIP_CACHE_SIZES = cache_config.get('chip_sizes', {})
if(verbose):
print(f'=:Architectures: [{grouped_targets.keys()}]')
for arch in grouped_targets:
runner = 'x64' if arch in ('nuttx', 'voxl2') else 'arm64'
runner = 'x64'
# armhf and aarch64 Linux boards need the arm64 container image
# which ships the arm-linux-gnueabihf and aarch64-linux-gnu cross compilers
# (the x64 container image does not include them)
if arch in ('armhf', 'aarch64'):
runner = 'arm64'
if(verbose):
print(f'=:Processing: [{arch}]')
temp_group = []
for man in grouped_targets[arch]['manufacturers']:
if(verbose):
print(f'=:Processing: [{arch}][{man}]')
man_len = len(grouped_targets[arch]['manufacturers'][man])
if(man_len > LOWER_LIMIT and man_len < (SPLIT_LIMIT + 1)):
# Manufacturers can have their own group
if arch == 'nuttx':
# Re-bucket NuttX targets by chip_family then manufacturer
chip_man_buckets = {} # (chip_family, manufacturer) -> [target_names]
for man in grouped_targets[arch]['manufacturers']:
for target in grouped_targets[arch]['manufacturers'][man]:
chip = target_chip_families.get(target, 'native')
key = (chip, man)
if key not in chip_man_buckets:
chip_man_buckets[key] = []
chip_man_buckets[key].append(target)
# Collect all chip families present
chip_families_seen = sorted(set(k[0] for k in chip_man_buckets.keys()))
for chip in chip_families_seen:
SPLIT_LIMIT = CHIP_SPLIT_LIMITS.get(chip, DEFAULT_SPLIT_LIMIT)
# Special naming for certain chip families
if chip == 'special':
chip_label = 'special'
elif chip == 'stm32f1':
chip_label = 'io'
elif chip == 'rp2040':
chip_label = 'special' # rp2040 goes into special group
else:
chip_label = chip
# Gather all (manufacturer -> targets) for this chip family
# NXP chip families (imxrt, kinetis, s32k) pool all manufacturers
# under "nxp" since all boards use NXP silicon regardless of
# which directory they live in (e.g., px4/fmu-v6xrt is imxrt).
nxp_chips = tuple(ci_config.get('nxp_chip_families', ['imxrt', 'kinetis', 's32k']))
man_targets = {}
for (c, m), targets in chip_man_buckets.items():
if c == chip:
man_key = 'nxp' if chip in nxp_chips else m
if man_key not in man_targets:
man_targets[man_key] = []
man_targets[man_key].extend(targets)
# Merge rp2040 targets into a flat list for the special group
if chip in ('special', 'rp2040'):
all_targets = []
for m in sorted(man_targets.keys()):
all_targets.extend(man_targets[m])
# These get added to the special bucket below
# We'll handle after the chip loop
continue
if(verbose):
print(f'=:Processing: [{arch}][{man}][{man_len}]==Manufacturers can have their own group')
group_name = arch + "-" + man
targets = comma_targets(grouped_targets[arch]['manufacturers'][man])
final_groups.append({
"container": grouped_targets[arch]['container'],
"targets": targets,
"arch": arch,
"runner": runner,
"group": group_name,
"len": len(grouped_targets[arch]['manufacturers'][man])
})
elif(man_len >= (SPLIT_LIMIT + 1)):
# Split big man groups into subgroups
# example: Pixhawk
if(verbose):
print(f'=:Processing: [{arch}][{man}][{man_len}]==Manufacturers has multiple own groups')
chunk_limit = SPLIT_LIMIT
print(f'=:Processing chip_family: [{chip}] ({chip_label})')
# Split into large-manufacturer groups and misc groups
# For NXP-exclusive chip families, always use the nxp name
# regardless of target count (there's no other manufacturer to pool with)
force_named = chip in nxp_chips
temp_group = [] # small manufacturers pooled here
for man in sorted(man_targets.keys()):
man_len = len(man_targets[man])
if (force_named or man_len > LOWER_LIMIT) and man_len <= SPLIT_LIMIT:
group_name = f"{man}-{chip_label}"
if(verbose):
print(f'=: [{man}][{man_len}] -> {group_name}')
final_groups.append({
"container": grouped_targets[arch]['container'],
"targets": comma_targets(man_targets[man]),
"arch": arch,
"chip_family": chip,
"runner": runner,
"group": group_name,
"len": man_len,
})
elif man_len > SPLIT_LIMIT:
chunk_counter = 0
for chunk in chunks_merged(man_targets[man], SPLIT_LIMIT):
group_name = f"{man}-{chip_label}-{chunk_counter}"
if(verbose):
print(f'=: [{man}][{man_len}] -> {group_name} ({len(chunk)})')
final_groups.append({
"container": grouped_targets[arch]['container'],
"targets": comma_targets(chunk),
"arch": arch,
"chip_family": chip,
"runner": runner,
"group": group_name,
"len": len(chunk),
})
chunk_counter += 1
else:
if(verbose):
print(f'=: [{man}][{man_len}] -> misc pool')
temp_group.extend(man_targets[man])
# Emit misc groups for small manufacturers
if temp_group:
misc_chunks = chunks_merged(temp_group, SPLIT_LIMIT)
num_misc_chunks = len(misc_chunks)
chunk_counter = 0
for chunk in misc_chunks:
if num_misc_chunks == 1:
group_name = f"misc-{chip_label}"
else:
group_name = f"misc-{chip_label}-{chunk_counter}"
if(verbose):
print(f'=: [misc][{len(chunk)}] -> {group_name}')
final_groups.append({
"container": grouped_targets[arch]['container'],
"targets": comma_targets(chunk),
"arch": arch,
"chip_family": chip,
"runner": runner,
"group": group_name,
"len": len(chunk),
})
chunk_counter += 1
# Now handle special + rp2040 targets
SPLIT_LIMIT = CHIP_SPLIT_LIMITS.get('special', DEFAULT_SPLIT_LIMIT)
special_targets = []
for (c, m), targets in chip_man_buckets.items():
if c in ('special', 'rp2040'):
special_targets.extend(targets)
if special_targets:
chunk_counter = 0
for chunk in chunks(grouped_targets[arch]['manufacturers'][man], chunk_limit):
group_name = arch + "-" + man + "-" + str(chunk_counter)
targets = comma_targets(chunk)
for chunk in chunks_merged(special_targets, SPLIT_LIMIT):
if len(special_targets) <= SPLIT_LIMIT:
group_name = 'special'
else:
group_name = f'special-{chunk_counter}'
if(verbose):
print(f'=: [special][{len(chunk)}] -> {group_name}')
final_groups.append({
"container": grouped_targets[arch]['container'],
"targets": targets,
"targets": comma_targets(chunk),
"arch": arch,
"chip_family": "special",
"runner": runner,
"group": group_name,
"len": len(chunk),
})
chunk_counter += 1
else:
if(verbose):
print(f'=:Processing: [{arch}][{man}][{man_len}]==Manufacturers too small group with others')
temp_group.extend(grouped_targets[arch]['manufacturers'][man])
temp_len = len(temp_group)
chunk_counter = 0
if(temp_len > 0 and temp_len < (SPLIT_LIMIT + 1)):
if(verbose):
print(f'=:Processing: [{arch}][orphan][{temp_len}]==Leftover arch can have their own group')
group_name = arch + "-" + str(chunk_counter)
targets = comma_targets(temp_group)
final_groups.append({
"container": grouped_targets[arch]['container'],
"targets": targets,
"arch": arch,
"runner": runner,
"group": group_name,
"len": temp_len
})
elif(temp_len >= (SPLIT_LIMIT + 1)):
# Split big man groups into subgroups
# example: Pixhawk
if(verbose):
print(f'=:Processing: [{arch}][orphan][{temp_len}]==Leftover arch can has multpile group')
chunk_limit = SPLIT_LIMIT
chunk_counter = 0
for chunk in chunks(temp_group, chunk_limit):
group_name = arch + "-" + str(chunk_counter)
targets = comma_targets(chunk)
elif arch == 'voxl2':
# VOXL2 stays as its own group
all_targets = []
for man in grouped_targets[arch]['manufacturers']:
all_targets.extend(grouped_targets[arch]['manufacturers'][man])
if all_targets:
final_groups.append({
"container": grouped_targets[arch]['container'],
"targets": targets,
"targets": comma_targets(all_targets),
"arch": arch,
"chip_family": "native",
"runner": runner,
"group": group_name,
"len": len(chunk),
"group": "voxl2-0",
"len": len(all_targets),
})
chunk_counter += 1
else:
# Non-NuttX groups (base, aarch64, armhf) - keep simple grouping
SPLIT_LIMIT = CHIP_SPLIT_LIMITS.get('native', DEFAULT_SPLIT_LIMIT)
all_targets = []
for man in grouped_targets[arch]['manufacturers']:
all_targets.extend(grouped_targets[arch]['manufacturers'][man])
if all_targets:
chunk_counter = 0
for chunk in chunks_merged(all_targets, SPLIT_LIMIT):
if len(all_targets) <= SPLIT_LIMIT:
group_name = f"{arch}-0"
else:
group_name = f"{arch}-{chunk_counter}"
final_groups.append({
"container": grouped_targets[arch]['container'],
"targets": comma_targets(chunk),
"arch": arch,
"chip_family": "native",
"runner": runner,
"group": group_name,
"len": len(chunk),
})
chunk_counter += 1
# Add cache_size to each group based on chip family
for g in final_groups:
g['cache_size'] = CHIP_CACHE_SIZES.get(g['chip_family'], DEFAULT_CACHE_SIZE)
if(verbose):
import pprint
print("================")
@@ -375,6 +596,58 @@ if (args.group):
print("= JSON output =")
print("===============")
print(json.dumps({ "include": final_groups }, **extra_args))
if args.seeders:
# Generate one seeder entry per chip family present in the groups.
# Each seeder builds a representative target to warm the ccache for
# all groups sharing that chip family.
seeder_targets = ci_config.get('seeders', {})
seeder_containers = {
'native': default_container,
}
# Determine which chip families actually have groups
active_families = set()
for g in final_groups:
cf = g['chip_family']
active_families.add(cf)
# voxl2 gets its own seeder with a different container
if g['group'].startswith('voxl2'):
active_families.add('voxl2')
seeders = []
for cf in sorted(active_families):
if cf == 'special':
continue # special group seeds from stm32h7
if cf == 'voxl2':
seeders.append({
'chip_family': 'voxl2',
'target': 'modalai_voxl2_default',
'container': voxl2_container,
'runner': 'x64',
})
elif cf == 'native':
# One seeder per runner arch that has native groups (exclude voxl2
# which has its own seeder with a different container)
native_runners = set()
for g in final_groups:
if g['chip_family'] == 'native' and not g['group'].startswith('voxl2'):
native_runners.add(g['runner'])
for r in sorted(native_runners):
seeders.append({
'chip_family': 'native',
'target': seeder_targets['native'],
'container': default_container,
'runner': r,
})
else:
seeders.append({
'chip_family': cf,
'target': seeder_targets.get(cf, seeder_targets['stm32h7']),
'container': seeder_containers.get(cf, default_container),
'runner': 'x64',
})
print(json.dumps({ "include": seeders }, **extra_args))
else:
print(json.dumps({ "include": final_groups }, **extra_args))
else:
print(json.dumps(github_action_config, **extra_args))
+288
View File
@@ -0,0 +1,288 @@
#!/usr/bin/env python3
"""
PR comment poster for analysis workflows.
This script is invoked from the `PR Comment Poster` workflow which runs on
`workflow_run` in the base repository context. It consumes a `pr-comment`
artifact produced by an upstream analysis job (clang-tidy, flash_analysis,
etc.) and posts or updates a sticky PR comment via the GitHub REST API.
Artifact contract (directory passed on the command line):
manifest.json
{
"pr_number": 12345, (required, int > 0)
"marker": "<!-- pr-comment-poster:flash-analysis -->", (required, printable ASCII)
"mode": "upsert" (optional, default "upsert")
}
body.md
Markdown comment body, posted verbatim. Must be non-empty and
<= 60000 bytes (GitHub's hard limit is 65535, we cap under).
Security: this script is run in a write-token context from a workflow that
MUST NOT check out PR code. Both manifest.json and body.md are treated as
opaque data. The marker is validated to printable ASCII only before use.
Subcommands:
validate <dir> Validate that <dir> contains a conforming manifest + body.
post <dir> Validate, then upsert a sticky comment on the target PR.
Requires env GITHUB_TOKEN and GITHUB_REPOSITORY.
Python stdlib only. No third-party dependencies.
"""
import argparse
import json
import os
import sys
import _github_helpers
from _github_helpers import fail as _fail
# GitHub hard limit is 65535 bytes. Cap well under to leave headroom for
# the appended marker line and any future wrapping.
MAX_BODY_BYTES = 60000
# Marker length bounds. 1..200 is plenty for an HTML comment tag such as
# "<!-- pr-comment-poster:flash-analysis -->".
MARKER_MIN_LEN = 1
MARKER_MAX_LEN = 200
ACCEPTED_MODES = ('upsert',)
USER_AGENT = 'px4-pr-comment-poster'
# ---------------------------------------------------------------------------
# Validation
# ---------------------------------------------------------------------------
def _is_printable_ascii(s):
# Space (0x20) through tilde (0x7E) inclusive.
return all(0x20 <= ord(ch) <= 0x7E for ch in s)
def validate_marker(marker):
"""Validate the marker string.
The marker is printable ASCII only and bounded in length. The original
shell implementation also rejected quotes, backticks, and backslashes
because the value flowed through jq and shell contexts. Now that Python
owns the handling (the value is only ever used as a substring match in
comment bodies and as a literal string in JSON request payloads that
urllib serialises for us) those characters are safe. We keep the
printable-ASCII and length rules as a belt-and-braces sanity check.
"""
if not isinstance(marker, str):
_fail('marker must be a string')
n = len(marker)
if n < MARKER_MIN_LEN or n > MARKER_MAX_LEN:
_fail('marker length out of range ({}..{}): {}'.format(
MARKER_MIN_LEN, MARKER_MAX_LEN, n))
if not _is_printable_ascii(marker):
_fail('marker contains non-printable or non-ASCII character')
def validate_manifest(directory):
"""Validate <directory>/manifest.json and <directory>/body.md.
Returns a dict with keys: pr_number (int), marker (str), mode (str),
body (str, verbatim contents of body.md).
"""
manifest_path = os.path.join(directory, 'manifest.json')
body_path = os.path.join(directory, 'body.md')
if not os.path.isfile(manifest_path):
_fail('manifest.json missing at {}'.format(manifest_path))
if not os.path.isfile(body_path):
_fail('body.md missing at {}'.format(body_path))
try:
with open(manifest_path, 'r', encoding='utf-8') as f:
manifest = json.load(f)
except (OSError, json.JSONDecodeError) as e:
_fail('manifest.json is not valid JSON: {}'.format(e))
if not isinstance(manifest, dict):
_fail('manifest.json must be a JSON object')
pr_number = manifest.get('pr_number')
# bool is a subclass of int in Python, so isinstance(True, int) is True.
# Reject bools explicitly so "true"/"false" in the manifest doesn't silently
# validate as 1/0 and then either fail upstream or poke the wrong PR.
if not isinstance(pr_number, int) or isinstance(pr_number, bool):
_fail('pr_number must be an integer')
if pr_number <= 0:
_fail('pr_number must be > 0 (got {})'.format(pr_number))
marker = manifest.get('marker')
validate_marker(marker)
mode = manifest.get('mode', 'upsert')
if mode not in ACCEPTED_MODES:
_fail('unsupported mode {!r} (accepted: {})'.format(
mode, ', '.join(ACCEPTED_MODES)))
# Read as bytes first so the size check is an honest byte count (matching
# GitHub's own 65535-byte comment limit) before we pay the cost of decoding.
try:
with open(body_path, 'rb') as f:
body_bytes = f.read()
except OSError as e:
_fail('could not read body.md: {}'.format(e))
if len(body_bytes) == 0:
_fail('body.md is empty')
if len(body_bytes) > MAX_BODY_BYTES:
_fail('body.md too large: {} bytes (max {})'.format(
len(body_bytes), MAX_BODY_BYTES))
# Require UTF-8 up front so a producer that wrote a garbage encoding fails
# here rather than later inside json.dumps with a less obvious traceback.
try:
body = body_bytes.decode('utf-8')
except UnicodeDecodeError as e:
_fail('body.md is not valid UTF-8: {}'.format(e))
return {
'pr_number': pr_number,
'marker': marker,
'mode': mode,
'body': body,
}
# ---------------------------------------------------------------------------
# Comment upsert
# ---------------------------------------------------------------------------
def find_existing_comment_id(client, repo, pr_number, marker):
"""Return the id of the first PR comment whose body contains marker, or None.
PR comments are issue comments in GitHub's data model, so we hit
/issues/{n}/comments rather than /pulls/{n}/comments (the latter only
returns review comments tied to specific code lines, which is not what
we want). The match is a plain substring check against the comment body;
the marker is expected to be an HTML comment that will not accidentally
appear in user-written prose.
"""
path = 'repos/{}/issues/{}/comments'.format(repo, pr_number)
for comment in client.paginated(path):
body = comment.get('body') or ''
if marker in body:
return comment.get('id')
return None
def build_final_body(body, marker):
"""Append the marker to body if not already present.
If the caller already embedded the marker (e.g. inside a hidden HTML
comment anywhere in their body) we leave the body alone; otherwise we
rstrip trailing newlines and append the marker on its own line after a
blank-line separator. Trailing-newline stripping keeps the output from
accumulating extra blank lines every time an existing comment is
re-rendered and re-posted.
"""
if marker in body:
return body
return '{}\n\n{}\n'.format(body.rstrip('\n'), marker)
def upsert_comment(client, repo, pr_number, marker, body):
final_body = build_final_body(body, marker)
existing_id = find_existing_comment_id(client, repo, pr_number, marker)
if existing_id is not None:
print('Updating comment {} on PR #{}'.format(existing_id, pr_number))
client.request(
'PATCH',
'repos/{}/issues/comments/{}'.format(repo, existing_id),
json_body={'body': final_body},
)
else:
print('Creating new comment on PR #{}'.format(pr_number))
client.request(
'POST',
'repos/{}/issues/{}/comments'.format(repo, pr_number),
json_body={'body': final_body},
)
# ---------------------------------------------------------------------------
# Entry points
# ---------------------------------------------------------------------------
def cmd_validate(args):
result = validate_manifest(args.directory)
print('ok: pr_number={} marker_len={} mode={} body_bytes={}'.format(
result['pr_number'],
len(result['marker']),
result['mode'],
len(result['body'].encode('utf-8')),
))
return 0
def cmd_post(args):
result = validate_manifest(args.directory)
# GITHUB_TOKEN is provided by the workflow via env; GITHUB_REPOSITORY is
# auto-set on every Actions runner. Both are required here because a local
# developer running the script directly won't have either unless they
# export them, and we want a clear error in that case.
token = os.environ.get('GITHUB_TOKEN')
if not token:
_fail('GITHUB_TOKEN is not set')
repo = os.environ.get('GITHUB_REPOSITORY')
if not repo:
_fail('GITHUB_REPOSITORY is not set (expected "owner/name")')
# Minimal shape check. If "owner/name" is malformed the subsequent API
# calls would 404 with an unhelpful URL. Fail fast here instead.
if '/' not in repo:
_fail('GITHUB_REPOSITORY must be "owner/name", got {!r}'.format(repo))
try:
client = _github_helpers.GitHubClient(token, user_agent=USER_AGENT)
upsert_comment(
client=client,
repo=repo,
pr_number=result['pr_number'],
marker=result['marker'],
body=result['body'],
)
except RuntimeError as e:
_fail(str(e))
return 0
def main(argv=None):
parser = argparse.ArgumentParser(
description='Validate and post sticky PR comments from CI artifacts.',
)
sub = parser.add_subparsers(dest='command', required=True)
p_validate = sub.add_parser(
'validate',
help='Validate manifest.json and body.md in the given directory.',
)
p_validate.add_argument('directory')
p_validate.set_defaults(func=cmd_validate)
p_post = sub.add_parser(
'post',
help='Validate, then upsert a sticky PR comment. Requires env '
'GITHUB_TOKEN and GITHUB_REPOSITORY.',
)
p_post.add_argument('directory')
p_post.set_defaults(func=cmd_post)
args = parser.parse_args(argv)
return args.func(args)
if __name__ == '__main__':
sys.exit(main())
+481
View File
@@ -0,0 +1,481 @@
#!/usr/bin/env python3
"""
PR review-comment poster for analysis workflows.
Sibling of Tools/ci/pr-comment-poster.py. Where pr-comment-poster.py posts
sticky issue-style PR comments, this script posts line-anchored review
comments on the "Files changed" tab. Use it for tools like clang-tidy that
want to flag specific lines instead of (or in addition to) a rollup
comment.
This script is invoked from the `PR Review Poster` workflow which runs on
`workflow_run` in the base repository context. It consumes a `pr-review`
artifact produced by an upstream analysis job and posts a fresh PR review
via the GitHub REST API, dismissing any stale review the same producer
left on a previous run.
Artifact contract (directory passed on the command line):
manifest.json
{
"pr_number": 12345, (required, int > 0)
"marker": "<!-- pr-review-poster:clang-tidy -->", (required, printable ASCII)
"event": "COMMENT", (required, "COMMENT" only)
"commit_sha": "0123456789abcdef0123456789abcdef01234567",(required, 40 hex chars)
"summary": "Optional review body text" (optional)
}
comments.json
JSON array of line-anchored review comment objects:
[
{"path": "src/foo.cpp", "line": 42, "side": "RIGHT",
"body": "..."},
{"path": "src/bar.hpp", "start_line": 10, "line": 15,
"side": "RIGHT", "start_side": "RIGHT", "body": "..."}
]
Note: `APPROVE` and `REQUEST_CHANGES` events are intentionally NOT
supported. Bots should never approve a pull request, and REQUEST_CHANGES
cannot be dismissed by the GITHUB_TOKEN when branch protection restricts
review dismissals, leading to undismissable spam on every push.
Security: this script is run in a write-token context from a workflow that
MUST NOT check out PR code. Both manifest.json and comments.json are
treated as opaque data. The marker is validated to printable ASCII only
before use, and only reviews authored by github-actions[bot] whose body
contains the marker can be dismissed (a fork cannot spoof either).
Subcommands:
validate <dir> Validate that <dir> contains a conforming manifest +
comments file.
post <dir> Validate, then dismiss any stale matching review and
post a new review on the target PR. Requires env
GITHUB_TOKEN and GITHUB_REPOSITORY.
Python stdlib only. No third-party dependencies.
"""
import argparse
import json
import os
import re
import sys
import time
import _github_helpers
from _github_helpers import fail as _fail
USER_AGENT = 'px4-pr-review-poster'
# Marker length bounds. 1..200 is plenty for an HTML comment tag such as
# "<!-- pr-review-poster:clang-tidy -->".
MARKER_MIN_LEN = 1
MARKER_MAX_LEN = 200
# Cap per-comment body size well under GitHub's hard limit so we leave
# headroom for the wrapping JSON envelope. Empirically GitHub allows ~65535
# bytes per review comment body; 60000 is a safe ceiling.
MAX_COMMENT_BODY_BYTES = 60000
# Cap on number of comments per single review POST. platisd uses 10. The
# value matters because GitHub's review-creation endpoint has a payload
# size limit and review comments occasionally trip an abuse-detection
# threshold when posted in very large batches. Smaller chunks also let us
# spread the work across multiple reviews so a single bad entry only
# fails its own chunk.
COMMENTS_PER_REVIEW = 10
# Sleep between successive review POSTs to stay clear of GitHub's
# secondary rate limits. platisd uses 10s; 5s is enough for our volume
# and cuts user-visible latency.
SLEEP_BETWEEN_CHUNKS_SECONDS = 5
ACCEPTED_EVENTS = ('COMMENT',)
ACCEPTED_SIDES = ('LEFT', 'RIGHT')
COMMIT_SHA_RE = re.compile(r'^[0-9a-f]{40}$')
# The login GitHub assigns to the built-in actions token. Used to filter
# the list of existing reviews so we never touch a human reviewer's review.
BOT_LOGIN = 'github-actions[bot]'
# ---------------------------------------------------------------------------
# Validation
# ---------------------------------------------------------------------------
def _is_printable_ascii(s):
return all(0x20 <= ord(ch) <= 0x7E for ch in s)
def validate_marker(marker):
"""Validate the marker string. See pr-comment-poster.py for rationale."""
if not isinstance(marker, str):
_fail('marker must be a string')
n = len(marker)
if n < MARKER_MIN_LEN or n > MARKER_MAX_LEN:
_fail('marker length out of range ({}..{}): {}'.format(
MARKER_MIN_LEN, MARKER_MAX_LEN, n))
if not _is_printable_ascii(marker):
_fail('marker contains non-printable or non-ASCII character')
def _validate_comment_entry(idx, entry):
"""Validate a single review-comment entry. Raises via _fail on error."""
if not isinstance(entry, dict):
_fail('comments[{}]: must be an object'.format(idx))
path = entry.get('path')
if not isinstance(path, str) or not path:
_fail('comments[{}].path: required non-empty string'.format(idx))
line = entry.get('line')
if not isinstance(line, int) or isinstance(line, bool) or line <= 0:
_fail('comments[{}].line: required positive integer'.format(idx))
side = entry.get('side', 'RIGHT')
if side not in ACCEPTED_SIDES:
_fail('comments[{}].side: must be one of {} (got {!r})'.format(
idx, ', '.join(ACCEPTED_SIDES), side))
if 'start_line' in entry:
start_line = entry['start_line']
if (not isinstance(start_line, int)
or isinstance(start_line, bool)
or start_line <= 0):
_fail('comments[{}].start_line: must be positive integer'.format(idx))
if start_line >= line:
_fail('comments[{}].start_line ({}) must be < line ({})'.format(
idx, start_line, line))
start_side = entry.get('start_side', side)
if start_side not in ACCEPTED_SIDES:
_fail('comments[{}].start_side: must be one of {}'.format(
idx, ', '.join(ACCEPTED_SIDES)))
body = entry.get('body')
if not isinstance(body, str) or not body:
_fail('comments[{}].body: required non-empty string'.format(idx))
body_bytes = len(body.encode('utf-8'))
if body_bytes > MAX_COMMENT_BODY_BYTES:
_fail('comments[{}].body too large: {} bytes (max {})'.format(
idx, body_bytes, MAX_COMMENT_BODY_BYTES))
def validate_manifest(directory):
"""Validate <directory>/manifest.json and <directory>/comments.json.
Returns a dict with keys: pr_number, marker, event, commit_sha,
summary, comments (list of validated comment dicts).
"""
manifest_path = os.path.join(directory, 'manifest.json')
comments_path = os.path.join(directory, 'comments.json')
if not os.path.isfile(manifest_path):
_fail('manifest.json missing at {}'.format(manifest_path))
if not os.path.isfile(comments_path):
_fail('comments.json missing at {}'.format(comments_path))
try:
with open(manifest_path, 'r', encoding='utf-8') as f:
manifest = json.load(f)
except (OSError, json.JSONDecodeError) as e:
_fail('manifest.json is not valid JSON: {}'.format(e))
if not isinstance(manifest, dict):
_fail('manifest.json must be a JSON object')
pr_number = manifest.get('pr_number')
if not isinstance(pr_number, int) or isinstance(pr_number, bool):
_fail('pr_number must be an integer')
if pr_number <= 0:
_fail('pr_number must be > 0 (got {})'.format(pr_number))
marker = manifest.get('marker')
validate_marker(marker)
event = manifest.get('event')
if event not in ACCEPTED_EVENTS:
_fail('event must be one of {} (got {!r}). APPROVE and '
'REQUEST_CHANGES are intentionally forbidden.'.format(
', '.join(ACCEPTED_EVENTS), event))
commit_sha = manifest.get('commit_sha')
if not isinstance(commit_sha, str) or not COMMIT_SHA_RE.match(commit_sha):
_fail('commit_sha must be a 40-character lowercase hex string')
summary = manifest.get('summary', '')
if summary is None:
summary = ''
if not isinstance(summary, str):
_fail('summary must be a string if present')
try:
with open(comments_path, 'r', encoding='utf-8') as f:
comments = json.load(f)
except (OSError, json.JSONDecodeError) as e:
_fail('comments.json is not valid JSON: {}'.format(e))
if not isinstance(comments, list):
_fail('comments.json must be a JSON array')
for idx, entry in enumerate(comments):
_validate_comment_entry(idx, entry)
return {
'pr_number': pr_number,
'marker': marker,
'event': event,
'commit_sha': commit_sha,
'summary': summary,
'comments': comments,
}
# ---------------------------------------------------------------------------
# Stale-review dismissal
# ---------------------------------------------------------------------------
def find_stale_reviews(client, repo, pr_number, marker):
"""Yield (id, state) for each existing review owned by the bot AND
whose body contains the marker.
Filtering on BOTH author == github-actions[bot] AND marker-in-body is
the security invariant: a fork PR cannot impersonate the bot login,
and a fork PR also cannot inject the marker into a human reviewer's
body without API access.
"""
path = 'repos/{}/pulls/{}/reviews'.format(repo, pr_number)
for review in client.paginated(path):
user = review.get('user') or {}
if user.get('login') != BOT_LOGIN:
continue
body = review.get('body') or ''
if marker not in body:
continue
yield review.get('id'), review.get('state')
def dismiss_stale_reviews(client, repo, pr_number, marker):
"""Dismiss (or, for PENDING reviews, delete) every stale matching review.
Returns the number of reviews that could NOT be dismissed (still active).
"""
dismissal_message = 'Superseded by a newer run'
failed_dismissals = 0
for review_id, state in find_stale_reviews(client, repo, pr_number, marker):
if review_id is None:
continue
if state in ('DISMISSED', 'COMMENTED'):
# Already inert or non-blocking; nothing to do.
continue
if state == 'PENDING':
# PENDING reviews cannot be dismissed; they must be deleted.
print('Deleting pending stale review {}'.format(review_id))
try:
client.request(
'DELETE',
'repos/{}/pulls/{}/reviews/{}'.format(
repo, pr_number, review_id))
except RuntimeError as e:
failed_dismissals += 1
print('warning: failed to delete pending review {}: {}'.format(
review_id, e), file=sys.stderr)
continue
print('Dismissing stale review {} (state={})'.format(review_id, state))
try:
client.request(
'PUT',
'repos/{}/pulls/{}/reviews/{}/dismissals'.format(
repo, pr_number, review_id),
json_body={
'message': dismissal_message,
'event': 'DISMISS',
},
)
except RuntimeError as e:
failed_dismissals += 1
print('warning: failed to dismiss review {}: {}'.format(
review_id, e), file=sys.stderr)
return failed_dismissals
# ---------------------------------------------------------------------------
# Review posting
# ---------------------------------------------------------------------------
def _chunk(lst, n):
"""Yield successive n-sized slices of lst."""
for i in range(0, len(lst), n):
yield lst[i:i + n]
def _build_review_body(marker, summary, chunk_index, chunk_total):
"""Construct the review body text.
Always begins with the marker (so future runs can find and dismiss
this review). Appends a chunk index when the comment set is split
across multiple reviews, and the producer-supplied summary if any.
"""
parts = [marker]
if chunk_total > 1:
parts.append('({}/{})'.format(chunk_index + 1, chunk_total))
if summary:
parts.append('')
parts.append(summary)
return '\n'.join(parts)
def _comment_to_api(entry):
"""Project a validated comment dict to the GitHub API shape."""
api = {
'path': entry['path'],
'line': entry['line'],
'side': entry.get('side', 'RIGHT'),
'body': entry['body'],
}
if 'start_line' in entry:
api['start_line'] = entry['start_line']
api['start_side'] = entry.get('start_side', api['side'])
return api
def post_review(client, repo, pr_number, marker, event, commit_sha, summary,
comments):
"""Post one or more reviews containing the validated comments.
Comments are split into COMMENTS_PER_REVIEW-sized chunks. Each chunk
becomes its own review POST. A failed chunk logs a warning and the
loop continues to the next chunk.
"""
chunks = list(_chunk(comments, COMMENTS_PER_REVIEW))
total = len(chunks)
if total == 0:
print('No comments to post; skipping review creation.')
return
posted_any = False
for idx, chunk in enumerate(chunks):
if idx > 0:
time.sleep(SLEEP_BETWEEN_CHUNKS_SECONDS)
body = _build_review_body(marker, summary, idx, total)
payload = {
'commit_id': commit_sha,
'body': body,
'event': event,
'comments': [_comment_to_api(c) for c in chunk],
}
print('Posting review chunk {}/{} with {} comment(s)'.format(
idx + 1, total, len(chunk)))
try:
client.request(
'POST',
'repos/{}/pulls/{}/reviews'.format(repo, pr_number),
json_body=payload,
)
posted_any = True
except RuntimeError as e:
# Most common cause is HTTP 422: a comment refers to a line
# GitHub does not consider part of the diff. Skip the bad
# chunk and keep going so other findings still get posted.
print('warning: review chunk {}/{} failed: {}'.format(
idx + 1, total, e), file=sys.stderr)
if not posted_any:
# If every single chunk failed, surface that as a hard error so
# the workflow turns red and a human looks at it.
_fail('all review chunks failed to post; see warnings above')
# ---------------------------------------------------------------------------
# Entry points
# ---------------------------------------------------------------------------
def cmd_validate(args):
result = validate_manifest(args.directory)
print(('ok: pr_number={} marker_len={} event={} commit_sha={} '
'comments={} summary_len={}').format(
result['pr_number'],
len(result['marker']),
result['event'],
result['commit_sha'],
len(result['comments']),
len(result['summary']),
))
return 0
def cmd_post(args):
result = validate_manifest(args.directory)
# Empty comment lists short-circuit silently. A producer that ran but
# found nothing to flag should not generate noise on the PR.
if len(result['comments']) == 0:
print('No comments in artifact; nothing to post.')
return 0
token = os.environ.get('GITHUB_TOKEN')
if not token:
_fail('GITHUB_TOKEN is not set')
repo = os.environ.get('GITHUB_REPOSITORY')
if not repo:
_fail('GITHUB_REPOSITORY is not set (expected "owner/name")')
if '/' not in repo:
_fail('GITHUB_REPOSITORY must be "owner/name", got {!r}'.format(repo))
try:
client = _github_helpers.GitHubClient(token, user_agent=USER_AGENT)
undismissed = dismiss_stale_reviews(
client=client,
repo=repo,
pr_number=result['pr_number'],
marker=result['marker'],
)
if undismissed > 0:
print('{} prior review(s) could not be dismissed (likely '
'branch protection).'.format(undismissed))
post_review(
client=client,
repo=repo,
pr_number=result['pr_number'],
marker=result['marker'],
event=result['event'],
commit_sha=result['commit_sha'],
summary=result['summary'],
comments=result['comments'],
)
except RuntimeError as e:
_fail(str(e))
return 0
def main(argv=None):
parser = argparse.ArgumentParser(
description='Validate and post line-anchored PR review comments '
'from CI artifacts.',
)
sub = parser.add_subparsers(dest='command', required=True)
p_validate = sub.add_parser(
'validate',
help='Validate manifest.json and comments.json in the given directory.',
)
p_validate.add_argument('directory')
p_validate.set_defaults(func=cmd_validate)
p_post = sub.add_parser(
'post',
help='Validate, then dismiss any stale review and post a new one. '
'Requires env GITHUB_TOKEN and GITHUB_REPOSITORY.',
)
p_post.add_argument('directory')
p_post.set_defaults(func=cmd_post)
args = parser.parse_args(argv)
return args.func(args)
if __name__ == '__main__':
sys.exit(main())
+147
View File
@@ -0,0 +1,147 @@
#!/usr/bin/env python3
"""
Run clang-tidy incrementally on files changed in a PR.
Usage: run-clang-tidy-pr.py <base-ref>
base-ref: e.g. origin/main
Computes the set of translation units (TUs) affected by the PR diff,
then invokes Tools/run-clang-tidy.py on that subset only.
Exits 0 silently when no C++ files were changed.
"""
import argparse
import json
import os
import subprocess
import sys
EXTENSIONS_CPP = {'.cpp', '.c'}
EXTENSIONS_HDR = {'.hpp', '.h'}
# Manual exclusions from Makefile:508
EXCLUDE_EXTRA = '|'.join([
'src/systemcmds/tests',
'src/examples',
'src/modules/gyro_fft/CMSIS_5',
'src/lib/drivers/smbus',
'src/drivers/gpio',
r'src/modules/commander/failsafe/emscripten',
r'failsafe_test\.dir',
])
def repo_root():
try:
return subprocess.check_output(
['git', 'rev-parse', '--show-toplevel'], text=True).strip()
except subprocess.CalledProcessError:
print('error: not inside a git repository', file=sys.stderr)
sys.exit(1)
def changed_files(base_ref, root):
try:
out = subprocess.check_output(
['git', 'diff', '--name-only', f'{base_ref}...HEAD',
'--', '*.cpp', '*.hpp', '*.h', '*.c'],
text=True, cwd=root).strip()
return out.splitlines() if out else []
except subprocess.CalledProcessError:
print(f'error: could not diff against "{base_ref}"'
'is the ref valid and fetched?', file=sys.stderr)
sys.exit(1)
def submodule_paths(root):
# Returns [] if .gitmodules is absent or has no paths — both valid
try:
out = subprocess.check_output(
['git', 'config', '--file', '.gitmodules',
'--get-regexp', 'path'],
text=True, cwd=root).strip()
return [line.split()[1] for line in out.splitlines()]
except subprocess.CalledProcessError:
return []
def build_exclude(root):
submodules = '|'.join(submodule_paths(root))
return f'{submodules}|{EXCLUDE_EXTRA}' if submodules else EXCLUDE_EXTRA
def load_db(build_dir):
db_path = os.path.join(build_dir, 'compile_commands.json')
if not os.path.isfile(db_path):
print(f'error: {db_path} not found', file=sys.stderr)
print('Run "make px4_sitl_default-clang" first to generate '
'the compilation database', file=sys.stderr)
sys.exit(1)
try:
with open(db_path) as f:
return json.load(f)
except json.JSONDecodeError as e:
print(f'error: compile_commands.json is malformed: {e}', file=sys.stderr)
sys.exit(1)
def find_tus(changed, db, root):
db_files = {e['file'] for e in db}
result = set()
for f in changed:
abs_path = os.path.join(root, f)
ext = os.path.splitext(f)[1]
if ext in EXTENSIONS_CPP:
if abs_path in db_files:
result.add(abs_path)
elif ext in EXTENSIONS_HDR:
hdr = os.path.basename(f)
for e in db:
try:
if hdr in open(e['file']).read():
result.add(e['file'])
except OSError:
pass # file deleted in PR — skip
return sorted(result)
def main():
parser = argparse.ArgumentParser(description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('base_ref',
help='Git ref to diff against, e.g. origin/main')
args = parser.parse_args()
root = repo_root()
build_dir = os.path.join(root, 'build', 'px4_sitl_default-clang')
run_tidy = os.path.join(root, 'Tools', 'run-clang-tidy.py')
if not os.path.isfile(run_tidy):
print(f'error: {run_tidy} not found', file=sys.stderr)
sys.exit(1)
changed = changed_files(args.base_ref, root)
if not changed:
print('No C++ files changed — skipping clang-tidy')
sys.exit(0)
db = load_db(build_dir)
tus = find_tus(changed, db, root)
if not tus:
print('No matching TUs in compile_commands.json — skipping clang-tidy')
sys.exit(0)
print(f'Running clang-tidy on {len(tus)} translation unit(s)')
result = subprocess.run(
[sys.executable, run_tidy,
'-header-filter=.*\\.hpp',
'-j0',
f'-exclude={build_exclude(root)}',
'-p', build_dir] + tus
)
sys.exit(result.returncode)
if __name__ == '__main__':
main()
+3 -1
View File
@@ -10,6 +10,7 @@ CONFIG_BOARD_SERIAL_EXT2="/dev/ttyS3"
CONFIG_DRIVERS_ADC_ADS1115=y
CONFIG_DRIVERS_ADC_BOARD_ADC=y
CONFIG_DRIVERS_BAROMETER_BMP388=y
CONFIG_DRIVERS_BAROMETER_DPS310=y
CONFIG_DRIVERS_BAROMETER_INVENSENSE_ICP201XX=y
CONFIG_DRIVERS_BAROMETER_MS5611=y
CONFIG_DRIVERS_CAMERA_CAPTURE=y
@@ -47,6 +48,7 @@ CONFIG_MODULES_CAMERA_FEEDBACK=y
CONFIG_MODULES_COMMANDER=y
CONFIG_MODULES_CONTROL_ALLOCATOR=y
CONFIG_MODULES_DATAMAN=y
CONFIG_NUM_MISSION_ITMES_SUPPORTED=1000
CONFIG_MODULES_EKF2=y
CONFIG_MODULES_ESC_BATTERY=y
CONFIG_MODULES_EVENTS=y
@@ -73,7 +75,6 @@ CONFIG_MODULES_MC_POS_CONTROL=y
CONFIG_MODULES_MC_RATE_CONTROL=y
CONFIG_MODULES_NAVIGATOR=y
CONFIG_MODE_NAVIGATOR_VTOL_TAKEOFF=y
CONFIG_NUM_MISSION_ITMES_SUPPORTED=1000
CONFIG_MODULES_RC_UPDATE=y
CONFIG_MODULES_SENSORS=y
CONFIG_MODULES_TEMPERATURE_COMPENSATION=y
@@ -101,3 +102,4 @@ CONFIG_SYSTEMCMDS_TUNE_CONTROL=y
CONFIG_SYSTEMCMDS_UORB=y
CONFIG_SYSTEMCMDS_VER=y
CONFIG_SYSTEMCMDS_WORK_QUEUE=y
CONFIG_ARCH_CHIP_STM32H7=y
@@ -83,10 +83,12 @@ ist8310 -X -b 1 -R 10 start
if param compare SENS_INT_BARO_EN 1
then
icp201xx -I -a 0x64 start
dps310 -I start
fi
#external baro
icp201xx -X start
dps310 -X start
unset INA_CONFIGURED
unset HAVE_PM2
@@ -34,8 +34,5 @@ nshterm /dev/ttyS3 &
# Start the time_persistor to cyclically store the RTC in FRAM
time_persistor start
# Start the task_watchdog as we do not have the logger watchdog
task_watchdog start
# Start the ESC telemetry
dshot telemetry -d /dev/ttyS5 -x
@@ -0,0 +1,19 @@
#!/bin/sh
#
# Board early init.
#
# On FRAM boards STORAGE_AVAILABLE=yes will set the USE_* flags. Additional
# enable required for task watchdog as this is not a generally used feature.
# On EEPROM boards: Only airframes and params are needed.
#
if mft query -q -k MTD -s MTD_PARAMETERS -v /mnt/microsd
then
# Start the task_watchdog as we do not have the logger watchdog
set USE_TASK_WATCHDOG yes
else
set PARAM_FILE /fs/microsd/params
set STORAGE_CHECK no
set USE_EXTERNAL_AIRFRAMES yes
set USE_ALT_UPDATE_DIRS yes
fi
@@ -287,8 +287,8 @@
/* AUX */
#define GPIO_LPUART4_RX (GPIO_LPUART4_RX_3 | LPUART_IOMUX) /* GPIO_B1_01 */
#define GPIO_LPUART4_TX (GPIO_LPUART4_TX_3 | LPUART_IOMUX) /* GPIO_B1_00 */
#define GPIO_LPUART4_RX (GPIO_LPUART4_RX_1 | LPUART_IOMUX) /* GPIO_B1_01 */
#define GPIO_LPUART4_TX (GPIO_LPUART4_TX_1 | LPUART_IOMUX) /* GPIO_B1_00 */
/* GPS 1 */
@@ -1,32 +1,42 @@
CONFIG_BOARD_TOOLCHAIN="arm-none-eabi"
CONFIG_BOARD_ARCHITECTURE="cortex-m7"
CONFIG_BOARD_SERIAL_GPS1="/dev/ttyS0"
CONFIG_BOARD_ARCHITECTURE="cortex-m4"
CONFIG_BOARD_CONSTRAINED_MEMORY=y
CONFIG_BOARD_SERIAL_GPS1="/dev/ttyS3"
CONFIG_BOARD_SERIAL_TEL1="/dev/ttyS1"
CONFIG_BOARD_SERIAL_TEL2="/dev/ttyS3"
CONFIG_BOARD_SERIAL_TEL3="/dev/ttyS5"
CONFIG_BOARD_SERIAL_TEL4="/dev/ttyS7"
CONFIG_BOARD_SERIAL_RC="/dev/ttyS4"
CONFIG_BOARD_SERIAL_EXT2="/dev/ttyS2"
CONFIG_BOARD_SERIAL_TEL2="/dev/ttyS2"
CONFIG_DRIVERS_ADC_ADS1115=y
CONFIG_DRIVERS_ADC_BOARD_ADC=y
CONFIG_DRIVERS_BAROMETER_DPS310=y
CONFIG_COMMON_BAROMETERS=y
CONFIG_DRIVERS_BATT_SMBUS=y
CONFIG_DRIVERS_CAMERA_CAPTURE=y
CONFIG_DRIVERS_CAMERA_TRIGGER=y
CONFIG_DRIVERS_CDCACM_AUTOSTART=y
CONFIG_COMMON_DIFFERENTIAL_PRESSURE=y
CONFIG_DRIVERS_DISTANCE_SENSOR_TF02PRO=y
CONFIG_DRIVERS_DISTANCE_SENSOR_TFMINI=y
CONFIG_DRIVERS_DSHOT=y
CONFIG_COMMON_DISTANCE_SENSOR=y
CONFIG_DRIVERS_GPS=y
CONFIG_DRIVERS_IMU_BOSCH_BMI088=y
CONFIG_DRIVERS_IMU_INVENSENSE_ICM42688P=y
CONFIG_DRIVERS_MAGNETOMETER_ISENTEK_IST8310=y
CONFIG_DRIVERS_MAGNETOMETER_QMC5883L=y
CONFIG_DRIVERS_IMU_INVENSENSE_ICM20948=y
CONFIG_DRIVERS_IMU_INVENSENSE_MPU6000=y
CONFIG_DRIVERS_IMU_INVENSENSE_MPU6500=y
CONFIG_DRIVERS_IMU_ST_L3GD20=y
CONFIG_DRIVERS_IMU_ST_LSM303D=y
CONFIG_DRIVERS_IMU_INVENSENSE_ICM20602=y
CONFIG_DRIVERS_IMU_INVENSENSE_MPU9250=y
CONFIG_DRIVERS_IRLOCK=y
CONFIG_COMMON_LIGHT=y
CONFIG_COMMON_MAGNETOMETER=y
CONFIG_DRIVERS_MAGNETOMETER_LIS3MDL=y
CONFIG_DRIVERS_PCA9685_PWM_OUT=y
CONFIG_DRIVERS_POWER_MONITOR_INA226=y
CONFIG_DRIVERS_PWM_INPUT=y
CONFIG_DRIVERS_PWM_OUT=y
CONFIG_DRIVERS_RC_INPUT=y
CONFIG_DRIVERS_SMART_BATTERY_BATMON=y
CONFIG_COMMON_TELEMETRY=y
CONFIG_DRIVERS_TONE_ALARM=y
CONFIG_DRIVERS_UAVCAN=y
CONFIG_BOARD_UAVCAN_INTERFACES=1
CONFIG_MODULES_AIRSPEED_SELECTOR=y
CONFIG_MODULES_ATTITUDE_ESTIMATOR_Q=y
CONFIG_MODULES_BATTERY_STATUS=y
CONFIG_MODULES_CAMERA_FEEDBACK=y
CONFIG_MODULES_COMMANDER=y
@@ -38,8 +48,8 @@ CONFIG_MODULES_EVENTS=y
CONFIG_MODULES_FLIGHT_MODE_MANAGER=y
CONFIG_MODULES_FW_ATT_CONTROL=y
CONFIG_MODULES_FW_AUTOTUNE_ATTITUDE_CONTROL=y
CONFIG_MODULES_FW_LATERAL_LONGITUDINAL_CONTROL=y
CONFIG_MODULES_FW_MODE_MANAGER=y
CONFIG_MODULES_FW_LATERAL_LONGITUDINAL_CONTROL=y
CONFIG_MODULES_FW_RATE_CONTROL=y
CONFIG_MODULES_GIMBAL=y
CONFIG_MODULES_GYRO_CALIBRATION=y
@@ -60,11 +70,14 @@ CONFIG_MODULES_MC_RATE_CONTROL=y
CONFIG_MODULES_NAVIGATOR=y
CONFIG_MODULES_RC_UPDATE=y
CONFIG_MODULES_SENSORS=y
CONFIG_MODULES_SIMULATION_SIMULATOR_SIH=y
CONFIG_MODULES_TEMPERATURE_COMPENSATION=y
CONFIG_MODULES_UUV_ATT_CONTROL=y
CONFIG_MODULES_UUV_POS_CONTROL=y
CONFIG_MODULES_VTOL_ATT_CONTROL=y
CONFIG_SYSTEMCMDS_ACTUATOR_TEST=y
CONFIG_SYSTEMCMDS_BL_UPDATE=y
CONFIG_SYSTEMCMDS_DMESG=y
CONFIG_SYSTEMCMDS_BSONDUMP=y
CONFIG_SYSTEMCMDS_DUMPFILE=y
CONFIG_SYSTEMCMDS_GPIO=y
CONFIG_SYSTEMCMDS_HARDFAULT_LOG=y
@@ -76,8 +89,10 @@ CONFIG_SYSTEMCMDS_NSHTERM=y
CONFIG_SYSTEMCMDS_PARAM=y
CONFIG_SYSTEMCMDS_PERF=y
CONFIG_SYSTEMCMDS_REBOOT=y
CONFIG_SYSTEMCMDS_REFLECT=y
CONFIG_SYSTEMCMDS_SD_BENCH=y
CONFIG_SYSTEMCMDS_SD_STRESS=y
CONFIG_SYSTEMCMDS_SERIAL_TEST=y
CONFIG_SYSTEMCMDS_SYSTEM_TIME=y
CONFIG_SYSTEMCMDS_TOP=y
CONFIG_SYSTEMCMDS_TOPIC_LISTENER=y
@@ -87,3 +102,6 @@ CONFIG_SYSTEMCMDS_USB_CONNECTED=y
CONFIG_SYSTEMCMDS_VER=y
CONFIG_SYSTEMCMDS_WORK_QUEUE=y
CONFIG_EXAMPLES_FAKE_GPS=y
CONFIG_BOARD_VENDOR="saam"
CONFIG_BOARD_MODEL="saampixv1_1"
CONFIG_BOARD_NAME="SaamPixV1_1"
@@ -0,0 +1,13 @@
{
"board_id": 1,
"magic": "PX4FWv1",
"description": "Firmware for the SaamPixV1_1 board",
"image": "",
"build_time": 0,
"summary": "SaamPixV1_1",
"version": "1.1",
"image_size": 0,
"image_maxsize": 2080768,
"git_identity": "",
"board_revision": 0
}
@@ -0,0 +1,7 @@
#!/bin/sh
#
# board specific defaults
#------------------------------------------------------------------------------
param set-default BAT1_V_DIV 10.1
param set-default BAT1_A_PER_V 17.0
+16
View File
@@ -0,0 +1,16 @@
#!/bin/sh
#
# SaamPixV1_1 specific board sensors init
#------------------------------------------------------------------------------
board_adc start
# external I2C compasses, if present
hmc5883 -X start
qmc5883l -X start
# internal SPI sensors
ms5611 -s start
icm20602 -s start
mpu9250 -s start
lis3mdl -s start
@@ -0,0 +1,271 @@
/************************************************************************************
* boards/saam/saampixv1_1/nuttx-config/include/board.h
* include/arch/board/board.h
*
* Copyright (C) 2009 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
************************************************************************************/
#ifndef __ARCH_BOARD_BOARD_H
#define __ARCH_BOARD_BOARD_H
/************************************************************************************
* Included Files
************************************************************************************/
#include "board_dma_map.h"
#include <nuttx/config.h>
#ifndef __ASSEMBLY__
# include <stdint.h>
#endif
#include <stm32.h>
/************************************************************************************
* Definitions
************************************************************************************/
/* Clocking *************************************************************************/
/* The SaamPixV1_1 uses a 8MHz crystal connected to the HSE.
*
* This is the "standard" configuration as set up by arch/arm/src/stm32f40xx_rcc.c:
* System Clock source : PLL (HSE)
* SYSCLK(Hz) : 168000000 Determined by PLL configuration
* HCLK(Hz) : 168000000 (STM32_RCC_CFGR_HPRE)
* AHB Prescaler : 1 (STM32_RCC_CFGR_HPRE)
* APB1 Prescaler : 4 (STM32_RCC_CFGR_PPRE1)
* APB2 Prescaler : 2 (STM32_RCC_CFGR_PPRE2)
* HSE Frequency(Hz) : 8000000 (STM32_BOARD_XTAL)
* PLLM : 8 (STM32_PLLCFG_PLLM)
* PLLN : 336 (STM32_PLLCFG_PLLN)
* PLLP : 2 (STM32_PLLCFG_PLLP)
* PLLQ : 7 (STM32_PLLCFG_PPQ)
* Main regulator output voltage : Scale1 mode Needed for high speed SYSCLK
* Flash Latency(WS) : 5
* Prefetch Buffer : OFF
* Instruction cache : ON
* Data cache : ON
* Require 48MHz for USB OTG FS, : Enabled
* SDIO and RNG clock
*/
/* HSI - 16 MHz RC factory-trimmed
* LSI - 32 KHz RC
* HSE - On-board crystal frequency is 8MHz
* LSE - not installed
*/
#define STM32_BOARD_XTAL 8000000ul
#define STM32_HSI_FREQUENCY 16000000ul
#define STM32_LSI_FREQUENCY 32000
#define STM32_HSE_FREQUENCY STM32_BOARD_XTAL
//#define STM32_LSE_FREQUENCY 32768
/* Main PLL Configuration.
*
* PLL source is HSE
* PLL_VCO = (STM32_HSE_FREQUENCY / PLLM) * PLLN
* = (8,000,000 / 8) * 336
* = 336,000,000
* SYSCLK = PLL_VCO / PLLP
* = 336,000,000 / 2 = 168,000,000
* USB OTG FS, SDIO and RNG Clock
* = PLL_VCO / PLLQ
* = 48,000,000
*/
#define STM32_PLLCFG_PLLM RCC_PLLCFG_PLLM(8)
#define STM32_PLLCFG_PLLN RCC_PLLCFG_PLLN(336)
#define STM32_PLLCFG_PLLP RCC_PLLCFG_PLLP_2
#define STM32_PLLCFG_PLLQ RCC_PLLCFG_PLLQ(7)
#define STM32_SYSCLK_FREQUENCY 168000000ul
/* AHB clock (HCLK) is SYSCLK (168MHz) */
#define STM32_RCC_CFGR_HPRE RCC_CFGR_HPRE_SYSCLK /* HCLK = SYSCLK / 1 */
#define STM32_HCLK_FREQUENCY STM32_SYSCLK_FREQUENCY
#define STM32_BOARD_HCLK STM32_HCLK_FREQUENCY /* same as above, to satisfy compiler */
/* APB1 clock (PCLK1) is HCLK/4 (42MHz) */
#define STM32_RCC_CFGR_PPRE1 RCC_CFGR_PPRE1_HCLKd4 /* PCLK1 = HCLK / 4 */
#define STM32_PCLK1_FREQUENCY (STM32_HCLK_FREQUENCY/4)
/* Timers driven from APB1 will be twice PCLK1 */
#define STM32_APB1_TIM2_CLKIN (2*STM32_PCLK1_FREQUENCY)
#define STM32_APB1_TIM3_CLKIN (2*STM32_PCLK1_FREQUENCY)
#define STM32_APB1_TIM4_CLKIN (2*STM32_PCLK1_FREQUENCY)
#define STM32_APB1_TIM5_CLKIN (2*STM32_PCLK1_FREQUENCY)
#define STM32_APB1_TIM6_CLKIN (2*STM32_PCLK1_FREQUENCY)
#define STM32_APB1_TIM7_CLKIN (2*STM32_PCLK1_FREQUENCY)
#define STM32_APB1_TIM12_CLKIN (2*STM32_PCLK1_FREQUENCY)
#define STM32_APB1_TIM13_CLKIN (2*STM32_PCLK1_FREQUENCY)
#define STM32_APB1_TIM14_CLKIN (2*STM32_PCLK1_FREQUENCY)
/* APB2 clock (PCLK2) is HCLK/2 (84MHz) */
#define STM32_RCC_CFGR_PPRE2 RCC_CFGR_PPRE2_HCLKd2 /* PCLK2 = HCLK / 2 */
#define STM32_PCLK2_FREQUENCY (STM32_HCLK_FREQUENCY/2)
/* Timers driven from APB2 will be twice PCLK2 */
#define STM32_APB2_TIM1_CLKIN (2*STM32_PCLK2_FREQUENCY)
#define STM32_APB2_TIM8_CLKIN (2*STM32_PCLK2_FREQUENCY)
#define STM32_APB2_TIM9_CLKIN (2*STM32_PCLK2_FREQUENCY)
#define STM32_APB2_TIM10_CLKIN (2*STM32_PCLK2_FREQUENCY)
#define STM32_APB2_TIM11_CLKIN (2*STM32_PCLK2_FREQUENCY)
/* Timer Frequencies, if APBx is set to 1, frequency is same to APBx
* otherwise frequency is 2xAPBx.
* Note: TIM1,8-11 are on APB2, others on APB1
*/
#define BOARD_TIM1_FREQUENCY STM32_APB2_TIM1_CLKIN
#define BOARD_TIM2_FREQUENCY STM32_APB1_TIM2_CLKIN
#define BOARD_TIM3_FREQUENCY STM32_APB1_TIM3_CLKIN
#define BOARD_TIM4_FREQUENCY STM32_APB1_TIM4_CLKIN
#define BOARD_TIM5_FREQUENCY STM32_APB1_TIM5_CLKIN
#define BOARD_TIM6_FREQUENCY STM32_APB1_TIM6_CLKIN
#define BOARD_TIM7_FREQUENCY STM32_APB1_TIM7_CLKIN
#define BOARD_TIM8_FREQUENCY STM32_APB2_TIM8_CLKIN
#define BOARD_TIM9_FREQUENCY STM32_APB2_TIM9_CLKIN
#define BOARD_TIM10_FREQUENCY STM32_APB2_TIM10_CLKIN
#define BOARD_TIM11_FREQUENCY STM32_APB2_TIM11_CLKIN
#define BOARD_TIM12_FREQUENCY STM32_APB1_TIM12_CLKIN
#define BOARD_TIM13_FREQUENCY STM32_APB1_TIM13_CLKIN
#define BOARD_TIM14_FREQUENCY STM32_APB1_TIM14_CLKIN
/* SDIO dividers. Note that slower clocking is required when DMA is disabled
* in order to avoid RX overrun/TX underrun errors due to delayed responses
* to service FIFOs in interrupt driven mode. These values have not been
* tuned!!!
*
* SDIOCLK=48MHz, SDIO_CK=SDIOCLK/(118+2)=400 KHz
*/
#define SDIO_INIT_CLKDIV (118 << SDIO_CLKCR_CLKDIV_SHIFT)
/* DMA ON: SDIOCLK=48MHz, SDIO_CK=SDIOCLK/(1+2)=16 MHz
* DMA OFF: SDIOCLK=48MHz, SDIO_CK=SDIOCLK/(2+2)=12 MHz
*/
#ifdef CONFIG_STM32_SDIO_DMA
# define SDIO_MMCXFR_CLKDIV (1 << SDIO_CLKCR_CLKDIV_SHIFT)
#else
# define SDIO_MMCXFR_CLKDIV (2 << SDIO_CLKCR_CLKDIV_SHIFT)
#endif
/* DMA ON: SDIOCLK=48MHz, SDIO_CK=SDIOCLK/(1+2)=16 MHz
* DMA OFF: SDIOCLK=48MHz, SDIO_CK=SDIOCLK/(2+2)=12 MHz
*/
#ifdef CONFIG_STM32_SDIO_DMA
# define SDIO_SDXFR_CLKDIV (1 << SDIO_CLKCR_CLKDIV_SHIFT)
#else
# define SDIO_SDXFR_CLKDIV (2 << SDIO_CLKCR_CLKDIV_SHIFT)
#endif
/* Alternate function pin selections ************************************************/
/*
* UARTs.
*/
#define GPIO_USART1_RX GPIO_USART1_RX_2 /* RC_INPUT */
#define GPIO_USART1_TX GPIO_USART1_TX_2
#define GPIO_USART2_RX GPIO_USART2_RX_2
#define GPIO_USART2_TX GPIO_USART2_TX_2
#define GPIO_USART2_RTS GPIO_USART2_RTS_2
#define GPIO_USART2_CTS GPIO_USART2_CTS_2
#define GPIO_USART3_RX GPIO_USART3_RX_3
#define GPIO_USART3_TX GPIO_USART3_TX_3
#define GPIO_USART3_CTS 0 // unused
#define GPIO_USART3_RTS 0 // unused
#define GPIO_UART4_RX GPIO_UART4_RX_1
#define GPIO_UART4_TX GPIO_UART4_TX_1
#define GPIO_USART6_RX GPIO_USART6_RX_2
#define GPIO_USART6_TX GPIO_USART6_TX_2
#define GPIO_UART7_RX GPIO_UART7_RX_1
#define GPIO_UART7_TX GPIO_UART7_TX_1
/* UART8 has no alternate pin config */
/*
* CAN
*
* CAN1 is routed to the onboard transceiver.
*/
#define GPIO_CAN1_RX GPIO_CAN1_RX_3
#define GPIO_CAN1_TX GPIO_CAN1_TX_3
/*
* I2C
*
* The optional _GPIO configurations allow the I2C driver to manually
* reset the bus to clear stuck slaves. They match the pin configuration,
* but are normally-high GPIOs.
*/
#define GPIO_I2C1_SCL GPIO_I2C1_SCL_2
#define GPIO_I2C1_SDA GPIO_I2C1_SDA_2
#define GPIO_I2C1_SCL_GPIO (GPIO_OUTPUT|GPIO_OPENDRAIN|GPIO_SPEED_50MHz|GPIO_OUTPUT_SET|GPIO_PORTB|GPIO_PIN8)
#define GPIO_I2C1_SDA_GPIO (GPIO_OUTPUT|GPIO_OPENDRAIN|GPIO_SPEED_50MHz|GPIO_OUTPUT_SET|GPIO_PORTB|GPIO_PIN9)
#define GPIO_I2C2_SCL GPIO_I2C2_SCL_1
#define GPIO_I2C2_SDA GPIO_I2C2_SDA_1
#define GPIO_I2C2_SCL_GPIO (GPIO_OUTPUT|GPIO_OPENDRAIN|GPIO_SPEED_50MHz|GPIO_OUTPUT_SET|GPIO_PORTB|GPIO_PIN10)
#define GPIO_I2C2_SDA_GPIO (GPIO_OUTPUT|GPIO_OPENDRAIN|GPIO_SPEED_50MHz|GPIO_OUTPUT_SET|GPIO_PORTB|GPIO_PIN11)
/*
* SPI
*
* There are sensors on SPI1, and SPI2 is connected to the FRAM.
*/
#define GPIO_SPI1_MISO (GPIO_SPI1_MISO_1|GPIO_SPEED_50MHz)
#define GPIO_SPI1_MOSI (GPIO_SPI1_MOSI_2|GPIO_SPEED_50MHz)
#define GPIO_SPI1_SCK (GPIO_SPI1_SCK_1|GPIO_SPEED_50MHz)
#define GPIO_SPI2_MISO (GPIO_SPI2_MISO_1|GPIO_SPEED_50MHz)
#define GPIO_SPI2_MOSI (GPIO_SPI2_MOSI_1|GPIO_SPEED_50MHz)
#define GPIO_SPI2_SCK (GPIO_SPI2_SCK_2|GPIO_SPEED_50MHz)
#define GPIO_SPI4_MISO (GPIO_SPI4_MISO_1|GPIO_SPEED_50MHz)
#define GPIO_SPI4_MOSI (GPIO_SPI4_MOSI_1|GPIO_SPEED_50MHz)
#define GPIO_SPI4_SCK (GPIO_SPI4_SCK_1|GPIO_SPEED_50MHz)
#endif /* __ARCH_BOARD_BOARD_H */
@@ -0,0 +1,87 @@
/****************************************************************************
*
* Copyright (c) 2020-2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#pragma once
/*
| DMA1 | Stream 0 | Stream 1 | Stream 2 | Stream 3 | Stream 4 | Stream 5 | Stream 6 | Stream 7 |
|------------|------------------|------------------|------------------|------------------|------------------|------------------|------------------|------------------|
| Channel 0 | SPI3_RX_1 | - | SPI3_RX_2 | SPI2_RX | SPI2_TX | SPI3_TX_1 | - | SPI3_TX_2 |
| Channel 1 | I2C1_RX | - | TIM7_UP_1 | - | TIM7_UP_2 | I2C1_RX_1 | I2C1_TX | I2C1_TX_1 |
| Channel 2 | TIM4_CH1 | - | I2C4_RX | TIM4_CH2 | - | I2C4_RX | TIM4_UP | TIM4_CH3 |
| Channel 3 | - | TIM2_UP_1 | I2C3_RX_1 | I2C2_EXT_RX | I2C3_TX | TIM2_CH1 | TIM2_CH2 | TIM2_UP_2 |
| | | TIM2_CH3 | | | | | TIM2_CH4_1 | TIM2_CH4_2 |
| Channel 4 | UART5_RX | USART3_RX | UART4_RX | USART3_TX_1 | UART4_TX | USART2_RX | USART2_TX | UART5_TX |
| Channel 5 | UART8_TX | UART7_TX | TIM3_CH4 | UART7_RX | TIM3_CH1 | TIM3_CH2 | UART8_RX | TIM3_CH3 |
| | | | TIM3_UP | | TIM3_TRIG | | | |
| Channel 6 | TIM5_CH3 | TIM5_CH4_1 | TIM5_CH1 | TIM5_CH4_2 | TIM5_CH2 | - | TIM5_UP_2 | - |
| | TIM5_UP_1 | TIM5_TRIG_1 | | TIM5_TRIG_2 | | | | |
| Channel 7 | - | TIM6_UP | I2C2_RX | I2C2_RX_1 | USART3_TX_2 | DAC1 | DAC2 | I2C2_TX |
| | | | | | | | | |
| Usage | | | | | | | | |
| DMA2 | Stream 0 | Stream 1 | Stream 2 | Stream 3 | Stream 4 | Stream 5 | Stream 6 | Stream 7 |
|------------|------------------|------------------|------------------|------------------|------------------|------------------|------------------|------------------|
| Channel 0 | ADC1_1 | SAI1_A | TIM8_CH1_1 | SAI1_A_1 | ADC1_2 | SAI1_B_1 | TIM1_CH1_1 | - |
| | | | TIM8_CH2_1 | | | | TIM1_CH2_1 | |
| | | | TIM8_CH3_1 | | | | TIM1_CH3_1 | |
| Channel 1 | - | DCMI_1 | ADC2_1 | ADC2_2 | SAI1_B | SPI6_TX | SPI6_RX | DCMI_2 |
| Channel 2 | ADC3_1 | ADC3_2 | - | SPI5_RX_1 | SPI5_TX_1 | CRYP_OUT | CRYP_IN | HASH_IN |
| Channel 3 | SPI1_RX_1 | - | SPI1_RX_2 | SPI1_TX_1 | - | SPI1_TX_2 | - | QUADSPI |
| Channel 4 | SPI4_RX_1 | SPI4_TX_1 | USART1_RX_1 | SDIO | - | USART1_RX_2 | SDIO | USART1_TX |
| Channel 5 | - | USART6_RX_1 | USART6_RX_2 | SPI4_RX_2 | SPI4_TX_2 | - | USART6_TX_1 | USART6_TX_2 |
| Channel 6 | TIM1_TRIG_1 | TIM1_CH1_2 | TIM1_CH2_2 | TIM1_CH1 | TIM1_CH4 | TIM1_UP | TIM1_CH3_2 | - |
| | | | | | TIM1_TRIG_2 | | | |
| | | | | | TIM1_COM | | | |
| Channel 7 | - | TIM8_UP | TIM8_CH1_2 | TIM8_CH2_2 | TIM8_CH3_2 | SPI5_RX_2 | SPI5_TX_2 | TIM8_CH4 |
| | | | | | | | | TIM8_TRIG |
| | | | | | | | | TIM8_COM |
| | | | | | | | | |
| Usage | SPI4_RX_1 | USART6_RX_1 | USART1_RX_1 | | SPI4_TX_2 | | SDIO | |
*/
// DMA1 Channel/Stream Selections
//--------------------------------------------//---------------------------//----------------
// DMA2 Channel/Stream Selections
//--------------------------------------------//---------------------------//----------------
#define DMACHAN_SPI4_RX DMAMAP_SPI4_RX_1 // DMA2, Stream 0, Channel 4 (SPI sensors RX)
#define DMAMAP_USART6_RX DMAMAP_USART6_RX_1 // DMA2, Stream 1, Channel 4
#define DMAMAP_USART1_RX DMAMAP_USART1_RX_1 // DMA2, Stream 2, Channel 4
// AVAILABLE // DMA2, Stream 3
#define DMACHAN_SPI4_TX DMAMAP_SPI4_TX_2 // DMA2, Stream 4, Channel 5 (SPI sensors TX)
// AVAILABLE // DMA2, Stream 5, Channel 6
#define DMAMAP_SDIO DMAMAP_SDIO_2 // DMA2, Stream 6, Channel 4
@@ -50,46 +50,41 @@
# CONFIG_NSH_DISABLE_UMOUNT is not set
# CONFIG_NSH_DISABLE_UNSET is not set
# CONFIG_NSH_DISABLE_USLEEP is not set
# CONFIG_STM32_CCMEXCLUDE is not set
CONFIG_ARCH="arm"
CONFIG_ARCH_BOARD_CUSTOM=y
CONFIG_ARCH_BOARD_CUSTOM_DIR="../../../../boards/xc-fly/xc-slam/nuttx-config"
CONFIG_ARCH_BOARD_CUSTOM_DIR="../../../../boards/saam/saampixv1_1/nuttx-config"
CONFIG_ARCH_BOARD_CUSTOM_DIR_RELPATH=y
CONFIG_ARCH_BOARD_CUSTOM_NAME="px4"
CONFIG_ARCH_CHIP="stm32h7"
CONFIG_ARCH_CHIP_STM32H743VI=y
CONFIG_ARCH_CHIP_STM32H7=y
CONFIG_ARCH_CHIP="stm32"
CONFIG_ARCH_CHIP_STM32=y
CONFIG_ARCH_CHIP_STM32F427V=y
CONFIG_ARCH_INTERRUPTSTACK=768
CONFIG_ARCH_STACKDUMP=y
CONFIG_ARMV7M_BASEPRI_WAR=y
CONFIG_ARMV7M_DCACHE=y
CONFIG_ARMV7M_DTCM=y
CONFIG_ARMV7M_ICACHE=y
CONFIG_ARMV7M_MEMCPY=y
CONFIG_ARMV7M_USEBASEPRI=y
CONFIG_ARM_MPU_EARLY_RESET=y
CONFIG_BOARDCTL_RESET=y
CONFIG_BOARD_ASSERT_RESET_VALUE=0
CONFIG_BOARD_CRASHDUMP=y
CONFIG_BOARD_LOOPSPERMSEC=95150
CONFIG_BOARD_LOOPSPERMSEC=16717
CONFIG_BOARD_RESET_ON_ASSERT=2
CONFIG_BUILTIN=y
CONFIG_CDCACM=y
CONFIG_CDCACM_IFLOWCONTROL=y
CONFIG_CDCACM_PRODUCTID=0x0036
CONFIG_CDCACM_PRODUCTSTR="X-MAV AP-H743v2"
CONFIG_CDCACM_PRODUCTID=0x008E
CONFIG_CDCACM_PRODUCTSTR="SaamPixV1_1 Flight Controller"
CONFIG_CDCACM_RXBUFSIZE=600
CONFIG_CDCACM_TXBUFSIZE=12000
CONFIG_CDCACM_VENDORID=0x1B8C
CONFIG_CDCACM_VENDORSTR="X-MAV"
CONFIG_CDCACM_TXBUFSIZE=2000
CONFIG_CDCACM_VENDORID=0x26ac
CONFIG_CDCACM_VENDORSTR="Saam Drones"
CONFIG_DEBUG_FULLOPT=y
CONFIG_DEBUG_HARDFAULT_ALERT=y
CONFIG_DEBUG_MEMFAULT=y
CONFIG_DEBUG_SYMBOLS=y
CONFIG_DEBUG_TCBINFO=y
CONFIG_DEFAULT_SMALL=y
CONFIG_DEV_FIFO_SIZE=0
CONFIG_DEV_PIPE_MAXSIZE=1024
CONFIG_DEV_PIPE_SIZE=70
CONFIG_EXPERIMENTAL=y
CONFIG_FAT_DMAMEMORY=y
CONFIG_FAT_LCNAMES=y
CONFIG_FAT_LFN=y
@@ -101,7 +96,6 @@ CONFIG_FS_FAT=y
CONFIG_FS_FATTIME=y
CONFIG_FS_PROCFS=y
CONFIG_FS_PROCFS_INCLUDE_PROGMEM=y
CONFIG_FS_PROCFS_MAX_TASKS=64
CONFIG_FS_PROCFS_REGISTER=y
CONFIG_FS_ROMFS=y
CONFIG_GRAN=y
@@ -113,8 +107,6 @@ CONFIG_I2C_RESET=y
CONFIG_IDLETHREAD_STACKSIZE=750
CONFIG_INIT_ENTRYPOINT="nsh_main"
CONFIG_INIT_STACKSIZE=3194
CONFIG_IOB_NBUFFERS=24
CONFIG_IOB_NCHAINS=24
CONFIG_LIBC_FLOATINGPOINT=y
CONFIG_LIBC_LONG_LONG=y
CONFIG_LIBC_MAX_EXITFUNS=1
@@ -124,14 +116,11 @@ CONFIG_MEMSET_OPTSPEED=y
CONFIG_MMCSD=y
CONFIG_MMCSD_SDIO=y
CONFIG_MMCSD_SDIOWAIT_WRCOMPLETE=y
CONFIG_MM_IOB=y
CONFIG_MM_REGIONS=4
CONFIG_MM_REGIONS=2
CONFIG_MTD=y
CONFIG_MTD_BYTE_WRITE=y
CONFIG_MTD_PARTITION=y
CONFIG_MTD_PROGMEM=y
CONFIG_MTD_RAMTRON=y
CONFIG_MTD_W25=y
CONFIG_NAME_MAX=40
CONFIG_NSH_ARCHINIT=y
CONFIG_NSH_ARGCAT=y
@@ -146,18 +135,17 @@ CONFIG_NSH_ROMFSETC=y
CONFIG_NSH_ROMFSSECTSIZE=128
CONFIG_NSH_STRERROR=y
CONFIG_NSH_VARS=y
CONFIG_OTG_ID_GPIO_DISABLE=y
CONFIG_PIPES=y
CONFIG_PREALLOC_TIMERS=50
CONFIG_PRIORITY_INHERITANCE=y
CONFIG_PTHREAD_MUTEX_ROBUST=y
CONFIG_PTHREAD_STACK_MIN=512
CONFIG_RAMTRON_EMULATE_PAGE_SHIFT=5
CONFIG_RAMTRON_EMULATE_SECTOR_SHIFT=5
CONFIG_RAMTRON_SETSPEED=y
CONFIG_RAM_SIZE=245760
CONFIG_RAM_START=0x20010000
CONFIG_RAM_SIZE=262144
CONFIG_RAM_START=0x20000000
CONFIG_RAW_BINARY=y
CONFIG_READLINE_CMD_HISTORY=y
CONFIG_READLINE_TABCOMPLETION=y
CONFIG_RTC_DATETIME=y
CONFIG_SCHED_HPWORK=y
CONFIG_SCHED_HPWORKPRIORITY=249
@@ -169,7 +157,7 @@ CONFIG_SCHED_LPWORK=y
CONFIG_SCHED_LPWORKPRIORITY=50
CONFIG_SCHED_LPWORKSTACKSIZE=1632
CONFIG_SCHED_WAITPID=y
CONFIG_SDMMC1_SDIO_PULLUP=y
CONFIG_SDIO_BLOCKSETUP=y
CONFIG_SEM_PREALLOCHOLDERS=32
CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS=y
CONFIG_SERIAL_TERMIOS=y
@@ -181,88 +169,87 @@ CONFIG_SIG_SIGWORK=4
CONFIG_STACK_COLORATION=y
CONFIG_START_DAY=30
CONFIG_START_MONTH=11
CONFIG_STDIO_BUFFER_SIZE=256
CONFIG_STM32H7_ADC1=y
CONFIG_STM32H7_ADC2=y
CONFIG_STM32H7_ADC3=y
CONFIG_STM32H7_BBSRAM=y
CONFIG_STM32H7_BBSRAM_FILES=5
CONFIG_STM32H7_BDMA=y
CONFIG_STM32H7_BKPSRAM=y
CONFIG_STM32H7_DMA1=y
CONFIG_STM32H7_DMA2=y
CONFIG_STM32H7_DMACAPABLE=y
CONFIG_STM32H7_FLASH_OVERRIDE_I=y
CONFIG_STM32H7_FLOWCONTROL_BROKEN=y
CONFIG_STM32H7_I2C1=y
CONFIG_STM32H7_I2C4=y
CONFIG_STM32H7_I2C_DYNTIMEO=y
CONFIG_STM32H7_I2C_DYNTIMEO_STARTSTOP=10
CONFIG_STM32H7_OTGFS=y
CONFIG_STM32H7_PROGMEM=y
CONFIG_STM32H7_RTC=y
CONFIG_STM32H7_RTC_HSECLOCK=y
CONFIG_STM32H7_RTC_MAGIC_REG=1
CONFIG_STM32H7_SAVE_CRASHDUMP=y
CONFIG_STM32H7_SDMMC1=y
CONFIG_STM32H7_SERIALBRK_BSDCOMPAT=y
CONFIG_STM32H7_SERIAL_DISABLE_REORDERING=y
CONFIG_STM32H7_SPI1=y
CONFIG_STM32H7_SPI2=y
CONFIG_STM32H7_SPI2_DMA=y
CONFIG_STM32H7_SPI2_DMA_BUFFER=4096
CONFIG_STM32H7_SPI3=y
CONFIG_STM32H7_SPI4=y
CONFIG_STM32H7_SPI_DMATHRESHOLD=8
CONFIG_STM32H7_TIM1=y
CONFIG_STM32H7_TIM2=y
CONFIG_STM32H7_TIM3=y
CONFIG_STM32H7_TIM4=y
CONFIG_STM32H7_TIM8=y
CONFIG_STM32H7_UART4=y
CONFIG_STM32H7_UART5=y
CONFIG_STM32H7_UART7=y
CONFIG_STM32H7_UART8=y
CONFIG_STM32H7_USART1=y
CONFIG_STM32H7_USART2=y
CONFIG_STM32H7_USART3=y
CONFIG_STM32H7_USART6=y
CONFIG_STM32H7_USART_BREAKS=y
CONFIG_STM32H7_USART_INVERT=y
CONFIG_STM32H7_USART_SINGLEWIRE=y
CONFIG_STM32H7_USART_SWAP=y
CONFIG_STDIO_BUFFER_SIZE=32
CONFIG_STM32_ADC1=y
CONFIG_STM32_BBSRAM=y
CONFIG_STM32_BBSRAM_FILES=5
CONFIG_STM32_BKPSRAM=y
CONFIG_STM32_CCMDATARAM=y
CONFIG_STM32_DISABLE_IDLE_SLEEP_DURING_DEBUG=y
CONFIG_STM32_DMA1=y
CONFIG_STM32_DMA2=y
CONFIG_STM32_FLASH_CONFIG_I=y
CONFIG_STM32_FLOWCONTROL_BROKEN=y
CONFIG_STM32_I2C1=y
CONFIG_STM32_I2C2=y
CONFIG_STM32_I2CTIMEOMS=10
CONFIG_STM32_I2CTIMEOTICKS=10
CONFIG_STM32_JTAG_SW_ENABLE=y
CONFIG_STM32_OTGFS=y
CONFIG_STM32_PWR=y
CONFIG_STM32_RTC=y
CONFIG_STM32_RTC_HSECLOCK=y
CONFIG_STM32_RTC_MAGIC=0xfacefeee
CONFIG_STM32_RTC_MAGIC_REG=1
CONFIG_STM32_RTC_MAGIC_TIME_SET=0xfacefeef
CONFIG_STM32_SAVE_CRASHDUMP=y
CONFIG_STM32_SDIO=y
CONFIG_STM32_SDIO_CARD=y
CONFIG_STM32_SERIALBRK_BSDCOMPAT=y
CONFIG_STM32_SERIAL_DISABLE_REORDERING=y
CONFIG_STM32_SPI1=y
CONFIG_STM32_SPI2=y
CONFIG_STM32_SPI4=y
CONFIG_STM32_SPI4_DMA=y
CONFIG_STM32_SPI4_DMA_BUFFER=512
CONFIG_STM32_SPI_DMATHRESHOLD=8
CONFIG_STM32_TIM10=y
CONFIG_STM32_TIM11=y
CONFIG_STM32_TIM3=y
CONFIG_STM32_TIM9=y
CONFIG_STM32_UART4=y
CONFIG_STM32_UART7=y
CONFIG_STM32_UART8=y
CONFIG_STM32_USART1=y
CONFIG_STM32_USART2=y
CONFIG_STM32_USART3=y
CONFIG_STM32_USART6=y
CONFIG_STM32_USART_BREAKS=y
CONFIG_STM32_USART_SINGLEWIRE=y
CONFIG_STM32_WWDG=y
CONFIG_SYSTEM_CDCACM=y
CONFIG_SYSTEM_NSH=y
CONFIG_TASK_NAME_SIZE=24
CONFIG_UART4_BAUD=921600
CONFIG_UART4_RXBUFSIZE=3000
CONFIG_UART4_BAUD=57600
CONFIG_UART4_RXBUFSIZE=300
CONFIG_UART4_RXDMA=y
CONFIG_UART4_TXBUFSIZE=3000
CONFIG_UART4_TXDMA=y
CONFIG_UART5_BAUD=57600
CONFIG_UART5_RXBUFSIZE=600
CONFIG_UART5_TXBUFSIZE=1500
CONFIG_UART4_TXBUFSIZE=300
CONFIG_UART7_BAUD=57600
CONFIG_UART7_RXBUFSIZE=600
CONFIG_UART7_TXBUFSIZE=3000
CONFIG_UART7_RXBUFSIZE=300
CONFIG_UART7_RXDMA=y
CONFIG_UART7_SERIAL_CONSOLE=y
CONFIG_UART7_TXBUFSIZE=300
CONFIG_UART8_BAUD=57600
CONFIG_UART8_RXBUFSIZE=600
CONFIG_UART8_TXBUFSIZE=3000
CONFIG_USART1_BAUD=57600
CONFIG_USART1_RXBUFSIZE=600
CONFIG_USART1_TXBUFSIZE=1500
CONFIG_UART8_RXBUFSIZE=300
CONFIG_UART8_TXBUFSIZE=300
CONFIG_USART1_RXBUFSIZE=128
CONFIG_USART1_RXDMA=y
CONFIG_USART1_TXBUFSIZE=32
CONFIG_USART2_BAUD=57600
CONFIG_USART2_IFLOWCONTROL=y
CONFIG_USART2_OFLOWCONTROL=y
CONFIG_USART2_RXBUFSIZE=600
CONFIG_USART2_TXBUFSIZE=3000
CONFIG_USART2_RXDMA=y
CONFIG_USART2_TXBUFSIZE=1100
CONFIG_USART3_BAUD=57600
CONFIG_USART3_RXBUFSIZE=180
CONFIG_USART3_TXBUFSIZE=1500
CONFIG_USART3_RXBUFSIZE=300
CONFIG_USART3_RXDMA=y
CONFIG_USART3_TXBUFSIZE=300
CONFIG_USART6_BAUD=57600
CONFIG_USART6_RXBUFSIZE=180
CONFIG_USART6_SERIAL_CONSOLE=y
CONFIG_USART6_RXBUFSIZE=300
CONFIG_USART6_RXDMA=y
CONFIG_USART6_TXBUFSIZE=300
CONFIG_USBDEV=y
CONFIG_USBDEV_BUSPOWERED=y
CONFIG_USBDEV_MAXPOWER=500
CONFIG_USEC_PER_TICK=1000
CONFIG_WATCHDOG=y
CONFIG_WQUEUE_NOTIFIER=y
@@ -0,0 +1,146 @@
/****************************************************************************
* scripts/ld.script
*
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/* The STM32F427 has 2048Kb of FLASH beginning at address 0x0800:0000 and
* 256Kb of SRAM. SRAM is split up into three blocks:
*
* 1) 112Kb of SRAM beginning at address 0x2000:0000
* 2) 16Kb of SRAM beginning at address 0x2001:c000
* 3) 64Kb of SRAM beginning at address 0x2002:0000
* 4) 64Kb of TCM SRAM beginning at address 0x1000:0000
*
* When booting from FLASH, FLASH memory is aliased to address 0x0000:0000
* where the code expects to begin execution by jumping to the entry point in
* the 0x0800:0000 address range.
*
* The first 0x4000 of flash is reserved for the bootloader.
*/
MEMORY
{
flash (rx) : ORIGIN = 0x08004000, LENGTH = 2032K
sram (rwx) : ORIGIN = 0x20000000, LENGTH = 192K
ccsram (rwx) : ORIGIN = 0x10000000, LENGTH = 64K
}
OUTPUT_ARCH(arm)
ENTRY(__start) /* treat __start as the anchor for dead code stripping */
EXTERN(_vectors) /* force the vectors to be included in the output */
/*
* Ensure that abort() is present in the final object. The exception handling
* code pulled in by libgcc.a requires it (and that code cannot be easily avoided).
*/
EXTERN(abort)
EXTERN(_bootdelay_signature)
SECTIONS
{
.text : {
_stext = ABSOLUTE(.);
*(.vectors)
. = ALIGN(32);
/*
This signature provides the bootloader with a way to delay booting
*/
_bootdelay_signature = ABSOLUTE(.);
FILL(0xffecc2925d7d05c5)
. += 8;
*(.text .text.*)
*(.fixup)
*(.gnu.warning)
*(.rodata .rodata.*)
*(.gnu.linkonce.t.*)
*(.got)
*(.gcc_except_table)
*(.gnu.linkonce.r.*)
_etext = ABSOLUTE(.);
} > flash
/*
* Init functions (static constructors and the like)
*/
.init_section : {
_sinit = ABSOLUTE(.);
KEEP(*(.init_array .init_array.*))
_einit = ABSOLUTE(.);
} > flash
.ARM.extab : {
*(.ARM.extab*)
} > flash
__exidx_start = ABSOLUTE(.);
.ARM.exidx : {
*(.ARM.exidx*)
} > flash
__exidx_end = ABSOLUTE(.);
_eronly = ABSOLUTE(.);
.data : {
_sdata = ABSOLUTE(.);
*(.data .data.*)
*(.gnu.linkonce.d.*)
CONSTRUCTORS
_edata = ABSOLUTE(.);
} > sram AT > flash
.bss : {
_sbss = ABSOLUTE(.);
*(.bss .bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
_ebss = ABSOLUTE(.);
} > sram
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_info 0 : { *(.debug_info) }
.debug_line 0 : { *(.debug_line) }
.debug_pubnames 0 : { *(.debug_pubnames) }
.debug_aranges 0 : { *(.debug_aranges) }
}
@@ -1,6 +1,6 @@
############################################################################
#
# Copyright (c) 2021 PX4 Development Team. All rights reserved.
# Copyright (c) 2015 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -30,40 +30,22 @@
# POSSIBILITY OF SUCH DAMAGE.
#
############################################################################
if("${PX4_BOARD_LABEL}" STREQUAL "bootloader")
add_library(drivers_board
bootloader_main.c
usb.c
)
target_link_libraries(drivers_board
PRIVATE
nuttx_arch
nuttx_drivers
bootloader
)
target_include_directories(drivers_board PRIVATE ${PX4_SOURCE_DIR}/platforms/nuttx/src/bootloader/common)
else()
add_library(drivers_board
i2c.cpp
init.c
led.c
sdio.c
spi.cpp
timer_config.cpp
usb.c
mtd.cpp
)
# add_dependencies(drivers_board arch_board_hw_info)
add_library(drivers_board
can.c
i2c.cpp
init.c
led.c
spi.cpp
timer_config.cpp
usb.c
)
target_link_libraries(drivers_board
PRIVATE
arch_io_pins
arch_spi
arch_board_hw_info
drivers__led
nuttx_arch
nuttx_drivers
px4_layer
)
endif()
target_link_libraries(drivers_board
PRIVATE
arch_spi
drivers__led # drv_led_start
nuttx_arch # sdio
nuttx_drivers # sdio
px4_layer
)
+193
View File
@@ -0,0 +1,193 @@
/****************************************************************************
*
* Copyright (c) 2020-2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file board_config.h
*
* SaamPixV1_1 internal definitions
*/
#pragma once
/****************************************************************************************************
* Included Files
****************************************************************************************************/
#include <px4_platform_common/px4_config.h>
#include <nuttx/compiler.h>
#include <stdint.h>
/****************************************************************************************************
* Definitions
****************************************************************************************************/
/* Configuration ************************************************************************************/
/* SaamPixV1_1 GPIOs ***********************************************************************************/
/* LEDs */
#define GPIO_LED1 (GPIO_OUTPUT|GPIO_OPENDRAIN|GPIO_SPEED_50MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTA|GPIO_PIN8)
#define BOARD_OVERLOAD_LED LED_RED
/*
* ADC channels
*
* These are the channel numbers of the ADCs of the microcontroller that can be used by the Px4 Firmware in the adc driver
*/
#define ADC_CHANNELS (1 << 4) | (1 << 10) | (1 << 11) | (1 << 12) | (1 << 13) | (1 << 14) | (1 << 15)
// ADC defines to be used in sensors.cpp to read from a particular channel
#define ADC_5V_RAIL_SENSE 4
#define ADC_BATTERY_CURRENT_CHANNEL 10
#define ADC_BATTERY_VOLTAGE_CHANNEL 12
#define ADC_RC_RSSI_CHANNEL 11
#define ADC_AIRSPEED_VOLTAGE_CHANNEL 15
/* Power supply control and monitoring GPIOs */
// #define GPIO_VDD_5V_PERIPH_EN (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTA|GPIO_PIN8)
// #define GPIO_VDD_BRICK_VALID (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN5)
// #define GPIO_VDD_SERVO_VALID (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN7)
// #define GPIO_VDD_3V3_SENSORS_EN (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTE|GPIO_PIN3)
// #define GPIO_VDD_5V_HIPOWER_OC (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTE|GPIO_PIN10)
// #define GPIO_VDD_5V_PERIPH_OC (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTE|GPIO_PIN15)
/* Tone alarm output */
#define TONE_ALARM_TIMER 14 /* timer 14 */
#define TONE_ALARM_CHANNEL 1 /* channel 1 */
#define GPIO_TONE_ALARM_IDLE (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTA|GPIO_PIN7)
#define GPIO_TONE_ALARM (GPIO_ALT|GPIO_AF9|GPIO_SPEED_2MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN7)
/* AUX PWMs
*/
#define DIRECT_PWM_OUTPUT_CHANNELS 8
/* USB OTG FS
*
* PA9 OTG_FS_VBUS VBUS sensing
*/
#define GPIO_OTGFS_VBUS (GPIO_INPUT|GPIO_FLOAT|GPIO_SPEED_100MHz|GPIO_OPENDRAIN|GPIO_PORTA|GPIO_PIN9)
/* High-resolution timer */
#define HRT_TIMER 8 /* use timer8 for the HRT */
#define HRT_TIMER_CHANNEL 2 /* use capture/compare channel */
#define HRT_PPM_CHANNEL 1
#define GPIO_PPM_IN GPIO_TIM8_CH1IN_1
/* PWM input driver. Use FMU AUX5 pins attached to timer4 channel 1 */
#define PWMIN_TIMER 4
#define PWMIN_TIMER_CHANNEL 1
#define GPIO_PWM_IN GPIO_TIM1_CH1IN_2
#define RC_SERIAL_PORT "/dev/ttyS0"
// #define GPIO_RSSI_IN (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTC|GPIO_PIN1)
#define GPIO_SBUS_INV (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTA|GPIO_PIN10)
#define RC_INVERT_INPUT(_invert_true) px4_arch_gpiowrite(GPIO_SBUS_INV, _invert_true);
#define GPIO_FRSKY_INV (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTB|GPIO_PIN12)
#define INVERT_FRSKY(_invert_true) px4_arch_gpiowrite(GPIO_FRSKY_INV, _invert_true);
/* Power switch controls */
#define SPEKTRUM_POWER(_on_true) do { } while (0)
/*
* SaamPixV1_1 has one RC_IN
*
* GPIO PPM_IN on PC6 T8CH1
* SPEKTRUM_RX (it's TX or RX in Bind) on PC6 UART1
* Inversion is possible via the 74LVC2G86 controlled by the FMU
* The FMU can drive GPIO PPM_IN as an output
*/
#define GPIO_PPM_IN_AS_OUT (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTC|GPIO_PIN6)
#define SPEKTRUM_RX_AS_GPIO_OUTPUT() px4_arch_configgpio(GPIO_PPM_IN_AS_OUT)
#define SPEKTRUM_RX_AS_UART() px4_arch_configgpio(GPIO_USART1_RX)
#define SPEKTRUM_OUT(_one_true) px4_arch_gpiowrite(GPIO_PPM_IN_AS_OUT, (_one_true))
/* By Providing BOARD_ADC_USB_CONNECTED (using the px4_arch abstraction)
* this board support the ADC system_power interface, and therefore
* provides the true logic GPIO BOARD_ADC_xxxx macros.
*/
#define BOARD_ADC_USB_CONNECTED (px4_arch_gpioread(GPIO_OTGFS_VBUS))
#define BOARD_ADC_BRICK_VALID (1)
#define BOARD_ADC_SERVO_VALID (1)
#define BOARD_ADC_PERIPH_5V_OC (0)
#define BOARD_ADC_HIPOWER_5V_OC (0)
/* This board provides a DMA pool and APIs */
#define BOARD_DMA_ALLOC_POOL_SIZE 5120
/* This board provides the board_on_reset interface */
#define BOARD_HAS_ON_RESET 1
__BEGIN_DECLS
/****************************************************************************************************
* Public Types
****************************************************************************************************/
/****************************************************************************************************
* Public data
****************************************************************************************************/
#ifndef __ASSEMBLY__
/****************************************************************************************************
* Public Functions
****************************************************************************************************/
/****************************************************************************************************
* Name: stm32_spiinitialize
*
* Description:
* Called to configure SPI chip select GPIO pins for the SaamPixV1_1 board.
*
****************************************************************************************************/
extern void stm32_spiinitialize(void);
extern void stm32_usbinitialize(void);
#define board_peripheral_reset(ms)
#include <px4_platform_common/board_common.h>
#endif /* __ASSEMBLY__ */
__END_DECLS
@@ -1,6 +1,6 @@
/****************************************************************************
*
* Copyright (C) 2021 PX4 Development Team. All rights reserved.
* Copyright (c) 2020-2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -32,47 +32,98 @@
****************************************************************************/
/**
* @file usb.c
* @file can.c
*
* Board-specific USB functions.
* Board-specific CAN functions.
*/
#include "board_config.h"
#include <nuttx/usb/usbdev.h>
#include <nuttx/usb/usbdev_trace.h>
#include <stm32_otg.h>
/************************************************************************************
* Included Files
************************************************************************************/
#include <px4_platform_common/px4_config.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/can/can.h>
#include <arch/board/board.h>
#include "chip.h"
#include "arm_internal.h"
#include "stm32.h"
#include "stm32_can.h"
#include "board_config.h"
#ifdef CONFIG_CAN
/************************************************************************************
* Name: stm32_usbinitialize
*
* Description:
* Called to setup USB-related GPIO pins for the board.
*
* Pre-processor Definitions
************************************************************************************/
/* Configuration ********************************************************************/
__EXPORT void stm32_usbinitialize(void)
{
/* The OTG FS has an internal soft pull-up */
/* Configure the OTG FS VBUS sensing GPIO, Power On, and Overcurrent GPIOs */
#ifdef CONFIG_STM32H7_OTGFS
stm32_configgpio(GPIO_OTGFS_VBUS);
#if defined(CONFIG_STM32_CAN1) && defined(CONFIG_STM32_CAN2)
# warning "Both CAN1 and CAN2 are enabled. Assuming only CAN1."
# undef CONFIG_STM32_CAN2
#endif
#ifdef CONFIG_STM32_CAN1
# define CAN_PORT 1
#else
# define CAN_PORT 2
#endif
}
/************************************************************************************
* Name: stm32_usbsuspend
* Private Functions
************************************************************************************/
/************************************************************************************
* Public Functions
************************************************************************************/
int can_devinit(void);
/************************************************************************************
* Name: can_devinit
*
* Description:
* Board logic must provide the stm32_usbsuspend logic if the USBDEV driver is
* used. This function is called whenever the USB enters or leaves suspend mode.
* This is an opportunity for the board logic to shutdown clocks, power, etc.
* while the USB is suspended.
* All STM32 architectures must provide the following interface to work with
* examples/can.
*
************************************************************************************/
__EXPORT void stm32_usbsuspend(FAR struct usbdev_s *dev, bool resume)
int can_devinit(void)
{
uinfo("resume: %d\n", resume);
static bool initialized = false;
struct can_dev_s *can;
int ret;
/* Check if we have already initialized */
if (!initialized) {
/* Call stm32_caninitialize() to get an instance of the CAN interface */
can = stm32_caninitialize(CAN_PORT);
if (can == NULL) {
canerr("ERROR: Failed to get CAN interface\n");
return -ENODEV;
}
/* Register the CAN driver at "/dev/can0" */
ret = can_register("/dev/can0", can);
if (ret < 0) {
canerr("ERROR: can_register failed: %d\n", ret);
return ret;
}
/* Now we are initialized */
initialized = true;
}
return OK;
}
#endif
@@ -1,6 +1,6 @@
/****************************************************************************
*
* Copyright (C) 2021 PX4 Development Team. All rights reserved.
* Copyright (C) 2020-2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -35,5 +35,5 @@
constexpr px4_i2c_bus_t px4_i2c_buses[I2C_BUS_MAX_BUS_ITEMS] = {
initI2CBusInternal(1),
initI2CBusExternal(4),
initI2CBusExternal(2),
};
+299
View File
@@ -0,0 +1,299 @@
/****************************************************************************
*
* Copyright (c) 2020-2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file init.c
*
* SaamPixV1_1-specific early startup code. This file implements the
* board_app_initialize() function that is called early by nsh during startup.
*
* Code here is run before the rcS script is invoked; it should start required
* subsystems and perform board-specific initialization.
*/
/****************************************************************************
* Included Files
****************************************************************************/
#include <px4_platform_common/px4_config.h>
#include <px4_platform_common/tasks.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <debug.h>
#include <errno.h>
#include <syslog.h>
#include <nuttx/board.h>
#include <nuttx/spi/spi.h>
#include <nuttx/i2c/i2c_master.h>
#include <nuttx/sdio.h>
#include <nuttx/mmcsd.h>
#include <nuttx/analog/adc.h>
#include <nuttx/mm/gran.h>
#include <stm32.h>
#include "board_config.h"
#include <stm32_uart.h>
#include <arch/board/board.h>
#include <drivers/drv_hrt.h>
#include <drivers/drv_board_led.h>
#include <px4_platform_common/init.h>
#include <px4_platform/board_dma_alloc.h>
#include <px4_arch/io_timer.h>
/****************************************************************************
* Pre-Processor Definitions
****************************************************************************/
/*
* Ideally we'd be able to get these from arm_internal.h,
* but since we want to be able to disable the NuttX use
* of leds for system indication at will and there is no
* separate switch, we need to build independent of the
* CONFIG_ARCH_LEDS configuration switch.
*/
__BEGIN_DECLS
extern void led_init(void);
extern void led_on(int led);
extern void led_off(int led);
__END_DECLS
/************************************************************************************
* Name: board_on_reset
*
* Description:
* Optionally provided function called on entry to board_system_reset
* It should perform any house keeping prior to the rest.
*
* status - 1 if resetting to boot loader
* 0 if just resetting
*
************************************************************************************/
__EXPORT void board_on_reset(int status)
{
/* configure the GPIO pins to outputs and keep them low */
for (int i = 0; i < DIRECT_PWM_OUTPUT_CHANNELS; ++i) {
px4_arch_configgpio(io_timer_channel_get_gpio_output(i));
}
/**
* On resets invoked from system (not boot) insure we establish a low
* output state (discharge the pins) on PWM pins before they become inputs.
*/
if (status >= 0) {
up_mdelay(400);
}
}
/****************************************************************************
* Public Functions
****************************************************************************/
/************************************************************************************
* Name: stm32_boardinitialize
*
* Description:
* All STM32 architectures must provide the following entry point. This entry point
* is called early in the initialization -- after all memory has been configured
* and mapped but before any devices have been initialized.
*
************************************************************************************/
__EXPORT void
stm32_boardinitialize(void)
{
// Reset all PWM to Low outputs.
board_on_reset(-1);
/* configure LEDs */
board_autoled_initialize();
/* configure ADC pins */
stm32_configgpio(GPIO_ADC1_IN4); /* VDD_5V_SENS */
stm32_configgpio(GPIO_ADC1_IN10); /* BATT_CURRENT_SENS */
stm32_configgpio(GPIO_ADC1_IN12); /* BATT_VOLTAGE_SENS */
stm32_configgpio(GPIO_ADC1_IN11); /* RSSI analog in */
stm32_configgpio(GPIO_ADC1_IN13); /* FMU_AUX_ADC_1 */
stm32_configgpio(GPIO_ADC1_IN14); /* FMU_AUX_ADC_2 */
stm32_configgpio(GPIO_ADC1_IN15); /* PRESSURE_SENS */
/* configure power supply control/sense pins */
stm32_configgpio(GPIO_SBUS_INV);
stm32_configgpio(GPIO_FRSKY_INV);
/* configure CAN interface */
stm32_configgpio(GPIO_CAN1_RX);
stm32_configgpio(GPIO_CAN1_TX);
/* configure SPI interfaces */
stm32_spiinitialize();
stm32_configgpio(GPIO_I2C2_SCL);
stm32_configgpio(GPIO_I2C2_SDA);
stm32_configgpio(GPIO_I2C1_SCL);
stm32_configgpio(GPIO_I2C1_SDA);
}
/****************************************************************************
* Name: board_app_initialize
*
* Description:
* Perform application specific initialization. This function is never
* called directly from application code, but only indirectly via the
* (non-standard) boardctl() interface using the command BOARDIOC_INIT.
*
* Input Parameters:
* arg - The boardctl() argument is passed to the board_app_initialize()
* implementation without modification. The argument has no
* meaning to NuttX; the meaning of the argument is a contract
* between the board-specific initalization logic and the the
* matching application logic. The value cold be such things as a
* mode enumeration value, a set of DIP switch switch settings, a
* pointer to configuration data read from a file or serial FLASH,
* or whatever you would like to do with it. Every implementation
* should accept zero/NULL as a default configuration.
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned on
* any failure to indicate the nature of the failure.
*
****************************************************************************/
static struct spi_dev_s *spi1;
static struct spi_dev_s *spi2;
static struct spi_dev_s *spi4;
static struct sdio_dev_s *sdio;
__EXPORT int board_app_initialize(uintptr_t arg)
{
px4_platform_init();
/* configure the DMA allocator */
if (board_dma_alloc_init() < 0) {
syslog(LOG_ERR, "DMA alloc FAILED\n");
}
#if defined(SERIAL_HAVE_RXDMA)
// set up the serial DMA polling at 1ms intervals for received bytes that have not triggered a DMA event.
static struct hrt_call serial_dma_call;
hrt_call_every(&serial_dma_call, 1000, 1000, (hrt_callout)stm32_serial_dma_poll, NULL);
#endif
/* initial LED state */
drv_led_start();
led_off(LED_AMBER);
if (board_hardfault_init(2, true) != 0) {
led_on(LED_AMBER);
}
/* Configure SPI-based devices */
spi4 = px4_spibus_initialize(4);
if (!spi4) {
syslog(LOG_ERR, "[boot] FAILED to initialize SPI port 4\n");
board_autoled_on(LED_AMBER);
}
/* Default SPI4 to 10MHz and de-assert the known chip selects. */
SPI_SETFREQUENCY(spi4, 10000000);
SPI_SETBITS(spi4, 8);
SPI_SETMODE(spi4, SPIDEV_MODE3);
up_udelay(20);
/* Get the SPI port for the FRAM */
spi1 = stm32_spibus_initialize(1);
if (!spi1) {
syslog(LOG_ERR, "[boot] FAILED to initialize SPI port 1\n");
board_autoled_on(LED_AMBER);
}
/* Default SPI1 to 37.5 MHz (40 MHz rounded to nearest valid divider, F4 max)
* and de-assert the known chip selects. */
// XXX start with 10.4 MHz in FRAM usage and go up to 37.5 once validated
SPI_SETFREQUENCY(spi1, 24 * 1000 * 1000);
SPI_SETBITS(spi1, 8);
spi2 = px4_spibus_initialize(2);
/* Default SPI2 to 10MHz and de-assert the known chip selects. */
SPI_SETFREQUENCY(spi2, 10000000);
SPI_SETBITS(spi2, 8);
#ifdef CONFIG_MMCSD
/* First, get an instance of the SDIO interface */
sdio = sdio_initialize(CONFIG_NSH_MMCSDSLOTNO);
if (!sdio) {
syslog(LOG_ERR, "[boot] Failed to initialize SDIO slot %d\n", CONFIG_NSH_MMCSDSLOTNO);
}
/* Now bind the SDIO interface to the MMC/SD driver */
int ret = mmcsd_slotinitialize(CONFIG_NSH_MMCSDMINOR, sdio);
if (ret != OK) {
syslog(LOG_ERR, "[boot] Failed to bind SDIO to the MMC/SD driver: %d\n", ret);
}
/* Then let's guess and say that there is a card in the slot. There is no card detect GPIO. */
sdio_mediachange(sdio, true);
#endif
/* Configure the HW based on the manifest */
px4_platform_configure();
return OK;
}
@@ -1,6 +1,6 @@
/****************************************************************************
*
* Copyright (c) 2021 PX4 Development Team. All rights reserved.
* Copyright (c) 2020-2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -34,18 +34,16 @@
/**
* @file led.c
*
* LED backend.
* SaamPixV1_1 LED backend.
*/
#include <px4_platform_common/px4_config.h>
#include <stdbool.h>
#include "chip.h"
#include "stm32_gpio.h"
#include "stm32.h"
#include "board_config.h"
#include <nuttx/board.h>
#include <arch/board/board.h>
/*
@@ -62,52 +60,37 @@ extern void led_off(int led);
extern void led_toggle(int led);
__END_DECLS
# define xlat(p) (p)
static uint32_t g_ledmap[] = {
GPIO_nLED_GREEN, // Indexed by BOARD_LED_GREEN
GPIO_nLED_BLUE, // Indexed by BOARD_LED_BLUE
GPIO_nLED_RED, // Indexed by BOARD_LED_RED
};
__EXPORT void led_init(void)
__EXPORT void led_init()
{
/* Configure LED GPIOs for output */
for (size_t l = 0; l < (sizeof(g_ledmap) / sizeof(g_ledmap[0])); l++) {
if (g_ledmap[l] != 0) {
stm32_configgpio(g_ledmap[l]);
}
}
}
/* Configure LED1 GPIO for output */
static void phy_set_led(int led, bool state)
{
/* Drive Low to switch on */
if (g_ledmap[led] != 0) {
stm32_gpiowrite(g_ledmap[led], !state);
}
}
static bool phy_get_led(int led)
{
/* If Low it is on */
if (g_ledmap[led] != 0) {
return !stm32_gpioread(g_ledmap[led]);
}
return false;
stm32_configgpio(GPIO_LED1);
}
__EXPORT void led_on(int led)
{
phy_set_led(xlat(led), true);
if (led == 1) {
/* Pull down to switch on */
stm32_gpiowrite(GPIO_LED1, false);
}
}
__EXPORT void led_off(int led)
{
phy_set_led(xlat(led), false);
if (led == 1) {
/* Pull up to switch off */
stm32_gpiowrite(GPIO_LED1, true);
}
}
__EXPORT void led_toggle(int led)
{
phy_set_led(xlat(led), !phy_get_led(xlat(led)));
if (led == 1) {
if (stm32_gpioread(GPIO_LED1)) {
stm32_gpiowrite(GPIO_LED1, false);
} else {
stm32_gpiowrite(GPIO_LED1, true);
}
}
}
@@ -1,6 +1,6 @@
/****************************************************************************
*
* Copyright (C) 2021 PX4 Development Team. All rights reserved.
* Copyright (C) 2020-2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -35,20 +35,18 @@
#include <drivers/drv_sensor.h>
#include <nuttx/spi/spi.h>
constexpr px4_spi_bus_t px4_spi_buses[SPI_BUS_MAX_BUS_ITEMS] = {
initSPIBus(SPI::Bus::SPI1, {
initSPIDevice(DRV_GYR_DEVTYPE_BMI088, SPI::CS{GPIO::PortA, GPIO::Pin3}, SPI::DRDY{GPIO::PortA, GPIO::Pin1}),
initSPIDevice(DRV_ACC_DEVTYPE_BMI088, SPI::CS{GPIO::PortA, GPIO::Pin2}, SPI::DRDY{GPIO::PortA, GPIO::Pin0}),
initSPIDevice(SPIDEV_FLASH(0), SPI::CS{GPIO::PortE, GPIO::Pin12}),
}),
initSPIBus(SPI::Bus::SPI2, {
initSPIDevice(SPIDEV_FLASH(2), SPI::CS{GPIO::PortD, GPIO::Pin4})
}),
initSPIBus(SPI::Bus::SPI3, {
//initSPIDevice(DRV_OSD_DEVTYPE_ATXXXX, SPI::CS{GPIO::PortA, GPIO::Pin15})
initSPIBusExternal(SPI::Bus::SPI2, {
initSPIConfigExternal(SPI::CS{GPIO::PortD, GPIO::Pin7}),
}),
initSPIBus(SPI::Bus::SPI4, {
initSPIDevice(DRV_IMU_DEVTYPE_ICM42688P, SPI::CS{GPIO::PortC, GPIO::Pin13}, SPI::DRDY{GPIO::PortE, GPIO::Pin4}),
initSPIDevice(DRV_IMU_DEVTYPE_ICM20602, SPI::CS{GPIO::PortB, GPIO::Pin2}, SPI::DRDY{GPIO::PortE, GPIO::Pin4}),
initSPIDevice(DRV_MAG_DEVTYPE_LIS3MDL, SPI::CS{GPIO::PortD, GPIO::Pin11}),
initSPIDevice(DRV_BARO_DEVTYPE_MS5611, SPI::CS{GPIO::PortC, GPIO::Pin15}),
initSPIDevice(DRV_IMU_DEVTYPE_MPU9250, SPI::CS{GPIO::PortE, GPIO::Pin3}, SPI::DRDY{GPIO::PortE, GPIO::Pin10}),
}),
};
@@ -1,6 +1,6 @@
/****************************************************************************
*
* Copyright (C) 2021 PX4 Development Team. All rights reserved.
* Copyright (c) 2020-2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -29,32 +29,24 @@
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
* * TIM2_CH1 T HEATER > PWM OUT or GPIO PA15
****************************************************************************/
#include <px4_arch/io_timer_hw_description.h>
constexpr io_timers_t io_timers[MAX_IO_TIMERS] = {
initIOTimer(Timer::Timer1, DMA{DMA::Index1}),
initIOTimer(Timer::Timer2, DMA{DMA::Index1}),
initIOTimer(Timer::Timer3, DMA{DMA::Index1}),
// initIOTimer(Timer::Timer2),
// initIOTimer(Timer::Timer3),
initIOTimer(Timer::Timer1),
initIOTimer(Timer::Timer4),
};
constexpr timer_io_channels_t timer_io_channels[MAX_TIMER_IO_CHANNELS] = {
initIOTimerChannel(io_timers, {Timer::Timer1, Timer::Channel1}, {GPIO::PortE, GPIO::Pin9}),
initIOTimerChannel(io_timers, {Timer::Timer1, Timer::Channel2}, {GPIO::PortE, GPIO::Pin11}),
initIOTimerChannel(io_timers, {Timer::Timer1, Timer::Channel3}, {GPIO::PortE, GPIO::Pin13}),
initIOTimerChannel(io_timers, {Timer::Timer1, Timer::Channel4}, {GPIO::PortE, GPIO::Pin14}),
initIOTimerChannel(io_timers, {Timer::Timer3, Timer::Channel4}, {GPIO::PortB, GPIO::Pin1}),
initIOTimerChannel(io_timers, {Timer::Timer3, Timer::Channel3}, {GPIO::PortB, GPIO::Pin0}),
initIOTimerChannel(io_timers, {Timer::Timer2, Timer::Channel3}, {GPIO::PortB, GPIO::Pin10}),
initIOTimerChannel(io_timers, {Timer::Timer2, Timer::Channel4}, {GPIO::PortB, GPIO::Pin11}),
initIOTimerChannelOutputClear(io_timers, {Timer::Timer1, Timer::Channel1}, {GPIO::PortE, GPIO::Pin9}),
initIOTimerChannelOutputClear(io_timers, {Timer::Timer1, Timer::Channel2}, {GPIO::PortE, GPIO::Pin11}),
initIOTimerChannelOutputClear(io_timers, {Timer::Timer1, Timer::Channel3}, {GPIO::PortE, GPIO::Pin13}),
initIOTimerChannelOutputClear(io_timers, {Timer::Timer1, Timer::Channel4}, {GPIO::PortE, GPIO::Pin14}),
initIOTimerChannelOutputClear(io_timers, {Timer::Timer4, Timer::Channel1}, {GPIO::PortD, GPIO::Pin12}),
initIOTimerChannelOutputClear(io_timers, {Timer::Timer4, Timer::Channel2}, {GPIO::PortD, GPIO::Pin13}),
initIOTimerChannelOutputClear(io_timers, {Timer::Timer4, Timer::Channel3}, {GPIO::PortD, GPIO::Pin14}),
initIOTimerChannelOutputClear(io_timers, {Timer::Timer4, Timer::Channel4}, {GPIO::PortD, GPIO::Pin15}),
};
constexpr io_timers_channel_mapping_t io_timers_channel_mapping =
@@ -1,6 +1,6 @@
/****************************************************************************
*
* Copyright (C) 2021 PX4 Development Team. All rights reserved.
* Copyright (c) 2020-2026 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,17 +37,41 @@
* Board-specific USB functions.
*/
#include "board_config.h"
/************************************************************************************
* Included Files
************************************************************************************/
#include <px4_platform_common/px4_config.h>
#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
#include <debug.h>
#include <nuttx/usb/usbdev.h>
#include <nuttx/usb/usbdev_trace.h>
#include <stm32_otg.h>
#include <debug.h>
#include <arm_internal.h>
#include <stm32.h>
#include "board_config.h"
/************************************************************************************
* Definitions
************************************************************************************/
/************************************************************************************
* Private Functions
************************************************************************************/
/************************************************************************************
* Public Functions
************************************************************************************/
/************************************************************************************
* Name: stm32_usbinitialize
*
* Description:
* Called to setup USB-related GPIO pins for the board.
* Called to setup USB-related GPIO pins for the SaamPixV1_1 board.
*
************************************************************************************/
@@ -57,8 +81,12 @@ __EXPORT void stm32_usbinitialize(void)
/* Configure the OTG FS VBUS sensing GPIO, Power On, and Overcurrent GPIOs */
#ifdef CONFIG_STM32H7_OTGFS
#ifdef CONFIG_STM32_OTGFS
stm32_configgpio(GPIO_OTGFS_VBUS);
/* XXX We only support device mode
stm32_configgpio(GPIO_OTGFS_PWRON);
stm32_configgpio(GPIO_OTGFS_OVER);
*/
#endif
}
@@ -72,6 +100,7 @@ __EXPORT void stm32_usbinitialize(void)
* while the USB is suspended.
*
************************************************************************************/
__EXPORT void stm32_usbsuspend(FAR struct usbdev_s *dev, bool resume)
{
uinfo("resume: %d\n", resume);
+1 -4
View File
@@ -17,10 +17,7 @@ then
fi
# baro
if ! dps310 -I start -a 0x76
then
spl06 -I start -a 0x76
fi
spl06 -I start -a 0x76
# internal mag
qmc5883p -I -R 4 start
@@ -243,7 +243,6 @@ CONFIG_UART7_RXBUFSIZE=600
CONFIG_UART7_TXBUFSIZE=3000
CONFIG_UART8_BAUD=57600
CONFIG_UART8_RXBUFSIZE=600
CONFIG_UART8_SERIAL_CONSOLE=y
CONFIG_UART8_TXBUFSIZE=3000
CONFIG_USART1_BAUD=57600
CONFIG_USART1_RXBUFSIZE=600
-2
View File
@@ -49,8 +49,6 @@ uint16_t board_get_can_interfaces(void)
{
uint16_t enabled_interfaces = 0x3;
enabled_interfaces &= ~(1 << 1);
return enabled_interfaces;
}
@@ -1,3 +0,0 @@
CONFIG_BOARD_TOOLCHAIN="arm-none-eabi"
CONFIG_BOARD_ARCHITECTURE="cortex-m7"
CONFIG_BOARD_ROMFSROOT=""
-13
View File
@@ -1,13 +0,0 @@
{
"board_id": 319,
"magic": "PX4FWv1",
"description": "Firmware for the XC-FLY board",
"image": "",
"build_time": 0,
"summary": "XC-FLY",
"version": "0.1",
"image_size": 0,
"image_maxsize": 1835008,
"git_identity": "",
"board_revision": 0
}
@@ -1,26 +0,0 @@
#!/bin/sh
#
# board specific defaults
#------------------------------------------------------------------------------
param set-default BAT1_A_PER_V 17
param set-default BAT1_N_CELLS 4
param set-default BAT1_V_CHARGED 4.2
param set-default BAT1_V_DIV 10.1
param set-default BAT1_V_EMPTY 3.2
param set-default SYS_HAS_MAG 1
param set-default PWM_MAIN_TIM0 -4
param set-default RC_INPUT_PROTO -1
param set-default IMU_GYRO_RATEMAX 2000
param set-default SYS_AUTOSTART 4001
param set-default MC_PITCHRATE_K 0.4
param set-default MC_ROLLRATE_K 0.35
param set-default MC_YAWRATE_K 1.2
param set-default MC_YAWRATE_MAX 360
param set-default MAV_TYPE 2
param set-default CA_AIRFRAME 0
param set-default CA_ROTOR_COUNT 4
param set-default CBRK_SUPPLY_CHK 894281
param set-default USB_MAV_MODE 5
@@ -1,7 +0,0 @@
#!/bin/sh
#
# board specific extras init
#------------------------------------------------------------------------------
# DShot telemetry is always on UART7
# dshot telemetry -d /dev/ttyS5
@@ -1,20 +0,0 @@
#!/bin/sh
#
# board specific sensors init
#------------------------------------------------------------------------------
board_adc start
# heater start
# BMI088
bmi088 -A -R 2 -s start
bmi088 -G -R 2 -s start
# 42688P
icm42688p -s start
# baro
dps310 -I start -a 119
# internal mag
ist8310 -I -R 2 start
@@ -1,17 +0,0 @@
#
# For a description of the syntax of this configuration file,
# see misc/tools/kconfig-language.txt.
#
config BOARD_HAS_PROBES
bool "Board provides GPIO or other Hardware for signaling to timing analyze."
default y
---help---
This board provides GPIO FMU-CH1-5, CAP1-6 as PROBE_1-11 to provide timing signals from selected drivers.
config BOARD_USE_PROBES
bool "Enable the use the board provided FMU-CH1-5, CAP1-6 as PROBE_1-11"
default n
depends on BOARD_HAS_PROBES
---help---
Select to use GPIO FMU-CH1-5, CAP1-6 to provide timing signals from selected drivers.
@@ -1,90 +0,0 @@
#
# This file is autogenerated: PLEASE DO NOT EDIT IT.
#
# You can use "make menuconfig" to make any modifications to the installed .config file.
# You can then do "make savedefconfig" to generate a new defconfig file that includes your
# modifications.
#
# CONFIG_DEV_CONSOLE is not set
# CONFIG_DISABLE_PSEUDOFS_OPERATIONS is not set
# CONFIG_SPI_EXCHANGE is not set
# CONFIG_STM32H7_SYSCFG is not set
CONFIG_ARCH="arm"
CONFIG_ARCH_BOARD_CUSTOM=y
CONFIG_ARCH_BOARD_CUSTOM_DIR="../../../../boards/xc-fly/xc-slam/nuttx-config"
CONFIG_ARCH_BOARD_CUSTOM_DIR_RELPATH=y
CONFIG_ARCH_BOARD_CUSTOM_NAME="px4"
CONFIG_ARCH_CHIP="stm32h7"
CONFIG_ARCH_CHIP_STM32H743VI=y
CONFIG_ARCH_CHIP_STM32H7=y
CONFIG_ARCH_INTERRUPTSTACK=768
CONFIG_ARMV7M_BASEPRI_WAR=y
CONFIG_ARMV7M_ICACHE=y
CONFIG_ARMV7M_MEMCPY=y
CONFIG_ARMV7M_USEBASEPRI=y
CONFIG_BOARDCTL=y
CONFIG_BOARDCTL_RESET=y
CONFIG_BOARD_ASSERT_RESET_VALUE=0
CONFIG_BOARD_INITTHREAD_PRIORITY=254
CONFIG_BOARD_LATE_INITIALIZE=y
CONFIG_BOARD_LOOPSPERMSEC=95150
CONFIG_BOARD_RESET_ON_ASSERT=2
CONFIG_CDCACM=y
CONFIG_CDCACM_IFLOWCONTROL=y
CONFIG_CDCACM_PRODUCTID=0x0036
CONFIG_CDCACM_PRODUCTSTR="XC-FLY XC-SLAM Bootloader"
CONFIG_CDCACM_RXBUFSIZE=600
CONFIG_CDCACM_TXBUFSIZE=12000
CONFIG_CDCACM_VENDORID=0x1B8C
CONFIG_CDCACM_VENDORSTR="XC-FLY"
CONFIG_DEBUG_FULLOPT=y
CONFIG_DEBUG_SYMBOLS=y
CONFIG_DEBUG_TCBINFO=y
CONFIG_DEFAULT_SMALL=y
CONFIG_EXPERIMENTAL=y
CONFIG_FDCLONE_DISABLE=y
CONFIG_FDCLONE_STDIO=y
CONFIG_HAVE_CXX=y
CONFIG_HAVE_CXXINITIALIZE=y
CONFIG_IDLETHREAD_STACKSIZE=750
CONFIG_INIT_ENTRYPOINT="bootloader_main"
CONFIG_INIT_STACKSIZE=3194
CONFIG_LIBC_FLOATINGPOINT=y
CONFIG_LIBC_LONG_LONG=y
CONFIG_LIBC_STRERROR=y
CONFIG_MEMSET_64BIT=y
CONFIG_MEMSET_OPTSPEED=y
CONFIG_PREALLOC_TIMERS=50
CONFIG_PTHREAD_STACK_MIN=512
CONFIG_RAM_SIZE=245760
CONFIG_RAM_START=0x20010000
CONFIG_RAW_BINARY=y
CONFIG_SERIAL_TERMIOS=y
CONFIG_SIG_DEFAULT=y
CONFIG_SIG_SIGALRM_ACTION=y
CONFIG_SIG_SIGUSR1_ACTION=y
CONFIG_SIG_SIGUSR2_ACTION=y
CONFIG_SPI=y
CONFIG_STACK_COLORATION=y
CONFIG_START_DAY=30
CONFIG_START_MONTH=11
CONFIG_STDIO_BUFFER_SIZE=32
CONFIG_STM32H7_BKPSRAM=y
CONFIG_STM32H7_DMA1=y
CONFIG_STM32H7_OTGFS=y
CONFIG_STM32H7_PROGMEM=y
CONFIG_STM32H7_SERIAL_DISABLE_REORDERING=y
CONFIG_STM32H7_TIM1=y
CONFIG_STM32H7_USART6=y
CONFIG_SYSTEMTICK_HOOK=y
CONFIG_SYSTEM_CDCACM=y
CONFIG_TASK_NAME_SIZE=24
CONFIG_TTY_SIGINT=y
CONFIG_TTY_SIGINT_CHAR=0x03
CONFIG_TTY_SIGTSTP=y
CONFIG_USART6_RXBUFSIZE=600
CONFIG_USART6_TXBUFSIZE=300
CONFIG_USBDEV=y
CONFIG_USBDEV_BUSPOWERED=y
CONFIG_USBDEV_MAXPOWER=500
CONFIG_USEC_PER_TICK=1000
@@ -1,491 +0,0 @@
/************************************************************************************
* nuttx-configs/px4_fmu-v6u/include/board.h
*
* Copyright (C) 2016-2019 Gregory Nutt. All rights reserved.
* Authors: David Sidrane <david.sidrane@nscdg.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
************************************************************************************/
#ifndef __NUTTX_CONFIG_MATEKH743SLIM_INCLUDE_BOARD_H
#define __NUTTX_CONFIG_MATEKH743SLIM_INCLUDE_BOARD_H
/************************************************************************************
* Included Files
************************************************************************************/
#include "board_dma_map.h"
#include <nuttx/config.h>
#ifndef __ASSEMBLY__
# include <stdint.h>
#endif
#include "stm32_rcc.h"
#include "stm32_sdmmc.h"
/************************************************************************************
* Pre-processor Definitions
************************************************************************************/
/* Clocking *************************************************************************/
/* The MatekH743-Slim board provides the following clock sources:
*
* X1: 16 MHz crystal for HSE
*
* So we have these clock source available within the STM32
*
* HSI: 16 MHz RC factory-trimmed
* HSE: 16 MHz crystal for HSE
*/
#define STM32_BOARD_XTAL 8000000ul
#define STM32_HSI_FREQUENCY 16000000ul
#define STM32_LSI_FREQUENCY 32000
#define STM32_HSE_FREQUENCY STM32_BOARD_XTAL
#define STM32_LSE_FREQUENCY 32768
/* Main PLL Configuration.
*
* PLL source is HSE = 16,000,000
*
* PLL_VCOx = (STM32_HSE_FREQUENCY / PLLM) * PLLN
* Subject to:
*
* 1 <= PLLM <= 63
* 4 <= PLLN <= 512
* 150 MHz <= PLL_VCOL <= 420MHz
* 192 MHz <= PLL_VCOH <= 836MHz
*
* SYSCLK = PLL_VCO / PLLP
* CPUCLK = SYSCLK / D1CPRE
* Subject to
*
* PLLP1 = {2, 4, 6, 8, ..., 128}
* PLLP2,3 = {2, 3, 4, ..., 128}
* CPUCLK <= 480 MHz
*/
#define STM32_BOARD_USEHSE
#define STM32_PLLCFG_PLLSRC RCC_PLLCKSELR_PLLSRC_HSE
/* PLL1, wide 4 - 8 MHz input, enable DIVP, DIVQ, DIVR
*
* PLL1_VCO = (8,000,000 / 1) * 120 = 960 MHz
*
* PLL1P = PLL1_VCO/2 = 960 MHz / 2 = 480 MHz
* PLL1Q = PLL1_VCO/4 = 960 MHz / 4 = 240 MHz
* PLL1R = PLL1_VCO/8 = 960 MHz / 8 = 120 MHz
*/
#define STM32_PLLCFG_PLL1CFG (RCC_PLLCFGR_PLL1VCOSEL_WIDE | \
RCC_PLLCFGR_PLL1RGE_4_8_MHZ | \
RCC_PLLCFGR_DIVP1EN | \
RCC_PLLCFGR_DIVQ1EN | \
RCC_PLLCFGR_DIVR1EN)
#define STM32_PLLCFG_PLL1M RCC_PLLCKSELR_DIVM1(1)
#define STM32_PLLCFG_PLL1N RCC_PLL1DIVR_N1(120)
#define STM32_PLLCFG_PLL1P RCC_PLL1DIVR_P1(2)
#define STM32_PLLCFG_PLL1Q RCC_PLL1DIVR_Q1(4)
#define STM32_PLLCFG_PLL1R RCC_PLL1DIVR_R1(8)
#define STM32_VCO1_FREQUENCY ((STM32_HSE_FREQUENCY / 1) * 120)
#define STM32_PLL1P_FREQUENCY (STM32_VCO1_FREQUENCY / 2)
#define STM32_PLL1Q_FREQUENCY (STM32_VCO1_FREQUENCY / 4)
#define STM32_PLL1R_FREQUENCY (STM32_VCO1_FREQUENCY / 8)
/* PLL2 */
#define STM32_PLLCFG_PLL2CFG (RCC_PLLCFGR_PLL2VCOSEL_WIDE | \
RCC_PLLCFGR_PLL2RGE_4_8_MHZ | \
RCC_PLLCFGR_DIVP2EN | \
RCC_PLLCFGR_DIVQ2EN | \
RCC_PLLCFGR_DIVR2EN)
#define STM32_PLLCFG_PLL2M RCC_PLLCKSELR_DIVM2(2)
#define STM32_PLLCFG_PLL2N RCC_PLL2DIVR_N2(48)
#define STM32_PLLCFG_PLL2P RCC_PLL2DIVR_P2(2)
#define STM32_PLLCFG_PLL2Q RCC_PLL2DIVR_Q2(2)
#define STM32_PLLCFG_PLL2R RCC_PLL2DIVR_R2(2)
#define STM32_VCO2_FREQUENCY ((STM32_HSE_FREQUENCY / 2) * 48)
#define STM32_PLL2P_FREQUENCY (STM32_VCO2_FREQUENCY / 2)
#define STM32_PLL2Q_FREQUENCY (STM32_VCO2_FREQUENCY / 2)
#define STM32_PLL2R_FREQUENCY (STM32_VCO2_FREQUENCY / 2)
/* PLL3 */
#define STM32_PLLCFG_PLL3CFG (RCC_PLLCFGR_PLL3VCOSEL_WIDE | \
RCC_PLLCFGR_PLL3RGE_4_8_MHZ | \
RCC_PLLCFGR_DIVQ3EN)
#define STM32_PLLCFG_PLL3M RCC_PLLCKSELR_DIVM3(2)
#define STM32_PLLCFG_PLL3N RCC_PLL3DIVR_N3(48)
#define STM32_PLLCFG_PLL3P RCC_PLL3DIVR_P3(2)
#define STM32_PLLCFG_PLL3Q RCC_PLL3DIVR_Q3(4)
#define STM32_PLLCFG_PLL3R RCC_PLL3DIVR_R3(2)
#define STM32_VCO3_FREQUENCY ((STM32_HSE_FREQUENCY / 2) * 48)
#define STM32_PLL3P_FREQUENCY (STM32_VCO3_FREQUENCY / 2)
#define STM32_PLL3Q_FREQUENCY (STM32_VCO3_FREQUENCY / 4)
#define STM32_PLL3R_FREQUENCY (STM32_VCO3_FREQUENCY / 2)
/* SYSCLK = PLL1P = 480MHz
* CPUCLK = SYSCLK / 1 = 480 MHz
*/
#define STM32_RCC_D1CFGR_D1CPRE (RCC_D1CFGR_D1CPRE_SYSCLK)
#define STM32_SYSCLK_FREQUENCY (STM32_PLL1P_FREQUENCY)
#define STM32_CPUCLK_FREQUENCY (STM32_SYSCLK_FREQUENCY / 1)
/* Configure Clock Assignments */
/* AHB clock (HCLK) is SYSCLK/2 (240 MHz max)
* HCLK1 = HCLK2 = HCLK3 = HCLK4 = 240
*/
#define STM32_RCC_D1CFGR_HPRE RCC_D1CFGR_HPRE_SYSCLKd2 /* HCLK = SYSCLK / 2 */
#define STM32_ACLK_FREQUENCY (STM32_CPUCLK_FREQUENCY / 2) /* ACLK in D1, HCLK3 in D1 */
#define STM32_HCLK_FREQUENCY (STM32_CPUCLK_FREQUENCY / 2) /* HCLK in D2, HCLK4 in D3 */
#define STM32_BOARD_HCLK STM32_HCLK_FREQUENCY /* same as above, to satisfy compiler */
/* APB1 clock (PCLK1) is HCLK/2 (120 MHz) */
#define STM32_RCC_D2CFGR_D2PPRE1 RCC_D2CFGR_D2PPRE1_HCLKd2 /* PCLK1 = HCLK / 2 */
#define STM32_PCLK1_FREQUENCY (STM32_HCLK_FREQUENCY/2)
/* APB2 clock (PCLK2) is HCLK/2 (120 MHz) */
#define STM32_RCC_D2CFGR_D2PPRE2 RCC_D2CFGR_D2PPRE2_HCLKd2 /* PCLK2 = HCLK / 2 */
#define STM32_PCLK2_FREQUENCY (STM32_HCLK_FREQUENCY/2)
/* APB3 clock (PCLK3) is HCLK/2 (120 MHz) */
#define STM32_RCC_D1CFGR_D1PPRE RCC_D1CFGR_D1PPRE_HCLKd2 /* PCLK3 = HCLK / 2 */
#define STM32_PCLK3_FREQUENCY (STM32_HCLK_FREQUENCY/2)
/* APB4 clock (PCLK4) is HCLK/4 (120 MHz) */
#define STM32_RCC_D3CFGR_D3PPRE RCC_D3CFGR_D3PPRE_HCLKd2 /* PCLK4 = HCLK / 2 */
#define STM32_PCLK4_FREQUENCY (STM32_HCLK_FREQUENCY/2)
/* Timer clock frequencies */
/* Timers driven from APB1 will be twice PCLK1 */
#define STM32_APB1_TIM2_CLKIN (2*STM32_PCLK1_FREQUENCY)
#define STM32_APB1_TIM3_CLKIN (2*STM32_PCLK1_FREQUENCY)
#define STM32_APB1_TIM4_CLKIN (2*STM32_PCLK1_FREQUENCY)
#define STM32_APB1_TIM5_CLKIN (2*STM32_PCLK1_FREQUENCY)
#define STM32_APB1_TIM6_CLKIN (2*STM32_PCLK1_FREQUENCY)
#define STM32_APB1_TIM7_CLKIN (2*STM32_PCLK1_FREQUENCY)
#define STM32_APB1_TIM12_CLKIN (2*STM32_PCLK1_FREQUENCY)
#define STM32_APB1_TIM13_CLKIN (2*STM32_PCLK1_FREQUENCY)
#define STM32_APB1_TIM14_CLKIN (2*STM32_PCLK1_FREQUENCY)
/* Timers driven from APB2 will be twice PCLK2 */
#define STM32_APB2_TIM1_CLKIN (2*STM32_PCLK2_FREQUENCY)
#define STM32_APB2_TIM8_CLKIN (2*STM32_PCLK2_FREQUENCY)
#define STM32_APB2_TIM15_CLKIN (2*STM32_PCLK2_FREQUENCY)
#define STM32_APB2_TIM16_CLKIN (2*STM32_PCLK2_FREQUENCY)
#define STM32_APB2_TIM17_CLKIN (2*STM32_PCLK2_FREQUENCY)
/* Kernel Clock Configuration
*
* Note: look at Table 54 in ST Manual
*/
/* I2C123 clock source */
#define STM32_RCC_D2CCIP2R_I2C123SRC RCC_D2CCIP2R_I2C123SEL_HSI
/* I2C4 clock source */
#define STM32_RCC_D3CCIPR_I2C4SRC RCC_D3CCIPR_I2C4SEL_HSI
/* SPI123 clock source */
#define STM32_RCC_D2CCIP1R_SPI123SRC RCC_D2CCIP1R_SPI123SEL_PLL2
/* SPI45 clock source */
#define STM32_RCC_D2CCIP1R_SPI45SRC RCC_D2CCIP1R_SPI45SEL_PLL2
/* SPI6 clock source */
#define STM32_RCC_D3CCIPR_SPI6SRC RCC_D3CCIPR_SPI6SEL_PLL2
/* USB 1 and 2 clock source */
#define STM32_RCC_D2CCIP2R_USBSRC RCC_D2CCIP2R_USBSEL_PLL3
/* ADC 1 2 3 clock source */
#define STM32_RCC_D3CCIPR_ADCSEL RCC_D3CCIPR_ADCSEL_PLL2
/* FDCAN 1 clock source */
// #define STM32_RCC_D2CCIP1R_FDCANSEL RCC_D2CCIP1R_FDCANSEL_HSE /* FDCAN 1 2 clock source */
#define STM32_FDCANCLK STM32_HSE_FREQUENCY
/* FLASH wait states
*
* ------------ ---------- -----------
* Vcore MAX ACLK WAIT STATES
* ------------ ---------- -----------
* 1.15-1.26 V 70 MHz 0
* (VOS1 level) 140 MHz 1
* 210 MHz 2
* 1.05-1.15 V 55 MHz 0
* (VOS2 level) 110 MHz 1
* 165 MHz 2
* 220 MHz 3
* 0.95-1.05 V 45 MHz 0
* (VOS3 level) 90 MHz 1
* 135 MHz 2
* 180 MHz 3
* 225 MHz 4
* ------------ ---------- -----------
*/
#define BOARD_FLASH_WAITSTATES 2
/* SDMMC definitions ********************************************************/
/* Init 400kHz, freq = PLL1Q/(2*div) div = PLL1Q/(2*freq) */
#define STM32_SDMMC_INIT_CLKDIV (300 << STM32_SDMMC_CLKCR_CLKDIV_SHIFT)
/* 25 MHz Max for now, 25 mHZ = PLL1Q/(2*div), div = PLL1Q/(2*freq)
* div = 4.8 = 240 / 50, So round up to 5 for default speed 24 MB/s
*/
#if defined(CONFIG_STM32H7_SDMMC_XDMA) || defined(CONFIG_STM32H7_SDMMC_IDMA)
# define STM32_SDMMC_MMCXFR_CLKDIV (5 << STM32_SDMMC_CLKCR_CLKDIV_SHIFT)
#else
# define STM32_SDMMC_MMCXFR_CLKDIV (100 << STM32_SDMMC_CLKCR_CLKDIV_SHIFT)
#endif
#if defined(CONFIG_STM32H7_SDMMC_XDMA) || defined(CONFIG_STM32H7_SDMMC_IDMA)
# define STM32_SDMMC_SDXFR_CLKDIV (5 << STM32_SDMMC_CLKCR_CLKDIV_SHIFT)
#else
# define STM32_SDMMC_SDXFR_CLKDIV (100 << STM32_SDMMC_CLKCR_CLKDIV_SHIFT)
#endif
#define STM32_SDMMC_CLKCR_EDGE STM32_SDMMC_CLKCR_NEGEDGE
/* LED definitions ******************************************************************/
/* The board has two, LED_GREEN a Green LED and LED_BLUE a Blue LED,
* that can be controlled by software.
*
* If CONFIG_ARCH_LEDS is not defined, then the user can control the LEDs in any way.
* The following definitions are used to access individual LEDs.
*/
/* LED index values for use with board_userled() */
#define BOARD_LED1 0
#define BOARD_LED2 1
#define BOARD_LED3 2
#define BOARD_NLEDS 3
#define BOARD_LED_RED BOARD_LED1
#define BOARD_LED_GREEN BOARD_LED2
#define BOARD_LED_BLUE BOARD_LED3
/* LED bits for use with board_userled_all() */
#define BOARD_LED1_BIT (1 << BOARD_LED1)
#define BOARD_LED2_BIT (1 << BOARD_LED2)
#define BOARD_LED3_BIT (1 << BOARD_LED3)
/* If CONFIG_ARCH_LEDS is defined, the usage by the board port is defined in
* include/board.h and src/stm32_leds.c. The LEDs are used to encode OS-related
* events as follows:
*
*
* SYMBOL Meaning LED state
* Red Green Blue
* ---------------------- -------------------------- ------ ------ ----*/
#define LED_STARTED 0 /* NuttX has been started OFF OFF OFF */
#define LED_HEAPALLOCATE 1 /* Heap has been allocated OFF OFF ON */
#define LED_IRQSENABLED 2 /* Interrupts enabled OFF ON OFF */
#define LED_STACKCREATED 3 /* Idle stack created OFF ON ON */
#define LED_INIRQ 4 /* In an interrupt N/C N/C GLOW */
#define LED_SIGNAL 5 /* In a signal handler N/C GLOW N/C */
#define LED_ASSERTION 6 /* An assertion failed GLOW N/C GLOW */
#define LED_PANIC 7 /* The system has crashed Blink OFF N/C */
#define LED_IDLE 8 /* MCU is is sleep mode ON OFF OFF */
/* Thus if the Green LED is statically on, NuttX has successfully booted and
* is, apparently, running normally. If the Red LED is flashing at
* approximately 2Hz, then a fatal error has been detected and the system
* has halted.
*/
/* Alternate function pin selections ************************************************/
#define GPIO_USART1_RX GPIO_USART1_RX_2 /* PBA10 */
#define GPIO_USART1_TX GPIO_USART1_TX_2 /* PA9 */
#define GPIO_USART1_CK GPIO_USART1_CK /* PB8 NC */
#define GPIO_USART2_RX GPIO_USART2_RX_2 /* PD6 */
#define GPIO_USART2_TX GPIO_USART2_TX_2 /* PD5 */
#define GPIO_USART2_CK GPIO_USART2_CK_2 /* PD7 NC */
#define GPIO_USART3_RX GPIO_USART3_RX_3 /* PD9 */
#define GPIO_USART3_TX GPIO_USART3_TX_3 /* PD8 */
#define GPIO_USART3_CK GPIO_USART3_CK_3 /* PD10 NC */
#define GPIO_UART4_RX GPIO_UART4_RX_3 /* PB8 */
#define GPIO_UART4_TX GPIO_UART4_TX_3 /* PB9 */
#define GPIO_UART5_RX GPIO_UART5_RX_1 /* PB12 */
#define GPIO_UART5_TX GPIO_UART5_TX_1 /* PB13 */
#define GPIO_USART6_RX GPIO_USART6_RX_1 /* PC7 */
#define GPIO_USART6_TX GPIO_USART6_TX_1 /* PC6 */
#define GPIO_UART7_RX GPIO_UART7_RX_3 /* PE7 */
#define GPIO_UART7_TX GPIO_UART7_TX_3 /* PE8 NC */
#define GPIO_UART8_RX GPIO_UART8_RX_1 /* PE0 */
#define GPIO_UART8_TX GPIO_UART8_TX_1 /* PE1 */
/* SPI
*
*/
#define ADJ_SLEW_RATE(p) (((p) & ~GPIO_SPEED_MASK) | (GPIO_SPEED_2MHz))
#define GPIO_SPI1_MISO GPIO_SPI1_MISO_1 /* PA6 */
#define GPIO_SPI1_MOSI GPIO_SPI1_MOSI_1 /* PA7 */
#define GPIO_SPI1_SCK ADJ_SLEW_RATE(GPIO_SPI1_SCK_1) /* PA5 */
#define GPIO_SPI2_MISO GPIO_SPI2_MISO_1 /* PB14 */
#define GPIO_SPI2_MOSI GPIO_SPI2_MOSI_3 /* PC3 */
#define GPIO_SPI2_SCK ADJ_SLEW_RATE(GPIO_SPI2_SCK_5) /* PD3 */
#define GPIO_SPI3_MISO GPIO_SPI3_MISO_1 /* PB4 */
#define GPIO_SPI3_MOSI GPIO_SPI3_MOSI_3 /* PB2 */
#define GPIO_SPI3_SCK ADJ_SLEW_RATE(GPIO_SPI3_SCK_1) /* PB3 */
#define GPIO_SPI4_MISO GPIO_SPI4_MISO_2 /* PE5 */
#define GPIO_SPI4_MOSI GPIO_SPI4_MOSI_2 /* PE6 */
#define GPIO_SPI4_SCK ADJ_SLEW_RATE(GPIO_SPI4_SCK_2) /* PE2 */
/* I2C
*
*
*/
#define GPIO_I2C1_SCL GPIO_I2C1_SCL_1 /* PB6 */
#define GPIO_I2C1_SDA GPIO_I2C1_SDA_1 /* PB7 */
#define GPIO_I2C1_SCL_GPIO (GPIO_OUTPUT | GPIO_OPENDRAIN |GPIO_SPEED_50MHz | GPIO_OUTPUT_SET | GPIO_PORTB | GPIO_PIN6)
#define GPIO_I2C1_SDA_GPIO (GPIO_OUTPUT | GPIO_OPENDRAIN |GPIO_SPEED_50MHz | GPIO_OUTPUT_SET | GPIO_PORTB | GPIO_PIN7)
#define GPIO_I2C4_SCL GPIO_I2C4_SCL_1 /* PD12 */
#define GPIO_I2C4_SDA GPIO_I2C4_SDA_1 /* PD13 */
#define GPIO_I2C4_SCL_GPIO (GPIO_OUTPUT | GPIO_OPENDRAIN |GPIO_SPEED_50MHz | GPIO_OUTPUT_SET | GPIO_PORTD | GPIO_PIN12)
#define GPIO_I2C4_SDA_GPIO (GPIO_OUTPUT | GPIO_OPENDRAIN |GPIO_SPEED_50MHz | GPIO_OUTPUT_SET | GPIO_PORTD | GPIO_PIN13)
#define GPIO_CAN1_RX GPIO_CAN1_RX_3 /* PD0 */
#define GPIO_CAN1_TX GPIO_CAN1_TX_3 /* PD1 */
/* SDMMC1
*
* SDMMC1_D0 PC8
* SDMMC1_D1 PC9
* SDMMC1_D2 PC10
* SDMMC1_D3 PC11
* SDMMC1_CK PC12
* SDMMC1_CMD PD2
*/
// #define GPIO_SDMMC1_D0 GPIO_SDMMC1_D0 /* PC8 */
// #define GPIO_SDMMC1_D1 GPIO_SDMMC1_D1 /* PC9 */
// #define GPIO_SDMMC1_D2 GPIO_SDMMC1_D2 /* PC10 */
// #define GPIO_SDMMC1_D3 GPIO_SDMMC1_D3 /* PC11 */
// #define GPIO_SDMMC1_CK GPIO_SDMMC1_CK /* PC12 */
// #define GPIO_SDMMC1_CMD GPIO_SDMMC1_CMD /* PD2 */
/* USB
*
* OTG_FS_DM PA11
* OTG_FS_DP PA12
* VBUS PA9
*/
/* Board provides GPIO or other Hardware for signaling to timing analyzer */
// #if defined(CONFIG_BOARD_USE_PROBES)
// # include "stm32_gpio.h"
// # define PROBE_N(n) (1<<((n)-1))
// # define PROBE_1 (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTI|GPIO_PIN0) /* PI0 AUX1 */
// # define PROBE_2 (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTH|GPIO_PIN12) /* PH12 AUX2 */
// # define PROBE_3 (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTH|GPIO_PIN11) /* PH11 AUX3 */
// # define PROBE_4 (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTH|GPIO_PIN10) /* PH10 AUX4 */
// # define PROBE_5 (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTD|GPIO_PIN13) /* PD13 AUX5 */
// # define PROBE_6 (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTD|GPIO_PIN14) /* PD14 AUX6 */
// # define PROBE_7 (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTH|GPIO_PIN6) /* PH6 AUX7 */
// # define PROBE_8 (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTH|GPIO_PIN9) /* PH9 AUX8 */
// # define PROBE_9 (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTE|GPIO_PIN11) /* PE11 CAP1 */
// # define PROBE_INIT(mask) \
// do { \
// if ((mask)& PROBE_N(1)) { stm32_configgpio(PROBE_1); } \
// if ((mask)& PROBE_N(2)) { stm32_configgpio(PROBE_2); } \
// if ((mask)& PROBE_N(3)) { stm32_configgpio(PROBE_3); } \
// if ((mask)& PROBE_N(4)) { stm32_configgpio(PROBE_4); } \
// if ((mask)& PROBE_N(5)) { stm32_configgpio(PROBE_5); } \
// if ((mask)& PROBE_N(6)) { stm32_configgpio(PROBE_6); } \
// if ((mask)& PROBE_N(7)) { stm32_configgpio(PROBE_7); } \
// if ((mask)& PROBE_N(8)) { stm32_configgpio(PROBE_8); } \
// if ((mask)& PROBE_N(9)) { stm32_configgpio(PROBE_9); } \
// } while(0)
// # define PROBE(n,s) do {stm32_gpiowrite(PROBE_##n,(s));}while(0)
// # define PROBE_MARK(n) PROBE(n,false);PROBE(n,true)
// #else
// # define PROBE_INIT(mask)
// # define PROBE(n,s)
// # define PROBE_MARK(n)
// #endif
#endif /*__NUTTX_CONFIG_MATEKH743SLIM_INCLUDE_BOARD_H */
@@ -1,62 +0,0 @@
/****************************************************************************
*
* Copyright (c) 2021 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#pragma once
// #define DMAMAP_SPI1_RX DMAMAP_DMA12_SPI1RX_0 /* DMA1:37 */
// #define DMAMAP_SPI1_TX DMAMAP_DMA12_SPI1TX_0 /* DMA1:38 */
#define DMAMAP_SPI2_RX DMAMAP_DMA12_SPI2RX_0 /* DMA1:39 */
#define DMAMAP_SPI2_TX DMAMAP_DMA12_SPI2TX_0 /* DMA1:40 */
// DMAMUX2
// #define DMAMAP_SPI3_RX DMAMAP_DMA12_SPI3RX_0 /* DMA1:61 */
// #define DMAMAP_SPI3_TX DMAMAP_DMA12_SPI3TX_0 /* DMA1:62 */
// #define DMAMAP_SPI6_RX DMAMAP_BDMA_SPI6_RX /* BDMA:11 */
// #define DMAMAP_SPI6_TX DMAMAP_BDMA_SPI6_TX /* BDMA:12 */
//TODO: UART DMA test
// #define DMAMAP_USART1_RX DMAMAP_DMA12_USART1RX_1 /*DMA2:41*/
// #define DMAMAP_USART1_TX DMAMAP_DMA12_USART1TX_1 /*DMA2:42*/
// #define DMAMAP_USART2_RX DMAMAP_DMA12_USART2RX_1 /* DMA2:43 */
// #define DMAMAP_USART2_TX DMAMAP_DMA12_USART2TX_1 /* DMA2:44 */
// #define DMAMAP_USART3_RX DMAMAP_DMA12_USART3RX_1 /* DMA2:45 */
// #define DMAMAP_USART3_TX DMAMAP_DMA12_USART3TX_1 /* DMA2:46 */
#define DMAMAP_UART4_RX DMAMAP_DMA12_UART4RX_1 /* DMA1:63 */
#define DMAMAP_UART4_TX DMAMAP_DMA12_UART4TX_1 /* DMA1:64 */
// #define DMAMAP_UART5_RX DMAMAP_DMA12_UART5RX_0 /* DMA1:65 */
// #define DMAMAP_UART5_TX DMAMAP_DMA12_UART5RX_0 /* DMA1:66 */
@@ -1,213 +0,0 @@
/****************************************************************************
* scripts/script.ld
*
* Copyright (C) 2016, 2019 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/* The Durandal-v1 uses an STM32H743II has 2048Kb of main FLASH memory.
* The flash memory is partitioned into a User Flash memory and a System
* Flash memory. Each of these memories has two banks:
*
* 1) User Flash memory:
*
* Bank 1: Start address 0x0800:0000 to 0x080F:FFFF with 8 sectors, 128Kb each
* Bank 2: Start address 0x0810:0000 to 0x081F:FFFF with 8 sectors, 128Kb each
*
* 2) System Flash memory:
*
* Bank 1: Start address 0x1FF0:0000 to 0x1FF1:FFFF with 1 x 128Kb sector
* Bank 1: Start address 0x1FF4:0000 to 0x1FF5:FFFF with 1 x 128Kb sector
*
* 3) User option bytes for user configuration, only in Bank 1.
*
* In the STM32H743II, two different boot spaces can be selected through
* the BOOT pin and the boot base address programmed in the BOOT_ADD0 and
* BOOT_ADD1 option bytes:
*
* 1) BOOT=0: Boot address defined by user option byte BOOT_ADD0[15:0].
* ST programmed value: Flash memory at 0x0800:0000
* 2) BOOT=1: Boot address defined by user option byte BOOT_ADD1[15:0].
* ST programmed value: System bootloader at 0x1FF0:0000
*
* The Durandal has a Switch on board, the BOOT0 pin is at ground so by default,
* the STM32 will boot to address 0x0800:0000 in FLASH unless the swiutch is
* drepresed, then the boot will be from 0x1FF0:0000
*
* The STM32H743ZI also has 1024Kb of data SRAM.
* SRAM is split up into several blocks and into three power domains:
*
* 1) TCM SRAMs are dedicated to the Cortex-M7 and are accessible with
* 0 wait states by the Cortex-M7 and by MDMA through AHBS slave bus
*
* 1.1) 128Kb of DTCM-RAM beginning at address 0x2000:0000
*
* The DTCM-RAM is organized as 2 x 64Kb DTCM-RAMs on 2 x 32 bit
* DTCM ports. The DTCM-RAM could be used for critical real-time
* data, such as interrupt service routines or stack / heap memory.
* Both DTCM-RAMs can be used in parallel (for load/store operations)
* thanks to the Cortex-M7 dual issue capability.
*
* 1.2) 64Kb of ITCM-RAM beginning at address 0x0000:0000
*
* This RAM is connected to ITCM 64-bit interface designed for
* execution of critical real-times routines by the CPU.
*
* 2) AXI SRAM (D1 domain) accessible by all system masters except BDMA
* through D1 domain AXI bus matrix
*
* 2.1) 512Kb of SRAM beginning at address 0x2400:0000
*
* 3) AHB SRAM (D2 domain) accessible by all system masters except BDMA
* through D2 domain AHB bus matrix
*
* 3.1) 128Kb of SRAM1 beginning at address 0x3000:0000
* 3.2) 128Kb of SRAM2 beginning at address 0x3002:0000
* 3.3) 32Kb of SRAM3 beginning at address 0x3004:0000
*
* SRAM1 - SRAM3 are one contiguous block: 288Kb at address 0x3000:0000
*
* 4) AHB SRAM (D3 domain) accessible by most of system masters
* through D3 domain AHB bus matrix
*
* 4.1) 64Kb of SRAM4 beginning at address 0x3800:0000
* 4.1) 4Kb of backup RAM beginning at address 0x3880:0000
*
* When booting from FLASH, FLASH memory is aliased to address 0x0000:0000
* where the code expects to begin execution by jumping to the entry point in
* the 0x0800:0000 address range.
*/
MEMORY
{
itcm (rwx) : ORIGIN = 0x00000000, LENGTH = 64K
flash (rx) : ORIGIN = 0x08000000, LENGTH = 2048K
dtcm1 (rwx) : ORIGIN = 0x20000000, LENGTH = 64K
dtcm2 (rwx) : ORIGIN = 0x20010000, LENGTH = 64K
sram (rwx) : ORIGIN = 0x24000000, LENGTH = 512K
sram1 (rwx) : ORIGIN = 0x30000000, LENGTH = 128K
sram2 (rwx) : ORIGIN = 0x30020000, LENGTH = 128K
sram3 (rwx) : ORIGIN = 0x30040000, LENGTH = 32K
sram4 (rwx) : ORIGIN = 0x38000000, LENGTH = 64K
bbram (rwx) : ORIGIN = 0x38800000, LENGTH = 4K
}
OUTPUT_ARCH(arm)
EXTERN(_vectors)
ENTRY(_stext)
/*
* Ensure that abort() is present in the final object. The exception handling
* code pulled in by libgcc.a requires it (and that code cannot be easily avoided).
*/
EXTERN(abort)
EXTERN(_bootdelay_signature)
SECTIONS
{
.text : {
_stext = ABSOLUTE(.);
*(.vectors)
. = ALIGN(32);
/*
This signature provides the bootloader with a way to delay booting
*/
_bootdelay_signature = ABSOLUTE(.);
FILL(0xffecc2925d7d05c5)
. += 8;
*(.text .text.*)
*(.fixup)
*(.gnu.warning)
*(.rodata .rodata.*)
*(.gnu.linkonce.t.*)
*(.glue_7)
*(.glue_7t)
*(.got)
*(.gcc_except_table)
*(.gnu.linkonce.r.*)
_etext = ABSOLUTE(.);
} > flash
/*
* Init functions (static constructors and the like)
*/
.init_section : {
_sinit = ABSOLUTE(.);
KEEP(*(.init_array .init_array.*))
_einit = ABSOLUTE(.);
} > flash
.ARM.extab : {
*(.ARM.extab*)
} > flash
__exidx_start = ABSOLUTE(.);
.ARM.exidx : {
*(.ARM.exidx*)
} > flash
__exidx_end = ABSOLUTE(.);
_eronly = ABSOLUTE(.);
.data : {
_sdata = ABSOLUTE(.);
*(.data .data.*)
*(.gnu.linkonce.d.*)
CONSTRUCTORS
_edata = ABSOLUTE(.);
} > sram AT > flash
.bss : {
_sbss = ABSOLUTE(.);
*(.bss .bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
_ebss = ABSOLUTE(.);
} > sram
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_info 0 : { *(.debug_info) }
.debug_line 0 : { *(.debug_line) }
.debug_pubnames 0 : { *(.debug_pubnames) }
.debug_aranges 0 : { *(.debug_aranges) }
}
@@ -1,228 +0,0 @@
/****************************************************************************
* scripts/script.ld
*
* Copyright (C) 2020 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/* The board uses an STM32H743II and has 2048Kb of main FLASH memory.
* The flash memory is partitioned into a User Flash memory and a System
* Flash memory. Each of these memories has two banks:
*
* 1) User Flash memory:
*
* Bank 1: Start address 0x0800:0000 to 0x080F:FFFF with 8 sectors, 128Kb each
* Bank 2: Start address 0x0810:0000 to 0x081F:FFFF with 8 sectors, 128Kb each
*
* 2) System Flash memory:
*
* Bank 1: Start address 0x1FF0:0000 to 0x1FF1:FFFF with 1 x 128Kb sector
* Bank 1: Start address 0x1FF4:0000 to 0x1FF5:FFFF with 1 x 128Kb sector
*
* 3) User option bytes for user configuration, only in Bank 1.
*
* In the STM32H743II, two different boot spaces can be selected through
* the BOOT pin and the boot base address programmed in the BOOT_ADD0 and
* BOOT_ADD1 option bytes:
*
* 1) BOOT=0: Boot address defined by user option byte BOOT_ADD0[15:0].
* ST programmed value: Flash memory at 0x0800:0000
* 2) BOOT=1: Boot address defined by user option byte BOOT_ADD1[15:0].
* ST programmed value: System bootloader at 0x1FF0:0000
*
* There's a switch on board, the BOOT0 pin is at ground so by default,
* the STM32 will boot to address 0x0800:0000 in FLASH unless the switch is
* drepresed, then the boot will be from 0x1FF0:0000
*
* The STM32H743ZI also has 1024Kb of data SRAM.
* SRAM is split up into several blocks and into three power domains:
*
* 1) TCM SRAMs are dedicated to the Cortex-M7 and are accessible with
* 0 wait states by the Cortex-M7 and by MDMA through AHBS slave bus
*
* 1.1) 128Kb of DTCM-RAM beginning at address 0x2000:0000
*
* The DTCM-RAM is organized as 2 x 64Kb DTCM-RAMs on 2 x 32 bit
* DTCM ports. The DTCM-RAM could be used for critical real-time
* data, such as interrupt service routines or stack / heap memory.
* Both DTCM-RAMs can be used in parallel (for load/store operations)
* thanks to the Cortex-M7 dual issue capability.
*
* 1.2) 64Kb of ITCM-RAM beginning at address 0x0000:0000
*
* This RAM is connected to ITCM 64-bit interface designed for
* execution of critical real-times routines by the CPU.
*
* 2) AXI SRAM (D1 domain) accessible by all system masters except BDMA
* through D1 domain AXI bus matrix
*
* 2.1) 512Kb of SRAM beginning at address 0x2400:0000
*
* 3) AHB SRAM (D2 domain) accessible by all system masters except BDMA
* through D2 domain AHB bus matrix
*
* 3.1) 128Kb of SRAM1 beginning at address 0x3000:0000
* 3.2) 128Kb of SRAM2 beginning at address 0x3002:0000
* 3.3) 32Kb of SRAM3 beginning at address 0x3004:0000
*
* SRAM1 - SRAM3 are one contiguous block: 288Kb at address 0x3000:0000
*
* 4) AHB SRAM (D3 domain) accessible by most of system masters
* through D3 domain AHB bus matrix
*
* 4.1) 64Kb of SRAM4 beginning at address 0x3800:0000
* 4.1) 4Kb of backup RAM beginning at address 0x3880:0000
*
* When booting from FLASH, FLASH memory is aliased to address 0x0000:0000
* where the code expects to begin execution by jumping to the entry point in
* the 0x0800:0000 address range.
*/
MEMORY
{
ITCM_RAM (rwx) : ORIGIN = 0x00000000, LENGTH = 64K
FLASH (rx) : ORIGIN = 0x08020000, LENGTH = 1792K
DTCM1_RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 64K
DTCM2_RAM (rwx) : ORIGIN = 0x20010000, LENGTH = 64K
AXI_SRAM (rwx) : ORIGIN = 0x24000000, LENGTH = 512K /* D1 domain AXI bus */
SRAM1 (rwx) : ORIGIN = 0x30000000, LENGTH = 128K /* D2 domain AHB bus */
SRAM2 (rwx) : ORIGIN = 0x30020000, LENGTH = 128K /* D2 domain AHB bus */
SRAM3 (rwx) : ORIGIN = 0x30040000, LENGTH = 32K /* D2 domain AHB bus */
SRAM4 (rwx) : ORIGIN = 0x38000000, LENGTH = 64K /* D3 domain */
BKPRAM (rwx) : ORIGIN = 0x38800000, LENGTH = 4K
}
OUTPUT_ARCH(arm)
EXTERN(_vectors)
ENTRY(_stext)
/*
* Ensure that abort() is present in the final object. The exception handling
* code pulled in by libgcc.a requires it (and that code cannot be easily avoided).
*/
EXTERN(abort)
EXTERN(_bootdelay_signature)
SECTIONS
{
.text : {
_stext = ABSOLUTE(.);
*(.vectors)
. = ALIGN(32);
/*
This signature provides the bootloader with a way to delay booting
*/
_bootdelay_signature = ABSOLUTE(.);
FILL(0xffecc2925d7d05c5)
. += 8;
*(.text .text.*)
*(.fixup)
*(.gnu.warning)
*(.rodata .rodata.*)
*(.gnu.linkonce.t.*)
*(.glue_7)
*(.glue_7t)
*(.got)
*(.gcc_except_table)
*(.gnu.linkonce.r.*)
_etext = ABSOLUTE(.);
} > FLASH
/*
* Init functions (static constructors and the like)
*/
.init_section : {
_sinit = ABSOLUTE(.);
KEEP(*(.init_array .init_array.*))
_einit = ABSOLUTE(.);
} > FLASH
.ARM.extab : {
*(.ARM.extab*)
} > FLASH
__exidx_start = ABSOLUTE(.);
.ARM.exidx : {
*(.ARM.exidx*)
} > FLASH
__exidx_end = ABSOLUTE(.);
_eronly = ABSOLUTE(.);
.data : {
_sdata = ABSOLUTE(.);
*(.data .data.*)
*(.gnu.linkonce.d.*)
CONSTRUCTORS
_edata = ABSOLUTE(.);
/* Pad out last section as the STM32H7 Flash write size is 256 bits. 32 bytes */
. = ALIGN(16);
FILL(0xffff)
. += 16;
} > AXI_SRAM AT > FLASH = 0xffff
.bss : {
_sbss = ABSOLUTE(.);
*(.bss .bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
_ebss = ABSOLUTE(.);
} > AXI_SRAM
/* Emit the the D3 power domain section for locating BDMA data */
.sram4_reserve (NOLOAD) :
{
*(.sram4)
. = ALIGN(4);
_sram4_heap_start = ABSOLUTE(.);
} > SRAM4
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_info 0 : { *(.debug_info) }
.debug_line 0 : { *(.debug_line) }
.debug_pubnames 0 : { *(.debug_pubnames) }
.debug_aranges 0 : { *(.debug_aranges) }
}
-69
View File
@@ -1,69 +0,0 @@
############################################################################
#
# Copyright (c) 2021 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# 3. Neither the name PX4 nor the names of its contributors may be
# used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
############################################################################
if("${PX4_BOARD_LABEL}" STREQUAL "bootloader")
add_library(drivers_board
bootloader_main.c
usb.c
)
target_link_libraries(drivers_board
PRIVATE
nuttx_arch
nuttx_drivers
bootloader
)
target_include_directories(drivers_board PRIVATE ${PX4_SOURCE_DIR}/platforms/nuttx/src/bootloader/common)
else()
add_library(drivers_board
i2c.cpp
init.c
led.c
sdio.c
spi.cpp
timer_config.cpp
usb.c
mtd.cpp
)
# add_dependencies(drivers_board arch_board_hw_info)
target_link_libraries(drivers_board
PRIVATE
arch_io_pins
arch_spi
arch_board_hw_info
drivers__led
nuttx_arch
nuttx_drivers
px4_layer
)
endif()
-234
View File
@@ -1,234 +0,0 @@
/****************************************************************************
*
* Copyright (c) 2021 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file board_config.h
*
* Board internal definitions
*/
#pragma once
/****************************************************************************************************
* Included Files
****************************************************************************************************/
#include <px4_platform_common/px4_config.h>
#include <nuttx/compiler.h>
#include <stdint.h>
#include <stm32_gpio.h>
/****************************************************************************************************
* Definitions
****************************************************************************************************/
#define FLASH_BASED_PARAMS
/* LEDs are driven with push open drain to support Anode to 5V or 3.3V */
# define GPIO_nLED_RED /* PD15 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_50MHz|GPIO_OUTPUT_SET|GPIO_PORTD|GPIO_PIN15)
# define GPIO_nLED_GREEN /* PD11 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_50MHz|GPIO_OUTPUT_SET|GPIO_PORTD|GPIO_PIN11)
# define GPIO_nLED_BLUE /* PB15 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_50MHz|GPIO_OUTPUT_SET|GPIO_PORTB|GPIO_PIN15)
# define BOARD_HAS_CONTROL_STATUS_LEDS 1
# define BOARD_OVERLOAD_LED LED_RED
# define BOARD_ARMED_STATE_LED LED_BLUE
/*
* ADC channels
*
* These are the channel numbers of the ADCs of the microcontroller that
* can be used by the Px4 Firmware in the adc driver
*/
/* ADC defines to be used in sensors.cpp to read from a particular channel */
#define SYSTEM_ADC_BASE STM32_ADC1_BASE
#define ADC12_CH(n) (n)
#define PX4_ADC_GPIO \
/* PC4 */ GPIO_ADC12_INP4, \
/* PC5 */ GPIO_ADC12_INP8
/* Define GPIO pins used as ADC N.B. Channel numbers must match below */
/* Define Channel numbers must match above GPIO pin IN(n)*/
#define ADC_BATTERY_VOLTAGE_CHANNEL ADC12_CH(4)
#define ADC_BATTERY_CURRENT_CHANNEL ADC12_CH(8)
#define ADC_CHANNELS \
((1 << ADC_BATTERY_VOLTAGE_CHANNEL) | \
(1 << ADC_BATTERY_CURRENT_CHANNEL))
#define BOARD_ADC_OPEN_CIRCUIT_V (1.6f)
/* Define Battery 1 Voltage Divider and A per V
*/
// #define BOARD_BATTERY1_V_DIV (11.0f) /* measured with the provided PM board */
// #define BOARD_BATTERY1_A_PER_V (40.0f)
// #define BOARD_BATTERY2_V_DIV (11.0f) /* measured with the provided PM board */
/* PWM
*/
#define DIRECT_PWM_OUTPUT_CHANNELS 8
#define BOARD_HAS_PWM DIRECT_PWM_OUTPUT_CHANNELS
// /* HEATER PA15 TIM2_CH1
// * PWM in future
// */
// #define GPIO_HEATER1_OUTPUT /* PA15 T2CH1 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTA|GPIO_PIN15)
// #define HEATER1_OUTPUT_EN(on_true) px4_arch_gpiowrite(GPIO_HEATER1_OUTPUT, (on_true))
/* Spare GPIO */
#define GPIO_PA4 /* PA4 */ (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN4)
#define GPIO_PC0 /* PC0 */ (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTC|GPIO_PIN0)
#define GPIO_PC1 /* PC1 */ (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTC|GPIO_PIN1)
/* Tone alarm output */
#define TONE_ALARM_TIMER 2 /* Timer 2*/
#define TONE_ALARM_CHANNEL 1 /* PA15 GPIO_TIM2_CH1 NC */
/*NC can be modified with Spare GPIO then connected with hardware */
#define GPIO_BUZZER_1 /* PA15 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTA|GPIO_PIN15)
#define GPIO_TONE_ALARM_IDLE GPIO_BUZZER_1
#define GPIO_TONE_ALARM GPIO_BUZZER_1
#define GPIO_TONE_ALARM_GPIO /* PA15 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTA|GPIO_PIN15)
/* USB OTG FS
*
* PE15 OTG_FS_VBUS VBUS sensing
*/
#define GPIO_OTGFS_VBUS /* PE15 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_SPEED_100MHz|GPIO_PORTE|GPIO_PIN15)
#define BOARD_ADC_USB_CONNECTED (px4_arch_gpioread(GPIO_OTGFS_VBUS))
/* High-resolution timer */
#define HRT_TIMER 8 /* use timer1 for the HRT */
#define HRT_TIMER_CHANNEL 1 /* use capture/compare channel 1 */
/* RC Serial port */
#define RC_SERIAL_PORT "/dev/ttyS4"
#define BOARD_SUPPORTS_RC_SERIAL_PORT_OUTPUT
// #define GPIO_SBUS_INV (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTD|GPIO_PIN14)
// #define RC_INVERT_INPUT(_invert_true) px4_arch_gpiowrite(GPIO_SBUS_INV, _invert_true);
/* SD card bringup does not work if performed on the IDLE thread because it
* will cause waiting. Use either:
*
* CONFIG_LIB_BOARDCTL=y, OR
* CONFIG_BOARD_INITIALIZE=y && CONFIG_BOARD_INITTHREAD=y
*/
#define SDIO_SLOTNO 0 /* Only one slot */
#define SDIO_MINOR 0
#if defined(CONFIG_BOARD_INITIALIZE) && !defined(CONFIG_LIB_BOARDCTL) && \
!defined(CONFIG_BOARD_INITTHREAD)
# warning SDIO initialization cannot be perfomed on the IDLE thread
#endif
/* This board provides a DMA pool and APIs */
#define BOARD_DMA_ALLOC_POOL_SIZE 5120
/* This board provides the board_on_reset interface */
#define BOARD_HAS_ON_RESET 1
#define PX4_GPIO_INIT_LIST { \
GPIO_CAN1_TX,\
GPIO_CAN1_RX, \
PX4_ADC_GPIO, \
GPIO_PC0, \
GPIO_PC1, \
GPIO_TONE_ALARM_IDLE, \
}
#define BOARD_ENABLE_CONSOLE_BUFFER
#define BOARD_NUM_IO_TIMERS 5
__BEGIN_DECLS
/****************************************************************************************************
* Public Types
****************************************************************************************************/
/****************************************************************************************************
* Public data
****************************************************************************************************/
#ifndef __ASSEMBLY__
/****************************************************************************************************
* Public Functions
****************************************************************************************************/
/****************************************************************************
* Name: stm32_sdio_initialize
*
* Description:
* Initialize SDIO-based MMC/SD card support
*
****************************************************************************/
int stm32_sdio_initialize(void);
/****************************************************************************************************
* Name: stm32_spiinitialize
*
* Description:
* Called to configure SPI chip select GPIO pins for the board.
*
****************************************************************************************************/
extern void stm32_spiinitialize(void);
extern void stm32_usbinitialize(void);
extern void board_peripheral_reset(int ms);
#include <px4_platform_common/board_common.h>
#endif /* __ASSEMBLY__ */
__END_DECLS

Some files were not shown because too many files have changed in this diff Show More