From f36fae273ec84ee2c53a33caa2dddea2d79db0da Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Tue, 15 Nov 2011 12:45:43 -0500 Subject: Move public headers to include directories; related cleanups. Move libmaple/*.h to (new) libmaple/include/libmaple/. The new accepted way to include a libmaple header foo.h is with: #include This is more polite in terms of the include namespace. It also allows us to e.g. implement the Arduino SPI library at all (which has header SPI.h; providing it was previously impossible on case-insensitive filesystems due to libmaple's spi.h). Similarly for Wirish. The old include style (#include "header.h") is now deprecated. libmaple/*.h: - Change include guard #defines from _FOO_H_ to _LIBMAPLE_FOO_H_. - Add license headers where they're missing - Add conditional extern "C" { ... } blocks where they're missing (they aren't always necessary, but we might was well do it against the future, while we're at it.). - Change includes from #include "foo.h" to #include . - Move includes after extern "C". - Remove extra trailing newlines Note that this doesn't include the headers under libmaple/usb/ or libmaple/usb/usb_lib. These will get fixed later. libmaple/*.c: - Change includes from #include "foo.h" to #include . Makefile: - Add I$(LIBMAPLE_PATH)/include/libmaple to GLOBAL_FLAGS. This allows for users (including Wirish) to migrate their code, but should go away ASAP, since it slows down compilation. Wirish: - Move wirish/**/*.h to (new) wirish/include/wirish/. This ignores the USB headers, which, as usual, are getting handled after everything else. - Similarly generify wirish/boards/ structure. For each supported board "foo", move wirish/boards/foo.h and wirish/boards/foo.cpp to wirish/boards/foo/include/board/board.h and wirish/boards/foo/board.cpp, respectively. Also remove the #ifdef hacks around the .cpp files. - wirish/rules.mk: put wirish/boards/foo/include in the include path (and add wirish/boards/foo/board.cpp to the list of sources to be compiled). This allows saying: #include instead of the hack currently in place. We can allow the user to override this setting later to make adding custom board definitions easier. - Disable -Werror in libmaple/rules.mk, as the current USB warnings don't let the olimex_stm32_h103 board compile. We can re-enable -Werror once we've moved the board-specific bits out of libmaple proper. libraries, examples: - Update includes accordingly. - Miscellaneous cosmetic fixups. Signed-off-by: Marti Bolivar --- libmaple/rules.mk | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'libmaple/rules.mk') diff --git a/libmaple/rules.mk b/libmaple/rules.mk index 1ee611d..a6b330a 100644 --- a/libmaple/rules.mk +++ b/libmaple/rules.mk @@ -6,10 +6,13 @@ BUILDDIRS += $(BUILD_PATH)/$(d) BUILDDIRS += $(BUILD_PATH)/$(d)/usb BUILDDIRS += $(BUILD_PATH)/$(d)/usb/usb_lib -LIBMAPLE_INCLUDES := -I$(LIBMAPLE_PATH) -I$(LIBMAPLE_PATH)/usb -I$(LIBMAPLE_PATH)/usb/usb_lib +LIBMAPLE_INCLUDES := -I$(LIBMAPLE_PATH)/include +# FIXME: move public USB headers to include/libmaple/usb/ or something. +LIBMAPLE_INCLUDES += -I$(LIBMAPLE_PATH)/usb \ + -I$(LIBMAPLE_PATH)/usb/usb_lib # Local flags -CFLAGS_$(d) = -I$(d) $(LIBMAPLE_INCLUDES) -Wall -Werror +CFLAGS_$(d) = -I$(d) $(LIBMAPLE_INCLUDES) -Wall # -Werror # Local rules and targets cSRCS_$(d) := adc.c \ -- cgit v1.2.3 From 844665608fbeeab270e3d1a4bd797afd24302a10 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Wed, 16 Nov 2011 13:26:34 -0500 Subject: Make USB its own submodule. Add libmaple/usb/rules.mk, which compiles the USB FS device firmware submodule. Move the logic for compiling the USB stack from libmaple/rules.mk into libmaple/usb/rules.mk. Move libmaple/usb/usb_cdacm.h to libmaple/include/libmaple/. Its API is sufficiently general that we'll be able to port it over to USB OTG (either FS or HS) eventually, and that lets us include it from Wirish using the new style for libmaple headers. Fix the includes for public libmaple headers within libmaple/usb. Signed-off-by: Marti Bolivar --- Makefile | 1 + libmaple/include/libmaple/usb_cdcacm.h | 59 ++++++++++++++++++++++++++++++++++ libmaple/rules.mk | 14 +------- libmaple/usb/rules.mk | 36 +++++++++++++++++++++ libmaple/usb/usb.c | 8 +++-- libmaple/usb/usb_cdcacm.c | 10 +++--- libmaple/usb/usb_cdcacm.h | 59 ---------------------------------- libmaple/usb/usb_descriptors.h | 2 +- libmaple/usb/usb_lib_globals.h | 1 + libmaple/usb/usb_reg_map.h | 4 +-- wirish/boards.cpp | 2 +- wirish/usb_serial.cpp | 2 +- 12 files changed, 114 insertions(+), 84 deletions(-) create mode 100644 libmaple/include/libmaple/usb_cdcacm.h create mode 100644 libmaple/usb/rules.mk delete mode 100644 libmaple/usb/usb_cdcacm.h (limited to 'libmaple/rules.mk') diff --git a/Makefile b/Makefile index c6a1e07..c2a60dd 100644 --- a/Makefile +++ b/Makefile @@ -80,6 +80,7 @@ ifeq ($(LIBMAPLE_MODULES),) else LIBMAPLE_MODULES += $(SRCROOT)/libmaple endif +LIBMAPLE_MODULES += $(SRCROOT)/libmaple/usb # USB FS device LIBMAPLE_MODULES += $(LIBMAPLE_MODULE_FAMILY) # family submodule in libmaple LIBMAPLE_MODULES += $(SRCROOT)/wirish # Official libraries: diff --git a/libmaple/include/libmaple/usb_cdcacm.h b/libmaple/include/libmaple/usb_cdcacm.h new file mode 100644 index 0000000..2dbcbea --- /dev/null +++ b/libmaple/include/libmaple/usb_cdcacm.h @@ -0,0 +1,59 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 LeafLabs LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file usb_cdcacm.h + * @brief USB CDC ACM (virtual serial terminal) support + */ + +#ifndef _LIBMAPLE_USB_CDCACM_H_ +#define _LIBMAPLE_USB_CDCACM_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void usb_cdcacm_enable(gpio_dev*, uint8); +void usb_cdcacm_disable(gpio_dev*, uint8); + +void usb_cdcacm_putc(char ch); +uint32 usb_cdcacm_tx(const uint8* buf, uint32 len); +uint32 usb_cdcacm_rx(uint8* buf, uint32 len); + +uint32 usb_cdcacm_data_available(void); /* in RX buffer */ +uint16 usb_cdcacm_get_pending(void); + +uint8 usb_cdcacm_get_dtr(void); +uint8 usb_cdcacm_get_rts(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libmaple/rules.mk b/libmaple/rules.mk index a6b330a..3dcf0ce 100644 --- a/libmaple/rules.mk +++ b/libmaple/rules.mk @@ -3,13 +3,8 @@ sp := $(sp).x dirstack_$(sp) := $(d) d := $(dir) BUILDDIRS += $(BUILD_PATH)/$(d) -BUILDDIRS += $(BUILD_PATH)/$(d)/usb -BUILDDIRS += $(BUILD_PATH)/$(d)/usb/usb_lib LIBMAPLE_INCLUDES := -I$(LIBMAPLE_PATH)/include -# FIXME: move public USB headers to include/libmaple/usb/ or something. -LIBMAPLE_INCLUDES += -I$(LIBMAPLE_PATH)/usb \ - -I$(LIBMAPLE_PATH)/usb/usb_lib # Local flags CFLAGS_$(d) = -I$(d) $(LIBMAPLE_INCLUDES) -Wall # -Werror @@ -33,14 +28,7 @@ cSRCS_$(d) := adc.c \ systick.c \ timer.c \ usart.c \ - util.c \ - usb/usb.c \ - usb/usb_reg_map.c \ - usb/usb_cdcacm.c \ - usb/usb_lib/usb_core.c \ - usb/usb_lib/usb_init.c \ - usb/usb_lib/usb_mem.c \ - usb/usb_lib/usb_regs.c + util.c sSRCS_$(d) := exc.S diff --git a/libmaple/usb/rules.mk b/libmaple/usb/rules.mk new file mode 100644 index 0000000..9ef8d70 --- /dev/null +++ b/libmaple/usb/rules.mk @@ -0,0 +1,36 @@ +# Standard things +sp := $(sp).x +dirstack_$(sp) := $(d) +d := $(dir) +BUILDDIRS += $(BUILD_PATH)/$(d) +BUILDDIRS += $(BUILD_PATH)/$(d)/usb_lib + +# Local flags +CFLAGS_$(d) = -I$(d) -I$(d)/usb_lib $(LIBMAPLE_INCLUDES) -Wall + +# Local rules and targets +sSRCS_$(d) := +cSRCS_$(d) := usb.c \ + usb_reg_map.c \ + usb_cdcacm.c \ + usb_lib/usb_core.c \ + usb_lib/usb_init.c \ + usb_lib/usb_mem.c \ + usb_lib/usb_regs.c + +sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%) +cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%) + +OBJS_$(d) := $(sFILES_$(d):%.S=$(BUILD_PATH)/%.o) \ + $(cFILES_$(d):%.c=$(BUILD_PATH)/%.o) +DEPS_$(d) := $(OBJS_$(d):%.o=%.d) + +$(OBJS_$(d)): TGT_CFLAGS := $(CFLAGS_$(d)) +$(OBJS_$(d)): TGT_ASFLAGS := + +TGT_BIN += $(OBJS_$(d)) + +# Standard things +-include $(DEPS_$(d)) +d := $(dirstack_$(sp)) +sp := $(basename $(sp)) diff --git a/libmaple/usb/usb.c b/libmaple/usb/usb.c index 667b11f..6f23848 100644 --- a/libmaple/usb/usb.c +++ b/libmaple/usb/usb.c @@ -29,14 +29,16 @@ * @brief USB support. */ -#include "usb.h" +#include -#include "libmaple.h" -#include "rcc.h" +#include +#include +/* Private headers */ #include "usb_reg_map.h" #include "usb_lib_globals.h" +/* usb_lib headers */ #include "usb_type.h" #include "usb_core.h" diff --git a/libmaple/usb/usb_cdcacm.c b/libmaple/usb/usb_cdcacm.c index dc7b79e..07d2bc8 100644 --- a/libmaple/usb/usb_cdcacm.c +++ b/libmaple/usb/usb_cdcacm.c @@ -31,16 +31,18 @@ * routines. */ -#include "usb_cdcacm.h" +#include -#include "nvic.h" -#include "delay.h" +#include +#include +#include -#include "usb.h" +/* Private headers */ #include "usb_descriptors.h" #include "usb_lib_globals.h" #include "usb_reg_map.h" +/* usb_lib headers */ #include "usb_type.h" #include "usb_core.h" #include "usb_def.h" diff --git a/libmaple/usb/usb_cdcacm.h b/libmaple/usb/usb_cdcacm.h deleted file mode 100644 index ec672a3..0000000 --- a/libmaple/usb/usb_cdcacm.h +++ /dev/null @@ -1,59 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2011 LeafLabs LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file usb_cdcacm.h - * @brief USB CDC ACM (virtual serial terminal) support - */ - -#ifndef _USB_CDCACM_H_ -#define _USB_CDCACM_H_ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -void usb_cdcacm_enable(gpio_dev*, uint8); -void usb_cdcacm_disable(gpio_dev*, uint8); - -void usb_cdcacm_putc(char ch); -uint32 usb_cdcacm_tx(const uint8* buf, uint32 len); -uint32 usb_cdcacm_rx(uint8* buf, uint32 len); - -uint32 usb_cdcacm_data_available(void); /* in RX buffer */ -uint16 usb_cdcacm_get_pending(void); - -uint8 usb_cdcacm_get_dtr(void); -uint8 usb_cdcacm_get_rts(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/libmaple/usb/usb_descriptors.h b/libmaple/usb/usb_descriptors.h index 405588a..9bcb2b6 100644 --- a/libmaple/usb/usb_descriptors.h +++ b/libmaple/usb/usb_descriptors.h @@ -27,7 +27,7 @@ #ifndef _USB_DESCRIPTORS_H_ #define _USB_DESCRIPTORS_H_ -#include "libmaple.h" +#include #define USB_DESCRIPTOR_TYPE_DEVICE 0x01 #define USB_DESCRIPTOR_TYPE_CONFIGURATION 0x02 diff --git a/libmaple/usb/usb_lib_globals.h b/libmaple/usb/usb_lib_globals.h index a494817..1cd2754 100644 --- a/libmaple/usb/usb_lib_globals.h +++ b/libmaple/usb/usb_lib_globals.h @@ -27,6 +27,7 @@ #ifndef _USB_LIB_GLOBALS_H_ #define _USB_LIB_GLOBALS_H_ +/* usb_lib headers */ #include "usb_type.h" #include "usb_core.h" diff --git a/libmaple/usb/usb_reg_map.h b/libmaple/usb/usb_reg_map.h index 5bf5d96..ce80842 100644 --- a/libmaple/usb/usb_reg_map.h +++ b/libmaple/usb/usb_reg_map.h @@ -24,8 +24,8 @@ * SOFTWARE. *****************************************************************************/ -#include "libmaple_types.h" -#include "util.h" +#include +#include #ifndef _USB_REG_MAP_H_ #define _USB_REG_MAP_H_ diff --git a/wirish/boards.cpp b/wirish/boards.cpp index dbdcf1c..1f97119 100644 --- a/wirish/boards.cpp +++ b/wirish/boards.cpp @@ -41,7 +41,7 @@ #include #include #include -#include "usb_cdcacm.h" +#include static void setupFlash(void); static void setupClocks(void); diff --git a/wirish/usb_serial.cpp b/wirish/usb_serial.cpp index 1fd6e65..388c739 100644 --- a/wirish/usb_serial.cpp +++ b/wirish/usb_serial.cpp @@ -32,7 +32,7 @@ #include -#include "usb_cdcacm.h" +#include #include #include -- cgit v1.2.3 From bdf0c087c0172dd911bb1cda7531b2bd46312700 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Wed, 16 Nov 2011 14:48:12 -0500 Subject: libmaple/rules.mk: Reinstate -Werror. This is OK across all boards now that USB is its own submodule. Signed-off-by: Marti Bolivar --- libmaple/rules.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libmaple/rules.mk') diff --git a/libmaple/rules.mk b/libmaple/rules.mk index 3dcf0ce..cdc0614 100644 --- a/libmaple/rules.mk +++ b/libmaple/rules.mk @@ -7,7 +7,7 @@ BUILDDIRS += $(BUILD_PATH)/$(d) LIBMAPLE_INCLUDES := -I$(LIBMAPLE_PATH)/include # Local flags -CFLAGS_$(d) = -I$(d) $(LIBMAPLE_INCLUDES) -Wall # -Werror +CFLAGS_$(d) = -I$(d) $(LIBMAPLE_INCLUDES) -Wall -Werror # Local rules and targets cSRCS_$(d) := adc.c \ -- cgit v1.2.3 From b6290890b64d5188f75527b979c5c7912547be9b Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Wed, 16 Nov 2011 15:14:03 -0500 Subject: Move RCC support for STM32F1 to libmaple/stm32f1/. This is a backwards-compatible change. Modify libmaple/rules.mk to include the family's include directory. This allows libmaple/include/libmaple/rcc.h to include the STM32F1 RCC header with #include . We'll use this convention henceforth to distinguish between top-level and family-specific headers. Signed-off-by: Marti Bolivar --- libmaple/include/libmaple/rcc.h | 523 ++------------------------------ libmaple/rcc.c | 206 ------------- libmaple/rules.mk | 3 +- libmaple/stm32f1/include/family/rcc.h | 553 ++++++++++++++++++++++++++++++++++ libmaple/stm32f1/rcc.c | 205 +++++++++++++ libmaple/stm32f1/rules.mk | 9 +- 6 files changed, 784 insertions(+), 715 deletions(-) delete mode 100644 libmaple/rcc.c create mode 100644 libmaple/stm32f1/include/family/rcc.h create mode 100644 libmaple/stm32f1/rcc.c (limited to 'libmaple/rules.mk') diff --git a/libmaple/include/libmaple/rcc.h b/libmaple/include/libmaple/rcc.h index ef44b68..a4b66e5 100644 --- a/libmaple/include/libmaple/rcc.h +++ b/libmaple/include/libmaple/rcc.h @@ -26,7 +26,7 @@ /** * @file rcc.h - * @brief reset and clock control definitions and prototypes + * @brief Reset and Clock Control (RCC) interface. */ #ifndef _LIBMAPLE_RCC_H_ @@ -37,350 +37,23 @@ extern "C"{ #endif #include +#include -/** RCC register map type */ -typedef struct rcc_reg_map { - __io uint32 CR; /**< Clock control register */ - __io uint32 CFGR; /**< Clock configuration register */ - __io uint32 CIR; /**< Clock interrupt register */ - __io uint32 APB2RSTR; /**< APB2 peripheral reset register */ - __io uint32 APB1RSTR; /**< APB1 peripheral reset register */ - __io uint32 AHBENR; /**< AHB peripheral clock enable register */ - __io uint32 APB2ENR; /**< APB2 peripheral clock enable register */ - __io uint32 APB1ENR; /**< APB1 peripheral clock enable register */ - __io uint32 BDCR; /**< Backup domain control register */ - __io uint32 CSR; /**< Control/status register */ -} rcc_reg_map; - -/** RCC register map base pointer */ -#define RCC_BASE ((struct rcc_reg_map*)0x40021000) - -/* - * Register bit definitions - */ - -/* Clock control register */ - -#define RCC_CR_PLLRDY_BIT 25 -#define RCC_CR_PLLON_BIT 24 -#define RCC_CR_CSSON_BIT 19 -#define RCC_CR_HSEBYP_BIT 18 -#define RCC_CR_HSERDY_BIT 17 -#define RCC_CR_HSEON_BIT 16 -#define RCC_CR_HSIRDY_BIT 1 -#define RCC_CR_HSION_BIT 0 - -#define RCC_CR_PLLRDY BIT(RCC_CR_PLLRDY_BIT) -#define RCC_CR_PLLON BIT(RCC_CR_PLLON_BIT) -#define RCC_CR_CSSON BIT(RCC_CR_CSSON_BIT) -#define RCC_CR_HSEBYP BIT(RCC_CR_HSEBYP_BIT) -#define RCC_CR_HSERDY BIT(RCC_CR_HSERDY_BIT) -#define RCC_CR_HSEON BIT(RCC_CR_HSEON_BIT) -#define RCC_CR_HSICAL (0xFF << 8) -#define RCC_CR_HSITRIM (0x1F << 3) -#define RCC_CR_HSIRDY BIT(RCC_CR_HSIRDY_BIT) -#define RCC_CR_HSION BIT(RCC_CR_HSION_BIT) - -/* Clock configuration register */ - -#define RCC_CFGR_USBPRE_BIT 22 -#define RCC_CFGR_PLLXTPRE_BIT 17 -#define RCC_CFGR_PLLSRC_BIT 16 - -#define RCC_CFGR_MCO (0x3 << 24) -#define RCC_CFGR_USBPRE BIT(RCC_CFGR_USBPRE_BIT) -#define RCC_CFGR_PLLMUL (0xF << 18) -#define RCC_CFGR_PLLXTPRE BIT(RCC_CFGR_PLLXTPRE_BIT) -#define RCC_CFGR_PLLSRC BIT(RCC_CFGR_PLLSRC_BIT) -#define RCC_CFGR_ADCPRE (0x3 << 14) -#define RCC_CFGR_PPRE2 (0x7 << 11) -#define RCC_CFGR_PPRE1 (0x7 << 8) -#define RCC_CFGR_HPRE (0xF << 4) -#define RCC_CFGR_SWS (0x3 << 2) -#define RCC_CFGR_SWS_PLL (0x2 << 2) -#define RCC_CFGR_SWS_HSE (0x1 << 2) -#define RCC_CFGR_SW 0x3 -#define RCC_CFGR_SW_PLL 0x2 -#define RCC_CFGR_SW_HSE 0x1 - -/* Clock interrupt register */ - -#define RCC_CIR_CSSC_BIT 23 -#define RCC_CIR_PLLRDYC_BIT 20 -#define RCC_CIR_HSERDYC_BIT 19 -#define RCC_CIR_HSIRDYC_BIT 18 -#define RCC_CIR_LSERDYC_BIT 17 -#define RCC_CIR_LSIRDYC_BIT 16 -#define RCC_CIR_PLLRDYIE_BIT 12 -#define RCC_CIR_HSERDYIE_BIT 11 -#define RCC_CIR_HSIRDYIE_BIT 10 -#define RCC_CIR_LSERDYIE_BIT 9 -#define RCC_CIR_LSIRDYIE_BIT 8 -#define RCC_CIR_CSSF_BIT 7 -#define RCC_CIR_PLLRDYF_BIT 4 -#define RCC_CIR_HSERDYF_BIT 3 -#define RCC_CIR_HSIRDYF_BIT 2 -#define RCC_CIR_LSERDYF_BIT 1 -#define RCC_CIR_LSIRDYF_BIT 0 - -#define RCC_CIR_CSSC BIT(RCC_CIR_CSSC_BIT) -#define RCC_CIR_PLLRDYC BIT(RCC_CIR_PLLRDYC_BIT) -#define RCC_CIR_HSERDYC BIT(RCC_CIR_HSERDYC_BIT) -#define RCC_CIR_HSIRDYC BIT(RCC_CIR_HSIRDYC_BIT) -#define RCC_CIR_LSERDYC BIT(RCC_CIR_LSERDYC_BIT) -#define RCC_CIR_LSIRDYC BIT(RCC_CIR_LSIRDYC_BIT) -#define RCC_CIR_PLLRDYIE BIT(RCC_CIR_PLLRDYIE_BIT) -#define RCC_CIR_HSERDYIE BIT(RCC_CIR_HSERDYIE_BIT) -#define RCC_CIR_HSIRDYIE BIT(RCC_CIR_HSIRDYIE_BIT) -#define RCC_CIR_LSERDYIE BIT(RCC_CIR_LSERDYIE_BIT) -#define RCC_CIR_LSIRDYIE BIT(RCC_CIR_LSIRDYIE_BIT) -#define RCC_CIR_CSSF BIT(RCC_CIR_CSSF_BIT) -#define RCC_CIR_PLLRDYF BIT(RCC_CIR_PLLRDYF_BIT) -#define RCC_CIR_HSERDYF BIT(RCC_CIR_HSERDYF_BIT) -#define RCC_CIR_HSIRDYF BIT(RCC_CIR_HSIRDYF_BIT) -#define RCC_CIR_LSERDYF BIT(RCC_CIR_LSERDYF_BIT) -#define RCC_CIR_LSIRDYF BIT(RCC_CIR_LSIRDYF_BIT) - -/* APB2 peripheral reset register */ - -#define RCC_APB2RSTR_TIM11RST_BIT 21 -#define RCC_APB2RSTR_TIM10RST_BIT 20 -#define RCC_APB2RSTR_TIM9RST_BIT 19 -#define RCC_APB2RSTR_ADC3RST_BIT 15 -#define RCC_APB2RSTR_USART1RST_BIT 14 -#define RCC_APB2RSTR_TIM8RST_BIT 13 -#define RCC_APB2RSTR_SPI1RST_BIT 12 -#define RCC_APB2RSTR_TIM1RST_BIT 11 -#define RCC_APB2RSTR_ADC2RST_BIT 10 -#define RCC_APB2RSTR_ADC1RST_BIT 9 -#define RCC_APB2RSTR_IOPGRST_BIT 8 -#define RCC_APB2RSTR_IOPFRST_BIT 7 -#define RCC_APB2RSTR_IOPERST_BIT 6 -#define RCC_APB2RSTR_IOPDRST_BIT 5 -#define RCC_APB2RSTR_IOPCRST_BIT 4 -#define RCC_APB2RSTR_IOPBRST_BIT 3 -#define RCC_APB2RSTR_IOPARST_BIT 2 -#define RCC_APB2RSTR_AFIORST_BIT 0 - -#define RCC_APB2RSTR_TIM11RST BIT(RCC_APB2RSTR_TIM11RST_BIT) -#define RCC_APB2RSTR_TIM10RST BIT(RCC_APB2RSTR_TIM10RST_BIT) -#define RCC_APB2RSTR_TIM9RST BIT(RCC_APB2RSTR_TIM9RST_BIT) -#define RCC_APB2RSTR_ADC3RST BIT(RCC_APB2RSTR_ADC3RST_BIT) -#define RCC_APB2RSTR_USART1RST BIT(RCC_APB2RSTR_USART1RST_BIT) -#define RCC_APB2RSTR_TIM8RST BIT(RCC_APB2RSTR_TIM8RST_BIT) -#define RCC_APB2RSTR_SPI1RST BIT(RCC_APB2RSTR_SPI1RST_BIT) -#define RCC_APB2RSTR_TIM1RST BIT(RCC_APB2RSTR_TIM1RST_BIT) -#define RCC_APB2RSTR_ADC2RST BIT(RCC_APB2RSTR_ADC2RST_BIT) -#define RCC_APB2RSTR_ADC1RST BIT(RCC_APB2RSTR_ADC1RST_BIT) -#define RCC_APB2RSTR_IOPGRST BIT(RCC_APB2RSTR_IOPGRST_BIT) -#define RCC_APB2RSTR_IOPFRST BIT(RCC_APB2RSTR_IOPFRST_BIT) -#define RCC_APB2RSTR_IOPERST BIT(RCC_APB2RSTR_IOPERST_BIT) -#define RCC_APB2RSTR_IOPDRST BIT(RCC_APB2RSTR_IOPDRST_BIT) -#define RCC_APB2RSTR_IOPCRST BIT(RCC_APB2RSTR_IOPCRST_BIT) -#define RCC_APB2RSTR_IOPBRST BIT(RCC_APB2RSTR_IOPBRST_BIT) -#define RCC_APB2RSTR_IOPARST BIT(RCC_APB2RSTR_IOPARST_BIT) -#define RCC_APB2RSTR_AFIORST BIT(RCC_APB2RSTR_AFIORST_BIT) - -/* APB1 peripheral reset register */ - -#define RCC_APB1RSTR_DACRST_BIT 29 -#define RCC_APB1RSTR_PWRRST_BIT 28 -#define RCC_APB1RSTR_BKPRST_BIT 27 -#define RCC_APB1RSTR_CANRST_BIT 25 -#define RCC_APB1RSTR_USBRST_BIT 23 -#define RCC_APB1RSTR_I2C2RST_BIT 22 -#define RCC_APB1RSTR_I2C1RST_BIT 21 -#define RCC_APB1RSTR_UART5RST_BIT 20 -#define RCC_APB1RSTR_UART4RST_BIT 19 -#define RCC_APB1RSTR_USART3RST_BIT 18 -#define RCC_APB1RSTR_USART2RST_BIT 17 -#define RCC_APB1RSTR_SPI3RST_BIT 15 -#define RCC_APB1RSTR_SPI2RST_BIT 14 -#define RCC_APB1RSTR_WWDRST_BIT 11 -#define RCC_APB1RSTR_TIM14RST_BIT 8 -#define RCC_APB1RSTR_TIM13RST_BIT 7 -#define RCC_APB1RSTR_TIM12RST_BIT 6 -#define RCC_APB1RSTR_TIM7RST_BIT 5 -#define RCC_APB1RSTR_TIM6RST_BIT 4 -#define RCC_APB1RSTR_TIM5RST_BIT 3 -#define RCC_APB1RSTR_TIM4RST_BIT 2 -#define RCC_APB1RSTR_TIM3RST_BIT 1 -#define RCC_APB1RSTR_TIM2RST_BIT 0 - -#define RCC_APB1RSTR_DACRST BIT(RCC_APB1RSTR_DACRST_BIT) -#define RCC_APB1RSTR_PWRRST BIT(RCC_APB1RSTR_PWRRST_BIT) -#define RCC_APB1RSTR_BKPRST BIT(RCC_APB1RSTR_BKPRST_BIT) -#define RCC_APB1RSTR_CANRST BIT(RCC_APB1RSTR_CANRST_BIT) -#define RCC_APB1RSTR_USBRST BIT(RCC_APB1RSTR_USBRST_BIT) -#define RCC_APB1RSTR_I2C2RST BIT(RCC_APB1RSTR_I2C2RST_BIT) -#define RCC_APB1RSTR_I2C1RST BIT(RCC_APB1RSTR_I2C1RST_BIT) -#define RCC_APB1RSTR_UART5RST BIT(RCC_APB1RSTR_UART5RST_BIT) -#define RCC_APB1RSTR_UART4RST BIT(RCC_APB1RSTR_UART4RST_BIT) -#define RCC_APB1RSTR_USART3RST BIT(RCC_APB1RSTR_USART3RST_BIT) -#define RCC_APB1RSTR_USART2RST BIT(RCC_APB1RSTR_USART2RST_BIT) -#define RCC_APB1RSTR_SPI3RST BIT(RCC_APB1RSTR_SPI3RST_BIT) -#define RCC_APB1RSTR_SPI2RST BIT(RCC_APB1RSTR_SPI2RST_BIT) -#define RCC_APB1RSTR_WWDRST BIT(RCC_APB1RSTR_WWDRST_BIT) -#define RCC_APB1RSTR_TIM14RST BIT(RCC_APB1RSTR_TIM14RST_BIT) -#define RCC_APB1RSTR_TIM13RST BIT(RCC_APB1RSTR_TIM13RST_BIT) -#define RCC_APB1RSTR_TIM12RST BIT(RCC_APB1RSTR_TIM12RST_BIT) -#define RCC_APB1RSTR_TIM7RST BIT(RCC_APB1RSTR_TIM7RST_BIT) -#define RCC_APB1RSTR_TIM6RST BIT(RCC_APB1RSTR_TIM6RST_BIT) -#define RCC_APB1RSTR_TIM5RST BIT(RCC_APB1RSTR_TIM5RST_BIT) -#define RCC_APB1RSTR_TIM4RST BIT(RCC_APB1RSTR_TIM4RST_BIT) -#define RCC_APB1RSTR_TIM3RST BIT(RCC_APB1RSTR_TIM3RST_BIT) -#define RCC_APB1RSTR_TIM2RST BIT(RCC_APB1RSTR_TIM2RST_BIT) - -/* AHB peripheral clock enable register */ - -#define RCC_AHBENR_SDIOEN_BIT 10 -#define RCC_AHBENR_FSMCEN_BIT 8 -#define RCC_AHBENR_CRCEN_BIT 7 -#define RCC_AHBENR_FLITFEN_BIT 4 -#define RCC_AHBENR_SRAMEN_BIT 2 -#define RCC_AHBENR_DMA2EN_BIT 1 -#define RCC_AHBENR_DMA1EN_BIT 0 - -#define RCC_AHBENR_SDIOEN BIT(RCC_AHBENR_SDIOEN_BIT) -#define RCC_AHBENR_FSMCEN BIT(RCC_AHBENR_FSMCEN_BIT) -#define RCC_AHBENR_CRCEN BIT(RCC_AHBENR_CRCEN_BIT) -#define RCC_AHBENR_FLITFEN BIT(RCC_AHBENR_FLITFEN_BIT) -#define RCC_AHBENR_SRAMEN BIT(RCC_AHBENR_SRAMEN_BIT) -#define RCC_AHBENR_DMA2EN BIT(RCC_AHBENR_DMA2EN_BIT) -#define RCC_AHBENR_DMA1EN BIT(RCC_AHBENR_DMA1EN_BIT) - -/* APB2 peripheral clock enable register */ - -#define RCC_APB2ENR_TIM11EN_BIT 21 -#define RCC_APB2ENR_TIM10EN_BIT 20 -#define RCC_APB2ENR_TIM9EN_BIT 19 -#define RCC_APB2ENR_ADC3EN_BIT 15 -#define RCC_APB2ENR_USART1EN_BIT 14 -#define RCC_APB2ENR_TIM8EN_BIT 13 -#define RCC_APB2ENR_SPI1EN_BIT 12 -#define RCC_APB2ENR_TIM1EN_BIT 11 -#define RCC_APB2ENR_ADC2EN_BIT 10 -#define RCC_APB2ENR_ADC1EN_BIT 9 -#define RCC_APB2ENR_IOPGEN_BIT 8 -#define RCC_APB2ENR_IOPFEN_BIT 7 -#define RCC_APB2ENR_IOPEEN_BIT 6 -#define RCC_APB2ENR_IOPDEN_BIT 5 -#define RCC_APB2ENR_IOPCEN_BIT 4 -#define RCC_APB2ENR_IOPBEN_BIT 3 -#define RCC_APB2ENR_IOPAEN_BIT 2 -#define RCC_APB2ENR_AFIOEN_BIT 0 - -#define RCC_APB2ENR_TIM11EN BIT(RCC_APB2ENR_TIM11EN_BIT) -#define RCC_APB2ENR_TIM10EN BIT(RCC_APB2ENR_TIM10EN_BIT) -#define RCC_APB2ENR_TIM9EN BIT(RCC_APB2ENR_TIM9EN_BIT) -#define RCC_APB2ENR_ADC3EN BIT(RCC_APB2ENR_ADC3EN_BIT) -#define RCC_APB2ENR_USART1EN BIT(RCC_APB2ENR_USART1EN_BIT) -#define RCC_APB2ENR_TIM8EN BIT(RCC_APB2ENR_TIM8EN_BIT) -#define RCC_APB2ENR_SPI1EN BIT(RCC_APB2ENR_SPI1EN_BIT) -#define RCC_APB2ENR_TIM1EN BIT(RCC_APB2ENR_TIM1EN_BIT) -#define RCC_APB2ENR_ADC2EN BIT(RCC_APB2ENR_ADC2EN_BIT) -#define RCC_APB2ENR_ADC1EN BIT(RCC_APB2ENR_ADC1EN_BIT) -#define RCC_APB2ENR_IOPGEN BIT(RCC_APB2ENR_IOPGEN_BIT) -#define RCC_APB2ENR_IOPFEN BIT(RCC_APB2ENR_IOPFEN_BIT) -#define RCC_APB2ENR_IOPEEN BIT(RCC_APB2ENR_IOPEEN_BIT) -#define RCC_APB2ENR_IOPDEN BIT(RCC_APB2ENR_IOPDEN_BIT) -#define RCC_APB2ENR_IOPCEN BIT(RCC_APB2ENR_IOPCEN_BIT) -#define RCC_APB2ENR_IOPBEN BIT(RCC_APB2ENR_IOPBEN_BIT) -#define RCC_APB2ENR_IOPAEN BIT(RCC_APB2ENR_IOPAEN_BIT) -#define RCC_APB2ENR_AFIOEN BIT(RCC_APB2ENR_AFIOEN_BIT) - -/* APB1 peripheral clock enable register */ - -#define RCC_APB1ENR_DACEN_BIT 29 -#define RCC_APB1ENR_PWREN_BIT 28 -#define RCC_APB1ENR_BKPEN_BIT 27 -#define RCC_APB1ENR_CANEN_BIT 25 -#define RCC_APB1ENR_USBEN_BIT 23 -#define RCC_APB1ENR_I2C2EN_BIT 22 -#define RCC_APB1ENR_I2C1EN_BIT 21 -#define RCC_APB1ENR_UART5EN_BIT 20 -#define RCC_APB1ENR_UART4EN_BIT 19 -#define RCC_APB1ENR_USART3EN_BIT 18 -#define RCC_APB1ENR_USART2EN_BIT 17 -#define RCC_APB1ENR_SPI3EN_BIT 15 -#define RCC_APB1ENR_SPI2EN_BIT 14 -#define RCC_APB1ENR_WWDEN_BIT 11 -#define RCC_APB1ENR_TIM14EN_BIT 8 -#define RCC_APB1ENR_TIM13EN_BIT 7 -#define RCC_APB1ENR_TIM12EN_BIT 6 -#define RCC_APB1ENR_TIM7EN_BIT 5 -#define RCC_APB1ENR_TIM6EN_BIT 4 -#define RCC_APB1ENR_TIM5EN_BIT 3 -#define RCC_APB1ENR_TIM4EN_BIT 2 -#define RCC_APB1ENR_TIM3EN_BIT 1 -#define RCC_APB1ENR_TIM2EN_BIT 0 - -#define RCC_APB1ENR_DACEN BIT(RCC_APB1ENR_DACEN_BIT) -#define RCC_APB1ENR_PWREN BIT(RCC_APB1ENR_PWREN_BIT) -#define RCC_APB1ENR_BKPEN BIT(RCC_APB1ENR_BKPEN_BIT) -#define RCC_APB1ENR_CANEN BIT(RCC_APB1ENR_CANEN_BIT) -#define RCC_APB1ENR_USBEN BIT(RCC_APB1ENR_USBEN_BIT) -#define RCC_APB1ENR_I2C2EN BIT(RCC_APB1ENR_I2C2EN_BIT) -#define RCC_APB1ENR_I2C1EN BIT(RCC_APB1ENR_I2C1EN_BIT) -#define RCC_APB1ENR_UART5EN BIT(RCC_APB1ENR_UART5EN_BIT) -#define RCC_APB1ENR_UART4EN BIT(RCC_APB1ENR_UART4EN_BIT) -#define RCC_APB1ENR_USART3EN BIT(RCC_APB1ENR_USART3EN_BIT) -#define RCC_APB1ENR_USART2EN BIT(RCC_APB1ENR_USART2EN_BIT) -#define RCC_APB1ENR_SPI3EN BIT(RCC_APB1ENR_SPI3EN_BIT) -#define RCC_APB1ENR_SPI2EN BIT(RCC_APB1ENR_SPI2EN_BIT) -#define RCC_APB1ENR_WWDEN BIT(RCC_APB1ENR_WWDEN_BIT) -#define RCC_APB1ENR_TIM14EN BIT(RCC_APB1ENR_TIM14EN_BIT) -#define RCC_APB1ENR_TIM13EN BIT(RCC_APB1ENR_TIM13EN_BIT) -#define RCC_APB1ENR_TIM12EN BIT(RCC_APB1ENR_TIM12EN_BIT) -#define RCC_APB1ENR_TIM7EN BIT(RCC_APB1ENR_TIM7EN_BIT) -#define RCC_APB1ENR_TIM6EN BIT(RCC_APB1ENR_TIM6EN_BIT) -#define RCC_APB1ENR_TIM5EN BIT(RCC_APB1ENR_TIM5EN_BIT) -#define RCC_APB1ENR_TIM4EN BIT(RCC_APB1ENR_TIM4EN_BIT) -#define RCC_APB1ENR_TIM3EN BIT(RCC_APB1ENR_TIM3EN_BIT) -#define RCC_APB1ENR_TIM2EN BIT(RCC_APB1ENR_TIM2EN_BIT) - -/* Backup domain control register */ - -#define RCC_BDCR_BDRST_BIT 16 -#define RCC_BDCR_RTCEN_BIT 15 -#define RCC_BDCR_LSEBYP_BIT 2 -#define RCC_BDCR_LSERDY_BIT 1 -#define RCC_BDCR_LSEON_BIT 0 - -#define RCC_BDCR_BDRST BIT(RCC_BDCR_BDRST_BIT) -#define RCC_BDCR_RTCEN BIT(RCC_BDCR_RTC_BIT) -#define RCC_BDCR_RTCSEL (0x3 << 8) -#define RCC_BDCR_RTCSEL_NONE (0x0 << 8) -#define RCC_BDCR_RTCSEL_LSE (0x1 << 8) -#define RCC_BDCR_RTCSEL_HSE (0x3 << 8) -#define RCC_BDCR_LSEBYP BIT(RCC_BDCR_LSEBYP_BIT) -#define RCC_BDCR_LSERDY BIT(RCC_BDCR_LSERDY_BIT) -#define RCC_BDCR_LSEON BIT(RCC_BDCR_LSEON_BIT) - -/* Control/status register */ - -#define RCC_CSR_LPWRRSTF_BIT 31 -#define RCC_CSR_WWDGRSTF_BIT 30 -#define RCC_CSR_IWDGRSTF_BIT 29 -#define RCC_CSR_SFTRSTF_BIT 28 -#define RCC_CSR_PORRSTF_BIT 27 -#define RCC_CSR_PINRSTF_BIT 26 -#define RCC_CSR_RMVF_BIT 24 -#define RCC_CSR_LSIRDY_BIT 1 -#define RCC_CSR_LSION_BIT 0 - -#define RCC_CSR_LPWRRSTF BIT(RCC_CSR_LPWRRSTF_BIT) -#define RCC_CSR_WWDGRSTF BIT(RCC_CSR_WWDGRSTF_BIT) -#define RCC_CSR_IWDGRSTF BIT(RCC_CSR_IWDGRSTF_BIT) -#define RCC_CSR_SFTRSTF BIT(RCC_CSR_SFTRSTF_BIT) -#define RCC_CSR_PORRSTF BIT(RCC_CSR_PORRSTF_BIT) -#define RCC_CSR_PINRSTF BIT(RCC_CSR_PINRSTF_BIT) -#define RCC_CSR_RMVF BIT(RCC_CSR_RMVF_BIT) -#define RCC_CSR_LSIRDY BIT(RCC_CSR_LSIRDY_BIT) -#define RCC_CSR_LSION BIT(RCC_CSR_LSION_BIT) - -/* - * Convenience routines +/* Note: Beyond the usual (registers, etc.), it's up to the family + * header to define the following types: + * + * - rcc_pllsrc: For each PLL source (passed to rcc_clk_init()). + * + * - rcc_pll_multiplier: If appropriate (TODO verify this makes sense). + * + * - rcc_clk_id: For each available peripheral. These are widely used + * as unique IDs (TODO extricate from RCC?). Peripherals which are + * common across families should use the same token for their + * rcc_clk_id in each family header. + * + * - rcc_clk_domain: For each clock domain (returned by rcc_dev_clk()). + * + * - rcc_prescaler (and a suitable set of dividers): for rcc_set_prescaler(). */ /** @@ -393,174 +66,12 @@ typedef enum rcc_sysclk_src { RCC_CLKSRC_PLL = 0x2, } rcc_sysclk_src; -/** - * PLL entry clock source - * @see rcc_clk_init() - */ -typedef enum rcc_pllsrc { - RCC_PLLSRC_HSE = (0x1 << 16), - RCC_PLLSRC_HSI_DIV_2 = (0x0 << 16) -} rcc_pllsrc; - -/** - * PLL multipliers - * @see rcc_clk_init() - */ -typedef enum rcc_pll_multiplier { - RCC_PLLMUL_2 = (0x0 << 18), - RCC_PLLMUL_3 = (0x1 << 18), - RCC_PLLMUL_4 = (0x2 << 18), - RCC_PLLMUL_5 = (0x3 << 18), - RCC_PLLMUL_6 = (0x4 << 18), - RCC_PLLMUL_7 = (0x5 << 18), - RCC_PLLMUL_8 = (0x6 << 18), - RCC_PLLMUL_9 = (0x7 << 18), - RCC_PLLMUL_10 = (0x8 << 18), - RCC_PLLMUL_11 = (0x9 << 18), - RCC_PLLMUL_12 = (0xA << 18), - RCC_PLLMUL_13 = (0xB << 18), - RCC_PLLMUL_14 = (0xC << 18), - RCC_PLLMUL_15 = (0xD << 18), - RCC_PLLMUL_16 = (0xE << 18), -} rcc_pll_multiplier; - -/** - * @brief Identifies bus and clock line for a peripheral. - * - * Also generally useful as a unique identifier for that peripheral - * (or its corresponding device struct). - */ -typedef enum rcc_clk_id { - RCC_GPIOA, - RCC_GPIOB, - RCC_GPIOC, - RCC_GPIOD, - RCC_AFIO, - RCC_ADC1, - RCC_ADC2, - RCC_ADC3, - RCC_USART1, - RCC_USART2, - RCC_USART3, - RCC_TIMER1, - RCC_TIMER2, - RCC_TIMER3, - RCC_TIMER4, - RCC_SPI1, - RCC_SPI2, - RCC_DMA1, - RCC_PWR, - RCC_BKP, - RCC_I2C1, - RCC_I2C2, - RCC_CRC, - RCC_FLITF, - RCC_SRAM, - RCC_USB, -#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) - RCC_GPIOE, - RCC_GPIOF, - RCC_GPIOG, - RCC_UART4, - RCC_UART5, - RCC_TIMER5, - RCC_TIMER6, - RCC_TIMER7, - RCC_TIMER8, - RCC_FSMC, - RCC_DAC, - RCC_DMA2, - RCC_SDIO, - RCC_SPI3, -#endif -#ifdef STM32_XL_DENSITY - RCC_TIMER9, - RCC_TIMER10, - RCC_TIMER11, - RCC_TIMER12, - RCC_TIMER13, - RCC_TIMER14, -#endif -} rcc_clk_id; - void rcc_clk_init(rcc_sysclk_src sysclk_src, rcc_pllsrc pll_src, rcc_pll_multiplier pll_mul); void rcc_clk_enable(rcc_clk_id device); void rcc_reset_dev(rcc_clk_id device); - -typedef enum rcc_clk_domain { - RCC_APB1, - RCC_APB2, - RCC_AHB -} rcc_clk_domain; - rcc_clk_domain rcc_dev_clk(rcc_clk_id device); - -/** - * Prescaler identifiers - * @see rcc_set_prescaler() - */ -typedef enum rcc_prescaler { - RCC_PRESCALER_AHB, - RCC_PRESCALER_APB1, - RCC_PRESCALER_APB2, - RCC_PRESCALER_USB, - RCC_PRESCALER_ADC -} rcc_prescaler; - -/** - * ADC prescaler dividers - * @see rcc_set_prescaler() - */ -typedef enum rcc_adc_divider { - RCC_ADCPRE_PCLK_DIV_2 = 0x0 << 14, - RCC_ADCPRE_PCLK_DIV_4 = 0x1 << 14, - RCC_ADCPRE_PCLK_DIV_6 = 0x2 << 14, - RCC_ADCPRE_PCLK_DIV_8 = 0x3 << 14, -} rcc_adc_divider; - -/** - * APB1 prescaler dividers - * @see rcc_set_prescaler() - */ -typedef enum rcc_apb1_divider { - RCC_APB1_HCLK_DIV_1 = 0x0 << 8, - RCC_APB1_HCLK_DIV_2 = 0x4 << 8, - RCC_APB1_HCLK_DIV_4 = 0x5 << 8, - RCC_APB1_HCLK_DIV_8 = 0x6 << 8, - RCC_APB1_HCLK_DIV_16 = 0x7 << 8, -} rcc_apb1_divider; - -/** - * APB2 prescaler dividers - * @see rcc_set_prescaler() - */ -typedef enum rcc_apb2_divider { - RCC_APB2_HCLK_DIV_1 = 0x0 << 11, - RCC_APB2_HCLK_DIV_2 = 0x4 << 11, - RCC_APB2_HCLK_DIV_4 = 0x5 << 11, - RCC_APB2_HCLK_DIV_8 = 0x6 << 11, - RCC_APB2_HCLK_DIV_16 = 0x7 << 11, -} rcc_apb2_divider; - -/** - * AHB prescaler dividers - * @see rcc_set_prescaler() - */ -typedef enum rcc_ahb_divider { - RCC_AHB_SYSCLK_DIV_1 = 0x0 << 4, - RCC_AHB_SYSCLK_DIV_2 = 0x8 << 4, - RCC_AHB_SYSCLK_DIV_4 = 0x9 << 4, - RCC_AHB_SYSCLK_DIV_8 = 0xA << 4, - RCC_AHB_SYSCLK_DIV_16 = 0xB << 4, - RCC_AHB_SYSCLK_DIV_32 = 0xC << 4, - RCC_AHB_SYSCLK_DIV_64 = 0xD << 4, - RCC_AHB_SYSCLK_DIV_128 = 0xD << 4, - RCC_AHB_SYSCLK_DIV_256 = 0xE << 4, - RCC_AHB_SYSCLK_DIV_512 = 0xF << 4, -} rcc_ahb_divider; - void rcc_set_prescaler(rcc_prescaler prescaler, uint32 divider); #ifdef __cplusplus diff --git a/libmaple/rcc.c b/libmaple/rcc.c deleted file mode 100644 index ed3f11e..0000000 --- a/libmaple/rcc.c +++ /dev/null @@ -1,206 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file rcc.c - * @brief Implements pretty much only the basic clock setup on the - * stm32, clock enable/disable and peripheral reset commands. - */ - -#include -#include -#include -#include - -#define APB1 RCC_APB1 -#define APB2 RCC_APB2 -#define AHB RCC_AHB - -struct rcc_dev_info { - const rcc_clk_domain clk_domain; - const uint8 line_num; -}; - -/* Device descriptor table, maps rcc_clk_id onto bus and enable/reset - * register bit numbers. */ -static const struct rcc_dev_info rcc_dev_table[] = { - [RCC_GPIOA] = { .clk_domain = APB2, .line_num = 2 }, - [RCC_GPIOB] = { .clk_domain = APB2, .line_num = 3 }, - [RCC_GPIOC] = { .clk_domain = APB2, .line_num = 4 }, - [RCC_GPIOD] = { .clk_domain = APB2, .line_num = 5 }, - [RCC_AFIO] = { .clk_domain = APB2, .line_num = 0 }, - [RCC_ADC1] = { .clk_domain = APB2, .line_num = 9 }, - [RCC_ADC2] = { .clk_domain = APB2, .line_num = 10 }, - [RCC_ADC3] = { .clk_domain = APB2, .line_num = 15 }, - [RCC_USART1] = { .clk_domain = APB2, .line_num = 14 }, - [RCC_USART2] = { .clk_domain = APB1, .line_num = 17 }, - [RCC_USART3] = { .clk_domain = APB1, .line_num = 18 }, - [RCC_TIMER1] = { .clk_domain = APB2, .line_num = 11 }, - [RCC_TIMER2] = { .clk_domain = APB1, .line_num = 0 }, - [RCC_TIMER3] = { .clk_domain = APB1, .line_num = 1 }, - [RCC_TIMER4] = { .clk_domain = APB1, .line_num = 2 }, - [RCC_SPI1] = { .clk_domain = APB2, .line_num = 12 }, - [RCC_SPI2] = { .clk_domain = APB1, .line_num = 14 }, - [RCC_DMA1] = { .clk_domain = AHB, .line_num = 0 }, - [RCC_PWR] = { .clk_domain = APB1, .line_num = 28}, - [RCC_BKP] = { .clk_domain = APB1, .line_num = 27}, - [RCC_I2C1] = { .clk_domain = APB1, .line_num = 21 }, - [RCC_I2C2] = { .clk_domain = APB1, .line_num = 22 }, - [RCC_CRC] = { .clk_domain = AHB, .line_num = 6}, - [RCC_FLITF] = { .clk_domain = AHB, .line_num = 4}, - [RCC_SRAM] = { .clk_domain = AHB, .line_num = 2}, - [RCC_USB] = { .clk_domain = APB1, .line_num = 23}, -#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) - [RCC_GPIOE] = { .clk_domain = APB2, .line_num = 6 }, - [RCC_GPIOF] = { .clk_domain = APB2, .line_num = 7 }, - [RCC_GPIOG] = { .clk_domain = APB2, .line_num = 8 }, - [RCC_UART4] = { .clk_domain = APB1, .line_num = 19 }, - [RCC_UART5] = { .clk_domain = APB1, .line_num = 20 }, - [RCC_TIMER5] = { .clk_domain = APB1, .line_num = 3 }, - [RCC_TIMER6] = { .clk_domain = APB1, .line_num = 4 }, - [RCC_TIMER7] = { .clk_domain = APB1, .line_num = 5 }, - [RCC_TIMER8] = { .clk_domain = APB2, .line_num = 13 }, - [RCC_FSMC] = { .clk_domain = AHB, .line_num = 8 }, - [RCC_DAC] = { .clk_domain = APB1, .line_num = 29 }, - [RCC_DMA2] = { .clk_domain = AHB, .line_num = 1 }, - [RCC_SDIO] = { .clk_domain = AHB, .line_num = 10 }, - [RCC_SPI3] = { .clk_domain = APB1, .line_num = 15 }, -#endif -#ifdef STM32_XL_DENSITY - [RCC_TIMER9] = { .clk_domain = APB2, .line_num = 19 }, - [RCC_TIMER10] = { .clk_domain = APB2, .line_num = 20 }, - [RCC_TIMER11] = { .clk_domain = APB2, .line_num = 21 }, - [RCC_TIMER12] = { .clk_domain = APB1, .line_num = 6 }, - [RCC_TIMER13] = { .clk_domain = APB1, .line_num = 7 }, - [RCC_TIMER14] = { .clk_domain = APB1, .line_num = 8 }, -#endif -}; - -/** - * @brief Initialize the clock control system. Initializes the system - * clock source to use the PLL driven by an external oscillator - * @param sysclk_src system clock source, must be PLL - * @param pll_src pll clock source, must be HSE - * @param pll_mul pll multiplier - */ -void rcc_clk_init(rcc_sysclk_src sysclk_src, - rcc_pllsrc pll_src, - rcc_pll_multiplier pll_mul) { - uint32 cfgr = 0; - uint32 cr; - - /* Assume that we're going to clock the chip off the PLL, fed by - * the HSE */ - ASSERT(sysclk_src == RCC_CLKSRC_PLL && - pll_src == RCC_PLLSRC_HSE); - - RCC_BASE->CFGR = pll_src | pll_mul; - - /* Turn on the HSE */ - cr = RCC_BASE->CR; - cr |= RCC_CR_HSEON; - RCC_BASE->CR = cr; - while (!(RCC_BASE->CR & RCC_CR_HSERDY)) - ; - - /* Now the PLL */ - cr |= RCC_CR_PLLON; - RCC_BASE->CR = cr; - while (!(RCC_BASE->CR & RCC_CR_PLLRDY)) - ; - - /* Finally, let's switch over to the PLL */ - cfgr &= ~RCC_CFGR_SW; - cfgr |= RCC_CFGR_SW_PLL; - RCC_BASE->CFGR = cfgr; - while ((RCC_BASE->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL) - ; -} - -/** - * @brief Turn on the clock line on a peripheral - * @param id Clock ID of the peripheral to turn on. - */ -void rcc_clk_enable(rcc_clk_id id) { - static const __io uint32* enable_regs[] = { - [APB1] = &RCC_BASE->APB1ENR, - [APB2] = &RCC_BASE->APB2ENR, - [AHB] = &RCC_BASE->AHBENR, - }; - - rcc_clk_domain clk_domain = rcc_dev_clk(id); - __io uint32* enr = (__io uint32*)enable_regs[clk_domain]; - uint8 lnum = rcc_dev_table[id].line_num; - - bb_peri_set_bit(enr, lnum, 1); -} - -/** - * @brief Reset a peripheral. - * @param id Clock ID of the peripheral to reset. - */ -void rcc_reset_dev(rcc_clk_id id) { - static const __io uint32* reset_regs[] = { - [APB1] = &RCC_BASE->APB1RSTR, - [APB2] = &RCC_BASE->APB2RSTR, - }; - - rcc_clk_domain clk_domain = rcc_dev_clk(id); - __io void* addr = (__io void*)reset_regs[clk_domain]; - uint8 lnum = rcc_dev_table[id].line_num; - - bb_peri_set_bit(addr, lnum, 1); - bb_peri_set_bit(addr, lnum, 0); -} - -/** - * @brief Get a peripheral's clock domain - * @param id Clock ID of the peripheral whose clock domain to return - * @return Clock source for the given clock ID - */ -rcc_clk_domain rcc_dev_clk(rcc_clk_id id) { - return rcc_dev_table[id].clk_domain; -} - -/** - * @brief Set the divider on a peripheral prescaler - * @param prescaler prescaler to set - * @param divider prescaler divider - */ -void rcc_set_prescaler(rcc_prescaler prescaler, uint32 divider) { - static const uint32 masks[] = { - [RCC_PRESCALER_AHB] = RCC_CFGR_HPRE, - [RCC_PRESCALER_APB1] = RCC_CFGR_PPRE1, - [RCC_PRESCALER_APB2] = RCC_CFGR_PPRE2, - [RCC_PRESCALER_USB] = RCC_CFGR_USBPRE, - [RCC_PRESCALER_ADC] = RCC_CFGR_ADCPRE, - }; - - uint32 cfgr = RCC_BASE->CFGR; - cfgr &= ~masks[prescaler]; - cfgr |= divider; - RCC_BASE->CFGR = cfgr; -} diff --git a/libmaple/rules.mk b/libmaple/rules.mk index cdc0614..cf95b48 100644 --- a/libmaple/rules.mk +++ b/libmaple/rules.mk @@ -4,7 +4,7 @@ dirstack_$(sp) := $(d) d := $(dir) BUILDDIRS += $(BUILD_PATH)/$(d) -LIBMAPLE_INCLUDES := -I$(LIBMAPLE_PATH)/include +LIBMAPLE_INCLUDES := -I$(LIBMAPLE_PATH)/include -I$(LIBMAPLE_MODULE_FAMILY)/include # Local flags CFLAGS_$(d) = -I$(d) $(LIBMAPLE_INCLUDES) -Wall -Werror @@ -22,7 +22,6 @@ cSRCS_$(d) := adc.c \ nvic.c \ pwr.c \ i2c.c \ - rcc.c \ spi.c \ syscalls.c \ systick.c \ diff --git a/libmaple/stm32f1/include/family/rcc.h b/libmaple/stm32f1/include/family/rcc.h new file mode 100644 index 0000000..261dc5d --- /dev/null +++ b/libmaple/stm32f1/include/family/rcc.h @@ -0,0 +1,553 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Perry Hung. + * Copyright (c) 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/rcc.h + * @brief STM32F1 reset and clock control (RCC) header. + */ + +#ifndef _LIBMAPLE_STM32F1_RCC_H_ +#define _LIBMAPLE_STM32F1_RCC_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +/* + * Register map + */ + +/** RCC register map type */ +typedef struct rcc_reg_map { + __io uint32 CR; /**< Clock control register */ + __io uint32 CFGR; /**< Clock configuration register */ + __io uint32 CIR; /**< Clock interrupt register */ + __io uint32 APB2RSTR; /**< APB2 peripheral reset register */ + __io uint32 APB1RSTR; /**< APB1 peripheral reset register */ + __io uint32 AHBENR; /**< AHB peripheral clock enable register */ + __io uint32 APB2ENR; /**< APB2 peripheral clock enable register */ + __io uint32 APB1ENR; /**< APB1 peripheral clock enable register */ + __io uint32 BDCR; /**< Backup domain control register */ + __io uint32 CSR; /**< Control/status register */ +} rcc_reg_map; + +/** RCC register map base pointer */ +#define RCC_BASE ((struct rcc_reg_map*)0x40021000) + +/* + * Register bit definitions + */ + +/* Clock control register */ + +#define RCC_CR_PLLRDY_BIT 25 +#define RCC_CR_PLLON_BIT 24 +#define RCC_CR_CSSON_BIT 19 +#define RCC_CR_HSEBYP_BIT 18 +#define RCC_CR_HSERDY_BIT 17 +#define RCC_CR_HSEON_BIT 16 +#define RCC_CR_HSIRDY_BIT 1 +#define RCC_CR_HSION_BIT 0 + +#define RCC_CR_PLLRDY BIT(RCC_CR_PLLRDY_BIT) +#define RCC_CR_PLLON BIT(RCC_CR_PLLON_BIT) +#define RCC_CR_CSSON BIT(RCC_CR_CSSON_BIT) +#define RCC_CR_HSEBYP BIT(RCC_CR_HSEBYP_BIT) +#define RCC_CR_HSERDY BIT(RCC_CR_HSERDY_BIT) +#define RCC_CR_HSEON BIT(RCC_CR_HSEON_BIT) +#define RCC_CR_HSICAL (0xFF << 8) +#define RCC_CR_HSITRIM (0x1F << 3) +#define RCC_CR_HSIRDY BIT(RCC_CR_HSIRDY_BIT) +#define RCC_CR_HSION BIT(RCC_CR_HSION_BIT) + +/* Clock configuration register */ + +#define RCC_CFGR_USBPRE_BIT 22 +#define RCC_CFGR_PLLXTPRE_BIT 17 +#define RCC_CFGR_PLLSRC_BIT 16 + +#define RCC_CFGR_MCO (0x3 << 24) +#define RCC_CFGR_USBPRE BIT(RCC_CFGR_USBPRE_BIT) +#define RCC_CFGR_PLLMUL (0xF << 18) +#define RCC_CFGR_PLLXTPRE BIT(RCC_CFGR_PLLXTPRE_BIT) +#define RCC_CFGR_PLLSRC BIT(RCC_CFGR_PLLSRC_BIT) +#define RCC_CFGR_ADCPRE (0x3 << 14) +#define RCC_CFGR_PPRE2 (0x7 << 11) +#define RCC_CFGR_PPRE1 (0x7 << 8) +#define RCC_CFGR_HPRE (0xF << 4) +#define RCC_CFGR_SWS (0x3 << 2) +#define RCC_CFGR_SWS_PLL (0x2 << 2) +#define RCC_CFGR_SWS_HSE (0x1 << 2) +#define RCC_CFGR_SW 0x3 +#define RCC_CFGR_SW_PLL 0x2 +#define RCC_CFGR_SW_HSE 0x1 + +/* Clock interrupt register */ + +#define RCC_CIR_CSSC_BIT 23 +#define RCC_CIR_PLLRDYC_BIT 20 +#define RCC_CIR_HSERDYC_BIT 19 +#define RCC_CIR_HSIRDYC_BIT 18 +#define RCC_CIR_LSERDYC_BIT 17 +#define RCC_CIR_LSIRDYC_BIT 16 +#define RCC_CIR_PLLRDYIE_BIT 12 +#define RCC_CIR_HSERDYIE_BIT 11 +#define RCC_CIR_HSIRDYIE_BIT 10 +#define RCC_CIR_LSERDYIE_BIT 9 +#define RCC_CIR_LSIRDYIE_BIT 8 +#define RCC_CIR_CSSF_BIT 7 +#define RCC_CIR_PLLRDYF_BIT 4 +#define RCC_CIR_HSERDYF_BIT 3 +#define RCC_CIR_HSIRDYF_BIT 2 +#define RCC_CIR_LSERDYF_BIT 1 +#define RCC_CIR_LSIRDYF_BIT 0 + +#define RCC_CIR_CSSC BIT(RCC_CIR_CSSC_BIT) +#define RCC_CIR_PLLRDYC BIT(RCC_CIR_PLLRDYC_BIT) +#define RCC_CIR_HSERDYC BIT(RCC_CIR_HSERDYC_BIT) +#define RCC_CIR_HSIRDYC BIT(RCC_CIR_HSIRDYC_BIT) +#define RCC_CIR_LSERDYC BIT(RCC_CIR_LSERDYC_BIT) +#define RCC_CIR_LSIRDYC BIT(RCC_CIR_LSIRDYC_BIT) +#define RCC_CIR_PLLRDYIE BIT(RCC_CIR_PLLRDYIE_BIT) +#define RCC_CIR_HSERDYIE BIT(RCC_CIR_HSERDYIE_BIT) +#define RCC_CIR_HSIRDYIE BIT(RCC_CIR_HSIRDYIE_BIT) +#define RCC_CIR_LSERDYIE BIT(RCC_CIR_LSERDYIE_BIT) +#define RCC_CIR_LSIRDYIE BIT(RCC_CIR_LSIRDYIE_BIT) +#define RCC_CIR_CSSF BIT(RCC_CIR_CSSF_BIT) +#define RCC_CIR_PLLRDYF BIT(RCC_CIR_PLLRDYF_BIT) +#define RCC_CIR_HSERDYF BIT(RCC_CIR_HSERDYF_BIT) +#define RCC_CIR_HSIRDYF BIT(RCC_CIR_HSIRDYF_BIT) +#define RCC_CIR_LSERDYF BIT(RCC_CIR_LSERDYF_BIT) +#define RCC_CIR_LSIRDYF BIT(RCC_CIR_LSIRDYF_BIT) + +/* APB2 peripheral reset register */ + +#define RCC_APB2RSTR_TIM11RST_BIT 21 +#define RCC_APB2RSTR_TIM10RST_BIT 20 +#define RCC_APB2RSTR_TIM9RST_BIT 19 +#define RCC_APB2RSTR_ADC3RST_BIT 15 +#define RCC_APB2RSTR_USART1RST_BIT 14 +#define RCC_APB2RSTR_TIM8RST_BIT 13 +#define RCC_APB2RSTR_SPI1RST_BIT 12 +#define RCC_APB2RSTR_TIM1RST_BIT 11 +#define RCC_APB2RSTR_ADC2RST_BIT 10 +#define RCC_APB2RSTR_ADC1RST_BIT 9 +#define RCC_APB2RSTR_IOPGRST_BIT 8 +#define RCC_APB2RSTR_IOPFRST_BIT 7 +#define RCC_APB2RSTR_IOPERST_BIT 6 +#define RCC_APB2RSTR_IOPDRST_BIT 5 +#define RCC_APB2RSTR_IOPCRST_BIT 4 +#define RCC_APB2RSTR_IOPBRST_BIT 3 +#define RCC_APB2RSTR_IOPARST_BIT 2 +#define RCC_APB2RSTR_AFIORST_BIT 0 + +#define RCC_APB2RSTR_TIM11RST BIT(RCC_APB2RSTR_TIM11RST_BIT) +#define RCC_APB2RSTR_TIM10RST BIT(RCC_APB2RSTR_TIM10RST_BIT) +#define RCC_APB2RSTR_TIM9RST BIT(RCC_APB2RSTR_TIM9RST_BIT) +#define RCC_APB2RSTR_ADC3RST BIT(RCC_APB2RSTR_ADC3RST_BIT) +#define RCC_APB2RSTR_USART1RST BIT(RCC_APB2RSTR_USART1RST_BIT) +#define RCC_APB2RSTR_TIM8RST BIT(RCC_APB2RSTR_TIM8RST_BIT) +#define RCC_APB2RSTR_SPI1RST BIT(RCC_APB2RSTR_SPI1RST_BIT) +#define RCC_APB2RSTR_TIM1RST BIT(RCC_APB2RSTR_TIM1RST_BIT) +#define RCC_APB2RSTR_ADC2RST BIT(RCC_APB2RSTR_ADC2RST_BIT) +#define RCC_APB2RSTR_ADC1RST BIT(RCC_APB2RSTR_ADC1RST_BIT) +#define RCC_APB2RSTR_IOPGRST BIT(RCC_APB2RSTR_IOPGRST_BIT) +#define RCC_APB2RSTR_IOPFRST BIT(RCC_APB2RSTR_IOPFRST_BIT) +#define RCC_APB2RSTR_IOPERST BIT(RCC_APB2RSTR_IOPERST_BIT) +#define RCC_APB2RSTR_IOPDRST BIT(RCC_APB2RSTR_IOPDRST_BIT) +#define RCC_APB2RSTR_IOPCRST BIT(RCC_APB2RSTR_IOPCRST_BIT) +#define RCC_APB2RSTR_IOPBRST BIT(RCC_APB2RSTR_IOPBRST_BIT) +#define RCC_APB2RSTR_IOPARST BIT(RCC_APB2RSTR_IOPARST_BIT) +#define RCC_APB2RSTR_AFIORST BIT(RCC_APB2RSTR_AFIORST_BIT) + +/* APB1 peripheral reset register */ + +#define RCC_APB1RSTR_DACRST_BIT 29 +#define RCC_APB1RSTR_PWRRST_BIT 28 +#define RCC_APB1RSTR_BKPRST_BIT 27 +#define RCC_APB1RSTR_CANRST_BIT 25 +#define RCC_APB1RSTR_USBRST_BIT 23 +#define RCC_APB1RSTR_I2C2RST_BIT 22 +#define RCC_APB1RSTR_I2C1RST_BIT 21 +#define RCC_APB1RSTR_UART5RST_BIT 20 +#define RCC_APB1RSTR_UART4RST_BIT 19 +#define RCC_APB1RSTR_USART3RST_BIT 18 +#define RCC_APB1RSTR_USART2RST_BIT 17 +#define RCC_APB1RSTR_SPI3RST_BIT 15 +#define RCC_APB1RSTR_SPI2RST_BIT 14 +#define RCC_APB1RSTR_WWDRST_BIT 11 +#define RCC_APB1RSTR_TIM14RST_BIT 8 +#define RCC_APB1RSTR_TIM13RST_BIT 7 +#define RCC_APB1RSTR_TIM12RST_BIT 6 +#define RCC_APB1RSTR_TIM7RST_BIT 5 +#define RCC_APB1RSTR_TIM6RST_BIT 4 +#define RCC_APB1RSTR_TIM5RST_BIT 3 +#define RCC_APB1RSTR_TIM4RST_BIT 2 +#define RCC_APB1RSTR_TIM3RST_BIT 1 +#define RCC_APB1RSTR_TIM2RST_BIT 0 + +#define RCC_APB1RSTR_DACRST BIT(RCC_APB1RSTR_DACRST_BIT) +#define RCC_APB1RSTR_PWRRST BIT(RCC_APB1RSTR_PWRRST_BIT) +#define RCC_APB1RSTR_BKPRST BIT(RCC_APB1RSTR_BKPRST_BIT) +#define RCC_APB1RSTR_CANRST BIT(RCC_APB1RSTR_CANRST_BIT) +#define RCC_APB1RSTR_USBRST BIT(RCC_APB1RSTR_USBRST_BIT) +#define RCC_APB1RSTR_I2C2RST BIT(RCC_APB1RSTR_I2C2RST_BIT) +#define RCC_APB1RSTR_I2C1RST BIT(RCC_APB1RSTR_I2C1RST_BIT) +#define RCC_APB1RSTR_UART5RST BIT(RCC_APB1RSTR_UART5RST_BIT) +#define RCC_APB1RSTR_UART4RST BIT(RCC_APB1RSTR_UART4RST_BIT) +#define RCC_APB1RSTR_USART3RST BIT(RCC_APB1RSTR_USART3RST_BIT) +#define RCC_APB1RSTR_USART2RST BIT(RCC_APB1RSTR_USART2RST_BIT) +#define RCC_APB1RSTR_SPI3RST BIT(RCC_APB1RSTR_SPI3RST_BIT) +#define RCC_APB1RSTR_SPI2RST BIT(RCC_APB1RSTR_SPI2RST_BIT) +#define RCC_APB1RSTR_WWDRST BIT(RCC_APB1RSTR_WWDRST_BIT) +#define RCC_APB1RSTR_TIM14RST BIT(RCC_APB1RSTR_TIM14RST_BIT) +#define RCC_APB1RSTR_TIM13RST BIT(RCC_APB1RSTR_TIM13RST_BIT) +#define RCC_APB1RSTR_TIM12RST BIT(RCC_APB1RSTR_TIM12RST_BIT) +#define RCC_APB1RSTR_TIM7RST BIT(RCC_APB1RSTR_TIM7RST_BIT) +#define RCC_APB1RSTR_TIM6RST BIT(RCC_APB1RSTR_TIM6RST_BIT) +#define RCC_APB1RSTR_TIM5RST BIT(RCC_APB1RSTR_TIM5RST_BIT) +#define RCC_APB1RSTR_TIM4RST BIT(RCC_APB1RSTR_TIM4RST_BIT) +#define RCC_APB1RSTR_TIM3RST BIT(RCC_APB1RSTR_TIM3RST_BIT) +#define RCC_APB1RSTR_TIM2RST BIT(RCC_APB1RSTR_TIM2RST_BIT) + +/* AHB peripheral clock enable register */ + +#define RCC_AHBENR_SDIOEN_BIT 10 +#define RCC_AHBENR_FSMCEN_BIT 8 +#define RCC_AHBENR_CRCEN_BIT 7 +#define RCC_AHBENR_FLITFEN_BIT 4 +#define RCC_AHBENR_SRAMEN_BIT 2 +#define RCC_AHBENR_DMA2EN_BIT 1 +#define RCC_AHBENR_DMA1EN_BIT 0 + +#define RCC_AHBENR_SDIOEN BIT(RCC_AHBENR_SDIOEN_BIT) +#define RCC_AHBENR_FSMCEN BIT(RCC_AHBENR_FSMCEN_BIT) +#define RCC_AHBENR_CRCEN BIT(RCC_AHBENR_CRCEN_BIT) +#define RCC_AHBENR_FLITFEN BIT(RCC_AHBENR_FLITFEN_BIT) +#define RCC_AHBENR_SRAMEN BIT(RCC_AHBENR_SRAMEN_BIT) +#define RCC_AHBENR_DMA2EN BIT(RCC_AHBENR_DMA2EN_BIT) +#define RCC_AHBENR_DMA1EN BIT(RCC_AHBENR_DMA1EN_BIT) + +/* APB2 peripheral clock enable register */ + +#define RCC_APB2ENR_TIM11EN_BIT 21 +#define RCC_APB2ENR_TIM10EN_BIT 20 +#define RCC_APB2ENR_TIM9EN_BIT 19 +#define RCC_APB2ENR_ADC3EN_BIT 15 +#define RCC_APB2ENR_USART1EN_BIT 14 +#define RCC_APB2ENR_TIM8EN_BIT 13 +#define RCC_APB2ENR_SPI1EN_BIT 12 +#define RCC_APB2ENR_TIM1EN_BIT 11 +#define RCC_APB2ENR_ADC2EN_BIT 10 +#define RCC_APB2ENR_ADC1EN_BIT 9 +#define RCC_APB2ENR_IOPGEN_BIT 8 +#define RCC_APB2ENR_IOPFEN_BIT 7 +#define RCC_APB2ENR_IOPEEN_BIT 6 +#define RCC_APB2ENR_IOPDEN_BIT 5 +#define RCC_APB2ENR_IOPCEN_BIT 4 +#define RCC_APB2ENR_IOPBEN_BIT 3 +#define RCC_APB2ENR_IOPAEN_BIT 2 +#define RCC_APB2ENR_AFIOEN_BIT 0 + +#define RCC_APB2ENR_TIM11EN BIT(RCC_APB2ENR_TIM11EN_BIT) +#define RCC_APB2ENR_TIM10EN BIT(RCC_APB2ENR_TIM10EN_BIT) +#define RCC_APB2ENR_TIM9EN BIT(RCC_APB2ENR_TIM9EN_BIT) +#define RCC_APB2ENR_ADC3EN BIT(RCC_APB2ENR_ADC3EN_BIT) +#define RCC_APB2ENR_USART1EN BIT(RCC_APB2ENR_USART1EN_BIT) +#define RCC_APB2ENR_TIM8EN BIT(RCC_APB2ENR_TIM8EN_BIT) +#define RCC_APB2ENR_SPI1EN BIT(RCC_APB2ENR_SPI1EN_BIT) +#define RCC_APB2ENR_TIM1EN BIT(RCC_APB2ENR_TIM1EN_BIT) +#define RCC_APB2ENR_ADC2EN BIT(RCC_APB2ENR_ADC2EN_BIT) +#define RCC_APB2ENR_ADC1EN BIT(RCC_APB2ENR_ADC1EN_BIT) +#define RCC_APB2ENR_IOPGEN BIT(RCC_APB2ENR_IOPGEN_BIT) +#define RCC_APB2ENR_IOPFEN BIT(RCC_APB2ENR_IOPFEN_BIT) +#define RCC_APB2ENR_IOPEEN BIT(RCC_APB2ENR_IOPEEN_BIT) +#define RCC_APB2ENR_IOPDEN BIT(RCC_APB2ENR_IOPDEN_BIT) +#define RCC_APB2ENR_IOPCEN BIT(RCC_APB2ENR_IOPCEN_BIT) +#define RCC_APB2ENR_IOPBEN BIT(RCC_APB2ENR_IOPBEN_BIT) +#define RCC_APB2ENR_IOPAEN BIT(RCC_APB2ENR_IOPAEN_BIT) +#define RCC_APB2ENR_AFIOEN BIT(RCC_APB2ENR_AFIOEN_BIT) + +/* APB1 peripheral clock enable register */ + +#define RCC_APB1ENR_DACEN_BIT 29 +#define RCC_APB1ENR_PWREN_BIT 28 +#define RCC_APB1ENR_BKPEN_BIT 27 +#define RCC_APB1ENR_CANEN_BIT 25 +#define RCC_APB1ENR_USBEN_BIT 23 +#define RCC_APB1ENR_I2C2EN_BIT 22 +#define RCC_APB1ENR_I2C1EN_BIT 21 +#define RCC_APB1ENR_UART5EN_BIT 20 +#define RCC_APB1ENR_UART4EN_BIT 19 +#define RCC_APB1ENR_USART3EN_BIT 18 +#define RCC_APB1ENR_USART2EN_BIT 17 +#define RCC_APB1ENR_SPI3EN_BIT 15 +#define RCC_APB1ENR_SPI2EN_BIT 14 +#define RCC_APB1ENR_WWDEN_BIT 11 +#define RCC_APB1ENR_TIM14EN_BIT 8 +#define RCC_APB1ENR_TIM13EN_BIT 7 +#define RCC_APB1ENR_TIM12EN_BIT 6 +#define RCC_APB1ENR_TIM7EN_BIT 5 +#define RCC_APB1ENR_TIM6EN_BIT 4 +#define RCC_APB1ENR_TIM5EN_BIT 3 +#define RCC_APB1ENR_TIM4EN_BIT 2 +#define RCC_APB1ENR_TIM3EN_BIT 1 +#define RCC_APB1ENR_TIM2EN_BIT 0 + +#define RCC_APB1ENR_DACEN BIT(RCC_APB1ENR_DACEN_BIT) +#define RCC_APB1ENR_PWREN BIT(RCC_APB1ENR_PWREN_BIT) +#define RCC_APB1ENR_BKPEN BIT(RCC_APB1ENR_BKPEN_BIT) +#define RCC_APB1ENR_CANEN BIT(RCC_APB1ENR_CANEN_BIT) +#define RCC_APB1ENR_USBEN BIT(RCC_APB1ENR_USBEN_BIT) +#define RCC_APB1ENR_I2C2EN BIT(RCC_APB1ENR_I2C2EN_BIT) +#define RCC_APB1ENR_I2C1EN BIT(RCC_APB1ENR_I2C1EN_BIT) +#define RCC_APB1ENR_UART5EN BIT(RCC_APB1ENR_UART5EN_BIT) +#define RCC_APB1ENR_UART4EN BIT(RCC_APB1ENR_UART4EN_BIT) +#define RCC_APB1ENR_USART3EN BIT(RCC_APB1ENR_USART3EN_BIT) +#define RCC_APB1ENR_USART2EN BIT(RCC_APB1ENR_USART2EN_BIT) +#define RCC_APB1ENR_SPI3EN BIT(RCC_APB1ENR_SPI3EN_BIT) +#define RCC_APB1ENR_SPI2EN BIT(RCC_APB1ENR_SPI2EN_BIT) +#define RCC_APB1ENR_WWDEN BIT(RCC_APB1ENR_WWDEN_BIT) +#define RCC_APB1ENR_TIM14EN BIT(RCC_APB1ENR_TIM14EN_BIT) +#define RCC_APB1ENR_TIM13EN BIT(RCC_APB1ENR_TIM13EN_BIT) +#define RCC_APB1ENR_TIM12EN BIT(RCC_APB1ENR_TIM12EN_BIT) +#define RCC_APB1ENR_TIM7EN BIT(RCC_APB1ENR_TIM7EN_BIT) +#define RCC_APB1ENR_TIM6EN BIT(RCC_APB1ENR_TIM6EN_BIT) +#define RCC_APB1ENR_TIM5EN BIT(RCC_APB1ENR_TIM5EN_BIT) +#define RCC_APB1ENR_TIM4EN BIT(RCC_APB1ENR_TIM4EN_BIT) +#define RCC_APB1ENR_TIM3EN BIT(RCC_APB1ENR_TIM3EN_BIT) +#define RCC_APB1ENR_TIM2EN BIT(RCC_APB1ENR_TIM2EN_BIT) + +/* Backup domain control register */ + +#define RCC_BDCR_BDRST_BIT 16 +#define RCC_BDCR_RTCEN_BIT 15 +#define RCC_BDCR_LSEBYP_BIT 2 +#define RCC_BDCR_LSERDY_BIT 1 +#define RCC_BDCR_LSEON_BIT 0 + +#define RCC_BDCR_BDRST BIT(RCC_BDCR_BDRST_BIT) +#define RCC_BDCR_RTCEN BIT(RCC_BDCR_RTC_BIT) +#define RCC_BDCR_RTCSEL (0x3 << 8) +#define RCC_BDCR_RTCSEL_NONE (0x0 << 8) +#define RCC_BDCR_RTCSEL_LSE (0x1 << 8) +#define RCC_BDCR_RTCSEL_HSE (0x3 << 8) +#define RCC_BDCR_LSEBYP BIT(RCC_BDCR_LSEBYP_BIT) +#define RCC_BDCR_LSERDY BIT(RCC_BDCR_LSERDY_BIT) +#define RCC_BDCR_LSEON BIT(RCC_BDCR_LSEON_BIT) + +/* Control/status register */ + +#define RCC_CSR_LPWRRSTF_BIT 31 +#define RCC_CSR_WWDGRSTF_BIT 30 +#define RCC_CSR_IWDGRSTF_BIT 29 +#define RCC_CSR_SFTRSTF_BIT 28 +#define RCC_CSR_PORRSTF_BIT 27 +#define RCC_CSR_PINRSTF_BIT 26 +#define RCC_CSR_RMVF_BIT 24 +#define RCC_CSR_LSIRDY_BIT 1 +#define RCC_CSR_LSION_BIT 0 + +#define RCC_CSR_LPWRRSTF BIT(RCC_CSR_LPWRRSTF_BIT) +#define RCC_CSR_WWDGRSTF BIT(RCC_CSR_WWDGRSTF_BIT) +#define RCC_CSR_IWDGRSTF BIT(RCC_CSR_IWDGRSTF_BIT) +#define RCC_CSR_SFTRSTF BIT(RCC_CSR_SFTRSTF_BIT) +#define RCC_CSR_PORRSTF BIT(RCC_CSR_PORRSTF_BIT) +#define RCC_CSR_PINRSTF BIT(RCC_CSR_PINRSTF_BIT) +#define RCC_CSR_RMVF BIT(RCC_CSR_RMVF_BIT) +#define RCC_CSR_LSIRDY BIT(RCC_CSR_LSIRDY_BIT) +#define RCC_CSR_LSION BIT(RCC_CSR_LSION_BIT) + +/* + * Other types + */ + +/** + * @brief Identifies bus and clock line for a peripheral. + * + * Also generally useful as a unique identifier for that peripheral + * (or its corresponding device struct). + */ +typedef enum rcc_clk_id { + RCC_GPIOA, + RCC_GPIOB, + RCC_GPIOC, + RCC_GPIOD, + RCC_AFIO, + RCC_ADC1, + RCC_ADC2, + RCC_ADC3, + RCC_USART1, + RCC_USART2, + RCC_USART3, + RCC_TIMER1, + RCC_TIMER2, + RCC_TIMER3, + RCC_TIMER4, + RCC_SPI1, + RCC_SPI2, + RCC_DMA1, + RCC_PWR, + RCC_BKP, + RCC_I2C1, + RCC_I2C2, + RCC_CRC, + RCC_FLITF, + RCC_SRAM, + RCC_USB, +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) + RCC_GPIOE, + RCC_GPIOF, + RCC_GPIOG, + RCC_UART4, + RCC_UART5, + RCC_TIMER5, + RCC_TIMER6, + RCC_TIMER7, + RCC_TIMER8, + RCC_FSMC, + RCC_DAC, + RCC_DMA2, + RCC_SDIO, + RCC_SPI3, +#endif +#ifdef STM32_XL_DENSITY + RCC_TIMER9, + RCC_TIMER10, + RCC_TIMER11, + RCC_TIMER12, + RCC_TIMER13, + RCC_TIMER14, +#endif +} rcc_clk_id; + +/** + * PLL multipliers + * @see rcc_clk_init() + */ +typedef enum rcc_pll_multiplier { + RCC_PLLMUL_2 = (0x0 << 18), + RCC_PLLMUL_3 = (0x1 << 18), + RCC_PLLMUL_4 = (0x2 << 18), + RCC_PLLMUL_5 = (0x3 << 18), + RCC_PLLMUL_6 = (0x4 << 18), + RCC_PLLMUL_7 = (0x5 << 18), + RCC_PLLMUL_8 = (0x6 << 18), + RCC_PLLMUL_9 = (0x7 << 18), + RCC_PLLMUL_10 = (0x8 << 18), + RCC_PLLMUL_11 = (0x9 << 18), + RCC_PLLMUL_12 = (0xA << 18), + RCC_PLLMUL_13 = (0xB << 18), + RCC_PLLMUL_14 = (0xC << 18), + RCC_PLLMUL_15 = (0xD << 18), + RCC_PLLMUL_16 = (0xE << 18), +} rcc_pll_multiplier; + +/** + * PLL entry clock source + * @see rcc_clk_init() + */ +typedef enum rcc_pllsrc { + RCC_PLLSRC_HSE = (0x1 << 16), + RCC_PLLSRC_HSI_DIV_2 = (0x0 << 16) +} rcc_pllsrc; + +typedef enum rcc_clk_domain { + RCC_APB1, + RCC_APB2, + RCC_AHB +} rcc_clk_domain; + +/** + * Prescaler identifiers + * @see rcc_set_prescaler() + */ +typedef enum rcc_prescaler { + RCC_PRESCALER_AHB, + RCC_PRESCALER_APB1, + RCC_PRESCALER_APB2, + RCC_PRESCALER_USB, + RCC_PRESCALER_ADC +} rcc_prescaler; + +/** + * ADC prescaler dividers + * @see rcc_set_prescaler() + */ +typedef enum rcc_adc_divider { + RCC_ADCPRE_PCLK_DIV_2 = 0x0 << 14, + RCC_ADCPRE_PCLK_DIV_4 = 0x1 << 14, + RCC_ADCPRE_PCLK_DIV_6 = 0x2 << 14, + RCC_ADCPRE_PCLK_DIV_8 = 0x3 << 14, +} rcc_adc_divider; + +/** + * APB1 prescaler dividers + * @see rcc_set_prescaler() + */ +typedef enum rcc_apb1_divider { + RCC_APB1_HCLK_DIV_1 = 0x0 << 8, + RCC_APB1_HCLK_DIV_2 = 0x4 << 8, + RCC_APB1_HCLK_DIV_4 = 0x5 << 8, + RCC_APB1_HCLK_DIV_8 = 0x6 << 8, + RCC_APB1_HCLK_DIV_16 = 0x7 << 8, +} rcc_apb1_divider; + +/** + * APB2 prescaler dividers + * @see rcc_set_prescaler() + */ +typedef enum rcc_apb2_divider { + RCC_APB2_HCLK_DIV_1 = 0x0 << 11, + RCC_APB2_HCLK_DIV_2 = 0x4 << 11, + RCC_APB2_HCLK_DIV_4 = 0x5 << 11, + RCC_APB2_HCLK_DIV_8 = 0x6 << 11, + RCC_APB2_HCLK_DIV_16 = 0x7 << 11, +} rcc_apb2_divider; + +/** + * AHB prescaler dividers + * @see rcc_set_prescaler() + */ +typedef enum rcc_ahb_divider { + RCC_AHB_SYSCLK_DIV_1 = 0x0 << 4, + RCC_AHB_SYSCLK_DIV_2 = 0x8 << 4, + RCC_AHB_SYSCLK_DIV_4 = 0x9 << 4, + RCC_AHB_SYSCLK_DIV_8 = 0xA << 4, + RCC_AHB_SYSCLK_DIV_16 = 0xB << 4, + RCC_AHB_SYSCLK_DIV_32 = 0xC << 4, + RCC_AHB_SYSCLK_DIV_64 = 0xD << 4, + RCC_AHB_SYSCLK_DIV_128 = 0xD << 4, + RCC_AHB_SYSCLK_DIV_256 = 0xE << 4, + RCC_AHB_SYSCLK_DIV_512 = 0xF << 4, +} rcc_ahb_divider; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libmaple/stm32f1/rcc.c b/libmaple/stm32f1/rcc.c new file mode 100644 index 0000000..c40d52f --- /dev/null +++ b/libmaple/stm32f1/rcc.c @@ -0,0 +1,205 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Perry Hung. + * Copyright (c) 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/rcc.c + * @brief STM32F1 RCC routines. + */ + +#include +#include +#include + +struct rcc_dev_info { + const rcc_clk_domain clk_domain; + const uint8 line_num; +}; + +#define APB1 RCC_APB1 +#define APB2 RCC_APB2 +#define AHB RCC_AHB + +/* Device descriptor table, maps rcc_clk_id onto bus and enable/reset + * register bit numbers. */ +static const struct rcc_dev_info rcc_dev_table[] = { + [RCC_GPIOA] = { .clk_domain = APB2, .line_num = 2 }, + [RCC_GPIOB] = { .clk_domain = APB2, .line_num = 3 }, + [RCC_GPIOC] = { .clk_domain = APB2, .line_num = 4 }, + [RCC_GPIOD] = { .clk_domain = APB2, .line_num = 5 }, + [RCC_AFIO] = { .clk_domain = APB2, .line_num = 0 }, + [RCC_ADC1] = { .clk_domain = APB2, .line_num = 9 }, + [RCC_ADC2] = { .clk_domain = APB2, .line_num = 10 }, + [RCC_ADC3] = { .clk_domain = APB2, .line_num = 15 }, + [RCC_USART1] = { .clk_domain = APB2, .line_num = 14 }, + [RCC_USART2] = { .clk_domain = APB1, .line_num = 17 }, + [RCC_USART3] = { .clk_domain = APB1, .line_num = 18 }, + [RCC_TIMER1] = { .clk_domain = APB2, .line_num = 11 }, + [RCC_TIMER2] = { .clk_domain = APB1, .line_num = 0 }, + [RCC_TIMER3] = { .clk_domain = APB1, .line_num = 1 }, + [RCC_TIMER4] = { .clk_domain = APB1, .line_num = 2 }, + [RCC_SPI1] = { .clk_domain = APB2, .line_num = 12 }, + [RCC_SPI2] = { .clk_domain = APB1, .line_num = 14 }, + [RCC_DMA1] = { .clk_domain = AHB, .line_num = 0 }, + [RCC_PWR] = { .clk_domain = APB1, .line_num = 28}, + [RCC_BKP] = { .clk_domain = APB1, .line_num = 27}, + [RCC_I2C1] = { .clk_domain = APB1, .line_num = 21 }, + [RCC_I2C2] = { .clk_domain = APB1, .line_num = 22 }, + [RCC_CRC] = { .clk_domain = AHB, .line_num = 6}, + [RCC_FLITF] = { .clk_domain = AHB, .line_num = 4}, + [RCC_SRAM] = { .clk_domain = AHB, .line_num = 2}, + [RCC_USB] = { .clk_domain = APB1, .line_num = 23}, +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) + [RCC_GPIOE] = { .clk_domain = APB2, .line_num = 6 }, + [RCC_GPIOF] = { .clk_domain = APB2, .line_num = 7 }, + [RCC_GPIOG] = { .clk_domain = APB2, .line_num = 8 }, + [RCC_UART4] = { .clk_domain = APB1, .line_num = 19 }, + [RCC_UART5] = { .clk_domain = APB1, .line_num = 20 }, + [RCC_TIMER5] = { .clk_domain = APB1, .line_num = 3 }, + [RCC_TIMER6] = { .clk_domain = APB1, .line_num = 4 }, + [RCC_TIMER7] = { .clk_domain = APB1, .line_num = 5 }, + [RCC_TIMER8] = { .clk_domain = APB2, .line_num = 13 }, + [RCC_FSMC] = { .clk_domain = AHB, .line_num = 8 }, + [RCC_DAC] = { .clk_domain = APB1, .line_num = 29 }, + [RCC_DMA2] = { .clk_domain = AHB, .line_num = 1 }, + [RCC_SDIO] = { .clk_domain = AHB, .line_num = 10 }, + [RCC_SPI3] = { .clk_domain = APB1, .line_num = 15 }, +#endif +#ifdef STM32_XL_DENSITY + [RCC_TIMER9] = { .clk_domain = APB2, .line_num = 19 }, + [RCC_TIMER10] = { .clk_domain = APB2, .line_num = 20 }, + [RCC_TIMER11] = { .clk_domain = APB2, .line_num = 21 }, + [RCC_TIMER12] = { .clk_domain = APB1, .line_num = 6 }, + [RCC_TIMER13] = { .clk_domain = APB1, .line_num = 7 }, + [RCC_TIMER14] = { .clk_domain = APB1, .line_num = 8 }, +#endif +}; + +/** + * @brief Initialize the clock control system. Initializes the system + * clock source to use the PLL driven by an external oscillator + * @param sysclk_src system clock source, must be PLL + * @param pll_src pll clock source, must be HSE + * @param pll_mul pll multiplier + */ +void rcc_clk_init(rcc_sysclk_src sysclk_src, + rcc_pllsrc pll_src, + rcc_pll_multiplier pll_mul) { + uint32 cfgr = 0; + uint32 cr; + + /* Assume that we're going to clock the chip off the PLL, fed by + * the HSE */ + ASSERT(sysclk_src == RCC_CLKSRC_PLL && + pll_src == RCC_PLLSRC_HSE); + + RCC_BASE->CFGR = pll_src | pll_mul; + + /* Turn on the HSE */ + cr = RCC_BASE->CR; + cr |= RCC_CR_HSEON; + RCC_BASE->CR = cr; + while (!(RCC_BASE->CR & RCC_CR_HSERDY)) + ; + + /* Now the PLL */ + cr |= RCC_CR_PLLON; + RCC_BASE->CR = cr; + while (!(RCC_BASE->CR & RCC_CR_PLLRDY)) + ; + + /* Finally, let's switch over to the PLL */ + cfgr &= ~RCC_CFGR_SW; + cfgr |= RCC_CFGR_SW_PLL; + RCC_BASE->CFGR = cfgr; + while ((RCC_BASE->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL) + ; +} + +/** + * @brief Turn on the clock line on a peripheral + * @param id Clock ID of the peripheral to turn on. + */ +void rcc_clk_enable(rcc_clk_id id) { + static const __io uint32* enable_regs[] = { + [APB1] = &RCC_BASE->APB1ENR, + [APB2] = &RCC_BASE->APB2ENR, + [AHB] = &RCC_BASE->AHBENR, + }; + + rcc_clk_domain clk_domain = rcc_dev_clk(id); + __io uint32* enr = (__io uint32*)enable_regs[clk_domain]; + uint8 lnum = rcc_dev_table[id].line_num; + + bb_peri_set_bit(enr, lnum, 1); +} + +/** + * @brief Reset a peripheral. + * @param id Clock ID of the peripheral to reset. + */ +void rcc_reset_dev(rcc_clk_id id) { + static const __io uint32* reset_regs[] = { + [APB1] = &RCC_BASE->APB1RSTR, + [APB2] = &RCC_BASE->APB2RSTR, + }; + + rcc_clk_domain clk_domain = rcc_dev_clk(id); + __io void* addr = (__io void*)reset_regs[clk_domain]; + uint8 lnum = rcc_dev_table[id].line_num; + + bb_peri_set_bit(addr, lnum, 1); + bb_peri_set_bit(addr, lnum, 0); +} + +/** + * @brief Get a peripheral's clock domain + * @param id Clock ID of the peripheral whose clock domain to return + * @return Clock source for the given clock ID + */ +rcc_clk_domain rcc_dev_clk(rcc_clk_id id) { + return rcc_dev_table[id].clk_domain; +} + +/** + * @brief Set the divider on a peripheral prescaler + * @param prescaler prescaler to set + * @param divider prescaler divider + */ +void rcc_set_prescaler(rcc_prescaler prescaler, uint32 divider) { + static const uint32 masks[] = { + [RCC_PRESCALER_AHB] = RCC_CFGR_HPRE, + [RCC_PRESCALER_APB1] = RCC_CFGR_PPRE1, + [RCC_PRESCALER_APB2] = RCC_CFGR_PPRE2, + [RCC_PRESCALER_USB] = RCC_CFGR_USBPRE, + [RCC_PRESCALER_ADC] = RCC_CFGR_ADCPRE, + }; + + uint32 cfgr = RCC_BASE->CFGR; + cfgr &= ~masks[prescaler]; + cfgr |= divider; + RCC_BASE->CFGR = cfgr; +} diff --git a/libmaple/stm32f1/rules.mk b/libmaple/stm32f1/rules.mk index 5cadefd..3c87920 100644 --- a/libmaple/stm32f1/rules.mk +++ b/libmaple/stm32f1/rules.mk @@ -4,16 +4,23 @@ dirstack_$(sp) := $(d) d := $(dir) BUILDDIRS += $(BUILD_PATH)/$(d) +# Local flags +CFLAGS_$(d) = -I$(d) $(LIBMAPLE_INCLUDES) -Wall -Werror + # Local rules and targets sSRCS_$(d) := isrs_performance.S \ vector_table_performance.S +cSRCS_$(d) := rcc.c sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%) +cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%) -OBJS_$(d) := $(sFILES_$(d):%.S=$(BUILD_PATH)/%.o) +OBJS_$(d) := $(sFILES_$(d):%.S=$(BUILD_PATH)/%.o) \ + $(cFILES_$(d):%.c=$(BUILD_PATH)/%.o) DEPS_$(d) := $(OBJS_$(d):%.o=%.d) $(OBJS_$(d)): TGT_ASFLAGS := +$(OBJS_$(d)): TGT_CFLAGS := $(CFLAGS_$(d)) TGT_BIN += $(OBJS_$(d)) -- cgit v1.2.3 From 748edc3887c714dcc92768556aac7ac563b6247e Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Thu, 17 Nov 2011 15:39:15 -0500 Subject: libmaple: Add build infrastructure for private headers. libmaple/rules.mk: Add LIBMAPLE_PRIVATE_INCLUDES, a place for storing headers which should be commonly available throughout libmaple, but not made public. Currently, this is just the libmaple directory. Add LIBMAPLE_PRIVATE_INCLUDES to the target flags in the STM32F1 and USB submodules. Signed-off-by: Marti Bolivar --- libmaple/rules.mk | 3 ++- libmaple/stm32f1/rules.mk | 2 +- libmaple/usb/rules.mk | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'libmaple/rules.mk') diff --git a/libmaple/rules.mk b/libmaple/rules.mk index cf95b48..cbff931 100644 --- a/libmaple/rules.mk +++ b/libmaple/rules.mk @@ -5,9 +5,10 @@ d := $(dir) BUILDDIRS += $(BUILD_PATH)/$(d) LIBMAPLE_INCLUDES := -I$(LIBMAPLE_PATH)/include -I$(LIBMAPLE_MODULE_FAMILY)/include +LIBMAPLE_PRIVATE_INCLUDES := -I$(LIBMAPLE_PATH) # Local flags -CFLAGS_$(d) = -I$(d) $(LIBMAPLE_INCLUDES) -Wall -Werror +CFLAGS_$(d) = $(LIBMAPLE_PRIVATE_INCLUDES) $(LIBMAPLE_INCLUDES) -Wall -Werror # Local rules and targets cSRCS_$(d) := adc.c \ diff --git a/libmaple/stm32f1/rules.mk b/libmaple/stm32f1/rules.mk index 03d2f95..5267e9b 100644 --- a/libmaple/stm32f1/rules.mk +++ b/libmaple/stm32f1/rules.mk @@ -5,7 +5,7 @@ d := $(dir) BUILDDIRS += $(BUILD_PATH)/$(d) # Local flags -CFLAGS_$(d) = -I$(d) $(LIBMAPLE_INCLUDES) -Wall -Werror +CFLAGS_$(d) = -I$(d) $(LIBMAPLE_PRIVATE_INCLUDES) $(LIBMAPLE_INCLUDES) -Wall -Werror # Local rules and targets sSRCS_$(d) := isrs_performance.S \ diff --git a/libmaple/usb/rules.mk b/libmaple/usb/rules.mk index 9ef8d70..816fad6 100644 --- a/libmaple/usb/rules.mk +++ b/libmaple/usb/rules.mk @@ -6,7 +6,7 @@ BUILDDIRS += $(BUILD_PATH)/$(d) BUILDDIRS += $(BUILD_PATH)/$(d)/usb_lib # Local flags -CFLAGS_$(d) = -I$(d) -I$(d)/usb_lib $(LIBMAPLE_INCLUDES) -Wall +CFLAGS_$(d) = -I$(d) -I$(d)/usb_lib $(LIBMAPLE_INCLUDES) $(LIBMAPLE_PRIVATE_INCLUDES) -Wall # Local rules and targets sSRCS_$(d) := -- cgit v1.2.3 From 5337e01c09e19573758efbc57a7f7e972d78ab3f Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Fri, 18 Nov 2011 17:24:14 -0500 Subject: RCC: Break out some portable functionality from stm32f1/. Portions of rcc_clk_enable(), rcc_reset_dev(), and rcc_set_prescaler() are portable; break these into static inline helpers in rcc_private.h. These guts of these are portable, but the arrays of registers etc. are not. Also add an extern declaration for rcc_dev_table into rcc_private.h. This lets us put rcc_dev_clk() into a newly resurrected libmaple/rcc.c, since that's portable. Signed-off-by: Marti Bolivar --- libmaple/rcc.c | 44 +++++++++++++++++++++++++++++++++ libmaple/rcc_private.h | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++ libmaple/rules.mk | 1 + libmaple/stm32f1/rcc.c | 41 ++++++------------------------ 4 files changed, 119 insertions(+), 34 deletions(-) create mode 100644 libmaple/rcc.c create mode 100644 libmaple/rcc_private.h (limited to 'libmaple/rules.mk') diff --git a/libmaple/rcc.c b/libmaple/rcc.c new file mode 100644 index 0000000..d6ed2d6 --- /dev/null +++ b/libmaple/rcc.c @@ -0,0 +1,44 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Perry Hung. + * Copyright (c) 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/rcc.c + * @brief Portable RCC routines. + */ + +#include + +#include "rcc_private.h" + +/** + * @brief Get a peripheral's clock domain + * @param id Clock ID of the peripheral whose clock domain to return + * @return Clock source for the given clock ID + */ +rcc_clk_domain rcc_dev_clk(rcc_clk_id id) { + return rcc_dev_table[id].clk_domain; +} diff --git a/libmaple/rcc_private.h b/libmaple/rcc_private.h new file mode 100644 index 0000000..66eaf00 --- /dev/null +++ b/libmaple/rcc_private.h @@ -0,0 +1,67 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/* + * RCC private header. + */ + +#ifndef _LIBMAPLE_PRIVATE_RCC_H_ +#define _LIBMAPLE_PRIVATE_RCC_H_ + +#include + +struct rcc_dev_info { + const rcc_clk_domain clk_domain; + const uint8 line_num; +}; + +extern const struct rcc_dev_info rcc_dev_table[]; + +static inline void rcc_do_clk_enable(__io uint32** enable_regs, + rcc_clk_id id) { + __io uint32 *enable_reg = enable_regs[rcc_dev_clk(id)]; + uint8 line_num = rcc_dev_table[id].line_num; + bb_peri_set_bit(enable_reg, line_num, 1); +} + +static inline void rcc_do_reset_dev(__io uint32** reset_regs, + rcc_clk_id id) { + __io uint32 *reset_reg = reset_regs[rcc_dev_clk(id)]; + uint8 line_num = rcc_dev_table[id].line_num; + bb_peri_set_bit(reset_reg, line_num, 1); + bb_peri_set_bit(reset_reg, line_num, 0); +} + +static inline void rcc_do_set_prescaler(const uint32 *masks, + rcc_prescaler prescaler, + uint32 divider) { + uint32 cfgr = RCC_BASE->CFGR; + cfgr &= ~masks[prescaler]; + cfgr |= divider; + RCC_BASE->CFGR = cfgr; +} + +#endif diff --git a/libmaple/rules.mk b/libmaple/rules.mk index cbff931..3ca5b3a 100644 --- a/libmaple/rules.mk +++ b/libmaple/rules.mk @@ -23,6 +23,7 @@ cSRCS_$(d) := adc.c \ nvic.c \ pwr.c \ i2c.c \ + rcc.c \ spi.c \ syscalls.c \ systick.c \ diff --git a/libmaple/stm32f1/rcc.c b/libmaple/stm32f1/rcc.c index c40d52f..c8d24c6 100644 --- a/libmaple/stm32f1/rcc.c +++ b/libmaple/stm32f1/rcc.c @@ -34,10 +34,7 @@ #include #include -struct rcc_dev_info { - const rcc_clk_domain clk_domain; - const uint8 line_num; -}; +#include "rcc_private.h" #define APB1 RCC_APB1 #define APB2 RCC_APB2 @@ -45,7 +42,7 @@ struct rcc_dev_info { /* Device descriptor table, maps rcc_clk_id onto bus and enable/reset * register bit numbers. */ -static const struct rcc_dev_info rcc_dev_table[] = { +const struct rcc_dev_info rcc_dev_table[] = { [RCC_GPIOA] = { .clk_domain = APB2, .line_num = 2 }, [RCC_GPIOB] = { .clk_domain = APB2, .line_num = 3 }, [RCC_GPIOC] = { .clk_domain = APB2, .line_num = 4 }, @@ -144,17 +141,12 @@ void rcc_clk_init(rcc_sysclk_src sysclk_src, * @param id Clock ID of the peripheral to turn on. */ void rcc_clk_enable(rcc_clk_id id) { - static const __io uint32* enable_regs[] = { + static __io uint32* enable_regs[] = { [APB1] = &RCC_BASE->APB1ENR, [APB2] = &RCC_BASE->APB2ENR, [AHB] = &RCC_BASE->AHBENR, }; - - rcc_clk_domain clk_domain = rcc_dev_clk(id); - __io uint32* enr = (__io uint32*)enable_regs[clk_domain]; - uint8 lnum = rcc_dev_table[id].line_num; - - bb_peri_set_bit(enr, lnum, 1); + rcc_do_clk_enable(enable_regs, id); } /** @@ -162,26 +154,11 @@ void rcc_clk_enable(rcc_clk_id id) { * @param id Clock ID of the peripheral to reset. */ void rcc_reset_dev(rcc_clk_id id) { - static const __io uint32* reset_regs[] = { + static __io uint32* reset_regs[] = { [APB1] = &RCC_BASE->APB1RSTR, [APB2] = &RCC_BASE->APB2RSTR, }; - - rcc_clk_domain clk_domain = rcc_dev_clk(id); - __io void* addr = (__io void*)reset_regs[clk_domain]; - uint8 lnum = rcc_dev_table[id].line_num; - - bb_peri_set_bit(addr, lnum, 1); - bb_peri_set_bit(addr, lnum, 0); -} - -/** - * @brief Get a peripheral's clock domain - * @param id Clock ID of the peripheral whose clock domain to return - * @return Clock source for the given clock ID - */ -rcc_clk_domain rcc_dev_clk(rcc_clk_id id) { - return rcc_dev_table[id].clk_domain; + rcc_do_reset_dev(reset_regs, id); } /** @@ -197,9 +174,5 @@ void rcc_set_prescaler(rcc_prescaler prescaler, uint32 divider) { [RCC_PRESCALER_USB] = RCC_CFGR_USBPRE, [RCC_PRESCALER_ADC] = RCC_CFGR_ADCPRE, }; - - uint32 cfgr = RCC_BASE->CFGR; - cfgr &= ~masks[prescaler]; - cfgr |= divider; - RCC_BASE->CFGR = cfgr; + rcc_do_set_prescaler(masks, prescaler, divider); } -- cgit v1.2.3 From c2a937bbb56294df10eec082ab23c353edf4629b Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Tue, 29 Nov 2011 02:06:33 -0500 Subject: Great renaming: use "series" instead of "family". This is for greater consistency with the ST application notes, which refer to migrating "across" series (e.g. F1 to F2), but compatibility "within" a family (e.g. F1). So: - Move libmaple/stm32x/include/family to .../include/series/ and fix up includes appropriately. - Refer to "family" headers as "series" headers in comments. - Make similar "find and replace"-style changes to build system variable names and comments. - Move support/ld/stm32/family to .../stm32/series. Signed-off-by: Marti Bolivar --- Makefile | 4 +- libmaple/include/libmaple/flash.h | 4 +- libmaple/include/libmaple/gpio.h | 6 +- libmaple/include/libmaple/nvic.h | 10 +- libmaple/include/libmaple/rcc.h | 6 +- libmaple/include/libmaple/stm32.h | 6 +- libmaple/rules.mk | 2 +- libmaple/stm32f1/include/family/flash.h | 142 ------ libmaple/stm32f1/include/family/gpio.h | 479 ------------------ libmaple/stm32f1/include/family/nvic.h | 139 ------ libmaple/stm32f1/include/family/rcc.h | 553 --------------------- libmaple/stm32f1/include/family/stm32.h | 100 ---- libmaple/stm32f1/include/series/flash.h | 142 ++++++ libmaple/stm32f1/include/series/gpio.h | 479 ++++++++++++++++++ libmaple/stm32f1/include/series/nvic.h | 139 ++++++ libmaple/stm32f1/include/series/rcc.h | 553 +++++++++++++++++++++ libmaple/stm32f1/include/series/stm32.h | 100 ++++ .../stm32/family/f1/performance/vector_symbols.inc | 78 --- .../stm32/series/f1/performance/vector_symbols.inc | 78 +++ support/make/target-config.mk | 6 +- 20 files changed, 1513 insertions(+), 1513 deletions(-) delete mode 100644 libmaple/stm32f1/include/family/flash.h delete mode 100644 libmaple/stm32f1/include/family/gpio.h delete mode 100644 libmaple/stm32f1/include/family/nvic.h delete mode 100644 libmaple/stm32f1/include/family/rcc.h delete mode 100644 libmaple/stm32f1/include/family/stm32.h create mode 100644 libmaple/stm32f1/include/series/flash.h create mode 100644 libmaple/stm32f1/include/series/gpio.h create mode 100644 libmaple/stm32f1/include/series/nvic.h create mode 100644 libmaple/stm32f1/include/series/rcc.h create mode 100644 libmaple/stm32f1/include/series/stm32.h delete mode 100644 support/ld/stm32/family/f1/performance/vector_symbols.inc create mode 100644 support/ld/stm32/series/f1/performance/vector_symbols.inc (limited to 'libmaple/rules.mk') diff --git a/Makefile b/Makefile index 2525c2e..1e00ed6 100644 --- a/Makefile +++ b/Makefile @@ -55,7 +55,7 @@ GLOBAL_CXXFLAGS := -fno-rtti -fno-exceptions -Wall $(TARGET_FLAGS) GLOBAL_ASFLAGS := -mcpu=cortex-m3 -march=armv7-m -mthumb \ -x assembler-with-cpp $(TARGET_FLAGS) LDFLAGS = -T$(LDDIR)/$(LDSCRIPT) -L$(LDDIR) \ - -mcpu=cortex-m3 -mthumb -Xlinker -L $(LD_FAMILY_PATH) \ + -mcpu=cortex-m3 -mthumb -Xlinker -L $(LD_SERIES_PATH) \ --gc-sections --print-gc-sections --march=armv7-m -Wall ## @@ -76,7 +76,7 @@ else LIBMAPLE_MODULES += $(SRCROOT)/libmaple endif LIBMAPLE_MODULES += $(SRCROOT)/libmaple/usb # USB FS device -LIBMAPLE_MODULES += $(LIBMAPLE_MODULE_FAMILY) # family submodule in libmaple +LIBMAPLE_MODULES += $(LIBMAPLE_MODULE_SERIES) # STM32 series submodule in libmaple LIBMAPLE_MODULES += $(SRCROOT)/wirish # Official libraries: LIBMAPLE_MODULES += $(SRCROOT)/libraries/Servo diff --git a/libmaple/include/libmaple/flash.h b/libmaple/include/libmaple/flash.h index 66d5b8e..97bfa26 100644 --- a/libmaple/include/libmaple/flash.h +++ b/libmaple/include/libmaple/flash.h @@ -47,10 +47,10 @@ extern "C"{ #define FLASH_WAIT_STATE_6 0x6 #define FLASH_WAIT_STATE_7 0x7 -/* The family header must define FLASH_SAFE_WAIT_STATES, the smallest +/* The series header must define FLASH_SAFE_WAIT_STATES, the smallest * number of wait states that it is safe to use when the MCU clock is * at its fastest rate (not considering overclocking). */ -#include +#include /* * Setup routines diff --git a/libmaple/include/libmaple/gpio.h b/libmaple/include/libmaple/gpio.h index e821ad4..609320f 100644 --- a/libmaple/include/libmaple/gpio.h +++ b/libmaple/include/libmaple/gpio.h @@ -37,11 +37,11 @@ extern "C"{ #endif /* - * Note: Family header must define: - * - struct gpio_dev (and declare extern pointers to family-provided ones) + * Note: Series header must define: + * - struct gpio_dev (and declare extern pointers to series-provided ones) * - enum gpio_pin_mode (TODO think hard on this) */ -#include +#include #include /* diff --git a/libmaple/include/libmaple/nvic.h b/libmaple/include/libmaple/nvic.h index 23425df..1a1a4ed 100644 --- a/libmaple/include/libmaple/nvic.h +++ b/libmaple/include/libmaple/nvic.h @@ -74,18 +74,18 @@ typedef struct nvic_reg_map { #define NVIC_BASE ((struct nvic_reg_map*)0xE000E100) /* - * Note: The family header must define enum nvic_irq_num, which gives + * Note: The series header must define enum nvic_irq_num, which gives * descriptive names to the interrupts and exceptions from NMI (-14) - * to the largest interrupt available in the family, where the value + * to the largest interrupt available in the series, where the value * for nonnegative enumerators corresponds to its position in the * vector table. * * It also must define a static inline nvic_irq_disable_all(), which - * writes 0xFFFFFFFF to all ICE registers available in the family. (We - * place the include here to give the family header access to + * writes 0xFFFFFFFF to all ICE registers available in the series. (We + * place the include here to give the series header access to * NVIC_BASE, in order to let it do so). */ -#include +#include void nvic_init(uint32 address, uint32 offset); void nvic_set_vector_table(uint32 address, uint32 offset); diff --git a/libmaple/include/libmaple/rcc.h b/libmaple/include/libmaple/rcc.h index a4b66e5..08f7c7e 100644 --- a/libmaple/include/libmaple/rcc.h +++ b/libmaple/include/libmaple/rcc.h @@ -37,9 +37,9 @@ extern "C"{ #endif #include -#include +#include -/* Note: Beyond the usual (registers, etc.), it's up to the family +/* Note: Beyond the usual (registers, etc.), it's up to the series * header to define the following types: * * - rcc_pllsrc: For each PLL source (passed to rcc_clk_init()). @@ -49,7 +49,7 @@ extern "C"{ * - rcc_clk_id: For each available peripheral. These are widely used * as unique IDs (TODO extricate from RCC?). Peripherals which are * common across families should use the same token for their - * rcc_clk_id in each family header. + * rcc_clk_id in each series header. * * - rcc_clk_domain: For each clock domain (returned by rcc_dev_clk()). * diff --git a/libmaple/include/libmaple/stm32.h b/libmaple/include/libmaple/stm32.h index 5efb670..356a360 100644 --- a/libmaple/include/libmaple/stm32.h +++ b/libmaple/include/libmaple/stm32.h @@ -37,8 +37,8 @@ extern "C" { #endif /* Everything enclosed in the following __DOXYGEN_PREDEFINED_HACK - * conditional block must be defined in the family header. */ -#include + * conditional block must be defined in the series header. */ +#include #ifdef __DOXYGEN_PREDEFINED_HACK @@ -66,7 +66,7 @@ extern "C" { #define PCLK2 /* - * Family- and MCU-specific values. + * Series- and MCU-specific values. */ /** diff --git a/libmaple/rules.mk b/libmaple/rules.mk index 3ca5b3a..f0776a7 100644 --- a/libmaple/rules.mk +++ b/libmaple/rules.mk @@ -4,7 +4,7 @@ dirstack_$(sp) := $(d) d := $(dir) BUILDDIRS += $(BUILD_PATH)/$(d) -LIBMAPLE_INCLUDES := -I$(LIBMAPLE_PATH)/include -I$(LIBMAPLE_MODULE_FAMILY)/include +LIBMAPLE_INCLUDES := -I$(LIBMAPLE_PATH)/include -I$(LIBMAPLE_MODULE_SERIES)/include LIBMAPLE_PRIVATE_INCLUDES := -I$(LIBMAPLE_PATH) # Local flags diff --git a/libmaple/stm32f1/include/family/flash.h b/libmaple/stm32f1/include/family/flash.h deleted file mode 100644 index 918a434..0000000 --- a/libmaple/stm32f1/include/family/flash.h +++ /dev/null @@ -1,142 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f1/flash.h - * @brief STM32F1 Flash header. - * - * Provides register map, base pointer, and register bit definitions - * for the Flash controller on the STM32F1 line, along with - * family-specific configuration values. - */ - -#ifndef _LIBMAPLE_STM32F1_FLASH_H_ -#define _LIBMAPLE_STM32F1_FLASH_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include - -/* - * Register map - */ - -/** Flash register map type */ -typedef struct flash_reg_map { - __io uint32 ACR; /**< Access control register */ - __io uint32 KEYR; /**< Key register */ - __io uint32 OPTKEYR; /**< OPTKEY register */ - __io uint32 SR; /**< Status register */ - __io uint32 CR; /**< Control register */ - __io uint32 AR; /**< Address register */ - __io uint32 OBR; /**< Option byte register */ - __io uint32 WRPR; /**< Write protection register */ -} flash_reg_map; - -/** Flash register map base pointer */ -#define FLASH_BASE ((struct flash_reg_map*)0x40022000) - -/* - * Register bit definitions - */ - -/* Access control register */ - -#define FLASH_ACR_PRFTBS_BIT 5 -#define FLASH_ACR_PRFTBE_BIT 4 -#define FLASH_ACR_HLFCYA_BIT 3 - -#define FLASH_ACR_PRFTBS BIT(FLASH_ACR_PRFTBS_BIT) -#define FLASH_ACR_PRFTBE BIT(FLASH_ACR_PRFTBE_BIT) -#define FLASH_ACR_HLFCYA BIT(FLASH_ACR_HLFCYA_BIT) -#define FLASH_ACR_LATENCY 0x7 - -/* Status register */ - -#define FLASH_SR_EOP_BIT 5 -#define FLASH_SR_WRPRTERR_BIT 4 -#define FLASH_SR_PGERR_BIT 2 -#define FLASH_SR_BSY_BIT 0 - -#define FLASH_SR_EOP BIT(FLASH_SR_EOP_BIT) -#define FLASH_SR_WRPRTERR BIT(FLASH_SR_WRPRTERR_BIT) -#define FLASH_SR_PGERR BIT(FLASH_SR_PGERR_BIT) -#define FLASH_SR_BSY BIT(FLASH_SR_BSY_BIT) - -/* Control register */ - -#define FLASH_CR_EOPIE_BIT 12 -#define FLASH_CR_ERRIE_BIT 10 -#define FLASH_CR_OPTWRE_BIT 9 -#define FLASH_CR_LOCK_BIT 7 -#define FLASH_CR_STRT_BIT 6 -#define FLASH_CR_OPTER_BIT 5 -#define FLASH_CR_OPTPG_BIT 4 -#define FLASH_CR_MER_BIT 2 -#define FLASH_CR_PER_BIT 1 -#define FLASH_CR_PG_BIT 0 - -#define FLASH_CR_EOPIE BIT(FLASH_CR_EOPIE_BIT) -#define FLASH_CR_ERRIE BIT(FLASH_CR_ERRIE_BIT) -#define FLASH_CR_OPTWRE BIT(FLASH_CR_OPTWRE_BIT) -#define FLASH_CR_LOCK BIT(FLASH_CR_LOCK_BIT) -#define FLASH_CR_STRT BIT(FLASH_CR_STRT_BIT) -#define FLASH_CR_OPTER BIT(FLASH_CR_OPTER_BIT) -#define FLASH_CR_OPTPG BIT(FLASH_CR_OPTPG_BIT) -#define FLASH_CR_MER BIT(FLASH_CR_MER_BIT) -#define FLASH_CR_PER BIT(FLASH_CR_PER_BIT) -#define FLASH_CR_PG BIT(FLASH_CR_PG_BIT) - -/* Option byte register */ - -#define FLASH_OBR_nRST_STDBY_BIT 4 -#define FLASH_OBR_nRST_STOP_BIT 3 -#define FLASH_OBR_WDG_SW_BIT 2 -#define FLASH_OBR_RDPRT_BIT 1 -#define FLASH_OBR_OPTERR_BIT 0 - -#define FLASH_OBR_DATA1 (0xFF << 18) -#define FLASH_OBR_DATA0 (0xFF << 10) -#define FLASH_OBR_USER 0x3FF -#define FLASH_OBR_nRST_STDBY BIT(FLASH_OBR_nRST_STDBY_BIT) -#define FLASH_OBR_nRST_STOP BIT(FLASH_OBR_nRST_STOP_BIT) -#define FLASH_OBR_WDG_SW BIT(FLASH_OBR_WDG_SW_BIT) -#define FLASH_OBR_RDPRT BIT(FLASH_OBR_RDPRT_BIT) -#define FLASH_OBR_OPTERR BIT(FLASH_OBR_OPTERR_BIT) - -/* - * Family-specific configuration values. - */ - -#define FLASH_SAFE_WAIT_STATES FLASH_WAIT_STATE_2 - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/libmaple/stm32f1/include/family/gpio.h b/libmaple/stm32f1/include/family/gpio.h deleted file mode 100644 index c10244d..0000000 --- a/libmaple/stm32f1/include/family/gpio.h +++ /dev/null @@ -1,479 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2011 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. -*****************************************************************************/ - -/** - * @file libmaple/stm32f1/gpio.h - * @brief General purpose I/O (GPIO) and Alternate Function I/O - * (AFIO) prototypes, defines, and inlined access functions. - */ - -#ifndef _LIBMAPLE_STM32F1_GPIO_H_ -#define _LIBMAPLE_STM32F1_GPIO_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include -#include - -/* - * GPIO register maps and devices - */ - -/** GPIO register map type */ -typedef struct gpio_reg_map { - __io uint32 CRL; /**< Port configuration register low */ - __io uint32 CRH; /**< Port configuration register high */ - __io uint32 IDR; /**< Port input data register */ - __io uint32 ODR; /**< Port output data register */ - __io uint32 BSRR; /**< Port bit set/reset register */ - __io uint32 BRR; /**< Port bit reset register */ - __io uint32 LCKR; /**< Port configuration lock register */ -} gpio_reg_map; - -/** - * @brief External interrupt line port selector. - * - * Used to determine which GPIO port to map an external interrupt line - * onto. */ -/* (See AFIO sections, below) */ -typedef enum afio_exti_port { - AFIO_EXTI_PA, /**< Use port A (PAx) pin. */ - AFIO_EXTI_PB, /**< Use port B (PBx) pin. */ - AFIO_EXTI_PC, /**< Use port C (PCx) pin. */ - AFIO_EXTI_PD, /**< Use port D (PDx) pin. */ -#ifdef STM32_HIGH_DENSITY - AFIO_EXTI_PE, /**< Use port E (PEx) pin. */ - AFIO_EXTI_PF, /**< Use port F (PFx) pin. */ - AFIO_EXTI_PG, /**< Use port G (PGx) pin. */ -#endif -} afio_exti_port; - -/** GPIO device type */ -typedef struct gpio_dev { - gpio_reg_map *regs; /**< Register map */ - rcc_clk_id clk_id; /**< RCC clock information */ - afio_exti_port exti_port; /**< AFIO external interrupt port value */ -} gpio_dev; - -extern gpio_dev gpioa; -extern gpio_dev* const GPIOA; -extern gpio_dev gpiob; -extern gpio_dev* const GPIOB; -extern gpio_dev gpioc; -extern gpio_dev* const GPIOC; -extern gpio_dev gpiod; -extern gpio_dev* const GPIOD; -#ifdef STM32_HIGH_DENSITY -extern gpio_dev gpioe; -extern gpio_dev* const GPIOE; -extern gpio_dev gpiof; -extern gpio_dev* const GPIOF; -extern gpio_dev gpiog; -extern gpio_dev* const GPIOG; -#endif - -/** GPIO port A register map base pointer */ -#define GPIOA_BASE ((struct gpio_reg_map*)0x40010800) -/** GPIO port B register map base pointer */ -#define GPIOB_BASE ((struct gpio_reg_map*)0x40010C00) -/** GPIO port C register map base pointer */ -#define GPIOC_BASE ((struct gpio_reg_map*)0x40011000) -/** GPIO port D register map base pointer */ -#define GPIOD_BASE ((struct gpio_reg_map*)0x40011400) -#ifdef STM32_HIGH_DENSITY -/** GPIO port E register map base pointer */ -#define GPIOE_BASE ((struct gpio_reg_map*)0x40011800) -/** GPIO port F register map base pointer */ -#define GPIOF_BASE ((struct gpio_reg_map*)0x40011C00) -/** GPIO port G register map base pointer */ -#define GPIOG_BASE ((struct gpio_reg_map*)0x40012000) -#endif - -/* - * GPIO register bit definitions - */ - -/* Control registers, low and high */ - -#define GPIO_CR_CNF (0x3 << 2) -#define GPIO_CR_CNF_INPUT_ANALOG (0x0 << 2) -#define GPIO_CR_CNF_INPUT_FLOATING (0x1 << 2) -#define GPIO_CR_CNF_INPUT_PU_PD (0x2 << 2) -#define GPIO_CR_CNF_OUTPUT_PP (0x0 << 2) -#define GPIO_CR_CNF_OUTPUT_OD (0x1 << 2) -#define GPIO_CR_CNF_AF_OUTPUT_PP (0x2 << 2) -#define GPIO_CR_CNF_AF_OUTPUT_OD (0x3 << 2) -#define GPIO_CR_MODE 0x3 -#define GPIO_CR_MODE_INPUT 0x0 -#define GPIO_CR_MODE_OUTPUT_10MHZ 0x1 -#define GPIO_CR_MODE_OUTPUT_2MHZ 0x2 -#define GPIO_CR_MODE_OUTPUT_50MHZ 0x3 - -/** - * @brief GPIO Pin modes. - * - * These only allow for 50MHZ max output speeds; if you want slower, - * use direct register access. - */ -typedef enum gpio_pin_mode { - GPIO_OUTPUT_PP = (GPIO_CR_CNF_OUTPUT_PP | - GPIO_CR_MODE_OUTPUT_50MHZ), /**< Output push-pull. */ - GPIO_OUTPUT_OD = (GPIO_CR_CNF_OUTPUT_OD | - GPIO_CR_MODE_OUTPUT_50MHZ), /**< Output open-drain. */ - GPIO_AF_OUTPUT_PP = (GPIO_CR_CNF_AF_OUTPUT_PP | - GPIO_CR_MODE_OUTPUT_50MHZ), /**< Alternate function - output push-pull. */ - GPIO_AF_OUTPUT_OD = (GPIO_CR_CNF_AF_OUTPUT_OD | - GPIO_CR_MODE_OUTPUT_50MHZ), /**< Alternate function - output open drain. */ - GPIO_INPUT_ANALOG = (GPIO_CR_CNF_INPUT_ANALOG | - GPIO_CR_MODE_INPUT), /**< Analog input. */ - GPIO_INPUT_FLOATING = (GPIO_CR_CNF_INPUT_FLOATING | - GPIO_CR_MODE_INPUT), /**< Input floating. */ - GPIO_INPUT_PD = (GPIO_CR_CNF_INPUT_PU_PD | - GPIO_CR_MODE_INPUT), /**< Input pull-down. */ - GPIO_INPUT_PU /**< Input pull-up. */ - /* GPIO_INPUT_PU treated as a special case, for ODR twiddling */ -} gpio_pin_mode; - -/** - * @brief Get a GPIO port's corresponding afio_exti_port. - * @param dev GPIO device whose afio_exti_port to return. - */ -static inline afio_exti_port gpio_exti_port(gpio_dev *dev) { - return dev->exti_port; -} - -/* - * AFIO register map - */ - -/** AFIO register map */ -typedef struct afio_reg_map { - __io uint32 EVCR; /**< Event control register. */ - __io uint32 MAPR; /**< AF remap and debug I/O configuration - register. */ - __io uint32 EXTICR1; /**< External interrupt configuration - register 1. */ - __io uint32 EXTICR2; /**< External interrupt configuration - register 2. */ - __io uint32 EXTICR3; /**< External interrupt configuration - register 3. */ - __io uint32 EXTICR4; /**< External interrupt configuration - register 4. */ - __io uint32 MAPR2; /**< AF remap and debug I/O configuration - register 2. */ -} afio_reg_map; - -/** AFIO register map base pointer. */ -#define AFIO_BASE ((struct afio_reg_map *)0x40010000) - -/* - * AFIO register bit definitions - */ - -/* Event control register */ - -#define AFIO_EVCR_EVOE (0x1 << 7) -#define AFIO_EVCR_PORT_PA (0x0 << 4) -#define AFIO_EVCR_PORT_PB (0x1 << 4) -#define AFIO_EVCR_PORT_PC (0x2 << 4) -#define AFIO_EVCR_PORT_PD (0x3 << 4) -#define AFIO_EVCR_PORT_PE (0x4 << 4) -#define AFIO_EVCR_PIN_0 0x0 -#define AFIO_EVCR_PIN_1 0x1 -#define AFIO_EVCR_PIN_2 0x2 -#define AFIO_EVCR_PIN_3 0x3 -#define AFIO_EVCR_PIN_4 0x4 -#define AFIO_EVCR_PIN_5 0x5 -#define AFIO_EVCR_PIN_6 0x6 -#define AFIO_EVCR_PIN_7 0x7 -#define AFIO_EVCR_PIN_8 0x8 -#define AFIO_EVCR_PIN_9 0x9 -#define AFIO_EVCR_PIN_10 0xA -#define AFIO_EVCR_PIN_11 0xB -#define AFIO_EVCR_PIN_12 0xC -#define AFIO_EVCR_PIN_13 0xD -#define AFIO_EVCR_PIN_14 0xE -#define AFIO_EVCR_PIN_15 0xF - -/* AF remap and debug I/O configuration register */ - -#define AFIO_MAPR_SWJ_CFG (0x7 << 24) -#define AFIO_MAPR_SWJ_CFG_FULL_SWJ (0x0 << 24) -#define AFIO_MAPR_SWJ_CFG_FULL_SWJ_NO_NJRST (0x1 << 24) -#define AFIO_MAPR_SWJ_CFG_NO_JTAG_SW (0x2 << 24) -#define AFIO_MAPR_SWJ_CFG_NO_JTAG_NO_SW (0x4 << 24) -#define AFIO_MAPR_ADC2_ETRGREG_REMAP BIT(20) -#define AFIO_MAPR_ADC2_ETRGINJ_REMAP BIT(19) -#define AFIO_MAPR_ADC1_ETRGREG_REMAP BIT(18) -#define AFIO_MAPR_ADC1_ETRGINJ_REMAP BIT(17) -#define AFIO_MAPR_TIM5CH4_IREMAP BIT(16) -#define AFIO_MAPR_PD01_REMAP BIT(15) -#define AFIO_MAPR_CAN_REMAP (0x3 << 13) -#define AFIO_MAPR_CAN_REMAP_NONE (0x0 << 13) -#define AFIO_MAPR_CAN_REMAP_PB8_PB9 (0x2 << 13) -#define AFIO_MAPR_CAN_REMAP_PD0_PD1 (0x3 << 13) -#define AFIO_MAPR_TIM4_REMAP BIT(12) -#define AFIO_MAPR_TIM3_REMAP (0x3 << 10) -#define AFIO_MAPR_TIM3_REMAP_NONE (0x0 << 10) -#define AFIO_MAPR_TIM3_REMAP_PARTIAL (0x2 << 10) -#define AFIO_MAPR_TIM3_REMAP_FULL (0x3 << 10) -#define AFIO_MAPR_TIM2_REMAP (0x3 << 8) -#define AFIO_MAPR_TIM2_REMAP_NONE (0x0 << 8) -#define AFIO_MAPR_TIM2_REMAP_PA15_PB3_PA2_PA3 (0x1 << 8) -#define AFIO_MAPR_TIM2_REMAP_PA0_PA1_PB10_PB11 (0x2 << 8) -#define AFIO_MAPR_TIM2_REMAP_FULL (0x3 << 8) -#define AFIO_MAPR_TIM1_REMAP (0x3 << 6) -#define AFIO_MAPR_TIM1_REMAP_NONE (0x0 << 6) -#define AFIO_MAPR_TIM1_REMAP_PARTIAL (0x1 << 6) -#define AFIO_MAPR_TIM1_REMAP_FULL (0x3 << 6) -#define AFIO_MAPR_USART3_REMAP (0x3 << 4) -#define AFIO_MAPR_USART3_REMAP_NONE (0x0 << 4) -#define AFIO_MAPR_USART3_REMAP_PARTIAL (0x1 << 4) -#define AFIO_MAPR_USART3_REMAP_FULL (0x3 << 4) -#define AFIO_MAPR_USART2_REMAP BIT(3) -#define AFIO_MAPR_USART1_REMAP BIT(2) -#define AFIO_MAPR_I2C1_REMAP BIT(1) -#define AFIO_MAPR_SPI1_REMAP BIT(0) - -/* External interrupt configuration register 1 */ - -#define AFIO_EXTICR1_EXTI3 (0xF << 12) -#define AFIO_EXTICR1_EXTI3_PA (0x0 << 12) -#define AFIO_EXTICR1_EXTI3_PB (0x1 << 12) -#define AFIO_EXTICR1_EXTI3_PC (0x2 << 12) -#define AFIO_EXTICR1_EXTI3_PD (0x3 << 12) -#define AFIO_EXTICR1_EXTI3_PE (0x4 << 12) -#define AFIO_EXTICR1_EXTI3_PF (0x5 << 12) -#define AFIO_EXTICR1_EXTI3_PG (0x6 << 12) -#define AFIO_EXTICR1_EXTI2 (0xF << 8) -#define AFIO_EXTICR1_EXTI2_PA (0x0 << 8) -#define AFIO_EXTICR1_EXTI2_PB (0x1 << 8) -#define AFIO_EXTICR1_EXTI2_PC (0x2 << 8) -#define AFIO_EXTICR1_EXTI2_PD (0x3 << 8) -#define AFIO_EXTICR1_EXTI2_PE (0x4 << 8) -#define AFIO_EXTICR1_EXTI2_PF (0x5 << 8) -#define AFIO_EXTICR1_EXTI2_PG (0x6 << 8) -#define AFIO_EXTICR1_EXTI1 (0xF << 4) -#define AFIO_EXTICR1_EXTI1_PA (0x0 << 4) -#define AFIO_EXTICR1_EXTI1_PB (0x1 << 4) -#define AFIO_EXTICR1_EXTI1_PC (0x2 << 4) -#define AFIO_EXTICR1_EXTI1_PD (0x3 << 4) -#define AFIO_EXTICR1_EXTI1_PE (0x4 << 4) -#define AFIO_EXTICR1_EXTI1_PF (0x5 << 4) -#define AFIO_EXTICR1_EXTI1_PG (0x6 << 4) -#define AFIO_EXTICR1_EXTI0 0xF -#define AFIO_EXTICR1_EXTI0_PA 0x0 -#define AFIO_EXTICR1_EXTI0_PB 0x1 -#define AFIO_EXTICR1_EXTI0_PC 0x2 -#define AFIO_EXTICR1_EXTI0_PD 0x3 -#define AFIO_EXTICR1_EXTI0_PE 0x4 -#define AFIO_EXTICR1_EXTI0_PF 0x5 -#define AFIO_EXTICR1_EXTI0_PG 0x6 - -/* External interrupt configuration register 2 */ - -#define AFIO_EXTICR2_EXTI7 (0xF << 12) -#define AFIO_EXTICR2_EXTI7_PA (0x0 << 12) -#define AFIO_EXTICR2_EXTI7_PB (0x1 << 12) -#define AFIO_EXTICR2_EXTI7_PC (0x2 << 12) -#define AFIO_EXTICR2_EXTI7_PD (0x3 << 12) -#define AFIO_EXTICR2_EXTI7_PE (0x4 << 12) -#define AFIO_EXTICR2_EXTI7_PF (0x5 << 12) -#define AFIO_EXTICR2_EXTI7_PG (0x6 << 12) -#define AFIO_EXTICR2_EXTI6 (0xF << 8) -#define AFIO_EXTICR2_EXTI6_PA (0x0 << 8) -#define AFIO_EXTICR2_EXTI6_PB (0x1 << 8) -#define AFIO_EXTICR2_EXTI6_PC (0x2 << 8) -#define AFIO_EXTICR2_EXTI6_PD (0x3 << 8) -#define AFIO_EXTICR2_EXTI6_PE (0x4 << 8) -#define AFIO_EXTICR2_EXTI6_PF (0x5 << 8) -#define AFIO_EXTICR2_EXTI6_PG (0x6 << 8) -#define AFIO_EXTICR2_EXTI5 (0xF << 4) -#define AFIO_EXTICR2_EXTI5_PA (0x0 << 4) -#define AFIO_EXTICR2_EXTI5_PB (0x1 << 4) -#define AFIO_EXTICR2_EXTI5_PC (0x2 << 4) -#define AFIO_EXTICR2_EXTI5_PD (0x3 << 4) -#define AFIO_EXTICR2_EXTI5_PE (0x4 << 4) -#define AFIO_EXTICR2_EXTI5_PF (0x5 << 4) -#define AFIO_EXTICR2_EXTI5_PG (0x6 << 4) -#define AFIO_EXTICR2_EXTI4 0xF -#define AFIO_EXTICR2_EXTI4_PA 0x0 -#define AFIO_EXTICR2_EXTI4_PB 0x1 -#define AFIO_EXTICR2_EXTI4_PC 0x2 -#define AFIO_EXTICR2_EXTI4_PD 0x3 -#define AFIO_EXTICR2_EXTI4_PE 0x4 -#define AFIO_EXTICR2_EXTI4_PF 0x5 -#define AFIO_EXTICR2_EXTI4_PG 0x6 - -/* AF remap and debug I/O configuration register 2 */ - -#define AFIO_MAPR2_FSMC_NADV BIT(10) -#define AFIO_MAPR2_TIM14_REMAP BIT(9) -#define AFIO_MAPR2_TIM13_REMAP BIT(8) -#define AFIO_MAPR2_TIM11_REMAP BIT(7) -#define AFIO_MAPR2_TIM10_REMAP BIT(6) -#define AFIO_MAPR2_TIM9_REMAP BIT(5) - -/* - * AFIO convenience routines - */ - -void afio_init(void); - -/** - * External interrupt line numbers. - */ -typedef enum afio_exti_num { - AFIO_EXTI_0, /**< External interrupt line 0. */ - AFIO_EXTI_1, /**< External interrupt line 1. */ - AFIO_EXTI_2, /**< External interrupt line 2. */ - AFIO_EXTI_3, /**< External interrupt line 3. */ - AFIO_EXTI_4, /**< External interrupt line 4. */ - AFIO_EXTI_5, /**< External interrupt line 5. */ - AFIO_EXTI_6, /**< External interrupt line 6. */ - AFIO_EXTI_7, /**< External interrupt line 7. */ - AFIO_EXTI_8, /**< External interrupt line 8. */ - AFIO_EXTI_9, /**< External interrupt line 9. */ - AFIO_EXTI_10, /**< External interrupt line 10. */ - AFIO_EXTI_11, /**< External interrupt line 11. */ - AFIO_EXTI_12, /**< External interrupt line 12. */ - AFIO_EXTI_13, /**< External interrupt line 13. */ - AFIO_EXTI_14, /**< External interrupt line 14. */ - AFIO_EXTI_15, /**< External interrupt line 15. */ -} afio_exti_num; - -void afio_exti_select(afio_exti_num exti, afio_exti_port gpio_port); - -/* HACK: Use upper bit to denote MAPR2, Bit 31 is reserved and - * not used in either MAPR or MAPR2 */ -#define AFIO_REMAP_USE_MAPR2 (1 << 31) - -/** - * @brief Available peripheral remaps. - * @see afio_remap() - */ -typedef enum afio_remap_peripheral { - AFIO_REMAP_ADC2_ETRGREG = AFIO_MAPR_ADC2_ETRGREG_REMAP, /**< - ADC 2 external trigger regular conversion remapping */ - AFIO_REMAP_ADC2_ETRGINJ = AFIO_MAPR_ADC2_ETRGINJ_REMAP, /**< - ADC 2 external trigger injected conversion remapping */ - AFIO_REMAP_ADC1_ETRGREG = AFIO_MAPR_ADC1_ETRGREG_REMAP, /**< - ADC 1 external trigger regular conversion remapping */ - AFIO_REMAP_ADC1_ETRGINJ = AFIO_MAPR_ADC1_ETRGINJ_REMAP, /**< - ADC 1 external trigger injected conversion remapping */ - AFIO_REMAP_TIM5CH4_I = AFIO_MAPR_TIM5CH4_IREMAP, /**< - Timer 5 channel 4 internal remapping */ - AFIO_REMAP_PD01 = AFIO_MAPR_PD01_REMAP, /**< - Port D0/Port D1 mapping on OSC_IN/OSC_OUT */ - AFIO_REMAP_CAN_1 = AFIO_MAPR_CAN_REMAP_PB8_PB9, /**< - CAN alternate function remapping 1 (RX on PB8, TX on PB9) */ - AFIO_REMAP_CAN_2 = AFIO_MAPR_CAN_REMAP_PD0_PD1, /**< - CAN alternate function remapping 2 (RX on PD0, TX on PD1) */ - AFIO_REMAP_TIM4 = AFIO_MAPR_TIM4_REMAP, /**< - Timer 4 remapping */ - AFIO_REMAP_TIM3_PARTIAL = AFIO_MAPR_TIM3_REMAP_PARTIAL, /**< - Timer 3 partial remapping */ - AFIO_REMAP_TIM3_FULL = AFIO_MAPR_TIM3_REMAP_FULL, /**< - Timer 3 full remapping */ - AFIO_REMAP_TIM2_PARTIAL_1 = AFIO_MAPR_TIM2_REMAP_PA15_PB3_PA2_PA3, /**< - Timer 2 partial remapping 1 (CH1 and ETR on PA15, CH2 on PB3, CH3 - on PA2, CH4 on PA3) */ - AFIO_REMAP_TIM2_PARTIAL_2 = AFIO_MAPR_TIM2_REMAP_PA0_PA1_PB10_PB11, /**< - Timer 2 partial remapping 2 (CH1 and ETR on PA0, CH2 on PA1, CH3 - on PB10, CH4 on PB11) */ - AFIO_REMAP_TIM2_FULL = AFIO_MAPR_TIM2_REMAP_FULL, /**< - Timer 2 full remapping */ - AFIO_REMAP_USART2 = AFIO_MAPR_USART2_REMAP, /**< - USART 2 remapping */ - AFIO_REMAP_USART1 = AFIO_MAPR_USART1_REMAP, /**< - USART 1 remapping */ - AFIO_REMAP_I2C1 = AFIO_MAPR_I2C1_REMAP, /**< - I2C 1 remapping */ - AFIO_REMAP_SPI1 = AFIO_MAPR_SPI1_REMAP, /**< - SPI 1 remapping */ - AFIO_REMAP_FSMC_NADV = (AFIO_MAPR2_FSMC_NADV | - AFIO_REMAP_USE_MAPR2), /**< - NADV signal not connected */ - AFIO_REMAP_TIM14 = (AFIO_MAPR2_TIM14_REMAP | - AFIO_REMAP_USE_MAPR2), /**< - Timer 14 remapping */ - AFIO_REMAP_TIM13 = (AFIO_MAPR2_TIM13_REMAP | - AFIO_REMAP_USE_MAPR2), /**< - Timer 13 remapping */ - AFIO_REMAP_TIM11 = (AFIO_MAPR2_TIM11_REMAP | - AFIO_REMAP_USE_MAPR2), /**< - Timer 11 remapping */ - AFIO_REMAP_TIM10 = (AFIO_MAPR2_TIM10_REMAP | - AFIO_REMAP_USE_MAPR2), /**< - Timer 10 remapping */ - AFIO_REMAP_TIM9 = (AFIO_MAPR2_TIM9_REMAP | - AFIO_REMAP_USE_MAPR2) /**< - Timer 9 */ -} afio_remap_peripheral; - -void afio_remap(afio_remap_peripheral p); - -/** - * @brief Debug port configuration - * - * Used to configure the behavior of JTAG and Serial Wire (SW) debug - * ports and their associated GPIO pins. - * - * @see afio_cfg_debug_ports() - */ -typedef enum afio_debug_cfg { - AFIO_DEBUG_FULL_SWJ = AFIO_MAPR_SWJ_CFG_FULL_SWJ, /**< - Full Serial Wire and JTAG debug */ - AFIO_DEBUG_FULL_SWJ_NO_NJRST = AFIO_MAPR_SWJ_CFG_FULL_SWJ_NO_NJRST, /**< - Full Serial Wire and JTAG, but no NJTRST. */ - AFIO_DEBUG_SW_ONLY = AFIO_MAPR_SWJ_CFG_NO_JTAG_SW, /**< - Serial Wire debug only (JTAG-DP disabled, - SW-DP enabled) */ - AFIO_DEBUG_NONE = AFIO_MAPR_SWJ_CFG_NO_JTAG_NO_SW /**< - No debug; all JTAG and SW pins are free - for use as GPIOs. */ -} afio_debug_cfg; - -/** - * @brief Enable or disable the JTAG and SW debug ports. - * @param config Desired debug port configuration - * @see afio_debug_cfg - */ -static inline void afio_cfg_debug_ports(afio_debug_cfg config) { - __io uint32 *mapr = &AFIO_BASE->MAPR; - *mapr = (*mapr & ~AFIO_MAPR_SWJ_CFG) | config; -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/libmaple/stm32f1/include/family/nvic.h b/libmaple/stm32f1/include/family/nvic.h deleted file mode 100644 index 69fd945..0000000 --- a/libmaple/stm32f1/include/family/nvic.h +++ /dev/null @@ -1,139 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f1/nvic.h - * @brief STM32F1 Nested Vectored Interrupt Controller (NVIC) support. - */ - -#ifndef _LIBMAPLE_STM32F1_NVIC_H_ -#define _LIBMAPLE_STM32F1_NVIC_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include - -/** - * @brief Interrupt vector table interrupt numbers. - * @see - */ -typedef enum nvic_irq_num { - NVIC_NMI = -14, /**< Non-maskable interrupt */ - NVIC_HARDFAULT = -13, /**< Hard fault (all class of fault) */ - NVIC_MEM_MANAGE = -12, /**< Memory management */ - NVIC_BUS_FAULT = -11, /**< Bus fault: prefetch fault, memory - access fault. */ - NVIC_USAGE_FAULT = -10, /**< Usage fault: Undefined instruction or - illegal state. */ - NVIC_SVC = -5, /**< System service call via SWI insruction */ - NVIC_DEBUG_MON = -4, /**< Debug monitor */ - NVIC_PEND_SVC = -2, /**< Pendable request for system service */ - NVIC_SYSTICK = -1, /**< System tick timer */ - NVIC_WWDG = 0, /**< Window watchdog interrupt */ - NVIC_PVD = 1, /**< PVD through EXTI line detection */ - NVIC_TAMPER = 2, /**< Tamper */ - NVIC_RTC = 3, /**< Real-time clock */ - NVIC_FLASH = 4, /**< Flash */ - NVIC_RCC = 5, /**< Reset and clock control */ - NVIC_EXTI0 = 6, /**< EXTI line 0 */ - NVIC_EXTI1 = 7, /**< EXTI line 1 */ - NVIC_EXTI2 = 8, /**< EXTI line 2 */ - NVIC_EXTI3 = 9, /**< EXTI line 3 */ - NVIC_EXTI4 = 10, /**< EXTI line 4 */ - NVIC_DMA_CH1 = 11, /**< DMA1 channel 1 */ - NVIC_DMA_CH2 = 12, /**< DMA1 channel 2 */ - NVIC_DMA_CH3 = 13, /**< DMA1 channel 3 */ - NVIC_DMA_CH4 = 14, /**< DMA1 channel 4 */ - NVIC_DMA_CH5 = 15, /**< DMA1 channel 5 */ - NVIC_DMA_CH6 = 16, /**< DMA1 channel 6 */ - NVIC_DMA_CH7 = 17, /**< DMA1 channel 7 */ - NVIC_ADC_1_2 = 18, /**< ADC1 and ADC2 */ - NVIC_USB_HP_CAN_TX = 19, /**< USB high priority or CAN TX */ - NVIC_USB_LP_CAN_RX0 = 20, /**< USB low priority or CAN RX0 */ - NVIC_CAN_RX1 = 21, /**< CAN RX1 */ - NVIC_CAN_SCE = 22, /**< CAN SCE */ - NVIC_EXTI_9_5 = 23, /**< EXTI line [9:5] */ - NVIC_TIMER1_BRK = 24, /**< Timer 1 break */ - NVIC_TIMER1_UP = 25, /**< Timer 1 update */ - NVIC_TIMER1_TRG_COM = 26, /**< Timer 1 trigger and commutation */ - NVIC_TIMER1_CC = 27, /**< Timer 1 capture/compare */ - NVIC_TIMER2 = 28, /**< Timer 2 */ - NVIC_TIMER3 = 29, /**< Timer 3 */ - NVIC_TIMER4 = 30, /**< Timer 4 */ - NVIC_I2C1_EV = 31, /**< I2C1 event */ - NVIC_I2C1_ER = 32, /**< I2C1 error */ - NVIC_I2C2_EV = 33, /**< I2C2 event */ - NVIC_I2C2_ER = 34, /**< I2C2 error */ - NVIC_SPI1 = 35, /**< SPI1 */ - NVIC_SPI2 = 36, /**< SPI2 */ - NVIC_USART1 = 37, /**< USART1 */ - NVIC_USART2 = 38, /**< USART2 */ - NVIC_USART3 = 39, /**< USART3 */ - NVIC_EXTI_15_10 = 40, /**< EXTI line [15:10] */ - NVIC_RTCALARM = 41, /**< RTC alarm through EXTI line */ - NVIC_USBWAKEUP = 42, /**< USB wakeup from suspend through - EXTI line */ - NVIC_TIMER8_BRK = 43, /**< Timer 8 break */ - NVIC_TIMER8_UP = 44, /**< Timer 8 update */ - NVIC_TIMER8_TRG_COM = 45, /**< Timer 8 trigger and commutation */ - NVIC_TIMER8_CC = 46, /**< Timer 8 capture/compare */ -#ifdef STM32_HIGH_DENSITY - NVIC_ADC3 = 47, /**< ADC3 */ - NVIC_FSMC = 48, /**< FSMC */ - NVIC_SDIO = 49, /**< SDIO */ - NVIC_TIMER5 = 50, /**< Timer 5 */ - NVIC_SPI3 = 51, /**< SPI3 */ - NVIC_UART4 = 52, /**< UART4 */ - NVIC_UART5 = 53, /**< UART5 */ - NVIC_TIMER6 = 54, /**< Timer 6 */ - NVIC_TIMER7 = 55, /**< Timer 7 */ - NVIC_DMA2_CH1 = 56, /**< DMA2 channel 1 */ - NVIC_DMA2_CH2 = 57, /**< DMA2 channel 2 */ - NVIC_DMA2_CH3 = 58, /**< DMA2 channel 3 */ - NVIC_DMA2_CH_4_5 = 59, /**< DMA2 channels 4 and 5 */ -#endif -} nvic_irq_num; - -static inline void nvic_irq_disable_all(void) { - /* Note: This only works up to XL density. The fix for - * connectivity line is: - * - * NVIC_BASE->ICER[2] = 0xF; - * - * We don't support connectivity line devices (yet), so leave it - * alone for now. - */ - NVIC_BASE->ICER[0] = 0xFFFFFFFF; - NVIC_BASE->ICER[1] = 0xFFFFFFFF; -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/libmaple/stm32f1/include/family/rcc.h b/libmaple/stm32f1/include/family/rcc.h deleted file mode 100644 index 261dc5d..0000000 --- a/libmaple/stm32f1/include/family/rcc.h +++ /dev/null @@ -1,553 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2011 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f1/rcc.h - * @brief STM32F1 reset and clock control (RCC) header. - */ - -#ifndef _LIBMAPLE_STM32F1_RCC_H_ -#define _LIBMAPLE_STM32F1_RCC_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -/* - * Register map - */ - -/** RCC register map type */ -typedef struct rcc_reg_map { - __io uint32 CR; /**< Clock control register */ - __io uint32 CFGR; /**< Clock configuration register */ - __io uint32 CIR; /**< Clock interrupt register */ - __io uint32 APB2RSTR; /**< APB2 peripheral reset register */ - __io uint32 APB1RSTR; /**< APB1 peripheral reset register */ - __io uint32 AHBENR; /**< AHB peripheral clock enable register */ - __io uint32 APB2ENR; /**< APB2 peripheral clock enable register */ - __io uint32 APB1ENR; /**< APB1 peripheral clock enable register */ - __io uint32 BDCR; /**< Backup domain control register */ - __io uint32 CSR; /**< Control/status register */ -} rcc_reg_map; - -/** RCC register map base pointer */ -#define RCC_BASE ((struct rcc_reg_map*)0x40021000) - -/* - * Register bit definitions - */ - -/* Clock control register */ - -#define RCC_CR_PLLRDY_BIT 25 -#define RCC_CR_PLLON_BIT 24 -#define RCC_CR_CSSON_BIT 19 -#define RCC_CR_HSEBYP_BIT 18 -#define RCC_CR_HSERDY_BIT 17 -#define RCC_CR_HSEON_BIT 16 -#define RCC_CR_HSIRDY_BIT 1 -#define RCC_CR_HSION_BIT 0 - -#define RCC_CR_PLLRDY BIT(RCC_CR_PLLRDY_BIT) -#define RCC_CR_PLLON BIT(RCC_CR_PLLON_BIT) -#define RCC_CR_CSSON BIT(RCC_CR_CSSON_BIT) -#define RCC_CR_HSEBYP BIT(RCC_CR_HSEBYP_BIT) -#define RCC_CR_HSERDY BIT(RCC_CR_HSERDY_BIT) -#define RCC_CR_HSEON BIT(RCC_CR_HSEON_BIT) -#define RCC_CR_HSICAL (0xFF << 8) -#define RCC_CR_HSITRIM (0x1F << 3) -#define RCC_CR_HSIRDY BIT(RCC_CR_HSIRDY_BIT) -#define RCC_CR_HSION BIT(RCC_CR_HSION_BIT) - -/* Clock configuration register */ - -#define RCC_CFGR_USBPRE_BIT 22 -#define RCC_CFGR_PLLXTPRE_BIT 17 -#define RCC_CFGR_PLLSRC_BIT 16 - -#define RCC_CFGR_MCO (0x3 << 24) -#define RCC_CFGR_USBPRE BIT(RCC_CFGR_USBPRE_BIT) -#define RCC_CFGR_PLLMUL (0xF << 18) -#define RCC_CFGR_PLLXTPRE BIT(RCC_CFGR_PLLXTPRE_BIT) -#define RCC_CFGR_PLLSRC BIT(RCC_CFGR_PLLSRC_BIT) -#define RCC_CFGR_ADCPRE (0x3 << 14) -#define RCC_CFGR_PPRE2 (0x7 << 11) -#define RCC_CFGR_PPRE1 (0x7 << 8) -#define RCC_CFGR_HPRE (0xF << 4) -#define RCC_CFGR_SWS (0x3 << 2) -#define RCC_CFGR_SWS_PLL (0x2 << 2) -#define RCC_CFGR_SWS_HSE (0x1 << 2) -#define RCC_CFGR_SW 0x3 -#define RCC_CFGR_SW_PLL 0x2 -#define RCC_CFGR_SW_HSE 0x1 - -/* Clock interrupt register */ - -#define RCC_CIR_CSSC_BIT 23 -#define RCC_CIR_PLLRDYC_BIT 20 -#define RCC_CIR_HSERDYC_BIT 19 -#define RCC_CIR_HSIRDYC_BIT 18 -#define RCC_CIR_LSERDYC_BIT 17 -#define RCC_CIR_LSIRDYC_BIT 16 -#define RCC_CIR_PLLRDYIE_BIT 12 -#define RCC_CIR_HSERDYIE_BIT 11 -#define RCC_CIR_HSIRDYIE_BIT 10 -#define RCC_CIR_LSERDYIE_BIT 9 -#define RCC_CIR_LSIRDYIE_BIT 8 -#define RCC_CIR_CSSF_BIT 7 -#define RCC_CIR_PLLRDYF_BIT 4 -#define RCC_CIR_HSERDYF_BIT 3 -#define RCC_CIR_HSIRDYF_BIT 2 -#define RCC_CIR_LSERDYF_BIT 1 -#define RCC_CIR_LSIRDYF_BIT 0 - -#define RCC_CIR_CSSC BIT(RCC_CIR_CSSC_BIT) -#define RCC_CIR_PLLRDYC BIT(RCC_CIR_PLLRDYC_BIT) -#define RCC_CIR_HSERDYC BIT(RCC_CIR_HSERDYC_BIT) -#define RCC_CIR_HSIRDYC BIT(RCC_CIR_HSIRDYC_BIT) -#define RCC_CIR_LSERDYC BIT(RCC_CIR_LSERDYC_BIT) -#define RCC_CIR_LSIRDYC BIT(RCC_CIR_LSIRDYC_BIT) -#define RCC_CIR_PLLRDYIE BIT(RCC_CIR_PLLRDYIE_BIT) -#define RCC_CIR_HSERDYIE BIT(RCC_CIR_HSERDYIE_BIT) -#define RCC_CIR_HSIRDYIE BIT(RCC_CIR_HSIRDYIE_BIT) -#define RCC_CIR_LSERDYIE BIT(RCC_CIR_LSERDYIE_BIT) -#define RCC_CIR_LSIRDYIE BIT(RCC_CIR_LSIRDYIE_BIT) -#define RCC_CIR_CSSF BIT(RCC_CIR_CSSF_BIT) -#define RCC_CIR_PLLRDYF BIT(RCC_CIR_PLLRDYF_BIT) -#define RCC_CIR_HSERDYF BIT(RCC_CIR_HSERDYF_BIT) -#define RCC_CIR_HSIRDYF BIT(RCC_CIR_HSIRDYF_BIT) -#define RCC_CIR_LSERDYF BIT(RCC_CIR_LSERDYF_BIT) -#define RCC_CIR_LSIRDYF BIT(RCC_CIR_LSIRDYF_BIT) - -/* APB2 peripheral reset register */ - -#define RCC_APB2RSTR_TIM11RST_BIT 21 -#define RCC_APB2RSTR_TIM10RST_BIT 20 -#define RCC_APB2RSTR_TIM9RST_BIT 19 -#define RCC_APB2RSTR_ADC3RST_BIT 15 -#define RCC_APB2RSTR_USART1RST_BIT 14 -#define RCC_APB2RSTR_TIM8RST_BIT 13 -#define RCC_APB2RSTR_SPI1RST_BIT 12 -#define RCC_APB2RSTR_TIM1RST_BIT 11 -#define RCC_APB2RSTR_ADC2RST_BIT 10 -#define RCC_APB2RSTR_ADC1RST_BIT 9 -#define RCC_APB2RSTR_IOPGRST_BIT 8 -#define RCC_APB2RSTR_IOPFRST_BIT 7 -#define RCC_APB2RSTR_IOPERST_BIT 6 -#define RCC_APB2RSTR_IOPDRST_BIT 5 -#define RCC_APB2RSTR_IOPCRST_BIT 4 -#define RCC_APB2RSTR_IOPBRST_BIT 3 -#define RCC_APB2RSTR_IOPARST_BIT 2 -#define RCC_APB2RSTR_AFIORST_BIT 0 - -#define RCC_APB2RSTR_TIM11RST BIT(RCC_APB2RSTR_TIM11RST_BIT) -#define RCC_APB2RSTR_TIM10RST BIT(RCC_APB2RSTR_TIM10RST_BIT) -#define RCC_APB2RSTR_TIM9RST BIT(RCC_APB2RSTR_TIM9RST_BIT) -#define RCC_APB2RSTR_ADC3RST BIT(RCC_APB2RSTR_ADC3RST_BIT) -#define RCC_APB2RSTR_USART1RST BIT(RCC_APB2RSTR_USART1RST_BIT) -#define RCC_APB2RSTR_TIM8RST BIT(RCC_APB2RSTR_TIM8RST_BIT) -#define RCC_APB2RSTR_SPI1RST BIT(RCC_APB2RSTR_SPI1RST_BIT) -#define RCC_APB2RSTR_TIM1RST BIT(RCC_APB2RSTR_TIM1RST_BIT) -#define RCC_APB2RSTR_ADC2RST BIT(RCC_APB2RSTR_ADC2RST_BIT) -#define RCC_APB2RSTR_ADC1RST BIT(RCC_APB2RSTR_ADC1RST_BIT) -#define RCC_APB2RSTR_IOPGRST BIT(RCC_APB2RSTR_IOPGRST_BIT) -#define RCC_APB2RSTR_IOPFRST BIT(RCC_APB2RSTR_IOPFRST_BIT) -#define RCC_APB2RSTR_IOPERST BIT(RCC_APB2RSTR_IOPERST_BIT) -#define RCC_APB2RSTR_IOPDRST BIT(RCC_APB2RSTR_IOPDRST_BIT) -#define RCC_APB2RSTR_IOPCRST BIT(RCC_APB2RSTR_IOPCRST_BIT) -#define RCC_APB2RSTR_IOPBRST BIT(RCC_APB2RSTR_IOPBRST_BIT) -#define RCC_APB2RSTR_IOPARST BIT(RCC_APB2RSTR_IOPARST_BIT) -#define RCC_APB2RSTR_AFIORST BIT(RCC_APB2RSTR_AFIORST_BIT) - -/* APB1 peripheral reset register */ - -#define RCC_APB1RSTR_DACRST_BIT 29 -#define RCC_APB1RSTR_PWRRST_BIT 28 -#define RCC_APB1RSTR_BKPRST_BIT 27 -#define RCC_APB1RSTR_CANRST_BIT 25 -#define RCC_APB1RSTR_USBRST_BIT 23 -#define RCC_APB1RSTR_I2C2RST_BIT 22 -#define RCC_APB1RSTR_I2C1RST_BIT 21 -#define RCC_APB1RSTR_UART5RST_BIT 20 -#define RCC_APB1RSTR_UART4RST_BIT 19 -#define RCC_APB1RSTR_USART3RST_BIT 18 -#define RCC_APB1RSTR_USART2RST_BIT 17 -#define RCC_APB1RSTR_SPI3RST_BIT 15 -#define RCC_APB1RSTR_SPI2RST_BIT 14 -#define RCC_APB1RSTR_WWDRST_BIT 11 -#define RCC_APB1RSTR_TIM14RST_BIT 8 -#define RCC_APB1RSTR_TIM13RST_BIT 7 -#define RCC_APB1RSTR_TIM12RST_BIT 6 -#define RCC_APB1RSTR_TIM7RST_BIT 5 -#define RCC_APB1RSTR_TIM6RST_BIT 4 -#define RCC_APB1RSTR_TIM5RST_BIT 3 -#define RCC_APB1RSTR_TIM4RST_BIT 2 -#define RCC_APB1RSTR_TIM3RST_BIT 1 -#define RCC_APB1RSTR_TIM2RST_BIT 0 - -#define RCC_APB1RSTR_DACRST BIT(RCC_APB1RSTR_DACRST_BIT) -#define RCC_APB1RSTR_PWRRST BIT(RCC_APB1RSTR_PWRRST_BIT) -#define RCC_APB1RSTR_BKPRST BIT(RCC_APB1RSTR_BKPRST_BIT) -#define RCC_APB1RSTR_CANRST BIT(RCC_APB1RSTR_CANRST_BIT) -#define RCC_APB1RSTR_USBRST BIT(RCC_APB1RSTR_USBRST_BIT) -#define RCC_APB1RSTR_I2C2RST BIT(RCC_APB1RSTR_I2C2RST_BIT) -#define RCC_APB1RSTR_I2C1RST BIT(RCC_APB1RSTR_I2C1RST_BIT) -#define RCC_APB1RSTR_UART5RST BIT(RCC_APB1RSTR_UART5RST_BIT) -#define RCC_APB1RSTR_UART4RST BIT(RCC_APB1RSTR_UART4RST_BIT) -#define RCC_APB1RSTR_USART3RST BIT(RCC_APB1RSTR_USART3RST_BIT) -#define RCC_APB1RSTR_USART2RST BIT(RCC_APB1RSTR_USART2RST_BIT) -#define RCC_APB1RSTR_SPI3RST BIT(RCC_APB1RSTR_SPI3RST_BIT) -#define RCC_APB1RSTR_SPI2RST BIT(RCC_APB1RSTR_SPI2RST_BIT) -#define RCC_APB1RSTR_WWDRST BIT(RCC_APB1RSTR_WWDRST_BIT) -#define RCC_APB1RSTR_TIM14RST BIT(RCC_APB1RSTR_TIM14RST_BIT) -#define RCC_APB1RSTR_TIM13RST BIT(RCC_APB1RSTR_TIM13RST_BIT) -#define RCC_APB1RSTR_TIM12RST BIT(RCC_APB1RSTR_TIM12RST_BIT) -#define RCC_APB1RSTR_TIM7RST BIT(RCC_APB1RSTR_TIM7RST_BIT) -#define RCC_APB1RSTR_TIM6RST BIT(RCC_APB1RSTR_TIM6RST_BIT) -#define RCC_APB1RSTR_TIM5RST BIT(RCC_APB1RSTR_TIM5RST_BIT) -#define RCC_APB1RSTR_TIM4RST BIT(RCC_APB1RSTR_TIM4RST_BIT) -#define RCC_APB1RSTR_TIM3RST BIT(RCC_APB1RSTR_TIM3RST_BIT) -#define RCC_APB1RSTR_TIM2RST BIT(RCC_APB1RSTR_TIM2RST_BIT) - -/* AHB peripheral clock enable register */ - -#define RCC_AHBENR_SDIOEN_BIT 10 -#define RCC_AHBENR_FSMCEN_BIT 8 -#define RCC_AHBENR_CRCEN_BIT 7 -#define RCC_AHBENR_FLITFEN_BIT 4 -#define RCC_AHBENR_SRAMEN_BIT 2 -#define RCC_AHBENR_DMA2EN_BIT 1 -#define RCC_AHBENR_DMA1EN_BIT 0 - -#define RCC_AHBENR_SDIOEN BIT(RCC_AHBENR_SDIOEN_BIT) -#define RCC_AHBENR_FSMCEN BIT(RCC_AHBENR_FSMCEN_BIT) -#define RCC_AHBENR_CRCEN BIT(RCC_AHBENR_CRCEN_BIT) -#define RCC_AHBENR_FLITFEN BIT(RCC_AHBENR_FLITFEN_BIT) -#define RCC_AHBENR_SRAMEN BIT(RCC_AHBENR_SRAMEN_BIT) -#define RCC_AHBENR_DMA2EN BIT(RCC_AHBENR_DMA2EN_BIT) -#define RCC_AHBENR_DMA1EN BIT(RCC_AHBENR_DMA1EN_BIT) - -/* APB2 peripheral clock enable register */ - -#define RCC_APB2ENR_TIM11EN_BIT 21 -#define RCC_APB2ENR_TIM10EN_BIT 20 -#define RCC_APB2ENR_TIM9EN_BIT 19 -#define RCC_APB2ENR_ADC3EN_BIT 15 -#define RCC_APB2ENR_USART1EN_BIT 14 -#define RCC_APB2ENR_TIM8EN_BIT 13 -#define RCC_APB2ENR_SPI1EN_BIT 12 -#define RCC_APB2ENR_TIM1EN_BIT 11 -#define RCC_APB2ENR_ADC2EN_BIT 10 -#define RCC_APB2ENR_ADC1EN_BIT 9 -#define RCC_APB2ENR_IOPGEN_BIT 8 -#define RCC_APB2ENR_IOPFEN_BIT 7 -#define RCC_APB2ENR_IOPEEN_BIT 6 -#define RCC_APB2ENR_IOPDEN_BIT 5 -#define RCC_APB2ENR_IOPCEN_BIT 4 -#define RCC_APB2ENR_IOPBEN_BIT 3 -#define RCC_APB2ENR_IOPAEN_BIT 2 -#define RCC_APB2ENR_AFIOEN_BIT 0 - -#define RCC_APB2ENR_TIM11EN BIT(RCC_APB2ENR_TIM11EN_BIT) -#define RCC_APB2ENR_TIM10EN BIT(RCC_APB2ENR_TIM10EN_BIT) -#define RCC_APB2ENR_TIM9EN BIT(RCC_APB2ENR_TIM9EN_BIT) -#define RCC_APB2ENR_ADC3EN BIT(RCC_APB2ENR_ADC3EN_BIT) -#define RCC_APB2ENR_USART1EN BIT(RCC_APB2ENR_USART1EN_BIT) -#define RCC_APB2ENR_TIM8EN BIT(RCC_APB2ENR_TIM8EN_BIT) -#define RCC_APB2ENR_SPI1EN BIT(RCC_APB2ENR_SPI1EN_BIT) -#define RCC_APB2ENR_TIM1EN BIT(RCC_APB2ENR_TIM1EN_BIT) -#define RCC_APB2ENR_ADC2EN BIT(RCC_APB2ENR_ADC2EN_BIT) -#define RCC_APB2ENR_ADC1EN BIT(RCC_APB2ENR_ADC1EN_BIT) -#define RCC_APB2ENR_IOPGEN BIT(RCC_APB2ENR_IOPGEN_BIT) -#define RCC_APB2ENR_IOPFEN BIT(RCC_APB2ENR_IOPFEN_BIT) -#define RCC_APB2ENR_IOPEEN BIT(RCC_APB2ENR_IOPEEN_BIT) -#define RCC_APB2ENR_IOPDEN BIT(RCC_APB2ENR_IOPDEN_BIT) -#define RCC_APB2ENR_IOPCEN BIT(RCC_APB2ENR_IOPCEN_BIT) -#define RCC_APB2ENR_IOPBEN BIT(RCC_APB2ENR_IOPBEN_BIT) -#define RCC_APB2ENR_IOPAEN BIT(RCC_APB2ENR_IOPAEN_BIT) -#define RCC_APB2ENR_AFIOEN BIT(RCC_APB2ENR_AFIOEN_BIT) - -/* APB1 peripheral clock enable register */ - -#define RCC_APB1ENR_DACEN_BIT 29 -#define RCC_APB1ENR_PWREN_BIT 28 -#define RCC_APB1ENR_BKPEN_BIT 27 -#define RCC_APB1ENR_CANEN_BIT 25 -#define RCC_APB1ENR_USBEN_BIT 23 -#define RCC_APB1ENR_I2C2EN_BIT 22 -#define RCC_APB1ENR_I2C1EN_BIT 21 -#define RCC_APB1ENR_UART5EN_BIT 20 -#define RCC_APB1ENR_UART4EN_BIT 19 -#define RCC_APB1ENR_USART3EN_BIT 18 -#define RCC_APB1ENR_USART2EN_BIT 17 -#define RCC_APB1ENR_SPI3EN_BIT 15 -#define RCC_APB1ENR_SPI2EN_BIT 14 -#define RCC_APB1ENR_WWDEN_BIT 11 -#define RCC_APB1ENR_TIM14EN_BIT 8 -#define RCC_APB1ENR_TIM13EN_BIT 7 -#define RCC_APB1ENR_TIM12EN_BIT 6 -#define RCC_APB1ENR_TIM7EN_BIT 5 -#define RCC_APB1ENR_TIM6EN_BIT 4 -#define RCC_APB1ENR_TIM5EN_BIT 3 -#define RCC_APB1ENR_TIM4EN_BIT 2 -#define RCC_APB1ENR_TIM3EN_BIT 1 -#define RCC_APB1ENR_TIM2EN_BIT 0 - -#define RCC_APB1ENR_DACEN BIT(RCC_APB1ENR_DACEN_BIT) -#define RCC_APB1ENR_PWREN BIT(RCC_APB1ENR_PWREN_BIT) -#define RCC_APB1ENR_BKPEN BIT(RCC_APB1ENR_BKPEN_BIT) -#define RCC_APB1ENR_CANEN BIT(RCC_APB1ENR_CANEN_BIT) -#define RCC_APB1ENR_USBEN BIT(RCC_APB1ENR_USBEN_BIT) -#define RCC_APB1ENR_I2C2EN BIT(RCC_APB1ENR_I2C2EN_BIT) -#define RCC_APB1ENR_I2C1EN BIT(RCC_APB1ENR_I2C1EN_BIT) -#define RCC_APB1ENR_UART5EN BIT(RCC_APB1ENR_UART5EN_BIT) -#define RCC_APB1ENR_UART4EN BIT(RCC_APB1ENR_UART4EN_BIT) -#define RCC_APB1ENR_USART3EN BIT(RCC_APB1ENR_USART3EN_BIT) -#define RCC_APB1ENR_USART2EN BIT(RCC_APB1ENR_USART2EN_BIT) -#define RCC_APB1ENR_SPI3EN BIT(RCC_APB1ENR_SPI3EN_BIT) -#define RCC_APB1ENR_SPI2EN BIT(RCC_APB1ENR_SPI2EN_BIT) -#define RCC_APB1ENR_WWDEN BIT(RCC_APB1ENR_WWDEN_BIT) -#define RCC_APB1ENR_TIM14EN BIT(RCC_APB1ENR_TIM14EN_BIT) -#define RCC_APB1ENR_TIM13EN BIT(RCC_APB1ENR_TIM13EN_BIT) -#define RCC_APB1ENR_TIM12EN BIT(RCC_APB1ENR_TIM12EN_BIT) -#define RCC_APB1ENR_TIM7EN BIT(RCC_APB1ENR_TIM7EN_BIT) -#define RCC_APB1ENR_TIM6EN BIT(RCC_APB1ENR_TIM6EN_BIT) -#define RCC_APB1ENR_TIM5EN BIT(RCC_APB1ENR_TIM5EN_BIT) -#define RCC_APB1ENR_TIM4EN BIT(RCC_APB1ENR_TIM4EN_BIT) -#define RCC_APB1ENR_TIM3EN BIT(RCC_APB1ENR_TIM3EN_BIT) -#define RCC_APB1ENR_TIM2EN BIT(RCC_APB1ENR_TIM2EN_BIT) - -/* Backup domain control register */ - -#define RCC_BDCR_BDRST_BIT 16 -#define RCC_BDCR_RTCEN_BIT 15 -#define RCC_BDCR_LSEBYP_BIT 2 -#define RCC_BDCR_LSERDY_BIT 1 -#define RCC_BDCR_LSEON_BIT 0 - -#define RCC_BDCR_BDRST BIT(RCC_BDCR_BDRST_BIT) -#define RCC_BDCR_RTCEN BIT(RCC_BDCR_RTC_BIT) -#define RCC_BDCR_RTCSEL (0x3 << 8) -#define RCC_BDCR_RTCSEL_NONE (0x0 << 8) -#define RCC_BDCR_RTCSEL_LSE (0x1 << 8) -#define RCC_BDCR_RTCSEL_HSE (0x3 << 8) -#define RCC_BDCR_LSEBYP BIT(RCC_BDCR_LSEBYP_BIT) -#define RCC_BDCR_LSERDY BIT(RCC_BDCR_LSERDY_BIT) -#define RCC_BDCR_LSEON BIT(RCC_BDCR_LSEON_BIT) - -/* Control/status register */ - -#define RCC_CSR_LPWRRSTF_BIT 31 -#define RCC_CSR_WWDGRSTF_BIT 30 -#define RCC_CSR_IWDGRSTF_BIT 29 -#define RCC_CSR_SFTRSTF_BIT 28 -#define RCC_CSR_PORRSTF_BIT 27 -#define RCC_CSR_PINRSTF_BIT 26 -#define RCC_CSR_RMVF_BIT 24 -#define RCC_CSR_LSIRDY_BIT 1 -#define RCC_CSR_LSION_BIT 0 - -#define RCC_CSR_LPWRRSTF BIT(RCC_CSR_LPWRRSTF_BIT) -#define RCC_CSR_WWDGRSTF BIT(RCC_CSR_WWDGRSTF_BIT) -#define RCC_CSR_IWDGRSTF BIT(RCC_CSR_IWDGRSTF_BIT) -#define RCC_CSR_SFTRSTF BIT(RCC_CSR_SFTRSTF_BIT) -#define RCC_CSR_PORRSTF BIT(RCC_CSR_PORRSTF_BIT) -#define RCC_CSR_PINRSTF BIT(RCC_CSR_PINRSTF_BIT) -#define RCC_CSR_RMVF BIT(RCC_CSR_RMVF_BIT) -#define RCC_CSR_LSIRDY BIT(RCC_CSR_LSIRDY_BIT) -#define RCC_CSR_LSION BIT(RCC_CSR_LSION_BIT) - -/* - * Other types - */ - -/** - * @brief Identifies bus and clock line for a peripheral. - * - * Also generally useful as a unique identifier for that peripheral - * (or its corresponding device struct). - */ -typedef enum rcc_clk_id { - RCC_GPIOA, - RCC_GPIOB, - RCC_GPIOC, - RCC_GPIOD, - RCC_AFIO, - RCC_ADC1, - RCC_ADC2, - RCC_ADC3, - RCC_USART1, - RCC_USART2, - RCC_USART3, - RCC_TIMER1, - RCC_TIMER2, - RCC_TIMER3, - RCC_TIMER4, - RCC_SPI1, - RCC_SPI2, - RCC_DMA1, - RCC_PWR, - RCC_BKP, - RCC_I2C1, - RCC_I2C2, - RCC_CRC, - RCC_FLITF, - RCC_SRAM, - RCC_USB, -#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) - RCC_GPIOE, - RCC_GPIOF, - RCC_GPIOG, - RCC_UART4, - RCC_UART5, - RCC_TIMER5, - RCC_TIMER6, - RCC_TIMER7, - RCC_TIMER8, - RCC_FSMC, - RCC_DAC, - RCC_DMA2, - RCC_SDIO, - RCC_SPI3, -#endif -#ifdef STM32_XL_DENSITY - RCC_TIMER9, - RCC_TIMER10, - RCC_TIMER11, - RCC_TIMER12, - RCC_TIMER13, - RCC_TIMER14, -#endif -} rcc_clk_id; - -/** - * PLL multipliers - * @see rcc_clk_init() - */ -typedef enum rcc_pll_multiplier { - RCC_PLLMUL_2 = (0x0 << 18), - RCC_PLLMUL_3 = (0x1 << 18), - RCC_PLLMUL_4 = (0x2 << 18), - RCC_PLLMUL_5 = (0x3 << 18), - RCC_PLLMUL_6 = (0x4 << 18), - RCC_PLLMUL_7 = (0x5 << 18), - RCC_PLLMUL_8 = (0x6 << 18), - RCC_PLLMUL_9 = (0x7 << 18), - RCC_PLLMUL_10 = (0x8 << 18), - RCC_PLLMUL_11 = (0x9 << 18), - RCC_PLLMUL_12 = (0xA << 18), - RCC_PLLMUL_13 = (0xB << 18), - RCC_PLLMUL_14 = (0xC << 18), - RCC_PLLMUL_15 = (0xD << 18), - RCC_PLLMUL_16 = (0xE << 18), -} rcc_pll_multiplier; - -/** - * PLL entry clock source - * @see rcc_clk_init() - */ -typedef enum rcc_pllsrc { - RCC_PLLSRC_HSE = (0x1 << 16), - RCC_PLLSRC_HSI_DIV_2 = (0x0 << 16) -} rcc_pllsrc; - -typedef enum rcc_clk_domain { - RCC_APB1, - RCC_APB2, - RCC_AHB -} rcc_clk_domain; - -/** - * Prescaler identifiers - * @see rcc_set_prescaler() - */ -typedef enum rcc_prescaler { - RCC_PRESCALER_AHB, - RCC_PRESCALER_APB1, - RCC_PRESCALER_APB2, - RCC_PRESCALER_USB, - RCC_PRESCALER_ADC -} rcc_prescaler; - -/** - * ADC prescaler dividers - * @see rcc_set_prescaler() - */ -typedef enum rcc_adc_divider { - RCC_ADCPRE_PCLK_DIV_2 = 0x0 << 14, - RCC_ADCPRE_PCLK_DIV_4 = 0x1 << 14, - RCC_ADCPRE_PCLK_DIV_6 = 0x2 << 14, - RCC_ADCPRE_PCLK_DIV_8 = 0x3 << 14, -} rcc_adc_divider; - -/** - * APB1 prescaler dividers - * @see rcc_set_prescaler() - */ -typedef enum rcc_apb1_divider { - RCC_APB1_HCLK_DIV_1 = 0x0 << 8, - RCC_APB1_HCLK_DIV_2 = 0x4 << 8, - RCC_APB1_HCLK_DIV_4 = 0x5 << 8, - RCC_APB1_HCLK_DIV_8 = 0x6 << 8, - RCC_APB1_HCLK_DIV_16 = 0x7 << 8, -} rcc_apb1_divider; - -/** - * APB2 prescaler dividers - * @see rcc_set_prescaler() - */ -typedef enum rcc_apb2_divider { - RCC_APB2_HCLK_DIV_1 = 0x0 << 11, - RCC_APB2_HCLK_DIV_2 = 0x4 << 11, - RCC_APB2_HCLK_DIV_4 = 0x5 << 11, - RCC_APB2_HCLK_DIV_8 = 0x6 << 11, - RCC_APB2_HCLK_DIV_16 = 0x7 << 11, -} rcc_apb2_divider; - -/** - * AHB prescaler dividers - * @see rcc_set_prescaler() - */ -typedef enum rcc_ahb_divider { - RCC_AHB_SYSCLK_DIV_1 = 0x0 << 4, - RCC_AHB_SYSCLK_DIV_2 = 0x8 << 4, - RCC_AHB_SYSCLK_DIV_4 = 0x9 << 4, - RCC_AHB_SYSCLK_DIV_8 = 0xA << 4, - RCC_AHB_SYSCLK_DIV_16 = 0xB << 4, - RCC_AHB_SYSCLK_DIV_32 = 0xC << 4, - RCC_AHB_SYSCLK_DIV_64 = 0xD << 4, - RCC_AHB_SYSCLK_DIV_128 = 0xD << 4, - RCC_AHB_SYSCLK_DIV_256 = 0xE << 4, - RCC_AHB_SYSCLK_DIV_512 = 0xF << 4, -} rcc_ahb_divider; - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/libmaple/stm32f1/include/family/stm32.h b/libmaple/stm32f1/include/family/stm32.h deleted file mode 100644 index 0b77ca0..0000000 --- a/libmaple/stm32f1/include/family/stm32.h +++ /dev/null @@ -1,100 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010, 2011 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/stm32f1/stm32.h - * @brief STM32F1 chip- and family-specific definitions. - */ - -#ifndef _LIBMAPLE_STM32F1_H_ -#define _LIBMAPLE_STM32F1_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Clock configuration. - */ - -#ifndef STM32_PCLK1 -#define STM32_PCLK1 36000000U -#endif - -#ifndef STM32_PCLK2 -#define STM32_PCLK2 72000000U -#endif - -#ifndef STM32_DELAY_US_MULT -#define STM32_DELAY_US_MULT 12 /* FIXME: value is incorrect. */ -#endif - -/* - * Density-specific values. - */ - -#ifdef STM32_MEDIUM_DENSITY -# define STM32_NR_INTERRUPTS 43 -#elif defined(STM32_HIGH_DENSITY) -# define STM32_NR_INTERRUPTS 60 -#else -#error "Unsupported STM32F1 density, or no density specified. Add something " \ - "like -DSTM32_MEDIUM_DENSITY to your compiler arguments." -#endif - -/* - * MCU-specific values. - */ - -#if defined(MCU_STM32F103RB) -# define STM32_NR_GPIO_PORTS 4 -# define STM32_SRAM_END ((void*)0x20005000) - -#elif defined(MCU_STM32F103ZE) -# define STM32_NR_GPIO_PORTS 7 -# define STM32_SRAM_END ((void*)0x20010000) - -#elif defined(MCU_STM32F103CB) - /* This STM32_NR_GPIO_PORTS is not stricly true, but only pins 0 - * and exist, and they're used for OSC (e.g. on e.g. LeafLabs - * Maple Mini), so we'll live with this for now. */ -# define STM32_NR_GPIO_PORTS 3 -# define STM32_SRAM_END ((void*)0x20005000) - -#elif defined(MCU_STM32F103RE) -# define STM32_NR_GPIO_PORTS 4 -# define STM32_SRAM_END ((void*)0x20010000) - -#else -#error "Unrecognized STM32F1 MCU, or no MCU specified. Add something like " \ - "-DMCU_STM32F103RB to your compiler arguments." -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/libmaple/stm32f1/include/series/flash.h b/libmaple/stm32f1/include/series/flash.h new file mode 100644 index 0000000..efa608c --- /dev/null +++ b/libmaple/stm32f1/include/series/flash.h @@ -0,0 +1,142 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Perry Hung. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/flash.h + * @brief STM32F1 Flash header. + * + * Provides register map, base pointer, and register bit definitions + * for the Flash controller on the STM32F1 line, along with + * series-specific configuration values. + */ + +#ifndef _LIBMAPLE_STM32F1_FLASH_H_ +#define _LIBMAPLE_STM32F1_FLASH_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include + +/* + * Register map + */ + +/** Flash register map type */ +typedef struct flash_reg_map { + __io uint32 ACR; /**< Access control register */ + __io uint32 KEYR; /**< Key register */ + __io uint32 OPTKEYR; /**< OPTKEY register */ + __io uint32 SR; /**< Status register */ + __io uint32 CR; /**< Control register */ + __io uint32 AR; /**< Address register */ + __io uint32 OBR; /**< Option byte register */ + __io uint32 WRPR; /**< Write protection register */ +} flash_reg_map; + +/** Flash register map base pointer */ +#define FLASH_BASE ((struct flash_reg_map*)0x40022000) + +/* + * Register bit definitions + */ + +/* Access control register */ + +#define FLASH_ACR_PRFTBS_BIT 5 +#define FLASH_ACR_PRFTBE_BIT 4 +#define FLASH_ACR_HLFCYA_BIT 3 + +#define FLASH_ACR_PRFTBS BIT(FLASH_ACR_PRFTBS_BIT) +#define FLASH_ACR_PRFTBE BIT(FLASH_ACR_PRFTBE_BIT) +#define FLASH_ACR_HLFCYA BIT(FLASH_ACR_HLFCYA_BIT) +#define FLASH_ACR_LATENCY 0x7 + +/* Status register */ + +#define FLASH_SR_EOP_BIT 5 +#define FLASH_SR_WRPRTERR_BIT 4 +#define FLASH_SR_PGERR_BIT 2 +#define FLASH_SR_BSY_BIT 0 + +#define FLASH_SR_EOP BIT(FLASH_SR_EOP_BIT) +#define FLASH_SR_WRPRTERR BIT(FLASH_SR_WRPRTERR_BIT) +#define FLASH_SR_PGERR BIT(FLASH_SR_PGERR_BIT) +#define FLASH_SR_BSY BIT(FLASH_SR_BSY_BIT) + +/* Control register */ + +#define FLASH_CR_EOPIE_BIT 12 +#define FLASH_CR_ERRIE_BIT 10 +#define FLASH_CR_OPTWRE_BIT 9 +#define FLASH_CR_LOCK_BIT 7 +#define FLASH_CR_STRT_BIT 6 +#define FLASH_CR_OPTER_BIT 5 +#define FLASH_CR_OPTPG_BIT 4 +#define FLASH_CR_MER_BIT 2 +#define FLASH_CR_PER_BIT 1 +#define FLASH_CR_PG_BIT 0 + +#define FLASH_CR_EOPIE BIT(FLASH_CR_EOPIE_BIT) +#define FLASH_CR_ERRIE BIT(FLASH_CR_ERRIE_BIT) +#define FLASH_CR_OPTWRE BIT(FLASH_CR_OPTWRE_BIT) +#define FLASH_CR_LOCK BIT(FLASH_CR_LOCK_BIT) +#define FLASH_CR_STRT BIT(FLASH_CR_STRT_BIT) +#define FLASH_CR_OPTER BIT(FLASH_CR_OPTER_BIT) +#define FLASH_CR_OPTPG BIT(FLASH_CR_OPTPG_BIT) +#define FLASH_CR_MER BIT(FLASH_CR_MER_BIT) +#define FLASH_CR_PER BIT(FLASH_CR_PER_BIT) +#define FLASH_CR_PG BIT(FLASH_CR_PG_BIT) + +/* Option byte register */ + +#define FLASH_OBR_nRST_STDBY_BIT 4 +#define FLASH_OBR_nRST_STOP_BIT 3 +#define FLASH_OBR_WDG_SW_BIT 2 +#define FLASH_OBR_RDPRT_BIT 1 +#define FLASH_OBR_OPTERR_BIT 0 + +#define FLASH_OBR_DATA1 (0xFF << 18) +#define FLASH_OBR_DATA0 (0xFF << 10) +#define FLASH_OBR_USER 0x3FF +#define FLASH_OBR_nRST_STDBY BIT(FLASH_OBR_nRST_STDBY_BIT) +#define FLASH_OBR_nRST_STOP BIT(FLASH_OBR_nRST_STOP_BIT) +#define FLASH_OBR_WDG_SW BIT(FLASH_OBR_WDG_SW_BIT) +#define FLASH_OBR_RDPRT BIT(FLASH_OBR_RDPRT_BIT) +#define FLASH_OBR_OPTERR BIT(FLASH_OBR_OPTERR_BIT) + +/* + * Series-specific configuration values. + */ + +#define FLASH_SAFE_WAIT_STATES FLASH_WAIT_STATE_2 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libmaple/stm32f1/include/series/gpio.h b/libmaple/stm32f1/include/series/gpio.h new file mode 100644 index 0000000..c10244d --- /dev/null +++ b/libmaple/stm32f1/include/series/gpio.h @@ -0,0 +1,479 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Perry Hung. + * Copyright (c) 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. +*****************************************************************************/ + +/** + * @file libmaple/stm32f1/gpio.h + * @brief General purpose I/O (GPIO) and Alternate Function I/O + * (AFIO) prototypes, defines, and inlined access functions. + */ + +#ifndef _LIBMAPLE_STM32F1_GPIO_H_ +#define _LIBMAPLE_STM32F1_GPIO_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include +#include + +/* + * GPIO register maps and devices + */ + +/** GPIO register map type */ +typedef struct gpio_reg_map { + __io uint32 CRL; /**< Port configuration register low */ + __io uint32 CRH; /**< Port configuration register high */ + __io uint32 IDR; /**< Port input data register */ + __io uint32 ODR; /**< Port output data register */ + __io uint32 BSRR; /**< Port bit set/reset register */ + __io uint32 BRR; /**< Port bit reset register */ + __io uint32 LCKR; /**< Port configuration lock register */ +} gpio_reg_map; + +/** + * @brief External interrupt line port selector. + * + * Used to determine which GPIO port to map an external interrupt line + * onto. */ +/* (See AFIO sections, below) */ +typedef enum afio_exti_port { + AFIO_EXTI_PA, /**< Use port A (PAx) pin. */ + AFIO_EXTI_PB, /**< Use port B (PBx) pin. */ + AFIO_EXTI_PC, /**< Use port C (PCx) pin. */ + AFIO_EXTI_PD, /**< Use port D (PDx) pin. */ +#ifdef STM32_HIGH_DENSITY + AFIO_EXTI_PE, /**< Use port E (PEx) pin. */ + AFIO_EXTI_PF, /**< Use port F (PFx) pin. */ + AFIO_EXTI_PG, /**< Use port G (PGx) pin. */ +#endif +} afio_exti_port; + +/** GPIO device type */ +typedef struct gpio_dev { + gpio_reg_map *regs; /**< Register map */ + rcc_clk_id clk_id; /**< RCC clock information */ + afio_exti_port exti_port; /**< AFIO external interrupt port value */ +} gpio_dev; + +extern gpio_dev gpioa; +extern gpio_dev* const GPIOA; +extern gpio_dev gpiob; +extern gpio_dev* const GPIOB; +extern gpio_dev gpioc; +extern gpio_dev* const GPIOC; +extern gpio_dev gpiod; +extern gpio_dev* const GPIOD; +#ifdef STM32_HIGH_DENSITY +extern gpio_dev gpioe; +extern gpio_dev* const GPIOE; +extern gpio_dev gpiof; +extern gpio_dev* const GPIOF; +extern gpio_dev gpiog; +extern gpio_dev* const GPIOG; +#endif + +/** GPIO port A register map base pointer */ +#define GPIOA_BASE ((struct gpio_reg_map*)0x40010800) +/** GPIO port B register map base pointer */ +#define GPIOB_BASE ((struct gpio_reg_map*)0x40010C00) +/** GPIO port C register map base pointer */ +#define GPIOC_BASE ((struct gpio_reg_map*)0x40011000) +/** GPIO port D register map base pointer */ +#define GPIOD_BASE ((struct gpio_reg_map*)0x40011400) +#ifdef STM32_HIGH_DENSITY +/** GPIO port E register map base pointer */ +#define GPIOE_BASE ((struct gpio_reg_map*)0x40011800) +/** GPIO port F register map base pointer */ +#define GPIOF_BASE ((struct gpio_reg_map*)0x40011C00) +/** GPIO port G register map base pointer */ +#define GPIOG_BASE ((struct gpio_reg_map*)0x40012000) +#endif + +/* + * GPIO register bit definitions + */ + +/* Control registers, low and high */ + +#define GPIO_CR_CNF (0x3 << 2) +#define GPIO_CR_CNF_INPUT_ANALOG (0x0 << 2) +#define GPIO_CR_CNF_INPUT_FLOATING (0x1 << 2) +#define GPIO_CR_CNF_INPUT_PU_PD (0x2 << 2) +#define GPIO_CR_CNF_OUTPUT_PP (0x0 << 2) +#define GPIO_CR_CNF_OUTPUT_OD (0x1 << 2) +#define GPIO_CR_CNF_AF_OUTPUT_PP (0x2 << 2) +#define GPIO_CR_CNF_AF_OUTPUT_OD (0x3 << 2) +#define GPIO_CR_MODE 0x3 +#define GPIO_CR_MODE_INPUT 0x0 +#define GPIO_CR_MODE_OUTPUT_10MHZ 0x1 +#define GPIO_CR_MODE_OUTPUT_2MHZ 0x2 +#define GPIO_CR_MODE_OUTPUT_50MHZ 0x3 + +/** + * @brief GPIO Pin modes. + * + * These only allow for 50MHZ max output speeds; if you want slower, + * use direct register access. + */ +typedef enum gpio_pin_mode { + GPIO_OUTPUT_PP = (GPIO_CR_CNF_OUTPUT_PP | + GPIO_CR_MODE_OUTPUT_50MHZ), /**< Output push-pull. */ + GPIO_OUTPUT_OD = (GPIO_CR_CNF_OUTPUT_OD | + GPIO_CR_MODE_OUTPUT_50MHZ), /**< Output open-drain. */ + GPIO_AF_OUTPUT_PP = (GPIO_CR_CNF_AF_OUTPUT_PP | + GPIO_CR_MODE_OUTPUT_50MHZ), /**< Alternate function + output push-pull. */ + GPIO_AF_OUTPUT_OD = (GPIO_CR_CNF_AF_OUTPUT_OD | + GPIO_CR_MODE_OUTPUT_50MHZ), /**< Alternate function + output open drain. */ + GPIO_INPUT_ANALOG = (GPIO_CR_CNF_INPUT_ANALOG | + GPIO_CR_MODE_INPUT), /**< Analog input. */ + GPIO_INPUT_FLOATING = (GPIO_CR_CNF_INPUT_FLOATING | + GPIO_CR_MODE_INPUT), /**< Input floating. */ + GPIO_INPUT_PD = (GPIO_CR_CNF_INPUT_PU_PD | + GPIO_CR_MODE_INPUT), /**< Input pull-down. */ + GPIO_INPUT_PU /**< Input pull-up. */ + /* GPIO_INPUT_PU treated as a special case, for ODR twiddling */ +} gpio_pin_mode; + +/** + * @brief Get a GPIO port's corresponding afio_exti_port. + * @param dev GPIO device whose afio_exti_port to return. + */ +static inline afio_exti_port gpio_exti_port(gpio_dev *dev) { + return dev->exti_port; +} + +/* + * AFIO register map + */ + +/** AFIO register map */ +typedef struct afio_reg_map { + __io uint32 EVCR; /**< Event control register. */ + __io uint32 MAPR; /**< AF remap and debug I/O configuration + register. */ + __io uint32 EXTICR1; /**< External interrupt configuration + register 1. */ + __io uint32 EXTICR2; /**< External interrupt configuration + register 2. */ + __io uint32 EXTICR3; /**< External interrupt configuration + register 3. */ + __io uint32 EXTICR4; /**< External interrupt configuration + register 4. */ + __io uint32 MAPR2; /**< AF remap and debug I/O configuration + register 2. */ +} afio_reg_map; + +/** AFIO register map base pointer. */ +#define AFIO_BASE ((struct afio_reg_map *)0x40010000) + +/* + * AFIO register bit definitions + */ + +/* Event control register */ + +#define AFIO_EVCR_EVOE (0x1 << 7) +#define AFIO_EVCR_PORT_PA (0x0 << 4) +#define AFIO_EVCR_PORT_PB (0x1 << 4) +#define AFIO_EVCR_PORT_PC (0x2 << 4) +#define AFIO_EVCR_PORT_PD (0x3 << 4) +#define AFIO_EVCR_PORT_PE (0x4 << 4) +#define AFIO_EVCR_PIN_0 0x0 +#define AFIO_EVCR_PIN_1 0x1 +#define AFIO_EVCR_PIN_2 0x2 +#define AFIO_EVCR_PIN_3 0x3 +#define AFIO_EVCR_PIN_4 0x4 +#define AFIO_EVCR_PIN_5 0x5 +#define AFIO_EVCR_PIN_6 0x6 +#define AFIO_EVCR_PIN_7 0x7 +#define AFIO_EVCR_PIN_8 0x8 +#define AFIO_EVCR_PIN_9 0x9 +#define AFIO_EVCR_PIN_10 0xA +#define AFIO_EVCR_PIN_11 0xB +#define AFIO_EVCR_PIN_12 0xC +#define AFIO_EVCR_PIN_13 0xD +#define AFIO_EVCR_PIN_14 0xE +#define AFIO_EVCR_PIN_15 0xF + +/* AF remap and debug I/O configuration register */ + +#define AFIO_MAPR_SWJ_CFG (0x7 << 24) +#define AFIO_MAPR_SWJ_CFG_FULL_SWJ (0x0 << 24) +#define AFIO_MAPR_SWJ_CFG_FULL_SWJ_NO_NJRST (0x1 << 24) +#define AFIO_MAPR_SWJ_CFG_NO_JTAG_SW (0x2 << 24) +#define AFIO_MAPR_SWJ_CFG_NO_JTAG_NO_SW (0x4 << 24) +#define AFIO_MAPR_ADC2_ETRGREG_REMAP BIT(20) +#define AFIO_MAPR_ADC2_ETRGINJ_REMAP BIT(19) +#define AFIO_MAPR_ADC1_ETRGREG_REMAP BIT(18) +#define AFIO_MAPR_ADC1_ETRGINJ_REMAP BIT(17) +#define AFIO_MAPR_TIM5CH4_IREMAP BIT(16) +#define AFIO_MAPR_PD01_REMAP BIT(15) +#define AFIO_MAPR_CAN_REMAP (0x3 << 13) +#define AFIO_MAPR_CAN_REMAP_NONE (0x0 << 13) +#define AFIO_MAPR_CAN_REMAP_PB8_PB9 (0x2 << 13) +#define AFIO_MAPR_CAN_REMAP_PD0_PD1 (0x3 << 13) +#define AFIO_MAPR_TIM4_REMAP BIT(12) +#define AFIO_MAPR_TIM3_REMAP (0x3 << 10) +#define AFIO_MAPR_TIM3_REMAP_NONE (0x0 << 10) +#define AFIO_MAPR_TIM3_REMAP_PARTIAL (0x2 << 10) +#define AFIO_MAPR_TIM3_REMAP_FULL (0x3 << 10) +#define AFIO_MAPR_TIM2_REMAP (0x3 << 8) +#define AFIO_MAPR_TIM2_REMAP_NONE (0x0 << 8) +#define AFIO_MAPR_TIM2_REMAP_PA15_PB3_PA2_PA3 (0x1 << 8) +#define AFIO_MAPR_TIM2_REMAP_PA0_PA1_PB10_PB11 (0x2 << 8) +#define AFIO_MAPR_TIM2_REMAP_FULL (0x3 << 8) +#define AFIO_MAPR_TIM1_REMAP (0x3 << 6) +#define AFIO_MAPR_TIM1_REMAP_NONE (0x0 << 6) +#define AFIO_MAPR_TIM1_REMAP_PARTIAL (0x1 << 6) +#define AFIO_MAPR_TIM1_REMAP_FULL (0x3 << 6) +#define AFIO_MAPR_USART3_REMAP (0x3 << 4) +#define AFIO_MAPR_USART3_REMAP_NONE (0x0 << 4) +#define AFIO_MAPR_USART3_REMAP_PARTIAL (0x1 << 4) +#define AFIO_MAPR_USART3_REMAP_FULL (0x3 << 4) +#define AFIO_MAPR_USART2_REMAP BIT(3) +#define AFIO_MAPR_USART1_REMAP BIT(2) +#define AFIO_MAPR_I2C1_REMAP BIT(1) +#define AFIO_MAPR_SPI1_REMAP BIT(0) + +/* External interrupt configuration register 1 */ + +#define AFIO_EXTICR1_EXTI3 (0xF << 12) +#define AFIO_EXTICR1_EXTI3_PA (0x0 << 12) +#define AFIO_EXTICR1_EXTI3_PB (0x1 << 12) +#define AFIO_EXTICR1_EXTI3_PC (0x2 << 12) +#define AFIO_EXTICR1_EXTI3_PD (0x3 << 12) +#define AFIO_EXTICR1_EXTI3_PE (0x4 << 12) +#define AFIO_EXTICR1_EXTI3_PF (0x5 << 12) +#define AFIO_EXTICR1_EXTI3_PG (0x6 << 12) +#define AFIO_EXTICR1_EXTI2 (0xF << 8) +#define AFIO_EXTICR1_EXTI2_PA (0x0 << 8) +#define AFIO_EXTICR1_EXTI2_PB (0x1 << 8) +#define AFIO_EXTICR1_EXTI2_PC (0x2 << 8) +#define AFIO_EXTICR1_EXTI2_PD (0x3 << 8) +#define AFIO_EXTICR1_EXTI2_PE (0x4 << 8) +#define AFIO_EXTICR1_EXTI2_PF (0x5 << 8) +#define AFIO_EXTICR1_EXTI2_PG (0x6 << 8) +#define AFIO_EXTICR1_EXTI1 (0xF << 4) +#define AFIO_EXTICR1_EXTI1_PA (0x0 << 4) +#define AFIO_EXTICR1_EXTI1_PB (0x1 << 4) +#define AFIO_EXTICR1_EXTI1_PC (0x2 << 4) +#define AFIO_EXTICR1_EXTI1_PD (0x3 << 4) +#define AFIO_EXTICR1_EXTI1_PE (0x4 << 4) +#define AFIO_EXTICR1_EXTI1_PF (0x5 << 4) +#define AFIO_EXTICR1_EXTI1_PG (0x6 << 4) +#define AFIO_EXTICR1_EXTI0 0xF +#define AFIO_EXTICR1_EXTI0_PA 0x0 +#define AFIO_EXTICR1_EXTI0_PB 0x1 +#define AFIO_EXTICR1_EXTI0_PC 0x2 +#define AFIO_EXTICR1_EXTI0_PD 0x3 +#define AFIO_EXTICR1_EXTI0_PE 0x4 +#define AFIO_EXTICR1_EXTI0_PF 0x5 +#define AFIO_EXTICR1_EXTI0_PG 0x6 + +/* External interrupt configuration register 2 */ + +#define AFIO_EXTICR2_EXTI7 (0xF << 12) +#define AFIO_EXTICR2_EXTI7_PA (0x0 << 12) +#define AFIO_EXTICR2_EXTI7_PB (0x1 << 12) +#define AFIO_EXTICR2_EXTI7_PC (0x2 << 12) +#define AFIO_EXTICR2_EXTI7_PD (0x3 << 12) +#define AFIO_EXTICR2_EXTI7_PE (0x4 << 12) +#define AFIO_EXTICR2_EXTI7_PF (0x5 << 12) +#define AFIO_EXTICR2_EXTI7_PG (0x6 << 12) +#define AFIO_EXTICR2_EXTI6 (0xF << 8) +#define AFIO_EXTICR2_EXTI6_PA (0x0 << 8) +#define AFIO_EXTICR2_EXTI6_PB (0x1 << 8) +#define AFIO_EXTICR2_EXTI6_PC (0x2 << 8) +#define AFIO_EXTICR2_EXTI6_PD (0x3 << 8) +#define AFIO_EXTICR2_EXTI6_PE (0x4 << 8) +#define AFIO_EXTICR2_EXTI6_PF (0x5 << 8) +#define AFIO_EXTICR2_EXTI6_PG (0x6 << 8) +#define AFIO_EXTICR2_EXTI5 (0xF << 4) +#define AFIO_EXTICR2_EXTI5_PA (0x0 << 4) +#define AFIO_EXTICR2_EXTI5_PB (0x1 << 4) +#define AFIO_EXTICR2_EXTI5_PC (0x2 << 4) +#define AFIO_EXTICR2_EXTI5_PD (0x3 << 4) +#define AFIO_EXTICR2_EXTI5_PE (0x4 << 4) +#define AFIO_EXTICR2_EXTI5_PF (0x5 << 4) +#define AFIO_EXTICR2_EXTI5_PG (0x6 << 4) +#define AFIO_EXTICR2_EXTI4 0xF +#define AFIO_EXTICR2_EXTI4_PA 0x0 +#define AFIO_EXTICR2_EXTI4_PB 0x1 +#define AFIO_EXTICR2_EXTI4_PC 0x2 +#define AFIO_EXTICR2_EXTI4_PD 0x3 +#define AFIO_EXTICR2_EXTI4_PE 0x4 +#define AFIO_EXTICR2_EXTI4_PF 0x5 +#define AFIO_EXTICR2_EXTI4_PG 0x6 + +/* AF remap and debug I/O configuration register 2 */ + +#define AFIO_MAPR2_FSMC_NADV BIT(10) +#define AFIO_MAPR2_TIM14_REMAP BIT(9) +#define AFIO_MAPR2_TIM13_REMAP BIT(8) +#define AFIO_MAPR2_TIM11_REMAP BIT(7) +#define AFIO_MAPR2_TIM10_REMAP BIT(6) +#define AFIO_MAPR2_TIM9_REMAP BIT(5) + +/* + * AFIO convenience routines + */ + +void afio_init(void); + +/** + * External interrupt line numbers. + */ +typedef enum afio_exti_num { + AFIO_EXTI_0, /**< External interrupt line 0. */ + AFIO_EXTI_1, /**< External interrupt line 1. */ + AFIO_EXTI_2, /**< External interrupt line 2. */ + AFIO_EXTI_3, /**< External interrupt line 3. */ + AFIO_EXTI_4, /**< External interrupt line 4. */ + AFIO_EXTI_5, /**< External interrupt line 5. */ + AFIO_EXTI_6, /**< External interrupt line 6. */ + AFIO_EXTI_7, /**< External interrupt line 7. */ + AFIO_EXTI_8, /**< External interrupt line 8. */ + AFIO_EXTI_9, /**< External interrupt line 9. */ + AFIO_EXTI_10, /**< External interrupt line 10. */ + AFIO_EXTI_11, /**< External interrupt line 11. */ + AFIO_EXTI_12, /**< External interrupt line 12. */ + AFIO_EXTI_13, /**< External interrupt line 13. */ + AFIO_EXTI_14, /**< External interrupt line 14. */ + AFIO_EXTI_15, /**< External interrupt line 15. */ +} afio_exti_num; + +void afio_exti_select(afio_exti_num exti, afio_exti_port gpio_port); + +/* HACK: Use upper bit to denote MAPR2, Bit 31 is reserved and + * not used in either MAPR or MAPR2 */ +#define AFIO_REMAP_USE_MAPR2 (1 << 31) + +/** + * @brief Available peripheral remaps. + * @see afio_remap() + */ +typedef enum afio_remap_peripheral { + AFIO_REMAP_ADC2_ETRGREG = AFIO_MAPR_ADC2_ETRGREG_REMAP, /**< + ADC 2 external trigger regular conversion remapping */ + AFIO_REMAP_ADC2_ETRGINJ = AFIO_MAPR_ADC2_ETRGINJ_REMAP, /**< + ADC 2 external trigger injected conversion remapping */ + AFIO_REMAP_ADC1_ETRGREG = AFIO_MAPR_ADC1_ETRGREG_REMAP, /**< + ADC 1 external trigger regular conversion remapping */ + AFIO_REMAP_ADC1_ETRGINJ = AFIO_MAPR_ADC1_ETRGINJ_REMAP, /**< + ADC 1 external trigger injected conversion remapping */ + AFIO_REMAP_TIM5CH4_I = AFIO_MAPR_TIM5CH4_IREMAP, /**< + Timer 5 channel 4 internal remapping */ + AFIO_REMAP_PD01 = AFIO_MAPR_PD01_REMAP, /**< + Port D0/Port D1 mapping on OSC_IN/OSC_OUT */ + AFIO_REMAP_CAN_1 = AFIO_MAPR_CAN_REMAP_PB8_PB9, /**< + CAN alternate function remapping 1 (RX on PB8, TX on PB9) */ + AFIO_REMAP_CAN_2 = AFIO_MAPR_CAN_REMAP_PD0_PD1, /**< + CAN alternate function remapping 2 (RX on PD0, TX on PD1) */ + AFIO_REMAP_TIM4 = AFIO_MAPR_TIM4_REMAP, /**< + Timer 4 remapping */ + AFIO_REMAP_TIM3_PARTIAL = AFIO_MAPR_TIM3_REMAP_PARTIAL, /**< + Timer 3 partial remapping */ + AFIO_REMAP_TIM3_FULL = AFIO_MAPR_TIM3_REMAP_FULL, /**< + Timer 3 full remapping */ + AFIO_REMAP_TIM2_PARTIAL_1 = AFIO_MAPR_TIM2_REMAP_PA15_PB3_PA2_PA3, /**< + Timer 2 partial remapping 1 (CH1 and ETR on PA15, CH2 on PB3, CH3 + on PA2, CH4 on PA3) */ + AFIO_REMAP_TIM2_PARTIAL_2 = AFIO_MAPR_TIM2_REMAP_PA0_PA1_PB10_PB11, /**< + Timer 2 partial remapping 2 (CH1 and ETR on PA0, CH2 on PA1, CH3 + on PB10, CH4 on PB11) */ + AFIO_REMAP_TIM2_FULL = AFIO_MAPR_TIM2_REMAP_FULL, /**< + Timer 2 full remapping */ + AFIO_REMAP_USART2 = AFIO_MAPR_USART2_REMAP, /**< + USART 2 remapping */ + AFIO_REMAP_USART1 = AFIO_MAPR_USART1_REMAP, /**< + USART 1 remapping */ + AFIO_REMAP_I2C1 = AFIO_MAPR_I2C1_REMAP, /**< + I2C 1 remapping */ + AFIO_REMAP_SPI1 = AFIO_MAPR_SPI1_REMAP, /**< + SPI 1 remapping */ + AFIO_REMAP_FSMC_NADV = (AFIO_MAPR2_FSMC_NADV | + AFIO_REMAP_USE_MAPR2), /**< + NADV signal not connected */ + AFIO_REMAP_TIM14 = (AFIO_MAPR2_TIM14_REMAP | + AFIO_REMAP_USE_MAPR2), /**< + Timer 14 remapping */ + AFIO_REMAP_TIM13 = (AFIO_MAPR2_TIM13_REMAP | + AFIO_REMAP_USE_MAPR2), /**< + Timer 13 remapping */ + AFIO_REMAP_TIM11 = (AFIO_MAPR2_TIM11_REMAP | + AFIO_REMAP_USE_MAPR2), /**< + Timer 11 remapping */ + AFIO_REMAP_TIM10 = (AFIO_MAPR2_TIM10_REMAP | + AFIO_REMAP_USE_MAPR2), /**< + Timer 10 remapping */ + AFIO_REMAP_TIM9 = (AFIO_MAPR2_TIM9_REMAP | + AFIO_REMAP_USE_MAPR2) /**< + Timer 9 */ +} afio_remap_peripheral; + +void afio_remap(afio_remap_peripheral p); + +/** + * @brief Debug port configuration + * + * Used to configure the behavior of JTAG and Serial Wire (SW) debug + * ports and their associated GPIO pins. + * + * @see afio_cfg_debug_ports() + */ +typedef enum afio_debug_cfg { + AFIO_DEBUG_FULL_SWJ = AFIO_MAPR_SWJ_CFG_FULL_SWJ, /**< + Full Serial Wire and JTAG debug */ + AFIO_DEBUG_FULL_SWJ_NO_NJRST = AFIO_MAPR_SWJ_CFG_FULL_SWJ_NO_NJRST, /**< + Full Serial Wire and JTAG, but no NJTRST. */ + AFIO_DEBUG_SW_ONLY = AFIO_MAPR_SWJ_CFG_NO_JTAG_SW, /**< + Serial Wire debug only (JTAG-DP disabled, + SW-DP enabled) */ + AFIO_DEBUG_NONE = AFIO_MAPR_SWJ_CFG_NO_JTAG_NO_SW /**< + No debug; all JTAG and SW pins are free + for use as GPIOs. */ +} afio_debug_cfg; + +/** + * @brief Enable or disable the JTAG and SW debug ports. + * @param config Desired debug port configuration + * @see afio_debug_cfg + */ +static inline void afio_cfg_debug_ports(afio_debug_cfg config) { + __io uint32 *mapr = &AFIO_BASE->MAPR; + *mapr = (*mapr & ~AFIO_MAPR_SWJ_CFG) | config; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libmaple/stm32f1/include/series/nvic.h b/libmaple/stm32f1/include/series/nvic.h new file mode 100644 index 0000000..69fd945 --- /dev/null +++ b/libmaple/stm32f1/include/series/nvic.h @@ -0,0 +1,139 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Perry Hung. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/nvic.h + * @brief STM32F1 Nested Vectored Interrupt Controller (NVIC) support. + */ + +#ifndef _LIBMAPLE_STM32F1_NVIC_H_ +#define _LIBMAPLE_STM32F1_NVIC_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include + +/** + * @brief Interrupt vector table interrupt numbers. + * @see + */ +typedef enum nvic_irq_num { + NVIC_NMI = -14, /**< Non-maskable interrupt */ + NVIC_HARDFAULT = -13, /**< Hard fault (all class of fault) */ + NVIC_MEM_MANAGE = -12, /**< Memory management */ + NVIC_BUS_FAULT = -11, /**< Bus fault: prefetch fault, memory + access fault. */ + NVIC_USAGE_FAULT = -10, /**< Usage fault: Undefined instruction or + illegal state. */ + NVIC_SVC = -5, /**< System service call via SWI insruction */ + NVIC_DEBUG_MON = -4, /**< Debug monitor */ + NVIC_PEND_SVC = -2, /**< Pendable request for system service */ + NVIC_SYSTICK = -1, /**< System tick timer */ + NVIC_WWDG = 0, /**< Window watchdog interrupt */ + NVIC_PVD = 1, /**< PVD through EXTI line detection */ + NVIC_TAMPER = 2, /**< Tamper */ + NVIC_RTC = 3, /**< Real-time clock */ + NVIC_FLASH = 4, /**< Flash */ + NVIC_RCC = 5, /**< Reset and clock control */ + NVIC_EXTI0 = 6, /**< EXTI line 0 */ + NVIC_EXTI1 = 7, /**< EXTI line 1 */ + NVIC_EXTI2 = 8, /**< EXTI line 2 */ + NVIC_EXTI3 = 9, /**< EXTI line 3 */ + NVIC_EXTI4 = 10, /**< EXTI line 4 */ + NVIC_DMA_CH1 = 11, /**< DMA1 channel 1 */ + NVIC_DMA_CH2 = 12, /**< DMA1 channel 2 */ + NVIC_DMA_CH3 = 13, /**< DMA1 channel 3 */ + NVIC_DMA_CH4 = 14, /**< DMA1 channel 4 */ + NVIC_DMA_CH5 = 15, /**< DMA1 channel 5 */ + NVIC_DMA_CH6 = 16, /**< DMA1 channel 6 */ + NVIC_DMA_CH7 = 17, /**< DMA1 channel 7 */ + NVIC_ADC_1_2 = 18, /**< ADC1 and ADC2 */ + NVIC_USB_HP_CAN_TX = 19, /**< USB high priority or CAN TX */ + NVIC_USB_LP_CAN_RX0 = 20, /**< USB low priority or CAN RX0 */ + NVIC_CAN_RX1 = 21, /**< CAN RX1 */ + NVIC_CAN_SCE = 22, /**< CAN SCE */ + NVIC_EXTI_9_5 = 23, /**< EXTI line [9:5] */ + NVIC_TIMER1_BRK = 24, /**< Timer 1 break */ + NVIC_TIMER1_UP = 25, /**< Timer 1 update */ + NVIC_TIMER1_TRG_COM = 26, /**< Timer 1 trigger and commutation */ + NVIC_TIMER1_CC = 27, /**< Timer 1 capture/compare */ + NVIC_TIMER2 = 28, /**< Timer 2 */ + NVIC_TIMER3 = 29, /**< Timer 3 */ + NVIC_TIMER4 = 30, /**< Timer 4 */ + NVIC_I2C1_EV = 31, /**< I2C1 event */ + NVIC_I2C1_ER = 32, /**< I2C1 error */ + NVIC_I2C2_EV = 33, /**< I2C2 event */ + NVIC_I2C2_ER = 34, /**< I2C2 error */ + NVIC_SPI1 = 35, /**< SPI1 */ + NVIC_SPI2 = 36, /**< SPI2 */ + NVIC_USART1 = 37, /**< USART1 */ + NVIC_USART2 = 38, /**< USART2 */ + NVIC_USART3 = 39, /**< USART3 */ + NVIC_EXTI_15_10 = 40, /**< EXTI line [15:10] */ + NVIC_RTCALARM = 41, /**< RTC alarm through EXTI line */ + NVIC_USBWAKEUP = 42, /**< USB wakeup from suspend through + EXTI line */ + NVIC_TIMER8_BRK = 43, /**< Timer 8 break */ + NVIC_TIMER8_UP = 44, /**< Timer 8 update */ + NVIC_TIMER8_TRG_COM = 45, /**< Timer 8 trigger and commutation */ + NVIC_TIMER8_CC = 46, /**< Timer 8 capture/compare */ +#ifdef STM32_HIGH_DENSITY + NVIC_ADC3 = 47, /**< ADC3 */ + NVIC_FSMC = 48, /**< FSMC */ + NVIC_SDIO = 49, /**< SDIO */ + NVIC_TIMER5 = 50, /**< Timer 5 */ + NVIC_SPI3 = 51, /**< SPI3 */ + NVIC_UART4 = 52, /**< UART4 */ + NVIC_UART5 = 53, /**< UART5 */ + NVIC_TIMER6 = 54, /**< Timer 6 */ + NVIC_TIMER7 = 55, /**< Timer 7 */ + NVIC_DMA2_CH1 = 56, /**< DMA2 channel 1 */ + NVIC_DMA2_CH2 = 57, /**< DMA2 channel 2 */ + NVIC_DMA2_CH3 = 58, /**< DMA2 channel 3 */ + NVIC_DMA2_CH_4_5 = 59, /**< DMA2 channels 4 and 5 */ +#endif +} nvic_irq_num; + +static inline void nvic_irq_disable_all(void) { + /* Note: This only works up to XL density. The fix for + * connectivity line is: + * + * NVIC_BASE->ICER[2] = 0xF; + * + * We don't support connectivity line devices (yet), so leave it + * alone for now. + */ + NVIC_BASE->ICER[0] = 0xFFFFFFFF; + NVIC_BASE->ICER[1] = 0xFFFFFFFF; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libmaple/stm32f1/include/series/rcc.h b/libmaple/stm32f1/include/series/rcc.h new file mode 100644 index 0000000..261dc5d --- /dev/null +++ b/libmaple/stm32f1/include/series/rcc.h @@ -0,0 +1,553 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Perry Hung. + * Copyright (c) 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/rcc.h + * @brief STM32F1 reset and clock control (RCC) header. + */ + +#ifndef _LIBMAPLE_STM32F1_RCC_H_ +#define _LIBMAPLE_STM32F1_RCC_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +/* + * Register map + */ + +/** RCC register map type */ +typedef struct rcc_reg_map { + __io uint32 CR; /**< Clock control register */ + __io uint32 CFGR; /**< Clock configuration register */ + __io uint32 CIR; /**< Clock interrupt register */ + __io uint32 APB2RSTR; /**< APB2 peripheral reset register */ + __io uint32 APB1RSTR; /**< APB1 peripheral reset register */ + __io uint32 AHBENR; /**< AHB peripheral clock enable register */ + __io uint32 APB2ENR; /**< APB2 peripheral clock enable register */ + __io uint32 APB1ENR; /**< APB1 peripheral clock enable register */ + __io uint32 BDCR; /**< Backup domain control register */ + __io uint32 CSR; /**< Control/status register */ +} rcc_reg_map; + +/** RCC register map base pointer */ +#define RCC_BASE ((struct rcc_reg_map*)0x40021000) + +/* + * Register bit definitions + */ + +/* Clock control register */ + +#define RCC_CR_PLLRDY_BIT 25 +#define RCC_CR_PLLON_BIT 24 +#define RCC_CR_CSSON_BIT 19 +#define RCC_CR_HSEBYP_BIT 18 +#define RCC_CR_HSERDY_BIT 17 +#define RCC_CR_HSEON_BIT 16 +#define RCC_CR_HSIRDY_BIT 1 +#define RCC_CR_HSION_BIT 0 + +#define RCC_CR_PLLRDY BIT(RCC_CR_PLLRDY_BIT) +#define RCC_CR_PLLON BIT(RCC_CR_PLLON_BIT) +#define RCC_CR_CSSON BIT(RCC_CR_CSSON_BIT) +#define RCC_CR_HSEBYP BIT(RCC_CR_HSEBYP_BIT) +#define RCC_CR_HSERDY BIT(RCC_CR_HSERDY_BIT) +#define RCC_CR_HSEON BIT(RCC_CR_HSEON_BIT) +#define RCC_CR_HSICAL (0xFF << 8) +#define RCC_CR_HSITRIM (0x1F << 3) +#define RCC_CR_HSIRDY BIT(RCC_CR_HSIRDY_BIT) +#define RCC_CR_HSION BIT(RCC_CR_HSION_BIT) + +/* Clock configuration register */ + +#define RCC_CFGR_USBPRE_BIT 22 +#define RCC_CFGR_PLLXTPRE_BIT 17 +#define RCC_CFGR_PLLSRC_BIT 16 + +#define RCC_CFGR_MCO (0x3 << 24) +#define RCC_CFGR_USBPRE BIT(RCC_CFGR_USBPRE_BIT) +#define RCC_CFGR_PLLMUL (0xF << 18) +#define RCC_CFGR_PLLXTPRE BIT(RCC_CFGR_PLLXTPRE_BIT) +#define RCC_CFGR_PLLSRC BIT(RCC_CFGR_PLLSRC_BIT) +#define RCC_CFGR_ADCPRE (0x3 << 14) +#define RCC_CFGR_PPRE2 (0x7 << 11) +#define RCC_CFGR_PPRE1 (0x7 << 8) +#define RCC_CFGR_HPRE (0xF << 4) +#define RCC_CFGR_SWS (0x3 << 2) +#define RCC_CFGR_SWS_PLL (0x2 << 2) +#define RCC_CFGR_SWS_HSE (0x1 << 2) +#define RCC_CFGR_SW 0x3 +#define RCC_CFGR_SW_PLL 0x2 +#define RCC_CFGR_SW_HSE 0x1 + +/* Clock interrupt register */ + +#define RCC_CIR_CSSC_BIT 23 +#define RCC_CIR_PLLRDYC_BIT 20 +#define RCC_CIR_HSERDYC_BIT 19 +#define RCC_CIR_HSIRDYC_BIT 18 +#define RCC_CIR_LSERDYC_BIT 17 +#define RCC_CIR_LSIRDYC_BIT 16 +#define RCC_CIR_PLLRDYIE_BIT 12 +#define RCC_CIR_HSERDYIE_BIT 11 +#define RCC_CIR_HSIRDYIE_BIT 10 +#define RCC_CIR_LSERDYIE_BIT 9 +#define RCC_CIR_LSIRDYIE_BIT 8 +#define RCC_CIR_CSSF_BIT 7 +#define RCC_CIR_PLLRDYF_BIT 4 +#define RCC_CIR_HSERDYF_BIT 3 +#define RCC_CIR_HSIRDYF_BIT 2 +#define RCC_CIR_LSERDYF_BIT 1 +#define RCC_CIR_LSIRDYF_BIT 0 + +#define RCC_CIR_CSSC BIT(RCC_CIR_CSSC_BIT) +#define RCC_CIR_PLLRDYC BIT(RCC_CIR_PLLRDYC_BIT) +#define RCC_CIR_HSERDYC BIT(RCC_CIR_HSERDYC_BIT) +#define RCC_CIR_HSIRDYC BIT(RCC_CIR_HSIRDYC_BIT) +#define RCC_CIR_LSERDYC BIT(RCC_CIR_LSERDYC_BIT) +#define RCC_CIR_LSIRDYC BIT(RCC_CIR_LSIRDYC_BIT) +#define RCC_CIR_PLLRDYIE BIT(RCC_CIR_PLLRDYIE_BIT) +#define RCC_CIR_HSERDYIE BIT(RCC_CIR_HSERDYIE_BIT) +#define RCC_CIR_HSIRDYIE BIT(RCC_CIR_HSIRDYIE_BIT) +#define RCC_CIR_LSERDYIE BIT(RCC_CIR_LSERDYIE_BIT) +#define RCC_CIR_LSIRDYIE BIT(RCC_CIR_LSIRDYIE_BIT) +#define RCC_CIR_CSSF BIT(RCC_CIR_CSSF_BIT) +#define RCC_CIR_PLLRDYF BIT(RCC_CIR_PLLRDYF_BIT) +#define RCC_CIR_HSERDYF BIT(RCC_CIR_HSERDYF_BIT) +#define RCC_CIR_HSIRDYF BIT(RCC_CIR_HSIRDYF_BIT) +#define RCC_CIR_LSERDYF BIT(RCC_CIR_LSERDYF_BIT) +#define RCC_CIR_LSIRDYF BIT(RCC_CIR_LSIRDYF_BIT) + +/* APB2 peripheral reset register */ + +#define RCC_APB2RSTR_TIM11RST_BIT 21 +#define RCC_APB2RSTR_TIM10RST_BIT 20 +#define RCC_APB2RSTR_TIM9RST_BIT 19 +#define RCC_APB2RSTR_ADC3RST_BIT 15 +#define RCC_APB2RSTR_USART1RST_BIT 14 +#define RCC_APB2RSTR_TIM8RST_BIT 13 +#define RCC_APB2RSTR_SPI1RST_BIT 12 +#define RCC_APB2RSTR_TIM1RST_BIT 11 +#define RCC_APB2RSTR_ADC2RST_BIT 10 +#define RCC_APB2RSTR_ADC1RST_BIT 9 +#define RCC_APB2RSTR_IOPGRST_BIT 8 +#define RCC_APB2RSTR_IOPFRST_BIT 7 +#define RCC_APB2RSTR_IOPERST_BIT 6 +#define RCC_APB2RSTR_IOPDRST_BIT 5 +#define RCC_APB2RSTR_IOPCRST_BIT 4 +#define RCC_APB2RSTR_IOPBRST_BIT 3 +#define RCC_APB2RSTR_IOPARST_BIT 2 +#define RCC_APB2RSTR_AFIORST_BIT 0 + +#define RCC_APB2RSTR_TIM11RST BIT(RCC_APB2RSTR_TIM11RST_BIT) +#define RCC_APB2RSTR_TIM10RST BIT(RCC_APB2RSTR_TIM10RST_BIT) +#define RCC_APB2RSTR_TIM9RST BIT(RCC_APB2RSTR_TIM9RST_BIT) +#define RCC_APB2RSTR_ADC3RST BIT(RCC_APB2RSTR_ADC3RST_BIT) +#define RCC_APB2RSTR_USART1RST BIT(RCC_APB2RSTR_USART1RST_BIT) +#define RCC_APB2RSTR_TIM8RST BIT(RCC_APB2RSTR_TIM8RST_BIT) +#define RCC_APB2RSTR_SPI1RST BIT(RCC_APB2RSTR_SPI1RST_BIT) +#define RCC_APB2RSTR_TIM1RST BIT(RCC_APB2RSTR_TIM1RST_BIT) +#define RCC_APB2RSTR_ADC2RST BIT(RCC_APB2RSTR_ADC2RST_BIT) +#define RCC_APB2RSTR_ADC1RST BIT(RCC_APB2RSTR_ADC1RST_BIT) +#define RCC_APB2RSTR_IOPGRST BIT(RCC_APB2RSTR_IOPGRST_BIT) +#define RCC_APB2RSTR_IOPFRST BIT(RCC_APB2RSTR_IOPFRST_BIT) +#define RCC_APB2RSTR_IOPERST BIT(RCC_APB2RSTR_IOPERST_BIT) +#define RCC_APB2RSTR_IOPDRST BIT(RCC_APB2RSTR_IOPDRST_BIT) +#define RCC_APB2RSTR_IOPCRST BIT(RCC_APB2RSTR_IOPCRST_BIT) +#define RCC_APB2RSTR_IOPBRST BIT(RCC_APB2RSTR_IOPBRST_BIT) +#define RCC_APB2RSTR_IOPARST BIT(RCC_APB2RSTR_IOPARST_BIT) +#define RCC_APB2RSTR_AFIORST BIT(RCC_APB2RSTR_AFIORST_BIT) + +/* APB1 peripheral reset register */ + +#define RCC_APB1RSTR_DACRST_BIT 29 +#define RCC_APB1RSTR_PWRRST_BIT 28 +#define RCC_APB1RSTR_BKPRST_BIT 27 +#define RCC_APB1RSTR_CANRST_BIT 25 +#define RCC_APB1RSTR_USBRST_BIT 23 +#define RCC_APB1RSTR_I2C2RST_BIT 22 +#define RCC_APB1RSTR_I2C1RST_BIT 21 +#define RCC_APB1RSTR_UART5RST_BIT 20 +#define RCC_APB1RSTR_UART4RST_BIT 19 +#define RCC_APB1RSTR_USART3RST_BIT 18 +#define RCC_APB1RSTR_USART2RST_BIT 17 +#define RCC_APB1RSTR_SPI3RST_BIT 15 +#define RCC_APB1RSTR_SPI2RST_BIT 14 +#define RCC_APB1RSTR_WWDRST_BIT 11 +#define RCC_APB1RSTR_TIM14RST_BIT 8 +#define RCC_APB1RSTR_TIM13RST_BIT 7 +#define RCC_APB1RSTR_TIM12RST_BIT 6 +#define RCC_APB1RSTR_TIM7RST_BIT 5 +#define RCC_APB1RSTR_TIM6RST_BIT 4 +#define RCC_APB1RSTR_TIM5RST_BIT 3 +#define RCC_APB1RSTR_TIM4RST_BIT 2 +#define RCC_APB1RSTR_TIM3RST_BIT 1 +#define RCC_APB1RSTR_TIM2RST_BIT 0 + +#define RCC_APB1RSTR_DACRST BIT(RCC_APB1RSTR_DACRST_BIT) +#define RCC_APB1RSTR_PWRRST BIT(RCC_APB1RSTR_PWRRST_BIT) +#define RCC_APB1RSTR_BKPRST BIT(RCC_APB1RSTR_BKPRST_BIT) +#define RCC_APB1RSTR_CANRST BIT(RCC_APB1RSTR_CANRST_BIT) +#define RCC_APB1RSTR_USBRST BIT(RCC_APB1RSTR_USBRST_BIT) +#define RCC_APB1RSTR_I2C2RST BIT(RCC_APB1RSTR_I2C2RST_BIT) +#define RCC_APB1RSTR_I2C1RST BIT(RCC_APB1RSTR_I2C1RST_BIT) +#define RCC_APB1RSTR_UART5RST BIT(RCC_APB1RSTR_UART5RST_BIT) +#define RCC_APB1RSTR_UART4RST BIT(RCC_APB1RSTR_UART4RST_BIT) +#define RCC_APB1RSTR_USART3RST BIT(RCC_APB1RSTR_USART3RST_BIT) +#define RCC_APB1RSTR_USART2RST BIT(RCC_APB1RSTR_USART2RST_BIT) +#define RCC_APB1RSTR_SPI3RST BIT(RCC_APB1RSTR_SPI3RST_BIT) +#define RCC_APB1RSTR_SPI2RST BIT(RCC_APB1RSTR_SPI2RST_BIT) +#define RCC_APB1RSTR_WWDRST BIT(RCC_APB1RSTR_WWDRST_BIT) +#define RCC_APB1RSTR_TIM14RST BIT(RCC_APB1RSTR_TIM14RST_BIT) +#define RCC_APB1RSTR_TIM13RST BIT(RCC_APB1RSTR_TIM13RST_BIT) +#define RCC_APB1RSTR_TIM12RST BIT(RCC_APB1RSTR_TIM12RST_BIT) +#define RCC_APB1RSTR_TIM7RST BIT(RCC_APB1RSTR_TIM7RST_BIT) +#define RCC_APB1RSTR_TIM6RST BIT(RCC_APB1RSTR_TIM6RST_BIT) +#define RCC_APB1RSTR_TIM5RST BIT(RCC_APB1RSTR_TIM5RST_BIT) +#define RCC_APB1RSTR_TIM4RST BIT(RCC_APB1RSTR_TIM4RST_BIT) +#define RCC_APB1RSTR_TIM3RST BIT(RCC_APB1RSTR_TIM3RST_BIT) +#define RCC_APB1RSTR_TIM2RST BIT(RCC_APB1RSTR_TIM2RST_BIT) + +/* AHB peripheral clock enable register */ + +#define RCC_AHBENR_SDIOEN_BIT 10 +#define RCC_AHBENR_FSMCEN_BIT 8 +#define RCC_AHBENR_CRCEN_BIT 7 +#define RCC_AHBENR_FLITFEN_BIT 4 +#define RCC_AHBENR_SRAMEN_BIT 2 +#define RCC_AHBENR_DMA2EN_BIT 1 +#define RCC_AHBENR_DMA1EN_BIT 0 + +#define RCC_AHBENR_SDIOEN BIT(RCC_AHBENR_SDIOEN_BIT) +#define RCC_AHBENR_FSMCEN BIT(RCC_AHBENR_FSMCEN_BIT) +#define RCC_AHBENR_CRCEN BIT(RCC_AHBENR_CRCEN_BIT) +#define RCC_AHBENR_FLITFEN BIT(RCC_AHBENR_FLITFEN_BIT) +#define RCC_AHBENR_SRAMEN BIT(RCC_AHBENR_SRAMEN_BIT) +#define RCC_AHBENR_DMA2EN BIT(RCC_AHBENR_DMA2EN_BIT) +#define RCC_AHBENR_DMA1EN BIT(RCC_AHBENR_DMA1EN_BIT) + +/* APB2 peripheral clock enable register */ + +#define RCC_APB2ENR_TIM11EN_BIT 21 +#define RCC_APB2ENR_TIM10EN_BIT 20 +#define RCC_APB2ENR_TIM9EN_BIT 19 +#define RCC_APB2ENR_ADC3EN_BIT 15 +#define RCC_APB2ENR_USART1EN_BIT 14 +#define RCC_APB2ENR_TIM8EN_BIT 13 +#define RCC_APB2ENR_SPI1EN_BIT 12 +#define RCC_APB2ENR_TIM1EN_BIT 11 +#define RCC_APB2ENR_ADC2EN_BIT 10 +#define RCC_APB2ENR_ADC1EN_BIT 9 +#define RCC_APB2ENR_IOPGEN_BIT 8 +#define RCC_APB2ENR_IOPFEN_BIT 7 +#define RCC_APB2ENR_IOPEEN_BIT 6 +#define RCC_APB2ENR_IOPDEN_BIT 5 +#define RCC_APB2ENR_IOPCEN_BIT 4 +#define RCC_APB2ENR_IOPBEN_BIT 3 +#define RCC_APB2ENR_IOPAEN_BIT 2 +#define RCC_APB2ENR_AFIOEN_BIT 0 + +#define RCC_APB2ENR_TIM11EN BIT(RCC_APB2ENR_TIM11EN_BIT) +#define RCC_APB2ENR_TIM10EN BIT(RCC_APB2ENR_TIM10EN_BIT) +#define RCC_APB2ENR_TIM9EN BIT(RCC_APB2ENR_TIM9EN_BIT) +#define RCC_APB2ENR_ADC3EN BIT(RCC_APB2ENR_ADC3EN_BIT) +#define RCC_APB2ENR_USART1EN BIT(RCC_APB2ENR_USART1EN_BIT) +#define RCC_APB2ENR_TIM8EN BIT(RCC_APB2ENR_TIM8EN_BIT) +#define RCC_APB2ENR_SPI1EN BIT(RCC_APB2ENR_SPI1EN_BIT) +#define RCC_APB2ENR_TIM1EN BIT(RCC_APB2ENR_TIM1EN_BIT) +#define RCC_APB2ENR_ADC2EN BIT(RCC_APB2ENR_ADC2EN_BIT) +#define RCC_APB2ENR_ADC1EN BIT(RCC_APB2ENR_ADC1EN_BIT) +#define RCC_APB2ENR_IOPGEN BIT(RCC_APB2ENR_IOPGEN_BIT) +#define RCC_APB2ENR_IOPFEN BIT(RCC_APB2ENR_IOPFEN_BIT) +#define RCC_APB2ENR_IOPEEN BIT(RCC_APB2ENR_IOPEEN_BIT) +#define RCC_APB2ENR_IOPDEN BIT(RCC_APB2ENR_IOPDEN_BIT) +#define RCC_APB2ENR_IOPCEN BIT(RCC_APB2ENR_IOPCEN_BIT) +#define RCC_APB2ENR_IOPBEN BIT(RCC_APB2ENR_IOPBEN_BIT) +#define RCC_APB2ENR_IOPAEN BIT(RCC_APB2ENR_IOPAEN_BIT) +#define RCC_APB2ENR_AFIOEN BIT(RCC_APB2ENR_AFIOEN_BIT) + +/* APB1 peripheral clock enable register */ + +#define RCC_APB1ENR_DACEN_BIT 29 +#define RCC_APB1ENR_PWREN_BIT 28 +#define RCC_APB1ENR_BKPEN_BIT 27 +#define RCC_APB1ENR_CANEN_BIT 25 +#define RCC_APB1ENR_USBEN_BIT 23 +#define RCC_APB1ENR_I2C2EN_BIT 22 +#define RCC_APB1ENR_I2C1EN_BIT 21 +#define RCC_APB1ENR_UART5EN_BIT 20 +#define RCC_APB1ENR_UART4EN_BIT 19 +#define RCC_APB1ENR_USART3EN_BIT 18 +#define RCC_APB1ENR_USART2EN_BIT 17 +#define RCC_APB1ENR_SPI3EN_BIT 15 +#define RCC_APB1ENR_SPI2EN_BIT 14 +#define RCC_APB1ENR_WWDEN_BIT 11 +#define RCC_APB1ENR_TIM14EN_BIT 8 +#define RCC_APB1ENR_TIM13EN_BIT 7 +#define RCC_APB1ENR_TIM12EN_BIT 6 +#define RCC_APB1ENR_TIM7EN_BIT 5 +#define RCC_APB1ENR_TIM6EN_BIT 4 +#define RCC_APB1ENR_TIM5EN_BIT 3 +#define RCC_APB1ENR_TIM4EN_BIT 2 +#define RCC_APB1ENR_TIM3EN_BIT 1 +#define RCC_APB1ENR_TIM2EN_BIT 0 + +#define RCC_APB1ENR_DACEN BIT(RCC_APB1ENR_DACEN_BIT) +#define RCC_APB1ENR_PWREN BIT(RCC_APB1ENR_PWREN_BIT) +#define RCC_APB1ENR_BKPEN BIT(RCC_APB1ENR_BKPEN_BIT) +#define RCC_APB1ENR_CANEN BIT(RCC_APB1ENR_CANEN_BIT) +#define RCC_APB1ENR_USBEN BIT(RCC_APB1ENR_USBEN_BIT) +#define RCC_APB1ENR_I2C2EN BIT(RCC_APB1ENR_I2C2EN_BIT) +#define RCC_APB1ENR_I2C1EN BIT(RCC_APB1ENR_I2C1EN_BIT) +#define RCC_APB1ENR_UART5EN BIT(RCC_APB1ENR_UART5EN_BIT) +#define RCC_APB1ENR_UART4EN BIT(RCC_APB1ENR_UART4EN_BIT) +#define RCC_APB1ENR_USART3EN BIT(RCC_APB1ENR_USART3EN_BIT) +#define RCC_APB1ENR_USART2EN BIT(RCC_APB1ENR_USART2EN_BIT) +#define RCC_APB1ENR_SPI3EN BIT(RCC_APB1ENR_SPI3EN_BIT) +#define RCC_APB1ENR_SPI2EN BIT(RCC_APB1ENR_SPI2EN_BIT) +#define RCC_APB1ENR_WWDEN BIT(RCC_APB1ENR_WWDEN_BIT) +#define RCC_APB1ENR_TIM14EN BIT(RCC_APB1ENR_TIM14EN_BIT) +#define RCC_APB1ENR_TIM13EN BIT(RCC_APB1ENR_TIM13EN_BIT) +#define RCC_APB1ENR_TIM12EN BIT(RCC_APB1ENR_TIM12EN_BIT) +#define RCC_APB1ENR_TIM7EN BIT(RCC_APB1ENR_TIM7EN_BIT) +#define RCC_APB1ENR_TIM6EN BIT(RCC_APB1ENR_TIM6EN_BIT) +#define RCC_APB1ENR_TIM5EN BIT(RCC_APB1ENR_TIM5EN_BIT) +#define RCC_APB1ENR_TIM4EN BIT(RCC_APB1ENR_TIM4EN_BIT) +#define RCC_APB1ENR_TIM3EN BIT(RCC_APB1ENR_TIM3EN_BIT) +#define RCC_APB1ENR_TIM2EN BIT(RCC_APB1ENR_TIM2EN_BIT) + +/* Backup domain control register */ + +#define RCC_BDCR_BDRST_BIT 16 +#define RCC_BDCR_RTCEN_BIT 15 +#define RCC_BDCR_LSEBYP_BIT 2 +#define RCC_BDCR_LSERDY_BIT 1 +#define RCC_BDCR_LSEON_BIT 0 + +#define RCC_BDCR_BDRST BIT(RCC_BDCR_BDRST_BIT) +#define RCC_BDCR_RTCEN BIT(RCC_BDCR_RTC_BIT) +#define RCC_BDCR_RTCSEL (0x3 << 8) +#define RCC_BDCR_RTCSEL_NONE (0x0 << 8) +#define RCC_BDCR_RTCSEL_LSE (0x1 << 8) +#define RCC_BDCR_RTCSEL_HSE (0x3 << 8) +#define RCC_BDCR_LSEBYP BIT(RCC_BDCR_LSEBYP_BIT) +#define RCC_BDCR_LSERDY BIT(RCC_BDCR_LSERDY_BIT) +#define RCC_BDCR_LSEON BIT(RCC_BDCR_LSEON_BIT) + +/* Control/status register */ + +#define RCC_CSR_LPWRRSTF_BIT 31 +#define RCC_CSR_WWDGRSTF_BIT 30 +#define RCC_CSR_IWDGRSTF_BIT 29 +#define RCC_CSR_SFTRSTF_BIT 28 +#define RCC_CSR_PORRSTF_BIT 27 +#define RCC_CSR_PINRSTF_BIT 26 +#define RCC_CSR_RMVF_BIT 24 +#define RCC_CSR_LSIRDY_BIT 1 +#define RCC_CSR_LSION_BIT 0 + +#define RCC_CSR_LPWRRSTF BIT(RCC_CSR_LPWRRSTF_BIT) +#define RCC_CSR_WWDGRSTF BIT(RCC_CSR_WWDGRSTF_BIT) +#define RCC_CSR_IWDGRSTF BIT(RCC_CSR_IWDGRSTF_BIT) +#define RCC_CSR_SFTRSTF BIT(RCC_CSR_SFTRSTF_BIT) +#define RCC_CSR_PORRSTF BIT(RCC_CSR_PORRSTF_BIT) +#define RCC_CSR_PINRSTF BIT(RCC_CSR_PINRSTF_BIT) +#define RCC_CSR_RMVF BIT(RCC_CSR_RMVF_BIT) +#define RCC_CSR_LSIRDY BIT(RCC_CSR_LSIRDY_BIT) +#define RCC_CSR_LSION BIT(RCC_CSR_LSION_BIT) + +/* + * Other types + */ + +/** + * @brief Identifies bus and clock line for a peripheral. + * + * Also generally useful as a unique identifier for that peripheral + * (or its corresponding device struct). + */ +typedef enum rcc_clk_id { + RCC_GPIOA, + RCC_GPIOB, + RCC_GPIOC, + RCC_GPIOD, + RCC_AFIO, + RCC_ADC1, + RCC_ADC2, + RCC_ADC3, + RCC_USART1, + RCC_USART2, + RCC_USART3, + RCC_TIMER1, + RCC_TIMER2, + RCC_TIMER3, + RCC_TIMER4, + RCC_SPI1, + RCC_SPI2, + RCC_DMA1, + RCC_PWR, + RCC_BKP, + RCC_I2C1, + RCC_I2C2, + RCC_CRC, + RCC_FLITF, + RCC_SRAM, + RCC_USB, +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) + RCC_GPIOE, + RCC_GPIOF, + RCC_GPIOG, + RCC_UART4, + RCC_UART5, + RCC_TIMER5, + RCC_TIMER6, + RCC_TIMER7, + RCC_TIMER8, + RCC_FSMC, + RCC_DAC, + RCC_DMA2, + RCC_SDIO, + RCC_SPI3, +#endif +#ifdef STM32_XL_DENSITY + RCC_TIMER9, + RCC_TIMER10, + RCC_TIMER11, + RCC_TIMER12, + RCC_TIMER13, + RCC_TIMER14, +#endif +} rcc_clk_id; + +/** + * PLL multipliers + * @see rcc_clk_init() + */ +typedef enum rcc_pll_multiplier { + RCC_PLLMUL_2 = (0x0 << 18), + RCC_PLLMUL_3 = (0x1 << 18), + RCC_PLLMUL_4 = (0x2 << 18), + RCC_PLLMUL_5 = (0x3 << 18), + RCC_PLLMUL_6 = (0x4 << 18), + RCC_PLLMUL_7 = (0x5 << 18), + RCC_PLLMUL_8 = (0x6 << 18), + RCC_PLLMUL_9 = (0x7 << 18), + RCC_PLLMUL_10 = (0x8 << 18), + RCC_PLLMUL_11 = (0x9 << 18), + RCC_PLLMUL_12 = (0xA << 18), + RCC_PLLMUL_13 = (0xB << 18), + RCC_PLLMUL_14 = (0xC << 18), + RCC_PLLMUL_15 = (0xD << 18), + RCC_PLLMUL_16 = (0xE << 18), +} rcc_pll_multiplier; + +/** + * PLL entry clock source + * @see rcc_clk_init() + */ +typedef enum rcc_pllsrc { + RCC_PLLSRC_HSE = (0x1 << 16), + RCC_PLLSRC_HSI_DIV_2 = (0x0 << 16) +} rcc_pllsrc; + +typedef enum rcc_clk_domain { + RCC_APB1, + RCC_APB2, + RCC_AHB +} rcc_clk_domain; + +/** + * Prescaler identifiers + * @see rcc_set_prescaler() + */ +typedef enum rcc_prescaler { + RCC_PRESCALER_AHB, + RCC_PRESCALER_APB1, + RCC_PRESCALER_APB2, + RCC_PRESCALER_USB, + RCC_PRESCALER_ADC +} rcc_prescaler; + +/** + * ADC prescaler dividers + * @see rcc_set_prescaler() + */ +typedef enum rcc_adc_divider { + RCC_ADCPRE_PCLK_DIV_2 = 0x0 << 14, + RCC_ADCPRE_PCLK_DIV_4 = 0x1 << 14, + RCC_ADCPRE_PCLK_DIV_6 = 0x2 << 14, + RCC_ADCPRE_PCLK_DIV_8 = 0x3 << 14, +} rcc_adc_divider; + +/** + * APB1 prescaler dividers + * @see rcc_set_prescaler() + */ +typedef enum rcc_apb1_divider { + RCC_APB1_HCLK_DIV_1 = 0x0 << 8, + RCC_APB1_HCLK_DIV_2 = 0x4 << 8, + RCC_APB1_HCLK_DIV_4 = 0x5 << 8, + RCC_APB1_HCLK_DIV_8 = 0x6 << 8, + RCC_APB1_HCLK_DIV_16 = 0x7 << 8, +} rcc_apb1_divider; + +/** + * APB2 prescaler dividers + * @see rcc_set_prescaler() + */ +typedef enum rcc_apb2_divider { + RCC_APB2_HCLK_DIV_1 = 0x0 << 11, + RCC_APB2_HCLK_DIV_2 = 0x4 << 11, + RCC_APB2_HCLK_DIV_4 = 0x5 << 11, + RCC_APB2_HCLK_DIV_8 = 0x6 << 11, + RCC_APB2_HCLK_DIV_16 = 0x7 << 11, +} rcc_apb2_divider; + +/** + * AHB prescaler dividers + * @see rcc_set_prescaler() + */ +typedef enum rcc_ahb_divider { + RCC_AHB_SYSCLK_DIV_1 = 0x0 << 4, + RCC_AHB_SYSCLK_DIV_2 = 0x8 << 4, + RCC_AHB_SYSCLK_DIV_4 = 0x9 << 4, + RCC_AHB_SYSCLK_DIV_8 = 0xA << 4, + RCC_AHB_SYSCLK_DIV_16 = 0xB << 4, + RCC_AHB_SYSCLK_DIV_32 = 0xC << 4, + RCC_AHB_SYSCLK_DIV_64 = 0xD << 4, + RCC_AHB_SYSCLK_DIV_128 = 0xD << 4, + RCC_AHB_SYSCLK_DIV_256 = 0xE << 4, + RCC_AHB_SYSCLK_DIV_512 = 0xF << 4, +} rcc_ahb_divider; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libmaple/stm32f1/include/series/stm32.h b/libmaple/stm32f1/include/series/stm32.h new file mode 100644 index 0000000..f0ca616 --- /dev/null +++ b/libmaple/stm32f1/include/series/stm32.h @@ -0,0 +1,100 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010, 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/stm32.h + * @brief STM32F1 chip- and series-specific definitions. + */ + +#ifndef _LIBMAPLE_STM32F1_H_ +#define _LIBMAPLE_STM32F1_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Clock configuration. + */ + +#ifndef STM32_PCLK1 +#define STM32_PCLK1 36000000U +#endif + +#ifndef STM32_PCLK2 +#define STM32_PCLK2 72000000U +#endif + +#ifndef STM32_DELAY_US_MULT +#define STM32_DELAY_US_MULT 12 /* FIXME: value is incorrect. */ +#endif + +/* + * Density-specific values. + */ + +#ifdef STM32_MEDIUM_DENSITY +# define STM32_NR_INTERRUPTS 43 +#elif defined(STM32_HIGH_DENSITY) +# define STM32_NR_INTERRUPTS 60 +#else +#error "Unsupported STM32F1 density, or no density specified. Add something " \ + "like -DSTM32_MEDIUM_DENSITY to your compiler arguments." +#endif + +/* + * MCU-specific values. + */ + +#if defined(MCU_STM32F103RB) +# define STM32_NR_GPIO_PORTS 4 +# define STM32_SRAM_END ((void*)0x20005000) + +#elif defined(MCU_STM32F103ZE) +# define STM32_NR_GPIO_PORTS 7 +# define STM32_SRAM_END ((void*)0x20010000) + +#elif defined(MCU_STM32F103CB) + /* This STM32_NR_GPIO_PORTS is not stricly true, but only pins 0 + * and exist, and they're used for OSC (e.g. on e.g. LeafLabs + * Maple Mini), so we'll live with this for now. */ +# define STM32_NR_GPIO_PORTS 3 +# define STM32_SRAM_END ((void*)0x20005000) + +#elif defined(MCU_STM32F103RE) +# define STM32_NR_GPIO_PORTS 4 +# define STM32_SRAM_END ((void*)0x20010000) + +#else +#error "Unrecognized STM32F1 MCU, or no MCU specified. Add something like " \ + "-DMCU_STM32F103RB to your compiler arguments." +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/support/ld/stm32/family/f1/performance/vector_symbols.inc b/support/ld/stm32/family/f1/performance/vector_symbols.inc deleted file mode 100644 index f8519bb..0000000 --- a/support/ld/stm32/family/f1/performance/vector_symbols.inc +++ /dev/null @@ -1,78 +0,0 @@ -EXTERN(__msp_init) -EXTERN(__exc_reset) -EXTERN(__exc_nmi) -EXTERN(__exc_hardfault) -EXTERN(__exc_memmanage) -EXTERN(__exc_busfault) -EXTERN(__exc_usagefault) -EXTERN(__stm32reservedexception7) -EXTERN(__stm32reservedexception8) -EXTERN(__stm32reservedexception9) -EXTERN(__stm32reservedexception10) -EXTERN(__exc_svc) -EXTERN(__exc_debug_monitor) -EXTERN(__stm32reservedexception13) -EXTERN(__exc_pendsv) -EXTERN(__exc_systick) - -EXTERN(__irq_wwdg) -EXTERN(__irq_pvd) -EXTERN(__irq_tamper) -EXTERN(__irq_rtc) -EXTERN(__irq_flash) -EXTERN(__irq_rcc) -EXTERN(__irq_exti0) -EXTERN(__irq_exti1) -EXTERN(__irq_exti2) -EXTERN(__irq_exti3) -EXTERN(__irq_exti4) -EXTERN(__irq_dma1_channel1) -EXTERN(__irq_dma1_channel2) -EXTERN(__irq_dma1_channel3) -EXTERN(__irq_dma1_channel4) -EXTERN(__irq_dma1_channel5) -EXTERN(__irq_dma1_channel6) -EXTERN(__irq_dma1_channel7) -EXTERN(__irq_adc) -EXTERN(__irq_usb_hp_can_tx) -EXTERN(__irq_usb_lp_can_rx0) -EXTERN(__irq_can_rx1) -EXTERN(__irq_can_sce) -EXTERN(__irq_exti9_5) -EXTERN(__irq_tim1_brk) -EXTERN(__irq_tim1_up) -EXTERN(__irq_tim1_trg_com) -EXTERN(__irq_tim1_cc) -EXTERN(__irq_tim2) -EXTERN(__irq_tim3) -EXTERN(__irq_tim4) -EXTERN(__irq_i2c1_ev) -EXTERN(__irq_i2c1_er) -EXTERN(__irq_i2c2_ev) -EXTERN(__irq_i2c2_er) -EXTERN(__irq_spi1) -EXTERN(__irq_spi2) -EXTERN(__irq_usart1) -EXTERN(__irq_usart2) -EXTERN(__irq_usart3) -EXTERN(__irq_exti15_10) -EXTERN(__irq_rtcalarm) -EXTERN(__irq_usbwakeup) - -EXTERN(__irq_tim8_brk) -EXTERN(__irq_tim8_up) -EXTERN(__irq_tim8_trg_com) -EXTERN(__irq_tim8_cc) -EXTERN(__irq_adc3) -EXTERN(__irq_fsmc) -EXTERN(__irq_sdio) -EXTERN(__irq_tim5) -EXTERN(__irq_spi3) -EXTERN(__irq_uart4) -EXTERN(__irq_uart5) -EXTERN(__irq_tim6) -EXTERN(__irq_tim7) -EXTERN(__irq_dma2_channel1) -EXTERN(__irq_dma2_channel2) -EXTERN(__irq_dma2_channel3) -EXTERN(__irq_dma2_channel4_5) diff --git a/support/ld/stm32/series/f1/performance/vector_symbols.inc b/support/ld/stm32/series/f1/performance/vector_symbols.inc new file mode 100644 index 0000000..f8519bb --- /dev/null +++ b/support/ld/stm32/series/f1/performance/vector_symbols.inc @@ -0,0 +1,78 @@ +EXTERN(__msp_init) +EXTERN(__exc_reset) +EXTERN(__exc_nmi) +EXTERN(__exc_hardfault) +EXTERN(__exc_memmanage) +EXTERN(__exc_busfault) +EXTERN(__exc_usagefault) +EXTERN(__stm32reservedexception7) +EXTERN(__stm32reservedexception8) +EXTERN(__stm32reservedexception9) +EXTERN(__stm32reservedexception10) +EXTERN(__exc_svc) +EXTERN(__exc_debug_monitor) +EXTERN(__stm32reservedexception13) +EXTERN(__exc_pendsv) +EXTERN(__exc_systick) + +EXTERN(__irq_wwdg) +EXTERN(__irq_pvd) +EXTERN(__irq_tamper) +EXTERN(__irq_rtc) +EXTERN(__irq_flash) +EXTERN(__irq_rcc) +EXTERN(__irq_exti0) +EXTERN(__irq_exti1) +EXTERN(__irq_exti2) +EXTERN(__irq_exti3) +EXTERN(__irq_exti4) +EXTERN(__irq_dma1_channel1) +EXTERN(__irq_dma1_channel2) +EXTERN(__irq_dma1_channel3) +EXTERN(__irq_dma1_channel4) +EXTERN(__irq_dma1_channel5) +EXTERN(__irq_dma1_channel6) +EXTERN(__irq_dma1_channel7) +EXTERN(__irq_adc) +EXTERN(__irq_usb_hp_can_tx) +EXTERN(__irq_usb_lp_can_rx0) +EXTERN(__irq_can_rx1) +EXTERN(__irq_can_sce) +EXTERN(__irq_exti9_5) +EXTERN(__irq_tim1_brk) +EXTERN(__irq_tim1_up) +EXTERN(__irq_tim1_trg_com) +EXTERN(__irq_tim1_cc) +EXTERN(__irq_tim2) +EXTERN(__irq_tim3) +EXTERN(__irq_tim4) +EXTERN(__irq_i2c1_ev) +EXTERN(__irq_i2c1_er) +EXTERN(__irq_i2c2_ev) +EXTERN(__irq_i2c2_er) +EXTERN(__irq_spi1) +EXTERN(__irq_spi2) +EXTERN(__irq_usart1) +EXTERN(__irq_usart2) +EXTERN(__irq_usart3) +EXTERN(__irq_exti15_10) +EXTERN(__irq_rtcalarm) +EXTERN(__irq_usbwakeup) + +EXTERN(__irq_tim8_brk) +EXTERN(__irq_tim8_up) +EXTERN(__irq_tim8_trg_com) +EXTERN(__irq_tim8_cc) +EXTERN(__irq_adc3) +EXTERN(__irq_fsmc) +EXTERN(__irq_sdio) +EXTERN(__irq_tim5) +EXTERN(__irq_spi3) +EXTERN(__irq_uart4) +EXTERN(__irq_uart5) +EXTERN(__irq_tim6) +EXTERN(__irq_tim7) +EXTERN(__irq_dma2_channel1) +EXTERN(__irq_dma2_channel2) +EXTERN(__irq_dma2_channel3) +EXTERN(__irq_dma2_channel4_5) diff --git a/support/make/target-config.mk b/support/make/target-config.mk index ea81b3b..2e360ea 100644 --- a/support/make/target-config.mk +++ b/support/make/target-config.mk @@ -53,14 +53,14 @@ TARGET_FLAGS += -DBOARD_$(BOARD) -DMCU_$(MCU) \ -DERROR_LED_PORT=$(ERROR_LED_PORT) \ -DERROR_LED_PIN=$(ERROR_LED_PIN) -# STM32 family-specific configuration values. +# STM32 series-specific configuration values. # NB: these only work for STM32F1 performance line chips, but those # are the only ones we support at this time. If you add support for # STM32F1 connectivity line MCUs or other STM32 families, this section # will need to change. -LD_FAMILY_PATH := $(LDDIR)/stm32/family/f1/performance -LIBMAPLE_MODULE_FAMILY := $(LIBMAPLE_PATH)/stm32f1 +LD_SERIES_PATH := $(LDDIR)/stm32/series/f1/performance +LIBMAPLE_MODULE_SERIES := $(LIBMAPLE_PATH)/stm32f1 # Memory target-specific configuration values -- cgit v1.2.3 From 9fadd89bd9ce6de5377a493f46ba5212097b2204 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Tue, 29 Nov 2011 15:54:59 -0500 Subject: Make BKP support STM32F1-only. - libmaple/bkp.h: Mark availability restriction. - Move libmaple/bkp.c to libmaple/stm32f1; adjust rules.mk files accordingly. Signed-off-by: Marti Bolivar --- libmaple/bkp.c | 129 ---------------------------------------- libmaple/include/libmaple/bkp.h | 2 +- libmaple/rules.mk | 1 - libmaple/stm32f1/bkp.c | 129 ++++++++++++++++++++++++++++++++++++++++ libmaple/stm32f1/rules.mk | 1 + 5 files changed, 131 insertions(+), 131 deletions(-) delete mode 100644 libmaple/bkp.c create mode 100644 libmaple/stm32f1/bkp.c (limited to 'libmaple/rules.mk') diff --git a/libmaple/bkp.c b/libmaple/bkp.c deleted file mode 100644 index 62783e7..0000000 --- a/libmaple/bkp.c +++ /dev/null @@ -1,129 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file bkp.c - * @brief Backup register support. - */ - -#include -#include -#include -#include - -static inline __io uint32* data_register(uint8 reg); - -bkp_dev bkp = { - .regs = BKP_BASE, -}; -/** Backup device. */ -const bkp_dev *BKP = &bkp; - -/** - * @brief Initialize backup interface. - * - * Enables the power and backup interface clocks, and resets the - * backup device. - */ -void bkp_init(void) { - /* Don't call pwr_init(), or you'll reset the device. We just - * need the clock. */ - rcc_clk_enable(RCC_PWR); - rcc_clk_enable(RCC_BKP); - rcc_reset_dev(RCC_BKP); -} - -/** - * Enable write access to the backup registers. Backup interface must - * be initialized for subsequent register writes to work. - * @see bkp_init() - */ -void bkp_enable_writes(void) { - *bb_perip(&PWR_BASE->CR, PWR_CR_DBP) = 1; -} - -/** - * Disable write access to the backup registers. - */ -void bkp_disable_writes(void) { - *bb_perip(&PWR_BASE->CR, PWR_CR_DBP) = 0; -} - -/** - * Read a value from given backup data register. - * @param reg Data register to read, from 1 to BKP_NR_DATA_REGS (10 on - * medium-density devices, 42 on high-density devices). - */ -uint16 bkp_read(uint8 reg) { - __io uint32* dr = data_register(reg); - if (!dr) { - ASSERT(0); /* nonexistent register */ - return 0; - } - return (uint16)*dr; -} - -/** - * @brief Write a value to given data register. - * - * Write access to backup registers must be enabled. - * - * @param reg Data register to write, from 1 to BKP_NR_DATA_REGS (10 - * on medium-density devices, 42 on high-density devices). - * @param val Value to write into the register. - * @see bkp_enable_writes() - */ -void bkp_write(uint8 reg, uint16 val) { - __io uint32* dr = data_register(reg); - if (!dr) { - ASSERT(0); /* nonexistent register */ - return; - } - *dr = (uint32)val; -} - -/* - * Data register memory layout is not contiguous. It's split up from - * 1--NR_LOW_DRS, beginning at BKP_BASE->DR1, through to - * (NR_LOW_DRS+1)--BKP_NR_DATA_REGS, beginning at BKP_BASE->DR11. - */ -#define NR_LOW_DRS 10 - -static inline __io uint32* data_register(uint8 reg) { - if (reg < 1 || reg > BKP_NR_DATA_REGS) { - return 0; - } - -#if BKP_NR_DATA_REGS == NR_LOW_DRS - return (uint32*)BKP_BASE + reg; -#else - if (reg <= NR_LOW_DRS) { - return (uint32*)BKP_BASE + reg; - } else { - return (uint32*)&(BKP_BASE->DR11) + (reg - NR_LOW_DRS - 1); - } -#endif -} diff --git a/libmaple/include/libmaple/bkp.h b/libmaple/include/libmaple/bkp.h index 92359b6..7f90c0c 100644 --- a/libmaple/include/libmaple/bkp.h +++ b/libmaple/include/libmaple/bkp.h @@ -26,7 +26,7 @@ /** * @file bkp.h - * @brief Backup register support. + * @brief Backup register support (STM32F1 only). */ #ifndef _LIBMAPLE_BKP_H_ diff --git a/libmaple/rules.mk b/libmaple/rules.mk index f0776a7..61d4edd 100644 --- a/libmaple/rules.mk +++ b/libmaple/rules.mk @@ -12,7 +12,6 @@ CFLAGS_$(d) = $(LIBMAPLE_PRIVATE_INCLUDES) $(LIBMAPLE_INCLUDES) -Wall -Werror # Local rules and targets cSRCS_$(d) := adc.c \ - bkp.c \ dac.c \ dma.c \ exti.c \ diff --git a/libmaple/stm32f1/bkp.c b/libmaple/stm32f1/bkp.c new file mode 100644 index 0000000..62783e7 --- /dev/null +++ b/libmaple/stm32f1/bkp.c @@ -0,0 +1,129 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file bkp.c + * @brief Backup register support. + */ + +#include +#include +#include +#include + +static inline __io uint32* data_register(uint8 reg); + +bkp_dev bkp = { + .regs = BKP_BASE, +}; +/** Backup device. */ +const bkp_dev *BKP = &bkp; + +/** + * @brief Initialize backup interface. + * + * Enables the power and backup interface clocks, and resets the + * backup device. + */ +void bkp_init(void) { + /* Don't call pwr_init(), or you'll reset the device. We just + * need the clock. */ + rcc_clk_enable(RCC_PWR); + rcc_clk_enable(RCC_BKP); + rcc_reset_dev(RCC_BKP); +} + +/** + * Enable write access to the backup registers. Backup interface must + * be initialized for subsequent register writes to work. + * @see bkp_init() + */ +void bkp_enable_writes(void) { + *bb_perip(&PWR_BASE->CR, PWR_CR_DBP) = 1; +} + +/** + * Disable write access to the backup registers. + */ +void bkp_disable_writes(void) { + *bb_perip(&PWR_BASE->CR, PWR_CR_DBP) = 0; +} + +/** + * Read a value from given backup data register. + * @param reg Data register to read, from 1 to BKP_NR_DATA_REGS (10 on + * medium-density devices, 42 on high-density devices). + */ +uint16 bkp_read(uint8 reg) { + __io uint32* dr = data_register(reg); + if (!dr) { + ASSERT(0); /* nonexistent register */ + return 0; + } + return (uint16)*dr; +} + +/** + * @brief Write a value to given data register. + * + * Write access to backup registers must be enabled. + * + * @param reg Data register to write, from 1 to BKP_NR_DATA_REGS (10 + * on medium-density devices, 42 on high-density devices). + * @param val Value to write into the register. + * @see bkp_enable_writes() + */ +void bkp_write(uint8 reg, uint16 val) { + __io uint32* dr = data_register(reg); + if (!dr) { + ASSERT(0); /* nonexistent register */ + return; + } + *dr = (uint32)val; +} + +/* + * Data register memory layout is not contiguous. It's split up from + * 1--NR_LOW_DRS, beginning at BKP_BASE->DR1, through to + * (NR_LOW_DRS+1)--BKP_NR_DATA_REGS, beginning at BKP_BASE->DR11. + */ +#define NR_LOW_DRS 10 + +static inline __io uint32* data_register(uint8 reg) { + if (reg < 1 || reg > BKP_NR_DATA_REGS) { + return 0; + } + +#if BKP_NR_DATA_REGS == NR_LOW_DRS + return (uint32*)BKP_BASE + reg; +#else + if (reg <= NR_LOW_DRS) { + return (uint32*)BKP_BASE + reg; + } else { + return (uint32*)&(BKP_BASE->DR11) + (reg - NR_LOW_DRS - 1); + } +#endif +} diff --git a/libmaple/stm32f1/rules.mk b/libmaple/stm32f1/rules.mk index 5267e9b..32b3a2c 100644 --- a/libmaple/stm32f1/rules.mk +++ b/libmaple/stm32f1/rules.mk @@ -14,6 +14,7 @@ sSRCS_$(d) := isrs_performance.S \ cSRCS_$(d) := rcc.c cSRCS_$(d) += flash.c cSRCS_$(d) += gpio.c +cSRCS_$(d) += bkp.c sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%) cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%) -- cgit v1.2.3 From 1ffbef80396cdb13a7976de0eefdc3017ca4499c Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Tue, 29 Nov 2011 16:16:05 -0500 Subject: [UNDO] Rip out a bunch of F1-only bits from libmaple proper We'll need to bring this functionality back online piecemeal as we add F2 support. Signed-off-by: Marti Bolivar --- Makefile | 2 +- libmaple/rules.mk | 13 +----------- libmaple/util.c | 62 ++++++++++++++++++++++++++++--------------------------- 3 files changed, 34 insertions(+), 43 deletions(-) (limited to 'libmaple/rules.mk') diff --git a/Makefile b/Makefile index 785b9a6..0784644 100644 --- a/Makefile +++ b/Makefile @@ -75,7 +75,7 @@ ifeq ($(LIBMAPLE_MODULES),) else LIBMAPLE_MODULES += $(SRCROOT)/libmaple endif -LIBMAPLE_MODULES += $(SRCROOT)/libmaple/usb # USB FS device +# LIBMAPLE_MODULES += $(SRCROOT)/libmaple/usb # USB FS device LIBMAPLE_MODULES += $(LIBMAPLE_MODULE_SERIES) # STM32 series submodule in libmaple LIBMAPLE_MODULES += $(SRCROOT)/wirish # Official libraries: diff --git a/libmaple/rules.mk b/libmaple/rules.mk index 61d4edd..8802161 100644 --- a/libmaple/rules.mk +++ b/libmaple/rules.mk @@ -11,23 +11,12 @@ LIBMAPLE_PRIVATE_INCLUDES := -I$(LIBMAPLE_PATH) CFLAGS_$(d) = $(LIBMAPLE_PRIVATE_INCLUDES) $(LIBMAPLE_INCLUDES) -Wall -Werror # Local rules and targets -cSRCS_$(d) := adc.c \ - dac.c \ - dma.c \ - exti.c \ - flash.c \ - fsmc.c \ +cSRCS_$(d) := flash.c \ gpio.c \ - iwdg.c \ nvic.c \ - pwr.c \ - i2c.c \ rcc.c \ - spi.c \ syscalls.c \ systick.c \ - timer.c \ - usart.c \ util.c sSRCS_$(d) := exc.S diff --git a/libmaple/util.c b/libmaple/util.c index 07e9572..96050a1 100644 --- a/libmaple/util.c +++ b/libmaple/util.c @@ -62,18 +62,18 @@ void __error(void) { /* Turn off peripheral interrupts */ nvic_irq_disable_all(); - /* Turn off timers */ - timer_disable_all(); + /* /\* Turn off timers *\/ */ + /* timer_disable_all(); */ - /* Turn off ADC */ - adc_disable_all(); + /* /\* Turn off ADC *\/ */ + /* adc_disable_all(); */ - /* Turn off all USARTs */ - usart_disable_all(); + /* /\* Turn off all USARTs *\/ */ + /* usart_disable_all(); */ - /* Turn the USB interrupt back on so the bootloader keeps on functioning */ - nvic_irq_enable(NVIC_USB_HP_CAN_TX); - nvic_irq_enable(NVIC_USB_LP_CAN_RX0); + /* /\* Turn the USB interrupt back on so the bootloader keeps on functioning *\/ */ + /* nvic_irq_enable(NVIC_USB_HP_CAN_TX); */ + /* nvic_irq_enable(NVIC_USB_LP_CAN_RX0); */ /* Reenable global interrupts */ nvic_globalirq_enable(); @@ -85,9 +85,9 @@ void __error(void) { * @sideeffect Configures ERROR_USART appropriately for writing. */ void _enable_error_usart() { - gpio_set_mode(ERROR_TX_PORT, ERROR_TX_PIN, GPIO_AF_OUTPUT_PP); - usart_init(ERROR_USART); - usart_set_baud_rate(ERROR_USART, ERROR_USART_CLK_SPEED, ERROR_USART_BAUD); + /* gpio_set_mode(ERROR_TX_PORT, ERROR_TX_PIN, GPIO_AF_OUTPUT_PP); */ + /* usart_init(ERROR_USART); */ + /* usart_set_baud_rate(ERROR_USART, ERROR_USART_CLK_SPEED, ERROR_USART_BAUD); */ } /** @@ -100,17 +100,17 @@ void _enable_error_usart() { */ void _fail(const char* file, int line, const char* exp) { /* Initialize the error USART */ - _enable_error_usart(); - - /* Print failed assert message */ - usart_putstr(ERROR_USART, "ERROR: FAILED ASSERT("); - usart_putstr(ERROR_USART, exp); - usart_putstr(ERROR_USART, "): "); - usart_putstr(ERROR_USART, file); - usart_putstr(ERROR_USART, ": "); - usart_putudec(ERROR_USART, line); - usart_putc(ERROR_USART, '\n'); - usart_putc(ERROR_USART, '\r'); + /* _enable_error_usart(); */ + + /* /\* Print failed assert message *\/ */ + /* usart_putstr(ERROR_USART, "ERROR: FAILED ASSERT("); */ + /* usart_putstr(ERROR_USART, exp); */ + /* usart_putstr(ERROR_USART, "): "); */ + /* usart_putstr(ERROR_USART, file); */ + /* usart_putstr(ERROR_USART, ": "); */ + /* usart_putudec(ERROR_USART, line); */ + /* usart_putc(ERROR_USART, '\n'); */ + /* usart_putc(ERROR_USART, '\r'); */ /* Shutdown and error fade */ __error(); @@ -130,14 +130,16 @@ void __assert_func(const char* file, int line, const char* method, * error state with the throbbing LED indicator. */ void abort() { - /* Initialize the error USART */ - _enable_error_usart(); + /* /\* Initialize the error USART *\/ */ + /* _enable_error_usart(); */ - /* Print abort message. */ - usart_putstr(ERROR_USART, "ERROR: PROGRAM ABORTED VIA abort()\n\r"); + /* /\* Print abort message. *\/ */ + /* usart_putstr(ERROR_USART, "ERROR: PROGRAM ABORTED VIA abort()\n\r"); */ - /* Shutdown and error fade */ - __error(); + /* /\* Shutdown and error fade *\/ */ + /* __error(); */ + while (1) + ; } /** @@ -145,7 +147,7 @@ void abort() { * @sideeffect Sets output push-pull on ERROR_LED_PIN. */ void throb(void) { -#ifdef HAVE_ERROR_LED +#if 0 int32 slope = 1; uint32 CC = 0x0000; uint32 TOP_CNT = 0x0200; -- cgit v1.2.3 From 117a6f118adb4540866beb5aba8afd8f98da139e Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Thu, 22 Mar 2012 16:01:51 -0400 Subject: Style change to libmaple/rules.mk. New style makes for cleaner diffs. Signed-off-by: Marti Bolivar --- libmaple/rules.mk | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'libmaple/rules.mk') diff --git a/libmaple/rules.mk b/libmaple/rules.mk index 8802161..abb6ab2 100644 --- a/libmaple/rules.mk +++ b/libmaple/rules.mk @@ -11,13 +11,13 @@ LIBMAPLE_PRIVATE_INCLUDES := -I$(LIBMAPLE_PATH) CFLAGS_$(d) = $(LIBMAPLE_PRIVATE_INCLUDES) $(LIBMAPLE_INCLUDES) -Wall -Werror # Local rules and targets -cSRCS_$(d) := flash.c \ - gpio.c \ - nvic.c \ - rcc.c \ - syscalls.c \ - systick.c \ - util.c +cSRCS_$(d) := flash.c +cSRCS_$(d) += gpio.c +cSRCS_$(d) += nvic.c +cSRCS_$(d) += rcc.c +cSRCS_$(d) += syscalls.c +cSRCS_$(d) += systick.c +cSRCS_$(d) += util.c sSRCS_$(d) := exc.S -- cgit v1.2.3 From eee763308a497105a1aa1aefd3c4b3124e8362b3 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Mon, 26 Mar 2012 15:42:25 -0400 Subject: [FIXME] Resurrected, shinier USART support. FIXME: - Test F1 support - Solve problem of duplicated bytes being TXed unless delay is inserted after configuration but before first bytes are TXed. Rip out nonportable bits from top-level interfaces. The USART register maps are basically the same between F1 and F2, so leave these, but add register bit definitions which had name changes to the libmaple header to avoid needless repetition. There are also a few new bits in the F2 USART registers; add definitions for these in the F2 USART header. Add Doxygen comments for all USART bit definitions. Deprecate struct usart_dev's max_baud field. This is just bloat that doesn't bring us much real benefit. Add new series-specific USART files for F1 and F2: - libmaple/stm32f[1,2]/usart.c - libmaple/stm32f[1,2]/include/series/usart.h These are standard series-specific files, providing register map base pointers, defining devices, implementing nonportable routines, etc. We need a portable way to configure the USART GPIOs. To this end, add usart_async_gpio_cfg() to the top-level USART interface. This function is implemented in new F1 and F2 USART backends to take the appropriate action to configure the RX and TX pins for asynchronous full duplex mode. USART baud rate calculation is done differently on the different series. Keep the usart_set_baud_rate() declaration in the top-level USART header, but move the implementations into the series-specific usart.c files. In usart_set_baud_rate(), allow for deriving clock_speed automatically by letting user tell us to figure out the peripheral clock speed by mapping the device's rcc_clk_id onto an STM32_PCLK[1,2] value. This preserves flexibility for users with non-default clock configurations, but makes things easier on everyone else. Add private USART files for portable private USART routines: - libmaple/usart_private.h - libmaple/usart_private.c Signed-off-by: Marti Bolivar --- libmaple/include/libmaple/usart.h | 229 ++++++++++++++++++++++++++------ libmaple/rules.mk | 2 + libmaple/stm32f1/include/series/usart.h | 76 +++++++++++ libmaple/stm32f1/rules.mk | 1 + libmaple/stm32f1/usart.c | 170 ++++++++++++++++++++++++ libmaple/stm32f2/include/series/usart.h | 103 ++++++++++++++ libmaple/stm32f2/rules.mk | 1 + libmaple/stm32f2/usart.c | 198 +++++++++++++++++++++++++++ libmaple/usart.c | 138 +------------------ libmaple/usart_private.c | 40 ++++++ libmaple/usart_private.h | 53 ++++++++ 11 files changed, 836 insertions(+), 175 deletions(-) create mode 100644 libmaple/stm32f1/include/series/usart.h create mode 100644 libmaple/stm32f1/usart.c create mode 100644 libmaple/stm32f2/include/series/usart.h create mode 100644 libmaple/stm32f2/usart.c create mode 100644 libmaple/usart_private.c create mode 100644 libmaple/usart_private.h (limited to 'libmaple/rules.mk') diff --git a/libmaple/include/libmaple/usart.h b/libmaple/include/libmaple/usart.h index f9bdb8b..42f9576 100644 --- a/libmaple/include/libmaple/usart.h +++ b/libmaple/include/libmaple/usart.h @@ -43,9 +43,10 @@ extern "C"{ #include #include #include +#include /* - * Register maps and devices + * Register map (common across supported STM32 series). */ /** USART register map type */ @@ -59,169 +60,315 @@ typedef struct usart_reg_map { __io uint32 GTPR; /**< Guard time and prescaler register */ } usart_reg_map; -/** USART1 register map base pointer */ -#define USART1_BASE ((struct usart_reg_map*)0x40013800) -/** USART2 register map base pointer */ -#define USART2_BASE ((struct usart_reg_map*)0x40004400) -/** USART3 register map base pointer */ -#define USART3_BASE ((struct usart_reg_map*)0x40004800) -#ifdef STM32_HIGH_DENSITY -/** UART4 register map base pointer */ -#define UART4_BASE ((struct usart_reg_map*)0x40004C00) -/** UART5 register map base pointer */ -#define UART5_BASE ((struct usart_reg_map*)0x40005000) -#endif - /* * Register bit definitions */ /* Status register */ +/** Clear to send bit */ #define USART_SR_CTS_BIT 9 +/** Line break detection bit */ #define USART_SR_LBD_BIT 8 +/** Transmit data register empty bit */ #define USART_SR_TXE_BIT 7 +/** Transmission complete bit */ #define USART_SR_TC_BIT 6 +/** Read data register not empty bit */ #define USART_SR_RXNE_BIT 5 +/** IDLE line detected bit */ #define USART_SR_IDLE_BIT 4 +/** Overrun error bit */ #define USART_SR_ORE_BIT 3 +/** Noise error bit */ #define USART_SR_NE_BIT 2 +/** + * @brief Synonym for USART_SR_NE_BIT. + * + * Some series (e.g. STM32F2) use "NF" for "noise flag" instead of the + * original "NE" for "noise error". The meaning of the bit is + * unchanged, but the NF flag can be disabled when the line is + * noise-free. + * + * @see USART_SR_NE_BIT + */ +#define USART_SR_NF_BIT USART_SR_NE_BIT +/** Framing error bit */ #define USART_SR_FE_BIT 1 +/** Parity error bit */ #define USART_SR_PE_BIT 0 +/** Clear to send mask */ #define USART_SR_CTS BIT(USART_SR_CTS_BIT) +/** Line break detected mask */ #define USART_SR_LBD BIT(USART_SR_LBD_BIT) +/** Transmit data register empty mask */ #define USART_SR_TXE BIT(USART_SR_TXE_BIT) +/** Transmission complete mask */ #define USART_SR_TC BIT(USART_SR_TC_BIT) +/** Read data register not empty mask */ #define USART_SR_RXNE BIT(USART_SR_RXNE_BIT) +/** IDLE line detected mask */ #define USART_SR_IDLE BIT(USART_SR_IDLE_BIT) +/** Overrun error mask */ #define USART_SR_ORE BIT(USART_SR_ORE_BIT) +/** Noise error mask */ #define USART_SR_NE BIT(USART_SR_NE_BIT) +/** + * @brief Synonym for USART_SR_NE. + * @see USART_SR_NF_BIT + */ +#define USART_SR_NF USART_SR_NE +/** Framing error mask */ #define USART_SR_FE BIT(USART_SR_FE_BIT) +/** Parity error mask */ #define USART_SR_PE BIT(USART_SR_PE_BIT) /* Data register */ +/** Data register data value mask */ #define USART_DR_DR 0xFF /* Baud rate register */ +/** Mantissa of USARTDIV mask */ #define USART_BRR_DIV_MANTISSA (0xFFF << 4) +/** Fraction of USARTDIV mask */ #define USART_BRR_DIV_FRACTION 0xF /* Control register 1 */ +/** USART enable bit */ #define USART_CR1_UE_BIT 13 +/** Word length bit */ #define USART_CR1_M_BIT 12 +/** Wakeup method bit */ #define USART_CR1_WAKE_BIT 11 +/** Parity control enable bit */ #define USART_CR1_PCE_BIT 10 +/** Parity selection bit */ #define USART_CR1_PS_BIT 9 +/** Parity error interrupt enable bit */ #define USART_CR1_PEIE_BIT 8 +/** Transmit data regsiter not empty interrupt enable bit */ #define USART_CR1_TXEIE_BIT 7 +/** Transmission complete interrupt enable bit */ #define USART_CR1_TCIE_BIT 6 +/** RXNE interrupt enable bit */ #define USART_CR1_RXNEIE_BIT 5 +/** IDLE interrupt enable bit */ #define USART_CR1_IDLEIE_BIT 4 +/** Transmitter enable bit */ #define USART_CR1_TE_BIT 3 +/** Receiver enable bit */ #define USART_CR1_RE_BIT 2 +/** Receiver wakeup bit */ #define USART_CR1_RWU_BIT 1 +/** Send break bit */ #define USART_CR1_SBK_BIT 0 +/** USART enable mask */ #define USART_CR1_UE BIT(USART_CR1_UE_BIT) +/** Word length mask */ #define USART_CR1_M BIT(USART_CR1_M_BIT) +/** Word length: 1 start bit, 8 data bits, n stop bit */ +#define USART_CR1_M_8N1 (0 << USART_CR1_M_BIT) +/** Word length: 1 start bit, 9 data bits, n stop bit */ +#define USART_CR1_M_9N1 (1 << USART_CR1_M_BIT) +/** Wakeup method mask */ #define USART_CR1_WAKE BIT(USART_CR1_WAKE_BIT) +/** Wakeup on idle line */ #define USART_CR1_WAKE_IDLE (0 << USART_CR1_WAKE_BIT) +/** Wakeup on address mark */ #define USART_CR1_WAKE_ADDR (1 << USART_CR1_WAKE_BIT) +/** Parity control enable mask */ #define USART_CR1_PCE BIT(USART_CR1_PCE_BIT) +/** Parity selection mask */ #define USART_CR1_PS BIT(USART_CR1_PS_BIT) +/** Parity selection: even parity */ #define USART_CR1_PS_EVEN (0 << USART_CR1_PS_BIT) +/** Parity selection: odd parity */ #define USART_CR1_PS_ODD (1 << USART_CR1_PS_BIT) +/** Parity error interrupt enable mask */ #define USART_CR1_PEIE BIT(USART_CR1_PEIE_BIT) +/** Transmit data register empty interrupt enable mask */ #define USART_CR1_TXEIE BIT(USART_CR1_TXEIE_BIT) +/** Transmission complete interrupt enable mask */ #define USART_CR1_TCIE BIT(USART_CR1_TCIE_BIT) +/** RXNE interrupt enable mask */ #define USART_CR1_RXNEIE BIT(USART_CR1_RXNEIE_BIT) +/** IDLE line interrupt enable mask */ #define USART_CR1_IDLEIE BIT(USART_CR1_IDLEIE_BIT) +/** Transmitter enable mask */ #define USART_CR1_TE BIT(USART_CR1_TE_BIT) +/** Receiver enable mask */ #define USART_CR1_RE BIT(USART_CR1_RE_BIT) +/** Receiver wakeup mask */ #define USART_CR1_RWU BIT(USART_CR1_RWU_BIT) +/** Receiver wakeup: receiver in active mode */ #define USART_CR1_RWU_ACTIVE (0 << USART_CR1_RWU_BIT) +/** Receiver wakeup: receiver in mute mode */ #define USART_CR1_RWU_MUTE (1 << USART_CR1_RWU_BIT) +/** Send break */ #define USART_CR1_SBK BIT(USART_CR1_SBK_BIT) /* Control register 2 */ +/** LIN mode enable bit */ #define USART_CR2_LINEN_BIT 14 +/** Clock enable bit */ #define USART_CR2_CLKEN_BIT 11 +/** Clock polarity bit */ #define USART_CR2_CPOL_BIT 10 +/** Clock phase bit */ #define USART_CR2_CPHA_BIT 9 +/** Last bit clock pulse bit */ #define USART_CR2_LBCL_BIT 8 +/** LIN break detection interrupt enable bit */ #define USART_CR2_LBDIE_BIT 6 +/** LIN break detection length bit */ #define USART_CR2_LBDL_BIT 5 +/** LIN mode enable mask */ #define USART_CR2_LINEN BIT(USART_CR2_LINEN_BIT) +/** STOP bits mask */ #define USART_CR2_STOP (0x3 << 12) +/** STOP bits: 1 stop bit */ #define USART_CR2_STOP_BITS_1 (0x0 << 12) -/* Not on UART4, UART5 */ +/** + * @brief STOP bits: 0.5 stop bits + * Not available on UART4, UART5. */ #define USART_CR2_STOP_BITS_POINT_5 (0x1 << 12) -/* Not on UART4, UART5 */ -#define USART_CR2_STOP_BITS_1_POINT_5 (0x3 << 12) +/** STOP bits: 2 stop bits */ #define USART_CR2_STOP_BITS_2 (0x2 << 12) +/** + * @brief STOP bits: 1.5 stop bits + * Not available on UART4, UART5. */ +#define USART_CR2_STOP_BITS_1_POINT_5 (0x3 << 12) +/** + * @brief Clock enable. + * Not available on UART4, UART5 */ #define USART_CR2_CLKEN BIT(USART_CR2_CLKEN_BIT) -/* Not on UART4, UART5 */ +/** + * @brief Clock polarity mask. + * Not available on UART4, UART5 */ #define USART_CR2_CPOL BIT(USART_CR2_CPOL_BIT) +/** Clock polarity: low */ #define USART_CR2_CPOL_LOW (0x0 << USART_CR2_CLKEN_BIT) +/** Clock polarity: high */ #define USART_CR2_CPOL_HIGH (0x1 << USART_CR2_CLKEN_BIT) -/* Not on UART4, UART5 */ +/** + * @brief Clock phase mask. + * Not available on UART4, UART5 */ #define USART_CR2_CPHA BIT(USART_CR2_CPHA_BIT) +/** + * @brief Clock phase: first + * First clock transition is the first data capture edge. */ #define USART_CR2_CPHA_FIRST (0x0 << USART_CR2_CPHA_BIT) +/** + * @brief Clock phase: second + * Second clock transition is the first data capture edge. */ #define USART_CR2_CPHA_SECOND (0x1 << USART_CR2_CPHA_BIT) -/* Not on UART4, UART5 */ +/** + * @brief Last bit clock pulse mask. + * + * When set, the last bit transmitted causes a clock pulse in + * synchronous mode. + * + * Not available on UART4, UART5 */ #define USART_CR2_LBCL BIT(USART_CR2_LBCL_BIT) +/** LIN break detection interrupt enable mask. */ #define USART_CR2_LBDIE BIT(USART_CR2_LBDIE_BIT) +/** LIN break detection length. */ #define USART_CR2_LBDL BIT(USART_CR2_LBDL_BIT) +/** LIN break detection length: 10 bits */ #define USART_CR2_LBDL_10_BIT (0 << USART_CR2_LBDL_BIT) +/** LIN break detection length: 11 bits */ #define USART_CR2_LBDL_11_BIT (1 << USART_CR2_LBDL_BIT) +/** + * @brief Address of the USART node + * This is useful during multiprocessor communication. */ #define USART_CR2_ADD 0xF /* Control register 3 */ +/** Clear to send interrupt enable bit */ #define USART_CR3_CTSIE_BIT 10 +/** Clear to send enable bit */ #define USART_CR3_CTSE_BIT 9 +/** Ready to send enable bit */ #define USART_CR3_RTSE_BIT 8 +/** DMA enable transmitter bit */ #define USART_CR3_DMAT_BIT 7 +/** DMA enable receiver bit */ #define USART_CR3_DMAR_BIT 6 +/** Smartcard mode enable bit */ #define USART_CR3_SCEN_BIT 5 +/** Smartcard NACK enable bit */ #define USART_CR3_NACK_BIT 4 +/** Half-duplex selection bit */ #define USART_CR3_HDSEL_BIT 3 +/** IrDA low power bit */ #define USART_CR3_IRLP_BIT 2 +/** IrDA mode enable bit */ #define USART_CR3_IREN_BIT 1 +/** Error interrupt enable bit */ #define USART_CR3_EIE_BIT 0 -/* Not on UART4, UART5 */ +/** + * @brief Clear to send interrupt enable + * Not available on UART4, UART5. */ #define USART_CR3_CTSIE BIT(USART_CR3_CTSIE_BIT) -/* Not on UART4, UART5 */ +/** + * @brief Clear to send enable + * Not available on UART4, UART5. */ #define USART_CR3_CTSE BIT(USART_CR3_CTSE_BIT) -/* Not on UART4, UART5 */ +/** + * @brief Ready to send enable + * Not available on UART4, UART5. */ #define USART_CR3_RTSE BIT(USART_CR3_RTSE_BIT) -/* Not on UART5 */ +/** + * @brief DMA enable transmitter + * Not available on UART5. */ #define USART_CR3_DMAT BIT(USART_CR3_DMAT_BIT) -/* Not on UART5 */ +/** + * @brief DMA enable receiver + * Not available on UART5. */ #define USART_CR3_DMAR BIT(USART_CR3_DMAR_BIT) -/* Not on UART4, UART5 */ +/** + * @brief Smartcard mode enable + * Not available on UART4, UART5. */ #define USART_CR3_SCEN BIT(USART_CR3_SCEN_BIT) -/* Not on UART4, UART5 */ +/** + * @brief Smartcard NACK enable + * Not available on UART4, UART5. */ #define USART_CR3_NACK BIT(USART_CR3_NACK_BIT) +/** + * @brief Half-duplex selection + * When set, single-wire half duplex mode is selected. + */ #define USART_CR3_HDSEL BIT(USART_CR3_HDSEL_BIT) +/** IrDA low power mode */ #define USART_CR3_IRLP BIT(USART_CR3_IRLP_BIT) -#define USART_CR3_IRLP_NORMAL (0 << USART_CR3_IRLP_BIT) -#define USART_CR3_IRLP_LOW_POWER (1 << USART_CR3_IRLP_BIT) +/** IrDA mode: normal */ +#define USART_CR3_IRLP_NORMAL (0U << USART_CR3_IRLP_BIT) +/** IrDA mode: low power */ +#define USART_CR3_IRLP_LOW_POWER (1U << USART_CR3_IRLP_BIT) +/** IrDA mode enable */ #define USART_CR3_IREN BIT(USART_CR3_IREN_BIT) +/** Error interrupt enable */ #define USART_CR3_EIE BIT(USART_CR3_EIE_BIT) /* Guard time and prescaler register */ -/* Not on UART4, UART5 */ +/** + * @brief Guard time value mask + * Used in Smartcard mode. Not available on UART4, UART5. */ #define USART_GTPR_GT (0xFF << 8) -/* Not on UART4, UART5 */ +/** + * @brief Prescaler value mask + * Restrictions on this value apply, depending on the USART mode. Not + * available on UART4, UART5. */ #define USART_GTPR_PSC 0xFF /* @@ -236,7 +383,8 @@ typedef struct usart_reg_map { typedef struct usart_dev { usart_reg_map *regs; /**< Register map */ ring_buffer *rb; /**< RX ring buffer */ - uint32 max_baud; /**< Maximum baud */ + uint32 max_baud; /**< @brief Deprecated. + * Maximum baud rate. */ uint8 rx_buf[USART_RX_BUF_SIZE]; /**< @brief Deprecated. * Actual RX buffer used by rb. * This field will be removed in @@ -245,16 +393,17 @@ typedef struct usart_dev { nvic_irq_num irq_num; /**< USART NVIC interrupt */ } usart_dev; -extern usart_dev *USART1; -extern usart_dev *USART2; -extern usart_dev *USART3; -#ifdef STM32_HIGH_DENSITY -extern usart_dev *UART4; -extern usart_dev *UART5; -#endif - void usart_init(usart_dev *dev); + +struct gpio_dev; /* forward declaration */ +void usart_async_gpio_cfg(usart_dev *udev, + struct gpio_dev *rx_dev, uint8 rx, + struct gpio_dev *tx_dev, uint8 tx, + unsigned flags); + +#define USART_USE_PCLK 0 void usart_set_baud_rate(usart_dev *dev, uint32 clock_speed, uint32 baud); + void usart_enable(usart_dev *dev); void usart_disable(usart_dev *dev); void usart_foreach(void (*fn)(usart_dev *dev)); diff --git a/libmaple/rules.mk b/libmaple/rules.mk index abb6ab2..5675c1c 100644 --- a/libmaple/rules.mk +++ b/libmaple/rules.mk @@ -18,6 +18,8 @@ cSRCS_$(d) += rcc.c cSRCS_$(d) += syscalls.c cSRCS_$(d) += systick.c cSRCS_$(d) += util.c +cSRCS_$(d) += usart.c +cSRCS_$(d) += usart_private.c sSRCS_$(d) := exc.S diff --git a/libmaple/stm32f1/include/series/usart.h b/libmaple/stm32f1/include/series/usart.h new file mode 100644 index 0000000..93a7728 --- /dev/null +++ b/libmaple/stm32f1/include/series/usart.h @@ -0,0 +1,76 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/usart.h + * @author Marti Bolivar + * @brief STM32F1 USART header. + */ + +#ifndef _LIBMAPLE_STM32F1_USART_H_ +#define _LIBMAPLE_STM32F1_USART_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +/* + * Register map base pointers + */ + +struct usart_reg_map; + +/** USART1 register map base pointer */ +#define USART1_BASE ((struct usart_reg_map*)0x40013800) +/** USART2 register map base pointer */ +#define USART2_BASE ((struct usart_reg_map*)0x40004400) +/** USART3 register map base pointer */ +#define USART3_BASE ((struct usart_reg_map*)0x40004800) +#ifdef STM32_HIGH_DENSITY +/** UART4 register map base pointer */ +#define UART4_BASE ((struct usart_reg_map*)0x40004C00) +/** UART5 register map base pointer */ +#define UART5_BASE ((struct usart_reg_map*)0x40005000) +#endif + +/* + * Devices + */ + +struct usart_dev; +extern struct usart_dev *USART1; +extern struct usart_dev *USART2; +extern struct usart_dev *USART3; +#ifdef STM32_HIGH_DENSITY +extern struct usart_dev *UART4; +extern struct usart_dev *UART5; +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libmaple/stm32f1/rules.mk b/libmaple/stm32f1/rules.mk index 4c7db60..3d34797 100644 --- a/libmaple/stm32f1/rules.mk +++ b/libmaple/stm32f1/rules.mk @@ -14,6 +14,7 @@ sSRCS_$(d) := isrs_performance.S \ cSRCS_$(d) := rcc.c cSRCS_$(d) += gpio.c cSRCS_$(d) += bkp.c +cSRCS_$(d) += usart.c sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%) cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%) diff --git a/libmaple/stm32f1/usart.c b/libmaple/stm32f1/usart.c new file mode 100644 index 0000000..ee68082 --- /dev/null +++ b/libmaple/stm32f1/usart.c @@ -0,0 +1,170 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * Copyright (c) 2010 Perry Hung. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/usart.c + * @author Marti Bolivar , + * Perry Hung + * @brief STM32F1 USART support. + */ + +#include +#include +#include "usart_private.h" + +/* + * Devices + */ + +static ring_buffer usart1_rb; +static usart_dev usart1 = { + .regs = USART1_BASE, + .rb = &usart1_rb, + .max_baud = 4500000UL, + .clk_id = RCC_USART1, + .irq_num = NVIC_USART1, +}; +/** USART1 device */ +usart_dev *USART1 = &usart1; + +static ring_buffer usart2_rb; +static usart_dev usart2 = { + .regs = USART2_BASE, + .rb = &usart2_rb, + .max_baud = 2250000UL, + .clk_id = RCC_USART2, + .irq_num = NVIC_USART2, +}; +/** USART2 device */ +usart_dev *USART2 = &usart2; + +static ring_buffer usart3_rb; +static usart_dev usart3 = { + .regs = USART3_BASE, + .rb = &usart3_rb, + .max_baud = 2250000UL, + .clk_id = RCC_USART3, + .irq_num = NVIC_USART3, +}; +/** USART3 device */ +usart_dev *USART3 = &usart3; + +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) +static ring_buffer uart4_rb; +static usart_dev uart4 = { + .regs = UART4_BASE, + .rb = &uart4_rb, + .max_baud = 2250000UL, + .clk_id = RCC_UART4, + .irq_num = NVIC_UART4, +}; +/** UART4 device */ +usart_dev *UART4 = &uart4; + +static ring_buffer uart5_rb; +static usart_dev uart5 = { + .regs = UART5_BASE, + .rb = &uart5_rb, + .max_baud = 2250000UL, + .clk_id = RCC_UART5, + .irq_num = NVIC_UART5, +}; +/** UART5 device */ +usart_dev *UART5 = &uart5; +#endif + +/* + * Routines + */ + +void usart_async_gpio_cfg(usart_dev *udev, + gpio_dev *rx_dev, uint8 rx, + gpio_dev *tx_dev, uint8 tx, + unsigned flags) { + gpio_set_mode(rx_dev, rx, GPIO_INPUT_FLOATING); + gpio_set_mode(tx_dev, tx, GPIO_AF_OUTPUT_PP); +} + +void usart_set_baud_rate(usart_dev *dev, uint32 clock_speed, uint32 baud) { + uint32 integer_part; + uint32 fractional_part; + uint32 tmp; + + /* Figure out the clock speed, if the user doesn't give one. */ + if (clock_speed == 0) { + clock_speed = _usart_clock_freq(dev); + } + ASSERT(clock_speed); + + /* Convert desired baud rate to baud rate register setting. */ + integer_part = (25 * clock_speed) / (4 * baud); + tmp = (integer_part / 100) << 4; + fractional_part = integer_part - (100 * (tmp >> 4)); + tmp |= (((fractional_part * 16) + 50) / 100) & ((uint8)0x0F); + + dev->regs->BRR = (uint16)tmp; +} + +/** + * @brief Call a function on each USART. + * @param fn Function to call. + */ +void usart_foreach(void (*fn)(usart_dev*)) { + fn(USART1); + fn(USART2); + fn(USART3); +#ifdef STM32_HIGH_DENSITY + fn(UART4); + fn(UART5); +#endif +} + +/* + * Interrupt handlers. + */ + +void __irq_usart1(void) { + usart_irq(&usart1_rb, USART1_BASE); +} + +void __irq_usart2(void) { + usart_irq(&usart2_rb, USART2_BASE); +} + +void __irq_usart3(void) { + usart_irq(&usart3_rb, USART3_BASE); +} + +#ifdef STM32_HIGH_DENSITY +void __irq_uart4(void) { + usart_irq(&uart4_rb, UART4_BASE); +} + +void __irq_uart5(void) { + usart_irq(&uart5_rb, UART5_BASE); +} +#endif diff --git a/libmaple/stm32f2/include/series/usart.h b/libmaple/stm32f2/include/series/usart.h new file mode 100644 index 0000000..9b18b9c --- /dev/null +++ b/libmaple/stm32f2/include/series/usart.h @@ -0,0 +1,103 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f2/usart.h + * @author Marti Bolivar + * @brief STM32F2 USART header. + */ + +#ifndef _LIBMAPLE_STM32F2_USART_H_ +#define _LIBMAPLE_STM32F2_USART_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +/* + * Register map base pointers. + */ + +struct usart_reg_map; + +/** USART1 register map base pointer */ +#define USART1_BASE ((struct usart_reg_map*)0x40011000) +/** USART2 register map base pointer */ +#define USART2_BASE ((struct usart_reg_map*)0x40004400) +/** USART3 register map base pointer */ +#define USART3_BASE ((struct usart_reg_map*)0x40004800) +/** UART4 register map base pointer */ +#define UART4_BASE ((struct usart_reg_map*)0x40004C00) +/** UART5 register map base pointer */ +#define UART5_BASE ((struct usart_reg_map*)0x40005000) +/** USART6 register map base pointer */ +#define USART6_BASE ((struct usart_reg_map*)0x40011400) + +/* + * F2-only register bit definitions. + */ + +/* Control register 1 */ + +/** + * @brief Oversampling mode bit. + * Availability: STM32F2. */ +#define USART_CR1_OVER8_BIT 15 + +/** + * @brief Oversampling mode. + * Availability: STM32F2. */ +#define USART_CR1_OVER8 (1U << USART_CR1_OVER8_BIT) + +/* Control register 3 */ + +/** One sample bit method enable bit. */ +#define USART_CR3_ONEBIT_BIT 11 + +/** One bit sample method enable. */ +#define USART_CR3_ONEBIT (1 << USART_CR3_ONEBIT_BIT) +/** Sample method: Three sample bit method. */ +#define USART_CR3_ONEBIT_3SAMPLE (0 << USART_CR3_ONEBIT_BIT) +/** Sample method: One sample bit method. */ +#define USART_CR3_ONEBIT_1SAMPLE (1 << USART_CR3_ONEBIT_BIT) + +/* + * Devices + */ + +struct usart_dev; +extern struct usart_dev *USART1; +extern struct usart_dev *USART2; +extern struct usart_dev *USART3; +extern struct usart_dev *UART4; +extern struct usart_dev *UART5; +extern struct usart_dev *USART6; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libmaple/stm32f2/rules.mk b/libmaple/stm32f2/rules.mk index 83ab043..54fa068 100644 --- a/libmaple/stm32f2/rules.mk +++ b/libmaple/stm32f2/rules.mk @@ -11,6 +11,7 @@ CFLAGS_$(d) = -I$(d) $(LIBMAPLE_INCLUDES) $(LIBMAPLE_PRIVATE_INCLUDES) -Wall -We sSRCS_$(d) := isrs.S vector_table.S cSRCS_$(d) := rcc.c cSRCS_$(d) += gpio.c +cSRCS_$(d) += usart.c sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%) cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%) diff --git a/libmaple/stm32f2/usart.c b/libmaple/stm32f2/usart.c new file mode 100644 index 0000000..364558c --- /dev/null +++ b/libmaple/stm32f2/usart.c @@ -0,0 +1,198 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f2/usart.c + * @author Marti Bolivar + * @brief STM32F2 USART support. + */ + +#include +#include +#include "usart_private.h" + +/* + * Devices + */ + +static ring_buffer usart1_rb; +static usart_dev usart1 = { + .regs = USART1_BASE, + .rb = &usart1_rb, + .max_baud = 4500000UL, /* FIXME */ + .clk_id = RCC_USART1, + .irq_num = NVIC_USART1, +}; +/** USART1 device */ +usart_dev *USART1 = &usart1; + +static ring_buffer usart2_rb; +static usart_dev usart2 = { + .regs = USART2_BASE, + .rb = &usart2_rb, + .max_baud = 2250000UL, /* FIXME */ + .clk_id = RCC_USART2, + .irq_num = NVIC_USART2, +}; +/** USART2 device */ +usart_dev *USART2 = &usart2; + +static ring_buffer usart3_rb; +static usart_dev usart3 = { + .regs = USART3_BASE, + .rb = &usart3_rb, + .max_baud = 2250000UL, /* FIXME */ + .clk_id = RCC_USART3, + .irq_num = NVIC_USART3, +}; +/** USART3 device */ +usart_dev *USART3 = &usart3; + +static ring_buffer uart4_rb; +static usart_dev uart4 = { + .regs = UART4_BASE, + .rb = &uart4_rb, + .max_baud = 2250000UL, /* FIXME */ + .clk_id = RCC_UART4, + .irq_num = NVIC_UART4, +}; +/** UART4 device */ +usart_dev *UART4 = &uart4; + +static ring_buffer uart5_rb; +static usart_dev uart5 = { + .regs = UART5_BASE, + .rb = &uart5_rb, + .max_baud = 2250000UL, /* FIXME */ + .clk_id = RCC_UART5, + .irq_num = NVIC_UART5, +}; +/** UART5 device */ +usart_dev *UART5 = &uart5; + +static ring_buffer usart6_rb; +static usart_dev usart6 = { + .regs = USART6_BASE, + .rb = &usart6_rb, + .max_baud = 4500000UL, /* FIXME */ + .clk_id = RCC_USART6, + .irq_num = NVIC_USART6, +}; +usart_dev *USART6 = &usart6; + +/* + * Routines + */ + +void usart_async_gpio_cfg(usart_dev *udev, + gpio_dev *rx_dev, uint8 rx, + gpio_dev *tx_dev, uint8 tx, + unsigned flags) { + gpio_af af; + switch (udev->clk_id) { + case RCC_USART1: + case RCC_USART2: + case RCC_USART3: + af = GPIO_AF_USART_1_2_3; + break; + case RCC_UART4: + case RCC_UART5: + case RCC_USART6: + af = GPIO_AF_USART_4_5_6; + break; + default: + ASSERT(0); + return; + } + gpio_set_modef(rx_dev, rx, GPIO_MODE_AF, 0); + gpio_set_modef(tx_dev, tx, GPIO_MODE_AF, 0); + gpio_set_af(rx_dev, rx, af); + gpio_set_af(tx_dev, tx, af); +} + +void usart_set_baud_rate(usart_dev *dev, uint32 clock_speed, uint32 baud) { + uint32 integer_part; + uint32 fractional_part; + uint32 tmp; + uint32 over8 = !!(dev->regs->CR1 & USART_CR1_OVER8); + + ASSERT(!over8); /* OVER8 is currently unsupported. */ + + /* Figure out the clock speed, if the user doesn't give one. */ + if (clock_speed == 0) { + clock_speed = _usart_clock_freq(dev); + } + ASSERT(clock_speed); + + /* Convert desired baud rate to baud rate register setting. */ + integer_part = (25 * clock_speed) / (2 * (2 - over8) * baud); + tmp = (integer_part / 100) << 4; + fractional_part = integer_part - (100 * (tmp >> 4)); + tmp |= ((fractional_part * 16 + 50) / 100) & (uint8)0x0F; + + dev->regs->BRR = tmp; +} + +/** + * @brief Call a function on each USART. + * @param fn Function to call. + */ +void usart_foreach(void (*fn)(usart_dev*)) { + fn(USART1); + fn(USART2); + fn(USART3); + fn(UART4); + fn(UART5); + fn(USART6); +} + +/* + * Interrupt handlers. + */ + +void __irq_usart1(void) { + usart_irq(&usart1_rb, USART1_BASE); +} + +void __irq_usart2(void) { + usart_irq(&usart2_rb, USART2_BASE); +} + +void __irq_usart3(void) { + usart_irq(&usart3_rb, USART3_BASE); +} + +void __irq_uart4(void) { + usart_irq(&uart4_rb, UART4_BASE); +} + +void __irq_uart5(void) { + usart_irq(&uart5_rb, UART5_BASE); +} + +void __irq_usart6(void) { + usart_irq(&usart6_rb, USART6_BASE); +} diff --git a/libmaple/usart.c b/libmaple/usart.c index ba63b79..1070aa2 100644 --- a/libmaple/usart.c +++ b/libmaple/usart.c @@ -33,67 +33,6 @@ #include -/* - * Devices - */ - -static ring_buffer usart1_rb; -static usart_dev usart1 = { - .regs = USART1_BASE, - .rb = &usart1_rb, - .max_baud = 4500000UL, - .clk_id = RCC_USART1, - .irq_num = NVIC_USART1 -}; -/** USART1 device */ -usart_dev *USART1 = &usart1; - -static ring_buffer usart2_rb; -static usart_dev usart2 = { - .regs = USART2_BASE, - .rb = &usart2_rb, - .max_baud = 2250000UL, - .clk_id = RCC_USART2, - .irq_num = NVIC_USART2 -}; -/** USART2 device */ -usart_dev *USART2 = &usart2; - -static ring_buffer usart3_rb; -static usart_dev usart3 = { - .regs = USART3_BASE, - .rb = &usart3_rb, - .max_baud = 2250000UL, - .clk_id = RCC_USART3, - .irq_num = NVIC_USART3 -}; -/** USART3 device */ -usart_dev *USART3 = &usart3; - -#ifdef STM32_HIGH_DENSITY -static ring_buffer uart4_rb; -static usart_dev uart4 = { - .regs = UART4_BASE, - .rb = &uart4_rb, - .max_baud = 2250000UL, - .clk_id = RCC_UART4, - .irq_num = NVIC_UART4 -}; -/** UART4 device */ -usart_dev *UART4 = &uart4; - -static ring_buffer uart5_rb; -static usart_dev uart5 = { - .regs = UART5_BASE, - .rb = &uart5_rb, - .max_baud = 2250000UL, - .clk_id = RCC_UART5, - .irq_num = NVIC_UART5 -}; -/** UART5 device */ -usart_dev *UART5 = &uart5; -#endif - /** * @brief Initialize a serial port. * @param dev Serial port to be initialized @@ -104,27 +43,6 @@ void usart_init(usart_dev *dev) { nvic_irq_enable(dev->irq_num); } -/** - * @brief Configure a serial port's baud rate. - * - * @param dev Serial port to be configured - * @param clock_speed Clock speed, in megahertz. - * @param baud Baud rate for transmit/receive. - */ -void usart_set_baud_rate(usart_dev *dev, uint32 clock_speed, uint32 baud) { - uint32 integer_part; - uint32 fractional_part; - uint32 tmp; - - /* See ST RM0008 for the details on configuring the baud rate register */ - integer_part = (25 * clock_speed) / (4 * baud); - tmp = (integer_part / 100) << 4; - fractional_part = integer_part - (100 * (tmp >> 4)); - tmp |= (((fractional_part * 16) + 50) / 100) & ((uint8)0x0F); - - dev->regs->BRR = (uint16)tmp; -} - /** * @brief Enable a serial port. * @@ -138,7 +56,8 @@ void usart_set_baud_rate(usart_dev *dev, uint32 clock_speed, uint32 baud) { */ void usart_enable(usart_dev *dev) { usart_reg_map *regs = dev->regs; - regs->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_RXNEIE; + regs->CR1 = (USART_CR1_TE | USART_CR1_RE | USART_CR1_RXNEIE | + USART_CR1_M_8N1); regs->CR1 |= USART_CR1_UE; } @@ -147,7 +66,7 @@ void usart_enable(usart_dev *dev) { * @param dev Serial port to be disabled */ void usart_disable(usart_dev *dev) { - /* FIXME this misbehaves if you try to use PWM on TX afterwards */ + /* FIXME this misbehaves (on F1) if you try to use PWM on TX afterwards */ usart_reg_map *regs = dev->regs; /* TC bit must be high before disabling the USART */ @@ -161,20 +80,6 @@ void usart_disable(usart_dev *dev) { usart_reset_rx(dev); } -/** - * @brief Call a function on each USART. - * @param fn Function to call. - */ -void usart_foreach(void (*fn)(usart_dev*)) { - fn(USART1); - fn(USART2); - fn(USART3); -#ifdef STM32_HIGH_DENSITY - fn(UART4); - fn(UART5); -#endif -} - /** * @brief Nonblocking USART transmit * @param dev Serial port to transmit over @@ -230,40 +135,3 @@ void usart_putudec(usart_dev *dev, uint32 val) { usart_putc(dev, digits[i]); } } - -/* - * Interrupt handlers. - */ - -static inline void usart_irq(usart_dev *dev) { -#ifdef USART_SAFE_INSERT - /* If the buffer is full and the user defines USART_SAFE_INSERT, - * ignore new bytes. */ - rb_safe_insert(dev->rb, (uint8)dev->regs->DR); -#else - /* By default, push bytes around in the ring buffer. */ - rb_push_insert(dev->rb, (uint8)dev->regs->DR); -#endif -} - -void __irq_usart1(void) { - usart_irq(USART1); -} - -void __irq_usart2(void) { - usart_irq(USART2); -} - -void __irq_usart3(void) { - usart_irq(USART3); -} - -#ifdef STM32_HIGH_DENSITY -void __irq_uart4(void) { - usart_irq(UART4); -} - -void __irq_uart5(void) { - usart_irq(UART5); -} -#endif diff --git a/libmaple/usart_private.c b/libmaple/usart_private.c new file mode 100644 index 0000000..d79387a --- /dev/null +++ b/libmaple/usart_private.c @@ -0,0 +1,40 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/usart_private.c + * @author Marti Bolivar + * @brief Private USART routines. + */ + +#include "usart_private.h" +#include + +uint32 _usart_clock_freq(usart_dev *dev) { + rcc_clk_domain domain = rcc_dev_clk(dev->clk_id); + return (domain == RCC_APB1 ? STM32_PCLK1 : + (domain == RCC_APB2 ? STM32_PCLK2 : 0)); +} diff --git a/libmaple/usart_private.h b/libmaple/usart_private.h new file mode 100644 index 0000000..a5cec83 --- /dev/null +++ b/libmaple/usart_private.h @@ -0,0 +1,53 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * Copyright (c) 2010 Perry Hung. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/usart_private.h + * @author Marti Bolivar + * @brief Private USART header. + */ + +#ifndef _LIBMAPLE_USART_PRIVATE_H_ +#define _LIBMAPLE_USART_PRIVATE_H_ + +#include +#include + +static inline void usart_irq(ring_buffer *rb, usart_reg_map *regs) { +#ifdef USART_SAFE_INSERT + /* If the buffer is full and the user defines USART_SAFE_INSERT, + * ignore new bytes. */ + rb_safe_insert(rb, (uint8)regs->DR); +#else + /* By default, push bytes around in the ring buffer. */ + rb_push_insert(rb, (uint8)regs->DR); +#endif +} + +uint32 _usart_clock_freq(usart_dev *dev); + +#endif -- cgit v1.2.3 From 6dd3c2e202e46c843e00498f5d9a675cfa83522d Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Mon, 26 Mar 2012 19:34:04 -0400 Subject: Clean up rules.mk files. Alphabetize targets and remove continuation lines. Signed-off-by: Marti Bolivar --- libmaple/rules.mk | 2 +- libmaple/stm32f1/rules.mk | 8 ++++---- libmaple/stm32f2/rules.mk | 5 +++-- 3 files changed, 8 insertions(+), 7 deletions(-) (limited to 'libmaple/rules.mk') diff --git a/libmaple/rules.mk b/libmaple/rules.mk index 5675c1c..4c2a40f 100644 --- a/libmaple/rules.mk +++ b/libmaple/rules.mk @@ -17,9 +17,9 @@ cSRCS_$(d) += nvic.c cSRCS_$(d) += rcc.c cSRCS_$(d) += syscalls.c cSRCS_$(d) += systick.c -cSRCS_$(d) += util.c cSRCS_$(d) += usart.c cSRCS_$(d) += usart_private.c +cSRCS_$(d) += util.c sSRCS_$(d) := exc.S diff --git a/libmaple/stm32f1/rules.mk b/libmaple/stm32f1/rules.mk index b961d77..bdff00e 100644 --- a/libmaple/stm32f1/rules.mk +++ b/libmaple/stm32f1/rules.mk @@ -8,13 +8,13 @@ BUILDDIRS += $(BUILD_PATH)/$(d) CFLAGS_$(d) = -I$(d) $(LIBMAPLE_PRIVATE_INCLUDES) $(LIBMAPLE_INCLUDES) -Wall -Werror # Local rules and targets -sSRCS_$(d) := isrs_performance.S \ - vector_table_performance.S +sSRCS_$(d) := isrs_performance.S +sSRCS_$(d) += vector_table_performance.S -cSRCS_$(d) := rcc.c +cSRCS_$(d) := bkp.c cSRCS_$(d) += fsmc.c cSRCS_$(d) += gpio.c -cSRCS_$(d) += bkp.c +cSRCS_$(d) += rcc.c cSRCS_$(d) += usart.c sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%) diff --git a/libmaple/stm32f2/rules.mk b/libmaple/stm32f2/rules.mk index 8711090..a46f8d1 100644 --- a/libmaple/stm32f2/rules.mk +++ b/libmaple/stm32f2/rules.mk @@ -8,11 +8,12 @@ BUILDDIRS += $(BUILD_PATH)/$(d) CFLAGS_$(d) = -I$(d) $(LIBMAPLE_INCLUDES) $(LIBMAPLE_PRIVATE_INCLUDES) -Wall -Werror # Local rules and targets -sSRCS_$(d) := isrs.S vector_table.S +sSRCS_$(d) := isrs.S +sSRCS_$(d) += vector_table.S -cSRCS_$(d) := rcc.c cSRCS_$(d) += fsmc.c cSRCS_$(d) += gpio.c +cSRCS_$(d) += rcc.c cSRCS_$(d) += usart.c sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%) -- cgit v1.2.3 From bf0f839fb1d7d8075b148e2e6788479a36f56b7e Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Mon, 26 Mar 2012 19:39:49 -0400 Subject: Resurrect PWR support for F1 and F2. Just add the missing register bit definitions in new series headers. Signed-off-by: Marti Bolivar --- libmaple/include/libmaple/pwr.h | 1 + libmaple/rules.mk | 1 + libmaple/stm32f1/include/series/pwr.h | 52 +++++++++++++++++++++++++ libmaple/stm32f2/include/series/pwr.h | 73 +++++++++++++++++++++++++++++++++++ 4 files changed, 127 insertions(+) create mode 100644 libmaple/stm32f1/include/series/pwr.h create mode 100644 libmaple/stm32f2/include/series/pwr.h (limited to 'libmaple/rules.mk') diff --git a/libmaple/include/libmaple/pwr.h b/libmaple/include/libmaple/pwr.h index 8841518..2611587 100644 --- a/libmaple/include/libmaple/pwr.h +++ b/libmaple/include/libmaple/pwr.h @@ -37,6 +37,7 @@ extern "C" { #endif #include +#include /** Power interface register map. */ typedef struct pwr_reg_map { diff --git a/libmaple/rules.mk b/libmaple/rules.mk index 4c2a40f..b12e3ff 100644 --- a/libmaple/rules.mk +++ b/libmaple/rules.mk @@ -14,6 +14,7 @@ CFLAGS_$(d) = $(LIBMAPLE_PRIVATE_INCLUDES) $(LIBMAPLE_INCLUDES) -Wall -Werror cSRCS_$(d) := flash.c cSRCS_$(d) += gpio.c cSRCS_$(d) += nvic.c +cSRCS_$(d) += pwr.c cSRCS_$(d) += rcc.c cSRCS_$(d) += syscalls.c cSRCS_$(d) += systick.c diff --git a/libmaple/stm32f1/include/series/pwr.h b/libmaple/stm32f1/include/series/pwr.h new file mode 100644 index 0000000..d13ffa7 --- /dev/null +++ b/libmaple/stm32f1/include/series/pwr.h @@ -0,0 +1,52 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file stm32f1/pwr.h + * @author Marti Bolivar + * @brief STM32F1 Power control (PWR) support. + */ + +#ifndef _LIBMAPLE_STM32F1_PWR_H_ +#define _LIBMAPLE_STM32F1_PWR_H_ + +/* + * Register bit definitions + */ + +/* Control register */ + +/* PVD level selection */ +#define PWR_CR_PLS_2_2V (0x0 << 5) +#define PWR_CR_PLS_2_3V (0x1 << 5) +#define PWR_CR_PLS_2_4V (0x2 << 5) +#define PWR_CR_PLS_2_5V (0x3 << 5) +#define PWR_CR_PLS_2_6V (0x4 << 5) +#define PWR_CR_PLS_2_7V (0x5 << 5) +#define PWR_CR_PLS_2_8V (0x6 << 5) +#define PWR_CR_PLS_2_9V (0x7 << 5) + +#endif diff --git a/libmaple/stm32f2/include/series/pwr.h b/libmaple/stm32f2/include/series/pwr.h new file mode 100644 index 0000000..dec2d76 --- /dev/null +++ b/libmaple/stm32f2/include/series/pwr.h @@ -0,0 +1,73 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file stm32f2/pwr.h + * @author Marti Bolivar + * @brief STM32F2 Power control (PWR) support. + */ + +#ifndef _LIBMAPLE_STM32F2_PWR_H_ +#define _LIBMAPLE_STM32F2_PWR_H_ + +/* + * Additional register bits + */ + +/* Control register */ + +/** + * @brief Flash power down in stop mode bit. + * Availability: STM32F2 */ +#define PWR_CR_FPDS_BIT 9 +/** + * @brief Flash power down in stop mode. + * Availability: STM32F2 */ +#define PWR_CR_FPDS (1U << PWR_CR_FPDS_BIT) + +/* PVD level selection */ +#define PWR_CR_PLS_2_0V (0x0 << 5) +#define PWR_CR_PLS_2_1V (0x1 << 5) +#define PWR_CR_PLS_2_3V (0x2 << 5) +#define PWR_CR_PLS_2_5V (0x3 << 5) +#define PWR_CR_PLS_2_6V (0x4 << 5) +#define PWR_CR_PLS_2_7V (0x5 << 5) +#define PWR_CR_PLS_2_8V (0x6 << 5) +#define PWR_CR_PLS_2_9V (0x7 << 5) + +/* Control/Status register */ + +/** Backup regulator enable bit. */ +#define PWR_CSR_BRE_BIT 9 +/** Backup regulator ready bit. */ +#define PWR_CSR_BRR_BIT 3 + +/** Backup regulator enable. */ +#define PWR_CSR_BRE (1U << PWR_CSR_BRE_BIT) +/** Backup regulator ready. */ +#define PWR_CSR_BRR (1U << PWR_CSR_BRR_BIT) + +#endif -- cgit v1.2.3 From 658068615dda2088c4198b3f1b4e2e8e8719c2a8 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Mon, 26 Mar 2012 19:51:39 -0400 Subject: Resurrect IWDG support. This peripheral is identical on F1 and F2. Signed-off-by: Marti Bolivar --- libmaple/include/libmaple/iwdg.h | 2 +- libmaple/rules.mk | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'libmaple/rules.mk') diff --git a/libmaple/include/libmaple/iwdg.h b/libmaple/include/libmaple/iwdg.h index baddf4f..80202d2 100644 --- a/libmaple/include/libmaple/iwdg.h +++ b/libmaple/include/libmaple/iwdg.h @@ -25,7 +25,7 @@ *****************************************************************************/ /** - * @file iwdg.h + * @file libmaple/iwdg.h * @author Michael Hope, Marti Bolivar * @brief Independent watchdog support. * diff --git a/libmaple/rules.mk b/libmaple/rules.mk index b12e3ff..24b3c0e 100644 --- a/libmaple/rules.mk +++ b/libmaple/rules.mk @@ -13,6 +13,7 @@ CFLAGS_$(d) = $(LIBMAPLE_PRIVATE_INCLUDES) $(LIBMAPLE_INCLUDES) -Wall -Werror # Local rules and targets cSRCS_$(d) := flash.c cSRCS_$(d) += gpio.c +cSRCS_$(d) += iwdg.c cSRCS_$(d) += nvic.c cSRCS_$(d) += pwr.c cSRCS_$(d) += rcc.c -- cgit v1.2.3 From d969ea5467101a8c03de9171a6444ce859c8da61 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Mon, 26 Mar 2012 19:58:46 -0400 Subject: libmaple/rules.mk: Cosmetics. Signed-off-by: Marti Bolivar --- libmaple/rules.mk | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'libmaple/rules.mk') diff --git a/libmaple/rules.mk b/libmaple/rules.mk index 24b3c0e..cc562ea 100644 --- a/libmaple/rules.mk +++ b/libmaple/rules.mk @@ -22,6 +22,14 @@ cSRCS_$(d) += systick.c cSRCS_$(d) += usart.c cSRCS_$(d) += usart_private.c cSRCS_$(d) += util.c +# These still need to be ported to F2: +# cSRCS_$(d) += adc.c +# cSRCS_$(d) += dac.c +# cSRCS_$(d) += dma.c +# cSRCS_$(d) += exti.c +# cSRCS_$(d) += i2c.c +# cSRCS_$(d) += spi.c +# cSRCS_$(d) += timer.c sSRCS_$(d) := exc.S -- cgit v1.2.3 From 28825b6a2f66b0329229185eb9cbd9004fae4b1b Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Mon, 26 Mar 2012 22:17:47 -0400 Subject: Resurrect ADC support. Standard refactoring: add series headers for F1 and F2, along with series adc.c files. There are some issues relating to adc_extsel_event to hammer out later, but this will do for now. We also add some new portability interfaces to libmaple/adc.h in order for Wirish to use the same code to initialize the ADCs at init() time. As usual, F1 is untested. Signed-off-by: Marti Bolivar --- libmaple/adc.c | 74 +------- libmaple/include/libmaple/adc.h | 175 +++++++----------- libmaple/rules.mk | 4 +- libmaple/stm32f1/adc.c | 110 +++++++++++ libmaple/stm32f1/include/series/adc.h | 254 ++++++++++++++++++++++++++ libmaple/stm32f1/rules.mk | 3 +- libmaple/stm32f2/adc.c | 84 +++++++++ libmaple/stm32f2/include/series/adc.h | 331 ++++++++++++++++++++++++++++++++++ libmaple/stm32f2/rules.mk | 1 + wirish/boards.cpp | 15 +- wirish/boards_private.h | 12 +- wirish/stm32f1/boards_setup.cpp | 39 ++-- wirish/stm32f2/boards_setup.cpp | 32 +++- 13 files changed, 920 insertions(+), 214 deletions(-) create mode 100644 libmaple/stm32f1/adc.c create mode 100644 libmaple/stm32f1/include/series/adc.h create mode 100644 libmaple/stm32f2/adc.c create mode 100644 libmaple/stm32f2/include/series/adc.h (limited to 'libmaple/rules.mk') diff --git a/libmaple/adc.c b/libmaple/adc.c index 40369e9..acce923 100644 --- a/libmaple/adc.c +++ b/libmaple/adc.c @@ -25,44 +25,15 @@ *****************************************************************************/ /** - * @file adc.c - * + * @file libmaple/adc.c + * @author Marti Bolivar , + * Perry Hung * @brief Analog to digital converter routines - * - * IMPORTANT: maximum external impedance must be below 0.4kOhms for 1.5 - * sample conversion time. - * - * At 55.5 cycles/sample, the external input impedance < 50kOhms. - * - * See STM32 manual RM0008 for how to calculate this. */ +#include #include #include -#include - -static adc_dev adc1 = { - .regs = ADC1_BASE, - .clk_id = RCC_ADC1 -}; -/** ADC1 device. */ -const adc_dev *ADC1 = &adc1; - -static adc_dev adc2 = { - .regs = ADC2_BASE, - .clk_id = RCC_ADC2 -}; -/** ADC2 device. */ -const adc_dev *ADC2 = &adc2; - -#ifdef STM32_HIGH_DENSITY -adc_dev adc3 = { - .regs = ADC3_BASE, - .clk_id = RCC_ADC3 -}; -/** ADC3 device. */ -const adc_dev *ADC3 = &adc3; -#endif /** * @brief Initialize an ADC peripheral. @@ -91,20 +62,10 @@ void adc_set_extsel(const adc_dev *dev, adc_extsel_event event) { } /** - * @brief Call a function on all ADC devices. - * @param fn Function to call on each ADC device. - */ -void adc_foreach(void (*fn)(const adc_dev*)) { - fn(ADC1); - fn(ADC2); -#ifdef STM32_HIGH_DENSITY - fn(ADC3); -#endif -} - -/** - * @brief Turn the given sample rate into values for ADC_SMPRx. Don't - * call this during conversion. + * @brief Set the sample rate for all channels on an ADC device. + * + * Don't call this during conversion. + * * @param dev adc device * @param smp_rate sample rate to set * @see adc_smp_rate @@ -126,26 +87,9 @@ void adc_set_sample_rate(const adc_dev *dev, adc_smp_rate smp_rate) { dev->regs->SMPR2 = adc_smpr2_val; } -/** - * @brief Calibrate an ADC peripheral - * @param dev adc device - */ -void adc_calibrate(const adc_dev *dev) { - __io uint32 *rstcal_bit = bb_perip(&(dev->regs->CR2), 3); - __io uint32 *cal_bit = bb_perip(&(dev->regs->CR2), 2); - - *rstcal_bit = 1; - while (*rstcal_bit) - ; - - *cal_bit = 1; - while (*cal_bit) - ; -} - /** * @brief Perform a single synchronous software triggered conversion on a - * channel. + * channel. * @param dev ADC device to use for reading. * @param channel channel to convert * @return conversion result diff --git a/libmaple/include/libmaple/adc.h b/libmaple/include/libmaple/adc.h index d531d00..be29676 100644 --- a/libmaple/include/libmaple/adc.h +++ b/libmaple/include/libmaple/adc.h @@ -1,6 +1,7 @@ /****************************************************************************** * The MIT License * + * Copyright (c) 2012 LeafLabs, LLC. * Copyright (c) 2010 Perry Hung. * * Permission is hereby granted, free of charge, to any person @@ -25,9 +26,10 @@ *****************************************************************************/ /** - * @file adc.h - * - * @brief Analog-to-Digital Conversion (ADC) header. + * @file libmaple/adc.h + * @author Marti Bolivar , + * Perry Hung + * @brief Analog-to-Digital Conversion (ADC) header. */ #ifndef _LIBMAPLE_ADC_H_ @@ -40,6 +42,12 @@ extern "C"{ #include #include #include +/* We include the series header below, after defining the register map + * and device structs. */ + +/* + * Register map + */ /** ADC register map type. */ typedef struct adc_reg_map { @@ -71,24 +79,30 @@ typedef struct adc_dev { rcc_clk_id clk_id; /**< RCC clock information */ } adc_dev; -extern const adc_dev *ADC1; -extern const adc_dev *ADC2; -#ifdef STM32_HIGH_DENSITY -extern const adc_dev *ADC3; -#endif - -/* - * Register map base pointers +/* Pull in the series header (which may need the above struct + * definitions). + * + * IMPORTANT: The series header must define the following: + * + * - enum adc_extsel_event (and typedef to adc_extsel_event): One per + * external event used to trigger start of conversion of a regular + * group. If two different series support the same event as a + * trigger, they must use the same token for the enumerator for that + * event. (The value of the enumerator is of course allowed to be + * different). + * + * - enum adc_smp_rate (and typedef to adc_smp_rate): One per + * available sampling time. These must be in the form ADC_SMPR_X_Y + * for X.Y cycles (e.g. ADC_SMPR_1_5 means 1.5 cycles), or + * ADC_SMPR_X for X cycles (e.g. ADC_SMPR_3 means 3 cycles). + * + * - enum adc_prescaler (and typedef): One per available prescaler, + * suitable for adc_set_prescaler. Series which have the same + * prescaler dividers (e.g. STM32F1 and STM32F2 both divide PCLK2 by + * 2, 4, 6, or 8) must provide the same tokens as enumerators, for + * portability. */ - -/** ADC1 register map base pointer. */ -#define ADC1_BASE ((struct adc_reg_map*)0x40012400) -/** ADC2 register map base pointer. */ -#define ADC2_BASE ((struct adc_reg_map*)0x40012800) -#ifdef STM32_HIGH_DENSITY -/** ADC3 register map base pointer. */ -#define ADC3_BASE ((struct adc_reg_map*)0x40013C00) -#endif +#include /* * Register bit definitions @@ -136,31 +150,9 @@ extern const adc_dev *ADC3; /* Control register 2 */ -#define ADC_CR2_ADON_BIT 0 -#define ADC_CR2_CONT_BIT 1 -#define ADC_CR2_CAL_BIT 2 -#define ADC_CR2_RSTCAL_BIT 3 -#define ADC_CR2_DMA_BIT 8 -#define ADC_CR2_ALIGN_BIT 11 -#define ADC_CR2_JEXTTRIG_BIT 15 -#define ADC_CR2_EXTTRIG_BIT 20 -#define ADC_CR2_JSWSTART_BIT 21 -#define ADC_CR2_SWSTART_BIT 22 -#define ADC_CR2_TSEREFE_BIT 23 - -#define ADC_CR2_ADON BIT(ADC_CR2_ADON_BIT) -#define ADC_CR2_CONT BIT(ADC_CR2_CONT_BIT) -#define ADC_CR2_CAL BIT(ADC_CR2_CAL_BIT) -#define ADC_CR2_RSTCAL BIT(ADC_CR2_RSTCAL_BIT) -#define ADC_CR2_DMA BIT(ADC_CR2_DMA_BIT) -#define ADC_CR2_ALIGN BIT(ADC_CR2_ALIGN_BIT) -#define ADC_CR2_JEXTSEL (0x7000) -#define ADC_CR2_JEXTTRIG BIT(ADC_CR2_JEXTTRIG_BIT) -#define ADC_CR2_EXTSEL (0xE0000) -#define ADC_CR2_EXTTRIG BIT(ADC_CR2_EXTTRIG_BIT) -#define ADC_CR2_JSWSTART BIT(ADC_CR2_JSWSTART_BIT) -#define ADC_CR2_SWSTART BIT(ADC_CR2_SWSTART_BIT) -#define ADC_CR2_TSEREFE BIT(ADC_CR2_TSEREFE_BIT) +/* Because this register varies significantly by series (e.g. some + * bits moved and others disappeared in the F1->F2 transition), its + * definitions are in the series headers. */ /* Sample time register 1 */ @@ -245,68 +237,47 @@ extern const adc_dev *ADC3; #define ADC_DR_ADC2DATA (0xFFFF << 16) #define ADC_DR_DATA 0xFFFF -void adc_init(const adc_dev *dev); +/* + * Routines + */ /** - * @brief External event selector for regular group conversion. - * @see adc_set_extsel + * @brief Set the ADC prescaler. + * + * This determines the ADC clock for all devices. */ -typedef enum adc_extsel_event { - ADC_ADC12_TIM1_CC1 = (0 << 17), /**< ADC1 and ADC2: Timer 1 CC1 event */ - ADC_ADC12_TIM1_CC2 = (1 << 17), /**< ADC1 and ADC2: Timer 1 CC2 event */ - ADC_ADC12_TIM1_CC3 = (2 << 17), /**< ADC1 and ADC2: Timer 1 CC3 event */ - ADC_ADC12_TIM2_CC2 = (3 << 17), /**< ADC1 and ADC2: Timer 2 CC2 event */ - ADC_ADC12_TIM3_TRGO = (4 << 17), /**< ADC1 and ADC2: Timer 3 TRGO event */ - ADC_ADC12_TIM4_CC4 = (5 << 17), /**< ADC1 and ADC2: Timer 4 CC4 event */ - ADC_ADC12_EXTI11 = (6 << 17), /**< ADC1 and ADC2: EXTI11 event */ -#ifdef STM32_HIGH_DENSITY - ADC_ADC12_TIM8_TRGO = (6 << 17), /**< ADC1 and ADC2: Timer 8 TRGO - event (high density only) */ -#endif - ADC_ADC12_SWSTART = (7 << 17), /**< ADC1 and ADC2: Software start */ -#ifdef STM32_HIGH_DENSITY - ADC_ADC3_TIM3_CC1 = (0 << 17), /**< ADC3: Timer 3 CC1 event - (high density only) */ - ADC_ADC3_TIM2_CC3 = (1 << 17), /**< ADC3: Timer 2 CC3 event - (high density only) */ - ADC_ADC3_TIM1_CC3 = (2 << 17), /**< ADC3: Timer 1 CC3 event - (high density only) */ - ADC_ADC3_TIM8_CC1 = (3 << 17), /**< ADC3: Timer 8 CC1 event - (high density only) */ - ADC_ADC3_TIM8_TRGO = (4 << 17), /**< ADC3: Timer 8 TRGO event - (high density only) */ - ADC_ADC3_TIM5_CC1 = (5 << 17), /**< ADC3: Timer 5 CC1 event - (high density only) */ - ADC_ADC3_TIM5_CC3 = (6 << 17), /**< ADC3: Timer 5 CC3 event - (high density only) */ - ADC_ADC3_SWSTART = (7 << 17), /**< ADC3: Software start (high - density only) */ -#endif - ADC_SWSTART = (7 << 17) /**< ADC1, ADC2, ADC3: Software start */ -} adc_extsel_event; +void adc_set_prescaler(adc_prescaler pre); +void adc_init(const adc_dev *dev); void adc_set_extsel(const adc_dev *dev, adc_extsel_event event); +void adc_set_sample_rate(const adc_dev *dev, adc_smp_rate smp_rate); +uint16 adc_read(const adc_dev *dev, uint8 channel); + +/** + * @brief Call a function on all ADC devices. + * @param fn Function to call on each ADC device. + */ void adc_foreach(void (*fn)(const adc_dev*)); /** - * @brief ADC sample times, in ADC clock cycles - * - * These control the amount of time spent sampling the input voltage. + * @brief Configure a GPIO pin for ADC conversion. + * @param gdev GPIO device to configure. + * @param bit Bit on gdev to configure for ADC conversion. */ -typedef enum { - ADC_SMPR_1_5, /**< 1.5 ADC cycles */ - ADC_SMPR_7_5, /**< 7.5 ADC cycles */ - ADC_SMPR_13_5, /**< 13.5 ADC cycles */ - ADC_SMPR_28_5, /**< 28.5 ADC cycles */ - ADC_SMPR_41_5, /**< 41.5 ADC cycles */ - ADC_SMPR_55_5, /**< 55.5 ADC cycles */ - ADC_SMPR_71_5, /**< 71.5 ADC cycles */ - ADC_SMPR_239_5 /**< 239.5 ADC cycles */ -} adc_smp_rate; +struct gpio_dev; +void adc_gpio_cfg(struct gpio_dev *gdev, uint8 bit); -void adc_set_sample_rate(const adc_dev *dev, adc_smp_rate smp_rate); -void adc_calibrate(const adc_dev *dev); -uint16 adc_read(const adc_dev *dev, uint8 channel); +/** + * @brief Enable an ADC and configure it for single conversion mode. + * + * This function performs any initialization necessary to allow the + * ADC device to perform a single synchronous regular software + * triggered conversion, using adc_read(). + * + * @param dev Device to enable. + * @see adc_read() + */ +void adc_enable_single_swstart(const adc_dev* dev); /** * @brief Set the regular channel sequence length. @@ -324,16 +295,6 @@ static inline void adc_set_reg_seqlen(const adc_dev *dev, uint8 length) { dev->regs->SQR1 = tmp; } -/** - * @brief Set external trigger conversion mode event for regular channels - * @param dev ADC device - * @param enable If 1, conversion on external events is enabled; if 0, - * disabled. - */ -static inline void adc_set_exttrig(const adc_dev *dev, uint8 enable) { - *bb_perip(&dev->regs->CR2, ADC_CR2_EXTTRIG_BIT) = !!enable; -} - /** * @brief Enable an adc peripheral * @param dev ADC device to enable diff --git a/libmaple/rules.mk b/libmaple/rules.mk index cc562ea..d118b16 100644 --- a/libmaple/rules.mk +++ b/libmaple/rules.mk @@ -11,7 +11,8 @@ LIBMAPLE_PRIVATE_INCLUDES := -I$(LIBMAPLE_PATH) CFLAGS_$(d) = $(LIBMAPLE_PRIVATE_INCLUDES) $(LIBMAPLE_INCLUDES) -Wall -Werror # Local rules and targets -cSRCS_$(d) := flash.c +cSRCS_$(d) := adc.c +cSRCS_$(d) += flash.c cSRCS_$(d) += gpio.c cSRCS_$(d) += iwdg.c cSRCS_$(d) += nvic.c @@ -23,7 +24,6 @@ cSRCS_$(d) += usart.c cSRCS_$(d) += usart_private.c cSRCS_$(d) += util.c # These still need to be ported to F2: -# cSRCS_$(d) += adc.c # cSRCS_$(d) += dac.c # cSRCS_$(d) += dma.c # cSRCS_$(d) += exti.c diff --git a/libmaple/stm32f1/adc.c b/libmaple/stm32f1/adc.c new file mode 100644 index 0000000..8242520 --- /dev/null +++ b/libmaple/stm32f1/adc.c @@ -0,0 +1,110 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * Copyright (c) 2010 Perry Hung. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/include/series/adc.c + * @brief STM32F1 ADC header. + */ + +#include +#include + +/* + * Devices + */ + +static adc_dev adc1 = { + .regs = ADC1_BASE, + .clk_id = RCC_ADC1 +}; +/** ADC1 device. */ +const adc_dev *ADC1 = &adc1; + +static adc_dev adc2 = { + .regs = ADC2_BASE, + .clk_id = RCC_ADC2 +}; +/** ADC2 device. */ +const adc_dev *ADC2 = &adc2; + +#ifdef STM32_HIGH_DENSITY +adc_dev adc3 = { + .regs = ADC3_BASE, + .clk_id = RCC_ADC3 +}; +/** ADC3 device. */ +const adc_dev *ADC3 = &adc3; +#endif + +/* + * STM32F1 routines + */ + +/** + * @brief Calibrate an ADC peripheral + * @param dev adc device + */ +void adc_calibrate(const adc_dev *dev) { + __io uint32 *rstcal_bit = bb_perip(&(dev->regs->CR2), 3); + __io uint32 *cal_bit = bb_perip(&(dev->regs->CR2), 2); + + *rstcal_bit = 1; + while (*rstcal_bit) + ; + + *cal_bit = 1; + while (*cal_bit) + ; +} + +/* + * Common routines + */ + +void adc_set_prescaler(adc_prescaler pre) { + rcc_set_prescaler(RCC_PRESCALER_ADC, (uint32)pre); +} + +void adc_foreach(void (*fn)(const adc_dev*)) { + fn(ADC1); + fn(ADC2); +#ifdef STM32_HIGH_DENSITY + fn(ADC3); +#endif +} + +void adc_gpio_cfg(gpio_dev *gdev, uint8 bit) { + gpio_set_mode(gdev, bit, GPIO_INPUT_ANALOG); +} + +void adc_enable_single_swstart(const adc_dev *dev) { + adc_init(dev); + adc_set_extsel(dev, ADC_SWSTART); + adc_set_exttrig(dev, 1); + adc_enable(dev); + adc_calibrate(dev); +} diff --git a/libmaple/stm32f1/include/series/adc.h b/libmaple/stm32f1/include/series/adc.h new file mode 100644 index 0000000..1798e55 --- /dev/null +++ b/libmaple/stm32f1/include/series/adc.h @@ -0,0 +1,254 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * Copyright (c) 2010 Perry Hung. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file stm32f1/include/series/adc.h + * @author Marti Bolivar , + * Perry Hung + * @brief STM32F1 ADC header. + */ + +#ifndef _LIBMAPLE_STM32F1_ADC_H_ +#define _LIBMAPLE_STM32F1_ADC_H_ + +#include /* For the prescalers */ + +/* + * Devices + */ + +extern const struct adc_dev *ADC1; +extern const struct adc_dev *ADC2; +#ifdef STM32_HIGH_DENSITY +extern const struct adc_dev *ADC3; +#endif + +/* + * Register map base pointers + */ + +/** ADC1 register map base pointer. */ +#define ADC1_BASE ((struct adc_reg_map*)0x40012400) +/** ADC2 register map base pointer. */ +#define ADC2_BASE ((struct adc_reg_map*)0x40012800) +#ifdef STM32_HIGH_DENSITY +/** ADC3 register map base pointer. */ +#define ADC3_BASE ((struct adc_reg_map*)0x40013C00) +#endif + +/* + * Register bit definitions + */ + +/* Control register 2 */ + +#define ADC_CR2_ADON_BIT 0 +#define ADC_CR2_CONT_BIT 1 +#define ADC_CR2_CAL_BIT 2 +#define ADC_CR2_RSTCAL_BIT 3 +#define ADC_CR2_DMA_BIT 8 +#define ADC_CR2_ALIGN_BIT 11 +#define ADC_CR2_JEXTTRIG_BIT 15 +#define ADC_CR2_EXTTRIG_BIT 20 +#define ADC_CR2_JSWSTART_BIT 21 +#define ADC_CR2_SWSTART_BIT 22 +#define ADC_CR2_TSEREFE_BIT 23 + +#define ADC_CR2_ADON (1U << ADC_CR2_ADON_BIT) +#define ADC_CR2_CONT (1U << ADC_CR2_CONT_BIT) +#define ADC_CR2_CAL (1U << ADC_CR2_CAL_BIT) +#define ADC_CR2_RSTCAL (1U << ADC_CR2_RSTCAL_BIT) +#define ADC_CR2_DMA (1U << ADC_CR2_DMA_BIT) +#define ADC_CR2_ALIGN (1U << ADC_CR2_ALIGN_BIT) +#define ADC_CR2_JEXTSEL 0x7000 +#define ADC_CR2_JEXTTRIG (1U << ADC_CR2_JEXTTRIG_BIT) +#define ADC_CR2_EXTSEL 0xE0000 +#define ADC_CR2_EXTTRIG (1U << ADC_CR2_EXTTRIG_BIT) +#define ADC_CR2_JSWSTART (1U << ADC_CR2_JSWSTART_BIT) +#define ADC_CR2_SWSTART (1U << ADC_CR2_SWSTART_BIT) +#define ADC_CR2_TSEREFE (1U << ADC_CR2_TSEREFE_BIT) + +/* + * Other types + */ + +/** + * @brief STM32F1 external event selectors for regular group + * conversion. + * + * Some external events are only available on ADCs 1 and 2, others + * only on ADC3, while others are available on all three ADCs. + * Additionally, some events are only available on high- and + * XL-density STM32F1 MCUs, as they use peripherals only available on + * those MCU densities. + * + * For ease of use, each event selector is given along with the ADCs + * it's available on, along with any other availability restrictions. + * + * @see adc_set_extsel() + */ +typedef enum adc_extsel_event { + /* TODO: Smarten this up a bit, as follows. + * + * The EXTSEL bits on F1 are a little brain-damaged in that the + * TIM8 TRGO event has different bits depending on whether you're + * using ADC1/2 or ADC3. We route around this by declaring two + * enumerators, ADC_EXT_EV_ADC12_TIM8_TRGO and + * ADC_EXT_EV_ADC3_TIM8_TRGO. + * + * The right thing to do is to provide a single + * ADC_EXT_EV_TIM8_TRGO enumerator and override adc_set_extsel on + * STM32F1 to handle this situation correctly. We can do that + * later, though, and change the per-ADC enumerator values to + * ADC_EXT_EV_TIM8_TRGO to preserve compatibility. */ + + /* ADC1 and ADC2 only: */ + ADC_EXT_EV_TIM1_CC1 = 0x00000, /**< ADC1, ADC2: Timer 1 CC1 event */ + ADC_EXT_EV_TIM1_CC2 = 0x20000, /**< ADC1, ADC2: Timer 1 CC2 event */ + ADC_EXT_EV_TIM2_CC2 = 0x60000, /**< ADC1, ADC2: Timer 2 CC2 event */ + ADC_EXT_EV_TIM3_TRGO = 0x80000, /**< ADC1, ADC2: Timer 3 TRGO event */ + ADC_EXT_EV_TIM4_CC4 = 0xA0000, /**< ADC1, ADC2: Timer 4 CC4 event */ + ADC_EXT_EV_EXTI11 = 0xC0000, /**< ADC1, ADC2: EXTI11 event */ + + /* Common: */ + ADC_EXT_EV_TIM1_CC3 = 0x40000, /**< ADC1, ADC2, ADC3: Timer 1 CC3 event */ + ADC_EXT_EV_SWSTART = 0xE0000, /**< ADC1, ADC2, ADC3: Software start */ + + /* HD only: */ + ADC_EXT_EV_TIM3_CC1 = 0x00000, /**< + * ADC3: Timer 3 CC1 event + * Availability: high- and XL-density. */ + ADC_EXT_EV_TIM2_CC3 = 0x20000, /**< + * ADC3: Timer 2 CC3 event + * Availability: high- and XL-density. */ + ADC_EXT_EV_TIM8_CC1 = 0x60000, /**< + * ADC3: Timer 8 CC1 event + * Availability: high- and XL-density. */ + ADC_EXT_EV_ADC3_TIM8_TRGO = 0x80000, /**< + * ADC3: Timer 8 TRGO event + * Availability: high- and XL-density. */ + ADC_EXT_EV_TIM5_CC1 = 0xA0000, /**< + * ADC3: Timer 5 CC1 event + * Availability: high- and XL-density. */ + ADC_EXT_EV_ADC12_TIM8_TRGO = 0xC0000, /**< + * ADC1, ADC2: Timer 8 TRGO event + * Availability: high- and XL-density. */ + ADC_EXT_EV_TIM5_CC3 = 0xC0000, /**< + * ADC3: Timer 5 CC3 event + * Availability: high- and XL-density. */ +} adc_extsel_event; + +/* We'll keep these old adc_extsel_event enumerators around for a + * while, for backwards compatibility: */ +/** Deprecated. Use ADC_EXT_EV_TIM1_CC1 instead. */ +#define ADC_ADC12_TIM1_CC1 ADC_EXT_EV_TIM1_CC1 +/** Deprecated. Use ADC_EXT_EV_TIM1_CC2 instead. */ +#define ADC_ADC12_TIM1_CC2 ADC_EXT_EV_TIM1_CC2 +/** Deprecated. Use ADC_EXT_EV_TIM1_CC3 instead. */ +#define ADC_ADC12_TIM1_CC3 ADC_EXT_EV_TIM1_CC3 +/** Deprecated. Use ADC_EXT_EV_TIM2_CC2 instead. */ +#define ADC_ADC12_TIM2_CC2 ADC_EXT_EV_TIM2_CC2 +/** Deprecated. Use ADC_EXT_EV_TIM3_TRGO instead. */ +#define ADC_ADC12_TIM3_TRGO ADC_EXT_EV_TIM3_TRGO +/** Deprecated. Use ADC_EXT_EV_TIM4_CC4 instead. */ +#define ADC_ADC12_TIM4_CC4 ADC_EXT_EV_TIM4_CC4 +/** Deprecated. Use ADC_EXT_EV_EXTI11 instead. */ +#define ADC_ADC12_EXTI11 ADC_EXT_EV_EXTI11 +/** Deprecated. Use ADC_EXT_EV_ADC12_TIM8_TRGO instead. */ +#define ADC_ADC12_TIM8_TRGO ADC_EXT_EV_ADC12_TIM8_TRGO +/** Deprecated. Use ADC_EXT_EV_SWSTART instead. */ +#define ADC_ADC12_SWSTART ADC_EXT_EV_SWSTART +/** Deprecated. Use ADC_EXT_EV_TIM1_CC1 instead. */ +#define ADC_ADC3_TIM3_CC1 ADC_EXT_EV_TIM1_CC1 +/** Deprecated. Use ADC_EXT_EV_TIM1_CC2 instead. */ +#define ADC_ADC3_TIM2_CC3 ADC_EXT_EV_TIM1_CC2 +/** Deprecated. Use ADC_EXT_EV_TIM1_CC3 instead. */ +#define ADC_ADC3_TIM1_CC3 ADC_EXT_EV_TIM1_CC3 +/** Deprecated. Use ADC_EXT_EV_TIM2_CC2 instead. */ +#define ADC_ADC3_TIM8_CC1 ADC_EXT_EV_TIM2_CC2 +/** Deprecated. Use ADC_EXT_EV_TIM3_TRGO instead. */ +#define ADC_ADC3_TIM8_TRGO ADC_EXT_EV_TIM3_TRGO +/** Deprecated. Use ADC_EXT_EV_TIM4_CC4 instead. */ +#define ADC_ADC3_TIM5_CC1 ADC_EXT_EV_TIM4_CC4 +/** Deprecated. Use ADC_EXT_EV_EXTI11 instead. */ +#define ADC_ADC3_TIM5_CC3 ADC_EXT_EV_EXTI11 +/** Deprecated. Use ADC_EXT_EV_TIM8_TRGO instead. */ +#define ADC_ADC3_SWSTART ADC_EXT_EV_TIM8_TRGO +/** Deprecated. Use ADC_EXT_EV_SWSTART instead. */ +#define ADC_SWSTART ADC_EXT_EV_SWSTART + +/** + * @brief STM32F1 sample times, in ADC clock cycles. + * + * These control the amount of time spent sampling the input voltage. + * + * IMPORTANT: maximum external impedance must be below 0.4kOhms for + * 1.5 cycle sampling time. At 55.5 cycles/sample, the external input + * impedance must be at most 50kOhms. See your device's datasheet for + * more information. + */ +typedef enum adc_smp_rate { + ADC_SMPR_1_5, /**< 1.5 ADC cycles */ + ADC_SMPR_7_5, /**< 7.5 ADC cycles */ + ADC_SMPR_13_5, /**< 13.5 ADC cycles */ + ADC_SMPR_28_5, /**< 28.5 ADC cycles */ + ADC_SMPR_41_5, /**< 41.5 ADC cycles */ + ADC_SMPR_55_5, /**< 55.5 ADC cycles */ + ADC_SMPR_71_5, /**< 71.5 ADC cycles */ + ADC_SMPR_239_5, /**< 239.5 ADC cycles */ +} adc_smp_rate; + +/** + * @brief STM32F1 ADC prescalers, as divisors of PCLK2. + */ +typedef enum adc_prescaler { + ADC_PRE_PCLK2_DIV_2 = RCC_ADCPRE_PCLK_DIV_2, /** PCLK2 divided by 2 */ + ADC_PRE_PCLK2_DIV_4 = RCC_ADCPRE_PCLK_DIV_4, /** PCLK2 divided by 4 */ + ADC_PRE_PCLK2_DIV_6 = RCC_ADCPRE_PCLK_DIV_6, /** PCLK2 divided by 6 */ + ADC_PRE_PCLK2_DIV_8 = RCC_ADCPRE_PCLK_DIV_8, /** PCLK2 divided by 8 */ +} adc_prescaler; + +/* + * Routines + */ + +void adc_calibrate(const adc_dev *dev); + +/** + * @brief Set external trigger conversion mode event for regular channels + * + * Availability: STM32F1. + * + * @param dev ADC device + * @param enable If 1, conversion on external events is enabled; if 0, + * disabled. + */ +static inline void adc_set_exttrig(const adc_dev *dev, uint8 enable) { + *bb_perip(&dev->regs->CR2, ADC_CR2_EXTTRIG_BIT) = !!enable; +} + +#endif diff --git a/libmaple/stm32f1/rules.mk b/libmaple/stm32f1/rules.mk index bdff00e..c0d6344 100644 --- a/libmaple/stm32f1/rules.mk +++ b/libmaple/stm32f1/rules.mk @@ -11,7 +11,8 @@ CFLAGS_$(d) = -I$(d) $(LIBMAPLE_PRIVATE_INCLUDES) $(LIBMAPLE_INCLUDES) -Wall -We sSRCS_$(d) := isrs_performance.S sSRCS_$(d) += vector_table_performance.S -cSRCS_$(d) := bkp.c +cSRCS_$(d) := adc.c +cSRCS_$(d) += bkp.c cSRCS_$(d) += fsmc.c cSRCS_$(d) += gpio.c cSRCS_$(d) += rcc.c diff --git a/libmaple/stm32f2/adc.c b/libmaple/stm32f2/adc.c new file mode 100644 index 0000000..fbe1618 --- /dev/null +++ b/libmaple/stm32f2/adc.c @@ -0,0 +1,84 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f2/include/series/adc.c + * @brief STM32F2 ADC header. + */ + +#include +#include + +/* + * Devices + */ + +static adc_dev adc1 = { + .regs = ADC1_BASE, + .clk_id = RCC_ADC1, +}; +/** ADC1 device. */ +const adc_dev *ADC1 = &adc1; + +static adc_dev adc2 = { + .regs = ADC2_BASE, + .clk_id = RCC_ADC2, +}; +/** ADC2 device. */ +const adc_dev *ADC2 = &adc2; + +adc_dev adc3 = { + .regs = ADC3_BASE, + .clk_id = RCC_ADC3, +}; +/** ADC3 device. */ +const adc_dev *ADC3 = &adc3; + +/* + * Common routines + */ + +void adc_set_prescaler(adc_prescaler pre) { + uint32 ccr = ADC_COMMON_BASE->CCR; + ccr &= ~ADC_CCR_ADCPRE; + ccr |= (uint32)pre; + ADC_COMMON_BASE->CCR = ccr; +} + +void adc_foreach(void (*fn)(const adc_dev*)) { + fn(ADC1); + fn(ADC2); + fn(ADC3); +} + +void adc_gpio_cfg(gpio_dev *gdev, uint8 bit) { + gpio_set_modef(gdev, bit, GPIO_MODE_ANALOG, GPIO_MODEF_PUPD_NONE); +} + +void adc_enable_single_swstart(const adc_dev *dev) { + adc_init(dev); + adc_enable(dev); +} diff --git a/libmaple/stm32f2/include/series/adc.h b/libmaple/stm32f2/include/series/adc.h new file mode 100644 index 0000000..4f0cd6b --- /dev/null +++ b/libmaple/stm32f2/include/series/adc.h @@ -0,0 +1,331 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file stm32f2/include/series/adc.h + * @author Marti Bolivar , + * @brief STM32F2 ADC header. + */ + +#ifndef _LIBMAPLE_STM32F2_ADC_H_ +#define _LIBMAPLE_STM32F2_ADC_H_ + +#include + +/* + * Devices + */ + +extern const struct adc_dev *ADC1; +extern const struct adc_dev *ADC2; +extern const struct adc_dev *ADC3; + +/* + * Common register map + */ + +/** ADC common register map type */ +typedef struct adc_common_reg_map { + __io uint32 CSR; /**< Common status register */ + __io uint32 CCR; /**< Common control register */ + __io uint32 CDR; /**< + * @brief Common regular data register + * for dual and triple modes */ +} adc_common_reg_map; + +/* + * Register map base pointers + */ + +/** ADC1 register map base pointer. */ +#define ADC1_BASE ((struct adc_reg_map*)0x40012000) +/** ADC2 register map base pointer. */ +#define ADC2_BASE ((struct adc_reg_map*)0x40012100) +/** ADC3 register map base pointer. */ +#define ADC3_BASE ((struct adc_reg_map*)0x40012200) +/** ADC common register map base pointer. */ +#define ADC_COMMON_BASE ((struct adc_common_reg_map*)0x40012300) + +/* + * Register bit definitions + */ + +/* Status register */ + +/** Overrun bit. */ +#define ADC_SR_OVR_BIT 5 +/** Overrun. */ +#define ADC_SR_OVR (1U << ADC_SR_OVR_BIT) + +/* Control register 1 */ + +/** Overrun interrupt enable bit. */ +#define ADC_CR1_OVRIE_BIT 26 + +/** Overrun interrupt error enable. */ +#define ADC_CR1_OVRIE (1U << ADC_CR1_OVRIE_BIT) +/** Conversion resolution. */ +#define ADC_CR1_RES (0x3U << 24) +/** Conversion resolution: 12 bit (at least 15 ADCCLK cycles). */ +#define ADC_CR1_RES_12BIT (0x0U << 24) +/** Conversion resolution: 10 bit (at least 13 ADCCLK cycles). */ +#define ADC_CR1_RES_10BIT (0x1U << 24) +/** Conversion resolution: 8 bit (at least 11 ADCCLK cycles). */ +#define ADC_CR1_RES_8BIT (0x2U << 24) +/** Conversion resolution: 6 bit (at least 9 ADCCLK cycles). */ +#define ADC_CR1_RES_6BIT (0x3U << 24) + +/* Control register 2 */ + +#define ADC_CR2_SWSTART_BIT 30 +#define ADC_CR2_JSWSTART_BIT 22 +#define ADC_CR2_ALIGN_BIT 11 +#define ADC_CR2_EOCS_BIT 10 +#define ADC_CR2_DDS_BIT 9 +#define ADC_CR2_DMA_BIT 8 +#define ADC_CR2_CONT_BIT 1 +#define ADC_CR2_ADON_BIT 0 + +#define ADC_CR2_SWSTART (1U << ADC_CR2_SWSTART_BIT) +#define ADC_CR2_EXTEN (0x3 << 28) +#define ADC_CR2_EXTEN_DISABLED (0x0 << 28) +#define ADC_CR2_EXTEN_RISE (0x1 << 28) +#define ADC_CR2_EXTEN_FALL (0x2 << 28) +#define ADC_CR2_EXTEN_RISE_FALL (0x3 << 28) +#define ADC_CR2_EXTSEL (0xF << 24) +#define ADC_CR2_EXTSEL_TIM1_CC1 (0x0 << 24) +#define ADC_CR2_EXTSEL_TIM1_CC2 (0x1 << 24) +#define ADC_CR2_EXTSEL_TIM1_CC3 (0x2 << 24) +#define ADC_CR2_EXTSEL_TIM2_CC2 (0x3 << 24) +#define ADC_CR2_EXTSEL_TIM2_CC3 (0x4 << 24) +#define ADC_CR2_EXTSEL_TIM2_CC4 (0x5 << 24) +#define ADC_CR2_EXTSEL_TIM1_TRGO (0x6 << 24) +#define ADC_CR2_EXTSEL_TIM3_CC1 (0x7 << 24) +#define ADC_CR2_EXTSEL_TIM3_TRGO (0x8 << 24) +#define ADC_CR2_EXTSEL_TIM4_CC4 (0x9 << 24) +#define ADC_CR2_EXTSEL_TIM5_CC1 (0xA << 24) +#define ADC_CR2_EXTSEL_TIM5_CC2 (0xB << 24) +#define ADC_CR2_EXTSEL_TIM5_CC3 (0xC << 24) +#define ADC_CR2_EXTSEL_TIM8_CC1 (0xD << 24) +#define ADC_CR2_EXTSEL_TIM8_TRGO (0xE << 24) +#define ADC_CR2_EXTSEL_TIM1_EXTI11 (0xF << 24) +#define ADC_CR2_JSWSTART (1U << ADC_CR2_JSWSTART_BIT) +#define ADC_CR2_JEXTEN (0x3 << 20) +#define ADC_CR2_JEXTEN_DISABLED (0x0 << 20) +#define ADC_CR2_JEXTEN_RISE (0x1 << 20) +#define ADC_CR2_JEXTEN_FALL (0x2 << 20) +#define ADC_CR2_JEXTEN_RISE_FALL (0x3 << 20) +#define ADC_CR2_JEXTSEL (0xF << 16) +#define ADC_CR2_JEXTSEL_TIM1_CC4 (0x0 << 16) +#define ADC_CR2_JEXTSEL_TIM1_TRGO (0x1 << 16) +#define ADC_CR2_JEXTSEL_TIM2_CC1 (0x2 << 16) +#define ADC_CR2_JEXTSEL_TIM2_TRGO (0x3 << 16) +#define ADC_CR2_JEXTSEL_TIM3_CC2 (0x4 << 16) +#define ADC_CR2_JEXTSEL_TIM3_CC4 (0x5 << 16) +#define ADC_CR2_JEXTSEL_TIM4_CC1 (0x6 << 16) +#define ADC_CR2_JEXTSEL_TIM4_CC2 (0x7 << 16) +#define ADC_CR2_JEXTSEL_TIM4_CC3 (0x8 << 16) +#define ADC_CR2_JEXTSEL_TIM4_TRGO (0x9 << 16) +#define ADC_CR2_JEXTSEL_TIM5_CC4 (0xA << 16) +#define ADC_CR2_JEXTSEL_TIM5_TRGO (0xB << 16) +#define ADC_CR2_JEXTSEL_TIM8_CC2 (0xC << 16) +#define ADC_CR2_JEXTSEL_TIM8_CC3 (0xD << 16) +#define ADC_CR2_JEXTSEL_TIM8_CC4 (0xE << 16) +#define ADC_CR2_JEXTSEL_TIM1_EXTI15 (0xF << 16) +#define ADC_CR2_ALIGN (1U << ADC_CR2_ALIGN_BIT) +#define ADC_CR2_ALIGN_RIGHT (0U << ADC_CR2_ALIGN_BIT) +#define ADC_CR2_ALIGN_LEFT (1U << ADC_CR2_ALIGN_BIT) +#define ADC_CR2_EOCS (1U << ADC_CR2_EOCS_BIT) +#define ADC_CR2_EOCS_SEQUENCE (0U << ADC_CR2_EOCS_BIT) +#define ADC_CR2_EOCS_CONVERSION (1U << ADC_CR2_EOCS_BIT) +#define ADC_CR2_DDS (1U << ADC_CR2_DDS_BIT) +#define ADC_CR2_DMA (1U << ADC_CR2_DMA_BIT) +#define ADC_CR2_CONT (1U << ADC_CR2_CONT_BIT) +#define ADC_CR2_ADON (1U << ADC_CR2_ADON_BIT) + +/* Common status register */ + +#define ADC_CSR_OVR3_BIT 21 +#define ADC_CSR_STRT3_BIT 20 +#define ADC_CSR_JSTRT3_BIT 19 +#define ADC_CSR_JEOC3_BIT 18 +#define ADC_CSR_EOC3_BIT 17 +#define ADC_CSR_AWD3_BIT 16 +#define ADC_CSR_OVR2_BIT 13 +#define ADC_CSR_STRT2_BIT 12 +#define ADC_CSR_JSTRT2_BIT 11 +#define ADC_CSR_JEOC2_BIT 10 +#define ADC_CSR_EOC2_BIT 9 +#define ADC_CSR_AWD2_BIT 8 +#define ADC_CSR_OVR1_BIT 5 +#define ADC_CSR_STRT1_BIT 4 +#define ADC_CSR_JSTRT1_BIT 3 +#define ADC_CSR_JEOC1_BIT 2 +#define ADC_CSR_EOC1_BIT 1 +#define ADC_CSR_AWD1_BIT 0 + +#define ADC_CSR_OVR3 (1U << ADC_CSR_OVR3_BIT) +#define ADC_CSR_STRT3 (1U << ADC_CSR_STRT3_BIT) +#define ADC_CSR_JSTRT3 (1U << ADC_CSR_JSTRT3_BIT) +#define ADC_CSR_JEOC3 (1U << ADC_CSR_JEOC3_BIT) +#define ADC_CSR_EOC3 (1U << ADC_CSR_EOC3_BIT) +#define ADC_CSR_AWD3 (1U << ADC_CSR_AWD3_BIT) +#define ADC_CSR_OVR2 (1U << ADC_CSR_OVR2_BIT) +#define ADC_CSR_STRT2 (1U << ADC_CSR_STRT2_BIT) +#define ADC_CSR_JSTRT2 (1U << ADC_CSR_JSTRT2_BIT) +#define ADC_CSR_JEOC2 (1U << ADC_CSR_JEOC2_BIT) +#define ADC_CSR_EOC2 (1U << ADC_CSR_EOC2_BIT) +#define ADC_CSR_AWD2 (1U << ADC_CSR_AWD2_BIT) +#define ADC_CSR_OVR1 (1U << ADC_CSR_OVR1_BIT) +#define ADC_CSR_STRT1 (1U << ADC_CSR_STRT1_BIT) +#define ADC_CSR_JSTRT1 (1U << ADC_CSR_JSTRT1_BIT) +#define ADC_CSR_JEOC1 (1U << ADC_CSR_JEOC1_BIT) +#define ADC_CSR_EOC1 (1U << ADC_CSR_EOC1_BIT) +#define ADC_CSR_AWD1 (1U << ADC_CSR_AWD1_BIT) + +/* Common control register */ + +#define ADC_CCR_TSVREFE_BIT 23 +#define ADC_CCR_VBATE_BIT 22 +#define ADC_CCR_DDS_BIT 13 + +#define ADC_CCR_TSVREFE (1U << ADC_CCR_TSVREFE_BIT) +#define ADC_CCR_VBATE (1U << ADC_CCR_VBATE_BIT) +#define ADC_CCR_ADCPRE (0x3 << 16) +#define ADC_CCR_ADCPRE_PCLK2_DIV_2 (0x0 << 16) +#define ADC_CCR_ADCPRE_PCLK2_DIV_4 (0x1 << 16) +#define ADC_CCR_ADCPRE_PCLK2_DIV_6 (0x2 << 16) +#define ADC_CCR_ADCPRE_PCLK2_DIV_8 (0x3 << 16) +#define ADC_CCR_DMA (0x3 << 14) +#define ADC_CCR_DMA_DIS (0x0 << 14) +#define ADC_CCR_DMA_MODE_1 (0x1 << 14) +#define ADC_CCR_DMA_MODE_2 (0x2 << 14) +#define ADC_CCR_DMA_MODE_3 (0x3 << 14) +#define ADC_CCR_DDS (1U << ADC_CCR_DDS_BIT) +#define ADC_CCR_DELAY (0xF << 8) +#define ADC_CCR_DELAY_5 (0x0 << 8) +#define ADC_CCR_DELAY_6 (0x1 << 8) +#define ADC_CCR_DELAY_7 (0x2 << 8) +#define ADC_CCR_DELAY_8 (0x3 << 8) +#define ADC_CCR_DELAY_9 (0x4 << 8) +#define ADC_CCR_DELAY_10 (0x5 << 8) +#define ADC_CCR_DELAY_11 (0x6 << 8) +#define ADC_CCR_DELAY_12 (0x7 << 8) +#define ADC_CCR_DELAY_13 (0x8 << 8) +#define ADC_CCR_DELAY_14 (0x9 << 8) +#define ADC_CCR_DELAY_15 (0xA << 8) +#define ADC_CCR_DELAY_16 (0xB << 8) +#define ADC_CCR_DELAY_17 (0xC << 8) +#define ADC_CCR_DELAY_18 (0xD << 8) +#define ADC_CCR_DELAY_19 (0xE << 8) +#define ADC_CCR_DELAY_20 (0xF << 8) +/** Multi ADC mode selection. */ +#define ADC_CCR_MULTI 0x1F +/** All ADCs independent. */ +#define ADC_CCR_MULTI_INDEPENDENT 0x0 +/** Dual mode: combined regular simultaneous/injected simultaneous. */ +#define ADC_CCR_MULTI_DUAL_REG_SIM_INJ_SIM 0x1 +/** Dual mode: combined regular simultaneous/alternate trigger. */ +#define ADC_CCR_MULTI_DUAL_REG_SIM_ALT_TRIG 0x2 +/** Dual mode: injected simultaneous mode only. */ +#define ADC_CCR_MULTI_DUAL_INJ_SIM 0x5 +/** Dual mode: regular simultaneous mode only. */ +#define ADC_CCR_MULTI_DUAL_REG_SIM 0x6 +/** Dual mode: interleaved mode only. */ +#define ADC_CCR_MULTI_DUAL_INTER 0x7 +/** Dual mode: alternate trigger mode only. */ +#define ADC_CCR_MULTI_DUAL_ALT_TRIG 0x9 +/** Triple mode: combined regular simultaneous/injected simultaneous. */ +#define ADC_CCR_MULTI_TRIPLE_REG_SIM_INJ_SIM 0x10 +/** Triple mode: combined regular simultaneous/alternate trigger. */ +#define ADC_CCR_MULTI_TRIPLE_REG_SIM_ALT_TRIG 0x11 +/** Triple mode: injected simultaneous mode only. */ +#define ADC_CCR_MULTI_TRIPLE_INJ_SIM 0x12 +/** Triple mode: regular simultaneous mode only. */ +#define ADC_CCR_MULTI_TRIPLE_REG_SIM 0x15 +/** Triple mode: interleaved mode only. */ +#define ADC_CCR_MULTI_TRIPLE_INTER 0x17 +/** Triple mode: alternate trigger mode only. */ +#define ADC_CCR_MULTI_TRIPLE_ALT_TRIG 0x19 + +/* Common regular data register for dual and triple modes */ + +#define ADC_CDR_DATA2 0xFFFF0000 +#define ADC_CDR_DATA1 0xFFFF + +/* + * Other types + */ + +/** + * @brief STM32F2 external event selectors for regular group + * conversion. + * @see adc_set_extsel() + */ +typedef enum adc_extsel_event { + ADC_EXT_EV_TIM1_CC1 = ADC_CR2_EXTSEL_TIM1_CC1, + ADC_EXT_EV_TIM1_CC2 = ADC_CR2_EXTSEL_TIM1_CC2, + ADC_EXT_EV_TIM1_CC3 = ADC_CR2_EXTSEL_TIM1_CC3, + ADC_EXT_EV_TIM2_CC2 = ADC_CR2_EXTSEL_TIM2_CC2, + ADC_EXT_EV_TIM2_CC3 = ADC_CR2_EXTSEL_TIM2_CC3, + ADC_EXT_EV_TIM2_CC4 = ADC_CR2_EXTSEL_TIM2_CC4, + ADC_EXT_EV_TIM1_TRGO = ADC_CR2_EXTSEL_TIM1_TRGO, + ADC_EXT_EV_TIM3_CC1 = ADC_CR2_EXTSEL_TIM3_CC1, + ADC_EXT_EV_TIM3_TRGO = ADC_CR2_EXTSEL_TIM3_TRGO, + ADC_EXT_EV_TIM4_CC4 = ADC_CR2_EXTSEL_TIM4_CC4, + ADC_EXT_EV_TIM5_CC1 = ADC_CR2_EXTSEL_TIM5_CC1, + ADC_EXT_EV_TIM5_CC2 = ADC_CR2_EXTSEL_TIM5_CC2, + ADC_EXT_EV_TIM5_CC3 = ADC_CR2_EXTSEL_TIM5_CC3, + ADC_EXT_EV_TIM8_CC1 = ADC_CR2_EXTSEL_TIM8_CC1, + ADC_EXT_EV_TIM8_TRGO = ADC_CR2_EXTSEL_TIM8_TRGO, + ADC_EXT_EV_TIM1_EXTI11 = ADC_CR2_EXTSEL_TIM1_EXTI11, +} adc_extsel_event; + +/** + * @brief STM32F2 sample times, in ADC clock cycles. + */ +typedef enum adc_smp_rate { + ADC_SMPR_3, /**< 3 ADC cycles */ + ADC_SMPR_15, /**< 15 ADC cycles */ + ADC_SMPR_28, /**< 28 ADC cycles */ + ADC_SMPR_56, /**< 56 ADC cycles */ + ADC_SMPR_84, /**< 84 ADC cycles */ + ADC_SMPR_112, /**< 112 ADC cycles */ + ADC_SMPR_144, /**< 144 ADC cycles */ + ADC_SMPR_480, /**< 480 ADC cycles */ +} adc_smp_rate; + +/** + * @brief STM32F2 ADC prescalers, as divisors of PCLK2. + */ +typedef enum adc_prescaler { + ADC_PRE_PCLK2_DIV_2 = ADC_CCR_ADCPRE_PCLK2_DIV_2, /** PCLK2 divided by 2 */ + ADC_PRE_PCLK2_DIV_4 = ADC_CCR_ADCPRE_PCLK2_DIV_4, /** PCLK2 divided by 4 */ + ADC_PRE_PCLK2_DIV_6 = ADC_CCR_ADCPRE_PCLK2_DIV_6, /** PCLK2 divided by 6 */ + ADC_PRE_PCLK2_DIV_8 = ADC_CCR_ADCPRE_PCLK2_DIV_8, /** PCLK2 divided by 8 */ +} adc_prescaler; + +#endif diff --git a/libmaple/stm32f2/rules.mk b/libmaple/stm32f2/rules.mk index a46f8d1..5951b94 100644 --- a/libmaple/stm32f2/rules.mk +++ b/libmaple/stm32f2/rules.mk @@ -11,6 +11,7 @@ CFLAGS_$(d) = -I$(d) $(LIBMAPLE_INCLUDES) $(LIBMAPLE_PRIVATE_INCLUDES) -Wall -We sSRCS_$(d) := isrs.S sSRCS_$(d) += vector_table.S +cSRCS_$(d) := adc.c cSRCS_$(d) += fsmc.c cSRCS_$(d) += gpio.c cSRCS_$(d) += rcc.c diff --git a/wirish/boards.cpp b/wirish/boards.cpp index 04b359f..54807d3 100644 --- a/wirish/boards.cpp +++ b/wirish/boards.cpp @@ -54,6 +54,7 @@ static void setup_flash(void); static void setup_clocks(void); static void setup_nvic(void); +static void setup_adcs(void); /* * Exported functions @@ -65,7 +66,7 @@ void init(void) { setup_nvic(); systick_init(SYSTICK_RELOAD_VAL); wirish::priv::board_setup_gpio(); - wirish::priv::board_setup_adc(); + setup_adcs(); wirish::priv::board_setup_timers(); wirish::priv::board_setup_usb(); boardInit(); @@ -124,7 +125,7 @@ static void setup_clocks(void) { // Configure AHBx, APBx, etc. prescalers and the main PLL. wirish::priv::board_setup_clock_prescalers(); - rcc_configure_pll(&wirish::priv::board_pll_cfg); + rcc_configure_pll(&wirish::priv::w_board_pll_cfg); // Enable the PLL, and wait until it's ready. rcc_turn_on_clk(RCC_CLK_PLL); @@ -146,3 +147,13 @@ static void setup_nvic(void) { #error "You must select a base address for the vector table." #endif } + +static void adc_default_config(const adc_dev *dev) { + adc_enable_single_swstart(dev); + adc_set_sample_rate(dev, wirish::priv::w_adc_smp); +} + +static void setup_adcs(void) { + adc_set_prescaler(wirish::priv::w_adc_pre); + adc_foreach(adc_default_config); +} diff --git a/wirish/boards_private.h b/wirish/boards_private.h index a4101c9..e32f298 100644 --- a/wirish/boards_private.h +++ b/wirish/boards_private.h @@ -28,11 +28,18 @@ * @file wirish/boards_private.h * @author Marti Bolivar * @brief Private board support header. + * + * This file declares chip-specific variables and functions which + * determine how init() behaves. It is not part of the public Wirish + * API, and can change without notice. */ #ifndef _WIRISH_BOARDS_PRIVATE_H_ #define _WIRISH_BOARDS_PRIVATE_H_ +#include +#include + namespace wirish { namespace priv { @@ -40,7 +47,9 @@ namespace wirish { * Chip-specific initialization data */ - extern rcc_pll_cfg board_pll_cfg; + extern rcc_pll_cfg w_board_pll_cfg; + extern adc_prescaler w_adc_pre; + extern adc_smp_rate w_adc_smp; /* * Chip-specific initialization routines and helper functions. @@ -49,7 +58,6 @@ namespace wirish { void board_reset_pll(void); void board_setup_clock_prescalers(void); void board_setup_gpio(void); - void board_setup_adc(void); void board_setup_timers(void); void board_setup_usb(void); diff --git a/wirish/stm32f1/boards_setup.cpp b/wirish/stm32f1/boards_setup.cpp index 4ee292a..8e16009 100644 --- a/wirish/stm32f1/boards_setup.cpp +++ b/wirish/stm32f1/boards_setup.cpp @@ -28,11 +28,15 @@ * @file wirish/stm32f1/boards_setup.cpp * @author Marti Bolivar * @brief STM32F1 chip setup. + * + * This file controls how init() behaves on the STM32F1. Be very + * careful when changing anything here. Many of these values depend + * upon each other. */ -#include +#include "boards_private.h" + #include -#include #include #include @@ -45,12 +49,11 @@ namespace wirish { namespace priv { static stm32f1_rcc_pll_data pll_data = {RCC_PLLMUL_9}; - rcc_pll_cfg board_pll_cfg = {RCC_PLLSRC_HSE, &pll_data}; + rcc_pll_cfg w_board_pll_cfg = {RCC_PLLSRC_HSE, &pll_data}; + adc_prescaler w_adc_pre = ADC_PRE_PCLK2_DIV_6; + adc_smp_rate w_adc_smp = ADC_SMPR_55_5; -#if 0 - static void config_adc(const adc_dev* dev); static void config_timer(timer_dev*); -#endif void board_reset_pll(void) { // TODO @@ -69,17 +72,8 @@ namespace wirish { afio_init(); } - void board_setup_adc(void) { -#if 0 - rcc_set_prescaler(RCC_PRESCALER_ADC, RCC_ADCPRE_PCLK_DIV_6); - adc_foreach(config_adc); -#endif - } - void board_setup_timers(void) { -#if 0 timer_foreach(config_timer); -#endif } void board_setup_usb(void) { @@ -92,19 +86,8 @@ namespace wirish { * Auxiliary routines */ -#if 0 - static void config_adc(const adc_dev *dev) { - adc_init(dev); - - adc_set_extsel(dev, ADC_SWSTART); - adc_set_exttrig(dev, true); - - adc_enable(dev); - adc_calibrate(dev); - adc_set_sample_rate(dev, ADC_SMPR_55_5); - } - static void config_timer(timer_dev *dev) { +#if 0 timer_adv_reg_map *regs = (dev->regs).adv; const uint16 full_overflow = 0xFFFF; const uint16 half_duty = 0x8FFF; @@ -135,7 +118,7 @@ namespace wirish { } timer_resume(dev); - } #endif + } } } diff --git a/wirish/stm32f2/boards_setup.cpp b/wirish/stm32f2/boards_setup.cpp index b3c690c..e1bf1fd 100644 --- a/wirish/stm32f2/boards_setup.cpp +++ b/wirish/stm32f2/boards_setup.cpp @@ -28,11 +28,18 @@ * @file wirish/stm32f2/boards_setup.cpp * @author Marti Bolivar * @brief STM32F2 chip setup. + * + * This file controls how init() behaves on the STM32F2. Be very + * careful when changing anything here. Many of these values depend + * upon each other. */ -#include +#include "boards_private.h" + #include +#include +// PLL configuration for 25 MHz external oscillator --> 120 MHz SYSCLK. #define PLL_Q 5 #define PLL_P 2 #define PLL_N 240 @@ -41,7 +48,18 @@ static stm32f2_rcc_pll_data pll_data = {PLL_Q, PLL_P, PLL_N, PLL_M}; namespace wirish { namespace priv { - rcc_pll_cfg board_pll_cfg = {RCC_PLLSRC_HSE, &pll_data}; + // PLL clocked off of HSE, with above configuration data. + rcc_pll_cfg w_board_pll_cfg = {RCC_PLLSRC_HSE, &pll_data}; + // As f_APB2 = 60 MHz (see board_setup_clock_prescalers), + // we need f_ADC = f_PCLK2 / 2 to get the (maximum) + // f_ADC = 30 MHz. + adc_prescaler w_adc_pre = ADC_PRE_PCLK2_DIV_2; + // With clocks as specified here (i.e. f_ADC = 30 MHz), this + // ADC sample rate allows for error less than 1/4 LSB with a + // 50 KOhm input impedance, assuming an internal sample and + // hold capacitance C_ADC at most 8.8 pF. See Equation 1 and + // Table 61 in the F2 datasheet for more details. + adc_smp_rate w_adc_smp = ADC_SMPR_144; void board_reset_pll(void) { // Set PLLCFGR to its reset value. @@ -49,8 +67,13 @@ namespace wirish { } void board_setup_clock_prescalers(void) { + // With f_SYSCLK = 120 MHz (as determined by board_pll_cfg), + // + // f_AHB = f_SYSCLK / 1 = 120 MHz rcc_set_prescaler(RCC_PRESCALER_AHB, RCC_AHB_SYSCLK_DIV_1); + // f_APB1 = f_AHB / 4 = 30 MHz rcc_set_prescaler(RCC_PRESCALER_APB1, RCC_APB1_HCLK_DIV_4); + // f_APB2 = f_AHB / 2 = 60 MHz rcc_set_prescaler(RCC_PRESCALER_APB2, RCC_APB2_HCLK_DIV_2); } @@ -58,10 +81,6 @@ namespace wirish { gpio_init_all(); } - void board_setup_adc(void) { - // TODO - } - void board_setup_timers(void) { // TODO } @@ -72,4 +91,3 @@ namespace wirish { } } - -- cgit v1.2.3 From 9cefeca5c1927c34d64e592bb4ad7ffe7c44822c Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Thu, 5 Apr 2012 17:10:33 -0400 Subject: timer: Fixes, rip out nonportable bits. Fix copy-paste errors in, and add missing, register bit definitions. For copy-paste errors that would result in source incompatibilities with past releases, add some legacy defines. Add series header and C file for STM32F1 which fills in the missing API. Much of the F1 timer.c would be repeated on F2, so also add timer_private.h to hold these. Support for timers 9 through 14 is still missing. Signed-off-by: Marti Bolivar --- libmaple/include/libmaple/timer.h | 233 ++++++++++++++++----------- libmaple/rules.mk | 2 +- libmaple/stm32f1/include/series/timer.h | 97 +++++++++++ libmaple/stm32f1/rules.mk | 1 + libmaple/stm32f1/timer.c | 152 ++++++++++++++++++ libmaple/timer.c | 275 +------------------------------- libmaple/timer_private.h | 168 +++++++++++++++++++ 7 files changed, 568 insertions(+), 360 deletions(-) create mode 100644 libmaple/stm32f1/include/series/timer.h create mode 100644 libmaple/stm32f1/timer.c create mode 100644 libmaple/timer_private.h (limited to 'libmaple/rules.mk') diff --git a/libmaple/include/libmaple/timer.h b/libmaple/include/libmaple/timer.h index fef34fc..0a046c9 100644 --- a/libmaple/include/libmaple/timer.h +++ b/libmaple/include/libmaple/timer.h @@ -42,8 +42,15 @@ extern "C"{ #include #include +struct timer_adv_reg_map; +struct timer_gen_reg_map; +struct timer_bas_reg_map; +struct timer_dev; +/* Include the series header here, as it may need the above */ +#include + /* - * Register maps and devices + * Register maps */ /** Advanced control timer register map type */ @@ -70,29 +77,10 @@ typedef struct timer_adv_reg_map { __io uint32 DMAR; /**< DMA address for full transfer */ } timer_adv_reg_map; -/** General purpose timer register map type */ -typedef struct timer_gen_reg_map { - __io uint32 CR1; /**< Control register 1 */ - __io uint32 CR2; /**< Control register 2 */ - __io uint32 SMCR; /**< Slave mode control register */ - __io uint32 DIER; /**< DMA/Interrupt enable register */ - __io uint32 SR; /**< Status register */ - __io uint32 EGR; /**< Event generation register */ - __io uint32 CCMR1; /**< Capture/compare mode register 1 */ - __io uint32 CCMR2; /**< Capture/compare mode register 2 */ - __io uint32 CCER; /**< Capture/compare enable register */ - __io uint32 CNT; /**< Counter */ - __io uint32 PSC; /**< Prescaler */ - __io uint32 ARR; /**< Auto-reload register */ - const uint32 RESERVED1; /**< Reserved */ - __io uint32 CCR1; /**< Capture/compare register 1 */ - __io uint32 CCR2; /**< Capture/compare register 2 */ - __io uint32 CCR3; /**< Capture/compare register 3 */ - __io uint32 CCR4; /**< Capture/compare register 4 */ - const uint32 RESERVED2; /**< Reserved */ - __io uint32 DCR; /**< DMA control register */ - __io uint32 DMAR; /**< DMA address for full transfer */ -} timer_gen_reg_map; +/* timer_gen_reg_map: intentionally omitted. + * + * General purpose timers differ slightly across series, so leave it + * up to the series header to define struct timer_gen_reg_map. */ /** Basic timer register map type */ typedef struct timer_bas_reg_map { @@ -110,25 +98,6 @@ typedef struct timer_bas_reg_map { __io uint32 ARR; /**< Auto-reload register */ } timer_bas_reg_map; -/** Timer 1 register map base pointer */ -#define TIMER1_BASE ((struct timer_adv_reg_map*)0x40012C00) -/** Timer 2 register map base pointer */ -#define TIMER2_BASE ((struct timer_gen_reg_map*)0x40000000) -/** Timer 3 register map base pointer */ -#define TIMER3_BASE ((struct timer_gen_reg_map*)0x40000400) -/** Timer 4 register map base pointer */ -#define TIMER4_BASE ((struct timer_gen_reg_map*)0x40000800) -#ifdef STM32_HIGH_DENSITY -/** Timer 5 register map base pointer */ -#define TIMER5_BASE ((struct timer_gen_reg_map*)0x40000C00) -/** Timer 6 register map base pointer */ -#define TIMER6_BASE ((struct timer_bas_reg_map*)0x40001000) -/** Timer 7 register map base pointer */ -#define TIMER7_BASE ((struct timer_bas_reg_map*)0x40001400) -/** Timer 8 register map base pointer */ -#define TIMER8_BASE ((struct timer_adv_reg_map*)0x40013400) -#endif - /* * Timer devices */ @@ -163,19 +132,14 @@ typedef struct timer_dev { timer_reg_map regs; /**< Register map */ rcc_clk_id clk_id; /**< RCC clock information */ timer_type type; /**< Timer's type */ - voidFuncPtr handlers[]; /**< User IRQ handlers */ + voidFuncPtr handlers[]; /**< + * @brief User IRQ handlers + * It's not a good idea to touch these + * directly. + * @see timer_attach_interrupt() + * @see timer_detach_interrupt() */ } timer_dev; -extern timer_dev *TIMER1; -extern timer_dev *TIMER2; -extern timer_dev *TIMER3; -extern timer_dev *TIMER4; -#ifdef STM32_HIGH_DENSITY -extern timer_dev *TIMER5; -extern timer_dev *TIMER6; -extern timer_dev *TIMER7; -extern timer_dev *TIMER8; -#endif /* * Register bit definitions @@ -278,12 +242,15 @@ extern timer_dev *TIMER8; /* DMA/Interrupt enable register (DIER) */ #define TIMER_DIER_TDE_BIT 14 +#define TIMER_DIER_COMDE_BIT 13 #define TIMER_DIER_CC4DE_BIT 12 #define TIMER_DIER_CC3DE_BIT 11 #define TIMER_DIER_CC2DE_BIT 10 #define TIMER_DIER_CC1DE_BIT 9 #define TIMER_DIER_UDE_BIT 8 +#define TIMER_DIER_BIE_BIT 7 #define TIMER_DIER_TIE_BIT 6 +#define TIMER_DIER_COMIE_BIT 5 #define TIMER_DIER_CC4IE_BIT 4 #define TIMER_DIER_CC3IE_BIT 3 #define TIMER_DIER_CC2IE_BIT 2 @@ -291,12 +258,15 @@ extern timer_dev *TIMER8; #define TIMER_DIER_UIE_BIT 0 #define TIMER_DIER_TDE BIT(TIMER_DIER_TDE_BIT) +#define TIMER_DIER_COMDE BIT(TIMER_DIER_COMDE_BIT) #define TIMER_DIER_CC4DE BIT(TIMER_DIER_CC4DE_BIT) #define TIMER_DIER_CC3DE BIT(TIMER_DIER_CC3DE_BIT) #define TIMER_DIER_CC2DE BIT(TIMER_DIER_CC2DE_BIT) #define TIMER_DIER_CC1DE BIT(TIMER_DIER_CC1DE_BIT) #define TIMER_DIER_UDE BIT(TIMER_DIER_UDE_BIT) +#define TIMER_DIER_BIE BIT(TIMER_DIER_BIE_BIT) #define TIMER_DIER_TIE BIT(TIMER_DIER_TIE_BIT) +#define TIMER_DIER_COMIE BIT(TIMER_DIER_COMIE_BIT) #define TIMER_DIER_CC4IE BIT(TIMER_DIER_CC4IE_BIT) #define TIMER_DIER_CC3IE BIT(TIMER_DIER_CC3IE_BIT) #define TIMER_DIER_CC2IE BIT(TIMER_DIER_CC2IE_BIT) @@ -333,14 +303,18 @@ extern timer_dev *TIMER8; /* Event generation register (EGR) */ +#define TIMER_EGR_BG_BIT 7 #define TIMER_EGR_TG_BIT 6 +#define TIMER_EGR_COMG_BIT 5 #define TIMER_EGR_CC4G_BIT 4 #define TIMER_EGR_CC3G_BIT 3 #define TIMER_EGR_CC2G_BIT 2 #define TIMER_EGR_CC1G_BIT 1 #define TIMER_EGR_UG_BIT 0 +#define TIMER_EGR_BG BIT(TIMER_EGR_BG_BIT) #define TIMER_EGR_TG BIT(TIMER_EGR_TG_BIT) +#define TIMER_EGR_COMG BIT(TIMER_EGR_COMG_BIT) #define TIMER_EGR_CC4G BIT(TIMER_EGR_CC4G_BIT) #define TIMER_EGR_CC3G BIT(TIMER_EGR_CC3G_BIT) #define TIMER_EGR_CC2G BIT(TIMER_EGR_CC2G_BIT) @@ -397,44 +371,83 @@ extern timer_dev *TIMER8; #define TIMER_CCMR2_OC4CE BIT(TIMER_CCMR2_OC4CE_BIT) #define TIMER_CCMR2_OC4M (0x3 << 12) -#define TIMER_CCMR2_IC2F (0xF << 12) +#define TIMER_CCMR2_IC4F (0xF << 12) #define TIMER_CCMR2_OC4PE BIT(TIMER_CCMR2_OC4PE_BIT) #define TIMER_CCMR2_OC4FE BIT(TIMER_CCMR2_OC4FE_BIT) -#define TIMER_CCMR2_IC2PSC (0x3 << 10) +#define TIMER_CCMR2_IC4PSC (0x3 << 10) #define TIMER_CCMR2_CC4S (0x3 << 8) -#define TIMER_CCMR1_CC4S_OUTPUT (TIMER_CCMR_CCS_OUTPUT << 8) -#define TIMER_CCMR1_CC4S_INPUT_TI1 (TIMER_CCMR_CCS_INPUT_TI1 << 8) -#define TIMER_CCMR1_CC4S_INPUT_TI2 (TIMER_CCMR_CCS_INPUT_TI2 << 8) -#define TIMER_CCMR1_CC4S_INPUT_TRC (TIMER_CCMR_CCS_INPUT_TRC << 8) +#define TIMER_CCMR2_CC4S_OUTPUT (TIMER_CCMR_CCS_OUTPUT << 8) +#define TIMER_CCMR2_CC4S_INPUT_TI1 (TIMER_CCMR_CCS_INPUT_TI1 << 8) +#define TIMER_CCMR2_CC4S_INPUT_TI2 (TIMER_CCMR_CCS_INPUT_TI2 << 8) +#define TIMER_CCMR2_CC4S_INPUT_TRC (TIMER_CCMR_CCS_INPUT_TRC << 8) #define TIMER_CCMR2_OC3CE BIT(TIMER_CCMR2_OC3CE_BIT) #define TIMER_CCMR2_OC3M (0x3 << 4) -#define TIMER_CCMR2_IC1F (0xF << 4) +#define TIMER_CCMR2_IC3F (0xF << 4) #define TIMER_CCMR2_OC3PE BIT(TIMER_CCMR2_OC3PE_BIT) #define TIMER_CCMR2_OC3FE BIT(TIMER_CCMR2_OC3FE_BIT) -#define TIMER_CCMR2_IC1PSC (0x3 << 2) +#define TIMER_CCMR2_IC3PSC (0x3 << 2) #define TIMER_CCMR2_CC3S 0x3 -#define TIMER_CCMR1_CC3S_OUTPUT TIMER_CCMR_CCS_OUTPUT -#define TIMER_CCMR1_CC3S_INPUT_TI1 TIMER_CCMR_CCS_INPUT_TI1 -#define TIMER_CCMR1_CC3S_INPUT_TI2 TIMER_CCMR_CCS_INPUT_TI2 -#define TIMER_CCMR1_CC3S_INPUT_TRC TIMER_CCMR_CCS_INPUT_TRC +#define TIMER_CCMR2_CC3S_OUTPUT TIMER_CCMR_CCS_OUTPUT +#define TIMER_CCMR2_CC3S_INPUT_TI1 TIMER_CCMR_CCS_INPUT_TI1 +#define TIMER_CCMR2_CC3S_INPUT_TI2 TIMER_CCMR_CCS_INPUT_TI2 +#define TIMER_CCMR2_CC3S_INPUT_TRC TIMER_CCMR_CCS_INPUT_TRC + +/* Old, copy-paste error CCMR2 bit definitions from previous releases, + * kept for backwards compatibility: */ +/** Deprecated. Use TIMER_CCMR1_CC4S_OUTPUT instead. */ +#define TIMER_CCMR1_CC4S_OUTPUT TIMER_CCMR2_CC4S_OUTPUT +/** Deprecated. Use TIMER_CCMR1_CC4S_INPUT_TI1 instead. */ +#define TIMER_CCMR1_CC4S_INPUT_TI1 TIMER_CCMR2_CC4S_INPUT_TI1 +/** Deprecated. Use TIMER_CCMR1_CC4S_INPUT_TI2 instead. */ +#define TIMER_CCMR1_CC4S_INPUT_TI2 TIMER_CCMR2_CC4S_INPUT_TI2 +/** Deprecated. Use TIMER_CCMR1_CC4S_INPUT_TRC instead. */ +#define TIMER_CCMR1_CC4S_INPUT_TRC TIMER_CCMR2_CC4S_INPUT_TRC +/** Deprecated. Use TIMER_CCMR2_IC4F instead. */ +#define TIMER_CCMR2_IC2F TIMER_CCMR2_IC4F +/** Deprecated. Use TIMER_CCMR2_IC4PSC instead. */ +#define TIMER_CCMR2_IC2PSC TIMER_CCMR2_IC4PSC +/** Deprecated. Use TIMER_CCMR2_IC3F instead. */ +#define TIMER_CCMR2_IC1F TIMER_CCMR2_IC3F +/** Deprecated. Use TIMER_CCMR2_IC3PSC instead. */ +#define TIMER_CCMR2_IC1PSC TIMER_CCMR2_IC3PSC +/** Deprecated. Use TIMER_CCMR1_CC3S_OUTPUT instead. */ +#define TIMER_CCMR1_CC3S_OUTPUT TIMER_CCMR2_CC3S_OUTPUT +/** Deprecated. Use TIMER_CCMR1_CC3S_INPUT_TI1 instead. */ +#define TIMER_CCMR1_CC3S_INPUT_TI1 TIMER_CCMR2_CC3S_INPUT_TI1 +/** Deprecated. Use TIMER_CCMR1_CC3S_INPUT_TI2 instead. */ +#define TIMER_CCMR1_CC3S_INPUT_TI2 TIMER_CCMR2_CC3S_INPUT_TI2 +/** Deprecated. Use TIMER_CCMR1_CC3S_INPUT_TRC instead. */ +#define TIMER_CCMR1_CC3S_INPUT_TRC TIMER_CCMR2_CC3S_INPUT_TRC /* Capture/compare enable register (CCER) */ #define TIMER_CCER_CC4P_BIT 13 #define TIMER_CCER_CC4E_BIT 12 +#define TIMER_CCER_CC3NP_BIT 11 +#define TIMER_CCER_CC3NE_BIT 10 #define TIMER_CCER_CC3P_BIT 9 #define TIMER_CCER_CC3E_BIT 8 +#define TIMER_CCER_CC2NP_BIT 7 +#define TIMER_CCER_CC2NE_BIT 6 #define TIMER_CCER_CC2P_BIT 5 #define TIMER_CCER_CC2E_BIT 4 +#define TIMER_CCER_CC1NP_BIT 3 +#define TIMER_CCER_CC1NE_BIT 2 #define TIMER_CCER_CC1P_BIT 1 #define TIMER_CCER_CC1E_BIT 0 #define TIMER_CCER_CC4P BIT(TIMER_CCER_CC4P_BIT) #define TIMER_CCER_CC4E BIT(TIMER_CCER_CC4E_BIT) +#define TIMER_CCER_CC3NP BIT(TIMER_CCER_CC3NP_BIT) +#define TIMER_CCER_CC3NE BIT(TIMER_CCER_CC3NE_BIT) #define TIMER_CCER_CC3P BIT(TIMER_CCER_CC3P_BIT) #define TIMER_CCER_CC3E BIT(TIMER_CCER_CC3E_BIT) +#define TIMER_CCER_CC2NP BIT(TIMER_CCER_CC2NP_BIT) +#define TIMER_CCER_CC2NE BIT(TIMER_CCER_CC2NE_BIT) #define TIMER_CCER_CC2P BIT(TIMER_CCER_CC2P_BIT) #define TIMER_CCER_CC2E BIT(TIMER_CCER_CC2E_BIT) +#define TIMER_CCER_CC1NP BIT(TIMER_CCER_CC1NP_BIT) +#define TIMER_CCER_CC1NE BIT(TIMER_CCER_CC1NE_BIT) #define TIMER_CCER_CC1P BIT(TIMER_CCER_CC1P_BIT) #define TIMER_CCER_CC1E BIT(TIMER_CCER_CC1E_BIT) @@ -463,24 +476,24 @@ extern timer_dev *TIMER8; /* DMA control register (DCR) */ #define TIMER_DCR_DBL (0x1F << 8) -#define TIMER_DCR_DBL_1BYTE (0x0 << 8) -#define TIMER_DCR_DBL_2BYTE (0x1 << 8) -#define TIMER_DCR_DBL_3BYTE (0x2 << 8) -#define TIMER_DCR_DBL_4BYTE (0x3 << 8) -#define TIMER_DCR_DBL_5BYTE (0x4 << 8) -#define TIMER_DCR_DBL_6BYTE (0x5 << 8) -#define TIMER_DCR_DBL_7BYTE (0x6 << 8) -#define TIMER_DCR_DBL_8BYTE (0x7 << 8) -#define TIMER_DCR_DBL_9BYTE (0x8 << 8) -#define TIMER_DCR_DBL_10BYTE (0x9 << 8) -#define TIMER_DCR_DBL_11BYTE (0xA << 8) -#define TIMER_DCR_DBL_12BYTE (0xB << 8) -#define TIMER_DCR_DBL_13BYTE (0xC << 8) -#define TIMER_DCR_DBL_14BYTE (0xD << 8) -#define TIMER_DCR_DBL_15BYTE (0xE << 8) -#define TIMER_DCR_DBL_16BYTE (0xF << 8) -#define TIMER_DCR_DBL_17BYTE (0x10 << 8) -#define TIMER_DCR_DBL_18BYTE (0x11 << 8) +#define TIMER_DCR_DBL_1_XFER (0x0 << 8) +#define TIMER_DCR_DBL_2_XFER (0x1 << 8) +#define TIMER_DCR_DBL_3_XFER (0x2 << 8) +#define TIMER_DCR_DBL_4_XFER (0x3 << 8) +#define TIMER_DCR_DBL_5_XFER (0x4 << 8) +#define TIMER_DCR_DBL_6_XFER (0x5 << 8) +#define TIMER_DCR_DBL_7_XFER (0x6 << 8) +#define TIMER_DCR_DBL_8_XFER (0x7 << 8) +#define TIMER_DCR_DBL_9_XFER (0x8 << 8) +#define TIMER_DCR_DBL_10_XFER (0x9 << 8) +#define TIMER_DCR_DBL_11_XFER (0xA << 8) +#define TIMER_DCR_DBL_12_XFER (0xB << 8) +#define TIMER_DCR_DBL_13_XFER (0xC << 8) +#define TIMER_DCR_DBL_14_XFER (0xD << 8) +#define TIMER_DCR_DBL_15_XFER (0xE << 8) +#define TIMER_DCR_DBL_16_XFER (0xF << 8) +#define TIMER_DCR_DBL_17_XFER (0x10 << 8) +#define TIMER_DCR_DBL_18_XFER (0x11 << 8) #define TIMER_DCR_DBA 0x1F #define TIMER_DCR_DBA_CR1 0x0 #define TIMER_DCR_DBA_CR2 0x1 @@ -503,6 +516,45 @@ extern timer_dev *TIMER8; #define TIMER_DCR_DBA_DCR 0x12 #define TIMER_DCR_DBA_DMAR 0x13 +/* Old, erroneous bit definitions from previous releases, kept for + * backwards compatibility: */ +/** Deprecated. Use TIMER_DCR_DBL_1_XFER instead. */ +#define TIMER_DCR_DBL_1BYTE TIMER_DCR_DBL_1_XFER +/** Deprecated. Use TIMER_DCR_DBL_2_XFER instead. */ +#define TIMER_DCR_DBL_2BYTE TIMER_DCR_DBL_2_XFER +/** Deprecated. Use TIMER_DCR_DBL_3_XFER instead. */ +#define TIMER_DCR_DBL_3BYTE TIMER_DCR_DBL_3_XFER +/** Deprecated. Use TIMER_DCR_DBL_4_XFER instead. */ +#define TIMER_DCR_DBL_4BYTE TIMER_DCR_DBL_4_XFER +/** Deprecated. Use TIMER_DCR_DBL_5_XFER instead. */ +#define TIMER_DCR_DBL_5BYTE TIMER_DCR_DBL_5_XFER +/** Deprecated. Use TIMER_DCR_DBL_6_XFER instead. */ +#define TIMER_DCR_DBL_6BYTE TIMER_DCR_DBL_6_XFER +/** Deprecated. Use TIMER_DCR_DBL_7_XFER instead. */ +#define TIMER_DCR_DBL_7BYTE TIMER_DCR_DBL_7_XFER +/** Deprecated. Use TIMER_DCR_DBL_8_XFER instead. */ +#define TIMER_DCR_DBL_8BYTE TIMER_DCR_DBL_8_XFER +/** Deprecated. Use TIMER_DCR_DBL_9_XFER instead. */ +#define TIMER_DCR_DBL_9BYTE TIMER_DCR_DBL_9_XFER +/** Deprecated. Use TIMER_DCR_DBL_10_XFER instead. */ +#define TIMER_DCR_DBL_10BYTE TIMER_DCR_DBL_10_XFER +/** Deprecated. Use TIMER_DCR_DBL_11_XFER instead. */ +#define TIMER_DCR_DBL_11BYTE TIMER_DCR_DBL_11_XFER +/** Deprecated. Use TIMER_DCR_DBL_12_XFER instead. */ +#define TIMER_DCR_DBL_12BYTE TIMER_DCR_DBL_12_XFER +/** Deprecated. Use TIMER_DCR_DBL_13_XFER instead. */ +#define TIMER_DCR_DBL_13BYTE TIMER_DCR_DBL_13_XFER +/** Deprecated. Use TIMER_DCR_DBL_14_XFER instead. */ +#define TIMER_DCR_DBL_14BYTE TIMER_DCR_DBL_14_XFER +/** Deprecated. Use TIMER_DCR_DBL_15_XFER instead. */ +#define TIMER_DCR_DBL_15BYTE TIMER_DCR_DBL_15_XFER +/** Deprecated. Use TIMER_DCR_DBL_16_XFER instead. */ +#define TIMER_DCR_DBL_16BYTE TIMER_DCR_DBL_16_XFER +/** Deprecated. Use TIMER_DCR_DBL_17_XFER instead. */ +#define TIMER_DCR_DBL_17BYTE TIMER_DCR_DBL_17_XFER +/** Deprecated. Use TIMER_DCR_DBL_18_XFER instead. */ +#define TIMER_DCR_DBL_18BYTE TIMER_DCR_DBL_18_XFER + /* * Convenience routines */ @@ -841,18 +893,19 @@ static inline void timer_cc_set_pol(timer_dev *dev, uint8 channel, uint8 pol) { /** * @brief Get a timer's DMA burst length. * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL. - * @return Number of bytes to be transferred per DMA request, from 1 to 18. + * @return Number of transfers per read or write to timer DMA register, + * from 1 to 18. */ static inline uint8 timer_dma_get_burst_len(timer_dev *dev) { uint32 dbl = ((dev->regs).gen->DCR & TIMER_DCR_DBL) >> 8; - return dbl + 1; /* 0 means 1 byte, etc. */ + return dbl + 1; /* 0 means 1 transfer, etc. */ } /** * @brief Set a timer's DMA burst length. * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL. - * @param length DMA burst length; i.e., number of bytes to transfer - * per DMA request, from 1 to 18. + * @param length DMA burst length; i.e., number of DMA transfers per + * read/write to timer DMA register, from 1 to 18. */ static inline void timer_dma_set_burst_len(timer_dev *dev, uint8 length) { uint32 tmp = (dev->regs).gen->DCR; @@ -907,7 +960,7 @@ typedef enum timer_dma_base_addr { /** * @brief Get the timer's DMA base address. * - * Some restrictions apply; see ST RM0008. + * Some restrictions apply; see the reference manual for your chip. * * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL. * @return DMA base address @@ -920,7 +973,7 @@ static inline timer_dma_base_addr timer_dma_get_base_addr(timer_dev *dev) { /** * @brief Set the timer's DMA base address. * - * Some restrictions apply; see ST RM0008. + * Some restrictions apply; see the reference manual for your chip. * * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL. * @param dma_base DMA base address. diff --git a/libmaple/rules.mk b/libmaple/rules.mk index d118b16..2f5e066 100644 --- a/libmaple/rules.mk +++ b/libmaple/rules.mk @@ -20,6 +20,7 @@ cSRCS_$(d) += pwr.c cSRCS_$(d) += rcc.c cSRCS_$(d) += syscalls.c cSRCS_$(d) += systick.c +cSRCS_$(d) += timer.c cSRCS_$(d) += usart.c cSRCS_$(d) += usart_private.c cSRCS_$(d) += util.c @@ -29,7 +30,6 @@ cSRCS_$(d) += util.c # cSRCS_$(d) += exti.c # cSRCS_$(d) += i2c.c # cSRCS_$(d) += spi.c -# cSRCS_$(d) += timer.c sSRCS_$(d) := exc.S diff --git a/libmaple/stm32f1/include/series/timer.h b/libmaple/stm32f1/include/series/timer.h new file mode 100644 index 0000000..3e2ab0f --- /dev/null +++ b/libmaple/stm32f1/include/series/timer.h @@ -0,0 +1,97 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file stm32f1/include/series/timer.h + * @author Marti Bolivar + * @brief STM32F1 timer sub-header. + */ + +#ifndef _LIBMAPLE_STM32F1_TIMER_H_ +#define _LIBMAPLE_STM32F1_TIMER_H_ + +#include +#include + +/* + * Register maps and devices + */ + +/** STM32F1 general purpose timer register map type */ +typedef struct timer_gen_reg_map { + __io uint32 CR1; /**< Control register 1 */ + __io uint32 CR2; /**< Control register 2 */ + __io uint32 SMCR; /**< Slave mode control register */ + __io uint32 DIER; /**< DMA/Interrupt enable register */ + __io uint32 SR; /**< Status register */ + __io uint32 EGR; /**< Event generation register */ + __io uint32 CCMR1; /**< Capture/compare mode register 1 */ + __io uint32 CCMR2; /**< Capture/compare mode register 2 */ + __io uint32 CCER; /**< Capture/compare enable register */ + __io uint32 CNT; /**< Counter */ + __io uint32 PSC; /**< Prescaler */ + __io uint32 ARR; /**< Auto-reload register */ + const uint32 RESERVED1; /**< Reserved */ + __io uint32 CCR1; /**< Capture/compare register 1 */ + __io uint32 CCR2; /**< Capture/compare register 2 */ + __io uint32 CCR3; /**< Capture/compare register 3 */ + __io uint32 CCR4; /**< Capture/compare register 4 */ + const uint32 RESERVED2; /**< Reserved */ + __io uint32 DCR; /**< DMA control register */ + __io uint32 DMAR; /**< DMA address for full transfer */ +} timer_gen_reg_map; + +/** Timer 1 register map base pointer */ +#define TIMER1_BASE ((struct timer_adv_reg_map*)0x40012C00) +/** Timer 2 register map base pointer */ +#define TIMER2_BASE ((struct timer_gen_reg_map*)0x40000000) +/** Timer 3 register map base pointer */ +#define TIMER3_BASE ((struct timer_gen_reg_map*)0x40000400) +/** Timer 4 register map base pointer */ +#define TIMER4_BASE ((struct timer_gen_reg_map*)0x40000800) +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) +/** Timer 5 register map base pointer */ +#define TIMER5_BASE ((struct timer_gen_reg_map*)0x40000C00) +/** Timer 6 register map base pointer */ +#define TIMER6_BASE ((struct timer_bas_reg_map*)0x40001000) +/** Timer 7 register map base pointer */ +#define TIMER7_BASE ((struct timer_bas_reg_map*)0x40001400) +/** Timer 8 register map base pointer */ +#define TIMER8_BASE ((struct timer_adv_reg_map*)0x40013400) +#endif + +extern struct timer_dev *TIMER1; +extern struct timer_dev *TIMER2; +extern struct timer_dev *TIMER3; +extern struct timer_dev *TIMER4; +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) +extern struct timer_dev *TIMER5; +extern struct timer_dev *TIMER6; +extern struct timer_dev *TIMER7; +extern struct timer_dev *TIMER8; +#endif + +#endif diff --git a/libmaple/stm32f1/rules.mk b/libmaple/stm32f1/rules.mk index c0d6344..03fddb3 100644 --- a/libmaple/stm32f1/rules.mk +++ b/libmaple/stm32f1/rules.mk @@ -16,6 +16,7 @@ cSRCS_$(d) += bkp.c cSRCS_$(d) += fsmc.c cSRCS_$(d) += gpio.c cSRCS_$(d) += rcc.c +cSRCS_$(d) += timer.c cSRCS_$(d) += usart.c sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%) diff --git a/libmaple/stm32f1/timer.c b/libmaple/stm32f1/timer.c new file mode 100644 index 0000000..7506cb6 --- /dev/null +++ b/libmaple/stm32f1/timer.c @@ -0,0 +1,152 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011, 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/timer.c + * @author Marti Bolivar + * @brief STM32F1 timer support. + */ + +#include +#include "timer_private.h" + +/* + * Devices + */ + +/* Use timer_private macros to save typing. */ +static DECLARE_ADVANCED_TIMER(timer1, 1); +static DECLARE_GENERAL_TIMER(timer2, 2); +static DECLARE_GENERAL_TIMER(timer3, 3); +static DECLARE_GENERAL_TIMER(timer4, 4); + +/** Timer 1 device (advanced) */ +timer_dev *TIMER1 = &timer1; +/** Timer 2 device (general-purpose) */ +timer_dev *TIMER2 = &timer2; +/** Timer 3 device (general-purpose) */ +timer_dev *TIMER3 = &timer3; +/** Timer 4 device (general-purpose) */ +timer_dev *TIMER4 = &timer4; + +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) +static DECLARE_GENERAL_TIMER(timer5, 5); +static DECLARE_BASIC_TIMER(timer6, 6); +static DECLARE_BASIC_TIMER(timer7, 7); +static DECLARE_ADVANCED_TIMER(timer8, 8); + +/** Timer 5 device (general-purpose) */ +timer_dev *TIMER5 = &timer5; +/** Timer 6 device (basic) */ +timer_dev *TIMER6 = &timer6; +/** Timer 7 device (basic) */ +timer_dev *TIMER7 = &timer7; +/** Timer 8 device (advanced) */ +timer_dev *TIMER8 = &timer8; +#endif + +/* + * Routines + */ + +/** + * @brief Call a function on timer devices. + * @param fn Function to call on each timer device. + */ +void timer_foreach(void (*fn)(timer_dev*)) { + fn(TIMER1); + fn(TIMER2); + fn(TIMER3); + fn(TIMER4); +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) + fn(TIMER5); + fn(TIMER6); + fn(TIMER7); + fn(TIMER8); +#endif +} + +/* + * IRQ handlers + */ + +void __irq_tim1_brk(void) { + dispatch_adv_brk(TIMER1); +} + +void __irq_tim1_up(void) { + dispatch_adv_up(TIMER1); +} + +void __irq_tim1_trg_com(void) { + dispatch_adv_trg_com(TIMER1); +} + +void __irq_tim1_cc(void) { + dispatch_adv_cc(TIMER1); +} + +void __irq_tim2(void) { + dispatch_general(TIMER2); +} + +void __irq_tim3(void) { + dispatch_general(TIMER3); +} + +void __irq_tim4(void) { + dispatch_general(TIMER4); +} + +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) +void __irq_tim5(void) { + dispatch_general(TIMER5); +} + +void __irq_tim6(void) { + dispatch_basic(TIMER6); +} + +void __irq_tim7(void) { + dispatch_basic(TIMER7); +} + +void __irq_tim8_brk(void) { + dispatch_adv_brk(TIMER8); +} + +void __irq_tim8_up(void) { + dispatch_adv_up(TIMER8); +} + +void __irq_tim8_trg_com(void) { + dispatch_adv_trg_com(TIMER8); +} + +void __irq_tim8_cc(void) { + dispatch_adv_cc(TIMER8); +} +#endif diff --git a/libmaple/timer.c b/libmaple/timer.c index 90995e2..d64e3e9 100644 --- a/libmaple/timer.c +++ b/libmaple/timer.c @@ -25,103 +25,13 @@ *****************************************************************************/ /** - * @file timer.c + * @file libmaple/timer.c * @author Marti Bolivar - * @brief New-style timer interface + * @brief Portable timer routines. */ #include -/* Just like the corresponding DIER bits: - * [0] = Update handler; - * [1,2,3,4] = capture/compare 1,2,3,4 handlers, respectively; - * [5] = COM; - * [6] = TRG; - * [7] = BRK. */ -#define NR_ADV_HANDLERS 8 -/* Update, capture/compare 1,2,3,4; ; trigger. */ -#define NR_GEN_HANDLERS 7 -/* Update only. */ -#define NR_BAS_HANDLERS 1 - -static timer_dev timer1 = { - .regs = { .adv = TIMER1_BASE }, - .clk_id = RCC_TIMER1, - .type = TIMER_ADVANCED, - .handlers = { [NR_ADV_HANDLERS - 1] = 0 }, -}; -/** Timer 1 device (advanced) */ -timer_dev *TIMER1 = &timer1; - -static timer_dev timer2 = { - .regs = { .gen = TIMER2_BASE }, - .clk_id = RCC_TIMER2, - .type = TIMER_GENERAL, - .handlers = { [NR_GEN_HANDLERS - 1] = 0 }, -}; -/** Timer 2 device (general-purpose) */ -timer_dev *TIMER2 = &timer2; - -static timer_dev timer3 = { - .regs = { .gen = TIMER3_BASE }, - .clk_id = RCC_TIMER3, - .type = TIMER_GENERAL, - .handlers = { [NR_GEN_HANDLERS - 1] = 0 }, -}; -/** Timer 3 device (general-purpose) */ -timer_dev *TIMER3 = &timer3; - -static timer_dev timer4 = { - .regs = { .gen = TIMER4_BASE }, - .clk_id = RCC_TIMER4, - .type = TIMER_GENERAL, - .handlers = { [NR_GEN_HANDLERS - 1] = 0 }, -}; -/** Timer 4 device (general-purpose) */ -timer_dev *TIMER4 = &timer4; - -#ifdef STM32_HIGH_DENSITY -static timer_dev timer5 = { - .regs = { .gen = TIMER5_BASE }, - .clk_id = RCC_TIMER5, - .type = TIMER_GENERAL, - .handlers = { [NR_GEN_HANDLERS - 1] = 0 }, -}; -/** Timer 5 device (general-purpose) */ -timer_dev *TIMER5 = &timer5; - -static timer_dev timer6 = { - .regs = { .bas = TIMER6_BASE }, - .clk_id = RCC_TIMER6, - .type = TIMER_BASIC, - .handlers = { [NR_BAS_HANDLERS - 1] = 0 }, -}; -/** Timer 6 device (basic) */ -timer_dev *TIMER6 = &timer6; - -static timer_dev timer7 = { - .regs = { .bas = TIMER7_BASE }, - .clk_id = RCC_TIMER7, - .type = TIMER_BASIC, - .handlers = { [NR_BAS_HANDLERS - 1] = 0 }, -}; -/** Timer 7 device (basic) */ -timer_dev *TIMER7 = &timer7; - -static timer_dev timer8 = { - .regs = { .adv = TIMER8_BASE }, - .clk_id = RCC_TIMER8, - .type = TIMER_ADVANCED, - .handlers = { [NR_ADV_HANDLERS - 1] = 0 }, -}; -/** Timer 8 device (advanced) */ -timer_dev *TIMER8 = &timer8; -#endif - -/* - * Convenience routines - */ - static void disable_channel(timer_dev *dev, uint8 channel); static void pwm_mode(timer_dev *dev, uint8 channel); static void output_compare_mode(timer_dev *dev, uint8 channel); @@ -190,23 +100,6 @@ void timer_set_mode(timer_dev *dev, uint8 channel, timer_mode mode) { } } -/** - * @brief Call a function on timer devices. - * @param fn Function to call on each timer device. - */ -void timer_foreach(void (*fn)(timer_dev*)) { - fn(TIMER1); - fn(TIMER2); - fn(TIMER3); - fn(TIMER4); -#ifdef STM32_HIGH_DENSITY - fn(TIMER5); - fn(TIMER6); - fn(TIMER7); - fn(TIMER8); -#endif -} - /** * @brief Attach a timer interrupt. * @param dev Timer device @@ -239,164 +132,6 @@ void timer_detach_interrupt(timer_dev *dev, uint8 interrupt) { dev->handlers[interrupt] = NULL; } -/* - * IRQ handlers - */ - -static inline void dispatch_adv_brk(timer_dev *dev); -static inline void dispatch_adv_up(timer_dev *dev); -static inline void dispatch_adv_trg_com(timer_dev *dev); -static inline void dispatch_adv_cc(timer_dev *dev); -static inline void dispatch_general(timer_dev *dev); -static inline void dispatch_basic(timer_dev *dev); - -void __irq_tim1_brk(void) { - dispatch_adv_brk(TIMER1); -} - -void __irq_tim1_up(void) { - dispatch_adv_up(TIMER1); -} - -void __irq_tim1_trg_com(void) { - dispatch_adv_trg_com(TIMER1); -} - -void __irq_tim1_cc(void) { - dispatch_adv_cc(TIMER1); -} - -void __irq_tim2(void) { - dispatch_general(TIMER2); -} - -void __irq_tim3(void) { - dispatch_general(TIMER3); -} - -void __irq_tim4(void) { - dispatch_general(TIMER4); -} - -#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) - -void __irq_tim5(void) { - dispatch_general(TIMER5); -} - -void __irq_tim6(void) { - dispatch_basic(TIMER6); -} - -void __irq_tim7(void) { - dispatch_basic(TIMER7); -} - -void __irq_tim8_brk(void) { - dispatch_adv_brk(TIMER8); -} - -void __irq_tim8_up(void) { - dispatch_adv_up(TIMER8); -} - -void __irq_tim8_trg_com(void) { - dispatch_adv_trg_com(TIMER8); -} - -void __irq_tim8_cc(void) { - dispatch_adv_cc(TIMER8); -} -#endif - -/* Note: the following dispatch routines make use of the fact that - * DIER interrupt enable bits and SR interrupt flags have common bit - * positions. Thus, ANDing DIER and SR lets us check if an interrupt - * is enabled and if it has occurred simultaneously. - */ - -/* A special-case dispatch routine for single-interrupt NVIC lines. - * This function assumes that the interrupt corresponding to `iid' has - * in fact occurred (i.e., it doesn't check DIER & SR). */ -static inline void dispatch_single_irq(timer_dev *dev, - timer_interrupt_id iid, - uint32 irq_mask) { - timer_bas_reg_map *regs = (dev->regs).bas; - void (*handler)(void) = dev->handlers[iid]; - if (handler) { - handler(); - regs->SR &= ~irq_mask; - } -} - -/* For dispatch routines which service multiple interrupts. */ -#define handle_irq(dier_sr, irq_mask, handlers, iid, handled_irq) do { \ - if ((dier_sr) & (irq_mask)) { \ - void (*__handler)(void) = (handlers)[iid]; \ - if (__handler) { \ - __handler(); \ - handled_irq |= (irq_mask); \ - } \ - } \ - } while (0) - -static inline void dispatch_adv_brk(timer_dev *dev) { - dispatch_single_irq(dev, TIMER_BREAK_INTERRUPT, TIMER_SR_BIF); -} - -static inline void dispatch_adv_up(timer_dev *dev) { - dispatch_single_irq(dev, TIMER_UPDATE_INTERRUPT, TIMER_SR_UIF); -} - -static inline void dispatch_adv_trg_com(timer_dev *dev) { - timer_adv_reg_map *regs = (dev->regs).adv; - uint32 dsr = regs->DIER & regs->SR; - void (**hs)(void) = dev->handlers; - uint32 handled = 0; /* Logical OR of SR interrupt flags we end up - * handling. We clear these. User handlers - * must clear overcapture flags, to avoid - * wasting time in output mode. */ - - handle_irq(dsr, TIMER_SR_TIF, hs, TIMER_TRG_INTERRUPT, handled); - handle_irq(dsr, TIMER_SR_COMIF, hs, TIMER_COM_INTERRUPT, handled); - - regs->SR &= ~handled; -} - -static inline void dispatch_adv_cc(timer_dev *dev) { - timer_adv_reg_map *regs = (dev->regs).adv; - uint32 dsr = regs->DIER & regs->SR; - void (**hs)(void) = dev->handlers; - uint32 handled = 0; - - handle_irq(dsr, TIMER_SR_CC4IF, hs, TIMER_CC4_INTERRUPT, handled); - handle_irq(dsr, TIMER_SR_CC3IF, hs, TIMER_CC3_INTERRUPT, handled); - handle_irq(dsr, TIMER_SR_CC2IF, hs, TIMER_CC2_INTERRUPT, handled); - handle_irq(dsr, TIMER_SR_CC1IF, hs, TIMER_CC1_INTERRUPT, handled); - - regs->SR &= ~handled; -} - -static inline void dispatch_general(timer_dev *dev) { - timer_gen_reg_map *regs = (dev->regs).gen; - uint32 dsr = regs->DIER & regs->SR; - void (**hs)(void) = dev->handlers; - uint32 handled = 0; - - handle_irq(dsr, TIMER_SR_TIF, hs, TIMER_TRG_INTERRUPT, handled); - handle_irq(dsr, TIMER_SR_CC4IF, hs, TIMER_CC4_INTERRUPT, handled); - handle_irq(dsr, TIMER_SR_CC3IF, hs, TIMER_CC3_INTERRUPT, handled); - handle_irq(dsr, TIMER_SR_CC2IF, hs, TIMER_CC2_INTERRUPT, handled); - handle_irq(dsr, TIMER_SR_CC1IF, hs, TIMER_CC1_INTERRUPT, handled); - handle_irq(dsr, TIMER_SR_UIF, hs, TIMER_UPDATE_INTERRUPT, handled); - - regs->SR &= ~handled; -} - -static inline void dispatch_basic(timer_dev *dev) { - dispatch_single_irq(dev, TIMER_UPDATE_INTERRUPT, TIMER_SR_UIF); -} - /* * Utilities */ @@ -417,6 +152,10 @@ static void output_compare_mode(timer_dev *dev, uint8 channel) { timer_cc_enable(dev, channel); } +/* FIXME: These IRQ enable routines fail for timers 9 through 14. + * We don't support those timers yet, so it's OK for now, but this + * really needs to get fixed. */ + static void enable_advanced_irq(timer_dev *dev, timer_interrupt_id id); static void enable_nonmuxed_irq(timer_dev *dev); @@ -462,7 +201,6 @@ static void enable_nonmuxed_irq(timer_dev *dev) { case RCC_TIMER4: nvic_irq_enable(NVIC_TIMER4); break; -#ifdef STM32_HIGH_DENSITY case RCC_TIMER5: nvic_irq_enable(NVIC_TIMER5); break; @@ -472,7 +210,6 @@ static void enable_nonmuxed_irq(timer_dev *dev) { case RCC_TIMER7: nvic_irq_enable(NVIC_TIMER7); break; -#endif default: ASSERT_FAULT(0); break; diff --git a/libmaple/timer_private.h b/libmaple/timer_private.h new file mode 100644 index 0000000..f882f51 --- /dev/null +++ b/libmaple/timer_private.h @@ -0,0 +1,168 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011, 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/timer_private.h + * @author Marti Bolivar + * @brief Private, internal timer APIs. + */ + +#ifndef _LIBMAPLE_TIMER_PRIVATE_H_ +#define _LIBMAPLE_TIMER_PRIVATE_H_ + +/* + * Devices + */ + +/* Just like the corresponding DIER bits: + * [0] = Update handler; + * [1,2,3,4] = capture/compare 1,2,3,4 handlers, respectively; + * [5] = COM; + * [6] = TRG; + * [7] = BRK. */ +#define NR_ADV_HANDLERS 8 +/* Update, capture/compare 1,2,3,4; ; trigger. */ +#define NR_GEN_HANDLERS 7 +/* Update only. */ +#define NR_BAS_HANDLERS 1 + +#define DECLARE_ADVANCED_TIMER(name, num) \ + timer_dev name = { \ + .regs = { .adv = TIMER##num##_BASE }, \ + .clk_id = RCC_TIMER##num, \ + .type = TIMER_ADVANCED, \ + .handlers = { [NR_ADV_HANDLERS - 1] = 0 }, \ + } + +#define DECLARE_GENERAL_TIMER(name, num) \ + timer_dev name = { \ + .regs = { .gen = TIMER##num##_BASE }, \ + .clk_id = RCC_TIMER##num, \ + .type = TIMER_GENERAL, \ + .handlers = { [NR_GEN_HANDLERS - 1] = 0 }, \ + } + +#define DECLARE_BASIC_TIMER(name, num) \ + timer_dev name = { \ + .regs = { .bas = TIMER##num##_BASE }, \ + .clk_id = RCC_TIMER##num, \ + .type = TIMER_BASIC, \ + .handlers = { [NR_BAS_HANDLERS - 1] = 0 }, \ + } + +/* + * IRQ handlers + */ + +/* Note: the following dispatch routines make use of the fact that + * DIER interrupt enable bits and SR interrupt flags have common bit + * positions. Thus, ANDing DIER and SR lets us check if an interrupt + * is enabled and if it has occurred simultaneously. + */ + +/* A special-case dispatch routine for single-interrupt NVIC lines. + * This function assumes that the interrupt corresponding to `iid' has + * in fact occurred (i.e., it doesn't check DIER & SR). */ +static __always_inline void dispatch_single_irq(timer_dev *dev, + timer_interrupt_id iid, + uint32 irq_mask) { + timer_bas_reg_map *regs = (dev->regs).bas; + void (*handler)(void) = dev->handlers[iid]; + if (handler) { + handler(); + regs->SR &= ~irq_mask; + } +} + +/* For dispatch routines which service multiple interrupts. */ +#define handle_irq(dier_sr, irq_mask, handlers, iid, handled_irq) do { \ + if ((dier_sr) & (irq_mask)) { \ + void (*__handler)(void) = (handlers)[iid]; \ + if (__handler) { \ + __handler(); \ + handled_irq |= (irq_mask); \ + } \ + } \ + } while (0) + +static __always_inline void dispatch_adv_brk(timer_dev *dev) { + dispatch_single_irq(dev, TIMER_BREAK_INTERRUPT, TIMER_SR_BIF); +} + +static __always_inline void dispatch_adv_up(timer_dev *dev) { + dispatch_single_irq(dev, TIMER_UPDATE_INTERRUPT, TIMER_SR_UIF); +} + +static __always_inline void dispatch_adv_trg_com(timer_dev *dev) { + timer_adv_reg_map *regs = (dev->regs).adv; + uint32 dsr = regs->DIER & regs->SR; + void (**hs)(void) = dev->handlers; + uint32 handled = 0; /* Logical OR of SR interrupt flags we end up + * handling. We clear these. User handlers + * must clear overcapture flags, to avoid + * wasting time in output mode. */ + + handle_irq(dsr, TIMER_SR_TIF, hs, TIMER_TRG_INTERRUPT, handled); + handle_irq(dsr, TIMER_SR_COMIF, hs, TIMER_COM_INTERRUPT, handled); + + regs->SR &= ~handled; +} + +static __always_inline void dispatch_adv_cc(timer_dev *dev) { + timer_adv_reg_map *regs = (dev->regs).adv; + uint32 dsr = regs->DIER & regs->SR; + void (**hs)(void) = dev->handlers; + uint32 handled = 0; + + handle_irq(dsr, TIMER_SR_CC4IF, hs, TIMER_CC4_INTERRUPT, handled); + handle_irq(dsr, TIMER_SR_CC3IF, hs, TIMER_CC3_INTERRUPT, handled); + handle_irq(dsr, TIMER_SR_CC2IF, hs, TIMER_CC2_INTERRUPT, handled); + handle_irq(dsr, TIMER_SR_CC1IF, hs, TIMER_CC1_INTERRUPT, handled); + + regs->SR &= ~handled; +} + +static __always_inline void dispatch_general(timer_dev *dev) { + timer_gen_reg_map *regs = (dev->regs).gen; + uint32 dsr = regs->DIER & regs->SR; + void (**hs)(void) = dev->handlers; + uint32 handled = 0; + + handle_irq(dsr, TIMER_SR_TIF, hs, TIMER_TRG_INTERRUPT, handled); + handle_irq(dsr, TIMER_SR_CC4IF, hs, TIMER_CC4_INTERRUPT, handled); + handle_irq(dsr, TIMER_SR_CC3IF, hs, TIMER_CC3_INTERRUPT, handled); + handle_irq(dsr, TIMER_SR_CC2IF, hs, TIMER_CC2_INTERRUPT, handled); + handle_irq(dsr, TIMER_SR_CC1IF, hs, TIMER_CC1_INTERRUPT, handled); + handle_irq(dsr, TIMER_SR_UIF, hs, TIMER_UPDATE_INTERRUPT, handled); + + regs->SR &= ~handled; +} + +static __always_inline void dispatch_basic(timer_dev *dev) { + dispatch_single_irq(dev, TIMER_UPDATE_INTERRUPT, TIMER_SR_UIF); +} + +#endif -- cgit v1.2.3 From 301fe2c02ef0ca779d11dcedc2a081436360fbe3 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Tue, 10 Apr 2012 16:05:42 -0400 Subject: libmaple/spi: Fixups, move nonportable bits into libmaple/stm32f1. Standard family support refactoring: add STM32F1 series spi.h, spi.c, and move anything that won't port to STM32F2 there. As part of a general effort to be cleaner, remove the dependency on libmaple/util.h from libmaple/spi.h by not using BIT(). Also forward declare struct gpio_dev for spi_gpio_cfg() to remove that include. Signed-off-by: Marti Bolivar --- libmaple/include/libmaple/spi.h | 118 ++++++++++++++++++---------------- libmaple/rules.mk | 2 +- libmaple/spi.c | 77 ---------------------- libmaple/stm32f1/include/series/spi.h | 70 ++++++++++++++++++++ libmaple/stm32f1/rules.mk | 1 + libmaple/stm32f1/spi.c | 97 ++++++++++++++++++++++++++++ 6 files changed, 231 insertions(+), 134 deletions(-) create mode 100644 libmaple/stm32f1/include/series/spi.h create mode 100644 libmaple/stm32f1/spi.c (limited to 'libmaple/rules.mk') diff --git a/libmaple/include/libmaple/spi.h b/libmaple/include/libmaple/spi.h index 7a665db..5b045a9 100644 --- a/libmaple/include/libmaple/spi.h +++ b/libmaple/include/libmaple/spi.h @@ -44,8 +44,7 @@ extern "C" { #include #include #include -#include -#include +#include /* * Register maps @@ -64,13 +63,6 @@ typedef struct spi_reg_map { __io uint32 I2SPR; /**< I2S prescaler register */ } spi_reg_map; -/** SPI1 register map base pointer */ -#define SPI1_BASE ((struct spi_reg_map*)0x40013000) -/** SPI2 register map base pointer */ -#define SPI2_BASE ((struct spi_reg_map*)0x40003800) -/** SPI3 register map base pointer */ -#define SPI3_BASE ((struct spi_reg_map*)0x40003C00) - /* * Register bit definitions */ @@ -91,20 +83,20 @@ typedef struct spi_reg_map { #define SPI_CR1_CPOL_BIT 1 #define SPI_CR1_CPHA_BIT 0 -#define SPI_CR1_BIDIMODE BIT(SPI_CR1_BIDIMODE_BIT) +#define SPI_CR1_BIDIMODE (1U << SPI_CR1_BIDIMODE_BIT) #define SPI_CR1_BIDIMODE_2_LINE (0x0 << SPI_CR1_BIDIMODE_BIT) #define SPI_CR1_BIDIMODE_1_LINE (0x1 << SPI_CR1_BIDIMODE_BIT) -#define SPI_CR1_BIDIOE BIT(SPI_CR1_BIDIOE_BIT) -#define SPI_CR1_CRCEN BIT(SPI_CR1_CRCEN_BIT) -#define SPI_CR1_CRCNEXT BIT(SPI_CR1_CRCNEXT_BIT) -#define SPI_CR1_DFF BIT(SPI_CR1_DFF_BIT) +#define SPI_CR1_BIDIOE (1U << SPI_CR1_BIDIOE_BIT) +#define SPI_CR1_CRCEN (1U << SPI_CR1_CRCEN_BIT) +#define SPI_CR1_CRCNEXT (1U << SPI_CR1_CRCNEXT_BIT) +#define SPI_CR1_DFF (1U << SPI_CR1_DFF_BIT) #define SPI_CR1_DFF_8_BIT (0x0 << SPI_CR1_DFF_BIT) #define SPI_CR1_DFF_16_BIT (0x1 << SPI_CR1_DFF_BIT) -#define SPI_CR1_RXONLY BIT(SPI_CR1_RXONLY_BIT) -#define SPI_CR1_SSM BIT(SPI_CR1_SSM_BIT) -#define SPI_CR1_SSI BIT(SPI_CR1_SSI_BIT) -#define SPI_CR1_LSBFIRST BIT(SPI_CR1_LSBFIRST_BIT) -#define SPI_CR1_SPE BIT(SPI_CR1_SPE_BIT) +#define SPI_CR1_RXONLY (1U << SPI_CR1_RXONLY_BIT) +#define SPI_CR1_SSM (1U << SPI_CR1_SSM_BIT) +#define SPI_CR1_SSI (1U << SPI_CR1_SSI_BIT) +#define SPI_CR1_LSBFIRST (1U << SPI_CR1_LSBFIRST_BIT) +#define SPI_CR1_SPE (1U << SPI_CR1_SPE_BIT) #define SPI_CR1_BR (0x7 << 3) #define SPI_CR1_BR_PCLK_DIV_2 (0x0 << 3) #define SPI_CR1_BR_PCLK_DIV_4 (0x1 << 3) @@ -114,17 +106,14 @@ typedef struct spi_reg_map { #define SPI_CR1_BR_PCLK_DIV_64 (0x5 << 3) #define SPI_CR1_BR_PCLK_DIV_128 (0x6 << 3) #define SPI_CR1_BR_PCLK_DIV_256 (0x7 << 3) -#define SPI_CR1_MSTR BIT(SPI_CR1_MSTR_BIT) -#define SPI_CR1_CPOL BIT(SPI_CR1_CPOL_BIT) +#define SPI_CR1_MSTR (1U << SPI_CR1_MSTR_BIT) +#define SPI_CR1_CPOL (1U << SPI_CR1_CPOL_BIT) #define SPI_CR1_CPOL_LOW (0x0 << SPI_CR1_CPOL_BIT) #define SPI_CR1_CPOL_HIGH (0x1 << SPI_CR1_CPOL_BIT) -#define SPI_CR1_CPHA BIT(SPI_CR1_CPHA_BIT) +#define SPI_CR1_CPHA (1U << SPI_CR1_CPHA_BIT) /* Control register 2 */ -/* RM0008-ism: SPI CR2 has "TXDMAEN" and "RXDMAEN" bits, while the - * USARTs have CR3 "DMAR" and "DMAT" bits. */ - #define SPI_CR2_TXEIE_BIT 7 #define SPI_CR2_RXNEIE_BIT 6 #define SPI_CR2_ERRIE_BIT 5 @@ -132,12 +121,12 @@ typedef struct spi_reg_map { #define SPI_CR2_TXDMAEN_BIT 1 #define SPI_CR2_RXDMAEN_BIT 0 -#define SPI_CR2_TXEIE BIT(SPI_CR2_TXEIE_BIT) -#define SPI_CR2_RXNEIE BIT(SPI_CR2_RXNEIE_BIT) -#define SPI_CR2_ERRIE BIT(SPI_CR2_ERRIE_BIT) -#define SPI_CR2_SSOE BIT(SPI_CR2_SSOE_BIT) -#define SPI_CR2_TXDMAEN BIT(SPI_CR2_TXDMAEN_BIT) -#define SPI_CR2_RXDMAEN BIT(SPI_CR2_RXDMAEN_BIT) +#define SPI_CR2_TXEIE (1U << SPI_CR2_TXEIE_BIT) +#define SPI_CR2_RXNEIE (1U << SPI_CR2_RXNEIE_BIT) +#define SPI_CR2_ERRIE (1U << SPI_CR2_ERRIE_BIT) +#define SPI_CR2_SSOE (1U << SPI_CR2_SSOE_BIT) +#define SPI_CR2_TXDMAEN (1U << SPI_CR2_TXDMAEN_BIT) +#define SPI_CR2_RXDMAEN (1U << SPI_CR2_RXDMAEN_BIT) /* Status register */ @@ -150,37 +139,35 @@ typedef struct spi_reg_map { #define SPI_SR_TXE_BIT 1 #define SPI_SR_RXNE_BIT 0 -#define SPI_SR_BSY BIT(SPI_SR_BSY_BIT) -#define SPI_SR_OVR BIT(SPI_SR_OVR_BIT) -#define SPI_SR_MODF BIT(SPI_SR_MODF_BIT) -#define SPI_SR_CRCERR BIT(SPI_SR_CRCERR_BIT) -#define SPI_SR_UDR BIT(SPI_SR_UDR_BIT) -#define SPI_SR_CHSIDE BIT(SPI_SR_CHSIDE_BIT) +#define SPI_SR_BSY (1U << SPI_SR_BSY_BIT) +#define SPI_SR_OVR (1U << SPI_SR_OVR_BIT) +#define SPI_SR_MODF (1U << SPI_SR_MODF_BIT) +#define SPI_SR_CRCERR (1U << SPI_SR_CRCERR_BIT) +#define SPI_SR_UDR (1U << SPI_SR_UDR_BIT) +#define SPI_SR_CHSIDE (1U << SPI_SR_CHSIDE_BIT) #define SPI_SR_CHSIDE_LEFT (0x0 << SPI_SR_CHSIDE_BIT) #define SPI_SR_CHSIDE_RIGHT (0x1 << SPI_SR_CHSIDE_BIT) -#define SPI_SR_TXE BIT(SPI_SR_TXE_BIT) -#define SPI_SR_RXNE BIT(SPI_SR_RXNE_BIT) +#define SPI_SR_TXE (1U << SPI_SR_TXE_BIT) +#define SPI_SR_RXNE (1U << SPI_SR_RXNE_BIT) /* I2S configuration register */ -/* RM0008-ism: CR1 has "CPOL", I2SCFGR has "CKPOL". */ - #define SPI_I2SCFGR_I2SMOD_BIT 11 #define SPI_I2SCFGR_I2SE_BIT 10 #define SPI_I2SCFGR_PCMSYNC_BIT 7 #define SPI_I2SCFGR_CKPOL_BIT 3 #define SPI_I2SCFGR_CHLEN_BIT 0 -#define SPI_I2SCFGR_I2SMOD BIT(SPI_I2SCFGR_I2SMOD_BIT) +#define SPI_I2SCFGR_I2SMOD (1U << SPI_I2SCFGR_I2SMOD_BIT) #define SPI_I2SCFGR_I2SMOD_SPI (0x0 << SPI_I2SCFGR_I2SMOD_BIT) #define SPI_I2SCFGR_I2SMOD_I2S (0x1 << SPI_I2SCFGR_I2SMOD_BIT) -#define SPI_I2SCFGR_I2SE BIT(SPI_I2SCFGR_I2SE_BIT) +#define SPI_I2SCFGR_I2SE (1U << SPI_I2SCFGR_I2SE_BIT) #define SPI_I2SCFGR_I2SCFG (0x3 << 8) #define SPI_I2SCFGR_I2SCFG_SLAVE_TX (0x0 << 8) #define SPI_I2SCFGR_I2SCFG_SLAVE_RX (0x1 << 8) #define SPI_I2SCFGR_I2SCFG_MASTER_TX (0x2 << 8) #define SPI_I2SCFGR_I2SCFG_MASTER_RX (0x3 << 8) -#define SPI_I2SCFGR_PCMSYNC BIT(SPI_I2SCFGR_PCMSYNC_BIT) +#define SPI_I2SCFGR_PCMSYNC (1U << SPI_I2SCFGR_PCMSYNC_BIT) #define SPI_I2SCFGR_PCMSYNC_SHORT (0x0 << SPI_I2SCFGR_PCMSYNC_BIT) #define SPI_I2SCFGR_PCMSYNC_LONG (0x1 << SPI_I2SCFGR_PCMSYNC_BIT) #define SPI_I2SCFGR_I2SSTD (0x3 << 4) @@ -188,17 +175,26 @@ typedef struct spi_reg_map { #define SPI_I2SCFGR_I2SSTD_MSB (0x1 << 4) #define SPI_I2SCFGR_I2SSTD_LSB (0x2 << 4) #define SPI_I2SCFGR_I2SSTD_PCM (0x3 << 4) -#define SPI_I2SCFGR_CKPOL BIT(SPI_I2SCFGR_CKPOL_BIT) +#define SPI_I2SCFGR_CKPOL (1U << SPI_I2SCFGR_CKPOL_BIT) #define SPI_I2SCFGR_CKPOL_LOW (0x0 << SPI_I2SCFGR_CKPOL_BIT) #define SPI_I2SCFGR_CKPOL_HIGH (0x1 << SPI_I2SCFGR_CKPOL_BIT) #define SPI_I2SCFGR_DATLEN (0x3 << 1) #define SPI_I2SCFGR_DATLEN_16_BIT (0x0 << 1) #define SPI_I2SCFGR_DATLEN_24_BIT (0x1 << 1) #define SPI_I2SCFGR_DATLEN_32_BIT (0x2 << 1) -#define SPI_I2SCFGR_CHLEN BIT(SPI_I2SCFGR_CHLEN_BIT) +#define SPI_I2SCFGR_CHLEN (1U << SPI_I2SCFGR_CHLEN_BIT) #define SPI_I2SCFGR_CHLEN_16_BIT (0x0 << SPI_I2SCFGR_CHLEN_BIT) #define SPI_I2SCFGR_CHLEN_32_BIT (0x1 << SPI_I2SCFGR_CHLEN_BIT) +/* I2S prescaler register */ + +#define SPI_I2SPR_MCKOE_BIT 9 +#define SPI_I2SPR_ODD_BIT 8 + +#define SPI_I2SPR_MCKOE (1U << SPI_I2SPR_MCKOE_BIT) +#define SPI_I2SPR_ODD (1U << SPI_I2SPR_ODD_BIT) +#define SPI_I2SPR_I2SDIV 0xFF + /* * Devices */ @@ -210,22 +206,28 @@ typedef struct spi_dev { nvic_irq_num irq_num; /**< NVIC interrupt number */ } spi_dev; -extern spi_dev *SPI1; -extern spi_dev *SPI2; -#ifdef STM32_HIGH_DENSITY -extern spi_dev *SPI3; -#endif - /* * SPI Convenience functions */ void spi_init(spi_dev *dev); +struct gpio_dev; +/** + * @brief Configure GPIO bit modes for use as a SPI port's pins. + * @param as_master If true, configure bits for use as a bus master. + * Otherwise, configure bits for use as slave. + * @param nss_dev NSS pin's GPIO device + * @param comm_dev SCK, MISO, MOSI pins' GPIO device + * @param nss_bit NSS pin's GPIO bit on nss_dev + * @param sck_bit SCK pin's GPIO bit on comm_dev + * @param miso_bit MISO pin's GPIO bit on comm_dev + * @param mosi_bit MOSI pin's GPIO bit on comm_dev + */ void spi_gpio_cfg(uint8 as_master, - gpio_dev *nss_dev, + struct gpio_dev *nss_dev, uint8 nss_bit, - gpio_dev *comm_dev, + struct gpio_dev *comm_dev, uint8 sck_bit, uint8 miso_bit, uint8 mosi_bit); @@ -244,7 +246,7 @@ typedef enum spi_mode { clock transition */ SPI_MODE_2, /**< Clock line idles high (1), data capture on first clock transition. */ - SPI_MODE_3 /**< Clock line idles high (1), data capture on + SPI_MODE_3, /**< Clock line idles high (1), data capture on second clock transition. */ } spi_mode; @@ -300,7 +302,11 @@ void spi_slave_enable(spi_dev *dev, uint32 spi_tx(spi_dev *dev, const void *buf, uint32 len); -void spi_foreach(void (*fn)(spi_dev (*dev))); +/** + * @brief Call a function on each SPI port + * @param fn Function to call. + */ +void spi_foreach(void (*fn)(spi_dev*)); void spi_peripheral_enable(spi_dev *dev); void spi_peripheral_disable(spi_dev *dev); diff --git a/libmaple/rules.mk b/libmaple/rules.mk index 2f5e066..93716d2 100644 --- a/libmaple/rules.mk +++ b/libmaple/rules.mk @@ -18,6 +18,7 @@ cSRCS_$(d) += iwdg.c cSRCS_$(d) += nvic.c cSRCS_$(d) += pwr.c cSRCS_$(d) += rcc.c +cSRCS_$(d) += spi.c cSRCS_$(d) += syscalls.c cSRCS_$(d) += systick.c cSRCS_$(d) += timer.c @@ -29,7 +30,6 @@ cSRCS_$(d) += util.c # cSRCS_$(d) += dma.c # cSRCS_$(d) += exti.c # cSRCS_$(d) += i2c.c -# cSRCS_$(d) += spi.c sSRCS_$(d) := exc.S diff --git a/libmaple/spi.c b/libmaple/spi.c index 00b7ce2..194a82e 100644 --- a/libmaple/spi.c +++ b/libmaple/spi.c @@ -37,36 +37,6 @@ static void spi_reconfigure(spi_dev *dev, uint32 cr1_config); -/* - * SPI devices - */ - -static spi_dev spi1 = { - .regs = SPI1_BASE, - .clk_id = RCC_SPI1, - .irq_num = NVIC_SPI1, -}; -/** SPI device 1 */ -spi_dev *SPI1 = &spi1; - -static spi_dev spi2 = { - .regs = SPI2_BASE, - .clk_id = RCC_SPI2, - .irq_num = NVIC_SPI2, -}; -/** SPI device 2 */ -spi_dev *SPI2 = &spi2; - -#ifdef STM32_HIGH_DENSITY -static spi_dev spi3 = { - .regs = SPI3_BASE, - .clk_id = RCC_SPI3, - .irq_num = NVIC_SPI3, -}; -/** SPI device 3 */ -spi_dev *SPI3 = &spi3; -#endif - /* * SPI convenience routines */ @@ -80,37 +50,6 @@ void spi_init(spi_dev *dev) { rcc_reset_dev(dev->clk_id); } -/** - * @brief Configure GPIO bit modes for use as a SPI port's pins. - * @param as_master If true, configure bits for use as a bus master. - * Otherwise, configure bits for use as slave. - * @param nss_dev NSS pin's GPIO device - * @param comm_dev SCK, MISO, MOSI pins' GPIO device - * @param nss_bit NSS pin's GPIO bit on nss_dev - * @param sck_bit SCK pin's GPIO bit on comm_dev - * @param miso_bit MISO pin's GPIO bit on comm_dev - * @param mosi_bit MOSI pin's GPIO bit on comm_dev - */ -void spi_gpio_cfg(uint8 as_master, - gpio_dev *nss_dev, - uint8 nss_bit, - gpio_dev *comm_dev, - uint8 sck_bit, - uint8 miso_bit, - uint8 mosi_bit) { - if (as_master) { - gpio_set_mode(nss_dev, nss_bit, GPIO_AF_OUTPUT_PP); - gpio_set_mode(comm_dev, sck_bit, GPIO_AF_OUTPUT_PP); - gpio_set_mode(comm_dev, miso_bit, GPIO_INPUT_FLOATING); - gpio_set_mode(comm_dev, mosi_bit, GPIO_AF_OUTPUT_PP); - } else { - gpio_set_mode(nss_dev, nss_bit, GPIO_INPUT_FLOATING); - gpio_set_mode(comm_dev, sck_bit, GPIO_INPUT_FLOATING); - gpio_set_mode(comm_dev, miso_bit, GPIO_AF_OUTPUT_PP); - gpio_set_mode(comm_dev, mosi_bit, GPIO_INPUT_FLOATING); - } -} - /** * @brief Configure and enable a SPI device as bus master. * @@ -165,18 +104,6 @@ uint32 spi_tx(spi_dev *dev, const void *buf, uint32 len) { return txed; } -/** - * @brief Call a function on each SPI port - * @param fn Function to call. - */ -void spi_foreach(void (*fn)(spi_dev*)) { - fn(SPI1); - fn(SPI2); -#ifdef STM32_HIGH_DENSITY - fn(SPI3); -#endif -} - /** * @brief Enable a SPI peripheral * @param dev Device to enable @@ -235,7 +162,3 @@ static void spi_reconfigure(spi_dev *dev, uint32 cr1_config) { dev->regs->CR1 = cr1_config; spi_peripheral_enable(dev); } - -/* - * IRQ handlers (TODO) - */ diff --git a/libmaple/stm32f1/include/series/spi.h b/libmaple/stm32f1/include/series/spi.h new file mode 100644 index 0000000..167df0c --- /dev/null +++ b/libmaple/stm32f1/include/series/spi.h @@ -0,0 +1,70 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011, 2012 LeafLabs, LLC. + * Copyright (c) 2010 Perry Hung. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/include/series/spi.h + * @author Marti Bolivar + * @brief STM32F1 SPI/I2S series header. + */ + +#ifndef _LIBMAPLE_STM32F1_SPI_H_ +#define _LIBMAPLE_STM32F1_SPI_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Register map base pointers + */ + +struct spi_reg_map; + +/** SPI1 register map base pointer */ +#define SPI1_BASE ((struct spi_reg_map*)0x40013000) +/** SPI2 register map base pointer */ +#define SPI2_BASE ((struct spi_reg_map*)0x40003800) +/** SPI3 register map base pointer */ +#define SPI3_BASE ((struct spi_reg_map*)0x40003C00) + +/* + * Device pointers + */ + +struct spi_dev; + +extern struct spi_dev *SPI1; +extern struct spi_dev *SPI2; +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) +extern struct spi_dev *SPI3; +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libmaple/stm32f1/rules.mk b/libmaple/stm32f1/rules.mk index 03fddb3..52ceea6 100644 --- a/libmaple/stm32f1/rules.mk +++ b/libmaple/stm32f1/rules.mk @@ -16,6 +16,7 @@ cSRCS_$(d) += bkp.c cSRCS_$(d) += fsmc.c cSRCS_$(d) += gpio.c cSRCS_$(d) += rcc.c +cSRCS_$(d) += spi.c cSRCS_$(d) += timer.c cSRCS_$(d) += usart.c diff --git a/libmaple/stm32f1/spi.c b/libmaple/stm32f1/spi.c new file mode 100644 index 0000000..b860918 --- /dev/null +++ b/libmaple/stm32f1/spi.c @@ -0,0 +1,97 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011, 2012 LeafLabs, LLC. + * Copyright (c) 2010 Perry Hung. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/spi.c + * @author Marti Bolivar + * @brief STM32F1 SPI/I2S support. + */ + +#include +#include + +/* + * Devices + */ + +static spi_dev spi1 = { + .regs = SPI1_BASE, + .clk_id = RCC_SPI1, + .irq_num = NVIC_SPI1, +}; +/** SPI device 1 */ +spi_dev *SPI1 = &spi1; + +static spi_dev spi2 = { + .regs = SPI2_BASE, + .clk_id = RCC_SPI2, + .irq_num = NVIC_SPI2, +}; +/** SPI device 2 */ +spi_dev *SPI2 = &spi2; + +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) +static spi_dev spi3 = { + .regs = SPI3_BASE, + .clk_id = RCC_SPI3, + .irq_num = NVIC_SPI3, +}; +/** SPI device 3 */ +spi_dev *SPI3 = &spi3; +#endif + +/* + * Routines + */ + +void spi_gpio_cfg(uint8 as_master, + gpio_dev *nss_dev, + uint8 nss_bit, + gpio_dev *comm_dev, + uint8 sck_bit, + uint8 miso_bit, + uint8 mosi_bit) { + if (as_master) { + gpio_set_mode(nss_dev, nss_bit, GPIO_AF_OUTPUT_PP); + gpio_set_mode(comm_dev, sck_bit, GPIO_AF_OUTPUT_PP); + gpio_set_mode(comm_dev, miso_bit, GPIO_INPUT_FLOATING); + gpio_set_mode(comm_dev, mosi_bit, GPIO_AF_OUTPUT_PP); + } else { + gpio_set_mode(nss_dev, nss_bit, GPIO_INPUT_FLOATING); + gpio_set_mode(comm_dev, sck_bit, GPIO_INPUT_FLOATING); + gpio_set_mode(comm_dev, miso_bit, GPIO_AF_OUTPUT_PP); + gpio_set_mode(comm_dev, mosi_bit, GPIO_INPUT_FLOATING); + } +} + +void spi_foreach(void (*fn)(spi_dev*)) { + fn(SPI1); + fn(SPI2); +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) + fn(SPI3); +#endif +} -- cgit v1.2.3 From 1f67ed8f23048c45b0a3deec232b19047966bce7 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Thu, 26 Apr 2012 17:33:56 -0400 Subject: stm32f1: Resurrect DMA support. (sets up breaking change) Breaking change set up: struct dma_handler_config is no longer part of the public API in . User code which was touching these was always mistaken; it should be using dma_attach_interrupt() or dma_detach_interrupt() instead. Other than that, just move the nonportable bits in and libmaple/dma.c to the appropriate places under libmaple/stm32f1/. (Ouch. This is almost everything.) Patch the (new) STM32F1 here and there to make everything compile; this is mostly limited to forward-declaring struct dma_dev and providing a hack _dma_dev_regs() declaration so inline functions in the series header can still access a device's registers. Signed-off-by: Marti Bolivar --- libmaple/dma.c | 338 +------------------------- libmaple/include/libmaple/dma.h | 404 ++----------------------------- libmaple/rules.mk | 2 +- libmaple/stm32f1/dma.c | 371 ++++++++++++++++++++++++++++ libmaple/stm32f1/include/series/dma.h | 438 ++++++++++++++++++++++++++++++++++ libmaple/stm32f1/rules.mk | 1 + 6 files changed, 836 insertions(+), 718 deletions(-) create mode 100644 libmaple/stm32f1/dma.c create mode 100644 libmaple/stm32f1/include/series/dma.h (limited to 'libmaple/rules.mk') diff --git a/libmaple/dma.c b/libmaple/dma.c index f20613b..6442e4d 100644 --- a/libmaple/dma.c +++ b/libmaple/dma.c @@ -2,6 +2,7 @@ * The MIT License * * Copyright (c) 2010 Michael Hope. + * Copyright (c) 2012 LeafLabs, LLC. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -25,47 +26,13 @@ *****************************************************************************/ /** - * @file dma.c + * @file libmaple/dma.c * @author Marti Bolivar ; * Original implementation by Michael Hope - * @brief Direct Memory Access peripheral support + * @brief Portable DMA routines. */ #include -#include -#include - -/* - * Devices - */ - -static dma_dev dma1 = { - .regs = DMA1_BASE, - .clk_id = RCC_DMA1, - .handlers = {{ .handler = NULL, .irq_line = NVIC_DMA_CH1 }, - { .handler = NULL, .irq_line = NVIC_DMA_CH2 }, - { .handler = NULL, .irq_line = NVIC_DMA_CH3 }, - { .handler = NULL, .irq_line = NVIC_DMA_CH4 }, - { .handler = NULL, .irq_line = NVIC_DMA_CH5 }, - { .handler = NULL, .irq_line = NVIC_DMA_CH6 }, - { .handler = NULL, .irq_line = NVIC_DMA_CH7 }} -}; -/** DMA1 device */ -dma_dev *DMA1 = &dma1; - -#ifdef STM32_HIGH_DENSITY -static dma_dev dma2 = { - .regs = DMA2_BASE, - .clk_id = RCC_DMA2, - .handlers = {{ .handler = NULL, .irq_line = NVIC_DMA2_CH1 }, - { .handler = NULL, .irq_line = NVIC_DMA2_CH2 }, - { .handler = NULL, .irq_line = NVIC_DMA2_CH3 }, - { .handler = NULL, .irq_line = NVIC_DMA2_CH_4_5 }, - { .handler = NULL, .irq_line = NVIC_DMA2_CH_4_5 }} /* !@#$ */ -}; -/** DMA2 device */ -dma_dev *DMA2 = &dma2; -#endif /* * Convenience routines @@ -78,302 +45,3 @@ dma_dev *DMA2 = &dma2; void dma_init(dma_dev *dev) { rcc_clk_enable(dev->clk_id); } - -/** - * @brief Set up a DMA transfer. - * - * The channel will be disabled before being reconfigured. The - * transfer will have low priority by default. You may choose another - * priority before the transfer begins using dma_set_priority(), as - * well as performing any other configuration you desire. When the - * channel is configured to your liking, enable it using dma_enable(). - * - * @param dev DMA device. - * @param channel DMA channel. - * @param peripheral_address Base address of peripheral data register - * involved in the transfer. - * @param peripheral_size Peripheral data transfer size. - * @param memory_address Base memory address involved in the transfer. - * @param memory_size Memory data transfer size. - * @param mode Logical OR of dma_mode_flags - * @sideeffect Disables the given DMA channel. - * @see dma_xfer_size - * @see dma_mode_flags - * @see dma_set_num_transfers() - * @see dma_set_priority() - * @see dma_attach_interrupt() - * @see dma_enable() - */ -void dma_setup_transfer(dma_dev *dev, - dma_channel channel, - __io void *peripheral_address, - dma_xfer_size peripheral_size, - __io void *memory_address, - dma_xfer_size memory_size, - uint32 mode) { - dma_channel_reg_map *channel_regs = dma_channel_regs(dev, channel); - - dma_disable(dev, channel); /* can't write to CMAR/CPAR otherwise */ - channel_regs->CCR = (memory_size << 10) | (peripheral_size << 8) | mode; - channel_regs->CMAR = (uint32)memory_address; - channel_regs->CPAR = (uint32)peripheral_address; -} - -/** - * @brief Set the number of data to be transferred on a DMA channel. - * - * You may not call this function while the channel is enabled. - * - * @param dev DMA device - * @param channel Channel through which the transfer occurs. - * @param num_transfers - */ -void dma_set_num_transfers(dma_dev *dev, - dma_channel channel, - uint16 num_transfers) { - dma_channel_reg_map *channel_regs; - - ASSERT_FAULT(!dma_is_channel_enabled(dev, channel)); - - channel_regs = dma_channel_regs(dev, channel); - channel_regs->CNDTR = num_transfers; -} - -/** - * @brief Set the priority of a DMA transfer. - * - * You may not call this function while the channel is enabled. - * - * @param dev DMA device - * @param channel DMA channel - * @param priority priority to set. - */ -void dma_set_priority(dma_dev *dev, - dma_channel channel, - dma_priority priority) { - dma_channel_reg_map *channel_regs; - uint32 ccr; - - ASSERT_FAULT(!dma_is_channel_enabled(dev, channel)); - - channel_regs = dma_channel_regs(dev, channel); - ccr = channel_regs->CCR; - ccr &= ~DMA_CCR_PL; - ccr |= priority; - channel_regs->CCR = ccr; -} - -/** - * @brief Attach an interrupt to a DMA transfer. - * - * Interrupts are enabled using appropriate mode flags in - * dma_setup_transfer(). - * - * @param dev DMA device - * @param channel Channel to attach handler to - * @param handler Interrupt handler to call when channel interrupt fires. - * @see dma_setup_transfer() - * @see dma_get_irq_cause() - * @see dma_detach_interrupt() - */ -void dma_attach_interrupt(dma_dev *dev, - dma_channel channel, - void (*handler)(void)) { - dev->handlers[channel - 1].handler = handler; - nvic_irq_enable(dev->handlers[channel - 1].irq_line); -} - -/** - * @brief Detach a DMA transfer interrupt handler. - * - * After calling this function, the given channel's interrupts will be - * disabled. - * - * @param dev DMA device - * @param channel Channel whose handler to detach - * @sideeffect Clears interrupt enable bits in the channel's CCR register. - * @see dma_attach_interrupt() - */ -void dma_detach_interrupt(dma_dev *dev, dma_channel channel) { - /* Don't use nvic_irq_disable()! Think about DMA2 channels 4 and 5. */ - dma_channel_regs(dev, channel)->CCR &= ~0xF; - dev->handlers[channel - 1].handler = NULL; -} - -/** - * @brief Discover the reason why a DMA interrupt was called. - * - * You may only call this function within an attached interrupt - * handler for the given channel. - * - * This function resets the internal DMA register state which encodes - * the cause of the interrupt; consequently, it can only be called - * once per interrupt handler invocation. - * - * @param dev DMA device - * @param channel Channel whose interrupt is being handled. - * @return Reason why the interrupt fired. - * @sideeffect Clears channel status flags in dev->regs->ISR. - * @see dma_attach_interrupt() - * @see dma_irq_cause - */ -dma_irq_cause dma_get_irq_cause(dma_dev *dev, dma_channel channel) { - uint8 status_bits = dma_get_isr_bits(dev, channel); - - /* If the channel global interrupt flag is cleared, then - * something's very wrong. */ - ASSERT(status_bits & BIT(0)); - - dma_clear_isr_bits(dev, channel); - - /* ISR flags get set even if the corresponding interrupt enable - * bits in the channel's configuration register are cleared, so we - * can't use a switch here. - * - * Don't change the order of these if statements. */ - if (status_bits & BIT(3)) { - return DMA_TRANSFER_ERROR; - } else if (status_bits & BIT(1)) { - return DMA_TRANSFER_COMPLETE; - } else if (status_bits & BIT(2)) { - return DMA_TRANSFER_HALF_COMPLETE; - } else if (status_bits & BIT(0)) { - /* Shouldn't happen (unless someone messed up an IFCR write). */ - throb(); - } -#if DEBUG_LEVEL < DEBUG_ALL - else { - /* We shouldn't have been called, but the debug level is too - * low for the above ASSERT() to have had any effect. In - * order to fail fast, mimic the DMA controller's behavior - * when an error occurs. */ - dma_disable(dev, channel); - } -#endif - return DMA_TRANSFER_ERROR; -} - -/** - * @brief Enable a DMA channel. - * @param dev DMA device - * @param channel Channel to enable - */ -void dma_enable(dma_dev *dev, dma_channel channel) { - dma_channel_reg_map *chan_regs = dma_channel_regs(dev, channel); - bb_peri_set_bit(&chan_regs->CCR, DMA_CCR_EN_BIT, 1); -} - -/** - * @brief Disable a DMA channel. - * @param dev DMA device - * @param channel Channel to disable - */ -void dma_disable(dma_dev *dev, dma_channel channel) { - dma_channel_reg_map *chan_regs = dma_channel_regs(dev, channel); - bb_peri_set_bit(&chan_regs->CCR, DMA_CCR_EN_BIT, 0); -} - -/** - * @brief Set the base memory address where data will be read from or - * written to. - * - * You must not call this function while the channel is enabled. - * - * If the DMA memory size is 16 bits, the address is automatically - * aligned to a half-word. If the DMA memory size is 32 bits, the - * address is aligned to a word. - * - * @param dev DMA Device - * @param channel Channel whose base memory address to set. - * @param addr Memory base address to use. - */ -void dma_set_mem_addr(dma_dev *dev, dma_channel channel, __io void *addr) { - dma_channel_reg_map *chan_regs; - - ASSERT_FAULT(!dma_is_channel_enabled(dev, channel)); - - chan_regs = dma_channel_regs(dev, channel); - chan_regs->CMAR = (uint32)addr; -} - -/** - * @brief Set the base peripheral address where data will be read from - * or written to. - * - * You must not call this function while the channel is enabled. - * - * If the DMA peripheral size is 16 bits, the address is automatically - * aligned to a half-word. If the DMA peripheral size is 32 bits, the - * address is aligned to a word. - * - * @param dev DMA Device - * @param channel Channel whose peripheral data register base address to set. - * @param addr Peripheral memory base address to use. - */ -void dma_set_per_addr(dma_dev *dev, dma_channel channel, __io void *addr) { - dma_channel_reg_map *chan_regs; - - ASSERT_FAULT(!dma_is_channel_enabled(dev, channel)); - - chan_regs = dma_channel_regs(dev, channel); - chan_regs->CPAR = (uint32)addr; -} - -/* - * IRQ handlers - */ - -static inline void dispatch_handler(dma_dev *dev, dma_channel channel) { - void (*handler)(void) = dev->handlers[channel - 1].handler; - if (handler) { - handler(); - dma_clear_isr_bits(dev, channel); /* in case handler doesn't */ - } -} - -void __irq_dma1_channel1(void) { - dispatch_handler(DMA1, DMA_CH1); -} - -void __irq_dma1_channel2(void) { - dispatch_handler(DMA1, DMA_CH2); -} - -void __irq_dma1_channel3(void) { - dispatch_handler(DMA1, DMA_CH3); -} - -void __irq_dma1_channel4(void) { - dispatch_handler(DMA1, DMA_CH4); -} - -void __irq_dma1_channel5(void) { - dispatch_handler(DMA1, DMA_CH5); -} - -void __irq_dma1_channel6(void) { - dispatch_handler(DMA1, DMA_CH6); -} - -void __irq_dma1_channel7(void) { - dispatch_handler(DMA1, DMA_CH7); -} - -#ifdef STM32_HIGH_DENSITY -void __irq_dma2_channel1(void) { - dispatch_handler(DMA2, DMA_CH1); -} - -void __irq_dma2_channel2(void) { - dispatch_handler(DMA2, DMA_CH2); -} - -void __irq_dma2_channel3(void) { - dispatch_handler(DMA2, DMA_CH3); -} - -void __irq_dma2_channel4_5(void) { - dispatch_handler(DMA2, DMA_CH4); - dispatch_handler(DMA2, DMA_CH5); -} -#endif diff --git a/libmaple/include/libmaple/dma.h b/libmaple/include/libmaple/dma.h index 32e915c..0aed572 100644 --- a/libmaple/include/libmaple/dma.h +++ b/libmaple/include/libmaple/dma.h @@ -33,10 +33,6 @@ * @brief Direct Memory Access peripheral support */ -/* - * See /notes/dma.txt for more information. - */ - #ifndef _LIBMAPLE_DMA_H_ #define _LIBMAPLE_DMA_H_ @@ -44,406 +40,50 @@ extern "C"{ #endif -#include -#include -#include - -/* - * Register maps - */ - -/** - * @brief DMA register map type. +/* provides: * - * Note that DMA controller 2 (register map base pointer DMA2_BASE) - * only supports channels 1--5. + * - Normal stuff: dma_reg_map and base pointers, register bit + * definitions, dma_dev pointer declarations, and any other + * convenience functions useful for that series. */ -typedef struct dma_reg_map { - __io uint32 ISR; /**< Interrupt status register */ - __io uint32 IFCR; /**< Interrupt flag clear register */ - __io uint32 CCR1; /**< Channel 1 configuration register */ - __io uint32 CNDTR1; /**< Channel 1 number of data register */ - __io uint32 CPAR1; /**< Channel 1 peripheral address register */ - __io uint32 CMAR1; /**< Channel 1 memory address register */ - const uint32 RESERVED1; /**< Reserved. */ - __io uint32 CCR2; /**< Channel 2 configuration register */ - __io uint32 CNDTR2; /**< Channel 2 number of data register */ - __io uint32 CPAR2; /**< Channel 2 peripheral address register */ - __io uint32 CMAR2; /**< Channel 2 memory address register */ - const uint32 RESERVED2; /**< Reserved. */ - __io uint32 CCR3; /**< Channel 3 configuration register */ - __io uint32 CNDTR3; /**< Channel 3 number of data register */ - __io uint32 CPAR3; /**< Channel 3 peripheral address register */ - __io uint32 CMAR3; /**< Channel 3 memory address register */ - const uint32 RESERVED3; /**< Reserved. */ - __io uint32 CCR4; /**< Channel 4 configuration register */ - __io uint32 CNDTR4; /**< Channel 4 number of data register */ - __io uint32 CPAR4; /**< Channel 4 peripheral address register */ - __io uint32 CMAR4; /**< Channel 4 memory address register */ - const uint32 RESERVED4; /**< Reserved. */ - __io uint32 CCR5; /**< Channel 5 configuration register */ - __io uint32 CNDTR5; /**< Channel 5 number of data register */ - __io uint32 CPAR5; /**< Channel 5 peripheral address register */ - __io uint32 CMAR5; /**< Channel 5 memory address register */ - const uint32 RESERVED5; /**< Reserved. */ - __io uint32 CCR6; /**< Channel 6 configuration register */ - __io uint32 CNDTR6; /**< Channel 6 number of data register */ - __io uint32 CPAR6; /**< Channel 6 peripheral address register */ - __io uint32 CMAR6; /**< Channel 6 memory address register */ - const uint32 RESERVED6; /**< Reserved. */ - __io uint32 CCR7; /**< Channel 7 configuration register */ - __io uint32 CNDTR7; /**< Channel 7 number of data register */ - __io uint32 CPAR7; /**< Channel 7 peripheral address register */ - __io uint32 CMAR7; /**< Channel 7 memory address register */ - const uint32 RESERVED7; /**< Reserved. */ -} dma_reg_map; - -/** DMA controller 1 register map base pointer */ -#define DMA1_BASE ((struct dma_reg_map*)0x40020000) - -#ifdef STM32_HIGH_DENSITY -/** DMA controller 2 register map base pointer */ -#define DMA2_BASE ((struct dma_reg_map*)0x40020400) -#endif - -/* - * Register bit definitions - */ - -/* Interrupt status register */ +#include -#define DMA_ISR_TEIF7_BIT 27 -#define DMA_ISR_HTIF7_BIT 26 -#define DMA_ISR_TCIF7_BIT 25 -#define DMA_ISR_GIF7_BIT 24 -#define DMA_ISR_TEIF6_BIT 23 -#define DMA_ISR_HTIF6_BIT 22 -#define DMA_ISR_TCIF6_BIT 21 -#define DMA_ISR_GIF6_BIT 20 -#define DMA_ISR_TEIF5_BIT 19 -#define DMA_ISR_HTIF5_BIT 18 -#define DMA_ISR_TCIF5_BIT 17 -#define DMA_ISR_GIF5_BIT 16 -#define DMA_ISR_TEIF4_BIT 15 -#define DMA_ISR_HTIF4_BIT 14 -#define DMA_ISR_TCIF4_BIT 13 -#define DMA_ISR_GIF4_BIT 12 -#define DMA_ISR_TEIF3_BIT 11 -#define DMA_ISR_HTIF3_BIT 10 -#define DMA_ISR_TCIF3_BIT 9 -#define DMA_ISR_GIF3_BIT 8 -#define DMA_ISR_TEIF2_BIT 7 -#define DMA_ISR_HTIF2_BIT 6 -#define DMA_ISR_TCIF2_BIT 5 -#define DMA_ISR_GIF2_BIT 4 -#define DMA_ISR_TEIF1_BIT 3 -#define DMA_ISR_HTIF1_BIT 2 -#define DMA_ISR_TCIF1_BIT 1 -#define DMA_ISR_GIF1_BIT 0 - -#define DMA_ISR_TEIF7 BIT(DMA_ISR_TEIF7_BIT) -#define DMA_ISR_HTIF7 BIT(DMA_ISR_HTIF7_BIT) -#define DMA_ISR_TCIF7 BIT(DMA_ISR_TCIF7_BIT) -#define DMA_ISR_GIF7 BIT(DMA_ISR_GIF7_BIT) -#define DMA_ISR_TEIF6 BIT(DMA_ISR_TEIF6_BIT) -#define DMA_ISR_HTIF6 BIT(DMA_ISR_HTIF6_BIT) -#define DMA_ISR_TCIF6 BIT(DMA_ISR_TCIF6_BIT) -#define DMA_ISR_GIF6 BIT(DMA_ISR_GIF6_BIT) -#define DMA_ISR_TEIF5 BIT(DMA_ISR_TEIF5_BIT) -#define DMA_ISR_HTIF5 BIT(DMA_ISR_HTIF5_BIT) -#define DMA_ISR_TCIF5 BIT(DMA_ISR_TCIF5_BIT) -#define DMA_ISR_GIF5 BIT(DMA_ISR_GIF5_BIT) -#define DMA_ISR_TEIF4 BIT(DMA_ISR_TEIF4_BIT) -#define DMA_ISR_HTIF4 BIT(DMA_ISR_HTIF4_BIT) -#define DMA_ISR_TCIF4 BIT(DMA_ISR_TCIF4_BIT) -#define DMA_ISR_GIF4 BIT(DMA_ISR_GIF4_BIT) -#define DMA_ISR_TEIF3 BIT(DMA_ISR_TEIF3_BIT) -#define DMA_ISR_HTIF3 BIT(DMA_ISR_HTIF3_BIT) -#define DMA_ISR_TCIF3 BIT(DMA_ISR_TCIF3_BIT) -#define DMA_ISR_GIF3 BIT(DMA_ISR_GIF3_BIT) -#define DMA_ISR_TEIF2 BIT(DMA_ISR_TEIF2_BIT) -#define DMA_ISR_HTIF2 BIT(DMA_ISR_HTIF2_BIT) -#define DMA_ISR_TCIF2 BIT(DMA_ISR_TCIF2_BIT) -#define DMA_ISR_GIF2 BIT(DMA_ISR_GIF2_BIT) -#define DMA_ISR_TEIF1 BIT(DMA_ISR_TEIF1_BIT) -#define DMA_ISR_HTIF1 BIT(DMA_ISR_HTIF1_BIT) -#define DMA_ISR_TCIF1 BIT(DMA_ISR_TCIF1_BIT) -#define DMA_ISR_GIF1 BIT(DMA_ISR_GIF1_BIT) - -/* Interrupt flag clear register */ - -#define DMA_IFCR_CTEIF7_BIT 27 -#define DMA_IFCR_CHTIF7_BIT 26 -#define DMA_IFCR_CTCIF7_BIT 25 -#define DMA_IFCR_CGIF7_BIT 24 -#define DMA_IFCR_CTEIF6_BIT 23 -#define DMA_IFCR_CHTIF6_BIT 22 -#define DMA_IFCR_CTCIF6_BIT 21 -#define DMA_IFCR_CGIF6_BIT 20 -#define DMA_IFCR_CTEIF5_BIT 19 -#define DMA_IFCR_CHTIF5_BIT 18 -#define DMA_IFCR_CTCIF5_BIT 17 -#define DMA_IFCR_CGIF5_BIT 16 -#define DMA_IFCR_CTEIF4_BIT 15 -#define DMA_IFCR_CHTIF4_BIT 14 -#define DMA_IFCR_CTCIF4_BIT 13 -#define DMA_IFCR_CGIF4_BIT 12 -#define DMA_IFCR_CTEIF3_BIT 11 -#define DMA_IFCR_CHTIF3_BIT 10 -#define DMA_IFCR_CTCIF3_BIT 9 -#define DMA_IFCR_CGIF3_BIT 8 -#define DMA_IFCR_CTEIF2_BIT 7 -#define DMA_IFCR_CHTIF2_BIT 6 -#define DMA_IFCR_CTCIF2_BIT 5 -#define DMA_IFCR_CGIF2_BIT 4 -#define DMA_IFCR_CTEIF1_BIT 3 -#define DMA_IFCR_CHTIF1_BIT 2 -#define DMA_IFCR_CTCIF1_BIT 1 -#define DMA_IFCR_CGIF1_BIT 0 - -#define DMA_IFCR_CTEIF7 BIT(DMA_IFCR_CTEIF7_BIT) -#define DMA_IFCR_CHTIF7 BIT(DMA_IFCR_CHTIF7_BIT) -#define DMA_IFCR_CTCIF7 BIT(DMA_IFCR_CTCIF7_BIT) -#define DMA_IFCR_CGIF7 BIT(DMA_IFCR_CGIF7_BIT) -#define DMA_IFCR_CTEIF6 BIT(DMA_IFCR_CTEIF6_BIT) -#define DMA_IFCR_CHTIF6 BIT(DMA_IFCR_CHTIF6_BIT) -#define DMA_IFCR_CTCIF6 BIT(DMA_IFCR_CTCIF6_BIT) -#define DMA_IFCR_CGIF6 BIT(DMA_IFCR_CGIF6_BIT) -#define DMA_IFCR_CTEIF5 BIT(DMA_IFCR_CTEIF5_BIT) -#define DMA_IFCR_CHTIF5 BIT(DMA_IFCR_CHTIF5_BIT) -#define DMA_IFCR_CTCIF5 BIT(DMA_IFCR_CTCIF5_BIT) -#define DMA_IFCR_CGIF5 BIT(DMA_IFCR_CGIF5_BIT) -#define DMA_IFCR_CTEIF4 BIT(DMA_IFCR_CTEIF4_BIT) -#define DMA_IFCR_CHTIF4 BIT(DMA_IFCR_CHTIF4_BIT) -#define DMA_IFCR_CTCIF4 BIT(DMA_IFCR_CTCIF4_BIT) -#define DMA_IFCR_CGIF4 BIT(DMA_IFCR_CGIF4_BIT) -#define DMA_IFCR_CTEIF3 BIT(DMA_IFCR_CTEIF3_BIT) -#define DMA_IFCR_CHTIF3 BIT(DMA_IFCR_CHTIF3_BIT) -#define DMA_IFCR_CTCIF3 BIT(DMA_IFCR_CTCIF3_BIT) -#define DMA_IFCR_CGIF3 BIT(DMA_IFCR_CGIF3_BIT) -#define DMA_IFCR_CTEIF2 BIT(DMA_IFCR_CTEIF2_BIT) -#define DMA_IFCR_CHTIF2 BIT(DMA_IFCR_CHTIF2_BIT) -#define DMA_IFCR_CTCIF2 BIT(DMA_IFCR_CTCIF2_BIT) -#define DMA_IFCR_CGIF2 BIT(DMA_IFCR_CGIF2_BIT) -#define DMA_IFCR_CTEIF1 BIT(DMA_IFCR_CTEIF1_BIT) -#define DMA_IFCR_CHTIF1 BIT(DMA_IFCR_CHTIF1_BIT) -#define DMA_IFCR_CTCIF1 BIT(DMA_IFCR_CTCIF1_BIT) -#define DMA_IFCR_CGIF1 BIT(DMA_IFCR_CGIF1_BIT) - -/* Channel configuration register */ - -#define DMA_CCR_MEM2MEM_BIT 14 -#define DMA_CCR_MINC_BIT 7 -#define DMA_CCR_PINC_BIT 6 -#define DMA_CCR_CIRC_BIT 5 -#define DMA_CCR_DIR_BIT 4 -#define DMA_CCR_TEIE_BIT 3 -#define DMA_CCR_HTIE_BIT 2 -#define DMA_CCR_TCIE_BIT 1 -#define DMA_CCR_EN_BIT 0 - -#define DMA_CCR_MEM2MEM BIT(DMA_CCR_MEM2MEM_BIT) -#define DMA_CCR_PL (0x3 << 12) -#define DMA_CCR_PL_LOW (0x0 << 12) -#define DMA_CCR_PL_MEDIUM (0x1 << 12) -#define DMA_CCR_PL_HIGH (0x2 << 12) -#define DMA_CCR_PL_VERY_HIGH (0x3 << 12) -#define DMA_CCR_MSIZE (0x3 << 10) -#define DMA_CCR_MSIZE_8BITS (0x0 << 10) -#define DMA_CCR_MSIZE_16BITS (0x1 << 10) -#define DMA_CCR_MSIZE_32BITS (0x2 << 10) -#define DMA_CCR_PSIZE (0x3 << 8) -#define DMA_CCR_PSIZE_8BITS (0x0 << 8) -#define DMA_CCR_PSIZE_16BITS (0x1 << 8) -#define DMA_CCR_PSIZE_32BITS (0x2 << 8) -#define DMA_CCR_MINC BIT(DMA_CCR_MINC_BIT) -#define DMA_CCR_PINC BIT(DMA_CCR_PINC_BIT) -#define DMA_CCR_CIRC BIT(DMA_CCR_CIRC_BIT) -#define DMA_CCR_DIR BIT(DMA_CCR_DIR_BIT) -#define DMA_CCR_TEIE BIT(DMA_CCR_TEIE_BIT) -#define DMA_CCR_HTIE BIT(DMA_CCR_HTIE_BIT) -#define DMA_CCR_TCIE BIT(DMA_CCR_TCIE_BIT) -#define DMA_CCR_EN BIT(DMA_CCR_EN_BIT) +#include +#include +#include /* * Devices */ -/** Encapsulates state related to a DMA channel interrupt. */ +/* Encapsulates state related to user interrupt handlers. You + * shouldn't touch these directly; use dma_attach_interrupt() and + * dma_detach_interupt() instead. */ typedef struct dma_handler_config { - void (*handler)(void); /**< User-specified channel interrupt - handler */ - nvic_irq_num irq_line; /**< Channel's NVIC interrupt number */ + void (*handler)(void); /* User handler */ + nvic_irq_num irq_line; /* IRQ line for interrupt */ } dma_handler_config; /** DMA device type */ typedef struct dma_dev { - dma_reg_map *regs; /**< Register map */ - rcc_clk_id clk_id; /**< Clock ID */ - dma_handler_config handlers[]; /**< - * @brief IRQ handlers and NVIC numbers. - * - * @see dma_attach_interrupt() - * @see dma_detach_interrupt() - */ + dma_reg_map *regs; /**< Register map */ + rcc_clk_id clk_id; /**< Clock ID */ + struct dma_handler_config handlers[]; /**< For internal use */ } dma_dev; -extern dma_dev *DMA1; -#ifdef STM32_HIGH_DENSITY -extern dma_dev *DMA2; -#endif - /* * Convenience functions */ void dma_init(dma_dev *dev); -/** Flags for DMA transfer configuration. */ -typedef enum dma_mode_flags { - DMA_MEM_2_MEM = 1 << 14, /**< Memory to memory mode */ - DMA_MINC_MODE = 1 << 7, /**< Auto-increment memory address */ - DMA_PINC_MODE = 1 << 6, /**< Auto-increment peripheral address */ - DMA_CIRC_MODE = 1 << 5, /**< Circular mode */ - DMA_FROM_MEM = 1 << 4, /**< Read from memory to peripheral */ - DMA_TRNS_ERR = 1 << 3, /**< Interrupt on transfer error */ - DMA_HALF_TRNS = 1 << 2, /**< Interrupt on half-transfer */ - DMA_TRNS_CMPLT = 1 << 1 /**< Interrupt on transfer completion */ -} dma_mode_flags; - -/** Source and destination transfer sizes. */ -typedef enum dma_xfer_size { - DMA_SIZE_8BITS = 0, /**< 8-bit transfers */ - DMA_SIZE_16BITS = 1, /**< 16-bit transfers */ - DMA_SIZE_32BITS = 2 /**< 32-bit transfers */ -} dma_xfer_size; - -/** DMA channel */ -typedef enum dma_channel { - DMA_CH1 = 1, /**< Channel 1 */ - DMA_CH2 = 2, /**< Channel 2 */ - DMA_CH3 = 3, /**< Channel 3 */ - DMA_CH4 = 4, /**< Channel 4 */ - DMA_CH5 = 5, /**< Channel 5 */ - DMA_CH6 = 6, /**< Channel 6 */ - DMA_CH7 = 7, /**< Channel 7 */ -} dma_channel; - -void dma_setup_transfer(dma_dev *dev, - dma_channel channel, - __io void *peripheral_address, - dma_xfer_size peripheral_size, - __io void *memory_address, - dma_xfer_size memory_size, - uint32 mode); - -void dma_set_num_transfers(dma_dev *dev, - dma_channel channel, - uint16 num_transfers); - -/** DMA transfer priority. */ -typedef enum dma_priority { - DMA_PRIORITY_LOW = DMA_CCR_PL_LOW, /**< Low priority */ - DMA_PRIORITY_MEDIUM = DMA_CCR_PL_MEDIUM, /**< Medium priority */ - DMA_PRIORITY_HIGH = DMA_CCR_PL_HIGH, /**< High priority */ - DMA_PRIORITY_VERY_HIGH = DMA_CCR_PL_VERY_HIGH /**< Very high priority */ -} dma_priority; - -void dma_set_priority(dma_dev *dev, - dma_channel channel, - dma_priority priority); - -void dma_attach_interrupt(dma_dev *dev, - dma_channel channel, - void (*handler)(void)); -void dma_detach_interrupt(dma_dev *dev, dma_channel channel); - -/** - * Encodes the reason why a DMA interrupt was called. - * @see dma_get_irq_cause() - */ -typedef enum dma_irq_cause { - DMA_TRANSFER_COMPLETE, /**< Transfer is complete. */ - DMA_TRANSFER_HALF_COMPLETE, /**< Transfer is half complete. */ - DMA_TRANSFER_ERROR, /**< Error occurred during transfer. */ -} dma_irq_cause; - -dma_irq_cause dma_get_irq_cause(dma_dev *dev, dma_channel channel); - -void dma_enable(dma_dev *dev, dma_channel channel); -void dma_disable(dma_dev *dev, dma_channel channel); - -void dma_set_mem_addr(dma_dev *dev, dma_channel channel, __io void *address); -void dma_set_per_addr(dma_dev *dev, dma_channel channel, __io void *address); - -/** - * @brief DMA channel register map type. - * - * Provides access to an individual channel's registers. - */ -typedef struct dma_channel_reg_map { - __io uint32 CCR; /**< Channel configuration register */ - __io uint32 CNDTR; /**< Channel number of data register */ - __io uint32 CPAR; /**< Channel peripheral address register */ - __io uint32 CMAR; /**< Channel memory address register */ -} dma_channel_reg_map; - -#define DMA_CHANNEL_NREGS 5 - -/** - * @brief Obtain a pointer to an individual DMA channel's registers. - * - * For example, dma_channel_regs(DMA1, DMA_CH1)->CCR is DMA1_BASE->CCR1. - * - * @param dev DMA device - * @param channel DMA channel whose channel register map to obtain. - */ -static inline dma_channel_reg_map* dma_channel_regs(dma_dev *dev, - dma_channel channel) { - __io uint32 *ccr1 = &dev->regs->CCR1; - return (dma_channel_reg_map*)(ccr1 + DMA_CHANNEL_NREGS * (channel - 1)); -} - -/** - * @brief Check if a DMA channel is enabled - * @param dev DMA device - * @param channel Channel whose enabled bit to check. - */ -static inline uint8 dma_is_channel_enabled(dma_dev *dev, dma_channel channel) { - return (uint8)(dma_channel_regs(dev, channel)->CCR & DMA_CCR_EN); -} - -/** - * @brief Get the ISR status bits for a DMA channel. - * - * The bits are returned right-aligned, in the following order: - * transfer error flag, half-transfer flag, transfer complete flag, - * global interrupt flag. - * - * If you're attempting to figure out why a DMA interrupt fired; you - * may find dma_get_irq_cause() more convenient. - * - * @param dev DMA device - * @param channel Channel whose ISR bits to return. - * @see dma_get_irq_cause(). - */ -static inline uint8 dma_get_isr_bits(dma_dev *dev, dma_channel channel) { - uint8 shift = (channel - 1) * 4; - return (dev->regs->ISR >> shift) & 0xF; -} - -/** - * @brief Clear the ISR status bits for a given DMA channel. - * - * If you're attempting to clean up after yourself in a DMA interrupt, - * you may find dma_get_irq_cause() more convenient. - * - * @param dev DMA device - * @param channel Channel whose ISR bits to clear. - * @see dma_get_irq_cause() +/* + * Hack: This is here so the series header can declare it and access + * dma_dev->regs without knowing the structure of dma_dev. Don't use + * it outside of a series header. */ -static inline void dma_clear_isr_bits(dma_dev *dev, dma_channel channel) { - dev->regs->IFCR = BIT(4 * (channel - 1)); +static __always_inline dma_reg_map* _dma_dev_regs(dma_dev *dev) { + return dev->regs; } #ifdef __cplusplus diff --git a/libmaple/rules.mk b/libmaple/rules.mk index 93716d2..d6efb1f 100644 --- a/libmaple/rules.mk +++ b/libmaple/rules.mk @@ -12,6 +12,7 @@ CFLAGS_$(d) = $(LIBMAPLE_PRIVATE_INCLUDES) $(LIBMAPLE_INCLUDES) -Wall -Werror # Local rules and targets cSRCS_$(d) := adc.c +cSRCS_$(d) += dma.c cSRCS_$(d) += flash.c cSRCS_$(d) += gpio.c cSRCS_$(d) += iwdg.c @@ -27,7 +28,6 @@ cSRCS_$(d) += usart_private.c cSRCS_$(d) += util.c # These still need to be ported to F2: # cSRCS_$(d) += dac.c -# cSRCS_$(d) += dma.c # cSRCS_$(d) += exti.c # cSRCS_$(d) += i2c.c diff --git a/libmaple/stm32f1/dma.c b/libmaple/stm32f1/dma.c new file mode 100644 index 0000000..14ac645 --- /dev/null +++ b/libmaple/stm32f1/dma.c @@ -0,0 +1,371 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Michael Hope. + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/dma.c + * @author Marti Bolivar ; + * Original implementation by Michael Hope + * @brief STM32F1 DMA support. + */ + +#include +#include + +/* + * Devices + */ + +static dma_dev dma1 = { + .regs = DMA1_BASE, + .clk_id = RCC_DMA1, + .handlers = {{ .handler = NULL, .irq_line = NVIC_DMA_CH1 }, + { .handler = NULL, .irq_line = NVIC_DMA_CH2 }, + { .handler = NULL, .irq_line = NVIC_DMA_CH3 }, + { .handler = NULL, .irq_line = NVIC_DMA_CH4 }, + { .handler = NULL, .irq_line = NVIC_DMA_CH5 }, + { .handler = NULL, .irq_line = NVIC_DMA_CH6 }, + { .handler = NULL, .irq_line = NVIC_DMA_CH7 }}, +}; +/** DMA1 device */ +dma_dev *DMA1 = &dma1; + +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) +static dma_dev dma2 = { + .regs = DMA2_BASE, + .clk_id = RCC_DMA2, + .handlers = {{ .handler = NULL, .irq_line = NVIC_DMA2_CH1 }, + { .handler = NULL, .irq_line = NVIC_DMA2_CH2 }, + { .handler = NULL, .irq_line = NVIC_DMA2_CH3 }, + { .handler = NULL, .irq_line = NVIC_DMA2_CH_4_5 }, + { .handler = NULL, .irq_line = NVIC_DMA2_CH_4_5 }}, /* !@#$ */ +}; +/** DMA2 device */ +dma_dev *DMA2 = &dma2; +#endif + +/* + * Routines + */ + +/** + * @brief Set up a DMA transfer. + * + * The channel will be disabled before being reconfigured. The + * transfer will have low priority by default. You may choose another + * priority before the transfer begins using dma_set_priority(), as + * well as performing any other configuration you desire. When the + * channel is configured to your liking, enable it using dma_enable(). + * + * @param dev DMA device. + * @param channel DMA channel. + * @param peripheral_address Base address of peripheral data register + * involved in the transfer. + * @param peripheral_size Peripheral data transfer size. + * @param memory_address Base memory address involved in the transfer. + * @param memory_size Memory data transfer size. + * @param mode Logical OR of dma_mode_flags + * @sideeffect Disables the given DMA channel. + * @see dma_xfer_size + * @see dma_mode_flags + * @see dma_set_num_transfers() + * @see dma_set_priority() + * @see dma_attach_interrupt() + * @see dma_enable() + */ +void dma_setup_transfer(dma_dev *dev, + dma_channel channel, + __io void *peripheral_address, + dma_xfer_size peripheral_size, + __io void *memory_address, + dma_xfer_size memory_size, + uint32 mode) { + dma_channel_reg_map *channel_regs = dma_channel_regs(dev, channel); + + dma_disable(dev, channel); /* can't write to CMAR/CPAR otherwise */ + channel_regs->CCR = (memory_size << 10) | (peripheral_size << 8) | mode; + channel_regs->CMAR = (uint32)memory_address; + channel_regs->CPAR = (uint32)peripheral_address; +} + +/** + * @brief Set the number of data to be transferred on a DMA channel. + * + * You may not call this function while the channel is enabled. + * + * @param dev DMA device + * @param channel Channel through which the transfer occurs. + * @param num_transfers + */ +void dma_set_num_transfers(dma_dev *dev, + dma_channel channel, + uint16 num_transfers) { + dma_channel_reg_map *channel_regs; + + ASSERT_FAULT(!dma_is_channel_enabled(dev, channel)); + + channel_regs = dma_channel_regs(dev, channel); + channel_regs->CNDTR = num_transfers; +} + +/** + * @brief Set the priority of a DMA transfer. + * + * You may not call this function while the channel is enabled. + * + * @param dev DMA device + * @param channel DMA channel + * @param priority priority to set. + */ +void dma_set_priority(dma_dev *dev, + dma_channel channel, + dma_priority priority) { + dma_channel_reg_map *channel_regs; + uint32 ccr; + + ASSERT_FAULT(!dma_is_channel_enabled(dev, channel)); + + channel_regs = dma_channel_regs(dev, channel); + ccr = channel_regs->CCR; + ccr &= ~DMA_CCR_PL; + ccr |= priority; + channel_regs->CCR = ccr; +} + +/** + * @brief Attach an interrupt to a DMA transfer. + * + * Interrupts are enabled using appropriate mode flags in + * dma_setup_transfer(). + * + * @param dev DMA device + * @param channel Channel to attach handler to + * @param handler Interrupt handler to call when channel interrupt fires. + * @see dma_setup_transfer() + * @see dma_get_irq_cause() + * @see dma_detach_interrupt() + */ +void dma_attach_interrupt(dma_dev *dev, + dma_channel channel, + void (*handler)(void)) { + dev->handlers[channel - 1].handler = handler; + nvic_irq_enable(dev->handlers[channel - 1].irq_line); +} + +/** + * @brief Detach a DMA transfer interrupt handler. + * + * After calling this function, the given channel's interrupts will be + * disabled. + * + * @param dev DMA device + * @param channel Channel whose handler to detach + * @sideeffect Clears interrupt enable bits in the channel's CCR register. + * @see dma_attach_interrupt() + */ +void dma_detach_interrupt(dma_dev *dev, dma_channel channel) { + /* Don't use nvic_irq_disable()! Think about DMA2 channels 4 and 5. */ + dma_channel_regs(dev, channel)->CCR &= ~0xF; + dev->handlers[channel - 1].handler = NULL; +} + +/** + * @brief Discover the reason why a DMA interrupt was called. + * + * You may only call this function within an attached interrupt + * handler for the given channel. + * + * This function resets the internal DMA register state which encodes + * the cause of the interrupt; consequently, it can only be called + * once per interrupt handler invocation. + * + * @param dev DMA device + * @param channel Channel whose interrupt is being handled. + * @return Reason why the interrupt fired. + * @sideeffect Clears channel status flags in dev->regs->ISR. + * @see dma_attach_interrupt() + * @see dma_irq_cause + */ +dma_irq_cause dma_get_irq_cause(dma_dev *dev, dma_channel channel) { + uint8 status_bits = dma_get_isr_bits(dev, channel); + + /* If the channel global interrupt flag is cleared, then + * something's very wrong. */ + ASSERT(status_bits & BIT(0)); + + dma_clear_isr_bits(dev, channel); + + /* ISR flags get set even if the corresponding interrupt enable + * bits in the channel's configuration register are cleared, so we + * can't use a switch here. + * + * Don't change the order of these if statements. */ + if (status_bits & BIT(3)) { + return DMA_TRANSFER_ERROR; + } else if (status_bits & BIT(1)) { + return DMA_TRANSFER_COMPLETE; + } else if (status_bits & BIT(2)) { + return DMA_TRANSFER_HALF_COMPLETE; + } else if (status_bits & BIT(0)) { + /* Shouldn't happen (unless someone messed up an IFCR write). */ + throb(); + } +#if DEBUG_LEVEL < DEBUG_ALL + else { + /* We shouldn't have been called, but the debug level is too + * low for the above ASSERT() to have had any effect. In + * order to fail fast, mimic the DMA controller's behavior + * when an error occurs. */ + dma_disable(dev, channel); + } +#endif + return DMA_TRANSFER_ERROR; +} + +/** + * @brief Enable a DMA channel. + * @param dev DMA device + * @param channel Channel to enable + */ +void dma_enable(dma_dev *dev, dma_channel channel) { + dma_channel_reg_map *chan_regs = dma_channel_regs(dev, channel); + bb_peri_set_bit(&chan_regs->CCR, DMA_CCR_EN_BIT, 1); +} + +/** + * @brief Disable a DMA channel. + * @param dev DMA device + * @param channel Channel to disable + */ +void dma_disable(dma_dev *dev, dma_channel channel) { + dma_channel_reg_map *chan_regs = dma_channel_regs(dev, channel); + bb_peri_set_bit(&chan_regs->CCR, DMA_CCR_EN_BIT, 0); +} + +/** + * @brief Set the base memory address where data will be read from or + * written to. + * + * You must not call this function while the channel is enabled. + * + * If the DMA memory size is 16 bits, the address is automatically + * aligned to a half-word. If the DMA memory size is 32 bits, the + * address is aligned to a word. + * + * @param dev DMA Device + * @param channel Channel whose base memory address to set. + * @param addr Memory base address to use. + */ +void dma_set_mem_addr(dma_dev *dev, dma_channel channel, __io void *addr) { + dma_channel_reg_map *chan_regs; + + ASSERT_FAULT(!dma_is_channel_enabled(dev, channel)); + + chan_regs = dma_channel_regs(dev, channel); + chan_regs->CMAR = (uint32)addr; +} + +/** + * @brief Set the base peripheral address where data will be read from + * or written to. + * + * You must not call this function while the channel is enabled. + * + * If the DMA peripheral size is 16 bits, the address is automatically + * aligned to a half-word. If the DMA peripheral size is 32 bits, the + * address is aligned to a word. + * + * @param dev DMA Device + * @param channel Channel whose peripheral data register base address to set. + * @param addr Peripheral memory base address to use. + */ +void dma_set_per_addr(dma_dev *dev, dma_channel channel, __io void *addr) { + dma_channel_reg_map *chan_regs; + + ASSERT_FAULT(!dma_is_channel_enabled(dev, channel)); + + chan_regs = dma_channel_regs(dev, channel); + chan_regs->CPAR = (uint32)addr; +} + +/* + * IRQ handlers + */ + +static __always_inline void dispatch_handler(dma_dev *dev, int channel) { + void (*handler)(void) = dev->handlers[channel - 1].handler; + if (handler) { + handler(); + dma_clear_isr_bits(dev, channel); /* in case handler doesn't */ + } +} + +void __irq_dma1_channel1(void) { + dispatch_handler(DMA1, DMA_CH1); +} + +void __irq_dma1_channel2(void) { + dispatch_handler(DMA1, DMA_CH2); +} + +void __irq_dma1_channel3(void) { + dispatch_handler(DMA1, DMA_CH3); +} + +void __irq_dma1_channel4(void) { + dispatch_handler(DMA1, DMA_CH4); +} + +void __irq_dma1_channel5(void) { + dispatch_handler(DMA1, DMA_CH5); +} + +void __irq_dma1_channel6(void) { + dispatch_handler(DMA1, DMA_CH6); +} + +void __irq_dma1_channel7(void) { + dispatch_handler(DMA1, DMA_CH7); +} + +#ifdef STM32_HIGH_DENSITY +void __irq_dma2_channel1(void) { + dispatch_handler(DMA2, DMA_CH1); +} + +void __irq_dma2_channel2(void) { + dispatch_handler(DMA2, DMA_CH2); +} + +void __irq_dma2_channel3(void) { + dispatch_handler(DMA2, DMA_CH3); +} + +void __irq_dma2_channel4_5(void) { + dispatch_handler(DMA2, DMA_CH4); + dispatch_handler(DMA2, DMA_CH5); +} +#endif diff --git a/libmaple/stm32f1/include/series/dma.h b/libmaple/stm32f1/include/series/dma.h new file mode 100644 index 0000000..60582ea --- /dev/null +++ b/libmaple/stm32f1/include/series/dma.h @@ -0,0 +1,438 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Michael Hope. + * Copyright (c) 2012 LeafLabs, LLC + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/include/series/dma.h + * @author Marti Bolivar ; + * Original implementation by Michael Hope + * @brief STM32F1 Direct Memory Access header + */ + +/* + * See /notes/dma-stm32f1.txt for more information. + */ + +#ifndef _LIBMAPLE_STM32F1_DMA_H_ +#define _LIBMAPLE_STM32F1_DMA_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include + +/* + * Register map and base pointers + */ + +/** + * @brief DMA register map type. + * + * Note that DMA controller 2 (register map base pointer DMA2_BASE) + * only supports channels 1--5. + */ +typedef struct dma_reg_map { + __io uint32 ISR; /**< Interrupt status register */ + __io uint32 IFCR; /**< Interrupt flag clear register */ + __io uint32 CCR1; /**< Channel 1 configuration register */ + __io uint32 CNDTR1; /**< Channel 1 number of data register */ + __io uint32 CPAR1; /**< Channel 1 peripheral address register */ + __io uint32 CMAR1; /**< Channel 1 memory address register */ + const uint32 RESERVED1; /**< Reserved. */ + __io uint32 CCR2; /**< Channel 2 configuration register */ + __io uint32 CNDTR2; /**< Channel 2 number of data register */ + __io uint32 CPAR2; /**< Channel 2 peripheral address register */ + __io uint32 CMAR2; /**< Channel 2 memory address register */ + const uint32 RESERVED2; /**< Reserved. */ + __io uint32 CCR3; /**< Channel 3 configuration register */ + __io uint32 CNDTR3; /**< Channel 3 number of data register */ + __io uint32 CPAR3; /**< Channel 3 peripheral address register */ + __io uint32 CMAR3; /**< Channel 3 memory address register */ + const uint32 RESERVED3; /**< Reserved. */ + __io uint32 CCR4; /**< Channel 4 configuration register */ + __io uint32 CNDTR4; /**< Channel 4 number of data register */ + __io uint32 CPAR4; /**< Channel 4 peripheral address register */ + __io uint32 CMAR4; /**< Channel 4 memory address register */ + const uint32 RESERVED4; /**< Reserved. */ + __io uint32 CCR5; /**< Channel 5 configuration register */ + __io uint32 CNDTR5; /**< Channel 5 number of data register */ + __io uint32 CPAR5; /**< Channel 5 peripheral address register */ + __io uint32 CMAR5; /**< Channel 5 memory address register */ + const uint32 RESERVED5; /**< Reserved. */ + __io uint32 CCR6; /**< Channel 6 configuration register */ + __io uint32 CNDTR6; /**< Channel 6 number of data register */ + __io uint32 CPAR6; /**< Channel 6 peripheral address register */ + __io uint32 CMAR6; /**< Channel 6 memory address register */ + const uint32 RESERVED6; /**< Reserved. */ + __io uint32 CCR7; /**< Channel 7 configuration register */ + __io uint32 CNDTR7; /**< Channel 7 number of data register */ + __io uint32 CPAR7; /**< Channel 7 peripheral address register */ + __io uint32 CMAR7; /**< Channel 7 memory address register */ + const uint32 RESERVED7; /**< Reserved. */ +} dma_reg_map; + +/** DMA controller 1 register map base pointer */ +#define DMA1_BASE ((struct dma_reg_map*)0x40020000) +/** DMA controller 2 register map base pointer */ +#define DMA2_BASE ((struct dma_reg_map*)0x40020400) + +/* + * Register bit definitions + */ + +/* Interrupt status register */ + +#define DMA_ISR_TEIF7_BIT 27 +#define DMA_ISR_HTIF7_BIT 26 +#define DMA_ISR_TCIF7_BIT 25 +#define DMA_ISR_GIF7_BIT 24 +#define DMA_ISR_TEIF6_BIT 23 +#define DMA_ISR_HTIF6_BIT 22 +#define DMA_ISR_TCIF6_BIT 21 +#define DMA_ISR_GIF6_BIT 20 +#define DMA_ISR_TEIF5_BIT 19 +#define DMA_ISR_HTIF5_BIT 18 +#define DMA_ISR_TCIF5_BIT 17 +#define DMA_ISR_GIF5_BIT 16 +#define DMA_ISR_TEIF4_BIT 15 +#define DMA_ISR_HTIF4_BIT 14 +#define DMA_ISR_TCIF4_BIT 13 +#define DMA_ISR_GIF4_BIT 12 +#define DMA_ISR_TEIF3_BIT 11 +#define DMA_ISR_HTIF3_BIT 10 +#define DMA_ISR_TCIF3_BIT 9 +#define DMA_ISR_GIF3_BIT 8 +#define DMA_ISR_TEIF2_BIT 7 +#define DMA_ISR_HTIF2_BIT 6 +#define DMA_ISR_TCIF2_BIT 5 +#define DMA_ISR_GIF2_BIT 4 +#define DMA_ISR_TEIF1_BIT 3 +#define DMA_ISR_HTIF1_BIT 2 +#define DMA_ISR_TCIF1_BIT 1 +#define DMA_ISR_GIF1_BIT 0 + +#define DMA_ISR_TEIF7 (1U << DMA_ISR_TEIF7_BIT) +#define DMA_ISR_HTIF7 (1U << DMA_ISR_HTIF7_BIT) +#define DMA_ISR_TCIF7 (1U << DMA_ISR_TCIF7_BIT) +#define DMA_ISR_GIF7 (1U << DMA_ISR_GIF7_BIT) +#define DMA_ISR_TEIF6 (1U << DMA_ISR_TEIF6_BIT) +#define DMA_ISR_HTIF6 (1U << DMA_ISR_HTIF6_BIT) +#define DMA_ISR_TCIF6 (1U << DMA_ISR_TCIF6_BIT) +#define DMA_ISR_GIF6 (1U << DMA_ISR_GIF6_BIT) +#define DMA_ISR_TEIF5 (1U << DMA_ISR_TEIF5_BIT) +#define DMA_ISR_HTIF5 (1U << DMA_ISR_HTIF5_BIT) +#define DMA_ISR_TCIF5 (1U << DMA_ISR_TCIF5_BIT) +#define DMA_ISR_GIF5 (1U << DMA_ISR_GIF5_BIT) +#define DMA_ISR_TEIF4 (1U << DMA_ISR_TEIF4_BIT) +#define DMA_ISR_HTIF4 (1U << DMA_ISR_HTIF4_BIT) +#define DMA_ISR_TCIF4 (1U << DMA_ISR_TCIF4_BIT) +#define DMA_ISR_GIF4 (1U << DMA_ISR_GIF4_BIT) +#define DMA_ISR_TEIF3 (1U << DMA_ISR_TEIF3_BIT) +#define DMA_ISR_HTIF3 (1U << DMA_ISR_HTIF3_BIT) +#define DMA_ISR_TCIF3 (1U << DMA_ISR_TCIF3_BIT) +#define DMA_ISR_GIF3 (1U << DMA_ISR_GIF3_BIT) +#define DMA_ISR_TEIF2 (1U << DMA_ISR_TEIF2_BIT) +#define DMA_ISR_HTIF2 (1U << DMA_ISR_HTIF2_BIT) +#define DMA_ISR_TCIF2 (1U << DMA_ISR_TCIF2_BIT) +#define DMA_ISR_GIF2 (1U << DMA_ISR_GIF2_BIT) +#define DMA_ISR_TEIF1 (1U << DMA_ISR_TEIF1_BIT) +#define DMA_ISR_HTIF1 (1U << DMA_ISR_HTIF1_BIT) +#define DMA_ISR_TCIF1 (1U << DMA_ISR_TCIF1_BIT) +#define DMA_ISR_GIF1 (1U << DMA_ISR_GIF1_BIT) + +/* Interrupt flag clear register */ + +#define DMA_IFCR_CTEIF7_BIT 27 +#define DMA_IFCR_CHTIF7_BIT 26 +#define DMA_IFCR_CTCIF7_BIT 25 +#define DMA_IFCR_CGIF7_BIT 24 +#define DMA_IFCR_CTEIF6_BIT 23 +#define DMA_IFCR_CHTIF6_BIT 22 +#define DMA_IFCR_CTCIF6_BIT 21 +#define DMA_IFCR_CGIF6_BIT 20 +#define DMA_IFCR_CTEIF5_BIT 19 +#define DMA_IFCR_CHTIF5_BIT 18 +#define DMA_IFCR_CTCIF5_BIT 17 +#define DMA_IFCR_CGIF5_BIT 16 +#define DMA_IFCR_CTEIF4_BIT 15 +#define DMA_IFCR_CHTIF4_BIT 14 +#define DMA_IFCR_CTCIF4_BIT 13 +#define DMA_IFCR_CGIF4_BIT 12 +#define DMA_IFCR_CTEIF3_BIT 11 +#define DMA_IFCR_CHTIF3_BIT 10 +#define DMA_IFCR_CTCIF3_BIT 9 +#define DMA_IFCR_CGIF3_BIT 8 +#define DMA_IFCR_CTEIF2_BIT 7 +#define DMA_IFCR_CHTIF2_BIT 6 +#define DMA_IFCR_CTCIF2_BIT 5 +#define DMA_IFCR_CGIF2_BIT 4 +#define DMA_IFCR_CTEIF1_BIT 3 +#define DMA_IFCR_CHTIF1_BIT 2 +#define DMA_IFCR_CTCIF1_BIT 1 +#define DMA_IFCR_CGIF1_BIT 0 + +#define DMA_IFCR_CTEIF7 (1U << DMA_IFCR_CTEIF7_BIT) +#define DMA_IFCR_CHTIF7 (1U << DMA_IFCR_CHTIF7_BIT) +#define DMA_IFCR_CTCIF7 (1U << DMA_IFCR_CTCIF7_BIT) +#define DMA_IFCR_CGIF7 (1U << DMA_IFCR_CGIF7_BIT) +#define DMA_IFCR_CTEIF6 (1U << DMA_IFCR_CTEIF6_BIT) +#define DMA_IFCR_CHTIF6 (1U << DMA_IFCR_CHTIF6_BIT) +#define DMA_IFCR_CTCIF6 (1U << DMA_IFCR_CTCIF6_BIT) +#define DMA_IFCR_CGIF6 (1U << DMA_IFCR_CGIF6_BIT) +#define DMA_IFCR_CTEIF5 (1U << DMA_IFCR_CTEIF5_BIT) +#define DMA_IFCR_CHTIF5 (1U << DMA_IFCR_CHTIF5_BIT) +#define DMA_IFCR_CTCIF5 (1U << DMA_IFCR_CTCIF5_BIT) +#define DMA_IFCR_CGIF5 (1U << DMA_IFCR_CGIF5_BIT) +#define DMA_IFCR_CTEIF4 (1U << DMA_IFCR_CTEIF4_BIT) +#define DMA_IFCR_CHTIF4 (1U << DMA_IFCR_CHTIF4_BIT) +#define DMA_IFCR_CTCIF4 (1U << DMA_IFCR_CTCIF4_BIT) +#define DMA_IFCR_CGIF4 (1U << DMA_IFCR_CGIF4_BIT) +#define DMA_IFCR_CTEIF3 (1U << DMA_IFCR_CTEIF3_BIT) +#define DMA_IFCR_CHTIF3 (1U << DMA_IFCR_CHTIF3_BIT) +#define DMA_IFCR_CTCIF3 (1U << DMA_IFCR_CTCIF3_BIT) +#define DMA_IFCR_CGIF3 (1U << DMA_IFCR_CGIF3_BIT) +#define DMA_IFCR_CTEIF2 (1U << DMA_IFCR_CTEIF2_BIT) +#define DMA_IFCR_CHTIF2 (1U << DMA_IFCR_CHTIF2_BIT) +#define DMA_IFCR_CTCIF2 (1U << DMA_IFCR_CTCIF2_BIT) +#define DMA_IFCR_CGIF2 (1U << DMA_IFCR_CGIF2_BIT) +#define DMA_IFCR_CTEIF1 (1U << DMA_IFCR_CTEIF1_BIT) +#define DMA_IFCR_CHTIF1 (1U << DMA_IFCR_CHTIF1_BIT) +#define DMA_IFCR_CTCIF1 (1U << DMA_IFCR_CTCIF1_BIT) +#define DMA_IFCR_CGIF1 (1U << DMA_IFCR_CGIF1_BIT) + +/* Channel configuration register */ + +#define DMA_CCR_MEM2MEM_BIT 14 +#define DMA_CCR_MINC_BIT 7 +#define DMA_CCR_PINC_BIT 6 +#define DMA_CCR_CIRC_BIT 5 +#define DMA_CCR_DIR_BIT 4 +#define DMA_CCR_TEIE_BIT 3 +#define DMA_CCR_HTIE_BIT 2 +#define DMA_CCR_TCIE_BIT 1 +#define DMA_CCR_EN_BIT 0 + +#define DMA_CCR_MEM2MEM (1U << DMA_CCR_MEM2MEM_BIT) +#define DMA_CCR_PL (0x3 << 12) +#define DMA_CCR_PL_LOW (0x0 << 12) +#define DMA_CCR_PL_MEDIUM (0x1 << 12) +#define DMA_CCR_PL_HIGH (0x2 << 12) +#define DMA_CCR_PL_VERY_HIGH (0x3 << 12) +#define DMA_CCR_MSIZE (0x3 << 10) +#define DMA_CCR_MSIZE_8BITS (0x0 << 10) +#define DMA_CCR_MSIZE_16BITS (0x1 << 10) +#define DMA_CCR_MSIZE_32BITS (0x2 << 10) +#define DMA_CCR_PSIZE (0x3 << 8) +#define DMA_CCR_PSIZE_8BITS (0x0 << 8) +#define DMA_CCR_PSIZE_16BITS (0x1 << 8) +#define DMA_CCR_PSIZE_32BITS (0x2 << 8) +#define DMA_CCR_MINC (1U << DMA_CCR_MINC_BIT) +#define DMA_CCR_PINC (1U << DMA_CCR_PINC_BIT) +#define DMA_CCR_CIRC (1U << DMA_CCR_CIRC_BIT) +#define DMA_CCR_DIR (1U << DMA_CCR_DIR_BIT) +#define DMA_CCR_TEIE (1U << DMA_CCR_TEIE_BIT) +#define DMA_CCR_HTIE (1U << DMA_CCR_HTIE_BIT) +#define DMA_CCR_TCIE (1U << DMA_CCR_TCIE_BIT) +#define DMA_CCR_EN (1U << DMA_CCR_EN_BIT) + +/* + * Devices + */ + +struct dma_dev; +extern struct dma_dev *DMA1; +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) +extern struct dma_dev *DMA2; +#endif + +/* + * Convenience routines. + */ + +/* This hack is due to a circular dependency between us and + * . */ +static __always_inline dma_reg_map* _dma_dev_regs(struct dma_dev*); + +/** Flags for DMA transfer configuration. */ +typedef enum dma_mode_flags { + DMA_MEM_2_MEM = 1 << 14, /**< Memory to memory mode */ + DMA_MINC_MODE = 1 << 7, /**< Auto-increment memory address */ + DMA_PINC_MODE = 1 << 6, /**< Auto-increment peripheral address */ + DMA_CIRC_MODE = 1 << 5, /**< Circular mode */ + DMA_FROM_MEM = 1 << 4, /**< Read from memory to peripheral */ + DMA_TRNS_ERR = 1 << 3, /**< Interrupt on transfer error */ + DMA_HALF_TRNS = 1 << 2, /**< Interrupt on half-transfer */ + DMA_TRNS_CMPLT = 1 << 1 /**< Interrupt on transfer completion */ +} dma_mode_flags; + +/** Source and destination transfer sizes. */ +typedef enum dma_xfer_size { + DMA_SIZE_8BITS = 0, /**< 8-bit transfers */ + DMA_SIZE_16BITS = 1, /**< 16-bit transfers */ + DMA_SIZE_32BITS = 2 /**< 32-bit transfers */ +} dma_xfer_size; + +/** DMA channel */ +typedef enum dma_channel { + DMA_CH1 = 1, /**< Channel 1 */ + DMA_CH2 = 2, /**< Channel 2 */ + DMA_CH3 = 3, /**< Channel 3 */ + DMA_CH4 = 4, /**< Channel 4 */ + DMA_CH5 = 5, /**< Channel 5 */ + DMA_CH6 = 6, /**< Channel 6 */ + DMA_CH7 = 7, /**< Channel 7 */ +} dma_channel; + +void dma_setup_transfer(struct dma_dev *dev, + dma_channel channel, + __io void *peripheral_address, + dma_xfer_size peripheral_size, + __io void *memory_address, + dma_xfer_size memory_size, + uint32 mode); + +void dma_set_num_transfers(struct dma_dev *dev, + dma_channel channel, + uint16 num_transfers); + +/** DMA transfer priority. */ +typedef enum dma_priority { + DMA_PRIORITY_LOW = DMA_CCR_PL_LOW, /**< Low priority */ + DMA_PRIORITY_MEDIUM = DMA_CCR_PL_MEDIUM, /**< Medium priority */ + DMA_PRIORITY_HIGH = DMA_CCR_PL_HIGH, /**< High priority */ + DMA_PRIORITY_VERY_HIGH = DMA_CCR_PL_VERY_HIGH /**< Very high priority */ +} dma_priority; + +void dma_set_priority(struct dma_dev *dev, + dma_channel channel, + dma_priority priority); + +void dma_attach_interrupt(struct dma_dev *dev, + dma_channel channel, + void (*handler)(void)); +void dma_detach_interrupt(struct dma_dev *dev, dma_channel channel); + +/** + * Encodes the reason why a DMA interrupt was called. + * @see dma_get_irq_cause() + */ +typedef enum dma_irq_cause { + DMA_TRANSFER_COMPLETE, /**< Transfer is complete. */ + DMA_TRANSFER_HALF_COMPLETE, /**< Transfer is half complete. */ + DMA_TRANSFER_ERROR, /**< Error occurred during transfer. */ +} dma_irq_cause; + +dma_irq_cause dma_get_irq_cause(struct dma_dev *dev, dma_channel channel); + +void dma_enable(struct dma_dev *dev, dma_channel channel); +void dma_disable(struct dma_dev *dev, dma_channel channel); + +void dma_set_mem_addr(struct dma_dev *dev, + dma_channel channel, + __io void *address); +void dma_set_per_addr(struct dma_dev *dev, + dma_channel channel, + __io void *address); + +/** + * @brief DMA channel register map type. + * + * Provides access to an individual channel's registers. + */ +typedef struct dma_channel_reg_map { + __io uint32 CCR; /**< Channel configuration register */ + __io uint32 CNDTR; /**< Channel number of data register */ + __io uint32 CPAR; /**< Channel peripheral address register */ + __io uint32 CMAR; /**< Channel memory address register */ +} dma_channel_reg_map; + +#define DMA_CHANNEL_NREGS 5 + +/** + * @brief Obtain a pointer to an individual DMA channel's registers. + * + * For example, dma_channel_regs(DMA1, DMA_CH1)->CCR is DMA1_BASE->CCR1. + * + * @param dev DMA device + * @param channel DMA channel whose channel register map to obtain. + */ +static inline dma_channel_reg_map* dma_channel_regs(struct dma_dev *dev, + dma_channel channel) { + __io uint32 *ccr1 = &_dma_dev_regs(dev)->CCR1; + return (dma_channel_reg_map*)(ccr1 + DMA_CHANNEL_NREGS * (channel - 1)); +} + +/** + * @brief Check if a DMA channel is enabled + * @param dev DMA device + * @param channel Channel whose enabled bit to check. + */ +static inline uint8 dma_is_channel_enabled(struct dma_dev *dev, + dma_channel channel) { + return (uint8)(dma_channel_regs(dev, channel)->CCR & DMA_CCR_EN); +} + +/** + * @brief Get the ISR status bits for a DMA channel. + * + * The bits are returned right-aligned, in the following order: + * transfer error flag, half-transfer flag, transfer complete flag, + * global interrupt flag. + * + * If you're attempting to figure out why a DMA interrupt fired; you + * may find dma_get_irq_cause() more convenient. + * + * @param dev DMA device + * @param channel Channel whose ISR bits to return. + * @see dma_get_irq_cause(). + */ +static inline uint8 dma_get_isr_bits(struct dma_dev *dev, + dma_channel channel) { + uint8 shift = (channel - 1) * 4; + return (_dma_dev_regs(dev)->ISR >> shift) & 0xF; +} + +/** + * @brief Clear the ISR status bits for a given DMA channel. + * + * If you're attempting to clean up after yourself in a DMA interrupt, + * you may find dma_get_irq_cause() more convenient. + * + * @param dev DMA device + * @param channel Channel whose ISR bits to clear. + * @see dma_get_irq_cause() + */ +static inline void dma_clear_isr_bits(struct dma_dev *dev, + dma_channel channel) { + _dma_dev_regs(dev)->IFCR = (1U << (4 * (channel - 1))); +} + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/libmaple/stm32f1/rules.mk b/libmaple/stm32f1/rules.mk index 52ceea6..b67f446 100644 --- a/libmaple/stm32f1/rules.mk +++ b/libmaple/stm32f1/rules.mk @@ -13,6 +13,7 @@ sSRCS_$(d) += vector_table_performance.S cSRCS_$(d) := adc.c cSRCS_$(d) += bkp.c +cSRCS_$(d) += dma.c cSRCS_$(d) += fsmc.c cSRCS_$(d) += gpio.c cSRCS_$(d) += rcc.c -- cgit v1.2.3 From 12dbd700d2a2172c40909b6302caf0aa83135478 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Thu, 3 May 2012 21:47:48 -0400 Subject: Fix wrong comment in libmaple/rules.mk. Signed-off-by: Marti Bolivar --- libmaple/rules.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libmaple/rules.mk') diff --git a/libmaple/rules.mk b/libmaple/rules.mk index d6efb1f..834c7a3 100644 --- a/libmaple/rules.mk +++ b/libmaple/rules.mk @@ -26,7 +26,7 @@ cSRCS_$(d) += timer.c cSRCS_$(d) += usart.c cSRCS_$(d) += usart_private.c cSRCS_$(d) += util.c -# These still need to be ported to F2: +# These still need to be brought back for F1: # cSRCS_$(d) += dac.c # cSRCS_$(d) += exti.c # cSRCS_$(d) += i2c.c -- cgit v1.2.3 From e34923631052c41349e660628fab310835ca5a5e Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Thu, 31 May 2012 16:02:00 -0400 Subject: Don't try to build some libmaple files. We can't do these on F2 right now. Signed-off-by: Marti Bolivar --- libmaple/rules.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'libmaple/rules.mk') diff --git a/libmaple/rules.mk b/libmaple/rules.mk index 834c7a3..5c63522 100644 --- a/libmaple/rules.mk +++ b/libmaple/rules.mk @@ -12,14 +12,14 @@ CFLAGS_$(d) = $(LIBMAPLE_PRIVATE_INCLUDES) $(LIBMAPLE_INCLUDES) -Wall -Werror # Local rules and targets cSRCS_$(d) := adc.c -cSRCS_$(d) += dma.c +# cSRCS_$(d) += dma.c cSRCS_$(d) += flash.c cSRCS_$(d) += gpio.c cSRCS_$(d) += iwdg.c cSRCS_$(d) += nvic.c cSRCS_$(d) += pwr.c cSRCS_$(d) += rcc.c -cSRCS_$(d) += spi.c +# cSRCS_$(d) += spi.c cSRCS_$(d) += syscalls.c cSRCS_$(d) += systick.c cSRCS_$(d) += timer.c -- cgit v1.2.3 From a5b5d4f27f94befaf5577563a0319e8194377118 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Sun, 3 Jun 2012 20:30:13 -0400 Subject: Bring back EXTI on F1, with deprecations for gpio.h on F1. Tested on Maple Mini with examples/mini-exti-test. Changes to Wirish are minor: use the new EXTI types exti_num and exti_cfg (see below) in place of now-deprecated variants in ext_interrupts.cpp. The way I originally did libmaple/exti.h was stupid, and fixing it turned out to be a little disruptive. libmaple/exti.h depends on libmaple/gpio.h (for AFIO), but that's a classic case of exposed implementation detail. So invert the dependency: make gpio.h depend on exti.h. Do this by adding exti_num and exti_cfg to exti.h; these respectively replace afio_exti_num and afio_exti_port. The afio_* variants are now deprecated. (Throw in a typedef and some macros at the bottom of the F1 series/gpio.h for backwards compatibility). Make exti_attach_interrupt() and exti_detach_interrupt() take exti_num/exti_cfg arguments instead of the afio_* variants. Make the EXTI dispatch routines __always_inline to defeat GCC -Os. Many renames throughout libmaple/stm32f1/ to stop using the deprecated names. Also move the previously F1-only gpio_exti_port() function into the public libmaple header. Reimplementing it in terms of rcc_clk_ids lets us deprecate the gpio_dev->exti_port field, which will save space in the future. While we're there, I notice that struct gpio_dev is defined once per series. That's dumb, as it misses the entire point of having device structs: they contain what's portable. So put the F1 version (which has the extra EXTI port field) into libmaple/gpio.h, and add the necessary exti_ports to libmaple/stm32f2/gpio.c. Sigh. We'll get rid of it eventually, at least. Clean up some other mistakes in gpio.h files as well (mostly removing util.h dependency). Sorry for the messy commit. For portability, add a new series-specific exti function, exti_select(). The F1 version in (new) libmaple/stm32f1/exti.c uses AFIO and some new private functionality in libmaple/exti.c and (new) libmaple/exti_private.h to make this convenient. We'll be able to do the SYSCFG equivalent on F2 without any trouble. Signed-off-by: Marti Bolivar --- libmaple/exti.c | 58 ++++++--- libmaple/exti_private.h | 34 ++++++ libmaple/include/libmaple/exti.h | 78 +++++++++++- libmaple/include/libmaple/gpio.h | 41 +++++-- libmaple/rules.mk | 2 +- libmaple/stm32f1/exti.c | 32 +++++ libmaple/stm32f1/gpio.c | 36 ++---- libmaple/stm32f1/include/series/gpio.h | 215 ++++++++++++++++++--------------- libmaple/stm32f1/rules.mk | 1 + libmaple/stm32f2/gpio.c | 9 ++ libmaple/stm32f2/include/series/gpio.h | 54 ++++----- wirish/ext_interrupts.cpp | 4 +- wirish/rules.mk | 2 +- 13 files changed, 375 insertions(+), 191 deletions(-) create mode 100644 libmaple/exti_private.h create mode 100644 libmaple/stm32f1/exti.c (limited to 'libmaple/rules.mk') diff --git a/libmaple/exti.c b/libmaple/exti.c index 248c4b6..d84b789 100644 --- a/libmaple/exti.c +++ b/libmaple/exti.c @@ -2,6 +2,7 @@ * The MIT License * * Copyright (c) 2010 Perry Hung. + * Copyright (c) 2011, 2012 LeafLabs, LLC. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -66,7 +67,7 @@ static exti_channel exti_channels[] = { }; /* - * Convenience routines + * Portable routines */ /** @@ -80,13 +81,13 @@ static exti_channel exti_channels[] = { * @param handler Function handler to execute when interrupt is triggered. * @param mode Type of transition to trigger on, one of: * EXTI_RISING, EXTI_FALLING, EXTI_RISING_FALLING. - * @see afio_exti_num - * @see afio_exti_port + * @see exti_num + * @see exti_cfg * @see voidFuncPtr * @see exti_trigger_mode */ -void exti_attach_interrupt(afio_exti_num num, - afio_exti_port port, +void exti_attach_interrupt(exti_num num, + exti_cfg port, voidFuncPtr handler, exti_trigger_mode mode) { ASSERT(handler); @@ -108,8 +109,8 @@ void exti_attach_interrupt(afio_exti_num num, break; } - /* Map num to port */ - afio_exti_select(num, port); + /* Use the chip-specific exti_select() to map num to port */ + exti_select(num, port); /* Unmask external interrupt request */ bb_peri_set_bit(&EXTI_BASE->IMR, num, 1); @@ -120,10 +121,10 @@ void exti_attach_interrupt(afio_exti_num num, /** * @brief Unregister an external interrupt handler - * @param num Number of the external interrupt line to disable. - * @see afio_exti_num + * @param num External interrupt line to disable. + * @see exti_num */ -void exti_detach_interrupt(afio_exti_num num) { +void exti_detach_interrupt(exti_num num) { /* First, mask the interrupt request */ bb_peri_set_bit(&EXTI_BASE->IMR, num, 0); @@ -135,28 +136,45 @@ void exti_detach_interrupt(afio_exti_num num) { exti_channels[num].handler = NULL; } +/* Weak default exti_select(), until we get F2 support */ +__weak void exti_select(exti_num num, exti_cfg port) { + ASSERT(0); +} + +/* + * Private routines + */ + +void exti_do_select(__io uint32 *exti_cr, exti_num num, exti_cfg port) { + uint32 shift = 4 * (num % 4); + uint32 cr = *exti_cr; + cr &= ~(0xF << shift); + cr |= port << shift; + *exti_cr = cr; +} + /* * Interrupt handlers */ void __irq_exti0(void) { - dispatch_single_exti(AFIO_EXTI_0); + dispatch_single_exti(EXTI0); } void __irq_exti1(void) { - dispatch_single_exti(AFIO_EXTI_1); + dispatch_single_exti(EXTI1); } void __irq_exti2(void) { - dispatch_single_exti(AFIO_EXTI_2); + dispatch_single_exti(EXTI2); } void __irq_exti3(void) { - dispatch_single_exti(AFIO_EXTI_3); + dispatch_single_exti(EXTI3); } void __irq_exti4(void) { - dispatch_single_exti(AFIO_EXTI_4); + dispatch_single_exti(EXTI4); } void __irq_exti9_5(void) { @@ -177,7 +195,7 @@ void __irq_exti15_10(void) { * won't actually be cleared in time and the ISR will fire again. To * compensate, this function NOPs for 2 cycles after clearing the * pending bits to ensure it takes effect. */ -static inline void clear_pending_msk(uint32 exti_msk) { +static __always_inline void clear_pending_msk(uint32 exti_msk) { EXTI_BASE->PR = exti_msk; asm volatile("nop"); asm volatile("nop"); @@ -185,7 +203,7 @@ static inline void clear_pending_msk(uint32 exti_msk) { /* This dispatch routine is for non-multiplexed EXTI lines only; i.e., * it doesn't check EXTI_PR. */ -static inline void dispatch_single_exti(uint32 exti) { +static __always_inline void dispatch_single_exti(uint32 exti) { voidFuncPtr handler = exti_channels[exti].handler; if (!handler) { @@ -193,18 +211,18 @@ static inline void dispatch_single_exti(uint32 exti) { } handler(); - clear_pending_msk(BIT(exti)); + clear_pending_msk(1U << exti); } /* Dispatch routine for EXTIs which share an IRQ. */ -static inline void dispatch_extis(uint32 start, uint32 stop) { +static __always_inline void dispatch_extis(uint32 start, uint32 stop) { uint32 pr = EXTI_BASE->PR; uint32 handled_msk = 0; uint32 exti; /* Dispatch user handlers for pending EXTIs. */ for (exti = start; exti <= stop; exti++) { - uint32 eb = BIT(exti); + uint32 eb = (1U << exti); if (pr & eb) { voidFuncPtr handler = exti_channels[exti].handler; if (handler) { diff --git a/libmaple/exti_private.h b/libmaple/exti_private.h new file mode 100644 index 0000000..4f0a4cf --- /dev/null +++ b/libmaple/exti_private.h @@ -0,0 +1,34 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. +*****************************************************************************/ + +#ifndef _LIBMAPLE_EXTI_PRIVATE_H_ +#define _LIBMAPLE_EXTI_PRIVATE_H_ + +#include + +void exti_do_select(__io uint32 *exti_cr, exti_num num, exti_cfg port); + +#endif diff --git a/libmaple/include/libmaple/exti.h b/libmaple/include/libmaple/exti.h index d7bfe51..5259a44 100644 --- a/libmaple/include/libmaple/exti.h +++ b/libmaple/include/libmaple/exti.h @@ -26,7 +26,7 @@ /** * @file libmaple/include/libmaple/exti.h - * @brief External interrupt control prototypes and defines + * @brief External interrupt control */ /* See notes/exti.txt for more info */ @@ -38,8 +38,11 @@ extern "C"{ #endif -#include -#include +#include + +/* + * Register map and base pointer. + */ /** EXTI register map type */ typedef struct exti_reg_map { @@ -54,6 +57,51 @@ typedef struct exti_reg_map { /** EXTI register map base pointer */ #define EXTI_BASE ((struct exti_reg_map*)0x40010400) +/* + * Types: exti_num, exti_cfg, exti_trigger_mode. + * + * A combination of these three specifies an external interrupt + * configuration (see exti_attach_interrupt()). + */ + +/** EXTI line. */ +typedef enum exti_num { + EXTI0, /**< EXTI line 0 */ + EXTI1, /**< EXTI line 1 */ + EXTI2, /**< EXTI line 2 */ + EXTI3, /**< EXTI line 3 */ + EXTI4, /**< EXTI line 4 */ + EXTI5, /**< EXTI line 5 */ + EXTI6, /**< EXTI line 6 */ + EXTI7, /**< EXTI line 7 */ + EXTI8, /**< EXTI line 8 */ + EXTI9, /**< EXTI line 9 */ + EXTI10, /**< EXTI line 10 */ + EXTI11, /**< EXTI line 11 */ + EXTI12, /**< EXTI line 12 */ + EXTI13, /**< EXTI line 13 */ + EXTI14, /**< EXTI line 14 */ + EXTI15, /**< EXTI line 15 */ +} exti_num; + +/** + * @brief EXTI port configuration + * + * These specify which GPIO port an external interrupt line should be + * connected to. + */ +typedef enum exti_cfg { + EXTI_PA, /**< Use PAx pin */ + EXTI_PB, /**< Use PBx pin */ + EXTI_PC, /**< Use PCx pin */ + EXTI_PD, /**< Use PDx pin */ + EXTI_PE, /**< Use PEx pin */ + EXTI_PF, /**< Use PFx pin */ + EXTI_PG, /**< Use PGx pin */ + EXTI_PH, /**< Use PHx pin */ + EXTI_PI, /**< Use PIx pin */ +} exti_cfg; + /** External interrupt trigger mode */ typedef enum exti_trigger_mode { EXTI_RISING, /**< Trigger on the rising edge */ @@ -61,11 +109,29 @@ typedef enum exti_trigger_mode { EXTI_RISING_FALLING /**< Trigger on both the rising and falling edges */ } exti_trigger_mode; -void exti_attach_interrupt(afio_exti_num num, - afio_exti_port port, +/* + * Routines + */ + +void exti_attach_interrupt(exti_num num, + exti_cfg port, voidFuncPtr handler, exti_trigger_mode mode); -void exti_detach_interrupt(afio_exti_num num); +void exti_detach_interrupt(exti_num num); + +/** + * @brief Set the GPIO port for an EXTI line. + * + * This is a low-level routine that most users will not + * need. exti_attach_interrupt() handles calling this function + * appropriately. + * + * @param num EXTI line + * @param port EXTI configuration for GPIO port to connect to num. + * @see exti_num + * @see exti_cfg + */ +extern void exti_select(exti_num num, exti_cfg port); #ifdef __cplusplus } // extern "C" diff --git a/libmaple/include/libmaple/gpio.h b/libmaple/include/libmaple/gpio.h index ca7b2bf..0cc3746 100644 --- a/libmaple/include/libmaple/gpio.h +++ b/libmaple/include/libmaple/gpio.h @@ -2,6 +2,7 @@ * The MIT License * * Copyright (c) 2010 Perry Hung. + * Copyright (c) 2011, 2012 LeafLabs, LLC. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -38,21 +39,45 @@ extern "C"{ /* * Note: Series header must define: - * - struct gpio_dev (and declare extern pointers to series-provided ones) - * - enum gpio_pin_mode (TODO think hard on this) + * - enum gpio_pin_mode (TODO think harder about portability here) */ #include -#include +#include +#include +#include /* - * GPIO Convenience routines + * Device type + */ + +/** GPIO device type */ +typedef struct gpio_dev { + gpio_reg_map *regs; /**< Register map */ + rcc_clk_id clk_id; /**< RCC clock information */ + /** + * @brief (Deprecated) External interrupt port. + * Instead of dev->exti_port, use gpio_exti_port(dev). + */ + exti_cfg exti_port; +} gpio_dev; + +/* + * Portable routines */ void gpio_init(gpio_dev *dev); void gpio_init_all(void); -/* TODO deprecate this? We should probably take a flags argument. */ +/* TODO flags argument version? */ void gpio_set_mode(gpio_dev *dev, uint8 pin, gpio_pin_mode mode); +/** + * @brief Get a GPIO port's corresponding EXTI port configuration. + * @param dev GPIO port whose exti_cfg to return. + */ +static inline exti_cfg gpio_exti_port(gpio_dev *dev) { + return (exti_cfg)(EXTI_PA + (dev->clk_id - RCC_GPIOA)); +} + /** * Set or reset a GPIO pin. * @@ -64,7 +89,7 @@ void gpio_set_mode(gpio_dev *dev, uint8 pin, gpio_pin_mode mode); */ static inline void gpio_write_bit(gpio_dev *dev, uint8 pin, uint8 val) { val = !val; /* "set" bits are lower than "reset" bits */ - dev->regs->BSRR = BIT(pin) << (16 * val); + dev->regs->BSRR = (1U << pin) << (16 * val); } /** @@ -77,7 +102,7 @@ static inline void gpio_write_bit(gpio_dev *dev, uint8 pin, uint8 val) { * @return True if the pin is set, false otherwise. */ static inline uint32 gpio_read_bit(gpio_dev *dev, uint8 pin) { - return dev->regs->IDR & BIT(pin); + return dev->regs->IDR & (1U << pin); } /** @@ -86,7 +111,7 @@ static inline uint32 gpio_read_bit(gpio_dev *dev, uint8 pin) { * @param pin Pin on dev to toggle. */ static inline void gpio_toggle_bit(gpio_dev *dev, uint8 pin) { - dev->regs->ODR = dev->regs->ODR ^ BIT(pin); + dev->regs->ODR = dev->regs->ODR ^ (1U << pin); } #ifdef __cplusplus diff --git a/libmaple/rules.mk b/libmaple/rules.mk index 5c63522..b39c318 100644 --- a/libmaple/rules.mk +++ b/libmaple/rules.mk @@ -13,6 +13,7 @@ CFLAGS_$(d) = $(LIBMAPLE_PRIVATE_INCLUDES) $(LIBMAPLE_INCLUDES) -Wall -Werror # Local rules and targets cSRCS_$(d) := adc.c # cSRCS_$(d) += dma.c +cSRCS_$(d) += exti.c cSRCS_$(d) += flash.c cSRCS_$(d) += gpio.c cSRCS_$(d) += iwdg.c @@ -28,7 +29,6 @@ cSRCS_$(d) += usart_private.c cSRCS_$(d) += util.c # These still need to be brought back for F1: # cSRCS_$(d) += dac.c -# cSRCS_$(d) += exti.c # cSRCS_$(d) += i2c.c sSRCS_$(d) := exc.S diff --git a/libmaple/stm32f1/exti.c b/libmaple/stm32f1/exti.c new file mode 100644 index 0000000..b9ff401 --- /dev/null +++ b/libmaple/stm32f1/exti.c @@ -0,0 +1,32 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. +*****************************************************************************/ + +#include +#include "exti_private.h" + +void exti_select(exti_num num, exti_cfg port) { + exti_do_select(&AFIO_BASE->EXTICR1 + num / 4, num, port); +} diff --git a/libmaple/stm32f1/gpio.c b/libmaple/stm32f1/gpio.c index 2cbe299..4b596e9 100644 --- a/libmaple/stm32f1/gpio.c +++ b/libmaple/stm32f1/gpio.c @@ -39,7 +39,7 @@ gpio_dev gpioa = { .regs = GPIOA_BASE, .clk_id = RCC_GPIOA, - .exti_port = AFIO_EXTI_PA, + .exti_port = EXTI_PA, }; /** GPIO port A device. */ gpio_dev* const GPIOA = &gpioa; @@ -47,7 +47,7 @@ gpio_dev* const GPIOA = &gpioa; gpio_dev gpiob = { .regs = GPIOB_BASE, .clk_id = RCC_GPIOB, - .exti_port = AFIO_EXTI_PB, + .exti_port = EXTI_PB, }; /** GPIO port B device. */ gpio_dev* const GPIOB = &gpiob; @@ -55,7 +55,7 @@ gpio_dev* const GPIOB = &gpiob; gpio_dev gpioc = { .regs = GPIOC_BASE, .clk_id = RCC_GPIOC, - .exti_port = AFIO_EXTI_PC, + .exti_port = EXTI_PC, }; /** GPIO port C device. */ gpio_dev* const GPIOC = &gpioc; @@ -63,7 +63,7 @@ gpio_dev* const GPIOC = &gpioc; gpio_dev gpiod = { .regs = GPIOD_BASE, .clk_id = RCC_GPIOD, - .exti_port = AFIO_EXTI_PD, + .exti_port = EXTI_PD, }; /** GPIO port D device. */ gpio_dev* const GPIOD = &gpiod; @@ -72,7 +72,7 @@ gpio_dev* const GPIOD = &gpiod; gpio_dev gpioe = { .regs = GPIOE_BASE, .clk_id = RCC_GPIOE, - .exti_port = AFIO_EXTI_PE, + .exti_port = EXTI_PE, }; /** GPIO port E device. */ gpio_dev* const GPIOE = &gpioe; @@ -80,7 +80,7 @@ gpio_dev* const GPIOE = &gpioe; gpio_dev gpiof = { .regs = GPIOF_BASE, .clk_id = RCC_GPIOF, - .exti_port = AFIO_EXTI_PF, + .exti_port = EXTI_PF, }; /** GPIO port F device. */ gpio_dev* const GPIOF = &gpiof; @@ -88,7 +88,7 @@ gpio_dev* const GPIOF = &gpiof; gpio_dev gpiog = { .regs = GPIOG_BASE, .clk_id = RCC_GPIOG, - .exti_port = AFIO_EXTI_PG, + .exti_port = EXTI_PG, }; /** GPIO port G device. */ gpio_dev* const GPIOG = &gpiog; @@ -132,9 +132,9 @@ void gpio_set_mode(gpio_dev *dev, uint8 pin, gpio_pin_mode mode) { *cr = tmp; if (mode == GPIO_INPUT_PD) { - regs->ODR &= ~BIT(pin); + regs->ODR &= ~(1U << pin); } else if (mode == GPIO_INPUT_PU) { - regs->ODR |= BIT(pin); + regs->ODR |= (1U << pin); } } @@ -152,24 +152,6 @@ void afio_init(void) { #define AFIO_EXTI_SEL_MASK 0xF -/** - * @brief Select a source input for an external interrupt. - * - * @param exti External interrupt. - * @param gpio_port Port which contains pin to use as source input. - * @see afio_exti_num - * @see afio_exti_port - */ -void afio_exti_select(afio_exti_num exti, afio_exti_port gpio_port) { - __io uint32 *exti_cr = &AFIO_BASE->EXTICR1 + exti / 4; - uint32 shift = 4 * (exti % 4); - uint32 cr = *exti_cr; - - cr &= ~(AFIO_EXTI_SEL_MASK << shift); - cr |= gpio_port << shift; - *exti_cr = cr; -} - /** * @brief Perform an alternate function remap. * @param remapping Remapping to perform. diff --git a/libmaple/stm32f1/include/series/gpio.h b/libmaple/stm32f1/include/series/gpio.h index 1f209fe..0ca6d56 100644 --- a/libmaple/stm32f1/include/series/gpio.h +++ b/libmaple/stm32f1/include/series/gpio.h @@ -2,7 +2,7 @@ * The MIT License * * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2011 LeafLabs, LLC. + * Copyright (c) 2011, 2012 LeafLabs, LLC. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -27,7 +27,7 @@ /** * @file libmaple/stm32f1/include/series/gpio.h - * @brief STM32F1 GPIO support. + * @brief STM32F1 GPIO and AFIO support. * * General purpose I/O (GPIO) and Alternate Function I/O (AFIO) * prototypes, defines, and support functions. @@ -40,8 +40,9 @@ extern "C"{ #endif -#include -#include +#include +#include +#include /* * GPIO register maps and devices @@ -58,46 +59,22 @@ typedef struct gpio_reg_map { __io uint32 LCKR; /**< Port configuration lock register */ } gpio_reg_map; -/** - * @brief External interrupt line port selector. - * - * Used to determine which GPIO port to map an external interrupt line - * onto. */ -/* (See AFIO sections, below) */ -typedef enum afio_exti_port { - AFIO_EXTI_PA, /**< Use port A (PAx) pin. */ - AFIO_EXTI_PB, /**< Use port B (PBx) pin. */ - AFIO_EXTI_PC, /**< Use port C (PCx) pin. */ - AFIO_EXTI_PD, /**< Use port D (PDx) pin. */ -#ifdef STM32_HIGH_DENSITY - AFIO_EXTI_PE, /**< Use port E (PEx) pin. */ - AFIO_EXTI_PF, /**< Use port F (PFx) pin. */ - AFIO_EXTI_PG, /**< Use port G (PGx) pin. */ -#endif -} afio_exti_port; - -/** GPIO device type */ -typedef struct gpio_dev { - gpio_reg_map *regs; /**< Register map */ - rcc_clk_id clk_id; /**< RCC clock information */ - afio_exti_port exti_port; /**< AFIO external interrupt port value */ -} gpio_dev; - -extern gpio_dev gpioa; -extern gpio_dev* const GPIOA; -extern gpio_dev gpiob; -extern gpio_dev* const GPIOB; -extern gpio_dev gpioc; -extern gpio_dev* const GPIOC; -extern gpio_dev gpiod; -extern gpio_dev* const GPIOD; +struct gpio_dev; +extern struct gpio_dev gpioa; +extern struct gpio_dev* const GPIOA; +extern struct gpio_dev gpiob; +extern struct gpio_dev* const GPIOB; +extern struct gpio_dev gpioc; +extern struct gpio_dev* const GPIOC; +extern struct gpio_dev gpiod; +extern struct gpio_dev* const GPIOD; #ifdef STM32_HIGH_DENSITY -extern gpio_dev gpioe; -extern gpio_dev* const GPIOE; -extern gpio_dev gpiof; -extern gpio_dev* const GPIOF; -extern gpio_dev gpiog; -extern gpio_dev* const GPIOG; +extern struct gpio_dev gpioe; +extern struct gpio_dev* const GPIOE; +extern struct gpio_dev gpiof; +extern struct gpio_dev* const GPIOF; +extern struct gpio_dev gpiog; +extern struct gpio_dev* const GPIOG; #endif /** GPIO port A register map base pointer */ @@ -108,14 +85,12 @@ extern gpio_dev* const GPIOG; #define GPIOC_BASE ((struct gpio_reg_map*)0x40011000) /** GPIO port D register map base pointer */ #define GPIOD_BASE ((struct gpio_reg_map*)0x40011400) -#ifdef STM32_HIGH_DENSITY /** GPIO port E register map base pointer */ #define GPIOE_BASE ((struct gpio_reg_map*)0x40011800) /** GPIO port F register map base pointer */ #define GPIOF_BASE ((struct gpio_reg_map*)0x40011C00) /** GPIO port G register map base pointer */ #define GPIOG_BASE ((struct gpio_reg_map*)0x40012000) -#endif /* * GPIO register bit definitions @@ -138,7 +113,7 @@ extern gpio_dev* const GPIOG; #define GPIO_CR_MODE_OUTPUT_50MHZ 0x3 /** - * @brief GPIO Pin modes. + * @brief GPIO pin modes. * * These only allow for 50MHZ max output speeds; if you want slower, * use direct register access. @@ -164,14 +139,6 @@ typedef enum gpio_pin_mode { /* GPIO_INPUT_PU treated as a special case, for ODR twiddling */ } gpio_pin_mode; -/** - * @brief Get a GPIO port's corresponding afio_exti_port. - * @param dev GPIO device whose afio_exti_port to return. - */ -static inline afio_exti_port gpio_exti_port(gpio_dev *dev) { - return dev->exti_port; -} - /* * AFIO register map */ @@ -232,17 +199,17 @@ typedef struct afio_reg_map { #define AFIO_MAPR_SWJ_CFG_FULL_SWJ_NO_NJRST (0x1 << 24) #define AFIO_MAPR_SWJ_CFG_NO_JTAG_SW (0x2 << 24) #define AFIO_MAPR_SWJ_CFG_NO_JTAG_NO_SW (0x4 << 24) -#define AFIO_MAPR_ADC2_ETRGREG_REMAP BIT(20) -#define AFIO_MAPR_ADC2_ETRGINJ_REMAP BIT(19) -#define AFIO_MAPR_ADC1_ETRGREG_REMAP BIT(18) -#define AFIO_MAPR_ADC1_ETRGINJ_REMAP BIT(17) -#define AFIO_MAPR_TIM5CH4_IREMAP BIT(16) -#define AFIO_MAPR_PD01_REMAP BIT(15) +#define AFIO_MAPR_ADC2_ETRGREG_REMAP (1U << 20) +#define AFIO_MAPR_ADC2_ETRGINJ_REMAP (1U << 19) +#define AFIO_MAPR_ADC1_ETRGREG_REMAP (1U << 18) +#define AFIO_MAPR_ADC1_ETRGINJ_REMAP (1U << 17) +#define AFIO_MAPR_TIM5CH4_IREMAP (1U << 16) +#define AFIO_MAPR_PD01_REMAP (1U << 15) #define AFIO_MAPR_CAN_REMAP (0x3 << 13) #define AFIO_MAPR_CAN_REMAP_NONE (0x0 << 13) #define AFIO_MAPR_CAN_REMAP_PB8_PB9 (0x2 << 13) #define AFIO_MAPR_CAN_REMAP_PD0_PD1 (0x3 << 13) -#define AFIO_MAPR_TIM4_REMAP BIT(12) +#define AFIO_MAPR_TIM4_REMAP (1U << 12) #define AFIO_MAPR_TIM3_REMAP (0x3 << 10) #define AFIO_MAPR_TIM3_REMAP_NONE (0x0 << 10) #define AFIO_MAPR_TIM3_REMAP_PARTIAL (0x2 << 10) @@ -260,10 +227,10 @@ typedef struct afio_reg_map { #define AFIO_MAPR_USART3_REMAP_NONE (0x0 << 4) #define AFIO_MAPR_USART3_REMAP_PARTIAL (0x1 << 4) #define AFIO_MAPR_USART3_REMAP_FULL (0x3 << 4) -#define AFIO_MAPR_USART2_REMAP BIT(3) -#define AFIO_MAPR_USART1_REMAP BIT(2) -#define AFIO_MAPR_I2C1_REMAP BIT(1) -#define AFIO_MAPR_SPI1_REMAP BIT(0) +#define AFIO_MAPR_USART2_REMAP (1U << 3) +#define AFIO_MAPR_USART1_REMAP (1U << 2) +#define AFIO_MAPR_I2C1_REMAP (1U << 1) +#define AFIO_MAPR_SPI1_REMAP (1U << 0) /* External interrupt configuration register 1 */ @@ -337,12 +304,12 @@ typedef struct afio_reg_map { /* AF remap and debug I/O configuration register 2 */ -#define AFIO_MAPR2_FSMC_NADV BIT(10) -#define AFIO_MAPR2_TIM14_REMAP BIT(9) -#define AFIO_MAPR2_TIM13_REMAP BIT(8) -#define AFIO_MAPR2_TIM11_REMAP BIT(7) -#define AFIO_MAPR2_TIM10_REMAP BIT(6) -#define AFIO_MAPR2_TIM9_REMAP BIT(5) +#define AFIO_MAPR2_FSMC_NADV (1U << 10) +#define AFIO_MAPR2_TIM14_REMAP (1U << 9) +#define AFIO_MAPR2_TIM13_REMAP (1U << 8) +#define AFIO_MAPR2_TIM11_REMAP (1U << 7) +#define AFIO_MAPR2_TIM10_REMAP (1U << 6) +#define AFIO_MAPR2_TIM9_REMAP (1U << 5) /* * AFIO convenience routines @@ -350,33 +317,9 @@ typedef struct afio_reg_map { void afio_init(void); -/** - * External interrupt line numbers. - */ -typedef enum afio_exti_num { - AFIO_EXTI_0, /**< External interrupt line 0. */ - AFIO_EXTI_1, /**< External interrupt line 1. */ - AFIO_EXTI_2, /**< External interrupt line 2. */ - AFIO_EXTI_3, /**< External interrupt line 3. */ - AFIO_EXTI_4, /**< External interrupt line 4. */ - AFIO_EXTI_5, /**< External interrupt line 5. */ - AFIO_EXTI_6, /**< External interrupt line 6. */ - AFIO_EXTI_7, /**< External interrupt line 7. */ - AFIO_EXTI_8, /**< External interrupt line 8. */ - AFIO_EXTI_9, /**< External interrupt line 9. */ - AFIO_EXTI_10, /**< External interrupt line 10. */ - AFIO_EXTI_11, /**< External interrupt line 11. */ - AFIO_EXTI_12, /**< External interrupt line 12. */ - AFIO_EXTI_13, /**< External interrupt line 13. */ - AFIO_EXTI_14, /**< External interrupt line 14. */ - AFIO_EXTI_15, /**< External interrupt line 15. */ -} afio_exti_num; - -void afio_exti_select(afio_exti_num exti, afio_exti_port gpio_port); - /* HACK: Use upper bit to denote MAPR2, Bit 31 is reserved and * not used in either MAPR or MAPR2 */ -#define AFIO_REMAP_USE_MAPR2 (1 << 31) +#define AFIO_REMAP_USE_MAPR2 (1U << 31) /** * @brief Available peripheral remaps. @@ -474,6 +417,86 @@ static inline void afio_cfg_debug_ports(afio_debug_cfg config) { *mapr = (*mapr & ~AFIO_MAPR_SWJ_CFG) | config; } +/* + * Deprecated bits + */ + +/** + * @brief Deprecated. Use exti_cfg instead. + * + * In previous versions of libmaple, exti_attach_interrupt() took an + * afio_exti_port argument; afio_exti_port was also a member of struct + * gpio_dev. This isn't portable, so we now use exti_cfg + * instead. This typedef (and the macros AFIO_EXTI_PA, ..., + * AFIO_EXTI_PG) exist to preserve backwards compatibility. + */ +typedef exti_cfg afio_exti_port; + +/** Deprecated. Use EXTI_PA instead. */ +#define AFIO_EXTI_PA EXTI_PA +/** Deprecated. Use EXTI_PB instead. */ +#define AFIO_EXTI_PB EXTI_PB +/** Deprecated. Use EXTI_PC instead. */ +#define AFIO_EXTI_PC EXTI_PC +/** Deprecated. Use EXTI_PD instead. */ +#define AFIO_EXTI_PD EXTI_PD +/** Deprecated. Use EXTI_PE instead. */ +#define AFIO_EXTI_PE EXTI_PE +/** Deprecated. Use EXTI_PF instead. */ +#define AFIO_EXTI_PF EXTI_PF +/** Deprecated. Use EXTI_PG instead. */ +#define AFIO_EXTI_PG EXTI_PG + +/** + * @brief Deprecated. Use exti_num instead. + * + * In previous versions of libmaple, exti_attach_interrupt() took an + * afio_exti_num argument. This isn't portable, so we use exti_num + * instead. This typedef (and the macros AFIO_EXTI_0, ..., + * AFIO_EXTI_15) exist to preserve backwards compatibility. + */ +typedef exti_num afio_exti_num; + +/** Deprecated. Use EXTI0 instead. */ +#define AFIO_EXTI_0 EXTI0 +/** Deprecated. Use EXTI1 instead. */ +#define AFIO_EXTI_1 EXTI1 +/** Deprecated. Use EXTI2 instead. */ +#define AFIO_EXTI_2 EXTI2 +/** Deprecated. Use EXTI3 instead. */ +#define AFIO_EXTI_3 EXTI3 +/** Deprecated. Use EXTI4 instead. */ +#define AFIO_EXTI_4 EXTI4 +/** Deprecated. Use EXTI5 instead. */ +#define AFIO_EXTI_5 EXTI5 +/** Deprecated. Use EXTI6 instead. */ +#define AFIO_EXTI_6 EXTI6 +/** Deprecated. Use EXTI7 instead. */ +#define AFIO_EXTI_7 EXTI7 +/** Deprecated. Use EXTI8 instead. */ +#define AFIO_EXTI_8 EXTI8 +/** Deprecated. Use EXTI9 instead. */ +#define AFIO_EXTI_9 EXTI9 +/** Deprecated. Use EXTI10 instead. */ +#define AFIO_EXTI_10 EXTI10 +/** Deprecated. Use EXTI11 instead. */ +#define AFIO_EXTI_11 EXTI11 +/** Deprecated. Use EXTI12 instead. */ +#define AFIO_EXTI_12 EXTI12 +/** Deprecated. Use EXTI13 instead. */ +#define AFIO_EXTI_13 EXTI13 +/** Deprecated. Use EXTI14 instead. */ +#define AFIO_EXTI_14 EXTI14 +/** Deprecated. Use EXTI15 instead. */ +#define AFIO_EXTI_15 EXTI15 + +/** + * @brief Deprecated. Use exti_select(exti, port) instead. + */ +static __always_inline void afio_exti_select(exti_num exti, exti_cfg port) { + exti_select(exti, port); +} + #ifdef __cplusplus } #endif diff --git a/libmaple/stm32f1/rules.mk b/libmaple/stm32f1/rules.mk index 0effea3..15f6fdb 100644 --- a/libmaple/stm32f1/rules.mk +++ b/libmaple/stm32f1/rules.mk @@ -17,6 +17,7 @@ sSRCS_$(d) += $(MCU_F1_LINE)/vector_table.S cSRCS_$(d) := adc.c cSRCS_$(d) += bkp.c cSRCS_$(d) += dma.c +cSRCS_$(d) += exti.c cSRCS_$(d) += fsmc.c cSRCS_$(d) += gpio.c cSRCS_$(d) += rcc.c diff --git a/libmaple/stm32f2/gpio.c b/libmaple/stm32f2/gpio.c index f2cd776..a26edaa 100644 --- a/libmaple/stm32f2/gpio.c +++ b/libmaple/stm32f2/gpio.c @@ -40,6 +40,7 @@ gpio_dev gpioa = { .regs = GPIOA_BASE, .clk_id = RCC_GPIOA, + .exti_port = EXTI_PA, }; /** GPIO port A device. */ gpio_dev* const GPIOA = &gpioa; @@ -47,6 +48,7 @@ gpio_dev* const GPIOA = &gpioa; gpio_dev gpiob = { .regs = GPIOB_BASE, .clk_id = RCC_GPIOB, + .exti_port = EXTI_PB, }; /** GPIO port B device. */ gpio_dev* const GPIOB = &gpiob; @@ -54,6 +56,7 @@ gpio_dev* const GPIOB = &gpiob; gpio_dev gpioc = { .regs = GPIOC_BASE, .clk_id = RCC_GPIOC, + .exti_port = EXTI_PC, }; /** GPIO port C device. */ gpio_dev* const GPIOC = &gpioc; @@ -61,6 +64,7 @@ gpio_dev* const GPIOC = &gpioc; gpio_dev gpiod = { .regs = GPIOD_BASE, .clk_id = RCC_GPIOD, + .exti_port = EXTI_PD, }; /** GPIO port D device. */ gpio_dev* const GPIOD = &gpiod; @@ -68,6 +72,7 @@ gpio_dev* const GPIOD = &gpiod; gpio_dev gpioe = { .regs = GPIOE_BASE, .clk_id = RCC_GPIOE, + .exti_port = EXTI_PE, }; /** GPIO port E device. */ gpio_dev* const GPIOE = &gpioe; @@ -75,6 +80,7 @@ gpio_dev* const GPIOE = &gpioe; gpio_dev gpiof = { .regs = GPIOF_BASE, .clk_id = RCC_GPIOF, + .exti_port = EXTI_PF, }; /** GPIO port F device. */ gpio_dev* const GPIOF = &gpiof; @@ -82,6 +88,7 @@ gpio_dev* const GPIOF = &gpiof; gpio_dev gpiog = { .regs = GPIOG_BASE, .clk_id = RCC_GPIOG, + .exti_port = EXTI_PG, }; /** GPIO port G device. */ gpio_dev* const GPIOG = &gpiog; @@ -89,6 +96,7 @@ gpio_dev* const GPIOG = &gpiog; gpio_dev gpioh = { .regs = GPIOH_BASE, .clk_id = RCC_GPIOH, + .exti_port = EXTI_PH, }; /** GPIO port G device. */ gpio_dev* const GPIOH = &gpioh; @@ -96,6 +104,7 @@ gpio_dev* const GPIOH = &gpioh; gpio_dev gpioi = { .regs = GPIOI_BASE, .clk_id = RCC_GPIOI, + .exti_port = EXTI_PI, }; /** GPIO port G device. */ gpio_dev* const GPIOI = &gpioi; diff --git a/libmaple/stm32f2/include/series/gpio.h b/libmaple/stm32f2/include/series/gpio.h index 9687247..1496e8e 100644 --- a/libmaple/stm32f2/include/series/gpio.h +++ b/libmaple/stm32f2/include/series/gpio.h @@ -1,7 +1,7 @@ /****************************************************************************** * The MIT License * - * Copyright (c) 2011 LeafLabs, LLC. + * Copyright (c) 2011, 2012 LeafLabs, LLC. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -36,8 +36,7 @@ extern "C"{ #endif -#include -#include +#include /* * GPIO register maps and devices @@ -76,30 +75,25 @@ typedef struct gpio_reg_map { /** GPIO port I register map base pointer */ #define GPIOI_BASE ((struct gpio_reg_map*)0x40022000) -/** GPIO device type */ -typedef struct gpio_dev { - gpio_reg_map *regs; - rcc_clk_id clk_id; -} gpio_dev; - -extern gpio_dev* const GPIOA; -extern gpio_dev gpioa; -extern gpio_dev* const GPIOB; -extern gpio_dev gpiob; -extern gpio_dev* const GPIOC; -extern gpio_dev gpioc; -extern gpio_dev* const GPIOD; -extern gpio_dev gpiod; -extern gpio_dev* const GPIOE; -extern gpio_dev gpioe; -extern gpio_dev* const GPIOF; -extern gpio_dev gpiof; -extern gpio_dev* const GPIOG; -extern gpio_dev gpiog; -extern gpio_dev* const GPIOH; -extern gpio_dev gpioh; -extern gpio_dev* const GPIOI; -extern gpio_dev gpioi; +struct gpio_dev; +extern struct gpio_dev* const GPIOA; +extern struct gpio_dev gpioa; +extern struct gpio_dev* const GPIOB; +extern struct gpio_dev gpiob; +extern struct gpio_dev* const GPIOC; +extern struct gpio_dev gpioc; +extern struct gpio_dev* const GPIOD; +extern struct gpio_dev gpiod; +extern struct gpio_dev* const GPIOE; +extern struct gpio_dev gpioe; +extern struct gpio_dev* const GPIOF; +extern struct gpio_dev gpiof; +extern struct gpio_dev* const GPIOG; +extern struct gpio_dev gpiog; +extern struct gpio_dev* const GPIOH; +extern struct gpio_dev gpioh; +extern struct gpio_dev* const GPIOI; +extern struct gpio_dev gpioi; /* * Register bit definitions @@ -215,7 +209,7 @@ typedef enum gpio_mode_flags { GPIO_MODEF_PUPD_PD = GPIO_PUPDR_PD << 3, /**< Pull-down */ } gpio_mode_flags; -void gpio_set_modef(gpio_dev *dev, +void gpio_set_modef(struct gpio_dev *dev, uint8 bit, gpio_pin_mode mode, unsigned flags); @@ -231,7 +225,7 @@ void gpio_set_modef(gpio_dev *dev, * @param pin Pin on the device whose mode to set, 0--15. * @param mode Mode to set the pin to. */ -static inline void gpio_set_mode(gpio_dev *dev, +static inline void gpio_set_mode(struct gpio_dev *dev, uint8 bit, gpio_pin_mode mode) { gpio_set_modef(dev, bit, mode, GPIO_MODEF_SPEED_HIGH); @@ -261,7 +255,7 @@ typedef enum gpio_af { GPIO_AF_EVENTOUT = 15, /**< EVENTOUT. */ } gpio_af; -void gpio_set_af(gpio_dev *dev, uint8 bit, gpio_af af); +void gpio_set_af(struct gpio_dev *dev, uint8 bit, gpio_af af); #ifdef __cplusplus } diff --git a/wirish/ext_interrupts.cpp b/wirish/ext_interrupts.cpp index 90c7e60..fab7343 100644 --- a/wirish/ext_interrupts.cpp +++ b/wirish/ext_interrupts.cpp @@ -53,7 +53,7 @@ void attachInterrupt(uint8 pin, voidFuncPtr handler, ExtIntTriggerMode mode) { exti_trigger_mode outMode = exti_out_mode(mode); - exti_attach_interrupt((afio_exti_num)(PIN_MAP[pin].gpio_bit), + exti_attach_interrupt((exti_num)(PIN_MAP[pin].gpio_bit), gpio_exti_port(PIN_MAP[pin].gpio_device), handler, outMode); @@ -68,7 +68,7 @@ void detachInterrupt(uint8 pin) { return; } - exti_detach_interrupt((afio_exti_num)(PIN_MAP[pin].gpio_bit)); + exti_detach_interrupt((exti_num)(PIN_MAP[pin].gpio_bit)); } static inline exti_trigger_mode exti_out_mode(ExtIntTriggerMode mode) { diff --git a/wirish/rules.mk b/wirish/rules.mk index 6d96cbe..a198c2d 100644 --- a/wirish/rules.mk +++ b/wirish/rules.mk @@ -22,6 +22,7 @@ sSRCS_$(d) := start.S cSRCS_$(d) := start_c.c cppSRCS_$(d) := boards.cpp cppSRCS_$(d) += cxxabi-compat.cpp +cppSRCS_$(d) += ext_interrupts.cpp cppSRCS_$(d) += HardwareSerial.cpp cppSRCS_$(d) += HardwareTimer.cpp cppSRCS_$(d) += Print.cpp @@ -39,7 +40,6 @@ cppSRCS_$(d) += $(MCU_SERIES)/wirish_digital.cpp cppSRCS_$(d) += $(WIRISH_BOARD_PATH)/board.cpp # TODO: revise these appropriately for F2 and put them back in: # HardwareSPI.cpp -# ext_interrupts.cpp sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%) cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%) -- cgit v1.2.3 From 23d81a1044ac3c3694d58d7659be8476ebe9ee15 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Mon, 4 Jun 2012 00:06:43 -0400 Subject: Bring back libmaple/dac.h. Minor variations on F2: DMA underrun interrupts, and a status register to hold the notification bits. Signed-off-by: Marti Bolivar --- libmaple/dac.c | 19 ++---- libmaple/include/libmaple/dac.h | 124 +++++++++++++++------------------- libmaple/rules.mk | 2 +- libmaple/stm32f1/include/series/dac.h | 71 +++++++++++++++++++ libmaple/stm32f2/include/series/dac.h | 94 ++++++++++++++++++++++++++ 5 files changed, 228 insertions(+), 82 deletions(-) create mode 100644 libmaple/stm32f1/include/series/dac.h create mode 100644 libmaple/stm32f2/include/series/dac.h (limited to 'libmaple/rules.mk') diff --git a/libmaple/dac.c b/libmaple/dac.c index 5a00590..d802d2b 100644 --- a/libmaple/dac.c +++ b/libmaple/dac.c @@ -2,7 +2,7 @@ * The MIT License * * Copyright (c) 2010 Bryan Newbold. - * Copyright (c) 2011 LeafLabs, LLC. + * Copyright (c) 2011, 2012 LeafLabs, LLC. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -30,21 +30,16 @@ * @brief Digital to analog converter support. */ +#include #include #include -#include - -#ifdef STM32_HIGH_DENSITY - -/** - * @brief DAC peripheral routines. - */ +#if STM32_HAVE_DAC dac_dev dac = { .regs = DAC_BASE, }; -/** DAC device. */ const dac_dev *DAC = &dac; +#endif /** * @brief Initialize the digital to analog converter @@ -98,11 +93,11 @@ void dac_enable_channel(const dac_dev *dev, uint8 channel) { */ switch (channel) { case 1: - gpio_set_mode(GPIOA, 4, GPIO_INPUT_ANALOG); + gpio_set_mode(GPIOA, 4, GPIO_MODE_ANALOG); dev->regs->CR |= DAC_CR_EN1; break; case 2: - gpio_set_mode(GPIOA, 5, GPIO_INPUT_ANALOG); + gpio_set_mode(GPIOA, 5, GPIO_MODE_ANALOG); dev->regs->CR |= DAC_CR_EN2; break; } @@ -123,5 +118,3 @@ void dac_disable_channel(const dac_dev *dev, uint8 channel) { break; } } - -#endif /* STM32_HIGH_DENSITY */ diff --git a/libmaple/include/libmaple/dac.h b/libmaple/include/libmaple/dac.h index 047f874..56bfdc4 100644 --- a/libmaple/include/libmaple/dac.h +++ b/libmaple/include/libmaple/dac.h @@ -1,7 +1,7 @@ /****************************************************************************** * The MIT License * - * Copyright (c) 2011 LeafLabs, LLC. + * Copyright (c) 2011, 2012 LeafLabs, LLC. * Copyright (c) 2010 Bryan Newbold. * * Permission is hereby granted, free of charge, to any person @@ -39,124 +39,112 @@ extern "C"{ #endif +#include #include #include +#include /* - * Register maps + * Register map base and device pointers. + * + * The DACs are the same on all supported targets, so it's not worth + * repeating these in the series headers. */ -/** DAC register map. */ -typedef struct dac_reg_map { - __io uint32 CR; /**< Control register */ - __io uint32 SWTRIGR; /**< Software trigger register */ - __io uint32 DHR12R1; /**< Channel 1 12-bit right-aligned data - holding register */ - __io uint32 DHR12L1; /**< Channel 1 12-bit left-aligned data - holding register */ - __io uint32 DHR8R1; /**< Channel 1 8-bit left-aligned data - holding register */ - __io uint32 DHR12R2; /**< Channel 2 12-bit right-aligned data - holding register */ - __io uint32 DHR12L2; /**< Channel 2 12-bit left-aligned data - holding register */ - __io uint32 DHR8R2; /**< Channel 2 8-bit left-aligned data - holding register */ - __io uint32 DHR12RD; /**< Dual DAC 12-bit right-aligned data - holding register */ - __io uint32 DHR12LD; /**< Dual DAC 12-bit left-aligned data - holding register */ - __io uint32 DHR8RD; /**< Dual DAC 8-bit right-aligned data holding - register */ - __io uint32 DOR1; /**< Channel 1 data output register */ - __io uint32 DOR2; /**< Channel 2 data output register */ -} dac_reg_map; - -/** DAC register map base address */ #define DAC_BASE ((struct dac_reg_map*)0x40007400) -/* - * Devices - */ - /** DAC device type. */ typedef struct dac_dev { dac_reg_map *regs; /**< Register map */ } dac_dev; +#if STM32_HAVE_DAC extern const dac_dev *DAC; +#endif /* * Register bit definitions */ /* Control register */ + /* Channel 1 control */ -#define DAC_CR_EN1 BIT(0) /* Enable */ -#define DAC_CR_BOFF1 BIT(1) /* Output buffer disable */ -#define DAC_CR_TEN1 BIT(2) /* Trigger enable */ -#define DAC_CR_TSEL1 (0x7 << 3) /* Trigger selection */ -#define DAC_CR_WAVE1 (0x3 << 6) /* Noise/triangle wave enable */ -#define DAC_CR_MAMP1 (0xF << 8) /* Mask/amplitude selector */ -#define DAC_CR_DMAEN1 BIT(12) /* DMA enable */ +#define DAC_CR_EN1 (1U << 0) /* Enable */ +#define DAC_CR_BOFF1 (1U << 1) /* Output buffer disable */ +#define DAC_CR_TEN1 (1U << 2) /* Trigger enable */ +#define DAC_CR_TSEL1 (0x7 << 3) /* Trigger selection */ +#define DAC_CR_WAVE1 (0x3 << 6) /* Noise/triangle wave */ +#define DAC_CR_MAMP1 (0xF << 8) /* Mask/amplitude selector */ +#define DAC_CR_DMAEN1 (1U << 12) /* DMA enable */ /* Channel 2 control */ -#define DAC_CR_EN2 BIT(16) /* Enable */ -#define DAC_CR_BOFF2 BIT(17) /* Output buffer disable */ -#define DAC_CR_TEN2 BIT(18) /* Trigger enable */ -#define DAC_CR_TSEL2 (0x7 << 19) /* Trigger selection */ -#define DAC_CR_WAVE2 (0x3 << 22) /* Noise/triangle wave generation*/ -#define DAC_CR_MAMP2 (0xF << 24) /* Mask/amplitude selector */ -#define DAC_CR_DMAEN2 BIT(28) /* DMA enable */ +#define DAC_CR_EN2 (1U << 16) /* Enable */ +#define DAC_CR_BOFF2 (1U << 17) /* Output buffer disable */ +#define DAC_CR_TEN2 (1U << 18) /* Trigger enable */ +#define DAC_CR_TSEL2 (0x7 << 19) /* Trigger selection */ +#define DAC_CR_WAVE2 (0x3 << 22) /* Noise/triangle wave */ +#define DAC_CR_MAMP2 (0xF << 24) /* Mask/amplitude selector */ +#define DAC_CR_DMAEN2 (1U << 28) /* DMA enable */ /* Software trigger register */ -#define DAC_SWTRIGR_SWTRIG1 BIT(0) /* Channel 1 software trigger */ -#define DAC_SWTRIGR_SWTRIG2 BIT(1) /* Channel 2 software trigger */ + +#define DAC_SWTRIGR_SWTRIG1 (1U << 0) /* Channel 1 software trigger */ +#define DAC_SWTRIGR_SWTRIG2 (1U << 1) /* Channel 2 software trigger */ /* Channel 1 12-bit right-aligned data holding register */ -#define DAC_DHR12R1_DACC1DHR 0x00000FFF + +#define DAC_DHR12R1_DACC1DHR 0x00000FFF /* Channel 1 12-bit left-aligned data holding register */ -#define DAC_DHR12L1_DACC1DHR 0x0000FFF0 + +#define DAC_DHR12L1_DACC1DHR 0x0000FFF0 /* Channel 1 8-bit left-aligned data holding register */ -#define DAC_DHR8R1_DACC1DHR 0x000000FF + +#define DAC_DHR8R1_DACC1DHR 0x000000FF /* Channel 2 12-bit right-aligned data holding register */ -#define DAC_DHR12R2_DACC2DHR 0x00000FFF + +#define DAC_DHR12R2_DACC2DHR 0x00000FFF /* Channel 2 12-bit left-aligned data holding register */ -#define DAC_DHR12L2_DACC2DHR 0x0000FFF0 + +#define DAC_DHR12L2_DACC2DHR 0x0000FFF0 /* Channel 2 8-bit left-aligned data holding register */ -#define DAC_DHR8R2_DACC2DHR 0x000000FF + +#define DAC_DHR8R2_DACC2DHR 0x000000FF /* Dual DAC 12-bit right-aligned data holding register */ -#define DAC_DHR12RD_DACC1DHR 0x00000FFF -#define DAC_DHR12RD_DACC2DHR 0x0FFF0000 + +#define DAC_DHR12RD_DACC1DHR 0x00000FFF +#define DAC_DHR12RD_DACC2DHR 0x0FFF0000 /* Dual DAC 12-bit left-aligned data holding register */ -#define DAC_DHR12LD_DACC1DHR 0x0000FFF0 -#define DAC_DHR12LD_DACC2DHR 0xFFF00000 + +#define DAC_DHR12LD_DACC1DHR 0x0000FFF0 +#define DAC_DHR12LD_DACC2DHR 0xFFF00000 /* Dual DAC 8-bit left-aligned data holding register */ -#define DAC_DHR8RD_DACC1DHR 0x000000FF -#define DAC_DHR8RD_DACC2DHR 0x0000FF00 + +#define DAC_DHR8RD_DACC1DHR 0x000000FF +#define DAC_DHR8RD_DACC2DHR 0x0000FF00 /* Channel 1 data output register */ -#define DAC_DOR1_DACC1DOR 0x00000FFF + +#define DAC_DOR1_DACC1DOR 0x00000FFF /* Channel 1 data output register */ -#define DAC_DOR2_DACC2DOR 0x00000FFF + +#define DAC_DOR2_DACC2DOR 0x00000FFF /* - * Convenience functions + * Routines */ -/* We take the dev argument in these convenience functions for - * future-proofing */ +/* We take the dev argument in these for future-proofing */ -#define DAC_CH1 0x1 -#define DAC_CH2 0x2 +#define DAC_CH1 0x1 +#define DAC_CH2 0x2 void dac_init(const dac_dev *dev, uint32 flags); void dac_write_channel(const dac_dev *dev, uint8 channel, uint16 val); diff --git a/libmaple/rules.mk b/libmaple/rules.mk index b39c318..08c4c02 100644 --- a/libmaple/rules.mk +++ b/libmaple/rules.mk @@ -12,6 +12,7 @@ CFLAGS_$(d) = $(LIBMAPLE_PRIVATE_INCLUDES) $(LIBMAPLE_INCLUDES) -Wall -Werror # Local rules and targets cSRCS_$(d) := adc.c +cSRCS_$(d) += dac.c # cSRCS_$(d) += dma.c cSRCS_$(d) += exti.c cSRCS_$(d) += flash.c @@ -28,7 +29,6 @@ cSRCS_$(d) += usart.c cSRCS_$(d) += usart_private.c cSRCS_$(d) += util.c # These still need to be brought back for F1: -# cSRCS_$(d) += dac.c # cSRCS_$(d) += i2c.c sSRCS_$(d) := exc.S diff --git a/libmaple/stm32f1/include/series/dac.h b/libmaple/stm32f1/include/series/dac.h new file mode 100644 index 0000000..c0d026b --- /dev/null +++ b/libmaple/stm32f1/include/series/dac.h @@ -0,0 +1,71 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/include/series/dac.h + * @brief STM32F1 DAC support + */ + +#ifndef _LIBMAPLE_STM32F1_DAC_H_ +#define _LIBMAPLE_STM32F1_DAC_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include + +/** STM32F1 DAC register map type. */ +typedef struct dac_reg_map { + __io uint32 CR; /**< Control register */ + __io uint32 SWTRIGR; /**< Software trigger register */ + __io uint32 DHR12R1; /**< Channel 1 12-bit right-aligned data + holding register */ + __io uint32 DHR12L1; /**< Channel 1 12-bit left-aligned data + holding register */ + __io uint32 DHR8R1; /**< Channel 1 8-bit left-aligned data + holding register */ + __io uint32 DHR12R2; /**< Channel 2 12-bit right-aligned data + holding register */ + __io uint32 DHR12L2; /**< Channel 2 12-bit left-aligned data + holding register */ + __io uint32 DHR8R2; /**< Channel 2 8-bit left-aligned data + holding register */ + __io uint32 DHR12RD; /**< Dual DAC 12-bit right-aligned data + holding register */ + __io uint32 DHR12LD; /**< Dual DAC 12-bit left-aligned data + holding register */ + __io uint32 DHR8RD; /**< Dual DAC 8-bit right-aligned data holding + register */ + __io uint32 DOR1; /**< Channel 1 data output register */ + __io uint32 DOR2; /**< Channel 2 data output register */ +} dac_reg_map; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libmaple/stm32f2/include/series/dac.h b/libmaple/stm32f2/include/series/dac.h new file mode 100644 index 0000000..0a578ca --- /dev/null +++ b/libmaple/stm32f2/include/series/dac.h @@ -0,0 +1,94 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f2/include/series/dac.h + * @brief STM32F2 DAC support + */ + +#ifndef _LIBMAPLE_STM32F2_DAC_H_ +#define _LIBMAPLE_STM32F2_DAC_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include + +/* + * Register map type + */ + +/** STM32F2 DAC register map type. */ +typedef struct dac_reg_map { + __io uint32 CR; /**< Control register */ + __io uint32 SWTRIGR; /**< Software trigger register */ + __io uint32 DHR12R1; /**< Channel 1 12-bit right-aligned data + holding register */ + __io uint32 DHR12L1; /**< Channel 1 12-bit left-aligned data + holding register */ + __io uint32 DHR8R1; /**< Channel 1 8-bit left-aligned data + holding register */ + __io uint32 DHR12R2; /**< Channel 2 12-bit right-aligned data + holding register */ + __io uint32 DHR12L2; /**< Channel 2 12-bit left-aligned data + holding register */ + __io uint32 DHR8R2; /**< Channel 2 8-bit left-aligned data + holding register */ + __io uint32 DHR12RD; /**< Dual DAC 12-bit right-aligned data + holding register */ + __io uint32 DHR12LD; /**< Dual DAC 12-bit left-aligned data + holding register */ + __io uint32 DHR8RD; /**< Dual DAC 8-bit right-aligned data holding + register */ + __io uint32 DOR1; /**< Channel 1 data output register */ + __io uint32 DOR2; /**< Channel 2 data output register */ + __io uint32 SR; /**< Status register */ +} dac_reg_map; + +/* + * Register bit definitions + */ + +/* Control register */ + +#define DAC_CR_DMAUDRIE1 (1U << 13) /* Channel 1 DMA underrun + * interrupt enable */ +#define DAC_CR_DMAUDRIE2 (1U << 29) /* Channel 2 DMA underrun + * interrupt enable */ + +/* Status register */ + +#define DAC_SR_DMAUDR1 (1U << 13) /* Channel 1 DMA underrun + * occurred */ +#define DAC_SR_DMAUDR2 (1U << 29) /* Channel 2 DMA underrun + * ocurred */ + +#ifdef __cplusplus +} +#endif + +#endif -- cgit v1.2.3 From 50cf479bc593bfcf68debac2812bcf7ce2862c52 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Thu, 7 Jun 2012 05:45:10 -0400 Subject: Move syscalls.c into Wirish. libmaple takes orders, it doesn't give them. Signed-off-by: Marti Bolivar --- libmaple/rules.mk | 1 - libmaple/syscalls.c | 169 ---------------------------------------------------- wirish/rules.mk | 1 + wirish/syscalls.c | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 170 insertions(+), 170 deletions(-) delete mode 100644 libmaple/syscalls.c create mode 100644 wirish/syscalls.c (limited to 'libmaple/rules.mk') diff --git a/libmaple/rules.mk b/libmaple/rules.mk index 08c4c02..649e4c8 100644 --- a/libmaple/rules.mk +++ b/libmaple/rules.mk @@ -22,7 +22,6 @@ cSRCS_$(d) += nvic.c cSRCS_$(d) += pwr.c cSRCS_$(d) += rcc.c # cSRCS_$(d) += spi.c -cSRCS_$(d) += syscalls.c cSRCS_$(d) += systick.c cSRCS_$(d) += timer.c cSRCS_$(d) += usart.c diff --git a/libmaple/syscalls.c b/libmaple/syscalls.c deleted file mode 100644 index 30a63bf..0000000 --- a/libmaple/syscalls.c +++ /dev/null @@ -1,169 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file libmaple/syscalls.c - * @brief newlib stubs - * - * Low level system routines used by Newlib for basic I/O and memory - * allocation. - */ - -#include - -#include -#include - -/* If CONFIG_HEAP_START (or CONFIG_HEAP_END) isn't defined, then - * assume _lm_heap_start (resp. _lm_heap_end) is appropriately set by - * the linker */ -#ifndef CONFIG_HEAP_START -extern char _lm_heap_start; -#define CONFIG_HEAP_START ((caddr_t)&_lm_heap_start) -#endif -#ifndef CONFIG_HEAP_END -extern char _lm_heap_end; -#define CONFIG_HEAP_END ((caddr_t)&_lm_heap_end) -#endif - -/* - * _sbrk -- Increment the program break. - * - * Get incr bytes more RAM (for use by the heap). malloc() and - * friends call this function behind the scenes. - */ -caddr_t _sbrk(int incr) { - static caddr_t pbreak = NULL; /* current program break */ - caddr_t ret; - - if (pbreak == NULL) { - pbreak = CONFIG_HEAP_START; - } - - if ((CONFIG_HEAP_END - pbreak < incr) || - (pbreak - CONFIG_HEAP_START < -incr)) { - errno = ENOMEM; - return (caddr_t)-1; - } - - ret = pbreak; - pbreak += incr; - return ret; -} - -int _open(const char *path, int flags, ...) { - return 1; -} - -int _close(int fd) { - return 0; -} - -int _fstat(int fd, struct stat *st) { - st->st_mode = S_IFCHR; - return 0; -} - -int _isatty(int fd) { - return 1; -} - -int isatty(int fd) { - return 1; -} - -int _lseek(int fd, off_t pos, int whence) { - return -1; -} - -unsigned char getch(void) { - return 0; -} - - -int _read(int fd, char *buf, size_t cnt) { - *buf = getch(); - - return 1; -} - -void putch(unsigned char c) { -} - -void cgets(char *s, int bufsize) { - char *p; - int c; - int i; - - for (i = 0; i < bufsize; i++) { - *(s+i) = 0; - } -// memset(s, 0, bufsize); - - p = s; - - for (p = s; p < s + bufsize-1;) { - c = getch(); - switch (c) { - case '\r' : - case '\n' : - putch('\r'); - putch('\n'); - *p = '\n'; - return; - - case '\b' : - if (p > s) { - *p-- = 0; - putch('\b'); - putch(' '); - putch('\b'); - } - break; - - default : - putch(c); - *p++ = c; - break; - } - } - return; -} - -int _write(int fd, const char *buf, size_t cnt) { - int i; - - for (i = 0; i < cnt; i++) - putch(buf[i]); - - return cnt; -} - -/* Override fgets() in newlib with a version that does line editing */ -char *fgets(char *s, int bufsize, void *f) { - cgets(s, bufsize); - return s; -} diff --git a/wirish/rules.mk b/wirish/rules.mk index a198c2d..acf4c46 100644 --- a/wirish/rules.mk +++ b/wirish/rules.mk @@ -20,6 +20,7 @@ CFLAGS_$(d) := $(LIBMAPLE_INCLUDES) $(WIRISH_INCLUDES) -I$(d) # Local rules and targets sSRCS_$(d) := start.S cSRCS_$(d) := start_c.c +cSRCS_$(d) += syscalls.c cppSRCS_$(d) := boards.cpp cppSRCS_$(d) += cxxabi-compat.cpp cppSRCS_$(d) += ext_interrupts.cpp diff --git a/wirish/syscalls.c b/wirish/syscalls.c new file mode 100644 index 0000000..d365e15 --- /dev/null +++ b/wirish/syscalls.c @@ -0,0 +1,169 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Perry Hung. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file wirish/syscalls.c + * @brief newlib stubs + * + * Low level system routines used by newlib for basic I/O and memory + * allocation. You can override most of these. + */ + +#include + +#include +#include + +/* If CONFIG_HEAP_START (or CONFIG_HEAP_END) isn't defined, then + * assume _lm_heap_start (resp. _lm_heap_end) is appropriately set by + * the linker */ +#ifndef CONFIG_HEAP_START +extern char _lm_heap_start; +#define CONFIG_HEAP_START ((caddr_t)&_lm_heap_start) +#endif +#ifndef CONFIG_HEAP_END +extern char _lm_heap_end; +#define CONFIG_HEAP_END ((caddr_t)&_lm_heap_end) +#endif + +/* + * _sbrk -- Increment the program break. + * + * Get incr bytes more RAM (for use by the heap). malloc() and + * friends call this function behind the scenes. + */ +caddr_t _sbrk(int incr) { + static caddr_t pbreak = NULL; /* current program break */ + caddr_t ret; + + if (pbreak == NULL) { + pbreak = CONFIG_HEAP_START; + } + + if ((CONFIG_HEAP_END - pbreak < incr) || + (pbreak - CONFIG_HEAP_START < -incr)) { + errno = ENOMEM; + return (caddr_t)-1; + } + + ret = pbreak; + pbreak += incr; + return ret; +} + +int _open(const char *path, int flags, ...) { + return 1; +} + +int _close(int fd) { + return 0; +} + +int _fstat(int fd, struct stat *st) { + st->st_mode = S_IFCHR; + return 0; +} + +int _isatty(int fd) { + return 1; +} + +int isatty(int fd) { + return 1; +} + +int _lseek(int fd, off_t pos, int whence) { + return -1; +} + +unsigned char getch(void) { + return 0; +} + + +int _read(int fd, char *buf, size_t cnt) { + *buf = getch(); + + return 1; +} + +void putch(unsigned char c) { +} + +void cgets(char *s, int bufsize) { + char *p; + int c; + int i; + + for (i = 0; i < bufsize; i++) { + *(s+i) = 0; + } +// memset(s, 0, bufsize); + + p = s; + + for (p = s; p < s + bufsize-1;) { + c = getch(); + switch (c) { + case '\r' : + case '\n' : + putch('\r'); + putch('\n'); + *p = '\n'; + return; + + case '\b' : + if (p > s) { + *p-- = 0; + putch('\b'); + putch(' '); + putch('\b'); + } + break; + + default : + putch(c); + *p++ = c; + break; + } + } + return; +} + +int _write(int fd, const char *buf, size_t cnt) { + int i; + + for (i = 0; i < cnt; i++) + putch(buf[i]); + + return cnt; +} + +/* Override fgets() in newlib with a version that does line editing */ +char *fgets(char *s, int bufsize, void *f) { + cgets(s, bufsize); + return s; +} -- cgit v1.2.3 From a52fe9205cbb8f8a2e458e300c2048d889b26b54 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Thu, 7 Jun 2012 21:41:50 -0400 Subject: Bring back . Add a spi_private.h with a SPI_DEV(), for convenience. Use it in the F1 and F2 implementations. We could probably unify these with an STM32_HAVE_SPI(n) macro, but we'll leave that for the future. Most everything from F1 is portable; F2 has some additional bit definitions and a spi_get_af() routine, but that's about it. Signed-off-by: Marti Bolivar --- libmaple/include/libmaple/spi.h | 2 +- libmaple/rules.mk | 2 +- libmaple/spi_private.h | 37 +++++++++++++++ libmaple/stm32f1/include/series/spi.h | 3 -- libmaple/stm32f1/spi.c | 25 ++-------- libmaple/stm32f2/include/series/spi.h | 88 +++++++++++++++++++++++++++++++++++ libmaple/stm32f2/rules.mk | 1 + libmaple/stm32f2/spi.c | 88 +++++++++++++++++++++++++++++++++++ 8 files changed, 221 insertions(+), 25 deletions(-) create mode 100644 libmaple/spi_private.h create mode 100644 libmaple/stm32f2/include/series/spi.h create mode 100644 libmaple/stm32f2/spi.c (limited to 'libmaple/rules.mk') diff --git a/libmaple/include/libmaple/spi.h b/libmaple/include/libmaple/spi.h index 90e2036..45dc5a2 100644 --- a/libmaple/include/libmaple/spi.h +++ b/libmaple/include/libmaple/spi.h @@ -307,7 +307,7 @@ uint32 spi_tx(spi_dev *dev, const void *buf, uint32 len); * @brief Call a function on each SPI port * @param fn Function to call. */ -void spi_foreach(void (*fn)(spi_dev*)); +extern void spi_foreach(void (*fn)(spi_dev*)); void spi_peripheral_enable(spi_dev *dev); void spi_peripheral_disable(spi_dev *dev); diff --git a/libmaple/rules.mk b/libmaple/rules.mk index 649e4c8..be93d2e 100644 --- a/libmaple/rules.mk +++ b/libmaple/rules.mk @@ -21,7 +21,7 @@ cSRCS_$(d) += iwdg.c cSRCS_$(d) += nvic.c cSRCS_$(d) += pwr.c cSRCS_$(d) += rcc.c -# cSRCS_$(d) += spi.c +cSRCS_$(d) += spi.c cSRCS_$(d) += systick.c cSRCS_$(d) += timer.c cSRCS_$(d) += usart.c diff --git a/libmaple/spi_private.h b/libmaple/spi_private.h new file mode 100644 index 0000000..f0e0bd1 --- /dev/null +++ b/libmaple/spi_private.h @@ -0,0 +1,37 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +#ifndef _LIBMAPLE_SPI_PRIVATE_H_ +#define _LIBMAPLE_SPI_PRIVATE_H_ + +#define SPI_DEV(num) \ + { \ + .regs = SPI##num##_BASE, \ + .clk_id = RCC_SPI##num, \ + .irq_num = NVIC_SPI##num, \ + } + +#endif diff --git a/libmaple/stm32f1/include/series/spi.h b/libmaple/stm32f1/include/series/spi.h index 8cc4c4d..d288a0c 100644 --- a/libmaple/stm32f1/include/series/spi.h +++ b/libmaple/stm32f1/include/series/spi.h @@ -46,11 +46,8 @@ extern "C" { struct spi_reg_map; -/** SPI1 register map base pointer */ #define SPI1_BASE ((struct spi_reg_map*)0x40013000) -/** SPI2 register map base pointer */ #define SPI2_BASE ((struct spi_reg_map*)0x40003800) -/** SPI3 register map base pointer */ #define SPI3_BASE ((struct spi_reg_map*)0x40003C00) /* diff --git a/libmaple/stm32f1/spi.c b/libmaple/stm32f1/spi.c index 72f2ef4..1c78cc3 100644 --- a/libmaple/stm32f1/spi.c +++ b/libmaple/stm32f1/spi.c @@ -33,35 +33,20 @@ #include #include +#include "spi_private.h" /* * Devices */ -static spi_dev spi1 = { - .regs = SPI1_BASE, - .clk_id = RCC_SPI1, - .irq_num = NVIC_SPI1, -}; -static spi_dev spi2 = { - .regs = SPI2_BASE, - .clk_id = RCC_SPI2, - .irq_num = NVIC_SPI2, -}; -#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) -static spi_dev spi3 = { - .regs = SPI3_BASE, - .clk_id = RCC_SPI3, - .irq_num = NVIC_SPI3, -}; -#endif +static spi_dev spi1 = SPI_DEV(1); +static spi_dev spi2 = SPI_DEV(2); -/** SPI device 1 */ spi_dev *SPI1 = &spi1; -/** SPI device 2 */ spi_dev *SPI2 = &spi2; + #if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) -/** SPI device 3 */ +static spi_dev spi3 = SPI_DEV(3); spi_dev *SPI3 = &spi3; #endif diff --git a/libmaple/stm32f2/include/series/spi.h b/libmaple/stm32f2/include/series/spi.h new file mode 100644 index 0000000..7b9f94a --- /dev/null +++ b/libmaple/stm32f2/include/series/spi.h @@ -0,0 +1,88 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f2/include/series/spi.h + * @author Marti Bolivar + * @brief STM32F2 SPI/I2S series header. + */ + +#ifndef _LIBMAPLE_STM32F2_SPI_H_ +#define _LIBMAPLE_STM32F2_SPI_H_ + +#include /* for gpio_af */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Register map base pointers + */ + +struct spi_reg_map; + +#define SPI1_BASE ((struct spi_reg_map*)0x40013000) +#define SPI2_BASE ((struct spi_reg_map*)0x40003800) +#define SPI3_BASE ((struct spi_reg_map*)0x40003C00) + +/* + * Register bit definitions + */ + +/* Control register 2 */ + +#define SPI_CR2_FRF_BIT 4 + +#define SPI_CR2_FRF (1U << SPI_CR2_FRF_BIT) + +/* Status register */ + +#define SPI_SR_TIFRFE_BIT 8 + +#define SPI_SR_TIFRFE (1U << SPI_SR_TIFRFE_BIT) + +/* + * Device pointers + */ + +struct spi_dev; + +extern struct spi_dev *SPI1; +extern struct spi_dev *SPI2; +extern struct spi_dev *SPI3; + +/* + * Routines + */ + +gpio_af spi_get_af(struct spi_dev *dev); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libmaple/stm32f2/rules.mk b/libmaple/stm32f2/rules.mk index fd6b933..759f905 100644 --- a/libmaple/stm32f2/rules.mk +++ b/libmaple/stm32f2/rules.mk @@ -16,6 +16,7 @@ cSRCS_$(d) += exti.c cSRCS_$(d) += fsmc.c cSRCS_$(d) += gpio.c cSRCS_$(d) += rcc.c +cSRCS_$(d) += spi.c cSRCS_$(d) += syscfg.c cSRCS_$(d) += timer.c cSRCS_$(d) += usart.c diff --git a/libmaple/stm32f2/spi.c b/libmaple/stm32f2/spi.c new file mode 100644 index 0000000..cfd9995 --- /dev/null +++ b/libmaple/stm32f2/spi.c @@ -0,0 +1,88 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f2/spi.c + * @author Marti Bolivar + * @brief STM32F2 SPI/I2S. + */ + +#include +#include "spi_private.h" + +/* + * Devices + */ + +static spi_dev spi1 = SPI_DEV(1); +static spi_dev spi2 = SPI_DEV(2); +static spi_dev spi3 = SPI_DEV(3); + +spi_dev *SPI1 = &spi1; +spi_dev *SPI2 = &spi2; +spi_dev *SPI3 = &spi3; + +/* + * Routines + */ + +void spi_config_gpios(spi_dev *dev, + uint8 as_master, + gpio_dev *nss_dev, + uint8 nss_bit, + gpio_dev *comm_dev, + uint8 sck_bit, + uint8 miso_bit, + uint8 mosi_bit) { + gpio_af dev_af = spi_get_af(dev); + gpio_set_mode(nss_dev, nss_bit, GPIO_MODE_AF); + gpio_set_mode(comm_dev, sck_bit, GPIO_MODE_AF); + gpio_set_mode(comm_dev, miso_bit, GPIO_MODE_AF); + gpio_set_mode(comm_dev, mosi_bit, GPIO_MODE_AF); + gpio_set_af(nss_dev, nss_bit, dev_af); + gpio_set_af(comm_dev, sck_bit, dev_af); + gpio_set_af(comm_dev, miso_bit, dev_af); + gpio_set_af(comm_dev, mosi_bit, dev_af); +} + +void spi_foreach(void (*fn)(spi_dev*)) { + fn(SPI1); + fn(SPI2); + fn(SPI3); +} + +gpio_af spi_get_af(spi_dev *dev) { + switch (dev->clk_id) { + case RCC_SPI1: /* Fall through */ + case RCC_SPI2: + return GPIO_AF_SPI_1_2; + case RCC_SPI3: + return GPIO_AF_SPI3; + default: + ASSERT(0); /* Can't happen */ + return (gpio_af)-1; + } +} -- cgit v1.2.3 From ba1d9f5eb6539003515b958b4935a06868e27733 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Tue, 12 Jun 2012 16:01:12 -0400 Subject: Build libmaple/dma.c on STM32F1. F2 doesn't work yet. Signed-off-by: Marti Bolivar --- libmaple/rules.mk | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'libmaple/rules.mk') diff --git a/libmaple/rules.mk b/libmaple/rules.mk index be93d2e..0c29ec7 100644 --- a/libmaple/rules.mk +++ b/libmaple/rules.mk @@ -13,7 +13,9 @@ CFLAGS_$(d) = $(LIBMAPLE_PRIVATE_INCLUDES) $(LIBMAPLE_INCLUDES) -Wall -Werror # Local rules and targets cSRCS_$(d) := adc.c cSRCS_$(d) += dac.c -# cSRCS_$(d) += dma.c +ifeq ($(MCU_SERIES),stm32f1) # FIXME add F2 support +cSRCS_$(d) += dma.c +endif cSRCS_$(d) += exti.c cSRCS_$(d) += flash.c cSRCS_$(d) += gpio.c -- cgit v1.2.3 From e72e411c1f0e4f96326351264301c6e475206e30 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Thu, 14 Jun 2012 18:31:40 -0400 Subject: Implement DMA tube API on STM32F2. Signed-off-by: Marti Bolivar --- libmaple/rules.mk | 2 - libmaple/stm32f2/dma.c | 504 +++++++++++++++++++++ libmaple/stm32f2/include/series/dma.h | 810 ++++++++++++++++++++++++++++++++++ libmaple/stm32f2/rules.mk | 1 + 4 files changed, 1315 insertions(+), 2 deletions(-) create mode 100644 libmaple/stm32f2/dma.c create mode 100644 libmaple/stm32f2/include/series/dma.h (limited to 'libmaple/rules.mk') diff --git a/libmaple/rules.mk b/libmaple/rules.mk index 0c29ec7..41f5601 100644 --- a/libmaple/rules.mk +++ b/libmaple/rules.mk @@ -13,9 +13,7 @@ CFLAGS_$(d) = $(LIBMAPLE_PRIVATE_INCLUDES) $(LIBMAPLE_INCLUDES) -Wall -Werror # Local rules and targets cSRCS_$(d) := adc.c cSRCS_$(d) += dac.c -ifeq ($(MCU_SERIES),stm32f1) # FIXME add F2 support cSRCS_$(d) += dma.c -endif cSRCS_$(d) += exti.c cSRCS_$(d) += flash.c cSRCS_$(d) += gpio.c diff --git a/libmaple/stm32f2/dma.c b/libmaple/stm32f2/dma.c new file mode 100644 index 0000000..26e87b9 --- /dev/null +++ b/libmaple/stm32f2/dma.c @@ -0,0 +1,504 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f2/dma.c + * @author Marti Bolivar + * @brief STM32F2 DMA support. + */ + +#include +#include +#include + +/* Hack to ensure inlining in dma_irq_handler() */ +#define DMA_GET_HANDLER(dev, tube) (dev->handlers[tube].handler) +#include "dma_private.h" + +/* + * Devices + */ + +static dma_dev dma1 = { + .regs = DMA1_BASE, + .clk_id = RCC_DMA1, + .handlers = {{ .handler = NULL, .irq_line = NVIC_DMA1_STREAM0 }, + { .handler = NULL, .irq_line = NVIC_DMA1_STREAM1 }, + { .handler = NULL, .irq_line = NVIC_DMA1_STREAM2 }, + { .handler = NULL, .irq_line = NVIC_DMA1_STREAM3 }, + { .handler = NULL, .irq_line = NVIC_DMA1_STREAM4 }, + { .handler = NULL, .irq_line = NVIC_DMA1_STREAM5 }, + { .handler = NULL, .irq_line = NVIC_DMA1_STREAM6 }, + { .handler = NULL, .irq_line = NVIC_DMA1_STREAM7 }}, +}; +dma_dev *DMA1 = &dma1; + +static dma_dev dma2 = { + .regs = DMA2_BASE, + .clk_id = RCC_DMA2, + .handlers = {{ .handler = NULL, .irq_line = NVIC_DMA2_STREAM0 }, + { .handler = NULL, .irq_line = NVIC_DMA2_STREAM1 }, + { .handler = NULL, .irq_line = NVIC_DMA2_STREAM2 }, + { .handler = NULL, .irq_line = NVIC_DMA2_STREAM3 }, + { .handler = NULL, .irq_line = NVIC_DMA2_STREAM4 }, + { .handler = NULL, .irq_line = NVIC_DMA2_STREAM5 }, + { .handler = NULL, .irq_line = NVIC_DMA2_STREAM6 }, + { .handler = NULL, .irq_line = NVIC_DMA2_STREAM7 }}, +}; +dma_dev *DMA2 = &dma2; + +/* + * Helpers for dealing with dma_request_src's bit encoding (see the + * comments in the dma_request_src definition). + */ + +/* rcc_clk_id of dma_dev which supports src. */ +static __always_inline rcc_clk_id src_clk_id(dma_request_src src) { + return (rcc_clk_id)(((uint32)src >> 3) & 0x3F); +} + +/* Bit vector of streams supporting src (e.g., bit 0 set => DMA_S0 support). */ +static __always_inline uint32 src_stream_mask(dma_request_src src) { + return ((uint32)src >> 10) & 0xFF; +} + +/* Channel corresponding to src. */ +static __always_inline dma_channel src_channel(dma_request_src src) { + return (dma_channel)(src & 0x7); +} + +/* + * Routines + */ + +/* For convenience */ +#define ASSERT_NOT_ENABLED(dev, tube) ASSERT(!dma_is_enabled(dev, tube)) + +/* Helpers for dma_tube_cfg() */ +static int preconfig_check(dma_dev *dev, dma_tube tube, dma_tube_config *cfg); +static int postconfig_check(dma_tube_reg_map *dummy, dma_tube_config *cfg); +static int config_fifo(dma_tube_reg_map *dummy, dma_tube_config *cfg); +static int config_src_dst(dma_tube_reg_map *dummy, dma_tube_config *cfg); +static void copy_regs(dma_tube_reg_map *src, dma_tube_reg_map *dst); + +int dma_tube_cfg(dma_dev *dev, dma_tube tube, dma_tube_config *cfg) { + dma_tube_reg_map dummy_regs; + dma_tube_reg_map *tregs = dma_tube_regs(dev, tube); + int ret; + + /* Initial error checking. */ + ret = preconfig_check(dev, tube, cfg); + if (ret < 0) { + return ret; + } + + /* Disable `tube' as per RM0033. */ + dma_disable(dev, tube); + dma_clear_isr_bits(dev, tube); + + /* Don't write to tregs until we've decided `cfg' is really OK, + * so as not to make a half-formed mess if we have to error out. */ + copy_regs(tregs, &dummy_regs); + + /* Try to reconfigure `tube', bailing on error. */ + ret = config_fifo(&dummy_regs, cfg); + if (ret < 0) { + return ret; + } + ret = config_src_dst(&dummy_regs, cfg); + if (ret < 0) { + return ret; + } + dummy_regs.SNDTR = cfg->tube_nr_xfers; + ret = postconfig_check(&dummy_regs, cfg); + if (ret < 0) { + return ret; + } + + /* Ok, we're good. Commit to the new configuration. */ + copy_regs(&dummy_regs, tregs); + return ret; +} + +void dma_set_priority(dma_dev *dev, dma_stream stream, dma_priority priority) { + dma_tube_reg_map *tregs = dma_tube_regs(dev, stream); + uint32 scr; + ASSERT_NOT_ENABLED(dev, stream); + scr = tregs->SCR; + scr &= ~DMA_SCR_PL; + scr |= (priority << 16); + tregs->SCR = scr; +} + +void dma_set_num_transfers(dma_dev *dev, dma_tube tube, uint16 num_transfers) { + dma_tube_reg_map *tregs = dma_tube_regs(dev, tube); + ASSERT_NOT_ENABLED(dev, tube); + tregs->SNDTR = num_transfers; +} + +/** + * @brief Set memory 0 or memory 1 address. + * + * This is a general function for setting one of the two memory + * addresses available on the double-buffered STM32F2 DMA controllers. + * + * @param dev DMA device + * @param tube Tube on dev. + * @param n If 0, set memory 0 address. If 1, set memory 1 address. + * @param address Address to set + */ +void dma_set_mem_n_addr(dma_dev *dev, dma_tube tube, int n, + __io void *address) { + dma_tube_reg_map *tregs = dma_tube_regs(dev, tube); + uint32 addr = (uint32)address; + + ASSERT_NOT_ENABLED(dev, tube); + if (n) { + tregs->SM1AR = addr; + } else { + tregs->SM0AR = addr; + } +} + +void dma_set_per_addr(dma_dev *dev, dma_tube tube, __io void *address) { + dma_tube_reg_map *tregs = dma_tube_regs(dev, tube); + ASSERT_NOT_ENABLED(dev, tube); + tregs->SPAR = (uint32)address; +} + +/** + * @brief Enable a stream's FIFO. + * + * You may only call this function when the stream is disabled. + * + * @param dev DMA device + * @param tube Stream whose FIFO to enable. + */ +void dma_enable_fifo(dma_dev *dev, dma_tube tube) { + ASSERT_NOT_ENABLED(dev, tube); + bb_peri_set_bit(&(dma_tube_regs(dev, tube)->SFCR), DMA_SFCR_DMDIS_BIT, 1); +} + +/** + * @brief Disable a stream's FIFO. + * + * You may only call this function when the stream is disabled. + * + * @param dev DMA device + * @param tube Stream whose FIFO to disable. + */ +void dma_disable_fifo(dma_dev *dev, dma_tube tube) { + ASSERT_NOT_ENABLED(dev, tube); + bb_peri_set_bit(&(dma_tube_regs(dev, tube)->SFCR), DMA_SFCR_DMDIS_BIT, 0); +} + +void dma_attach_interrupt(dma_dev *dev, dma_tube tube, + void (*handler)(void)) { + dev->handlers[tube].handler = handler; + nvic_irq_enable(dev->handlers[tube].irq_line); +} + +void dma_detach_interrupt(dma_dev *dev, dma_tube tube) { + nvic_irq_disable(dev->handlers[tube].irq_line); + dev->handlers[tube].handler = NULL; +} + +void dma_enable(dma_dev *dev, dma_tube tube) { + dma_tube_reg_map *tregs = dma_tube_regs(dev, tube); + bb_peri_set_bit(&tregs->SCR, DMA_SCR_EN_BIT, 1); +} + +void dma_disable(dma_dev *dev, dma_tube tube) { + dma_tube_reg_map *tregs = dma_tube_regs(dev, tube); + bb_peri_set_bit(&tregs->SCR, DMA_SCR_EN_BIT, 0); + /* The stream might not get disabled immediately, so wait. */ + while (tregs->SCR & DMA_SCR_EN) + ; +} + +dma_irq_cause dma_get_irq_cause(dma_dev *dev, dma_tube tube) { + /* TODO: does it still make sense to have this function? We should + * probably just be returning the ISR bits, with some defines to + * pull the flags out. The lack of masked status bits is an + * annoyance that would require documentation to solve, though. */ + uint8 status_bits = dma_get_isr_bits(dev, tube); + dma_clear_isr_bits(dev, tube); + ASSERT(status_bits); /* Or something's very wrong */ + /* Don't change the order of these if statements. */ + if (status_bits & 0x0) { + return DMA_TRANSFER_FIFO_ERROR; + } else if (status_bits & 0x4) { + return DMA_TRANSFER_DME_ERROR; + } else if (status_bits & 0x8) { + return DMA_TRANSFER_ERROR; + } else if (status_bits & 0x20) { + return DMA_TRANSFER_COMPLETE; + } else if (status_bits & 0x10) { + return DMA_TRANSFER_HALF_COMPLETE; + } + + /* Something's wrong; one of those bits should have been set. Fail + * an assert, and mimic the error behavior in case of a high debug + * level. */ + ASSERT(0); + dma_disable(dev, tube); + return DMA_TRANSFER_ERROR; +} + +/* + * IRQ handlers + */ + +void __irq_dma1_stream0(void) { + dma_irq_handler(DMA1, DMA_S0); +} + +void __irq_dma1_stream1(void) { + dma_irq_handler(DMA1, DMA_S1); +} + +void __irq_dma1_stream2(void) { + dma_irq_handler(DMA1, DMA_S2); +} + +void __irq_dma1_stream3(void) { + dma_irq_handler(DMA1, DMA_S3); +} + +void __irq_dma1_stream4(void) { + dma_irq_handler(DMA1, DMA_S4); +} + +void __irq_dma1_stream5(void) { + dma_irq_handler(DMA1, DMA_S5); +} + +void __irq_dma1_stream6(void) { + dma_irq_handler(DMA1, DMA_S6); +} + +void __irq_dma1_stream7(void) { + dma_irq_handler(DMA1, DMA_S7); +} + +void __irq_dma2_stream0(void) { + dma_irq_handler(DMA2, DMA_S0); +} + +void __irq_dma2_stream1(void) { + dma_irq_handler(DMA2, DMA_S1); +} + +void __irq_dma2_stream2(void) { + dma_irq_handler(DMA2, DMA_S2); +} + +void __irq_dma2_stream3(void) { + dma_irq_handler(DMA2, DMA_S3); +} + +void __irq_dma2_stream4(void) { + dma_irq_handler(DMA2, DMA_S4); +} + +void __irq_dma2_stream5(void) { + dma_irq_handler(DMA2, DMA_S5); +} + +void __irq_dma2_stream6(void) { + dma_irq_handler(DMA2, DMA_S6); +} + +void __irq_dma2_stream7(void) { + dma_irq_handler(DMA2, DMA_S7); +} + +/* + * Auxiliary routines for dma_tube_cfg() + */ + +/* Is addr acceptable for use as DMA src/dst? */ +static int cfg_mem_ok(__io void *addr) { + enum dma_atype atype = _dma_addr_type(addr); + return atype == DMA_ATYPE_MEM || atype == DMA_ATYPE_PER; +} + +/* Is src -> dst a reasonable combination of [MEM,PER] -> [MEM,PER]? */ +static int cfg_dir_ok(dma_dev *dev, __io void *src, __io void *dst) { + switch (_dma_addr_type(dst)) { + case DMA_ATYPE_MEM: + /* Only DMA2 can do memory-to-memory */ + return ((_dma_addr_type(src) == DMA_ATYPE_PER) || + (dev->clk_id == RCC_DMA2)); + case DMA_ATYPE_PER: + /* Peripheral-to-peripheral is illegal */ + return _dma_addr_type(src) == DMA_ATYPE_PER; + default: /* Can't happen */ + ASSERT(0); + return 0; + } +} + +/* Initial sanity check for dma_tube_cfg() */ +static int preconfig_check(dma_dev *dev, dma_tube tube, + dma_tube_config *cfg) { + if (!(src_stream_mask(cfg->tube_req_src) & (1U << tube))) { + /* ->tube_req_src not supported by stream */ + return -DMA_TUBE_CFG_EREQ; + } + if (cfg->tube_nr_xfers > 65535) { + /* That's too many. */ + return -DMA_TUBE_CFG_ENDATA; + } + if (src_clk_id(cfg->tube_req_src) != dev->clk_id) { + /* ->tube_req_src not supported by dev */ + return -DMA_TUBE_CFG_EDEV; + } + if (!cfg_mem_ok(cfg->tube_src)) { + return -DMA_TUBE_CFG_ESRC; + } + if (!cfg_mem_ok(cfg->tube_dst)) { + return -DMA_TUBE_CFG_EDST; + } + if (!cfg_dir_ok(dev, cfg->tube_src, cfg->tube_dst)) { + return -DMA_TUBE_CFG_EDIR; + } + return DMA_TUBE_CFG_SUCCESS; +} + +static int config_fifo(dma_tube_reg_map *dummy, dma_tube_config *cfg) { + /* TODO: FIFO configuration based on cfg->target_data */ + uint32 sfcr = dummy->SFCR; + sfcr &= ~DMA_SFCR_FEIE; + sfcr |= (cfg->tube_flags & DMA_CFG_FIFO_ERR_IE) ? DMA_SFCR_FEIE : 0; + dummy->SFCR = sfcr; + return DMA_TUBE_CFG_SUCCESS; +} + +/* Helper for configuring (DMA_SxCR) */ +#define BITS_WE_CARE_ABOUT \ + (DMA_SCR_CHSEL | DMA_SCR_MBURST | DMA_SCR_PBURST | DMA_SCR_PINCOS | \ + DMA_SCR_MINC | DMA_SCR_PINC | DMA_SCR_CIRC | DMA_SCR_DIR | \ + DMA_SCR_PFCTRL | DMA_SCR_TCIE | DMA_SCR_HTIE | DMA_SCR_TEIE | \ + DMA_SCR_DMEIE) +static inline void config_scr(dma_tube_reg_map *dummy, dma_tube_config *cfg, + unsigned src_shift, uint32 src_inc, + unsigned dst_shift, uint32 dst_inc, + uint32 dir) { + /* These would go here if we supported them: MBURST, PBURST, + * PINCOS, PFCTRL. We explicitly choose low priority, and double + * buffering belongs elsewhere, I think. [mbolivar] */ + uint32 flags = cfg->tube_flags & BITS_WE_CARE_ABOUT; + uint32 scr = dummy->SCR; + scr &= ~(BITS_WE_CARE_ABOUT | DMA_SCR_PL); + scr |= (/* CHSEL */ + (src_channel(cfg->tube_req_src) << 25) | + /* MSIZE/PSIZE */ + (cfg->tube_src_size << src_shift) | + (cfg->tube_dst_size << dst_shift) | + /* MINC/PINC */ + ((cfg->tube_flags & DMA_CFG_SRC_INC) ? src_inc : 0) | + ((cfg->tube_flags & DMA_CFG_DST_INC) ? dst_inc : 0) | + /* DIR */ + dir | + /* Other flags carried by cfg->tube_flags */ + flags); + dummy->SCR = scr; +} +#undef BITS_WE_CARE_ABOUT + +/* Helper for when cfg->tube_dst is memory */ +static int config_to_mem(dma_tube_reg_map *dummy, dma_tube_config *cfg) { + uint32 dir = (_dma_addr_type(cfg->tube_src) == DMA_ATYPE_MEM ? + DMA_SCR_DIR_MEM_TO_MEM : DMA_SCR_DIR_PER_TO_MEM); + + if ((dir == DMA_SCR_DIR_MEM_TO_MEM) && (cfg->tube_flags & DMA_CFG_CIRC)) { + return -DMA_TUBE_CFG_ECFG; /* Can't do DMA_CFG_CIRC and mem->mem. */ + } + + config_scr(dummy, cfg, 11, DMA_SCR_PINC, 13, DMA_SCR_MINC, dir); + dummy->SPAR = (uint32)cfg->tube_src; + dummy->SM0AR = (uint32)cfg->tube_dst; + return DMA_TUBE_CFG_SUCCESS; +} + +/* Helper for when cfg->tube_src is peripheral */ +static int config_to_per(dma_tube_reg_map *dummy, dma_tube_config *cfg) { + config_scr(dummy, cfg, 13, DMA_SCR_MINC, 11, DMA_SCR_PINC, + DMA_SCR_DIR_MEM_TO_PER); + dummy->SM0AR = (uint32)cfg->tube_src; + dummy->SPAR = (uint32)cfg->tube_dst; + return DMA_TUBE_CFG_SUCCESS; +} + +/* Configures SCR, SPAR, SM0AR, and checks that the result is OK. */ +static int config_src_dst(dma_tube_reg_map *dummy, dma_tube_config *cfg) { + switch (_dma_addr_type(cfg->tube_dst)) { + case DMA_ATYPE_MEM: + return config_to_mem(dummy, cfg); + case DMA_ATYPE_PER: + return config_to_per(dummy, cfg); + case DMA_ATYPE_OTHER: + default: /* shut up, GCC */ + /* Can't happen */ + ASSERT(0); + return -DMA_TUBE_CFG_ECFG; + } +} + +/* Final checks we can only perform when fully configured */ +static int postconfig_check(dma_tube_reg_map *dummy, dma_tube_config *cfg) { + /* TODO add dma_get_[mem,per]_size() and use them here */ + /* msize and psize are in bytes here: */ + uint32 scr = dummy->SCR; + uint32 msize = 1U << ((scr >> 13) & 0x3); + uint32 psize = 1U << ((scr >> 11) & 0x3); + + /* Ensure NDT will work with PSIZE/MSIZE. + * + * RM0033 specifies that PSIZE, MSIZE, and NDT must be such that + * the last transfer completes; i.e. that if PSIZE < MSIZE, then + * NDT is a multiple of MSIZE/PSIZE. See e.g. Table 27. */ + if ((psize < msize) && (cfg->tube_nr_xfers % (msize / psize))) { + return -DMA_TUBE_CFG_ENDATA; + } + + /* Direct mode is only possible if MSIZE == PSIZE. */ + if ((msize != psize) && !(dummy->SFCR & DMA_SFCR_DMDIS)) { + return -DMA_TUBE_CFG_ESIZE; + } + + return DMA_TUBE_CFG_SUCCESS; +} + +/* Convenience for dealing with dummy registers */ +static void copy_regs(dma_tube_reg_map *src, dma_tube_reg_map *dst) { + dst->SCR = src->SCR; + dst->SNDTR = src->SNDTR; + dst->SPAR = src->SPAR; + dst->SM0AR = src->SM0AR; + dst->SFCR = src->SFCR; +} diff --git a/libmaple/stm32f2/include/series/dma.h b/libmaple/stm32f2/include/series/dma.h new file mode 100644 index 0000000..43bd1a2 --- /dev/null +++ b/libmaple/stm32f2/include/series/dma.h @@ -0,0 +1,810 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f2/include/series/dma.h + * @author Marti Bolivar + * @brief STM32F2 DMA series header + */ + +#ifndef _LIBMAPLE_STM32F2_DMA_H_ +#define _LIBMAPLE_STM32F2_DMA_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include +#include + +/* + * Register map and base pointers + */ + +/** + * @brief STM32F2 DMA register map type. + */ +typedef struct dma_reg_map { + /* Isn't it nice how on F1, it's CCR1, but on F2, it's S1CR? */ + + /* Global DMA registers */ + __io uint32 LISR; /**< Low interrupt status register */ + __io uint32 HISR; /**< High interrupt status register */ + __io uint32 LIFCR; /**< Low interrupt flag clear register */ + __io uint32 HIFCR; /**< High interrupt flag clear register */ + /* Stream 0 registers */ + __io uint32 S0CR; /**< Stream 0 control register */ + __io uint32 S0NDTR; /**< Stream 0 number of data register */ + __io uint32 S0PAR; /**< Stream 0 peripheral address register */ + __io uint32 S0M0AR; /**< Stream 0 memory 0 address register */ + __io uint32 S0M1AR; /**< Stream 0 memory 1 address register */ + __io uint32 S0FCR; /**< Stream 0 FIFO control register */ + /* Stream 1 registers */ + __io uint32 S1CR; /**< Stream 1 control register */ + __io uint32 S1NDTR; /**< Stream 1 number of data register */ + __io uint32 S1PAR; /**< Stream 1 peripheral address register */ + __io uint32 S1M0AR; /**< Stream 1 memory 0 address register */ + __io uint32 S1M1AR; /**< Stream 1 memory 1 address register */ + __io uint32 S1FCR; /**< Stream 1 FIFO control register */ + /* Stream 2 registers */ + __io uint32 S2CR; /**< Stream 2 control register */ + __io uint32 S2NDTR; /**< Stream 2 number of data register */ + __io uint32 S2PAR; /**< Stream 2 peripheral address register */ + __io uint32 S2M0AR; /**< Stream 2 memory 0 address register */ + __io uint32 S2M1AR; /**< Stream 2 memory 1 address register */ + __io uint32 S2FCR; /**< Stream 2 FIFO control register */ + /* Stream 3 registers */ + __io uint32 S3CR; /**< Stream 3 control register */ + __io uint32 S3NDTR; /**< Stream 3 number of data register */ + __io uint32 S3PAR; /**< Stream 3 peripheral address register */ + __io uint32 S3M0AR; /**< Stream 3 memory 0 address register */ + __io uint32 S3M1AR; /**< Stream 3 memory 1 address register */ + __io uint32 S3FCR; /**< Stream 3 FIFO control register */ + /* Stream 4 registers */ + __io uint32 S4CR; /**< Stream 4 control register */ + __io uint32 S4NDTR; /**< Stream 4 number of data register */ + __io uint32 S4PAR; /**< Stream 4 peripheral address register */ + __io uint32 S4M0AR; /**< Stream 4 memory 0 address register */ + __io uint32 S4M1AR; /**< Stream 4 memory 1 address register */ + __io uint32 S4FCR; /**< Stream 4 FIFO control register */ + /* Stream 5 registers */ + __io uint32 S5CR; /**< Stream 5 control register */ + __io uint32 S5NDTR; /**< Stream 5 number of data register */ + __io uint32 S5PAR; /**< Stream 5 peripheral address register */ + __io uint32 S5M0AR; /**< Stream 5 memory 0 address register */ + __io uint32 S5M1AR; /**< Stream 5 memory 1 address register */ + __io uint32 S5FCR; /**< Stream 5 FIFO control register */ + /* Stream 6 registers */ + __io uint32 S6CR; /**< Stream 6 control register */ + __io uint32 S6NDTR; /**< Stream 6 number of data register */ + __io uint32 S6PAR; /**< Stream 6 peripheral address register */ + __io uint32 S6M0AR; /**< Stream 6 memory 0 address register */ + __io uint32 S6M1AR; /**< Stream 6 memory 1 address register */ + __io uint32 S6FCR; /**< Stream 6 FIFO control register */ + /* Stream 7 registers */ + __io uint32 S7CR; /**< Stream 7 control register */ + __io uint32 S7NDTR; /**< Stream 7 number of data register */ + __io uint32 S7PAR; /**< Stream 7 peripheral address register */ + __io uint32 S7M0AR; /**< Stream 7 memory 0 address register */ + __io uint32 S7M1AR; /**< Stream 7 memory 1 address register */ + __io uint32 S7FCR; /**< Stream 7 FIFO control register */ +} dma_reg_map; + +/** DMA controller 1 register map base pointer */ +#define DMA1_BASE ((struct dma_reg_map*)0x40026000) +/** DMA controller 2 register map base pointer */ +#define DMA2_BASE ((struct dma_reg_map*)0x40026400) + +/** + * @brief STM32F2 DMA stream (i.e. tube) register map type. + * Provides access to an individual stream's registers. + * @see dma_tube_regs() + */ +typedef struct dma_tube_reg_map { + __io uint32 SCR; /**< Stream configuration register */ + __io uint32 SNDTR; /**< Stream number of data register */ + __io uint32 SPAR; /**< Stream peripheral address register */ + __io uint32 SM0AR; /**< Stream memory 0 address register */ + __io uint32 SM1AR; /**< Stream memory 1 address register */ + __io uint32 SFCR; /**< Stream FIFO control register */ +} dma_tube_reg_map; + +/** DMA1 stream 0 register map base pointer */ +#define DMA1S0_BASE ((struct dma_tube_reg_map*)0x40026010) +/** DMA1 stream 1 register map base pointer */ +#define DMA1S1_BASE ((struct dma_tube_reg_map*)0x40026028) +/** DMA1 stream 2 register map base pointer */ +#define DMA1S2_BASE ((struct dma_tube_reg_map*)0x40026040) +/** DMA1 stream 3 register map base pointer */ +#define DMA1S3_BASE ((struct dma_tube_reg_map*)0x40026058) +/** DMA1 stream 4 register map base pointer */ +#define DMA1S4_BASE ((struct dma_tube_reg_map*)0x40026070) +/** DMA1 stream 5 register map base pointer */ +#define DMA1S5_BASE ((struct dma_tube_reg_map*)0x40026088) +/** DMA1 stream 6 register map base pointer */ +#define DMA1S6_BASE ((struct dma_tube_reg_map*)0x400260A0) +/** DMA1 stream 7 register map base pointer */ +#define DMA1S7_BASE ((struct dma_tube_reg_map*)0x400260B8) + +/** DMA2 stream 0 register map base pointer */ +#define DMA2S0_BASE ((struct dma_tube_reg_map*)0x40026410) +/** DMA2 stream 1 register map base pointer */ +#define DMA2S1_BASE ((struct dma_tube_reg_map*)0x40026028) +/** DMA2 stream 2 register map base pointer */ +#define DMA2S2_BASE ((struct dma_tube_reg_map*)0x40026040) +/** DMA2 stream 3 register map base pointer */ +#define DMA2S3_BASE ((struct dma_tube_reg_map*)0x40026058) +/** DMA2 stream 4 register map base pointer */ +#define DMA2S4_BASE ((struct dma_tube_reg_map*)0x40026070) +/** DMA2 stream 5 register map base pointer */ +#define DMA2S5_BASE ((struct dma_tube_reg_map*)0x40026088) +/** DMA2 stream 6 register map base pointer */ +#define DMA2S6_BASE ((struct dma_tube_reg_map*)0x400260A0) +/** DMA2 stream 7 register map base pointer */ +#define DMA2S7_BASE ((struct dma_tube_reg_map*)0x400260B8) + +/* + * Register bit definitions + */ + +/* Low interrupt status register */ + +#define DMA_LISR_TCIF3_BIT 27 +#define DMA_LISR_HTIF3_BIT 26 +#define DMA_LISR_TEIF3_BIT 25 +#define DMA_LISR_DMEIF3_BIT 24 +#define DMA_LISR_FEIF3_BIT 22 +#define DMA_LISR_TCIF2_BIT 21 +#define DMA_LISR_HTIF2_BIT 20 +#define DMA_LISR_TEIF2_BIT 19 +#define DMA_LISR_DMEIF2_BIT 18 +#define DMA_LISR_FEIF2_BIT 16 +#define DMA_LISR_TCIF1_BIT 11 +#define DMA_LISR_HTIF1_BIT 10 +#define DMA_LISR_TEIF1_BIT 9 +#define DMA_LISR_DMEIF1_BIT 8 +#define DMA_LISR_FEIF1_BIT 6 +#define DMA_LISR_TCIF0_BIT 5 +#define DMA_LISR_HTIF0_BIT 4 +#define DMA_LISR_TEIF0_BIT 3 +#define DMA_LISR_DMEIF0_BIT 2 +#define DMA_LISR_FEIF0_BIT 0 + +#define DMA_LISR_TCIF3 (1U << DMA_LISR_TCIF3_BIT) +#define DMA_LISR_HTIF3 (1U << DMA_LISR_HTIF3_BIT) +#define DMA_LISR_TEIF3 (1U << DMA_LISR_TEIF3_BIT) +#define DMA_LISR_DMEIF3 (1U << DMA_LISR_DMEIF3_BIT) +#define DMA_LISR_FEIF3 (1U << DMA_LISR_FEIF3_BIT) +#define DMA_LISR_TCIF2 (1U << DMA_LISR_TCIF2_BIT) +#define DMA_LISR_HTIF2 (1U << DMA_LISR_HTIF2_BIT) +#define DMA_LISR_TEIF2 (1U << DMA_LISR_TEIF2_BIT) +#define DMA_LISR_DMEIF2 (1U << DMA_LISR_DMEIF2_BIT) +#define DMA_LISR_FEIF2 (1U << DMA_LISR_FEIF2_BIT) +#define DMA_LISR_TCIF1 (1U << DMA_LISR_TCIF1_BIT) +#define DMA_LISR_HTIF1 (1U << DMA_LISR_HTIF1_BIT) +#define DMA_LISR_TEIF1 (1U << DMA_LISR_TEIF1_BIT) +#define DMA_LISR_DMEIF1 (1U << DMA_LISR_DMEIF1_BIT) +#define DMA_LISR_FEIF1 (1U << DMA_LISR_FEIF1_BIT) +#define DMA_LISR_TCIF0 (1U << DMA_LISR_TCIF0_BIT) +#define DMA_LISR_HTIF0 (1U << DMA_LISR_HTIF0_BIT) +#define DMA_LISR_TEIF0 (1U << DMA_LISR_TEIF0_BIT) +#define DMA_LISR_DMEIF0 (1U << DMA_LISR_DMEIF0_BIT) +#define DMA_LISR_FEIF0 (1U << DMA_LISR_FEIF0_BIT) + +/* High interrupt status register */ + +#define DMA_HISR_TCIF7_BIT 27 +#define DMA_HISR_HTIF7_BIT 26 +#define DMA_HISR_TEIF7_BIT 25 +#define DMA_HISR_DMEIF7_BIT 24 +#define DMA_HISR_FEIF7_BIT 22 +#define DMA_HISR_TCIF6_BIT 21 +#define DMA_HISR_HTIF6_BIT 20 +#define DMA_HISR_TEIF6_BIT 19 +#define DMA_HISR_DMEIF6_BIT 18 +#define DMA_HISR_FEIF6_BIT 16 +#define DMA_HISR_TCIF5_BIT 11 +#define DMA_HISR_HTIF5_BIT 10 +#define DMA_HISR_TEIF5_BIT 9 +#define DMA_HISR_DMEIF5_BIT 8 +#define DMA_HISR_FEIF5_BIT 6 +#define DMA_HISR_TCIF4_BIT 5 +#define DMA_HISR_HTIF4_BIT 4 +#define DMA_HISR_TEIF4_BIT 3 +#define DMA_HISR_DMEIF4_BIT 2 +#define DMA_HISR_FEIF4_BIT 0 + +#define DMA_HISR_TCIF7 (1U << DMA_HISR_TCIF7_BIT) +#define DMA_HISR_HTIF7 (1U << DMA_HISR_HTIF7_BIT) +#define DMA_HISR_TEIF7 (1U << DMA_HISR_TEIF7_BIT) +#define DMA_HISR_DMEIF7 (1U << DMA_HISR_DMEIF7_BIT) +#define DMA_HISR_FEIF7 (1U << DMA_HISR_FEIF7_BIT) +#define DMA_HISR_TCIF6 (1U << DMA_HISR_TCIF6_BIT) +#define DMA_HISR_HTIF6 (1U << DMA_HISR_HTIF6_BIT) +#define DMA_HISR_TEIF6 (1U << DMA_HISR_TEIF6_BIT) +#define DMA_HISR_DMEIF6 (1U << DMA_HISR_DMEIF6_BIT) +#define DMA_HISR_FEIF6 (1U << DMA_HISR_FEIF6_BIT) +#define DMA_HISR_TCIF5 (1U << DMA_HISR_TCIF5_BIT) +#define DMA_HISR_HTIF5 (1U << DMA_HISR_HTIF5_BIT) +#define DMA_HISR_TEIF5 (1U << DMA_HISR_TEIF5_BIT) +#define DMA_HISR_DMEIF5 (1U << DMA_HISR_DMEIF5_BIT) +#define DMA_HISR_FEIF5 (1U << DMA_HISR_FEIF5_BIT) +#define DMA_HISR_TCIF4 (1U << DMA_HISR_TCIF4_BIT) +#define DMA_HISR_HTIF4 (1U << DMA_HISR_HTIF4_BIT) +#define DMA_HISR_TEIF4 (1U << DMA_HISR_TEIF4_BIT) +#define DMA_HISR_DMEIF4 (1U << DMA_HISR_DMEIF4_BIT) +#define DMA_HISR_FEIF4 (1U << DMA_HISR_FEIF4_BIT) + +/* Low interrupt flag clear register */ + +#define DMA_LIFCR_CTCIF3_BIT 27 +#define DMA_LIFCR_CHTIF3_BIT 26 +#define DMA_LIFCR_CTEIF3_BIT 25 +#define DMA_LIFCR_CDMEIF3_BIT 24 +#define DMA_LIFCR_CFEIF3_BIT 22 +#define DMA_LIFCR_CTCIF2_BIT 21 +#define DMA_LIFCR_CHTIF2_BIT 20 +#define DMA_LIFCR_CTEIF2_BIT 19 +#define DMA_LIFCR_CDMEIF2_BIT 18 +#define DMA_LIFCR_CFEIF2_BIT 16 +#define DMA_LIFCR_CTCIF1_BIT 11 +#define DMA_LIFCR_CHTIF1_BIT 10 +#define DMA_LIFCR_CTEIF1_BIT 9 +#define DMA_LIFCR_CDMEIF1_BIT 8 +#define DMA_LIFCR_CFEIF1_BIT 6 +#define DMA_LIFCR_CTCIF0_BIT 5 +#define DMA_LIFCR_CHTIF0_BIT 4 +#define DMA_LIFCR_CTEIF0_BIT 3 +#define DMA_LIFCR_CDMEIF0_BIT 2 +#define DMA_LIFCR_CFEIF0_BIT 0 + +#define DMA_LIFCR_CTCIF3 (1U << DMA_LIFCR_CTCIF3_BIT) +#define DMA_LIFCR_CHTIF3 (1U << DMA_LIFCR_CHTIF3_BIT) +#define DMA_LIFCR_CTEIF3 (1U << DMA_LIFCR_CTEIF3_BIT) +#define DMA_LIFCR_CDMEIF3 (1U << DMA_LIFCR_CDMEIF3_BIT) +#define DMA_LIFCR_CFEIF3 (1U << DMA_LIFCR_CFEIF3_BIT) +#define DMA_LIFCR_CTCIF2 (1U << DMA_LIFCR_CTCIF2_BIT) +#define DMA_LIFCR_CHTIF2 (1U << DMA_LIFCR_CHTIF2_BIT) +#define DMA_LIFCR_CTEIF2 (1U << DMA_LIFCR_CTEIF2_BIT) +#define DMA_LIFCR_CDMEIF2 (1U << DMA_LIFCR_CDMEIF2_BIT) +#define DMA_LIFCR_CFEIF2 (1U << DMA_LIFCR_CFEIF2_BIT) +#define DMA_LIFCR_CTCIF1 (1U << DMA_LIFCR_CTCIF1_BIT) +#define DMA_LIFCR_CHTIF1 (1U << DMA_LIFCR_CHTIF1_BIT) +#define DMA_LIFCR_CTEIF1 (1U << DMA_LIFCR_CTEIF1_BIT) +#define DMA_LIFCR_CDMEIF1 (1U << DMA_LIFCR_CDMEIF1_BIT) +#define DMA_LIFCR_CFEIF1 (1U << DMA_LIFCR_CFEIF1_BIT) +#define DMA_LIFCR_CTCIF0 (1U << DMA_LIFCR_CTCIF0_BIT) +#define DMA_LIFCR_CHTIF0 (1U << DMA_LIFCR_CHTIF0_BIT) +#define DMA_LIFCR_CTEIF0 (1U << DMA_LIFCR_CTEIF0_BIT) +#define DMA_LIFCR_CDMEIF0 (1U << DMA_LIFCR_CDMEIF0_BIT) +#define DMA_LIFCR_CFEIF0 (1U << DMA_LIFCR_CFEIF0_BIT) + +/* High interrupt flag clear regsister */ + +#define DMA_HIFCR_CTCIF7_BIT 27 +#define DMA_HIFCR_CHTIF7_BIT 26 +#define DMA_HIFCR_CTEIF7_BIT 25 +#define DMA_HIFCR_CDMEIF7_BIT 24 +#define DMA_HIFCR_CFEIF7_BIT 22 +#define DMA_HIFCR_CTCIF6_BIT 21 +#define DMA_HIFCR_CHTIF6_BIT 20 +#define DMA_HIFCR_CTEIF6_BIT 19 +#define DMA_HIFCR_CDMEIF6_BIT 18 +#define DMA_HIFCR_CFEIF6_BIT 16 +#define DMA_HIFCR_CTCIF5_BIT 11 +#define DMA_HIFCR_CHTIF5_BIT 10 +#define DMA_HIFCR_CTEIF5_BIT 9 +#define DMA_HIFCR_CDMEIF5_BIT 8 +#define DMA_HIFCR_CFEIF5_BIT 6 +#define DMA_HIFCR_CTCIF4_BIT 5 +#define DMA_HIFCR_CHTIF4_BIT 4 +#define DMA_HIFCR_CTEIF4_BIT 3 +#define DMA_HIFCR_CDMEIF4_BIT 2 +#define DMA_HIFCR_CFEIF4_BIT 0 + +#define DMA_HIFCR_CTCIF7 (1U << DMA_HIFCR_CTCIF7_BIT) +#define DMA_HIFCR_CHTIF7 (1U << DMA_HIFCR_CHTIF7_BIT) +#define DMA_HIFCR_CTEIF7 (1U << DMA_HIFCR_CTEIF7_BIT) +#define DMA_HIFCR_CDMEIF7 (1U << DMA_HIFCR_CDMEIF7_BIT) +#define DMA_HIFCR_CFEIF7 (1U << DMA_HIFCR_CFEIF7_BIT) +#define DMA_HIFCR_CTCIF6 (1U << DMA_HIFCR_CTCIF6_BIT) +#define DMA_HIFCR_CHTIF6 (1U << DMA_HIFCR_CHTIF6_BIT) +#define DMA_HIFCR_CTEIF6 (1U << DMA_HIFCR_CTEIF6_BIT) +#define DMA_HIFCR_CDMEIF6 (1U << DMA_HIFCR_CDMEIF6_BIT) +#define DMA_HIFCR_CFEIF6 (1U << DMA_HIFCR_CFEIF6_BIT) +#define DMA_HIFCR_CTCIF5 (1U << DMA_HIFCR_CTCIF5_BIT) +#define DMA_HIFCR_CHTIF5 (1U << DMA_HIFCR_CHTIF5_BIT) +#define DMA_HIFCR_CTEIF5 (1U << DMA_HIFCR_CTEIF5_BIT) +#define DMA_HIFCR_CDMEIF5 (1U << DMA_HIFCR_CDMEIF5_BIT) +#define DMA_HIFCR_CFEIF5 (1U << DMA_HIFCR_CFEIF5_BIT) +#define DMA_HIFCR_CTCIF4 (1U << DMA_HIFCR_CTCIF4_BIT) +#define DMA_HIFCR_CHTIF4 (1U << DMA_HIFCR_CHTIF4_BIT) +#define DMA_HIFCR_CTEIF4 (1U << DMA_HIFCR_CTEIF4_BIT) +#define DMA_HIFCR_CDMEIF4 (1U << DMA_HIFCR_CDMEIF4_BIT) +#define DMA_HIFCR_CFEIF4 (1U << DMA_HIFCR_CFEIF4_BIT) + +/* Stream configuration register */ + +#define DMA_SCR_CT_BIT 19 +#define DMA_SCR_DBM_BIT 18 +#define DMA_SCR_PINCOS_BIT 15 +#define DMA_SCR_MINC_BIT 10 +#define DMA_SCR_PINC_BIT 9 +#define DMA_SCR_CIRC_BIT 8 +#define DMA_SCR_PFCTRL_BIT 5 +#define DMA_SCR_TCIE_BIT 4 +#define DMA_SCR_HTIE_BIT 3 +#define DMA_SCR_TEIE_BIT 2 +#define DMA_SCR_DMEIE_BIT 1 +#define DMA_SCR_EN_BIT 0 + +#define DMA_SCR_CHSEL (0x7 << 25) +#define DMA_SCR_CHSEL_CH_0 (0x0 << 25) +#define DMA_SCR_CHSEL_CH_1 (0x1 << 25) +#define DMA_SCR_CHSEL_CH_2 (0x2 << 25) +#define DMA_SCR_CHSEL_CH_3 (0x3 << 25) +#define DMA_SCR_CHSEL_CH_4 (0x4 << 25) +#define DMA_SCR_CHSEL_CH_5 (0x5 << 25) +#define DMA_SCR_CHSEL_CH_6 (0x6 << 25) +#define DMA_SCR_CHSEL_CH_7 (0x7 << 25) +#define DMA_SCR_MBURST (0x3 << 23) +#define DMA_SCR_MBURST_SINGLE (0x0 << 23) +#define DMA_SCR_MBURST_INCR4 (0x1 << 23) +#define DMA_SCR_MBURST_INCR8 (0x2 << 23) +#define DMA_SCR_MBURST_INCR16 (0x3 << 23) +#define DMA_SCR_PBURST (0x3 << 21) +#define DMA_SCR_PBURST_SINGLE (0x0 << 21) +#define DMA_SCR_PBURST_INCR4 (0x1 << 21) +#define DMA_SCR_PBURST_INCR8 (0x2 << 21) +#define DMA_SCR_PBURST_INCR16 (0x3 << 21) +#define DMA_SCR_CT (1U << DMA_SCR_CT_BIT) +#define DMA_SCR_DBM (1U << DMA_SCR_DBM_BIT) +#define DMA_SCR_PL (0x3 << 16) +#define DMA_SCR_PL_LOW (0x0 << 16) +#define DMA_SCR_PL_MEDIUM (0x1 << 16) +#define DMA_SCR_PL_HIGH (0x2 << 16) +#define DMA_SCR_VERY_HIGH (0x3 << 16) +#define DMA_SCR_PINCOS (1U << DMA_SCR_PINCOS_BIT) +#define DMA_SCR_MSIZE (0x3 << 13) +#define DMA_SCR_MSIZE_8BITS (0x0 << 13) +#define DMA_SCR_MSIZE_16BITS (0x1 << 13) +#define DMA_SCR_MSIZE_32BITS (0x2 << 13) +#define DMA_SCR_PSIZE (0x3 << 11) +#define DMA_SCR_PSIZE_8BITS (0x0 << 11) +#define DMA_SCR_PSIZE_16BITS (0x1 << 11) +#define DMA_SCR_PSIZE_32BITS (0x2 << 11) +#define DMA_SCR_MINC (1U << DMA_SCR_MINC_BIT) +#define DMA_SCR_PINC (1U << DMA_SCR_PINC_BIT) +#define DMA_SCR_CIRC (1U << DMA_SCR_CIRC_BIT) +#define DMA_SCR_DIR (0x3 << 6) +#define DMA_SCR_DIR_PER_TO_MEM (0x0 << 6) +#define DMA_SCR_DIR_MEM_TO_PER (0x1 << 6) +#define DMA_SCR_DIR_MEM_TO_MEM (0x2 << 6) +#define DMA_SCR_PFCTRL (1U << DMA_SCR_PFCTRL_BIT) +#define DMA_SCR_TCIE (1U << DMA_SCR_TCIE_BIT) +#define DMA_SCR_HTIE (1U << DMA_SCR_HTIE_BIT) +#define DMA_SCR_TEIE (1U << DMA_SCR_TEIE_BIT) +#define DMA_SCR_DMEIE (1U << DMA_SCR_DMEIE_BIT) +#define DMA_SCR_EN (1U << DMA_SCR_EN_BIT) + +/* Stream FIFO control register */ + +#define DMA_SFCR_FEIE_BIT 7 +#define DMA_SFCR_DMDIS_BIT 2 + +#define DMA_SFCR_FEIE (1U << DMA_SFCR_FEIE_BIT) +#define DMA_SFCR_FS (0x7 << 3) +#define DMA_SFCR_FS_ZERO_TO_QUARTER (0x0 << 3) +#define DMA_SFCR_FS_QUARTER_TO_HALF (0x1 << 3) +#define DMA_SFCR_FS_HALF_TO_THREE_QUARTERS (0x2 << 3) +#define DMA_SFCR_FS_THREE_QUARTERS_TO_FULL (0x3 << 3) +#define DMA_SFCR_FS_EMPTY (0x4 << 3) +#define DMA_SFCR_FS_FULL (0x5 << 3) +#define DMA_SFCR_DMDIS (1U << DMA_SFCR_DMDIS_BIT) +#define DMA_SFCR_FTH (0x3 << 0) +#define DMA_SFCR_FTH_QUARTER_FULL (0x0 << 3) +#define DMA_SFCR_FTH_HALF_FULL (0x1 << 3) +#define DMA_SFCR_FTH_THREE_QUARTERS_FULL (0x2 << 3) +#define DMA_SFCR_FTH_FULL (0x3 << 3) + +/* + * Devices + */ + +extern dma_dev *DMA1; +extern dma_dev *DMA2; + +/* + * Other types needed by, or useful for, + */ + +/** + * @brief DMA streams + * This is also the dma_tube type for STM32F2. + * @see dma_tube + */ +typedef enum dma_stream { + DMA_S0 = 0, + DMA_S1 = 1, + DMA_S2 = 2, + DMA_S3 = 3, + DMA_S4 = 4, + DMA_S5 = 5, + DMA_S6 = 6, + DMA_S7 = 7, +} dma_stream; + +/** STM32F2 dma_tube (=dma_stream) */ +#define dma_tube dma_stream + +/** + * @brief STM32F2 configuration flags for dma_tube_config. + * @see struct dma_tube_config + */ +typedef enum dma_cfg_flags { + /* NB: flags that aren't SCR bits are treated specially. */ + + /** + * Source address increment mode + * + * If this flag is set, the source address is incremented (by the + * source size) after each DMA transfer. + */ + DMA_CFG_SRC_INC = 1U << 31, + + /** + * Destination address increment mode + * + * If this flag is set, the destination address is incremented (by + * the destination size) after each DMA transfer. + */ + DMA_CFG_DST_INC = 1U << 30, + + /** + * Circular mode + * + * This mode is not available for memory-to-memory transfers. + */ + DMA_CFG_CIRC = DMA_SCR_CIRC, + + /** Transfer complete interrupt enable */ + DMA_CFG_CMPLT_IE = DMA_SCR_TCIE, + /** Transfer half-complete interrupt enable */ + DMA_CFG_HALF_CMPLT_IE = DMA_SCR_HTIE, + /** Transfer error interrupt enable */ + DMA_CFG_ERR_IE = DMA_SCR_TEIE, + /** Direct mode error interrupt enable */ + DMA_CFG_DM_ERR_IE = DMA_SCR_DMEIE, + /** FIFO error interrupt enable */ + DMA_CFG_FIFO_ERR_IE = (1U << 29), +} dma_cfg_flags; + +/** + * @brief STM32F2 DMA request sources. + * + * IMPORTANT: + * + * 1. On STM32F2, a particular dma_request_src is always tied to a + * single DMA controller, but often can be supported by multiple + * streams. For example, DMA requests from ADC1 (DMA_REQ_SRC_ADC1) can + * only be handled by DMA2, but they can go to either stream 0 or + * stream 4 (though not any other stream). If you try to use a request + * source with the wrong DMA controller or the wrong stream on + * STM32F2, dma_tube_cfg() will fail. + * + * 2. A single stream can only handle a single request source at a + * time. If you change a stream's request source later, it will stop + * serving requests from the old source. However, for some streams, + * some sources conflict with one another (when they correspond to the + * same channel on that stream), and on STM32F2, Terrible Super-Bad + * Things will happen if two conflicting request sources are active at + * the same time. + * + * @see struct dma_tube_config + * @see dma_tube_cfg() + */ +typedef enum dma_request_src { + /* These are constructed like so (though this may change, so user + * code shouldn't depend on it): + * + * Bits 0--2: Channel associated with request source + * + * Bits 3--9: rcc_clk_id of DMA controller associated with request source + * + * Bits 10--17: Bit mask of streams which can handle that request + * source. (E.g., bit 10 set means stream 0 can + * handle the source, bit 11 set means stream 1 can, + * etc.) + * + * Among other things, this is used for error checking in + * dma_tube_cfg(). If you change this bit encoding, you need to + * update the helper functions in stm32f2/dma.c. + */ +#define _DMA_STM32F2_REQ_SRC(stream_mask, clk_id, channel) \ + (((stream_mask) << 10) | ((clk_id) << 3) | (channel)) +#define _DMA_S(n) (1U << (n)) + + /* DMA1 request sources */ +#define _DMA_1_REQ_SRC(stream_mask, channel) \ + _DMA_STM32F2_REQ_SRC(stream_mask, RCC_DMA1, channel) + + /* Channel 0 */ + DMA_REQ_SRC_SPI3_RX = _DMA_1_REQ_SRC(_DMA_S(0) | _DMA_S(2), 0), + DMA_REQ_SRC_SPI2_RX = _DMA_1_REQ_SRC(_DMA_S(3), 0), + DMA_REQ_SRC_SPI2_TX = _DMA_1_REQ_SRC(_DMA_S(4), 0), + DMA_REQ_SRC_SPI3_TX = _DMA_1_REQ_SRC(_DMA_S(5) | _DMA_S(7), 0), + + /* Channel 1 */ + DMA_REQ_SRC_I2C1_RX = _DMA_1_REQ_SRC(_DMA_S(0) | _DMA_S(5), 1), + DMA_REQ_SRC_TIM7_UP = _DMA_1_REQ_SRC(_DMA_S(2) | _DMA_S(4), 1), + DMA_REQ_SRC_I2C1_TX = _DMA_1_REQ_SRC(_DMA_S(6) | _DMA_S(7), 1), + + /* Channel 2 */ + DMA_REQ_SRC_TIM4_CH1 = _DMA_1_REQ_SRC(_DMA_S(0), 2), + DMA_REQ_SRC_TIM4_CH2 = _DMA_1_REQ_SRC(_DMA_S(3), 2), + DMA_REQ_SRC_TIM4_UP = _DMA_1_REQ_SRC(_DMA_S(6), 2), + DMA_REQ_SRC_TIM4_CH3 = _DMA_1_REQ_SRC(_DMA_S(7), 2), + + /* Channel 3 */ + DMA_REQ_SRC_TIM2_UP = _DMA_1_REQ_SRC(_DMA_S(1) | _DMA_S(7), 3), + DMA_REQ_SRC_TIM2_CH3 = _DMA_1_REQ_SRC(_DMA_S(1), 3), + DMA_REQ_SRC_I2C3_RX = _DMA_1_REQ_SRC(_DMA_S(2), 3), + DMA_REQ_SRC_I2C3_TX = _DMA_1_REQ_SRC(_DMA_S(4), 3), + DMA_REQ_SRC_TIM2_CH1 = _DMA_1_REQ_SRC(_DMA_S(5), 3), + DMA_REQ_SRC_TIM2_CH2 = _DMA_1_REQ_SRC(_DMA_S(6), 3), + DMA_REQ_SRC_TIM2_CH4 = _DMA_1_REQ_SRC(_DMA_S(6) | _DMA_S(7), 3), + + /* Channel 4 */ + DMA_REQ_SRC_UART5_RX = _DMA_1_REQ_SRC(_DMA_S(0), 4), + DMA_REQ_SRC_USART3_RX = _DMA_1_REQ_SRC(_DMA_S(1), 4), + DMA_REQ_SRC_UART4_RX = _DMA_1_REQ_SRC(_DMA_S(2), 4), + DMA_REQ_SRC_USART3_TX = _DMA_1_REQ_SRC(_DMA_S(3), 4), + DMA_REQ_SRC_UART4_TX = _DMA_1_REQ_SRC(_DMA_S(4), 4), + DMA_REQ_SRC_USART2_RX = _DMA_1_REQ_SRC(_DMA_S(5), 4), + DMA_REQ_SRC_USART2_TX = _DMA_1_REQ_SRC(_DMA_S(6), 4), + DMA_REQ_SRC_UART5_TX = _DMA_1_REQ_SRC(_DMA_S(7), 4), + + /* Channel 5 */ + DMA_REQ_SRC_TIM3_CH4 = _DMA_1_REQ_SRC(_DMA_S(2), 5), + DMA_REQ_SRC_TIM3_UP = _DMA_1_REQ_SRC(_DMA_S(2), 5), + DMA_REQ_SRC_TIM3_CH1 = _DMA_1_REQ_SRC(_DMA_S(4), 5), + DMA_REQ_SRC_TIM3_TRIG = _DMA_1_REQ_SRC(_DMA_S(4), 5), + DMA_REQ_SRC_TIM3_CH2 = _DMA_1_REQ_SRC(_DMA_S(5), 5), + DMA_REQ_SRC_TIM3_CH3 = _DMA_1_REQ_SRC(_DMA_S(7), 5), + + /* Channel 6 */ + DMA_REQ_SRC_TIM5_CH3 = _DMA_1_REQ_SRC(_DMA_S(0), 6), + DMA_REQ_SRC_TIM5_UP = _DMA_1_REQ_SRC(_DMA_S(0) | _DMA_S(6), 6), + DMA_REQ_SRC_TIM5_CH4 = _DMA_1_REQ_SRC(_DMA_S(1) | _DMA_S(3), 6), + DMA_REQ_SRC_TIM5_TRIG = _DMA_1_REQ_SRC(_DMA_S(1) | _DMA_S(3), 6), + DMA_REQ_SRC_TIM5_CH1 = _DMA_1_REQ_SRC(_DMA_S(2), 6), + DMA_REQ_SRC_TIM5_CH2 = _DMA_1_REQ_SRC(_DMA_S(4), 6), + + /* Channel 7 */ + DMA_REQ_SRC_TIM6_UP = _DMA_1_REQ_SRC(_DMA_S(1), 7), + DMA_REQ_SRC_I2C2_RX = _DMA_1_REQ_SRC(_DMA_S(2) | _DMA_S(3), 7), + DMA_REQ_SRC_USART3_TX_ALTERNATE = _DMA_1_REQ_SRC(_DMA_S(4), 7), + DMA_REQ_SRC_DAC1 = _DMA_1_REQ_SRC(_DMA_S(5), 7), + DMA_REQ_SRC_DAC2 = _DMA_1_REQ_SRC(_DMA_S(6), 7), + DMA_REQ_SRC_I2C2_TX = _DMA_1_REQ_SRC(_DMA_S(7), 7), +#undef _DMA_1_REQ_SRC + + /* DMA2 request sources */ +#define _DMA_2_REQ_SRC(stream_mask, channel) \ + _DMA_STM32F2_REQ_SRC(stream_mask, RCC_DMA2, channel) + + /* Channel 0 */ + DMA_REQ_SRC_ADC1 = _DMA_2_REQ_SRC(_DMA_S(0) | _DMA_S(4), 0), + /* You can use these "DMA_REQ_SRC_TIMx_CHx_ALTERNATE" if you know + * what you're doing, but the other ones (for channels 6 and 7), + * are better, in that they don't conflict with one another. */ + DMA_REQ_SRC_TIM8_CH1_ALTERNATE = _DMA_2_REQ_SRC(_DMA_S(2), 0), + DMA_REQ_SRC_TIM8_CH2_ALTERNATE = _DMA_2_REQ_SRC(_DMA_S(2), 0), + DMA_REQ_SRC_TIM8_CH3_ALTERNATE = _DMA_2_REQ_SRC(_DMA_S(2), 0), + DMA_REQ_SRC_TIM1_CH1_ALTERNATE = _DMA_2_REQ_SRC(_DMA_S(6), 0), + DMA_REQ_SRC_TIM1_CH2_ALTERNATE = _DMA_2_REQ_SRC(_DMA_S(6), 0), + DMA_REQ_SRC_TIM1_CH3_ALTENRATE = _DMA_2_REQ_SRC(_DMA_S(6), 0), + + /* Channel 1 */ + DMA_REQ_SRC_DCMI = _DMA_2_REQ_SRC(_DMA_S(1) | _DMA_S(7), 1), + DMA_REQ_SRC_ADC2 = _DMA_2_REQ_SRC(_DMA_S(2) | _DMA_S(3), 1), + + /* Channel 2 */ + DMA_REQ_SRC_ADC3 = _DMA_2_REQ_SRC(_DMA_S(0) | _DMA_S(1), 2), + DMA_REQ_SRC_CRYP_OUT = _DMA_2_REQ_SRC(_DMA_S(5), 2), + DMA_REQ_SRC_CRYP_IN = _DMA_2_REQ_SRC(_DMA_S(6), 2), + DMA_REQ_SRC_HASH_IN = _DMA_2_REQ_SRC(_DMA_S(7), 2), + + /* Channel 3 */ + DMA_REQ_SRC_SPI1_RX = _DMA_2_REQ_SRC(_DMA_S(0) | _DMA_S(2), 3), + DMA_REQ_SRC_SPI1_TX = _DMA_2_REQ_SRC(_DMA_S(3) | _DMA_S(5), 3), + + /* Channel 4 */ + DMA_REQ_SRC_USART1_RX = _DMA_2_REQ_SRC(_DMA_S(2) | _DMA_S(5), 4), + DMA_REQ_SRC_SDIO = _DMA_2_REQ_SRC(_DMA_S(3) | _DMA_S(6), 4), + DMA_REQ_SRC_USART1_TX = _DMA_2_REQ_SRC(_DMA_S(7), 4), + + /* Channel 5 */ + DMA_REQ_SRC_USART6_RX = _DMA_2_REQ_SRC(_DMA_S(1) | _DMA_S(2), 5), + DMA_REQ_SRC_USART6_TX = _DMA_2_REQ_SRC(_DMA_S(6) | _DMA_S(7), 5), + + /* Channel 6 */ + DMA_REQ_SRC_TIM1_TRIG = _DMA_2_REQ_SRC(_DMA_S(0) | _DMA_S(4), 6), + DMA_REQ_SRC_TIM1_CH1 = _DMA_2_REQ_SRC(_DMA_S(1) | _DMA_S(3), 6), + DMA_REQ_SRC_TIM1_CH2 = _DMA_2_REQ_SRC(_DMA_S(3), 6), + DMA_REQ_SRC_TIM1_CH4 = _DMA_2_REQ_SRC(_DMA_S(4), 6), + DMA_REQ_SRC_TIM1_COM = _DMA_2_REQ_SRC(_DMA_S(4), 6), + DMA_REQ_SRC_TIM1_UP = _DMA_2_REQ_SRC(_DMA_S(5), 6), + DMA_REQ_SRC_TIM1_CH3 = _DMA_2_REQ_SRC(_DMA_S(6), 6), + + /* Channel 7 */ + DMA_REQ_SRC_TIM8_UP = _DMA_2_REQ_SRC(_DMA_S(1), 7), + DMA_REQ_SRC_TIM8_CH1 = _DMA_2_REQ_SRC(_DMA_S(2), 7), + DMA_REQ_SRC_TIM8_CH2 = _DMA_2_REQ_SRC(_DMA_S(3), 7), + DMA_REQ_SRC_TIM8_CH3 = _DMA_2_REQ_SRC(_DMA_S(4), 7), + DMA_REQ_SRC_TIM8_CH4 = _DMA_2_REQ_SRC(_DMA_S(7), 7), + DMA_REQ_SRC_TIM8_TRIG = _DMA_2_REQ_SRC(_DMA_S(7), 7), + DMA_REQ_SRC_TIM8_COM = _DMA_2_REQ_SRC(_DMA_S(7), 7), +#undef _DMA_2_REQ_SRC +#undef _DMA_S +} dma_request_src; + +/* + * Tube conveniences + */ + +static inline dma_tube_reg_map* dma_tube_regs(dma_dev *dev, + dma_tube tube) { + ASSERT(DMA_S0 <= tube && tube <= DMA_S7); + switch (dev->clk_id) { + case RCC_DMA1: + return DMA1S0_BASE + (int)tube; + case RCC_DMA2: + return DMA2S0_BASE + (int)tube; + default: + /* Can't happen */ + ASSERT(0); + return 0; + } +} + +static inline uint8 dma_is_enabled(dma_dev *dev, dma_tube tube) { + return dma_tube_regs(dev, tube)->SCR & DMA_SCR_EN; +} + +/* F2-only; available because of double-buffering. */ +void dma_set_mem_n_addr(dma_dev *dev, dma_tube tube, int n, + __io void *address); + +/** + * @brief Set memory 0 address. + * Availability: STM32F2. + * + * @param dev DMA device + * @param tube Tube whose memory 0 address to set + * @param addr Address to use as memory 0 + */ +static __always_inline void +dma_set_mem0_addr(dma_dev *dev, dma_tube tube, __io void *addr) { + dma_set_mem_n_addr(dev, tube, 0, addr); +} + +/** + * @brief Set memory 1 address. + * Availability: STM32F2. + * + * @param dev DMA device + * @param tube Tube whose memory 1 address to set + * @param addr Address to use as memory 1 + */ +static __always_inline void +dma_set_mem1_addr(dma_dev *dev, dma_tube tube, __io void *addr) { + dma_set_mem_n_addr(dev, tube, 1, addr); +} + +/* Assume the user means SM0AR in a non-double-buffered configuration. */ +static __always_inline void +dma_set_mem_addr(dma_dev *dev, dma_tube tube, __io void *addr) { + dma_set_mem0_addr(dev, tube, addr); +} + +/* SM0AR and SM1AR are treated as though they have the same size */ +static inline dma_xfer_size dma_get_mem_size(dma_dev *dev, dma_tube tube) { + return (dma_xfer_size)(dma_tube_regs(dev, tube)->SCR >> 13); +} + +static inline dma_xfer_size dma_get_per_size(dma_dev *dev, dma_tube tube) { + return (dma_xfer_size)(dma_tube_regs(dev, tube)->SCR >> 11); +} + +void dma_enable_fifo(dma_dev *dev, dma_tube tube); +void dma_disable_fifo(dma_dev *dev, dma_tube tube); + +static __always_inline int dma_is_fifo_enabled(dma_dev *dev, dma_tube tube) { + return dma_tube_regs(dev, tube)->SFCR & DMA_SFCR_DMDIS; +} + +/* + * TODO: + * - Double-buffer configuration function + * - FIFO configuration function + * - MBURST/PBURST configuration function + */ + +/* + * ISR/IFCR conveniences. + */ + +/* (undocumented) helper for reading LISR/HISR and writing + * LIFCR/HIFCR. For these registers, + * + * S0, S4: bits start at bit 0 + * S1, S5: 6 + * S2, S6: 16 + * S3, S7: 22 + * + * I can't imagine why ST didn't just use a byte for each group. The + * bits fit, and it would have made functions like these simpler and + * faster. Oh well. */ +static __always_inline uint32 _dma_sr_fcr_shift(dma_tube tube) { + switch (tube) { + case DMA_S0: /* fall through */ + case DMA_S4: + return 0; + case DMA_S1: /* fall through */ + case DMA_S5: + return 6; + case DMA_S2: /* fall through */ + case DMA_S6: + return 16; + case DMA_S3: /* fall through */ + case DMA_S7: + return 22; + } + /* Can't happen */ + ASSERT(0); + return 0; +} + +static inline uint8 dma_get_isr_bits(dma_dev *dev, dma_tube tube) { + dma_reg_map *regs = dev->regs; + __io uint32 *isr = tube > DMA_S3 ? ®s->HISR : ®s->LISR; + return (*isr >> _dma_sr_fcr_shift(tube)) & 0x3D; +} + +static inline void dma_clear_isr_bits(dma_dev *dev, dma_tube tube) { + dma_reg_map *regs = dev->regs; + __io uint32 *ifcr = tube > DMA_S3 ? ®s->HIFCR : ®s->LIFCR; + *ifcr = (0x3D << _dma_sr_fcr_shift(tube)); +} + +#undef _DMA_IRQ_BIT_SHIFT + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/libmaple/stm32f2/rules.mk b/libmaple/stm32f2/rules.mk index 759f905..4c62cc2 100644 --- a/libmaple/stm32f2/rules.mk +++ b/libmaple/stm32f2/rules.mk @@ -12,6 +12,7 @@ sSRCS_$(d) := isrs.S sSRCS_$(d) += vector_table.S cSRCS_$(d) := adc.c +cSRCS_$(d) += dma.c cSRCS_$(d) += exti.c cSRCS_$(d) += fsmc.c cSRCS_$(d) += gpio.c -- cgit v1.2.3 From bcd28f11c2e7adfd488a10e59ed9dfad7877746d Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Wed, 20 Jun 2012 13:47:47 -0400 Subject: I2C: Restore on F1, refactoring prep for F2. Bring back support on STM32F1 with a view towards how it'll be implemented on STM32F2. There are still many F1-isms in libmaple/i2c.c and , to be dealt with subsequently. Move device declarations and base pointer definitions to a new F1 . The register maps and bit definitions themselves are identical on both series, so leave them in the libmaple header. Add i2c_private.h, which contains: - I2C_DEV(), a convenience macro for defining an i2c_dev, and - declarations for the event and error IRQ handlers. The IRQ handlers are large, and I2C is slow anyway, so I see no reason to make them inline in the private header (as we do for some other peripherals). We just expose the existing ones that were formerly static in libmaple/i2c.c, but prefix the names with underscore. Move the device declarations and IRQ handlers into new stm32f1/i2c.c. These use the i2c_private.h API. Signed-off-by: Marti Bolivar --- libmaple/i2c.c | 47 ++------------------------- libmaple/i2c_private.h | 46 +++++++++++++++++++++++++++ libmaple/include/libmaple/i2c.h | 17 +--------- libmaple/rules.mk | 7 ++-- libmaple/stm32f1/i2c.c | 60 +++++++++++++++++++++++++++++++++++ libmaple/stm32f1/include/series/i2c.h | 56 ++++++++++++++++++++++++++++++++ libmaple/stm32f1/rules.mk | 1 + 7 files changed, 171 insertions(+), 63 deletions(-) create mode 100644 libmaple/i2c_private.h create mode 100644 libmaple/stm32f1/i2c.c create mode 100644 libmaple/stm32f1/include/series/i2c.h (limited to 'libmaple/rules.mk') diff --git a/libmaple/i2c.c b/libmaple/i2c.c index 3db8516..5c0d5e4 100644 --- a/libmaple/i2c.c +++ b/libmaple/i2c.c @@ -2,6 +2,7 @@ * The MIT License * * Copyright (c) 2010 Perry Hung. + * Copyright (c) 2012 LeafLabs, LLC. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -40,32 +41,6 @@ #include -static i2c_dev i2c_dev1 = { - .regs = I2C1_BASE, - .gpio_port = &gpiob, - .sda_pin = 7, - .scl_pin = 6, - .clk_id = RCC_I2C1, - .ev_nvic_line = NVIC_I2C1_EV, - .er_nvic_line = NVIC_I2C1_ER, - .state = I2C_STATE_DISABLED -}; -/** I2C1 device */ -i2c_dev* const I2C1 = &i2c_dev1; - -static i2c_dev i2c_dev2 = { - .regs = I2C2_BASE, - .gpio_port = &gpiob, - .sda_pin = 11, - .scl_pin = 10, - .clk_id = RCC_I2C2, - .ev_nvic_line = NVIC_I2C2_EV, - .er_nvic_line = NVIC_I2C2_ER, - .state = I2C_STATE_DISABLED -}; -/** I2C2 device */ -i2c_dev* const I2C2 = &i2c_dev2; - static inline int32 wait_for_state_change(i2c_dev *dev, i2c_state state, uint32 timeout); @@ -129,7 +104,7 @@ enum { * @brief IRQ handler for I2C master. Handles transmission/reception. * @param dev I2C device */ -static void i2c_irq_handler(i2c_dev *dev) { +void _i2c_irq_handler(i2c_dev *dev) { i2c_msg *msg = dev->msg; uint8 read = msg->flags & I2C_MSG_READ; @@ -289,20 +264,12 @@ static void i2c_irq_handler(i2c_dev *dev) { } } -void __irq_i2c1_ev(void) { - i2c_irq_handler(&i2c_dev1); -} - -void __irq_i2c2_ev(void) { - i2c_irq_handler(&i2c_dev2); -} - /** * @brief Interrupt handler for I2C error conditions * @param dev I2C device * @sideeffect Aborts any pending I2C transactions */ -static void i2c_irq_error_handler(i2c_dev *dev) { +void _i2c_irq_error_handler(i2c_dev *dev) { I2C_CRUMB(ERROR_ENTRY, dev->regs->SR1, dev->regs->SR2); dev->error_flags = dev->regs->SR2 & (I2C_SR1_BERR | @@ -318,14 +285,6 @@ static void i2c_irq_error_handler(i2c_dev *dev) { dev->state = I2C_STATE_ERROR; } -void __irq_i2c1_er(void) { - i2c_irq_error_handler(&i2c_dev1); -} - -void __irq_i2c2_er(void) { - i2c_irq_error_handler(&i2c_dev2); -} - /** * @brief Reset an I2C bus. * diff --git a/libmaple/i2c_private.h b/libmaple/i2c_private.h new file mode 100644 index 0000000..4a0f01f --- /dev/null +++ b/libmaple/i2c_private.h @@ -0,0 +1,46 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +#ifndef _LIBMAPLE_I2C_PRIVATE_H_ +#define _LIBMAPLE_I2C_PRIVATE_H_ + +#define I2C_DEV(num, port, sda, scl) \ + { \ + .regs = I2C##num##_BASE, \ + .gpio_port = port, \ + .sda_pin = sda, \ + .scl_pin = scl, \ + .clk_id = RCC_I2C##num, \ + .ev_nvic_line = NVIC_I2C##num##_EV, \ + .er_nvic_line = NVIC_I2C##num##_ER, \ + .state = I2C_STATE_DISABLED, \ + } + +struct i2c_dev; +void _i2c_irq_handler(struct i2c_dev *dev); +void _i2c_irq_error_handler(struct i2c_dev *dev); + +#endif /* _LIBMAPLE_I2C_PRIVATE_H_ */ diff --git a/libmaple/include/libmaple/i2c.h b/libmaple/include/libmaple/i2c.h index 7ee0b9a..2b36404 100644 --- a/libmaple/include/libmaple/i2c.h +++ b/libmaple/include/libmaple/i2c.h @@ -37,6 +37,7 @@ extern "C" { #endif +#include #include #include #include @@ -96,22 +97,6 @@ typedef struct i2c_dev { volatile i2c_state state; /**< Device state */ } i2c_dev; -/* - * Devices - */ - -extern i2c_dev* const I2C1; -extern i2c_dev* const I2C2; - -/* - * Register map base pointers - */ - -/** I2C1 register map base pointer */ -#define I2C1_BASE ((struct i2c_reg_map*)0x40005400) -/** I2C2 register map base pointer */ -#define I2C2_BASE ((struct i2c_reg_map*)0x40005800) - /* * Register bit definitions */ diff --git a/libmaple/rules.mk b/libmaple/rules.mk index 41f5601..71979f0 100644 --- a/libmaple/rules.mk +++ b/libmaple/rules.mk @@ -27,10 +27,11 @@ cSRCS_$(d) += timer.c cSRCS_$(d) += usart.c cSRCS_$(d) += usart_private.c cSRCS_$(d) += util.c -# These still need to be brought back for F1: -# cSRCS_$(d) += i2c.c - sSRCS_$(d) := exc.S +# I2C support must be ported to F2: +ifeq ($(MCU_SERIES),stm32f1) +cSRCS_$(d) += i2c.c +endif cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%) sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%) diff --git a/libmaple/stm32f1/i2c.c b/libmaple/stm32f1/i2c.c new file mode 100644 index 0000000..9ebcb40 --- /dev/null +++ b/libmaple/stm32f1/i2c.c @@ -0,0 +1,60 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +#include "i2c_private.h" +#include + +/* + * Devices + */ + +static i2c_dev i2c1 = I2C_DEV(1, &gpiob, 7, 6); +static i2c_dev i2c2 = I2C_DEV(2, &gpiob, 11, 10); + +/** STM32F1 I2C device 1 */ +i2c_dev* const I2C1 = &i2c1; +/** STM32F1 I2C device 2 */ +i2c_dev* const I2C2 = &i2c2; + +/* + * IRQ handlers + */ + +void __irq_i2c1_ev(void) { + _i2c_irq_handler(I2C1); +} + +void __irq_i2c2_ev(void) { + _i2c_irq_handler(I2C2); +} + +void __irq_i2c1_er(void) { + _i2c_irq_error_handler(I2C1); +} + +void __irq_i2c2_er(void) { + _i2c_irq_error_handler(I2C2); +} diff --git a/libmaple/stm32f1/include/series/i2c.h b/libmaple/stm32f1/include/series/i2c.h new file mode 100644 index 0000000..0e4b3ba --- /dev/null +++ b/libmaple/stm32f1/include/series/i2c.h @@ -0,0 +1,56 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Perry Hung (from ). + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/include/stm32f1/include/series/i2c.h + * @brief STM32F1 I2C + */ + +#ifndef _LIBMAPLE_STM32F1_I2C_H_ +#define _LIBMAPLE_STM32F1_I2C_H_ + +/* + * Register maps + */ + +struct i2c_reg_map; + +/** STM32F1 I2C1 register map base pointer */ +#define I2C1_BASE ((struct i2c_reg_map*)0x40005400) +/** STM32F1 I2C2 register map base pointer */ +#define I2C2_BASE ((struct i2c_reg_map*)0x40005800) + +/* + * Devices + */ + +struct i2c_dev; + +extern struct i2c_dev* const I2C1; +extern struct i2c_dev* const I2C2; + +#endif /* _LIBMAPLE_STM32F1_I2C_H_ */ diff --git a/libmaple/stm32f1/rules.mk b/libmaple/stm32f1/rules.mk index 15f6fdb..3ca0813 100644 --- a/libmaple/stm32f1/rules.mk +++ b/libmaple/stm32f1/rules.mk @@ -20,6 +20,7 @@ cSRCS_$(d) += dma.c cSRCS_$(d) += exti.c cSRCS_$(d) += fsmc.c cSRCS_$(d) += gpio.c +cSRCS_$(d) += i2c.c cSRCS_$(d) += rcc.c cSRCS_$(d) += spi.c cSRCS_$(d) += timer.c -- cgit v1.2.3