Record that serial receive is not implemented

Found while explaining a DMA channel that stayed permanently armed with cndtr=256
during the flash investigation. It is USART1's receive channel, running in
LL_DMA_MODE_CIRCULAR, so never completing is correct behaviour and not a bug.

But it exposed a real gap. driver/uart.c derives its write pointer from
sizeof(UART_DMA_Buffer) - LL_DMA_GetDataLength(...), and the DMA model only
services SPI, so CNDTR never decrements for USART and that expression is always
zero. Combined with USART1 being a py32-stub with no chardev backend, nothing can
be sent *to* the firmware.

The cost is specific: UART_IsCommandAvailable never fires, so the UV-K5 programming
protocol in app/uart.c is unreachable -- 0x0514 handshake, 0x051B EEPROM read,
0x051D EEPROM write, 0x05DD reset. CPS/CHIRP-style tools cannot talk to this
emulator. Transmit is unaffected, which is why the firmware banner shows up fine
and this went unnoticed.

Documented rather than fixed: it needs a chardev on USART1 plus circular-mode DMA
driven by receive, which is a new feature rather than a repair. The notes say what
would be involved so the next person does not have to rediscover the mechanism.

Status table also updated to reflect what the flash and DMA fixes settled --
persistence and frequency entry now work.
This commit is contained in:
mckero committed 2026-08-28 15:52:05 +01:00
1 parent 65e50c0065
commit cdb73f13a0
2 files changed
+25 -1

No files matched your search

+21
View File
@@ -452,6 +452,27 @@ from a passing emulator test.
Timing is also deliberately wrong — see the SysTick section in README.md. Fine Timing is also deliberately wrong — see the SysTick section in README.md. Fine
for menus and control flow; useless for signal timing. for menus and control flow; useless for signal timing.
**Serial receive does not work.** Transmit does — the firmware banner and its
`printf` output reach stderr and the web UI log — but nothing can be sent *to* the
firmware. Two things are missing, and both would need building:
- USART1 is a `py32-stub` with no chardev backend, so there is no source of
incoming bytes.
- `driver/uart.c` receives over DMA channel 2 in `LL_DMA_MODE_CIRCULAR` and finds
the write pointer with `sizeof(UART_DMA_Buffer) - LL_DMA_GetDataLength(...)`. The
DMA model only services SPI and never decrements `CNDTR` for USART, so that
expression is always 0 and the firmware sees an empty buffer. A channel sitting
permanently armed with `cndtr=256` and `cpar=0x40013804` is this, not a bug.
What that costs: `UART_IsCommandAvailable` never fires, so the whole UV-K5
programming protocol in `app/uart.c` is unreachable — `0x0514` handshake, `0x051B`
EEPROM read, `0x051D` EEPROM write, `0x05DD` reset. CPS/CHIRP-style tools cannot
talk to this emulator. Keypad, screen and the web UI are unaffected.
Doing it properly means giving USART1 a real chardev, implementing circular-mode
DMA with a decrementing `CNDTR`, and driving it from receive rather than from
`TXDMAEN` as the SPI path does.
## If you add a peripheral ## If you add a peripheral
1. Read the register layout from the CMSIS header 1. Read the register layout from the CMSIS header
+4 -1
View File
@@ -36,8 +36,11 @@ has no public datasheet, so its driver is the only specification available.
| --- | --- | | --- | --- |
| Boot to main loop | works, ~5 s | | Boot to main loop | works, ~5 s |
| LCD contents | readable via `tools/screenshot.py` | | LCD contents | readable via `tools/screenshot.py` |
| SPI flash, settings, calibration | works | | SPI flash, settings, calibration | works, and persists across power cycles |
| Frequency entry | works, stored per band and kept |
| Keypad and menu navigation | works, including waking from power save | | Keypad and menu navigation | works, including waking from power save |
| Serial output (firmware log) | works, appears in the web UI log |
| Serial input / CPS programming | **not implemented**, see [AGENTS.md](AGENTS.md#what-this-cannot-do) |
| Timing accuracy | deliberately wrong, see [Timing](#timing) | | Timing accuracy | deliberately wrong, see [Timing](#timing) |
| Radio/RF behaviour | not modelled | | Radio/RF behaviour | not modelled |