This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 4416660ce229a8074d3eb121576b1698fcbe981e
Author: dechao_gong <[email protected]>
AuthorDate: Tue Sep 15 13:01:04 2026 +0800

    arch/arm/ameba: enable SMP on AmebaSmart CA32 (RTL8730E)
    
    RTL8730E has dual Cortex-A32 cores (CA32) in the AP domain.  Core1 is
    powered off by default and requires an explicit HSYS power-on sequence
    before ATF SP_MIN can service the PSCI CPU_ON call.  Without it, SP_MIN
    writes the entry point to the mailbox and times out waiting for Core1 to
    poll it.
    
    Add rtl8730e_core1_power_on() that mirrors SDK smp.c:rtk_core1_power_on():
    assert reset, assert isolation, two-stage power-on with up_udelay() for
    correct 50/50/500/50 us timing, then release isolation and reset.  Call it
    from up_cpu_start() before psci_cpu_on().
    
    Enable CONFIG_SMP / CONFIG_SMP_NCPUS=2 / CONFIG_ARM_PSCI in the nsh
    defconfig.
    
    Enabling SMP also exposed a latent WHC skb alignment bug: the Realtek
    WHC WiFi driver keeps the AP/NP DDR views coherent with by-VA
    DCache_Clean/Invalidate at SKB_CACHE_SZ (64 on RTL8730E) granularity,
    which requires every skb buffer to be cache-line aligned.  The port had
    omitted CONFIG_MM_DEFAULT_ALIGNMENT (defaulting to 8; the 8721Dx parts
    set 32), so heap-allocated skb buffers were unaligned and the cache
    maintenance spilled onto the neighbouring skb struct, corrupting its
    immutable buf pointer (seen as skb->buf = 0x05 and a TX memcpy data
    abort on "renew wlan0").  This was harmless on single core -- the
    non-shareable DDR mapping made the stray maintenance a no-op -- but the
    SMP shareable mapping plus real dual-core concurrency turned it into a
    hard fault.  Set CONFIG_MM_DEFAULT_ALIGNMENT=64 in the nsh defconfig.
    
    Hardware verified on RTL8730E (C-cut): /proc/cpuinfo shows both processor 0
    and processor 1; getprime 2 completes two concurrent threads in ~573 ms
    (same as single-thread), confirming true parallel execution across both 
cores.
    "renew wlan0" now obtains a DHCP lease (192.168.1.101) without faulting.
    
    Assisted-by: Claude Sonnet 4.6 <[email protected]>
    Signed-off-by: dechao_gong <[email protected]>
---
 arch/arm/src/common/ameba/ameba_os_wrap.c          | 13 +++-
 arch/arm/src/rtl8730e/rtl8730e_boot.c              | 72 ++++++++++++++++++++++
 boards/arm/rtl8730e/ca32-evb/configs/nsh/defconfig |  4 ++
 3 files changed, 86 insertions(+), 3 deletions(-)

diff --git a/arch/arm/src/common/ameba/ameba_os_wrap.c 
b/arch/arm/src/common/ameba/ameba_os_wrap.c
index ed40479a766..ed562e16740 100644
--- a/arch/arm/src/common/ameba/ameba_os_wrap.c
+++ b/arch/arm/src/common/ameba/ameba_os_wrap.c
@@ -170,9 +170,16 @@ bool os_heap_add(uint8_t *start_addr, size_t heap_size)
  * the NP DMAs them, so an unaligned base would clobber neighbouring data on
  * cache maintenance.  whc_ipc_host_init_skb() outright rejects an unaligned
  * skb_data_buf ("skb_data_buf malloc fail!"), leaving the skb pool empty and
- * the TX path handing the NP a garbage buffer pointer.  This is guaranteed
- * by CONFIG_MM_DEFAULT_ALIGNMENT=32 (>= SKB_CACHE_SZ) -- every NuttX heap
- * block is then cache-line aligned, so plain kmm_* suffices here.
+ * the TX path handing the NP a garbage buffer pointer.  Worse, when the pool
+ * squeaks past that check but is not aligned to the full cache line, the
+ * driver's by-VA DCache_Clean/Invalidate spills onto the neighbouring skb
+ * struct and corrupts its (immutable) buf pointer, so a later TX memcpy
+ * faults on a garbage skb->data (seen as skb->buf = 0x05).
+ *
+ * This is guaranteed by CONFIG_MM_DEFAULT_ALIGNMENT >= SKB_CACHE_SZ -- every
+ * NuttX heap block is then cache-line aligned, so plain kmm_* suffices here.
+ * SKB_CACHE_SZ is 32 on the other Ameba WHC parts but 64 on AmebaSmart
+ * (RTL8730E), so that board's defconfig sets CONFIG_MM_DEFAULT_ALIGNMENT=64.
  */
 
 void *rtos_mem_malloc(uint32_t size)
diff --git a/arch/arm/src/rtl8730e/rtl8730e_boot.c 
b/arch/arm/src/rtl8730e/rtl8730e_boot.c
index 00e66e9baaa..54ca01ca684 100644
--- a/arch/arm/src/rtl8730e/rtl8730e_boot.c
+++ b/arch/arm/src/rtl8730e/rtl8730e_boot.c
@@ -25,6 +25,7 @@
  ****************************************************************************/
 
 #include <nuttx/config.h>
