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