Add I2C trace capability; Fix another STM32 I2C/FSMC bug; add verify command to the I2C tool

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3961 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2011-09-18 17:52:00 +00:00
parent 699178b9bc
commit 9233cd668e
11 changed files with 569 additions and 120 deletions

View File

@ -106,3 +106,8 @@
show or set the time (only if CONFIG_RTC is set). show or set the time (only if CONFIG_RTC is set).
6.10 2011-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr> 6.10 2011-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
* apps/system/i2c: Add repitition and address auto-incrementing so that
and command can be executed numerous times. Add a new verify command
that will write to a register, read from register, and verify that
returned value.

View File

@ -40,7 +40,7 @@ include $(APPDIR)/Make.defs
# I2C tool # I2C tool
ASRCS = ASRCS =
CSRCS = i2c_bus.c i2c_common.c i2c_dev.c i2c_get.c i2c_main.c i2c_set.c CSRCS = i2c_bus.c i2c_common.c i2c_dev.c i2c_get.c i2c_main.c i2c_set.c i2c_verf.c
AOBJS = $(ASRCS:.S=$(OBJEXT)) AOBJS = $(ASRCS:.S=$(OBJEXT))

View File

@ -21,6 +21,7 @@ CONTENTS
- dev - dev
- get - get
- set - set
- verf
o I2C Build Configuration o I2C Build Configuration
- NuttX Configuration Requirements - NuttX Configuration Requirements
- I2C Tool Configuration Options - I2C Tool Configuration Options
@ -74,12 +75,13 @@ options.
Usage: i2c <cmd> [arguments] Usage: i2c <cmd> [arguments]
Where <cmd> is one of: Where <cmd> is one of:
Show help: ? Show help : ?
List buses: bus List buses : bus
List devices: dev [OPTIONS] <first> <last> List devices : dev [OPTIONS] <first> <last>
Read register: get [OPTIONS] Read register : get [OPTIONS] [<repititions>]
Show help: help Show help : help
Write register: set [OPTIONS] <value> Write register: set [OPTIONS] <value> [<repititions>]
Verify access : verf [OPTIONS] <value> [<repititions>]
Where common "sticky" OPTIONS include: Where common "sticky" OPTIONS include:
[-a addr] is the I2C device address (hex). Default: 03 Current: 03 [-a addr] is the I2C device address (hex). Default: 03 Current: 03
@ -87,6 +89,7 @@ options.
[-r regaddr] is the I2C device register address (hex). Default: 00 Current: 00 [-r regaddr] is the I2C device register address (hex). Default: 00 Current: 00
[-w width] is the data width (8 or 16 decimal). Default: 8 Current: 8 [-w width] is the data width (8 or 16 decimal). Default: 8 Current: 8
[-s|n], send/don't send start between command and data. Default: -n Current: -n [-s|n], send/don't send start between command and data. Default: -n Current: -n
[-i|j], Auto increment|don't increment regaddr on repititions. Default: NO Current: NO
[-f freq] I2C frequency. Default: 100000 Current: 100000 [-f freq] I2C frequency. Default: 100000 Current: 100000
NOTES: NOTES:
@ -195,6 +198,11 @@ Common Option Summary
This determines whether or not there should be a new I2C START between This determines whether or not there should be a new I2C START between
sending of the register address and sending/receiving of the register data. sending of the register address and sending/receiving of the register data.
[-i|j], Auto increment|don't increment regaddr on repititions. Default: NO Current: NO
On commands that take a optional number of repetitions, the option can be
used to temporarily increment the regaddr value by one on each repitition.
[-f freq] I2C frequency. Default: 400000 Current: 400000 [-f freq] I2C frequency. Default: 400000 Current: 400000
The [-f freq] sets the frequency of the I2C device. The [-f freq] sets the frequency of the I2C device.
@ -257,6 +265,13 @@ Read register: get [OPTIONS]
data value from the device. Optionally, it may re-start the transfer data value from the device. Optionally, it may re-start the transfer
before obtaining the data. before obtaining the data.
An optional <repititions> argument can be supplied to repeat the
read operation an arbitrary number of times (up to 2 billion). If
auto-increment is select (-i), then the register address will be
temporarily incremented on each repitions. The increment is temporary
in the since that it will not alter the "sticky" value of the
register address.
On success, the output will look like the following (the data value On success, the output will look like the following (the data value
read will be shown as a 4-character hexadecimal number if the 16-bit read will be shown as a 4-character hexadecimal number if the 16-bit
data width option is selected). data width option is selected).
@ -274,10 +289,17 @@ Write register: set [OPTIONS] <value>
range 00-ff) or a 16-bit value (in the range 0000-ffff), depending upon range 00-ff) or a 16-bit value (in the range 0000-ffff), depending upon
the selected data width. the selected data width.
This command with write the 8-bit address value then write the 8- or 16-bit This command will write the 8-bit address value then write the 8- or 16-bit
data value to the device. Optionally, it may re-start the transfer data value to the device. Optionally, it may re-start the transfer
before writing the data. before writing the data.
An optional <repititions> argument can be supplied to repeat the
write operation an arbitrary number of times (up to 2 billion). If
auto-increment is select (-i), then the register address will be
temporarily incremented on each repitions. The increment is temporary
in the since that it will not alter the "sticky" value of the
register address.
On success, the output will look like the following (the data value On success, the output will look like the following (the data value
written will be shown as a 4-character hexadecimal number if the 16-bit written will be shown as a 4-character hexadecimal number if the 16-bit
data width option is selected). data width option is selected).
@ -286,6 +308,35 @@ Write register: set [OPTIONS] <value>
All values (except the bus numbers) are hexadecimal. All values (except the bus numbers) are hexadecimal.
Verify access : verf [OPTIONS] <value> [<repititions>]
------------------------------------------------------
This command combines writing and reading from an I2C device register.
It will write a value to an will write a value to an I2C register using
the selected I2C parameters in the common options just as described for
tie 'set' command. Then this command will read the value back just
as described with the 'get' command. Finally, this command will compare
the value read and against the value written and emit an error message
if they do not match.
If no value is provided, then this command will use the register address
itself as the data, providing for a address-in-address test.
An optional <repititions> argument can be supplied to repeat the
verify operation an arbitrary number of times (up to 2 billion). If
auto-increment is select (-i), then the register address will be
temporarily incremented on each repitions. The increment is temporary
in the since that it will not alter the "sticky" value of the
register address.
On success, the output will look like the following (the data value
written will be shown as a 4-character hexadecimal number if the 16-bit
data width option is selected).
VERIFY Bus: 1 Addr: 49 Subaddr: 04 Wrote: 96 Read: 92 FAILURE
All values (except the bus numbers) are hexadecimal.
I2C BUILD CONFIGURATION I2C BUILD CONFIGURATION
======================= =======================