+#include <nuttx/arch.h>
 
 #include "arm_internal.h"
 
@@ -132,6 +133,71 @@ void arm_boot(void)
 #endif
 }
 
+/* RTL8730E HSYS / CA32 register addresses for Core1 power sequencing.
+ * Core1 is powered off by default; ATF SP_MIN waits for Core1 to poll its
+ * mailbox but the core never wakes unless the HSYS power rails are enabled
+ * first.  These constants mirror the SDK smp.c / ameba_hsys.h definitions
+ * without requiring vendor headers.
+ */
+
+#define RTL8730E_HSYS_BASE      0x41000000u
+#define RTL8730E_HSYS_HP_PWC    0x000u
+#define RTL8730E_HSYS_HP_ISO    0x004u
+#define RTL8730E_CA32_RST_CTRL  0x41000204u
+
+#define HSYS_PSW_HP_AP_CORE(x)      (((x) & 0x3u) << 4)
+#define HSYS_PSW_HP_AP_CORE_2ND(x)  (((x) & 0x3u) << 6)
+#define HSYS_ISO_HP_AP_CORE(x)      (((x) & 0x3u) << 4)
+#define HSYS_GET_ISO_HP_AP_CORE(x)  (((x) >> 4) & 0x3u)
+#define CA32_NCOREPORESET(x)        (((x) & 0x3u) << 0)
+#define CA32_NCORERESET(x)          (((x) & 0x3u) << 4)
+
+static void rtl8730e_core1_power_on(void)
+{
+  volatile uint32_t *pwc = (volatile uint32_t *)(RTL8730E_HSYS_BASE +
+                                                 RTL8730E_HSYS_HP_PWC);
+  volatile uint32_t *iso = (volatile uint32_t *)(RTL8730E_HSYS_BASE +
+                                                 RTL8730E_HSYS_HP_ISO);
+  volatile uint32_t *rst = (volatile uint32_t *)RTL8730E_CA32_RST_CTRL;
+  uint32_t val;
+
+  /* Assert reset on core1 */
+
+  *rst &= ~(CA32_NCOREPORESET(0x2u) | CA32_NCORERESET(0x2u));
+
+  /* Assert isolation on core1 */
+
+  val  = *iso;
+  val |= HSYS_ISO_HP_AP_CORE(0x2u);
+  *iso = val;
+  up_udelay(50);
+
+  /* First-stage power-on (mask 0x3 keeps core0 rails stable) */
+
+  val  = *pwc;
+  val |= HSYS_PSW_HP_AP_CORE(0x3u);
+  *pwc = val;
+  up_udelay(50);
+
+  /* Second-stage power-on */
+
+  val  = *pwc;
+  val |= HSYS_PSW_HP_AP_CORE_2ND(0x3u);
+  *pwc = val;
+  up_udelay(500);
+
+  /* Release isolation */
+
+  val  = *iso;
+  val &= ~HSYS_ISO_HP_AP_CORE(0x3u);
+  *iso = val;
+  up_udelay(50);
+
+  /* Release reset */
+
+  *rst |= (CA32_NCOREPORESET(0x2u) | CA32_NCORERESET(0x2u));
+}
+
 #if defined(CONFIG_ARM_PSCI) && defined(CONFIG_SMP)
 int up_cpu_start(int cpu)
 {
@@ -149,6 +215,12 @@ int up_cpu_start(int cpu)
   UP_DSB();
 #endif
 
+  if (cpu == 1)
+    {
+      rtl8730e_core1_power_on();
+      up_udelay(40);
+    }
+
   return psci_cpu_on(cpu, (uintptr_t)__start);
 }
 #endif
diff --git a/boards/arm/rtl8730e/ca32-evb/configs/nsh/defconfig 
b/boards/arm/rtl8730e/ca32-evb/configs/nsh/defconfig
index a0bcfe619f1..e98deccb492 100644
--- a/boards/arm/rtl8730e/ca32-evb/configs/nsh/defconfig
+++ b/boards/arm/rtl8730e/ca32-evb/configs/nsh/defconfig
@@ -13,6 +13,9 @@ CONFIG_ARCH_BOARD_CA32_EVB=y
 CONFIG_ARCH_CHIP="rtl8730e"
 CONFIG_ARCH_CHIP_RTL8730E=y
 CONFIG_ARCH_INTERRUPTSTACK=2048
+CONFIG_ARM_PSCI=y
+CONFIG_SMP=y
+CONFIG_SMP_NCPUS=2
 CONFIG_ARCH_LOWVECTORS=y
 CONFIG_IDENTITY_TEXTMAP=y
 CONFIG_ARM_SEMIHOSTING_HOSTFS=y
@@ -38,6 +41,7 @@ CONFIG_HAVE_CXXINITIALIZE=y
 CONFIG_IDLETHREAD_STACKSIZE=4096
 CONFIG_INIT_ENTRYPOINT="init_main"
 CONFIG_LIBC_EXECFUNCS=y
+CONFIG_MM_DEFAULT_ALIGNMENT=64
 CONFIG_MODULE=y
 CONFIG_NSH_BUILTIN_APPS=y
 CONFIG_NSH_FILEIOSIZE=512

Reply via email to