boards/arm/ra8m1: Register the GPT timers and add GPIO support

Register GPT0 (32-bit) as /dev/timer0 and GPT9 (16-bit) as /dev/timer1
during bring-up.

Register the Arduino Uno shield header's D2-D5 as inputs and D6-D13 as
outputs through the generic GPIO expander driver, as /dev/gpio0-3 and
/dev/gpio4-11.

Add the ek-ra8m1:timer-gpio configuration (nsh plus both GPT channels,
the GPIO support above, and apps/examples/gpio and
apps/examples/timer_gpio), used to validate the GPT timer driver on
hardware with an oscilloscope.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Assisted-by: Claude:claude-sonnet-5
Signed-off-by: leocafonso <leocafonso@gmail.com>
This commit is contained in:
leocafonso 2026-09-30 18:36:00 -07:00 • committed by Xiang Xiao
parent 279e1ec458
commit 2c061c6c18
7 changed files with 327 additions and 0 deletions

View file

@ -0,0 +1,44 @@
#
# 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_ARCH="arm"
CONFIG_ARCH_BOARD="ek-ra8m1"
CONFIG_ARCH_BOARD_EK_RA8M1=y
CONFIG_ARCH_CHIP="ra8m1"
CONFIG_ARCH_CHIP_R7FA8M1AHECBD=y
CONFIG_ARCH_CHIP_RA8M1=y
CONFIG_ARCH_STACKDUMP=y
CONFIG_BOARD_LOOPSPERMSEC=43103
CONFIG_BUILTIN=y
CONFIG_DEV_GPIO=y
CONFIG_EXAMPLES_GPIO=y
CONFIG_EXAMPLES_TIMER_GPIO=y
CONFIG_EXAMPLES_TIMER_GPIO_INTERVAL=200000
CONFIG_FS_PROCFS=y
CONFIG_HAVE_CXX=y
CONFIG_HAVE_CXXINITIALIZE=y
CONFIG_INIT_ENTRYPOINT="nsh_main"
CONFIG_INTELHEX_BINARY=y
CONFIG_NSH_BUILTIN_APPS=y
CONFIG_NSH_DISABLE_IFUPDOWN=y
CONFIG_NSH_FILEIOSIZE=512
CONFIG_NSH_READLINE=y
CONFIG_PREALLOC_TIMERS=4
CONFIG_RAM_SIZE=917504
CONFIG_RAM_START=0x22000000
CONFIG_RA_GPT0_GPT=y
CONFIG_RA_GPT9_GPT=y
CONFIG_RA_GPT_TIMER=y
CONFIG_RA_SCI9_UART=y
CONFIG_RR_INTERVAL=200
CONFIG_SCHED_WAITPID=y
CONFIG_SCI9_SERIAL_CONSOLE=y
CONFIG_START_DAY=28
CONFIG_START_MONTH=6
CONFIG_START_YEAR=2013
CONFIG_SYSTEM_NSH=y
CONFIG_TASK_NAME_SIZE=32

View file

