Browse Source

fixed the coding style in the components/drivers

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@2431 bbd45198-f89e-11dd-88c7-29a3b14d5316
dzzxzz@gmail.com 12 years ago
parent
commit
68b7e7c481

+ 450 - 444
components/drivers/i2c/i2c-bit-ops.c

@@ -1,444 +1,450 @@
-/*
- * File      : i2c-bit-ops.c
- * 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
- */
-
-#include <rtdevice.h>
-
-#ifdef RT_I2C_BIT_DEBUG
-#define bit_dbg(fmt, ...)	rt_kprintf(fmt, ##__VA_ARGS__)
-#else
-#define bit_dbg(fmt, ...)
-#endif
-
-
-#define SET_SDA(ops, val)	ops->set_sda(ops->data, val)
-#define SET_SCL(ops, val)	ops->set_scl(ops->data, val)
-#define GET_SDA(ops)		ops->get_sda(ops->data)
-#define GET_SCL(ops)		ops->get_scl(ops->data)
-
-rt_inline void i2c_delay(struct rt_i2c_bit_ops *ops)
-{
-    ops->udelay((ops->delay_us + 1) >> 1);
-}
-
-rt_inline void i2c_delay2(struct rt_i2c_bit_ops *ops)
-{
-    ops->udelay(ops->delay_us);
-}
-
-#define SDA_L(ops)	SET_SDA(ops, 0)
-#define SDA_H(ops)	SET_SDA(ops, 1)
-#define SCL_L(ops)	SET_SCL(ops, 0)
-
-/*
- * release scl line, and wait scl line to high.
- */
-static rt_err_t SCL_H(struct rt_i2c_bit_ops *ops)
-{
-    rt_tick_t start;
-
-    SET_SCL(ops, 1);
-
-    if (!ops->get_scl)
-        goto done;
-
-    start = rt_tick_get();
-    while (!GET_SCL(ops))
-    {
-        if ((rt_tick_get() - start) > ops->timeout)
-            return -RT_ETIMEOUT;
-        rt_thread_delay((ops->timeout + 1) >> 1);
-    }
-#ifdef RT_I2C_BIT_DEBUG
-    if (rt_tick_get() != start)
-    {
-        bit_dbg("wait %ld tick for SCL line to go high\n",
-                rt_tick_get() - start);
-    }
-#endif
-
-done:
-    i2c_delay(ops);
-
-    return RT_EOK;
-}
-
-
-static void i2c_start(struct rt_i2c_bit_ops *ops)
-{
-#ifdef RT_I2C_BIT_DEBUG
-    if (ops->get_scl && !GET_SCL(ops))
-    {
-        bit_dbg("I2C bus error, SCL line low\n");
-    }
-    if (ops->get_sda && !GET_SDA(ops))
-    {
-        bit_dbg("I2C bus error, SDA line low\n");
-    }
-#endif
-    SDA_L(ops);
-    i2c_delay(ops);
-    SCL_L(ops);
-}
-
-static void i2c_restart(struct rt_i2c_bit_ops *ops)
-{
-    SDA_H(ops);
-    SCL_H(ops);
-    i2c_delay(ops);
-    SDA_L(ops);
-    i2c_delay(ops);
-    SCL_L(ops);
-}
-
-
-static void i2c_stop(struct rt_i2c_bit_ops *ops)
-{
-    SDA_L(ops);
-    i2c_delay(ops);
-    SCL_H(ops);
-    i2c_delay(ops);
-    SDA_H(ops);
-    i2c_delay2(ops);
-}
-
-rt_inline rt_bool_t i2c_waitack(struct rt_i2c_bit_ops *ops)
-{
-    rt_bool_t ack;
-
-    SDA_H(ops);
-    i2c_delay(ops);
-
-    if (SCL_H(ops) < 0)
-    {
-        bit_dbg("wait ack timeout\n");
-        return -RT_ETIMEOUT;
-    }
-
-    ack = !GET_SDA(ops);    /* ACK : SDA pin is pulled low */
-    bit_dbg("%s\n", ack ? "ACK" : "NACK");
-
-    SCL_L(ops);
-
-    return ack;
-}
-
-
-static rt_int32_t i2c_writeb(struct rt_i2c_bus_device *bus, rt_uint8_t data)
-{
-    rt_int32_t i;
-    rt_uint8_t bit;
-
-    struct rt_i2c_bit_ops *ops = bus->priv;
-
-    for (i = 7; i >= 0; i--)
-    {
-        SCL_L(ops);
-        bit = (data >> i) & 1;
-        SET_SDA(ops, bit);
-        i2c_delay(ops);
-        if (SCL_H(ops) < 0)
-        {
-            bit_dbg("i2c_writeb: 0x%02x, "
-                    "wait scl pin high timeout at bit %d\n",
-                    data, i);
-            return -RT_ETIMEOUT;
-        }
-
-    }
-    SCL_L(ops);
-    i2c_delay(ops);
-
-    return i2c_waitack(ops);
-}
-
-
-static rt_int32_t i2c_readb(struct rt_i2c_bus_device *bus)
-{
-    rt_uint8_t i;
-    rt_uint8_t data = 0;
-    struct rt_i2c_bit_ops *ops = bus->priv;
-
-    SDA_H(ops);
-    i2c_delay(ops);
-    for (i = 0; i < 8; i++)
-    {
-        data <<= 1;
-
-        if (SCL_H(ops) < 0)
-        {
-            bit_dbg("i2c_readb: wait scl pin high "
-                    "timeout at bit %d\n", 7 - i);
-            return -RT_ETIMEOUT;
-        }
-
-        if (GET_SDA(ops))
-            data |= 1;
-        SCL_L(ops);
-        i2c_delay2(ops);
-    }
-
-    return data;
-}
-
-
-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;
-    const rt_uint8_t *ptr = msg->buf;
-    rt_int32_t count = msg->len;
-    rt_uint16_t ignore_nack = msg->flags & RT_I2C_IGNORE_NACK;
-
-    while (count > 0)
-    {
-        ret = i2c_writeb(bus, *ptr);
-
-        if ((ret > 0) || (ignore_nack && (ret == 0)))
-        {
-            count--;
-            ptr++;
-            bytes++;
-        }
-        else if (ret == 0)
-        {
-            i2c_dbg("send bytes: NACK.\n");
-            return 0;
-        }
-        else
-        {
-            i2c_dbg("send bytes: error %d\n", ret);
-            return ret;
-        }
-    }
-    return bytes;
-}
-
-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;
-
-    if (ack)
-        SET_SDA(ops, 0);
-    i2c_delay(ops);
-    if (SCL_H(ops) < 0)
-    {
-        bit_dbg("ACK or NACK timeout\n");
-        return -RT_ETIMEOUT;
-    }
-    SCL_L(ops);
-    return RT_EOK;
-}
-
-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 */
-    rt_uint8_t *ptr = msg->buf;
-    rt_int32_t count = msg->len;
-    const rt_uint32_t flags = msg->flags;
-
-    while (count > 0)
-    {
-        val = i2c_readb(bus);
-        if (val >= 0)
-        {
-            *ptr = val;
-            bytes++;
-        }
-        else
-        {
-            break;
-        }
-
-        ptr++;
-        count--;
-
-        bit_dbg("recieve bytes: 0x%02x, %s\n",
-                val, (flags & RT_I2C_NO_READ_ACK) ?
-                "(No ACK/NACK)" : (count ? "ACK" : "NACK"));
-
-        if (!(flags & RT_I2C_NO_READ_ACK))
-        {
-            val = i2c_send_ack_or_nack(bus, count);
-            if (val < 0)
-                return val;
-        }
-    }
-    return bytes;
-}
-
-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;
-    rt_int32_t i;
-    rt_err_t ret = 0;
-
-    for (i = 0; i <= retries; i++)
-    {
-        ret = i2c_writeb(bus, addr);
-        if (ret == 1 || i == retries)
-            break;
-        bit_dbg("send stop condition\n");
-        i2c_stop(ops);
-        i2c_delay2(ops);
-        bit_dbg("send start condition\n");
-        i2c_start(ops);
-    }
-
-    return ret;
-}
-
-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;
-    struct rt_i2c_bit_ops *ops = bus->priv;
-
-    rt_uint8_t addr1, addr2;
-    rt_int32_t retries;
-    rt_err_t  ret;
-
-    retries = ignore_nack ? 0 : bus->retries;
-
-    if (flags & RT_I2C_ADDR_10BIT)
-    {
-        addr1 = 0xf0 | ((msg->addr >> 7) & 0x06);
-        addr2 = msg->addr & 0xff;
-
-        bit_dbg("addr1: %d, addr2: %d\n", addr1, addr2);
-
-        ret = i2c_send_address(bus, addr1, retries);
-        if ((ret != 1) && !ignore_nack)
-        {
-            bit_dbg("NACK: sending first addr\n");
-            return -RT_EIO;
-        }
-
-        ret = i2c_writeb(bus, addr2);
-        if ((ret != 1) && !ignore_nack)
-        {
-            bit_dbg("NACK: sending second addr\n");
-            return -RT_EIO;
-        }
-        if (flags & RT_I2C_RD)
-        {
-            bit_dbg("send repeated start condition\n");
-            i2c_restart(ops);
-            addr1 |= 0x01;
-            ret = i2c_send_address(bus, addr1, retries);
-            if ((ret != 1) && !ignore_nack)
-            {
-                bit_dbg("NACK: sending repeated addr\n");
-                return -RT_EIO;
-            }
-        }
-    }
-    else
-    {
-        /* 7-bit addr */
-        addr1 = msg->addr << 1;
-        if (flags & RT_I2C_RD)
-            addr1 |= 1;
-        ret = i2c_send_address(bus, addr1, retries);
-        if ((ret != 1) && !ignore_nack)
-            return -RT_EIO;
-    }
-
-    return RT_EOK;
-}
-
-
-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;
-    struct rt_i2c_bit_ops *ops = bus->priv;
-    rt_int32_t i, ret;
-    rt_uint16_t ignore_nack;
-
-    bit_dbg("send start condition\n");
-    i2c_start(ops);
-    for (i = 0; i < num; i++)
-    {
-        msg = &msgs[i];
-        ignore_nack = msg->flags & RT_I2C_IGNORE_NACK;
-        if (!(msg->flags & RT_I2C_NO_START))
-        {
-            if (i)
-            {
-                i2c_restart(ops);
-            }
-            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",
-                        msgs[i].addr, i);
-                goto out;
-            }
-        }
-        if (msg->flags & RT_I2C_RD)
-        {
-            ret = i2c_recv_bytes(bus, msg);
-            if (ret >= 1)
-                bit_dbg("read %d byte%s\n",
-                        ret, ret == 1 ? "" : "s");
-            if (ret < msg->len)
-            {
-                if (ret >= 0)
-                    ret = -RT_EIO;
-                goto out;
-            }
-        }
-        else
-        {
-            ret = i2c_send_bytes(bus, msg);
-            if (ret >= 1)
-                bit_dbg("write %d byte%s\n",
-                        ret, ret == 1 ? "" : "s");
-            if (ret < msg->len)
-            {
-                if (ret >= 0)
-                    ret = -RT_ERROR;
-                goto out;
-            }
-        }
-    }
-    ret = i;
-
-out:
-    bit_dbg("send stop condition\n");
-    i2c_stop(ops);
-
-    return ret;
-}
-
-
-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_device *bus, const char *bus_name)
-{
-    struct rt_i2c_bit_ops *bit_ops = bus->priv;
-    RT_ASSERT(bit_ops != RT_NULL);
-
-    bus->ops = &i2c_bit_bus_ops;
-
-    return rt_i2c_bus_device_register(bus, bus_name);
-}
+/*
+ * File      : i2c-bit-ops.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2012, 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
+ */
+
+#include <rtdevice.h>
+
+#ifdef RT_I2C_BIT_DEBUG
+#define bit_dbg(fmt, ...)   rt_kprintf(fmt, ##__VA_ARGS__)
+#else
+#define bit_dbg(fmt, ...)
+#endif
+
+#define SET_SDA(ops, val)   ops->set_sda(ops->data, val)
+#define SET_SCL(ops, val)   ops->set_scl(ops->data, val)
+#define GET_SDA(ops)        ops->get_sda(ops->data)
+#define GET_SCL(ops)        ops->get_scl(ops->data)
+
+rt_inline void i2c_delay(struct rt_i2c_bit_ops *ops)
+{
+    ops->udelay((ops->delay_us + 1) >> 1);
+}
+
+rt_inline void i2c_delay2(struct rt_i2c_bit_ops *ops)
+{
+    ops->udelay(ops->delay_us);
+}
+
+#define SDA_L(ops)          SET_SDA(ops, 0)
+#define SDA_H(ops)          SET_SDA(ops, 1)
+#define SCL_L(ops)          SET_SCL(ops, 0)
+
+/**
+ * release scl line, and wait scl line to high.
+ */
+static rt_err_t SCL_H(struct rt_i2c_bit_ops *ops)
+{
+    rt_tick_t start;
+
+    SET_SCL(ops, 1);
+
+    if (!ops->get_scl)
+        goto done;
+
+    start = rt_tick_get();
+    while (!GET_SCL(ops))
+    {
+        if ((rt_tick_get() - start) > ops->timeout)
+            return -RT_ETIMEOUT;
+        rt_thread_delay((ops->timeout + 1) >> 1);
+    }
+#ifdef RT_I2C_BIT_DEBUG
+    if (rt_tick_get() != start)
+    {
+        bit_dbg("wait %ld tick for SCL line to go high\n",
+                rt_tick_get() - start);
+    }
+#endif
+
+done:
+    i2c_delay(ops);
+
+    return RT_EOK;
+}
+
+static void i2c_start(struct rt_i2c_bit_ops *ops)
+{
+#ifdef RT_I2C_BIT_DEBUG
+    if (ops->get_scl && !GET_SCL(ops))
+    {
+        bit_dbg("I2C bus error, SCL line low\n");
+    }
+    if (ops->get_sda && !GET_SDA(ops))
+    {
+        bit_dbg("I2C bus error, SDA line low\n");
+    }
+#endif
+    SDA_L(ops);
+    i2c_delay(ops);
+    SCL_L(ops);
+}
+
+static void i2c_restart(struct rt_i2c_bit_ops *ops)
+{
+    SDA_H(ops);
+    SCL_H(ops);
+    i2c_delay(ops);
+    SDA_L(ops);
+    i2c_delay(ops);
+    SCL_L(ops);
+}
+
+static void i2c_stop(struct rt_i2c_bit_ops *ops)
+{
+    SDA_L(ops);
+    i2c_delay(ops);
+    SCL_H(ops);
+    i2c_delay(ops);
+    SDA_H(ops);
+    i2c_delay2(ops);
+}
+
+rt_inline rt_bool_t i2c_waitack(struct rt_i2c_bit_ops *ops)
+{
+    rt_bool_t ack;
+
+    SDA_H(ops);
+    i2c_delay(ops);
+
+    if (SCL_H(ops) < 0)
+    {
+        bit_dbg("wait ack timeout\n");
+
+        return -RT_ETIMEOUT;
+    }
+
+    ack = !GET_SDA(ops);    /* ACK : SDA pin is pulled low */
+    bit_dbg("%s\n", ack ? "ACK" : "NACK");
+
+    SCL_L(ops);
+
+    return ack;
+}
+
+static rt_int32_t i2c_writeb(struct rt_i2c_bus_device *bus, rt_uint8_t data)
+{
+    rt_int32_t i;
+    rt_uint8_t bit;
+
+    struct rt_i2c_bit_ops *ops = bus->priv;
+
+    for (i = 7; i >= 0; i--)
+    {
+        SCL_L(ops);
+        bit = (data >> i) & 1;
+        SET_SDA(ops, bit);
+        i2c_delay(ops);
+        if (SCL_H(ops) < 0)
+        {
+            bit_dbg("i2c_writeb: 0x%02x, "
+                    "wait scl pin high timeout at bit %d\n",
+                    data, i);
+
+            return -RT_ETIMEOUT;
+        }
+    }
+    SCL_L(ops);
+    i2c_delay(ops);
+
+    return i2c_waitack(ops);
+}
+
+static rt_int32_t i2c_readb(struct rt_i2c_bus_device *bus)
+{
+    rt_uint8_t i;
+    rt_uint8_t data = 0;
+    struct rt_i2c_bit_ops *ops = bus->priv;
+
+    SDA_H(ops);
+    i2c_delay(ops);
+    for (i = 0; i < 8; i++)
+    {
+        data <<= 1;
+
+        if (SCL_H(ops) < 0)
+        {
+            bit_dbg("i2c_readb: wait scl pin high "
+                    "timeout at bit %d\n", 7 - i);
+
+            return -RT_ETIMEOUT;
+        }
+
+        if (GET_SDA(ops))
+            data |= 1;
+        SCL_L(ops);
+        i2c_delay2(ops);
+    }
+
+    return data;
+}
+
+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;
+    const rt_uint8_t *ptr = msg->buf;
+    rt_int32_t count = msg->len;
+    rt_uint16_t ignore_nack = msg->flags & RT_I2C_IGNORE_NACK;
+
+    while (count > 0)
+    {
+        ret = i2c_writeb(bus, *ptr);
+
+        if ((ret > 0) || (ignore_nack && (ret == 0)))
+        {
+            count --;
+            ptr ++;
+            bytes ++;
+        }
+        else if (ret == 0)
+        {
+            i2c_dbg("send bytes: NACK.\n");
+
+            return 0;
+        }
+        else
+        {
+            i2c_dbg("send bytes: error %d\n", ret);
+
+            return ret;
+        }
+    }
+
+    return bytes;
+}
+
+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;
+
+    if (ack)
+        SET_SDA(ops, 0);
+    i2c_delay(ops);
+    if (SCL_H(ops) < 0)
+    {
+        bit_dbg("ACK or NACK timeout\n");
+
+        return -RT_ETIMEOUT;
+    }
+    SCL_L(ops);
+
+    return RT_EOK;
+}
+
+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 */
+    rt_uint8_t *ptr = msg->buf;
+    rt_int32_t count = msg->len;
+    const rt_uint32_t flags = msg->flags;
+
+    while (count > 0)
+    {
+        val = i2c_readb(bus);
+        if (val >= 0)
+        {
+            *ptr = val;
+            bytes ++;
+        }
+        else
+        {
+            break;
+        }
+
+        ptr ++;
+        count --;
+
+        bit_dbg("recieve bytes: 0x%02x, %s\n",
+                val, (flags & RT_I2C_NO_READ_ACK) ?
+                "(No ACK/NACK)" : (count ? "ACK" : "NACK"));
+
+        if (!(flags & RT_I2C_NO_READ_ACK))
+        {
+            val = i2c_send_ack_or_nack(bus, count);
+            if (val < 0)
+                return val;
+        }
+    }
+
+    return bytes;
+}
+
+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;
+    rt_int32_t i;
+    rt_err_t ret = 0;
+
+    for (i = 0; i <= retries; i++)
+    {
+        ret = i2c_writeb(bus, addr);
+        if (ret == 1 || i == retries)
+            break;
+        bit_dbg("send stop condition\n");
+        i2c_stop(ops);
+        i2c_delay2(ops);
+        bit_dbg("send start condition\n");
+        i2c_start(ops);
+    }
+
+    return ret;
+}
+
+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;
+    struct rt_i2c_bit_ops *ops = bus->priv;
+
+    rt_uint8_t addr1, addr2;
+    rt_int32_t retries;
+    rt_err_t ret;
+
+    retries = ignore_nack ? 0 : bus->retries;
+
+    if (flags & RT_I2C_ADDR_10BIT)
+    {
+        addr1 = 0xf0 | ((msg->addr >> 7) & 0x06);
+        addr2 = msg->addr & 0xff;
+
+        bit_dbg("addr1: %d, addr2: %d\n", addr1, addr2);
+
+        ret = i2c_send_address(bus, addr1, retries);
+        if ((ret != 1) && !ignore_nack)
+        {
+            bit_dbg("NACK: sending first addr\n");
+
+            return -RT_EIO;
+        }
+
+        ret = i2c_writeb(bus, addr2);
+        if ((ret != 1) && !ignore_nack)
+        {
+            bit_dbg("NACK: sending second addr\n");
+
+            return -RT_EIO;
+        }
+        if (flags & RT_I2C_RD)
+        {
+            bit_dbg("send repeated start condition\n");
+            i2c_restart(ops);
+            addr1 |= 0x01;
+            ret = i2c_send_address(bus, addr1, retries);
+            if ((ret != 1) && !ignore_nack)
+            {
+                bit_dbg("NACK: sending repeated addr\n");
+
+                return -RT_EIO;
+            }
+        }
+    }
+    else
+    {
+        /* 7-bit addr */
+        addr1 = msg->addr << 1;
+        if (flags & RT_I2C_RD)
+            addr1 |= 1;
+        ret = i2c_send_address(bus, addr1, retries);
+        if ((ret != 1) && !ignore_nack)
+            return -RT_EIO;
+    }
+
+    return RT_EOK;
+}
+
+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;
+    struct rt_i2c_bit_ops *ops = bus->priv;
+    rt_int32_t i, ret;
+    rt_uint16_t ignore_nack;
+
+    bit_dbg("send start condition\n");
+    i2c_start(ops);
+    for (i = 0; i < num; i++)
+    {
+        msg = &msgs[i];
+        ignore_nack = msg->flags & RT_I2C_IGNORE_NACK;
+        if (!(msg->flags & RT_I2C_NO_START))
+        {
+            if (i)
+            {
+                i2c_restart(ops);
+            }
+            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",
+                        msgs[i].addr, i);
+                goto out;
+            }
+        }
+        if (msg->flags & RT_I2C_RD)
+        {
+            ret = i2c_recv_bytes(bus, msg);
+            if (ret >= 1)
+                bit_dbg("read %d byte%s\n", ret, ret == 1 ? "" : "s");
+            if (ret < msg->len)
+            {
+                if (ret >= 0)
+                    ret = -RT_EIO;
+                goto out;
+            }
+        }
+        else
+        {
+            ret = i2c_send_bytes(bus, msg);
+            if (ret >= 1)
+                bit_dbg("write %d byte%s\n", ret, ret == 1 ? "" : "s");
+            if (ret < msg->len)
+            {
+                if (ret >= 0)
+                    ret = -RT_ERROR;
+                goto out;
+            }
+        }
+    }
+    ret = i;
+
+out:
+    bit_dbg("send stop condition\n");
+    i2c_stop(ops);
+
+    return ret;
+}
+
+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_device *bus,
+                            const char               *bus_name)
+{
+    struct rt_i2c_bit_ops *bit_ops = bus->priv;
+    RT_ASSERT(bit_ops != RT_NULL);
+
+    bus->ops = &i2c_bit_bus_ops;
+
+    return rt_i2c_bus_device_register(bus, bus_name);
+}

