arch/arm/ameba: add GPIO driver for RTL8730E (AmebaSmart CA32)

Wire the shared ameba_gpio driver to the RTL8730E CA32 core.

The CA32 replaces the vendor CA32 OS as BL33; the SDK startup that
normally initialises GPIO_PORTx[] never runs under NuttX.  The three
GPIO port base addresses are patched at runtime inside
rtl8730e_gpio_initialize() before any ROM GPIO function is called.
GPIO_INTStatusGet and GPIO_INTStatusClearEdge are absent from the
RTL8730E ROM and are provided as static inline helpers in the new
ameba_gpio_chip.h.

Key changes:
- ameba_gpio_chip.h (new): chip parameters, split AMEBA_APBPERIPH_GPIO
  / AMEBA_APBPERIPH_GPIO_CLK bits, inline INTStatus helpers
- ameba_gpio.c: add AMEBA_APBPERIPH_GPIO_CLK fallback macro so chips
  with separate periph/clock enable bits work without driver changes
- Make.defs: enable ameba_gpio.c + rtl8730e_flash_stubs.c + lib_rom.a
  under CONFIG_AMEBA_GPIO; consolidate flash_stubs into GPIO||FLASH_FS
- ameba_board.mk: remove duplicate lib_rom.a (Make.defs is authoritative)
- rtl8730e_flash_stubs.c: make _strcmp weak; delegate Pinmux_Config to
  lib_rom.a's _Pinmux_Config so GPIO pad mux is configured correctly
- Kconfig: source common/ameba/Kconfig to expose CONFIG_AMEBA_GPIO
- dramboot.ld: include .sramdram.only.data in .data so GPIO_PORTx[] is
  copied to RAM by the normal arm_data_initialize() path
- scripts/Make.defs: extend --no-warn-mismatch to GPIO and WiFi configs
- rtl8730e_gpio.c (new): pin table (PB19 output /dev/gpio0, PB20 input
  /dev/gpio1, PB11 falling-edge interrupt /dev/gpio2) + GPIO_PORTx patch
- configs/gpio/ (new): defconfig for GPIO example verification
- nxstyle.c: add _Pinmux_ to mixed-case whitelist (ROM symbol)

Hardware verified on RTL8730E CA32:
- PB19 output write 0/1, readback matches
- PB20 input reads PB19-driven level
- PB11 falling-edge interrupt triggers correctly

Signed-off-by: dechao_gong <dechao_gong@realsil.com.cn>
Assisted-by: Claude <noreply@anthropic.com>
This commit is contained in:
dechao_gong 2026-09-22 10:15:20 +08:00 • committed by Alan C. Assis
parent 1f9793b7b5
commit 7e34d1c6b4
14 changed files with 335 additions and 14 deletions

View file