View File

@ -72,10 +72,10 @@
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Name: cmd_bus * Name: i2ccmd_bus
****************************************************************************/ ****************************************************************************/
int cmd_bus(FAR struct i2ctool_s *i2ctool, int argc, char **argv) int i2ccmd_bus(FAR struct i2ctool_s *i2ctool, int argc, char **argv)
{ {
FAR struct i2c_dev_s *dev; FAR struct i2c_dev_s *dev;
int i; int i;

View File

@ -118,6 +118,14 @@ int common_args(FAR struct i2ctool_s *i2ctool, FAR char **arg)
i2ctool->freq = value; i2ctool->freq = value;
return ret; return ret;
case 'i':
i2ctool->autoincr = true;
return 1;
case 'j':
i2ctool->autoincr = false;
return 1;
case 'n': case 'n':
i2ctool->start = false; i2ctool->start = false;
return 1; return 1;

View File

@ -74,10 +74,10 @@
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Name: cmd_dev * Name: i2ccmd_dev
****************************************************************************/ ****************************************************************************/
int cmd_dev(FAR struct i2ctool_s *i2ctool, int argc, char **argv) int i2ccmd_dev(FAR struct i2ctool_s *i2ctool, int argc, char **argv)
{ {
FAR struct i2c_dev_s *dev; FAR struct i2c_dev_s *dev;
struct i2c_msg_s msg[2]; struct i2c_msg_s msg[2];

View File

@ -39,6 +39,8 @@
#include <nuttx/config.h> #include <nuttx/config.h>
#include <stdlib.h>
#include <nuttx/i2c.h> #include <nuttx/i2c.h>
#include "i2ctool.h" #include "i2ctool.h"
@ -72,33 +74,64 @@
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Name: cmd_get * Name: i2ccmd_get
****************************************************************************/ ****************************************************************************/
int cmd_get(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv) int i2ccmd_get(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv)
{ {
FAR struct i2c_dev_s *dev; FAR struct i2c_dev_s *dev;
struct i2c_msg_s msg[2]; FAR char *ptr;
union uint16_t result;
{ uint8_t regaddr;
uint16_t data16; long repititions;
uint8_t data8;
} u;
int nargs; int nargs;
int argndx;
int ret; int ret;
int i; int i;
/* Parse any command line arguments */ /* Parse any command line arguments */
for (i = 1; i < argc; ) for (argndx = 1; argndx < argc; )
{ {
nargs = common_args(i2ctool, &argv[i]); /* Break out of the look when the last option has been parsed */
ptr = argv[argndx];
if (*ptr != '-')
{
break;
}
/* Otherwise, check for common options */
nargs = common_args(i2ctool, &argv[argndx]);
if (nargs < 0) if (nargs < 0)
{ {
return ERROR; return ERROR;
} }
i += nargs; argndx += nargs;
}
/* There may be one more thing on the command line: The repitition
* count.
*/
repititions = 1;
if (argndx < argc)
{
repititions = strtol(argv[argndx], NULL, 16);
if (repititions < 1)
{
i2ctool_printf(i2ctool, g_i2cargrange, argv[0]);
return ERROR;
}
argndx++;
}
if (argndx != argc)
{
i2ctool_printf(i2ctool, g_i2ctoomanyargs, argv[0]);
return ERROR;
} }
/* Get a handle to the I2C bus */ /* Get a handle to the I2C bus */
@ -110,16 +143,75 @@ int cmd_get(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv)
return ERROR; return ERROR;
} }
/* Set the frequency and address (NOTE: Only 7-bit address supported now) */ /* Set the frequency and the address (NOTE: Only 7-bit address supported now) */
I2C_SETFREQUENCY(dev, i2ctool->freq); I2C_SETFREQUENCY(dev, i2ctool->freq);
I2C_SETADDRESS(dev, i2ctool->addr, 7); I2C_SETADDRESS(dev, i2ctool->addr, 7);
/* Loop for the requested number of repititions */
regaddr = i2ctool->regaddr;
ret = OK;
for (i = 0; i < repititions; i++)
{
/* Read from the I2C bus */
ret = i2ctool_get(i2ctool, dev, regaddr, &result);
/* Display the result */
if (ret == OK)
{
i2ctool_printf(i2ctool, "READ Bus: %d Addr: %02x Subaddr: %02x Value: ",
i2ctool->bus, i2ctool->addr, i2ctool->regaddr);
if (i2ctool->width == 8)
{
i2ctool_printf(i2ctool, "%02x\n", result);
}
else
{
i2ctool_printf(i2ctool, "%04x\n", result);
}
}
else
{
i2ctool_printf(i2ctool, g_i2cxfrerror, argv[0], -ret);
break;
}
/* Auto-increment the address if so configured */
if (i2ctool->autoincr)
{
regaddr++;
}
}
(void)up_i2cuninitialize(dev);
return ret;
}
/****************************************************************************
* Name: i2ctool_get
****************************************************************************/
int i2ctool_get(FAR struct i2ctool_s *i2ctool, FAR struct i2c_dev_s *dev,
uint8_t regaddr, uint16_t *result)
{
struct i2c_msg_s msg[2];
union
{
uint16_t data16;
uint8_t data8;
} u;
int ret;
/* Set up data structures */ /* Set up data structures */
msg[0].addr = i2ctool->addr; msg[0].addr = i2ctool->addr;
msg[0].flags = 0; msg[0].flags = 0;
msg[0].buffer = &i2ctool->regaddr; msg[0].buffer = &regaddr;
msg[0].length = 1; msg[0].length = 1;
msg[1].addr = i2ctool->addr; msg[1].addr = i2ctool->addr;
@ -138,43 +230,28 @@ int cmd_get(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv)
if (i2ctool->start) if (i2ctool->start)
{ {
ret = I2C_TRANSFER(dev, &msg[0], 1); ret = I2C_TRANSFER(dev, &msg[0], 1);
if (ret < 0) if (ret== OK)
{ {
i2ctool_printf(i2ctool, g_i2cxfrerror, argv[0], -ret); ret = I2C_TRANSFER(dev, &msg[1], 1);
goto errout;
}
ret = I2C_TRANSFER(dev, &msg[1], 1);
if (ret < 0)
{
i2ctool_printf(i2ctool, g_i2cxfrerror, argv[0], -ret);
goto errout;
} }
} }
else else
{ {
ret = I2C_TRANSFER(dev, msg, 2); ret = I2C_TRANSFER(dev, msg, 2);
if (ret < 0) }
/* Return the result of the read operation */
if (ret == OK)
{
if (i2ctool->width == 8)
{ {
goto errout; *result = (uint16_t)u.data8;
}
else
{
*result = u.data16;
} }
} }
return ret;
i2ctool_printf(i2ctool, "READ Bus: %d Addr: %02x Subaddr: %02x Value: ",
i2ctool->bus, i2ctool->addr, i2ctool->regaddr);
if (i2ctool->width == 8)
{
i2ctool_printf(i2ctool, "%02x\n", u.data8);
}
else
{
i2ctool_printf(i2ctool, "%04x\n", u.data16);
}
(void)up_i2cuninitialize(dev);
return OK;
errout:
i2ctool_printf(i2ctool, g_i2cxfrerror, argv[0], -ret);
(void)up_i2cuninitialize(dev);
return ERROR;
} }

View File

@ -64,8 +64,8 @@
* Private Function Prototypes * Private Function Prototypes
****************************************************************************/ ****************************************************************************/
static int cmd_help(FAR struct i2ctool_s *i2ctool, int argc, char **argv); static int i2ccmd_help(FAR struct i2ctool_s *i2ctool, int argc, char **argv);
static int cmd_unrecognized(FAR struct i2ctool_s *i2ctool, int argc, char **argv); static int i2ccmd_unrecognized(FAR struct i2ctool_s *i2ctool, int argc, char **argv);
/**************************************************************************** /****************************************************************************
* Private Data * Private Data
@ -75,13 +75,14 @@ struct i2ctool_s g_i2ctool;
static const struct cmdmap_s g_i2ccmds[] = static const struct cmdmap_s g_i2ccmds[] =
{ {
{ "?", cmd_help, "Show help", NULL }, { "?", i2ccmd_help, "Show help ", NULL },
{ "bus", cmd_bus, "List busses", NULL }, { "bus", i2ccmd_bus, "List busses ", NULL },
{ "dev", cmd_dev, "List devices", "[OPTIONS] <first> <last>" }, { "dev", i2ccmd_dev, "List devices ", "[OPTIONS] <first> <last>" },
{ "get", cmd_get, "Read register", "[OPTIONS]" }, { "get", i2ccmd_get, "Read register ", "[OPTIONS] [<repititions>]" },
{ "help", cmd_help, "Show help", NULL }, { "help", i2ccmd_help, "Show help ", NULL },
{ "set", cmd_set, "Write register", "[OPTIONS] <value>" }, { "set", i2ccmd_set, "Write register", "[OPTIONS] <value> [<repititions>]" },
{ NULL, NULL, NULL, NULL } { "verf", i2ccmd_verf, "Verify access ", "[OPTIONS] [<value>] [<repititions>]" },
{ NULL, NULL, NULL, NULL }
}; };
/**************************************************************************** /****************************************************************************
@ -103,10 +104,10 @@ const char g_i2cxfrerror[] = "i2ctool: %s: Transfer failed: %d\n";
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Name: cmd_help * Name: i2ccmd_help
****************************************************************************/ ****************************************************************************/
static int cmd_help(FAR struct i2ctool_s *i2ctool, int argc, char **argv) static int i2ccmd_help(FAR struct i2ctool_s *i2ctool, int argc, char **argv)
{ {
const struct cmdmap_s *ptr; const struct cmdmap_s *ptr;
@ -140,6 +141,9 @@ static int cmd_help(FAR struct i2ctool_s *i2ctool, int argc, char **argv)
i2ctool_printf(i2ctool, " [-s|n], send/don't send start between command and data. " i2ctool_printf(i2ctool, " [-s|n], send/don't send start between command and data. "
"Default: -n Current: %s\n", "Default: -n Current: %s\n",
i2ctool->start ? "-s" : "-n"); i2ctool->start ? "-s" : "-n");
i2ctool_printf(i2ctool, " [-i|j], Auto increment|don't increment regaddr on repititions. "
"Default: NO Current: %s\n",
i2ctool->autoincr ? "YES" : "NO");
i2ctool_printf(i2ctool, " [-f freq] I2C frequency. " i2ctool_printf(i2ctool, " [-f freq] I2C frequency. "
"Default: %d Current: %d\n", "Default: %d Current: %d\n",
CONFIG_I2CTOOL_DEFFREQ, i2ctool->freq); CONFIG_I2CTOOL_DEFFREQ, i2ctool->freq);
@ -156,10 +160,10 @@ static int cmd_help(FAR struct i2ctool_s *i2ctool, int argc, char **argv)
} }
/**************************************************************************** /****************************************************************************
* Name: cmd_unrecognized * Name: i2ccmd_unrecognized
****************************************************************************/ ****************************************************************************/
static int cmd_unrecognized(FAR struct i2ctool_s *i2ctool, int argc, char **argv) static int i2ccmd_unrecognized(FAR struct i2ctool_s *i2ctool, int argc, char **argv)
{ {
i2ctool_printf(i2ctool, g_i2ccmdnotfound, argv[0]); i2ctool_printf(i2ctool, g_i2ccmdnotfound, argv[0]);
return ERROR; return ERROR;
@ -187,7 +191,7 @@ static int i2c_execute(FAR struct i2ctool_s *i2ctool, int argc, char *argv[])
/* See if the command is one that we understand */ /* See if the command is one that we understand */
cmd = argv[0]; cmd = argv[0];
handler = cmd_unrecognized; handler = i2ccmd_unrecognized;
for (cmdmap = g_i2ccmds; cmdmap->cmd; cmdmap++) for (cmdmap = g_i2ccmds; cmdmap->cmd; cmdmap++)
{ {
@ -272,7 +276,7 @@ int i2c_parse(FAR struct i2ctool_s *i2ctool, int argc, char *argv[])
* command status. * command status.
*/ */
return cmd_help(i2ctool, 0, NULL); return i2ccmd_help(i2ctool, 0, NULL);
} }
/* Parse all of the arguments following the command name. */ /* Parse all of the arguments following the command name. */

View File

@ -74,24 +74,20 @@
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Name: cmd_set * Name: i2ccmd_set
****************************************************************************/ ****************************************************************************/
int cmd_set(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv) int i2ccmd_set(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv)
{ {
FAR struct i2c_dev_s *dev; FAR struct i2c_dev_s *dev;
struct i2c_msg_s msg[2];
FAR char *ptr; FAR char *ptr;
union uint8_t regaddr;
{
uint16_t data16;
uint8_t data8;
} u;
long value; long value;
long repititions;
int nargs; int nargs;
int argndx; int argndx;
int ret; int ret;
int i;
/* Parse any command line arguments */ /* Parse any command line arguments */
@ -115,7 +111,7 @@ int cmd_set(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv)
argndx += nargs; argndx += nargs;
} }
/* There should be exactly one more thing on the command line: The value /* There must be at least one more thing on the command line: The value
* to be written. * to be written.
*/ */
@ -144,6 +140,23 @@ int cmd_set(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv)
return ERROR; return ERROR;
} }
/* There may be one more thing on the command line: The repitition
* count.
*/
repititions = 1;
if (argndx < argc)
{
repititions = strtol(argv[argndx], NULL, 16);
if (repititions < 1)
{
i2ctool_printf(i2ctool, g_i2cargrange, argv[0]);
return ERROR;
}
argndx++;
}
if (argndx != argc) if (argndx != argc)
{ {
i2ctool_printf(i2ctool, g_i2ctoomanyargs, argv[0]); i2ctool_printf(i2ctool, g_i2ctoomanyargs, argv[0]);
@ -159,23 +172,82 @@ int cmd_set(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv)
return ERROR; return ERROR;
} }
/* Set the frequency and address (NOTE: Only 7-bit address supported now) */ /* Set the frequency and the address (NOTE: Only 7-bit address supported now) */
I2C_SETFREQUENCY(dev, i2ctool->freq); I2C_SETFREQUENCY(dev, i2ctool->freq);
I2C_SETADDRESS(dev, i2ctool->addr, 7); I2C_SETADDRESS(dev, i2ctool->addr, 7);
/* Loop for the requested number of repititions */
regaddr = i2ctool->regaddr;
ret = OK;
for (i = 0; i < repititions; i++)
{
/* Write to the I2C bus */
ret = i2ctool_set(i2ctool, dev, regaddr, (uint16_t)value);
/* Display the result */
if (ret == OK)
{
i2ctool_printf(i2ctool, "WROTE Bus: %d Addr: %02x Subaddr: %02x Value: ",
i2ctool->bus, i2ctool->addr, i2ctool->regaddr);
if (i2ctool->width == 8)
{
i2ctool_printf(i2ctool, "%02x\n", (int)value);
}
else
{
i2ctool_printf(i2ctool, "%04x\n", (int)value);
}
}
else
{
i2ctool_printf(i2ctool, g_i2cxfrerror, argv[0], -ret);
break;
}
/* Auto-increment the address if so configured */
if (i2ctool->autoincr)
{
regaddr++;
}
}
(void)up_i2cuninitialize(dev);
return ret;
}
/****************************************************************************
* Name: i2ctool_set
****************************************************************************/
int i2ctool_set(FAR struct i2ctool_s *i2ctool, FAR struct i2c_dev_s *dev,
uint8_t regaddr, uint16_t value)
{
struct i2c_msg_s msg[2];
union
{
uint16_t data16;
uint8_t data8;
} u;
int ret;
/* Set up data structures */ /* Set up data structures */
msg[0].addr = i2ctool->addr; msg[0].addr = i2ctool->addr;
msg[0].flags = 0; msg[0].flags = 0;
msg[0].buffer = &i2ctool->regaddr; msg[0].buffer = &regaddr;
msg[0].length = 1; msg[0].length = 1;
msg[1].addr = i2ctool->addr; msg[1].addr = i2ctool->addr;
msg[1].flags = 0; msg[1].flags = 0;
if (i2ctool->width == 8) if (i2ctool->width == 8)
{ {
u.data8 = value; u.data8 = (uint8_t)value;
msg[1].buffer = &u.data8; msg[1].buffer = &u.data8;
msg[1].length = 1; msg[1].length = 1;
} }
@ -189,43 +261,15 @@ int cmd_set(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv)
if (i2ctool->start) if (i2ctool->start)
{ {
ret = I2C_TRANSFER(dev, &msg[0], 1); ret = I2C_TRANSFER(dev, &msg[0], 1);
if (ret < 0) if (ret == OK)
{ {
i2ctool_printf(i2ctool, g_i2cxfrerror, argv[0], -ret); ret = I2C_TRANSFER(dev, &msg[1], 1);
goto errout;
}
ret = I2C_TRANSFER(dev, &msg[1], 1);
if (ret < 0)
{
i2ctool_printf(i2ctool, g_i2cxfrerror, argv[0], -ret);
goto errout;
} }
} }
else else
{ {
ret = I2C_TRANSFER(dev, msg, 2); ret = I2C_TRANSFER(dev, msg, 2);
if (ret < 0)
{
goto errout;
}
} }
i2ctool_printf(i2ctool, "WROTE Bus: %d Addr: %02x Subaddr: %02x Value: ", return ret;
i2ctool->bus, i2ctool->addr, i2ctool->regaddr);
if (i2ctool->width == 8)
{
i2ctool_printf(i2ctool, "%02x\n", u.data8);
}
else
{
i2ctool_printf(i2ctool, "%04x\n", u.data16);
}
(void)up_i2cuninitialize(dev);
return OK;
errout:
i2ctool_printf(i2ctool, g_i2cxfrerror, argv[0], -ret);
(void)up_i2cuninitialize(dev);
return ERROR;
} }

