summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bsp/ls1cdev/libraries/ls1c_gpio.c7
-rw-r--r--bsp/ls1cdev/libraries/ls1c_i2c.c373
-rw-r--r--bsp/ls1cdev/libraries/ls1c_i2c.h134
-rw-r--r--bsp/ls1cdev/libraries/ls1c_public.c22
-rw-r--r--bsp/ls1cdev/libraries/ls1c_public.h16
-rw-r--r--bsp/ls1cdev/libraries/ls1c_regs.h5
6 files changed, 555 insertions, 2 deletions
diff --git a/bsp/ls1cdev/libraries/ls1c_gpio.c b/bsp/ls1cdev/libraries/ls1c_gpio.c
index d0f0633b4e..ee073b7c4b 100644
--- a/bsp/ls1cdev/libraries/ls1c_gpio.c
+++ b/bsp/ls1cdev/libraries/ls1c_gpio.c
@@ -211,8 +211,8 @@ unsigned int gpio_get(unsigned int gpio)
*/
void gpio_set_irq_type(unsigned int gpio, gpio_irq_type_t type)
{
- volatile unsigned int *int_pol; // �жϼ���ѡ��Ĵ���
- volatile unsigned int *int_edge; // �жϱ���ѡ��Ĵ���
+ volatile unsigned int *int_pol = NULL; // �жϼ���ѡ��Ĵ���
+ volatile unsigned int *int_edge = NULL; // �жϱ���ѡ��Ĵ���
unsigned int port = GPIO_GET_PORT(gpio);
unsigned int pin = GPIO_GET_PIN(gpio);
@@ -257,6 +257,9 @@ void gpio_set_irq_type(unsigned int gpio, gpio_irq_type_t type)
*int_pol &= ~(1 << pin);
*int_edge &= ~(1 << pin);
break;
+
+ default:
+ break;
}
return ;
diff --git a/bsp/ls1cdev/libraries/ls1c_i2c.c b/bsp/ls1cdev/libraries/ls1c_i2c.c
new file mode 100644
index 0000000000..6a1622471c
--- /dev/null
+++ b/bsp/ls1cdev/libraries/ls1c_i2c.c
@@ -0,0 +1,373 @@
+/*
+ * File : ls1c_i2c.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2012, RT-Thread Development Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2017-09-06 ���� first version
+ */
+
+// ��װӲ��i2c�ӿ�
+
+
+#include "ls1c_public.h"
+#include "ls1c_regs.h"
+#include "ls1c_clock.h"
+#include "ls1c_i2c.h"
+#include "ls1c_delay.h"
+
+
+
+/*
+ * I2C�����Ĵ�����Ի���ַ��ƫ��
+ * �������ݼĴ����ͽ������ݼĴ�����ƫ������ͬ��
+ * ����Ĵ�����״̬�Ĵ�����ƫ������ͬ�ģ���ͬ��������Ĵ���ֻд��״̬�Ĵ���ֻ��
+ */
+#define LS1C_I2C_PRER_LOW_OFFSET (0) // ��Ƶ���������ֽڼĴ���ƫ��
+#define LS1C_I2C_PRER_HIGH_OFFSET (1) // ��Ƶ���������ֽڼĴ���ƫ��
+#define LS1C_I2C_CONTROL_OFFSET (2) // ���ƼĴ���ƫ��
+#define LS1C_I2C_DATA_OFFSET (3) // �������ݼĴ����ͽ������ݼĴ�����ƫ������ͬ��
+#define LS1C_I2C_CMD_OFFSET (4) // ����Ĵ���ƫ�ƣ�ֻд
+#define LS1C_I2C_STATUS_OFFSET (4) // ״̬�Ĵ���ƫ�ƣ�ֻ��
+
+
+// ���ƼĴ�����λ��
+#define LS1C_I2C_CONTROL_EN (0x80) // i2cģ��ʹ��
+#define LS1C_I2C_CONTROL_IEN (0x40) // �ж�ʹ��
+
+// ����Ĵ�����λ��
+#define LS1C_I2C_CMD_START (0x90) // ����START�ź�
+#define LS1C_I2C_CMD_STOP (0x40) // ����STOP�ź�
+#define LS1C_I2C_CMD_READ (0x20) // �������źţ�������ACK�ź�
+#define LS1C_I2C_CMD_WRITE (0x10) // ����д�ź�
+#define LS1C_I2C_CMD_READ_ACK (0x20) // ����ACK�źţ�����ź���ͬ
+#define LS1C_I2C_CMD_READ_NACK (0x28) // ����NACK�ź�
+#define LS1C_I2C_CMD_IACK (0x00) // �����ж�Ӧ���ź�
+
+// ״̬�Ĵ�����λ��
+#define LS1C_I2C_STATUS_IF (0x01) // �жϱ�־λ
+#define LS1C_I2C_STATUS_TIP (0x02) // ָʾ����Ĺ��̡�1�����ڴ��䣻0���������
+#define LS1C_I2C_STATUS_ARBLOST (0x20) // I2C��ʧȥI2C���ߵĿ���Ȩ
+#define LS1C_I2C_STATUS_BUSY (0x40) // I2C����æ��־
+#define LS1C_I2C_STATUS_NACK (0x80) // Ӧ��λ��־��1��û�յ�Ӧ��λ��0���յ�Ӧ��λ
+
+
+/*
+ * ��ȡָ��i2cģ��Ļ���ַ
+ * @I2Cx I2Cģ��ı��
+ */
+void *i2c_get_base(ls1c_i2c_t I2Cx)
+{
+ void *base = NULL;
+
+ switch (I2Cx)
+ {
+ case LS1C_I2C_0:
+ base = (void *)LS1C_I2C0_BASE;
+ break;
+
+ case LS1C_I2C_1:
+ base = (void *)LS1C_I2C1_BASE;
+ break;
+
+ case LS1C_I2C_2:
+ base = (void *)LS1C_I2C2_BASE;
+ break;
+
+ default:
+ base = NULL;
+ break;
+ }
+
+ return base;
+}
+
+
+/*
+ * ������Ĵ���д����
+ * @i2c_info_p i2cģ����Ϣ
+ * @cmd ����
+ */
+void i2c_cmd(ls1c_i2c_info_t *i2c_info_p, unsigned char cmd)
+{
+ void *i2c_base = i2c_get_base(i2c_info_p->I2Cx);
+
+ reg_write_8(cmd, i2c_base + LS1C_I2C_CMD_OFFSET);
+
+ return ;
+}
+
+
+/*
+ * ִ��START�������START�ź�
+ * @i2c_info_p i2cģ����Ϣ
+ */
+void i2c_cmd_start(ls1c_i2c_info_t *i2c_info_p)
+{
+ i2c_cmd(i2c_info_p, LS1C_I2C_CMD_START);
+ return ;
+}
+
+
+/*
+ * ִ��STOP�������STOP�ź�
+ * @i2c_info_p i2cģ����Ϣ
+ */
+void i2c_cmd_stop(ls1c_i2c_info_t *i2c_info_p)
+{
+ i2c_cmd(i2c_info_p, LS1C_I2C_CMD_STOP);
+ return ;
+}
+
+
+/*
+ * ִ��д����
+ * @i2c_info_p i2cģ����Ϣ
+ */
+void i2c_cmd_write(ls1c_i2c_info_t *i2c_info_p)
+{
+ i2c_cmd(i2c_info_p, LS1C_I2C_CMD_WRITE);
+ return ;
+}
+
+
+/*
+ * ִ�ж�ack������Ͷ�ack�ź�
+ * @i2c_info_p i2cģ����Ϣ
+ */
+void i2c_cmd_read_ack(ls1c_i2c_info_t *i2c_info_p)
+{
+ i2c_cmd(i2c_info_p, LS1C_I2C_CMD_READ_ACK);
+ return ;
+}
+
+
+/*
+ * ִ�ж�nack����,���Ͷ�nack�ź�
+ * @i2c_info_p i2cģ����Ϣ
+ */
+void i2c_cmd_read_nack(ls1c_i2c_info_t *i2c_info_p)
+{
+ i2c_cmd(i2c_info_p, LS1C_I2C_CMD_READ_NACK);
+ return ;
+}
+
+
+/*
+ * �����ж�Ӧ���ź�
+ * @i2c_info_p i2cģ����Ϣ
+ */
+void i2c_cmd_iack(ls1c_i2c_info_t *i2c_info_p)
+{
+ i2c_cmd(i2c_info_p, LS1C_I2C_CMD_IACK);
+ return ;
+}
+
+
+/*
+ * ��ȡ״̬�Ĵ�����ֵ
+ * @i2c_info_p i2cģ����Ϣ
+ * @ret ״̬�Ĵ�����ֵ
+ */
+unsigned char i2c_get_status(ls1c_i2c_info_t *i2c_info_p)
+{
+ void *i2c_base = i2c_get_base(i2c_info_p->I2Cx);
+
+ return reg_read_8(i2c_base + LS1C_I2C_STATUS_OFFSET);
+}
+
+
+/*
+ * Poll the i2c status register until the specified bit is set.
+ * Returns 0 if timed out (100 msec).
+ * @i2c_info_p i2cģ����Ϣ
+ * @bit �Ĵ�����ijһλ
+ * @ret true or false
+ */
+int i2c_poll_status(ls1c_i2c_info_t *i2c_info_p, unsigned long bit)
+{
+ int loop_cntr = 20000;
+
+ do {
+ delay_us(1);
+ } while ((i2c_get_status(i2c_info_p) & bit) && (0 < --loop_cntr));
+
+ return (0 < loop_cntr);
+}
+
+
+/*
+ * ��ʼ��ָ��i2cģ��
+ * @i2c_info_p ij��i2cģ�����Ϣ
+ */
+void i2c_init(ls1c_i2c_info_t *i2c_info_p)
+{
+ void *i2c_base = i2c_get_base(i2c_info_p->I2Cx);
+ unsigned long i2c_clock = i2c_info_p->clock;
+ unsigned char ctrl = reg_read_8(i2c_base + LS1C_I2C_CONTROL_OFFSET);
+ unsigned long prescale = 0;
+
+ /* make sure the device is disabled */
+ ctrl = ctrl & ~(LS1C_I2C_CONTROL_EN | LS1C_I2C_CONTROL_IEN);
+ reg_write_8(ctrl, i2c_base + LS1C_I2C_CONTROL_OFFSET);
+
+ // ����ʱ��
+ i2c_clock = MIN(i2c_clock, LS1C_I2C_CLOCK_MAX); // �����������������
+ prescale = clk_get_apb_rate();
+ prescale = (prescale / (5 * i2c_clock)) - 1;
+ reg_write_8(prescale & 0xff, i2c_base + LS1C_I2C_PRER_LOW_OFFSET);
+ reg_write_8(prescale >> 8, i2c_base + LS1C_I2C_PRER_HIGH_OFFSET);
+
+ // ʹ��
+ i2c_cmd_iack(i2c_info_p);
+ ctrl = ctrl | LS1C_I2C_CONTROL_EN;
+ reg_write_8(ctrl, i2c_base + LS1C_I2C_CONTROL_OFFSET);
+
+ return ;
+}
+
+
+/*
+ * (�ٷ���һ���ֽ�����֮��)���մӻ����͵�ACK�ź�
+ * @i2c_info_p i2cģ����Ϣ
+ * @ret LS1C_I2C_ACK or LS1C_I2C_NACK
+ */
+ls1c_i2c_ack_t i2c_receive_ack(ls1c_i2c_info_t *i2c_info_p)
+{
+ ls1c_i2c_ack_t ret = LS1C_I2C_NACK;
+
+ if (LS1C_I2C_STATUS_NACK & i2c_get_status(i2c_info_p))
+ {
+ ret = LS1C_I2C_NACK;
+ }
+ else
+ {
+ ret = LS1C_I2C_ACK;
+ }
+
+ return ret;
+}
+
+
+/*
+ * ��������
+ * @i2c_info_p i2cģ����Ϣ
+ * @buf ���ݻ���
+ * @len ���������ݵij���
+ */
+ls1c_i2c_ret_t i2c_receive_data(ls1c_i2c_info_t *i2c_info_p, unsigned char *buf, int len)
+{
+ void *i2c_base = i2c_get_base(i2c_info_p->I2Cx);
+ int i = 0;
+
+ for (i=0; i<len; i++)
+ {
+ // ��ʼ����
+ if (i != (len - 1))
+ i2c_cmd_read_ack(i2c_info_p);
+ else
+ i2c_cmd_read_nack(i2c_info_p);
+
+ // �ȴ���ֱ���������
+ if (!i2c_poll_status(i2c_info_p, LS1C_I2C_STATUS_TIP))
+ return LS1C_I2C_RET_TIMEOUT;
+
+ // ��ȡ���ݣ�������
+ *buf++ = reg_read_8(i2c_base + LS1C_I2C_DATA_OFFSET);
+ }
+
+ return LS1C_I2C_RET_OK;
+}
+
+
+/*
+ * ����START�źź͵�ַ
+ * @i2c_info_p i2cģ����Ϣ
+ * @slave_addr �ӻ���ַ
+ * @direction ���ݴ��䷽��(����д)
+ */
+ls1c_i2c_ret_t i2c_send_start_and_addr(ls1c_i2c_info_t *i2c_info_p,
+ unsigned char slave_addr,
+ ls1c_i2c_direction_t direction)
+{
+ void *i2c_base = i2c_get_base(i2c_info_p->I2Cx);
+ unsigned char data = 0;
+
+ // �ȴ�i2c���߿���
+ if (!i2c_poll_status(i2c_info_p, LS1C_I2C_STATUS_BUSY))
+ return LS1C_I2C_RET_TIMEOUT;
+
+ // ����ַ�����ݼĴ���
+ data = (slave_addr << 1) | ((LS1C_I2C_DIRECTION_READ == direction) ? 1 : 0);
+ reg_write_8(data , i2c_base + LS1C_I2C_DATA_OFFSET);
+
+ // ��ʼ����
+ i2c_cmd_start(i2c_info_p);
+
+ // �ȴ���ֱ���������
+ if (!i2c_poll_status(i2c_info_p, LS1C_I2C_STATUS_TIP))
+ return LS1C_I2C_RET_TIMEOUT;
+
+ return LS1C_I2C_RET_OK;
+}
+
+
+/*
+ * ��������
+ * @i2c_info_p i2cģ����Ϣ
+ * @data �����͵�����
+ * @len ���������ݵij���
+ */
+ls1c_i2c_ret_t i2c_send_data(ls1c_i2c_info_t *i2c_info_p, unsigned char *data, int len)
+{
+ void *i2c_base = i2c_get_base(i2c_info_p->I2Cx);
+ int i = 0;
+
+ for (i=0; i<len; i++)
+ {
+ // ��һ���ֽ�����д�����ݼĴ���
+ reg_write_8(*data++, i2c_base + LS1C_I2C_DATA_OFFSET);
+
+ // ��ʼ����
+ reg_write_8(LS1C_I2C_CMD_WRITE, i2c_base + LS1C_I2C_CMD_OFFSET);
+
+ // �ȴ���ֱ���������
+ if (!i2c_poll_status(i2c_info_p, LS1C_I2C_STATUS_TIP))
+ return LS1C_I2C_RET_TIMEOUT;
+
+ // ��ȡӦ���ź�
+ if (LS1C_I2C_ACK != i2c_receive_ack(i2c_info_p))
+ return len;
+ }
+
+ return LS1C_I2C_RET_OK;
+}
+
+
+
+/*
+ * ����STOP�ź�
+ * @i2c_info_p i2cģ����Ϣ
+ */
+void i2c_send_stop(ls1c_i2c_info_t *i2c_info_p)
+{
+ i2c_cmd_stop(i2c_info_p);
+ return ;
+}
+
+
diff --git a/bsp/ls1cdev/libraries/ls1c_i2c.h b/bsp/ls1cdev/libraries/ls1c_i2c.h
new file mode 100644
index 0000000000..ada22242fb
--- /dev/null
+++ b/bsp/ls1cdev/libraries/ls1c_i2c.h
@@ -0,0 +1,134 @@
+/*
+ * File : ls1c_i2c.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2012, RT-Thread Development Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2017-09-06 ���� first version
+ */
+
+
+// Ӳ��i2c�ӿڵ�ͷ�ļ�
+
+#ifndef __OPENLOONGSON_I2C_H
+#define __OPENLOONGSON_I2C_H
+
+
+
+// I2C��ʱ��Ƶ��
+#define LS1C_I2C_CLOCK_DEFAULT (100000) // Hz. Ĭ��Ƶ��
+#define LS1C_I2C_CLOCK_MAX (400000) // Hz, max 400 Kbits/sec
+
+
+// I2C���
+typedef enum
+{
+ LS1C_I2C_0 = 0,
+ LS1C_I2C_1,
+ LS1C_I2C_2
+}ls1c_i2c_t;
+
+
+// I2C���ݴ��䷽��
+typedef enum
+{
+ LS1C_I2C_DIRECTION_WRITE = 0, // ������ӻ�д��Ϣ
+ LS1C_I2C_DIRECTION_READ, // ������ӻ�����Ϣ
+}ls1c_i2c_direction_t;
+
+
+// Ӳ��I2C��Ϣ
+typedef struct
+{
+ ls1c_i2c_t I2Cx; // i2c���
+ unsigned long clock; // i2cʱ��Ƶ�ʣ���λhz
+}ls1c_i2c_info_t;
+
+
+// I2CӦ��
+typedef enum
+{
+ LS1C_I2C_ACK = 0, // �յ�Ӧ��
+ LS1C_I2C_NACK = 1, // û�յ�Ӧ��
+}ls1c_i2c_ack_t;
+
+
+// ��������ֵ
+typedef enum
+{
+ LS1C_I2C_RET_OK = 0, // OK
+ LS1C_I2C_RET_TIMEOUT, // ��ʱ
+}ls1c_i2c_ret_t;
+
+
+
+/*
+ * ��ʼ��ָ��i2cģ��
+ * @i2c_info_p ij��i2cģ�����Ϣ
+ */
+void i2c_init(ls1c_i2c_info_t *i2c_info_p);
+
+
+/*
+ * (�ٷ���һ���ֽ�����֮��)���մӻ����͵�ACK�ź�
+ * @i2c_info_p i2cģ����Ϣ
+ * @ret LS1C_I2C_ACK or LS1C_I2C_NACK
+ */
+ls1c_i2c_ack_t i2c_receive_ack(ls1c_i2c_info_t *i2c_info_p);
+
+
+/*
+ * ��������
+ * @i2c_info_p i2cģ����Ϣ
+ * @buf ���ݻ���
+ * @len ���������ݵij���
+ */
+ls1c_i2c_ret_t i2c_receive_data(ls1c_i2c_info_t *i2c_info_p, unsigned char *buf, int len);
+
+
+
+/*
+ * ����START�źź͵�ַ
+ * @i2c_info_p i2cģ����Ϣ
+ * @slave_addr �ӻ���ַ
+ * @direction ���ݴ��䷽��(����д)
+ */
+ls1c_i2c_ret_t i2c_send_start_and_addr(ls1c_i2c_info_t *i2c_info_p,
+ unsigned char slave_addr,
+ ls1c_i2c_direction_t direction);
+
+
+/*
+ * ��������
+ * @i2c_info_p i2cģ����Ϣ
+ * @data �����͵�����
+ * @len ���������ݵij���
+ */
+ls1c_i2c_ret_t i2c_send_data(ls1c_i2c_info_t *i2c_info_p, unsigned char *data, int len);
+
+
+/*
+ * ����STOP�ź�
+ * @i2c_info_p i2cģ����Ϣ
+ */
+void i2c_send_stop(ls1c_i2c_info_t *i2c_info_p);
+
+
+
+#endif
+
diff --git a/bsp/ls1cdev/libraries/ls1c_public.c b/bsp/ls1cdev/libraries/ls1c_public.c
index 84518f0bd0..a04f68a877 100644
--- a/bsp/ls1cdev/libraries/ls1c_public.c
+++ b/bsp/ls1cdev/libraries/ls1c_public.c
@@ -55,6 +55,28 @@ unsigned int reg_get_bit(volatile unsigned int *reg, unsigned int bit)
/*
+ * ��Ĵ�����д��8bit(һ���ֽ�)����
+ * @data ��������
+ * @addr �Ĵ�����ַ
+ */
+void reg_write_8(unsigned char data, volatile unsigned char *addr)
+{
+ *addr = data;
+}
+
+
+/*
+ * �ӼĴ�������8bit(һ���ֽ�)����
+ * @addr �Ĵ�����ַ
+ * @ret ����������
+ */
+unsigned char reg_read_8(volatile unsigned char *addr)
+{
+ return (*addr);
+}
+
+
+/*
* ��Ĵ�����дһ��32bit������
* @data ��������
* @addr �Ĵ�����ַ
diff --git a/bsp/ls1cdev/libraries/ls1c_public.h b/bsp/ls1cdev/libraries/ls1c_public.h
index 3ecabeafaa..34164d8c1c 100644
--- a/bsp/ls1cdev/libraries/ls1c_public.h
+++ b/bsp/ls1cdev/libraries/ls1c_public.h
@@ -58,6 +58,22 @@ unsigned int reg_get_bit(volatile unsigned int *reg, unsigned int bit);
/*
+ * ��Ĵ�����д��8bit(һ���ֽ�)����
+ * @data ��������
+ * @addr �Ĵ�����ַ
+ */
+void reg_write_8(unsigned char data, volatile unsigned char *addr);
+
+
+/*
+ * �ӼĴ�������8bit(һ���ֽ�)����
+ * @addr �Ĵ�����ַ
+ * @ret ����������
+ */
+unsigned char reg_read_8(volatile unsigned char *addr);
+
+
+/*
* ��Ĵ�����дһ��32bit������
* @data ��������
* @addr �Ĵ�����ַ
diff --git a/bsp/ls1cdev/libraries/ls1c_regs.h b/bsp/ls1cdev/libraries/ls1c_regs.h
index fb67086d34..3d23429865 100644
--- a/bsp/ls1cdev/libraries/ls1c_regs.h
+++ b/bsp/ls1cdev/libraries/ls1c_regs.h
@@ -111,6 +111,11 @@
#define LS1C_INT4_EDGE (0xbfd010b4)
+// I2C�Ĵ���
+#define LS1C_I2C0_BASE (0xbfe58000)
+#define LS1C_I2C1_BASE (0xbfe68000)
+#define LS1C_I2C2_BASE (0xbfe70000)
+
#endif