source: rtems/c/src/lib/libbsp/arm/atsam/libraries/libchip/source/pio.c @ 7c39cab

5
Last change on this file since 7c39cab was 71c5552f, checked in by Christian Mauderer <christian.mauderer@…>, on 03/12/18 at 15:43:28

bsp/atsam: Allow setting the drive strength.

This adds a simple function for setting the PIO drive strength.

  • Property mode set to 100644
File size: 14.3 KB
Line 
1/* ---------------------------------------------------------------------------- */
2/*                  Atmel Microcontroller Software Support                      */
3/*                       SAM Software Package License                           */
4/* ---------------------------------------------------------------------------- */
5/* Copyright (c) 2015, Atmel Corporation                                        */
6/*                                                                              */
7/* All rights reserved.                                                         */
8/*                                                                              */
9/* Redistribution and use in source and binary forms, with or without           */
10/* modification, are permitted provided that the following condition is met:    */
11/*                                                                              */
12/* - Redistributions of source code must retain the above copyright notice,     */
13/* this list of conditions and the disclaimer below.                            */
14/*                                                                              */
15/* Atmel's name may not be used to endorse or promote products derived from     */
16/* this software without specific prior written permission.                     */
17/*                                                                              */
18/* DISCLAIMER:  THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR   */
19/* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
20/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE   */
21/* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,      */
22/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
23/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,  */
24/* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    */
25/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING         */
26/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */
27/* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                           */
28/* ---------------------------------------------------------------------------- */
29
30/** \file */
31
32/*----------------------------------------------------------------------------
33 *        Headers
34 *----------------------------------------------------------------------------*/
35#include "chip.h"
36
37/*----------------------------------------------------------------------------
38 *        Local functions
39 *----------------------------------------------------------------------------*/
40
41/**
42 * \brief Configures one or more pin(s) of a PIO controller as being controlled by
43 * peripheral A. Optionally, the corresponding internal pull-up(s) can be enabled.
44 *
45 * \param pio  Pointer to a PIO controller.
46 * \param mask  Bitmask of one or more pin(s) to configure.
47 * \param enablePullUp  Indicates if the pin(s) internal pull-up shall be
48 *                      configured.
49 */
50static void PIO_SetPeripheralA(
51        Pio *pio,
52        unsigned int mask,
53        unsigned char enablePullUp)
54{
55        unsigned int abcdsr;
56        /* Disable interrupts on the pin(s) */
57        pio->PIO_IDR = mask;
58
59        /* Enable the pull-up(s) if necessary */
60        if (enablePullUp)
61                pio->PIO_PUER = mask;
62        else
63                pio->PIO_PUDR = mask;
64
65        abcdsr = pio->PIO_ABCDSR[0];
66        pio->PIO_ABCDSR[0] &= (~mask & abcdsr);
67        abcdsr = pio->PIO_ABCDSR[1];
68        pio->PIO_ABCDSR[1] &= (~mask & abcdsr);
69        pio->PIO_PDR = mask;
70}
71
72/**
73 * \brief Configures one or more pin(s) of a PIO controller as being controlled
74 * by peripheral B. Optionally, the corresponding internal pull-up(s) can be
75 * enabled.
76 *
77 * \param pio  Pointer to a PIO controller.
78 * \param mask  Bitmask of one or more pin(s) to configure.
79 * \param enablePullUp  Indicates if the pin(s) internal pull-up shall be
80 *                      configured.
81 */
82static void PIO_SetPeripheralB(
83        Pio *pio,
84        unsigned int mask,
85        unsigned char enablePullUp)
86{
87        unsigned int abcdsr;
88        /* Disable interrupts on the pin(s) */
89        pio->PIO_IDR = mask;
90
91        /* Enable the pull-up(s) if necessary */
92        if (enablePullUp)
93                pio->PIO_PUER = mask;
94        else
95                pio->PIO_PUDR = mask;
96
97        abcdsr = pio->PIO_ABCDSR[0];
98        pio->PIO_ABCDSR[0] = (mask | abcdsr);
99        abcdsr = pio->PIO_ABCDSR[1];
100        pio->PIO_ABCDSR[1] &= (~mask & abcdsr);
101
102        pio->PIO_PDR = mask;
103}
104
105/**
106 * \brief Configures one or more pin(s) of a PIO controller as being controlled
107 * by peripheral C. Optionally, the corresponding internal pull-up(s) can be
108 * enabled.
109 *
110 * \param pio  Pointer to a PIO controller.
111 * \param mask  Bitmask of one or more pin(s) to configure.
112 * \param enablePullUp  Indicates if the pin(s) internal pull-up shall be
113 *                      configured.
114 */
115static void PIO_SetPeripheralC(
116        Pio *pio,
117        unsigned int mask,
118        unsigned char enablePullUp)
119{
120        unsigned int abcdsr;
121        /* Disable interrupts on the pin(s) */
122        pio->PIO_IDR = mask;
123
124        /* Enable the pull-up(s) if necessary */
125        if (enablePullUp)
126                pio->PIO_PUER = mask;
127        else
128                pio->PIO_PUDR = mask;
129
130        abcdsr = pio->PIO_ABCDSR[0];
131        pio->PIO_ABCDSR[0] &= (~mask & abcdsr);
132        abcdsr = pio->PIO_ABCDSR[1];
133        pio->PIO_ABCDSR[1] = (mask | abcdsr);
134
135        pio->PIO_PDR = mask;
136}
137
138/**
139 * \brief Configures one or more pin(s) of a PIO controller as being controlled
140 * by peripheral D. Optionally, the corresponding internal pull-up(s) can be
141 * enabled.
142 *
143 * \param pio  Pointer to a PIO controller.
144 * \param mask  Bitmask of one or more pin(s) to configure.
145 * \param enablePullUp  Indicates if the pin(s) internal pull-up shall be
146 *                      configured.
147 */
148static void PIO_SetPeripheralD(
149        Pio *pio,
150        unsigned int mask,
151        unsigned char enablePullUp)
152{
153        unsigned int abcdsr;
154        /* Disable interrupts on the pin(s) */
155        pio->PIO_IDR = mask;
156
157        /* Enable the pull-up(s) if necessary */
158        if (enablePullUp)
159                pio->PIO_PUER = mask;
160        else
161                pio->PIO_PUDR = mask;
162
163        abcdsr = pio->PIO_ABCDSR[0];
164        pio->PIO_ABCDSR[0] = (mask | abcdsr);
165        abcdsr = pio->PIO_ABCDSR[1];
166        pio->PIO_ABCDSR[1] = (mask | abcdsr);
167
168        pio->PIO_PDR = mask;
169}
170
171/**
172 * \brief Configures one or more pin(s) or a PIO controller as inputs. Optionally,
173 * the corresponding internal pull-up(s) and glitch filter(s) can be enabled.
174 *
175 * \param pio  Pointer to a PIO controller.
176 * \param mask  Bitmask indicating which pin(s) to configure as input(s).
177 * \param enablePullUp  Indicates if the internal pull-up(s) must be enabled.
178 * \param enableFilter  Indicates if the glitch filter(s) must be enabled.
179 */
180static void PIO_SetInput(
181        Pio *pio,
182        unsigned int mask,
183        unsigned char attribute)
184{
185        /* Disable interrupts */
186        pio->PIO_IDR = mask;
187
188        /* Enable pull-up(s) if necessary */
189        if (attribute & PIO_PULLUP)
190                pio->PIO_PUER = mask;
191        else
192                pio->PIO_PUDR = mask;
193
194        /* Enable Input Filter if necessary */
195        if (attribute & (PIO_DEGLITCH | PIO_DEBOUNCE))
196                pio->PIO_IFER = mask;
197        else
198                pio->PIO_IFDR = mask;
199
200        /* Enable de-glitch or de-bounce if necessary */
201        if (attribute & PIO_DEGLITCH)
202                pio->PIO_IFSCDR = mask;
203        else {
204                if (attribute & PIO_DEBOUNCE)
205                        pio->PIO_IFSCER = mask;
206        }
207
208        /* Configure additional interrupt mode registers */
209        if (attribute & PIO_IT_AIME) {
210                // enable additional interrupt mode
211                pio->PIO_AIMER  = mask;
212
213                // if bit field of selected pin is 1, set as Rising Edge/High level detection event
214                if (attribute & PIO_IT_RE_OR_HL)
215                        pio->PIO_REHLSR = mask;
216                else
217                        pio->PIO_FELLSR = mask;
218
219                /* if bit field of selected pin is 1, set as edge detection source */
220                if (attribute & PIO_IT_EDGE)
221                        pio->PIO_ESR = mask;
222                else
223                        pio->PIO_LSR = mask;
224        } else {
225                /* disable additional interrupt mode */
226                pio->PIO_AIMDR = mask;
227        }
228
229        /* Configure pin as input */
230        pio->PIO_ODR = mask;
231        pio->PIO_PER = mask;
232}
233
234/**
235 * \brief Configures one or more pin(s) of a PIO controller as outputs, with the
236 * given default value. Optionally, the multi-drive feature can be enabled
237 * on the pin(s).
238 *
239 * \param pio  Pointer to a PIO controller.
240 * \param mask  Bitmask indicating which pin(s) to configure.
241 * \param defaultValue  Default level on the pin(s).
242 * \param enableMultiDrive  Indicates if the pin(s) shall be configured as
243 *                          open-drain.
244 * \param enablePullUp  Indicates if the pin shall have its pull-up activated.
245 */
246static void PIO_SetOutput(
247        Pio *pio,
248        unsigned int mask,
249        unsigned char defaultValue,
250        unsigned char enableMultiDrive,
251        unsigned char enablePullUp)
252{
253        /* Disable interrupts */
254        pio->PIO_IDR = mask;
255
256        /* Enable pull-up(s) if necessary */
257        if (enablePullUp)
258                pio->PIO_PUER = mask;
259        else
260                pio->PIO_PUDR = mask;
261
262        /* Enable multi-drive if necessary */
263        if (enableMultiDrive)
264                pio->PIO_MDER = mask;
265        else
266                pio->PIO_MDDR = mask;
267
268        /* Set default value */
269        if (defaultValue)
270                pio->PIO_SODR = mask;
271        else
272                pio->PIO_CODR = mask;
273
274        /* Configure pin(s) as output(s) */
275        pio->PIO_OER = mask;
276        pio->PIO_PER = mask;
277}
278
279/*----------------------------------------------------------------------------
280 *         Global functions
281 *----------------------------------------------------------------------------*/
282
283/**
284 * \brief Configures a list of Pin instances, each of which can either hold a
285 * single pin or a group of pins, depending on the mask value; all pins are
286 * configured by this function. The size of the array must also be provided and
287 *  is easily computed using PIO_LISTSIZE whenever its length is not known in
288 * advance.
289 *
290 * \param list  Pointer to a list of Pin instances.
291 * \param size  Size of the Pin list (calculated using PIO_LISTSIZE).
292 *
293 * \return 1 if the pins have been configured properly; otherwise 0.
294 */
295uint8_t PIO_Configure(const Pin *list, uint32_t size)
296{
297        /* Configure pins */
298        while (size > 0) {
299                switch (list->type) {
300                case PIO_PERIPH_A:
301                        PIO_SetPeripheralA(list->pio,
302                                                           list->mask,
303                                                           (list->attribute & PIO_PULLUP) ? 1 : 0);
304                        break;
305
306                case PIO_PERIPH_B:
307                        PIO_SetPeripheralB(list->pio,
308                                                           list->mask,
309                                                           (list->attribute & PIO_PULLUP) ? 1 : 0);
310                        break;
311
312                case PIO_PERIPH_C:
313                        PIO_SetPeripheralC(list->pio,
314                                                           list->mask,
315                                                           (list->attribute & PIO_PULLUP) ? 1 : 0);
316                        break;
317
318                case PIO_PERIPH_D:
319                        PIO_SetPeripheralD(list->pio,
320                                                           list->mask,
321                                                           (list->attribute & PIO_PULLUP) ? 1 : 0);
322                        break;
323
324                case PIO_INPUT:
325#ifndef __FPGA
326                        PMC_EnablePeripheral(list->id);
327#endif
328                        PIO_SetInput(list->pio,
329                                                 list->mask,
330                                                 list->attribute);
331                        break;
332
333                case PIO_OUTPUT_0:
334                case PIO_OUTPUT_1:
335                        PIO_SetOutput(list->pio,
336                                                  list->mask,
337                                                  (list->type == PIO_OUTPUT_1),
338                                                  (list->attribute & PIO_OPENDRAIN) ? 1 : 0,
339                                                  (list->attribute & PIO_PULLUP) ? 1 : 0);
340                        break;
341
342                default: return 0;
343                }
344
345                list++;
346                size--;
347        }
348
349        return 1;
350}
351
352/**
353 * \brief Sets a high output level on all the PIOs defined in the given Pin
354 * instance.
355 * This has no immediate effects on PIOs that are not output, but the PIO
356 * controller will memorize the value they are changed to outputs.
357 *
358 * \param pin  Pointer to a Pin instance describing one or more pins.
359 */
360void PIO_Set(const Pin *pin)
361{
362        pin->pio->PIO_SODR = pin->mask;
363}
364
365/**
366 * \brief Sets a low output level on all the PIOs defined in the given Pin
367 * instance.
368 * This has no immediate effects on PIOs that are not output, but the PIO
369 * controller will memorize the value they are changed to outputs.
370 *
371 * \param pin  Pointer to a Pin instance describing one or more pins.
372 */
373void PIO_Clear(const Pin *pin)
374{
375        pin->pio->PIO_CODR = pin->mask;
376}
377
378/**
379 * \brief Returns 1 if one or more PIO of the given Pin instance currently have
380 * a high level; otherwise returns 0. This method returns the actual value that
381 * is being read on the pin. To return the supposed output value of a pin, use
382 * PIO_GetOutputDataStatus() instead.
383 *
384 * \param pin  Pointer to a Pin instance describing one or more pins.
385 *
386 * \return 1 if the Pin instance contains at least one PIO that currently has
387 * a high level; otherwise 0.
388 */
389unsigned char PIO_Get(const Pin *pin)
390{
391        unsigned int reg;
392
393        if ((pin->type == PIO_OUTPUT_0) || (pin->type == PIO_OUTPUT_1))
394                reg = pin->pio->PIO_ODSR;
395        else
396                reg = pin->pio->PIO_PDSR;
397
398        if ((reg & pin->mask) == 0)
399                return 0;
400        else
401                return 1;
402}
403
404/**
405 * \brief Returns 1 if one or more PIO of the given Pin are configured to output
406 * a high level (even if they are not output).
407 * To get the actual value of the pin, use PIO_Get() instead.
408 *
409 * \param pin  Pointer to a Pin instance describing one or more pins.
410 *
411 * \return 1 if the Pin instance contains at least one PIO that is configured
412 * to output a high level; otherwise 0.
413 */
414unsigned char PIO_GetOutputDataStatus(const Pin *pin)
415{
416        if ((pin->pio->PIO_ODSR & pin->mask) == 0)
417                return 0;
418        else
419                return 1;
420}
421
422/**
423 * \brief Configures Glitch or Denouncing filter for input.
424 *
425 * \param pin  Pointer to a Pin instance describing one or more pins.
426 * \param cuttoff  Cut off frequency for denounce filter.
427 */
428void PIO_SetDebounceFilter(const Pin *pin, uint32_t cuttoff)
429{
430        Pio *pio = pin->pio;
431
432        pio->PIO_IFSCER = pin->mask; /* set Denouncing, 0 bit field no effect */
433        pio->PIO_SCDR = ((32678 / (2 * (cuttoff))) - 1) & 0x3FFF;
434        /* the lowest 14 bits work */
435}
436
437/**
438 * \brief Enable write protect.
439 *
440 * \param pin  Pointer to a Pin instance describing one or more pins.
441 */
442void PIO_EnableWriteProtect(const Pin *pin)
443{
444        Pio *pio = pin->pio;
445
446        pio->PIO_WPMR = (PIO_WPMR_WPKEY_VALID | PIO_WPMR_WPEN_EN);
447}
448
449/**
450 * \brief Disable write protect.
451 *
452 * \param pin  Pointer to a Pin instance describing one or more pins.
453 */
454
455void PIO_DisableWriteProtect(const Pin *pin)
456{
457        Pio *pio = pin->pio;
458
459        pio->PIO_WPMR = (PIO_WPMR_WPKEY_VALID | PIO_WPMR_WPEN_DIS);
460}
461
462/**
463 * \brief Get write protect violation information.
464 *
465 * \param pin  Pointer to a Pin instance describing one or more pins.
466 */
467uint32_t PIO_GetWriteProtectViolationInfo(const Pin *pin)
468{
469        Pio *pio = pin->pio;
470        return (pio->PIO_WPSR);
471}
472
473/**
474 *  \brief Set pin type
475 * the pin is controlled by the corresponding peripheral (A, B, C, D,E)
476 * \param pin      Pointer to a Pin instance describing one or more pins.
477 * \param pinType  PIO_PERIPH_A, PIO_PERIPH_B, ...
478 */
479void PIO_SetPinType(Pin *pin, uint8_t pinType)
480{
481        pin->type = pinType;
482}
483
484/**
485 * \brief Set the drive strength of the pin.
486 *
487 * \param pin  Pointer to a Pin instance describing one or more pins.
488 * \param strength  0 for low drive strength or 1 for high drive strength.
489 */
490void PIO_SetDriveStrength(const Pin *pin, uint8_t strength)
491{
492        Pio *pio = pin->pio;
493
494        if (strength) {
495                pio->PIO_DRIVER |= pin->mask;
496        } else {
497                pio->PIO_DRIVER &= ~(pin->mask);
498        }
499}
Note: See TracBrowser for help on using the repository browser.