@ -321,6 +321,49 @@
#define GPIO_SCI9_RX GPIO_RXD9_MISO9_SCL9_3 /* PA15 */
#define GPIO_SCI9_TX GPIO_TXD9_MOSI9_SDA9_3 /* PA14 */
/* Arduino shield header pin selections *************************************/
/* D2-D5 are wired as inputs, D6-D13 as outputs (see
* Documentation/platforms/arm/ra8m1/boards/ek-ra8m1 or the schematic,
* "EK-RA8M1 Arduino Shield Connection", for the D0-D13/port mapping this is
* taken from). D0/D1 are left alone here since they are SCI9's RXD/TXD
* pins, already covered by GPIO_SCI9_RX/GPIO_SCI9_TX above.
*/
#define GPIO_ARDUINO_D2 (gpio_pinset_t){ PORT9, PIN6, GPIO_INPUT } /* P906 */
#define GPIO_ARDUINO_D3 (gpio_pinset_t){ PORT9, PIN7, GPIO_INPUT } /* P907 */
#define GPIO_ARDUINO_D4 (gpio_pinset_t){ PORT9, PIN5, GPIO_INPUT } /* P905 */
#define GPIO_ARDUINO_D5 (gpio_pinset_t){ PORT6, PIN1, GPIO_INPUT } /* P601 */
#define GPIO_ARDUINO_D6 (gpio_pinset_t){ PORT6, PIN2, (GPIO_OUTPUT | GPIO_LOW_DRIVE | GPIO_OUTPUT_LOW) } /* P602 */
#define GPIO_ARDUINO_D7 (gpio_pinset_t){ PORT9, PIN8, (GPIO_OUTPUT | GPIO_LOW_DRIVE | GPIO_OUTPUT_LOW) } /* P908 */
#define GPIO_ARDUINO_D8 (gpio_pinset_t){ PORT9, PIN9, (GPIO_OUTPUT | GPIO_LOW_DRIVE | GPIO_OUTPUT_LOW) } /* P909 */
#define GPIO_ARDUINO_D9 (gpio_pinset_t){ PORT6, PIN3, (GPIO_OUTPUT | GPIO_LOW_DRIVE | GPIO_OUTPUT_LOW) } /* P603 */
#define GPIO_ARDUINO_D10 (gpio_pinset_t){ PORT4, PIN13, (GPIO_OUTPUT | GPIO_LOW_DRIVE | GPIO_OUTPUT_LOW) } /* P413 */
#define GPIO_ARDUINO_D11 (gpio_pinset_t){ PORT4, PIN11, (GPIO_OUTPUT | GPIO_LOW_DRIVE | GPIO_OUTPUT_LOW) } /* P411 */
#define GPIO_ARDUINO_D12 (gpio_pinset_t){ PORT4, PIN10, (GPIO_OUTPUT | GPIO_LOW_DRIVE | GPIO_OUTPUT_LOW) } /* P410 */
#define GPIO_ARDUINO_D13 (gpio_pinset_t){ PORT4, PIN12, (GPIO_OUTPUT | GPIO_LOW_DRIVE | GPIO_OUTPUT_LOW) } /* P412 */
/* Index values for use with the /dev/gpioN devices ra8m1_gpio.c registers:
* inputs first (D2-D5, in header order), then outputs (D6-D13).
*/
#define BOARD_ARDUINO_D2_GPIO 0
#define BOARD_ARDUINO_D3_GPIO 1
#define BOARD_ARDUINO_D4_GPIO 2
#define BOARD_ARDUINO_D5_GPIO 3
#define BOARD_NGPIOIN 4
#define BOARD_ARDUINO_D6_GPIO 0
#define BOARD_ARDUINO_D7_GPIO 1
#define BOARD_ARDUINO_D8_GPIO 2
#define BOARD_ARDUINO_D9_GPIO 3
#define BOARD_ARDUINO_D10_GPIO 4
#define BOARD_ARDUINO_D11_GPIO 5
#define BOARD_ARDUINO_D12_GPIO 6
#define BOARD_ARDUINO_D13_GPIO 7
#define BOARD_NGPIOOUT 8
/* LED pin selections *******************************************************/
/* The EK-RA8M1 has three user LEDs. They are driven active high. */

View file

@ -26,6 +26,10 @@ else()
list(APPEND SRCS ra8m1_userleds.c)
endif()
if(CONFIG_DEV_GPIO)
list(APPEND SRCS ra8m1_gpio.c)
endif()
target_sources(board PRIVATE ${SRCS})
set_property(GLOBAL PROPERTY LD_SCRIPT "${NUTTX_BOARD_DIR}/scripts/ek_ra8m1.ld")

View file

@ -28,4 +28,8 @@ else
CSRCS += ra8m1_userleds.c
endif
ifeq ($(CONFIG_DEV_GPIO),y)
CSRCS += ra8m1_gpio.c
endif
include $(TOPDIR)/boards/Board.mk

View file

@ -51,5 +51,18 @@
int ra8m1_bringup(void);
/****************************************************************************
* Name: ra8m1_gpio_initialize
*
* Description:
* Register the Arduino shield header's D2-D13 with the generic GPIO
* expander driver.
*
****************************************************************************/
#ifdef CONFIG_DEV_GPIO
int ra8m1_gpio_initialize(void);
#endif
#endif /* __ASSEMBLY__ */
#endif /* __BOARDS_ARM_RA8M1_EK_RA8M1_SRC_EK_RA8M1_H */

View file

@ -37,6 +37,10 @@
#include "ek_ra8m1.h"
#ifdef CONFIG_RA_GPT_TIMER
# include "ra_gpt.h"
#endif
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@ -75,5 +79,33 @@ int ra8m1_bringup(void)
}
#endif
#ifdef CONFIG_RA_GPT0_GPT
/* GPT0 is a 32-bit timer */
ret = ra_gpt_timer_initialize("/dev/timer0", 0);
if (ret < 0)
{
syslog(LOG_ERR, "ERROR: GPT0 timer failed: %d\n", ret);
}
#endif
#ifdef CONFIG_RA_GPT9_GPT
/* GPT9 is a 16-bit timer */
ret = ra_gpt_timer_initialize("/dev/timer1", 9);
if (ret < 0)
{
syslog(LOG_ERR, "ERROR: GPT9 timer failed: %d\n", ret);
}
#endif
#ifdef CONFIG_DEV_GPIO
ret = ra8m1_gpio_initialize();
if (ret < 0)
{
syslog(LOG_ERR, "ERROR: ra8m1_gpio_initialize() failed: %d\n", ret);
}
#endif
return ret;
}

View file