249
system/i2c/i2c_verf.c Normal file
View File

@ -0,0 +1,249 @@
/****************************************************************************
* apps/system/i2c/i2c_verf.c
*
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* 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 <stdlib.h>
#include <nuttx/i2c.h>
#include "i2ctool.h"
/****************************************************************************
* Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: i2ccmd_verf
****************************************************************************/
int i2ccmd_verf(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv)
{
FAR struct i2c_dev_s *dev;
FAR char *ptr;
uint16_t rdvalue;
uint8_t regaddr;
bool addrinaddr;
long wrvalue;
long repititions;
int nargs;
int argndx;
int ret;
int i;
/* Parse any command line arguments */
for (argndx = 1; argndx < argc; )
{
/* Break out of the look when the last option has been parsed */
ptr = argv[argndx];
if (*ptr != '-')
{
break;
}
/* Otherwise, check for common options */
nargs = common_args(i2ctool, &argv[argndx]);
if (nargs < 0)
{
return ERROR;
}
argndx += nargs;
}
/* The options may be followed by the optional wrvalue to be written. If omitted, then
* the register address will be used as the wrvalue, providing an address-in-address
* test.
*/
addrinaddr = true;
wrvalue = 0;
if (argndx < argc)
{
wrvalue = strtol(argv[argndx], NULL, 16);
if (i2ctool->width == 8)
{
if (wrvalue < 0 || wrvalue > 255)
{
i2ctool_printf(i2ctool, g_i2cargrange, argv[0]);
return ERROR;
}
}
else if (wrvalue < 0 || wrvalue > 65535)
{
i2ctool_printf(i2ctool, g_i2cargrange, argv[0]);
return ERROR;
}
addrinaddr = false;
argndx++;
}
/* There may be one more thing on the command line: The repitition
* count.
*/
repititions = 1;
if (argndx < argc)
{
repititions = strtol(argv[argndx], NULL, 16);
if (repititions < 1)
{
i2ctool_printf(i2ctool, g_i2cargrange, argv[0]);
return ERROR;
}
argndx++;
}
if (argndx != argc)
{
i2ctool_printf(i2ctool, g_i2ctoomanyargs, argv[0]);
return ERROR;
}
/* Get a handle to the I2C bus */
dev = up_i2cinitialize(i2ctool->bus);
if (!dev)
{
i2ctool_printf(i2ctool, "Failed to get bus %d\n", i2ctool->bus);
return ERROR;
}
/* Set the frequency and the address (NOTE: Only 7-bit address supported now) */
I2C_SETFREQUENCY(dev, i2ctool->freq);
I2C_SETADDRESS(dev, i2ctool->addr, 7);
/* Loop for the requested number of repititions */
regaddr = i2ctool->regaddr;
ret = OK;
for (i = 0; i < repititions; i++)
{
/* If we are performing an address-in-address test, then use the register
* address as the value to write.
*/
if (addrinaddr)
{
wrvalue = regaddr;
}
/* Write to the I2C bus */
ret = i2ctool_set(i2ctool, dev, regaddr, (uint16_t)wrvalue);
if (ret == OK)
{
/* Read the value back from the I2C bus */
ret = i2ctool_get(i2ctool, dev, regaddr, &rdvalue);
}
/* Display the result */
if (ret == OK)
{
i2ctool_printf(i2ctool, "VERIFY Bus: %d Addr: %02x Subaddr: %02x Wrote: ",
i2ctool->bus, i2ctool->addr, i2ctool->regaddr);
if (i2ctool->width == 8)
{
i2ctool_printf(i2ctool, "%02x Read: %02x", (int)wrvalue, (int)rdvalue);
}
else
{
i2ctool_printf(i2ctool, "%04x Read: %04x", (int)wrvalue, (int)rdvalue);
}
if (wrvalue != rdvalue)
{
i2ctool_printf(i2ctool, " <<< FAILURE\n");
}
else
{
i2ctool_printf(i2ctool, "\n");
}
}
else
{
i2ctool_printf(i2ctool, g_i2cxfrerror, argv[0], -ret);
break;
}
/* Auto-increment the address if so configured */
if (i2ctool->autoincr)
{
regaddr++;
}
}
(void)up_i2cuninitialize(dev);
return ret;
}

