From 65740289203c303448bc4766f84b3ad3935dd3b2 Mon Sep 17 00:00:00 2001 From: raul_chen Date: Wed, 1 Jul 2026 16:04:59 +0800 Subject: [PATCH] arch/arm: add Realtek RTL8721Dx and RTL8720F (Ameba WHC) support Add the ARM architecture-level support and build system for the Realtek Ameba WHC (Wi-Fi Host Controller) dual-core SoCs: - RTL8721Dx (KM4 Cortex-M33 host + KM0 NP) - RTL8720F (KM4TZ Cortex-M33 secure host + KM4NS NP) New directories under arch/arm/src/: - common/ameba/ -- IC-agnostic glue (os_wrapper, netdev, KV store, flash MTD, WHC Wi-Fi, SDK bootstrap) - rtl8721dx/ -- RTL8721Dx register-level drivers - rtl8720f/ -- RTL8720F register-level drivers New directories under arch/arm/include/: - rtl8721dx/ -- RTL8721Dx IRQ and chip headers - rtl8720f/ -- RTL8720F IRQ and chip headers Also includes tools/nxstyle.c white-list entries for the Realtek SDK CamelCase symbols and tools/ameba/Config.mk for the make flash target. Signed-off-by: raul_chen --- arch/arm/Kconfig | 30 + arch/arm/include/rtl8720f/chip.h | 53 + arch/arm/include/rtl8720f/irq.h | 147 +++ arch/arm/include/rtl8721dx/chip.h | 53 + arch/arm/include/rtl8721dx/irq.h | 170 +++ arch/arm/src/common/ameba/.gitignore | 4 + arch/arm/src/common/ameba/ameba_flash_mtd.c | 402 +++++++ arch/arm/src/common/ameba/ameba_flash_mtd.h | 134 +++ arch/arm/src/common/ameba/ameba_kv.c | 203 ++++ arch/arm/src/common/ameba/ameba_os_wrap.c | 988 ++++++++++++++++++ arch/arm/src/common/ameba/ameba_os_wrap.h | 90 ++ arch/arm/src/common/ameba/ameba_sdk.mk | 91 ++ arch/arm/src/common/ameba/ameba_wlan.c | 829 +++++++++++++++ arch/arm/src/common/ameba/ameba_wlan.h | 90 ++ .../ameba/sdk_shim/os_wrapper_specific.h | 49 + arch/arm/src/common/ameba/toolchain.mk | 75 ++ .../src/common/ameba/tools/ameba_build_np.sh | 167 +++ .../src/common/ameba/tools/ameba_fetch_sdk.sh | 67 ++ .../ameba/tools/ameba_fetch_toolchain.sh | 91 ++ .../common/ameba/tools/ameba_gen_autoconf.sh | 93 ++ .../src/common/ameba/tools/ameba_setup_env.sh | 120 +++ arch/arm/src/common/ameba/wifi/ameba_wifi.c | 330 ++++++ .../src/common/ameba/wifi/ameba_wifi_depend.c | 401 +++++++ .../ameba/wifi/include/ameba_lwip_off.h | 41 + .../common/ameba/wifi/include/lwip_netconf.h | 190 ++++ arch/arm/src/rtl8720f/CMakeLists.txt | 44 + arch/arm/src/rtl8720f/Kconfig | 85 ++ arch/arm/src/rtl8720f/Make.defs | 217 ++++ arch/arm/src/rtl8720f/ameba_allocateheap.c | 141 +++ arch/arm/src/rtl8720f/ameba_app_start.c | 274 +++++ arch/arm/src/rtl8720f/ameba_board.mk | 418 ++++++++ arch/arm/src/rtl8720f/ameba_ipc.c | 150 +++ arch/arm/src/rtl8720f/ameba_ipc.h | 51 + arch/arm/src/rtl8720f/ameba_irq.c | 382 +++++++ arch/arm/src/rtl8720f/ameba_irq.h | 76 ++ arch/arm/src/rtl8720f/ameba_loguart.c | 413 ++++++++ arch/arm/src/rtl8720f/ameba_start.c | 172 +++ arch/arm/src/rtl8720f/ameba_timerisr.c | 72 ++ arch/arm/src/rtl8720f/ameba_wifi_init.c | 134 +++ arch/arm/src/rtl8720f/chip.h | 39 + .../src/rtl8720f/hardware/ameba_memorymap.h | 62 ++ arch/arm/src/rtl8721dx/CMakeLists.txt | 44 + arch/arm/src/rtl8721dx/Kconfig | 85 ++ arch/arm/src/rtl8721dx/Make.defs | 198 ++++ arch/arm/src/rtl8721dx/ameba_allocateheap.c | 141 +++ arch/arm/src/rtl8721dx/ameba_app_start.c | 303 ++++++ arch/arm/src/rtl8721dx/ameba_board.mk | 418 ++++++++ arch/arm/src/rtl8721dx/ameba_irq.c | 382 +++++++ arch/arm/src/rtl8721dx/ameba_irq.h | 76 ++ arch/arm/src/rtl8721dx/ameba_loguart.c | 406 +++++++ arch/arm/src/rtl8721dx/ameba_start.c | 172 +++ arch/arm/src/rtl8721dx/ameba_timerisr.c | 72 ++ arch/arm/src/rtl8721dx/ameba_wifi_init.c | 170 +++ arch/arm/src/rtl8721dx/chip.h | 39 + .../src/rtl8721dx/hardware/ameba_memorymap.h | 52 + tools/ameba/Config.mk | 74 ++ tools/nxstyle.c | 72 +- 57 files changed, 10307 insertions(+), 35 deletions(-) create mode 100644 arch/arm/include/rtl8720f/chip.h create mode 100644 arch/arm/include/rtl8720f/irq.h create mode 100644 arch/arm/include/rtl8721dx/chip.h create mode 100644 arch/arm/include/rtl8721dx/irq.h create mode 100644 arch/arm/src/common/ameba/.gitignore create mode 100644 arch/arm/src/common/ameba/ameba_flash_mtd.c create mode 100644 arch/arm/src/common/ameba/ameba_flash_mtd.h create mode 100644 arch/arm/src/common/ameba/ameba_kv.c create mode 100644 arch/arm/src/common/ameba/ameba_os_wrap.c create mode 100644 arch/arm/src/common/ameba/ameba_os_wrap.h create mode 100644 arch/arm/src/common/ameba/ameba_sdk.mk create mode 100644 arch/arm/src/common/ameba/ameba_wlan.c create mode 100644 arch/arm/src/common/ameba/ameba_wlan.h create mode 100644 arch/arm/src/common/ameba/sdk_shim/os_wrapper_specific.h create mode 100644 arch/arm/src/common/ameba/toolchain.mk create mode 100755 arch/arm/src/common/ameba/tools/ameba_build_np.sh create mode 100755 arch/arm/src/common/ameba/tools/ameba_fetch_sdk.sh create mode 100755 arch/arm/src/common/ameba/tools/ameba_fetch_toolchain.sh create mode 100755 arch/arm/src/common/ameba/tools/ameba_gen_autoconf.sh create mode 100755 arch/arm/src/common/ameba/tools/ameba_setup_env.sh create mode 100644 arch/arm/src/common/ameba/wifi/ameba_wifi.c create mode 100644 arch/arm/src/common/ameba/wifi/ameba_wifi_depend.c create mode 100644 arch/arm/src/common/ameba/wifi/include/ameba_lwip_off.h create mode 100644 arch/arm/src/common/ameba/wifi/include/lwip_netconf.h create mode 100644 arch/arm/src/rtl8720f/CMakeLists.txt create mode 100644 arch/arm/src/rtl8720f/Kconfig create mode 100644 arch/arm/src/rtl8720f/Make.defs create mode 100644 arch/arm/src/rtl8720f/ameba_allocateheap.c create mode 100644 arch/arm/src/rtl8720f/ameba_app_start.c create mode 100644 arch/arm/src/rtl8720f/ameba_board.mk create mode 100644 arch/arm/src/rtl8720f/ameba_ipc.c create mode 100644 arch/arm/src/rtl8720f/ameba_ipc.h create mode 100644 arch/arm/src/rtl8720f/ameba_irq.c create mode 100644 arch/arm/src/rtl8720f/ameba_irq.h create mode 100644 arch/arm/src/rtl8720f/ameba_loguart.c create mode 100644 arch/arm/src/rtl8720f/ameba_start.c create mode 100644 arch/arm/src/rtl8720f/ameba_timerisr.c create mode 100644 arch/arm/src/rtl8720f/ameba_wifi_init.c create mode 100644 arch/arm/src/rtl8720f/chip.h create mode 100644 arch/arm/src/rtl8720f/hardware/ameba_memorymap.h create mode 100644 arch/arm/src/rtl8721dx/CMakeLists.txt create mode 100644 arch/arm/src/rtl8721dx/Kconfig create mode 100644 arch/arm/src/rtl8721dx/Make.defs create mode 100644 arch/arm/src/rtl8721dx/ameba_allocateheap.c create mode 100644 arch/arm/src/rtl8721dx/ameba_app_start.c create mode 100644 arch/arm/src/rtl8721dx/ameba_board.mk create mode 100644 arch/arm/src/rtl8721dx/ameba_irq.c create mode 100644 arch/arm/src/rtl8721dx/ameba_irq.h create mode 100644 arch/arm/src/rtl8721dx/ameba_loguart.c create mode 100644 arch/arm/src/rtl8721dx/ameba_start.c create mode 100644 arch/arm/src/rtl8721dx/ameba_timerisr.c create mode 100644 arch/arm/src/rtl8721dx/ameba_wifi_init.c create mode 100644 arch/arm/src/rtl8721dx/chip.h create mode 100644 arch/arm/src/rtl8721dx/hardware/ameba_memorymap.h create mode 100644 tools/ameba/Config.mk diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index e45eed4a24e..b107f0ab91d 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -855,6 +855,28 @@ config ARCH_CHIP_MPS ---help--- MPS platform (MPS2 MPS3) +config ARCH_CHIP_RTL8721DX + bool "Realtek RTL8721Dx" + select ARCH_CORTEXM33 + select ARCH_HAVE_FPU + select ARMV8M_HAVE_STACKCHECK + select OTHER_UART_SERIALDRIVER + ---help--- + Realtek RTL8721Dx (KM4 application core, ARMv8-M.main / + Cortex-M33) + +config ARCH_CHIP_RTL8720F + bool "Realtek RTL8720F" + select ARCH_CORTEXM33 + select ARCH_HAVE_FPU + select ARMV8M_HAVE_STACKCHECK + select OTHER_UART_SERIALDRIVER + ---help--- + Realtek RTL8720F (km4tz application/host core, ARMv8-M.main / + Cortex-M33). Dual-core WHC like the RTL8721Dx; the WiFi MAC/PHY + runs on the km4ns network-processor core. Shares the IC-agnostic + ameba glue in arch/arm/src/common/ameba. + config ARCH_CHIP_QEMU_ARM bool "QEMU virt platform (ARMv7a)" select ARCH_HAVE_POWEROFF @@ -1345,6 +1367,8 @@ config ARCH_CHIP default "tlsr82" if ARCH_CHIP_TLSR82 default "qemu" if ARCH_CHIP_QEMU_ARM default "mps" if ARCH_CHIP_MPS + default "rtl8721dx" if ARCH_CHIP_RTL8721DX + default "rtl8720f" if ARCH_CHIP_RTL8720F default "goldfish" if ARCH_CHIP_GOLDFISH_ARM default "at32" if ARCH_CHIP_AT32 default "cxd32xx" if ARCH_CHIP_CXD32XX @@ -1914,6 +1938,12 @@ endif if ARCH_CHIP_MPS source "arch/arm/src/mps/Kconfig" endif +if ARCH_CHIP_RTL8721DX +source "arch/arm/src/rtl8721dx/Kconfig" +endif +if ARCH_CHIP_RTL8720F +source "arch/arm/src/rtl8720f/Kconfig" +endif if ARCH_CHIP_GOLDFISH_ARM source "arch/arm/src/goldfish/Kconfig" endif diff --git a/arch/arm/include/rtl8720f/chip.h b/arch/arm/include/rtl8720f/chip.h new file mode 100644 index 00000000000..8b15d9dd7a8 --- /dev/null +++ b/arch/arm/include/rtl8720f/chip.h @@ -0,0 +1,53 @@ +/**************************************************************************** + * arch/arm/include/rtl8720f/chip.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_INCLUDE_RTL8720F_CHIP_H +#define __ARCH_ARM_INCLUDE_RTL8720F_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Prototypes + ****************************************************************************/ + +#define NVIC_SYSH_PRIORITY_MIN 0xf0 /* Bits [7:5] set in minimum priority */ +#define NVIC_SYSH_PRIORITY_DEFAULT 0x80 /* Midpoint is the default */ +#define NVIC_SYSH_PRIORITY_MAX 0x00 /* Zero is maximum priority */ +#define NVIC_SYSH_PRIORITY_STEP 0x10 /* Four bits of interrupt priority used */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +#endif /* __ARCH_ARM_INCLUDE_RTL8720F_CHIP_H */ diff --git a/arch/arm/include/rtl8720f/irq.h b/arch/arm/include/rtl8720f/irq.h new file mode 100644 index 00000000000..34422340720 --- /dev/null +++ b/arch/arm/include/rtl8720f/irq.h @@ -0,0 +1,147 @@ +/**************************************************************************** + * arch/arm/include/rtl8720f/irq.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* This file should never be included directly but, rather, only indirectly + * through nuttx/irq.h + */ + +#ifndef __ARCH_ARM_INCLUDE_RTL8720F_IRQ_H +#define __ARCH_ARM_INCLUDE_RTL8720F_IRQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Processor Exceptions (vectors 0-15) */ + +#define RTL8720F_IRQ_RESERVED (0) /* Reserved vector (only used with + * CONFIG_DEBUG_FEATURES) */ + /* Vector 1: Reset (not handler) */ +#define RTL8720F_IRQ_NMI (2) /* Vector 2: Non-Maskable Interrupt */ +#define RTL8720F_IRQ_HARDFAULT (3) /* Vector 3: Hard fault */ +#define RTL8720F_IRQ_MEMFAULT (4) /* Vector 4: Memory management (MPU) */ +#define RTL8720F_IRQ_BUSFAULT (5) /* Vector 5: Bus fault */ +#define RTL8720F_IRQ_USAGEFAULT (6) /* Vector 6: Usage fault */ +#define RTL8720F_IRQ_SECUREFAULT (7) /* Vector 7: Secure fault */ +#define RTL8720F_IRQ_SVCALL (11) /* Vector 11: SVC call */ +#define RTL8720F_IRQ_DBGMONITOR (12) /* Vector 12: Debug Monitor */ +#define RTL8720F_IRQ_PENDSV (14) /* Vector 14: Pendable system service */ +#define RTL8720F_IRQ_SYSTICK (15) /* Vector 15: System tick */ +#define RTL8720F_IRQ_FIRST (16) /* Vector number of the first external + * interrupt */ + +/* External interrupts (vectors >= 16). These map to the RTL8720F km4tz + * (AP / host) peripheral interrupt vector numbers (APIRQn, 0..57) as defined + * by the SDK's component/soc/RTL8720F/fwlib/include/ameba_vector_table.h + * (CONFIG_ARM_CORE_CM4_KM4TZ branch). + */ + +#define RTL8720F_IRQ_WIFI_FISR_FESR (RTL8720F_IRQ_FIRST + 0) +#define RTL8720F_IRQ_WL_PROTOCOL (RTL8720F_IRQ_FIRST + 1) +#define RTL8720F_IRQ_AP_WAKE (RTL8720F_IRQ_FIRST + 2) +#define RTL8720F_IRQ_IPC_KM4 (RTL8720F_IRQ_FIRST + 3) /* IPC_KM4TZ */ +#define RTL8720F_IRQ_IWDG (RTL8720F_IRQ_FIRST + 4) +#define RTL8720F_IRQ_TIMER0 (RTL8720F_IRQ_FIRST + 5) +#define RTL8720F_IRQ_TIMER1 (RTL8720F_IRQ_FIRST + 6) +#define RTL8720F_IRQ_TIMER2 (RTL8720F_IRQ_FIRST + 7) +#define RTL8720F_IRQ_TIMER3 (RTL8720F_IRQ_FIRST + 8) +#define RTL8720F_IRQ_TIMER4 (RTL8720F_IRQ_FIRST + 9) +#define RTL8720F_IRQ_TIMER5 (RTL8720F_IRQ_FIRST + 10) +#define RTL8720F_IRQ_TIMER6 (RTL8720F_IRQ_FIRST + 11) +#define RTL8720F_IRQ_PMC_TIMER0 (RTL8720F_IRQ_FIRST + 12) +#define RTL8720F_IRQ_PMC_TIMER1 (RTL8720F_IRQ_FIRST + 13) +#define RTL8720F_IRQ_UART0 (RTL8720F_IRQ_FIRST + 14) +#define RTL8720F_IRQ_UART1 (RTL8720F_IRQ_FIRST + 15) +#define RTL8720F_IRQ_UART2 (RTL8720F_IRQ_FIRST + 16) +#define RTL8720F_IRQ_UART_LOG (RTL8720F_IRQ_FIRST + 17) +#define RTL8720F_IRQ_GPIOA (RTL8720F_IRQ_FIRST + 18) +#define RTL8720F_IRQ_RSVD (RTL8720F_IRQ_FIRST + 19) +#define RTL8720F_IRQ_I2C0 (RTL8720F_IRQ_FIRST + 20) +#define RTL8720F_IRQ_I2C1 (RTL8720F_IRQ_FIRST + 21) +#define RTL8720F_IRQ_GDMA0_CH0 (RTL8720F_IRQ_FIRST + 22) +#define RTL8720F_IRQ_GDMA0_CH1 (RTL8720F_IRQ_FIRST + 23) +#define RTL8720F_IRQ_GDMA0_CH2 (RTL8720F_IRQ_FIRST + 24) +#define RTL8720F_IRQ_GDMA0_CH3 (RTL8720F_IRQ_FIRST + 25) +#define RTL8720F_IRQ_GDMA0_CH4 (RTL8720F_IRQ_FIRST + 26) +#define RTL8720F_IRQ_GDMA0_CH5 (RTL8720F_IRQ_FIRST + 27) +#define RTL8720F_IRQ_GDMA0_CH6 (RTL8720F_IRQ_FIRST + 28) +#define RTL8720F_IRQ_GDMA0_CH7 (RTL8720F_IRQ_FIRST + 29) +#define RTL8720F_IRQ_SPI0 (RTL8720F_IRQ_FIRST + 30) +#define RTL8720F_IRQ_SPI1 (RTL8720F_IRQ_FIRST + 31) +#define RTL8720F_IRQ_SPORT (RTL8720F_IRQ_FIRST + 32) +#define RTL8720F_IRQ_RTC (RTL8720F_IRQ_FIRST + 33) +#define RTL8720F_IRQ_ADC (RTL8720F_IRQ_FIRST + 34) +#define RTL8720F_IRQ_BOR (RTL8720F_IRQ_FIRST + 35) +#define RTL8720F_IRQ_PWR_DOWN (RTL8720F_IRQ_FIRST + 36) +#define RTL8720F_IRQ_PKE (RTL8720F_IRQ_FIRST + 37) +#define RTL8720F_IRQ_TRNG (RTL8720F_IRQ_FIRST + 38) +#define RTL8720F_IRQ_AON_TIM (RTL8720F_IRQ_FIRST + 39) +#define RTL8720F_IRQ_AON_WAKEPIN (RTL8720F_IRQ_FIRST + 40) +#define RTL8720F_IRQ_SDIO_WIFI (RTL8720F_IRQ_FIRST + 41) +#define RTL8720F_IRQ_SDIO_BT (RTL8720F_IRQ_FIRST + 42) +#define RTL8720F_IRQ_RXI300 (RTL8720F_IRQ_FIRST + 43) +#define RTL8720F_IRQ_PSRAMC (RTL8720F_IRQ_FIRST + 44) +#define RTL8720F_IRQ_SPI_FLASH (RTL8720F_IRQ_FIRST + 45) +#define RTL8720F_IRQ_RSIP (RTL8720F_IRQ_FIRST + 46) +#define RTL8720F_IRQ_AES (RTL8720F_IRQ_FIRST + 47) +#define RTL8720F_IRQ_SHA (RTL8720F_IRQ_FIRST + 48) +#define RTL8720F_IRQ_AES_S (RTL8720F_IRQ_FIRST + 49) +#define RTL8720F_IRQ_SHA_S (RTL8720F_IRQ_FIRST + 50) +#define RTL8720F_IRQ_KM4NS_WDG_RST (RTL8720F_IRQ_FIRST + 51) +#define RTL8720F_IRQ_KM4TZ_NS_WDG (RTL8720F_IRQ_FIRST + 52) +#define RTL8720F_IRQ_KM4TZ_S_WDG (RTL8720F_IRQ_FIRST + 53) +#define RTL8720F_IRQ_OCP (RTL8720F_IRQ_FIRST + 54) +#define RTL8720F_IRQ_BT_CTRL_HIGH (RTL8720F_IRQ_FIRST + 55) +#define RTL8720F_IRQ_BT_CTRL_LOW (RTL8720F_IRQ_FIRST + 56) +#define RTL8720F_IRQ_IR (RTL8720F_IRQ_FIRST + 57) + +#define RTL8720F_IRQ_NEXTINT (58) /* Number of external interrupts + * (APIRQn PERI_IRQ_MAX) */ + +#define NR_IRQS (RTL8720F_IRQ_FIRST + RTL8720F_IRQ_NEXTINT) + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif + +#endif /* __ARCH_ARM_INCLUDE_RTL8720F_IRQ_H */ diff --git a/arch/arm/include/rtl8721dx/chip.h b/arch/arm/include/rtl8721dx/chip.h new file mode 100644 index 00000000000..ce115b48c6e --- /dev/null +++ b/arch/arm/include/rtl8721dx/chip.h @@ -0,0 +1,53 @@ +/**************************************************************************** + * arch/arm/include/rtl8721dx/chip.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_INCLUDE_RTL8721DX_CHIP_H +#define __ARCH_ARM_INCLUDE_RTL8721DX_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Prototypes + ****************************************************************************/ + +#define NVIC_SYSH_PRIORITY_MIN 0xf0 /* Bits [7:5] set in minimum priority */ +#define NVIC_SYSH_PRIORITY_DEFAULT 0x80 /* Midpoint is the default */ +#define NVIC_SYSH_PRIORITY_MAX 0x00 /* Zero is maximum priority */ +#define NVIC_SYSH_PRIORITY_STEP 0x10 /* Four bits of interrupt priority used */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +#endif /* __ARCH_ARM_INCLUDE_RTL8721DX_CHIP_H */ diff --git a/arch/arm/include/rtl8721dx/irq.h b/arch/arm/include/rtl8721dx/irq.h new file mode 100644 index 00000000000..bb3a2430bfd --- /dev/null +++ b/arch/arm/include/rtl8721dx/irq.h @@ -0,0 +1,170 @@ +/**************************************************************************** + * arch/arm/include/rtl8721dx/irq.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* This file should never be included directly but, rather, + * only indirectly through nuttx/irq.h + */ + +#ifndef __ARCH_ARM_INCLUDE_RTL8721DX_IRQ_H +#define __ARCH_ARM_INCLUDE_RTL8721DX_IRQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Prototypes + ****************************************************************************/ + +/* Processor Exceptions (vectors 0-15) */ + +#define RTL8721DX_IRQ_RESERVED (0) /* Reserved vector (only used with + * CONFIG_DEBUG_FEATURES) */ + /* Vector 0: Reset stack pointer */ + /* Vector 1: Reset (not an IRQ) */ +#define RTL8721DX_IRQ_NMI (2) /* Vector 2: Non-Maskable Interrupt */ +#define RTL8721DX_IRQ_HARDFAULT (3) /* Vector 3: Hard fault */ +#define RTL8721DX_IRQ_MEMFAULT (4) /* Vector 4: Memory management (MPU) */ +#define RTL8721DX_IRQ_BUSFAULT (5) /* Vector 5: Bus fault */ +#define RTL8721DX_IRQ_USAGEFAULT (6) /* Vector 6: Usage fault */ + /* Vectors 7-10: Reserved */ +#define RTL8721DX_IRQ_SVCALL (11) /* Vector 11: SVC call */ +#define RTL8721DX_IRQ_DBGMONITOR (12) /* Vector 12: Debug Monitor */ + /* Vector 13: Reserved */ +#define RTL8721DX_IRQ_PENDSV (14) /* Vector 14: Pendable system service */ +#define RTL8721DX_IRQ_SYSTICK (15) /* Vector 15: System tick */ + +#define RTL8721DX_IRQ_FIRST (16) /* Vector number of the first external + * interrupt */ + +/* External interrupts (vectors >= 16). These map directly to the KM4 + * peripheral interrupt vector numbers (0..69) as defined by the amebadplus + * SDK. + */ + +#define RTL8721DX_IRQ_WIFI_FISR_FESR (RTL8721DX_IRQ_FIRST + 0) +#define RTL8721DX_IRQ_WIFI_FTSR_MBOX (RTL8721DX_IRQ_FIRST + 1) +#define RTL8721DX_IRQ_WL_DMA (RTL8721DX_IRQ_FIRST + 2) +#define RTL8721DX_IRQ_WL_PROTOCOL (RTL8721DX_IRQ_FIRST + 3) +#define RTL8721DX_IRQ_BT_SCB (RTL8721DX_IRQ_FIRST + 4) +#define RTL8721DX_IRQ_SYS_ILLEGAL_WR (RTL8721DX_IRQ_FIRST + 5) +#define RTL8721DX_IRQ_BT_WAKE_HOST (RTL8721DX_IRQ_FIRST + 6) +#define RTL8721DX_IRQ_RXI300 (RTL8721DX_IRQ_FIRST + 7) +#define RTL8721DX_IRQ_IPC_KM4 (RTL8721DX_IRQ_FIRST + 8) +#define RTL8721DX_IRQ_IWDG (RTL8721DX_IRQ_FIRST + 9) +#define RTL8721DX_IRQ_TIMER0 (RTL8721DX_IRQ_FIRST + 10) +#define RTL8721DX_IRQ_TIMER1 (RTL8721DX_IRQ_FIRST + 11) +#define RTL8721DX_IRQ_TIMER2 (RTL8721DX_IRQ_FIRST + 12) +#define RTL8721DX_IRQ_TIMER3 (RTL8721DX_IRQ_FIRST + 13) +#define RTL8721DX_IRQ_TIMER4 (RTL8721DX_IRQ_FIRST + 14) +#define RTL8721DX_IRQ_TIMER5 (RTL8721DX_IRQ_FIRST + 15) +#define RTL8721DX_IRQ_TIMER6 (RTL8721DX_IRQ_FIRST + 16) +#define RTL8721DX_IRQ_TIMER7 (RTL8721DX_IRQ_FIRST + 17) +#define RTL8721DX_IRQ_TIMER8 (RTL8721DX_IRQ_FIRST + 18) +#define RTL8721DX_IRQ_TIMER9 (RTL8721DX_IRQ_FIRST + 19) +#define RTL8721DX_IRQ_TIMER10 (RTL8721DX_IRQ_FIRST + 20) +#define RTL8721DX_IRQ_TIMER11 (RTL8721DX_IRQ_FIRST + 21) +#define RTL8721DX_IRQ_PMC_TIMER0 (RTL8721DX_IRQ_FIRST + 22) +#define RTL8721DX_IRQ_PMC_TIMER1 (RTL8721DX_IRQ_FIRST + 23) +#define RTL8721DX_IRQ_UART0 (RTL8721DX_IRQ_FIRST + 24) +#define RTL8721DX_IRQ_UART1 (RTL8721DX_IRQ_FIRST + 25) +#define RTL8721DX_IRQ_UART2_BT (RTL8721DX_IRQ_FIRST + 26) +#define RTL8721DX_IRQ_UART_LOG (RTL8721DX_IRQ_FIRST + 27) +#define RTL8721DX_IRQ_GPIOA (RTL8721DX_IRQ_FIRST + 28) +#define RTL8721DX_IRQ_GPIOB (RTL8721DX_IRQ_FIRST + 29) +#define RTL8721DX_IRQ_I2C0 (RTL8721DX_IRQ_FIRST + 30) +#define RTL8721DX_IRQ_I2C1 (RTL8721DX_IRQ_FIRST + 31) +#define RTL8721DX_IRQ_CTOUCH (RTL8721DX_IRQ_FIRST + 32) +#define RTL8721DX_IRQ_GDMA0_CH0 (RTL8721DX_IRQ_FIRST + 33) +#define RTL8721DX_IRQ_GDMA0_CH1 (RTL8721DX_IRQ_FIRST + 34) +#define RTL8721DX_IRQ_GDMA0_CH2 (RTL8721DX_IRQ_FIRST + 35) +#define RTL8721DX_IRQ_GDMA0_CH3 (RTL8721DX_IRQ_FIRST + 36) +#define RTL8721DX_IRQ_GDMA0_CH4 (RTL8721DX_IRQ_FIRST + 37) +#define RTL8721DX_IRQ_GDMA0_CH5 (RTL8721DX_IRQ_FIRST + 38) +#define RTL8721DX_IRQ_GDMA0_CH6 (RTL8721DX_IRQ_FIRST + 39) +#define RTL8721DX_IRQ_GDMA0_CH7 (RTL8721DX_IRQ_FIRST + 40) +#define RTL8721DX_IRQ_PPE (RTL8721DX_IRQ_FIRST + 41) +#define RTL8721DX_IRQ_SPI0 (RTL8721DX_IRQ_FIRST + 42) +#define RTL8721DX_IRQ_SPI1 (RTL8721DX_IRQ_FIRST + 43) +#define RTL8721DX_IRQ_SPORT0 (RTL8721DX_IRQ_FIRST + 44) +#define RTL8721DX_IRQ_SPORT1 (RTL8721DX_IRQ_FIRST + 45) +#define RTL8721DX_IRQ_RTC (RTL8721DX_IRQ_FIRST + 46) +#define RTL8721DX_IRQ_ADC (RTL8721DX_IRQ_FIRST + 47) +#define RTL8721DX_IRQ_ADC_COMP (RTL8721DX_IRQ_FIRST + 48) +#define RTL8721DX_IRQ_BOR (RTL8721DX_IRQ_FIRST + 49) +#define RTL8721DX_IRQ_PWR_DOWN (RTL8721DX_IRQ_FIRST + 50) +#define RTL8721DX_IRQ_SPI_FLASH (RTL8721DX_IRQ_FIRST + 51) +#define RTL8721DX_IRQ_KEYSCAN (RTL8721DX_IRQ_FIRST + 52) +#define RTL8721DX_IRQ_RSIP (RTL8721DX_IRQ_FIRST + 53) +#define RTL8721DX_IRQ_AES (RTL8721DX_IRQ_FIRST + 54) +#define RTL8721DX_IRQ_SHA (RTL8721DX_IRQ_FIRST + 55) +#define RTL8721DX_IRQ_PSRAMC (RTL8721DX_IRQ_FIRST + 56) +#define RTL8721DX_IRQ_TRNG (RTL8721DX_IRQ_FIRST + 57) +#define RTL8721DX_IRQ_AES_S (RTL8721DX_IRQ_FIRST + 58) +#define RTL8721DX_IRQ_SHA_S (RTL8721DX_IRQ_FIRST + 59) +#define RTL8721DX_IRQ_AON_TIM (RTL8721DX_IRQ_FIRST + 60) +#define RTL8721DX_IRQ_AON_WAKEPIN (RTL8721DX_IRQ_FIRST + 61) +#define RTL8721DX_IRQ_LEDC (RTL8721DX_IRQ_FIRST + 62) +#define RTL8721DX_IRQ_IR (RTL8721DX_IRQ_FIRST + 63) +#define RTL8721DX_IRQ_SDIO (RTL8721DX_IRQ_FIRST + 64) +#define RTL8721DX_IRQ_KM4_NS_WDG (RTL8721DX_IRQ_FIRST + 65) +#define RTL8721DX_IRQ_KM4_S_WDG (RTL8721DX_IRQ_FIRST + 66) +#define RTL8721DX_IRQ_QSPI (RTL8721DX_IRQ_FIRST + 67) +#define RTL8721DX_IRQ_USB (RTL8721DX_IRQ_FIRST + 68) +#define RTL8721DX_IRQ_OCP (RTL8721DX_IRQ_FIRST + 69) + +#define RTL8721DX_IRQ_NEXTINT (70) /* Number of external interrupts */ + +#define NR_IRQS (RTL8721DX_IRQ_FIRST + RTL8721DX_IRQ_NEXTINT) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Inline functions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif + +#endif /* __ARCH_ARM_INCLUDE_RTL8721DX_IRQ_H */ diff --git a/arch/arm/src/common/ameba/.gitignore b/arch/arm/src/common/ameba/.gitignore new file mode 100644 index 00000000000..8d83cbabece --- /dev/null +++ b/arch/arm/src/common/ameba/.gitignore @@ -0,0 +1,4 @@ +# Auto-fetched ameba-rtos SDK (one shared checkout for all ameba ARM ICs, +# fetched by tools/ameba_fetch_sdk.sh when AMEBA_SDK is unset). Vendor source +# + its python venv; never committed (vendor cache, not a build artifact). +/ameba-rtos/ diff --git a/arch/arm/src/common/ameba/ameba_flash_mtd.c b/arch/arm/src/common/ameba/ameba_flash_mtd.c new file mode 100644 index 00000000000..615cd78673a --- /dev/null +++ b/arch/arm/src/common/ameba/ameba_flash_mtd.c @@ -0,0 +1,402 @@ +/**************************************************************************** + * arch/arm/src/common/ameba/ameba_flash_mtd.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * NuttX MTD driver for the Ameba on-chip SPI NOR flash. + * + * This is the thin "flash backend" layer of the NuttX storage stack + * (MTD -> littlefs -> file API / KV). As on other SoCs whose boot flash is + * not on a directly drivable SPI bus, it is the XIP flash managed by the + * SDK's SPIC/ROM code and SHARED with the NP core. So we wrap the SDK's + * flash primitives, which already: + * - take the inter-core hardware semaphore and IPC-pause the NP + * (FLASH_Write_Lock) around erase/program, and + * - disable interrupts so no XIP fetch happens mid-operation. + * + * read -> FLASH_ReadStream (memcpy from the XIP-mapped region) + * write -> FLASH_WriteStream (self-locked page program) + * erase -> FLASH_EraseXIP (self-locked 4 KiB sector erase) + * + * Only a sub-region of the flash is exposed (the SDK's VFS1 data partition), + * so all addresses are biased by priv->base; littlefs can never touch the + * firmware images. + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ameba_flash_mtd.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define AMEBA_FLASH_ERASE_SECTOR 2 /* FLASH_Erase_Type: EraseSector */ +#define AMEBA_FLASH_ERASED_STATE 0xff /* NOR erased byte value */ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct ameba_mtd_dev_s +{ + struct mtd_dev_s mtd; /* MTD interface -- must be the first member */ + uint32_t base; /* Flash byte offset of the partition start */ + uint32_t nsectors; /* Number of erase sectors in the partition */ +}; + +/**************************************************************************** + * External Function Prototypes (SDK fwlib, ameba_flash_ram.c) + ****************************************************************************/ + +extern int FLASH_ReadStream(uint32_t address, uint32_t len, uint8_t *data); +extern int FLASH_WriteStream(uint32_t address, uint32_t len, uint8_t *data); +extern void FLASH_EraseXIP(uint32_t erasetype, uint32_t address); + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int ameba_mtd_erase(FAR struct mtd_dev_s *dev, off_t startblock, + size_t nblocks); +static ssize_t ameba_mtd_bread(FAR struct mtd_dev_s *dev, off_t startblock, + size_t nblocks, FAR uint8_t *buffer); +static ssize_t ameba_mtd_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, + size_t nblocks, FAR const uint8_t *buffer); +static ssize_t ameba_mtd_read(FAR struct mtd_dev_s *dev, off_t offset, + size_t nbytes, FAR uint8_t *buffer); +#ifdef CONFIG_MTD_BYTE_WRITE +static ssize_t ameba_mtd_write(FAR struct mtd_dev_s *dev, off_t offset, + size_t nbytes, FAR const uint8_t *buffer); +#endif +static int ameba_mtd_ioctl(FAR struct mtd_dev_s *dev, int cmd, + unsigned long arg); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ameba_mtd_erase + * + * Description: + * Erase the specified erase blocks (units of AMEBA_FLASH_SECTOR_SIZE). + * + ****************************************************************************/ + +static int ameba_mtd_erase(FAR struct mtd_dev_s *dev, off_t startblock, + size_t nblocks) +{ + FAR struct ameba_mtd_dev_s *priv = (FAR struct ameba_mtd_dev_s *)dev; + size_t i; + + if (startblock + nblocks > priv->nsectors) + { + return -EINVAL; + } + + for (i = 0; i < nblocks; i++) + { + uint32_t addr = priv->base + + (uint32_t)(startblock + i) * AMEBA_FLASH_SECTOR_SIZE; + + FLASH_EraseXIP(AMEBA_FLASH_ERASE_SECTOR, addr); + } + + return (int)nblocks; +} + +/**************************************************************************** + * Name: ameba_mtd_bread + * + * Description: + * Read the specified number of read/write blocks (units of + * AMEBA_FLASH_PAGE_SIZE). + * + ****************************************************************************/ + +static ssize_t ameba_mtd_bread(FAR struct mtd_dev_s *dev, off_t startblock, + size_t nblocks, FAR uint8_t *buffer) +{ + FAR struct ameba_mtd_dev_s *priv = (FAR struct ameba_mtd_dev_s *)dev; + uint32_t addr = priv->base + + (uint32_t)startblock * AMEBA_FLASH_PAGE_SIZE; + uint32_t len = (uint32_t)nblocks * AMEBA_FLASH_PAGE_SIZE; + + if (FLASH_ReadStream(addr, len, buffer) != 1) + { + return -EIO; + } + + return (ssize_t)nblocks; +} + +/**************************************************************************** + * Name: ameba_mtd_bwrite + * + * Description: + * Write the specified number of read/write blocks. The blocks must have + * been erased first (littlefs guarantees this at the erase-block level). + * + ****************************************************************************/ + +static ssize_t ameba_mtd_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, + size_t nblocks, FAR const uint8_t *buffer) +{ + FAR struct ameba_mtd_dev_s *priv = (FAR struct ameba_mtd_dev_s *)dev; + uint32_t addr = priv->base + + (uint32_t)startblock * AMEBA_FLASH_PAGE_SIZE; + uint32_t len = (uint32_t)nblocks * AMEBA_FLASH_PAGE_SIZE; + + if (FLASH_WriteStream(addr, len, (uint8_t *)buffer) != 1) + { + return -EIO; + } + + return (ssize_t)nblocks; +} + +/**************************************************************************** + * Name: ameba_mtd_read + ****************************************************************************/ + +static ssize_t ameba_mtd_read(FAR struct mtd_dev_s *dev, off_t offset, + size_t nbytes, FAR uint8_t *buffer) +{ + FAR struct ameba_mtd_dev_s *priv = (FAR struct ameba_mtd_dev_s *)dev; + + if (offset + (off_t)nbytes > + (off_t)(priv->nsectors * AMEBA_FLASH_SECTOR_SIZE)) + { + return -EINVAL; + } + + if (FLASH_ReadStream(priv->base + (uint32_t)offset, (uint32_t)nbytes, + buffer) != 1) + { + return -EIO; + } + + return (ssize_t)nbytes; +} + +/**************************************************************************** + * Name: ameba_mtd_write + ****************************************************************************/ + +#ifdef CONFIG_MTD_BYTE_WRITE +static ssize_t ameba_mtd_write(FAR struct mtd_dev_s *dev, off_t offset, + size_t nbytes, FAR const uint8_t *buffer) +{ + FAR struct ameba_mtd_dev_s *priv = (FAR struct ameba_mtd_dev_s *)dev; + + if (offset + (off_t)nbytes > + (off_t)(priv->nsectors * AMEBA_FLASH_SECTOR_SIZE)) + { + return -EINVAL; + } + + if (FLASH_WriteStream(priv->base + (uint32_t)offset, (uint32_t)nbytes, + (uint8_t *)buffer) != 1) + { + return -EIO; + } + + return (ssize_t)nbytes; +} +#endif + +/**************************************************************************** + * Name: ameba_mtd_ioctl + ****************************************************************************/ + +static int ameba_mtd_ioctl(FAR struct mtd_dev_s *dev, int cmd, + unsigned long arg) +{ + FAR struct ameba_mtd_dev_s *priv = (FAR struct ameba_mtd_dev_s *)dev; + int ret = -ENOTTY; + + switch (cmd) + { + case MTDIOC_GEOMETRY: + { + FAR struct mtd_geometry_s *geo = + (FAR struct mtd_geometry_s *)((uintptr_t)arg); + + if (geo == NULL) + { + return -EINVAL; + } + + memset(geo, 0, sizeof(*geo)); + geo->blocksize = AMEBA_FLASH_PAGE_SIZE; + geo->erasesize = AMEBA_FLASH_SECTOR_SIZE; + geo->neraseblocks = priv->nsectors; + strncpy(geo->model, "ameba-nor", sizeof(geo->model) - 1); + ret = OK; + } + break; + + case BIOC_PARTINFO: + { + FAR struct partition_info_s *info = + (FAR struct partition_info_s *)((uintptr_t)arg); + + if (info == NULL) + { + return -EINVAL; + } + + info->numsectors = priv->nsectors * + (AMEBA_FLASH_SECTOR_SIZE / + AMEBA_FLASH_PAGE_SIZE); + info->sectorsize = AMEBA_FLASH_PAGE_SIZE; + info->startsector = priv->base / AMEBA_FLASH_PAGE_SIZE; + strncpy(info->parent, "", sizeof(info->parent)); + ret = OK; + } + break; + + case MTDIOC_ERASESTATE: + { + FAR uint8_t *state = (FAR uint8_t *)((uintptr_t)arg); + + *state = AMEBA_FLASH_ERASED_STATE; + ret = OK; + } + break; + + case MTDIOC_BULKERASE: + ret = ameba_mtd_erase(dev, 0, priv->nsectors); + ret = (ret < 0) ? ret : OK; + break; + + default: + ret = -ENOTTY; + break; + } + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ameba_flash_mtd_initialize + ****************************************************************************/ + +FAR struct mtd_dev_s *ameba_flash_mtd_initialize(uint32_t offset, + uint32_t nbytes) +{ + FAR struct ameba_mtd_dev_s *priv; + + if ((offset % AMEBA_FLASH_SECTOR_SIZE) != 0 || + (nbytes % AMEBA_FLASH_SECTOR_SIZE) != 0 || nbytes == 0) + { + ferr("ERROR: misaligned partition off=0x%08lx size=0x%08lx\n", + (unsigned long)offset, (unsigned long)nbytes); + return NULL; + } + + priv = (FAR struct ameba_mtd_dev_s *)kmm_zalloc(sizeof(*priv)); + if (priv == NULL) + { + return NULL; + } + + priv->base = offset; + priv->nsectors = nbytes / AMEBA_FLASH_SECTOR_SIZE; + + priv->mtd.erase = ameba_mtd_erase; + priv->mtd.bread = ameba_mtd_bread; + priv->mtd.bwrite = ameba_mtd_bwrite; + priv->mtd.read = ameba_mtd_read; +#ifdef CONFIG_MTD_BYTE_WRITE + priv->mtd.write = ameba_mtd_write; +#endif + priv->mtd.ioctl = ameba_mtd_ioctl; + priv->mtd.name = "ameba-nor"; + + return &priv->mtd; +} + +/**************************************************************************** + * Name: ameba_flash_fs_initialize + ****************************************************************************/ + +int ameba_flash_fs_initialize(void) +{ + FAR struct mtd_dev_s *mtd; + int ret; + + mtd = ameba_flash_mtd_initialize(AMEBA_FLASH_VFS1_OFFSET, + AMEBA_FLASH_VFS1_SIZE); + if (mtd == NULL) + { + ferr("ERROR: ameba_flash_mtd_initialize failed\n"); + return -ENODEV; + } + + ret = register_mtddriver(AMEBA_FLASH_FS_DEVPATH, mtd, 0755, NULL); + if (ret < 0) + { + ferr("ERROR: register_mtddriver(%s) failed: %d\n", + AMEBA_FLASH_FS_DEVPATH, ret); + return ret; + } + + /* Mount littlefs. On a blank/never-formatted partition the first mount + * fails; retry once with "forceformat" to lay down a fresh filesystem. + */ + + ret = nx_mount(AMEBA_FLASH_FS_DEVPATH, AMEBA_FLASH_FS_MOUNTPT, + "littlefs", 0, NULL); + if (ret < 0) + { + finfo("littlefs mount failed (%d), formatting %s\n", ret, + AMEBA_FLASH_FS_MOUNTPT); + ret = nx_mount(AMEBA_FLASH_FS_DEVPATH, AMEBA_FLASH_FS_MOUNTPT, + "littlefs", 0, "forceformat"); + if (ret < 0) + { + ferr("ERROR: littlefs format/mount failed: %d\n", ret); + return ret; + } + } + + return OK; +} diff --git a/arch/arm/src/common/ameba/ameba_flash_mtd.h b/arch/arm/src/common/ameba/ameba_flash_mtd.h new file mode 100644 index 00000000000..462f9df5c4f --- /dev/null +++ b/arch/arm/src/common/ameba/ameba_flash_mtd.h @@ -0,0 +1,134 @@ +/**************************************************************************** + * arch/arm/src/common/ameba/ameba_flash_mtd.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_COMMON_AMEBA_AMEBA_FLASH_MTD_H +#define __ARCH_ARM_SRC_COMMON_AMEBA_AMEBA_FLASH_MTD_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +struct mtd_dev_s; + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* On-chip SPI NOR flash geometry (Puya/Winbond class). NOR has three + * distinct granularities; only the smallest two are programmable units: + * - erase sector = 4 KiB : smallest erasable unit (FLASH_EraseXIP). + * Exposed as the MTD erase block + * (geo->erasesize). + * - program page = 256 B : the NOR page-program boundary -- a single + * page-program command cannot cross it (the + * address wraps within the 256-byte page). + * Used as the MTD block unit (geo->blocksize) + * for bread/bwrite. + * - read = any : reads are byte-granular (FLASH_ReadStream). + * PAGE_SIZE is the NOR program page, NOT a NAND page -- it applies to NOR + * too. + */ + +#define AMEBA_FLASH_SECTOR_SIZE 4096 +#define AMEBA_FLASH_PAGE_SIZE 256 + +/* Data partition used for the NuttX filesystem -- the SDK's "VFS1" region, + * which the vendor reserves for the littlefs/KV store and which does NOT + * overlap the NP/AP image2 or OTA partitions. + * + * The geometry is NOT hardcoded here: it is taken from the SDK flash layout + * (CONFIG_FLASH_VFS1_OFFSET/SIZE), which the board Make.defs extracts from + * the regenerated platform_autoconf.h and passes in as + * AMEBA_FLASH_VFS1_OFFSET_XIP / AMEBA_FLASH_VFS1_SIZE_CFG. The SDK + * menuconfig is thus the single source of truth -- change the partition + * table there and this follows automatically. + * The fallbacks below are the vendor default (used only if the board did not + * provide the -D, e.g. a clean-clone first parse before PREBUILD ran). + * + * CONFIG_FLASH_VFS1_OFFSET is an XIP address (flash region base 0x08000000); + * the FLASH_xxx primitives want the flash byte offset, so strip the base. + */ + +#ifndef AMEBA_FLASH_VFS1_OFFSET_XIP +# define AMEBA_FLASH_VFS1_OFFSET_XIP 0x083e0000 +#endif +#ifndef AMEBA_FLASH_VFS1_SIZE_CFG +# define AMEBA_FLASH_VFS1_SIZE_CFG 0x00020000 +#endif + +#define AMEBA_FLASH_XIP_BASE 0x08000000 +#define AMEBA_FLASH_VFS1_OFFSET (AMEBA_FLASH_VFS1_OFFSET_XIP - AMEBA_FLASH_XIP_BASE) +#define AMEBA_FLASH_VFS1_SIZE AMEBA_FLASH_VFS1_SIZE_CFG + +/* Where the data partition is mounted, and the WiFi key-value sub-directory + * under it (rt_kv_set/get store one file per key here). Kept in this shared + * header so the board mount code and ameba_kv.c agree. + */ + +#define AMEBA_FLASH_FS_DEVPATH "/dev/ameba-nor" +#define AMEBA_FLASH_FS_MOUNTPT "/data" +#define AMEBA_KV_DIR "/data/kv" + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: ameba_flash_mtd_initialize + * + * Description: + * Create an MTD device over a region of the on-chip SPI NOR flash, backed + * by the SDK's interrupt-safe, dual-core-locked FLASH_xxx primitives. + * + * Input Parameters: + * offset - Flash byte offset of the partition start (sector aligned). + * nbytes - Partition size in bytes (sector-size multiple). + * + * Returned Value: + * An initialized MTD device pointer on success; NULL on failure. + * + ****************************************************************************/ + +FAR struct mtd_dev_s *ameba_flash_mtd_initialize(uint32_t offset, + uint32_t nbytes); + +/**************************************************************************** + * Name: ameba_flash_fs_initialize + * + * Description: + * Create the VFS1-partition MTD device, register it at + * AMEBA_FLASH_FS_DEVPATH and mount a littlefs filesystem on it at + * AMEBA_FLASH_FS_MOUNTPT (formatting it on first use). Invoked from the + * board bring-up. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int ameba_flash_fs_initialize(void); + +#endif /* __ARCH_ARM_SRC_COMMON_AMEBA_AMEBA_FLASH_MTD_H */ diff --git a/arch/arm/src/common/ameba/ameba_kv.c b/arch/arm/src/common/ameba/ameba_kv.c new file mode 100644 index 00000000000..8eef5c9c93b --- /dev/null +++ b/arch/arm/src/common/ameba/ameba_kv.c @@ -0,0 +1,203 @@ +/**************************************************************************** + * arch/arm/src/common/ameba/ameba_kv.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Realtek SDK key-value store (rt_kv_*) backed by the NuttX filesystem. + * + * The WHC host WiFi libraries persist fast-connect / PMK-cache data through + * the SDK's rt_kv_set/get API. In the vendor SDK these store one file per + * key on a littlefs partition (component/file_system/kv/kv.c does + * fopen(":KV/") + fwrite/fread). Here we provide the same + * symbols on top of NuttX's own littlefs mount (AMEBA_KV_DIR), keeping one + * file per key. + * + * This file lives on the NuttX side of the WiFi port (full NuttX headers, + * POSIX file API) -- the lwIP-colliding SDK headers are NOT pulled in, so it + * is compiled through CHIP_CSRCS rather than the SDK include path. The + * symbols are always defined when WiFi is built; if no flash filesystem is + * configured they degrade to "store nothing / always miss", which simply + * disables fast-connect (a full scan/connect still works). + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include "ameba_flash_mtd.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#ifdef CONFIG_RTL8721DX_FLASH_FS + +/**************************************************************************** + * Name: ameba_kv_path + * + * Description: + * Build the "/" path. Returns 0 on success. + * + ****************************************************************************/ + +static int ameba_kv_path(char *path, size_t size, const char *key) +{ + int n = snprintf(path, size, "%s/%s", AMEBA_KV_DIR, key); + + return (n > 0 && (size_t)n < size) ? 0 : -1; +} + +/**************************************************************************** + * Name: rt_kv_set + * + * Description: + * Store len bytes of val under key (overwriting any previous value). + * + * Returned Value: + * The number of bytes stored on success, or a negative value on error. + * + ****************************************************************************/ + +int32_t rt_kv_set(const char *key, const void *val, int32_t len) +{ + char path[64]; + int fd; + ssize_t nw; + + if (key == NULL || val == NULL || len < 0 || + ameba_kv_path(path, sizeof(path), key) < 0) + { + return -1; + } + + /* The mount point is created by the board bring-up; make sure the KV + * sub-directory exists (ignore "already exists"). + */ + + mkdir(AMEBA_KV_DIR, 0777); + + fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (fd < 0) + { + return -1; + } + + nw = write(fd, val, (size_t)len); + close(fd); + + return (nw == (ssize_t)len) ? len : -1; +} + +/**************************************************************************** + * Name: rt_kv_get + * + * Description: + * Read up to len bytes of the value stored under key into buffer. + * + * Returned Value: + * The number of bytes read on success, or a negative value if the key + * does not exist / cannot be read (treated as a cache miss by callers). + * + ****************************************************************************/ + +int32_t rt_kv_get(const char *key, void *buffer, int32_t len) +{ + char path[64]; + int fd; + ssize_t nr; + + if (key == NULL || buffer == NULL || len < 0 || + ameba_kv_path(path, sizeof(path), key) < 0) + { + return -1; + } + + fd = open(path, O_RDONLY); + if (fd < 0) + { + return -1; + } + + nr = read(fd, buffer, (size_t)len); + close(fd); + + return (nr < 0) ? -1 : (int32_t)nr; +} + +/**************************************************************************** + * Name: rt_kv_delete + * + * Description: + * Remove the value stored under key. Returns 0 on success. + * + ****************************************************************************/ + +int32_t rt_kv_delete(const char *key) +{ + char path[64]; + + if (key == NULL || ameba_kv_path(path, sizeof(path), key) < 0) + { + return -1; + } + + return (unlink(path) == 0) ? 0 : -1; +} + +#else /* CONFIG_RTL8721DX_FLASH_FS */ + +/* No persistent filesystem configured: provide the symbols so the WiFi + * libraries link, but store nothing. rt_kv_get always misses, so the host + * just performs a normal (full) connect instead of a fast-connect. + */ + +int32_t rt_kv_set(const char *key, const void *val, int32_t len) +{ + UNUSED(key); + UNUSED(val); + UNUSED(len); + return 0; +} + +int32_t rt_kv_get(const char *key, void *buffer, int32_t len) +{ + UNUSED(key); + UNUSED(buffer); + UNUSED(len); + return -1; +} + +int32_t rt_kv_delete(const char *key) +{ + UNUSED(key); + return -1; +} + +#endif /* CONFIG_RTL8721DX_FLASH_FS */ diff --git a/arch/arm/src/common/ameba/ameba_os_wrap.c b/arch/arm/src/common/ameba/ameba_os_wrap.c new file mode 100644 index 00000000000..ed40479a766 --- /dev/null +++ b/arch/arm/src/common/ameba/ameba_os_wrap.c @@ -0,0 +1,988 @@ +/**************************************************************************** + * arch/arm/src/common/ameba/ameba_os_wrap.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Description + * + * NuttX-backed implementation of the Realtek "os_wrapper" (rtos_*) API. + * + * The Realtek Ameba chip libraries (fwlib, hal, swlib, soc) are + * written against the SDK's OS-abstraction layer (os_wrapper.h, the rtos_* + * functions). In the upstream SDK these resolve to a FreeRTOS backend. In + * the NuttX port NuttX owns the image and provides the scheduler, so this + * file re-implements the same rtos_* symbols on top of NuttX primitives + * (nxsem / nxmutex / kmm / kthread / clock). The SDK's FreeRTOS backend + * (lib_freertos_os_wrapper.a) is therefore NOT linked. + * + * Only the subset of the os_wrapper API that the *kept* chip libraries + * reference (verified with nm) is implemented here. Unused entry points are + * intentionally omitted so the linker never pulls in dead code. + * + * Signatures and return conventions are taken verbatim from the SDK headers + * in component/os/os_wrapper/include/ (RTK_SUCCESS == 0, RTK_FAIL == -1). + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "arm_internal.h" +#include "ameba_os_wrap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define RTK_SUCCESS (0) +#define RTK_FAIL (-1) + +/* "Block forever" sentinel used by the SDK timeout arguments. */ + +#define RTOS_MAX_DELAY (0xffffffffu) + +/* The SDK task API uses "higher value == higher priority" with a maximum of + * RTOS_TASK_MAX_PRIORITIES (11). NuttX uses the same direction but a 1..255 + * range. Map the SDK band onto a NuttX band that sits comfortably below the + * high-priority kernel threads but above the idle thread. + */ + +#define RTOS_TASK_MAX_PRIORITIES (11) +#define AMEBA_TASK_PRIO_BASE (100) + +/* Maximum nesting depth tracked for rtos_critical_enter/exit. */ + +#define AMEBA_CRITICAL_NEST_MAX (16) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* These mirror the opaque handle and callback typedefs from the SDK headers + * (os_wrapper_semaphore.h / _mutex.h / _task.h). They are replicated here + * rather than including the SDK headers to avoid dragging in the rest of the + * SDK build configuration. The underlying types MUST stay (void *) so the + * ABI matches the chip libraries that were compiled against the SDK headers. + */ + +typedef void *rtos_sema_t; +typedef void *rtos_mutex_t; +typedef void *rtos_task_t; +typedef void *rtos_timer_t; +typedef void (*rtos_task_function_t)(void *); + +/* Trampoline context: NuttX kernel threads have a main_t entry + * (int (*)(int, char **)) while the SDK passes void (*)(void *). We bridge + * the two by allocating this context, encoding its address into argv[1] and + * recovering it in ameba_task_trampoline(). + */ + +struct ameba_task_ctx_s +{ + void (*routine)(void *); + void *param; +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int ameba_task_trampoline(int argc, char *argv[]) +{ + struct ameba_task_ctx_s *ctx; + void (*routine)(void *); + void *param; + + /* argv[1] holds the context pointer encoded as a hex string. */ + + ctx = (struct ameba_task_ctx_s *)(uintptr_t)strtoul(argv[1], NULL, 16); + routine = ctx->routine; + param = ctx->param; + kmm_free(ctx); + + routine(param); + + /* SDK tasks are expected never to return; if one does, self-delete. */ + + return 0; +} + +/**************************************************************************** + * Public Functions: memory (os_wrapper_memory.h) + ****************************************************************************/ + +void rtos_mem_init(void) +{ + /* NuttX initialises its heap during nx_start(); nothing to do here. */ +} + +bool os_heap_add(uint8_t *start_addr, size_t heap_size) +{ + /* The NuttX heap is fixed at nx_start() time (see ameba_allocateheap.c). + * Dynamic SDK heap-region donation (used by the SDK only for PSRAM, which + * this board lacks) is therefore a no-op. + */ + + UNUSED(start_addr); + UNUSED(heap_size); + return false; +} + +/* The WiFi WHC skb pool (and other DMA buffers shared with the NP) must be + * cache-line aligned: the driver does DCache_Clean/Invalidate on them and + * 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. + */ + +void *rtos_mem_malloc(uint32_t size) +{ + return kmm_malloc((size_t)size); +} + +void *rtos_mem_zmalloc(uint32_t size) +{ + return kmm_zalloc((size_t)size); +} + +void *rtos_mem_calloc(uint32_t element_num, uint32_t element_size) +{ + return kmm_calloc((size_t)element_num, (size_t)element_size); +} + +void *rtos_mem_realloc(void *pbuf, uint32_t size) +{ + return kmm_realloc(pbuf, (size_t)size); +} + +void rtos_mem_free(void *pbuf) +{ + if (pbuf != NULL) + { + kmm_free(pbuf); + } +} + +/**************************************************************************** + * Public Functions: unified object helpers (shared with FreeRTOS shim) + ****************************************************************************/ + +struct ameba_qobj_s *ameba_qobj_alloc(uint8_t tag) +{ + struct ameba_qobj_s *obj = kmm_zalloc(sizeof(struct ameba_qobj_s)); + int ret; + + if (obj == NULL) + { + return NULL; + } + + obj->tag = tag; + + switch (tag) + { + case AMEBA_QOBJ_MUTEX: + ret = nxmutex_init(&obj->u.mutex); + break; + + case AMEBA_QOBJ_RMUTEX: + ret = nxrmutex_init(&obj->u.rmutex); + break; + + case AMEBA_QOBJ_SEM: + default: + + /* Caller initialises the semaphore counts via nxsem_init below. */ + + ret = OK; + break; + } + + if (ret < 0) + { + kmm_free(obj); + return NULL; + } + + return obj; +} + +void ameba_qobj_free(struct ameba_qobj_s *obj) +{ + if (obj == NULL) + { + return; + } + + switch (obj->tag) + { + case AMEBA_QOBJ_SEM: + nxsem_destroy(&obj->u.sem); + break; + + case AMEBA_QOBJ_MUTEX: + nxmutex_destroy(&obj->u.mutex); + break; + + case AMEBA_QOBJ_RMUTEX: + nxrmutex_destroy(&obj->u.rmutex); + break; + + default: + break; + } + + kmm_free(obj); +} + +int ameba_qobj_take(struct ameba_qobj_s *obj, uint32_t ms) +{ + int ret; + + if (obj == NULL) + { + return RTK_FAIL; + } + + switch (obj->tag) + { + case AMEBA_QOBJ_MUTEX: + if (up_interrupt_context() || ms == 0) + { + ret = nxmutex_trylock(&obj->u.mutex); + } + else + { + ret = nxmutex_lock(&obj->u.mutex); + } + break; + + case AMEBA_QOBJ_RMUTEX: + if (up_interrupt_context() || ms == 0) + { + ret = nxrmutex_trylock(&obj->u.rmutex); + } + else + { + ret = nxrmutex_lock(&obj->u.rmutex); + } + break; + + case AMEBA_QOBJ_SEM: + default: + if (up_interrupt_context() || ms == 0) + { + ret = nxsem_trywait(&obj->u.sem); + } + else if (ms == RTOS_MAX_DELAY) + { + ret = nxsem_wait_uninterruptible(&obj->u.sem); + } + else + { + ret = nxsem_tickwait_uninterruptible(&obj->u.sem, + MSEC2TICK(ms)); + } + break; + } + + return (ret == OK) ? RTK_SUCCESS : RTK_FAIL; +} + +int ameba_qobj_give(struct ameba_qobj_s *obj) +{ + int ret; + + if (obj == NULL) + { + return RTK_FAIL; + } + + switch (obj->tag) + { + case AMEBA_QOBJ_MUTEX: + ret = nxmutex_unlock(&obj->u.mutex); + break; + + case AMEBA_QOBJ_RMUTEX: + ret = nxrmutex_unlock(&obj->u.rmutex); + break; + + case AMEBA_QOBJ_SEM: + default: + ret = nxsem_post(&obj->u.sem); + break; + } + + return (ret == OK) ? RTK_SUCCESS : RTK_FAIL; +} + +/**************************************************************************** + * Public Functions: semaphore (os_wrapper_semaphore.h) + ****************************************************************************/ + +int rtos_sema_create(rtos_sema_t *pp_handle, uint32_t init_count, + uint32_t max_count) +{ + struct ameba_qobj_s *obj; + + UNUSED(max_count); + + if (pp_handle == NULL) + { + return RTK_FAIL; + } + + obj = ameba_qobj_alloc(AMEBA_QOBJ_SEM); + if (obj == NULL) + { + return RTK_FAIL; + } + + if (nxsem_init(&obj->u.sem, 0, init_count) < 0) + { + kmm_free(obj); + return RTK_FAIL; + } + + *pp_handle = (rtos_sema_t)obj; + return RTK_SUCCESS; +} + +int rtos_sema_create_binary(rtos_sema_t *pp_handle) +{ + return rtos_sema_create(pp_handle, 0, 1); +} + +int rtos_sema_delete(rtos_sema_t p_handle) +{ + if (p_handle == NULL) + { + return RTK_FAIL; + } + + ameba_qobj_free((struct ameba_qobj_s *)p_handle); + return RTK_SUCCESS; +} + +int rtos_sema_take(rtos_sema_t p_handle, uint32_t timeout_ms) +{ + return ameba_qobj_take((struct ameba_qobj_s *)p_handle, timeout_ms); +} + +int rtos_sema_give(rtos_sema_t p_handle) +{ + return ameba_qobj_give((struct ameba_qobj_s *)p_handle); +} + +uint32_t rtos_sema_get_count(rtos_sema_t p_handle) +{ + struct ameba_qobj_s *obj = (struct ameba_qobj_s *)p_handle; + int count = 0; + + if (obj != NULL && obj->tag == AMEBA_QOBJ_SEM) + { + nxsem_get_value(&obj->u.sem, &count); + } + + return (uint32_t)count; +} + +/**************************************************************************** + * Public Functions: mutex (os_wrapper_mutex.h) + ****************************************************************************/ + +int rtos_mutex_create(rtos_mutex_t *pp_handle) +{ + struct ameba_qobj_s *obj; + + if (pp_handle == NULL) + { + return RTK_FAIL; + } + + obj = ameba_qobj_alloc(AMEBA_QOBJ_MUTEX); + if (obj == NULL) + { + return RTK_FAIL; + } + + *pp_handle = (rtos_mutex_t)obj; + return RTK_SUCCESS; +} + +int rtos_mutex_delete(rtos_mutex_t p_handle) +{ + if (p_handle == NULL) + { + return RTK_FAIL; + } + + ameba_qobj_free((struct ameba_qobj_s *)p_handle); + return RTK_SUCCESS; +} + +int rtos_mutex_take(rtos_mutex_t p_handle, uint32_t wait_ms) +{ + return ameba_qobj_take((struct ameba_qobj_s *)p_handle, wait_ms); +} + +int rtos_mutex_give(rtos_mutex_t p_handle) +{ + return ameba_qobj_give((struct ameba_qobj_s *)p_handle); +} + +/**************************************************************************** + * Public Functions: task / scheduler (os_wrapper_task.h) + ****************************************************************************/ + +int rtos_task_create(rtos_task_t *pp_handle, const char *p_name, + rtos_task_function_t p_routine, void *p_param, + size_t stack_size_in_byte, uint16_t priority) +{ + struct ameba_task_ctx_s *ctx; + char argbuf[2 + sizeof(uintptr_t) * 2 + 1]; + char *argv[2]; + int prio; + int pid; + + if (p_routine == NULL) + { + return RTK_FAIL; + } + + ctx = kmm_malloc(sizeof(struct ameba_task_ctx_s)); + if (ctx == NULL) + { + return RTK_FAIL; + } + + ctx->routine = p_routine; + ctx->param = p_param; + + snprintf(argbuf, sizeof(argbuf), "%p", (void *)ctx); + argv[0] = argbuf; + argv[1] = NULL; + + /* Map the SDK priority band (1..RTOS_TASK_MAX_PRIORITIES) onto a NuttX + * band centred on AMEBA_TASK_PRIO_BASE, clamped to the legal range. + */ + + prio = AMEBA_TASK_PRIO_BASE + (int)priority; + if (prio >= SCHED_PRIORITY_MAX) + { + prio = SCHED_PRIORITY_MAX - 1; + } + else if (prio <= SCHED_PRIORITY_MIN) + { + prio = SCHED_PRIORITY_MIN + 1; + } + + pid = kthread_create(p_name ? p_name : "ameba", + prio, (int)stack_size_in_byte, + ameba_task_trampoline, argv); + if (pid < 0) + { + kmm_free(ctx); + return RTK_FAIL; + } + + if (pp_handle != NULL) + { + *pp_handle = (rtos_task_t)(uintptr_t)pid; + } + + return RTK_SUCCESS; +} + +int rtos_task_delete(rtos_task_t p_handle) +{ + pid_t pid = (pid_t)(uintptr_t)p_handle; + + if (p_handle == NULL) + { + /* Delete the calling task. */ + + pid = nxsched_gettid(); + } + + kthread_delete(pid); + return RTK_SUCCESS; +} + +uint32_t rtos_task_priority_get(rtos_task_t p_handle) +{ + struct sched_param param; + pid_t pid = (pid_t)(uintptr_t)p_handle; + + if (pid == 0) + { + pid = nxsched_gettid(); + } + + if (nxsched_get_param(pid, ¶m) < 0) + { + return 0; + } + + /* Map the NuttX priority back onto the SDK band (see rtos_task_create). */ + + return (uint32_t)(param.sched_priority - AMEBA_TASK_PRIO_BASE); +} + +int rtos_task_priority_set(rtos_task_t p_handle, uint16_t priority) +{ + struct sched_param param; + pid_t pid = (pid_t)(uintptr_t)p_handle; + int prio = AMEBA_TASK_PRIO_BASE + (int)priority; + + if (prio >= SCHED_PRIORITY_MAX) + { + prio = SCHED_PRIORITY_MAX - 1; + } + else if (prio <= SCHED_PRIORITY_MIN) + { + prio = SCHED_PRIORITY_MIN + 1; + } + + if (pid == 0) + { + pid = nxsched_gettid(); + } + + param.sched_priority = prio; + return (nxsched_set_param(pid, ¶m) < 0) ? RTK_FAIL : RTK_SUCCESS; +} + +/* Run p_func(arg1, arg2) from the LP work queue after wait_ms (deferred + * call, used by the WPA supplicant). Mirrors FreeRTOS + * xTimerPendFunctionCall. + */ + +struct ameba_pend_call_s +{ + struct work_s work; + void (*func)(void *, uint32_t); + void *arg1; + uint32_t arg2; +}; + +static void ameba_pend_call_trampoline(void *arg) +{ + struct ameba_pend_call_s *p = (struct ameba_pend_call_s *)arg; + + p->func(p->arg1, p->arg2); + kmm_free(p); +} + +int rtos_timer_pend_function_call(void (*p_func)(void *, uint32_t), + void *pv_parameter1, + uint32_t ul_parameter2, + uint32_t wait_ms) +{ + struct ameba_pend_call_s *p; + + if (p_func == NULL) + { + return RTK_FAIL; + } + + p = kmm_malloc(sizeof(struct ameba_pend_call_s)); + if (p == NULL) + { + return RTK_FAIL; + } + + memset(&p->work, 0, sizeof(p->work)); + p->func = p_func; + p->arg1 = pv_parameter1; + p->arg2 = ul_parameter2; + work_queue(LPWORK, &p->work, ameba_pend_call_trampoline, p, + MSEC2TICK(wait_ms)); + return RTK_SUCCESS; +} + +int rtos_sched_suspend(void) +{ + /* NuttX has no global "suspend all" that is safe to expose to the chip + * libraries; the only callers are coarse critical sections. Use a + * lightweight scheduler lock instead. + */ + + sched_lock(); + return RTK_SUCCESS; +} + +int rtos_sched_resume(void) +{ + sched_unlock(); + return RTK_SUCCESS; +} + +/**************************************************************************** + * Public Functions: critical (os_wrapper_critical.h) + ****************************************************************************/ + +int rtos_critical_is_in_interrupt(void) +{ + return up_interrupt_context() ? 1 : 0; +} + +/* Nested critical section support. The SDK API has no "flags" output + * parameter; it relies on the backend to stack the saved interrupt state + * internally. We keep a small saved-state stack so nested enter/exit pairs + * restore the correct PRIMASK on the way out. + */ + +static irqstate_t g_critical_flags[AMEBA_CRITICAL_NEST_MAX]; +static volatile uint32_t g_critical_nest; + +void rtos_critical_enter(uint32_t component_id) +{ + irqstate_t flags; + + UNUSED(component_id); + + flags = enter_critical_section(); + + if (g_critical_nest < AMEBA_CRITICAL_NEST_MAX) + { + g_critical_flags[g_critical_nest] = flags; + } + + g_critical_nest++; +} + +void rtos_critical_exit(uint32_t component_id) +{ + irqstate_t flags = 0; + + UNUSED(component_id); + + if (g_critical_nest > 0) + { + g_critical_nest--; + if (g_critical_nest < AMEBA_CRITICAL_NEST_MAX) + { + flags = g_critical_flags[g_critical_nest]; + } + } + + leave_critical_section(flags); +} + +void __rtos_critical_enter_os(void) +{ + rtos_critical_enter(0); +} + +void __rtos_critical_exit_os(void) +{ + rtos_critical_exit(0); +} + +uint32_t rtos_get_critical_state(void) +{ + return g_critical_nest; +} + +/**************************************************************************** + * Public Functions: time (os_wrapper_time.h) + ****************************************************************************/ + +uint32_t rtos_time_get_current_system_time_ms(void) +{ + return (uint32_t)TICK2MSEC(clock_systime_ticks()); +} + +/**************************************************************************** + * Public Functions: static mutex / sema (os_wrapper_*.h) + * + * The SDK's "_static" variants exist because FreeRTOS lets the caller + * supply the object storage. Here the handle is already a pointer to our + * own heap-allocated wrapper, so the static and dynamic variants are + * identical -- just delegate. + ****************************************************************************/ + +int rtos_mutex_create_static(rtos_mutex_t *pp_handle) +{ + return rtos_mutex_create(pp_handle); +} + +int rtos_mutex_delete_static(rtos_mutex_t p_handle) +{ + return rtos_mutex_delete(p_handle); +} + +int rtos_sema_create_static(rtos_sema_t *pp_handle, uint32_t init_count, + uint32_t max_count) +{ + return rtos_sema_create(pp_handle, init_count, max_count); +} + +int rtos_sema_create_binary_static(rtos_sema_t *pp_handle) +{ + return rtos_sema_create(pp_handle, 0, 1); +} + +int rtos_sema_delete_static(rtos_sema_t p_handle) +{ + return rtos_sema_delete(p_handle); +} + +/**************************************************************************** + * Public Functions: memory / time extras (os_wrapper_memory.h, _time.h) + ****************************************************************************/ + +uint32_t rtos_mem_get_free_heap_size(void) +{ + struct mallinfo info = mallinfo(); + return (uint32_t)info.fordblks; +} + +void rtos_time_delay_ms(uint32_t ms) +{ + if (ms != 0) + { + nxsig_usleep(ms * 1000); + } +} + +/**************************************************************************** + * Public Functions: software timers (os_wrapper_timer.h) + * + * FreeRTOS-style software timers, backed by the NuttX low-priority work + * queue so the timer callback runs in task context (the SDK's WiFi timer + * callbacks may call back into the rtos_ / wifi APIs, so an ISR/wdog context + * is unsafe). reload == auto-reload (periodic); otherwise one-shot. + ****************************************************************************/ + +struct ameba_timer_s +{ + struct work_s work; + void (*cb)(void *); + uint32_t id; + uint32_t period_ticks; + bool reload; + volatile bool active; +}; + +static void ameba_timer_dispatch(void *arg) +{ + struct ameba_timer_s *t = (struct ameba_timer_s *)arg; + + if (!t->active) + { + return; + } + + /* FreeRTOS passes the timer handle to the callback. */ + + t->cb((void *)t); + + if (t->active && t->reload) + { + work_queue(LPWORK, &t->work, ameba_timer_dispatch, t, t->period_ticks); + } + else + { + t->active = false; + } +} + +int rtos_timer_create(rtos_timer_t *pp_handle, const char *p_timer_name, + uint32_t timer_id, uint32_t interval_ms, + uint8_t reload, void (*p_timer_callback)(void *)) +{ + struct ameba_timer_s *t; + + UNUSED(p_timer_name); + + if (pp_handle == NULL || p_timer_callback == NULL) + { + return RTK_FAIL; + } + + t = (struct ameba_timer_s *)kmm_zalloc(sizeof(*t)); + if (t == NULL) + { + return RTK_FAIL; + } + + t->cb = p_timer_callback; + t->id = timer_id; + t->reload = (reload != 0); + t->period_ticks = MSEC2TICK(interval_ms); + if (t->period_ticks == 0) + { + t->period_ticks = 1; + } + + *pp_handle = (rtos_timer_t)t; + return RTK_SUCCESS; +} + +int rtos_timer_create_static(rtos_timer_t *pp_handle, + const char *p_timer_name, + uint32_t timer_id, uint32_t interval_ms, + uint8_t reload, + void (*p_timer_callback)(void *)) +{ + return rtos_timer_create(pp_handle, p_timer_name, timer_id, interval_ms, + reload, p_timer_callback); +} + +int rtos_timer_start(rtos_timer_t p_handle, uint32_t wait_ms) +{ + struct ameba_timer_s *t = (struct ameba_timer_s *)p_handle; + + UNUSED(wait_ms); + + if (t == NULL) + { + return RTK_FAIL; + } + + t->active = true; + work_queue(LPWORK, &t->work, ameba_timer_dispatch, t, t->period_ticks); + return RTK_SUCCESS; +} + +int rtos_timer_stop(rtos_timer_t p_handle, uint32_t wait_ms) +{ + struct ameba_timer_s *t = (struct ameba_timer_s *)p_handle; + + UNUSED(wait_ms); + + if (t == NULL) + { + return RTK_FAIL; + } + + t->active = false; + work_cancel(LPWORK, &t->work); + return RTK_SUCCESS; +} + +int rtos_timer_change_period(rtos_timer_t p_handle, uint32_t interval_ms, + uint32_t wait_ms) +{ + struct ameba_timer_s *t = (struct ameba_timer_s *)p_handle; + + UNUSED(wait_ms); + + if (t == NULL) + { + return RTK_FAIL; + } + + t->period_ticks = MSEC2TICK(interval_ms); + if (t->period_ticks == 0) + { + t->period_ticks = 1; + } + + t->active = true; + + /* work_queue on an already-queued work re-schedules it. */ + + work_queue(LPWORK, &t->work, ameba_timer_dispatch, t, t->period_ticks); + return RTK_SUCCESS; +} + +uint32_t rtos_timer_is_timer_active(rtos_timer_t p_handle) +{ + struct ameba_timer_s *t = (struct ameba_timer_s *)p_handle; + return (t != NULL && t->active) ? 1 : 0; +} + +int rtos_timer_delete(rtos_timer_t p_handle, uint32_t wait_ms) +{ + struct ameba_timer_s *t = (struct ameba_timer_s *)p_handle; + + UNUSED(wait_ms); + + if (t == NULL) + { + return RTK_FAIL; + } + + t->active = false; + work_cancel(LPWORK, &t->work); + kmm_free(t); + return RTK_SUCCESS; +} + +int rtos_timer_delete_static(rtos_timer_t p_handle, uint32_t wait_ms) +{ + return rtos_timer_delete(p_handle, wait_ms); +} + +uint32_t rtos_timer_get_id(rtos_timer_t p_handle) +{ + struct ameba_timer_s *t = (struct ameba_timer_s *)p_handle; + return (t != NULL) ? t->id : 0; +} + +/* rtos_queue_send/receive: referenced by the SDK event source (rtw_event.c) + * from its wifi_cast / promisc paths, which the NuttX STA port does not use. + * The symbols must resolve (rtw_event.o is pulled in for wifi_event_handle), + * but the functions are never exercised -- provide failing no-ops. Queues + * are otherwise not part of the os_wrapper subset NuttX backs. + */ + +int rtos_queue_send(void *p_handle, void *p_msg, uint32_t wait_ms) +{ + (void)p_handle; + (void)p_msg; + (void)wait_ms; + return RTK_FAIL; +} + +int rtos_queue_receive(void *p_handle, void *p_msg, uint32_t wait_ms) +{ + (void)p_handle; + (void)p_msg; + (void)wait_ms; + return RTK_FAIL; +} diff --git a/arch/arm/src/common/ameba/ameba_os_wrap.h b/arch/arm/src/common/ameba/ameba_os_wrap.h new file mode 100644 index 00000000000..6e2c87b1eaa --- /dev/null +++ b/arch/arm/src/common/ameba/ameba_os_wrap.h @@ -0,0 +1,90 @@ +/**************************************************************************** + * arch/arm/src/common/ameba/ameba_os_wrap.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_COMMON_AMEBA_AMEBA_OS_WRAP_H +#define __ARCH_ARM_SRC_COMMON_AMEBA_AMEBA_OS_WRAP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define AMEBA_QOBJ_SEM (0) /* counting / binary semaphore */ +#define AMEBA_QOBJ_MUTEX (1) /* (non-recursive) mutex */ +#define AMEBA_QOBJ_RMUTEX (2) /* recursive mutex */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Unified synchronisation object. + * + * Both the os_wrapper (rtos_sema_* / rtos_mutex_*) backend and the raw + * FreeRTOS shim (xQueue* / xSemaphore*) hand the chip libraries a pointer to + * one of these. Because FreeRTOS represents semaphores and mutexes as the + * same opaque QueueHandle_t, the generic FreeRTOS functions (e.g. + * xQueueSemaphoreTake, xQueueGenericSend) may be invoked on a handle created + * by the os_wrapper sema API, and vice-versa. Using a single tagged + * object for every flavour guarantees a handle is valid no matter which API + * acts on it. + */ + +struct ameba_qobj_s +{ + uint8_t tag; /* AMEBA_QOBJ_* */ + union + { + sem_t sem; /* AMEBA_QOBJ_SEM */ + mutex_t mutex; /* AMEBA_QOBJ_MUTEX */ + rmutex_t rmutex; /* AMEBA_QOBJ_RMUTEX */ + } u; +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* Unified sync-object helpers implemented in ameba_os_wrap.c (the rtos_* + * mutex/semaphore backend is built on top of them). + */ + +struct ameba_qobj_s *ameba_qobj_alloc(uint8_t tag); +void ameba_qobj_free(struct ameba_qobj_s *obj); + +/* Blocking / polling take + give operating on the unified object. ms uses + * the SDK convention (0 == try, 0xffffffff == block forever). + */ + +int ameba_qobj_take(struct ameba_qobj_s *obj, uint32_t ms); +int ameba_qobj_give(struct ameba_qobj_s *obj); + +#endif /* __ARCH_ARM_SRC_COMMON_AMEBA_AMEBA_OS_WRAP_H */ diff --git a/arch/arm/src/common/ameba/ameba_sdk.mk b/arch/arm/src/common/ameba/ameba_sdk.mk new file mode 100644 index 00000000000..75dceec0d4e --- /dev/null +++ b/arch/arm/src/common/ameba/ameba_sdk.mk @@ -0,0 +1,91 @@ +############################################################################ +# arch/arm/src/common/ameba/ameba_sdk.mk +# +# Shared ameba-rtos SDK locator for ALL ameba ARM ICs. The ameba-rtos SDK is +# multi-chip (amebadplus / amebalite / amebasmart / ...), so it is fetched +# ONCE into arch/arm/src/common/ameba/ameba-rtos and reused by every chip's +# Make.defs -- one shared vendor-SDK checkout under the common ameba directory. +# +# The checkout PERSISTS across `make distclean` (it is gitignored cache, not a +# build artifact): switching ICs does clean + reconfigure + build, and re-cloning +# the multi-GB SDK every time would be unacceptable. A pristine reset is a +# manual `rm -rf` of the checkout. +# +# Included by BOTH the per-chip arch Make.defs and the board scripts/Make.defs +# (separate make instances). Each chip selects its SoC subdir via +# AMEBA_SOC_NAME *before* including this file. +# +# Two modes: +# 1. AMEBA_SDK set externally -> use that checkout as-is (sanity-checked). +# 2. AMEBA_SDK unset -> resolve to the shared in-tree checkout and +# fetch it on demand (the source clone happens here at parse time so it is +# available to the board PREBUILD, which runs before the arch context +# phase; the heavier python venv is provisioned later, in POSTBUILD). +# +# The pin (commit / URL) is shared across chips and overridable from the +# environment or board config. +############################################################################ + +AMEBA_SDK_REPO = ameba-rtos +ifndef AMEBA_SDK_VERSION + AMEBA_SDK_VERSION = 7d12f509102c31a2d8fa2a65843c6acb06f323f5 +endif +ifndef AMEBA_SDK_URL + AMEBA_SDK_URL = https://github.com/Ameba-AIoT/ameba-rtos.git +endif + +AMEBA_COMMON_DIR = $(TOPDIR)$(DELIM)arch$(DELIM)arm$(DELIM)src$(DELIM)common$(DELIM)ameba +AMEBA_FETCH_SDK = $(AMEBA_COMMON_DIR)$(DELIM)tools$(DELIM)ameba_fetch_sdk.sh + +# Goals that must NOT trigger an SDK fetch or toolchain probe. The SDK source +# is only needed for an actual build; clean/config goals must work (and stay +# fast) without it. CRITICAL: include clean_context / *config / apps_preconfig +# -- `make distclean` and tools/configure.sh re-invoke make for THESE as +# sub-makes (with MAKECMDGOALS set to them, not to "distclean"), so omitting +# them makes a plain `distclean` spuriously re-clone the 1.7GB SDK every time +# (painful when switching ICs, which requires distclean). +AMEBA_NOFETCH_GOALS = clean subdir_clean distclean subdir_distclean \ + clean_context clean_bootloader \ + config oldconfig olddefconfig menuconfig nconfig \ + qconfig gconfig savedefconfig \ + apps_preconfig apps_clean apps_distclean + +ifeq ($(AMEBA_SDK),) + # Mode 2: shared in-tree checkout, auto-fetched on demand. + AMEBA_SDK = $(AMEBA_COMMON_DIR)$(DELIM)$(AMEBA_SDK_REPO) + AMEBA_SDK_AUTOFETCH = y + + # Clone the SOURCE now (needed by PREBUILD's ld-script generation), unless + # this is a clean/config-only goal. The venv is NOT built here -- it is + # provisioned lazily by POSTBUILD via the same script with --with-venv. + # + # The clone runs via $(shell ...); its output is captured into a throwaway + # variable (a bare $(shell) on its own line would feed the command output + # back as makefile text -> "missing separator"). Failure is surfaced via + # .SHELLSTATUS so a broken fetch stops the build with a clear message. + ifeq ($(filter $(AMEBA_NOFETCH_GOALS),$(MAKECMDGOALS)),) + ifeq ($(wildcard $(AMEBA_SDK)/component/soc),) + $(info Fetching ameba-rtos SDK $(AMEBA_SDK_VERSION) (one-time) ...) + AMEBA_FETCH_LOG := $(shell $(AMEBA_FETCH_SDK) $(AMEBA_SDK_URL) $(AMEBA_SDK_VERSION) $(AMEBA_SDK) 2>&1) + ifneq ($(.SHELLSTATUS),0) + $(error ameba-rtos SDK fetch failed: $(AMEBA_FETCH_LOG)) + endif + endif + endif +else + # Mode 1: external checkout -- sanity-check it (it must already exist). + ifeq ($(wildcard $(AMEBA_SDK)/component/soc),) + $(error AMEBA_SDK=$(AMEBA_SDK) does not look like an ameba-rtos checkout \ + (component/soc not found)) + endif +endif + +# Resolve the asdk toolchain to the version the (now-located) SDK declares, so +# make uses the SDK-matched compiler instead of whatever arm-none-eabi-gcc +# happens to be on PATH. Skipped for clean/config-only goals where the SDK may +# be absent. +ifeq ($(filter $(AMEBA_NOFETCH_GOALS),$(MAKECMDGOALS)),) + ifneq ($(wildcard $(AMEBA_SDK)/cmake/global_define.cmake),) + include $(AMEBA_COMMON_DIR)$(DELIM)toolchain.mk + endif +endif diff --git a/arch/arm/src/common/ameba/ameba_wlan.c b/arch/arm/src/common/ameba/ameba_wlan.c new file mode 100644 index 00000000000..7eeeb34e542 --- /dev/null +++ b/arch/arm/src/common/ameba/ameba_wlan.c @@ -0,0 +1,829 @@ +/**************************************************************************** + * arch/arm/src/common/ameba/ameba_wlan.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * NuttX WLAN (STA) network device for Ameba WHC SoCs. + * + * The NP runs the WiFi MAC/PHY and delivers/accepts 802.3 (Ethernet) + * frames over the WHC IPC, so this is a plain Ethernet-style netdev + * (NET_LL_IEEE80211). + * The data path crosses to the SDK-header side through a thin byte-buffer + * ABI (the SDK's lwIP/pbuf headers collide with NuttX's, so they cannot + * share a + * translation unit): + * + * TX: ameba_wlan_txpoll -> ameba_wifi_txframe() [ameba_wifi_depend.c] + * RX: netif_adapter_wifi_recv_whc() -> ameba_wlan_rxframe() (this file) + * + * Follows the standard NuttX Ethernet-style netdev (devif) RX/TX idiom. + * IW (wireless-extension) ioctls drive scan / connect / SoftAP via wapi. + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_NET_PKT +# include +#endif +#ifdef CONFIG_NETDEV_IOCTL +# include +#endif + +#include "ameba_wlan.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define AMEBA_WLAN_STA_IDX 0 /* STA interface index on the NP */ +#define AMEBA_WLAN_AP_IDX 1 /* SoftAP interface index on the NP */ +#define AMEBA_WLAN_DEVNUM AMEBA_WLAN_STA_IDX + +/* Per-frame work buffer size (Ethernet MTU + headers + guard). */ + +#define AMEBA_WLAN_BUFSIZE (CONFIG_NET_ETH_PKTSIZE + CONFIG_NET_GUARDSIZE) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct ameba_wlan_s +{ + struct net_driver_s dev; /* Interface understood by the network */ + struct work_s pollwork; /* For deferring TX poll work to LPWORK */ + struct work_s rxwork; /* For deferring RX processing to LPWORK */ + struct iob_queue_s rxq; /* Frames queued by the WHC RX callback */ + bool bifup; /* true: ifup; false: ifdown */ + uint8_t devnum; /* NP interface index */ + + /* Association state collected across IW (wapi) ioctls. */ + + uint8_t mode; /* IW_MODE_INFRA (STA) or IW_MODE_MASTER */ + uint8_t channel; /* SoftAP channel hint (1..165, 0=default) */ + uint8_t ssid[AMEBA_WLAN_SSID_MAXLEN + 1]; + uint8_t ssid_len; + uint8_t psk[64]; /* WPA passphrase (8..63 chars) */ + uint8_t psk_len; + + /* Cached scan results (filled on SIOCSIWSCAN, read on SIOCGIWSCAN). */ + + struct ameba_scan_ap scan[AMEBA_WLAN_MAX_SCAN_AP]; + int scan_count; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct ameba_wlan_s g_ameba_wlan; + +/* TX work buffer (network stack fills it during devif_poll) and RX work + * buffer (incoming frame copied in, with room for an in-place reply). + */ + +static uint8_t g_txbuf[AMEBA_WLAN_BUFSIZE] + aligned_data(4); +static uint8_t g_rxbuf[AMEBA_WLAN_BUFSIZE] + aligned_data(4); + +/**************************************************************************** + * External Function Prototypes (SDK side, libameba_wifi.a) + ****************************************************************************/ + +extern int ameba_wifi_txframe(int idx, const void *buf, unsigned int len, + unsigned char is_special); +extern int ameba_wifi_get_mac(int idx, unsigned char *mac); +extern int ameba_wifi_scan_start(void); +extern int ameba_wifi_scan_results(struct ameba_scan_ap *out, int max); +extern int ameba_wifi_connect(const unsigned char *ssid, int ssid_len, + const unsigned char *pw, int pw_len); +extern int ameba_wifi_disconnect(void); +extern int ameba_wifi_start_ap(const unsigned char *ssid, int ssid_len, + const unsigned char *pw, int pw_len, + int channel); +extern int ameba_wifi_stop_ap(void); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ameba_wlan_is_dhcp + * + * Description: + * Detect a DHCP frame (IPv4 UDP ports 67/68) so the NP can prioritise it, + * mirroring the SDK lwIP adapter's is_special_pkt logic. + * + ****************************************************************************/ + +static unsigned char ameba_wlan_is_dhcp(const uint8_t *frame, + unsigned int len) +{ + const struct eth_hdr_s *eth = (const struct eth_hdr_s *)frame; + + if (len >= ETH_HDRLEN + 24 && eth->type == HTONS(ETHTYPE_IP)) + { + const uint8_t *ip = frame + ETH_HDRLEN; + + /* UDP src/dst ports at IP+20 (no-options header): + * 67=server, 68=client. + */ + + if ((ip[21] == 68 && ip[23] == 67) || (ip[21] == 67 && ip[23] == 68)) + { + return 1; + } + } + + return 0; +} + +/**************************************************************************** + * Name: ameba_wlan_transmit + * + * Description: + * Hand the frame currently in dev->d_buf/d_len to the NP over WHC. + * Called with the network locked. + * + ****************************************************************************/ + +static int ameba_wlan_transmit(struct ameba_wlan_s *priv) +{ + struct net_driver_s *dev = &priv->dev; + int ret; + + NETDEV_TXPACKETS(dev); + + ret = ameba_wifi_txframe(priv->devnum, dev->d_buf, dev->d_len, + ameba_wlan_is_dhcp(dev->d_buf, dev->d_len)); + ninfo("tx len=%u type=0x%04x ret=%d\n", + (unsigned)dev->d_len, + (unsigned)((dev->d_buf[12] << 8) | dev->d_buf[13]), ret); + if (ret != 0) + { + NETDEV_TXERRORS(dev); + return -EIO; + } + + NETDEV_TXDONE(dev); + return OK; +} + +/**************************************************************************** + * Name: ameba_wlan_txpoll + * + * Description: + * devif_poll() callback: transmit one prepared packet. whc_host_send() + * copies the frame, so the work buffer is immediately reusable -> return 0 + * to keep draining the queued packets. + * + ****************************************************************************/ + +static int ameba_wlan_txpoll(struct net_driver_s *dev) +{ + struct ameba_wlan_s *priv = (struct ameba_wlan_s *)dev->d_private; + + if (dev->d_len > 0) + { + ameba_wlan_transmit(priv); + } + + return 0; +} + +/**************************************************************************** + * Name: ameba_wlan_reply + * + * Description: + * Send the response, if any, that the network stack produced while + * handling a received frame. + * + * NuttX processes RX packets IN PLACE and SYNCHRONOUSLY: ipv4_input() / + * ipv6_input() / arp_input() consume the frame in dev->d_buf and, when + * the protocol requires an immediate answer, build that answer into the + * SAME buffer and set dev->d_len to its length. So after *_input() + * returns: + * - d_len > 0 -> the stack left a reply to send (e.g. an ARP reply to + * an ARP request, an ICMP echo reply to a ping, a TCP + * ACK) -> transmit it. + * - d_len == 0 -> nothing to send (e.g. a UDP datagram delivered to a + * socket) -> do nothing. + * + * This is NOT an echo/loopback of the received frame; it is the stack's + * own response. It is the standard NuttX devif RX-then-maybe-TX idiom + * used by every NuttX Ethernet driver. + * + ****************************************************************************/ + +static void ameba_wlan_reply(struct ameba_wlan_s *priv) +{ + if (priv->dev.d_len > 0) + { + ameba_wlan_transmit(priv); + } +} + +/**************************************************************************** + * Name: ameba_wlan_rxdispatch + * + * Description: + * Feed one staged frame (already in dev->d_buf/d_len) into the network + * stack by EtherType and transmit any in-place reply it produced (see + * ameba_wlan_reply): _input() may turn the RX buffer into a + * response (ARP/ICMP/TCP) with d_len set. Called from ameba_wlan_rxwork + * with the network locked. + * + ****************************************************************************/ + +static void ameba_wlan_rxdispatch(struct ameba_wlan_s *priv) +{ + struct net_driver_s *dev = &priv->dev; + struct eth_hdr_s *eth = (struct eth_hdr_s *)dev->d_buf; + + NETDEV_RXPACKETS(dev); + +#ifdef CONFIG_NET_PKT + pkt_input(dev); +#endif + + if (eth->type == HTONS(ETHTYPE_IP)) + { +#ifdef CONFIG_NET_IPv4 + NETDEV_RXIPV4(dev); + ipv4_input(dev); + ameba_wlan_reply(priv); +#else + NETDEV_RXDROPPED(dev); +#endif + } + else if (eth->type == HTONS(ETHTYPE_IP6)) + { +#ifdef CONFIG_NET_IPv6 + NETDEV_RXIPV6(dev); + ipv6_input(dev); + ameba_wlan_reply(priv); +#else + NETDEV_RXDROPPED(dev); +#endif + } + else if (eth->type == HTONS(ETHTYPE_ARP)) + { +#ifdef CONFIG_NET_ARP + NETDEV_RXARP(dev); + arp_input(dev); + ameba_wlan_reply(priv); +#else + NETDEV_RXDROPPED(dev); +#endif + } + else + { + NETDEV_RXDROPPED(dev); + } +} + +/**************************************************************************** + * Name: ameba_wlan_rxwork + * + * Description: + * Deferred RX processing (HPWORK). Drains the frames queued by + * ameba_wlan_rxframe and runs each through the network stack. + * + * Decoupling stack processing from the WHC RX callback is the whole point: + * the callback now returns immediately, so the WHC layer recycles its NP + * RX buffer (sends RECV_DONE) at once instead of waiting for ipv4_input() + * and the in-place reply TX. Otherwise the NP RX ring drains and the NP + * drops the bulk of an incoming stream (iperf collapsed to <1 Mbps). This + * is the standard NuttX WiFi netdev idiom and matches what the vendor lwIP + * adapter does via its tcpip mailbox. + * + ****************************************************************************/ + +static void ameba_wlan_rxwork(void *arg) +{ + struct ameba_wlan_s *priv = (struct ameba_wlan_s *)arg; + struct net_driver_s *dev = &priv->dev; + struct iob_s *iob; + irqstate_t flags; + + net_lock(); + + for (; ; ) + { + flags = enter_critical_section(); + iob = iob_remove_queue(&priv->rxq); + leave_critical_section(flags); + + if (iob == NULL) + { + break; + } + + /* Copy the queued frame out into the flat work buffer (room for an + * in-place reply) and run it through the stack. + */ + + dev->d_len = iob_copyout(g_rxbuf, iob, iob->io_pktlen, 0); + dev->d_buf = g_rxbuf; + iob_free_chain(iob); + + ameba_wlan_rxdispatch(priv); + } + + net_unlock(); +} + +/**************************************************************************** + * Name: ameba_wlan_rxframe + * + * Description: + * RX entry from the WHC host RX path (SDK side). Runs in the WHC RX task + * context: copy the frame into a pooled IOB, queue it, and schedule the + * deferred worker -- then return at once so the WHC layer can recycle the + * NP buffer (RECV_DONE) without waiting for stack processing. + * + ****************************************************************************/ + +void ameba_wlan_rxframe(int idx, const unsigned char *buf, unsigned int len) +{ + struct ameba_wlan_s *priv = &g_ameba_wlan; + struct iob_s *iob; + irqstate_t flags; + int ret; + + UNUSED(idx); + + if (!priv->bifup || len == 0 || len > AMEBA_WLAN_BUFSIZE) + { + return; + } + + /* Backpressure: drop if the IOB pool cannot hold the frame. Dropping here + * is far better than blocking the WHC RX task, which would stall the NP. + */ + + if (len > iob_navail(false) * CONFIG_IOB_BUFSIZE) + { + NETDEV_RXDROPPED(&priv->dev); + return; + } + + iob = iob_tryalloc(false); + if (iob == NULL) + { + NETDEV_RXDROPPED(&priv->dev); + return; + } + + ret = iob_trycopyin(iob, buf, len, 0, false); + if (ret != (int)len) + { + iob_free_chain(iob); + NETDEV_RXDROPPED(&priv->dev); + return; + } + + flags = enter_critical_section(); + ret = iob_tryadd_queue(iob, &priv->rxq); + leave_critical_section(flags); + + if (ret < 0) + { + iob_free_chain(iob); + NETDEV_RXDROPPED(&priv->dev); + return; + } + + if (work_available(&priv->rxwork)) + { + work_queue(HPWORK, &priv->rxwork, ameba_wlan_rxwork, priv, 0); + } +} + +/**************************************************************************** + * Name: ameba_wlan_txavail_work / ameba_wlan_txavail + ****************************************************************************/ + +static void ameba_wlan_txavail_work(void *arg) +{ + struct ameba_wlan_s *priv = (struct ameba_wlan_s *)arg; + + net_lock(); + if (priv->bifup) + { + priv->dev.d_buf = g_txbuf; + priv->dev.d_len = 0; + devif_poll(&priv->dev, ameba_wlan_txpoll); + } + + net_unlock(); +} + +static int ameba_wlan_txavail(struct net_driver_s *dev) +{ + struct ameba_wlan_s *priv = (struct ameba_wlan_s *)dev->d_private; + + if (work_available(&priv->pollwork)) + { + work_queue(LPWORK, &priv->pollwork, ameba_wlan_txavail_work, priv, 0); + } + + return OK; +} + +/**************************************************************************** + * Name: ameba_wlan_ifup / ameba_wlan_ifdown + ****************************************************************************/ + +static int ameba_wlan_ifup(struct net_driver_s *dev) +{ + struct ameba_wlan_s *priv = (struct ameba_wlan_s *)dev->d_private; + uint8_t mac[IFHWADDRLEN]; + + if (ameba_wifi_get_mac(priv->devnum, mac) == 0) + { + memcpy(dev->d_mac.ether.ether_addr_octet, mac, IFHWADDRLEN); + } + + ninfo("Bringing up wlan%d %02x:%02x:%02x:%02x:%02x:%02x\n", priv->devnum, + dev->d_mac.ether.ether_addr_octet[0], + dev->d_mac.ether.ether_addr_octet[1], + dev->d_mac.ether.ether_addr_octet[2], + dev->d_mac.ether.ether_addr_octet[3], + dev->d_mac.ether.ether_addr_octet[4], + dev->d_mac.ether.ether_addr_octet[5]); + + priv->bifup = true; + + /* Mark the link as running so the network stack will route TX out this + * device (udp_sendto rejects a !IFF_RUNNING device with -EHOSTUNREACH, + * which is what blocked DHCP DISCOVER from ever being transmitted). + */ + + netdev_carrier_on(dev); + return OK; +} + +static int ameba_wlan_ifdown(struct net_driver_s *dev) +{ + struct ameba_wlan_s *priv = (struct ameba_wlan_s *)dev->d_private; + irqstate_t flags; + + flags = enter_critical_section(); + priv->bifup = false; + leave_critical_section(flags); + + /* Stop the deferred RX worker and drop any frames it had not yet drained + * so the IOBs are not leaked across an ifdown/ifup cycle. + */ + + work_cancel(HPWORK, &priv->rxwork); + + flags = enter_critical_section(); + iob_free_queue(&priv->rxq); + leave_critical_section(flags); + + netdev_carrier_off(dev); + return OK; +} + +/**************************************************************************** + * Name: ameba_wlan_ioctl + ****************************************************************************/ + +#ifdef CONFIG_NETDEV_IOCTL + +/**************************************************************************** + * Name: ameba_wlan_format_scan + * + * Description: + * Encode the cached scan results into the wapi iw_event stream expected + * by SIOCGIWSCAN (one + * SIOCGIWAP/SIOCGIWFREQ/IWEVQUAL/SIOCGIWESSID/SIOCGIWENCODE set per AP), + * the iw_event stream layout the WAPI tool decodes. + * The SIOCGIWENCODE event carries only the enabled/disabled flag (the SDK + * scan record's security field), so wapi shows 0x8000 (open) vs a + * non-zero "encryption enabled" value rather than the 0xffff "unknown" + * placeholder. + * + ****************************************************************************/ + +static int ameba_wlan_format_scan(struct ameba_wlan_s *priv, + struct iwreq *iwr) +{ + unsigned int need; + uint8_t *pos; + int i; + + if (priv->scan_count <= 0) + { + iwr->u.data.length = 0; + return OK; + } + + need = priv->scan_count * + (offsetof(struct iw_event, u) * 5 + sizeof(struct sockaddr) + + sizeof(struct iw_freq) + sizeof(struct iw_quality) + + sizeof(struct iw_point) + IW_ESSID_MAX_SIZE + + sizeof(struct iw_point)); + + if (iwr->u.data.pointer == NULL || iwr->u.data.length < need) + { + iwr->u.data.length = need; + return -E2BIG; + } + + pos = iwr->u.data.pointer; + + for (i = 0; i < priv->scan_count; i++) + { + struct ameba_scan_ap *ap = &priv->scan[i]; + struct iw_event *iwe; + + iwe = (struct iw_event *)pos; + iwe->len = offsetof(struct iw_event, u) + sizeof(struct sockaddr); + iwe->cmd = SIOCGIWAP; + memcpy(iwe->u.ap_addr.sa_data, ap->bssid, 6); + + iwe = (struct iw_event *)((uintptr_t)iwe + iwe->len); + iwe->len = offsetof(struct iw_event, u) + sizeof(struct iw_freq); + iwe->cmd = SIOCGIWFREQ; + iwe->u.freq.e = 0; + iwe->u.freq.m = ap->channel; + + iwe = (struct iw_event *)((uintptr_t)iwe + iwe->len); + iwe->len = offsetof(struct iw_event, u) + sizeof(struct iw_quality); + iwe->cmd = IWEVQUAL; + iwe->u.qual.level = (uint8_t)ap->rssi; + iwe->u.qual.updated = IW_QUAL_DBM; + + iwe = (struct iw_event *)((uintptr_t)iwe + iwe->len); + iwe->len = offsetof(struct iw_event, u) + sizeof(struct iw_point) + + IW_ESSID_MAX_SIZE; + iwe->cmd = SIOCGIWESSID; + iwe->u.essid.length = ap->ssid_len; + iwe->u.essid.flags = 1; + iwe->u.essid.pointer = (FAR void *)(uintptr_t)sizeof(struct iw_point); + memcpy((uint8_t *)iwe + offsetof(struct iw_event, u) + + sizeof(struct iw_point), ap->ssid, IW_ESSID_MAX_SIZE); + + iwe = (struct iw_event *)((uintptr_t)iwe + iwe->len); + iwe->len = offsetof(struct iw_event, u) + sizeof(struct iw_point); + iwe->cmd = SIOCGIWENCODE; + iwe->u.data.length = 0; + iwe->u.data.pointer = NULL; + iwe->u.data.flags = ap->security ? + (IW_ENCODE_ENABLED | IW_ENCODE_NOKEY) : + IW_ENCODE_DISABLED; + + pos = (uint8_t *)((uintptr_t)iwe + iwe->len); + } + + iwr->u.data.length = need; + return OK; +} + +/**************************************************************************** + * Name: ameba_wlan_freq2channel + * + * Description: + * Map an SIOCSIWFREQ iw_freq into an 802.11 channel number. wapi encodes + * "wapi freq fixed" with wapi_float2freq(): a small arrives + * as a bare channel number (e == 0), a larger value as a frequency + * (m * 10^e Hz, or MHz when e == 0). Returns 0 when it cannot be mapped, + * leaving the caller's default in place. + * + ****************************************************************************/ + +static uint8_t ameba_wlan_freq2channel(const struct iw_freq *f) +{ + uint64_t hz = (uint64_t)f->m; + uint32_t mhz; + int e = f->e; + + if (e == 0 && f->m >= 1 && f->m <= 165) + { + return (uint8_t)f->m; /* already a channel number */ + } + + while (e-- > 0) + { + hz *= 10; + } + + mhz = (hz >= 1000000) ? (uint32_t)(hz / 1000000) : (uint32_t)hz; + + if (mhz >= 2412 && mhz <= 2484) + { + return (mhz == 2484) ? 14 : (uint8_t)((mhz - 2412) / 5 + 1); + } + + if (mhz >= 5000 && mhz <= 5900) + { + return (uint8_t)((mhz - 5000) / 5); + } + + return 0; +} + +static int ameba_wlan_ioctl(struct net_driver_s *dev, int cmd, + unsigned long arg) +{ + struct ameba_wlan_s *priv = (struct ameba_wlan_s *)dev->d_private; + struct iwreq *iwr = (struct iwreq *)((uintptr_t)arg); + int ret = OK; + + switch (cmd) + { + case SIOCSIWSCAN: /* Trigger a (blocking) scan */ + { + ret = ameba_wifi_scan_start(); + if (ret < 0) + { + priv->scan_count = 0; + return -EIO; + } + + ret = ameba_wifi_scan_results(priv->scan, AMEBA_WLAN_MAX_SCAN_AP); + priv->scan_count = (ret < 0) ? 0 : ret; + return OK; + } + + case SIOCGIWSCAN: /* Read back the cached scan results */ + return ameba_wlan_format_scan(priv, iwr); + + case SIOCSIWENCODEEXT: /* Store the WPA passphrase */ + { + struct iw_encode_ext *ext = iwr->u.encoding.pointer; + uint8_t klen; + + if (ext == NULL) + { + return -EINVAL; + } + + klen = ext->key_len > (int)sizeof(priv->psk) - 1 ? + sizeof(priv->psk) - 1 : ext->key_len; + memcpy(priv->psk, ext->key, klen); + priv->psk[klen] = '\0'; + priv->psk_len = klen; + return OK; + } + + case SIOCSIWESSID: /* Set SSID; flags!=0 => connect / start AP */ + { + uint8_t slen = iwr->u.essid.length; + + if (iwr->u.essid.pointer == NULL) + { + return -EINVAL; + } + + if (slen > AMEBA_WLAN_SSID_MAXLEN) + { + slen = AMEBA_WLAN_SSID_MAXLEN; + } + + memcpy(priv->ssid, iwr->u.essid.pointer, slen); + priv->ssid[slen] = '\0'; + priv->ssid_len = slen; + + /* In master (SoftAP) mode the SSID commit starts/stops the AP; + * otherwise it is the STA connect/disconnect trigger. + */ + + if (priv->mode == IW_MODE_MASTER) + { + if (iwr->u.essid.flags == 0) + { + ret = ameba_wifi_stop_ap(); + priv->devnum = AMEBA_WLAN_STA_IDX; + return ret < 0 ? -EIO : OK; + } + + ret = ameba_wifi_start_ap(priv->ssid, priv->ssid_len, + priv->psk, priv->psk_len, + priv->channel); + if (ret < 0) + { + return -EHOSTUNREACH; + } + + /* Traffic now flows on the SoftAP interface: bind the netdev + * TX path to it and adopt the AP MAC as the host L2 address. + */ + + priv->devnum = AMEBA_WLAN_AP_IDX; + ameba_wifi_get_mac(priv->devnum, + dev->d_mac.ether.ether_addr_octet); + return OK; + } + + if (iwr->u.essid.flags == 0) + { + return ameba_wifi_disconnect(); + } + + return ameba_wifi_connect(priv->ssid, priv->ssid_len, + priv->psk, priv->psk_len) < 0 ? + -EHOSTUNREACH : OK; + } + + case SIOCSIWMODE: /* STA (infra) vs SoftAP (master) */ + priv->mode = (uint8_t)iwr->u.mode; + return OK; + + case SIOCSIWFREQ: /* SoftAP channel hint (STA uses full scan) */ + { + uint8_t ch = ameba_wlan_freq2channel(&iwr->u.freq); + if (ch != 0) + { + priv->channel = ch; + } + + return OK; + } + + case SIOCSIWAUTH: /* Auth params derived from PSK presence */ + case SIOCSIWAP: /* BSSID pinning not used */ + return OK; + + case SIOCGIWESSID: + if (iwr->u.essid.pointer != NULL) + { + memcpy(iwr->u.essid.pointer, priv->ssid, priv->ssid_len); + iwr->u.essid.length = priv->ssid_len; + iwr->u.essid.flags = priv->bifup ? 1 : 0; + } + + return OK; + + default: + nwarn("Unsupported WLAN ioctl 0x%04x\n", cmd); + return -ENOTTY; + } + + return ret; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int ameba_wlan_initialize(void) +{ + struct ameba_wlan_s *priv = &g_ameba_wlan; + struct net_driver_s *dev = &priv->dev; + + memset(priv, 0, sizeof(*priv)); + priv->devnum = AMEBA_WLAN_DEVNUM; + priv->mode = IW_MODE_INFRA; /* STA by default; wapi can switch to AP */ + + dev->d_ifup = ameba_wlan_ifup; + dev->d_ifdown = ameba_wlan_ifdown; + dev->d_txavail = ameba_wlan_txavail; +#ifdef CONFIG_NETDEV_IOCTL + dev->d_ioctl = ameba_wlan_ioctl; +#endif + dev->d_private = priv; + dev->d_buf = g_txbuf; + + return netdev_register(dev, NET_LL_IEEE80211); +} diff --git a/arch/arm/src/common/ameba/ameba_wlan.h b/arch/arm/src/common/ameba/ameba_wlan.h new file mode 100644 index 00000000000..36dae205943 --- /dev/null +++ b/arch/arm/src/common/ameba/ameba_wlan.h @@ -0,0 +1,90 @@ +/**************************************************************************** + * arch/arm/src/common/ameba/ameba_wlan.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_COMMON_AMEBA_AMEBA_WLAN_H +#define __ARCH_ARM_SRC_COMMON_AMEBA_AMEBA_WLAN_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* One scan result, in plain types so it can cross the SDK<->NuttX boundary + * (the SDK's struct rtw_scan_result lives behind colliding headers). + */ + +#define AMEBA_WLAN_SSID_MAXLEN 32 +#define AMEBA_WLAN_MAX_SCAN_AP 48 + +struct ameba_scan_ap +{ + uint8_t ssid[AMEBA_WLAN_SSID_MAXLEN + 1]; /* NUL-terminated SSID */ + uint8_t ssid_len; /* SSID length */ + uint8_t bssid[6]; /* AP MAC */ + int16_t rssi; /* signal strength (dBm) */ + uint8_t channel; /* radio channel */ + uint8_t security; /* 0 open, else needs PSK */ +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: ameba_wlan_initialize + * + * Description: + * Register the WLAN (STA) network device (wlan0). Call after the WHC + * host stack is up (wifi_on). Returns 0 on success, a negated errno on + * failure. + * + ****************************************************************************/ + +int ameba_wlan_initialize(void); + +/**************************************************************************** + * Name: ameba_wlan_rxframe + * + * Description: + * RX entry called by the WHC host RX path (netif_adapter_wifi_recv_whc, + * SDK side) with one received Ethernet frame. Injects it into the NuttX + * network stack. Runs in the WHC host RX task context. + * + ****************************************************************************/ + +void ameba_wlan_rxframe(int idx, const unsigned char *buf, unsigned int len); + +#ifdef __cplusplus +} +#endif + +#endif /* __ARCH_ARM_SRC_COMMON_AMEBA_AMEBA_WLAN_H */ diff --git a/arch/arm/src/common/ameba/sdk_shim/os_wrapper_specific.h b/arch/arm/src/common/ameba/sdk_shim/os_wrapper_specific.h new file mode 100644 index 00000000000..5ee85131d6d --- /dev/null +++ b/arch/arm/src/common/ameba/sdk_shim/os_wrapper_specific.h @@ -0,0 +1,49 @@ +/**************************************************************************** + * arch/arm/src/common/ameba/sdk_shim/os_wrapper_specific.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * NuttX shim for the SDK's os_wrapper_specific.h. + * + * The stock SDK header (component/os/freertos/os_wrapper/include/) pulls in + * FreeRTOS.h, which does not exist in the NuttX port (rtos_* are backed by + * ameba_os_wrap.c). Its only payload is the RTOS_CONVERT_MS_TO_TICKS + * helper, reproduced here on NuttX's tick base. This shim is placed ahead + * of the SDK include path for the fwlib compile so SDK sources (e.g. + * ameba_flash_ram.c) + * resolve it without dragging in FreeRTOS. + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_COMMON_AMEBA_SDK_SHIM_OS_WRAPPER_SPECIFIC_H +#define __ARCH_ARM_SRC_COMMON_AMEBA_SDK_SHIM_OS_WRAPPER_SPECIFIC_H + +/* This header is compiled with the scoped SDK fwlib include set (no NuttX + * core headers), so the conversion is expressed self-contained. The NuttX + * port runs at CONFIG_USEC_PER_TICK = 1000 (1 ms / tick), so milliseconds + * map 1:1 to ticks; 0xFFFFFFFF keeps its "wait forever" sentinel. + */ + +#ifndef RTOS_CONVERT_MS_TO_TICKS +# define RTOS_CONVERT_MS_TO_TICKS(MS) \ + (((MS) == 0xFFFFFFFFUL) ? 0xFFFFFFFFUL : (unsigned long)(MS)) +#endif + +#endif /* __ARCH_ARM_SRC_COMMON_AMEBA_SDK_SHIM_OS_WRAPPER_SPECIFIC_H */ diff --git a/arch/arm/src/common/ameba/toolchain.mk b/arch/arm/src/common/ameba/toolchain.mk new file mode 100644 index 00000000000..ba2b52dd715 --- /dev/null +++ b/arch/arm/src/common/ameba/toolchain.mk @@ -0,0 +1,75 @@ +############################################################################ +# arch/arm/src/common/ameba/toolchain.mk +# +# Resolve the asdk (arm-none-eabi) toolchain to the EXACT version the fetched +# SDK requires, by reading the SDK's own declaration -- the SDK is the single +# source of truth, so the toolchain can never drift from the pinned SDK commit: +# +# cmake/global_define.cmake -> v_ASDK_VER (10.3.1) +# cmake/toolchain/ameba-toolchain-asdk-.cmake -> ToolChainVerMinor (4602) +# +# When the SDK is bumped to a commit that needs a different toolchain, those +# cmake values change and this picks the new toolchain up automatically -- no +# manual sync of a duplicated pin in the NuttX tree. Path layout mirrors the +# SDK's own ameba-toolchain-asdk-.cmake. +# +# Included by ameba_sdk.mk AFTER $(AMEBA_SDK) is resolved, in both make +# instances. If the matching toolchain is present we prepend it to PATH so the +# compile/link recipes use it regardless of what else is on PATH (the bare +# system arm-none-eabi-gcc is typically a different GCC and must not be used to +# build objects that link against the SDK's asdk-built archives). If it is +# missing we only warn (so menuconfig / clean still work) with the SDK's own +# download coordinates. +############################################################################ + +AMEBA_TOOLCHAIN_DIR ?= $(HOME)/rtk-toolchain + +AMEBA_ASDK_VER := $(strip $(shell sed -n \ + 's/.*v_ASDK_VER[ \t][ \t]*\([0-9.][0-9.]*\).*/\1/p' \ + $(AMEBA_SDK)/cmake/global_define.cmake 2>/dev/null)) + +ifneq ($(AMEBA_ASDK_VER),) + AMEBA_ASDK_BUILD := $(strip $(shell sed -n \ + 's/.*ToolChainVerMinor[ \t][ \t]*\([0-9][0-9]*\).*/\1/p' \ + $(AMEBA_SDK)/cmake/toolchain/ameba-toolchain-asdk-$(AMEBA_ASDK_VER).cmake 2>/dev/null)) +endif + +AMEBA_FETCH_TOOLCHAIN = $(AMEBA_COMMON_DIR)$(DELIM)tools$(DELIM)ameba_fetch_toolchain.sh +AMEBA_SETUP_ENV = $(AMEBA_COMMON_DIR)$(DELIM)tools$(DELIM)ameba_setup_env.sh + +# Prebuilts bundle (ninja + cmake) that the SDK's env.sh downloads -- NOT pip +# packages. The SDK build steps (NP build, axf2bin) need ninja/cmake on PATH. +# Version read from env.sh (single source of truth). Prepended even before the +# bundle exists on disk; ameba_setup_env.sh (run in PREBUILD) provisions it. +AMEBA_PREBUILTS_VER := $(strip $(shell sed -n 's/^PREBUILTS_VERSION=//p' \ + $(AMEBA_SDK)/env.sh 2>/dev/null | head -1)) +ifneq ($(AMEBA_PREBUILTS_VER),) + AMEBA_PREBUILTS_BIN := $(AMEBA_TOOLCHAIN_DIR)/prebuilts-linux-$(AMEBA_PREBUILTS_VER)/bin + ifeq ($(findstring $(AMEBA_PREBUILTS_BIN),$(PATH)),) + export PATH := $(AMEBA_PREBUILTS_BIN):$(PATH) + endif +endif + +ifneq ($(AMEBA_ASDK_BUILD),) + AMEBA_ASDK_NAME := asdk-$(AMEBA_ASDK_VER)-$(AMEBA_ASDK_BUILD) + AMEBA_ASDK_BIN := $(AMEBA_TOOLCHAIN_DIR)/$(AMEBA_ASDK_NAME)/linux/newlib/bin + + # Point PATH and GCCVER at the SDK-matched toolchain UNCONDITIONALLY (even if + # it is not on disk yet) so the version-gated flags are computed for the right + # compiler. On a bare machine the toolchain is downloaded by the PREBUILD + # step (ameba_fetch_toolchain.sh) before any compile, into exactly this path. + ifeq ($(findstring $(AMEBA_ASDK_BIN),$(PATH)),) + export PATH := $(AMEBA_ASDK_BIN):$(PATH) + endif + # Pin GCCVER to this toolchain's true major version (10 for asdk-10.3.1) and + # export it, so arch/arm/src/common/Toolchain.defs does NOT probe a stray PATH + # gcc. Otherwise version-gated flags (e.g. --param=min-pagesize=0 for + # GCC>=12) get computed for the wrong compiler and the asdk gcc rejects them. + # Accurate, not a workaround: this IS the compiler's major version. + export GCCVER := $(firstword $(subst ., ,$(AMEBA_ASDK_VER))) + + ifeq ($(wildcard $(AMEBA_ASDK_BIN)/arm-none-eabi-gcc),) + $(info ameba: toolchain $(AMEBA_ASDK_NAME) not present -- it will be \ + auto-fetched into $(AMEBA_TOOLCHAIN_DIR)/ during prebuild.) + endif +endif diff --git a/arch/arm/src/common/ameba/tools/ameba_build_np.sh b/arch/arm/src/common/ameba/tools/ameba_build_np.sh new file mode 100755 index 00000000000..b62f63a8a17 --- /dev/null +++ b/arch/arm/src/common/ameba/tools/ameba_build_np.sh @@ -0,0 +1,167 @@ +#!/bin/sh +############################################################################ +# arch/arm/src/common/ameba/tools/ameba_build_np.sh +# +# Build the NP (network/device core) image2 AND the bootloader FROM THE PINNED +# SDK SOURCE, and drop _image2_all.bin + boot.bin into . +# The NP core's SDK build target differs per IC (passed as ): +# km0 on RTL8721Dx (amebadplus), km4ns on RTL8720F, ... +# +# Why build (not ship release bins): the SDK shares many .c files and configs +# between the AP (NuttX) and NP/boot, so they must be built from the SAME pinned +# SDK as the AP image. The SDK build is incremental, so re-running this every +# NuttX build is cheap when nothing changed. +# +# Uses the SDK's native single-core / boot build entry points: +# ameba.py build --core # -> project_/image/_image2_all.bin +# ameba.py build -g boot # -> .../image/boot.bin +# The upstream SDK supports these natively (no SDK patching): `-k/--core` +# builds the given core (its target already depends on the image2 postbuild), +# `-g boot` builds the bootloader, and wifi_feature_disable honours the +# AMEBA_AP_ASM env var to generate the "noused" stubs from an external AP. +# +# The NP WiFi driver strips ("noused") any host (AP) WiFi API the AP image does +# not reference, replacing it with a stub that, if ever called, sets call_noused +# and the NP api task DEADLOCKS ("Compile NP after AP!"). The SDK normally feeds +# gen_noused_c.py the AP image's disassembly (built first). Here the AP is NuttX +# (built outside the SDK), so its disassembly is passed in as and handed +# to the SDK via the AMEBA_AP_ASM env var (see wifi_feature_disable/CMakeLists.txt). +# Without it the NP stubs APIs NuttX uses (e.g. wifi_get_scan_records) and hangs. +# +# Usage: ameba_build_np.sh [] +############################################################################ + +set -e + +SDK="$1" +SOC="$2" +OUT="$3" +AP_ASM="$4" +# NP/device-core build target: "km0" on amebadplus, "km4ns" on RTL8720F, etc. +# Its image2 is project_/image/_image2_all.bin. +NP_TARGET="${5:-km0}" +# AP-core project name: "km4" on amebadplus, "km4tz" on RTL8720F. Selects which +# per-core SDK kconfig (build_/menuconfig/.config_) to stage as +# config_km4 for the AP image2 packaging step (see below). +AP_CORE="${6:-km4}" + +if [ -z "$SDK" ] || [ -z "$SOC" ] || [ -z "$OUT" ]; then + echo "usage: ameba_build_np.sh [] []" >&2 + exit 1 +fi + +# Hand the AP (NuttX KM4) disassembly to the SDK's WiFi noused generator so the +# NP keeps real implementations for the WiFi APIs NuttX actually calls. +if [ -n "$AP_ASM" ]; then + [ -f "$AP_ASM" ] || { echo "ameba_build_np.sh: AP asm '$AP_ASM' not found" >&2; exit 1; } + AMEBA_AP_ASM="$AP_ASM" + export AMEBA_AP_ASM +fi + +# Use the python dir ameba_setup_env.sh resolved (a real .venv when one +# exists, otherwise a system-python3 shim); fall back to system python3. +PYDIR=$(cat "$SDK/.amebapy/bindir" 2>/dev/null) +VENV_PY="$PYDIR/python" +[ -x "$VENV_PY" ] || VENV_PY=python3 + +mkdir -p "$OUT" + +# Put that bin dir FIRST on PATH so the SDK build's bare `python` calls +# (setconfig.py / axf2bin) and cmake's FindPython3 resolve to the same +# interpreter (which has json5/pycryptodome). Without this the SDK configure +# fails with "Miss module: json5". prebuilts (ninja/cmake) + asdk are already +# on PATH from toolchain.mk in the NuttX build context. +PATH="${PYDIR:+$PYDIR:}$PATH" +export PATH + +# Isolate the SDK build from NuttX's Kconfig environment: NuttX exports +# BINDIR/APPSDIR/APPSBINDIR/EXTERNALDIR (tools/Unix.mk KCONFIG_ENV) plus +# srctree/KCONFIG_CONFIG, which leak into the SDK's own kconfiglib (ameba.py +# menuconfig/build) and break its Kconfig path resolution. Clear them so the +# SDK uses its own. +unset srctree BINDIR APPSDIR APPSBINDIR EXTERNALDIR EXTERNDIR KCONFIG_CONFIG \ + ARCHDIR DRIVERDIR BOARDDIR 2>/dev/null || true +# Also drop the make jobserver so the SDK's nested ninja doesn't choke on +# NuttX's jobserver fds ("Could not initialize jobserver: Invalid fds"). +unset MAKEFLAGS MAKELEVEL MFLAGS MAKEOVERRIDES 2>/dev/null || true + +# ameba.py resolves build_/ relative to the CWD, so it must run from the +# SDK root (not the NuttX tree). +cd "$SDK" || { echo "ameba_build_np.sh: cannot cd to $SDK" >&2; exit 1; } + +WORKDIR="$SDK/build_$SOC/build" + +# collect : copy immediately after its build, so +# a later -g build (which cleans the other core's image dir) cannot wipe it. +collect() { + name="$1"; rel="$2" + src="$WORKDIR/$rel" + [ -f "$src" ] || src=$(find "$SDK/build_$SOC" -name "$name" 2>/dev/null | head -1) + [ -f "$src" ] || { echo "ameba_build_np.sh: $name not produced" >&2; exit 1; } + cp "$src" "$OUT/$name" +} + +"$VENV_PY" "$SDK/ameba.py" soc "$SOC" +# --set needs an existing .config; -r generates the default one first (so this +# works on a clean tree). Result is deterministic: default config + SHELL=n. +"$VENV_PY" "$SDK/ameba.py" menuconfig "$SOC" -r +"$VENV_PY" "$SDK/ameba.py" menuconfig "$SOC" --set SHELL=n + +# Build the NP/device image2 (with AMEBA_AP_ASM-driven noused, so it stays +# aligned with exactly the host WiFi APIs NuttX references). +"$VENV_PY" "$SDK/ameba.py" build "$SOC" --core "$NP_TARGET" + +# Collect the NP image2 NOW, before the boot build: an isolated `-g boot` (which +# succeeds on amebadplus) reconfigures and cleans the OTHER core's image dir, +# wiping the just-built NP image -- so it must be saved immediately. +# project_km0 on amebadplus, project_km4ns on RTL8720F -- collect() falls back +# to a tree-wide find, so the exact relpath is only a hint. +collect "${NP_TARGET}_image2_all.bin" "project_${NP_TARGET}/image/${NP_TARGET}_image2_all.bin" + +# Build the boot (image1) loader. Prefer the isolated `-g boot` target; some +# SoCs (RTL8720F) cannot wire its loader-postbuild dependency in isolation, so +# fall back to a full SoC build, which builds boot correctly -- and, because +# AMEBA_AP_ASM is still exported, also rebuilds the NP image with the right +# noused set (the SDK's own AP image is built too and simply discarded). Both +# the NP and boot are therefore freshly rebuilt every NuttX build; nothing is +# reused stale across the two cores. +if ! "$VENV_PY" "$SDK/ameba.py" build "$SOC" -g boot; then + echo "ameba_build_np.sh: '-g boot' not buildable in isolation on $SOC;" \ + "doing a full SoC build to produce boot (AMEBA_AP_ASM kept)" >&2 + "$VENV_PY" "$SDK/ameba.py" build "$SOC" +fi + +collect boot.bin project_km4/image/boot.bin + +# Stage the SDK kconfig snapshots the NuttX POSTBUILD packaging step consumes: +# config_km4 - the AP-core () kconfig, used to wrap NuttX's img2 into +# _image2_all.bin (axf2bin make/image2/postbuild.cmake). +# config_fw - the full-firmware kconfig, used to combine boot + NP + AP into +# app.bin (project/postbuild.cmake). +# These are taken from the SDK BUILD output (build_/build/...), which is the +# exact set the SDK's own postbuild reads -- see cmake/common.cmake: the SoC +# combine uses ${BINARY_DIR}/.config (build/.config) and each image2 uses +# ${BINARY_DIR}/.config_ (build/project_/.config_). These are +# written by the configure step of the builds run above (the AP core is +# configured by the `-g boot` / full SoC build), with SHELL=n, from the PINNED +# SDK -- never committed -- so a clean checkout reproduces them and they can +# never drift from the images they were built against. Fall back to the +# menuconfig snapshot (byte-identical in practice) if the build dir lacks one. +BUILDCFG="$SDK/build_$SOC/build" +MENUCFG="$SDK/build_$SOC/menuconfig" +stage_cfg() { + dst="$1"; build_rel="$2"; menu_rel="$3" + if [ -f "$BUILDCFG/$build_rel" ]; then + cp "$BUILDCFG/$build_rel" "$OUT/$dst" + elif [ -f "$MENUCFG/$menu_rel" ]; then + cp "$MENUCFG/$menu_rel" "$OUT/$dst" + else + echo "ameba_build_np.sh: kconfig for $dst not produced" \ + "($build_rel / $menu_rel)" >&2 + exit 1 + fi +} +stage_cfg config_km4 "project_$AP_CORE/.config_$AP_CORE" ".config_$AP_CORE" +stage_cfg config_fw ".config" ".config" + +echo "NP/boot: built ${NP_TARGET}_image2_all.bin + staged kconfig from SDK ($SOC)" diff --git a/arch/arm/src/common/ameba/tools/ameba_fetch_sdk.sh b/arch/arm/src/common/ameba/tools/ameba_fetch_sdk.sh new file mode 100755 index 00000000000..7eba7602ec1 --- /dev/null +++ b/arch/arm/src/common/ameba/tools/ameba_fetch_sdk.sh @@ -0,0 +1,67 @@ +#!/bin/sh +############################################################################ +# arch/arm/src/common/ameba/tools/ameba_fetch_sdk.sh +# +# Idempotently clone the ameba-rtos SDK source at the pinned commit. One +# checkout under arch/arm/src/common/ameba/ serves every ameba ARM IC. +# +# This ONLY fetches source. The dev environment (prebuilts = ninja/cmake, and +# the python venv) is provisioned separately by ameba_setup_env.sh, which runs +# the SDK's own env.sh -- the canonical, version-matched setup. +# +# The pinned upstream SDK natively supports the out-of-SDK build NuttX needs +# (single-core `--core ` and `-g boot` entry points, and the +# AMEBA_AP_ASM-driven WiFi "noused" branch), so NO SDK patching is required. +# Any *.patch dropped in ../patches/ is still applied (extension point), but the +# tree currently ships none. +# +# The clone is SHALLOW (depth 1) at the pinned commit: no history is fetched, +# which keeps the download small/fast (the checked-out source tree is the same +# size either way). GitHub serves fetch-by-SHA, so the exact pin lands. +# +# Usage: ameba_fetch_sdk.sh +# +# Safe to call repeatedly: the clone is created only when missing. +############################################################################ + +set -e + +URL="$1" +VERSION="$2" +DEST="$3" + +if [ -z "$URL" ] || [ -z "$VERSION" ] || [ -z "$DEST" ]; then + echo "ameba_fetch_sdk.sh: missing argument (url version dest)" >&2 + exit 1 +fi + +# patches/ sits next to this script's parent (tools/../patches). +PATCH_DIR="$(CDPATH= cd "$(dirname "$0")/../patches" 2>/dev/null && pwd || true)" + +if [ ! -d "$DEST/component/soc" ]; then + echo "Auto-fetching ameba-rtos SDK $VERSION into $DEST (shallow) ..." + # Clear any partial/failed previous fetch so a retry is idempotent (a half + # fetch leaves a .git with 'origin' already added, which would otherwise make + # 'git remote add' below fail). + rm -rf "$DEST" + # Shallow fetch of the exact pinned commit -- no history, smaller/faster than + # a full clone. (`git clone --depth 1` only works for a branch/tag tip, so + # init + fetch is used to land an arbitrary pinned commit.) + git init --quiet "$DEST" + git -C "$DEST" remote add origin "$URL" + git -C "$DEST" fetch --quiet --depth 1 origin "$VERSION" + git -C "$DEST" checkout --quiet FETCH_HEAD + + # Apply the NuttX build patches on top of the pinned commit. Done only on a + # fresh clone so re-runs do not double-apply. + if [ -n "$PATCH_DIR" ] && [ -d "$PATCH_DIR" ]; then + for p in "$PATCH_DIR"/*.patch; do + [ -f "$p" ] || continue + echo "Applying SDK patch: $(basename "$p")" + git -C "$DEST" apply "$p" || { + echo "ameba_fetch_sdk.sh: failed to apply $(basename "$p")" >&2 + exit 1 + } + done + fi +fi diff --git a/arch/arm/src/common/ameba/tools/ameba_fetch_toolchain.sh b/arch/arm/src/common/ameba/tools/ameba_fetch_toolchain.sh new file mode 100755 index 00000000000..bc3a86b9ba5 --- /dev/null +++ b/arch/arm/src/common/ameba/tools/ameba_fetch_toolchain.sh @@ -0,0 +1,91 @@ +#!/bin/sh +############################################################################ +# arch/arm/src/common/ameba/tools/ameba_fetch_toolchain.sh +# +# Idempotently download + extract the asdk (arm-none-eabi) toolchain that the +# fetched SDK pins, WITHOUT modifying the SDK. The version, archive name and +# download URLs are all read from the SDK's own toolchain cmake (single source +# of truth), then fetched with wget + tar exactly the way the SDK's +# cmake/toolchain/ameba-toolchain-check.cmake does: +# +# download $TOOLCHAINURL/$NAME -> $TOOLCHAIN_DIR +# tar -jxf $NAME -> $TOOLCHAIN_DIR/asdk- +# rename asdk- -> asdk-- +# +# Usage: ameba_fetch_toolchain.sh [toolchain_dir] +# ameba-rtos checkout (has cmake/global_define.cmake) +# [toolchain_dir] install root (default: $HOME/rtk-toolchain) +# +# No-op when the matching toolchain is already present, so it is safe to call +# at the start of every build. +############################################################################ + +set -e + +SDK="$1" +TOOLCHAIN_DIR="${2:-$HOME/rtk-toolchain}" + +if [ -z "$SDK" ] || [ ! -f "$SDK/cmake/global_define.cmake" ]; then + echo "ameba_fetch_toolchain.sh: bad SDK dir '$SDK'" >&2 + exit 1 +fi + +# --- Read the pinned version from the SDK (the single source of truth) ------ + +VER=$(sed -n 's/.*v_ASDK_VER[ \t][ \t]*\([0-9.][0-9.]*\).*/\1/p' \ + "$SDK/cmake/global_define.cmake") +TC_CMAKE="$SDK/cmake/toolchain/ameba-toolchain-asdk-$VER.cmake" +if [ -z "$VER" ] || [ ! -f "$TC_CMAKE" ]; then + echo "ameba_fetch_toolchain.sh: cannot resolve ASDK version from SDK" >&2 + exit 1 +fi +BUILD=$(sed -n 's/.*ToolChainVerMinor[ \t][ \t]*\([0-9][0-9]*\).*/\1/p' "$TC_CMAKE") + +MAJOR="asdk-$VER" +DEST="$TOOLCHAIN_DIR/$MAJOR-$BUILD" + +# Already installed? (matches what toolchain.mk expects on PATH) +if [ -x "$DEST/linux/newlib/bin/arm-none-eabi-gcc" ]; then + exit 0 +fi + +# Archive name + candidate URLs, read from the SDK toolchain cmake. The cmake +# offers an Aliyun (default) and a GitHub (USE_SECOND_SOURCE) mirror; try both. +NAME="$MAJOR-linux-newlib-build-$BUILD-x86_64_with_small_reent.tar.bz2" +URLS=$(sed -n 's/.*set(TOOLCHAINURL[ \t][ \t]*\(http[^ )]*\).*/\1/p' "$TC_CMAKE") +if [ -z "$URLS" ]; then + echo "ameba_fetch_toolchain.sh: no TOOLCHAINURL found in $TC_CMAKE" >&2 + exit 1 +fi + +echo "Fetching asdk toolchain $MAJOR-$BUILD (one-time) into $TOOLCHAIN_DIR ..." +mkdir -p "$TOOLCHAIN_DIR" + +# Download (skip if the archive is already there), trying each mirror. +if [ ! -f "$TOOLCHAIN_DIR/$NAME" ]; then + ok= + for u in $URLS; do + echo " trying $u/$NAME" + if wget --progress=bar:force -O "$TOOLCHAIN_DIR/$NAME" "$u/$NAME"; then + ok=1; break + fi + rm -f "$TOOLCHAIN_DIR/$NAME" + done + if [ -z "$ok" ]; then + echo "ameba_fetch_toolchain.sh: download failed from all mirrors" >&2 + exit 1 + fi +fi + +# Extract (-> asdk-) then rename to asdk--, as the SDK does. +echo " extracting $NAME ..." +rm -rf "$TOOLCHAIN_DIR/$MAJOR" +tar -jxf "$TOOLCHAIN_DIR/$NAME" -C "$TOOLCHAIN_DIR" +rm -rf "$DEST" +mv "$TOOLCHAIN_DIR/$MAJOR" "$DEST" + +if [ ! -x "$DEST/linux/newlib/bin/arm-none-eabi-gcc" ]; then + echo "ameba_fetch_toolchain.sh: extracted tree missing arm-none-eabi-gcc at $DEST" >&2 + exit 1 +fi +echo " installed $MAJOR-$BUILD" diff --git a/arch/arm/src/common/ameba/tools/ameba_gen_autoconf.sh b/arch/arm/src/common/ameba/tools/ameba_gen_autoconf.sh new file mode 100755 index 00000000000..e13bd3961a1 --- /dev/null +++ b/arch/arm/src/common/ameba/tools/ameba_gen_autoconf.sh @@ -0,0 +1,93 @@ +#!/usr/bin/env bash +############################################################################ +# arch/arm/src/common/ameba/tools/ameba_gen_autoconf.sh +# +# Regenerate the AP-core platform_autoconf.h from the SDK menuconfig and stage +# it (with an include guard) at the path NuttX consumes. +# +# Why: the SDK flash layout / feature switches (CONFIG_FLASH_VFS1_OFFSET, +# CONFIG_WHC_*, ...) live in the SDK Kconfig. Rather than commit a hand-made +# platform_autoconf.h snapshot (which silently drifts when the SDK menuconfig +# changes, and is absent on a clean clone), we regenerate it from the SDK on +# every build. The SDK is then the single source of truth: change the layout +# in `ameba.py menuconfig ` and NuttX (ld script, WiFi force-include, VFS1 +# partition geometry) follows automatically. +# +# `ameba.py menuconfig -r` writes the default .config and regenerates the +# per-core headers at build_/menuconfig/project_/platform_autoconf.h. +# The SDK header ships WITHOUT an include guard, but ameba_lwip_off.h's +# `#undef CONFIG_LWIP_LAYER` relies on the autoconf being processed exactly once +# (many SDK headers re-#include it). So we wrap the generated header in a guard +# while staging it. +# +# usage: ameba_gen_autoconf.sh +# sdk_dir - ameba-rtos checkout +# soc - ameba.py SoC id (RTL8721Dx / RTL8720F / ...) +# ap_project - AP-core project subdir name (km4 on amebadplus, km4tz on 8720F) +# out_header - destination path for the guarded platform_autoconf.h +############################################################################ + +set -e + +SDK="$1" +SOC="$2" +AP_PROJECT="$3" +OUT="$4" + +if [ -z "$SDK" ] || [ -z "$SOC" ] || [ -z "$AP_PROJECT" ] || [ -z "$OUT" ]; then + echo "usage: ameba_gen_autoconf.sh " >&2 + exit 1 +fi + +# Use the python dir ameba_setup_env.sh resolved (a real .venv when one +# exists, otherwise a system-python3 shim); fall back to system python3. +PYDIR=$(cat "$SDK/.amebapy/bindir" 2>/dev/null) +VENV_PY="$PYDIR/python" +[ -x "$VENV_PY" ] || VENV_PY=python3 + +# Put that bin dir FIRST on PATH so the SDK tooling's bare `python` calls +# (setconfig.py / kconfiglib) resolve to the same interpreter. +PATH="${PYDIR:+$PYDIR:}$PATH" +export PATH + +# Isolate from NuttX's Kconfig environment (BINDIR/srctree/KCONFIG_CONFIG ...), +# which otherwise leaks into the SDK's own kconfiglib and breaks its Kconfig +# path resolution. Also drop the make jobserver fds. +unset srctree BINDIR APPSDIR APPSBINDIR EXTERNALDIR EXTERNDIR KCONFIG_CONFIG \ + ARCHDIR DRIVERDIR BOARDDIR 2>/dev/null || true +unset MAKEFLAGS MAKELEVEL MFLAGS MAKEOVERRIDES 2>/dev/null || true + +# ameba.py resolves build_/ relative to the CWD, so run from the SDK root. +cd "$SDK" || { echo "ameba_gen_autoconf.sh: cannot cd to $SDK" >&2; exit 1; } + +# Select the SoC and write the default config + regenerate the per-core headers. +# -r is deterministic (default config), so a clean clone reproduces it exactly. +"$VENV_PY" "$SDK/ameba.py" soc "$SOC" >/dev/null +"$VENV_PY" "$SDK/ameba.py" menuconfig "$SOC" -r >/dev/null + +GEN="$SDK/build_$SOC/menuconfig/project_$AP_PROJECT/platform_autoconf.h" +if [ ! -f "$GEN" ]; then + echo "ameba_gen_autoconf.sh: generated autoconf not found: $GEN" >&2 + exit 1 +fi + +# Stage with an include guard so the force-included override in ameba_lwip_off.h +# survives the SDK's repeated re-#includes of this header. +mkdir -p "$(dirname "$OUT")" +{ + echo "/* Auto-generated by ameba_gen_autoconf.sh from the SDK menuconfig." + echo " * DO NOT EDIT and DO NOT COMMIT -- regenerated on every build so the" + echo " * SDK Kconfig stays the single source of truth. The include guard is" + echo " * added here (the SDK header has none) so ameba_lwip_off.h's" + echo " * #undef CONFIG_LWIP_LAYER survives the SDK's repeated re-#includes." + echo " */" + echo "" + echo "#ifndef __AMEBA_PLATFORM_AUTOCONF_H__" + echo "#define __AMEBA_PLATFORM_AUTOCONF_H__" + echo "" + cat "$GEN" + echo "" + echo "#endif /* __AMEBA_PLATFORM_AUTOCONF_H__ */" +} > "$OUT" + +echo "GEN: platform_autoconf.h <- SDK menuconfig ($SOC project_$AP_PROJECT)" diff --git a/arch/arm/src/common/ameba/tools/ameba_setup_env.sh b/arch/arm/src/common/ameba/tools/ameba_setup_env.sh new file mode 100755 index 00000000000..12c4ad26df8 --- /dev/null +++ b/arch/arm/src/common/ameba/tools/ameba_setup_env.sh @@ -0,0 +1,120 @@ +#!/bin/sh +############################################################################ +# arch/arm/src/common/ameba/tools/ameba_setup_env.sh +# +# Ensure the ameba-rtos build prerequisites are available, WITHOUT hard- +# requiring the SDK python venv (.venv). Two things are needed: +# +# * ninja/cmake -- shipped in the prebuilts bundle the SDK env.sh fetches; +# * a python interpreter (reachable as both `python` and `python3`) that has +# the SDK tool deps json5/click used by the cmake setconfig + axf2bin steps. +# +# Resolution is unified across developer machines and CI -- it uses whatever +# already works and only bootstraps when nothing does. It resolves a *bin +# directory* to prepend to PATH and records it in $SDK/.amebapy/bindir; the +# rest of the build (board.mk PATH prepend, ameba_gen_autoconf.sh / +# ameba_build_np.sh) reads that file instead of hard-coding $SDK/.venv/bin: +# +# 1. the SDK venv ($SDK/.venv/bin), if its python imports the deps -- a +# developer who ran `source env.sh`, or a cached venv. The venv python +# MUST be used by its real path (so its site-packages stay active), so +# this case publishes $SDK/.venv/bin directly. +# 2. otherwise the system python3, if it imports the deps (CI installs them; +# env.sh also pip-installs them to the system when its venv is pip-less). +# A thin $SDK/.amebapy/bin is created with python/python3 symlinks to the +# system interpreter (it is not a venv, so the symlinks keep the system +# site-packages, and a bare `python` exists for the SDK cmake steps). +# 3. otherwise run the SDK env.sh once to bootstrap prebuilts + venv, then +# re-resolve. +# +# This is why the build no longer fails on a broken/missing .venv (e.g. a CI +# image without python3-venv/ensurepip): as long as the system python3 carries +# the deps, the build proceeds against it. +# +# Usage: ameba_setup_env.sh [toolchain_dir] +# +# Idempotent: a no-op once ninja and a deps-carrying python are resolved. +############################################################################ + +set -e + +SDK="$1" +TCDIR="${2:-$HOME/rtk-toolchain}" + +[ -f "$SDK/env.sh" ] || { echo "ameba_setup_env.sh: no env.sh in $SDK" >&2; exit 1; } + +PBVER=$(sed -n 's/^PREBUILTS_VERSION=//p' "$SDK/env.sh" | head -1) +PB="$TCDIR/prebuilts-linux-$PBVER" +SHIMBIN="$SDK/.amebapy/bin" +BINFILE="$SDK/.amebapy/bindir" + +# env.sh installs the full tools/requirements.txt into whichever python it can +# (the SDK .venv on a dev box; the system python3 in CI, where its venv is +# pip-less). This sentinel just confirms that install landed in the python we +# are about to use. It checks json5 + click (the ameba.py / setconfig deps) +# AND Crypto (pycryptodome) -- a *compiled* wheel: the deps that fail on a +# flaky PyPI / a toolchain-less image are the compiled ones, so a successful +# `import Crypto` is a reliable signal the whole set (incl. cryptography/ecdsa/ +# pyelftools/... used by the axf2bin image-signing step) installed too. +# kconfiglib is vendored in the SDK (put on sys.path by ameba.py), not gated. +py_has_deps() { + "$1" -c 'import json5, click, Crypto' 2>/dev/null +} + +# Echo the bin directory whose python/python3 carry the deps, or return 1. +resolve_bindir() { + # 1. real SDK venv -- used directly so its site-packages stay active. + if [ -x "$SDK/.venv/bin/python" ] && py_has_deps "$SDK/.venv/bin/python"; then + printf '%s\n' "$SDK/.venv/bin" + return 0 + fi + + # 2. system python3 -- expose it via a non-venv shim dir so a bare `python` + # exists and the system site-packages (with the deps) stay visible. + if command -v python3 >/dev/null 2>&1 && py_has_deps python3; then + sp=$(command -v python3) + mkdir -p "$SHIMBIN" + ln -sf "$sp" "$SHIMBIN/python" + ln -sf "$sp" "$SHIMBIN/python3" + printf '%s\n' "$SHIMBIN" + return 0 + fi + + return 1 +} + +publish_bindir() { + mkdir -p "$SDK/.amebapy" + printf '%s\n' "$1" > "$BINFILE" +} + +# Fast path: ninja present and a deps-carrying python already resolves. +if [ -x "$PB/bin/ninja" ] && BINDIR=$(resolve_bindir); then + publish_bindir "$BINDIR" + exit 0 +fi + +echo "Setting up ameba-rtos build prerequisites (prebuilts + python deps) ..." + +# Bootstrap via the SDK env.sh (fetches the prebuilts bundle; on a developer +# box also builds the .venv and pip-installs the deps). Best-effort: on CI it +# may only manage to install the deps to the system python3, which is fine. +RTK_TOOLCHAIN_DIR="$TCDIR" bash -c "cd '$SDK' && . ./env.sh" &2; \ + echo " Check network access to the ameba prebuilts release." >&2; \ + exit 1; } + +if BINDIR=$(resolve_bindir); then + publish_bindir "$BINDIR" + echo "ameba-rtos prerequisites ready (prebuilts $PBVER, python dir: $BINDIR)." + exit 0 +fi + +echo "ameba_setup_env.sh: no python carries the SDK tool deps." >&2 +echo " Provide them for the system python3 (the full SDK tool set), e.g.:" >&2 +echo " python3 -m pip install -r $SDK/tools/requirements.txt" >&2 +echo " or 'apt install python3-venv' so env.sh can build the SDK .venv." >&2 +exit 1 diff --git a/arch/arm/src/common/ameba/wifi/ameba_wifi.c b/arch/arm/src/common/ameba/wifi/ameba_wifi.c new file mode 100644 index 00000000000..b4d32ff21ee --- /dev/null +++ b/arch/arm/src/common/ameba/wifi/ameba_wifi.c @@ -0,0 +1,330 @@ +/**************************************************************************** + * arch/arm/src/common/ameba/wifi/ameba_wifi.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * WHC (WiFi Host Controller) host bring-up for the Ameba AP core. + * + * This is the SDK-header side of the WiFi port (compiled with the vendor + * WiFi include set into libameba_wifi.a, NOT through the NuttX CSRCS path -- + * the two header trees collide). It performs the host init sequence the SDK + * runs from its AP main()/wifi_init_thread(), minus everything NuttX already + * owns (clocks, heap, scheduler): + * + * wifi_set_rom2flash(); // remap ROM wifi hooks to flash + * wifi_set_task_size(); // populate g_rtw_task_size + * whc_host_init(); // == whc_ipc_host_init() in IPC mode + * wifi_on(RTW_MODE_STA); // power on the MAC/PHY on the NP + * + * The IPC transport itself (AP<->NP on-chip IPC interrupt + ipc_table_init) + * is wired on the NuttX side in ameba_wifi_init.c, which calls + * ameba_wifi_start from a dedicated task once the scheduler is running. + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "lwip_netconf.h" /* shim (pulled in transitively by headers) */ +#include /* wifi_on, RTW_MODE_STA, RTK_SUCCESS, ... */ +#include /* g_rtw_task_size */ +#include /* rtos_mem_zmalloc / rtos_mem_free */ +#include /* DiagPrintf (SDK swlib) */ + +#include "ameba_wlan.h" /* struct ameba_scan_ap (plain ABI types) */ + +/**************************************************************************** + * Public Function Prototypes (resolved from SDK libs / compiled sources) + ****************************************************************************/ + +extern void wifi_set_rom2flash(void); +extern void wifi_set_task_size(void); /* rtw_task_size.c (compiled) */ +extern void whc_ipc_host_init(void); /* lib_wifi_whc_ap */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ameba_wifi_start + * + * Description: + * Run the AP host WiFi init sequence and power on the radio in STA mode. + * Must be called from task context (wifi_on blocks on the NP round-trip + * over IPC), after ameba_wifi_init.c has brought up the IPC interrupt and + * ipc_table_init(). + * + * Returned Value: + * 0 on success, a negative value on failure. + * + ****************************************************************************/ + +int ameba_wifi_start(void) +{ + int ret; + + DiagPrintf("[ameba-wifi] WHC host bring-up (STA) ...\n"); + + wifi_set_rom2flash(); + wifi_set_task_size(); + + /* The vendor sizes these WHC host tasks for the lwIP model, where the IPC + * message-queue task only hands RX frames to the tcpip mailbox. In this + * NuttX port the same task (whc_msg_q_task) runs the full devif input path + * (ipv4_input/arp_input/...) inline, which overflows the stock ~704-byte + * stack. Enlarge the host tasks here -- before whc_ipc_host_init() + * creates them -- instead of patching the SDK headers. + */ + + if (g_rtw_task_size.ipc_msg_q_task < 4096) + { + g_rtw_task_size.ipc_msg_q_task = 4096; + } + + if (g_rtw_task_size.ipc_blk_api_task < 2048) + { + g_rtw_task_size.ipc_blk_api_task = 2048; + } + + if (g_rtw_task_size.ipc_unblk_api_task < 4096) + { + g_rtw_task_size.ipc_unblk_api_task = 4096; + } + + whc_ipc_host_init(); + + /* Keep the vendor's default power-save (IPS) config: the WHC driver wakes + * the radio automatically on the next host API call, so no special + * override is needed here. + */ + + ret = wifi_on(RTW_MODE_STA); + if (ret != RTK_SUCCESS) + { + DiagPrintf("[ameba-wifi] wifi_on(STA) failed: %d\n", ret); + return -1; + } + + DiagPrintf("[ameba-wifi] wifi_on(STA) ok\n"); + return 0; +} + +/**************************************************************************** + * Name: ameba_wifi_scan_start + * + * Description: + * Run one blocking active scan. Returns the number of APs found + * (>= 0) or a negative value on error. + * + ****************************************************************************/ + +int ameba_wifi_scan_start(void) +{ + struct rtw_scan_param scan_param; + int ret; + + memset(&scan_param, 0, sizeof(scan_param)); + scan_param.options = RTW_SCAN_ACTIVE; + + ret = wifi_scan_networks(&scan_param, 1); + return (ret < RTK_SUCCESS) ? -1 : ret; +} + +/**************************************************************************** + * Name: ameba_wifi_scan_results + * + * Description: + * Copy up to max scan records into the caller's plain ameba_scan_ap array. + * Returns the number copied, or a negative value on error. + * + ****************************************************************************/ + +int ameba_wifi_scan_results(struct ameba_scan_ap *out, int max) +{ + struct rtw_scan_result *list; + u32 ap_num = (u32)max; + u32 i; + int n; + + if (out == NULL || max <= 0) + { + return -1; + } + + list = rtos_mem_zmalloc(ap_num * sizeof(struct rtw_scan_result)); + if (list == NULL) + { + return -1; + } + + if (wifi_get_scan_records(&ap_num, list) < 0) + { + rtos_mem_free(list); + return -1; + } + + for (i = 0, n = 0; i < ap_num && n < max; i++) + { + u8 slen = list[i].ssid.len; + + if (slen > AMEBA_WLAN_SSID_MAXLEN) + { + slen = AMEBA_WLAN_SSID_MAXLEN; + } + + memcpy(out[n].ssid, list[i].ssid.val, slen); + out[n].ssid[slen] = '\0'; + out[n].ssid_len = slen; + memcpy(out[n].bssid, list[i].bssid.octet, 6); + out[n].rssi = list[i].signal_strength; + out[n].channel = (uint8_t)list[i].channel; + out[n].security = (list[i].security == RTW_SECURITY_OPEN) ? 0 : 1; + n++; + } + + rtos_mem_free(list); + return n; +} + +/**************************************************************************** + * Name: ameba_wifi_connect + * + * Description: + * Connect (blocking) to ssid with the given PSK. Empty password => open. + * Returns 0 on success, a negative value on failure. + * + ****************************************************************************/ + +int ameba_wifi_connect(const unsigned char *ssid, int ssid_len, + const unsigned char *pw, int pw_len) +{ + struct rtw_network_info info; + int ret; + + if (ssid == NULL || ssid_len <= 0 || ssid_len > RTW_ESSID_MAX_SIZE) + { + return -1; + } + + memset(&info, 0, sizeof(info)); + info.ssid.len = (u8)ssid_len; + memcpy(info.ssid.val, ssid, ssid_len); + info.channel = 0; /* full scan to find the AP */ + + if (pw != NULL && pw_len > 0) + { + info.password = (u8 *)pw; + info.password_len = pw_len; + info.security_type = RTW_SECURITY_WPA_WPA2_MIXED_PSK; + } + else + { + info.security_type = RTW_SECURITY_OPEN; + } + + DiagPrintf("[ameba-wifi] connecting to \"%s\" ...\n", info.ssid.val); + ret = wifi_connect(&info, 1); + if (ret != RTK_SUCCESS) + { + DiagPrintf("[ameba-wifi] connect failed: %d\n", ret); + return -1; + } + + DiagPrintf("[ameba-wifi] connected\n"); + return 0; +} + +/**************************************************************************** + * Name: ameba_wifi_disconnect + ****************************************************************************/ + +int ameba_wifi_disconnect(void) +{ + return (wifi_disconnect() == RTK_SUCCESS) ? 0 : -1; +} + +/**************************************************************************** + * Name: ameba_wifi_start_ap + * + * Description: + * Start a SoftAP on WiFi interface-1 with the given SSID/PSK/channel. + * An empty (or too-short) password starts an open AP; otherwise WPA2-AES + * PSK is used. wifi_on() has already run (STA mode) in + * ameba_wifi_start(), which the SDK requires before wifi_start_ap(); the + * resulting STA+SoftAP concurrency is harmless when only the AP is used. + * When a STA link is up the SoftAP follows the STA channel (SDK + * behavior), so channel is only a hint for the standalone-AP case. + * Blocks on the NP round-trip, so it must run from task context (it does + * -- driven from the wapi ioctl path). + * + * Returns 0 on success, a negative value on failure. + * + ****************************************************************************/ + +int ameba_wifi_start_ap(const unsigned char *ssid, int ssid_len, + const unsigned char *pw, int pw_len, int channel) +{ + struct rtw_softap_info ap; + int ret; + + if (ssid == NULL || ssid_len <= 0 || ssid_len > RTW_ESSID_MAX_SIZE) + { + return -1; + } + + memset(&ap, 0, sizeof(ap)); + ap.ssid.len = (u8)ssid_len; + memcpy(ap.ssid.val, ssid, ssid_len); + ap.channel = (channel >= 1 && channel <= 165) ? (u8)channel : 1; + + if (pw != NULL && pw_len >= RTW_MIN_PSK_LEN) + { + ap.password = (u8 *)pw; + ap.password_len = (u8)pw_len; + ap.security_type = RTW_SECURITY_WPA2_AES_PSK; + } + else + { + ap.security_type = RTW_SECURITY_OPEN; + } + + DiagPrintf("[ameba-wifi] start AP \"%s\" ch=%d %s ...\n", + ap.ssid.val, ap.channel, + ap.security_type == RTW_SECURITY_OPEN ? "open" : "wpa2"); + + ret = wifi_start_ap(&ap); + if (ret != RTK_SUCCESS) + { + DiagPrintf("[ameba-wifi] wifi_start_ap failed: %d\n", ret); + return -1; + } + + DiagPrintf("[ameba-wifi] SoftAP started\n"); + return 0; +} + +/**************************************************************************** + * Name: ameba_wifi_stop_ap + ****************************************************************************/ + +int ameba_wifi_stop_ap(void) +{ + return (wifi_stop_ap() == RTK_SUCCESS) ? 0 : -1; +} diff --git a/arch/arm/src/common/ameba/wifi/ameba_wifi_depend.c b/arch/arm/src/common/ameba/wifi/ameba_wifi_depend.c new file mode 100644 index 00000000000..00a91470399 --- /dev/null +++ b/arch/arm/src/common/ameba/wifi/ameba_wifi_depend.c @@ -0,0 +1,401 @@ +/**************************************************************************** + * arch/arm/src/common/ameba/wifi/ameba_wifi_depend.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * NuttX backing for the lwIP/event glue that the Realtek WHC host WiFi + * libraries call out to. In the vendor SDK these live in the lwIP netif + * adapter, the rtw_event dispatcher and the rtk_app auto-reconnect / fast- + * connect helpers -- all of which pull in lwIP, wpa_supplicant, p2p and the + * AT-command service. NuttX replaces lwIP with its native BSD network stack + * and does not use those helpers, so they are provided here. + * + * The symbols NuttX does not exercise (lwIP netif up/down, the AT-command + * service, P2P/WPS) are minimal stubs here; the live RX/TX data path and the + * WiFi event indications run through the NuttX netdev (ameba_wlan.c) and the + * SDK's own rtw_event.c dispatcher. + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/* This file sits on the SDK side of the boundary: it is compiled with the + * vendor WiFi include set, NOT the NuttX one (the two header trees collide + * -- e.g. lwIP vs NuttX atomic.h). So it pulls only SDK/shim headers and + * uses the SDK's DiagPrintf (linked from swlib/log.c) for diagnostics rather + * than NuttX syslog. + */ + +#include + +#include "lwip_netconf.h" /* shim: struct pbuf, pbuf_layer/type */ +#include /* u8/u32/s32, struct rtw_network_info */ +#include /* struct internal_block_param */ +#include /* rtos_mem_zmalloc / rtos_mem_free */ +#include /* struct eth_drv_sg */ +#include /* DiagPrintf (SDK swlib) */ + +/* WHC host TX (whc_ipc_host_send, == whc_host_send macro in IPC mode). */ + +extern int whc_ipc_host_send(int idx, struct eth_drv_sg *sg_list, + int sg_len, int total_len, void *raw_para, + u8 is_special_pkt); + +/* NuttX netdev RX entry (ameba_wlan.c) -- raw Ethernet frame into devif. */ + +extern void ameba_wlan_rxframe(int idx, const unsigned char *buf, + unsigned int len); + +/* WHC host join-state globals (defined in lib_wifi_whc_ap). wifi_connect() + * blocks on join_block_param->sema until the join-status event posts it. + */ + +extern u8 rtw_join_status; +extern int join_fail_reason; +extern struct internal_block_param *join_block_param; + +/* Host-side WPA supplicant event handlers (lib_wpa_lite). In the IPC scheme + * the NP does scan/auth/assoc and forwards the PSK/SAE handshake to the host + * via these events; the host supplicant drives the 4-way handshake. We + * dispatch them directly (instead of compiling the heavyweight rtw_event.c). + */ + +/* SET_PSK_INFO */ + +extern void rtw_psk_set_psk_info_evt_hdl(u8 *evt_info); + +/* STA_4WAY_START */ + +extern void rtw_psk_sta_start_4way(u8 *evt_info); + +/* STA_4WAY_RECV */ + +extern void rtw_psk_sta_recv_eapol(u8 *evt_info); + +/* EXTERNAL_AUTH */ + +extern void rtw_sae_sta_start(u8 *evt_info); + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* Packet-buffer glue + data path. + * + * Allocate a packet buffer for the WHC RX copy path. The WHC host RX + * (whc_ipc_host_trx.c, non-SHARE_TO_PBUF mode) does pbuf_alloc(PBUF_RAW, + * len, PBUF_POOL) then memcpy's the frame into pbuf->payload. A single + * contiguous pbuf (struct + payload in one block) covers Ethernet-sized + * frames, so the copy loop runs once and never chains. + */ + +struct pbuf *pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type) +{ + struct pbuf *p; + + (void)layer; + (void)type; + + p = rtos_mem_zmalloc(sizeof(struct pbuf) + length); + if (p == NULL) + { + return NULL; + } + + p->payload = (void *)(p + 1); + p->tot_len = length; + p->len = length; + p->ref = 1; + p->next = NULL; + return p; +} + +void pbuf_free(struct pbuf *p) +{ + if (p != NULL) + { + rtos_mem_free(p); + } +} + +/* RX seam: the WHC host RX path calls this with a received Ethernet frame + * from the NP. Hand the raw bytes to the NuttX netdev (ameba_wlan.c), then + * free the pbuf (we own it -- copy mode). Runs in the WHC host RX task + * context. + */ + +void netif_adapter_wifi_recv_whc(uint8_t idx, struct pbuf *p_buf) +{ + if (p_buf == NULL) + { + return; + } + + ameba_wlan_rxframe(idx, (const unsigned char *)p_buf->payload, + p_buf->tot_len); + pbuf_free(p_buf); +} + +/* TX seam: send one contiguous Ethernet frame to the NP over WHC IPC. + * Called by the NuttX netdev TX path. is_special flags DHCP frames (the NP + * prioritises / does not power-save-defer them, mirroring the SDK lwIP + * adapter). + */ + +int ameba_wifi_txframe(int idx, const void *buf, unsigned int len, + unsigned char is_special) +{ + struct eth_drv_sg sg; + + sg.buf = (unsigned int)(uintptr_t)buf; + sg.len = len; + return whc_ipc_host_send(idx, &sg, 1, (int)len, NULL, is_special); +} + +/* Query the STA MAC address (host API -> NP). Thin wrapper so the NuttX + * netdev can fill dev->d_mac without pulling SDK headers. Referencing + * wifi_get_mac_address here also keeps its real NP implementation (the NP + * noused generator sees it in the NuttX image). Returns 0 on success. + */ + +int ameba_wifi_get_mac(int idx, unsigned char *mac) +{ + struct rtw_mac m; + + if (wifi_get_mac_address(idx, &m, 0) != RTK_SUCCESS) + { + return -1; + } + + mac[0] = m.octet[0]; mac[1] = m.octet[1]; mac[2] = m.octet[2]; + mac[3] = m.octet[3]; mac[4] = m.octet[4]; mac[5] = m.octet[5]; + return 0; +} + +/* Bring the WLAN netif administratively up. In NuttX the netdev + * (ameba_wlan.c) owns interface state, so this is a no-op here. + */ + +void lwip_netif_set_up(uint8_t idx) +{ + (void)idx; +} + +/* Counterpart called from wifi_stop_ap(); netdev state is owned by NuttX. */ + +void lwip_netif_set_down(uint8_t idx) +{ + (void)idx; +} + +/* lwIP netif link hooks that the precompiled lib_wifi_whc_ap.a references + * from wifi_start_ap()/wifi_stop_ap() (built with CONFIG_LWIP_LAYER on). + * NuttX's netdev (ameba_wlan.c) owns carrier via ifup, so these are no-ops. + */ + +void lwip_netif_set_link_up(unsigned char idx) +{ + (void)idx; +} + +void lwip_netif_set_link_down(unsigned char idx) +{ + (void)idx; +} + +/* WiFi event dispatch (wifi_event_init / wifi_indication / + * wifi_event_handle and the per-event handlers) is provided by the SDK's own + * table-driven dispatcher, component/wifi/common/rtw_event.c, which is + * compiled into libameba_wifi.a. Its event_internal_hdl[] table already + * handles JOIN_STATUS (incl. posting join_block_param->sema for a + * synchronous connect), the WPA 4-way handshake, SAE/OWE, etc., and stays in + * sync with the SDK automatically. We no longer hand-maintain a + * wifi_event_handle() switch here. + */ + +/* rtk_app helpers not used by the NuttX port. */ + +s32 wifi_set_autoreconnect(u8 enable) +{ + (void)enable; + return 0; +} + +int wifi_stop_autoreconnect(void) +{ + return 0; +} + +/* Flash key-value store (rt_kv_set/get/delete, used for fast-connect / PMK + * caching) is implemented NuttX-side in ameba_kv.c on top of the littlefs + * data partition -- it cannot live here because this translation unit is + * compiled with the lwIP-colliding SDK include set. + */ + +void rtw_reconn_new_conn(struct rtw_network_info *connect_param) +{ + (void)connect_param; +} + +void wifi_fast_connect_enable(unsigned char enable) +{ + (void)enable; +} + +/* lwIP netif info accessors. + * + * The WHC host libs query the per-interface IP/GW/mask/MAC and netif state + * through these lwIP-named accessors. NuttX's netdev (ameba_wlan.c) owns + * the interface state and IP config, so these return zeroed scratch -- the + * SDK paths that would consume real values are not on the host's data path. + */ + +static u8 g_ameba_ip_scratch[4]; +static u8 g_ameba_mac_scratch[6]; + +u8 *lwip_get_ip(u8 idx) +{ + (void)idx; + return g_ameba_ip_scratch; +} + +u8 *lwip_get_gw(u8 idx) +{ + (void)idx; + return g_ameba_ip_scratch; +} + +u8 *lwip_get_mask(u8 idx) +{ + (void)idx; + return g_ameba_ip_scratch; +} + +u8 *lwip_get_mac(u8 idx) +{ + (void)idx; + return g_ameba_mac_scratch; +} + +u8 lwip_get_ipv6_enabled(void) +{ + return 0; +} + +int lwip_is_valid_ip(int idx, unsigned char *ip_dest) +{ + (void)idx; + (void)ip_dest; + return 0; +} + +void lwip_wlan_set_netif_info(int idx_wlan, void *dev, + unsigned char *dev_addr) +{ + (void)idx_wlan; + (void)dev; + (void)dev_addr; +} + +/* AP-mode netif pointer; STA-only build leaves it NULL (AP path unused). */ + +void *pnetif_ap = NULL; + +/* DHCP server helper (AP only). */ + +int dhcps_ip_in_table_check(void *pnetif, u8 gate, u8 d) +{ + (void)pnetif; + (void)gate; + (void)d; + return 0; +} + +/* atcmd stub + WTN/mesh. + * + * The SDK event handlers (rtw_event.c) emit AT-command status strings via + * at_printf_indicate(). We do not link the AT-command service (it is the + * NP's shell, disabled here), so provide a no-op: the WiFi event path needs + * the symbol, but the indications themselves are unused on the NuttX host. + */ + +void at_printf_indicate(const char *fmt, ...) +{ + (void)fmt; +} + +/* The SDK event source (rtw_event.c) references handlers from subsystems we + * do not link: EAP/802.1X enterprise auth (we do PSK/SAE) and the + * auto-reconnect helper. Their table entries / call sites are reachable + * from the pulled-in rtw_event.o, so the symbols must resolve; the functions + * themselves are never exercised (STA PSK/SAE). Provide no-ops. + * + * (_sscanf_ss is supplied as the genuine SDK implementation, not here: + * RTL8721Dx compiles swlib/sscanf_minimal.c, RTL8720F gets it from the + * whole-archived ROM lib. See the per-board Make.defs.) + */ + +int get_eap_phase(void) +{ + return 0; +} + +void eap_eapol_start_hdl(u8 *evt_info) +{ + (void)evt_info; +} + +void eap_eapol_recvd_hdl(u8 *buf, s32 buf_len) +{ + (void)buf; + (void)buf_len; +} + +void eap_disconnected_hdl(void) +{ +} + +void rtw_reconn_join_status_hdl(u8 *evt_info) +{ + (void)evt_info; +} + +void rtw_reconn_dhcp_status_hdl(u8 *evt_info) +{ + (void)evt_info; +} + +void wtn_rnat_ap_init(u8 enable) +{ + (void)enable; +} + +int wtn_socket_init(u8 enable, u8 rnat_ap_start) +{ + (void)enable; + (void)rnat_ap_start; + return 0; +} + +int wtn_socket_send(u8 *buf, u32 len) +{ + (void)buf; + (void)len; + return 0; +} diff --git a/arch/arm/src/common/ameba/wifi/include/ameba_lwip_off.h b/arch/arm/src/common/ameba/wifi/include/ameba_lwip_off.h new file mode 100644 index 00000000000..ac7aa434ee7 --- /dev/null +++ b/arch/arm/src/common/ameba/wifi/include/ameba_lwip_off.h @@ -0,0 +1,41 @@ +/**************************************************************************** + * arch/arm/src/common/ameba/wifi/include/ameba_lwip_off.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* Force the SDK's CONFIG_LWIP_LAYER OFF for the NuttX-compiled WiFi sources. + * + * NuttX owns the network stack (its native netdev, ameba_wlan.c) -- NOT + * lwIP. The SDK ships with CONFIG_LWIP_LAYER=1 in platform_autoconf.h, + * which makes the SDK event source (component/wifi/common/rtw_event.c) pull + * in the lwIP netif / DHCP-server headers (dhcp/dhcps.h -> ip_addr_t ...) + * and call lwip_netif_set_link_up()/lwip_dhcp_stop() on connect/disconnect. + * None of that applies here, so we compile those rtw_event.c paths out. The + * pieces NuttX DOES need from rtw_event.c (the event dispatch table, the + * WPA/SAE handlers, and posting join_block_param->sema for a synchronous + * connect) are NOT guarded by CONFIG_LWIP_LAYER, so they remain. + * + * This header is force-included (-include) AFTER platform_autoconf.h so the + * #undef overrides the SDK default. The precompiled WHC libs still + * reference the lwip_* accessors (lwip_get_ip ...), which + * ameba_wifi_depend.c defines unconditionally regardless of this switch. + */ + +#undef CONFIG_LWIP_LAYER diff --git a/arch/arm/src/common/ameba/wifi/include/lwip_netconf.h b/arch/arm/src/common/ameba/wifi/include/lwip_netconf.h new file mode 100644 index 00000000000..40bf4d962f8 --- /dev/null +++ b/arch/arm/src/common/ameba/wifi/include/lwip_netconf.h @@ -0,0 +1,190 @@ +/**************************************************************************** + * arch/arm/src/common/ameba/wifi/include/lwip_netconf.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * NuttX port shim for the Realtek WHC host WiFi stack. + * + * The precompiled Realtek wifi host libraries (lib_wifi_whc_ap, ...) and a + * few SDK wifi sources we compile here (rtw_task_size.c, ...) include + * and embed lwIP's pbuf structs BY VALUE, e.g. + * + * struct rtw_pbuf { struct pbuf_custom p; struct sk_buff *skb; + * u8 busy; }; + * + * NuttX provides its own native BSD socket stack, so lwIP is NOT linked. + * This shim therefore supplies ONLY: + * 1. the lwIP struct/enum layouts that cross the precompiled-lib ABI + * boundary (struct pbuf / pbuf_custom and the pbuf_layer/pbuf_type + * enums passed to pbuf_alloc), copied VERBATIM from the pinned SDK's + * component/lwip/lwip_v2.1.2 -- keep in sync if the SDK lwIP version is + * bumped; and + * 2. prototypes of the lwIP-named glue functions that NuttX implements in + * ameba_wifi_depend.c (pbuf_alloc / netif_adapter_wifi_recv_whc / + * lwip_netif_set_up). + * + * It deliberately does NOT include lwip/opt.h or the full lwipconf.h header + * tree -- only the ABI is reproduced, not the lwIP API. + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_COMMON_AMEBA_WIFI_INCLUDE_LWIP_NETCONF_H +#define __ARCH_ARM_SRC_COMMON_AMEBA_WIFI_INCLUDE_LWIP_NETCONF_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* lwIP arch integer types (lwip/arch.h) used by the pbuf layout. */ + +#ifndef LWIP_ARCH_TYPES_DEFINED +#define LWIP_ARCH_TYPES_DEFINED +typedef uint8_t u8_t; +typedef uint16_t u16_t; +typedef uint32_t u32_t; +typedef int8_t s8_t; +typedef int16_t s16_t; +typedef int32_t s32_t; +#endif + +/* lwIP default reference-count width (lwip/opt.h: LWIP_PBUF_REF_T = u8_t). */ + +#define LWIP_PBUF_REF_T u8_t + +/* pbuf_layer header-length constituents. lwIP defaults with ETH_PAD_SIZE 0 + * and IPv6 enabled on this SoC (wifi_api exposes lwip_ipv6_enabled). These + * feed the pbuf_layer enum below; they affect TX headroom only and are not + * consulted on the control-plane path. + */ + +#define PBUF_LINK_ENCAPSULATION_HLEN 0 +#define PBUF_LINK_HLEN 14 +#define PBUF_IP_HLEN 40 +#define PBUF_TRANSPORT_HLEN 20 + +/* pbuf_type bit flags (lwip/pbuf.h). */ + +#define PBUF_TYPE_FLAG_STRUCT_DATA_CONTIGUOUS 0x80 +#define PBUF_TYPE_FLAG_DATA_VOLATILE 0x40 +#define PBUF_TYPE_ALLOC_SRC_MASK 0x0F +#define PBUF_ALLOC_FLAG_RX 0x0100 +#define PBUF_ALLOC_FLAG_DATA_CONTIGUOUS 0x0200 +#define PBUF_TYPE_ALLOC_SRC_MASK_STD_HEAP 0x00 +#define PBUF_TYPE_ALLOC_SRC_MASK_STD_MEMP_PBUF 0x01 +#define PBUF_TYPE_ALLOC_SRC_MASK_STD_MEMP_PBUF_POOL 0x02 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Enumeration of pbuf layers (lwip/pbuf.h) -- exact values preserved so the + * layer hint passed by the precompiled libs is interpreted identically. + */ + +typedef enum +{ + PBUF_TRANSPORT = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN, + PBUF_IP = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + + PBUF_IP_HLEN, + PBUF_LINK = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN, + PBUF_RAW_TX = PBUF_LINK_ENCAPSULATION_HLEN, + PBUF_RAW = 0 +} pbuf_layer; + +/* Enumeration of pbuf types (lwip/pbuf.h) -- exact values preserved. */ + +typedef enum +{ + PBUF_RAM = (PBUF_ALLOC_FLAG_DATA_CONTIGUOUS | + PBUF_TYPE_FLAG_STRUCT_DATA_CONTIGUOUS | + PBUF_TYPE_ALLOC_SRC_MASK_STD_HEAP), + PBUF_ROM = PBUF_TYPE_ALLOC_SRC_MASK_STD_MEMP_PBUF, + PBUF_REF = (PBUF_TYPE_FLAG_DATA_VOLATILE | + PBUF_TYPE_ALLOC_SRC_MASK_STD_MEMP_PBUF), + PBUF_POOL = (PBUF_ALLOC_FLAG_RX | + PBUF_TYPE_FLAG_STRUCT_DATA_CONTIGUOUS | + PBUF_TYPE_ALLOC_SRC_MASK_STD_MEMP_PBUF_POOL) +} pbuf_type; + +/* struct pbuf / pbuf_custom -- layout copied verbatim from lwip/pbuf.h of + * the pinned SDK. Embedded by value in struct rtw_pbuf, so the layout MUST + * match. + */ + +struct pbuf +{ + struct pbuf *next; /* next pbuf in singly linked chain */ + void *payload; /* pointer to the actual data in the buffer */ + u16_t tot_len; /* total length of this + all next buffers */ + u16_t len; /* length of this buffer */ + u8_t type_internal; /* pbuf type and allocation source flags */ + u8_t flags; /* misc flags */ + LWIP_PBUF_REF_T ref; /* reference count */ + u8_t if_idx; /* input netif's index (incoming packets) */ +}; + +typedef void (*pbuf_free_custom_fn)(struct pbuf *p); + +struct pbuf_custom +{ + struct pbuf pbuf; /* the actual pbuf */ + pbuf_free_custom_fn custom_free_function; /* called by pbuf_free */ +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* lwIP-named glue implemented by NuttX in ameba_wifi_depend.c. */ + +struct pbuf *pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type); +void pbuf_free(struct pbuf *p); + +/* STA netif index -- only passed to the no-op lwIP link/dhcp glue below, so + * the value is immaterial (the SDK enum has it = STA_WLAN_INDEX = 0). + */ + +#ifndef NETIF_WLAN_STA_INDEX +#define NETIF_WLAN_STA_INDEX 0 +#endif + +/* lwIP netif link hooks referenced by the precompiled lib_wifi_whc_ap.a + * (wifi_start_ap/wifi_stop_ap, built with CONFIG_LWIP_LAYER on). NuttX's + * netdev (ameba_wlan.c) owns carrier via ifup, so these are no-ops + * (ameba_wifi_depend.c) -- they exist only to satisfy the link. + */ + +void lwip_netif_set_link_up(unsigned char idx); +void lwip_netif_set_link_down(unsigned char idx); + +#ifdef __cplusplus +} +#endif + +#endif /* __ARCH_ARM_SRC_COMMON_AMEBA_WIFI_INCLUDE_LWIP_NETCONF_H */ diff --git a/arch/arm/src/rtl8720f/CMakeLists.txt b/arch/arm/src/rtl8720f/CMakeLists.txt new file mode 100644 index 00000000000..f80b1a8f18f --- /dev/null +++ b/arch/arm/src/rtl8720f/CMakeLists.txt @@ -0,0 +1,44 @@ +# ############################################################################## +# arch/arm/src/rtl8720f/CMakeLists.txt +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more contributor +# license agreements. See the NOTICE file distributed with this work for +# additional information regarding copyright ownership. The ASF licenses this +# file to you under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +# +# ############################################################################## + +# IC-specific register drivers + IPC wiring live here; IC-agnostic glue is +# shared from arch/arm/src/common/ameba. +set(SRCS ameba_allocateheap.c ameba_irq.c ameba_loguart.c ameba_start.c + ameba_timerisr.c) + +set(AMEBA_COMMON ${CMAKE_CURRENT_LIST_DIR}/../common/ameba) + +list(APPEND SRCS ${AMEBA_COMMON}/ameba_os_wrap.c) + +if(CONFIG_RTL8720F_WIFI) + list(APPEND SRCS ameba_wifi_init.c ${AMEBA_COMMON}/ameba_kv.c) + if(CONFIG_NET) + list(APPEND SRCS ${AMEBA_COMMON}/ameba_wlan.c) + endif() +endif() + +if(CONFIG_RTL8720F_FLASH_FS) + list(APPEND SRCS ${AMEBA_COMMON}/ameba_flash_mtd.c) +endif() + +target_include_directories(arch PRIVATE ${AMEBA_COMMON}) +target_sources(arch PRIVATE ${SRCS}) diff --git a/arch/arm/src/rtl8720f/Kconfig b/arch/arm/src/rtl8720f/Kconfig new file mode 100644 index 00000000000..0b9d3d65baf --- /dev/null +++ b/arch/arm/src/rtl8720f/Kconfig @@ -0,0 +1,85 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +if ARCH_CHIP_RTL8720F + +menu "RTL8720F Chip Selection" + +config RTL8720F_KM4 + bool + default y + ---help--- + The Realtek RTL8720F KM4 application core + (ARMv8-M.main / Cortex-M33). + +endmenu # RTL8720F Chip Selection + +menu "RTL8720F Bring-up Options" + +config RTL8720F_HEAP_SIZE + hex "NuttX reserved heap size (bytes)" + default 0x10000 + ---help--- + During bring-up NuttX runs as a guest on the Realtek SDK image and + must not touch RAM that the SDK owns. Instead of claiming all SRAM + from the end of NuttX's BSS to the end of memory (which overlaps the + SDK heap), NuttX uses a self-contained, statically reserved heap of + this size placed in NuttX's own .bss. up_allocate_heap() returns + this buffer. Keep it within the 288KB KM4 SRAM budget after NuttX + text/data/bss. + +config RTL8720F_LOGUART_RXBUFSIZE + int "LOG-UART console RX buffer size" + default 256 + ---help--- + Size of the NuttX receive buffer for the LOG-UART console. + +config RTL8720F_LOGUART_TXBUFSIZE + int "LOG-UART console TX buffer size" + default 256 + ---help--- + Size of the NuttX transmit buffer for the LOG-UART console. + +endmenu # RTL8720F Bring-up Options + +menu "RTL8720F WiFi" + +config RTL8720F_WIFI + bool "WiFi (WHC host) support" + default n + ---help--- + Link the Realtek WHC (WiFi Host Controller) host stack so the AP can + drive the WiFi MAC/PHY that runs on the NP network processor. The + AP-side host WiFi control libraries (lib_wifi_whc_ap and friends) + are linked from the pinned SDK; the lwIP / event glue they expect is + provided by NuttX (arch/arm/src/common/ameba/wifi/), routing frames + into NuttX's native network stack instead of lwIP. + + M3.1 brings up the control plane only (wifi_on + scan); the data + path and netdev/wireless-extension wiring follow. + +endmenu # RTL8720F WiFi + +menu "RTL8720F Storage" + +config RTL8720F_FLASH_FS + bool "On-chip SPI NOR data filesystem (littlefs)" + default n + select MTD + select MTD_BYTE_WRITE + select FS_LITTLEFS + ---help--- + Expose the SDK "VFS1" data partition (the last 128 KiB of the + on-chip SPI NOR flash, which does not overlap the NP/AP firmware + images) as a NuttX MTD device and mount a littlefs filesystem on it + at /data. This provides persistent storage for application data and + backs the WiFi fast-connect / PMK key-value store (rt_kv_*). + + The MTD backend wraps the SDK's dual-core-locked FLASH_xxx flash + primitives (ameba_flash_mtd.c). + +endmenu # RTL8720F Storage + +endif # ARCH_CHIP_RTL8720F diff --git a/arch/arm/src/rtl8720f/Make.defs b/arch/arm/src/rtl8720f/Make.defs new file mode 100644 index 00000000000..9d4de5be0f1 --- /dev/null +++ b/arch/arm/src/rtl8720f/Make.defs @@ -0,0 +1,217 @@ +############################################################################ +# arch/arm/src/rtl8720f/Make.defs +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include armv8-m/Make.defs + +# IC-agnostic Ameba glue (os_wrapper backend, netdev, KV, flash MTD, ...) is +# shared by every ameba ARM chip from arch/arm/src/common/ameba/. Put it on +# VPATH + the include path so the CHIP_CSRCS filenames below resolve there +# (single source, no per-IC duplication). Truly IC-specific files (register +# drivers, IPC wiring, chip.h) stay in this chip directory. + +AMEBA_COMMON_SRC = $(TOPDIR)$(DELIM)arch$(DELIM)arm$(DELIM)src$(DELIM)common$(DELIM)ameba +VPATH += common$(DELIM)ameba +INCLUDES += ${INCDIR_PREFIX}$(AMEBA_COMMON_SRC) + +CHIP_CSRCS = ameba_start.c ameba_loguart.c ameba_irq.c ameba_timerisr.c +CHIP_CSRCS += ameba_allocateheap.c +CHIP_CSRCS += ameba_os_wrap.c + +# km4tz<->km4ns IPC bring-up. Needed by the SDK flash erase/program path +# (inter-core XIP pause) AND by WiFi, so compile it whenever either is enabled. +ifneq ($(CONFIG_RTL8720F_WIFI)$(CONFIG_RTL8720F_FLASH_FS),) +CHIP_CSRCS += ameba_ipc.c +endif + +ifeq ($(CONFIG_RTL8720F_WIFI),y) +CHIP_CSRCS += ameba_wifi_init.c +# rt_kv_* symbols are referenced by the WHC host WiFi libraries -- always +# provide them (backed by the data filesystem, or stubbed if it is disabled). +CHIP_CSRCS += ameba_kv.c +ifeq ($(CONFIG_NET),y) +CHIP_CSRCS += ameba_wlan.c +endif +endif + +ifeq ($(CONFIG_RTL8720F_FLASH_FS),y) +CHIP_CSRCS += ameba_flash_mtd.c +endif + +############################################################################ +# Realtek RTL8720F SDK integration +# +# Direction A (vendored-SDK model): NuttX owns the AP image2 and is the +# *primary* linker. The reduced image2 link reuses the vendor SDK chip +# libraries + ROM symbols + linker scripts; FreeRTOS / lwIP / mbedTLS / +# WiFi / BT / file-system / at_cmd / ota are all dropped (NuttX provides its +# own). This folds the prototype scripts (nuttx-ameba-ext/link_img2.sh and +# package_app.sh) into NuttX's native build: the linked `nuttx` ELF *is* the +# AP (km4tz) image2 .axf, and POSTBUILD (board scripts/Make.defs) packages it +# into a flashable app.bin. +# +# The vendor SDK (ameba-rtos) is treated as a referenced 3rd-party checkout: +# its sources, ROM symbol files and linker scripts are referenced at build time +# and never committed to NuttX. The pre-compiled chip archives + the build +# staging area are kept under boards/arm/rtl8720f/rtl8720f_evb/prebuilt/ +# (gitignored, not part of the NuttX source tree, as vendor blobs are kept +# out of NuttX). +############################################################################ + +# This IC (RTL8720F) maps to the SDK's RTL8720F SoC subtree. Set before +# including the shared locator so future chips can reuse the one SDK checkout +# by selecting their own AMEBA_SOC_NAME. + +AMEBA_SOC_NAME = RTL8720F + +# Locate (and, when unset, auto-fetch) the one shared ameba-rtos SDK. Shared +# with the board's scripts/Make.defs via common/ameba/ameba_sdk.mk so both make +# instances resolve $(AMEBA_SDK) identically. See that file for the two modes. + +include $(TOPDIR)$(DELIM)arch$(DELIM)arm$(DELIM)src$(DELIM)common$(DELIM)ameba$(DELIM)ameba_sdk.mk + +# SDK sub-trees referenced by the image2 link. + +# NOTE (8720F vs amebadplus): the AP/host core is km4tz (TrustZone secure) on +# RTL8720F, vs km4 on amebadplus. So the application-core project subtree is +# project_km4tz (NP/device core is km4ns, the prebuilt-blob core -- analogous +# to amebadplus's km0). +AMEBA_SOC = $(AMEBA_SDK)/component/soc/$(AMEBA_SOC_NAME) +AMEBA_PROJ = $(AMEBA_SOC)/project +AMEBA_KM4_PROJ = $(AMEBA_PROJ)/project_km4tz +AMEBA_SOC_LIB = $(AMEBA_KM4_PROJ)/lib/soc + +# Vendored prebuilt area inside the board (gitignored vendor blobs). + +AMEBA_PREBUILT = $(BOARD_DIR)$(DELIM)prebuilt +AMEBA_PREBUILT_LIBS = $(AMEBA_PREBUILT)$(DELIM)libs + +# --- Pre-compiled chip libraries kept in the reduced image2 ---------------- +# +# Vendor chip archives produced by a full SDK build, vendored under +# prebuilt/libs/. The chipinfo / pmc soc archives ship pre-compiled inside the +# SDK source tree, so they are taken directly from $(AMEBA_SDK). These are +# normal archives (members pulled on demand) and are appended to EXTRA_LIBS so +# they sit inside NuttX's standard --start-group/--end-group, resolving against +# each other and the NuttX libs. Everything unreferenced is dropped by +# --gc-sections, so listing an archive only costs link time, not image size. +# +# NOTE: the mbed-style "hal" layer (serial_api/gpio_api/...) is intentionally +# NOT linked -- NuttX provides its own uart_ops/ioexpander drivers, so the SDK +# hal is dead weight here (it contributed 0 objects). NuttX drivers sit +# directly on the fwlib register layer instead. + +# fwlib register-layer objects NuttX actually uses are compiled FROM SDK SOURCE +# into libameba_fwlib.a by the board PREBUILD (see scripts/Make.defs: +# AMEBA_FWLIB_SRCS), not vendored as a prebuilt blob -- so a bare checkout that +# only auto-fetched the SDK source can still link. --gc-sections keeps only the +# referenced members. Add fwlib sources there as new drivers need them. +EXTRA_LIBS += $(AMEBA_PREBUILT_LIBS)$(DELIM)libameba_fwlib.a + +# chipinfo / pmc ship pre-compiled INSIDE the SDK source tree (lib/soc), so a +# fresh SDK clone already has them -- linked directly from $(AMEBA_SDK), no +# vendored blob needed. (0 members pulled today, but kept for chip-init use.) +EXTRA_LIBS += $(AMEBA_SOC_LIB)$(DELIM)lib_chipinfo.a +EXTRA_LIBS += $(AMEBA_SOC_LIB)$(DELIM)lib_pmc.a + +# --- WiFi (WHC host) chip libraries (CONFIG_RTL8720F_WIFI) ----------------- +# +# KM4-side host WiFi control libs from the pinned SDK. STA-PSK reduced set: +# the host controller (whc_ap), rtk_app helpers, security/crypto, the WPA-lite +# supplicant and coexistence -- eap/p2p/wps are NOT linked. The lwIP / event +# glue these expect is supplied by NuttX in libameba_wifi.a (built from a few +# SDK config sources + arch/.../wifi/ameba_wifi_depend.c by the board PREBUILD). +# Everything unreferenced is dropped by --gc-sections; all of these sit inside +# NuttX's --start-group so they resolve against each other and the NuttX libs. + +ifeq ($(CONFIG_RTL8720F_WIFI),y) +AMEBA_APP_LIB = $(AMEBA_KM4_PROJ)/lib/application +EXTRA_LIBS += $(AMEBA_APP_LIB)$(DELIM)lib_wifi_whc_ap.a +EXTRA_LIBS += $(AMEBA_APP_LIB)$(DELIM)lib_wifi_rtk_app.a +EXTRA_LIBS += $(AMEBA_APP_LIB)$(DELIM)lib_wifi_com_sec.a +EXTRA_LIBS += $(AMEBA_APP_LIB)$(DELIM)lib_wpa_lite.a +# NOTE: unlike RTL8721Dx (where lib_coex.a is an AP-side lib), on RTL8720F the +# WiFi/BT coexistence lib lives on the NP (km4ns/lib/application/lib_coex.a) and +# is linked into the NP prebuilt image -- the AP (NuttX host) must NOT link it. +EXTRA_LIBS += $(AMEBA_PREBUILT_LIBS)$(DELIM)libameba_wifi.a +endif + +# crtbegin.o / crtend.o (asdk gcc runtime) and -lm / -lstdc++ from the SDK +# image2 link rule. crtbegin/crtend must be positional objects, so they are +# added via EXTRA_LIBS (which the link rule places inside the group, after the +# archives); the C++ / math libs are name-spec'd through EXTRA_LIBS too. + +CRT_DIR := $(dir $(shell $(CC) $(ARCHCPUFLAGS) -print-file-name=crtbegin.o)) + +EXTRA_LIBS += $(CRT_DIR)crtbegin.o +EXTRA_LIBS += $(CRT_DIR)crtend.o + +# --- Link flags reproducing link_img2.sh ----------------------------------- +# +# -u/-e app_start : force-pull the SDK's app_start object (runs silicon +# init then calls NuttX's main()); NuttX provides the +# Img2EntryFun0 entry descriptor pointing at it. +# --gc-sections : drop everything unreferenced (this is what removes +# FreeRTOS / lwIP / mbedTLS members of the chip libs). +# --defsym aliases : map NuttX's _sbss/_ebss/_sdata/_edata/_eronly onto +# the SDK linker-script symbols (the SDK ld owns the +# section layout). +# --no-enum-size-warning / --warn-common / --build-id=none / --cref: match the +# SDK link rule. + +LDFLAGS += -u app_start +LDFLAGS += -e app_start +LDFLAGS += --gc-sections + +# ROM library (rom_common/*.c incl. ameba_systimer_rom.c -> SYSTIMER_Init, etc., +# real code running from XIP/RAM). The SDK links it whole-archived so its fixed +# .romlib.bss is fully populated (the SDK __romlib_bss_end__ ASSERT depends on +# it). TrustZone is off in this config -> lib_rom.a (else lib_rom_tz.a). +# --gc-sections still drops the unreferenced ROM .text afterwards. +LDFLAGS += --whole-archive $(AMEBA_SOC_LIB)$(DELIM)lib_rom.a --no-whole-archive +LDFLAGS += --no-enum-size-warning +LDFLAGS += --warn-common +LDFLAGS += --build-id=none +LDFLAGS += --cref +LDFLAGS += --defsym=_sbss=__bss_start__ +LDFLAGS += --defsym=_ebss=__bss_end__ +LDFLAGS += --defsym=_sdata=__sram_image2_start__ +LDFLAGS += --defsym=_edata=__sram_image2_start__ +LDFLAGS += --defsym=_eronly=__sram_image2_start__ + +# Emit a fresh map next to the ELF for verification (mirrors text.map). + +LDFLAGS += -Map=$(TOPDIR)$(DELIM)nuttx.map + +# -lm / -lstdc++ are name-spec libs: add them through LIBPATHS/EXTRA_LIBS so the +# linker pulls libstdc++ (C++ static-init support that crtbegin/crtend expect) +# and libm. They go last in the group via EXTRA_LIBS ordering above is fine +# because they are searched as archives. + +LDLIBS += -lm -lstdc++ + +# --- Auto-fetched SDK: intentionally NOT removed on distclean -------------- +# +# sdk.mk clones the pinned ameba-rtos into arch/arm/src/common/ameba/ameba-rtos +# (gitignored) when AMEBA_SDK is unset. It is a cache shared by all ameba ICs, +# NOT a build artifact, so it must SURVIVE `make distclean`: switching ICs does +# distclean + reconfigure + build, and re-cloning the multi-GB SDK every time is +# unacceptable. A pristine reset is a manual `rm -rf` of the checkout. diff --git a/arch/arm/src/rtl8720f/ameba_allocateheap.c b/arch/arm/src/rtl8720f/ameba_allocateheap.c new file mode 100644 index 00000000000..7204d030813 --- /dev/null +++ b/arch/arm/src/rtl8720f/ameba_allocateheap.c @@ -0,0 +1,141 @@ +/**************************************************************************** + * arch/arm/src/rtl8720f/ameba_allocateheap.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "arm_internal.h" +#include "chip.h" +#include "hardware/ameba_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Terminology. + * In the flat build (CONFIG_BUILD_FLAT=y), there is only a single heap + * accessed with the standard allocations (malloc/free). This heap is + * referred to as the user heap. Only the flat build with a single SRAM + * region is supported on the RTL8720F. + */ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* NuttX heap = all remaining KM4 on-chip SRAM. + * + * The KM4 image2 linker script (ameba_img2_all.ld) lays out this region for + * us: __bdram_heap_buffer_start__ is the first byte after NuttX's .bss, and + * __bdram_heap_buffer_size__ is an ABSOLUTE symbol whose VALUE is the number + * of bytes from there to the end of the KM4 SRAM region + * (__km4_bd_ram_end__). Using these gives NuttX every SRAM byte the SDK did + * not reserve, instead of a fixed compile-time buffer, and tracks the + * chip/board RAM automatically. + * + * Boards with PSRAM can add it as a second region via arm_addregion() using + * __psram_heap_buffer_start__/__psram_heap_buffer_size__ (zero on + * PKE8721DAF, which has no PSRAM). + */ + +extern uint8_t __bdram_heap_buffer_start__[]; +extern uint8_t __bdram_heap_buffer_size__[]; /* ABS symbol: value == bytes */ + +#define NUTTX_HEAP_BASE ((void *)__bdram_heap_buffer_start__) +#define NUTTX_HEAP_SIZE ((size_t)((uintptr_t)__bdram_heap_buffer_size__)) + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_allocate_heap + * + * Description: + * This function will be called to dynamically set aside the heap region. + * + * For the flat build, this returns the location and size of the single + * heap: all KM4 SRAM remaining after NuttX's .data/.bss, as computed by + * the SDK linker script. + * + ****************************************************************************/ + +void up_allocate_heap(void **heap_start, size_t *heap_size) +{ + *heap_start = NUTTX_HEAP_BASE; + *heap_size = NUTTX_HEAP_SIZE; + +#if defined(CONFIG_MM_KERNEL_HEAP) + *heap_size -= CONFIG_MM_KERNEL_HEAPSIZE; +#endif +} + +/**************************************************************************** + * Name: up_allocate_kheap + * + * Description: + * For the kernel build (CONFIG_BUILD_PROTECTED/KERNEL=y) with both kernel- + * and user-space heaps (CONFIG_MM_KERNEL_HEAP=y), this function allocates + * the kernel-space heap. + * + ****************************************************************************/ + +#if defined(CONFIG_MM_KERNEL_HEAP) +void up_allocate_kheap(void **heap_start, size_t *heap_size) +{ + /* Carve the kernel heap off the top of the SRAM heap region. */ + + *heap_start = (void *)((uintptr_t)NUTTX_HEAP_BASE + + (NUTTX_HEAP_SIZE - CONFIG_MM_KERNEL_HEAPSIZE)); + *heap_size = CONFIG_MM_KERNEL_HEAPSIZE; +} +#endif + +/**************************************************************************** + * Name: arm_addregion + * + * Description: + * Memory may be added in non-contiguous chunks. Additional chunks are + * added by calling this function. + * + ****************************************************************************/ + +#if CONFIG_MM_REGIONS > 1 +void arm_addregion(void) +{ +} +#endif diff --git a/arch/arm/src/rtl8720f/ameba_app_start.c b/arch/arm/src/rtl8720f/ameba_app_start.c new file mode 100644 index 00000000000..82feb457183 --- /dev/null +++ b/arch/arm/src/rtl8720f/ameba_app_start.c @@ -0,0 +1,274 @@ +/**************************************************************************** + * arch/arm/src/rtl8720f/ameba_app_start.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * NuttX-owned image2 entry for the RTL8720F km4tz application core. + * + * This is a NuttX adaptation of the Realtek SDK's app_start() + * (component/soc/RTL8720F/fwlib/ram_km4tz/ameba_app_start.c). It runs the + * same OS-independent silicon init the SDK boot performs -- enable cache, + * clear image2 BSS, set the log level, data-flash high-speed setup, OSC + * calibration, the system timer, pin-mux and MPU, then call NuttX's main(). + * The SDK FreeRTOS/newlib bring-up and its fault-backtrace patch are + * intentionally omitted; NuttX provides its own scheduler, libc and crash + * reporting. + * + * Owning this file (not patching the SDK ameba_app_start.c) keeps the + * vendor SDK pristine. It is compiled with the SDK fwlib include set (see + * the board AMEBA_FWLIB_SRCS), not the NuttX header set. The image2 entry + * uses a NULL ram_wakeup so the SDK deep-sleep (SOCPS) wake path is not + * pulled into the image. + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "ameba_soc.h" +#include "os_wrapper.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const char *TAG = "APP"; + +/**************************************************************************** + * External Function Prototypes + ****************************************************************************/ + +extern int main(void); + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +u32 app_mpu_nocache_check(u32 mem_addr) +{ + mpu_region_config mpu_cfg; + + mpu_cfg.region_base = (uint32_t)__ram_nocache_start__; + mpu_cfg.region_size = __ram_nocache_end__ - __ram_nocache_start__; + + if ((mem_addr >= mpu_cfg.region_base) && + (mem_addr < (mpu_cfg.region_base + mpu_cfg.region_size))) + { + return TRUE; + } + else + { + return FALSE; + } +} + +/* AP has 8 secure mpu entries & 8 non-secure mpu entries. */ + +u32 app_mpu_nocache_init(void) +{ + mpu_region_config mpu_cfg; + u32 mpu_entry = 0; + + /* ROM code inside the CPU does not enter cache; set it RO so a NULL-ptr + * access faults. + */ + + mpu_entry = mpu_entry_alloc(); + mpu_cfg.region_base = 0x20000; + mpu_cfg.region_size = 0x18000; + mpu_cfg.xn = MPU_EXEC_ALLOW; + mpu_cfg.ap = MPU_UN_PRIV_RO; + mpu_cfg.sh = MPU_NON_SHAREABLE; + mpu_cfg.attr_idx = MPU_MEM_ATTR_IDX_NC; + mpu_region_cfg(mpu_entry, &mpu_cfg); + + /* nocache region */ + + mpu_entry = mpu_entry_alloc(); + mpu_cfg.region_base = (uint32_t)__ram_nocache_start__; + mpu_cfg.region_size = __ram_nocache_end__ - __ram_nocache_start__; + mpu_cfg.xn = MPU_EXEC_ALLOW; + mpu_cfg.ap = MPU_UN_PRIV_RW; + mpu_cfg.sh = MPU_NON_SHAREABLE; + mpu_cfg.attr_idx = MPU_MEM_ATTR_IDX_NC; + if (mpu_cfg.region_size >= 32) + { + mpu_region_cfg(mpu_entry, &mpu_cfg); + } + + /* set global bss to nocache */ + + DCache_CleanInvalidate((u32)__global_bss_start__, + (u32)(__global_bss_end__ - __global_bss_start__)); + mpu_entry = mpu_entry_alloc(); + mpu_cfg.region_base = (uint32_t)__global_bss_start__; + mpu_cfg.region_size = __global_bss_end__ - __global_bss_start__; + mpu_cfg.xn = MPU_EXEC_ALLOW; + mpu_cfg.ap = MPU_UN_PRIV_RW; + mpu_cfg.sh = MPU_NON_SHAREABLE; + mpu_cfg.attr_idx = MPU_MEM_ATTR_IDX_NC; + if (mpu_cfg.region_size >= 32) + { + mpu_region_cfg(mpu_entry, &mpu_cfg); + } + + /* nocache region */ + + mpu_entry = mpu_entry_alloc(); + mpu_cfg.region_base = (uint32_t)__sram_image2_start__; + mpu_cfg.region_size = N_BYTE_ALIGMENT(((u32)__sram_image2_end__ - + (u32)__sram_image2_start__), 32); + mpu_cfg.xn = MPU_EXEC_ALLOW; + mpu_cfg.ap = MPU_UN_PRIV_RW; + mpu_cfg.sh = MPU_NON_SHAREABLE; + mpu_cfg.attr_idx = MPU_MEM_ATTR_IDX_NC; + if (mpu_cfg.region_size >= 32) + { + mpu_region_cfg(mpu_entry, &mpu_cfg); + } + + return 0; +} + +#if defined(__GNUC__) +/* Provided for C++ support so the toolchain init does not fail to link. */ + +void _init(void) +{ +} +#endif + +void app_testmode_status(void) +{ + /* OTPC and SIC share one master port; OTPC uses it by default and SIC can + * use it once OTPC autoload is done. + */ + + if (SYSCFG_TRP_TestMode()) + { + if (SYSCFG_TRP_OTPBYP()) + { + RTK_LOGI(TAG, "Bypass OTP autoload\r\n"); + } + else + { + RTK_LOGI(TAG, "In Test mode: 0x%lx\r\n", SYSCFG_TRP_ICFG()); + } + } +} + +void app_init_debug_flag(void) +{ + /* Initialise the log level used by the ROM-code global variable. */ + + if (SYSCFG_OTP_DisBootLog() == FALSE) + { + rtk_log_level_set("*", RTK_LOG_INFO); + } + else + { + rtk_log_level_set("*", RTK_LOG_ERROR); + } +} + +void os_init(void) +{ +#ifdef CONFIG_PSRAM_ALL_FOR_AP_HEAP +#if (defined CONFIG_WHC_HOST || defined CONFIG_WHC_NONE) + extern bool os_heap_add(u8 *start_addr, size_t heap_size); + if (ChipInfo_PsramExists()) + { + os_heap_add((uint8_t *)__km4tz_bd_psram_start__, + (size_t)(__non_secure_psram_end__ - + __km4tz_bd_psram_start__)); + } + +#endif +#endif + rtos_mem_init(); +} + +/* The image2 application entry point. */ + +void app_start(void) +{ + /* Enable the non-secure cache. */ + + Cache_Enable(ENABLE); + + /* Clear the image2 BSS (covers NuttX's .bss too). */ + + _memset((void *)__bss_start__, 0, (__bss_end__ - __bss_start__)); + + app_init_debug_flag(); + +#ifdef CONFIG_TRUSTZONE + PutChar = (void (*)(char))LOGUART_PutChar; + SCB->VTOR = (u32)RomVectorTable; + RomVectorTable[0] = (HAL_VECTOR_FUN)MSP_RAM_HP_NS; +#endif + + app_testmode_status(); + + data_flash_highspeed_setup(); + + SystemCoreClockUpdate(); + RTK_LOGI(TAG, "AP CPU CLK: %lu Hz \n", SystemCoreClock); + + /* Heap region setup (a no-op under NuttX, which owns its own heap). */ + + os_init(); + + if (SYSCFG_CHIPType_Get() == CHIP_TYPE_ASIC) + { + /* Only ASIC needs OSC calibration. */ + + OSC2M_Calibration(30000); + } + + SYSTIMER_Init(); + + /* Low-power pins do not need pinmap init again after wake from dslp. */ + + pinmap_init(); + + mpu_init(); + app_mpu_nocache_init(); + + main(); +} + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* Image2 entry descriptor: the SDK bootloader (image1) jumps to ram_start. + * A NULL ram_wakeup keeps the SDK deep-sleep (SOCPS) wake path -- which the + * SDK's own descriptor wires to SOCPS_WakeFromPG_AP -- out of the image. + */ + +IMAGE2_ENTRY_SECTION +RAM_START_FUNCTION Img2EntryFun0 = +{ + app_start, + NULL, + (u32)RomVectorTable +}; diff --git a/arch/arm/src/rtl8720f/ameba_board.mk b/arch/arm/src/rtl8720f/ameba_board.mk new file mode 100644 index 00000000000..bb01a0d4d91 --- /dev/null +++ b/arch/arm/src/rtl8720f/ameba_board.mk @@ -0,0 +1,418 @@ +############################################################################ +# arch/arm/src/rtl8720f/ameba_board.mk +# +# Shared board-build definitions for the RTL8720F (Ameba WHC) -- the SDK +# include sets, fwlib/WiFi source lists, image2 linker-script generation, +# PREBUILD and POSTBUILD. A board's scripts/Make.defs is a thin wrapper that +# just `include`s this file, so every RTL8720F board shares one definition +# (and a second board on this IC needs no copy). Board-specific paths come +# from $(BOARD_DIR), so each board keeps its own prebuilt/ staging dir. +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include $(TOPDIR)/.config +include $(TOPDIR)/tools/Config.mk + +# Resolve (and, when AMEBA_SDK is unset, auto-fetch) the one shared ameba-rtos +# SDK, and prepend the SDK-matched asdk toolchain to PATH. This MUST precede +# Toolchain.defs: that file probes the compiler version to compute flags (e.g. +# --param=min-pagesize=0 on newer GCC), so the SDK toolchain has to be on PATH +# first or the flags get computed for the wrong compiler. AMEBA_SOC_NAME +# selects this IC's SoC subtree. + +AMEBA_SOC_NAME = RTL8720F +include $(TOPDIR)/arch/arm/src/common/ameba/ameba_sdk.mk + +include $(TOPDIR)/arch/arm/src/armv8-m/Toolchain.defs + +############################################################################ +# Linker script +# +# The `nuttx` ELF must be linked as the Realtek KM4 image2 .axf, so the link +# uses the *SDK's own* layout + image2 + ROM-symbol linker scripts (exactly as +# the prototype link_img2.sh did): +# +# ameba_layout.ld (included by ameba_img2_all.ld) +# ameba_img2_all.ld +# ameba_rom_symbol_acut_s.ld (CONFIG_LINK_ROM_SYMB) +# +# ameba_img2_all.ld is C-preprocessed (it #includes ameba_layout.ld and the +# generated platform_autoconf.h), then ameba_rom_symbol_acut_s.ld is appended. +# Finally NuttX's own .vectors orphan section is folded into the loadable SRAM +# data region so the (large power-of-two aligned) vector table does not land in +# and overflow the tiny fixed KM4_IMG2_ENTRY region. This reproduces the +# generated rlx8721d.ld byte-for-byte without editing any SDK source file +# (the SDK tree stays read-only). +# +# The combined script is generated into scripts/ as ld.script and used as the +# single ARCHSCRIPT. ld.script content is already fully expanded (no macros, +# no #include), so the standard ARCHSCRIPT cpp .tmp pass is idempotent. +############################################################################ + +# SDK linker-script sources and the vendored, config-derived autoconf header. + +AMEBA_SOC = $(AMEBA_SDK)/component/soc/$(AMEBA_SOC_NAME) +AMEBA_PROJ = $(AMEBA_SOC)/project +AMEBA_KM4_LD = $(AMEBA_PROJ)/project_km4tz/ld +AMEBA_LAYOUT_LD = $(AMEBA_PROJ)/ameba_layout.ld +AMEBA_IMG2_LD = $(AMEBA_KM4_LD)/ameba_img2_all.ld +AMEBA_ROM_LD = $(AMEBA_KM4_LD)/ameba_rom_symbol_acut_s.ld + +AMEBA_PREBUILT = $(BOARD_DIR)$(DELIM)prebuilt +AMEBA_PREBUILT_LIBS = $(AMEBA_PREBUILT)$(DELIM)libs +AMEBA_AUTOCONF = $(AMEBA_PREBUILT)$(DELIM)platform_autoconf.h + +# fwlib register-layer objects, compiled FROM SDK SOURCE into libameba_fwlib.a +# (linked via arch/.../rtl8720f/Make.defs EXTRA_LIBS) instead of vendoring a +# prebuilt blob -- so a bare checkout that only auto-fetched the SDK source can +# still link. Grow AMEBA_FWLIB_SRCS as NuttX drivers call more fwlib functions; +# --gc-sections keeps only what is referenced. AMEBA_FWLIB_INC is the SDK's +# fwlib include set, kept scoped to this compile so SDK headers never leak into +# the NuttX core build (where they would clash). + +AMEBA_FWLIB_A = $(AMEBA_PREBUILT_LIBS)$(DELIM)libameba_fwlib.a +# RTL8720F: ameba_pmu.c lives in fwlib/ram_common (not misc/), and DiagPrintf +# is a ROM symbol (provided by ameba_rom_symbol_acut_s.ld), so no swlib/log.c. +AMEBA_FWLIB_SRCS = $(AMEBA_SOC)/fwlib/ram_common/ameba_arch.c \ + $(AMEBA_SOC)/fwlib/ram_common/ameba_loguart.c \ + $(AMEBA_SOC)/fwlib/ram_common/ameba_ipc_api.c \ + $(AMEBA_SOC)/fwlib/ram_common/ameba_ipc_ram.c \ + $(AMEBA_SOC)/fwlib/ram_common/ameba_clk.c \ + $(AMEBA_SOC)/fwlib/ram_common/ameba_pmctimer.c \ + $(AMEBA_SOC)/fwlib/ram_common/ameba_pmu.c + +# NuttX owns the image2 entry: arch/arm/src/rtl8720f/ameba_app_start.c is a +# NuttX adaptation of the SDK app_start() that runs all OS-independent silicon +# init (cache/data-flash/pinmux/system-timer/MPU/...), zeroes BSS, then calls +# NuttX's main() (ameba_start.c). It is built with the SDK fwlib include set, +# so the fwlib sources it pulls in are listed alongside it. +AMEBA_FWLIB_SRCS += $(TOPDIR)/arch/arm/src/rtl8720f/ameba_app_start.c \ + $(AMEBA_SOC)/fwlib/ram_common/ameba_mpu_ram.c \ + $(AMEBA_SOC)/fwlib/ram_km4tz/ameba_data_flashclk.c \ + $(AMEBA_SOC)/fwlib/ram_km4tz/ameba_flashclk.c \ + $(AMEBA_SOC)/fwlib/ram_km4tz/ameba_pinmap.c \ + $(AMEBA_SDK)/component/soc/usrcfg/$(AMEBA_SOC_NAME)/ameba_flashcfg.c \ + $(AMEBA_SDK)/component/soc/usrcfg/$(AMEBA_SOC_NAME)/ameba_pinmapcfg.c + +# Flash primitives (FLASH_ReadStream/WriteStream/EraseXIP) for the MTD data +# filesystem. These self-lock against the NP core (inter-core HW semaphore + +# IPC pause) and disable IRQs around erase/program. +ifeq ($(CONFIG_RTL8720F_FLASH_FS),y) +AMEBA_FWLIB_SRCS += $(AMEBA_SOC)/fwlib/ram_common/ameba_flash_ram.c +endif +AMEBA_FWLIB_INC = -I$(TOPDIR)/arch/arm/src/common/ameba/sdk_shim \ + -I$(AMEBA_SOC)/fwlib/include \ + -I$(AMEBA_SOC)/fwlib/include/rom \ + -I$(AMEBA_SOC)/swlib \ + -I$(AMEBA_SOC)/hal/include \ + -I$(AMEBA_SOC)/hal/src \ + -I$(AMEBA_SDK)/component/soc/common/include \ + -I$(AMEBA_SDK)/component/soc/common/include/cmsis \ + -I$(AMEBA_SOC)/app/monitor/include \ + -I$(AMEBA_SDK)/component/soc/usrcfg/$(AMEBA_SOC_NAME)/include \ + -I$(AMEBA_SDK)/component/soc/usrcfg/common \ + -I$(AMEBA_SOC)/misc \ + -I$(AMEBA_SDK)/component/os/os_wrapper/include \ + -I$(AMEBA_SDK)/component/ssl/mbedtls-3.6.5/include \ + -I$(AMEBA_SDK)/component/soc/common/crashdump/include \ + -I$(AMEBA_PREBUILT) + +# --- WiFi (WHC host) glue lib (CONFIG_RTL8720F_WIFI) ---------------------- +# +# libameba_wifi.a holds the NuttX-side glue the precompiled host WiFi libs +# expect: a couple of SDK config sources (the user WiFi config + the task-size +# table, compiled from source so their struct layouts match the libs' ABI) and +# the NuttX lwIP/event shim (arch/.../wifi/ameba_wifi_depend.c). It is built +# with the vendor WiFi include set -- which collides with NuttX's own headers +# (lwIP vs NuttX atomic.h, ...) -- so it is compiled in its own PREBUILD loop +# (like libameba_fwlib.a), NOT through the normal arch CSRCS path. The shim +# include dir comes FIRST so its minimal shadows the SDK's. +AMEBA_WIFI_A = $(AMEBA_PREBUILT_LIBS)$(DELIM)libameba_wifi.a +AMEBA_WIFI_DIR = $(TOPDIR)$(DELIM)arch$(DELIM)arm$(DELIM)src$(DELIM)common$(DELIM)ameba$(DELIM)wifi +AMEBA_WIFI_SRCS = $(AMEBA_SDK)/component/soc/usrcfg/$(AMEBA_SOC_NAME)/ameba_wificfg.c \ + $(AMEBA_SDK)/component/wifi/common/rtw_task_size.c \ + $(AMEBA_SDK)/component/wifi/common/rtw_event.c \ + $(AMEBA_SDK)/component/soc/common/diagnose/ameba_diagnose_none.c \ + $(AMEBA_SDK)/component/wifi/wpa_supplicant/wpa_supplicant/wifi_p2p_disable.c \ + $(AMEBA_WIFI_DIR)/ameba_wifi_depend.c \ + $(AMEBA_WIFI_DIR)/ameba_wifi.c +# +# Force-include the SDK autoconf so EVERY wifi source sees CONFIG_WHC_HOST / +# CONFIG_WHC_INTF_IPC / ... (the SDK build force-includes platform_autoconf.h +# globally). Without this, sources that don't #include it themselves silently +# compile the wrong #if branch -- e.g. rtw_task_size.c's wifi_set_task_size() +# becomes empty, leaving g_rtw_task_size all-zero, so the WHC host event tasks +# are created with stack size 0 and never run -> wifi_connect() blocks forever +# waiting for the join-status event. +AMEBA_WIFI_INC = -include $(AMEBA_AUTOCONF) \ + -include $(AMEBA_WIFI_DIR)/include/ameba_lwip_off.h \ + -I$(AMEBA_WIFI_DIR)/include \ + -I$(AMEBA_WIFI_DIR)/.. \ + -I$(AMEBA_SDK)/component/wifi/api \ + -I$(AMEBA_SDK)/component/wifi/common \ + -I$(AMEBA_SDK)/component/wifi/driver/include \ + -I$(AMEBA_SDK)/component/wifi/driver/intf \ + -I$(AMEBA_SDK)/component/wifi/whc \ + -I$(AMEBA_SDK)/component/wifi/whc/whc_host_rtos \ + -I$(AMEBA_SDK)/component/wifi/whc/whc_host_rtos/ipc \ + -I$(AMEBA_SDK)/component/at_cmd \ + -I$(AMEBA_SDK)/component/wifi/wpa_supplicant/wpa_supplicant \ + -I$(AMEBA_SDK)/component/wifi/wpa_supplicant/wpa_lite \ + -I$(AMEBA_SDK)/component/wifi/wpa_supplicant/wpa_lite/rom \ + -I$(AMEBA_SDK)/component/wifi/wpa_supplicant/src \ + -I$(AMEBA_SDK)/component/wifi/wpa_supplicant/src/utils \ + -I$(AMEBA_SDK)/component/wifi/rtk_app/wifi_auto_reconnect \ + -I$(AMEBA_SDK)/component/network \ + -I$(AMEBA_SDK)/component/soc/common/diagnose \ + -I$(AMEBA_SOC)/app/monitor/include \ + -I$(AMEBA_SOC)/fwlib/include \ + -I$(AMEBA_SOC)/fwlib/include/rom \ + -I$(AMEBA_SOC)/swlib \ + -I$(AMEBA_SOC)/hal/include \ + -I$(AMEBA_SOC)/misc \ + -I$(AMEBA_SDK)/component/soc/common/include \ + -I$(AMEBA_SDK)/component/soc/common/include/cmsis \ + -I$(AMEBA_SDK)/component/os/os_wrapper/include \ + -I$(AMEBA_SDK)/component/soc/usrcfg/$(AMEBA_SOC_NAME)/include \ + -I$(AMEBA_SDK)/component/soc/usrcfg/common \ + -I$(AMEBA_SDK)/component/ssl/mbedtls-3.6.5/include \ + -I$(AMEBA_PREBUILT) + +# The combined script is generated under prebuilt/ (gitignored) by PREBUILD +# (below) and used as the single ARCHSCRIPT. Its content is already fully +# expanded (no macros, no #include), so the standard ARCHSCRIPT cpp .tmp pass +# is idempotent. ARCHSCRIPT must name a plain file here (not a rule target): +# defining an explicit recipe in this globally-included Make.defs would hijack +# the default make goal, so the generation is done in PREBUILD instead. + +GENLDSCRIPT = $(AMEBA_PREBUILT)$(DELIM)ld.script.gen + +ARCHSCRIPT += $(GENLDSCRIPT) + +# NP/device image (km4ns) + bootloader. +# +# The NP image and boot are ALWAYS (re)built from the pinned SDK source on every +# NuttX build -- no "use a stale vendored blob" shortcut -- so the two cores can +# never drift out of alignment. The NP build runs AFTER the KM4TZ (NuttX) link +# because the SDK WiFi "noused" generator strips any host WiFi API the AP image +# does not reference (calling a stripped API later deadlocks the NP -- "Compile +# NP after AP!"). So it is a POSTBUILD step handed NuttX's own disassembly +# (target_img2.asm, produced earlier in POSTBUILD) as the AP image via +# AMEBA_AP_ASM. The NP target is km4ns (the 5th arg). +# +# AMEBA_PY_SOC is the ameba.py SoC identifier for this board (public name), +# distinct from AMEBA_SOC_NAME (the SDK soc/ subdir). +AMEBA_PY_SOC = RTL8720F +AMEBA_BUILD_NP_SH = $(AMEBA_COMMON_DIR)$(DELIM)tools$(DELIM)ameba_build_np.sh + +# platform_autoconf.h is regenerated from the SDK menuconfig on every build (see +# ameba_gen_autoconf.sh) -- the SDK Kconfig is the single source of truth for +# the flash layout (CONFIG_FLASH_VFS1_*) and feature switches (CONFIG_WHC_* ...). +# AMEBA_AP_PROJECT is the AP-core SDK project subdir (km4tz on RTL8720F). +AMEBA_AP_PROJECT = km4tz +AMEBA_GEN_AUTOCONF = $(AMEBA_COMMON_DIR)$(DELIM)tools$(DELIM)ameba_gen_autoconf.sh +AMEBA_NP_PREBUILD = true +AMEBA_NP_POSTBUILD = $(AMEBA_BUILD_NP_SH) $(AMEBA_SDK) $(AMEBA_PY_SOC) \ + $(AMEBA_PREBUILT) $(AMEBA_PKGDIR)$(DELIM)target_img2.asm \ + km4ns $(AMEBA_AP_PROJECT) + +# PREBUILD -- (re)generate the combined image2 linker script before the build. +# +# ameba_img2_all.ld is C-preprocessed (it #includes ameba_layout.ld and the +# vendored, config-derived platform_autoconf.h, staged as +# project_km4/platform_autoconf.h on the include path), then +# ameba_rom_symbol_acut_s.ld is appended, then NuttX's .vectors orphan is folded +# into the loadable SRAM data region. This reproduces the SDK-generated +# rlx8721d.ld without editing any SDK source file. + +define PREBUILD + $(Q) test -n "$(AMEBA_SDK)" || \ + { echo "ERROR: AMEBA_SDK is not set. Export it to your ameba-rtos checkout."; exit 1; } + $(Q) $(AMEBA_FETCH_TOOLCHAIN) $(AMEBA_SDK) $(AMEBA_TOOLCHAIN_DIR) + $(Q) $(AMEBA_SETUP_ENV) $(AMEBA_SDK) $(AMEBA_TOOLCHAIN_DIR) + $(Q) $(AMEBA_GEN_AUTOCONF) $(AMEBA_SDK) $(AMEBA_PY_SOC) $(AMEBA_AP_PROJECT) \ + $(AMEBA_AUTOCONF) + $(Q) $(AMEBA_NP_PREBUILD) + $(Q) echo "GEN: libameba_fwlib.a (fwlib from SDK source)" + $(Q) mkdir -p $(AMEBA_PREBUILT_LIBS)$(DELIM)fwlib_obj + $(Q) rebuild_fwlib=0; \ + for src in $(AMEBA_FWLIB_SRCS); do \ + obj=$(AMEBA_PREBUILT_LIBS)/fwlib_obj/`basename $$src .c`.o; \ + if [ "$$src" -nt "$$obj" ] 2>/dev/null || [ ! -f "$$obj" ]; then \ + $(CC) $(ARCHCPUFLAGS) -Os -ffunction-sections -fdata-sections \ + $(AMEBA_FWLIB_INC) -c $$src -o $$obj || exit 1; \ + rebuild_fwlib=1; \ + fi; \ + done; \ + if [ "$$rebuild_fwlib" = "1" ] || [ ! -f "$(AMEBA_FWLIB_A)" ]; then \ + $(CROSSDEV)ar crs $(AMEBA_FWLIB_A) $(AMEBA_PREBUILT_LIBS)/fwlib_obj/*.o; \ + fi + $(Q) if [ "$(CONFIG_RTL8720F_WIFI)" = "y" ]; then \ + echo "GEN: libameba_wifi.a (WHC host glue from SDK source + NuttX shim)"; \ + mkdir -p $(AMEBA_PREBUILT_LIBS)$(DELIM)wifi_obj; \ + rebuild_wifi=0; \ + for src in $(AMEBA_WIFI_SRCS); do \ + obj=$(AMEBA_PREBUILT_LIBS)/wifi_obj/`basename $$src .c`.o; \ + if [ "$$src" -nt "$$obj" ] 2>/dev/null || [ ! -f "$$obj" ]; then \ + $(CC) $(ARCHCPUFLAGS) -Os -ffunction-sections -fdata-sections \ + $(AMEBA_WIFI_INC) -c $$src -o $$obj || exit 1; \ + rebuild_wifi=1; \ + fi; \ + done; \ + if [ "$$rebuild_wifi" = "1" ] || [ ! -f "$(AMEBA_WIFI_A)" ]; then \ + $(CROSSDEV)ar crs $(AMEBA_WIFI_A) $(AMEBA_PREBUILT_LIBS)/wifi_obj/*.o; \ + fi; \ + fi + $(Q) echo "GEN: ld.script.gen (Ameba KM4 image2)" + $(Q) mkdir -p $(AMEBA_PREBUILT)$(DELIM)project_km4tz + $(Q) cp $(AMEBA_AUTOCONF) $(AMEBA_PREBUILT)$(DELIM)project_km4tz$(DELIM)platform_autoconf.h + $(Q) $(CC) -E -P -xc -c $(AMEBA_IMG2_LD) -o $(GENLDSCRIPT) -I $(AMEBA_PREBUILT) + $(Q) cat $(AMEBA_ROM_LD) >> $(GENLDSCRIPT) + $(Q) sed -i 's|^\([[:space:]]*\)\*(\.data\*)|\1*(.vectors*)\n\1*(.data*)|' $(GENLDSCRIPT) +endef + +CFLAGS := $(ARCHCFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) +CPICFLAGS = $(ARCHPICFLAGS) $(CFLAGS) +CXXFLAGS := $(ARCHCXXFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) +CXXPICFLAGS = $(ARCHPICFLAGS) $(CXXFLAGS) +CPPFLAGS := $(ARCHINCLUDES) $(ARCHDEFINES) + +CFLAGS += $(EXTRAFLAGS) +CPPFLAGS += $(EXTRAFLAGS) + +# VFS1 data-partition geometry for the littlefs MTD comes from the SDK flash +# layout (CONFIG_FLASH_VFS1_OFFSET/SIZE in the regenerated platform_autoconf.h), +# so ameba_flash_mtd.c never hardcodes it. Extract the two values and pass them +# as neutral -D macros (a NuttX C file must not force-include the SDK autoconf). +# The header falls back to the vendor default if these are absent (e.g. the very +# first parse on a clean clone, before PREBUILD has generated the autoconf). +ifneq ($(wildcard $(AMEBA_AUTOCONF)),) +AMEBA_VFS1_OFFSET := $(strip $(shell awk '$$2=="CONFIG_FLASH_VFS1_OFFSET"{print $$3}' $(AMEBA_AUTOCONF))) +AMEBA_VFS1_SIZE := $(strip $(shell awk '$$2=="CONFIG_FLASH_VFS1_SIZE"{print $$3}' $(AMEBA_AUTOCONF))) +CFLAGS += $(if $(AMEBA_VFS1_OFFSET),-DAMEBA_FLASH_VFS1_OFFSET_XIP=$(AMEBA_VFS1_OFFSET)) +CFLAGS += $(if $(AMEBA_VFS1_SIZE),-DAMEBA_FLASH_VFS1_SIZE_CFG=$(AMEBA_VFS1_SIZE)) +endif + +AFLAGS := $(CFLAGS) -D__ASSEMBLY__ + +# NXFLAT module definitions + +NXFLATLDFLAGS1 = -r -d -warn-common +NXFLATLDFLAGS2 = $(NXFLATLDFLAGS1) -T$(TOPDIR)$(DELIM)binfmt$(DELIM)libnxflat$(DELIM)gnu-nxflat-pcrel.ld -no-check-sections +LDNXFLATFLAGS = -e main -s 2048 + +############################################################################ +# POSTBUILD -- package the linked image2 into a flashable app.bin +# +# Runs after `nuttx` (== the KM4 image2 .axf) is linked. This folds the +# prototype package_app.sh into NuttX's build: +# +# 1. Replicate the SDK image2 postbuild prologue (copy map/axf, nm/objdump). +# 2. Run the SDK km4tz image2 postbuild.cmake (axf2bin) -> km4tz_image2_all.bin. +# 3. Run the SDK project firmware_package postbuild.cmake combining the +# freshly built AP (km4tz) image2 with the freshly built NP (km4ns) image2 +# -> app.bin, copied into $(TOPDIR). +# +# The NP (km4ns) image2 is rebuilt from the pinned SDK source every build (by +# AMEBA_NP_POSTBUILD, fed the AP disassembly), so the two cores never drift. +# The SDK scripts/cmake/python are invoked read-only; only artefacts under the +# build staging dir are written. +# +# Tooling resolved from the asdk toolchain on PATH and the python interpreter +# ameba_setup_env.sh resolved (recorded in .amebapy/bindir: a real SDK .venv +# when one exists, otherwise a system-python3 shim). CMAKE may be overridden +# via the CMAKE environment variable; it defaults to `cmake` on PATH. That bin +# dir is prepended to PATH for the SDK cmake/axf2bin steps so `python`/`python3` +# resolve to the deps-carrying interpreter. It is read at recipe run time (the +# `$$(cat ...)` defers until after ameba_setup_env.sh has written the file). +############################################################################ + +AMEBA_VENV_BIN = $$(cat $(AMEBA_SDK)/.amebapy/bindir 2>/dev/null) + +CMAKE ?= cmake +NM ?= $(CROSSDEV)nm +OBJDUMP ?= $(CROSSDEV)objdump +STRIP ?= $(CROSSDEV)strip +OBJCOPY ?= $(CROSSDEV)objcopy +SIZE ?= $(CROSSDEV)size + +AMEBA_SOC_PROJ = $(AMEBA_SOC)/project +AMEBA_KM4_PROJ = $(AMEBA_SOC_PROJ)/project_km4tz + +# Staging dir for the SDK packaging steps (under the board, gitignored). + +AMEBA_PKGDIR = $(AMEBA_PREBUILT)$(DELIM)pkg + +define POSTBUILD + $(Q) echo "PACK: app.bin (Ameba AP km4tz image2 + NP km4ns image2)" + $(Q) test -n "$(AMEBA_SDK)" || \ + { echo "ERROR: AMEBA_SDK is not set"; exit 1; } + $(Q) $(AMEBA_SETUP_ENV) $(AMEBA_SDK) $(AMEBA_TOOLCHAIN_DIR) + $(Q) rm -rf $(AMEBA_PKGDIR) + $(Q) mkdir -p $(AMEBA_PKGDIR) + $(Q) cp $(TOPDIR)$(DELIM)nuttx $(AMEBA_PKGDIR)$(DELIM)target_img2.axf + $(Q) $(NM) $(AMEBA_PKGDIR)$(DELIM)target_img2.axf | sort \ + > $(AMEBA_PKGDIR)$(DELIM)target_img2.map + $(Q) $(OBJDUMP) -d $(AMEBA_PKGDIR)$(DELIM)target_img2.axf \ + > $(AMEBA_PKGDIR)$(DELIM)target_img2.asm + $(Q) $(AMEBA_NP_POSTBUILD) + $(Q) cp $(AMEBA_PKGDIR)$(DELIM)target_img2.axf \ + $(AMEBA_PKGDIR)$(DELIM)target_pure_img2.axf + $(Q) $(STRIP) $(AMEBA_PKGDIR)$(DELIM)target_pure_img2.axf + $(Q) cp $(AMEBA_PREBUILT)$(DELIM)config_km4 $(AMEBA_PKGDIR)$(DELIM).config_km4 + $(Q) cp $(AMEBA_PREBUILT)$(DELIM)config_fw $(AMEBA_PKGDIR)$(DELIM).config + $(Q) cp $(AMEBA_PREBUILT)$(DELIM)km4ns_image2_all.bin \ + $(AMEBA_PKGDIR)$(DELIM)km4ns_image2_all.bin + $(Q) printf '{\n "soc": {\n "name": "RTL8720F"\n }\n}\n' \ + > $(AMEBA_PKGDIR)$(DELIM)soc_info.json + $(Q) TARGET_SOC=RTL8720F PATH=$(AMEBA_VENV_BIN):$$PATH $(CMAKE) \ + -Dc_BASEDIR=$(AMEBA_SDK) \ + -Dc_CMAKE_FILES_DIR=$(AMEBA_SDK)/cmake \ + -Dc_SOC_PROJECT_DIR=$(AMEBA_SOC_PROJ) \ + -Dc_MCU_PROJECT_DIR=$(AMEBA_KM4_PROJ) \ + -Dc_MCU_PROJECT_NAME=km4tz \ + -Dc_MCU_KCONFIG_FILE=$(AMEBA_PKGDIR)$(DELIM).config_km4 \ + -Dc_SDK_IMAGE_TARGET_DIR=$(AMEBA_PKGDIR) \ + -DKM4_BUILDDIR= \ + -DFINAL_IMAGE_DIR=$(AMEBA_PKGDIR) \ + -DBUILD_TYPE=NONE -DANALYZE_MP_IMG=0 -DDAILY_BUILD=0 \ + -DEXTERN_DIR=$(AMEBA_PKGDIR) -DCODE_ANALYZE_RETRY= \ + -DIMAGESCRIPTDIR=$(AMEBA_SDK)/tools/image_scripts \ + -DCMAKE_SIZE=$(SIZE) -DCMAKE_OBJCOPY=$(OBJCOPY) \ + -P $(AMEBA_KM4_PROJ)/make/image2/postbuild.cmake + $(Q) TARGET_SOC=RTL8720F PATH=$(AMEBA_VENV_BIN):$$PATH $(CMAKE) \ + -Dc_BASEDIR=$(AMEBA_SDK) \ + -Dc_CMAKE_FILES_DIR=$(AMEBA_SDK)/cmake \ + -Dc_MCU_KCONFIG_FILE=$(AMEBA_PKGDIR)$(DELIM).config \ + -Dc_SOC_PROJECT_DIR=$(AMEBA_SOC_PROJ) \ + -Dc_SDK_IMAGE_TARGET_DIR= \ + -Dc_IMAGE_OUTPUT_DIR=$(AMEBA_PKGDIR) \ + -Dc_APP_BINARY_NAME=app.bin \ + -Dc_IMAGE1_ALL_FILES= \ + -Dc_IMAGE2_ALL_FILES="$(AMEBA_PKGDIR)/km4ns_image2_all.bin;$(AMEBA_PKGDIR)/km4tz_image2_all.bin" \ + -Dc_IMAGE3_ALL_FILES= \ + -DFINAL_IMAGE_DIR=$(TOPDIR) \ + -DANALYZE_MP_IMG=0 -DEXTERN_DIR=$(AMEBA_PKGDIR) \ + -P $(AMEBA_SOC_PROJ)/postbuild.cmake + $(Q) cp $(AMEBA_PREBUILT)$(DELIM)boot.bin $(TOPDIR)$(DELIM)boot.bin + $(Q) cp $(AMEBA_PREBUILT)$(DELIM)km4ns_image2_all.bin \ + $(TOPDIR)$(DELIM)km4ns_image2_all.bin + $(Q) echo "PACK: wrote $(TOPDIR)$(DELIM){app.bin,boot.bin,km4ns_image2_all.bin}" +endef diff --git a/arch/arm/src/rtl8720f/ameba_ipc.c b/arch/arm/src/rtl8720f/ameba_ipc.c new file mode 100644 index 00000000000..5916cd6e686 --- /dev/null +++ b/arch/arm/src/rtl8720f/ameba_ipc.c @@ -0,0 +1,150 @@ +/**************************************************************************** + * arch/arm/src/rtl8720f/ameba_ipc.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * RTL8720F km4tz<->km4ns IPC bring-up. + * + * The on-chip IPC links the AP (km4tz, runs NuttX) and the NP (km4ns, the + * prebuilt device blob). Several SDK fwlib subsystems use it, NOT just + * WiFi: + * + * - FLASH_Write_Lock()/Unlock() (ameba_flash_ram.c) IPC-pause the NP while + * the AP erases/programs flash. Both cores XIP from the SAME SPI NOR + * (NP@0x02000000, AP@0x04000000), so the NP MUST be paused during a + * flash erase/program or its XIP fetch faults. The lock sends + * IPC_A2N_FLASHPG_REQ and busy-waits for the NP to acknowledge; without + * IPC up the AP hangs. + * - The WHC host WiFi TRX channels. + * + * This must therefore be initialized before the flash filesystem mounts, + * independent of whether WiFi is enabled. It mirrors the SDK km4tz main(): + * + * ipc_table_init(IPCAP_DEV); + * InterruptRegister(IPC_INTHandler, IPC_KM4TZ_IRQ, IPCAP_DEV, ...); + * InterruptEn(IPC_KM4TZ_IRQ, ...); + * + * but using NuttX's irq_attach()/up_enable_irq() (NuttX owns the vector + * table). ipc_table_init() walks the .ipc.table.data section and registers + * every channel callback the linked SDK objects contributed. + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "ameba_irq.h" +#include "ameba_ipc.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* AP (km4tz) IPC device register base = IPCAP_DEV / IPC0_REG_BASE, from the + * SDK RTL8720F hal_platform.h. This matches the SDK km4tz main(), which + * calls ipc_table_init(IPCAP_DEV) with the NON-secure alias 0x40804000 + * (the secure alias 0x50804000 is NOT what the AP uses). + * RTL8720F_IRQ_IPC_KM4 maps to APIRQn IPC_KM4TZ_IRQ (external vector 3) -- + * see arch/.../irq.h. + */ + +#define IPCAP_DEV ((void *)0x40804000) + +/**************************************************************************** + * External Function Prototypes + ****************************************************************************/ + +/* SDK fwlib IPC (libameba_fwlib.a, compiled from SDK source). */ + +extern uint32_t IPC_INTHandler(void *data); +extern void ipc_table_init(void *ipcx); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static bool g_ameba_ipc_inited; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ameba_ipc_interrupt + * + * Description: + * NuttX IRQ handler shim for the km4tz IPC interrupt; forwards to the + * SDK's IPC_INTHandler, which dispatches to the registered channel + * callbacks. + * + ****************************************************************************/ + +static int ameba_ipc_interrupt(int irq, void *context, void *arg) +{ + UNUSED(irq); + UNUSED(context); + + IPC_INTHandler(arg); + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ameba_ipc_initialize + * + * Description: + * Bring up the km4tz<->km4ns IPC transport once, after the scheduler is + * running. Idempotent: safe to call from both the flash filesystem + * bring-up and the WiFi bring-up; only the first call wires the interrupt + * and walks the channel table. + * + ****************************************************************************/ + +void ameba_ipc_initialize(void) +{ + if (g_ameba_ipc_inited) + { + return; + } + + g_ameba_ipc_inited = true; + + /* Register every channel the linked SDK objects contributed (flash sync, + * and -- when linked -- the WHC WiFi TRX channels), then route the IPC + * interrupt to the SDK dispatcher. Order follows the SDK km4tz main(): + * table first, then unmask the NVIC line. + */ + + ipc_table_init(IPCAP_DEV); + irq_attach(RTL8720F_IRQ_IPC_KM4, ameba_ipc_interrupt, IPCAP_DEV); + up_enable_irq(RTL8720F_IRQ_IPC_KM4); +} diff --git a/arch/arm/src/rtl8720f/ameba_ipc.h b/arch/arm/src/rtl8720f/ameba_ipc.h new file mode 100644 index 00000000000..172c45c7a04 --- /dev/null +++ b/arch/arm/src/rtl8720f/ameba_ipc.h @@ -0,0 +1,51 @@ +/**************************************************************************** + * arch/arm/src/rtl8720f/ameba_ipc.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_RTL8720F_AMEBA_IPC_H +#define __ARCH_ARM_SRC_RTL8720F_AMEBA_IPC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: ameba_ipc_initialize + * + * Description: + * Bring up the km4tz<->km4ns IPC transport once (idempotent). Required by + * the SDK flash erase/program path (inter-core pause) and by WiFi. Call + * after the scheduler is running and before the flash filesystem mounts. + * + ****************************************************************************/ + +void ameba_ipc_initialize(void); + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_RTL8720F_AMEBA_IPC_H */ diff --git a/arch/arm/src/rtl8720f/ameba_irq.c b/arch/arm/src/rtl8720f/ameba_irq.c new file mode 100644 index 00000000000..84c7492b24c --- /dev/null +++ b/arch/arm/src/rtl8720f/ameba_irq.c @@ -0,0 +1,382 @@ +/**************************************************************************** + * arch/arm/src/rtl8720f/ameba_irq.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include "arm_internal.h" +#include "ameba_irq.h" +#include "nvic.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define NVIC_ENA_OFFSET (0) +#define NVIC_CLRENA_OFFSET (NVIC_IRQ0_31_CLEAR - NVIC_IRQ0_31_ENABLE) + +#define DEFPRIORITY32 (NVIC_SYSH_PRIORITY_DEFAULT << 24 | \ + NVIC_SYSH_PRIORITY_DEFAULT << 16 | \ + NVIC_SYSH_PRIORITY_DEFAULT << 8 | \ + NVIC_SYSH_PRIORITY_DEFAULT) + +/* Size of the interrupt stack allocation */ + +#define INTSTACK_ALLOC (CONFIG_SMP_NCPUS * INTSTACK_SIZE) + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_FEATURES +static int ameba_nmi(int irq, void *context, void *arg) +{ + up_irq_save(); + _err("PANIC!!! NMI received\n"); + PANIC(); + return 0; +} + +static int ameba_pendsv(int irq, void *context, void *arg) +{ +#ifndef CONFIG_ARCH_HIPRI_INTERRUPT + up_irq_save(); + _err("PANIC!!! PendSV received\n"); + PANIC(); +#endif + return 0; +} + +static int ameba_reserved(int irq, void *context, void *arg) +{ + up_irq_save(); + _err("PANIC!!! Reserved interrupt\n"); + PANIC(); + return 0; +} +#endif + +/**************************************************************************** + * Name: ameba_prioritize_syscall + * + * Description: + * Set the priority of an exception. This function may be needed + * internally even if support for prioritized interrupts is not enabled. + * + ****************************************************************************/ + +static inline void ameba_prioritize_syscall(int priority) +{ + uint32_t regval; + + /* SVCALL is system handler 11 */ + + regval = getreg32(NVIC_SYSH8_11_PRIORITY); + regval &= ~NVIC_SYSH_PRIORITY_PR11_MASK; + regval |= (priority << NVIC_SYSH_PRIORITY_PR11_SHIFT); + putreg32(regval, NVIC_SYSH8_11_PRIORITY); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_prioritize_irq + * + * Description: + * Set the priority of an IRQ. This function may be needed internally + * even if support for prioritized interrupts is not enabled. + * + ****************************************************************************/ + +int up_prioritize_irq(int irq, int priority) +{ + uint32_t regaddr; + uint32_t regval; + int shift; + + DEBUGASSERT(irq >= 0 && irq < NR_IRQS && + (unsigned)priority <= NVIC_SYSH_PRIORITY_MIN); + + if (irq < 16) + { + /* NVIC_SYSH_PRIORITY() maps {0..15} to one of three priority + * registers (0-3 are invalid) + */ + + regaddr = NVIC_SYSH_PRIORITY(irq); + irq -= 4; + } + else + { + /* NVIC_IRQ_PRIORITY() maps {0..} to one of many priority registers */ + + irq -= 16; + regaddr = NVIC_IRQ_PRIORITY(irq); + } + + regval = getreg32(regaddr); + shift = ((irq & 3) << 3); + regval &= ~(0xff << shift); + regval |= (priority << shift); + putreg32(regval, regaddr); + + return OK; +} + +/**************************************************************************** + * Name: up_irqinitialize + * + * Description: + * This function is called by up_initialize() during the bring-up of the + * system. It is the responsibility of this function to but the interrupt + * subsystem into the working and ready state. + * + ****************************************************************************/ + +void up_irqinitialize(void) +{ + uint32_t regaddr; + int num_priority_registers; + int i; + + /* Disable all interrupts */ + + for (i = 0; i < NR_IRQS - AMEBA_IRQ_FIRST; i += 32) + { + putreg32(0xffffffff, NVIC_IRQ_CLEAR(i)); + } + + putreg32((uint32_t)_vectors, NVIC_VECTAB); + +#ifdef CONFIG_ARCH_RAMVECTORS + /* If CONFIG_ARCH_RAMVECTORS is defined, then we are using a RAM-based + * vector table that requires special initialization. + */ + + up_ramvec_initialize(); +#endif + + /* Set all interrupts (and exceptions) to the default priority */ + + putreg32(DEFPRIORITY32, NVIC_SYSH4_7_PRIORITY); + putreg32(DEFPRIORITY32, NVIC_SYSH8_11_PRIORITY); + putreg32(DEFPRIORITY32, NVIC_SYSH12_15_PRIORITY); + + /* The NVIC ICTR register (bits 0-4) holds the number of of interrupt + * lines that the NVIC supports: + * + * 0 -> 32 interrupt lines, 8 priority registers + * 1 -> 64 " " " ", 16 priority registers + * 2 -> 96 " " " ", 32 priority registers + * ... + */ + + num_priority_registers = (getreg32(NVIC_ICTR) + 1) * 8; + + /* Now set all of the interrupt lines to the default priority */ + + regaddr = NVIC_IRQ0_3_PRIORITY; + while (num_priority_registers--) + { + putreg32(DEFPRIORITY32, regaddr); + regaddr += 4; + } + + /* Attach the SVCall and Hard Fault exception handlers. The SVCall + * exception is used for performing context switches; The Hard Fault + * must also be caught because a SVCall may show up as a Hard Fault + * under certain conditions. + */ + + irq_attach(AMEBA_IRQ_SVCALL, arm_svcall, NULL); + irq_attach(AMEBA_IRQ_HARDFAULT, arm_hardfault, NULL); + + /* Set the priority of the SVCall interrupt */ + + up_prioritize_irq(AMEBA_IRQ_PENDSV, NVIC_SYSH_PRIORITY_MIN); + + ameba_prioritize_syscall(NVIC_SYSH_SVCALL_PRIORITY); + + /* If the MPU is enabled, then attach and enable the Memory Management + * Fault handler. + */ + +#ifdef CONFIG_ARM_MPU + irq_attach(AMEBA_IRQ_MEMFAULT, arm_memfault, NULL); + up_enable_irq(AMEBA_IRQ_MEMFAULT); +#endif + + /* Attach all other processor exceptions (except reset and sys tick) */ + +#ifdef CONFIG_DEBUG_FEATURES + irq_attach(AMEBA_IRQ_NMI, ameba_nmi, NULL); +#ifndef CONFIG_ARM_MPU + irq_attach(AMEBA_IRQ_MEMFAULT, arm_memfault, NULL); +#endif + irq_attach(AMEBA_IRQ_BUSFAULT, arm_busfault, NULL); + irq_attach(AMEBA_IRQ_USAGEFAULT, arm_usagefault, NULL); + irq_attach(AMEBA_IRQ_PENDSV, ameba_pendsv, NULL); + arm_enable_dbgmonitor(); + irq_attach(AMEBA_IRQ_DBGMONITOR, arm_dbgmonitor, NULL); + irq_attach(AMEBA_IRQ_RESERVED, ameba_reserved, NULL); +#endif + +#ifndef CONFIG_SUPPRESS_INTERRUPTS + + /* And finally, enable interrupts */ + + arm_color_intstack(); + up_irq_enable(); +#endif +} + +static int ameba_irqinfo(int irq, uintptr_t *regaddr, uint32_t *bit, + uintptr_t offset) +{ + int n; + + DEBUGASSERT(irq >= AMEBA_IRQ_NMI && irq < NR_IRQS); + + /* Check for external interrupt */ + + if (irq >= AMEBA_IRQ_FIRST) + { + n = irq - AMEBA_IRQ_FIRST; + *regaddr = NVIC_IRQ_ENABLE(n) + offset; + *bit = (uint32_t)0x1 << (n & 0x1f); + } + + /* Handle processor exceptions. Only a few can be disabled */ + + else + { + *regaddr = NVIC_SYSHCON; + if (irq == AMEBA_IRQ_MEMFAULT) + { + *bit = NVIC_SYSHCON_MEMFAULTENA; + } + else if (irq == AMEBA_IRQ_BUSFAULT) + { + *bit = NVIC_SYSHCON_BUSFAULTENA; + } + else if (irq == AMEBA_IRQ_USAGEFAULT) + { + *bit = NVIC_SYSHCON_USGFAULTENA; + } + else if (irq == AMEBA_IRQ_SYSTICK) + { + *regaddr = NVIC_SYSTICK_CTRL; + *bit = NVIC_SYSTICK_CTRL_ENABLE; + } + else + { + return -EINVAL; /* Invalid or unsupported exception */ + } + } + + return OK; +} + +/**************************************************************************** + * Name: up_disable_irq + * + * Description: + * Disable the IRQ specified by 'irq' + * + ****************************************************************************/ + +void up_disable_irq(int irq) +{ + uintptr_t regaddr; + uint32_t regval; + uint32_t bit; + + if (ameba_irqinfo(irq, ®addr, &bit, NVIC_CLRENA_OFFSET) == 0) + { + /* Modify the appropriate bit in the register to disable the interrupt. + * For normal interrupts, we need to set the bit in the associated + * Interrupt Clear Enable register. For other exceptions, we need to + * clear the bit in the System Handler Control and State Register. + */ + + if (irq >= AMEBA_IRQ_FIRST) + { + putreg32(bit, regaddr); + } + else + { + regval = getreg32(regaddr); + regval &= ~bit; + putreg32(regval, regaddr); + } + } +} + +/**************************************************************************** + * Name: up_enable_irq + * + * Description: + * Enable the IRQ specified by 'irq' + * + ****************************************************************************/ + +void up_enable_irq(int irq) +{ + uintptr_t regaddr; + uint32_t regval; + uint32_t bit; + + if (ameba_irqinfo(irq, ®addr, &bit, NVIC_ENA_OFFSET) == 0) + { + /* Modify the appropriate bit in the register to enable the interrupt. + * For normal interrupts, we need to set the bit in the associated + * Interrupt Set Enable register. For other exceptions, we need to + * set the bit in the System Handler Control and State Register. + */ + + if (irq >= AMEBA_IRQ_FIRST) + { + putreg32(bit, regaddr); + } + else + { + regval = getreg32(regaddr); + regval |= bit; + putreg32(regval, regaddr); + } + } +} + +/**************************************************************************** + * Name: arm_ack_irq + ****************************************************************************/ + +void arm_ack_irq(int irq) +{ +} diff --git a/arch/arm/src/rtl8720f/ameba_irq.h b/arch/arm/src/rtl8720f/ameba_irq.h new file mode 100644 index 00000000000..d4afbb365b2 --- /dev/null +++ b/arch/arm/src/rtl8720f/ameba_irq.h @@ -0,0 +1,76 @@ +/**************************************************************************** + * arch/arm/src/rtl8720f/ameba_irq.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_RTL8720F_AMEBA_IRQ_H +#define __ARCH_ARM_SRC_RTL8720F_AMEBA_IRQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Processor exception aliases used by the chip-internal logic. These mirror + * the ARMv8-M processor exception vector numbers (0-15) exported by + * arch/rtl8720f/irq.h. + */ + +#define AMEBA_IRQ_RESERVED RTL8720F_IRQ_RESERVED +#define AMEBA_IRQ_NMI RTL8720F_IRQ_NMI +#define AMEBA_IRQ_HARDFAULT RTL8720F_IRQ_HARDFAULT +#define AMEBA_IRQ_MEMFAULT RTL8720F_IRQ_MEMFAULT +#define AMEBA_IRQ_BUSFAULT RTL8720F_IRQ_BUSFAULT +#define AMEBA_IRQ_USAGEFAULT RTL8720F_IRQ_USAGEFAULT +#define AMEBA_IRQ_SVCALL RTL8720F_IRQ_SVCALL +#define AMEBA_IRQ_DBGMONITOR RTL8720F_IRQ_DBGMONITOR +#define AMEBA_IRQ_PENDSV RTL8720F_IRQ_PENDSV +#define AMEBA_IRQ_SYSTICK RTL8720F_IRQ_SYSTICK +#define AMEBA_IRQ_FIRST RTL8720F_IRQ_FIRST + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_RTL8720F_AMEBA_IRQ_H */ diff --git a/arch/arm/src/rtl8720f/ameba_loguart.c b/arch/arm/src/rtl8720f/ameba_loguart.c new file mode 100644 index 00000000000..b3a79018c2f --- /dev/null +++ b/arch/arm/src/rtl8720f/ameba_loguart.c @@ -0,0 +1,413 @@ +/*************************************************************************** + * arch/arm/src/rtl8720f/ameba_loguart.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ***************************************************************************/ + +/*************************************************************************** + * Included Files + ***************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "arm_internal.h" +#include "chip.h" +#include "ameba_irq.h" + +/*************************************************************************** + * Pre-processor Definitions + ***************************************************************************/ + +/* This driver targets the RTL8720F LOG-UART, which NuttX (on + * the KM4 application core) owns directly. + * + * The Realtek SDK's app_start() runs BEFORE NuttX and has already + * configured the LOG-UART pinmux/clock/baud and printed its boot banner, + * so the hardware is not re-initialized here. + * + * The LOG-UART is physically shared with the NP, but the NP image is built + * with CONFIG_SHELL=n: the NP neither runs its monitor shell nor claims the + * LOG-UART RX interrupt. NuttX therefore routes the LOG-UART interrupt to + * the AP with LOGUART_INTCoreConfig() and reads RX directly via the ROM + * helpers, giving the AP sole ownership of the console (no IPC relay). + * + * NuttX installs its own vector table and re-points VTOR in + * up_irqinitialize(), so once NuttX is running it fully owns the NVIC. + */ + +/* LOGUART_INTConfig() interrupt-source bit (RX data available). */ + +#define LOGUART_BIT_ERBI (1u << 0) + +/* LOGUART_INTCoreConfig() per-core routing masks (SDK KM0/KM4 mask bits): + * select which core's NVIC the LOG-UART interrupt is delivered to. NP is + * the network core (km4ns), AP is the host core (km4tz / NuttX). + */ + +#define LOGUART_BIT_INTR_MASK_NP (1u << 0) +#define LOGUART_BIT_INTR_MASK_AP (1u << 1) + +/* SDK ENABLE/DISABLE values. */ + +#define AMEBA_ENABLE 1 +#define AMEBA_DISABLE 0 + +/* LOG-UART device base (UARTLOG_REG_BASE, from SDK RTL8720F + * hal_platform.h). NOTE: this is the RTL8720F address (0x401C6000) -- it + * differs from the RTL8721Dx LOG-UART (0x4100F000). Only + * LOGUART_INTConfig()/INTCoreConfig() take this base explicitly; the TX + * path (DiagPrintf/LOGUART_PutChar) is a ROM call with its own internal + * base, which is why TX worked even when this was wrong but configuring + * the RX interrupt bus-faulted. + */ + +#define LOGUART_DEV ((void *)0x401C6000) + +/*************************************************************************** + * External ROM/SDK Function Prototypes + ***************************************************************************/ + +/* These live in the RTL8720F ROM and are resolved at link time from the + * SDK's ROM symbol script. Declared here (instead of including the SDK + * headers) to keep the SDK include tree out of the NuttX build. + */ + +extern void LOGUART_PutChar(unsigned char c); +extern unsigned char LOGUART_Readable(void); +extern unsigned char LOGUART_GetChar(int pullmode); +extern void LOGUART_INTConfig(void *dev, unsigned int it, + unsigned int state); +extern void LOGUART_INTCoreConfig(void *dev, unsigned int mask, + unsigned int state); + +/*************************************************************************** + * Private Function Prototypes + ***************************************************************************/ + +static int loguart_setup(struct uart_dev_s *dev); +static void loguart_shutdown(struct uart_dev_s *dev); +static int loguart_attach(struct uart_dev_s *dev); +static void loguart_detach(struct uart_dev_s *dev); +static int loguart_interrupt(int irq, void *context, void *arg); +static int loguart_ioctl(struct file *filep, int cmd, unsigned long arg); +static int loguart_receive(struct uart_dev_s *dev, unsigned int *status); +static void loguart_rxint(struct uart_dev_s *dev, bool enable); +static bool loguart_rxavailable(struct uart_dev_s *dev); +static void loguart_send(struct uart_dev_s *dev, int ch); +static void loguart_txint(struct uart_dev_s *dev, bool enable); +static bool loguart_txready(struct uart_dev_s *dev); +static bool loguart_txempty(struct uart_dev_s *dev); + +/*************************************************************************** + * Private Data + ***************************************************************************/ + +static const struct uart_ops_s g_loguart_ops = +{ + .setup = loguart_setup, + .shutdown = loguart_shutdown, + .attach = loguart_attach, + .detach = loguart_detach, + .ioctl = loguart_ioctl, + .receive = loguart_receive, + .rxint = loguart_rxint, + .rxavailable = loguart_rxavailable, + .send = loguart_send, + .txint = loguart_txint, + .txready = loguart_txready, + .txempty = loguart_txempty, +}; + +/* I/O buffers for the LOG-UART console. */ + +static char g_loguart_rxbuffer[CONFIG_RTL8720F_LOGUART_RXBUFSIZE]; +static char g_loguart_txbuffer[CONFIG_RTL8720F_LOGUART_TXBUFSIZE]; + +/* The LOG-UART port device. */ + +static struct uart_dev_s g_loguart_port = +{ + .isconsole = true, + .recv = + { + .size = CONFIG_RTL8720F_LOGUART_RXBUFSIZE, + .buffer = g_loguart_rxbuffer, + }, + .xmit = + { + .size = CONFIG_RTL8720F_LOGUART_TXBUFSIZE, + .buffer = g_loguart_txbuffer, + }, + .ops = &g_loguart_ops, +}; + +/*************************************************************************** + * Private Functions + ***************************************************************************/ + +/*************************************************************************** + * Name: loguart_setup + ***************************************************************************/ + +static int loguart_setup(struct uart_dev_s *dev) +{ + UNUSED(dev); + return OK; +} + +/*************************************************************************** + * Name: loguart_shutdown + ***************************************************************************/ + +static void loguart_shutdown(struct uart_dev_s *dev) +{ + loguart_rxint(dev, false); +} + +/*************************************************************************** + * Name: loguart_attach + * + * Description: + * Route the LOG-UART interrupt to KM4 and attach the handler. The + * data-available (RX) source itself is enabled later via rxint(). + * + ***************************************************************************/ + +static int loguart_attach(struct uart_dev_s *dev) +{ + int ret; + + ret = irq_attach(RTL8720F_IRQ_UART_LOG, loguart_interrupt, dev); + if (ret == OK) + { + /* Claim the LOG-UART interrupt for the AP (the NP is built + * CONFIG_SHELL=n and does not claim it) and unmask it in the NVIC. + */ + + LOGUART_INTCoreConfig(LOGUART_DEV, LOGUART_BIT_INTR_MASK_NP, + AMEBA_DISABLE); + LOGUART_INTCoreConfig(LOGUART_DEV, LOGUART_BIT_INTR_MASK_AP, + AMEBA_ENABLE); + up_enable_irq(RTL8720F_IRQ_UART_LOG); + } + + return ret; +} + +/*************************************************************************** + * Name: loguart_detach + ***************************************************************************/ + +static void loguart_detach(struct uart_dev_s *dev) +{ + UNUSED(dev); + up_disable_irq(RTL8720F_IRQ_UART_LOG); + irq_detach(RTL8720F_IRQ_UART_LOG); +} + +/*************************************************************************** + * Name: loguart_interrupt + * + * Description: + * Common LOG-UART interrupt handler. Drains the RX FIFO into the NuttX + * receive buffer. + * + ***************************************************************************/ + +static int loguart_interrupt(int irq, void *context, void *arg) +{ + struct uart_dev_s *dev = (struct uart_dev_s *)arg; + + UNUSED(irq); + UNUSED(context); + + if (LOGUART_Readable()) + { + uart_recvchars(dev); + } + + return OK; +} + +/*************************************************************************** + * Name: loguart_ioctl + ***************************************************************************/ + +static int loguart_ioctl(struct file *filep, int cmd, unsigned long arg) +{ + UNUSED(filep); + UNUSED(cmd); + UNUSED(arg); + return -ENOTTY; +} + +/*************************************************************************** + * Name: loguart_receive + ***************************************************************************/ + +static int loguart_receive(struct uart_dev_s *dev, unsigned int *status) +{ + UNUSED(dev); + + *status = 0; + + /* Read one byte in polled (non-pull) mode. */ + + return (int)LOGUART_GetChar(false); +} + +/*************************************************************************** + * Name: loguart_rxint + ***************************************************************************/ + +static void loguart_rxint(struct uart_dev_s *dev, bool enable) +{ + irqstate_t flags; + + UNUSED(dev); + + flags = enter_critical_section(); + + if (enable) + { + LOGUART_INTConfig(LOGUART_DEV, LOGUART_BIT_ERBI, AMEBA_ENABLE); + } + else + { + LOGUART_INTConfig(LOGUART_DEV, LOGUART_BIT_ERBI, AMEBA_DISABLE); + } + + leave_critical_section(flags); +} + +/*************************************************************************** + * Name: loguart_rxavailable + ***************************************************************************/ + +static bool loguart_rxavailable(struct uart_dev_s *dev) +{ + UNUSED(dev); + return LOGUART_Readable() != 0; +} + +/*************************************************************************** + * Name: loguart_send + ***************************************************************************/ + +static void loguart_send(struct uart_dev_s *dev, int ch) +{ + UNUSED(dev); + LOGUART_PutChar((unsigned char)ch); +} + +/*************************************************************************** + * Name: loguart_txint + * + * Description: + * TX is synchronous (LOGUART_PutChar blocks for FIFO space), so there + * is no hardware TX interrupt; pump the transmit buffer when asked to + * enable. + * + ***************************************************************************/ + +static void loguart_txint(struct uart_dev_s *dev, bool enable) +{ + irqstate_t flags; + + if (enable) + { + flags = enter_critical_section(); + uart_xmitchars(dev); + leave_critical_section(flags); + } +} + +/*************************************************************************** + * Name: loguart_txready + ***************************************************************************/ + +static bool loguart_txready(struct uart_dev_s *dev) +{ + UNUSED(dev); + return true; +} + +/*************************************************************************** + * Name: loguart_txempty + ***************************************************************************/ + +static bool loguart_txempty(struct uart_dev_s *dev) +{ + UNUSED(dev); + return true; +} + +/*************************************************************************** + * Public Functions + ***************************************************************************/ + +/*************************************************************************** + * Name: arm_lowputc + ***************************************************************************/ + +void arm_lowputc(char ch) +{ + if (ch == '\n') + { + LOGUART_PutChar((unsigned char)'\r'); + } + + LOGUART_PutChar((unsigned char)ch); +} + +/*************************************************************************** + * Name: arm_earlyserialinit + ***************************************************************************/ + +void arm_earlyserialinit(void) +{ +} + +/*************************************************************************** + * Name: arm_serialinit + ***************************************************************************/ + +void arm_serialinit(void) +{ + uart_register("/dev/console", &g_loguart_port); + uart_register("/dev/ttyS0", &g_loguart_port); +} + +/*************************************************************************** + * Name: up_putc + ***************************************************************************/ + +void up_putc(int ch) +{ + arm_lowputc((char)ch); +} diff --git a/arch/arm/src/rtl8720f/ameba_start.c b/arch/arm/src/rtl8720f/ameba_start.c new file mode 100644 index 00000000000..9dc7a698321 --- /dev/null +++ b/arch/arm/src/rtl8720f/ameba_start.c @@ -0,0 +1,172 @@ +/**************************************************************************** + * arch/arm/src/rtl8720f/ameba_start.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Description + * + * NuttX owns the km4tz image2. The entry is a NuttX-owned app_start() + * (arch/arm/src/rtl8720f/ameba_app_start.c, built with the SDK fwlib include + * set) that runs ALL the OS-independent silicon init (cache, data-flash + * high-speed, system timer, pinmux, MPU, ...) and zeroes BSS, then calls + * main(). Its Img2EntryFun0 descriptor (also in that file) is what the SDK + * bootloader jumps to. + * + * main() is therefore the hand-off point from silicon bring-up to NuttX: + * it switches MSP onto a NuttX-owned stack (the idle-thread stack), points + * VTOR at NuttX's own vector table, configures the FPU, and calls + * nx_start(). nx_start() never returns, so the SDK FreeRTOS scheduler is + * never launched. + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include + +#include "arm_internal.h" +#include "nvic.h" +#include "ameba_irq.h" + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* Reserved idle-thread stack, owned by NuttX (in NuttX's own .bss). The ARM + * full-descending stack grows down from the top of this buffer. + * g_idle_topstack points at the TOP and is consumed by the scheduler / idle + * thread bring-up logic. + */ + +static uint8_t g_idle_stack[CONFIG_IDLETHREAD_STACKSIZE] + aligned_data(8); + +const uintptr_t g_idle_topstack = + (uintptr_t)g_idle_stack + CONFIG_IDLETHREAD_STACKSIZE; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* NuttX vector table (armv8-m/arm_vectors.c). */ + +extern const void * const _vectors[]; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void ameba_start_continue(void) noreturn_function used_code; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ameba_start_continue + * + * Description: + * Runs on the NuttX idle stack (MSP already switched by main()). The SDK + * app_start() has already done all silicon init and zeroed BSS, so here we + * only take ownership of the vector table / FPU and enter the scheduler. + * + ****************************************************************************/ + +static void ameba_start_continue(void) +{ + /* Configure the FPU. */ + + arm_fpuconfig(); + + /* Point the vector table at NuttX's own table (the SDK app_start left VTOR + * pointing at the SDK/ROM table). + */ + + putreg32((uint32_t)_vectors, NVIC_VECTAB); + + /* Perform early serial initialization. */ + +#ifdef USE_EARLYSERIALINIT + arm_earlyserialinit(); +#endif + + /* Start NuttX. Never returns. */ + + nx_start(); + + for (; ; ); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: main + * + * Description: + * Hand-off from the SDK app_start() (which ran the silicon init and + * zeroed BSS) into NuttX. Switches MSP onto the NuttX idle stack as the + * very first action, then branches to ameba_start_continue() (which runs + * on that new stack). Declared naked so the compiler emits no prologue + * that would touch the (about-to-be-replaced) stack. Never returns. + * + ****************************************************************************/ + +int main(void) naked_function; +int main(void) +{ + __asm__ __volatile__ + ( + " movs r0, #0\n" + " msr msplim, r0\n" + " ldr r0, =g_idle_topstack\n" + " ldr r0, [r0]\n" + " msr msp, r0\n" + " b ameba_start_continue\n" + ); +} + +/**************************************************************************** + * Name: __start + * + * Description: + * Reset entry referenced by the NuttX armv8-m vector table (_vectors[1]). + * In this port the real image2 entry is Img2EntryFun0 -> app_start() -> + * main() (see ameba_app_start.c); __start exists so the vector table links + * and falls into the NuttX hand-off should the reset vector ever be taken. + * + ****************************************************************************/ + +void __start(void) naked_function; +void __start(void) +{ + __asm__ __volatile__ + ( + " b main\n" + ); +} diff --git a/arch/arm/src/rtl8720f/ameba_timerisr.c b/arch/arm/src/rtl8720f/ameba_timerisr.c new file mode 100644 index 00000000000..1963db45a72 --- /dev/null +++ b/arch/arm/src/rtl8720f/ameba_timerisr.c @@ -0,0 +1,72 @@ +/**************************************************************************** + * arch/arm/src/rtl8720f/ameba_timerisr.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "arm_internal.h" +#include "systick.h" +#include "ameba_irq.h" +#include "nvic.h" + +/**************************************************************************** + * External Symbols + ****************************************************************************/ + +/* SDK CMSIS core-clock variable, set to the real KM4 CPU frequency (e.g. + * 240 MHz) by SystemCoreClockUpdate() in ameba_app_start() before NuttX + * runs. The ARMv8-M SysTick is clocked from the processor clock + * (CLKSOURCE=1, the 'true' below), so this is the correct reload base. + * Reading it at runtime avoids hard-coding a frequency that must track the + * SDK clock setup. + */ + +extern uint32_t SystemCoreClock; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: up_timer_initialize + * + * Description: + * This function is called during start-up to initialize + * the timer hardware. + * + ****************************************************************************/ + +void up_timer_initialize(void) +{ + uint32_t freq = SystemCoreClock; + + /* Set reload register and start the generic ARMv8-M SysTick driver. */ + + putreg32((freq / CLK_TCK) - 1, NVIC_SYSTICK_RELOAD); + up_timer_set_lowerhalf(systick_initialize(true, freq, -1)); +} diff --git a/arch/arm/src/rtl8720f/ameba_wifi_init.c b/arch/arm/src/rtl8720f/ameba_wifi_init.c new file mode 100644 index 00000000000..2bff9b442dd --- /dev/null +++ b/arch/arm/src/rtl8720f/ameba_wifi_init.c @@ -0,0 +1,134 @@ +/**************************************************************************** + * arch/arm/src/rtl8720f/ameba_wifi_init.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * NuttX side of the RTL8720F WiFi bring-up. + * + * The WHC host stack talks to the WiFi MAC/PHY (which runs on the NP network + * processor, km4ns) over the on-chip AP<->NP IPC. This file wires that IPC + * into NuttX's interrupt system -- mirroring the SDK AP main(): + * + * InterruptRegister(IPC_INTHandler, IPC_KM4_IRQ, IPCKM4_DEV, ...); + * InterruptEn(IPC_KM4_IRQ, ...); + * ipc_table_init(IPCKM4_DEV); + * + * but using NuttX's irq_attach()/up_enable_irq() (NuttX owns the vector + * table). ipc_table_init() then walks the .ipc.table.data section and + * registers every channel callback the linked SDK objects contributed, + * including the WHC WiFi TRX channels. Once IPC is live it spawns a task + * that runs the (blocking) host bring-up in ameba_wifi_start() (SDK-header + * side, libameba_wifi.a). + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include + +#include "ameba_irq.h" +#include "ameba_ipc.h" +#ifdef CONFIG_NET +# include "ameba_wlan.h" +#endif + +/**************************************************************************** + * External Function Prototypes + ****************************************************************************/ + +/* Host WiFi bring-up (libameba_wifi.a, SDK-header side). */ + +extern int ameba_wifi_start(void); + +/**************************************************************************** + * Name: ameba_wifi_start_task + * + * Description: + * Task entry running the blocking WHC host bring-up once the scheduler and + * IPC are up. + * + ****************************************************************************/ + +static int ameba_wifi_start_task(int argc, char *argv[]) +{ + UNUSED(argc); + UNUSED(argv); + + /* Power on the WHC host stack (blocks on the NP round-trip), then register + * the wlan0 network device. + */ + + int ret = ameba_wifi_start(); + + syslog(LOG_INFO, "[ameba-wifi] ameba_wifi_start -> %d\n", ret); + if (ret == 0) + { +#ifdef CONFIG_NET + ret = ameba_wlan_initialize(); + syslog(LOG_INFO, "[ameba-wifi] ameba_wlan_initialize -> %d\n", ret); +#endif + } + + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rtl8720f_wifi_initialize + * + * Description: + * Bring up the KM4 IPC transport for WiFi and start the WHC host stack. + * Call from board bring-up after the scheduler is running. + * + * Returned Value: + * 0 on success; a negated errno on failure to spawn the bring-up task. + * + ****************************************************************************/ + +int rtl8720f_wifi_initialize(void) +{ + int pid; + + /* Route the km4tz IPC interrupt to the SDK dispatcher and register every + * channel the linked objects contributed (WHC WiFi TRX channels included). + * Idempotent and shared with the flash filesystem bring-up. + */ + + ameba_ipc_initialize(); + + /* wifi_on() blocks on the NP round-trip, so run it off the init path. */ + + pid = kthread_create("ameba_wifi", SCHED_PRIORITY_DEFAULT, 8192, + ameba_wifi_start_task, NULL); + return pid < 0 ? pid : 0; +} diff --git a/arch/arm/src/rtl8720f/chip.h b/arch/arm/src/rtl8720f/chip.h new file mode 100644 index 00000000000..1d69739029a --- /dev/null +++ b/arch/arm/src/rtl8720f/chip.h @@ -0,0 +1,39 @@ +/**************************************************************************** + * arch/arm/src/rtl8720f/chip.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_RTL8720F_CHIP_H +#define __ARCH_ARM_SRC_RTL8720F_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ARMV8M_PERIPHERAL_INTERRUPTS NR_IRQS + +#endif /* __ARCH_ARM_SRC_RTL8720F_CHIP_H */ diff --git a/arch/arm/src/rtl8720f/hardware/ameba_memorymap.h b/arch/arm/src/rtl8720f/hardware/ameba_memorymap.h new file mode 100644 index 00000000000..fa2a55ab494 --- /dev/null +++ b/arch/arm/src/rtl8720f/hardware/ameba_memorymap.h @@ -0,0 +1,62 @@ +/**************************************************************************** + * arch/arm/src/rtl8720f/hardware/ameba_memorymap.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_RTL8720F_HARDWARE_AMEBA_MEMORYMAP_H +#define __ARCH_ARM_SRC_RTL8720F_HARDWARE_AMEBA_MEMORYMAP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* RTL8720F memory map (from SDK + * component/soc/RTL8720F/project/ameba_layout.ld and + * fwlib/include/hal_platform.h). + * + * On-chip SRAM is 512 KiB: 0x2000_0000 .. 0x2008_0000 (secure alias at + * 0x3000_0000). Partitioned low->high: 8 KiB shared KM4TZ/KM4NS RAM, the + * KM4TZ IMG2 region (where NuttX runs), then the KM4NS IMG2 region + * (~184-192 KiB, the prebuilt NP/device image). + * + * NuttX runs on km4tz as IMG2. The heap is taken from the SDK image2 linker + * symbols __bdram_heap_buffer_start__/_size__ (see ameba_allocateheap.c), so + * the window below mainly feeds CONFIG_RAM_START/SIZE (kept in sync with the + * board defconfig). + */ + +/* Whole on-chip SRAM (secure alias base; km4tz runs in the secure world). */ + +#define AMEBA_SRAM_START 0x30000000 +#define AMEBA_SRAM_SIZE 0x00080000 /* 512 KiB */ + +/* km4tz IMG2 RAM window (matches board CONFIG_RAM_START/SIZE). */ + +#define PRIMARY_RAM_START 0x30008000 +#define PRIMARY_RAM_SIZE 0x00040000 +#define PRIMARY_RAM_END (PRIMARY_RAM_START + PRIMARY_RAM_SIZE) + +#endif /* __ARCH_ARM_SRC_RTL8720F_HARDWARE_AMEBA_MEMORYMAP_H */ diff --git a/arch/arm/src/rtl8721dx/CMakeLists.txt b/arch/arm/src/rtl8721dx/CMakeLists.txt new file mode 100644 index 00000000000..3b47d76726b --- /dev/null +++ b/arch/arm/src/rtl8721dx/CMakeLists.txt @@ -0,0 +1,44 @@ +# ############################################################################## +# arch/arm/src/rtl8721dx/CMakeLists.txt +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more contributor +# license agreements. See the NOTICE file distributed with this work for +# additional information regarding copyright ownership. The ASF licenses this +# file to you under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +# +# ############################################################################## + +# IC-specific register drivers + IPC wiring live here; IC-agnostic glue is +# shared from arch/arm/src/common/ameba. +set(SRCS ameba_allocateheap.c ameba_irq.c ameba_loguart.c ameba_start.c + ameba_timerisr.c) + +set(AMEBA_COMMON ${CMAKE_CURRENT_LIST_DIR}/../common/ameba) + +list(APPEND SRCS ${AMEBA_COMMON}/ameba_os_wrap.c) + +if(CONFIG_RTL8721DX_WIFI) + list(APPEND SRCS ameba_wifi_init.c ${AMEBA_COMMON}/ameba_kv.c) + if(CONFIG_NET) + list(APPEND SRCS ${AMEBA_COMMON}/ameba_wlan.c) + endif() +endif() + +if(CONFIG_RTL8721DX_FLASH_FS) + list(APPEND SRCS ${AMEBA_COMMON}/ameba_flash_mtd.c) +endif() + +target_include_directories(arch PRIVATE ${AMEBA_COMMON}) +target_sources(arch PRIVATE ${SRCS}) diff --git a/arch/arm/src/rtl8721dx/Kconfig b/arch/arm/src/rtl8721dx/Kconfig new file mode 100644 index 00000000000..64efd1cecab --- /dev/null +++ b/arch/arm/src/rtl8721dx/Kconfig @@ -0,0 +1,85 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +if ARCH_CHIP_RTL8721DX + +menu "RTL8721Dx Chip Selection" + +config RTL8721DX_KM4 + bool + default y + ---help--- + The Realtek RTL8721Dx KM4 application core + (ARMv8-M.main / Cortex-M33). + +endmenu # RTL8721Dx Chip Selection + +menu "RTL8721Dx Bring-up Options" + +config RTL8721DX_HEAP_SIZE + hex "NuttX reserved heap size (bytes)" + default 0x10000 + ---help--- + During bring-up NuttX runs as a guest on the Realtek SDK image and + must not touch RAM that the SDK owns. Instead of claiming all SRAM + from the end of NuttX's BSS to the end of memory (which overlaps the + SDK heap), NuttX uses a self-contained, statically reserved heap of + this size placed in NuttX's own .bss. up_allocate_heap() returns + this buffer. Keep it within the 288KB KM4 SRAM budget after NuttX + text/data/bss. + +config RTL8721DX_LOGUART_RXBUFSIZE + int "LOG-UART console RX buffer size" + default 256 + ---help--- + Size of the NuttX receive buffer for the LOG-UART console. + +config RTL8721DX_LOGUART_TXBUFSIZE + int "LOG-UART console TX buffer size" + default 256 + ---help--- + Size of the NuttX transmit buffer for the LOG-UART console. + +endmenu # RTL8721Dx Bring-up Options + +menu "RTL8721Dx WiFi" + +config RTL8721DX_WIFI + bool "WiFi (WHC host) support" + default n + ---help--- + Link the Realtek WHC (WiFi Host Controller) host stack so the AP can + drive the WiFi MAC/PHY that runs on the NP network processor. The + AP-side host WiFi control libraries (lib_wifi_whc_ap and friends) + are linked from the pinned SDK; the lwIP / event glue they expect is + provided by NuttX (arch/arm/src/common/ameba/wifi/), routing frames + into NuttX's native network stack instead of lwIP. + + M3.1 brings up the control plane only (wifi_on + scan); the data + path and netdev/wireless-extension wiring follow. + +endmenu # RTL8721Dx WiFi + +menu "RTL8721Dx Storage" + +config RTL8721DX_FLASH_FS + bool "On-chip SPI NOR data filesystem (littlefs)" + default n + select MTD + select MTD_BYTE_WRITE + select FS_LITTLEFS + ---help--- + Expose the SDK "VFS1" data partition (the last 128 KiB of the + on-chip SPI NOR flash, which does not overlap the NP/AP firmware + images) as a NuttX MTD device and mount a littlefs filesystem on it + at /data. This provides persistent storage for application data and + backs the WiFi fast-connect / PMK key-value store (rt_kv_*). + + The MTD backend wraps the SDK's dual-core-locked FLASH_xxx flash + primitives (ameba_flash_mtd.c). + +endmenu # RTL8721Dx Storage + +endif # ARCH_CHIP_RTL8721DX diff --git a/arch/arm/src/rtl8721dx/Make.defs b/arch/arm/src/rtl8721dx/Make.defs new file mode 100644 index 00000000000..108aa64e800 --- /dev/null +++ b/arch/arm/src/rtl8721dx/Make.defs @@ -0,0 +1,198 @@ +############################################################################ +# arch/arm/src/rtl8721dx/Make.defs +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include armv8-m/Make.defs + +# IC-agnostic Ameba glue (os_wrapper backend, netdev, KV, flash MTD, ...) is +# shared by every ameba ARM chip from arch/arm/src/common/ameba/. Put it on +# VPATH + the include path so the CHIP_CSRCS filenames below resolve there +# (single source, no per-IC duplication). Truly IC-specific files (register +# drivers, IPC wiring, chip.h) stay in this chip directory. + +AMEBA_COMMON_SRC = $(TOPDIR)$(DELIM)arch$(DELIM)arm$(DELIM)src$(DELIM)common$(DELIM)ameba +VPATH += common$(DELIM)ameba +INCLUDES += ${INCDIR_PREFIX}$(AMEBA_COMMON_SRC) + +CHIP_CSRCS = ameba_start.c ameba_loguart.c ameba_irq.c ameba_timerisr.c +CHIP_CSRCS += ameba_allocateheap.c +CHIP_CSRCS += ameba_os_wrap.c + +ifeq ($(CONFIG_RTL8721DX_WIFI),y) +CHIP_CSRCS += ameba_wifi_init.c +# rt_kv_* symbols are referenced by the WHC host WiFi libraries -- always +# provide them (backed by the data filesystem, or stubbed if it is disabled). +CHIP_CSRCS += ameba_kv.c +ifeq ($(CONFIG_NET),y) +CHIP_CSRCS += ameba_wlan.c +endif +endif + +ifeq ($(CONFIG_RTL8721DX_FLASH_FS),y) +CHIP_CSRCS += ameba_flash_mtd.c +endif + +############################################################################ +# Realtek RTL8721Dx SDK integration +# +# Direction A (vendored-SDK model): NuttX owns the AP image2 and is the +# *primary* linker. The reduced image2 link reuses the vendor SDK chip +# libraries + ROM symbols + linker scripts; FreeRTOS / lwIP / mbedTLS / +# WiFi / BT / file-system / at_cmd / ota are all dropped (NuttX provides its +# own). This folds the prototype scripts (nuttx-ameba-ext/link_img2.sh and +# package_app.sh) into NuttX's native build: the linked `nuttx` ELF *is* the +# AP (km4) image2 .axf, and POSTBUILD (board scripts/Make.defs) packages it +# into a flashable app.bin. +# +# The vendor SDK (ameba-rtos) is treated as a referenced 3rd-party checkout: +# its sources, ROM symbol files and linker scripts are referenced at build time +# and never committed to NuttX. The pre-compiled chip archives + the build +# staging area are kept under boards/arm/rtl8721dx/pke8721daf/prebuilt/ +# (gitignored, not part of the NuttX source tree, as vendor blobs are kept +# out of NuttX). +############################################################################ + +# This IC (RTL8721Dx) maps to the SDK's amebadplus SoC subtree. Set before +# including the shared locator so future chips can reuse the one SDK checkout +# by selecting their own AMEBA_SOC_NAME. + +AMEBA_SOC_NAME = amebadplus + +# Locate (and, when unset, auto-fetch) the one shared ameba-rtos SDK. Shared +# with the board's scripts/Make.defs via common/ameba/ameba_sdk.mk so both make +# instances resolve $(AMEBA_SDK) identically. See that file for the two modes. + +include $(TOPDIR)$(DELIM)arch$(DELIM)arm$(DELIM)src$(DELIM)common$(DELIM)ameba$(DELIM)ameba_sdk.mk + +# SDK sub-trees referenced by the image2 link. + +AMEBA_SOC = $(AMEBA_SDK)/component/soc/$(AMEBA_SOC_NAME) +AMEBA_PROJ = $(AMEBA_SOC)/project +AMEBA_KM4_PROJ = $(AMEBA_PROJ)/project_km4 +AMEBA_SOC_LIB = $(AMEBA_KM4_PROJ)/lib/soc + +# Vendored prebuilt area inside the board (gitignored vendor blobs). + +AMEBA_PREBUILT = $(BOARD_DIR)$(DELIM)prebuilt +AMEBA_PREBUILT_LIBS = $(AMEBA_PREBUILT)$(DELIM)libs + +# --- Pre-compiled chip libraries kept in the reduced image2 ---------------- +# +# Vendor chip archives produced by a full SDK build, vendored under +# prebuilt/libs/. The chipinfo / pmc soc archives ship pre-compiled inside the +# SDK source tree, so they are taken directly from $(AMEBA_SDK). These are +# normal archives (members pulled on demand) and are appended to EXTRA_LIBS so +# they sit inside NuttX's standard --start-group/--end-group, resolving against +# each other and the NuttX libs. Everything unreferenced is dropped by +# --gc-sections, so listing an archive only costs link time, not image size. +# +# NOTE: the mbed-style "hal" layer (serial_api/gpio_api/...) is intentionally +# NOT linked -- NuttX provides its own uart_ops/ioexpander drivers, so the SDK +# hal is dead weight here (it contributed 0 objects). NuttX drivers sit +# directly on the fwlib register layer instead. + +# fwlib register-layer objects NuttX actually uses are compiled FROM SDK SOURCE +# into libameba_fwlib.a by the board PREBUILD (see scripts/Make.defs: +# AMEBA_FWLIB_SRCS), not vendored as a prebuilt blob -- so a bare checkout that +# only auto-fetched the SDK source can still link. --gc-sections keeps only the +# referenced members. Add fwlib sources there as new drivers need them. +EXTRA_LIBS += $(AMEBA_PREBUILT_LIBS)$(DELIM)libameba_fwlib.a + +# chipinfo / pmc ship pre-compiled INSIDE the SDK source tree (lib/soc), so a +# fresh SDK clone already has them -- linked directly from $(AMEBA_SDK), no +# vendored blob needed. (0 members pulled today, but kept for chip-init use.) +EXTRA_LIBS += $(AMEBA_SOC_LIB)$(DELIM)lib_chipinfo.a +EXTRA_LIBS += $(AMEBA_SOC_LIB)$(DELIM)lib_pmc.a + +# --- WiFi (WHC host) chip libraries (CONFIG_RTL8721DX_WIFI) ----------------- +# +# KM4-side host WiFi control libs from the pinned SDK. STA-PSK reduced set: +# the host controller (whc_ap), rtk_app helpers, security/crypto, the WPA-lite +# supplicant and coexistence -- eap/p2p/wps are NOT linked. The lwIP / event +# glue these expect is supplied by NuttX in libameba_wifi.a (built from a few +# SDK config sources + arch/.../wifi/ameba_wifi_depend.c by the board PREBUILD). +# Everything unreferenced is dropped by --gc-sections; all of these sit inside +# NuttX's --start-group so they resolve against each other and the NuttX libs. + +ifeq ($(CONFIG_RTL8721DX_WIFI),y) +AMEBA_APP_LIB = $(AMEBA_KM4_PROJ)/lib/application +EXTRA_LIBS += $(AMEBA_APP_LIB)$(DELIM)lib_wifi_whc_ap.a +EXTRA_LIBS += $(AMEBA_APP_LIB)$(DELIM)lib_wifi_rtk_app.a +EXTRA_LIBS += $(AMEBA_APP_LIB)$(DELIM)lib_wifi_com_sec.a +EXTRA_LIBS += $(AMEBA_APP_LIB)$(DELIM)lib_wpa_lite.a +EXTRA_LIBS += $(AMEBA_APP_LIB)$(DELIM)lib_coex.a +EXTRA_LIBS += $(AMEBA_PREBUILT_LIBS)$(DELIM)libameba_wifi.a +endif + +# crtbegin.o / crtend.o (asdk gcc runtime) and -lm / -lstdc++ from the SDK +# image2 link rule. crtbegin/crtend must be positional objects, so they are +# added via EXTRA_LIBS (which the link rule places inside the group, after the +# archives); the C++ / math libs are name-spec'd through EXTRA_LIBS too. + +CRT_DIR := $(dir $(shell $(CC) $(ARCHCPUFLAGS) -print-file-name=crtbegin.o)) + +EXTRA_LIBS += $(CRT_DIR)crtbegin.o +EXTRA_LIBS += $(CRT_DIR)crtend.o + +# --- Link flags reproducing link_img2.sh ----------------------------------- +# +# -u/-e app_start : force-pull the SDK's app_start object (it defines the +# image2 entry descriptor Img2EntryFun0 + app_start, +# which runs silicon init then calls NuttX's main()). +# --gc-sections : drop everything unreferenced (this is what removes +# FreeRTOS / lwIP / mbedTLS members of the chip libs). +# --defsym aliases : map NuttX's _sbss/_ebss/_sdata/_edata/_eronly onto +# the SDK linker-script symbols (the SDK ld owns the +# section layout). +# --no-enum-size-warning / --warn-common / --build-id=none / --cref: match the +# SDK link rule. + +LDFLAGS += -u app_start +LDFLAGS += -e app_start +LDFLAGS += --gc-sections +LDFLAGS += --no-enum-size-warning +LDFLAGS += --warn-common +LDFLAGS += --build-id=none +LDFLAGS += --cref +LDFLAGS += --defsym=_sbss=__bss_start__ +LDFLAGS += --defsym=_ebss=__bss_end__ +LDFLAGS += --defsym=_sdata=__sram_image2_start__ +LDFLAGS += --defsym=_edata=__sram_image2_start__ +LDFLAGS += --defsym=_eronly=__sram_image2_start__ + +# Emit a fresh map next to the ELF for verification (mirrors text.map). + +LDFLAGS += -Map=$(TOPDIR)$(DELIM)nuttx.map + +# -lm / -lstdc++ are name-spec libs: add them through LIBPATHS/EXTRA_LIBS so the +# linker pulls libstdc++ (C++ static-init support that crtbegin/crtend expect) +# and libm. They go last in the group via EXTRA_LIBS ordering above is fine +# because they are searched as archives. + +LDLIBS += -lm -lstdc++ + +# --- Auto-fetched SDK: intentionally NOT removed on distclean -------------- +# +# sdk.mk clones the pinned ameba-rtos into arch/arm/src/common/ameba/ameba-rtos +# (gitignored) when AMEBA_SDK is unset. It is a cache shared by all ameba ICs, +# NOT a build artifact, so it must SURVIVE `make distclean`: switching ICs does +# distclean + reconfigure + build, and re-cloning the multi-GB SDK every time is +# unacceptable. A pristine reset is a manual `rm -rf` of the checkout. diff --git a/arch/arm/src/rtl8721dx/ameba_allocateheap.c b/arch/arm/src/rtl8721dx/ameba_allocateheap.c new file mode 100644 index 00000000000..83005cb52f1 --- /dev/null +++ b/arch/arm/src/rtl8721dx/ameba_allocateheap.c @@ -0,0 +1,141 @@ +/**************************************************************************** + * arch/arm/src/rtl8721dx/ameba_allocateheap.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "arm_internal.h" +#include "chip.h" +#include "hardware/ameba_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Terminology. + * In the flat build (CONFIG_BUILD_FLAT=y), there is only a single heap + * accessed with the standard allocations (malloc/free). This heap is + * referred to as the user heap. Only the flat build with a single SRAM + * region is supported on the RTL8721Dx. + */ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* NuttX heap = all remaining KM4 on-chip SRAM. + * + * The KM4 image2 linker script (ameba_img2_all.ld) lays out this region for + * us: __bdram_heap_buffer_start__ is the first byte after NuttX's .bss, and + * __bdram_heap_buffer_size__ is an ABSOLUTE symbol whose VALUE is the number + * of bytes from there to the end of the KM4 SRAM region + * (__km4_bd_ram_end__). Using these gives NuttX every SRAM byte the SDK did + * not reserve, instead of a fixed compile-time buffer, and tracks the + * chip/board RAM automatically. + * + * Boards with PSRAM can add it as a second region via arm_addregion() using + * __psram_heap_buffer_start__/__psram_heap_buffer_size__ (zero on + * PKE8721DAF, which has no PSRAM). + */ + +extern uint8_t __bdram_heap_buffer_start__[]; +extern uint8_t __bdram_heap_buffer_size__[]; /* ABS symbol: value == bytes */ + +#define NUTTX_HEAP_BASE ((void *)__bdram_heap_buffer_start__) +#define NUTTX_HEAP_SIZE ((size_t)((uintptr_t)__bdram_heap_buffer_size__)) + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_allocate_heap + * + * Description: + * This function will be called to dynamically set aside the heap region. + * + * For the flat build, this returns the location and size of the single + * heap: all KM4 SRAM remaining after NuttX's .data/.bss, as computed by + * the SDK linker script. + * + ****************************************************************************/ + +void up_allocate_heap(void **heap_start, size_t *heap_size) +{ + *heap_start = NUTTX_HEAP_BASE; + *heap_size = NUTTX_HEAP_SIZE; + +#if defined(CONFIG_MM_KERNEL_HEAP) + *heap_size -= CONFIG_MM_KERNEL_HEAPSIZE; +#endif +} + +/**************************************************************************** + * Name: up_allocate_kheap + * + * Description: + * For the kernel build (CONFIG_BUILD_PROTECTED/KERNEL=y) with both kernel- + * and user-space heaps (CONFIG_MM_KERNEL_HEAP=y), this function allocates + * the kernel-space heap. + * + ****************************************************************************/ + +#if defined(CONFIG_MM_KERNEL_HEAP) +void up_allocate_kheap(void **heap_start, size_t *heap_size) +{ + /* Carve the kernel heap off the top of the SRAM heap region. */ + + *heap_start = (void *)((uintptr_t)NUTTX_HEAP_BASE + + (NUTTX_HEAP_SIZE - CONFIG_MM_KERNEL_HEAPSIZE)); + *heap_size = CONFIG_MM_KERNEL_HEAPSIZE; +} +#endif + +/**************************************************************************** + * Name: arm_addregion + * + * Description: + * Memory may be added in non-contiguous chunks. Additional chunks are + * added by calling this function. + * + ****************************************************************************/ + +#if CONFIG_MM_REGIONS > 1 +void arm_addregion(void) +{ +} +#endif diff --git a/arch/arm/src/rtl8721dx/ameba_app_start.c b/arch/arm/src/rtl8721dx/ameba_app_start.c new file mode 100644 index 00000000000..262d5e0962d --- /dev/null +++ b/arch/arm/src/rtl8721dx/ameba_app_start.c @@ -0,0 +1,303 @@ +/**************************************************************************** + * arch/arm/src/rtl8721dx/ameba_app_start.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * NuttX-owned image2 entry for the RTL8721Dx KM4 application core. + * + * This is a NuttX adaptation of the Realtek SDK's app_start() + * (component/soc/amebadplus/fwlib/ram_km4/ameba_app_start.c). It runs the + * same OS-independent silicon init the SDK boot performs -- enable cache, + * clear image2 BSS, init the NS vector table, MPU, brown-out detector, + * crystal/OSC calibration and the data-flash high-speed setup, then call + * NuttX's main(). The SDK FreeRTOS/newlib bring-up and its fault-handler + * redirect are intentionally omitted; NuttX provides its own scheduler, libc + * and crash reporting. + * + * Owning this file (not patching the SDK ameba_app_start.c) keeps the + * vendor SDK pristine. It is compiled with the SDK fwlib include set (see + * the board AMEBA_FWLIB_SRCS), not the NuttX header set, so it uses the SDK + * types and APIs directly. + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "ameba_soc.h" +#include "os_wrapper.h" +#include "os_wrapper_memory.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const char *const TAG = "APP"; + +/**************************************************************************** + * External Function Prototypes + ****************************************************************************/ + +extern int main(void); + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +u32 app_mpu_nocache_check(u32 mem_addr) +{ + mpu_region_config mpu_cfg; + + mpu_cfg.region_base = (uint32_t)__ram_nocache_start__; + mpu_cfg.region_size = __ram_nocache_end__ - __ram_nocache_start__; + + if ((mem_addr >= mpu_cfg.region_base) && + (mem_addr < (mpu_cfg.region_base + mpu_cfg.region_size))) + { + return TRUE; + } + else + { + return FALSE; + } +} + +/* KM4 has 4 secure mpu entries & 8 non-secure mpu entries. */ + +u32 app_mpu_nocache_init(void) +{ + mpu_region_config mpu_cfg; + u32 mpu_entry = 0; + + /* ROM code inside the CPU does not enter cache; set it RO so a NULL-ptr + * access faults. + */ + + mpu_entry = mpu_entry_alloc(); + mpu_cfg.region_base = 0x00000000; + mpu_cfg.region_size = 0x00080000; + mpu_cfg.xn = MPU_EXEC_ALLOW; + mpu_cfg.ap = MPU_UN_PRIV_RO; + mpu_cfg.sh = MPU_NON_SHAREABLE; + mpu_cfg.attr_idx = MPU_MEM_ATTR_IDX_NC; + mpu_region_cfg(mpu_entry, &mpu_cfg); + + mpu_entry = mpu_entry_alloc(); + mpu_cfg.region_base = (uint32_t)__ram_nocache_start__; + mpu_cfg.region_size = __ram_nocache_end__ - __ram_nocache_start__; + mpu_cfg.xn = MPU_EXEC_ALLOW; + mpu_cfg.ap = MPU_UN_PRIV_RW; + mpu_cfg.sh = MPU_NON_SHAREABLE; + mpu_cfg.attr_idx = MPU_MEM_ATTR_IDX_NC; + if (mpu_cfg.region_size >= 32) + { + mpu_region_cfg(mpu_entry, &mpu_cfg); + } + + return 0; +} + +#if defined(__GNUC__) +/* Provided for C++ support so the toolchain init does not fail to link. */ + +void _init(void) +{ +} +#endif + +void app_testmode_status(void) +{ + /* OTPC and SIC share one master port; OTPC uses it by default and SIC can + * use it once OTPC autoload is done. + */ + + if (SYSCFG_TRP_TestMode()) + { + if (SYSCFG_TRP_OTPBYP()) + { + RTK_LOGI(TAG, "Bypass OTP autoload\r\n"); + } + else + { + RTK_LOGI(TAG, "In Test mode: 0x%lx\r\n", SYSCFG_TRP_ICFG()); + } + } +} + +void app_bod_init(void) +{ + /* Only init BOD on the first power-on. */ + + if (BOOT_Reason() != 0) + { + return; + } + + BOR_ThresholdSet(0x8, 0x5); + RTK_LOGI(TAG, "BOR arises when supply voltage decreases under 2.57V and " + "recovers above 2.7V.\n"); + + BOR_ModeSet(BOR_RESET); + BOR_Enable(ENABLE); + + /* Avoid an unwanted extra reset. Default debounce delay is 100us + * (BOR_TDBC = 0x1); it takes 100us for the BOD output to sync to the + * digital circuit. + */ + + DelayUs(100); + RCC_PeriphClockCmd(APBPeriph_BOR, APBPeriph_CLOCK_NULL, ENABLE); +} + +void app_vdd1833_detect(void) +{ + ADC_InitTypeDef ADC_InitStruct; + u32 buf[16]; + u32 i = 0; + u32 temp = 0; + u32 data = 0; + + RCC_PeriphClockCmd(APBPeriph_ADC, APBPeriph_ADC_CLOCK, ENABLE); + + ADC_StructInit(&ADC_InitStruct); + ADC_InitStruct.ADC_OpMode = ADC_AUTO_MODE; + ADC_InitStruct.ADC_CvlistLen = 0; + ADC_InitStruct.ADC_Cvlist[0] = ADC_CH9; /* AVDD33 */ + ADC_Init(&ADC_InitStruct); + + ADC_Cmd(ENABLE); + ADC_ReceiveBuf(buf, 16); + ADC_Cmd(DISABLE); + + while (i < 16) + { + data += ADC_GET_DATA_GLOBAL(buf[i++]); + } + + data >>= 4; + + temp = HAL_READ32(SYSTEM_CTRL_BASE, REG_AON_RSVD_FOR_SW1); + if (data > 3000) /* 3000: about 2.4V */ + { + temp |= AON_BIT_WIFI_RF_1833_SEL; + } + else + { + temp &= ~AON_BIT_WIFI_RF_1833_SEL; + RTK_LOGI(TAG, "IO Power 1.8V\n"); + } + + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_AON_RSVD_FOR_SW1, temp); +} + +/* The image2 application entry point. */ + +void app_start(void) +{ + RTK_LOGI(TAG, "KM4 APP START \n"); + + /* Enable the non-secure cache. */ + + Cache_Enable(ENABLE); + + /* Clear the image2 BSS (covers NuttX's .bss too). */ + + _memset((void *)__bss_start__, 0, (__bss_end__ - __bss_start__)); + + /* NS vector table init (NuttX repoints VTOR at its own table in main()). */ + + irq_table_init(MSP_RAM_HP_NS); + + RTK_LOGI(TAG, "VTOR: %lx, VTOR_NS:%lx\n", SCB->VTOR, SCB_NS->VTOR); + +#if (defined CONFIG_WHC_HOST || defined CONFIG_WHC_NONE) + extern bool os_heap_add(u8 *start_addr, size_t heap_size); +#ifdef CONFIG_PSRAM_ALL_FOR_AP_HEAP + if (ChipInfo_PsramExists()) + { + os_heap_add((uint8_t *)__km4_bd_psram_start__, + (size_t)(__non_secure_psram_end__ - + __km4_bd_psram_start__)); + } +#endif +#endif + + /* Heap region setup (a no-op under NuttX, which owns its own heap). */ + + rtos_mem_init(); + + RTK_LOGI(TAG, "VTOR: %lx, VTOR_NS:%lx\n", SCB->VTOR, SCB_NS->VTOR); + + app_testmode_status(); + data_flash_highspeed_setup(); + + cmse_address_info_t cmse_address_info = cmse_TT((void *)app_start); + RTK_LOGI(TAG, "IMG2 SECURE STATE: %d\n", cmse_address_info.flags.secure); + + SystemCoreClockUpdate(); + + XTAL_INIT(); + + if (SYSCFG_CHIPType_Get() == CHIP_TYPE_ASIC_POSTSIM) + { + /* Only ASIC needs OSC calibration. */ + + OSC4M_Init(); + OSC4M_Calibration(30000); + if ((((BOOT_Reason()) & AON_BIT_RSTF_DSLP) == FALSE) && + (RTCIO_IsEnabled() == FALSE)) + { + OSC131K_Calibration(30000); /* PPM=30000=3% (7.5ms) */ + } + } + + mpu_init(); + app_mpu_nocache_init(); + + app_vdd1833_detect(); + + app_bod_init(); + + /* Force SP alignment to 8 bytes. */ + + __asm("ldr r1, =#0xFFFFFFF8\n" + "mov r0, sp \n" + "and r0, r0, r1\n" + "mov sp, r0\n"); + + main(); +} + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* Image2 entry descriptor: the SDK bootloader (image1) jumps to ram_start. + * A NULL ram_wakeup keeps the SDK deep-sleep (SOCPS) path out of the image. + */ + +IMAGE2_ENTRY_SECTION +RAM_START_FUNCTION Img2EntryFun0 = +{ + app_start, + NULL, + (u32)NewVectorTable +}; diff --git a/arch/arm/src/rtl8721dx/ameba_board.mk b/arch/arm/src/rtl8721dx/ameba_board.mk new file mode 100644 index 00000000000..fe08c1b4253 --- /dev/null +++ b/arch/arm/src/rtl8721dx/ameba_board.mk @@ -0,0 +1,418 @@ +############################################################################ +# arch/arm/src/rtl8721dx/ameba_board.mk +# +# Shared board-build definitions for the RTL8721Dx (Ameba WHC) -- the SDK +# include sets, fwlib/WiFi source lists, image2 linker-script generation, +# PREBUILD and POSTBUILD. A board's scripts/Make.defs is a thin wrapper that +# just `include`s this file, so every RTL8721Dx board shares one definition +# (and a second board on this IC needs no copy). Board-specific paths come +# from $(BOARD_DIR), so each board keeps its own prebuilt/ staging dir. +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include $(TOPDIR)/.config +include $(TOPDIR)/tools/Config.mk + +# Resolve (and, when AMEBA_SDK is unset, auto-fetch) the one shared ameba-rtos +# SDK, and prepend the SDK-matched asdk toolchain to PATH. This MUST precede +# Toolchain.defs: that file probes the compiler version to compute flags (e.g. +# --param=min-pagesize=0 on newer GCC), so the SDK toolchain has to be on PATH +# first or the flags get computed for the wrong compiler. AMEBA_SOC_NAME +# selects this IC's SoC subtree. + +AMEBA_SOC_NAME = amebadplus +include $(TOPDIR)/arch/arm/src/common/ameba/ameba_sdk.mk + +include $(TOPDIR)/arch/arm/src/armv8-m/Toolchain.defs + +############################################################################ +# Linker script +# +# The `nuttx` ELF must be linked as the Realtek KM4 image2 .axf, so the link +# uses the *SDK's own* layout + image2 + ROM-symbol linker scripts (exactly as +# the prototype link_img2.sh did): +# +# ameba_layout.ld (included by ameba_img2_all.ld) +# ameba_img2_all.ld +# ameba_rom_symbol_acut_s.ld (CONFIG_LINK_ROM_SYMB) +# +# ameba_img2_all.ld is C-preprocessed (it #includes ameba_layout.ld and the +# generated platform_autoconf.h), then ameba_rom_symbol_acut_s.ld is appended. +# Finally NuttX's own .vectors orphan section is folded into the loadable SRAM +# data region so the (large power-of-two aligned) vector table does not land in +# and overflow the tiny fixed KM4_IMG2_ENTRY region. This reproduces the +# generated rlx8721d.ld byte-for-byte without editing any SDK source file +# (the SDK tree stays read-only). +# +# The combined script is generated into scripts/ as ld.script and used as the +# single ARCHSCRIPT. ld.script content is already fully expanded (no macros, +# no #include), so the standard ARCHSCRIPT cpp .tmp pass is idempotent. +############################################################################ + +# SDK linker-script sources and the vendored, config-derived autoconf header. + +AMEBA_SOC = $(AMEBA_SDK)/component/soc/$(AMEBA_SOC_NAME) +AMEBA_PROJ = $(AMEBA_SOC)/project +AMEBA_KM4_LD = $(AMEBA_PROJ)/project_km4/ld +AMEBA_LAYOUT_LD = $(AMEBA_PROJ)/ameba_layout.ld +AMEBA_IMG2_LD = $(AMEBA_KM4_LD)/ameba_img2_all.ld +AMEBA_ROM_LD = $(AMEBA_KM4_LD)/ameba_rom_symbol_acut_s.ld + +AMEBA_PREBUILT = $(BOARD_DIR)$(DELIM)prebuilt +AMEBA_PREBUILT_LIBS = $(AMEBA_PREBUILT)$(DELIM)libs +AMEBA_AUTOCONF = $(AMEBA_PREBUILT)$(DELIM)platform_autoconf.h + +# fwlib register-layer objects, compiled FROM SDK SOURCE into libameba_fwlib.a +# (linked via arch/.../rtl8721dx/Make.defs EXTRA_LIBS) instead of vendoring a +# prebuilt blob -- so a bare checkout that only auto-fetched the SDK source can +# still link. Grow AMEBA_FWLIB_SRCS as NuttX drivers call more fwlib functions; +# --gc-sections keeps only what is referenced. AMEBA_FWLIB_INC is the SDK's +# fwlib include set, kept scoped to this compile so SDK headers never leak into +# the NuttX core build (where they would clash). + +AMEBA_FWLIB_A = $(AMEBA_PREBUILT_LIBS)$(DELIM)libameba_fwlib.a +AMEBA_FWLIB_SRCS = $(AMEBA_SOC)/fwlib/ram_common/ameba_arch.c \ + $(AMEBA_SOC)/fwlib/ram_common/ameba_loguart.c \ + $(AMEBA_SOC)/fwlib/ram_common/ameba_ipc_api.c \ + $(AMEBA_SOC)/fwlib/ram_common/ameba_ipc_ram.c \ + $(AMEBA_SOC)/misc/ameba_pmu.c \ + $(AMEBA_SOC)/swlib/log.c \ + $(AMEBA_SOC)/swlib/sscanf_minimal.c + +# NuttX owns the image2 entry: arch/arm/src/rtl8721dx/ameba_app_start.c is a +# NuttX adaptation of the SDK app_start() that runs all OS-independent silicon +# init (cache/MPU/brown-out/data-flash/...), zeroes BSS, then calls NuttX's +# main() (ameba_start.c). It is built with the SDK fwlib include set, so the +# fwlib sources it pulls in are listed alongside it. +AMEBA_FWLIB_SRCS += $(TOPDIR)/arch/arm/src/rtl8721dx/ameba_app_start.c \ + $(AMEBA_SOC)/fwlib/ram_common/ameba_mpu_ram.c \ + $(AMEBA_SOC)/fwlib/ram_common/ameba_bor.c \ + $(AMEBA_SOC)/fwlib/ram_common/ameba_reset.c \ + $(AMEBA_SOC)/fwlib/ram_common/ameba_clk.c \ + $(AMEBA_SOC)/fwlib/ram_common/ameba_rtc_io.c \ + $(AMEBA_SOC)/fwlib/ram_common/ameba_adc.c \ + $(AMEBA_SOC)/fwlib/ram_km4/ameba_data_flashclk.c + +# Flash primitives (FLASH_ReadStream/WriteStream/EraseXIP) for the MTD data +# filesystem. These self-lock against the NP core (inter-core HW semaphore + +# IPC pause) and disable IRQs around erase/program. +ifeq ($(CONFIG_RTL8721DX_FLASH_FS),y) +AMEBA_FWLIB_SRCS += $(AMEBA_SOC)/fwlib/ram_common/ameba_flash_ram.c +endif +AMEBA_FWLIB_INC = -mcmse \ + -I$(TOPDIR)/arch/arm/src/common/ameba/sdk_shim \ + -I$(AMEBA_SOC)/fwlib/include \ + -I$(AMEBA_SOC)/fwlib/include/rom \ + -I$(AMEBA_SOC)/swlib \ + -I$(AMEBA_SOC)/hal/include \ + -I$(AMEBA_SOC)/hal/src \ + -I$(AMEBA_SDK)/component/soc/common/include \ + -I$(AMEBA_SDK)/component/soc/common/include/cmsis \ + -I$(AMEBA_SOC)/app/monitor/include \ + -I$(AMEBA_SDK)/component/soc/usrcfg/$(AMEBA_SOC_NAME)/include \ + -I$(AMEBA_SDK)/component/soc/usrcfg/common \ + -I$(AMEBA_SOC)/misc \ + -I$(AMEBA_SDK)/component/os/os_wrapper/include \ + -I$(AMEBA_SDK)/component/soc/common/crashdump/include \ + -I$(AMEBA_PREBUILT) + +# --- WiFi (WHC host) glue lib (CONFIG_RTL8721DX_WIFI) ---------------------- +# +# libameba_wifi.a holds the NuttX-side glue the precompiled host WiFi libs +# expect: a couple of SDK config sources (the user WiFi config + the task-size +# table, compiled from source so their struct layouts match the libs' ABI) and +# the NuttX lwIP/event shim (arch/.../wifi/ameba_wifi_depend.c). It is built +# with the vendor WiFi include set -- which collides with NuttX's own headers +# (lwIP vs NuttX atomic.h, ...) -- so it is compiled in its own PREBUILD loop +# (like libameba_fwlib.a), NOT through the normal arch CSRCS path. The shim +# include dir comes FIRST so its minimal shadows the SDK's. +AMEBA_WIFI_A = $(AMEBA_PREBUILT_LIBS)$(DELIM)libameba_wifi.a +AMEBA_WIFI_DIR = $(TOPDIR)$(DELIM)arch$(DELIM)arm$(DELIM)src$(DELIM)common$(DELIM)ameba$(DELIM)wifi +AMEBA_WIFI_SRCS = $(AMEBA_SDK)/component/soc/usrcfg/$(AMEBA_SOC_NAME)/ameba_wificfg.c \ + $(AMEBA_SDK)/component/wifi/common/rtw_task_size.c \ + $(AMEBA_SDK)/component/wifi/common/rtw_event.c \ + $(AMEBA_SDK)/component/soc/common/diagnose/ameba_diagnose_none.c \ + $(AMEBA_SDK)/component/wifi/wpa_supplicant/wpa_supplicant/wifi_p2p_disable.c \ + $(AMEBA_WIFI_DIR)/ameba_wifi_depend.c \ + $(AMEBA_WIFI_DIR)/ameba_wifi.c +# +# Force-include the SDK autoconf so EVERY wifi source sees CONFIG_WHC_HOST / +# CONFIG_WHC_INTF_IPC / ... (the SDK build force-includes platform_autoconf.h +# globally). Without this, sources that don't #include it themselves silently +# compile the wrong #if branch -- e.g. rtw_task_size.c's wifi_set_task_size() +# becomes empty, leaving g_rtw_task_size all-zero, so the WHC host event tasks +# are created with stack size 0 and never run -> wifi_connect() blocks forever +# waiting for the join-status event. +AMEBA_WIFI_INC = -include $(AMEBA_AUTOCONF) \ + -include $(AMEBA_WIFI_DIR)/include/ameba_lwip_off.h \ + -I$(AMEBA_WIFI_DIR)/include \ + -I$(AMEBA_WIFI_DIR)/.. \ + -I$(AMEBA_SDK)/component/wifi/api \ + -I$(AMEBA_SDK)/component/wifi/common \ + -I$(AMEBA_SDK)/component/wifi/driver/include \ + -I$(AMEBA_SDK)/component/wifi/driver/intf \ + -I$(AMEBA_SDK)/component/wifi/whc \ + -I$(AMEBA_SDK)/component/wifi/whc/whc_host_rtos \ + -I$(AMEBA_SDK)/component/wifi/whc/whc_host_rtos/ipc \ + -I$(AMEBA_SDK)/component/at_cmd \ + -I$(AMEBA_SDK)/component/wifi/wpa_supplicant/wpa_supplicant \ + -I$(AMEBA_SDK)/component/wifi/wpa_supplicant/wpa_lite \ + -I$(AMEBA_SDK)/component/wifi/wpa_supplicant/wpa_lite/rom \ + -I$(AMEBA_SDK)/component/wifi/wpa_supplicant/src \ + -I$(AMEBA_SDK)/component/wifi/wpa_supplicant/src/utils \ + -I$(AMEBA_SDK)/component/wifi/rtk_app/wifi_auto_reconnect \ + -I$(AMEBA_SDK)/component/network \ + -I$(AMEBA_SDK)/component/soc/common/diagnose \ + -I$(AMEBA_SOC)/app/monitor/include \ + -I$(AMEBA_SOC)/fwlib/include \ + -I$(AMEBA_SOC)/fwlib/include/rom \ + -I$(AMEBA_SOC)/swlib \ + -I$(AMEBA_SOC)/hal/include \ + -I$(AMEBA_SOC)/misc \ + -I$(AMEBA_SDK)/component/soc/common/include \ + -I$(AMEBA_SDK)/component/soc/common/include/cmsis \ + -I$(AMEBA_SDK)/component/os/os_wrapper/include \ + -I$(AMEBA_SDK)/component/soc/usrcfg/$(AMEBA_SOC_NAME)/include \ + -I$(AMEBA_SDK)/component/soc/usrcfg/common \ + -I$(AMEBA_SDK)/component/ssl/mbedtls-3.6.5/include \ + -I$(AMEBA_PREBUILT) + +# The combined script is generated under prebuilt/ (gitignored) by PREBUILD +# (below) and used as the single ARCHSCRIPT. Its content is already fully +# expanded (no macros, no #include), so the standard ARCHSCRIPT cpp .tmp pass +# is idempotent. ARCHSCRIPT must name a plain file here (not a rule target): +# defining an explicit recipe in this globally-included Make.defs would hijack +# the default make goal, so the generation is done in PREBUILD instead. + +GENLDSCRIPT = $(AMEBA_PREBUILT)$(DELIM)ld.script.gen + +ARCHSCRIPT += $(GENLDSCRIPT) + +# NP (network core, km0 on this IC) image + bootloader. AP/NP share many SDK +# sources, so the NP image must come from the SAME pinned SDK -- a fixed release +# bin would drift. +# +# The NP (km0) image and boot are ALWAYS (re)built from the pinned SDK source on +# every NuttX build -- no "use a stale vendored blob" shortcut -- so the two +# cores can never drift out of alignment. The NP build runs AFTER the AP (km4 / +# NuttX) link because the SDK WiFi "noused" generator strips any host WiFi API +# the AP image does not reference (calling a stripped API later deadlocks the NP +# -- "Compile NP after AP!"). So it is a POSTBUILD step handed NuttX's own +# disassembly (target_img2.asm, produced earlier in POSTBUILD) as the AP image +# via AMEBA_AP_ASM. +# +# AMEBA_PY_SOC is the ameba.py SoC identifier for this board (public name), +# distinct from AMEBA_SOC_NAME (the SDK soc/ subdir). +AMEBA_PY_SOC = RTL8721Dx +AMEBA_BUILD_NP_SH = $(AMEBA_COMMON_DIR)$(DELIM)tools$(DELIM)ameba_build_np.sh + +# platform_autoconf.h is regenerated from the SDK menuconfig on every build (see +# ameba_gen_autoconf.sh) -- the SDK Kconfig is the single source of truth for +# the flash layout (CONFIG_FLASH_VFS1_*) and feature switches (CONFIG_WHC_* ...). +# AMEBA_AP_PROJECT is the AP-core SDK project subdir (km4 on amebadplus). +AMEBA_AP_PROJECT = km4 +AMEBA_GEN_AUTOCONF = $(AMEBA_COMMON_DIR)$(DELIM)tools$(DELIM)ameba_gen_autoconf.sh +AMEBA_NP_PREBUILD = true +AMEBA_NP_POSTBUILD = $(AMEBA_BUILD_NP_SH) $(AMEBA_SDK) $(AMEBA_PY_SOC) \ + $(AMEBA_PREBUILT) $(AMEBA_PKGDIR)$(DELIM)target_img2.asm \ + km0 $(AMEBA_AP_PROJECT) + +# PREBUILD -- (re)generate the combined image2 linker script before the build. +# +# ameba_img2_all.ld is C-preprocessed (it #includes ameba_layout.ld and the +# vendored, config-derived platform_autoconf.h, staged as +# project_km4/platform_autoconf.h on the include path), then +# ameba_rom_symbol_acut_s.ld is appended, then NuttX's .vectors orphan is folded +# into the loadable SRAM data region. This reproduces the SDK-generated +# rlx8721d.ld without editing any SDK source file. + +define PREBUILD + $(Q) test -n "$(AMEBA_SDK)" || \ + { echo "ERROR: AMEBA_SDK is not set. Export it to your ameba-rtos checkout."; exit 1; } + $(Q) $(AMEBA_FETCH_TOOLCHAIN) $(AMEBA_SDK) $(AMEBA_TOOLCHAIN_DIR) + $(Q) $(AMEBA_SETUP_ENV) $(AMEBA_SDK) $(AMEBA_TOOLCHAIN_DIR) + $(Q) $(AMEBA_GEN_AUTOCONF) $(AMEBA_SDK) $(AMEBA_PY_SOC) $(AMEBA_AP_PROJECT) \ + $(AMEBA_AUTOCONF) + $(Q) $(AMEBA_NP_PREBUILD) + $(Q) echo "GEN: libameba_fwlib.a (fwlib from SDK source)" + $(Q) mkdir -p $(AMEBA_PREBUILT_LIBS)$(DELIM)fwlib_obj + $(Q) rebuild_fwlib=0; \ + for src in $(AMEBA_FWLIB_SRCS); do \ + obj=$(AMEBA_PREBUILT_LIBS)/fwlib_obj/`basename $$src .c`.o; \ + if [ "$$src" -nt "$$obj" ] 2>/dev/null || [ ! -f "$$obj" ]; then \ + $(CC) $(ARCHCPUFLAGS) -Os -ffunction-sections -fdata-sections \ + $(AMEBA_FWLIB_INC) -c $$src -o $$obj || exit 1; \ + rebuild_fwlib=1; \ + fi; \ + done; \ + if [ "$$rebuild_fwlib" = "1" ] || [ ! -f "$(AMEBA_FWLIB_A)" ]; then \ + $(CROSSDEV)ar crs $(AMEBA_FWLIB_A) $(AMEBA_PREBUILT_LIBS)/fwlib_obj/*.o; \ + fi + $(Q) if [ "$(CONFIG_RTL8721DX_WIFI)" = "y" ]; then \ + echo "GEN: libameba_wifi.a (WHC host glue from SDK source + NuttX shim)"; \ + mkdir -p $(AMEBA_PREBUILT_LIBS)$(DELIM)wifi_obj; \ + rebuild_wifi=0; \ + for src in $(AMEBA_WIFI_SRCS); do \ + obj=$(AMEBA_PREBUILT_LIBS)/wifi_obj/`basename $$src .c`.o; \ + if [ "$$src" -nt "$$obj" ] 2>/dev/null || [ ! -f "$$obj" ]; then \ + $(CC) $(ARCHCPUFLAGS) -Os -ffunction-sections -fdata-sections \ + $(AMEBA_WIFI_INC) -c $$src -o $$obj || exit 1; \ + rebuild_wifi=1; \ + fi; \ + done; \ + if [ "$$rebuild_wifi" = "1" ] || [ ! -f "$(AMEBA_WIFI_A)" ]; then \ + $(CROSSDEV)ar crs $(AMEBA_WIFI_A) $(AMEBA_PREBUILT_LIBS)/wifi_obj/*.o; \ + fi; \ + fi + $(Q) echo "GEN: ld.script.gen (Ameba AP km4 image2)" + $(Q) mkdir -p $(AMEBA_PREBUILT)$(DELIM)project_km4 + $(Q) cp $(AMEBA_AUTOCONF) $(AMEBA_PREBUILT)$(DELIM)project_km4$(DELIM)platform_autoconf.h + $(Q) $(CC) -E -P -xc -c $(AMEBA_IMG2_LD) -o $(GENLDSCRIPT) -I $(AMEBA_PREBUILT) + $(Q) cat $(AMEBA_ROM_LD) >> $(GENLDSCRIPT) + $(Q) sed -i 's|^\([[:space:]]*\)\*(\.data\*)|\1*(.vectors*)\n\1*(.data*)|' $(GENLDSCRIPT) +endef + +CFLAGS := $(ARCHCFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) +CPICFLAGS = $(ARCHPICFLAGS) $(CFLAGS) +CXXFLAGS := $(ARCHCXXFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) +CXXPICFLAGS = $(ARCHPICFLAGS) $(CXXFLAGS) +CPPFLAGS := $(ARCHINCLUDES) $(ARCHDEFINES) + +CFLAGS += $(EXTRAFLAGS) +CPPFLAGS += $(EXTRAFLAGS) + +# VFS1 data-partition geometry for the littlefs MTD comes from the SDK flash +# layout (CONFIG_FLASH_VFS1_OFFSET/SIZE in the regenerated platform_autoconf.h), +# so ameba_flash_mtd.c never hardcodes it. Extract the two values and pass them +# as neutral -D macros (a NuttX C file must not force-include the SDK autoconf). +# The header falls back to the vendor default if these are absent (e.g. the very +# first parse on a clean clone, before PREBUILD has generated the autoconf). +ifneq ($(wildcard $(AMEBA_AUTOCONF)),) +AMEBA_VFS1_OFFSET := $(strip $(shell awk '$$2=="CONFIG_FLASH_VFS1_OFFSET"{print $$3}' $(AMEBA_AUTOCONF))) +AMEBA_VFS1_SIZE := $(strip $(shell awk '$$2=="CONFIG_FLASH_VFS1_SIZE"{print $$3}' $(AMEBA_AUTOCONF))) +CFLAGS += $(if $(AMEBA_VFS1_OFFSET),-DAMEBA_FLASH_VFS1_OFFSET_XIP=$(AMEBA_VFS1_OFFSET)) +CFLAGS += $(if $(AMEBA_VFS1_SIZE),-DAMEBA_FLASH_VFS1_SIZE_CFG=$(AMEBA_VFS1_SIZE)) +endif + +AFLAGS := $(CFLAGS) -D__ASSEMBLY__ + +# NXFLAT module definitions + +NXFLATLDFLAGS1 = -r -d -warn-common +NXFLATLDFLAGS2 = $(NXFLATLDFLAGS1) -T$(TOPDIR)$(DELIM)binfmt$(DELIM)libnxflat$(DELIM)gnu-nxflat-pcrel.ld -no-check-sections +LDNXFLATFLAGS = -e main -s 2048 + +############################################################################ +# POSTBUILD -- package the linked image2 into a flashable app.bin +# +# Runs after `nuttx` (== the KM4 image2 .axf) is linked. This folds the +# prototype package_app.sh into NuttX's build: +# +# 1. Replicate the SDK image2 postbuild prologue (copy map/axf, nm/objdump). +# 2. Run the SDK AP (km4) image2 postbuild.cmake (axf2bin) -> km4_image2_all.bin. +# 3. Run the SDK project firmware_package postbuild.cmake combining the +# freshly built AP (km4) image2 with the freshly built NP (km0) image2 -> +# app.bin, copied into $(TOPDIR). +# +# The NP (km0) image2 is (re)built from the pinned SDK source in the NP POSTBUILD +# step above (NuttX only owns the AP / km4 image2). The SDK scripts/cmake/python +# are invoked read-only; only artefacts under the build staging dir are written. +# +# Tooling resolved from the asdk toolchain on PATH and the python interpreter +# ameba_setup_env.sh resolved (recorded in .amebapy/bindir: a real SDK .venv +# when one exists, otherwise a system-python3 shim). CMAKE may be overridden +# via the CMAKE environment variable; it defaults to `cmake` on PATH. That bin +# dir is prepended to PATH for the SDK cmake/axf2bin steps so `python`/`python3` +# resolve to the deps-carrying interpreter. It is read at recipe run time (the +# `$$(cat ...)` defers until after ameba_setup_env.sh has written the file). +############################################################################ + +AMEBA_VENV_BIN = $$(cat $(AMEBA_SDK)/.amebapy/bindir 2>/dev/null) + +CMAKE ?= cmake +NM ?= $(CROSSDEV)nm +OBJDUMP ?= $(CROSSDEV)objdump +STRIP ?= $(CROSSDEV)strip +OBJCOPY ?= $(CROSSDEV)objcopy +SIZE ?= $(CROSSDEV)size + +AMEBA_SOC_PROJ = $(AMEBA_SOC)/project +AMEBA_KM4_PROJ = $(AMEBA_SOC_PROJ)/project_km4 + +# Staging dir for the SDK packaging steps (under the board, gitignored). + +AMEBA_PKGDIR = $(AMEBA_PREBUILT)$(DELIM)pkg + +define POSTBUILD + $(Q) echo "PACK: app.bin (Ameba AP km4 image2 + NP km0 image2)" + $(Q) test -n "$(AMEBA_SDK)" || \ + { echo "ERROR: AMEBA_SDK is not set"; exit 1; } + $(Q) $(AMEBA_SETUP_ENV) $(AMEBA_SDK) $(AMEBA_TOOLCHAIN_DIR) + $(Q) rm -rf $(AMEBA_PKGDIR) + $(Q) mkdir -p $(AMEBA_PKGDIR) + $(Q) cp $(TOPDIR)$(DELIM)nuttx $(AMEBA_PKGDIR)$(DELIM)target_img2.axf + $(Q) $(NM) $(AMEBA_PKGDIR)$(DELIM)target_img2.axf | sort \ + > $(AMEBA_PKGDIR)$(DELIM)target_img2.map + $(Q) $(OBJDUMP) -d $(AMEBA_PKGDIR)$(DELIM)target_img2.axf \ + > $(AMEBA_PKGDIR)$(DELIM)target_img2.asm + $(Q) $(AMEBA_NP_POSTBUILD) + $(Q) cp $(AMEBA_PKGDIR)$(DELIM)target_img2.axf \ + $(AMEBA_PKGDIR)$(DELIM)target_pure_img2.axf + $(Q) $(STRIP) $(AMEBA_PKGDIR)$(DELIM)target_pure_img2.axf + $(Q) cp $(AMEBA_PREBUILT)$(DELIM)config_km4 $(AMEBA_PKGDIR)$(DELIM).config_km4 + $(Q) cp $(AMEBA_PREBUILT)$(DELIM)config_fw $(AMEBA_PKGDIR)$(DELIM).config + $(Q) cp $(AMEBA_PREBUILT)$(DELIM)km0_image2_all.bin \ + $(AMEBA_PKGDIR)$(DELIM)km0_image2_all.bin + $(Q) printf '{\n "soc": {\n "name": "RTL8721Dx"\n }\n}\n' \ + > $(AMEBA_PKGDIR)$(DELIM)soc_info.json + $(Q) TARGET_SOC=RTL8721Dx PATH=$(AMEBA_VENV_BIN):$$PATH $(CMAKE) \ + -Dc_BASEDIR=$(AMEBA_SDK) \ + -Dc_CMAKE_FILES_DIR=$(AMEBA_SDK)/cmake \ + -Dc_SOC_PROJECT_DIR=$(AMEBA_SOC_PROJ) \ + -Dc_MCU_PROJECT_DIR=$(AMEBA_KM4_PROJ) \ + -Dc_MCU_PROJECT_NAME=km4 \ + -Dc_MCU_KCONFIG_FILE=$(AMEBA_PKGDIR)$(DELIM).config_km4 \ + -Dc_SDK_IMAGE_TARGET_DIR=$(AMEBA_PKGDIR) \ + -DKM4_BUILDDIR= \ + -DFINAL_IMAGE_DIR=$(AMEBA_PKGDIR) \ + -DBUILD_TYPE=NONE -DANALYZE_MP_IMG=0 -DDAILY_BUILD=0 \ + -DEXTERN_DIR=$(AMEBA_PKGDIR) -DCODE_ANALYZE_RETRY= \ + -DIMAGESCRIPTDIR=$(AMEBA_SDK)/tools/image_scripts \ + -DCMAKE_SIZE=$(SIZE) -DCMAKE_OBJCOPY=$(OBJCOPY) \ + -P $(AMEBA_KM4_PROJ)/make/image2/postbuild.cmake + $(Q) TARGET_SOC=RTL8721Dx PATH=$(AMEBA_VENV_BIN):$$PATH $(CMAKE) \ + -Dc_BASEDIR=$(AMEBA_SDK) \ + -Dc_CMAKE_FILES_DIR=$(AMEBA_SDK)/cmake \ + -Dc_MCU_KCONFIG_FILE=$(AMEBA_PKGDIR)$(DELIM).config \ + -Dc_SOC_PROJECT_DIR=$(AMEBA_SOC_PROJ) \ + -Dc_SDK_IMAGE_TARGET_DIR= \ + -Dc_IMAGE_OUTPUT_DIR=$(AMEBA_PKGDIR) \ + -Dc_APP_BINARY_NAME=app.bin \ + -Dc_IMAGE1_ALL_FILES= \ + -Dc_IMAGE2_ALL_FILES="$(AMEBA_PKGDIR)/km0_image2_all.bin;$(AMEBA_PKGDIR)/km4_image2_all.bin" \ + -Dc_IMAGE3_ALL_FILES= \ + -DFINAL_IMAGE_DIR=$(TOPDIR) \ + -DANALYZE_MP_IMG=0 -DEXTERN_DIR=$(AMEBA_PKGDIR) \ + -P $(AMEBA_SOC_PROJ)/postbuild.cmake + $(Q) cp $(AMEBA_PREBUILT)$(DELIM)boot.bin $(TOPDIR)$(DELIM)boot.bin + $(Q) cp $(AMEBA_PREBUILT)$(DELIM)km0_image2_all.bin \ + $(TOPDIR)$(DELIM)km0_image2_all.bin + $(Q) echo "PACK: wrote $(TOPDIR)$(DELIM){app.bin,boot.bin,km0_image2_all.bin}" +endef diff --git a/arch/arm/src/rtl8721dx/ameba_irq.c b/arch/arm/src/rtl8721dx/ameba_irq.c new file mode 100644 index 00000000000..876200c73b4 --- /dev/null +++ b/arch/arm/src/rtl8721dx/ameba_irq.c @@ -0,0 +1,382 @@ +/**************************************************************************** + * arch/arm/src/rtl8721dx/ameba_irq.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include "arm_internal.h" +#include "ameba_irq.h" +#include "nvic.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define NVIC_ENA_OFFSET (0) +#define NVIC_CLRENA_OFFSET (NVIC_IRQ0_31_CLEAR - NVIC_IRQ0_31_ENABLE) + +#define DEFPRIORITY32 (NVIC_SYSH_PRIORITY_DEFAULT << 24 | \ + NVIC_SYSH_PRIORITY_DEFAULT << 16 | \ + NVIC_SYSH_PRIORITY_DEFAULT << 8 | \ + NVIC_SYSH_PRIORITY_DEFAULT) + +/* Size of the interrupt stack allocation */ + +#define INTSTACK_ALLOC (CONFIG_SMP_NCPUS * INTSTACK_SIZE) + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_FEATURES +static int ameba_nmi(int irq, void *context, void *arg) +{ + up_irq_save(); + _err("PANIC!!! NMI received\n"); + PANIC(); + return 0; +} + +static int ameba_pendsv(int irq, void *context, void *arg) +{ +#ifndef CONFIG_ARCH_HIPRI_INTERRUPT + up_irq_save(); + _err("PANIC!!! PendSV received\n"); + PANIC(); +#endif + return 0; +} + +static int ameba_reserved(int irq, void *context, void *arg) +{ + up_irq_save(); + _err("PANIC!!! Reserved interrupt\n"); + PANIC(); + return 0; +} +#endif + +/**************************************************************************** + * Name: ameba_prioritize_syscall + * + * Description: + * Set the priority of an exception. This function may be needed + * internally even if support for prioritized interrupts is not enabled. + * + ****************************************************************************/ + +static inline void ameba_prioritize_syscall(int priority) +{ + uint32_t regval; + + /* SVCALL is system handler 11 */ + + regval = getreg32(NVIC_SYSH8_11_PRIORITY); + regval &= ~NVIC_SYSH_PRIORITY_PR11_MASK; + regval |= (priority << NVIC_SYSH_PRIORITY_PR11_SHIFT); + putreg32(regval, NVIC_SYSH8_11_PRIORITY); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_prioritize_irq + * + * Description: + * Set the priority of an IRQ. This function may be needed internally + * even if support for prioritized interrupts is not enabled. + * + ****************************************************************************/ + +int up_prioritize_irq(int irq, int priority) +{ + uint32_t regaddr; + uint32_t regval; + int shift; + + DEBUGASSERT(irq >= 0 && irq < NR_IRQS && + (unsigned)priority <= NVIC_SYSH_PRIORITY_MIN); + + if (irq < 16) + { + /* NVIC_SYSH_PRIORITY() maps {0..15} to one of three priority + * registers (0-3 are invalid) + */ + + regaddr = NVIC_SYSH_PRIORITY(irq); + irq -= 4; + } + else + { + /* NVIC_IRQ_PRIORITY() maps {0..} to one of many priority registers */ + + irq -= 16; + regaddr = NVIC_IRQ_PRIORITY(irq); + } + + regval = getreg32(regaddr); + shift = ((irq & 3) << 3); + regval &= ~(0xff << shift); + regval |= (priority << shift); + putreg32(regval, regaddr); + + return OK; +} + +/**************************************************************************** + * Name: up_irqinitialize + * + * Description: + * This function is called by up_initialize() during the bring-up of the + * system. It is the responsibility of this function to but the interrupt + * subsystem into the working and ready state. + * + ****************************************************************************/ + +void up_irqinitialize(void) +{ + uint32_t regaddr; + int num_priority_registers; + int i; + + /* Disable all interrupts */ + + for (i = 0; i < NR_IRQS - AMEBA_IRQ_FIRST; i += 32) + { + putreg32(0xffffffff, NVIC_IRQ_CLEAR(i)); + } + + putreg32((uint32_t)_vectors, NVIC_VECTAB); + +#ifdef CONFIG_ARCH_RAMVECTORS + /* If CONFIG_ARCH_RAMVECTORS is defined, then we are using a RAM-based + * vector table that requires special initialization. + */ + + up_ramvec_initialize(); +#endif + + /* Set all interrupts (and exceptions) to the default priority */ + + putreg32(DEFPRIORITY32, NVIC_SYSH4_7_PRIORITY); + putreg32(DEFPRIORITY32, NVIC_SYSH8_11_PRIORITY); + putreg32(DEFPRIORITY32, NVIC_SYSH12_15_PRIORITY); + + /* The NVIC ICTR register (bits 0-4) holds the number of of interrupt + * lines that the NVIC supports: + * + * 0 -> 32 interrupt lines, 8 priority registers + * 1 -> 64 " " " ", 16 priority registers + * 2 -> 96 " " " ", 32 priority registers + * ... + */ + + num_priority_registers = (getreg32(NVIC_ICTR) + 1) * 8; + + /* Now set all of the interrupt lines to the default priority */ + + regaddr = NVIC_IRQ0_3_PRIORITY; + while (num_priority_registers--) + { + putreg32(DEFPRIORITY32, regaddr); + regaddr += 4; + } + + /* Attach the SVCall and Hard Fault exception handlers. The SVCall + * exception is used for performing context switches; The Hard Fault + * must also be caught because a SVCall may show up as a Hard Fault + * under certain conditions. + */ + + irq_attach(AMEBA_IRQ_SVCALL, arm_svcall, NULL); + irq_attach(AMEBA_IRQ_HARDFAULT, arm_hardfault, NULL); + + /* Set the priority of the SVCall interrupt */ + + up_prioritize_irq(AMEBA_IRQ_PENDSV, NVIC_SYSH_PRIORITY_MIN); + + ameba_prioritize_syscall(NVIC_SYSH_SVCALL_PRIORITY); + + /* If the MPU is enabled, then attach and enable the Memory Management + * Fault handler. + */ + +#ifdef CONFIG_ARM_MPU + irq_attach(AMEBA_IRQ_MEMFAULT, arm_memfault, NULL); + up_enable_irq(AMEBA_IRQ_MEMFAULT); +#endif + + /* Attach all other processor exceptions (except reset and sys tick) */ + +#ifdef CONFIG_DEBUG_FEATURES + irq_attach(AMEBA_IRQ_NMI, ameba_nmi, NULL); +#ifndef CONFIG_ARM_MPU + irq_attach(AMEBA_IRQ_MEMFAULT, arm_memfault, NULL); +#endif + irq_attach(AMEBA_IRQ_BUSFAULT, arm_busfault, NULL); + irq_attach(AMEBA_IRQ_USAGEFAULT, arm_usagefault, NULL); + irq_attach(AMEBA_IRQ_PENDSV, ameba_pendsv, NULL); + arm_enable_dbgmonitor(); + irq_attach(AMEBA_IRQ_DBGMONITOR, arm_dbgmonitor, NULL); + irq_attach(AMEBA_IRQ_RESERVED, ameba_reserved, NULL); +#endif + +#ifndef CONFIG_SUPPRESS_INTERRUPTS + + /* And finally, enable interrupts */ + + arm_color_intstack(); + up_irq_enable(); +#endif +} + +static int ameba_irqinfo(int irq, uintptr_t *regaddr, uint32_t *bit, + uintptr_t offset) +{ + int n; + + DEBUGASSERT(irq >= AMEBA_IRQ_NMI && irq < NR_IRQS); + + /* Check for external interrupt */ + + if (irq >= AMEBA_IRQ_FIRST) + { + n = irq - AMEBA_IRQ_FIRST; + *regaddr = NVIC_IRQ_ENABLE(n) + offset; + *bit = (uint32_t)0x1 << (n & 0x1f); + } + + /* Handle processor exceptions. Only a few can be disabled */ + + else + { + *regaddr = NVIC_SYSHCON; + if (irq == AMEBA_IRQ_MEMFAULT) + { + *bit = NVIC_SYSHCON_MEMFAULTENA; + } + else if (irq == AMEBA_IRQ_BUSFAULT) + { + *bit = NVIC_SYSHCON_BUSFAULTENA; + } + else if (irq == AMEBA_IRQ_USAGEFAULT) + { + *bit = NVIC_SYSHCON_USGFAULTENA; + } + else if (irq == AMEBA_IRQ_SYSTICK) + { + *regaddr = NVIC_SYSTICK_CTRL; + *bit = NVIC_SYSTICK_CTRL_ENABLE; + } + else + { + return -EINVAL; /* Invalid or unsupported exception */ + } + } + + return OK; +} + +/**************************************************************************** + * Name: up_disable_irq + * + * Description: + * Disable the IRQ specified by 'irq' + * + ****************************************************************************/ + +void up_disable_irq(int irq) +{ + uintptr_t regaddr; + uint32_t regval; + uint32_t bit; + + if (ameba_irqinfo(irq, ®addr, &bit, NVIC_CLRENA_OFFSET) == 0) + { + /* Modify the appropriate bit in the register to disable the interrupt. + * For normal interrupts, we need to set the bit in the associated + * Interrupt Clear Enable register. For other exceptions, we need to + * clear the bit in the System Handler Control and State Register. + */ + + if (irq >= AMEBA_IRQ_FIRST) + { + putreg32(bit, regaddr); + } + else + { + regval = getreg32(regaddr); + regval &= ~bit; + putreg32(regval, regaddr); + } + } +} + +/**************************************************************************** + * Name: up_enable_irq + * + * Description: + * Enable the IRQ specified by 'irq' + * + ****************************************************************************/ + +void up_enable_irq(int irq) +{ + uintptr_t regaddr; + uint32_t regval; + uint32_t bit; + + if (ameba_irqinfo(irq, ®addr, &bit, NVIC_ENA_OFFSET) == 0) + { + /* Modify the appropriate bit in the register to enable the interrupt. + * For normal interrupts, we need to set the bit in the associated + * Interrupt Set Enable register. For other exceptions, we need to + * set the bit in the System Handler Control and State Register. + */ + + if (irq >= AMEBA_IRQ_FIRST) + { + putreg32(bit, regaddr); + } + else + { + regval = getreg32(regaddr); + regval |= bit; + putreg32(regval, regaddr); + } + } +} + +/**************************************************************************** + * Name: arm_ack_irq + ****************************************************************************/ + +void arm_ack_irq(int irq) +{ +} diff --git a/arch/arm/src/rtl8721dx/ameba_irq.h b/arch/arm/src/rtl8721dx/ameba_irq.h new file mode 100644 index 00000000000..fa12a0095d1 --- /dev/null +++ b/arch/arm/src/rtl8721dx/ameba_irq.h @@ -0,0 +1,76 @@ +/**************************************************************************** + * arch/arm/src/rtl8721dx/ameba_irq.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_RTL8721DX_AMEBA_IRQ_H +#define __ARCH_ARM_SRC_RTL8721DX_AMEBA_IRQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Processor exception aliases used by the chip-internal logic. These mirror + * the ARMv8-M processor exception vector numbers (0-15) exported by + * arch/rtl8721dx/irq.h. + */ + +#define AMEBA_IRQ_RESERVED RTL8721DX_IRQ_RESERVED +#define AMEBA_IRQ_NMI RTL8721DX_IRQ_NMI +#define AMEBA_IRQ_HARDFAULT RTL8721DX_IRQ_HARDFAULT +#define AMEBA_IRQ_MEMFAULT RTL8721DX_IRQ_MEMFAULT +#define AMEBA_IRQ_BUSFAULT RTL8721DX_IRQ_BUSFAULT +#define AMEBA_IRQ_USAGEFAULT RTL8721DX_IRQ_USAGEFAULT +#define AMEBA_IRQ_SVCALL RTL8721DX_IRQ_SVCALL +#define AMEBA_IRQ_DBGMONITOR RTL8721DX_IRQ_DBGMONITOR +#define AMEBA_IRQ_PENDSV RTL8721DX_IRQ_PENDSV +#define AMEBA_IRQ_SYSTICK RTL8721DX_IRQ_SYSTICK +#define AMEBA_IRQ_FIRST RTL8721DX_IRQ_FIRST + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_RTL8721DX_AMEBA_IRQ_H */ diff --git a/arch/arm/src/rtl8721dx/ameba_loguart.c b/arch/arm/src/rtl8721dx/ameba_loguart.c new file mode 100644 index 00000000000..7903e2477a5 --- /dev/null +++ b/arch/arm/src/rtl8721dx/ameba_loguart.c @@ -0,0 +1,406 @@ +/*************************************************************************** + * arch/arm/src/rtl8721dx/ameba_loguart.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ***************************************************************************/ + +/*************************************************************************** + * Included Files + ***************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "arm_internal.h" +#include "chip.h" +#include "ameba_irq.h" + +/*************************************************************************** + * Pre-processor Definitions + ***************************************************************************/ + +/* This driver targets the RTL8721Dx LOG-UART, which NuttX (on + * the KM4 application core) owns directly. + * + * The Realtek SDK's app_start() runs BEFORE NuttX and has already + * configured the LOG-UART pinmux/clock/baud and printed its boot banner, so + * the hardware is not re-initialized here. + * + * The LOG-UART is physically shared with the NP, but the NP image is built + * with CONFIG_SHELL=n: the NP neither runs its monitor shell nor claims the + * LOG-UART RX interrupt. NuttX therefore routes the LOG-UART interrupt to + * the AP with LOGUART_INTCoreConfig() and reads RX directly via the ROM + * helpers, giving the AP sole ownership of the console (no IPC relay). + * + * NuttX installs its own vector table and re-points VTOR in + * up_irqinitialize(), so once NuttX is running it fully owns the NVIC. + */ + +/* LOGUART_INTConfig() interrupt-source bit (RX data available). */ + +#define LOGUART_BIT_ERBI (1u << 0) + +/* LOGUART_INTCoreConfig() per-core routing masks (SDK KM0/KM4 mask bits): + * select which core's NVIC the LOG-UART interrupt is delivered to. NP is + * the network core (km0), AP is the host core (km4 / NuttX). + */ + +#define LOGUART_BIT_INTR_MASK_NP (1u << 0) +#define LOGUART_BIT_INTR_MASK_AP (1u << 1) + +/* SDK ENABLE/DISABLE values. */ + +#define AMEBA_ENABLE 1 +#define AMEBA_DISABLE 0 + +/* LOG-UART device base (UARTLOG_REG_BASE, from SDK hal_platform.h). */ + +#define LOGUART_DEV ((void *)0x4100f000) + +/*************************************************************************** + * External ROM/SDK Function Prototypes + ***************************************************************************/ + +/* These live in the RTL8721Dx ROM and are resolved at link time from the + * SDK's ROM symbol script. Declared here (instead of including the SDK + * headers) to keep the SDK include tree out of the NuttX build. + */ + +extern void LOGUART_PutChar(unsigned char c); +extern unsigned char LOGUART_Readable(void); +extern unsigned char LOGUART_GetChar(int pullmode); +extern void LOGUART_INTConfig(void *dev, unsigned int it, + unsigned int state); +extern void LOGUART_INTCoreConfig(void *dev, unsigned int mask, + unsigned int state); + +/*************************************************************************** + * Private Function Prototypes + ***************************************************************************/ + +static int loguart_setup(struct uart_dev_s *dev); +static void loguart_shutdown(struct uart_dev_s *dev); +static int loguart_attach(struct uart_dev_s *dev); +static void loguart_detach(struct uart_dev_s *dev); +static int loguart_interrupt(int irq, void *context, void *arg); +static int loguart_ioctl(struct file *filep, int cmd, unsigned long arg); +static int loguart_receive(struct uart_dev_s *dev, unsigned int *status); +static void loguart_rxint(struct uart_dev_s *dev, bool enable); +static bool loguart_rxavailable(struct uart_dev_s *dev); +static void loguart_send(struct uart_dev_s *dev, int ch); +static void loguart_txint(struct uart_dev_s *dev, bool enable); +static bool loguart_txready(struct uart_dev_s *dev); +static bool loguart_txempty(struct uart_dev_s *dev); + +/*************************************************************************** + * Private Data + ***************************************************************************/ + +static const struct uart_ops_s g_loguart_ops = +{ + .setup = loguart_setup, + .shutdown = loguart_shutdown, + .attach = loguart_attach, + .detach = loguart_detach, + .ioctl = loguart_ioctl, + .receive = loguart_receive, + .rxint = loguart_rxint, + .rxavailable = loguart_rxavailable, + .send = loguart_send, + .txint = loguart_txint, + .txready = loguart_txready, + .txempty = loguart_txempty, +}; + +/* I/O buffers for the LOG-UART console. */ + +static char g_loguart_rxbuffer[CONFIG_RTL8721DX_LOGUART_RXBUFSIZE]; +static char g_loguart_txbuffer[CONFIG_RTL8721DX_LOGUART_TXBUFSIZE]; + +/* The LOG-UART port device. */ + +static struct uart_dev_s g_loguart_port = +{ + .isconsole = true, + .recv = + { + .size = CONFIG_RTL8721DX_LOGUART_RXBUFSIZE, + .buffer = g_loguart_rxbuffer, + }, + .xmit = + { + .size = CONFIG_RTL8721DX_LOGUART_TXBUFSIZE, + .buffer = g_loguart_txbuffer, + }, + .ops = &g_loguart_ops, +}; + +/*************************************************************************** + * Private Functions + ***************************************************************************/ + +/*************************************************************************** + * Name: loguart_setup + ***************************************************************************/ + +static int loguart_setup(struct uart_dev_s *dev) +{ + UNUSED(dev); + return OK; +} + +/*************************************************************************** + * Name: loguart_shutdown + ***************************************************************************/ + +static void loguart_shutdown(struct uart_dev_s *dev) +{ + loguart_rxint(dev, false); +} + +/*************************************************************************** + * Name: loguart_attach + * + * Description: + * Route the LOG-UART interrupt to KM4 and attach the handler. The + * data-available (RX) source itself is enabled later via rxint(). + * + ***************************************************************************/ + +static int loguart_attach(struct uart_dev_s *dev) +{ + int ret; + + ret = irq_attach(RTL8721DX_IRQ_UART_LOG, loguart_interrupt, dev); + if (ret == OK) + { + /* Claim the LOG-UART interrupt for the AP (the NP is built + * CONFIG_SHELL=n and does not claim it) and unmask it in the NVIC. + */ + + LOGUART_INTCoreConfig(LOGUART_DEV, LOGUART_BIT_INTR_MASK_NP, + AMEBA_DISABLE); + LOGUART_INTCoreConfig(LOGUART_DEV, LOGUART_BIT_INTR_MASK_AP, + AMEBA_ENABLE); + up_enable_irq(RTL8721DX_IRQ_UART_LOG); + } + + return ret; +} + +/*************************************************************************** + * Name: loguart_detach + ***************************************************************************/ + +static void loguart_detach(struct uart_dev_s *dev) +{ + UNUSED(dev); + up_disable_irq(RTL8721DX_IRQ_UART_LOG); + irq_detach(RTL8721DX_IRQ_UART_LOG); +} + +/*************************************************************************** + * Name: loguart_interrupt + * + * Description: + * Common LOG-UART interrupt handler. Drains the RX FIFO into the NuttX + * receive buffer. + * + ***************************************************************************/ + +static int loguart_interrupt(int irq, void *context, void *arg) +{ + struct uart_dev_s *dev = (struct uart_dev_s *)arg; + + UNUSED(irq); + UNUSED(context); + + if (LOGUART_Readable()) + { + uart_recvchars(dev); + } + + return OK; +} + +/*************************************************************************** + * Name: loguart_ioctl + ***************************************************************************/ + +static int loguart_ioctl(struct file *filep, int cmd, unsigned long arg) +{ + UNUSED(filep); + UNUSED(cmd); + UNUSED(arg); + return -ENOTTY; +} + +/*************************************************************************** + * Name: loguart_receive + ***************************************************************************/ + +static int loguart_receive(struct uart_dev_s *dev, unsigned int *status) +{ + UNUSED(dev); + + *status = 0; + + /* Read one byte in polled (non-pull) mode. */ + + return (int)LOGUART_GetChar(false); +} + +/*************************************************************************** + * Name: loguart_rxint + ***************************************************************************/ + +static void loguart_rxint(struct uart_dev_s *dev, bool enable) +{ + irqstate_t flags; + + UNUSED(dev); + + flags = enter_critical_section(); + + if (enable) + { + LOGUART_INTConfig(LOGUART_DEV, LOGUART_BIT_ERBI, AMEBA_ENABLE); + } + else + { + LOGUART_INTConfig(LOGUART_DEV, LOGUART_BIT_ERBI, AMEBA_DISABLE); + } + + leave_critical_section(flags); +} + +/*************************************************************************** + * Name: loguart_rxavailable + ***************************************************************************/ + +static bool loguart_rxavailable(struct uart_dev_s *dev) +{ + UNUSED(dev); + return LOGUART_Readable() != 0; +} + +/*************************************************************************** + * Name: loguart_send + ***************************************************************************/ + +static void loguart_send(struct uart_dev_s *dev, int ch) +{ + UNUSED(dev); + LOGUART_PutChar((unsigned char)ch); +} + +/*************************************************************************** + * Name: loguart_txint + * + * Description: + * TX is synchronous (LOGUART_PutChar blocks for FIFO space), so there is + * no hardware TX interrupt; pump the transmit buffer when asked to + * enable. + * + ***************************************************************************/ + +static void loguart_txint(struct uart_dev_s *dev, bool enable) +{ + irqstate_t flags; + + if (enable) + { + flags = enter_critical_section(); + uart_xmitchars(dev); + leave_critical_section(flags); + } +} + +/*************************************************************************** + * Name: loguart_txready + ***************************************************************************/ + +static bool loguart_txready(struct uart_dev_s *dev) +{ + UNUSED(dev); + return true; +} + +/*************************************************************************** + * Name: loguart_txempty + ***************************************************************************/ + +static bool loguart_txempty(struct uart_dev_s *dev) +{ + UNUSED(dev); + return true; +} + +/*************************************************************************** + * Public Functions + ***************************************************************************/ + +/*************************************************************************** + * Name: arm_lowputc + ***************************************************************************/ + +void arm_lowputc(char ch) +{ + if (ch == '\n') + { + LOGUART_PutChar((unsigned char)'\r'); + } + + LOGUART_PutChar((unsigned char)ch); +} + +/*************************************************************************** + * Name: arm_earlyserialinit + ***************************************************************************/ + +void arm_earlyserialinit(void) +{ +} + +/*************************************************************************** + * Name: arm_serialinit + ***************************************************************************/ + +void arm_serialinit(void) +{ + uart_register("/dev/console", &g_loguart_port); + uart_register("/dev/ttyS0", &g_loguart_port); +} + +/*************************************************************************** + * Name: up_putc + ***************************************************************************/ + +void up_putc(int ch) +{ + arm_lowputc((char)ch); +} diff --git a/arch/arm/src/rtl8721dx/ameba_start.c b/arch/arm/src/rtl8721dx/ameba_start.c new file mode 100644 index 00000000000..47ba3a4300e --- /dev/null +++ b/arch/arm/src/rtl8721dx/ameba_start.c @@ -0,0 +1,172 @@ +/**************************************************************************** + * arch/arm/src/rtl8721dx/ameba_start.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Description + * + * NuttX owns the KM4 image2. The image2 entry is a NuttX-owned app_start() + * (arch/arm/src/rtl8721dx/ameba_app_start.c, built with the SDK fwlib + * include set) that runs ALL OS-independent silicon init (cache, data-flash + * high-speed, MPU, brown-out, XTAL/OSC, ...) and zeroes BSS, then calls + * main(). Its Img2EntryFun0 descriptor (also in that file) is what the SDK + * bootloader jumps to. + * + * main() is therefore the hand-off point from silicon bring-up to + * NuttX: it switches MSP onto a NuttX-owned stack (the idle-thread stack), + * points VTOR at NuttX's own vector table, configures the FPU, and calls + * nx_start(). nx_start() never returns, so the SDK FreeRTOS scheduler is + * never launched. + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include + +#include "arm_internal.h" +#include "nvic.h" +#include "ameba_irq.h" + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* Reserved idle-thread stack, owned by NuttX (in NuttX's own .bss). The ARM + * full-descending stack grows down from the top of this buffer. + * g_idle_topstack points at the TOP and is consumed by the scheduler / idle + * thread bring-up logic. + */ + +static uint8_t g_idle_stack[CONFIG_IDLETHREAD_STACKSIZE] + aligned_data(8); + +const uintptr_t g_idle_topstack = + (uintptr_t)g_idle_stack + CONFIG_IDLETHREAD_STACKSIZE; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* NuttX vector table (armv8-m/arm_vectors.c). */ + +extern const void * const _vectors[]; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void ameba_start_continue(void) noreturn_function used_code; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ameba_start_continue + * + * Description: + * Runs on the NuttX idle stack (MSP already switched by main()). The SDK + * app_start() has already done all silicon init and zeroed BSS, so here we + * only take ownership of the vector table / FPU and enter the scheduler. + * + ****************************************************************************/ + +static void ameba_start_continue(void) +{ + /* Configure the FPU. */ + + arm_fpuconfig(); + + /* Point the vector table at NuttX's own table (app_start left VTOR + * pointing at the SDK/ROM table). + */ + + putreg32((uint32_t)_vectors, NVIC_VECTAB); + + /* Perform early serial initialization. */ + +#ifdef USE_EARLYSERIALINIT + arm_earlyserialinit(); +#endif + + /* Start NuttX. Never returns. */ + + nx_start(); + + for (; ; ); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: main + * + * Description: + * Hand-off from app_start() (which ran the silicon init and zeroed BSS) + * into NuttX. Switches MSP onto the NuttX idle stack as the + * very first action, then branches to ameba_start_continue() (which runs + * on that new stack). Declared naked so the compiler emits no prologue + * that would touch the (about-to-be-replaced) stack. Never returns. + * + ****************************************************************************/ + +int main(void) naked_function; +int main(void) +{ + __asm__ __volatile__ + ( + " movs r0, #0\n" + " msr msplim, r0\n" + " ldr r0, =g_idle_topstack\n" + " ldr r0, [r0]\n" + " msr msp, r0\n" + " b ameba_start_continue\n" + ); +} + +/**************************************************************************** + * Name: __start + * + * Description: + * Reset entry referenced by the NuttX armv8-m vector table (_vectors[1]). + * In this port the real image2 entry is Img2EntryFun0 -> app_start() -> + * main() (see ameba_app_start.c); __start exists so the vector table links + * and falls into the NuttX hand-off should the reset vector ever be taken. + * + ****************************************************************************/ + +void __start(void) naked_function; +void __start(void) +{ + __asm__ __volatile__ + ( + " b main\n" + ); +} diff --git a/arch/arm/src/rtl8721dx/ameba_timerisr.c b/arch/arm/src/rtl8721dx/ameba_timerisr.c new file mode 100644 index 00000000000..098d0d4a6f4 --- /dev/null +++ b/arch/arm/src/rtl8721dx/ameba_timerisr.c @@ -0,0 +1,72 @@ +/**************************************************************************** + * arch/arm/src/rtl8721dx/ameba_timerisr.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "arm_internal.h" +#include "systick.h" +#include "ameba_irq.h" +#include "nvic.h" + +/**************************************************************************** + * External Symbols + ****************************************************************************/ + +/* SDK CMSIS core-clock variable, set to the real KM4 CPU frequency (e.g. + * 240 MHz) by SystemCoreClockUpdate() in ameba_app_start() before NuttX + * runs. The ARMv8-M SysTick is clocked from the processor clock + * (CLKSOURCE=1, the 'true' below), so this is the correct reload base. + * Reading it at runtime avoids hard-coding a frequency that must track the + * SDK clock setup. + */ + +extern uint32_t SystemCoreClock; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: up_timer_initialize + * + * Description: + * This function is called during start-up to initialize + * the timer hardware. + * + ****************************************************************************/ + +void up_timer_initialize(void) +{ + uint32_t freq = SystemCoreClock; + + /* Set reload register and start the generic ARMv8-M SysTick driver. */ + + putreg32((freq / CLK_TCK) - 1, NVIC_SYSTICK_RELOAD); + up_timer_set_lowerhalf(systick_initialize(true, freq, -1)); +} diff --git a/arch/arm/src/rtl8721dx/ameba_wifi_init.c b/arch/arm/src/rtl8721dx/ameba_wifi_init.c new file mode 100644 index 00000000000..2ccd8f0b509 --- /dev/null +++ b/arch/arm/src/rtl8721dx/ameba_wifi_init.c @@ -0,0 +1,170 @@ +/**************************************************************************** + * arch/arm/src/rtl8721dx/ameba_wifi_init.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * NuttX side of the RTL8721Dx WiFi bring-up. + * + * The WHC host stack talks to the WiFi MAC/PHY (which runs on the NP network + * processor, km0) over the on-chip AP<->NP IPC. This file wires that IPC + * into NuttX's interrupt system -- mirroring the SDK AP main(): + * + * InterruptRegister(IPC_INTHandler, IPC_KM4_IRQ, IPCKM4_DEV, ...); + * InterruptEn(IPC_KM4_IRQ, ...); + * ipc_table_init(IPCKM4_DEV); + * + * but using NuttX's irq_attach()/up_enable_irq() (NuttX owns the vector + * table). ipc_table_init() then walks the .ipc.table.data section and + * registers every channel callback the linked SDK objects contributed, + * including the WHC WiFi TRX channels. Once IPC is live it spawns a task + * that runs the (blocking) host bring-up in ameba_wifi_start() (SDK-header + * side, libameba_wifi.a). + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include + +#include "ameba_irq.h" +#ifdef CONFIG_NET +# include "ameba_wlan.h" +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* KM4 IPC device register base (IPC1_REG_BASE, from SDK hal_platform.h). */ + +#define IPCKM4_DEV ((void *)0x41014080) + +/**************************************************************************** + * External Function Prototypes + ****************************************************************************/ + +/* SDK fwlib IPC (libameba_fwlib.a, compiled from SDK source). */ + +extern uint32_t IPC_INTHandler(void *data); +extern void ipc_table_init(void *ipcx); + +/* Host WiFi bring-up (libameba_wifi.a, SDK-header side). */ + +extern int ameba_wifi_start(void); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ameba_ipc_interrupt + * + * Description: + * NuttX IRQ handler shim for the KM4 IPC interrupt; forwards to the SDK's + * IPC_INTHandler, which dispatches to the registered channel callbacks + * (WHC WiFi TRX, etc.). + * + ****************************************************************************/ + +static int ameba_ipc_interrupt(int irq, void *context, void *arg) +{ + UNUSED(irq); + UNUSED(context); + + IPC_INTHandler(arg); + return OK; +} + +/**************************************************************************** + * Name: ameba_wifi_start_task + * + * Description: + * Task entry running the blocking WHC host bring-up once the scheduler and + * IPC are up. + * + ****************************************************************************/ + +static int ameba_wifi_start_task(int argc, char *argv[]) +{ + UNUSED(argc); + UNUSED(argv); + + /* Power on the WHC host stack (blocks on the NP round-trip), then register + * the wlan0 network device. + */ + + int ret = ameba_wifi_start(); + + syslog(LOG_INFO, "[ameba-wifi] ameba_wifi_start -> %d\n", ret); + if (ret == 0) + { +#ifdef CONFIG_NET + ret = ameba_wlan_initialize(); + syslog(LOG_INFO, "[ameba-wifi] ameba_wlan_initialize -> %d\n", ret); +#endif + } + + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rtl8721dx_wifi_initialize + * + * Description: + * Bring up the KM4 IPC transport for WiFi and start the WHC host stack. + * Call from board bring-up after the scheduler is running. + * + * Returned Value: + * 0 on success; a negated errno on failure to spawn the bring-up task. + * + ****************************************************************************/ + +int rtl8721dx_wifi_initialize(void) +{ + int pid; + + /* Route the KM4 IPC interrupt to the SDK dispatcher and register every + * channel the linked objects contributed (WHC WiFi TRX channels included). + */ + + irq_attach(RTL8721DX_IRQ_IPC_KM4, ameba_ipc_interrupt, IPCKM4_DEV); + up_enable_irq(RTL8721DX_IRQ_IPC_KM4); + ipc_table_init(IPCKM4_DEV); + + /* wifi_on() blocks on the NP round-trip, so run it off the init path. */ + + pid = kthread_create("ameba_wifi", SCHED_PRIORITY_DEFAULT, 8192, + ameba_wifi_start_task, NULL); + return pid < 0 ? pid : 0; +} diff --git a/arch/arm/src/rtl8721dx/chip.h b/arch/arm/src/rtl8721dx/chip.h new file mode 100644 index 00000000000..dfb8055d79c --- /dev/null +++ b/arch/arm/src/rtl8721dx/chip.h @@ -0,0 +1,39 @@ +/**************************************************************************** + * arch/arm/src/rtl8721dx/chip.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_RTL8721DX_CHIP_H +#define __ARCH_ARM_SRC_RTL8721DX_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ARMV8M_PERIPHERAL_INTERRUPTS NR_IRQS + +#endif /* __ARCH_ARM_SRC_RTL8721DX_CHIP_H */ diff --git a/arch/arm/src/rtl8721dx/hardware/ameba_memorymap.h b/arch/arm/src/rtl8721dx/hardware/ameba_memorymap.h new file mode 100644 index 00000000000..551fa2380d5 --- /dev/null +++ b/arch/arm/src/rtl8721dx/hardware/ameba_memorymap.h @@ -0,0 +1,52 @@ +/**************************************************************************** + * arch/arm/src/rtl8721dx/hardware/ameba_memorymap.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_RTL8721DX_HARDWARE_AMEBA_MEMORYMAP_H +#define __ARCH_ARM_SRC_RTL8721DX_HARDWARE_AMEBA_MEMORYMAP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* RTL8721Dx KM4 application-core memory map. + * + * NuttX runs from the KM4 image2 SRAM window; .text/.data/.bss and the heap + * live in this single SRAM region. The flash is a SPI NOR reached over the + * SDK XIP path and shared with the KM0 network processor. + */ + +/* SRAM (288KB) */ + +#define AMEBA_SRAM_START 0x20020000 +#define AMEBA_SRAM_SIZE 0x00048000 + +#define PRIMARY_RAM_START AMEBA_SRAM_START +#define PRIMARY_RAM_SIZE AMEBA_SRAM_SIZE +#define PRIMARY_RAM_END (PRIMARY_RAM_START + PRIMARY_RAM_SIZE) + +#endif /* __ARCH_ARM_SRC_RTL8721DX_HARDWARE_AMEBA_MEMORYMAP_H */ diff --git a/tools/ameba/Config.mk b/tools/ameba/Config.mk new file mode 100644 index 00000000000..df67a96aa81 --- /dev/null +++ b/tools/ameba/Config.mk @@ -0,0 +1,74 @@ +############################################################################ +# tools/ameba/Config.mk +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ +# +# Realtek Ameba WHC flashing support. +# +# Including this fragment in a board's scripts/Make.defs (after +# ameba_board.mk) adds the `flash` target. Usage: +# +# make flash AMEBA_PORT=/dev/ttyUSB0 [ AMEBA_BAUD=1500000 ] +# +# The board must set AMEBA_FLASH_PROFILE to the profile base name +# (e.g. "RTL8721Dx" or "RTL8720F") before including this file. +# +# AMEBA_PORT -- serial port (required) +# AMEBA_BAUD -- baud rate (default 1500000) +# +# Dependencies: +# The ameba-rtos SDK must already be fetched (auto-fetched on first +# build) and its python venv or dep-ful system python must be on PATH +# so that AmebaFlash.py (from the SDK) can import its dependencies. + +# AMEBA_BAUD -- serial baud rate (default 1500000) + +AMEBA_BAUD ?= 1500000 + +# FLASH -- Download the built images via the SDK's AmebaFlash.py + +define FLASH + $(Q) if [ -z "$(AMEBA_PORT)" ]; then \ + echo "FLASH error: Missing serial port device argument."; \ + echo "USAGE: make flash AMEBA_PORT=/dev/ttyUSB0 [ AMEBA_BAUD=$(AMEBA_BAUD) ]"; \ + exit 1; \ + fi + $(Q) AMEBAPY="$$(cat $(AMEBA_SDK)/.amebapy/bindir 2>/dev/null)/python"; \ + if [ ! -x "$$AMEBAPY" ]; then \ + AMEBAPY="python3"; \ + fi; \ + SCRIPT="$(AMEBA_SDK)/tools/ameba/Flash/AmebaFlash.py"; \ + if [ ! -f "$$SCRIPT" ]; then \ + echo "FLASH error: AmebaFlash.py not found at $$SCRIPT"; \ + echo " Has the ameba-rtos SDK been fetched? Run make first."; \ + exit 1; \ + fi; \ + PROFILE="$(AMEBA_SDK)/tools/ameba/Flash/Devices/Profiles/$(AMEBA_FLASH_PROFILE).rdev"; \ + if [ ! -f "$$PROFILE" ]; then \ + echo "FLASH error: profile not found: $$PROFILE"; \ + echo " Set AMEBA_FLASH_PROFILE in the board's Make.defs."; \ + exit 1; \ + fi; \ + $$AMEBAPY "$$SCRIPT" \ + --download \ + --profile "$$PROFILE" \ + --image-dir "$(TOPDIR)" \ + --port "$(AMEBA_PORT)" \ + --baudrate "$(or $(AMEBA_BAUD),1500000)" \ + --log-level info +endef diff --git a/tools/nxstyle.c b/tools/nxstyle.c index d344eb47111..c68ef405414 100644 --- a/tools/nxstyle.c +++ b/tools/nxstyle.c @@ -257,6 +257,32 @@ static const char *g_white_prefix[] = */ "uxrCustom", /* uxrCustomTransport */ + + /* Ref: arch/arm/src/common/ameba, arch/arm/src/rtl8721dx, + * arch/arm/src/rtl8720f and the matching boards. + * Realtek Ameba SDK ROM/HAL symbols and ARM CMSE intrinsics referenced + * by the port; renaming them would break linkage against the vendor blob. + */ + + "ADC_", + "APBPeriph_", + "BOOT_", + "BOR_", + "Cache_", + "DCache_", + "ChipInfo_", + "FLASH_", + "IPC_", + "LOGUART_", + "OSC2M_", + "OSC4M_", + "OSC131K_", + "RCC_", + "RTCIO_", + "SYSCFG_", + "SYSTIMER_", + "SystemCoreClock", /* SystemCoreClock, SystemCoreClockUpdate */ + "cmse_", /* ARM CMSE TrustZone intrinsics (arm_cmse.h) */ NULL }; @@ -291,6 +317,17 @@ static const char *g_white_content_list[] = "NativeSymbol", "RuntimeInitArgs", + /* Ref: arch/arm/src/common/ameba, arch/arm/src/rtl8721dx, + * arch/arm/src/rtl8720f. Standalone Realtek Ameba SDK ROM symbols. + */ + + "DelayUs", + "DiagPrintf", + "Img2EntryFun0", + "NewVectorTable", + "RomVectorTable", + "PutChar", + /* Ref: gnu_unwind_find_exidx.c */ "__EIT_entry", @@ -378,41 +415,6 @@ static const char *g_white_content_list[] = "SEGGER_RTT", - /* Ref: - * drivers/crypto/pnt/pnt_se05x_api.c - */ - - "smStatus_t", - "Se05xSession_t", - "SE05x_ECSignatureAlgo_t", - "kSE05x_ECSignatureAlgo_NA", - "kSE05x_ECSignatureAlgo_PLAIN", - "kSE05x_ECSignatureAlgo_SHA", - "kSE05x_ECSignatureAlgo_SHA_224", - "kSE05x_ECSignatureAlgo_SHA_256", - "kSE05x_ECSignatureAlgo_SHA_384", - "kSE05x_ECSignatureAlgo_SHA_512", - "kSE05x_ECCurve_NIST_P256" - "SE05x_Result_t", - "kSE05x_Result_NA", - "kSE05x_Result_SUCCESS", - "kSE05x_INS_NA", - "kSE05x_KeyPart_Pair", - "kSE05x_KeyPart_Public", - "pScp03_enc_key", - "pScp03_mac_key", - "pScp03_dek_key", - "Se05x_API_SessionOpen", - "Se05x_API_SessionClose", - "Se05x_API_CheckObjectExists", - "Se05x_API_ReadObject", - "Se05x_API_WriteECKey", - "Se05x_API_WriteBinary", - "Se05x_API_ReadSize", - "Se05x_API_DeleteSecureObject", - "Se05x_API_ECDHGenerateSharedSecret", - "Se05x_API_ECDSAVerify", - /* Ref: * fs/nfs/rpc.h * fs/nfs/nfs_proto.h