@ -109,8 +109,17 @@
* AMEBA_GPIO_PORT_IRQS vector table come from <ameba_gpio_chip.h>. The
* fwlib GPIO_Init() leaves the peripheral clock to the caller, so the driver
* gates AMEBA_APBPERIPH_GPIO on before use (RCC touches the LSYS block).
*
* On most Ameba chips the peripheral-enable and clock-enable bits are the
* same value, so a single macro suffices for both RCC_PeriphClockCmd args.
* On chips where they differ (e.g. RTL8730E), <ameba_gpio_chip.h> may also
* define AMEBA_APBPERIPH_GPIO_CLK for the clock-enable argument.
*/
#ifndef AMEBA_APBPERIPH_GPIO_CLK
# define AMEBA_APBPERIPH_GPIO_CLK AMEBA_APBPERIPH_GPIO
#endif
/****************************************************************************
* Private Types
****************************************************************************/
@ -256,7 +265,7 @@ static void ameba_gpio_configure(struct ameba_gpio_dev_s *priv,
/* Gate on the GPIO peripheral clock (idempotent). */
RCC_PeriphClockCmd(AMEBA_APBPERIPH_GPIO, AMEBA_APBPERIPH_GPIO,
RCC_PeriphClockCmd(AMEBA_APBPERIPH_GPIO, AMEBA_APBPERIPH_GPIO_CLK,
AMEBA_ENABLE);
switch (pintype)

View file

@ -30,4 +30,6 @@ config ARCH_CHIP_RTL8730E_CA32
endmenu # "Realtek AmebaSmart (RTL8730E) Chip Selection"
source "arch/arm/src/common/ameba/Kconfig"
endif # ARCH_CHIP_RTL8730E

View file

@ -59,6 +59,21 @@ ifeq ($(CONFIG_BUILD_PROTECTED),y)
CHIP_CSRCS += rtl8730e_userspace.c rtl8730e_allocateheap.c
endif
AMEBA_AP_SOC_LIB = $(TOPDIR)/arch/arm/src/common/ameba/ameba-rtos/component/soc/amebasmart/project/project_ap/lib/soc
# lib_rom.a provides ROM stubs (GPIO, UART, flash, Pinmux, etc.).
# rtl8730e_flash_stubs.c supplies the RAM-side symbols that lib_rom.a objects
# expect (DiagPrintfNano, irq_enable, Pinmux_Config, etc.). Compile them once
# whenever any driver needing ROM is enabled.
ifneq ($(filter y,$(CONFIG_AMEBA_GPIO) $(CONFIG_RTL8730E_FLASH_FS)),)
CHIP_CSRCS += rtl8730e_flash_stubs.c
EXTRA_LIBS += $(AMEBA_AP_SOC_LIB)$(DELIM)lib_rom.a
endif
ifeq ($(CONFIG_AMEBA_GPIO),y)
CHIP_CSRCS += ameba_gpio.c
endif
# WiFi (WHC host, CA32 side).
ifeq ($(CONFIG_RTL8730E_WIFI),y)
CHIP_CSRCS += rtl8730e_wifi_init.c
@ -80,7 +95,6 @@ endif
# On-chip SPI NOR flash MTD (littlefs data partition).
ifeq ($(CONFIG_RTL8730E_FLASH_FS),y)
CHIP_CSRCS += rtl8730e_flash_stubs.c
# ameba_flash_mtd.c lives in the common Ameba driver directory (already on
# VPATH + INCLUDES at the top of this file).

View file

@ -61,12 +61,9 @@ AMEBA_FWLIB_SRCS += $(AMEBA_SOC)/fwlib/ram_common/ameba_ipc_api.c \
$(AMEBA_SOC)/fwlib/ram_common/ameba_ipc_ram.c
endif
ifeq ($(CONFIG_RTL8730E_FLASH_FS),y)
AMEBA_FWLIB_SRCS += $(AMEBA_SOC)/fwlib/ram_common/ameba_flash_ram.c
# lib_rom.a: prebuilt SDK AP library that provides FLASH_TxData/RxCmd/Erase/
# SetStatus and RSIP_MMU_* called by ameba_flash_ram.c at link time.
EXTRA_LIBS += $(AMEBA_SOC)/project/project_ap/lib/soc/lib_rom.a
endif
# Include paths scoped to the fwlib compile only (never leaked to NuttX core).

View file

@ -0,0 +1,101 @@
/****************************************************************************
* arch/arm/src/rtl8730e/ameba_gpio_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_RTL8730E_AMEBA_GPIO_CHIP_H
#define __ARCH_ARM_SRC_RTL8730E_AMEBA_GPIO_CHIP_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <nuttx/irq.h>
/****************************************************************************
* Pre-processor Definitions (register map for local helpers)
****************************************************************************/
#define RTL8730E_GPIO_BASE UINT32_C(0x4200D000)
#define RTL8730E_GPIO_STRIDE UINT32_C(0x400)
#define RTL8730E_GPIO_INT_STATUS UINT32_C(0x40)
#define RTL8730E_GPIO_INT_EOI UINT32_C(0x4C)
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Per-chip GPIO parameters for the shared driver
* (arch/arm/src/common/ameba/ameba_gpio.c).
*
* RTL8730E (CA32) exposes three GPIO ports: A, B, and C, each a 32-pin
* bank with its own GIC SPI interrupt. The CA32 IRQ numbers are the GIC
* SPI numbers (9/10/11) plus RTL8730E_SPI_IRQ_BASE (32).
*/
/* Number of GPIO ports (banks) this chip exposes. */
#define AMEBA_GPIO_NPORTS 3
/* GIC SPI vectors for GPIOA/B/C on CA32, indexed by port number. */
#define AMEBA_GPIO_PORT_IRQS { 41, 42, 43 }
/* RCC_PeriphClockCmd(periph, clock, state) takes two separate bit masks:
* periph - APBPeriph_GPIO: bit 23, enables the GPIO function
* clock - APBPeriph_GPIO_CLOCK: bit 8, enables the GPIO bus clock
* On RTL8730E these are distinct; on the KM4-based Ameba parts they
* happen to be the same value, so the shared driver passes one macro
* for both. Define AMEBA_APBPERIPH_GPIO_CLK to override the clock arg.
*/
#define AMEBA_APBPERIPH_GPIO ((uint32_t)1 << 23)
#define AMEBA_APBPERIPH_GPIO_CLK ((uint32_t)1 << 8)
/****************************************************************************
* Inline Functions
****************************************************************************/
/* GPIO_INTStatusGet / GPIO_INTStatusClearEdge are absent from the RTL8730E
* ROM and fwlib; provide them here as inlines so no separate .c file is
* needed (unlike the KM4-based parts where these symbols are in the ROM).
*/
static inline uint32_t GPIO_INTStatusGet(uint32_t port)
{
volatile uint32_t *r =
(volatile uint32_t *)(RTL8730E_GPIO_BASE + port * RTL8730E_GPIO_STRIDE +
RTL8730E_GPIO_INT_STATUS);
return *r;
}
static inline void GPIO_INTStatusClearEdge(uint32_t port)
{
volatile uint32_t *r =
(volatile uint32_t *)(RTL8730E_GPIO_BASE + port * RTL8730E_GPIO_STRIDE +
RTL8730E_GPIO_INT_EOI);
*r = UINT32_C(0xffffffff);
}
#endif /* __ARCH_ARM_SRC_RTL8730E_AMEBA_GPIO_CHIP_H */

View file

@ -173,7 +173,7 @@ void *_memset(void *s, int c, size_t n)
return memset(s, c, n);
}
int _strcmp(const char *s1, const char *s2)
int __attribute__((weak)) _strcmp(const char *s1, const char *s2)
{
return strcmp(s1, s2);
}
@ -325,12 +325,16 @@ void System_Reset(void)
__asm__ volatile("b .");
}
/* Pinmux_Config: flash/LOGUART pinmux is handled by KM4; stub for CA32. */
/* Pinmux_Config: lib_rom.a declares this as an external reference and
* provides _Pinmux_Config as the actual register-writing implementation.
* Delegate to it so GPIO_Init can configure pad mux for user GPIO pins.
*/
extern void _Pinmux_Config(uint32_t pinname, uint32_t pinfunc);
void Pinmux_Config(uint32_t pinname, uint32_t pinfunc)
{
(void)pinname;
(void)pinfunc;
_Pinmux_Config(pinname, pinfunc);
}
/****************************************************************************

View file

@ -0,0 +1,63 @@
#
# This file is autogenerated: PLEASE DO NOT EDIT IT.
#
# You can use "make menuconfig" to make any modifications to the installed .config file.
# You can then do "make savedefconfig" to generate a new defconfig file that includes your
# modifications.
#
# CONFIG_NSH_DISABLE_MB is not set
# CONFIG_NSH_DISABLE_MH is not set
# CONFIG_NSH_DISABLE_MW is not set
CONFIG_ALARM_ARCH=y
CONFIG_AMEBA_GPIO=y
CONFIG_ARCH="arm"
CONFIG_ARCH_BOARD="rtl8730e_evb"
CONFIG_ARCH_BOARD_RTL8730E_EVB=y
CONFIG_ARCH_CHIP="rtl8730e"
CONFIG_ARCH_CHIP_RTL8730E=y
CONFIG_ARCH_CHIP_RTL8730E_CA32=y
CONFIG_ARCH_INTERRUPTSTACK=2048
CONFIG_ARCH_LOWVECTORS=y
CONFIG_ARM_PSCI=y
CONFIG_BOARD_LOOPSPERMSEC=393693
CONFIG_BUILTIN=y
CONFIG_DEBUG_ASSERTIONS=y
CONFIG_DEBUG_FEATURES=y
CONFIG_DEBUG_FULLOPT=y
CONFIG_DEBUG_SYMBOLS=y
CONFIG_DEFAULT_TASK_STACKSIZE=4096
CONFIG_EXAMPLES_GPIO=y
CONFIG_EXAMPLES_HELLO=y
CONFIG_EXPERIMENTAL=y
CONFIG_FLASH_SIZE=1048576
CONFIG_FLASH_START=0x60300000
CONFIG_FLASH_VSTART=0x60300000
CONFIG_FS_PROCFS=y
CONFIG_FS_TMPFS=y
CONFIG_HAVE_CXX=y
CONFIG_HAVE_CXXINITIALIZE=y
CONFIG_IDLETHREAD_STACKSIZE=4096
CONFIG_INIT_ENTRYPOINT="nsh_main"
CONFIG_LIBC_MEMFD_ERROR=y
CONFIG_MM_DEFAULT_ALIGNMENT=64
CONFIG_NSH_BUILTIN_APPS=y
CONFIG_NSH_FILEIOSIZE=512
CONFIG_NSH_READLINE=y
CONFIG_PREALLOC_TIMERS=4
CONFIG_PRIORITY_INHERITANCE=y
CONFIG_RAM_SIZE=3145728
CONFIG_RAM_START=0x60400000
CONFIG_RAM_VSTART=0x60400000
CONFIG_RAW_BINARY=y
CONFIG_READLINE_CMD_HISTORY=y
CONFIG_RR_INTERVAL=200
CONFIG_SCHED_HPWORK=y
CONFIG_SCHED_HPWORKPRIORITY=192
CONFIG_SMP=y
CONFIG_SMP_NCPUS=2
CONFIG_STACK_COLORATION=y
CONFIG_START_DAY=25
CONFIG_START_MONTH=4
CONFIG_START_YEAR=2023
CONFIG_SYSTEM_NSH=y
CONFIG_USEC_PER_TICK=1000

View file

@ -59,9 +59,10 @@ AMEBA_BAUD ?= 1500000
include $(TOPDIR)$(DELIM)arch$(DELIM)arm$(DELIM)src$(DELIM)common$(DELIM)ameba$(DELIM)ameba_sdk.mk
include $(TOPDIR)$(DELIM)arch$(DELIM)arm$(DELIM)src$(DELIM)rtl8730e$(DELIM)ameba_board.mk
# lib_rom.a is compiled without VFP ABI flags; suppress the harmless mismatch
# warning so the linker does not abort on it.
ifeq ($(CONFIG_RTL8730E_FLASH_FS),y)
# lib_rom.a and the RTK toolchain's libgcc.a are compiled without VFP ABI
# flags; suppress the harmless mismatch so the linker does not abort on it
# whenever libameba_fwlib.a is in the link (GPIO, WiFi, or flash-FS config).
ifneq ($(filter y,$(CONFIG_AMEBA_GPIO) $(CONFIG_RTL8730E_WIFI) $(CONFIG_RTL8730E_FLASH_FS)),)
LDFLAGS += --no-warn-mismatch
endif

View file

@ -105,6 +105,13 @@ SECTIONS
.data : { /* Data */
_sdata = .;
*(.data*)
/* lib_rom.a places GPIO port-base tables and other init data in
* .sramdram.only.data. These must be copied from flash to RAM
* before any ROM GPIO (or other sramdram) functions are called.
* Including them here causes the normal _eronly..._edata copy in
* arm_data_initialize() to handle them automatically.
*/
*(.sramdram.only.data)
. = ALIGN(8);
__start_impls = .;
*(.impls)

