mirror of
https://github.com/apache/nuttx.git
synced 2026-09-11 21:20:10 +00:00
arch/arm/rtl8721dx: add shared Ameba GPIO driver.
Add a board-agnostic GPIO driver for Realtek Ameba chips, exposing pins
through the NuttX GPIO (ioexpander) upper half at /dev/gpioN.
- arch/arm/src/common/ameba/ameba_gpio.{c,h}: the shared driver, sitting
directly on the SDK fwlib register layer. The fwlib GPIO API it calls
resolves at link time from the on-chip ROM symbol table, except
GPIO_INTStatusGet/ClearEdge which are not in ROM and are compiled in
from fwlib ram_common/ameba_gpio.c (that object also carries GPIO_Init,
harmlessly overriding the equivalent ROM copy). Pin interrupts are
dispatched NuttX-natively: the port's NVIC vector is owned by NuttX
via irq_attach, and the ISR reads and clears status through the fwlib
GPIO_INTStatus* helpers.
- The driver keeps nothing IC-specific: the port count, the per-port
NVIC vectors and the RCC gate bits come from a per-chip
<ameba_gpio_chip.h> resolved on the include path, so bringing up a new
Ameba chip only adds that header, not a change to the shared driver.
- arch/arm/src/common/ameba/Kconfig: a shared "Ameba Peripheral Support"
menu with the AMEBA_GPIO option, sourced by each Ameba chip's Kconfig so
it is reused across ICs (RTL8721Dx, RTL8720F, ...).
- arch/arm/src/rtl8721dx: provide ameba_gpio_chip.h, wire the driver into
both the Make/Kconfig and CMake builds, and compile the fwlib
ameba_gpio.c register layer into libameba_fwlib for the RTL8721Dx.
- boards/arm/rtl8721dx/pke8721daf: board pin table (rtl8721dx_gpio.c),
bring-up registration, and a standalone gpio defconfig.
- Documentation: describe the gpio configuration and pin encoding.
tools/nxstyle: whitelist the Ameba "GPIO_" SDK ROM symbol prefix (alongside
the existing FLASH_/IPC_/... Ameba prefixes) so the vendor GPIO API's mixed-case
identifiers do not trip nxstyle, matching how the other Ameba SDK prefixes are
handled.
Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: dechao_gong <dechao_gong@realsil.com.cn>
This commit is contained in:
parent
099aa3425f
commit
e2ff8be900
16 changed files with 1004 additions and 0 deletions
|
|
@ -33,6 +33,8 @@ Supported in this NuttX port:
|
|||
partition), backing the Wi-Fi key-value store
|
||||
* Wi-Fi station and SoftAP through the ``wapi`` tool
|
||||
* DHCP client (STA) and DHCP server (SoftAP)
|
||||
* GPIO pins exposed as ``/dev/gpioN`` character devices (input, output and
|
||||
interrupt), driven directly on the SDK fwlib register layer
|
||||
|
||||
Buttons and LEDs
|
||||
================
|
||||
|
|
@ -58,6 +60,24 @@ The console is the LOG-UART at 1500000 8N1 (the rate is configured by the
|
|||
bootloader and inherited by NuttX). The Wi-Fi examples below are available from
|
||||
this configuration.
|
||||
|
||||
gpio
|
||||
----
|
||||
|
||||
Minimal NSH with the GPIO driver and the ``gpio`` example enabled (no Wi-Fi).
|
||||
The board registers three pins from its pin table (see
|
||||
``boards/arm/rtl8721dx/pke8721daf/src/rtl8721dx_gpio.c``): an output at
|
||||
``/dev/gpio0``, an input at ``/dev/gpio1`` and an interrupt pin at
|
||||
``/dev/gpio2``. Edit that table to match a board's wiring. Exercise them with
|
||||
the example::
|
||||
|
||||
nsh> gpio -o 1 /dev/gpio0 # drive the output high
|
||||
nsh> gpio /dev/gpio1 # read the input
|
||||
nsh> gpio -w 1 /dev/gpio2 # wait for a rising-edge interrupt
|
||||
|
||||
Pins are encoded with the ``AMEBA_PA()`` / ``AMEBA_PB()`` helpers from
|
||||
``arch/arm/src/common/ameba/ameba_gpio.h`` (port A/B, pin 0-31), matching the
|
||||
Ameba SDK ``PinName`` layout.
|
||||
|
||||
Wi-Fi
|
||||
=====
|
||||
|
||||
|
|
|
|||
25
arch/arm/src/common/ameba/Kconfig
Normal file
25
arch/arm/src/common/ameba/Kconfig
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#
|
||||
# For a description of the syntax of this configuration file,
|
||||
# see the file kconfig-language.txt in the NuttX tools repository.
|
||||
#
|
||||
# Shared Realtek Ameba peripheral drivers (arch/arm/src/common/ameba). These
|
||||
# options are common to every Ameba ARM chip (RTL8721Dx, RTL8720F, ...) and
|
||||
# are sourced from each chip's own Kconfig.
|
||||
#
|
||||
|
||||
menu "Ameba Peripheral Support"
|
||||
|
||||
config AMEBA_GPIO
|
||||
bool "GPIO"
|
||||
default n
|
||||
select DEV_GPIO
|
||||
---help---
|
||||
Expose Ameba GPIO pins through the NuttX GPIO (ioexpander) upper
|
||||
half at /dev/gpioN. The board selects which pins are registered
|
||||
and their type (input, output or interrupt) in its bring-up code.
|
||||
|
||||
The driver (arch/arm/src/common/ameba/ameba_gpio.c) sits on the SDK
|
||||
fwlib register layer and dispatches pin interrupts through the ROM
|
||||
GPIO interrupt handler.
|
||||
|
||||
endmenu # Ameba Peripheral Support
|
||||
572
arch/arm/src/common/ameba/ameba_gpio.c
Normal file
572
arch/arm/src/common/ameba/ameba_gpio.c
Normal file
|
|
@ -0,0 +1,572 @@
|
|||
/****************************************************************************
|
||||
* arch/arm/src/common/ameba/ameba_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
|
||||
****************************************************************************/
|
||||
|
||||
/* NuttX GPIO (ioexpander) lower half for the Realtek Ameba GPIO controller.
|
||||
*
|
||||
* The pad mux, pull resistors and GPIO port registers are all programmed
|
||||
* through the SDK fwlib GPIO API (GPIO_Init(), GPIO_WriteBit(), ...).
|
||||
*
|
||||
* Most of the API has no SDK source and resolves to the on-chip ROM symbol
|
||||
* table (GPIO_WriteBit, GPIO_ReadDataBit, GPIO_INTConfig, GPIO_Direction,
|
||||
* GPIO_INTMode, Pinmux_Config, PAD_PullCtrl, ...). Only GPIO_INTStatusGet
|
||||
* and GPIO_INTStatusClearEdge are missing from ROM; they live in fwlib
|
||||
* ram_common/ameba_gpio.c, compiled into libameba_fwlib.a to provide them
|
||||
* (see AMEBA_FWLIB_SRCS). That same source also defines GPIO_Init (which
|
||||
* IS in ROM), so the local object overrides the ROM PROVIDE(GPIO_Init) as a
|
||||
* harmless side effect -- same source, equivalent behaviour. To keep the
|
||||
* vendor headers out of the NuttX include world, the handful of fwlib
|
||||
* symbols and the GPIO_InitTypeDef layout used here are declared locally
|
||||
* below rather than pulled in from <ameba_gpio.h>.
|
||||
*
|
||||
* Interrupt dispatch stays NuttX-native: the port's NVIC vector is owned by
|
||||
* NuttX (irq_attach), and the ISR reads/clears the controller status through
|
||||
* the fwlib GPIO_INTStatus* helpers before calling each pending pin's
|
||||
* registered callback.
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <nuttx/ioexpander/gpio.h>
|
||||
|
||||
#include "arm_internal.h"
|
||||
#include "ameba_gpio.h"
|
||||
|
||||
/* Per-chip GPIO parameters (port count, per-port NVIC vectors, RCC gate
|
||||
* bits). Resolved from the configured chip's directory on the include path
|
||||
* (arch/.../chip -> arch/arm/src/<chip>); see <ameba_gpio_chip.h> there.
|
||||
*/
|
||||
|
||||
#include "ameba_gpio_chip.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Pin encoding (SDK "PinName": port in bits[7:5], pin num in bits[4:0]). */
|
||||
|
||||
#define AMEBA_PIN_PORT(pin) (((pin) >> 5) & 0x07)
|
||||
#define AMEBA_PIN_NUM(pin) ((pin) & 0x1f)
|
||||
|
||||
/* Mirror of the fwlib GPIO_InitTypeDef field values (ameba_gpio.h).
|
||||
* Declared locally so the SDK header need not leak into NuttX includes.
|
||||
*/
|
||||
|
||||
#define AMEBA_GPIO_MODE_IN 0x0 /* GPIO_Mode_IN */
|
||||
#define AMEBA_GPIO_MODE_OUT 0x1 /* GPIO_Mode_OUT */
|
||||
#define AMEBA_GPIO_MODE_INT 0x2 /* GPIO_Mode_INT */
|
||||
|
||||
#define AMEBA_GPIO_PUPD_NONE 0x0 /* GPIO_PuPd_NOPULL */
|
||||
#define AMEBA_GPIO_PUPD_DOWN 0x1 /* GPIO_PuPd_DOWN */
|
||||
#define AMEBA_GPIO_PUPD_UP 0x2 /* GPIO_PuPd_UP */
|
||||
|
||||
#define AMEBA_GPIO_IT_LEVEL 0x0 /* GPIO_INT_Trigger_LEVEL */
|
||||
#define AMEBA_GPIO_IT_EDGE 0x1 /* GPIO_INT_Trigger_EDGE */
|
||||
#define AMEBA_GPIO_IT_BOTHEDGE 0x2 /* GPIO_INT_Trigger_BOTHEDGE */
|
||||
|
||||
#define AMEBA_GPIO_POL_LOW 0x0 /* GPIO_INT_POLARITY_ACTIVE_LOW */
|
||||
#define AMEBA_GPIO_POL_HIGH 0x1 /* GPIO_INT_POLARITY_ACTIVE_HIGH */
|
||||
|
||||
#define AMEBA_GPIO_DEBOUNCE_OFF 0x0 /* GPIO_INT_DEBOUNCE_DISABLE */
|
||||
|
||||
/* Second argument to GPIO_INTConfig() / state passed to GPIO_WriteBit(). */
|
||||
|
||||
#define AMEBA_DISABLE 0x0
|
||||
#define AMEBA_ENABLE 0x1
|
||||
|
||||
/* AMEBA_APBPERIPH_GPIO (the RCC gate bits), AMEBA_GPIO_NPORTS and the
|
||||
* 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).
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/* Layout-compatible mirror of the fwlib GPIO_InitTypeDef (all u32, same
|
||||
* order); passed by address to GPIO_Init().
|
||||
*/
|
||||
|
||||
struct ameba_gpio_init_s
|
||||
{
|
||||
uint32_t mode; /* GPIO_Mode */
|
||||
uint32_t pupd; /* GPIO_PuPd */
|
||||
uint32_t ittrigger; /* GPIO_ITTrigger */
|
||||
uint32_t itpolarity; /* GPIO_ITPolarity */
|
||||
uint32_t itdebounce; /* GPIO_ITDebounce */
|
||||
uint32_t pin; /* GPIO_Pin */
|
||||
};
|
||||
|
||||
struct ameba_gpio_dev_s
|
||||
{
|
||||
struct gpio_dev_s gpio; /* Lower-half GPIO device (must be first) */
|
||||
uint8_t pin; /* SDK pin encoding (port[7:5] | num[4:0]) */
|
||||
pin_interrupt_t callback; /* Interrupt callback (interrupt pins only) */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/* SDK fwlib GPIO API used by this driver. These are plain extern symbols;
|
||||
* the driver does not care where each comes from -- every one is resolved
|
||||
* at link time either by the on-chip ROM symbol table or by a fwlib object
|
||||
* compiled into libameba_fwlib.a. Which source applies is per-chip:
|
||||
*
|
||||
* RCC_PeriphClockCmd, GPIO_Init, GPIO_WriteBit, GPIO_ReadDataBit and
|
||||
* GPIO_INTConfig are in ROM on every Ameba ARM chip. (GPIO_Init also
|
||||
* reaches Pinmux_Config, GPIO_Direction, GPIO_INTMode and PAD_PullCtrl
|
||||
* internally, resolved inside ROM, so the driver never names them.)
|
||||
*
|
||||
* GPIO_INTStatusGet and GPIO_INTStatusClearEdge are the gap. On RTL8721Dx
|
||||
* they come from fwlib ram_common/ameba_gpio.c, compiled in via
|
||||
* AMEBA_FWLIB_SRCS (that object also carries GPIO_Init and harmlessly
|
||||
* overrides the ROM copy). On amebalite/amebasmart they are in neither ROM
|
||||
* nor any SDK source, so a chip adding those parts MUST supply its own
|
||||
* definition -- a small object writing the port's GPIO_INT_STATUS /
|
||||
* GPIO_INT_EOI -- via its board build. The shared driver needs no change;
|
||||
* this is the per-chip contract for these two symbols.
|
||||
*/
|
||||
|
||||
extern void RCC_PeriphClockCmd(uint32_t periph, uint32_t clock,
|
||||
uint8_t newstate);
|
||||
extern void GPIO_Init(struct ameba_gpio_init_s *init);
|
||||
extern void GPIO_WriteBit(uint32_t pin, uint32_t state);
|
||||
extern uint32_t GPIO_ReadDataBit(uint32_t pin);
|
||||
extern void GPIO_INTConfig(uint32_t pin, uint32_t newstate);
|
||||
extern uint32_t GPIO_INTStatusGet(uint32_t port);
|
||||
extern void GPIO_INTStatusClearEdge(uint32_t port);
|
||||
|
||||
/* GPIO lower-half operations */
|
||||
|
||||
static int ameba_gpio_read(struct gpio_dev_s *dev, bool *value);
|
||||
static int ameba_gpio_write(struct gpio_dev_s *dev, bool value);
|
||||
static int ameba_gpio_attach(struct gpio_dev_s *dev,
|
||||
pin_interrupt_t callback);
|
||||
static int ameba_gpio_enable(struct gpio_dev_s *dev, bool enable);
|
||||
static int ameba_gpio_setpintype(struct gpio_dev_s *dev,
|
||||
enum gpio_pintype_e pintype);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const struct gpio_operations_s g_ameba_gpio_ops =
|
||||
{
|
||||
.go_read = ameba_gpio_read,
|
||||
.go_write = ameba_gpio_write,
|
||||
.go_attach = ameba_gpio_attach,
|
||||
.go_enable = ameba_gpio_enable,
|
||||
.go_setpintype = ameba_gpio_setpintype,
|
||||
};
|
||||
|
||||
/* Driver-wide state, kept in one controller instance instead of
|
||||
* scattered file-scope globals. A single NVIC vector per port drives
|
||||
* up to 32 pins, so the dispatch table, the attach flags and the NVIC
|
||||
* vectors are all per-port, and one spinlock guards the shared table.
|
||||
*/
|
||||
|
||||
struct ameba_gpio_ctrl_s
|
||||
{
|
||||
/* Per-pin device lookup for interrupt dispatch, indexed [port][pin-num];
|
||||
* set once an interrupt pin is registered, read by the port ISR.
|
||||
*/
|
||||
|
||||
struct ameba_gpio_dev_s *int_dev[AMEBA_GPIO_NPORTS][32];
|
||||
|
||||
/* Set once a port's NVIC vector has been attached + enabled. */
|
||||
|
||||
bool port_attached[AMEBA_GPIO_NPORTS];
|
||||
|
||||
/* Per-port NVIC vector, from the chip's <ameba_gpio_chip.h>. */
|
||||
|
||||
const int irq[AMEBA_GPIO_NPORTS];
|
||||
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
static struct ameba_gpio_ctrl_s g_ameba_gpio =
|
||||
{
|
||||
.irq = AMEBA_GPIO_PORT_IRQS,
|
||||
.lock = SP_UNLOCKED,
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ameba_gpio_configure
|
||||
*
|
||||
* Description:
|
||||
* Program the pad mux, direction, pull and (for interrupt pins) trigger
|
||||
* mode for the given pin type through the fwlib GPIO_Init(). Interrupt
|
||||
* pins are left masked until the application enables them.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void ameba_gpio_configure(struct ameba_gpio_dev_s *priv,
|
||||
enum gpio_pintype_e pintype)
|
||||
{
|
||||
struct ameba_gpio_init_s init;
|
||||
|
||||
init.pin = priv->pin;
|
||||
init.pupd = AMEBA_GPIO_PUPD_NONE;
|
||||
init.ittrigger = AMEBA_GPIO_IT_EDGE;
|
||||
init.itpolarity = AMEBA_GPIO_POL_LOW;
|
||||
init.itdebounce = AMEBA_GPIO_DEBOUNCE_OFF;
|
||||
|
||||
/* Gate on the GPIO peripheral clock (idempotent). */
|
||||
|
||||
RCC_PeriphClockCmd(AMEBA_APBPERIPH_GPIO, AMEBA_APBPERIPH_GPIO,
|
||||
AMEBA_ENABLE);
|
||||
|
||||
switch (pintype)
|
||||
{
|
||||
case GPIO_OUTPUT_PIN:
|
||||
case GPIO_OUTPUT_PIN_OPENDRAIN:
|
||||
init.mode = AMEBA_GPIO_MODE_OUT;
|
||||
break;
|
||||
|
||||
case GPIO_INPUT_PIN:
|
||||
init.mode = AMEBA_GPIO_MODE_IN;
|
||||
break;
|
||||
|
||||
case GPIO_INPUT_PIN_PULLUP:
|
||||
init.mode = AMEBA_GPIO_MODE_IN;
|
||||
init.pupd = AMEBA_GPIO_PUPD_UP;
|
||||
break;
|
||||
|
||||
case GPIO_INPUT_PIN_PULLDOWN:
|
||||
init.mode = AMEBA_GPIO_MODE_IN;
|
||||
init.pupd = AMEBA_GPIO_PUPD_DOWN;
|
||||
break;
|
||||
|
||||
case GPIO_INTERRUPT_HIGH_PIN:
|
||||
init.mode = AMEBA_GPIO_MODE_INT;
|
||||
init.ittrigger = AMEBA_GPIO_IT_LEVEL;
|
||||
init.itpolarity = AMEBA_GPIO_POL_HIGH;
|
||||
break;
|
||||
|
||||
case GPIO_INTERRUPT_LOW_PIN:
|
||||
init.mode = AMEBA_GPIO_MODE_INT;
|
||||
init.ittrigger = AMEBA_GPIO_IT_LEVEL;
|
||||
init.itpolarity = AMEBA_GPIO_POL_LOW;
|
||||
break;
|
||||
|
||||
case GPIO_INTERRUPT_RISING_PIN:
|
||||
init.mode = AMEBA_GPIO_MODE_INT;
|
||||
init.ittrigger = AMEBA_GPIO_IT_EDGE;
|
||||
init.itpolarity = AMEBA_GPIO_POL_HIGH;
|
||||
break;
|
||||
|
||||
case GPIO_INTERRUPT_BOTH_PIN:
|
||||
init.mode = AMEBA_GPIO_MODE_INT;
|
||||
init.ittrigger = AMEBA_GPIO_IT_BOTHEDGE;
|
||||
init.itpolarity = AMEBA_GPIO_POL_LOW;
|
||||
break;
|
||||
|
||||
case GPIO_INTERRUPT_PIN:
|
||||
case GPIO_INTERRUPT_FALLING_PIN:
|
||||
default:
|
||||
init.mode = AMEBA_GPIO_MODE_INT;
|
||||
init.ittrigger = AMEBA_GPIO_IT_EDGE;
|
||||
init.itpolarity = AMEBA_GPIO_POL_LOW;
|
||||
break;
|
||||
}
|
||||
|
||||
GPIO_Init(&init);
|
||||
|
||||
/* GPIO_Init() leaves the interrupt source enabled, and setting up the
|
||||
* trigger can latch a stale edge. While the pin is still unmasked, clear
|
||||
* that latch, then mask the pin until the application enables it. Order
|
||||
* matters: GPIO_INTStatusClearEdge() acts through the masked
|
||||
* GPIO_INT_STATUS, so it clears only a currently-unmasked pin --
|
||||
* clearing after masking would miss this pin. The clear+mask pair runs
|
||||
* under the port lock so the ISR cannot dispatch a stale edge in between;
|
||||
* clearing the whole port's edge latches is safe during registration, as
|
||||
* no interrupt pin is application-enabled yet.
|
||||
*/
|
||||
|
||||
if (init.mode == AMEBA_GPIO_MODE_INT)
|
||||
{
|
||||
irqstate_t flags = spin_lock_irqsave(&g_ameba_gpio.lock);
|
||||
|
||||
GPIO_INTStatusClearEdge(AMEBA_PIN_PORT(priv->pin));
|
||||
GPIO_INTConfig(priv->pin, AMEBA_DISABLE);
|
||||
|
||||
spin_unlock_irqrestore(&g_ameba_gpio.lock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ameba_gpio_interrupt
|
||||
*
|
||||
* Description:
|
||||
* NuttX-native vector for a GPIO port. Reads the (masked) interrupt
|
||||
* status, clears the edge latches and dispatches to each pending pin's
|
||||
* registered callback.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int ameba_gpio_interrupt(int irq, void *context, void *arg)
|
||||
{
|
||||
int port = (int)(uintptr_t)arg;
|
||||
uint32_t status = GPIO_INTStatusGet(port);
|
||||
|
||||
/* Clear the port's edge latches. GPIO_INTStatusClearEdge() re-reads the
|
||||
* status internally and takes no bitmask, so an edge that arrives between
|
||||
* the read above and this clear is acknowledged without being dispatched
|
||||
* this pass -- an inherent limit of the two-call fwlib interface. It is
|
||||
* harmless for the board's single edge pin, and level-triggered sources
|
||||
* re-assert and fire again regardless.
|
||||
*/
|
||||
|
||||
GPIO_INTStatusClearEdge(port);
|
||||
|
||||
while (status != 0)
|
||||
{
|
||||
int num = __builtin_ctz(status);
|
||||
struct ameba_gpio_dev_s *priv = g_ameba_gpio.int_dev[port][num];
|
||||
|
||||
status &= ~((uint32_t)1 << num);
|
||||
|
||||
if (priv != NULL && priv->callback != NULL)
|
||||
{
|
||||
priv->callback(&priv->gpio, num);
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ameba_gpio_read
|
||||
****************************************************************************/
|
||||
|
||||
static int ameba_gpio_read(struct gpio_dev_s *dev, bool *value)
|
||||
{
|
||||
struct ameba_gpio_dev_s *priv = (struct ameba_gpio_dev_s *)dev;
|
||||
|
||||
DEBUGASSERT(priv != NULL && value != NULL);
|
||||
|
||||
*value = (GPIO_ReadDataBit(priv->pin) != 0);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ameba_gpio_write
|
||||
****************************************************************************/
|
||||
|
||||
static int ameba_gpio_write(struct gpio_dev_s *dev, bool value)
|
||||
{
|
||||
struct ameba_gpio_dev_s *priv = (struct ameba_gpio_dev_s *)dev;
|
||||
|
||||
DEBUGASSERT(priv != NULL);
|
||||
|
||||
GPIO_WriteBit(priv->pin, value ? AMEBA_ENABLE : AMEBA_DISABLE);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ameba_gpio_attach
|
||||
****************************************************************************/
|
||||
|
||||
static int ameba_gpio_attach(struct gpio_dev_s *dev,
|
||||
pin_interrupt_t callback)
|
||||
{
|
||||
struct ameba_gpio_dev_s *priv = (struct ameba_gpio_dev_s *)dev;
|
||||
|
||||
DEBUGASSERT(priv != NULL);
|
||||
|
||||
/* Mask the interrupt while (re)attaching, then record the callback. */
|
||||
|
||||
GPIO_INTConfig(priv->pin, AMEBA_DISABLE);
|
||||
priv->callback = callback;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ameba_gpio_enable
|
||||
****************************************************************************/
|
||||
|
||||
static int ameba_gpio_enable(struct gpio_dev_s *dev, bool enable)
|
||||
{
|
||||
struct ameba_gpio_dev_s *priv = (struct ameba_gpio_dev_s *)dev;
|
||||
|
||||
DEBUGASSERT(priv != NULL);
|
||||
|
||||
if (enable && priv->callback != NULL)
|
||||
{
|
||||
/* Unmask the pin, then drop any stale edge that unmasking just exposed
|
||||
* (the GPIO_Init arming transient, or an edge latched while masked) so
|
||||
* the first wait does not fire on a past interrupt. Clearing runs
|
||||
* with the pin unmasked -- GPIO_INTStatusClearEdge() works through the
|
||||
* masked GPIO_INT_STATUS -- and the port lock keeps the ISR from
|
||||
* dispatching that stale edge between the two steps. Level-triggered
|
||||
* pins do not latch, so a genuinely active level still fires at once.
|
||||
*/
|
||||
|
||||
irqstate_t flags = spin_lock_irqsave(&g_ameba_gpio.lock);
|
||||
|
||||
GPIO_INTConfig(priv->pin, AMEBA_ENABLE);
|
||||
GPIO_INTStatusClearEdge(AMEBA_PIN_PORT(priv->pin));
|
||||
|
||||
spin_unlock_irqrestore(&g_ameba_gpio.lock, flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
GPIO_INTConfig(priv->pin, AMEBA_DISABLE);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ameba_gpio_setpintype
|
||||
****************************************************************************/
|
||||
|
||||
static int ameba_gpio_setpintype(struct gpio_dev_s *dev,
|
||||
enum gpio_pintype_e pintype)
|
||||
{
|
||||
struct ameba_gpio_dev_s *priv = (struct ameba_gpio_dev_s *)dev;
|
||||
|
||||
DEBUGASSERT(priv != NULL);
|
||||
|
||||
if (pintype >= GPIO_NPINTYPES)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ameba_gpio_configure(priv, pintype);
|
||||
dev->gp_pintype = pintype;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ameba_gpio_port_attach
|
||||
*
|
||||
* Description:
|
||||
* Attach and enable the NuttX-native interrupt vector for the GPIO port
|
||||
* that owns the given pin (once per port).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void ameba_gpio_port_attach(uint8_t pin)
|
||||
{
|
||||
irqstate_t flags;
|
||||
int port = AMEBA_PIN_PORT(pin);
|
||||
|
||||
flags = spin_lock_irqsave(&g_ameba_gpio.lock);
|
||||
|
||||
if (!g_ameba_gpio.port_attached[port])
|
||||
{
|
||||
int irq = g_ameba_gpio.irq[port];
|
||||
|
||||
irq_attach(irq, ameba_gpio_interrupt, (void *)(uintptr_t)port);
|
||||
up_enable_irq(irq);
|
||||
g_ameba_gpio.port_attached[port] = true;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&g_ameba_gpio.lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ameba_gpio_register
|
||||
*
|
||||
* Description:
|
||||
* See ameba_gpio.h.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ameba_gpio_register(int minor, uint8_t pin, enum gpio_pintype_e pintype)
|
||||
{
|
||||
struct ameba_gpio_dev_s *priv;
|
||||
bool interrupt;
|
||||
int ret;
|
||||
|
||||
if (pintype >= GPIO_NPINTYPES)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
interrupt = (pintype >= GPIO_INTERRUPT_PIN);
|
||||
|
||||
priv = kmm_zalloc(sizeof(struct ameba_gpio_dev_s));
|
||||
if (priv == NULL)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
priv->pin = pin;
|
||||
priv->gpio.gp_pintype = pintype;
|
||||
priv->gpio.gp_ops = &g_ameba_gpio_ops;
|
||||
|
||||
/* Apply the pad/pin configuration for this pin type. */
|
||||
|
||||
ameba_gpio_configure(priv, pintype);
|
||||
|
||||
if (interrupt)
|
||||
{
|
||||
/* Publish the device for the port ISR and make sure the owning port's
|
||||
* NuttX vector is live. The pin stays masked until the application
|
||||
* attaches a callback and enables it.
|
||||
*/
|
||||
|
||||
g_ameba_gpio.int_dev[AMEBA_PIN_PORT(pin)][AMEBA_PIN_NUM(pin)] = priv;
|
||||
ameba_gpio_port_attach(pin);
|
||||
}
|
||||
|
||||
ret = gpio_pin_register(&priv->gpio, minor);
|
||||
if (ret < 0)
|
||||
{
|
||||
gpioerr("ERROR: gpio_pin_register(%d) failed: %d\n", minor, ret);
|
||||
|
||||
if (interrupt)
|
||||
{
|
||||
GPIO_INTConfig(pin, AMEBA_DISABLE);
|
||||
g_ameba_gpio.int_dev[AMEBA_PIN_PORT(pin)][AMEBA_PIN_NUM(pin)] =
|
||||
NULL;
|
||||
}
|
||||
|
||||
kmm_free(priv);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
93
arch/arm/src/common/ameba/ameba_gpio.h
Normal file
93
arch/arm/src/common/ameba/ameba_gpio.h
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
/****************************************************************************
|
||||
* arch/arm/src/common/ameba/ameba_gpio.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_GPIO_H
|
||||
#define __ARCH_ARM_SRC_COMMON_AMEBA_AMEBA_GPIO_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <nuttx/ioexpander/gpio.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* A pin is identified with the same encoding the Ameba SDK uses for its
|
||||
* "PinName": bits[7:5] select the GPIO port and bits[4:0] the pin within
|
||||
* the port. Boards build their pin table from these helpers so the shared
|
||||
* driver never needs to know a board's wiring.
|
||||
*/
|
||||
|
||||
#define AMEBA_PORT_A 0
|
||||
#define AMEBA_PORT_B 1
|
||||
|
||||
#define AMEBA_PIN(port, num) ((uint8_t)(((port) << 5) | ((num) & 0x1f)))
|
||||
|
||||
/* Convenience: the RTL8721Dx / RTL8720F break out ports A and B. */
|
||||
|
||||
#define AMEBA_PA(num) AMEBA_PIN(AMEBA_PORT_A, (num))
|
||||
#define AMEBA_PB(num) AMEBA_PIN(AMEBA_PORT_B, (num))
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ameba_gpio_register
|
||||
*
|
||||
* Description:
|
||||
* Configure a single Ameba GPIO pin and register it with the NuttX GPIO
|
||||
* (ioexpander) upper half at /dev/gpioN, where N is the given minor.
|
||||
*
|
||||
* Input Parameters:
|
||||
* minor - The /dev/gpioN minor number.
|
||||
* pin - The pin, encoded with AMEBA_PIN() / AMEBA_PA() / AMEBA_PB().
|
||||
* pintype - One of enum gpio_pintype_e (input, output or one of the
|
||||
* interrupt pin types).
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ameba_gpio_register(int minor, uint8_t pin, enum gpio_pintype_e pintype);
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_COMMON_AMEBA_AMEBA_GPIO_H */
|
||||
|
|
@ -40,6 +40,10 @@ if(CONFIG_RTL8721DX_FLASH_FS)
|
|||
list(APPEND SRCS ${AMEBA_COMMON}/ameba_flash_mtd.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_AMEBA_GPIO)
|
||||
list(APPEND SRCS ${AMEBA_COMMON}/ameba_gpio.c)
|
||||
endif()
|
||||
|
||||
target_include_directories(arch PRIVATE ${AMEBA_COMMON})
|
||||
target_sources(arch PRIVATE ${SRCS})
|
||||
|
||||
|
|
@ -90,6 +94,12 @@ if(CONFIG_RTL8721DX_FLASH_FS)
|
|||
list(APPEND AMEBA_FWLIB_SRCS ${AMEBA_SOC}/fwlib/ram_common/ameba_flash_ram.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_AMEBA_GPIO)
|
||||
# GPIO_INTStatusGet/ClearEdge are not in the ROM symbol table; compile them in
|
||||
# from the fwlib source (mirrors the make build's ameba_board.mk).
|
||||
list(APPEND AMEBA_FWLIB_SRCS ${AMEBA_SOC}/fwlib/ram_common/ameba_gpio.c)
|
||||
endif()
|
||||
|
||||
# Silence a couple of warnings the vendored SDK sources trip under NuttX's
|
||||
# warning set, scoped to this fwlib compile only (never relaxing NuttX's own):
|
||||
# -Wno-int-conversion: the SDK passes NULL to irq_register()'s u32 "Data"
|
||||
|
|
|
|||
|
|
@ -82,4 +82,9 @@ config RTL8721DX_FLASH_FS
|
|||
|
||||
endmenu # RTL8721Dx Storage
|
||||
|
||||
# Shared Ameba peripheral drivers (GPIO, ...) live in the common IC-agnostic
|
||||
# tree and are configured through one Kconfig reused by every Ameba chip.
|
||||
|
||||
source "arch/arm/src/common/ameba/Kconfig"
|
||||
|
||||
endif # ARCH_CHIP_RTL8721DX
|
||||
|
|
|
|||
|
|
@ -50,6 +50,10 @@ ifeq ($(CONFIG_RTL8721DX_FLASH_FS),y)
|
|||
CHIP_CSRCS += ameba_flash_mtd.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_AMEBA_GPIO),y)
|
||||
CHIP_CSRCS += ameba_gpio.c
|
||||
endif
|
||||
|
||||
############################################################################
|
||||
# Realtek RTL8721Dx SDK integration
|
||||
#
|
||||
|
|
|
|||
|
|
@ -116,6 +116,18 @@ AMEBA_FWLIB_SRCS += $(TOPDIR)/arch/arm/src/rtl8721dx/ameba_app_start.c \
|
|||
ifeq ($(CONFIG_RTL8721DX_FLASH_FS),y)
|
||||
AMEBA_FWLIB_SRCS += $(AMEBA_SOC)/fwlib/ram_common/ameba_flash_ram.c
|
||||
endif
|
||||
# GPIO register layer. The GPIO driver (arch/.../common/ameba/ameba_gpio.c)
|
||||
# calls the fwlib GPIO API. GPIO_INTStatusGet/ClearEdge are NOT in the ROM
|
||||
# symbol table, so fwlib ram_common/ameba_gpio.c is compiled in to provide
|
||||
# them. That same source also defines GPIO_Init (which IS in ROM), so the
|
||||
# local object overrides the ROM PROVIDE(GPIO_Init) as a harmless side effect
|
||||
# (same source, equivalent behaviour). Everything else the driver calls
|
||||
# (GPIO_WriteBit/ReadDataBit/Direction/INTMode/INTConfig, Pinmux_Config,
|
||||
# PAD_PullCtrl) has no SDK source and resolves to the ROM symbol table.
|
||||
ifeq ($(CONFIG_AMEBA_GPIO),y)
|
||||
AMEBA_FWLIB_SRCS += $(AMEBA_SOC)/fwlib/ram_common/ameba_gpio.c
|
||||
endif
|
||||
|
||||
# -Wno-int-conversion: the vendored SDK passes NULL to irq_register()'s u32
|
||||
# "Data" (interrupt context) argument in many places -- an intentional
|
||||
# NULL-as-context idiom. Silence -Wint-conversion for the SDK fwlib sources
|
||||
|
|
|
|||
70
arch/arm/src/rtl8721dx/ameba_gpio_chip.h
Normal file
70
arch/arm/src/rtl8721dx/ameba_gpio_chip.h
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/****************************************************************************
|
||||
* arch/arm/src/rtl8721dx/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_RTL8721DX_AMEBA_GPIO_CHIP_H
|
||||
#define __ARCH_ARM_SRC_RTL8721DX_AMEBA_GPIO_CHIP_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Per-chip GPIO parameters for the shared driver
|
||||
* (arch/arm/src/common/ameba/ameba_gpio.c). The driver logic, pin encoding
|
||||
* and fwlib API are identical across every Ameba ARM chip, but the port
|
||||
* count, the per-port NVIC vectors and the RCC gate bits are not. Each chip
|
||||
* supplies its own <ameba_gpio_chip.h> on the include path (arch/.../chip);
|
||||
* the common driver sizes its tables and wires its vectors from the macros
|
||||
* below, so nothing IC-specific is left in common.
|
||||
*
|
||||
* RTL8721Dx (KM4) breaks out two GPIO ports, A and B, each a 32-pin bank
|
||||
* with its own interrupt vector.
|
||||
*/
|
||||
|
||||
/* Number of GPIO ports (banks) this chip exposes. */
|
||||
|
||||
#define AMEBA_GPIO_NPORTS 2
|
||||
|
||||
/* NVIC vector for each port, as an initialiser indexed by port number
|
||||
* (0 = A, 1 = B). Its width must match AMEBA_GPIO_NPORTS.
|
||||
*/
|
||||
|
||||
#define AMEBA_GPIO_PORT_IRQS { RTL8721DX_IRQ_GPIOA, RTL8721DX_IRQ_GPIOB }
|
||||
|
||||
/* APBPeriph_GPIO / APBPeriph_GPIO_CLOCK (sysreg_lsys.h): the peripheral and
|
||||
* clock bits RCC_PeriphClockCmd() gates for the GPIO block. On RTL8721Dx
|
||||
* both are ((1 << 30) | (1 << 4)); this value differs on amebasmart, which
|
||||
* is why it lives here rather than in the shared driver.
|
||||
*/
|
||||
|
||||
#define AMEBA_APBPERIPH_GPIO (((uint32_t)1 << 30) | ((uint32_t)1 << 4))
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_RTL8721DX_AMEBA_GPIO_CHIP_H */
|
||||
51
boards/arm/rtl8721dx/pke8721daf/configs/gpio/defconfig
Normal file
51
boards/arm/rtl8721dx/pke8721daf/configs/gpio/defconfig
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#
|
||||
# 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_DEBUG_WARN is not set
|
||||
CONFIG_AMEBA_GPIO=y
|
||||
CONFIG_ARCH="arm"
|
||||
CONFIG_ARCH_BOARD="pke8721daf"
|
||||
CONFIG_ARCH_BOARD_PKE8721DAF=y
|
||||
CONFIG_ARCH_CHIP="rtl8721dx"
|
||||
CONFIG_ARCH_CHIP_RTL8721DX=y
|
||||
CONFIG_ARCH_INTERRUPTSTACK=2048
|
||||
CONFIG_ARCH_STACKDUMP=y
|
||||
CONFIG_ARMV8M_SYSTICK=y
|
||||
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_FS_PROCFS=y
|
||||
CONFIG_FS_TMPFS=y
|
||||
CONFIG_IDLETHREAD_STACKSIZE=4096
|
||||
CONFIG_INIT_ENTRYPOINT="nsh_main"
|
||||
CONFIG_LIBC_MEMFD_ERROR=y
|
||||
CONFIG_MM_DEFAULT_ALIGNMENT=32
|
||||
CONFIG_NSH_BUILTIN_APPS=y
|
||||
CONFIG_NSH_FILEIOSIZE=512
|
||||
CONFIG_NSH_READLINE=y
|
||||
CONFIG_PREALLOC_TIMERS=4
|
||||
CONFIG_RAM_SIZE=294912
|
||||
CONFIG_RAM_START=0x20020000
|
||||
CONFIG_RR_INTERVAL=200
|
||||
CONFIG_RTL8721DX_FLASH_FS=y
|
||||
CONFIG_SCHED_HPWORK=y
|
||||
CONFIG_SCHED_HPWORKPRIORITY=192
|
||||
CONFIG_SCHED_LPWORK=y
|
||||
CONFIG_STACK_COLORATION=y
|
||||
CONFIG_START_DAY=16
|
||||
CONFIG_START_MONTH=6
|
||||
CONFIG_START_YEAR=2026
|
||||
CONFIG_SYSTEM_NSH=y
|
||||
CONFIG_SYSTEM_NSH_STACKSIZE=2500
|
||||
CONFIG_TIMER=y
|
||||
CONFIG_TIMER_ARCH=y
|
||||
CONFIG_USEC_PER_TICK=1000
|
||||
|
|
@ -22,7 +22,18 @@
|
|||
|
||||
set(SRCS rtl8721dx_boot.c rtl8721dx_bringup.c)
|
||||
|
||||
if(CONFIG_AMEBA_GPIO)
|
||||
list(APPEND SRCS rtl8721dx_gpio.c)
|
||||
endif()
|
||||
|
||||
target_sources(board PRIVATE ${SRCS})
|
||||
|
||||
if(CONFIG_AMEBA_GPIO)
|
||||
# The board pin table pulls in the shared driver's public header from
|
||||
# arch/arm/src/common/ameba/, not on the default board include path.
|
||||
target_include_directories(board
|
||||
PRIVATE ${NUTTX_DIR}/arch/arm/src/common/ameba)
|
||||
endif()
|
||||
|
||||
# LD_SCRIPT is not set here: the Ameba image2 linker script is generated
|
||||
# (prebuilt/ld.script.gen) and published by the shared ameba_board.cmake.
|
||||
|
|
|
|||
|
|
@ -24,4 +24,13 @@ include $(TOPDIR)/Make.defs
|
|||
|
||||
CSRCS = rtl8721dx_boot.c rtl8721dx_bringup.c
|
||||
|
||||
ifeq ($(CONFIG_AMEBA_GPIO),y)
|
||||
CSRCS += rtl8721dx_gpio.c
|
||||
|
||||
# The board pin table pulls in the shared driver's public header from
|
||||
# arch/arm/src/common/ameba/, which is not on the default board include path.
|
||||
|
||||
CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)arch$(DELIM)arm$(DELIM)src$(DELIM)common$(DELIM)ameba
|
||||
endif
|
||||
|
||||
include $(TOPDIR)/boards/Board.mk
|
||||
|
|
|
|||
|
|
@ -108,6 +108,16 @@ int rtl8721dx_bringup(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AMEBA_GPIO
|
||||
/* Register the board's GPIO pins at /dev/gpioN. */
|
||||
|
||||
ret = rtl8721dx_gpio_initialize();
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: rtl8721dx_gpio_initialize failed: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Install the inter-core HW IPC-semaphore RTOS hooks LAST -- after all the
|
||||
* flash / WHC bring-up above, and just before this (board_late_initialize)
|
||||
* path returns and nx_start() hands off to the init task.
|
||||
|
|
|
|||
98
boards/arm/rtl8721dx/pke8721daf/src/rtl8721dx_gpio.c
Normal file
98
boards/arm/rtl8721dx/pke8721daf/src/rtl8721dx_gpio.c
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
/****************************************************************************
|
||||
* boards/arm/rtl8721dx/pke8721daf/src/rtl8721dx_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 "rtl8721dx_pke8721daf.h"
|
||||
|
||||
#ifdef CONFIG_AMEBA_GPIO
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/* One entry per GPIO pin exposed to NuttX. The pins below are examples used
|
||||
* by the `gpio` (examples/gpio) test -- adjust them to match your board's
|
||||
* wiring. They are registered in order as /dev/gpio0, /dev/gpio1, ...
|
||||
*/
|
||||
|
||||
struct rtl8721dx_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 rtl8721dx_gpio_s g_gpio_pins[] =
|
||||
{
|
||||
{ AMEBA_PB(18), GPIO_OUTPUT_PIN }, /* /dev/gpio0: output */
|
||||
{ AMEBA_PB(19), GPIO_INPUT_PIN }, /* /dev/gpio1: input */
|
||||
{ AMEBA_PB(20), GPIO_INTERRUPT_PIN }, /* /dev/gpio2: interrupt */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rtl8721dx_gpio_initialize
|
||||
*
|
||||
* Description:
|
||||
* Register the board's GPIO pins with the NuttX GPIO upper half.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int rtl8721dx_gpio_initialize(void)
|
||||
{
|
||||
int ret;
|
||||
size_t i;
|
||||
|
||||
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 */
|
||||
|
|
@ -68,6 +68,19 @@ int rtl8721dx_bringup(void);
|
|||
int rtl8721dx_wifi_initialize(void);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AMEBA_GPIO
|
||||
/****************************************************************************
|
||||
* Name: rtl8721dx_gpio_initialize
|
||||
*
|
||||
* Description:
|
||||
* Register the board's GPIO pins with the NuttX GPIO upper half
|
||||
* (boards/arm/rtl8721dx/pke8721daf/src/rtl8721dx_gpio.c).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int rtl8721dx_gpio_initialize(void);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_RTL8721DX_FLASH_FS
|
||||
/****************************************************************************
|
||||
* Name: ameba_flash_fs_initialize
|
||||
|
|
|
|||
|
|
@ -272,6 +272,7 @@ static const char *g_white_prefix[] =
|
|||
"DCache_",
|
||||
"ChipInfo_",
|
||||
"FLASH_",
|
||||
"GPIO_",
|
||||
"IPC_",
|
||||
"LOGUART_",
|
||||
"OSC2M_",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue