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:
patacongo 2011-09-11 14:55:31 +00:00
parent bdf8ede547
commit 455b9336fb
6 changed files with 201 additions and 60 deletions

View File

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

View File

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

View File

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

View File

@ -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, &regaddr, 1); ret = I2C_WRITE(priv->i2c, &regaddr, 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;

View File

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

View File

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