]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/Common/drivers/Atmel/at91lib/peripherals/twi/twi.c
Add FreeRTOS-Plus directory.
[freertos] / FreeRTOS / Demo / Common / drivers / Atmel / 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 #ifndef trace_LEVEL\r
31     #define trace_LEVEL  1\r
32 #endif\r
33 \r
34 //------------------------------------------------------------------------------\r
35 //         Headers\r
36 //------------------------------------------------------------------------------\r
37 \r
38 #include "twi.h"\r
39 #include <utility/math.h>\r
40 #include <utility/assert.h>\r
41 #include <utility/trace.h>\r
42 \r
43 //------------------------------------------------------------------------------\r
44 //         Global functions\r
45 //------------------------------------------------------------------------------\r
46 \r
47 //------------------------------------------------------------------------------\r
48 /// Configures a TWI peripheral to operate in master mode, at the given\r
49 /// frequency (in Hz). The duty cycle of the TWI clock is set to 50%.\r
50 /// \param pTwi  Pointer to an AT91S_TWI instance.\r
51 /// \param twck  Desired TWI clock frequency.\r
52 /// \param mck  Master clock frequency.\r
53 //------------------------------------------------------------------------------\r
54 void TWI_Configure(AT91S_TWI *pTwi, unsigned int twck, unsigned int mck)\r
55 {\r
56     unsigned int ckdiv = 0;\r
57     unsigned int cldiv;\r
58     unsigned char ok = 0;\r
59 \r
60     trace_LOG(trace_DEBUG, "-D- TWI_Configure()\n\r");\r
61     SANITY_CHECK(pTwi);\r
62 \r
63     // Reset the TWI\r
64     pTwi->TWI_CR = AT91C_TWI_SWRST;\r
65 \r
66     // Set master mode\r
67     pTwi->TWI_CR = AT91C_TWI_MSEN;\r
68 \r
69     // Configure clock\r
70     while (!ok) {\r
71         \r
72         cldiv = ((mck / (2 * twck)) - 3) / power(2, ckdiv);\r
73         if (cldiv <= 255) {\r
74 \r
75             ok = 1;\r
76         }\r
77         else {\r
78 \r
79             ckdiv++;\r
80         }\r
81     }\r
82 \r
83     ASSERT(ckdiv < 8, "-F- Cannot find valid TWI clock parameters\n\r");\r
84     trace_LOG(trace_INFO, "-D- Using CKDIV = %u and CLDIV/CHDIV = %u\n\r", ckdiv, cldiv);\r
85     pTwi->TWI_CWGR = (ckdiv << 16) | (cldiv << 8) | cldiv;\r
86 }\r
87 \r
88 //------------------------------------------------------------------------------\r
89 /// Sends a STOP condition on the TWI.\r
90 /// \param pTwi  Pointer to an AT91S_TWI instance.\r
91 //------------------------------------------------------------------------------\r
92 void TWI_Stop(AT91S_TWI *pTwi)\r
93 {\r
94     SANITY_CHECK(pTwi);\r
95 \r
96     pTwi->TWI_CR = AT91C_TWI_STOP;\r
97 }\r
98 \r
99 //------------------------------------------------------------------------------\r
100 /// Starts a read operation on the TWI bus with the specified slave, and returns\r
101 /// immediately. Data must then be read using TWI_ReadByte() whenever a byte is\r
102 /// available (poll using TWI_ByteReceived()).\r
103 /// \param pTwi  Pointer to an AT91S_TWI instance.\r
104 /// \param address  Slave address on the bus.\r
105 /// \param iaddress  Optional internal address bytes.\r
106 /// \param isize  Number of internal address bytes.\r
107 //-----------------------------------------------------------------------------\r
108 void TWI_StartRead(\r
109     AT91S_TWI *pTwi,\r
110     unsigned char address,\r
111     unsigned int iaddress,\r
112     unsigned char isize)\r
113 {\r
114     trace_LOG(trace_DEBUG, "-D- TWI_StartRead()\n\r");\r
115     SANITY_CHECK(pTwi);\r
116     SANITY_CHECK((address & 0x80) == 0);\r
117     SANITY_CHECK((iaddress & 0xFF000000) == 0);\r
118     SANITY_CHECK(isize < 4);\r
119 \r
120     // Set slave address and number of internal address bytes\r
121     pTwi->TWI_MMR = (isize << 8) | AT91C_TWI_MREAD | (address << 16);\r
122 \r
123     // Set internal address bytes\r
124     pTwi->TWI_IADR = iaddress;\r
125 \r
126     // Send START condition\r
127     pTwi->TWI_CR = AT91C_TWI_START;\r
128 }\r
129 \r
130 //-----------------------------------------------------------------------------\r
131 /// Reads a byte from the TWI bus. The read operation must have been started\r
132 /// using TWI_StartRead() and a byte must be available (check with\r
133 /// TWI_ByteReceived()).\r
134 /// Returns the byte read.\r
135 /// \param pTwi  Pointer to an AT91S_TWI instance.\r
136 //-----------------------------------------------------------------------------\r
137 unsigned char TWI_ReadByte(AT91S_TWI *pTwi)\r
138 {\r
139     SANITY_CHECK(pTwi);\r
140 \r
141     return pTwi->TWI_RHR;\r
142 }\r
143 \r
144 //-----------------------------------------------------------------------------\r
145 /// Sends a byte of data to one of the TWI slaves on the bus. This function\r
146 /// must be called once before TWI_StartWrite() with the first byte of data\r
147 /// to send, then it shall be called repeatedly after that to send the\r
148 /// remaining bytes.\r
149 /// \param pTwi  Pointer to an AT91S_TWI instance.\r
150 /// \param byte  Byte to send.\r
151 //-----------------------------------------------------------------------------\r
152 void TWI_WriteByte(AT91S_TWI *pTwi, unsigned char byte)\r
153 {\r
154     SANITY_CHECK(pTwi);\r
155 \r
156     pTwi->TWI_THR = byte;\r
157 }\r
158 \r
159 //-----------------------------------------------------------------------------\r
160 /// Starts a write operation on the TWI to access the selected slave, then\r
161 /// returns immediately. A byte of data must be provided to start the write;\r
162 /// other bytes are written next.\r
163 /// \param pTwi  Pointer to an AT91S_TWI instance.\r
164 /// \param address  Address of slave to acccess on the bus.\r
165 /// \param iaddress  Optional slave internal address.\r
166 /// \param isize  Number of internal address bytes.\r
167 /// \param byte  First byte to send.\r
168 //-----------------------------------------------------------------------------\r
169 void TWI_StartWrite(\r
170     AT91S_TWI *pTwi,\r
171     unsigned char address,\r
172     unsigned int iaddress,\r
173     unsigned char isize,\r
174     unsigned char byte)\r
175 {\r
176     trace_LOG(trace_DEBUG, "-D- TWI_StartWrite()\n\r");\r
177     SANITY_CHECK(pTwi);\r
178     SANITY_CHECK((address & 0x80) == 0);\r
179     SANITY_CHECK((iaddress & 0xFF000000) == 0);\r
180     SANITY_CHECK(isize < 4);\r
181 \r
182     // Set slave address and number of internal address bytes\r
183     pTwi->TWI_MMR = (isize << 8) | (address << 16);\r
184 \r
185     // Set internal address bytes\r
186     pTwi->TWI_IADR = iaddress;\r
187 \r
188     // Write first byte to send\r
189     TWI_WriteByte(pTwi, byte);\r
190 }\r
191 \r
192 //-----------------------------------------------------------------------------\r
193 /// Returns 1 if a byte has been received and can be read on the given TWI\r
194 /// peripheral; otherwise, returns 0. This function resets the status register\r
195 /// of the TWI.\r
196 /// \param pTwi  Pointer to an AT91S_TWI instance.\r
197 //-----------------------------------------------------------------------------\r
198 unsigned char TWI_ByteReceived(AT91S_TWI *pTwi)\r
199 {\r
200     return ((pTwi->TWI_SR & AT91C_TWI_RXRDY) == AT91C_TWI_RXRDY);\r
201 }\r
202 \r
203 //-----------------------------------------------------------------------------\r
204 /// Returns 1 if a byte has been sent, so another one can be stored for\r
205 /// transmission; otherwise returns 0. This function clears the status register\r
206 /// of the TWI.\r
207 /// \param pTwi  Pointer to an AT91S_TWI instance.\r
208 //-----------------------------------------------------------------------------\r
209 unsigned char TWI_ByteSent(AT91S_TWI *pTwi)\r
210 {\r
211     return ((pTwi->TWI_SR & AT91C_TWI_TXRDY) == AT91C_TWI_TXRDY);\r
212 }\r
213 \r
214 //-----------------------------------------------------------------------------\r
215 /// Returns 1 if the current transmission is complete (the STOP has been sent);\r
216 /// otherwise returns 0.\r
217 /// \param pTwi  Pointer to an AT91S_TWI instance.\r
218 //-----------------------------------------------------------------------------\r
219 unsigned char TWI_TransferComplete(AT91S_TWI *pTwi)\r
220 {\r
221     return ((pTwi->TWI_SR & AT91C_TWI_TXCOMP) == AT91C_TWI_TXCOMP);\r
222 }\r
223 \r
224 //-----------------------------------------------------------------------------\r
225 /// Enables the selected interrupts sources on a TWI peripheral.\r
226 /// \param pTwi  Pointer to an AT91S_TWI instance.\r
227 /// \param sources  Bitwise OR of selected interrupt sources.\r
228 //-----------------------------------------------------------------------------\r
229 void TWI_EnableIt(AT91S_TWI *pTwi, unsigned int sources)\r
230 {\r
231     SANITY_CHECK(pTwi);\r
232     SANITY_CHECK((sources & 0xFFFFFEF8) == 0);\r
233 \r
234     pTwi->TWI_IER = sources;\r
235 }\r
236 \r
237 //-----------------------------------------------------------------------------\r
238 /// Disables the selected interrupts sources on a TWI peripheral.\r
239 /// \param pTwi  Pointer to an AT91S_TWI instance.\r
240 /// \param sources  Bitwise OR of selected interrupt sources.\r
241 //-----------------------------------------------------------------------------\r
242 void TWI_DisableIt(AT91S_TWI *pTwi, unsigned int sources)\r
243 {\r
244     SANITY_CHECK(pTwi);\r
245     SANITY_CHECK((sources & 0xFFFFFEF8) == 0);\r
246 \r
247     pTwi->TWI_IDR = sources;\r
248 }\r
249 \r
250 //-----------------------------------------------------------------------------\r
251 /// Returns the current status register of the given TWI peripheral. This\r
252 /// resets the internal value of the status register, so further read may yield\r
253 /// different values.\r
254 /// \param pTwi  Pointer to an AT91S_TWI instance.\r
255 //-----------------------------------------------------------------------------\r
256 unsigned int TWI_GetStatus(AT91S_TWI *pTwi)\r
257 {\r
258     SANITY_CHECK(pTwi);\r
259 \r
260     return pTwi->TWI_SR;\r
261 }\r
262 \r
263 //-----------------------------------------------------------------------------\r
264 /// Returns the current status register of the given TWI peripheral, but\r
265 /// masking interrupt sources which are not currently enabled.\r
266 /// This resets the internal value of the status register, so further read may\r
267 /// yield different values.\r
268 /// \param pTwi  Pointer to an AT91S_TWI instance.\r
269 //-----------------------------------------------------------------------------\r
270 unsigned int TWI_GetMaskedStatus(AT91S_TWI *pTwi)\r
271 {\r
272     unsigned int status;\r
273     \r
274     SANITY_CHECK(pTwi);\r
275     \r
276     status = pTwi->TWI_SR;\r
277     status &= pTwi->TWI_IMR;\r
278 \r
279     return status;\r
280 }\r
281 \r