Shadow-Mode: The output- and configuration registers of the IO-Expander
are held in the microcontrollers memory and only written to the IO-Expander. This reduces bus traffic and is more error-proof than the normal read- modify-write operation. Retry Mode: If enabled and an error occurs while writing to the IO-Expander the current transmission is automatically repeated once.
This commit is contained in:
parent
43d7301255
commit
3d5e690977
@ -52,6 +52,26 @@ config IOEXPANDER_MULTIPIN
|
||||
This settings enable the definition of routines for
|
||||
optimized simultaneous access to multiple pins.
|
||||
|
||||
config IOEXPANDER_SHADOW_MODE
|
||||
bool "Use Shadow Mode instead of Read-Modify-Write Operations"
|
||||
default n
|
||||
---help---
|
||||
This setting enables a mode where the output and pin
|
||||
configuration registers are held in RAM.
|
||||
With this for example we do not need to read back the
|
||||
output-register every time we want to change one pin.
|
||||
We do instead change the bit in the internal register
|
||||
and then just write this register to the IO-Expander.
|
||||
This reduces bus traffic and eliminates the problem of
|
||||
EMC-caused toggling of output pins.
|
||||
|
||||
config IOEXPANDER_RETRY
|
||||
bool "Retry to send commands and data at I2C communication errors"
|
||||
default n
|
||||
---help---
|
||||
Retry to send commands and data if a I2C-communication
|
||||
error occurs (eg. caused by EMC).
|
||||
|
||||
endif # IOEXPANDER
|
||||
|
||||
config DEV_GPIO
|
||||
|
@ -223,11 +223,20 @@ static int pca9555_setbit(FAR struct pca9555_dev_s *pca, uint8_t addr,
|
||||
|
||||
buf[0] = addr;
|
||||
|
||||
#ifdef CONFIG_IOEXPANDER_SHADOW_MODE
|
||||
/* Get the shadowed register value */
|
||||
|
||||
buf[1] = pca->sreg[addr];
|
||||
|
||||
#else
|
||||
/* Get the register value from the IO-Expander */
|
||||
|
||||
ret = pca9555_writeread(pca, &buf[0], 1, &buf[1], 1);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (bitval)
|
||||
{
|
||||
@ -238,7 +247,23 @@ static int pca9555_setbit(FAR struct pca9555_dev_s *pca, uint8_t addr,
|
||||
buf[1] &= ~(1 << pin);
|
||||
}
|
||||
|
||||
return pca9555_write(pca, buf, 2);
|
||||
#ifdef CONFIG_IOEXPANDER_SHADOW_MODE
|
||||
/* Save the new register value in the shadow register */
|
||||
|
||||
pca->sreg[addr] = buf[1];
|
||||
#endif
|
||||
|
||||
ret = pca9555_write(pca, buf, 2);
|
||||
#ifdef CONFIG_IOEXPANDER_RETRY
|
||||
if (ret != OK)
|
||||
{
|
||||
/* Try again (only once) */
|
||||
|
||||
ret = pca9555_write(pca, buf, 2);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -271,6 +296,12 @@ static int pca9555_getbit(FAR struct pca9555_dev_s *pca, uint8_t addr,
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IOEXPANDER_SHADOW_MODE
|
||||
/* Save the new register value in the shadow register */
|
||||
|
||||
pca->sreg[addr] = buf;
|
||||
#endif
|
||||
|
||||
*val = (buf >> pin) & 1;
|
||||
return OK;
|
||||
}
|
||||
@ -417,6 +448,13 @@ static int pca9555_getmultibits(FAR struct pca9555_dev_s *pca, uint8_t addr,
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IOEXPANDER_SHADOW_MODE
|
||||
/* Save the new register value in the shadow register */
|
||||
|
||||
pca->sreg[addr] = buf[0];
|
||||
pca->sreg[addr+1] = buf[1];
|
||||
#endif
|
||||
|
||||
/* Read the requested bits */
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
@ -465,15 +503,22 @@ static int pca9555_multiwritepin(FAR struct ioexpander_dev_s *dev,
|
||||
|
||||
/* Start by reading both registers, whatever the pins to change. We could
|
||||
* attempt to read one port only if all pins were on the same port, but
|
||||
* this would not save much. */
|
||||
* this would not save much.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_IOEXPANDER_SHADOW_MODE
|
||||
ret = pca9555_writeread(pca, &addr, 1, &buf[1], 2);
|
||||
if (ret < 0)
|
||||
{
|
||||
|
||||
pca9555_unlock(pca);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
/* In Shadow-Mode we "read" the pin status from the shadow registers */
|
||||
|
||||
buf[1] = pca->sreg[addr];
|
||||
buf[2] = pca->sreg[addr+1];
|
||||
#endif
|
||||
|
||||
/* Apply the user defined changes */
|
||||
|
||||
@ -505,6 +550,11 @@ static int pca9555_multiwritepin(FAR struct ioexpander_dev_s *dev,
|
||||
/* Now write back the new pins states */
|
||||
|
||||
buf[0] = addr;
|
||||
#ifdef CONFIG_IOEXPANDER_SHADOW_MODE
|
||||
/* Save the new register values in the shadow register */
|
||||
pca->sreg[addr] = buf[1];
|
||||
pca->sreg[addr+1] = buf[2];
|
||||
#endif
|
||||
ret = pca9555_write(pca, buf, 3);
|
||||
|
||||
pca9555_unlock(pca);
|
||||
@ -585,6 +635,11 @@ static void pca9555_irqworker(void *arg)
|
||||
ret = pca9555_writeread(pca, &addr, 1, buf, 2);
|
||||
if (ret == OK)
|
||||
{
|
||||
#ifdef CONFIG_IOEXPANDER_SHADOW_MODE
|
||||
/* Don't forget to update the shadow registers at this point */
|
||||
|
||||
pca->sreg[addr] = buf;
|
||||
#endif
|
||||
bits = ((unsigned int)buf[0] << 8) | buf[1];
|
||||
|
||||
/* If signal PID is registered, enqueue signal. */
|
||||
|
@ -61,6 +61,7 @@
|
||||
/********************************************************************************************
|
||||
* Pre-processor Definitions
|
||||
********************************************************************************************/
|
||||
|
||||
/* Configuration ****************************************************************************/
|
||||
/* Prerequisites:
|
||||
* CONFIG_I2C
|
||||
@ -118,11 +119,12 @@ struct pca9555_dev_s
|
||||
{
|
||||
struct ioexpander_dev_s dev; /* Nested structure to allow casting as public gpio
|
||||
* expander. */
|
||||
|
||||
#ifdef CONFIG_IOEXPANDER_SHADOW_MODE
|
||||
uint8_t sreg[8]; /* Shadowed registers of the PCA9555 */
|
||||
#endif
|
||||
#ifdef CONFIG_PCA9555_MULTIPLE
|
||||
FAR struct pca9555_dev_s *flink; /* Supports a singly linked list of drivers */
|
||||
#endif
|
||||
|
||||
FAR struct pca9555_config_s *config; /* Board configuration data */
|
||||
FAR struct i2c_master_s *i2c; /* Saved I2C driver instance */
|
||||
sem_t exclsem; /* Mutual exclusion */
|
||||
|
Loading…
Reference in New Issue
Block a user