+ 131 - 135
components/drivers/i2c/i2c_core.c

@@ -1,135 +1,131 @@
-/*
- * File      : i2c_core.c
- * 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
- */
-
-#include <rtdevice.h>
-
-static struct rt_mutex i2c_core_lock;
-
-rt_err_t rt_i2c_bus_device_register(struct rt_i2c_bus_device *bus,
-                                    const char *bus_name)
-{
-    rt_err_t res = RT_EOK;
-
-    rt_mutex_init(&bus->lock, "i2c_bus_lock", RT_IPC_FLAG_FIFO);
-
-    rt_mutex_take(&i2c_core_lock, RT_WAITING_FOREVER);
-
-    if (bus->timeout == 0)
-        bus->timeout = RT_TICK_PER_SECOND;
-
-    res = rt_i2c_bus_device_device_init(bus, bus_name);
-
-    i2c_dbg("I2C bus [%s] registered\n", bus_name);
-
-    rt_mutex_release(&i2c_core_lock);
-    return res;
-}
-
-
-struct rt_i2c_bus_device* rt_i2c_bus_device_find(const char *bus_name)
-{
-    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)
-    {
-        i2c_dbg("I2C bus %s not exist\n", bus_name);
-        return RT_NULL;
-    }
-
-    bus = (struct rt_i2c_bus_device *)dev->user_data;
-
-    return bus;
-}
-
-
-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 < 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
-
-        rt_mutex_take(&bus->lock, RT_WAITING_FOREVER);
-        ret = bus->ops->master_xfer(bus, msgs, num);
-        rt_mutex_release(&bus->lock);
-
-        return ret;
-    }
-    else
-    {
-        i2c_dbg("I2C bus operation not supported\n");
-        return 0;
-    }
-}
-
-
-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;
-
-    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);
-
-    return (ret > 0) ? count : ret;
-}
-
-
-
-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;
-    RT_ASSERT(bus != RT_NULL);
-
-    msg.addr = addr;
-    msg.flags = flags & RT_I2C_ADDR_10BIT;
-    msg.flags |= RT_I2C_RD;
-    msg.len = count;
-    msg.buf = buf;
-
-    ret = rt_i2c_transfer(bus, &msg, 1);
-
-    return (ret > 0) ? count : ret;
-}
-
-
-rt_err_t rt_i2c_core_init(void)
-{
-
-    return rt_mutex_init (&i2c_core_lock, "i2c_core_lock", RT_IPC_FLAG_FIFO);
-}
-
+/*
+ * File      : i2c_core.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2012, 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
+ */
+
+#include <rtdevice.h>
+
+static struct rt_mutex i2c_core_lock;
+
+rt_err_t rt_i2c_bus_device_register(struct rt_i2c_bus_device *bus,
+                                    const char               *bus_name)
+{
+    rt_err_t res = RT_EOK;
+
+    rt_mutex_init(&bus->lock, "i2c_bus_lock", RT_IPC_FLAG_FIFO);
+
+    rt_mutex_take(&i2c_core_lock, RT_WAITING_FOREVER);
+
+    if (bus->timeout == 0)
+        bus->timeout = RT_TICK_PER_SECOND;
+
+    res = rt_i2c_bus_device_device_init(bus, bus_name);
+
+    i2c_dbg("I2C bus [%s] registered\n", bus_name);
+
+    rt_mutex_release(&i2c_core_lock);
+
+    return res;
+}
+
+struct rt_i2c_bus_device *rt_i2c_bus_device_find(const char *bus_name)
+{
+    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)
+    {
+        i2c_dbg("I2C bus %s not exist\n", bus_name);
+
+        return RT_NULL;
+    }
+
+    bus = (struct rt_i2c_bus_device *)dev->user_data;
+
+    return bus;
+}
+
+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 < 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
+
+        rt_mutex_take(&bus->lock, RT_WAITING_FOREVER);
+        ret = bus->ops->master_xfer(bus, msgs, num);
+        rt_mutex_release(&bus->lock);
+
+        return ret;
+    }
+    else
+    {
+        i2c_dbg("I2C bus operation not supported\n");
+
+        return 0;
+    }
+}
+
+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;
+
+    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);
+
+    return (ret > 0) ? count : ret;
+}
+
+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;
+    RT_ASSERT(bus != RT_NULL);
+
+    msg.addr   = addr;
+    msg.flags  = flags & RT_I2C_ADDR_10BIT;
+    msg.flags |= RT_I2C_RD;
+    msg.len    = count;
+    msg.buf    = buf;
+
+    ret = rt_i2c_transfer(bus, &msg, 1);
+
+    return (ret > 0) ? count : ret;
+}
+
+rt_err_t rt_i2c_core_init(void)
+{
+    return rt_mutex_init(&i2c_core_lock, "i2c_core_lock", RT_IPC_FLAG_FIFO);
+}
+

