Correct error in clock_gettime(); fix wait for STOP in I2C stm32 driver
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3948 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
bdf8ede547
commit
455b9336fb
@ -2070,3 +2070,7 @@
|
|||||||
temperature sensor driver.
|
temperature sensor driver.
|
||||||
* configs/stm3210e-eval/src/up_lm75.c: Add support for the LM-75 on the
|
* configs/stm3210e-eval/src/up_lm75.c: Add support for the LM-75 on the
|
||||||
STMicro STM3210E-EVAL board.
|
STMicro STM3210E-EVAL board.
|
||||||
|
* sched/clock_gettime.c: Correct an error in the tv_nsec calculation
|
||||||
|
that happens only config CONFIG_RTC is enabled.
|
||||||
|
* arch/arm/src/stm32/stm32_i2c.c: Correct some bugs related to waiting
|
||||||
|
to the I2C STOP condition to be cleared.
|
||||||
|
@ -429,12 +429,25 @@ static inline void stm32_i2c_sendstart(FAR struct stm32_i2c_priv_s *priv)
|
|||||||
|
|
||||||
static inline void stm32_i2c_clrstart(FAR struct stm32_i2c_priv_s *priv)
|
static inline void stm32_i2c_clrstart(FAR struct stm32_i2c_priv_s *priv)
|
||||||
{
|
{
|
||||||
/* "This [START] bit is set and cleared by software and cleared by hardware
|
/* "Note: When the STOP, START or PEC bit is set, the software must
|
||||||
|
* not perform any write access to I2C_CR1 before this bit is
|
||||||
|
* cleared by hardware. Otherwise there is a risk of setting a
|
||||||
|
* second STOP, START or PEC request."
|
||||||
|
*
|
||||||
|
* "The [STOP] bit is set and cleared by software, cleared by hardware
|
||||||
|
* when a Stop condition is detected, set by hardware when a timeout
|
||||||
|
* error is detected.
|
||||||
|
*
|
||||||
|
* "This [START] bit is set and cleared by software and cleared by hardware
|
||||||
* when start is sent or PE=0." The bit must be cleared by software if the
|
* when start is sent or PE=0." The bit must be cleared by software if the
|
||||||
* START is never sent.
|
* START is never sent.
|
||||||
|
*
|
||||||
|
* "This [PEC] bit is set and cleared by software, and cleared by hardware
|
||||||
|
* when PEC is transferred or by a START or Stop condition or when PE=0."
|
||||||
*/
|
*/
|
||||||
|
|
||||||
stm32_i2c_modifyreg(priv, STM32_I2C_CR1_OFFSET, I2C_CR1_START, 0);
|
stm32_i2c_modifyreg(priv, STM32_I2C_CR1_OFFSET,
|
||||||
|
I2C_CR1_START|I2C_CR1_STOP|I2C_CR1_PEC, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void stm32_i2c_sendstop(FAR struct stm32_i2c_priv_s *priv)
|
static inline void stm32_i2c_sendstop(FAR struct stm32_i2c_priv_s *priv)
|
||||||
@ -871,6 +884,7 @@ int stm32_i2c_process(FAR struct i2c_dev_s *dev, FAR struct i2c_msg_s *msgs, int
|
|||||||
struct stm32_i2c_inst_s *inst = (struct stm32_i2c_inst_s *)dev;
|
struct stm32_i2c_inst_s *inst = (struct stm32_i2c_inst_s *)dev;
|
||||||
uint32_t status = 0;
|
uint32_t status = 0;
|
||||||
uint32_t ahbenr;
|
uint32_t ahbenr;
|
||||||
|
uint16_t regval;
|
||||||
int status_errno = 0;
|
int status_errno = 0;
|
||||||
|
|
||||||
ASSERT(count);
|
ASSERT(count);
|
||||||
@ -879,15 +893,43 @@ int stm32_i2c_process(FAR struct i2c_dev_s *dev, FAR struct i2c_msg_s *msgs, int
|
|||||||
|
|
||||||
ahbenr = stm32_i2c_disablefsmc(inst->priv);
|
ahbenr = stm32_i2c_disablefsmc(inst->priv);
|
||||||
|
|
||||||
/* Wait as stop might still be in progress
|
/* Wait as stop might still be in progress; but stop might also
|
||||||
*
|
* be set because of a timeout error: "The [STOP] bit is set and
|
||||||
* \todo GET RID OF THIS PERFORMANCE LOSS and for() loop
|
* cleared by software, cleared by hardware when a Stop condition is
|
||||||
|
* detected, set by hardware when a timeout error is detected."
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for (; stm32_i2c_getreg(inst->priv, STM32_I2C_CR1_OFFSET) & I2C_CR1_STOP; )
|
for (;;)
|
||||||
{
|
{
|
||||||
up_waste();
|
/* Check for STOP condition */
|
||||||
|
|
||||||
|
regval = stm32_i2c_getreg(inst->priv, STM32_I2C_CR1_OFFSET);
|
||||||
|
if ((regval & I2C_CR1_STOP) == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for timeout error */
|
||||||
|
|
||||||
|
regval = stm32_i2c_getreg(inst->priv, STM32_I2C_SR1_OFFSET);
|
||||||
|
if ((regval & I2C_SR1_TIMEOUT) != 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Clear any pending error interrupts */
|
||||||
|
|
||||||
|
stm32_i2c_putreg(inst->priv, STM32_I2C_SR1_OFFSET, 0);
|
||||||
|
|
||||||
|
/* "Note: When the STOP, START or PEC bit is set, the software must
|
||||||
|
* not perform any write access to I2C_CR1 before this bit is
|
||||||
|
* cleared by hardware. Otherwise there is a risk of setting a
|
||||||
|
* second STOP, START or PEC request." However, if the bits are
|
||||||
|
* not cleared by hardware, then we will have to do that from hardware.
|
||||||
|
*/
|
||||||
|
|
||||||
|
stm32_i2c_clrstart(inst->priv);
|
||||||
|
|
||||||
/* Old transfers are done */
|
/* Old transfers are done */
|
||||||
|
|
||||||
@ -898,10 +940,6 @@ int stm32_i2c_process(FAR struct i2c_dev_s *dev, FAR struct i2c_msg_s *msgs, int
|
|||||||
|
|
||||||
stm32_i2c_setclock(inst->priv, inst->frequency);
|
stm32_i2c_setclock(inst->priv, inst->frequency);
|
||||||
|
|
||||||
/* Clear any pending error interrupts */
|
|
||||||
|
|
||||||
stm32_i2c_putreg(inst->priv, STM32_I2C_SR1_OFFSET, 0);
|
|
||||||
|
|
||||||
/* Trigger start condition, then the process moves into the ISR. I2C
|
/* Trigger start condition, then the process moves into the ISR. I2C
|
||||||
* interrupts will be enabled within stm32_i2c_waitisr().
|
* interrupts will be enabled within stm32_i2c_waitisr().
|
||||||
*/
|
*/
|
||||||
@ -917,10 +955,10 @@ int stm32_i2c_process(FAR struct i2c_dev_s *dev, FAR struct i2c_msg_s *msgs, int
|
|||||||
status = stm32_i2c_getstatus(inst->priv);
|
status = stm32_i2c_getstatus(inst->priv);
|
||||||
status_errno = ETIMEDOUT;
|
status_errno = ETIMEDOUT;
|
||||||
|
|
||||||
/* " Note: When the STOP, START or PEC bit is set, the software must
|
/* "Note: When the STOP, START or PEC bit is set, the software must
|
||||||
* not perform any write access to I2C_CR1 before this bit is
|
* not perform any write access to I2C_CR1 before this bit is
|
||||||
* cleared by hardware. Otherwise there is a risk of setting a
|
* cleared by hardware. Otherwise there is a risk of setting a
|
||||||
* second STOP, START or PEC request."
|
* second STOP, START or PEC request."
|
||||||
*/
|
*/
|
||||||
|
|
||||||
stm32_i2c_clrstart(inst->priv);
|
stm32_i2c_clrstart(inst->priv);
|
||||||
@ -936,6 +974,8 @@ int stm32_i2c_process(FAR struct i2c_dev_s *dev, FAR struct i2c_msg_s *msgs, int
|
|||||||
|
|
||||||
if ((status & I2C_SR1_ERRORMASK) != 0)
|
if ((status & I2C_SR1_ERRORMASK) != 0)
|
||||||
{
|
{
|
||||||
|
/* I2C_SR1_ERRORMASK is the 'OR' of the following individual bits: */
|
||||||
|
|
||||||
if (status & I2C_SR1_BERR)
|
if (status & I2C_SR1_BERR)
|
||||||
{
|
{
|
||||||
/* Bus Error */
|
/* Bus Error */
|
||||||
@ -975,7 +1015,7 @@ int stm32_i2c_process(FAR struct i2c_dev_s *dev, FAR struct i2c_msg_s *msgs, int
|
|||||||
|
|
||||||
/* This is not an error and should never happen since SMBus is not enabled */
|
/* This is not an error and should never happen since SMBus is not enabled */
|
||||||
|
|
||||||
else if (status & I2C_SR1_SMBALERT)
|
else /* if (status & I2C_SR1_SMBALERT) */
|
||||||
{
|
{
|
||||||
/* SMBus alert is an optional signal with an interrupt line for devices
|
/* SMBus alert is an optional signal with an interrupt line for devices
|
||||||
* that want to trade their ability to master for a pin.
|
* that want to trade their ability to master for a pin.
|
||||||
@ -987,9 +1027,11 @@ int stm32_i2c_process(FAR struct i2c_dev_s *dev, FAR struct i2c_msg_s *msgs, int
|
|||||||
|
|
||||||
/* This is not an error, but should not happen. The BUSY signal can hang,
|
/* This is not an error, but should not happen. The BUSY signal can hang,
|
||||||
* however, if there are unhealthy devices on the bus that need to be reset.
|
* however, if there are unhealthy devices on the bus that need to be reset.
|
||||||
|
* NOTE: We will only see this buy indication if stm32_i2c_sem_waitisr()
|
||||||
|
* fails above; Otherwise it is cleared.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
else if (status & (I2C_SR2_BUSY << 16))
|
else if ((status & (I2C_SR2_BUSY << 16)) != 0)
|
||||||
{
|
{
|
||||||
/* I2C Bus is for some reason busy */
|
/* I2C Bus is for some reason busy */
|
||||||
|
|
||||||
@ -1016,7 +1058,7 @@ int stm32_i2c_write(FAR struct i2c_dev_s *dev, const uint8_t *buffer, int buflen
|
|||||||
.buffer = (uint8_t *)buffer,
|
.buffer = (uint8_t *)buffer,
|
||||||
.length = buflen
|
.length = buflen
|
||||||
};
|
};
|
||||||
|
|
||||||
return stm32_i2c_process(dev, &msgv, 1);
|
return stm32_i2c_process(dev, &msgv, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ Contents
|
|||||||
- NuttX buildroot Toolchain
|
- NuttX buildroot Toolchain
|
||||||
- DFU
|
- DFU
|
||||||
- LEDs
|
- LEDs
|
||||||
|
- Temperature Sensor
|
||||||
- STM3210E-EVAL-specific Configuration Options
|
- STM3210E-EVAL-specific Configuration Options
|
||||||
- Configurations
|
- Configurations
|
||||||
|
|
||||||
@ -237,6 +238,32 @@ They are encoded as follows:
|
|||||||
on a small proportion of the time.
|
on a small proportion of the time.
|
||||||
*** LED2 may also flicker normally if signals are processed.
|
*** LED2 may also flicker normally if signals are processed.
|
||||||
|
|
||||||
|
Temperature Sensor
|
||||||
|
==================
|
||||||
|
|
||||||
|
Support for the on-board LM-75 temperature sensor is available. This supported
|
||||||
|
has been verified, but has not been included in any of the available the
|
||||||
|
configurations. To set up the temperature sensor, add the following to the
|
||||||
|
NuttX configuration file
|
||||||
|
|
||||||
|
CONFIG_I2C=y
|
||||||
|
CONFIG_I2C_LM75=y
|
||||||
|
|
||||||
|
Then you can implement logic like the following to use the temperature sensor:
|
||||||
|
|
||||||
|
#include <nuttx/sensors/lm75.h>
|
||||||
|
#include <arch/board/board.h>
|
||||||
|
|
||||||
|
ret = stm32_lm75initialize("/dev/temp"); /* Register the temperature sensor */
|
||||||
|
fd = open("/dev/temp", O_RDONLY); /* Open the temperature sensor device */
|
||||||
|
ret = ioctl(fd, SNIOC_FAHRENHEIT, 0); /* Select Fahrenheit */
|
||||||
|
bytesread = read(fd, buffer, 8*sizeof(b16_t)); /* Read temperature samples */
|
||||||
|
|
||||||
|
More complex temperature sensor operations are also available. See the IOCTAL
|
||||||
|
commands enumerated in include/nuttx/sensors/lm75.h. Also read the descriptions
|
||||||
|
of the stm32_lm75initialize() and stm32_lm75attach() interfaces in the
|
||||||
|
arch/board/board.h file (sames as configs/stm3210e-eval/include/board.h).
|
||||||
|
|
||||||
STM3210E-EVAL-specific Configuration Options
|
STM3210E-EVAL-specific Configuration Options
|
||||||
============================================
|
============================================
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <fixedmath.h>
|
#include <fixedmath.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
#include <nuttx/fs.h>
|
#include <nuttx/fs.h>
|
||||||
#include <nuttx/i2c.h>
|
#include <nuttx/i2c.h>
|
||||||
@ -57,7 +58,19 @@
|
|||||||
/* Centigrade to Fahrenheit conversion: F = 9*C/5 + 32 */
|
/* Centigrade to Fahrenheit conversion: F = 9*C/5 + 32 */
|
||||||
|
|
||||||
#define B16_9DIV5 (9 * 65536 / 5)
|
#define B16_9DIV5 (9 * 65536 / 5)
|
||||||
#define B16_32 (32 * 65536);
|
#define B16_32 (32 * 65536)
|
||||||
|
|
||||||
|
/* Debug for this file only */
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_LM75
|
||||||
|
# define lm75dbg dbg
|
||||||
|
#else
|
||||||
|
# ifdef CONFIG_CPP_HAVE_VARARGS
|
||||||
|
# define lm75dbg(x...)
|
||||||
|
# else
|
||||||
|
# define lm75dbg (void)
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private
|
* Private
|
||||||
@ -75,14 +88,12 @@ struct lm75_dev_s
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
/* I2C Helpers */
|
/* I2C Helpers */
|
||||||
|
|
||||||
static int lm75_readb8(FAR struct lm75_dev_s *priv, uint8_t regaddr,
|
static int lm75_readb16(FAR struct lm75_dev_s *priv, uint8_t regaddr,
|
||||||
FAR b8_t *regvalue);
|
FAR b16_t *regvalue);
|
||||||
#if 0 // Not used
|
static int lm75_writeb16(FAR struct lm75_dev_s *priv, uint8_t regaddr,
|
||||||
static int lm75_writeb8(FAR struct lm75_dev_s *priv, uint8_t regaddr,
|
b16_t regval);
|
||||||
b8_t regval);
|
static int lm75_readtemp(FAR struct lm75_dev_s *priv, FAR b16_t *temp);
|
||||||
#endif
|
static int lm75_readconf(FAR struct lm75_dev_s *priv, FAR uint8_t *conf);
|
||||||
static int lm75_readtemp(FAR struct lm75_dev_s *priv, b16_t *temp);
|
|
||||||
static int lm75_readconf(FAR struct lm75_dev_s *priv, uint8_t *conf);
|
|
||||||
static int lm75_writeconf(FAR struct lm75_dev_s *priv, uint8_t conf);
|
static int lm75_writeconf(FAR struct lm75_dev_s *priv, uint8_t conf);
|
||||||
|
|
||||||
/* Character driver methods */
|
/* Character driver methods */
|
||||||
@ -114,15 +125,15 @@ static const struct file_operations lm75_fops =
|
|||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: lm75_readb8
|
* Name: lm75_readb16
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Read a 16-bit register (LM75_TEMP_REG, LM75_THYS_REG, or LM75_TOS_REG)
|
* Read a 16-bit register (LM75_TEMP_REG, LM75_THYS_REG, or LM75_TOS_REG)
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int lm75_readb8(FAR struct lm75_dev_s *priv, uint8_t regaddr,
|
static int lm75_readb16(FAR struct lm75_dev_s *priv, uint8_t regaddr,
|
||||||
FAR b8_t *regvalue)
|
FAR b16_t *regvalue)
|
||||||
{
|
{
|
||||||
uint8_t buffer[2];
|
uint8_t buffer[2];
|
||||||
int ret;
|
int ret;
|
||||||
@ -133,6 +144,7 @@ static int lm75_readb8(FAR struct lm75_dev_s *priv, uint8_t regaddr,
|
|||||||
ret = I2C_WRITE(priv->i2c, ®addr, 1);
|
ret = I2C_WRITE(priv->i2c, ®addr, 1);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
|
lm75dbg("I2C_WRITE failed: %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,43 +153,49 @@ static int lm75_readb8(FAR struct lm75_dev_s *priv, uint8_t regaddr,
|
|||||||
ret = I2C_READ(priv->i2c, buffer, 2);
|
ret = I2C_READ(priv->i2c, buffer, 2);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
|
lm75dbg("I2C_READ failed: %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Data format is: TTTTTTTT Txxxxxxx where TTTTTTTTT is a nine-bit
|
/* Data format is: TTTTTTTT Txxxxxxx where TTTTTTTTT is a nine-bit,
|
||||||
* temperature value with LSB = 0.5 degrees centigrade. So the raw
|
* signed temperature value with LSB = 0.5 degrees centigrade. So the
|
||||||
* data is b8_t
|
* raw data is b8_t
|
||||||
*/
|
*/
|
||||||
|
|
||||||
*regvalue = (b8_t)buffer[0] << 8 | (b8_t)buffer[1];
|
*regvalue = b8tob16((b8_t)buffer[0] << 8 | (b8_t)buffer[1]);
|
||||||
|
lm75dbg("addr: %02x value: %08x ret: %d\n", regaddr, *regvalue, ret);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: lm75_writeb8
|
* Name: lm75_writeb16
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Write to a 16-bit register (LM75_TEMP_REG, LM75_THYS_REG, or LM75_TOS_REG)
|
* Write to a 16-bit register (LM75_TEMP_REG, LM75_THYS_REG, or LM75_TOS_REG)
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#if 0 // Not used
|
|
||||||
static int lm75_writeb8(FAR struct lm75_dev_s *priv, uint8_t regaddr,
|
static int lm75_writeb16(FAR struct lm75_dev_s *priv, uint8_t regaddr,
|
||||||
b8_t regval)
|
b16_t regval)
|
||||||
{
|
{
|
||||||
uint8_t buffer[3];
|
uint8_t buffer[3];
|
||||||
|
b8_t regb8;
|
||||||
|
|
||||||
|
lm75dbg("addr: %02x value: %08x\n", regaddr, regval);
|
||||||
|
|
||||||
/* Set up a 3 byte message to send */
|
/* Set up a 3 byte message to send */
|
||||||
|
|
||||||
buffer[0] = regaddr;
|
buffer[0] = regaddr;
|
||||||
buffer[1] = regval >> 8;
|
|
||||||
buffer[2] = regval;
|
regb8 = b16tob8(regval);
|
||||||
|
buffer[1] = (uint8_t)(regb8 >> 8);
|
||||||
|
buffer[2] = (uint8_t)regb8;
|
||||||
|
|
||||||
/* Write the register address followed by the data (no RESTART) */
|
/* Write the register address followed by the data (no RESTART) */
|
||||||
|
|
||||||
I2C_SETADDRESS(priv->i2c, priv->addr, 7);
|
I2C_SETADDRESS(priv->i2c, priv->addr, 7);
|
||||||
return I2C_WRITE(priv->i2c, buffer, 3);
|
return I2C_WRITE(priv->i2c, buffer, 3);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: lm75_readtemp
|
* Name: lm75_readtemp
|
||||||
@ -187,26 +205,20 @@ static int lm75_writeb8(FAR struct lm75_dev_s *priv, uint8_t regaddr,
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int lm75_readtemp(FAR struct lm75_dev_s *priv, b16_t *temp)
|
static int lm75_readtemp(FAR struct lm75_dev_s *priv, FAR b16_t *temp)
|
||||||
{
|
{
|
||||||
b8_t temp8;
|
|
||||||
b16_t temp16;
|
b16_t temp16;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Read the raw temperature data. Data format is: TTTTTTTT Txxxxxxx where
|
/* Read the raw temperature data (b16_t) */
|
||||||
* TTTTTTTTT is a nine-bit temperature value with LSB = 0.5 degrees centigrade.
|
|
||||||
* So the raw data is b8_t.
|
ret = lm75_readb16(priv, LM75_TEMP_REG, &temp16);
|
||||||
*/
|
|
||||||
|
|
||||||
ret = lm75_readb8(priv, LM75_TEMP_REG, &temp8);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
|
lm75dbg("lm75_readb16 failed: %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
lm75dbg("Centigrade: %08x\n", temp16);
|
||||||
/* Convert to b16_t */
|
|
||||||
|
|
||||||
temp16 = b8tob16(temp8);
|
|
||||||
|
|
||||||
/* Was fahrenheit requested? */
|
/* Was fahrenheit requested? */
|
||||||
|
|
||||||
@ -215,6 +227,7 @@ static int lm75_readtemp(FAR struct lm75_dev_s *priv, b16_t *temp)
|
|||||||
/* Centigrade to Fahrenheit conversion: F = 9*C/5 + 32 */
|
/* Centigrade to Fahrenheit conversion: F = 9*C/5 + 32 */
|
||||||
|
|
||||||
temp16 = b16mulb16(temp16, B16_9DIV5) + B16_32;
|
temp16 = b16mulb16(temp16, B16_9DIV5) + B16_32;
|
||||||
|
lm75dbg("Fahrenheit: %08x\n", temp16);
|
||||||
}
|
}
|
||||||
|
|
||||||
*temp = temp16;
|
*temp = temp16;
|
||||||
@ -229,7 +242,7 @@ static int lm75_readtemp(FAR struct lm75_dev_s *priv, b16_t *temp)
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int lm75_readconf(FAR struct lm75_dev_s *priv, uint8_t *conf)
|
static int lm75_readconf(FAR struct lm75_dev_s *priv, FAR uint8_t *conf)
|
||||||
{
|
{
|
||||||
uint8_t buffer;
|
uint8_t buffer;
|
||||||
int ret;
|
int ret;
|
||||||
@ -242,12 +255,14 @@ static int lm75_readconf(FAR struct lm75_dev_s *priv, uint8_t *conf)
|
|||||||
ret = I2C_WRITE(priv->i2c, &buffer, 1);
|
ret = I2C_WRITE(priv->i2c, &buffer, 1);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
|
lm75dbg("I2C_WRITE failed: %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Restart and read 8-bits from the register */
|
/* Restart and read 8-bits from the register */
|
||||||
|
|
||||||
ret = I2C_READ(priv->i2c, conf, 1);
|
ret = I2C_READ(priv->i2c, conf, 1);
|
||||||
|
lm75dbg("conf: %02x ret: %d\n", *conf, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,6 +278,8 @@ static int lm75_writeconf(FAR struct lm75_dev_s *priv, uint8_t conf)
|
|||||||
{
|
{
|
||||||
uint8_t buffer[2];
|
uint8_t buffer[2];
|
||||||
|
|
||||||
|
lm75dbg("conf: %02x\n", conf);
|
||||||
|
|
||||||
/* Set up a 2 byte message to send */
|
/* Set up a 2 byte message to send */
|
||||||
|
|
||||||
buffer[0] = LM75_CONF_REG;
|
buffer[0] = LM75_CONF_REG;
|
||||||
@ -310,16 +327,19 @@ static ssize_t lm75_read(FAR struct file *filep, FAR char *buffer, size_t buflen
|
|||||||
FAR struct lm75_dev_s *priv = inode->i_private;
|
FAR struct lm75_dev_s *priv = inode->i_private;
|
||||||
FAR b16_t *ptr;
|
FAR b16_t *ptr;
|
||||||
ssize_t nsamples;
|
ssize_t nsamples;
|
||||||
|
int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* How many samples were requested to get? */
|
/* How many samples were requested to get? */
|
||||||
|
|
||||||
nsamples = buflen/sizeof(b16_t);
|
nsamples = buflen / sizeof(b16_t);
|
||||||
ptr = (FAR b16_t *)buffer;
|
ptr = (FAR b16_t *)buffer;
|
||||||
|
|
||||||
|
lm75dbg("buflen: %d nsamples: %d\n", buflen, nsamples);
|
||||||
|
|
||||||
/* Get the requested number of samples */
|
/* Get the requested number of samples */
|
||||||
|
|
||||||
for (; nsamples > 0; nsamples--)
|
for (i = 0; i < nsamples; i++)
|
||||||
{
|
{
|
||||||
b16_t temp;
|
b16_t temp;
|
||||||
|
|
||||||
@ -328,6 +348,7 @@ static ssize_t lm75_read(FAR struct file *filep, FAR char *buffer, size_t buflen
|
|||||||
ret = lm75_readtemp(priv, &temp);
|
ret = lm75_readtemp(priv, &temp);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
|
lm75dbg("lm75_readtemp failed: %d\n",ret);
|
||||||
return (ssize_t)ret;
|
return (ssize_t)ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -359,7 +380,7 @@ static int lm75_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||||||
FAR struct lm75_dev_s *priv = inode->i_private;
|
FAR struct lm75_dev_s *priv = inode->i_private;
|
||||||
int ret = OK;
|
int ret = OK;
|
||||||
|
|
||||||
switch (arg)
|
switch (cmd)
|
||||||
{
|
{
|
||||||
/* Read from the configuration register. Arg: uint8_t* pointer */
|
/* Read from the configuration register. Arg: uint8_t* pointer */
|
||||||
|
|
||||||
@ -367,6 +388,7 @@ static int lm75_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||||||
{
|
{
|
||||||
FAR uint8_t *ptr = (FAR uint8_t *)((uintptr_t)arg);
|
FAR uint8_t *ptr = (FAR uint8_t *)((uintptr_t)arg);
|
||||||
ret = lm75_readconf(priv, ptr);
|
ret = lm75_readconf(priv, ptr);
|
||||||
|
lm75dbg("conf: %02x ret: %d\n", *ptr, ret);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -374,6 +396,7 @@ static int lm75_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||||||
|
|
||||||
case SNIOC_WRITECONF:
|
case SNIOC_WRITECONF:
|
||||||
ret = lm75_writeconf(priv, (uint8_t)arg);
|
ret = lm75_writeconf(priv, (uint8_t)arg);
|
||||||
|
lm75dbg("conf: %02x ret: %d\n", *(uint8_t*)arg, ret);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Shutdown the LM75, Arg: None */
|
/* Shutdown the LM75, Arg: None */
|
||||||
@ -386,6 +409,7 @@ static int lm75_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||||||
{
|
{
|
||||||
ret = lm75_writeconf(priv, conf | LM75_CONF_SHUTDOWN);
|
ret = lm75_writeconf(priv, conf | LM75_CONF_SHUTDOWN);
|
||||||
}
|
}
|
||||||
|
lm75dbg("conf: %02x ret: %d\n", conf | LM75_CONF_SHUTDOWN, ret);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -399,6 +423,7 @@ static int lm75_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||||||
{
|
{
|
||||||
ret = lm75_writeconf(priv, conf & ~LM75_CONF_SHUTDOWN);
|
ret = lm75_writeconf(priv, conf & ~LM75_CONF_SHUTDOWN);
|
||||||
}
|
}
|
||||||
|
lm75dbg("conf: %02x ret: %d\n", conf & ~LM75_CONF_SHUTDOWN, ret);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -406,15 +431,52 @@ static int lm75_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||||||
|
|
||||||
case SNIOC_FAHRENHEIT:
|
case SNIOC_FAHRENHEIT:
|
||||||
priv->fahrenheit = true;
|
priv->fahrenheit = true;
|
||||||
|
lm75dbg("Fahrenheit\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Report Samples in Centigrade */
|
/* Report Samples in Centigrade */
|
||||||
|
|
||||||
case SNIOC_CENTIGRADE:
|
case SNIOC_CENTIGRADE:
|
||||||
priv->fahrenheit = false;
|
priv->fahrenheit = false;
|
||||||
|
lm75dbg("Centigrade\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Read THYS temperature register. Arg: b16_t* pointer */
|
||||||
|
|
||||||
|
case SNIOC_READTHYS:
|
||||||
|
{
|
||||||
|
FAR b16_t *ptr = (FAR b16_t *)((uintptr_t)arg);
|
||||||
|
ret = lm75_readb16(priv, LM75_THYS_REG, ptr);
|
||||||
|
lm75dbg("THYS: %08x ret: %d\n", *ptr, ret);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Write THYS temperature register. Arg: b16_t value */
|
||||||
|
|
||||||
|
case SNIOC_WRITETHYS:
|
||||||
|
ret = lm75_writeb16(priv, LM75_THYS_REG, (b16_t)arg);
|
||||||
|
lm75dbg("THYS: %08x ret: %d\n", (b16_t)arg, ret);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Read TOS (Over-temp Shutdown Threshold) Register. Arg: b16_t* pointer */
|
||||||
|
|
||||||
|
case SNIOC_READTOS:
|
||||||
|
{
|
||||||
|
FAR b16_t *ptr = (FAR b16_t *)((uintptr_t)arg);
|
||||||
|
ret = lm75_readb16(priv, LM75_TOS_REG, ptr);
|
||||||
|
lm75dbg("TOS: %08x ret: %d\n", *ptr, ret);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Write TOS (Over-temp Shutdown Threshold) Register. Arg: b16_t value */
|
||||||
|
|
||||||
|
case SNIOC_WRITRETOS:
|
||||||
|
ret = lm75_writeb16(priv, LM75_TOS_REG, (b16_t)arg);
|
||||||
|
lm75dbg("TOS: %08x ret: %d\n", (b16_t)arg, ret);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
lm75dbg("Unrecognized cmd: %d\n", cmd);
|
||||||
ret = -ENOTTY;
|
ret = -ENOTTY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -454,6 +516,7 @@ int lm75_register(FAR const char *devpath, FAR struct i2c_dev_s *i2c, uint8_t ad
|
|||||||
priv = (FAR struct lm75_dev_s *)malloc(sizeof(struct lm75_dev_s));
|
priv = (FAR struct lm75_dev_s *)malloc(sizeof(struct lm75_dev_s));
|
||||||
if (!priv)
|
if (!priv)
|
||||||
{
|
{
|
||||||
|
lm75dbg("Failed to allocate instance\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -466,6 +529,7 @@ int lm75_register(FAR const char *devpath, FAR struct i2c_dev_s *i2c, uint8_t ad
|
|||||||
ret = register_driver(devpath, &lm75_fops, 0555, priv);
|
ret = register_driver(devpath, &lm75_fops, 0555, priv);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
|
lm75dbg("Failed to register driver: %d\n", ret);
|
||||||
free(priv);
|
free(priv);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -61,6 +61,10 @@
|
|||||||
#define SNIOC_POWERUP _SNIOC(0x0004) /* Arg: None */
|
#define SNIOC_POWERUP _SNIOC(0x0004) /* Arg: None */
|
||||||
#define SNIOC_FAHRENHEIT _SNIOC(0x0005) /* Arg: None */
|
#define SNIOC_FAHRENHEIT _SNIOC(0x0005) /* Arg: None */
|
||||||
#define SNIOC_CENTIGRADE _SNIOC(0x0006) /* Arg: None */
|
#define SNIOC_CENTIGRADE _SNIOC(0x0006) /* Arg: None */
|
||||||
|
#define SNIOC_READTHYS _SNIOC(0x0007) /* Arg: b16_t* pointer */
|
||||||
|
#define SNIOC_WRITETHYS _SNIOC(0x0008) /* Arg: b16_t value */
|
||||||
|
#define SNIOC_READTOS _SNIOC(0x0009) /* Arg: b16_t* pointer */
|
||||||
|
#define SNIOC_WRITRETOS _SNIOC(0x000a) /* Arg: b16_t value */
|
||||||
|
|
||||||
/* LM-75 Register Definitions ***********************************************/
|
/* LM-75 Register Definitions ***********************************************/
|
||||||
/* LM-75 Registers addresses */
|
/* LM-75 Registers addresses */
|
||||||
@ -68,7 +72,7 @@
|
|||||||
#define LM75_TEMP_REG 0x00 /* Temperature Register */
|
#define LM75_TEMP_REG 0x00 /* Temperature Register */
|
||||||
#define LM75_CONF_REG 0x01 /* Configuration Register */
|
#define LM75_CONF_REG 0x01 /* Configuration Register */
|
||||||
#define LM75_THYS_REG 0x02 /* Temperature Register */
|
#define LM75_THYS_REG 0x02 /* Temperature Register */
|
||||||
#define LM75_TOS_REG 0x03 /* Over-temp Shutdown threshold Register */
|
#define LM75_TOS_REG 0x03 /* Over-temp Shutdown Threshold Register */
|
||||||
|
|
||||||
/* Configuration Register Bit Definitions */
|
/* Configuration Register Bit Definitions */
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ int clock_gettime(clockid_t clock_id, struct timespec *tp)
|
|||||||
if (g_rtc_enabled)
|
if (g_rtc_enabled)
|
||||||
{
|
{
|
||||||
tp->tv_sec = up_rtc_gettime();
|
tp->tv_sec = up_rtc_gettime();
|
||||||
tp->tv_nsec = (up_rtc_getclock() & (RTC_CLOCKS_PER_SEC-1) ) * (1000000000/TICK_PER_SEC);
|
tp->tv_nsec = (up_rtc_getclock() & (RTC_CLOCKS_PER_SEC-1) ) * (1000000000/RTC_CLOCKS_PER_SEC);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user