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/*---------------------------------------------------------------------------*/
48void
49i2c_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 */
60
61 REG(SYS_CTRL_SRI2C) &= ~1; /* Normal position */
62
63 /* Set pins in input */
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/*---------------------------------------------------------------------------*/
90void
92{
93 REG(I2CM_CR) |= 0x10; /* Set MFE bit */
94}
95/*---------------------------------------------------------------------------*/
96void
98{
99 REG(I2CM_CR) &= ~0x10; /* Reset MFE bit */
100}
101/*---------------------------------------------------------------------------*/
102void
103i2c_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/*---------------------------------------------------------------------------*/
110void
111i2c_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/*---------------------------------------------------------------------------*/
120void
122{
123 REG(I2CM_DR) = data;
124}
125/*---------------------------------------------------------------------------*/
126uint8_t
128{
129 return REG(I2CM_DR);
130}
131/*---------------------------------------------------------------------------*/
132void
134{
135 REG(I2CM_CTRL) = cmd;
136 /* Here we need a delay, otherwise the I2C module keep the receiver mode */
138}
139/*---------------------------------------------------------------------------*/
140uint8_t
142{
143 return REG(I2CM_STAT) & I2CM_STAT_BUSY;
144}
145/*---------------------------------------------------------------------------*/
146uint8_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/*---------------------------------------------------------------------------*/
158uint8_t
159i2c_single_send(uint8_t slave_addr, uint8_t data)
160{
161 i2c_master_set_slave_address(slave_addr, I2C_SEND);
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/*---------------------------------------------------------------------------*/
171uint8_t
172i2c_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/*---------------------------------------------------------------------------*/
187uint8_t
188i2c_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/*---------------------------------------------------------------------------*/
217uint8_t
218i2c_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/** @} */
void clock_delay_usec(uint16_t dt)
Delay a given number of microseconds.
Definition: clock.c:150
#define GPIO_PIN_MASK(PIN)
Converts a pin number to a pin mask.
Definition: gpio.h:320
#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
#define GPIO_PORT_TO_BASE(PORT)
Converts a port number to the port base address.
Definition: gpio.h:328
#define GPIO_SET_INPUT(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to input.
Definition: gpio.h:78
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
void i2c_set_frequency(uint32_t freq)
Initialize I2C peripheral clock with given frequency.
Definition: i2c.c:103
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
void i2c_master_data_put(uint8_t data)
Prepare data to be transmitted.
Definition: i2c.c:121
uint8_t i2c_master_data_get(void)
Return received data from I2C.
Definition: i2c.c:127
uint8_t i2c_master_busy(void)
Return the busy state of I2C module.
Definition: i2c.c:141
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_enable(void)
Enable master I2C module.
Definition: i2c.c:91
void i2c_master_command(uint8_t cmd)
Control the state of the master module for send and receive operations.
Definition: i2c.c:133
void i2c_master_disable(void)
Disable master I2C module.
Definition: i2c.c:97
uint8_t i2c_master_error(void)
Return the status register if error occurred during last communication.
Definition: i2c.c:147
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
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
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
#define IOC_I2CMSSDA
I2C SDA.
Definition: ioc.h:136
#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 IOC_I2CMSSCL
I2C SCL.
Definition: ioc.h:137
void ioc_set_over(uint8_t port, uint8_t pin, uint8_t over)
Set Port:Pin override function.
Definition: ioc.c:54
#define IOC_OVERRIDE_DIS
Override Disabled.
Definition: ioc.h:226
#define SYS_CTRL_SRI2C
I2C clocks - reset control.
Definition: sys-ctrl.h:82
#define SYS_CTRL_RCGCI2C
I2C clocks - active mode.
Definition: sys-ctrl.h:79
Header file for the cc2538 System Control driver.