]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/Common/drivers/Atmel/at91lib/peripherals/pio/pio.c
Add FreeRTOS-Plus directory.
[freertos] / FreeRTOS / Demo / Common / drivers / Atmel / at91lib / peripherals / pio / pio.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 //         Headers\r
32 //------------------------------------------------------------------------------\r
33 \r
34 #include "pio.h"\r
35 #include <board.h>\r
36 \r
37 //------------------------------------------------------------------------------\r
38 //         Internal definitions\r
39 //------------------------------------------------------------------------------\r
40 /// \internal Returns the current value of a register.\r
41 #define READ(peripheral, register)          (peripheral->register)\r
42 /// \internal Modifies the current value of a register.\r
43 #define WRITE(peripheral, register, value)  (peripheral->register = value)\r
44 \r
45 //------------------------------------------------------------------------------\r
46 //         Internal functions\r
47 //------------------------------------------------------------------------------\r
48 //------------------------------------------------------------------------------\r
49 /// Configures one or more pin(s) of a PIO controller as being controlled by\r
50 /// peripheral A. Optionally, the corresponding internal pull-up(s) can be\r
51 /// enabled.\r
52 /// \param pio  Pointer to a PIO controller.\r
53 /// \param mask  Bitmask of one or more pin(s) to configure.\r
54 /// \param enablePullUp  Indicates if the pin(s) internal pull-up shall be\r
55 ///                      configured.\r
56 //------------------------------------------------------------------------------\r
57 static void PIO_SetPeripheralA(AT91S_PIO *pio,\r
58                                unsigned int mask,\r
59                                unsigned char enablePullUp)\r
60 {\r
61     // Disable interrupts on the pin(s)\r
62     WRITE(pio, PIO_IDR, mask);\r
63 \r
64     // Enable the pull-up(s) if necessary\r
65     if (enablePullUp) {\r
66 \r
67         WRITE(pio, PIO_PPUER, mask);\r
68     }\r
69     else {\r
70 \r
71         WRITE(pio, PIO_PPUDR, mask);\r
72     }\r
73 \r
74     // Configure pin\r
75     WRITE(pio, PIO_ASR, mask);\r
76     WRITE(pio, PIO_PDR, mask);\r
77 }\r
78 \r
79 //------------------------------------------------------------------------------\r
80 /// Configures one or more pin(s) of a PIO controller as being controlled by\r
81 /// peripheral A. Optionally, the corresponding internal pull-up(s) can be\r
82 /// enabled.\r
83 /// \param pio  Pointer to a PIO controller.\r
84 /// \param mask  Bitmask of one or more pin(s) to configure.\r
85 /// \param enablePullUp  Indicates if the pin(s) internal pull-up shall be\r
86 ///                      configured.\r
87 //------------------------------------------------------------------------------\r
88 static void PIO_SetPeripheralB(AT91S_PIO *pio,\r
89                                unsigned int mask,\r
90                                unsigned char enablePullUp)\r
91 {\r
92     // Disable interrupts on the pin(s)\r
93     WRITE(pio, PIO_IDR, mask);\r
94 \r
95     // Enable the pull-up(s) if necessary\r
96     if (enablePullUp) {\r
97 \r
98         WRITE(pio, PIO_PPUER, mask);\r
99     }\r
100     else {\r
101 \r
102         WRITE(pio, PIO_PPUDR, mask);\r
103     }\r
104 \r
105     // Configure pin\r
106     WRITE(pio, PIO_BSR, mask);\r
107     WRITE(pio, PIO_PDR, mask);\r
108 }\r
109 \r
110 //------------------------------------------------------------------------------\r
111 /// Configures one or more pin(s) or a PIO controller as inputs. Optionally,\r
112 /// the corresponding internal pull-up(s) and glitch filter(s) can be\r
113 /// enabled.\r
114 /// \param pio  Pointer to a PIO controller.\r
115 /// \param mask  Bitmask indicating which pin(s) to configure as input(s).\r
116 /// \param enablePullUp  Indicates if the internal pull-up(s) must be enabled.\r
117 /// \param enableFilter  Indicates if the glitch filter(s) must be enabled.\r
118 //------------------------------------------------------------------------------\r
119 static void PIO_SetInput(AT91S_PIO *pio,\r
120                          unsigned int mask,\r
121                          unsigned char enablePullUp,\r
122                          unsigned char enableFilter)\r
123 {\r
124     // Disable interrupts\r
125     WRITE(pio, PIO_IDR, mask);\r
126 \r
127     // Enable pull-up(s) if necessary\r
128     if (enablePullUp) {\r
129     \r
130         WRITE(pio, PIO_PPUER, mask);\r
131     }\r
132     else {\r
133     \r
134         WRITE(pio, PIO_PPUDR, mask);\r
135     }\r
136 \r
137     // Enable filter(s) if necessary\r
138     if (enableFilter) {\r
139     \r
140         WRITE(pio, PIO_IFER, mask);\r
141     }\r
142     else {\r
143     \r
144         WRITE(pio, PIO_IFDR, mask);\r
145     }\r
146 \r
147     // Configure pin as input\r
148     WRITE(pio, PIO_ODR, mask);\r
149     WRITE(pio, PIO_PER, mask);\r
150 }\r
151 \r
152 //------------------------------------------------------------------------------\r
153 /// Configures one or more pin(s) of a PIO controller as outputs, with the\r
154 /// given default value. Optionally, the multi-drive feature can be enabled\r
155 /// on the pin(s).\r
156 /// \param pio  Pointer to a PIO controller.\r
157 /// \param mask  Bitmask indicating which pin(s) to configure.\r
158 /// \param defaultValue  Default level on the pin(s).\r
159 /// \param enableMultiDrive  Indicates if the pin(s) shall be configured as\r
160 ///                          open-drain.\r
161 /// \param enablePullUp  Indicates if the pin shall have its pull-up activated.\r
162 //------------------------------------------------------------------------------\r
163 static void PIO_SetOutput(AT91S_PIO *pio,\r
164                           unsigned int mask,\r
165                           unsigned char defaultValue,\r
166                           unsigned char enableMultiDrive,\r
167                           unsigned char enablePullUp)\r
168 {\r
169     // Disable interrupts\r
170     WRITE(pio, PIO_IDR, mask);\r
171 \r
172     // Enable pull-up(s) if necessary\r
173     if (enablePullUp) {\r
174     \r
175         WRITE(pio, PIO_PPUER, mask);\r
176     }\r
177     else {\r
178     \r
179         WRITE(pio, PIO_PPUDR, mask);\r
180     }\r
181 \r
182     // Enable multi-drive if necessary\r
183     if (enableMultiDrive) {\r
184     \r
185         WRITE(pio, PIO_MDER, mask);\r
186     }\r
187     else {\r
188     \r
189         WRITE(pio, PIO_MDDR, mask);\r
190     }\r
191 \r
192     // Set default value\r
193     if (defaultValue) {\r
194 \r
195         WRITE(pio, PIO_SODR, mask);\r
196     }\r
197     else {\r
198 \r
199         WRITE(pio, PIO_CODR, mask);\r
200     }\r
201 \r
202     // Configure pin(s) as output(s)\r
203     WRITE(pio, PIO_OER, mask);\r
204     WRITE(pio, PIO_PER, mask);\r
205 }\r
206 \r
207 //------------------------------------------------------------------------------\r
208 //         Exported functions\r
209 //------------------------------------------------------------------------------\r
210 //------------------------------------------------------------------------------\r
211 /// Configures a list of Pin instances, which can either hold a single pin or a \r
212 /// group of pins, depending on the mask value; all pins are configured by this \r
213 /// function.\r
214 /// Returns 1 if the configuration has been performed successfully; otherwise 0.\r
215 /// \param list  Pointer to a list of Pin instances.\r
216 /// \param size  Size of the Pin list (see <PIO_LISTSIZE>).\r
217 //------------------------------------------------------------------------------\r
218 unsigned char PIO_Configure(const Pin *list, unsigned int size)\r
219 {\r
220     // Configure pins\r
221     while (size > 0) {\r
222     \r
223         switch (list->type) {\r
224     \r
225             case PIO_PERIPH_A:\r
226                 PIO_SetPeripheralA(list->pio,\r
227                                    list->mask,\r
228                                    (list->attribute & PIO_PULLUP) ? 1 : 0);\r
229                 break;\r
230     \r
231             case PIO_PERIPH_B:\r
232                 PIO_SetPeripheralB(list->pio,\r
233                                    list->mask,\r
234                                    (list->attribute & PIO_PULLUP) ? 1 : 0);\r
235                 break;\r
236     \r
237             case PIO_INPUT:\r
238                 AT91C_BASE_PMC->PMC_PCER = 1 << list->id;\r
239                 PIO_SetInput(list->pio,\r
240                              list->mask,\r
241                              (list->attribute & PIO_PULLUP) ? 1 : 0,\r
242                              (list->attribute & PIO_DEGLITCH)? 1 : 0);\r
243                 break;\r
244     \r
245             case PIO_OUTPUT_0:\r
246             case PIO_OUTPUT_1:\r
247                 PIO_SetOutput(list->pio,\r
248                               list->mask,\r
249                               (list->type == PIO_OUTPUT_1),\r
250                               (list->attribute & PIO_OPENDRAIN) ? 1 : 0,\r
251                               (list->attribute & PIO_PULLUP) ? 1 : 0);\r
252                 break;\r
253     \r
254             default: return 0;\r
255         }\r
256 \r
257         list++;\r
258         size--;\r
259     }\r
260 \r
261     return 1;\r
262 }\r
263 \r
264 //------------------------------------------------------------------------------\r
265 /// Sets a high output level on one or more pin(s) (if configured as output(s)).\r
266 /// \param pin  Pointer to a Pin instance describing one or more pins.\r
267 //------------------------------------------------------------------------------\r
268 void PIO_Set(const Pin *pin)\r
269 {\r
270     WRITE(pin->pio, PIO_SODR, pin->mask);\r
271 }\r
272 \r
273 //------------------------------------------------------------------------------\r
274 /// Sets a low output level on one or more pin(s) (if configured as output(s)).\r
275 /// \param pin  Pointer to a Pin instance describing one or more pins.\r
276 //------------------------------------------------------------------------------\r
277 void PIO_Clear(const Pin *pin)\r
278 {\r
279     WRITE(pin->pio, PIO_CODR, pin->mask);\r
280 }\r
281 \r
282 //------------------------------------------------------------------------------\r
283 /// Returns 1 if one or more PIO of the given Pin instance currently have a high\r
284 /// level; otherwise returns 0.\r
285 /// \param pin  Pointer to a Pin instance describing one or more pins.\r
286 //------------------------------------------------------------------------------\r
287 unsigned char PIO_Get(const Pin *pin)\r
288 {\r
289     unsigned int reg;\r
290     if ((pin->type == PIO_OUTPUT_0) || (pin->type == PIO_OUTPUT_1)) {\r
291 \r
292         reg = READ(pin->pio, PIO_ODSR);\r
293     }\r
294     else {\r
295 \r
296         reg = READ(pin->pio, PIO_PDSR);\r
297     }\r
298 \r
299     if ((reg & pin->mask) == 0) {\r
300 \r
301         return 0;\r
302     }\r
303     else {\r
304 \r
305         return 1;\r
306     }\r
307 }\r
308 \r
309 \r
310 //------------------------------------------------------------------------------\r
311 /// Returns 1 if one or more PIO of the given Pin data to be driven on the I/O line\r
312 /// level; otherwise returns 0.\r
313 /// \param pin  Pointer to a Pin instance describing one or more pins.\r
314 //------------------------------------------------------------------------------\r
315 unsigned char PIO_GetOutputDataStatus(const Pin *pin)\r
316 {\r
317     if ((READ(pin->pio, PIO_ODSR) & pin->mask) == 0) {\r
318 \r
319         return 0;\r
320     }\r
321     else {\r
322 \r
323         return 1;\r
324     }\r
325 }\r
326 \r
327 //------------------------------------------------------------------------------\r
328 /// Returns the value of ISR for the PIO controller of the pin.\r
329 /// Reading this register acknoledges all the ITs.\r
330 /// \param pin  Pointer to a Pin instance describing one or more pins.\r
331 //------------------------------------------------------------------------------\r
332 unsigned int PIO_GetISR(const Pin *pin)\r
333 {\r
334     return (READ(pin->pio, PIO_ISR));\r
335 }\r
336 \r