]> git.sur5r.net Git - freertos/blob - Demo/CORTEX_AT91SAM3U256_IAR/AT91Lib/peripherals/twi/twi.c
Start to re-arrange files to include FreeRTOS+ in main download.
[freertos] / Demo / CORTEX_AT91SAM3U256_IAR / AT91Lib / peripherals / twi / twi.c
1 /* ----------------------------------------------------------------------------\r
2  *         ATMEL Microcontroller Software Support\r
3  * ----------------------------------------------------------------------------\r
4  * Copyright (c) 2008, Atmel Corporation\r
5  *\r
6  * All rights reserved.\r
7  *\r
8  * Redistribution and use in source and binary forms, with or without\r
9  * modification, are permitted provided that the following conditions are met:\r
10  *\r
11  * - Redistributions of source code must retain the above copyright notice,\r
12  * this list of conditions and the disclaimer below.\r
13  *\r
14  * Atmel's name may not be used to endorse or promote products derived from\r
15  * this software without specific prior written permission.\r
16  *\r
17  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR\r
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
20  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,\r
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
23  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
24  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
25  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
26  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
27  * ----------------------------------------------------------------------------\r
28  */\r
29 \r
30 //------------------------------------------------------------------------------\r
31 /// \unit\r
32 ///\r
33 /// !Purpose\r
34 ///\r
35 /// Interface for configuration the Two Wire Interface (TWI) peripheral.\r
36 ///\r
37 /// !Usage\r
38 ///\r
39 /// -# Configures a TWI peripheral to operate in master mode, at the given\r
40 /// frequency (in Hz) using TWI_Configure().\r
41 /// -# Sends a STOP condition on the TWI using TWI_Stop().\r
42 /// -# Starts a read operation on the TWI bus with the specified slave using\r
43 /// TWI_StartRead(). Data must then be read using TWI_ReadByte() whenever\r
44 /// a byte is available (poll using TWI_ByteReceived()).\r
45 /// -# Starts a write operation on the TWI to access the selected slave using\r
46 /// TWI_StartWrite(). A byte of data must be provided to start the write;\r
47 /// other bytes are written next.\r
48 /// -# Sends a byte of data to one of the TWI slaves on the bus using TWI_WriteByte().\r
49 /// This function must be called once before TWI_StartWrite() with the first byte of data\r
50 /// to send, then it shall be called repeatedly after that to send the remaining bytes.\r
51 /// -# Check if a byte has been received and can be read on the given TWI\r
52 /// peripheral using TWI_ByteReceived().\r
53 /// Check if a byte has been sent using TWI_ByteSent().\r
54 /// -# Check if the current transmission is complete (the STOP has been sent)\r
55 /// using TWI_TransferComplete().\r
56 /// -# Enables & disable the selected interrupts sources on a TWI peripheral\r
57 /// using TWI_EnableIt() and TWI_DisableIt().\r
58 /// -# Get current status register of the given TWI peripheral using\r
59 /// TWI_GetStatus(). Get current status register of the given TWI peripheral, but\r
60 /// masking interrupt sources which are not currently enabled using\r
61 /// TWI_GetMaskedStatus().\r
62 //------------------------------------------------------------------------------\r
63 \r
64 \r
65 //------------------------------------------------------------------------------\r
66 //         Headers\r
67 //------------------------------------------------------------------------------\r
68 \r
69 #include "twi.h"\r
70 #include <utility/math.h>\r
71 #include <utility/assert.h>\r
72 #include <utility/trace.h>\r
73 \r
74 //------------------------------------------------------------------------------\r
75 //         Global functions\r
76 //------------------------------------------------------------------------------\r
77 \r
78 //------------------------------------------------------------------------------\r
79 /// Configures a TWI peripheral to operate in master mode, at the given\r
80 /// frequency (in Hz). The duty cycle of the TWI clock is set to 50%.\r
81 /// \param pTwi  Pointer to an AT91S_TWI instance.\r
82 /// \param twck  Desired TWI clock frequency.\r
83 /// \param mck  Master clock frequency.\r
84 //------------------------------------------------------------------------------\r
85 void TWI_ConfigureMaster(AT91S_TWI *pTwi, unsigned int twck, unsigned int mck)\r
86 {\r
87     unsigned int ckdiv = 0;\r
88     unsigned int cldiv;\r
89     unsigned char ok = 0;\r
90 \r
91     TRACE_DEBUG("TWI_ConfigureMaster()\n\r");\r
92     SANITY_CHECK(pTwi);\r
93 \r
94 #ifdef AT91C_TWI_SVEN  // TWI slave\r
95     // SVEN: TWI Slave Mode Enabled\r
96     pTwi->TWI_CR = AT91C_TWI_SVEN;\r
97 #endif\r
98     // Reset the TWI\r
99     pTwi->TWI_CR = AT91C_TWI_SWRST;\r
100     pTwi->TWI_RHR;\r
101 \r
102     // TWI Slave Mode Disabled, TWI Master Mode Disabled\r
103 #ifdef AT91C_TWI_SVEN  // TWI slave\r
104     pTwi->TWI_CR = AT91C_TWI_SVDIS;\r
105 #endif\r
106     pTwi->TWI_CR = AT91C_TWI_MSDIS;\r
107 \r
108     // Set master mode\r
109     pTwi->TWI_CR = AT91C_TWI_MSEN;\r
110 \r
111     // Configure clock\r
112     while (!ok) {\r
113         cldiv = ((mck / (2 * twck)) - 3) / power(2, ckdiv);\r
114         if (cldiv <= 255) {\r
115 \r
116             ok = 1;\r
117         }\r
118         else {\r
119 \r
120             ckdiv++;\r
121         }\r
122     }\r
123 \r
124     ASSERT(ckdiv < 8, "-F- Cannot find valid TWI clock parameters\n\r");\r
125     TRACE_DEBUG("Using CKDIV = %u and CLDIV/CHDIV = %u\n\r", ckdiv, cldiv);\r
126     pTwi->TWI_CWGR = 0;\r
127     pTwi->TWI_CWGR = (ckdiv << 16) | (cldiv << 8) | cldiv;\r
128 }\r
129 \r
130 \r
131 \r
132 #ifdef AT91C_TWI_SVEN  // TWI slave\r
133 //------------------------------------------------------------------------------\r
134 /// Configures a TWI peripheral to operate in slave mode\r
135 /// \param pTwi  Pointer to an AT91S_TWI instance.\r
136 //------------------------------------------------------------------------------\r
137 void TWI_ConfigureSlave(AT91S_TWI *pTwi, unsigned char slaveAddress)\r
138 {\r
139     unsigned int i;\r
140 \r
141     // TWI software reset\r
142     pTwi->TWI_CR = AT91C_TWI_SWRST;\r
143     pTwi->TWI_RHR;\r
144 \r
145     // Wait at least 10 ms\r
146     for (i=0; i < 1000000; i++);\r
147 \r
148     // TWI Slave Mode Disabled, TWI Master Mode Disabled\r
149     pTwi->TWI_CR = AT91C_TWI_SVDIS | AT91C_TWI_MSDIS;\r
150 \r
151     // Slave Address\r
152     pTwi->TWI_SMR = 0;\r
153     pTwi->TWI_SMR = (slaveAddress << 16) & AT91C_TWI_SADR;\r
154 \r
155     // SVEN: TWI Slave Mode Enabled\r
156     pTwi->TWI_CR = AT91C_TWI_SVEN;\r
157 \r
158     // Wait at least 10 ms\r
159     for (i=0; i < 1000000; i++);\r
160     ASSERT( (pTwi->TWI_CR & AT91C_TWI_SVDIS)!=AT91C_TWI_SVDIS, "Problem slave mode");\r
161 }\r
162 #endif\r
163 \r
164 //------------------------------------------------------------------------------\r
165 /// Sends a STOP condition on the TWI.\r
166 /// \param pTwi  Pointer to an AT91S_TWI instance.\r
167 //------------------------------------------------------------------------------\r
168 void TWI_Stop(AT91S_TWI *pTwi)\r
169 {\r
170     SANITY_CHECK(pTwi);\r
171 \r
172     pTwi->TWI_CR = AT91C_TWI_STOP;\r
173 }\r
174 \r
175 //------------------------------------------------------------------------------\r
176 /// Starts a read operation on the TWI bus with the specified slave, and returns\r
177 /// immediately. Data must then be read using TWI_ReadByte() whenever a byte is\r
178 /// available (poll using TWI_ByteReceived()).\r
179 /// \param pTwi  Pointer to an AT91S_TWI instance.\r
180 /// \param address  Slave address on the bus.\r
181 /// \param iaddress  Optional internal address bytes.\r
182 /// \param isize  Number of internal address bytes.\r
183 //-----------------------------------------------------------------------------\r
184 void TWI_StartRead(\r
185     AT91S_TWI *pTwi,\r
186     unsigned char address,\r
187     unsigned int iaddress,\r
188     unsigned char isize)\r
189 {\r
190     //TRACE_DEBUG("TWI_StartRead()\n\r");\r
191     SANITY_CHECK(pTwi);\r
192     SANITY_CHECK((address & 0x80) == 0);\r
193     SANITY_CHECK((iaddress & 0xFF000000) == 0);\r
194     SANITY_CHECK(isize < 4);\r
195 \r
196     // Set slave address and number of internal address bytes\r
197     pTwi->TWI_MMR = 0;\r
198     pTwi->TWI_MMR = (isize << 8) | AT91C_TWI_MREAD | (address << 16);\r
199 \r
200     // Set internal address bytes\r
201     pTwi->TWI_IADR = 0;\r
202     pTwi->TWI_IADR = iaddress;\r
203 \r
204     // Send START condition\r
205     pTwi->TWI_CR = AT91C_TWI_START;\r
206 }\r
207 \r
208 //-----------------------------------------------------------------------------\r
209 /// Reads a byte from the TWI bus. The read operation must have been started\r
210 /// using TWI_StartRead() and a byte must be available (check with\r
211 /// TWI_ByteReceived()).\r
212 /// Returns the byte read.\r
213 /// \param pTwi  Pointer to an AT91S_TWI instance.\r
214 //-----------------------------------------------------------------------------\r
215 unsigned char TWI_ReadByte(AT91S_TWI *pTwi)\r
216 {\r
217     SANITY_CHECK(pTwi);\r
218 \r
219     return pTwi->TWI_RHR;\r
220 }\r
221 \r
222 //-----------------------------------------------------------------------------\r
223 /// Sends a byte of data to one of the TWI slaves on the bus. This function\r
224 /// must be called once before TWI_StartWrite() with the first byte of data\r
225 /// to send, then it shall be called repeatedly after that to send the\r
226 /// remaining bytes.\r
227 /// \param pTwi  Pointer to an AT91S_TWI instance.\r
228 /// \param byte  Byte to send.\r
229 //-----------------------------------------------------------------------------\r
230 void TWI_WriteByte(AT91S_TWI *pTwi, unsigned char byte)\r
231 {\r
232     SANITY_CHECK(pTwi);\r
233 \r
234     pTwi->TWI_THR = byte;\r
235 }\r
236 \r
237 //-----------------------------------------------------------------------------\r
238 /// Starts a write operation on the TWI to access the selected slave, then\r
239 /// returns immediately. A byte of data must be provided to start the write;\r
240 /// other bytes are written next.\r
241 /// \param pTwi  Pointer to an AT91S_TWI instance.\r
242 /// \param address  Address of slave to acccess on the bus.\r
243 /// \param iaddress  Optional slave internal address.\r
244 /// \param isize  Number of internal address bytes.\r
245 /// \param byte  First byte to send.\r
246 //-----------------------------------------------------------------------------\r
247 void TWI_StartWrite(\r
248     AT91S_TWI *pTwi,\r
249     unsigned char address,\r
250     unsigned int iaddress,\r
251     unsigned char isize,\r
252     unsigned char byte)\r
253 {\r
254     //TRACE_DEBUG("TWI_StartWrite()\n\r");\r
255     SANITY_CHECK(pTwi);\r
256     SANITY_CHECK((address & 0x80) == 0);\r
257     SANITY_CHECK((iaddress & 0xFF000000) == 0);\r
258     SANITY_CHECK(isize < 4);\r
259 \r
260     // Set slave address and number of internal address bytes\r
261     pTwi->TWI_MMR = 0;\r
262     pTwi->TWI_MMR = (isize << 8) | (address << 16);\r
263 \r
264     // Set internal address bytes\r
265     pTwi->TWI_IADR = 0;\r
266     pTwi->TWI_IADR = iaddress;\r
267 \r
268     // Write first byte to send\r
269     TWI_WriteByte(pTwi, byte);\r
270 }\r
271 \r
272 //-----------------------------------------------------------------------------\r
273 /// Returns 1 if a byte has been received and can be read on the given TWI\r
274 /// peripheral; otherwise, returns 0. This function resets the status register\r
275 /// of the TWI.\r
276 /// \param pTwi  Pointer to an AT91S_TWI instance.\r
277 //-----------------------------------------------------------------------------\r
278 unsigned char TWI_ByteReceived(AT91S_TWI *pTwi)\r
279 {\r
280     return ((pTwi->TWI_SR & AT91C_TWI_RXRDY) == AT91C_TWI_RXRDY);\r
281 }\r
282 \r
283 //-----------------------------------------------------------------------------\r
284 /// Returns 1 if a byte has been sent, so another one can be stored for\r
285 /// transmission; otherwise returns 0. This function clears the status register\r
286 /// of the TWI.\r
287 /// \param pTwi  Pointer to an AT91S_TWI instance.\r
288 //-----------------------------------------------------------------------------\r
289 unsigned char TWI_ByteSent(AT91S_TWI *pTwi)\r
290 {\r
291     return ((pTwi->TWI_SR & AT91C_TWI_TXRDY) == AT91C_TWI_TXRDY);\r
292 }\r
293 \r
294 //-----------------------------------------------------------------------------\r
295 /// Returns 1 if the current transmission is complete (the STOP has been sent);\r
296 /// otherwise returns 0.\r
297 /// \param pTwi  Pointer to an AT91S_TWI instance.\r
298 //-----------------------------------------------------------------------------\r
299 unsigned char TWI_TransferComplete(AT91S_TWI *pTwi)\r
300 {\r
301     return ((pTwi->TWI_SR & AT91C_TWI_TXCOMP) == AT91C_TWI_TXCOMP);\r
302 }\r
303 \r
304 //-----------------------------------------------------------------------------\r
305 /// Enables the selected interrupts sources on a TWI peripheral.\r
306 /// \param pTwi  Pointer to an AT91S_TWI instance.\r
307 /// \param sources  Bitwise OR of selected interrupt sources.\r
308 //-----------------------------------------------------------------------------\r
309 void TWI_EnableIt(AT91S_TWI *pTwi, unsigned int sources)\r
310 {\r
311     SANITY_CHECK(pTwi);\r
312     SANITY_CHECK((sources & 0xFFFFF088) == 0);\r
313 \r
314     pTwi->TWI_IER = sources;\r
315 }\r
316 \r
317 //-----------------------------------------------------------------------------\r
318 /// Disables the selected interrupts sources on a TWI peripheral.\r
319 /// \param pTwi  Pointer to an AT91S_TWI instance.\r
320 /// \param sources  Bitwise OR of selected interrupt sources.\r
321 //-----------------------------------------------------------------------------\r
322 void TWI_DisableIt(AT91S_TWI *pTwi, unsigned int sources)\r
323 {\r
324     SANITY_CHECK(pTwi);\r
325     SANITY_CHECK((sources & 0xFFFFF088) == 0);\r
326 \r
327     pTwi->TWI_IDR = sources;\r
328 }\r
329 \r
330 //-----------------------------------------------------------------------------\r
331 /// Returns the current status register of the given TWI peripheral. This\r
332 /// resets the internal value of the status register, so further read may yield\r
333 /// different values.\r
334 /// \param pTwi  Pointer to an AT91S_TWI instance.\r
335 //-----------------------------------------------------------------------------\r
336 unsigned int TWI_GetStatus(AT91S_TWI *pTwi)\r
337 {\r
338     SANITY_CHECK(pTwi);\r
339 \r
340     return pTwi->TWI_SR;\r
341 }\r
342 \r
343 //-----------------------------------------------------------------------------\r
344 /// Returns the current status register of the given TWI peripheral, but\r
345 /// masking interrupt sources which are not currently enabled.\r
346 /// This resets the internal value of the status register, so further read may\r
347 /// yield different values.\r
348 /// \param pTwi  Pointer to an AT91S_TWI instance.\r
349 //-----------------------------------------------------------------------------\r
350 unsigned int TWI_GetMaskedStatus(AT91S_TWI *pTwi)\r
351 {\r
352     unsigned int status;\r
353 \r
354     SANITY_CHECK(pTwi);\r
355 \r
356     status = pTwi->TWI_SR;\r
357     status &= pTwi->TWI_IMR;\r
358 \r
359     return status;\r
360 }\r
361 //-----------------------------------------------------------------------------\r
362 /// Sends a STOP condition. STOP Condition is sent just after completing\r
363 /// the current byte transmission in master read mode.\r
364 /// \param pTwi  Pointer to an AT91S_TWI instance.\r
365 //-----------------------------------------------------------------------------\r
366 void TWI_SendSTOPCondition(AT91S_TWI *pTwi)\r
367 {\r
368     SANITY_CHECK(pTwi);\r
369 \r
370     pTwi->TWI_CR |= AT91C_TWI_STOP;\r
371 }\r
372 \r