usb_drv_exit() masks the UDC interrupt in the interrupt controller at
every disconnect, but only usb_init_device(), once at boot, unmasked
it. After the first unplug the UDC raised no more interrupts: on the
next plug the charging icon showed - plug detection polls VBUS_STS -
but the host's reset and requests went unanswered, so the device never
enumerated and the USB screen never came up.
Unmask it in usb_drv_init(), which runs at every connect, so that it
pairs with the mask in usb_drv_exit(). The interrupt is now masked
while USB is off, at boot too; nothing needs it then.
Tested on a Samsung YP-CP3: it enumerates at every replug.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Iab7b7e93c140990c39b0e6dfae23ffcc829f6ab2
Every sector of a write waited for the previous sector's transfer to
the chip before it was copied into a controller slot, so the copy and
the transfer never ran together. The slot the copy goes to is not the
one in transfer: copy first and wait only before the BCH engine and
the transfer restart.
On the Samsung YP-CP3, same test: 3.26 MB/s, every read verified, also
after a power cycle.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I41f43658916891a2ded74bbe21b6970f7cc78068
On a two-plane part an FTL page spans the same page of two blocks, one
in each plane, and flash_program() programmed them one after the other:
two program busy times (tPROG) per page. The original firmware's
FlashProgEnhanced() programs both with one two-plane program - 80h, the
first page, 11h, a wait of tDBSY, 81h, the second page, 10h - so the
planes share one tPROG.
Do the same where the runs of a write cover the same page of both
planes, on parts that take 81h for the second page. The original
firmware sends 80h there on Toshiba and Micron parts, which address
the planes differently too; those still program a page at a time.
enum vendor_t moves to nand-target.h for the check.
Over USB mass storage on a Samsung YP-CP3 the NAND wrote at 2.22 MB/s,
against 4.35 MB/s in the original firmware; now 2.86 MB/s, every read
verified.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I2f40e2ec426cf787b4ce452cbd0d0eb4b702e168
flash_read() latched the page afresh for every sector. The controller
streams a page from its first sector, so each sector also cost a
transfer of every sector before it in the page: reading an 8-sector
page sector by sector took 8 array loads and 36 sector transfers
instead of 1 and 8. Over USB mass storage on a Samsung YP-CP3 the
NAND read at 1.87 MB/s, against 8.25 MB/s in the original firmware.
Read each run of sectors that lie consecutively in one raw page with a
single latch. On a two-plane part a run of FTL sectors stays in one
page until it moves on to the other plane.
On the YP-CP3, same test: 5.64 MB/s, every read verified.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I9b08e56f4429ae432ccd2d2e23b9b34c18e56e97
Firmware builds reprogram the SDRAM controller twice. system_init()
sets burst 8, T_RP = T_RCD = 1 and the refresh, with CAS 3 since
a6538abd16 - CAS 2 on HM60X/HM801. And set_sdram_timing(), on every CPU
frequency change, rewrites the mode: CAS 2 whenever the AHB runs at
100 MHz or below, which is every clock this code sets.
On a generic rk2705 the firmware hangs in system_init() on those writes;
with them skipped it boots. Doing the same writes from IRAM, so that
nothing touches the SDRAM while the controller reprograms the chip,
hangs the same way: it is the settings themselves. The board's SDRAM
is an Elpida EDS1216AATA-75 (16 MB), a 133 MHz part at CAS 3 whose
minimum clock period at CAS 2 is 10 ns - exactly the 100 MHz it runs
at here, with no margin, next to minimal T_RP/T_RCD.
On a Samsung YP-CP3 the firmware boots but corrupts memory at random
once the clock first changes: data aborts on valid addresses in
unrelated code, undefined instruction exceptions on valid instructions,
glitches in the boot logo, crashes on USB plug and unplug. A memory
test over 15 MB passes with the boot's setup (CAS 3, burst 1,
T_RP = T_RCD = 2) and with system_init()'s values alike - it never
changes the clock - and skipping only the system_init() writes is not
enough, as set_sdram_timing() still selects CAS 2. With both removed
the YP-CP3 runs, passes a USB mass storage stress test and survives
USB unplug.
The boot ROM's and the bootloaders' setup works on every rk27xx target
seen, and nothing before Rockbox changes it (the NAND bootloader's
stage 1 and rk27load's s1 only probe the organisation). The gain
claimed for the tweak was a slight improvement in memory throughput.
So remove it for every rk27xx target, the HM60X/HM801 CAS 2 included,
and have set_sdram_timing() adjust only the refresh to the bus clock.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Icd063367783b0ae6eb80bad67d908269c07e704f
Every SD write failed. The card took the write command and went to
receive-data state, but never saw the block: CMD12 still found it there,
and the controller reported a missing CRC status after each block, 20
retries over. Reads worked. Stress-tested over USB mass storage on a
generic rk2705, with a SDHC card, in the normal firmware and in the
bootloader alike.
sd_init_card() switched the card to high-speed mode with CMD6. This host
is an SD 1.01 controller with a card clock of at most 25 MHz, per the
rk27xx datasheet; high speed and CMD6 came with SD 1.10, and a card
switched to it evidently does not take the data this host drives. The
original firmware never switches: after selecting the card it sets the
block length and a 1-bit bus and stays at default speed. A slower card
clock did not help; dropping the switch alone did.
Leave the card at default speed. Tested on a generic rk2705:
ums_stress.py over a 32 MiB window of the card - fill, verify, edge
sizes, a mixed read/write soak - passes at 2.3 MB/s writing and reading,
about 75% of what a 1-bit bus at 25 MHz carries.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Icfafab0bb460c8c0fda3dea455df9a36622bf764
When all three components share 1x2 or 2x1 sampling there is no chroma
subsampling, but each interleaved MCU holds two blocks per component.
The core loader assumed one chroma block per MCU, so these files (the
folder.jpg in the original report) decoded to garbage and have been
rejected since chroma sampling is validated.
Lay out the MCU generically in fix_headers(): each component's H x V
blocks in turn, with a per-block position that places chroma blocks
with the same offsets as luma. The MCU size and decode buffer now come
from the luma sampling in colour builds too, and the chroma IDCT scale
from the luma:chroma sampling ratio, which is unchanged for 1x1
chroma. The unused subsample_x/y fields are removed.
All other layouts decode byte-identically to before at every scale.
The new layouts decode byte-identically to the same image encoded as
4:4:4. Code size drops by 108 bytes on the e200 and struct jpeg by
20 bytes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I63a894d6609e56f3553a902afd6278ce70e04637
Both JPEG decoders accepted several baseline layouts they cannot decode
and produced garbage without an error:
- chroma with sampling factors other than 1x1 (the MCU layout is chosen
from luma alone, so any other chroma layout desynchronises)
- files written as more than one scan, where the first scan does not
hold every component (it was decoded as if it were interleaved)
- scans whose components are not in frame order
- a height of 0 in SOF, to be defined later by a DNL marker
Reject these in process_markers(). The imageviewer then falls back to
the jpegp decoder on colour targets, which handles all of them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Ia3373f2b934eef6e3f354b4d064faf2d89868050
Both JPEG decoders ignored the Tq selector in the frame header and
always dequantized luma with table 0 and chroma with table 1. Files
with a single shared table multiplied chroma by an empty table, and
files with separate Cb and Cr tables used the wrong one for Cr.
imageviewer/jpeg: build one dequantization table per component (3
instead of 2, +256 bytes) from the table it selects. tab_membership is
no longer used and is removed.
Core loader: the raw tables are pre-scaled in place for the IDCT, and
luma and chroma can use different IDCT scales. fix_quant_tables() now
maps each component to a table slot, copying a table that luma and
chroma share at different scales to a slot no component uses (there are
4 slots and at most 3 components, so one is always free), and rewrites
quanttable_select to that slot. No extra memory.
Selectors above 3 are rejected.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: If04c61fb0fef95da11d98d9918ea7225d8a440b0
Both JPEG decoders ignored the DC/AC table selectors in the SOS header
and always decoded luma with tables 0 and chroma with tables 1, the
layout libjpeg writes by default. Files where all components share
table 0, or where the slots are assigned differently, decoded to noise.
Look up each component's tables from its selectors instead. Baseline
JPEG only allows tables 0 and 1, which both decoders already hold, so
this needs no extra memory; selectors above 1 are rejected. In the core
loader tab_membership is no longer used and is removed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Ie1ec407ddecf1256fef410b1256b97af412fb194
The bit reader refilled from the input buffer without checking its end.
The end-of-data check in the decode loops only runs once per MCU row, so
a stream that desynchronises (or is truncated) read past the end of the
file buffer for the rest of the row. Return zero bytes past the end
instead; the pointer still advances so the per-row check stops the
decode.
Found with AddressSanitizer on a JPEG whose chroma is sampled more
densely than its luma.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Iaada1bc3cbf62b18f10fb2377c12d4d5cb9524de
config.h defines HAVE_STORAGE_FLUSH for the rk27xx Scheme A FTL when
CONFIG_STORAGE has STORAGE_NAND and CONFIG_NAND is NAND_RK27XX. sim.h
undefines CONFIG_NAND but keeps CONFIG_STORAGE, so a simulator for a
NAND target - the iPod nano 2G - evaluated the undefined macro:
"CONFIG_NAND" is not defined, evaluates to 0 [-Wundef]
Test that it is defined first.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Id1e328f08c14d7c5528d29f110fdbb8be68ab2f5
The debug menu tests CONFIG_NAND == NAND_RK27XX to include the FTL
scheme finder. Most targets do not define CONFIG_NAND at all, so every
native build but rk27xx's warned twice:
"CONFIG_NAND" is not defined, evaluates to 0 [-Wundef]
Test that it is defined first.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I82a1e8fa2f09aac1c5f0d746fb6d475e389d12d6
CONFIG_RK27XX_FTL selects the FTL a target's NAND uses,
RK27XX_FTL_SCHEME_A or RK27XX_FTL_SCHEME_B. rk27generic and the YP-CP3
are Scheme A, the HM-60x Scheme B. ftl-rk27xx.c mounts the one named;
for Scheme B it maps the drives onto the volumes ID block 1 records:
the system disk from LBA 0, the user volume after the system data
area.
The other rk27xx targets with NAND - HM-801, MA8, MA8C, MA9, MA9C and
iHiFi 760, 770, 770C, 800, 960 - have no confirmed scheme. They drop
the NAND from storage and build only the FTL scheme finder, so users
can report what their device holds and the scheme can then be set.
Only Scheme A flushes at shutdown: Scheme B holds nothing in RAM.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I484217b82c6de7316b90b354c012bfbaa263b3dd
Many rk27xx targets have NAND whose format nobody has examined. The
finder reads ID block 1 and the first page of the first 512 blocks and
says which FTL formatted them: Scheme A by its remap-log blocks,
Scheme B by its bad-block table and data headers, another Scheme B
generation by other 0xFxxx tags. The later ID block layout ('RK27' at
0x0a) records the FTL area's BCH strength at 0x1ed - 8 on the HM-601,
14 on the Archos Vision 28 - and the scan reads in that mode.
It is read-only, shown in the debug menu as "View FTL scheme", and
built for targets whose NAND is not storage - none yet.
Run on dumps of an HM-601 it reports Scheme B, a Samsung YP-CP3
Scheme A, and an Archos Vision 28 the other Scheme B generation.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I0528f9d2a6996089b6488a77b43942f6fd1f2c16
Scheme B is the self-describing NAND format of the HiFiMAN HM-601 and
similar players: every block carries its logical number and a version
in its metadata, so the mapping is rebuilt by a scan at mount, and
small writes go through a 16-page RAM cache journalled to flash.
ftl-scheme-b.c is a reimplementation from reverse engineering. The
format and the behaviour were worked out by analysing the machine code
of the HM-601's NAND bootloader and of a compiled Rockchip FTL object
from the rk2808 platform, which handles the same format, and checked
against dumps of the media; no source code was used. Where the two
binaries differ the HM-601 is followed: 16-bit versions compared
across wrap, plain 0xF200/0xF100 tags, a copy that stamps one header
on every page. The number of open exchange blocks is configurable - 8
on the HM-601, whose mount recovers no more.
Checked by running the compiled object under qemu over a NAND
simulator, side by side with this code, on a 4 GiB HM-601 dump: the
same state after mount, identical reads of all 3958 logical blocks,
and flash programs and erases identical one for one - over 600 random
writes on each of three seeds and at every power-cut point of three
sweeps, 1435 points - with 0 wrong sectors.
Not built yet: no target selects it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Icb935ea78d716c1e51f1453fc3ab3f47f3467027
The controller has a second ECC mode, BCHCTL bit 13: t=14 instead of
t=8, over the same field and polynomial. Some firmware writes its FTL
area in it - the Archos Vision 28 does - while every boot area seen is
t=8.
flash_set_ecc() selects the mode for reads and copies of the FTL area;
flash_read_raw(), which reads the boot area, stays at t=8. Writing is
refused in t=14 mode: a t=14 sector is a 538-byte record on the media
(3 metadata and 23 parity bytes), the program path addresses 528-byte
records, and programming in that mode has not been tried.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Iaf4ce9274b72838b7719232fc49cdce0cceecbac
The flash layer writes 0x00 into metadata byte 1 of every page it
programs, which is how Scheme A tells a programmed page from an erased
one. Scheme B keeps a 16-bit field in bytes 0-1 of every sector - its
block tags, versions and block numbers - so it needs the byte as
written.
Add flash_set_meta_passthrough() to turn the forcing off, and
flash_copy_meta(), a copy that either keeps each sector's own metadata
or programs a page of it given by the caller: Scheme B's copy stamps
one header on every page it moves.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I49b2c24d812284af2c50d776f0942b5b1b989c98
The NAND holds two volumes, SYS and USER; the split is recorded in the
boot area, so they are separate drives rather than partitions of one.
SYS is hidden: nothing in it is the user's, and deleting or overfilling
it stops the device booting. HAVE_RK27XX_NAND_SYS, documented in the
config and off, brings it back as a drive of its own.
storage.c numbers drives by driver, SD first:
default HAVE_RK27XX_NAND_SYS
drive 0 SD SD
drive 1 NAND USER NAND SYS
drive 2 NAND USER
NUM_DRIVES was 1, which was already wrong for a target whose
CONFIG_STORAGE names both SD and NAND.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Ic68921838faef0ff6fd296d43e86ec3a10a091c5
ftl-rk27xx.c has been four empty stubs since 2010. Fill them in with
the flash translation layer the rk2705/rk2706 original firmware uses,
called Scheme A here to tell it from the log-structured layout of later
firmware. It reads and writes that format exactly as the original
firmware does, so a device keeps working with its original firmware
after Rockbox has written to it.
- ftl-scheme-a.{c,h}: the FTL. The file opens with a description of
the on-flash format and how the FTL works: the SYS and USER volumes,
super-blocks and zones, the zone table, the remap log and its mirror,
the exchange record and the write protocol, power-loss recovery, bad
blocks. Oddities of the original firmware kept for compatibility are
marked where they are.
- Parameters that differ between firmware builds - the zone reserve
base, the system zone offset, the format flag - are recovered from
the media at mount and checked against its structure; a mount that
cannot confirm them is read-only. A mount that would have to repair
the remap log while not allowed to write fails rather than serve
wrong data.
- ftl-rk27xx.c: the storage glue. It finds the boot area's ID block,
which records where SYS ends, and mounts the FTL.
- ata-nand-rk27xx.c: a drive per volume. SYS holds the original
firmware - on a Rockbox device including the BASE.RKW that chainloads
the bootloader - and nothing of the user's, so it is a drive only when
the target defines HAVE_RK27XX_NAND_SYS. Capacity comes from the FTL's
tables, not from raw block geometry.
- config.h: HAVE_STORAGE_FLUSH for the rk27xx NAND. The FTL holds up to
three part-written pages in RAM; storage_flush() commits them at
shutdown and ROLO.
Writing is opt-in: without FTL_ALLOW_WRITE the FTL mounts read-only and
never writes the flash, not even a repair the mount could make.
Two bugs of the original firmware are not reproduced. A write starting
before a page held part-written in RAM and running through it left two
buffers holding that page, and the older one was later programmed over
the newer data; such a write now flushes the held page first. And its
bad-block marker took two of its three metadata bytes from the stack,
which can make a retired block look like a remap-log block; the marker
is now written in full.
Tested in a host simulator on NAND images of a Samsung YP-CP3 and a
generic rk2705, against the original firmware's FTL object run under
qemu-arm: identical traces of every read, program and erase, with a
hash of the data each program writes, over mounting and reading, random
writes with every sector verified, a power cut at every flash operation
of a write, and a program or erase failure at every one.
On a generic rk2705: the read-only mount reports the layout and
capacities the original firmware does and every file's MD5 matches; a
write test passes 8192/8192 across a remount and a power cycle.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I573d944389cefb456ecf38c6c7b91bebfe0fe377
system_init() gates the clocks of modules a firmware build does not use,
and the list included the NAND controller's HCLK. Once the NAND is
storage, the first access to the controller - flash_init() writing
FMWAIT at 0x180e8004 - takes a data abort on the unclocked peripheral.
No rk27xx target stored to NAND before, which is why this never showed.
The LCDC clock in the same list stays gated: the firmware draws with it
gated, the MCU interface running from the LCDC HCLK, which is not.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I52a4dc9e63fe5b89c85b60dc3ef77d74528dc06f
flash-rk27xx.c drives the NAND controller and its BCH engine for the
flash translation layer that follows. It knows the chip's geometry and
how to read, program, erase and copy sectors, but not what the sectors
mean.
- Addresses are 512-byte sectors in a linear view of the chip where a
block is a super-block: on a two-plane part, one physical block from
each plane, consecutive pages alternating between them. The layer
maps that view to the chip; the FTL never sees planes.
- Every sector carries 16 spare bytes: 13 of BCH code, generated and
checked by the hardware, and 3 for the FTL. Byte 1 is written 0x00 on
every program - the "page programmed" marker the original firmware's
FTL keys its mount and recovery on.
- The program sequence was read out of the original firmware's own
machine code. The write kick is the read kick plus FL_WR, and the BCH
engine needs BCH_WR to encode rather than decode.
- A copy is read through the ECC engine and programmed, never the
chip's internal data move, which on this MLC part would carry bit
errors forward.
- Writes are refused until the FTL enables them, and writes into the
boot area are dropped and reported successful, as the original
firmware does. The write-protect line is lifted only for the duration
of each program or erase.
- Failures and timeouts are counted: the FTL can act on few of them.
Only the first chip is handled; every device the FTL has been checked
on has one.
Tested on a generic rk2705 directly, on a free block: a program across
both planes, a single-sector program with metadata, a whole page, a
copy and an erase each read back byte-exact through the controller's
ECC decode, which also shows the code it generated is valid.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: If6ffa9f9811172f4f8829c1e68d6de9466a022c8
flash_init() identifies a chip by looking its READ ID device code up in
device_code[] and taking the capacity from device_info[] at the same
index. device_code[] had seven entries and device_info[] eight: 0xd5
(16 Gbit) was dropped when the table was transcribed from the OF. Every
code after the gap picked up the capacity one row up, so a 0xd7
(32 Gbit, 4 GiB) part was sized at 2 GiB.
On a generic rk2705 that halved total_phy_sec to 4194304, and the FTL
looked for its tables in the wrong place and read erased flash. With the
entry restored it reports 8388608, matching the chip and the host-side
dump of the same unit.
The OF's own table, as it appears in its NAND bootloader:
76 79 f1 da dc d3 d5 d7 00 00 02 00 00 00 04 00 ...
A compile-time check now fails the build if the two tables differ in
length again. Also fixes two register addresses in the same loop that
were missing a digit (0x180E204/0x180E208 for 0x180E8204/0x180E8208);
they are stored for reference only and nothing reads them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Ia70c249eea2e44ea34aef52d8ae20860b2b5db9d
nand-rk27xx.c held a complete transcription of the OF's NAND handling -
chip detection, geometry derivation, chip select, ECC reads - inside
"#if 0", written as documentation back when the FTL was still unknown.
It has therefore never been compiled.
Enabling it exposed three things nothing had ever caught:
- flash_init() looks up ManufactureIDTbl[] and DeviceCode[], but the
tables are named manufacture_id_tbl[] and device_code[]
- mlc_refresh_row, flash_pend_cmd and flash_read_status_cmd are
assigned but were never defined
- memcpy() was used without including string.h
struct flashspec_t moves to nand-target.h, with flash_spec[] and
total_phy_sec declared there, because the FTL's flash primitives need
the geometry flash_init() derives. The "_raw" fields describe one
physical plane and the others the multi-plane view the FTL addresses;
that distinction is load-bearing for the FTL's address mapping, so both
are kept.
flash_read_page() is renamed flash_read_page_raw(). It reads a whole
page unbuffered and without ECC, and the name is needed for the FTL
primitive that does the ECC read.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Change-Id: I3eb2d6f41d72b3239a0f9493e49532c242c588fa
BCHCTL bit 13 and the whole of BCHST were marked unknown. Both are
needed by any driver that reads NAND through the controller's ECC
engine: a read has to be able to report an uncorrectable sector, and MLC
parts want a refresh once a sector needs enough correction.
BCHCTL bit 13 ECC strength, clear = t=8, set = t=14 (both m=13,
poly 0x25af). Established by decoding both modes
against real media until the stored ECC bytes
reproduced.
BCHST bit 0 result valid
bit 2 error - uncorrectable when set together with bit 0
bits 6:3 number of corrected bit errors
Taken from the rk2705 NAND bootloader's ECC read loop:
tst r0,#1 ; tst r0,#4 both set -> sector uncorrectable
lsl r0,#25 ; lsr r0,#28 -> (BCHST >> 3) & 0xf, corrected bits
cmp r0,#3 >= 3 triggers a block refresh
The threshold agrees with MlcRefreshHook in the Samsung OF's flash.o, so
two independent firmwares say the same thing.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Change-Id: I1e356d5510827b46035f1d7d4a2cc69f4e83f43f
At a CELT to hybrid mode switch, opus_decode_frame() runs CELT's pitch
PLC nested in the new frame, and celt_decode_lost() held a copy of up to
2 KB of excitation for celt_fir(). On stackOverflow.opus that overran
the 9 KB codec stack on native targets such as the e200v2. Filtering in
place from the last sample down needs no copy; output is bit-identical.
Worst case over all 242 mode switches of stackOverflow.opus, measured
under qemu: 9140 -> 7676 bytes below opus_decode(), against 8912 left
for it on the e200v2.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Iaa9f57182ad86ab76c81c55bea72aa517cc18230
commit_discard_idcache() invalidated both cache ways while running from
cached SDRAM. When the loop polling for the invalidate to finish starts on
a cache line of its own, it is fetched through the ways being invalidated
and the CPU takes a data abort, reported at the loop's branch. Whether it
crashed thus depended on where the linker put the function.
usb_storage calls it on every USB connect. On rk27generic a jpeg change
that grew clip_jpeg_fd by 8 bytes moved the loop onto a new line, and the
firmware crashed as the USB screen came up, with an empty backtrace.
Turn the cache controller off around the invalidate, as crt0.S does at
start-up. The cache is write-through, so no data is lost.
Tested on a generic rk2705 with the function padded so the poll loop starts
a new cache line: without this change it crashes at the first USB connect,
with it the device enumerates as a mass storage device. The normally
linked build works too.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I319b811fdef30717999b60132000e70f410001fc
The rk27xx UDC driver was fixed and stress-tested on a generic rk2705
against the USB core of early 2026 - including a port to the control
request API of that time. Meanwhile the core took over the EP0 state
machine (usb_core_setup_received()) and endpoint allocation, and the
driver was converted to both without the fixes. This carries them over.
Transfers and resets (a mass-storage stress test fell off the bus after
10,000 - 27,000 operations without these):
- Transfers are set up with interrupts disabled: the interrupt handler
advances buf/cnt of the same endpoint for the next packet.
- ep_write()'s wait for TXFULL to clear is bounded by an iteration count.
It also runs in the interrupt handler, where current_tick never
advances, so a tick timeout spun forever.
- A bus reset cancels transfers - usb_drv_cancel_all_transfers() was
empty - instead of re-initialising the completion semaphores, which
loses a thread blocked on one for good; blocked senders are woken with
an error and the enabled endpoints NAKed and flushed. The reset handler
also calls usb_core_bus_reset(), which it never did.
- Blocking sends time out after a second and report the error.
- An ACK with no transfer armed (one cancelled by a reset) is ignored.
Configuration:
- The configuration number is DEV_INFO [11:8]; it was read as bits 10:7,
bit 7 being DEV_EN, so configuration 1 was reported as 2.
- The UDC completes SET_ADDRESS and SET_CONFIGURATION itself, raising no
interrupt, so udc_helper() - which reports them from DEV_INFO - also
runs from a tick task while the device is unconfigured. After a bus
reset of a configured device the host re-sends SET_CONFIGURATION and
goes straight to a bulk command that NAKs without interrupting: without
the tick, the device never came back.
EP0, with the core now running the control state machine:
- Right after connect the UDC reports one SETUP with both registers zero;
no host sends that, and it is ignored.
- A SETUP clears a stall, and ends - reported to the core as failed -
any EP0 transfer still in flight, which belongs to a request the host
abandoned; otherwise the core would wait for it forever. EP0 stall uses
the EP0 registers, not endpoints[0], a stub without registers.
- Control reads are clipped to wLength and end with a zero length packet
when a short answer fills whole packets.
- The core arms status stages with no buffer; they land in a dummy one.
- A status OUT arriving while the data IN is still going - the host took
less than was offered - ends the data stage too.
- At a bus reset EP0 transfers are dropped silently: the core resets its
own EP0 state.
Tested on a generic rk2705. The transfer, reset and configuration fixes
first against the USB core of early 2026: RAM-disk, NAND and SD stress
tests over USB mass storage, and usbreset recovery. Then the driver as it
is here, on the current core: enumeration, and a mass-storage stress test
of three LUNs at once (RAM disk, NAND, SD) that also passes after an eject
and a cold power cycle.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I1b2d03ca8f688f2a0e7b28ead64b7ab050a0a9e8
The UDC was only ever connected from the interrupt handler, on CONN_INTR.
That needs a cable-insert edge after the stack is up, and there is none
when the cable is already in - booting with it plugged, or taking the
controller over from the ROM loader or hwstub, which leave it enumerated
as a different device. The device then never enumerated.
Connecting from usb_drv_init() would not do either: usb_core_init() calls
it first, before the class drivers are set up and before the core sets its
own state, so a fast host enumerated against state that was then
overwritten and the descriptor read timed out - depending on timing.
Add usb_drv_connect(), which drops off the bus, resets the PHY and
reconnects, and call it from usb_enable() after usb_core_init() returns.
Tested on a generic rk2705, loaded over hwstub with the cable in: the
device drops off, comes back and enumerates as Rockbox.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I372bd6a49594c00909ada0cc43b046178140e755
sd_read_sectors() and sd_write_sectors() take sd_mtx and power the
controller, then check the requested range and return -1 on failure -
leaving the mutex held and the controller on. Check the range first.
With no card present numblocks is 0, so every request takes that path.
Rockbox mutexes are recursive for the owning thread, so the first thread
to touch the SD drive keeps working, and every other thread that does
blocks forever.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I16c2be3bde5c62946fdedaabe115b6c4bc330467
The folded Rice value was unfolded with a signed shift, which is wrong
once it reaches 2^31, and the unary length limit was (INT_MAX >> k) + 2,
about half of what a 32-bit residual can need. Streams with very large
residuals (FLAC decoder testbench file 63) were misparsed, overran the
frame and lost sync at the next one. Unfold as unsigned and derive the
limit from UINT_MAX, clamped to INT_MAX. The fast path is unchanged.
The existing 0x80000000 error check now also works as intended, since
the Golomb reader's error value maps to it. The FLAC spec forbids a
residual of -2^31.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Change-Id: I0bdce9db69e1b30565ecc23126923ba401b7deca
On ARMv5E and later the fixed-phase FIR cycles at 8, 12 and 16 kHz load
two samples a word and take two coefficients a word from a literal
pool; smla<x><y> picks the halves, so an odd-aligned window costs
nothing. Outputs are paired as two interleaved accumulator chains. The
FIR buffer is now word aligned. Generated by
silk/arm/gen_resampler_armv5e.py. Bit-exact; OPUS_ARM_NO_SILK_ASM
disables it, and config.h sets that on M-profile cores.
Measured on the Clip+, silk_5.opus (WB SILK):
20.93 -> 15.84 MHz, -24.3%.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Ibec71fd52542f768f22e2970c9f8c45118c708b9
On ARMv4 the fixed-phase FIR cycles at 8, 12 and 16 kHz run as adds of
shifted samples rather than multiplies: every coefficient is a constant,
and a shifted add is one cycle where mla plus loading the coefficient is
five or six. Each sample is loaded once per cycle and added into the
two or three outputs it feeds, sharing partial products such as 31x
between them, about 27 adds per output. The kernels are generated by
silk/arm/gen_resampler_armv4.py. Bit-exact; OPUS_ARM_NO_SILK_ASM
disables them.
Measured on the e200v1, silk_5.opus (WB SILK), with the previous commit:
36.31 -> 28.85 MHz, -20.5%.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Ic1fd5777e91d182248f43954e4b6ae977309dc5d
The FM screen had no actions for the rk27xx generic keypad; give it those
its keymap already maps (menu, play, stop, exit) in radio.c.
The board's tuner is an RDA5807P. It keeps being driven as a TEA5767, in
the chip's compatible mode, as the original firmware does: tuning, seek
and the stereo indicator work so, and the RDA mode would bring nothing
here - this variant has no RDS. Say so next to CONFIG_TUNER.
The tuner's audio is on the codec's line input 1: only that line is
powered and mixed in while the radio plays (RK27XX_CODEC_FM_LINE 1). With
line 2 instead the radio is silent.
Tested on the rk27generic board: manual tuning, seek, stereo indicator and
audio.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I2135ee484705ff0fce6d88e73288d8ed2aec6c2d
audiohw_set_monitor() switched the output mixer from the DAC to both line
bypasses: voice and beeps went silent while the radio played, and a line
nobody listened to was mixed in, with its noise. Both line inputs were
also powered from start-up on.
- the target names the line its tuner is on, RK27XX_CODEC_FM_LINE (1 or
2); both are used where it does not say
- monitoring adds that line's bypass to the DAC instead of replacing it
- the line inputs stay in standby until monitored, and go back after
Only rk27generic uses the internal codec - the other rk27xx targets
have external DACs or codecs.
Tested on rk27generic: the radio plays through the monitored line, key
clicks stay audible over it, and playback is unaffected.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I177fdf605e4d997159898c868b2186c9584eb19a
The 8, 12 and 16 kHz to 48 kHz steps visit only two or three FIR phases
in a fixed cycle, so each set of input samples is read once and reused
across outputs. Bit-exact; OPUS_NO_SILK_FIXED_PHASE disables it.
Measured with silk_5.opus (WB SILK):
e200v1: 36.31 -> 33.38 MHz, -8.1%
Clip+: 21.66 -> 20.93 MHz, -3.4%
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Icb0f8ded62739dfee1f574e4888a54c778aa3d53
Bootloaders with this change are now able to boot rockbox binaries over
1MB. (1.5MB buffer led to bootloader hanging)
Change-Id: I540bd4146aaa7236df93e74f6f2c69aa32e4a874
The contents of appextra are added to the INCLUDES list, eg:
appextra="recorder:hosted"
will result in this at compile time:
INCLUDES += -I$(APPDIR)/recorder -I$(APPDIR)/hosted
With that in mind,
* 'gui' and 'recorder' have been set for all targets other than
the original charcell Archos. Globally set these instead of
using them everywhere.
* 'hosted' was effectively a no-op and removed entirely.
* 'radio' was specified on a lot of targets that didn't have a radio,
just make it global as well.
The net result is that only the android targets now define 'appextra' in
their configure entry. A future patch will remove the need to specify
the ones that are now global.
Change-Id: I751284cde4785077c54405a8a10be819021e4255
It's not part of the build farm, doesn't have a manual, and isn't
even listed on the www site or wiki yet.
Change-Id: I5fc79d0316717898f16ff794cba114a46472ae8f
- config: HAVE_RECORDING, sources microphone and FM, 8-48 kHz
- wm8751.c: the YP-CP3's own audiohw_set_recsrc(). The rk27xx cannot
send received samples straight back out, so what is heard of an input
goes through the codec's analog bypass - the input PGA into the output
mixers: the radio always, the microphone never. As in the original
firmware, the radio passes the PGA at +12 dB when only listened to,
and the microphone - mono, on RINPUT2 - gets +13 dB boost and is
recorded by the right ADC onto both channels (the original firmware's
noise gate is left out). The HD300's version assumes the microphone on
INPUT3 and headphones on OUT1, and switches OUT2 - the YP-CP3's
headphones - off.
- wm8751.c: the playback-only FM monitor added for the YP-CP3 goes; the
radio is routed by audiohw_set_recsrc() now, as on the HD300
- wm8751.h: DATSEL, which ADC feeds each channel of the output data
Only partly tested on hardware: FM radio still plays, and the recording
screen's peak meter follows the microphone. Not yet tested: a recorded
file played back, recording FM, recording gain range.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I3c25f4333f765d98dddc2fd722c111f8493bbe77