+ 126 - 113
components/drivers/i2c/i2c_dev.c

@@ -1,113 +1,126 @@
-#include <rtdevice.h>
-
-static rt_err_t i2c_bus_device_init(rt_device_t dev)
-{
-    struct rt_i2c_bus_device* bus = (struct rt_i2c_bus_device *)dev->user_data;
-    RT_ASSERT(bus != RT_NULL);
-
-    return RT_EOK;
-}
-
-static rt_size_t i2c_bus_device_read (rt_device_t dev,
-                                      rt_off_t pos,
-                                      void *buffer,
-                                      rt_size_t count)
-{
-    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(buffer != RT_NULL);
-
-    i2c_dbg("I2C bus dev [%s] reading %u bytes.\n", dev->parent.name, 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 count)
-{
-    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(buffer != RT_NULL);
-
-    i2c_dbg("I2C bus dev writing %u bytes.\n", dev->parent.name, count);
-
-    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_priv_data *priv_data;
-    struct rt_i2c_bus_device* bus = (struct rt_i2c_bus_device *)dev->user_data;
-
-    RT_ASSERT(bus != RT_NULL);
-
-    switch (cmd)
-    {
-    case RT_I2C_DEV_CTRL_10BIT: /* set 10-bit addr mode */
-        bus->flags |= RT_I2C_ADDR_10BIT;
-        break;
-    case RT_I2C_DEV_CTRL_ADDR:
-        bus->addr = *(rt_uint16_t *)args;
-        break;
-    case RT_I2C_DEV_CTRL_TIMEOUT:
-        bus->timeout = *(rt_uint32_t *)args;
-        break;
-    case RT_I2C_DEV_CTRL_RW:
-        priv_data = (struct rt_i2c_priv_data *)args;
-        ret = rt_i2c_transfer(bus, priv_data->msgs, priv_data->number);
-        if (ret < 0)
-        {
-            return -RT_EIO;
-        }
-        break;
-    default:
-        break;
-    }
-
-    return RT_EOK;
-}
-
-
-rt_err_t rt_i2c_bus_device_device_init(struct rt_i2c_bus_device* bus,
-                                       const char* name)
-{
-    struct rt_device *device;
-    RT_ASSERT(bus != RT_NULL);
-
-    device = &bus->parent;
-
-    device->user_data = bus;
-
-    /* set device type */
-    device->type    = RT_Device_Class_I2CBUS;
-    /* initialize device interface */
-    device->init	= i2c_bus_device_init;
-    device->open	= RT_NULL;
-    device->close	= RT_NULL;
-    device->read	= i2c_bus_device_read;
-    device->write	= i2c_bus_device_write;
-    device->control = i2c_bus_device_control;
-
-    /* register to device manager */
-    rt_device_register(device, name, RT_DEVICE_FLAG_RDWR);
-
-    return RT_EOK;
-}
+/*
+ * File      : i2c_dev.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2012, 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
+ */
+
+#include <rtdevice.h>
+
+static rt_err_t i2c_bus_device_init(rt_device_t dev)
+{
+    struct rt_i2c_bus_device *bus = (struct rt_i2c_bus_device *)dev->user_data;
+    RT_ASSERT(bus != RT_NULL);
+
+    return RT_EOK;
+}
+
+static rt_size_t i2c_bus_device_read(rt_device_t dev,
+                                     rt_off_t    pos,
+                                     void       *buffer,
+                                     rt_size_t   count)
+{
+    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(buffer != RT_NULL);
+
+    i2c_dbg("I2C bus dev [%s] reading %u bytes.\n", dev->parent.name, 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   count)
+{
+    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(buffer != RT_NULL);
+
+    i2c_dbg("I2C bus dev writing %u bytes.\n", dev->parent.name, count);
+
+    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_priv_data *priv_data;
+    struct rt_i2c_bus_device *bus = (struct rt_i2c_bus_device *)dev->user_data;
+
+    RT_ASSERT(bus != RT_NULL);
+
+    switch (cmd)
+    {
+    /* set 10-bit addr mode */
+    case RT_I2C_DEV_CTRL_10BIT:
+        bus->flags |= RT_I2C_ADDR_10BIT;
+        break;
+    case RT_I2C_DEV_CTRL_ADDR:
+        bus->addr = *(rt_uint16_t *)args;
+        break;
+    case RT_I2C_DEV_CTRL_TIMEOUT:
+        bus->timeout = *(rt_uint32_t *)args;
+        break;
+    case RT_I2C_DEV_CTRL_RW:
+        priv_data = (struct rt_i2c_priv_data *)args;
+        ret = rt_i2c_transfer(bus, priv_data->msgs, priv_data->number);
+        if (ret < 0)
+        {
+            return -RT_EIO;
+        }
+        break;
+    default:
+        break;
+    }
+
+    return RT_EOK;
+}
+
+rt_err_t rt_i2c_bus_device_device_init(struct rt_i2c_bus_device *bus,
+                                       const char               *name)
+{
+    struct rt_device *device;
+    RT_ASSERT(bus != RT_NULL);
+
+    device = &bus->parent;
+
+    device->user_data = bus;
+
+    /* set device type */
+    device->type    = RT_Device_Class_I2CBUS;
+    /* initialize device interface */
+    device->init    = i2c_bus_device_init;
+    device->open    = RT_NULL;
+    device->close   = RT_NULL;
+    device->read    = i2c_bus_device_read;
+    device->write   = i2c_bus_device_write;
+    device->control = i2c_bus_device_control;
+
+    /* register to device manager */
+    rt_device_register(device, name, RT_DEVICE_FLAG_RDWR);
+
+    return RT_EOK;
+}

+ 43 - 43
components/drivers/include/drivers/i2c-bit-ops.h

@@ -1,43 +1,43 @@
-/*
- * File      : i2c-bit-ops.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_BIT_OPS_H__
-#define __I2C_BIT_OPS_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct rt_i2c_bit_ops
-{
-    void *data;  /* private data for lowlevel routines */
-    void (*set_sda) (void *data, rt_int32_t state);
-    void (*set_scl) (void *data, rt_int32_t state);
-    rt_int32_t  (*get_sda) (void *data);
-    rt_int32_t  (*get_scl) (void *data);
-
-    void (*udelay) (rt_uint32_t us);
-
-    rt_uint32_t delay_us;  /* scl and sda line delay */
-    rt_uint32_t timeout;  /* in tick */
-};
-
-rt_err_t rt_i2c_bit_add_bus(struct rt_i2c_bus_device *bus,
-                            const char *bus_name);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+/*
+ * File      : i2c-bit-ops.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2012, 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_BIT_OPS_H__
+#define __I2C_BIT_OPS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct rt_i2c_bit_ops
+{
+    void *data;            /* private data for lowlevel routines */
+    void (*set_sda)(void *data, rt_int32_t state);
+    void (*set_scl)(void *data, rt_int32_t state);
+    rt_int32_t (*get_sda)(void *data);
+    rt_int32_t (*get_scl)(void *data);
+
+    void (*udelay)(rt_uint32_t us);
+
+    rt_uint32_t delay_us;  /* scl and sda line delay */
+    rt_uint32_t timeout;   /* in tick */
+};
+
+rt_err_t rt_i2c_bit_add_bus(struct rt_i2c_bus_device *bus,
+                            const char               *bus_name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 95 - 95
components/drivers/include/drivers/i2c.h

@@ -1,95 +1,95 @@
-/*
- * 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 <rtthread.h>
-
-#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
+/*
+ * File      : i2c.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2012, 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 <rtthread.h>
+
+#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

+ 42 - 29
components/drivers/include/drivers/i2c_dev.h

@@ -1,29 +1,42 @@
-#ifndef __I2C_DEV_H__
-#define __I2C_DEV_H__
-
-#include <rtthread.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define RT_I2C_DEV_CTRL_10BIT        0x20
-#define RT_I2C_DEV_CTRL_ADDR         0x21
-#define RT_I2C_DEV_CTRL_TIMEOUT      0x22
-#define RT_I2C_DEV_CTRL_RW           0x23
-
-struct rt_i2c_priv_data
-{
-    struct rt_i2c_msg  *msgs;
-    rt_size_t  number;
-};
-
-rt_err_t rt_i2c_bus_device_device_init(struct rt_i2c_bus_device* bus,
-                                       const char* name);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+/*
+ * File      : i2c_dev.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2012, 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_DEV_H__
+#define __I2C_DEV_H__
+
+#include <rtthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define RT_I2C_DEV_CTRL_10BIT        0x20
+#define RT_I2C_DEV_CTRL_ADDR         0x21
+#define RT_I2C_DEV_CTRL_TIMEOUT      0x22
+#define RT_I2C_DEV_CTRL_RW           0x23
+
+struct rt_i2c_priv_data
+{
+    struct rt_i2c_msg  *msgs;
+    rt_size_t  number;
+};
+
+rt_err_t rt_i2c_bus_device_device_init(struct rt_i2c_bus_device *bus,
+                                       const char               *name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 86 - 77
components/drivers/mtd/mtd_nand.c

@@ -1,78 +1,87 @@
-/*
- * File      : mtd_core.c
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2006 - 2012, 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
- * 2011-12-05     Bernard      the first version
- */
-
-/*
- * COPYRIGHT (C) 2012, Shanghai Real Thread
- */
-
-#include <drivers/mtd_nand.h>
-
-#ifdef RT_USING_MTD_NAND
-
-/*
- * RT-Thread Generic Device Interface
- */
-static rt_err_t _mtd_init(rt_device_t dev)
-{
-	return RT_EOK;
-}
-
-static rt_err_t _mtd_open(rt_device_t dev, rt_uint16_t oflag)
-{
-	return RT_EOK;
-}
-
-static rt_err_t _mtd_close(rt_device_t dev)
-{
-	return RT_EOK;
-}
-
-static rt_size_t _mtd_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
-{
-	return size;
-}
-
-static rt_size_t _mtd_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
-{
-	return size;
-}
-
-static rt_err_t _mtd_control(rt_device_t dev, rt_uint8_t cmd, void *args)
-{
-	return RT_EOK;
-}
-
-rt_err_t rt_mtd_nand_register_device(const char* name, struct rt_mtd_nand_device* device)
-{
-	rt_device_t dev;
-
-	dev = RT_DEVICE(device);
-	RT_ASSERT(dev != RT_NULL);
-
-	/* set device class and generic device interface */
-	dev->type 		= RT_Device_Class_MTD;
-	dev->init 		= _mtd_init;
-	dev->open 		= _mtd_open;
-	dev->read 		= _mtd_read;
-	dev->write 		= _mtd_write;
-	dev->close      = _mtd_close;
-	dev->control 	= _mtd_control;
-
-	dev->rx_indicate = RT_NULL;
-	dev->tx_complete = RT_NULL;
-
-	/* register to RT-Thread device system */
-	return rt_device_register(dev, name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
+/*
+ * File      : mtd_core.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2012, 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
+ * 2011-12-05     Bernard      the first version
+ */
+
+/*
+ * COPYRIGHT (C) 2012, Shanghai Real Thread
+ */
+
+#include <drivers/mtd_nand.h>
+
+#ifdef RT_USING_MTD_NAND
+
+/**
+ * RT-Thread Generic Device Interface
+ */
+static rt_err_t _mtd_init(rt_device_t dev)
+{
+    return RT_EOK;
 }
-#endif
+
+static rt_err_t _mtd_open(rt_device_t dev, rt_uint16_t oflag)
+{
+    return RT_EOK;
+}
+
+static rt_err_t _mtd_close(rt_device_t dev)
+{
+    return RT_EOK;
+}
+
+static rt_size_t _mtd_read(rt_device_t dev,
+                           rt_off_t    pos,
+                           void       *buffer,
+                           rt_size_t   size)
+{
+    return size;
+}
+
+static rt_size_t _mtd_write(rt_device_t dev,
+                            rt_off_t    pos,
+                            const void *buffer,
+                            rt_size_t   size)
+{
+    return size;
+}
+
+static rt_err_t _mtd_control(rt_device_t dev, rt_uint8_t cmd, void *args)
+{
+    return RT_EOK;
+}
+
+rt_err_t rt_mtd_nand_register_device(const char                *name,
+                                     struct rt_mtd_nand_device *device)
+{
+    rt_device_t dev;
+
+    dev = RT_DEVICE(device);
+    RT_ASSERT(dev != RT_NULL);
+
+    /* set device class and generic device interface */
+    dev->type        = RT_Device_Class_MTD;
+    dev->init        = _mtd_init;
+    dev->open        = _mtd_open;
+    dev->read        = _mtd_read;
+    dev->write       = _mtd_write;
+    dev->close       = _mtd_close;
+    dev->control     = _mtd_control;
+
+    dev->rx_indicate = RT_NULL;
+    dev->tx_complete = RT_NULL;
+
+    /* register to RT-Thread device system */
+    return rt_device_register(dev, name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
+}
+
+
+#endif

+ 82 - 74
components/drivers/mtd/mtd_nor.c

@@ -1,74 +1,82 @@
-/*
- * File      : mtd_nor.c
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2012, Shanghai Real-Thread Technology Co., Ltd
- *
- * 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-5-30     Bernard      the first version
- */
-
-#include <drivers/mtd_nor.h>
-
-#ifdef RT_USING_MTD_NOR
-
-/*
- * RT-Thread Generic Device Interface
- */
-static rt_err_t _mtd_init(rt_device_t dev)
-{
-	return RT_EOK;
-}
-
-static rt_err_t _mtd_open(rt_device_t dev, rt_uint16_t oflag)
-{
-	return RT_EOK;
-}
-
-static rt_err_t _mtd_close(rt_device_t dev)
-{
-	return RT_EOK;
-}
-
-static rt_size_t _mtd_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
-{
-	return size;
-}
-
-static rt_size_t _mtd_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
-{
-	return size;
-}
-
-static rt_err_t _mtd_control(rt_device_t dev, rt_uint8_t cmd, void *args)
-{
-	return RT_EOK;
-}
-
-rt_err_t rt_mtd_nor_register_device(const char* name, struct rt_mtd_nor_device* device)
-{
-	rt_device_t dev;
-
-	dev = RT_DEVICE(device);
-	RT_ASSERT(dev != RT_NULL);
-
-	/* set device class and generic device interface */
-	dev->type 		= RT_Device_Class_MTD;
-	dev->init 		= _mtd_init;
-	dev->open 		= _mtd_open;
-	dev->read 		= _mtd_read;
-	dev->write 		= _mtd_write;
-	dev->close      = _mtd_close;
-	dev->control 	= _mtd_control;
-
-	dev->rx_indicate = RT_NULL;
-	dev->tx_complete = RT_NULL;
-
-	/* register to RT-Thread device system */
-	return rt_device_register(dev, name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
-}
-#endif
+/*
+ * File      : mtd_nor.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2012, Shanghai Real-Thread Technology Co., Ltd
+ *
+ * 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-5-30     Bernard      the first version
+ */
+
+#include <drivers/mtd_nor.h>
+
+#ifdef RT_USING_MTD_NOR
+
+/**
+ * RT-Thread Generic Device Interface
+ */
+static rt_err_t _mtd_init(rt_device_t dev)
+{
+    return RT_EOK;
+}
+
+static rt_err_t _mtd_open(rt_device_t dev, rt_uint16_t oflag)
+{
+    return RT_EOK;
+}
+
+static rt_err_t _mtd_close(rt_device_t dev)
+{
+    return RT_EOK;
+}
+
+static rt_size_t _mtd_read(rt_device_t dev,
+                           rt_off_t    pos,
+                           void       *buffer,
+                           rt_size_t   size)
+{
+    return size;
+}
+
+static rt_size_t _mtd_write(rt_device_t dev,
+                            rt_off_t    pos,
+                            const void *buffer,
+                            rt_size_t   size)
+{
+    return size;
+}
+
+static rt_err_t _mtd_control(rt_device_t dev, rt_uint8_t cmd, void *args)
+{
+    return RT_EOK;
+}
+
+rt_err_t rt_mtd_nor_register_device(const char               *name,
+                                    struct rt_mtd_nor_device *device)
+{
+    rt_device_t dev;
+
+    dev = RT_DEVICE(device);
+    RT_ASSERT(dev != RT_NULL);
+
+    /* set device class and generic device interface */
+    dev->type        = RT_Device_Class_MTD;
+    dev->init        = _mtd_init;
+    dev->open        = _mtd_open;
+    dev->read        = _mtd_read;
+    dev->write       = _mtd_write;
+    dev->close       = _mtd_close;
+    dev->control     = _mtd_control;
+
+    dev->rx_indicate = RT_NULL;
+    dev->tx_complete = RT_NULL;
+
+    /* register to RT-Thread device system */
+    return rt_device_register(dev, name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
+}
+
+#endif

+ 611 - 611
components/drivers/rtc/alarm.c

@@ -1,611 +1,611 @@
-/*
- * File      : alarm.c
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2006 - 2012, 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-10-27     heyuanjie87       first version.
- */
-
-#include <rtthread.h>
-#include <rtdevice.h>
-
-#define RT_RTC_YEARS_MAX         137
-#define RT_ALARM_DELAY             2
-#define RT_ALARM_STATE_INITED   0x02
-#define RT_ALARM_STATE_START    0x01
-#define RT_ALARM_STATE_STOP     0x00
-
-#if(defined(RT_USING_RTC) && defined(RT_USING_ALARM))
-static struct rt_alarm_container _container;
-
-rt_inline rt_uint32_t alarm_mkdaysec(struct tm *time)
-{
-    rt_uint32_t sec;
-
-    sec = time->tm_sec;
-    sec += time->tm_min * 60;
-    sec += time->tm_hour * 3600;
-
-    return (sec);
-}
-
-static rt_err_t alarm_set(struct rt_alarm *alarm)
-{
-    rt_device_t device;
-    struct rt_rtc_wkalarm wkalarm;
-    rt_err_t ret;
-
-    device = rt_device_find("rtc");
-    if (device == RT_NULL)
-    {
-        return (RT_ERROR);
-    }
-    if (alarm->flag & RT_ALARM_STATE_START)
-        wkalarm.enable = RT_TRUE;
-    else
-        wkalarm.enable = RT_FALSE;
-
-    wkalarm.tm_sec = alarm->wktime.tm_sec;
-    wkalarm.tm_min = alarm->wktime.tm_min;
-    wkalarm.tm_hour = alarm->wktime.tm_hour;
-
-    ret = rt_device_control(device, RT_DEVICE_CTRL_RTC_SET_ALARM, &wkalarm);
-    if ((ret == RT_EOK) && wkalarm.enable)
-    {
-        ret = rt_device_control(device, RT_DEVICE_CTRL_RTC_GET_ALARM, &wkalarm);
-        if (ret == RT_EOK)
-        {
-            /* 
-              some RTC device like RX8025,it's alarms precision is 1 minute.
-              in this case,low level RTC driver should set wkalarm->tm_sec to 0.
-            */
-            alarm->wktime.tm_sec = wkalarm.tm_sec;
-            alarm->wktime.tm_min = wkalarm.tm_min;
-            alarm->wktime.tm_hour = wkalarm.tm_hour;
-        }
-    }
-
-    return (ret);
-}
-
-static void alarm_wakeup(struct rt_alarm *alarm, struct tm *now)
-{
-    rt_uint32_t sec_alarm, sec_now;
-    rt_bool_t wakeup = RT_FALSE;
-    time_t timestamp;
-    
-    sec_alarm = alarm_mkdaysec(&alarm->wktime);
-    sec_now = alarm_mkdaysec(now);
-
-    if (alarm->flag & RT_ALARM_STATE_START)
-    {
-        switch (alarm->flag & 0xFF00)
-        {
-        case RT_ALARM_ONESHOT:
-        {
-            sec_alarm = mktime(&alarm->wktime);
-            sec_now = mktime(now);
-            if (((sec_now - sec_alarm) <= RT_ALARM_DELAY) && (sec_now >= sec_alarm))
-            {
-                /* stop alarm */
-                alarm->flag &= ~RT_ALARM_STATE_START;
-                alarm_set(alarm);
-                wakeup = RT_TRUE;
-            }  
-        }
-        break;
-        case RT_ALARM_DAILY:
-        {
-            if (((sec_now - sec_alarm) <= RT_ALARM_DELAY) && (sec_now >= sec_alarm))
-                wakeup = RT_TRUE;
-        }
-        break;
-        case RT_ALARM_WEEKLY:
-        {
-            /* alarm at wday */
-            sec_alarm += alarm->wktime.tm_wday * 24 * 3600;
-            sec_now += now->tm_wday * 24 * 3600;
-
-            if (((sec_now - sec_alarm) <= RT_ALARM_DELAY) && (sec_now >= sec_alarm))
-                wakeup = RT_TRUE;
-        }
-        break;
-        case RT_ALARM_MONTHLY:
-        {
-            /* monthly someday generate alarm signals */
-            if (alarm->wktime.tm_mday == now->tm_mday)
-            {
-                if ((sec_now - sec_alarm) <= RT_ALARM_DELAY)
-                    wakeup = RT_TRUE;
-            }
-        }
-        break;
-        case RT_ALARM_YAERLY:
-        {
-            if ((alarm->wktime.tm_mday == now->tm_mday) && \
-                (alarm->wktime.tm_mon == now->tm_mon))
-            {
-                  if ((sec_now - sec_alarm) <= RT_ALARM_DELAY)
-                    wakeup = RT_TRUE;           
-            }
-        }
-        break;
-        }
-
-        if ((wakeup == RT_TRUE) && (alarm->callback != RT_NULL))
-        {
-            timestamp = time(RT_NULL);
-            alarm->callback(alarm, timestamp);
-        }   
-    }
-}
-
-static void alarm_update(rt_uint32_t event)
-{
-    struct rt_alarm *alm_prev = RT_NULL, *alm_next = RT_NULL;
-    struct rt_alarm *alarm;
-    rt_int32_t sec_now, sec_alarm, sec_tmp;
-    rt_int32_t sec_next = 24 * 3600, sec_prev = 0;
-    time_t timestamp;
-    struct tm now;
-    rt_list_t *next;
-
-    rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER);
-    if (!rt_list_isempty(&_container.head))
-    {
-        /* get time of now */
-        timestamp = time(RT_NULL);
-        localtime_r(&timestamp, &now);
-
-        for (next = _container.head.next; next != &_container.head; next = next->next)
-        {
-            alarm = rt_list_entry(next, struct rt_alarm, list);
-            /* check the overtime alarm */
-            alarm_wakeup(alarm, &now);
-        }
-
-        timestamp = time(RT_NULL);
-        localtime_r(&timestamp, &now);
-        sec_now = alarm_mkdaysec(&now);
-
-        for (next = _container.head.next; next != &_container.head; next = next->next)
-        {
-            alarm = rt_list_entry(next, struct rt_alarm, list);
-            /* calculate seconds from 00:00:00 */
-            sec_alarm = alarm_mkdaysec(&alarm->wktime);
-
-            if ((alarm->flag & RT_ALARM_STATE_START) && (alarm != _container.current))
-            {
-                sec_tmp = sec_alarm - sec_now;
-                if (sec_tmp > 0)
-                {
-                    /* find alarm after now(now to 23:59:59) and the most recent */
-                    if (sec_tmp < sec_next)
-                    {
-                        sec_next = sec_tmp;
-                        alm_next = alarm;
-                    }
-                }
-                else
-                {
-                    /* find alarm before now(00:00:00 to now) and furthest from now */
-                    if (sec_tmp < sec_prev)
-                    {
-                        sec_prev = sec_tmp;
-                        alm_prev = alarm;
-                    }
-                }
-            }
-        }
-        /* enable the alarm after now first */
-        if (sec_next < 24 * 3600)
-        {
-            if (alarm_set(alm_next) == RT_EOK)
-                _container.current = alm_next;
-        }
-        else if (sec_prev < 0)
-        {
-            /* enable the alarm before now */
-            if (alarm_set(alm_prev) == RT_EOK)
-                _container.current = alm_prev;
-        }
-    }
-    rt_mutex_release(&_container.mutex);
-}
-
-static rt_uint32_t days_of_year_month(int tm_year, int tm_mon)
-{
-    rt_uint32_t ret, year;
-
-    year = tm_year + 1900;
-    if (tm_mon == 1)
-    {
-        ret = 28 + ((!(year % 4) && (year % 100)) || !(year % 400));
-    }
-    else if (((tm_mon <= 6) && (tm_mon % 2 == 0)) || ((tm_mon > 6) && (tm_mon % 2 == 1)))
-    {
-        ret = 31;
-    }
-    else
-    {
-        ret = 30;
-    }
-
-    return (ret);
-}
-
-static rt_bool_t is_valid_date(struct tm *date)
-{
-    if ((date->tm_year < 0) || (date->tm_year > RT_RTC_YEARS_MAX))
-    {
-        return (RT_FALSE);
-    }
-
-    if ((date->tm_mon < 0) || (date->tm_mon > 11))
-    {
-        return (RT_FALSE);
-    }
-
-    if ((date->tm_mday < 1) || \
-        (date->tm_mday > days_of_year_month(date->tm_year, date->tm_mon)))
-    {
-        return (RT_FALSE);
-    }
-
-    return (RT_TRUE);
-}
-
-static rt_err_t alarm_setup(rt_alarm_t alarm, struct tm *wktime)
-{
-    rt_err_t ret = RT_ERROR;
-    time_t timestamp;
-    struct tm *setup, now;
-
-    setup = &alarm->wktime;
-    *setup = *wktime;
-    timestamp = time(RT_NULL);
-    localtime_r(&timestamp, &now);
-
-    /* if these are a "don't care" value,we set them to now*/
-    if ((setup->tm_sec > 59) || (setup->tm_sec < 0))
-        setup->tm_sec = now.tm_sec;
-    if ((setup->tm_min > 59) || (setup->tm_min < 0))
-        setup->tm_min = now.tm_min;
-    if ((setup->tm_hour > 23) || (setup->tm_hour < 0))
-        setup->tm_hour = now.tm_hour;
-
-    switch (alarm->flag & 0xFF00)
-    {
-    case RT_ALARM_DAILY:
-    {
-        /* do nothing but needed */
-    }
-    break;
-    case RT_ALARM_ONESHOT:
-    {
-        /* if these are "don't care" value we set them to now */
-        if (setup->tm_year == RT_ALARM_TM_NOW)
-            setup->tm_year = now.tm_year;
-        if (setup->tm_mon == RT_ALARM_TM_NOW)
-            setup->tm_mon = now.tm_mon;
-        if (setup->tm_mday == RT_ALARM_TM_NOW)
-            setup->tm_mday = now.tm_mday;
-        /* make sure the setup is valid */
-        if (!is_valid_date(setup))
-            goto _exit;
-    }
-    break;
-    case RT_ALARM_WEEKLY:
-    {
-        /* if tm_wday is a "don't care" value we set it to now */
-        if ((setup->tm_wday < 0) || (setup->tm_wday > 6))
-            setup->tm_wday = now.tm_wday;
-    }
-    break;
-    case RT_ALARM_MONTHLY:
-    {
-        /* if tm_mday is a "don't care" value we set it to now */
-        if ((setup->tm_mday < 1) || (setup->tm_mday > 31))
-            setup->tm_mday = now.tm_mday;
-    }
-    break;
-    case RT_ALARM_YAERLY:
-    {
-        /* if tm_mon is a "don't care" value we set it to now */
-        if ((setup->tm_mon < 0) || (setup->tm_mon > 11))
-            setup->tm_mon = now.tm_mon;
-
-        if (setup->tm_mon == 1)
-        {
-            /* tm_mon is February */
-
-            /* tm_mday should be 1~29.otherwise,it's a "don't care" value */
-            if ((setup->tm_mday < 1) || (setup->tm_mday > 29))
-                setup->tm_mday = now.tm_mday;
-        }
-        else if (((setup->tm_mon <= 6) && (setup->tm_mon % 2 == 0)) || \
-                 ((setup->tm_mon > 6) && (setup->tm_mon % 2 == 1)))
-        {
-            /* Jan,Mar,May,Jul,Aug,Oct,Dec */
-
-            /* tm_mday should be 1~31.otherwise,it's a "don't care" value */
-            if ((setup->tm_mday < 1) || (setup->tm_mday > 31))
-                setup->tm_mday = now.tm_mday;
-        }
-        else
-        {
-            /* tm_mday should be 1~30.otherwise,it's a "don't care" value */
-            if ((setup->tm_mday < 1) || (setup->tm_mday > 30))
-                setup->tm_mday = now.tm_mday;
-        }
-    }
-    break;
-    default:
-    {
-        goto _exit;
-    }
-    }
-    
-    if ((setup->tm_hour == 23) && (setup->tm_min == 59) && (setup->tm_sec == 59))
-    {
-        /*
-           for insurance purposes, we will generate an alarm
-           signal two seconds ahead of.
-        */
-        setup->tm_sec = 60 - RT_ALARM_DELAY;
-    }
-    /* set initialized state */
-    alarm->flag |= RT_ALARM_STATE_INITED;
-    ret = RT_EOK;
-   
-_exit:
-
-    return (ret);
-}
-
-/** \brief send a rtc alarm event
- *
- * \param dev pointer to RTC device(currently unused,you can ignore it)
- * \param event RTC event(currently unused) 
- * \return none
- */
-void rt_alarm_update(rt_device_t dev, rt_uint32_t event)
-{
-    rt_event_send(&_container.event, 1);
-}
-
-/** \brief modify the alarm setup
- *
- * \param alarm pointer to alarm
- * \param cmd control command
- * \param arg argument
- */
-rt_err_t rt_alarm_control(rt_alarm_t alarm, rt_uint8_t cmd, void *arg)
-{
-    rt_err_t ret = RT_ERROR;
-
-    RT_ASSERT(alarm != RT_NULL);
-    
-    rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER);
-    switch (cmd)
-    {
-    case RT_ALARM_MODIFY:
-    {
-        struct rt_alarm_setup *setup;
-        
-        RT_ASSERT(arg != RT_NULL); 
-        setup = arg;
-        rt_alarm_stop(alarm);
-        alarm->flag = setup->flag & 0xFF00;
-        alarm->wktime = setup->wktime;
-        ret = alarm_setup(alarm, &alarm->wktime);  
-    }
-    break;  
-    }
-
-    rt_mutex_release(&_container.mutex); 
-
-    return (ret);
-}
-
-/** \brief start a alarm
- *
- * \param alarm pointer to alarm
- * \return RT_EOK
- */
-rt_err_t rt_alarm_start(rt_alarm_t alarm)
-{
-    rt_int32_t sec_now, sec_old, sec_new;
-    rt_err_t ret = RT_ERROR;
-    time_t timestamp;
-    struct tm now;
-    
-    if (alarm == RT_NULL)
-        return (ret);
-    rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER);
-    if (!(alarm->flag & RT_ALARM_STATE_INITED))
-    {
-        if (alarm_setup(alarm, &alarm->wktime) != RT_EOK)
-            goto _exit;
-    }   
-    if ((alarm->flag & 0x01) == RT_ALARM_STATE_STOP)
-    {
-        timestamp = time(RT_NULL);
-        localtime_r(&timestamp, &now);
-            
-        alarm->flag |= RT_ALARM_STATE_START;
-        /* set alarm */
-        if (_container.current == RT_NULL)
-        {
-            ret = alarm_set(alarm);
-        }
-        else
-        {
-            sec_now = alarm_mkdaysec(&now);
-            sec_old = alarm_mkdaysec(&_container.current->wktime);
-            sec_new = alarm_mkdaysec(&alarm->wktime);
-
-            if ((sec_new < sec_old) && (sec_new > sec_now))
-            {
-                ret = alarm_set(alarm);
-            }
-            else if ((sec_new > sec_now) && (sec_old < sec_now))
-            {
-                ret = alarm_set(alarm);
-            }
-            else if ((sec_new < sec_old) && (sec_old < sec_now))
-            {
-                ret = alarm_set(alarm);
-            }
-            else
-            {
-                ret = RT_EOK;
-                goto _exit;
-            }
-        }
-
-        if (ret == RT_EOK)
-        {
-            _container.current = alarm;
-        }
-    }
-
-_exit:
-    rt_mutex_release(&_container.mutex);
-
-    return (ret);
-}
-
-/** \brief stop a alarm
- *
- * \param alarm pointer to alarm
- * \return RT_EOK
- */
-rt_err_t rt_alarm_stop(rt_alarm_t alarm)
-{
-    rt_err_t ret = RT_ERROR;
-    
-    if (alarm == RT_NULL)
-        return (ret);
-    rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER);
-    if (!(alarm->flag & RT_ALARM_STATE_START))
-        goto _exit;
-    /* stop alarm */
-    alarm->flag &= ~RT_ALARM_STATE_START;
-    
-    if (_container.current == alarm)
-    {
-        ret = alarm_set(alarm);
-        _container.current = RT_NULL;
-    }    
-
-    if (ret == RT_EOK)
-        alarm_update(0);
-
-_exit:
-    rt_mutex_release(&_container.mutex);
-
-    return (ret);
-}
-
-/** \brief delete a alarm
- *
- * \param alarm pointer to alarm
- * \return RT_EOK
- */
-rt_err_t rt_alarm_delete(rt_alarm_t alarm)
-{
-    rt_err_t ret = RT_ERROR;
-    
-    if (alarm == RT_NULL)
-        return (ret);    
-    rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER);    
-    /* stop the alarm */
-    alarm->flag &= ~RT_ALARM_STATE_START;
-    if (_container.current == alarm)
-    {
-        ret = alarm_set(alarm);
-        _container.current = RT_NULL;
-        /* set new alarm if necessary */
-        alarm_update(0);        
-    }
-    rt_list_remove(&alarm->list);
-    rt_free(alarm);
-
-    rt_mutex_release(&_container.mutex);
-    
-    return (ret);
-}
-
-/** \brief create a alarm
- *
- * \param flag set alarm mode e.g: RT_ALARM_DAILY
- * \param setup pointer to setup infomation
- */
-rt_alarm_t rt_alarm_create(rt_alarm_callback_t callback, struct rt_alarm_setup *setup)
-{
-    struct rt_alarm *alarm;
-    
-    if (setup == RT_NULL)
-        return (RT_NULL);
-    alarm = rt_malloc(sizeof(struct rt_alarm));
-    if (alarm == RT_NULL)
-        return (RT_NULL);
-    rt_list_init(&alarm->list);
-    
-    alarm->wktime = setup->wktime;
-    alarm->flag = setup->flag & 0xFF00;
-    alarm->callback = callback;
-    rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER);    
-    rt_list_insert_after(&_container.head, &alarm->list);
-    rt_mutex_release(&_container.mutex);
-
-    return (alarm);
-}
-
-/** \brief rtc alarm service thread entry
- *
- */
-static void rt_alarmsvc_thread_init(void *param)
-{
-    rt_uint32_t recv;
-
-    rt_list_init(&_container.head);
-    rt_event_init(&_container.event, "alarmsvc", RT_IPC_FLAG_FIFO);
-    rt_mutex_init(&_container.mutex, "alarmsvc", RT_IPC_FLAG_FIFO);
-    _container.current = RT_NULL;
-
-    while (1)
-    {
-        if (rt_event_recv(&_container.event, 0xFFFF,
-                          RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
-                          RT_WAITING_FOREVER, &recv) == RT_EOK)
-        {
-            alarm_update(recv);           
-        }
-    }
-}
-
-
-/** \brief initialize alarm service system
- *
- * \param none
- * \return none
- */
-void rt_alarm_system_init(void)
-{
-    rt_thread_t tid;
-
-    tid = rt_thread_create("alarmsvc",
-                           rt_alarmsvc_thread_init, RT_NULL,
-                           512, 8, 1);
-    if (tid != RT_NULL)
-        rt_thread_startup(tid);
-}
-#endif
+/*
+ * File      : alarm.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2012, 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-10-27     heyuanjie87       first version.
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define RT_RTC_YEARS_MAX         137
+#define RT_ALARM_DELAY             2
+#define RT_ALARM_STATE_INITED   0x02
+#define RT_ALARM_STATE_START    0x01
+#define RT_ALARM_STATE_STOP     0x00
+
+#if(defined(RT_USING_RTC) && defined(RT_USING_ALARM))
+static struct rt_alarm_container _container;
+
+rt_inline rt_uint32_t alarm_mkdaysec(struct tm *time)
+{
+    rt_uint32_t sec;
+
+    sec = time->tm_sec;
+    sec += time->tm_min * 60;
+    sec += time->tm_hour * 3600;
+
+    return (sec);
+}
+
+static rt_err_t alarm_set(struct rt_alarm *alarm)
+{
+    rt_device_t device;
+    struct rt_rtc_wkalarm wkalarm;
+    rt_err_t ret;
+
+    device = rt_device_find("rtc");
+    if (device == RT_NULL)
+    {
+        return (RT_ERROR);
+    }
+    if (alarm->flag & RT_ALARM_STATE_START)
+        wkalarm.enable = RT_TRUE;
+    else
+        wkalarm.enable = RT_FALSE;
+
+    wkalarm.tm_sec = alarm->wktime.tm_sec;
+    wkalarm.tm_min = alarm->wktime.tm_min;
+    wkalarm.tm_hour = alarm->wktime.tm_hour;
+
+    ret = rt_device_control(device, RT_DEVICE_CTRL_RTC_SET_ALARM, &wkalarm);
+    if ((ret == RT_EOK) && wkalarm.enable)
+    {
+        ret = rt_device_control(device, RT_DEVICE_CTRL_RTC_GET_ALARM, &wkalarm);
+        if (ret == RT_EOK)
+        {
+            /* 
+              some RTC device like RX8025,it's alarms precision is 1 minute.
+              in this case,low level RTC driver should set wkalarm->tm_sec to 0.
+            */
+            alarm->wktime.tm_sec = wkalarm.tm_sec;
+            alarm->wktime.tm_min = wkalarm.tm_min;
+            alarm->wktime.tm_hour = wkalarm.tm_hour;
+        }
+    }
+
+    return (ret);
+}
+
+static void alarm_wakeup(struct rt_alarm *alarm, struct tm *now)
+{
+    rt_uint32_t sec_alarm, sec_now;
+    rt_bool_t wakeup = RT_FALSE;
+    time_t timestamp;
+    
+    sec_alarm = alarm_mkdaysec(&alarm->wktime);
+    sec_now = alarm_mkdaysec(now);
+
+    if (alarm->flag & RT_ALARM_STATE_START)
+    {
+        switch (alarm->flag & 0xFF00)
+        {
+        case RT_ALARM_ONESHOT:
+        {
+            sec_alarm = mktime(&alarm->wktime);
+            sec_now = mktime(now);
+            if (((sec_now - sec_alarm) <= RT_ALARM_DELAY) && (sec_now >= sec_alarm))
+            {
+                /* stop alarm */
+                alarm->flag &= ~RT_ALARM_STATE_START;
+                alarm_set(alarm);
+                wakeup = RT_TRUE;
+            }  
+        }
+        break;
+        case RT_ALARM_DAILY:
+        {
+            if (((sec_now - sec_alarm) <= RT_ALARM_DELAY) && (sec_now >= sec_alarm))
+                wakeup = RT_TRUE;
+        }
+        break;
+        case RT_ALARM_WEEKLY:
+        {
+            /* alarm at wday */
+            sec_alarm += alarm->wktime.tm_wday * 24 * 3600;
+            sec_now += now->tm_wday * 24 * 3600;
+
+            if (((sec_now - sec_alarm) <= RT_ALARM_DELAY) && (sec_now >= sec_alarm))
+                wakeup = RT_TRUE;
+        }
+        break;
+        case RT_ALARM_MONTHLY:
+        {
+            /* monthly someday generate alarm signals */
+            if (alarm->wktime.tm_mday == now->tm_mday)
+            {
+                if ((sec_now - sec_alarm) <= RT_ALARM_DELAY)
+                    wakeup = RT_TRUE;
+            }
+        }
+        break;
+        case RT_ALARM_YAERLY:
+        {
+            if ((alarm->wktime.tm_mday == now->tm_mday) && \
+                (alarm->wktime.tm_mon == now->tm_mon))
+            {
+                  if ((sec_now - sec_alarm) <= RT_ALARM_DELAY)
+                    wakeup = RT_TRUE;           
+            }
+        }
+        break;
+        }
+
+        if ((wakeup == RT_TRUE) && (alarm->callback != RT_NULL))
+        {
+            timestamp = time(RT_NULL);
+            alarm->callback(alarm, timestamp);
+        }   
+    }
+}
+
+static void alarm_update(rt_uint32_t event)
+{
+    struct rt_alarm *alm_prev = RT_NULL, *alm_next = RT_NULL;
+    struct rt_alarm *alarm;
+    rt_int32_t sec_now, sec_alarm, sec_tmp;
+    rt_int32_t sec_next = 24 * 3600, sec_prev = 0;
+    time_t timestamp;
+    struct tm now;
+    rt_list_t *next;
+
+    rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER);
+    if (!rt_list_isempty(&_container.head))
+    {
+        /* get time of now */
+        timestamp = time(RT_NULL);
+        localtime_r(&timestamp, &now);
+
+        for (next = _container.head.next; next != &_container.head; next = next->next)
+        {
+            alarm = rt_list_entry(next, struct rt_alarm, list);
+            /* check the overtime alarm */
+            alarm_wakeup(alarm, &now);
+        }
+
+        timestamp = time(RT_NULL);
+        localtime_r(&timestamp, &now);
+        sec_now = alarm_mkdaysec(&now);
+
+        for (next = _container.head.next; next != &_container.head; next = next->next)
+        {
+            alarm = rt_list_entry(next, struct rt_alarm, list);
+            /* calculate seconds from 00:00:00 */
+            sec_alarm = alarm_mkdaysec(&alarm->wktime);
+
+            if ((alarm->flag & RT_ALARM_STATE_START) && (alarm != _container.current))
+            {
+                sec_tmp = sec_alarm - sec_now;
+                if (sec_tmp > 0)
+                {
+                    /* find alarm after now(now to 23:59:59) and the most recent */
+                    if (sec_tmp < sec_next)
+                    {
+                        sec_next = sec_tmp;
+                        alm_next = alarm;
+                    }
+                }
+                else
+                {
+                    /* find alarm before now(00:00:00 to now) and furthest from now */
+                    if (sec_tmp < sec_prev)
+                    {
+                        sec_prev = sec_tmp;
+                        alm_prev = alarm;
+                    }
+                }
+            }
+        }
+        /* enable the alarm after now first */
+        if (sec_next < 24 * 3600)
+        {
+            if (alarm_set(alm_next) == RT_EOK)
+                _container.current = alm_next;
+        }
+        else if (sec_prev < 0)
+        {
+            /* enable the alarm before now */
+            if (alarm_set(alm_prev) == RT_EOK)
+                _container.current = alm_prev;
+        }
+    }
+    rt_mutex_release(&_container.mutex);
+}
+
+static rt_uint32_t days_of_year_month(int tm_year, int tm_mon)
+{
+    rt_uint32_t ret, year;
+
+    year = tm_year + 1900;
+    if (tm_mon == 1)
+    {
+        ret = 28 + ((!(year % 4) && (year % 100)) || !(year % 400));
+    }
+    else if (((tm_mon <= 6) && (tm_mon % 2 == 0)) || ((tm_mon > 6) && (tm_mon % 2 == 1)))
+    {
+        ret = 31;
+    }
+    else
+    {
+        ret = 30;
+    }
+
+    return (ret);
+}
+
+static rt_bool_t is_valid_date(struct tm *date)
+{
+    if ((date->tm_year < 0) || (date->tm_year > RT_RTC_YEARS_MAX))
+    {
+        return (RT_FALSE);
+    }
+
+    if ((date->tm_mon < 0) || (date->tm_mon > 11))
+    {
+        return (RT_FALSE);
+    }
+
+    if ((date->tm_mday < 1) || \
+        (date->tm_mday > days_of_year_month(date->tm_year, date->tm_mon)))
+    {
+        return (RT_FALSE);
+    }
+
+    return (RT_TRUE);
+}
+
+static rt_err_t alarm_setup(rt_alarm_t alarm, struct tm *wktime)
+{
+    rt_err_t ret = RT_ERROR;
+    time_t timestamp;
+    struct tm *setup, now;
+
+    setup = &alarm->wktime;
+    *setup = *wktime;
+    timestamp = time(RT_NULL);
+    localtime_r(&timestamp, &now);
+
+    /* if these are a "don't care" value,we set them to now*/
+    if ((setup->tm_sec > 59) || (setup->tm_sec < 0))
+        setup->tm_sec = now.tm_sec;
+    if ((setup->tm_min > 59) || (setup->tm_min < 0))
+        setup->tm_min = now.tm_min;
+    if ((setup->tm_hour > 23) || (setup->tm_hour < 0))
+        setup->tm_hour = now.tm_hour;
+
+    switch (alarm->flag & 0xFF00)
+    {
+    case RT_ALARM_DAILY:
+    {
+        /* do nothing but needed */
+    }
+    break;
+    case RT_ALARM_ONESHOT:
+    {
+        /* if these are "don't care" value we set them to now */
+        if (setup->tm_year == RT_ALARM_TM_NOW)
+            setup->tm_year = now.tm_year;
+        if (setup->tm_mon == RT_ALARM_TM_NOW)
+            setup->tm_mon = now.tm_mon;
+        if (setup->tm_mday == RT_ALARM_TM_NOW)
+            setup->tm_mday = now.tm_mday;
+        /* make sure the setup is valid */
+        if (!is_valid_date(setup))
+            goto _exit;
+    }
+    break;
+    case RT_ALARM_WEEKLY:
+    {
+        /* if tm_wday is a "don't care" value we set it to now */
+        if ((setup->tm_wday < 0) || (setup->tm_wday > 6))
+            setup->tm_wday = now.tm_wday;
+    }
+    break;
+    case RT_ALARM_MONTHLY:
+    {
+        /* if tm_mday is a "don't care" value we set it to now */
+        if ((setup->tm_mday < 1) || (setup->tm_mday > 31))
+            setup->tm_mday = now.tm_mday;
+    }
+    break;
+    case RT_ALARM_YAERLY:
+    {
+        /* if tm_mon is a "don't care" value we set it to now */
+        if ((setup->tm_mon < 0) || (setup->tm_mon > 11))
+            setup->tm_mon = now.tm_mon;
+
+        if (setup->tm_mon == 1)
+        {
+            /* tm_mon is February */
+
+            /* tm_mday should be 1~29.otherwise,it's a "don't care" value */
+            if ((setup->tm_mday < 1) || (setup->tm_mday > 29))
+                setup->tm_mday = now.tm_mday;
+        }
+        else if (((setup->tm_mon <= 6) && (setup->tm_mon % 2 == 0)) || \
+                 ((setup->tm_mon > 6) && (setup->tm_mon % 2 == 1)))
+        {
+            /* Jan,Mar,May,Jul,Aug,Oct,Dec */
+
+            /* tm_mday should be 1~31.otherwise,it's a "don't care" value */
+            if ((setup->tm_mday < 1) || (setup->tm_mday > 31))
+                setup->tm_mday = now.tm_mday;
+        }
+        else
+        {
+            /* tm_mday should be 1~30.otherwise,it's a "don't care" value */
+            if ((setup->tm_mday < 1) || (setup->tm_mday > 30))
+                setup->tm_mday = now.tm_mday;
+        }
+    }
+    break;
+    default:
+    {
+        goto _exit;
+    }
+    }
+    
+    if ((setup->tm_hour == 23) && (setup->tm_min == 59) && (setup->tm_sec == 59))
+    {
+        /*
+           for insurance purposes, we will generate an alarm
+           signal two seconds ahead of.
+        */
+        setup->tm_sec = 60 - RT_ALARM_DELAY;
+    }
+    /* set initialized state */
+    alarm->flag |= RT_ALARM_STATE_INITED;
+    ret = RT_EOK;
+   
+_exit:
+
+    return (ret);
+}
+
+/** \brief send a rtc alarm event
+ *
+ * \param dev pointer to RTC device(currently unused,you can ignore it)
+ * \param event RTC event(currently unused) 
+ * \return none
+ */
+void rt_alarm_update(rt_device_t dev, rt_uint32_t event)
+{
+    rt_event_send(&_container.event, 1);
+}
+
+/** \brief modify the alarm setup
+ *
+ * \param alarm pointer to alarm
+ * \param cmd control command
+ * \param arg argument
+ */
+rt_err_t rt_alarm_control(rt_alarm_t alarm, rt_uint8_t cmd, void *arg)
+{
+    rt_err_t ret = RT_ERROR;
+
+    RT_ASSERT(alarm != RT_NULL);
+    
+    rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER);
+    switch (cmd)
+    {
+    case RT_ALARM_MODIFY:
+    {
+        struct rt_alarm_setup *setup;
+        
+        RT_ASSERT(arg != RT_NULL); 
+        setup = arg;
+        rt_alarm_stop(alarm);
+        alarm->flag = setup->flag & 0xFF00;
+        alarm->wktime = setup->wktime;
+        ret = alarm_setup(alarm, &alarm->wktime);  
+    }
+    break;  
+    }
+
+    rt_mutex_release(&_container.mutex); 
+
+    return (ret);
+}
+
+/** \brief start a alarm
+ *
+ * \param alarm pointer to alarm
+ * \return RT_EOK
+ */
+rt_err_t rt_alarm_start(rt_alarm_t alarm)
+{
+    rt_int32_t sec_now, sec_old, sec_new;
+    rt_err_t ret = RT_ERROR;
+    time_t timestamp;
+    struct tm now;
+    
+    if (alarm == RT_NULL)
+        return (ret);
+    rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER);
+    if (!(alarm->flag & RT_ALARM_STATE_INITED))
+    {
+        if (alarm_setup(alarm, &alarm->wktime) != RT_EOK)
+            goto _exit;
+    }   
+    if ((alarm->flag & 0x01) == RT_ALARM_STATE_STOP)
+    {
+        timestamp = time(RT_NULL);
+        localtime_r(&timestamp, &now);
+            
+        alarm->flag |= RT_ALARM_STATE_START;
+        /* set alarm */
+        if (_container.current == RT_NULL)
+        {
+            ret = alarm_set(alarm);
+        }
+        else
+        {
+            sec_now = alarm_mkdaysec(&now);
+            sec_old = alarm_mkdaysec(&_container.current->wktime);
+            sec_new = alarm_mkdaysec(&alarm->wktime);
+
+            if ((sec_new < sec_old) && (sec_new > sec_now))
+            {
+                ret = alarm_set(alarm);
+            }
+            else if ((sec_new > sec_now) && (sec_old < sec_now))
+            {
+                ret = alarm_set(alarm);
+            }
+            else if ((sec_new < sec_old) && (sec_old < sec_now))
+            {
+                ret = alarm_set(alarm);
+            }
+            else
+            {
+                ret = RT_EOK;
+                goto _exit;
+            }
+        }
+
+        if (ret == RT_EOK)
+        {
+            _container.current = alarm;
+        }
+    }
+
+_exit:
+    rt_mutex_release(&_container.mutex);
+
+    return (ret);
+}
+
+/** \brief stop a alarm
+ *
+ * \param alarm pointer to alarm
+ * \return RT_EOK
+ */
+rt_err_t rt_alarm_stop(rt_alarm_t alarm)
+{
+    rt_err_t ret = RT_ERROR;
+    
+    if (alarm == RT_NULL)
+        return (ret);
+    rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER);
+    if (!(alarm->flag & RT_ALARM_STATE_START))
+        goto _exit;
+    /* stop alarm */
+    alarm->flag &= ~RT_ALARM_STATE_START;
+    
+    if (_container.current == alarm)
+    {
+        ret = alarm_set(alarm);
+        _container.current = RT_NULL;
+    }    
+
+    if (ret == RT_EOK)
+        alarm_update(0);
+
+_exit:
+    rt_mutex_release(&_container.mutex);
+
+    return (ret);
+}
+
+/** \brief delete a alarm
+ *
+ * \param alarm pointer to alarm
+ * \return RT_EOK
+ */
+rt_err_t rt_alarm_delete(rt_alarm_t alarm)
+{
+    rt_err_t ret = RT_ERROR;
+    
+    if (alarm == RT_NULL)
+        return (ret);    
+    rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER);    
+    /* stop the alarm */
+    alarm->flag &= ~RT_ALARM_STATE_START;
+    if (_container.current == alarm)
+    {
+        ret = alarm_set(alarm);
+        _container.current = RT_NULL;
+        /* set new alarm if necessary */
+        alarm_update(0);        
+    }
+    rt_list_remove(&alarm->list);
+    rt_free(alarm);
+
+    rt_mutex_release(&_container.mutex);
+    
+    return (ret);
+}
+
+/** \brief create a alarm
+ *
+ * \param flag set alarm mode e.g: RT_ALARM_DAILY
+ * \param setup pointer to setup infomation
+ */
+rt_alarm_t rt_alarm_create(rt_alarm_callback_t callback, struct rt_alarm_setup *setup)
+{
+    struct rt_alarm *alarm;
+    
+    if (setup == RT_NULL)
+        return (RT_NULL);
+    alarm = rt_malloc(sizeof(struct rt_alarm));
+    if (alarm == RT_NULL)
+        return (RT_NULL);
+    rt_list_init(&alarm->list);
+    
+    alarm->wktime = setup->wktime;
+    alarm->flag = setup->flag & 0xFF00;
+    alarm->callback = callback;
+    rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER);    
+    rt_list_insert_after(&_container.head, &alarm->list);
+    rt_mutex_release(&_container.mutex);
+
+    return (alarm);
+}
+
+/** \brief rtc alarm service thread entry
+ *
+ */
+static void rt_alarmsvc_thread_init(void *param)
+{
+    rt_uint32_t recv;
+
+    rt_list_init(&_container.head);
+    rt_event_init(&_container.event, "alarmsvc", RT_IPC_FLAG_FIFO);
+    rt_mutex_init(&_container.mutex, "alarmsvc", RT_IPC_FLAG_FIFO);
+    _container.current = RT_NULL;
+
+    while (1)
+    {
+        if (rt_event_recv(&_container.event, 0xFFFF,
+                          RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
+                          RT_WAITING_FOREVER, &recv) == RT_EOK)
+        {
+            alarm_update(recv);           
+        }
+    }
+}
+
+
+/** \brief initialize alarm service system
+ *
+ * \param none
+ * \return none
+ */
+void rt_alarm_system_init(void)
+{
+    rt_thread_t tid;
+
+    tid = rt_thread_create("alarmsvc",
+                           rt_alarmsvc_thread_init, RT_NULL,
+                           512, 8, 1);
+    if (tid != RT_NULL)
+        rt_thread_startup(tid);
+}
+#endif

