Very big update according to API documented for LPC122x and LPC82x micro-controllers master
authorNathael Pajani <nathael.pajani@ed3l.fr>
Fri, 9 Dec 2016 20:30:54 +0000 (21:30 +0100)
committerNathael Pajani <nathael.pajani@ed3l.fr>
Fri, 9 Dec 2016 20:30:54 +0000 (21:30 +0100)
Most has not been tested (only chenillard example)

71 files changed:
Makefile
README
apps/.gitignore [new file with mode: 0644]
apps/mbed_adapter/chenillard/Makefile [new file with mode: 0644]
apps/mbed_adapter/chenillard/README [new file with mode: 0644]
apps/mbed_adapter/chenillard/main.c [new file with mode: 0644]
apps/mbed_lpc1224/chenillard/Makefile
apps/mbed_lpc1224/chenillard/main.c
core/bootstrap.c
core/fault_handlers.c
core/iap.c
core/pio.c
core/rom_helpers.c
core/system.c
core/systick.c
core/vector_table.c
core/watchdog.c [new file with mode: 0644]
drivers/adc.c
drivers/countertimers.c [new file with mode: 0644]
drivers/gpio.c
drivers/i2c.c
drivers/serial.c
drivers/ssp.c
drivers/timers.c
drivers/usbcore.c [new file with mode: 0644]
extdrv/eeprom.c
extdrv/status_led.c
extdrv/tmp101_temp_sensor.c
include/core/iap.h
include/core/lpc_core.h [new file with mode: 0644]
include/core/lpc_core_cm0.h [deleted file]
include/core/lpc_regs.h [new file with mode: 0644]
include/core/lpc_regs_11u3x.h [deleted file]
include/core/pio.h
include/core/system.h
include/core/systick.h
include/core/watchdog.h [new file with mode: 0644]
include/drivers/adc.h
include/drivers/countertimers.h [new file with mode: 0644]
include/drivers/gpio.h
include/drivers/i2c.h
include/drivers/serial.h
include/drivers/ssp.h
include/drivers/timers.h
include/drivers/usb.h [new file with mode: 0644]
include/drivers/usb_rom.h [new file with mode: 0644]
include/extdrv/eeprom.h
include/extdrv/status_led.h
include/extdrv/tmp101_temp_sensor.h
include/lib/errno.h [new file with mode: 0644]
include/lib/font.h [new file with mode: 0644]
include/lib/list.h [new file with mode: 0644]
include/lib/protocols/dtplug/defs.h [new file with mode: 0644]
include/lib/protocols/dtplug/slave.h [new file with mode: 0644]
include/lib/stddef.h
include/lib/stdint.h [new file with mode: 0644]
include/lib/stdio.h
include/lib/stdlib.h
include/lib/string.h
include/lib/time.h
include/lib/usb_dap/dap.h [new file with mode: 0644]
include/lib/usb_dap/dap_version_html.h [new file with mode: 0644]
include/lib/utils.h
lib/protocols/dtplug/slave.c [new file with mode: 0644]
lib/stdlib.c
lib/string.c
lib/time.c
lib/uprintf.c
lib/utils.c
lib/vsprintf.c
lpc_link_lpc11u35.ld

index 32e5871..13bac0b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -25,6 +25,7 @@ TARGET_INCLUDES = $(TARGET_DIR)/
 OBJDIR = objs
 
 SRC = $(wildcard */*.c)
+SRC += $(wildcard lib/*/*.c)
 OBJS = ${SRC:%.c=${OBJDIR}/%.o}
 DEPS = ${OBJS:%.o=$(OBJDIR)/%.d}
 
diff --git a/README b/README
index e69de29..8577c0e 100644 (file)
--- a/README
+++ b/README
@@ -0,0 +1,3 @@
+dd if=image.bin of=/dev/disk/by-label/CRP\\x20DISABLD bs=512 seek=4
+
+
diff --git a/apps/.gitignore b/apps/.gitignore
new file mode 100644 (file)
index 0000000..fff9e1f
--- /dev/null
@@ -0,0 +1,10 @@
+# NOTE! Don't add files that are generated in specific
+# subdirectories here. Add them in the ".gitignore" file
+# in that subdirectory instead.
+#
+# NOTE! Please use 'git ls-files -i --exclude-standard'
+# command after changing this file, to see if there are
+# any tracked files which get ignored after the change.
+#
+# Normal rules
+dev
diff --git a/apps/mbed_adapter/chenillard/Makefile b/apps/mbed_adapter/chenillard/Makefile
new file mode 100644 (file)
index 0000000..a2742d0
--- /dev/null
@@ -0,0 +1,12 @@
+# Makefile for "base" apps for the LPC1224-mbed Module.
+
+MODULE = $(shell basename $(shell cd .. && pwd && cd -))
+NAME = $(shell basename $(CURDIR))
+
+.PHONY: $(NAME).bin
+$(NAME).bin:
+       @make -C ../../.. --no-print-directory NAME=$(NAME) MODULE=$(MODULE) apps/$(MODULE)/$(NAME)/$@
+
+clean mrproper:
+       @make -C ../../.. --no-print-directory $@
+
diff --git a/apps/mbed_adapter/chenillard/README b/apps/mbed_adapter/chenillard/README
new file mode 100644 (file)
index 0000000..4064184
--- /dev/null
@@ -0,0 +1,23 @@
+MBed adapter board gpio test
+
+Copyright 2016 Nathael Pajani <nathael.pajani@ed3l.fr>
+
+
+/* ****************************************************************************
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ *************************************************************************** */
+
+This code is used to test the support of the lpc11u35 internal modules.
+
diff --git a/apps/mbed_adapter/chenillard/main.c b/apps/mbed_adapter/chenillard/main.c
new file mode 100644 (file)
index 0000000..f0eb417
--- /dev/null
@@ -0,0 +1,155 @@
+/****************************************************************************
+ *   apps/mbed_lpc1224/chenillard/main.c
+ *
+ * LPC1224-mbed firmware for onboard LPC11U35 bridge
+ *
+ * Copyright 2013-2014 Nathael Pajani <nathael.pajani@ed3l.fr>
+ *
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ *************************************************************************** */
+
+
+#include "core/system.h"
+#include "core/pio.h"
+#include "core/systick.h"
+#include "lib/stdio.h"
+#include "drivers/serial.h"
+#include "drivers/gpio.h"
+#include "extdrv/status_led.h"
+
+
+#define MODULE_VERSION    0x01
+#define MODULE_NAME "Mbed-adapter"
+
+
+#define SELECTED_FREQ  FREQ_SEL_48MHz
+
+/***************************************************************************** */
+/* Pins configuration */
+/* pins blocks are passed to set_pins() for pins configuration.
+ * Unused pin blocks can be removed safely with the corresponding set_pins() call
+ * All pins blocks may be safelly merged in a single block for single set_pins() call..
+ */
+const struct pio_config common_pins[] = {
+       /* UART 0 */
+       { LPC_UART0_RX_PIO_0_18,  LPC_IO_DIGITAL },
+       { LPC_UART0_TX_PIO_0_19,  LPC_IO_DIGITAL },
+       /* USB */
+       { LPC_USB_FTOGGLE_PIO_0_1, LPC_IO_DIGITAL },
+       { LPC_USB_VBUS_PIO_0_3, (LPC_IO_DIGITAL | LPC_IO_MODE_PULL_DOWN) },
+       { LPC_USB_CONNECT_PIO_0_6, LPC_IO_DIGITAL },
+       ARRAY_LAST_PIO,
+};
+
+const struct pio status_led_red = LPC_GPIO_0_13; /* MSD */
+const struct pio status_led_green = LPC_GPIO_0_14; /* DAP */
+const struct pio status_led_blue = LPC_GPIO_0_15; /* Serial */
+
+const struct pio target_reset = LPC_GPIO_0_4;
+const struct pio target_isp = LPC_GPIO_0_5;
+const struct pio button_target_isp = LPC_GPIO_0_11;
+const struct pio button_target_reset = LPC_GPIO_0_12;
+
+const struct pio target_swd_swclk = LPC_GPIO_0_8;
+const struct pio target_swd_swdio = LPC_GPIO_0_10;
+
+
+
+
+/***************************************************************************** */
+void system_init()
+{
+       /* Stop the watchdog */
+       startup_watchdog_disable(); /* Do it right now, before it gets a chance to break in */
+       system_set_default_power_state();
+       clock_config(SELECTED_FREQ, LPC_SYSCLK_SRC_XTAL_OSC);
+       set_pins(common_pins);
+       gpio_on();
+       status_led_config(&status_led_green, &status_led_red, &status_led_blue, 0);
+       /* System tick timer MUST be configured and running in order to use the sleeping functions */
+       systick_timer_on(1); /* 1ms */
+       systick_start();
+}
+
+/* Define our fault handler. This one is not mandatory, the dummy fault handler
+ * will be used when it's not overridden here.
+ * Note : The default one does a simple infinite loop. If the watchdog is deactivated
+ * the system will hang.
+ * An alternative would be to perform soft reset of the micro-controller.
+ */
+void fault_info(const char* name, uint32_t len)
+{
+       uprintf(UART0, name);
+       while (1);
+}
+
+
+volatile uint32_t flag = 0;
+void stop_leds(uint32_t num)
+{
+       flag = 1;
+}
+
+/***************************************************************************** */
+int main(void)
+{
+       system_init();
+       uart_on(0, 115200, NULL);
+
+       set_gpio_callback(stop_leds, &button_target_isp, EDGES_BOTH);
+       set_gpio_callback(stop_leds, &button_target_reset, EDGES_BOTH);
+
+       while (1) {
+               status_led(all);
+               msleep(500);
+               status_led(none);
+               msleep(200);
+               status_led(red_only);
+               msleep(200);
+               status_led(green_only);
+               msleep(200);
+               status_led(blue_only);
+               msleep(200);
+               status_led(red_only);
+               msleep(200);
+               status_led(green_only);
+               msleep(200);
+               status_led(blue_only);
+               msleep(200);
+               status_led(red_on);
+               msleep(200);
+               status_led(green_on);
+               msleep(200);
+               status_led(blue_on);
+               msleep(200);
+               status_led(red_off);
+               msleep(200);
+               status_led(green_off);
+               msleep(200);
+               status_led(none);
+               if (flag != 0) {
+                       msleep(2000);
+                       uprintf(UART0, "button_pressed\n");
+                       flag = 0;
+               } else {
+                       msleep(200);
+               }
+       }
+       return 0;
+}
+
+
+
index b3a5e89..a2742d0 100644 (file)
@@ -1,10 +1,12 @@
-# Makefile for lpc11U35 mbed interface apps
+# Makefile for "base" apps for the LPC1224-mbed Module.
 
+MODULE = $(shell basename $(shell cd .. && pwd && cd -))
 NAME = $(shell basename $(CURDIR))
 
 .PHONY: $(NAME).bin
 $(NAME).bin:
-       @make -C ../.. --no-print-directory NAME=$(NAME) apps/$(NAME)/$@
+       @make -C ../../.. --no-print-directory NAME=$(NAME) MODULE=$(MODULE) apps/$(MODULE)/$(NAME)/$@
 
 clean mrproper:
-       @make -C ../.. --no-print-directory $@
+       @make -C ../../.. --no-print-directory $@
+
index 8b106b9..54779d1 100644 (file)
  *************************************************************************** */
 
 
-#include <stdint.h>
-#include "core/lpc_regs_11u3x.h"
-#include "core/lpc_core_cm0.h"
-#include "core/pio.h"
 #include "core/system.h"
+#include "core/pio.h"
 #include "core/systick.h"
 #include "lib/stdio.h"
 #include "drivers/serial.h"
@@ -69,26 +66,18 @@ const struct pio target_swd_swdio = LPC_GPIO_0_8;
 
 
 
-uint8_t gpio_get_pin_loader_state(void)
-{
-       uint8_t* gpio_bytes = LPC_GPIO_ALL_BYTES;
-       uint8_t offset = ((button_target_reset.port << 5) + button_target_reset.pin);
-       return gpio_bytes[offset];
-}
 
 /***************************************************************************** */
 void system_init()
 {
        /* Stop the watchdog */
-       stop_watchdog(); /* Do it right now, before it gets a chance to break in */
-       system_brown_out_detection_config(0);
+       startup_watchdog_disable(); /* Do it right now, before it gets a chance to break in */
        system_set_default_power_state();
        clock_config(SELECTED_FREQ, LPC_SYSCLK_SRC_XTAL_OSC);
        set_pins(common_pins);
        gpio_on();
-       status_led_config(&status_led_green, &status_led_red, &status_led_blue);
-       /* System tick timer MUST be configured and running in order to use the sleeping
-        * functions */
+       status_led_config(&status_led_green, &status_led_red, &status_led_blue, 0);
+       /* System tick timer MUST be configured and running in order to use the sleeping functions */
        systick_timer_on(1); /* 1ms */
        systick_start();
 }
@@ -97,11 +86,12 @@ void system_init()
  * will be used when it's not overridden here.
  * Note : The default one does a simple infinite loop. If the watchdog is deactivated
  * the system will hang.
+ * An alternative would be to perform soft reset of the micro-controller.
  */
 void fault_info(const char* name, uint32_t len)
 {
-       serial_write(0, name, len);
-       /*FIXME : wait for end of Tx and perform soft reset of the micro-controller ! */
+       uprintf(UART0, name);
+       while (1);
 }
 
 
@@ -112,12 +102,13 @@ void stop_leds(uint32_t num)
 }
 
 /***************************************************************************** */
-int main(void) {
+int main(void)
+{
        system_init();
        uart_on(0, 115200, NULL);
 
-       set_gpio_callback(stop_leds, 0, &button_target_isp, EDGES_BOTH);
-       set_gpio_callback(stop_leds, 1, &button_target_reset, EDGES_BOTH);
+       set_gpio_callback(stop_leds, &button_target_isp, EDGES_BOTH);
+       set_gpio_callback(stop_leds, &button_target_reset, EDGES_BOTH);
 
        while (1) {
                status_led(all);
@@ -149,6 +140,7 @@ int main(void) {
                status_led(none);
                if (flag != 0) {
                        msleep(2000);
+                       uprintf(UART0, "button_pressed\n");
                        flag = 0;
                } else {
                        msleep(200);
index 84d8f96..e615448 100644 (file)
@@ -46,16 +46,16 @@ void SVC_Handler(void) __attribute__ ((weak, alias ("Dummy_Handler")));
 void PendSV_Handler(void) __attribute__ ((weak, alias ("Dummy_Handler")));
 void SysTick_Handler(void) __attribute__ ((weak, alias ("Dummy_Handler")));
 /* LPC12xx specific interrupt handlers */
-void Pin_Int0_Handler(void) __attribute__ ((weak, alias ("Dummy_Handler")));
-void Pin_Int1_Handler(void) __attribute__ ((weak, alias ("Dummy_Handler")));
-void Pin_Int2_Handler(void) __attribute__ ((weak, alias ("Dummy_Handler")));
-void Pin_Int3_Handler(void) __attribute__ ((weak, alias ("Dummy_Handler")));
-void Pin_Int4_Handler(void) __attribute__ ((weak, alias ("Dummy_Handler")));
-void Pin_Int5_Handler(void) __attribute__ ((weak, alias ("Dummy_Handler")));
-void Pin_Int6_Handler(void) __attribute__ ((weak, alias ("Dummy_Handler")));
-void Pin_Int7_Handler(void) __attribute__ ((weak, alias ("Dummy_Handler")));
-void GPIO_GRP_INT0_Handler(void) __attribute__ ((weak, alias ("Dummy_Handler")));
-void GPIO_GRP_INT1_Handler(void) __attribute__ ((weak, alias ("Dummy_Handler")));
+void PININT_0_Handler(void) __attribute__ ((weak, alias ("Dummy_Handler")));
+void PININT_1_Handler(void) __attribute__ ((weak, alias ("Dummy_Handler")));
+void PININT_2_Handler(void) __attribute__ ((weak, alias ("Dummy_Handler")));
+void PININT_3_Handler(void) __attribute__ ((weak, alias ("Dummy_Handler")));
+void PININT_4_Handler(void) __attribute__ ((weak, alias ("Dummy_Handler")));
+void PININT_5_Handler(void) __attribute__ ((weak, alias ("Dummy_Handler")));
+void PININT_6_Handler(void) __attribute__ ((weak, alias ("Dummy_Handler")));
+void PININT_7_Handler(void) __attribute__ ((weak, alias ("Dummy_Handler")));
+void GPIO_GRPINT_0_Handler(void) __attribute__ ((weak, alias ("Dummy_Handler")));
+void GPIO_GRPINT_1_Handler(void) __attribute__ ((weak, alias ("Dummy_Handler")));
 void I2C_0_Handler(void) __attribute__ ((weak, alias ("Dummy_Handler")));
 void TIMER_0_Handler(void) __attribute__ ((weak, alias ("Dummy_Handler")));
 void TIMER_1_Handler(void) __attribute__ ((weak, alias ("Dummy_Handler")));
@@ -101,16 +101,16 @@ void *vector_table[] __attribute__ ((section(".vectors"))) = {
        PendSV_Handler,
        SysTick_Handler, /* 15 */
        /* LPC11U3x specific interrupt vectors, refer to chapter 6 of LPC11U3x User manual (UM10462) */
-       Pin_Int0_Handler,     /* 16 */ /* IRQ0 */
-       Pin_Int1_Handler,
-       Pin_Int2_Handler,
-       Pin_Int3_Handler,
-       Pin_Int4_Handler, /* 20 */
-       Pin_Int5_Handler, /* 21 */ /* IRQ5 */
-       Pin_Int6_Handler,
-       Pin_Int7_Handler,
-       GPIO_GRP_INT0_Handler,
-       GPIO_GRP_INT1_Handler, /* 25 */
+       PININT_0_Handler,     /* 16 */ /* IRQ0 */
+       PININT_1_Handler,
+       PININT_2_Handler,
+       PININT_3_Handler,
+       PININT_4_Handler, /* 20 */
+       PININT_5_Handler, /* 21 */ /* IRQ5 */
+       PININT_6_Handler,
+       PININT_7_Handler,
+       GPIO_GRPINT_0_Handler,
+       GPIO_GRPINT_1_Handler, /* 25 */
        0, /* 26 */ /* IRQ10 */
        0,
        0,
index f385c66..f49e63e 100644 (file)
  *
  *****************************************************************************/
 
-#include "core/lpc_regs_11u3x.h"
+/* Default "fault" handlers, which catch the fault exceptions.
+ * These are defined as weak aliases of a dummy fault handler which enters an empty infinite
+ *   loop and chould be overidden by user defined handlers.
+ */
+
+#include "lib/stdint.h"
 
 void fault_info(const char* name, uint32_t len) __attribute__ ((weak, alias ("Dummy_Fault_Handler")));
 
index ad55904..87c7e38 100644 (file)
  *
  *****************************************************************************/
 
-#include <stdint.h>
-#include "core/lpc_regs_11u3x.h"
+#include "lib/stdint.h"
+#include "core/system.h"
 #include "core/iap.h"
 
 
+/* IAP - In-Application Programming
+ * Driver for the IAP interface of the LPC122x.
+ * This interface allows In-Application programming of the internal flash memory of the LPC122x
+ *   microcontroller.
+ * Refer to LPC122x documentation (UM10441.pdf) for more information.
+ */
+
 static uint32_t get_sector_number(uint32_t addr)
 {
        uint32_t sector = 0;
@@ -64,7 +71,7 @@ int flash_hal_erase_sector(uint32_t addr)
 }
 
 /* Flash a binary image chunk to a sector. */
-int flash_hal_program_page(uint32_t addr, uint32_t sz, unsigned char *buf)
+int flash_hal_program_page(uint32_t addr, uint32_t size, unsigned char *buf)
 {
        uint32_t sector = 0;
        int ret = 0;
@@ -96,6 +103,62 @@ int flash_hal_program_page(uint32_t addr, uint32_t sz, unsigned char *buf)
        }
 
        /* FIXME : in original code, size was hardcoded to 1024 */
-       return iap_copy_ram_to_flash(addr, (uint32_t)buf, sz);
+       return iap_copy_ram_to_flash(addr, (uint32_t)buf, size);
+}
+
+
+/* Re-invoke ISP ROM routine
+ * This functionnality is part of the IAP interface, and enables running the boot process from
+ *   start once the microcontroller got flashed.
+ * This function is not supposed to return.
+ * Refer to Application Note AN11305 from NXP.
+ */
+/* FIXME : Refer to App note AN11305 and check all this.
+ *    Actually this is done as in CMSIS-DAP interface code. */
+void reinvoque_isp(void)
+{
+       struct lpc_sys_config* sys_ctrl = LPC_SYS_CONFIG;
+
+       /* make sure USB clock is turned on before calling ISP */
+       subsystem_power(LPC_SYS_ABH_CLK_CTRL_USB, 1); /* Enable clock to USB registers */
+       /* make sure 32-bit Timer 1 is turned on before calling ISP */
+       subsystem_power(LPC_SYS_ABH_CLK_CTRL_CT32B1, 1);
+       /* make sure GPIO clock is turned on before calling ISP */
+       subsystem_power(LPC_SYS_ABH_CLK_CTRL_GPIO, 1);
+       /* make sure IO configuration clock is turned on before calling ISP */
+       subsystem_power(LPC_SYS_ABH_CLK_CTRL_IO_CONFIG, 1);
+       /* make sure AHB clock divider is 1:1 */
+       sys_ctrl->sys_AHB_clk_div = 1;
+
+       /* Set stack pointer to ROM value (reset default) This must be the last piece of code executed
+        *   before calling ISP, because most C expressions and function returns will fail after the
+        *   stack pointer is changed. */
+       set_main_stack_pointer(*((uint32_t *)0x00000000));
+
+       /* Enter ISP. We call "iap_entry" to enter ISP because the ISP entry is done through the same
+        *   command interface as IAP. */
+       iap_reinvoke_isp();
+}
+
+
+static inline void go(void (*app) (void))
+{
+       app();
+}
+/* Start a given application without re-invocation of ISP code or system reset.
+ * Warning:
+ *   This is dangerous, as none of the registers will be in their default state.
+ *   There could be interrupts enables that your new application will have no hendler for, leading
+ *     to UB (undefined behavior).
+ */
+void start_app(uint32_t start_app_addr, uint32_t stack_pointer)
+{
+       /* setup for use of the main stack pointer */
+       uint32_t control = get_CONTROL();
+       set_CONTROL(control & ~(0x02));
+
+       set_main_stack_pointer(stack_pointer);
+
+       go((void *)start_app_addr);
 }
 
index 48f0285..b94ee2c 100644 (file)
@@ -25,9 +25,6 @@
 /*   Public access to Pins setup   */
 
 
-#include <stdint.h>
-#include "core/lpc_regs_11u3x.h"
-#include "core/lpc_core_cm0.h"
 #include "core/system.h"
 #include "core/pio.h"
 
@@ -146,3 +143,14 @@ void set_pins(const struct pio_config* pins)
        }
 }
 
+/* IO config clock */
+/* To change GPIO config the io config block must be powered on */
+void io_config_clk_on(void)
+{
+       subsystem_power(LPC_SYS_ABH_CLK_CTRL_IO_CONFIG, 1);
+}
+void io_config_clk_off(void)
+{
+       subsystem_power(LPC_SYS_ABH_CLK_CTRL_IO_CONFIG, 0);
+}
+
index 34f436d..a251686 100644 (file)
  *
  *************************************************************************** */
 
-#include <stdint.h>
+/* ROM helpers are functions avalable for the user which do not use space in the
+ *  internal reprogrammable flash.
+ * They are stored in the internal ROM memory and may be called using specific
+ *  calls with defined parameters depending on the ROM call used.
+ * Refer to LPC11u3x documentation for more information.
+ */
+
 #include "core/system.h"
-#include "core/lpc_core_cm0.h"
 #include "core/iap.h"
 #include "lib/string.h"
+#include "drivers/usb_rom.h"
 
 /*******************************************************************************/
 /*            Integer division using ROM based division routines               */
@@ -92,7 +98,6 @@ enum iap_commands {
        IAP_CMD_REINVOQUE_ISP = 57,
        IAP_CMD_READ_UID = 58,
        IAP_CMD_ERASE_PAGE = 59,
-       IAP_CMD_ERASE_INFO_PAGE = 60,
        IAP_CMD_EEPROM_WRITE = 61,
        IAP_CMD_EEPROM_READ = 62,
 };
@@ -104,6 +109,12 @@ static uint32_t params[5];
 static uint32_t results[5];
 
 
+void iap_reinvoke_isp(void)
+{
+       params[0] = IAP_CMD_REINVOQUE_ISP;
+       iap_entry(params, results);
+}
+
 int iap_prepare_flash(uint32_t start_sector, uint32_t end_sector)
 {
        params[0] = IAP_CMD_PREPARE_SECTORS_FOR_WRITE;
@@ -193,6 +204,13 @@ int iap_eeprom_read(uint8_t* eeprom_addr, uint8_t* ram_addr, uint32_t length)
 }
 
 
+/*******************************************************************************/
+/*            USB ROM based driver for CDC, DFU, HID and CDC                   */
+/*******************************************************************************/
+struct lpc_usb_rom_api* usb_rom_api;
+
+
+
 /*******************************************************************************/
 /*            Rom based routines initialisation                                */
 /*******************************************************************************/
@@ -200,7 +218,7 @@ int iap_eeprom_read(uint8_t* eeprom_addr, uint8_t* ram_addr, uint32_t length)
 #define LPC_11U3x_IAP_ROM_LOC (0x1FFF1FF1)
 
 struct rom_helpers {
-       const unsigned p_dev0;
+       const unsigned usb_rom;
        const unsigned p_dev1;
        const unsigned p_dev2;
        const unsigned p_dev3;
@@ -217,6 +235,7 @@ void rom_helpers_init(void)
 {
        rom_div_helpers = (struct lpc_rom_div_helpers*)(ROM_DRIVERS->rom_div);
        iap_entry = (iap_entry_func)LPC_11U3x_IAP_ROM_LOC;
+       usb_rom_api = (struct lpc_usb_rom_api*)(ROM_DRIVERS->usb_rom);
 }
 
 
index 2772b76..48e2bb1 100644 (file)
  *
  *************************************************************************** */
 
-#include <stdint.h>
+/*
+ * This file holds some system wide initialisation functions and clock or sleep
+ *   related functions.
+ */
 
-#include "core/lpc_regs_11u3x.h"
-#include "core/lpc_core_cm0.h"
 #include "core/system.h"
-#include "core/pio.h"
 #include "drivers/timers.h" /* Used for IRC calibration */
 
 
@@ -65,37 +65,18 @@ static void flash_accelerator_config(uint32_t freq_sel)
        fcfg->flash_cfg |= (freq_sel & 0x03);
 }
 
-/* Stop the watchdog */
-void stop_watchdog(void)
-{
-       struct lpc_sys_control* sys_ctrl = LPC_SYS_CONTROL;
-    struct lpc_watchdog* wdt = LPC_WDT;
-
-       /* Power wadchdog block before changing it's configuration */
-       if (! (sys_ctrl->sys_AHB_clk_ctrl & LPC_SYS_ABH_CLK_CTRL_Watchdog)) {
-               sys_ctrl->sys_AHB_clk_ctrl |= LPC_SYS_ABH_CLK_CTRL_Watchdog;
-       }
-       /* Stop watchdog */
-    wdt->mode = 0;
-    wdt->feed_seqence = 0xAA;
-    wdt->feed_seqence = 0x55;
-       /* And power it down */
-       sys_ctrl->sys_AHB_clk_ctrl &= ~(LPC_SYS_ABH_CLK_CTRL_Watchdog);
-       sys_ctrl->powerdown_run_cfg |= LPC_POWER_DOWN_WDT_OSC;
-}
-
 /* Configure the brown-out detection */
 void system_brown_out_detection_config(uint32_t level)
 {
-       struct lpc_sys_control* sys_ctrl = LPC_SYS_CONTROL;
+       struct lpc_sys_config* sys_config = LPC_SYS_CONFIG;
 
        if (level == 0) {
                /* Disable Brown-Out Detection, power it down */
-               sys_ctrl->powerdown_run_cfg |= LPC_POWER_DOWN_BOD;
+               sys_config->powerdown_run_cfg |= LPC_POWER_DOWN_BOD;
                lpc_private.brown_out_detection_enabled = 0;
        } else {
                /* Power on Brown-Out Detection. */
-               sys_ctrl->powerdown_run_cfg &= ~(LPC_POWER_DOWN_BOD);
+               sys_config->powerdown_run_cfg &= ~(LPC_POWER_DOWN_BOD);
                lpc_private.brown_out_detection_enabled = 1;
                /* Configure Brown-Out Detection */
                /* FIXME */
@@ -110,9 +91,9 @@ void system_brown_out_detection_config(uint32_t level)
  */
 void system_set_default_power_state(void)
 {
-       struct lpc_sys_control* sys_ctrl = LPC_SYS_CONTROL;
+       struct lpc_sys_config* sys_config = LPC_SYS_CONFIG;
        /* Start with all memory powered on and nothing else */
-       sys_ctrl->sys_AHB_clk_ctrl = LPC_SYS_ABH_CLK_CTRL_MEM_ALL;
+       sys_config->sys_AHB_clk_ctrl = LPC_SYS_ABH_CLK_CTRL_MEM_BASE;
 }
 
 /* Enter deep sleep.
@@ -120,15 +101,15 @@ void system_set_default_power_state(void)
  */
 void enter_deep_sleep(void)
 {
-       struct lpc_sys_control* sys_ctrl = LPC_SYS_CONTROL;
+       struct lpc_sys_config* sys_config = LPC_SYS_CONFIG;
 
        /* Ask for the same clock status when waking up */
-       sys_ctrl->powerdown_awake_cfg = sys_ctrl->powerdown_run_cfg;
+       sys_config->powerdown_wake_cfg = sys_config->powerdown_run_cfg;
        /* Set deep_sleep config */
        if (lpc_private.brown_out_detection_enabled) {
-               sys_ctrl->powerdown_sleep_cfg = LPC_DEEP_SLEEP_CFG_NOWDTLOCK_BOD_ON;
+               sys_config->powerdown_sleep_cfg = LPC_DEEP_SLEEP_CFG_NOWDTLOCK_BOD_ON;
        } else {
-               sys_ctrl->powerdown_sleep_cfg = LPC_DEEP_SLEEP_CFG_NOWDTLOCK_BOD_OFF;
+               sys_config->powerdown_sleep_cfg = LPC_DEEP_SLEEP_CFG_NOWDTLOCK_BOD_OFF;
        }
        /* Enter deep sleep */
        /* FIXME */
@@ -137,13 +118,19 @@ void enter_deep_sleep(void)
 /* Power on or off a subsystem */
 void subsystem_power(uint32_t power_bit, uint32_t on_off)
 {
-       struct lpc_sys_control* sys_ctrl = LPC_SYS_CONTROL;
+       struct lpc_sys_config* sys_config = LPC_SYS_CONFIG;
        if (on_off == 1) {
-               sys_ctrl->sys_AHB_clk_ctrl |= power_bit;
+               sys_config->sys_AHB_clk_ctrl |= power_bit;
        } else {
-               sys_ctrl->sys_AHB_clk_ctrl &= ~(power_bit);
+               sys_config->sys_AHB_clk_ctrl &= ~(power_bit);
        }
 }
+/* Check whether a subsystem is powered or not */
+uint8_t subsystem_powered(uint32_t power_bit)
+{
+       struct lpc_sys_config* sys_config = LPC_SYS_CONFIG;
+       return (sys_config->sys_AHB_clk_ctrl & power_bit);
+}
 
 /***************************************************************************** */
 /*                      System Clock                                           */
@@ -166,25 +153,25 @@ static void propagate_main_clock(void);
  */
 void clock_config(uint32_t freq_sel, uint32_t clk_src)
 {
-       struct lpc_sys_control* sys_ctrl = LPC_SYS_CONTROL;
+       struct lpc_sys_config* sys_config = LPC_SYS_CONFIG;
 
        lpc_disable_irq();
        /* Turn on IRC */
-       sys_ctrl->powerdown_run_cfg &= ~(LPC_POWER_DOWN_IRC);
-       sys_ctrl->powerdown_run_cfg &= ~(LPC_POWER_DOWN_IRC_OUT);
+       sys_config->powerdown_run_cfg &= ~(LPC_POWER_DOWN_IRC);
+       sys_config->powerdown_run_cfg &= ~(LPC_POWER_DOWN_IRC_OUT);
        /* Use IRC clock source for main clock during config */
-       sys_ctrl->main_clk_sel = LPC_SYSCLK_SRC_IRC_OSC;
+       sys_config->main_clk_sel = LPC_SYSCLK_SRC_IRC_OSC;
        /* Switch the main clock source */
-       sys_ctrl->main_clk_upd_en = 0;
-       sys_ctrl->main_clk_upd_en = 1;
+       sys_config->main_clk_upd_en = 0;
+       sys_config->main_clk_upd_en = 1;
 
        /* Set AHB clock divider : divide by one ... */
-       sys_ctrl->sys_AHB_clk_div = 1;
+       sys_config->sys_AHB_clk_div = 1;
        /* Configure number of CPU clocks for flash access before setting the new clock */
        flash_accelerator_config(freq_sel);
 
        /* power off PLL */
-       sys_ctrl->powerdown_run_cfg |= LPC_POWER_DOWN_SYSPLL;
+       sys_config->powerdown_run_cfg |= LPC_POWER_DOWN_SYSPLL;
 
        /* If using only internal RC, we are done */
        if (freq_sel == FREQ_SEL_IRC) {
@@ -206,26 +193,26 @@ void clock_config(uint32_t freq_sel, uint32_t clk_src)
                }
                lpc_private.main_clock = (((freq_sel >> 3) & 0xFF) * 12 * 1000 * 1000);
                /* Setup PLL dividers */
-               sys_ctrl->sys_pll_ctrl = (((M - 1) & 0x1F) | (N << 5));
+               sys_config->sys_pll_ctrl = (((M - 1) & 0x1F) | (N << 5));
                /* Turn power on/off for external crystal */
                if (clk_src == LPC_SYSCLK_SRC_XTAL_OSC) {
-                       sys_ctrl->powerdown_run_cfg &= ~(LPC_POWER_DOWN_SYS_OSC);
+                       sys_config->powerdown_run_cfg &= ~(LPC_POWER_DOWN_SYS_OSC);
                } else {
-                       sys_ctrl->powerdown_run_cfg |= LPC_POWER_DOWN_SYS_OSC;
+                       sys_config->powerdown_run_cfg |= LPC_POWER_DOWN_SYS_OSC;
                }
                /* Set sys_pll_clk to selected source */
-               sys_ctrl->sys_pll_clk_sel = clk_src;
-               sys_ctrl->sys_pll_clk_upd_en = 0;  /* SYSPLLCLKUEN must go from LOW to HIGH */
-               sys_ctrl->sys_pll_clk_upd_en = 1;
+               sys_config->sys_pll_clk_sel = clk_src;
+               sys_config->sys_pll_clk_upd_en = 0;  /* SYSPLLCLKUEN must go from LOW to HIGH */
+               sys_config->sys_pll_clk_upd_en = 1;
                /* Power-up PLL */
-               sys_ctrl->powerdown_run_cfg &= ~(LPC_POWER_DOWN_SYSPLL);
+               sys_config->powerdown_run_cfg &= ~(LPC_POWER_DOWN_SYSPLL);
                /* Wait Until PLL Locked */
-               while (!(sys_ctrl->sys_pll_status & 0x01));
+               while (!(sys_config->sys_pll_status & 0x01));
                /* Use PLL output as main clock */
-               sys_ctrl->main_clk_sel = LPC_SYSCLK_SRC_PLL_OUTPUT;
+               sys_config->main_clk_sel = LPC_SYSCLK_SRC_PLL_OUTPUT;
                /* Switch the main clock source */
-               sys_ctrl->main_clk_upd_en = 0;
-               sys_ctrl->main_clk_upd_en = 1;
+               sys_config->main_clk_upd_en = 0;
+               sys_config->main_clk_upd_en = 1;
        }
 
        /* And call all clock updaters */
@@ -282,25 +269,27 @@ void IRC_osc_calibration_done(void)
  */
 int IRC_osc_calibration(void)
 {
-       struct lpc_sys_control* sys_ctrl = LPC_SYS_CONTROL;
-       uint32_t timer_val = timer_get_counter_val(irc_trim_timer_num);
+       struct lpc_sys_config* sys_config = LPC_SYS_CONFIG;
+       uint32_t timer_val = 0;
 
        if (trim_timer_started == 0) {
                return -2;
        }
+
+       timer_get_counter_val(irc_trim_timer_num, &timer_val);
        if (timer_val > (trim_calibration_ref + trim_calibration_delta)) {
-               if ((sys_ctrl->IRC_ctrl & 0xFFFF) == 0) {
+               if ((sys_config->IRC_ctrl & 0xFFFF) == 0) {
                        /* We cannot do better trimming ... */
                        return -1;
                }
-               sys_ctrl->IRC_ctrl--;
+               sys_config->IRC_ctrl--;
                trimming_dec_count++;
        } else if (timer_val < (trim_calibration_ref - trim_calibration_delta)) {
-               if ((sys_ctrl->IRC_ctrl & 0xFFFF) == 0xFFFF) {
+               if ((sys_config->IRC_ctrl & 0xFFFF) == 0xFFFF) {
                        /* We cannot do better trimming ... */
                        return -1;
                }
-               sys_ctrl->IRC_ctrl++;
+               sys_config->IRC_ctrl++;
                trimming_inc_count;
        } else {
                trimming_no_change++;
@@ -328,16 +317,6 @@ static void propagate_main_clock(void)
        adc_clk_update();
 }
 
-/* IO config clock */
-/* To change GPIO config the io config block must be powered on */
-void io_config_clk_on(void)
-{
-       subsystem_power(LPC_SYS_ABH_CLK_CTRL_IO_CONFIG, 1);
-}
-void io_config_clk_off(void)
-{
-       subsystem_power(LPC_SYS_ABH_CLK_CTRL_IO_CONFIG, 0);
-}
 
 /***************************************************************************** */
 /*                    CLK Out                                                  */
@@ -351,21 +330,21 @@ void io_config_clk_off(void)
 
 void clkout_on(uint32_t src, uint32_t div)
 {
-       struct lpc_sys_control* sys_ctrl = LPC_SYS_CONTROL;
+       struct lpc_sys_config* sys_config = LPC_SYS_CONFIG;
 
        /* Select clk_out clock source */
-       sys_ctrl->clk_out_src_sel = (src & 0x03);
+       sys_config->clk_out_src_sel = (src & 0x03);
        /* Activate clk_out */
-       sys_ctrl->clk_out_div = (div & 0xFF);
-       sys_ctrl->clk_out_upd_en = 0;
-       sys_ctrl->clk_out_upd_en = 1;
+       sys_config->clk_out_div = (div & 0xFF);
+       sys_config->clk_out_upd_en = 0;
+       sys_config->clk_out_upd_en = 1;
 }
 void clkout_off(void)
 {
-       struct lpc_sys_control* sys_ctrl = LPC_SYS_CONTROL;
-       sys_ctrl->clk_out_div = 0; /* Disable CLKOUT */
-       sys_ctrl->clk_out_upd_en = 0;
-       sys_ctrl->clk_out_upd_en = 1;
+       struct lpc_sys_config* sys_config = LPC_SYS_CONFIG;
+       sys_config->clk_out_div = 0; /* Disable CLKOUT */
+       sys_config->clk_out_upd_en = 0;
+       sys_config->clk_out_upd_en = 1;
 }
 
 
index fcdf43e..d74a699 100644 (file)
  *************************************************************************** */
 
 
-
 /***************************************************************************** */
 /*               System Tick Timer                                             */
 /***************************************************************************** */
 
-#include <stdint.h>
-#include "core/lpc_regs_11u3x.h"
-#include "core/lpc_core_cm0.h"
+/* Driver for the internal systick timer of the LPC122x.
+ * Refer to the LPC122x documentation (UM10441.pdf) for more information
+ */
+
 #include "core/system.h"
 #include "core/systick.h"
+#include "lib/errno.h"
 
 
 /* Static variables */
index 98eebb5..b46bbc0 100644 (file)
  *
  *****************************************************************************/
 
-#include <stdint.h>
-#include "core/lpc_regs_11u3x.h"
+/* This file holds the code related to the vector table relocation in RAM.
+ * This mechanism is used by the IAP code before re-programming the first sector of the internal
+ *   flash memory which usually holds the active vector table.
+ */
+
+#include "lib/stdint.h"
+#include "core/system.h"
 #include "core/iap.h"
 
 #define NVIC_NUM_VECTORS (16 + 32)            /* CORE + MCU Peripherals */
@@ -38,7 +43,7 @@
 
 void relocate_vector_table(void)
 {
-       struct lpc_sys_control* sysctrl = LPC_SYS_CONTROL;
+       struct lpc_sys_config* sysctrl = LPC_SYS_CONFIG;
     int i;
     /* Space for dynamic vectors, initialised to allocate in R/W */
     static volatile uint32_t * vectors = (uint32_t*)NVIC_RAM_VECTOR_ADDRESS;
diff --git a/core/watchdog.c b/core/watchdog.c
new file mode 100644 (file)
index 0000000..e13013f
--- /dev/null
@@ -0,0 +1,289 @@
+/****************************************************************************
+ *   core/watchdog.c
+ *
+ * Watchdog support
+ *
+ * Copyright 2012 Nathael Pajani <nathael.pajani@ed3l.fr>
+ *
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ *************************************************************************** */
+
+/*
+ * This file implements support of the Windowed Watchdog (WWDT)
+ */
+
+#include "core/system.h"
+#include "core/watchdog.h"
+
+
+
+/***************************************************************************** */
+void watchdog_feed(void)
+{
+       struct lpc_watchdog* wdt = LPC_WDT;
+       subsystem_power(LPC_SYS_ABH_CLK_CTRL_Watchdog, 1);
+       lpc_disable_irq();
+       wdt->feed_seqence = 0xAA;
+       wdt->feed_seqence = 0x55;
+       lpc_enable_irq();
+}
+
+static void (*wdt_callback)(void) = NULL;
+
+void WDT_Handler(void)
+{
+       struct lpc_watchdog* wdt = LPC_WDT;
+       wdt->mode |= LPC_WDT_INTR_FLAG;
+       /* Call user callback if the user registered one */
+       if (wdt_callback != NULL) {
+               wdt_callback();
+       }
+}
+
+/* Lock the watchdog clock source. Once the clock is locked, the configuration is
+ * permanent, there's no way to change it. Make all configuration steps before locking
+ * the watchdog Clock source.
+*/
+void watchdog_lock_clk_src(void)
+{
+       struct lpc_watchdog* wdt = LPC_WDT;
+       wdt->clk_src_sel |= LPC_WDT_CLK_SRC_LOCK;
+}
+
+/* Lock the watchdog clock source power.
+ * Once locked, writes to the current watchdog clock power bits in powerdown_*_cfg will
+ *   have no effect.
+ * It is still possible to switch the watchdog clock source and turn of the clock if the
+ *   watchdog clock source has not been locked yet.
+ */
+void watchdog_lock_clk_src_power(void)
+{
+       struct lpc_sys_config* sys_config = LPC_SYS_CONFIG;
+       struct lpc_watchdog* wdt = LPC_WDT;
+
+       if (wdt->clk_src_sel & LPC_WDT_CLK_WDOSC) {
+               sys_config->powerdown_sleep_cfg &= ~(LPC_POWER_DOWN_WDT_OSC);
+               sys_config->powerdown_wake_cfg &= ~(LPC_POWER_DOWN_WDT_OSC);
+       } else {
+               sys_config->powerdown_wake_cfg &= ~(LPC_POWER_DOWN_IRC);
+               sys_config->powerdown_wake_cfg &= ~(LPC_POWER_DOWN_IRC_OUT);
+       }
+       wdt->mode |= LPC_WDT_CLK_POWER_LOCK;
+}
+
+/* Lock the watchdog timer value */
+void watchdog_lock_timer_val(void)
+{
+       struct lpc_watchdog* wdt = LPC_WDT;
+       wdt->mode |= LPC_WDT_TIMER_VAL_PROTECT;
+}
+
+/* Change the watchdog timer value, if not protected */
+void watchdog_set_timer_val(uint32_t nb_clk)
+{
+       struct lpc_watchdog* wdt = LPC_WDT;
+
+       if (!(wdt->mode & LPC_WDT_TIMER_VAL_PROTECT)) {
+               wdt->timer_const = ((nb_clk >> 2) & LPC_WDT_TIMER_MAX);
+       }
+}
+
+/* Lock the Watchdog enable bit.
+ * It is still possible to disable the watchdog by setting it's clock to an unpowered
+ *   source if you did not lock the watchdog clock source and clock source power.
+ */
+void watchdog_lock_enable(void)
+{
+       struct lpc_watchdog* wdt = LPC_WDT;
+       wdt->mode |= LPC_WDT_EN_LOCK;
+}
+/* Lock the watchdog and all related features.
+ * Calls all the other watchdog_lock_* functions (clk_src, clk_src_power, timer_val, enable).
+ */
+void watchdog_lock_full(void)
+{
+       watchdog_lock_enable();
+       watchdog_lock_timer_val();
+       watchdog_lock_clk_src_power();
+       watchdog_lock_clk_src();
+}
+
+/* Disable deep power down mode entry
+ * Calls to wfi() will allow entry in sleep and deep-sleep modes, but not deep-power-down mode.
+ */
+void watchdog_disable_power_down(void)
+{
+       struct lpc_watchdog* wdt = LPC_WDT;
+       wdt->mode |= LPC_WDT_POWER_DOWN_DISABLE;
+}
+
+/*
+ * Configure the watchdog.
+ * clk_sel is either 0 (IRC) or 1 (WDTCLK). The corresponding clock source will be powered on.
+ * Note : only WDTCLK is running in deep power down mode
+ * Note : protecting the clock source power will prevent turning off the IRC for power saving
+ *   if it is selected as main clock source.
+ */
+void watchdog_config(const struct wdt_config* wd_conf)
+{
+       struct lpc_sys_config* sys_config = LPC_SYS_CONFIG;
+       struct lpc_watchdog* wdt = LPC_WDT;
+
+       NVIC_DisableIRQ(WDT_IRQ);
+       /* Power wadchdog block before changing it's configuration */
+       subsystem_power(LPC_SYS_ABH_CLK_CTRL_Watchdog, 1);
+       /* If intr_mode_only is set, a watchdog timeout will trigger an interrupt instead of a reset */
+       if (wd_conf->intr_mode_only == 1) {
+               wdt->mode = LPC_WDT_EN;
+       } else {
+               wdt->mode = LPC_WDT_EN | LPC_WDT_RESET_ON_TIMEOUT;
+       }
+       /* Register the callback for the interrupt */
+       wdt_callback = wd_conf->callback;
+       /* Configure watchdog timeout for normal operation */
+       wdt->timer_const = ((wd_conf->nb_clk >> 2) & LPC_WDT_TIMER_MAX);
+       /* Watchdog clock select */
+       if (wd_conf->clk_sel == LPC_WDT_CLK_IRC) {
+               sys_config->powerdown_run_cfg &= ~(LPC_POWER_DOWN_IRC);
+               sys_config->powerdown_run_cfg &= ~(LPC_POWER_DOWN_IRC_OUT);
+               wdt->clk_src_sel = LPC_WDT_CLK_IRC;
+       } else {
+               sys_config->powerdown_run_cfg &= ~(LPC_POWER_DOWN_WDT_OSC);
+               wdt->clk_src_sel = LPC_WDT_CLK_WDOSC;
+       }
+       /* Use the windows functionnality ? */
+       if (wd_conf->wdt_window > 0x100) {
+               wdt->window_compare = (wd_conf->wdt_window & LPC_WDT_TIMER_MAX);
+       }
+       /* Warning interrupt ? */
+       if (wd_conf->wdt_warn != 0) {
+               if (wd_conf->wdt_warn > LPC_WDT_WARNINT_MAXVAL) {
+                       wdt->warning_int_compare = LPC_WDT_WARNINT_MAXVAL;
+               } else {
+                       wdt->warning_int_compare = wd_conf->wdt_warn;
+               }
+       }
+       /* Protect any of the watchdog functions now ? */
+       if (wd_conf->locks != 0) {
+               uint32_t mode = wdt->mode;
+               if (wd_conf->locks & WDT_CLK_POWER_LOCK) {
+                       mode |= LPC_WDT_CLK_POWER_LOCK;
+                       if (wd_conf->clk_sel == LPC_WDT_CLK_WDOSC) {
+                               sys_config->powerdown_sleep_cfg &= ~(LPC_POWER_DOWN_WDT_OSC);
+                               sys_config->powerdown_wake_cfg &= ~(LPC_POWER_DOWN_WDT_OSC);
+                       } else {
+                               sys_config->powerdown_wake_cfg &= ~(LPC_POWER_DOWN_IRC);
+                               sys_config->powerdown_wake_cfg &= ~(LPC_POWER_DOWN_IRC_OUT);
+                       }
+               }
+               if (wd_conf->locks & WDT_CLK_SRC_LOCK) {
+                       wdt->clk_src_sel |= LPC_WDT_CLK_SRC_LOCK;
+               }
+               if (wd_conf->locks & WDT_EN_LOCK) {
+                       mode |= LPC_WDT_EN_LOCK;
+               }
+               if (wd_conf->locks & WDT_TIMER_VAL_LOCK) {
+                       mode |= LPC_WDT_TIMER_VAL_PROTECT;
+               }
+               if (wd_conf->locks & WDT_POWER_DOWN_LOCK) {
+                       mode |= LPC_WDT_POWER_DOWN_DISABLE;
+               }
+               wdt->mode = mode;
+       }
+       /* Feed sequence to validate the configuration */
+       watchdog_feed();
+       NVIC_EnableIRQ(WDT_IRQ);
+}
+
+
+/*
+ * Stop the watchdog
+ * This function can be used during system operation to stop the watchdog if it has not
+ *   been locked or protected against clock source modification, for example when entering
+ *   sleep or deep sleep.
+ * It will also try to power-down the oscilators if not used for main clock.
+ * Return 0 if a solution has been found to stop the watchdog, or -1 if watchdog is still
+ *   running after this call.
+ * TODO : Check this function, and implement the missing cases
+ */
+int stop_watchdog(void)
+{
+       struct lpc_sys_config* sys_config = LPC_SYS_CONFIG;
+       struct lpc_watchdog* wdt = LPC_WDT;
+       int ret = -1;
+
+       NVIC_DisableIRQ(WDT_IRQ);
+       subsystem_power(LPC_SYS_ABH_CLK_CTRL_Watchdog, 1);
+       /* Clear enable bit ? */
+       if (!(wdt->mode & LPC_WDT_EN_LOCK)) {
+               wdt->mode &= ~(LPC_WDT_EN);
+               watchdog_feed();
+               ret = 0;
+       } else if (!(wdt->clk_src_sel & LPC_WDT_CLK_SRC_LOCK)) {
+               /* If Watchdog enable bit cannot be cleared, try to set watchdog clock to
+                *   an unpowered clock source */
+               /* If current clock is WDCLK and power to curent clock is protected, temprarily
+                *   move clk source to IRC */
+               if ((wdt->clk_src_sel == LPC_WDT_CLK_WDOSC) && (wdt->mode & LPC_WDT_CLK_POWER_LOCK)) {
+                       wdt->clk_src_sel = LPC_WDT_CLK_IRC;
+               }
+               sys_config->powerdown_run_cfg |= LPC_POWER_DOWN_WDT_OSC;
+               /* Power wadchdog block before changing it's configuration */
+               wdt->clk_src_sel = LPC_WDT_CLK_WDOSC;
+               ret = 0;
+       }
+       if (ret != 0) {
+               subsystem_power(LPC_SYS_ABH_CLK_CTRL_Watchdog, 0);
+               return -1;
+       }
+       if (wdt->mode & LPC_WDT_CLK_POWER_LOCK) {
+               subsystem_power(LPC_SYS_ABH_CLK_CTRL_Watchdog, 0);
+               return 0;
+       }
+       /* If main clock and clkout not running from IRC (possibly through PLL), turn off IRC */
+       if ((sys_config->main_clk_sel != LPC_MAIN_CLK_SRC_IRC_OSC) &&
+               ((sys_config->main_clk_sel & 0x01) && (sys_config->sys_pll_clk_sel != LPC_PLL_CLK_SRC_IRC_OSC)) &&
+               (sys_config->clk_out_src_sel != LPC_CLKOUT_SRC_IRC_OSC)) {
+               sys_config->powerdown_run_cfg |= LPC_POWER_DOWN_IRC;
+               sys_config->powerdown_run_cfg |= LPC_POWER_DOWN_IRC_OUT;
+       }
+       subsystem_power(LPC_SYS_ABH_CLK_CTRL_Watchdog, 0);
+       return 0;
+}
+
+
+
+/*
+ * Disable the watchdog
+ * This function can be used upon system startup to disable watchdog operation
+ */
+void startup_watchdog_disable(void)
+{
+       struct lpc_sys_config* sys_config = LPC_SYS_CONFIG;
+       struct lpc_watchdog* wdt = LPC_WDT;
+
+       /* Power wadchdog block before changing it's configuration */
+       subsystem_power(LPC_SYS_ABH_CLK_CTRL_Watchdog, 1);
+       /* Stop watchdog */
+       wdt->mode = 0;
+       watchdog_feed();
+       /* And power it down */
+       subsystem_power(LPC_SYS_ABH_CLK_CTRL_Watchdog, 0);
+       sys_config->powerdown_run_cfg |= LPC_POWER_DOWN_WDT_OSC;
+       NVIC_DisableIRQ(WDT_IRQ);
+}
+
+
index 5e1f33f..08c1847 100644 (file)
@@ -1,7 +1,7 @@
 /****************************************************************************
  *  drivers/adc.c
  *
- * Copyright 2012 Nathael Pajani <nathael.pajani@ed3l.fr>
+ * Copyright 2012-2016 Nathael Pajani <nathael.pajani@ed3l.fr>
  *
  * 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
 /*                Analog to Digital Converter (ADC)                            */
 /***************************************************************************** */
 
-#include <stdint.h>
-#include "core/lpc_regs_11u3x.h"
-#include "core/lpc_core_cm0.h"
+/* ADC driver for the integrated ADC module of the LPC11u3x
+ * Refer to LPC11u3x documentation (UM10462.pdf) for more information.
+ */
+
 #include "core/system.h"
-#include "core/pio.h"
+#include "lib/errno.h"
 #include "drivers/adc.h"
 
-
 /* Should be as near to 4.5MHz as possible
  * See LPC11U3x manual (UM10462.pdf), remark on page 381 in section 19.2.
  */
 
 /***************************************************************************** */
 /* Generic ADC handler */
+void (*adc_int_callback)(uint32_t) = NULL;
 void ADC_Handler(void)
 {
-/*
-       volatile struct lpc_adc* adc = LPC_ADC;
+       volatile struct lpc_adc* adc = LPC_ADC_REGS;
        uint32_t status = adc->status;
-*/
-       /* .... What to do ... is specific to your application */
-       /* FIXME : Add an handler callback. */
+
+       if (adc_int_callback != NULL) {
+               adc_int_callback(status);
+       }
 }
 
 /* Read the conversion from the given channel (0 to 7)
  * This function reads the conversion value directly in the data register and
  * always returns a value.
  * Return 0 if the value is a new one and no overrun occured.
- * Return -1 if channel does not exist
+ * Return -EINVAL if channel does not exist
  * Retuen 1 if the value is an old one
  * Return 2 if an overrun occured
  */
-int adc_get_value(uint16_t * val, int channel)
+int adc_get_value(uint16_t * val, uint8_t channel)
 {
-       struct lpc_adc* adc = LPC_ADC;
+       struct lpc_adc* adc = LPC_ADC_REGS;
        uint32_t save_reg = 0;
 
-       if (channel > 7)
-               return -1;
+       if (channel >= NB_ADC_CHANNELS)
+               return -EINVAL;
 
        /* Save the whole register as some bits are cleared when register is read */
        save_reg = adc->data[channel];
@@ -81,24 +82,24 @@ int adc_get_value(uint16_t * val, int channel)
 }
 
 /* Start a conversion on the given channel (0 to 7) */
-void adc_start_convertion_once(unsigned int channel, int use_int)
+void adc_start_convertion_once(uint8_t channel, uint8_t seq_num, uint8_t use_int)
 {
-       struct lpc_adc* adc = LPC_ADC;
+       struct lpc_adc* adc = LPC_ADC_REGS;
        uint32_t reg_val = 0;
 
-       if (channel > 7)
+       if (channel >= NB_ADC_CHANNELS)
                return;
 
        /* Get a clean control register */
-       reg_val = adc->ctrl & ~(LPC_ADC_CHANNEL_MASK | LPC_ADC_START_CONV_MASK | LPC_ADC_BURST);
+       reg_val = adc->ctrl & ~(ADC_MCH_MASK | LPC_ADC_START_CONV_MASK | LPC_ADC_BURST);
 
        /* Set conversion channel bit */
-       reg_val |= LPC_ADC_CHANNEL(channel);
+       reg_val |= ADC_MCH(channel);
 
        /*  Use of interrupts for the specified channel ? */
        if (use_int) {
                /* Set interrupt Bit */
-               adc->int_en = LPC_ADC_CHANNEL(channel);
+               adc->int_en = ADC_MCH(channel);
        } else {
                adc->int_en = 0;
        }
@@ -111,15 +112,15 @@ void adc_start_convertion_once(unsigned int channel, int use_int)
 
 /* Start burst conversions.
  * channels is a bit mask of requested channels.
- * Use LPC_ADC_CHANNEL(x) (x = 0 .. 7) for channels selection.
+ * Use ADC_MCH(x) (x = 0 .. 7) for channels selection.
  */
-void adc_start_burst_conversion(uint8_t channels)
+void adc_start_burst_conversion(uint16_t channels, uint8_t seq_num)
 {
-       struct lpc_adc* adc = LPC_ADC;
+       struct lpc_adc* adc = LPC_ADC_REGS;
        uint32_t reg_val = 0;
 
        /* Get a clean control register */
-       reg_val = adc->ctrl & ~(LPC_ADC_CHANNEL_MASK | LPC_ADC_START_CONV_MASK | LPC_ADC_BURST);
+       reg_val = adc->ctrl & ~(ADC_MCH_MASK | LPC_ADC_START_CONV_MASK | LPC_ADC_BURST);
 
        /* Set conversion channel bits and burst mode */
        reg_val |= channels;
@@ -134,31 +135,28 @@ void adc_start_burst_conversion(uint8_t channels)
        adc->ctrl = (reg_val & LPC_ADC_CTRL_MASK);
 }
 
+void adc_stop_burst_conversion(uint8_t seq_num)
+{
+}
+
 
 /* This should be used to configure conversion start on falling or rising edges of
  * some signals, or on timer for burst conversions.
  */
-void adc_prepare_conversion_on_event(uint8_t channels, uint8_t event, int use_int)
+void adc_prepare_conversion_on_event(uint16_t channels, uint8_t seq_num, uint8_t event,
+                                                                               uint8_t use_int, uint32_t mode)
 {
-       struct lpc_adc* adc = LPC_ADC;
+       struct lpc_adc* adc = LPC_ADC_REGS;
        uint32_t reg_val = 0;
 
        /* Get a clean control register */
-       reg_val = adc->ctrl & ~(LPC_ADC_CHANNEL_MASK | LPC_ADC_START_CONV_MASK | LPC_ADC_BURST);
+       reg_val = adc->ctrl & ~(ADC_MCH_MASK | LPC_ADC_START_CONV_MASK | LPC_ADC_BURST);
        /* Set conversion channel bits and burst mode */
-       reg_val |= channels;
+       reg_val |= (channels & ADC_MCH_MASK);
        /* Set conversion condition bits */
-       switch (event) {
-               case ADC_CONV_ON_CT32B0_MAT0_RISING :
-                       reg_val |= LPC_ADC_START_CONV_EVENT(LPC_ADC_START_CONV_EDGE_CT32B0_MAT0);
-                       reg_val |= LPC_ADC_START_EDGE_RISING;
-                       break;
-               case ADC_CONV_ON_CT16B0_MAT0_RISING :
-                       reg_val |= LPC_ADC_START_CONV_EVENT(LPC_ADC_START_CONV_EDGE_CT16B0_MAT0);
-                       reg_val |= LPC_ADC_START_EDGE_RISING;
-                       break;
-               default:
-                       break;
+       reg_val |= LPC_ADC_START_CONV_EVENT(event);
+       if (mode != 0) {
+               reg_val |= (mode & LPC_ADC_ADDITIONAL_MODE_MASK);
        }
 
        /*  Use of interrupts for the specified channel ? */
@@ -172,13 +170,24 @@ void adc_prepare_conversion_on_event(uint8_t channels, uint8_t event, int use_in
        adc->ctrl = (reg_val & LPC_ADC_CTRL_MASK);
 }
 
+
+/* Software trigger of the given configured sequence */
+void adc_trigger_sequence_conversion(uint8_t seq_num)
+{
+       struct lpc_adc* adc = LPC_ADC_REGS;
+
+       adc->ctrl &= ~(LPC_ADC_START_CONV_MASK);
+       adc->ctrl |= LPC_ADC_START_CONV_NOW;
+}
+
+
 /* Change The ADC resolution.
  * Use defines from lpc_regs_11xx.h to specify the bit width for the convertion.
  * Ranges from LPC_ADC_3BITS to LPC_ADC_10BITS.
  */
 int adc_set_resolution(int bits)
 {
-       struct lpc_adc* adc = LPC_ADC;
+       struct lpc_adc* adc = LPC_ADC_REGS;
        if (bits & ~LPC_ADC_BITS_MASK) {
                return -EINVAL;
        }
@@ -192,7 +201,7 @@ int adc_set_resolution(int bits)
 
 void adc_clk_update(void)
 {
-       struct lpc_adc* adc = LPC_ADC;
+       struct lpc_adc* adc = LPC_ADC_REGS;
        uint32_t main_clock = get_main_clock();
        uint32_t clkdiv = 0;
 
@@ -202,16 +211,20 @@ void adc_clk_update(void)
 }
 
 
-void adc_on(void)
+void adc_on(void (*adc_callback)(uint32_t))
 {
-       struct lpc_sys_control* sys_ctrl = LPC_SYS_CONTROL;
-       struct lpc_adc* adc = LPC_ADC;
+       struct lpc_sys_config* sys_config = LPC_SYS_CONFIG;
+       struct lpc_adc* adc = LPC_ADC_REGS;
 
        /* Disable ADC Interrupt */
        NVIC_DisableIRQ(ADC_IRQ);
 
+       /* Brown-Out detection must be powered to operate the ADC.
+        * See Section 19.2 of UM10441 revision 2.1 or newer for more information */
+       sys_config->powerdown_run_cfg &= ~LPC_POWER_DOWN_BOD;
+
        /* Power-up ADC */
-       sys_ctrl->powerdown_run_cfg &= ~LPC_POWER_DOWN_ADC;
+       sys_config->powerdown_run_cfg &= ~LPC_POWER_DOWN_ADC;
        /* Provide clock to ADC */
        subsystem_power(LPC_SYS_ABH_CLK_CTRL_ADC, 1);
        adc_clk_update();
@@ -221,6 +234,8 @@ void adc_on(void)
 
        /* Remove the default global interrupt enabled setting */
        adc->int_en = 0;
+       /* Register a possible calback */
+       adc_int_callback = adc_callback;
 
        /* Enable ADC Interrupt */
        NVIC_EnableIRQ(ADC_IRQ);
@@ -228,12 +243,14 @@ void adc_on(void)
 
 void adc_off(void)
 {
-       struct lpc_sys_control* sys_ctrl = LPC_SYS_CONTROL;
+       struct lpc_sys_config* sys_config = LPC_SYS_CONFIG;
 
        /* Disable ADC Interrupt */
        NVIC_DisableIRQ(ADC_IRQ);
+       /* Remove callback */
+       adc_int_callback = NULL;
        /* Power Down ADC */
-       sys_ctrl->powerdown_run_cfg |= LPC_POWER_DOWN_ADC;
+       sys_config->powerdown_run_cfg |= LPC_POWER_DOWN_ADC;
        /* Remove clock from ADC block */
        subsystem_power(LPC_SYS_ABH_CLK_CTRL_ADC, 0);
 }
diff --git a/drivers/countertimers.c b/drivers/countertimers.c
new file mode 100644 (file)
index 0000000..a074c86
--- /dev/null
@@ -0,0 +1,371 @@
+/****************************************************************************
+ *  drivers/countertimers.c
+ *
+ * Copyright 2016 Nathael Pajani <nathael.pajani@ed3l.fr>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ *************************************************************************** */
+
+
+
+/***************************************************************************** */
+/*                Timers                                                       */
+/***************************************************************************** */
+
+/* Timers driver for the integrated timers of the LPC11u3x.
+ * The LPC11u3x has two 16bits timers and two 32bits timers.
+ * Refer to LPC11u3x documentation (UM10462.pdf) for more information.
+ */
+
+#include "core/system.h"
+#include "lib/errno.h"
+#include "drivers/timers.h"
+#include "drivers/countertimers.h"
+
+
+/* These are local to our file */
+struct countertimer_device
+{
+       struct lpc_timer* regs;
+       uint32_t power_bit;
+       uint8_t irq;
+       uint8_t configured;
+       void (*callback)(uint32_t); /* Possible RX callback */
+};
+
+static struct countertimer_device countertimers[NUM_COUNTERTIMERS] = {
+       {
+               .regs = LPC_TMR16B0,
+               .power_bit = LPC_SYS_ABH_CLK_CTRL_CT16B0,
+               .irq = TIMER0_IRQ,
+               .configured = 0,
+               .callback = NULL,
+       },
+       {
+               .regs = LPC_TMR16B1,
+               .power_bit = LPC_SYS_ABH_CLK_CTRL_CT16B1,
+               .irq = TIMER1_IRQ,
+               .configured = 0,
+               .callback = NULL,
+       },
+       {
+               .regs = LPC_TMR32B0,
+               .power_bit = LPC_SYS_ABH_CLK_CTRL_CT32B0,
+               .irq = TIMER2_IRQ,
+               .configured = 0,
+               .callback = NULL,
+       },
+       {
+               .regs = LPC_TMR32B1,
+               .power_bit = LPC_SYS_ABH_CLK_CTRL_CT32B1,
+               .irq = TIMER3_IRQ,
+               .configured = 0,
+               .callback = NULL,
+       },
+};
+
+/* Handlers */
+void TIMER_Handler(struct countertimer_device* timer)
+{
+       uint32_t intr_flags = timer->regs->int_reg; /* Backup the flags */
+
+       /* Clear the interrupt */
+       timer->regs->int_reg = intr_flags;
+       /* And call the user routine if one has been registered */
+       if (timer->callback != NULL) {
+               timer->callback(intr_flags);
+       }
+}
+void TIMER_0_Handler(void)
+{
+       TIMER_Handler(&countertimers[0]);
+}
+void TIMER_1_Handler(void)
+{
+       TIMER_Handler(&countertimers[1]);
+}
+void TIMER_2_Handler(void)
+{
+       TIMER_Handler(&countertimers[2]);
+}
+void TIMER_3_Handler(void)
+{
+       TIMER_Handler(&countertimers[3]);
+}
+
+
+
+/* Start the timer :
+ * Remove the reset flag if present and set timer enable flag.
+ * Timer must be turned on and configured (no checks done here).
+ */
+void countertimer_start(uint8_t timer_num)
+{
+       /* Remove reset flag and set timer enable flag */
+       countertimers[timer_num].regs->timer_ctrl = LPC_TIMER_COUNTER_ENABLE;
+}
+
+/* Pause the timer counter, does not reset */
+void countertimer_pause(uint8_t timer_num)
+{
+       /* Remove timer enable flag */
+       countertimers[timer_num].regs->timer_ctrl = 0;
+}
+
+/* Stops and resets the timer counter */
+void countertimer_stop(uint8_t timer_num)
+{
+       /* Remove timer enable flag and request reset */
+       countertimers[timer_num].regs->timer_ctrl = LPC_TIMER_COUNTER_RESET;
+       /* Remove reset flag */
+       countertimers[timer_num].regs->timer_ctrl = 0;
+}
+
+/* Resets the timer and lets it count again imediately */
+void countertimer_restart(uint8_t timer_num)
+{
+       /* Set timer reset flag */
+       countertimers[timer_num].regs->timer_ctrl = LPC_TIMER_COUNTER_RESET;
+       /* Remove reset flag and start counter */
+       countertimers[timer_num].regs->timer_ctrl = LPC_TIMER_COUNTER_ENABLE;
+}
+
+int countertimer_get_counter_val(uint8_t timer_num, uint32_t* val)
+{
+       *val = countertimers[timer_num].regs->timer_counter;
+       return 0;
+}
+
+int countertimer_get_capture_val(uint8_t timer_num, uint8_t channel, uint32_t* val)
+{
+       if (channel >= MAX_CHANNELS) {
+               return -EINVAL;
+       }
+       *val = countertimers[timer_num].regs->capture_reg[channel];
+       return 0;
+}
+
+
+/* Change the match value of a single timer channel */
+int countertimer_set_match(uint8_t timer_num, uint8_t channel, uint32_t val)
+{
+       if (channel > NUM_COUNTERTIMERS_CHANS)
+               return -EINVAL;
+
+       countertimers[timer_num].regs->match_reg[channel] = val;
+       return 0;
+}
+
+struct common_operations countertimer_ops = {
+       .start = countertimer_start,
+       .cont = countertimer_start,
+       .pause = countertimer_pause,
+       .stop = countertimer_stop,
+       .restart = countertimer_restart,
+       .halt = countertimer_stop,
+       .get_counter = countertimer_get_counter_val,
+       .get_capture = countertimer_get_capture_val,
+       .set_match = countertimer_set_match,
+};
+
+
+
+/*******************************************************************************/
+/* Configuration operations */
+
+
+/*   Timer Setup as PWM */
+/* Returns 0 on success
+ * Takes a timer number and a timer PWM config structure as arguments.
+ * Refer to timer PWM config structure for details.
+ */
+int countertimer_pwm_setup(uint8_t timer_num, const struct lpc_timer_pwm_config* conf)
+{
+       struct countertimer_device* timer = &(countertimers[timer_num]);
+       uint8_t max_chan = 0;
+       uint8_t active_chans = 0;
+       int i = 0;
+
+       /* Make sure we have a PWM cycle length */
+       if (conf->period == 0) {
+               return -EINVAL;
+       }
+       switch (timer_num) {
+               case LPC_TIMER_16B0:
+               case LPC_TIMER_16B1:
+                       if (conf->nb_channels > NUM_COUNTERTIMERS_16B_PWM_CHANS) {
+                               return -EINVAL;
+                       }
+                       max_chan = NUM_COUNTERTIMERS_16B_PWM_CHANS;
+                       break;
+               case LPC_TIMER_32B0:
+               case LPC_TIMER_32B1:
+                       if (conf->nb_channels > NUM_COUNTERTIMERS_32B_PWM_CHANS) {
+                               return -EINVAL;
+                       }
+                       max_chan = NUM_COUNTERTIMERS_32B_PWM_CHANS;
+                       break;
+       }
+
+       if (conf->period_chan >= MAX_CHANNELS) {
+                return -EINVAL;
+       }
+       /* Setup selected PWM channels */
+       for (i = 0; i < conf->nb_channels; i++) {
+               if (conf->outputs[i] >= max_chan) {
+                       continue;
+               }
+               timer->regs->match_reg[ conf->outputs[i] ] = conf->match_values[i];
+               /* Mark channel as active */
+               active_chans |= LPC_PWM_CHANNEL_ENABLE(conf->outputs[i]);
+       }
+
+       /* Setup period */
+       timer->regs->match_reg[ conf->period_chan ] = conf->period;
+       /* Setup selected channel as PWM cycle length control */
+       timer->regs->match_ctrl &= ~(LPC_TIMER_MATCH_ERASE(conf->period_chan));
+       timer->regs->match_ctrl |= (LPC_TIMER_RESET_ON_MATCH << LPC_TIMER_MATCH_SHIFT(conf->period_chan));
+       active_chans |= LPC_PWM_CHANNEL_ENABLE(conf->period_chan);
+
+       /* Setup count mode as timer */
+       timer->regs->count_ctrl = LPC_COUNTER_IS_TIMER;
+
+       /* Activate selected PWM channels and period channel */
+       timer->regs->pwm_ctrl = active_chans;
+
+       return 0; /* Config OK */
+}
+
+
+/* Timer Setup in timer or counter mode, with optionnal capture and match configuration
+ * Takes a timer number and a timer counter config structure as arguments.
+ * Returns 0 on success
+ */
+int countertimer_tc_setup(uint8_t timer_num, const struct lpc_tc_config* conf)
+{
+       struct countertimer_device* timer = &(countertimers[timer_num]);
+       int i = 0;
+
+       if (conf->mode & LPC_TIMER_MODE_SPECIFIC) {
+               return -EINVAL;
+       }
+       /* Erase existing configuration */
+       timer->regs->capture_ctrl = 0;
+       timer->regs->match_ctrl = 0;
+       timer->regs->external_match = 0;
+
+       /* Override the prescaler value if requested */
+       if (conf->prescale_val != 0) {
+               timer->regs->prescale = conf->prescale_val;
+       }
+       /* Select between timer (counts on PCLK) and counter mode (counts on CAP events) */
+       if (conf->mode & LPC_TIMER_MODE_COUNTER) {
+               /* Configure the counter */
+               timer->regs->count_ctrl = (conf->count_control & 0x0F);
+               timer->regs->count_ctrl |= LPC_COUNTER_INC_INPUT(conf->count_chan);
+       } else {
+               /* Timer mode */
+               timer->regs->count_ctrl = LPC_COUNTER_IS_TIMER;
+       }
+
+       /* Configure the reset on capture functionality when selected */
+       if (conf->reset_on_cap & LPC_COUNTER_CLEAR_ON_EVENT_EN) {
+               timer->regs->count_ctrl = LPC_COUNTER_CLEAR_ON_EVENT_EN;
+               timer->regs->count_ctrl |= ((conf->reset_on_cap & 0x07) << LPC_COUNTER_CLEAR_ON_EVENT_SHIFT);
+       }
+
+       if (conf->mode & LPC_TIMER_MODE_CAPTURE) {
+               for (i = 0; i < MAX_CHANNELS; i++) {
+                       timer->regs->capture_ctrl |= ((conf->cap_control[i] & 0x07) << LPC_TIMER_CAPTURE_SHIFT(i));
+               }
+       }
+
+       if (conf->mode & LPC_TIMER_MODE_MATCH) {
+               for (i = 0; i < MAX_CHANNELS; i++) {
+                       timer->regs->match_ctrl |= ((conf->match_control[i] & 0x07) << LPC_TIMER_MATCH_SHIFT(i));
+                       timer->regs->match_reg[i] = conf->match[i];
+                       timer->regs->external_match |= ((conf->ext_match_config[i] & 0x03) << LPC_TIMER_EXT_MATCH_SHIFT(i));
+               }
+       }
+
+       /* Ensure that counter input chan has not been configured to reset or stop the timer or as a
+        * capture channel (See remarks in user manual UM10441 page 268 section 14.7.11) when the ct is
+        * configured in counter mode. */
+       if (conf->mode & LPC_TIMER_MODE_COUNTER) {
+               timer->regs->match_ctrl &= ~LPC_TIMER_MATCH_ERASE(conf->count_chan);
+               timer->regs->capture_ctrl &= ~LPC_TIMER_CAPTURE_ERASE(conf->count_chan);
+               timer->regs->external_match &= ~LPC_TIMER_EXT_MATCH_ERASE(conf->count_chan);
+       }
+
+       return 0; /* Config OK */
+}
+
+struct config_operations countertimer_cfg_ops = {
+       .pwm_config = countertimer_pwm_setup,
+       .tc_config = countertimer_tc_setup,
+};
+
+
+
+
+/*******************************************************************************/
+/* Init operations */
+
+/* Power up a timer.
+ * clkrate is the desired timer clock rate. It will be used to divide the main clock
+ *   to get the timer prescaler value.
+ * Set clkrate to 0 to disable the prescaler.
+ */
+int countertimer_on(uint8_t timer_num, uint32_t clkrate, void (*callback)(uint32_t))
+{
+       struct countertimer_device* timer = NULL;
+       uint32_t prescale; /* The clock divider for the counter */
+
+       timer = &(countertimers[timer_num]);
+
+       NVIC_DisableIRQ( timer->irq );
+       /* Power up the timer */
+       subsystem_power(timer->power_bit, 1);
+       /* Reset counter on next PCLK positive edge, and disable counter */
+       timer->regs->timer_ctrl = LPC_TIMER_COUNTER_RESET;
+
+       /* Store the callback, OK even if none given */
+       timer->callback = callback;
+
+       /* Set the prescaler value */
+       if (clkrate == 0) {
+               prescale = 0;
+       } else {
+               prescale = (get_main_clock() / clkrate) - 1;
+       }
+       timer->regs->prescale = prescale;
+
+       NVIC_EnableIRQ( timer->irq );
+       return 0;
+}
+
+/* Removes the main clock from the selected timer block */
+int countertimer_off(uint8_t timer_num)
+{
+       NVIC_DisableIRQ( countertimers[timer_num].irq );
+       subsystem_power(countertimers[timer_num].power_bit, 0);
+       return 0;
+}
+
+struct init_operations countertimer_init_ops = {
+       .timer_on = countertimer_on,
+       .timer_off = countertimer_off,
+};
+
index 5529b7f..b54795f 100644 (file)
 /*                GPIOs and GPIO Interrupts                                    */
 /***************************************************************************** */
 
+/* Driver for GPIO configuration and access (including GPIO interrupts) on the LPC11u3x.
+ * Refer to LPC11u3x documentation (UM10462.pdf) for more information.
+ */
 
-
-#include <stdint.h>
-#include "core/lpc_regs_11u3x.h"
-#include "core/lpc_core_cm0.h"
 #include "core/system.h"
+#include "lib/errno.h"
 #include "core/pio.h"
 #include "drivers/gpio.h"
 
@@ -77,15 +77,16 @@ void config_gpio(const struct pio* gpio, uint32_t mode, uint8_t dir, uint8_t ini
 
 
 #define NB_PIN_INTERRUPTS  8
-static void (*gpio_calbacks[NB_PIN_INTERRUPTS]) (uint32_t);
+static void (*gpio_callbacks[NB_PIN_INTERRUPTS]) (uint32_t) = {0};
 
 
-int set_gpio_callback(void (*callback) (uint32_t), uint8_t irq, const struct pio* gpio, uint8_t sense)
+int set_gpio_callback(void (*callback) (uint32_t), const struct pio* gpio, uint8_t sense)
 {
        struct lpc_gpio* gpio_port = NULL;
-       struct lpc_sys_control* sys_ctrl = LPC_SYS_CONTROL;
+       struct lpc_sys_config* sys_conf = LPC_SYS_CONFIG;
        struct lpc_gpio_pin_edge_interrupt* edge_conf = LPC_GPIO_INT_EDGE;
        struct lpc_gpio_pin_level_interrupt* level_conf = LPC_GPIO_INT_LEVEL;
+       uint8_t irq = 0;
 
        /* Sanity checks */
        if (irq >= NB_PIN_INTERRUPTS) {
@@ -106,14 +107,22 @@ int set_gpio_callback(void (*callback) (uint32_t), uint8_t irq, const struct pio
                        return -EINVAL;
        }
 
+       /* Get the next available interrupt and register the callback if empty slot found. */
+       for (irq = 0; irq < NB_PIN_INTERRUPTS; irq++) {
+               if (gpio_callbacks[irq] == NULL) {
+                       gpio_callbacks[irq] = callback;
+                       break;
+               }
+       }
+       /* If not found, return. */
+       if (irq == NB_PIN_INTERRUPTS) {
+               return -ENODEV;
+       }
+
        /* Configure the pin as interrupt source */
        config_pio(gpio, LPC_IO_DIGITAL);
        gpio_port->data_dir &= ~(1 << gpio->pin); /* Input */
 
-       /* Register the callback */
-       /* FIXME : we should check that there were none registered for the selected pin */
-       gpio_calbacks[irq] = callback;
-
        /* Power the Pin interrupt block */
        subsystem_power(LPC_SYS_ABH_CLK_CTRL_PINT, 1);
        subsystem_power(LPC_SYS_ABH_CLK_CTRL_P0INT, 1);
@@ -151,17 +160,17 @@ int set_gpio_callback(void (*callback) (uint32_t), uint8_t irq, const struct pio
        }
 
        /* Connect the port/pin to the interrupt */
-       sys_ctrl->gpio_int_sel[irq] = ((gpio->pin & 0x1F) | (gpio->port << 5));
+       sys_conf->gpio_int_sel[irq] = ((gpio->pin & 0x1F) | (gpio->port << 5));
 
-       NVIC_EnableIRQ(irq);
-       return 0;
+       NVIC_EnableIRQ(irq + PIN_INT0_IRQ);
+       return irq;
 }
 void remove_gpio_callback(uint8_t irq)
 {
        /* Remove the handler */
-       gpio_calbacks[irq] = NULL;
+       gpio_callbacks[irq] = NULL;
        /* And disable the interrupt */
-       NVIC_DisableIRQ(irq);
+       NVIC_DisableIRQ(irq + PIN_INT0_IRQ);
 }
 
 
@@ -169,12 +178,12 @@ void remove_gpio_callback(uint8_t irq)
 /* Using LPC_GPIO_INT_EDGE is OK for both types of interupts */
 /* Note : For level interrupts, we toggle the active level, which may no be what's th euser wants ... */
 #define DECLARE_PIO_INT_HANDLER(x) \
-       void Pin_Int ## x ## _Handler(void) \
+       void PININT_ ## x ## _Handler(void) \
        { \
                struct lpc_gpio_pin_edge_interrupt* regs = LPC_GPIO_INT_EDGE; \
                regs->status = (0x01 << (x)); \
-               if (gpio_calbacks[(x)] != NULL) { \
-                       gpio_calbacks[(x)]((x)); \
+               if (gpio_callbacks[(x)] != NULL) { \
+                       gpio_callbacks[(x)]((x)); \
                } \
        }
 DECLARE_PIO_INT_HANDLER(0);
@@ -186,10 +195,10 @@ DECLARE_PIO_INT_HANDLER(5);
 DECLARE_PIO_INT_HANDLER(6);
 DECLARE_PIO_INT_HANDLER(7);
 
-void PIO_GRP_0_Handler(void)
+void GPIO_GRPINT_0_Handler(void)
 {
 }
-void PIO_GRP_1_Handler(void)
+void GPIO_GRPINT_1_Handler(void)
 {
 }
 
index 877da65..63b341f 100644 (file)
 /*                      I2C                                                   */
 /**************************************************************************** */
 
-#include <stdint.h>
+/* I2C driver for the I2C bus integrated module of the LPC11u3x
+ * Refer to LPC11u3x documentation (UM10462.pdf) for more information.
+ */
 
-#include "core/lpc_regs_11u3x.h"
-#include "core/lpc_core_cm0.h"
 #include "core/system.h"
-#include "core/pio.h"
 #include "lib/string.h"
+#include "lib/errno.h"
 #include "drivers/i2c.h"
 
 
 /*
  * I2C Bus structure
  *
+ * mode : current configuration mode : I2C_MASTER, I2C_SLAVE or I2C_MONITOR.
  * clock : current i2c clock.
  * state : global state of the i2c engine.
  * master_status : status returned by i2c block as found in "status" register.
@@ -52,6 +53,7 @@
  */
 struct i2c_bus {
        volatile struct lpc_i2c* regs;
+       uint8_t mode;
        volatile uint32_t clock;
        volatile uint32_t state;
        volatile uint32_t master_status;
@@ -70,7 +72,12 @@ struct i2c_bus {
        volatile uint32_t read_index;
 };
 
-static struct i2c_bus mod_i2c;
+static struct i2c_bus i2c_buses[NB_I2C_BUSSES] = {
+       {
+               .regs = (struct lpc_i2c*)LPC_I2C0,
+               .state = I2C_OK,
+       },
+};
 
 
 /* FIXME : Should add a field "what to do on addr NACK" to i2c_bus structure, and use
@@ -86,7 +93,7 @@ static struct i2c_bus mod_i2c;
 void I2C_0_Handler(void)
 {
        uint8_t status;
-       struct i2c_bus* i2c = &mod_i2c;
+       struct i2c_bus* i2c = &(i2c_buses[0]);
 
        i2c->timeout = 0;
 
@@ -230,7 +237,10 @@ void I2C_0_Handler(void)
                        break;
 
                case 0x50: /* Data byte has been received and ACK sent */
-                       i2c->in_buff[i2c->read_index++] = i2c->regs->data;
+                       if (i2c->in_buff != NULL) {
+                               i2c->in_buff[i2c->read_index] = i2c->regs->data;
+                       }
+                       i2c->read_index++;
                        if ((i2c->read_index + 1) < i2c->read_length) {
                                /* assert ACK after data is received, requesting next Data from slave */
                                i2c->regs->ctrl_set = I2C_ASSERT_ACK;
@@ -243,7 +253,10 @@ void I2C_0_Handler(void)
 
                case 0x58: /* Data byte has been received and NACK "sent" */
                        /* This tells the slave it was the last byte. We should be done. */
-                       i2c->in_buff[i2c->read_index++] = i2c->regs->data;
+                       if (i2c->in_buff != NULL) {
+                               i2c->in_buff[i2c->read_index] = i2c->regs->data;
+                       }
+                       i2c->read_index++;
                        /* FIXME : We have two other options : Repeated START or STOP + START,
                         *    but what for ? periodic reads ? */
                        i2c->regs->ctrl_set = I2C_STOP_FLAG;
@@ -265,6 +278,55 @@ void I2C_0_Handler(void)
 /***************************************************************************** */
 /*                        I2C access                                           */
 /***************************************************************************** */
+static int i2c_perform_data_transfer(struct i2c_bus* i2c)
+{
+       int ret = 0;
+
+       /* Start the process */
+       i2c->state = I2C_BUSY;
+       i2c->regs->ctrl_set = I2C_START_FLAG;
+       /* Wait for process completion */
+       do {} while (i2c->state == I2C_BUSY);
+
+       /* Handle returned state (errors or OK) */
+       switch (i2c->state) {
+               case I2C_OK:
+               case I2C_NO_DATA:
+                       /* Return 0 : success */
+                       break;
+               case I2C_NACK:
+                       ret = -EREMOTEIO;
+                       break;
+               case I2C_ARBITRATION_LOST:
+                       ret = -EBUSY;
+                       break;
+               case I2C_BUS_ERROR: /* This one is bad ... */
+               case I2C_ERROR_UNKNOWN:
+               default:
+                       ret = -EIO;
+                       break;
+       }
+
+       return ret;
+}
+
+/* Release Bus
+ * Some devices do not release the Bus at the end of a transaction if they don't receive
+ *   a start condition immediately followed by a stop condition.
+ */
+void i2c_release_bus(uint8_t bus_num)
+{
+       struct i2c_bus* i2c = &(i2c_buses[0]);
+       /* Force device to release the bus :
+        *    send a START followed by a STOP (initiate transmission with nul write_length) */
+       i2c->state = I2C_BUSY;
+       i2c->write_length = 0;
+       i2c->regs->ctrl_set = I2C_START_FLAG;
+       do {} while (i2c->state == I2C_BUSY);
+       i2c->state = I2C_OK;
+}
+
+
 /* Read
  * Performs a non-blocking read on the module's i2c bus.
  *   cmd_buf : buffer containing all control byte to be sent on the i2c bus
@@ -276,79 +338,46 @@ void I2C_0_Handler(void)
  * RETURN VALUE
  *   Upon successfull completion, returns the number of bytes read. On error, returns a negative
  *   integer equivalent to errors from glibc.
- *   -EBADFD : Device not initialized (-77)
- *   -EBUSY : Device or ressource Busy or Arbitration lost (-16)
- *   -EAGAIN : Device already in use (-11)
- *   -EINVAL : Invalid argument (no cmd_buf, or no inbuff when count > 0) (-22)
- *   -EREMOTEIO : Device did not acknowledge (-121)
- *   -EIO : Bad one: Illegal start or stop, or illegal state in i2c state machine (-5)
  */
-int i2c_read(const void *cmd_buf, size_t cmd_size, const void* ctrl_buf, void* inbuff, size_t count)
+int i2c_read(uint8_t bus_num, const void *cmd_buf, size_t cmd_size, const void* ctrl_buf, void* inbuff, size_t count)
 {
+       struct i2c_bus* i2c = &(i2c_buses[0]);
        int ret = 0;
 
        /* Checks */
-       if (mod_i2c.regs != LPC_I2C0)
+       if (i2c->regs != LPC_I2C0)
                return -EBADFD;
        if (cmd_buf == NULL)
                return -EINVAL;
        if ((inbuff == NULL) && (count > 0))
                return -EINVAL;
 
-       if (mod_i2c.state == I2C_BUSY) {
+       if (i2c->state == I2C_BUSY) {
                return -EBUSY;
        }
-       if (mod_i2c.state != I2C_OK) {
+       if (i2c->state != I2C_OK) {
                /* What should we do ??? someone failed to reset status ? */
        }
 
-       /* Set up mod_i2c for read operation */
+       /* Set up i2c structure for read operation */
        /* command (write) buffer */
-       mod_i2c.out_buff = cmd_buf;
-       mod_i2c.write_length = cmd_size;
+       i2c->out_buff = cmd_buf;
+       i2c->write_length = cmd_size;
        /* control buffer, if any. Note that it's the only way to control
         *   operations on modules i2C bus to simplify the interface */
-       mod_i2c.repeated_start_restart = ctrl_buf;
-       mod_i2c.restart_after_addr = I2C_CONT;
-       mod_i2c.restart_after_data = 0;
+       i2c->repeated_start_restart = ctrl_buf;
+       i2c->restart_after_addr = I2C_CONT;
+       i2c->restart_after_data = 0;
        /* read buffer */
-       mod_i2c.in_buff = inbuff;
-       mod_i2c.read_length = count;
-       mod_i2c.read_index = 0;
-
-       /* Start the process */
-       mod_i2c.state = I2C_BUSY;
-       mod_i2c.regs->ctrl_set = I2C_START_FLAG;
-       /* And wait for process completion */
-       do {} while (mod_i2c.state == I2C_BUSY);
+       i2c->in_buff = inbuff;
+       i2c->read_length = count;
+       i2c->read_index = 0;
 
-       /* Handle returned state (errors or OK) */
-       switch (mod_i2c.state) {
-               case I2C_OK:
-               case I2C_NO_DATA:
-                       ret = mod_i2c.read_index;
-                       break;
-               case I2C_NACK:
-                       ret = -EREMOTEIO;
-                       break;
-               case I2C_ARBITRATION_LOST:
-                       ret = -EBUSY;
-                       break;
-               case I2C_BUS_ERROR: /* This one is bad ... */
-               case I2C_ERROR_UNKNOWN:
-               default:
-                       ret = -EIO;
-                       break;
+       ret = i2c_perform_data_transfer(i2c);
+       if (ret == 0) {
+               return i2c->read_index;
        }
 
-       /* Force device to release the bus :
-        *    send a START followed by a STOP (initiate transmission with nul write_length) */
-       mod_i2c.state = I2C_BUSY;
-       mod_i2c.write_length = 0;
-       mod_i2c.regs->ctrl_set = I2C_START_FLAG;
-       do {} while (mod_i2c.state == I2C_BUSY);
-       mod_i2c.state = I2C_OK;
-
        return ret;
 }
 
@@ -363,76 +392,43 @@ int i2c_read(const void *cmd_buf, size_t cmd_size, const void* ctrl_buf, void* i
  * RETURN VALUE
  *   Upon successfull completion, returns the number of bytes written. On error, returns a negative
  *   integer equivalent to errors from glibc.
- *   -EBADFD : Device not initialized
- *   -EBUSY : Device or ressource Busy or Arbitration lost
- *   -EAGAIN : Device already in use
- *   -EINVAL : Invalid argument (buf)
- *   -EREMOTEIO : Device did not acknowledge
- *   -EIO : Bad one: Illegal start or stop, or illegal state in i2c state machine
  */
-int i2c_write(const void *buf, size_t count, const void* ctrl_buf)
+int i2c_write(uint8_t bus_num, const void *buf, size_t count, const void* ctrl_buf)
 {
+       struct i2c_bus* i2c = &(i2c_buses[0]);
        int ret = 0;
 
        /* Checks */
-       if (mod_i2c.regs != LPC_I2C0)
+       if (i2c->regs != LPC_I2C0)
                return -EBADFD;
        if (buf == NULL)
                return -EINVAL;
 
-       if (mod_i2c.state == I2C_BUSY) {
+       if (i2c->state == I2C_BUSY) {
                return -EBUSY;
        }
-       if (mod_i2c.state != I2C_OK) {
+       if (i2c->state != I2C_OK) {
                /* What should we do ??? someone failed to reset status ? */
        }
 
        /* Clear read information to prevent entering master receiver states */
-       mod_i2c.read_length = 0;
-       mod_i2c.in_buff = NULL;
-       mod_i2c.state = I2C_BUSY;
-       /* Set up mod_i2c for write operation */
-       mod_i2c.out_buff = buf;
-       mod_i2c.write_length = count;
+       i2c->read_length = 0;
+       i2c->in_buff = NULL;
+       i2c->state = I2C_BUSY;
+       /* Set up i2c_bus structure for write operation */
+       i2c->out_buff = buf;
+       i2c->write_length = count;
        /* control buffer, if any. Note that it's the only way to control
         *   operations on modules i2C bus to simplify the interface */
-       mod_i2c.restart_after_addr = I2C_CONT;
-       mod_i2c.repeated_start_restart = ctrl_buf;
-       mod_i2c.restart_after_data = 0;
+       i2c->restart_after_addr = I2C_CONT;
+       i2c->repeated_start_restart = ctrl_buf;
+       i2c->restart_after_data = 0;
 
-       /* Start the process */
-       mod_i2c.state = I2C_BUSY;
-       mod_i2c.regs->ctrl_set = I2C_START_FLAG;
-       /* Wait for process completion */
-       do {} while (mod_i2c.state == I2C_BUSY);
-
-       /* Handle returned state (errors or OK) */
-       switch (mod_i2c.state) {
-               case I2C_OK:
-               case I2C_NO_DATA:
-                       ret = mod_i2c.write_length;
-                       break;
-               case I2C_NACK:
-                       ret = -EREMOTEIO;
-                       break;
-               case I2C_ARBITRATION_LOST:
-                       ret = -EBUSY;
-                       break;
-               case I2C_BUS_ERROR: /* This one is bad ... */
-               case I2C_ERROR_UNKNOWN:
-               default:
-                       ret = -EIO;
-                       break;
+       ret = i2c_perform_data_transfer(i2c);
+       if (ret == 0) {
+               return i2c->write_length;
        }
 
-       /* Force device to release the bus :
-        *    send a START followed by a STOP (initiate transmission with nul write_length) */
-       mod_i2c.state = I2C_BUSY;
-       mod_i2c.write_length = 0;
-       mod_i2c.regs->ctrl_set = I2C_START_FLAG;
-       do {} while (mod_i2c.state == I2C_BUSY);
-       mod_i2c.state = I2C_OK;
-
        return ret;
 }
 
@@ -453,40 +449,47 @@ static void i2c_clock_on(uint32_t i2c_clk_freq)
        i2c->clk_duty_low = (scl_clk - i2c->clk_duty_high);
 }
 
-void i2c_on(uint32_t i2c_clk_freq)
+/* I2C on / off
+ *   bus_num : I2C bus number to use. Ignored on this micro-controller which has only one I2C bus.
+ *   i2c_clk_freq : I2C clock freqeuncy in Hz
+ *   mode is one of I2C_MASTER, I2C_SLAVE or I2C_MONITOR.
+ *   Note that only I2C_MASTER is currently supported.
+ */
+int i2c_on(uint8_t bus_num, uint32_t i2c_clk_freq, uint8_t mode)
 {
-       struct lpc_i2c* i2c = LPC_I2C0;
+       struct i2c_bus* i2c = &(i2c_buses[0]);
 
        NVIC_DisableIRQ(I2C0_IRQ);
        /* Power on I2C 0 block */
        subsystem_power(LPC_SYS_ABH_CLK_CTRL_I2C, 1);
        /* Set clock */
        i2c_clock_on(i2c_clk_freq);
-       mod_i2c.clock = i2c_clk_freq;
-       /* Initialize i2c_bus struct */
-       memset(&mod_i2c, 0, sizeof(struct i2c_bus));
-       mod_i2c.regs = (struct lpc_i2c*)LPC_I2C0;
-       mod_i2c.state = I2C_OK;
+       i2c->clock = i2c_clk_freq;
        /* Enable I2C */
        /* FIXME: if enabling slave functions, add I2C_ASSERT_ACK flag */
-       i2c->ctrl_set = (I2C_ENABLE_FLAG);
+       i2c->regs->ctrl_set = (I2C_ENABLE_FLAG);
        /* And enable interrupts */
        NVIC_EnableIRQ(I2C0_IRQ);
+
+       return 0;
 }
 
-void i2c_off(void)
+int i2c_off(uint8_t bus_num)
 {
+       struct i2c_bus* i2c = &(i2c_buses[0]);
        NVIC_DisableIRQ(I2C0_IRQ);
        subsystem_power(LPC_SYS_ABH_CLK_CTRL_I2C, 0);
-       mod_i2c.clock = 0;
+       i2c->clock = 0;
+       return 0;
 }
 
 /* Allow system to propagate main clock */
 void i2c_clock_update(void)
 {
-       if (mod_i2c.clock) {
+       struct i2c_bus* i2c = &(i2c_buses[0]);
+       if (i2c->clock) {
                /* FIXME : we should stop I2C transfers, disable I2C interrupts and stop I1C clock. */
-               i2c_clock_on(mod_i2c.clock); /* 6 is not a module num, nor system i2c (5) */
+               i2c_clock_on(i2c->clock); /* 6 is not a module num, nor system i2c (5) */
        }
 }
 
index 81b2d2c..1272058 100644 (file)
 /***************************************************************************** */
 /*                UARTs                                                        */
 /***************************************************************************** */
-/* Both UARTs are available, UART numbers are in the range 0 - 1 */
+/* UART driver for the integrated USART of the LPC11u3x
+ * Refer to LPC11u3x documentation (UM10462.pdf) for more information.
+ */
 
-#include <stdint.h>
-#include "core/lpc_regs_11u3x.h"
-#include "core/lpc_core_cm0.h"
 #include "core/system.h"
 #include "core/pio.h"
 #include "lib/string.h"
 #include "lib/utils.h"
+#include "lib/errno.h"
 #include "drivers/serial.h"
 
 struct uart_device
@@ -133,14 +133,31 @@ static void uart_start_sending(uint32_t uart_num)
 }
 
 
+/****************************************************************************** */
+/*    Serial send byte - quick function with almost no tests.
+ * If the uart is not sending, the byte is placed directly in the data buffer and
+ * the call returns 0.
+ * Else, the call returns -EBUSY and nothing is sent.
+ */
+int serial_send_quickbyte(uint32_t uart_num, uint8_t data)
+{
+       struct uart_device* uart = &uarts[uart_num];
+       if (!uart->sending) {
+               uart->regs->func.buffer = data;
+               return 0;
+       } else {
+               return -EBUSY;
+       }
+}
 
 /***************************************************************************** */
 /*    Serial Write
  *
  * Try to send at most "length" characters from "buf" on the requested uart.
- * Returns -1 on error, or number of characters copied into output buffer, witch
- * may be less than requested "length"
- * Possible errors: requested uart does not exists or unable to acquire uart lock.
+ * Returns a negative value on error, or number of characters copied into output buffer,
+ * witch may be less than requested "length"
+ * Possible errors: requested uart does not exists (-EINVAL) or unable to acquire uart
+ * lock (-EBUSY).
  *
  * Warning for Real Time : This implementation will block if there's already a
  * transmission ongoing.
@@ -150,18 +167,19 @@ int serial_write(uint32_t uart_num, const char *buf, uint32_t length)
        struct uart_device* uart = NULL;
 
        if (uart_num >= NUM_UARTS)
-               return -1;
+               return -EINVAL;
 
        uart = &uarts[uart_num];
        /* Lock acquire */
        if (sync_lock_test_and_set(&uart->out_lock, 1) == 1) {
-               return -1;
+               return -EBUSY;
        }
 
        /* If UART is sending wait for buffer empty */
        /* FIXME : be smart for OS, call scheduler or return */
        while (uart->sending != 0) {
-               if (get_priority_mask() == 0) {
+               /* If interrupt are masked, check for tx ourselves */
+               if (get_priority_mask() != 0) {
                        uart_check_tx(uart, uart->regs->func.intr_pending);
                }
        }
@@ -183,10 +201,10 @@ int serial_write(uint32_t uart_num, const char *buf, uint32_t length)
 
 
 /***************************************************************************** */
-/*     Serial Flush
+/*    Serial Flush
  *
  * Wait until all characters have been sent
- * Returns -1 on error, 0 on success.
+ * Returns -EINVAL on error, 0 on success.
  * Possible errors: requested uart does not exists or unable to acquire uart lock.
  *
  * Warning for Real Time : This implementation will block if there's already a
@@ -197,15 +215,15 @@ int serial_flush(uint32_t uart_num)
        struct uart_device* uart = NULL;
 
        if (uart_num >= NUM_UARTS)
-          return -1;
+          return -EINVAL;
 
        uart = &uarts[uart_num];
 
        /* Active wait for message to be sent. If interrupts are
-       * disabled, call the UART handler while waiting. */
+        * disabled, call the UART handler while waiting. */
        while (uart->sending) {
-          if (get_priority_mask() == 0) {
-                  uart_check_tx(uart, uart->regs->func.intr_pending);
+               if (get_priority_mask() != 0) {
+                       uart_check_tx(uart, uart->regs->func.intr_pending);
                }
        }
 
@@ -235,14 +253,14 @@ static struct uart_clk_cfg uart_clk_table[] = {
  */
 static void uart_clk_on(uint32_t uart_num, uint32_t baudrate)
 {
-       struct lpc_sys_control* sys_ctrl = LPC_SYS_CONTROL;
+       struct lpc_sys_config* sys_config = LPC_SYS_CONFIG;
        struct lpc_uart* uart = uarts[uart_num].regs; /* Get the right registers */
        uint32_t div = 0, pclk = 0;
        /* Save baudrate value */
        uarts[uart_num].baudrate = baudrate;
        /* Configure UART clock */
        pclk = get_main_clock(); /* See above note */
-       sys_ctrl->uart_clk_div = 0x01;
+       sys_config->uart_clk_div = 0x01;
        /* The easy one : divider is an integer, or baudrate is low enought for the aproximation */
        if ((baudrate <= 115200) || ((div * baudrate * 16) == pclk)) {
                div = (pclk / (baudrate * 16));
@@ -273,10 +291,10 @@ static void uart_clk_on(uint32_t uart_num, uint32_t baudrate)
 }
 static void uart_clk_off(uint32_t uart_num)
 {
-       struct lpc_sys_control* sys_ctrl = LPC_SYS_CONTROL;
+       struct lpc_sys_config* sys_config = LPC_SYS_CONFIG;
        /* Erase saved baudrate */
        uarts[uart_num].baudrate = 0;
-       sys_ctrl->uart_clk_div = 0;
+       sys_config->uart_clk_div = 0;
 }
 
 static uint32_t uart_setup(uint32_t uart_num)
@@ -284,9 +302,9 @@ static uint32_t uart_setup(uint32_t uart_num)
        struct lpc_uart* uart = uarts[uart_num].regs; /* Get the right registers */
        uint32_t status = 0;
        /* Set up UART mode */
-       uart->line_ctrl = uarts[uart_num].config;;
+       uart->line_ctrl = uarts[uart_num].config;
        /* Clear all fifo, reset and enable them */
-       /* Note : fifo trigger level is one bit */
+       /* Note : fifo trigger level is one byte */
        uart->ctrl.fifo_ctrl = (LPC_UART_FIFO_EN | LPC_UART_TX_CLR | LPC_UART_RX_CLR);
        /* Clear the Line Status Register, return it to prevent compiler from removing the read */
        status = uart->line_status;
@@ -296,6 +314,21 @@ static uint32_t uart_setup(uint32_t uart_num)
        return status;
 }
 
+/* Change UART configuration (number of data, parity and stop bits).
+ * config is a mask of LPC_UART_xBIT (x = 5..8), LPC_UART_xSTOP (x = 1..2)
+ *   and one of LPC_UART_NO_PAR, LPC_UART_ODD_PAR or LPC_UART_EVEN_PAR.
+ */
+int uart_set_config(uint8_t uart_num, uint32_t config)
+{
+       struct uart_device* uart = NULL;
+
+       if (uart_num >= NUM_UARTS)
+               return -EINVAL;
+       uart = &uarts[uart_num];
+       uart->config = config;
+       return 0;
+}
+
 struct uart_def
 {
        uint32_t irq;
@@ -391,9 +424,6 @@ int uart_on(uint32_t uart_num, uint32_t baudrate, void (*rx_callback)(uint8_t))
        uarts[uart_num].rx_callback = rx_callback;
 
        NVIC_DisableIRQ( uart->irq );
-       /* Setup pins, must be done before clock setup and with uart powered off. */
-       uart_clk_off(uart_num);
-       subsystem_power(uart->power_offset, 0);
        /* Turn On power */
        subsystem_power(uart->power_offset, 1);
        /* Setup clock acording to baudrate */
index 7cdec75..bd77a3b 100644 (file)
 /*                SSP                                                          */
 /***************************************************************************** */
 
-#include <stdint.h>
-#include "core/lpc_regs_11u3x.h"
-#include "core/lpc_core_cm0.h"
+/* SSP/SPI driver for the SSP bus integrated module of the LPC11u3x
+ * Refer to LPC11u3x documentation (UM10462.pdf) for more information.
+ */
+
 #include "core/system.h"
 #include "core/pio.h"
+#include "lib/errno.h"
 #include "lib/string.h"
 #include "drivers/ssp.h"
 
@@ -278,7 +280,7 @@ int spi_transfer_multiple_frames(uint8_t ssp_num, void* data_out, void* data_in,
 /***************************************************************************** */
 uint32_t ssp_clk_on(uint8_t ssp_num, uint32_t rate)
 {
-       struct lpc_sys_control* sys_ctrl = LPC_SYS_CONTROL;
+       struct lpc_sys_config* sys_config = LPC_SYS_CONFIG;
        struct lpc_ssp* ssp_regs = ssps[ssp_num].regs;
        uint32_t prescale = 0, pclk_div = 0;
        uint32_t pclk = 0, div = 0;
@@ -309,10 +311,10 @@ uint32_t ssp_clk_on(uint8_t ssp_num, uint32_t rate)
        /* Activate the SSP clock (maybe divide main clock) */
        switch (ssp_num) {
                case 0:
-                       sys_ctrl->ssp0_clk_div = pclk_div;
+                       sys_config->ssp0_clk_div = pclk_div;
                        break;
                case 1:
-                       sys_ctrl->ssp1_clk_div = pclk_div;
+                       sys_config->ssp1_clk_div = pclk_div;
                        break;
        }
 
index 11a079d..8ebd2f8 100644 (file)
@@ -1,7 +1,7 @@
 /****************************************************************************
  *  drivers/timers.c
  *
- * Copyright 2012 Nathael Pajani <nathael.pajani@ed3l.fr>
+ * Copyright 2016 Nathael Pajani <nathael.pajani@ed3l.fr>
  *
  * 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
 /*                Timers                                                       */
 /***************************************************************************** */
 
-#include <stdint.h>
-#include "core/lpc_regs_11u3x.h"
-#include "core/lpc_core_cm0.h"
-#include "core/system.h"
-#include "core/pio.h"
-#include "lib/string.h"
+/* Driver for the different kinds of timers available in the LPC11u3x
+ *
+ * This inludes :
+ * - 32 bits Timers driver
+ *   The LPC11u3x has two 32 bits Timer.
+ * - 16 bits Timers driver
+ *   The LPC11u3x has two 16 bits Timer.
+ *
+ * Refer to LPC11u3x documentation (UM10441.pdf) for more information.
+ *
+ * All common functions are available using a common interface. Only specific
+ * functions have a specific interface, described in separate headers files.
+ */
+
+
+#include "lib/stdint.h"
+#include "lib/errno.h"
 #include "drivers/timers.h"
 
 
 /* These are local to our file */
-struct timer_device
-{
-       struct lpc_timer* regs;
-       uint32_t power_bit;
-       uint32_t irq;
-       void (*callback)(uint32_t); /* Possible RX callback */
+struct timer_device {
+       uint8_t num;
+       struct common_operations* ops;
+       struct config_operations* cfg_ops;
+       struct init_operations* init_ops;
 };
-static struct timer_device timer_devices[NUM_TIMERS] = {
-       { LPC_TMR16B0, LPC_SYS_ABH_CLK_CTRL_CT16B0, TIMER0_IRQ },
-       { LPC_TMR16B1, LPC_SYS_ABH_CLK_CTRL_CT16B1, TIMER1_IRQ },
-       { LPC_TMR32B0, LPC_SYS_ABH_CLK_CTRL_CT32B0, TIMER2_IRQ },
-       { LPC_TMR32B1, LPC_SYS_ABH_CLK_CTRL_CT32B1, TIMER3_IRQ },
-};
-
 
 
-/* Handlers */
-void TIMER_Handler(struct timer_device* timer)
-{
-       uint32_t intr_flags = timer->regs->int_reg; /* Backup the flags */
+/* 32 bits and 16 bits Counter Timers */
+extern struct common_operations countertimer_ops;
+extern struct config_operations countertimer_cfg_ops;
+extern struct init_operations countertimer_init_ops;
+
+
+struct timer_device timers[NUM_TIMERS] = {
+       {
+               .num = LPC_TIMER_16B0,
+               .ops = &countertimer_ops,
+               .cfg_ops = &countertimer_cfg_ops,
+               .init_ops = &countertimer_init_ops,
+       },
+       {
+               .num = LPC_TIMER_16B1,
+               .ops = &countertimer_ops,
+               .cfg_ops = &countertimer_cfg_ops,
+               .init_ops = &countertimer_init_ops,
+       },
+       {
+               .num = LPC_TIMER_32B0,
+               .ops = &countertimer_ops,
+               .cfg_ops = &countertimer_cfg_ops,
+               .init_ops = &countertimer_init_ops,
+       },
+       {
+               .num = LPC_TIMER_32B1,
+               .ops = &countertimer_ops,
+               .cfg_ops = &countertimer_cfg_ops,
+               .init_ops = &countertimer_init_ops,
+       },
+};
 
-       /* Clear the interrupt */
-       timer->regs->int_reg = intr_flags;
-       /* And call the user routine if one has been registered */
-       if (timer->callback != NULL) {
-               timer->callback(intr_flags);
-       }
-}
-void TIMER_0_Handler(void)
-{
-       TIMER_Handler(&timer_devices[0]);
-}
-void TIMER_1_Handler(void)
-{
-       TIMER_Handler(&timer_devices[1]);
-}
-void TIMER_2_Handler(void)
-{
-       TIMER_Handler(&timer_devices[2]);
-}
-void TIMER_3_Handler(void)
-{
-       TIMER_Handler(&timer_devices[3]);
-}
 
+/*******************************************************************************/
+/* Wrappers to common functions */
 
+#define GENERIC_TIMER_OPS(name) \
+       void timer_ ## name(uint8_t timer_num) \
+       { \
+               if (timer_num >= NUM_TIMERS) \
+                       return; \
+               if (timers[timer_num].ops && timers[timer_num].ops->name) { \
+                       timers[timer_num].ops->name(timer_num); \
+               } \
+       }
 
-/* Start the timer :
- * Remove the reset flag if present and set timer enable flag.
- * Timer must be turned on and configured (no checks done here).
+/* Start a timer */
+GENERIC_TIMER_OPS(start);
+/* Pause timer operation */
+GENERIC_TIMER_OPS(pause);
+/* Continue timer operation when the timer got paused */
+GENERIC_TIMER_OPS(cont);
+/* Reset the timer and let it count again imediately */
+GENERIC_TIMER_OPS(restart);
+/* Stop timer counting and reset timer counter to reload value / initial state */
+GENERIC_TIMER_OPS(stop);
+/* Same as stop */
+GENERIC_TIMER_OPS(halt);
+
+
+/* Get the current counter value
+ * Return 0 if the value is valid.
  */
-void timer_start(uint32_t timer_num)
-{
-       if (timer_num >= NUM_TIMERS)
-               return;
-       /* Remove reset flag and set timer enable flag */
-       timer_devices[timer_num].regs->timer_ctrl = LPC_TIMER_COUNTER_ENABLE;
-}
-void timer_continue(uint32_t timer_num) __attribute__ ((alias ("timer_start")));
-/* Pause the timer counter, does not reset */
-void timer_pause(uint32_t timer_num)
-{
-       if (timer_num >= NUM_TIMERS)
-               return;
-       /* Remove timer enable flag */
-       timer_devices[timer_num].regs->timer_ctrl = 0;
-}
-/* Stops and resets the timer counter */
-void timer_stop(uint32_t timer_num)
+int timer_get_counter_val(uint8_t timer_num, uint32_t* val)
 {
        if (timer_num >= NUM_TIMERS)
-               return;
-       /* Remove timer enable flag and request reset */
-       timer_devices[timer_num].regs->timer_ctrl = LPC_TIMER_COUNTER_RESET;
-       /* Remove reset flag */
-       timer_devices[timer_num].regs->timer_ctrl = 0;
-}
-/* Resets the timer and lets it count again imediately */
-void timer_restart(uint32_t timer_num)
-{
-       if (timer_num >= NUM_TIMERS)
-               return;
-       /* Set timer reset flag */
-       timer_devices[timer_num].regs->timer_ctrl = LPC_TIMER_COUNTER_RESET;
-       /* Remove reset flag and start counter */
-       timer_devices[timer_num].regs->timer_ctrl = LPC_TIMER_COUNTER_ENABLE;
+               return -EINVAL;
+       if (timers[timer_num].ops && timers[timer_num].ops->get_counter) {
+               return timers[timer_num].ops->get_counter(timer_num, val);
+       }
+       return -ENODEV;
 }
 
-uint32_t timer_get_capture_val(uint32_t timer_num, uint32_t channel)
+
+/* Get the value of the timer when the capture event last triggered
+ * Return 0 if the value is valid.
+ */
+int timer_get_capture_val(uint8_t timer_num, uint8_t channel, uint32_t* val)
 {
        if (timer_num >= NUM_TIMERS)
-               return 0;
-       /* FIXME */
-       return 0;
+               return -EINVAL;
+       if (timers[timer_num].ops && timers[timer_num].ops->get_capture) {
+               return timers[timer_num].ops->get_capture(timer_num, channel, val);
+       }
+       return -ENODEV;
 }
-uint32_t timer_get_counter_val(uint32_t timer_num)
+
+
+/* Change the match value of a single timer channel */
+int timer_set_match(uint8_t timer_num, uint8_t channel, uint32_t val)
 {
        if (timer_num >= NUM_TIMERS)
-               return 0;
-       return timer_devices[timer_num].regs->timer_counter;
+               return -EINVAL;
+       if (timers[timer_num].ops && timers[timer_num].ops->set_match) {
+               return timers[timer_num].ops->set_match(timer_num, channel, val);
+       }
+       return -ENODEV;
 }
 
-/* Change the match value of a single timer channel */
-void timer_set_match(uint32_t timer_num, uint32_t channel, uint32_t val)
+
+/*******************************************************************************/
+/* Configuration */
+
+/* Configure the timer as PWM. Call to timer-specific function */
+int timer_pwm_config(uint8_t timer_num, const struct lpc_timer_pwm_config* conf)
 {
        if (timer_num >= NUM_TIMERS)
-               return;
-       if (channel > 3)
-               return;
-
-       timer_devices[timer_num].regs->match_reg[channel] = val;
+               return -EINVAL;
+       if (timers[timer_num].cfg_ops && timers[timer_num].cfg_ops->pwm_config) {
+               return timers[timer_num].cfg_ops->pwm_config(timer_num, conf);
+       }
+       return -ENODEV;
 }
 
 
-/***************************************************************************** */
-/*   Timer Setup */
-/* Returns 0 on success
- * Takes a timer number and a timer config structure as arguments.
- * Refer to timer config structure for details.
+/* Timer Setup in timer or counter mode, with optionnal capture and match configuration
+ * Takes a timer number and a timer counter config structure as arguments.
+ * Returns 0 on success
  */
-int timer_setup(uint32_t timer_num, const struct timer_config* conf)
+int timer_counter_config(uint8_t timer_num, const struct lpc_tc_config* conf)
 {
-       struct timer_device* timer = NULL;
-       int i = 0;
        if (timer_num >= NUM_TIMERS)
-               return -ENODEV;
-       timer = &(timer_devices[timer_num]);
-
-       /* Configure the reset on capture functionality */
-       if (conf->reset_on_capture != 0x00) {
-               timer->regs->count_ctrl = LPC_COUNTER_CLEAR_ON_EVENT_EN;
-               timer->regs->count_ctrl |= ((conf->reset_on_capture & 0x07) << LPC_COUNTER_CLEAR_ON_EVENT_SHIFT);
+               return -EINVAL;
+       if (timers[timer_num].cfg_ops && timers[timer_num].cfg_ops->tc_config) {
+               return timers[timer_num].cfg_ops->tc_config(timer_num, conf);
        }
-
-       switch (conf->mode) {
-               case LPC_TIMER_MODE_TIMER:
-                       timer->regs->capture_ctrl = 0; /* Timer mode ! */
-                       timer->regs->count_ctrl = LPC_COUNTER_IS_TIMER;
-                       break;
-               case LPC_TIMER_MODE_COUNTER:
-                       if ((conf->config[0] & 0x03) == 0x00) {
-                               return -EINVAL;
-                       }
-                       /* Must set capture chanel N config to 0b000 in capture control register,
-                        * (see remarks in user manual UM10462 page 361 section 16.7.11)
-                        * Use the LPC_COUNTER_INC_INPUT(x) set by the user to do so automatically
-                        */
-                       timer->regs->capture_ctrl &= ~LPC_TIMER_CAPTURE_ERASE(((conf->config[0] >> LPC_COUNTER_INC_INPUT_SHIFT) & 0x03) * 3);
-                       /* Configure the counter */
-                       timer->regs->count_ctrl |= (conf->config[0] & 0x0F);
-                       break;
-               case LPC_TIMER_MODE_CAPTURE:
-                       timer->regs->capture_ctrl = 0;
-                       for (i = 0; i < NUM_CHANS; i++) {
-                               timer->regs->capture_ctrl |= ((conf->config[i] & 0x07) << LPC_TIMER_CAPTURE_SHIFT(i));
-                       }
-                       break;
-               case LPC_TIMER_MODE_MATCH:
-                       timer->regs->match_ctrl = 0;
-                       timer->regs->external_match = 0;
-                       for (i = 0; i < NUM_CHANS; i++) {
-                               timer->regs->match_ctrl |= ((conf->config[i] & 0x07) << LPC_TIMER_MATCH_SHIFT(i));
-                               timer->regs->match_reg[i] = conf->match[i];
-                               timer->regs->external_match |= ((conf->ext_match_config[i] & 0x03) << (LPC_TIMER_EXT_MATCH0_SHIFT + i*2));
-                       }
-                       break;
-               case LPC_TIMER_MODE_PWM:
-                       if (conf->match[ conf->config[1] ] == 0) {
-                               return -EINVAL; /* Force use of Channel 3 for PWM cycle length */
-                       }
-                       /* Activate selected PWM channels 0 to 2 */
-                       timer->regs->pwm_ctrl = (conf->config[0] & 0x07);
-                       /* Use Channel 3 for PWM cycle length as recommended in the manual */
-                       timer->regs->match_ctrl &= ~(LPC_TIMER_MATCH_ERASE(conf->config[1]));
-                       timer->regs->match_ctrl |= (LPC_TIMER_RESET_ON_MATCH << LPC_TIMER_MATCH_SHIFT(conf->config[1]));
-                       for (i = 0; i < NUM_CHANS; i++) {
-                               timer->regs->match_reg[i] = conf->match[i];
-                       }
-                       break;
-               case LPC_TIMER_MODE_PWD:
-                       break;
-       }
-       return 0; /* Config OK */
+       return -ENODEV;
 }
 
+/*******************************************************************************/
+/* Init operations */
 
 /* Power up a timer.
- * Note that clkrate should be a divider of the main clock frequency chosed
- *   for your application as it will be used to divide the main clock to get
- *   the prescaler value.
- * Set clkrate to 0 to disable the prescaler.
+ * clkrate is the desired timer clock rate. It will be used to divide the main clock
+ *   to get the timer prescaler value.
+ *   Set clkrate to 0 to disable the prescaler.
+ * callback is the interrupt callback for this timer.
  */
-void timer_on(uint32_t timer_num, uint32_t clkrate, void (*callback)(uint32_t))
+int timer_on(uint8_t timer_num, uint32_t clkrate, void (*callback)(uint32_t))
 {
-       struct timer_device* timer = NULL;
-       uint32_t prescale; /* The clock divider for the counter */
-
        if (timer_num >= NUM_TIMERS)
-               return;
-       timer = &(timer_devices[timer_num]);
-
-       NVIC_DisableIRQ( timer->irq );
-       /* Power up the timer */
-       subsystem_power(timer->power_bit, 1);
-       /* Reset counter on next PCLK positive edge, and disable counter */
-       timer->regs->timer_ctrl = LPC_TIMER_COUNTER_RESET;
-
-       /* Store the callback, OK even if none given */
-       timer->callback = callback;
-
-       /* Set the prescaler value */
-       if (clkrate == 0) {
-               prescale = 0;
-       } else {
-               prescale = (get_main_clock() / clkrate) - 1;
+               return -EINVAL;
+       if (timers[timer_num].init_ops && timers[timer_num].init_ops->timer_on) {
+               timers[timer_num].init_ops->timer_on(timer_num, clkrate, callback);
        }
-       timer->regs->prescale = prescale;
-
-       NVIC_EnableIRQ(timer_devices[timer_num].irq);
+       return -ENODEV;
 }
 
 /* Removes the main clock from the selected timer block */
-void timer_off(uint32_t timer_num)
+int timer_off(uint8_t timer_num)
 {
        if (timer_num >= NUM_TIMERS)
-               return;
-       NVIC_DisableIRQ( timer_devices[timer_num].irq );
-       subsystem_power(timer_devices[timer_num].power_bit, 0);
+               return -EINVAL;
+       if (timers[timer_num].init_ops && timers[timer_num].init_ops->timer_off) {
+               return timers[timer_num].init_ops->timer_off(timer_num);
+       }
+       return -ENODEV;
 }
+
diff --git a/drivers/usbcore.c b/drivers/usbcore.c
new file mode 100644 (file)
index 0000000..77c0e9f
--- /dev/null
@@ -0,0 +1,137 @@
+/****************************************************************************
+ *  drivers/usbcore.c
+ *
+ * Copyright 2015 Nathael Pajani <nathael.pajani@ed3l.fr>
+ *
+ * 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 3 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 <http://www.gnu.org/licenses/>.
+ *
+ *************************************************************************** */
+
+
+/***************************************************************************** */
+/*                USB                                                          */
+/***************************************************************************** */
+
+/*
+ * This file holds all the hardware related functions for the USB subsystem
+ */
+
+
+#include "core/system.h"
+#include "core/pio.h"
+#include "lib/string.h"
+#include "drivers/usb.h"
+
+
+
+/***************************************************************************** */
+void usb_init(void)
+{
+/*     struct lpc_usb_device* usb = LPC_USB; */
+}
+
+void disable_usb_irq(void)
+{
+       NVIC_DisableIRQ(USB_IRQ);
+}
+
+void enable_usb_irq(void)
+{
+       NVIC_EnableIRQ(USB_IRQ);
+}
+
+
+/***************************************************************************** */
+/* USB Setup */
+
+/* Configure USB PLL */
+void usb_clk_on(void)
+{
+       struct lpc_sys_config* sys_ctrl = LPC_SYS_CONFIG;
+       /* We have a 12MHz external Oscilator, this makes M=4 and P=2 */
+       uint32_t M = 4;
+       uint32_t N = 1; /* P = 2 ^ N */
+
+       /* Note :  ALL STEPS ARE REQUIRED ! */
+       /* First of all, turn off interrupts, nothing should happen between the two writes of the
+        *  feed sequence (writting of 0xAA and 0x55 to pll1_feed) */
+       lpc_disable_irq();
+
+       /* Power-down USB PLL */
+       sys_ctrl->powerdown_run_cfg |= LPC_POWER_DOWN_USBPLL;
+       /* Configure PLL */
+       sys_ctrl->usb_pll_ctrl = (((M - 1) & 0x1F) | (N << 5));
+       /* Power up external oscilator (if not yep powered) */
+       sys_ctrl->powerdown_run_cfg &= ~(LPC_POWER_DOWN_SYS_OSC);
+       /* Select external xtal oscilator as USB PLL Clock source */
+       sys_ctrl->usb_pll_clk_sel = LPC_USBPLLCLK_SRC_XTAL_OSC;
+       sys_ctrl->usb_pll_clk_upd_en = 0;  /* USBPLLCLKUEN must go from LOW to HIGH */
+       sys_ctrl->usb_pll_clk_upd_en = 1;
+       /* Power-up USB PLL */
+       sys_ctrl->powerdown_run_cfg &= ~LPC_POWER_DOWN_USBPLL;
+
+       /* Wait Until PLL Locked */
+       while (!(sys_ctrl->usb_pll_status & 0x01));
+
+       /* Select USB PLL as Clock source */
+       sys_ctrl->usb_clk_sel = LPC_USBCLK_SRC_USB_PLL_OUT;
+       sys_ctrl->usb_clk_div = 1; /* Divide by 1 */
+       /* Update Clock Source */
+       sys_ctrl->usb_clk_upd_en = 0;  /* USBCLKUEN must go from LOW to HIGH */
+       sys_ctrl->usb_clk_upd_en = 1;
+
+       /* Turn interrupts on once again*/
+       lpc_enable_irq();
+}
+
+void usb_clk_off(void)
+{
+       struct lpc_sys_config* sys_ctrl = LPC_SYS_CONFIG;
+       sys_ctrl->powerdown_run_cfg |= LPC_POWER_DOWN_USB; /* Power-down USB PHY */
+       sys_ctrl->powerdown_run_cfg |= LPC_POWER_DOWN_USBPLL; /* Power-down USB PLL */
+       subsystem_power(LPC_SYS_ABH_CLK_CTRL_USB, 0); /* Disable clock to USB registers */
+       subsystem_power(LPC_SYS_ABH_CLK_CTRL_USBRAM, 0); /* Disable clock to USB RAM */
+}
+
+
+/* Turn on the USB block */
+int usb_on(void)
+{
+       struct lpc_sys_config* sys_ctrl = LPC_SYS_CONFIG;
+
+       NVIC_DisableIRQ(USB_IRQ);
+
+       /* Enable clock to USB registers */
+       subsystem_power(LPC_SYS_ABH_CLK_CTRL_USB, 1);
+       /* Power Up USB memory */
+       sys_ctrl->sys_AHB_clk_ctrl |= LPC_SYS_ABH_CLK_CTRL_MEM_USB;
+       subsystem_power(LPC_SYS_ABH_CLK_CTRL_USBRAM, 1); /* Enable clock to USB RAM */
+       /* Configure USB PLL */
+       usb_clk_on();
+       /* Power-up USB PHY */
+       sys_ctrl->powerdown_run_cfg &= ~LPC_POWER_DOWN_USB;
+
+       NVIC_EnableIRQ(USB_IRQ);
+
+       return 0; /* Config OK */
+}
+
+/* Turn off the USB block */
+void usb_off(void)
+{
+       struct lpc_sys_config* sys_ctrl = LPC_SYS_CONFIG;
+       usb_clk_off();
+       sys_ctrl->powerdown_run_cfg |= LPC_POWER_DOWN_USB; /* Power-off USB PHY */
+}
+
index 968790a..91e2c7d 100644 (file)
  *
  *************************************************************************** */
 
-#include <stdint.h>
-
-#include "core/lpc_regs_11u3x.h"
-#include "core/lpc_core_cm0.h"
 #include "core/system.h"
 #include "core/pio.h"
+#include "lib/errno.h"
 #include "lib/string.h"
 #include "drivers/gpio.h"
 #include "drivers/i2c.h"
 #include "extdrv/eeprom.h"
 
+/* FIXME : All of this will have to be re-written with an eeprom definition structure
+ * This will have the address, bus number, and eeprom type, in order to remove the static
+ *   variables and hardcoded bus number from this code.
+ */
 
 /***************************************************************************** */
 /*          Read and Write for eeprom                                          */
@@ -69,14 +70,14 @@ int eeprom_detect(uint8_t eeprom_addr)
        if (eeprom_addr == EEPROM_ID_SMALL_ADDR_1) {
                cmd_buf[0] = EEPROM_ID_SMALL_ADDR_2;
        }
-       ret = i2c_read(cmd_buf, 1, NULL, NULL, 0);
+       ret = i2c_read(0, cmd_buf, 1, NULL, NULL, 0);
        if (ret == 0) {
                return EEPROM_TYPE_SMALL;
        }
 
        /* No small eeprom ... look for big ones */
        cmd_buf[0] = eeprom_addr;
-       ret = i2c_read(cmd_buf, 1, NULL, NULL, 0);
+       ret = i2c_read(0, cmd_buf, 1, NULL, NULL, 0);
        if (ret == 0) {
                return EEPROM_TYPE_BIG;
        }
@@ -111,13 +112,6 @@ int get_eeprom_type(uint8_t eeprom_addr)
  * RETURN VALUE
  *   Upon successfull completion, returns the number of bytes read. On error, returns a negative
  *   integer equivalent to errors from glibc.
- *   -EFAULT : address above eeprom size
- *   -EBADFD : Device not initialized
- *   -EBUSY : Device or ressource Busy or Arbitration lost
- *   -EAGAIN : Device already in use
- *   -EINVAL : Invalid argument (buf)
- *   -EREMOTEIO : Device did not acknowledge
- *   -EIO : Bad one: Illegal start or stop, or illegal state in i2c state machine
  */
 #define CMD_BUF_SIZE 4
 int eeprom_read(uint8_t eeprom_addr, uint32_t offset, void *buf, size_t count)
@@ -135,14 +129,14 @@ int eeprom_read(uint8_t eeprom_addr, uint32_t offset, void *buf, size_t count)
                        cmd_buf[0] = EEPROM_ID_SMALL_ADDR_1 | ((offset & 0x700) >> 7);
                        cmd_buf[1] = offset & 0xFF;
                        cmd_buf[2] = EEPROM_ID_SMALL_ADDR_1 | 0x01;
-                       ret = i2c_read(cmd_buf, CMD_BUF_SIZE - 1, ctrl_buf + 1, buf, count);
+                       ret = i2c_read(0, cmd_buf, CMD_BUF_SIZE - 1, ctrl_buf + 1, buf, count);
                        break;
                case EEPROM_TYPE_BIG:
                        cmd_buf[0] = eeprom_addr;
                        cmd_buf[1] = ((offset & 0xFF00) >> 8);
                        cmd_buf[2] = offset & 0xFF;
                        cmd_buf[3] = (eeprom_addr | 0x01);
-                       ret = i2c_read(cmd_buf, CMD_BUF_SIZE, ctrl_buf, buf, count);
+                       ret = i2c_read(0, cmd_buf, CMD_BUF_SIZE, ctrl_buf, buf, count);
                        break;
                default:
                        ret = -1;
@@ -159,13 +153,6 @@ int eeprom_read(uint8_t eeprom_addr, uint32_t offset, void *buf, size_t count)
  * RETURN VALUE
  *   Upon successfull completion, returns the number of bytes written. On error, returns a negative
  *   integer equivalent to errors from glibc.
- *   -EFAULT : address above eeprom size
- *   -EBADFD : Device not initialized
- *   -EBUSY : Device or ressource Busy or Arbitration lost
- *   -EAGAIN : Device already in use
- *   -EINVAL : Invalid argument (buf)
- *   -EREMOTEIO : Device did not acknowledge
- *   -EIO : Bad one: Illegal start or stop, or illegal state in i2c state machine
  */
 #define CMD_SIZE_SMALL 2
 #define CMD_SIZE_BIG 3
@@ -220,7 +207,7 @@ int eeprom_write(uint8_t eeprom_addr, uint32_t offset, const void *buf, size_t c
                offset += size;
                memcpy(full_buff, cmd, cmd_size);
                memcpy(full_buff + cmd_size, buf + write_count, size);
-               ret = i2c_write(full_buff, (cmd_size + size), NULL);
+               ret = i2c_write(0, full_buff, (cmd_size + size), NULL);
 
                if (ret != (cmd_size + size)) {
                        break;
@@ -228,7 +215,7 @@ int eeprom_write(uint8_t eeprom_addr, uint32_t offset, const void *buf, size_t c
                /* Wait for page write completion : The device does not acknoledge anything during
                 * page write, perform page writes with no data, until it returns 1 */
                do {
-                       ret = i2c_write(full_buff, 1, NULL);
+                       ret = i2c_write(0, full_buff, 1, NULL);
                } while (ret != 1);
 
                write_count += size;
index f8b983d..1b96e9e 100644 (file)
@@ -23,9 +23,8 @@
 /***************************************************************************** */
 
 
-#include <stdint.h>
-#include "core/lpc_regs_11u3x.h"
 #include "core/system.h"
+#include "core/systick.h"
 #include "core/pio.h"
 #include "drivers/gpio.h"
 #include "extdrv/status_led.h"
@@ -46,17 +45,84 @@ struct pio blue_led = {0, 0, 0};
 #define LED_GREEN  (1 << green_led.pin)
 #define LED_BLUE   (1 << blue_led.pin)
 
-void status_led_config(const struct pio* green, const struct pio* red, const struct pio* blue)
+/* Led blinking delays
+ * Each led will be left "ON" for it's "on_time" counts of the blink_base period, and "OFF" for
+ *   it's "off_time" counts of the blink_base period.
+ * The "on_count" is initialised to the number of cycles (on + off) to give a defined number of
+ *   led blinks
+ */
+
+/* Red led */
+static volatile uint32_t red_on_time = 0;
+static volatile uint32_t red_off_time = 0;
+static volatile uint32_t red_on_count = 0;
+/* Green led */
+static volatile uint32_t green_on_time = 0;
+static volatile uint32_t green_off_time = 0;
+static volatile uint32_t green_on_count = 0;
+/* Blue led */
+static volatile uint32_t blue_on_time = 0;
+static volatile uint32_t blue_off_time = 0;
+static volatile uint32_t blue_on_count = 0;
+
+void leds_blinker(uint32_t tick)
+{
+       struct lpc_gpio* gpio_red = LPC_GPIO_REGS(red_led.port);
+       struct lpc_gpio* gpio_green = LPC_GPIO_REGS(green_led.port);
+       struct lpc_gpio* gpio_blue = LPC_GPIO_REGS(blue_led.port);
+       static uint32_t red_counter = 0;
+       static uint32_t green_counter = 0;
+       static uint32_t blue_counter = 0;
+
+       if (red_on_count) {
+               if (red_counter++ == red_on_time) {
+                       gpio_red->clear = LED_RED;
+                       red_on_count--;
+               } else if (red_counter > red_off_time) {
+                       gpio_red->set = LED_RED;
+                       red_counter = 0;
+               }
+       }
+       if (green_on_count) {
+               if (green_counter++ == green_on_time) {
+                       gpio_green->clear = LED_GREEN;
+                       green_on_count--;
+               } else if (green_counter > green_off_time) {
+                       gpio_green->set = LED_GREEN;
+                       green_counter = 0;
+               }
+       }
+       if (blue_on_count) {
+               if (blue_counter++ == blue_on_time) {
+                       gpio_blue->clear = LED_BLUE;
+                       blue_on_count--;
+               } else if (blue_counter > blue_off_time) {
+                       gpio_blue->set = LED_BLUE;
+                       blue_counter = 0;
+               }
+       }
+}
+
+
+/* Configure the status leds, giving the red, green and blue pio structures and an eventual
+ *  blink "base" period in ms.
+ * Set blink_base to 0 if you do not want blinking activated.
+ */
+void status_led_config(const struct pio* green, const struct pio* red, const struct pio* blue, uint32_t blink_base)
 {
        uint32_t mode = LPC_IO_MODE_PULL_UP | LPC_IO_DRIVE_HIGHCURENT;
        /* Copy status led info */
        pio_copy(&red_led, red);
        pio_copy(&green_led, green);
        pio_copy(&blue_led, blue);
+
        /* Status Leds: all off */
        config_gpio(&green_led, mode, GPIO_DIR_OUT, 1);
        config_gpio(&red_led, mode, GPIO_DIR_OUT, 1);
        config_gpio(&blue_led, mode, GPIO_DIR_OUT, 1);
+
+       /* If blinking is requested, set the systick callback */
+       add_systick_callback(leds_blinker, blink_base);
 }
 
 void status_led(uint32_t val)
@@ -127,9 +193,39 @@ void status_led(uint32_t val)
        }
 }
 
+
+/* Start led blinking */
+void blink_led_red(uint32_t on_time, uint32_t off_time, uint32_t count)
+{
+       red_on_time = on_time;
+       red_off_time = off_time;
+       red_on_count = count;
+}
+void blink_msd_led(uint32_t on_time, uint32_t off_time, uint32_t count) __attribute__ ((alias ("blink_led_red")));
+
+void blink_led_green(uint32_t on_time, uint32_t off_time, uint32_t count)
+{
+       green_on_time = on_time;
+       green_off_time = off_time;
+       green_on_count = count;
+}
+void blink_dap_led(uint32_t on_time, uint32_t off_time, uint32_t count) __attribute__ ((alias ("blink_led_green")));
+
+void blink_led_blue(uint32_t on_time, uint32_t off_time, uint32_t count)
+{
+       blue_on_time = on_time;
+       blue_off_time = off_time;
+       blue_on_count = count;
+}
+void blink_cdc_led(uint32_t on_time, uint32_t off_time, uint32_t count) __attribute__ ((alias ("blink_led_blue")));
+
+
+/* Turn on or off a led
+ * This does stop the blinking of the led if it was configured */
 void gpio_set_dap_led(uint8_t state)
 {
        struct lpc_gpio* gpio_green = LPC_GPIO_REGS(green_led.port);
+       green_on_count = 0;
        if (state) {
                gpio_green->set = LED_GREEN;
        } else {
@@ -140,6 +236,7 @@ void gpio_set_dap_led(uint8_t state)
 void gpio_set_msd_led(uint8_t state)
 {
        struct lpc_gpio* gpio_red = LPC_GPIO_REGS(red_led.port);
+       red_on_count = 0;
        if (state) {
                gpio_red->set = LED_RED;
        } else {
@@ -150,6 +247,7 @@ void gpio_set_msd_led(uint8_t state)
 void gpio_set_cdc_led(uint8_t state)
 {
        struct lpc_gpio* gpio_blue = LPC_GPIO_REGS(blue_led.port);
+       blue_on_count = 0;
        if (state) {
                gpio_blue->set = LED_BLUE;
        } else {
index 5109aec..8677947 100644 (file)
  *
  *************************************************************************** */
 
-#include <stdint.h>
 
-#include "core/lpc_regs_11u3x.h"
-#include "core/lpc_core_cm0.h"
 #include "core/system.h"
+#include "lib/errno.h"
 #include "drivers/i2c.h"
 #include "extdrv/tmp101_temp_sensor.h"
 
@@ -69,7 +67,7 @@ int tmp101_probe_sensor(struct tmp101_sensor_config* conf)
 
        /* Did we already probe the sensor ? */
        if (conf->probe_ok != 1) {
-               conf->probe_ok = i2c_read(&cmd_buf, 1, NULL, NULL, 0);
+               conf->probe_ok = i2c_read(conf->bus_num, &cmd_buf, 1, NULL, NULL, 0);
        }
        return conf->probe_ok;
 }
@@ -90,12 +88,6 @@ int tmp101_convert_to_deci_degrees(uint16_t raw)
  * Return value(s):
  *   Upon successfull completion, returns 0 and the temperature read is placed in the
  *   provided integers. On error, returns a negative integer equivalent to errors from glibc.
- *   -EBADFD : I2C not initialized
- *   -EBUSY : Device or ressource Busy or Arbitration lost
- *   -EINVAL : Invalid argument (buf)
- *   -ENODEV : No such device
- *   -EREMOTEIO : Device did not acknowledge : Any device present ?
- *   -EIO : Bad one: Illegal start or stop, or illegal state in i2c state machine
  */
 #define CMD_BUF_SIZE 3
 int tmp101_sensor_read(struct tmp101_sensor_config* conf, uint16_t* raw, int* deci_degrees)
@@ -112,23 +104,25 @@ int tmp101_sensor_read(struct tmp101_sensor_config* conf, uint16_t* raw, int* de
        /* Read the requested data */
        if (conf->last_accessed_register == TMP_REG_TEMPERATURE) {
                /* No need to switch back to temperature register */
-               ret = i2c_read((cmd_buf + 2), 1, (ctrl_buf + 2), (char*)&temp, 2);
+               ret = i2c_read(conf->bus_num, (cmd_buf + 2), 1, (ctrl_buf + 2), (char*)&temp, 2);
        } else {
                /* Send (write) temperature register address to TMP101 internal pointer */
-               ret = i2c_read(cmd_buf, CMD_BUF_SIZE, ctrl_buf, (char*)&temp, 2);
+               ret = i2c_read(conf->bus_num, cmd_buf, CMD_BUF_SIZE, ctrl_buf, (char*)&temp, 2);
                conf->last_accessed_register = TMP_REG_TEMPERATURE;
        }
 
-       if (ret == 2) {
-               if (raw != NULL) {
-                       *raw = byte_swap_16(temp);
-               }
-               if (deci_degrees != NULL) {
-                       *deci_degrees = tmp101_convert_to_deci_degrees(byte_swap_16(temp));
-               }
-               return 0;
+       if (ret != 2) {
+               conf->probe_ok = 0;
+               return ret;
        }
-       return ret;
+
+       if (raw != NULL) {
+               *raw = byte_swap_16(temp);
+       }
+       if (deci_degrees != NULL) {
+               *deci_degrees = tmp101_convert_to_deci_degrees(byte_swap_16(temp));
+       }
+       return 0;
 }
 
 
@@ -139,12 +133,6 @@ int tmp101_sensor_read(struct tmp101_sensor_config* conf, uint16_t* raw, int* de
  * Return value :
  *   Upon successfull completion, returns 0. On error, returns a negative integer
  *   equivalent to errors from glibc.
- *   -EBADFD : I2C not initialized
- *   -EBUSY : Device or ressource Busy or Arbitration lost
- *   -EINVAL : Invalid argument (buf)
- *   -ENODEV : No such device
- *   -EREMOTEIO : Device did not acknowledge : Any device present ?
- *   -EIO : Bad one: Illegal start or stop, or illegal state in i2c state machine
  */
 #define CONF_BUF_SIZE 4
 int tmp101_sensor_config(struct tmp101_sensor_config* conf)
@@ -160,12 +148,13 @@ int tmp101_sensor_config(struct tmp101_sensor_config* conf)
        conf->actual_config = (TMP_SHUTDOWN_MODE_ON | TMP_THERMOSTAT_INTERRUPT_MODE | TMP_ALERT_POLARITY_HIGH);
        conf->actual_config |= (conf->resolution & (0x03 << 5));
        cmd[2] = conf->actual_config;
-       ret = i2c_write(cmd, 3, NULL);
+       ret = i2c_write(conf->bus_num, cmd, 3, NULL);
        conf->last_accessed_register = TMP_REG_CONFIG;
-       if (ret == 3) {
-               return 0; /* Config success */
+       if (ret != 3) {
+               conf->probe_ok = 0;
+               return ret;
        }
-       return ret;
+       return 0; /* Config success */
 }
 
 /* Start a conversion when the sensor is in shutdown mode. */
@@ -180,12 +169,13 @@ int tmp101_sensor_start_conversion(struct tmp101_sensor_config* conf)
 
        cmd[2] = conf->actual_config;
        cmd[2] |= TMP_ONE_SHOT_TRIGGER;
-       ret = i2c_write(cmd, 3, NULL);
+       ret = i2c_write(conf->bus_num, cmd, 3, NULL);
        conf->last_accessed_register = TMP_REG_CONFIG;
-       if (ret == 3) {
-               return 0; /* Conversion start success */
+       if (ret != 3) {
+               conf->probe_ok = 0;
+               return ret;
        }
-       return ret;
+       return 0; /* Conversion start success */
 }
 
 
index e23d635..d3c9be4 100644 (file)
@@ -1,7 +1,7 @@
 /****************************************************************************
  *   core/iap.h
  *
- *
+ * Copyright 2015 Nathael Pajani <nathael.pajani@ed3l.fr>
  *
  * 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
@@ -21,7 +21,7 @@
 #ifndef CORE_IAP_H
 #define CORE_IAP_H
 
-#include <stdint.h>
+#include "lib/stdint.h"
 
 
 /*******************************************************************************/
 #define LPC11U35_END_FLASH    (LPC11U35_NB_SECTOR * LPC11U35_SECTOR_SIZE)
 
 
-
-
-/*******************************************************************************/
-/* Direct access to IAP function */
-
+/* Return values */
 enum iap_status {
        IAP_STATUS_CMD_SUCCESS = 0,
        IAP_STATUS_INVALID_COMMAND,
@@ -69,6 +65,12 @@ enum iap_status {
        IAP_STATUS_BUSY,
 };
 
+/*******************************************************************************/
+/* Direct access to IAP function */
+
+/* IPA entry call for reinvoque ISP */
+void iap_reinvoke_isp(void);
+
 /* Prepare sectors from the programm flash memory for erasing or writting
  * Sectors numbers start at 0. A flash sector size is 4kB (0x1000 bytes)
  * Provide the same sector number as start and end to prepare a single sector.
@@ -143,5 +145,13 @@ int flash_hal_erase_sector(uint32_t addr);
  */
 int flash_hal_program_page (uint32_t addr, uint32_t sz, unsigned char *buf);
 
+/* Re-invoke ISP ROM routine
+ * This functionnality is part of the IAP interface, and enables running the boot process from
+ *   start once the microcontroller got flashed.
+ * This function is not supposed to return.
+ */
+void reinvoque_isp(void);
+
+
 #endif /* CORE_IAP_H */
 
diff --git a/include/core/lpc_core.h b/include/core/lpc_core.h
new file mode 100644 (file)
index 0000000..e91bba5
--- /dev/null
@@ -0,0 +1,489 @@
+/****************************************************************************
+ *   core/lpc_core.h
+ *
+ * Helper functions to access some registers and Cortex M0 core functionalities.
+ *
+ * Most of the code from here has been adapted from CMSIS.
+ *
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ *************************************************************************** */
+
+#ifndef LPC_CORE_H
+#define LPC_CORE_H
+
+#include "lib/stdint.h"
+#include "core/lpc_regs.h"
+
+
+
+/***************************************************************************** */
+/*                    Cortex-M0 System Control Block                           */
+/***************************************************************************** */
+/* Cortex-M0 System Control Block Registers */
+struct syst_ctrl_block_regs {
+       volatile const uint32_t cpuid; /* 0x000 : CPU ID Base Register (R/ ) */
+       volatile uint32_t icsr;        /* 0x004 : Interrupt Control State Register (R/W) */
+       uint32_t reserved_0;
+       volatile uint32_t aircr;       /* 0x00C : Application Interrupt / Reset Control Register (R/W) */
+       volatile uint32_t scr;         /* 0x010 : System Control Register (R/W) */
+       volatile uint32_t ccr;         /* 0x014 : Configuration Control Register (R/W) */
+       uint32_t reserved_1;
+       volatile uint32_t shp[2];      /* 0x01C : System Handlers Priority Registers. [0] is reserved_ (R/W) */
+};
+#define LPC_SCB       ((struct syst_ctrl_block_regs *) LPC_SCB_BASE) /* SCB configuration struct */
+
+/* SCB CPUID Register Definitions */
+#define SCB_CPUID_IMPLEMENTER      (0xFFUL << 24)     /* SCB CPUID: IMPLEMENTER Mask */
+#define SCB_CPUID_VARIANT          (0xFUL << 20)      /* SCB CPUID: VARIANT Mask */
+#define SCB_CPUID_ARCHITECTURE     (0xFUL << 16)      /* SCB CPUID: ARCHITECTURE Mask */
+#define SCB_CPUID_PARTNO           (0xFFFUL << 4)     /* SCB CPUID: PARTNO Mask */
+#define SCB_CPUID_REVISION         (0xFUL << 0)       /* SCB CPUID: REVISION Mask */
+
+/* SCB Interrupt Control State Register Definitions */
+#define SCB_ICSR_NMIPENDSET        (1UL << 31)        /* SCB ICSR: NMIPENDSET Mask */
+#define SCB_ICSR_PENDSVSET         (1UL << 28)        /* SCB ICSR: PENDSVSET Mask */
+#define SCB_ICSR_PENDSVCLR         (1UL << 27)        /* SCB ICSR: PENDSVCLR Mask */
+#define SCB_ICSR_PENDSTSET         (1UL << 26)        /* SCB ICSR: PENDSTSET Mask */
+#define SCB_ICSR_PENDSTCLR         (1UL << 25)        /* SCB ICSR: PENDSTCLR Mask */
+#define SCB_ICSR_ISRPREEMPT        (1UL << 23)        /* SCB ICSR: ISRPREEMPT Mask */
+#define SCB_ICSR_ISRPENDING        (1UL << 22)        /* SCB ICSR: ISRPENDING Mask */
+#define SCB_ICSR_VECTPENDING       (0x1FFUL << 12)    /* SCB ICSR: VECTPENDING Mask */
+#define SCB_ICSR_VECTACTIVE        (0x1FFUL << 0)     /* SCB ICSR: VECTACTIVE Mask */
+
+/* SCB Application Interrupt and Reset Control Register Definitions */
+#define SCB_AIRCR_VECTKEY_OFFSET   16
+#define SCB_AIRCR_VECTKEY          (0xFFFFUL << 16)   /* SCB AIRCR: VECTKEY Mask */
+#define SCB_AIRCR_VECTKEYSTAT      (0xFFFFUL << 16)   /* SCB AIRCR: VECTKEYSTAT Mask */
+#define SCB_AIRCR_ENDIANESS        (1UL << 15)        /* SCB AIRCR: ENDIANESS Mask */
+#define SCB_AIRCR_SYSRESETREQ      (1UL << 2)         /* SCB AIRCR: SYSRESETREQ Mask */
+#define SCB_AIRCR_VECTCLRACTIVE    (1UL << 1)         /* SCB AIRCR: VECTCLRACTIVE Mask */
+
+/* SCB System Control Register Definitions */
+#define SCB_SCR_SEVONPEND          (1UL << 4)         /* SCB SCR: SEVONPEND Mask */
+#define SCB_SCR_SLEEPDEEP          (1UL << 2)         /* SCB SCR: SLEEPDEEP Mask */
+#define SCB_SCR_SLEEPONEXIT        (1UL << 1)         /* SCB SCR: SLEEPONEXIT Mask */
+
+/* SCB Configuration Control Register Definitions */
+#define SCB_CCR_STKALIGN           (1UL << 9)         /* SCB CCR: STKALIGN Mask */
+#define SCB_CCR_UNALIGN_TRP        (1UL << 3)         /* SCB CCR: UNALIGN_TRP Mask */
+
+
+
+/*******************************************************************************/
+/*                Core Instructions                                            */
+/*******************************************************************************/
+/* NOP */
+#define nop() __asm volatile ("nop" : : : "memory")
+/* SEV : Send Event */
+#define sev() __asm volatile ("sev" : : : "memory")
+/* WFE : Wait For Event */
+#define wfe() __asm volatile ("wfe" : : : "memory")
+/* WFI : Wait For Interrupt */
+#define wfi() __asm volatile ("wfi" : : : "memory")
+
+
+/* Synchronization */
+/* Instruction Synchronization Barrier : Flushes pipeline */
+#define isb() __asm volatile ("isb" : : : "memory")
+/* Data Synchronization Barrier : All explicit memory access completed */
+#define dsb() __asm volatile ("dsb" : : : "memory")
+/* Data Memory Barrier : Ensures apparent order but not completion */
+#define dmb() __asm volatile ("dmb" : : : "memory")
+
+
+
+/* Access to the Application Program Status Register (APSR). */
+static inline uint32_t get_APSR(void)
+{
+       uint32_t r; __asm volatile ("mrs %0, apsr" : "=r" (r)); return (r);
+}
+#define APSR_SATURATION  (get_APSR() & (0x1 << 27))  /* bit 27  Saturation condition flag */
+#define APSR_OVERFLOW    (get_APSR() & (0x1 << 28))  /* bit 28  Overflow condition code flag */
+#define APSR_CARRY       (get_APSR() & (0x1 << 29))  /* bit 29  Carry condition code flag */
+#define APSR_ZERO        (get_APSR() & (0x1 << 30))  /* bit 30  Zero condition code flag */
+#define APSR_NEGATIVE    (get_APSR() & (0x1 << 31))  /* bit 31  Negative condition code flag */
+
+
+/* Access the Interrupt Program Status Register (IPSR). */
+static inline uint32_t get_IPSR(void)
+{
+       uint32_t r; __asm volatile ("mrs %0, ipsr" : "=r" (r)); return (r);
+}
+#define IPSR      (get_IPSR() & 0x1FF)  /* bit:  0..8  Exception number */
+#define IPSR_IRQ0 16
+#define IRQ_NUM   (IPSR - IPSR_IRQ0)
+
+
+/* Control Register */
+static inline uint32_t get_CONTROL(void)
+{
+       uint32_t r; __asm volatile ("mrs %0, control" : "=r" (r)); return (r);
+}
+static inline void set_CONTROL(uint32_t control)
+{
+       __asm volatile ("msr control, %0" : : "r" (control));
+}
+
+
+/* Process Stack Pointer */
+static inline uint32_t get_process_stack_pointer(void)
+{
+       register uint32_t r; __asm volatile ("mrs %0, psp" : "=r" (r)); return (r);
+}
+static inline void set_process_stack_pointer(uint32_t top_of_stack)
+{
+       __asm volatile ("msr psp, %0" : : "r" (top_of_stack));
+}
+
+
+/* Main Stack Pointer */
+static inline uint32_t get_main_stack_pointer(void)
+{
+       register uint32_t r; __asm volatile ("mrs %0, msp" : "=r" (r)); return (r);
+}
+static inline void set_main_stack_pointer(uint32_t top_of_stack)
+{
+       __asm volatile ("msr msp, %0" : : "r" (top_of_stack));
+}
+
+
+/* Priority Mask */
+static inline uint32_t get_priority_mask(void)
+{
+       uint32_t r; __asm volatile ("mrs %0, primask" : "=r" (r)); return (r);
+}
+static inline void set_priority_mask(uint32_t mask)
+{
+       __asm volatile ("msr primask, %0" : : "r" (mask));
+}
+
+
+/* Base Priority */
+static inline uint32_t get_base_priority(void)
+{
+       uint32_t r; __asm volatile ("mrs %0, basepri_max" : "=r" (r)); return (r);
+}
+static inline void set_base_priority(uint32_t prio)
+{
+       __asm volatile ("msr basepri, %0" : : "r" (prio));
+}
+
+
+/* Fault Mask */
+static inline uint32_t get_fault_mask(void)
+{
+       uint32_t r; __asm volatile ("mrs %0, faultmask" : "=r" (r)); return (r);
+}
+static inline void set_fault_mask(uint32_t mask)
+{
+       __asm volatile ("msr faultmask, %0" : : "r" (mask));
+}
+
+
+
+/*******************************************************************************/
+/*            Byte swap instructions                                           */
+/*******************************************************************************/
+/* Swap bytes of each 16-bit halfword in a 32-bit word, keeping halfword order */
+static inline uint32_t double_byte_swap_16(volatile uint32_t value)
+{
+       uint32_t result = 0;
+       __asm volatile ("rev16 %0, %1" : "=l" (result) : "l" (value));
+       return result;
+}
+/* Change endianness of a 16-bit halfword */
+static inline uint32_t byte_swap_16(volatile uint16_t value)
+{
+       uint32_t result = 0;
+       __asm volatile ("rev16 %0, %1" : "=l" (result) : "l" (value));
+       return (result & 0xFFFF);
+}
+/* Change endianness of a 32-bit word */
+static inline uint32_t byte_swap_32(volatile uint32_t value)
+{
+       uint32_t result = 0;
+       __asm volatile ("rev %0, %1" : "=l" (result) : "l" (value));
+       return result;
+}
+
+
+
+
+
+/*******************************************************************************/
+/*            Interrupts                                                       */
+/*******************************************************************************/
+
+/* Cortex-M0 Processor Exceptions Numbers */
+/* Note : entry 0 is "end stack pointer" */
+#define RESET_IRQ       ( -15 ) /*  1 - Reset ... not an interrupt ... */
+#define NMI_IRQ         ( -14 ) /*  2 - Non Maskable Interrupt */
+#define HARD_FAULT_IRQ  ( -13 ) /*  3 - Cortex-M0 Hard Fault Interrupt */
+/* Note : entry 7 is the 2’s complement of the check-sum of the previous 7 entries */
+#define SV_CALL_IRQ     (  -5 ) /* 11 - Cortex-M0 Supervisor Call Interrupt */
+#define PEND_SV_IRQ     (  -2 ) /* 14 - Cortex-M0 Pend SV Interrupt */
+#define SYSTICK_IRQ     (  -1 ) /* 15 - Cortex-M0 System Tick Interrupt */
+/* LPC12xx Specific Interrupt Numbers */
+#define PIN_INT0_IRQ       0   /* I/O pins can be used as wakeup source. */
+#define PIN_INT1_IRQ       1
+#define PIN_INT2_IRQ       2
+#define PIN_INT3_IRQ       3
+#define PIN_INT4_IRQ       4
+#define PIN_INT5_IRQ       5
+#define PIN_INT6_IRQ       6
+#define PIN_INT7_IRQ       7
+#define GRP_INT0_IRQ       8
+#define GRP_INT1_IRQ       9
+#define SSP1_IRQ          14  /* 14 - SSP 1 */
+#define I2C0_IRQ          15  /* 15 - I2C 0 */
+#define TIMER0_IRQ        16  /* 16 - Timer 0 */
+#define TIMER1_IRQ        17  /* 17 - Timer 1 */
+#define TIMER2_IRQ        18  /* 18 - Timer 2 */
+#define TIMER3_IRQ        19  /* 19 - Timer 3 */
+#define SSP0_IRQ          20  /* 20 - SSP 0 */
+#define UART0_IRQ         21  /* 21 - UART 0 */
+#define USB_IRQ           22  /* 22 - USB */
+#define USB_FIQ_IRQ       23  /* 23 - USB FIQ */
+#define ADC_IRQ           24  /* 24 - A/D Converter */
+#define WDT_IRQ           25  /* 25 - Watchdog */
+#define BOD_IRQ           26  /* 26 - Brown Out Detect(BOD) */
+#define FLASH_IRQ         27  /* 27 - Flash / EEPROM */
+#define USB_WAKEUP_IRQ    30  /* 26 - USB Wakeup */
+#define IOH_IRQ           31  /* 27 - I/O Handler */
+
+
+/* Enable IRQ Interrupts
+  Enables IRQ interrupts by clearing the I-bit in the CPSR.
+  Can only be executed in Privileged modes.
+ */
+static inline void lpc_enable_irq(void)
+{
+       __asm volatile ("cpsie i");
+}
+
+/* Disable IRQ Interrupts
+  Disables IRQ interrupts by setting the I-bit in the CPSR.
+  Can only be executed in Privileged modes.
+ */
+static inline void lpc_disable_irq(void)
+{
+       __asm volatile ("cpsid i");
+}
+
+
+/*******************************************************************************/
+/*                Hardware Abstraction Layer : NVIC Functions                  */
+/*******************************************************************************/
+
+/* Cortex-M0 NVIC Registers */
+struct nvic_regs {
+       volatile uint32_t int_set_enable;  /* 0x000 : Interrupt Set Enable Register (R/W) */
+       uint32_t reserved_0[31];
+       volatile uint32_t int_clear_enable;  /* 0x080 : Interrupt Clear Enable Register (R/W) */
+       uint32_t reserved_1[31];
+       volatile uint32_t int_set_pending;  /* 0x100 : Interrupt Set Pending Register (R/W) */
+       uint32_t reserved_2[31];
+       volatile uint32_t int_clear_pending;  /* 0x180 : Interrupt Clear Pending Register (R/W) */
+       uint32_t reserved_3[31];
+       volatile uint32_t int_active_bit; /* 0x200 : Interrupt Active Bit Register (R/-) */
+       uint32_t reserved_4[63];
+       volatile uint32_t int_priority[8]; /* 0x3EC : Interrupt Priority Register (R/W) */
+};
+#define LPC_NVIC      ((struct nvic_regs *) LPC_NVIC_BASE)        /* NVIC configuration struct */
+
+
+/*  Enable External Interrupt
+  This function enables a device specific interrupt in the NVIC interrupt controller.
+  The interrupt number cannot be a negative value.
+  IRQ : Number of the external interrupt to enable
+ */
+static inline void NVIC_EnableIRQ(uint32_t IRQ)
+{
+       struct nvic_regs* nvic = LPC_NVIC;
+       nvic->int_set_enable = (1 << (IRQ & 0x1F));
+}
+
+/*  Disable External Interrupt
+  This function disables a device specific interupt in the NVIC interrupt controller.
+  The interrupt number cannot be a negative value.
+  IRQ : Number of the external interrupt to disable
+ */
+static inline void NVIC_DisableIRQ(uint32_t IRQ)
+{
+       struct nvic_regs* nvic = LPC_NVIC;
+       nvic->int_clear_enable = (1 << (IRQ & 0x1F));
+}
+
+/*  Get Pending Interrupt
+  This function reads the pending register in the NVIC and returns the pending bit
+    for the specified interrupt.
+  IRQ : Number of the interrupt for get pending
+  return :
+     0  Interrupt status is not pending
+     1  Interrupt status is pending
+ */
+static inline uint32_t NVIC_GetPendingIRQ(uint32_t IRQ)
+{
+       struct nvic_regs* nvic = LPC_NVIC;
+       return (uint32_t)((nvic->int_set_pending & (1 << (IRQ & 0x1F)))?1:0);
+}
+
+/*  Set Pending Interrupt
+  This function sets the pending bit for the specified interrupt.
+  The interrupt number cannot be a negative value.
+  IRQ : Number of the interrupt for set pending
+ */
+static inline void NVIC_SetPendingIRQ(uint32_t IRQ)
+{
+       struct nvic_regs* nvic = LPC_NVIC;
+       nvic->int_set_pending = (1 << (IRQ & 0x1F));
+}
+
+/*  Clear Pending Interrupt
+  This function clears the pending bit for the specified interrupt.
+  The interrupt number cannot be a negative value.
+  IRQ : Number of the interrupt for clear pending
+ */
+static inline void NVIC_ClearPendingIRQ(uint32_t IRQ)
+{
+       struct nvic_regs* nvic = LPC_NVIC;
+       nvic->int_clear_pending = (1 << (IRQ & 0x1F));
+}
+
+
+/* The following MACROS handle generation of the register offset and byte masks */
+#define LPC_NVIC_PRIO_BITS  5  /* Number of Bits used for Priority Levels */
+#define LPC_IRQ_BIT_SHIFT(IRQ) (((uint32_t)(IRQ) & 0x03) * 8)
+#define LPC_IRQ_SHP_IDX(IRQ)   ((((int32_t)(IRQ) + 16) >> 2) - 1)
+#define LPC_IRQ_IP_IDX(IRQ)    ((uint32_t)(IRQ) >> 2)
+
+/*  Set Interrupt Priority
+  This function sets the priority for the specified interrupt. The interrupt
+    number can be positive to specify an external (device specific)
+    interrupt, or negative to specify an internal (core) interrupt.
+  Note: The priority cannot be set for every core interrupt.
+  IRQ : Number of the interrupt for set priority
+  priority : Priority to set
+ */
+static inline void NVIC_SetPriority(uint32_t IRQ, uint32_t priority)
+{
+       if ((int32_t)IRQ < 0) {
+               if ((int32_t)IRQ > (-12)) {
+                       struct syst_ctrl_block_regs* scb = LPC_SCB;
+                       scb->shp[LPC_IRQ_SHP_IDX(IRQ)] = (scb->shp[LPC_IRQ_SHP_IDX(IRQ)] & ~(0xFF << LPC_IRQ_BIT_SHIFT(IRQ))) |
+                               (((priority << (8 - LPC_NVIC_PRIO_BITS)) & 0xFF) << LPC_IRQ_BIT_SHIFT(IRQ));
+               }
+       } else if (LPC_IRQ_IP_IDX(IRQ) < 8) {
+               struct nvic_regs* nvic = LPC_NVIC;
+               nvic->int_priority[LPC_IRQ_IP_IDX(IRQ)] = (nvic->int_priority[LPC_IRQ_IP_IDX(IRQ)] & ~(0xFF << LPC_IRQ_BIT_SHIFT(IRQ))) |
+                       (((priority << (8 - LPC_NVIC_PRIO_BITS)) & 0xFF) << LPC_IRQ_BIT_SHIFT(IRQ));
+       }
+}
+
+
+/*  Get Interrupt Priority
+  This function reads the priority for the specified interrupt. The interrupt
+    number can be positive to specify an external (device specific)
+    interrupt, or negative to specify an internal (core) interrupt.
+  The returned priority value is automatically aligned to the implemented
+    priority bits of the microcontroller.
+  IRQ : Number of the interrupt for get priority
+  return : Interrupt Priority
+ */
+static inline uint32_t NVIC_GetPriority(uint32_t IRQ)
+{
+       if ((int32_t)IRQ < 0) {
+               if ((int32_t)IRQ > (-12)) {
+                       struct syst_ctrl_block_regs* scb = LPC_SCB;
+                       /* Get priority for Cortex-M0 system interrupts */
+                       return ((uint32_t)((scb->shp[LPC_IRQ_SHP_IDX(IRQ)] >> LPC_IRQ_BIT_SHIFT(IRQ) ) >> (8 - LPC_NVIC_PRIO_BITS)));
+               }
+       } else if (LPC_IRQ_IP_IDX(IRQ) < 8) {
+               struct nvic_regs* nvic = LPC_NVIC;
+               /* Get priority for device specific interrupts */
+               return ((uint32_t)((nvic->int_priority[LPC_IRQ_IP_IDX(IRQ)] >> LPC_IRQ_BIT_SHIFT(IRQ) ) >> (8 - LPC_NVIC_PRIO_BITS)));
+       }
+}
+
+
+/*  System Reset
+  This function initiate a system reset request to reset the MCU.
+ */
+static inline void NVIC_SystemReset(void)
+{
+       struct syst_ctrl_block_regs* scb = LPC_SCB;
+       dsb(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */
+       scb->aircr = ((0x5FA << SCB_AIRCR_VECTKEY_OFFSET) | SCB_AIRCR_SYSRESETREQ);
+       dsb();  /* Ensure completion of memory access */
+       while (1); /* wait until reset */
+}
+
+
+
+/*******************************************************************************/
+/*            Sync lock                                                        */
+/*******************************************************************************/
+/* NOTE : There is no syncro instructions on Cortex-M0 */
+
+/* IRQ released version : IRQ are enabled upon return
+ * Returns the old value after the new value has been set.
+ */
+static inline uint32_t sync_lock_test_and_set(volatile uint32_t *addr, uint32_t value)
+{
+       uint32_t oldval;
+       lpc_disable_irq();
+       dsb();
+       oldval = *addr;
+       *addr = value;
+       dsb();
+       lpc_enable_irq();
+       return oldval;
+}
+/* Remove the lock */
+static inline void sync_lock_release(volatile uint32_t *addr)
+{
+       *addr = 0;
+       dsb();
+}
+
+/* IRQ disabled version : If lock is acquired (old value is 0) IRQ are
+ *   disabled when the call returns
+ * Returns the old value after the new value has been set.
+ */
+static inline uint32_t irq_sync_lock_test_and_set(volatile uint32_t *addr, uint32_t value)
+{
+       uint32_t oldval;
+       lpc_disable_irq();
+       dsb();
+       oldval = *addr;
+       *addr = value;
+       dsb();
+       if (oldval) {
+               lpc_enable_irq();
+       }
+       return oldval;
+}
+/* Remove the lock */
+static inline void irq_sync_lock_release(volatile uint32_t *addr)
+{
+       *addr = 0;
+       dsb();
+       lpc_enable_irq();
+}
+
+
+#endif /* LPC_CORE_H */
+
diff --git a/include/core/lpc_core_cm0.h b/include/core/lpc_core_cm0.h
deleted file mode 100644 (file)
index e639b04..0000000
+++ /dev/null
@@ -1,392 +0,0 @@
-/****************************************************************************
- *   core/lpc_core_cm0.h
- *
- * Helper functions to access some registers and Cortex M0 core functionalities.
- *
- *
- * Most of the code from here comes from CMSIS. Should this be rewritten ?
- *
- *
- * 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 <http://www.gnu.org/licenses/>.
- *
- *************************************************************************** */
-
-#ifndef LPC_CORE_CM0_H
-#define LPC_CORE_CM0_H
-
-#include <stdint.h>   /* standard types definitions */
-#include "core/lpc_regs_11u3x.h"
-
-
-/*******************************************************************************/
-/*                Core Instructions                                            */
-/*******************************************************************************/
-/* NOP */
-#define nop() __asm volatile ("nop" : : : "memory")
-/* SEV : Send Event */
-#define sev() __asm volatile ("sev" : : : "memory")
-/* WFE : Wait For Event */
-#define wfe() __asm volatile ("wfe" : : : "memory")
-/* WFI : Wait For Interrupt */
-#define wfi() __asm volatile ("wfi" : : : "memory")
-
-
-/* Synchronization */
-/* Instruction Synchronization Barrier : Flushes pipeline */
-#define isb() __asm volatile ("isb" : : : "memory")
-/* Data Synchronization Barrier : All explicit memory access completed */
-#define dsb() __asm volatile ("dsb" : : : "memory")
-/* Data Memory Barrier : Ensures apparent order but not completion */
-#define dmb() __asm volatile ("dmb" : : : "memory")
-
-
-
-/* Access to the Application Program Status Register (APSR). */
-static inline uint32_t get_APSR(void)
-{
-       uint32_t r; __asm volatile ("mrs %0, apsr" : "=r" (r)); return (r);
-}
-#define APSR_SATURATION  (get_APSR & (0x1 << 27))  /* bit 27  Saturation condition flag */
-#define APSR_OVERFLOW    (get_APSR & (0x1 << 28))  /* bit 28  Overflow condition code flag */
-#define APSR_CARRY       (get_APSR & (0x1 << 29))  /* bit 29  Carry condition code flag */
-#define APSR_ZERO        (get_APSR & (0x1 << 30))  /* bit 30  Zero condition code flag */
-#define APSR_NEGATIVE    (get_APSR & (0x1 << 31))  /* bit 31  Negative condition code flag */
-
-
-/* Access the Interrupt Program Status Register (IPSR). */
-static inline uint32_t get_IPSR(void)
-{
-       uint32_t r; __asm volatile ("mrs %0, ipsr" : "=r" (r)); return (r);
-}
-#define IPSR      (get_IPSR & 0x1FF)  /* bit:  0..8  Exception number */
-#define IPSR_IRQ0 16
-#define IRQ_NUM   (IPSR - IPSR_IRQ0)
-
-
-/* Control Register */
-static inline uint32_t get_CONTROL(void)
-{
-       uint32_t r; __asm volatile ("mrs %0, control" : "=r" (r)); return (r);
-}
-static inline void set_CONTROL(uint32_t control)
-{
-       __asm volatile ("msr control, %0" : : "r" (control));
-}
-
-
-/* Process Stack Pointer */
-static inline uint32_t get_process_stack_pointer(void)
-{
-       register uint32_t r; __asm volatile ("mrs %0, psp" : "=r" (r)); return (r);
-}
-static inline void set_process_stack_pointer(uint32_t top_of_stack)
-{
-       __asm volatile ("msr psp, %0" : : "r" (top_of_stack));
-}
-
-
-/* Main Stack Pointer */
-static inline uint32_t get_main_stack_pointer(void)
-{
-       register uint32_t r; __asm volatile ("mrs %0, msp" : "=r" (r)); return (r);
-}
-static inline void set_main_stack_pointer(uint32_t top_of_stack)
-{
-       __asm volatile ("msr msp, %0" : : "r" (top_of_stack));
-}
-
-
-/* Priority Mask */
-static inline uint32_t get_priority_mask(void)
-{
-       uint32_t r; __asm volatile ("mrs %0, primask" : "=r" (r)); return (r);
-}
-static inline void set_priority_mask(uint32_t mask)
-{
-       __asm volatile ("msr primask, %0" : : "r" (mask));
-}
-
-
-/* Base Priority */
-static inline uint32_t get_base_priority(void)
-{
-       uint32_t r; __asm volatile ("mrs %0, basepri_max" : "=r" (r)); return (r);
-}
-static inline void set_base_priority(uint32_t prio)
-{
-       __asm volatile ("msr basepri, %0" : : "r" (prio));
-}
-
-
-/* Fault Mask */
-static inline uint32_t get_fault_mask(void)
-{
-       uint32_t r; __asm volatile ("mrs %0, faultmask" : "=r" (r)); return (r);
-}
-static inline void set_fault_mask(uint32_t mask)
-{
-       __asm volatile ("msr faultmask, %0" : : "r" (mask));
-}
-
-
-
-/*******************************************************************************/
-/*            Byte swap instructions                                           */
-/*******************************************************************************/
-/* Swap bytes of each 16-bit halfword in a 32-bit word, keeping halfword order */
-static inline uint32_t double_byte_swap_16(volatile uint32_t value)
-{
-       uint32_t result = 0;
-       __asm volatile ("rev16 %0, %1" : "=l" (result) : "l" (value));
-       return result;
-}
-/* Change endianness of a 16-bit halfword */
-static inline uint32_t byte_swap_16(volatile uint16_t value)
-{
-       uint32_t result = 0;
-       __asm volatile ("rev16 %0, %1" : "=l" (result) : "l" (value));
-       return (result & 0xFFFF);
-}
-/* Change endianness of a 32-bit word */
-static inline uint32_t byte_swap_32(volatile uint32_t value)
-{
-       uint32_t result = 0;
-       __asm volatile ("rev %0, %1" : "=l" (result) : "l" (value));
-       return result;
-}
-
-
-
-
-
-/*******************************************************************************/
-/*            Interrupts                                                       */
-/*******************************************************************************/
-
-/* Cortex-M0 Processor Exceptions Numbers */
-/* Note : entry 0 is "end stack pointer" */
-#define RESET_IRQ       ( -15 ) /*  1 - Reset ... not an interrupt ... */
-#define NMI_IRQ         ( -14 ) /*  2 - Non Maskable Interrupt */
-#define HARD_FAULT_IRQ  ( -13 ) /*  3 - Cortex-M0 Hard Fault Interrupt */
-/* Note : entry 7 is the 2’s complement of the check-sum of the previous 7 entries */
-#define SV_CALL_IRQ     (  -5 ) /* 11 - Cortex-M0 Supervisor Call Interrupt */
-#define PEND_SV_IRQ     (  -2 ) /* 14 - Cortex-M0 Pend SV Interrupt */
-#define SYSTICK_IRQ     (  -1 ) /* 15 - Cortex-M0 System Tick Interrupt */
-/* LPC12xx Specific Interrupt Numbers */
-#define PIN_INT0_IRQ       0   /* I/O pins can be used as wakeup source. */
-#define PIN_INT1_IRQ       1
-#define PIN_INT2_IRQ       2
-#define PIN_INT3_IRQ       3
-#define PIN_INT4_IRQ       4
-#define PIN_INT5_IRQ       5
-#define PIN_INT6_IRQ       6
-#define PIN_INT7_IRQ       7
-#define GRP_INT0_IRQ       8
-#define GRP_INT1_IRQ       9
-#define SSP1_IRQ          14  /* 14 - SSP 1 */
-#define I2C0_IRQ          15  /* 15 - I2C 0 */
-#define TIMER0_IRQ        16  /* 16 - Timer 0 */
-#define TIMER1_IRQ        17  /* 17 - Timer 1 */
-#define TIMER2_IRQ        18  /* 18 - Timer 2 */
-#define TIMER3_IRQ        19  /* 19 - Timer 3 */
-#define SSP0_IRQ          20  /* 20 - SSP 0 */
-#define UART0_IRQ         21  /* 21 - UART 0 */
-#define USB_IRQ           22  /* 22 - USB */
-#define USB_FIQ_IRQ       23  /* 23 - USB FIQ */
-#define ADC_IRQ           24  /* 24 - A/D Converter */
-#define WDT_IRQ           25  /* 25 - Watchdog */
-#define BOD_IRQ           26  /* 26 - Brown Out Detect(BOD) */
-#define FLASH_IRQ         27  /* 27 - Flash / EEPROM */
-#define USB_WAKEUP_IRQ    30  /* 26 - USB Wakeup */
-#define IOH_IRQ           31  /* 27 - I/O Handler */
-
-
-/* Enable IRQ Interrupts
-  Enables IRQ interrupts by clearing the I-bit in the CPSR.
-  Can only be executed in Privileged modes.
- */
-static inline void lpc_enable_irq(void)
-{
-       __asm volatile ("cpsie i");
-}
-
-/* Disable IRQ Interrupts
-  Disables IRQ interrupts by setting the I-bit in the CPSR.
-  Can only be executed in Privileged modes.
- */
-static inline void lpc_disable_irq(void)
-{
-       __asm volatile ("cpsid i");
-}
-
-
-/*******************************************************************************/
-/*                Hardware Abstraction Layer : NVIC Functions                  */
-/*******************************************************************************/
-/*  Enable External Interrupt
-  This function enables a device specific interrupt in the NVIC interrupt controller.
-  The interrupt number cannot be a negative value.
-  IRQ : Number of the external interrupt to enable
- */
-static inline void NVIC_EnableIRQ(uint32_t IRQ)
-{
-       struct nvic_regs* nvic = LPC_NVIC;
-       nvic->int_set_enable = (1 << (IRQ & 0x1F));
-}
-
-/*  Disable External Interrupt
-  This function disables a device specific interupt in the NVIC interrupt controller.
-  The interrupt number cannot be a negative value.
-  IRQ : Number of the external interrupt to disable
- */
-static inline void NVIC_DisableIRQ(uint32_t IRQ)
-{
-       struct nvic_regs* nvic = LPC_NVIC;
-       nvic->int_clear_enable = (1 << (IRQ & 0x1F));
-}
-
-/*  Get Pending Interrupt
-  This function reads the pending register in the NVIC and returns the pending bit
-    for the specified interrupt.
-  IRQ : Number of the interrupt for get pending
-  return :
-     0  Interrupt status is not pending
-     1  Interrupt status is pending
- */
-static inline uint32_t NVIC_GetPendingIRQ(uint32_t IRQ)
-{
-       struct nvic_regs* nvic = LPC_NVIC;
-       return (uint32_t)((nvic->int_set_pending & (1 << (IRQ & 0x1F)))?1:0);
-}
-
-/*  Set Pending Interrupt
-  This function sets the pending bit for the specified interrupt.
-  The interrupt number cannot be a negative value.
-  IRQ : Number of the interrupt for set pending
- */
-static inline void NVIC_SetPendingIRQ(uint32_t IRQ)
-{
-       struct nvic_regs* nvic = LPC_NVIC;
-       nvic->int_set_pending = (1 << (IRQ & 0x1F));
-}
-
-/*  Clear Pending Interrupt
-  This function clears the pending bit for the specified interrupt.
-  The interrupt number cannot be a negative value.
-  IRQ : Number of the interrupt for clear pending
- */
-static inline void NVIC_ClearPendingIRQ(uint32_t IRQ)
-{
-       struct nvic_regs* nvic = LPC_NVIC;
-       nvic->int_clear_pending = (1 << (IRQ & 0x1F));
-}
-
-
-/* The following MACROS handle generation of the register offset and byte masks */
-#define LPC_NVIC_PRIO_BITS  5  /* Number of Bits used for Priority Levels */
-#define LPC_IRQ_BIT_SHIFT(IRQ) (((uint32_t)(IRQ) & 0x03) * 8)
-#define LPC_IRQ_SHP_IDX(IRQ)   ((((int32_t)(IRQ) + 16) >> 2) - 1)
-#define LPC_IRQ_IP_IDX(IRQ)    ((uint32_t)(IRQ) >> 2)
-
-/*  Set Interrupt Priority
-  This function sets the priority for the specified interrupt. The interrupt
-    number can be positive to specify an external (device specific)
-    interrupt, or negative to specify an internal (core) interrupt.
-  Note: The priority cannot be set for every core interrupt.
-  IRQ : Number of the interrupt for set priority
-  priority : Priority to set
- */
-static inline void NVIC_SetPriority(uint32_t IRQ, uint32_t priority)
-{
-       if ((int32_t)IRQ < 0) {
-               if ((int32_t)IRQ > (-12)) {
-                       struct syst_ctrl_block_regs* scb = LPC_SCB;
-                       scb->shp[LPC_IRQ_SHP_IDX(IRQ)] = (scb->shp[LPC_IRQ_SHP_IDX(IRQ)] & ~(0xFF << LPC_IRQ_BIT_SHIFT(IRQ))) |
-                               (((priority << (8 - LPC_NVIC_PRIO_BITS)) & 0xFF) << LPC_IRQ_BIT_SHIFT(IRQ));
-               }
-       } else if (LPC_IRQ_IP_IDX(IRQ) < 8) {
-               struct nvic_regs* nvic = LPC_NVIC;
-               nvic->int_priority[LPC_IRQ_IP_IDX(IRQ)] = (nvic->int_priority[LPC_IRQ_IP_IDX(IRQ)] & ~(0xFF << LPC_IRQ_BIT_SHIFT(IRQ))) |
-                       (((priority << (8 - LPC_NVIC_PRIO_BITS)) & 0xFF) << LPC_IRQ_BIT_SHIFT(IRQ));
-       }
-}
-
-
-/*  Get Interrupt Priority
-  This function reads the priority for the specified interrupt. The interrupt
-    number can be positive to specify an external (device specific)
-    interrupt, or negative to specify an internal (core) interrupt.
-  The returned priority value is automatically aligned to the implemented
-    priority bits of the microcontroller.
-  IRQ : Number of the interrupt for get priority
-  return : Interrupt Priority
- */
-static inline uint32_t NVIC_GetPriority(uint32_t IRQ)
-{
-       if ((int32_t)IRQ < 0) {
-               if ((int32_t)IRQ > (-12)) {
-                       struct syst_ctrl_block_regs* scb = LPC_SCB;
-                       /* Get priority for Cortex-M0 system interrupts */
-                       return ((uint32_t)((scb->shp[LPC_IRQ_SHP_IDX(IRQ)] >> LPC_IRQ_BIT_SHIFT(IRQ) ) >> (8 - LPC_NVIC_PRIO_BITS)));
-               }
-       } else if (LPC_IRQ_IP_IDX(IRQ) < 8) {
-               struct nvic_regs* nvic = LPC_NVIC;
-               /* Get priority for device specific interrupts */
-               return ((uint32_t)((nvic->int_priority[LPC_IRQ_IP_IDX(IRQ)] >> LPC_IRQ_BIT_SHIFT(IRQ) ) >> (8 - LPC_NVIC_PRIO_BITS)));
-       }
-}
-
-
-/*  System Reset
-  This function initiate a system reset request to reset the MCU.
- */
-static inline void NVIC_SystemReset(void)
-{
-       struct syst_ctrl_block_regs* scb = LPC_SCB;
-       dsb(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */
-       scb->aircr = ((0x5FA << SCB_AIRCR_VECTKEY_OFFSET) | SCB_AIRCR_SYSRESETREQ);
-       dsb();  /* Ensure completion of memory access */
-       while (1); /* wait until reset */
-}
-
-
-
-/*******************************************************************************/
-/*            Sync lock                                                        */
-/*******************************************************************************/
-/* There is no syncro instructions on Cortex-M0
- * Returns the old value if the new value has been set (lock acquired)
- */
-static inline uint32_t sync_lock_test_and_set(volatile uint32_t *addr, uint32_t value)
-{
-       uint32_t oldval;
-       lpc_disable_irq();
-    dsb();
-       oldval = *addr;
-       *addr = value;
-    dsb();
-       lpc_enable_irq();
-       return oldval;
-}
-/* Remove the lock */
-static inline void sync_lock_release(volatile uint32_t *addr)
-{
-    *addr = 0;
-    dsb();
-}
-
-
-
-#endif /* LPC_CORE_CM0_H */
-
diff --git a/include/core/lpc_regs.h b/include/core/lpc_regs.h
new file mode 100644 (file)
index 0000000..29c8242
--- /dev/null
@@ -0,0 +1,77 @@
+/****************************************************************************
+ *   core/lpc_regs.h
+ *
+ * LPC11u3x Cortex-M0 Core Registers definitions
+ *
+ * Copyright 2012 Nathael Pajani <nathael.pajani@ed3l.fr>
+ *
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ *************************************************************************** */
+#ifndef LPC_REGS_H
+#define LPC_REGS_H
+
+#include "lib/stddef.h"
+#include "lib/stdint.h"
+
+
+
+/***************************************************************************** */
+/*                          Memory Map                                         */
+/***************************************************************************** */
+/* Base addresses */
+#define LPC_FLASH_BASE        (0x00000000UL)
+#define LPC_RAM_BASE          (0x10000000UL)
+#define LPC_RAM1_BASE         (0x20000000UL)
+#define LPC_USB_RAM_BASE      (0x20004000UL)
+#define LPC_APB0_BASE         (0x40000000UL)
+#define LPC_APB1_BASE         (0x40080000UL) /* USB in LPC11U3x */
+#define LPC_AHB_BASE          (0x50000000UL)
+
+/* Memory mapping of Cortex-M0 Hardware */
+#define LPC_SCS_BASE        (0xE000E000UL)         /* System Control Space Base Address */
+#define LPC_COREDEBUG_BASE  (0xE000EDF0UL)         /* Core Debug Base Address */
+#define LPC_SYSTICK_BASE    (LPC_SCS_BASE + 0x0010UL)  /* SysTick Base Address */
+#define LPC_NVIC_BASE       (LPC_SCS_BASE + 0x0100UL)  /* NVIC Base Address */
+#define LPC_SCB_BASE        (LPC_SCS_BASE + 0x0D00UL)  /* System Control Block Base Address */
+
+/* APB0 peripherals */
+#define LPC_I2C0_BASE          (LPC_APB0_BASE + 0x00000)
+#define LPC_WDT_BASE           (LPC_APB0_BASE + 0x04000)
+#define LPC_UART0_BASE         (LPC_APB0_BASE + 0x08000)
+#define LPC_TIMER0_BASE        (LPC_APB0_BASE + 0x0C000)
+#define LPC_TIMER1_BASE        (LPC_APB0_BASE + 0x10000)
+#define LPC_TIMER2_BASE        (LPC_APB0_BASE + 0x14000)
+#define LPC_TIMER3_BASE        (LPC_APB0_BASE + 0x18000)
+#define LPC_ADC_BASE           (LPC_APB0_BASE + 0x1C000)
+#define LPC_PMU_BASE           (LPC_APB0_BASE + 0x38000)
+#define LPC_FLASH_EEPROM_BASE  (LPC_APB0_BASE + 0x3C000)
+#define LPC_SSP0_BASE          (LPC_APB0_BASE + 0x40000)
+#define LPC_IOCON_BASE         (LPC_APB0_BASE + 0x44000)
+#define LPC_SYSCON_BASE        (LPC_APB0_BASE + 0x48000)
+#define LPC_GPIO_INTR_BASE     (LPC_APB0_BASE + 0x4C000)
+#define LPC_SSP1_BASE          (LPC_APB0_BASE + 0x58000)
+#define LPC_GPIO_GRP0_INT_BASE (LPC_APB0_BASE + 0x5C000)
+#define LPC_GPIO_GRP1_INT_BASE (LPC_APB0_BASE + 0x60000)
+
+/* APB1 peripherals */
+#define LPC_USB_BASE           (LPC_APB1_BASE + 0x00000)
+
+/* AHB peripherals */
+#define LPC_GPIO_BASE          (LPC_AHB_BASE + 0x00000)
+
+
+
+#endif  /* LPC_REGS_H */
diff --git a/include/core/lpc_regs_11u3x.h b/include/core/lpc_regs_11u3x.h
deleted file mode 100644 (file)
index 8f01ce9..0000000
+++ /dev/null
@@ -1,926 +0,0 @@
-/****************************************************************************
- *   core/lpc12xx_regs.h
- *
- * Cortex-M0 Core Registers definitions
- *
- * Copyright 2012 Nathael Pajani <nathael.pajani@ed3l.fr>
- *
- *
- * 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 <http://www.gnu.org/licenses/>.
- *
- *************************************************************************** */
-#ifndef LPC_REGS_H
-#define LPC_REGS_H
-
-/* Get size_t, and NULL from <stddef.h>.  */
-#undef __need_malloc_and_calloc
-#define __need_size_t
-#define __need_NULL
-#include <stddef.h>
-#include <stdint.h>
-
-
-
-/***************************************************************************** */
-/*                          Memory Map                                         */
-/***************************************************************************** */
-/* Base addresses */
-#define LPC_FLASH_BASE        (0x00000000UL)
-#define LPC_RAM_BASE          (0x10000000UL)
-#define LPC_RAM1_BASE         (0x20000000UL)
-#define LPC_USB_RAM_BASE      (0x20004000UL)
-#define LPC_APB0_BASE         (0x40000000UL)
-#define LPC_APB1_BASE         (0x40080000UL) /* USB in LPC11U3x */
-#define LPC_AHB_BASE          (0x50000000UL)
-
-/* Memory mapping of Cortex-M0 Hardware */
-#define LPC_SCS_BASE        (0xE000E000UL)         /* System Control Space Base Address */
-#define LPC_COREDEBUG_BASE  (0xE000EDF0UL)         /* Core Debug Base Address */
-#define LPC_SYSTICK_BASE    (LPC_SCS_BASE + 0x0010UL)  /* SysTick Base Address */
-#define LPC_NVIC_BASE       (LPC_SCS_BASE + 0x0100UL)  /* NVIC Base Address */
-#define LPC_SCB_BASE        (LPC_SCS_BASE + 0x0D00UL)  /* System Control Block Base Address */
-
-/* APB0 peripherals */
-#define LPC_I2C0_BASE          (LPC_APB0_BASE + 0x00000)
-#define LPC_WDT_BASE           (LPC_APB0_BASE + 0x04000)
-#define LPC_UART0_BASE         (LPC_APB0_BASE + 0x08000)
-#define LPC_TIMER0_BASE        (LPC_APB0_BASE + 0x0C000)
-#define LPC_TIMER1_BASE        (LPC_APB0_BASE + 0x10000)
-#define LPC_TIMER2_BASE        (LPC_APB0_BASE + 0x14000)
-#define LPC_TIMER3_BASE        (LPC_APB0_BASE + 0x18000)
-#define LPC_ADC_BASE           (LPC_APB0_BASE + 0x1C000)
-#define LPC_PMU_BASE           (LPC_APB0_BASE + 0x38000)
-#define LPC_FLASH_EEPROM_BASE  (LPC_APB0_BASE + 0x3C000)
-#define LPC_SSP0_BASE          (LPC_APB0_BASE + 0x40000)
-#define LPC_IOCON_BASE         (LPC_APB0_BASE + 0x44000)
-#define LPC_SYSCON_BASE        (LPC_APB0_BASE + 0x48000)
-#define LPC_GPIO_INTR_BASE     (LPC_APB0_BASE + 0x4C000)
-#define LPC_SSP1_BASE          (LPC_APB0_BASE + 0x58000)
-#define LPC_GPIO_GRP0_INT_BASE (LPC_APB0_BASE + 0x5C000)
-#define LPC_GPIO_GRP1_INT_BASE (LPC_APB0_BASE + 0x60000)
-
-/* APB1 peripherals */
-#define LPC_USB_BASE           (LPC_APB1_BASE + 0x00000)
-
-/* AHB peripherals */
-#define LPC_GPIO_BASE          (LPC_AHB_BASE + 0x00000)
-
-
-
-/***************************************************************************** */
-/*                     System Control                                          */
-/***************************************************************************** */
-/* System Control (SYSCON) */
-struct lpc_sys_start_logic_ctrl
-{
-       volatile uint32_t edge_ctrl;  /* 0x00 : edge control Register 0 (R/W) */
-       volatile uint32_t signal_en;  /* 0x04 : signal enable Register 0 (R/W) */
-       volatile uint32_t reset;      /* 0x08 : reset Register 0  (-/W) */
-       volatile uint32_t status;     /* 0x0C : status Register 0 (R/-) */
-};
-struct lpc_sys_control
-{
-       volatile uint32_t sys_mem_remap;   /* 0x000 System memory remap (R/W) */
-       volatile uint32_t peripheral_reset_ctrl; /* 0x004 Peripheral reset control (R/W) */
-       volatile uint32_t sys_pll_ctrl;    /* 0x008 System PLL control (R/W) */
-       volatile uint32_t sys_pll_status;  /* 0x00C System PLL status (R/ ) */
-       volatile uint32_t usb_pll_ctrl;    /* 0x010 USB PLL control (R/W) */
-       volatile uint32_t usb_pll_status;  /* 0x014 USB PLL status (R/ ) */
-       uint32_t reserved_0[2];
-
-       volatile uint32_t sys_osc_ctrl;    /* 0x020 : System oscillator control (R/W) */
-       volatile uint32_t WDT_osc_ctrl;    /* 0x024 : Watchdog oscillator control (R/W) */
-       volatile uint32_t IRC_ctrl;        /* 0x028 : IRC control (R/W) */
-       uint32_t reserved_1[1];
-       volatile uint32_t sys_reset_status;    /* 0x030 : System reset status Register (R/ ) */
-       uint32_t reserved_2[3];
-       volatile uint32_t sys_pll_clk_sel;     /* 0x040 : System PLL clock source select (R/W) */
-       volatile uint32_t sys_pll_clk_upd_en;  /* 0x044 : System PLL clock source update enable (R/W) */
-       volatile uint32_t usb_pll_clk_sel;     /* 0x048 : USB PLL clock source select (R/W) */
-       volatile uint32_t usb_pll_clk_upd_en;  /* 0x04C : USB PLL clock source update enable (R/W) */
-       uint32_t reserved_3[8];
-
-       volatile uint32_t main_clk_sel;     /* 0x070 : Main clock source select (R/W) */
-       volatile uint32_t main_clk_upd_en;  /* 0x074 : Main clock source update enable (R/W) */
-       volatile uint32_t sys_AHB_clk_div;  /* 0x078 : System AHB clock divider (R/W) */
-       uint32_t reserved_4[1];
-       volatile uint32_t sys_AHB_clk_ctrl; /* 0x080 : System AHB clock control (R/W) */
-       uint32_t reserved_5[4];
-
-       volatile uint32_t ssp0_clk_div;   /* 0x094 : SSP0 clock divider (R/W) */
-       volatile uint32_t uart_clk_div;   /* 0x098 : UART0 clock divider (R/W) */
-       volatile uint32_t ssp1_clk_div;   /* 0x09C : SSP1 clock divider (R/W) */
-       uint32_t reserved_6a[8];
-       volatile uint32_t usb_clk_sel;    /* 0x0C0 : USB clock source select (R/W) */
-       volatile uint32_t usb_clk_upd_en; /* 0x0C4 : USB clock source update enable (R/W) */
-       volatile uint32_t usb_clk_div;    /* 0x0C8 : USB clock source divider (R/W) */
-       uint32_t reserved_6b[5];
-
-       volatile uint32_t clk_out_src_sel; /* 0x0E0 : CLKOUT clock source select (R/W) */
-       volatile uint32_t clk_out_upd_en;  /* 0x0E4 : CLKOUT clock source update enable (R/W) */
-       volatile uint32_t clk_out_div;     /* 0x0E8 : CLKOUT clock divider (R/W) */
-       uint32_t reserved_7[5];
-
-       volatile uint32_t por_captured_io_status[2];  /* 0x100 - 0x104 : POR captured PIO status 0 and 1 (R/ ) */
-       uint32_t reserved_8[11];
-
-       volatile uint32_t IO_config_clk_div[7]; /* 0x134 - 0x14C : Peripheral clocks 6 to 0 for glitch filter */
-
-       volatile uint32_t BOD_ctrl;      /* 0x150 : BOD control (R/W) */
-       volatile uint32_t sys_tick_cal;  /* 0x154 : System tick counter calibration (R/W) */
-       volatile uint32_t ahb_prio_set;  /* 0x158 : AHB priority setting (-/-) */
-       uint32_t reserved_9[5];
-       volatile uint32_t irq_latency;   /* 0x170 : IRQ delay, alloxs trade-off bw latency and determinism (R/W) */
-       volatile uint32_t int_nmi_cfg;   /* 0x174 : NMI interrupt source configuration control (R/W) */
-       volatile uint32_t gpio_int_sel[8]; /* 0x178 - 0x194 : GPIO Pin Interrupt Select 0 to 8 (R/W) */
-       volatile uint32_t usb_clk_ctrl;    /* 0x198 : USB Clock control (R/W) */
-       volatile uint32_t usb_clk_status;  /* 0x198 : USB Clock status (R/W) */
-       uint32_t reserved_10[24];
-
-       struct lpc_sys_start_logic_ctrl start_log_strl[2]; /* 0x200 to 0x20C and 0x210 to 0x21C :
-                                                                                                Start logic 0 and Start logic 1/peripheral interrupts */
-       uint32_t reserved_11[4];
-
-       volatile uint32_t powerdown_sleep_cfg;  /* 0x230 : Power-down states in Deep-sleep mode (R/W) */
-       volatile uint32_t powerdown_awake_cfg;  /* 0x234 : Power-down states after wake-up (R/W) */
-       volatile uint32_t powerdown_run_cfg;        /* 0x238 : Power-down configuration Register (R/W) */
-       uint32_t reserved_12[110];
-       volatile const uint32_t device_id;  /* 0x3F4 : Device ID (R/ ) */
-};
-
-#define LPC_SYS_CONTROL ((struct lpc_sys_control *) LPC_SYSCON_BASE)
-
-/* AHB control bits
- *   0 (System (cortexM0, syscon, PMU, ...)) is a read only bit (system cannot be disabled)
- */
-#define LPC_SYS_ABH_CLK_CTRL_SYSTEM     (1 <<  0) /* Read only */
-#define LPC_SYS_ABH_CLK_CTRL_ROM        (1 <<  1)
-#define LPC_SYS_ABH_CLK_CTRL_RAM        (1 <<  2)
-#define LPC_SYS_ABH_CLK_CTRL_FLASH_REG  (1 <<  3)
-#define LPC_SYS_ABH_CLK_CTRL_FLASH      (1 <<  4)
-#define LPC_SYS_ABH_CLK_CTRL_I2C        (1 <<  5)
-#define LPC_SYS_ABH_CLK_CTRL_GPIO       (1 <<  6)
-#define LPC_SYS_ABH_CLK_CTRL_CT16B0     (1 <<  7)
-#define LPC_SYS_ABH_CLK_CTRL_CT16B1     (1 <<  8)
-#define LPC_SYS_ABH_CLK_CTRL_CT32B0     (1 <<  9)
-#define LPC_SYS_ABH_CLK_CTRL_CT32B1     (1 << 10)
-#define LPC_SYS_ABH_CLK_CTRL_SSP0       (1 << 11)
-#define LPC_SYS_ABH_CLK_CTRL_UART0      (1 << 12)
-#define LPC_SYS_ABH_CLK_CTRL_ADC        (1 << 13)
-#define LPC_SYS_ABH_CLK_CTRL_USB        (1 << 14)
-#define LPC_SYS_ABH_CLK_CTRL_Watchdog   (1 << 15)
-#define LPC_SYS_ABH_CLK_CTRL_IO_CONFIG  (1 << 16)
-#define LPC_SYS_ABH_CLK_CTRL_SSP1       (1 << 18)
-#define LPC_SYS_ABH_CLK_CTRL_PINT       (1 << 19)
-#define LPC_SYS_ABH_CLK_CTRL_P0INT      (1 << 23)
-#define LPC_SYS_ABH_CLK_CTRL_P1INT      (1 << 24)
-#define LPC_SYS_ABH_CLK_CTRL_RAM1       (1 << 26)
-#define LPC_SYS_ABH_CLK_CTRL_USBRAM     (1 << 27)
-/* Helper */
-#define LPC_SYS_ABH_CLK_CTRL_MEM_ALL    0x0000001F
-
-#define LPC_SSP0_RESET_N       (1 << 0)
-#define LPC_I2C_RESET_N        (1 << 1)
-#define LPC_SSP1_RESET_N       (1 << 2)
-
-#define LPC_POWER_DOWN_IRC_OUT      (1 << 0)
-#define LPC_POWER_DOWN_IRC          (1 << 1)
-#define LPC_POWER_DOWN_FLASH        (1 << 2)
-#define LPC_POWER_DOWN_BOD          (1 << 3)
-#define LPC_POWER_DOWN_ADC          (1 << 4)
-#define LPC_POWER_DOWN_SYS_OSC      (1 << 5)
-#define LPC_POWER_DOWN_WDT_OSC      (1 << 6)
-#define LPC_POWER_DOWN_SYSPLL       (1 << 7)
-#define LPC_POWER_DOWN_USBPLL       (1 << 8)
-#define LPC_POWER_DOWN_USB          (1 << 10)
-                            /* write bit 11, 13, 14, 15 always as ones   and   bits 9 and 12 always as zeroes */
-#define LPC_POWER_DOWN_MASK(x)    (  ((x) | (1 << 11) | (0x07 << 13))   &   ~((1 << 9) | (1 << 12))  )
-
-#define LPC_DEEP_SLEEP_CFG_NOWDTLOCK_BOD_ON  0x0000FFF7
-#define LPC_DEEP_SLEEP_CFG_NOWDTLOCK_BOD_OFF 0x0000FFFF
-
-#define LPC_CLKOUT_SRC_IRC_OSC       0x00
-#define LPC_CLKOUT_SRC_XTAL_OSC      0x01
-#define LPC_CLKOUT_SRC_WATCHDOG_OSC  0x02
-#define LPC_CLKOUT_SRC_MAIN_CLK      0x03
-
-#define LPC_SYSCLK_SRC_IRC_OSC       0x00
-#define LPC_SYSCLK_SRC_XTAL_OSC      0x01
-#define LPC_SYSCLK_SRC_PLL_INPUT     0x01
-#define LPC_SYSCLK_SRC_WATCHDOG_OSC  0x02
-#define LPC_SYSCLK_SRC_MAIN_CLK      0x03
-#define LPC_SYSCLK_SRC_PLL_OUTPUT    0x03
-
-#define LPC_USBPLLCLK_SRC_IRC_OSC    0x00
-#define LPC_USBPLLCLK_SRC_XTAL_OSC   0x01
-
-#define LPC_USBCLK_SRC_USB_PLL_OUT   0x00
-#define LPC_USBCLK_SRC_MAIN_CLK      0x01
-
-
-/***************************************************************************** */
-/*                  Flash Control                                              */
-/***************************************************************************** */
-/* Flash configuration */
-struct lpc_flash_control
-{
-       uint32_t reserved_0[4];
-       volatile uint32_t flash_cfg; /* 0x028 Flash configuration (R/W) */
-       uint32_t reserved_1[3];
-       /* Flash Memory Signature */
-       volatile uint32_t flash_signature_start;  /* 0x020 : Signature start address (R/W) */
-       volatile uint32_t flash_signature_end;    /* 0x024 : Signature end address (R/W) */
-       uint32_t reserved_2[1];
-       volatile uint32_t flash_signature[4];     /* 0x02C - 0x038 : Signature Words (R/-) */
-       uint32_t reserved_3[24];
-       /* EEPROM Memory Signature */
-       volatile uint32_t eeprom_signature_start;  /* 0x09C : Signature start address (R/W) */
-       volatile uint32_t eeprom_signature_end;    /* 0x0A0 : Signature end address (R/W) */
-       volatile uint32_t eeprom_signature;        /* 0x0A4 : Signature (R/-) */
-       uint32_t reserved_4[975];
-       /* Flash Memory Signature Generation */
-       volatile uint32_t flash_sig_gen_status;    /* 0xFE0 : Flash signature generation status (R/-) */
-       uint32_t reserved_5[1];
-       volatile uint32_t flash_sig_gen_stat_clr;  /* 0xFE8 : Flash signature generation status clear (R/W) */
-};
-#define LPC_FLASH_CONTROL ((struct lpc_flash_control *) LPC_FLASH_EEPROM_BASE)
-#define LPC_FLASH_CFG_MASK   0x03
-#define LPC_FLASH_CFG_SHIFT  0
-
-
-
-/***************************************************************************** */
-/*                     Cortex-M0 NVIC                                          */
-/***************************************************************************** */
-/* Cortex-M0 NVIC Registers */
-struct nvic_regs {
-       volatile uint32_t int_set_enable;  /* 0x000 : Interrupt Set Enable Register (R/W) */
-       uint32_t reserved_0[31];
-       volatile uint32_t int_clear_enable;  /* 0x080 : Interrupt Clear Enable Register (R/W) */
-       uint32_t reserved_1[31];
-       volatile uint32_t int_set_pending;  /* 0x100 : Interrupt Set Pending Register (R/W) */
-       uint32_t reserved_2[31];
-       volatile uint32_t int_clear_pending;  /* 0x180 : Interrupt Clear Pending Register (R/W) */
-       uint32_t reserved_3[31];
-       uint32_t reserved_4[64];
-       volatile uint32_t int_priority[8]; /* 0x3EC : Interrupt Priority Register (R/W) */
-};
-#define LPC_NVIC      ((struct nvic_regs *) LPC_NVIC_BASE)        /* NVIC configuration struct */
-
-
-/***************************************************************************** */
-/*                    Cortex-M0 System Control Block                           */
-/***************************************************************************** */
-/* Cortex-M0 System Control Block Registers */
-struct syst_ctrl_block_regs {
-       volatile const uint32_t cpuid; /* 0x000 : CPU ID Base Register (R/ ) */
-       volatile uint32_t icsr;        /* 0x004 : Interrupt Control State Register (R/W) */
-       uint32_t reserved_0;
-       volatile uint32_t aircr;       /* 0x00C : Application Interrupt / Reset Control Register (R/W) */
-       volatile uint32_t scr;         /* 0x010 : System Control Register (R/W) */
-       volatile uint32_t ccr;         /* 0x014 : Configuration Control Register (R/W) */
-       uint32_t reserved_1;
-       volatile uint32_t shp[2];      /* 0x01C : System Handlers Priority Registers. [0] is reserved_ (R/W) */
-};
-#define LPC_SCB       ((struct syst_ctrl_block_regs *) LPC_SCB_BASE) /* SCB configuration struct */
-
-/* SCB CPUID Register Definitions */
-#define SCB_CPUID_IMPLEMENTER      (0xFFUL << 24)     /* SCB CPUID: IMPLEMENTER Mask */
-#define SCB_CPUID_VARIANT          (0xFUL << 20)      /* SCB CPUID: VARIANT Mask */
-#define SCB_CPUID_ARCHITECTURE     (0xFUL << 16)      /* SCB CPUID: ARCHITECTURE Mask */
-#define SCB_CPUID_PARTNO           (0xFFFUL << 4)     /* SCB CPUID: PARTNO Mask */
-#define SCB_CPUID_REVISION         (0xFUL << 0)       /* SCB CPUID: REVISION Mask */
-
-/* SCB Interrupt Control State Register Definitions */
-#define SCB_ICSR_NMIPENDSET        (1UL << 31)        /* SCB ICSR: NMIPENDSET Mask */
-#define SCB_ICSR_PENDSVSET         (1UL << 28)        /* SCB ICSR: PENDSVSET Mask */
-#define SCB_ICSR_PENDSVCLR         (1UL << 27)        /* SCB ICSR: PENDSVCLR Mask */
-#define SCB_ICSR_PENDSTSET         (1UL << 26)        /* SCB ICSR: PENDSTSET Mask */
-#define SCB_ICSR_PENDSTCLR         (1UL << 25)        /* SCB ICSR: PENDSTCLR Mask */
-#define SCB_ICSR_ISRPREEMPT        (1UL << 23)        /* SCB ICSR: ISRPREEMPT Mask */
-#define SCB_ICSR_ISRPENDING        (1UL << 22)        /* SCB ICSR: ISRPENDING Mask */
-#define SCB_ICSR_VECTPENDING       (0x1FFUL << 12)    /* SCB ICSR: VECTPENDING Mask */
-#define SCB_ICSR_VECTACTIVE        (0x1FFUL << 0)     /* SCB ICSR: VECTACTIVE Mask */
-
-/* SCB Application Interrupt and Reset Control Register Definitions */
-#define SCB_AIRCR_VECTKEY_OFFSET   16
-#define SCB_AIRCR_VECTKEY          (0xFFFFUL << 16)   /* SCB AIRCR: VECTKEY Mask */
-#define SCB_AIRCR_VECTKEYSTAT      (0xFFFFUL << 16)   /* SCB AIRCR: VECTKEYSTAT Mask */
-#define SCB_AIRCR_ENDIANESS        (1UL << 15)        /* SCB AIRCR: ENDIANESS Mask */
-#define SCB_AIRCR_SYSRESETREQ      (1UL << 2)         /* SCB AIRCR: SYSRESETREQ Mask */
-#define SCB_AIRCR_VECTCLRACTIVE    (1UL << 1)         /* SCB AIRCR: VECTCLRACTIVE Mask */
-
-/* SCB System Control Register Definitions */
-#define SCB_SCR_SEVONPEND          (1UL << 4)         /* SCB SCR: SEVONPEND Mask */
-#define SCB_SCR_SLEEPDEEP          (1UL << 2)         /* SCB SCR: SLEEPDEEP Mask */
-#define SCB_SCR_SLEEPONEXIT        (1UL << 1)         /* SCB SCR: SLEEPONEXIT Mask */
-
-/* SCB Configuration Control Register Definitions */
-#define SCB_CCR_STKALIGN           (1UL << 9)         /* SCB CCR: STKALIGN Mask */
-#define SCB_CCR_UNALIGN_TRP        (1UL << 3)         /* SCB CCR: UNALIGN_TRP Mask */
-
-
-
-/***************************************************************************** */
-/*                    Cortex-M0 System Timer                                   */
-/***************************************************************************** */
-/* Cortex-M0 System Timer Registers */
-struct lpc_system_tick {
-       volatile uint32_t control;     /* 0x000 : SysTick Control and Status Register (R/W) */
-       volatile uint32_t reload_val;  /* 0x004 : SysTick Reload Value Register (R/W) */
-       volatile uint32_t value;       /* 0x008 : SysTick Current Value Register (R/W) */
-       volatile const uint32_t calibration;  /* 0x00C : SysTick Calibration Register (R/ ) */
-};
-#define LPC_SYSTICK  ((struct lpc_system_tick*) LPC_SYSTICK_BASE) /* SysTick configuration struct */
-
-/* SysTick Control / Status Register Definitions */
-#define LPC_SYSTICK_CTRL_COUNTFLAG  (1UL << 16)   /* SysTick CTRL: COUNTFLAG Mask */
-#define LPC_SYSTICK_CTRL_CLKSOURCE  (1UL << 2)    /* SysTick CTRL: CLKSOURCE Mask */
-#define LPC_SYSTICK_CTRL_CLK_MAIN   (1UL << 2)    /* SysTick CTRL: CLKSOURCE is main clock */
-#define LPC_SYSTICK_CTRL_TICKINT    (1UL << 1)    /* SysTick CTRL: TICKINT Mask */
-#define LPC_SYSTICK_CTRL_ENABLE     (1UL << 0)    /* SysTick CTRL: ENABLE Mask */
-
-/* SysTick Reload Register Definitions */
-#define LPC_SYSTICK_LOAD_RELOAD     (0xFFFFFFUL)  /* SysTick LOAD: RELOAD Mask */
-
-/* SysTick Current Register Definitions */
-#define LPC_SYSTICK_VAL_CURRENT     (0xFFFFFFUL)  /* SysTick VAL: CURRENT Mask */
-
-/* SysTick Calibration Register Definitions */
-#define LPC_SYSTICK_CALIB_NOREF     (1UL << 31)   /* SysTick CALIB: NOREF Mask */
-#define LPC_SYSTICK_CALIB_SKEW      (1UL << 30)   /* SysTick CALIB: SKEW Mask */
-#define LPC_SYSTICK_CALIB_TENMS     (0xFFFFFFUL)  /* SysTick CALIB: TENMS Mask */
-
-
-
-
-/***************************************************************************** */
-/*                     Power Management Unit                                   */
-/***************************************************************************** */
-/* Power Management Unit (PMU) */
-struct lpc_pm_unit
-{
-       volatile uint32_t power_ctrl;  /* 0x000 : Power control Register (R/W) */
-       volatile uint32_t gp_data[4];  /* 0x004 to 0x010 : General purpose Register 0 to 3 (R/W) */
-       volatile uint32_t system_config; /* 0x014 : System configuration register (R/W) */
-                                                       /* (RTC clock control and hysteresis of the WAKEUP pin) */
-};
-#define LPC_PMU         ((struct lpc_pm_unit *) LPC_PMU_BASE)
-
-/* System config register */
-#define LPC_WAKEUP_PIN_HYST_MASK    (0x01 << 10)
-#define LPC_RTC_CLK_SRC_SHIFT       11
-#define LPC_RTC_CLK_SRC_MASK        (0x0F << LPC_RTC_CLK_SRC_SHIFT)
-/* See RTC section above for RTC Clock source selection bits */
-
-
-/***************************************************************************** */
-/*                     IO Control                                              */
-/***************************************************************************** */
-/* Pin Connect Block (IOCON) */
-struct lpc_io_control
-{
-       volatile uint32_t pio0_0;    /* 0x000 : I/O configuration for pin pio0_0 (R/W) */
-       volatile uint32_t pio0_1;    /* 0x004 : I/O configuration for pin pio0_1 (R/W) */
-       volatile uint32_t pio0_2;    /* 0x008 : I/O configuration for pin pio0_2 (R/W) */
-       volatile uint32_t pio0_3;    /* 0x00C : I/O configuration for pin pio0_3 (R/W) */
-       volatile uint32_t pio0_4;    /* 0x010 : I/O configuration for pin pio0_4 (R/W) */
-       volatile uint32_t pio0_5;    /* 0x014 : I/O configuration for pin pio0_5 (R/W) */
-       volatile uint32_t pio0_6;    /* 0x018 : I/O configuration for pin pio0_6 (R/W) */
-       volatile uint32_t pio0_7;    /* 0x01C : I/O configuration for pin pio0_7 (R/W) */
-       volatile uint32_t pio0_8;    /* 0x020 : I/O configuration for pin pio0_8 (R/W) */
-       volatile uint32_t pio0_9;    /* 0x024 : I/O configuration for pin pio0_9 (R/W) */
-       volatile uint32_t pio0_10;   /* 0x028 : I/O configuration for pin SWD0_10 (R/W) */
-       volatile uint32_t pio0_11;   /* 0x02C : I/O configuration for pin pio0_11 (R/W) */
-       volatile uint32_t pio0_12;   /* 0x030 : I/O configuration for pin pio0_12 (R/W) */
-       volatile uint32_t pio0_13;   /* 0x034 : I/O configuration for pin pio0_13 (R/W) */
-       volatile uint32_t pio0_14;   /* 0x038 : I/O configuration for pin pio0_14 (R/W) */
-       volatile uint32_t pio0_15;   /* 0x03C : I/O configuration for pin pio0_15 (R/W) */
-       volatile uint32_t pio0_16;   /* 0x040 : I/O configuration for pin pio0_16 (R/W) */
-       volatile uint32_t pio0_17;   /* 0x044 : I/O configuration for pin pio0_17 (R/W) */
-       volatile uint32_t pio0_18;   /* 0x048 : I/O configuration for pin pio0_18 (R/W) */
-       volatile uint32_t pio0_19;   /* 0x04C : I/O configuration for pin pio0_19 (R/W) */
-       volatile uint32_t pio0_20;   /* 0x050 : I/O configuration for pin pio0_20 (R/W) */
-       volatile uint32_t pio0_21;   /* 0x054 : I/O configuration for pin pio0_21 (R/W) */
-       volatile uint32_t pio0_22;   /* 0x058 : I/O configuration for pin pio0_22 (R/W) */
-       volatile uint32_t pio0_23;   /* 0x05C : I/O configuration for pin pio0_23 (R/W) */
-
-       volatile uint32_t pio1_0;    /* 0x060 : I/O configuration for pin pio1_0 (R/W) */
-       volatile uint32_t pio1_1;    /* 0x064 : I/O configuration for pin pio1_1 (R/W) */
-       volatile uint32_t pio1_2;    /* 0x068 : I/O configuration for pin pio1_2 (R/W) */
-       volatile uint32_t pio1_3;    /* 0x06C : I/O configuration for pin pio1_3 (R/W) */
-       volatile uint32_t pio1_4;    /* 0x070 : I/O configuration for pin pio1_4 (R/W) */
-       volatile uint32_t pio1_5;    /* 0x074 : I/O configuration for pin pio1_5 (R/W) */
-       volatile uint32_t pio1_6;    /* 0x078 : I/O configuration for pin pio1_6 (R/W) */
-       volatile uint32_t pio1_7;    /* 0x07C : I/O configuration for pin pio0_7 (R/W) */
-       volatile uint32_t pio1_8;    /* 0x080 : I/O configuration for pin pio0_8 (R/W) */
-       volatile uint32_t pio1_9;    /* 0x084 : I/O configuration for pin pio0_9 (R/W) */
-       volatile uint32_t pio1_10;   /* 0x088 : I/O configuration for pin SWD0_10 (R/W) */
-       volatile uint32_t pio1_11;   /* 0x08C : I/O configuration for pin pio0_11 (R/W) */
-       volatile uint32_t pio1_12;   /* 0x090 : I/O configuration for pin pio0_12 (R/W) */
-       volatile uint32_t pio1_13;   /* 0x094 : I/O configuration for pin pio0_13 (R/W) */
-       volatile uint32_t pio1_14;   /* 0x098 : I/O configuration for pin pio0_14 (R/W) */
-       volatile uint32_t pio1_15;   /* 0x09C : I/O configuration for pin pio0_15 (R/W) */
-       volatile uint32_t pio1_16;   /* 0x0A0 : I/O configuration for pin pio0_16 (R/W) */
-       volatile uint32_t pio1_17;   /* 0x0A4 : I/O configuration for pin pio0_17 (R/W) */
-       volatile uint32_t pio1_18;   /* 0x0A8 : I/O configuration for pin pio0_18 (R/W) */
-       volatile uint32_t pio1_19;   /* 0x0AC : I/O configuration for pin pio0_19 (R/W) */
-       volatile uint32_t pio1_20;   /* 0x0B0 : I/O configuration for pin pio0_20 (R/W) */
-       volatile uint32_t pio1_21;   /* 0x0B4 : I/O configuration for pin pio0_21 (R/W) */
-       volatile uint32_t pio1_22;   /* 0x0B8 : I/O configuration for pin pio0_22 (R/W) */
-       volatile uint32_t pio1_23;   /* 0x0BC : I/O configuration for pin pio0_23 (R/W) */
-       volatile uint32_t pio1_24;   /* 0x0C0 : I/O configuration for pin pio0_24 (R/W) */
-       volatile uint32_t pio1_25;   /* 0x0C4 : I/O configuration for pin pio0_25 (R/W) */
-       volatile uint32_t pio1_26;   /* 0x0C8 : I/O configuration for pin pio0_26 (R/W) */
-       volatile uint32_t pio1_27;   /* 0x0CC : I/O configuration for pin pio0_27 (R/W) */
-       volatile uint32_t pio1_28;   /* 0x0D0 : I/O configuration for pin pio0_28 (R/W) */
-       volatile uint32_t pio1_29;   /* 0x0D4 : I/O configuration for pin pio0_29 (R/W) */
-       uint32_t reserved_1[1];
-       volatile uint32_t pio1_31;   /* 0x0DC : I/O configuration for pin pio0_31 (R/W) */
-};
-#define LPC_IO_CONTROL  ((struct lpc_io_control *) LPC_IOCON_BASE)
-
-/* FIXME : to be completed */
-#define LPC_IO_FUNC_ALT(x) ((x & 0x07) << 0)
-
-#define LPC_IO_MODE_INACTIVE  (0x00 << 3)
-#define LPC_IO_MODE_PULL_DOWN (0x01 << 3)
-#define LPC_IO_MODE_PULL_UP   (0x02 << 3)
-#define LPC_IO_MODE_REPEATER  (0x03 << 3)
-
-#define LPC_IO_HISTERESIS_EN  (0x01 << 5)
-#define LPC_IO_INVERTED  (0x01 << 6)
-
-#define LPC_IO_ANALOG    (0x00 << 7)
-#define LPC_IO_DIGITAL   (0x01 << 7)
-
-#define LPC_IO_FILTERING_DISABLE (0x01 << 8)
-
-#define LPC_IO_DRIVE_LOWCURENT  (0x00 << 9)
-#define LPC_IO_DRIVE_HIGHCURENT (0x01 << 9)
-
-#define LPC_IO_OPEN_DRAIN_ENABLE (0x01 << 10)
-
-#define LPC_IO_SAMPLE_MODE_BYP    (0x00 << 11)
-#define LPC_FILTER_ONE_CLK    1
-#define LPC_FILTER_TWO_CLK    2
-#define LPC_FILTER_THREE_CLK  3
-#define LPC_IO_SAMPLE_MODE(x)     ((x & 0x03) << 11)
-#define LPC_IO_SAMPLE_CLK_DIV(x)  ((x & 0x07) << 13)
-
-
-/***************************************************************************** */
-/*                     General Purpose Input/Output (GPIO)                     */
-/***************************************************************************** */
-/* General Purpose Input/Output (GPIO) */
-struct lpc_gpio
-{
-       volatile uint32_t data_dir;   /* 0x000 : Data direction Register (R/W) */
-       uint32_t reserved_0[31];
-       volatile uint32_t mask;       /* 0x080 : Pin mask, affects in, out, set, clear and toggle */
-       uint32_t reserved_1[31];
-       volatile uint32_t value;      /* 0x100 : Port data Register (R/-) */
-       uint32_t reserved_2[31];
-       volatile uint32_t masked_val; /* 0x180 : Port masked data Register (R/W) */
-       uint32_t reserved_3[31];
-       volatile uint32_t set;        /* 0x200 : Port output set Register (-/W) */
-       uint32_t reserved_4[31];
-       volatile uint32_t clear;      /* 0x280 : Port output clear Register (-/W) */
-       uint32_t reserved_5[31];
-       volatile uint32_t toggle;     /* 0x300 : Port output invert Register (-/W) */
-};
-#define LPC_GPIO_0      ((struct lpc_gpio *) (LPC_GPIO_BASE + 0x2000))
-#define LPC_GPIO_1      ((struct lpc_gpio *) (LPC_GPIO_BASE + 0x2004))
-
-#define LPC_GPIO_REGS(x)  ((struct lpc_gpio *) (LPC_GPIO_BASE + 0x2000 + ((x) * 4)))
-
-#define GPIO_DIR_IN 0
-#define GPIO_DIR_OUT 1
-
-#define LPC_GPIO_ALL_BYTES  ((uint8_t*) (LPC_GPIO_BASE + 0x0000))
-#define LPC_GPIO_0_BYTES  ((uint8_t*) (LPC_GPIO_BASE + 0x0000))
-#define LPC_GPIO_1_BYTES  ((uint8_t*) (LPC_GPIO_BASE + 0x0020))
-#define LPC_GPIO_ALL_WORDS  ((uint32_t*) (LPC_GPIO_BASE + 0x1000))
-#define LPC_GPIO_0_WORDS  ((uint32_t*) (LPC_GPIO_BASE + 0x1000))
-#define LPC_GPIO_1_WORDS  ((uint32_t*) (LPC_GPIO_BASE + 0x1080))
-
-/* General Purpose Input/Output (GPIO) : multiple ports access */
-#define LPC_NB_GPIO_PORTS 2
-struct lpc_gpio_all
-{
-       volatile uint32_t data_dir[LPC_NB_GPIO_PORTS];   /* 0x000 : Data direction Register (R/W) */
-       uint32_t reserved_0[32 - LPC_NB_GPIO_PORTS];
-       volatile uint32_t mask[LPC_NB_GPIO_PORTS];       /* 0x080 : Pin mask, affects in, out, set, clear and toggle */
-       uint32_t reserved_1[32 - LPC_NB_GPIO_PORTS];
-       volatile uint32_t value[LPC_NB_GPIO_PORTS];      /* 0x100 : Port data Register (R/-) */
-       uint32_t reserved_2[32 - LPC_NB_GPIO_PORTS];
-       volatile uint32_t masked_val[LPC_NB_GPIO_PORTS]; /* 0x180 : Port masked data Register (R/W) */
-       uint32_t reserved_3[32 - LPC_NB_GPIO_PORTS];
-       volatile uint32_t set[LPC_NB_GPIO_PORTS];        /* 0x200 : Port output set Register (-/W) */
-       uint32_t reserved_4[32 - LPC_NB_GPIO_PORTS];
-       volatile uint32_t clear[LPC_NB_GPIO_PORTS];      /* 0x280 : Port output clear Register (-/W) */
-       uint32_t reserved_5[32 - LPC_NB_GPIO_PORTS];
-       volatile uint32_t toggle[LPC_NB_GPIO_PORTS];     /* 0x300 : Port output invert Register (-/W) */
-};
-#define LPC_GPIO_ALL     ((struct lpc_gpio_all *) (LPC_GPIO_BASE + 0x2000))
-
-/***************************************************************************** */
-/*                     GPIO Interrupts Control                                 */
-/***************************************************************************** */
-
-struct lpc_gpio_pin_edge_interrupt
-{
-       volatile uint32_t mode;       /* 0x000 : Pin interrupt mode (level/edge) (R/W) */
-       volatile uint32_t rising_enable;       /* 0x004 : Rising edge interrupt enable (R/W) */
-       volatile uint32_t rising_enable_set;   /* 0x008 : Set above reg .... (-/W) */
-       volatile uint32_t rising_enable_clear; /* 0x00C : Clear above reg .... (-/W) */
-       volatile uint32_t falling_enable;        /* 0x010 : Falling edge interrupt enable (R/W) */
-       volatile uint32_t falling_enable_set;    /* 0x014 : Set above reg .... (-/W) */
-       volatile uint32_t falling_enable_clear;  /* 0x018 : Clear above reg .... (-/W) */
-       volatile uint32_t rising_edge_detected;  /* 0x01C : Rising edge detected (R/W) */
-       volatile uint32_t falling_edge_detected; /* 0x020 : Falling edge detected (R/W) */
-       volatile uint32_t status;     /* 0x024 : Int status / clear both edge detection status (R/W) */
-};
-#define LPC_GPIO_INT_EDGE      ((struct lpc_gpio_pin_edge_interrupt *) LPC_GPIO_INTR_BASE)
-
-struct lpc_gpio_pin_level_interrupt
-{
-       volatile uint32_t mode;       /* 0x000 : Pin interrupt mode (level/edge) (R/W) */
-       volatile uint32_t enable;     /* 0x004 : Level interrupt enable (R/W) */
-       volatile uint32_t enable_set;      /* 0x008 : Set above reg .... (-/W) */
-       volatile uint32_t enable_clear;    /* 0x00C : Clear above reg .... (-/W) */
-       volatile uint32_t active_level;    /* 0x010 : Set active level (R/W) */
-       volatile uint32_t set_active_high; /* 0x014 : Set active level to high (-/W) */
-       volatile uint32_t set_active_low;  /* 0x018 : Set active level to low (-/W) */
-       uint32_t reserved[2];
-       volatile uint32_t status_and_toggle; /* 0x024 : Int status / toggle level (R/W) */
-};
-#define LPC_GPIO_INT_LEVEL     ((struct lpc_gpio_pin_level_interrupt *) LPC_GPIO_INTR_BASE)
-
-#define LPC_GPIO_INT_MODE_EDGE    0
-#define LPC_GPIO_INT_MODE_LEVEL   1
-
-#define LPC_GPIO_INT(x)  (0x01 << (x & 0x07))
-
-struct group_gpio_int
-{
-       volatile uint32_t control;     /* 0x000 : Grouped interrupt control (R/W) */
-       uint32_t reserved_0[7];
-       volatile uint32_t polarity[2]; /* 0x020 - 0x024 : Port 0/1 pins polarity (R/W) */
-       uint32_t reserved_1[6];
-       volatile uint32_t enable[2];   /* 0x040 - 0x044 : Port 0/1 pins interrupt enable (R/W) */
-};
-#define LPC_GROUP0_GPIO_INT     ((struct group_gpio_int *) LPC_GPIO_GRP0_INT_BASE)
-#define LPC_GROUP1_GPIO_INT     ((struct group_gpio_int *) LPC_GPIO_GRP1_INT_BASE)
-
-
-
-/***************************************************************************** */
-/*                     Universal Asynchronous Receiver Transmitter             */
-/***************************************************************************** */
-/* Universal Asynchronous Receiver Transmitter (UART) */
-struct lpc_uart_func {
-       volatile uint32_t buffer; /* 0x000 : Transmit / Receiver Buffer Register (R/W) */
-       volatile uint32_t intr_enable; /* 0x004 : Interrupt Enable Register (R/W) */
-       volatile uint32_t intr_pending; /* 0x008 : Interrupt ID Register (R/-) */
-};
-struct lpc_uart_ctrl {
-       volatile uint32_t divisor_latch_lsb;  /* 0x000 : Divisor Latch LSB (R/W) */
-       volatile uint32_t divisor_latch_msb;  /* 0x004 : Divisor Latch MSB (R/W) */
-       volatile uint32_t fifo_ctrl;  /* 0x008 : Fifo Control Register (-/W) */
-};
-struct lpc_uart
-{
-       union {
-               struct lpc_uart_func func;
-               struct lpc_uart_ctrl ctrl;
-       };
-       volatile uint32_t line_ctrl;   /* 0x00C : Line Control Register (R/W) */
-       volatile uint32_t modem_ctrl;  /* 0x010 : Modem control Register (R/W) */
-       volatile const uint32_t line_status;   /* 0x014 : Line Status Register (R/ ) */
-       volatile const uint32_t modem_status;  /* 0x018 : Modem status Register (R/ ) */
-       volatile uint32_t scratch_pad;  /* 0x01C : Scratch Pad Register (R/W) */
-       volatile uint32_t auto_baud_ctrl;  /* 0x020 : Auto-baud Control Register (R/W) */
-       volatile uint32_t irda_ctrl;       /* 0x024 : UART IrDA Control Register (R/W) */
-       volatile uint32_t fractional_div;  /* 0x028 : Fractional Divider Register (R/W) */
-       volatile uint32_t oversampling;    /* 0x02C : Oversampling Register (R/W) */
-       volatile uint32_t transmit_enable; /* 0x030 : Transmit Enable Register (R/W) */
-       uint32_t reserved_1[3];
-       volatile uint32_t half_duplex_en;  /* 0x040 :  Half-duplex Enable Register (R/W) */
-       uint32_t reserved_2;
-       volatile uint32_t smart_card_ctrl;  /* 0x048 : Smart Card Interface Control Register (R/W) */
-       volatile uint32_t RS485_ctrl;       /* 0x04C : RS-485/EIA-485 Control Register (R/W) */
-       volatile uint32_t RS485_addr_match; /* 0x050 : RS-485/EIA-485 address match Register (R/W) */
-       volatile uint32_t RS485_dir_ctrl_delay;  /* 0x054 : RS-485/EIA-485 direction control delay Register (R/W) */
-       volatile uint32_t sync_ctrl;  /* 0x058 : Synchronous Mode Control Register (R/W) */
-};
-#define LPC_UART_0        ((struct lpc_uart *) LPC_UART0_BASE)
-
-/* Line Control Register */
-#define LPC_UART_5BIT          (0x00 << 0)
-#define LPC_UART_6BIT          (0x01 << 0)
-#define LPC_UART_7BIT          (0x02 << 0)
-#define LPC_UART_8BIT          (0x03 << 0)
-#define LPC_UART_1STOP         (0x00 << 2)
-#define LPC_UART_2STOP         (0x01 << 2)
-#define LPC_UART_NO_PAR        (0x00 << 3)
-#define LPC_UART_ODD_PAR      ((0x01 << 3) | (0x00 << 4))
-#define LPC_UART_EVEN_PAR      ((0x01 << 3) | (0x01 << 4))
-#define LPC_UART_ENABLE_DLAB   (0x01 << 7)
-/* FIFO Control Register */
-#define LPC_UART_FIFO_EN       (0x01 << 0)
-#define LPC_UART_TX_CLR        (0x01 << 1)
-#define LPC_UART_RX_CLR        (0x01 << 2)
-#define LPC_UART_FIFO_TRIG(x)  ((x & 0x03) << 6) /* 1 / 4 / 8 / 14 chars */
-/* Interrupt Enable Register */
-#define LPC_UART_RX_INT_EN     (0x01 << 0)
-#define LPC_UART_TX_INT_EN     (0x01 << 1)
-#define LPC_UART_RX_STATUS_INT_EN   (0x01 << 2)
-/* Interrupt status */
-#define LPC_UART_INT_MASK      (0x7 << 1)
-#define LPC_UART_INT_MODEM     (0x0 << 1)
-#define LPC_UART_INT_TX        (0x1 << 1)
-#define LPC_UART_INT_RX        (0x2 << 1)
-#define LPC_UART_INT_RX_STATUS (0x3 << 1)
-#define LPC_UART_INT_TIMEOUT   (0x6 << 1)
-/* RS485 Control */
-#define LPC_RS485_ENABLE       (0x1 << 0)
-#define LPC_RS485_RX_DIS       (0x1 << 1)
-#define LPC_RS485_AUTO_ADDR_EN (0x1 << 2)
-#define LPC_RS485_DIR_PIN_RTS  (0x0 << 3)
-#define LPC_RS485_DIR_PIN_DTR  (0x1 << 3)
-#define LPC_RS485_AUTO_DIR_EN  (0x1 << 4)
-#define LPC_RS485_DIR_CTRL_INV (0x1 << 5)
-/* RS485 */
-#define LPC_RS485_ADDR(x)  ((x) & 0xFF)
-#define LPC_RS485_DIR_DELAY(x)  ((x) & 0xFF)
-/* IrDA */
-#define LPC_IRDA_PULSEDIV(x)  (((x) & 0x07) << 3)
-
-
-/***************************************************************************** */
-/*                     Inter-Integrated Circuit                                */
-/***************************************************************************** */
-/* Inter-Integrated Circuit (I2C) */
-struct lpc_i2c
-{
-       volatile uint32_t ctrl_set;      /* 0x000 : I2C Control Set Register (R/W) */
-       volatile const uint32_t status;  /* 0x004 : I2C Status Register (R/-) */
-       volatile uint32_t data;          /* 0x008 : I2C Data Register (R/W) */
-       volatile uint32_t slave_addr_0;  /* 0x00C : I2C Slave Address Register 0 (R/W) */
-       volatile uint32_t clk_duty_high; /* 0x010 : SCL Duty Cycle Register High Half Word (R/W) */
-       volatile uint32_t clk_duty_low;  /* 0x014 : SCL Duty Cycle Register Low Half Word (R/W) */
-       volatile  uint32_t ctrl_clear;   /* 0x018 : I2C Control Clear Register (-/W) */
-       volatile uint32_t monitor_mode_ctrl;  /* 0x01C : Monitor mode control register (R/W) */
-       volatile uint32_t slave_addr_1;  /* 0x020 : I2C Slave Address Register 1 (R/W) */
-       volatile uint32_t slave_addr_2;  /* 0x024 : I2C Slave Address Register 2 (R/W) */
-       volatile uint32_t slave_addr_3;  /* 0x028 : I2C Slave Address Register 3 (R/W) */
-       volatile const uint32_t data_buffer;  /* 0x02C : Data buffer register (-/W) */
-       volatile uint32_t slave_addr_mask[4]; /* 0x030 to 0x03C : I2C Slave address mask register 0 to 3 (R/W) */
-};
-#define LPC_I2C0         ((struct lpc_i2c *) LPC_I2C0_BASE)
-
-#define I2C_ASSERT_ACK   (0x01 << 2)
-#define I2C_INTR_FLAG    (0x01 << 3)
-#define I2C_STOP_FLAG    (0x01 << 4)
-#define I2C_START_FLAG   (0x01 << 5)
-#define I2C_ENABLE_FLAG  (0x01 << 6)
-
-
-/***************************************************************************** */
-/*                     Synchronous Serial Communication                        */
-/***************************************************************************** */
-/* Synchronous Serial Communication (SSP) */
-struct lpc_ssp
-{
-       volatile uint32_t ctrl_0;        /* 0x000 : Control Register 0 (R/W) */
-       volatile uint32_t ctrl_1;        /* 0x004 : Control Register 1 (R/W) */
-       volatile uint32_t data;          /* 0x008 : Data Register (R/W) */
-       volatile const uint32_t status;  /* 0x00C : Status Registe (R/-) */
-       volatile uint32_t clk_prescale;  /* 0x010 : Clock Prescale Register (R/W) */
-       volatile uint32_t int_mask;      /* 0x014 : Interrupt Mask Set and Clear Register (R/W) */
-       volatile uint32_t raw_int_status;     /* 0x018 : Raw Interrupt Status Register (R/-) */
-       volatile uint32_t masked_int_status;  /* 0x01C : Masked Interrupt Status Register (R/-) */
-       volatile uint32_t int_clear;     /* 0x020 : SSPICR Interrupt Clear Register (-/W) */
-};
-#define LPC_SSP0        ((struct lpc_ssp *) LPC_SSP0_BASE)
-#define LPC_SSP1        ((struct lpc_ssp *) LPC_SSP1_BASE)
-
-/* SSP Control 0 register */
-#define LPC_SSP_DATA_WIDTH(x)    (((x) - 1) & 0x0F) /* Use 4 for 4 bits, 5 for 5 bits, .... */
-#define LPC_SSP_FRAME_SPI        (0x00 << 4)
-#define LPC_SSP_FRAME_TI         (0x01 << 4)
-#define LPC_SSP_FRAME_MICROWIRE  (0x02 << 4)
-#define LPC_SSP_SPI_CLK_LOW      (0x00 << 6)
-#define LPC_SSP_SPI_CLK_HIGH     (0x01 << 6)
-#define LPC_SSP_SPI_CLK_FIRST    (0x00 << 7)
-#define LPC_SSP_SPI_CLK_LAST     (0x01 << 7)
-#define LPC_SSP_SPI_CLK_RATE_DIV(x) (((x) & 0xFF) << 8)
-/* SSP Control 1 register */
-#define LPC_SSP_LOOPBACK_MODE      (0x01 << 0)
-#define LPC_SSP_ENABLE             (0x01 << 1)
-#define LPC_SSP_MASTER_MODE        (0x00 << 2)
-#define LPC_SSP_SLAVE_MODE         (0x01 << 2)
-#define LPC_SSP_SLAVE_OUT_DISABLE  (0x01 << 3)
-
-/* SSP Status register */
-#define LPC_SSP_ST_TX_EMPTY      (0x01 << 0)
-#define LPC_SSP_ST_TX_NOT_FULL   (0x01 << 1)
-#define LPC_SSP_ST_RX_NOT_EMPTY  (0x01 << 2)
-#define LPC_SSP_ST_RX_FULL       (0x01 << 3)
-#define LPC_SSP_ST_BUSY          (0x01 << 4)
-
-/* SSP Interrupt Mask, Raw, Status, Clear */
-#define LPC_SSP_INTR_RX_OVERRUN      (0x01 << 0)
-#define LPC_SSP_INTR_RX_TIMEOUT      (0x01 << 1)
-#define LPC_SSP_INTR_RX_HALF_FULL    (0x01 << 2)
-#define LPC_SSP_INTR_TX_HALF_EMPTY   (0x01 << 3)
-
-/* SSP DMA Control */
-#define LPC_SSP_RX_DMA_EN   (0x01 << 0)
-#define LPC_SSP_TX_DMA_EN   (0x01 << 1)
-
-
-
-/***************************************************************************** */
-/*                     Timer                                                   */
-/***************************************************************************** */
-/* Timer (TMR) */
-struct lpc_timer
-{
-       volatile uint32_t int_reg;        /* 0x000 : Interrupt Register (R/W) */
-       volatile uint32_t timer_ctrl;     /* 0x004 : Timer Control Register (R/W) */
-       volatile uint32_t timer_counter;  /* 0x008 : Timer Counter Register (R/W) */
-       volatile uint32_t prescale;       /* 0x00C : Prescale Register (R/W) */
-       volatile uint32_t prescale_counter;  /* 0x010 : Prescale Counter Register (R/W) */
-       volatile uint32_t match_ctrl;     /* 0x014 : Match Control Register (R/W) */
-       volatile uint32_t match_reg[4];    /* 0x018 : Match Register 0 to 3 (R/W) */
-       volatile uint32_t capture_ctrl;   /* 0x028 : Capture Control Register (R/W) */
-       volatile const uint32_t capture_reg[4]; /* 0x02C : Capture Register 0 to 3 (R/ ) */
-       volatile uint32_t external_match; /* 0x03C : External Match Register (R/W) */
-       uint32_t reserved_2[12];
-       volatile uint32_t count_ctrl;     /* 0x070 : Count Control Register (R/W) */
-       volatile uint32_t pwm_ctrl;       /* 0x074 : PWM Control Register (R/W) */
-};
-#define LPC_TMR16B0     ((struct lpc_timer *) LPC_TIMER0_BASE)
-#define LPC_TMR16B1     ((struct lpc_timer *) LPC_TIMER1_BASE)
-#define LPC_TMR32B0     ((struct lpc_timer *) LPC_TIMER2_BASE)
-#define LPC_TMR32B1     ((struct lpc_timer *) LPC_TIMER3_BASE)
-
-#define LPC_TIMER_COUNTER_ENABLE (1 << 0) /* CEN */
-#define LPC_TIMER_COUNTER_RESET  (1 << 1) /* CRST */
-
-/* Match internal configuration */
-#define LPC_TIMER_INTERRUPT_ON_MATCH   0x01
-#define LPC_TIMER_RESET_ON_MATCH       0x02
-#define LPC_TIMER_STOP_ON_MATCH        0x04
-#define LPC_TIMER_MATCH_ERASE(x)       (0x07 << ((x) * 3))
-#define LPC_TIMER_MATCH_SHIFT(x)       ((x) * 3)
-/* Capture internal configuration */
-#define LPC_TIMER_CAP_ON_RISING_EDGE   0x01
-#define LPC_TIMER_CAP_ON_FALLING_EDGE  0x02
-#define LPC_TIMER_INTERRUPT_ON_CAPTURE 0x04
-#define LPC_TIMER_CAPTURE_ERASE(x)     (0x07 << ((x) * 3))
-#define LPC_TIMER_CAPTURE_SHIFT(x)     ((x) * 3)
-/* Match external configuration */
-#define LPC_TIMER_NOTHING_ON_MATCH     0x00
-#define LPC_TIMER_CLEAR_ON_MATCH       0x01
-#define LPC_TIMER_SET_ON_MATCH         0x02
-#define LPC_TIMER_TOGGLE_ON_MATCH      0x03
-#define LPC_TIMER_EXT_MATCH0_SHIFT     4
-#define LPC_TIMER_EXT_MATCH1_SHIFT     6
-#define LPC_TIMER_EXT_MATCH2_SHIFT     8
-#define LPC_TIMER_EXT_MATCH3_SHIFT     10
-/* Counter */
-#define LPC_COUNTER_IS_TIMER           0x00
-#define LPC_COUNTER_INC_ON_RISING      0x01
-#define LPC_COUNTER_INC_ON_FALLING     0x02
-#define LPC_COUNTER_INC_ON_BOTH        0x03
-#define LPC_COUNTER_INC_INPUT_SHIFT    2
-#define LPC_COUNTER_INC_INPUT(x)       (((x) & 0x03) << LPC_COUNTER_INC_INPUT_SHIFT)
-#define LPC_COUNTER_CLEAR_ON_EVENT_EN  (0x01 << 4)
-#define LPC_COUNTER_CLEAR_ON_EVENT_SHIFT  5
-#define LPC_COUNTER_CLEAR_ON_CHAN0_RISE   0x00
-#define LPC_COUNTER_CLEAR_ON_CHAN0_FALL   0x01
-#define LPC_COUNTER_CLEAR_ON_CHAN1_RISE   0x02
-#define LPC_COUNTER_CLEAR_ON_CHAN1_FALL   0x03
-#define LPC_COUNTER_CLEAR_ON_CHAN2_RISE   0x04
-#define LPC_COUNTER_CLEAR_ON_CHAN2_FALL   0x05
-#define LPC_COUNTER_CLEAR_ON_CHAN3_RISE   0x06
-#define LPC_COUNTER_CLEAR_ON_CHAN3_FALL   0x07
-/* PWM */
-#define LPC_PWM_CHANNEL_ENABLE(x)    (0x01 << (x))
-
-
-
-/***************************************************************************** */
-/*                     Watchdog Timer                                          */
-/***************************************************************************** */
-/* Watchdog Timer (WDT) */
-struct lpc_watchdog
-{
-       volatile uint32_t mode;          /* 0x000 : Watchdog mode register (R/W) */
-       volatile uint32_t timer_const;   /* 0x004 : Watchdog timer constant register (R/W) */
-       volatile uint32_t feed_seqence;  /* 0x008 : Watchdog feed sequence register ( /W) */
-       volatile const uint32_t timer_value;  /* 0x00C : Watchdog timer value register (R/ ) */
-       volatile uint32_t clk_src_sel;   /* 0x010 : Wathdog Clock Source Selection Register (R/W) */
-       volatile uint32_t warning_int_compare; /* 0x014 : Watchdog Warning Interrupt compare value. */
-       volatile uint32_t window_compare;      /* 0x018 : Watchdog Window compare value. */
-};
-#define LPC_WDT         ((struct lpc_watchdog *) LPC_WDT_BASE)
-
-
-/***************************************************************************** */
-/*                     Analog-to-Digital Converter                             */
-/***************************************************************************** */
-/* Analog-to-Digital Converter (ADC) */
-struct lpc_adc
-{
-       volatile uint32_t ctrl;         /* 0x000 : A/D Control Register (R/W) */
-       volatile uint32_t global_data;  /* 0x004 : A/D Global Data Register (R/W) */
-       uint32_t reserved_0;
-       volatile uint32_t int_en;  /* 0x00C : A/D Interrupt Enable Register (R/W) */
-       volatile uint32_t data[8]; /* Offset: 0x010-0x02C A/D Channel 0..7 Data Register (R/W) */
-       volatile const uint32_t status; /* 0x030 : A/D Status Register (R/ ) */
-};
-#define LPC_ADC         ((struct lpc_adc *) LPC_ADC_BASE)
-
-/* ADC Control register bits */
-#define LPC_ADC_CTRL_MASK  0x0F0FFFFF
-/* LPC_ADC_CHANNEL_* are also used for interrupt register */
-#define LPC_ADC_CHANNEL_MASK (0xFF << 0)
-#define LPC_ADC_CHANNEL(x)  (0x01 << ((x) & 0x07))
-#define LPC_ADC_BURST     (0x01 << 16)
-
-#define LPC_ADC_10BITS  (0x00 << 17)
-#define LPC_ADC_9BITS   (0x01 << 17)
-#define LPC_ADC_8BITS   (0x02 << 17)
-#define LPC_ADC_7BITS   (0x03 << 17)
-#define LPC_ADC_6BITS   (0x04 << 17)
-#define LPC_ADC_5BITS   (0x05 << 17)
-#define LPC_ADC_4BITS   (0x06 << 17)
-#define LPC_ADC_3BITS   (0x07 << 17)
-#define LPC_ADC_BITS_MASK  (0x07 << 17)
-
-#define LPC_ADC_START_CONV_NOW  (0x01 << 24)
-enum lpc_adc_start_conv_events {
-       LPC_ADC_START_CONV_EDGE_CT16B0_CAP0 = 2,
-       LPC_ADC_START_CONV_EDGE_CT32B0_CAP0,
-       LPC_ADC_START_CONV_EDGE_CT32B0_MAT0,
-       LPC_ADC_START_CONV_EDGE_CT32B0_MAT1,
-       LPC_ADC_START_CONV_EDGE_CT16B0_MAT0,
-       LPC_ADC_START_CONV_EDGE_CT16B0_MAT1,
-};
-#define LPC_ADC_START_CONV_EVENT(x) (((x) & 0x7) << 24)
-#define LPC_ADC_START_EDGE_FALLING  (0x1 << 27)
-#define LPC_ADC_START_EDGE_RISING   (0x0 << 27)
-#define LPC_ADC_START_CONV_MASK (0x07 << 24)
-
-/* ADC Data register bits */
-#define LPC_ADC_RESULT_SHIFT  6
-#define LPC_ADC_RESULT_MASK   0x3FF
-#define LPC_ADC_OVERRUN    (0x01 << 30)
-#define LPC_ADC_CONV_DONE  (0x01 << 31)
-
-/* For more readability when selecting a channel number */
-#define LPC_ADC_NUM(x)    (x)
-
-
-/***************************************************************************** */
-/*                     USB (Universal Serial Bus)                              */
-/***************************************************************************** */
-/* USB Device Controller */
-struct lpc_usb_device
-{
-    volatile uint32_t dev_cmd_status;     /* 0x000 : USB Device Command and Status register (R/W) */
-    volatile uint32_t info;               /* 0x004 : USb Info register (R/W) */
-    volatile uint32_t ep_list_start;      /* 0x008 : USB EP Command and Status List start address (R/W) */
-    volatile uint32_t data_buff_start;    /* 0x00C : USB Data buffer start address (R/W) */
-    volatile uint32_t link_pm;            /* 0x010 : USB Link Power Management register (R/W) */
-    volatile uint32_t ep_skip;            /* 0x014 : USB Endpoint skip (R/W) */
-    volatile uint32_t ep_in_use;          /* 0x018 : USB Endpoint Buffer in use (R/W) */
-    volatile uint32_t ep_buff_config;     /* 0x01C : USB Endpoint Buffer Configuration register (R/W) */
-    volatile uint32_t intr_status;        /* 0x020 : USB interrupt status register (R/W) */
-    volatile uint32_t intr_enable;        /* 0x024 : USB interrupt enable register (R/W) */
-    volatile uint32_t set_intr_status;    /* 0x028 : USB set interrupt status register (R/W) */
-    volatile uint32_t intr_routing;       /* 0x02C : USB interrupt routing register (R/W) */
-       uint32_t reserved_0;
-    volatile uint32_t ep_toggle;          /* 0x034 : USB Endpoint toggle register (R/W) */
-};
-#define LPC_USB         ((struct lpc_usb_device *) LPC_USB_BASE)
-
-
-
-
-#endif  /* LPC_REGS_H */
index c987827..a7372f6 100644 (file)
 
 /* The "PIO" module gives access to the configuration of all the pins of the
  * micro-controller, whatever the function of the pin.
- * It has nothing related to GPIO function of the pins.
+ * It has nothing related to the GPIO function of the pins.
  */
 
-#include <stdint.h>
+#include "lib/stdint.h"
+#include "core/lpc_regs.h"
 
 struct pio {
     uint8_t port;  /* 0xFF indicates the end of a pin array */
@@ -56,6 +57,12 @@ void config_pio(const struct pio* pp, uint32_t mode);
 /* Configure a set (array) of pins in a single loop */
 void set_pins(const struct pio_config* pins);
 
+/* IO config clock */
+/* To change GPIO config the io config block must be powered on */
+void io_config_clk_on(void);
+void io_config_clk_off(void);
+
+
 /****************************************************************************/
 /*  GPIO Pins  */
 #define LPC_GPIO_0_0  {0,  0, 1}
@@ -280,4 +287,99 @@ void set_pins(const struct pio_config* pins);
 
 
 
+/***************************************************************************** */
+/*                     IO Control                                              */
+/***************************************************************************** */
+/* Pin Connect Block (IOCON) */
+struct lpc_io_control
+{
+       volatile uint32_t pio0_0;    /* 0x000 : I/O configuration for pin pio0_0 (R/W) */
+       volatile uint32_t pio0_1;    /* 0x004 : I/O configuration for pin pio0_1 (R/W) */
+       volatile uint32_t pio0_2;    /* 0x008 : I/O configuration for pin pio0_2 (R/W) */
+       volatile uint32_t pio0_3;    /* 0x00C : I/O configuration for pin pio0_3 (R/W) */
+       volatile uint32_t pio0_4;    /* 0x010 : I/O configuration for pin pio0_4 (R/W) */
+       volatile uint32_t pio0_5;    /* 0x014 : I/O configuration for pin pio0_5 (R/W) */
+       volatile uint32_t pio0_6;    /* 0x018 : I/O configuration for pin pio0_6 (R/W) */
+       volatile uint32_t pio0_7;    /* 0x01C : I/O configuration for pin pio0_7 (R/W) */
+       volatile uint32_t pio0_8;    /* 0x020 : I/O configuration for pin pio0_8 (R/W) */
+       volatile uint32_t pio0_9;    /* 0x024 : I/O configuration for pin pio0_9 (R/W) */
+       volatile uint32_t pio0_10;   /* 0x028 : I/O configuration for pin SWD0_10 (R/W) */
+       volatile uint32_t pio0_11;   /* 0x02C : I/O configuration for pin pio0_11 (R/W) */
+       volatile uint32_t pio0_12;   /* 0x030 : I/O configuration for pin pio0_12 (R/W) */
+       volatile uint32_t pio0_13;   /* 0x034 : I/O configuration for pin pio0_13 (R/W) */
+       volatile uint32_t pio0_14;   /* 0x038 : I/O configuration for pin pio0_14 (R/W) */
+       volatile uint32_t pio0_15;   /* 0x03C : I/O configuration for pin pio0_15 (R/W) */
+       volatile uint32_t pio0_16;   /* 0x040 : I/O configuration for pin pio0_16 (R/W) */
+       volatile uint32_t pio0_17;   /* 0x044 : I/O configuration for pin pio0_17 (R/W) */
+       volatile uint32_t pio0_18;   /* 0x048 : I/O configuration for pin pio0_18 (R/W) */
+       volatile uint32_t pio0_19;   /* 0x04C : I/O configuration for pin pio0_19 (R/W) */
+       volatile uint32_t pio0_20;   /* 0x050 : I/O configuration for pin pio0_20 (R/W) */
+       volatile uint32_t pio0_21;   /* 0x054 : I/O configuration for pin pio0_21 (R/W) */
+       volatile uint32_t pio0_22;   /* 0x058 : I/O configuration for pin pio0_22 (R/W) */
+       volatile uint32_t pio0_23;   /* 0x05C : I/O configuration for pin pio0_23 (R/W) */
+
+       volatile uint32_t pio1_0;    /* 0x060 : I/O configuration for pin pio1_0 (R/W) */
+       volatile uint32_t pio1_1;    /* 0x064 : I/O configuration for pin pio1_1 (R/W) */
+       volatile uint32_t pio1_2;    /* 0x068 : I/O configuration for pin pio1_2 (R/W) */
+       volatile uint32_t pio1_3;    /* 0x06C : I/O configuration for pin pio1_3 (R/W) */
+       volatile uint32_t pio1_4;    /* 0x070 : I/O configuration for pin pio1_4 (R/W) */
+       volatile uint32_t pio1_5;    /* 0x074 : I/O configuration for pin pio1_5 (R/W) */
+       volatile uint32_t pio1_6;    /* 0x078 : I/O configuration for pin pio1_6 (R/W) */
+       volatile uint32_t pio1_7;    /* 0x07C : I/O configuration for pin pio0_7 (R/W) */
+       volatile uint32_t pio1_8;    /* 0x080 : I/O configuration for pin pio0_8 (R/W) */
+       volatile uint32_t pio1_9;    /* 0x084 : I/O configuration for pin pio0_9 (R/W) */
+       volatile uint32_t pio1_10;   /* 0x088 : I/O configuration for pin SWD0_10 (R/W) */
+       volatile uint32_t pio1_11;   /* 0x08C : I/O configuration for pin pio0_11 (R/W) */
+       volatile uint32_t pio1_12;   /* 0x090 : I/O configuration for pin pio0_12 (R/W) */
+       volatile uint32_t pio1_13;   /* 0x094 : I/O configuration for pin pio0_13 (R/W) */
+       volatile uint32_t pio1_14;   /* 0x098 : I/O configuration for pin pio0_14 (R/W) */
+       volatile uint32_t pio1_15;   /* 0x09C : I/O configuration for pin pio0_15 (R/W) */
+       volatile uint32_t pio1_16;   /* 0x0A0 : I/O configuration for pin pio0_16 (R/W) */
+       volatile uint32_t pio1_17;   /* 0x0A4 : I/O configuration for pin pio0_17 (R/W) */
+       volatile uint32_t pio1_18;   /* 0x0A8 : I/O configuration for pin pio0_18 (R/W) */
+       volatile uint32_t pio1_19;   /* 0x0AC : I/O configuration for pin pio0_19 (R/W) */
+       volatile uint32_t pio1_20;   /* 0x0B0 : I/O configuration for pin pio0_20 (R/W) */
+       volatile uint32_t pio1_21;   /* 0x0B4 : I/O configuration for pin pio0_21 (R/W) */
+       volatile uint32_t pio1_22;   /* 0x0B8 : I/O configuration for pin pio0_22 (R/W) */
+       volatile uint32_t pio1_23;   /* 0x0BC : I/O configuration for pin pio0_23 (R/W) */
+       volatile uint32_t pio1_24;   /* 0x0C0 : I/O configuration for pin pio0_24 (R/W) */
+       volatile uint32_t pio1_25;   /* 0x0C4 : I/O configuration for pin pio0_25 (R/W) */
+       volatile uint32_t pio1_26;   /* 0x0C8 : I/O configuration for pin pio0_26 (R/W) */
+       volatile uint32_t pio1_27;   /* 0x0CC : I/O configuration for pin pio0_27 (R/W) */
+       volatile uint32_t pio1_28;   /* 0x0D0 : I/O configuration for pin pio0_28 (R/W) */
+       volatile uint32_t pio1_29;   /* 0x0D4 : I/O configuration for pin pio0_29 (R/W) */
+       uint32_t reserved_1[1];
+       volatile uint32_t pio1_31;   /* 0x0DC : I/O configuration for pin pio0_31 (R/W) */
+};
+#define LPC_IO_CONTROL  ((struct lpc_io_control *) LPC_IOCON_BASE)
+
+/* FIXME : to be completed */
+#define LPC_IO_FUNC_ALT(x) ((x & 0x07) << 0)
+
+#define LPC_IO_MODE_INACTIVE  (0x00 << 3)
+#define LPC_IO_MODE_PULL_DOWN (0x01 << 3)
+#define LPC_IO_MODE_PULL_UP   (0x02 << 3)
+#define LPC_IO_MODE_REPEATER  (0x03 << 3)
+
+#define LPC_IO_HISTERESIS_EN  (0x01 << 5)
+#define LPC_IO_INVERTED  (0x01 << 6)
+
+#define LPC_IO_ANALOG    (0x00 << 7)
+#define LPC_IO_DIGITAL   (0x01 << 7)
+
+#define LPC_IO_FILTERING_DISABLE (0x01 << 8)
+
+#define LPC_IO_DRIVE_LOWCURENT  (0x00 << 9)
+#define LPC_IO_DRIVE_HIGHCURENT (0x01 << 9)
+
+#define LPC_IO_OPEN_DRAIN_ENABLE (0x01 << 10)
+
+#define LPC_IO_SAMPLE_MODE_BYP    (0x00 << 11)
+#define LPC_FILTER_ONE_CLK    1
+#define LPC_FILTER_TWO_CLK    2
+#define LPC_FILTER_THREE_CLK  3
+#define LPC_IO_SAMPLE_MODE(x)     ((x & 0x03) << 11)
+#define LPC_IO_SAMPLE_CLK_DIV(x)  ((x & 0x07) << 13)
+
+
 #endif /* CORE_PIO_H */
index d0a3111..9ed62db 100644 (file)
 #ifndef CORE_SYSTEM_H
 #define CORE_SYSTEM_H
 
-#include <stdint.h>
-
-#include "core/lpc_regs_11u3x.h"
-#include "core/lpc_core_cm0.h"
-
-
-/* Error Values, from glibc errno.h and errno-base.h */
-#define EIO          5 /* Bad one: Input or Output error. */
-#define E2BIG        7 /* Argument list too long or Data size beyond buffer size */
-#define EAGAIN      11 /* Device already in use */
-#define EFAULT      14 /* Address error */
-#define EBUSY       16 /* Device or ressource Busy */
-#define ENODEV      19 /* No such device */
-#define EINVAL      22 /* Invalid argument */
-#define EBADFD      77 /* Device not initialized */
-#define EREMOTEIO  121 /* Device did not acknowledge */
-
-/* Note on error values for I2C :
- *  EIO : Bad one: Illegal start or stop, or illegal state in i2c state machine
- *  EFAULT : address above eeprom size
- *  EBUSY : Device or ressource Busy or Arbitration lost
- *  EREMOTEIO : Device did not acknowledge
- */
+#include "lib/stdint.h"
+
+#include "core/lpc_regs.h"
+#include "core/lpc_core.h"
+#include "core/watchdog.h"
+
 
 /***************************************************************************** */
 /*                       Power up defaults                                     */
 /***************************************************************************** */
-/* Change reset power state to our default, removing power from unused
- * interfaces */
+/* Change reset power state to our default, removing power from unused interfaces */
 void system_set_default_power_state(void);
 
-/* Configure all default pin functions for dtplug, even if modules or functions
- * are not used */
-void system_set_default_pins(void);
-
-/* Stop the watchdog */
-void stop_watchdog(void);
 
 /***************************************************************************** */
 /*                       Power                                                 */
@@ -70,6 +46,8 @@ void enter_deep_sleep(void);
 
 /* Power on or off a subsystem */
 void subsystem_power(uint32_t power_bit, uint32_t on_off);
+/* Check whether a subsystem is powered or not */
+uint8_t subsystem_powered(uint32_t power_bit);
 
 /* Configure the brown-out detection. */
 void system_brown_out_detection_config(uint32_t level);
@@ -102,10 +80,6 @@ void clock_config(uint32_t freq_sel, uint32_t clk_src);
 /* return current main clock in HZ */
 uint32_t get_main_clock(void);
 
-/* IO config clock */
-/* To change GPIO config the io config block must be powered on */
-void io_config_clk_on(void);
-void io_config_clk_off(void);
 
 /* This is mainly a debug feature, but can be used to provide a clock to an
  * external peripheral */
@@ -135,4 +109,213 @@ void msleep(uint32_t ms);
 void usleep(uint32_t us);
 
 
+
+
+/***************************************************************************** */
+/*                     System Configuration                                    */
+/***************************************************************************** */
+/* System Configuration (SYSCON) */
+struct lpc_sys_start_logic_ctrl
+{
+       volatile uint32_t edge_ctrl;  /* 0x00 : edge control Register 0 (R/W) */
+       volatile uint32_t signal_en;  /* 0x04 : signal enable Register 0 (R/W) */
+       volatile uint32_t reset;      /* 0x08 : reset Register 0  (-/W) */
+       volatile uint32_t status;     /* 0x0C : status Register 0 (R/-) */
+};
+struct lpc_sys_config
+{
+       volatile uint32_t sys_mem_remap;   /* 0x000 System memory remap (R/W) */
+       volatile uint32_t peripheral_reset_ctrl; /* 0x004 Peripheral reset control (R/W) */
+       volatile uint32_t sys_pll_ctrl;    /* 0x008 System PLL control (R/W) */
+       volatile uint32_t sys_pll_status;  /* 0x00C System PLL status (R/ ) */
+       volatile uint32_t usb_pll_ctrl;    /* 0x010 USB PLL control (R/W) */
+       volatile uint32_t usb_pll_status;  /* 0x014 USB PLL status (R/ ) */
+       uint32_t reserved_0[2];
+
+       volatile uint32_t sys_osc_ctrl;    /* 0x020 : System oscillator control (R/W) */
+       volatile uint32_t WDT_osc_ctrl;    /* 0x024 : Watchdog oscillator control (R/W) */
+       volatile uint32_t IRC_ctrl;        /* 0x028 : IRC control (R/W) */
+       uint32_t reserved_1[1];
+       volatile uint32_t sys_reset_status;    /* 0x030 : System reset status Register (R/ ) */
+       uint32_t reserved_2[3];
+       volatile uint32_t sys_pll_clk_sel;     /* 0x040 : System PLL clock source select (R/W) */
+       volatile uint32_t sys_pll_clk_upd_en;  /* 0x044 : System PLL clock source update enable (R/W) */
+       volatile uint32_t usb_pll_clk_sel;     /* 0x048 : USB PLL clock source select (R/W) */
+       volatile uint32_t usb_pll_clk_upd_en;  /* 0x04C : USB PLL clock source update enable (R/W) */
+       uint32_t reserved_3[8];
+
+       volatile uint32_t main_clk_sel;     /* 0x070 : Main clock source select (R/W) */
+       volatile uint32_t main_clk_upd_en;  /* 0x074 : Main clock source update enable (R/W) */
+       volatile uint32_t sys_AHB_clk_div;  /* 0x078 : System AHB clock divider (R/W) */
+       uint32_t reserved_4[1];
+       volatile uint32_t sys_AHB_clk_ctrl; /* 0x080 : System AHB clock control (R/W) */
+       uint32_t reserved_5[4];
+
+       volatile uint32_t ssp0_clk_div;   /* 0x094 : SSP0 clock divider (R/W) */
+       volatile uint32_t uart_clk_div;   /* 0x098 : UART0 clock divider (R/W) */
+       volatile uint32_t ssp1_clk_div;   /* 0x09C : SSP1 clock divider (R/W) */
+       uint32_t reserved_6a[8];
+       volatile uint32_t usb_clk_sel;    /* 0x0C0 : USB clock source select (R/W) */
+       volatile uint32_t usb_clk_upd_en; /* 0x0C4 : USB clock source update enable (R/W) */
+       volatile uint32_t usb_clk_div;    /* 0x0C8 : USB clock source divider (R/W) */
+       uint32_t reserved_6b[5];
+
+       volatile uint32_t clk_out_src_sel; /* 0x0E0 : CLKOUT clock source select (R/W) */
+       volatile uint32_t clk_out_upd_en;  /* 0x0E4 : CLKOUT clock source update enable (R/W) */
+       volatile uint32_t clk_out_div;     /* 0x0E8 : CLKOUT clock divider (R/W) */
+       uint32_t reserved_7[5];
+
+       volatile uint32_t por_captured_io_status[2];  /* 0x100 - 0x104 : POR captured PIO status 0 and 1 (R/ ) */
+       uint32_t reserved_8[11];
+
+       volatile uint32_t IO_config_clk_div[7]; /* 0x134 - 0x14C : Peripheral clocks 6 to 0 for glitch filter */
+
+       volatile uint32_t BOD_ctrl;      /* 0x150 : BOD control (R/W) */
+       volatile uint32_t sys_tick_cal;  /* 0x154 : System tick counter calibration (R/W) */
+       volatile uint32_t ahb_prio_set;  /* 0x158 : AHB priority setting (-/-) */
+       uint32_t reserved_9[5];
+       volatile uint32_t irq_latency;   /* 0x170 : IRQ delay, alloxs trade-off bw latency and determinism (R/W) */
+       volatile uint32_t int_nmi_cfg;   /* 0x174 : NMI interrupt source configuration control (R/W) */
+       volatile uint32_t gpio_int_sel[8]; /* 0x178 - 0x194 : GPIO Pin Interrupt Select 0 to 8 (R/W) */
+       volatile uint32_t usb_clk_ctrl;    /* 0x198 : USB Clock control (R/W) */
+       volatile uint32_t usb_clk_status;  /* 0x198 : USB Clock status (R/W) */
+       uint32_t reserved_10[24];
+
+       struct lpc_sys_start_logic_ctrl start_log_ctrl[2]; /* 0x200 to 0x20C and 0x210 to 0x21C :
+                                                                                                Start logic 0 and Start logic 1/peripheral interrupts */
+       uint32_t reserved_11[4];
+
+       volatile uint32_t powerdown_sleep_cfg;  /* 0x230 : Power-down states in Deep-sleep mode (R/W) */
+       volatile uint32_t powerdown_wake_cfg;  /* 0x234 : Power-down states after wake-up (R/W) */
+       volatile uint32_t powerdown_run_cfg;        /* 0x238 : Power-down configuration Register (R/W) */
+       uint32_t reserved_12[110];
+       volatile const uint32_t device_id;  /* 0x3F4 : Device ID (R/ ) */
+};
+
+#define LPC_SYS_CONFIG ((struct lpc_sys_config *) LPC_SYSCON_BASE)
+
+/* AHB control bits
+ *   0 (System (cortexM0, syscon, PMU, ...)) is a read only bit (system cannot be disabled)
+ */
+#define LPC_SYS_ABH_CLK_CTRL_SYSTEM     (1 <<  0) /* Read only */
+#define LPC_SYS_ABH_CLK_CTRL_ROM        (1 <<  1)
+#define LPC_SYS_ABH_CLK_CTRL_RAM        (1 <<  2)
+#define LPC_SYS_ABH_CLK_CTRL_FLASH_REG  (1 <<  3)
+#define LPC_SYS_ABH_CLK_CTRL_FLASH      (1 <<  4)
+#define LPC_SYS_ABH_CLK_CTRL_I2C        (1 <<  5)
+#define LPC_SYS_ABH_CLK_CTRL_GPIO       (1 <<  6)
+#define LPC_SYS_ABH_CLK_CTRL_CT16B0     (1 <<  7)
+#define LPC_SYS_ABH_CLK_CTRL_CT16B1     (1 <<  8)
+#define LPC_SYS_ABH_CLK_CTRL_CT32B0     (1 <<  9)
+#define LPC_SYS_ABH_CLK_CTRL_CT32B1     (1 << 10)
+#define LPC_SYS_ABH_CLK_CTRL_SSP0       (1 << 11)
+#define LPC_SYS_ABH_CLK_CTRL_UART0      (1 << 12)
+#define LPC_SYS_ABH_CLK_CTRL_ADC        (1 << 13)
+#define LPC_SYS_ABH_CLK_CTRL_USB        (1 << 14)
+#define LPC_SYS_ABH_CLK_CTRL_Watchdog   (1 << 15)
+#define LPC_SYS_ABH_CLK_CTRL_IO_CONFIG  (1 << 16)
+#define LPC_SYS_ABH_CLK_CTRL_SSP1       (1 << 18)
+#define LPC_SYS_ABH_CLK_CTRL_PINT       (1 << 19)
+#define LPC_SYS_ABH_CLK_CTRL_P0INT      (1 << 23)
+#define LPC_SYS_ABH_CLK_CTRL_P1INT      (1 << 24)
+#define LPC_SYS_ABH_CLK_CTRL_RAM1       (1 << 26)
+#define LPC_SYS_ABH_CLK_CTRL_USBRAM     (1 << 27)
+/* Helper */
+#define LPC_SYS_ABH_CLK_CTRL_MEM_BASE    0x0000001F
+#define LPC_SYS_ABH_CLK_CTRL_MEM_USB   (LPC_SYS_ABH_CLK_CTRL_RAM1 | LPC_SYS_ABH_CLK_CTRL_USBRAM)
+#define LPC_SYS_ABH_CLK_CTRL_MEM_ALL   (LPC_SYS_ABH_CLK_CTRL_MEM_BASE | LPC_SYS_ABH_CLK_CTRL_MEM_USB)
+
+#define LPC_SSP0_RESET_N       (1 << 0)
+#define LPC_I2C_RESET_N        (1 << 1)
+#define LPC_SSP1_RESET_N       (1 << 2)
+
+#define LPC_POWER_DOWN_IRC_OUT      (1 << 0)
+#define LPC_POWER_DOWN_IRC          (1 << 1)
+#define LPC_POWER_DOWN_FLASH        (1 << 2)
+#define LPC_POWER_DOWN_BOD          (1 << 3)
+#define LPC_POWER_DOWN_ADC          (1 << 4)
+#define LPC_POWER_DOWN_SYS_OSC      (1 << 5)
+#define LPC_POWER_DOWN_WDT_OSC      (1 << 6)
+#define LPC_POWER_DOWN_SYSPLL       (1 << 7)
+#define LPC_POWER_DOWN_USBPLL       (1 << 8)
+#define LPC_POWER_DOWN_USB          (1 << 10)
+                            /* write bit 11, 13, 14, 15 always as ones   and   bits 9 and 12 always as zeroes */
+#define LPC_POWER_DOWN_MASK(x)    (  ((x) | (1 << 11) | (0x07 << 13))   &   ~((1 << 9) | (1 << 12))  )
+
+#define LPC_DEEP_SLEEP_CFG_NOWDTLOCK_BOD_ON  0x0000FFF7
+#define LPC_DEEP_SLEEP_CFG_NOWDTLOCK_BOD_OFF 0x0000FFFF
+
+#define LPC_MAIN_CLK_SRC_IRC_OSC       0x00
+#define LPC_MAIN_CLK_SRC_PLL_IN        0x01
+#define LPC_MAIN_CLK_SRC_WATCHDOG_OSC  0x02
+#define LPC_MAIN_CLK_SRC_PLL_OUT       0x03
+
+#define LPC_PLL_CLK_SRC_IRC_OSC        0x00
+#define LPC_PLL_CLK_SRC_EXT_OSC        0x01
+
+#define LPC_CLKOUT_SRC_IRC_OSC       0x00
+#define LPC_CLKOUT_SRC_XTAL_OSC      0x01
+#define LPC_CLKOUT_SRC_WATCHDOG_OSC  0x02
+#define LPC_CLKOUT_SRC_MAIN_CLK      0x03
+
+#define LPC_SYSCLK_SRC_IRC_OSC       0x00
+#define LPC_SYSCLK_SRC_XTAL_OSC      0x01
+#define LPC_SYSCLK_SRC_PLL_INPUT     0x01
+#define LPC_SYSCLK_SRC_WATCHDOG_OSC  0x02
+#define LPC_SYSCLK_SRC_MAIN_CLK      0x03
+#define LPC_SYSCLK_SRC_PLL_OUTPUT    0x03
+
+#define LPC_USBPLLCLK_SRC_IRC_OSC    0x00
+#define LPC_USBPLLCLK_SRC_XTAL_OSC   0x01
+
+#define LPC_USBCLK_SRC_USB_PLL_OUT   0x00
+#define LPC_USBCLK_SRC_MAIN_CLK      0x01
+
+
+/***************************************************************************** */
+/*                  Flash Control                                              */
+/***************************************************************************** */
+/* Flash configuration */
+struct lpc_flash_control
+{
+       uint32_t reserved_0[4];
+       volatile uint32_t flash_cfg; /* 0x028 Flash configuration (R/W) */
+       uint32_t reserved_1[3];
+       /* Flash Memory Signature */
+       volatile uint32_t flash_signature_start;  /* 0x020 : Signature start address (R/W) */
+       volatile uint32_t flash_signature_end;    /* 0x024 : Signature end address (R/W) */
+       uint32_t reserved_2[1];
+       volatile uint32_t flash_signature[4];     /* 0x02C - 0x038 : Signature Words (R/-) */
+       uint32_t reserved_3[24];
+       /* EEPROM Memory Signature */
+       volatile uint32_t eeprom_signature_start;  /* 0x09C : Signature start address (R/W) */
+       volatile uint32_t eeprom_signature_end;    /* 0x0A0 : Signature end address (R/W) */
+       volatile uint32_t eeprom_signature;        /* 0x0A4 : Signature (R/-) */
+       uint32_t reserved_4[975];
+       /* Flash Memory Signature Generation */
+       volatile uint32_t flash_sig_gen_status;    /* 0xFE0 : Flash signature generation status (R/-) */
+       uint32_t reserved_5[1];
+       volatile uint32_t flash_sig_gen_stat_clr;  /* 0xFE8 : Flash signature generation status clear (R/W) */
+};
+#define LPC_FLASH_CONTROL ((struct lpc_flash_control *) LPC_FLASH_EEPROM_BASE)
+#define LPC_FLASH_CFG_MASK   0x03
+#define LPC_FLASH_CFG_SHIFT  0
+
+
+/***************************************************************************** */
+/*                     Power Management Unit                                   */
+/***************************************************************************** */
+/* Power Management Unit (PMU) */
+struct lpc_pm_unit
+{
+       volatile uint32_t power_ctrl;  /* 0x000 : Power control Register (R/W) */
+       volatile uint32_t gp_data[4];  /* 0x004 to 0x010 : General purpose Register 0 to 3 (R/W) */
+       volatile uint32_t system_config; /* 0x014 : System configuration register (R/W) */
+};
+#define LPC_PMU         ((struct lpc_pm_unit *) LPC_PMU_BASE)
+
+/* System config register */
+#define LPC_WAKEUP_PIN_HYST_MASK    (0x01 << 10)
+
+
 #endif /* CORE_SYSTEM_H */
index f643414..c1f0024 100644 (file)
 #ifndef CORE_SYSTICK_H
 #define CORE_SYSTICK_H
 
-#include <stdint.h>
+#include "lib/stdint.h"
+#include "core/lpc_regs.h"
 
 /***************************************************************************** */
 /*               System Tick Timer                                             */
 /***************************************************************************** */
 
+/* Driver for the internal systick timer of the LPC11u3x. */
+
 /* Start the system tick timer
  * Starting the systick timer also resets the internal tick counters.
  * If you need a value that goes beyond one start/stop cycle and accross resets,
@@ -102,4 +105,37 @@ int remove_systick_callback(void (*callback) (uint32_t));
 void usleep_short(uint32_t us);
 
 
-#endif /* CORE_SYSTEM_H */
+
+/***************************************************************************** */
+/*                    Cortex-M0 System Timer                                   */
+/***************************************************************************** */
+/* Cortex-M0 System Timer Registers */
+struct lpc_system_tick {
+       volatile uint32_t control;     /* 0x000 : SysTick Control and Status Register (R/W) */
+       volatile uint32_t reload_val;  /* 0x004 : SysTick Reload Value Register (R/W) */
+       volatile uint32_t value;       /* 0x008 : SysTick Current Value Register (R/W) */
+       volatile const uint32_t calibration;  /* 0x00C : SysTick Calibration Register (R/ ) */
+};
+#define LPC_SYSTICK  ((struct lpc_system_tick*) LPC_SYSTICK_BASE) /* SysTick configuration struct */
+
+/* SysTick Control / Status Register Definitions */
+#define LPC_SYSTICK_CTRL_COUNTFLAG  (1UL << 16)   /* SysTick CTRL: COUNTFLAG Mask */
+#define LPC_SYSTICK_CTRL_CLKSOURCE  (1UL << 2)    /* SysTick CTRL: CLKSOURCE Mask */
+#define LPC_SYSTICK_CTRL_CLK_MAIN   (1UL << 2)    /* SysTick CTRL: CLKSOURCE is main clock */
+#define LPC_SYSTICK_CTRL_TICKINT    (1UL << 1)    /* SysTick CTRL: TICKINT Mask */
+#define LPC_SYSTICK_CTRL_ENABLE     (1UL << 0)    /* SysTick CTRL: ENABLE Mask */
+
+/* SysTick Reload Register Definitions */
+#define LPC_SYSTICK_LOAD_RELOAD     (0xFFFFFFUL)  /* SysTick LOAD: RELOAD Mask */
+
+/* SysTick Current Register Definitions */
+#define LPC_SYSTICK_VAL_CURRENT     (0xFFFFFFUL)  /* SysTick VAL: CURRENT Mask */
+
+/* SysTick Calibration Register Definitions */
+#define LPC_SYSTICK_CALIB_NOREF     (1UL << 31)   /* SysTick CALIB: NOREF Mask */
+#define LPC_SYSTICK_CALIB_SKEW      (1UL << 30)   /* SysTick CALIB: SKEW Mask */
+#define LPC_SYSTICK_CALIB_TENMS     (0xFFFFFFUL)  /* SysTick CALIB: TENMS Mask */
+
+
+
+#endif /* CORE_SYSTICK_H */
diff --git a/include/core/watchdog.h b/include/core/watchdog.h
new file mode 100644 (file)
index 0000000..1b9dcc8
--- /dev/null
@@ -0,0 +1,166 @@
+/****************************************************************************
+ *   core/watchdog.h
+ *
+ * Watchdog support
+ *
+ * Copyright 2012 Nathael Pajani <nathael.pajani@ed3l.fr>
+ *
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ *************************************************************************** */
+
+/*
+ * This file implements support of the Windowed Watchdog (WWDT)
+ */
+
+
+#ifndef CORE_WATCHDOG_H
+#define CORE_WATCHDOG_H
+
+#include "lib/stdint.h"
+
+#define WDT_CLK_POWER_LOCK  (0x01 << 0)
+#define WDT_CLK_SRC_LOCK    (0x01 << 1)
+#define WDT_EN_LOCK         (0x01 << 2)
+#define WDT_TIMER_VAL_LOCK  (0x01 << 3)
+#define WDT_POWER_DOWN_LOCK (0x01 << 4)
+
+
+#define WDT_CLK_IRC 0
+#define WDT_CLK_WDTCLK 1
+struct wdt_config {
+       /* clk_sel is either 0 (IRC) or 1 (WDTCLK). The corresponding clock source will be powered on. */
+       uint8_t clk_sel;
+       uint8_t intr_mode_only; /* If set to 1, a watchdog timeout will trigger an interrupt instead of a reset */
+       void (*callback)(void);
+       uint32_t locks; /* Bitfield from WDT_*_LOCK defined in watchdog.h */
+       /* Number of clk_src clocks before the watchdog timer times out. Will be divided by 4 to give
+        *   the watchdog reload value */
+       uint32_t nb_clk;  /* 0x3FF to 0x03FFFFFF */
+       /* The next two values are relative to the timer value, not the number of clk_src clocks. */
+       uint32_t wdt_window; /* Watchdog window value : 0x100 to 0x00FFFFFF */
+       uint16_t wdt_warn; /* 0x00 to 0x3FF */
+};
+
+/***************************************************************************** */
+void watchdog_feed(void);
+
+
+/* Lock the watchdog clock source. Once the clock is locked, the configuration is
+ * permanent, there's no way to change it. Make all configuration steps before locking
+ * the watchdog Clock source.
+*/
+void watchdog_lock_clk_src(void);
+
+/* Lock the watchdog clock source power.
+ * Once locked, writes to the current watchdog clock power bits in powerdown_*_cfg will
+ *   have no effect.
+ * It is still possible to switch the watchdog clock source and turn of the clock if the
+ *   watchdog clock source has not been locked yet.
+ */
+void watchdog_lock_clk_src_power(void);
+
+/* Lock the watchdog timer value */
+void watchdog_lock_timer_val(void);
+
+/* Change the watchdog timer value, if not protected */
+void watchdog_set_timer_val(uint32_t nb_clk);
+
+/* Lock the Watchdog enable bit.
+ * It is still possible to disable the watchdog by setting it's clock to an unpowered
+ *   source if you did not lock the watchdog clock source and clock source power.
+ */
+void watchdog_lock_enable(void);
+
+/* Lock the watchdog and all related features.
+ * Calls all the other watchdog_lock_* functions (clk_src, clk_src_power, timer_val, enable).
+ */
+void watchdog_lock_full(void);
+
+/* Disable deep power down mode entry
+ * Calls to wfi() will allow entry in sleep and deep-sleep modes, but not deep-power-down mode.
+ */
+void watchdog_disable_power_down(void);
+
+/*
+ * Configure the watchdog.
+ * clk_sel is either 0 (IRC) or 1 (WDTCLK). The corresponding clock source will be powered on.
+ * Note : only WDTCLK is running in deep power down mode
+ * Note : protecting the clock source power will prevent turning off the IRC for power saving
+ *   if it is selected as main clock source.
+ */
+void watchdog_config(const struct wdt_config* wd_conf);
+
+
+/*
+ * Stop the watchdog
+ * This function can be used during system operation to stop the watchdog if it has not
+ *   been locked or protected against clock source modification, for example when entering
+ *   sleep or deep sleep.
+ * It will also try to power-down the oscilators if not used for main clock.
+ * Return 0 if a solution has been found to stop the watchdog, or -1 if watchdog is still
+ *   running after this call.
+ * TODO : Check this function, and implement the missing cases
+ */
+int stop_watchdog(void);
+
+
+/*
+ * Disable the watchdog
+ * This function can be used upon system startup to disable watchdog operation
+ */
+void startup_watchdog_disable(void);
+
+
+/***************************************************************************** */
+/*                     Watchdog Timer                                          */
+/***************************************************************************** */
+/* Watchdog Timer (WDT) */
+struct lpc_watchdog
+{
+       volatile uint32_t mode;          /* 0x000 : Watchdog mode register (R/W) */
+       volatile uint32_t timer_const;   /* 0x004 : Watchdog timer constant register (R/W) */
+       volatile uint32_t feed_seqence;  /* 0x008 : Watchdog feed sequence register ( /W) */
+       volatile const uint32_t timer_value;  /* 0x00C : Watchdog timer value register (R/ ) */
+       volatile uint32_t clk_src_sel;   /* 0x010 : Wathdog Clock Source Selection Register (R/W) */
+       volatile uint32_t warning_int_compare; /* 0x014 : Watchdog Warning Interrupt compare value. */
+       volatile uint32_t window_compare;      /* 0x018 : Watchdog Window compare value. */
+};
+#define LPC_WDT         ((struct lpc_watchdog *) LPC_WDT_BASE)
+
+#define LPC_WDT_TIMER_MAX  0xFFFFFF
+
+/* Mode register */
+#define LPC_WDT_EN                  (0x01 << 0)
+#define LPC_WDT_RESET_ON_TIMEOUT    (0x01 << 1)
+#define LPC_WDT_TIMEOUT_FLAG        (0x01 << 2)
+#define LPC_WDT_INTR_FLAG           (0x01 << 3)
+#define LPC_WDT_TIMER_VAL_PROTECT   (0x01 << 4) /* WDPROTECT */
+#define LPC_WDT_CLK_POWER_LOCK      (0x01 << 5) /* WDLOCKCLK */
+#define LPC_WDT_POWER_DOWN_DISABLE  (0x01 << 6) /* WDLOCKDP */
+#define LPC_WDT_EN_LOCK             (0x01 << 7) /* WDLOCKDP */
+
+/* Clk source */
+#define LPC_WDT_CLK_IRC       (0x00 <<  0)
+#define LPC_WDT_CLK_WDOSC     (0x01 <<  0)
+#define LPC_WDT_CLK_SRC_LOCK  (0x01 << 31)
+
+/* Warning Interupt */
+#define LPC_WDT_WARNINT_CMPVAL(x)  ((x) & 0x3FF)
+#define LPC_WDT_WARNINT_MAXVAL     0x3FF
+
+
+
+#endif /* CORE_WATCHDOG_H */
index d802293..2dac314 100644 (file)
 #define DRIVERS_ADC_H
 
 
-#include <stdint.h>
+
+#include "lib/stdint.h"
+#include "core/lpc_regs.h"
 
 /***************************************************************************** */
 /*                Analog to Digital Converter (ADC)                            */
 /***************************************************************************** */
 
-enum adc_events {
-       /* CT32B0 */
-       ADC_CONV_ON_CT32B0_CAP0_RISING,
-       ADC_CONV_ON_CT32B0_CAP0_FALLING,
-       ADC_CONV_ON_CT32B0_MAT0_RISING,
-       ADC_CONV_ON_CT32B0_MAT0_FALLING,
-       ADC_CONV_ON_CT32B0_MAT1_RISING,
-       ADC_CONV_ON_CT32B0_MAT1_FALLING,
-       /* CT16B0 */
-       ADC_CONV_ON_CT16B0_CAP0_RISING,
-       ADC_CONV_ON_CT16B0_CAP0_FALLING,
-       ADC_CONV_ON_CT16B0_MAT0_RISING,
-       ADC_CONV_ON_CT16B0_MAT0_FALLING,
-       ADC_CONV_ON_CT16B0_MAT1_RISING,
-       ADC_CONV_ON_CT16B0_MAT1_FALLING,
-};
+/* ADC driver for the integrated ADC module of the LPC11u3x.
+ * Refer to LPC11u3x documentation (UM10462.pdf) for more information.
+ */
+
+#define NB_ADC_CHANNELS  8
+#define NB_ADC_SEQUENCES 1
 
+#define LPC_ADC_SEQ(x)  0
 
-/* Read the conversion from the given channel (0 to 7)
+
+/* Read the conversion from the given channel
  * This function reads the conversion value directly in the data register and
  * always returns a value.
- * Return 1 if the value is a new one, else return 0.
- * Return -1 if channel does not exist
+ * Return 0 if the value is a new one and no overrun occured.
+ * Return -EINVAL if channel does not exist
+ * Retuen 1 if the value is an old one
+ * Return 2 if an overrun occured
  */
-int adc_get_value(uint16_t * val, int channel);
+int adc_get_value(uint16_t * val, uint8_t channel);
 
 /* Start a conversion on the given channel (0 to 7)
  * Unsupported yet : Set use_int to 1 to have your interrupt callback called upon conversion done.
  */
-void adc_start_convertion_once(unsigned int channel, int use_int);
+void adc_start_convertion_once(uint8_t channel, uint8_t seq_num, uint8_t use_int);
 
 /* Start burst conversions.
  * channels is a bit mask of requested channels.
- * Use LPC_ADC_CHANNEL(x) (x = 0 .. 7) for channels selection.
+ * Use ADC_MCH(x) (x = 0 .. 7) for channels selection.
  */
-void adc_start_burst_conversion(uint8_t channels);
+void adc_start_burst_conversion(uint16_t channels, uint8_t seq_num);
+void adc_stop_burst_conversion(uint8_t seq_num);
+
 
+enum lpc_adc_start_conv_events {
+       LPC_ADC_START_CONV_EDGE_CT16B0_CAP0 = 2,
+       LPC_ADC_START_CONV_EDGE_CT32B0_CAP0,
+       LPC_ADC_START_CONV_EDGE_CT32B0_MAT0,
+       LPC_ADC_START_CONV_EDGE_CT32B0_MAT1,
+       LPC_ADC_START_CONV_EDGE_CT16B0_MAT0,
+       LPC_ADC_START_CONV_EDGE_CT16B0_MAT1,
+};
 /* This should be used to configure conversion start on falling or rising edges of
  * some signals, or on timer for burst conversions.
  */
-void adc_prepare_conversion_on_event(uint8_t channels, uint8_t event, int use_int);
+void adc_prepare_conversion_on_event(uint16_t channels, uint8_t seq_num, uint8_t event,
+                                                                               uint8_t use_int, uint32_t mode);
+
+/* Software trigger of the given configured sequence.
+ * Note : If the sequence was configured for triggering on an external event, it won't be anymore.
+ */
+void adc_trigger_sequence_conversion(uint8_t seq_num);
+
+
+/***************************************************************************** */
+/*   ADC Setup : private part : Clocks, Pins, Power and Mode   */
+void adc_on(void (*adc_callback)(uint32_t));
+void adc_off(void);
 
 /* Change The ADC resolution.
  * Use defines from lpc_regs_11xx.h to specify the bit width for the convertion.
@@ -78,10 +96,54 @@ int adc_set_resolution(int bits);
 
 
 /***************************************************************************** */
-/*   ADC Setup : private part : Clocks, Pins, Power and Mode   */
-void adc_clk_update(void);
-void adc_on(void);
-void adc_off(void);
+/*                     Analog-to-Digital Converter                             */
+/***************************************************************************** */
+/* Analog-to-Digital Converter (ADC) */
+struct lpc_adc
+{
+       volatile uint32_t ctrl;         /* 0x000 : A/D Control Register (R/W) */
+       volatile uint32_t global_data;  /* 0x004 : A/D Global Data Register (R/W) */
+       uint32_t reserved_0;
+       volatile uint32_t int_en;  /* 0x00C : A/D Interrupt Enable Register (R/W) */
+       volatile uint32_t data[8]; /* Offset: 0x010-0x02C A/D Channel 0..7 Data Register (R/W) */
+       volatile const uint32_t status; /* 0x030 : A/D Status Register (R/ ) */
+};
+#define LPC_ADC_REGS      ((struct lpc_adc *) LPC_ADC_BASE)
+
+/* ADC Control register bits */
+#define LPC_ADC_CTRL_MASK  0x0F01FFFF
+/* ADC_MCH_* are also used for interrupt register */
+#define ADC_MCH_MASK    (0xFF << 0)
+#define ADC_MCH(x)      (0x01 << ((x) & 0x07))
+#define LPC_ADC_BURST   (0x01 << 16)
+
+#define LPC_ADC_10BITS  (0x00 << 17)
+#define LPC_ADC_9BITS   (0x01 << 17)
+#define LPC_ADC_8BITS   (0x02 << 17)
+#define LPC_ADC_7BITS   (0x03 << 17)
+#define LPC_ADC_6BITS   (0x04 << 17)
+#define LPC_ADC_5BITS   (0x05 << 17)
+#define LPC_ADC_4BITS   (0x06 << 17)
+#define LPC_ADC_3BITS   (0x07 << 17)
+#define LPC_ADC_BITS_MASK  (0x07 << 17)
+
+
+#define LPC_ADC_START_CONV_MASK (0x07 << 24)
+#define LPC_ADC_START_CONV_NOW  (0x01 << 24)
+#define LPC_ADC_START_CONV_EVENT(x) (((x) & 0x7) << 24)
+#define LPC_ADC_START_EDGE_FALLING  (0x1 << 27)
+#define LPC_ADC_START_EDGE_RISING   (0x0 << 27)
+#define LPC_ADC_ADDITIONAL_MODE_MASK (0x1 << 27)
+
+/* ADC Data register bits */
+#define LPC_ADC_RESULT_SHIFT  6
+#define LPC_ADC_RESULT_MASK   0x3FF
+#define LPC_ADC_OVERRUN    (0x01 << 30)
+#define LPC_ADC_CONV_DONE  (0x01 << 31)
+
+/* For more readability when selecting a channel number */
+#define LPC_ADC(x)    (x)
+
 
 #endif /* DRIVERS_ADC_H */
 
diff --git a/include/drivers/countertimers.h b/include/drivers/countertimers.h
new file mode 100644 (file)
index 0000000..646a691
--- /dev/null
@@ -0,0 +1,116 @@
+/****************************************************************************
+ *  drivers/countertimers.h
+ *
+ * Copyright 2012-2016 Nathael Pajani <nathael.pajani@ed3l.fr>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ *************************************************************************** */
+
+#ifndef DRIVERS_COUNTER_TIMERS_H
+#define DRIVERS_COUNTER_TIMERS_H
+
+
+#include "lib/stdint.h"
+#include "core/lpc_regs.h"
+
+/***************************************************************************** */
+/*                  Counter Timer                                              */
+/***************************************************************************** */
+/* Timers driver for the integrated timers of the LPC11u3x.
+ * The LPC11u3x has two 16bits timers and two 32bits timers.
+ * Refer to LPC11u3x documentation (UM10462.pdf) for more information.
+ */
+#define NUM_COUNTERTIMERS     4
+#define NUM_COUNTERTIMERS_CHANS  4
+#define NUM_COUNTERTIMERS_16B_PWM_CHANS 2
+#define NUM_COUNTERTIMERS_32B_PWM_CHANS 4
+
+/* Timer (TMR) */
+struct lpc_timer
+{
+       volatile uint32_t int_reg;        /* 0x000 : Interrupt Register (R/W) */
+       volatile uint32_t timer_ctrl;     /* 0x004 : Timer Control Register (R/W) */
+       volatile uint32_t timer_counter;  /* 0x008 : Timer Counter Register (R/W) */
+       volatile uint32_t prescale;       /* 0x00C : Prescale Register (R/W) */
+       volatile uint32_t prescale_counter;  /* 0x010 : Prescale Counter Register (R/W) */
+       volatile uint32_t match_ctrl;     /* 0x014 : Match Control Register (R/W) */
+       volatile uint32_t match_reg[4];    /* 0x018 : Match Register 0 to 3 (R/W) */
+       volatile uint32_t capture_ctrl;   /* 0x028 : Capture Control Register (R/W) */
+       volatile const uint32_t capture_reg[4]; /* 0x02C : Capture Register 0 to 3 (R/ ) */
+       volatile uint32_t external_match; /* 0x03C : External Match Register (R/W) */
+       uint32_t reserved_2[12];
+       volatile uint32_t count_ctrl;     /* 0x070 : Count Control Register (R/W) */
+       volatile uint32_t pwm_ctrl;       /* 0x074 : PWM Control Register (R/W) */
+};
+#define LPC_TMR16B0     ((struct lpc_timer *) LPC_TIMER0_BASE)
+#define LPC_TMR16B1     ((struct lpc_timer *) LPC_TIMER1_BASE)
+#define LPC_TMR32B0     ((struct lpc_timer *) LPC_TIMER2_BASE)
+#define LPC_TMR32B1     ((struct lpc_timer *) LPC_TIMER3_BASE)
+#define LPC_TIMER_REGS(x)  ((struct lpc_timer *) (LPC_TIMER0_BASE + ((x) * 0x4000)))
+
+
+#define LPC_TIMER_COUNTER_ENABLE (1 << 0) /* CEN */
+#define LPC_TIMER_COUNTER_RESET  (1 << 1) /* CRST */
+
+
+/* Match internal configuration */
+#define LPC_TIMER_INTERRUPT_ON_MATCH   0x01
+#define LPC_TIMER_RESET_ON_MATCH       0x02
+#define LPC_TIMER_STOP_ON_MATCH        0x04
+#define LPC_TIMER_INT_RESET_AND_STOP_ON_MATCH  \
+                       (LPC_TIMER_INTERRUPT_ON_MATCH | LPC_TIMER_RESET_ON_MATCH | LPC_TIMER_STOP_ON_MATCH)
+#define LPC_TIMER_MATCH_SHIFT(x)       (((x) & 0x03) * 3)
+#define LPC_TIMER_MATCH_ERASE(x)       (0x07 << LPC_TIMER_MATCH_SHIFT(x))
+
+/* Capture internal configuration */
+#define LPC_TIMER_CAP_ON_RISING_EDGE   0x01
+#define LPC_TIMER_CAP_ON_FALLING_EDGE  0x02
+#define LPC_TIMER_INTERRUPT_ON_CAPTURE 0x04
+#define LPC_TIMER_CAPTURE_SHIFT(x)     (((x) & 0x03) * 3)
+#define LPC_TIMER_CAPTURE_ERASE(x)     (0x07 << LPC_TIMER_CAPTURE_SHIFT(x))
+
+/* Match external configuration */
+#define LPC_TIMER_NOTHING_ON_MATCH     0x00
+#define LPC_TIMER_CLEAR_ON_MATCH       0x01
+#define LPC_TIMER_SET_ON_MATCH         0x02
+#define LPC_TIMER_TOGGLE_ON_MATCH      0x03
+#define LPC_TIMER_EXT_MATCH_SHIFT(x)   (((x) * 2)  + 4)
+#define LPC_TIMER_EXT_MATCH_ERASE(x)   (0x03 << LPC_TIMER_EXT_MATCH_SHIFT(x))
+
+/* Counter */
+#define LPC_COUNTER_IS_TIMER           0x00
+#define LPC_COUNTER_INC_ON_RISING      0x01
+#define LPC_COUNTER_INC_ON_FALLING     0x02
+#define LPC_COUNTER_INC_ON_BOTH        0x03
+#define LPC_COUNTER_INC_INPUT_SHIFT    2
+#define LPC_COUNTER_INC_INPUT(x)       (((x) & 0x03) << LPC_COUNTER_INC_INPUT_SHIFT)
+#define LPC_COUNTER_CLEAR_ON_EVENT_EN  (0x01 << 4)
+#define LPC_COUNTER_CLEAR_ON_EVENT_SHIFT  5
+#define LPC_COUNTER_CLEAR_ON_CHAN0_RISE   0x00
+#define LPC_COUNTER_CLEAR_ON_CHAN0_FALL   0x01
+#define LPC_COUNTER_CLEAR_ON_CHAN1_RISE   0x02
+#define LPC_COUNTER_CLEAR_ON_CHAN1_FALL   0x03
+#define LPC_COUNTER_CLEAR_ON_CHAN2_RISE   0x04
+#define LPC_COUNTER_CLEAR_ON_CHAN2_FALL   0x05
+#define LPC_COUNTER_CLEAR_ON_CHAN3_RISE   0x06
+#define LPC_COUNTER_CLEAR_ON_CHAN3_FALL   0x07
+
+/* PWM */
+#define LPC_PWM_CHANNEL_ENABLE(x)    (0x01 << ((x) & 0x03))
+
+
+#endif /* DRIVERS_COUNTER_TIMERS_H */
+
+
index 8534bee..5c464d6 100644 (file)
  *
  *************************************************************************** */
 
+/***************************************************************************** */
+/*                GPIOs and GPIO Interrupts                                    */
+/***************************************************************************** */
+
+/* Driver for GPIO configuration and access (including GPIO interrupts) on the LPC11u3x.
+ * Refer to LPC11u3x documentation (UM10462.pdf) for more information.
+ */
+
 #ifndef DRIVERS_GPIO_H
 #define DRIVERS_GPIO_H
 
 
-#include <stdint.h>
+#include "lib/stdint.h"
+#include "core/lpc_regs.h"
 #include "core/pio.h"
 
 
+
+/***************************************************************************** */
+/*                     General Purpose Input/Output (GPIO)                     */
+/***************************************************************************** */
+/* General Purpose Input/Output (GPIO) */
+struct lpc_gpio
+{
+       volatile uint32_t data_dir;   /* 0x000 : Data direction Register (R/W) */
+       uint32_t reserved_0[31];
+       volatile uint32_t mask;       /* 0x080 : Pin mask, affects in, out, set, clear and toggle */
+       uint32_t reserved_1[31];
+       volatile uint32_t value;      /* 0x100 : Port data Register (R/-) */
+       uint32_t reserved_2[31];
+       volatile uint32_t masked_val; /* 0x180 : Port masked data Register (R/W) */
+       uint32_t reserved_3[31];
+       volatile uint32_t set;        /* 0x200 : Port output set Register (-/W) */
+       uint32_t reserved_4[31];
+       volatile uint32_t clear;      /* 0x280 : Port output clear Register (-/W) */
+       uint32_t reserved_5[31];
+       volatile uint32_t toggle;     /* 0x300 : Port output invert Register (-/W) */
+};
+#define LPC_GPIO_0      ((struct lpc_gpio *) (LPC_GPIO_BASE + 0x2000))
+#define LPC_GPIO_1      ((struct lpc_gpio *) (LPC_GPIO_BASE + 0x2004))
+
+#define LPC_GPIO_REGS(x)  ((struct lpc_gpio *) (LPC_GPIO_BASE + 0x2000 + ((x) * 4)))
+
+#define LPC_GPIO_ALL_BYTES  ((uint8_t*) (LPC_GPIO_BASE + 0x0000))
+#define LPC_GPIO_0_BYTES  ((uint8_t*) (LPC_GPIO_BASE + 0x0000))
+#define LPC_GPIO_1_BYTES  ((uint8_t*) (LPC_GPIO_BASE + 0x0020))
+#define LPC_GPIO_ALL_WORDS  ((uint32_t*) (LPC_GPIO_BASE + 0x1000))
+#define LPC_GPIO_0_WORDS  ((uint32_t*) (LPC_GPIO_BASE + 0x1000))
+#define LPC_GPIO_1_WORDS  ((uint32_t*) (LPC_GPIO_BASE + 0x1080))
+
+/* General Purpose Input/Output (GPIO) : multiple ports access */
+#define LPC_NB_GPIO_PORTS 2
+struct lpc_gpio_all
+{
+       volatile uint32_t data_dir[LPC_NB_GPIO_PORTS];   /* 0x000 : Data direction Register (R/W) */
+       uint32_t reserved_0[32 - LPC_NB_GPIO_PORTS];
+       volatile uint32_t mask[LPC_NB_GPIO_PORTS];       /* 0x080 : Pin mask, affects in, out, set, clear and toggle */
+       uint32_t reserved_1[32 - LPC_NB_GPIO_PORTS];
+       volatile uint32_t value[LPC_NB_GPIO_PORTS];      /* 0x100 : Port data Register (R/-) */
+       uint32_t reserved_2[32 - LPC_NB_GPIO_PORTS];
+       volatile uint32_t masked_val[LPC_NB_GPIO_PORTS]; /* 0x180 : Port masked data Register (R/W) */
+       uint32_t reserved_3[32 - LPC_NB_GPIO_PORTS];
+       volatile uint32_t set[LPC_NB_GPIO_PORTS];        /* 0x200 : Port output set Register (-/W) */
+       uint32_t reserved_4[32 - LPC_NB_GPIO_PORTS];
+       volatile uint32_t clear[LPC_NB_GPIO_PORTS];      /* 0x280 : Port output clear Register (-/W) */
+       uint32_t reserved_5[32 - LPC_NB_GPIO_PORTS];
+       volatile uint32_t toggle[LPC_NB_GPIO_PORTS];     /* 0x300 : Port output invert Register (-/W) */
+};
+#define LPC_GPIO_ALL     ((struct lpc_gpio_all *) (LPC_GPIO_BASE + 0x2000))
+
+
 /***************************************************************************** */
 /*   Public access to GPIO setup   */
 
 
+enum gpio_ports {
+       GPIO_PORT0 = 0,
+       GPIO_PORT1,
+};
+
+#define GPIO_DIR_IN 0
+#define GPIO_DIR_OUT 1
+
 enum gpio_interrupt_senses {
        EDGES_BOTH = 0,
        EDGE_FALLING,
@@ -38,26 +109,10 @@ enum gpio_interrupt_senses {
        LEVEL_LOW,
 };
 
-/* GPIO Interrupts */
-/* Add a callback on a GPIO interrupt.
- * This call will configure the GPIO (call to config_pio()), set it as input and
- * activate the interrupt on the given 'sense' event. use the gpio_interrupt_senses
- * enum for 'sense' values.
- * The callback will receive the pin number as argument (but not the port number).
- * Note :
- *   The interrupt hanlers are not efficient if the pin is not a low numbered one (require
- *   32 shifts + test for pin number 31).
- *   Use them if you place the signals generating interrupts on low numbered pins.
- *   When possible, get in touch with the people doing the electronic design, or change
- *   the handlers in drivers/gpio.c
- */
-int set_gpio_callback(void (*callback) (uint32_t), uint8_t irq, const struct pio* gpio, uint8_t sense);
-void remove_gpio_callback(uint8_t irq);
-
-
 
 /* GPIO Activation */
 void gpio_on(void);
+
 void gpio_off(void);
 
 #define gpio_dir_in(gpio) \
@@ -85,6 +140,18 @@ void gpio_off(void);
        gpio_port->clear = (1 << gpio.pin);\
 }
 
+#define gpio_toggle(gpio) \
+{ \
+       struct lpc_gpio* gpio_port = LPC_GPIO_REGS(gpio.port); \
+       gpio_port->toggle = (1 << gpio.pin);\
+}
+
+static inline uint32_t gpio_read(const struct pio gpio)
+{
+       struct lpc_gpio* gpio_port = LPC_GPIO_REGS(gpio.port);
+       return (gpio_port->value & (1 << gpio.pin));
+}
+
 
 /* GPIO Configuration
  * This function calls the config_pio() function for the gpio with the given
@@ -95,4 +162,67 @@ void gpio_off(void);
 void config_gpio(const struct pio* gpio, uint32_t mode, uint8_t dir, uint8_t ini_val);
 
 
+/* GPIO Interrupts */
+/* Add a callback on a GPIO interrupt.
+ * This call will configure the GPIO (call to config_pio()), set it as input and
+ * activate the interrupt on the given 'sense' event. use the gpio_interrupt_senses
+ * enum for 'sense' values.
+ * The callback will receive the irq number as argument.
+ * Returns the interrupt number if OK, or a negative value in case of error..
+ */
+int set_gpio_callback(void (*callback) (uint32_t), const struct pio* gpio, uint8_t sense);
+void remove_gpio_callback(uint8_t irq);
+
+
+
+/***************************************************************************** */
+/*                     GPIO Interrupts Control                                 */
+/***************************************************************************** */
+
+struct lpc_gpio_pin_edge_interrupt
+{
+       volatile uint32_t mode;       /* 0x000 : Pin interrupt mode (level/edge) (R/W) */
+       volatile uint32_t rising_enable;       /* 0x004 : Rising edge interrupt enable (R/W) */
+       volatile uint32_t rising_enable_set;   /* 0x008 : Set above reg .... (-/W) */
+       volatile uint32_t rising_enable_clear; /* 0x00C : Clear above reg .... (-/W) */
+       volatile uint32_t falling_enable;        /* 0x010 : Falling edge interrupt enable (R/W) */
+       volatile uint32_t falling_enable_set;    /* 0x014 : Set above reg .... (-/W) */
+       volatile uint32_t falling_enable_clear;  /* 0x018 : Clear above reg .... (-/W) */
+       volatile uint32_t rising_edge_detected;  /* 0x01C : Rising edge detected (R/W) */
+       volatile uint32_t falling_edge_detected; /* 0x020 : Falling edge detected (R/W) */
+       volatile uint32_t status;     /* 0x024 : Int status / clear both edge detection status (R/W) */
+};
+#define LPC_GPIO_INT_EDGE      ((struct lpc_gpio_pin_edge_interrupt *) LPC_GPIO_INTR_BASE)
+
+struct lpc_gpio_pin_level_interrupt
+{
+       volatile uint32_t mode;       /* 0x000 : Pin interrupt mode (level/edge) (R/W) */
+       volatile uint32_t enable;     /* 0x004 : Level interrupt enable (R/W) */
+       volatile uint32_t enable_set;      /* 0x008 : Set above reg .... (-/W) */
+       volatile uint32_t enable_clear;    /* 0x00C : Clear above reg .... (-/W) */
+       volatile uint32_t active_level;    /* 0x010 : Set active level (R/W) */
+       volatile uint32_t set_active_high; /* 0x014 : Set active level to high (-/W) */
+       volatile uint32_t set_active_low;  /* 0x018 : Set active level to low (-/W) */
+       uint32_t reserved[2];
+       volatile uint32_t status_and_toggle; /* 0x024 : Int status / toggle level (R/W) */
+};
+#define LPC_GPIO_INT_LEVEL     ((struct lpc_gpio_pin_level_interrupt *) LPC_GPIO_INTR_BASE)
+
+#define LPC_GPIO_INT_MODE_EDGE    0
+#define LPC_GPIO_INT_MODE_LEVEL   1
+
+#define LPC_GPIO_INT(x)  (0x01 << (x & 0x07))
+
+struct group_gpio_int
+{
+       volatile uint32_t control;     /* 0x000 : Grouped interrupt control (R/W) */
+       uint32_t reserved_0[7];
+       volatile uint32_t polarity[2]; /* 0x020 - 0x024 : Port 0/1 pins polarity (R/W) */
+       uint32_t reserved_1[6];
+       volatile uint32_t enable[2];   /* 0x040 - 0x044 : Port 0/1 pins interrupt enable (R/W) */
+};
+#define LPC_GROUP0_GPIO_INT     ((struct group_gpio_int *) LPC_GPIO_GRP0_INT_BASE)
+#define LPC_GROUP1_GPIO_INT     ((struct group_gpio_int *) LPC_GPIO_GRP1_INT_BASE)
+
+
 #endif /* DRIVERS_GPIO_H */
index de21457..6075cbf 100644 (file)
  *
  *************************************************************************** */
 
+/**************************************************************************** */
+/*                      I2C                                                   */
+/**************************************************************************** */
+
+/* I2C driver for the I2C bus integrated module of the LPC11u3x.
+ * Refer to LPC11u3x documentation (UM10462.pdf) for more information.
+ */
+
 #ifndef DRIVERS_I2C_H
 #define DRIVERS_I2C_H
 
-#include <stdint.h>
+#include "lib/stdint.h"
+#include "core/lpc_regs.h"
 
 
+#define NB_I2C_BUSSES   1
+
 #define I2C_CLK_100KHz  (100*1000)
 #define I2C_CLK_400KHz  (400*1000)
 
 #define I2C_READ_BIT 0x01
 #define I2C_WRITE_BIT 0x00
 
+enum i2c_busses {
+       I2C0 = 0,
+       I2C1,
+       I2C2,
+       I2C3,
+};
+
+enum i2c_modes {
+   I2C_MASTER = 0,
+   I2C_SLAVE,
+   I2C_MONITOR,
+};
+
 enum i2c_conditions {
        I2C_CONT = 0,
        I2C_DO_REPEATED_START,
@@ -97,7 +121,7 @@ enum i2c_state_machine_states {
  *   -EREMOTEIO : Device did not acknowledge
  *   -EIO : Bad one: Illegal start or stop, or illegal state in i2c state machine
  */
-int i2c_read(const void *cmd_buf, size_t cmd_size, const void* ctrl_buf, void* inbuff, size_t count);
+int i2c_read(uint8_t bus_num, const void *cmd_buf, size_t cmd_size, const void* ctrl_buf, void* inbuff, size_t count);
 
 /* I2C Write
  * Performs a non-blocking write on the i2c bus.
@@ -118,19 +142,61 @@ int i2c_read(const void *cmd_buf, size_t cmd_size, const void* ctrl_buf, void* i
  *   -EREMOTEIO : Device did not acknowledge
  *   -EIO : Bad one: Illegal start or stop, or illegal state in i2c state machine
  */
-int i2c_write(const void *buf, size_t count, const void* ctrl_buf);
+int i2c_write(uint8_t bus_num, const void *buf, size_t count, const void* ctrl_buf);
+
 
+/* Release Bus
+ * Some devices do not release the Bus at the end of a transaction if they don't receive
+ *   a start condition immediately followed by a stop condition.
+ */
+void i2c_release_bus(uint8_t bus_num);
 
 
 
 /***************************************************************************** */
 /*                I2C Init                                                     */
 /***************************************************************************** */
-void i2c_on(uint32_t i2c_clk_freq);
-void i2c_off(void);
+/* I2C on / off
+ *   bus_num : I2C bus number to use. Ignored on this micro-controller which has only one I2C bus.
+ *   i2c_clk_freq : I2C clock freqeuncy in Hz
+ *   mode is one of I2C_MASTER, I2C_SLAVE or I2C_MONITOR.
+ *   Note that only I2C_MASTER is currently supported.
+ */
+int i2c_on(uint8_t bus_num, uint32_t i2c_clk_freq, uint8_t mode);
+int i2c_off(uint8_t bus_num);
 /* Allow system to propagate main clock */
 void i2c_clock_update(void);
 
 
 
+/***************************************************************************** */
+/*                     Inter-Integrated Circuit                                */
+/***************************************************************************** */
+/* Inter-Integrated Circuit (I2C) */
+struct lpc_i2c
+{
+       volatile uint32_t ctrl_set;      /* 0x000 : I2C Control Set Register (R/W) */
+       volatile const uint32_t status;  /* 0x004 : I2C Status Register (R/-) */
+       volatile uint32_t data;          /* 0x008 : I2C Data Register (R/W) */
+       volatile uint32_t slave_addr_0;  /* 0x00C : I2C Slave Address Register 0 (R/W) */
+       volatile uint32_t clk_duty_high; /* 0x010 : SCL Duty Cycle Register High Half Word (R/W) */
+       volatile uint32_t clk_duty_low;  /* 0x014 : SCL Duty Cycle Register Low Half Word (R/W) */
+       volatile  uint32_t ctrl_clear;   /* 0x018 : I2C Control Clear Register (-/W) */
+       volatile uint32_t monitor_mode_ctrl;  /* 0x01C : Monitor mode control register (R/W) */
+       volatile uint32_t slave_addr_1;  /* 0x020 : I2C Slave Address Register 1 (R/W) */
+       volatile uint32_t slave_addr_2;  /* 0x024 : I2C Slave Address Register 2 (R/W) */
+       volatile uint32_t slave_addr_3;  /* 0x028 : I2C Slave Address Register 3 (R/W) */
+       volatile const uint32_t data_buffer;  /* 0x02C : Data buffer register (-/W) */
+       volatile uint32_t slave_addr_mask[4]; /* 0x030 to 0x03C : I2C Slave address mask register 0 to 3 (R/W) */
+};
+#define LPC_I2C0         ((struct lpc_i2c *) LPC_I2C0_BASE)
+
+#define I2C_ASSERT_ACK   (0x01 << 2)
+#define I2C_INTR_FLAG    (0x01 << 3)
+#define I2C_STOP_FLAG    (0x01 << 4)
+#define I2C_START_FLAG   (0x01 << 5)
+#define I2C_ENABLE_FLAG  (0x01 << 6)
+
+
+
 #endif /* DRIVERS_I2C_H */
index 877ae0d..1a9136c 100644 (file)
  *
  *************************************************************************** */
 
+/***************************************************************************** */
+/*                UARTs                                                        */
+/***************************************************************************** */
+/* UART driver for the integrated UARTs of the LPC11u3x.
+ * Refer to LPC11u3x documentation (UM10462.pdf) for more information.
+ */
+
 #ifndef DRIVERS_SERIAL_H
 #define DRIVERS_SERIAL_H
 
 
-#include <stdint.h>
+#include "lib/stdint.h"
+#include "core/lpc_regs.h"
 
 
+#define UART0  0
+
 #define SERIAL_CAP_UART   (1 << 0)
 #define SERIAL_CAP_RS485  (1 << 1)
 #define SERIAL_CAP_IRDA   (1 << 2)
 /*    Serial Write
  *
  * Try to send at most "length" characters from "buf" on the requested uart.
- * Returns -1 on error, or number of characters copied into output buffer, witch
- * may be less than requested "length"
- * Possible errors: requested uart does not exists or unable to acquire uart lock.
+ * Returns a negative value on error, or number of characters copied into output buffer,
+ * witch may be less than requested "length"
+ * Possible errors: requested uart does not exists (-EINVAL) or unable to acquire uart
+ * lock (-EBUSY).
  *
  * Warning for Real Time : This implementation will block if there's already a
  * transmission ongoing.
@@ -61,7 +72,7 @@ int serial_write(uint32_t uart_num, const char *buf, uint32_t length);
 /*    Serial Flush
  *
  * Wait until all characters have been sent
- * Returns -1 on error, 0 on success.
+ * Returns -EINVAL on error, 0 on success.
  * Possible errors: requested uart does not exists or unable to acquire uart lock.
  *
  * Warning for Real Time : This implementation will block if there's already a
@@ -70,10 +81,25 @@ int serial_write(uint32_t uart_num, const char *buf, uint32_t length);
 int serial_flush(uint32_t uart_num);
 
 
+/****************************************************************************** */
+/*    Serial send byte - quick function with almost no tests.
+ * If the uart is not sending, the byte is placed directly in the data buffer and
+ * the call returns 0.
+ * Else, the call returns -EBUSY and nothing is sent.
+ */
+int serial_send_quickbyte(uint32_t uart_num, uint8_t data);
+
 
 /***************************************************************************** */
 /*   Public access to UART setup   */
 
+
+/* Change UART configuration (number of data, parity and stop bits).
+ * config is a mask of LPC_UART_xBIT (x = 5..8), LPC_UART_xSTOP (x = 1..2)
+ *   and one of LPC_UART_NO_PAR, LPC_UART_ODD_PAR or LPC_UART_EVEN_PAR.
+ */
+int uart_set_config(uint8_t uart_num, uint32_t config);
+
 /* Change uart mode to RS485
  * return -ENODEV when the device does not support RS485 mode.
  */
@@ -94,4 +120,87 @@ void uart_off(uint32_t uart_num);
 
 
 
+/***************************************************************************** */
+/*                     Universal Asynchronous Receiver Transmitter             */
+/***************************************************************************** */
+/* Universal Asynchronous Receiver Transmitter (UART) */
+struct lpc_uart_func {
+       volatile uint32_t buffer; /* 0x000 : Transmit / Receiver Buffer Register (R/W) */
+       volatile uint32_t intr_enable; /* 0x004 : Interrupt Enable Register (R/W) */
+       volatile uint32_t intr_pending; /* 0x008 : Interrupt ID Register (R/-) */
+};
+struct lpc_uart_ctrl {
+       volatile uint32_t divisor_latch_lsb;  /* 0x000 : Divisor Latch LSB (R/W) */
+       volatile uint32_t divisor_latch_msb;  /* 0x004 : Divisor Latch MSB (R/W) */
+       volatile uint32_t fifo_ctrl;  /* 0x008 : Fifo Control Register (-/W) */
+};
+struct lpc_uart
+{
+       union {
+               struct lpc_uart_func func;
+               struct lpc_uart_ctrl ctrl;
+       };
+       volatile uint32_t line_ctrl;   /* 0x00C : Line Control Register (R/W) */
+       volatile uint32_t modem_ctrl;  /* 0x010 : Modem control Register (R/W) */
+       volatile const uint32_t line_status;   /* 0x014 : Line Status Register (R/ ) */
+       volatile const uint32_t modem_status;  /* 0x018 : Modem status Register (R/ ) */
+       volatile uint32_t scratch_pad;  /* 0x01C : Scratch Pad Register (R/W) */
+       volatile uint32_t auto_baud_ctrl;  /* 0x020 : Auto-baud Control Register (R/W) */
+       volatile uint32_t irda_ctrl;       /* 0x024 : UART IrDA Control Register (R/W) */
+       volatile uint32_t fractional_div;  /* 0x028 : Fractional Divider Register (R/W) */
+       volatile uint32_t oversampling;    /* 0x02C : Oversampling Register (R/W) */
+       volatile uint32_t transmit_enable;  /* 0x030 : Transmit Enable Register (R/W) */
+       uint32_t reserved_1[3];
+       volatile uint32_t half_duplex_en;  /* 0x040 :  Half-duplex Enable Register (R/W) */
+       uint32_t reserved_2;
+       volatile uint32_t smart_card_ctrl;  /* 0x048 : Smart Card Interface Control Register (R/W) */
+       volatile uint32_t RS485_ctrl;       /* 0x04C : RS-485/EIA-485 Control Register (R/W) */
+       volatile uint32_t RS485_addr_match; /* 0x050 : RS-485/EIA-485 address match Register (R/W) */
+       volatile uint32_t RS485_dir_ctrl_delay;  /* 0x054 : RS-485/EIA-485 direction control delay Register (R/W) */
+       volatile uint32_t sync_ctrl;  /* 0x058 : Synchronous Mode Control Register (R/W) */
+};
+#define LPC_UART_0        ((struct lpc_uart *) LPC_UART0_BASE)
+
+/* Line Control Register */
+#define LPC_UART_5BIT          (0x00 << 0)
+#define LPC_UART_6BIT          (0x01 << 0)
+#define LPC_UART_7BIT          (0x02 << 0)
+#define LPC_UART_8BIT          (0x03 << 0)
+#define LPC_UART_1STOP         (0x00 << 2)
+#define LPC_UART_2STOP         (0x01 << 2)
+#define LPC_UART_NO_PAR        (0x00 << 3)
+#define LPC_UART_ODD_PAR      ((0x01 << 3) | (0x00 << 4))
+#define LPC_UART_EVEN_PAR      ((0x01 << 3) | (0x01 << 4))
+#define LPC_UART_ENABLE_DLAB   (0x01 << 7)
+/* FIFO Control Register */
+#define LPC_UART_FIFO_EN       (0x01 << 0)
+#define LPC_UART_RX_CLR        (0x01 << 1)
+#define LPC_UART_TX_CLR        (0x01 << 2)
+#define LPC_UART_DMA_MODE_EN   (0x01 << 3)
+#define LPC_UART_FIFO_TRIG(x)  ((x & 0x03) << 6) /* 1 / 4 / 8 / 14 chars */
+/* Interrupt Enable Register */
+#define LPC_UART_RX_INT_EN     (0x01 << 0)
+#define LPC_UART_TX_INT_EN     (0x01 << 1)
+#define LPC_UART_RX_STATUS_INT_EN   (0x01 << 2)
+/* Interrupt status */
+#define LPC_UART_INT_MASK      (0x7 << 1)
+#define LPC_UART_INT_MODEM     (0x0 << 1)
+#define LPC_UART_INT_TX        (0x1 << 1)
+#define LPC_UART_INT_RX        (0x2 << 1)
+#define LPC_UART_INT_RX_STATUS (0x3 << 1)
+#define LPC_UART_INT_TIMEOUT   (0x6 << 1)
+/* RS485 Control */
+#define LPC_RS485_ENABLE       (0x1 << 0)
+#define LPC_RS485_RX_DIS       (0x1 << 1)
+#define LPC_RS485_AUTO_ADDR_EN (0x1 << 2)
+#define LPC_RS485_DIR_PIN_RTS  (0x0 << 3)
+#define LPC_RS485_DIR_PIN_DTR  (0x1 << 3)
+#define LPC_RS485_AUTO_DIR_EN  (0x1 << 4)
+#define LPC_RS485_DIR_CTRL_INV (0x1 << 5)
+/* RS485 */
+#define LPC_RS485_ADDR(x)  ((x) & 0xFF)
+#define LPC_RS485_DIR_DELAY(x)  ((x) & 0xFF)
+/* IrDA */
+#define LPC_IRDA_PULSEDIV(x)  (((x) & 0x07) << 3)
+
 #endif /* DRIVERS_SERIAL_H */
index a3202f2..ab1a6d4 100644 (file)
 /*                SSP                                                          */
 /***************************************************************************** */
 
-#include <stdint.h>
+/* SSP/SPI driver for the SSP bus integrated module of the LPC11u3x.
+ * Refer to LPC11u3x documentation (UM10462.pdf) for more information.
+ */
+
+#include "lib/stdint.h"
+#include "core/lpc_regs.h"
 
 
+enum ssp_bus_number {
+       SSP_BUS_0 = 0,
+       SSP_BUS_1,
+};
+
 /* Set this to 1 for use of this driver in a multitasking OS, it will activate the SPI Mutex */
 #define MULTITASKING 0
 
@@ -93,7 +103,7 @@ void ssp_clk_update(void);
 /* SSP Setup as master */
 /* Returns 0 on success
  * Parameters :
- *  frame_type is SPI, TI or MICROWIRE (use apropriate defines for this one:
+ *  frame_type is SPI, TI or MICROWIRE (use apropriate defines for this one).
  *     LPC_SSP_FRAME_SPI - LPC_SSP_FRAME_TI - LPC_SSP_FRAME_MICROWIRE).
  *  data_width is a number between 4 and 16.
  *  rate : The bit rate, in Hz.
@@ -110,5 +120,61 @@ void ssp_off(uint8_t ssp_num);
 
 
 
+
+/***************************************************************************** */
+/*                     Synchronous Serial Communication                        */
+/***************************************************************************** */
+/* Synchronous Serial Communication (SSP) */
+struct lpc_ssp
+{
+       volatile uint32_t ctrl_0;        /* 0x000 : Control Register 0 (R/W) */
+       volatile uint32_t ctrl_1;        /* 0x004 : Control Register 1 (R/W) */
+       volatile uint32_t data;          /* 0x008 : Data Register (R/W) */
+       volatile const uint32_t status;  /* 0x00C : Status Registe (R/-) */
+       volatile uint32_t clk_prescale;  /* 0x010 : Clock Prescale Register (R/W) */
+       volatile uint32_t int_mask;      /* 0x014 : Interrupt Mask Set and Clear Register (R/W) */
+       volatile uint32_t raw_int_status;     /* 0x018 : Raw Interrupt Status Register (R/-) */
+       volatile uint32_t masked_int_status;  /* 0x01C : Masked Interrupt Status Register (R/-) */
+       volatile uint32_t int_clear;     /* 0x020 : SSPICR Interrupt Clear Register (-/W) */
+       volatile uint32_t dma_ctrl;      /* 0x024 : DMA Control Register (R/W) */
+};
+#define LPC_SSP0        ((struct lpc_ssp *) LPC_SSP0_BASE)
+#define LPC_SSP1        ((struct lpc_ssp *) LPC_SSP1_BASE)
+
+/* SSP Control 0 register */
+#define LPC_SSP_DATA_WIDTH(x)    (((x) - 1) & 0x0F) /* Use 4 for 4 bits, 5 for 5 bits, .... */
+#define LPC_SSP_FRAME_SPI        (0x00 << 4)
+#define LPC_SSP_FRAME_TI         (0x01 << 4)
+#define LPC_SSP_FRAME_MICROWIRE  (0x02 << 4)
+#define LPC_SSP_SPI_CLK_LOW      (0x00 << 6)
+#define LPC_SSP_SPI_CLK_HIGH     (0x01 << 6)
+#define LPC_SSP_SPI_CLK_FIRST    (0x00 << 7)
+#define LPC_SSP_SPI_CLK_LAST     (0x01 << 7)
+#define LPC_SSP_SPI_CLK_RATE_DIV(x) (((x) & 0xFF) << 8)
+/* SSP Control 1 register */
+#define LPC_SSP_LOOPBACK_MODE      (0x01 << 0)
+#define LPC_SSP_ENABLE             (0x01 << 1)
+#define LPC_SSP_MASTER_MODE        (0x00 << 2)
+#define LPC_SSP_SLAVE_MODE         (0x01 << 2)
+#define LPC_SSP_SLAVE_OUT_DISABLE  (0x01 << 3)
+
+/* SSP Status register */
+#define LPC_SSP_ST_TX_EMPTY      (0x01 << 0)
+#define LPC_SSP_ST_TX_NOT_FULL   (0x01 << 1)
+#define LPC_SSP_ST_RX_NOT_EMPTY  (0x01 << 2)
+#define LPC_SSP_ST_RX_FULL       (0x01 << 3)
+#define LPC_SSP_ST_BUSY          (0x01 << 4)
+
+/* SSP Interrupt Mask, Raw, Status, Clear */
+#define LPC_SSP_INTR_RX_OVERRUN      (0x01 << 0)
+#define LPC_SSP_INTR_RX_TIMEOUT      (0x01 << 1)
+#define LPC_SSP_INTR_RX_HALF_FULL    (0x01 << 2)
+#define LPC_SSP_INTR_TX_HALF_EMPTY   (0x01 << 3)
+
+/* SSP DMA Control */
+#define LPC_SSP_RX_DMA_EN   (0x01 << 0)
+#define LPC_SSP_TX_DMA_EN   (0x01 << 1)
+
+
 #endif /* DRIVERS_SSP_H */
 
index dcb4f08..3102564 100644 (file)
@@ -1,7 +1,7 @@
 /****************************************************************************
  *  drivers/timers.h
  *
- * Copyright 2012 Nathael Pajani <nathael.pajani@ed3l.fr>
+ * Copyright 2012-2016 Nathael Pajani <nathael.pajani@ed3l.fr>
  *
  * 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
 #ifndef DRIVERS_TIMERS_H
 #define DRIVERS_TIMERS_H
 
-#include <stdint.h>
-
 /***************************************************************************** */
 /*                Timers                                                       */
 /***************************************************************************** */
-/* Four timers are available, Two 16 bits and two 32 bits
- * All timers have 4 channels though 32 bits timers have all 4 channels available
- *   on capture /match pins while 16bits ones have only two (channels 0 and 1).
+
+/* Driver for the different kinds of timers available in the LPC11u3x
+ *
+ * This inludes :
+ * - 32 bits Timers driver
+ *   The LPC11u3x has two 32 bits Timer.
+ * - 16 bits Timers driver
+ *   The LPC11u3x has two 16 bits Timer.
+ *
+ * Refer to LPC11u3x documentation (UM10462.pdf) for more information.
+ *
+ * All common functions are available using a common interface. Only specific
+ * functions have a specific interface, described in separate headers files.
+ */
+
+#include "lib/stdint.h"
+#include "drivers/countertimers.h"
+
+/***************************************************************************** */
+/* All timers have 4 channels. 32 bits timers have all 4 channels available
+ *   on capture / match pins while 16 bits timers have only two (channels 0 and 1).
  */
 #define NUM_TIMERS 4
-#define NUM_CHANS 4
+#define MAX_CHANNELS 4
 
 /* Timer numbers to be used for functions from this driver. */
-#define LPC_TIMER_16B0  0
-#define LPC_TIMER_16B1  1
-#define LPC_TIMER_32B0  2
-#define LPC_TIMER_32B1  3
-
-
-/* Timer modes for the "mode" timer config structure field */
-enum lpc_timer_mode {
-       LPC_TIMER_MODE_TIMER = 0,
-       LPC_TIMER_MODE_COUNTER,
-       LPC_TIMER_MODE_CAPTURE,
-       LPC_TIMER_MODE_MATCH,
-       LPC_TIMER_MODE_PWM,  /* Pulse Width Modulation */
-       LPC_TIMER_MODE_PWD,  /* Pulse Width Demodulation */
+enum lpc_timers {
+       LPC_TIMER_16B0 = 0,  /* 16 bits timer 0 */
+       LPC_TIMER_16B1,  /* 16 bits timer 1 */
+       LPC_TIMER_32B0,  /* 32 bits timer 0 */
+       LPC_TIMER_32B1,  /* 32 bits timer 1 */
+};
+
+enum lpc_timer_channels {
+       CHAN0 = 0,
+       CHAN1,
+       CHAN2,
+       CHAN3,
+};
+
+/* Available timer modes *
+ * Some mode may be combined, and some are exlusive :
+ * Values here are important :
+ *   PWM and PWD and any further mode handled by a specific configure function will have
+ *   bit 2 set
+ */
+#define LPC_TIMER_MODE_TIMER     (0x00 << 0)
+#define LPC_TIMER_MODE_COUNTER   (0x01 << 0)
+#define LPC_TIMER_MODE_SPECIFIC  (0x02 << 0)
+#define LPC_TIMER_MODE_CAPTURE   (0x01 << 6)
+#define LPC_TIMER_MODE_MATCH     (0x01 << 7)
+/* Specific modes */
+#define LPC_TIMER_MODE_PWM       (LPC_TIMER_MODE_SPECIFIC | (0x01 << 2))  /* Pulse Width Modulation */
+#define LPC_TIMER_MODE_PWD       (LPC_TIMER_MODE_SPECIFIC | (0x02 << 2))  /* Pulse Width Demodulation */
+
+
+/*******************************************************************************/
+/* Configurations */
+
+/* PWM
+ * This structure is used for the timer_pwm_config() function.
+ * nb_channels is the number of PWM channels used
+ * period_chan is the channel number used to generate the period.
+ * period is the PWM cycle period, in timer clock cycles. It is the value to wich the timer
+ *   will count.
+ * outputs[] is the list of outputs / channels corresponding to each 'match_values'
+ * match_values[] control the PWM channels duty-cycle. They are the timer values at wich
+ *   the corresponding outputs will toggle. They must be lower than or equal to the period
+ *   value.
+ * outputs_initial_state defines whether the outputs start low or high at the beginning of
+ *   the PWM cycle. Support for this depends on the target.
+ *   The LPC11u3x enforces a low state initial output.
+ */
+struct lpc_timer_pwm_config {
+       uint8_t nb_channels;
+       uint8_t period_chan;
+       uint32_t period;
+       uint8_t outputs[MAX_CHANNELS];
+       uint32_t match_values[MAX_CHANNELS];
+       uint32_t outputs_initial_state;
 };
 
-/* Structure used to pass parameters to configure a timer */
-/* Notes:
- * In counter or PWM mode, the config is done using config[0] for enabled channels and config[1] holds
- *   the channel number used to control PWM cycle.
- * The field "reset_on_capture" must be set to LPC_COUNTER_CLEAR_ON_EVENT_EN ored with one
- *   of the LPC_COUNTER_CLEAR_ON_CHAN*_* to activate the clear timer on event functionality
+/* This structure is used for the timer_counter_config() function.
+ * mode is a mask of LPC_TIMER_MODE_* values. Note that some can be combined, and some are
+ *   exclusive : only one of these : LPC_TIMER_MODE_TIMER or LPC_TIMER_MODE_COUNTER and
+ *   possibly one or both of these : LPC_TIMER_MODE_CAPTURE and LPC_TIMER_MODE_MATCH
+ * prescale_val: if not nul, override the prescaler value computed during timer_on() with this
+ *   value. It is not clear in the documentation whether the prescaler is used in counter mode
+ *   or not.
+ * count_control selects the capture channel used to increment the counter when in counter mode.
+ *   count_control is one of LPC_COUNTER_INC_ON_RISING or LPC_COUNTER_INC_ON_FALLING or
+ *   LPC_COUNTER_INC_ON_BOTH.
+ * count_chann selects the channel used to increment the counter (value between 0 and MAX_CHANS).
+ * reset_on_cap is activated by adding LPC_COUNTER_CLEAR_ON_EVENT_EN to a capture reset event (one
+ *   of LPC_COUNTER_CLEAR_ON_*** whith *** Going from CHAN0_RISE, CHAN0_FALL, ... to CHAN3_FALL)
+ * match_control[] is a combination of LPC_TIMER_INTERRUPT_ON_MATCH, LPC_TIMER_RESET_ON_MATCH and
+ *   LPC_TIMER_STOP_ON_MATCH for each match channel.
+ *   This controls the internal behaviour on each match event.
+ * match[] holds the match values.
+ * ext_match_config[] is one of LPC_TIMER_NOTHING_ON_MATCH, LPC_TIMER_CLEAR_ON_MATCH,
+ *   LPC_TIMER_SET_ON_MATCH or LPC_TIMER_TOGGLE_ON_MATCH for each match channel.
+ *   This controls the behavior of the output associated to the corresponding match channel. The
+ *   corresponding pin must be configured as match output by the user.
+ * cap_control[] is a combination of LPC_TIMER_CAP_ON_RISING_EDGE, LPC_TIMER_CAP_ON_FALLING_EDGE
+ *   and LPC_TIMER_INTERRUPT_ON_CAPTURE.
+ *   This controls when the TC current value is loaded to the corresponding match value register,
+ *   and whether this triggers an interrupt or not.
  */
-struct timer_config
-{
-       uint32_t mode; /* Counter, Timer Capture, Timer Match or PWM */
-       uint8_t config[NUM_CHANS]; /* Configure the internal behavior when a capture or a match occurs */
-       uint8_t ext_match_config[NUM_CHANS]; /* Configure the external behavior when a match occurs */
-       uint32_t match[NUM_CHANS]; /* The match values if the timer is used in match mode */
-       uint32_t reset_on_capture;
+struct lpc_tc_config {
+       uint16_t mode;
+       uint32_t prescale_val;
+       uint8_t count_control;
+       uint8_t count_chan;
+       uint8_t reset_on_cap;
+       uint8_t match_control[MAX_CHANNELS];
+       uint32_t match[MAX_CHANNELS];
+       uint8_t ext_match_config[MAX_CHANNELS];
+       uint8_t cap_control[MAX_CHANNELS];
 };
 
 
 
+/*******************************************************************************/
+/* Operation structures, not for use by user programms */
+struct common_operations {
+       /* Running control */
+       void (*start)(uint8_t);
+       void (*stop)(uint8_t);
+       void (*pause)(uint8_t);
+       void (*cont)(uint8_t);
+       void (*restart)(uint8_t);
+       void (*halt)(uint8_t);
+       /* Counter */
+       int (*get_counter)(uint8_t, uint32_t*);
+       int (*get_capture)(uint8_t, uint8_t, uint32_t*);
+       int (*set_match)(uint8_t, uint8_t, uint32_t);
+};
+struct config_operations {
+       int (*pwm_config)(uint8_t, const struct lpc_timer_pwm_config*);
+       int (*tc_config)(uint8_t, const struct lpc_tc_config*);
+};
+struct init_operations {
+       int (*timer_on)(uint8_t, uint32_t, void (*)(uint32_t));
+       int (*timer_off)(uint8_t);
+};
+
+/*******************************************************************************/
+/* Common operations */
+
 /* Start the timer :
  * Remove the reset flag if present and set timer enable flag.
  * Timer must be turned on and configured (no checks done here).
  */
-void timer_start(uint32_t timer_num);
-void timer_continue(uint32_t timer_num);
+void timer_start(uint8_t timer_num);
+void timer_continue(uint8_t timer_num);
 
 /* Pause the timer counter, does not reset */
-void timer_pause(uint32_t timer_num);
+void timer_pause(uint8_t timer_num);
 
 /* Stop and reset the timer counter */
-void timer_stop(uint32_t timer_num);
+void timer_stop(uint8_t timer_num);
+void timer_halt(uint8_t timer_num);
 
 /* Resets the timer and lets it count again imediately */
-void timer_restart(uint32_t timer_num);
+void timer_restart(uint8_t timer_num);
 
-uint32_t timer_get_capture_val(uint32_t timer_num, uint32_t channel);
 
-uint32_t timer_get_counter_val(uint32_t timer_num);
+/* Get the current counter value
+ * Return 0 if the value is valid.
+ */
+int timer_get_counter_val(uint8_t timer_num, uint32_t* val);
+
+
+/* Get the value of the timer when the capture event last triggered
+  * Return 0 if the value is valid.
+ */
+int timer_get_capture_val(uint8_t timer_num, uint8_t channel, uint32_t* val);
 
 /* Change the match value of a single timer channel */
-void timer_set_match(uint32_t timer_num, uint32_t channel, uint32_t val);
+int timer_set_match(uint8_t timer_num, uint8_t channel, uint32_t val);
 
-/***************************************************************************** */
-/*   Timer Setup */
-/* Returns 0 on success
- * Takes a timer number and a timer config structure as arguments.
- * Refer to timer config structure for details.
- * Note: use of channel 3 for PWM cycle length is enforced.
+
+/*******************************************************************************/
+/* Configuration */
+
+/* PWM configuration in order to use the timer as a PWM controller.
+ * For the pwm_conf structure, refer to it's definition above..
+ * The Timer must be "on" (call timer_on() for this timer before the call to
+ *   timer_pwm_config(), with the disired clock rate, which will define the
+ *   length of a timer clock cycle, which is the base for the timer period
+ *   definition).
+ * The timer will not be started. User code must call timer_start() in order
+ *   to start the PWM.
  */
-int timer_setup(uint32_t timer_num, const struct timer_config* conf);
+int timer_pwm_config(uint8_t timer_num, const struct lpc_timer_pwm_config* pwm_conf);
 
 
+/* Timer Setup in timer or counter mode, with optionnal capture and match configuration
+ * Takes a timer number and a timer counter config structure as arguments.
+ * Returns 0 on success
+ */
+int timer_counter_config(uint8_t timer_num, const struct lpc_tc_config* conf);
+
+
+/*******************************************************************************/
+/* Init */
 
 /* Power up a timer.
- * Note that clkrate should be a divider of the main clock frequency chosed
- *   for your application as it will be used to divide the main clock to get
- *   the prescaler value.
- * Set clkrate to 0 to disable the prescaler.
+ * clkrate is the desired timer clock rate. It will be used to divide the main clock
+ *   to get the timer prescaler value.
+ *   Set clkrate to 0 to disable the prescaler.
  * callback is used for all the possible timer interrupts (activated using the
  *   config field in timer_config struct upon timer setup)
  *   The interrupt flags are passed to the interrupt routine as argument.
  */
-void timer_on(uint32_t timer_num, uint32_t clkrate, void (*callback)(uint32_t));
+int timer_on(uint8_t timer_num, uint32_t clkrate, void (*callback)(uint32_t));
 
 /* Removes the main clock from the selected timer block */
-void timer_off(uint32_t timer_num);
+int timer_off(uint8_t timer_num);
+
 
 #endif /* DRIVERS_TIMERS_H */
 
diff --git a/include/drivers/usb.h b/include/drivers/usb.h
new file mode 100644 (file)
index 0000000..e8e6ecb
--- /dev/null
@@ -0,0 +1,81 @@
+/****************************************************************************
+ *  drivers/usb.h
+ *
+ * Copyright 2015 Nathael Pajani <nathael.pajani@ed3l.fr>
+ *
+ * This file is derived from Work covered by the Apache 2.0 licence.
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * Original sources should be found there :
+ *     https://github.com/mbedmicro/CMSIS-DAP.git
+ *
+ * Original copyright notice :
+ *    CMSIS-DAP Interface Firmware
+ *    Copyright (c) 2009-2013 ARM Limited
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ *************************************************************************** */
+
+
+
+/***************************************************************************** */
+/*                USB                                                          */
+/***************************************************************************** */
+/* USB driver for the integrated USB controller of the LPC11u3x.
+ * Refer to LPC11u3x documentation (UM10462.pdf) for more information.
+ */
+
+#ifndef DRIVERS_USB_H
+#define DRIVERS_USB_H
+
+#include "lib/stdint.h"
+#include "core/lpc_regs.h"
+
+
+
+/***************************************************************************** */
+/* USB Setup */
+
+/* Turn on the USB block */
+int usb_on(void);
+
+/* Turn off the USB block */
+void usb_off(void);
+
+
+
+/***************************************************************************** */
+/*                     USB (Universal Serial Bus)                              */
+/***************************************************************************** */
+/* USB Device Controller */
+struct lpc_usb_device
+{
+    volatile uint32_t dev_cmd_status;     /* 0x000 : USB Device Command and Status register (R/W) */
+    volatile uint32_t info;               /* 0x004 : USb Info register (R/W) */
+    volatile uint32_t ep_list_start;      /* 0x008 : USB EP Command and Status List start address (R/W) */
+    volatile uint32_t data_buff_start;    /* 0x00C : USB Data buffer start address (R/W) */
+    volatile uint32_t link_pm;            /* 0x010 : USB Link Power Management register (R/W) */
+    volatile uint32_t ep_skip;            /* 0x014 : USB Endpoint skip (R/W) */
+    volatile uint32_t ep_in_use;          /* 0x018 : USB Endpoint Buffer in use (R/W) */
+    volatile uint32_t ep_buff_config;     /* 0x01C : USB Endpoint Buffer Configuration register (R/W) */
+    volatile uint32_t intr_status;        /* 0x020 : USB interrupt status register (R/W) */
+    volatile uint32_t intr_enable;        /* 0x024 : USB interrupt enable register (R/W) */
+    volatile uint32_t set_intr_status;    /* 0x028 : USB set interrupt status register (R/W) */
+    volatile uint32_t intr_routing;       /* 0x02C : USB interrupt routing register (R/W) */
+       uint32_t reserved_0;
+    volatile uint32_t ep_toggle;          /* 0x034 : USB Endpoint toggle register (R/W) */
+};
+#define LPC_USB         ((struct lpc_usb_device *) LPC_USB_BASE)
+
+#endif /* DRIVERS_USB_H */
diff --git a/include/drivers/usb_rom.h b/include/drivers/usb_rom.h
new file mode 100644 (file)
index 0000000..30988d6
--- /dev/null
@@ -0,0 +1,986 @@
+/****************************************************************************
+ *  drivers/usb_rom.h
+ *
+ * Copyright 2014 Nathael Pajani <nathael.pajani@ed3l.fr>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ *************************************************************************** */
+
+#ifndef DRIVERS_USB_ROM_H
+#define DRIVERS_USB_ROM_H
+
+/***************************************************************************** */
+/*         USB ROM based driver for CDC, DFU, HID and CDC                      */
+/***************************************************************************** */
+
+#include "lib/stdint.h"
+
+struct lpc_usb_rom_api {
+       /* Pointer to function table which exposes functions which interact directly with USB
+        *   device stack's core layer. */
+    const struct usbdev_hw_api* hw;
+       /* Pointer to function table which exposes functions which interact directly with USB
+        *   device controller hardware. */
+    const struct usbdev_core_api* core;
+       /* Pointer to function table which exposes functions provided by MSC function driver module. */
+    const struct usbdev_msc_api* msc;
+       /* Pointer to function table which exposes functions provided by DFU function driver module. */
+    const struct usbdev_dfu_api* dfu;
+       /* Pointer to function table which exposes functions provided by HID function driver module. */
+    const struct usbdev_hid_api* hid;
+       /* Pointer to function table which exposes functions provided by CDC-ACM function driver module. */
+    const struct usbdev_cdc_api* cdc;
+    const uint32_t reserved; /* Reserved for future function driver module. */
+       /* Version identifier of USB ROM stack.
+        * The version is defined as 0x0CHDMhCC where each nibble represents version number of the
+        *    corresponding component.
+        * CC - 7:0 - 8bit core version number
+        * h - 11:8 - 4bit hardware interface version number
+        * M - 15:12 - 4bit MSC class module version number
+        * D - 19:16 - 4bit DFU class module version number
+        * H - 23:20 - 4bit HID class module version number
+        * C - 27:24 - 4bit CDC class module version number
+        * H - 31:28 - 4bit reserved
+        */
+    const uint32_t version;
+};
+
+extern struct lpc_usb_rom_api* usb_rom_api;
+
+
+union bm {
+       uint8_t recipient;  /* Recipient type */
+       uint8_t type;       /* Request type */
+       uint8_t direction;  /* Direction type */
+};
+
+
+
+/***************************************************************************** */
+/* HW and Core Structures */
+
+union request_type {
+       uint8_t b; /* byte wide access member */
+       uint8_t bm; /* bitfield structure access member */
+};
+
+struct usb_endpoint_descriptor {
+       uint8_t bLength;
+       uint8_t bDescriptorType;
+       uint8_t bEndpointAddress;
+       uint8_t bmAttributes;
+       uint16_t wMaxPacketSize;
+       uint8_t bInterval;
+    /* NOTE:  these two are _only_ in audio endpoints. */
+    /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
+       uint8_t bRefresh;
+       uint8_t bSynchAddress;
+} __attribute__ ((packed));
+
+struct usb_common_descriptor {
+       uint8_t bLength; 
+       uint8_t bDescriptorType;
+} __attribute__ ((packed));
+
+struct usb_core_descriptor {
+       uint8_t* device_desc; /* Pointer to USB device descriptor */
+       uint8_t* string_desc; /* Pointer to array of USB string descriptors */
+       /* Pointer to USB device configuration descriptor when device is operating in full speed mode. */
+       uint8_t* full_speed_desc;
+       /* Pointer to USB device configuration descriptor when device is operating in high speed mode.
+        * For full-speed only implementation this pointer should be same as full_speed_desc. */
+       uint8_t* high_speed_desc;
+       /* Pointer to USB device qualifier descriptor. For full-speed only implementation this pointer
+        * should be set to null (0). */
+       uint8_t* device_qualifier;
+} __attribute__ ((packed));
+
+struct usb_device_qualifier_descriptor {
+       uint8_t bLength; /* Size of descriptor ni bytes */
+       uint8_t bDescriptorType; /* Device Qualifier Type */
+       uint16_t bcdUSB; /* USB specification version number (e.g., 0200H for V2.00) */
+       uint8_t bDeviceClass; /* Class Code */
+       uint8_t bDeviceSubClass; /* SubClass Code */
+       uint8_t bDeviceProtocol; /* Protocol Code */
+       uint8_t bMaxPacketSize0; /* Maximum packet size for other speed */
+       uint8_t bNumConfigurations; /* Number of Other-speed Configurations */
+       uint8_t bReserved; /* Reserved for future use, must be zero */
+} __attribute__ ((packed));
+
+struct usb_dfu_func_descriptor {
+       uint8_t bLength;
+       uint8_t bDescriptorType;
+       uint8_t bmAttributes;
+       uint16_t wDetachTimeOut;
+       uint16_t wTransferSize;
+       uint16_t bcdDFUVersion;
+} __attribute__ ((packed));
+
+struct usb_interface_descriptor {
+       uint8_t bLength; /* Size of descriptor ni bytes */
+       uint8_t bDescriptorType; /* Interface Descriptor Type */
+       /* Number of this interface. Zero-based value identifying the index in the array of concurrent
+        *   interfaces supported by this configuration. */
+       uint8_t bInterfaceNumber;
+       /* Value used to select this alternate setting for the interface identified in the prior field */
+       uint8_t bAlternateSetting;
+       /* Number of endpoints used by this interface (excluding endpoint zero). If this value is zero, this
+        *   interface only uses the Default Control Pipe. */
+       uint8_t bNumEndpoints;
+       uint8_t bInterfaceClass; /* Class code (assigned by the USB-IF). */
+       uint8_t bInterfaceSubClass; /* Subclass code (assigned by the USB-IF). */
+       uint8_t bInterfaceProtocol; /* Protocol code (assigned by the USB). */
+       uint8_t iInterface; /* Index of string descriptor describing this interface */
+} __attribute__ ((packed));
+
+struct usb_other_speed_configuration {
+       uint8_t bLength; /* Size of descriptor ni bytes */
+       uint8_t bDescriptorType; /* Other Speed configuration Type */
+       uint16_t wTotalLength; /* Total length of data returned */
+       uint8_t bNumInterfaces; /* Number of interfaces supported by this speed configuration */
+       uint8_t bConfigurationValue; /* Value to use to select configuration */
+       uint8_t IConfiguration; /* Index of string descriptor */
+       uint8_t bmAttributes; /* Same as Configuration descriptor */
+       uint8_t bMaxPower; /* Same as Configuration descriptor */
+} __attribute__ ((packed));
+
+struct usb_setup_packet {
+       /* This bit-mapped field identifies the characteristics of the specific request. */
+       union request_type bmRequestType;
+       /* This field specifies the particular request. The Type bits in the bmRequestType field modify the
+        *   meaning of this field. */
+       uint8_t bRequest;
+       /* Used to pass a parameter to the device, specific to the request. */
+       uint16_t wValue;
+       /* Used to pass a parameter to the device, specific to the request. The wIndex field is often used in
+        *   requests to specify an endpoint or an interface. */
+       uint16_t wIndex;
+       /* This field specifies the length of the data transferred during the second phase of the control transfer. */
+       uint16_t wlength;
+} __attribute__ ((packed));
+
+struct usb_string_descriptor {
+       uint8_t bLength; /* Size of descriptor ni bytes */
+       uint8_t bDescriptorType; /* String descriptor type */
+       uint16_t bString; /* unicode encoded string */
+} __attribute__ ((packed));
+
+struct wb {
+       uint8_t l; /* Lower byte */
+       uint8_t h; /* upper byte */
+} __attribute__ ((packed));
+
+
+
+struct usbdev_api_init_param {
+       /* USB device controller's base register address. */
+       uint32_t usb_reg_base;
+
+       /* Base memory location from where the stack can allocate data and buffers.
+        * Remark: The memory address set in this field should be accessible by USB DMA controller.
+        * Also this value should be aligned on 2048 byte boundary. */
+    uint32_t mem_base;
+
+       /* The size of memory buffer which stack can use.
+       Remark: The mem_size should be greater than the size returned by USBD_HW_API::GetMemSize() routine. */
+       uint32_t mem_size;
+
+       uint8_t max_num_ep; /* max number of endpoints supported by the USB device controller instance */
+       uint8_t pad0[3];
+
+       /* Event for USB interface reset.
+        * This event fires when the USB host requests that the device reset its interface.
+        * This event fires after the control endpoint has been automatically configured by the library.
+        * Remark: This event is called from USB_ISR context and hence is time-critical.
+        * Having delays in this callback will prevent the device from enumerating correctly or operate properly.
+        */
+       void (*USB_Reset_Event)(void);
+
+       /* Event for USB suspend.
+        * This event fires when the USB host suspends the device by halting its transmission of Start Of Frame
+        *   pulses to the device.
+        * This is generally hooked in order to move the device over to a low power state until the host wakes up
+        *   the device.
+        * Remark: This event is called from USB_ISR context and hence is time-critical.
+        * Having delays in this callback will cause other system issues.
+        */
+       void (*USB_Suspend_Event)(void);
+
+       /* Event for USB wake up or resume.
+        * This event fires when a the USB device interface is suspended and the host wakes up the device by
+        *   supplying Start Of Frame pulses.
+        * This is generally hooked to pull the user application out of a low power state and back into normal
+        *   operating mode.
+        * Remark: This event is called from USB_ISR context and hence is time-critical.
+        * Having delays in this callback will cause other system issues.
+        */
+       void (*USB_Resume_Event)(void);
+
+       void (*reserved0)(void); /* Reserved parameter should be set to zero. */
+
+       /* Event for USB Start Of Frame detection, when enabled.
+        * This event fires at the start of each USB frame, once per millisecond in full-speed mode or once per
+        *   125 microseconds in high-speed mode, and is synchronized to the USB bus.
+        * This event is time-critical; it is run once per millisecond (full-speed mode) and thus long handlers
+        *   will significantly degrade device performance.
+        * This event should only be enabled when needed to reduce device wake-ups.
+        * Remark: This event is not normally active - it must be manually enabled and disabled via the USB
+        *   interrupt register.
+        */
+       void (*USB_SOF_Event)(void);
+
+       /* Event for remote wake-up configuration, when enabled.
+        * This event fires when the USB host request the device to configure itself for remote wake-up capability.
+        * The USB host sends this request to device which report remote wake-up capable in their device
+        *   descriptors, before going to low-power state.
+        * The application layer should implement this callback if they have any special on board circuit to
+        *   triger remote wake up event. Also application can use this callback to differentiate the following
+        *   SUSPEND event is caused by cable plug-out or host SUSPEND request.
+        * The device can wake-up host only after receiving this callback and remote wake-up feature is enabled
+        *   by host. To signal remote wake-up the device has to generate resume signaling on bus by calling
+        *   usb_rom_api->hw->WakeUp() routine.
+        * Parameters:
+        *   usb_handle = Handle to the USB device stack.
+        *   enable = When 0 - Clear the wake-up configuration, 1 - Enable the wake-up configuration.
+        * Returns: The call back should return ErrorCode to indicate success or error condition.
+        */
+       uint32_t (*USB_WakeUpCfg)(void* usb_handle, uint32_t enable);
+
+       void (*USB_Power_Event)(void); /* Reserved parameter should be set to zero. */
+
+       /* Event for error condition.
+        * This event fires when USB device controller detect an error condition in the system.
+        * Parameters:
+        *   usb_handle = Handle to the USB device stack.
+        *   status = USB device interrupt status register.
+        * Returns: The call back should return ErrorCode to indicate success or error condition.
+        */
+       void (*USB_Error_Event)(void* usb_handle, uint32_t status);
+
+       /* Event for USB configuration number changed.
+        * This event fires when a the USB host changes the selected configuration number.
+        * On receiving configuration change request from host, the stack enables/configures the endpoints
+        *   needed by the new configuration before calling this callback function.
+        * Remark: This event is called from USB_ISR context and hence is time-critical.
+        * Having delays in this callback will prevent the device from enumerating correctly or operate properly.
+        */
+       void (*USB_Configure_Event)(void);
+
+       /* Event for USB interface setting changed.
+        * This event fires when a the USB host changes the interface setting to one of alternate interface settings.
+        * On receiving interface change request from host, the stack enables/configures the endpoints needed by
+        *   the new alternate interface setting before calling this callback function.
+        * Remark: This event is called from USB_ISR context and hence is time-critical.
+        * Having delays in this callback will prevent the device from enumerating correctly or operate properly.
+        */
+       void (*USB_Interface_Event)(void);
+
+       /* Event for USB feature changed.
+        * This event fires when a the USB host send set/clear feature request.
+        * The stack handles this request for USB_FEATURE_REMOTE_WAKEUP, USB_FEATURE_TEST_MODE and
+        *   USB_FEATURE_ENDPOINT_STALL features only.
+        * On receiving feature request from host, the stack handle the request appropriately and then calls this
+        *   callback function.
+        * Remark: This event is called from USB_ISR context and hence is time-critical.
+        * Having delays in this callback will prevent the device from enumerating correctly or operate properly.
+        */
+       void (*USB_Feature_Event)(void);
+
+       /* Reserved parameter for future use. should be set to zero. */
+       uint32_t (*virt_to_phys)(void *vaddr);
+       void (*cache_flush)(uint32_t *start_adr, uint32_t *end_adr);
+} __attribute__ ((packed));
+
+
+
+
+
+struct usbdev_hw_api {
+       /* GetMemSize
+        * Function to determine the memory required by the USB device stack's DCD and core layers.
+        * This function is called by application layer before calling usb_rom_api->hw->init().
+        * Remark: Some memory areas are not accessible by all bus masters.
+        * Parameters:
+        *   param = Structure containing USB device stack initialization parameters.
+        * Returns: Returns the required memory size in bytes.
+        */
+       uint32_t (*GetMemSize)(struct usbdev_api_init_param* param);
+
+       /* Init
+        * Function to initialize USB device stack's DCD and core layers.
+        * This function is called by application layer to initialize USB hardware and core layers.
+        * On successful initialization the function returns a handle to USB device stack which should be passed
+        *   to the rest of the functions.
+        * Parameters:
+        *   usb_handle = Pointer to the USB device stack handle of type USBD_HANDLE_T.
+        *   core_desc = ?
+        *   param = Structure containing USB device stack initialization parameters.
+        * Returns: Returns ErrorCode to indicate success or error condition.
+        * Return values:
+        *   LPC_OK(0) = On success
+        *   ERR_USBD_BAD_MEM_BUF(0x0004000b) = When insufficient memory buffer is passed or memory is not
+        *      aligned on 2048 boundary.
+        */
+       void* (*Init)(void* usb_handle, struct usb_core_descriptor* core_desc, struct usbdev_api_init_param* param);
+
+       /* Connect
+        * Function to make USB device visible/invisible on the USB bus.
+        * This function is called after the USB initialization.
+        * This function uses the soft connect feature to make the device visible on the USB bus. This function
+        *   is called only after the application is ready to handle the USB data. The enumeration process is
+        *   started by the host after the device detection. The driver handles the enumeration process according
+        *   to the USB descriptors passed in the USB initialization function.
+        * Parameters:
+        *   usb_handle = Handle to the USB device stack.
+        *   con = States whether to connect (1) or to disconnect (0).
+        * Returns: Nothing.
+        */
+       void (*Connect)(void* usb_handle, uint32_t con);
+
+       /* ISR
+        * Function to USB device controller interrupt events.
+        * When the user application is active the interrupt handlers are mapped in the user flash space.
+        * The user application must provide an interrupt handler for the USB interrupt and call this function in
+        *   the interrupt handler routine. The driver interrupt handler takes appropriate action according to
+        *   the data received on the USB bus.
+        * Parameters:
+        *   usb_handle = Handle to the USB device stack.
+        * Returns: Nothing.
+        */
+       void (*ISR)(void* usb_handle);
+
+       /* Reset
+        * Function to Reset USB device stack and hardware controller.
+        * Reset USB device stack and hardware controller.
+        * Disables all endpoints except EP0.
+        * Clears all pending interrupts and resets endpoint transfer queues.
+        * This function is called internally by usb_rom_api->hw->init() and from reset event.
+        * Parameters:
+        *   usb_handle = Handle to the USB device stack.
+        * Returns: Nothing.
+        */
+       void (*Reset)(void* usb_handle);
+
+       /* ForceFullSpeed
+        * Function to force high speed USB device to operate in full speed mode.
+        * This function is useful for testing the behavior of current device when connected to a full speed only hosts.
+        * Parameters:
+        *   usb_handle = Handle to the USB device stack.
+        *   cfg = When 1 - set force full-speed or 0 - clear force full-speed.
+        * Returns: Nothing.
+        */
+       void (*ForceFullSpeed)(void* usb_handle, uint32_t cfg);
+
+       /* WakeUpCfg
+        * Function to configure USB device controller to walk-up host on remote events.
+        * This function is called by application layer to configure the USB device controller to wake up on
+        *   remote events. It is recommended to call this function from users's USB_WakeUpCfg() callback routine
+        *   registered with stack.
+        * Remark: User's USB_WakeUpCfg() is registered with stack by setting the USB_WakeUpCfg member of struct
+        *   usbdev_api_init_param structure before calling usb_rom_api->hw->Init() routine.
+        *   Certain USB device controllers needed to keep some clocks always on to generate resume signaling
+        *   through usb_rom_api->hw->WakeUp().
+        *   This hook is provided to support such controllers. In most controllers cases this is an empty routine.
+        * Parameters:
+        *   usb_handle = Handle to the USB device stack.
+        *   cfg = 1 - Configure controller to wake on remote events. 0 - Configure controller not to wake on remote events.
+        * Returns: Nothing.
+        */
+       void (*WakeUpCfg)(void* usb_handle, uint32_t cfg);
+
+       /* SetAddress
+        * Function to set USB address assigned by host in device controller hardware.
+        * This function is called automatically when USB_REQUEST_SET_ADDRESS request is received by the stack
+        *   from USB host.
+        * This interface is provided to users to invoke this function in other scenarios which are not handled
+        *   by current stack. In most user applications this function is not called directly.
+        *   Also this function can be used by users who are selectively modifying the USB device stack's
+        *   standard handlers through callback interface exposed by the stack.
+        * Parameters:
+        *   usb_handle = Handle to the USB device stack.
+        *   adr = USB bus Address to which the device controller should respond. Usually assigned by the USB host.
+        * Returns: Nothing.
+        */
+       void (*SetAddress)(void* usb_handle, uint32_t adr);
+
+       /* Configure
+        * Function to configure device controller hardware with selected configuration.
+        * This function is called automatically when USB_REQUEST_SET_CONFIGURATION request is received by the
+        *   stack from USB host.
+        * This interface is provided to users to invoke this function in other scenarios which are not handled
+        *   by current stack. In most user applications this function is not called directly.
+        *   Also this function can be used by users who are selectively modifying the USB device stack's
+        *   standard handlers through callback interface exposed by the stack.
+        * Parameters:
+        *   usb_handle = Handle to the USB device stack.
+        *   cfg = Configuration index.
+        * Returns: Nothing.
+        */
+       void (*Configure)(void* usb_handle, uint32_t cfg);
+
+        /* ConfigEP
+        * Function to configure USB Endpoint according to descriptor.
+        * This function is called automatically when USB_REQUEST_SET_CONFIGURATION request is received by the
+        *   stack from USB host.
+      &