JorgeGzm opened a new pull request, #20997:
URL: https://github.com/apache/nuttx/pull/20997
## Summary
The GD32W51x (Cortex-M33, board GD-xD-W515-EVAL) and the GD32VW55x
(RISC-V Nuclei N307, board GD32VW553K-START) are two GigaDevice Wi-Fi SoCs
with different cores but the same generation of peripherals: the USART,
SPI, DMA (multi-channel with sub-peripheral requests), RTC (with the
IRC32K), RCU and PMU blocks are the same IP, so most of the drivers of the
two ports have the same structure. This PR brings the same set of new
features to both ports, implemented the same way in each, and fixes bugs
found in both while doing it.
**New features, on both chips:**
| Feature | GD32W51x (GD-xD-W515-EVAL) | GD32VW55x (GD32VW553K-START) |
|---|---|---|
| Deep-sleep power management (`CONFIG_PM`, activity governor), new `pm`
configuration | yes | yes |
| UART reception through the DMA (`CONFIG_<port>_RXDMA`) | yes | yes |
| UART transmission through the DMA (`CONFIG_<port>_TXDMA`) | yes | yes |
| Calibration of the IRC32K that clocks the RTC | yes | yes |
**New features, GD32W51x only** (the GD32VW553K-START has no external QSPI
flash):
- QSPI reads through the DMA (`CONFIG_GD32W51X_QSPI_DMA`).
- QSPI memory-mapped mode (`gd32_qspi_enter/exit_memorymapped()`, as on the
STM32), with the board option `CONFIG_GD_XD_W515_EVAL_QSPI_MEMMAP`.
- Code and data run in place from the QSPI flash
(`CONFIG_GD_XD_W515_EVAL_QSPI_XIP`, `locate_code(".qspixip")`).
- The GD-Link USB supply (PC0) sampled by the ADC on the board.
**Fixes:**
- W51x: an SPI DMA no longer ends on a single data mode or FIFO exception,
which does not stop the transfer (the LCD frame buffer was cut).
- VW55x: an SPI DMA no longer ends at the half transfer interrupt (an
exchange ended while its second half was still on the wire: 9/50 good
exchanges in loopback before, 50/50 after).
- VW55x: the PLL is set up as the firmware library V1.6.0 does (the AHB
clock is lowered in steps before going back to the IRC16M).
- VW55x: the clock setup waits 1 ms for the 40 MHz crystal before starting
the PLL. The HXTAL stable flag never sets on this chip and the firmware
library does not wait; the PLL locked to the starting crystal runs about
12 % slow for about 0.5 ms, which matters on every deep-sleep wake-up.
- VW55x: along with the SPI fix, the case labels of the SPI mode switch
are indented as nxstyle expects (no functional change).
The series has 12 commits, one per feature and chip; the board changes
go with the arch change they enable.
### How the features work
**Power management.** On both chips the `PM_STANDBY` state of the IDLE
domain is the PMU deep-sleep mode (core and bus clocks stopped, SRAM and
registers kept, LDO in low power and low-driver mode), entered from a
custom `up_idle()` (`ARCH_IDLE_CUSTOM`). The RTC wake-up timer ends the
deep-sleep, received characters are reported as PM activity, and the
debugger connection is kept (`DBG_CTL0.DSLP_HOLD`). The system time is
corrected with the time spent asleep, measured on the RTC:
- W51x: `clock_resynchronize()` with `up_rtc_getdatetime_with_subseconds()`
(`ARCH_HAVE_RTC_SUBSECONDS`). The wake-up timer fires every
`CONFIG_GD32W51X_PM_WAKEUP_MS`. `WFI` runs with PRIMASK set and BASEPRI
cleared, since the critical section raises BASEPRI, which would mask the
wake-up interrupt.
- VW55x: the system timer (mtime, stopped in deep-sleep) is advanced by the
time asleep. The wake-up timer is set to the next mtime alarm, at most
`CONFIG_GD32VW55X_PM_WAKEUP_MS`. The two calendar readings are taken at
the start of a sub-second unit, from the calendar counters (BPSHAD), with
an asynchronous prescaler of 2 for units of about 60 us; otherwise the
fixed phase of the wake-up in a unit biased every sleep.
**UART DMA.** Reception uses a circular DMA buffer
(`CONFIG_<chip>_SERIAL_RXDMA_BUFFER_SIZE`), handed to the serial driver on
the idle line interrupt and on the half and full transfer interrupts.
Transmission sends each contiguous part of the transmit buffer with one
DMA transfer; the full transfer interrupt frees the space and starts the
next transfer. A UART may use the DMA for reception, transmission or both;
the console starts its DMA from `*_serialinit()`, since it is not set up
again when opened.
**IRC32K calibration.** The IRC32K is measured against the crystal-derived
core clock at boot, and the synchronous prescaler of the RTC is set from
it (the W515 runs at about 32.8 kHz, the VW553 at about 35.2 kHz, +10 %).
**QSPI execute in place (GD32W51x).** Code run from the QSPI window
(0x90000000) hangs the bus as soon as it also reads the window (its literal
pool, its data). Through the remap of the instruction cache (16 MiB at
0x10000000 to the window, master port of the external memories) code and
data both work, so the `.qspixip` section is linked at 0x10f00000. It is
stored after the image in the internal flash and programmed to the last
MiB of the QSPI flash at boot when it differs, so `nuttx.bin` is still
programmed as usual.
## Impact
- New Kconfig options, all off by default: `CONFIG_PM` support on both
chips (`GD32W51X_PM_*`, `GD32VW55X_PM_*`), `CONFIG_<port>_RXDMA` and
`CONFIG_<port>_TXDMA` on the UARTs of both chips,
`CONFIG_GD32W51X_QSPI_DMA`, `CONFIG_GD_XD_W515_EVAL_QSPI_MEMMAP`,
`CONFIG_GD_XD_W515_EVAL_QSPI_XIP`.
- New configurations: `gd-xd-w515-eval:pm` and `gd32vw553k-start:pm`.
- Default behaviour changes, on all configurations:
- both chips calibrate the IRC32K at boot (about 100 ms);
- the VW55x waits 1 ms for the crystal at boot;
- the VW55x RTC uses an asynchronous prescaler of 2 (the calendar still
runs at 1 Hz).
- Both chips now select `ARCH_IDLE_CUSTOM`; without `CONFIG_PM` their
`up_idle()` behaves as the common one.
- The W515 linker script now includes `nuttx/config.h` (preprocessed, as
the other boards) to add the `.qspixip` region when it is enabled.
- The radios of the VW55x are not supported in deep-sleep (documented).
- Documentation: the two board pages describe the `pm` configurations, the
QSPI DMA, memory-mapped and XIP options and the PC0 ADC channel.
- No change outside `arch/arm/src/gd32w51x`, `arch/risc-v/src/gd32vw55x`,
the two boards, `arch/arm/Kconfig`, `arch/risc-v/Kconfig` and their
documentation.
## Testing
Host: Ubuntu 24.04 (Linux x86_64), Arm GNU Toolchain 13.2.rel1 and xPack
RISC-V GCC 14.2.0. Boards: GD-xD-W515-EVAL (GD32W515PIQ6) and
GD32VW553K-START (GD32VW553KMQ7).
**Build:**
- every commit of the series builds `gd-xd-w515-eval:nsh` and
`gd32vw553k-start:nsh`;
- the head builds every configuration of the two boards without warnings:
- W515: `nsh`, `littlefs`, `periph`, `pm`, `ostest`;
- VW553: `nsh`, `ostest`, `periph`, `pwm`, `adc`, `littlefs`, `sdcard`,
`sht3x`, `wapi`, `sta_softap`, `ble`, `pm`;
- `tools/checkpatch.sh -c -u -m -g` passes on the series.
**Power management** (`pm` configurations, NSH left idle):
```
W515: nsh> cat /proc/pm/state0
normal 20s 17% idle 15s 13% standby 76s 67%
VW553: nsh> cat /proc/pm/state0
normal 18s 10% idle 9s 5% standby 134s 78%
```
- NSH answers the first key (0.2 s on the VW553).
- `sleep 3` takes 3.00 s (host measured, ±8 ms) while the VW553 sleeps
between ticks.
- System clock against the host:
- W515: right within 1 s after 1 minute of standby.
- VW553: -0.074 s after 125 s of standby; before the crystal wait it was
-0.93 s. The remaining error is the IRC32K, since the board has no
32.768 kHz crystal.
**UART DMA** (console, UART2 on both boards):
- W515: 8 KiB sent to the board in one burst at 115200 (`dd` from
`/dev/console` to tmpfs) and read back with `cat`, unchanged.
- Reception: about 260 DMA/UART interrupts for the 8 KiB, instead of
about 8200.
- Transmission (`cat` of the 8 KiB): 61 DMA interrupts and 2 UART
interrupts.
- VW553: 2 KiB sent and read back unchanged. Larger bursts from the host
make the virtual COM port of the on-board GD-Link drop off the USB bus,
with or without the DMA.
**IRC32K calibration:** W515 32.8 kHz, 180 s and a reboot within 1 s of
the host (+3.9 s before). VW553 35.2 kHz (+17 s in 3 minutes before).
**SPI DMA:**
- W515: the ST7735S LCD frame buffer (`fb` example, SPI0 with DMA) shows
the full image.
- VW553: MOSI-MISO loopback, 50 exchanges of 24 bytes with `spi exch`,
50/50 right (9/50 before).
**QSPI (W515):**
- DMA: `cmp` of a 256 KiB file on the LittleFS of the QSPI flash is equal;
read in 60 ms instead of 80 ms.
- Memory-mapped: `xd 0x90000000` shows the flash contents.
- XIP, self-test at boot:
```
QSPI XIP section programmed (176 bytes)
QSPI XIP: code at 0x10f00001, data at 0x10f0002c: crc 21821ab6 OK
NuttShell (NSH) NuttX-13.1.0
nsh> reboot
QSPI XIP: code at 0x10f00001, data at 0x10f0002c: crc 21821ab6 OK
```
**ADC (W515):** channel 4 (PC0, GD-Link VBUS through its divider) reads
2.6 V.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]