+ 1 - 0
components/drivers/src/completion.c

@@ -89,6 +89,7 @@ rt_err_t rt_completion_wait(struct rt_completion *completion,
 
 __exit:
     rt_hw_interrupt_enable(level);
+
     return result;
 }
 

+ 205 - 205
components/drivers/src/pipe.c

@@ -1,205 +1,205 @@
-/*
- * File      : pipe.c
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2012, 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-09-30     Bernard      first version.
- */
-
-#include <rthw.h>
-#include <rtthread.h>
-#include <rtdevice.h>
-
-static rt_size_t rt_pipe_read(rt_device_t dev,
-                              rt_off_t    pos,
-                              void       *buffer,
-                              rt_size_t   size)
-{
-    rt_uint32_t level;
-    rt_thread_t thread;
-    struct rt_pipe_device *pipe;
-    rt_size_t read_nbytes;
-
-    pipe = PIPE_DEVICE(dev);
-    RT_ASSERT(pipe != RT_NULL);
-
-    thread = rt_thread_self();
-
-    /* current context checking */
-    RT_DEBUG_NOT_IN_INTERRUPT;
-
-    do 
-    {
-        level = rt_hw_interrupt_disable();
-        read_nbytes = rt_ringbuffer_get(&(pipe->ringbuffer), buffer, size);
-        if (read_nbytes == 0)
-        {
-            rt_thread_suspend(thread);
-            /* waiting on suspended read list */
-            rt_list_insert_before(&(pipe->suspended_read_list), &(thread->tlist));
-            rt_hw_interrupt_enable(level);
-
-            rt_schedule();
-        }
-        else
-        {
-            if (!rt_list_isempty(&pipe->suspended_write_list))
-            {
-                /* get suspended thread */
-                thread = rt_list_entry(pipe->suspended_write_list.next, 
-                    struct rt_thread, tlist);
-
-                /* resume the write thread */
-                rt_thread_resume(thread);
-                rt_hw_interrupt_enable(level);
-
-                rt_schedule();
-            }
-            else
-            {
-                rt_hw_interrupt_enable(level);
-            }
-            break;
-        }
-    } while (read_nbytes == 0);
-
-    return read_nbytes;
-}
-
-struct rt_pipe_device *_pipe = RT_NULL;
-static rt_size_t rt_pipe_write(rt_device_t dev,
-                               rt_off_t    pos,
-                               const void *buffer,
-                               rt_size_t   size)
-{
-    rt_uint32_t level;
-    rt_thread_t thread;
-    struct rt_pipe_device *pipe;
-    rt_size_t write_nbytes;
-
-    pipe = PIPE_DEVICE(dev);
-    RT_ASSERT(pipe != RT_NULL);
-    if (_pipe == RT_NULL)
-        _pipe = pipe;
-
-    thread = rt_thread_self();
-
-    /* current context checking */
-    RT_DEBUG_NOT_IN_INTERRUPT;
-
-    do 
-    {
-        level = rt_hw_interrupt_disable();
-        write_nbytes = rt_ringbuffer_put(&(pipe->ringbuffer), buffer, size);
-        if (write_nbytes == 0)
-        {
-            /* pipe full, waiting on suspended write list */
-            rt_thread_suspend(thread);
-            /* waiting on suspended read list */
-            rt_list_insert_before(&(pipe->suspended_write_list), &(thread->tlist));
-            rt_hw_interrupt_enable(level);
-
-            rt_schedule();
-        }
-        else
-        {
-            if (!rt_list_isempty(&pipe->suspended_read_list))
-            {
-                /* get suspended thread */
-                thread = rt_list_entry(pipe->suspended_read_list.next,
-                                       struct rt_thread, tlist);
-
-                /* resume the read thread */
-                rt_thread_resume(thread);
-                rt_hw_interrupt_enable(level);
-
-                rt_schedule();
-            }
-            else
-            {
-                rt_hw_interrupt_enable(level);
-            }
-            break;
-        }
-    }while (write_nbytes == 0);
-
-    return write_nbytes;
-}
-
-static rt_err_t rt_pipe_control(rt_device_t dev, rt_uint8_t cmd, void *args)
-{
-    return RT_EOK;
-}
-
-rt_err_t rt_pipe_create(const char *name, rt_size_t size)
-{
-    rt_err_t result = RT_EOK;
-    rt_uint8_t *rb_memptr = RT_NULL;
-    struct rt_pipe_device *pipe = RT_NULL;
-
-    /* get aligned size */
-    size = RT_ALIGN(size, RT_ALIGN_SIZE);
-    pipe = (struct rt_pipe_device *)rt_calloc(1, sizeof(struct rt_pipe_device));
-    if (pipe != RT_NULL)
-    {
-        /* create ring buffer of pipe */
-        rb_memptr = rt_malloc(size);
-        if (rb_memptr == RT_NULL)
-        {
-            result = -RT_ENOMEM;
-            goto __exit;
-        }
-        /* initialize suspended list */
-        rt_list_init(&pipe->suspended_read_list);
-        rt_list_init(&pipe->suspended_write_list);
-        
-        /* initialize ring buffer */
-        rt_ringbuffer_init(&pipe->ringbuffer, rb_memptr, size);
-
-        /* create device */
-        pipe->parent.type    = RT_Device_Class_Char;
-        pipe->parent.init    = RT_NULL;
-        pipe->parent.open    = RT_NULL;
-        pipe->parent.close   = RT_NULL;
-        pipe->parent.read    = rt_pipe_read;
-        pipe->parent.write   = rt_pipe_write;
-        pipe->parent.control = rt_pipe_control;
-
-        return rt_device_register(&(pipe->parent), name, RT_DEVICE_FLAG_RDWR);
-    }
-    else
-    {
-        result = -RT_ENOMEM;
-    }
-
-__exit:
-    if (pipe != RT_NULL)
-        rt_free(pipe);
-    if (rb_memptr != RT_NULL)
-        rt_free(rb_memptr);
-
-    return result;
-}
-RTM_EXPORT(rt_pipe_create);
-
-void rt_pipe_destroy(struct rt_pipe_device *pipe)
-{
-    if (pipe == RT_NULL)
-        return;
-
-    /* un-register pipe device */
-    rt_device_unregister(&(pipe->parent));
-
-    /* release memory */
-    rt_free(pipe->ringbuffer.buffer_ptr);
-    rt_free(pipe);
-
-    return;
-}
-RTM_EXPORT(rt_pipe_destroy);
+/*
+ * File      : pipe.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2012, 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-09-30     Bernard      first version.
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+static rt_size_t rt_pipe_read(rt_device_t dev,
+                              rt_off_t    pos,
+                              void       *buffer,
+                              rt_size_t   size)
+{
+    rt_uint32_t level;
+    rt_thread_t thread;
+    struct rt_pipe_device *pipe;
+    rt_size_t read_nbytes;
+
+    pipe = PIPE_DEVICE(dev);
+    RT_ASSERT(pipe != RT_NULL);
+
+    thread = rt_thread_self();
+
+    /* current context checking */
+    RT_DEBUG_NOT_IN_INTERRUPT;
+
+    do 
+    {
+        level = rt_hw_interrupt_disable();
+        read_nbytes = rt_ringbuffer_get(&(pipe->ringbuffer), buffer, size);
+        if (read_nbytes == 0)
+        {
+            rt_thread_suspend(thread);
+            /* waiting on suspended read list */
+            rt_list_insert_before(&(pipe->suspended_read_list), &(thread->tlist));
+            rt_hw_interrupt_enable(level);
+
+            rt_schedule();
+        }
+        else
+        {
+            if (!rt_list_isempty(&pipe->suspended_write_list))
+            {
+                /* get suspended thread */
+                thread = rt_list_entry(pipe->suspended_write_list.next, 
+                    struct rt_thread, tlist);
+
+                /* resume the write thread */
+                rt_thread_resume(thread);
+                rt_hw_interrupt_enable(level);
+
+                rt_schedule();
+            }
+            else
+            {
+                rt_hw_interrupt_enable(level);
+            }
+            break;
+        }
+    } while (read_nbytes == 0);
+
+    return read_nbytes;
+}
+
+struct rt_pipe_device *_pipe = RT_NULL;
+static rt_size_t rt_pipe_write(rt_device_t dev,
+                               rt_off_t    pos,
+                               const void *buffer,
+                               rt_size_t   size)
+{
+    rt_uint32_t level;
+    rt_thread_t thread;
+    struct rt_pipe_device *pipe;
+    rt_size_t write_nbytes;
+
+    pipe = PIPE_DEVICE(dev);
+    RT_ASSERT(pipe != RT_NULL);
+    if (_pipe == RT_NULL)
+        _pipe = pipe;
+
+    thread = rt_thread_self();
+
+    /* current context checking */
+    RT_DEBUG_NOT_IN_INTERRUPT;
+
+    do
+    {
+        level = rt_hw_interrupt_disable();
+        write_nbytes = rt_ringbuffer_put(&(pipe->ringbuffer), buffer, size);
+        if (write_nbytes == 0)
+        {
+            /* pipe full, waiting on suspended write list */
+            rt_thread_suspend(thread);
+            /* waiting on suspended read list */
+            rt_list_insert_before(&(pipe->suspended_write_list), &(thread->tlist));
+            rt_hw_interrupt_enable(level);
+
+            rt_schedule();
+        }
+        else
+        {
+            if (!rt_list_isempty(&pipe->suspended_read_list))
+            {
+                /* get suspended thread */
+                thread = rt_list_entry(pipe->suspended_read_list.next,
+                                       struct rt_thread, tlist);
+
+                /* resume the read thread */
+                rt_thread_resume(thread);
+                rt_hw_interrupt_enable(level);
+
+                rt_schedule();
+            }
+            else
+            {
+                rt_hw_interrupt_enable(level);
+            }
+            break;
+        }
+    }while (write_nbytes == 0);
+
+    return write_nbytes;
+}
+
+static rt_err_t rt_pipe_control(rt_device_t dev, rt_uint8_t cmd, void *args)
+{
+    return RT_EOK;
+}
+
+rt_err_t rt_pipe_create(const char *name, rt_size_t size)
+{
+    rt_err_t result = RT_EOK;
+    rt_uint8_t *rb_memptr = RT_NULL;
+    struct rt_pipe_device *pipe = RT_NULL;
+
+    /* get aligned size */
+    size = RT_ALIGN(size, RT_ALIGN_SIZE);
+    pipe = (struct rt_pipe_device *)rt_calloc(1, sizeof(struct rt_pipe_device));
+    if (pipe != RT_NULL)
+    {
+        /* create ring buffer of pipe */
+        rb_memptr = rt_malloc(size);
+        if (rb_memptr == RT_NULL)
+        {
+            result = -RT_ENOMEM;
+            goto __exit;
+        }
+        /* initialize suspended list */
+        rt_list_init(&pipe->suspended_read_list);
+        rt_list_init(&pipe->suspended_write_list);
+        
+        /* initialize ring buffer */
+        rt_ringbuffer_init(&pipe->ringbuffer, rb_memptr, size);
+
+        /* create device */
+        pipe->parent.type    = RT_Device_Class_Char;
+        pipe->parent.init    = RT_NULL;
+        pipe->parent.open    = RT_NULL;
+        pipe->parent.close   = RT_NULL;
+        pipe->parent.read    = rt_pipe_read;
+        pipe->parent.write   = rt_pipe_write;
+        pipe->parent.control = rt_pipe_control;
+
+        return rt_device_register(&(pipe->parent), name, RT_DEVICE_FLAG_RDWR);
+    }
+    else
+    {
+        result = -RT_ENOMEM;
+    }
+
+__exit:
+    if (pipe != RT_NULL)
+        rt_free(pipe);
+    if (rb_memptr != RT_NULL)
+        rt_free(rb_memptr);
+
+    return result;
+}
+RTM_EXPORT(rt_pipe_create);
+
+void rt_pipe_destroy(struct rt_pipe_device *pipe)
+{
+    if (pipe == RT_NULL)
+        return;
+
+    /* un-register pipe device */
+    rt_device_unregister(&(pipe->parent));
+
+    /* release memory */
+    rt_free(pipe->ringbuffer.buffer_ptr);
+    rt_free(pipe);
+
+    return;
+}
+RTM_EXPORT(rt_pipe_destroy);

