Contiki-NG
i2c.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015, Mehdi Migault
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  *
14  * 3. Neither the name of the copyright holder nor the names of its
15  * contributors may be used to endorse or promote products derived
16  * from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29  * OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 /**
32  * \addtogroup cc2538-i2c cc2538 I2C Control
33  * @{
34  *
35  * \file
36  * Implementation file of the I2C Control module
37  *
38  * \author
39  * Mehdi Migault
40  */
41 
42 #include "i2c.h"
43 
44 #include <stdint.h>
45 #include "clock.h"
46 #include "sys-ctrl.h"
47 /*---------------------------------------------------------------------------*/
48 void
49 i2c_init(uint8_t port_sda, uint8_t pin_sda, uint8_t port_scl, uint8_t pin_scl,
50  uint32_t bus_speed)
51 {
52  /* Enable I2C clock in different modes */
53  REG(SYS_CTRL_RCGCI2C) |= 1; /* Run mode */
54 
55  /* Reset I2C peripheral */
56  REG(SYS_CTRL_SRI2C) |= 1; /* Reset position */
57 
58  /* Delay for a little bit */
59  clock_delay_usec(50);
60 
61  REG(SYS_CTRL_SRI2C) &= ~1; /* Normal position */
62 
63  /* Set pins in input */
64  GPIO_SET_INPUT(GPIO_PORT_TO_BASE(port_sda), GPIO_PIN_MASK(pin_sda));
65  GPIO_SET_INPUT(GPIO_PORT_TO_BASE(port_scl), GPIO_PIN_MASK(pin_scl));
66 
67  /* Set peripheral control for the pins */
70 
71  /* Set the pad to no drive type */
72  ioc_set_over(port_sda, pin_sda, IOC_OVERRIDE_DIS);
73  ioc_set_over(port_scl, pin_scl, IOC_OVERRIDE_DIS);
74 
75  /* Set pins as peripheral inputs */
76  REG(IOC_I2CMSSDA) = ioc_input_sel(port_sda, pin_sda);
77  REG(IOC_I2CMSSCL) = ioc_input_sel(port_scl, pin_scl);
78 
79  /* Set pins as peripheral outputs */
80  ioc_set_sel(port_sda, pin_sda, IOC_PXX_SEL_I2C_CMSSDA);
81  ioc_set_sel(port_scl, pin_scl, IOC_PXX_SEL_I2C_CMSSCL);
82 
83  /* Enable the I2C master module */
85 
86  /* t the master clock frequency */
87  i2c_set_frequency(bus_speed);
88 }
89 /*---------------------------------------------------------------------------*/
90 void
92 {
93  REG(I2CM_CR) |= 0x10; /* Set MFE bit */
94 }
95 /*---------------------------------------------------------------------------*/
96 void
98 {
99  REG(I2CM_CR) &= ~0x10; /* Reset MFE bit */
100 }
101 /*---------------------------------------------------------------------------*/
102 void
103 i2c_set_frequency(uint32_t freq)
104 {
105  /* Peripheral clock setting, using the system clock */
106  REG(I2CM_TPR) = ((SYS_CTRL_SYS_CLOCK + (2 * 10 * freq) - 1) /
107  (2 * 10 * freq)) - 1;
108 }
109 /*---------------------------------------------------------------------------*/
110 void
111 i2c_master_set_slave_address(uint8_t slave_addr, uint8_t access_mode)
112 {
113  if(access_mode) {
114  REG(I2CM_SA) = ((slave_addr << 1) | 1);
115  } else {
116  REG(I2CM_SA) = (slave_addr << 1);
117  }
118 }
119 /*---------------------------------------------------------------------------*/
120 void
121 i2c_master_data_put(uint8_t data)
122 {
123  REG(I2CM_DR) = data;
124 }
125 /*---------------------------------------------------------------------------*/
126 uint8_t
128 {
129  return REG(I2CM_DR);
130 }
131 /*---------------------------------------------------------------------------*/
132 void
133 i2c_master_command(uint8_t cmd)
134 {
135  REG(I2CM_CTRL) = cmd;
136  /* Here we need a delay, otherwise the I2C module keep the receiver mode */
137  clock_delay_usec(1);
138 }
139 /*---------------------------------------------------------------------------*/
140 uint8_t
142 {
143  return REG(I2CM_STAT) & I2CM_STAT_BUSY;
144 }
145 /*---------------------------------------------------------------------------*/
146 uint8_t
148 {
149  uint8_t temp = REG(I2CM_STAT); /* Get all status */
150  if(temp & I2CM_STAT_BUSY) { /* No valid if BUSY bit is set */
151  return I2C_MASTER_ERR_NONE;
152  } else if(temp & (I2CM_STAT_ERROR | I2CM_STAT_ARBLST)) {
153  return temp; /* Compare later */
154  }
155  return I2C_MASTER_ERR_NONE;
156 }
157 /*---------------------------------------------------------------------------*/
158 uint8_t
159 i2c_single_send(uint8_t slave_addr, uint8_t data)
160 {
161  i2c_master_set_slave_address(slave_addr, I2C_SEND);
162  i2c_master_data_put(data);
163  i2c_master_command(I2C_MASTER_CMD_SINGLE_SEND);
164 
165  while(i2c_master_busy());
166 
167  /* Return the STAT register of I2C module if error occured, I2C_MASTER_ERR_NONE otherwise */
168  return i2c_master_error();
169 }
170 /*---------------------------------------------------------------------------*/
171 uint8_t
172 i2c_single_receive(uint8_t slave_addr, uint8_t *data)
173 {
174  uint8_t temp;
175 
176  i2c_master_set_slave_address(slave_addr, I2C_RECEIVE);
177  i2c_master_command(I2C_MASTER_CMD_SINGLE_RECEIVE);
178 
179  while(i2c_master_busy());
180  temp = i2c_master_error();
181  if(temp == I2C_MASTER_ERR_NONE) {
182  *data = i2c_master_data_get();
183  }
184  return temp;
185 }
186 /*---------------------------------------------------------------------------*/
187 uint8_t
188 i2c_burst_send(uint8_t slave_addr, uint8_t *data, uint8_t len)
189 {
190  uint8_t sent;
191  if((len == 0) || (data == NULL)) {
192  return I2CM_STAT_INVALID;
193  }
194  if(len == 1) {
195  return i2c_single_send(slave_addr, data[0]);
196  }
197  i2c_master_set_slave_address(slave_addr, I2C_SEND);
198  i2c_master_data_put(data[0]);
199  i2c_master_command(I2C_MASTER_CMD_BURST_SEND_START);
200  while(i2c_master_busy());
201  if(i2c_master_error() == I2C_MASTER_ERR_NONE) {
202  for(sent = 1; sent <= (len - 2); sent++) {
203  i2c_master_data_put(data[sent]);
204  i2c_master_command(I2C_MASTER_CMD_BURST_SEND_CONT);
205  while(i2c_master_busy());
206  }
207  /* This should be the last byte, stop sending */
208  i2c_master_data_put(data[len - 1]);
209  i2c_master_command(I2C_MASTER_CMD_BURST_SEND_FINISH);
210  while(i2c_master_busy());
211  }
212 
213  /* Return the STAT register of I2C module if error occurred, I2C_MASTER_ERR_NONE otherwise */
214  return i2c_master_error();
215 }
216 /*---------------------------------------------------------------------------*/
217 uint8_t
218 i2c_burst_receive(uint8_t slave_addr, uint8_t *data, uint8_t len)
219 {
220  uint8_t recv = 0;
221  if((len == 0) || data == NULL) {
222  return I2CM_STAT_INVALID;
223  }
224  if(len == 1) {
225  return i2c_single_receive(slave_addr, &data[0]);
226  }
227  i2c_master_set_slave_address(slave_addr, I2C_RECEIVE);
228  i2c_master_command(I2C_MASTER_CMD_BURST_RECEIVE_START);
229  while(i2c_master_busy());
230  if(i2c_master_error() == I2C_MASTER_ERR_NONE) {
231  data[0] = i2c_master_data_get();
232  /* If we got 2 or more bytes pending to be received, keep going*/
233  for(recv = 1; recv <= (len - 2); recv++) {
234  i2c_master_command(I2C_MASTER_CMD_BURST_RECEIVE_CONT);
235  while(i2c_master_busy());
236  data[recv] = i2c_master_data_get();
237  }
238  /* This should be the last byte, stop receiving */
239  i2c_master_command(I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
240  while(i2c_master_busy());
241  data[len - 1] = i2c_master_data_get();
242  }
243  return i2c_master_error();
244 }
245 /*---------------------------------------------------------------------------*/
246 /** @} */
uint8_t i2c_master_data_get(void)
Return received data from I2C.
Definition: i2c.c:127
#define SYS_CTRL_RCGCI2C
I2C clocks - active mode.
Definition: sys-ctrl.h:79
uint8_t i2c_master_busy(void)
Return the busy state of I2C module.
Definition: i2c.c:141
Header file for the cc2538 System Control driver.
void i2c_set_frequency(uint32_t freq)
Initialize I2C peripheral clock with given frequency.
Definition: i2c.c:103
void i2c_master_data_put(uint8_t data)
Prepare data to be transmitted.
Definition: i2c.c:121
uint8_t i2c_burst_send(uint8_t slave_addr, uint8_t *data, uint8_t len)
Perform all operations to send multiple bytes to a slave.
Definition: i2c.c:188
#define IOC_I2CMSSDA
I2C SDA.
Definition: ioc.h:136
void clock_delay_usec(uint16_t dt)
Delay a given number of microseconds.
Definition: clock.c:150
#define IOC_OVERRIDE_DIS
Override Disabled.
Definition: ioc.h:226
#define GPIO_PIN_MASK(PIN)
Converts a pin number to a pin mask.
Definition: gpio.h:320
#define IOC_I2CMSSCL
I2C SCL.
Definition: ioc.h:137
uint8_t i2c_master_error(void)
Return the status register if error occurred during last communication.
Definition: i2c.c:147
void i2c_init(uint8_t port_sda, uint8_t pin_sda, uint8_t port_scl, uint8_t pin_scl, uint32_t bus_speed)
Initialize the I2C peripheral and pins.
Definition: i2c.c:49
void i2c_master_disable(void)
Disable master I2C module.
Definition: i2c.c:97
void ioc_set_over(uint8_t port, uint8_t pin, uint8_t over)
Set Port:Pin override function.
Definition: ioc.c:54
#define GPIO_SET_INPUT(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to input.
Definition: gpio.h:78
void i2c_master_command(uint8_t cmd)
Control the state of the master module for send and receive operations.
Definition: i2c.c:133
uint8_t i2c_burst_receive(uint8_t slave_addr, uint8_t *data, uint8_t len)
Perform all operations to receive multiple bytes from a slave.
Definition: i2c.c:218
void i2c_master_set_slave_address(uint8_t slave_addr, uint8_t access_mode)
Set the address of slave and access mode for the next I2C communication.
Definition: i2c.c:111
#define GPIO_PERIPHERAL_CONTROL(PORT_BASE, PIN_MASK)
Configure the pin to be under peripheral control with PIN_MASK of port with PORT_BASE.
Definition: gpio.h:250
uint8_t i2c_single_receive(uint8_t slave_addr, uint8_t *data)
Perform all operations to receive a byte from a slave.
Definition: i2c.c:172
#define ioc_input_sel(port, pin)
Generates an IOC_INPUT_SEL_PXn value from a port/pin number.
Definition: ioc.h:286
void ioc_set_sel(uint8_t port, uint8_t pin, uint8_t sel)
Function select for Port:Pin.
Definition: ioc.c:66
#define GPIO_PORT_TO_BASE(PORT)
Converts a port number to the port base address.
Definition: gpio.h:328
#define SYS_CTRL_SRI2C
I2C clocks - reset control.
Definition: sys-ctrl.h:82
uint8_t i2c_single_send(uint8_t slave_addr, uint8_t data)
Perform all operations to send a byte to a slave.
Definition: i2c.c:159
void i2c_master_enable(void)
Enable master I2C module.
Definition: i2c.c:91