@ -0,0 +1,187 @@
/****************************************************************************
* boards/arm/ra8m1/ek-ra8m1/src/ra8m1_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 <stdint.h>
#include <stdbool.h>
#include <assert.h>
#include <nuttx/ioexpander/gpio.h>
#include <arch/board/board.h>
#include "ra_gpio.h"
#include "ek_ra8m1.h"
#ifdef CONFIG_DEV_GPIO
/****************************************************************************
* Private Types
****************************************************************************/
struct ra8m1_gpio_dev_s
{
struct gpio_dev_s gpio;
uint8_t id;
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static int gpin_read(FAR struct gpio_dev_s *dev, FAR bool *value);
static int gpout_read(FAR struct gpio_dev_s *dev, FAR bool *value);
static int gpout_write(FAR struct gpio_dev_s *dev, bool value);
/****************************************************************************
* Private Data
****************************************************************************/
static const struct gpio_operations_s g_gpin_ops =
{
.go_read = gpin_read,
.go_write = NULL,
.go_attach = NULL,
.go_enable = NULL,
};
static const struct gpio_operations_s g_gpout_ops =
{
.go_read = gpout_read,
.go_write = gpout_write,
.go_attach = NULL,
.go_enable = NULL,
};
/* The Arduino Uno shield header's D2-D5 (inputs) and D6-D13 (outputs), for
* apps that use the generic GPIO expander interface (e.g.
* apps/examples/gpio, apps/examples/timer_gpio). See GPIO_ARDUINO_Dn in
* board.h for the pin mapping this comes from.
*/
static const gpio_pinset_t g_gpioinputs[BOARD_NGPIOIN] =
{
GPIO_ARDUINO_D2, GPIO_ARDUINO_D3, GPIO_ARDUINO_D4, GPIO_ARDUINO_D5
};
static const gpio_pinset_t g_gpiooutputs[BOARD_NGPIOOUT] =
{
GPIO_ARDUINO_D6, GPIO_ARDUINO_D7, GPIO_ARDUINO_D8, GPIO_ARDUINO_D9,
GPIO_ARDUINO_D10, GPIO_ARDUINO_D11, GPIO_ARDUINO_D12, GPIO_ARDUINO_D13
};
static struct ra8m1_gpio_dev_s g_gpin[BOARD_NGPIOIN];
static struct ra8m1_gpio_dev_s g_gpout[BOARD_NGPIOOUT];
/****************************************************************************
* Private Functions
****************************************************************************/
static int gpin_read(FAR struct gpio_dev_s *dev, FAR bool *value)
{
FAR struct ra8m1_gpio_dev_s *ra8m1gpio =
(FAR struct ra8m1_gpio_dev_s *)dev;
DEBUGASSERT(ra8m1gpio != NULL && value != NULL);
DEBUGASSERT(ra8m1gpio->id < BOARD_NGPIOIN);
*value = ra_gpioread(g_gpioinputs[ra8m1gpio->id]);
return OK;
}
static int gpout_read(FAR struct gpio_dev_s *dev, FAR bool *value)
{
FAR struct ra8m1_gpio_dev_s *ra8m1gpio =
(FAR struct ra8m1_gpio_dev_s *)dev;
DEBUGASSERT(ra8m1gpio != NULL && value != NULL);
DEBUGASSERT(ra8m1gpio->id < BOARD_NGPIOOUT);
*value = ra_gpioread(g_gpiooutputs[ra8m1gpio->id]);
return OK;
}
static int gpout_write(FAR struct gpio_dev_s *dev, bool value)
{
FAR struct ra8m1_gpio_dev_s *ra8m1gpio =
(FAR struct ra8m1_gpio_dev_s *)dev;
DEBUGASSERT(ra8m1gpio != NULL);
DEBUGASSERT(ra8m1gpio->id < BOARD_NGPIOOUT);
ra_gpiowrite(g_gpiooutputs[ra8m1gpio->id], value);
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: ra8m1_gpio_initialize
*
* Description:
* Register the Arduino shield header's D2-D5 (inputs) and D6-D13
* (outputs) with the generic GPIO expander driver, as /dev/gpio0-3 and
* /dev/gpio4-11 respectively.
*
****************************************************************************/
int ra8m1_gpio_initialize(void)
{
int i;
int pincount = 0;
for (i = 0; i < BOARD_NGPIOIN; i++)
{
g_gpin[i].gpio.gp_pintype = GPIO_INPUT_PIN;
g_gpin[i].gpio.gp_ops = &g_gpin_ops;
g_gpin[i].id = i;
gpio_pin_register(&g_gpin[i].gpio, pincount);
ra_configgpio(g_gpioinputs[i]);
pincount++;
}
for (i = 0; i < BOARD_NGPIOOUT; i++)
{
g_gpout[i].gpio.gp_pintype = GPIO_OUTPUT_PIN;
g_gpout[i].gpio.gp_ops = &g_gpout_ops;
g_gpout[i].id = i;
gpio_pin_register(&g_gpout[i].gpio, pincount);
ra_gpiowrite(g_gpiooutputs[i], false);
ra_configgpio(g_gpiooutputs[i]);
pincount++;
}
return OK;
}
#endif /* CONFIG_DEV_GPIO */