+ 161 - 155
components/drivers/src/ringbuffer.c

@@ -1,155 +1,161 @@
-/*
- * File      : ringbuffer.c
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2012, 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-09-30     Bernard      first version.
- */
-
-#include <rtthread.h>
-#include <rtdevice.h>
-#include <string.h>
-
-void rt_ringbuffer_init(struct rt_ringbuffer *rb,
-                        rt_uint8_t           *pool,
-                        rt_uint16_t           size)
-{
-    RT_ASSERT(rb != RT_NULL);
-
-    /* initialize read and write index */
-    rb->read_index = rb->write_index = 0;
-
-    /* set buffer pool and size */
-    rb->buffer_ptr = pool;
-    rb->buffer_size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE);
-}
-RTM_EXPORT(rt_ringbuffer_init);
-
-rt_size_t rt_ringbuffer_put(struct rt_ringbuffer *rb,
-                            const rt_uint8_t     *ptr,
-                            rt_uint16_t           length)
-{
-    rt_uint16_t size;
-    rt_uint16_t mask;
-    rt_uint16_t write_position;
-    
-    RT_ASSERT(rb != RT_NULL);
-
-    mask = rb->buffer_size - 1;
-    /* whether has enough space */
-    size = rb->buffer_size - (rb->write_index - rb->read_index);
-
-    /* no space */
-    if (size == 0) return 0;
-    /* drop some data */
-    if (size < length) length = size;
-
-    write_position = (rb->write_index & mask);
-    if (rb->buffer_size - write_position> length)
-    {
-        /* read_index - write_index = empty space */
-        memcpy(&rb->buffer_ptr[write_position], ptr, length);
-    }
-    else
-    {
-        memcpy(&rb->buffer_ptr[write_position], ptr,
-               rb->buffer_size - write_position);
-        memcpy(&rb->buffer_ptr[0], &ptr[rb->buffer_size - write_position],
-               length - (rb->buffer_size - write_position));
-    }
-    rb->write_index += length;
-
-    return length;
-}
-RTM_EXPORT(rt_ringbuffer_put);
-
-/**
- * put a character into ring buffer
- */
-rt_size_t rt_ringbuffer_putchar(struct rt_ringbuffer* rb, const rt_uint8_t ch)
-{
-    rt_uint16_t mask;
-
-    RT_ASSERT(rb != RT_NULL);
-    /* whether has enough space */
-    mask = rb->buffer_size - 1;
-    
-    /* whether has enough space */
-    if (rb->write_index - rb->read_index == rb->buffer_size) return 0;
-
-    /* put character */
-    rb->buffer_ptr[rb->write_index & mask] = ch;
-    rb->write_index += 1;
-
-    return 1;
-}
-RTM_EXPORT(rt_ringbuffer_putchar);
-
-/**
- *  get data from ring buffer
- */
-rt_size_t rt_ringbuffer_get(struct rt_ringbuffer *rb,
-                            rt_uint8_t           *ptr,
-                            rt_uint16_t           length)
-{
-    rt_size_t size;
-    rt_uint16_t mask;
-    rt_uint16_t read_position;
-
-    RT_ASSERT(rb != RT_NULL);
-    /* whether has enough data  */
-    mask = rb->buffer_size - 1;
-    size = rb->write_index - rb->read_index;
-
-    /* no data */
-    if (size == 0) return 0;
-    /* less data */
-    if (size < length) length = size;
-
-    read_position = rb->read_index & mask;
-    if (rb->buffer_size - read_position >= length)
-    {
-        /* copy all of data */
-        memcpy(ptr, &rb->buffer_ptr[read_position], length);
-    }
-    else
-    {
-        /* copy first and second */
-        memcpy(ptr, &rb->buffer_ptr[read_position],
-               rb->buffer_size - read_position);
-        memcpy(&ptr[rb->buffer_size - read_position], &rb->buffer_ptr[0],
-               length - rb->buffer_size + read_position);
-    }
-    rb->read_index += length;
-
-    return length;
-}
-RTM_EXPORT(rt_ringbuffer_get);
-
-/**
- * get a character from a ringbuffer
- */
-rt_size_t rt_ringbuffer_getchar(struct rt_ringbuffer *rb, rt_uint8_t *ch)
-{
-    rt_uint16_t mask;
-
-    RT_ASSERT(rb != RT_NULL);
-    
-    /* ringbuffer is empty */
-    if (rb->read_index == rb->write_index) return 0;
-
-    mask = rb->buffer_size - 1;
-
-    /* put character */
-    *ch = rb->buffer_ptr[rb->read_index & mask];
-    rb->read_index += 1;
-
-    return 1;
-}
-RTM_EXPORT(rt_ringbuffer_getchar);
+/*
+ * File      : ringbuffer.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2012, 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-09-30     Bernard      first version.
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+#include <string.h>
+
+void rt_ringbuffer_init(struct rt_ringbuffer *rb,
+                        rt_uint8_t           *pool,
+                        rt_uint16_t           size)
+{
+    RT_ASSERT(rb != RT_NULL);
+
+    /* initialize read and write index */
+    rb->read_index = rb->write_index = 0;
+
+    /* set buffer pool and size */
+    rb->buffer_ptr = pool;
+    rb->buffer_size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE);
+}
+RTM_EXPORT(rt_ringbuffer_init);
+
+rt_size_t rt_ringbuffer_put(struct rt_ringbuffer *rb,
+                            const rt_uint8_t     *ptr,
+                            rt_uint16_t           length)
+{
+    rt_uint16_t size;
+    rt_uint16_t mask;
+    rt_uint16_t write_position;
+    
+    RT_ASSERT(rb != RT_NULL);
+
+    mask = rb->buffer_size - 1;
+    /* whether has enough space */
+    size = rb->buffer_size - (rb->write_index - rb->read_index);
+
+    /* no space */
+    if (size == 0)
+        return 0;
+    /* drop some data */
+    if (size < length)
+        length = size;
+
+    write_position = (rb->write_index & mask);
+    if (rb->buffer_size - write_position> length)
+    {
+        /* read_index - write_index = empty space */
+        memcpy(&rb->buffer_ptr[write_position], ptr, length);
+    }
+    else
+    {
+        memcpy(&rb->buffer_ptr[write_position], ptr,
+               rb->buffer_size - write_position);
+        memcpy(&rb->buffer_ptr[0], &ptr[rb->buffer_size - write_position],
+               length - (rb->buffer_size - write_position));
+    }
+    rb->write_index += length;
+
+    return length;
+}
+RTM_EXPORT(rt_ringbuffer_put);
+
+/**
+ * put a character into ring buffer
+ */
+rt_size_t rt_ringbuffer_putchar(struct rt_ringbuffer *rb, const rt_uint8_t ch)
+{
+    rt_uint16_t mask;
+
+    RT_ASSERT(rb != RT_NULL);
+    /* whether has enough space */
+    mask = rb->buffer_size - 1;
+
+    /* whether has enough space */
+    if (rb->write_index - rb->read_index == rb->buffer_size)
+        return 0;
+
+    /* put character */
+    rb->buffer_ptr[rb->write_index & mask] = ch;
+    rb->write_index += 1;
+
+    return 1;
+}
+RTM_EXPORT(rt_ringbuffer_putchar);
+
+/**
+ *  get data from ring buffer
+ */
+rt_size_t rt_ringbuffer_get(struct rt_ringbuffer *rb,
+                            rt_uint8_t           *ptr,
+                            rt_uint16_t           length)
+{
+    rt_size_t size;
+    rt_uint16_t mask;
+    rt_uint16_t read_position;
+
+    RT_ASSERT(rb != RT_NULL);
+    /* whether has enough data  */
+    mask = rb->buffer_size - 1;
+    size = rb->write_index - rb->read_index;
+
+    /* no data */
+    if (size == 0)
+        return 0;
+    /* less data */
+    if (size < length)
+        length = size;
+
+    read_position = rb->read_index & mask;
+    if (rb->buffer_size - read_position >= length)
+    {
+        /* copy all of data */
+        memcpy(ptr, &rb->buffer_ptr[read_position], length);
+    }
+    else
+    {
+        /* copy first and second */
+        memcpy(ptr, &rb->buffer_ptr[read_position],
+               rb->buffer_size - read_position);
+        memcpy(&ptr[rb->buffer_size - read_position], &rb->buffer_ptr[0],
+               length - rb->buffer_size + read_position);
+    }
+    rb->read_index += length;
+
+    return length;
+}
+RTM_EXPORT(rt_ringbuffer_get);
+
+/**
+ * get a character from a ringbuffer
+ */
+rt_size_t rt_ringbuffer_getchar(struct rt_ringbuffer *rb, rt_uint8_t *ch)
+{
+    rt_uint16_t mask;
+
+    RT_ASSERT(rb != RT_NULL);
+    
+    /* ringbuffer is empty */
+    if (rb->read_index == rb->write_index)
+        return 0;
+
+    mask = rb->buffer_size - 1;
+
+    /* put character */
+    *ch = rb->buffer_ptr[rb->read_index & mask];
+    rb->read_index += 1;
+
+    return 1;
+}
+RTM_EXPORT(rt_ringbuffer_getchar);