View File

@ -49,6 +49,8 @@
#include <stdbool.h> #include <stdbool.h>
#include <errno.h> #include <errno.h>
#include <nuttx/i2c.h>
/**************************************************************************** /****************************************************************************
* Definitions * Definitions
****************************************************************************/ ****************************************************************************/
@ -139,7 +141,8 @@ struct i2ctool_s
uint8_t bus; /* [-b bus] is the I2C bus number */ uint8_t bus; /* [-b bus] is the I2C bus number */
uint8_t regaddr; /* [-r regaddr] is the I2C device register address */ uint8_t regaddr; /* [-r regaddr] is the I2C device register address */
uint8_t width; /* [-w width] is the data width (8 or 16) */ uint8_t width; /* [-w width] is the data width (8 or 16) */
bool start; /* [-s|n], send/don't send start between command and data */ bool start; /* [-s|n], send|don't send start between command and data */
bool autoincr; /* [-i|j], Auto increment|don't increment regaddr on repititions */
uint32_t freq; /* [-f freq] I2C frequency */ uint32_t freq; /* [-f freq] I2C frequency */
/* Output streams */ /* Output streams */
@ -184,10 +187,18 @@ void i2ctool_flush(FAR struct i2ctool_s *i2ctool);
/* Command handlers */ /* Command handlers */
int cmd_bus(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv); int i2ccmd_bus(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv);
int cmd_dev(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv); int i2ccmd_dev(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv);
int cmd_get(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv); int i2ccmd_get(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv);
int cmd_set(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv); int i2ccmd_set(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv);
int i2ccmd_verf(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv);
/* I2C access functions */
int i2ctool_get(FAR struct i2ctool_s *i2ctool, FAR struct i2c_dev_s *dev,
uint8_t addr, uint16_t *result);
int i2ctool_set(FAR struct i2ctool_s *i2ctool, FAR struct i2c_dev_s *dev,
uint8_t regaddr, uint16_t value);
/* Common logic */ /* Common logic */