From 014f9a0545556f2e0d4fb3faba5607e59e1e97ad Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Thu, 31 May 2012 17:17:06 -0400 Subject: examples/blinky.cpp works on F2. Only OUTPUT mode is tested; any other modes might work, but no guarantees. Bring back: - wirish/wirish_digital.cpp - wirish/cxxabi-compat.cpp - wirish/wirish_time.cpp Add new: - wirish/stm32f1/wirish_digital.cpp - wirish/stm32f2/wirish_digital.cpp Move pinMode() from wirish/wirish_digital.cpp into the file by the same basename in wirish/stm32f1. This implementation is tied to F1. Add an F2 implementation in wirish/stm32f2/wirish_digital.cpp. Signed-off-by: Marti Bolivar --- wirish/stm32f2/wirish_digital.cpp | 130 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 wirish/stm32f2/wirish_digital.cpp (limited to 'wirish/stm32f2/wirish_digital.cpp') diff --git a/wirish/stm32f2/wirish_digital.cpp b/wirish/stm32f2/wirish_digital.cpp new file mode 100644 index 0000000..a67111d --- /dev/null +++ b/wirish/stm32f2/wirish_digital.cpp @@ -0,0 +1,130 @@ +/****************************************************************************** + * 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. + *****************************************************************************/ + +/* + * STM32F2 implementations for basic GPIO functionality. + */ + +#include + +#include +#include + +#include + +void pinMode(uint8 pin, WiringPinMode w_mode) { + if (pin >= BOARD_NR_GPIO_PINS) { + return; + } + + gpio_pin_mode mode; + // People always do the silly pin-toggle speed benchmark, so let's + // accomodate them: + unsigned flags = GPIO_MODEF_SPEED_HIGH; + bool pwm = false; + switch(w_mode) { + case OUTPUT: + mode = GPIO_MODE_OUTPUT; + break; + case OUTPUT_OPEN_DRAIN: + mode = GPIO_MODE_OUTPUT; + flags |= GPIO_MODEF_TYPE_OD; + break; + case INPUT: + case INPUT_FLOATING: + mode = GPIO_MODE_INPUT; + break; + case INPUT_ANALOG: + mode = GPIO_MODE_ANALOG; + break; + case INPUT_PULLUP: + mode = GPIO_MODE_INPUT; + flags |= GPIO_MODEF_PUPD_PU; + break; + case INPUT_PULLDOWN: + mode = GPIO_MODE_INPUT; + flags |= GPIO_MODEF_PUPD_PD; + break; + case PWM: + mode = GPIO_MODE_AF; + pwm = true; + break; + case PWM_OPEN_DRAIN: + mode = GPIO_MODE_AF; + flags |= GPIO_MODEF_TYPE_OD; + pwm = true; + break; + default: + ASSERT(0); // Can't happen + return; + } + + const stm32_pin_info *info = &PIN_MAP[pin]; + + if (pwm) { + /* If enabling PWM, tell the timer to do PWM, and tell the pin + * to listen to the right timer. */ + ASSERT(info->timer_device != NULL); + if (info->timer_device == NULL) { + return; + } + gpio_af timer_af; + /* TODO make this code a convenience + * routine for series that support GPIO alternate + * functions. */ + switch(info->timer_device->clk_id) { + case RCC_TIMER1: // fall-through + case RCC_TIMER2: + timer_af = GPIO_AF_TIM_1_2; + break; + case RCC_TIMER3: // fall-through + case RCC_TIMER4: // ... + case RCC_TIMER5: + timer_af = GPIO_AF_TIM_3_4_5; + break; + /* Timers 6 and 7 don't have any capture/compare, so they + * can't do PWM (and in fact have no AF values). */ + case RCC_TIMER8: // fall-through + case RCC_TIMER9: // ... + case RCC_TIMER10: // ... + case RCC_TIMER11: + timer_af = GPIO_AF_TIM_8_9_10_11; + break; + case RCC_TIMER12: // fall-through + case RCC_TIMER13: // ... + case RCC_TIMER14: + timer_af = GPIO_AF_CAN_1_2_TIM_12_13_14; + break; + default: + ASSERT(0); // Can't happen + return; + } + timer_set_mode(info->timer_device, info->timer_channel, TIMER_PWM); + gpio_set_af(info->gpio_device, info->gpio_bit, timer_af); + } else { + gpio_set_modef(info->gpio_device, info->gpio_bit, mode, flags); + } +} -- cgit v1.2.3 From cc40b48edacdee58e56e443993aa3c1f22c9374e Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Sat, 2 Jun 2012 23:57:52 -0400 Subject: STM32F2: fix pinMode() for PWM, PWM_OPEN_DRAIN. Make it so the call to gpio_set_modef() actually happens. Signed-off-by: Marti Bolivar --- wirish/stm32f2/wirish_digital.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'wirish/stm32f2/wirish_digital.cpp') diff --git a/wirish/stm32f2/wirish_digital.cpp b/wirish/stm32f2/wirish_digital.cpp index a67111d..bf9dcf5 100644 --- a/wirish/stm32f2/wirish_digital.cpp +++ b/wirish/stm32f2/wirish_digital.cpp @@ -124,7 +124,6 @@ void pinMode(uint8 pin, WiringPinMode w_mode) { } timer_set_mode(info->timer_device, info->timer_channel, TIMER_PWM); gpio_set_af(info->gpio_device, info->gpio_bit, timer_af); - } else { - gpio_set_modef(info->gpio_device, info->gpio_bit, mode, flags); } + gpio_set_modef(info->gpio_device, info->gpio_bit, mode, flags); } -- cgit v1.2.3 From ff56b76d41a390ed193da180316690f6e2dcbb75 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Sun, 3 Jun 2012 00:02:10 -0400 Subject: STM32F2: Add timer_get_af(). Pull some code out of the F2 pinMode() into a utility function. This feels generally useful enough to be exposed to the users (it will, for example, make it easier to implement input capture in a clean way). Signed-off-by: Marti Bolivar --- libmaple/stm32f2/include/series/timer.h | 7 +++++ libmaple/stm32f2/timer.c | 45 +++++++++++++++++++++++++++++++++ wirish/stm32f2/wirish_digital.cpp | 32 +---------------------- 3 files changed, 53 insertions(+), 31 deletions(-) (limited to 'wirish/stm32f2/wirish_digital.cpp') diff --git a/libmaple/stm32f2/include/series/timer.h b/libmaple/stm32f2/include/series/timer.h index 0d959d0..ed473b4 100644 --- a/libmaple/stm32f2/include/series/timer.h +++ b/libmaple/stm32f2/include/series/timer.h @@ -34,6 +34,7 @@ #define _LIBMAPLE_STM32F2_TIMER_H_ #include +#include /* for gpio_af */ /* * Register maps and base pointers @@ -167,4 +168,10 @@ extern struct timer_dev *TIMER12; extern struct timer_dev *TIMER13; extern struct timer_dev *TIMER14; +/* + * Routines + */ + +gpio_af timer_get_af(struct timer_dev *dev); + #endif diff --git a/libmaple/stm32f2/timer.c b/libmaple/stm32f2/timer.c index 3f9a8d2..f644b16 100644 --- a/libmaple/stm32f2/timer.c +++ b/libmaple/stm32f2/timer.c @@ -114,6 +114,51 @@ void timer_foreach(void (*fn)(timer_dev*)) { fn(TIMER14); } +/** + * @brief Get the GPIO alternate function corresponding to a timer. + * + * For example, if dev is TIMER1, this function returns + * GPIO_AF_TIM_1_2. This is useful for e.g. using gpio_set_af() to set + * a pin's alternate function to a timer. + * + * Note that the timer gpio_afs are shared with other timers (and + * sometimes with CAN). For example, timers 1 and 2 both use + * GPIO_AF_TIM_1_2. Because of that, it can pay to e.g not point two + * timers at the same pin. + * + * @param dev Timer device, must not be TIMER6 or TIMER7. + * @return gpio_af corresponding to dev + * @see gpio_set_af + * @see gpio_af + */ +gpio_af timer_get_af(timer_dev *dev) { + rcc_clk_id clk_id = dev->clk_id; + /* Timers 6 and 7 don't have any capture/compare, so they can't do + * PWM (and in fact have no AF values). */ + ASSERT(clk_id != RCC_TIMER6 && clk_id != RCC_TIMER7); + switch(dev->clk_id) { + case RCC_TIMER1: // fall-through + case RCC_TIMER2: + return GPIO_AF_TIM_1_2; + case RCC_TIMER3: // fall-through + case RCC_TIMER4: // ... + case RCC_TIMER5: + return GPIO_AF_TIM_3_4_5; + case RCC_TIMER8: // fall-through + case RCC_TIMER9: // ... + case RCC_TIMER10: // ... + case RCC_TIMER11: + return GPIO_AF_TIM_8_9_10_11; + case RCC_TIMER12: // fall-through + case RCC_TIMER13: // ... + case RCC_TIMER14: + return GPIO_AF_CAN_1_2_TIM_12_13_14; + default: + ASSERT(0); // Can't happen + return (gpio_af)-1; + } +} + /* * IRQ handlers * diff --git a/wirish/stm32f2/wirish_digital.cpp b/wirish/stm32f2/wirish_digital.cpp index bf9dcf5..4d46f1c 100644 --- a/wirish/stm32f2/wirish_digital.cpp +++ b/wirish/stm32f2/wirish_digital.cpp @@ -91,37 +91,7 @@ void pinMode(uint8 pin, WiringPinMode w_mode) { if (info->timer_device == NULL) { return; } - gpio_af timer_af; - /* TODO make this code a convenience - * routine for series that support GPIO alternate - * functions. */ - switch(info->timer_device->clk_id) { - case RCC_TIMER1: // fall-through - case RCC_TIMER2: - timer_af = GPIO_AF_TIM_1_2; - break; - case RCC_TIMER3: // fall-through - case RCC_TIMER4: // ... - case RCC_TIMER5: - timer_af = GPIO_AF_TIM_3_4_5; - break; - /* Timers 6 and 7 don't have any capture/compare, so they - * can't do PWM (and in fact have no AF values). */ - case RCC_TIMER8: // fall-through - case RCC_TIMER9: // ... - case RCC_TIMER10: // ... - case RCC_TIMER11: - timer_af = GPIO_AF_TIM_8_9_10_11; - break; - case RCC_TIMER12: // fall-through - case RCC_TIMER13: // ... - case RCC_TIMER14: - timer_af = GPIO_AF_CAN_1_2_TIM_12_13_14; - break; - default: - ASSERT(0); // Can't happen - return; - } + gpio_af timer_af = timer_get_af(info->timer_device); timer_set_mode(info->timer_device, info->timer_channel, TIMER_PWM); gpio_set_af(info->gpio_device, info->gpio_bit, timer_af); } -- cgit v1.2.3