diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2014-11-07 13:47:39 +0100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2014-11-20 10:30:06 +0100 |
commit | 41c5f1b7795d95179d1b501fc93b27abd6c19d27 (patch) | |
tree | 688c479d01b3ae9f5c6de24bc2ebcbee2068afc8 /testsuites/libtests | |
parent | Add RTEMS port of Linux I2C user-space API (diff) | |
download | rtems-41c5f1b7795d95179d1b501fc93b27abd6c19d27.tar.bz2 |
Add I2C driver framework
This I2C driver framework has some major differences compared to libi2c.
* It is compatible to the Linux I2C user-space API.
* It uses generic IMFS nodes and thus reduces the levels of indirection.
* The drivers don't have to mess around with minor numbers to get their
state information.
* No arbitrary bus controller model is assumed. The main task of an I2C
bus controller driver is to process I2C messages. How this is done is
private to the driver.
* Scatter/gather operations are supported (I2C_M_NOSTART).
Diffstat (limited to 'testsuites/libtests')
-rw-r--r-- | testsuites/libtests/Makefile.am | 1 | ||||
-rw-r--r-- | testsuites/libtests/configure.ac | 1 | ||||
-rw-r--r-- | testsuites/libtests/i2c01/Makefile.am | 19 | ||||
-rw-r--r-- | testsuites/libtests/i2c01/i2c01.doc | 11 | ||||
-rw-r--r-- | testsuites/libtests/i2c01/i2c01.scn | 2 | ||||
-rw-r--r-- | testsuites/libtests/i2c01/init.c | 286 |
6 files changed, 320 insertions, 0 deletions
diff --git a/testsuites/libtests/Makefile.am b/testsuites/libtests/Makefile.am index 26e11c69f6..bee6e75a25 100644 --- a/testsuites/libtests/Makefile.am +++ b/testsuites/libtests/Makefile.am @@ -1,6 +1,7 @@ ACLOCAL_AMFLAGS = -I ../aclocal _SUBDIRS = POSIX +_SUBDIRS += i2c01 _SUBDIRS += newlib01 _SUBDIRS += block17 _SUBDIRS += exit02 diff --git a/testsuites/libtests/configure.ac b/testsuites/libtests/configure.ac index 7d4871d447..fccdc1d12c 100644 --- a/testsuites/libtests/configure.ac +++ b/testsuites/libtests/configure.ac @@ -66,6 +66,7 @@ AS_IF([test x"$HAVE_LIBDL" = x"yes"],[ # Explicitly list all Makefiles here AC_CONFIG_FILES([Makefile +i2c01/Makefile newlib01/Makefile block17/Makefile exit02/Makefile diff --git a/testsuites/libtests/i2c01/Makefile.am b/testsuites/libtests/i2c01/Makefile.am new file mode 100644 index 0000000000..f329337057 --- /dev/null +++ b/testsuites/libtests/i2c01/Makefile.am @@ -0,0 +1,19 @@ +rtems_tests_PROGRAMS = i2c01 +i2c01_SOURCES = init.c + +dist_rtems_tests_DATA = i2c01.scn i2c01.doc + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../automake/compile.am +include $(top_srcdir)/../automake/leaf.am + +AM_CPPFLAGS += -I$(top_srcdir)/../support/include + +LINK_OBJS = $(i2c01_OBJECTS) +LINK_LIBS = $(i2c01_LDLIBS) + +i2c01$(EXEEXT): $(i2c01_OBJECTS) $(i2c01_DEPENDENCIES) + @rm -f i2c01$(EXEEXT) + $(make-exe) + +include $(top_srcdir)/../automake/local.am diff --git a/testsuites/libtests/i2c01/i2c01.doc b/testsuites/libtests/i2c01/i2c01.doc new file mode 100644 index 0000000000..79185eea36 --- /dev/null +++ b/testsuites/libtests/i2c01/i2c01.doc @@ -0,0 +1,11 @@ +This file describes the directives and concepts tested by this test set. + +test set name: i2c01 + +directives: + + TBD + +concepts: + + - Ensure that the I2C driver framework works. diff --git a/testsuites/libtests/i2c01/i2c01.scn b/testsuites/libtests/i2c01/i2c01.scn new file mode 100644 index 0000000000..1b54497eb4 --- /dev/null +++ b/testsuites/libtests/i2c01/i2c01.scn @@ -0,0 +1,2 @@ +*** BEGIN OF TEST I2C 1 *** +*** END OF TEST I2C 1 *** diff --git a/testsuites/libtests/i2c01/init.c b/testsuites/libtests/i2c01/init.c new file mode 100644 index 0000000000..7f38d34fc7 --- /dev/null +++ b/testsuites/libtests/i2c01/init.c @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifdef HAVE_CONFIG_H + #include "config.h" +#endif + +#include <dev/i2c/i2c.h> + +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <errno.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <rtems/libcsupport.h> + +#include "tmacros.h" + +const char rtems_test_name[] = "I2C 1"; + +#define SPARE_ADDRESS_BITS 3 + +#define DEVICE_SIMPLE_READ_WRITE (0UL << SPARE_ADDRESS_BITS) + +typedef struct test_device test_device; + +struct test_device { + int (*transfer)( + i2c_bus *bus, + i2c_msg *msgs, + uint32_t msg_count, + test_device *dev + ); +}; + +typedef struct { + test_device base; + char buf[3]; +} test_device_simple_read_write; + +typedef struct { + i2c_bus base; + unsigned long clock; + test_device *devices[1]; + test_device_simple_read_write simple_read_write; +} test_bus; + +static const char bus_path[] = "/dev/i2c-0"; + +static int test_simple_read_write_transfer( + i2c_bus *bus, + i2c_msg *msgs, + uint32_t msg_count, + test_device *base +) +{ + test_device_simple_read_write *dev = (test_device_simple_read_write *) base; + + if (msg_count == 1 && msgs[0].len == sizeof(dev->buf)) { + if ((msgs[0].flags & I2C_M_RD) != 0) { + memcpy(msgs[0].buf, &dev->buf[0], sizeof(dev->buf)); + } else { + memcpy(&dev->buf[0], msgs[0].buf, sizeof(dev->buf)); + } + + return 0; + } else { + return -EIO; + } +} + +static int test_transfer(i2c_bus *base, i2c_msg *msgs, uint32_t msg_count) +{ + test_bus *bus = (test_bus *) base; + uint16_t addr; + test_device *dev; + + addr = msgs[0].addr >> SPARE_ADDRESS_BITS; + if (addr >= RTEMS_ARRAY_SIZE(bus->devices)) { + return -EIO; + } + + dev = bus->devices[addr]; + + return (*dev->transfer)(&bus->base, msgs, msg_count, dev); +} + +static int test_set_clock(i2c_bus *base, unsigned long clock) +{ + test_bus *bus = (test_bus *) base; + + bus->clock = clock; + + return 0; +} + +static void test_destroy(i2c_bus *base) +{ + i2c_bus_destroy_and_free(base); +} + +static void test_simple_read_write(test_bus *bus, int fd) +{ + static const char zero[] = { 0, 0, 0 }; + static const char abc[] = { 'a', 'b', 'c' }; + + int rv; + char buf[3]; + ssize_t n; + + rv = ioctl(fd, I2C_SLAVE, DEVICE_SIMPLE_READ_WRITE); + rtems_test_assert(rv == 0); + + errno = 0; + rv = ioctl(fd, 0xb00b); + rtems_test_assert(rv == -1); + rtems_test_assert(errno == ENOTTY); + + errno = 0; + n = write(fd, &buf[0], 1000); + rtems_test_assert(n == -1); + rtems_test_assert(errno == EIO); + + errno = 0; + n = read(fd, &buf[0], 1000); + rtems_test_assert(n == -1); + rtems_test_assert(errno == EIO); + + rtems_test_assert( + memcmp(&bus->simple_read_write.buf[0], &zero[0], sizeof(buf)) == 0 + ); + + n = write(fd, &abc[0], sizeof(buf)); + rtems_test_assert(n == (ssize_t) sizeof(buf)); + + rtems_test_assert( + memcmp(&bus->simple_read_write.buf[0], &abc[0], sizeof(buf)) == 0 + ); + + n = read(fd, &buf[0], sizeof(buf)); + rtems_test_assert(n == (ssize_t) sizeof(buf)); + + rtems_test_assert(memcmp(&buf[0], &abc[0], sizeof(buf)) == 0); +} + +static void test(void) +{ + rtems_resource_snapshot snapshot; + test_bus *bus; + int rv; + int fd; + + rtems_resource_snapshot_take(&snapshot); + + bus = (test_bus *) i2c_bus_alloc_and_init(sizeof(*bus)); + rtems_test_assert(bus != NULL); + + bus->base.transfer = test_transfer; + bus->base.set_clock = test_set_clock; + bus->base.destroy = test_destroy; + bus->base.functionality = I2C_FUNC_I2C | I2C_FUNC_PROTOCOL_MANGLING + | I2C_FUNC_NOSTART; + + bus->simple_read_write.base.transfer = test_simple_read_write_transfer; + bus->devices[0] = &bus->simple_read_write.base; + + rv = i2c_bus_register(&bus->base, &bus_path[0]); + rtems_test_assert(rv == 0); + + fd = open(&bus_path[0], O_RDWR); + rtems_test_assert(fd >= 0); + + rtems_test_assert(bus->clock == 0); + rv = ioctl(fd, I2C_BUS_SET_CLOCK, 0xdeadbeefUL); + rtems_test_assert(rv == 0); + rtems_test_assert(bus->clock == 0xdeadbeef); + + rv = ioctl(fd, I2C_BUS_OBTAIN); + rtems_test_assert(rv == 0); + + rv = ioctl(fd, I2C_BUS_RELEASE); + rtems_test_assert(rv == 0); + + rtems_test_assert(!bus->base.ten_bit_address); + + rv = ioctl(fd, I2C_TENBIT, 1UL); + rtems_test_assert(rv == 0); + rtems_test_assert(bus->base.ten_bit_address); + + rv = ioctl(fd, I2C_TENBIT, 0UL); + rtems_test_assert(rv == 0); + rtems_test_assert(!bus->base.ten_bit_address); + + rtems_test_assert(!bus->base.use_pec); + + rv = ioctl(fd, I2C_PEC, 1UL); + rtems_test_assert(rv == 0); + rtems_test_assert(bus->base.use_pec); + + rv = ioctl(fd, I2C_PEC, 0UL); + rtems_test_assert(rv == 0); + rtems_test_assert(!bus->base.use_pec); + + rv = ioctl(fd, I2C_SLAVE, 123UL); + rtems_test_assert(rv == 0); + rtems_test_assert(bus->base.default_address == 123); + + rv = ioctl(fd, I2C_SLAVE_FORCE, 456UL); + rtems_test_assert(rv == 0); + rtems_test_assert(bus->base.default_address == 456); + + rtems_test_assert(bus->base.retries == 0); + + rv = ioctl(fd, I2C_RETRIES, 1UL); + rtems_test_assert(rv == 0); + rtems_test_assert(bus->base.retries == 1); + + rv = ioctl(fd, I2C_RETRIES, 0UL); + rtems_test_assert(rv == 0); + rtems_test_assert(bus->base.retries == 0); + + rtems_test_assert(bus->base.timeout == 0); + + rv = ioctl(fd, I2C_TIMEOUT, 1UL); + rtems_test_assert(rv == 0); + rtems_test_assert(bus->base.timeout == 5); + + rv = ioctl(fd, I2C_TIMEOUT, 0UL); + rtems_test_assert(rv == 0); + rtems_test_assert(bus->base.timeout == 0); + + test_simple_read_write(bus, fd); + + rv = close(fd); + rtems_test_assert(rv == 0); + + rv = unlink(&bus_path[0]); + rtems_test_assert(rv == 0); + + rtems_test_assert(rtems_resource_snapshot_check(&snapshot)); +} + +static void Init(rtems_task_argument arg) +{ + TEST_BEGIN(); + + test(); + + TEST_END(); + rtems_test_exit(0); +} + +#define CONFIGURE_MICROSECONDS_PER_TICK 2000 + +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER + +#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM + +#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 7 + +#define CONFIGURE_MAXIMUM_TASKS 1 + +#define CONFIGURE_MAXIMUM_SEMAPHORES 1 + +#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION + +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE + +#define CONFIGURE_INIT + +#include <rtems/confdefs.h> |