Change the mutations to use `Pmut` and change the define to keep the
non-mutations from accidentally mutating.
All these mutations only touched the diagonals, so no risk of them
having broken symmetry.
Change their define so they don't use the mutable original, only the
name through a const-cast pointer. There are no writes to the covariance
matrix in these files, so nothing else needs changing.
In preparation for changing the regular `P` name to const, in
preparation for auditing the code so that writes to the matrix keep its
necessary numeric properties.
Sadly there is not a better way than a per-file `#define` to make the
switch. Making `P` a reference to `Pmut` substantially changes the
compiler output. Defining `P` in the header file conflicts with other
includes. Doing the rename at the top of each file allows each file to
be fixed independently.
It is the only HAL that sets `-Wframe-larger-than` so it is the only one
where the limit needs modification to fit the EKF.
ChibiOS additionally does not use Clang, so that check can be dropped.
MAVFTP defines @MAV_LOG as the flight-stack-independent location for log
files, so that a GCS can find them without being told where a particular
board keeps them. QGroundControl asks for it before anything else, and
falls back to guessing per-firmware paths when it is not there.
It is an alias rather than a filesystem of its own: the backend table
gains a root, and where a row carries one the resolver rewrites a path
under that prefix to sit under that directory before handing it to the
filesystem which serves it. @MAV_LOG points at the local filesystem, under
whatever directory this board logs to, following a custom log directory
the same way AP_Logger_File does.
The rewritten path has to hold the root as well as the path, so the buffer
is sized for the longest path an FTP listing stats - the longest path a
request can carry, a separator and a 255 byte name - underneath the longest
log directory a board has, and a static_assert holds boards to that. A
path too long to rewrite is refused with ENAMETOOLONG before any filesystem
sees it, rather than being truncated into the name of some other file.
That buffer is not on the stack, where every path-based call would pay for
it. It is allocated the first time an alias is used and kept, and a
semaphore is held around each backend call which uses it. rename, the one
call with two paths alive at once, allocates a second buffer for its new
path and frees it afterwards. Paths which are not aliases take neither the
semaphore nor a buffer.
An alias can't sit on LittleFS for now, and @MAV_LOG is not built where
LittleFS is the local filesystem; forcing it on is a build error. LittleFS
holds its lock from opendir() to closedir(), so the semaphore, held across
each call, would be released before that lock, which ChibiOS mutexes do not
allow, and a thread listing an alias directory would wait for the semaphore
while holding the lock another thread holding the semaphore could be
waiting for.
rename now compares the filesystems which serve its two paths rather than
their table rows, since an alias shares its filesystem with other paths,
and sets EXDEV when they differ.
A prefix now has to be the whole of a path's first component, so that
"@MAV_LOG_backup" is not served as "_backup" under the log directory. This
is not particular to the alias: "@SYSfoo" used to be served by @SYS as
"foo", and is now the local file of that name. Nothing in the tree relied
on the old behaviour.
@MAV_LOG, and the alias support with it, is only built where the logs go
to a filesystem at all.
A tab separates the fields of a listing entry, so a name containing one
cannot be represented. The MAVFTP spec (mavlink-devguide#738) has such an
entry sent as a skip entry, which keeps entry offsets consistent, and
ListDirectoryWithTime follows List Directory in this. Plain listings are
left sending the name as they always have.
The listing format gives every entry a size, and ListDirectoryWithTime
gives every entry a time as well, with the type character the only thing
distinguishing a directory from a file. We emitted a bare "D<name>" for a
directory instead, so a client parsing the documented three fields found
only one.
A directory has no meaningful size, so it is reported as zero. Listing
with times now has to stat a directory as well; one which cannot be
stat'ed is still listed, with its time reported as unknown.
Plain ListDirectory is unchanged: it still emits the bare "D<name>" it
always has, so no existing client sees a different directory entry.
MAVSDK's server already sends these fields and its client parses them.
QGroundControl assumed a directory entry was a bare name; a fix for that
is in hand.
The listing format defines an mtime of zero as "the autopilot does not
know when this file was written", but no filesystem we have ever emits
it. FATFS stamps a file with the FAT epoch, 1980-01-01, when it has no
RTC to ask - and RTC_TYPES defaults to GPS only, so a vehicle which has
not had a fix stamps every file it writes that way. Confirmed on a
ZeroOneX6: every file on the card, across dozens of boots, comes back
as 1980-01-01.
Nothing at or before the FAT epoch is a real modification time, so send
the zero the format defines and let the client say it does not know.
Done here rather than in AP_Filesystem_FATFS::stat(), whose st_mtime
also reaches LOG_ENTRY.time_utc and the scripting stat() binding.
This extends MAVLink FTP to support the new opcode that allows to list
files with modification time in UTC.
This is according to the new spec in:
https://github.com/mavlink/mavlink-devguide/pull/701
(cherry picked from commit 4bc2447cb676f36bf0d712798beacf1de69440f3)
RCOutput_PRU, RCOutput_AioPRU_PB2 and RCOutput_AeroIO wrote into their
channel arrays without checking the channel number; every other Linux
RCOutput backend already does. On PRU the overrun is particularly
unpleasant as pending[MAX_PWMS] aliases the corked flag, so a write to
channel 12 uncorks the backend and makes the subsequent push() a no-op.
SRV_Channels::output_ch_all() already sweeps 16 channels by default,
so these overruns are reachable today on pxf, erleboard and pocket2.
This reverts commit 2f87db990f.
PR #34359 was merged by mistake. On the bench, with an ESC on
YJUAV_A6SE_H743 output 1, the hold presents a continuous high (full
throttle to a PWM ESC) for about 10.5s after every reset, and for as
long as safety is engaged when output 1 is a motor outside
BRD_SAFETY_MASK, which is Copter's default. The ESC started to enter
throttle calibration. Back the change out until the hold can be
chosen per output.
This reverts commit 239f5c1f97.
PR #34359 was merged by mistake. On the bench, with an ESC on
YJUAV_A6SE_H743 output 1, the hold presents a continuous high (full
throttle to a PWM ESC) for about 10.5s after every reset, and for as
long as safety is engaged when output 1 is a motor outside
BRD_SAFETY_MASK, which is Copter's default. The ESC started to enter
throttle calibration. Back the change out until the hold can be
chosen per output.
This reverts commit 67fd60ce26.
PR #34359 was merged by mistake. On the bench, with an ESC on
YJUAV_A6SE_H743 output 1, the hold presents a continuous high (full
throttle to a PWM ESC) for about 10.5s after every reset, and for as
long as safety is engaged when output 1 is a motor outside
BRD_SAFETY_MASK, which is Copter's default. The ESC started to enter
throttle calibration. Back the change out until the hold can be
chosen per output.
PWM1 is on PA15, the JTDI pin, whose reset and power-on pull-up gave the
M1 servo a short pulse on every boot. Declare it HOLD_HIGH so the
application keeps it a pulled-up input until RCOutput's first real
frame, matching the bootloader, which already keeps the pull-up.
The STM32 JTAG pins JTDI (PA15) and NJTRST (PB4) come out of every
reset, and out of power-on, with an internal pull-up enabled, and 84
hwdef directories in the tree route a PWM output through one of them:
61 through PA15, 38 through PB4, 15 through both. A servo on such an
output sees the line pulled high from then until firmware reconfigures
the pin. On the H743 that measured 692us to the bootloader's board init
on a warm reset, and 496us and 520us on two cold power-ons. Each is a
pulse inside the range servos accept, so the servo drives to an endpoint
and holds it through the rest of the boot. Nothing can shorten that
window, since no code runs during it.
Give hwdef a HOLD_HIGH keyword for PWM pins. The generator emits such a
pin as a pulled-up input with its timer alternate function preset, and a
HAL_PWM_HOLD_HIGH_MASK of the channels concerned. It rejects the keyword
on any pin RCOutput will never hand back to a timer: anything other than
a PWM(n) timer output in the main configuration, so also an RC input, the
alarm and an ALT(n) pin. One predicate decides both that and which pins
get a mask bit, so the two cannot disagree. The check is made when the
pin is parsed, which covers bootloader builds too. STM32F1 is rejected
outright, since its pin setup does not honour the keyword at all.
RCOutput keeps each channel an input until the first non-zero value is
pushed to it, in the PWM and DShot output paths, and only then switches
the pin to the timer. With the bootloader also keeping the pull-up, the
line is high continuously from the reset until the first real frame,
which for a channel outside BRD_SAFETY_MASK means until safety is
disarmed, so the servo sees a high far longer than any valid pulse
rather than a plausible short one followed by seconds of silence. On
the bench the test servo did not move at all across ten reboots.
The mode switch is an unlocked read-modify-write of the port registers,
and other threads change the modes of other pins on the same port, so
a single write can be lost. The channel is therefore not marked handed
over until a later output finds the pin already in alternate mode; until
then each output writes the mode again, so a lost write is repaired one
output later rather than leaving the pin an input until reboot.
Several other owners of a pad have to take it explicitly, because none
of them goes through the normal output path:
- the alarm driver configures a timer and never the pad, and disables
the group's channels first, so the hold on the alarm's own channel is
released before that. Only that channel: no real frame will ever
arrive for the rest of the group, so a HOLD_HIGH pin among them is
correctly left held;
- soft serial saves and restores the pad's mode, so BLHeli passthrough
hands the pin over when it selects it, or it would save "input" and
transmit nothing;
- neopixel and ProfiLED output is chosen at runtime by SERVOx_FUNCTION
on an ordinary PWM(n) pin and is sent without push_local(), so the
serial LED path releases its group's pads before driving them;
- DShot commands such as beeps are sent before arming, when nothing has
released the pad yet, so the command path releases every channel it
transmits on;
- bidirectional DShot, when enabled at runtime, takes the pads of a
whole group during init, so it clears the pending bit there. A pin
merely declared BIDIR keeps its hold; one whose group has bidirectional
DShot enabled gets no protection. The hwdef allows HOLD_HIGH and BIDIR
together deliberately.
Verified under Renode on YJUAV_A6SE_H743 with ArduPlane: the
application's board init leaves PA15 an input, it stays one through
24.8s of init, and the mode write that puts it on TIM2 lands at the same
microsecond as the first non-zero CCR1 write. With the first mode write
dropped on purpose, the next output found PA15 still an input and wrote
it; unmodified, the second output sees the mode has held and later
outputs no longer read the port. MatekF405-TE and the IOMCU
firmware still build, and a no-mask board's firmware is byte-identical.
PA15 drives PWM1 on this board and is also JTDI, which the STM32H743
brings out of every reset, and out of power-on, with its internal
pull-up enabled. The M1 servo line is therefore held high from then
until the bootloader's board init reconfigured the pin as a floating
input. On logic-analyser captures of the real board that is 692us on a
warm reset, and 496us and 520us on two cold power-ons, one over USB and
one at 12V. Each of those is a pulse inside the range most servos
accept, and it sent the servo to an extreme.
Configure PA15 as an input with pull-up in the bootloader instead, so
the line stays high continuously until the application switches the pin
to its timer, whose idle level is low. The servo then sees one high
lasting the whole bootloader, far outside any valid pulse width, rather
than a plausible command. Verified under Renode with the bootloader
held: PA15 reads input with pull-up while the bootloader owns the pins.
DEVTYPE_RM3100_2 (0x12) was introduced by dd4cf6ccdd and reverted by
a0cf4e158a; no release firmware used it. Tools/scripts/decode_devid.py
shows this comment as a warning when decoding such an ID.
Parameter conversion tables whose entries all share an old key found at
runtime (e.g. via find_top_level_key_by_pointer()) cannot be constant
if the key is stored in each entry, so a static table is initialised at
runtime and kept in RAM. Adding a ConversionInfoNoKey table type plus
convert_old_parameters() and convert_old_parameters_scaled() overloads
which take the key separately allows these tables to be placed in
.rodata.
terrain_srtm_alt_ms is zero until the first writeTerrainData, and
imuSampleTime_ms counts from boot, so for the first five seconds of uptime
the age test passes against a terrain altitude that is still zero.
terrain_srtm_alt_valid then reports a terrain height the core has never
received: FuseOptFlow scales flow from it, getHeightControlLimit drops the
optical flow altitude cap, and getFilterStatus counts it towards relative
position validity.
On the ground at boot that costs little, since the value it invents is the
height above an origin the vehicle is sitting on. It matters after an
in-flight watchdog reset, where millis() restarts at zero and the vehicle
comes back armed and flying.
gndHgtValidTime_ms is guarded against exactly this one expression away, so
this is the same idiom rather than a new one. The 5 s is named while it is
being touched, because it is about to have a second user.
No autotest: the window is the first five seconds of uptime and closes
before healthy() opens, so SITL cannot enter it from a cold boot, and the
in-flight reset that reaches it is not something the harness can stage.
terrain_srtm_alt is the terrain height above the EKF origin, positive up:
AP_AHRS::writeTerrainAMSL() converts the AMSL height AP_Terrain supplies
with alt_amsl_m - origin.alt, and the core stores it verbatim. pd is the
vehicle's position.z, positive down. Height above ground is therefore (-pd)
minus the terrain height, not the terrain height minus pd. The neighbouring
terrainState expression is right because terrainState is itself a D
coordinate, built as position.z + rngOnGnd, so the two branches of one
variable were being differenced in opposite conventions.
Where the AHRS and core origins coincide the old error is 2 x
terrain_srtm_alt, so it is smallest where the origin sits at field
elevation and grows with relief - and it moves the wrong way, reading high
over ground that is above the origin. AP_AHRS subtracts the one public
origin and hands the same figure to every core, which then differences it
against its own position.z, so where a core's own origin altitude has moved
- ekfGpsRefHgt drift, or lanes aligning against different receivers under
EK3_AFFINITY - the corrected form still carries that difference. The trace
here is complete only for the default EK3_OGN_HGT_MASK.
A terrain height that disagrees with the datum still collapses the scale
height to the on-ground range through the MAX, exactly as it does today.
The old expression could go negative too - over ground that sits further
below the origin than the vehicle sits above it - so this is pre-existing,
and the sign fix moves which geometry triggers it rather than closing it.
Falling back to terrainState there is the obvious repair and it does not
work: the enclosing condition has already declared that state stale.
Measured in SITL off the Kalaupapa cliffs, holding 60 m above an origin the
ground falls to 160 m below, so the true height above ground reaches 220 m.
GPS navigates, so flow is not fused into velocity and both builds fly the
same trajectory; only the scale height differs. Across the traverse the
logged flow innovation consistency ratio saturates its 255 ceiling - at
least 2.55, so flow at that geometry is rejected outright - against a peak
of 0 with this change. The raw innovation is deliberately not quoted: XKF5
logs it as an int16 scaled by 1000, and the old expression drives it past
the wrap point, so the logged figure there is an aliased value rather than
the real one.
Use the QURT-only Clang diagnostic push/pop approach from PR #28897 around the landing retry altitude comparison. Keep the existing subtraction and fabsf conversion unchanged while suppressing -Wabsolute-value at this call site.
The GPS message is a run of fixed-width ASCII fields, each exactly as
wide as the value it holds, with the terminating nul landing on the
first byte of the field which follows it. Nothing bounded the
formatted values, so an out-of-range input would overflow its field and
shift everything after it, and gcc-16 rejects the latitude outright:
AP_ADSB_Sagetech.cpp:497: error: 'snprintf' output may be truncated
before the last format character [-Werror=format-truncation=]
Bound each component to the widest value its field can represent, and
share the formatting between the two Sagetech drivers rather than
duplicating it.
The seconds of the time of fix are now formatted as an integer rather
than as a float so that the width of the field is known; the
milliseconds are rounded and carried into the seconds, which gives
output identical to the previous "%06.3f" except on exact
half-millisecond ties. The MXS driver converted its epoch to seconds
through a double, which can round up to the following second at
present-day epoch values; it now uses integer division.
Built for sparknavi-blue, which master does not currently build.
Keep the historical blind 0x20 RTC_CONFIG write on ICM-45686 CLKIN boards;
only RMW bit5 on ICM-56686 so shipping Cube/SIYI/JPilot CLKIN paths stay unchanged.
Revert FIFO_TMST_FSYNC_EN to 0x01. ICM-56686 FIFO_CONFIG4 bit0 is TMST/FSYNC
and bit1 is compression (DS-000563 v1.1); the 45686 bit map does not apply.