diff --git a/arch/arm/src/stm32l4/Kconfig b/arch/arm/src/stm32l4/Kconfig index a71d7e7faa1..15cfe093ac4 100644 --- a/arch/arm/src/stm32l4/Kconfig +++ b/arch/arm/src/stm32l4/Kconfig @@ -1221,6 +1221,7 @@ config STM32L4_TIM17 config STM32L4_COMP bool "COMP" default n + select COMP depends on STM32L4_HAVE_COMP config STM32L4_SAI1 diff --git a/arch/arm/src/stm32l4/stm32l4.h b/arch/arm/src/stm32l4/stm32l4.h index fad620ad86a..eec55e3ee91 100644 --- a/arch/arm/src/stm32l4/stm32l4.h +++ b/arch/arm/src/stm32l4/stm32l4.h @@ -57,8 +57,8 @@ #include "chip.h" #include "stm32l4_adc.h" -//#include "stm32l4_bkp.h" #include "stm32l4_can.h" +#include "stm32l4_comp.h" #include "stm32l4_dbgmcu.h" #include "stm32l4_dma.h" #include "stm32l4_exti.h" diff --git a/arch/arm/src/stm32l4/stm32l4_comp.c b/arch/arm/src/stm32l4/stm32l4_comp.c index ba0882b9736..8e2f4ff9086 100644 --- a/arch/arm/src/stm32l4/stm32l4_comp.c +++ b/arch/arm/src/stm32l4/stm32l4_comp.c @@ -1,4 +1,5 @@ -/************************************************************************************ +/**************************************************************************** + * arch/arm/src/stm32l4/stm32l4_comp.c * * Copyright (c) 2017 Gregory Nutt. All rights reserved. @@ -34,14 +35,22 @@ * 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 "chip.h" #include "stm32l4_comp.h" +#include "stm32l4_exti.h" #include "stm32l4_gpio.h" #include "up_arch.h" @@ -52,54 +61,304 @@ # error "Unrecognized STM32 chip" #endif -/************************************************************************************ +#ifdef CONFIG_STM32L4_COMP + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* COMP Register access */ + +static inline void modify_csr(FAR const struct stm32l4_comp_config_s *cfg, + uint32_t clearbits, uint32_t setbits); +static inline uint32_t get_csr(const struct stm32l4_comp_config_s *cfg); +static void stm32l4_compenable(FAR struct stm32l4_comp_config_s *cfg, + bool en); +static int stm32l4_compconfig(FAR const struct comp_dev_s *dev); + +/* COMP Driver Methods */ + +static void comp_shutdown(FAR struct comp_dev_s *dev); +static int comp_setup(FAR struct comp_dev_s *dev); +static int comp_read(FAR struct comp_dev_s *dev); +static int comp_ioctl(FAR struct comp_dev_s *dev, int cmd, + unsigned long arg); +static int comp_bind(FAR struct comp_dev_s *dev, + FAR const struct comp_callback_s *callback); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct comp_ops_s g_compops = +{ + .ao_shutdown = comp_shutdown, + .ao_setup = comp_setup, + .ao_read = comp_read, + .ao_ioctl = comp_ioctl, + .ao_bind = comp_bind, +}; + +static struct stm32l4_comp_config_s g_comp1priv = +{ + .interrupt = + { + .cb = NULL, /* will be bound to upper-half driver */ + .rising = true, + .falling = false + }, + .inp = STM32L4_COMP_INP_PIN_3, + .inm = STM32L4_COMP_INM_VREF, + .hyst = STM32L4_COMP_HYST_LOW, + .speed = STM32L4_COMP_SPEED_MEDIUM, + .inverted = false, + .csr = STM32L4_COMP1_CSR, +}; + +static struct comp_dev_s g_comp1dev = +{ + .ad_ops = &g_compops, + .ad_priv = &g_comp1priv, +}; + +static struct stm32l4_comp_config_s g_comp2priv = +{ + .interrupt = + { + .cb = NULL, /* will be bound to upper-half driver */ + .rising = true, + .falling = false + }, + .inp = STM32L4_COMP_INP_PIN_1, + .inm = STM32L4_COMP_INM_DAC_1, + .hyst = STM32L4_COMP_HYST_LOW, + .speed = STM32L4_COMP_SPEED_MEDIUM, + .inverted = false, + .csr = STM32L4_COMP2_CSR, +}; + +static struct comp_dev_s g_comp2dev = +{ + .ad_ops = &g_compops, + .ad_priv = &g_comp2priv, +}; + +/**************************************************************************** * Private Functions - ************************************************************************************/ + ****************************************************************************/ -/************************************************************************************ +/**************************************************************************** * Name: modify_csr - ************************************************************************************/ + ****************************************************************************/ -static inline void modify_csr(int cmp, uint32_t clearbits, uint32_t setbits) +static inline void modify_csr(FAR const struct stm32l4_comp_config_s *cfg, + uint32_t clearbits, uint32_t setbits) { - modifyreg32(cmp == STM32L4_COMP1 ? STM32L4_COMP1_CSR : STM32L4_COMP2_CSR, - clearbits, setbits); + modifyreg32(cfg->csr, clearbits, setbits); } -/************************************************************************************ +/**************************************************************************** * Name: get_csr - ************************************************************************************/ + ****************************************************************************/ -static inline uint32_t get_csr(int cmp) +static inline uint32_t get_csr(const struct stm32l4_comp_config_s *cfg) { - return getreg32(cmp == STM32L4_COMP1 ? STM32L4_COMP1_CSR : STM32L4_COMP2_CSR); + return getreg32(cfg->csr); } -/************************************************************************************* - * Public Functions - ************************************************************************************/ +/**************************************************************************** + * Name: comp_setup + * + * Description: + * Configure the COMP. This method is called the first time that the COMP + * device is opened. This will occur when the port is first opened. + * This setup includes configuring and attaching COMP interrupts. + * + * Input Parameters: + * dev - pointer to device structure used by the driver + * + * Returned Value: + * + ****************************************************************************/ -/************************************************************************************ +static int comp_setup(FAR struct comp_dev_s *dev) +{ + int ret; + + /* Configure selected comparator */ + + ret = stm32l4_compconfig(dev); + if (ret < 0) + { + aerr("ERROR: Failed to initialize COMP: %d\n", ret); + return ret; + } + + return OK; +} + +/**************************************************************************** + * Name: comp_shutdown + * + * Description: + * Disable the COMP. This method is called when the COMP device is closed. + * This method reverses the operation the setup method. + * Works only if COMP device is not locked. + * + * Input Parameters: + * dev - pointer to device structure used by the driver + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void comp_shutdown(FAR struct comp_dev_s *dev) +{ + FAR struct stm32l4_comp_config_s *cfg; + + cfg = dev->ad_priv; + stm32l4_compenable(cfg, false); +} + +/**************************************************************************** + * Name: comp_read + * + * Description: + * Get the COMP output state. + * + * Input Parameters: + * dev - pointer to device structure used by the driver + * + * Returned Value: + * 0 if output is low (non-inverting input below inverting input), + * 1 if output is high (non inverting input above inverting input). + * + ****************************************************************************/ + +static int comp_read(FAR struct comp_dev_s *dev) +{ + FAR struct stm32l4_comp_config_s *cfg; + uint32_t regval; + + cfg = dev->ad_priv; + regval = get_csr(cfg); + + return (((regval & COMP_CSR_VALUE) == 0) ? 0 : 1); +} + +/**************************************************************************** + * Name: comp_ioctl + * + * Description: + * All ioctl calls will be routed through this method. + * + * Input Parameters: + * dev - pointer to device structure used by the driver + * cmd - command + * arg - arguments passed with command + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int comp_ioctl(FAR struct comp_dev_s *dev, int cmd, unsigned long arg) +{ +#warning "Missing logic" + return -ENOTTY; +} + +/**************************************************************************** + * Name: comp_bind + * + * Description: + * Bind upper half callback. + * + * Input Parameters: + * dev - pointer to device structure used by the driver + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int comp_bind(FAR struct comp_dev_s *dev, + FAR const struct comp_callback_s *callback) +{ + FAR struct stm32l4_comp_config_s *priv = + (FAR struct stm32l4_comp_config_s *)dev->ad_priv; + + DEBUGASSERT(priv != NULL); + priv->interrupt.cb = callback; + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32l4_compenable + * + * Description: + * Enable/disable comparator + * + * Parameters: + * cmp - comparator + * cfg - enable/disable flag + * + ****************************************************************************/ + +static void stm32l4_compenable(FAR struct stm32l4_comp_config_s *cfg, bool en) +{ + uint32_t clearbits = en ? 0 : COMP_CSR_EN; + uint32_t setbits = en ? COMP_CSR_EN : 0; + + modify_csr(cfg, clearbits, setbits); +} + +static int stm32l4_exti_comp_isr(int irq, void *context, FAR void *arg) +{ + FAR struct comp_dev_s *dev = (FAR struct comp_dev_s *)arg; + struct stm32l4_comp_config_s *cfg = dev->ad_priv; + + DEBUGASSERT(cfg->interrupt.cb && + (cfg->interrupt.rising || cfg->interrupt.falling)); + + ainfo("isr: %d\n", (cfg->csr == STM32L4_COMP1_CSR ? 0 : 1)); + + cfg->interrupt.cb->au_notify(dev, comp_read(dev)); + + return 0; +} + +/**************************************************************************** * Name: stm32l4_compconfig * * Description: * Configure comparator and I/Os used as comparators inputs * * Parameters: - * cmp - comparator * cfg - configuration * * Returns: * 0 on success, a negated errno value on failure * - ************************************************************************************/ + ****************************************************************************/ -int stm32l4_compconfig(int cmp, const struct stm32l4_comp_config_s *cfg) +static int stm32l4_compconfig(FAR const struct comp_dev_s *dev) { + FAR struct stm32l4_comp_config_s *cfg; uint32_t regval = 0; uint32_t mask = 0; uint32_t clearbits; uint32_t setbits; + int ret; + int cmp; + + cfg = dev->ad_priv; + cmp = cfg->csr == STM32L4_COMP1_CSR ? STM32L4_COMP1 : STM32L4_COMP2; /* Input plus */ @@ -269,49 +528,76 @@ int stm32l4_compconfig(int cmp, const struct stm32l4_comp_config_s *cfg) clearbits = regval ^ mask; setbits = regval; - modify_csr(cmp, clearbits, setbits); + modify_csr(cfg, clearbits, setbits); + + /* Enable */ + + stm32l4_compenable(cfg, true); + + /* Enable interrupt */ + + if (cfg->interrupt.cb && (cfg->interrupt.rising || cfg->interrupt.falling)) + { + ret = stm32l4_exti_comp(cmp, cfg->interrupt.rising, cfg->interrupt.falling, + 0, stm32l4_exti_comp_isr, (void *)dev); + if (ret < 0) + { + aerr("stm32l4_exti_comp failed ret = %d\n", ret); + return ERROR; + } + } + + ainfo("comp%d configured\n", cmp); + return 0; } -/************************************************************************************ - * Name: stm32l4_compenable +/**************************************************************************** + * Name: stm32l4_compinitialize * * Description: - * Enable/disable comparator + * Initialize the COMP. * - * Parameters: - * cmp - comparator - * cfg - enable/disable flag + * Input Parameters: + * intf - The COMP interface number. * - * Returns: - * 0 on success, a negated errno value on failure + * Returned Value: + * Valid COMP device structure reference on success; a NULL on failure. * - ************************************************************************************/ + * Assumptions: + * 1. Clock to the COMP block has enabled, + * 2. Board-specific logic has already configured + * + ****************************************************************************/ -int stm32l4_compenable(int cmp, bool en) +FAR struct comp_dev_s* stm32l4_compinitialize(int intf, + FAR const struct stm32l4_comp_config_s *cfg) { - uint32_t clearbits = en ? 0 : COMP_CSR_EN; - uint32_t setbits = en ? COMP_CSR_EN : 0; + FAR struct comp_dev_s *dev; - modify_csr(cmp, clearbits, setbits); - return 0; + switch (intf) + { + case 1: + ainfo("COMP1 selected\n"); + dev = &g_comp1dev; + break; + + case 2: + ainfo("COMP2 selected\n"); + dev = &g_comp2dev; + break; + + default: + aerr("ERROR: No COMP interface defined\n"); + return NULL; + } + + if (cfg) + { + memcpy(dev->ad_priv, cfg, sizeof(*cfg)); + } + + return dev; } -/************************************************************************************ - * Name: stm32l4_compread - * - * Description: - * Read comparator output - * - * Parameters: - * - cmp: comparator - * - * Returns: - * true for high, false for low - * - ************************************************************************************/ - -bool stm32l4_compread(int cmp) -{ - return !!(get_csr(cmp) & COMP_CSR_VALUE); -} +#endif /* CONFIG_STM32L4_COMP */ diff --git a/arch/arm/src/stm32l4/stm32l4_comp.h b/arch/arm/src/stm32l4/stm32l4_comp.h index 8262c6ef65e..029c26c7308 100644 --- a/arch/arm/src/stm32l4/stm32l4_comp.h +++ b/arch/arm/src/stm32l4/stm32l4_comp.h @@ -51,6 +51,7 @@ ************************************************************************************/ #if defined(CONFIG_STM32L4_STM32L4X3) + /* Comparators */ enum stm32l4_comp_e @@ -142,11 +143,19 @@ enum stm32l4_comp_speed_e struct stm32l4_comp_config_s { - uint8_t inp; /* Plus input pin (see enum stm32l4_comp_inp_e) */ - uint8_t inm; /* Minus input pin (see enum stm32l4_comp_inm_e) */ - uint8_t hyst; /* Hysteresis (see enum stm32l4_comp_hyst_e) */ - uint8_t speed; /* Speed (see stm32l4_comp_speed_e) */ - bool inverted; /* Invert output? */ + struct + { + FAR const struct comp_callback_s *cb; + bool rising; + bool falling; + } interrupt; + + uint8_t inp; /* Plus input pin (see enum stm32l4_comp_inp_e) */ + uint8_t inm; /* Minus input pin (see enum stm32l4_comp_inm_e) */ + uint8_t hyst; /* Hysteresis (see enum stm32l4_comp_hyst_e) */ + uint8_t speed; /* Speed (see stm32l4_comp_speed_e) */ + bool inverted; /* Invert output? */ + uint32_t csr; /* Control and status register */ }; /************************************************************************************ @@ -162,55 +171,27 @@ extern "C" #define EXTERN extern #endif -/************************************************************************************ - * Name: stm32l4_compconfig +/**************************************************************************** + * Name: stm32l4_compinitialize * * Description: - * Configure comparator and I/Os used as comparators inputs + * Initialize the COMP. * - * Parameters: - * cmp - comparator - * cfg - configuration + * Input Parameters: + * intf - The COMP interface number. + * cfg - configuration * - * Returns: - * 0 on success, a negated errno value on failure + * Returned Value: + * Valid COMP device structure reference on success; a NULL on failure. * - ************************************************************************************/ + * Assumptions: + * 1. Clock to the COMP block has enabled, + * 2. Board-specific logic has already configured + * + ****************************************************************************/ -int stm32l4_compconfig(int cmp, const struct stm32l4_comp_config_s *cfg); - -/************************************************************************************ - * Name: stm32l4_compenable - * - * Description: - * Enable/disable comparator - * - * Parameters: - * cmp - comparator - * cfg - enable/disable flag - * - * Returns: - * 0 on success, a negated errno value on failure - * - ************************************************************************************/ - -int stm32l4_compenable(int cmp, bool en); - -/************************************************************************************ - * Name: stm32l4_compread - * - * Description: - * Read comparator output - * - * Parameters: - * - cmp: comparator - * - * Returns: - * true for high, false for low - * - ************************************************************************************/ - -bool stm32l4_compread(int cmp); +FAR struct comp_dev_s* stm32l4_compinitialize(int intf, + FAR const struct stm32l4_comp_config_s *cfg); #undef EXTERN #ifdef __cplusplus diff --git a/arch/arm/src/stm32l4/stm32l4_exti_comp.c b/arch/arm/src/stm32l4/stm32l4_exti_comp.c index 7aaa8b2f48d..147eb3f4b48 100644 --- a/arch/arm/src/stm32l4/stm32l4_exti_comp.c +++ b/arch/arm/src/stm32l4/stm32l4_exti_comp.c @@ -159,23 +159,23 @@ int stm32l4_exti_comp(int cmp, bool risingedge, bool fallingedge, up_disable_irq(STM32L4_IRQ_COMP); } - /* Configure rising/falling edges */ + /* Configure rising/falling edges */ - modifyreg32(STM32L4_EXTI1_RTSR, risingedge ? 0 : ln, risingedge ? ln : 0); - modifyreg32(STM32L4_EXTI1_FTSR, fallingedge ? 0 : ln, fallingedge ? ln : 0); + modifyreg32(STM32L4_EXTI1_RTSR, risingedge ? 0 : ln, risingedge ? ln : 0); + modifyreg32(STM32L4_EXTI1_FTSR, fallingedge ? 0 : ln, fallingedge ? ln : 0); - /* Enable Events and Interrupts */ + /* Enable Events and Interrupts */ - modifyreg32(STM32L4_EXTI1_EMR, event ? 0 : ln, event ? ln : 0); - modifyreg32(STM32L4_EXTI1_IMR, func ? 0 : ln, func ? ln : 0); + modifyreg32(STM32L4_EXTI1_EMR, event ? 0 : ln, event ? ln : 0); + modifyreg32(STM32L4_EXTI1_IMR, func ? 0 : ln, func ? ln : 0); - /* Get the previous IRQ handler and save the new IRQ handler. */ + /* Get the previous IRQ handler and save the new IRQ handler. */ - g_comp_handlers[cmp].callback = func; - g_comp_handlers[cmp].arg = arg; + g_comp_handlers[cmp].callback = func; + g_comp_handlers[cmp].arg = arg; - /* Leave the critical section */ + /* Leave the critical section */ - leave_critical_section(flags); - return OK; + leave_critical_section(flags); + return OK; }