From 7fe593af9cb6370414dc54e12f5e17f5e8ae13d9 Mon Sep 17 00:00:00 2001 From: Nathael Pajani Date: Thu, 17 Apr 2014 23:56:33 +0200 Subject: [PATCH] Very big commit for a big rewrite of the pins configuration process, making it easier to select pins functions and configure the code according to the hardware. Some parts still have to be improved (dependent on pins being on port 0). At least the code compiles and runs on the target, and the parts I tested run fine. --- core/pio.c | 141 ++++++++++++++ core/system.c | 29 --- drivers/adc.c | 14 +- drivers/eeprom.c | 14 +- drivers/gpio.c | 346 +++++------------------------------ drivers/i2c.c | 9 +- drivers/serial.c | 15 +- drivers/ssp.c | 43 +++-- drivers/status_led.c | 124 +++++++++++++ drivers/timers.c | 40 +++- include/core/lpc_regs_12xx.h | 2 +- include/core/pio.h | 262 ++++++++++++++++++++++++++ include/drivers/gpio.h | 35 +--- include/drivers/ssp.h | 5 - include/drivers/status_led.h | 52 ++++++ include/drivers/timers.h | 56 ------ 16 files changed, 717 insertions(+), 470 deletions(-) create mode 100644 core/pio.c create mode 100644 drivers/status_led.c create mode 100644 include/core/pio.h create mode 100644 include/drivers/status_led.h diff --git a/core/pio.c b/core/pio.c new file mode 100644 index 0000000..b2afd9f --- /dev/null +++ b/core/pio.c @@ -0,0 +1,141 @@ +/**************************************************************************** + * core/pio.c + * + * Copyright 2012 Nathael Pajani + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + *************************************************************************** */ + +/***************************************************************************** */ +/* GPIOs */ +/***************************************************************************** */ + + + +#include +#include "core/lpc_regs_12xx.h" +#include "core/lpc_core_cm0.h" +#include "core/system.h" +#include "core/pio.h" + + +/***************************************************************************** */ +/* Public access to GPIO setup */ +static volatile uint32_t* pio_regs_handles_port0[PORT0_NB_PINS] = { + &(LPC_IO_CONTROL->pio0_0), + &(LPC_IO_CONTROL->pio0_1), + &(LPC_IO_CONTROL->pio0_2), + &(LPC_IO_CONTROL->pio0_3), + &(LPC_IO_CONTROL->pio0_4), + &(LPC_IO_CONTROL->pio0_5), + &(LPC_IO_CONTROL->pio0_6), + &(LPC_IO_CONTROL->pio0_7), + &(LPC_IO_CONTROL->pio0_8), + &(LPC_IO_CONTROL->pio0_9), + &(LPC_IO_CONTROL->pio0_10), + &(LPC_IO_CONTROL->pio0_11), + &(LPC_IO_CONTROL->pio0_12), + &(LPC_IO_CONTROL->pio0_13), + &(LPC_IO_CONTROL->pio0_14), + &(LPC_IO_CONTROL->pio0_15), + &(LPC_IO_CONTROL->pio0_16), + &(LPC_IO_CONTROL->pio0_17), + &(LPC_IO_CONTROL->pio0_18), + &(LPC_IO_CONTROL->pio0_19), + &(LPC_IO_CONTROL->pio0_20), + &(LPC_IO_CONTROL->pio0_21), + &(LPC_IO_CONTROL->pio0_22), + &(LPC_IO_CONTROL->pio0_23), + &(LPC_IO_CONTROL->pio0_24), + &(LPC_IO_CONTROL->pio0_25), + &(LPC_IO_CONTROL->pio0_26), + &(LPC_IO_CONTROL->pio0_27), + &(LPC_IO_CONTROL->pio0_28), + &(LPC_IO_CONTROL->pio0_29), + &(LPC_IO_CONTROL->pio0_30), + &(LPC_IO_CONTROL->pio0_31), +}; +static volatile uint32_t* pio_regs_handles_port1[PORT1_NB_PINS] = { + &(LPC_IO_CONTROL->pio1_0), + &(LPC_IO_CONTROL->pio1_1), + &(LPC_IO_CONTROL->pio1_2), + &(LPC_IO_CONTROL->pio1_3), + &(LPC_IO_CONTROL->pio1_4), + &(LPC_IO_CONTROL->pio1_5), + &(LPC_IO_CONTROL->pio1_6), +}; +static volatile uint32_t* pio_regs_handles_port2[PORT2_NB_PINS] = { + &(LPC_IO_CONTROL->pio2_0), + &(LPC_IO_CONTROL->pio2_1), + &(LPC_IO_CONTROL->pio2_2), + &(LPC_IO_CONTROL->pio2_3), + &(LPC_IO_CONTROL->pio2_4), + &(LPC_IO_CONTROL->pio2_5), + &(LPC_IO_CONTROL->pio2_6), + &(LPC_IO_CONTROL->pio2_7), + &(LPC_IO_CONTROL->pio2_8), + &(LPC_IO_CONTROL->pio2_9), + &(LPC_IO_CONTROL->pio2_10), + &(LPC_IO_CONTROL->pio2_11), + &(LPC_IO_CONTROL->pio2_12), + &(LPC_IO_CONTROL->pio2_13), + &(LPC_IO_CONTROL->pio2_14), + &(LPC_IO_CONTROL->pio2_15), +}; + +void pio_copy(struct pio* dst, struct pio* src) +{ + dst->port = src->port; + dst->pin = src->pin; + dst->alt_setting = src->alt_setting; +} + +void config_pio(struct pio* pp, uint32_t mode) +{ + volatile uint32_t* handle = NULL; + + switch (pp->port) { + case 0: + if (pp->pin >= PORT0_NB_PINS) + return; + handle = pio_regs_handles_port0[pp->pin]; + break; + case 1: + if (pp->pin >= PORT1_NB_PINS) + return; + handle = pio_regs_handles_port1[pp->pin]; + break; + case 2: + if (pp->pin >= PORT2_NB_PINS) + return; + handle = pio_regs_handles_port2[pp->pin]; + break; + default: + return; + } + /* Make sure IO_Config is clocked */ + io_config_clk_on(); + + *handle = (LPC_IO_FUNC_ALT(pp->alt_setting) | mode); + + /* Config done, power off IO_CONFIG block */ + io_config_clk_off(); +} + + +/* FIXME: We should add some system-wide way to "reserve" a pin, but anyway this + * would not prevent anyone from configuring the same pin for two diferent functions + * when not using our code. + */ diff --git a/core/system.c b/core/system.c index 3db2330..d2c2872 100644 --- a/core/system.c +++ b/core/system.c @@ -277,35 +277,6 @@ void clkout_off(void) { } -/***************************************************************************** */ -/* Peripheral Pins */ -/***************************************************************************** */ -void Dummy_Pin_Config(void) { - do { } while (0); -} - -void set_i2c_pins(void) __attribute__ ((weak, alias ("Dummy_Pin_Config"))); -void set_ssp_pins(void) __attribute__ ((weak, alias ("Dummy_Pin_Config"))); -void set_uarts_pins(void) __attribute__ ((weak, alias ("Dummy_Pin_Config"))); -void set_gpio_pins(void) __attribute__ ((weak, alias ("Dummy_Pin_Config"))); -void set_adc_pins(void) __attribute__ ((weak, alias ("Dummy_Pin_Config"))); - -void system_set_default_pins(void) -{ - /* Set all pins as GPIO first, those used for something else will - override the settings in corresponding pin setup functions. */ - set_gpio_pins(); - set_uarts_pins(); - set_i2c_pins(); - set_ssp_pins(); - set_adc_pins(); -} - -/* FIXME: We should add some system-wide way to "reserve" a pin. - This would not prevent anyone from configuring the same pin for two diferent - functions. - */ - /***************************************************************************** */ /* Note that if the systick core functions are used these will be overridden */ diff --git a/drivers/adc.c b/drivers/adc.c index d40ea21..3cffe61 100644 --- a/drivers/adc.c +++ b/drivers/adc.c @@ -28,7 +28,7 @@ #include "core/lpc_regs_12xx.h" #include "core/lpc_core_cm0.h" #include "core/system.h" -#include "drivers/gpio.h" +#include "core/pio.h" /* Should be as near to 9MHz as possible */ #define adc_clk_Val 9000000 @@ -124,15 +124,15 @@ void adc_set_resolution(int bits) /***************************************************************************** */ /* ADC Setup : private part : Clocks, Pins, Power and Mode */ +extern struct pio adc_pins[]; + void set_adc_pins(void) { + int i = 0; /* Configure ADC pins */ - config_gpio(0, 30, (LPC_IO_FUNC_ALT(3) | LPC_IO_ANALOG)); - config_gpio(0, 31, (LPC_IO_FUNC_ALT(3) | LPC_IO_ANALOG)); - config_gpio(1, 0, (LPC_IO_FUNC_ALT(2) | LPC_IO_ANALOG)); - config_gpio(1, 1, (LPC_IO_FUNC_ALT(2) | LPC_IO_ANALOG)); - config_gpio(1, 2, (LPC_IO_FUNC_ALT(2) | LPC_IO_ANALOG)); - config_gpio(1, 3, (LPC_IO_FUNC_ALT(1) | LPC_IO_ANALOG)); + for (i = 0; adc_pins[i].port != 0xFF; i++) { + config_pio(&adc_pins[i], LPC_IO_ANALOG); + } } void adc_clk_update(void) diff --git a/drivers/eeprom.c b/drivers/eeprom.c index a46b2e8..f6d786b 100644 --- a/drivers/eeprom.c +++ b/drivers/eeprom.c @@ -25,9 +25,9 @@ #include "core/lpc_regs_12xx.h" #include "core/lpc_core_cm0.h" #include "core/system.h" +#include "core/pio.h" #include "lib/string.h" #include "drivers/i2c.h" -#include "drivers/gpio.h" /***************************************************************************** */ @@ -36,20 +36,22 @@ /* These are place-holders to set the SPI chip select low if the SPI driver is not used. * These dummy functions will be over-ridden by SPI ones if the SPI driver is used. */ -#define I2C_CS_PIN 15 +#define I2C_CS_GPIO LPC_GPIO_0_15 int I2C_CS_Default_Set(void) { struct lpc_gpio* gpio0 = LPC_GPIO_0; - config_gpio(0, I2C_CS_PIN, (LPC_IO_FUNC_ALT(0) | LPC_IO_MODE_PULL_UP | LPC_IO_DIGITAL)); + struct pio i2c_eeprom_cs = I2C_CS_GPIO; + config_pio(&i2c_eeprom_cs, (LPC_IO_MODE_PULL_UP | LPC_IO_DIGITAL)); /* Configure SPI_CS as output and set it low. */ - gpio0->data_dir |= (1 << I2C_CS_PIN); - gpio0->clear = (1 << I2C_CS_PIN); + gpio0->data_dir |= (1 << i2c_eeprom_cs.pin); + gpio0->clear = (1 << i2c_eeprom_cs.pin); return 0; } void I2C_CS_Default_Release(void) { struct lpc_gpio* gpio0 = LPC_GPIO_0; - gpio0->set = (1 << I2C_CS_PIN); + struct pio i2c_eeprom_cs = I2C_CS_GPIO; + gpio0->set = (1 << i2c_eeprom_cs.pin); } int spi_device_cs_pull_low(void) __attribute__ ((weak, alias ("I2C_CS_Default_Set"))); diff --git a/drivers/gpio.c b/drivers/gpio.c index 308b32f..cde7f0d 100644 --- a/drivers/gpio.c +++ b/drivers/gpio.c @@ -32,100 +32,19 @@ /***************************************************************************** */ -/* Public access to GPIO setup */ -#define PORT0_NB_PINS 32 -#define PORT1_NB_PINS 7 -#define PORT2_NB_PINS 16 -static volatile uint32_t* gpio_regs_handles_port0[PORT0_NB_PINS] = { - &(LPC_IO_CONTROL->pio0_0), - &(LPC_IO_CONTROL->pio0_1), - &(LPC_IO_CONTROL->pio0_2), - &(LPC_IO_CONTROL->pio0_3), - &(LPC_IO_CONTROL->pio0_4), - &(LPC_IO_CONTROL->pio0_5), - &(LPC_IO_CONTROL->pio0_6), - &(LPC_IO_CONTROL->pio0_7), - &(LPC_IO_CONTROL->pio0_8), - &(LPC_IO_CONTROL->pio0_9), - &(LPC_IO_CONTROL->pio0_10), - &(LPC_IO_CONTROL->pio0_11), - &(LPC_IO_CONTROL->pio0_12), - &(LPC_IO_CONTROL->pio0_13), - &(LPC_IO_CONTROL->pio0_14), - &(LPC_IO_CONTROL->pio0_15), - &(LPC_IO_CONTROL->pio0_16), - &(LPC_IO_CONTROL->pio0_17), - &(LPC_IO_CONTROL->pio0_18), - &(LPC_IO_CONTROL->pio0_19), - &(LPC_IO_CONTROL->pio0_20), - &(LPC_IO_CONTROL->pio0_21), - &(LPC_IO_CONTROL->pio0_22), - &(LPC_IO_CONTROL->pio0_23), - &(LPC_IO_CONTROL->pio0_24), - &(LPC_IO_CONTROL->pio0_25), - &(LPC_IO_CONTROL->pio0_26), - &(LPC_IO_CONTROL->pio0_27), - &(LPC_IO_CONTROL->pio0_28), - &(LPC_IO_CONTROL->pio0_29), - &(LPC_IO_CONTROL->pio0_30), - &(LPC_IO_CONTROL->pio0_31), -}; -static volatile uint32_t* gpio_regs_handles_port1[PORT1_NB_PINS] = { - &(LPC_IO_CONTROL->pio1_0), - &(LPC_IO_CONTROL->pio1_1), - &(LPC_IO_CONTROL->pio1_2), - &(LPC_IO_CONTROL->pio1_3), - &(LPC_IO_CONTROL->pio1_4), - &(LPC_IO_CONTROL->pio1_5), - &(LPC_IO_CONTROL->pio1_6), -}; -static volatile uint32_t* gpio_regs_handles_port2[PORT2_NB_PINS] = { - &(LPC_IO_CONTROL->pio2_0), - &(LPC_IO_CONTROL->pio2_1), - &(LPC_IO_CONTROL->pio2_2), - &(LPC_IO_CONTROL->pio2_3), - &(LPC_IO_CONTROL->pio2_4), - &(LPC_IO_CONTROL->pio2_5), - &(LPC_IO_CONTROL->pio2_6), - &(LPC_IO_CONTROL->pio2_7), - &(LPC_IO_CONTROL->pio2_8), - &(LPC_IO_CONTROL->pio2_9), - &(LPC_IO_CONTROL->pio2_10), - &(LPC_IO_CONTROL->pio2_11), - &(LPC_IO_CONTROL->pio2_12), - &(LPC_IO_CONTROL->pio2_13), - &(LPC_IO_CONTROL->pio2_14), - &(LPC_IO_CONTROL->pio2_15), -}; +/* GPIO setup */ -void config_gpio(uint8_t port, uint8_t pin, uint32_t mode) -{ - volatile uint32_t* handle = NULL; - switch (port) { - case 0: - if (pin >= PORT0_NB_PINS) - return; - handle = gpio_regs_handles_port0[pin]; - break; - case 1: - if (pin >= PORT1_NB_PINS) - return; - handle = gpio_regs_handles_port1[pin]; - break; - case 2: - if (pin >= PORT2_NB_PINS) - return; - handle = gpio_regs_handles_port2[pin]; - break; - default: - return; +/* Set all GPIO used in a default state */ +extern struct pio gpio_pins[]; + +void set_gpio_pins(void) +{ + int i = 0; + /* Set GPIO pins as GPIO */ + for (i = 0; gpio_pins[i].port != 0xFF; i++) { + config_pio(&gpio_pins[i], LPC_IO_MODE_PULL_UP); } - /* Make sure IO_Config is clocked */ - io_config_clk_on(); - *handle = mode; - /* Config done, power off IO_CONFIG block */ - io_config_clk_off(); } void gpio_on(void) @@ -133,7 +52,7 @@ void gpio_on(void) /* Provide power to GPIO control blocks */ subsystem_power(LPC_SYS_ABH_CLK_CTRL_GPIO0, 1); subsystem_power(LPC_SYS_ABH_CLK_CTRL_GPIO1, 1); - /* FIXME : Power this one two if you use LQFP64 or LQFP100 packages */ + /* FIXME : Power this one too if you use LQFP64 or LQFP100 packages */ /* subsystem_power(LPC_SYS_ABH_CLK_CTRL_GPIO2, 1); */ } void gpio_off(void) @@ -145,118 +64,38 @@ void gpio_off(void) } -/* Set all GPIO used on the GPIO_Demo module in a default state */ -void set_gpio_pins(void) -{ - struct lpc_io_control* ioctrl = LPC_IO_CONTROL; - - /* Make sure IO_Config is clocked */ - io_config_clk_on(); - - /* Configure GPIO pins */ - ioctrl->pio0_0 = LPC_IO_FUNC_ALT(0) | LPC_IO_MODE_PULL_UP; - ioctrl->pio0_3 = LPC_IO_FUNC_ALT(0) | LPC_IO_MODE_PULL_UP; - ioctrl->pio0_4 = LPC_IO_FUNC_ALT(0) | LPC_IO_MODE_PULL_UP; - ioctrl->pio0_5 = LPC_IO_FUNC_ALT(0) | LPC_IO_MODE_PULL_UP; - ioctrl->pio0_6 = LPC_IO_FUNC_ALT(0) | LPC_IO_MODE_PULL_UP; - ioctrl->pio0_19 = LPC_IO_FUNC_ALT(0) | LPC_IO_MODE_PULL_UP; - ioctrl->pio0_20 = LPC_IO_FUNC_ALT(0) | LPC_IO_MODE_PULL_UP; - ioctrl->pio0_21 = LPC_IO_FUNC_ALT(0) | LPC_IO_MODE_PULL_UP; - ioctrl->pio0_22 = LPC_IO_FUNC_ALT(0) | LPC_IO_MODE_PULL_UP; - ioctrl->pio0_23 = LPC_IO_FUNC_ALT(0) | LPC_IO_MODE_PULL_UP; - ioctrl->pio0_24 = LPC_IO_FUNC_ALT(0) | LPC_IO_MODE_PULL_UP; - ioctrl->pio0_25 = LPC_IO_FUNC_ALT(6) | LPC_IO_MODE_PULL_UP; - ioctrl->pio0_26 = LPC_IO_FUNC_ALT(6) | LPC_IO_MODE_PULL_UP; - ioctrl->pio0_27 = LPC_IO_FUNC_ALT(0) | LPC_IO_MODE_PULL_UP; - ioctrl->pio0_28 = LPC_IO_FUNC_ALT(0) | LPC_IO_MODE_PULL_UP; - ioctrl->pio0_29 = LPC_IO_FUNC_ALT(0) | LPC_IO_MODE_PULL_UP; - /* ADC pins configured in ADC driver. Kept for info, for those not using them as ADC */ - ioctrl->pio0_30 = LPC_IO_FUNC_ALT(1) | LPC_IO_MODE_PULL_UP; /* AD0 */ - ioctrl->pio0_31 = LPC_IO_FUNC_ALT(1) | LPC_IO_MODE_PULL_UP; /* AD1 */ - ioctrl->pio1_0 = LPC_IO_FUNC_ALT(1) | LPC_IO_MODE_PULL_UP; /* AD2 */ - ioctrl->pio1_1 = LPC_IO_FUNC_ALT(1) | LPC_IO_MODE_PULL_UP; /* AD3 */ - ioctrl->pio1_2 = LPC_IO_FUNC_ALT(0) | LPC_IO_MODE_PULL_UP; /* AD4 */ - ioctrl->pio1_3 = LPC_IO_FUNC_ALT(0) | LPC_IO_MODE_PULL_UP; /* AD5 */ - /* Bicolor led */ - ioctrl->pio1_4 = LPC_IO_FUNC_ALT(0) | LPC_IO_MODE_PULL_UP; /* Green LED */ - ioctrl->pio1_5 = LPC_IO_FUNC_ALT(0) | LPC_IO_MODE_PULL_UP; /* Red LED */ - /* SPI pins */ - ioctrl->pio0_14 = LPC_IO_FUNC_ALT(0) | LPC_IO_MODE_PULL_UP; /* SPI Clock */ - ioctrl->pio0_15 = LPC_IO_FUNC_ALT(0) | LPC_IO_MODE_PULL_UP; /* SPI Chip Select */ - ioctrl->pio0_16 = LPC_IO_FUNC_ALT(0) | LPC_IO_MODE_PULL_UP; /* SPI MISO */ - ioctrl->pio0_17 = LPC_IO_FUNC_ALT(0) | LPC_IO_MODE_PULL_UP; /* SPI MOSI */ - /* UART pins */ - ioctrl->pio0_1 = LPC_IO_FUNC_ALT(0) | LPC_IO_MODE_PULL_UP; /* UART0 RxD */ - ioctrl->pio0_2 = LPC_IO_FUNC_ALT(0) | LPC_IO_MODE_PULL_UP; /* UART0 TxD */ - ioctrl->pio0_8 = LPC_IO_FUNC_ALT(0) | LPC_IO_MODE_PULL_UP; /* UART1 RxD */ - ioctrl->pio0_9 = LPC_IO_FUNC_ALT(0) | LPC_IO_MODE_PULL_UP; /* UART1 TxD */ - /* I2C pins */ - ioctrl->pio0_10 = LPC_IO_FUNC_ALT(0) | LPC_IO_MODE_PULL_UP; /* I2C SCL */ - ioctrl->pio0_11 = LPC_IO_FUNC_ALT(0) | LPC_IO_MODE_PULL_UP; /* I2C SDA */ - - /* Config done, power off IO_CONFIG block */ - io_config_clk_off(); -} - - -/* Most pins have GPIO function on function 0, but a few have it on another function ... - * Return the function number for the GPIO function. - */ -uint8_t lpc_io_func_gpio(uint8_t port, uint8_t pin){ - switch (port) { - case 1: - switch (pin) { - case 0: - case 1: - return 1; - } - break; - case 0: - switch (pin) { - case 13: - case 30: - case 31: - return 1; - case 25: - case 26: - return 6; - } - break; - } - return 0; -} - +/***************************************************************************** */ +/* GPIO Interrupts Callbacks */ static void (*gpio_calbacks_port0[PORT0_NB_PINS]) (uint32_t); static void (*gpio_calbacks_port1[PORT1_NB_PINS]) (uint32_t); static void (*gpio_calbacks_port2[PORT2_NB_PINS]) (uint32_t); - -int set_gpio_callback(void (*callback) (uint32_t), uint8_t port, uint8_t pin, uint8_t sense) +int set_gpio_callback(void (*callback) (uint32_t), struct pio* gpio, uint8_t sense) { struct lpc_gpio* gpio_port = NULL; uint32_t irq = 0; /* Register the callback */ /* FIXME : we should check that there were none registered for the selected pin */ - switch (port) { + switch (gpio->port) { case 0: - if (pin >= PORT0_NB_PINS) + if (gpio->pin >= PORT0_NB_PINS) return -EINVAL; - gpio_calbacks_port0[pin] = callback; + gpio_calbacks_port0[gpio->pin] = callback; gpio_port = LPC_GPIO_0; irq = PIO_0_IRQ; break; case 1: - if (pin >= PORT1_NB_PINS) + if (gpio->pin >= PORT1_NB_PINS) return -EINVAL; - gpio_calbacks_port1[pin] = callback; + gpio_calbacks_port1[gpio->pin] = callback; gpio_port = LPC_GPIO_1; irq = PIO_1_IRQ; break; case 2: - if (pin >= PORT2_NB_PINS) + if (gpio->pin >= PORT2_NB_PINS) return -EINVAL; - gpio_calbacks_port2[pin] = callback; + gpio_calbacks_port2[gpio->pin] = callback; gpio_port = LPC_GPIO_2; irq = PIO_2_IRQ; break; @@ -265,65 +104,65 @@ int set_gpio_callback(void (*callback) (uint32_t), uint8_t port, uint8_t pin, ui } /* Configure the pin as interrupt source */ - gpio_port->data_dir &= ~(1 << pin); /* Input */ - config_gpio(port, pin, (lpc_io_func_gpio(port, pin) | LPC_IO_DIGITAL)); + gpio_port->data_dir &= ~(1 << gpio->pin); /* Input */ + config_pio(gpio, LPC_IO_DIGITAL); switch (sense) { case EDGES_BOTH: - gpio_port->int_sense &= ~(1 << pin); - gpio_port->int_both_edges |= (1 << pin); + gpio_port->int_sense &= ~(1 << gpio->pin); + gpio_port->int_both_edges |= (1 << gpio->pin); break; case EDGE_RISING: - gpio_port->int_sense &= ~(1 << pin); - gpio_port->int_both_edges &= ~(1 << pin); - gpio_port->int_event |= (1 << pin); + gpio_port->int_sense &= ~(1 << gpio->pin); + gpio_port->int_both_edges &= ~(1 << gpio->pin); + gpio_port->int_event |= (1 << gpio->pin); break; case EDGE_FALLING: - gpio_port->int_sense &= ~(1 << pin); - gpio_port->int_both_edges &= ~(1 << pin); - gpio_port->int_event &= ~(1 << pin); + gpio_port->int_sense &= ~(1 << gpio->pin); + gpio_port->int_both_edges &= ~(1 << gpio->pin); + gpio_port->int_event &= ~(1 << gpio->pin); break; case LEVEL_LOW: - gpio_port->int_sense |= (1 << pin); - gpio_port->int_both_edges &= ~(1 << pin); - gpio_port->int_event &= ~(1 << pin); + gpio_port->int_sense |= (1 << gpio->pin); + gpio_port->int_both_edges &= ~(1 << gpio->pin); + gpio_port->int_event &= ~(1 << gpio->pin); break; case LEVEL_HIGH: - gpio_port->int_sense |= (1 << pin); - gpio_port->int_both_edges &= ~(1 << pin); - gpio_port->int_event |= (1 << pin); + gpio_port->int_sense |= (1 << gpio->pin); + gpio_port->int_both_edges &= ~(1 << gpio->pin); + gpio_port->int_event |= (1 << gpio->pin); break; default: /* Not handled, do not activate the interrupt */ return -EINVAL; } - gpio_port->int_enable |= (1 << pin); + gpio_port->int_enable |= (1 << gpio->pin); NVIC_EnableIRQ(irq); return 0; } -void remove_gpio_callback(uint8_t port, uint8_t pin) +void remove_gpio_callback(struct pio* gpio) { struct lpc_gpio* gpio_port = NULL; uint32_t irq = 0; /* Remove the handler */ - switch (port) { + switch (gpio->port) { case 0: - if (pin >= PORT0_NB_PINS) + if (gpio->pin >= PORT0_NB_PINS) return; - gpio_calbacks_port0[pin] = NULL; + gpio_calbacks_port0[gpio->pin] = NULL; gpio_port = LPC_GPIO_0; irq = PIO_0_IRQ; break; case 1: - if (pin >= PORT1_NB_PINS) + if (gpio->pin >= PORT1_NB_PINS) return; - gpio_calbacks_port1[pin] = NULL; + gpio_calbacks_port1[gpio->pin] = NULL; gpio_port = LPC_GPIO_1; irq = PIO_1_IRQ; break; case 2: - if (pin >= PORT2_NB_PINS) + if (gpio->pin >= PORT2_NB_PINS) return; - gpio_calbacks_port2[pin] = NULL; + gpio_calbacks_port2[gpio->pin] = NULL; gpio_port = LPC_GPIO_2; irq = PIO_2_IRQ; break; @@ -331,7 +170,7 @@ void remove_gpio_callback(uint8_t port, uint8_t pin) return; } /* And disable the interrupt */ - gpio_port->int_enable &= ~(1 << pin); + gpio_port->int_enable &= ~(1 << gpio->pin); if (gpio_port->int_enable == 0) { NVIC_DisableIRQ(irq); } @@ -343,7 +182,6 @@ void remove_gpio_callback(uint8_t port, uint8_t pin) * with the people doing the electronic design. * Use them if you place the signals generating interrupts on low numbered pins */ -#include "drivers/serial.h" void PIO_0_Handler(void) { struct lpc_gpio* gpio0 = LPC_GPIO_0; @@ -406,93 +244,3 @@ void PIO_2_Handler(void) } -/***************************************************************************** */ -/* Status LED */ - -#define LED_RED 5 -#define LED_GREEN 4 - -/* The status LED is on GPIO Port 1, pin 4 (PIO1_4) and Port 1, pin 5 (PIO1_5) */ -void status_led_config(void) -{ - struct lpc_gpio* gpio1 = LPC_GPIO_1; - uint32_t mode = (LPC_IO_MODE_PULL_UP | LPC_IO_DIGITAL | LPC_IO_DRIVE_HIGHCURENT); - /* Status Led GPIO */ - config_gpio(1, LED_GREEN, (lpc_io_func_gpio(1, LED_GREEN) | mode)); - config_gpio(1, LED_RED, (lpc_io_func_gpio(1, LED_RED) | mode)); - /* Configure both as output */ - gpio1->data_dir |= (1 << LED_GREEN) | (1 << LED_RED); - /* Turn both LEDs on */ - //gpio1->set = (1 << LED_GREEN) | (1 << LED_RED); - gpio1->set = (1 << LED_GREEN); -} - -void status_led(uint32_t val) -{ - struct lpc_gpio* gpio1 = LPC_GPIO_1; - - switch (val) { - case red_only: - gpio1->set = (1 << LED_RED); - gpio1->clear = (1 << LED_GREEN); - break; - case red_on: - gpio1->set = (1 << LED_RED); - break; - case red_off: - gpio1->clear = (1 << LED_RED); - break; - case red_toggle: - gpio1->invert = (1 << LED_RED); - break; - case green_only: - gpio1->set = (1 << LED_GREEN); - gpio1->clear = (1 << LED_RED); - break; - case green_on: - gpio1->set = (1 << LED_GREEN); - break; - case green_off: - gpio1->clear = (1 << LED_GREEN); - break; - case green_toggle: - gpio1->invert = (1 << LED_GREEN); - break; - case both: - gpio1->set = (1 << LED_GREEN) | (1 << LED_RED); - break; - case toggle: - gpio1->invert = (1 << LED_GREEN) | (1 << LED_RED); - break; - case none: - default: - gpio1->clear = (1 << LED_GREEN) | (1 << LED_RED); - break; - } -} - -void chenillard(uint32_t ms) -{ - status_led(red_only); - msleep(ms); - status_led(green_only); - msleep(ms); - status_led(none); - msleep(ms); - status_led(both); - msleep(ms); - status_led(none); - msleep(ms); - status_led(red_only); - msleep(ms); - status_led(red_only); - msleep(ms); - status_led(none); - msleep(ms); - status_led(green_only); - msleep(ms); - status_led(green_only); - msleep(ms); - status_led(none); - msleep(ms); -} diff --git a/drivers/i2c.c b/drivers/i2c.c index 3b47b27..26b99c4 100644 --- a/drivers/i2c.c +++ b/drivers/i2c.c @@ -448,10 +448,15 @@ static void i2c_clock_on(uint32_t i2c_clk_freq) i2c->clk_duty_low = (scl_clk - i2c->clk_duty_high); } +extern struct pio i2c0_pins[]; + void set_i2c_pins(void) { - config_gpio(0, 10, (LPC_IO_FUNC_ALT(2) | LPC_IO_OPEN_DRAIN_ENABLE)); /* True open drain */ - config_gpio(0, 11, (LPC_IO_FUNC_ALT(2) | LPC_IO_OPEN_DRAIN_ENABLE)); + int i = 0; + /* Configure I2C pins */ + for (i = 0; i2c0_pins[i].port != 0xFF; i++) { + config_pio(&i2c0_pins[i], (LPC_IO_ANALOG | LPC_IO_OPEN_DRAIN_ENABLE)); + } } void i2c_on(uint32_t i2c_clk_freq) diff --git a/drivers/serial.c b/drivers/serial.c index 91ec299..f667cc3 100644 --- a/drivers/serial.c +++ b/drivers/serial.c @@ -228,17 +228,22 @@ static uint32_t uart_mode_setup(uint32_t uart_num) /* Note : We MUST set LPC_IO_DIGITAL for Rx even if the bit is marked as "Reserved" in * the datasheet ! */ +extern struct pio uart0_pins[]; +extern struct pio uart1_pins[]; + static void uart_set_pin_func(uint32_t uart_num) { - /* Configure UART pins (Only Rx and Tx) */ + int i = 0; switch (uart_num) { case 0: - config_gpio(0, 1, (LPC_IO_FUNC_ALT(2) | LPC_IO_DIGITAL)); - config_gpio(0, 2, (LPC_IO_FUNC_ALT(2) | LPC_IO_DIGITAL)); + for (i = 0; uart0_pins[i].port != 0xFF; i++) { + config_pio(&uart0_pins[i], LPC_IO_DIGITAL); + } break; case 1: - config_gpio(0, 8, (LPC_IO_FUNC_ALT(2) | LPC_IO_DIGITAL)); - config_gpio(0, 9, (LPC_IO_FUNC_ALT(2) | LPC_IO_DIGITAL)); + for (i = 0; uart1_pins[i].port != 0xFF; i++) { + config_pio(&uart1_pins[i], LPC_IO_DIGITAL); + } break; } } diff --git a/drivers/ssp.c b/drivers/ssp.c index fdf15fa..601df27 100644 --- a/drivers/ssp.c +++ b/drivers/ssp.c @@ -28,6 +28,7 @@ #include "core/lpc_regs_12xx.h" #include "core/lpc_core_cm0.h" #include "core/system.h" +#include "core/pio.h" #include "lib/string.h" #include "drivers/ssp.h" #include "drivers/gpio.h" @@ -92,33 +93,34 @@ static uint32_t spi_cs_mutex = 0; * SPI bus. * Any data sent by the master on the SPI bus while the spi_cs_mutex is held will be lost. */ +#define SPI_CS_PIN LPC_GPIO_0_15 int spi_device_cs_pull_low(void) { struct lpc_gpio* gpio0 = LPC_GPIO_0; + struct pio spi_cs = SPI_CS_PIN; if (sync_lock_test_and_set(&spi_cs_mutex, 1) == 1) { return -EBUSY; } /* Configure pin as GPIO */ - config_gpio(0, SPI_CS_PIN, (LPC_IO_FUNC_ALT(0) | LPC_IO_MODE_PULL_UP | LPC_IO_DIGITAL)); + config_pio(&spi_cs, (LPC_IO_MODE_PULL_UP | LPC_IO_DIGITAL)); /* Configure pin as output and set it low */ - gpio0->data_dir |= (1 << SPI_CS_PIN); - gpio0->clear = (1 << SPI_CS_PIN); + gpio0->data_dir |= (1 << spi_cs.pin); + gpio0->clear = (1 << spi_cs.pin); return 0; } void spi_device_cs_release(void) { struct lpc_gpio* gpio0 = LPC_GPIO_0; + struct pio spi_cs = SPI_CS_PIN; /* Release mutex */ sync_lock_release(&spi_cs_mutex); /* Set pin high */ - gpio0->set = (1 << SPI_CS_PIN); - /* Configure pin as SPI again */ - config_gpio(0, SPI_CS_PIN, (LPC_IO_FUNC_ALT(2) | LPC_IO_DIGITAL)); /* SPI Chip Select */ + gpio0->set = (1 << spi_cs.pin); } @@ -245,16 +247,18 @@ void ssp_clk_update(void) } } -/* Configure main SPI pins, used in both master and device mode. - * The slave select is not configured here as it's use is implementation dependant in master - * mode. In slave mode it is configured in the ssp_slave_on() function. - */ -void set_ssp_pins(void) +/* Configure all SPI pins. */ +extern struct pio ssp0_pins[]; +static void ssp_set_pin_func(uint32_t ssp_num) { - /* Main SPI pins */ - config_gpio(0, 14, (LPC_IO_FUNC_ALT(2) | LPC_IO_DIGITAL)); /* SPI Clock */ - config_gpio(0, 16, (LPC_IO_FUNC_ALT(2) | LPC_IO_DIGITAL)); /* SPI MISO */ - config_gpio(0, 17, (LPC_IO_FUNC_ALT(2) | LPC_IO_DIGITAL)); /* SPI MOSI */ + int i = 0; + switch (ssp_num) { + case 0: + for (i = 0; ssp0_pins[i].port != 0xFF; i++) { + config_pio(&ssp0_pins[i], LPC_IO_DIGITAL); + } + break; + } } @@ -276,6 +280,10 @@ int ssp_master_on(uint8_t frame_type, uint8_t data_width, uint32_t rate ) struct lpc_ssp* ssp = LPC_SSP0; NVIC_DisableIRQ(SSP0_IRQ); + + /* Configure pins first */ + ssp_set_pin_func(0); /* Only one SPI on the LPC1224 */ + /* Power up the ssp block */ subsystem_power(LPC_SYS_ABH_CLK_CTRL_SSP0, 1); @@ -316,9 +324,6 @@ int ssp_slave_on(uint8_t frame_type, uint8_t data_width, uint8_t out_en, uint32_ ssp->ctrl_1 |= LPC_SSP_SLAVE_OUT_DISABLE; } - /* Use SPI as Device : configure the SSEL pin */ - config_gpio(0, SPI_CS_PIN, (LPC_IO_FUNC_ALT(2) | LPC_IO_DIGITAL)); /* SPI Chip Select */ - /* Configure the clock : done after basic configuration. * Our clock must be at least 12 times the master clock */ ssp_current_clk = ssp_clk_on(max_rate * 16); @@ -326,6 +331,8 @@ int ssp_slave_on(uint8_t frame_type, uint8_t data_width, uint8_t out_en, uint32_ /* Enable SSP */ ssp->ctrl_1 |= LPC_SSP_ENABLE; + ssp_set_pin_func(0); + NVIC_EnableIRQ(SSP0_IRQ); return 0; /* Config OK */ } diff --git a/drivers/status_led.c b/drivers/status_led.c new file mode 100644 index 0000000..1c75327 --- /dev/null +++ b/drivers/status_led.c @@ -0,0 +1,124 @@ +/**************************************************************************** + * drivers/status_led.c + * + * Copyright 2012 Nathael Pajani + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * +*************************************************************************** */ + +/***************************************************************************** */ +/* Status Led */ +/***************************************************************************** */ + + +#include +#include "core/lpc_regs_12xx.h" +#include "core/system.h" +#include "core/pio.h" +#include "drivers/status_led.h" + + +/***************************************************************************** */ +/* Status LED is the bicolors red/green led on the GPIO Demo module */ + +/* The status LED is on GPIO Port 1, pin 4 (PIO1_4) and Port 1, pin 5 (PIO1_5) */ +#define LED_RED 5 +#define LED_GREEN 4 + +void status_led_config(void) +{ + struct lpc_gpio* gpio1 = LPC_GPIO_1; + uint32_t mode = (LPC_IO_MODE_PULL_UP | LPC_IO_DIGITAL | LPC_IO_DRIVE_HIGHCURENT); + struct pio red_led = LPC_GPIO_1_4; + struct pio green_led = LPC_GPIO_1_5; + /* Status Led GPIO */ + config_pio(&green_led, mode); + config_pio(&red_led, mode); + /* Configure both as output */ + gpio1->data_dir |= (1 << LED_GREEN) | (1 << LED_RED); + /* Turn both LEDs on */ + //gpio1->set = (1 << LED_GREEN) | (1 << LED_RED); + gpio1->set = (1 << LED_GREEN); +} + +void status_led(uint32_t val) +{ + struct lpc_gpio* gpio1 = LPC_GPIO_1; + + switch (val) { + case red_only: + gpio1->set = (1 << LED_RED); + gpio1->clear = (1 << LED_GREEN); + break; + case red_on: + gpio1->set = (1 << LED_RED); + break; + case red_off: + gpio1->clear = (1 << LED_RED); + break; + case red_toggle: + gpio1->toggle = (1 << LED_RED); + break; + case green_only: + gpio1->set = (1 << LED_GREEN); + gpio1->clear = (1 << LED_RED); + break; + case green_on: + gpio1->set = (1 << LED_GREEN); + break; + case green_off: + gpio1->clear = (1 << LED_GREEN); + break; + case green_toggle: + gpio1->toggle = (1 << LED_GREEN); + break; + case both: + gpio1->set = (1 << LED_GREEN) | (1 << LED_RED); + break; + case toggle: + gpio1->toggle = (1 << LED_GREEN) | (1 << LED_RED); + break; + case none: + default: + gpio1->clear = (1 << LED_GREEN) | (1 << LED_RED); + break; + } +} + +void chenillard(uint32_t ms) +{ + status_led(red_only); + msleep(ms); + status_led(green_only); + msleep(ms); + status_led(none); + msleep(ms); + status_led(both); + msleep(ms); + status_led(none); + msleep(ms); + status_led(red_only); + msleep(ms); + status_led(red_only); + msleep(ms); + status_led(none); + msleep(ms); + status_led(green_only); + msleep(ms); + status_led(green_only); + msleep(ms); + status_led(none); + msleep(ms); +} diff --git a/drivers/timers.c b/drivers/timers.c index 21e2ab6..0edd3e9 100644 --- a/drivers/timers.c +++ b/drivers/timers.c @@ -198,18 +198,36 @@ int timer_setup(uint32_t timer_num, struct timer_config* conf) } -/* Setup one pin to use as match or capture pin - * This configure function can be used only for pins on port 0. - * Use LPC_TIMER_*B*_CHANNEL_*_PIN_* definitions for the pin number and either - * LPC_TIMER_PIN_FUNC_CAPTURE or LPC_TIMER_PIN_FUNC_MATCH for the function. - * Note: These pins are not setup using the usual system set default pins functions - * as most functions may be affected to many different pins, and the use of the - * timers does no require the use of pins. - */ +/* Setup timer pins to be used as match or capture pin */ +extern struct pio timer0_pins[]; +extern struct pio timer1_pins[]; +extern struct pio timer2_pins[]; +extern struct pio timer3_pins[]; + #define LPC_TIMER_PIN_CONFIG (LPC_IO_MODE_PULL_UP | LPC_IO_DIGITAL | LPC_IO_DRIVE_HIGHCURENT) -void timer_pins_setup(uint8_t port, uint8_t pin_num, uint32_t func) +static void timer_pins_setup(uint32_t timer_num) { - config_gpio(port, pin_num, (func | LPC_TIMER_PIN_CONFIG)); + int i = 0; + struct pio* timer_pins = NULL; + switch (timer_num) { + case LPC_TIMER_16B0: + timer_pins = timer0_pins; + break; + case LPC_TIMER_16B1: + timer_pins = timer1_pins; + break; + case LPC_TIMER_32B0: + timer_pins = timer2_pins; + break; + case LPC_TIMER_32B1: + timer_pins = timer3_pins; + break; + default: + return; + } + for (i = 0; timer_pins[i].port != 0xFF; i++) { + config_pio(&timer_pins[i], LPC_TIMER_PIN_CONFIG); + } } /* Power up a timer. @@ -241,6 +259,8 @@ void timer_on(uint32_t timer_num, uint32_t clkrate) } timer->regs->prescale = prescale; + timer_pins_setup(timer_num); + NVIC_EnableIRQ(timer_devices[timer_num].irq); } diff --git a/include/core/lpc_regs_12xx.h b/include/core/lpc_regs_12xx.h index 14cdcea..80dafb5 100644 --- a/include/core/lpc_regs_12xx.h +++ b/include/core/lpc_regs_12xx.h @@ -444,7 +444,7 @@ struct lpc_gpio volatile uint32_t out; /* 0x08 : Port output Register (R/W) */ volatile uint32_t set; /* 0x0C : Port output set Register (-/W) */ volatile uint32_t clear; /* 0x10 : Port output clear Register (-/W) */ - volatile uint32_t invert; /* 0x14 : Port output invert Register (-/W) */ + volatile uint32_t toggle; /* 0x14 : Port output invert Register (-/W) */ uint32_t reserved_1[2]; volatile uint32_t data_dir; /* 0x20 : Data direction Register (R/W) */ volatile uint32_t int_sense; /* 0x24 : Interrupt sense Register (R/W) */ diff --git a/include/core/pio.h b/include/core/pio.h new file mode 100644 index 0000000..84b4f90 --- /dev/null +++ b/include/core/pio.h @@ -0,0 +1,262 @@ +/**************************************************************************** + * core/pio.h + * + * Copyright 2014 Nathael Pajani + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + ****************************************************************************/ + +#ifndef CORE_PIO_H +#define CORE_PIO_H + +#include + +struct pio { + uint8_t port; /* 0xFF indicates the end of a pin array */ + uint8_t pin; + uint8_t alt_setting; +}; + +#define ARRAY_LAST_PIN {0xFF, 0xFF, 0xFF} + + +#define PORT0_NB_PINS 32 +#define PORT1_NB_PINS 7 +#define PORT2_NB_PINS 16 + +void pio_copy(struct pio* dst, struct pio* src); + +void config_pio(struct pio* pp, uint32_t mode); + + +/****************************************************************************/ +/* GPIO Pins */ +#define LPC_GPIO_0_0 {0, 0, 0} +#define LPC_GPIO_0_1 {0, 1, 0} +#define LPC_GPIO_0_2 {0, 2, 0} +#define LPC_GPIO_0_3 {0, 3, 0} +#define LPC_GPIO_0_4 {0, 4, 0} +#define LPC_GPIO_0_5 {0, 5, 0} +#define LPC_GPIO_0_6 {0, 6, 0} +#define LPC_GPIO_0_7 {0, 7, 0} +#define LPC_GPIO_0_8 {0, 8, 0} +#define LPC_GPIO_0_9 {0, 9, 0} +#define LPC_GPIO_0_10 {0, 10, 0} +#define LPC_GPIO_0_11 {0, 11, 0} +#define LPC_GPIO_0_12 {0, 12, 0} +#define LPC_GPIO_0_13 {0, 13, 1} +#define LPC_GPIO_0_14 {0, 14, 0} +#define LPC_GPIO_0_15 {0, 15, 0} +#define LPC_GPIO_0_16 {0, 16, 0} +#define LPC_GPIO_0_17 {0, 17, 0} +#define LPC_GPIO_0_18 {0, 18, 0} +#define LPC_GPIO_0_19 {0, 19, 0} +#define LPC_GPIO_0_20 {0, 20, 0} +#define LPC_GPIO_0_21 {0, 21, 0} +#define LPC_GPIO_0_22 {0, 22, 0} +#define LPC_GPIO_0_23 {0, 23, 0} +#define LPC_GPIO_0_24 {0, 24, 0} +#define LPC_GPIO_0_25 {0, 25, 6} +#define LPC_GPIO_0_26 {0, 26, 6} +#define LPC_GPIO_0_27 {0, 27, 0} +#define LPC_GPIO_0_28 {0, 28, 0} +#define LPC_GPIO_0_29 {0, 29, 0} +#define LPC_GPIO_0_30 {0, 30, 1} +#define LPC_GPIO_0_31 {0, 31, 1} + +#define LPC_GPIO_1_0 {1, 0, 1} +#define LPC_GPIO_1_1 {1, 1, 1} +#define LPC_GPIO_1_2 {1, 2, 0} +#define LPC_GPIO_1_3 {1, 3, 0} +#define LPC_GPIO_1_4 {1, 4, 0} +#define LPC_GPIO_1_5 {1, 5, 0} +#define LPC_GPIO_1_6 {1, 6, 0} + +#define LPC_GPIO_2_0 {2, 0, 0} +#define LPC_GPIO_2_1 {2, 1, 0} +#define LPC_GPIO_2_2 {2, 2, 0} +#define LPC_GPIO_2_3 {2, 3, 0} +#define LPC_GPIO_2_4 {2, 4, 0} +#define LPC_GPIO_2_5 {2, 5, 0} +#define LPC_GPIO_2_6 {2, 6, 0} +#define LPC_GPIO_2_7 {2, 7, 0} +#define LPC_GPIO_2_8 {2, 8, 1} +#define LPC_GPIO_2_9 {2, 9, 1} +#define LPC_GPIO_2_10 {2, 10, 1} +#define LPC_GPIO_2_11 {2, 11, 0} +#define LPC_GPIO_2_12 {2, 12, 0} +#define LPC_GPIO_2_13 {2, 13, 0} +#define LPC_GPIO_2_14 {2, 14, 0} +#define LPC_GPIO_2_15 {2, 15, 0} + + +/****************************************************************************/ +/* CLKOUT and Reset Pin */ +#define LPC_CLKOUT_PIO_0_12 {0, 12, 2} +#define LPC_RESET_PIO_0_13 {0, 13, 0} + + +/****************************************************************************/ +/* SWD (Debug) pins */ +#define LPC_SWD_SWCLK_PIO_0_18 {0, 18, 1} +#define LPC_SWD_SWCLK_PIO_0_26 {0, 26, 0} +#define LPC_SWD_SWDIO_PIO_0_25 {0, 25, 0} +#define LPC_SWD_SWDIO_PIO_1_2 {1, 2, 1} + + +/****************************************************************************/ +/* UART0 Rx/Tx Pins */ +#define LPC_UART0_RX_PIO_0_1 {0, 1, 2} +#define LPC_UART0_RX_PIO_2_1 {2, 1, 4} +#define LPC_UART0_TX_PIO_0_2 {0, 2, 2} +#define LPC_UART0_TX_PIO_2_2 {2, 2, 4} +/* UART0 - Other UART function pins */ +#define LPC_UART0_CTS_PIO_0_7 {0, 7, 2} +#define LPC_UART0_CTS_PIO_2_4 {2, 4, 4} +#define LPC_UART0_DCD_PIO_0_5 {0, 5, 2} +#define LPC_UART0_DCD_PIO_2_6 {2, 6, 4} +#define LPC_UART0_DSR_PIO_0_4 {0, 4, 2} +#define LPC_UART0_DSR_PIO_2_7 {2, 7, 4} +#define LPC_UART0_DTR_PIO_0_3 {0, 3, 2} +#define LPC_UART0_DTR_PIO_2_3 {2, 3, 4} +#define LPC_UART0_RI_PIO_0_6 {0, 6, 2} +#define LPC_UART0_RI_PIO_2_5 {2, 5, 4} +#define LPC_UART0_RTS_PIO_0_0 {0, 0, 2} +#define LPC_UART0_RTS_PIO_2_0 {2, 0, 5} /* FIXME: Doc does not list func 1 ... maybe its func 4 */ + +/* UART1 Rx/Tx Pins */ +#define LPC_UART1_RX_PIO_0_8 {0, 8, 2} +#define LPC_UART1_RX_PIO_2_11 {2, 11, 5} +#define LPC_UART1_RX_PIO_2_12 {2, 12, 3} +#define LPC_UART1_TX_PIO_0_9 {0, 9, 2} +#define LPC_UART1_TX_PIO_2_10 {2, 10, 5} +#define LPC_UART1_TX_PIO_2_13 {2, 13, 3} + +/****************************************************************************/ +/* I2C Pins */ +#define LPC_I2C0_SCL_PIO_0_10 {0, 10, 2} +#define LPC_I2C0_SDA_PIO_0_11 {0, 11, 2} + +/****************************************************************************/ +/* SPI Pins */ +/* SSP 0 */ +#define LPC_SSP0_SCLK_PIO_0_14 {0, 14, 2} +#define LPC_SSP0_MOSI_PIO_0_17 {0, 17, 2} +#define LPC_SSP0_MISO_PIO_0_16 {0, 16, 2} +#define LPC_SSP0_SSEL_PIO_0_15 {0, 15, 2} + + +/****************************************************************************/ +/* ADC Pins */ +#define LPC_ADC_AD0_PIO_0_30 {0, 30, 3} +#define LPC_ADC_AD1_PIO_0_31 {0, 31, 3} +#define LPC_ADC_AD2_PIO_1_0 {1, 0, 2} +#define LPC_ADC_AD3_PIO_1_1 {1, 1, 2} +#define LPC_ADC_AD4_PIO_1_2 {1, 2, 2} +#define LPC_ADC_AD5_PIO_1_3 {1, 4, 1} +#define LPC_ADC_AD6_PIO_1_4 {1, 4, 1} +#define LPC_ADC_AD7_PIO_1_5 {1, 5, 1} + + +/****************************************************************************/ +/* Timer Pins */ + +/* 16 bits timer 0 match pins */ +#define LPC_TIMER_16B0_M0_PIO_0_11 {0, 11, 4} +#define LPC_TIMER_16B0_M0_PIO_0_28 {0, 28, 4} +#define LPC_TIMER_16B0_M0_PIO_2_0 {2, 0, 4} +#define LPC_TIMER_16B0_M1_PIO_0_12 {0, 12, 4} +#define LPC_TIMER_16B0_M1_PIO_0_29 {0, 29, 4} +#define LPC_TIMER_16B0_M1_PIO_2_1 {2, 1, 4} +/* 16 bits timer 0 capture pins */ +#define LPC_TIMER_16B0_C0_PIO_0_11 {0, 11, 3} +#define LPC_TIMER_16B0_C0_PIO_0_28 {0, 28, 3} +#define LPC_TIMER_16B0_C0_PIO_2_0 {2, 0, 3} +#define LPC_TIMER_16B0_C1_PIO_0_12 {0, 12, 3} +#define LPC_TIMER_16B0_C1_PIO_0_29 {0, 29, 3} +#define LPC_TIMER_16B0_C1_PIO_2_1 {2, 1, 3} + +/* 16 bits timer 1 match pins */ +#define LPC_TIMER_16B1_M0_PIO_0_15 {0, 15, 4} +#define LPC_TIMER_16B1_M0_PIO_1_5 {1, 5, 3} +#define LPC_TIMER_16B1_M0_PIO_2_2 {2, 2, 3} +#define LPC_TIMER_16B1_M1_PIO_0_16 {0, 16, 4} +#define LPC_TIMER_16B1_M1_PIO_1_6 {1, 6, 2} +#define LPC_TIMER_16B1_M1_PIO_2_3 {2, 3, 3} +/* 16 bits timer 1 capture pins */ +#define LPC_TIMER_16B1_C0_PIO_0_15 {0, 15, 3} +#define LPC_TIMER_16B1_C0_PIO_1_5 {1, 5, 2} +#define LPC_TIMER_16B1_C0_PIO_2_2 {2, 2, 2} +#define LPC_TIMER_16B1_C1_PIO_0_16 {0, 16, 3} +#define LPC_TIMER_16B1_C1_PIO_1_6 {1, 6, 1} +#define LPC_TIMER_16B1_C1_PIO_2_3 {2, 3, 2} + +/* 32 bits timer 0 match pins */ +#define LPC_TIMER_32B0_M0_PIO_0_1 {0, 1, 4} +#define LPC_TIMER_32B0_M0_PIO_0_18 {0, 18, 4} +#define LPC_TIMER_32B0_M0_PIO_2_4 {2, 4, 3} +#define LPC_TIMER_32B0_M1_PIO_0_2 {0, 2, 4} +#define LPC_TIMER_32B0_M1_PIO_0_19 {0, 19, 4} +#define LPC_TIMER_32B0_M1_PIO_2_5 {2, 5, 3} +#define LPC_TIMER_32B0_M2_PIO_0_3 {0, 3, 4} +#define LPC_TIMER_32B0_M2_PIO_0_20 {0, 20, 4} +#define LPC_TIMER_32B0_M2_PIO_2_6 {2, 6, 3} +#define LPC_TIMER_32B0_M3_PIO_0_4 {0, 4, 4} +#define LPC_TIMER_32B0_M3_PIO_0_21 {0, 21, 4} +#define LPC_TIMER_32B0_M3_PIO_2_7 {2, 7, 3} +/* 32 bits timer 0 capture pins */ +#define LPC_TIMER_32B0_C0_PIO_0_1 {0, 1, 3} +#define LPC_TIMER_32B0_C0_PIO_0_18 {0, 18, 3} +#define LPC_TIMER_32B0_C0_PIO_2_4 {2, 4, 2} +#define LPC_TIMER_32B0_C1_PIO_0_2 {0, 2, 3} +#define LPC_TIMER_32B0_C1_PIO_0_19 {0, 19, 3} +#define LPC_TIMER_32B0_C1_PIO_2_5 {2, 5, 2} +#define LPC_TIMER_32B0_C2_PIO_0_3 {0, 3, 3} +#define LPC_TIMER_32B0_C2_PIO_0_20 {0, 20, 3} +#define LPC_TIMER_32B0_C2_PIO_2_6 {2, 6, 2} +#define LPC_TIMER_32B0_C3_PIO_0_4 {0, 4, 3} +#define LPC_TIMER_32B0_C3_PIO_0_21 {0, 21, 3} +#define LPC_TIMER_32B0_C3_PIO_2_7 {2, 7, 2} + +/* 32 bits timer 1 match pins */ +#define LPC_TIMER_32B1_M0_PIO_0_6 {0, 6, 4} +#define LPC_TIMER_32B1_M0_PIO_0_23 {0, 23, 4} +#define LPC_TIMER_32B1_M0_PIO_2_8 {2, 8, 3} +#define LPC_TIMER_32B1_M1_PIO_0_7 {0, 7, 4} +#define LPC_TIMER_32B1_M1_PIO_0_24 {0, 24, 4} +#define LPC_TIMER_32B1_M1_PIO_2_9 {2, 9, 3} +#define LPC_TIMER_32B1_M2_PIO_0_8 {0, 8, 4} +#define LPC_TIMER_32B1_M2_PIO_0_25 {0, 25, 4} +#define LPC_TIMER_32B1_M2_PIO_2_10 {2, 10, 3} +#define LPC_TIMER_32B1_M3_PIO_0_9 {0, 9, 4} +#define LPC_TIMER_32B1_M3_PIO_0_26 {0, 26, 4} +#define LPC_TIMER_32B1_M3_PIO_2_11 {2, 11, 3} +/* 32 bits timer 1 capture pins */ +#define LPC_TIMER_32B1_C0_PIO_0_6 {0, 6, 3} +#define LPC_TIMER_32B1_C0_PIO_0_23 {0, 23, 3} +#define LPC_TIMER_32B1_C0_PIO_2_8 {2, 8, 2} +#define LPC_TIMER_32B1_C1_PIO_0_7 {0, 7, 3} +#define LPC_TIMER_32B1_C1_PIO_0_24 {0, 24, 3} +#define LPC_TIMER_32B1_C1_PIO_2_9 {2, 9, 2} +#define LPC_TIMER_32B1_C2_PIO_0_8 {0, 8, 3} +#define LPC_TIMER_32B1_C2_PIO_0_25 {0, 25, 3} +#define LPC_TIMER_32B1_C2_PIO_2_10 {2, 10, 2} +#define LPC_TIMER_32B1_C3_PIO_0_9 {0, 9, 3} +#define LPC_TIMER_32B1_C3_PIO_0_26 {0, 26, 3} +#define LPC_TIMER_32B1_C3_PIO_2_11 {2, 11, 2} + + + +#endif /* CORE_PIO_H */ diff --git a/include/drivers/gpio.h b/include/drivers/gpio.h index 1017520..a0a3793 100644 --- a/include/drivers/gpio.h +++ b/include/drivers/gpio.h @@ -23,14 +23,13 @@ #include +#include "core/pio.h" /***************************************************************************** */ /* Public access to GPIO setup */ -void config_gpio(uint8_t port, uint8_t pin, uint32_t mode); - enum gpio_interrupt_senses { EDGES_BOTH = 0, EDGE_FALLING, @@ -40,39 +39,11 @@ enum gpio_interrupt_senses { }; -/* Most pins have GPIO function on function 0, but a few have it on another function ... - * Return the function number for the GPIO function. - */ -uint8_t lpc_io_func_gpio(uint8_t port, uint8_t pin); - -int set_gpio_callback(void (*callback) (uint32_t), uint8_t port, uint8_t pin, uint8_t sense); -void remove_gpio_callback(uint8_t port, uint8_t pin); +int set_gpio_callback(void (*callback) (uint32_t), struct pio* gpio, uint8_t sense); +void remove_gpio_callback(struct pio* gpio); void gpio_on(void); void gpio_off(void); -/***************************************************************************** */ -/* Status LED */ -/* The status LED is on GPIO Port 1, pin 4 (PIO1_4) and Port 1, pin 5 (PIO1_5) */ -void status_led_config(void); - -void status_led(uint32_t val); - -void chenillard(uint32_t ms); - -enum led_status { - none = 0, - red_only, - red_on, - red_off, - red_toggle, - green_only, - green_on, - green_off, - green_toggle, - both, - toggle, -}; - #endif /* DRIVERS_GPIO_H */ diff --git a/include/drivers/ssp.h b/include/drivers/ssp.h index 15a2e45..f78aaf7 100644 --- a/include/drivers/ssp.h +++ b/include/drivers/ssp.h @@ -27,7 +27,6 @@ /***************************************************************************** */ #include -#include "drivers/gpio.h" /* Set this to 1 for use of this driver in a multitasking OS, it will activate the SPI Mutex */ @@ -38,7 +37,6 @@ enum spi_fifo_or_pooling { SPI_USE_FIFO = 1, }; -#define SPI_CS_PIN 15 /***************************************************************************** */ /* SPI device mode slave select sharing. @@ -91,9 +89,6 @@ int spi_transfer_multiple_frames(uint16_t* data_out, int size, uint16_t* data_in /***************************************************************************** */ uint32_t ssp_clk_on(uint32_t rate); void ssp_clk_update(void); -void set_ssp_pins(void); - - /***************************************************************************** */ /* SSP Setup as master */ diff --git a/include/drivers/status_led.h b/include/drivers/status_led.h new file mode 100644 index 0000000..50ecc96 --- /dev/null +++ b/include/drivers/status_led.h @@ -0,0 +1,52 @@ +/**************************************************************************** + * drivers/status_led.h + * + * Copyright 2012 Nathael Pajani + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + *************************************************************************** */ + +#ifndef DRIVERS_STATUS_LED_H +#define DRIVERS_STATUS_LED_H + + +#include + + +/***************************************************************************** */ +/* Status LED */ +/* The status LED is on GPIO Port 1, pin 4 (PIO1_4) and Port 1, pin 5 (PIO1_5) */ +void status_led_config(void); + +void status_led(uint32_t val); + +void chenillard(uint32_t ms); + +enum led_status { + none = 0, + red_only, + red_on, + red_off, + red_toggle, + green_only, + green_on, + green_off, + green_toggle, + both, + toggle, +}; + + +#endif /* DRIVERS_STATUS_LED_H */ diff --git a/include/drivers/timers.h b/include/drivers/timers.h index a3dff99..316a5fe 100644 --- a/include/drivers/timers.h +++ b/include/drivers/timers.h @@ -101,62 +101,6 @@ void timer_set_match(uint32_t timer_num, uint32_t channel, uint32_t val); int timer_setup(uint32_t timer_num, struct timer_config* conf); -/* Some alternate pins for timers are on port 2, not handled by our code as they are - * unavailable on the 48 pins LQFP package used in the GPIO Demo module. - * Some alternate pins for timers are on port 1, not handled by our code to get simpler code ... - * Note that the alternate function numbers for most capture and match functions on - * port 2 are 2 and 3 instead of 3 and 4 ! - */ -/* 16 bits timer 0 match / capture pins */ -#define LPC_TIMER_16B0_CHANNEL_0_PIO_28 28 -#define LPC_TIMER_16B0_CHANNEL_1_PIO_29 29 -#define LPC_TIMER_16B0_CHANNEL_0_PIO_11 11 -#define LPC_TIMER_16B0_CHANNEL_1_PIO_12 12 -/* Alternate on PIO2_0 and PIO2_1 */ - -/* 16 bits timer 1 match / capture pins */ -#define LPC_TIMER_16B1_CHANNEL_0_PIO_15 15 -#define LPC_TIMER_16B1_CHANNEL_1_PIO_16 16 -/* Alternate on PIO1_5 and PIO1_6 */ -/* Alternate on PIO2_2 and PIO2_3 */ - -/* 32 bits timer 0 match / capture pins */ -#define LPC_TIMER_32B0_CHANNEL_0_PIO_1 1 -#define LPC_TIMER_32B0_CHANNEL_1_PIO_2 2 -#define LPC_TIMER_32B0_CHANNEL_2_PIO_3 3 -#define LPC_TIMER_32B0_CHANNEL_3_PIO_4 4 -#define LPC_TIMER_32B0_CHANNEL_0_PIO_18 18 -#define LPC_TIMER_32B0_CHANNEL_1_PIO_19 19 -#define LPC_TIMER_32B0_CHANNEL_2_PIO_20 20 -#define LPC_TIMER_32B0_CHANNEL_3_PIO_21 21 -/* Alternate on PIO2_4 to PIO2_7 */ - -/* 32 bits timer 1 match / capture pins */ -#define LPC_TIMER_32B1_CHANNEL_0_PIO_6 6 -#define LPC_TIMER_32B1_CHANNEL_1_PIO_7 7 -#define LPC_TIMER_32B1_CHANNEL_2_PIO_8 8 -#define LPC_TIMER_32B1_CHANNEL_3_PIO_9 9 -#define LPC_TIMER_32B1_CHANNEL_0_PIO_23 23 -#define LPC_TIMER_32B1_CHANNEL_1_PIO_24 24 -#define LPC_TIMER_32B1_CHANNEL_2_PIO_25 25 -#define LPC_TIMER_32B1_CHANNEL_3_PIO_26 26 -/* Alternate on PIO2_8 to PIO2_11 */ - -/* Capture or match alternate function select for port 0 pins */ -#define LPC_TIMER_PIN_FUNC_CAPTURE LPC_IO_FUNC_ALT(3) -#define LPC_TIMER_PIN_FUNC_MATCH LPC_IO_FUNC_ALT(4) - - -/* Setup one pin to use as match or capture pin - * This configure function can be used only for pins on port 0. - * Use LPC_TIMER_*B*_CHANNEL_*_PIO_* definitions for the pin number and either - * LPC_TIMER_PIN_FUNC_CAPTURE or LPC_TIMER_PIN_FUNC_MATCH for the function. - * Note: These pins are not setup using the usual system set default pins functions - * as most functions may be affected to many different pins, and the use of the - * timers does no require the use of pins. - */ -void timer_pins_setup(uint8_t port, uint8_t pin_num, uint32_t func); - /* Power up a timer. * Note that clkrate should be a divider of the main clock frequency chosed -- 2.43.0