STM32L4 COMP: bind to upper half comp driver

This commit is contained in:
Pekka Ervasti 2017-08-22 06:47:57 -06:00 committed by Gregory Nutt
parent cc0fea60ad
commit 6b1ccef2f9
5 changed files with 384 additions and 116 deletions

View File

@ -1221,6 +1221,7 @@ config STM32L4_TIM17
config STM32L4_COMP
bool "COMP"
default n
select COMP
depends on STM32L4_HAVE_COMP
config STM32L4_SAI1

View File

@ -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"

View File

@ -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 <nuttx/config.h>
#include <debug.h>
#include <string.h>
#include <nuttx/analog/comp.h>
#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 */

View File

@ -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

View File

@ -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;
}