diff --git a/arch/arm/src/stm32/chip/stm32f33xxx_hrtim.h b/arch/arm/src/stm32/chip/stm32f33xxx_hrtim.h index 5842822ccf..8106886567 100644 --- a/arch/arm/src/stm32/chip/stm32f33xxx_hrtim.h +++ b/arch/arm/src/stm32/chip/stm32f33xxx_hrtim.h @@ -1206,7 +1206,7 @@ /* Common Burst Mode Control Register */ #define HRTIM_BMCR_BME (1 << 0) /* Bit 0: Burst Mode Enable */ -#define HRTIM_BMCR_BMOM (1 << 0) /* Bit 1: Burst Mode Operating Mode */ +#define HRTIM_BMCR_BMOM (1 << 1) /* Bit 1: Burst Mode Operating Mode */ #define HRTIM_BMCR_BMCLK_SHIFT 2 /* Bits 2-5: Burst Mode Clock Source */ #define HRTIM_BMCR_BMCLK_MASK (15 << HRTIM_BMCR_BMCLK_SHIFT) # define HRTIM_BMCR_BMCLK_0 (0 << HRTIM_BMCR_BMCLK_SHIFT) /* 0000: Master Timer Counter Reset/roll-over */ diff --git a/arch/arm/src/stm32/stm32_hrtim.c b/arch/arm/src/stm32/stm32_hrtim.c index 495b5e3ee2..b1d1e6e6e0 100644 --- a/arch/arm/src/stm32/stm32_hrtim.c +++ b/arch/arm/src/stm32/stm32_hrtim.c @@ -594,11 +594,11 @@ static int hrtim_tim_dma_cfg(FAR struct stm32_hrtim_s *priv, uint8_t timer, static int hrtim_deadtime_config(FAR struct stm32_hrtim_s *priv); #endif #ifdef CONFIG_STM32_HRTIM_BURST -int hrtim_burst_enable(FAR struct hrtim_dev_s *dev, bool state); -int hrtim_burst_cmp_update(FAR struct hrtim_dev_s *dev, uint16_t cmp); -int hrtim_burst_per_update(FAR struct hrtim_dev_s *dev, uint16_t per); -uint16_t hrtim_burst_cmp_get(FAR struct hrtim_dev_s *dev); -uint16_t hrtim_burst_per_get (FAR struct hrtim_dev_s *dev); +static int hrtim_burst_enable(FAR struct hrtim_dev_s *dev, bool state); +static int hrtim_burst_cmp_update(FAR struct hrtim_dev_s *dev, uint16_t cmp); +static int hrtim_burst_per_update(FAR struct hrtim_dev_s *dev, uint16_t per); +static uint16_t hrtim_burst_cmp_get(FAR struct hrtim_dev_s *dev); +static uint16_t hrtim_burst_per_get(FAR struct hrtim_dev_s *dev); static int hrtim_burst_config(FAR struct stm32_hrtim_s *priv); #endif #ifdef CONFIG_STM32_HRTIM_FAULTS @@ -669,7 +669,7 @@ static struct stm32_hrtim_tim_s g_master = /* If MASTER is disabled, we need only MASTER base */ #ifdef CONFIG_STM32_HRTIM_MASTER - .pclk = HRTIM_CLOCK/HRTIM_MASTER_PRESCALER, + .pclk = HRTIM_CLOCK/(HRTIM_MASTER_PRESCALER+1), .mode = HRTIM_MASTER_MODE, # ifdef CONFIG_STM32_HRTIM_MASTER_DAC .dac = HRTIM_MASTER_DAC, @@ -760,7 +760,7 @@ static struct stm32_hrtim_tim_s g_tima = .tim = { .base = STM32_HRTIM1_TIMERA_BASE, - .pclk = HRTIM_CLOCK/HRTIM_TIMA_PRESCALER, + .pclk = HRTIM_CLOCK/(HRTIM_TIMA_PRESCALER+1), .mode = HRTIM_TIMA_MODE, #ifdef CONFIG_STM32_HRTIM_TIMA_DAC .dac = HRTIM_TIMA_DAC, @@ -851,7 +851,7 @@ static struct stm32_hrtim_tim_s g_timb = .tim = { .base = STM32_HRTIM1_TIMERB_BASE, - .pclk = HRTIM_CLOCK/HRTIM_TIMB_PRESCALER, + .pclk = HRTIM_CLOCK/(HRTIM_TIMB_PRESCALER+1), .mode = HRTIM_TIMB_MODE, #ifdef CONFIG_STM32_HRTIM_TIMB_DAC .dac = HRTIM_TIMB_DAC, @@ -942,7 +942,7 @@ static struct stm32_hrtim_tim_s g_timc = .tim = { .base = STM32_HRTIM1_TIMERC_BASE, - .pclk = HRTIM_CLOCK/HRTIM_TIMC_PRESCALER, + .pclk = HRTIM_CLOCK/(HRTIM_TIMC_PRESCALER+1), .mode = HRTIM_TIMC_MODE, #ifdef CONFIG_STM32_HRTIM_TIMC_DAC .dac = HRTIM_TIMC_DAC, @@ -1033,7 +1033,7 @@ static struct stm32_hrtim_tim_s g_timd = .tim = { .base = STM32_HRTIM1_TIMERD_BASE, - .pclk = HRTIM_CLOCK/HRTIM_TIMD_PRESCALER, + .pclk = HRTIM_CLOCK/(HRTIM_TIMD_PRESCALER+1), .mode = HRTIM_TIMD_MODE, #ifdef CONFIG_STM32_HRTIM_TIMD_DAC .dac = HRTIM_TIMD_DAC, @@ -1124,7 +1124,7 @@ static struct stm32_hrtim_tim_s g_time = .tim = { .base = STM32_HRTIM1_TIMERE_BASE, - .pclk = HRTIM_CLOCK/HRTIM_TIME_PRESCALER, + .pclk = HRTIM_CLOCK/(HRTIM_TIME_PRESCALER+1), .mode = HRTIM_TIME_MODE, #ifdef CONFIG_STM32_HRTIM_TIME_DAC .dac = HRTIM_TIME_DAC, @@ -2655,7 +2655,7 @@ static int hrtim_deadtime_config(FAR struct stm32_hrtim_s *priv) * Name: hrtim_burst_enable ****************************************************************************/ -int hrtim_burst_enable(FAR struct hrtim_dev_s *dev, bool state) +static int hrtim_burst_enable(FAR struct hrtim_dev_s *dev, bool state) { FAR struct stm32_hrtim_s *priv = (FAR struct stm32_hrtim_s *)dev->hd_priv; @@ -2679,7 +2679,7 @@ int hrtim_burst_enable(FAR struct hrtim_dev_s *dev, bool state) * Name: hrtim_burst_cmp_update ****************************************************************************/ -int hrtim_burst_cmp_update(FAR struct hrtim_dev_s *dev, uint16_t cmp) +static int hrtim_burst_cmp_update(FAR struct hrtim_dev_s *dev, uint16_t cmp) { FAR struct stm32_hrtim_s *priv = (FAR struct stm32_hrtim_s *)dev->hd_priv; @@ -2692,7 +2692,7 @@ int hrtim_burst_cmp_update(FAR struct hrtim_dev_s *dev, uint16_t cmp) * Name: hrtim_burst_per_update ****************************************************************************/ -int hrtim_burst_per_update(FAR struct hrtim_dev_s *dev, uint16_t per) +static int hrtim_burst_per_update(FAR struct hrtim_dev_s *dev, uint16_t per) { FAR struct stm32_hrtim_s *priv = (FAR struct stm32_hrtim_s *)dev->hd_priv; @@ -2705,7 +2705,7 @@ int hrtim_burst_per_update(FAR struct hrtim_dev_s *dev, uint16_t per) * Name: hrtim_burst_cmp_get ****************************************************************************/ -uint16_t hrtim_burst_cmp_get(FAR struct hrtim_dev_s *dev) +static uint16_t hrtim_burst_cmp_get(FAR struct hrtim_dev_s *dev) { FAR struct stm32_hrtim_s *priv = (FAR struct stm32_hrtim_s *)dev->hd_priv; @@ -2716,7 +2716,7 @@ uint16_t hrtim_burst_cmp_get(FAR struct hrtim_dev_s *dev) * Name: hrtim_burst_per_get ****************************************************************************/ -uint16_t hrtim_burst_per_get(FAR struct hrtim_dev_s *dev) +static uint16_t hrtim_burst_per_get(FAR struct hrtim_dev_s *dev) { FAR struct stm32_hrtim_s *priv = (FAR struct stm32_hrtim_s *)dev->hd_priv; diff --git a/arch/arm/src/stm32/stm32_hrtim.h b/arch/arm/src/stm32/stm32_hrtim.h index ffd36232a5..5c5e2e4291 100644 --- a/arch/arm/src/stm32/stm32_hrtim.h +++ b/arch/arm/src/stm32/stm32_hrtim.h @@ -782,7 +782,7 @@ enum stm32_hrtim_burst_source_e enum stm32_hrtim_burst_precaler_e { - HRTIM_BURST_PRESCALER_0 = 0, + HRTIM_BURST_PRESCALER_1 = 0, HRTIM_BURST_PRESCALER_2 = 1, HRTIM_BURST_PRESCALER_4 = 2, HRTIM_BURST_PRESCALER_8 = 3, diff --git a/configs/stm32f334-disco/include/board.h b/configs/stm32f334-disco/include/board.h index da769acd6f..3345942110 100644 --- a/configs/stm32f334-disco/include/board.h +++ b/configs/stm32f334-disco/include/board.h @@ -211,44 +211,51 @@ #define GPIO_USART2_RX GPIO_USART2_RX_3 /* PB4 */ #define GPIO_USART2_TX GPIO_USART2_TX_3 /* PB3 */ -/* COMP */ +/* Board configuration for powerled example */ -/* OPAMP */ +/* - Set HRTIM TIMC output 1 on PERIOD + * - Reset HRTIM TIMC output 1 on HRTIM EEV2. + * - HRTIM EEV2 is connected to COMP4 output which works as current limit. + * - COMP4 inverting input is connected to DAC1CH1 output. + * - COMP4 non-inverting input is connceted to current sense resitor (1 Ohm). + * - DAC1CH1 DMA transfer is triggered by HRTIM TIMC events, which is used + * to provide slope compensation + */ -#define OPAMP2_VMSEL OPAMP2_VMSEL_PC5 -#define OPAMP2_VPSEL OPAMP2_VPSEL_PB14 +#if defined(CONFIG_EXAMPLES_POWERLED) -/* HRTIM */ +/* Comparators configuration ************************************************/ -#define HRTIM_TIMA_PRESCALER 2 +#define COMP4_INM COMP_INMSEL_DAC1CH1 -#define HRTIM_TIMA_CH1_SET HRTIM_OUT_SET_CMP1 -#define HRTIM_TIMA_CH1_RST HRTIM_OUT_RST_PER -#define HRTIM_TIMA_CH2_SET HRTIM_OUT_SET_PER -#define HRTIM_TIMA_CH2_RST HRTIM_OUT_RST_CMP1 +/* HRTIM configuration ******************************************************/ -#define HRTIM_FAULT_SAMPLING 0 -#define HRTIM_FAULT1_POL 0 -#define HRTIM_FAULT1_SRC 0 -#define HRTIM_FAULT1_FILTER 0 -#define HRTIM_FAULT1_LOCK 0 +#define HRTIM_TIMC_PRESCALER HRTIM_PRESCALER_1 +#define HRTIM_TIMC_MODE HRTIM_MODE_CONT +#define HRTIM_TIMC_DMA (HRTIM_DMA_REP|HRTIM_DMA_CMP1|HRTIM_DMA_CMP2| \ + HRTIM_DMA_CMP3|HRTIM_DMA_CMP4) +#define HRTIM_TIMC_CH1_SET HRTIM_OUT_SET_PER +#define HRTIM_TIMC_CH1_RST HRTIM_OUT_RST_EXTEVNT2 +#define HRTIM_TIMC_CH1_IDLE_STATE HRTIM_IDLE_INACTIVE -#define HRTIM_EEV_SAMPLING 0 -#define HRTIM_EEV1_FILTER 0 -#define HRTIM_EEV1_SRC 0 -#define HRTIM_EEV1_POL 0 -#define HRTIM_EEV1_SEN 0 -#define HRTIM_EEV1_MODE 0 +#define HRTIM_EEV_SAMPLING HRTIM_EEV_SAMPLING_d1 +#define HRTIM_EEV2_SRC HRTIM_EEV_SRC_ANALOG +#define HRTIM_EEV2_FILTER HRTIM_EEV_DISABLE +#define HRTIM_EEV2_POL HRTIM_EEV_POL_HIGH +#define HRTIM_EEV2_SEN HRTIM_EEV_SEN_LEVEL +#define HRTIM_EEV2_MODE HRTIM_EEV_MODE_FAST -#define HRTIM_ADC_TRG1 HRTIM_ADCTRG13_MC1 - -#define HRTIM_TIMA_DAC 0 +#define HRTIM_BURST_CLOCK HRTIM_BURST_CLOCK_HRTIM +#define HRTIM_BURST_PRESCALER HRTIM_BURST_PRESCALER_1 +#define HRTIM_BURST_TRIGGERS 0 /* DMA channels *************************************************************/ -/* ADC */ -#define ADC1_DMA_CHAN DMACHAN_ADC1 /* DMA1_CH1 */ -#define ADC2_DMA_CHAN DMACHAN_ADC2_1 /* DMA1_CH2 */ +/* DAC */ + +#define DAC1CH1_DMA_CHAN DMACHAN_HRTIM1_C + +#endif /* CONFIG_EXAMPLES_POWERLED */ /**************************************************************************** * Public Data diff --git a/configs/stm32f334-disco/src/Makefile b/configs/stm32f334-disco/src/Makefile index b7f839a0b7..6b9c2fb3a9 100644 --- a/configs/stm32f334-disco/src/Makefile +++ b/configs/stm32f334-disco/src/Makefile @@ -52,18 +52,10 @@ ifeq ($(CONFIG_LIB_BOARDCTL),y) CSRCS += stm32_appinit.c endif -ifeq ($(CONFIG_ADC),y) -CSRCS += stm32_adc.c -endif - ifeq ($(CONFIG_CAN),y) CSRCS += stm32_can.c endif -ifeq ($(CONFIG_DAC),y) -CSRCS += stm32_dac.c -endif - ifeq ($(CONFIG_PWM),y) CSRCS += stm32_pwm.c endif @@ -76,16 +68,8 @@ ifeq ($(CONFIG_TIMER),y) CSRCS += stm32_timer.c endif -ifeq ($(CONFIG_HRTIM),y) -CSRCS += stm32_hrtim.c -endif - -ifeq ($(CONFIG_COMP),y) -CSRCS += stm32_comp.c -endif - -ifeq ($(CONFIG_OPAMP),y) -CSRCS += stm32_opamp.c +ifeq ($(CONFIG_DRIVERS_POWERLED),y) +CSRCS += stm32_powerled.c endif include $(TOPDIR)/configs/Board.mk diff --git a/configs/stm32f334-disco/src/stm32_appinit.c b/configs/stm32f334-disco/src/stm32_appinit.c index 1e97d7681a..665ea6ae5e 100644 --- a/configs/stm32f334-disco/src/stm32_appinit.c +++ b/configs/stm32f334-disco/src/stm32_appinit.c @@ -96,6 +96,7 @@ int board_app_initialize(uintptr_t arg) { int ret; +#ifndef CONFIG_DRIVERS_POWERLED #ifdef HAVE_LEDS /* Register the LED driver */ @@ -156,6 +157,17 @@ int board_app_initialize(uintptr_t arg) syslog(LOG_ERR, "ERROR: stm32_hrtim_setup failed: %d\n", ret); } #endif +#endif + +#ifdef CONFIG_DRIVERS_POWERLED + /* Initialize powerled and register the powerled driver */ + + ret = stm32_powerled_setup(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: stm32_powerled_setup failed: %d\n", ret); + } +#endif UNUSED(ret); return OK; diff --git a/configs/stm32f334-disco/src/stm32_powerled.c b/configs/stm32f334-disco/src/stm32_powerled.c new file mode 100644 index 0000000000..9fd7137ecc --- /dev/null +++ b/configs/stm32f334-disco/src/stm32_powerled.c @@ -0,0 +1,603 @@ +/**************************************************************************** + * configs/stm32f334-disco/src/stm32_powerled.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Mateusz Szafoni + * + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include "stm32.h" + +#if defined(CONFIG_EXAMPLES_POWERLED) && defined(CONFIG_DRIVERS_POWERLED) + +#if !defined(CONFIG_STM32_HRTIM1) || !defined(CONFIG_HRTIM) +#error "Powerled example requires HRTIM1 support" +#endif + +#if !defined(CONFIG_STM32_DAC1CH1) || !defined(CONFIG_DAC) \ + || !defined(CONFIG_STM32_DAC1CH1_DMA) +#error "Powerled example requires DAC1 with DMA support" +#endif + +#if !defined(CONFIG_STM32_COMP4) || !defined(CONFIG_COMP) +#error "Powerled example requires COMP4 support" +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* REVISIT: Move to stm32_hrtim.h ? */ + +#define HRTIM_CMP_SET(hrtim, tim, index, cmp) \ + hrtim->hd_ops->cmp_update(hrtim, tim, index, cmp) +#define HRTIM_PER_SET(hrtim, tim, per) \ + hrtim->hd_ops->per_update(hrtim, tim, per) +#define HRTIM_OUTPUTS_ENABLE(hrtim, tim, state) \ + hrtim->hd_ops->outputs_enable(hrtim, tim, state) +#define HRTIM_BURST_CMP_SET(hrtim, cmp) \ + hrtim->hd_ops->burst_cmp_set(hrtim, cmp); +#define HRTIM_BURST_PER_SET(hrtim, per) \ + hrtim->hd_ops->burst_per_set(hrtim, per); +#define HRTIM_BURST_ENABLE(hrtim, state) \ + hrtim->hd_ops->burst_enable(hrtim, state); + +#if CONFIG_STM32_DAC1CH1_DMA_BUFFER_SIZE != 5 + #error "This example requires DAC1CH1 DMA buffer size == 5" +#endif + +/* Peripheral selection */ + +#define DAC_CURRENT_LIMIT 1 +#define COMP_CURRENT_LIMIT 4 + +/* Maximum onboard LED current is 350mA */ + +#define LED_ABSOLUTE_CURRENT_LIMIT_mA 250 + +/* Voltage reference for DAC */ + +#define DAC_REF_VOLTAGE_mV 3300 + +/* DAC resolution */ + +#define DAC_RESOLUTION 4096 + +/* Current sense resistance */ + +#define LED_CURRENT_SENSE_RESISTOR 1 + +/* There is 1 Ohm resistor in series with MOSFET which gives 1A/1V ratio */ + +#define CURRENT_TO_VOLTAGE_RATIO (1/(LED_CURRENT_SENSE_RESISTOR)) + +/**************************************************************************** + * Private Type Definition + ****************************************************************************/ + +/* Private data for powerled */ + +struct powerled_priv_s +{ + bool running; + uint16_t dacbuffer[CONFIG_STM32_DAC1CH1_DMA_BUFFER_SIZE]; + uint16_t current_tab[CONFIG_STM32_DAC1CH1_DMA_BUFFER_SIZE]; +}; + +/**************************************************************************** + * Private Function Protototypes + ****************************************************************************/ + +static int powerled_setup(FAR struct powerled_dev_s *dev); +static int powerled_shutdown(FAR struct powerled_dev_s *dev); +static int powerled_start(FAR struct powerled_dev_s *dev); +static int powerled_stop(FAR struct powerled_dev_s *dev); +static int powerled_params_set(FAR struct powerled_dev_s *dev, + FAR struct powerled_params_s *param); +static int powerled_mode_set(FAR struct powerled_dev_s *dev, uint8_t mode); +static int powerled_limits_set(FAR struct powerled_dev_s *dev, + FAR struct powerled_limits_s *limits); +static int powerled_state_get(FAR struct powerled_dev_s *dev, + FAR struct powerled_state_s *state); +static int powerled_fault_set(FAR struct powerled_dev_s *dev, uint8_t fault); +static int powerled_fault_get(FAR struct powerled_dev_s *dev, + FAR uint8_t *fault); +static int powerled_fault_clean(FAR struct powerled_dev_s *dev, + uint8_t fault); +static int powerled_ioctl(FAR struct powerled_dev_s *dev, int cmd, + unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +struct powerled_priv_s powerled_priv; + +struct powerled_s g_powerled = +{ + .opmode = POWERLED_OPMODE_INIT, + .state = POWERLED_STATE_INIT, + .priv = &powerled_priv +}; + +struct powerled_ops_s g_powerled_ops = +{ + .setup = powerled_setup, + .shutdown = powerled_shutdown, + .start = powerled_start, + .stop = powerled_stop, + .params_set = powerled_params_set, + .mode_set = powerled_mode_set, + .limits_set = powerled_limits_set, + .state_get = powerled_state_get, + .fault_set = powerled_fault_set, + .fault_get = powerled_fault_get, + .fault_clean = powerled_fault_clean, + .ioctl = powerled_ioctl +}; + +struct powerled_dev_s g_powerled_dev = +{ + .ops = &g_powerled_ops, + .priv = &g_powerled +}; + +/* Lower part of the POWERLED driver gather 3 pheriperals: + * - HRTIM - responsible for PWM generation + * - COMP4 - acting as current limit + * - DAC1CH1 - provides threshold voltage to comparator inverting input + */ + +struct powerled_lower_dev_s +{ + struct hrtim_dev_s *hrtim; /* PWM generation */ + struct comp_dev_s *comp; /* current limit control */ + struct dac_dev_s *dac; /* current limit threshold */ + struct adc_dev_s *adc; /* not used in this demo - only as reference */ + struct opamp_dev_s *opamp; /* not used in this demo - only as reference */ +}; + +struct powerled_lower_dev_s g_powerled_lower = +{ + .hrtim = NULL, + .comp = NULL, + .dac = NULL, + .adc = NULL, + .opamp = NULL +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int powerled_shutdown(FAR struct powerled_dev_s *dev) +{ + /* TODO ? */ + + return 0; +} + +/**************************************************************************** + * Name: powerled_setup + * + * Description: + * + * + * Returned Value: + * 0 on success, a negated errno value on failure + * + ****************************************************************************/ + +static int powerled_setup(FAR struct powerled_dev_s *dev) +{ + FAR struct powerled_lower_dev_s *lower = dev->lower; + FAR struct powerled_s *powerled = (FAR struct powerled_s *)dev->priv; + FAR struct hrtim_dev_s *hrtim = NULL; + FAR struct comp_dev_s *comp = NULL; + FAR struct dac_dev_s *dac = NULL; + FAR struct powerled_priv_s *priv = (struct powerled_priv_s *)powerled->priv; + + /* Check lower half drivers */ + + hrtim = lower->hrtim; + if (hrtim == NULL) + { + printf("ERROR: failed to get hrtim "); + } + + comp = lower->comp; + if (comp == NULL) + { + printf("ERROR: failed to get lower level interface"); + } + + dac = lower->dac; + if (dac == NULL) + { + printf("ERROR: failed to get lower level interface"); + } + + /* Do nothing */ + + return OK; +} + +static int powerled_start(FAR struct powerled_dev_s *dev) +{ + FAR struct powerled_lower_dev_s *lower = dev->lower; + FAR struct powerled_s *powerled = (FAR struct powerled_s *)dev->priv; + FAR struct hrtim_dev_s *hrtim = lower->hrtim; + FAR struct dac_dev_s *dac = lower->dac; + struct powerled_priv_s *priv = (struct powerled_priv_s *)powerled->priv; + int i = 0; + int current_av_mA = 0.0; + int current_max_mA = ((int)(powerled->limits.current * 1000)); + uint16_t burst_cmp = 0; + uint16_t burst_per = 0; + + /* Stop HRTIM PWM */ + + HRTIM_OUTPUTS_ENABLE(hrtim, HRTIM_OUT_TIMC_CH1, false); + HRTIM_BURST_ENABLE(hrtim, false); + + /* Configure according to mode */ + + if (powerled->opmode == POWERLED_OPMODE_CONTINUOUS) + { + /* Average curent set to max */ + + current_av_mA = ((uint16_t)(current_max_mA)); + + /* Dimming through burst mode IDLE state */ + + burst_per = 1000; + + burst_cmp = ((uint16_t)(((float)burst_per)*(100.0-powerled->param.brightness)/100.0)); + } + + else if (powerled->opmode == POWERLED_OPMODE_FLASH) + { + /* Average current - brightness */ + /* Flashing through burst mode IDLE state */ + + /* Maximum brightness is achieved when average LED current is equalt to + * LED current limit, and there is no IDLE state */ + + current_av_mA = ((uint16_t)(powerled->param.brightness * current_max_mA + / POWERLED_BRIGHTNESS_MAX)); + + /* TODO: configure burst mode period and compare. + * Probably need to change burst mode prescaler in run-time ?? + */ + + burst_per = 65000; + burst_cmp = 64000; + } + + /* Configure DAC buffer */ + + for (i = 0; i < CONFIG_STM32_DAC1CH1_DMA_BUFFER_SIZE; i += 1) + { + /* TODO: add slope compensation */ + + priv->current_tab[i] = current_av_mA ; + } + + /* Convert current sense value thresholds for DAC */ + + for (i = 0; i < CONFIG_STM32_DAC1CH1_DMA_BUFFER_SIZE; i += 1) + { + priv->dacbuffer[i] = priv->current_tab[i] * DAC_RESOLUTION / DAC_REF_VOLTAGE_mV; + } + + /* Write DAC buffer */ + + dac->ad_ops->ao_ioctl(dac, IO_DMABUFFER_INIT, (unsigned long)priv->dacbuffer); + + /* Configure HRTIM PWM */ + + /* 1 period is 4us - 100% time */ + + HRTIM_PER_SET(hrtim, HRTIM_TIMER_TIMC, 18432); + + /* 20% time */ + + HRTIM_CMP_SET(hrtim, HRTIM_TIMER_TIMC, HRTIM_CMP1, 3686); + + /* 40% time */ + + HRTIM_CMP_SET(hrtim, HRTIM_TIMER_TIMC, HRTIM_CMP2, 7373); + + /* 60% time */ + + HRTIM_CMP_SET(hrtim, HRTIM_TIMER_TIMC, HRTIM_CMP3, 11059); + + /* 80% time */ + + HRTIM_CMP_SET(hrtim, HRTIM_TIMER_TIMC, HRTIM_CMP4, 14746); + + /* Start DAC */ + + dac->ad_ops->ao_send(dac, NULL); + + /* Start HRTIM PWM */ + + HRTIM_OUTPUTS_ENABLE(hrtim, HRTIM_OUT_TIMC_CH1, true); + + /* Configure burst mode */ + + HRTIM_BURST_CMP_SET(hrtim, burst_cmp); + HRTIM_BURST_PER_SET(hrtim, burst_per); + HRTIM_BURST_ENABLE(hrtim, true); + + /* Set running flag */ + + if (priv->running == false) + { + priv->running = true; + } + + return OK; +} + +static int powerled_stop(FAR struct powerled_dev_s *dev) +{ + FAR struct powerled_lower_dev_s *lower = dev->lower; + FAR struct hrtim_dev_s *hrtim = lower->hrtim; + + printf("powerled_stop\n"); + + HRTIM_OUTPUTS_ENABLE(hrtim, HRTIM_OUT_TIMC_CH1, false); + + return OK; +} + +static int powerled_params_set(FAR struct powerled_dev_s *dev, + FAR struct powerled_params_s *param) +{ + FAR struct powerled_s *powerled = (FAR struct powerled_s *)dev->priv; + FAR struct powerled_lower_dev_s *lower = dev->lower; + FAR struct hrtim_dev_s *hrtim = lower->hrtim; + FAR struct dac_dev_s *dac = lower->dac; + int ret = OK; + + /* Store params in pirvate struct. */ + + powerled->param.brightness = param->brightness; + powerled->param.frequency = param->frequency; + powerled->param.duty = param->duty; + + return ret; +} + +static int powerled_mode_set(FAR struct powerled_dev_s *dev, uint8_t mode) +{ + FAR struct powerled_s *powerled = (FAR struct powerled_s *)dev->priv; + int ret = OK; + + switch (mode) + { + case POWERLED_OPMODE_CONTINUOUS: + { + powerled->opmode = mode; + break; + } + + case POWERLED_OPMODE_FLASH: + { + powerled->opmode = mode; + break; + } + + default: + { + printf("ERROR: unsupported POWERLED mode %d!\n", mode); + ret = ERROR; + goto errout; + } + } + +errout: + return ret; +} + +static int powerled_limits_set(FAR struct powerled_dev_s *dev, + FAR struct powerled_limits_s *limits) +{ + FAR struct powerled_s *powerled = (FAR struct powerled_s *)dev->priv; + int ret = OK; + + /* Some assertions */ + + if (limits->current <= 0) + { + printf("Output current limit must be set!\n"); + ret = ERROR; + goto errout; + } + + if (limits->current > LED_ABSOLUTE_CURRENT_LIMIT_mA) + { + limits->current = LED_ABSOLUTE_CURRENT_LIMIT_mA; + printf("LED current limiit > LED absoulute current limit." + " Set current limit to %d.\n", + limits->current); + } + + /* We need only output current */ + + powerled->limits.current = limits->current; + + /* Lock limits */ + + powerled->limits.lock = true; + +errout: + return ret; +} + +static int powerled_state_get(FAR struct powerled_dev_s *dev, + FAR struct powerled_state_s *state) +{ + return 0; +} + +static int powerled_fault_set(FAR struct powerled_dev_s *dev, uint8_t fault) +{ + return 0; +} + +static int powerled_fault_get(FAR struct powerled_dev_s *dev, FAR uint8_t *fault) +{ + return 0; +} + +static int powerled_fault_clean(FAR struct powerled_dev_s *dev, uint8_t fault) +{ + return 0; +} + +static int powerled_ioctl(FAR struct powerled_dev_s *dev, int cmd, unsigned long arg) +{ + int ret = ERROR; + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_powerled_setup + * + * Description: + * Initialize POWERLED driver. + * This function should be call by board_app_initialize() (?) + * + * Returned Value: + * 0 on success, a negated errno value on failure + * + ****************************************************************************/ + +int stm32_powerled_setup(void) +{ + static bool initialized = false; + struct hrtim_dev_s *hrtim = NULL; + struct comp_dev_s *comp = NULL; + struct dac_dev_s *dac = NULL; + struct powerled_lower_dev_s *lower = &g_powerled_lower; + struct powerled_dev_s *powerled = &g_powerled_dev; + int ret; + + if (!initialized) + { + /* Get the HRTIM interface */ + + hrtim = stm32_hrtiminitialize(); + if (hrtim == NULL) + { + printf("ERROR: Failed to get HRTIM1 interface\n"); + return -ENODEV; + } + + /* Get the DAC interface */ + + dac = stm32_dacinitialize(DAC_CURRENT_LIMIT); + if (dac == NULL) + { + printf("ERROR: Failed to get DAC %d interface\n", DAC_CURRENT_LIMIT); + return -ENODEV; + } + + /* Get the COMP interface */ + + comp = stm32_compinitialize(COMP_CURRENT_LIMIT); + if (comp == NULL) + { + printf("ERROR: Failed to get COMP %d interface\n", + COMP_CURRENT_LIMIT); + return -ENODEV; + } + + /* Initialize POWERLED lower driver interfaces */ + + lower->hrtim = hrtim; + lower->comp = comp; + lower->dac = dac; + lower->adc = NULL; + lower->opamp = NULL; + + /* We do not need register character drivers for POWERLED lower peripherals. + * All control should be done via POWERLED character driver. + */ + + ret = powerled_register("/dev/powerled0", powerled, (void *)lower); + if (ret < 0) + { + printf("ERROR: powerled_register failed: %d\n", ret); + return ret; + } + + initialized = true; + } + + return OK; +} + +#endif /* CONFIG_EXAMPLE_POWERLED && CONFIG_DRIVERS_POWERLED*/ diff --git a/configs/stm32f334-disco/src/stm32f334-disco.h b/configs/stm32f334-disco/src/stm32f334-disco.h index 0e3b030abf..5dd54481ab 100644 --- a/configs/stm32f334-disco/src/stm32f334-disco.h +++ b/configs/stm32f334-disco/src/stm32f334-disco.h @@ -195,4 +195,16 @@ int stm32_comp_setup(void); int stm32_opamp_setup(void); #endif +/**************************************************************************** + * Name: stm32_powerled_setup + * + * Description: + * Initialize POWERLED peripheral for the board. + * + ****************************************************************************/ + +#ifdef CONFIG_DRIVERS_POWERLED +int stm32_powerled_setup(void); +#endif + #endif /* __CONFIGS_STM32F334_DISCO_SRC_STM32F334_DISCO_H */ diff --git a/drivers/power/Make.defs b/drivers/power/Make.defs index 8fb6a638a0..7ec75e9330 100644 --- a/drivers/power/Make.defs +++ b/drivers/power/Make.defs @@ -64,6 +64,18 @@ POWER_CFLAGS := ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)drivers$ endif +# Add powerled support + +ifeq ($(CONFIG_DRIVERS_POWERLED),y) + +CSRCS += powerled.c + +POWER_DEPPATH := --dep-path power +POWER_VPATH := :power +POWER_CFLAGS := ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)drivers$(DELIM)power} + +endif + # Add battery charger drivers ifeq ($(CONFIG_BATTERY_CHARGER),y) diff --git a/drivers/power/powerled.c b/drivers/power/powerled.c new file mode 100644 index 0000000000..354221bfde --- /dev/null +++ b/drivers/power/powerled.c @@ -0,0 +1,443 @@ +/**************************************************************************** + * drivers/power/powerled.c + * Upper-half, character driver for high power LED driver. + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Mateusz Szafoni + * + * 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 +#include + +#include +#include +#include +#include + +#include + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int powerled_open(FAR struct file *filep); +static int powerled_close(FAR struct file *filep); +static int powerled_ioctl(FAR struct file *filep, int cmd, unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations powerled_fops = +{ + powerled_open, /* open */ + powerled_close, /* close */ + NULL, /* read */ + NULL, /* write */ + NULL, /* seek */ + powerled_ioctl /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , NULL /* poll */ +#endif +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + , NULL /* unlink */ +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: powerled_open + * + * Description: + * This function is called whenever the POWERLED device is opened. + * + ****************************************************************************/ + +static int powerled_open(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct powerled_dev_s *dev = inode->i_private; + uint8_t tmp; + int ret = OK; + + /* If the port is the middle of closing, wait until the close is finished */ + + if (sem_wait(&dev->closesem) != OK) + { + ret = -errno; + } + else + { + /* Increment the count of references to the device. If this the first + * time that the driver has been opened for this device, then initialize + * the device. + */ + + tmp = dev->ocount + 1; + if (tmp == 0) + { + /* More than 255 opens; uint8_t overflows to zero */ + + ret = -EMFILE; + } + else + { + /* Check if this is the first time that the driver has been opened. */ + + if (tmp == 1) + { + /* Yes.. perform one time hardware initialization. */ + + irqstate_t flags = enter_critical_section(); + ret = dev->ops->setup(dev); + if (ret == OK) + { + /* Save the new open count on success */ + + dev->ocount = tmp; + } + + leave_critical_section(flags); + } + } + + sem_post(&dev->closesem); + } + + return OK; +} + +/**************************************************************************** + * Name: powerled_close + * + * Description: + * This routine is called when the POWERLED device is closed. + * It waits for the last remaining data to be sent. + * + ****************************************************************************/ + +static int powerled_close(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct powerled_dev_s *dev = inode->i_private; + irqstate_t flags; + int ret = OK; + + if (sem_wait(&dev->closesem) != OK) + { + ret = -errno; + } + else + { + /* Decrement the references to the driver. If the reference count will + * decrement to 0, then uninitialize the driver. + */ + + if (dev->ocount > 1) + { + dev->ocount--; + sem_post(&dev->closesem); + } + else + { + /* There are no more references to the port */ + + dev->ocount = 0; + + /* Free the IRQ and disable the POWERLED device */ + + flags = enter_critical_section(); /* Disable interrupts */ + dev->ops->shutdown(dev); /* Disable the POWERLED */ + leave_critical_section(flags); + + sem_post(&dev->closesem); + } + } + + return ret; +} + +/**************************************************************************** + * Name: powerled_ioctl +****************************************************************************/ + +static int powerled_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct powerled_dev_s *dev = inode->i_private; + FAR struct powerled_s *powerled = (FAR struct powerled_s *)dev->priv; + int ret; + + switch (cmd) + { + case PWRIOC_START: + { + + /* Allow powerled start only when limits set and structure is locked */ + + if (powerled->limits.lock == false || + powerled->limits.current <= 0) + { + pwrerr("ERROR: powerled limits must be set" + " and locked before start\n"); + + ret = -EPERM; + goto errout; + } + + /* Check powerled mode */ + + if (powerled->opmode != POWERLED_OPMODE_CONTINUOUS && + powerled->opmode != POWERLED_OPMODE_FLASH) + { + pwrerr("ERROR: unsupported powerled mode!"); + + ret = -EPERM; + goto errout; + } + + /* Finally, call start from lower-half driver */ + + ret = dev->ops->start(dev); + if (ret != OK) + { + pwrerr("ERROR: PWRIOC_START failed %d\n", ret); + } + break; + } + + case PWRIOC_STOP: + { + ret = dev->ops->stop(dev); + if (ret != OK) + { + pwrerr("ERROR: PWRIOC_STOP failed %d\n", ret); + } + break; + } + + case PWRIOC_SET_MODE: + { + uint8_t mode = ((uint8_t)arg); + + ret = dev->ops->mode_set(dev, mode); + if (ret != OK) + { + pwrerr("ERROR: PWRIOC_SET_MODE failed %d\n", ret); + } + break; + } + + case PWRIOC_SET_LIMITS: + { + FAR struct powerled_limits_s *limits = + (FAR struct powerled_limits_s *)((uintptr_t)arg); + + if (powerled->limits.lock == true) + { + pwrerr("ERROR: PWRRLED limits locked!\n"); + + ret = -EPERM; + goto errout; + } + + /* NOTE: this call must set the powerled_limits_s structure */ + + ret = dev->ops->limits_set(dev, limits); + if (ret != OK) + { + pwrerr("ERROR: PWRIOC_SET_LIMITS failed %d\n", ret); + } + break; + } + + case PWRIOC_GET_STATE: + { + FAR struct powerled_state_s *state = + (FAR struct powerled_state_s *)((uintptr_t)arg); + + ret = dev->ops->state_get(dev, state); + if (ret != OK) + { + pwrerr("ERROR: PWRIOC_GET_STATE failed %d\n", ret); + } + break; + } + + case PWRIOC_SET_FAULT: + { + uint8_t fault = ((uint8_t)arg); + + ret = dev->ops->fault_set(dev, fault); + if (ret != OK) + { + pwrerr("ERROR: PWRIOC_SET_FAULT failed %d\n", ret); + } + break; + } + + case PWRIOC_GET_FAULT: + { + uint8_t *fault = ((uint8_t*)arg); + + ret = dev->ops->fault_get(dev, fault); + if (ret != OK) + { + pwrerr("ERROR: PWRIOC_GET_FAULT failed %d\n", ret); + } + break; + } + + case PWRIOC_CLEAN_FAULT: + { + uint8_t fault = ((uint8_t)arg); + + ret = dev->ops->fault_clean(dev, fault); + if (ret != OK) + { + pwrerr("ERROR: PWRIOC_CLEAN_FAULT failed %d\n", ret); + } + break; + } + + case PWRIOC_SET_PARAMS: + { + FAR struct powerled_params_s *params = + (FAR struct powerled_params_s *)((uintptr_t)arg); + + if (powerled->param.lock == true) + { + pwrerr("ERROR: powerled params locked!\n"); + + ret = -EPERM; + goto errout; + } + + if (params->brightness < 0.0 || params->brightness > 100.0 || + params->frequency < 0.0 || params->duty < 0.0 || params->duty > 100.0) + { + pwrerr("ERROR: powerled invalid parameters %f %f %f\n", + params->brightness, params->frequency, params->duty); + + ret = -EPERM; + goto errout; + } + + ret = dev->ops->params_set(dev, params); + if (ret != OK) + { + pwrerr("ERROR: PWRIOC_SET_PARAMS failed %d\n", ret); + } + break; + } + + default: + { + pwrinfo("Forwarding unrecognized cmd: %d arg: %ld\n", cmd, arg); + ret = dev->ops->ioctl(dev, cmd, arg); + break; + } + } + +errout: + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: powerled_register + ****************************************************************************/ + +int powerled_register(FAR const char *path, FAR struct powerled_dev_s *dev, FAR void *lower) +{ + int ret; + + DEBUGASSERT(path != NULL && dev != NULL && lower != NULL); + DEBUGASSERT(dev->ops != NULL); + + /* For safety reason, when some necessary low-level logic is not provided, + * system should fail before low-level hardware initialization, so: + * - all ops are checked here, before character driver registration + * - all ops must be provided, even if not used + */ + + DEBUGASSERT(dev->ops->setup != NULL); + DEBUGASSERT(dev->ops->shutdown != NULL); + DEBUGASSERT(dev->ops->stop != NULL); + DEBUGASSERT(dev->ops->start != NULL); + DEBUGASSERT(dev->ops->params_set != NULL); + DEBUGASSERT(dev->ops->mode_set != NULL); + DEBUGASSERT(dev->ops->limits_set != NULL); + DEBUGASSERT(dev->ops->fault_set != NULL); + DEBUGASSERT(dev->ops->state_get != NULL); + DEBUGASSERT(dev->ops->fault_get != NULL); + DEBUGASSERT(dev->ops->fault_clean != NULL); + DEBUGASSERT(dev->ops->ioctl != NULL); + + /* Initialize the HRTIM device structure */ + + dev->ocount = 0; + + /* Initialize semaphores */ + + sem_init(&dev->closesem, 0, 1); + + /* Connect POWERLED driver with lower level interface */ + + dev->lower = lower; + + /* Register the POWERLED character driver */ + + ret = register_driver(path, &powerled_fops, 0444, dev); + if (ret < 0) + { + sem_destroy(&dev->closesem); + } + + return ret; +} diff --git a/drivers/power/smps.c b/drivers/power/smps.c index e8fd40f458..1fa5e2a103 100644 --- a/drivers/power/smps.c +++ b/drivers/power/smps.c @@ -247,7 +247,7 @@ static int smps_ioctl(FAR struct file *filep, int cmd, unsigned long arg) smps->limits.p_in <= 0 && smps->limits.p_out <= 0 )) { pwrerr("ERROR: SMPS limits data must be set" - " and locked before SMPS start\n", ret); + " and locked before SMPS start\n"); ret = -EPERM; goto errout; @@ -300,7 +300,7 @@ static int smps_ioctl(FAR struct file *filep, int cmd, unsigned long arg) ret = dev->ops->start(dev); if (ret != OK) { - pwrerr("ERROR: SMPSC_START failed %d\n", ret); + pwrerr("ERROR: PWRIOC_START failed %d\n", ret); } break; } @@ -310,7 +310,7 @@ static int smps_ioctl(FAR struct file *filep, int cmd, unsigned long arg) ret = dev->ops->stop(dev); if (ret != OK) { - pwrerr("ERROR: SMPSC_STOP failed %d\n", ret); + pwrerr("ERROR: PWRIOC_STOP failed %d\n", ret); } break; } @@ -322,7 +322,7 @@ static int smps_ioctl(FAR struct file *filep, int cmd, unsigned long arg) ret = dev->ops->mode_set(dev, mode); if (ret != OK) { - pwrerr("ERROR: SMPSC_SET_MODE failed %d\n", ret); + pwrerr("ERROR: PWRIOC_SET_MODE failed %d\n", ret); } break; } @@ -345,7 +345,7 @@ static int smps_ioctl(FAR struct file *filep, int cmd, unsigned long arg) ret = dev->ops->limits_set(dev, limits); if (ret != OK) { - pwrerr("ERROR: SMPSC_SET_LIMITS failed %d\n", ret); + pwrerr("ERROR: PWRIOC_SET_LIMITS failed %d\n", ret); } break; } @@ -358,7 +358,7 @@ static int smps_ioctl(FAR struct file *filep, int cmd, unsigned long arg) ret = dev->ops->state_get(dev, state); if (ret != OK) { - pwrerr("ERROR: SMPSC_GET_STATE failed %d\n", ret); + pwrerr("ERROR: PWRIOC_GET_STATE failed %d\n", ret); } break; } @@ -370,7 +370,7 @@ static int smps_ioctl(FAR struct file *filep, int cmd, unsigned long arg) ret = dev->ops->fault_set(dev, fault); if (ret != OK) { - pwrerr("ERROR: SMPSC_SET_FAULT failed %d\n", ret); + pwrerr("ERROR: PWRIOC_SET_FAULT failed %d\n", ret); } break; } @@ -382,7 +382,7 @@ static int smps_ioctl(FAR struct file *filep, int cmd, unsigned long arg) ret = dev->ops->fault_get(dev, fault); if (ret != OK) { - pwrerr("ERROR: SMPSC_GET_FAULT failed %d\n", ret); + pwrerr("ERROR: PWRIOC_GET_FAULT failed %d\n", ret); } break; } @@ -394,7 +394,7 @@ static int smps_ioctl(FAR struct file *filep, int cmd, unsigned long arg) ret = dev->ops->fault_clean(dev, fault); if (ret != OK) { - pwrerr("ERROR: SMPSC_CLEAN_FAULT failed %d\n", ret); + pwrerr("ERROR: PWRIOC_CLEAN_FAULT failed %d\n", ret); } break; } @@ -461,7 +461,7 @@ static int smps_ioctl(FAR struct file *filep, int cmd, unsigned long arg) ret = dev->ops->params_set(dev, params); if (ret != OK) { - pwrerr("ERROR: SMPSC_SET_PARAMS failed %d\n", ret); + pwrerr("ERROR: PWRIOC_SET_PARAMS failed %d\n", ret); } break; } diff --git a/include/nuttx/power/powerled.h b/include/nuttx/power/powerled.h new file mode 100644 index 0000000000..873eb53f12 --- /dev/null +++ b/include/nuttx/power/powerled.h @@ -0,0 +1,251 @@ +/**************************************************************************** + * include/nuttx/power/powerled.h + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Mateusz Szafoni + * + * 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. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_DRIVERS_POWER_POWERLED_H +#define __INCLUDE_NUTTX_DRIVERS_POWER_POWERLED_H + +/* + * The powerled driver is split into two parts: + * + * 1) An "upper half", generic driver that provides the common high power LED + * interface to application level code, and + * 2) A "lower half", platform-specific driver that implements the low-level + * functionality. + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include + +#ifdef CONFIG_DRIVERS_POWERLED + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define POWERLED_BRIGHTNESS_MAX ((float)100.0) +#define POWERLED_BRIGHTNESS_MIN ((float)0.0) + +#define POWERLED_DUTY_MAX ((float)100.0) +#define POWERLED_DUTY_MIN ((float)0.0) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Powerled operation mode */ + +enum powerled_opmode_e +{ + POWERLED_OPMODE_INIT = 0, /* Initial mode */ + POWERLED_OPMODE_CONTINUOUS, /* Continuous mode */ + POWERLED_OPMODE_FLASH /* Flash mode */ +}; + +/* Powerled state */ + +enum powerled_state_e +{ + POWERLED_STATE_INIT = 0, /* Initial state */ + POWERLED_STATE_IDLE = 1, /* IDLE state */ + POWERLED_STATE_RUN = 2, /* Run state */ + POWERLED_STATE_FAULT = 3, /* Fault state */ + POWERLED_STATE_CRITICAL = 4 /* Critical Fault state */ +}; + +/* This structure describes converter state */ + +struct powerled_state_s +{ + uint8_t state; /* Powerled state */ +}; + +/* Powerled limits */ + +struct powerled_limits_s +{ + bool lock; /* This bit must be set after + * limits configuration. + */ + float current; /* Max current for LED */ +}; + +/* Powerled parameters */ + +struct powerled_params_s +{ + bool lock; /* Lock this structure. Set this bit + * if there is no need to change SMPS + * parameter during run-time. + */ + float brightness; /* LED brightnes used in continuous and + * flash mode. + * Valid value: 0.0 - 100.0 + */ + float frequency; /* Flash frequency, used in flash mode */ + float duty; /* Flash duty, used in flash mode + * Valid value: 0.0 - 100.0 + */ +}; + +/* Powerled private data strucutre */ + +struct powerled_s +{ + uint8_t opmode; /* Powerled operation mode */ + uint8_t opflags; /* Powerled operation flags */ + struct powerled_limits_s limits; /* Powerled limits */ + struct powerled_params_s param; /* Powerled settings */ + struct powerled_state_s state; /* Powerled state */ + FAR void *priv; /* Private data */ +}; + +/* Powerled operations used to call from the upper-half, generic powerled driver + * into lower-half, platform-specific logic. + */ + +struct powerled_dev_s; +struct powerled_ops_s +{ + /* Configure powerled */ + + CODE int (*setup)(FAR struct powerled_dev_s *dev); + + /* Disable converter action */ + + CODE int (*shutdown)(FAR struct powerled_dev_s *dev); + + /* Stop powerled action */ + + CODE int (*stop)(FAR struct powerled_dev_s *dev); + + /* Start powerled action */ + + CODE int (*start)(FAR struct powerled_dev_s *dev); + + /* Set powerled parameters */ + + CODE int (*params_set)(FAR struct powerled_dev_s *dev, + struct powerled_params_s *param); + + /* Set powerled operation mode */ + + CODE int (*mode_set)(FAR struct powerled_dev_s *dev, uint8_t mode); + + /* Set powerled limits */ + + CODE int (*limits_set)(FAR struct powerled_dev_s *dev, + FAR struct powerled_limits_s *limits); + + /* Set powerled fault */ + + CODE int (*fault_set)(FAR struct powerled_dev_s *dev, uint8_t fault); + + /* Get powerled state */ + + CODE int (*state_get)(FAR struct powerled_dev_s *dev, + FAR struct powerled_state_s *state); + + /* Get current fault state */ + + CODE int (*fault_get)(FAR struct powerled_dev_s *dev, FAR uint8_t *fault); + + /* Clean fault state */ + + CODE int (*fault_clean)(FAR struct powerled_dev_s *dev, uint8_t fault); + + /* Lower-half logic may support platform-specific ioctl commands */ + + CODE int (*ioctl)(FAR struct powerled_dev_s *dev, int cmd, unsigned long arg); +}; + +/* Powerled device structure used by the driver. The caller of powerled_register + * must allocate and initialize this structure. The calling logic need + * provide 'ops', 'priv' and 'lower' elements. + */ + +struct powerled_dev_s +{ + /* Fields managed by common upper half powerled logic */ + + uint8_t ocount; /* The number of times the device + * has been opened + */ + sem_t closesem; /* Locks out new opens while close + * is in progress + */ + + /* Fields provided by lower half powerled logic */ + + FAR const struct powerled_ops_s *ops; /* Arch-specific operations */ + FAR void *priv; /* Reference to powerled private data */ + FAR void *lower; /* Reference to lower level drivers */ +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: powerled_register + ****************************************************************************/ + +int powerled_register(FAR const char *path, FAR struct powerled_dev_s *dev, + FAR void *lower); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_DRIVERS_POWERLED */ +#endif /* __INCLUDE_NUTTX_DRIVERS_POWER_POWERLED_H */ diff --git a/include/nuttx/power/smps.h b/include/nuttx/power/smps.h index d1eface593..52fe6c5276 100644 --- a/include/nuttx/power/smps.h +++ b/include/nuttx/power/smps.h @@ -33,8 +33,8 @@ * ****************************************************************************/ -#ifndef __INCLUDE_NUTTX_DRIVERS_POWER_H -#define __INCLUDE_NUTTX_DRIVERS_POWER_H +#ifndef __INCLUDE_NUTTX_DRIVERS_POWER_SMPS_H +#define __INCLUDE_NUTTX_DRIVERS_POWER_SMPS_H /* * The SMPS (switched-mode power supply) driver is split into two parts: @@ -304,4 +304,4 @@ int smps_register(FAR const char *path, FAR struct smps_dev_s *dev, #endif #endif /* CONFIG_DRIVERS_SMPS */ -#endif /* __INCLUDE_NUTTX_DRIVERS_POWER_H */ +#endif /* __INCLUDE_NUTTX_DRIVERS_POWER_SMPS_H */