diff --git a/bsp/stm32f10x/drivers/fm24cl64.c b/bsp/stm32f10x/drivers/fm24cl64.c new file mode 100644 index 0000000000..ed0a78a2ca --- /dev/null +++ b/bsp/stm32f10x/drivers/fm24cl64.c @@ -0,0 +1,29 @@ +/* + * File : fm24cl64.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2017, 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 + * 2017-07-17 aubrcool@qq.com 1st version + */ + +#include +#include +#include "i2c/fm24clxx.h" + +const struct fm24clxx_config fm24cl64_cfg = +{ + .size = 64 * 1024, + .addr = 0x50, + .flags = 0, +}; + +int rt_hw_fm24cl64_init(const char *fm_device_name, const char *i2c_bus) +{ + return fm24clxx_register(fm_device_name, i2c_bus, (void *)&fm24cl64_cfg); +} diff --git a/bsp/stm32f10x/drivers/fm24cl64.h b/bsp/stm32f10x/drivers/fm24cl64.h new file mode 100644 index 0000000000..bc613fea72 --- /dev/null +++ b/bsp/stm32f10x/drivers/fm24cl64.h @@ -0,0 +1,22 @@ +/* + * File : fm24cl64.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2017, 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 + * 2017-07-17 aubrcool@qq.com 1st version + */ + +#ifndef __FM24CL64_H__ +#define __FM24CL64_H__ + +#include + +extern int rt_hw_fm24cl64_init(const char *fm_device_name, const char *i2c_bus); + +#endif /*__FM24CL64_H__*/ diff --git a/bsp/stm32f10x/drivers/stm32f1_i2c.c b/bsp/stm32f10x/drivers/stm32f1_i2c.c new file mode 100644 index 0000000000..5ba942f417 --- /dev/null +++ b/bsp/stm32f10x/drivers/stm32f1_i2c.c @@ -0,0 +1,542 @@ +/* + * File : stm32f1_i2c.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006-2017, 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 + * 2017-07-04 aubrcool@qq.com 1st version + */ +#include "stm32f10x.h" +#include "stm32f1_i2c.h" +#include + +#ifdef RT_USING_I2C + +/* I2C SPE mask */ +#define CR1_PE_Set ((uint16_t)0x0001) +#define CR1_PE_Reset ((uint16_t)0xFFFE) + +/* I2C START mask */ +#define CR1_START_Set ((uint16_t)0x0100) +#define CR1_START_Reset ((uint16_t)0xFEFF) + +/* I2C STOP mask */ +#define CR1_STOP_Set ((uint16_t)0x0200) +#define CR1_STOP_Reset ((uint16_t)0xFDFF) + +/* I2C ACK mask */ +#define CR1_ACK_Set ((uint16_t)0x0400) +#define CR1_ACK_Reset ((uint16_t)0xFBFF) + +/* I2C ENGC mask */ +#define CR1_ENGC_Set ((uint16_t)0x0040) +#define CR1_ENGC_Reset ((uint16_t)0xFFBF) + +/* I2C SWRST mask */ +#define CR1_SWRST_Set ((uint16_t)0x8000) +#define CR1_SWRST_Reset ((uint16_t)0x7FFF) + +/* I2C PEC mask */ +#define CR1_PEC_Set ((uint16_t)0x1000) +#define CR1_PEC_Reset ((uint16_t)0xEFFF) + +/* I2C ENPEC mask */ +#define CR1_ENPEC_Set ((uint16_t)0x0020) +#define CR1_ENPEC_Reset ((uint16_t)0xFFDF) + +/* I2C ENARP mask */ +#define CR1_ENARP_Set ((uint16_t)0x0010) +#define CR1_ENARP_Reset ((uint16_t)0xFFEF) + +/* I2C NOSTRETCH mask */ +#define CR1_NOSTRETCH_Set ((uint16_t)0x0080) +#define CR1_NOSTRETCH_Reset ((uint16_t)0xFF7F) + +/* I2C registers Masks */ +#define CR1_CLEAR_Mask ((uint16_t)0xFBF5) + +/* I2C DMAEN mask */ +#define CR2_DMAEN_Set ((uint16_t)0x0800) +#define CR2_DMAEN_Reset ((uint16_t)0xF7FF) + +/* I2C LAST mask */ +#define CR2_LAST_Set ((uint16_t)0x1000) +#define CR2_LAST_Reset ((uint16_t)0xEFFF) + +/* I2C FREQ mask */ +#define CR2_FREQ_Reset ((uint16_t)0xFFC0) + +/* I2C ADD0 mask */ +#define OAR1_ADD0_Set ((uint16_t)0x0001) +#define OAR1_ADD0_Reset ((uint16_t)0xFFFE) + +/* I2C ENDUAL mask */ +#define OAR2_ENDUAL_Set ((uint16_t)0x0001) +#define OAR2_ENDUAL_Reset ((uint16_t)0xFFFE) + +/* I2C ADD2 mask */ +#define OAR2_ADD2_Reset ((uint16_t)0xFF01) + +/* I2C F/S mask */ +#define CCR_FS_Set ((uint16_t)0x8000) + +/* I2C CCR mask */ +#define CCR_CCR_Set ((uint16_t)0x0FFF) + +/* I2C FLAG mask */ +#define FLAG_Mask ((uint32_t)0x00FFFFFF) + +/* I2C Interrupt Enable mask */ +#define ITEN_Mask ((uint32_t)0x07000000) + +#define I2CADDR 0x0A + +enum +{ + EV_END = 0, +}; + +#ifdef RT_USING_I2C1 +static struct stm32_i2c_bus stm32_i2c1 = +{ + .I2C = I2C1, +}; +#endif /*RT_USING_I2C1*/ +#ifdef RT_USING_I2C2 +static struct stm32_i2c_bus stm32_i2c2 = +{ + .I2C = I2C2, +}; +#endif /*RT_USING_I2C2*/ + +rt_inline rt_err_t stm32_i2c_wait_ev(struct stm32_i2c_bus *bus, + rt_uint32_t ev, rt_uint32_t timeout) +{ + rt_uint32_t res = 0; + rt_event_recv(&bus->ev, 0x01 << ev, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, + timeout, &res); + if(res != ev) + { + return RT_ERROR; + } + else + { + return RT_EOK; + } +} +rt_inline void stm32_i2c_send_ev(struct stm32_i2c_bus *bus, rt_uint32_t ev) +{ + rt_event_send(&bus->ev, 0x01 << ev); +} + +static rt_size_t stm_i2c_mst_xfer(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num); +static rt_size_t stm_i2c_slv_xfer(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num); +static rt_err_t stm_i2c_bus_control(struct rt_i2c_bus_device *bus, + rt_uint32_t, + rt_uint32_t); + +static const struct rt_i2c_bus_device_ops stm32_i2c_ops = +{ + stm_i2c_mst_xfer, + stm_i2c_slv_xfer, + stm_i2c_bus_control, +}; +rt_inline void stm32_i2c_disable_nvic(I2C_TypeDef *I2C, rt_uint32_t value) +{ + NVIC_InitTypeDef NVIC_InitStructure; + + rt_uint32_t evno, erno; + if(I2C == I2C1) + { + evno = I2C1_EV_IRQn; + erno = I2C1_ER_IRQn; + } + else + { + evno = I2C2_EV_IRQn; + erno = I2C2_ER_IRQn; + } + NVIC_InitStructure.NVIC_IRQChannel = evno; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 6; + NVIC_InitStructure.NVIC_IRQChannelCmd = value; + NVIC_Init(&NVIC_InitStructure); + + NVIC_InitStructure.NVIC_IRQChannel = erno; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 6; + NVIC_InitStructure.NVIC_IRQChannelCmd = value; + NVIC_Init(&NVIC_InitStructure); +} +static void stm32_i2c_nvic_Config(I2C_TypeDef *I2C) +{ + stm32_i2c_disable_nvic(I2C, ENABLE); +} +static rt_err_t stm_i2c_init(struct rt_i2c_bus_device *bus, rt_uint32_t bitrate) +{ + struct stm32_i2c_bus *stm32_i2c; + I2C_InitTypeDef I2C_InitStructure; + + RT_ASSERT(bus != RT_NULL); + if(bitrate != 100000 && bitrate != 400000) + { + return RT_EIO; + } + + stm32_i2c = (struct stm32_i2c_bus *) bus; + I2C_Cmd(stm32_i2c->I2C, DISABLE); + I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; + I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; + I2C_InitStructure.I2C_OwnAddress1 = I2CADDR; + I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; + I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; + I2C_InitStructure.I2C_ClockSpeed = bitrate; + + I2C_Init(stm32_i2c->I2C, &I2C_InitStructure); + I2C_Cmd(stm32_i2c->I2C, ENABLE); + + I2C_ITConfig(stm32_i2c->I2C, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, ENABLE); + + stm32_i2c_nvic_Config(stm32_i2c->I2C); + + return RT_EOK; +} + +static rt_size_t stm_i2c_mst_xfer(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num) +{ + struct stm32_i2c_bus *stm32_i2c; + rt_uint32_t numbak = num; + RT_ASSERT(bus != RT_NULL); + stm32_i2c = (struct stm32_i2c_bus *) bus; + + stm32_i2c->msg = msgs; + stm32_i2c->msg_ptr = 0; + stm32_i2c->msg_cnt = num; + stm32_i2c->dptr = 0; + stm32_i2c->wait_stop = 0; + + I2C_GetLastEvent(stm32_i2c->I2C); + while(stm32_i2c->msg_ptr < stm32_i2c->msg_cnt) + { + stm32_i2c->wait_stop = 0; + if(!(stm32_i2c->msg[stm32_i2c->msg_ptr].flags & RT_I2C_NO_START)) + { + stm32_i2c->I2C->CR1 |= CR1_START_Set; + } + stm32_i2c_wait_ev(stm32_i2c, EV_END, 1000); + } + stm32_i2c->msg = RT_NULL; + stm32_i2c->msg_ptr = 0; + stm32_i2c->msg_cnt = 0; + stm32_i2c->dptr = 0; + stm32_i2c->wait_stop = 0; + return numbak; +} +static rt_size_t stm_i2c_slv_xfer(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num) +{ + return 0; +} +static rt_err_t stm_i2c_bus_control(struct rt_i2c_bus_device *bus, + rt_uint32_t cmd, + rt_uint32_t arg) +{ + return RT_ERROR; +} +rt_inline void stm32_i2c_ev_handler(struct stm32_i2c_bus *stm32_i2c) +{ + unsigned int I2C_Event; + rt_uint8_t data = 0; + struct rt_i2c_msg *pmsg; + + I2C_Event = I2C_GetLastEvent(stm32_i2c->I2C); + + if(!stm32_i2c->msg) + { + return; + } + // EV5 0x00030001 + if ((I2C_Event & I2C_EVENT_MASTER_MODE_SELECT) == I2C_EVENT_MASTER_MODE_SELECT) + { + // EV5 0x00030001 + pmsg = &stm32_i2c->msg[stm32_i2c->msg_ptr]; + if(pmsg->flags & RT_I2C_ADDR_10BIT) + { + data = ((pmsg->addr >> 8) << 1) | 0xF0; + } + else + { + data = pmsg->addr << 1; + } + if(pmsg->flags & RT_I2C_RD) + { + data |= 0x01; + } + stm32_i2c->I2C->DR = data; + if(!(pmsg->flags & RT_I2C_RD)) + { + return; + } + if(pmsg->len > 1) + { + stm32_i2c->I2C->CR1 |= CR1_ACK_Set; + return; + } + } + else if((I2C_Event & I2C_EVENT_MASTER_MODE_ADDRESS10) == + I2C_EVENT_MASTER_MODE_ADDRESS10) + { + // EV9 + data = pmsg->addr & 0xFF; + stm32_i2c->I2C->DR = data; + } + else if((I2C_Event & I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) == + I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) + { + //EVT 6 SEND 0x00070082 + } + else if ((I2C_Event & I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) == + I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) + { + //EVT 6 RECE 0x00030002 + pmsg = &stm32_i2c->msg[stm32_i2c->msg_ptr]; + if(!(pmsg->flags & RT_I2C_RD)) + { + return; + } + if(pmsg->len > 1) + { + return; + } + if(stm32_i2c->msg_ptr < stm32_i2c->msg_cnt - 1) + { + return; + } + else if((pmsg[1].flags & RT_I2C_NO_START)) + { + return; + } + stm32_i2c->I2C->CR1 |= CR1_STOP_Set; + stm32_i2c->I2C->CR1 &= CR1_ACK_Reset; + } + else if ((I2C_Event & I2C_EVENT_MASTER_BYTE_RECEIVED) == + I2C_EVENT_MASTER_BYTE_RECEIVED) + { + // EVT 7 0x00030040 + pmsg = &stm32_i2c->msg[stm32_i2c->msg_ptr]; + + if(pmsg->len && (pmsg->flags & RT_I2C_RD)) + { + pmsg->buf[stm32_i2c->dptr] = stm32_i2c->I2C->DR; + stm32_i2c->dptr++; + pmsg->len--; + } + if(pmsg->len == 1 && (pmsg->flags & RT_I2C_RD)) + { + if(stm32_i2c->msg_ptr >= stm32_i2c->msg_cnt - 1) + { + stm32_i2c->I2C->CR1 &= CR1_ACK_Reset; + stm32_i2c->I2C->CR1 |= CR1_STOP_Set; + } + else if(!(pmsg[1].flags & RT_I2C_NO_START)) + { + stm32_i2c->I2C->CR1 &= CR1_ACK_Reset; + stm32_i2c->I2C->CR1 |= CR1_STOP_Set; + } + } + if(pmsg->len) + { + return; + } + stm32_i2c->dptr = 0; + stm32_i2c->msg_ptr++; + if(stm32_i2c->msg_ptr < stm32_i2c->msg_cnt) + { + return; + } + stm32_i2c->I2C->CR1 |= CR1_ACK_Set; + stm32_i2c_send_ev(stm32_i2c, EV_END); + } + else if((I2C_Event & I2C_EVENT_MASTER_BYTE_TRANSMITTING) == + I2C_EVENT_MASTER_BYTE_TRANSMITTING) + { + //EVT8 0x00070080 + if(stm32_i2c->wait_stop == 0xAAAA5555) + { + stm32_i2c->wait_stop = 0; + stm32_i2c->I2C->CR1 |= CR1_STOP_Set; + stm32_i2c_send_ev(stm32_i2c, EV_END); + return; + } + if(stm32_i2c->wait_stop == 0x5555AAAA) + { //restart cond + stm32_i2c->wait_stop = 0; + stm32_i2c_send_ev(stm32_i2c, EV_END); + return; + } + + pmsg = &stm32_i2c->msg[stm32_i2c->msg_ptr]; + if(!(pmsg->flags & RT_I2C_RD) && pmsg->len) + { + stm32_i2c->I2C->DR = pmsg->buf[stm32_i2c->dptr]; + stm32_i2c->dptr++; + pmsg->len--; + } + + if(!(pmsg->flags & RT_I2C_RD) && pmsg->len) + { + return; + } + + if(stm32_i2c->msg_ptr < stm32_i2c->msg_cnt - 1 && pmsg->len == 0) + { + stm32_i2c->msg_ptr++; + stm32_i2c->dptr = 0; + pmsg = &stm32_i2c->msg[stm32_i2c->msg_ptr]; + if(pmsg->flags & RT_I2C_NO_START) + { + return; + } + else + { + stm32_i2c->wait_stop == 0x5555AAAA; + return; + } + } + if(stm32_i2c->msg_ptr < stm32_i2c->msg_cnt && pmsg->len == 0) + { + stm32_i2c->msg_ptr++; + stm32_i2c->dptr = 0; + } + stm32_i2c->wait_stop = 0xAAAA5555; + } +} + +#ifdef RT_USING_I2C1 +void I2C1_EV_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + stm32_i2c_ev_handler(&stm32_i2c1); + + /* leave interrupt */ + rt_interrupt_leave(); + +} +#endif /*RT_USING_I2C1*/ + +#ifdef RT_USING_I2C2 +void I2C2_EV_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + stm32_i2c_ev_handler(&stm32_i2c2); + + /* leave interrupt */ + rt_interrupt_leave(); + +} +#endif /*RT_USING_I2C2*/ + +rt_inline void stm32_i2c_er_handler(struct stm32_i2c_bus *stm32_i2c) +{ + if (I2C2->SR1 & 1 << 10) + { + I2C2->SR1 &= ~(1 << 10); + } + if (I2C2->SR1 & 1 << 14) + { + I2C2->SR1 &= ~(1 << 14); + } + if (I2C2->SR1 & 1 << 11) + { + I2C2->SR1 &= ~(1 << 11); + } + if (I2C2->SR1 & 1 << 9) + { + I2C2->SR1 &= ~(1 << 9); + } + if (I2C2->SR1 & 1 << 8) + { + I2C2->SR1 &= ~(1 << 8); + } +} + +#ifdef RT_USING_I2C1 +void I2C1_ER_IRQHandler(void) //I2C2 Error Interrupt +{ + /* enter interrupt */ + rt_interrupt_enter(); + + stm32_i2c_er_handler(&stm32_i2c1); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /*RT_USING_I2C1*/ + +#ifdef RT_USING_I2C2 +void I2C2_ER_IRQHandler(void) //I2C2 Error Interrupt +{ + /* enter interrupt */ + rt_interrupt_enter(); + + stm32_i2c_er_handler(&stm32_i2c2); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /*RT_USING_I2C2*/ + +rt_err_t stm32_i2c_register(I2C_TypeDef *I2C, rt_uint32_t bitrate, + const char * i2c_bus_name) +{ + struct stm32_i2c_bus *pi2c; + rt_err_t res; + +#ifdef RT_USING_I2C1 + if(I2C == I2C1) + { + pi2c = &stm32_i2c1; + RCC_APB2PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); + } + else +#endif /*RT_USING_I2C1*/ +#ifdef RT_USING_I2C2 + if(I2C == I2C2) + { + pi2c = &stm32_i2c2; + RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE); + } + else +#endif /*RT_USING_I2C2*/ + { + return RT_ENOSYS; + } + if(rt_event_init(&pi2c->ev, i2c_bus_name, RT_IPC_FLAG_FIFO) != RT_EOK) + { + return RT_ERROR; + } + pi2c->parent.ops = &stm32_i2c_ops; + if((res = stm_i2c_init(&pi2c->parent, bitrate)) != RT_EOK) + { + return res; + } + return rt_i2c_bus_device_register(&pi2c->parent, i2c_bus_name); +} +#endif /*RT_USING_I2C*/ diff --git a/bsp/stm32f10x/drivers/stm32f1_i2c.h b/bsp/stm32f10x/drivers/stm32f1_i2c.h new file mode 100644 index 0000000000..0cebe02e85 --- /dev/null +++ b/bsp/stm32f10x/drivers/stm32f1_i2c.h @@ -0,0 +1,42 @@ +/* + * File : stm32f1_i2c.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006-2013, 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 + * 2017-07-04 aubrcool@qq.com 1st version + */ +#include "stm32f10x.h" +#include + +#ifndef __STM32F10X_I2C_H__ +#define __STM32F10X_I2C_H__ + +#include "stm32f10x.h" +#include "stm32f10x_i2c.h" + +#include "board.h" + + +struct stm32_i2c_bus +{ + struct rt_i2c_bus_device parent; + struct rt_event ev; + I2C_TypeDef *I2C; + struct rt_i2c_msg *msg; + rt_uint32_t msg_cnt; + volatile rt_uint32_t msg_ptr; + volatile rt_uint32_t dptr; + rt_uint32_t wait_stop; +}; + +/* public function list */ +rt_err_t stm32_i2c_register(I2C_TypeDef *I2C, rt_uint32_t bitrate, + const char * i2c_bus_name); + +#endif /*__STM32F10X_I2C_H__*/