-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
132 additions
and
63 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,28 @@ | ||
/* | ||
* Copyright (C) 2015-2016 Freie Universität Berlin | ||
* 2017 HAW Hamburg | ||
* | ||
* This file is subject to the terms and conditions of the GNU Lesser | ||
* General Public License v2.1. See the file LICENSE in the top level | ||
* directory for more details. | ||
*/ | ||
|
||
/** | ||
* @ingroup cpu_cc2538 | ||
* @ingroup cpu_cc2538 | ||
* @{ | ||
* | ||
* @file | ||
* @brief CPU specific definitions for internal peripheral handling | ||
* @brief CPU specific definitions for internal peripheral handling | ||
* | ||
* @author Hauke Petersen <[email protected]> | ||
* @author Hauke Petersen <[email protected]> | ||
* @author Sebastian Meiling <[email protected]> | ||
*/ | ||
|
||
#ifndef PERIPH_CPU_H | ||
#define PERIPH_CPU_H | ||
|
||
#include <stdint.h> | ||
#include <stdio.h> | ||
|
||
#include "cpu.h" | ||
|
||
|
@@ -44,13 +47,104 @@ extern "C" { | |
typedef uint32_t gpio_t; | ||
/** @} */ | ||
|
||
/** | ||
* @name Internal GPIO shift and masking | ||
* @{ | ||
*/ | ||
#define PORTNUM_MASK (0x00007000) /**< bit mask for GPIO port [0-3] */ | ||
#define PORTNUM_SHIFT (12U) /**< bit shift for GPIO port */ | ||
#define PIN_MASK (0x00000007) /**< bit mask for GPIO pin [0-7] */ | ||
#define GPIO_MASK (0xfffff000) /**< bit mask for GPIO port addr */ | ||
/** @} */ | ||
|
||
/** | ||
* @brief Define a custom GPIO_PIN macro | ||
* | ||
* For the CC2538, we use OR the gpio ports base register address with the | ||
* actual pin number. | ||
*/ | ||
#define GPIO_PIN(port, pin) (gpio_t)(((uint32_t)GPIO_A + (port << 12)) | pin) | ||
#define GPIO_PIN(port, pin) (gpio_t)(((uint32_t)GPIO_A + \ | ||
(port << PORTNUM_SHIFT)) | pin) | ||
|
||
/** | ||
* @brief Access GPIO low-level device | ||
* | ||
* @param[in] pin gpio pin | ||
* | ||
* @return pointer to gpio low level device address | ||
*/ | ||
static inline cc2538_gpio_t *gpio(gpio_t pin) | ||
{ | ||
return (cc2538_gpio_t *)(pin & GPIO_MASK); | ||
} | ||
|
||
/** | ||
* @brief Helper function to get port number for gpio pin | ||
* | ||
* @param[in] pin gpio pin | ||
* | ||
* @return port number of gpio pin, [0=A - 3=D] | ||
*/ | ||
static inline uint8_t gpio_port_num(gpio_t pin) | ||
{ | ||
return (uint8_t)((pin & PORTNUM_MASK) >> PORTNUM_SHIFT) - 1; | ||
} | ||
|
||
/** | ||
* @brief Helper function to get pin number for gpio pin | ||
* | ||
* @param[in] pin gpio pin | ||
* | ||
* @return pin number of gpio pin, [0 - 7] | ||
*/ | ||
static inline uint8_t gpio_pin_num(gpio_t pin) | ||
{ | ||
return (uint8_t)(pin & PIN_MASK); | ||
} | ||
|
||
/** | ||
* @brief Helper function to get bit mask for gpio pin number | ||
* | ||
* @param[in] pin gpio pin | ||
* | ||
* @return bit mask for gpio pin number, 2^[0 - 7] | ||
*/ | ||
static inline uint32_t gpio_pin_mask(gpio_t pin) | ||
{ | ||
return (1 << (pin & PIN_MASK)); | ||
} | ||
|
||
/** | ||
* @brief Helper function to get CC2538 gpio number from port and pin | ||
* | ||
* @param[in] pin gpio pin | ||
* | ||
* @return number of gpio pin, [0 - 31] | ||
*/ | ||
static inline uint8_t gpio_pp_num(gpio_t pin) | ||
{ | ||
return (uint8_t)((gpio_port_num(pin) * 8) + gpio_pin_num(pin)); | ||
} | ||
|
||
/** | ||
* @brief Helper function to enable gpio hardware control | ||
* | ||
* @param[in] pin gpio pin | ||
*/ | ||
static inline void gpio_hw_ctrl(gpio_t pin) | ||
{ | ||
gpio(pin)->AFSEL |= gpio_pin_mask(pin); | ||
} | ||
|
||
/** | ||
* @brief Helper function to enable gpio software control | ||
* | ||
* @param[in] pin gpio pin | ||
*/ | ||
static inline void gpio_sw_ctrl(gpio_t pin) | ||
{ | ||
gpio(pin)->AFSEL &= ~gpio_pin_mask(pin); | ||
} | ||
|
||
/** | ||
* @brief Define a custom GPIO_UNDEF value | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,7 +17,7 @@ | |
* | ||
* @author Ian Martin <[email protected]> | ||
* @author Hauke Petersen <[email protected]> | ||
* | ||
* @author Sebastian Meiling <[email protected]> | ||
* @} | ||
*/ | ||
|
||
|
@@ -26,36 +26,10 @@ | |
#include "cpu.h" | ||
#include "periph/gpio.h" | ||
|
||
#define GPIO_MASK (0xfffff000) | ||
#define PORTNUM_MASK (0x00007000) | ||
#define PORTNUM_SHIFT (12U) | ||
#define PIN_MASK (0x00000007) | ||
#define MODE_NOTSUP (0xff) | ||
|
||
static inline cc2538_gpio_t *gpio(gpio_t pin) | ||
{ | ||
return (cc2538_gpio_t *)(pin & GPIO_MASK); | ||
} | ||
#define ENABLE_DEBUG (0) | ||
#include "debug.h" | ||
|
||
static inline int port_num(gpio_t pin) | ||
{ | ||
return (int)((pin & PORTNUM_MASK) >> PORTNUM_SHIFT) - 1; | ||
} | ||
|
||
static inline int pin_num(gpio_t pin) | ||
{ | ||
return (int)(pin & PIN_MASK); | ||
} | ||
|
||
static inline uint32_t pin_mask(gpio_t pin) | ||
{ | ||
return (1 << (pin & PIN_MASK)); | ||
} | ||
|
||
static inline int pp_num(gpio_t pin) | ||
{ | ||
return (port_num(pin) * 8) + pin_num(pin); | ||
} | ||
#define MODE_NOTSUP (0xff) | ||
|
||
static gpio_isr_ctx_t isr_ctx[4][8]; | ||
|
||
|
@@ -66,22 +40,23 @@ int gpio_init(gpio_t pin, gpio_mode_t mode) | |
return -1; | ||
} | ||
|
||
DEBUG("GPIO %"PRIu32", PORT: %u, PIN: %u\n", (uint32_t)pin, gpio_port_num(pin), gpio_pin_num(pin)); | ||
|
||
/* disable any alternate function and any eventual interrupts */ | ||
gpio(pin)->IE &= ~pin_mask(pin); | ||
gpio(pin)->AFSEL &= ~pin_mask(pin); | ||
gpio(pin)->IE &= ~gpio_pin_mask(pin); | ||
gpio(pin)->AFSEL &= ~gpio_pin_mask(pin); | ||
/* configure pull configuration */ | ||
IOC->OVER[pp_num(pin)] = mode; | ||
IOC->OVER[gpio_pp_num(pin)] = mode; | ||
|
||
/* set pin direction */ | ||
if (mode == IOC_OVERRIDE_OE) { | ||
gpio(pin)->DIR |= pin_mask(pin); | ||
gpio(pin)->DIR |= gpio_pin_mask(pin); | ||
} | ||
else { | ||
gpio(pin)->DIR &= ~pin_mask(pin); | ||
gpio(pin)->DIR &= ~gpio_pin_mask(pin); | ||
} | ||
/* clear pin */ | ||
gpio(pin)->DATA &= ~pin_mask(pin); | ||
gpio(pin)->DATA &= ~gpio_pin_mask(pin); | ||
|
||
return 0; | ||
} | ||
|
@@ -94,80 +69,80 @@ int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank, | |
} | ||
|
||
/* store the callback information for later: */ | ||
isr_ctx[port_num(pin)][pin_num(pin)].cb = cb; | ||
isr_ctx[port_num(pin)][pin_num(pin)].arg = arg; | ||
isr_ctx[gpio_port_num(pin)][gpio_pin_num(pin)].cb = cb; | ||
isr_ctx[gpio_port_num(pin)][gpio_pin_num(pin)].arg = arg; | ||
|
||
/* enable power-up interrupts for this GPIO port: */ | ||
SYS_CTRL->IWE |= (1 << port_num(pin)); | ||
SYS_CTRL->IWE |= (1 << gpio_port_num(pin)); | ||
|
||
/* configure the active flank(s) */ | ||
gpio(pin)->IS &= ~pin_mask(pin); | ||
gpio(pin)->IS &= ~gpio_pin_mask(pin); | ||
switch(flank) { | ||
case GPIO_FALLING: | ||
gpio(pin)->IBE &= ~pin_mask(pin); | ||
gpio(pin)->IEV &= ~pin_mask(pin); | ||
gpio(pin)->P_EDGE_CTRL |= (1 << pp_num(pin)); | ||
gpio(pin)->IBE &= ~gpio_pin_mask(pin); | ||
gpio(pin)->IEV &= ~gpio_pin_mask(pin); | ||
gpio(pin)->P_EDGE_CTRL |= (1 << gpio_pp_num(pin)); | ||
break; | ||
case GPIO_RISING: | ||
gpio(pin)->IBE &= ~pin_mask(pin); | ||
gpio(pin)->IEV |= pin_mask(pin); | ||
gpio(pin)->P_EDGE_CTRL &= ~(1 << pp_num(pin)); | ||
gpio(pin)->IBE &= ~gpio_pin_mask(pin); | ||
gpio(pin)->IEV |= gpio_pin_mask(pin); | ||
gpio(pin)->P_EDGE_CTRL &= ~(1 << gpio_pp_num(pin)); | ||
break; | ||
case GPIO_BOTH: | ||
gpio(pin)->IBE |= pin_mask(pin); | ||
gpio(pin)->IBE |= gpio_pin_mask(pin); | ||
break; | ||
default: | ||
return -1; | ||
} | ||
|
||
/* reset interrupt status */ | ||
gpio(pin)->IC = pin_mask(pin); | ||
gpio(pin)->PI_IEN |= (1 << pp_num(pin)); | ||
gpio(pin)->IC = gpio_pin_mask(pin); | ||
gpio(pin)->PI_IEN |= (1 << gpio_pp_num(pin)); | ||
/* enable global interrupt for the selected GPIO port */ | ||
NVIC_EnableIRQ(GPIO_PORT_A_IRQn + port_num(pin)); | ||
NVIC_EnableIRQ(GPIO_PORT_A_IRQn + gpio_port_num(pin)); | ||
/* unmask pin interrupt */ | ||
gpio(pin)->IE |= pin_mask(pin); | ||
gpio(pin)->IE |= gpio_pin_mask(pin); | ||
|
||
return 0; | ||
} | ||
|
||
void gpio_irq_enable(gpio_t pin) | ||
{ | ||
gpio(pin)->IE |= pin_mask(pin); | ||
gpio(pin)->IE |= gpio_pin_mask(pin); | ||
} | ||
|
||
void gpio_irq_disable(gpio_t pin) | ||
{ | ||
gpio(pin)->IE &= ~pin_mask(pin); | ||
gpio(pin)->IE &= ~gpio_pin_mask(pin); | ||
} | ||
|
||
int gpio_read(gpio_t pin) | ||
{ | ||
return (int)(gpio(pin)->DATA & pin_mask(pin)); | ||
return (int)(gpio(pin)->DATA & gpio_pin_mask(pin)); | ||
} | ||
|
||
void gpio_set(gpio_t pin) | ||
{ | ||
gpio(pin)->DATA |= pin_mask(pin); | ||
gpio(pin)->DATA |= gpio_pin_mask(pin); | ||
} | ||
|
||
void gpio_clear(gpio_t pin) | ||
{ | ||
gpio(pin)->DATA &= ~pin_mask(pin); | ||
gpio(pin)->DATA &= ~gpio_pin_mask(pin); | ||
} | ||
|
||
void gpio_toggle(gpio_t pin) | ||
{ | ||
gpio(pin)->DATA ^= pin_mask(pin); | ||
gpio(pin)->DATA ^= gpio_pin_mask(pin); | ||
} | ||
|
||
void gpio_write(gpio_t pin, int value) | ||
{ | ||
if (value) { | ||
gpio(pin)->DATA |= pin_mask(pin); | ||
gpio(pin)->DATA |= gpio_pin_mask(pin); | ||
} | ||
else { | ||
gpio(pin)->DATA &= ~pin_mask(pin); | ||
gpio(pin)->DATA &= ~gpio_pin_mask(pin); | ||
} | ||
} | ||
|
||
|