c581b71a92442a0ce88bfd0d8911e3d1ffbc4323
[bertos.git] / bertos / cpu / cortex-m3 / drv / i2c_lm3s.c
1 /**
2  * \file
3  * <!--
4  * This file is part of BeRTOS.
5  *
6  * Bertos is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  * As a special exception, you may use this file as part of a free software
21  * library without restriction.  Specifically, if other files instantiate
22  * templates or use macros or inline functions from this file, or you compile
23  * this file and link it with other files to produce an executable, this
24  * file does not by itself cause the resulting executable to be covered by
25  * the GNU General Public License.  This exception does not however
26  * invalidate any other reasons why the executable file might be covered by
27  * the GNU General Public License.
28  *
29  * Copyright 2010 Develer S.r.l. (http://www.develer.com/)
30  *
31  * -->
32  *
33  * \brief Driver for the LM3S I2C (implementation)
34  *
35  */
36
37 #include "cfg/cfg_i2c.h"
38
39 #define LOG_LEVEL  I2C_LOG_LEVEL
40 #define LOG_FORMAT I2C_LOG_FORMAT
41
42 #include <cfg/log.h>
43
44 #include <cfg/debug.h>
45 #include <cfg/macros.h> // BV()
46 #include <cfg/module.h>
47
48 #include <cpu/detect.h>
49 #include <cpu/irq.h>
50
51 #include <io/cm3_types.h>
52 #include <io/lm3s.h>
53
54 #include <drv/timer.h>
55 #include <drv/i2c.h>
56 #include <drv/gpio_lm3s.h>
57 #include <drv/clock_lm3s.h>
58
59
60 #define I2C     I2C0_MASTER_BASE
61
62 /**
63  * Send START condition on the bus.
64  *
65  * \return true on success, false otherwise.
66  */
67 static bool i2c_builtin_start(void)
68 {
69         return true;
70 }
71
72
73 /**
74  * Send START condition and select slave for write.
75  * \c id is the device id comprehensive of address left shifted by 1.
76  * The LSB of \c id is ignored and reset to 0 for write operation.
77  *
78  * \return true on success, false otherwise.
79  */
80 bool i2c_builtin_start_w(uint8_t id)
81 {
82
83         HWREG(I2C + I2C_O_MSA) = (id << 1) | BV(I2C_MSA_ADDS);
84
85         return true;
86 }
87
88
89 /**
90  * Send START condition and select slave for read.
91  * \c id is the device id comprehensive of address left shifted by 1.
92  * The LSB of \c id is ignored and set to 1 for read operation.
93  *
94  * \return true on success, false otherwise.
95  */
96 bool i2c_builtin_start_r(uint8_t id)
97 {
98         HWREG(I2C + I2C_O_MSA) = (id << 1) | BV(I2C_MSA_ADDR);
99
100         return true;
101 }
102
103
104 /**
105  * Send STOP condition.
106  */
107 void i2c_builtin_stop(void)
108 {
109
110 }
111
112
113 /**
114  * Put a single byte in master transmitter mode
115  * to the selected slave device through the TWI bus.
116  *
117  * \return true on success, false on error.
118  */
119 bool i2c_builtin_put(const uint8_t data)
120 {
121         return true;
122 }
123
124 /**
125  * Get 1 byte from slave in master transmitter mode
126  * to the selected slave device through the I2C bus.
127  * If \a ack is true issue a ACK after getting the byte,
128  * otherwise a NACK is issued.
129  *
130  * \return the byte read if ok, EOF on errors.
131  */
132 int i2c_builtin_get(bool ack)
133 {
134
135         if (ack)
136         {
137
138         }
139         else
140         {
141
142         }
143
144         /* avoid sign extension */
145         return 0;
146 }
147
148
149 INLINE bool check_i2cStatus(uint32_t base)
150 {
151         ticks_t start = timer_clock();
152
153         while (true)
154         {
155                 while(true)
156                 {
157                         uint32_t status = HWREG(base + I2C_O_MCS);
158
159                         if (status & I2C_MCS_ADRACK)
160                                 if (timer_clock() - start > ms_to_ticks(CONFIG_I2C_START_TIMEOUT))
161                                 {
162                                         LOG_ERR("Timeout on I2C_START\n");
163                                                 break;
164                                 }
165
166                         if (status & I2C_MCS_BUSY)
167                                 continue;
168                         else
169                                 return true;
170                 }
171         }
172
173         return false;
174 }
175
176 bool i2c_send(const void *_buf, size_t count)
177 {
178         const uint8_t *buf = (const uint8_t *)_buf;
179
180         if (count == 1)
181         {
182                 HWREG(I2C + I2C_O_MDR) = *buf++;
183
184                 HWREG(I2C + I2C_O_MCS) = I2C_MASTER_CMD_SINGLE_SEND;
185
186                 if ( !check_i2cStatus(I2C) )
187                         return false;
188
189                 count--;
190         }
191
192         if (count > 1)
193         {
194                 HWREG(I2C + I2C_O_MDR) = *buf++;
195                 count--;
196
197                 HWREG(I2C + I2C_O_MCS) = I2C_MASTER_CMD_BURST_SEND_START;
198
199                 if ( !check_i2cStatus(I2C) )
200                         return false;
201
202                 while(count)
203                 {
204                         HWREG(I2C + I2C_O_MDR) = *buf++;
205                         HWREG(I2C + I2C_O_MCS) = I2C_MASTER_CMD_BURST_SEND_CONT;
206
207                         if ( !check_i2cStatus(I2C) )
208                                 return false;
209
210                         count--;
211                 }
212
213                 HWREG(I2C + I2C_O_MCS) = I2C_MASTER_CMD_BURST_SEND_FINISH;
214
215                 if ( !check_i2cStatus(I2C) )
216                         return false;
217
218         }
219
220         return true;
221 }
222
223 /**
224  * In order to read bytes from the i2c we should make some tricks.
225  * This because the silicon manage automatically the NACK on last byte, so to read
226  * one, two or three byte we should manage separately these cases.
227  */
228 bool i2c_recv(void *_buf, size_t count)
229 {
230         uint8_t *buf = (const uint8_t *)_buf;
231
232         if (count == 1)
233         {
234                 HWREG(I2C + I2C_O_MCS) = I2C_MASTER_CMD_SINGLE_RECEIVE;
235
236                 if ( !check_i2cStatus(I2C) )
237                         return false;
238
239                 *buf++ = HWREGB(I2C + I2C_O_MDR);
240                 count--;
241         }
242
243         if (count > 1)
244         {
245                 HWREG(I2C + I2C_O_MCS) = I2C_MASTER_CMD_BURST_RECEIVE_START;
246
247                 if ( !check_i2cStatus(I2C) )
248                         return false;
249
250                 while(count)
251                 {
252                         *buf++ = HWREGB(I2C + I2C_O_MDR);
253
254                         HWREG(I2C + I2C_O_MCS) = I2C_MASTER_CMD_BURST_RECEIVE_CONT;
255
256                         if ( !check_i2cStatus(I2C) )
257                                 return false;
258
259                         count--;
260                 }
261
262                 HWREG(I2C + I2C_O_MCS) = I2C_MASTER_CMD_BURST_RECEIVE_FINISH;
263
264                 if ( !check_i2cStatus(I2C) )
265                         return false;
266
267                 *buf++ = HWREGB(I2C + I2C_O_MDR);
268                 count--;
269         }
270
271         return true;
272 }
273 MOD_DEFINE(i2c);
274
275 /**
276  * Initialize I2C module.
277  */
278 void i2c_builtin_init(void)
279 {
280
281         /* Enable the peripheral clock */
282         SYSCTL_RCGC1_R |= SYSCTL_RCGC1_I2C0;
283         SYSCTL_RCGC2_R |= SYSCTL_RCGC2_GPIOB;
284
285
286         /* Configure GPIO pins to work as I2C pins */
287         lm3s_gpioPinConfig(GPIO_PORTB_BASE, GPIO_I2C0_SCL_PIN | GPIO_I2C0_SDA_PIN,
288                         GPIO_DIR_MODE_HW, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_OD);
289
290         //Enable I2C in master mode
291         HWREG(I2C + I2C_O_MCR) |= I2C_MCR_MFE;
292
293     /*
294          * Compute the clock divider that achieves the fastest speed less than or
295      * equal to the desired speed.  The numerator is biased to favor a larger
296      * clock divider so that the resulting clock is always less than or equal
297      * to the desired clock, never greater.
298          */
299     HWREG(I2C + I2C_O_MTPR) = ((CPU_FREQ + (2 * 10 * CONFIG_I2C_FREQ) - 1) / (2 * 10 * CONFIG_I2C_FREQ)) - 1;
300
301         MOD_INIT(i2c);
302 }