From 78111c37c6174de035a546ca661f0f68bb68c4cd Mon Sep 17 00:00:00 2001 From: Till Straumann Date: Thu, 3 Nov 2005 02:52:41 +0000 Subject: 2005-11-02 straumanatslacdotstanford.edu * libchip/i2c/i2c-2b-eeprom.c, libchip/i2c/i2c-2b-eeprom.h, libchip/i2c/i2c-ds1621.c, libchip/i2c/i2c-ds1621.h: New files. * libchip/Makefile.am, libchip/preinstall.am, wrapup/Makefile.am: added a simple API/library for i2c devices and drivers for i2c 2-byte eeproms and a ds1621 temperature sensor; API is documented in libi2c.h --- c/src/libchip/Makefile.am | 9 +++ c/src/libchip/i2c/i2c-2b-eeprom.c | 132 ++++++++++++++++++++++++++++++++++++++ c/src/libchip/i2c/i2c-2b-eeprom.h | 32 +++++++++ c/src/libchip/i2c/i2c-ds1621.c | 87 +++++++++++++++++++++++++ c/src/libchip/i2c/i2c-ds1621.h | 39 +++++++++++ c/src/libchip/preinstall.am | 8 +++ 6 files changed, 307 insertions(+) create mode 100644 c/src/libchip/i2c/i2c-2b-eeprom.c create mode 100644 c/src/libchip/i2c/i2c-2b-eeprom.h create mode 100644 c/src/libchip/i2c/i2c-ds1621.c create mode 100644 c/src/libchip/i2c/i2c-ds1621.h (limited to 'c/src/libchip') diff --git a/c/src/libchip/Makefile.am b/c/src/libchip/Makefile.am index c4994535aa..90284212b8 100644 --- a/c/src/libchip/Makefile.am +++ b/c/src/libchip/Makefile.am @@ -62,6 +62,15 @@ endif EXTRA_DIST += rtc/README.ds1643 rtc/README.icm7170 rtc/README.m48t08 \ rtc/README.m48t18 rtc/STATUS +# i2c +if LIBCHIP +include_libchip_HEADERS += i2c/i2c-ds1621.h i2c/i2c-2b-eeprom.h + +noinst_LIBRARIES += libi2cio.a +libi2cio_a_CPPFLAGS = $(AM_CPPFLAGS) +libi2cio_a_SOURCES = i2c/i2c-ds1621.c i2c/i2c-2b-eeprom.c +endif + # serial if LIBCHIP include_libchip_HEADERS += serial/mc68681.h serial/ns16550.h serial/z85c30.h \ diff --git a/c/src/libchip/i2c/i2c-2b-eeprom.c b/c/src/libchip/i2c/i2c-2b-eeprom.c new file mode 100644 index 0000000000..c24463f5d5 --- /dev/null +++ b/c/src/libchip/i2c/i2c-2b-eeprom.c @@ -0,0 +1,132 @@ +/* $Id$ */ + +/* Trivial i2c driver for reading "2-byte eeproms". + * On 'open' the read-pointer is reset to 0, subsequent + * read operations slurp data from there... + */ + +/* Author: Till Straumann, 2005 */ + + +#include +#include + +#include +#include + +#define EEPROM_PG_SZ 32 +#define ALGN(x) (((unsigned32)(x) + EEPROM_PG_SZ) & ~(EEPROM_PG_SZ-1)) + +static rtems_status_code +send_file_ptr (rtems_device_minor_number minor, unsigned pos, int tout) +{ + int sc; + unsigned char bytes[2]; + + bytes[0] = (pos >> 8) & 0xff; + bytes[1] = (pos) & 0xff; + + /* poll addressing the next page; if 'tout' is <=0 we only try once + * and return the status. If 'tout' is positive, we try 'tout' times + * and return RTEMS_TIMEOUT if it didnt work + */ + while ((sc = rtems_libi2c_start_write_bytes (minor, bytes, 2)) < 0) { + if (--tout <= 0) + return tout ? -sc : RTEMS_TIMEOUT; + rtems_task_wake_after (1); + } + return RTEMS_SUCCESSFUL; +} + +static rtems_status_code +i2c_2b_eeprom_write (rtems_device_major_number major, + rtems_device_minor_number minor, void *arg) +{ + rtems_libio_rw_args_t *rwargs = arg; + unsigned off = rwargs->offset; + int cnt = rwargs->count; + char *buf = rwargs->buffer; + int sc; + unsigned end; + int l; + + if (cnt <= 0) + return RTEMS_SUCCESSFUL; + + if ((sc = send_file_ptr (minor, off, 0))) + return sc; + + do { + /* write up to next page boundary */ + end = ALGN (off); + l = end - off; + if (l > cnt) + l = cnt; + + sc = rtems_libi2c_write_bytes (minor, buf, l); + if (sc < 0) + return -sc; + + sc = rtems_libi2c_send_stop (minor); + if (sc) + return sc; + + rwargs->bytes_moved += l; + + buf += l; + cnt -= l; + off += l; + + /* poll addressing the next page */ + if ((sc = send_file_ptr (minor, off, 100))) + return sc; + + } while (cnt > 0); + + return rtems_libi2c_send_stop (minor); +} + +static rtems_status_code +i2c_2b_eeprom_read (rtems_device_major_number major, + rtems_device_minor_number minor, void *arg) +{ + int sc; + rtems_libio_rw_args_t *rwargs = arg; + + if (RTEMS_SUCCESSFUL != (sc = send_file_ptr (minor, rwargs->offset, 0))) + return -sc; + + sc = rtems_libi2c_start_read_bytes (minor, rwargs->buffer, rwargs->count); + + if (sc < 0) { + rwargs->bytes_moved = 0; + return -sc; + } + rwargs->bytes_moved = sc; + + return rtems_libi2c_send_stop (minor); +} + +static rtems_driver_address_table myops = { + read_entry: i2c_2b_eeprom_read, + write_entry: i2c_2b_eeprom_write, +}; + +static rtems_libi2c_drv_t my_drv_tbl = { + ops: &myops, + size: sizeof (my_drv_tbl), +}; + +/* provide a second table for R/O access */ +static rtems_driver_address_table my_ro_ops = { + read_entry: i2c_2b_eeprom_read, +}; + +static rtems_libi2c_drv_t my_ro_drv_tbl = { + ops: &my_ro_ops, + size: sizeof (my_ro_drv_tbl), +}; + + +rtems_libi2c_drv_t *i2c_2b_eeprom_driver_descriptor = &my_drv_tbl; +rtems_libi2c_drv_t *i2c_2b_eeprom_ro_driver_descriptor = &my_ro_drv_tbl; diff --git a/c/src/libchip/i2c/i2c-2b-eeprom.h b/c/src/libchip/i2c/i2c-2b-eeprom.h new file mode 100644 index 0000000000..e5c72554c3 --- /dev/null +++ b/c/src/libchip/i2c/i2c-2b-eeprom.h @@ -0,0 +1,32 @@ +/* $Id$ */ +#ifndef I2C_2B_EEPROM_DRIVER_H +#define I2C_2B_EEPROM_DRIVER_H + +/* Trivial i2c driver for reading and writing "2-byte eeproms". + * On 'open' the file-pointer is reset to 0, subsequent + * read/write operations slurp/write data from there... + */ + +/* Author: Till Straumann, 2005 */ + + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* pass one of these to rtems_libi2c_register_drv() */ + +/* These ops provide no write access */ +extern rtems_libi2c_drv_t *i2c_2b_eeprom_ro_driver_descriptor; + +/* Use these for writing and reading */ +extern rtems_libi2c_drv_t *i2c_2b_eeprom_driver_descriptor; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/src/libchip/i2c/i2c-ds1621.c b/c/src/libchip/i2c/i2c-ds1621.c new file mode 100644 index 0000000000..fc76e83750 --- /dev/null +++ b/c/src/libchip/i2c/i2c-ds1621.c @@ -0,0 +1,87 @@ +/* $Id$ */ + +/* Trivial i2c driver for the maxim DS1621 temperature sensor; + * just implements reading constant conversions with 8-bit + * resolution. + * Demonstrates the implementation of a i2c high-level driver. + */ + +/* Author: Till Straumann, 2005 */ +#include +#include + +#include + +#include + + +static rtems_status_code +ds1621_init (rtems_device_major_number major, rtems_device_minor_number minor, + void *arg) +{ + int sc; + char csr[2] = { DS1621_CMD_CSR_ACCESS, 0 }, cmd; + + /* First start command acquires a lock for the bus */ + + /* Initialize; switch continuous conversion on */ + sc = rtems_libi2c_start_write_bytes (minor, csr, 1); + if (sc < 0) + return -sc; + + sc = rtems_libi2c_start_read_bytes (minor, csr + 1, 1); + if (sc < 0) + return -sc; + + csr[1] &= ~DS1621_CSR_1SHOT; + + sc = rtems_libi2c_start_write_bytes (minor, csr, 2); + if (sc < 0) + return -sc; + + /* Start conversion */ + cmd = DS1621_CMD_START_CONV; + + sc = rtems_libi2c_start_write_bytes (minor, &cmd, 1); + if (sc < 0) + return -sc; + + /* sending 'stop' relinquishes the bus mutex -- don't hold it + * across system calls! + */ + return rtems_libi2c_send_stop (minor); +} + +static rtems_status_code +ds1621_read (rtems_device_major_number major, rtems_device_minor_number minor, + void *arg) +{ + int sc; + rtems_libio_rw_args_t *rwargs = arg; + char cmd = DS1621_CMD_READ_TEMP; + + sc = rtems_libi2c_start_write_bytes (minor, &cmd, 1); + if (sc < 0) + return -sc; + if (sc < 1) + return RTEMS_IO_ERROR; + sc = rtems_libi2c_start_read_bytes (minor, rwargs->buffer, 1); + if (sc < 0) { + rwargs->bytes_moved = 0; + return -sc; + } + rwargs->bytes_moved = 1; + return rtems_libi2c_send_stop (minor); +} + +static rtems_driver_address_table myops = { + initialization_entry: ds1621_init, + read_entry: ds1621_read, +}; + +static rtems_libi2c_drv_t my_drv_tbl = { + ops: &myops, + size: sizeof (my_drv_tbl), +}; + +rtems_libi2c_drv_t *i2c_ds1621_driver_descriptor = &my_drv_tbl; diff --git a/c/src/libchip/i2c/i2c-ds1621.h b/c/src/libchip/i2c/i2c-ds1621.h new file mode 100644 index 0000000000..802af03727 --- /dev/null +++ b/c/src/libchip/i2c/i2c-ds1621.h @@ -0,0 +1,39 @@ +/* $Id$ */ +#ifndef I2C_DS_1621_DRIVER_H +#define I2C_DS_1621_DRIVER_H + +/* Trivial i2c driver for the maxim DS1621 temperature sensor; + * just implements reading constant conversions with 8-bit + * resolution. + * Demonstrates the implementation of a i2c high-level driver. + */ + +/* Author: Till Straumann, 2005 */ + +#define DS1621_CMD_READ_TEMP 0xaa +#define DS1621_CMD_CSR_ACCESS 0xac +#define DS1621_CMD_START_CONV 0xee + +/* CSR bits */ +#define DS1621_CSR_DONE (1<<7) +#define DS1621_CSR_TEMP_HI (1<<6) /* T >= hi register */ +#define DS1621_CSR_TEMP_LO (1<<5) /* T <= lo register */ +#define DS1621_CSR_NVMEM_BSY (1<<4) /* non-volatile memory busy */ +#define DS1621_CSR_OUT_POL (1<<1) /* Thermostat output active polarity */ +#define DS1621_CSR_1SHOT (1<<0) /* Oneshot mode */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* for registration with libi2c */ +extern rtems_libi2c_drv_t *i2c_ds1621_driver_descriptor; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/src/libchip/preinstall.am b/c/src/libchip/preinstall.am index 3e5c1947bf..c563522367 100644 --- a/c/src/libchip/preinstall.am +++ b/c/src/libchip/preinstall.am @@ -77,6 +77,14 @@ $(PROJECT_INCLUDE)/libchip/rtc.h: rtc/rtc.h $(PROJECT_INCLUDE)/libchip/$(dirstam $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libchip/rtc.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/libchip/rtc.h +$(PROJECT_INCLUDE)/libchip/i2c-ds1621.h: i2c/i2c-ds1621.h $(PROJECT_INCLUDE)/libchip/$(dirstamp) + $(INSTALL_DATA) $< $@ +PREINSTALL_FILES += $(PROJECT_INCLUDE)/libchip/i2c-ds1621.h + +$(PROJECT_INCLUDE)/libchip/i2c-2b-eeprom.h: i2c/i2c-2b-eeprom.h $(PROJECT_INCLUDE)/libchip/$(dirstamp) + $(INSTALL_DATA) $< $@ +PREINSTALL_FILES += $(PROJECT_INCLUDE)/libchip/i2c-2b-eeprom.h + $(PROJECT_INCLUDE)/libchip/icm7170.h: rtc/icm7170.h $(PROJECT_INCLUDE)/libchip/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libchip/icm7170.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/libchip/icm7170.h -- cgit v1.2.3