diff --git a/configs/photon/include/board.h b/configs/photon/include/board.h index e9ec9e1e71..f8503eaa24 100644 --- a/configs/photon/include/board.h +++ b/configs/photon/include/board.h @@ -204,6 +204,26 @@ * 2Hz, then a fatal error has been detected and the system has halted. */ +/* TIM */ + +#define GPIO_TIM2_CH2OUT GPIO_TIM2_CH2OUT_1 +#define GPIO_TIM2_CH3OUT GPIO_TIM2_CH3OUT_1 +#define GPIO_TIM2_CH4OUT GPIO_TIM2_CH4OUT_1 + +/* RGB LED + * + * R = TIM2 CH2 on PA1 | G = TIM2 CH3 on PA2 | B = TIM4 CH4 on PA3 + * + * Note: Pin configs: GPIO_TIM2_CH2OUT ; GPIO_TIM2_CH3OUT ; GPIO_TIM2_CH4OUT + */ + +#define RGBLED_RPWMTIMER 2 +#define RGBLED_RPWMCHANNEL 2 +#define RGBLED_GPWMTIMER 2 +#define RGBLED_GPWMCHANNEL 3 +#define RGBLED_BPWMTIMER 2 +#define RGBLED_BPWMCHANNEL 4 + /* Button definitions ***************************************************************/ #define BOARD_BUTTON1 0 diff --git a/configs/photon/rgbled/defconfig b/configs/photon/rgbled/defconfig new file mode 100644 index 0000000000..94c6239fd2 --- /dev/null +++ b/configs/photon/rgbled/defconfig @@ -0,0 +1,69 @@ +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="photon" +CONFIG_ARCH_BOARD_PHOTON=y +CONFIG_ARCH_CHIP_STM32F205RG=y +CONFIG_ARCH_CHIP_STM32=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARDCTL_USBDEVCTRL=y +CONFIG_BOARD_LOOPSPERMSEC=16717 +CONFIG_BUILTIN=y +CONFIG_CDCACM_CONSOLE=y +CONFIG_CDCACM=y +# CONFIG_DEV_CONSOLE is not set +CONFIG_DISABLE_POLL=y +CONFIG_EXAMPLES_NSH=y +CONFIG_EXAMPLES_RGBLED=y +CONFIG_FS_PROCFS=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_HAVE_CXX=y +CONFIG_INTELHEX_BINARY=y +CONFIG_MAX_TASKS=16 +CONFIG_MAX_WDOGPARMS=2 +CONFIG_MM_REGIONS=2 +CONFIG_NFILE_DESCRIPTORS=8 +CONFIG_NFILE_STREAMS=8 +CONFIG_NSH_ARCHINIT=y +# CONFIG_NSH_ARGCAT is not set +CONFIG_NSH_BUILTIN_APPS=y +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +# CONFIG_NSH_CMDPARMS is not set +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_READLINE=y +CONFIG_PHOTON_DFU_BOOTLOADER=y +CONFIG_PHOTON_IWDG=y +CONFIG_PHOTON_WDG_THREAD=y +CONFIG_PREALLOC_MQ_MSGS=4 +CONFIG_PREALLOC_TIMERS=4 +CONFIG_PREALLOC_WDOGS=16 +CONFIG_PWM_MULTICHAN=y +CONFIG_PWM_NCHANNELS=4 +CONFIG_PWM=y +CONFIG_RAMLOG_BUFSIZE=8192 +CONFIG_RAMLOG_SYSLOG=y +CONFIG_RAMLOG=y +CONFIG_RAM_SIZE=114688 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_RGBLED=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_SDCLONE_DISABLE=y +CONFIG_START_DAY=6 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2011 +CONFIG_STM32_IWDG=y +CONFIG_STM32_JTAG_SW_ENABLE=y +CONFIG_STM32_OTGHS=y +CONFIG_STM32_PWM_MULTICHAN=y +CONFIG_STM32_TIM2_CH2OUT=y +CONFIG_STM32_TIM2_CH3OUT=y +CONFIG_STM32_TIM2_CH4OUT=y +CONFIG_STM32_TIM2_CHANNEL2=y +CONFIG_STM32_TIM2_CHANNEL3=y +CONFIG_STM32_TIM2_CHANNEL4=y +CONFIG_STM32_TIM2_PWM=y +CONFIG_STM32_TIM2=y +CONFIG_STM32_USART1=y +CONFIG_USBDEV=y +CONFIG_USER_ENTRYPOINT="nsh_main" diff --git a/configs/photon/src/Makefile b/configs/photon/src/Makefile index 253117c3da..43c7ef34c7 100644 --- a/configs/photon/src/Makefile +++ b/configs/photon/src/Makefile @@ -68,4 +68,8 @@ ifeq ($(CONFIG_STM32_OTGHS),y) CSRCS += stm32_usb.c endif +ifeq ($(CONFIG_RGBLED),y) + CSRCS += stm32_rgbled.c +endif + include $(TOPDIR)/configs/Board.mk diff --git a/configs/photon/src/photon.h b/configs/photon/src/photon.h index 5b2412f7e0..e07f142160 100644 --- a/configs/photon/src/photon.h +++ b/configs/photon/src/photon.h @@ -132,6 +132,26 @@ void weak_function stm32_spidev_initialize(void); int photon_watchdog_initialize(void); #endif +/**************************************************************************** + * Name: stm32_rgbled_setup + * + * Description: + * This function is called by board initialization logic to configure the + * RGB LED driver. This function will register the driver as /dev/rgbled0. + * + * Input Parameters: + * None + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +#ifdef CONFIG_RGBLED +int stm32_rgbled_setup(void); +#endif + /**************************************************************************** * Name: photon_wlan_initialize * diff --git a/configs/photon/src/stm32_bringup.c b/configs/photon/src/stm32_bringup.c index d55f3bc291..1354d6fb8f 100644 --- a/configs/photon/src/stm32_bringup.c +++ b/configs/photon/src/stm32_bringup.c @@ -132,6 +132,16 @@ int stm32_bringup(void) } #endif +#ifdef CONFIG_RGBLED + /* Configure and initialize the RGB LED. */ + + ret = stm32_rgbled_setup(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: stm32_rgbled_setup() failed: %d\n", ret); + } +#endif + #ifdef CONFIG_PHOTON_WLAN /* Initialize wlan driver and hardware */ diff --git a/configs/photon/src/stm32_rgbled.c b/configs/photon/src/stm32_rgbled.c new file mode 100644 index 0000000000..b60c0a6803 --- /dev/null +++ b/configs/photon/src/stm32_rgbled.c @@ -0,0 +1,251 @@ +/************************************************************************************ + * configs/photon/src/stm32_rgbled.c + * + * Copyright (C) 2018 Verge Inc. All rights reserved. + * Author: Anthony Merlino + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include + +#include +#include +#include + +#include "chip.h" +#include "up_arch.h" +#include "stm32_pwm.h" +#include "photon.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ +/* Configuration ********************************************************************/ + +#define HAVE_RGBLED 1 + +#ifndef CONFIG_PWM +# undef HAVE_RGBLED +#endif + +#ifndef CONFIG_STM32_TIM2 +# undef HAVE_RGBLED +#endif + +#ifndef CONFIG_PWM_MULTICHAN +# undef HAVE_RGBLED +#endif + +#ifndef CONFIG_STM32_TIM2_PWM +# undef HAVE_RGBLED +#endif + +#ifndef CONFIG_STM32_TIM2_CHANNEL2 +# undef HAVE_PWM +#endif + +#ifndef CONFIG_STM32_TIM2_CHANNEL3 +# undef HAVE_PWM +#endif + +#ifndef CONFIG_STM32_TIM2_CHANNEL4 +# undef HAVE_PWM +#endif + +#ifdef HAVE_RGBLED + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_rgbled_setup + * + * Description: + * Initial for support of a connected RGB LED using PWM. + * + ************************************************************************************/ + +int stm32_rgbled_setup(void) +{ + static bool initialized = false; + struct pwm_lowerhalf_s *ledr; + struct pwm_lowerhalf_s *ledg; + struct pwm_lowerhalf_s *ledb; + struct pwm_info_s info; + int i; + int ret; + + /* Have we already initialized? */ + + if (!initialized) + { + /* Call stm32_pwminitialize() to get an instance of the PWM interface */ + + ledr = stm32_pwminitialize(RGBLED_RPWMTIMER); + if (!ledr) + { + lederr("ERROR: Failed to get the STM32 PWM lower half to LEDR\n"); + return -ENODEV; + } + + ledr->ops->setup(ledr); + + /* Call stm32_pwminitialize() to get an instance of the PWM interface */ + + ledg = stm32_pwminitialize(RGBLED_GPWMTIMER); + if (!ledg) + { + lederr("ERROR: Failed to get the STM32 PWM lower half to LEDG\n"); + return -ENODEV; + } + + ledg->ops->setup(ledg); + + /* Call stm32_pwminitialize() to get an instance of the PWM interface */ + + ledb = stm32_pwminitialize(RGBLED_BPWMTIMER); + if (!ledb) + { + lederr("ERROR: Failed to get the STM32 PWM lower half to LEDB\n"); + return -ENODEV; + } + + ledb->ops->setup(ledb); + + /* Define frequency and duty cycle */ + + info.frequency = 100; + +#ifdef CONFIG_PWM_MULTICHAN + + /* Setup the duty cycle and channel for red */ + + i = 0; + info.channels[i].duty = 0; + info.channels[i++].channel = RGBLED_RPWMCHANNEL; + + /* If red and green use same timer, setup together */ + + if (RGBLED_RPWMTIMER == RGBLED_GPWMTIMER) + { + info.channels[i++].channel = RGBLED_GPWMCHANNEL; + } + + /* If red and blue use same timer, setup together */ + + if (RGBLED_RPWMTIMER == RGBLED_BPWMTIMER) + { + info.channels[i++].channel = RGBLED_BPWMCHANNEL; + } + + /* Start the timer used for red, and any other colors that are + * sourced on a different channel of the same timer */ + + ledr->ops->start(ledr, &info); + + /* Clear the channels from the struct */ + + for (i = 0; i < CONFIG_PWM_NCHANNELS; i++) + { + info.channels[i].channel = 0; + } + + /* If the green timer is not the same as the red timer, then set it up. */ + + if (RGBLED_GPWMTIMER != RGBLED_RPWMTIMER) + { + i = 0; + info.channels[i++].channel = RGBLED_GPWMCHANNEL; + + /* If the blue timer uses the same timer and the green */ + + if (RGBLED_GPWMTIMER == RGBLED_BPWMTIMER) + { + info.channels[i++].channel = RGBLED_BPWMCHANNEL; + } + + /* Start green timer (and maybe blue) */ + + ledg->ops->start(ledg, &info); + + /* Clear the channels from the struct */ + + for (i = 0; i < CONFIG_PWM_NCHANNELS; i++) + { + info.channels[i].channel = 0; + } + } + + /* If the blue timer is different than the red and the green, it must be setup seperately */ + + if (RGBLED_BPWMTIMER != RGBLED_RPWMTIMER && RGBLED_BPWMTIMER != RGBLED_GPWMTIMER) + { + info.channels[0].channel = RGBLED_BPWMCHANNEL; + ledb->ops->start(ledb, &info); + } +#else + info.duty = 0; + ledr->ops->start(ledr, &info); + ledg->ops->start(ledg, &info); + ledb->ops->start(ledb, &info); +#endif + + /* Register the RGB LED diver at "/dev/rgbled0" */ + +#ifdef CONFIG_PWM_MULTICHAN + ret = rgbled_register("/dev/rgbled0", ledr, ledg, ledb, RGBLED_RPWMCHANNEL, RGBLED_GPWMCHANNEL, RGBLED_BPWMCHANNEL); +#else + ret = rgbled_register("/dev/rgbled0", ledr, ledg, ledb); +#endif + if (ret < 0) + { + lederr("ERROR: rgbled_register failed: %d\n", ret); + return ret; + } + + /* Now we are initialized */ + + initialized = true; + } + + return OK; +} + +#else +# error "HAVE_RGBLED is undefined" +#endif /* HAVE_RGBLED */