This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 1971ddd081e70eb557ce71e357c5f5e4b48e1906 Author: Matteo Golin <[email protected]> AuthorDate: Wed Jul 8 16:17:27 2026 -0400 boards/raspberrypi-4b: Bring up PWM devices Brings up PWM interfaces for the RPi4B when enabled. Signed-off-by: Matteo Golin <[email protected]> --- boards/arm64/bcm2711/raspberrypi-4b/Kconfig | 9 ++ .../bcm2711/raspberrypi-4b/src/CMakeLists.txt | 6 +- boards/arm64/bcm2711/raspberrypi-4b/src/Makefile | 4 + boards/arm64/bcm2711/raspberrypi-4b/src/rpi4b.h | 13 ++ .../bcm2711/raspberrypi-4b/src/rpi4b_bringup.c | 4 + .../arm64/bcm2711/raspberrypi-4b/src/rpi4b_pwm.c | 152 +++++++++++++++++++++ 6 files changed, 187 insertions(+), 1 deletion(-) diff --git a/boards/arm64/bcm2711/raspberrypi-4b/Kconfig b/boards/arm64/bcm2711/raspberrypi-4b/Kconfig index 6628e835924..f0eeff0acb7 100644 --- a/boards/arm64/bcm2711/raspberrypi-4b/Kconfig +++ b/boards/arm64/bcm2711/raspberrypi-4b/Kconfig @@ -68,4 +68,13 @@ config RPI4B_BMP280 ---help--- Registers the driver for the BMP280 sensor on I2C1 for experimenting. +config RPI4B_AUDIOJACK + bool "Enable audio over jack" + default n + depends on AUDIO_TONE + depends on BCM2711_PWM1 + ---help--- + Enables PWM-based audio over the on-board audio jack. Device registered + as /dev/tone1. + endif # ARCH_BOARD_RASPBERRYPI_4B diff --git a/boards/arm64/bcm2711/raspberrypi-4b/src/CMakeLists.txt b/boards/arm64/bcm2711/raspberrypi-4b/src/CMakeLists.txt index e3c6860ae15..259867ab621 100644 --- a/boards/arm64/bcm2711/raspberrypi-4b/src/CMakeLists.txt +++ b/boards/arm64/bcm2711/raspberrypi-4b/src/CMakeLists.txt @@ -29,11 +29,15 @@ if(CONFIG_DEV_GPIO) endif() if(CONFIG_RPI4B_SDMMC) - list(APPEND rpi4b_sdmmc.c) + list(APPEND SRCS rpi4b_sdmmc.c) endif() if(CONFIG_BCM2711_I2C_DRIVER) list(APPEND SRCS bcm2711_i2cdev.c) endif() +if(CONFIG_BCM2711_PWM) + list(APPEND SRCS rpi4b_pwm.c) +endif() + target_sources(board PRIVATE ${SRCS}) diff --git a/boards/arm64/bcm2711/raspberrypi-4b/src/Makefile b/boards/arm64/bcm2711/raspberrypi-4b/src/Makefile index 214f2a084c2..5f51b37c869 100644 --- a/boards/arm64/bcm2711/raspberrypi-4b/src/Makefile +++ b/boards/arm64/bcm2711/raspberrypi-4b/src/Makefile @@ -38,6 +38,10 @@ ifeq ($(CONFIG_BCM2711_I2C_DRIVER),y) CSRCS += bcm2711_i2cdev.c endif +ifeq ($(CONFIG_BCM2711_PWM),y) +CSRCS += rpi4b_pwm.c +endif + include $(TOPDIR)/boards/Board.mk .PHONY: distclean diff --git a/boards/arm64/bcm2711/raspberrypi-4b/src/rpi4b.h b/boards/arm64/bcm2711/raspberrypi-4b/src/rpi4b.h index 72f3d7caa2c..e842e4be966 100644 --- a/boards/arm64/bcm2711/raspberrypi-4b/src/rpi4b.h +++ b/boards/arm64/bcm2711/raspberrypi-4b/src/rpi4b.h @@ -57,6 +57,19 @@ int rpi4b_bringup(void); int rpi4b_sdmmc_initialize(void); #endif +/**************************************************************************** + * Name: rpi4b_pwm_initialize + * + * Description: + * Initialize PWM interfaces on the RPi4B. + * Also initializes PWM-audio driver if that was selected + * + ****************************************************************************/ + +#if defined(CONFIG_BCM2711_PWM) +int rpi4b_pwm_initialize(void); +#endif + #if defined(CONFIG_DEV_GPIO) int bcm2711_dev_gpio_init(void); #endif /* defined(CONFIG_DEV_GPIO) */ diff --git a/boards/arm64/bcm2711/raspberrypi-4b/src/rpi4b_bringup.c b/boards/arm64/bcm2711/raspberrypi-4b/src/rpi4b_bringup.c index 98097cb031a..e6c027d35db 100644 --- a/boards/arm64/bcm2711/raspberrypi-4b/src/rpi4b_bringup.c +++ b/boards/arm64/bcm2711/raspberrypi-4b/src/rpi4b_bringup.c @@ -160,6 +160,10 @@ int rpi4b_bringup(void) } #endif +#ifdef CONFIG_BCM2711_PWM + ret = rpi4b_pwm_initialize(); +#endif + #ifdef CONFIG_RPI4B_BMP280 struct i2c_master_s *i2c1 = bcm2711_i2cbus_initialize(1); if (i2c1 == NULL) diff --git a/boards/arm64/bcm2711/raspberrypi-4b/src/rpi4b_pwm.c b/boards/arm64/bcm2711/raspberrypi-4b/src/rpi4b_pwm.c new file mode 100644 index 00000000000..7fc0b194ff6 --- /dev/null +++ b/boards/arm64/bcm2711/raspberrypi-4b/src/rpi4b_pwm.c @@ -0,0 +1,152 @@ +/**************************************************************************** + * boards/arm64/bcm2711/raspberrypi-4b/src/rpi4b_pwm.c + * + * Contributed by: Matteo Golin <[email protected]> + * + * SPDX-License-Identifer: 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 <nuttx/debug.h> + +#include <syslog.h> +#include <errno.h> + +#include <nuttx/timers/pwm.h> +#include <nuttx/timers/oneshot.h> + +#ifdef CONFIG_RPI4B_AUDIOJACK +#include <nuttx/audio/tone.h> +#endif + +#include "bcm2711_pwm.h" +#include "bcm2711_oneshot.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rpi4b_pwm_initialize + * + * Description: + * Initialize PWM interfaces on the RPi4B. + * Also initializes PWM-audio driver if that was selected + * + ****************************************************************************/ + +int rpi4b_pwm_initialize(void) +{ + int ret = 0; + int err = 0; +#ifdef CONFIG_BCM2711_PWM0 + struct pwm_lowerhalf_s *pwm0; +#endif +#ifdef CONFIG_BCM2711_PWM1 + struct pwm_lowerhalf_s *pwm1; +#endif +#ifdef CONFIG_RPI4B_AUDIOJACK + struct oneshot_lowerhalf_s *oneshot; +#endif + +#ifdef CONFIG_BCM2711_PWM0 + pwm0 = bcm2711_pwminitialize(0); + if (pwm0 == NULL) + { + syslog(LOG_ERR, "Couldn't initialize PWM0."); + err = -EAGAIN; + ret = err; + } + + /* Only try to register if initialization was successful */ + + if (err == 0) + { + err = pwm_register("/dev/pwm0", pwm0); + if (err < 0) + { + syslog(LOG_ERR, "Couldn't register PWM0: %d\n", err); + ret = err; + } + } +#endif /* CONFIG_BCM2711_PWM0 */ + +#ifdef CONFIG_BCM2711_PWM1 + pwm1 = bcm2711_pwminitialize(1); + if (pwm1 == NULL) + { + syslog(LOG_ERR, "Couldn't initialize PWM1."); + err = -EAGAIN; + ret = err; + } + + /* Only try to register if initialization was successful */ + + if (err == 0) + { + err = pwm_register("/dev/pwm1", pwm1); + if (err < 0) + { + syslog(LOG_ERR, "Couldn't register PWM1: %d\n", err); + ret = err; + } + } +#endif /* CONFIG_BCM2711_PWM1 */ + +#ifdef CONFIG_RPI4B_AUDIOJACK + + /* Don't try to register audio device with NULL lower-half */ + + if (pwm1 == NULL) + { + audwarn("PWM1 not setup, skipping tone registration."); + return ret; + } + + /* Get a oneshot timer driver. We allocate timer 0 for this. I pick a + * random resolution of 10us since I know the BCM2711 timer driver can do + * 1us of resolution and ignores this parameter otherwise. + */ + + oneshot = oneshot_initialize(0, 10); + if (oneshot == NULL) + { + syslog(LOG_ERR, "Couldn't initialize one-shot timer channel 0."); + return -EAGAIN; + } + + /* NOTE: The PWM interface supports two channels. We register the audio + * device on the first one. + */ + + audinfo("Registering /dev/tone1 using PWM1 channel 1."); + err = tone_register("/dev/tone1", pwm1, 1, oneshot); + if (err != 0) + { + syslog(LOG_ERR, "Couldn't register PWM audio tone driver: %d\n", err); + ret = err; + } +#endif /* CONFIG_RPI4B_AUDIOJACK */ + + return ret; +}