View file

@ -34,8 +34,12 @@ ifeq ($(CONFIG_LIBC_FDT),y)
CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)libs$(DELIM)libc$(DELIM)fdt$(DELIM)dtc$(DELIM)libfdt
endif
ifeq ($(CONFIG_RTL8730E_FLASH_FS),y)
ifneq ($(CONFIG_RTL8730E_FLASH_FS)$(CONFIG_AMEBA_GPIO),)
CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)arch$(DELIM)arm$(DELIM)src$(DELIM)common$(DELIM)ameba
endif
ifeq ($(CONFIG_AMEBA_GPIO),y)
CSRCS += rtl8730e_gpio.c
endif
include $(TOPDIR)/boards/Board.mk

View file

@ -242,6 +242,15 @@ int rtl8730e_bringup(void)
}
#endif
#ifdef CONFIG_AMEBA_GPIO
ret = rtl8730e_gpio_initialize();
if (ret < 0)
{
syslog(LOG_ERR,
"ERROR: Failed to initialize GPIO: %d\n", ret);
}
#endif
UNUSED(ret);
return OK;
}

View file

@ -57,5 +57,9 @@
int rtl8730e_bringup(void);
#endif
#ifdef CONFIG_AMEBA_GPIO
int rtl8730e_gpio_initialize(void);
#endif
#endif /* __ASSEMBLY__ */
#endif /* __BOARDS_ARM_RTL8730E_RTL8730E_EVB_SRC_RTL8730E_EVB_H */

