]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_M7_SAMV71_Xplained/libchip_samv7/source/pio.c
Update version number ready for V8.2.1 release.
[freertos] / FreeRTOS / Demo / CORTEX_M7_SAMV71_Xplained / libchip_samv7 / source / pio.c
1 /* ----------------------------------------------------------------------------\r
2  *         SAM Software Package License\r
3  * ----------------------------------------------------------------------------\r
4  * Copyright (c) 2014, 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 /** \file */\r
31 \r
32 /*----------------------------------------------------------------------------\r
33  *        Headers\r
34  *----------------------------------------------------------------------------*/\r
35 #include "chip.h"\r
36 \r
37 /*----------------------------------------------------------------------------\r
38  *        Local functions\r
39  *----------------------------------------------------------------------------*/\r
40 \r
41 /**\r
42  * \brief Configures one or more pin(s) of a PIO controller as being controlled by\r
43  * peripheral A. Optionally, the corresponding internal pull-up(s) can be enabled.\r
44  *\r
45  * \param pio  Pointer to a PIO controller.\r
46  * \param mask  Bitmask of one or more pin(s) to configure.\r
47  * \param enablePullUp  Indicates if the pin(s) internal pull-up shall be\r
48  *                      configured.\r
49  */\r
50 static void PIO_SetPeripheralA(\r
51     Pio *pio,\r
52     unsigned int mask,\r
53     unsigned char enablePullUp)\r
54 {\r
55     unsigned int abcdsr;\r
56     /* Disable interrupts on the pin(s) */\r
57     pio->PIO_IDR = mask;\r
58 \r
59     /* Enable the pull-up(s) if necessary */\r
60     if (enablePullUp) {\r
61         pio->PIO_PUER = mask;\r
62     }\r
63     else {\r
64 \r
65         pio->PIO_PUDR = mask;\r
66     }\r
67 \r
68     abcdsr = pio->PIO_ABCDSR[0];\r
69     pio->PIO_ABCDSR[0] &= (~mask & abcdsr);\r
70     abcdsr = pio->PIO_ABCDSR[1];\r
71     pio->PIO_ABCDSR[1] &= (~mask & abcdsr);\r
72     pio->PIO_PDR = mask;\r
73 }\r
74 \r
75 /**\r
76  * \brief Configures one or more pin(s) of a PIO controller as being controlled by\r
77  * peripheral B. Optionally, the corresponding internal pull-up(s) can be enabled.\r
78  *\r
79  * \param pio  Pointer to a PIO controller.\r
80  * \param mask  Bitmask of one or more pin(s) to configure.\r
81  * \param enablePullUp  Indicates if the pin(s) internal pull-up shall be\r
82  *                      configured.\r
83  */\r
84 static void PIO_SetPeripheralB(\r
85     Pio *pio,\r
86     unsigned int mask,\r
87     unsigned char enablePullUp)\r
88 {\r
89     unsigned int abcdsr;\r
90     /* Disable interrupts on the pin(s) */\r
91     pio->PIO_IDR = mask;\r
92 \r
93     /* Enable the pull-up(s) if necessary */\r
94     if (enablePullUp) {\r
95 \r
96         pio->PIO_PUER = mask;\r
97     }\r
98     else {\r
99 \r
100         pio->PIO_PUDR = mask;\r
101     }\r
102 \r
103     abcdsr = pio->PIO_ABCDSR[0];\r
104     pio->PIO_ABCDSR[0] = (mask | abcdsr);\r
105     abcdsr = pio->PIO_ABCDSR[1];\r
106     pio->PIO_ABCDSR[1] &= (~mask & abcdsr);\r
107 \r
108     pio->PIO_PDR = mask;\r
109 }\r
110 \r
111 /**\r
112  * \brief Configures one or more pin(s) of a PIO controller as being controlled by\r
113  * peripheral C. Optionally, the corresponding internal pull-up(s) can be enabled.\r
114  *\r
115  * \param pio  Pointer to a PIO controller.\r
116  * \param mask  Bitmask of one or more pin(s) to configure.\r
117  * \param enablePullUp  Indicates if the pin(s) internal pull-up shall be\r
118  *                      configured.\r
119  */\r
120 static void PIO_SetPeripheralC(\r
121     Pio *pio,\r
122     unsigned int mask,\r
123     unsigned char enablePullUp)\r
124 {\r
125     unsigned int abcdsr;\r
126     /* Disable interrupts on the pin(s) */\r
127     pio->PIO_IDR = mask;\r
128 \r
129     /* Enable the pull-up(s) if necessary */\r
130     if (enablePullUp) {\r
131 \r
132         pio->PIO_PUER = mask;\r
133     }\r
134     else {\r
135 \r
136         pio->PIO_PUDR = mask;\r
137     }\r
138 \r
139     abcdsr = pio->PIO_ABCDSR[0];\r
140     pio->PIO_ABCDSR[0] &= (~mask & abcdsr);\r
141     abcdsr = pio->PIO_ABCDSR[1];\r
142     pio->PIO_ABCDSR[1] = (mask | abcdsr);\r
143 \r
144     pio->PIO_PDR = mask;\r
145 }\r
146 \r
147 /**\r
148  * \brief Configures one or more pin(s) of a PIO controller as being controlled by\r
149  * peripheral D. Optionally, the corresponding internal pull-up(s) can be enabled.\r
150  *\r
151  * \param pio  Pointer to a PIO controller.\r
152  * \param mask  Bitmask of one or more pin(s) to configure.\r
153  * \param enablePullUp  Indicates if the pin(s) internal pull-up shall be\r
154  *                      configured.\r
155  */\r
156 static void PIO_SetPeripheralD(\r
157     Pio *pio,\r
158     unsigned int mask,\r
159     unsigned char enablePullUp)\r
160 {\r
161     unsigned int abcdsr;\r
162     /* Disable interrupts on the pin(s) */\r
163     pio->PIO_IDR = mask;\r
164 \r
165     /* Enable the pull-up(s) if necessary */\r
166     if (enablePullUp) {\r
167 \r
168         pio->PIO_PUER = mask;\r
169     }\r
170     else {\r
171 \r
172         pio->PIO_PUDR = mask;\r
173     }\r
174 \r
175     abcdsr = pio->PIO_ABCDSR[0];\r
176     pio->PIO_ABCDSR[0] = (mask | abcdsr);\r
177     abcdsr = pio->PIO_ABCDSR[1];\r
178     pio->PIO_ABCDSR[1] = (mask | abcdsr);\r
179 \r
180     pio->PIO_PDR = mask;\r
181 }\r
182 \r
183 /**\r
184  * \brief Configures one or more pin(s) or a PIO controller as inputs. Optionally,\r
185  * the corresponding internal pull-up(s) and glitch filter(s) can be enabled.\r
186  *\r
187  * \param pio  Pointer to a PIO controller.\r
188  * \param mask  Bitmask indicating which pin(s) to configure as input(s).\r
189  * \param enablePullUp  Indicates if the internal pull-up(s) must be enabled.\r
190  * \param enableFilter  Indicates if the glitch filter(s) must be enabled.\r
191  */\r
192 static void PIO_SetInput(\r
193     Pio *pio,\r
194     unsigned int mask,\r
195     unsigned char attribute)\r
196 {\r
197     /* Disable interrupts */\r
198     pio->PIO_IDR = mask;\r
199 \r
200     /* Enable pull-up(s) if necessary */\r
201     if (attribute & PIO_PULLUP)\r
202         pio->PIO_PUER = mask;\r
203     else\r
204         pio->PIO_PUDR = mask;\r
205 \r
206     /* Enable Input Filter if necessary */\r
207     if (attribute & (PIO_DEGLITCH | PIO_DEBOUNCE))\r
208         pio->PIO_IFER = mask;\r
209     else\r
210         pio->PIO_IFDR = mask;\r
211 \r
212     /* Enable de-glitch or de-bounce if necessary */\r
213     if (attribute & PIO_DEGLITCH)\r
214     {\r
215         pio->PIO_IFSCDR = mask;\r
216     }\r
217     else\r
218     {\r
219         if (attribute & PIO_DEBOUNCE)\r
220         {\r
221             pio->PIO_IFSCER = mask;\r
222         }\r
223     }\r
224 \r
225     /* Configure pin as input */\r
226     pio->PIO_ODR = mask;\r
227     pio->PIO_PER = mask;\r
228 }\r
229 \r
230 /**\r
231  * \brief Configures one or more pin(s) of a PIO controller as outputs, with the\r
232  * given default value. Optionally, the multi-drive feature can be enabled\r
233  * on the pin(s).\r
234  *\r
235  * \param pio  Pointer to a PIO controller.\r
236  * \param mask  Bitmask indicating which pin(s) to configure.\r
237  * \param defaultValue  Default level on the pin(s).\r
238  * \param enableMultiDrive  Indicates if the pin(s) shall be configured as\r
239  *                          open-drain.\r
240  * \param enablePullUp  Indicates if the pin shall have its pull-up activated.\r
241  */\r
242 static void PIO_SetOutput(\r
243     Pio *pio,\r
244     unsigned int mask,\r
245     unsigned char defaultValue,\r
246     unsigned char enableMultiDrive,\r
247     unsigned char enablePullUp)\r
248 {\r
249     /* Disable interrupts */\r
250     pio->PIO_IDR = mask;\r
251 \r
252     /* Enable pull-up(s) if necessary */\r
253     if (enablePullUp) {\r
254 \r
255         pio->PIO_PUER = mask;\r
256     }\r
257     else {\r
258 \r
259         pio->PIO_PUDR = mask;\r
260     }\r
261 \r
262     /* Enable multi-drive if necessary */\r
263     if (enableMultiDrive) {\r
264 \r
265         pio->PIO_MDER = mask;\r
266     }\r
267     else {\r
268 \r
269         pio->PIO_MDDR = mask;\r
270     }\r
271 \r
272     /* Set default value */\r
273     if (defaultValue) {\r
274 \r
275         pio->PIO_SODR = mask;\r
276     }\r
277     else {\r
278 \r
279         pio->PIO_CODR = mask;\r
280     }\r
281 \r
282     /* Configure pin(s) as output(s) */\r
283     pio->PIO_OER = mask;\r
284     pio->PIO_PER = mask;\r
285 }\r
286 \r
287 /*----------------------------------------------------------------------------\r
288  *         Global functions\r
289  *----------------------------------------------------------------------------*/\r
290 \r
291 /**\r
292  * \brief Configures a list of Pin instances, each of which can either hold a single\r
293  * pin or a group of pins, depending on the mask value; all pins are configured\r
294  * by this function. The size of the array must also be provided and is easily\r
295  * computed using PIO_LISTSIZE whenever its length is not known in advance.\r
296  *\r
297  * \param list  Pointer to a list of Pin instances.\r
298  * \param size  Size of the Pin list (calculated using PIO_LISTSIZE).\r
299  *\r
300  * \return 1 if the pins have been configured properly; otherwise 0.\r
301  */\r
302 uint8_t PIO_Configure( const Pin *list, uint32_t size )\r
303 {\r
304     /* Configure pins */\r
305     while ( size > 0 )\r
306     {\r
307         switch ( list->type )\r
308         {\r
309 \r
310             case PIO_PERIPH_A:\r
311                 PIO_SetPeripheralA(list->pio,\r
312                                    list->mask,\r
313                                    (list->attribute & PIO_PULLUP) ? 1 : 0);\r
314             break;\r
315 \r
316             case PIO_PERIPH_B:\r
317                 PIO_SetPeripheralB(list->pio,\r
318                                    list->mask,\r
319                                    (list->attribute & PIO_PULLUP) ? 1 : 0);\r
320             break;\r
321 \r
322             case PIO_PERIPH_C:\r
323                 PIO_SetPeripheralC(list->pio,\r
324                                    list->mask,\r
325                                    (list->attribute & PIO_PULLUP) ? 1 : 0);\r
326             break;\r
327 \r
328             case PIO_PERIPH_D:\r
329                 PIO_SetPeripheralD(list->pio,\r
330                                    list->mask,\r
331                                    (list->attribute & PIO_PULLUP) ? 1 : 0);\r
332             break;\r
333             case PIO_INPUT:\r
334 #ifndef __FPGA\r
335                 PMC_EnablePeripheral(list->id);\r
336 #endif\r
337                 PIO_SetInput(list->pio,\r
338                              list->mask,\r
339                              list->attribute);\r
340                 break;\r
341 \r
342             case PIO_OUTPUT_0:\r
343             case PIO_OUTPUT_1:\r
344                 PIO_SetOutput(list->pio,\r
345                               list->mask,\r
346                               (list->type == PIO_OUTPUT_1),\r
347                               (list->attribute & PIO_OPENDRAIN) ? 1 : 0,\r
348                               (list->attribute & PIO_PULLUP) ? 1 : 0);\r
349                 break;\r
350 \r
351             default: return 0;\r
352         }\r
353 \r
354         list++;\r
355         size--;\r
356     }\r
357 \r
358     return 1;\r
359 }\r
360 \r
361 /**\r
362  * \brief Sets a high output level on all the PIOs defined in the given Pin instance.\r
363  * This has no immediate effects on PIOs that are not output, but the PIO\r
364  * controller will memorize the value they are changed to outputs.\r
365  *\r
366  * \param pin  Pointer to a Pin instance describing one or more pins.\r
367  */\r
368 void PIO_Set(const Pin *pin)\r
369 {\r
370     pin->pio->PIO_SODR = pin->mask;\r
371 }\r
372 \r
373 /**\r
374  * \brief Sets a low output level on all the PIOs defined in the given Pin instance.\r
375  * This has no immediate effects on PIOs that are not output, but the PIO\r
376  * controller will memorize the value they are changed to outputs.\r
377  *\r
378  * \param pin  Pointer to a Pin instance describing one or more pins.\r
379  */\r
380 void PIO_Clear(const Pin *pin)\r
381 {\r
382     pin->pio->PIO_CODR = pin->mask;\r
383 }\r
384 \r
385 /**\r
386  * \brief Returns 1 if one or more PIO of the given Pin instance currently have\r
387  * a high level; otherwise returns 0. This method returns the actual value that\r
388  * is being read on the pin. To return the supposed output value of a pin, use\r
389  * PIO_GetOutputDataStatus() instead.\r
390  *\r
391  * \param pin  Pointer to a Pin instance describing one or more pins.\r
392  *\r
393  * \return 1 if the Pin instance contains at least one PIO that currently has\r
394  * a high level; otherwise 0.\r
395  */\r
396 unsigned char PIO_Get( const Pin *pin )\r
397 {\r
398     unsigned int reg ;\r
399 \r
400     if ( (pin->type == PIO_OUTPUT_0) || (pin->type == PIO_OUTPUT_1) )\r
401     {\r
402         reg = pin->pio->PIO_ODSR ;\r
403     }\r
404     else\r
405     {\r
406         reg = pin->pio->PIO_PDSR ;\r
407     }\r
408 \r
409     if ( (reg & pin->mask) == 0 )\r
410     {\r
411         return 0 ;\r
412     }\r
413     else\r
414     {\r
415         return 1 ;\r
416     }\r
417 }\r
418 \r
419 /**\r
420  * \brief Returns 1 if one or more PIO of the given Pin are configured to output a\r
421  * high level (even if they are not output).\r
422  * To get the actual value of the pin, use PIO_Get() instead.\r
423  *\r
424  * \param pin  Pointer to a Pin instance describing one or more pins.\r
425  *\r
426  * \return 1 if the Pin instance contains at least one PIO that is configured\r
427  * to output a high level; otherwise 0.\r
428  */\r
429 unsigned char PIO_GetOutputDataStatus(const Pin *pin)\r
430 {\r
431     if ((pin->pio->PIO_ODSR & pin->mask) == 0) {\r
432 \r
433         return 0;\r
434     }\r
435     else {\r
436 \r
437         return 1;\r
438     }\r
439 }\r
440 \r
441 /*\r
442  * \brief Configures Glitch or Debouncing filter for input.\r
443  *\r
444  * \param pin  Pointer to a Pin instance describing one or more pins.\r
445  * \param cuttoff  Cutt off frequency for debounce filter.\r
446  */\r
447 void PIO_SetDebounceFilter( const Pin *pin, uint32_t cuttoff )\r
448 {\r
449     Pio *pio = pin->pio;\r
450 \r
451     pio->PIO_IFSCER = pin->mask; /* set Debouncing, 0 bit field no effect */\r
452     pio->PIO_SCDR = ((32678/(2*(cuttoff))) - 1) & 0x3FFF; /* the lowest 14 bits work */\r
453 }\r
454 \r
455 /*\r
456  * \brief Enable write protect.\r
457  *\r
458  * \param pin  Pointer to a Pin instance describing one or more pins.\r
459  */\r
460 void PIO_EnableWriteProtect( const Pin *pin )\r
461 {\r
462    Pio *pio = pin->pio;\r
463 \r
464    pio->PIO_WPMR = ( PIO_WPMR_WPKEY_VALID | PIO_WPMR_WPEN_EN );\r
465 }\r
466 \r
467 /*\r
468  * \brief Disable write protect.\r
469  *\r
470  * \param pin  Pointer to a Pin instance describing one or more pins.\r
471  */\r
472 \r
473 void PIO_DisableWriteProtect( const Pin *pin )\r
474 {\r
475    Pio *pio = pin->pio;\r
476 \r
477    pio->PIO_WPMR = ( PIO_WPMR_WPKEY_VALID | PIO_WPMR_WPEN_DIS );\r
478 }\r
479 \r
480 /*\r
481  * \brief Get write protect violation information.\r
482  *\r
483  * \param pin  Pointer to a Pin instance describing one or more pins.\r
484  */\r
485 \r
486 uint32_t PIO_GetWriteProtectViolationInfo( const Pin * pin )\r
487 {\r
488     Pio *pio = pin->pio;\r
489     return (pio->PIO_WPSR);\r
490 }\r
491 /* \brief Set pin type\r
492  * the pin is controlled by the corresponding peripheral (A, B, C, D,E)\r
493  * \param pin      Pointer to a Pin instance describing one or more pins.\r
494  * \param pinType  PIO_PERIPH_A, PIO_PERIPH_B, ...\r
495  */\r
496 \r
497 void PIO_SetPinType( Pin * pin, uint8_t pinType)\r
498 {\r
499     pin->type = pinType;\r
500 }\r
501 \r