You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
365 lines
9.3 KiB
C
365 lines
9.3 KiB
C
/**
|
|
* \file
|
|
*
|
|
* \brief XMEGA architecture specific IOPORT service implementation header file.
|
|
*
|
|
* Copyright (c) 2012-2016 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>
|
|
*/
|
|
#ifndef IOPORT_XMEGA_H
|
|
#define IOPORT_XMEGA_H
|
|
|
|
#define IOPORT_CREATE_PIN(port, pin) ((IOPORT_ ## port) * 8 + (pin))
|
|
#define IOPORT_BASE_ADDRESS 0x600
|
|
#define IOPORT_PORT_OFFSET 0x20
|
|
|
|
/** \name IOPORT port numbers */
|
|
/** @{ */
|
|
#if !XMEGA_B3
|
|
# define IOPORT_PORTA 0
|
|
#endif
|
|
|
|
#define IOPORT_PORTB 1
|
|
#define IOPORT_PORTC 2
|
|
#define IOPORT_PORTD 3
|
|
|
|
#if !XMEGA_B3
|
|
# define IOPORT_PORTE 4
|
|
#endif
|
|
|
|
#if XMEGA_A1 || XMEGA_A1U || XMEGA_A3 || XMEGA_A3U || XMEGA_A3B || XMEGA_A3BU || \
|
|
XMEGA_C3 || XMEGA_D3
|
|
# define IOPORT_PORTF 5
|
|
#endif
|
|
|
|
#if XMEGA_B1 || XMEGA_B3
|
|
# define IOPORT_PORTG 6
|
|
#endif
|
|
|
|
#if XMEGA_A1 || XMEGA_A1U
|
|
# define IOPORT_PORTH 7
|
|
# define IOPORT_PORTJ 8
|
|
# define IOPORT_PORTK 9
|
|
#endif
|
|
|
|
#if XMEGA_B1 || XMEGA_B3
|
|
# define IOPORT_PORTM 11
|
|
#endif
|
|
|
|
#if XMEGA_A1 || XMEGA_A1U
|
|
# define IOPORT_PORTQ 14
|
|
#endif
|
|
|
|
#define IOPORT_PORTR 15
|
|
/** @} */
|
|
|
|
/**
|
|
* \weakgroup ioport_group
|
|
* \section ioport_modes IOPORT Modes
|
|
*
|
|
* For details on these please see the XMEGA Manual.
|
|
*
|
|
* @{
|
|
*/
|
|
|
|
/** \name IOPORT Mode bit definitions */
|
|
/** @{ */
|
|
#define IOPORT_MODE_TOTEM (0x00 << 3) /*!< Totem-pole */
|
|
#define IOPORT_MODE_BUSKEEPER (0x01 << 3) /*!< Buskeeper */
|
|
#define IOPORT_MODE_PULLDOWN (0x02 << 3) /*!< Pull-down */
|
|
#define IOPORT_MODE_PULLUP (0x03 << 3) /*!< Pull-up */
|
|
#define IOPORT_MODE_WIREDOR (0x04 << 3) /*!< Wired OR */
|
|
#define IOPORT_MODE_WIREDAND (0x05 << 3) /*!< Wired AND */
|
|
#define IOPORT_MODE_WIREDORPULL (0x06 << 3) /*!< Wired OR with pull-down */
|
|
#define IOPORT_MODE_WIREDANDPULL (0x07 << 3) /*!< Wired AND with pull-up */
|
|
#define IOPORT_MODE_INVERT_PIN (0x01 << 6) /*!< Invert output and input */
|
|
#define IOPORT_MODE_SLEW_RATE_LIMIT (0x01 << 7) /*!< Slew rate limiting */
|
|
/** @} */
|
|
|
|
/** @} */
|
|
|
|
typedef uint8_t ioport_mode_t;
|
|
typedef uint8_t ioport_pin_t;
|
|
typedef uint8_t ioport_port_t;
|
|
typedef uint8_t ioport_port_mask_t;
|
|
|
|
__always_inline static ioport_port_t arch_ioport_pin_to_port_id(ioport_pin_t pin)
|
|
{
|
|
return pin >> 3;
|
|
}
|
|
|
|
__always_inline static PORT_t *arch_ioport_port_to_base(ioport_port_t port)
|
|
{
|
|
return (PORT_t *)((uintptr_t)IOPORT_BASE_ADDRESS +
|
|
(port * IOPORT_PORT_OFFSET));
|
|
}
|
|
|
|
__always_inline static PORT_t *arch_ioport_pin_to_base(ioport_pin_t pin)
|
|
{
|
|
return arch_ioport_port_to_base(arch_ioport_pin_to_port_id(pin));
|
|
}
|
|
|
|
__always_inline static ioport_port_mask_t arch_ioport_pin_to_mask(
|
|
ioport_pin_t pin)
|
|
{
|
|
return 1U << (pin & 0x07);
|
|
}
|
|
|
|
__always_inline static ioport_port_mask_t arch_ioport_pin_to_index(
|
|
ioport_pin_t pin)
|
|
{
|
|
return (pin & 0x07);
|
|
}
|
|
|
|
__always_inline static void arch_ioport_init(void)
|
|
{
|
|
}
|
|
|
|
__always_inline static void arch_ioport_enable_port(ioport_port_t port,
|
|
ioport_port_mask_t mask)
|
|
{
|
|
PORT_t *base = arch_ioport_port_to_base(port);
|
|
volatile uint8_t *pin_ctrl = &base->PIN0CTRL;
|
|
|
|
uint8_t flags = cpu_irq_save();
|
|
|
|
for (uint8_t i = 0; i < 8; i++) {
|
|
if (mask & arch_ioport_pin_to_mask(i)) {
|
|
pin_ctrl[i] &= ~PORT_ISC_gm;
|
|
}
|
|
}
|
|
|
|
cpu_irq_restore(flags);
|
|
}
|
|
|
|
__always_inline static void arch_ioport_enable_pin(ioport_pin_t pin)
|
|
{
|
|
PORT_t *base = arch_ioport_pin_to_base(pin);
|
|
volatile uint8_t *pin_ctrl
|
|
= (&base->PIN0CTRL + arch_ioport_pin_to_index(pin));
|
|
|
|
uint8_t flags = cpu_irq_save();
|
|
|
|
*pin_ctrl &= ~PORT_ISC_gm;
|
|
|
|
cpu_irq_restore(flags);
|
|
}
|
|
|
|
__always_inline static void arch_ioport_disable_port(ioport_port_t port,
|
|
ioport_port_mask_t mask)
|
|
{
|
|
PORT_t *base = arch_ioport_port_to_base(port);
|
|
volatile uint8_t *pin_ctrl = &base->PIN0CTRL;
|
|
|
|
uint8_t flags = cpu_irq_save();
|
|
|
|
for (uint8_t i = 0; i < 8; i++) {
|
|
if (mask & arch_ioport_pin_to_mask(i)) {
|
|
pin_ctrl[i] |= PORT_ISC_INPUT_DISABLE_gc;
|
|
}
|
|
}
|
|
|
|
cpu_irq_restore(flags);
|
|
}
|
|
|
|
__always_inline static void arch_ioport_disable_pin(ioport_pin_t pin)
|
|
{
|
|
PORT_t *base = arch_ioport_pin_to_base(pin);
|
|
volatile uint8_t *pin_ctrl
|
|
= (&base->PIN0CTRL + arch_ioport_pin_to_index(pin));
|
|
|
|
uint8_t flags = cpu_irq_save();
|
|
|
|
*pin_ctrl |= PORT_ISC_INPUT_DISABLE_gc;
|
|
|
|
cpu_irq_restore(flags);
|
|
}
|
|
|
|
__always_inline static void arch_ioport_set_port_mode(ioport_port_t port,
|
|
ioport_port_mask_t mask, ioport_mode_t mode)
|
|
{
|
|
PORT_t *base = arch_ioport_port_to_base(port);
|
|
volatile uint8_t *pin_ctrl = &base->PIN0CTRL;
|
|
uint8_t new_mode_bits = (mode & ~PORT_ISC_gm);
|
|
|
|
uint8_t flags = cpu_irq_save();
|
|
|
|
for (uint8_t i = 0; i < 8; i++) {
|
|
if (mask & arch_ioport_pin_to_mask(i)) {
|
|
pin_ctrl[i]
|
|
= (pin_ctrl[i] &
|
|
PORT_ISC_gm) | new_mode_bits;
|
|
}
|
|
}
|
|
|
|
cpu_irq_restore(flags);
|
|
}
|
|
|
|
__always_inline static void arch_ioport_set_pin_mode(ioport_pin_t pin,
|
|
ioport_mode_t mode)
|
|
{
|
|
PORT_t *base = arch_ioport_pin_to_base(pin);
|
|
volatile uint8_t *pin_ctrl
|
|
= (&base->PIN0CTRL + arch_ioport_pin_to_index(pin));
|
|
|
|
uint8_t flags = cpu_irq_save();
|
|
|
|
*pin_ctrl &= PORT_ISC_gm;
|
|
*pin_ctrl |= mode;
|
|
|
|
cpu_irq_restore(flags);
|
|
}
|
|
|
|
__always_inline static void arch_ioport_set_port_dir(ioport_port_t port,
|
|
ioport_port_mask_t mask, enum ioport_direction dir)
|
|
{
|
|
PORT_t *base = arch_ioport_port_to_base(port);
|
|
|
|
if (dir == IOPORT_DIR_OUTPUT) {
|
|
base->DIRSET = mask;
|
|
} else if (dir == IOPORT_DIR_INPUT) {
|
|
base->DIRCLR = mask;
|
|
}
|
|
}
|
|
|
|
__always_inline static void arch_ioport_set_pin_dir(ioport_pin_t pin,
|
|
enum ioport_direction dir)
|
|
{
|
|
PORT_t *base = arch_ioport_pin_to_base(pin);
|
|
|
|
if (dir == IOPORT_DIR_OUTPUT) {
|
|
base->DIRSET = arch_ioport_pin_to_mask(pin);
|
|
} else if (dir == IOPORT_DIR_INPUT) {
|
|
base->DIRCLR = arch_ioport_pin_to_mask(pin);
|
|
}
|
|
}
|
|
|
|
__always_inline static void arch_ioport_set_pin_level(ioport_pin_t pin,
|
|
bool level)
|
|
{
|
|
PORT_t *base = arch_ioport_pin_to_base(pin);
|
|
|
|
if (level) {
|
|
base->OUTSET = arch_ioport_pin_to_mask(pin);
|
|
} else {
|
|
base->OUTCLR = arch_ioport_pin_to_mask(pin);
|
|
}
|
|
}
|
|
|
|
__always_inline static void arch_ioport_set_port_level(ioport_port_t port,
|
|
ioport_port_mask_t mask, enum ioport_value level)
|
|
{
|
|
PORT_t *base = arch_ioport_port_to_base(port);
|
|
if (level) {
|
|
base->OUTSET |= mask;
|
|
base->OUTCLR &= ~mask;
|
|
} else {
|
|
base->OUTSET &= ~mask;
|
|
base->OUTCLR |= mask;
|
|
}
|
|
}
|
|
|
|
__always_inline static bool arch_ioport_get_pin_level(ioport_pin_t pin)
|
|
{
|
|
PORT_t *base = arch_ioport_pin_to_base(pin);
|
|
|
|
return base->IN & arch_ioport_pin_to_mask(pin);
|
|
}
|
|
|
|
__always_inline static ioport_port_mask_t arch_ioport_get_port_level(
|
|
ioport_port_t port, ioport_port_mask_t mask)
|
|
{
|
|
PORT_t *base = arch_ioport_port_to_base(port);
|
|
|
|
return base->IN & mask;
|
|
}
|
|
|
|
__always_inline static void arch_ioport_toggle_pin_level(ioport_pin_t pin)
|
|
{
|
|
PORT_t *base = arch_ioport_pin_to_base(pin);
|
|
|
|
base->OUTTGL = arch_ioport_pin_to_mask(pin);
|
|
}
|
|
|
|
__always_inline static void arch_ioport_toggle_port_level(ioport_port_t port,
|
|
ioport_port_mask_t mask)
|
|
{
|
|
PORT_t *base = arch_ioport_port_to_base(port);
|
|
|
|
base->OUTTGL = mask;
|
|
}
|
|
|
|
__always_inline static void arch_ioport_set_pin_sense_mode(ioport_pin_t pin,
|
|
enum ioport_sense pin_sense)
|
|
{
|
|
PORT_t *base = arch_ioport_pin_to_base(pin);
|
|
volatile uint8_t *pin_ctrl
|
|
= (&base->PIN0CTRL + arch_ioport_pin_to_index(pin));
|
|
|
|
uint8_t flags = cpu_irq_save();
|
|
|
|
*pin_ctrl &= ~PORT_ISC_gm;
|
|
*pin_ctrl |= (pin_sense & PORT_ISC_gm);
|
|
|
|
cpu_irq_restore(flags);
|
|
}
|
|
|
|
__always_inline static void arch_ioport_set_port_sense_mode(ioport_port_t port,
|
|
ioport_port_mask_t mask, enum ioport_sense pin_sense)
|
|
{
|
|
PORT_t *base = arch_ioport_port_to_base(port);
|
|
volatile uint8_t *pin_ctrl = &base->PIN0CTRL;
|
|
uint8_t new_sense_bits = (pin_sense & PORT_ISC_gm);
|
|
|
|
uint8_t flags = cpu_irq_save();
|
|
|
|
for (uint8_t i = 0; i < 8; i++) {
|
|
if (mask & arch_ioport_pin_to_mask(i)) {
|
|
pin_ctrl[i]
|
|
= (pin_ctrl[i] &
|
|
~PORT_ISC_gm) | new_sense_bits;
|
|
}
|
|
}
|
|
|
|
cpu_irq_restore(flags);
|
|
}
|
|
|
|
#endif /* IOPORT_XMEGA_H */
|