123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311 |
- /**
- * \file
- *
- * \brief SAM Pin Multiplexer Driver
- *
- * Copyright (C) 2012-2015 Atmel Corporation. All rights reserved.
- *
- * \asf_license_start
- *
- * \page License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * 3. The name of Atmel may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * 4. This software may only be redistributed and used in connection with an
- * Atmel microcontroller product.
- *
- * 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
- * EXPRESSLY AND SPECIFICALLY 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.
- *
- * \asf_license_stop
- *
- */
- /*
- * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
- */
- #include <pinmux.h>
- /**
- * \internal
- * Writes out a given configuration of a Port pin configuration to the
- * hardware module.
- *
- * \note If the pin direction is set as an output, the pull-up/pull-down input
- * configuration setting is ignored.
- *
- * \param[in] port Base of the PORT module to configure
- * \param[in] pin_mask Mask of the port pin to configure
- * \param[in] config Configuration settings for the pin
- */
- static void _system_pinmux_config(
- PortGroup *const port,
- const uint32_t pin_mask,
- const struct system_pinmux_config *const config)
- {
- Assert(port);
- Assert(config);
- /* Track the configuration bits into a temporary variable before writing */
- uint32_t pin_cfg = 0;
- /* Enabled powersave mode, don't create configuration */
- if (!config->powersave) {
- /* Enable the pin peripheral MUX flag if non-GPIO selected (pinmux will
- * be written later) and store the new MUX mask */
- if (config->mux_position != SYSTEM_PINMUX_GPIO) {
- pin_cfg |= PORT_WRCONFIG_PMUXEN;
- pin_cfg |= (config->mux_position << PORT_WRCONFIG_PMUX_Pos);
- }
- /* Check if the user has requested that the input buffer be enabled */
- if ((config->direction == SYSTEM_PINMUX_PIN_DIR_INPUT) ||
- (config->direction == SYSTEM_PINMUX_PIN_DIR_OUTPUT_WITH_READBACK)) {
- /* Enable input buffer flag */
- pin_cfg |= PORT_WRCONFIG_INEN;
- /* Enable pull-up/pull-down control flag if requested */
- if (config->input_pull != SYSTEM_PINMUX_PIN_PULL_NONE) {
- pin_cfg |= PORT_WRCONFIG_PULLEN;
- }
- /* Clear the port DIR bits to disable the output buffer */
- port->DIRCLR.reg = pin_mask;
- }
- /* Check if the user has requested that the output buffer be enabled */
- if ((config->direction == SYSTEM_PINMUX_PIN_DIR_OUTPUT) ||
- (config->direction == SYSTEM_PINMUX_PIN_DIR_OUTPUT_WITH_READBACK)) {
- /* Cannot use a pull-up if the output driver is enabled,
- * if requested the input buffer can only sample the current
- * output state */
- pin_cfg &= ~PORT_WRCONFIG_PULLEN;
- }
- } else {
- port->DIRCLR.reg = pin_mask;
- }
- /* The Write Configuration register (WRCONFIG) requires the
- * pins to to grouped into two 16-bit half-words - split them out here */
- uint32_t lower_pin_mask = (pin_mask & 0xFFFF);
- uint32_t upper_pin_mask = (pin_mask >> 16);
- /* Configure the lower 16-bits of the port to the desired configuration,
- * including the pin peripheral multiplexer just in case it is enabled */
- port->WRCONFIG.reg
- = (lower_pin_mask << PORT_WRCONFIG_PINMASK_Pos) |
- pin_cfg | PORT_WRCONFIG_WRPMUX | PORT_WRCONFIG_WRPINCFG;
- /* Configure the upper 16-bits of the port to the desired configuration,
- * including the pin peripheral multiplexer just in case it is enabled */
- port->WRCONFIG.reg
- = (upper_pin_mask << PORT_WRCONFIG_PINMASK_Pos) |
- pin_cfg | PORT_WRCONFIG_WRPMUX | PORT_WRCONFIG_WRPINCFG |
- PORT_WRCONFIG_HWSEL;
- if(!config->powersave) {
- /* Set the pull-up state once the port pins are configured if one was
- * requested and it does not violate the valid set of port
- * configurations */
- if (pin_cfg & PORT_WRCONFIG_PULLEN) {
- /* Set the OUT register bits to enable the pull-up if requested,
- * clear to enable pull-down */
- if (config->input_pull == SYSTEM_PINMUX_PIN_PULL_UP) {
- port->OUTSET.reg = pin_mask;
- } else {
- port->OUTCLR.reg = pin_mask;
- }
- }
- /* Check if the user has requested that the output buffer be enabled */
- if ((config->direction == SYSTEM_PINMUX_PIN_DIR_OUTPUT) ||
- (config->direction == SYSTEM_PINMUX_PIN_DIR_OUTPUT_WITH_READBACK)) {
- /* Set the port DIR bits to enable the output buffer */
- port->DIRSET.reg = pin_mask;
- }
- }
- }
- /**
- * \brief Writes a Port pin configuration to the hardware module.
- *
- * Writes out a given configuration of a Port pin configuration to the hardware
- * module.
- *
- * \note If the pin direction is set as an output, the pull-up/pull-down input
- * configuration setting is ignored.
- *
- * \param[in] gpio_pin Index of the GPIO pin to configure
- * \param[in] config Configuration settings for the pin
- */
- void system_pinmux_pin_set_config(
- const uint8_t gpio_pin,
- const struct system_pinmux_config *const config)
- {
- PortGroup *const port = system_pinmux_get_group_from_gpio_pin(gpio_pin);
- uint32_t pin_mask = (1UL << (gpio_pin % 32));
- _system_pinmux_config(port, pin_mask, config);
- }
- /**
- * \brief Writes a Port pin group configuration to the hardware module.
- *
- * Writes out a given configuration of a Port pin group configuration to the
- * hardware module.
- *
- * \note If the pin direction is set as an output, the pull-up/pull-down input
- * configuration setting is ignored.
- *
- * \param[in] port Base of the PORT module to configure
- * \param[in] mask Mask of the port pin(s) to configure
- * \param[in] config Configuration settings for the pin
- */
- void system_pinmux_group_set_config(
- PortGroup *const port,
- const uint32_t mask,
- const struct system_pinmux_config *const config)
- {
- Assert(port);
- for (int i = 0; i < 32; i++) {
- if (mask & (1UL << i)) {
- _system_pinmux_config(port, (1UL << i), config);
- }
- }
- }
- /**
- * \brief Configures the input sampling mode for a group of pins.
- *
- * Configures the input sampling mode for a group of pins, to
- * control when the physical I/O pin value is sampled and
- * stored inside the microcontroller.
- *
- * \param[in] port Base of the PORT module to configure
- * \param[in] mask Mask of the port pin(s) to configure
- * \param[in] mode New pin sampling mode to configure
- */
- void system_pinmux_group_set_input_sample_mode(
- PortGroup *const port,
- const uint32_t mask,
- const enum system_pinmux_pin_sample mode)
- {
- Assert(port);
- if (mode == SYSTEM_PINMUX_PIN_SAMPLE_ONDEMAND) {
- port->CTRL.reg |= mask;
- } else {
- port->CTRL.reg &= ~mask;
- }
- }
- #ifdef FEATURE_SYSTEM_PINMUX_SLEWRATE_LIMITER
- /**
- * \brief Configures the output slew rate mode for a group of pins.
- *
- * Configures the output slew rate mode for a group of pins, to
- * control the speed at which the physical output pin can react to
- * logical changes of the I/O pin value.
- *
- * \param[in] port Base of the PORT module to configure
- * \param[in] mask Mask of the port pin(s) to configure
- * \param[in] mode New pin slew rate mode to configure
- */
- void system_pinmux_group_set_output_slew_rate(
- PortGroup *const port,
- const uint32_t mask,
- const enum system_pinmux_pin_slew_rate mode)
- {
- Assert(port);
- for (int i = 0; i < 32; i++) {
- if (mask & (1UL << i)) {
- if (mode == SYSTEM_PINMUX_PIN_SLEW_RATE_LIMITED) {
- port->PINCFG[i].reg |= PORT_PINCFG_SLEWLIM;
- } else {
- port->PINCFG[i].reg &= ~PORT_PINCFG_SLEWLIM;
- }
- }
- }
- }
- #endif
- #ifdef FEATURE_SYSTEM_PINMUX_DRIVE_STRENGTH
- /**
- * \brief Configures the output driver strength mode for a group of pins.
- *
- * Configures the output drive strength for a group of pins, to
- * control the amount of current the pad is able to sink/source.
- *
- * \param[in] port Base of the PORT module to configure
- * \param[in] mask Mask of the port pin(s) to configure
- * \param[in] mode New output driver strength mode to configure
- */
- void system_pinmux_group_set_output_strength(
- PortGroup *const port,
- const uint32_t mask,
- const enum system_pinmux_pin_strength mode)
- {
- Assert(port);
- for (int i = 0; i < 32; i++) {
- if (mask & (1UL << i)) {
- if (mode == SYSTEM_PINMUX_PIN_STRENGTH_HIGH) {
- port->PINCFG[i].reg |= PORT_PINCFG_DRVSTR;
- } else {
- port->PINCFG[i].reg &= ~PORT_PINCFG_DRVSTR;
- }
- }
- }
- }
- #endif
- #ifdef FEATURE_SYSTEM_PINMUX_OPEN_DRAIN
- /**
- * \brief Configures the output driver mode for a group of pins.
- *
- * Configures the output driver mode for a group of pins, to
- * control the pad behavior.
- *
- * \param[in] port Base of the PORT module to configure
- * \param[in] mask Mask of the port pin(s) to configure
- * \param[in] mode New pad output driver mode to configure
- */
- void system_pinmux_group_set_output_drive(
- PortGroup *const port,
- const uint32_t mask,
- const enum system_pinmux_pin_drive mode)
- {
- Assert(port);
- for (int i = 0; i < 32; i++) {
- if (mask & (1UL << i)) {
- if (mode == SYSTEM_PINMUX_PIN_DRIVE_OPEN_DRAIN) {
- port->PINCFG[i].reg |= PORT_PINCFG_ODRAIN;
- } else {
- port->PINCFG[i].reg &= ~PORT_PINCFG_ODRAIN;
- }
- }
- }
- }
- #endif
|