diff options
Diffstat (limited to '')
-rw-r--r-- | c/src/lib/libbsp/arm/atsam/libraries/libchip/source/pio.c | 462 |
1 files changed, 462 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/arm/atsam/libraries/libchip/source/pio.c b/c/src/lib/libbsp/arm/atsam/libraries/libchip/source/pio.c new file mode 100644 index 0000000000..1e4a1277e2 --- /dev/null +++ b/c/src/lib/libbsp/arm/atsam/libraries/libchip/source/pio.c @@ -0,0 +1,462 @@ +/* ---------------------------------------------------------------------------- */ +/* Atmel Microcontroller Software Support */ +/* SAM Software Package License */ +/* ---------------------------------------------------------------------------- */ +/* Copyright (c) 2015, Atmel Corporation */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following condition is met: */ +/* */ +/* - Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the disclaimer below. */ +/* */ +/* Atmel's name may not be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR */ +/* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE */ +/* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, */ +/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */ +/* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */ +/* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* ---------------------------------------------------------------------------- */ + +/** \file */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ +#include "chip.h" + +/*---------------------------------------------------------------------------- + * Local functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Configures one or more pin(s) of a PIO controller as being controlled by + * peripheral A. Optionally, the corresponding internal pull-up(s) can be enabled. + * + * \param pio Pointer to a PIO controller. + * \param mask Bitmask of one or more pin(s) to configure. + * \param enablePullUp Indicates if the pin(s) internal pull-up shall be + * configured. + */ +static void PIO_SetPeripheralA( + Pio *pio, + unsigned int mask, + unsigned char enablePullUp) +{ + unsigned int abcdsr; + /* Disable interrupts on the pin(s) */ + pio->PIO_IDR = mask; + + /* Enable the pull-up(s) if necessary */ + if (enablePullUp) + pio->PIO_PUER = mask; + else + pio->PIO_PUDR = mask; + + abcdsr = pio->PIO_ABCDSR[0]; + pio->PIO_ABCDSR[0] &= (~mask & abcdsr); + abcdsr = pio->PIO_ABCDSR[1]; + pio->PIO_ABCDSR[1] &= (~mask & abcdsr); + pio->PIO_PDR = mask; +} + +/** + * \brief Configures one or more pin(s) of a PIO controller as being controlled + * by peripheral B. Optionally, the corresponding internal pull-up(s) can be + * enabled. + * + * \param pio Pointer to a PIO controller. + * \param mask Bitmask of one or more pin(s) to configure. + * \param enablePullUp Indicates if the pin(s) internal pull-up shall be + * configured. + */ +static void PIO_SetPeripheralB( + Pio *pio, + unsigned int mask, + unsigned char enablePullUp) +{ + unsigned int abcdsr; + /* Disable interrupts on the pin(s) */ + pio->PIO_IDR = mask; + + /* Enable the pull-up(s) if necessary */ + if (enablePullUp) + pio->PIO_PUER = mask; + else + pio->PIO_PUDR = mask; + + abcdsr = pio->PIO_ABCDSR[0]; + pio->PIO_ABCDSR[0] = (mask | abcdsr); + abcdsr = pio->PIO_ABCDSR[1]; + pio->PIO_ABCDSR[1] &= (~mask & abcdsr); + + pio->PIO_PDR = mask; +} + +/** + * \brief Configures one or more pin(s) of a PIO controller as being controlled + * by peripheral C. Optionally, the corresponding internal pull-up(s) can be + * enabled. + * + * \param pio Pointer to a PIO controller. + * \param mask Bitmask of one or more pin(s) to configure. + * \param enablePullUp Indicates if the pin(s) internal pull-up shall be + * configured. + */ +static void PIO_SetPeripheralC( + Pio *pio, + unsigned int mask, + unsigned char enablePullUp) +{ + unsigned int abcdsr; + /* Disable interrupts on the pin(s) */ + pio->PIO_IDR = mask; + + /* Enable the pull-up(s) if necessary */ + if (enablePullUp) + pio->PIO_PUER = mask; + else + pio->PIO_PUDR = mask; + + abcdsr = pio->PIO_ABCDSR[0]; + pio->PIO_ABCDSR[0] &= (~mask & abcdsr); + abcdsr = pio->PIO_ABCDSR[1]; + pio->PIO_ABCDSR[1] = (mask | abcdsr); + + pio->PIO_PDR = mask; +} + +/** + * \brief Configures one or more pin(s) of a PIO controller as being controlled + * by peripheral D. Optionally, the corresponding internal pull-up(s) can be + * enabled. + * + * \param pio Pointer to a PIO controller. + * \param mask Bitmask of one or more pin(s) to configure. + * \param enablePullUp Indicates if the pin(s) internal pull-up shall be + * configured. + */ +static void PIO_SetPeripheralD( + Pio *pio, + unsigned int mask, + unsigned char enablePullUp) +{ + unsigned int abcdsr; + /* Disable interrupts on the pin(s) */ + pio->PIO_IDR = mask; + + /* Enable the pull-up(s) if necessary */ + if (enablePullUp) + pio->PIO_PUER = mask; + else + pio->PIO_PUDR = mask; + + abcdsr = pio->PIO_ABCDSR[0]; + pio->PIO_ABCDSR[0] = (mask | abcdsr); + abcdsr = pio->PIO_ABCDSR[1]; + pio->PIO_ABCDSR[1] = (mask | abcdsr); + + pio->PIO_PDR = mask; +} + +/** + * \brief Configures one or more pin(s) or a PIO controller as inputs. Optionally, + * the corresponding internal pull-up(s) and glitch filter(s) can be enabled. + * + * \param pio Pointer to a PIO controller. + * \param mask Bitmask indicating which pin(s) to configure as input(s). + * \param enablePullUp Indicates if the internal pull-up(s) must be enabled. + * \param enableFilter Indicates if the glitch filter(s) must be enabled. + */ +static void PIO_SetInput( + Pio *pio, + unsigned int mask, + unsigned char attribute) +{ + /* Disable interrupts */ + pio->PIO_IDR = mask; + + /* Enable pull-up(s) if necessary */ + if (attribute & PIO_PULLUP) + pio->PIO_PUER = mask; + else + pio->PIO_PUDR = mask; + + /* Enable Input Filter if necessary */ + if (attribute & (PIO_DEGLITCH | PIO_DEBOUNCE)) + pio->PIO_IFER = mask; + else + pio->PIO_IFDR = mask; + + /* Enable de-glitch or de-bounce if necessary */ + if (attribute & PIO_DEGLITCH) + pio->PIO_IFSCDR = mask; + else { + if (attribute & PIO_DEBOUNCE) + pio->PIO_IFSCER = mask; + } + + /* Configure pin as input */ + pio->PIO_ODR = mask; + pio->PIO_PER = mask; +} + +/** + * \brief Configures one or more pin(s) of a PIO controller as outputs, with the + * given default value. Optionally, the multi-drive feature can be enabled + * on the pin(s). + * + * \param pio Pointer to a PIO controller. + * \param mask Bitmask indicating which pin(s) to configure. + * \param defaultValue Default level on the pin(s). + * \param enableMultiDrive Indicates if the pin(s) shall be configured as + * open-drain. + * \param enablePullUp Indicates if the pin shall have its pull-up activated. + */ +static void PIO_SetOutput( + Pio *pio, + unsigned int mask, + unsigned char defaultValue, + unsigned char enableMultiDrive, + unsigned char enablePullUp) +{ + /* Disable interrupts */ + pio->PIO_IDR = mask; + + /* Enable pull-up(s) if necessary */ + if (enablePullUp) + pio->PIO_PUER = mask; + else + pio->PIO_PUDR = mask; + + /* Enable multi-drive if necessary */ + if (enableMultiDrive) + pio->PIO_MDER = mask; + else + pio->PIO_MDDR = mask; + + /* Set default value */ + if (defaultValue) + pio->PIO_SODR = mask; + else + pio->PIO_CODR = mask; + + /* Configure pin(s) as output(s) */ + pio->PIO_OER = mask; + pio->PIO_PER = mask; +} + +/*---------------------------------------------------------------------------- + * Global functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Configures a list of Pin instances, each of which can either hold a + * single pin or a group of pins, depending on the mask value; all pins are + * configured by this function. The size of the array must also be provided and + * is easily computed using PIO_LISTSIZE whenever its length is not known in + * advance. + * + * \param list Pointer to a list of Pin instances. + * \param size Size of the Pin list (calculated using PIO_LISTSIZE). + * + * \return 1 if the pins have been configured properly; otherwise 0. + */ +uint8_t PIO_Configure(const Pin *list, uint32_t size) +{ + /* Configure pins */ + while (size > 0) { + switch (list->type) { + case PIO_PERIPH_A: + PIO_SetPeripheralA(list->pio, + list->mask, + (list->attribute & PIO_PULLUP) ? 1 : 0); + break; + + case PIO_PERIPH_B: + PIO_SetPeripheralB(list->pio, + list->mask, + (list->attribute & PIO_PULLUP) ? 1 : 0); + break; + + case PIO_PERIPH_C: + PIO_SetPeripheralC(list->pio, + list->mask, + (list->attribute & PIO_PULLUP) ? 1 : 0); + break; + + case PIO_PERIPH_D: + PIO_SetPeripheralD(list->pio, + list->mask, + (list->attribute & PIO_PULLUP) ? 1 : 0); + break; + + case PIO_INPUT: +#ifndef __FPGA + PMC_EnablePeripheral(list->id); +#endif + PIO_SetInput(list->pio, + list->mask, + list->attribute); + break; + + case PIO_OUTPUT_0: + case PIO_OUTPUT_1: + PIO_SetOutput(list->pio, + list->mask, + (list->type == PIO_OUTPUT_1), + (list->attribute & PIO_OPENDRAIN) ? 1 : 0, + (list->attribute & PIO_PULLUP) ? 1 : 0); + break; + + default: return 0; + } + + list++; + size--; + } + + return 1; +} + +/** + * \brief Sets a high output level on all the PIOs defined in the given Pin + * instance. + * This has no immediate effects on PIOs that are not output, but the PIO + * controller will memorize the value they are changed to outputs. + * + * \param pin Pointer to a Pin instance describing one or more pins. + */ +void PIO_Set(const Pin *pin) +{ + pin->pio->PIO_SODR = pin->mask; +} + +/** + * \brief Sets a low output level on all the PIOs defined in the given Pin + * instance. + * This has no immediate effects on PIOs that are not output, but the PIO + * controller will memorize the value they are changed to outputs. + * + * \param pin Pointer to a Pin instance describing one or more pins. + */ +void PIO_Clear(const Pin *pin) +{ + pin->pio->PIO_CODR = pin->mask; +} + +/** + * \brief Returns 1 if one or more PIO of the given Pin instance currently have + * a high level; otherwise returns 0. This method returns the actual value that + * is being read on the pin. To return the supposed output value of a pin, use + * PIO_GetOutputDataStatus() instead. + * + * \param pin Pointer to a Pin instance describing one or more pins. + * + * \return 1 if the Pin instance contains at least one PIO that currently has + * a high level; otherwise 0. + */ +unsigned char PIO_Get(const Pin *pin) +{ + unsigned int reg; + + if ((pin->type == PIO_OUTPUT_0) || (pin->type == PIO_OUTPUT_1)) + reg = pin->pio->PIO_ODSR; + else + reg = pin->pio->PIO_PDSR; + + if ((reg & pin->mask) == 0) + return 0; + else + return 1; +} + +/** + * \brief Returns 1 if one or more PIO of the given Pin are configured to output + * a high level (even if they are not output). + * To get the actual value of the pin, use PIO_Get() instead. + * + * \param pin Pointer to a Pin instance describing one or more pins. + * + * \return 1 if the Pin instance contains at least one PIO that is configured + * to output a high level; otherwise 0. + */ +unsigned char PIO_GetOutputDataStatus(const Pin *pin) +{ + if ((pin->pio->PIO_ODSR & pin->mask) == 0) + return 0; + else + return 1; +} + +/** + * \brief Configures Glitch or Denouncing filter for input. + * + * \param pin Pointer to a Pin instance describing one or more pins. + * \param cuttoff Cut off frequency for denounce filter. + */ +void PIO_SetDebounceFilter(const Pin *pin, uint32_t cuttoff) +{ + Pio *pio = pin->pio; + + pio->PIO_IFSCER = pin->mask; /* set Denouncing, 0 bit field no effect */ + pio->PIO_SCDR = ((32678 / (2 * (cuttoff))) - 1) & 0x3FFF; + /* the lowest 14 bits work */ +} + +/** + * \brief Enable write protect. + * + * \param pin Pointer to a Pin instance describing one or more pins. + */ +void PIO_EnableWriteProtect(const Pin *pin) +{ + Pio *pio = pin->pio; + + pio->PIO_WPMR = (PIO_WPMR_WPKEY_VALID | PIO_WPMR_WPEN_EN); +} + +/** + * \brief Disable write protect. + * + * \param pin Pointer to a Pin instance describing one or more pins. + */ + +void PIO_DisableWriteProtect(const Pin *pin) +{ + Pio *pio = pin->pio; + + pio->PIO_WPMR = (PIO_WPMR_WPKEY_VALID | PIO_WPMR_WPEN_DIS); +} + +/** + * \brief Get write protect violation information. + * + * \param pin Pointer to a Pin instance describing one or more pins. + */ +uint32_t PIO_GetWriteProtectViolationInfo(const Pin *pin) +{ + Pio *pio = pin->pio; + return (pio->PIO_WPSR); +} + +/** + * \brief Set pin type + * the pin is controlled by the corresponding peripheral (A, B, C, D,E) + * \param pin Pointer to a Pin instance describing one or more pins. + * \param pinType PIO_PERIPH_A, PIO_PERIPH_B, ... + */ +void PIO_SetPinType(Pin *pin, uint8_t pinType) +{ + pin->type = pinType; +} + |