From 85169d7fe8850c2a299c135c0417b567ebdf03c6 Mon Sep 17 00:00:00 2001 From: "luohui2320@gmail.com" Date: Wed, 13 Jun 2012 16:55:46 +0000 Subject: [PATCH] update I2C driver, which now just use small memory git-svn-id: https://rt-thread.googlecode.com/svn/trunk@2159 bbd45198-f89e-11dd-88c7-29a3b14d5316 --- components/drivers/i2c/i2c-bit-ops.c | 33 +- components/drivers/i2c/i2c.h | 117 ------- components/drivers/i2c/i2c_core.c | 324 +++--------------- components/drivers/i2c/i2c_dev.c | 84 ++--- .../{i2c => include/drivers}/i2c-bit-ops.h | 2 +- components/drivers/include/drivers/i2c.h | 79 +++++ .../{i2c => include/drivers}/i2c_dev.h | 3 +- components/drivers/include/rtdevice.h | 9 + 8 files changed, 172 insertions(+), 479 deletions(-) delete mode 100644 components/drivers/i2c/i2c.h rename components/drivers/{i2c => include/drivers}/i2c-bit-ops.h (90%) create mode 100644 components/drivers/include/drivers/i2c.h rename components/drivers/{i2c => include/drivers}/i2c_dev.h (73%) diff --git a/components/drivers/i2c/i2c-bit-ops.c b/components/drivers/i2c/i2c-bit-ops.c index 6d87df46e..9fcbc9e9b 100644 --- a/components/drivers/i2c/i2c-bit-ops.c +++ b/components/drivers/i2c/i2c-bit-ops.c @@ -12,8 +12,7 @@ * 2012-04-25 weety first version */ -#include -#include +#include #ifdef RT_I2C_BIT_DEBUG #define bit_dbg(fmt, ...) rt_kprintf(fmt, ##__VA_ARGS__) @@ -126,7 +125,7 @@ rt_inline rt_bool_t i2c_waitack(struct rt_i2c_bit_ops *ops) return -RT_ETIMEOUT; } - ack = !GET_SDA(ops); /* ack : sda pin is pulled low */ + ack = !GET_SDA(ops); /* ACK : SDA pin is pulled low */ bit_dbg("%s\n", ack ? "ACK" : "NACK"); SCL_L(ops); @@ -135,7 +134,7 @@ rt_inline rt_bool_t i2c_waitack(struct rt_i2c_bit_ops *ops) } -static rt_int32_t i2c_writeb(struct rt_i2c_bus *bus, rt_uint8_t data) +static rt_int32_t i2c_writeb(struct rt_i2c_bus_device *bus, rt_uint8_t data) { rt_int32_t i; rt_uint8_t bit; @@ -151,7 +150,7 @@ static rt_int32_t i2c_writeb(struct rt_i2c_bus *bus, rt_uint8_t data) if (SCL_H(ops) < 0) { bit_dbg("i2c_writeb: 0x%02x, " - "wait scl pin high timeout at bit #%d\n", + "wait scl pin high timeout at bit %d\n", data, i); return -RT_ETIMEOUT; } @@ -164,7 +163,7 @@ static rt_int32_t i2c_writeb(struct rt_i2c_bus *bus, rt_uint8_t data) } -static rt_int32_t i2c_readb(struct rt_i2c_bus *bus) +static rt_int32_t i2c_readb(struct rt_i2c_bus_device *bus) { rt_uint8_t i; rt_uint8_t data = 0; @@ -179,7 +178,7 @@ static rt_int32_t i2c_readb(struct rt_i2c_bus *bus) if (SCL_H(ops) < 0) { bit_dbg("i2c_readb: wait scl pin high " - "timeout at bit #%d\n", 7 - i); + "timeout at bit %d\n", 7 - i); return -RT_ETIMEOUT; } @@ -193,7 +192,7 @@ static rt_int32_t i2c_readb(struct rt_i2c_bus *bus) } -static rt_size_t i2c_send_bytes(struct rt_i2c_bus *bus, struct rt_i2c_msg *msg) +static rt_size_t i2c_send_bytes(struct rt_i2c_bus_device *bus, struct rt_i2c_msg *msg) { rt_int32_t ret; rt_size_t bytes = 0; @@ -225,7 +224,7 @@ static rt_size_t i2c_send_bytes(struct rt_i2c_bus *bus, struct rt_i2c_msg *msg) return bytes; } -static rt_err_t i2c_send_ack_or_nack(struct rt_i2c_bus *bus, int ack) +static rt_err_t i2c_send_ack_or_nack(struct rt_i2c_bus_device *bus, int ack) { struct rt_i2c_bit_ops *ops = bus->priv; @@ -241,7 +240,7 @@ static rt_err_t i2c_send_ack_or_nack(struct rt_i2c_bus *bus, int ack) return RT_EOK; } -static rt_size_t i2c_recv_bytes(struct rt_i2c_bus *bus, struct rt_i2c_msg *msg) +static rt_size_t i2c_recv_bytes(struct rt_i2c_bus_device *bus, struct rt_i2c_msg *msg) { rt_int32_t val; rt_int32_t bytes = 0; /* actual bytes */ @@ -279,7 +278,7 @@ static rt_size_t i2c_recv_bytes(struct rt_i2c_bus *bus, struct rt_i2c_msg *msg) return bytes; } -static rt_int32_t i2c_send_address(struct rt_i2c_bus *bus, +static rt_int32_t i2c_send_address(struct rt_i2c_bus_device *bus, rt_uint8_t addr, rt_int32_t retries) { struct rt_i2c_bit_ops *ops = bus->priv; @@ -301,7 +300,7 @@ static rt_int32_t i2c_send_address(struct rt_i2c_bus *bus, return ret; } -static rt_err_t i2c_bit_send_address(struct rt_i2c_bus *bus, struct rt_i2c_msg *msg) +static rt_err_t i2c_bit_send_address(struct rt_i2c_bus_device *bus, struct rt_i2c_msg *msg) { rt_uint16_t flags = msg->flags; rt_uint16_t ignore_nack = msg->flags & RT_I2C_IGNORE_NACK; @@ -360,7 +359,7 @@ static rt_err_t i2c_bit_send_address(struct rt_i2c_bus *bus, struct rt_i2c_msg * } -static rt_size_t i2c_bit_xfer(struct rt_i2c_bus *bus, +static rt_size_t i2c_bit_xfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num) { struct rt_i2c_msg *msg; @@ -383,7 +382,7 @@ static rt_size_t i2c_bit_xfer(struct rt_i2c_bus *bus, ret = i2c_bit_send_address(bus, msg); if ((ret != RT_EOK) && !ignore_nack) { - bit_dbg("receive NACK from device addr 0x%02x msg #%d\n", + bit_dbg("receive NACK from device addr 0x%02x msg %d\n", msgs[i].addr, i); goto out; } @@ -425,14 +424,14 @@ out: } -static const struct rt_i2c_bus_ops i2c_bit_bus_ops = { +static const struct rt_i2c_bus_device_ops i2c_bit_bus_ops = { i2c_bit_xfer, RT_NULL, RT_NULL }; -rt_err_t rt_i2c_bit_add_bus(struct rt_i2c_bus *bus) +rt_err_t rt_i2c_bit_add_bus(struct rt_i2c_bus_device *bus, const char *bus_name) { rt_err_t err; @@ -441,5 +440,5 @@ rt_err_t rt_i2c_bit_add_bus(struct rt_i2c_bus *bus) bus->ops = &i2c_bit_bus_ops; - return rt_i2c_bus_register(bus); + return rt_i2c_bus_device_register(bus, bus_name); } diff --git a/components/drivers/i2c/i2c.h b/components/drivers/i2c/i2c.h deleted file mode 100644 index 987e720b2..000000000 --- a/components/drivers/i2c/i2c.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * File : i2c.h - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2006, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2012-04-25 weety first version - */ - -#ifndef __I2C_H__ -#define __I2C_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef RT_I2C_NAME_SIZE -#define RT_I2C_NAME_SIZE 32 -#endif - -#define RT_I2C_WR 0x0000 -#define RT_I2C_RD (1u << 0) -#define RT_I2C_ADDR_10BIT (1u << 2) /* this is a ten bit chip address */ -#define RT_I2C_NO_START (1u << 4) -#define RT_I2C_IGNORE_NACK (1u << 5) -#define RT_I2C_NO_READ_ACK (1u << 6) /* when I2C reading, we do not ACK */ - -struct rt_i2c_msg { - rt_uint16_t addr; - rt_uint16_t flags; - rt_uint16_t len; - rt_uint8_t *buf; -}; - -struct rt_i2c_hardware_info { - char name[RT_I2C_NAME_SIZE]; - rt_uint16_t flags; - rt_uint16_t addr; - rt_uint32_t bus_id; - rt_list_t list; -}; - -#define RT_I2C_HARDWARE_INFO(name, flags, addr, bus_id) \ - name,flags,addr,bus_id,{RT_NULL,RT_NULL} - -struct rt_i2c_bus; - -struct rt_i2c_bus_ops { - rt_size_t (*master_xfer) (struct rt_i2c_bus *bus, struct rt_i2c_msg *msgs, rt_uint32_t num); - rt_size_t (*slave_xfer) (struct rt_i2c_bus *bus, struct rt_i2c_msg *msgs, rt_uint32_t num); - rt_err_t (*i2c_bus_control) (struct rt_i2c_bus *bus, rt_uint32_t, rt_uint32_t); -}; - -/*for i2c bus driver*/ -struct rt_i2c_bus { - struct rt_device *parent; - char name[RT_I2C_NAME_SIZE]; - rt_uint32_t id; - const struct rt_i2c_bus_ops *ops; - struct rt_mutex lock; - rt_list_t devices; - rt_list_t list; - rt_uint32_t timeout; - rt_uint32_t retries; - void *priv; -}; - -struct rt_i2c_device; -struct rt_i2c_driver { - char name[RT_I2C_NAME_SIZE]; - rt_err_t (*probe)(struct rt_i2c_device *device); - rt_err_t (*remove)(struct rt_i2c_device *device); - rt_list_t devices; -}; - -/*for i2c device driver*/ -struct rt_i2c_device { - rt_uint32_t flags; - rt_uint16_t addr; - struct rt_i2c_bus *bus; - struct rt_i2c_driver *driver; - struct rt_device dev; - rt_list_t drv_list; - rt_list_t bus_list; -}; - -#ifdef RT_I2C_DEBUG -#define i2c_dbg(fmt, ...) rt_kprintf(fmt, ##__VA_ARGS__) -#else -#define i2c_dbg(fmt, ...) -#endif - -rt_err_t rt_i2c_bus_register(struct rt_i2c_bus *bus); -rt_err_t rt_i2c_bus_unregister(struct rt_i2c_bus *bus); -void rt_i2c_hw_info_register(struct rt_i2c_hardware_info *info, rt_uint32_t size); -rt_err_t rt_i2c_bus_attach_driver(struct rt_i2c_driver *driver); -rt_err_t rt_i2c_bus_detach_driver(struct rt_i2c_driver *driver); -rt_size_t rt_i2c_transfer(struct rt_i2c_bus *bus, - struct rt_i2c_msg *msgs, rt_uint32_t size); -rt_size_t rt_i2c_master_send(struct rt_i2c_device *device, - const rt_uint8_t *buf, rt_uint32_t size); -rt_size_t rt_i2c_master_recv(struct rt_i2c_device *device, - rt_uint8_t *buf ,rt_uint32_t size); -rt_err_t rt_i2c_core_init(); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/components/drivers/i2c/i2c_core.c b/components/drivers/i2c/i2c_core.c index e48b2e494..2bd4f4615 100644 --- a/components/drivers/i2c/i2c_core.c +++ b/components/drivers/i2c/i2c_core.c @@ -12,362 +12,118 @@ * 2012-04-25 weety first version */ -#include -#include +#include static struct rt_mutex i2c_core_lock; -static struct rt_mutex i2c_hardware_lock; -static rt_list_t i2c_hw_info_list = RT_LIST_OBJECT_INIT(i2c_hw_info_list); -static rt_list_t i2c_bus_list = RT_LIST_OBJECT_INIT(i2c_bus_list); -static struct rt_i2c_bus *find_i2c_bus(rt_uint32_t id) +rt_err_t rt_i2c_bus_device_register(struct rt_i2c_bus_device *bus, const char *bus_name) { - rt_list_t *list; - struct rt_i2c_bus *bus = RT_NULL; + rt_err_t res = RT_EOK; - for (list = (&i2c_bus_list)->next; list != &i2c_bus_list; list = list->next) - { - bus = (struct rt_i2c_bus *)rt_list_entry(list, struct rt_i2c_bus, list); - if (bus->id == id) - { - return bus; - } - } - - return RT_NULL; -} - - -rt_err_t rt_i2c_bus_register(struct rt_i2c_bus *bus) -{ - rt_err_t ret = RT_EOK; - struct rt_i2c_bus *tbus; - - rt_mutex_init (&bus->lock, "i2c_bus_lock", RT_IPC_FLAG_FIFO); + rt_mutex_init(&bus->lock, "i2c_bus_lock", RT_IPC_FLAG_FIFO); rt_mutex_take(&i2c_core_lock, RT_WAITING_FOREVER); - tbus = find_i2c_bus(bus->id); - if (tbus != RT_NULL) - { - rt_kprintf("I2C bus ID [%d] already registered\n", bus->id); - ret = -RT_ERROR; - goto out; - } - if (bus->timeout == 0) bus->timeout = RT_TICK_PER_SECOND; - - rt_list_init(&bus->devices); - - ret = rt_i2c_bus_device_init(bus, bus->name); - if (ret != RT_EOK) - { - rt_mutex_release(&i2c_core_lock); - rt_kprintf("I2C bus [%s] register failed\n", bus->name); - goto out; - } + + res = rt_i2c_bus_device_device_init(bus, bus_name); - rt_list_insert_after(&i2c_bus_list, &bus->list); + i2c_dbg("I2C bus [%s] registered\n", bus_name); rt_mutex_release(&i2c_core_lock); - - rt_kprintf("I2C bus [%s] registered\n", bus->name); -out: - return ret; + return res; } -rt_err_t rt_i2c_bus_unregister(struct rt_i2c_bus *bus) +struct rt_i2c_bus_device* rt_i2c_bus_device_find(const char *bus_name) { - rt_err_t ret = RT_EOK; - struct rt_i2c_bus *bus_l; - rt_list_t *list; - struct rt_i2c_device *device; - - rt_mutex_take(&i2c_core_lock, RT_WAITING_FOREVER); - - rt_i2c_bus_device_exit(bus); - - for (list = (&bus->devices)->next; list != &bus->devices; list = list->next) + struct rt_i2c_bus_device *bus; + rt_device_t dev = rt_device_find(bus_name); + if (dev == RT_NULL || dev->type != RT_Device_Class_I2CBUS) { - device = (struct rt_i2c_device *)rt_list_entry(list, struct rt_i2c_device, bus_list); - if (device) - { - ret = device->driver->remove(device); - if (ret != RT_EOK) - { - i2c_dbg("I2C driver [%s] unregister failed\n", device->driver->name); - goto out; - } - rt_list_remove(&device->drv_list); - rt_list_remove(&device->bus_list); - } + i2c_dbg("I2C bus %s not exist\n", bus_name); + return RT_NULL; } - rt_list_init(&bus->devices); - rt_list_remove(&bus->list); - - rt_mutex_detach (&bus->lock); - - rt_kprintf("I2C bus [%s] unregister\n", bus->name); -out: - rt_mutex_release(&i2c_core_lock); - return ret; + bus = (struct rt_i2c_bus_device *)dev->user_data; + + return bus; } -rt_inline struct rt_i2c_hardware_info * -i2c_check_hw_info(struct rt_i2c_hardware_info *hwinfo) -{ - rt_list_t *list; - struct rt_i2c_hardware_info *info; - - for (list = (&i2c_hw_info_list)->next; list != &i2c_hw_info_list; list = list->next) - { - info = (struct rt_i2c_hardware_info *)rt_list_entry(list, - struct rt_i2c_hardware_info, list); - if ((info->bus_id == hwinfo->bus_id) && (info->addr == hwinfo->addr)) - { - return info; - } - } - - return RT_NULL; -} - -void rt_i2c_hw_info_register(struct rt_i2c_hardware_info *info, rt_uint32_t size) -{ - rt_mutex_take(&i2c_hardware_lock, RT_WAITING_FOREVER); - for( ; size > 0; size--, info++) - { - if (i2c_check_hw_info(info) == RT_NULL) - { - rt_list_insert_after(&i2c_hw_info_list, &info->list); - } - else - { - rt_kprintf("I2C hw info [%s:%d:%d] already registered\n", - info->name, info->bus_id, info->addr); - } - } - rt_mutex_release(&i2c_hardware_lock); -} - -rt_err_t rt_i2c_check_addr(struct rt_i2c_bus *bus, rt_uint16_t addr) -{ - rt_list_t *list; - struct rt_i2c_device *device; - - for (list = (&bus->devices)->next; list != &bus->devices; list = list->next) - { - device = (struct rt_i2c_device *)rt_list_entry(list, struct rt_i2c_device, bus_list); - if (device->addr == addr) - { - rt_kprintf("ERR: device at addr[0x%02x] " - "already registered\n", addr); - return -RT_ERROR; - } - } - - return RT_EOK; -} - -static rt_err_t i2c_driver_probe(struct rt_i2c_bus *bus, - struct rt_i2c_driver *driver, struct rt_i2c_hardware_info *info) -{ - rt_err_t ret = RT_EOK; - struct rt_i2c_device *device; - - device = rt_malloc(sizeof(struct rt_i2c_device)); - if (device == RT_NULL) - { - i2c_dbg("I2C malloc memory failed\n"); - return -RT_ENOMEM; - } - rt_memset(device, 0, sizeof(struct rt_i2c_device)); - - device->flags = info->flags; - device->addr = info->addr; - device->bus = bus; - device->driver = driver; - - rt_list_insert_after(&bus->devices, &device->bus_list); - rt_list_insert_after(&driver->devices, &device->drv_list); - ret = driver->probe(device); - - return ret; -} - -static rt_err_t i2c_bus_match_hw(struct rt_i2c_driver *driver) -{ - rt_err_t ret = RT_EOK; - rt_list_t *list; - struct rt_i2c_hardware_info *info; - struct rt_i2c_bus *bus = RT_NULL; - - for (list = (&i2c_hw_info_list)->next; list != &i2c_hw_info_list; list = list->next) - { - info = (struct rt_i2c_hardware_info *)rt_list_entry(list, - struct rt_i2c_hardware_info, list); - if (rt_strncmp(info->name, driver->name, RT_I2C_NAME_SIZE) == 0) - { - bus = find_i2c_bus(info->bus_id); - if (bus) - { - if (rt_i2c_check_addr(bus, info->addr) != RT_EOK) - { - continue; - } - if (i2c_driver_probe(bus, driver, info) != RT_EOK) - { - ret = -RT_ERROR; - } - } - } - } - - return ret; -} - -rt_err_t rt_i2c_bus_attach_driver(struct rt_i2c_driver *driver) -{ - rt_err_t ret = RT_EOK; - - rt_mutex_take(&i2c_core_lock, RT_WAITING_FOREVER); - ret = i2c_bus_match_hw(driver); - rt_mutex_release(&i2c_core_lock); - - if (ret != RT_EOK) - { - goto out; - } - - rt_kprintf("I2C driver [%s] registered\n", driver->name); - - return RT_EOK; - -out: - rt_kprintf("I2C driver [%s] register failed\n", driver->name); - return ret; -} - - -rt_err_t rt_i2c_bus_detach_driver(struct rt_i2c_driver *driver) -{ - rt_err_t ret = RT_EOK; - rt_list_t *list; - struct rt_i2c_device *device; - - rt_mutex_take(&i2c_core_lock, RT_WAITING_FOREVER); - for (list = (&driver->devices)->next; list != &driver->devices; list = list->next) - { - device = (struct rt_i2c_device *)rt_list_entry(list, struct rt_i2c_device, drv_list); - if (device) - { - ret = driver->remove(device); - if (ret != RT_EOK) - { - rt_mutex_release(&i2c_core_lock); - goto out; - } - rt_list_remove(&device->drv_list); - rt_list_remove(&device->bus_list); - } - } - - rt_mutex_release(&i2c_core_lock); - - rt_kprintf("I2C driver [%s] unregister\n", driver->name); - -out: - return ret; -} - - -rt_size_t rt_i2c_transfer(struct rt_i2c_bus *bus, - struct rt_i2c_msg *msgs, rt_uint32_t size) +rt_size_t rt_i2c_transfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num) { rt_size_t ret; if (bus->ops->master_xfer) { -#ifdef RT_I2C_DEBUG - for (ret = 0; ret < size; ret++) + #ifdef RT_I2C_DEBUG + for (ret = 0; ret < num; ret++) { i2c_dbg("msgs[%d] %c, addr=0x%02x, len=%d%s\n", ret, (msgs[ret].flags & RT_I2C_RD) ? 'R' : 'W', msgs[ret].addr, msgs[ret].len); } -#endif + #endif rt_mutex_take(&bus->lock, RT_WAITING_FOREVER); - - ret = bus->ops->master_xfer(bus, msgs, size); + ret = bus->ops->master_xfer(bus, msgs, num); rt_mutex_release(&bus->lock); return ret; } else { - rt_kprintf("I2C bus transfers not supported\n"); + rt_kprintf("I2C bus operation not supported\n"); return -RT_ERROR; } } -rt_size_t rt_i2c_master_send(struct rt_i2c_device *device, - const rt_uint8_t *buf, rt_uint32_t size) +rt_size_t rt_i2c_master_send(struct rt_i2c_bus_device *bus, rt_uint16_t addr, + rt_uint16_t flags, const rt_uint8_t *buf, + rt_uint32_t count) { rt_size_t ret; struct rt_i2c_msg msg; - struct rt_i2c_bus *bus = device->bus; - msg.addr = device->addr; - msg.flags = device->flags & RT_I2C_ADDR_10BIT; - msg.len = size; + msg.addr = addr; + msg.flags = flags & RT_I2C_ADDR_10BIT; + msg.len = count; msg.buf = (rt_uint8_t *)buf; ret = rt_i2c_transfer(bus, &msg, 1); - if (ret > 0) - { - return size; - } - - return ret; + return (ret > 0) ? count : ret; } -rt_size_t rt_i2c_master_recv(struct rt_i2c_device *device, - rt_uint8_t *buf, rt_uint32_t size) +rt_size_t rt_i2c_master_recv(struct rt_i2c_bus_device *bus, rt_uint16_t addr, + rt_uint16_t flags, rt_uint8_t *buf, + rt_uint32_t count) { rt_size_t ret; struct rt_i2c_msg msg; - struct rt_i2c_bus *bus = device->bus; RT_ASSERT(bus != RT_NULL); - msg.addr = device->addr; - msg.flags = device->flags & RT_I2C_ADDR_10BIT; + msg.addr = addr; + msg.flags = flags & RT_I2C_ADDR_10BIT; msg.flags |= RT_I2C_RD; - msg.len = size; + msg.len = count; msg.buf = buf; ret = rt_i2c_transfer(bus, &msg, 1); - if (ret > 0) - { - return size; - } - - return ret; + return (ret > 0) ? count : ret; } -rt_err_t rt_i2c_core_init() +rt_err_t rt_i2c_core_init(void) { + rt_mutex_init (&i2c_core_lock, "i2c_core_lock", RT_IPC_FLAG_FIFO); - rt_mutex_init (&i2c_hardware_lock, "i2c_hw_lock", RT_IPC_FLAG_FIFO); + } diff --git a/components/drivers/i2c/i2c_dev.c b/components/drivers/i2c/i2c_dev.c index e74d6252a..5743903ac 100644 --- a/components/drivers/i2c/i2c_dev.c +++ b/components/drivers/i2c/i2c_dev.c @@ -1,12 +1,8 @@ -#include -#include +#include static rt_err_t i2c_bus_device_init(rt_device_t dev) { - struct rt_i2c_bus* bus; - struct rt_i2c_device *i2c_device = dev->user_data; - - bus = i2c_device->bus; + struct rt_i2c_bus_device* bus = (struct rt_i2c_bus_device *)dev->user_data; RT_ASSERT(bus != RT_NULL); return RT_EOK; @@ -14,53 +10,54 @@ static rt_err_t i2c_bus_device_init(rt_device_t dev) static rt_size_t i2c_bus_device_read (rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t count) { - struct rt_i2c_bus* bus; - struct rt_i2c_device *i2c_device = dev->user_data; + rt_uint16_t addr; + rt_uint16_t flags; + struct rt_i2c_bus_device* bus = (struct rt_i2c_bus_device *)dev->user_data; - bus = i2c_device->bus; RT_ASSERT(bus != RT_NULL); - RT_ASSERT(i2c_device != RT_NULL); RT_ASSERT(buffer != RT_NULL); - i2c_dbg("I2C bus dev [%s] reading %u bytes.\n", bus->name, count); + i2c_dbg("I2C bus dev [%s] reading %u bytes.\n", dev->parent.name, count); - return rt_i2c_master_recv(i2c_device, buffer, count); + addr = pos & 0xffff; + flags = (pos >> 16) & 0xffff; + + return rt_i2c_master_recv(bus, addr, flags, buffer, count); } -static rt_size_t i2c_bus_device_write (rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) +static rt_size_t i2c_bus_device_write (rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t count) { - struct rt_i2c_bus* bus; - struct rt_i2c_device *i2c_device = dev->user_data; - - bus = i2c_device->bus; + rt_uint16_t addr; + rt_uint16_t flags; + struct rt_i2c_bus_device* bus = (struct rt_i2c_bus_device *)dev->user_data; + RT_ASSERT(bus != RT_NULL); - RT_ASSERT(i2c_device != RT_NULL); RT_ASSERT(buffer != RT_NULL); - i2c_dbg("I2C bus dev writing %u bytes.\n", bus->name, size); + i2c_dbg("I2C bus dev writing %u bytes.\n", dev->parent.name, count); - return rt_i2c_master_send(i2c_device, buffer, size); + addr = pos & 0xffff; + flags = (pos >> 16) & 0xffff; + + return rt_i2c_master_send(bus, addr, flags, buffer, count); } static rt_err_t i2c_bus_device_control(rt_device_t dev, rt_uint8_t cmd, void *args) { rt_err_t ret; - struct rt_i2c_bus* bus; struct rt_i2c_priv_data *priv_data; - struct rt_i2c_device *i2c_device = dev->user_data; + struct rt_i2c_bus_device* bus = (struct rt_i2c_bus_device *)dev->user_data; - bus = i2c_device->bus; RT_ASSERT(bus != RT_NULL); - RT_ASSERT(i2c_device != RT_NULL); switch (cmd) { case RT_I2C_DEV_CTRL_10BIT: /* set 10-bit addr mode */ - i2c_device->flags |= RT_I2C_ADDR_10BIT; + bus->flags |= RT_I2C_ADDR_10BIT; break; case RT_I2C_DEV_CTRL_ADDR: - i2c_device->addr = *(rt_uint16_t *)args; + bus->addr = *(rt_uint16_t *)args; break; case RT_I2C_DEV_CTRL_TIMEOUT: bus->timeout = *(rt_uint32_t *)args; @@ -80,27 +77,14 @@ static rt_err_t i2c_bus_device_control(rt_device_t dev, rt_uint8_t cmd, void *ar } -rt_err_t rt_i2c_bus_device_init(struct rt_i2c_bus* bus, const char* name) +rt_err_t rt_i2c_bus_device_device_init(struct rt_i2c_bus_device* bus, const char* name) { struct rt_device *device; - struct rt_i2c_device *i2c_device; RT_ASSERT(bus != RT_NULL); - //device = &bus->parent; + device = &bus->parent; - i2c_device = rt_malloc(sizeof(struct rt_i2c_device)); - if (i2c_device == RT_NULL) - { - return -RT_ENOMEM; - } - - rt_memset(i2c_device, 0, sizeof(struct rt_i2c_device)); - - device = &i2c_device->dev; - i2c_device->bus = bus; - bus->parent = device; - - device->user_data = i2c_device; + device->user_data = bus; /* set device type */ device->type = RT_Device_Class_I2CBUS; @@ -118,20 +102,4 @@ rt_err_t rt_i2c_bus_device_init(struct rt_i2c_bus* bus, const char* name) return RT_EOK; } -rt_err_t rt_i2c_bus_device_exit(struct rt_i2c_bus* bus) -{ - struct rt_device *device; - struct rt_i2c_device *i2c_device; - RT_ASSERT(bus != RT_NULL); - device = bus->parent; - - i2c_device = device->user_data;; - - /* register to device manager */ - rt_device_unregister(device); - - rt_free(i2c_device); - - return RT_EOK; -} diff --git a/components/drivers/i2c/i2c-bit-ops.h b/components/drivers/include/drivers/i2c-bit-ops.h similarity index 90% rename from components/drivers/i2c/i2c-bit-ops.h rename to components/drivers/include/drivers/i2c-bit-ops.h index 0f4947863..8b9253d9f 100644 --- a/components/drivers/i2c/i2c-bit-ops.h +++ b/components/drivers/include/drivers/i2c-bit-ops.h @@ -32,7 +32,7 @@ struct rt_i2c_bit_ops { rt_uint32_t timeout; /* in tick */ }; -rt_err_t rt_i2c_bit_add_bus(struct rt_i2c_bus *bus); +rt_err_t rt_i2c_bit_add_bus(struct rt_i2c_bus_device *bus, const char *bus_name); #ifdef __cplusplus } diff --git a/components/drivers/include/drivers/i2c.h b/components/drivers/include/drivers/i2c.h new file mode 100644 index 000000000..69b43e95b --- /dev/null +++ b/components/drivers/include/drivers/i2c.h @@ -0,0 +1,79 @@ +/* + * File : i2c.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2012-04-25 weety first version + */ + +#ifndef __I2C_H__ +#define __I2C_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define RT_I2C_WR 0x0000 +#define RT_I2C_RD (1u << 0) +#define RT_I2C_ADDR_10BIT (1u << 2) /* this is a ten bit chip address */ +#define RT_I2C_NO_START (1u << 4) +#define RT_I2C_IGNORE_NACK (1u << 5) +#define RT_I2C_NO_READ_ACK (1u << 6) /* when I2C reading, we do not ACK */ + +struct rt_i2c_msg { + rt_uint16_t addr; + rt_uint16_t flags; + rt_uint16_t len; + rt_uint8_t *buf; +}; + +struct rt_i2c_bus_device; + +struct rt_i2c_bus_device_ops { + rt_size_t (*master_xfer) (struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num); + rt_size_t (*slave_xfer) (struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num); + rt_err_t (*i2c_bus_control) (struct rt_i2c_bus_device *bus, rt_uint32_t, rt_uint32_t); +}; + +/*for i2c bus driver*/ +struct rt_i2c_bus_device { + struct rt_device parent; + const struct rt_i2c_bus_device_ops *ops; + rt_uint16_t flags; + rt_uint16_t addr; + struct rt_mutex lock; + rt_uint32_t timeout; + rt_uint32_t retries; + void *priv; +}; + +#ifdef RT_I2C_DEBUG +#define i2c_dbg(fmt, ...) rt_kprintf(fmt, ##__VA_ARGS__) +#else +#define i2c_dbg(fmt, ...) +#endif + +rt_err_t rt_i2c_bus_device_register(struct rt_i2c_bus_device *bus, const char *bus_name); +struct rt_i2c_bus_device* rt_i2c_bus_device_find(const char *bus_name); +rt_size_t rt_i2c_transfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num); +rt_size_t rt_i2c_master_send(struct rt_i2c_bus_device *bus, rt_uint16_t addr, + rt_uint16_t flags, const rt_uint8_t *buf, + rt_uint32_t count); +rt_size_t rt_i2c_master_recv(struct rt_i2c_bus_device *bus, rt_uint16_t addr, + rt_uint16_t flags, rt_uint8_t *buf, + rt_uint32_t count); +rt_err_t rt_i2c_core_init(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/i2c/i2c_dev.h b/components/drivers/include/drivers/i2c_dev.h similarity index 73% rename from components/drivers/i2c/i2c_dev.h rename to components/drivers/include/drivers/i2c_dev.h index 5f343929a..b173e9933 100644 --- a/components/drivers/i2c/i2c_dev.h +++ b/components/drivers/include/drivers/i2c_dev.h @@ -17,8 +17,7 @@ struct rt_i2c_priv_data { rt_size_t number; }; -rt_err_t rt_i2c_bus_device_init(struct rt_i2c_bus* bus, const char* name); -rt_err_t rt_i2c_bus_device_exit(struct rt_i2c_bus* bus); +rt_err_t rt_i2c_bus_device_device_init(struct rt_i2c_bus_device* bus, const char* name); #ifdef __cplusplus diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h index 2b4b7b9ec..77dbddd9a 100644 --- a/components/drivers/include/rtdevice.h +++ b/components/drivers/include/rtdevice.h @@ -67,4 +67,13 @@ rt_size_t rt_ringbuffer_emptry_size(struct rt_ringbuffer* rb); #include "drivers/serial.h" #endif +#ifdef RT_USING_I2C +#include "drivers/i2c.h" +#include "drivers/i2c_dev.h" +#endif + +#ifdef RT_USING_I2C_BITOPS +#include "drivers/i2c-bit-ops.h" +#endif + #endif