aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.include5
-rw-r--r--lib/cm3/nvic.c (renamed from lib/stm32/nvic.c)62
-rw-r--r--lib/cm3/scb.c (renamed from lib/stm32/f1/scb.c)2
-rw-r--r--lib/cm3/systick.c (renamed from lib/stm32/systick.c)65
-rw-r--r--lib/cm3/vector.c (renamed from lib/lpc17xx/vector.c)54
-rw-r--r--lib/dispatch/vector_chipset.c11
-rw-r--r--lib/dispatch/vector_nvic.c35
-rw-r--r--lib/efm32/efm32g/Makefile38
-rw-r--r--lib/efm32/efm32g/libopencm3_efm32g.ld79
-rw-r--r--lib/efm32/efm32g/libopencm3_efm32g880f128.ld15
-rw-r--r--lib/efm32/efm32gg/Makefile38
-rw-r--r--lib/efm32/efm32gg/libopencm3_efm32gg.ld79
-rw-r--r--lib/efm32/efm32gg/libopencm3_efm32gg990f1024.ld15
-rw-r--r--lib/efm32/efm32lg/Makefile38
-rw-r--r--lib/efm32/efm32lg/libopencm3_efm32lg.ld79
-rw-r--r--lib/efm32/efm32tg/Makefile38
-rw-r--r--lib/efm32/efm32tg/libopencm3_efm32tg.ld79
-rw-r--r--lib/efm32/efm32tg/libopencm3_efm32tg840f32.ld15
-rw-r--r--lib/lm3s/Makefile2
-rw-r--r--lib/lm3s/vector.c454
-rw-r--r--lib/lm4f/Makefile35
-rw-r--r--lib/lm4f/gpio.c (renamed from lib/stm32/f2/scb.c)18
-rw-r--r--lib/lm4f/libopencm3_lm4f.ld2
-rw-r--r--lib/lm4f/rcc.c493
-rw-r--r--lib/lm4f/systemcontrol.c40
-rw-r--r--lib/lpc13xx/Makefile4
-rw-r--r--lib/lpc17xx/Makefile4
-rw-r--r--lib/lpc43xx/Makefile5
-rw-r--r--lib/lpc43xx/nvic.c76
-rw-r--r--lib/lpc43xx/systick.c69
-rw-r--r--lib/lpc43xx/vector.c264
-rw-r--r--lib/lpc43xx/vector_chipset.c48
-rw-r--r--lib/stm32/can.c (renamed from lib/stm32/f1/can.c)185
-rw-r--r--lib/stm32/common/crc_common_all.c (renamed from lib/stm32/crc.c)6
-rw-r--r--lib/stm32/common/dac_common_all.c (renamed from lib/stm32/dac.c)6
-rw-r--r--lib/stm32/common/dma_common_f13.c431
-rw-r--r--lib/stm32/common/dma_common_f24.c780
-rw-r--r--lib/stm32/common/gpio_common_all.c139
-rw-r--r--lib/stm32/common/gpio_common_f24.c195
-rw-r--r--lib/stm32/common/i2c_common_all.c (renamed from lib/stm32/i2c.c)152
-rw-r--r--lib/stm32/common/iwdg_common_all.c (renamed from lib/stm32/iwdg.c)6
-rw-r--r--lib/stm32/common/pwr_common_all.c217
-rw-r--r--lib/stm32/common/rtc_common_bcd.c78
-rw-r--r--lib/stm32/common/spi_common_all.c (renamed from lib/stm32/spi.c)18
-rw-r--r--lib/stm32/common/usart_common_all.c (renamed from lib/stm32/usart.c)38
-rw-r--r--lib/stm32/desig.c (renamed from lib/stm32/f1/desig.c)24
-rw-r--r--lib/stm32/exti2.c (renamed from lib/stm32/f4/exti.c)26
-rw-r--r--lib/stm32/f1/Makefile13
-rw-r--r--lib/stm32/f1/adc.c114
-rw-r--r--lib/stm32/f1/crc.c29
-rw-r--r--lib/stm32/f1/dac.c28
-rw-r--r--lib/stm32/f1/dma.c349
-rw-r--r--lib/stm32/f1/flash.c63
-rw-r--r--lib/stm32/f1/gpio.c142
-rw-r--r--lib/stm32/f1/i2c.c28
-rw-r--r--lib/stm32/f1/iwdg.c28
-rw-r--r--lib/stm32/f1/rcc.c181
-rw-r--r--lib/stm32/f1/rtc.c2
-rw-r--r--lib/stm32/f1/spi.c28
-rw-r--r--lib/stm32/f1/usart.c28
-rw-r--r--lib/stm32/f1/vector.c296
-rw-r--r--lib/stm32/f2/Makefile9
-rw-r--r--lib/stm32/f2/crc.c29
-rw-r--r--lib/stm32/f2/dac.c28
-rw-r--r--lib/stm32/f2/dma.c28
-rw-r--r--lib/stm32/f2/exti.c146
-rw-r--r--lib/stm32/f2/flash.c72
-rw-r--r--lib/stm32/f2/gpio.c134
-rw-r--r--lib/stm32/f2/i2c.c28
-rw-r--r--lib/stm32/f2/iwdg.c28
-rw-r--r--lib/stm32/f2/rcc.c2
-rw-r--r--lib/stm32/f2/rtc.c27
-rw-r--r--lib/stm32/f2/spi.c28
-rw-r--r--lib/stm32/f2/timer.c928
-rw-r--r--lib/stm32/f2/usart.c28
-rw-r--r--lib/stm32/f2/vector.c336
-rw-r--r--lib/stm32/f4/Makefile14
-rw-r--r--lib/stm32/f4/adc.c1021
-rw-r--r--lib/stm32/f4/crc.c29
-rw-r--r--lib/stm32/f4/dac.c28
-rw-r--r--lib/stm32/f4/dma.c28
-rw-r--r--lib/stm32/f4/flash.c74
-rw-r--r--lib/stm32/f4/gpio.c134
-rw-r--r--lib/stm32/f4/i2c.c28
-rw-r--r--lib/stm32/f4/iwdg.c28
-rw-r--r--lib/stm32/f4/rcc.c4
-rw-r--r--lib/stm32/f4/rtc.c27
-rw-r--r--lib/stm32/f4/spi.c28
-rw-r--r--lib/stm32/f4/timer.c928
-rw-r--r--lib/stm32/f4/usart.c28
-rw-r--r--lib/stm32/f4/vector.c341
-rw-r--r--lib/stm32/f4/vector_chipset.c27
-rw-r--r--lib/stm32/l1/Makefile40
-rw-r--r--lib/stm32/l1/crc.c29
-rw-r--r--lib/stm32/l1/dac.c28
-rw-r--r--lib/stm32/l1/flash.c52
-rw-r--r--lib/stm32/l1/gpio.c28
-rw-r--r--lib/stm32/l1/i2c.c28
-rw-r--r--lib/stm32/l1/iwdg.c28
-rw-r--r--lib/stm32/l1/libopencm3_stm32l1.ld83
-rw-r--r--lib/stm32/l1/pwr.c37
-rw-r--r--lib/stm32/l1/rcc.c549
-rw-r--r--lib/stm32/l1/rtc.c27
-rw-r--r--lib/stm32/l1/spi.c28
-rw-r--r--lib/stm32/l1/stm32l15xx8.ld (renamed from lib/stm32/f4/scb.c)20
-rw-r--r--lib/stm32/l1/stm32l15xxb.ld31
-rw-r--r--lib/stm32/l1/usart.c28
-rw-r--r--lib/stm32/timer.c (renamed from lib/stm32/f1/timer.c)154
-rw-r--r--lib/usb/usb.c106
-rw-r--r--lib/usb/usb_control.c199
-rw-r--r--lib/usb/usb_f103.c99
-rw-r--r--lib/usb/usb_f107.c338
-rw-r--r--lib/usb/usb_f207.c91
-rw-r--r--lib/usb/usb_fx07_common.c318
-rw-r--r--lib/usb/usb_fx07_common.h38
-rw-r--r--lib/usb/usb_private.h82
-rw-r--r--lib/usb/usb_standard.c196
117 files changed, 7627 insertions, 5539 deletions
diff --git a/lib/Makefile.include b/lib/Makefile.include
index 9fbea24..f9eeefe 100644
--- a/lib/Makefile.include
+++ b/lib/Makefile.include
@@ -23,6 +23,9 @@ ifneq ($(V),1)
Q := @
endif
+# common objects
+OBJS += vector.o systick.o scb.o nvic.o assert.o
+
all: $(SRCLIBDIR)/$(LIBNAME).a
$(SRCLIBDIR)/$(LIBNAME).a: $(SRCLIBDIR)/$(LIBNAME).ld $(OBJS)
@@ -39,7 +42,7 @@ $(SRCLIBDIR)/$(LIBNAME).ld: $(LIBNAME).ld
$(Q)$(CC) $(CFLAGS) -o $@ -c $<
clean:
- @printf " CLEAN lib/stm32/f1\n"
+ @printf " CLEAN lib$(subst $(shell cd $(dir $(lastword $(MAKEFILE_LIST))) && pwd),,$(shell pwd))\n"
$(Q)rm -f *.o *.d ../*.o ../*.d
$(Q)rm -f $(SRCLIBDIR)/$(LIBNAME).a
$(Q)rm -f $(SRCLIBDIR)/$(LIBNAME).ld
diff --git a/lib/stm32/nvic.c b/lib/cm3/nvic.c
index 84fa674..db187b3 100644
--- a/lib/stm32/nvic.c
+++ b/lib/cm3/nvic.c
@@ -1,31 +1,9 @@
-/** @defgroup STM32F_nvic_file NVIC
-
-@ingroup STM32F_files
-
-@brief <b>libopencm3 STM32F Nested Vectored Interrupt Controller</b>
-
-@version 1.0.0
-
-@author @htmlonly &copy; @endhtmlonly 2010 Thomas Otto <tommi@viadmin.org>
-@author @htmlonly &copy; @endhtmlonly 2012 Fergus Noble <fergusnoble@gmail.com>
-
-@date 18 August 2012
-
-The STM32F series provides up to 68 maskable user interrupts for the STM32F10x
-series, and 87 for the STM32F2xx and STM32F4xx series.
-
-The NVIC registers are defined by the ARM standards but the STM32F series have some
-additional limitations
-@see Cortex-M3 Devices Generic User Guide
-@see STM32F10xxx Cortex-M3 programming manual
-
-LGPL License Terms @ref lgpl_license
-*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
* Copyright (C) 2012 Fergus Noble <fergusnoble@gmail.com>
+ * Copyright (C) 2012 Benjamin Vernoux <titanmkd@gmail.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -40,10 +18,32 @@ LGPL License Terms @ref lgpl_license
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
+/** @defgroup CM3_nvic_file NVIC
+@ingroup CM3_files
+
+@brief <b>libopencm3 Cortex Nested Vectored Interrupt Controller</b>
+
+@version 1.0.0
+
+@author @htmlonly &copy; @endhtmlonly 2010 Thomas Otto <tommi@viadmin.org>
+@author @htmlonly &copy; @endhtmlonly 2012 Fergus Noble <fergusnoble@gmail.com>
+
+@date 18 August 2012
+
+Cortex processors provide 14 cortex-defined interrupts (NMI, usage faults,
+systicks etc.) and varying numbers of implementation defined interrupts
+(typically peripherial interrupts and DMA).
+
+@see Cortex-M3 Devices Generic User Guide
+@see STM32F10xxx Cortex-M3 programming manual
+
+LGPL License Terms @ref lgpl_license
+*/
/**@{*/
-#include <libopencm3/stm32/nvic.h>
+#include <libopencm3/cm3/nvic.h>
+#include <libopencm3/cm3/scs.h>
/*-----------------------------------------------------------------------------*/
/** @brief NVIC Enable Interrupt
@@ -153,7 +153,18 @@ Control Register (SCB_AIRCR), as done in @ref scb_set_priority_grouping.
void nvic_set_priority(u8 irqn, u8 priority)
{
- NVIC_IPR(irqn) = priority;
+ /* code from lpc43xx/nvic.c -- this is quite a hack and alludes to the
+ * negative interrupt numbers assigned to the system interrupts. better
+ * handling would mean signed integers. */
+ if(irqn>=NVIC_IRQ_COUNT)
+ {
+ /* Cortex-M system interrupts */
+ SCS_SHPR( (irqn&0xF)-4 ) = priority;
+ }else
+ {
+ /* Device specific interrupts */
+ NVIC_IPR(irqn) = priority;
+ }
}
/*-----------------------------------------------------------------------------*/
@@ -171,4 +182,3 @@ void nvic_generate_software_interrupt(u16 irqn)
NVIC_STIR |= irqn;
}
/**@}*/
-
diff --git a/lib/stm32/f1/scb.c b/lib/cm3/scb.c
index e59134e..904bd7c 100644
--- a/lib/stm32/f1/scb.c
+++ b/lib/cm3/scb.c
@@ -17,7 +17,7 @@
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <libopencm3/stm32/f1/scb.h>
+#include <libopencm3/cm3/scb.h>
void scb_reset_core(void)
{
diff --git a/lib/stm32/systick.c b/lib/cm3/systick.c
index 36077cc..874261b 100644
--- a/lib/stm32/systick.c
+++ b/lib/cm3/systick.c
@@ -1,27 +1,8 @@
-/** @defgroup STM32F_systick_file SysTick
-
-@ingroup STM32F_files
-
-@brief <b>libopencm3 STM32Fxx System Tick Timer</b>
-
-@version 1.0.0
-
-@author @htmlonly &copy; @endhtmlonly 2010 Thomas Otto <tommi@viadmin.org>
-
-@date 19 August 2012
-
-This library supports the System Tick timer in the
-STM32F series of ARM Cortex Microcontrollers by ST Microelectronics.
-
-The System Tick timer is part of the ARM Cortex core. It is a 24 bit
-down counter that can be configured with an automatical reload value.
-
-LGPL License Terms @ref lgpl_license
- */
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
+ * Copyright (C) 2012 Benjamin Vernoux <titanmkd@gmail.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -36,9 +17,28 @@ LGPL License Terms @ref lgpl_license
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
+/** @defgroup CM3_systick_file SysTick
+
+@ingroup CM3_files
+
+@brief <b>libopencm3 Cortex System Tick Timer</b>
+
+@version 1.0.0
+
+@author @htmlonly &copy; @endhtmlonly 2010 Thomas Otto <tommi@viadmin.org>
+
+@date 19 August 2012
+
+This library supports the System Tick timer in ARM Cortex Microcontrollers.
+
+The System Tick timer is part of the ARM Cortex core. It is a 24 bit
+down counter that can be configured with an automatical reload value.
+
+LGPL License Terms @ref lgpl_license
+ */
/**@{*/
-#include <libopencm3/stm32/systick.h>
+#include <libopencm3/cm3/systick.h>
/*-----------------------------------------------------------------------------*/
/** @brief SysTick Set the Automatic Reload Value.
@@ -60,9 +60,20 @@ void systick_set_reload(u32 value)
@returns 24 bit reload value as u32.
*/
+u32 systick_get_reload(void)
+{
+ return (STK_LOAD & 0x00FFFFFF);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief Get the current SysTick counter value.
+
+@returns 24 bit current value as u32.
+*/
+
u32 systick_get_value(void)
{
- return STK_VAL;
+ return (STK_VAL & 0x00FFFFFF);
}
/*-----------------------------------------------------------------------------*/
@@ -135,5 +146,15 @@ u8 systick_get_countflag(void)
else
return 0;
}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief SysTick Get Calibration Value
+
+@returns Current calibration value
+*/
+u32 systick_get_calib(void)
+{
+ return (STK_CALIB&0x00FFFFFF);
+}
/**@}*/
diff --git a/lib/lpc17xx/vector.c b/lib/cm3/vector.c
index 518f562..3cfd4f5 100644
--- a/lib/lpc17xx/vector.c
+++ b/lib/cm3/vector.c
@@ -1,7 +1,8 @@
/*
* This file is part of the libopencm3 project.
*
- * Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
+ * Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>,
+ * Copyright (C) 2012 chrysn <chrysn@fsfe.org>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -14,19 +15,26 @@
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
- * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <libopencm3/cm3/vector.h>
+
+/* load optional platform dependent initialization routines */
+#include "../dispatch/vector_chipset.c"
+/* load the weak symbols for IRQ_HANDLERS */
+#include "../dispatch/vector_nvic.c"
+
#define WEAK __attribute__ ((weak))
/* Symbols exported by the linker script(s): */
extern unsigned _data_loadaddr, _data, _edata, _ebss, _stack;
void main(void);
-void reset_handler(void);
void blocking_handler(void);
void null_handler(void);
+void WEAK reset_handler(void);
void WEAK nmi_handler(void);
void WEAK hard_fault_handler(void);
void WEAK mem_manage_handler(void);
@@ -37,38 +45,37 @@ void WEAK debug_monitor_handler(void);
void WEAK pend_sv_handler(void);
void WEAK sys_tick_handler(void);
-/* TODO: Interrupt handler prototypes */
-
__attribute__ ((section(".vectors")))
-void (*const vector_table[]) (void) = {
- (void*)&_stack, /* Addr: 0x0000_0000 */
- reset_handler, /* Addr: 0x0000_0004 */
- nmi_handler, /* Addr: 0x0000_0008 */
- hard_fault_handler, /* Addr: 0x0000_000C */
- mem_manage_handler, /* Addr: 0x0000_0010 */
- bus_fault_handler, /* Addr: 0x0000_0014 */
- usage_fault_handler, /* Addr: 0x0000_0018 */
- 0, 0, 0, 0, /* Reserved Addr: 0x0000_001C - 0x0000_002B */
- sv_call_handler, /* Addr: 0x0000_002C */
- debug_monitor_handler, /* Addr: 0x0000_0030 */
- 0, /* Reserved Addr: 0x0000_00034 */
- pend_sv_handler, /* Addr: 0x0000_0038 */
- sys_tick_handler, /* Addr: 0x0000_003C */
+vector_table_t vector_table = {
+ .initial_sp_value = &_stack,
+ .reset = reset_handler,
+ .nmi = nmi_handler,
+ .hard_fault = hard_fault_handler,
+ .memory_manage_fault = mem_manage_handler,
+ .bus_fault = bus_fault_handler,
+ .usage_fault = usage_fault_handler,
+ .debug_monitor = debug_monitor_handler,
+ .sv_call = sv_call_handler,
+ .pend_sv = pend_sv_handler,
+ .systick = sys_tick_handler,
+ .irq = {
+ IRQ_HANDLERS
+ }
};
-
-void reset_handler(void)
+void WEAK __attribute__ ((naked)) reset_handler(void)
{
volatile unsigned *src, *dest;
- __asm__("MSR msp, %0" : : "r"(&_stack));
-
for (src = &_data_loadaddr, dest = &_data; dest < &_edata; src++, dest++)
*dest = *src;
while (dest < &_ebss)
*dest++ = 0;
+ /* might be provided by platform specific vector.c */
+ pre_main();
+
/* Call the application's entry point. */
main();
}
@@ -92,4 +99,3 @@ void null_handler(void)
#pragma weak debug_monitor_handler = null_handler
#pragma weak pend_sv_handler = null_handler
#pragma weak sys_tick_handler = null_handler
-/* TODO: Interrupt handler weak aliases */
diff --git a/lib/dispatch/vector_chipset.c b/lib/dispatch/vector_chipset.c
new file mode 100644
index 0000000..796276c
--- /dev/null
+++ b/lib/dispatch/vector_chipset.c
@@ -0,0 +1,11 @@
+#if defined(STM32F4)
+# include "../stm32/f4/vector_chipset.c"
+
+#elif defined(LPC43XX)
+# include "../lpc43xx/vector_chipset.c"
+
+#else
+
+static void pre_main(void) {}
+
+#endif
diff --git a/lib/dispatch/vector_nvic.c b/lib/dispatch/vector_nvic.c
new file mode 100644
index 0000000..182de4c
--- /dev/null
+++ b/lib/dispatch/vector_nvic.c
@@ -0,0 +1,35 @@
+#if defined(STM32F1)
+# include "../stm32/f1/vector_nvic.c"
+#elif defined(STM32F2)
+# include "../stm32/f2/vector_nvic.c"
+#elif defined(STM32F4)
+# include "../stm32/f4/vector_nvic.c"
+#elif defined(STM32L1)
+# include "../stm32/l1/vector_nvic.c"
+
+#elif defined(EFM32TG)
+# include "../efm32/efm32tg/vector_nvic.c"
+#elif defined(EFM32G)
+# include "../efm32/efm32g/vector_nvic.c"
+#elif defined(EFM32LG)
+# include "../efm32/efm32lg/vector_nvic.c"
+#elif defined(EFM32GG)
+# include "../efm32/efm32gg/vector_nvic.c"
+
+#elif defined(LPC13XX)
+# include "../lpc13xx/vector_nvic.c"
+#elif defined(LPC17XX)
+# include "../lpc17xx/vector_nvic.c"
+#elif defined(LPC43XX)
+# include "../lpc43xx/vector_nvic.c"
+
+#elif defined(LM3S) || defined(LM4F)
+/* Yes, we use the same interrupt table for both LM3S and LM4F */
+# include "../lm3s/vector_nvic.c"
+
+#else
+# warning"no interrupts defined for chipset; not allocating space in the vector table"
+
+#define IRQ_HANDLERS
+
+#endif
diff --git a/lib/efm32/efm32g/Makefile b/lib/efm32/efm32g/Makefile
new file mode 100644
index 0000000..1dd4485
--- /dev/null
+++ b/lib/efm32/efm32g/Makefile
@@ -0,0 +1,38 @@
+##
+## This file is part of the libopencm3 project.
+##
+## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
+## Copyright (C) 2012 chrysn <chrysn@fsfe.org>
+##
+## This library is free software: you can redistribute it and/or modify
+## it under the terms of the GNU Lesser General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This library 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 Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public License
+## along with this library. If not, see <http://www.gnu.org/licenses/>.
+##
+
+LIBNAME = libopencm3_efm32g
+FAMILY = EFM32G
+
+PREFIX ?= arm-none-eabi
+#PREFIX ?= arm-elf
+CC = $(PREFIX)-gcc
+AR = $(PREFIX)-ar
+CFLAGS = -Os -g -Wall -Wextra -I../../../include -fno-common \
+ -mcpu=cortex-m3 -mthumb -Wstrict-prototypes \
+ -ffunction-sections -fdata-sections -MD -D$(FAMILY)
+# ARFLAGS = rcsv
+ARFLAGS = rcs
+OBJS =
+
+VPATH += ../:../../cm3
+
+include ../../Makefile.include
+
diff --git a/lib/efm32/efm32g/libopencm3_efm32g.ld b/lib/efm32/efm32g/libopencm3_efm32g.ld
new file mode 100644
index 0000000..8ef5e42
--- /dev/null
+++ b/lib/efm32/efm32g/libopencm3_efm32g.ld
@@ -0,0 +1,79 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>,
+ * Copyright (C) 2012 chrysn <chrysn@fsfe.org>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Generic linker script for EFM32 targets using libopencm3. */
+
+/* Memory regions must be defined in the ld script which includes this one. */
+
+/* Enforce emmition of the vector table. */
+EXTERN (vector_table)
+
+/* Define the entry point of the output file. */
+ENTRY(reset_handler)
+
+/* Define sections. */
+SECTIONS
+{
+ . = ORIGIN(rom);
+
+ .text : {
+ *(.vectors) /* Vector table */
+ *(.text*) /* Program code */
+ . = ALIGN(4);
+ *(.rodata*) /* Read-only data */
+ . = ALIGN(4);
+ _etext = .;
+ } >rom
+
+ . = ORIGIN(ram);
+
+ .data : AT(_etext) {
+ _data = .;
+ *(.data*) /* Read-write initialized data */
+ . = ALIGN(4);
+ _edata = .;
+ } >ram
+
+ .bss : {
+ *(.bss*) /* Read-write zero initialized data */
+ *(COMMON)
+ . = ALIGN(4);
+ _ebss = .;
+ } >ram AT >rom
+ _data_loadaddr = LOADADDR(.data);
+
+ /*
+ * The .eh_frame section appears to be used for C++ exception handling.
+ * You may need to fix this if you're using C++.
+ */
+ /DISCARD/ : { *(.eh_frame) }
+
+ /*
+ * Another section used by C++ stuff, appears when using newlib with
+ * 64bit (long long) printf support - discard it for now.
+ */
+ /DISCARD/ : { *(.ARM.exidx) }
+
+ . = ALIGN(4);
+ end = .;
+}
+
+PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram));
+
diff --git a/lib/efm32/efm32g/libopencm3_efm32g880f128.ld b/lib/efm32/efm32g/libopencm3_efm32g880f128.ld
new file mode 100644
index 0000000..09c6fb0
--- /dev/null
+++ b/lib/efm32/efm32g/libopencm3_efm32g880f128.ld
@@ -0,0 +1,15 @@
+/* lengths from d011_efm32tg840_datasheet.pdf table 1.1, offset from
+ * d0034_efm32tg_reference_manual.pdf figure 5.2.
+ *
+ * the origins and memory structure are constant over all tinygeckos, but the
+ * MEMORY section requires the use of constants, and has thus to be duplicated
+ * over the chip variants.
+ * */
+
+MEMORY
+{
+ rom (rx) : ORIGIN = 0, LENGTH = 128k
+ ram (rwx) : ORIGIN = 0x20000000, LENGTH = 16k
+}
+
+INCLUDE libopencm3_efm32g.ld;
diff --git a/lib/efm32/efm32gg/Makefile b/lib/efm32/efm32gg/Makefile
new file mode 100644
index 0000000..2407859
--- /dev/null
+++ b/lib/efm32/efm32gg/Makefile
@@ -0,0 +1,38 @@
+##
+## This file is part of the libopencm3 project.
+##
+## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
+## Copyright (C) 2012 chrysn <chrysn@fsfe.org>
+##
+## This library is free software: you can redistribute it and/or modify
+## it under the terms of the GNU Lesser General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This library 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 Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public License
+## along with this library. If not, see <http://www.gnu.org/licenses/>.
+##
+
+LIBNAME = libopencm3_efm32gg
+FAMILY = EFM32GG
+
+PREFIX ?= arm-none-eabi
+#PREFIX ?= arm-elf
+CC = $(PREFIX)-gcc
+AR = $(PREFIX)-ar
+CFLAGS = -Os -g -Wall -Wextra -I../../../include -fno-common \
+ -mcpu=cortex-m3 -mthumb -Wstrict-prototypes \
+ -ffunction-sections -fdata-sections -MD -D$(FAMILY)
+# ARFLAGS = rcsv
+ARFLAGS = rcs
+OBJS =
+
+VPATH += ../:../../cm3
+
+include ../../Makefile.include
+
diff --git a/lib/efm32/efm32gg/libopencm3_efm32gg.ld b/lib/efm32/efm32gg/libopencm3_efm32gg.ld
new file mode 100644
index 0000000..8ef5e42
--- /dev/null
+++ b/lib/efm32/efm32gg/libopencm3_efm32gg.ld
@@ -0,0 +1,79 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>,
+ * Copyright (C) 2012 chrysn <chrysn@fsfe.org>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Generic linker script for EFM32 targets using libopencm3. */
+
+/* Memory regions must be defined in the ld script which includes this one. */
+
+/* Enforce emmition of the vector table. */
+EXTERN (vector_table)
+
+/* Define the entry point of the output file. */
+ENTRY(reset_handler)
+
+/* Define sections. */
+SECTIONS
+{
+ . = ORIGIN(rom);
+
+ .text : {
+ *(.vectors) /* Vector table */
+ *(.text*) /* Program code */
+ . = ALIGN(4);
+ *(.rodata*) /* Read-only data */
+ . = ALIGN(4);
+ _etext = .;
+ } >rom
+
+ . = ORIGIN(ram);
+
+ .data : AT(_etext) {
+ _data = .;
+ *(.data*) /* Read-write initialized data */
+ . = ALIGN(4);
+ _edata = .;
+ } >ram
+
+ .bss : {
+ *(.bss*) /* Read-write zero initialized data */
+ *(COMMON)
+ . = ALIGN(4);
+ _ebss = .;
+ } >ram AT >rom
+ _data_loadaddr = LOADADDR(.data);
+
+ /*
+ * The .eh_frame section appears to be used for C++ exception handling.
+ * You may need to fix this if you're using C++.
+ */
+ /DISCARD/ : { *(.eh_frame) }
+
+ /*
+ * Another section used by C++ stuff, appears when using newlib with
+ * 64bit (long long) printf support - discard it for now.
+ */
+ /DISCARD/ : { *(.ARM.exidx) }
+
+ . = ALIGN(4);
+ end = .;
+}
+
+PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram));
+
diff --git a/lib/efm32/efm32gg/libopencm3_efm32gg990f1024.ld b/lib/efm32/efm32gg/libopencm3_efm32gg990f1024.ld
new file mode 100644
index 0000000..694e17a
--- /dev/null
+++ b/lib/efm32/efm32gg/libopencm3_efm32gg990f1024.ld
@@ -0,0 +1,15 @@
+/* lengths from d046_efm32gg990_datasheet.pdf table 1.1, offset from
+ * d0034_efm32tg_reference_manual.pdf figure 5.2.
+ *
+ * the origins and memory structure are constant over all giantgeckos, but the
+ * MEMORY section requires the use of constants, and has thus to be duplicated
+ * over the chip variants.
+ * */
+
+MEMORY
+{
+ rom (rx) : ORIGIN = 0, LENGTH = 1024k
+ ram (rwx) : ORIGIN = 0x20000000, LENGTH = 128k
+}
+
+INCLUDE libopencm3_efm32gg.ld;
diff --git a/lib/efm32/efm32lg/Makefile b/lib/efm32/efm32lg/Makefile
new file mode 100644
index 0000000..9b6343c
--- /dev/null
+++ b/lib/efm32/efm32lg/Makefile
@@ -0,0 +1,38 @@
+##
+## This file is part of the libopencm3 project.
+##
+## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
+## Copyright (C) 2012 chrysn <chrysn@fsfe.org>
+##
+## This library is free software: you can redistribute it and/or modify
+## it under the terms of the GNU Lesser General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This library 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 Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public License
+## along with this library. If not, see <http://www.gnu.org/licenses/>.
+##
+
+LIBNAME = libopencm3_efm32lg
+FAMILY = EFM32LG
+
+PREFIX ?= arm-none-eabi
+#PREFIX ?= arm-elf
+CC = $(PREFIX)-gcc
+AR = $(PREFIX)-ar
+CFLAGS = -Os -g -Wall -Wextra -I../../../include -fno-common \
+ -mcpu=cortex-m3 -mthumb -Wstrict-prototypes \
+ -ffunction-sections -fdata-sections -MD -D$(FAMILY)
+# ARFLAGS = rcsv
+ARFLAGS = rcs
+OBJS =
+
+VPATH += ../:../../cm3
+
+include ../../Makefile.include
+
diff --git a/lib/efm32/efm32lg/libopencm3_efm32lg.ld b/lib/efm32/efm32lg/libopencm3_efm32lg.ld
new file mode 100644
index 0000000..8ef5e42
--- /dev/null
+++ b/lib/efm32/efm32lg/libopencm3_efm32lg.ld
@@ -0,0 +1,79 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>,
+ * Copyright (C) 2012 chrysn <chrysn@fsfe.org>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Generic linker script for EFM32 targets using libopencm3. */
+
+/* Memory regions must be defined in the ld script which includes this one. */
+
+/* Enforce emmition of the vector table. */
+EXTERN (vector_table)
+
+/* Define the entry point of the output file. */
+ENTRY(reset_handler)
+
+/* Define sections. */
+SECTIONS
+{
+ . = ORIGIN(rom);
+
+ .text : {
+ *(.vectors) /* Vector table */
+ *(.text*) /* Program code */
+ . = ALIGN(4);
+ *(.rodata*) /* Read-only data */
+ . = ALIGN(4);
+ _etext = .;
+ } >rom
+
+ . = ORIGIN(ram);
+
+ .data : AT(_etext) {
+ _data = .;
+ *(.data*) /* Read-write initialized data */
+ . = ALIGN(4);
+ _edata = .;
+ } >ram
+
+ .bss : {
+ *(.bss*) /* Read-write zero initialized data */
+ *(COMMON)
+ . = ALIGN(4);
+ _ebss = .;
+ } >ram AT >rom
+ _data_loadaddr = LOADADDR(.data);
+
+ /*
+ * The .eh_frame section appears to be used for C++ exception handling.
+ * You may need to fix this if you're using C++.
+ */
+ /DISCARD/ : { *(.eh_frame) }
+
+ /*
+ * Another section used by C++ stuff, appears when using newlib with
+ * 64bit (long long) printf support - discard it for now.
+ */
+ /DISCARD/ : { *(.ARM.exidx) }
+
+ . = ALIGN(4);
+ end = .;
+}
+
+PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram));
+
diff --git a/lib/efm32/efm32tg/Makefile b/lib/efm32/efm32tg/Makefile
new file mode 100644
index 0000000..605438a
--- /dev/null
+++ b/lib/efm32/efm32tg/Makefile
@@ -0,0 +1,38 @@
+##
+## This file is part of the libopencm3 project.
+##
+## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
+## Copyright (C) 2012 chrysn <chrysn@fsfe.org>
+##
+## This library is free software: you can redistribute it and/or modify
+## it under the terms of the GNU Lesser General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This library 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 Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public License
+## along with this library. If not, see <http://www.gnu.org/licenses/>.
+##
+
+LIBNAME = libopencm3_efm32tg
+FAMILY = EFM32TG
+
+PREFIX ?= arm-none-eabi
+#PREFIX ?= arm-elf
+CC = $(PREFIX)-gcc
+AR = $(PREFIX)-ar
+CFLAGS = -Os -g -Wall -Wextra -I../../../include -fno-common \
+ -mcpu=cortex-m3 -mthumb -Wstrict-prototypes \
+ -ffunction-sections -fdata-sections -MD -D$(FAMILY)
+# ARFLAGS = rcsv
+ARFLAGS = rcs
+OBJS =
+
+VPATH += ../:../../cm3
+
+include ../../Makefile.include
+
diff --git a/lib/efm32/efm32tg/libopencm3_efm32tg.ld b/lib/efm32/efm32tg/libopencm3_efm32tg.ld
new file mode 100644
index 0000000..8ef5e42
--- /dev/null
+++ b/lib/efm32/efm32tg/libopencm3_efm32tg.ld
@@ -0,0 +1,79 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>,
+ * Copyright (C) 2012 chrysn <chrysn@fsfe.org>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Generic linker script for EFM32 targets using libopencm3. */
+
+/* Memory regions must be defined in the ld script which includes this one. */
+
+/* Enforce emmition of the vector table. */
+EXTERN (vector_table)
+
+/* Define the entry point of the output file. */
+ENTRY(reset_handler)
+
+/* Define sections. */
+SECTIONS
+{
+ . = ORIGIN(rom);
+
+ .text : {
+ *(.vectors) /* Vector table */
+ *(.text*) /* Program code */
+ . = ALIGN(4);
+ *(.rodata*) /* Read-only data */
+ . = ALIGN(4);
+ _etext = .;
+ } >rom
+
+ . = ORIGIN(ram);
+
+ .data : AT(_etext) {
+ _data = .;
+ *(.data*) /* Read-write initialized data */
+ . = ALIGN(4);
+ _edata = .;
+ } >ram
+
+ .bss : {
+ *(.bss*) /* Read-write zero initialized data */
+ *(COMMON)
+ . = ALIGN(4);
+ _ebss = .;
+ } >ram AT >rom
+ _data_loadaddr = LOADADDR(.data);
+
+ /*
+ * The .eh_frame section appears to be used for C++ exception handling.
+ * You may need to fix this if you're using C++.
+ */
+ /DISCARD/ : { *(.eh_frame) }
+
+ /*
+ * Another section used by C++ stuff, appears when using newlib with
+ * 64bit (long long) printf support - discard it for now.
+ */
+ /DISCARD/ : { *(.ARM.exidx) }
+
+ . = ALIGN(4);
+ end = .;
+}
+
+PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram));
+
diff --git a/lib/efm32/efm32tg/libopencm3_efm32tg840f32.ld b/lib/efm32/efm32tg/libopencm3_efm32tg840f32.ld
new file mode 100644
index 0000000..2cb8daf
--- /dev/null
+++ b/lib/efm32/efm32tg/libopencm3_efm32tg840f32.ld
@@ -0,0 +1,15 @@
+/* lengths from d011_efm32tg840_datasheet.pdf table 1.1, offset from
+ * d0034_efm32tg_reference_manual.pdf figure 5.2.
+ *
+ * the origins and memory structure are constant over all tinygeckos, but the
+ * MEMORY section requires the use of constants, and has thus to be duplicated
+ * over the chip variants.
+ * */
+
+MEMORY
+{
+ rom (rx) : ORIGIN = 0, LENGTH = 32k
+ ram (rwx) : ORIGIN = 0x20000000, LENGTH = 4k
+}
+
+INCLUDE libopencm3_efm32tg.ld;
diff --git a/lib/lm3s/Makefile b/lib/lm3s/Makefile
index e471a00..6fc814d 100644
--- a/lib/lm3s/Makefile
+++ b/lib/lm3s/Makefile
@@ -25,7 +25,7 @@ CC = $(PREFIX)-gcc
AR = $(PREFIX)-ar
CFLAGS = -Os -g -Wall -Wextra -I../../include -fno-common \
-mcpu=cortex-m3 -mthumb -Wstrict-prototypes \
- -ffunction-sections -fdata-sections -MD
+ -ffunction-sections -fdata-sections -MD -DLM3S
# ARFLAGS = rcsv
ARFLAGS = rcs
OBJS = gpio.o vector.o assert.o
diff --git a/lib/lm3s/vector.c b/lib/lm3s/vector.c
deleted file mode 100644
index b7c92ae..0000000
--- a/lib/lm3s/vector.c
+++ /dev/null
@@ -1,454 +0,0 @@
-/*
- * This file is part of the libopencm3 project.
- *
- * Copyright (C) 2011 Gareth McMullin <gareth@blacksphere.co.nz>
- *
- * This library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define WEAK __attribute__ ((weak))
-
-/* Symbols exported by the linker script(s): */
-extern unsigned _data_loadaddr, _data, _edata, _ebss, _stack;
-
-void main(void);
-void reset_handler(void);
-void blocking_handler(void);
-void null_handler(void);
-
-void WEAK nmi_handler(void);
-void WEAK hard_fault_handler(void);
-void WEAK mem_manage_handler(void);
-void WEAK bus_fault_handler(void);
-void WEAK usage_fault_handler(void);
-void WEAK sv_call_handler(void);
-void WEAK debug_monitor_handler(void);
-void WEAK pend_sv_handler(void);
-void WEAK sys_tick_handler(void);
-
-void WEAK gpioa_handler(void);
-void WEAK gpiob_handler(void);
-void WEAK gpioc_handler(void);
-void WEAK gpiod_handler(void);
-void WEAK gpioe_handler(void);
-void WEAK uart0_handler(void);
-void WEAK uart1_handler(void);
-void WEAK ssi0_handler(void);
-void WEAK i2c0_handler(void);
-void WEAK pwm0_fault_handler(void);
-void WEAK pwm0_0_handler(void);
-void WEAK pwm0_1_handler(void);
-void WEAK pwm0_2_handler(void);
-void WEAK qei0_handler(void);
-void WEAK adc0ss0_handler(void);
-void WEAK adc0ss1_handler(void);
-void WEAK adc0ss2_handler(void);
-void WEAK adc0ss3_handler(void);
-void WEAK watchdog_handler(void);
-void WEAK timer0a_handler(void);
-void WEAK timer0b_handler(void);
-void WEAK timer1a_handler(void);
-void WEAK timer1b_handler(void);
-void WEAK timer2a_handler(void);
-void WEAK timer2b_handler(void);
-void WEAK comp0_handler(void);
-void WEAK comp1_handler(void);
-void WEAK comp2_handler(void);
-void WEAK sysctl_handler(void);
-void WEAK flash_handler(void);
-void WEAK gpiof_handler(void);
-void WEAK gpiog_handler(void);
-void WEAK gpioh_handler(void);
-void WEAK uart2_handler(void);
-void WEAK ssi1_handler(void);
-void WEAK timer3a_handler(void);
-void WEAK timer3b_handler(void);
-void WEAK i2c1_handler(void);
-void WEAK qei1_handler(void);
-void WEAK can0_handler(void);
-void WEAK can1_handler(void);
-void WEAK can2_handler(void);
-void WEAK eth_handler(void);
-void WEAK hibernate_handler(void);
-void WEAK usb0_handler(void);
-void WEAK pwm0_3_handler(void);
-void WEAK udma_handler(void);
-void WEAK udmaerr_handler(void);
-void WEAK adc1ss0_handler(void);
-void WEAK adc1ss1_handler(void);
-void WEAK adc1ss2_handler(void);
-void WEAK adc1ss3_handler(void);
-void WEAK i2s0_handler(void);
-void WEAK epi0_handler(void);
-void WEAK gpioj_handler(void);
-void WEAK gpiok_handler(void);
-void WEAK gpiol_handler(void);
-void WEAK ssi2_handler(void);
-void WEAK ssi3_handler(void);
-void WEAK uart3_handler(void);
-void WEAK uart4_handler(void);
-void WEAK uart5_handler(void);
-void WEAK uart6_handler(void);
-void WEAK uart7_handler(void);
-void WEAK i2c2_handler(void);
-void WEAK i2c3_handler(void);
-void WEAK timer4a_handler(void);
-void WEAK timer4b_handler(void);
-void WEAK timer5a_handler(void);
-void WEAK timer5b_handler(void);
-void WEAK wtimer0a_handler(void);
-void WEAK wtimer0b_handler(void);
-void WEAK wtimer1a_handler(void);
-void WEAK wtimer1b_handler(void);
-void WEAK wtimer2a_handler(void);
-void WEAK wtimer2b_handler(void);
-void WEAK wtimer3a_handler(void);
-void WEAK wtimer3b_handler(void);
-void WEAK wtimer4a_handler(void);
-void WEAK wtimer4b_handler(void);
-void WEAK wtimer5a_handler(void);
-void WEAK wtimer5b_handler(void);
-void WEAK sysexc_handler(void);
-void WEAK peci0_handler(void);
-void WEAK lpc0_handler(void);
-void WEAK i2c4_handler(void);
-void WEAK i2c5_handler(void);
-void WEAK gpiom_handler(void);
-void WEAK gpion_handler(void);
-void WEAK fan0_handler(void);
-void WEAK gpiop0_handler(void);
-void WEAK gpiop1_handler(void);
-void WEAK gpiop2_handler(void);
-void WEAK gpiop3_handler(void);
-void WEAK gpiop4_handler(void);
-void WEAK gpiop5_handler(void);
-void WEAK gpiop6_handler(void);
-void WEAK gpiop7_handler(void);
-void WEAK gpioq0_handler(void);
-void WEAK gpioq1_handler(void);
-void WEAK gpioq2_handler(void);
-void WEAK gpioq3_handler(void);
-void WEAK gpioq4_handler(void);
-void WEAK gpioq5_handler(void);
-void WEAK gpioq6_handler(void);
-void WEAK gpioq7_handler(void);
-void WEAK pwm1_0_handler(void);
-void WEAK pwm1_1_handler(void);
-void WEAK pwm1_2_handler(void);
-void WEAK pwm1_3_handler(void);
-void WEAK pwm1_fault_handler(void);
-
-__attribute__ ((section(".vectors")))
-void (*const vector_table[]) (void) = {
- (void *)&_stack,
- reset_handler,
- nmi_handler,
- hard_fault_handler,
- mem_manage_handler,
- bus_fault_handler,
- usage_fault_handler,
- 0, 0, 0, 0, /* Reserved */
- sv_call_handler,
- debug_monitor_handler,
- 0, /* Reserved */
- pend_sv_handler,
- sys_tick_handler,
-
- gpioa_handler, /* 16 */
- gpiob_handler, /* 17 */
- gpioc_handler, /* 18 */
- gpiod_handler, /* 19 */
- gpioe_handler, /* 20 */
- uart0_handler, /* 21 */
- uart1_handler, /* 22 */
- ssi0_handler, /* 23 */
- i2c0_handler, /* 24 */
- pwm0_fault_handler, /* 25 */
- pwm0_0_handler, /* 26 */
- pwm0_1_handler, /* 27 */
- pwm0_2_handler, /* 28 */
- qei0_handler, /* 29 */
- adc0ss0_handler, /* 30 */
- adc0ss1_handler, /* 31 */
- adc0ss2_handler, /* 32 */
- adc0ss3_handler, /* 33 */
- watchdog_handler, /* 34 */
- timer0a_handler, /* 35 */
- timer0b_handler, /* 36 */
- timer1a_handler, /* 37 */
- timer1b_handler, /* 38 */
- timer2a_handler, /* 39 */
- timer2b_handler, /* 40 */
- comp0_handler, /* 41 */
- comp1_handler, /* 42 */
- comp2_handler, /* 43 */
- sysctl_handler, /* 44 */
- flash_handler, /* 45 */
- gpiof_handler, /* 46 */
- gpiog_handler, /* 47 */
- gpioh_handler, /* 48 */
- uart2_handler, /* 49 */
- ssi1_handler, /* 50 */
- timer3a_handler, /* 51 */
- timer3b_handler, /* 52 */
- i2c1_handler, /* 53 */
- qei1_handler, /* 54 */
- can0_handler, /* 55 */
- can1_handler, /* 56 */
- can2_handler, /* 57 */
- eth_handler, /* 58 */
- hibernate_handler, /* 59 */
- usb0_handler, /* 60 */
- pwm0_3_handler, /* 61 */
- udma_handler, /* 62 */
- udmaerr_handler, /* 63 */
- adc1ss0_handler, /* 64 */
- adc1ss1_handler, /* 65 */
- adc1ss2_handler, /* 66 */
- adc1ss3_handler, /* 67 */
- i2s0_handler, /* 68 */
- epi0_handler, /* 69 */
- gpioj_handler, /* 70 */
- gpiok_handler, /* 71 */
- gpiol_handler, /* 72 */
- ssi2_handler, /* 73 */
- ssi3_handler, /* 74 */
- uart3_handler, /* 75 */
- uart4_handler, /* 76 */
- uart5_handler, /* 77 */
- uart6_handler, /* 78 */
- uart7_handler, /* 79 */
- 0, /* 80 */
- 0, /* 81 */
- 0, /* 82 */
- 0, /* 83 */
- i2c2_handler, /* 84 */
- i2c3_handler, /* 85 */
- timer4a_handler, /* 86 */
- timer4b_handler, /* 87 */
- 0, /* 88 */
- 0, /* 89 */
- 0, /* 90 */
- 0, /* 91 */
- 0, /* 92 */
- 0, /* 93 */
- 0, /* 94 */
- 0, /* 95 */
- 0, /* 96 */
- 0, /* 97 */
- 0, /* 98 */
- 0, /* 99 */
- 0, /* 100 */
- 0, /* 101 */
- 0, /* 102 */
- 0, /* 103 */
- 0, /* 104 */
- 0, /* 105 */
- 0, /* 106 */
- 0, /* 107 */
- timer5a_handler, /* 108 */
- timer5b_handler, /* 109 */
- wtimer0a_handler, /* 110 */
- wtimer0b_handler, /* 111 */
- wtimer1a_handler, /* 112 */
- wtimer1b_handler, /* 113 */
- wtimer2a_handler, /* 114 */
- wtimer2b_handler, /* 115 */
- wtimer3a_handler, /* 116 */
- wtimer3b_handler, /* 117 */
- wtimer4a_handler, /* 118 */
- wtimer4b_handler, /* 119 */
- wtimer5a_handler, /* 120 */
- wtimer5b_handler, /* 121 */
- sysexc_handler, /* 122 */
- peci0_handler, /* 123 */
- lpc0_handler, /* 124 */
- i2c4_handler, /* 125 */
- i2c5_handler, /* 126 */
- gpiom_handler, /* 127 */
- gpion_handler, /* 128 */
- 0, /* 129 */
- fan0_handler, /* 130 */
- 0, /* 131 */
- gpiop0_handler, /* 132 */
- gpiop1_handler, /* 133 */
- gpiop2_handler, /* 134 */
- gpiop3_handler, /* 135 */
- gpiop4_handler, /* 136 */
- gpiop5_handler, /* 137 */
- gpiop6_handler, /* 138 */
- gpiop7_handler, /* 139 */
- gpioq0_handler, /* 140 */
- gpioq1_handler, /* 141 */
- gpioq2_handler, /* 142 */
- gpioq3_handler, /* 143 */
- gpioq4_handler, /* 144 */
- gpioq5_handler, /* 145 */
- gpioq6_handler, /* 146 */
- gpioq7_handler, /* 147 */
- 0, /* 148 */
- 0, /* 149 */
- pwm1_0_handler, /* 150 */
- pwm1_1_handler, /* 151 */
- pwm1_2_handler, /* 152 */
- pwm1_3_handler, /* 153 */
- pwm1_fault_handler, /* 154 */
-};
-
-void reset_handler(void)
-{
- volatile unsigned *src, *dest;
-
- __asm__("MSR msp, %0" : : "r"(&_stack));
-
- for (src = &_data_loadaddr, dest = &_data; dest < &_edata; src++, dest++)
- *dest = *src;
-
- while (dest < &_ebss)
- *dest++ = 0;
-
- /* Call the application's entry point. */
- main();
-}
-
-void blocking_handler(void)
-{
- while (1) ;
-}
-
-void null_handler(void)
-{
- /* Do nothing. */
-}
-
-#pragma weak nmi_handler = null_handler
-#pragma weak hard_fault_handler = blocking_handler
-#pragma weak mem_manage_handler = blocking_handler
-#pragma weak bus_fault_handler = blocking_handler
-#pragma weak usage_fault_handler = blocking_handler
-#pragma weak sv_call_handler = null_handler
-#pragma weak debug_monitor_handler = null_handler
-#pragma weak pend_sv_handler = null_handler
-#pragma weak sys_tick_handler = null_handler
-#pragma weak gpioa_handler = null_handler
-#pragma weak gpiob_handler = null_handler
-#pragma weak gpioc_handler = null_handler
-#pragma weak gpiod_handler = null_handler
-#pragma weak gpioe_handler = null_handler
-#pragma weak uart0_handler = null_handler
-#pragma weak uart1_handler = null_handler
-#pragma weak ssi0_handler = null_handler
-#pragma weak i2c0_handler = null_handler
-#pragma weak pwm0_fault_handler = null_handler
-#pragma weak pwm0_0_handler = null_handler
-#pragma weak pwm0_1_handler = null_handler
-#pragma weak pwm0_2_handler = null_handler
-#pragma weak qei0_handler = null_handler
-#pragma weak adc0ss0_handler = null_handler
-#pragma weak adc0ss1_handler = null_handler
-#pragma weak adc0ss2_handler = null_handler
-#pragma weak adc0ss3_handler = null_handler
-#pragma weak watchdog_handler = null_handler
-#pragma weak timer0a_handler = null_handler
-#pragma weak timer0b_handler = null_handler
-#pragma weak timer1a_handler = null_handler
-#pragma weak timer1b_handler = null_handler
-#pragma weak timer2a_handler = null_handler
-#pragma weak timer2b_handler = null_handler
-#pragma weak comp0_handler = null_handler
-#pragma weak comp1_handler = null_handler
-#pragma weak comp2_handler = null_handler
-#pragma weak sysctl_handler = null_handler
-#pragma weak flash_handler = null_handler
-#pragma weak gpiof_handler = null_handler
-#pragma weak gpiog_handler = null_handler
-#pragma weak gpioh_handler = null_handler
-#pragma weak uart2_handler = null_handler
-#pragma weak ssi1_handler = null_handler
-#pragma weak timer3a_handler = null_handler
-#pragma weak timer3b_handler = null_handler
-#pragma weak i2c1_handler = null_handler
-#pragma weak qei1_handler = null_handler
-#pragma weak can0_handler = null_handler
-#pragma weak can1_handler = null_handler
-#pragma weak can2_handler = null_handler
-#pragma weak eth_handler = null_handler
-#pragma weak hibernate_handler = null_handler
-#pragma weak usb0_handler = null_handler
-#pragma weak pwm0_3_handler = null_handler
-#pragma weak udma_handler = null_handler
-#pragma weak udmaerr_handler = null_handler
-#pragma weak adc1ss0_handler = null_handler
-#pragma weak adc1ss1_handler = null_handler
-#pragma weak adc1ss2_handler = null_handler
-#pragma weak adc1ss3_handler = null_handler
-#pragma weak i2s0_handler = null_handler
-#pragma weak epi0_handler = null_handler
-#pragma weak gpioj_handler = null_handler
-#pragma weak gpiok_handler = null_handler
-#pragma weak gpiol_handler = null_handler
-#pragma weak ssi2_handler = null_handler
-#pragma weak ssi3_handler = null_handler
-#pragma weak uart3_handler = null_handler
-#pragma weak uart4_handler = null_handler
-#pragma weak uart5_handler = null_handler
-#pragma weak uart6_handler = null_handler
-#pragma weak uart7_handler = null_handler
-#pragma weak i2c2_handler = null_handler
-#pragma weak i2c3_handler = null_handler
-#pragma weak timer4a_handler = null_handler
-#pragma weak timer4b_handler = null_handler
-#pragma weak timer5a_handler = null_handler
-#pragma weak timer5b_handler = null_handler
-#pragma weak wtimer0a_handler = null_handler
-#pragma weak wtimer0b_handler = null_handler
-#pragma weak wtimer1a_handler = null_handler
-#pragma weak wtimer1b_handler = null_handler
-#pragma weak wtimer2a_handler = null_handler
-#pragma weak wtimer2b_handler = null_handler
-#pragma weak wtimer3a_handler = null_handler
-#pragma weak wtimer3b_handler = null_handler
-#pragma weak wtimer4a_handler = null_handler
-#pragma weak wtimer4b_handler = null_handler
-#pragma weak wtimer5a_handler = null_handler
-#pragma weak wtimer5b_handler = null_handler
-#pragma weak sysexc_handler = null_handler
-#pragma weak peci0_handler = null_handler
-#pragma weak lpc0_handler = null_handler
-#pragma weak i2c4_handler = null_handler
-#pragma weak i2c5_handler = null_handler
-#pragma weak gpiom_handler = null_handler
-#pragma weak gpion_handler = null_handler
-#pragma weak fan0_handler = null_handler
-#pragma weak gpiop0_handler = null_handler
-#pragma weak gpiop1_handler = null_handler
-#pragma weak gpiop2_handler = null_handler
-#pragma weak gpiop3_handler = null_handler
-#pragma weak gpiop4_handler = null_handler
-#pragma weak gpiop5_handler = null_handler
-#pragma weak gpiop6_handler = null_handler
-#pragma weak gpiop7_handler = null_handler
-#pragma weak gpioq0_handler = null_handler
-#pragma weak gpioq1_handler = null_handler
-#pragma weak gpioq2_handler = null_handler
-#pragma weak gpioq3_handler = null_handler
-#pragma weak gpioq4_handler = null_handler
-#pragma weak gpioq5_handler = null_handler
-#pragma weak gpioq6_handler = null_handler
-#pragma weak gpioq7_handler = null_handler
-#pragma weak pwm1_0_handler = null_handler
-#pragma weak pwm1_1_handler = null_handler
-#pragma weak pwm1_2_handler = null_handler
-#pragma weak pwm1_3_handler = null_handler
-#pragma weak pwm1_fault_handler = null_handler
diff --git a/lib/lm4f/Makefile b/lib/lm4f/Makefile
new file mode 100644
index 0000000..a3b7dce
--- /dev/null
+++ b/lib/lm4f/Makefile
@@ -0,0 +1,35 @@
+##
+## This file is part of the libopencm3 project.
+##
+## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
+##
+## This library is free software: you can redistribute it and/or modify
+## it under the terms of the GNU Lesser General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This library 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 Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public License
+## along with this library. If not, see <http://www.gnu.org/licenses/>.
+##
+
+LIBNAME = libopencm3_lm4f
+
+PREFIX ?= arm-none-eabi
+#PREFIX ?= arm-elf
+CC = $(PREFIX)-gcc
+AR = $(PREFIX)-ar
+CFLAGS = -Os -g -Wall -Wextra -I../../include -fno-common \
+ -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -Wstrict-prototypes \
+ -ffunction-sections -fdata-sections -MD -DLM4F
+# ARFLAGS = rcsv
+ARFLAGS = rcs
+OBJS = gpio.o vector.o assert.o systemcontrol.o rcc.o
+
+VPATH += ../cm3
+
+include ../Makefile.include
diff --git a/lib/stm32/f2/scb.c b/lib/lm4f/gpio.c
index abb7b44..2d50116 100644
--- a/lib/stm32/f2/scb.c
+++ b/lib/lm4f/gpio.c
@@ -1,7 +1,7 @@
/*
* This file is part of the libopencm3 project.
*
- * Copyright (C) 2010 Gareth McMullin <gareth@blacksphere.co.nz>
+ * Copyright (C) 2011 Gareth McMullin <gareth@blacksphere.co.nz>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -17,19 +17,15 @@
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <libopencm3/stm32/f2/scb.h>
+#include <libopencm3/lm4f/gpio.h>
-void scb_reset_core(void)
+void gpio_set(u32 gpioport, u8 gpios)
{
- SCB_AIRCR = SCB_AIRCR_VECTKEY | SCB_AIRCR_VECTRESET;
+ /* ipaddr[9:2] mask the bits to be set, hence the array index */
+ GPIO_DATA(gpioport)[gpios] = 0xff;
}
-void scb_reset_system(void)
+void gpio_clear(u32 gpioport, u8 gpios)
{
- SCB_AIRCR = SCB_AIRCR_VECTKEY | SCB_AIRCR_SYSRESETREQ;
-}
-
-void scb_set_priority_grouping(u32 prigroup)
-{
- SCB_AIRCR = SCB_AIRCR_VECTKEY | prigroup;
+ GPIO_DATA(gpioport)[gpios] = 0;
}
diff --git a/lib/lm4f/libopencm3_lm4f.ld b/lib/lm4f/libopencm3_lm4f.ld
new file mode 100644
index 0000000..12d939e
--- /dev/null
+++ b/lib/lm4f/libopencm3_lm4f.ld
@@ -0,0 +1,2 @@
+/* Yes, we can simply use the lm3s linker script */
+INCLUDE "libopencm3_lm3s.ld"
diff --git a/lib/lm4f/rcc.c b/lib/lm4f/rcc.c
new file mode 100644
index 0000000..48eb2a2
--- /dev/null
+++ b/lib/lm4f/rcc.c
@@ -0,0 +1,493 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * @defgroup rcc_file RCC
+ *
+ * @ingroup LM4F
+ *
+ * \brief <b>libopencm3 LM4F Clock control API</b>
+ *
+ * The LM$F clock API provides functionaliity for manipulating the system clock,
+ * oscillator, and PLL. Functions are provided for fine-grained control of clock
+ * control registers, while also providing higher level functionality to easily
+ * configure the main system clock source.
+ *
+ * The following code snippet uses fine-grained mechanisms to configures the
+ * chip to run off an external 16MHz crystal, and use the PLL to derive a clock
+ * frequency of 80MHz.
+ * @code{.c}
+ * // A divisor of 5 gives us a clock of 400/5 = 80MHz
+ * #define PLLDIV_80MHZ 5
+ *
+ * // Enable the main oscillator
+ * rcc_enable_main_osc();
+ *
+ * // Make RCC2 override RCC
+ * rcc_enable_rcc2();
+ *
+ * // Set XTAL value to 16MHz
+ * rcc_configure_xtal(XTAL_16M);
+ * // Set the oscillator source as the main oscillator
+ * rcc_set_osc_source(OSCSRC_MOSC);
+ * // Enable the PLL
+ * rcc_pll_on();
+ *
+ * // Change the clock divisor
+ * rcc_set_pll_divisor(PLLDIV_80MHZ);
+ *
+ * // We cannot use the PLL as a clock source until it locks
+ * rcc_wait_for_pll_ready();
+ * // Disable PLL bypass to derive the system clock from the PLL clock
+ * rcc_pll_bypass_disable();
+ *
+ * // Keep track of frequency
+ * lm4f_rcc_sysclk_freq = 80E6;
+ * @endcode
+ *
+ * The same can be achieved by a simple call to high-level routines:
+ * @code
+ * // A divisor of 5 gives us a clock of 400/5 = 80MHz
+ * #define PLLDIV_80MHZ 5
+ *
+ * rcc_sysclk_config(OSCSRC_MOSC, XTAL_16M, PLLDIV_80MHZ);
+ * @endcode
+ *
+ * @{
+ */
+
+#include <libopencm3/lm4f/rcc.h>
+
+/**
+ * @defgroup rcc_low_level Low-level clock control API
+ * @{
+ */
+/**
+ * \brief System clock frequency
+ *
+ * This variable is provided to keep track of the system clock frequency. It
+ * should be updated every time the system clock is changed via the fine-grained
+ * mechanisms. The initial value is 16MHz, which corresponds to the clock of the
+ * internal 16MHz oscillator.
+ *
+ * High-level routines update the system clock automatically.
+ * For read access, it is recommended to acces this variable via
+ * @code
+ * rcc_get_system_clock_frequency();
+ * @endcode
+ *
+ * If write access is desired (i.e. when changing the system clock via the
+ * fine-grained mechanisms), then include the following line in your code:
+ * @code
+ * extern u32 lm4f_rcc_sysclk_freq;
+ * @endcode
+ */
+u32 lm4f_rcc_sysclk_freq = 16000000;
+
+
+/**
+ * \brief Configure the crystal type connected to the device.
+ *
+ * Configure the crystal type connected between the OSCO and OSCI pins by
+ * writing the appropriate value to the XTAL field in SYSCTL_RCC. The PLL
+ * parameters are automatically adjusted in hardware to provide a PLL clock of
+ * 400MHz.
+ *
+ * @param[in] xtal predefined crystal type @see xtal_t
+ */
+void rcc_configure_xtal(xtal_t xtal)
+{
+ u32 reg32;
+
+ reg32 = SYSCTL_RCC;
+ reg32 &= ~SYSCTL_RCC_XTAL_MASK;
+ reg32 |= (xtal & SYSCTL_RCC_XTAL_MASK);
+ SYSCTL_RCC = reg32;
+}
+
+/**
+ * \brief Disable the main oscillator
+ *
+ * Sets the IOSCDIS bit in SYSCTL_RCC, disabling the main oscillator.
+ */
+void rcc_disable_main_osc(void)
+{
+ SYSCTL_RCC |= SYSCTL_RCC_MOSCDIS;
+}
+
+/**
+ * \brief Disable the internal oscillator
+ *
+ * Sets the IOSCDIS bit in SYSCTL_RCC, disabling the internal oscillator.
+ */
+void rcc_disable_interal_osc(void)
+{
+ SYSCTL_RCC |= SYSCTL_RCC_IOSCDIS;
+}
+
+/**
+ * \brief Enable the main oscillator
+ *
+ * Clears the MOSCDIS bit in SYSCTL_RCC, enabling the main oscillator.
+ */
+void rcc_enable_main_osc(void)
+{
+ SYSCTL_RCC &= ~SYSCTL_RCC_MOSCDIS;
+}
+
+/**
+ * \brief Enable the internal oscillator
+ *
+ * Clears the IOSCDIS bit in SYSCTL_RCC, enabling the internal oscillator.
+ */
+void rcc_enable_interal_osc(void)
+{
+ SYSCTL_RCC &= ~SYSCTL_RCC_IOSCDIS;
+}
+
+/**
+ * \brief Enable the use of SYSCTL_RCC2 register for clock control
+ *
+ * Enables the USERCC2 bit in SYSCTTL_RCC2. Settings in SYSCTL_RCC2 will
+ * override settings in SYSCTL_RCC.
+ * This function must be called before other calls to manipulate the clock, as
+ * libopencm3 uses the SYSCTL_RCC2 register.
+ */
+void rcc_enable_rcc2(void)
+{
+ SYSCTL_RCC2 |= SYSCTL_RCC2_USERCC2;
+}
+
+/**
+ * \brief Power down the main PLL
+ *
+ * Sets the SYSCTL_RCC2_PWRDN2 in SYSCTL_RCC2 to power down the PLL.
+ *
+ * USERCC2 must have been set by a call to rcc_enable_rcc2() before calling this
+ * function.
+ */
+void rcc_pll_off(void)
+{
+ SYSCTL_RCC2 |= SYSCTL_RCC2_PWRDN2;
+}
+
+/**
+ * \brief Power up the main PLL
+ *
+ * Clears the PWRDN2 in SYSCTL_RCC2 to power on the PLL.
+ *
+ * USERCC2 must have been set by a call to rcc_enable_rcc2() before calling this
+ * function.
+ */
+void rcc_pll_on(void)
+{
+ SYSCTL_RCC2 &= ~SYSCTL_RCC2_PWRDN2;
+}
+
+/**
+ * \brief Set the oscillator source to be used by the system clock
+ *
+ * Set the clock source for the system clock.
+ *
+ * USERCC2 must have been set by a call to rcc_enable_rcc2() before calling this
+ * function.
+ */
+void rcc_set_osc_source(osc_src_t src)
+{
+ u32 reg32;
+
+ reg32 = SYSCTL_RCC2;
+ reg32 &= ~SYSCTL_RCC2_OSCSRC2_MASK;
+ reg32 |= (src & SYSCTL_RCC2_OSCSRC2_MASK);
+ SYSCTL_RCC2 = reg32;
+}
+
+/**
+ * \brief Disable the PLL bypass and use the PLL clock
+ *
+ * Clear BYPASS2 in SYSCTL_RCC2. The system clock is derived from the PLL
+ * clock divided by the divisor specified in SYSDIV2.
+ *
+ * USERCC2 must have been set by a call to rcc_enable_rcc2() before calling this
+ * function.
+ */
+void rcc_pll_bypass_disable(void)
+{
+ SYSCTL_RCC2 &= ~SYSCTL_RCC2_BYPASS2;
+}
+
+/**
+ * \brief Enable the PLL bypass and use the oscillator clock
+ *
+ * Set BYPASS2 in SYSCTL_RCC2. The system clock is derived from the oscillator
+ * clock divided by the divisor specified in SYSDIV2.
+ *
+ * USERCC2 must have been set by a call to rcc_enable_rcc2() before calling this
+ * function.
+ */
+void rcc_pll_bypass_enable(void)
+{
+ SYSCTL_RCC2 |= SYSCTL_RCC2_BYPASS2;
+}
+
+/**
+ * \brief Set the PLL clock divisor (from 400MHz)
+ *
+ * Set the binary divisor used to predivide the system clock down for use as the
+ * timing reference for the PWM module. The divisor is expected to be a divisor
+ * from 400MHz, not 200MHz. The DIV400 is also set.
+ *
+ * Specifies the divisor that used to generate the system clock from either the
+ * PLL output or the oscillator source (depending on the BYPASS2 bit in
+ * SYSCTL_RCC2). SYSDIV2 is used for the divisor when both the USESYSDIV bit in
+ * SYSCTL_RCC is set.
+ *
+ * USERCC2 must have been set by a call to rcc_enable_rcc2() before calling this
+ * function.
+ *
+ * @param[in] div clock divisor to apply to the 400MHz PLL clock. It is the
+ * caller's responsibility to ensure that the divisor will not create
+ * a system clock that is out of spec.
+ */
+void rcc_set_pll_divisor(u8 div400)
+{
+ u32 reg32;
+
+ SYSCTL_RCC |= SYSCTL_RCC_USESYSDIV;
+
+ reg32 = SYSCTL_RCC2;
+ reg32 &= ~SYSCTL_RCC2_SYSDIV400_MASK;
+ reg32 |= (div400 << 22) & SYSCTL_RCC2_SYSDIV400_MASK;
+ /* We are expecting a divider from 400MHz */
+ reg32 |= SYSCTL_RCC2_DIV400;
+ SYSCTL_RCC2 = reg32;
+}
+/**
+ * \brief Set the PWM unit clock divisor
+ *
+ * Set the binary divisor used to predivide the system clock down for use as the
+ * timing reference for the PWM module.
+ *
+ * @param[in] div clock divisor to use @see pwm_clkdiv_t
+ */
+void rcc_set_pwm_divisor(pwm_clkdiv_t div)
+{
+ u32 reg32;
+
+ reg32 = SYSCTL_RCC;
+ reg32 &= ~SYSCTL_RCC_PWMDIV_MASK;
+ reg32 |= (div & SYSCTL_RCC_PWMDIV_MASK);
+ SYSCTL_RCC = reg32;
+}
+
+/**
+ * \brief Power down the USB PLL
+ *
+ * Sets the USBPWRDN in SYSCTL_RCC2 to power down the USB PLL.
+ *
+ * USERCC2 must have been set by a call to rcc_enable_rcc2() before calling this
+ * function.
+ */
+void rcc_usb_pll_off(void)
+{
+ SYSCTL_RCC2 |= SYSCTL_RCC2_USBPWRDN;
+}
+
+/**
+ * \brief Power up the USB PLL
+ *
+ * Clears the USBPWRDN in SYSCTL_RCC2 to power on the USB PLL.
+ *
+ * USERCC2 must have been set by a call to rcc_enable_rcc2() before calling this
+ * function.
+ */
+void rcc_usb_pll_on(void)
+{
+ SYSCTL_RCC2 &= ~SYSCTL_RCC2_USBPWRDN;
+}
+
+/**
+ * \brief Wait for main PLL to lock
+ *
+ * Waits until the LOCK bit in SYSCTL_PLLSTAT is set. This guarantees that the
+ * PLL is locked, and ready to use.
+ */
+void rcc_wait_for_pll_ready(void)
+{
+ while(!(SYSCTL_PLLSTAT & SYSCTL_PLLSTAT_LOCK));
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @defgroup rcc_high_level High-level clock control API
+ * @{
+ */
+
+/**
+ * \brief Change the PLL divisor
+ *
+ * Changes the divisor applied to the 400MHz PLL clock. The PLL must have
+ * previously been configured by selecting an appropriate XTAL value, and
+ * turning on the PLL. This function does not reconfigure the XTAL value or
+ * oscillator source. It only changes the PLL divisor.
+ *
+ * The PLL is bypassed before modifying the divisor, and the function blocks
+ * until the PLL is locked, then the bypass is disabled, before returning.
+ *
+ * @param [in] pll_div400 The clock divisor to apply to the 400MHz PLL clock.
+ */
+void rcc_change_pll_divisor(u8 pll_div400)
+{
+ /* Bypass the PLL while its settings are modified */
+ rcc_pll_bypass_enable();
+ /* Change the clock divisor */
+ rcc_set_pll_divisor(pll_div400);
+ /* We cannot use the PLL as a clock source until it locks */
+ rcc_wait_for_pll_ready();
+ /* Disable PLL bypass to derive the system clock from the PLL clock */
+ rcc_pll_bypass_disable();
+ /* Update the system clock frequency for housekeeping */
+ lm4f_rcc_sysclk_freq = (u32)400E6 / pll_div400;
+}
+
+/**
+ * \brief Get the system clock frequency
+ *
+ * @return System clock frequency in Hz
+ */
+u32 rcc_get_system_clock_frequency(void)
+{
+ return lm4f_rcc_sysclk_freq;
+}
+
+/* Get the clock frequency corresponging to a given XTAL value */
+static u32 xtal_to_freq(xtal_t xtal)
+{
+ const u32 freqs[] = {
+ 4000000, /* XTAL_4M */
+ 4096000, /* XTAL_4M_096 */
+ 4915200, /* XTAL_4M_9152 */
+ 5000000, /* ,XTAL_5M */
+ 5120000, /* XTAL_5M_12 */
+ 6000000, /* XTAL_6M */
+ 6144000, /* XTAL_6M_144 */
+ 7372800, /* XTAL_7M_3728 */
+ 8000000, /* XTAL_8M */
+ 8192000, /* XTAL_8M_192 */
+ 10000000, /* XTAL_10M */
+ 12000000, /* XTAL_12M */
+ 12288000, /* XTAL_12M_288 */
+ 13560000, /* XTAL_13M_56 */
+ 14318180, /* XTAL_14M_31818 */
+ 16000000, /* XTAL_16M */
+ 16384000, /* XTAL_16M_384 */
+ 18000000, /* XTAL_18M */
+ 20000000, /* XTAL_20M */
+ 24000000, /* XTAL_24M */
+ 25000000, /* XTAL_25M */
+ };
+
+ return freqs[xtal - XTAL_4M];
+}
+
+/**
+ * \brief Configure the system clock source
+ *
+ * Sets up the system clock, including configuring the oscillator source, and
+ * PLL to acheve the desired system clock frequency. Where applicable, The LM4F
+ * clock API uses the new RCC2 register to configure clock parameters.
+ *
+ * Enables the main oscillator if the clock source is OSCSRC_MOSC. If the main
+ * oscillator was previously enabled, it will not be disabled. If desired, it
+ * can be separately disabled by a call to rcc_disable_main_osc().
+ *
+ * Configures the system clock to run from the 400MHz PLL with a divisor of
+ * pll_div400 applied. If pll_div400 is 0, then the PLL is disabled, and the
+ * system clock is configured to run off a "raw" clock. If the PLL was
+ * previously powered on, it will not be disabled. If desired, it can de powered
+ * off by a call to rcc_pll_off().
+ *
+ * @param [in] osc_src Oscillator from where to derive the system clock.
+ * @param [in] xtal Type of crystal connected to the OSCO/OSCI pins
+ * @param [in] pll_div400 The clock divisor to apply to the 400MHz PLL clock.
+ * If 0, then the PLL is disabled, and the system runs
+ * off a "raw" clock.
+ *
+ * @return System clock frequency in Hz
+ */
+void rcc_sysclk_config(osc_src_t osc_src, xtal_t xtal, u8 pll_div400)
+{
+ /*
+ * We could be using the PLL at this point, or we could be running of a
+ * raw clock. Either way, it is safer to bypass the PLL now.
+ */
+ rcc_pll_bypass_enable();
+
+ /* Enable the main oscillator, if needed */
+ if (osc_src == OSCSRC_MOSC)
+ rcc_enable_main_osc();
+
+ /* Make RCC2 override RCC */
+ rcc_enable_rcc2();
+
+ /* Set XTAL value to 16MHz */
+ rcc_configure_xtal(xtal);
+ /* Set the oscillator source */
+ rcc_set_osc_source(osc_src);
+ if (pll_div400) {
+ /* Enable the PLL */
+ rcc_pll_on();
+ /* Configure the PLL to the divisor we want */
+ rcc_change_pll_divisor(pll_div400);
+ } else {
+ /* We are running off a raw clock */
+ switch (osc_src) {
+ case OSCSRC_PIOSC:
+ lm4f_rcc_sysclk_freq = 16000000;
+ break;
+ case OSCSRC_PIOSC_D4:
+ lm4f_rcc_sysclk_freq = 4000000;
+ break;
+ case OSCSRC_MOSC:
+ lm4f_rcc_sysclk_freq = xtal_to_freq(xtal);
+ break;
+ case OSCSRC_32K_EXT:
+ lm4f_rcc_sysclk_freq = 32768;
+ break;
+ case OSCSRC_30K_INT: /* Fall through. */
+ default:
+ /*
+ * We either are running off the internal 30KHz
+ * oscillator, which is +- 50% imprecise, or we got a
+ * bad osc_src parameter.
+ */
+ lm4f_rcc_sysclk_freq = 0;
+ }
+ }
+
+}
+
+/**
+ * @}
+ * @}
+ */
diff --git a/lib/lm4f/systemcontrol.c b/lib/lm4f/systemcontrol.c
new file mode 100644
index 0000000..691b661
--- /dev/null
+++ b/lib/lm4f/systemcontrol.c
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/lm4f/systemcontrol.h>
+
+/**
+ * \brief Enable the clock source for the peripheral
+ *
+ * @param[in] periph peripheral and clock type to enable @see clken_t
+ */
+void periph_clock_enable(clken_t periph)
+{
+ MMIO32(SYSCTL_BASE + (periph >> 5)) |= 1 << (periph & 0x1f);
+}
+
+/**
+ * \brief Disable the clock source for the peripheral
+ *
+ * @param[in] periph peripheral and clock type to enable @see clken_t
+ */
+void periph_clock_disable(clken_t periph)
+{
+ MMIO32(SYSCTL_BASE + (periph >> 5)) &= ~(1 << (periph & 0x1f));
+}
diff --git a/lib/lpc13xx/Makefile b/lib/lpc13xx/Makefile
index e1e69f7..15bc686 100644
--- a/lib/lpc13xx/Makefile
+++ b/lib/lpc13xx/Makefile
@@ -25,10 +25,10 @@ CC = $(PREFIX)-gcc
AR = $(PREFIX)-ar
CFLAGS = -Os -g -Wall -Wextra -I../../include -fno-common \
-mcpu=cortex-m3 -mthumb -Wstrict-prototypes \
- -ffunction-sections -fdata-sections -MD
+ -ffunction-sections -fdata-sections -MD -DLPC13XX
# ARFLAGS = rcsv
ARFLAGS = rcs
-OBJS = gpio.o assert.o
+OBJS = gpio.o
VPATH += ../cm3
diff --git a/lib/lpc17xx/Makefile b/lib/lpc17xx/Makefile
index d1da64a..19fc152 100644
--- a/lib/lpc17xx/Makefile
+++ b/lib/lpc17xx/Makefile
@@ -25,10 +25,10 @@ CC = $(PREFIX)-gcc
AR = $(PREFIX)-ar
CFLAGS = -O0 -g -Wall -Wextra -I../../include -fno-common \
-mcpu=cortex-m3 -mthumb -Wstrict-prototypes \
- -ffunction-sections -fdata-sections -MD
+ -ffunction-sections -fdata-sections -MD -DLPC17XX
# ARFLAGS = rcsv
ARFLAGS = rcs
-OBJS = gpio.o vector.o assert.o
+OBJS = gpio.o
VPATH += ../cm3
diff --git a/lib/lpc43xx/Makefile b/lib/lpc43xx/Makefile
index 6e08ea0..efbba0d 100644
--- a/lib/lpc43xx/Makefile
+++ b/lib/lpc43xx/Makefile
@@ -28,11 +28,10 @@ AR = $(PREFIX)-ar
CFLAGS = -O2 -g3 -Wall -Wextra -I../../include -fno-common \
-mcpu=cortex-m4 -mthumb -Wstrict-prototypes \
-ffunction-sections -fdata-sections -MD \
- -mfloat-abi=hard -mfpu=fpv4-sp-d16
+ -mfloat-abi=hard -mfpu=fpv4-sp-d16 -DLPC43XX
# ARFLAGS = rcsv
ARFLAGS = rcs
-OBJS = gpio.o vector.o scu.o i2c.o ssp.o nvic.o systick.o \
- assert.o
+OBJS = gpio.o scu.o i2c.o ssp.o
VPATH += ../cm3
diff --git a/lib/lpc43xx/nvic.c b/lib/lpc43xx/nvic.c
deleted file mode 100644
index 4793312..0000000
--- a/lib/lpc43xx/nvic.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * This file is part of the libopencm3 project.
- *
- * Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
- * Copyright (C) 2012 Fergus Noble <fergusnoble@gmail.com>
- * Copyright (C) 2012 Benjamin Vernoux <titanmkd@gmail.com>
- *
- * This library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-#include <libopencm3/cm3/scs.h>
-#include <libopencm3/lpc43xx/nvic.h>
-
-void nvic_enable_irq(u8 irqn)
-{
- NVIC_ISER(irqn / 32) = (1 << (irqn % 32));
-}
-
-void nvic_disable_irq(u8 irqn)
-{
- NVIC_ICER(irqn / 32) = (1 << (irqn % 32));
-}
-
-u8 nvic_get_pending_irq(u8 irqn)
-{
- return NVIC_ISPR(irqn / 32) & (1 << (irqn % 32)) ? 1 : 0;
-}
-
-void nvic_set_pending_irq(u8 irqn)
-{
- NVIC_ISPR(irqn / 32) = (1 << (irqn % 32));
-}
-
-void nvic_clear_pending_irq(u8 irqn)
-{
- NVIC_ICPR(irqn / 32) = (1 << (irqn % 32));
-}
-
-u8 nvic_get_active_irq(u8 irqn)
-{
- return NVIC_IABR(irqn / 32) & (1 << (irqn % 32)) ? 1 : 0;
-}
-
-u8 nvic_get_irq_enabled(u8 irqn)
-{
- return NVIC_ISER(irqn / 32) & (1 << (irqn % 32)) ? 1 : 0;
-}
-
-void nvic_set_priority(u8 irqn, u8 priority)
-{
- if(irqn>NVIC_M4_QEI_IRQ)
- {
- /* Cortex-M system interrupts */
- SCS_SHPR( (irqn&0xF)-4 ) = priority;
- }else
- {
- /* Device specific interrupts */
- NVIC_IPR(irqn) = priority;
- }
-}
-
-void nvic_generate_software_interrupt(u8 irqn)
-{
- if (irqn <= 239)
- NVIC_STIR |= irqn;
-}
diff --git a/lib/lpc43xx/systick.c b/lib/lpc43xx/systick.c
deleted file mode 100644
index 82345a9..0000000
--- a/lib/lpc43xx/systick.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * This file is part of the libopencm3 project.
- *
- * Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
- * Copyright (C) 2012 Benjamin Vernoux <titanmkd@gmail.com>
- *
- * This library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <libopencm3/lpc43xx/systick.h>
-
-void systick_set_reload(u32 value)
-{
- STK_LOAD = (value & 0x00FFFFFF);
-}
-
-u32 systick_get_value(void)
-{
- return STK_VAL;
-}
-
-void systick_set_clocksource(u8 clocksource)
-{
- STK_CTRL |= clocksource;
-}
-
-void systick_interrupt_enable(void)
-{
- STK_CTRL |= STK_CTRL_TICKINT;
-}
-
-void systick_interrupt_disable(void)
-{
- STK_CTRL &= ~STK_CTRL_TICKINT;
-}
-
-void systick_counter_enable(void)
-{
- STK_CTRL |= STK_CTRL_ENABLE;
-}
-
-void systick_counter_disable(void)
-{
- STK_CTRL &= ~STK_CTRL_ENABLE;
-}
-
-u8 systick_get_countflag(void)
-{
- if (STK_CTRL & STK_CTRL_COUNTFLAG)
- return 1;
- else
- return 0;
-}
-
-u32 systick_get_calib(void)
-{
- return (STK_CALIB&0x00FFFFFF);
-}
diff --git a/lib/lpc43xx/vector.c b/lib/lpc43xx/vector.c
deleted file mode 100644
index 23008bc..0000000
--- a/lib/lpc43xx/vector.c
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * This file is part of the libopencm3 project.
- *
- * Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
- * Copyright (C) 2012 Michael Ossmann <mike@ossmann.com>
- *
- * This library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define WEAK __attribute__ ((weak))
-
-/* Symbols exported by the linker script(s): */
-extern unsigned _data_loadaddr, _data, _edata, _ebss, _stack;
-extern unsigned _etext_ram, _text_ram, _etext_rom;
-
-void main(void);
-void reset_handler(void);
-void blocking_handler(void);
-void null_handler(void);
-
-void WEAK nmi_handler(void);
-void WEAK hard_fault_handler(void);
-void WEAK mem_manage_handler(void);
-void WEAK bus_fault_handler(void);
-void WEAK usage_fault_handler(void);
-void WEAK sv_call_handler(void);
-void WEAK debug_monitor_handler(void);
-void WEAK pend_sv_handler(void);
-void WEAK sys_tick_handler(void);
-void WEAK dac_irqhandler(void);
-void WEAK m0core_irqhandler(void);
-void WEAK dma_irqhandler(void);
-void WEAK ethernet_irqhandler(void);
-void WEAK sdio_irqhandler(void);
-void WEAK lcd_irqhandler(void);
-void WEAK usb0_irqhandler(void);
-void WEAK usb1_irqhandler(void);
-void WEAK sct_irqhandler(void);
-void WEAK ritimer_irqhandler(void);
-void WEAK timer0_irqhandler(void);
-void WEAK timer1_irqhandler(void);
-void WEAK timer2_irqhandler(void);
-void WEAK timer3_irqhandler(void);
-void WEAK mcpwm_irqhandler(void);
-void WEAK adc0_irqhandler(void);
-void WEAK i2c0_irqhandler(void);
-void WEAK i2c1_irqhandler(void);
-void WEAK spi_irqhandler(void);
-void WEAK adc1_irqhandler(void);
-void WEAK ssp0_irqhandler(void);
-void WEAK ssp1_irqhandler(void);
-void WEAK usart0_irqhandler(void);
-void WEAK uart1_irqhandler(void);
-void WEAK usart2_irqhandler(void);
-void WEAK usart3_irqhandler(void);
-void WEAK i2s0_irqhandler(void);
-void WEAK i2s1_irqhandler(void);
-void WEAK spifi_irqhandler(void);
-void WEAK sgpio_irqhandler(void);
-void WEAK pin_int0_irqhandler(void);
-void WEAK pin_int1_irqhandler(void);
-void WEAK pin_int2_irqhandler(void);
-void WEAK pin_int3_irqhandler(void);
-void WEAK pin_int4_irqhandler(void);
-void WEAK pin_int5_irqhandler(void);
-void WEAK pin_int6_irqhandler(void);
-void WEAK pin_int7_irqhandler(void);
-void WEAK gint0_irqhandler(void);
-void WEAK gint1_irqhandler(void);
-void WEAK eventrouter_irqhandler(void);
-void WEAK c_can1_irqhandler(void);
-void WEAK atimer_irqhandler(void);
-void WEAK rtc_irqhandler(void);
-void WEAK wwdt_irqhandler(void);
-void WEAK c_can0_irqhandler(void);
-void WEAK qei_irqhandler(void);
-
-__attribute__ ((section(".vectors")))
-void (*const vector_table[]) (void) = {
- /* Cortex-M4 interrupts */
- (void*)&_stack,
- reset_handler,
- nmi_handler,
- hard_fault_handler,
- mem_manage_handler,
- bus_fault_handler,
- usage_fault_handler,
- 0, 0, 0, 0, /* reserved */
- sv_call_handler,
- debug_monitor_handler,
- 0, /* reserved */
- pend_sv_handler,
- sys_tick_handler,
-
- /* LPC43xx interrupts */
- dac_irqhandler,
- m0core_irqhandler,
- dma_irqhandler,
- 0, /* reserved */
- 0, /* reserved */
- ethernet_irqhandler,
- sdio_irqhandler,
- lcd_irqhandler,
- usb0_irqhandler,
- usb1_irqhandler,
- sct_irqhandler,
- ritimer_irqhandler,
- timer0_irqhandler,
- timer1_irqhandler,
- timer2_irqhandler,
- timer3_irqhandler,
- mcpwm_irqhandler,
- adc0_irqhandler,
- i2c0_irqhandler,
- i2c1_irqhandler,
- spi_irqhandler,
- adc1_irqhandler,
- ssp0_irqhandler,
- ssp1_irqhandler,
- usart0_irqhandler,
- uart1_irqhandler,
- usart2_irqhandler,
- usart3_irqhandler,
- i2s0_irqhandler,
- i2s1_irqhandler,
- spifi_irqhandler,
- sgpio_irqhandler,
- pin_int0_irqhandler,
- pin_int1_irqhandler,
- pin_int2_irqhandler,
- pin_int3_irqhandler,
- pin_int4_irqhandler,
- pin_int5_irqhandler,
- pin_int6_irqhandler,
- pin_int7_irqhandler,
- gint0_irqhandler,
- gint1_irqhandler,
- eventrouter_irqhandler,
- c_can1_irqhandler,
- 0, /* reserved */
- 0, /* reserved */
- atimer_irqhandler,
- rtc_irqhandler,
- 0, /* reserved */
- wwdt_irqhandler,
- 0, /* reserved */
- c_can0_irqhandler,
- qei_irqhandler,
-};
-
-#define MMIO32(addr) (*(volatile unsigned long*)(addr))
-#define CREG_M4MEMMAP MMIO32( (0x40043000 + 0x100) )
-
-void reset_handler(void)
-{
- volatile unsigned *src, *dest;
-
- __asm__("MSR msp, %0" : : "r"(&_stack));
-
- /* Copy the code from ROM to Real RAM (if enabled) */
- if( (&_etext_ram-&_text_ram) > 0 )
- {
- src = &_etext_rom-(&_etext_ram-&_text_ram);
- /* Change Shadow memory to ROM (for Debug Purpose in case Boot has not set correctly the M4MEMMAP because of debug) */
- CREG_M4MEMMAP = (unsigned long)src;
-
- for(dest = &_text_ram; dest < &_etext_ram; )
- {
- *dest++ = *src++;
- }
-
- /* Change Shadow memory to Real RAM */
- CREG_M4MEMMAP = (unsigned long)&_text_ram;
-
- /* Continue Execution in RAM */
- }
-
- for (src = &_data_loadaddr, dest = &_data; dest < &_edata; src++, dest++)
- *dest = *src;
-
- while (dest < &_ebss)
- *dest++ = 0;
-
- /* Call the application's entry point. */
- main();
-}
-
-void blocking_handler(void)
-{
- while (1) ;
-}
-
-void null_handler(void)
-{
- /* Do nothing. */
-}
-
-#pragma weak nmi_handler = null_handler
-#pragma weak hard_fault_handler = blocking_handler
-#pragma weak mem_manage_handler = blocking_handler
-#pragma weak bus_fault_handler = blocking_handler
-#pragma weak usage_fault_handler = blocking_handler
-#pragma weak sv_call_handler = null_handler
-#pragma weak debug_monitor_handler = null_handler
-#pragma weak pend_sv_handler = null_handler
-#pragma weak sys_tick_handler = null_handler
-#pragma weak dac_irqhandler = null_handler
-#pragma weak m0core_irqhandler = null_handler
-#pragma weak dma_irqhandler = null_handler
-#pragma weak ethernet_irqhandler = null_handler
-#pragma weak sdio_irqhandler = null_handler
-#pragma weak lcd_irqhandler = null_handler
-#pragma weak usb0_irqhandler = null_handler
-#pragma weak usb1_irqhandler = null_handler
-#pragma weak sct_irqhandler = null_handler
-#pragma weak ritimer_irqhandler = null_handler
-#pragma weak timer0_irqhandler = null_handler
-#pragma weak timer1_irqhandler = null_handler
-#pragma weak timer2_irqhandler = null_handler
-#pragma weak timer3_irqhandler = null_handler
-#pragma weak mcpwm_irqhandler = null_handler
-#pragma weak adc0_irqhandler = null_handler
-#pragma weak i2c0_irqhandler = null_handler
-#pragma weak i2c1_irqhandler = null_handler
-#pragma weak spi_irqhandler = null_handler
-#pragma weak adc1_irqhandler = null_handler
-#pragma weak ssp0_irqhandler = null_handler
-#pragma weak ssp1_irqhandler = null_handler
-#pragma weak usart0_irqhandler = null_handler
-#pragma weak uart1_irqhandler = null_handler
-#pragma weak usart2_irqhandler = null_handler
-#pragma weak usart3_irqhandler = null_handler
-#pragma weak i2s0_irqhandler = null_handler
-#pragma weak i2s1_irqhandler = null_handler
-#pragma weak spifi_irqhandler = null_handler
-#pragma weak sgpio_irqhandler = null_handler
-#pragma weak pin_int0_irqhandler = null_handler
-#pragma weak pin_int1_irqhandler = null_handler
-#pragma weak pin_int2_irqhandler = null_handler
-#pragma weak pin_int3_irqhandler = null_handler
-#pragma weak pin_int4_irqhandler = null_handler
-#pragma weak pin_int5_irqhandler = null_handler
-#pragma weak pin_int6_irqhandler = null_handler
-#pragma weak pin_int7_irqhandler = null_handler
-#pragma weak gint0_irqhandler = null_handler
-#pragma weak gint1_irqhandler = null_handler
-#pragma weak eventrouter_irqhandler = null_handler
-#pragma weak c_can1_irqhandler = null_handler
-#pragma weak atimer_irqhandler = null_handler
-#pragma weak rtc_irqhandler = null_handler
-#pragma weak wwdt_irqhandler = null_handler
-#pragma weak c_can0_irqhandler = null_handler
-#pragma weak qei_irqhandler = null_handler
diff --git a/lib/lpc43xx/vector_chipset.c b/lib/lpc43xx/vector_chipset.c
new file mode 100644
index 0000000..0463a65
--- /dev/null
+++ b/lib/lpc43xx/vector_chipset.c
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
+ * Copyright (C) 2012 Michael Ossmann <mike@ossmann.com>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/cm3/common.h>
+
+extern unsigned _etext_ram, _text_ram, _etext_rom;
+
+#define CREG_M4MEMMAP MMIO32( (0x40043000 + 0x100) )
+
+static void pre_main(void)
+{
+ volatile unsigned *src, *dest;
+
+ /* Copy the code from ROM to Real RAM (if enabled) */
+ if( (&_etext_ram-&_text_ram) > 0 )
+ {
+ src = &_etext_rom-(&_etext_ram-&_text_ram);
+ /* Change Shadow memory to ROM (for Debug Purpose in case Boot has not set correctly the M4MEMMAP because of debug) */
+ CREG_M4MEMMAP = (unsigned long)src;
+
+ for(dest = &_text_ram; dest < &_etext_ram; )
+ {
+ *dest++ = *src++;
+ }
+
+ /* Change Shadow memory to Real RAM */
+ CREG_M4MEMMAP = (unsigned long)&_text_ram;
+
+ /* Continue Execution in RAM */
+ }
+}
diff --git a/lib/stm32/f1/can.c b/lib/stm32/can.c
index fc7e0e7..7fde585 100644
--- a/lib/stm32/f1/can.c
+++ b/lib/stm32/can.c
@@ -1,3 +1,21 @@
+/** @defgroup can_file CAN
+
+@ingroup STM32F_files
+
+@brief <b>libopencm3 STM32Fxxx CAN</b>
+
+@version 1.0.0
+
+@author @htmlonly &copy; @endhtmlonly 2010 Piotr Esden-Tempski <piotr@esden.net>
+
+@date 12 November 2012
+
+Devices can have up to two CAN peripherals. The peripherals support up to 1MBit
+transmission rate. The peripheral has several filters for incoming messages that
+can be distributed between two FIFOs and three transmit mailboxes.
+
+LGPL License Terms @ref lgpl_license
+*/
/*
* This file is part of the libopencm3 project.
*
@@ -18,8 +36,25 @@
*/
#include <libopencm3/stm32/can.h>
-#include <libopencm3/stm32/f1/rcc.h>
+#if defined(STM32F1)
+# include <libopencm3/stm32/f1/rcc.h>
+#elif defined(STM32F2)
+# include <libopencm3/stm32/f2/rcc.h>
+#elif defined(STM32F4)
+# include <libopencm3/stm32/f4/rcc.h>
+#else
+# error "stm32 family not defined."
+#endif
+
+/*-----------------------------------------------------------------------------*/
+/** @brief CAN Reset
+
+The CAN peripheral and all its associated configuration registers are placed in the
+reset condition. The reset is effective via the RCC peripheral reset system.
+
+@param[in] canport Unsigned int32. CAN block register address base @ref can_reg_base.
+ */
void can_reset(u32 canport)
{
if (canport == CAN1) {
@@ -31,8 +66,27 @@ void can_reset(u32 canport)
}
}
+/*-----------------------------------------------------------------------------*/
+/** @brief CAN Init
+
+Initialize the selected CAN peripheral block.
+
+@param[in] canport Unsigend int32. CAN register base address @ref can_reg_base.
+@param[in] ttcm bool. Time triggered communication mode.
+@param[in] abom bool. Automatic bus-off management.
+@param[in] awum bool. Automatic wakeup mode.
+@param[in] nart bool. No automatic retransmission.
+@param[in] rflm bool. Receive FIFO locked mode.
+@param[in] txfp bool. Transmit FIFO priority.
+@param[in] sjw Unsigned int32. Resynchronization time quanta jump width.
+@param[in] ts1 Unsigned int32. Time segment 1 time quanta width.
+@param[in] ts2 Unsigned int32. Time segment 2 time quanta width.
+@param[in] brp Unsigned int32. Baud rate prescaler.
+@returns int 0 on success, 1 on initialization failure.
+*/
int can_init(u32 canport, bool ttcm, bool abom, bool awum, bool nart,
- bool rflm, bool txfp, u32 sjw, u32 ts1, u32 ts2, u32 brp)
+ bool rflm, bool txfp, u32 sjw, u32 ts1, u32 ts2, u32 brp,
+ bool loopback, bool silent)
{
u32 wait_ack = 0x00000000;
u32 can_msr_inak_timeout = 0x0000FFFF;
@@ -54,6 +108,9 @@ int can_init(u32 canport, bool ttcm, bool abom, bool awum, bool nart,
if ((CAN_MSR(canport) & CAN_MSR_INAK) != CAN_MSR_INAK)
return 1;
+ /* clear can timing bits */
+ CAN_BTR(canport) = 0;
+
/* Set the automatic bus-off management. */
if (ttcm)
CAN_MCR(canport) |= CAN_MCR_TTCM;
@@ -85,8 +142,19 @@ int can_init(u32 canport, bool ttcm, bool abom, bool awum, bool nart,
else
CAN_MCR(canport) &= ~CAN_MCR_TXFP;
+ if (silent)
+ CAN_BTR(canport) |= CAN_BTR_SILM;
+ else
+ CAN_BTR(canport) &= ~CAN_BTR_SILM;
+
+ if (loopback)
+ CAN_BTR(canport) |= CAN_BTR_LBKM;
+ else
+ CAN_BTR(canport) &= ~CAN_BTR_LBKM;
+
+
/* Set bit timings. */
- CAN_BTR(canport) = sjw | ts2 | ts1 |
+ CAN_BTR(canport) |= sjw | ts2 | ts1 |
(u32)(CAN_BTR_BRP_MASK & (brp - 1));
/* Request initialization "leave". */
@@ -105,6 +173,20 @@ int can_init(u32 canport, bool ttcm, bool abom, bool awum, bool nart,
return ret;
}
+/*-----------------------------------------------------------------------------*/
+/** @brief CAN Filter Init
+
+Initialize incoming message filter and assign to FIFO.
+
+@param[in] canport Unsigned int32. CAN block register base @ref can_reg_base.
+@param[in] nr Unsigned int32. ID number of the filter.
+@param[in] scale_32bit bool. 32-bit scale for the filter?
+@param[in] id_list_mode bool. ID list filter mode?
+@param[in] fr1 Unsigned int32. First filter register content.
+@param[in] fr2 Unsigned int32. Second filter register content.
+@param[in] fifo Unsigned int32. FIFO id.
+@param[in] enable bool. Enable filter?
+ */
void can_filter_init(u32 canport, u32 nr, bool scale_32bit, bool id_list_mode,
u32 fr1, u32 fr2, u32 fifo, bool enable)
{
@@ -151,6 +233,18 @@ void can_filter_init(u32 canport, u32 nr, bool scale_32bit, bool id_list_mode,
CAN_FMR(canport) &= ~CAN_FMR_FINIT;
}
+/*-----------------------------------------------------------------------------*/
+/** @brief CAN Initialize a 16bit Message ID Mask Filter
+
+@param[in] canport Unsigned int32. CAN block register base @ref can_reg_base.
+@param[in] nr Unsigned int32. ID number of the filter.
+@param[in] id1 Unsigned int16. First message ID to filter.
+@param[in] mask1 Unsigned int16. First message ID bit mask.
+@param[in] id2 Unsigned int16. Second message ID to filter.
+@param[in] mask2 Unsigned int16. Second message ID bit mask.
+@param[in] fifo Unsigned int32. FIFO id.
+@param[in] enable bool. Enable filter?
+ */
void can_filter_id_mask_16bit_init(u32 canport, u32 nr, u16 id1, u16 mask1,
u16 id2, u16 mask2, u32 fifo, bool enable)
{
@@ -159,12 +253,34 @@ void can_filter_id_mask_16bit_init(u32 canport, u32 nr, u16 id1, u16 mask1,
((u32)id2 << 16) | (u32)mask2, fifo, enable);
}
+/*-----------------------------------------------------------------------------*/
+/** @brief CAN Initialize a 32bit Message ID Mask Filter
+
+@param[in] canport Unsigned int32. CAN block register base @ref can_reg_base.
+@param[in] nr Unsigned int32. ID number of the filter.
+@param[in] id Unsigned int32. Message ID to filter.
+@param[in] mask Unsigned int32. Message ID bit mask.
+@param[in] fifo Unsigned int32. FIFO id.
+@param[in] enable bool. Enable filter?
+ */
void can_filter_id_mask_32bit_init(u32 canport, u32 nr, u32 id, u32 mask,
u32 fifo, bool enable)
{
can_filter_init(canport, nr, true, false, id, mask, fifo, enable);
}
+/*-----------------------------------------------------------------------------*/
+/** @brief CAN Initialize a 16bit Message ID List Filter
+
+@param[in] canport Unsigned int32. CAN block register base @ref can_reg_base.
+@param[in] nr Unsigned int32. ID number of the filter.
+@param[in] id1 Unsigned int16. First message ID to match.
+@param[in] id2 Unsigned int16. Second message ID to match.
+@param[in] id3 Unsigned int16. Third message ID to match.
+@param[in] id4 Unsigned int16. Fourth message ID to match.
+@param[in] fifo Unsigned int32. FIFO id.
+@param[in] enable bool. Enable filter?
+ */
void can_filter_id_list_16bit_init(u32 canport, u32 nr, u16 id1, u16 id2,
u16 id3, u16 id4, u32 fifo, bool enable)
{
@@ -173,27 +289,62 @@ void can_filter_id_list_16bit_init(u32 canport, u32 nr, u16 id1, u16 id2,
((u32)id3 << 16) | (u32)id4, fifo, enable);
}
+/*-----------------------------------------------------------------------------*/
+/** @brief CAN Initialize a 32bit Message ID List Filter
+
+@param[in] canport Unsigned int32. CAN block register base @ref can_reg_base.
+@param[in] nr Unsigned int32. ID number of the filter.
+@param[in] id1 Unsigned int32. First message ID to match.
+@param[in] id2 Unsigned int32. Second message ID to match.
+@param[in] fifo Unsigned int32. FIFO id.
+@param[in] enable bool. Enable filter?
+ */
void can_filter_id_list_32bit_init(u32 canport, u32 nr, u32 id1, u32 id2,
u32 fifo, bool enable)
{
can_filter_init(canport, nr, true, true, id1, id2, fifo, enable);
}
+/*-----------------------------------------------------------------------------*/
+/** @brief CAN Enable IRQ
+
+@param[in] canport Unsigned int32. CAN block register base @ref can_reg_base.
+@param[in] irq Unsigned int32. IRQ bit(s).
+ */
void can_enable_irq(u32 canport, u32 irq)
{
CAN_IER(canport) |= irq;
}
+/*-----------------------------------------------------------------------------*/
+/** @brief CAN Disable IRQ
+
+@param[in] canport Unsigned int32. CAN block register base @ref can_reg_base.
+@param[in] irq Unsigned int32. IRQ bit(s).
+ */
void can_disable_irq(u32 canport, u32 irq)
{
CAN_IER(canport) &= ~irq;
}
+/*-----------------------------------------------------------------------------*/
+/** @brief CAN Transmit Message
+
+@param[in] canport Unsigned int32. CAN block register base @ref can_reg_base.
+@param[in] id Unsigned int32. Message ID.
+@param[in] ext bool. Extended message ID?
+@param[in] rtr bool. Request transmit?
+@param[in] length Unsigned int8. Message payload length.
+@param[in] data Unsigned int8[]. Message payload data.
+@returns int 0, 1 or 2 on success and depending on which outgoing mailbox got
+selected. -1 if no mailbox was available and no transmission got queued.
+ */
int can_transmit(u32 canport, u32 id, bool ext, bool rtr, u8 length, u8 *data)
{
int ret = 0, i;
u32 mailbox = 0;
+ /* Check which transmit mailbox is empty if any. */
if ((CAN_TSR(canport) & CAN_TSR_TME0) == CAN_TSR_TME0) {
ret = 0;
mailbox = CAN_MBOX0;
@@ -207,7 +358,7 @@ int can_transmit(u32 canport, u32 id, bool ext, bool rtr, u8 length, u8 *data)
ret = -1;
}
- /* Check if we have an empty mailbox. */
+ /* If we have no empty mailbox return with an error. */
if (ret == -1)
return ret;
@@ -245,6 +396,12 @@ int can_transmit(u32 canport, u32 id, bool ext, bool rtr, u8 length, u8 *data)
return ret;
}
+/*-----------------------------------------------------------------------------*/
+/** @brief CAN Release FIFO
+
+@param[in] canport Unsigned int32. CAN block register base @ref can_reg_base.
+@param[in] fifo Unsigned int8. FIFO id.
+ */
void can_fifo_release(u32 canport, u8 fifo)
{
if (fifo == 0)
@@ -253,6 +410,19 @@ void can_fifo_release(u32 canport, u8 fifo)
CAN_RF1R(canport) |= CAN_RF1R_RFOM1;
}
+/*-----------------------------------------------------------------------------*/
+/** @brief CAN Receive Message
+
+@param[in] canport Unsigned int32. CAN block register base @ref can_reg_base.
+@param[in] fifo Unsigned int8. FIFO id.
+@param[in] release bool. Release the FIFO automatically after coping data out.
+@param[out] id Unsigned int32 pointer. Message ID.
+@param[out] ext bool pointer. The message ID is extended?
+@param[out] rtr bool pointer. Request of transmission?
+@param[out] fmi Unsigned int32 pointer. ID of the matched filter.
+@param[out] length Unsigned int8 pointer. Length of message payload.
+@param[out] data Unsigned int8[]. Message payload data.
+ */
void can_receive(u32 canport, u8 fifo, bool release, u32 *id, bool *ext,
bool *rtr, u32 *fmi, u8 *length, u8 *data)
{
@@ -299,5 +469,10 @@ void can_receive(u32 canport, u8 fifo, bool release, u32 *id, bool *ext,
/* Release the FIFO. */
if (release)
- can_fifo_release(CAN1, 0);
+ can_fifo_release(canport, fifo);
+}
+
+bool can_available_mailbox(u32 canport)
+{
+ return CAN_TSR(canport) & (CAN_TSR_TME0 | CAN_TSR_TME1 | CAN_TSR_TME2);
}
diff --git a/lib/stm32/crc.c b/lib/stm32/common/crc_common_all.c
index bd9e8d2..d65d1b7 100644
--- a/lib/stm32/crc.c
+++ b/lib/stm32/common/crc_common_all.c
@@ -1,8 +1,4 @@
-/** @defgroup crc_file CRC
-
-@ingroup STM32F_files
-
-@brief <b>libopencm3 STM32Fxxx CRC</b>
+/** @addtogroup crc_file
@version 1.0.0
diff --git a/lib/stm32/dac.c b/lib/stm32/common/dac_common_all.c
index 55440bf..a6be233 100644
--- a/lib/stm32/dac.c
+++ b/lib/stm32/common/dac_common_all.c
@@ -1,8 +1,4 @@
-/** @defgroup STM32F_dac_file DAC
-
-@ingroup STM32F_files
-
-@brief <b>libopencm3 STM32Fxx Digital to Analog Converter</b>
+/** @addtogroup dac_file
@version 1.0.0
diff --git a/lib/stm32/common/dma_common_f13.c b/lib/stm32/common/dma_common_f13.c
new file mode 100644
index 0000000..35b9da6
--- /dev/null
+++ b/lib/stm32/common/dma_common_f13.c
@@ -0,0 +1,431 @@
+/** @addtogroup dma_file
+
+@version 1.0.0
+
+@author @htmlonly &copy; @endhtmlonly 2010 Thomas Otto <tommi@viadmin.org>
+
+@date 18 August 2012
+
+This library supports the DMA Control System in the STM32 series of ARM Cortex
+Microcontrollers by ST Microelectronics.
+
+Up to two DMA controllers are supported. 12 DMA channels are allocated 7 to
+the first DMA controller and 5 to the second. Each channel is connected to
+between 3 and 6 hardware peripheral DMA signals in a logical OR arrangement.
+
+DMA transfers can be configured to occur between peripheral and memory in
+any combination including memory to memory. Circular mode transfers are
+also supported in transfers involving a peripheral. An arbiter is provided
+to resolve priority DMA requests. Transfers can be made with 8, 16 or 32 bit
+words.
+
+LGPL License Terms @ref lgpl_license
+ */
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**@{*/
+
+#include <libopencm3/stm32/f1/dma.h>
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Reset
+
+The channel is disabled and configuration registers are cleared.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
+*/
+
+void dma_channel_reset(u32 dma, u8 channel)
+{
+ /* Disable channel and reset config bits. */
+ DMA_CCR(dma, channel) = 0;
+ /* Reset data transfer number. */
+ DMA_CNDTR(dma, channel) = 0;
+ /* Reset peripheral address. */
+ DMA_CPAR(dma, channel) = 0;
+ /* Reset memory address. */
+ DMA_CMAR(dma, channel) = 0;
+ /* Reset interrupt flags. */
+ DMA_IFCR(dma) |= DMA_IFCR_CIF(channel);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Clear Interrupt Flag
+
+The interrupt flag for the channel is cleared. More than one interrupt for the
+same channel may be cleared by using the logical OR of the interrupt flags.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] channel unsigned int8. Channel number: @ref dma_ch
+@param[in] interrupts unsigned int32. Logical OR of interrupt numbers: @ref dma_if_offset
+*/
+
+void dma_clear_interrupt_flags(u32 dma, u8 channel, u32 interrupts)
+{
+/* Get offset to interrupt flag location in channel field */
+ u32 flags = (interrupts << DMA_FLAG_OFFSET(channel));
+ DMA_IFCR(dma) = flags;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Read Interrupt Flag
+
+The interrupt flag for the channel is returned.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] channel unsigned int8. Channel number: @ref dma_ch
+@param[in] interrupt unsigned int32. Interrupt number: @ref dma_ch
+@returns bool interrupt flag is set.
+*/
+
+bool dma_get_interrupt_flag(u32 dma, u8 channel, u32 interrupt)
+{
+/* get offset to interrupt flag location in channel field. */
+ u32 flag = (interrupt << DMA_FLAG_OFFSET(channel));
+ return ((DMA_ISR(dma) & flag) > 0);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Enable Memory to Memory Transfers
+
+Memory to memory transfers do not require a trigger to activate each transfer.
+Transfers begin immediately the channel has been enabled, and proceed without
+intervention.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
+*/
+
+void dma_enable_mem2mem_mode(u32 dma, u8 channel)
+{
+ DMA_CCR(dma, channel) |= DMA_CCR_MEM2MEM;
+ DMA_CCR(dma, channel) &= ~DMA_CCR_CIRC;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Set Priority
+
+Channel Priority has four levels: low to very high. This has precedence over the
+hardware priority.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
+@param[in] prio unsigned int32. Priority level @ref dma_ch_pri.
+*/
+
+void dma_set_priority(u32 dma, u8 channel, u32 prio)
+{
+ DMA_CCR(dma, channel) &= ~(DMA_CCR_PL_MASK);
+ DMA_CCR(dma, channel) |= prio;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Set Memory Word Width
+
+Set the memory word width 8 bits, 16 bits, or 32 bits. Refer to datasheet for
+alignment information if the source and destination widths do not match.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
+@param[in] mem_size unsigned int32. Memory word width @ref dma_ch_memwidth.
+*/
+
+void dma_set_memory_size(u32 dma, u8 channel, u32 mem_size)
+{
+
+ DMA_CCR(dma, channel) &= ~(DMA_CCR_MSIZE_MASK);
+ DMA_CCR(dma, channel) |= mem_size;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Set Peripheral Word Width
+
+Set the peripheral word width 8 bits, 16 bits, or 32 bits. Refer to datasheet for
+alignment information if the source and destination widths do not match, or
+if the peripheral does not support byte or half-word writes.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
+@param[in] peripheral_size unsigned int32. Peripheral word width @ref dma_ch_perwidth.
+*/
+
+void dma_set_peripheral_size(u32 dma, u8 channel, u32 peripheral_size)
+{
+ DMA_CCR(dma, channel) &= ~(DMA_CCR_PSIZE_MASK);
+ DMA_CCR(dma, channel) |= peripheral_size;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Enable Memory Increment after Transfer
+
+Following each transfer the current memory address is incremented by
+1, 2 or 4 depending on the data size set in @ref dma_set_memory_size. The
+value held by the base memory address register is unchanged.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
+*/
+
+void dma_enable_memory_increment_mode(u32 dma, u8 channel)
+{
+ DMA_CCR(dma, channel) |= DMA_CCR_MINC;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Disable Memory Increment after Transfer
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
+*/
+
+void dma_disable_memory_increment_mode(u32 dma, u8 channel)
+{
+ DMA_CCR(dma, channel) &= ~DMA_CCR_MINC;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Enable Peripheral Increment after Transfer
+
+Following each transfer the current peripheral address is incremented by
+1, 2 or 4 depending on the data size set in @ref dma_set_peripheral_size. The
+value held by the base peripheral address register is unchanged.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
+*/
+
+void dma_enable_peripheral_increment_mode(u32 dma, u8 channel)
+{
+ DMA_CCR(dma, channel) |= DMA_CCR_PINC;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Disable Peripheral Increment after Transfer
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
+*/
+
+void dma_disable_peripheral_increment_mode(u32 dma, u8 channel)
+{
+ DMA_CCR(dma, channel) &= ~DMA_CCR_PINC;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Enable Memory Circular Mode
+
+After the number of bytes/words to be transferred has been completed, the
+original transfer block size, memory and peripheral base addresses are
+reloaded and the process repeats.
+
+@note This cannot be used with memory to memory mode, which is explictly
+disabled here.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
+*/
+
+void dma_enable_circular_mode(u32 dma, u8 channel)
+{
+ DMA_CCR(dma, channel) |= DMA_CCR_CIRC;
+ DMA_CCR(dma, channel) &= ~DMA_CCR_MEM2MEM;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Enable Transfers from a Peripheral
+
+The data direction is set to read from a peripheral.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
+*/
+
+void dma_set_read_from_peripheral(u32 dma, u8 channel)
+{
+ DMA_CCR(dma, channel) &= ~DMA_CCR_DIR;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Enable Transfers from Memory
+
+The data direction is set to read from memory.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
+*/
+
+void dma_set_read_from_memory(u32 dma, u8 channel)
+{
+ DMA_CCR(dma, channel) |= DMA_CCR_DIR;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Enable Interrupt on Transfer Error
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
+*/
+
+void dma_enable_transfer_error_interrupt(u32 dma, u8 channel)
+{
+ DMA_CCR(dma, channel) |= DMA_CCR_TEIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Disable Interrupt on Transfer Error
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
+*/
+
+void dma_disable_transfer_error_interrupt(u32 dma, u8 channel)
+{
+ DMA_CCR(dma, channel) &= ~DMA_CCR_TEIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Enable Interrupt on Transfer Half Complete
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
+*/
+
+void dma_enable_half_transfer_interrupt(u32 dma, u8 channel)
+{
+ DMA_CCR(dma, channel) |= DMA_CCR_HTIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Disable Interrupt on Transfer Half Complete
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
+*/
+
+void dma_disable_half_transfer_interrupt(u32 dma, u8 channel)
+{
+ DMA_CCR(dma, channel) &= ~DMA_CCR_HTIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Enable Interrupt on Transfer Complete
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
+*/
+
+void dma_enable_transfer_complete_interrupt(u32 dma, u8 channel)
+{
+ DMA_CCR(dma, channel) |= DMA_CCR_TCIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Disable Interrupt on Transfer Complete
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
+*/
+
+void dma_disable_transfer_complete_interrupt(u32 dma, u8 channel)
+{
+ DMA_CCR(dma, channel) &= ~DMA_CCR_TCIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Enable
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
+*/
+
+void dma_enable_channel(u32 dma, u8 channel)
+{
+ DMA_CCR(dma, channel) |= DMA_CCR_EN;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Disable
+
+@note The DMA channel registers retain their values when the channel is disabled.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
+*/
+
+void dma_disable_channel(u32 dma, u8 channel)
+{
+ DMA_CCR(dma, channel) &= ~DMA_CCR_EN;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Set the Peripheral Address
+
+Set the address of the peripheral register to or from which data is to be transferred.
+Refer to the documentation for the specific peripheral.
+
+@note The DMA channel must be disabled before setting this address. This function
+has no effect if the channel is enabled.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
+@param[in] address unsigned int32. Peripheral Address.
+*/
+
+void dma_set_peripheral_address(u32 dma, u8 channel, u32 address)
+{
+ if (!(DMA_CCR(dma, channel) & DMA_CCR_EN))
+ DMA_CPAR(dma, channel) = (u32) address;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Set the Base Memory Address
+
+@note The DMA channel must be disabled before setting this address. This function
+has no effect if the channel is enabled.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
+@param[in] address unsigned int32. Memory Initial Address.
+*/
+
+void dma_set_memory_address(u32 dma, u8 channel, u32 address)
+{
+ if (!(DMA_CCR(dma, channel) & DMA_CCR_EN))
+ DMA_CMAR(dma, channel) = (u32) address;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Set the Transfer Block Size
+
+@note The DMA channel must be disabled before setting this count value. The count
+is not changed if the channel is enabled.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
+@param[in] number unsigned int16. Number of data words to transfer (65535 maximum).
+*/
+
+void dma_set_number_of_data(u32 dma, u8 channel, u16 number)
+{
+ DMA_CNDTR(dma, channel) = number;
+}
+/**@}*/
+
diff --git a/lib/stm32/common/dma_common_f24.c b/lib/stm32/common/dma_common_f24.c
new file mode 100644
index 0000000..504c30e
--- /dev/null
+++ b/lib/stm32/common/dma_common_f24.c
@@ -0,0 +1,780 @@
+/** @addtogroup dma_file
+
+@version 1.0.0
+
+@author @htmlonly &copy; @endhtmlonly 2012 Ken Sarkies <ksarkies@internode.on.net>
+
+@date 30 November 2012
+
+This library supports the DMA Control System in the STM32F2 and STM32F4
+series of ARM Cortex Microcontrollers by ST Microelectronics.
+
+Up to two DMA controllers are supported each with 8 streams, and each stream
+having up to 8 channels hardware dedicated to various peripheral DMA signals.
+
+DMA transfers can be configured to occur between peripheral and memory in
+either direction, and memory to memory. Peripheral to peripheral transfer
+is not supported. Circular mode transfers are also supported in transfers
+involving a peripheral. An arbiter is provided to resolve priority DMA
+requests. Transfers can be made with 8, 16 or 32 bit words.
+
+Each stream has access to a 4 word deep FIFO and can use double buffering
+by means of two memory pointers. When using the FIFO it is possible to
+configure transfers to occur in indivisible bursts.
+
+It is also possible to select a peripheral to control the flow of data rather
+than the DMA controller. This limits the functionality but is udeful when the
+number of transfers is unknown.
+
+LGPL License Terms @ref lgpl_license
+ */
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2012 Ken Sarkies <ksarkies@internode.on.net>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**@{*/
+
+#include <libopencm3/stm32/f4/dma.h>
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Reset
+
+The specified stream is disabled and configuration registers are cleared.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+*/
+
+void dma_stream_reset(u32 dma, u8 stream)
+{
+/* Disable stream (must be done before register is otherwise changed). */
+ DMA_SCR(dma, stream) &= ~DMA_SxCR_EN;
+/* Reset all config bits. */
+ DMA_SCR(dma, stream) = 0;
+/* Reset data transfer number. */
+ DMA_SNDTR(dma, stream) = 0;
+/* Reset peripheral and memory addresses. */
+ DMA_SPAR(dma, stream) = 0;
+ DMA_SM0AR(dma, stream) = 0;
+ DMA_SM1AR(dma, stream) = 0;
+/* This is the default setting */
+ DMA_SFCR(dma, stream) = 0x21;
+/* Reset all stream interrupt flags using the interrupt flag clear register. */
+ u32 mask = DMA_ISR_MASK(stream);
+ if (stream < 4)
+ {
+ DMA_LIFCR(dma) |= mask;
+ }
+ else
+ {
+ DMA_HIFCR(dma) |= mask;
+ }
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Clear Interrupt Flag
+
+The interrupt flag for the stream is cleared. More than one interrupt for the
+same stream may be cleared by using the bitwise OR of the interrupt flags.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+@param[in] interrupts unsigned int32. Bitwise OR of interrupt numbers: @ref dma_if_offset
+*/
+
+void dma_clear_interrupt_flags(u32 dma, u8 stream, u32 interrupts)
+{
+/* Get offset to interrupt flag location in stream field */
+ u32 flags = (interrupts << DMA_ISR_OFFSET(stream));
+/* First four streams are in low register. Flag clear must be set then reset. */
+ if (stream < 4)
+ {
+ DMA_LIFCR(dma) = flags;
+ }
+ else
+ {
+ DMA_HIFCR(dma) = flags;
+ }
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Read Interrupt Flag
+
+The interrupt flag for the stream is returned.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+@param[in] interrupt unsigned int32. Interrupt number: @ref dma_if_offset
+@returns bool interrupt flag is set.
+*/
+
+bool dma_get_interrupt_flag(u32 dma, u8 stream, u32 interrupt)
+{
+/* get offset to interrupt flag location in stream field.
+Assumes stream and interrupt parameters are integers */
+ u32 flag = (interrupt << DMA_ISR_OFFSET(stream));
+/* First four streams are in low register */
+ if (stream < 4) return ((DMA_LISR(dma) & flag) > 0);
+ else return ((DMA_HISR(dma) & flag) > 0);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Enable Transfer Direction
+
+Set peripheral to memory, memory to peripheral or memory to memory. If memory
+to memory mode is selected, circular mode and double buffer modes are disabled.
+Ensure that these modes are not enabled at a later time.
+
+Ensure that the stream is disabled otherwise the setting will not be changed.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+@param[in] direction unsigned int32. Data transfer direction @ref dma_st_dir
+*/
+
+void dma_set_transfer_mode(u32 dma, u8 stream, u32 direction)
+{
+ u32 reg32 = (DMA_SCR(dma, stream) & ~DMA_SxCR_DIR_MASK);
+/* Disable circular and double buffer modes if memory to memory transfers
+are in effect (Direct Mode is automatically disabled by hardware) */
+ if (direction == DMA_SxCR_DIR_MEM_TO_MEM)
+ {
+ reg32 &= ~(DMA_SxCR_CIRC | DMA_SxCR_DBM);
+ }
+ DMA_SCR(dma, stream) = (reg32 | direction);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Set Priority
+
+Stream Priority has four levels: low to very high. This has precedence over the
+hardware priority. In the event of equal software priority the lower numbered
+stream has priority.
+
+Ensure that the stream is disabled otherwise the setting will not be changed.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+@param[in] prio unsigned int32. Priority level @ref dma_st_pri.
+*/
+
+void dma_set_priority(u32 dma, u8 stream, u32 prio)
+{
+ DMA_SCR(dma, stream) &= ~(DMA_SxCR_PL_MASK);
+ DMA_SCR(dma, stream) |= prio;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Set Memory Word Width
+
+Set the memory word width 8 bits, 16 bits, or 32 bits. Refer to datasheet for
+alignment information if the source and destination widths do not match.
+
+Ensure that the stream is disabled otherwise the setting will not be changed.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+@param[in] mem_size unsigned int32. Memory word width @ref dma_st_memwidth.
+*/
+
+void dma_set_memory_size(u32 dma, u8 stream, u32 mem_size)
+{
+
+ DMA_SCR(dma, stream) &= ~(DMA_SxCR_MSIZE_MASK);
+ DMA_SCR(dma, stream) |= mem_size;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Set Peripheral Word Width
+
+Set the peripheral word width 8 bits, 16 bits, or 32 bits. Refer to datasheet for
+alignment information if the source and destination widths do not match, or
+if the peripheral does not support byte or half-word writes.
+
+Ensure that the stream is disabled otherwise the setting will not be changed.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+@param[in] peripheral_size unsigned int32. Peripheral word width @ref dma_st_perwidth.
+*/
+
+void dma_set_peripheral_size(u32 dma, u8 stream, u32 peripheral_size)
+{
+ DMA_SCR(dma, stream) &= ~(DMA_SxCR_PSIZE_MASK);
+ DMA_SCR(dma, stream) |= peripheral_size;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Enable Memory Increment after Transfer
+
+Following each transfer the current memory address is incremented by
+1, 2 or 4 depending on the data size set in @ref dma_set_memory_size. The
+value held by the base memory address register is unchanged.
+
+Ensure that the stream is disabled otherwise the setting will not be changed.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+*/
+
+void dma_enable_memory_increment_mode(u32 dma, u8 stream)
+{
+ DMA_SCR(dma, stream) |= DMA_SxCR_MINC;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Disable Memory Increment after Transfer
+
+Ensure that the stream is disabled otherwise the setting will not be changed.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+*/
+
+void dma_disable_memory_increment_mode(u32 dma, u8 stream)
+{
+ DMA_SCR(dma, stream) &= ~DMA_SxCR_MINC;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Enable Variable Sized Peripheral Increment after Transfer
+
+Following each transfer the current peripheral address is incremented by
+1, 2 or 4 depending on the data size set in @ref dma_set_peripheral_size. The
+value held by the base peripheral address register is unchanged.
+
+Ensure that the stream is disabled otherwise the setting will not be changed.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+*/
+
+void dma_enable_peripheral_increment_mode(u32 dma, u8 stream)
+{
+ u32 reg32 = (DMA_SCR(dma, stream) | DMA_SxCR_PINC);
+ DMA_SCR(dma, stream) = (reg32 & ~DMA_SxCR_PINCOS);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Disable Peripheral Increment after Transfer
+
+Ensure that the stream is disabled otherwise the setting will not be changed.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+*/
+
+void dma_disable_peripheral_increment_mode(u32 dma, u8 stream)
+{
+ DMA_SCR(dma, stream) &= ~DMA_SxCR_PINC;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Enable Fixed Sized Peripheral Increment after Transfer
+
+Following each transfer the current peripheral address is incremented by
+4 regardless of the data size. The value held by the base peripheral address
+register is unchanged.
+
+Ensure that the stream is disabled otherwise the setting will not be changed.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+*/
+
+void dma_enable_fixed_peripheral_increment_mode(u32 dma, u8 stream)
+{
+ DMA_SCR(dma, stream) |= (DMA_SxCR_PINC | DMA_SxCR_PINCOS);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Enable Memory Circular Mode
+
+After the number of bytes/words to be transferred has been completed, the
+original transfer block size, memory and peripheral base addresses are
+reloaded and the process repeats.
+
+Ensure that the stream is disabled otherwise the setting will not be changed.
+
+@note This cannot be used with memory to memory mode. It is disabled
+automatically if the peripheral is selected as the flow controller.
+It is enabled automatically if double buffered mode is selected.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+*/
+
+void dma_enable_circular_mode(u32 dma, u8 stream)
+{
+ DMA_SCR(dma, stream) |= DMA_SxCR_CIRC;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Channel Select
+
+Associate an input channel to the stream. Not every channel is allocated to a
+hardware DMA request signal. The allocations for each stream are given in the
+STM32F4 Reference Manual.
+
+Ensure that the stream is disabled otherwise the setting will not be changed.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+@param[in] channel unsigned int8. Channel selection @ref dma_ch_sel
+*/
+
+void dma_channel_select(u32 dma, u8 stream, u32 channel)
+{
+ DMA_SCR(dma, stream) |= channel;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Set Memory Burst Configuration
+
+Set the memory burst type to none, 4 8 or 16 word length. This is forced to none
+if direct mode is used.
+
+Ensure that the stream is disabled otherwise the setting will not be changed.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+@param[in] burst unsigned int8. Memory Burst selection @ref dma_mburst
+*/
+
+void dma_set_memory_burst(u32 dma, u8 stream, u32 burst)
+{
+ u32 reg32 = (DMA_SCR(dma, stream) & ~DMA_SxCR_MBURST_MASK);
+ DMA_SCR(dma, stream) = (reg32 | burst);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Set Peripheral Burst Configuration
+
+Set the memory burst type to none, 4 8 or 16 word length. This is forced to none
+if direct mode is used.
+
+Ensure that the stream is disabled otherwise the setting will not be changed.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+@param[in] burst unsigned int8. Peripheral Burst selection @ref dma_pburst
+*/
+
+void dma_set_peripheral_burst(u32 dma, u8 stream, u32 burst)
+{
+ u32 reg32 = (DMA_SCR(dma, stream) & ~DMA_SxCR_PBURST_MASK);
+ DMA_SCR(dma, stream) = (reg32 | burst);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Set Initial Target Memory
+
+In double buffered mode, set the target memory (M0 or M1) to be used for the first
+transfer.
+
+Ensure that the stream is disabled otherwise the setting will not be changed.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+@param[in] memory unsigned int8. Initial memory pointer to use: 0 or 1
+*/
+
+void dma_set_initial_target(u32 dma, u8 stream, u8 memory)
+{
+ u32 reg32 = (DMA_SCR(dma, stream) & ~DMA_SxCR_CT);
+ if (memory == 1) reg32 |= DMA_SxCR_CT;
+ DMA_SCR(dma, stream) = reg32;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Read Current Memory Target
+
+In double buffer mode, return the current memory target (M0 or M1). It is possible
+to update the memory pointer in the register that is <b> not </b> currently in
+use. An attempt to change the register currently in use will cause the stream
+to be disabled and the transfer error flag to be set.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+@returns unsigned int8. Memory buffer in use: 0 or 1
+*/
+
+u8 dma_get_target(u32 dma, u8 stream)
+{
+ if (DMA_SCR(dma, stream) & DMA_SxCR_CT) return 1;
+ return 0;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Enable Double Buffer Mode
+
+Double buffer mode is used for memory to/from peripheral transfers only, and in
+circular mode which is automatically enabled. Two memory buffers must be
+established with pointers stored in the memory pointer registers.
+
+Ensure that the stream is disabled otherwise the setting will not be changed.
+
+@note This cannot be used with memory to memory mode.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+*/
+
+void dma_enable_double_buffer_mode(u32 dma, u8 stream)
+{
+ DMA_SCR(dma, stream) |= DMA_SxCR_DBM;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Disable Double Buffer Mode
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+*/
+
+void dma_disable_double_buffer_mode(u32 dma, u8 stream)
+{
+ DMA_SCR(dma, stream) &= ~DMA_SxCR_DBM;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Set Peripheral Flow Control
+
+Set the peripheral to control DMA flow. Useful when the number of transfers is
+unknown. This is forced off when memory to memory mode is selected.
+
+Ensure that the stream is disabled otherwise the setting will not be changed.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+*/
+
+void dma_set_peripheral_flow_control(u32 dma, u8 stream)
+{
+ DMA_SCR(dma, stream) |= DMA_SxCR_PFCTRL;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Set DMA Flow Control
+
+Set the DMA controller to control DMA flow. This is the default.
+
+Ensure that the stream is disabled otherwise the setting will not be changed.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+*/
+
+void dma_set_dma_flow_control(u32 dma, u8 stream)
+{
+ DMA_SCR(dma, stream) &= ~DMA_SxCR_PFCTRL;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Enable Interrupt on Transfer Error
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+*/
+
+void dma_enable_transfer_error_interrupt(u32 dma, u8 stream)
+{
+ dma_clear_interrupt_flags(dma, stream, DMA_ISR_TEIF);
+ DMA_SCR(dma, stream) |= DMA_SxCR_TEIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Disable Interrupt on Transfer Error
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+*/
+
+void dma_disable_transfer_error_interrupt(u32 dma, u8 stream)
+{
+ DMA_SCR(dma, stream) &= ~DMA_SxCR_TEIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Enable Interrupt on Transfer Half Complete
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+*/
+
+void dma_enable_half_transfer_interrupt(u32 dma, u8 stream)
+{
+ dma_clear_interrupt_flags(dma, stream, DMA_ISR_HTIF);
+ DMA_SCR(dma, stream) |= DMA_SxCR_HTIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Disable Interrupt on Transfer Half Complete
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+*/
+
+void dma_disable_half_transfer_interrupt(u32 dma, u8 stream)
+{
+ DMA_SCR(dma, stream) &= ~DMA_SxCR_HTIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Enable Interrupt on Transfer Complete
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+*/
+
+void dma_enable_transfer_complete_interrupt(u32 dma, u8 stream)
+{
+ dma_clear_interrupt_flags(dma, stream, DMA_ISR_TCIF);
+ DMA_SCR(dma, stream) |= DMA_SxCR_TCIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Disable Interrupt on Transfer Complete
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+*/
+
+void dma_disable_transfer_complete_interrupt(u32 dma, u8 stream)
+{
+ DMA_SCR(dma, stream) &= ~DMA_SxCR_TCIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Enable Interrupt on Direct Mode Error
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+*/
+
+void dma_enable_direct_mode_error_interrupt(u32 dma, u8 stream)
+{
+ dma_clear_interrupt_flags(dma, stream, DMA_ISR_DMEIF);
+ DMA_SCR(dma, stream) |= DMA_SxCR_DMEIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Disable Interrupt on Direct Mode Error
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+*/
+
+void dma_disable_direct_mode_error_interrupt(u32 dma, u8 stream)
+{
+ DMA_SCR(dma, stream) &= ~DMA_SxCR_DMEIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Enable Interrupt on FIFO Error
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+*/
+
+void dma_enable_fifo_error_interrupt(u32 dma, u8 stream)
+{
+ dma_clear_interrupt_flags(dma, stream, DMA_ISR_FEIF);
+ DMA_SFCR(dma, stream) |= DMA_SxFCR_FEIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Disable Interrupt on FIFO Error
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+*/
+
+void dma_disable_fifo_error_interrupt(u32 dma, u8 stream)
+{
+ DMA_SFCR(dma, stream) &= ~DMA_SxFCR_FEIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Get FIFO Status
+
+Status of FIFO (empty. full or partial filled states) is returned. This has no
+meaning if direct mode is enabled (as the FIFO is not used).
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+@returns u32 FIFO Status @ref dma_fifo_status
+*/
+
+u32 dma_fifo_status(u32 dma, u8 stream)
+{
+ return (DMA_SFCR(dma, stream) & DMA_SxFCR_FS_MASK);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Enable Direct Mode
+
+Direct mode is the default. Data is transferred as soon as a DMA request is
+received. The FIFO is not used. This must not be set when memory to memory
+mode is selected.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+*/
+
+void dma_enable_direct_mode(u32 dma, u8 stream)
+{
+ DMA_SFCR(dma, stream) &= ~DMA_SxFCR_DMDIS;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Enable FIFO Mode
+
+Data is transferred via a FIFO.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+*/
+
+void dma_enable_fifo_mode(u32 dma, u8 stream)
+{
+ DMA_SFCR(dma, stream) |= DMA_SxFCR_DMDIS;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Set FIFO Threshold
+
+This is the filled level at which data is transferred out of the FIFO to the
+destination.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+@param[in] threshold unsigned int8. Threshold setting @ref dma_fifo_thresh
+*/
+
+void dma_set_fifo_threshold(u32 dma, u8 stream, u32 threshold)
+{
+ u32 reg32 = (DMA_SFCR(dma, stream) & ~DMA_SxFCR_FTH_MASK);
+ DMA_SFCR(dma, stream) = (reg32 | threshold);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Enable
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+*/
+
+void dma_enable_stream(u32 dma, u8 stream)
+{
+ DMA_SCR(dma, stream) |= DMA_SxCR_EN;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Disable
+
+@note The DMA stream registers retain their values when the stream is disabled.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+*/
+
+void dma_disable_stream(u32 dma, u8 stream)
+{
+ DMA_SCR(dma, stream) &= ~DMA_SxCR_EN;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Set the Peripheral Address
+
+Set the address of the peripheral register to or from which data is to be transferred.
+Refer to the documentation for the specific peripheral.
+
+@note The DMA stream must be disabled before setting this address. This function
+has no effect if the stream is enabled.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+@param[in] address unsigned int32. Peripheral Address.
+*/
+
+void dma_set_peripheral_address(u32 dma, u8 stream, u32 address)
+{
+ if (!(DMA_SCR(dma, stream) & DMA_SxCR_EN))
+ DMA_SPAR(dma, stream) = (u32 *) address;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Set the Base Memory Address 0
+
+Set the address pointer to the memory location for DMA transfers. The DMA stream
+must normally be disabled before setting this address, however it is possible
+to change this in double buffer mode when the current target is memory area 1
+(see @ref dma_get_target).
+
+This is the default base memory address used in direct mode.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+@param[in] address unsigned int32. Memory Initial Address.
+*/
+
+void dma_set_memory_address(u32 dma, u8 stream, u32 address)
+{
+ u32 reg32 = DMA_SCR(dma, stream);
+ if ( !(reg32 & DMA_SxCR_EN) || ((reg32 & DMA_SxCR_CT) && (reg32 & DMA_SxCR_DBM)) )
+ DMA_SM0AR(dma, stream) = (u32 *) address;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Set the Base Memory Address 1
+
+Set the address pointer to the memory location for DMA transfers. The DMA stream
+must normally be disabled before setting this address, however it is possible
+to change this in double buffer mode when the current target is memory area 0
+(see @ref dma_get_target).
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+@param[in] address unsigned int32. Memory Initial Address.
+*/
+
+void dma_set_memory_address_1(u32 dma, u8 stream, u32 address)
+{
+ u32 reg32 = DMA_SCR(dma, stream);
+ if ( !(reg32 & DMA_SxCR_EN) || (!(reg32 & DMA_SxCR_CT) && (reg32 & DMA_SxCR_DBM)) )
+ DMA_SM1AR(dma, stream) = (u32 *) address;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Stream Set the Transfer Block Size
+
+@note The DMA stream must be disabled before setting this count value. The count
+is not changed if the stream is enabled.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] stream unsigned int8. Stream number: @ref dma_st_number
+@param[in] number unsigned int16. Number of data words to transfer (65535 maximum).
+*/
+
+void dma_set_number_of_data(u32 dma, u8 stream, u16 number)
+{
+ DMA_SNDTR(dma, stream) = number;
+}
+/**@}*/
+
diff --git a/lib/stm32/common/gpio_common_all.c b/lib/stm32/common/gpio_common_all.c
new file mode 100644
index 0000000..d23e415
--- /dev/null
+++ b/lib/stm32/common/gpio_common_all.c
@@ -0,0 +1,139 @@
+/** @addtogroup gpio_file */
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define WEAK __attribute__ ((weak))
+
+#include <libopencm3/stm32/gpio.h>
+
+/**@{*/
+
+/*-----------------------------------------------------------------------------*/
+/** @brief Set a Group of Pins Atomic
+
+Set one or more pins of the given GPIO port to 1 in an atomic operation.
+
+@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
+@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
+ If multiple pins are to be changed, use logical OR '|' to separate them.
+*/
+void gpio_set(u32 gpioport, u16 gpios)
+{
+ GPIO_BSRR(gpioport) = gpios;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief Clear a Group of Pins Atomic
+
+Clear one or more pins of the given GPIO port to 0 in an atomic operation.
+
+@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
+@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
+ If multiple pins are to be changed, use logical OR '|' to separate them.
+*/
+void gpio_clear(u32 gpioport, u16 gpios)
+{
+ GPIO_BSRR(gpioport) = (gpios << 16);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief Read a Group of Pins.
+
+@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
+@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
+ If multiple pins are to be read, use logical OR '|' to separate them.
+@return Unsigned int16 value of the pin values. The bit position of the pin value
+ returned corresponds to the pin number.
+*/
+u16 gpio_get(u32 gpioport, u16 gpios)
+{
+ return gpio_port_read(gpioport) & gpios;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief Toggle a Group of Pins
+
+Toggle one or more pins of the given GPIO port. This is not an atomic operation.
+
+@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
+@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
+ If multiple pins are to be changed, use logical OR '|' to separate them.
+*/
+void gpio_toggle(u32 gpioport, u16 gpios)
+{
+ GPIO_ODR(gpioport) ^= gpios;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief Read from a Port
+
+Read the current value of the given GPIO port. Only the lower 16 bits contain
+valid pin data.
+
+@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
+@return Unsigned int16. The value held in the specified GPIO port.
+*/
+u16 gpio_port_read(u32 gpioport)
+{
+ return (u16)GPIO_IDR(gpioport);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief Write to a Port
+
+Write a value to the given GPIO port.
+
+@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
+@param[in] data Unsigned int16. The value to be written to the GPIO port.
+*/
+void gpio_port_write(u32 gpioport, u16 data)
+{
+ GPIO_ODR(gpioport) = data;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief Lock the Configuration of a Group of Pins
+
+The configuration of one or more pins of the given GPIO port is locked. There is
+no mechanism to unlock these via software. Unlocking occurs at the next reset.
+
+@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
+@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
+ If multiple pins are to be locked, use logical OR '|' to separate them.
+*/
+void gpio_port_config_lock(u32 gpioport, u16 gpios)
+{
+ u32 reg32;
+
+ /* Special "Lock Key Writing Sequence", see datasheet. */
+ GPIO_LCKR(gpioport) = GPIO_LCKK | gpios; /* Set LCKK. */
+ GPIO_LCKR(gpioport) = ~GPIO_LCKK & gpios; /* Clear LCKK. */
+ GPIO_LCKR(gpioport) = GPIO_LCKK | gpios; /* Set LCKK. */
+ reg32 = GPIO_LCKR(gpioport); /* Read LCKK. */
+ reg32 = GPIO_LCKR(gpioport); /* Read LCKK again. */
+
+ /* Tell the compiler the variable is actually used. It will get optimized out anyways. */
+ reg32 = reg32;
+
+ /* If (reg32 & GPIO_LCKK) is true, the lock is now active. */
+}
+
+/**@}*/
+
diff --git a/lib/stm32/common/gpio_common_f24.c b/lib/stm32/common/gpio_common_f24.c
new file mode 100644
index 0000000..5b29693
--- /dev/null
+++ b/lib/stm32/common/gpio_common_f24.c
@@ -0,0 +1,195 @@
+/** @addtogroup gpio_file
+
+@version 1.0.0
+
+@author @htmlonly &copy; @endhtmlonly 2009 Uwe Hermann <uwe@hermann-uwe.de>
+@author @htmlonly &copy; @endhtmlonly 2012 Ken Sarkies <ksarkies@internode.on.net>
+
+@date 18 August 2012
+
+Each I/O port has 16 individually configurable bits. Many I/O pins share GPIO
+functionality with a number of alternate functions and must be configured to the
+alternate function mode if these are to be accessed. A feature is available to
+remap alternative functions to a limited set of alternative pins in the event
+of a clash of requirements.
+
+The data registers associated with each port for input and output are 32 bit with
+the upper 16 bits unused. The output buffer must be written as a 32 bit word, but
+individual bits may be set or reset separately in atomic operations to avoid race
+conditions during interrupts. Bits may also be individually locked to prevent
+accidental configuration changes. Once locked the configuration cannot be changed
+until after the next reset.
+
+Each port bit can be configured as analog or digital input, the latter can be
+floating or pulled up or down. As outputs they can be configured as either
+push-pull or open drain, digital I/O or alternate function, and with maximum
+output speeds of 2MHz, 10MHz, or 50MHz.
+
+On reset all ports are configured as digital floating input.
+
+@section gpio_api_ex Basic GPIO Handling API.
+
+Example 1: Push-pull digital output actions with pullup on ports C2 and C9
+
+@code
+ gpio_mode_setup(GPIOC, GPIO_MODE_OUTPUT,
+ GPIO_PUPD_PULLUP, GPIO2 | GPIO9);
+ gpio_output_options(GPIOC, GPIO_OTYPE_PP,
+ GPIO_OSPEED_25MHZ, GPIO2 | GPIO9);
+ gpio_set(GPIOC, GPIO2 | GPIO9);
+ gpio_clear(GPIOC, GPIO2);
+ gpio_toggle(GPIOC, GPIO2 | GPIO9);
+ gpio_port_write(GPIOC, 0x204);
+@endcode
+
+Example 2: Digital input on port C12 with pullup
+
+@code
+ gpio_mode_setup(GPIOC, GPIO_MODE_INPUT,
+ GPIO_PUPD_PULLUP, GPIO12);
+ reg16 = gpio_port_read(GPIOC);
+@endcode
+
+LGPL License Terms @ref lgpl_license
+*/
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2011 Fergus Noble <fergusnoble@gmail.com>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**@{*/
+
+#include <libopencm3/stm32/common/gpio_common_all.h>
+#include <libopencm3/stm32/gpio.h>
+
+/*-----------------------------------------------------------------------------*/
+/** @brief Set GPIO Pin Mode
+
+Sets the Pin Direction and Analog/Digital Mode, and Output Pin Pullup,
+for a set of GPIO pins on a given GPIO port.
+
+@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
+@param[in] mode Unsigned int8. Pin mode @ref gpio_mode
+@param[in] pull_up_down Unsigned int8. Pin pullup/pulldown configuration @ref gpio_pup
+@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
+ If multiple pins are to be set, use bitwise OR '|' to separate them.
+*/
+void gpio_mode_setup(u32 gpioport, u8 mode, u8 pull_up_down, u16 gpios)
+{
+ u16 i;
+ u32 moder, pupd;
+
+ /*
+ * We want to set the config only for the pins mentioned in gpios,
+ * but keeping the others, so read out the actual config first.
+ */
+ moder = GPIO_MODER(gpioport);
+ pupd = GPIO_PUPDR(gpioport);
+
+ for (i = 0; i < 16; i++) {
+ if (!((1 << i) & gpios))
+ continue;
+
+ moder &= ~GPIO_MODE_MASK(i);
+ moder |= GPIO_MODE(i, mode);
+ pupd &= ~GPIO_PUPD_MASK(i);
+ pupd |= GPIO_PUPD(i, pull_up_down);
+ }
+
+ /* Set mode and pull up/down control registers. */
+ GPIO_MODER(gpioport) = moder;
+ GPIO_PUPDR(gpioport) = pupd;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief Set GPIO Output Options
+
+When the pin is set to output mode, this sets the configuration (analog/digital and
+open drain/push pull) and speed, for a set of GPIO pins on a given GPIO port.
+
+@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
+@param[in] otype Unsigned int8. Pin output type @ref gpio_output_type
+@param[in] speed Unsigned int8. Pin speed @ref gpio_speed
+@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
+ If multiple pins are to be set, use bitwise OR '|' to separate them.
+*/
+void gpio_set_output_options(u32 gpioport, u8 otype, u8 speed, u16 gpios)
+{
+ u16 i;
+ u32 ospeedr;
+
+ if (otype == 0x1)
+ GPIO_OTYPER(gpioport) |= gpios;
+ else
+ GPIO_OTYPER(gpioport) &= ~gpios;
+
+ ospeedr = GPIO_OSPEEDR(gpioport);
+
+ for (i = 0; i < 16; i++) {
+ if (!((1 << i) & gpios))
+ continue;
+ ospeedr &= ~GPIO_OSPEED_MASK(i);
+ ospeedr |= GPIO_OSPEED(i, speed);
+ }
+
+ GPIO_OSPEEDR(gpioport) = ospeedr;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief Set GPIO Alternate Function Selection
+
+Set the alternate function mapping number for each pin. Most pins have alternate
+functions associated with them. When set to AF mode, a pin may be used for one of
+its allocated alternate functions selected by the number given here. To determine
+the number to be used for the desired function refer to the individual datasheet
+for the particular device. A table is given under the Pin Selection chapter.
+
+Note that a number of pins may be set but only with a single AF number. In practice
+this would rarely be useful as each pin is likely to require a different number.
+
+@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
+@param[in] alt_func_num Unsigned int8. Pin alternate function number @ref gpio_af_num
+@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
+ If multiple pins are to be set, use bitwise OR '|' to separate them.
+*/
+void gpio_set_af(u32 gpioport, u8 alt_func_num, u16 gpios)
+{
+ u16 i;
+ u32 afrl, afrh;
+
+ afrl = GPIO_AFRL(gpioport);
+ afrh = GPIO_AFRH(gpioport);
+
+ for (i = 0; i < 8; i++) {
+ if (!((1 << i) & gpios))
+ continue;
+ afrl &= ~GPIO_AFR_MASK(i);
+ afrl |= GPIO_AFR(i, alt_func_num);
+ }
+
+ for (i = 8; i < 16; i++) {
+ if (!((1 << i) & gpios))
+ continue;
+ afrh &= ~GPIO_AFR_MASK(i - 8);
+ afrh |= GPIO_AFR(i - 8, alt_func_num);
+ }
+
+ GPIO_AFRL(gpioport) = afrl;
+ GPIO_AFRH(gpioport) = afrh;
+}
+/**@}*/
+
diff --git a/lib/stm32/i2c.c b/lib/stm32/common/i2c_common_all.c
index e1d3a09..28ae199 100644
--- a/lib/stm32/i2c.c
+++ b/lib/stm32/common/i2c_common_all.c
@@ -1,8 +1,4 @@
-/** @defgroup i2c_file I2C
-
-@ingroup STM32F_files
-
-@brief <b>libopencm3 STM32Fxxx I2C</b>
+/** @addtogroup i2c_file
@version 1.0.0
@@ -43,7 +39,7 @@ LGPL License Terms @ref lgpl_license
*/
#include <libopencm3/stm32/i2c.h>
-#include <libopencm3/stm32/f4/rcc.h>
+#include <libopencm3/stm32/rcc.h>
/**@{*/
@@ -125,6 +121,18 @@ void i2c_send_stop(u32 i2c)
}
/*-----------------------------------------------------------------------------*/
+/** @brief I2C Clear Stop Flag.
+
+Clear the "Send Stop" flag in the I2C config register
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+*/
+void i2c_clear_stop(u32 i2c)
+{
+ I2C_CR1(i2c) &= ~I2C_CR1_STOP;
+}
+
+/*-----------------------------------------------------------------------------*/
/** @brief I2C Set the 7 bit Slave Address for the Peripheral.
This sets an address for Slave mode operation, in 7 bit form.
@@ -269,5 +277,135 @@ void i2c_send_data(u32 i2c, u8 data)
I2C_DR(i2c) = data;
}
-/**@}*/
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Get Data.
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+*/
+uint8_t i2c_get_data(u32 i2c)
+{
+ return I2C_DR(i2c) & 0xff;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Enable Interrupt
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+@param[in] interrupt Unsigned int32. Interrupt to enable.
+*/
+void i2c_enable_interrupt(u32 i2c, u32 interrupt)
+{
+ I2C_CR2(i2c) |= interrupt;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Disable Interrupt
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+@param[in] interrupt Unsigned int32. Interrupt to disable.
+*/
+void i2c_disable_interrupt(u32 i2c, u32 interrupt)
+{
+ I2C_CR2(i2c) &= ~interrupt;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Enable ACK
+
+Enables acking of own 7/10 bit address
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+*/
+void i2c_enable_ack(u32 i2c)
+{
+ I2C_CR1(i2c) |= I2C_CR1_ACK;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Disable ACK
+
+Disables acking of own 7/10 bit address
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+*/
+void i2c_disable_ack(u32 i2c)
+{
+ I2C_CR1(i2c) &= ~I2C_CR1_ACK;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C NACK Next Byte
+
+Causes the I2C controller to NACK the reception of the next byte
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+*/
+void i2c_nack_next(u32 i2c)
+{
+ I2C_CR1(i2c) |= I2C_CR1_POS;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C NACK Next Byte
+
+Causes the I2C controller to NACK the reception of the current byte
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+*/
+void i2c_nack_current(u32 i2c)
+{
+ I2C_CR1(i2c) &= ~I2C_CR1_POS;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Set clock duty cycle
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+@param[in] dutycycle Unsigned int32. I2C duty cycle @ref i2c_duty_cycle.
+*/
+void i2c_set_dutycycle(u32 i2c, u32 dutycycle)
+{
+ if (dutycycle == I2C_CCR_DUTY_DIV2)
+ I2C_CCR(i2c) &= ~I2C_CCR_DUTY;
+ else
+ I2C_CCR(i2c) |= I2C_CCR_DUTY;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Enable DMA
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+*/
+void i2c_enable_dma(u32 i2c)
+{
+ I2C_CR2(i2c) |= I2C_CR2_DMAEN;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Disable DMA
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+*/
+void i2c_disable_dma(u32 i2c)
+{
+ I2C_CR2(i2c) &= ~I2C_CR2_DMAEN;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Set DMA last transfer
+
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+*/
+void i2c_set_dma_last_transfer(u32 i2c)
+{
+ I2C_CR2(i2c) |= I2C_CR2_LAST;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief I2C Clear DMA last transfer
+@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
+*/
+void i2c_clear_dma_last_transfer(u32 i2c)
+{
+ I2C_CR2(i2c) &= ~I2C_CR2_LAST;
+}
+
+/**@}*/
diff --git a/lib/stm32/iwdg.c b/lib/stm32/common/iwdg_common_all.c
index 251bec1..d3d9364 100644
--- a/lib/stm32/iwdg.c
+++ b/lib/stm32/common/iwdg_common_all.c
@@ -1,8 +1,4 @@
-/** @defgroup STM32F_iwdg_file IWDG
-
-@ingroup STM32F_files
-
-@brief <b>libopencm3 STM32F1xx Independent Watchdog Timer</b>
+/** @addtogroup iwdg_file
@version 1.0.0
diff --git a/lib/stm32/common/pwr_common_all.c b/lib/stm32/common/pwr_common_all.c
new file mode 100644
index 0000000..451ed1c
--- /dev/null
+++ b/lib/stm32/common/pwr_common_all.c
@@ -0,0 +1,217 @@
+/** @defgroup STM32F1xx-pwr-file PWR
+
+@ingroup STM32F1xx
+
+@brief <b>libopencm3 STM32F1xx Power Control</b>
+
+@version 1.0.0
+
+@author @htmlonly &copy; @endhtmlonly 2012 Ken Sarkies <ksarkies@internode.on.net>
+
+@date 18 August 2012
+
+This library supports the power control system for the
+STM32F1 series of ARM Cortex Microcontrollers by ST Microelectronics.
+
+LGPL License Terms @ref lgpl_license
+*/
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2012 Ken Sarkies <ksarkies@internode.on.net>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**@{*/
+
+#include <libopencm3/stm32/pwr.h>
+
+/*---------------------------------------------------------------------------*/
+/** @brief Disable Backup Domain Write Protection.
+
+This allows backup domain registers to be changed. These registers are write
+protected after a reset.
+*/
+
+void pwr_disable_backup_domain_write_protect(void)
+{
+ PWR_CR |= PWR_CR_DBP;
+}
+
+/*---------------------------------------------------------------------------*/
+/** @brief Re-enable Backup Domain Write Protection.
+
+This protects backup domain registers from inadvertent change.
+*/
+
+void pwr_enable_backup_domain_write_protect(void)
+{
+ PWR_CR &= ~PWR_CR_DBP;
+}
+
+/*---------------------------------------------------------------------------*/
+/** @brief Enable Power Voltage Detector.
+
+This provides voltage level threshold detection. The result of detection is
+provided in the power voltage detector output flag (see @ref pwr_voltage_high)
+or by setting the EXTI16 interrupt (see datasheet for configuration details).
+
+@param[in] pvd_level u32. Taken from @ref pwr_pls.
+*/
+
+void pwr_enable_power_voltage_detect(u32 pvd_level)
+{
+ PWR_CR &= ~PWR_CR_PLS_MASK;
+ PWR_CR |= (PWR_CR_PVDE | pvd_level);
+}
+
+/*---------------------------------------------------------------------------*/
+/** @brief Disable Power Voltage Detector.
+
+*/
+
+void pwr_disable_power_voltage_detect(void)
+{
+ PWR_CR &= ~PWR_CR_PVDE;
+}
+
+/*---------------------------------------------------------------------------*/
+/** @brief Clear the Standby Flag.
+
+This is set when the processor returns from a standby mode.
+*/
+
+void pwr_clear_standby_flag(void)
+{
+ PWR_CR |= PWR_CR_CSBF;
+}
+
+/*---------------------------------------------------------------------------*/
+/** @brief Clear the Wakeup Flag.
+
+This is set when the processor receives a wakeup signal.
+*/
+
+void pwr_clear_wakeup_flag(void)
+{
+ PWR_CR |= PWR_CR_CWUF;
+}
+
+/*---------------------------------------------------------------------------*/
+/** @brief Set Standby Mode in Deep Sleep.
+
+*/
+
+void pwr_set_standby_mode(void)
+{
+ PWR_CR |= PWR_CR_PDDS;
+}
+
+/*---------------------------------------------------------------------------*/
+/** @brief Set Stop Mode in Deep Sleep.
+
+*/
+
+void pwr_set_stop_mode(void)
+{
+ PWR_CR &= ~PWR_CR_PDDS;
+}
+
+/*---------------------------------------------------------------------------*/
+/** @brief Voltage Regulator On in Stop Mode.
+
+*/
+
+void pwr_voltage_regulator_on_in_stop(void)
+{
+ PWR_CR &= ~PWR_CR_LPDS;
+}
+
+/*---------------------------------------------------------------------------*/
+/** @brief Voltage Regulator Low Power in Stop Mode.
+
+*/
+
+void pwr_voltage_regulator_low_power_in_stop(void)
+{
+ PWR_CR |= PWR_CR_LPDS;
+}
+
+/*---------------------------------------------------------------------------*/
+/** @brief Enable Wakeup Pin.
+
+The wakeup pin is used for waking the processor from standby mode.
+*/
+
+void pwr_enable_wakeup_pin(void)
+{
+ PWR_CSR |= PWR_CSR_EWUP;
+}
+
+/*---------------------------------------------------------------------------*/
+/** @brief Release Wakeup Pin.
+
+The wakeup pin is used for general purpose I/O.
+*/
+
+void pwr_disable_wakeup_pin(void)
+{
+ PWR_CSR &= ~PWR_CSR_EWUP;
+}
+
+/*---------------------------------------------------------------------------*/
+/** @brief Get Voltage Detector Output.
+
+The voltage detector threshold must be set when the power voltage detector is
+enabled, see @ref pwr_enable_power_voltage_detect.
+
+@returns boolean: TRUE if the power voltage is above the preset voltage
+threshold.
+*/
+
+bool pwr_voltage_high(void)
+{
+ return (PWR_CSR & PWR_CSR_PVDO);
+}
+
+/*---------------------------------------------------------------------------*/
+/** @brief Get Standby Flag.
+
+The standby flag is set when the processor returns from a standby state. It is
+cleared by software (see @ref pwr_clear_standby_flag).
+
+@returns boolean: TRUE if the processor was in standby state.
+*/
+
+bool pwr_get_standby_flag(void)
+{
+ return (PWR_CSR & PWR_CSR_SBF);
+}
+
+/*---------------------------------------------------------------------------*/
+/** @brief Get Wakeup Flag.
+
+The wakeup flag is set when a wakeup event has been received. It is
+cleared by software (see @ref pwr_clear_wakeup_flag).
+
+@returns boolean: TRUE if a wakeup event was received.
+*/
+
+bool pwr_get_wakeup_flag(void)
+{
+ return (PWR_CSR & PWR_CSR_WUF);
+}
+/**@}*/
+
diff --git a/lib/stm32/common/rtc_common_bcd.c b/lib/stm32/common/rtc_common_bcd.c
new file mode 100644
index 0000000..c302ea2
--- /dev/null
+++ b/lib/stm32/common/rtc_common_bcd.c
@@ -0,0 +1,78 @@
+/** @addtogroup rtc_file */
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**@{*/
+
+#include <libopencm3/stm32/rtc.h>
+
+/*---------------------------------------------------------------------------*/
+/** @brief Set RTC prescalars.
+
+This sets the RTC synchronous and asynchronous prescalars.
+*/
+
+void rtc_set_prescaler(u32 sync, u32 async) {
+ /*
+ * Even if only one of the two fields needs to be changed,
+ * 2 separate write accesses must be performed to the RTC_PRER register.
+ */
+ RTC_PRER = (sync & RTC_PRER_PREDIV_S_MASK);
+ RTC_PRER |= (async << RTC_PRER_PREDIV_A_SHIFT);
+}
+
+/*---------------------------------------------------------------------------*/
+/** @brief Wait for RTC registers to be synchronised with the APB1 bus
+
+ Time and Date are accessed through shadow registers which must be synchronized
+*/
+
+void rtc_wait_for_synchro(void) {
+ /* Unlock RTC registers */
+ RTC_WPR = 0xca;
+ RTC_WPR = 0x53;
+
+ RTC_ISR &= ~(RTC_ISR_RSF);
+
+ while (!(RTC_ISR & RTC_ISR_RSF)) {
+ ;
+ }
+ /* disable write protection again */
+ RTC_WPR = 0xff;
+}
+
+/*---------------------------------------------------------------------------*/
+/** @brief Unlock write access to the RTC registers
+
+*/
+void rtc_unlock(void) {
+ RTC_WPR = 0xca;
+ RTC_WPR = 0x53;
+}
+
+/*---------------------------------------------------------------------------*/
+/** @brief Lock write access to the RTC registers
+
+*/
+void rtc_lock(void) {
+ RTC_WPR = 0xff;
+}
+
+/**@}*/
diff --git a/lib/stm32/spi.c b/lib/stm32/common/spi_common_all.c
index 90675b3..2e6473d 100644
--- a/lib/stm32/spi.c
+++ b/lib/stm32/common/spi_common_all.c
@@ -1,8 +1,4 @@
-/** @defgroup spi_file SPI
-
-@ingroup STM32F_files
-
-@brief <b>libopencm3 STM32Fxxx SPI</b>
+/** @addtogroup spi_file
@version 1.0.0
@@ -58,15 +54,7 @@ LGPL License Terms @ref lgpl_license
*/
#include <libopencm3/stm32/spi.h>
-#if defined(STM32F1)
-# include <libopencm3/stm32/f1/rcc.h>
-#elif defined(STM32F2)
-# include <libopencm3/stm32/f2/rcc.h>
-#elif defined(STM32F4)
-# include <libopencm3/stm32/f4/rcc.h>
-#else
-# error "stm32 family not defined."
-#endif
+#include <libopencm3/stm32/rcc.h>
/*
* SPI and I2S code.
@@ -103,10 +91,12 @@ void spi_reset(u32 spi_peripheral)
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_SPI2RST);
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_SPI2RST);
break;
+#if defined(STM32F1) || defined(STM32F2) || defined(STM32F3) || defined(STM32F4)
case SPI3:
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_SPI3RST);
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_SPI3RST);
break;
+#endif
}
}
diff --git a/lib/stm32/usart.c b/lib/stm32/common/usart_common_all.c
index 5cf861b..0c3d302 100644
--- a/lib/stm32/usart.c
+++ b/lib/stm32/common/usart_common_all.c
@@ -1,8 +1,4 @@
-/** @defgroup STM32F1xx_usart_file USART
-
-@ingroup STM32F_files
-
-@brief <b>libopencm3 STM32F USART</b>
+/** @addtogroup usart_file
@version 1.0.0
@@ -39,16 +35,7 @@ LGPL License Terms @ref lgpl_license
/**@{*/
#include <libopencm3/stm32/usart.h>
-
-#if defined(STM32F1)
-# include <libopencm3/stm32/f1/rcc.h>
-#elif defined(STM32F2)
-# include <libopencm3/stm32/f2/rcc.h>
-#elif defined(STM32F4)
-# include <libopencm3/stm32/f4/rcc.h>
-#else
-# error "stm32 family not defined."
-#endif
+#include <libopencm3/stm32/rcc.h>
/*-----------------------------------------------------------------------------*/
/** @brief USART Set Baudrate.
@@ -398,6 +385,27 @@ void usart_disable_tx_interrupt(u32 usart)
USART_CR1(usart) &= ~USART_CR1_TXEIE;
}
+/*-----------------------------------------------------------------------------*/
+/** @brief USART Error Interrupt Enable.
+
+@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
+*/
+
+void usart_enable_error_interrupt(u32 usart)
+{
+ USART_CR3(usart) |= USART_CR3_EIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief USART Error Interrupt Disable.
+
+@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
+*/
+
+void usart_disable_error_interrupt(u32 usart)
+{
+ USART_CR3(usart) &= ~USART_CR3_EIE;
+}
/*---------------------------------------------------------------------------*/
/** @brief USART Read a Status Flag.
diff --git a/lib/stm32/f1/desig.c b/lib/stm32/desig.c
index 7ae968e..ea861aa 100644
--- a/lib/stm32/f1/desig.c
+++ b/lib/stm32/desig.c
@@ -17,7 +17,7 @@
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <libopencm3/stm32/f1/desig.h>
+#include <libopencm3/stm32/desig.h>
u16 desig_get_flash_size(void)
{
@@ -35,3 +35,25 @@ void desig_get_unique_id(u32 result[])
result[1] = bits63_32;
result[2] = bits31_16 << 16 | bits15_0;
}
+
+void desig_get_unique_id_as_string(char *string,
+ unsigned int string_len)
+{
+ int i, len;
+ u8 device_id[12];
+ static const char chars[] = "0123456789ABCDEF";
+
+ desig_get_unique_id((u32 *)device_id);
+
+ /* Each byte produces two characters */
+ len = (2 * sizeof(device_id) < string_len) ?
+ 2 * sizeof(device_id) : string_len - 1;
+
+ for (i = 0; i < len; i += 2) {
+ string[i] = chars[(device_id[i / 2] >> 0) & 0x0F];
+ string[i + 1] = chars[(device_id[i / 2] >> 4) & 0x0F];
+ }
+
+ string[len] = '\0';
+}
+
diff --git a/lib/stm32/f4/exti.c b/lib/stm32/exti2.c
index 155c21f..bea2f4d 100644
--- a/lib/stm32/f4/exti.c
+++ b/lib/stm32/exti2.c
@@ -2,6 +2,7 @@
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Mark Butler <mbutler@physics.otago.ac.nz>
+ * Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -15,11 +16,22 @@
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This provides the code for the "next gen" EXTI block provided in F2/F4/L1
+ * devices. (differences only in the source selection)
*/
#include <libopencm3/stm32/exti.h>
-#include <libopencm3/stm32/f4/syscfg.h>
+#include <libopencm3/stm32/syscfg.h>
+#if defined(STM32F2)
+#include <libopencm3/stm32/f2/gpio.h>
+#elif defined(STM32F4)
#include <libopencm3/stm32/f4/gpio.h>
+#elif defined(STM32L1)
+#include <libopencm3/stm32/l1/gpio.h>
+#else
+#error "invalid/unknown stm32 family for this code"
+#endif
void exti_set_trigger(u32 extis, exti_trigger_type trig)
{
@@ -121,12 +133,24 @@ void exti_select_source(u32 exti, u32 gpioport)
case GPIOE:
bits = 0xb;
break;
+#if defined(STM32L1)
+#else
case GPIOF:
bits = 0xa;
break;
case GPIOG:
bits = 0x9;
break;
+#endif
+ case GPIOH:
+ bits = 0x8;
+ break;
+#if defined(STM32L1)
+#else
+ case GPIOI:
+ bits = 0x7;
+ break;
+#endif
}
/* Ensure that only valid EXTI lines are used. */
diff --git a/lib/stm32/f1/Makefile b/lib/stm32/f1/Makefile
index a2f7bf2..ba0d4b8 100644
--- a/lib/stm32/f1/Makefile
+++ b/lib/stm32/f1/Makefile
@@ -24,16 +24,19 @@ PREFIX ?= arm-none-eabi
CC = $(PREFIX)-gcc
AR = $(PREFIX)-ar
CFLAGS = -Os -g -Wall -Wextra -I../../../include -fno-common \
- -mcpu=cortex-m3 -mthumb -Wstrict-prototypes \
+ -mcpu=cortex-m3 -msoft-float -mthumb -Wstrict-prototypes \
-ffunction-sections -fdata-sections -MD -DSTM32F1
# ARFLAGS = rcsv
ARFLAGS = rcs
-OBJS = vector.o rcc.o gpio.o usart.o adc.o spi.o flash.o nvic.o \
- rtc.o i2c.o dma.o systick.o exti.o scb.o ethernet.o \
+OBJS = rcc.o gpio.o adc.o flash.o rtc.o dma.o exti.o ethernet.o \
usb_f103.o usb.o usb_control.o usb_standard.o can.o \
- timer.o usb_f107.o desig.o crc.o assert.o dac.o iwdg.o pwr.o
+ timer.o usb_f107.o desig.o pwr_common_all.o \
+ usb_fx07_common.o \
+ gpio_common_all.o dma_common_f13.o spi_common_all.o \
+ dac_common_all.o usart_common_all.o iwdg_common_all.o \
+ i2c_common_all.o crc_common_all.o
-VPATH += ../../usb:../:../../cm3
+VPATH += ../../usb:../:../../cm3:../common
include ../../Makefile.include
diff --git a/lib/stm32/f1/adc.c b/lib/stm32/f1/adc.c
index 0a05aac..71eb926 100644
--- a/lib/stm32/f1/adc.c
+++ b/lib/stm32/f1/adc.c
@@ -187,7 +187,7 @@ void adc_set_dual_mode(u32 mode)
This flag is set after all channels of a regular or injected group have been
converted.
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
@returns bool. End of conversion flag.
*/
@@ -201,7 +201,7 @@ bool adc_eoc(u32 adc)
This flag is set after all channels of an injected group have been converted.
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
@returns bool. End of conversion flag.
*/
@@ -217,7 +217,7 @@ The result read back is 12 bits, right or left aligned within the first 16 bits.
For ADC1 only, the higher 16 bits will hold the result from ADC2 if
an appropriate dual mode has been set @see adc_set_dual_mode.
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
@returns Unsigned int32 conversion result.
*/
@@ -233,7 +233,7 @@ The result read back from the selected injected result register (one of four) is
12 bits, right or left aligned within the first 16 bits. The result can have a
negative value if the injected channel offset has been set @see adc_set_injected_offset.
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
@param[in] reg Unsigned int8. Register number (1 ... 4).
@returns Unsigned int32 conversion result.
*/
@@ -260,7 +260,7 @@ This value is subtracted from the injected channel results after conversion
is complete, and can result in negative results. A separate value can be specified
for each injected data register.
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
@param[in] reg Unsigned int8. Register number (1 ... 4).
@param[in] offset Unsigned int32.
*/
@@ -290,7 +290,7 @@ The analog watchdog allows the monitoring of an analog signal between two thresh
levels. The thresholds must be preset. Comparison is done before data alignment
takes place, so the thresholds are left-aligned.
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_enable_analog_watchdog_regular(u32 adc)
@@ -301,7 +301,7 @@ void adc_enable_analog_watchdog_regular(u32 adc)
/*-----------------------------------------------------------------------------*/
/** @brief ADC Disable Analog Watchdog for Regular Conversions
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_disable_analog_watchdog_regular(u32 adc)
@@ -316,7 +316,7 @@ The analog watchdog allows the monitoring of an analog signal between two thresh
levels. The thresholds must be preset. Comparison is done before data alignment
takes place, so the thresholds are left-aligned.
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_enable_analog_watchdog_injected(u32 adc)
@@ -327,7 +327,7 @@ void adc_enable_analog_watchdog_injected(u32 adc)
/*-----------------------------------------------------------------------------*/
/** @brief ADC Disable Analog Watchdog for Injected Conversions
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_disable_analog_watchdog_injected(u32 adc)
@@ -346,8 +346,8 @@ of the same length or until the whole group has all been converted. When the
the whole group has been converted, the next trigger will restart conversion
of the subgroup at the beginning of the whole group.
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
-@param[in] length Unsigned int8. Number of channels in the group @ref adc_cr1_discnum
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
+@param[in] length Unsigned int8. Number of channels in the group @ref adc_cr1_discnum.
*/
void adc_enable_discontinuous_mode_regular(u32 adc, u8 length)
@@ -360,7 +360,7 @@ void adc_enable_discontinuous_mode_regular(u32 adc, u8 length)
/*-----------------------------------------------------------------------------*/
/** @brief ADC Disable Discontinuous Mode for Regular Conversions
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_disable_discontinuous_mode_regular(u32 adc)
@@ -375,7 +375,7 @@ In this mode the ADC converts sequentially one channel of the defined group of
injected channels, cycling back to the first channel in the group once the
entire group has been converted.
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_enable_discontinuous_mode_injected(u32 adc)
@@ -386,7 +386,7 @@ void adc_enable_discontinuous_mode_injected(u32 adc)
/*-----------------------------------------------------------------------------*/
/** @brief ADC Disable Discontinuous Mode for Injected Conversions
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_disable_discontinuous_mode_injected(u32 adc)
@@ -413,7 +413,7 @@ void adc_enable_automatic_injected_group_conversion(u32 adc)
/*-----------------------------------------------------------------------------*/
/** @brief ADC Disable Automatic Injected Conversions
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_disable_automatic_injected_group_conversion(u32 adc)
@@ -433,7 +433,7 @@ injected channels. If neither are enabled, the analog watchdog feature will be
disabled.
@ref adc_enable_analog_watchdog_injected, @ref adc_enable_analog_watchdog_regular.
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_enable_analog_watchdog_on_all_channels(u32 adc)
@@ -453,8 +453,8 @@ injected channels. If neither are enabled, the analog watchdog feature will be
disabled. If both are enabled, the same channel number is monitored.
@ref adc_enable_analog_watchdog_injected, @ref adc_enable_analog_watchdog_regular.
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
-@param[in] channel Unsigned int8. ADC channel number @ref adc_watchdog_channel
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
+@param[in] channel Unsigned int8. ADC channel number @ref adc_watchdog_channel.
*/
void adc_enable_analog_watchdog_on_selected_channel(u32 adc, u8 channel)
@@ -475,7 +475,7 @@ In this mode a conversion consists of a scan of the predefined set of channels,
regular and injected, each channel conversion immediately following the
previous one. It can use single, continuous or discontinuous mode.
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_enable_scan_mode(u32 adc)
@@ -497,7 +497,7 @@ void adc_disable_scan_mode(u32 adc)
/*-----------------------------------------------------------------------------*/
/** @brief ADC Enable Injected End-Of-Conversion Interrupt
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_enable_eoc_interrupt_injected(u32 adc)
@@ -508,7 +508,7 @@ void adc_enable_eoc_interrupt_injected(u32 adc)
/*-----------------------------------------------------------------------------*/
/** @brief ADC Disable Injected End-Of-Conversion Interrupt
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_disable_eoc_interrupt_injected(u32 adc)
@@ -519,7 +519,7 @@ void adc_disable_eoc_interrupt_injected(u32 adc)
/*-----------------------------------------------------------------------------*/
/** @brief ADC Enable Analog Watchdog Interrupt
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_enable_awd_interrupt(u32 adc)
@@ -530,7 +530,7 @@ void adc_enable_awd_interrupt(u32 adc)
/*-----------------------------------------------------------------------------*/
/** @brief ADC Disable Analog Watchdog Interrupt
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_disable_awd_interrupt(u32 adc)
@@ -541,7 +541,7 @@ void adc_disable_awd_interrupt(u32 adc)
/*-----------------------------------------------------------------------------*/
/** @brief ADC Enable Regular End-Of-Conversion Interrupt
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_enable_eoc_interrupt(u32 adc)
@@ -552,7 +552,7 @@ void adc_enable_eoc_interrupt(u32 adc)
/*-----------------------------------------------------------------------------*/
/** @brief ADC Disable Regular End-Of-Conversion Interrupt
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_disable_eoc_interrupt(u32 adc)
@@ -566,7 +566,7 @@ void adc_disable_eoc_interrupt(u32 adc)
This enables both the sensor and the reference voltage measurements on channels
16 and 17.
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_enable_temperature_sensor(u32 adc)
@@ -580,7 +580,7 @@ void adc_enable_temperature_sensor(u32 adc)
Disabling this will reduce power consumption from the sensor and the reference
voltage measurements.
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_disable_temperature_sensor(u32 adc)
@@ -599,7 +599,7 @@ Note this is a software trigger and requires triggering to be enabled and the
trigger source to be set appropriately otherwise conversion will not start.
This is not the same as the ADC start conversion operation.
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_start_conversion_regular(u32 adc)
@@ -622,7 +622,7 @@ Note this is a software trigger and requires triggering to be enabled and the
trigger source to be set appropriately otherwise conversion will not start.
This is not the same as the ADC start conversion operation.
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_start_conversion_injected(u32 adc)
@@ -659,9 +659,9 @@ For ADC3
@li Timer 5 CC3 event
@li Software Start
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
@param[in] trigger Unsigned int8. Trigger identifier @ref adc_trigger_regular_12
-for ADC1 and ADC2, or @ref adc_trigger_regular_3 for ADC3
+for ADC1 and ADC2, or @ref adc_trigger_regular_3 for ADC3.
*/
void adc_enable_external_trigger_regular(u32 adc, u32 trigger)
@@ -677,7 +677,7 @@ void adc_enable_external_trigger_regular(u32 adc, u32 trigger)
/*-----------------------------------------------------------------------------*/
/** @brief ADC Disable an External Trigger for Regular Channels
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_disable_external_trigger_regular(u32 adc)
@@ -710,9 +710,9 @@ For ADC3
@li Timer 5 CC4 event
@li Software Start
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
@param[in] trigger Unsigned int8. Trigger identifier @ref adc_trigger_injected_12
-for ADC1 and ADC2, or @ref adc_trigger_injected_3 for ADC3
+for ADC1 and ADC2, or @ref adc_trigger_injected_3 for ADC3.
*/
void adc_enable_external_trigger_injected(u32 adc, u32 trigger)
{
@@ -727,7 +727,7 @@ void adc_enable_external_trigger_injected(u32 adc, u32 trigger)
/*-----------------------------------------------------------------------------*/
/** @brief ADC Disable an External Trigger for Injected Channels
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_disable_external_trigger_injected(u32 adc)
@@ -738,7 +738,7 @@ void adc_disable_external_trigger_injected(u32 adc)
/*-----------------------------------------------------------------------------*/
/** @brief ADC Set the Data as Left Aligned
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_set_left_aligned(u32 adc)
@@ -749,7 +749,7 @@ void adc_set_left_aligned(u32 adc)
/*-----------------------------------------------------------------------------*/
/** @brief ADC Set the Data as Right Aligned
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_set_right_aligned(u32 adc)
@@ -764,7 +764,7 @@ Only available for ADC1 through DMA1 channel1, and ADC3 through DMA2 channel5.
ADC2 will use DMA if it is set as slave in dual mode with ADC1 in DMA transfer
mode.
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_enable_dma(u32 adc)
@@ -776,7 +776,7 @@ void adc_enable_dma(u32 adc)
/*-----------------------------------------------------------------------------*/
/** @brief ADC Disable DMA Transfers
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_disable_dma(u32 adc)
@@ -791,7 +791,7 @@ void adc_disable_dma(u32 adc)
This resets the calibration registers. It is not clear if this is required to be
done before every calibration operation.
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_reset_calibration(u32 adc)
@@ -810,7 +810,7 @@ until this happens and the ADC is ready for use.
The ADC must have been powered down for at least 2 ADC clock cycles, then powered on.
before calibration starts
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_calibration(u32 adc)
@@ -825,7 +825,7 @@ void adc_calibration(u32 adc)
In this mode the ADC starts a new conversion of a single channel or a channel
group immediately following completion of the previous channel group conversion.
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_set_continuous_conversion_mode(u32 adc)
@@ -839,7 +839,7 @@ void adc_set_continuous_conversion_mode(u32 adc)
In this mode the ADC performs a conversion of one channel or a channel group
and stops.
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_set_single_conversion_mode(u32 adc)
@@ -856,7 +856,7 @@ If the ADC is already on this function call will initiate a conversion.
@deprecated to be removed in a later release
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_on(u32 adc)
@@ -869,7 +869,7 @@ void adc_on(u32 adc)
Turn off the ADC to reduce power consumption to a few microamps.
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
*/
void adc_off(u32 adc)
@@ -882,9 +882,9 @@ void adc_off(u32 adc)
The sampling time can be selected in ADC clock cycles from 1.5 to 239.5.
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
-@param[in] channel Unsigned int8. ADC Channel integer 0..18 or from @ref adc_channel
-@param[in] time Unsigned int8. Sampling time selection from @ref adc_sample_rg
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
+@param[in] channel Unsigned int8. ADC Channel integer 0..18 or from @ref adc_channel.
+@param[in] time Unsigned int8. Sampling time selection from @ref adc_sample_rg.
*/
void adc_set_sample_time(u32 adc, u8 channel, u8 time)
@@ -910,8 +910,8 @@ void adc_set_sample_time(u32 adc, u8 channel, u8 time)
The sampling time can be selected in ADC clock cycles from 1.5 to 239.5, same for
all channels.
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
-@param[in] time Unsigned int8. Sampling time selection from @ref adc_sample_rg
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
+@param[in] time Unsigned int8. Sampling time selection from @ref adc_sample_rg.
*/
void adc_set_sample_time_on_all_channels(u32 adc, u8 time)
@@ -931,8 +931,8 @@ void adc_set_sample_time_on_all_channels(u32 adc, u8 time)
/*-----------------------------------------------------------------------------*/
/** @brief ADC Set Analog Watchdog Upper Threshold
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
-@param[in] threshold Unsigned int8. Upper threshold value
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
+@param[in] threshold Unsigned int8. Upper threshold value.
*/
void adc_set_watchdog_high_threshold(u32 adc, u16 threshold)
@@ -947,8 +947,8 @@ void adc_set_watchdog_high_threshold(u32 adc, u16 threshold)
/*-----------------------------------------------------------------------------*/
/** @brief ADC Set Analog Watchdog Lower Threshold
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
-@param[in] threshold Unsigned int8. Lower threshold value
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
+@param[in] threshold Unsigned int8. Lower threshold value.
*/
void adc_set_watchdog_low_threshold(u32 adc, u16 threshold)
@@ -967,7 +967,7 @@ Define a sequence of channels to be converted as a regular group with a length
from 1 to 16 channels. If this is called during conversion, the current conversion
is reset and conversion begins again with the newly defined group.
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
@param[in] length Unsigned int8. Number of channels in the group.
@param[in] channel Unsigned int8[]. Set of channels in sequence, integers 0..18.
*/
@@ -1003,9 +1003,9 @@ Defines a sequence of channels to be converted as an injected group with a lengt
from 1 to 4 channels. If this is called during conversion, the current conversion
is reset and conversion begins again with the newly defined group.
-@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base.
@param[in] length Unsigned int8. Number of channels in the group.
-@param[in] channel Unsigned int8[]. Set of channels in sequence, integers 0..18
+@param[in] channel Unsigned int8[]. Set of channels in sequence, integers 0..18.
*/
void adc_set_injected_sequence(u32 adc, u8 length, u8 channel[])
diff --git a/lib/stm32/f1/crc.c b/lib/stm32/f1/crc.c
new file mode 100644
index 0000000..505fb79
--- /dev/null
+++ b/lib/stm32/f1/crc.c
@@ -0,0 +1,29 @@
+/** @defgroup crc_file CRC
+
+@ingroup STM32F1xx
+
+@brief <b>libopencm3 STM32F1xx CRC</b>
+
+*/
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/crc.h>
+#include <libopencm3/stm32/common/crc_common_all.h>
+
+
diff --git a/lib/stm32/f1/dac.c b/lib/stm32/f1/dac.c
new file mode 100644
index 0000000..90dc029
--- /dev/null
+++ b/lib/stm32/f1/dac.c
@@ -0,0 +1,28 @@
+/** @defgroup dac_file DAC
+
+@ingroup STM32F1xx
+
+@brief <b>libopencm3 STM32F1xx DAC</b>
+
+*/
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/dac.h>
+#include <libopencm3/stm32/common/dac_common_all.h>
+
diff --git a/lib/stm32/f1/dma.c b/lib/stm32/f1/dma.c
index 04cb8a1..f22baef 100644
--- a/lib/stm32/f1/dma.c
+++ b/lib/stm32/f1/dma.c
@@ -1,29 +1,14 @@
-/** @defgroup STM32F1xx-dma-file DMA
+/** @defgroup dma_file DMA
@ingroup STM32F1xx
-@brief <b>libopencm3 STM32F1xx DMA Controller</b>
+@brief <b>libopencm3 STM32F1xx DMA</b>
-@version 1.0.0
-
-@author @htmlonly &copy; @endhtmlonly 2010 Thomas Otto <tommi@viadmin.org>
-
-@date 18 August 2012
-
-This library supports the DMA
-Control System in the STM32F1xx series of ARM Cortex Microcontrollers
-by ST Microelectronics. It can provide for two DMA controllers,
-one with 7 channels and one with 5. Channels are hardware dedicated
-and each is shared with a number of different sources (only one can be
-used at a time, under the responsibility of the programmer).
+*/
-LGPL License Terms @ref lgpl_license
- */
/*
* This file is part of the libopencm3 project.
*
- * Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
- *
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@@ -38,330 +23,6 @@ LGPL License Terms @ref lgpl_license
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
-/**@{*/
-
-#include <libopencm3/stm32/f1/dma.h>
-
-/*-----------------------------------------------------------------------------*/
-/** @brief DMA Channel Reset
-
-The channel is disabled and configuration registers are cleared.
-
-@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
-@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
-*/
-
-void dma_channel_reset(u32 dma, u8 channel)
-{
- /* Disable channel. */
- DMA_CCR(dma, channel) &= ~DMA_CCR_EN;
- /* Reset config bits. */
- DMA_CCR(dma, channel) = 0;
- /* Reset data transfer number. */
- DMA_CNDTR(dma, channel) = 0;
- /* Reset peripheral address. */
- DMA_CPAR(dma, channel) = 0;
- /* Reset memory address. */
- DMA_CMAR(dma, channel) = 0;
- /* Reset interrupt flags. */
- DMA_IFCR(dma) |= DMA_IFCR_CIF(channel);
-}
-
-/*-----------------------------------------------------------------------------*/
-/** @brief DMA Channel Enable Memory to Memory Transfers
-
-Memory to memory transfers do not require a trigger to activate each transfer.
-Transfers begin immediately the channel has been enabled, and proceed without
-intervention.
-
-@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
-@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
-*/
-
-void dma_enable_mem2mem_mode(u32 dma, u8 channel)
-{
- DMA_CCR(dma, channel) |= DMA_CCR_MEM2MEM;
- DMA_CCR(dma, channel) &= ~DMA_CCR_CIRC;
-}
-
-/*-----------------------------------------------------------------------------*/
-/** @brief DMA Channel Set Priority
-
-Channel Priority has four levels: low to very high. This has precedence over the
-hardware priority.
-
-@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
-@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
-@param[in] prio unsigned int32. Priority level @ref dma_ch_pri.
-*/
-
-void dma_set_priority(u32 dma, u8 channel, u32 prio)
-{
- DMA_CCR(dma, channel) &= ~(DMA_CCR_PL_MASK);
- DMA_CCR(dma, channel) |= prio;
-}
-
-/*-----------------------------------------------------------------------------*/
-/** @brief DMA Channel Set Memory Word Width
-
-Set the memory word width 8 bits, 16 bits, or 32 bits. Refer to datasheet for
-alignment information if the source and destination widths do not match.
-
-@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
-@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
-@param[in] mem_size unsigned int32. Memory word width @ref dma_ch_memwidth.
-*/
-
-void dma_set_memory_size(u32 dma, u8 channel, u32 mem_size)
-{
-
- DMA_CCR(dma, channel) &= ~(DMA_CCR_MSIZE_MASK);
- DMA_CCR(dma, channel) |= mem_size;
-}
-
-/*-----------------------------------------------------------------------------*/
-/** @brief DMA Channel Set Peripheral Word Width
-
-Set the peripheral word width 8 bits, 16 bits, or 32 bits. Refer to datasheet for
-alignment information if the source and destination widths do not match, or
-if the peripheral does not support byte or half-word writes.
-
-@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
-@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
-@param[in] peripheral_size unsigned int32. Peripheral word width @ref dma_ch_perwidth.
-*/
-
-void dma_set_peripheral_size(u32 dma, u8 channel, u32 peripheral_size)
-{
- DMA_CCR(dma, channel) &= ~(DMA_CCR_PSIZE_MASK);
- DMA_CCR(dma, channel) |= peripheral_size;
-}
-
-/*-----------------------------------------------------------------------------*/
-/** @brief DMA Channel Enable Memory Increment after Transfer
-
-Following each transfer the current memory address is incremented by
-1, 2 or 4 depending on the data size set in @ref dma_set_memory_size. The
-value held by the base memory address register is unchanged.
-
-@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
-@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
-*/
-
-void dma_enable_memory_increment_mode(u32 dma, u8 channel)
-{
- DMA_CCR(dma, channel) |= DMA_CCR_MINC;
-}
-
-/*-----------------------------------------------------------------------------*/
-/** @brief DMA Channel Disable Memory Increment after Transfer
-
-@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
-@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
-*/
-
-void dma_enable_peripheral_increment_mode(u32 dma, u8 channel)
-{
- DMA_CCR(dma, channel) |= DMA_CCR_PINC;
-}
-
-/*-----------------------------------------------------------------------------*/
-/** @brief DMA Channel Enable Memory Circular Mode
-
-After the number of bytes/words to be transferred has been completed, the
-original transfer block size, memory and peripheral base addresses are
-reloaded and the process repeats.
-
-@note This cannot be used with memory to memory mode, which is explictly
-disabled here.
-
-@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
-@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
-*/
-
-void dma_enable_circular_mode(u32 dma, u8 channel)
-{
- DMA_CCR(dma, channel) |= DMA_CCR_CIRC;
- DMA_CCR(dma, channel) &= ~DMA_CCR_MEM2MEM;
-}
-
-/*-----------------------------------------------------------------------------*/
-/** @brief DMA Channel Enable Transfers from a Peripheral
-
-The data direction is set to read from a peripheral.
-
-@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
-@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
-*/
-
-void dma_set_read_from_peripheral(u32 dma, u8 channel)
-{
- DMA_CCR(dma, channel) &= ~DMA_CCR_DIR;
-}
-
-/*-----------------------------------------------------------------------------*/
-/** @brief DMA Channel Enable Transfers from Memory
-
-The data direction is set to read from memory.
-
-@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
-@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
-*/
-
-void dma_set_read_from_memory(u32 dma, u8 channel)
-{
- DMA_CCR(dma, channel) |= DMA_CCR_DIR;
-}
-
-/*-----------------------------------------------------------------------------*/
-/** @brief DMA Channel Enable Interrupt on Transfer Error
-
-@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
-@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
-*/
-
-void dma_enable_transfer_error_interrupt(u32 dma, u8 channel)
-{
- DMA_CCR(dma, channel) |= DMA_CCR_TEIE;
-}
-
-/*-----------------------------------------------------------------------------*/
-/** @brief DMA Channel Disable Interrupt on Transfer Error
-
-@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
-@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
-*/
-
-void dma_disable_transfer_error_interrupt(u32 dma, u8 channel)
-{
- DMA_CCR(dma, channel) &= ~DMA_CCR_TEIE;
-}
-
-/*-----------------------------------------------------------------------------*/
-/** @brief DMA Channel Enable Interrupt on Transfer Half Complete
-
-@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
-@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
-*/
-
-void dma_enable_half_transfer_interrupt(u32 dma, u8 channel)
-{
- DMA_CCR(dma, channel) |= DMA_CCR_HTIE;
-}
-
-/*-----------------------------------------------------------------------------*/
-/** @brief DMA Channel Disable Interrupt on Transfer Half Complete
-
-@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
-@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
-*/
-
-void dma_disable_half_transfer_interrupt(u32 dma, u8 channel)
-{
- DMA_CCR(dma, channel) &= ~DMA_CCR_HTIE;
-}
-
-/*-----------------------------------------------------------------------------*/
-/** @brief DMA Channel Enable Interrupt on Transfer Complete
-
-@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
-@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
-*/
-
-void dma_enable_transfer_complete_interrupt(u32 dma, u8 channel)
-{
- DMA_CCR(dma, channel) |= DMA_CCR_TCIE;
-}
-
-/*-----------------------------------------------------------------------------*/
-/** @brief DMA Channel Disable Interrupt on Transfer Complete
-
-@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
-@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
-*/
-
-void dma_disable_transfer_complete_interrupt(u32 dma, u8 channel)
-{
- DMA_CCR(dma, channel) &= ~DMA_CCR_TCIE;
-}
-
-/*-----------------------------------------------------------------------------*/
-/** @brief DMA Channel Enable
-
-@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
-@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
-*/
-
-void dma_enable_channel(u32 dma, u8 channel)
-{
- DMA_CCR(dma, channel) |= DMA_CCR_EN;
-}
-
-/*-----------------------------------------------------------------------------*/
-/** @brief DMA Channel Disable
-
-@note The DMA channel registers retain their values when the channel is disabled.
-
-@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
-@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
-*/
-
-void dma_disable_channel(u32 dma, u8 channel)
-{
- DMA_CCR(dma, channel) &= ~DMA_CCR_EN;
-}
-
-/*-----------------------------------------------------------------------------*/
-/** @brief DMA Channel Set the Peripheral Address
-
-Set the address of the peripheral register to or from which data is to be transferred.
-Refer to the documentation for the specific peripheral.
-
-@note The DMA channel must be disabled before setting this address. This function
-has no effect if the channel is enabled.
-
-@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
-@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
-@param[in] address unsigned int32. Peripheral Address.
-*/
-
-void dma_set_peripheral_address(u32 dma, u8 channel, u32 address)
-{
- if (!(DMA_CCR(dma, channel) & DMA_CCR_EN))
- DMA_CPAR(dma, channel) = (u32) address;
-}
-
-/*-----------------------------------------------------------------------------*/
-/** @brief DMA Channel Set the Base Memory Address
-
-@note The DMA channel must be disabled before setting this address. This function
-has no effect if the channel is enabled.
-
-@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
-@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
-@param[in] address unsigned int32. Memory Initial Address.
-*/
-
-void dma_set_memory_address(u32 dma, u8 channel, u32 address)
-{
- if (!(DMA_CCR(dma, channel) & DMA_CCR_EN))
- DMA_CMAR(dma, channel) = (u32) address;
-}
-
-/*-----------------------------------------------------------------------------*/
-/** @brief DMA Channel Set the Transfer Block Size
-
-@note The DMA channel must be disabled before setting this count value. The count
-is not changed if the channel is enabled.
-
-@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
-@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
-@param[in] number unsigned int16. Number of data words to transfer (65535 maximum).
-*/
-
-void dma_set_number_of_data(u32 dma, u8 channel, u16 number)
-{
- DMA_CNDTR(dma, channel) = number;
-}
-/**@}*/
+#include <libopencm3/stm32/dma.h>
+#include <libopencm3/stm32/common/dma_common_f13.h>
diff --git a/lib/stm32/f1/flash.c b/lib/stm32/f1/flash.c
index 232086c..49f182c 100644
--- a/lib/stm32/f1/flash.c
+++ b/lib/stm32/f1/flash.c
@@ -22,22 +22,22 @@
void flash_prefetch_buffer_enable(void)
{
- FLASH_ACR |= FLASH_PRFTBE;
+ FLASH_ACR |= FLASH_ACR_PRFTBE;
}
void flash_prefetch_buffer_disable(void)
{
- FLASH_ACR &= ~FLASH_PRFTBE;
+ FLASH_ACR &= ~FLASH_ACR_PRFTBE;
}
void flash_halfcycle_enable(void)
{
- FLASH_ACR |= FLASH_HLFCYA;
+ FLASH_ACR |= FLASH_ACR_HLFCYA;
}
void flash_halfcycle_disable(void)
{
- FLASH_ACR &= ~FLASH_HLFCYA;
+ FLASH_ACR &= ~FLASH_ACR_HLFCYA;
}
void flash_set_ws(u32 ws)
@@ -53,33 +53,33 @@ void flash_set_ws(u32 ws)
void flash_unlock(void)
{
/* Authorize the FPEC access. */
- FLASH_KEYR = FLASH_KEY1;
- FLASH_KEYR = FLASH_KEY2;
+ FLASH_KEYR = FLASH_KEYR_KEY1;
+ FLASH_KEYR = FLASH_KEYR_KEY2;
}
void flash_lock(void)
{
- FLASH_CR |= FLASH_LOCK;
+ FLASH_CR |= FLASH_CR_LOCK;
}
void flash_clear_pgerr_flag(void)
{
- FLASH_SR |= FLASH_PGERR;
+ FLASH_SR |= FLASH_SR_PGERR;
}
void flash_clear_eop_flag(void)
{
- FLASH_SR |= FLASH_EOP;
+ FLASH_SR |= FLASH_SR_EOP;
}
void flash_clear_wrprterr_flag(void)
{
- FLASH_SR |= FLASH_WRPRTERR;
+ FLASH_SR |= FLASH_SR_WRPRTERR;
}
void flash_clear_bsy_flag(void)
{
- FLASH_SR &= ~FLASH_BSY;
+ FLASH_SR &= ~FLASH_SR_BSY;
}
void flash_clear_status_flags(void)
@@ -92,13 +92,14 @@ void flash_clear_status_flags(void)
void flash_unlock_option_bytes(void)
{
- FLASH_OPTKEYR = FLASH_KEY1;
- FLASH_OPTKEYR = FLASH_KEY2;
+ /* F1 uses same keys for flash and option */
+ FLASH_OPTKEYR = FLASH_KEYR_KEY1;
+ FLASH_OPTKEYR = FLASH_KEYR_KEY2;
}
void flash_wait_for_last_operation(void)
{
- while ((FLASH_SR & FLASH_BSY) == FLASH_BSY)
+ while ((FLASH_SR & FLASH_SR_BSY) == FLASH_SR_BSY)
;
}
@@ -108,7 +109,7 @@ void flash_program_word(u32 address, u32 data)
flash_wait_for_last_operation();
/* Enable writes to flash. */
- FLASH_CR |= FLASH_PG;
+ FLASH_CR |= FLASH_CR_PG;
/* Program the first half of the word. */
(*(volatile u16 *)address) = (u16)data;
@@ -123,67 +124,67 @@ void flash_program_word(u32 address, u32 data)
flash_wait_for_last_operation();
/* Disable writes to flash. */
- FLASH_CR &= ~FLASH_PG;
+ FLASH_CR &= ~FLASH_CR_PG;
}
void flash_program_half_word(u32 address, u16 data)
{
flash_wait_for_last_operation();
- FLASH_CR |= FLASH_PG;
+ FLASH_CR |= FLASH_CR_PG;
(*(volatile u16 *)address) = data;
flash_wait_for_last_operation();
- FLASH_CR &= ~FLASH_PG; /* Disable the PG bit. */
+ FLASH_CR &= ~FLASH_CR_PG; /* Disable the PG bit. */
}
void flash_erase_page(u32 page_address)
{
flash_wait_for_last_operation();
- FLASH_CR |= FLASH_PER;
+ FLASH_CR |= FLASH_CR_PER;
FLASH_AR = page_address;
- FLASH_CR |= FLASH_STRT;
+ FLASH_CR |= FLASH_CR_STRT;
flash_wait_for_last_operation();
- FLASH_CR &= ~FLASH_PER;
+ FLASH_CR &= ~FLASH_CR_PER;
}
void flash_erase_all_pages(void)
{
flash_wait_for_last_operation();
- FLASH_CR |= FLASH_MER; /* Enable mass erase. */
- FLASH_CR |= FLASH_STRT; /* Trigger the erase. */
+ FLASH_CR |= FLASH_CR_MER; /* Enable mass erase. */
+ FLASH_CR |= FLASH_CR_STRT; /* Trigger the erase. */
flash_wait_for_last_operation();
- FLASH_CR &= ~FLASH_MER; /* Disable mass erase. */
+ FLASH_CR &= ~FLASH_CR_MER; /* Disable mass erase. */
}
void flash_erase_option_bytes(void)
{
flash_wait_for_last_operation();
- if ((FLASH_CR & FLASH_OPTWRE) == 0)
+ if ((FLASH_CR & FLASH_CR_OPTWRE) == 0)
flash_unlock_option_bytes();
- FLASH_CR |= FLASH_OPTER; /* Enable option byte erase. */
- FLASH_CR |= FLASH_STRT;
+ FLASH_CR |= FLASH_CR_OPTER; /* Enable option byte erase. */
+ FLASH_CR |= FLASH_CR_STRT;
flash_wait_for_last_operation();
- FLASH_CR &= ~FLASH_OPTER; /* Disable option byte erase. */
+ FLASH_CR &= ~FLASH_CR_OPTER; /* Disable option byte erase. */
}
void flash_program_option_bytes(u32 address, u16 data)
{
flash_wait_for_last_operation();
- if ((FLASH_CR & FLASH_OPTWRE) == 0)
+ if ((FLASH_CR & FLASH_CR_OPTWRE) == 0)
flash_unlock_option_bytes();
- FLASH_CR |= FLASH_OPTPG; /* Enable option byte programming. */
+ FLASH_CR |= FLASH_CR_OPTPG; /* Enable option byte programming. */
(*(volatile u16 *)address) = data;
flash_wait_for_last_operation();
- FLASH_CR &= ~FLASH_OPTPG; /* Disable option byte programming. */
+ FLASH_CR &= ~FLASH_CR_OPTPG; /* Disable option byte programming. */
}
diff --git a/lib/stm32/f1/gpio.c b/lib/stm32/f1/gpio.c
index 0602012..2b33cad 100644
--- a/lib/stm32/f1/gpio.c
+++ b/lib/stm32/f1/gpio.c
@@ -1,4 +1,4 @@
-/** @defgroup STM32F1xx_gpio_file GPIO
+/** @defgroup gpio_file GPIO
@ingroup STM32F1xx
@@ -11,9 +11,6 @@
@date 18 August 2012
-This library supports the General Purpose I/O System in the STM32F1xx series
-of ARM Cortex Microcontrollers by ST Microelectronics.
-
Each I/O port has 16 individually configurable bits. Many I/O pins share GPIO
functionality with a number of alternate functions and must be configured to the
alternate function mode if these are to be accessed. A feature is available to
@@ -55,7 +52,7 @@ Example 1: Digital input on port C12
@endcode
LGPL License Terms @ref lgpl_license
- */
+*/
/*
* This file is part of the libopencm3 project.
*
@@ -75,25 +72,10 @@ LGPL License Terms @ref lgpl_license
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
-/*
- * Basic GPIO handling API.
- *
- * Examples:
- * gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ,
- * GPIO_CNF_OUTPUT_PUSHPULL, GPIO12);
- * gpio_set(GPIOB, GPIO4);
- * gpio_clear(GPIOG, GPIO2 | GPIO9);
- * gpio_get(GPIOC, GPIO1);
- * gpio_toggle(GPIOA, GPIO7 | GPIO8);
- * reg16 = gpio_port_read(GPIOD);
- * gpio_port_write(GPIOF, 0xc8fe);
- *
- * TODO:
- * - GPIO remapping support
- */
-/**@{*/
+#include <libopencm3/stm32/gpio.h>
+#include <libopencm3/stm32/common/gpio_common_all.h>
-#include <libopencm3/stm32/f1/gpio.h>
+/**@{*/
/*-----------------------------------------------------------------------------*/
/** @brief Set GPIO Pin Mode
@@ -146,116 +128,6 @@ void gpio_set_mode(u32 gpioport, u8 mode, u8 cnf, u16 gpios)
}
/*-----------------------------------------------------------------------------*/
-/** @brief Set a Group of Pins Atomic
-
-Set one or more pins of the given GPIO port to 1 in an atomic operation.
-
-@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
-@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
- If multiple pins are to be changed, use logical OR '|' to separate them.
-*/
-void gpio_set(u32 gpioport, u16 gpios)
-{
- GPIO_BSRR(gpioport) = gpios;
-}
-
-/*-----------------------------------------------------------------------------*/
-/** @brief Clear a Group of Pins Atomic
-
-Clear one or more pins of the given GPIO port to 0 in an atomic operation.
-
-@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
-@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
- If multiple pins are to be changed, use logical OR '|' to separate them.
-*/
-void gpio_clear(u32 gpioport, u16 gpios)
-{
- GPIO_BRR(gpioport) = gpios;
-}
-
-/*-----------------------------------------------------------------------------*/
-/** @brief Read a Group of Pins.
-
-@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
-@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
- If multiple pins are to be read, use logical OR '|' to separate them.
-@return Unsigned int16 value of the pin values. The bit position of the pin value
- returned corresponds to the pin number.
-*/
-u16 gpio_get(u32 gpioport, u16 gpios)
-{
- return gpio_port_read(gpioport) & gpios;
-}
-
-/*-----------------------------------------------------------------------------*/
-/** @brief Toggle a Group of Pins
-
-Toggle one or more pins of the given GPIO port. This is not an atomic operation.
-
-@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
-@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
- If multiple pins are to be changed, use logical OR '|' to separate them.
-*/
-void gpio_toggle(u32 gpioport, u16 gpios)
-{
- GPIO_ODR(gpioport) ^= gpios;
-}
-
-/*-----------------------------------------------------------------------------*/
-/** @brief Read from a Port
-
-Read the current value of the given GPIO port. Only the lower 16 bits contain
-valid pin data.
-
-@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
-@return Unsigned int16. The value held in the specified GPIO port.
-*/
-u16 gpio_port_read(u32 gpioport)
-{
- return (u16)GPIO_IDR(gpioport);
-}
-
-/*-----------------------------------------------------------------------------*/
-/** @brief Write to a Port
-
-Write a value to the given GPIO port.
-
-@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
-@param[in] data Unsigned int16. The value to be written to the GPIO port.
-*/
-void gpio_port_write(u32 gpioport, u16 data)
-{
- GPIO_ODR(gpioport) = data;
-}
-
-/*-----------------------------------------------------------------------------*/
-/** @brief Lock the Configuration of a Group of Pins
-
-The configuration of one or more pins of the given GPIO port is locked. There is
-no mechanism to unlock these via software. Unlocking occurs at the next reset.
-
-@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
-@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
- If multiple pins are to be locked, use logical OR '|' to separate them.
-*/
-void gpio_port_config_lock(u32 gpioport, u16 gpios)
-{
- u32 reg32;
-
- /* Special "Lock Key Writing Sequence", see datasheet. */
- GPIO_LCKR(gpioport) = GPIO_LCKK | gpios; /* Set LCKK. */
- GPIO_LCKR(gpioport) = ~GPIO_LCKK & gpios; /* Clear LCKK. */
- GPIO_LCKR(gpioport) = GPIO_LCKK | gpios; /* Set LCKK. */
- reg32 = GPIO_LCKR(gpioport); /* Read LCKK. */
- reg32 = GPIO_LCKR(gpioport); /* Read LCKK again. */
-
- /* Tell the compiler the variable is actually used. It will get optimized out anyways. */
- reg32 = reg32;
-
- /* If (reg32 & GPIO_LCKK) is true, the lock is now active. */
-}
-
-/*-----------------------------------------------------------------------------*/
/** @brief Map the EVENTOUT signal
Enable the EVENTOUT signal and select the port and pin to be used.
@@ -292,7 +164,7 @@ value cannot be ascertained from the hardware.
*/
void gpio_primary_remap(u8 swjdisable, u32 maps)
{
- AFIO_MAPR = swjdisable | (maps & 0x1FFFFF);
+ AFIO_MAPR |= swjdisable | (maps & 0x1FFFFF);
}
/*-----------------------------------------------------------------------------*/
@@ -310,7 +182,7 @@ The AFIO remapping feature is used only with the STM32F10x series.
*/
void gpio_secondary_remap(u32 maps)
{
- AFIO_MAPR2 = maps;
+ AFIO_MAPR2 |= maps;
}
/**@}*/
diff --git a/lib/stm32/f1/i2c.c b/lib/stm32/f1/i2c.c
new file mode 100644
index 0000000..2d86bf3
--- /dev/null
+++ b/lib/stm32/f1/i2c.c
@@ -0,0 +1,28 @@
+/** @defgroup i2c_file I2C
+
+@ingroup STM32F1xx
+
+@brief <b>libopencm3 STM32F1xx I2C</b>
+
+*/
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/i2c.h>
+#include <libopencm3/stm32/common/i2c_common_all.h>
+
diff --git a/lib/stm32/f1/iwdg.c b/lib/stm32/f1/iwdg.c
new file mode 100644
index 0000000..85cf18c
--- /dev/null
+++ b/lib/stm32/f1/iwdg.c
@@ -0,0 +1,28 @@
+/** @defgroup iwdg_file IWDG
+
+@ingroup STM32F1xx
+
+@brief <b>libopencm3 STM32F1xx Independent Watchdog Timer</b>
+
+*/
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/iwdg.h>
+#include <libopencm3/stm32/common/iwdg_common_all.h>
+
diff --git a/lib/stm32/f1/rcc.c b/lib/stm32/f1/rcc.c
index ab3350b..707c931 100644
--- a/lib/stm32/f1/rcc.c
+++ b/lib/stm32/f1/rcc.c
@@ -71,6 +71,12 @@ void rcc_osc_ready_int_clear(osc_t osc)
case PLL:
RCC_CIR |= RCC_CIR_PLLRDYC;
break;
+ case PLL2:
+ RCC_CIR |= RCC_CIR_PLL2RDYC;
+ break;
+ case PLL3:
+ RCC_CIR |= RCC_CIR_PLL3RDYC;
+ break;
case HSE:
RCC_CIR |= RCC_CIR_HSERDYC;
break;
@@ -98,6 +104,12 @@ void rcc_osc_ready_int_enable(osc_t osc)
case PLL:
RCC_CIR |= RCC_CIR_PLLRDYIE;
break;
+ case PLL2:
+ RCC_CIR |= RCC_CIR_PLL2RDYIE;
+ break;
+ case PLL3:
+ RCC_CIR |= RCC_CIR_PLL3RDYIE;
+ break;
case HSE:
RCC_CIR |= RCC_CIR_HSERDYIE;
break;
@@ -125,6 +137,12 @@ void rcc_osc_ready_int_disable(osc_t osc)
case PLL:
RCC_CIR &= ~RCC_CIR_PLLRDYIE;
break;
+ case PLL2:
+ RCC_CIR &= ~RCC_CIR_PLL2RDYIE;
+ break;
+ case PLL3:
+ RCC_CIR &= ~RCC_CIR_PLL3RDYIE;
+ break;
case HSE:
RCC_CIR &= ~RCC_CIR_HSERDYIE;
break;
@@ -153,6 +171,12 @@ int rcc_osc_ready_int_flag(osc_t osc)
case PLL:
return ((RCC_CIR & RCC_CIR_PLLRDYF) != 0);
break;
+ case PLL2:
+ return ((RCC_CIR & RCC_CIR_PLL2RDYF) != 0);
+ break;
+ case PLL3:
+ return ((RCC_CIR & RCC_CIR_PLL3RDYF) != 0);
+ break;
case HSE:
return ((RCC_CIR & RCC_CIR_HSERDYF) != 0);
break;
@@ -203,6 +227,12 @@ void rcc_wait_for_osc_ready(osc_t osc)
case PLL:
while ((RCC_CR & RCC_CR_PLLRDY) == 0);
break;
+ case PLL2:
+ while ((RCC_CR & RCC_CR_PLL2RDY) == 0);
+ break;
+ case PLL3:
+ while ((RCC_CR & RCC_CR_PLL3RDY) == 0);
+ break;
case HSE:
while ((RCC_CR & RCC_CR_HSERDY) == 0);
break;
@@ -238,6 +268,12 @@ void rcc_osc_on(osc_t osc)
case PLL:
RCC_CR |= RCC_CR_PLLON;
break;
+ case PLL2:
+ RCC_CR |= RCC_CR_PLL2ON;
+ break;
+ case PLL3:
+ RCC_CR |= RCC_CR_PLL3ON;
+ break;
case HSE:
RCC_CR |= RCC_CR_HSEON;
break;
@@ -273,6 +309,12 @@ void rcc_osc_off(osc_t osc)
case PLL:
RCC_CR &= ~RCC_CR_PLLON;
break;
+ case PLL2:
+ RCC_CR &= ~RCC_CR_PLL2ON;
+ break;
+ case PLL3:
+ RCC_CR &= ~RCC_CR_PLL3ON;
+ break;
case HSE:
RCC_CR &= ~RCC_CR_HSEON;
break;
@@ -331,6 +373,8 @@ void rcc_osc_bypass_enable(osc_t osc)
RCC_BDCR |= RCC_BDCR_LSEBYP;
break;
case PLL:
+ case PLL2:
+ case PLL3:
case HSI:
case LSI:
/* Do nothing, only HSE/LSE allowed here. */
@@ -361,6 +405,8 @@ void rcc_osc_bypass_disable(osc_t osc)
RCC_BDCR &= ~RCC_BDCR_LSEBYP;
break;
case PLL:
+ case PLL2:
+ case PLL3:
case HSI:
case LSI:
/* Do nothing, only HSE/LSE allowed here. */
@@ -485,6 +531,40 @@ void rcc_set_pll_multiplication_factor(u32 mul)
}
/*-----------------------------------------------------------------------------*/
+/** @brief RCC Set the PLL2 Multiplication Factor.
+
+@note This only has effect when the PLL is disabled.
+
+@param[in] mul Unsigned int32. PLL multiplication factor @ref rcc_cfgr_pmf
+*/
+
+void rcc_set_pll2_multiplication_factor(u32 mul)
+{
+ u32 reg32;
+
+ reg32 = RCC_CFGR2;
+ reg32 &= ~((1 << 11) | (1 << 10) | (1 << 9) | (1 << 8));
+ RCC_CFGR2 = (reg32 | (mul << 8));
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief RCC Set the PLL3 Multiplication Factor.
+
+@note This only has effect when the PLL is disabled.
+
+@param[in] mul Unsigned int32. PLL multiplication factor @ref rcc_cfgr_pmf
+*/
+
+void rcc_set_pll3_multiplication_factor(u32 mul)
+{
+ u32 reg32;
+
+ reg32 = RCC_CFGR2;
+ reg32 &= ~((1 << 15) | (1 << 14) | (1 << 13) | (1 << 12));
+ RCC_CFGR2 = (reg32 | (mul << 12));
+}
+
+/*-----------------------------------------------------------------------------*/
/** @brief RCC Set the PLL Clock Source.
@note This only has effect when the PLL is disabled.
@@ -602,6 +682,36 @@ void rcc_set_usbpre(u32 usbpre)
RCC_CFGR = (reg32 | (usbpre << 22));
}
+void rcc_set_prediv1(u32 prediv)
+{
+ u32 reg32;
+ reg32 = RCC_CFGR2;
+ reg32 &= ~(1 << 3) | (1 << 2) | (1 << 1) | (1 << 0);
+ RCC_CFGR2 |= (reg32 | prediv);
+}
+
+void rcc_set_prediv2(u32 prediv)
+{
+ u32 reg32;
+ reg32 = RCC_CFGR2;
+ reg32 &= ~(1 << 7) | (1 << 6) | (1 << 5) | (1 << 4);
+ RCC_CFGR2 |= (reg32 | (prediv << 4));
+}
+
+void rcc_set_prediv1_source(u32 rccsrc)
+{
+ RCC_CFGR2 &= ~(1 << 16);
+ RCC_CFGR2 |= (rccsrc << 16);
+}
+
+void rcc_set_mco(u32 mcosrc)
+{
+ u32 reg32;
+ reg32 = RCC_CFGR;
+ reg32 &= ~((1 << 27) | (1 << 26) | (1 << 25) | (1 << 24));
+ RCC_CFGR |= (reg32 | (mcosrc << 24));
+}
+
/*-----------------------------------------------------------------------------*/
/** @brief RCC Get the System Clock Source.
@@ -651,7 +761,7 @@ void rcc_clock_setup_in_hsi_out_64mhz(void)
* 1WS from 24-48MHz
* 2WS from 48-72MHz
*/
- flash_set_ws(FLASH_LATENCY_2WS);
+ flash_set_ws(FLASH_ACR_LATENCY_2WS);
/*
* Set the PLL multiplication factor to 16.
@@ -704,7 +814,7 @@ void rcc_clock_setup_in_hsi_out_48mhz(void)
* 1WS from 24-48MHz
* 2WS from 48-72MHz
*/
- flash_set_ws(FLASH_LATENCY_1WS);
+ flash_set_ws(FLASH_ACR_LATENCY_1WS);
/*
* Set the PLL multiplication factor to 12.
@@ -755,7 +865,7 @@ void rcc_clock_setup_in_hsi_out_24mhz(void) {
* 1WS from 24-48MHz
* 2WS from 48-72MHz
*/
- flash_set_ws(FLASH_LATENCY_0WS);
+ flash_set_ws(FLASH_ACR_LATENCY_0WS);
/*
* Set the PLL multiplication factor to 6.
@@ -812,7 +922,7 @@ void rcc_clock_setup_in_hse_8mhz_out_24mhz(void)
* 1WS from 24-48MHz
* 2WS from 48-72MHz
*/
- flash_set_ws(FLASH_LATENCY_0WS);
+ flash_set_ws(FLASH_ACR_LATENCY_0WS);
/*
* Set the PLL multiplication factor to 3.
@@ -875,7 +985,7 @@ void rcc_clock_setup_in_hse_8mhz_out_72mhz(void)
* 1WS from 24-48MHz
* 2WS from 48-72MHz
*/
- flash_set_ws(FLASH_LATENCY_2WS);
+ flash_set_ws(FLASH_ACR_LATENCY_2WS);
/*
* Set the PLL multiplication factor to 9.
@@ -938,7 +1048,7 @@ void rcc_clock_setup_in_hse_12mhz_out_72mhz(void)
* 1WS from 24-48MHz
* 2WS from 48-72MHz
*/
- flash_set_ws(FLASH_LATENCY_2WS);
+ flash_set_ws(FLASH_ACR_LATENCY_2WS);
/*
* Set the PLL multiplication factor to 9.
@@ -1001,7 +1111,7 @@ void rcc_clock_setup_in_hse_16mhz_out_72mhz(void)
* 1WS from 24-48MHz
* 2WS from 48-72MHz
*/
- flash_set_ws(FLASH_LATENCY_2WS);
+ flash_set_ws(FLASH_ACR_LATENCY_2WS);
/*
* Set the PLL multiplication factor to 9.
@@ -1031,6 +1141,63 @@ void rcc_clock_setup_in_hse_16mhz_out_72mhz(void)
}
/*-----------------------------------------------------------------------------*/
+/** @brief RCC Set System Clock PLL at 72MHz from HSE at 25MHz
+
+*/
+
+void rcc_clock_setup_in_hse_25mhz_out_72mhz(void)
+{
+ /* Enable external high-speed oscillator 25MHz. */
+ rcc_osc_on(HSE);
+ rcc_wait_for_osc_ready(HSE);
+ rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSECLK);
+
+ /*
+ * Sysclk runs with 72MHz -> 2 waitstates.
+ * 0WS from 0-24MHz
+ * 1WS from 24-48MHz
+ * 2WS from 48-72MHz
+ */
+ flash_set_ws(FLASH_ACR_LATENCY_2WS);
+
+ /*
+ * Set prescalers for AHB, ADC, ABP1, ABP2.
+ * Do this before touching the PLL (TODO: why?).
+ */
+ rcc_set_hpre(RCC_CFGR_HPRE_SYSCLK_NODIV); /* Set. 72MHz Max. 72MHz */
+ rcc_set_adcpre(RCC_CFGR_ADCPRE_PCLK2_DIV6); /* Set. 12MHz Max. 14MHz */
+ rcc_set_ppre1(RCC_CFGR_PPRE1_HCLK_DIV2); /* Set. 36MHz Max. 36MHz */
+ rcc_set_ppre2(RCC_CFGR_PPRE2_HCLK_NODIV); /* Set. 72MHz Max. 72MHz */
+
+ /* Set pll2 prediv and multiplier */
+ rcc_set_prediv2(RCC_CFGR2_PREDIV2_DIV5);
+ rcc_set_pll2_multiplication_factor(RCC_CFGR2_PLL2MUL_PLL2_CLK_MUL8);
+
+ /* Enable PLL2 oscillator and wait for it to stabilize */
+ rcc_osc_on(PLL2);
+ rcc_wait_for_osc_ready(PLL2);
+
+ /* Set pll1 prediv/multiplier, prediv1 src, and usb predivider */
+ rcc_set_pllxtpre(RCC_CFGR_PLLXTPRE_HSE_CLK);
+ rcc_set_prediv1_source(RCC_CFGR2_PREDIV1SRC_PLL2_CLK);
+ rcc_set_prediv1(RCC_CFGR2_PREDIV_DIV5);
+ rcc_set_pll_multiplication_factor(RCC_CFGR_PLLMUL_PLL_CLK_MUL9);
+ rcc_set_pll_source(RCC_CFGR_PLLSRC_PREDIV1_CLK);
+ rcc_set_usbpre(RCC_CFGR_USBPRE_PLL_VCO_CLK_DIV3);
+
+ /* enable PLL1 and wait for it to stabilize */
+ rcc_osc_on(PLL);
+ rcc_wait_for_osc_ready(PLL);
+
+ /* Select PLL as SYSCLK source. */
+ rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_PLLCLK);
+
+ /* Set the peripheral clock frequencies used */
+ rcc_ppre1_frequency = 36000000;
+ rcc_ppre2_frequency = 72000000;
+}
+
+/*-----------------------------------------------------------------------------*/
/** @brief RCC Reset the backup domain
The backup domain register is reset to disable all controls.
diff --git a/lib/stm32/f1/rtc.c b/lib/stm32/f1/rtc.c
index 08a4953..cfc5f5b 100644
--- a/lib/stm32/f1/rtc.c
+++ b/lib/stm32/f1/rtc.c
@@ -67,6 +67,8 @@ void rtc_awake_from_off(osc_t clock_source)
RCC_BDCR |= (1 << 9) | (1 << 8);
break;
case PLL:
+ case PLL2:
+ case PLL3:
case HSI:
/* Unusable clock source, here to prevent warnings. */
/* Turn off clock sources to RTC. */
diff --git a/lib/stm32/f1/spi.c b/lib/stm32/f1/spi.c
new file mode 100644
index 0000000..3be5c23
--- /dev/null
+++ b/lib/stm32/f1/spi.c
@@ -0,0 +1,28 @@
+/** @defgroup spi_file SPI
+
+@ingroup STM32F1xx
+
+@brief <b>libopencm3 STM32F1xx SPI</b>
+
+*/
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/spi.h>
+#include <libopencm3/stm32/common/spi_common_all.h>
+
diff --git a/lib/stm32/f1/usart.c b/lib/stm32/f1/usart.c
new file mode 100644
index 0000000..ecf2b06
--- /dev/null
+++ b/lib/stm32/f1/usart.c
@@ -0,0 +1,28 @@
+/** @defgroup usart_file USART
+
+@ingroup STM32F1xx
+
+@brief <b>libopencm3 STM32F1xx USART</b>
+
+*/
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/usart.h>
+#include <libopencm3/stm32/common/usart_common_all.h>
+
diff --git a/lib/stm32/f1/vector.c b/lib/stm32/f1/vector.c
deleted file mode 100644
index f496ae4..0000000
--- a/lib/stm32/f1/vector.c
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * This file is part of the libopencm3 project.
- *
- * Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
- *
- * This library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define WEAK __attribute__ ((weak))
-
-/* Symbols exported by the linker script(s): */
-extern unsigned _data_loadaddr, _data, _edata, _ebss, _stack;
-
-void main(void);
-void reset_handler(void);
-void blocking_handler(void);
-void null_handler(void);
-
-void WEAK nmi_handler(void);
-void WEAK hard_fault_handler(void);
-void WEAK mem_manage_handler(void);
-void WEAK bus_fault_handler(void);
-void WEAK usage_fault_handler(void);
-void WEAK sv_call_handler(void);
-void WEAK debug_monitor_handler(void);
-void WEAK pend_sv_handler(void);
-void WEAK sys_tick_handler(void);
-void WEAK wwdg_isr(void);
-void WEAK pvd_isr(void);
-void WEAK tamper_isr(void);
-void WEAK rtc_isr(void);
-void WEAK flash_isr(void);
-void WEAK rcc_isr(void);
-void WEAK exti0_isr(void);
-void WEAK exti1_isr(void);
-void WEAK exti2_isr(void);
-void WEAK exti3_isr(void);
-void WEAK exti4_isr(void);
-void WEAK dma1_channel1_isr(void);
-void WEAK dma1_channel2_isr(void);
-void WEAK dma1_channel3_isr(void);
-void WEAK dma1_channel4_isr(void);
-void WEAK dma1_channel5_isr(void);
-void WEAK dma1_channel6_isr(void);
-void WEAK dma1_channel7_isr(void);
-void WEAK adc1_2_isr(void);
-void WEAK usb_hp_can_tx_isr(void);
-void WEAK usb_lp_can_rx0_isr(void);
-void WEAK can_rx1_isr(void);
-void WEAK can_sce_isr(void);
-void WEAK exti9_5_isr(void);
-void WEAK tim1_brk_isr(void);
-void WEAK tim1_up_isr(void);
-void WEAK tim1_trg_com_isr(void);
-void WEAK tim1_cc_isr(void);
-void WEAK tim2_isr(void);
-void WEAK tim3_isr(void);
-void WEAK tim4_isr(void);
-void WEAK i2c1_ev_isr(void);
-void WEAK i2c1_er_isr(void);
-void WEAK i2c2_ev_isr(void);
-void WEAK i2c2_er_isr(void);
-void WEAK spi1_isr(void);
-void WEAK spi2_isr(void);
-void WEAK usart1_isr(void);
-void WEAK usart2_isr(void);
-void WEAK usart3_isr(void);
-void WEAK exti15_10_isr(void);
-void WEAK rtc_alarm_isr(void);
-void WEAK usb_wakeup_isr(void);
-void WEAK tim8_brk_isr(void);
-void WEAK tim8_up_isr(void);
-void WEAK tim8_trg_com_isr(void);
-void WEAK tim8_cc_isr(void);
-void WEAK adc3_isr(void);
-void WEAK fsmc_isr(void);
-void WEAK sdio_isr(void);
-void WEAK tim5_isr(void);
-void WEAK spi3_isr(void);
-void WEAK uart4_isr(void);
-void WEAK uart5_isr(void);
-void WEAK tim6_isr(void);
-void WEAK tim7_isr(void);
-void WEAK dma2_channel1_isr(void);
-void WEAK dma2_channel2_isr(void);
-void WEAK dma2_channel3_isr(void);
-void WEAK dma2_channel4_5_isr(void);
-void WEAK dma2_channel5_isr(void);
-void WEAK eth_isr(void);
-void WEAK eth_wkup_isr(void);
-void WEAK can2_tx_isr(void);
-void WEAK can2_rx0_isr(void);
-void WEAK can2_rx1_isr(void);
-void WEAK can2_sce_isr(void);
-void WEAK otg_fs_isr(void);
-
-
-__attribute__ ((section(".vectors")))
-void (*const vector_table[]) (void) = {
- (void*)&_stack, /* Addr: 0x0000_0000 */
- reset_handler, /* Addr: 0x0000_0004 */
- nmi_handler, /* Addr: 0x0000_0008 */
- hard_fault_handler, /* Addr: 0x0000_000C */
- mem_manage_handler, /* Addr: 0x0000_0010 */
- bus_fault_handler, /* Addr: 0x0000_0014 */
- usage_fault_handler, /* Addr: 0x0000_0018 */
- 0, 0, 0, 0, /* Reserved Addr: 0x0000_001C - 0x0000_002B */
- sv_call_handler, /* Addr: 0x0000_002C */
- debug_monitor_handler, /* Addr: 0x0000_0030*/
- 0, /* Reserved Addr: 0x0000_00034 */
- pend_sv_handler, /* Addr: 0x0000_0038 */
- sys_tick_handler, /* Addr: 0x0000_003C */
- wwdg_isr, /* Addr: 0x0000_0040 */
- pvd_isr, /* Addr: 0x0000_0044 */
- tamper_isr, /* Addr: 0x0000_0048 */
- rtc_isr, /* Addr: 0x0000_004C */
- flash_isr, /* Addr: 0x0000_0050 */
- rcc_isr, /* Addr: 0x0000_0054 */
- exti0_isr, /* Addr: 0x0000_0058 */
- exti1_isr, /* Addr: 0x0000_005C */
- exti2_isr, /* Addr: 0x0000_0060 */
- exti3_isr, /* Addr: 0x0000_0064 */
- exti4_isr, /* Addr: 0x0000_0068 */
- dma1_channel1_isr, /* Addr: 0x0000_006C */
- dma1_channel2_isr, /* Addr: 0x0000_0070 */
- dma1_channel3_isr, /* Addr: 0x0000_0074 */
- dma1_channel4_isr, /* Addr: 0x0000_0078 */
- dma1_channel5_isr, /* Addr: 0x0000_007C */
- dma1_channel6_isr, /* Addr: 0x0000_0080 */
- dma1_channel7_isr, /* Addr: 0x0000_0084 */
- adc1_2_isr, /* Addr: 0x0000_0088 */
- usb_hp_can_tx_isr, /* Addr: 0x0000_008C */
- usb_lp_can_rx0_isr, /* Addr: 0x0000_0090 */
- can_rx1_isr, /* Addr: 0x0000_0094 */
- can_sce_isr, /* Addr: 0x0000_0098 */
- exti9_5_isr, /* Addr: 0x0000_009C */
- tim1_brk_isr, /* Addr: 0x0000_00A0 */
- tim1_up_isr, /* Addr: 0x0000_00A4 */
- tim1_trg_com_isr, /* Addr: 0x0000_00A8 */
- tim1_cc_isr, /* Addr: 0x0000_00AC */
- tim2_isr, /* Addr: 0x0000_00B0 */
- tim3_isr, /* Addr: 0x0000_00B4 */
- tim4_isr, /* Addr: 0x0000_00B8 */
- i2c1_ev_isr, /* Addr: 0x0000_00BC */
- i2c1_er_isr, /* Addr: 0x0000_00C0 */
- i2c2_ev_isr, /* Addr: 0x0000_00C4 */
- i2c2_er_isr, /* Addr: 0x0000_00C8 */
- spi1_isr, /* Addr: 0x0000_00CC */
- spi2_isr, /* Addr: 0x0000_00D0 */
- usart1_isr, /* Addr: 0x0000_00D4 */
- usart2_isr, /* Addr: 0x0000_00D8 */
- usart3_isr, /* Addr: 0x0000_00DC */
- exti15_10_isr, /* Addr: 0x0000_00E0 */
- rtc_alarm_isr, /* Addr: 0x0000_00E4 */
- usb_wakeup_isr, /* Addr: 0x0000_00E8 */
- tim8_brk_isr, /* Addr: 0x0000_00EC */
- tim8_up_isr, /* Addr: 0x0000_00F0 */
- tim8_trg_com_isr, /* Addr: 0x0000_00F4 */
- tim8_cc_isr, /* Addr: 0x0000_00F8 */
- adc3_isr, /* Addr: 0x0000_00FC */
- fsmc_isr, /* Addr: 0x0000_0100 */
- sdio_isr, /* Addr: 0x0000_0104 */
- tim5_isr, /* Addr: 0x0000_0108 */
- spi3_isr, /* Addr: 0x0000_010C */
- uart4_isr, /* Addr: 0x0000_0110 */
- uart5_isr, /* Addr: 0x0000_0114 */
- tim6_isr, /* Addr: 0x0000_0118 */
- tim7_isr, /* Addr: 0x0000_011C */
- dma2_channel1_isr, /* Addr: 0x0000_0120 */
- dma2_channel2_isr, /* Addr: 0x0000_0124 */
- dma2_channel3_isr, /* Addr: 0x0000_0128 */
- dma2_channel4_5_isr, /* Addr: 0x0000_012C */
- dma2_channel5_isr, /* Addr: 0x0000_0130 */
- eth_isr, /* Addr: 0x0000_0134 */
- eth_wkup_isr, /* Addr: 0x0000_0138 */
- can2_tx_isr, /* Addr: 0x0000_013C */
- can2_rx0_isr, /* Addr: 0x0000_0140 */
- can2_rx1_isr, /* Addr: 0x0000_0144 */
- can2_sce_isr, /* Addr: 0x0000_0148 */
- otg_fs_isr, /* Addr: 0x0000_014C */
-};
-
-void reset_handler(void)
-{
- volatile unsigned *src, *dest;
-
- __asm__("MSR msp, %0" : : "r"(&_stack));
-
- for (src = &_data_loadaddr, dest = &_data; dest < &_edata; src++, dest++)
- *dest = *src;
-
- while (dest < &_ebss)
- *dest++ = 0;
-
- /* Call the application's entry point. */
- main();
-}
-
-void blocking_handler(void)
-{
- while (1) ;
-}
-
-void null_handler(void)
-{
- /* Do nothing. */
-}
-
-#pragma weak nmi_handler = null_handler
-#pragma weak hard_fault_handler = blocking_handler
-#pragma weak mem_manage_handler = blocking_handler
-#pragma weak bus_fault_handler = blocking_handler
-#pragma weak usage_fault_handler = blocking_handler
-#pragma weak sv_call_handler = null_handler
-#pragma weak debug_monitor_handler = null_handler
-#pragma weak pend_sv_handler = null_handler
-#pragma weak sys_tick_handler = null_handler
-#pragma weak wwdg_isr = null_handler
-#pragma weak pvd_isr = null_handler
-#pragma weak tamper_isr = null_handler
-#pragma weak rtc_isr = null_handler
-#pragma weak flash_isr = null_handler
-#pragma weak rcc_isr = null_handler
-#pragma weak exti0_isr = null_handler
-#pragma weak exti1_isr = null_handler
-#pragma weak exti2_isr = null_handler
-#pragma weak exti3_isr = null_handler
-#pragma weak exti4_isr = null_handler
-#pragma weak dma1_channel1_isr = null_handler
-#pragma weak dma1_channel2_isr = null_handler
-#pragma weak dma1_channel3_isr = null_handler
-#pragma weak dma1_channel4_isr = null_handler
-#pragma weak dma1_channel5_isr = null_handler
-#pragma weak dma1_channel6_isr = null_handler
-#pragma weak dma1_channel7_isr = null_handler
-#pragma weak adc1_2_isr = null_handler
-#pragma weak usb_hp_can_tx_isr = null_handler
-#pragma weak usb_lp_can_rx0_isr = null_handler
-#pragma weak can_rx1_isr = null_handler
-#pragma weak can_sce_isr = null_handler
-#pragma weak exti9_5_isr = null_handler
-#pragma weak tim1_brk_isr = null_handler
-#pragma weak tim1_up_isr = null_handler
-#pragma weak tim1_trg_com_isr = null_handler
-#pragma weak tim1_cc_isr = null_handler
-#pragma weak tim2_isr = null_handler
-#pragma weak tim3_isr = null_handler
-#pragma weak tim4_isr = null_handler
-#pragma weak i2c1_ev_isr = null_handler
-#pragma weak i2c1_er_isr = null_handler
-#pragma weak i2c2_ev_isr = null_handler
-#pragma weak i2c2_er_isr = null_handler
-#pragma weak spi1_isr = null_handler
-#pragma weak spi2_isr = null_handler
-#pragma weak usart1_isr = null_handler
-#pragma weak usart2_isr = null_handler
-#pragma weak usart3_isr = null_handler
-#pragma weak exti15_10_isr = null_handler
-#pragma weak rtc_alarm_isr = null_handler
-#pragma weak usb_wakeup_isr = null_handler
-#pragma weak tim8_brk_isr = null_handler
-#pragma weak tim8_up_isr = null_handler
-#pragma weak tim8_trg_com_isr = null_handler
-#pragma weak tim8_cc_isr = null_handler
-#pragma weak adc3_isr = null_handler
-#pragma weak fsmc_isr = null_handler
-#pragma weak sdio_isr = null_handler
-#pragma weak tim5_isr = null_handler
-#pragma weak spi3_isr = null_handler
-#pragma weak uart4_isr = null_handler
-#pragma weak uart5_isr = null_handler
-#pragma weak tim6_isr = null_handler
-#pragma weak tim7_isr = null_handler
-#pragma weak dma2_channel1_isr = null_handler
-#pragma weak dma2_channel2_isr = null_handler
-#pragma weak dma2_channel3_isr = null_handler
-#pragma weak dma2_channel4_5_isr = null_handler
-#pragma weak dma2_channel5_isr
-#pragma weak eth_isr = null_handler
-#pragma weak eth_wkup_isr = null_handler
-#pragma weak can2_tx_isr = null_handler
-#pragma weak can2_rx0_isr = null_handler
-#pragma weak can2_rx1_isr = null_handler
-#pragma weak can2_sce_isr = null_handler
-#pragma weak otg_fs_isr = null_handler
diff --git a/lib/stm32/f2/Makefile b/lib/stm32/f2/Makefile
index c127d61..85e6458 100644
--- a/lib/stm32/f2/Makefile
+++ b/lib/stm32/f2/Makefile
@@ -28,9 +28,12 @@ CFLAGS = -Os -g -Wall -Wextra -I../../../include -fno-common \
-ffunction-sections -fdata-sections -MD -DSTM32F2
# ARFLAGS = rcsv
ARFLAGS = rcs
-OBJS = vector.o rcc.o gpio.o usart.o spi.o flash.o nvic.o \
- i2c.o systick.o exti.o scb.o timer.o assert.o
+OBJS = rcc.o gpio.o flash.o exti2.o timer.o \
+ gpio_common_all.o gpio_common_f24.o dma_common_f24.o spi_common_all.o \
+ dac_common_all.o usart_common_all.o iwdg_common_all.o i2c_common_all.o \
+ crc_common_all.o \
+ rtc_common_bcd.o
-VPATH += ../../usb:../:../../cm3
+VPATH += ../../usb:../:../../cm3:../common
include ../../Makefile.include
diff --git a/lib/stm32/f2/crc.c b/lib/stm32/f2/crc.c
new file mode 100644
index 0000000..5437f7c
--- /dev/null
+++ b/lib/stm32/f2/crc.c
@@ -0,0 +1,29 @@
+/** @defgroup crc_file CRC
+
+@ingroup STM32F2xx
+
+@brief <b>libopencm3 STM32F2xx CRC</b>
+
+*/
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/crc.h>
+#include <libopencm3/stm32/common/crc_common_all.h>
+
+
diff --git a/lib/stm32/f2/dac.c b/lib/stm32/f2/dac.c
new file mode 100644
index 0000000..5d20703
--- /dev/null
+++ b/lib/stm32/f2/dac.c
@@ -0,0 +1,28 @@
+/** @defgroup dac_file DAC
+
+@ingroup STM32F2xx
+
+@brief <b>libopencm3 STM32F2xx DAC</b>
+
+*/
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/dac.h>
+#include <libopencm3/stm32/common/dac_common_all.h>
+
diff --git a/lib/stm32/f2/dma.c b/lib/stm32/f2/dma.c
new file mode 100644
index 0000000..8e8f702
--- /dev/null
+++ b/lib/stm32/f2/dma.c
@@ -0,0 +1,28 @@
+/** @defgroup dma_file DMA
+
+@ingroup STM32F2xx
+
+@brief <b>libopencm3 STM32F2xx DMA</b>
+
+*/
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/dma.h>
+#include <libopencm3/stm32/common/dma_common_f24.h>
+
diff --git a/lib/stm32/f2/exti.c b/lib/stm32/f2/exti.c
deleted file mode 100644
index 5280914..0000000
--- a/lib/stm32/f2/exti.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * This file is part of the libopencm3 project.
- *
- * Copyright (C) 2010 Mark Butler <mbutler@physics.otago.ac.nz>
- *
- * This library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <libopencm3/stm32/exti.h>
-#include <libopencm3/stm32/f2/syscfg.h>
-#include <libopencm3/stm32/f2/gpio.h>
-
-void exti_set_trigger(u32 extis, exti_trigger_type trig)
-{
- switch (trig) {
- case EXTI_TRIGGER_RISING:
- EXTI_RTSR |= extis;
- EXTI_FTSR &= ~extis;
- break;
- case EXTI_TRIGGER_FALLING:
- EXTI_RTSR &= ~extis;
- EXTI_FTSR |= extis;
- break;
- case EXTI_TRIGGER_BOTH:
- EXTI_RTSR |= extis;
- EXTI_FTSR |= extis;
- break;
- }
-}
-
-void exti_enable_request(u32 extis)
-{
- /* Enable interrupts. */
- EXTI_IMR |= extis;
-
- /* Enable events. */
- EXTI_EMR |= extis;
-}
-
-void exti_disable_request(u32 extis)
-{
- /* Disable interrupts. */
- EXTI_IMR &= ~extis;
-
- /* Disable events. */
- EXTI_EMR &= ~extis;
-}
-
-/*
- * Reset the interrupt request by writing a 1 to the corresponding
- * pending bit register.
- */
-void exti_reset_request(u32 extis)
-{
- EXTI_PR = extis;
-}
-
-/*
- * Remap an external interrupt line to the corresponding pin on the
- * specified GPIO port.
- *
- * TODO: This could be rewritten in fewer lines of code.
- */
-void exti_select_source(u32 exti, u32 gpioport)
-{
- u8 shift, bits;
-
- shift = bits = 0;
-
- switch (exti) {
- case EXTI0:
- case EXTI4:
- case EXTI8:
- case EXTI12:
- shift = 0;
- break;
- case EXTI1:
- case EXTI5:
- case EXTI9:
- case EXTI13:
- shift = 4;
- break;
- case EXTI2:
- case EXTI6:
- case EXTI10:
- case EXTI14:
- shift = 8;
- break;
- case EXTI3:
- case EXTI7:
- case EXTI11:
- case EXTI15:
- shift = 12;
- break;
- }
-
- switch (gpioport) {
- case GPIOA:
- bits = 0xf;
- break;
- case GPIOB:
- bits = 0xe;
- break;
- case GPIOC:
- bits = 0xd;
- break;
- case GPIOD:
- bits = 0xc;
- break;
- case GPIOE:
- bits = 0xb;
- break;
- case GPIOF:
- bits = 0xa;
- break;
- case GPIOG:
- bits = 0x9;
- break;
- }
-
- /* Ensure that only valid EXTI lines are used. */
- if (exti < EXTI4) {
- SYSCFG_EXTICR1 &= ~(0x000F << shift);
- SYSCFG_EXTICR1 |= (~bits << shift);
- } else if (exti < EXTI8) {
- SYSCFG_EXTICR2 &= ~(0x000F << shift);
- SYSCFG_EXTICR2 |= (~bits << shift);
- } else if (exti < EXTI12) {
- SYSCFG_EXTICR3 &= ~(0x000F << shift);
- SYSCFG_EXTICR3 |= (~bits << shift);
- } else if (exti < EXTI16) {
- SYSCFG_EXTICR4 &= ~(0x000F << shift);
- SYSCFG_EXTICR4 |= (~bits << shift);
- }
-}
diff --git a/lib/stm32/f2/flash.c b/lib/stm32/f2/flash.c
index 6e2c64d..0b9f834 100644
--- a/lib/stm32/f2/flash.c
+++ b/lib/stm32/f2/flash.c
@@ -28,42 +28,42 @@ static inline void flash_set_program_size(u32 psize)
void flash_data_cache_enable(void)
{
- FLASH_ACR |= FLASH_DCE;
+ FLASH_ACR |= FLASH_ACR_DCE;
}
void flash_dcache_disable(void)
{
- FLASH_ACR &= ~FLASH_DCE;
+ FLASH_ACR &= ~FLASH_ACR_DCE;
}
void flash_icache_enable(void)
{
- FLASH_ACR |= FLASH_ICE;
+ FLASH_ACR |= FLASH_ACR_ICE;
}
void flash_icache_disable(void)
{
- FLASH_ACR &= ~FLASH_ICE;
+ FLASH_ACR &= ~FLASH_ACR_ICE;
}
void flash_prefetch_enable(void)
{
- FLASH_ACR |= FLASH_PRFTEN;
+ FLASH_ACR |= FLASH_ACR_PRFTEN;
}
void flash_prefetch_disable(void)
{
- FLASH_ACR &= ~FLASH_PRFTEN;
+ FLASH_ACR &= ~FLASH_ACR_PRFTEN;
}
void flash_dcache_reset(void)
{
- FLASH_ACR |= FLASH_DCRST;
+ FLASH_ACR |= FLASH_ACR_DCRST;
}
void flash_icache_reset(void)
{
- FLASH_ACR |= FLASH_ICRST;
+ FLASH_ACR |= FLASH_ACR_ICRST;
}
void flash_set_ws(u32 ws)
@@ -79,43 +79,43 @@ void flash_set_ws(u32 ws)
void flash_unlock(void)
{
/* Authorize the FPEC access. */
- FLASH_KEYR = FLASH_KEY1;
- FLASH_KEYR = FLASH_KEY2;
+ FLASH_KEYR = FLASH_KEYR_KEY1;
+ FLASH_KEYR = FLASH_KEYR_KEY2;
}
void flash_lock(void)
{
- FLASH_CR |= FLASH_LOCK;
+ FLASH_CR |= FLASH_CR_LOCK;
}
void flash_clear_pgserr_flag(void)
{
- FLASH_SR |= FLASH_PGSERR;
+ FLASH_SR |= FLASH_SR_PGSERR;
}
void flash_clear_pgperr_flag(void)
{
- FLASH_SR |= FLASH_PGPERR;
+ FLASH_SR |= FLASH_SR_PGPERR;
}
void flash_clear_pgaerr_flag(void)
{
- FLASH_SR |= FLASH_PGAERR;
+ FLASH_SR |= FLASH_SR_PGAERR;
}
void flash_clear_eop_flag(void)
{
- FLASH_SR |= FLASH_EOP;
+ FLASH_SR |= FLASH_SR_EOP;
}
void flash_clear_wrperr_flag(void)
{
- FLASH_SR |= FLASH_WRPERR;
+ FLASH_SR |= FLASH_SR_WRPERR;
}
void flash_clear_bsy_flag(void)
{
- FLASH_SR &= ~FLASH_BSY;
+ FLASH_SR &= ~FLASH_SR_BSY;
}
void flash_clear_status_flags(void)
@@ -130,18 +130,18 @@ void flash_clear_status_flags(void)
void flash_unlock_option_bytes(void)
{
- FLASH_OPTKEYR = FLASH_OPTKEY1;
- FLASH_OPTKEYR = FLASH_OPTKEY2;
+ FLASH_OPTKEYR = FLASH_OPTKEYR_KEY1;
+ FLASH_OPTKEYR = FLASH_OPTKEYR_KEY2;
}
void flash_lock_option_bytes(void)
{
- FLASH_OPTCR |= FLASH_OPTLOCK;
+ FLASH_OPTCR |= FLASH_OPTCR_OPTLOCK;
}
void flash_wait_for_last_operation(void)
{
- while ((FLASH_SR & FLASH_BSY) == FLASH_BSY)
+ while ((FLASH_SR & FLASH_SR_BSY) == FLASH_SR_BSY)
;
}
@@ -152,7 +152,7 @@ void flash_program_double_word(u32 address, u64 data, u32 program_size)
flash_set_program_size(program_size);
/* Enable writes to flash. */
- FLASH_CR |= FLASH_PG;
+ FLASH_CR |= FLASH_CR_PG;
/* Program the first half of the word. */
MMIO64(address) = data;
@@ -161,7 +161,7 @@ void flash_program_double_word(u32 address, u64 data, u32 program_size)
flash_wait_for_last_operation();
/* Disable writes to flash. */
- FLASH_CR &= ~FLASH_PG;
+ FLASH_CR &= ~FLASH_CR_PG;
}
void flash_program_word(u32 address, u32 data, u32 program_size)
@@ -171,7 +171,7 @@ void flash_program_word(u32 address, u32 data, u32 program_size)
flash_set_program_size(program_size);
/* Enable writes to flash. */
- FLASH_CR |= FLASH_PG;
+ FLASH_CR |= FLASH_CR_PG;
/* Program the first half of the word. */
MMIO32(address) = data;
@@ -180,7 +180,7 @@ void flash_program_word(u32 address, u32 data, u32 program_size)
flash_wait_for_last_operation();
/* Disable writes to flash. */
- FLASH_CR &= ~FLASH_PG;
+ FLASH_CR &= ~FLASH_CR_PG;
}
void flash_program_half_word(u32 address, u16 data, u32 program_size)
@@ -188,13 +188,13 @@ void flash_program_half_word(u32 address, u16 data, u32 program_size)
flash_wait_for_last_operation();
flash_set_program_size(program_size);
- FLASH_CR |= FLASH_PG;
+ FLASH_CR |= FLASH_CR_PG;
MMIO16(address) = data;
flash_wait_for_last_operation();
- FLASH_CR &= ~FLASH_PG; /* Disable the PG bit. */
+ FLASH_CR &= ~FLASH_CR_PG; /* Disable the PG bit. */
}
void flash_program_byte(u32 address, u8 data, u32 program_size)
@@ -202,13 +202,13 @@ void flash_program_byte(u32 address, u8 data, u32 program_size)
flash_wait_for_last_operation();
flash_set_program_size(program_size);
- FLASH_CR |= FLASH_PG;
+ FLASH_CR |= FLASH_CR_PG;
MMIO8(address) = data;
flash_wait_for_last_operation();
- FLASH_CR &= ~FLASH_PG; /* Disable the PG bit. */
+ FLASH_CR &= ~FLASH_CR_PG; /* Disable the PG bit. */
}
void flash_erase_sector(u32 sector, u32 program_size)
@@ -218,10 +218,10 @@ void flash_erase_sector(u32 sector, u32 program_size)
FLASH_CR &= ~(((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)) << 3);
FLASH_CR |= sector;
- FLASH_CR |= FLASH_STRT;
+ FLASH_CR |= FLASH_CR_STRT;
flash_wait_for_last_operation();
- FLASH_CR &= ~FLASH_SER;
+ FLASH_CR &= ~FLASH_CR_SER;
FLASH_CR &= ~(((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)) << 3);
}
@@ -230,21 +230,21 @@ void flash_erase_all_sectors(u32 program_size)
flash_wait_for_last_operation();
flash_set_program_size(program_size);
- FLASH_CR |= FLASH_MER; /* Enable mass erase. */
- FLASH_CR |= FLASH_STRT; /* Trigger the erase. */
+ FLASH_CR |= FLASH_CR_MER; /* Enable mass erase. */
+ FLASH_CR |= FLASH_CR_STRT; /* Trigger the erase. */
flash_wait_for_last_operation();
- FLASH_CR &= ~FLASH_MER; /* Disable mass erase. */
+ FLASH_CR &= ~FLASH_CR_MER; /* Disable mass erase. */
}
void flash_program_option_bytes(u32 data)
{
flash_wait_for_last_operation();
- if (FLASH_OPTCR & FLASH_OPTLOCK)
+ if (FLASH_OPTCR & FLASH_OPTCR_OPTLOCK)
flash_unlock_option_bytes();
FLASH_OPTCR = data & ~0x3;
- FLASH_OPTCR |= FLASH_OPTSTRT; /* Enable option byte programming. */
+ FLASH_OPTCR |= FLASH_OPTCR_OPTSTRT; /* Enable option byte programming. */
flash_wait_for_last_operation();
}
diff --git a/lib/stm32/f2/gpio.c b/lib/stm32/f2/gpio.c
index 984cddb..a2dfc88 100644
--- a/lib/stm32/f2/gpio.c
+++ b/lib/stm32/f2/gpio.c
@@ -1,8 +1,14 @@
+/** @defgroup gpio_file GPIO
+
+@ingroup STM32F2xx
+
+@brief <b>libopencm3 STM32F2xx General Purpose I/O</b>
+
+*/
+
/*
* This file is part of the libopencm3 project.
*
- * Copyright (C) 2011 Fergus Noble <fergusnoble@gmail.com>
- *
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@@ -17,126 +23,6 @@
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <libopencm3/stm32/f2/gpio.h>
-
-void gpio_mode_setup(u32 gpioport, u8 mode, u8 pull_up_down, u16 gpios)
-{
- u16 i;
- u32 moder, pupd;
-
- /*
- * We want to set the config only for the pins mentioned in gpios,
- * but keeping the others, so read out the actual config first.
- */
- moder = GPIO_MODER(gpioport);
- pupd = GPIO_PUPDR(gpioport);
-
- for (i = 0; i < 16; i++) {
- if (!((1 << i) & gpios))
- continue;
-
- moder &= ~GPIO_MODE_MASK(i);
- moder |= GPIO_MODE(i, mode);
- pupd &= ~GPIO_PUPD_MASK(i);
- pupd |= GPIO_PUPD(i, pull_up_down);
- }
-
- /* Set mode and pull up/down control registers. */
- GPIO_MODER(gpioport) = moder;
- GPIO_PUPDR(gpioport) = pupd;
-}
-
-void gpio_set_output_options(u32 gpioport, u8 otype, u8 speed, u16 gpios)
-{
- u16 i;
- u32 ospeedr;
-
- if (otype == 0x1)
- GPIO_OTYPER(gpioport) |= gpios;
- else
- GPIO_OTYPER(gpioport) &= ~gpios;
-
- ospeedr = GPIO_OSPEEDR(gpioport);
-
- for (i = 0; i < 16; i++) {
- if (!((1 << i) & gpios))
- continue;
- ospeedr &= ~GPIO_OSPEED_MASK(i);
- ospeedr |= GPIO_OSPEED(i, speed);
- }
-
- GPIO_OSPEEDR(gpioport) = ospeedr;
-}
-
-void gpio_set_af(u32 gpioport, u8 alt_func_num, u16 gpios)
-{
- u16 i;
- u32 afrl, afrh;
-
- afrl = GPIO_AFRL(gpioport);
- afrh = GPIO_AFRH(gpioport);
-
- for (i = 0; i < 8; i++) {
- if (!((1 << i) & gpios))
- continue;
- afrl &= ~GPIO_AFR_MASK(i);
- afrl |= GPIO_AFR(i, alt_func_num);
- }
-
- for (i = 8; i < 16; i++) {
- if (!((1 << i) & gpios))
- continue;
- afrl &= ~GPIO_AFR_MASK(i - 8);
- afrh |= GPIO_AFR(i - 8, alt_func_num);
- }
-
- GPIO_AFRL(gpioport) = afrl;
- GPIO_AFRH(gpioport) = afrh;
-}
-
-void gpio_set(u32 gpioport, u16 gpios)
-{
- GPIO_BSRR(gpioport) = gpios;
-}
-
-void gpio_clear(u32 gpioport, u16 gpios)
-{
- GPIO_BSRR(gpioport) = gpios << 16;
-}
-
-u16 gpio_get(u32 gpioport, u16 gpios)
-{
- return gpio_port_read(gpioport) & gpios;
-}
-
-void gpio_toggle(u32 gpioport, u16 gpios)
-{
- GPIO_ODR(gpioport) ^= gpios;
-}
-
-u16 gpio_port_read(u32 gpioport)
-{
- return (u16)GPIO_IDR(gpioport);
-}
-
-void gpio_port_write(u32 gpioport, u16 data)
-{
- GPIO_ODR(gpioport) = data;
-}
-
-void gpio_port_config_lock(u32 gpioport, u16 gpios)
-{
- u32 reg32;
-
- /* Special "Lock Key Writing Sequence", see datasheet. */
- GPIO_LCKR(gpioport) = GPIO_LCKK | gpios; /* Set LCKK. */
- GPIO_LCKR(gpioport) = ~GPIO_LCKK & gpios; /* Clear LCKK. */
- GPIO_LCKR(gpioport) = GPIO_LCKK | gpios; /* Set LCKK. */
- reg32 = GPIO_LCKR(gpioport); /* Read LCKK. */
- reg32 = GPIO_LCKR(gpioport); /* Read LCKK again. */
-
- /* Tell the compiler the variable is actually used. It will get optimized out anyways. */
- reg32 = reg32;
+#include <libopencm3/stm32/gpio.h>
+#include <libopencm3/stm32/common/gpio_common_f24.h>
- /* If (reg32 & GPIO_LCKK) is true, the lock is now active. */
-}
diff --git a/lib/stm32/f2/i2c.c b/lib/stm32/f2/i2c.c
new file mode 100644
index 0000000..f20a840
--- /dev/null
+++ b/lib/stm32/f2/i2c.c
@@ -0,0 +1,28 @@
+/** @defgroup i2c_file I2C
+
+@ingroup STM32F2xx
+
+@brief <b>libopencm3 STM32F2xx I2C</b>
+
+*/
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/i2c.h>
+#include <libopencm3/stm32/common/spi_common_all.h>
+
diff --git a/lib/stm32/f2/iwdg.c b/lib/stm32/f2/iwdg.c
new file mode 100644
index 0000000..0440d88
--- /dev/null
+++ b/lib/stm32/f2/iwdg.c
@@ -0,0 +1,28 @@
+/** @defgroup iwdg_file IWDG
+
+@ingroup STM32F2xx
+
+@brief <b>libopencm3 STM32F2xx Independent Watchdog Timer</b>
+
+*/
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/iwdg.h>
+#include <libopencm3/stm32/common/iwdg_common_all.h>
+
diff --git a/lib/stm32/f2/rcc.c b/lib/stm32/f2/rcc.c
index cc2c9bb..d60c232 100644
--- a/lib/stm32/f2/rcc.c
+++ b/lib/stm32/f2/rcc.c
@@ -37,7 +37,7 @@ const clock_scale_t hse_8mhz_3v3[CLOCK_3V3_END] =
.hpre = RCC_CFGR_HPRE_DIV_NONE,
.ppre1 = RCC_CFGR_PPRE_DIV_4,
.ppre2 = RCC_CFGR_PPRE_DIV_2,
- .flash_config = FLASH_ICE | FLASH_DCE | FLASH_LATENCY_3WS,
+ .flash_config = FLASH_ACR_ICE | FLASH_ACR_DCE | FLASH_ACR_LATENCY_3WS,
.apb1_frequency = 30000000,
.apb2_frequency = 60000000,
},
diff --git a/lib/stm32/f2/rtc.c b/lib/stm32/f2/rtc.c
new file mode 100644
index 0000000..461d0b1
--- /dev/null
+++ b/lib/stm32/f2/rtc.c
@@ -0,0 +1,27 @@
+/** @defgroup rtc_file RTC
+
+@ingroup STM32F2xx
+
+@brief <b>libopencm3 STM32F2xx RTC</b>
+
+*/
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/rtc.h>
+#include <libopencm3/stm32/common/rtc_common_bcd.h>
diff --git a/lib/stm32/f2/spi.c b/lib/stm32/f2/spi.c
new file mode 100644
index 0000000..bc4a4ee
--- /dev/null
+++ b/lib/stm32/f2/spi.c
@@ -0,0 +1,28 @@
+/** @defgroup spi_file SPI
+
+@ingroup STM32F2xx
+
+@brief <b>libopencm3 STM32F2xx SPI</b>
+
+*/
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/spi.h>
+#include <libopencm3/stm32/common/spi_common_f24.h>
+
diff --git a/lib/stm32/f2/timer.c b/lib/stm32/f2/timer.c
deleted file mode 100644
index 659f8a9..0000000
--- a/lib/stm32/f2/timer.c
+++ /dev/null
@@ -1,928 +0,0 @@
-/*
- * This file is part of the libopencm3 project.
- *
- * Copyright (C) 2010 Edward Cheeseman <evbuilder@users.sourceforge.org>
- * Copyright (C) 2011 Stephen Caudle <scaudle@doceme.com>
- *
- * This library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
- * Basic TIMER handling API.
- *
- * Examples:
- * timer_set_mode(TIM1, TIM_CR1_CKD_CK_INT_MUL_2,
- * TIM_CR1_CMS_CENTRE_3, TIM_CR1_DIR_UP);
- */
-
-#include <libopencm3/stm32/f2/timer.h>
-#include <libopencm3/stm32/f2/rcc.h>
-
-void timer_reset(u32 timer_peripheral)
-{
- switch (timer_peripheral) {
- case TIM1:
- rcc_peripheral_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM1RST);
- rcc_peripheral_clear_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM1RST);
- break;
- case TIM2:
- rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM2RST);
- rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM2RST);
- break;
- case TIM3:
- rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM3RST);
- rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM3RST);
- break;
- case TIM4:
- rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM4RST);
- rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM4RST);
- break;
- case TIM5:
- rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM5RST);
- rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM5RST);
- break;
- case TIM6:
- rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM6RST);
- rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM6RST);
- break;
- case TIM7:
- rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM7RST);
- rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM7RST);
- break;
- case TIM8:
- rcc_peripheral_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM8RST);
- rcc_peripheral_clear_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM8RST);
- break;
-/* These timers are not supported in libopencm3 yet */
-/*
- case TIM9:
- rcc_peripheral_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM9RST);
- rcc_peripheral_clear_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM9RST);
- break;
- case TIM10:
- rcc_peripheral_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM10RST);
- rcc_peripheral_clear_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM10RST);
- break;
- case TIM11:
- rcc_peripheral_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM11RST);
- rcc_peripheral_clear_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM11RST);
- break;
- case TIM12:
- rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM12RST);
- rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM12RST);
- break;
- case TIM13:
- rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM13RST);
- rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM13RST);
- break;
- case TIM14:
- rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM14RST);
- rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM14RST);
- break;
-*/
- }
-}
-
-void timer_enable_irq(u32 timer_peripheral, u32 irq)
-{
- TIM_DIER(timer_peripheral) |= irq;
-}
-
-void timer_disable_irq(u32 timer_peripheral, u32 irq)
-{
- TIM_DIER(timer_peripheral) &= ~irq;
-}
-
-bool timer_get_flag(u32 timer_peripheral, u32 flag)
-{
- if (((TIM_SR(timer_peripheral) & flag) != 0) &&
- ((TIM_DIER(timer_peripheral) & flag) != 0)) {
- return true;
- }
-
- return false;
-}
-
-void timer_clear_flag(u32 timer_peripheral, u32 flag)
-{
- TIM_SR(timer_peripheral) &= ~flag;
-}
-
-void timer_set_mode(u32 timer_peripheral, u32 clock_div,
- u32 alignment, u32 direction)
-{
- u32 cr1;
-
- cr1 = TIM_CR1(timer_peripheral);
-
- cr1 &= ~(TIM_CR1_CKD_CK_INT_MASK | TIM_CR1_CMS_MASK | TIM_CR1_DIR_DOWN);
-
- cr1 |= clock_div | alignment | direction;
-
- TIM_CR1(timer_peripheral) = cr1;
-}
-
-void timer_set_clock_division(u32 timer_peripheral, u32 clock_div)
-{
- clock_div &= TIM_CR1_CKD_CK_INT_MASK;
- TIM_CR1(timer_peripheral) &= ~TIM_CR1_CKD_CK_INT_MASK;
- TIM_CR1(timer_peripheral) |= clock_div;
-}
-
-void timer_enable_preload(u32 timer_peripheral)
-{
- TIM_CR1(timer_peripheral) |= TIM_CR1_ARPE;
-}
-
-void timer_disable_preload(u32 timer_peripheral)
-{
- TIM_CR1(timer_peripheral) &= ~TIM_CR1_ARPE;
-}
-
-void timer_set_alignment(u32 timer_peripheral, u32 alignment)
-{
- alignment &= TIM_CR1_CMS_MASK;
- TIM_CR1(timer_peripheral) &= ~TIM_CR1_CMS_MASK;
- TIM_CR1(timer_peripheral) |= alignment;
-}
-
-void timer_direction_up(u32 timer_peripheral)
-{
- TIM_CR1(timer_peripheral) &= ~TIM_CR1_DIR_DOWN;
-}
-
-void timer_direction_down(u32 timer_peripheral)
-{
- TIM_CR1(timer_peripheral) |= TIM_CR1_DIR_DOWN;
-}
-
-void timer_one_shot_mode(u32 timer_peripheral)
-{
- TIM_CR1(timer_peripheral) |= TIM_CR1_OPM;
-}
-
-void timer_continuous_mode(u32 timer_peripheral)
-{
- TIM_CR1(timer_peripheral) &= ~TIM_CR1_OPM;
-}
-
-void timer_update_on_any(u32 timer_peripheral)
-{
- TIM_CR1(timer_peripheral) &= ~TIM_CR1_URS;
-}
-
-void timer_update_on_overflow(u32 timer_peripheral)
-{
- TIM_CR1(timer_peripheral) |= TIM_CR1_URS;
-}
-
-void timer_enable_update_event(u32 timer_peripheral)
-{
- TIM_CR1(timer_peripheral) &= ~TIM_CR1_UDIS;
-}
-
-void timer_disable_update_event(u32 timer_peripheral)
-{
- TIM_CR1(timer_peripheral) |= TIM_CR1_UDIS;
-}
-
-void timer_enable_counter(u32 timer_peripheral)
-{
- TIM_CR1(timer_peripheral) |= TIM_CR1_CEN;
-}
-
-void timer_disable_counter(u32 timer_peripheral)
-{
- TIM_CR1(timer_peripheral) &= ~TIM_CR1_CEN;
-}
-
-void timer_set_output_idle_state(u32 timer_peripheral, u32 outputs)
-{
- TIM_CR2(timer_peripheral) |= outputs & TIM_CR2_OIS_MASK;
-}
-
-void timer_reset_output_idle_state(u32 timer_peripheral, u32 outputs)
-{
- TIM_CR2(timer_peripheral) &= ~(outputs & TIM_CR2_OIS_MASK);
-}
-
-void timer_set_ti1_ch123_xor(u32 timer_peripheral)
-{
- TIM_CR2(timer_peripheral) |= TIM_CR2_TI1S;
-}
-
-void timer_set_ti1_ch1(u32 timer_peripheral)
-{
- TIM_CR2(timer_peripheral) &= ~TIM_CR2_TI1S;
-}
-
-void timer_set_master_mode(u32 timer_peripheral, u32 mode)
-{
- TIM_CR2(timer_peripheral) &= ~TIM_CR2_MMS_MASK;
- TIM_CR2(timer_peripheral) |= mode;
-}
-
-void timer_set_dma_on_compare_event(u32 timer_peripheral)
-{
- TIM_CR2(timer_peripheral) &= ~TIM_CR2_CCDS;
-}
-
-void timer_set_dma_on_update_event(u32 timer_peripheral)
-{
- TIM_CR2(timer_peripheral) |= TIM_CR2_CCDS;
-}
-
-void timer_enable_compare_control_update_on_trigger(u32 timer_peripheral)
-{
- TIM_CR2(timer_peripheral) |= TIM_CR2_CCUS;
-}
-
-void timer_disable_compare_control_update_on_trigger(u32 timer_peripheral)
-{
- TIM_CR2(timer_peripheral) &= ~TIM_CR2_CCUS;
-}
-
-void timer_enable_preload_complementry_enable_bits(u32 timer_peripheral)
-{
- TIM_CR2(timer_peripheral) |= TIM_CR2_CCPC;
-}
-
-void timer_disable_preload_complementry_enable_bits(u32 timer_peripheral)
-{
- TIM_CR2(timer_peripheral) &= ~TIM_CR2_CCPC;
-}
-
-void timer_set_prescaler(u32 timer_peripheral, u32 value)
-{
- TIM_PSC(timer_peripheral) = value;
-}
-
-void timer_set_repetition_counter(u32 timer_peripheral, u32 value)
-{
- if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_RCR(timer_peripheral) = value;
-}
-
-void timer_set_period(u32 timer_peripheral, u32 period)
-{
- TIM_ARR(timer_peripheral) = period;
-}
-
-void timer_enable_oc_clear(u32 timer_peripheral, enum tim_oc_id oc_id)
-{
- switch (oc_id) {
- case TIM_OC1:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1CE;
- break;
- case TIM_OC2:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2CE;
- break;
- case TIM_OC3:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3CE;
- break;
- case TIM_OC4:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4CE;
- break;
- case TIM_OC1N:
- case TIM_OC2N:
- case TIM_OC3N:
- /* Ignoring as fast enable only applies to the whole channel. */
- break;
- }
-}
-
-void timer_disable_oc_clear(u32 timer_peripheral, enum tim_oc_id oc_id)
-{
- switch (oc_id) {
- case TIM_OC1:
- TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC1CE;
- break;
- case TIM_OC2:
- TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC2CE;
- break;
- case TIM_OC3:
- TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC3CE;
- break;
- case TIM_OC4:
- TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC4CE;
- break;
- case TIM_OC1N:
- case TIM_OC2N:
- case TIM_OC3N:
- /* Ignoring as fast enable only applies to the whole channel. */
- break;
- }
-}
-
-void timer_set_oc_fast_mode(u32 timer_peripheral, enum tim_oc_id oc_id)
-{
- switch (oc_id) {
- case TIM_OC1:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1FE;
- break;
- case TIM_OC2:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2FE;
- break;
- case TIM_OC3:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3FE;
- break;
- case TIM_OC4:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4FE;
- break;
- case TIM_OC1N:
- case TIM_OC2N:
- case TIM_OC3N:
- /* Ignoring as fast enable only applies to the whole channel. */
- break;
- }
-}
-
-void timer_set_oc_slow_mode(u32 timer_peripheral, enum tim_oc_id oc_id)
-{
- switch (oc_id) {
- case TIM_OC1:
- TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC1FE;
- break;
- case TIM_OC2:
- TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC2FE;
- break;
- case TIM_OC3:
- TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC3FE;
- break;
- case TIM_OC4:
- TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC4FE;
- break;
- case TIM_OC1N:
- case TIM_OC2N:
- case TIM_OC3N:
- /* Ignoring as this option applies to the whole channel. */
- break;
- }
-}
-
-void timer_set_oc_mode(u32 timer_peripheral, enum tim_oc_id oc_id,
- enum tim_oc_mode oc_mode)
-{
- switch (oc_id) {
- case TIM_OC1:
- TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_CC1S_MASK;
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_CC1S_OUT;
- TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC1M_MASK;
- switch (oc_mode) {
- case TIM_OCM_FROZEN:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1M_FROZEN;
- break;
- case TIM_OCM_ACTIVE:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1M_ACTIVE;
- break;
- case TIM_OCM_INACTIVE:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1M_INACTIVE;
- break;
- case TIM_OCM_TOGGLE:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1M_TOGGLE;
- break;
- case TIM_OCM_FORCE_LOW:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1M_FORCE_LOW;
- break;
- case TIM_OCM_FORCE_HIGH:
- TIM_CCMR1(timer_peripheral) |=
- TIM_CCMR1_OC1M_FORCE_HIGH;
- break;
- case TIM_OCM_PWM1:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1M_PWM1;
- break;
- case TIM_OCM_PWM2:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1M_PWM2;
- break;
- }
- break;
- case TIM_OC2:
- TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_CC2S_MASK;
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_CC2S_OUT;
- TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC2M_MASK;
- switch (oc_mode) {
- case TIM_OCM_FROZEN:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2M_FROZEN;
- break;
- case TIM_OCM_ACTIVE:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2M_ACTIVE;
- break;
- case TIM_OCM_INACTIVE:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2M_INACTIVE;
- break;
- case TIM_OCM_TOGGLE:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2M_TOGGLE;
- break;
- case TIM_OCM_FORCE_LOW:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2M_FORCE_LOW;
- break;
- case TIM_OCM_FORCE_HIGH:
- TIM_CCMR1(timer_peripheral) |=
- TIM_CCMR1_OC2M_FORCE_HIGH;
- break;
- case TIM_OCM_PWM1:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2M_PWM1;
- break;
- case TIM_OCM_PWM2:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2M_PWM2;
- break;
- }
- break;
- case TIM_OC3:
- TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR2_CC3S_MASK;
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR2_CC3S_OUT;
- TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC3M_MASK;
- switch (oc_mode) {
- case TIM_OCM_FROZEN:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3M_FROZEN;
- break;
- case TIM_OCM_ACTIVE:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR2_OC3M_ACTIVE;
- break;
- case TIM_OCM_INACTIVE:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3M_INACTIVE;
- break;
- case TIM_OCM_TOGGLE:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3M_TOGGLE;
- break;
- case TIM_OCM_FORCE_LOW:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3M_FORCE_LOW;
- break;
- case TIM_OCM_FORCE_HIGH:
- TIM_CCMR2(timer_peripheral) |=
- TIM_CCMR2_OC3M_FORCE_HIGH;
- break;
- case TIM_OCM_PWM1:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3M_PWM1;
- break;
- case TIM_OCM_PWM2:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3M_PWM2;
- break;
- }
- break;
- case TIM_OC4:
- TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR2_CC4S_MASK;
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR2_CC4S_OUT;
- TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC4M_MASK;
- switch (oc_mode) {
- case TIM_OCM_FROZEN:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4M_FROZEN;
- break;
- case TIM_OCM_ACTIVE:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR2_OC4M_ACTIVE;
- break;
- case TIM_OCM_INACTIVE:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4M_INACTIVE;
- break;
- case TIM_OCM_TOGGLE:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4M_TOGGLE;
- break;
- case TIM_OCM_FORCE_LOW:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4M_FORCE_LOW;
- break;
- case TIM_OCM_FORCE_HIGH:
- TIM_CCMR2(timer_peripheral) |=
- TIM_CCMR2_OC4M_FORCE_HIGH;
- break;
- case TIM_OCM_PWM1:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4M_PWM1;
- break;
- case TIM_OCM_PWM2:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4M_PWM2;
- break;
- }
- break;
- case TIM_OC1N:
- case TIM_OC2N:
- case TIM_OC3N:
- /* Ignoring as this option applies to the whole channel. */
- break;
- }
-}
-
-void timer_enable_oc_preload(u32 timer_peripheral, enum tim_oc_id oc_id)
-{
- switch (oc_id) {
- case TIM_OC1:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1PE;
- break;
- case TIM_OC2:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2PE;
- break;
- case TIM_OC3:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3PE;
- break;
- case TIM_OC4:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4PE;
- break;
- case TIM_OC1N:
- case TIM_OC2N:
- case TIM_OC3N:
- /* Ignoring as this option applies to the whole channel. */
- break;
- }
-}
-
-void timer_disable_oc_preload(u32 timer_peripheral, enum tim_oc_id oc_id)
-{
- switch (oc_id) {
- case TIM_OC1:
- TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC1PE;
- break;
- case TIM_OC2:
- TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC2PE;
- break;
- case TIM_OC3:
- TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC3PE;
- break;
- case TIM_OC4:
- TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC4PE;
- break;
- case TIM_OC1N:
- case TIM_OC2N:
- case TIM_OC3N:
- /* Ignoring as this option applies to the whole channel. */
- break;
- }
-}
-
-void timer_set_oc_polarity_high(u32 timer_peripheral, enum tim_oc_id oc_id)
-{
- switch (oc_id) {
- case TIM_OC1:
- TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC1P;
- break;
- case TIM_OC2:
- TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC2P;
- break;
- case TIM_OC3:
- TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC3P;
- break;
- case TIM_OC4:
- TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC4P;
- break;
- case TIM_OC1N:
- case TIM_OC2N:
- case TIM_OC3N:
- /* Ignoring as this option applies to TIM1 and TIM8 only. */
- break;
- }
-
- /* Acting for TIM1 and TIM8 only from here onwards. */
- if ((timer_peripheral != TIM1) && (timer_peripheral != TIM8))
- return;
-
- switch (oc_id) {
- case TIM_OC1N:
- TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC1NP;
- break;
- case TIM_OC2N:
- TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC2NP;
- break;
- case TIM_OC3N:
- TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC3NP;
- break;
- case TIM_OC1:
- case TIM_OC2:
- case TIM_OC3:
- case TIM_OC4:
- /* Ignoring as this option was already set above. */
- break;
- }
-}
-
-void timer_set_oc_polarity_low(u32 timer_peripheral, enum tim_oc_id oc_id)
-{
- switch (oc_id) {
- case TIM_OC1:
- TIM_CCER(timer_peripheral) |= TIM_CCER_CC1P;
- break;
- case TIM_OC2:
- TIM_CCER(timer_peripheral) |= TIM_CCER_CC2P;
- break;
- case TIM_OC3:
- TIM_CCER(timer_peripheral) |= TIM_CCER_CC3P;
- break;
- case TIM_OC4:
- TIM_CCER(timer_peripheral) |= TIM_CCER_CC4P;
- break;
- case TIM_OC1N:
- case TIM_OC2N:
- case TIM_OC3N:
- /* Ignoring as this option applies to TIM1 and TIM8 only. */
- break;
- }
-
- /* Acting for TIM1 and TIM8 only from here onwards. */
- if ((timer_peripheral != TIM1) && (timer_peripheral != TIM8))
- return;
-
- switch (oc_id) {
- case TIM_OC1N:
- TIM_CCER(timer_peripheral) |= TIM_CCER_CC1NP;
- break;
- case TIM_OC2N:
- TIM_CCER(timer_peripheral) |= TIM_CCER_CC2NP;
- break;
- case TIM_OC3N:
- TIM_CCER(timer_peripheral) |= TIM_CCER_CC3NP;
- break;
- case TIM_OC1:
- case TIM_OC2:
- case TIM_OC3:
- case TIM_OC4:
- /* Ignoring as this option was already set above. */
- break;
- }
-}
-
-void timer_enable_oc_output(u32 timer_peripheral, enum tim_oc_id oc_id)
-{
- switch (oc_id) {
- case TIM_OC1:
- TIM_CCER(timer_peripheral) |= TIM_CCER_CC1E;
- break;
- case TIM_OC2:
- TIM_CCER(timer_peripheral) |= TIM_CCER_CC2E;
- break;
- case TIM_OC3:
- TIM_CCER(timer_peripheral) |= TIM_CCER_CC3E;
- break;
- case TIM_OC4:
- TIM_CCER(timer_peripheral) |= TIM_CCER_CC4E;
- break;
- case TIM_OC1N:
- case TIM_OC2N:
- case TIM_OC3N:
- /* Ignoring as this option applies to TIM1 and TIM8 only. */
- break;
- }
-
- /* Acting for TIM1 and TIM8 only from here onwards. */
- if ((timer_peripheral != TIM1) && (timer_peripheral != TIM8))
- return;
-
- switch (oc_id) {
- case TIM_OC1N:
- TIM_CCER(timer_peripheral) |= TIM_CCER_CC1NE;
- break;
- case TIM_OC2N:
- TIM_CCER(timer_peripheral) |= TIM_CCER_CC2NE;
- break;
- case TIM_OC3N:
- TIM_CCER(timer_peripheral) |= TIM_CCER_CC3NE;
- break;
- case TIM_OC1:
- case TIM_OC2:
- case TIM_OC3:
- case TIM_OC4:
- /* Ignoring as this option was already set above. */
- break;
- }
-}
-
-void timer_disable_oc_output(u32 timer_peripheral, enum tim_oc_id oc_id)
-{
- switch (oc_id) {
- case TIM_OC1:
- TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC1E;
- break;
- case TIM_OC2:
- TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC2E;
- break;
- case TIM_OC3:
- TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC3E;
- break;
- case TIM_OC4:
- TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC4E;
- break;
- case TIM_OC1N:
- case TIM_OC2N:
- case TIM_OC3N:
- /* Ignoring as this option applies to TIM1 and TIM8 only. */
- break;
- }
-
- /* Acting for TIM1 and TIM8 only from here onwards. */
- if ((timer_peripheral != TIM1) && (timer_peripheral != TIM8))
- return;
-
- switch (oc_id) {
- case TIM_OC1N:
- TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC1NE;
- break;
- case TIM_OC2N:
- TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC2NE;
- break;
- case TIM_OC3N:
- TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC3NE;
- break;
- case TIM_OC1:
- case TIM_OC2:
- case TIM_OC3:
- case TIM_OC4:
- /* Ignoring as this option was already set above. */
- break;
- }
-}
-
-void timer_set_oc_idle_state_set(u32 timer_peripheral, enum tim_oc_id oc_id)
-{
- /* Acting for TIM1 and TIM8 only. */
- if ((timer_peripheral != TIM1) && (timer_peripheral != TIM8))
- return;
-
- switch (oc_id) {
- case TIM_OC1:
- TIM_CR2(timer_peripheral) |= TIM_CR2_OIS1;
- break;
- case TIM_OC1N:
- TIM_CR2(timer_peripheral) |= TIM_CR2_OIS1N;
- break;
- case TIM_OC2:
- TIM_CR2(timer_peripheral) |= TIM_CR2_OIS2;
- break;
- case TIM_OC2N:
- TIM_CR2(timer_peripheral) |= TIM_CR2_OIS2N;
- break;
- case TIM_OC3:
- TIM_CR2(timer_peripheral) |= TIM_CR2_OIS3;
- break;
- case TIM_OC3N:
- TIM_CR2(timer_peripheral) |= TIM_CR2_OIS3N;
- break;
- case TIM_OC4:
- TIM_CR2(timer_peripheral) |= TIM_CR2_OIS4;
- break;
- }
-}
-
-void timer_set_oc_idle_state_unset(u32 timer_peripheral, enum tim_oc_id oc_id)
-{
- /* Acting for TIM1 and TIM8 only. */
- if ((timer_peripheral != TIM1) && (timer_peripheral != TIM8))
- return;
-
- switch (oc_id) {
- case TIM_OC1:
- TIM_CR2(timer_peripheral) &= ~TIM_CR2_OIS1;
- break;
- case TIM_OC1N:
- TIM_CR2(timer_peripheral) &= ~TIM_CR2_OIS1N;
- break;
- case TIM_OC2:
- TIM_CR2(timer_peripheral) &= ~TIM_CR2_OIS2;
- break;
- case TIM_OC2N:
- TIM_CR2(timer_peripheral) &= ~TIM_CR2_OIS2N;
- break;
- case TIM_OC3:
- TIM_CR2(timer_peripheral) &= ~TIM_CR2_OIS3;
- break;
- case TIM_OC3N:
- TIM_CR2(timer_peripheral) &= ~TIM_CR2_OIS3N;
- break;
- case TIM_OC4:
- TIM_CR2(timer_peripheral) &= ~TIM_CR2_OIS4;
- break;
- }
-}
-
-void timer_set_oc_value(u32 timer_peripheral, enum tim_oc_id oc_id, u32 value)
-{
- switch (oc_id) {
- case TIM_OC1:
- TIM_CCR1(timer_peripheral) = value;
- break;
- case TIM_OC2:
- TIM_CCR2(timer_peripheral) = value;
- break;
- case TIM_OC3:
- TIM_CCR3(timer_peripheral) = value;
- break;
- case TIM_OC4:
- TIM_CCR4(timer_peripheral) = value;
- break;
- case TIM_OC1N:
- case TIM_OC2N:
- case TIM_OC3N:
- /* Ignoring as this option applies to the whole channel. */
- break;
- }
-}
-
-void timer_enable_break_main_output(u32 timer_peripheral)
-{
- if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_BDTR(timer_peripheral) |= TIM_BDTR_MOE;
-}
-
-void timer_disable_break_main_output(u32 timer_peripheral)
-{
- if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_BDTR(timer_peripheral) &= ~TIM_BDTR_MOE;
-}
-
-void timer_enable_break_automatic_output(u32 timer_peripheral)
-{
- if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_BDTR(timer_peripheral) |= TIM_BDTR_AOE;
-}
-
-void timer_disable_break_automatic_output(u32 timer_peripheral)
-{
- if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_BDTR(timer_peripheral) &= ~TIM_BDTR_AOE;
-}
-
-void timer_set_break_polarity_high(u32 timer_peripheral)
-{
- if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_BDTR(timer_peripheral) |= TIM_BDTR_BKP;
-}
-
-void timer_set_break_polarity_low(u32 timer_peripheral)
-{
- if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_BDTR(timer_peripheral) &= ~TIM_BDTR_BKP;
-}
-
-void timer_enable_break(u32 timer_peripheral)
-{
- if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_BDTR(timer_peripheral) |= TIM_BDTR_BKE;
-}
-
-void timer_disable_break(u32 timer_peripheral)
-{
- if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_BDTR(timer_peripheral) &= ~TIM_BDTR_BKE;
-}
-
-void timer_set_enabled_off_state_in_run_mode(u32 timer_peripheral)
-{
- if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_BDTR(timer_peripheral) |= TIM_BDTR_OSSR;
-}
-
-void timer_set_disabled_off_state_in_run_mode(u32 timer_peripheral)
-{
- if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_BDTR(timer_peripheral) &= ~TIM_BDTR_OSSR;
-}
-
-void timer_set_enabled_off_state_in_idle_mode(u32 timer_peripheral)
-{
- if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_BDTR(timer_peripheral) |= TIM_BDTR_OSSI;
-}
-
-void timer_set_disabled_off_state_in_idle_mode(u32 timer_peripheral)
-{
- if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_BDTR(timer_peripheral) &= ~TIM_BDTR_OSSI;
-}
-
-void timer_set_break_lock(u32 timer_peripheral, u32 lock)
-{
- if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_BDTR(timer_peripheral) |= lock;
-}
-
-void timer_set_deadtime(u32 timer_peripheral, u32 deadtime)
-{
- if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_BDTR(timer_peripheral) |= deadtime;
-}
-
-void timer_generate_event(u32 timer_peripheral, u32 event)
-{
- TIM_EGR(timer_peripheral) |= event;
-}
-
-u32 timer_get_counter(u32 timer_peripheral)
-{
- return TIM_CNT(timer_peripheral);
-}
-
-void timer_set_option(u32 timer_peripheral, u32 option)
-{
- if (timer_peripheral == TIM2) {
- TIM_OR(timer_peripheral) &= ~TIM2_OR_ITR1_RMP_MASK;
- TIM_OR(timer_peripheral) |= option;
- } else if (timer_peripheral == TIM5) {
- TIM_OR(timer_peripheral) &= ~TIM5_OR_TI4_RMP_MASK;
- TIM_OR(timer_peripheral) |= option;
- }
-}
diff --git a/lib/stm32/f2/usart.c b/lib/stm32/f2/usart.c
new file mode 100644
index 0000000..225b706
--- /dev/null
+++ b/lib/stm32/f2/usart.c
@@ -0,0 +1,28 @@
+/** @defgroup usart_file USART
+
+@ingroup STM32F2xx
+
+@brief <b>libopencm3 STM32F2xx USART</b>
+
+*/
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/usart.h>
+#include <libopencm3/stm32/common/usart_common_all.h>
+
diff --git a/lib/stm32/f2/vector.c b/lib/stm32/f2/vector.c
deleted file mode 100644
index 3429bfb..0000000
--- a/lib/stm32/f2/vector.c
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- * This file is part of the libopencm3 project.
- *
- * Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
- * Copyright (C) 2011 Fergus Noble <fergusnoble@gmail.com>
- *
- * This library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define WEAK __attribute__ ((weak))
-
-/* Symbols exported by the linker script(s): */
-extern unsigned _data_loadaddr, _data, _edata, _ebss, _stack;
-
-void main(void);
-void reset_handler(void);
-void blocking_handler(void);
-void null_handler(void);
-
-void WEAK reset_handler(void);
-void WEAK nmi_handler(void);
-void WEAK hard_fault_handler(void);
-void WEAK mem_manage_handler(void);
-void WEAK bus_fault_handler(void);
-void WEAK usage_fault_handler(void);
-void WEAK sv_call_handler(void);
-void WEAK debug_monitor_handler(void);
-void WEAK pend_sv_handler(void);
-void WEAK sys_tick_handler(void);
-void WEAK wwdg_isr(void);
-void WEAK pvd_isr(void);
-void WEAK tamp_stamp_isr(void);
-void WEAK rtc_wkup_isr(void);
-void WEAK flash_isr(void);
-void WEAK rcc_isr(void);
-void WEAK exti0_isr(void);
-void WEAK exti1_isr(void);
-void WEAK exti2_isr(void);
-void WEAK exti3_isr(void);
-void WEAK exti4_isr(void);
-void WEAK dma1_stream0_isr(void);
-void WEAK dma1_stream1_isr(void);
-void WEAK dma1_stream2_isr(void);
-void WEAK dma1_stream3_isr(void);
-void WEAK dma1_stream4_isr(void);
-void WEAK dma1_stream5_isr(void);
-void WEAK dma1_stream6_isr(void);
-void WEAK adc_isr(void);
-void WEAK can1_tx_isr(void);
-void WEAK can1_rx0_isr(void);
-void WEAK can1_rx1_isr(void);
-void WEAK can1_sce_isr(void);
-void WEAK exti9_5_isr(void);
-void WEAK tim1_brk_tim9_isr(void);
-void WEAK tim1_up_tim10_isr(void);
-void WEAK tim1_trg_com_tim11_isr(void);
-void WEAK tim1_cc_isr(void);
-void WEAK tim2_isr(void);
-void WEAK tim3_isr(void);
-void WEAK tim4_isr(void);
-void WEAK i2c1_ev_isr(void);
-void WEAK i2c1_er_isr(void);
-void WEAK i2c2_ev_isr(void);
-void WEAK i2c2_er_isr(void);
-void WEAK spi1_isr(void);
-void WEAK spi2_isr(void);
-void WEAK usart1_isr(void);
-void WEAK usart2_isr(void);
-void WEAK usart3_isr(void);
-void WEAK exti15_10_isr(void);
-void WEAK rtc_alarm_isr(void);
-void WEAK usb_fs_wkup_isr(void);
-void WEAK tim8_brk_tim12_isr(void);
-void WEAK tim8_up_tim13_isr(void);
-void WEAK tim8_trg_com_tim14_isr(void);
-void WEAK tim8_cc_isr(void);
-void WEAK dma1_stream7_isr(void);
-void WEAK fsmc_isr(void);
-void WEAK sdio_isr(void);
-void WEAK tim5_isr(void);
-void WEAK spi3_isr(void);
-void WEAK uart4_isr(void);
-void WEAK uart5_isr(void);
-void WEAK tim6_dac_isr(void);
-void WEAK tim7_isr(void);
-void WEAK dma2_stream0_isr(void);
-void WEAK dma2_stream1_isr(void);
-void WEAK dma2_stream2_isr(void);
-void WEAK dma2_stream3_isr(void);
-void WEAK dma2_stream4_isr(void);
-void WEAK eth_isr(void);
-void WEAK eth_wkup_isr(void);
-void WEAK can2_tx_isr(void);
-void WEAK can2_rx0_isr(void);
-void WEAK can2_rx1_isr(void);
-void WEAK can2_sce_isr(void);
-void WEAK otg_fs_isr(void);
-void WEAK dma2_stream5_isr(void);
-void WEAK dma2_stream6_isr(void);
-void WEAK dma2_stream7_isr(void);
-void WEAK usart6_isr(void);
-void WEAK i2c3_ev_isr(void);
-void WEAK i2c3_er_isr(void);
-void WEAK otg_hs_ep1_out_isr(void);
-void WEAK otg_hs_ep1_in_isr(void);
-void WEAK otg_hs_wkup_isr(void);
-void WEAK otg_hs_isr(void);
-void WEAK dcmi_isr(void);
-void WEAK cryp_isr(void);
-void WEAK hash_rng_isr(void);
-
-__attribute__ ((section(".vectors")))
-void (*const vector_table[]) (void) = {
- (void *)&_stack,
- reset_handler,
- nmi_handler,
- hard_fault_handler,
- mem_manage_handler,
- bus_fault_handler,
- usage_fault_handler,
- 0, 0, 0, 0, /* Reserved */
- sv_call_handler,
- debug_monitor_handler,
- 0, /* Reserved */
- pend_sv_handler,
- sys_tick_handler,
- wwdg_isr,
- pvd_isr,
- tamp_stamp_isr,
- rtc_wkup_isr,
- flash_isr,
- rcc_isr,
- exti0_isr,
- exti1_isr,
- exti2_isr,
- exti3_isr,
- exti4_isr,
- dma1_stream0_isr,
- dma1_stream1_isr,
- dma1_stream2_isr,
- dma1_stream3_isr,
- dma1_stream4_isr,
- dma1_stream5_isr,
- dma1_stream6_isr,
- adc_isr,
- can1_tx_isr,
- can1_rx0_isr,
- can1_rx1_isr,
- can1_sce_isr,
- exti9_5_isr,
- tim1_brk_tim9_isr,
- tim1_up_tim10_isr,
- tim1_trg_com_tim11_isr,
- tim1_cc_isr,
- tim2_isr,
- tim3_isr,
- tim4_isr,
- i2c1_ev_isr,
- i2c1_er_isr,
- i2c2_ev_isr,
- i2c2_er_isr,
- spi1_isr,
- spi2_isr,
- usart1_isr,
- usart2_isr,
- usart3_isr,
- exti15_10_isr,
- rtc_alarm_isr,
- usb_fs_wkup_isr,
- tim8_brk_tim12_isr,
- tim8_up_tim13_isr,
- tim8_trg_com_tim14_isr,
- tim8_cc_isr,
- dma1_stream7_isr,
- fsmc_isr,
- sdio_isr,
- tim5_isr,
- spi3_isr,
- uart4_isr,
- uart5_isr,
- tim6_dac_isr,
- tim7_isr,
- dma2_stream0_isr,
- dma2_stream1_isr,
- dma2_stream2_isr,
- dma2_stream3_isr,
- dma2_stream4_isr,
- eth_isr,
- eth_wkup_isr,
- can2_tx_isr,
- can2_rx0_isr,
- can2_rx1_isr,
- can2_sce_isr,
- otg_fs_isr,
- dma2_stream5_isr,
- dma2_stream6_isr,
- dma2_stream7_isr,
- usart6_isr,
- i2c3_ev_isr,
- i2c3_er_isr,
- otg_hs_ep1_out_isr,
- otg_hs_ep1_in_isr,
- otg_hs_wkup_isr,
- otg_hs_isr,
- dcmi_isr,
- cryp_isr,
- hash_rng_isr,
-};
-
-void reset_handler(void)
-{
- volatile unsigned *src, *dest;
-
- __asm__("MSR msp, %0" : : "r"(&_stack));
-
- for (src = &_data_loadaddr, dest = &_data; dest < &_edata; src++, dest++)
- *dest = *src;
-
- while (dest < &_ebss)
- *dest++ = 0;
-
- /* Call the application's entry point. */
- main();
-}
-
-void blocking_handler(void)
-{
- while (1) ;
-}
-
-void null_handler(void)
-{
- /* Do nothing. */
-}
-
-#pragma weak nmi_handler = null_handler
-#pragma weak hard_fault_handler = blocking_handler
-#pragma weak mem_manage_handler = blocking_handler
-#pragma weak bus_fault_handler = blocking_handler
-#pragma weak usage_fault_handler = blocking_handler
-#pragma weak sv_call_handler = null_handler
-#pragma weak debug_monitor_handler = null_handler
-#pragma weak pend_sv_handler = null_handler
-#pragma weak sys_tick_handler = null_handler
-#pragma weak wwdg_isr = null_handler
-#pragma weak pvd_isr = null_handler
-#pragma weak tamp_stamp_isr = null_handler
-#pragma weak rtc_wkup_isr = null_handler
-#pragma weak flash_isr = null_handler
-#pragma weak rcc_isr = null_handler
-#pragma weak exti0_isr = null_handler
-#pragma weak exti1_isr = null_handler
-#pragma weak exti2_isr = null_handler
-#pragma weak exti3_isr = null_handler
-#pragma weak exti4_isr = null_handler
-#pragma weak dma1_stream0_isr = null_handler
-#pragma weak dma1_stream1_isr = null_handler
-#pragma weak dma1_stream2_isr = null_handler
-#pragma weak dma1_stream3_isr = null_handler
-#pragma weak dma1_stream4_isr = null_handler
-#pragma weak dma1_stream5_isr = null_handler
-#pragma weak dma1_stream6_isr = null_handler
-#pragma weak adc_isr = null_handler
-#pragma weak can1_tx_isr = null_handler
-#pragma weak can1_rx0_isr = null_handler
-#pragma weak can1_rx1_isr = null_handler
-#pragma weak can1_sce_isr = null_handler
-#pragma weak exti9_5_isr = null_handler
-#pragma weak tim1_brk_tim9_isr = null_handler
-#pragma weak tim1_up_tim10_isr = null_handler
-#pragma weak tim1_trg_com_tim11_isr = null_handler
-#pragma weak tim1_cc_isr = null_handler
-#pragma weak tim2_isr = null_handler
-#pragma weak tim3_isr = null_handler
-#pragma weak tim4_isr = null_handler
-#pragma weak i2c1_ev_isr = null_handler
-#pragma weak i2c1_er_isr = null_handler
-#pragma weak i2c2_ev_isr = null_handler
-#pragma weak i2c2_er_isr = null_handler
-#pragma weak spi1_isr = null_handler
-#pragma weak spi2_isr = null_handler
-#pragma weak usart1_isr = null_handler
-#pragma weak usart2_isr = null_handler
-#pragma weak usart3_isr = null_handler
-#pragma weak exti15_10_isr = null_handler
-#pragma weak rtc_alarm_isr = null_handler
-#pragma weak usb_fs_wkup_isr = null_handler
-#pragma weak tim8_brk_tim12_isr = null_handler
-#pragma weak tim8_up_tim13_isr = null_handler
-#pragma weak tim8_trg_com_tim14_isr = null_handler
-#pragma weak tim8_cc_isr = null_handler
-#pragma weak dma1_stream7_isr = null_handler
-#pragma weak fsmc_isr = null_handler
-#pragma weak sdio_isr = null_handler
-#pragma weak tim5_isr = null_handler
-#pragma weak spi3_isr = null_handler
-#pragma weak uart4_isr = null_handler
-#pragma weak uart5_isr = null_handler
-#pragma weak tim6_dac_isr = null_handler
-#pragma weak tim7_isr = null_handler
-#pragma weak dma2_stream0_isr = null_handler
-#pragma weak dma2_stream1_isr = null_handler
-#pragma weak dma2_stream2_isr = null_handler
-#pragma weak dma2_stream3_isr = null_handler
-#pragma weak dma2_stream4_isr = null_handler
-#pragma weak eth_isr = null_handler
-#pragma weak eth_wkup_isr = null_handler
-#pragma weak can2_tx_isr = null_handler
-#pragma weak can2_rx0_isr = null_handler
-#pragma weak can2_rx1_isr = null_handler
-#pragma weak can2_sce_isr = null_handler
-#pragma weak otg_fs_isr = null_handler
-#pragma weak dma2_stream5_isr = null_handler
-#pragma weak dma2_stream6_isr = null_handler
-#pragma weak dma2_stream7_isr = null_handler
-#pragma weak usart6_isr = null_handler
-#pragma weak i2c3_ev_isr = null_handler
-#pragma weak i2c3_er_isr = null_handler
-#pragma weak otg_hs_ep1_out_isr = null_handler
-#pragma weak otg_hs_ep1_in_isr = null_handler
-#pragma weak otg_hs_wkup_isr = null_handler
-#pragma weak otg_hs_isr = null_handler
-#pragma weak dcmi_isr = null_handler
-#pragma weak cryp_isr = null_handler
-#pragma weak hash_rng_isr = null_handler
diff --git a/lib/stm32/f4/Makefile b/lib/stm32/f4/Makefile
index fd0b279..8ff7c6a 100644
--- a/lib/stm32/f4/Makefile
+++ b/lib/stm32/f4/Makefile
@@ -29,11 +29,15 @@ CFLAGS = -Os -g -Wall -Wextra -I../../../include -fno-common \
-ffunction-sections -fdata-sections -MD -DSTM32F4
# ARFLAGS = rcsv
ARFLAGS = rcs
-OBJS = vector.o rcc.o gpio.o usart.o spi.o flash.o nvic.o \
- i2c.o systick.o exti.o scb.o pwr.o timer.o \
- usb.o usb_standard.o usb_control.o usb_f107.o \
- assert.o
+OBJS = rcc.o gpio.o flash.o exti2.o pwr.o timer.o \
+ usb.o usb_standard.o usb_control.o usb_fx07_common.o usb_f107.o \
+ usb_f207.o adc.o dma.o \
+ pwr_common_all.o \
+ gpio_common_all.o gpio_common_f24.o dma_common_f24.o spi_common_all.o \
+ dac_common_all.o usart_common_all.o iwdg_common_all.o i2c_common_all.o \
+ crc_common_all.o \
+ rtc_common_bcd.o
-VPATH += ../../usb:../:../../cm3
+VPATH += ../../usb:../:../../cm3:../common
include ../../Makefile.include
diff --git a/lib/stm32/f4/adc.c b/lib/stm32/f4/adc.c
new file mode 100644
index 0000000..aef49a4
--- /dev/null
+++ b/lib/stm32/f4/adc.c
@@ -0,0 +1,1021 @@
+/** @defgroup STM32F4xx_adc_file ADC
+
+@ingroup STM32F4xx
+
+@brief <b>libopencm3 STM32F4xx Analog to Digital Converters</b>
+
+@author @htmlonly &copy; @endhtmlonly 2012 Ken Sarkies <ksarkies@internode.on.net>
+
+@date 30 August 2012
+
+This library supports the A/D Converter Control System in the STM32 series
+of ARM Cortex Microcontrollers by ST Microelectronics.
+
+Devices can have up to three A/D converters each with their own set of registers.
+However all the A/D converters share a common clock which is prescaled from the APB2
+clock by default by a minimum factor of 2 to a maximum of 8. The ADC resolution
+can be set to 12, 10, 8 or 6 bits.
+
+Each A/D converter has up to 19 channels:
+@li On ADC1 the analog channels 16 is internally connected to the temperature
+sensor, channel 17 to V<sub>REFINT</sub>, and channel 18 to V<sub>BATT</sub>.
+@li On ADC2 and ADC3 the analog channels 16 - 18 are not used.
+
+The conversions can occur as a one-off conversion whereby the process stops once
+conversion is complete. The conversions can also be continuous wherein a new
+conversion starts immediately the previous conversion has ended.
+
+Conversion can occur as a single channel conversion or a scan of a group of
+channels in either continuous or one-off mode. If more than one channel is converted
+in a scan group, DMA must be used to transfer the data as there is only one
+result register available. An interrupt can be set to occur at the end of
+conversion, which occurs after all channels have been scanned.
+
+A discontinuous mode allows a subgroup of group of a channels to be converted in
+bursts of a given length.
+
+Injected conversions allow a second group of channels to be converted separately
+from the regular group. An interrupt can be set to occur at the end of
+conversion, which occurs after all channels have been scanned.
+
+@section adc_f4_api_ex Basic ADC Handling API.
+
+Example 1: Simple single channel conversion polled. Enable the peripheral clock
+and ADC, reset ADC and set the prescaler divider. Set multiple mode to independent.
+
+@code
+gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO1);
+rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_ADC1EN);
+adc_set_clk_prescale(RCC_CFGR_ADCPRE_BY2);
+adc_disable_scan_mode(ADC1);
+adc_set_single_conversion_mode(ADC1);
+adc_set_sample_time(ADC1, ADC_CHANNEL0, ADC_SMPR1_SMP_1DOT5CYC);
+u8 channels[] = ADC_CHANNEL0;
+adc_set_regular_sequence(ADC1, 1, channels);
+adc_set_multi_mode(ADC_CCR_MULTI_INDEPENDENT);
+adc_power_on(ADC1);
+adc_start_conversion_regular(ADC1);
+while (! adc_eoc(ADC1));
+reg16 = adc_read_regular(ADC1);
+@endcode
+
+LGPL License Terms @ref lgpl_license
+ */
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2012 Ken Sarkies <ksarkies@internode.on.net>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/f4/adc.h>
+
+/**@{*/
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Off
+
+Turn off the ADC to reduce power consumption to a few microamps.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_off(u32 adc)
+{
+ ADC_CR2(adc) &= ~ADC_CR2_ADON;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Enable Analog Watchdog for Regular Conversions
+
+The analog watchdog allows the monitoring of an analog signal between two threshold
+levels. The thresholds must be preset. Comparison is done before data alignment
+takes place, so the thresholds are left-aligned.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_enable_analog_watchdog_regular(u32 adc)
+{
+ ADC_CR1(adc) |= ADC_CR1_AWDEN;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Disable Analog Watchdog for Regular Conversions
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_disable_analog_watchdog_regular(u32 adc)
+{
+ ADC_CR1(adc) &= ~ADC_CR1_AWDEN;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Enable Analog Watchdog for Injected Conversions
+
+The analog watchdog allows the monitoring of an analog signal between two threshold
+levels. The thresholds must be preset. Comparison is done before data alignment
+takes place, so the thresholds are left-aligned.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_enable_analog_watchdog_injected(u32 adc)
+{
+ ADC_CR1(adc) |= ADC_CR1_JAWDEN;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Disable Analog Watchdog for Injected Conversions
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_disable_analog_watchdog_injected(u32 adc)
+{
+ ADC_CR1(adc) &= ~ADC_CR1_JAWDEN;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Enable Discontinuous Mode for Regular Conversions
+
+In this mode the ADC converts, on each trigger, a subgroup of up to 8 of the
+defined regular channel group. The subgroup is defined by the number of
+consecutive channels to be converted. After a subgroup has been converted
+the next trigger will start conversion of the immediately following subgroup
+of the same length or until the whole group has all been converted. When the
+the whole group has been converted, the next trigger will restart conversion
+of the subgroup at the beginning of the whole group.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] length Unsigned int8. Number of channels in the group @ref adc_cr1_discnum
+*/
+
+void adc_enable_discontinuous_mode_regular(u32 adc, u8 length)
+{
+ if ( (length-1) > 7 ) return;
+ ADC_CR1(adc) |= ADC_CR1_DISCEN;
+ ADC_CR2(adc) |= ((length-1) << ADC_CR1_DISCNUM_SHIFT);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Disable Discontinuous Mode for Regular Conversions
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_disable_discontinuous_mode_regular(u32 adc)
+{
+ ADC_CR1(adc) &= ~ADC_CR1_DISCEN;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Enable Discontinuous Mode for Injected Conversions
+
+In this mode the ADC converts sequentially one channel of the defined group of
+injected channels, cycling back to the first channel in the group once the
+entire group has been converted.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_enable_discontinuous_mode_injected(u32 adc)
+{
+ ADC_CR1(adc) |= ADC_CR1_JDISCEN;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Disable Discontinuous Mode for Injected Conversions
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_disable_discontinuous_mode_injected(u32 adc)
+{
+ ADC_CR1(adc) &= ~ADC_CR1_JDISCEN;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Enable Automatic Injected Conversions
+
+The ADC converts a defined injected group of channels immediately after the
+regular channels have been converted. The external trigger on the injected
+channels is disabled as required.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_enable_automatic_injected_group_conversion(u32 adc)
+{
+ adc_disable_external_trigger_injected(adc);
+ ADC_CR1(adc) |= ADC_CR1_JAUTO;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Disable Automatic Injected Conversions
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_disable_automatic_injected_group_conversion(u32 adc)
+{
+ ADC_CR1(adc) &= ~ADC_CR1_JAUTO;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Enable Analog Watchdog for All Regular and/or Injected Channels
+
+The analog watchdog allows the monitoring of an analog signal between two threshold
+levels. The thresholds must be preset. Comparison is done before data alignment
+takes place, so the thresholds are left-aligned.
+
+@note The analog watchdog must be enabled for either or both of the regular or
+injected channels. If neither are enabled, the analog watchdog feature will be
+disabled.
+@ref adc_enable_analog_watchdog_injected, @ref adc_enable_analog_watchdog_regular.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_enable_analog_watchdog_on_all_channels(u32 adc)
+{
+ ADC_CR1(adc) &= ~ADC_CR1_AWDSGL;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Enable Analog Watchdog for a Selected Channel
+
+The analog watchdog allows the monitoring of an analog signal between two threshold
+levels. The thresholds must be preset. Comparison is done before data alignment
+takes place, so the thresholds are left-aligned.
+
+@note The analog watchdog must be enabled for either or both of the regular or
+injected channels. If neither are enabled, the analog watchdog feature will be
+disabled. If both are enabled, the same channel number is monitored.
+@ref adc_enable_analog_watchdog_injected, @ref adc_enable_analog_watchdog_regular.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] channel Unsigned int8. ADC channel number @ref adc_watchdog_channel
+*/
+
+void adc_enable_analog_watchdog_on_selected_channel(u32 adc, u8 channel)
+{
+ u32 reg32;
+
+ reg32 = (ADC_CR1(adc) & ~ADC_CR1_AWDCH_MASK); /* Clear bits [4:0]. */
+ if (channel < 18)
+ reg32 |= channel;
+ ADC_CR1(adc) = reg32;
+ ADC_CR1(adc) |= ADC_CR1_AWDSGL;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Set Scan Mode
+
+In this mode a conversion consists of a scan of the predefined set of channels,
+regular and injected, each channel conversion immediately following the
+previous one. It can use single, continuous or discontinuous mode.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_enable_scan_mode(u32 adc)
+{
+ ADC_CR1(adc) |= ADC_CR1_SCAN;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Disable Scan Mode
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_disable_scan_mode(u32 adc)
+{
+ ADC_CR1(adc) &= ~ADC_CR1_SCAN;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Enable Injected End-Of-Conversion Interrupt
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_enable_eoc_interrupt_injected(u32 adc)
+{
+ ADC_CR1(adc) |= ADC_CR1_JEOCIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Disable Injected End-Of-Conversion Interrupt
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_disable_eoc_interrupt_injected(u32 adc)
+{
+ ADC_CR1(adc) &= ~ADC_CR1_JEOCIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Enable Analog Watchdog Interrupt
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_enable_awd_interrupt(u32 adc)
+{
+ ADC_CR1(adc) |= ADC_CR1_AWDIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Disable Analog Watchdog Interrupt
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_disable_awd_interrupt(u32 adc)
+{
+ ADC_CR1(adc) &= ~ADC_CR1_AWDIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Enable Regular End-Of-Conversion Interrupt
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_enable_eoc_interrupt(u32 adc)
+{
+ ADC_CR1(adc) |= ADC_CR1_EOCIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Disable Regular End-Of-Conversion Interrupt
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_disable_eoc_interrupt(u32 adc)
+{
+ ADC_CR1(adc) &= ~ADC_CR1_EOCIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Software Triggered Conversion on Regular Channels
+
+This starts conversion on a set of defined regular channels. It is cleared by
+hardware once conversion starts.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_start_conversion_regular(u32 adc)
+{
+ /* Start conversion on regular channels. */
+ ADC_CR2(adc) |= ADC_CR2_SWSTART;
+
+ /* Wait until the ADC starts the conversion. */
+ while (ADC_CR2(adc) & ADC_CR2_SWSTART);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Software Triggered Conversion on Injected Channels
+
+This starts conversion on a set of defined injected channels. It is cleared by
+hardware once conversion starts.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_start_conversion_injected(u32 adc)
+{
+ /* Start conversion on injected channels. */
+ ADC_CR2(adc) |= ADC_CR2_JSWSTART;
+
+ /* Wait until the ADC starts the conversion. */
+ while (ADC_CR2(adc) & ADC_CR2_JSWSTART);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Set the Data as Left Aligned
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_set_left_aligned(u32 adc)
+{
+ ADC_CR2(adc) |= ADC_CR2_ALIGN;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Set the Data as Right Aligned
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_set_right_aligned(u32 adc)
+{
+ ADC_CR2(adc) &= ~ADC_CR2_ALIGN;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Enable DMA Transfers
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_enable_dma(u32 adc)
+{
+ ADC_CR2(adc) |= ADC_CR2_DMA;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Disable DMA Transfers
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_disable_dma(u32 adc)
+{
+ ADC_CR2(adc) &= ~ADC_CR2_DMA;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Enable Continuous Conversion Mode
+
+In this mode the ADC starts a new conversion of a single channel or a channel
+group immediately following completion of the previous channel group conversion.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_set_continuous_conversion_mode(u32 adc)
+{
+ ADC_CR2(adc) |= ADC_CR2_CONT;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Enable Single Conversion Mode
+
+In this mode the ADC performs a conversion of one channel or a channel group
+and stops.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_set_single_conversion_mode(u32 adc)
+{
+ ADC_CR2(adc) &= ~ADC_CR2_CONT;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Set the Sample Time for a Single Channel
+
+The sampling time can be selected in ADC clock cycles from 1.5 to 239.5.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] channel Unsigned int8. ADC Channel integer 0..18 or from @ref adc_channel
+@param[in] time Unsigned int8. Sampling time selection from @ref adc_sample_rg
+*/
+
+void adc_set_sample_time(u32 adc, u8 channel, u8 time)
+{
+ u32 reg32;
+
+ if (channel < 10) {
+ reg32 = ADC_SMPR2(adc);
+ reg32 &= ~(0x7 << (channel * 3));
+ reg32 |= (time << (channel * 3));
+ ADC_SMPR2(adc) = reg32;
+ } else {
+ reg32 = ADC_SMPR1(adc);
+ reg32 &= ~(0x7 << ((channel - 10) * 3));
+ reg32 |= (time << ((channel - 10) * 3));
+ ADC_SMPR1(adc) = reg32;
+ }
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Set the Sample Time for All Channels
+
+The sampling time can be selected in ADC clock cycles from 1.5 to 239.5, same for
+all channels.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] time Unsigned int8. Sampling time selection from @ref adc_sample_rg
+*/
+
+void adc_set_sample_time_on_all_channels(u32 adc, u8 time)
+{
+ u8 i;
+ u32 reg32 = 0;
+
+ for (i = 0; i <= 9; i++)
+ reg32 |= (time << (i * 3));
+ ADC_SMPR2(adc) = reg32;
+
+ for (i = 10; i <= 17; i++)
+ reg32 |= (time << ((i - 10) * 3));
+ ADC_SMPR1(adc) = reg32;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Set Analog Watchdog Upper Threshold
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] threshold Unsigned int8. Upper threshold value
+*/
+
+void adc_set_watchdog_high_threshold(u32 adc, u16 threshold)
+{
+ u32 reg32 = 0;
+
+ reg32 = (u32)threshold;
+ reg32 &= ~0xfffff000; /* Clear all bits above 11. */
+ ADC_HTR(adc) = reg32;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Set Analog Watchdog Lower Threshold
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] threshold Unsigned int8. Lower threshold value
+*/
+
+void adc_set_watchdog_low_threshold(u32 adc, u16 threshold)
+{
+ u32 reg32 = 0;
+
+ reg32 = (u32)threshold;
+ reg32 &= ~0xfffff000; /* Clear all bits above 11. */
+ ADC_LTR(adc) = reg32;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Set a Regular Channel Conversion Sequence
+
+Define a sequence of channels to be converted as a regular group with a length
+from 1 to 16 channels. If this is called during conversion, the current conversion
+is reset and conversion begins again with the newly defined group.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] length Unsigned int8. Number of channels in the group.
+@param[in] channel Unsigned int8[]. Set of channels in sequence, integers 0..18.
+*/
+
+void adc_set_regular_sequence(u32 adc, u8 length, u8 channel[])
+{
+ u32 reg32_1 = 0, reg32_2 = 0, reg32_3 = 0;
+ u8 i = 0;
+
+ /* Maximum sequence length is 16 channels. */
+ if (length > 16)
+ return;
+
+ for (i = 1; i <= length; i++) {
+ if (i <= 6)
+ reg32_3 |= (channel[i - 1] << ((i - 1) * 5));
+ if ((i > 6) & (i <= 12))
+ reg32_2 |= (channel[i - 1] << ((i - 6 - 1) * 5));
+ if ((i > 12) & (i <= 16))
+ reg32_1 |= (channel[i - 1] << ((i - 12 - 1) * 5));
+ }
+ reg32_1 |= ((length -1) << ADC_SQR1_L_LSB);
+
+ ADC_SQR1(adc) = reg32_1;
+ ADC_SQR2(adc) = reg32_2;
+ ADC_SQR3(adc) = reg32_3;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Set an Injected Channel Conversion Sequence
+
+Defines a sequence of channels to be converted as an injected group with a length
+from 1 to 4 channels. If this is called during conversion, the current conversion
+is reset and conversion begins again with the newly defined group.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] length Unsigned int8. Number of channels in the group.
+@param[in] channel Unsigned int8[]. Set of channels in sequence, integers 0..18
+*/
+
+void adc_set_injected_sequence(u32 adc, u8 length, u8 channel[])
+{
+ u32 reg32 = 0;
+ u8 i = 0;
+
+ /* Maximum sequence length is 4 channels. */
+ if ((length-1) > 3)
+ return;
+
+ for (i = 1; i <= length; i++)
+ reg32 |= (channel[4 - i] << ((4 - i) * 5));
+
+ reg32 |= ((length - 1) << ADC_JSQR_JL_LSB);
+
+ ADC_JSQR(adc) = reg32;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Read the End-of-Conversion Flag
+
+This flag is set after all channels of a regular or injected group have been
+converted.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@returns bool. End of conversion flag.
+*/
+
+bool adc_eoc(u32 adc)
+{
+ return ((ADC_SR(adc) & ADC_SR_EOC) != 0);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Read the End-of-Conversion Flag for Injected Conversion
+
+This flag is set after all channels of an injected group have been converted.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@returns bool. End of conversion flag.
+*/
+
+bool adc_eoc_injected(u32 adc)
+{
+ return ((ADC_SR(adc) & ADC_SR_JEOC) != 0);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Read from the Regular Conversion Result Register
+
+The result read back is 12 bits, right or left aligned within the first 16 bits.
+For ADC1 only, the higher 16 bits will hold the result from ADC2 if
+an appropriate dual mode has been set @see adc_set_dual_mode.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@returns Unsigned int32 conversion result.
+*/
+
+u32 adc_read_regular(u32 adc)
+{
+ return ADC_DR(adc);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Read from an Injected Conversion Result Register
+
+The result read back from the selected injected result register (one of four) is
+12 bits, right or left aligned within the first 16 bits. The result can have a
+negative value if the injected channel offset has been set @see adc_set_injected_offset.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] reg Unsigned int8. Register number (1 ... 4).
+@returns Unsigned int32 conversion result.
+*/
+
+u32 adc_read_injected(u32 adc, u8 reg)
+{
+ switch (reg) {
+ case 1:
+ return ADC_JDR1(adc);
+ case 2:
+ return ADC_JDR2(adc);
+ case 3:
+ return ADC_JDR3(adc);
+ case 4:
+ return ADC_JDR4(adc);
+ }
+ return 0;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Set the Injected Channel Data Offset
+
+This value is subtracted from the injected channel results after conversion
+is complete, and can result in negative results. A separate value can be specified
+for each injected data register.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] reg Unsigned int8. Register number (1 ... 4).
+@param[in] offset Unsigned int32.
+*/
+
+void adc_set_injected_offset(u32 adc, u8 reg, u32 offset)
+{
+ switch (reg) {
+ case 1:
+ ADC_JOFR1(adc) = offset;
+ break;
+ case 2:
+ ADC_JOFR2(adc) = offset;
+ break;
+ case 3:
+ ADC_JOFR3(adc) = offset;
+ break;
+ case 4:
+ ADC_JOFR4(adc) = offset;
+ break;
+ }
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Power On
+
+If the ADC is in power-down mode then it is powered up. The application needs
+to wait a time of about 3 microseconds for stabilization before using the ADC.
+If the ADC is already on this function call will have no effect.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_power_on(u32 adc)
+{
+ ADC_CR2(adc) |= ADC_CR2_ADON;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Set Clock Prescale
+
+The ADC clock taken from the APB2 clock can be scaled down by 2, 4, 6 or 8.
+
+@param[in] prescale Unsigned int32. Prescale value for ADC Clock @ref adc_ccr_adcpre
+*/
+
+void adc_set_clk_prescale(u32 prescale)
+{
+ u32 reg32 = ((ADC_CCR & ~ADC_CCR_ADCPRE_MASK) | prescale);
+ ADC_CCR = reg32;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Set Dual/Triple Mode
+
+The multiple mode uses ADC1 as master, ADC2 and optionally ADC3 in a slave
+arrangement. This setting is applied to ADC1 only.
+
+The various modes possible are described in the reference manual.
+
+@param[in] mode Unsigned int32. Multiple mode selection from @ref adc_multi_mode
+*/
+
+void adc_set_multi_mode(u32 mode)
+{
+ ADC_CCR |= mode;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Enable an External Trigger for Regular Channels
+
+This enables an external trigger for set of defined regular channels, and sets the
+polarity of the trigger event: rising or falling edge or both. Note that if the
+trigger polarity is zero, triggering is disabled.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] trigger Unsigned int32. Trigger identifier @ref adc_trigger_regular
+@param[in] polarity Unsigned int32. Trigger polarity @ref adc_trigger_polarity_regular
+*/
+
+void adc_enable_external_trigger_regular(u32 adc, u32 trigger, u32 polarity)
+{
+ u32 reg32 = ADC_CR2(adc);
+
+ reg32 &= ~(ADC_CR2_EXTSEL_MASK | ADC_CR2_EXTEN_MASK);
+ reg32 |= (trigger | polarity);
+ ADC_CR2(adc) = reg32;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Disable an External Trigger for Regular Channels
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_disable_external_trigger_regular(u32 adc)
+{
+ ADC_CR2(adc) &= ~ADC_CR2_EXTEN_MASK;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Enable an External Trigger for Injected Channels
+
+This enables an external trigger for set of defined injected channels, and sets the
+polarity of the trigger event: rising or falling edge or both.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] trigger Unsigned int8. Trigger identifier @ref adc_trigger_injected
+@param[in] polarity Unsigned int32. Trigger polarity @ref adc_trigger_polarity_injected
+*/
+
+void adc_enable_external_trigger_injected(u32 adc, u32 trigger, u32 polarity)
+{
+ u32 reg32 = ADC_CR2(adc);
+
+ reg32 &= ~(ADC_CR2_JEXTSEL_MASK | ADC_CR2_JEXTEN_MASK);
+ reg32 |= (trigger | polarity);
+ ADC_CR2(adc) = reg32;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Disable an External Trigger for Injected Channels
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_disable_external_trigger_injected(u32 adc)
+{
+ ADC_CR2(adc) &= ~ADC_CR2_JEXTEN_MASK;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Set Resolution
+
+ADC Resolution can be reduced from 12 bits to 10, 8 or 6 bits for a corresponding
+reduction in conversion time (resolution + 3 ADC clock cycles).
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@param[in] resolution Unsigned int8. Resolution value @ref adc_cr1_res
+*/
+
+void adc_set_resolution(u32 adc, u16 resolution)
+{
+ u32 reg32 = ADC_CR1(adc);
+
+ reg32 &= ~ADC_CR1_RES_MASK;
+ reg32 |= resolution;
+ ADC_CR1(adc) = reg32;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Enable the Overrun Interrupt
+
+The overrun interrupt is generated when data is not read from a result register
+before the next conversion is written. If DMA is enabled, all transfers are
+terminated and any conversion sequence is aborted.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_enable_overrun_interrupt(u32 adc)
+{
+ ADC_CR1(adc) |= ADC_CR1_OVRIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Disable the Overrun Interrupt
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_disable_overrun_interrupt(u32 adc)
+{
+ ADC_CR1(adc) &= ~ADC_CR1_OVRIE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Read the Overrun Flag
+
+The overrun flag is set when data is not read from a result register before the next
+conversion is written. If DMA is enabled, all transfers are terminated and any
+conversion sequence is aborted.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@returns Unsigned int32 conversion result.
+*/
+
+bool adc_get_overrun_flag(u32 adc)
+{
+ return (ADC_SR(adc) & ADC_SR_OVR);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Clear Overrun Flags
+
+The overrun flag is cleared. Note that if an overrun occurs, DMA is terminated.
+The flag must be cleared and the DMA stream and ADC reinitialised to resume
+conversions (see the reference manual).
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@returns Unsigned int32 conversion result.
+*/
+
+void adc_clear_overrun_flag(u32 adc)
+{
+/* need to write zero to clear this */
+ ADC_SR(adc) &= ~ADC_SR_OVR;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Enable an EOC for Each Conversion
+
+The EOC is set after each conversion in a sequence rather than at the end of the
+sequence. Overrun detection is enabled only if DMA is enabled.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_eoc_after_each(u32 adc)
+{
+ ADC_CR2(adc) |= ADC_CR2_EOCS;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Disable the EOC for Each Conversion
+
+The EOC is set at the end of each sequence rather than after each conversion in the
+sequence. Overrun detection is enabled always.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_eoc_after_group(u32 adc)
+{
+ ADC_CR2(adc) &= ~ADC_CR2_EOCS;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Set DMA to Continue
+
+This must be set to allow DMA to continue to operate after the last conversion in
+the DMA sequence. This allows DMA to be used in continuous circular mode.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_set_dma_continue(u32 adc)
+{
+ ADC_CR2(adc) |= ADC_CR2_DDS;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Set DMA to Terminate
+
+This must be set to allow DMA to terminate after the last conversion in the DMA
+sequence. This can avoid overrun errors.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_set_dma_terminate(u32 adc)
+{
+ ADC_CR2(adc) &= ~ADC_CR2_DDS;
+}
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Read the Analog Watchdog Flag
+
+This flag is set when the converted voltage crosses the high or low thresholds.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+@returns bool. AWD flag.
+*/
+
+bool adc_awd(u32 adc)
+{
+ return (ADC_SR(adc) & ADC_SR_AWD);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Enable The Temperature Sensor
+
+This enables both the sensor and the reference voltage measurements on channels
+16 and 17. These are only available on ADC1 channel 16 and 17 respectively.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_enable_temperature_sensor()
+{
+ ADC_CCR |= ADC_CCR_TSVREFE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief ADC Disable The Temperature Sensor
+
+Disabling this will reduce power consumption from the sensor and the reference
+voltage measurements.
+
+@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
+*/
+
+void adc_disable_temperature_sensor()
+{
+ ADC_CCR &= ~ADC_CCR_TSVREFE;
+}
+
+/*-----------------------------------------------------------------------------*/
+
+/**@}*/
+
diff --git a/lib/stm32/f4/crc.c b/lib/stm32/f4/crc.c
new file mode 100644
index 0000000..90e6782
--- /dev/null
+++ b/lib/stm32/f4/crc.c
@@ -0,0 +1,29 @@
+/** @defgroup crc_file CRC
+
+@ingroup STM32F4xx
+
+@brief <b>libopencm3 STM32F4xx CRC</b>
+
+*/
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/crc.h>
+#include <libopencm3/stm32/common/crc_common_all.h>
+
+
diff --git a/lib/stm32/f4/dac.c b/lib/stm32/f4/dac.c
new file mode 100644
index 0000000..4776c41
--- /dev/null
+++ b/lib/stm32/f4/dac.c
@@ -0,0 +1,28 @@
+/** @defgroup dac_file DAC
+
+@ingroup STM32F4xx
+
+@brief <b>libopencm3 STM32F4xx DAC</b>
+
+*/
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/dac.h>
+#include <libopencm3/stm32/common/dac_common_all.h>
+
diff --git a/lib/stm32/f4/dma.c b/lib/stm32/f4/dma.c
new file mode 100644
index 0000000..c9f5db6
--- /dev/null
+++ b/lib/stm32/f4/dma.c
@@ -0,0 +1,28 @@
+/** @defgroup dma_file DMA
+
+@ingroup STM32F4xx
+
+@brief <b>libopencm3 STM32F4xx DMA</b>
+
+*/
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/dma.h>
+#include <libopencm3/stm32/common/dma_common_f24.h>
+
diff --git a/lib/stm32/f4/flash.c b/lib/stm32/f4/flash.c
index a9fe06c..75446ea 100644
--- a/lib/stm32/f4/flash.c
+++ b/lib/stm32/f4/flash.c
@@ -28,42 +28,42 @@ static inline void flash_set_program_size(u32 psize)
void flash_data_cache_enable(void)
{
- FLASH_ACR |= FLASH_DCE;
+ FLASH_ACR |= FLASH_ACR_DCE;
}
void flash_dcache_disable(void)
{
- FLASH_ACR &= ~FLASH_DCE;
+ FLASH_ACR &= ~FLASH_ACR_DCE;
}
void flash_icache_enable(void)
{
- FLASH_ACR |= FLASH_ICE;
+ FLASH_ACR |= FLASH_ACR_ICE;
}
void flash_icache_disable(void)
{
- FLASH_ACR &= ~FLASH_ICE;
+ FLASH_ACR &= ~FLASH_ACR_ICE;
}
void flash_prefetch_enable(void)
{
- FLASH_ACR |= FLASH_PRFTEN;
+ FLASH_ACR |= FLASH_ACR_PRFTEN;
}
void flash_prefetch_disable(void)
{
- FLASH_ACR &= ~FLASH_PRFTEN;
+ FLASH_ACR &= ~FLASH_ACR_PRFTEN;
}
void flash_dcache_reset(void)
{
- FLASH_ACR |= FLASH_DCRST;
+ FLASH_ACR |= FLASH_ACR_DCRST;
}
void flash_icache_reset(void)
{
- FLASH_ACR |= FLASH_ICRST;
+ FLASH_ACR |= FLASH_ACR_ICRST;
}
void flash_set_ws(u32 ws)
@@ -79,43 +79,43 @@ void flash_set_ws(u32 ws)
void flash_unlock(void)
{
/* Authorize the FPEC access. */
- FLASH_KEYR = FLASH_KEY1;
- FLASH_KEYR = FLASH_KEY2;
+ FLASH_KEYR = FLASH_KEYR_KEY1;
+ FLASH_KEYR = FLASH_KEYR_KEY2;
}
void flash_lock(void)
{
- FLASH_CR |= FLASH_LOCK;
+ FLASH_CR |= FLASH_CR_LOCK;
}
void flash_clear_pgserr_flag(void)
{
- FLASH_SR |= FLASH_PGSERR;
+ FLASH_SR |= FLASH_SR_PGSERR;
}
void flash_clear_pgperr_flag(void)
{
- FLASH_SR |= FLASH_PGPERR;
+ FLASH_SR |= FLASH_SR_PGPERR;
}
void flash_clear_pgaerr_flag(void)
{
- FLASH_SR |= FLASH_PGAERR;
+ FLASH_SR |= FLASH_SR_PGAERR;
}
void flash_clear_eop_flag(void)
{
- FLASH_SR |= FLASH_EOP;
+ FLASH_SR |= FLASH_SR_EOP;
}
void flash_clear_wrperr_flag(void)
{
- FLASH_SR |= FLASH_WRPERR;
+ FLASH_SR |= FLASH_SR_WRPERR;
}
void flash_clear_bsy_flag(void)
{
- FLASH_SR &= ~FLASH_BSY;
+ FLASH_SR &= ~FLASH_SR_BSY;
}
void flash_clear_status_flags(void)
@@ -130,18 +130,18 @@ void flash_clear_status_flags(void)
void flash_unlock_option_bytes(void)
{
- FLASH_OPTKEYR = FLASH_OPTKEY1;
- FLASH_OPTKEYR = FLASH_OPTKEY2;
+ FLASH_OPTKEYR = FLASH_OPTKEYR_KEY1;
+ FLASH_OPTKEYR = FLASH_OPTKEYR_KEY2;
}
void flash_lock_option_bytes(void)
{
- FLASH_OPTCR |= FLASH_OPTLOCK;
+ FLASH_OPTCR |= FLASH_OPTCR_OPTLOCK;
}
void flash_wait_for_last_operation(void)
{
- while ((FLASH_SR & FLASH_BSY) == FLASH_BSY)
+ while ((FLASH_SR & FLASH_SR_BSY) == FLASH_SR_BSY)
;
}
@@ -152,7 +152,7 @@ void flash_program_double_word(u32 address, u64 data, u32 program_size)
flash_set_program_size(program_size);
/* Enable writes to flash. */
- FLASH_CR |= FLASH_PG;
+ FLASH_CR |= FLASH_CR_PG;
/* Program the first half of the word. */
MMIO64(address) = data;
@@ -161,7 +161,7 @@ void flash_program_double_word(u32 address, u64 data, u32 program_size)
flash_wait_for_last_operation();
/* Disable writes to flash. */
- FLASH_CR &= ~FLASH_PG;
+ FLASH_CR &= ~FLASH_CR_PG;
}
void flash_program_word(u32 address, u32 data, u32 program_size)
@@ -171,7 +171,7 @@ void flash_program_word(u32 address, u32 data, u32 program_size)
flash_set_program_size(program_size);
/* Enable writes to flash. */
- FLASH_CR |= FLASH_PG;
+ FLASH_CR |= FLASH_CR_PG;
/* Program the first half of the word. */
MMIO32(address) = data;
@@ -180,7 +180,7 @@ void flash_program_word(u32 address, u32 data, u32 program_size)
flash_wait_for_last_operation();
/* Disable writes to flash. */
- FLASH_CR &= ~FLASH_PG;
+ FLASH_CR &= ~FLASH_CR_PG;
}
void flash_program_half_word(u32 address, u16 data, u32 program_size)
@@ -188,13 +188,13 @@ void flash_program_half_word(u32 address, u16 data, u32 program_size)
flash_wait_for_last_operation();
flash_set_program_size(program_size);
- FLASH_CR |= FLASH_PG;
+ FLASH_CR |= FLASH_CR_PG;
MMIO16(address) = data;
flash_wait_for_last_operation();
- FLASH_CR &= ~FLASH_PG; /* Disable the PG bit. */
+ FLASH_CR &= ~FLASH_CR_PG; /* Disable the PG bit. */
}
void flash_program_byte(u32 address, u8 data, u32 program_size)
@@ -202,13 +202,13 @@ void flash_program_byte(u32 address, u8 data, u32 program_size)
flash_wait_for_last_operation();
flash_set_program_size(program_size);
- FLASH_CR |= FLASH_PG;
+ FLASH_CR |= FLASH_CR_PG;
MMIO8(address) = data;
flash_wait_for_last_operation();
- FLASH_CR &= ~FLASH_PG; /* Disable the PG bit. */
+ FLASH_CR &= ~FLASH_CR_PG; /* Disable the PG bit. */
}
void flash_erase_sector(u32 sector, u32 program_size)
@@ -218,11 +218,11 @@ void flash_erase_sector(u32 sector, u32 program_size)
FLASH_CR &= ~(((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)) << 3);
FLASH_CR |= sector;
- FLASH_CR |= FLASH_SER;
- FLASH_CR |= FLASH_STRT;
+ FLASH_CR |= FLASH_CR_SER;
+ FLASH_CR |= FLASH_CR_STRT;
flash_wait_for_last_operation();
- FLASH_CR &= ~FLASH_SER;
+ FLASH_CR &= ~FLASH_CR_SER;
FLASH_CR &= ~(((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)) << 3);
}
@@ -231,21 +231,21 @@ void flash_erase_all_sectors(u32 program_size)
flash_wait_for_last_operation();
flash_set_program_size(program_size);
- FLASH_CR |= FLASH_MER; /* Enable mass erase. */
- FLASH_CR |= FLASH_STRT; /* Trigger the erase. */
+ FLASH_CR |= FLASH_CR_MER; /* Enable mass erase. */
+ FLASH_CR |= FLASH_CR_STRT; /* Trigger the erase. */
flash_wait_for_last_operation();
- FLASH_CR &= ~FLASH_MER; /* Disable mass erase. */
+ FLASH_CR &= ~FLASH_CR_MER; /* Disable mass erase. */
}
void flash_program_option_bytes(u32 data)
{
flash_wait_for_last_operation();
- if (FLASH_OPTCR & FLASH_OPTLOCK)
+ if (FLASH_OPTCR & FLASH_OPTCR_OPTLOCK)
flash_unlock_option_bytes();
FLASH_OPTCR = data & ~0x3;
- FLASH_OPTCR |= FLASH_OPTSTRT; /* Enable option byte programming. */
+ FLASH_OPTCR |= FLASH_OPTCR_OPTSTRT; /* Enable option byte programming. */
flash_wait_for_last_operation();
}
diff --git a/lib/stm32/f4/gpio.c b/lib/stm32/f4/gpio.c
index 1d7739d..96a6f45 100644
--- a/lib/stm32/f4/gpio.c
+++ b/lib/stm32/f4/gpio.c
@@ -1,8 +1,14 @@
+/** @defgroup gpio_file GPIO
+
+@ingroup STM32F4xx
+
+@brief <b>libopencm3 STM32F4xx General Purpose I/O</b>
+
+*/
+
/*
* This file is part of the libopencm3 project.
*
- * Copyright (C) 2011 Fergus Noble <fergusnoble@gmail.com>
- *
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@@ -17,126 +23,6 @@
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <libopencm3/stm32/f4/gpio.h>
-
-void gpio_mode_setup(u32 gpioport, u8 mode, u8 pull_up_down, u16 gpios)
-{
- u16 i;
- u32 moder, pupd;
-
- /*
- * We want to set the config only for the pins mentioned in gpios,
- * but keeping the others, so read out the actual config first.
- */
- moder = GPIO_MODER(gpioport);
- pupd = GPIO_PUPDR(gpioport);
-
- for (i = 0; i < 16; i++) {
- if (!((1 << i) & gpios))
- continue;
-
- moder &= ~GPIO_MODE_MASK(i);
- moder |= GPIO_MODE(i, mode);
- pupd &= ~GPIO_PUPD_MASK(i);
- pupd |= GPIO_PUPD(i, pull_up_down);
- }
-
- /* Set mode and pull up/down control registers. */
- GPIO_MODER(gpioport) = moder;
- GPIO_PUPDR(gpioport) = pupd;
-}
-
-void gpio_set_output_options(u32 gpioport, u8 otype, u8 speed, u16 gpios)
-{
- u16 i;
- u32 ospeedr;
-
- if (otype == 0x1)
- GPIO_OTYPER(gpioport) |= gpios;
- else
- GPIO_OTYPER(gpioport) &= ~gpios;
-
- ospeedr = GPIO_OSPEEDR(gpioport);
-
- for (i = 0; i < 16; i++) {
- if (!((1 << i) & gpios))
- continue;
- ospeedr &= ~GPIO_OSPEED_MASK(i);
- ospeedr |= GPIO_OSPEED(i, speed);
- }
-
- GPIO_OSPEEDR(gpioport) = ospeedr;
-}
-
-void gpio_set_af(u32 gpioport, u8 alt_func_num, u16 gpios)
-{
- u16 i;
- u32 afrl, afrh;
-
- afrl = GPIO_AFRL(gpioport);
- afrh = GPIO_AFRH(gpioport);
-
- for (i = 0; i < 8; i++) {
- if (!((1 << i) & gpios))
- continue;
- afrl &= ~GPIO_AFR_MASK(i);
- afrl |= GPIO_AFR(i, alt_func_num);
- }
-
- for (i = 8; i < 16; i++) {
- if (!((1 << i) & gpios))
- continue;
- afrl &= ~GPIO_AFR_MASK(i - 8);
- afrh |= GPIO_AFR(i - 8, alt_func_num);
- }
-
- GPIO_AFRL(gpioport) = afrl;
- GPIO_AFRH(gpioport) = afrh;
-}
-
-void gpio_set(u32 gpioport, u16 gpios)
-{
- GPIO_BSRR(gpioport) = gpios;
-}
-
-void gpio_clear(u32 gpioport, u16 gpios)
-{
- GPIO_BSRR(gpioport) = gpios << 16;
-}
-
-u16 gpio_get(u32 gpioport, u16 gpios)
-{
- return gpio_port_read(gpioport) & gpios;
-}
-
-void gpio_toggle(u32 gpioport, u16 gpios)
-{
- GPIO_ODR(gpioport) ^= gpios;
-}
-
-u16 gpio_port_read(u32 gpioport)
-{
- return (u16)GPIO_IDR(gpioport);
-}
-
-void gpio_port_write(u32 gpioport, u16 data)
-{
- GPIO_ODR(gpioport) = data;
-}
-
-void gpio_port_config_lock(u32 gpioport, u16 gpios)
-{
- u32 reg32;
-
- /* Special "Lock Key Writing Sequence", see datasheet. */
- GPIO_LCKR(gpioport) = GPIO_LCKK | gpios; /* Set LCKK. */
- GPIO_LCKR(gpioport) = ~GPIO_LCKK & gpios; /* Clear LCKK. */
- GPIO_LCKR(gpioport) = GPIO_LCKK | gpios; /* Set LCKK. */
- reg32 = GPIO_LCKR(gpioport); /* Read LCKK. */
- reg32 = GPIO_LCKR(gpioport); /* Read LCKK again. */
-
- /* Tell the compiler the variable is actually used. It will get optimized out anyways. */
- reg32 = reg32;
+#include <libopencm3/stm32/gpio.h>
+#include <libopencm3/stm32/common/gpio_common_f24.h>
- /* If (reg32 & GPIO_LCKK) is true, the lock is now active. */
-}
diff --git a/lib/stm32/f4/i2c.c b/lib/stm32/f4/i2c.c
new file mode 100644
index 0000000..3250faa
--- /dev/null
+++ b/lib/stm32/f4/i2c.c
@@ -0,0 +1,28 @@
+/** @defgroup i2c_file I2C
+
+@ingroup STM32F4xx
+
+@brief <b>libopencm3 STM32F4xx I2C</b>
+
+*/
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/i2c.h>
+#include <libopencm3/stm32/common/spi_common_all.h>
+
diff --git a/lib/stm32/f4/iwdg.c b/lib/stm32/f4/iwdg.c
new file mode 100644
index 0000000..9332fc4
--- /dev/null
+++ b/lib/stm32/f4/iwdg.c
@@ -0,0 +1,28 @@
+/** @defgroup iwdg_file IWDG
+
+@ingroup STM32F4xx
+
+@brief <b>libopencm3 STM32F4xx Independent Watchdog Timer</b>
+
+*/
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/iwdg.h>
+#include <libopencm3/stm32/common/iwdg_common_all.h>
+
diff --git a/lib/stm32/f4/rcc.c b/lib/stm32/f4/rcc.c
index f506d4b..1024f0b 100644
--- a/lib/stm32/f4/rcc.c
+++ b/lib/stm32/f4/rcc.c
@@ -39,7 +39,7 @@ const clock_scale_t hse_8mhz_3v3[CLOCK_3V3_END] =
.ppre1 = RCC_CFGR_PPRE_DIV_4,
.ppre2 = RCC_CFGR_PPRE_DIV_2,
.power_save = 1,
- .flash_config = FLASH_ICE | FLASH_DCE | FLASH_LATENCY_3WS,
+ .flash_config = FLASH_ACR_ICE | FLASH_ACR_DCE | FLASH_ACR_LATENCY_3WS,
.apb1_frequency = 30000000,
.apb2_frequency = 60000000,
},
@@ -51,7 +51,7 @@ const clock_scale_t hse_8mhz_3v3[CLOCK_3V3_END] =
.hpre = RCC_CFGR_HPRE_DIV_NONE,
.ppre1 = RCC_CFGR_PPRE_DIV_4,
.ppre2 = RCC_CFGR_PPRE_DIV_2,
- .flash_config = FLASH_ICE | FLASH_DCE | FLASH_LATENCY_5WS,
+ .flash_config = FLASH_ACR_ICE | FLASH_ACR_DCE | FLASH_ACR_LATENCY_5WS,
.apb1_frequency = 42000000,
.apb2_frequency = 84000000,
},
diff --git a/lib/stm32/f4/rtc.c b/lib/stm32/f4/rtc.c
new file mode 100644
index 0000000..1b301fa
--- /dev/null
+++ b/lib/stm32/f4/rtc.c
@@ -0,0 +1,27 @@
+/** @defgroup rtc_file RTC
+
+@ingroup STM32F4xx
+
+@brief <b>libopencm3 STM32F4xx RTC</b>
+
+*/
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/rtc.h>
+#include <libopencm3/stm32/common/rtc_common_bcd.h>
diff --git a/lib/stm32/f4/spi.c b/lib/stm32/f4/spi.c
new file mode 100644
index 0000000..40f5501
--- /dev/null
+++ b/lib/stm32/f4/spi.c
@@ -0,0 +1,28 @@
+/** @defgroup spi_file SPI
+
+@ingroup STM32F4xx
+
+@brief <b>libopencm3 STM32F4xx SPI</b>
+
+*/
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/spi.h>
+#include <libopencm3/stm32/common/spi_common_f24.h>
+
diff --git a/lib/stm32/f4/timer.c b/lib/stm32/f4/timer.c
deleted file mode 100644
index 6d5ab9d..0000000
--- a/lib/stm32/f4/timer.c
+++ /dev/null
@@ -1,928 +0,0 @@
-/*
- * This file is part of the libopencm3 project.
- *
- * Copyright (C) 2010 Edward Cheeseman <evbuilder@users.sourceforge.org>
- * Copyright (C) 2011 Stephen Caudle <scaudle@doceme.com>
- *
- * This library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
- * Basic TIMER handling API.
- *
- * Examples:
- * timer_set_mode(TIM1, TIM_CR1_CKD_CK_INT_MUL_2,
- * TIM_CR1_CMS_CENTRE_3, TIM_CR1_DIR_UP);
- */
-
-#include <libopencm3/stm32/f4/timer.h>
-#include <libopencm3/stm32/f4/rcc.h>
-
-void timer_reset(u32 timer_peripheral)
-{
- switch (timer_peripheral) {
- case TIM1:
- rcc_peripheral_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM1RST);
- rcc_peripheral_clear_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM1RST);
- break;
- case TIM2:
- rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM2RST);
- rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM2RST);
- break;
- case TIM3:
- rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM3RST);
- rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM3RST);
- break;
- case TIM4:
- rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM4RST);
- rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM4RST);
- break;
- case TIM5:
- rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM5RST);
- rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM5RST);
- break;
- case TIM6:
- rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM6RST);
- rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM6RST);
- break;
- case TIM7:
- rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM7RST);
- rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM7RST);
- break;
- case TIM8:
- rcc_peripheral_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM8RST);
- rcc_peripheral_clear_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM8RST);
- break;
-/* These timers are not supported in libopencm3 yet */
-/*
- case TIM9:
- rcc_peripheral_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM9RST);
- rcc_peripheral_clear_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM9RST);
- break;
- case TIM10:
- rcc_peripheral_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM10RST);
- rcc_peripheral_clear_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM10RST);
- break;
- case TIM11:
- rcc_peripheral_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM11RST);
- rcc_peripheral_clear_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM11RST);
- break;
- case TIM12:
- rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM12RST);
- rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM12RST);
- break;
- case TIM13:
- rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM13RST);
- rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM13RST);
- break;
- case TIM14:
- rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM14RST);
- rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM14RST);
- break;
-*/
- }
-}
-
-void timer_enable_irq(u32 timer_peripheral, u32 irq)
-{
- TIM_DIER(timer_peripheral) |= irq;
-}
-
-void timer_disable_irq(u32 timer_peripheral, u32 irq)
-{
- TIM_DIER(timer_peripheral) &= ~irq;
-}
-
-bool timer_get_flag(u32 timer_peripheral, u32 flag)
-{
- if (((TIM_SR(timer_peripheral) & flag) != 0) &&
- ((TIM_DIER(timer_peripheral) & flag) != 0)) {
- return true;
- }
-
- return false;
-}
-
-void timer_clear_flag(u32 timer_peripheral, u32 flag)
-{
- TIM_SR(timer_peripheral) &= ~flag;
-}
-
-void timer_set_mode(u32 timer_peripheral, u32 clock_div,
- u32 alignment, u32 direction)
-{
- u32 cr1;
-
- cr1 = TIM_CR1(timer_peripheral);
-
- cr1 &= ~(TIM_CR1_CKD_CK_INT_MASK | TIM_CR1_CMS_MASK | TIM_CR1_DIR_DOWN);
-
- cr1 |= clock_div | alignment | direction;
-
- TIM_CR1(timer_peripheral) = cr1;
-}
-
-void timer_set_clock_division(u32 timer_peripheral, u32 clock_div)
-{
- clock_div &= TIM_CR1_CKD_CK_INT_MASK;
- TIM_CR1(timer_peripheral) &= ~TIM_CR1_CKD_CK_INT_MASK;
- TIM_CR1(timer_peripheral) |= clock_div;
-}
-
-void timer_enable_preload(u32 timer_peripheral)
-{
- TIM_CR1(timer_peripheral) |= TIM_CR1_ARPE;
-}
-
-void timer_disable_preload(u32 timer_peripheral)
-{
- TIM_CR1(timer_peripheral) &= ~TIM_CR1_ARPE;
-}
-
-void timer_set_alignment(u32 timer_peripheral, u32 alignment)
-{
- alignment &= TIM_CR1_CMS_MASK;
- TIM_CR1(timer_peripheral) &= ~TIM_CR1_CMS_MASK;
- TIM_CR1(timer_peripheral) |= alignment;
-}
-
-void timer_direction_up(u32 timer_peripheral)
-{
- TIM_CR1(timer_peripheral) &= ~TIM_CR1_DIR_DOWN;
-}
-
-void timer_direction_down(u32 timer_peripheral)
-{
- TIM_CR1(timer_peripheral) |= TIM_CR1_DIR_DOWN;
-}
-
-void timer_one_shot_mode(u32 timer_peripheral)
-{
- TIM_CR1(timer_peripheral) |= TIM_CR1_OPM;
-}
-
-void timer_continuous_mode(u32 timer_peripheral)
-{
- TIM_CR1(timer_peripheral) &= ~TIM_CR1_OPM;
-}
-
-void timer_update_on_any(u32 timer_peripheral)
-{
- TIM_CR1(timer_peripheral) &= ~TIM_CR1_URS;
-}
-
-void timer_update_on_overflow(u32 timer_peripheral)
-{
- TIM_CR1(timer_peripheral) |= TIM_CR1_URS;
-}
-
-void timer_enable_update_event(u32 timer_peripheral)
-{
- TIM_CR1(timer_peripheral) &= ~TIM_CR1_UDIS;
-}
-
-void timer_disable_update_event(u32 timer_peripheral)
-{
- TIM_CR1(timer_peripheral) |= TIM_CR1_UDIS;
-}
-
-void timer_enable_counter(u32 timer_peripheral)
-{
- TIM_CR1(timer_peripheral) |= TIM_CR1_CEN;
-}
-
-void timer_disable_counter(u32 timer_peripheral)
-{
- TIM_CR1(timer_peripheral) &= ~TIM_CR1_CEN;
-}
-
-void timer_set_output_idle_state(u32 timer_peripheral, u32 outputs)
-{
- TIM_CR2(timer_peripheral) |= outputs & TIM_CR2_OIS_MASK;
-}
-
-void timer_reset_output_idle_state(u32 timer_peripheral, u32 outputs)
-{
- TIM_CR2(timer_peripheral) &= ~(outputs & TIM_CR2_OIS_MASK);
-}
-
-void timer_set_ti1_ch123_xor(u32 timer_peripheral)
-{
- TIM_CR2(timer_peripheral) |= TIM_CR2_TI1S;
-}
-
-void timer_set_ti1_ch1(u32 timer_peripheral)
-{
- TIM_CR2(timer_peripheral) &= ~TIM_CR2_TI1S;
-}
-
-void timer_set_master_mode(u32 timer_peripheral, u32 mode)
-{
- TIM_CR2(timer_peripheral) &= ~TIM_CR2_MMS_MASK;
- TIM_CR2(timer_peripheral) |= mode;
-}
-
-void timer_set_dma_on_compare_event(u32 timer_peripheral)
-{
- TIM_CR2(timer_peripheral) &= ~TIM_CR2_CCDS;
-}
-
-void timer_set_dma_on_update_event(u32 timer_peripheral)
-{
- TIM_CR2(timer_peripheral) |= TIM_CR2_CCDS;
-}
-
-void timer_enable_compare_control_update_on_trigger(u32 timer_peripheral)
-{
- TIM_CR2(timer_peripheral) |= TIM_CR2_CCUS;
-}
-
-void timer_disable_compare_control_update_on_trigger(u32 timer_peripheral)
-{
- TIM_CR2(timer_peripheral) &= ~TIM_CR2_CCUS;
-}
-
-void timer_enable_preload_complementry_enable_bits(u32 timer_peripheral)
-{
- TIM_CR2(timer_peripheral) |= TIM_CR2_CCPC;
-}
-
-void timer_disable_preload_complementry_enable_bits(u32 timer_peripheral)
-{
- TIM_CR2(timer_peripheral) &= ~TIM_CR2_CCPC;
-}
-
-void timer_set_prescaler(u32 timer_peripheral, u32 value)
-{
- TIM_PSC(timer_peripheral) = value;
-}
-
-void timer_set_repetition_counter(u32 timer_peripheral, u32 value)
-{
- if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_RCR(timer_peripheral) = value;
-}
-
-void timer_set_period(u32 timer_peripheral, u32 period)
-{
- TIM_ARR(timer_peripheral) = period;
-}
-
-void timer_enable_oc_clear(u32 timer_peripheral, enum tim_oc_id oc_id)
-{
- switch (oc_id) {
- case TIM_OC1:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1CE;
- break;
- case TIM_OC2:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2CE;
- break;
- case TIM_OC3:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3CE;
- break;
- case TIM_OC4:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4CE;
- break;
- case TIM_OC1N:
- case TIM_OC2N:
- case TIM_OC3N:
- /* Ignoring as fast enable only applies to the whole channel. */
- break;
- }
-}
-
-void timer_disable_oc_clear(u32 timer_peripheral, enum tim_oc_id oc_id)
-{
- switch (oc_id) {
- case TIM_OC1:
- TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC1CE;
- break;
- case TIM_OC2:
- TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC2CE;
- break;
- case TIM_OC3:
- TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC3CE;
- break;
- case TIM_OC4:
- TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC4CE;
- break;
- case TIM_OC1N:
- case TIM_OC2N:
- case TIM_OC3N:
- /* Ignoring as fast enable only applies to the whole channel. */
- break;
- }
-}
-
-void timer_set_oc_fast_mode(u32 timer_peripheral, enum tim_oc_id oc_id)
-{
- switch (oc_id) {
- case TIM_OC1:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1FE;
- break;
- case TIM_OC2:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2FE;
- break;
- case TIM_OC3:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3FE;
- break;
- case TIM_OC4:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4FE;
- break;
- case TIM_OC1N:
- case TIM_OC2N:
- case TIM_OC3N:
- /* Ignoring as fast enable only applies to the whole channel. */
- break;
- }
-}
-
-void timer_set_oc_slow_mode(u32 timer_peripheral, enum tim_oc_id oc_id)
-{
- switch (oc_id) {
- case TIM_OC1:
- TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC1FE;
- break;
- case TIM_OC2:
- TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC2FE;
- break;
- case TIM_OC3:
- TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC3FE;
- break;
- case TIM_OC4:
- TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC4FE;
- break;
- case TIM_OC1N:
- case TIM_OC2N:
- case TIM_OC3N:
- /* Ignoring as this option applies to the whole channel. */
- break;
- }
-}
-
-void timer_set_oc_mode(u32 timer_peripheral, enum tim_oc_id oc_id,
- enum tim_oc_mode oc_mode)
-{
- switch (oc_id) {
- case TIM_OC1:
- TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_CC1S_MASK;
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_CC1S_OUT;
- TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC1M_MASK;
- switch (oc_mode) {
- case TIM_OCM_FROZEN:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1M_FROZEN;
- break;
- case TIM_OCM_ACTIVE:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1M_ACTIVE;
- break;
- case TIM_OCM_INACTIVE:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1M_INACTIVE;
- break;
- case TIM_OCM_TOGGLE:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1M_TOGGLE;
- break;
- case TIM_OCM_FORCE_LOW:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1M_FORCE_LOW;
- break;
- case TIM_OCM_FORCE_HIGH:
- TIM_CCMR1(timer_peripheral) |=
- TIM_CCMR1_OC1M_FORCE_HIGH;
- break;
- case TIM_OCM_PWM1:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1M_PWM1;
- break;
- case TIM_OCM_PWM2:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1M_PWM2;
- break;
- }
- break;
- case TIM_OC2:
- TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_CC2S_MASK;
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_CC2S_OUT;
- TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC2M_MASK;
- switch (oc_mode) {
- case TIM_OCM_FROZEN:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2M_FROZEN;
- break;
- case TIM_OCM_ACTIVE:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2M_ACTIVE;
- break;
- case TIM_OCM_INACTIVE:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2M_INACTIVE;
- break;
- case TIM_OCM_TOGGLE:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2M_TOGGLE;
- break;
- case TIM_OCM_FORCE_LOW:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2M_FORCE_LOW;
- break;
- case TIM_OCM_FORCE_HIGH:
- TIM_CCMR1(timer_peripheral) |=
- TIM_CCMR1_OC2M_FORCE_HIGH;
- break;
- case TIM_OCM_PWM1:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2M_PWM1;
- break;
- case TIM_OCM_PWM2:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2M_PWM2;
- break;
- }
- break;
- case TIM_OC3:
- TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR2_CC3S_MASK;
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR2_CC3S_OUT;
- TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC3M_MASK;
- switch (oc_mode) {
- case TIM_OCM_FROZEN:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3M_FROZEN;
- break;
- case TIM_OCM_ACTIVE:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR2_OC3M_ACTIVE;
- break;
- case TIM_OCM_INACTIVE:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3M_INACTIVE;
- break;
- case TIM_OCM_TOGGLE:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3M_TOGGLE;
- break;
- case TIM_OCM_FORCE_LOW:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3M_FORCE_LOW;
- break;
- case TIM_OCM_FORCE_HIGH:
- TIM_CCMR2(timer_peripheral) |=
- TIM_CCMR2_OC3M_FORCE_HIGH;
- break;
- case TIM_OCM_PWM1:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3M_PWM1;
- break;
- case TIM_OCM_PWM2:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3M_PWM2;
- break;
- }
- break;
- case TIM_OC4:
- TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR2_CC4S_MASK;
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR2_CC4S_OUT;
- TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC4M_MASK;
- switch (oc_mode) {
- case TIM_OCM_FROZEN:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4M_FROZEN;
- break;
- case TIM_OCM_ACTIVE:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR2_OC4M_ACTIVE;
- break;
- case TIM_OCM_INACTIVE:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4M_INACTIVE;
- break;
- case TIM_OCM_TOGGLE:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4M_TOGGLE;
- break;
- case TIM_OCM_FORCE_LOW:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4M_FORCE_LOW;
- break;
- case TIM_OCM_FORCE_HIGH:
- TIM_CCMR2(timer_peripheral) |=
- TIM_CCMR2_OC4M_FORCE_HIGH;
- break;
- case TIM_OCM_PWM1:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4M_PWM1;
- break;
- case TIM_OCM_PWM2:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4M_PWM2;
- break;
- }
- break;
- case TIM_OC1N:
- case TIM_OC2N:
- case TIM_OC3N:
- /* Ignoring as this option applies to the whole channel. */
- break;
- }
-}
-
-void timer_enable_oc_preload(u32 timer_peripheral, enum tim_oc_id oc_id)
-{
- switch (oc_id) {
- case TIM_OC1:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1PE;
- break;
- case TIM_OC2:
- TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2PE;
- break;
- case TIM_OC3:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3PE;
- break;
- case TIM_OC4:
- TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4PE;
- break;
- case TIM_OC1N:
- case TIM_OC2N:
- case TIM_OC3N:
- /* Ignoring as this option applies to the whole channel. */
- break;
- }
-}
-
-void timer_disable_oc_preload(u32 timer_peripheral, enum tim_oc_id oc_id)
-{
- switch (oc_id) {
- case TIM_OC1:
- TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC1PE;
- break;
- case TIM_OC2:
- TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC2PE;
- break;
- case TIM_OC3:
- TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC3PE;
- break;
- case TIM_OC4:
- TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC4PE;
- break;
- case TIM_OC1N:
- case TIM_OC2N:
- case TIM_OC3N:
- /* Ignoring as this option applies to the whole channel. */
- break;
- }
-}
-
-void timer_set_oc_polarity_high(u32 timer_peripheral, enum tim_oc_id oc_id)
-{
- switch (oc_id) {
- case TIM_OC1:
- TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC1P;
- break;
- case TIM_OC2:
- TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC2P;
- break;
- case TIM_OC3:
- TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC3P;
- break;
- case TIM_OC4:
- TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC4P;
- break;
- case TIM_OC1N:
- case TIM_OC2N:
- case TIM_OC3N:
- /* Ignoring as this option applies to TIM1 and TIM8 only. */
- break;
- }
-
- /* Acting for TIM1 and TIM8 only from here onwards. */
- if ((timer_peripheral != TIM1) && (timer_peripheral != TIM8))
- return;
-
- switch (oc_id) {
- case TIM_OC1N:
- TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC1NP;
- break;
- case TIM_OC2N:
- TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC2NP;
- break;
- case TIM_OC3N:
- TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC3NP;
- break;
- case TIM_OC1:
- case TIM_OC2:
- case TIM_OC3:
- case TIM_OC4:
- /* Ignoring as this option was already set above. */
- break;
- }
-}
-
-void timer_set_oc_polarity_low(u32 timer_peripheral, enum tim_oc_id oc_id)
-{
- switch (oc_id) {
- case TIM_OC1:
- TIM_CCER(timer_peripheral) |= TIM_CCER_CC1P;
- break;
- case TIM_OC2:
- TIM_CCER(timer_peripheral) |= TIM_CCER_CC2P;
- break;
- case TIM_OC3:
- TIM_CCER(timer_peripheral) |= TIM_CCER_CC3P;
- break;
- case TIM_OC4:
- TIM_CCER(timer_peripheral) |= TIM_CCER_CC4P;
- break;
- case TIM_OC1N:
- case TIM_OC2N:
- case TIM_OC3N:
- /* Ignoring as this option applies to TIM1 and TIM8 only. */
- break;
- }
-
- /* Acting for TIM1 and TIM8 only from here onwards. */
- if ((timer_peripheral != TIM1) && (timer_peripheral != TIM8))
- return;
-
- switch (oc_id) {
- case TIM_OC1N:
- TIM_CCER(timer_peripheral) |= TIM_CCER_CC1NP;
- break;
- case TIM_OC2N:
- TIM_CCER(timer_peripheral) |= TIM_CCER_CC2NP;
- break;
- case TIM_OC3N:
- TIM_CCER(timer_peripheral) |= TIM_CCER_CC3NP;
- break;
- case TIM_OC1:
- case TIM_OC2:
- case TIM_OC3:
- case TIM_OC4:
- /* Ignoring as this option was already set above. */
- break;
- }
-}
-
-void timer_enable_oc_output(u32 timer_peripheral, enum tim_oc_id oc_id)
-{
- switch (oc_id) {
- case TIM_OC1:
- TIM_CCER(timer_peripheral) |= TIM_CCER_CC1E;
- break;
- case TIM_OC2:
- TIM_CCER(timer_peripheral) |= TIM_CCER_CC2E;
- break;
- case TIM_OC3:
- TIM_CCER(timer_peripheral) |= TIM_CCER_CC3E;
- break;
- case TIM_OC4:
- TIM_CCER(timer_peripheral) |= TIM_CCER_CC4E;
- break;
- case TIM_OC1N:
- case TIM_OC2N:
- case TIM_OC3N:
- /* Ignoring as this option applies to TIM1 and TIM8 only. */
- break;
- }
-
- /* Acting for TIM1 and TIM8 only from here onwards. */
- if ((timer_peripheral != TIM1) && (timer_peripheral != TIM8))
- return;
-
- switch (oc_id) {
- case TIM_OC1N:
- TIM_CCER(timer_peripheral) |= TIM_CCER_CC1NE;
- break;
- case TIM_OC2N:
- TIM_CCER(timer_peripheral) |= TIM_CCER_CC2NE;
- break;
- case TIM_OC3N:
- TIM_CCER(timer_peripheral) |= TIM_CCER_CC3NE;
- break;
- case TIM_OC1:
- case TIM_OC2:
- case TIM_OC3:
- case TIM_OC4:
- /* Ignoring as this option was already set above. */
- break;
- }
-}
-
-void timer_disable_oc_output(u32 timer_peripheral, enum tim_oc_id oc_id)
-{
- switch (oc_id) {
- case TIM_OC1:
- TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC1E;
- break;
- case TIM_OC2:
- TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC2E;
- break;
- case TIM_OC3:
- TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC3E;
- break;
- case TIM_OC4:
- TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC4E;
- break;
- case TIM_OC1N:
- case TIM_OC2N:
- case TIM_OC3N:
- /* Ignoring as this option applies to TIM1 and TIM8 only. */
- break;
- }
-
- /* Acting for TIM1 and TIM8 only from here onwards. */
- if ((timer_peripheral != TIM1) && (timer_peripheral != TIM8))
- return;
-
- switch (oc_id) {
- case TIM_OC1N:
- TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC1NE;
- break;
- case TIM_OC2N:
- TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC2NE;
- break;
- case TIM_OC3N:
- TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC3NE;
- break;
- case TIM_OC1:
- case TIM_OC2:
- case TIM_OC3:
- case TIM_OC4:
- /* Ignoring as this option was already set above. */
- break;
- }
-}
-
-void timer_set_oc_idle_state_set(u32 timer_peripheral, enum tim_oc_id oc_id)
-{
- /* Acting for TIM1 and TIM8 only. */
- if ((timer_peripheral != TIM1) && (timer_peripheral != TIM8))
- return;
-
- switch (oc_id) {
- case TIM_OC1:
- TIM_CR2(timer_peripheral) |= TIM_CR2_OIS1;
- break;
- case TIM_OC1N:
- TIM_CR2(timer_peripheral) |= TIM_CR2_OIS1N;
- break;
- case TIM_OC2:
- TIM_CR2(timer_peripheral) |= TIM_CR2_OIS2;
- break;
- case TIM_OC2N:
- TIM_CR2(timer_peripheral) |= TIM_CR2_OIS2N;
- break;
- case TIM_OC3:
- TIM_CR2(timer_peripheral) |= TIM_CR2_OIS3;
- break;
- case TIM_OC3N:
- TIM_CR2(timer_peripheral) |= TIM_CR2_OIS3N;
- break;
- case TIM_OC4:
- TIM_CR2(timer_peripheral) |= TIM_CR2_OIS4;
- break;
- }
-}
-
-void timer_set_oc_idle_state_unset(u32 timer_peripheral, enum tim_oc_id oc_id)
-{
- /* Acting for TIM1 and TIM8 only. */
- if ((timer_peripheral != TIM1) && (timer_peripheral != TIM8))
- return;
-
- switch (oc_id) {
- case TIM_OC1:
- TIM_CR2(timer_peripheral) &= ~TIM_CR2_OIS1;
- break;
- case TIM_OC1N:
- TIM_CR2(timer_peripheral) &= ~TIM_CR2_OIS1N;
- break;
- case TIM_OC2:
- TIM_CR2(timer_peripheral) &= ~TIM_CR2_OIS2;
- break;
- case TIM_OC2N:
- TIM_CR2(timer_peripheral) &= ~TIM_CR2_OIS2N;
- break;
- case TIM_OC3:
- TIM_CR2(timer_peripheral) &= ~TIM_CR2_OIS3;
- break;
- case TIM_OC3N:
- TIM_CR2(timer_peripheral) &= ~TIM_CR2_OIS3N;
- break;
- case TIM_OC4:
- TIM_CR2(timer_peripheral) &= ~TIM_CR2_OIS4;
- break;
- }
-}
-
-void timer_set_oc_value(u32 timer_peripheral, enum tim_oc_id oc_id, u32 value)
-{
- switch (oc_id) {
- case TIM_OC1:
- TIM_CCR1(timer_peripheral) = value;
- break;
- case TIM_OC2:
- TIM_CCR2(timer_peripheral) = value;
- break;
- case TIM_OC3:
- TIM_CCR3(timer_peripheral) = value;
- break;
- case TIM_OC4:
- TIM_CCR4(timer_peripheral) = value;
- break;
- case TIM_OC1N:
- case TIM_OC2N:
- case TIM_OC3N:
- /* Ignoring as this option applies to the whole channel. */
- break;
- }
-}
-
-void timer_enable_break_main_output(u32 timer_peripheral)
-{
- if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_BDTR(timer_peripheral) |= TIM_BDTR_MOE;
-}
-
-void timer_disable_break_main_output(u32 timer_peripheral)
-{
- if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_BDTR(timer_peripheral) &= ~TIM_BDTR_MOE;
-}
-
-void timer_enable_break_automatic_output(u32 timer_peripheral)
-{
- if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_BDTR(timer_peripheral) |= TIM_BDTR_AOE;
-}
-
-void timer_disable_break_automatic_output(u32 timer_peripheral)
-{
- if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_BDTR(timer_peripheral) &= ~TIM_BDTR_AOE;
-}
-
-void timer_set_break_polarity_high(u32 timer_peripheral)
-{
- if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_BDTR(timer_peripheral) |= TIM_BDTR_BKP;
-}
-
-void timer_set_break_polarity_low(u32 timer_peripheral)
-{
- if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_BDTR(timer_peripheral) &= ~TIM_BDTR_BKP;
-}
-
-void timer_enable_break(u32 timer_peripheral)
-{
- if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_BDTR(timer_peripheral) |= TIM_BDTR_BKE;
-}
-
-void timer_disable_break(u32 timer_peripheral)
-{
- if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_BDTR(timer_peripheral) &= ~TIM_BDTR_BKE;
-}
-
-void timer_set_enabled_off_state_in_run_mode(u32 timer_peripheral)
-{
- if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_BDTR(timer_peripheral) |= TIM_BDTR_OSSR;
-}
-
-void timer_set_disabled_off_state_in_run_mode(u32 timer_peripheral)
-{
- if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_BDTR(timer_peripheral) &= ~TIM_BDTR_OSSR;
-}
-
-void timer_set_enabled_off_state_in_idle_mode(u32 timer_peripheral)
-{
- if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_BDTR(timer_peripheral) |= TIM_BDTR_OSSI;
-}
-
-void timer_set_disabled_off_state_in_idle_mode(u32 timer_peripheral)
-{
- if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_BDTR(timer_peripheral) &= ~TIM_BDTR_OSSI;
-}
-
-void timer_set_break_lock(u32 timer_peripheral, u32 lock)
-{
- if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_BDTR(timer_peripheral) |= lock;
-}
-
-void timer_set_deadtime(u32 timer_peripheral, u32 deadtime)
-{
- if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_BDTR(timer_peripheral) |= deadtime;
-}
-
-void timer_generate_event(u32 timer_peripheral, u32 event)
-{
- TIM_EGR(timer_peripheral) |= event;
-}
-
-u32 timer_get_counter(u32 timer_peripheral)
-{
- return TIM_CNT(timer_peripheral);
-}
-
-void timer_set_option(u32 timer_peripheral, u32 option)
-{
- if (timer_peripheral == TIM2) {
- TIM_OR(timer_peripheral) &= ~TIM2_OR_ITR1_RMP_MASK;
- TIM_OR(timer_peripheral) |= option;
- } else if (timer_peripheral == TIM5) {
- TIM_OR(timer_peripheral) &= ~TIM5_OR_TI4_RMP_MASK;
- TIM_OR(timer_peripheral) |= option;
- }
-}
diff --git a/lib/stm32/f4/usart.c b/lib/stm32/f4/usart.c
new file mode 100644
index 0000000..e0f7be8
--- /dev/null
+++ b/lib/stm32/f4/usart.c
@@ -0,0 +1,28 @@
+/** @defgroup usart_file USART
+
+@ingroup STM32F4xx
+
+@brief <b>libopencm3 STM32F4xx USART</b>
+
+*/
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/usart.h>
+#include <libopencm3/stm32/common/usart_common_all.h>
+
diff --git a/lib/stm32/f4/vector.c b/lib/stm32/f4/vector.c
deleted file mode 100644
index 01b5e64..0000000
--- a/lib/stm32/f4/vector.c
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
- * This file is part of the libopencm3 project.
- *
- * Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
- * Copyright (C) 2011 Fergus Noble <fergusnoble@gmail.com>
- *
- * This library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <libopencm3/stm32/f4/scb.h>
-
-#define WEAK __attribute__ ((weak))
-
-/* Symbols exported by the linker script(s): */
-extern unsigned _data_loadaddr, _data, _edata, _ebss, _stack;
-
-void main(void);
-void reset_handler(void);
-void blocking_handler(void);
-void null_handler(void);
-
-void WEAK reset_handler(void);
-void WEAK nmi_handler(void);
-void WEAK hard_fault_handler(void);
-void WEAK mem_manage_handler(void);
-void WEAK bus_fault_handler(void);
-void WEAK usage_fault_handler(void);
-void WEAK sv_call_handler(void);
-void WEAK debug_monitor_handler(void);
-void WEAK pend_sv_handler(void);
-void WEAK sys_tick_handler(void);
-void WEAK wwdg_isr(void);
-void WEAK pvd_isr(void);
-void WEAK tamp_stamp_isr(void);
-void WEAK rtc_wkup_isr(void);
-void WEAK flash_isr(void);
-void WEAK rcc_isr(void);
-void WEAK exti0_isr(void);
-void WEAK exti1_isr(void);
-void WEAK exti2_isr(void);
-void WEAK exti3_isr(void);
-void WEAK exti4_isr(void);
-void WEAK dma1_stream0_isr(void);
-void WEAK dma1_stream1_isr(void);
-void WEAK dma1_stream2_isr(void);
-void WEAK dma1_stream3_isr(void);
-void WEAK dma1_stream4_isr(void);
-void WEAK dma1_stream5_isr(void);
-void WEAK dma1_stream6_isr(void);
-void WEAK adc_isr(void);
-void WEAK can1_tx_isr(void);
-void WEAK can1_rx0_isr(void);
-void WEAK can1_rx1_isr(void);
-void WEAK can1_sce_isr(void);
-void WEAK exti9_5_isr(void);
-void WEAK tim1_brk_tim9_isr(void);
-void WEAK tim1_up_tim10_isr(void);
-void WEAK tim1_trg_com_tim11_isr(void);
-void WEAK tim1_cc_isr(void);
-void WEAK tim2_isr(void);
-void WEAK tim3_isr(void);
-void WEAK tim4_isr(void);
-void WEAK i2c1_ev_isr(void);
-void WEAK i2c1_er_isr(void);
-void WEAK i2c2_ev_isr(void);
-void WEAK i2c2_er_isr(void);
-void WEAK spi1_isr(void);
-void WEAK spi2_isr(void);
-void WEAK usart1_isr(void);
-void WEAK usart2_isr(void);
-void WEAK usart3_isr(void);
-void WEAK exti15_10_isr(void);
-void WEAK rtc_alarm_isr(void);
-void WEAK usb_fs_wkup_isr(void);
-void WEAK tim8_brk_tim12_isr(void);
-void WEAK tim8_up_tim13_isr(void);
-void WEAK tim8_trg_com_tim14_isr(void);
-void WEAK tim8_cc_isr(void);
-void WEAK dma1_stream7_isr(void);
-void WEAK fsmc_isr(void);
-void WEAK sdio_isr(void);
-void WEAK tim5_isr(void);
-void WEAK spi3_isr(void);
-void WEAK uart4_isr(void);
-void WEAK uart5_isr(void);
-void WEAK tim6_dac_isr(void);
-void WEAK tim7_isr(void);
-void WEAK dma2_stream0_isr(void);
-void WEAK dma2_stream1_isr(void);
-void WEAK dma2_stream2_isr(void);
-void WEAK dma2_stream3_isr(void);
-void WEAK dma2_stream4_isr(void);
-void WEAK eth_isr(void);
-void WEAK eth_wkup_isr(void);
-void WEAK can2_tx_isr(void);
-void WEAK can2_rx0_isr(void);
-void WEAK can2_rx1_isr(void);
-void WEAK can2_sce_isr(void);
-void WEAK otg_fs_isr(void);
-void WEAK dma2_stream5_isr(void);
-void WEAK dma2_stream6_isr(void);
-void WEAK dma2_stream7_isr(void);
-void WEAK usart6_isr(void);
-void WEAK i2c3_ev_isr(void);
-void WEAK i2c3_er_isr(void);
-void WEAK otg_hs_ep1_out_isr(void);
-void WEAK otg_hs_ep1_in_isr(void);
-void WEAK otg_hs_wkup_isr(void);
-void WEAK otg_hs_isr(void);
-void WEAK dcmi_isr(void);
-void WEAK cryp_isr(void);
-void WEAK hash_rng_isr(void);
-
-__attribute__ ((section(".vectors")))
-void (*const vector_table[]) (void) = {
- (void *)&_stack,
- reset_handler,
- nmi_handler,
- hard_fault_handler,
- mem_manage_handler,
- bus_fault_handler,
- usage_fault_handler,
- 0, 0, 0, 0, /* Reserved */
- sv_call_handler,
- debug_monitor_handler,
- 0, /* Reserved */
- pend_sv_handler,
- sys_tick_handler,
- wwdg_isr,
- pvd_isr,
- tamp_stamp_isr,
- rtc_wkup_isr,
- flash_isr,
- rcc_isr,
- exti0_isr,
- exti1_isr,
- exti2_isr,
- exti3_isr,
- exti4_isr,
- dma1_stream0_isr,
- dma1_stream1_isr,
- dma1_stream2_isr,
- dma1_stream3_isr,
- dma1_stream4_isr,
- dma1_stream5_isr,
- dma1_stream6_isr,
- adc_isr,
- can1_tx_isr,
- can1_rx0_isr,
- can1_rx1_isr,
- can1_sce_isr,
- exti9_5_isr,
- tim1_brk_tim9_isr,
- tim1_up_tim10_isr,
- tim1_trg_com_tim11_isr,
- tim1_cc_isr,
- tim2_isr,
- tim3_isr,
- tim4_isr,
- i2c1_ev_isr,
- i2c1_er_isr,
- i2c2_ev_isr,
- i2c2_er_isr,
- spi1_isr,
- spi2_isr,
- usart1_isr,
- usart2_isr,
- usart3_isr,
- exti15_10_isr,
- rtc_alarm_isr,
- usb_fs_wkup_isr,
- tim8_brk_tim12_isr,
- tim8_up_tim13_isr,
- tim8_trg_com_tim14_isr,
- tim8_cc_isr,
- dma1_stream7_isr,
- fsmc_isr,
- sdio_isr,
- tim5_isr,
- spi3_isr,
- uart4_isr,
- uart5_isr,
- tim6_dac_isr,
- tim7_isr,
- dma2_stream0_isr,
- dma2_stream1_isr,
- dma2_stream2_isr,
- dma2_stream3_isr,
- dma2_stream4_isr,
- eth_isr,
- eth_wkup_isr,
- can2_tx_isr,
- can2_rx0_isr,
- can2_rx1_isr,
- can2_sce_isr,
- otg_fs_isr,
- dma2_stream5_isr,
- dma2_stream6_isr,
- dma2_stream7_isr,
- usart6_isr,
- i2c3_ev_isr,
- i2c3_er_isr,
- otg_hs_ep1_out_isr,
- otg_hs_ep1_in_isr,
- otg_hs_wkup_isr,
- otg_hs_isr,
- dcmi_isr,
- cryp_isr,
- hash_rng_isr,
-};
-
-void reset_handler(void)
-{
- volatile unsigned *src, *dest;
-
- __asm__("MSR msp, %0" : : "r"(&_stack));
-
- /* Enable access to Floating-Point coprocessor. */
- SCB_CPACR |= SCB_CPACR_FULL * (SCB_CPACR_CP10 | SCB_CPACR_CP11);
-
- for (src = &_data_loadaddr, dest = &_data; dest < &_edata; src++, dest++)
- *dest = *src;
-
- while (dest < &_ebss)
- *dest++ = 0;
-
- /* Call the application's entry point. */
- main();
-}
-
-void blocking_handler(void)
-{
- while (1) ;
-}
-
-void null_handler(void)
-{
- /* Do nothing. */
-}
-
-#pragma weak nmi_handler = null_handler
-#pragma weak hard_fault_handler = blocking_handler
-#pragma weak mem_manage_handler = blocking_handler
-#pragma weak bus_fault_handler = blocking_handler
-#pragma weak usage_fault_handler = blocking_handler
-#pragma weak sv_call_handler = null_handler
-#pragma weak debug_monitor_handler = null_handler
-#pragma weak pend_sv_handler = null_handler
-#pragma weak sys_tick_handler = null_handler
-#pragma weak wwdg_isr = null_handler
-#pragma weak pvd_isr = null_handler
-#pragma weak tamp_stamp_isr = null_handler
-#pragma weak rtc_wkup_isr = null_handler
-#pragma weak flash_isr = null_handler
-#pragma weak rcc_isr = null_handler
-#pragma weak exti0_isr = null_handler
-#pragma weak exti1_isr = null_handler
-#pragma weak exti2_isr = null_handler
-#pragma weak exti3_isr = null_handler
-#pragma weak exti4_isr = null_handler
-#pragma weak dma1_stream0_isr = null_handler
-#pragma weak dma1_stream1_isr = null_handler
-#pragma weak dma1_stream2_isr = null_handler
-#pragma weak dma1_stream3_isr = null_handler
-#pragma weak dma1_stream4_isr = null_handler
-#pragma weak dma1_stream5_isr = null_handler
-#pragma weak dma1_stream6_isr = null_handler
-#pragma weak adc_isr = null_handler
-#pragma weak can1_tx_isr = null_handler
-#pragma weak can1_rx0_isr = null_handler
-#pragma weak can1_rx1_isr = null_handler
-#pragma weak can1_sce_isr = null_handler
-#pragma weak exti9_5_isr = null_handler
-#pragma weak tim1_brk_tim9_isr = null_handler
-#pragma weak tim1_up_tim10_isr = null_handler
-#pragma weak tim1_trg_com_tim11_isr = null_handler
-#pragma weak tim1_cc_isr = null_handler
-#pragma weak tim2_isr = null_handler
-#pragma weak tim3_isr = null_handler
-#pragma weak tim4_isr = null_handler
-#pragma weak i2c1_ev_isr = null_handler
-#pragma weak i2c1_er_isr = null_handler
-#pragma weak i2c2_ev_isr = null_handler
-#pragma weak i2c2_er_isr = null_handler
-#pragma weak spi1_isr = null_handler
-#pragma weak spi2_isr = null_handler
-#pragma weak usart1_isr = null_handler
-#pragma weak usart2_isr = null_handler
-#pragma weak usart3_isr = null_handler
-#pragma weak exti15_10_isr = null_handler
-#pragma weak rtc_alarm_isr = null_handler
-#pragma weak usb_fs_wkup_isr = null_handler
-#pragma weak tim8_brk_tim12_isr = null_handler
-#pragma weak tim8_up_tim13_isr = null_handler
-#pragma weak tim8_trg_com_tim14_isr = null_handler
-#pragma weak tim8_cc_isr = null_handler
-#pragma weak dma1_stream7_isr = null_handler
-#pragma weak fsmc_isr = null_handler
-#pragma weak sdio_isr = null_handler
-#pragma weak tim5_isr = null_handler
-#pragma weak spi3_isr = null_handler
-#pragma weak uart4_isr = null_handler
-#pragma weak uart5_isr = null_handler
-#pragma weak tim6_dac_isr = null_handler
-#pragma weak tim7_isr = null_handler
-#pragma weak dma2_stream0_isr = null_handler
-#pragma weak dma2_stream1_isr = null_handler
-#pragma weak dma2_stream2_isr = null_handler
-#pragma weak dma2_stream3_isr = null_handler
-#pragma weak dma2_stream4_isr = null_handler
-#pragma weak eth_isr = null_handler
-#pragma weak eth_wkup_isr = null_handler
-#pragma weak can2_tx_isr = null_handler
-#pragma weak can2_rx0_isr = null_handler
-#pragma weak can2_rx1_isr = null_handler
-#pragma weak can2_sce_isr = null_handler
-#pragma weak otg_fs_isr = null_handler
-#pragma weak dma2_stream5_isr = null_handler
-#pragma weak dma2_stream6_isr = null_handler
-#pragma weak dma2_stream7_isr = null_handler
-#pragma weak usart6_isr = null_handler
-#pragma weak i2c3_ev_isr = null_handler
-#pragma weak i2c3_er_isr = null_handler
-#pragma weak otg_hs_ep1_out_isr = null_handler
-#pragma weak otg_hs_ep1_in_isr = null_handler
-#pragma weak otg_hs_wkup_isr = null_handler
-#pragma weak otg_hs_isr = null_handler
-#pragma weak dcmi_isr = null_handler
-#pragma weak cryp_isr = null_handler
-#pragma weak hash_rng_isr = null_handler
diff --git a/lib/stm32/f4/vector_chipset.c b/lib/stm32/f4/vector_chipset.c
new file mode 100644
index 0000000..145be05
--- /dev/null
+++ b/lib/stm32/f4/vector_chipset.c
@@ -0,0 +1,27 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
+ * Copyright (C) 2011 Fergus Noble <fergusnoble@gmail.com>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/cm3/scb.h>
+
+static void pre_main(void)
+{
+ /* Enable access to Floating-Point coprocessor. */
+ SCB_CPACR |= SCB_CPACR_FULL * (SCB_CPACR_CP10 | SCB_CPACR_CP11);
+}
diff --git a/lib/stm32/l1/Makefile b/lib/stm32/l1/Makefile
new file mode 100644
index 0000000..9b677ab
--- /dev/null
+++ b/lib/stm32/l1/Makefile
@@ -0,0 +1,40 @@
+##
+## This file is part of the libopencm3 project.
+##
+## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
+##
+## This library is free software: you can redistribute it and/or modify
+## it under the terms of the GNU Lesser General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This library 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 Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public License
+## along with this library. If not, see <http://www.gnu.org/licenses/>.
+##
+
+LIBNAME = libopencm3_stm32l1
+
+PREFIX ?= arm-none-eabi
+#PREFIX ?= arm-elf
+CC = $(PREFIX)-gcc
+AR = $(PREFIX)-ar
+CFLAGS = -Os -g -Wall -Wextra -I../../../include -fno-common \
+ -mcpu=cortex-m3 -mthumb -Wstrict-prototypes \
+ -ffunction-sections -fdata-sections -MD -DSTM32L1
+# ARFLAGS = rcsv
+ARFLAGS = rcs
+OBJS = rcc.o desig.o crc.o usart.o exti2.o flash.o timer.o
+OBJS += gpio_common_all.o gpio_common_f24.o spi_common_all.o crc_common_all.o
+OBJS += dac_common_all.o usart_common_all.o iwdg_common_all.o i2c_common_all.o
+OBJS += pwr_common_all.o pwr.o
+OBJS += rtc_common_bcd.o
+
+VPATH += ../../usb:../:../../cm3:../common
+
+include ../../Makefile.include
+
diff --git a/lib/stm32/l1/crc.c b/lib/stm32/l1/crc.c
new file mode 100644
index 0000000..7d51341
--- /dev/null
+++ b/lib/stm32/l1/crc.c
@@ -0,0 +1,29 @@
+/** @defgroup crc_file CRC
+
+@ingroup STM32L1xx
+
+@brief <b>libopencm3 STM32L1xx CRC</b>
+
+*/
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/crc.h>
+#include <libopencm3/stm32/common/crc_common_all.h>
+
+
diff --git a/lib/stm32/l1/dac.c b/lib/stm32/l1/dac.c
new file mode 100644
index 0000000..534f9f1
--- /dev/null
+++ b/lib/stm32/l1/dac.c
@@ -0,0 +1,28 @@
+/** @defgroup dac_file DAC
+
+@ingroup STM32L1xx
+
+@brief <b>libopencm3 STM32L1xx DAC</b>
+
+*/
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/dac.h>
+#include <libopencm3/stm32/common/dac_common_all.h>
+
diff --git a/lib/stm32/l1/flash.c b/lib/stm32/l1/flash.c
new file mode 100644
index 0000000..7b20f69
--- /dev/null
+++ b/lib/stm32/l1/flash.c
@@ -0,0 +1,52 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
+ * Copyright (C) 2010 Mark Butler <mbutler@physics.otago.ac.nz>
+ * Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/l1/flash.h>
+
+void flash_64bit_enable(void)
+{
+ FLASH_ACR |= FLASH_ACR_ACC64;
+}
+
+void flash_64bit_disable(void)
+{
+ FLASH_ACR &= ~FLASH_ACR_ACC64;
+}
+
+void flash_prefetch_enable(void)
+{
+ FLASH_ACR |= FLASH_ACR_PRFTEN;
+}
+
+void flash_prefetch_disable(void)
+{
+ FLASH_ACR &= ~FLASH_ACR_PRFTEN;
+}
+
+void flash_set_ws(u32 ws)
+{
+ u32 reg32;
+
+ reg32 = FLASH_ACR;
+ reg32 &= ~(1 << 0);
+ reg32 |= ws;
+ FLASH_ACR = reg32;
+} \ No newline at end of file
diff --git a/lib/stm32/l1/gpio.c b/lib/stm32/l1/gpio.c
new file mode 100644
index 0000000..7fc2012
--- /dev/null
+++ b/lib/stm32/l1/gpio.c
@@ -0,0 +1,28 @@
+/** @defgroup gpio_file GPIO
+
+@ingroup STM32L1xx
+
+@brief <b>libopencm3 STM32L1xx General Purpose I/O</b>
+
+*/
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/gpio.h>
+#include <libopencm3/stm32/common/gpio_common_all.h>
+
diff --git a/lib/stm32/l1/i2c.c b/lib/stm32/l1/i2c.c
new file mode 100644
index 0000000..7a6fe84
--- /dev/null
+++ b/lib/stm32/l1/i2c.c
@@ -0,0 +1,28 @@
+/** @defgroup i2c_file I2C
+
+@ingroup STM32L1xx
+
+@brief <b>libopencm3 STM32L1xx I2C</b>
+
+*/
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/i2c.h>
+#include <libopencm3/stm32/common/spi_common_all.h>
+
diff --git a/lib/stm32/l1/iwdg.c b/lib/stm32/l1/iwdg.c
new file mode 100644
index 0000000..05ddf04
--- /dev/null
+++ b/lib/stm32/l1/iwdg.c
@@ -0,0 +1,28 @@
+/** @defgroup iwdg_file IWDG
+
+@ingroup STM32L1xx
+
+@brief <b>libopencm3 STM32L1xx Independent Watchdog Timer</b>
+
+*/
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/iwdg.h>
+#include <libopencm3/stm32/common/iwdg_common_all.h>
+
diff --git a/lib/stm32/l1/libopencm3_stm32l1.ld b/lib/stm32/l1/libopencm3_stm32l1.ld
new file mode 100644
index 0000000..9d165f6
--- /dev/null
+++ b/lib/stm32/l1/libopencm3_stm32l1.ld
@@ -0,0 +1,83 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Generic linker script for STM32 targets using libopencm3. */
+
+/* Memory regions must be defined in the ld script which includes this one. */
+
+/* Enforce emmition of the vector table. */
+EXTERN (vector_table)
+
+/* Define the entry point of the output file. */
+ENTRY(reset_handler)
+
+/* Define sections. */
+SECTIONS
+{
+ .text : {
+ *(.vectors) /* Vector table */
+ *(.text*) /* Program code */
+ . = ALIGN(4);
+ *(.rodata*) /* Read-only data */
+ . = ALIGN(4);
+ } >rom
+
+ /*
+ * Another section used by C++ stuff, appears when using newlib with
+ * 64bit (long long) printf support
+ */
+ .ARM.extab : {
+ *(.ARM.extab*)
+ } >rom
+ .ARM.exidx : {
+ __exidx_start = .;
+ *(.ARM.exidx*)
+ __exidx_end = .;
+ } >rom
+
+ . = ALIGN(4);
+ _etext = .;
+
+ .data : {
+ _data = .;
+ *(.data*) /* Read-write initialized data */
+ . = ALIGN(4);
+ _edata = .;
+ } >ram AT >rom
+ _data_loadaddr = LOADADDR(.data);
+
+ .bss : {
+ *(.bss*) /* Read-write zero initialized data */
+ *(COMMON)
+ . = ALIGN(4);
+ _ebss = .;
+ } >ram
+
+ /*
+ * The .eh_frame section appears to be used for C++ exception handling.
+ * You may need to fix this if you're using C++.
+ */
+ /DISCARD/ : { *(.eh_frame) }
+
+ . = ALIGN(4);
+ end = .;
+}
+
+PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram));
+
diff --git a/lib/stm32/l1/pwr.c b/lib/stm32/l1/pwr.c
new file mode 100644
index 0000000..8541851
--- /dev/null
+++ b/lib/stm32/l1/pwr.c
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/pwr.h>
+
+void pwr_set_vos_scale(vos_scale_t scale)
+{
+ PWR_CR &= ~(PWR_CR_VOS_MASK);
+ switch (scale) {
+ case RANGE1:
+ PWR_CR |= PWR_CR_VOS_RANGE1;
+ break;
+ case RANGE2:
+ PWR_CR |= PWR_CR_VOS_RANGE2;
+ break;
+ case RANGE3:
+ PWR_CR |= PWR_CR_VOS_RANGE3;
+ break;
+ }
+}
+
diff --git a/lib/stm32/l1/rcc.c b/lib/stm32/l1/rcc.c
new file mode 100644
index 0000000..106032a
--- /dev/null
+++ b/lib/stm32/l1/rcc.c
@@ -0,0 +1,549 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2009 Federico Ruiz-Ugalde <memeruiz at gmail dot com>
+ * Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
+ * Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
+ * Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ * Based on the F4 code...
+ */
+
+#include <libopencm3/stm32/l1/rcc.h>
+#include <libopencm3/stm32/l1/flash.h>
+#include <libopencm3/stm32/pwr.h>
+
+/* Set the default ppre1 and ppre2 peripheral clock frequencies after reset. */
+u32 rcc_ppre1_frequency = 2097000;
+u32 rcc_ppre2_frequency = 2097000;
+
+const clock_scale_t clock_config[CLOCK_CONFIG_END] =
+{
+ { /* 24MHz PLL from HSI */
+ .pll_source = RCC_CFGR_PLLSRC_HSI_CLK,
+ .pll_mul = RCC_CFGR_PLLMUL_MUL3,
+ .pll_div = RCC_CFGR_PLLDIV_DIV2,
+ .hpre = RCC_CFGR_HPRE_SYSCLK_NODIV,
+ .ppre1 = RCC_CFGR_PPRE1_HCLK_NODIV,
+ .ppre2 = RCC_CFGR_PPRE2_HCLK_NODIV,
+ .voltage_scale = RANGE1,
+ .flash_config = FLASH_ACR_LATENCY_1WS,
+ .apb1_frequency = 24000000,
+ .apb2_frequency = 24000000,
+ },
+ { /* 32MHz PLL from HSI */
+ .pll_source = RCC_CFGR_PLLSRC_HSI_CLK,
+ .pll_mul = RCC_CFGR_PLLMUL_MUL6,
+ .pll_div = RCC_CFGR_PLLDIV_DIV3,
+ .hpre = RCC_CFGR_HPRE_SYSCLK_NODIV,
+ .ppre1 = RCC_CFGR_PPRE1_HCLK_NODIV,
+ .ppre2 = RCC_CFGR_PPRE2_HCLK_NODIV,
+ .voltage_scale = RANGE1,
+ .flash_config = FLASH_ACR_LATENCY_1WS,
+ .apb1_frequency = 32000000,
+ .apb2_frequency = 32000000,
+ },
+ { /* 16MHz HSI raw */
+ .hpre = RCC_CFGR_HPRE_SYSCLK_NODIV,
+ .ppre1 = RCC_CFGR_PPRE1_HCLK_NODIV,
+ .ppre2 = RCC_CFGR_PPRE2_HCLK_NODIV,
+ .voltage_scale = RANGE1,
+ .flash_config = FLASH_ACR_LATENCY_0WS,
+ .apb1_frequency = 16000000,
+ .apb2_frequency = 16000000,
+ },
+ { /* 4MHz HSI raw */
+ .hpre = RCC_CFGR_HPRE_SYSCLK_DIV4,
+ .ppre1 = RCC_CFGR_PPRE1_HCLK_NODIV,
+ .ppre2 = RCC_CFGR_PPRE2_HCLK_NODIV,
+ .voltage_scale = RANGE1,
+ .flash_config = FLASH_ACR_LATENCY_0WS,
+ .apb1_frequency = 4000000,
+ .apb2_frequency = 4000000,
+ },
+ { /* 4MHz MSI raw */
+ .hpre = RCC_CFGR_HPRE_SYSCLK_NODIV,
+ .ppre1 = RCC_CFGR_PPRE1_HCLK_NODIV,
+ .ppre2 = RCC_CFGR_PPRE2_HCLK_NODIV,
+ .voltage_scale = RANGE1,
+ .flash_config = FLASH_ACR_LATENCY_0WS,
+ .apb1_frequency = 4194000,
+ .apb2_frequency = 4194000,
+ .msi_range = RCC_ICSCR_MSIRANGE_4MHZ,
+ },
+ { /* 2MHz MSI raw */
+ .hpre = RCC_CFGR_HPRE_SYSCLK_NODIV,
+ .ppre1 = RCC_CFGR_PPRE1_HCLK_NODIV,
+ .ppre2 = RCC_CFGR_PPRE2_HCLK_NODIV,
+ .voltage_scale = RANGE1,
+ .flash_config = FLASH_ACR_LATENCY_0WS,
+ .apb1_frequency = 2097000,
+ .apb2_frequency = 2097000,
+ .msi_range = RCC_ICSCR_MSIRANGE_2MHZ,
+ },
+};
+
+void rcc_osc_ready_int_clear(osc_t osc)
+{
+ switch (osc) {
+ case PLL:
+ RCC_CIR |= RCC_CIR_PLLRDYC;
+ break;
+ case HSE:
+ RCC_CIR |= RCC_CIR_HSERDYC;
+ break;
+ case HSI:
+ RCC_CIR |= RCC_CIR_HSIRDYC;
+ break;
+ case LSE:
+ RCC_CIR |= RCC_CIR_LSERDYC;
+ break;
+ case LSI:
+ RCC_CIR |= RCC_CIR_LSIRDYC;
+ break;
+ case MSI:
+ RCC_CIR |= RCC_CIR_MSIRDYC;
+ break;
+ }
+}
+
+void rcc_osc_ready_int_enable(osc_t osc)
+{
+ switch (osc) {
+ case PLL:
+ RCC_CIR |= RCC_CIR_PLLRDYIE;
+ break;
+ case HSE:
+ RCC_CIR |= RCC_CIR_HSERDYIE;
+ break;
+ case HSI:
+ RCC_CIR |= RCC_CIR_HSIRDYIE;
+ break;
+ case LSE:
+ RCC_CIR |= RCC_CIR_LSERDYIE;
+ break;
+ case LSI:
+ RCC_CIR |= RCC_CIR_LSIRDYIE;
+ break;
+ case MSI:
+ RCC_CIR |= RCC_CIR_MSIRDYIE;
+ break;
+ }
+}
+
+void rcc_osc_ready_int_disable(osc_t osc)
+{
+ switch (osc) {
+ case PLL:
+ RCC_CIR &= ~RCC_CIR_PLLRDYIE;
+ break;
+ case HSE:
+ RCC_CIR &= ~RCC_CIR_HSERDYIE;
+ break;
+ case HSI:
+ RCC_CIR &= ~RCC_CIR_HSIRDYIE;
+ break;
+ case LSE:
+ RCC_CIR &= ~RCC_CIR_LSERDYIE;
+ break;
+ case LSI:
+ RCC_CIR &= ~RCC_CIR_LSIRDYIE;
+ break;
+ case MSI:
+ RCC_CIR &= ~RCC_CIR_MSIRDYIE;
+ break;
+ }
+}
+
+int rcc_osc_ready_int_flag(osc_t osc)
+{
+ switch (osc) {
+ case PLL:
+ return ((RCC_CIR & RCC_CIR_PLLRDYF) != 0);
+ break;
+ case HSE:
+ return ((RCC_CIR & RCC_CIR_HSERDYF) != 0);
+ break;
+ case HSI:
+ return ((RCC_CIR & RCC_CIR_HSIRDYF) != 0);
+ break;
+ case LSE:
+ return ((RCC_CIR & RCC_CIR_LSERDYF) != 0);
+ break;
+ case LSI:
+ return ((RCC_CIR & RCC_CIR_LSIRDYF) != 0);
+ break;
+ case MSI:
+ return ((RCC_CIR & RCC_CIR_MSIRDYF) != 0);
+ break;
+ }
+
+ /* Shouldn't be reached. */
+ return -1;
+}
+
+void rcc_css_int_clear(void)
+{
+ RCC_CIR |= RCC_CIR_CSSC;
+}
+
+int rcc_css_int_flag(void)
+{
+ return ((RCC_CIR & RCC_CIR_CSSF) != 0);
+}
+
+void rcc_wait_for_osc_ready(osc_t osc)
+{
+ switch (osc) {
+ case PLL:
+ while ((RCC_CR & RCC_CR_PLLRDY) == 0);
+ break;
+ case HSE:
+ while ((RCC_CR & RCC_CR_HSERDY) == 0);
+ break;
+ case HSI:
+ while ((RCC_CR & RCC_CR_HSIRDY) == 0);
+ break;
+ case MSI:
+ while ((RCC_CR & RCC_CR_MSIRDY) == 0);
+ break;
+ case LSE:
+ while ((RCC_CSR & RCC_CSR_LSERDY) == 0);
+ break;
+ case LSI:
+ while ((RCC_CSR & RCC_CSR_LSIRDY) == 0);
+ break;
+ }
+}
+
+void rcc_wait_for_sysclk_status(osc_t osc)
+{
+ switch (osc) {
+ case PLL:
+ while ((RCC_CFGR & ((1 << 1) | (1 << 0))) != RCC_CFGR_SWS_SYSCLKSEL_PLLCLK);
+ break;
+ case HSE:
+ while ((RCC_CFGR & ((1 << 1) | (1 << 0))) != RCC_CFGR_SWS_SYSCLKSEL_HSECLK);
+ break;
+ case HSI:
+ while ((RCC_CFGR & ((1 << 1) | (1 << 0))) != RCC_CFGR_SWS_SYSCLKSEL_HSICLK);
+ break;
+ case MSI:
+ while ((RCC_CFGR & ((1 << 1) | (1 << 0))) != RCC_CFGR_SWS_SYSCLKSEL_MSICLK);
+ break;
+ default:
+ /* Shouldn't be reached. */
+ break;
+ }
+}
+
+void rcc_osc_on(osc_t osc)
+{
+ switch (osc) {
+ case PLL:
+ RCC_CR |= RCC_CR_PLLON;
+ break;
+ case MSI:
+ RCC_CR |= RCC_CR_MSION;
+ break;
+ case HSE:
+ RCC_CR |= RCC_CR_HSEON;
+ break;
+ case HSI:
+ RCC_CR |= RCC_CR_HSION;
+ break;
+ case LSE:
+ RCC_CSR |= RCC_CSR_LSEON;
+ break;
+ case LSI:
+ RCC_CSR |= RCC_CSR_LSION;
+ break;
+ }
+}
+
+void rcc_osc_off(osc_t osc)
+{
+ switch (osc) {
+ case PLL:
+ RCC_CR &= ~RCC_CR_PLLON;
+ break;
+ case MSI:
+ RCC_CR &= ~RCC_CR_MSION;
+ break;
+ case HSE:
+ RCC_CR &= ~RCC_CR_HSEON;
+ break;
+ case HSI:
+ RCC_CR &= ~RCC_CR_HSION;
+ break;
+ case LSE:
+ RCC_CSR &= ~RCC_CSR_LSEON;
+ break;
+ case LSI:
+ RCC_CSR &= ~RCC_CSR_LSION;
+ break;
+ }
+}
+
+void rcc_css_enable(void)
+{
+ RCC_CR |= RCC_CR_CSSON;
+}
+
+void rcc_css_disable(void)
+{
+ RCC_CR &= ~RCC_CR_CSSON;
+}
+
+void rcc_osc_bypass_enable(osc_t osc)
+{
+ switch (osc) {
+ case HSE:
+ RCC_CR |= RCC_CR_HSEBYP;
+ break;
+ case LSE:
+ RCC_CSR |= RCC_CSR_LSEBYP;
+ break;
+ case PLL:
+ case HSI:
+ case LSI:
+ case MSI:
+ /* Do nothing, only HSE/LSE allowed here. */
+ break;
+ }
+}
+
+void rcc_osc_bypass_disable(osc_t osc)
+{
+ switch (osc) {
+ case HSE:
+ RCC_CR &= ~RCC_CR_HSEBYP;
+ break;
+ case LSE:
+ RCC_CSR &= ~RCC_CSR_LSEBYP;
+ break;
+ case PLL:
+ case HSI:
+ case LSI:
+ case MSI:
+ /* Do nothing, only HSE/LSE allowed here. */
+ break;
+ }
+}
+
+void rcc_peripheral_enable_clock(volatile u32 *reg, u32 en)
+{
+ *reg |= en;
+}
+
+void rcc_peripheral_disable_clock(volatile u32 *reg, u32 en)
+{
+ *reg &= ~en;
+}
+
+void rcc_peripheral_reset(volatile u32 *reg, u32 reset)
+{
+ *reg |= reset;
+}
+
+void rcc_peripheral_clear_reset(volatile u32 *reg, u32 clear_reset)
+{
+ *reg &= ~clear_reset;
+}
+
+void rcc_set_sysclk_source(u32 clk)
+{
+ u32 reg32;
+
+ reg32 = RCC_CFGR;
+ reg32 &= ~((1 << 1) | (1 << 0));
+ RCC_CFGR = (reg32 | clk);
+}
+
+void rcc_set_pll_configuration(u32 source, u32 multiplier, u32 divisor)
+{
+ u32 reg32;
+
+ reg32 = RCC_CFGR;
+ reg32 &= ~(RCC_CFGR_PLLDIV_MASK << RCC_CFGR_PLLDIV_SHIFT);
+ reg32 &= ~(RCC_CFGR_PLLMUL_MASK << RCC_CFGR_PLLMUL_SHIFT);
+ reg32 &= ~(1 << 16);
+ reg32 |= (source << 16);
+ reg32 |= (multiplier << RCC_CFGR_PLLMUL_SHIFT);
+ reg32 |= (divisor << RCC_CFGR_PLLDIV_SHIFT);
+ RCC_CFGR = reg32;
+}
+
+void rcc_set_pll_source(u32 pllsrc)
+{
+ u32 reg32;
+
+ reg32 = RCC_CFGR;
+ reg32 &= ~(1 << 16);
+ RCC_CFGR = (reg32 | (pllsrc << 16));
+}
+
+void rcc_set_ppre2(u32 ppre2)
+{
+ u32 reg32;
+
+ reg32 = RCC_CFGR;
+ reg32 &= ~((1 << 13) | (1 << 12) | (1 << 11));
+ RCC_CFGR = (reg32 | (ppre2 << 11));
+}
+
+void rcc_set_ppre1(u32 ppre1)
+{
+ u32 reg32;
+
+ reg32 = RCC_CFGR;
+ reg32 &= ~((1 << 10) | (1 << 9) | (1 << 8));
+ RCC_CFGR = (reg32 | (ppre1 << 8));
+}
+
+void rcc_set_hpre(u32 hpre)
+{
+ u32 reg32;
+
+ reg32 = RCC_CFGR;
+ reg32 &= ~((1 << 4) | (1 << 5) | (1 << 6) | (1 << 7));
+ RCC_CFGR = (reg32 | (hpre << 4));
+}
+
+void rcc_set_rtcpre(u32 rtcpre)
+{
+ u32 reg32;
+
+ reg32 = RCC_CR;
+ reg32 &= ~((1 << 30) | (1 << 29));
+ RCC_CR = (reg32 | (rtcpre << 29));
+}
+
+u32 rcc_system_clock_source(void)
+{
+ /* Return the clock source which is used as system clock. */
+ return ((RCC_CFGR & 0x000c) >> 2);
+}
+
+void rcc_rtc_select_clock(u32 clock)
+{
+ RCC_CSR &= ~(RCC_CSR_RTCSEL_MASK << RCC_CSR_RTCSEL_SHIFT);
+ RCC_CSR |= (clock << RCC_CSR_RTCSEL_SHIFT);
+}
+
+void rcc_clock_setup_msi(const clock_scale_t *clock)
+{
+ /* Enable internal multi-speed oscillator. */
+
+ u32 reg = RCC_ICSCR;
+ reg &= ~(RCC_ICSCR_MSIRANGE_MASK << RCC_ICSCR_MSIRANGE_SHIFT);
+ reg |= (clock->msi_range << RCC_ICSCR_MSIRANGE_SHIFT);
+ RCC_ICSCR = reg;
+
+ rcc_osc_on(MSI);
+ rcc_wait_for_osc_ready(MSI);
+
+ /* Select MSI as SYSCLK source. */
+ rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_MSICLK);
+
+ /*
+ * Set prescalers for AHB, ADC, ABP1, ABP2.
+ * Do this before touching the PLL (TODO: why?).
+ */
+ rcc_set_hpre(clock->hpre);
+ rcc_set_ppre1(clock->ppre1);
+ rcc_set_ppre2(clock->ppre2);
+
+ pwr_set_vos_scale(clock->voltage_scale);
+
+ // I guess this should be in the settings?
+ flash_64bit_enable();
+ flash_prefetch_enable();
+ /* Configure flash settings. */
+ flash_set_ws(clock->flash_config);
+
+ /* Set the peripheral clock frequencies used. */
+ rcc_ppre1_frequency = clock->apb1_frequency;
+ rcc_ppre2_frequency = clock->apb2_frequency;
+}
+
+void rcc_clock_setup_hsi(const clock_scale_t *clock)
+{
+ /* Enable internal high-speed oscillator. */
+ rcc_osc_on(HSI);
+ rcc_wait_for_osc_ready(HSI);
+
+ /* Select HSI as SYSCLK source. */
+ rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSICLK);
+
+ /*
+ * Set prescalers for AHB, ADC, ABP1, ABP2.
+ * Do this before touching the PLL (TODO: why?).
+ */
+ rcc_set_hpre(clock->hpre);
+ rcc_set_ppre1(clock->ppre1);
+ rcc_set_ppre2(clock->ppre2);
+
+ pwr_set_vos_scale(clock->voltage_scale);
+
+ // I guess this should be in the settings?
+ flash_64bit_enable();
+ flash_prefetch_enable();
+ /* Configure flash settings. */
+ flash_set_ws(clock->flash_config);
+
+ /* Set the peripheral clock frequencies used. */
+ rcc_ppre1_frequency = clock->apb1_frequency;
+ rcc_ppre2_frequency = clock->apb2_frequency;
+}
+
+void rcc_clock_setup_pll(const clock_scale_t *clock)
+{
+ /* Enable internal high-speed oscillator. */
+ rcc_osc_on(HSI);
+ rcc_wait_for_osc_ready(HSI);
+
+ /* Select HSI as SYSCLK source. */
+ rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSICLK);
+
+ /*
+ * Set prescalers for AHB, ADC, ABP1, ABP2.
+ * Do this before touching the PLL (TODO: why?).
+ */
+ rcc_set_hpre(clock->hpre);
+ rcc_set_ppre1(clock->ppre1);
+ rcc_set_ppre2(clock->ppre2);
+
+ pwr_set_vos_scale(clock->voltage_scale);
+
+ // I guess this should be in the settings?
+ flash_64bit_enable();
+ flash_prefetch_enable();
+ /* Configure flash settings. */
+ flash_set_ws(clock->flash_config);
+
+ rcc_set_pll_configuration(clock->pll_source, clock->pll_mul, clock->pll_div);
+
+ /* Enable PLL oscillator and wait for it to stabilize. */
+ rcc_osc_on(PLL);
+ rcc_wait_for_osc_ready(PLL);
+
+ /* Select PLL as SYSCLK source. */
+ rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_PLLCLK);
+
+ /* Set the peripheral clock frequencies used. */
+ rcc_ppre1_frequency = clock->apb1_frequency;
+ rcc_ppre2_frequency = clock->apb2_frequency;
+}
diff --git a/lib/stm32/l1/rtc.c b/lib/stm32/l1/rtc.c
new file mode 100644
index 0000000..bc7f87f
--- /dev/null
+++ b/lib/stm32/l1/rtc.c
@@ -0,0 +1,27 @@
+/** @defgroup rtc_file RTC
+
+@ingroup STM32L1xx
+
+@brief <b>libopencm3 STM32L1xx RTC</b>
+
+*/
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/rtc.h>
+#include <libopencm3/stm32/common/rtc_common_bcd.h>
diff --git a/lib/stm32/l1/spi.c b/lib/stm32/l1/spi.c
new file mode 100644
index 0000000..30c44dd
--- /dev/null
+++ b/lib/stm32/l1/spi.c
@@ -0,0 +1,28 @@
+/** @defgroup spi_file SPI
+
+@ingroup STM32L1xx
+
+@brief <b>libopencm3 STM32L1xx SPI</b>
+
+*/
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/spi.h>
+#include <libopencm3/stm32/common/spi_common_all.h>
+
diff --git a/lib/stm32/f4/scb.c b/lib/stm32/l1/stm32l15xx8.ld
index cbf4d53..1f20f57 100644
--- a/lib/stm32/f4/scb.c
+++ b/lib/stm32/l1/stm32l15xx8.ld
@@ -1,7 +1,7 @@
/*
* This file is part of the libopencm3 project.
*
- * Copyright (C) 2010 Gareth McMullin <gareth@blacksphere.co.nz>
+ * Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -17,19 +17,15 @@
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <libopencm3/stm32/f4/scb.h>
+/* Linker script for STM32L15xx8, 64K flash, 10K RAM. */
-void scb_reset_core(void)
+/* Define memory regions. */
+MEMORY
{
- SCB_AIRCR = SCB_AIRCR_VECTKEY | SCB_AIRCR_VECTRESET;
+ rom (rx) : ORIGIN = 0x08000000, LENGTH = 64K
+ ram (rwx) : ORIGIN = 0x20000000, LENGTH = 10K
}
-void scb_reset_system(void)
-{
- SCB_AIRCR = SCB_AIRCR_VECTKEY | SCB_AIRCR_SYSRESETREQ;
-}
+/* Include the common ld script. */
+INCLUDE libopencm3_stm32l1.ld
-void scb_set_priority_grouping(u32 prigroup)
-{
- SCB_AIRCR = SCB_AIRCR_VECTKEY | prigroup;
-}
diff --git a/lib/stm32/l1/stm32l15xxb.ld b/lib/stm32/l1/stm32l15xxb.ld
new file mode 100644
index 0000000..4c14b71
--- /dev/null
+++ b/lib/stm32/l1/stm32l15xxb.ld
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Linker script for STM32L15xxB, 128K flash, 16K RAM. */
+
+/* Define memory regions. */
+MEMORY
+{
+ rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K
+ ram (rwx) : ORIGIN = 0x20000000, LENGTH = 16K
+}
+
+/* Include the common ld script. */
+INCLUDE libopencm3_stm32l1.ld
+
diff --git a/lib/stm32/l1/usart.c b/lib/stm32/l1/usart.c
new file mode 100644
index 0000000..67fd674
--- /dev/null
+++ b/lib/stm32/l1/usart.c
@@ -0,0 +1,28 @@
+/** @defgroup usart_file USART
+
+@ingroup STM32L1xx
+
+@brief <b>libopencm3 STM32L1xx USART</b>
+
+*/
+
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/usart.h>
+#include <libopencm3/stm32/common/usart_common_all.h>
+
diff --git a/lib/stm32/f1/timer.c b/lib/stm32/timer.c
index 384eaaf..1a346ef 100644
--- a/lib/stm32/f1/timer.c
+++ b/lib/stm32/timer.c
@@ -2,7 +2,7 @@
@ingroup STM32F1xx
-@brief <b>libopencm3 STM32F1xx Timers</b>
+@brief <b>libopencm3 STM32 Timers</b>
@version 1.0.0
@@ -11,9 +11,9 @@
@date 18 August 2012
This library supports the General Purpose and Advanced Control Timers for
-the STM32F1xx series of ARM Cortex Microcontrollers by ST Microelectronics.
+the STM32 series of ARM Cortex Microcontrollers by ST Microelectronics.
-The STM32F1xx series have four general purpose timers (2-5), while some have
+The STM32 series have four general purpose timers (2-5), while some have
an additional two advanced timers (1,8), and some have two basic timers (6,7).
Some of the larger devices have additional general purpose timers (9-14).
@@ -70,6 +70,7 @@ push-pull outputs where the PWM output will appear.
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Edward Cheeseman <evbuilder@users.sourceforge.org>
+ * Copyright (C) 2011 Stephen Caudle <scaudle@doceme.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -96,7 +97,23 @@ push-pull outputs where the PWM output will appear.
/**@{*/
#include <libopencm3/stm32/timer.h>
-#include <libopencm3/stm32/f1/rcc.h>
+
+#if defined(STM32F1)
+#define ADVANCED_TIMERS (defined (TIM1_BASE) || defined(TIM8_BASE))
+# include <libopencm3/stm32/f1/rcc.h>
+#elif defined(STM32F2)
+#define ADVANCED_TIMERS (defined (TIM1_BASE) || defined(TIM8_BASE))
+# include <libopencm3/stm32/f2/timer.h>
+# include <libopencm3/stm32/f2/rcc.h>
+#elif defined(STM32F4)
+#define ADVANCED_TIMERS (defined (TIM1_BASE) || defined(TIM8_BASE))
+# include <libopencm3/stm32/f4/timer.h>
+# include <libopencm3/stm32/f4/rcc.h>
+#elif defined(STM32L1)
+# include <libopencm3/stm32/l1/rcc.h>
+#else
+# error "stm32 family not defined."
+#endif
/*---------------------------------------------------------------------------*/
/** @brief Reset a Timer.
@@ -112,10 +129,12 @@ system.
void timer_reset(u32 timer_peripheral)
{
switch (timer_peripheral) {
+#if defined(TIM1_BASE)
case TIM1:
rcc_peripheral_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM1RST);
rcc_peripheral_clear_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM1RST);
break;
+#endif
case TIM2:
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM2RST);
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM2RST);
@@ -128,10 +147,12 @@ void timer_reset(u32 timer_peripheral)
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM4RST);
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM4RST);
break;
+#if defined(TIM5_BASE)
case TIM5:
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM5RST);
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM5RST);
break;
+#endif
case TIM6:
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM6RST);
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM6RST);
@@ -140,10 +161,12 @@ void timer_reset(u32 timer_peripheral)
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM7RST);
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM7RST);
break;
+#if defined(TIM8_BASE)
case TIM8:
rcc_peripheral_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM8RST);
rcc_peripheral_clear_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM8RST);
break;
+#endif
/* These timers are not supported in libopencm3 yet */
/*
case TIM9:
@@ -218,8 +241,10 @@ bool timer_interrupt_source(u32 timer_peripheral, u32 flag)
if (((TIM_SR(timer_peripheral) & TIM_DIER(timer_peripheral) & flag) == 0) ||
(flag > TIM_SR_BIF)) return false;
/* Only an interrupt source for advanced timers */
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((flag == TIM_SR_BIF) || (flag == TIM_SR_COMIF))
return ((timer_peripheral == TIM1) || (timer_peripheral == TIM8));
+#endif
return true;
}
@@ -404,7 +429,7 @@ void timer_continuous_mode(u32 timer_peripheral)
/*---------------------------------------------------------------------------*/
/** @brief Set the Timer to Generate Update IRQ or DMA on any Event.
-The events which will generate an interrupt or DMA request can be
+The events which will generate an interrupt or DMA request can be
@li a counter underflow/overflow,
@li a forced update,
@li an event from the slave mode controller.
@@ -492,8 +517,10 @@ If several settings are to be made, use the logical OR of the output control val
void timer_set_output_idle_state(u32 timer_peripheral, u32 outputs)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_CR2(timer_peripheral) |= outputs & TIM_CR2_OIS_MASK;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -511,8 +538,10 @@ This determines the value of the timer output compare when it enters idle state.
void timer_reset_output_idle_state(u32 timer_peripheral, u32 outputs)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_CR2(timer_peripheral) &= ~(outputs & TIM_CR2_OIS_MASK);
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -599,8 +628,10 @@ outputs.
void timer_enable_compare_control_update_on_trigger(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_CR2(timer_peripheral) |= TIM_CR2_CCUS;
+ TIM_CR2(timer_peripheral) |= TIM_CR2_CCUS;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -618,8 +649,10 @@ outputs.
void timer_disable_compare_control_update_on_trigger(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_CR2(timer_peripheral) &= ~TIM_CR2_CCUS;
+ TIM_CR2(timer_peripheral) &= ~TIM_CR2_CCUS;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -636,8 +669,10 @@ outputs.
void timer_enable_preload_complementry_enable_bits(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_CR2(timer_peripheral) |= TIM_CR2_CCPC;
+ TIM_CR2(timer_peripheral) |= TIM_CR2_CCPC;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -653,8 +688,10 @@ outputs.
void timer_disable_preload_complementry_enable_bits(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
- TIM_CR2(timer_peripheral) &= ~TIM_CR2_CCPC;
+ TIM_CR2(timer_peripheral) &= ~TIM_CR2_CCPC;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -685,8 +722,10 @@ count cycles have been completed.
void timer_set_repetition_counter(u32 timer_peripheral, u32 value)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_RCR(timer_peripheral) = value;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1007,7 +1046,7 @@ void timer_set_oc_mode(u32 timer_peripheral, enum tim_oc_id oc_id,
/** @brief Timer Enable the Output Compare Preload Register
@param[in] timer_peripheral Unsigned int32. Timer register address base @ref tim_reg_base
-@param[in] oc_id enum ::tim_oc_id OC channel designators
+@param[in] oc_id enum ::tim_oc_id OC channel designators
TIM_OCx where x=1..4, TIM_OCxN where x=1..3 (no action taken)
*/
@@ -1038,7 +1077,7 @@ void timer_enable_oc_preload(u32 timer_peripheral, enum tim_oc_id oc_id)
/** @brief Timer Disable the Output Compare Preload Register
@param[in] timer_peripheral Unsigned int32. Timer register address base @ref tim_reg_base
-@param[in] oc_id enum ::tim_oc_id OC channel designators
+@param[in] oc_id enum ::tim_oc_id OC channel designators
TIM_OCx where x=1..4, TIM_OCxN where x=1..3 (no action)
*/
@@ -1071,7 +1110,7 @@ void timer_disable_oc_preload(u32 timer_peripheral, enum tim_oc_id oc_id)
The polarity of the channel output is set active high.
@param[in] timer_peripheral Unsigned int32. Timer register address base @ref tim_reg_base
-@param[in] oc_id enum ::tim_oc_id OC channel designators
+@param[in] oc_id enum ::tim_oc_id OC channel designators
TIM_OCx where x=1..4, TIM_OCxN where x=1..3 (only for advanced timers 1 and 8)
*/
@@ -1098,8 +1137,12 @@ void timer_set_oc_polarity_high(u32 timer_peripheral, enum tim_oc_id oc_id)
}
/* Acting for TIM1 and TIM8 only from here onwards. */
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral != TIM1) && (timer_peripheral != TIM8))
return;
+#else
+ return;
+#endif
switch (oc_id) {
case TIM_OC1N:
@@ -1126,7 +1169,7 @@ void timer_set_oc_polarity_high(u32 timer_peripheral, enum tim_oc_id oc_id)
The polarity of the channel output is set active low.
@param[in] timer_peripheral Unsigned int32. Timer register address base @ref tim_reg_base
-@param[in] oc_id enum ::tim_oc_id OC channel designators
+@param[in] oc_id enum ::tim_oc_id OC channel designators
TIM_OCx where x=1..4, TIM_OCxN where x=1..3 (only for advanced timers 1 and 8)
*/
@@ -1153,8 +1196,12 @@ void timer_set_oc_polarity_low(u32 timer_peripheral, enum tim_oc_id oc_id)
}
/* Acting for TIM1 and TIM8 only from here onwards. */
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral != TIM1) && (timer_peripheral != TIM8))
return;
+#else
+ return;
+#endif
switch (oc_id) {
case TIM_OC1N:
@@ -1181,7 +1228,7 @@ void timer_set_oc_polarity_low(u32 timer_peripheral, enum tim_oc_id oc_id)
The channel output compare functionality is enabled.
@param[in] timer_peripheral Unsigned int32. Timer register address base @ref tim_reg_base
-@param[in] oc_id enum ::tim_oc_id OC channel designators
+@param[in] oc_id enum ::tim_oc_id OC channel designators
TIM_OCx where x=1..4, TIM_OCxN where x=1..3 (only for advanced timers 1 and 8)
*/
@@ -1208,8 +1255,12 @@ void timer_enable_oc_output(u32 timer_peripheral, enum tim_oc_id oc_id)
}
/* Acting for TIM1 and TIM8 only from here onwards. */
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral != TIM1) && (timer_peripheral != TIM8))
return;
+#else
+ return;
+#endif
switch (oc_id) {
case TIM_OC1N:
@@ -1236,7 +1287,7 @@ void timer_enable_oc_output(u32 timer_peripheral, enum tim_oc_id oc_id)
The channel output compare functionality is disabled.
@param[in] timer_peripheral Unsigned int32. Timer register address base @ref tim_reg_base
-@param[in] oc_id enum ::tim_oc_id OC channel designators
+@param[in] oc_id enum ::tim_oc_id OC channel designators
TIM_OCx where x=1..4, TIM_OCxN where x=1..3 (only for advanced timers 1 and 8)
*/
@@ -1263,8 +1314,12 @@ void timer_disable_oc_output(u32 timer_peripheral, enum tim_oc_id oc_id)
}
/* Acting for TIM1 and TIM8 only from here onwards. */
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral != TIM1) && (timer_peripheral != TIM8))
return;
+#else
+ return;
+#endif
switch (oc_id) {
case TIM_OC1N:
@@ -1294,12 +1349,13 @@ void timer_disable_oc_output(u32 timer_peripheral, enum tim_oc_id oc_id)
@note This setting is only valid for the advanced timers.
@param[in] timer_peripheral Unsigned int32. Timer register address base @ref tim_reg_base
-@param[in] oc_id enum ::tim_oc_id OC channel designators
+@param[in] oc_id enum ::tim_oc_id OC channel designators
TIM_OCx where x=1..4, TIM_OCxN where x=1..3 (only for advanced timers 1 and 8)
*/
void timer_set_oc_idle_state_set(u32 timer_peripheral, enum tim_oc_id oc_id)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
/* Acting for TIM1 and TIM8 only. */
if ((timer_peripheral != TIM1) && (timer_peripheral != TIM8))
return;
@@ -1327,6 +1383,7 @@ void timer_set_oc_idle_state_set(u32 timer_peripheral, enum tim_oc_id oc_id)
TIM_CR2(timer_peripheral) |= TIM_CR2_OIS4;
break;
}
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1338,12 +1395,13 @@ void timer_set_oc_idle_state_set(u32 timer_peripheral, enum tim_oc_id oc_id)
@note This setting is only valid for the advanced timers.
@param[in] timer_peripheral Unsigned int32. Timer register address base @ref tim_reg_base
-@param[in] oc_id enum ::tim_oc_id OC channel designators
+@param[in] oc_id enum ::tim_oc_id OC channel designators
TIM_OCx where x=1..4, TIM_OCxN where x=1..3 (only for advanced timers 1 and 8)
*/
void timer_set_oc_idle_state_unset(u32 timer_peripheral, enum tim_oc_id oc_id)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
/* Acting for TIM1 and TIM8 only. */
if ((timer_peripheral != TIM1) && (timer_peripheral != TIM8))
return;
@@ -1371,6 +1429,7 @@ void timer_set_oc_idle_state_unset(u32 timer_peripheral, enum tim_oc_id oc_id)
TIM_CR2(timer_peripheral) &= ~TIM_CR2_OIS4;
break;
}
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1381,7 +1440,7 @@ to the compare register.
@param[in] timer_peripheral Unsigned int32. Timer register address base @ref tim_reg_base
(TIM9 .. TIM14 not yet supported here).
-@param[in] oc_id enum ::tim_oc_id OC channel designators
+@param[in] oc_id enum ::tim_oc_id OC channel designators
TIM_OCx where x=1..4, TIM_OCxN where x=1..3 (no action taken)
@param[in] value Unsigned int32. Compare value.
*/
@@ -1426,8 +1485,10 @@ timer <b>even if break or deadtime features are not being used</b>.
void timer_enable_break_main_output(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_BDTR(timer_peripheral) |= TIM_BDTR_MOE;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1443,8 +1504,10 @@ the Master Output Enable in the Break and Deadtime Register.
void timer_disable_break_main_output(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_BDTR(timer_peripheral) &= ~TIM_BDTR_MOE;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1452,7 +1515,7 @@ void timer_disable_break_main_output(u32 timer_peripheral)
Enables the automatic output feature of the Break function of an advanced
timer so that the output is re-enabled at the next update event following a
-break event.
+break event.
@note This setting is only valid for the advanced timers.
@@ -1461,8 +1524,10 @@ break event.
void timer_enable_break_automatic_output(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_BDTR(timer_peripheral) |= TIM_BDTR_AOE;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1470,7 +1535,7 @@ void timer_enable_break_automatic_output(u32 timer_peripheral)
Disables the automatic output feature of the Break function of an advanced
timer so that the output is re-enabled at the next update event following a
-break event.
+break event.
@note This setting is only valid for the advanced timers.
@@ -1479,8 +1544,10 @@ break event.
void timer_disable_break_automatic_output(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_BDTR(timer_peripheral) &= ~TIM_BDTR_AOE;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1495,8 +1562,10 @@ Sets the break function to activate when the break input becomes high.
void timer_set_break_polarity_high(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_BDTR(timer_peripheral) |= TIM_BDTR_BKP;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1511,8 +1580,10 @@ Sets the break function to activate when the break input becomes low.
void timer_set_break_polarity_low(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_BDTR(timer_peripheral) &= ~TIM_BDTR_BKP;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1527,8 +1598,10 @@ Enables the break function of an advanced timer.
void timer_enable_break(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_BDTR(timer_peripheral) |= TIM_BDTR_BKE;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1543,8 +1616,10 @@ Disables the break function of an advanced timer.
void timer_disable_break(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_BDTR(timer_peripheral) &= ~TIM_BDTR_BKE;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1563,8 +1638,10 @@ inactive level as defined by the output polarity.
void timer_set_enabled_off_state_in_run_mode(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_BDTR(timer_peripheral) |= TIM_BDTR_OSSR;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1582,8 +1659,10 @@ disabled, the output is also disabled.
void timer_set_disabled_off_state_in_run_mode(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_BDTR(timer_peripheral) &= ~TIM_BDTR_OSSR;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1600,8 +1679,10 @@ inactive level as defined by the output polarity.
void timer_set_enabled_off_state_in_idle_mode(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_BDTR(timer_peripheral) |= TIM_BDTR_OSSI;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1617,8 +1698,10 @@ timer. When the master output is disabled the output is also disabled.
void timer_set_disabled_off_state_in_idle_mode(u32 timer_peripheral)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_BDTR(timer_peripheral) &= ~TIM_BDTR_OSSI;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1636,8 +1719,10 @@ timer reset has occurred.
void timer_set_break_lock(u32 timer_peripheral, u32 lock)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_BDTR(timer_peripheral) |= lock;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1660,8 +1745,10 @@ number of DTSC cycles:
void timer_set_deadtime(u32 timer_peripheral, u32 deadtime)
{
+#if (defined(ADVANCED_TIMERS) && (ADVANCED_TIMERS))
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
TIM_BDTR(timer_peripheral) |= deadtime;
+#endif
}
/*---------------------------------------------------------------------------*/
@@ -1697,6 +1784,29 @@ u32 timer_get_counter(u32 timer_peripheral)
}
/*---------------------------------------------------------------------------*/
+/** @brief Set Timer Option
+
+Set timer options register on TIM2 or TIM5, used for oscillator calibration
+on TIM5 and trigger remapping on TIM2. Only available on F4 and F2.
+
+@param[in] timer_peripheral Unsigned int32. Timer register address base
+@returns Unsigned int32. Option flags.
+*/
+
+#if (defined(STM32F4) || defined(STM32F2))
+void timer_set_option(u32 timer_peripheral, u32 option)
+{
+ if (timer_peripheral == TIM2) {
+ TIM_OR(timer_peripheral) &= ~TIM2_OR_ITR1_RMP_MASK;
+ TIM_OR(timer_peripheral) |= option;
+ } else if (timer_peripheral == TIM5) {
+ TIM_OR(timer_peripheral) &= ~TIM5_OR_TI4_RMP_MASK;
+ TIM_OR(timer_peripheral) |= option;
+ }
+}
+#endif
+
+/*---------------------------------------------------------------------------*/
/** @brief Set Counter
Set the value of a timer's counter register contents.
@@ -1803,11 +1913,11 @@ void timer_ic_set_input(u32 timer_peripheral, enum tim_ic_id ic, enum tim_ic_inp
in &= 3;
if (((ic == TIM_IC2) || (ic == TIM_IC4)) &&
- ((in == TIM_IC_IN_TI1) || (in = TIM_IC_IN_TI2))) {
+ ((in == TIM_IC_IN_TI1) || (in == TIM_IC_IN_TI2))) {
/* Input select bits are flipped for these combinations */
in ^= 3;
}
-
+
switch (ic) {
case TIM_IC1:
TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_CC1S_MASK;
diff --git a/lib/usb/usb.c b/lib/usb/usb.c
index 1ebb6ec..0799202 100644
--- a/lib/usb/usb.c
+++ b/lib/usb/usb.c
@@ -21,8 +21,6 @@
#include <libopencm3/usb/usbd.h>
#include "usb_private.h"
-struct _usbd_device _usbd_device;
-
u8 usbd_control_buffer[128] __attribute__((weak));
/**
@@ -43,104 +41,112 @@ u8 usbd_control_buffer[128] __attribute__((weak));
* @param strings TODO
* @return Zero on success (currently cannot fail).
*/
-int usbd_init(const usbd_driver *driver,
- const struct usb_device_descriptor *dev,
- const struct usb_config_descriptor *conf, const char **strings)
+usbd_device *usbd_init(const usbd_driver *driver,
+ const struct usb_device_descriptor *dev,
+ const struct usb_config_descriptor *conf,
+ const char **strings, int num_strings)
{
- _usbd_device.driver = driver;
- _usbd_device.desc = dev;
- _usbd_device.config = conf;
- _usbd_device.strings = strings;
- _usbd_device.ctrl_buf = usbd_control_buffer;
- _usbd_device.ctrl_buf_len = sizeof(usbd_control_buffer);
+ usbd_device *usbd_dev;
+
+ usbd_dev = driver->init();
- _usbd_hw_init();
+ usbd_dev->driver = driver;
+ usbd_dev->desc = dev;
+ usbd_dev->config = conf;
+ usbd_dev->strings = strings;
+ usbd_dev->num_strings = num_strings;
+ usbd_dev->ctrl_buf = usbd_control_buffer;
+ usbd_dev->ctrl_buf_len = sizeof(usbd_control_buffer);
- _usbd_device.user_callback_ctr[0][USB_TRANSACTION_SETUP] =
+ usbd_dev->user_callback_ctr[0][USB_TRANSACTION_SETUP] =
_usbd_control_setup;
- _usbd_device.user_callback_ctr[0][USB_TRANSACTION_OUT] =
+ usbd_dev->user_callback_ctr[0][USB_TRANSACTION_OUT] =
_usbd_control_out;
- _usbd_device.user_callback_ctr[0][USB_TRANSACTION_IN] =
+ usbd_dev->user_callback_ctr[0][USB_TRANSACTION_IN] =
_usbd_control_in;
- return 0;
+ return usbd_dev;
}
-void usbd_register_reset_callback(void (*callback)(void))
+void usbd_register_reset_callback(usbd_device *usbd_dev, void (*callback)(void))
{
- _usbd_device.user_callback_reset = callback;
+ usbd_dev->user_callback_reset = callback;
}
-void usbd_register_suspend_callback(void (*callback)(void))
+void usbd_register_suspend_callback(usbd_device *usbd_dev,
+ void (*callback)(void))
{
- _usbd_device.user_callback_suspend = callback;
+ usbd_dev->user_callback_suspend = callback;
}
-void usbd_register_resume_callback(void (*callback)(void))
+void usbd_register_resume_callback(usbd_device *usbd_dev,
+ void (*callback)(void))
{
- _usbd_device.user_callback_resume = callback;
+ usbd_dev->user_callback_resume = callback;
}
-void usbd_register_sof_callback(void (*callback)(void))
+void usbd_register_sof_callback(usbd_device *usbd_dev, void (*callback)(void))
{
- _usbd_device.user_callback_sof = callback;
+ usbd_dev->user_callback_sof = callback;
}
-void usbd_set_control_buffer_size(u16 size)
+void usbd_set_control_buffer_size(usbd_device *usbd_dev, u16 size)
{
- _usbd_device.ctrl_buf_len = size;
+ usbd_dev->ctrl_buf_len = size;
}
-void _usbd_reset(void)
+void _usbd_reset(usbd_device *usbd_dev)
{
- _usbd_device.current_address = 0;
- _usbd_device.current_config = 0;
- usbd_ep_setup(0, USB_ENDPOINT_ATTR_CONTROL, 64, NULL);
- _usbd_hw_set_address(0);
+ usbd_dev->current_address = 0;
+ usbd_dev->current_config = 0;
+ usbd_ep_setup(usbd_dev, 0, USB_ENDPOINT_ATTR_CONTROL, 64, NULL);
+ usbd_dev->driver->set_address(usbd_dev, 0);
- if (_usbd_device.user_callback_reset)
- _usbd_device.user_callback_reset();
+ if (usbd_dev->user_callback_reset)
+ usbd_dev->user_callback_reset();
}
/* Functions to wrap the low-level driver */
-void usbd_poll(void)
+void usbd_poll(usbd_device *usbd_dev)
{
- _usbd_device.driver->poll();
+ usbd_dev->driver->poll(usbd_dev);
}
-void usbd_disconnect(bool disconnected)
+void usbd_disconnect(usbd_device *usbd_dev, bool disconnected)
{
/* not all drivers support disconnection */
- if (_usbd_device.driver->disconnect)
- _usbd_device.driver->disconnect(disconnected);
+ if (usbd_dev->driver->disconnect)
+ usbd_dev->driver->disconnect(usbd_dev, disconnected);
}
-void usbd_ep_setup(u8 addr, u8 type, u16 max_size, void (*callback)(u8 ep))
+void usbd_ep_setup(usbd_device *usbd_dev, u8 addr, u8 type, u16 max_size,
+ void (*callback)(usbd_device *usbd_dev, u8 ep))
{
- _usbd_device.driver->ep_setup(addr, type, max_size, callback);
+ usbd_dev->driver->ep_setup(usbd_dev, addr, type, max_size, callback);
}
-u16 usbd_ep_write_packet(u8 addr, const void *buf, u16 len)
+u16 usbd_ep_write_packet(usbd_device *usbd_dev, u8 addr,
+ const void *buf, u16 len)
{
- return _usbd_device.driver->ep_write_packet(addr, buf, len);
+ return usbd_dev->driver->ep_write_packet(usbd_dev, addr, buf, len);
}
-u16 usbd_ep_read_packet(u8 addr, void *buf, u16 len)
+u16 usbd_ep_read_packet(usbd_device *usbd_dev, u8 addr, void *buf, u16 len)
{
- return _usbd_device.driver->ep_read_packet(addr, buf, len);
+ return usbd_dev->driver->ep_read_packet(usbd_dev, addr, buf, len);
}
-void usbd_ep_stall_set(u8 addr, u8 stall)
+void usbd_ep_stall_set(usbd_device *usbd_dev, u8 addr, u8 stall)
{
- _usbd_device.driver->ep_stall_set(addr, stall);
+ usbd_dev->driver->ep_stall_set(usbd_dev, addr, stall);
}
-u8 usbd_ep_stall_get(u8 addr)
+u8 usbd_ep_stall_get(usbd_device *usbd_dev, u8 addr)
{
- return _usbd_device.driver->ep_stall_get(addr);
+ return usbd_dev->driver->ep_stall_get(usbd_dev, addr);
}
-void usbd_ep_nak_set(u8 addr, u8 nak)
+void usbd_ep_nak_set(usbd_device *usbd_dev, u8 addr, u8 nak)
{
- _usbd_device.driver->ep_nak_set(addr, nak);
+ usbd_dev->driver->ep_nak_set(usbd_dev, addr, nak);
}
diff --git a/lib/usb/usb_control.c b/lib/usb/usb_control.c
index 3dd0857..82843df 100644
--- a/lib/usb/usb_control.c
+++ b/lib/usb/usb_control.c
@@ -21,77 +21,73 @@
#include <libopencm3/usb/usbd.h>
#include "usb_private.h"
-static struct usb_control_state {
- enum {
- IDLE, STALLED,
- DATA_IN, LAST_DATA_IN, STATUS_IN,
- DATA_OUT, LAST_DATA_OUT, STATUS_OUT,
- } state;
- struct usb_setup_data req;
- u8 *ctrl_buf;
- u16 ctrl_len;
- void (*complete)(struct usb_setup_data *req);
-} control_state;
-
/* Register application callback function for handling USB control requests. */
-int usbd_register_control_callback(u8 type, u8 type_mask,
+int usbd_register_control_callback(usbd_device *usbd_dev, u8 type, u8 type_mask,
usbd_control_callback callback)
{
int i;
for (i = 0; i < MAX_USER_CONTROL_CALLBACK; i++) {
- if (_usbd_device.user_control_callback[i].cb)
+ if (usbd_dev->user_control_callback[i].cb)
continue;
- _usbd_device.user_control_callback[i].type = type;
- _usbd_device.user_control_callback[i].type_mask = type_mask;
- _usbd_device.user_control_callback[i].cb = callback;
+ usbd_dev->user_control_callback[i].type = type;
+ usbd_dev->user_control_callback[i].type_mask = type_mask;
+ usbd_dev->user_control_callback[i].cb = callback;
return 0;
}
return -1;
}
-static void usb_control_send_chunk(void)
+static void usb_control_send_chunk(usbd_device *usbd_dev)
{
- if (_usbd_device.desc->bMaxPacketSize0 < control_state.ctrl_len) {
+ if (usbd_dev->desc->bMaxPacketSize0 < usbd_dev->control_state.ctrl_len) {
/* Data stage, normal transmission */
- usbd_ep_write_packet(0, control_state.ctrl_buf,
- _usbd_device.desc->bMaxPacketSize0);
- control_state.state = DATA_IN;
- control_state.ctrl_buf += _usbd_device.desc->bMaxPacketSize0;
- control_state.ctrl_len -= _usbd_device.desc->bMaxPacketSize0;
+ usbd_ep_write_packet(usbd_dev, 0,
+ usbd_dev->control_state.ctrl_buf,
+ usbd_dev->desc->bMaxPacketSize0);
+ usbd_dev->control_state.state = DATA_IN;
+ usbd_dev->control_state.ctrl_buf +=
+ usbd_dev->desc->bMaxPacketSize0;
+ usbd_dev->control_state.ctrl_len -=
+ usbd_dev->desc->bMaxPacketSize0;
} else {
/* Data stage, end of transmission */
- usbd_ep_write_packet(0, control_state.ctrl_buf,
- control_state.ctrl_len);
- control_state.state = LAST_DATA_IN;
- control_state.ctrl_len = 0;
- control_state.ctrl_buf = NULL;
+ usbd_ep_write_packet(usbd_dev, 0,
+ usbd_dev->control_state.ctrl_buf,
+ usbd_dev->control_state.ctrl_len);
+ usbd_dev->control_state.state = LAST_DATA_IN;
+ usbd_dev->control_state.ctrl_len = 0;
+ usbd_dev->control_state.ctrl_buf = NULL;
}
}
-static int usb_control_recv_chunk(void)
+static int usb_control_recv_chunk(usbd_device *usbd_dev)
{
- u16 packetsize = MIN(_usbd_device.desc->bMaxPacketSize0,
- control_state.req.wLength - control_state.ctrl_len);
- u16 size = usbd_ep_read_packet(0, control_state.ctrl_buf +
- control_state.ctrl_len, packetsize);
+ u16 packetsize = MIN(usbd_dev->desc->bMaxPacketSize0,
+ usbd_dev->control_state.req.wLength -
+ usbd_dev->control_state.ctrl_len);
+ u16 size = usbd_ep_read_packet(usbd_dev, 0,
+ usbd_dev->control_state.ctrl_buf +
+ usbd_dev->control_state.ctrl_len,
+ packetsize);
if (size != packetsize) {
- usbd_ep_stall_set(0, 1);
+ usbd_ep_stall_set(usbd_dev, 0, 1);
return -1;
}
- control_state.ctrl_len += size;
+ usbd_dev->control_state.ctrl_len += size;
return packetsize;
}
-static int usb_control_request_dispatch(struct usb_setup_data *req)
+static int usb_control_request_dispatch(usbd_device *usbd_dev,
+ struct usb_setup_data *req)
{
int i, result = 0;
- struct user_control_callback *cb = _usbd_device.user_control_callback;
+ struct user_control_callback *cb = usbd_dev->user_control_callback;
/* Call user command hook function. */
for (i = 0; i < MAX_USER_CONTROL_CALLBACK; i++) {
@@ -99,140 +95,149 @@ static int usb_control_request_dispatch(struct usb_setup_data *req)
break;
if ((req->bmRequestType & cb[i].type_mask) == cb[i].type) {
- result = cb[i].cb(req, &control_state.ctrl_buf,
- &control_state.ctrl_len,
- &control_state.complete);
- if (result)
+ result = cb[i].cb(usbd_dev, req,
+ &(usbd_dev->control_state.ctrl_buf),
+ &(usbd_dev->control_state.ctrl_len),
+ &(usbd_dev->control_state.complete));
+ if (result == USBD_REQ_HANDLED ||
+ result == USBD_REQ_NOTSUPP)
return result;
}
}
-
+
/* Try standard request if not already handled. */
- return _usbd_standard_request(req, &control_state.ctrl_buf,
- &control_state.ctrl_len);
+ return _usbd_standard_request(usbd_dev, req,
+ &(usbd_dev->control_state.ctrl_buf),
+ &(usbd_dev->control_state.ctrl_len));
}
/* Handle commands and read requests. */
-static void usb_control_setup_read(struct usb_setup_data *req)
+static void usb_control_setup_read(usbd_device *usbd_dev,
+ struct usb_setup_data *req)
{
- control_state.ctrl_buf = _usbd_device.ctrl_buf;
- control_state.ctrl_len = req->wLength;
+ usbd_dev->control_state.ctrl_buf = usbd_dev->ctrl_buf;
+ usbd_dev->control_state.ctrl_len = req->wLength;
- if (usb_control_request_dispatch(req)) {
- if (control_state.ctrl_len) {
+ if (usb_control_request_dispatch(usbd_dev, req)) {
+ if (usbd_dev->control_state.ctrl_len) {
/* Go to data out stage if handled. */
- usb_control_send_chunk();
+ usb_control_send_chunk(usbd_dev);
} else {
/* Go to status stage if handled. */
- usbd_ep_write_packet(0, NULL, 0);
- control_state.state = STATUS_IN;
+ usbd_ep_write_packet(usbd_dev, 0, NULL, 0);
+ usbd_dev->control_state.state = STATUS_IN;
}
} else {
/* Stall endpoint on failure. */
- usbd_ep_stall_set(0, 1);
+ usbd_ep_stall_set(usbd_dev, 0, 1);
}
}
-static void usb_control_setup_write(struct usb_setup_data *req)
+static void usb_control_setup_write(usbd_device *usbd_dev,
+ struct usb_setup_data *req)
{
- if (req->wLength > _usbd_device.ctrl_buf_len) {
- usbd_ep_stall_set(0, 1);
+ if (req->wLength > usbd_dev->ctrl_buf_len) {
+ usbd_ep_stall_set(usbd_dev, 0, 1);
return;
}
/* Buffer into which to write received data. */
- control_state.ctrl_buf = _usbd_device.ctrl_buf;
- control_state.ctrl_len = 0;
+ usbd_dev->control_state.ctrl_buf = usbd_dev->ctrl_buf;
+ usbd_dev->control_state.ctrl_len = 0;
/* Wait for DATA OUT stage. */
- if (req->wLength > _usbd_device.desc->bMaxPacketSize0)
- control_state.state = DATA_OUT;
+ if (req->wLength > usbd_dev->desc->bMaxPacketSize0)
+ usbd_dev->control_state.state = DATA_OUT;
else
- control_state.state = LAST_DATA_OUT;
+ usbd_dev->control_state.state = LAST_DATA_OUT;
}
-void _usbd_control_setup(u8 ea)
+void _usbd_control_setup(usbd_device *usbd_dev, u8 ea)
{
- struct usb_setup_data *req = &control_state.req;
+ struct usb_setup_data *req = &usbd_dev->control_state.req;
(void)ea;
- control_state.complete = NULL;
+ usbd_dev->control_state.complete = NULL;
- if (usbd_ep_read_packet(0, req, 8) != 8) {
- usbd_ep_stall_set(0, 1);
+ if (usbd_ep_read_packet(usbd_dev, 0, req, 8) != 8) {
+ usbd_ep_stall_set(usbd_dev, 0, 1);
return;
}
if (req->wLength == 0) {
- usb_control_setup_read(req);
+ usb_control_setup_read(usbd_dev, req);
} else if (req->bmRequestType & 0x80) {
- usb_control_setup_read(req);
+ usb_control_setup_read(usbd_dev, req);
} else {
- usb_control_setup_write(req);
+ usb_control_setup_write(usbd_dev, req);
}
}
-void _usbd_control_out(u8 ea)
+void _usbd_control_out(usbd_device *usbd_dev, u8 ea)
{
(void)ea;
- switch (control_state.state) {
+ switch (usbd_dev->control_state.state) {
case DATA_OUT:
- if (usb_control_recv_chunk() < 0)
+ if (usb_control_recv_chunk(usbd_dev) < 0)
break;
- if ((control_state.req.wLength - control_state.ctrl_len) <=
- _usbd_device.desc->bMaxPacketSize0)
- control_state.state = LAST_DATA_OUT;
+ if ((usbd_dev->control_state.req.wLength -
+ usbd_dev->control_state.ctrl_len) <=
+ usbd_dev->desc->bMaxPacketSize0)
+ usbd_dev->control_state.state = LAST_DATA_OUT;
break;
case LAST_DATA_OUT:
- if (usb_control_recv_chunk() < 0)
+ if (usb_control_recv_chunk(usbd_dev) < 0)
break;
/*
* We have now received the full data payload.
* Invoke callback to process.
*/
- if (usb_control_request_dispatch(&control_state.req)) {
+ if (usb_control_request_dispatch(usbd_dev,
+ &(usbd_dev->control_state.req))) {
/* Got to status stage on success. */
- usbd_ep_write_packet(0, NULL, 0);
- control_state.state = STATUS_IN;
+ usbd_ep_write_packet(usbd_dev, 0, NULL, 0);
+ usbd_dev->control_state.state = STATUS_IN;
} else {
- usbd_ep_stall_set(0, 1);
+ usbd_ep_stall_set(usbd_dev, 0, 1);
}
break;
case STATUS_OUT:
- usbd_ep_read_packet(0, NULL, 0);
- control_state.state = IDLE;
- if (control_state.complete)
- control_state.complete(&control_state.req);
- control_state.complete = NULL;
+ usbd_ep_read_packet(usbd_dev, 0, NULL, 0);
+ usbd_dev->control_state.state = IDLE;
+ if (usbd_dev->control_state.complete)
+ usbd_dev->control_state.complete(usbd_dev,
+ &(usbd_dev->control_state.req));
+ usbd_dev->control_state.complete = NULL;
break;
default:
- usbd_ep_stall_set(0, 1);
+ usbd_ep_stall_set(usbd_dev, 0, 1);
}
}
-void _usbd_control_in(u8 ea)
+void _usbd_control_in(usbd_device *usbd_dev, u8 ea)
{
(void)ea;
- struct usb_setup_data *req = &control_state.req;
+ struct usb_setup_data *req = &(usbd_dev->control_state.req);
- switch (control_state.state) {
+ switch (usbd_dev->control_state.state) {
case DATA_IN:
- usb_control_send_chunk();
+ usb_control_send_chunk(usbd_dev);
break;
case LAST_DATA_IN:
- control_state.state = STATUS_OUT;
+ usbd_dev->control_state.state = STATUS_OUT;
break;
case STATUS_IN:
- if (control_state.complete)
- control_state.complete(&control_state.req);
+ if (usbd_dev->control_state.complete)
+ usbd_dev->control_state.complete(usbd_dev,
+ &(usbd_dev->control_state.req));
/* Exception: Handle SET ADDRESS function here... */
if ((req->bmRequestType == 0) &&
(req->bRequest == USB_REQ_SET_ADDRESS))
- _usbd_hw_set_address(req->wValue);
- control_state.state = IDLE;
+ usbd_dev->driver->set_address(usbd_dev, req->wValue);
+ usbd_dev->control_state.state = IDLE;
break;
default:
- usbd_ep_stall_set(0, 1);
+ usbd_ep_stall_set(usbd_dev, 0, 1);
}
}
diff --git a/lib/usb/usb_f103.c b/lib/usb/usb_f103.c
index 22db8cc..aa323d9 100644
--- a/lib/usb/usb_f103.c
+++ b/lib/usb/usb_f103.c
@@ -24,19 +24,23 @@
#include <libopencm3/usb/usbd.h>
#include "usb_private.h"
-static void stm32f103_usbd_init(void);
-static void stm32f103_set_address(u8 addr);
-static void stm32f103_ep_setup(u8 addr, u8 type, u16 max_size,
- void (*callback) (u8 ep));
-static void stm32f103_endpoints_reset(void);
-static void stm32f103_ep_stall_set(u8 addr, u8 stall);
-static u8 stm32f103_ep_stall_get(u8 addr);
-static void stm32f103_ep_nak_set(u8 addr, u8 nak);
-static u16 stm32f103_ep_write_packet(u8 addr, const void *buf, u16 len);
-static u16 stm32f103_ep_read_packet(u8 addr, void *buf, u16 len);
-static void stm32f103_poll(void);
+static usbd_device *stm32f103_usbd_init(void);
+static void stm32f103_set_address(usbd_device *usbd_dev, u8 addr);
+static void stm32f103_ep_setup(usbd_device *usbd_dev, u8 addr, u8 type,
+ u16 max_size,
+ void (*callback) (usbd_device *usbd_dev, u8 ep));
+static void stm32f103_endpoints_reset(usbd_device *usbd_dev);
+static void stm32f103_ep_stall_set(usbd_device *usbd_dev, u8 addr, u8 stall);
+static u8 stm32f103_ep_stall_get(usbd_device *usbd_dev, u8 addr);
+static void stm32f103_ep_nak_set(usbd_device *usbd_dev, u8 addr, u8 nak);
+static u16 stm32f103_ep_write_packet(usbd_device *usbd_dev, u8 addr,
+ const void *buf, u16 len);
+static u16 stm32f103_ep_read_packet(usbd_device *usbd_dev, u8 addr, void *buf,
+ u16 len);
+static void stm32f103_poll(usbd_device *usbd_dev);
static u8 force_nak[8];
+static struct _usbd_device usbd_dev;
const struct _usbd_driver stm32f103_usb_driver = {
.init = stm32f103_usbd_init,
@@ -52,7 +56,7 @@ const struct _usbd_driver stm32f103_usb_driver = {
};
/** Initialize the USB device controller hardware of the STM32. */
-static void stm32f103_usbd_init(void)
+static usbd_device *stm32f103_usbd_init(void)
{
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN);
SET_REG(USB_CNTR_REG, 0);
@@ -62,10 +66,12 @@ static void stm32f103_usbd_init(void)
/* Enable RESET, SUSPEND, RESUME and CTR interrupts. */
SET_REG(USB_CNTR_REG, USB_CNTR_RESETM | USB_CNTR_CTRM |
USB_CNTR_SUSPM | USB_CNTR_WKUPM);
+ return &usbd_dev;
}
-static void stm32f103_set_address(u8 addr)
+static void stm32f103_set_address(usbd_device *usbd_dev, u8 addr)
{
+ (void)usbd_dev;
/* Set device address and enable. */
SET_REG(USB_DADDR_REG, (addr & USB_DADDR_ADDR) | USB_DADDR_ENABLE);
}
@@ -76,8 +82,9 @@ static void stm32f103_set_address(u8 addr)
* @param ep Index of endpoint to configure.
* @param size Size in bytes of the RX buffer.
*/
-static void usb_set_ep_rx_bufsize(u8 ep, u32 size)
+static void usb_set_ep_rx_bufsize(usbd_device *usbd_dev, u8 ep, u32 size)
{
+ (void)usbd_dev;
if (size > 62) {
if (size & 0x1f)
size -= 32;
@@ -89,8 +96,9 @@ static void usb_set_ep_rx_bufsize(u8 ep, u32 size)
}
}
-static void stm32f103_ep_setup(u8 addr, u8 type, u16 max_size,
- void (*callback) (u8 ep))
+static void stm32f103_ep_setup(usbd_device *usbd_dev, u8 addr, u8 type,
+ u16 max_size,
+ void (*callback) (usbd_device *usbd_dev, u8 ep))
{
/* Translate USB standard type codes to STM32. */
const u16 typelookup[] = {
@@ -107,32 +115,30 @@ static void stm32f103_ep_setup(u8 addr, u8 type, u16 max_size,
USB_SET_EP_TYPE(addr, typelookup[type]);
if (dir || (addr == 0)) {
- USB_SET_EP_TX_ADDR(addr, _usbd_device.pm_top);
+ USB_SET_EP_TX_ADDR(addr, usbd_dev->pm_top);
if (callback) {
- _usbd_device.
- user_callback_ctr[addr][USB_TRANSACTION_IN] =
+ usbd_dev->user_callback_ctr[addr][USB_TRANSACTION_IN] =
(void *)callback;
}
USB_CLR_EP_TX_DTOG(addr);
USB_SET_EP_TX_STAT(addr, USB_EP_TX_STAT_NAK);
- _usbd_device.pm_top += max_size;
+ usbd_dev->pm_top += max_size;
}
if (!dir) {
- USB_SET_EP_RX_ADDR(addr, _usbd_device.pm_top);
- usb_set_ep_rx_bufsize(addr, max_size);
+ USB_SET_EP_RX_ADDR(addr, usbd_dev->pm_top);
+ usb_set_ep_rx_bufsize(usbd_dev, addr, max_size);
if (callback) {
- _usbd_device.
- user_callback_ctr[addr][USB_TRANSACTION_OUT] =
+ usbd_dev->user_callback_ctr[addr][USB_TRANSACTION_OUT] =
(void *)callback;
}
USB_CLR_EP_RX_DTOG(addr);
USB_SET_EP_RX_STAT(addr, USB_EP_RX_STAT_VALID);
- _usbd_device.pm_top += max_size;
+ usbd_dev->pm_top += max_size;
}
}
-static void stm32f103_endpoints_reset(void)
+static void stm32f103_endpoints_reset(usbd_device *usbd_dev)
{
int i;
@@ -141,11 +147,12 @@ static void stm32f103_endpoints_reset(void)
USB_SET_EP_TX_STAT(i, USB_EP_TX_STAT_DISABLED);
USB_SET_EP_RX_STAT(i, USB_EP_RX_STAT_DISABLED);
}
- _usbd_device.pm_top = 0x40 + (2 * _usbd_device.desc->bMaxPacketSize0);
+ usbd_dev->pm_top = 0x40 + (2 * usbd_dev->desc->bMaxPacketSize0);
}
-static void stm32f103_ep_stall_set(u8 addr, u8 stall)
+static void stm32f103_ep_stall_set(usbd_device *usbd_dev, u8 addr, u8 stall)
{
+ (void)usbd_dev;
if (addr == 0)
USB_SET_EP_TX_STAT(addr, stall ? USB_EP_TX_STAT_STALL :
USB_EP_TX_STAT_NAK);
@@ -169,8 +176,9 @@ static void stm32f103_ep_stall_set(u8 addr, u8 stall)
}
}
-static u8 stm32f103_ep_stall_get(u8 addr)
+static u8 stm32f103_ep_stall_get(usbd_device *usbd_dev, u8 addr)
{
+ (void)usbd_dev;
if (addr & 0x80) {
if ((*USB_EP_REG(addr & 0x7F) & USB_EP_TX_STAT) ==
USB_EP_TX_STAT_STALL)
@@ -183,8 +191,9 @@ static u8 stm32f103_ep_stall_get(u8 addr)
return 0;
}
-static void stm32f103_ep_nak_set(u8 addr, u8 nak)
+static void stm32f103_ep_nak_set(usbd_device *usbd_dev, u8 addr, u8 nak)
{
+ (void)usbd_dev;
/* It does not make sence to force NAK on IN endpoints. */
if (addr & 0x80)
return;
@@ -213,8 +222,10 @@ static void usb_copy_to_pm(volatile void *vPM, const void *buf, u16 len)
*PM = *lbuf;
}
-static u16 stm32f103_ep_write_packet(u8 addr, const void *buf, u16 len)
+static u16 stm32f103_ep_write_packet(usbd_device *usbd_dev, u8 addr,
+ const void *buf, u16 len)
{
+ (void)usbd_dev;
addr &= 0x7F;
if ((*USB_EP_REG(addr) & USB_EP_TX_STAT) == USB_EP_TX_STAT_VALID)
@@ -247,8 +258,10 @@ static void usb_copy_from_pm(void *buf, const volatile void *vPM, u16 len)
*(u8 *) lbuf = *(u8 *) PM;
}
-static u16 stm32f103_ep_read_packet(u8 addr, void *buf, u16 len)
+static u16 stm32f103_ep_read_packet(usbd_device *usbd_dev, u8 addr, void *buf,
+ u16 len)
{
+ (void)usbd_dev;
if ((*USB_EP_REG(addr) & USB_EP_RX_STAT) == USB_EP_RX_STAT_VALID)
return 0;
@@ -262,13 +275,13 @@ static u16 stm32f103_ep_read_packet(u8 addr, void *buf, u16 len)
return len;
}
-static void stm32f103_poll(void)
+static void stm32f103_poll(usbd_device *usbd_dev)
{
u16 istr = *USB_ISTR_REG;
if (istr & USB_ISTR_RESET) {
- _usbd_device.pm_top = 0x40;
- _usbd_reset();
+ usbd_dev->pm_top = 0x40;
+ _usbd_reset(usbd_dev);
USB_CLR_ISTR_RESET();
return;
}
@@ -282,27 +295,27 @@ static void stm32f103_poll(void)
else /* IN transaction */
USB_CLR_EP_TX_CTR(ep);
- if (_usbd_device.user_callback_ctr[ep][type])
- _usbd_device.user_callback_ctr[ep][type] (ep);
+ if (usbd_dev->user_callback_ctr[ep][type])
+ usbd_dev->user_callback_ctr[ep][type] (usbd_dev, ep);
else
USB_CLR_EP_RX_CTR(ep);
}
if (istr & USB_ISTR_SUSP) {
USB_CLR_ISTR_SUSP();
- if (_usbd_device.user_callback_suspend)
- _usbd_device.user_callback_suspend();
+ if (usbd_dev->user_callback_suspend)
+ usbd_dev->user_callback_suspend();
}
if (istr & USB_ISTR_WKUP) {
USB_CLR_ISTR_WKUP();
- if (_usbd_device.user_callback_resume)
- _usbd_device.user_callback_resume();
+ if (usbd_dev->user_callback_resume)
+ usbd_dev->user_callback_resume();
}
if (istr & USB_ISTR_SOF) {
- if (_usbd_device.user_callback_sof)
- _usbd_device.user_callback_sof();
+ if (usbd_dev->user_callback_sof)
+ usbd_dev->user_callback_sof();
USB_CLR_ISTR_SOF();
}
}
diff --git a/lib/usb/usb_f107.c b/lib/usb/usb_f107.c
index a5a4a6c..009979d 100644
--- a/lib/usb/usb_f107.c
+++ b/lib/usb/usb_f107.c
@@ -23,49 +23,34 @@
#include <libopencm3/stm32/otg_fs.h>
#include <libopencm3/usb/usbd.h>
#include "usb_private.h"
+#include "usb_fx07_common.h"
/* Receive FIFO size in 32-bit words. */
#define RX_FIFO_SIZE 128
-static uint16_t fifo_mem_top;
-static uint16_t fifo_mem_top_ep0;
-static u8 force_nak[4];
+static usbd_device *stm32f107_usbd_init(void);
-static void stm32f107_usbd_init(void);
-static void stm32f107_set_address(u8 addr);
-static void stm32f107_ep_setup(u8 addr, u8 type, u16 max_size,
- void (*callback)(u8 ep));
-static void stm32f107_endpoints_reset(void);
-static void stm32f107_ep_stall_set(u8 addr, u8 stall);
-static u8 stm32f107_ep_stall_get(u8 addr);
-static void stm32f107_ep_nak_set(u8 addr, u8 nak);
-static u16 stm32f107_ep_write_packet(u8 addr, const void *buf, u16 len);
-static u16 stm32f107_ep_read_packet(u8 addr, void *buf, u16 len);
-static void stm32f107_poll(void);
-static void stm32f107_disconnect(bool disconnected);
-
-/*
- * We keep a backup copy of the out endpoint size registers to restore them
- * after a transaction.
- */
-static u32 doeptsiz[4];
+static struct _usbd_device usbd_dev;
const struct _usbd_driver stm32f107_usb_driver = {
.init = stm32f107_usbd_init,
- .set_address = stm32f107_set_address,
- .ep_setup = stm32f107_ep_setup,
- .ep_reset = stm32f107_endpoints_reset,
- .ep_stall_set = stm32f107_ep_stall_set,
- .ep_stall_get = stm32f107_ep_stall_get,
- .ep_nak_set = stm32f107_ep_nak_set,
- .ep_write_packet = stm32f107_ep_write_packet,
- .ep_read_packet = stm32f107_ep_read_packet,
- .poll = stm32f107_poll,
- .disconnect = stm32f107_disconnect,
+ .set_address = stm32fx07_set_address,
+ .ep_setup = stm32fx07_ep_setup,
+ .ep_reset = stm32fx07_endpoints_reset,
+ .ep_stall_set = stm32fx07_ep_stall_set,
+ .ep_stall_get = stm32fx07_ep_stall_get,
+ .ep_nak_set = stm32fx07_ep_nak_set,
+ .ep_write_packet = stm32fx07_ep_write_packet,
+ .ep_read_packet = stm32fx07_ep_read_packet,
+ .poll = stm32fx07_poll,
+ .disconnect = stm32fx07_disconnect,
+ .base_address = USB_OTG_FS_BASE,
+ .set_address_before_status = 1,
+ .rx_fifo_size = RX_FIFO_SIZE,
};
/** Initialize the USB device controller hardware of the STM32. */
-static void stm32f107_usbd_init(void)
+static usbd_device *stm32f107_usbd_init(void)
{
OTG_FS_GINTSTS = OTG_FS_GINTSTS_MMIS;
@@ -88,8 +73,8 @@ static void stm32f107_usbd_init(void)
/* Restart the PHY clock. */
OTG_FS_PCGCCTL = 0;
- OTG_FS_GRXFSIZ = RX_FIFO_SIZE;
- fifo_mem_top = RX_FIFO_SIZE;
+ OTG_FS_GRXFSIZ = stm32f107_usb_driver.rx_fifo_size;
+ usbd_dev.fifo_mem_top = stm32f107_usb_driver.rx_fifo_size;
/* Unmask interrupts for TX and RX. */
OTG_FS_GAHBCFG |= OTG_FS_GAHBCFG_GINT;
@@ -101,289 +86,6 @@ static void stm32f107_usbd_init(void)
OTG_FS_GINTMSK_SOFM;
OTG_FS_DAINTMSK = 0xF;
OTG_FS_DIEPMSK = OTG_FS_DIEPMSK_XFRCM;
-}
-
-static void stm32f107_set_address(u8 addr)
-{
- OTG_FS_DCFG = (OTG_FS_DCFG & ~OTG_FS_DCFG_DAD) | (addr << 4);
-}
-
-static void stm32f107_ep_setup(u8 addr, u8 type, u16 max_size,
- void (*callback) (u8 ep))
-{
- /*
- * Configure endpoint address and type. Allocate FIFO memory for
- * endpoint. Install callback funciton.
- */
- u8 dir = addr & 0x80;
- addr &= 0x7f;
-
- if (addr == 0) { /* For the default control endpoint */
- /* Configure IN part. */
- if (max_size >= 64) {
- OTG_FS_DIEPCTL0 = OTG_FS_DIEPCTL0_MPSIZ_64;
- } else if (max_size >= 32) {
- OTG_FS_DIEPCTL0 = OTG_FS_DIEPCTL0_MPSIZ_32;
- } else if (max_size >= 16) {
- OTG_FS_DIEPCTL0 = OTG_FS_DIEPCTL0_MPSIZ_16;
- } else {
- OTG_FS_DIEPCTL0 = OTG_FS_DIEPCTL0_MPSIZ_8;
- }
- OTG_FS_DIEPTSIZ0 = (max_size & OTG_FS_DIEPSIZ0_XFRSIZ_MASK);
- OTG_FS_DIEPCTL0 |= OTG_FS_DIEPCTL0_EPENA | OTG_FS_DIEPCTL0_SNAK;
-
- /* Configure OUT part. */
- doeptsiz[0] = OTG_FS_DIEPSIZ0_STUPCNT_1 | (1 << 19) |
- (max_size & OTG_FS_DIEPSIZ0_XFRSIZ_MASK);
- OTG_FS_DOEPTSIZ(0) = doeptsiz[0];
- OTG_FS_DOEPCTL(0) |=
- OTG_FS_DOEPCTL0_EPENA | OTG_FS_DIEPCTL0_SNAK;
-
- OTG_FS_GNPTXFSIZ = ((max_size / 4) << 16) | RX_FIFO_SIZE;
- fifo_mem_top += max_size / 4;
- fifo_mem_top_ep0 = fifo_mem_top;
-
- return;
- }
-
- if (dir) {
- OTG_FS_DIEPTXF(addr) = ((max_size / 4) << 16) | fifo_mem_top;
- fifo_mem_top += max_size / 4;
-
- OTG_FS_DIEPTSIZ(addr) =
- (max_size & OTG_FS_DIEPSIZ0_XFRSIZ_MASK);
- OTG_FS_DIEPCTL(addr) |=
- OTG_FS_DIEPCTL0_EPENA | OTG_FS_DIEPCTL0_SNAK | (type << 18)
- | OTG_FS_DIEPCTL0_USBAEP | OTG_FS_DIEPCTLX_SD0PID
- | (addr << 22) | max_size;
-
- if (callback) {
- _usbd_device.
- user_callback_ctr[addr][USB_TRANSACTION_IN] =
- (void *)callback;
- }
- }
-
- if (!dir) {
- doeptsiz[addr] = (1 << 19) |
- (max_size & OTG_FS_DIEPSIZ0_XFRSIZ_MASK);
- OTG_FS_DOEPTSIZ(addr) = doeptsiz[addr];
- OTG_FS_DOEPCTL(addr) |= OTG_FS_DOEPCTL0_EPENA |
- OTG_FS_DOEPCTL0_USBAEP | OTG_FS_DIEPCTL0_CNAK |
- OTG_FS_DOEPCTLX_SD0PID | (type << 18) | max_size;
-
- if (callback) {
- _usbd_device.
- user_callback_ctr[addr][USB_TRANSACTION_OUT] =
- (void *)callback;
- }
- }
-}
-
-static void stm32f107_endpoints_reset(void)
-{
- /* The core resets the endpoints automatically on reset. */
- fifo_mem_top = fifo_mem_top_ep0;
-}
-
-static void stm32f107_ep_stall_set(u8 addr, u8 stall)
-{
- if (addr == 0) {
- if (stall)
- OTG_FS_DIEPCTL(addr) |= OTG_FS_DIEPCTL0_STALL;
- else
- OTG_FS_DIEPCTL(addr) &= ~OTG_FS_DIEPCTL0_STALL;
- }
-
- if (addr & 0x80) {
- addr &= 0x7F;
-
- if (stall) {
- OTG_FS_DIEPCTL(addr) |= OTG_FS_DIEPCTL0_STALL;
- } else {
- OTG_FS_DIEPCTL(addr) &= ~OTG_FS_DIEPCTL0_STALL;
- OTG_FS_DIEPCTL(addr) |= OTG_FS_DIEPCTLX_SD0PID;
- }
- } else {
- if (stall) {
- OTG_FS_DOEPCTL(addr) |= OTG_FS_DOEPCTL0_STALL;
- } else {
- OTG_FS_DOEPCTL(addr) &= ~OTG_FS_DOEPCTL0_STALL;
- OTG_FS_DOEPCTL(addr) |= OTG_FS_DOEPCTLX_SD0PID;
- }
- }
-}
-
-static u8 stm32f107_ep_stall_get(u8 addr)
-{
- /* Return non-zero if STALL set. */
- if (addr & 0x80)
- return
- (OTG_FS_DIEPCTL(addr & 0x7f) & OTG_FS_DIEPCTL0_STALL) ? 1 : 0;
- else
- return (OTG_FS_DOEPCTL(addr) & OTG_FS_DOEPCTL0_STALL) ? 1 : 0;
-}
-
-static void stm32f107_ep_nak_set(u8 addr, u8 nak)
-{
- /* It does not make sence to force NAK on IN endpoints. */
- if (addr & 0x80)
- return;
-
- force_nak[addr] = nak;
-
- if (nak)
- OTG_FS_DOEPCTL(addr) |= OTG_FS_DOEPCTL0_SNAK;
- else
- OTG_FS_DOEPCTL(addr) |= OTG_FS_DOEPCTL0_CNAK;
-}
-static u16 stm32f107_ep_write_packet(u8 addr, const void *buf, u16 len)
-{
- const u32 *buf32 = buf;
- int i;
-
- addr &= 0x7F;
-
- /* Return if endpoint is already enabled. */
- if (OTG_FS_DIEPTSIZ(addr) & OTG_FS_DIEPSIZ0_PKTCNT)
- return 0;
-
- /* Enable endpoint for transmission. */
- OTG_FS_DIEPTSIZ(addr) = (1 << 19) | len;
- OTG_FS_DIEPCTL(addr) |= OTG_FS_DIEPCTL0_EPENA | OTG_FS_DIEPCTL0_CNAK;
-
- /* Copy buffer to endpoint FIFO. */
- volatile u32 *fifo = OTG_FS_FIFO(addr);
- for (i = len; i > 0; i -= 4)
- *fifo++ = *buf32++;
-
- return len;
-}
-
-/*
- * Received packet size for each endpoint. This is assigned in
- * stm32f107_poll() which reads the packet status push register GRXSTSP
- * for use in stm32f107_ep_read_packet().
- */
-static uint16_t rxbcnt;
-
-static u16 stm32f107_ep_read_packet(u8 addr, void *buf, u16 len)
-{
- int i;
- u32 *buf32 = buf;
- u32 extra;
-
- len = MIN(len, rxbcnt);
- rxbcnt -= len;
-
- volatile u32 *fifo = OTG_FS_FIFO(addr);
- for (i = len; i >= 4; i -= 4)
- *buf32++ = *fifo++;
-
- if (i) {
- extra = *fifo++;
- memcpy(buf32, &extra, i);
- }
-
- OTG_FS_DOEPTSIZ(addr) = doeptsiz[addr];
- OTG_FS_DOEPCTL(addr) |= OTG_FS_DOEPCTL0_EPENA |
- (force_nak[addr] ? OTG_FS_DOEPCTL0_SNAK : OTG_FS_DOEPCTL0_CNAK);
-
- return len;
-}
-
-static void stm32f107_poll(void)
-{
- /* Read interrupt status register. */
- u32 intsts = OTG_FS_GINTSTS;
- int i;
-
- if (intsts & OTG_FS_GINTSTS_ENUMDNE) {
- /* Handle USB RESET condition. */
- OTG_FS_GINTSTS = OTG_FS_GINTSTS_ENUMDNE;
- fifo_mem_top = RX_FIFO_SIZE;
- _usbd_reset();
- return;
- }
-
- /* Note: RX and TX handled differently in this device. */
- if (intsts & OTG_FS_GINTSTS_RXFLVL) {
- /* Receive FIFO non-empty. */
- u32 rxstsp = OTG_FS_GRXSTSP;
- u32 pktsts = rxstsp & OTG_FS_GRXSTSP_PKTSTS_MASK;
- if ((pktsts != OTG_FS_GRXSTSP_PKTSTS_OUT) &&
- (pktsts != OTG_FS_GRXSTSP_PKTSTS_SETUP))
- return;
-
- u8 ep = rxstsp & OTG_FS_GRXSTSP_EPNUM_MASK;
- u8 type;
- if (pktsts == OTG_FS_GRXSTSP_PKTSTS_SETUP)
- type = USB_TRANSACTION_SETUP;
- else
- type = USB_TRANSACTION_OUT;
-
- /* Save packet size for stm32f107_ep_read_packet(). */
- rxbcnt = (rxstsp & OTG_FS_GRXSTSP_BCNT_MASK) >> 4;
-
- /*
- * FIXME: Why is a delay needed here?
- * This appears to fix a problem where the first 4 bytes
- * of the DATA OUT stage of a control transaction are lost.
- */
- for (i = 0; i < 1000; i++)
- __asm__("nop");
-
- if (_usbd_device.user_callback_ctr[ep][type])
- _usbd_device.user_callback_ctr[ep][type] (ep);
-
- /* Discard unread packet data. */
- for (i = 0; i < rxbcnt; i += 4)
- (void)*OTG_FS_FIFO(ep);
-
- rxbcnt = 0;
- }
-
- /*
- * There is no global interrupt flag for transmit complete.
- * The XFRC bit must be checked in each OTG_FS_DIEPINT(x).
- */
- for (i = 0; i < 4; i++) { /* Iterate over endpoints. */
- if (OTG_FS_DIEPINT(i) & OTG_FS_DIEPINTX_XFRC) {
- /* Transfer complete. */
- if (_usbd_device.
- user_callback_ctr[i][USB_TRANSACTION_IN]) {
- _usbd_device.
- user_callback_ctr[i][USB_TRANSACTION_IN](i);
- }
- OTG_FS_DIEPINT(i) = OTG_FS_DIEPINTX_XFRC;
- }
- }
-
- if (intsts & OTG_FS_GINTSTS_USBSUSP) {
- if (_usbd_device.user_callback_suspend)
- _usbd_device.user_callback_suspend();
- OTG_FS_GINTSTS = OTG_FS_GINTSTS_USBSUSP;
- }
-
- if (intsts & OTG_FS_GINTSTS_WKUPINT) {
- if (_usbd_device.user_callback_resume)
- _usbd_device.user_callback_resume();
- OTG_FS_GINTSTS = OTG_FS_GINTSTS_WKUPINT;
- }
-
- if (intsts & OTG_FS_GINTSTS_SOF) {
- if (_usbd_device.user_callback_sof)
- _usbd_device.user_callback_sof();
- OTG_FS_GINTSTS = OTG_FS_GINTSTS_SOF;
- }
-}
-
-static void stm32f107_disconnect(bool disconnected)
-{
- if (disconnected) {
- OTG_FS_DCTL |= OTG_FS_DCTL_SDIS;
- } else {
- OTG_FS_DCTL &= ~OTG_FS_DCTL_SDIS;
- }
+ return &usbd_dev;
}
diff --git a/lib/usb/usb_f207.c b/lib/usb/usb_f207.c
new file mode 100644
index 0000000..b2509e5
--- /dev/null
+++ b/lib/usb/usb_f207.c
@@ -0,0 +1,91 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2011 Gareth McMullin <gareth@blacksphere.co.nz>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <libopencm3/cm3/common.h>
+#include <libopencm3/stm32/tools.h>
+#include <libopencm3/stm32/otg_hs.h>
+#include <libopencm3/usb/usbd.h>
+#include "usb_private.h"
+#include "usb_fx07_common.h"
+
+/* Receive FIFO size in 32-bit words. */
+#define RX_FIFO_SIZE 512
+
+static usbd_device *stm32f207_usbd_init(void);
+
+static struct _usbd_device usbd_dev;
+
+const struct _usbd_driver stm32f207_usb_driver = {
+ .init = stm32f207_usbd_init,
+ .set_address = stm32fx07_set_address,
+ .ep_setup = stm32fx07_ep_setup,
+ .ep_reset = stm32fx07_endpoints_reset,
+ .ep_stall_set = stm32fx07_ep_stall_set,
+ .ep_stall_get = stm32fx07_ep_stall_get,
+ .ep_nak_set = stm32fx07_ep_nak_set,
+ .ep_write_packet = stm32fx07_ep_write_packet,
+ .ep_read_packet = stm32fx07_ep_read_packet,
+ .poll = stm32fx07_poll,
+ .disconnect = stm32fx07_disconnect,
+ .base_address = USB_OTG_HS_BASE,
+ .set_address_before_status = 1,
+ .rx_fifo_size = RX_FIFO_SIZE,
+};
+
+/** Initialize the USB device controller hardware of the STM32. */
+static usbd_device *stm32f207_usbd_init(void)
+{
+ OTG_HS_GINTSTS = OTG_HS_GINTSTS_MMIS;
+
+ OTG_HS_GUSBCFG |= OTG_HS_GUSBCFG_PHYSEL;
+ /* Enable VBUS sensing in device mode and power down the PHY. */
+ OTG_HS_GCCFG |= OTG_HS_GCCFG_VBUSBSEN | OTG_HS_GCCFG_PWRDWN;
+
+ /* Wait for AHB idle. */
+ while (!(OTG_HS_GRSTCTL & OTG_HS_GRSTCTL_AHBIDL)) ;
+ /* Do core soft reset. */
+ OTG_HS_GRSTCTL |= OTG_HS_GRSTCTL_CSRST;
+ while (OTG_HS_GRSTCTL & OTG_HS_GRSTCTL_CSRST) ;
+
+ /* Force peripheral only mode. */
+ OTG_HS_GUSBCFG |= OTG_HS_GUSBCFG_FDMOD | OTG_HS_GUSBCFG_TRDT_MASK;
+
+ /* Full speed device. */
+ OTG_HS_DCFG |= OTG_HS_DCFG_DSPD;
+
+ /* Restart the PHY clock. */
+ OTG_HS_PCGCCTL = 0;
+
+ OTG_HS_GRXFSIZ = stm32f207_usb_driver.rx_fifo_size;
+ usbd_dev.fifo_mem_top = stm32f207_usb_driver.rx_fifo_size;
+
+ /* Unmask interrupts for TX and RX. */
+ OTG_HS_GAHBCFG |= OTG_HS_GAHBCFG_GINT;
+ OTG_HS_GINTMSK = OTG_HS_GINTMSK_ENUMDNEM |
+ OTG_HS_GINTMSK_RXFLVLM |
+ OTG_HS_GINTMSK_IEPINT |
+ OTG_HS_GINTMSK_USBSUSPM |
+ OTG_HS_GINTMSK_WUIM |
+ OTG_HS_GINTMSK_SOFM;
+ OTG_HS_DAINTMSK = 0xF;
+ OTG_HS_DIEPMSK = OTG_HS_DIEPMSK_XFRCM;
+
+ return &usbd_dev;
+}
diff --git a/lib/usb/usb_fx07_common.c b/lib/usb/usb_fx07_common.c
new file mode 100644
index 0000000..9178092
--- /dev/null
+++ b/lib/usb/usb_fx07_common.c
@@ -0,0 +1,318 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2011 Gareth McMullin <gareth@blacksphere.co.nz>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <libopencm3/cm3/common.h>
+#include <libopencm3/stm32/tools.h>
+#include <libopencm3/stm32/otg_fs.h>
+#include <libopencm3/stm32/otg_hs.h>
+#include <libopencm3/usb/usbd.h>
+#include "usb_private.h"
+#include "usb_fx07_common.h"
+
+/* The FS core and the HS core have the same register layout.
+ * As the code can be used on both cores, the registers offset is modified
+ * according to the selected cores base address. */
+#define dev_base_address (usbd_dev->driver->base_address)
+#define REBASE(x) MMIO32((x)+(dev_base_address))
+#define REBASE_FIFO(x) ((volatile u32*)((dev_base_address) + (OTG_FIFO(x))))
+
+void stm32fx07_set_address(usbd_device *usbd_dev, u8 addr)
+{
+ REBASE(OTG_DCFG) = (REBASE(OTG_DCFG) & ~OTG_FS_DCFG_DAD) | (addr << 4);
+}
+
+void stm32fx07_ep_setup(usbd_device *usbd_dev, u8 addr, u8 type, u16 max_size,
+ void (*callback) (usbd_device *usbd_dev, u8 ep))
+{
+ /*
+ * Configure endpoint address and type. Allocate FIFO memory for
+ * endpoint. Install callback funciton.
+ */
+ u8 dir = addr & 0x80;
+ addr &= 0x7f;
+
+ if (addr == 0) { /* For the default control endpoint */
+ /* Configure IN part. */
+ if (max_size >= 64) {
+ REBASE(OTG_DIEPCTL0) = OTG_FS_DIEPCTL0_MPSIZ_64;
+ } else if (max_size >= 32) {
+ REBASE(OTG_DIEPCTL0) = OTG_FS_DIEPCTL0_MPSIZ_32;
+ } else if (max_size >= 16) {
+ REBASE(OTG_DIEPCTL0) = OTG_FS_DIEPCTL0_MPSIZ_16;
+ } else {
+ REBASE(OTG_DIEPCTL0) = OTG_FS_DIEPCTL0_MPSIZ_8;
+ }
+ REBASE(OTG_DIEPTSIZ0) =
+ (max_size & OTG_FS_DIEPSIZ0_XFRSIZ_MASK);
+ REBASE(OTG_DIEPCTL0) |=
+ OTG_FS_DIEPCTL0_EPENA | OTG_FS_DIEPCTL0_SNAK;
+
+ /* Configure OUT part. */
+ usbd_dev->doeptsiz[0] = OTG_FS_DIEPSIZ0_STUPCNT_1 |
+ OTG_FS_DIEPSIZ0_PKTCNT |
+ (max_size & OTG_FS_DIEPSIZ0_XFRSIZ_MASK);
+ REBASE(OTG_DOEPTSIZ(0)) = usbd_dev->doeptsiz[0];
+ REBASE(OTG_DOEPCTL(0)) |=
+ OTG_FS_DOEPCTL0_EPENA | OTG_FS_DIEPCTL0_SNAK;
+
+ REBASE(OTG_GNPTXFSIZ) = ((max_size / 4) << 16) |
+ usbd_dev->driver->rx_fifo_size;
+ usbd_dev->fifo_mem_top += max_size / 4;
+ usbd_dev->fifo_mem_top_ep0 = usbd_dev->fifo_mem_top;
+
+ return;
+ }
+
+ if (dir) {
+ REBASE(OTG_DIEPTXF(addr)) = ((max_size / 4) << 16) |
+ usbd_dev->fifo_mem_top;
+ usbd_dev->fifo_mem_top += max_size / 4;
+
+ REBASE(OTG_DIEPTSIZ(addr)) =
+ (max_size & OTG_FS_DIEPSIZ0_XFRSIZ_MASK);
+ REBASE(OTG_DIEPCTL(addr)) |=
+ OTG_FS_DIEPCTL0_EPENA | OTG_FS_DIEPCTL0_SNAK | (type << 18)
+ | OTG_FS_DIEPCTL0_USBAEP | OTG_FS_DIEPCTLX_SD0PID
+ | (addr << 22) | max_size;
+
+ if (callback) {
+ usbd_dev->user_callback_ctr[addr][USB_TRANSACTION_IN] =
+ (void *)callback;
+ }
+ }
+
+ if (!dir) {
+ usbd_dev->doeptsiz[addr] = OTG_FS_DIEPSIZ0_PKTCNT |
+ (max_size & OTG_FS_DIEPSIZ0_XFRSIZ_MASK);
+ REBASE(OTG_DOEPTSIZ(addr)) = usbd_dev->doeptsiz[addr];
+ REBASE(OTG_DOEPCTL(addr)) |= OTG_FS_DOEPCTL0_EPENA |
+ OTG_FS_DOEPCTL0_USBAEP | OTG_FS_DIEPCTL0_CNAK |
+ OTG_FS_DOEPCTLX_SD0PID | (type << 18) | max_size;
+
+ if (callback) {
+ usbd_dev->user_callback_ctr[addr][USB_TRANSACTION_OUT] =
+ (void *)callback;
+ }
+ }
+}
+
+void stm32fx07_endpoints_reset(usbd_device *usbd_dev)
+{
+ /* The core resets the endpoints automatically on reset. */
+ usbd_dev->fifo_mem_top = usbd_dev->fifo_mem_top_ep0;
+}
+
+void stm32fx07_ep_stall_set(usbd_device *usbd_dev, u8 addr, u8 stall)
+{
+ if (addr == 0) {
+ if (stall)
+ REBASE(OTG_DIEPCTL(addr)) |= OTG_FS_DIEPCTL0_STALL;
+ else
+ REBASE(OTG_DIEPCTL(addr)) &= ~OTG_FS_DIEPCTL0_STALL;
+ }
+
+ if (addr & 0x80) {
+ addr &= 0x7F;
+
+ if (stall) {
+ REBASE(OTG_DIEPCTL(addr)) |= OTG_FS_DIEPCTL0_STALL;
+ } else {
+ REBASE(OTG_DIEPCTL(addr)) &= ~OTG_FS_DIEPCTL0_STALL;
+ REBASE(OTG_DIEPCTL(addr)) |= OTG_FS_DIEPCTLX_SD0PID;
+ }
+ } else {
+ if (stall) {
+ REBASE(OTG_DOEPCTL(addr)) |= OTG_FS_DOEPCTL0_STALL;
+ } else {
+ REBASE(OTG_DOEPCTL(addr)) &= ~OTG_FS_DOEPCTL0_STALL;
+ REBASE(OTG_DOEPCTL(addr)) |= OTG_FS_DOEPCTLX_SD0PID;
+ }
+ }
+}
+
+u8 stm32fx07_ep_stall_get(usbd_device *usbd_dev, u8 addr)
+{
+ /* Return non-zero if STALL set. */
+ if (addr & 0x80)
+ return (REBASE(OTG_DIEPCTL(addr & 0x7f)) &
+ OTG_FS_DIEPCTL0_STALL) ? 1 : 0;
+ else
+ return (REBASE(OTG_DOEPCTL(addr)) &
+ OTG_FS_DOEPCTL0_STALL) ? 1 : 0;
+}
+
+void stm32fx07_ep_nak_set(usbd_device *usbd_dev, u8 addr, u8 nak)
+{
+ /* It does not make sence to force NAK on IN endpoints. */
+ if (addr & 0x80)
+ return;
+
+ usbd_dev->force_nak[addr] = nak;
+
+ if (nak)
+ REBASE(OTG_DOEPCTL(addr)) |= OTG_FS_DOEPCTL0_SNAK;
+ else
+ REBASE(OTG_DOEPCTL(addr)) |= OTG_FS_DOEPCTL0_CNAK;
+}
+
+u16 stm32fx07_ep_write_packet(usbd_device *usbd_dev, u8 addr,
+ const void *buf, u16 len)
+{
+ const u32 *buf32 = buf;
+ int i;
+
+ addr &= 0x7F;
+
+ /* Return if endpoint is already enabled. */
+ if (REBASE(OTG_DIEPTSIZ(addr)) & OTG_FS_DIEPSIZ0_PKTCNT)
+ return 0;
+
+ /* Enable endpoint for transmission. */
+ REBASE(OTG_DIEPTSIZ(addr)) = OTG_FS_DIEPSIZ0_PKTCNT | len;
+ REBASE(OTG_DIEPCTL(addr)) |= OTG_FS_DIEPCTL0_EPENA |
+ OTG_FS_DIEPCTL0_CNAK;
+ volatile u32 *fifo = REBASE_FIFO(addr);
+
+ /* Copy buffer to endpoint FIFO, note - memcpy does not work */
+ for (i = len; i > 0; i -= 4)
+ *fifo++ = *buf32++;
+
+ return len;
+}
+
+u16 stm32fx07_ep_read_packet(usbd_device *usbd_dev, u8 addr, void *buf, u16 len)
+{
+ int i;
+ u32 *buf32 = buf;
+ u32 extra;
+
+ len = MIN(len, usbd_dev->rxbcnt);
+ usbd_dev->rxbcnt -= len;
+
+ volatile u32 *fifo = REBASE_FIFO(addr);
+ for (i = len; i >= 4; i -= 4)
+ *buf32++ = *fifo++;
+
+ if (i) {
+ extra = *fifo++;
+ memcpy(buf32, &extra, i);
+ }
+
+ REBASE(OTG_DOEPTSIZ(addr)) = usbd_dev->doeptsiz[addr];
+ REBASE(OTG_DOEPCTL(addr)) |= OTG_FS_DOEPCTL0_EPENA |
+ (usbd_dev->force_nak[addr] ?
+ OTG_FS_DOEPCTL0_SNAK : OTG_FS_DOEPCTL0_CNAK);
+
+ return len;
+}
+
+void stm32fx07_poll(usbd_device *usbd_dev)
+{
+ /* Read interrupt status register. */
+ u32 intsts = REBASE(OTG_GINTSTS);
+ int i;
+
+ if (intsts & OTG_FS_GINTSTS_ENUMDNE) {
+ /* Handle USB RESET condition. */
+ REBASE(OTG_GINTSTS) = OTG_FS_GINTSTS_ENUMDNE;
+ usbd_dev->fifo_mem_top = usbd_dev->driver->rx_fifo_size;
+ _usbd_reset(usbd_dev);
+ return;
+ }
+
+ /* Note: RX and TX handled differently in this device. */
+ if (intsts & OTG_FS_GINTSTS_RXFLVL) {
+ /* Receive FIFO non-empty. */
+ u32 rxstsp = REBASE(OTG_GRXSTSP);
+ u32 pktsts = rxstsp & OTG_FS_GRXSTSP_PKTSTS_MASK;
+ if ((pktsts != OTG_FS_GRXSTSP_PKTSTS_OUT) &&
+ (pktsts != OTG_FS_GRXSTSP_PKTSTS_SETUP))
+ return;
+
+ u8 ep = rxstsp & OTG_FS_GRXSTSP_EPNUM_MASK;
+ u8 type;
+ if (pktsts == OTG_FS_GRXSTSP_PKTSTS_SETUP)
+ type = USB_TRANSACTION_SETUP;
+ else
+ type = USB_TRANSACTION_OUT;
+
+ /* Save packet size for stm32f107_ep_read_packet(). */
+ usbd_dev->rxbcnt = (rxstsp & OTG_FS_GRXSTSP_BCNT_MASK) >> 4;
+
+ /*
+ * FIXME: Why is a delay needed here?
+ * This appears to fix a problem where the first 4 bytes
+ * of the DATA OUT stage of a control transaction are lost.
+ */
+ for (i = 0; i < 1000; i++)
+ __asm__("nop");
+
+ if (usbd_dev->user_callback_ctr[ep][type])
+ usbd_dev->user_callback_ctr[ep][type] (usbd_dev, ep);
+
+ /* Discard unread packet data. */
+ for (i = 0; i < usbd_dev->rxbcnt; i += 4)
+ (void)*REBASE_FIFO(ep);
+
+ usbd_dev->rxbcnt = 0;
+ }
+
+ /*
+ * There is no global interrupt flag for transmit complete.
+ * The XFRC bit must be checked in each OTG_FS_DIEPINT(x).
+ */
+ for (i = 0; i < 4; i++) { /* Iterate over endpoints. */
+ if (REBASE(OTG_DIEPINT(i)) & OTG_FS_DIEPINTX_XFRC) {
+ /* Transfer complete. */
+ if (usbd_dev->user_callback_ctr[i][USB_TRANSACTION_IN])
+ usbd_dev->user_callback_ctr[i]
+ [USB_TRANSACTION_IN](usbd_dev, i);
+
+ REBASE(OTG_DIEPINT(i)) = OTG_FS_DIEPINTX_XFRC;
+ }
+ }
+
+ if (intsts & OTG_FS_GINTSTS_USBSUSP) {
+ if (usbd_dev->user_callback_suspend)
+ usbd_dev->user_callback_suspend();
+ REBASE(OTG_GINTSTS) = OTG_FS_GINTSTS_USBSUSP;
+ }
+
+ if (intsts & OTG_FS_GINTSTS_WKUPINT) {
+ if (usbd_dev->user_callback_resume)
+ usbd_dev->user_callback_resume();
+ REBASE(OTG_GINTSTS) = OTG_FS_GINTSTS_WKUPINT;
+ }
+
+ if (intsts & OTG_FS_GINTSTS_SOF) {
+ if (usbd_dev->user_callback_sof)
+ usbd_dev->user_callback_sof();
+ REBASE(OTG_GINTSTS) = OTG_FS_GINTSTS_SOF;
+ }
+}
+
+void stm32fx07_disconnect(usbd_device *usbd_dev, bool disconnected)
+{
+ if (disconnected) {
+ REBASE(OTG_DCTL) |= OTG_FS_DCTL_SDIS;
+ } else {
+ REBASE(OTG_DCTL) &= ~OTG_FS_DCTL_SDIS;
+ }
+}
diff --git a/lib/usb/usb_fx07_common.h b/lib/usb/usb_fx07_common.h
new file mode 100644
index 0000000..4d8d38e
--- /dev/null
+++ b/lib/usb/usb_fx07_common.h
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2011 Gareth McMullin <gareth@blacksphere.co.nz>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __USB_FX07_COMMON_H_
+#define __USB_FX07_COMMON_H_
+
+void stm32fx07_set_address(usbd_device *usbd_dev, u8 addr);
+void stm32fx07_ep_setup(usbd_device *usbd_dev, u8 addr, u8 type, u16 max_size,
+ void (*callback)(usbd_device *usbd_dev, u8 ep));
+void stm32fx07_endpoints_reset(usbd_device *usbd_dev);
+void stm32fx07_ep_stall_set(usbd_device *usbd_dev, u8 addr, u8 stall);
+u8 stm32fx07_ep_stall_get(usbd_device *usbd_dev, u8 addr);
+void stm32fx07_ep_nak_set(usbd_device *usbd_dev, u8 addr, u8 nak);
+u16 stm32fx07_ep_write_packet(usbd_device *usbd_dev, u8 addr, const void *buf,
+ u16 len);
+u16 stm32fx07_ep_read_packet(usbd_device *usbd_dev, u8 addr, void *buf,
+ u16 len);
+void stm32fx07_poll(usbd_device *usbd_dev);
+void stm32fx07_disconnect(usbd_device *usbd_dev, bool disconnected);
+
+
+#endif /* __USB_FX07_COMMON_H_ */
diff --git a/lib/usb/usb_private.h b/lib/usb/usb_private.h
index a1e5e4c..454e8c6 100644
--- a/lib/usb/usb_private.h
+++ b/lib/usb/usb_private.h
@@ -25,10 +25,11 @@
#define MIN(a, b) ((a)<(b) ? (a) : (b))
/** Internal collection of device information. */
-extern struct _usbd_device {
+struct _usbd_device {
const struct usb_device_descriptor *desc;
const struct usb_config_descriptor *config;
const char **strings;
+ int num_strings;
u8 *ctrl_buf; /**< Internal buffer used for control transfers */
u16 ctrl_buf_len;
@@ -44,19 +45,49 @@ extern struct _usbd_device {
void (*user_callback_resume)(void);
void (*user_callback_sof)(void);
+ struct usb_control_state {
+ enum {
+ IDLE, STALLED,
+ DATA_IN, LAST_DATA_IN, STATUS_IN,
+ DATA_OUT, LAST_DATA_OUT, STATUS_OUT,
+ } state;
+ struct usb_setup_data req __attribute__((aligned(4)));
+ u8 *ctrl_buf;
+ u16 ctrl_len;
+ void (*complete)(usbd_device *usbd_dev,
+ struct usb_setup_data *req);
+ } control_state;
+
struct user_control_callback {
usbd_control_callback cb;
u8 type;
u8 type_mask;
} user_control_callback[MAX_USER_CONTROL_CALLBACK];
- void (*user_callback_ctr[8][3])(u8 ea);
+ void (*user_callback_ctr[8][3])(usbd_device *usbd_dev, u8 ea);
/* User callback function for some standard USB function hooks */
- void (*user_callback_set_config)(u16 wValue);
+ void (*user_callback_set_config)(usbd_device *usbd_dev, u16 wValue);
const struct _usbd_driver *driver;
-} _usbd_device;
+
+ /* private driver data */
+
+ uint16_t fifo_mem_top;
+ uint16_t fifo_mem_top_ep0;
+ u8 force_nak[4];
+ /*
+ * We keep a backup copy of the out endpoint size registers to restore them
+ * after a transaction.
+ */
+ u32 doeptsiz[4];
+ /*
+ * Received packet size for each endpoint. This is assigned in
+ * stm32f107_poll() which reads the packet status push register GRXSTSP
+ * for use in stm32f107_ep_read_packet().
+ */
+ uint16_t rxbcnt;
+};
enum _usbd_transaction {
USB_TRANSACTION_IN,
@@ -64,31 +95,34 @@ enum _usbd_transaction {
USB_TRANSACTION_SETUP,
};
-void _usbd_control_in(u8 ea);
-void _usbd_control_out(u8 ea);
-void _usbd_control_setup(u8 ea);
+void _usbd_control_in(usbd_device *usbd_dev, u8 ea);
+void _usbd_control_out(usbd_device *usbd_dev, u8 ea);
+void _usbd_control_setup(usbd_device *usbd_dev, u8 ea);
-int _usbd_standard_request(struct usb_setup_data *req, u8 **buf, u16 *len);
+int _usbd_standard_request(usbd_device *usbd_dev, struct usb_setup_data *req,
+ u8 **buf, u16 *len);
-void _usbd_reset(void);
+void _usbd_reset(usbd_device *usbd_dev);
/* Functions provided by the hardware abstraction. */
struct _usbd_driver {
- void (*init)(void);
- void (*set_address)(u8 addr);
- void (*ep_setup)(u8 addr, u8 type, u16 max_size, void (*cb)(u8 ep));
- void (*ep_reset)(void);
- void (*ep_stall_set)(u8 addr, u8 stall);
- void (*ep_nak_set)(u8 addr, u8 nak);
- u8 (*ep_stall_get)(u8 addr);
- u16 (*ep_write_packet)(u8 addr, const void *buf, u16 len);
- u16 (*ep_read_packet)(u8 addr, void *buf, u16 len);
- void (*poll)(void);
- void (*disconnect)(bool disconnected);
+ usbd_device *(*init)(void);
+ void (*set_address)(usbd_device *usbd_dev, u8 addr);
+ void (*ep_setup)(usbd_device *usbd_dev, u8 addr, u8 type, u16 max_size,
+ void (*cb)(usbd_device *usbd_dev, u8 ep));
+ void (*ep_reset)(usbd_device *usbd_dev);
+ void (*ep_stall_set)(usbd_device *usbd_dev, u8 addr, u8 stall);
+ void (*ep_nak_set)(usbd_device *usbd_dev, u8 addr, u8 nak);
+ u8 (*ep_stall_get)(usbd_device *usbd_dev, u8 addr);
+ u16 (*ep_write_packet)(usbd_device *usbd_dev, u8 addr, const void *buf,
+ u16 len);
+ u16 (*ep_read_packet)(usbd_device *usbd_dev, u8 addr, void *buf,
+ u16 len);
+ void (*poll)(usbd_device *usbd_dev);
+ void (*disconnect)(usbd_device *usbd_dev, bool disconnected);
+ u32 base_address;
+ bool set_address_before_status;
+ u16 rx_fifo_size;
};
-#define _usbd_hw_init() _usbd_device.driver->init()
-#define _usbd_hw_set_address(addr) _usbd_device.driver->set_address(addr)
-#define _usbd_hw_endpoints_reset() _usbd_device.driver->ep_reset()
-
#endif
diff --git a/lib/usb/usb_standard.c b/lib/usb/usb_standard.c
index 2d7c619..e14fee3 100644
--- a/lib/usb/usb_standard.c
+++ b/lib/usb/usb_standard.c
@@ -21,15 +21,18 @@
#include <libopencm3/usb/usbd.h>
#include "usb_private.h"
-void usbd_register_set_config_callback(void (*callback)(u16 wValue))
+void usbd_register_set_config_callback(usbd_device *usbd_dev,
+ void (*callback)(usbd_device *usbd_dev,
+ u16 wValue))
{
- _usbd_device.user_callback_set_config = callback;
+ usbd_dev->user_callback_set_config = callback;
}
-static u16 build_config_descriptor(u8 index, u8 *buf, u16 len)
+static u16 build_config_descriptor(usbd_device *usbd_dev,
+ u8 index, u8 *buf, u16 len)
{
u8 *tmpbuf = buf;
- const struct usb_config_descriptor *cfg = &_usbd_device.config[index];
+ const struct usb_config_descriptor *cfg = &usbd_dev->config[index];
u16 count, total = 0, totallen = 0;
u16 i, j, k;
@@ -43,7 +46,7 @@ static u16 build_config_descriptor(u8 index, u8 *buf, u16 len)
for (i = 0; i < cfg->bNumInterfaces; i++) {
/* Interface Association Descriptor, if any */
if (cfg->interface[i].iface_assoc) {
- const struct usb_iface_assoc_descriptor *assoc =
+ const struct usb_iface_assoc_descriptor *assoc =
cfg->interface[i].iface_assoc;
memcpy(buf, assoc, count = MIN(len, assoc->bLength));
buf += count;
@@ -87,53 +90,79 @@ static u16 build_config_descriptor(u8 index, u8 *buf, u16 len)
return total;
}
-static int usb_standard_get_descriptor(struct usb_setup_data *req,
+static int usb_descriptor_type(u16 wValue)
+{
+ return wValue >> 8;
+}
+
+static int usb_descriptor_index(u16 wValue)
+{
+ return wValue & 0xFF;
+}
+
+static int usb_standard_get_descriptor(usbd_device *usbd_dev,
+ struct usb_setup_data *req,
u8 **buf, u16 *len)
{
- int i;
+ int i, array_idx, descr_idx;
struct usb_string_descriptor *sd;
- switch (req->wValue >> 8) {
+ descr_idx = usb_descriptor_index(req->wValue);
+
+ switch (usb_descriptor_type(req->wValue)) {
case USB_DT_DEVICE:
- *buf = (u8 *) _usbd_device.desc;
- *len = MIN(*len, _usbd_device.desc->bLength);
- return 1;
+ *buf = (u8 *) usbd_dev->desc;
+ *len = MIN(*len, usbd_dev->desc->bLength);
+ return USBD_REQ_HANDLED;
case USB_DT_CONFIGURATION:
- *buf = _usbd_device.ctrl_buf;
- *len = build_config_descriptor(req->wValue & 0xff, *buf, *len);
- return 1;
+ *buf = usbd_dev->ctrl_buf;
+ *len = build_config_descriptor(usbd_dev, descr_idx, *buf, *len);
+ return USBD_REQ_HANDLED;
case USB_DT_STRING:
- sd = (struct usb_string_descriptor *)_usbd_device.ctrl_buf;
-
- if (!_usbd_device.strings)
- return 0; /* Device doesn't support strings. */
-
- /* Check that string index is in range. */
- for (i = 0; i <= (req->wValue & 0xff); i++)
- if (_usbd_device.strings[i] == NULL)
- return 0;
+ sd = (struct usb_string_descriptor *)usbd_dev->ctrl_buf;
+
+ if (descr_idx == 0) {
+ /* Send sane Language ID descriptor... */
+ sd->wData[0] = USB_LANGID_ENGLISH_US;
+ sd->bLength = sizeof(sd->bLength) + sizeof(sd->bDescriptorType)
+ + sizeof(sd->wData[0]);
+
+ *len = MIN(*len, sd->bLength);
+ } else {
+ array_idx = descr_idx - 1;
+
+ if (!usbd_dev->strings)
+ return USBD_REQ_NOTSUPP; /* Device doesn't support strings. */
+ /* Check that string index is in range. */
+ if (array_idx >= usbd_dev->num_strings)
+ return USBD_REQ_NOTSUPP;
+
+ /* Strings with Language ID differnet from
+ * USB_LANGID_ENGLISH_US are not supported */
+ if (req->wIndex != USB_LANGID_ENGLISH_US)
+ return USBD_REQ_NOTSUPP;
+
+ /* Ths string is returned as UTF16, hence the multiplication */
+ sd->bLength = strlen(usbd_dev->strings[array_idx]) * 2 +
+ sizeof(sd->bLength) + sizeof(sd->bDescriptorType);
+
+ *len = MIN(*len, sd->bLength);
+
+ for (i = 0; i < (*len / 2) - 1; i++)
+ sd->wData[i] =
+ usbd_dev->strings[array_idx][i];
+ }
- sd->bLength = strlen(_usbd_device.strings[req->wValue & 0xff])
- * 2 + 2;
sd->bDescriptorType = USB_DT_STRING;
-
*buf = (u8 *)sd;
- *len = MIN(*len, sd->bLength);
-
- for (i = 0; i < (*len / 2) - 1; i++)
- sd->wData[i] =
- _usbd_device.strings[req->wValue & 0xff][i];
- /* Send sane Language ID descriptor... */
- if ((req->wValue & 0xff) == 0)
- sd->wData[0] = 0x409;
-
- return 1;
+ return USBD_REQ_HANDLED;
}
- return 0;
+ return USBD_REQ_NOTSUPP;
}
-static int usb_standard_set_address(struct usb_setup_data *req, u8 **buf,
+static int usb_standard_set_address(usbd_device *usbd_dev,
+ struct usb_setup_data *req, u8 **buf,
u16 *len)
{
(void)req;
@@ -144,19 +173,20 @@ static int usb_standard_set_address(struct usb_setup_data *req, u8 **buf,
if ((req->bmRequestType != 0) || (req->wValue >= 128))
return 0;
- _usbd_device.current_address = req->wValue;
+ usbd_dev->current_address = req->wValue;
/*
* Special workaround for STM32F10[57] that require the address
* to be set here. This is undocumented!
*/
- if (_usbd_device.driver == &stm32f107_usb_driver)
- _usbd_device.driver->set_address(req->wValue);
+ if ( usbd_dev->driver->set_address_before_status)
+ usbd_dev->driver->set_address(usbd_dev, req->wValue);
return 1;
}
-static int usb_standard_set_configuration(struct usb_setup_data *req,
+static int usb_standard_set_configuration(usbd_device *usbd_dev,
+ struct usb_setup_data *req,
u8 **buf, u16 *len)
{
int i;
@@ -166,43 +196,46 @@ static int usb_standard_set_configuration(struct usb_setup_data *req,
(void)len;
/* Is this correct, or should we reset alternate settings. */
- if (req->wValue == _usbd_device.current_config)
+ if (req->wValue == usbd_dev->current_config)
return 1;
- _usbd_device.current_config = req->wValue;
+ usbd_dev->current_config = req->wValue;
/* Reset all endpoints. */
- _usbd_hw_endpoints_reset();
+ usbd_dev->driver->ep_reset(usbd_dev);
- if (_usbd_device.user_callback_set_config) {
+ if (usbd_dev->user_callback_set_config) {
/*
* Flush control callbacks. These will be reregistered
* by the user handler.
*/
for (i = 0; i < MAX_USER_CONTROL_CALLBACK; i++)
- _usbd_device.user_control_callback[i].cb = NULL;
+ usbd_dev->user_control_callback[i].cb = NULL;
- _usbd_device.user_callback_set_config(req->wValue);
+ usbd_dev->user_callback_set_config(usbd_dev, req->wValue);
}
return 1;
}
-static int usb_standard_get_configuration(struct usb_setup_data *req,
+static int usb_standard_get_configuration(usbd_device *usbd_dev,
+ struct usb_setup_data *req,
u8 **buf, u16 *len)
{
(void)req;
if (*len > 1)
*len = 1;
- (*buf)[0] = _usbd_device.current_config;
+ (*buf)[0] = usbd_dev->current_config;
return 1;
}
-static int usb_standard_set_interface(struct usb_setup_data *req,
+static int usb_standard_set_interface(usbd_device *usbd_dev,
+ struct usb_setup_data *req,
u8 **buf, u16 *len)
{
+ (void)usbd_dev;
(void)req;
(void)buf;
@@ -214,9 +247,11 @@ static int usb_standard_set_interface(struct usb_setup_data *req,
return 1;
}
-static int usb_standard_get_interface(struct usb_setup_data *req,
+static int usb_standard_get_interface(usbd_device *usbd_dev,
+ struct usb_setup_data *req,
u8 **buf, u16 *len)
{
+ (void)usbd_dev;
(void)req;
(void)buf;
@@ -227,9 +262,11 @@ static int usb_standard_get_interface(struct usb_setup_data *req,
return 1;
}
-static int usb_standard_device_get_status(struct usb_setup_data *req,
+static int usb_standard_device_get_status(usbd_device *usbd_dev,
+ struct usb_setup_data *req,
u8 **buf, u16 *len)
{
+ (void)usbd_dev;
(void)req;
/* bit 0: self powered */
@@ -242,9 +279,11 @@ static int usb_standard_device_get_status(struct usb_setup_data *req,
return 1;
}
-static int usb_standard_interface_get_status(struct usb_setup_data *req,
+static int usb_standard_interface_get_status(usbd_device *usbd_dev,
+ struct usb_setup_data *req,
u8 **buf, u16 *len)
{
+ (void)usbd_dev;
(void)req;
/* not defined */
@@ -256,45 +295,50 @@ static int usb_standard_interface_get_status(struct usb_setup_data *req,
return 1;
}
-static int usb_standard_endpoint_get_status(struct usb_setup_data *req,
+static int usb_standard_endpoint_get_status(usbd_device *usbd_dev,
+ struct usb_setup_data *req,
u8 **buf, u16 *len)
{
(void)req;
if (*len > 2)
*len = 2;
- (*buf)[0] = usbd_ep_stall_get(req->wIndex) ? 1 : 0;
+ (*buf)[0] = usbd_ep_stall_get(usbd_dev, req->wIndex) ? 1 : 0;
(*buf)[1] = 0;
return 1;
}
-static int usb_standard_endpoint_stall(struct usb_setup_data *req,
+static int usb_standard_endpoint_stall(usbd_device *usbd_dev,
+ struct usb_setup_data *req,
u8 **buf, u16 *len)
{
(void)buf;
(void)len;
- usbd_ep_stall_set(req->wIndex, 1);
+ usbd_ep_stall_set(usbd_dev, req->wIndex, 1);
return 1;
}
-static int usb_standard_endpoint_unstall(struct usb_setup_data *req,
+static int usb_standard_endpoint_unstall(usbd_device *usbd_dev,
+ struct usb_setup_data *req,
u8 **buf, u16 *len)
{
(void)buf;
(void)len;
- usbd_ep_stall_set(req->wIndex, 0);
+ usbd_ep_stall_set(usbd_dev, req->wIndex, 0);
return 1;
}
-int _usbd_standard_request_device(struct usb_setup_data *req, u8 **buf,
+int _usbd_standard_request_device(usbd_device *usbd_dev,
+ struct usb_setup_data *req, u8 **buf,
u16 *len)
{
- int (*command)(struct usb_setup_data *req, u8 **buf, u16 *len) = NULL;
+ int (*command)(usbd_device *usbd_dev, struct usb_setup_data *req, u8
+ **buf, u16 *len) = NULL;
switch (req->bRequest) {
case USB_REQ_CLEAR_FEATURE:
@@ -337,13 +381,15 @@ int _usbd_standard_request_device(struct usb_setup_data *req, u8 **buf,
if (!command)
return 0;
- return command(req, buf, len);
+ return command(usbd_dev, req, buf, len);
}
-int _usbd_standard_request_interface(struct usb_setup_data *req, u8 **buf,
+int _usbd_standard_request_interface(usbd_device *usbd_dev,
+ struct usb_setup_data *req, u8 **buf,
u16 *len)
{
- int (*command)(struct usb_setup_data *req, u8 **buf, u16 *len) = NULL;
+ int (*command)(usbd_device *usbd_dev, struct usb_setup_data *req,
+ u8 **buf, u16 *len) = NULL;
switch (req->bRequest) {
case USB_REQ_CLEAR_FEATURE:
@@ -364,13 +410,15 @@ int _usbd_standard_request_interface(struct usb_setup_data *req, u8 **buf,
if (!command)
return 0;
- return command(req, buf, len);
+ return command(usbd_dev, req, buf, len);
}
-int _usbd_standard_request_endpoint(struct usb_setup_data *req, u8 **buf,
+int _usbd_standard_request_endpoint(usbd_device *usbd_dev,
+ struct usb_setup_data *req, u8 **buf,
u16 *len)
{
- int (*command) (struct usb_setup_data *req, u8 **buf, u16 *len) = NULL;
+ int (*command) (usbd_device *usbd_dev, struct usb_setup_data *req,
+ u8 **buf, u16 *len) = NULL;
switch (req->bRequest) {
case USB_REQ_CLEAR_FEATURE:
@@ -396,10 +444,11 @@ int _usbd_standard_request_endpoint(struct usb_setup_data *req, u8 **buf,
if (!command)
return 0;
- return command(req, buf, len);
+ return command(usbd_dev, req, buf, len);
}
-int _usbd_standard_request(struct usb_setup_data *req, u8 **buf, u16 *len)
+int _usbd_standard_request(usbd_device *usbd_dev,
+ struct usb_setup_data *req, u8 **buf, u16 *len)
{
/* FIXME: Have class/vendor requests as well. */
if ((req->bmRequestType & USB_REQ_TYPE_TYPE) != USB_REQ_TYPE_STANDARD)
@@ -407,11 +456,12 @@ int _usbd_standard_request(struct usb_setup_data *req, u8 **buf, u16 *len)
switch (req->bmRequestType & USB_REQ_TYPE_RECIPIENT) {
case USB_REQ_TYPE_DEVICE:
- return _usbd_standard_request_device(req, buf, len);
+ return _usbd_standard_request_device(usbd_dev, req, buf, len);
case USB_REQ_TYPE_INTERFACE:
- return _usbd_standard_request_interface(req, buf, len);
+ return _usbd_standard_request_interface(usbd_dev, req,
+ buf, len);
case USB_REQ_TYPE_ENDPOINT:
- return _usbd_standard_request_endpoint(req, buf, len);
+ return _usbd_standard_request_endpoint(usbd_dev, req, buf, len);
default:
return 0;
}