aboutsummaryrefslogtreecommitdiffstats
path: root/libmaple/i2c.h
diff options
context:
space:
mode:
authorPerry Hung <iperry@gmail.com>2011-03-21 02:45:58 -0400
committerPerry Hung <iperry@gmail.com>2011-03-21 02:47:53 -0400
commit7241820179bb729d14900676fbff943f7f44cb97 (patch)
treed60a38f908eda00b934b6d3452f6a777c4277be6 /libmaple/i2c.h
parent1591fc9e3f851327c16bbcb88e6abee1706f9cfc (diff)
parentc73306508820705eef4f2cb9f8542acdba599cd8 (diff)
downloadlibrambutan-7241820179bb729d14900676fbff943f7f44cb97.tar.gz
librambutan-7241820179bb729d14900676fbff943f7f44cb97.zip
Merge branch 'i2c-wip' into refactor
Conflicts: examples/test-fsmc.cpp libmaple/rules.mk wirish/boards.h
Diffstat (limited to 'libmaple/i2c.h')
-rw-r--r--libmaple/i2c.h259
1 files changed, 259 insertions, 0 deletions
diff --git a/libmaple/i2c.h b/libmaple/i2c.h
new file mode 100644
index 0000000..21c17c1
--- /dev/null
+++ b/libmaple/i2c.h
@@ -0,0 +1,259 @@
+/* *****************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2010 Perry Hung.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ * ****************************************************************************/
+
+/**
+ * @brief libmaple i2c header
+ */
+
+#ifndef _I2C_H_
+#define _I2C_H_
+
+typedef struct i2c_reg_map {
+ __io uint32 CR1;
+ __io uint32 CR2;
+ __io uint32 OAR1;
+ __io uint32 OAR2;
+ __io uint32 DR;
+ __io uint32 SR1;
+ __io uint32 SR2;
+ __io uint32 CCR;
+ __io uint32 TRISE;
+} i2c_reg_map;
+
+typedef enum i2c_state {
+ I2C_STATE_IDLE,
+ I2C_STATE_XFER_DONE,
+ I2C_STATE_BUSY,
+ I2C_STATE_ERROR = -1
+} i2c_state;
+
+typedef struct i2c_msg {
+ uint16 addr;
+#define I2C_MSG_READ 0x1
+#define I2C_MSG_10BIT_ADDR 0x2
+ uint16 flags;
+ uint16 length;
+ uint16 xferred;
+ uint8 *data;
+} i2c_msg;
+
+typedef struct i2c_dev {
+ i2c_reg_map *regs;
+ gpio_dev *gpio_port;
+ uint8 sda_pin;
+ uint8 scl_pin;
+ uint8 clk_line;
+ uint8 ev_nvic_line;
+ uint8 er_nvic_line;
+ volatile uint8 state;
+ uint16 msgs_left;
+ i2c_msg *msg;
+} i2c_dev;
+
+
+extern i2c_dev* const I2C1;
+
+#define I2C1_BASE (i2c_reg_map*)0x40005400
+#define I2C2_BASE (i2c_reg_map*)0x40005800
+
+/* i2c enable options */
+#define I2C_FAST_MODE 0x1 // 400 khz
+#define I2C_DUTY_16_9 0x2 // 16/9 duty ratio
+
+/* Control register 1 bits */
+#define I2C_CR1_SWRST BIT(15) // Software reset
+#define I2C_CR1_ALERT BIT(13) // SMBus alert
+#define I2C_CR1_PEC BIT(12) // Packet error checking
+#define I2C_CR1_POS BIT(11) // Acknowledge/PEC position
+#define I2C_CR1_ACK BIT(10) // Acknowledge enable
+#define I2C_CR1_START BIT(8) // Start generation
+#define I2C_CR1_STOP BIT(9) // Stop generation
+#define I2C_CR1_PE BIT(0) // Peripheral Enable
+
+/* Control register 2 bits */
+#define I2C_CR2_LAST BIT(12) // DMA last transfer
+#define I2C_CR2_DMAEN BIT(11) // DMA requests enable
+#define I2C_CR2_ITBUFEN BIT(10) // Buffer interrupt enable
+#define I2C_CR2_ITEVTEN BIT(9) // Event interupt enable
+#define I2C_CR2_ITERREN BIT(8) // Error interupt enable
+#define I2C_CR2_FREQ 0xFFF // Peripheral input frequency
+
+/* Clock control register bits */
+#define I2C_CCR_FS BIT(15) // Master mode selection
+#define I2C_CCR_CCR 0xFFF // Clock control bits
+
+/* Status register 1 bits */
+#define I2C_SR1_SB BIT(0) // Start bit
+#define I2C_SR1_ADDR BIT(1) // Address sent/matched
+#define I2C_SR1_BTF BIT(2) // Byte transfer finished
+#define I2C_SR1_ADD10 BIT(3) // 10-bit header sent
+#define I2C_SR1_STOPF BIT(4) // Stop detection
+#define I2C_SR1_RXNE BIT(6) // Data register not empty
+#define I2C_SR1_TXE BIT(7) // Data register empty
+#define I2C_SR1_BERR BIT(8) // Bus error
+#define I2C_SR1_ARLO BIT(9) // Arbitration lost
+#define I2C_SR1_AF BIT(10) // Acknowledge failure
+#define I2C_SR1_OVR BIT(11) // Overrun/underrun
+#define I2C_SR1_PECERR BIT(12) // PEC Error in reception
+#define I2C_SR1_TIMEOUT BIT(14) // Timeout or Tlow error
+#define I2C_SR1_SMBALERT BIT(15) // SMBus alert
+
+/* Status register 2 bits */
+#define I2C_SR2_MSL BIT(0) // Master/slave
+#define I2C_SR2_BUSY BIT(1) // Bus busy
+#define I2C_SR2_TRA BIT(2) // Transmitter/receiver
+#define I2C_SR2_GENCALL BIT(4) // General call address
+#define I2C_SR2_SMBDEFAULT BIT(5) // SMBus device default address
+#define I2C_SR2_SMBHOST BIT(6) // SMBus host header
+#define I2C_SR2_DUALF BIT(7) // Dual flag
+#define I2C_SR2_PEC 0xFF00 // Packet error checking register
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void i2c_master_enable(i2c_dev *dev, uint32 flags);
+int32 i2c_master_xfer(i2c_dev *dev, i2c_msg *msgs, uint16 num);
+
+/*
+ * Low level register twiddling functions
+ */
+
+/**
+ * @brief turn on an i2c peripheral
+ * @param dev i2c device
+ */
+static inline void i2c_peripheral_enable(i2c_dev *dev) {
+ dev->regs->CR1 |= I2C_CR1_PE;
+}
+
+/**
+ * @brief turn off an i2c peripheral
+ * @param dev i2c device
+ */
+static inline void i2c_peripheral_disable(i2c_dev *dev) {
+ dev->regs->CR1 &= ~I2C_CR1_PE;
+}
+
+/**
+ * @brief Fill transmit register
+ * @param dev i2c device
+ * @param byte byte to write
+ */
+static inline void i2c_write(i2c_dev *dev, uint8 byte) {
+ dev->regs->DR = byte;
+}
+
+
+/**
+ * @brief Set input clock frequency, in mhz
+ * @param dev i2c
+ * @param freq frequency in megahertz (2-36)
+ */
+static inline void i2c_set_input_clk(i2c_dev *dev, uint32 freq) {
+ uint32 cr2 = dev->regs->CR2;
+ cr2 &= ~I2C_CR2_FREQ;
+ cr2 |= freq;
+ dev->regs->CR2 = freq;
+}
+
+
+/**
+ * @brief Set i2c clock control register. See RM008
+ * @param dev i2c device
+ * @return
+ * @sideeffect
+ */
+static inline void i2c_set_clk_control(i2c_dev *dev, uint32 val) {
+ uint32 ccr = dev->regs->CCR;
+ ccr &= ~I2C_CCR_CCR;
+ ccr |= val;
+ dev->regs->CCR = ccr;
+}
+
+static inline void i2c_set_fast_mode(i2c_dev *dev) {
+ dev->regs->CCR |= I2C_CCR_FS;
+}
+
+static inline void i2c_set_standard_mode(i2c_dev *dev) {
+ dev->regs->CCR &= ~I2C_CCR_FS;
+}
+
+/**
+ * @brief Set SCL rise time
+ * @param
+ */
+static inline void i2c_set_trise(i2c_dev *dev, uint32 trise) {
+ dev->regs->TRISE = trise;
+}
+
+static inline void i2c_start_condition(i2c_dev *dev) {
+ uint32 cr1;
+ while ((cr1 = dev->regs->CR1) & (I2C_CR1_START |
+ I2C_CR1_STOP |
+ I2C_CR1_PEC)) {
+ ;
+ }
+ dev->regs->CR1 |= I2C_CR1_START;
+}
+
+static inline void i2c_stop_condition(i2c_dev *dev) {
+ uint32 cr1;
+ while ((cr1 = dev->regs->CR1) & (I2C_CR1_START |
+ I2C_CR1_STOP |
+ I2C_CR1_PEC)) {
+ ;
+ }
+ dev->regs->CR1 |= I2C_CR1_STOP;
+}
+
+static inline void i2c_send_slave_addr(i2c_dev *dev, uint32 addr, uint32 rw) {
+ dev->regs->DR = (addr << 1) | rw;
+}
+
+#define I2C_IRQ_ERROR I2C_CR2_ITERREN
+#define I2C_IRQ_EVENT I2C_CR2_ITEVTEN
+#define I2C_IRQ_BUFFER I2C_CR2_ITBUFEN
+static inline void i2c_enable_irq(i2c_dev *dev, uint32 irqs) {
+ dev->regs->CR2 |= irqs;
+}
+
+static inline void i2c_disable_irq(i2c_dev *dev, uint32 irqs) {
+ dev->regs->CR2 &= ~irqs;
+}
+
+static inline void i2c_enable_ack(i2c_dev *dev) {
+ dev->regs->CR1 |= I2C_CR1_ACK;
+}
+
+static inline void i2c_disable_ack(i2c_dev *dev) {
+ dev->regs->CR1 &= ~I2C_CR1_ACK;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+