View file

@ -0,0 +1,105 @@
/****************************************************************************
* boards/arm/rtl8730e/rtl8730e_evb/src/rtl8730e_gpio.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 <nuttx/config.h>
#include <sys/param.h>
#include <syslog.h>
#include <nuttx/ioexpander/gpio.h>
#include "ameba_gpio.h"
#include "rtl8730e_evb.h"
#ifdef CONFIG_AMEBA_GPIO
/****************************************************************************
* Private Types
****************************************************************************/
struct rtl8730e_gpio_s
{
uint8_t pin; /* AMEBA_PA()/AMEBA_PB() pin encoding */
enum gpio_pintype_e pintype; /* Input, output or interrupt */
};
/****************************************************************************
* Private Data
****************************************************************************/
static const struct rtl8730e_gpio_s g_gpio_pins[] =
{
{ AMEBA_PB(19), GPIO_OUTPUT_PIN }, /* /dev/gpio0: output */
{ AMEBA_PB(20), GPIO_INPUT_PIN }, /* /dev/gpio1: input */
{ AMEBA_PB(11), GPIO_INTERRUPT_PIN }, /* /dev/gpio2: interrupt */
};
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: rtl8730e_gpio_initialize
*
* Description:
* Register the board's GPIO pins with the NuttX GPIO upper half.
*
****************************************************************************/
int rtl8730e_gpio_initialize(void)
{
int ret;
size_t i;
/* Initialise the ROM GPIO port-base lookup table. lib_rom.a places
* GPIO_PORTx in .sramdram.only.data which NuttX's linker script does not
* copy, so the array is zero at boot. Write the three port bases before
* any ROM GPIO function is called.
*/
extern void *GPIO_PORTx[3];
GPIO_PORTx[0] = (void *)0x4200d000u; /* GPIOA */
GPIO_PORTx[1] = (void *)0x4200d400u; /* GPIOB */
GPIO_PORTx[2] = (void *)0x4200d800u; /* GPIOC */
for (i = 0; i < nitems(g_gpio_pins); i++)
{
ret = ameba_gpio_register(i, g_gpio_pins[i].pin,
g_gpio_pins[i].pintype);
if (ret < 0)
{
syslog(LOG_ERR,
"ERROR: ameba_gpio_register(/dev/gpio%zu) failed: %d\n",
i, ret);
return ret;
}
}
return OK;
}
#endif /* CONFIG_AMEBA_GPIO */

View file

@ -301,6 +301,7 @@ static const char *g_white_prefix[] =
"PAD_",
"PLL_", /* PLL_ClkGet — amebadplus SPI ip_clk query */
"Pinmux_",
"_Pinmux_", /* _Pinmux_Config — ROM symbol for RTL8730E pad mux */
"RCC_",
"RTC_", /* RTC_InitTypeDef, RTC_Enable, RTC_SetTime, etc. */
"RTCIO_",