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]

Reply via email to