From 0ce69264dbb1841b4093c04302c53ccfab02ca48 Mon Sep 17 00:00:00 2001 From: patacongo Date: Sun, 18 Sep 2011 17:52:00 +0000 Subject: 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 --- apps/system/i2c/Makefile | 2 +- apps/system/i2c/README.txt | 65 +++++++++-- apps/system/i2c/i2c_bus.c | 4 +- apps/system/i2c/i2c_common.c | 8 ++ apps/system/i2c/i2c_dev.c | 4 +- apps/system/i2c/i2c_get.c | 163 ++++++++++++++++++++-------- apps/system/i2c/i2c_main.c | 34 +++--- apps/system/i2c/i2c_set.c | 132 +++++++++++++++-------- apps/system/i2c/i2c_verf.c | 249 +++++++++++++++++++++++++++++++++++++++++++ apps/system/i2c/i2ctool.h | 21 +++- 10 files changed, 563 insertions(+), 119 deletions(-) create mode 100644 apps/system/i2c/i2c_verf.c (limited to 'apps/system/i2c') diff --git a/apps/system/i2c/Makefile b/apps/system/i2c/Makefile index 2755c9322..5ea974452 100644 --- a/apps/system/i2c/Makefile +++ b/apps/system/i2c/Makefile @@ -40,7 +40,7 @@ include $(APPDIR)/Make.defs # I2C tool 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)) diff --git a/apps/system/i2c/README.txt b/apps/system/i2c/README.txt index 0435be148..97801bcaa 100755 --- a/apps/system/i2c/README.txt +++ b/apps/system/i2c/README.txt @@ -21,6 +21,7 @@ CONTENTS - dev - get - set + - verf o I2C Build Configuration - NuttX Configuration Requirements - I2C Tool Configuration Options @@ -74,12 +75,13 @@ options. Usage: i2c [arguments] Where is one of: - Show help: ? - List buses: bus - List devices: dev [OPTIONS] - Read register: get [OPTIONS] - Show help: help - Write register: set [OPTIONS] + Show help : ? + List buses : bus + List devices : dev [OPTIONS] + Read register : get [OPTIONS] [] + Show help : help + Write register: set [OPTIONS] [] + Verify access : verf [OPTIONS] [] Where common "sticky" OPTIONS include: [-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 [-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 + [-i|j], Auto increment|don't increment regaddr on repititions. Default: NO Current: NO [-f freq] I2C frequency. Default: 100000 Current: 100000 NOTES: @@ -195,6 +198,11 @@ Common Option Summary 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. +[-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 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 before obtaining the data. + An optional 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 read will be shown as a 4-character hexadecimal number if the 16-bit data width option is selected). @@ -274,10 +289,17 @@ Write register: set [OPTIONS] range 00-ff) or a 16-bit value (in the range 0000-ffff), depending upon 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 before writing the data. + An optional 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 written will be shown as a 4-character hexadecimal number if the 16-bit data width option is selected). @@ -286,6 +308,35 @@ Write register: set [OPTIONS] All values (except the bus numbers) are hexadecimal. +Verify access : verf [OPTIONS] [] +------------------------------------------------------ + + 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 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 ======================= diff --git a/apps/system/i2c/i2c_bus.c b/apps/system/i2c/i2c_bus.c index 23bd83f58..07e6d2da3 100644 --- a/apps/system/i2c/i2c_bus.c +++ b/apps/system/i2c/i2c_bus.c @@ -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; int i; diff --git a/apps/system/i2c/i2c_common.c b/apps/system/i2c/i2c_common.c index 6d5396346..e7b27693a 100644 --- a/apps/system/i2c/i2c_common.c +++ b/apps/system/i2c/i2c_common.c @@ -118,6 +118,14 @@ int common_args(FAR struct i2ctool_s *i2ctool, FAR char **arg) i2ctool->freq = value; return ret; + case 'i': + i2ctool->autoincr = true; + return 1; + + case 'j': + i2ctool->autoincr = false; + return 1; + case 'n': i2ctool->start = false; return 1; diff --git a/apps/system/i2c/i2c_dev.c b/apps/system/i2c/i2c_dev.c index d5c65f236..f2b5a0e21 100644 --- a/apps/system/i2c/i2c_dev.c +++ b/apps/system/i2c/i2c_dev.c @@ -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; struct i2c_msg_s msg[2]; diff --git a/apps/system/i2c/i2c_get.c b/apps/system/i2c/i2c_get.c index 6c2083dd5..773f2c963 100644 --- a/apps/system/i2c/i2c_get.c +++ b/apps/system/i2c/i2c_get.c @@ -39,6 +39,8 @@ #include +#include + #include #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; - struct i2c_msg_s msg[2]; - union - { - uint16_t data16; - uint8_t data8; - } u; - + FAR char *ptr; + uint16_t result; + uint8_t regaddr; + long repititions; int nargs; + int argndx; int ret; int i; /* 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) { 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 */ @@ -110,16 +143,75 @@ int cmd_get(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv) 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_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 */ msg[0].addr = i2ctool->addr; msg[0].flags = 0; - msg[0].buffer = &i2ctool->regaddr; + msg[0].buffer = ®addr; msg[0].length = 1; 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) { ret = I2C_TRANSFER(dev, &msg[0], 1); - if (ret < 0) + if (ret== OK) { - i2ctool_printf(i2ctool, g_i2cxfrerror, argv[0], -ret); - goto errout; - } - ret = I2C_TRANSFER(dev, &msg[1], 1); - if (ret < 0) - { - i2ctool_printf(i2ctool, g_i2cxfrerror, argv[0], -ret); - goto errout; + ret = I2C_TRANSFER(dev, &msg[1], 1); } } else { ret = I2C_TRANSFER(dev, msg, 2); - if (ret < 0) - { - goto errout; - } } - 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 + /* Return the result of the read operation */ + + if (ret == OK) { - i2ctool_printf(i2ctool, "%04x\n", u.data16); + if (i2ctool->width == 8) + { + *result = (uint16_t)u.data8; + } + else + { + *result = u.data16; + } } - - (void)up_i2cuninitialize(dev); - return OK; - -errout: - i2ctool_printf(i2ctool, g_i2cxfrerror, argv[0], -ret); - (void)up_i2cuninitialize(dev); - return ERROR; + return ret; } diff --git a/apps/system/i2c/i2c_main.c b/apps/system/i2c/i2c_main.c index cb4889c54..2a0e5d626 100644 --- a/apps/system/i2c/i2c_main.c +++ b/apps/system/i2c/i2c_main.c @@ -64,8 +64,8 @@ * Private Function Prototypes ****************************************************************************/ -static int cmd_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_help(FAR struct i2ctool_s *i2ctool, int argc, char **argv); +static int i2ccmd_unrecognized(FAR struct i2ctool_s *i2ctool, int argc, char **argv); /**************************************************************************** * Private Data @@ -75,13 +75,14 @@ struct i2ctool_s g_i2ctool; static const struct cmdmap_s g_i2ccmds[] = { - { "?", cmd_help, "Show help", NULL }, - { "bus", cmd_bus, "List busses", NULL }, - { "dev", cmd_dev, "List devices", "[OPTIONS] " }, - { "get", cmd_get, "Read register", "[OPTIONS]" }, - { "help", cmd_help, "Show help", NULL }, - { "set", cmd_set, "Write register", "[OPTIONS] " }, - { NULL, NULL, NULL, NULL } + { "?", i2ccmd_help, "Show help ", NULL }, + { "bus", i2ccmd_bus, "List busses ", NULL }, + { "dev", i2ccmd_dev, "List devices ", "[OPTIONS] " }, + { "get", i2ccmd_get, "Read register ", "[OPTIONS] []" }, + { "help", i2ccmd_help, "Show help ", NULL }, + { "set", i2ccmd_set, "Write register", "[OPTIONS] []" }, + { "verf", i2ccmd_verf, "Verify access ", "[OPTIONS] [] []" }, + { 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; @@ -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. " "Default: -n Current: %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. " "Default: %d Current: %d\n", 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]); 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 */ cmd = argv[0]; - handler = cmd_unrecognized; + handler = i2ccmd_unrecognized; 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. */ - return cmd_help(i2ctool, 0, NULL); + return i2ccmd_help(i2ctool, 0, NULL); } /* Parse all of the arguments following the command name. */ diff --git a/apps/system/i2c/i2c_set.c b/apps/system/i2c/i2c_set.c index 22706ff08..66fd8c85a 100644 --- a/apps/system/i2c/i2c_set.c +++ b/apps/system/i2c/i2c_set.c @@ -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; - struct i2c_msg_s msg[2]; FAR char *ptr; - union - { - uint16_t data16; - uint8_t data8; - } u; - + uint8_t regaddr; long value; + long repititions; int nargs; int argndx; int ret; + int i; /* Parse any command line arguments */ @@ -115,7 +111,7 @@ int cmd_set(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv) 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. */ @@ -144,6 +140,23 @@ int cmd_set(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv) 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) { 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; } - /* 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_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 */ msg[0].addr = i2ctool->addr; msg[0].flags = 0; - msg[0].buffer = &i2ctool->regaddr; + msg[0].buffer = ®addr; msg[0].length = 1; msg[1].addr = i2ctool->addr; msg[1].flags = 0; if (i2ctool->width == 8) { - u.data8 = value; + u.data8 = (uint8_t)value; msg[1].buffer = &u.data8; msg[1].length = 1; } @@ -189,43 +261,15 @@ int cmd_set(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv) if (i2ctool->start) { ret = I2C_TRANSFER(dev, &msg[0], 1); - if (ret < 0) + if (ret == OK) { - i2ctool_printf(i2ctool, g_i2cxfrerror, argv[0], -ret); - goto errout; - } - ret = I2C_TRANSFER(dev, &msg[1], 1); - if (ret < 0) - { - i2ctool_printf(i2ctool, g_i2cxfrerror, argv[0], -ret); - goto errout; + ret = I2C_TRANSFER(dev, &msg[1], 1); } } else { ret = I2C_TRANSFER(dev, msg, 2); - if (ret < 0) - { - goto errout; - } - } - - 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", 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; + return ret; } diff --git a/apps/system/i2c/i2c_verf.c b/apps/system/i2c/i2c_verf.c new file mode 100644 index 000000000..0fa34b96e --- /dev/null +++ b/apps/system/i2c/i2c_verf.c @@ -0,0 +1,249 @@ +/**************************************************************************** + * apps/system/i2c/i2c_verf.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include + +#include + +#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; +} diff --git a/apps/system/i2c/i2ctool.h b/apps/system/i2c/i2ctool.h index 56802ffb2..9726f0083 100644 --- a/apps/system/i2c/i2ctool.h +++ b/apps/system/i2c/i2ctool.h @@ -49,6 +49,8 @@ #include #include +#include + /**************************************************************************** * Definitions ****************************************************************************/ @@ -139,7 +141,8 @@ struct i2ctool_s uint8_t bus; /* [-b bus] is the I2C bus number */ uint8_t regaddr; /* [-r regaddr] is the I2C device register address */ 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 */ /* Output streams */ @@ -184,10 +187,18 @@ void i2ctool_flush(FAR struct i2ctool_s *i2ctool); /* Command handlers */ -int cmd_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 cmd_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_bus(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv); +int i2ccmd_dev(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv); +int i2ccmd_get(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 */ -- cgit v1.2.3