1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/cpu/lpc11u34/periph/gpio.c
2015-10-02 14:56:52 +02:00

502 lines
10 KiB
C

/*
* Copyright (C) 2015 Freie Universität Berlin
*
* 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_lpc11u34
* @{
*
* @file
* @brief Low-level GPIO driver implementation
*
* @author Paul RATHGEB <paul.rathgeb@skynet.be>
*
* @}
*/
#include "cpu.h"
#include "thread.h"
#include "periph/gpio.h"
typedef struct {
gpio_cb_t cb;
void *arg;
} gpio_state_t;
/* Static IOCON registers definition */
volatile uint32_t * const lpc_pin_registers[] = {
/* PORT 0 (PIO0_0 -> PIO0_23) */
&LPC_IOCON->RESET_PIO0_0, &LPC_IOCON->PIO0_1,
&LPC_IOCON->PIO0_2, &LPC_IOCON->PIO0_3,
&LPC_IOCON->PIO0_4, &LPC_IOCON->PIO0_5,
&LPC_IOCON->PIO0_6, &LPC_IOCON->PIO0_7,
&LPC_IOCON->PIO0_8, &LPC_IOCON->PIO0_9,
&LPC_IOCON->SWCLK_PIO0_10, &LPC_IOCON->TDI_PIO0_11,
&LPC_IOCON->TMS_PIO0_12, &LPC_IOCON->TDO_PIO0_13,
&LPC_IOCON->TRST_PIO0_14, &LPC_IOCON->SWDIO_PIO0_15,
&LPC_IOCON->PIO0_16, &LPC_IOCON->PIO0_17,
&LPC_IOCON->PIO0_18, &LPC_IOCON->PIO0_19,
&LPC_IOCON->PIO0_20, &LPC_IOCON->PIO0_21,
&LPC_IOCON->PIO0_22, &LPC_IOCON->PIO0_23,
/* PORT 1 (PIO1_0 -> PIO0_31) */
&LPC_IOCON->PIO1_0, &LPC_IOCON->PIO1_1,
&LPC_IOCON->PIO1_2, &LPC_IOCON->PIO1_3,
&LPC_IOCON->PIO1_4, &LPC_IOCON->PIO1_5,
&LPC_IOCON->PIO1_6, &LPC_IOCON->PIO1_7,
&LPC_IOCON->PIO1_8, &LPC_IOCON->PIO1_9,
&LPC_IOCON->PIO1_10, &LPC_IOCON->PIO1_11,
&LPC_IOCON->PIO1_12, &LPC_IOCON->PIO1_13,
&LPC_IOCON->PIO1_14, &LPC_IOCON->PIO1_15,
&LPC_IOCON->PIO1_16, &LPC_IOCON->PIO1_17,
&LPC_IOCON->PIO1_18, &LPC_IOCON->PIO1_19,
&LPC_IOCON->PIO1_20, &LPC_IOCON->PIO1_21,
&LPC_IOCON->PIO1_22, &LPC_IOCON->PIO1_23,
&LPC_IOCON->PIO1_24, &LPC_IOCON->PIO1_25,
&LPC_IOCON->PIO1_26, &LPC_IOCON->PIO1_27,
&LPC_IOCON->PIO1_28, &LPC_IOCON->PIO1_29,
&LPC_IOCON->PIO1_30, &LPC_IOCON->PIO1_31,
};
static int8_t flex_int_mapping[GPIO_NUMOF];
static gpio_state_t gpio_config[GPIO_NUMOF];
static uint8_t gpio_int_id = 0;
/* static port mappings */
static const uint8_t gpio_port_map[GPIO_NUMOF] = {
#if GPIO_0_EN
[GPIO_0] = GPIO_0_PORT,
#endif
#if GPIO_1_EN
[GPIO_1] = GPIO_1_PORT,
#endif
#if GPIO_2_EN
[GPIO_2] = GPIO_2_PORT,
#endif
#if GPIO_3_EN
[GPIO_3] = GPIO_3_PORT,
#endif
#if GPIO_4_EN
[GPIO_4] = GPIO_4_PORT,
#endif
#if GPIO_5_EN
[GPIO_5] = GPIO_5_PORT,
#endif
#if GPIO_6_EN
[GPIO_6] = GPIO_6_PORT,
#endif
#if GPIO_7_EN
[GPIO_7] = GPIO_7_PORT,
#endif
#if GPIO_8_EN
[GPIO_8] = GPIO_8_PORT,
#endif
#if GPIO_9_EN
[GPIO_9] = GPIO_9_PORT,
#endif
#if GPIO_10_EN
[GPIO_10] = GPIO_10_PORT,
#endif
#if GPIO_11_EN
[GPIO_11] = GPIO_11_PORT,
#endif
#if GPIO_12_EN
[GPIO_12] = GPIO_12_PORT,
#endif
#if GPIO_13_EN
[GPIO_13] = GPIO_13_PORT,
#endif
#if GPIO_14_EN
[GPIO_14] = GPIO_14_PORT,
#endif
#if GPIO_15_EN
[GPIO_15] = GPIO_15_PORT,
#endif
#if GPIO_16_EN
[GPIO_16] = GPIO_16_PORT,
#endif
#if GPIO_17_EN
[GPIO_17] = GPIO_17_PORT,
#endif
#if GPIO_18_EN
[GPIO_18] = GPIO_18_PORT,
#endif
#if GPIO_19_EN
[GPIO_19] = GPIO_19_PORT,
#endif
#if GPIO_20_EN
[GPIO_20] = GPIO_20_PORT,
#endif
#if GPIO_21_EN
[GPIO_21] = GPIO_21_PORT,
#endif
#if GPIO_22_EN
[GPIO_22] = GPIO_22_PORT,
#endif
#if GPIO_23_EN
[GPIO_23] = GPIO_23_PORT,
#endif
#if GPIO_24_EN
[GPIO_24] = GPIO_24_PORT,
#endif
#if GPIO_25_EN
[GPIO_25] = GPIO_25_PORT,
#endif
#if GPIO_26_EN
[GPIO_26] = GPIO_26_PORT,
#endif
#if GPIO_27_EN
[GPIO_27] = GPIO_27_PORT,
#endif
#if GPIO_28_EN
[GPIO_28] = GPIO_28_PORT,
#endif
#if GPIO_29_EN
[GPIO_29] = GPIO_29_PORT,
#endif
#if GPIO_30_EN
[GPIO_30] = GPIO_30_PORT,
#endif
#if GPIO_31_EN
[GPIO_31] = GPIO_31_PORT,
#endif
};
/* static pin mappings */
static const uint8_t gpio_pin_map[GPIO_NUMOF] = {
#if GPIO_0_EN
[GPIO_0] = GPIO_0_PIN,
#endif
#if GPIO_1_EN
[GPIO_1] = GPIO_1_PIN,
#endif
#if GPIO_2_EN
[GPIO_2] = GPIO_2_PIN,
#endif
#if GPIO_3_EN
[GPIO_3] = GPIO_3_PIN,
#endif
#if GPIO_4_EN
[GPIO_4] = GPIO_4_PIN,
#endif
#if GPIO_5_EN
[GPIO_5] = GPIO_5_PIN,
#endif
#if GPIO_6_EN
[GPIO_6] = GPIO_6_PIN,
#endif
#if GPIO_7_EN
[GPIO_7] = GPIO_7_PIN,
#endif
#if GPIO_8_EN
[GPIO_8] = GPIO_8_PIN,
#endif
#if GPIO_9_EN
[GPIO_9] = GPIO_9_PIN,
#endif
#if GPIO_10_EN
[GPIO_10] = GPIO_10_PIN,
#endif
#if GPIO_11_EN
[GPIO_11] = GPIO_11_PIN,
#endif
#if GPIO_12_EN
[GPIO_12] = GPIO_12_PIN,
#endif
#if GPIO_13_EN
[GPIO_13] = GPIO_13_PIN,
#endif
#if GPIO_14_EN
[GPIO_14] = GPIO_14_PIN,
#endif
#if GPIO_15_EN
[GPIO_15] = GPIO_15_PIN,
#endif
#if GPIO_16_EN
[GPIO_16] = GPIO_16_PIN,
#endif
#if GPIO_17_EN
[GPIO_17] = GPIO_17_PIN,
#endif
#if GPIO_18_EN
[GPIO_18] = GPIO_18_PIN,
#endif
#if GPIO_19_EN
[GPIO_19] = GPIO_19_PIN,
#endif
#if GPIO_20_EN
[GPIO_20] = GPIO_20_PIN,
#endif
#if GPIO_21_EN
[GPIO_21] = GPIO_21_PIN,
#endif
#if GPIO_22_EN
[GPIO_22] = GPIO_22_PIN,
#endif
#if GPIO_23_EN
[GPIO_23] = GPIO_23_PIN,
#endif
#if GPIO_24_EN
[GPIO_24] = GPIO_24_PIN,
#endif
#if GPIO_25_EN
[GPIO_25] = GPIO_25_PIN,
#endif
#if GPIO_26_EN
[GPIO_26] = GPIO_26_PIN,
#endif
#if GPIO_27_EN
[GPIO_27] = GPIO_27_PIN,
#endif
#if GPIO_28_EN
[GPIO_28] = GPIO_28_PIN,
#endif
#if GPIO_29_EN
[GPIO_29] = GPIO_29_PIN,
#endif
#if GPIO_30_EN
[GPIO_30] = GPIO_30_PIN,
#endif
#if GPIO_31_EN
[GPIO_31] = GPIO_31_PIN,
#endif
};
int gpio_init(gpio_t dev, gpio_dir_t dir, gpio_pp_t pullup)
{
uint8_t port;
uint8_t pin;
if (dev >= GPIO_NUMOF) {
return -1;
}
/* Get the port and pin values */
port = gpio_port_map[dev];
pin = gpio_pin_map[dev];
/* Put pin in the primary function */
*lpc_pin_registers[pin + (port * 24)] = *lpc_pin_registers[pin + (port * 24)] & ~(0x07);
/* Disable resistors */
*lpc_pin_registers[pin + (port * 24)] &= ~(3 << 3);
/* Set resistors */
if (pullup == GPIO_PULLUP) {
*lpc_pin_registers[pin + (port * 24)] |= (2 << 3);
}
else if (pullup == GPIO_PULLDOWN) {
*lpc_pin_registers[pin + (port * 24)] |= (1 << 3);
}
/* Set direction */
if (dir == GPIO_DIR_OUT) {
LPC_GPIO->DIR[port] |= (1 << pin); /* set pin to output mode */
}
else {
LPC_GPIO->DIR[port] &= ~(1 << pin); /* set pin to output mode */
}
return 0; /* all OK */
}
int gpio_init_int(gpio_t dev, gpio_pp_t pullup, gpio_flank_t flank, gpio_cb_t cb, void *arg)
{
int res;
uint8_t pin;
uint8_t port;
LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 19);
if (dev >= GPIO_NUMOF) {
return -1;
}
if (gpio_int_id > 7) {
return -1;
}
port = gpio_port_map[dev];
pin = gpio_pin_map[dev];
/* configure pin as input */
res = gpio_init(dev, GPIO_DIR_IN, pullup);
if (res < 0) {
return res;
}
/* Disable interrupts */
NVIC_DisableIRQ(gpio_int_id);
/* Register pin as flex interrupt */
LPC_SYSCON->PINTSEL[gpio_int_id] = (port * 24) + pin;
/* set callback */
gpio_config[gpio_int_id].cb = cb;
gpio_config[gpio_int_id].arg = arg;
/* configure the event that triggers an interrupt */
switch (flank) {
case GPIO_RISING:
LPC_GPIO_PIN_INT->ISEL &= ~(1 << gpio_int_id); /* Set PMODE=edge sensitive */
LPC_GPIO_PIN_INT->IENR |= (1 << gpio_int_id); /* Enable rising edge. */
LPC_GPIO_PIN_INT->IENF &= ~(1 << gpio_int_id); /* Disable falling edge. */
break;
case GPIO_FALLING:
LPC_GPIO_PIN_INT->ISEL &= ~(1 << gpio_int_id); /* Set PMODE=edge sensitive */
LPC_GPIO_PIN_INT->IENR &= ~(1 << gpio_int_id); /* Disable rising edge. */
LPC_GPIO_PIN_INT->IENF |= (1 << gpio_int_id); /* Enable falling edge. */
break;
case GPIO_BOTH:
LPC_GPIO_PIN_INT->ISEL &= ~(1 << gpio_int_id); /* Set PMODE=edge sensitive */
LPC_GPIO_PIN_INT->IENR |= (1 << gpio_int_id); /* Enable rising edge. */
LPC_GPIO_PIN_INT->IENF |= (1 << gpio_int_id); /* Enable falling edge. */
break;
}
/* clear any pending requests */
LPC_GPIO_PIN_INT->RISE = (1 << gpio_int_id); /* Clear rising edge (sort of) flag */
LPC_GPIO_PIN_INT->FALL = (1 << gpio_int_id); /* Clear falling edge (sort of) flag */
NVIC_SetPriority(gpio_int_id, 3);
flex_int_mapping[dev] = gpio_int_id+1;
gpio_int_id++;
return 0;
}
void gpio_irq_enable(gpio_t dev)
{
if (dev >= GPIO_NUMOF) {
return;
}
NVIC_EnableIRQ(flex_int_mapping[dev]-1);
}
void gpio_irq_disable(gpio_t dev)
{
uint8_t int_id;
if (dev >= GPIO_NUMOF) {
return;
}
int_id = flex_int_mapping[dev] - 1;
NVIC_DisableIRQ(int_id);
}
int gpio_read(gpio_t dev)
{
uint8_t port;
uint8_t pin;
if (dev >= GPIO_NUMOF) {
return -1;
}
port = gpio_port_map[dev];
pin = gpio_pin_map[dev];
if(LPC_GPIO->PIN[port] & (1 << pin)) /* read output data register */
return 1;
else
return 0;
}
void gpio_set(gpio_t dev)
{
uint8_t port;
uint8_t pin;
if (dev >= GPIO_NUMOF) {
return;
}
port = gpio_port_map[dev];
pin = gpio_pin_map[dev];
LPC_GPIO->SET[port] = (1 << pin);
}
void gpio_clear(gpio_t dev)
{
uint8_t port;
uint8_t pin;
if (dev >= GPIO_NUMOF) {
return;
}
port = gpio_port_map[dev];
pin = gpio_pin_map[dev];
LPC_GPIO->CLR[port] = (1 << pin);
}
void gpio_toggle(gpio_t dev)
{
if (dev >= GPIO_NUMOF) {
return;
}
LPC_GPIO->NOT[gpio_port_map[dev]] = (1 << gpio_pin_map[dev]);
}
void gpio_write(gpio_t dev, int value)
{
if (value) {
gpio_set(dev);
} else {
gpio_clear(dev);
}
}
static inline void isr_common(uint8_t int_id) {
LPC_GPIO_PIN_INT->IST |= (1 << int_id); /* Clear pending interrupt */
gpio_config[int_id].cb(gpio_config[int_id].arg);
if (sched_context_switch_request) {
thread_yield();
}
}
void isr_pinint0(void)
{
isr_common(0);
}
void isr_pinint1(void)
{
isr_common(1);
}
void isr_pinint2(void)
{
isr_common(2);
}
void isr_pinint3(void)
{
isr_common(3);
}
void isr_pinint4(void)
{
isr_common(4);
}
void isr_pinint5(void)
{
isr_common(5);
}
void isr_pinint6(void)
{
isr_common(6);
}
void isr_pinint7(void)
{
isr_common(7);
}