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 --- wirish/rules.mk | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'wirish/rules.mk') diff --git a/wirish/rules.mk b/wirish/rules.mk index 1bf6245..923c17b 100644 --- a/wirish/rules.mk +++ b/wirish/rules.mk @@ -4,9 +4,12 @@ dirstack_$(sp) := $(d) d := $(dir) BUILDDIRS += $(BUILD_PATH)/$(d) BUILDDIRS += $(BUILD_PATH)/$(d)/comm -BUILDDIRS += $(BUILD_PATH)/$(d)/boards -WIRISH_INCLUDES := -I$(d) -I$(d)/comm -I$(d)/boards +# Board config -- TODO allow user override +WIRISH_BOARD_PATH := boards/$(BOARD) +BUILDDIRS += $(BUILD_PATH)/$(d)/$(WIRISH_BOARD_PATH) + +WIRISH_INCLUDES := -I$(d)/include -I$(d)/$(WIRISH_BOARD_PATH)/include # Local flags CFLAGS_$(d) := $(WIRISH_INCLUDES) $(LIBMAPLE_INCLUDES) @@ -18,11 +21,6 @@ cSRCS_$(d) := start_c.c cppSRCS_$(d) := wirish_math.cpp \ Print.cpp \ boards.cpp \ - boards/maple.cpp \ - boards/maple_mini.cpp \ - boards/maple_native.cpp \ - boards/maple_RET6.cpp \ - boards/olimex_stm32_h103.cpp \ comm/HardwareSerial.cpp \ comm/HardwareSPI.cpp \ HardwareTimer.cpp \ @@ -34,6 +32,7 @@ cppSRCS_$(d) := wirish_math.cpp \ pwm.cpp \ ext_interrupts.cpp \ wirish_digital.cpp +cppSRCS_$(d) += $(WIRISH_BOARD_PATH)/board.cpp sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%) cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%) -- cgit v1.2.3 From cb2f3071fcd49590499888c27c8f325699eafda9 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Tue, 15 Nov 2011 16:05:12 -0500 Subject: Move wirish/comm/*.cpp into wirish. The wirish/comm/ directory is stupid. Signed-off-by: Marti Bolivar --- wirish/HardwareSPI.cpp | 319 +++++++++++++++++++++++++++++++++++++++++ wirish/HardwareSerial.cpp | 120 ++++++++++++++++ wirish/comm/HardwareSPI.cpp | 319 ----------------------------------------- wirish/comm/HardwareSerial.cpp | 120 ---------------- wirish/rules.mk | 5 +- 5 files changed, 441 insertions(+), 442 deletions(-) create mode 100644 wirish/HardwareSPI.cpp create mode 100644 wirish/HardwareSerial.cpp delete mode 100644 wirish/comm/HardwareSPI.cpp delete mode 100644 wirish/comm/HardwareSerial.cpp (limited to 'wirish/rules.mk') diff --git a/wirish/HardwareSPI.cpp b/wirish/HardwareSPI.cpp new file mode 100644 index 0000000..e1f186e --- /dev/null +++ b/wirish/HardwareSPI.cpp @@ -0,0 +1,319 @@ +/****************************************************************************** + * 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. + *****************************************************************************/ + +/** + * @author Marti Bolivar + * @brief Wirish SPI implementation. + */ + +#include + +#include +#include +#include + +#include +#include + +struct spi_pins { + uint8 nss; + uint8 sck; + uint8 miso; + uint8 mosi; +}; + +static const spi_pins* dev_to_spi_pins(spi_dev *dev); + +static void enable_device(spi_dev *dev, + bool as_master, + SPIFrequency frequency, + spi_cfg_flag endianness, + spi_mode mode); + +static const spi_pins board_spi_pins[] __FLASH__ = { + {BOARD_SPI1_NSS_PIN, + BOARD_SPI1_SCK_PIN, + BOARD_SPI1_MISO_PIN, + BOARD_SPI1_MOSI_PIN}, + {BOARD_SPI2_NSS_PIN, + BOARD_SPI2_SCK_PIN, + BOARD_SPI2_MISO_PIN, + BOARD_SPI2_MOSI_PIN}, +#ifdef STM32_HIGH_DENSITY + {BOARD_SPI3_NSS_PIN, + BOARD_SPI3_SCK_PIN, + BOARD_SPI3_MISO_PIN, + BOARD_SPI3_MOSI_PIN}, +#endif +}; + + +/* + * Constructor + */ + +HardwareSPI::HardwareSPI(uint32 spi_num) { + switch (spi_num) { + case 1: + this->spi_d = SPI1; + break; + case 2: + this->spi_d = SPI2; + break; +#ifdef STM32_HIGH_DENSITY + case 3: + this->spi_d = SPI3; + break; +#endif + default: + ASSERT(0); + } +} + +/* + * Set up/tear down + */ + +void HardwareSPI::begin(SPIFrequency frequency, uint32 bitOrder, uint32 mode) { + if (mode >= 4) { + ASSERT(0); + return; + } + spi_cfg_flag end = bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB; + spi_mode m = (spi_mode)mode; + enable_device(this->spi_d, true, frequency, end, m); +} + +void HardwareSPI::begin(void) { + this->begin(SPI_1_125MHZ, MSBFIRST, 0); +} + +void HardwareSPI::beginSlave(uint32 bitOrder, uint32 mode) { + if (mode >= 4) { + ASSERT(0); + return; + } + spi_cfg_flag end = bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB; + spi_mode m = (spi_mode)mode; + enable_device(this->spi_d, false, (SPIFrequency)0, end, m); +} + +void HardwareSPI::beginSlave(void) { + this->beginSlave(MSBFIRST, 0); +} + +void HardwareSPI::end(void) { + if (!spi_is_enabled(this->spi_d)) { + return; + } + + // Follows RM0008's sequence for disabling a SPI in master/slave + // full duplex mode. + while (spi_is_rx_nonempty(this->spi_d)) { + // FIXME [0.1.0] remove this once you have an interrupt based driver + volatile uint16 rx __attribute__((unused)) = spi_rx_reg(this->spi_d); + } + while (!spi_is_tx_empty(this->spi_d)) + ; + while (spi_is_busy(this->spi_d)) + ; + spi_peripheral_disable(this->spi_d); +} + +/* + * I/O + */ + +uint8 HardwareSPI::read(void) { + uint8 buf[1]; + this->read(buf, 1); + return buf[0]; +} + +void HardwareSPI::read(uint8 *buf, uint32 len) { + uint32 rxed = 0; + while (rxed < len) { + while (!spi_is_rx_nonempty(this->spi_d)) + ; + buf[rxed++] = (uint8)spi_rx_reg(this->spi_d); + } +} + +void HardwareSPI::write(uint8 byte) { + this->write(&byte, 1); +} + +void HardwareSPI::write(const uint8 *data, uint32 length) { + uint32 txed = 0; + while (txed < length) { + txed += spi_tx(this->spi_d, data + txed, length - txed); + } +} + +uint8 HardwareSPI::transfer(uint8 byte) { + this->write(byte); + return this->read(); +} + +/* + * Pin accessors + */ + +uint8 HardwareSPI::misoPin(void) { + return dev_to_spi_pins(this->spi_d)->miso; +} + +uint8 HardwareSPI::mosiPin(void) { + return dev_to_spi_pins(this->spi_d)->mosi; +} + +uint8 HardwareSPI::sckPin(void) { + return dev_to_spi_pins(this->spi_d)->sck; +} + +uint8 HardwareSPI::nssPin(void) { + return dev_to_spi_pins(this->spi_d)->nss; +} + +/* + * Deprecated functions + */ + +uint8 HardwareSPI::send(uint8 data) { + uint8 buf[] = {data}; + return this->send(buf, 1); +} + +uint8 HardwareSPI::send(uint8 *buf, uint32 len) { + uint32 txed = 0; + uint8 ret = 0; + while (txed < len) { + this->write(buf[txed++]); + ret = this->read(); + } + return ret; +} + +uint8 HardwareSPI::recv(void) { + return this->read(); +} + +/* + * Auxiliary functions + */ + +static void configure_gpios(spi_dev *dev, bool as_master); +static spi_baud_rate determine_baud_rate(spi_dev *dev, SPIFrequency freq); + +static const spi_pins* dev_to_spi_pins(spi_dev *dev) { + switch (dev->clk_id) { + case RCC_SPI1: return board_spi_pins; + case RCC_SPI2: return board_spi_pins + 1; +#ifdef STM32_HIGH_DENSITY + case RCC_SPI3: return board_spi_pins + 2; +#endif + default: return NULL; + } +} + +/* Enables the device in master or slave full duplex mode. If you + * change this code, you must ensure that appropriate changes are made + * to HardwareSPI::end(). */ +static void enable_device(spi_dev *dev, + bool as_master, + SPIFrequency freq, + spi_cfg_flag endianness, + spi_mode mode) { + spi_baud_rate baud = determine_baud_rate(dev, freq); + uint32 cfg_flags = (endianness | SPI_DFF_8_BIT | SPI_SW_SLAVE | + (as_master ? SPI_SOFT_SS : 0)); + + spi_init(dev); + configure_gpios(dev, as_master); + if (as_master) { + spi_master_enable(dev, baud, mode, cfg_flags); + } else { + spi_slave_enable(dev, mode, cfg_flags); + } +} + +static void disable_pwm(const stm32_pin_info *i) { + if (i->timer_device) { + timer_set_mode(i->timer_device, i->timer_channel, TIMER_DISABLED); + } +} + +static void configure_gpios(spi_dev *dev, bool as_master) { + const spi_pins *pins = dev_to_spi_pins(dev); + + if (!pins) { + return; + } + + const stm32_pin_info *nssi = &PIN_MAP[pins->nss]; + const stm32_pin_info *scki = &PIN_MAP[pins->sck]; + const stm32_pin_info *misoi = &PIN_MAP[pins->miso]; + const stm32_pin_info *mosii = &PIN_MAP[pins->mosi]; + + disable_pwm(nssi); + disable_pwm(scki); + disable_pwm(misoi); + disable_pwm(mosii); + + spi_gpio_cfg(as_master, + nssi->gpio_device, + nssi->gpio_bit, + scki->gpio_device, + scki->gpio_bit, + misoi->gpio_bit, + mosii->gpio_bit); +} + +static const spi_baud_rate baud_rates[MAX_SPI_FREQS] __FLASH__ = { + SPI_BAUD_PCLK_DIV_2, + SPI_BAUD_PCLK_DIV_4, + SPI_BAUD_PCLK_DIV_8, + SPI_BAUD_PCLK_DIV_16, + SPI_BAUD_PCLK_DIV_32, + SPI_BAUD_PCLK_DIV_64, + SPI_BAUD_PCLK_DIV_128, + SPI_BAUD_PCLK_DIV_256, +}; + +/* + * Note: This assumes you're on a LeafLabs-style board + * (CYCLES_PER_MICROSECOND == 72, APB2 at 72MHz, APB1 at 36MHz). + */ +static spi_baud_rate determine_baud_rate(spi_dev *dev, SPIFrequency freq) { + if (rcc_dev_clk(dev->clk_id) == RCC_APB2 && freq == SPI_140_625KHZ) { + /* APB2 peripherals are too fast for 140.625 KHz */ + ASSERT(0); + return (spi_baud_rate)~0; + } + return (rcc_dev_clk(dev->clk_id) == RCC_APB2 ? + baud_rates[freq + 1] : + baud_rates[freq]); +} diff --git a/wirish/HardwareSerial.cpp b/wirish/HardwareSerial.cpp new file mode 100644 index 0000000..a9eb763 --- /dev/null +++ b/wirish/HardwareSerial.cpp @@ -0,0 +1,120 @@ +/****************************************************************************** + * 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 HardwareSerial.cpp + * @brief Wirish serial port implementation. + */ + +#include + +#include +#include +#include + +#include + +#define TX1 BOARD_USART1_TX_PIN +#define RX1 BOARD_USART1_RX_PIN +#define TX2 BOARD_USART2_TX_PIN +#define RX2 BOARD_USART2_RX_PIN +#define TX3 BOARD_USART3_TX_PIN +#define RX3 BOARD_USART3_RX_PIN +#if defined STM32_HIGH_DENSITY && !defined(BOARD_maple_RET6) +#define TX4 BOARD_UART4_TX_PIN +#define RX4 BOARD_UART4_RX_PIN +#define TX5 BOARD_UART5_TX_PIN +#define RX5 BOARD_UART5_RX_PIN +#endif + +HardwareSerial Serial1(USART1, TX1, RX1, STM32_PCLK2); +HardwareSerial Serial2(USART2, TX2, RX2, STM32_PCLK1); +HardwareSerial Serial3(USART3, TX3, RX3, STM32_PCLK1); +#if defined(STM32_HIGH_DENSITY) && !defined(BOARD_maple_RET6) +HardwareSerial Serial4(UART4, TX4, RX4, STM32_PCLK1); +HardwareSerial Serial5(UART5, TX5, RX5, STM32_PCLK1); +#endif + +HardwareSerial::HardwareSerial(usart_dev *usart_device, + uint8 tx_pin, + uint8 rx_pin, + uint32 clock_speed) { + this->usart_device = usart_device; + this->clock_speed = clock_speed; + this->tx_pin = tx_pin; + this->rx_pin = rx_pin; +} + +/* + * Set up/tear down + */ + +void HardwareSerial::begin(uint32 baud) { + ASSERT(baud <= usart_device->max_baud); + + if (baud > usart_device->max_baud) { + return; + } + + const stm32_pin_info *txi = &PIN_MAP[tx_pin]; + const stm32_pin_info *rxi = &PIN_MAP[rx_pin]; + + gpio_set_mode(txi->gpio_device, txi->gpio_bit, GPIO_AF_OUTPUT_PP); + gpio_set_mode(rxi->gpio_device, rxi->gpio_bit, GPIO_INPUT_FLOATING); + + if (txi->timer_device != NULL) { + /* Turn off any PWM if there's a conflict on this GPIO bit. */ + timer_set_mode(txi->timer_device, txi->timer_channel, TIMER_DISABLED); + } + + usart_init(usart_device); + usart_set_baud_rate(usart_device, clock_speed, baud); + usart_enable(usart_device); +} + +void HardwareSerial::end(void) { + usart_disable(usart_device); +} + +/* + * I/O + */ + +uint8 HardwareSerial::read(void) { + return usart_getc(usart_device); +} + +uint32 HardwareSerial::available(void) { + return usart_data_available(usart_device); +} + +void HardwareSerial::write(unsigned char ch) { + usart_putc(usart_device, ch); +} + +void HardwareSerial::flush(void) { + usart_reset_rx(usart_device); +} diff --git a/wirish/comm/HardwareSPI.cpp b/wirish/comm/HardwareSPI.cpp deleted file mode 100644 index e1f186e..0000000 --- a/wirish/comm/HardwareSPI.cpp +++ /dev/null @@ -1,319 +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. - *****************************************************************************/ - -/** - * @author Marti Bolivar - * @brief Wirish SPI implementation. - */ - -#include - -#include -#include -#include - -#include -#include - -struct spi_pins { - uint8 nss; - uint8 sck; - uint8 miso; - uint8 mosi; -}; - -static const spi_pins* dev_to_spi_pins(spi_dev *dev); - -static void enable_device(spi_dev *dev, - bool as_master, - SPIFrequency frequency, - spi_cfg_flag endianness, - spi_mode mode); - -static const spi_pins board_spi_pins[] __FLASH__ = { - {BOARD_SPI1_NSS_PIN, - BOARD_SPI1_SCK_PIN, - BOARD_SPI1_MISO_PIN, - BOARD_SPI1_MOSI_PIN}, - {BOARD_SPI2_NSS_PIN, - BOARD_SPI2_SCK_PIN, - BOARD_SPI2_MISO_PIN, - BOARD_SPI2_MOSI_PIN}, -#ifdef STM32_HIGH_DENSITY - {BOARD_SPI3_NSS_PIN, - BOARD_SPI3_SCK_PIN, - BOARD_SPI3_MISO_PIN, - BOARD_SPI3_MOSI_PIN}, -#endif -}; - - -/* - * Constructor - */ - -HardwareSPI::HardwareSPI(uint32 spi_num) { - switch (spi_num) { - case 1: - this->spi_d = SPI1; - break; - case 2: - this->spi_d = SPI2; - break; -#ifdef STM32_HIGH_DENSITY - case 3: - this->spi_d = SPI3; - break; -#endif - default: - ASSERT(0); - } -} - -/* - * Set up/tear down - */ - -void HardwareSPI::begin(SPIFrequency frequency, uint32 bitOrder, uint32 mode) { - if (mode >= 4) { - ASSERT(0); - return; - } - spi_cfg_flag end = bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB; - spi_mode m = (spi_mode)mode; - enable_device(this->spi_d, true, frequency, end, m); -} - -void HardwareSPI::begin(void) { - this->begin(SPI_1_125MHZ, MSBFIRST, 0); -} - -void HardwareSPI::beginSlave(uint32 bitOrder, uint32 mode) { - if (mode >= 4) { - ASSERT(0); - return; - } - spi_cfg_flag end = bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB; - spi_mode m = (spi_mode)mode; - enable_device(this->spi_d, false, (SPIFrequency)0, end, m); -} - -void HardwareSPI::beginSlave(void) { - this->beginSlave(MSBFIRST, 0); -} - -void HardwareSPI::end(void) { - if (!spi_is_enabled(this->spi_d)) { - return; - } - - // Follows RM0008's sequence for disabling a SPI in master/slave - // full duplex mode. - while (spi_is_rx_nonempty(this->spi_d)) { - // FIXME [0.1.0] remove this once you have an interrupt based driver - volatile uint16 rx __attribute__((unused)) = spi_rx_reg(this->spi_d); - } - while (!spi_is_tx_empty(this->spi_d)) - ; - while (spi_is_busy(this->spi_d)) - ; - spi_peripheral_disable(this->spi_d); -} - -/* - * I/O - */ - -uint8 HardwareSPI::read(void) { - uint8 buf[1]; - this->read(buf, 1); - return buf[0]; -} - -void HardwareSPI::read(uint8 *buf, uint32 len) { - uint32 rxed = 0; - while (rxed < len) { - while (!spi_is_rx_nonempty(this->spi_d)) - ; - buf[rxed++] = (uint8)spi_rx_reg(this->spi_d); - } -} - -void HardwareSPI::write(uint8 byte) { - this->write(&byte, 1); -} - -void HardwareSPI::write(const uint8 *data, uint32 length) { - uint32 txed = 0; - while (txed < length) { - txed += spi_tx(this->spi_d, data + txed, length - txed); - } -} - -uint8 HardwareSPI::transfer(uint8 byte) { - this->write(byte); - return this->read(); -} - -/* - * Pin accessors - */ - -uint8 HardwareSPI::misoPin(void) { - return dev_to_spi_pins(this->spi_d)->miso; -} - -uint8 HardwareSPI::mosiPin(void) { - return dev_to_spi_pins(this->spi_d)->mosi; -} - -uint8 HardwareSPI::sckPin(void) { - return dev_to_spi_pins(this->spi_d)->sck; -} - -uint8 HardwareSPI::nssPin(void) { - return dev_to_spi_pins(this->spi_d)->nss; -} - -/* - * Deprecated functions - */ - -uint8 HardwareSPI::send(uint8 data) { - uint8 buf[] = {data}; - return this->send(buf, 1); -} - -uint8 HardwareSPI::send(uint8 *buf, uint32 len) { - uint32 txed = 0; - uint8 ret = 0; - while (txed < len) { - this->write(buf[txed++]); - ret = this->read(); - } - return ret; -} - -uint8 HardwareSPI::recv(void) { - return this->read(); -} - -/* - * Auxiliary functions - */ - -static void configure_gpios(spi_dev *dev, bool as_master); -static spi_baud_rate determine_baud_rate(spi_dev *dev, SPIFrequency freq); - -static const spi_pins* dev_to_spi_pins(spi_dev *dev) { - switch (dev->clk_id) { - case RCC_SPI1: return board_spi_pins; - case RCC_SPI2: return board_spi_pins + 1; -#ifdef STM32_HIGH_DENSITY - case RCC_SPI3: return board_spi_pins + 2; -#endif - default: return NULL; - } -} - -/* Enables the device in master or slave full duplex mode. If you - * change this code, you must ensure that appropriate changes are made - * to HardwareSPI::end(). */ -static void enable_device(spi_dev *dev, - bool as_master, - SPIFrequency freq, - spi_cfg_flag endianness, - spi_mode mode) { - spi_baud_rate baud = determine_baud_rate(dev, freq); - uint32 cfg_flags = (endianness | SPI_DFF_8_BIT | SPI_SW_SLAVE | - (as_master ? SPI_SOFT_SS : 0)); - - spi_init(dev); - configure_gpios(dev, as_master); - if (as_master) { - spi_master_enable(dev, baud, mode, cfg_flags); - } else { - spi_slave_enable(dev, mode, cfg_flags); - } -} - -static void disable_pwm(const stm32_pin_info *i) { - if (i->timer_device) { - timer_set_mode(i->timer_device, i->timer_channel, TIMER_DISABLED); - } -} - -static void configure_gpios(spi_dev *dev, bool as_master) { - const spi_pins *pins = dev_to_spi_pins(dev); - - if (!pins) { - return; - } - - const stm32_pin_info *nssi = &PIN_MAP[pins->nss]; - const stm32_pin_info *scki = &PIN_MAP[pins->sck]; - const stm32_pin_info *misoi = &PIN_MAP[pins->miso]; - const stm32_pin_info *mosii = &PIN_MAP[pins->mosi]; - - disable_pwm(nssi); - disable_pwm(scki); - disable_pwm(misoi); - disable_pwm(mosii); - - spi_gpio_cfg(as_master, - nssi->gpio_device, - nssi->gpio_bit, - scki->gpio_device, - scki->gpio_bit, - misoi->gpio_bit, - mosii->gpio_bit); -} - -static const spi_baud_rate baud_rates[MAX_SPI_FREQS] __FLASH__ = { - SPI_BAUD_PCLK_DIV_2, - SPI_BAUD_PCLK_DIV_4, - SPI_BAUD_PCLK_DIV_8, - SPI_BAUD_PCLK_DIV_16, - SPI_BAUD_PCLK_DIV_32, - SPI_BAUD_PCLK_DIV_64, - SPI_BAUD_PCLK_DIV_128, - SPI_BAUD_PCLK_DIV_256, -}; - -/* - * Note: This assumes you're on a LeafLabs-style board - * (CYCLES_PER_MICROSECOND == 72, APB2 at 72MHz, APB1 at 36MHz). - */ -static spi_baud_rate determine_baud_rate(spi_dev *dev, SPIFrequency freq) { - if (rcc_dev_clk(dev->clk_id) == RCC_APB2 && freq == SPI_140_625KHZ) { - /* APB2 peripherals are too fast for 140.625 KHz */ - ASSERT(0); - return (spi_baud_rate)~0; - } - return (rcc_dev_clk(dev->clk_id) == RCC_APB2 ? - baud_rates[freq + 1] : - baud_rates[freq]); -} diff --git a/wirish/comm/HardwareSerial.cpp b/wirish/comm/HardwareSerial.cpp deleted file mode 100644 index a9eb763..0000000 --- a/wirish/comm/HardwareSerial.cpp +++ /dev/null @@ -1,120 +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 HardwareSerial.cpp - * @brief Wirish serial port implementation. - */ - -#include - -#include -#include -#include - -#include - -#define TX1 BOARD_USART1_TX_PIN -#define RX1 BOARD_USART1_RX_PIN -#define TX2 BOARD_USART2_TX_PIN -#define RX2 BOARD_USART2_RX_PIN -#define TX3 BOARD_USART3_TX_PIN -#define RX3 BOARD_USART3_RX_PIN -#if defined STM32_HIGH_DENSITY && !defined(BOARD_maple_RET6) -#define TX4 BOARD_UART4_TX_PIN -#define RX4 BOARD_UART4_RX_PIN -#define TX5 BOARD_UART5_TX_PIN -#define RX5 BOARD_UART5_RX_PIN -#endif - -HardwareSerial Serial1(USART1, TX1, RX1, STM32_PCLK2); -HardwareSerial Serial2(USART2, TX2, RX2, STM32_PCLK1); -HardwareSerial Serial3(USART3, TX3, RX3, STM32_PCLK1); -#if defined(STM32_HIGH_DENSITY) && !defined(BOARD_maple_RET6) -HardwareSerial Serial4(UART4, TX4, RX4, STM32_PCLK1); -HardwareSerial Serial5(UART5, TX5, RX5, STM32_PCLK1); -#endif - -HardwareSerial::HardwareSerial(usart_dev *usart_device, - uint8 tx_pin, - uint8 rx_pin, - uint32 clock_speed) { - this->usart_device = usart_device; - this->clock_speed = clock_speed; - this->tx_pin = tx_pin; - this->rx_pin = rx_pin; -} - -/* - * Set up/tear down - */ - -void HardwareSerial::begin(uint32 baud) { - ASSERT(baud <= usart_device->max_baud); - - if (baud > usart_device->max_baud) { - return; - } - - const stm32_pin_info *txi = &PIN_MAP[tx_pin]; - const stm32_pin_info *rxi = &PIN_MAP[rx_pin]; - - gpio_set_mode(txi->gpio_device, txi->gpio_bit, GPIO_AF_OUTPUT_PP); - gpio_set_mode(rxi->gpio_device, rxi->gpio_bit, GPIO_INPUT_FLOATING); - - if (txi->timer_device != NULL) { - /* Turn off any PWM if there's a conflict on this GPIO bit. */ - timer_set_mode(txi->timer_device, txi->timer_channel, TIMER_DISABLED); - } - - usart_init(usart_device); - usart_set_baud_rate(usart_device, clock_speed, baud); - usart_enable(usart_device); -} - -void HardwareSerial::end(void) { - usart_disable(usart_device); -} - -/* - * I/O - */ - -uint8 HardwareSerial::read(void) { - return usart_getc(usart_device); -} - -uint32 HardwareSerial::available(void) { - return usart_data_available(usart_device); -} - -void HardwareSerial::write(unsigned char ch) { - usart_putc(usart_device, ch); -} - -void HardwareSerial::flush(void) { - usart_reset_rx(usart_device); -} diff --git a/wirish/rules.mk b/wirish/rules.mk index 923c17b..6fa3a28 100644 --- a/wirish/rules.mk +++ b/wirish/rules.mk @@ -3,7 +3,6 @@ sp := $(sp).x dirstack_$(sp) := $(d) d := $(dir) BUILDDIRS += $(BUILD_PATH)/$(d) -BUILDDIRS += $(BUILD_PATH)/$(d)/comm # Board config -- TODO allow user override WIRISH_BOARD_PATH := boards/$(BOARD) @@ -21,8 +20,8 @@ cSRCS_$(d) := start_c.c cppSRCS_$(d) := wirish_math.cpp \ Print.cpp \ boards.cpp \ - comm/HardwareSerial.cpp \ - comm/HardwareSPI.cpp \ + HardwareSerial.cpp \ + HardwareSPI.cpp \ HardwareTimer.cpp \ usb_serial.cpp \ cxxabi-compat.cpp \ -- cgit v1.2.3 From 2ab2f4d3784692f8cd0e79d24638157926f894ca Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Mon, 21 Nov 2011 17:22:38 -0500 Subject: [UNDO] Rip out everything but libmaple and Wirish startup code. We'll need to bring all this functionality back online piecemeal as we add F2 support. Signed-off-by: Marti Bolivar --- Makefile | 8 ++++---- wirish/rules.mk | 38 +++++++++++++++++++------------------- 2 files changed, 23 insertions(+), 23 deletions(-) (limited to 'wirish/rules.mk') diff --git a/Makefile b/Makefile index 9b37580..785b9a6 100644 --- a/Makefile +++ b/Makefile @@ -79,12 +79,12 @@ LIBMAPLE_MODULES += $(SRCROOT)/libmaple/usb # USB FS device LIBMAPLE_MODULES += $(LIBMAPLE_MODULE_SERIES) # STM32 series submodule in libmaple LIBMAPLE_MODULES += $(SRCROOT)/wirish # Official libraries: -LIBMAPLE_MODULES += $(SRCROOT)/libraries/Servo -LIBMAPLE_MODULES += $(SRCROOT)/libraries/LiquidCrystal -LIBMAPLE_MODULES += $(SRCROOT)/libraries/Wire +# LIBMAPLE_MODULES += $(SRCROOT)/libraries/Servo +# LIBMAPLE_MODULES += $(SRCROOT)/libraries/LiquidCrystal +# LIBMAPLE_MODULES += $(SRCROOT)/libraries/Wire # Experimental libraries: -LIBMAPLE_MODULES += $(SRCROOT)/libraries/FreeRTOS +# LIBMAPLE_MODULES += $(SRCROOT)/libraries/FreeRTOS # Call each module's rules.mk: $(foreach m,$(LIBMAPLE_MODULES),$(eval $(call LIBMAPLE_MODULE_template,$(m)))) diff --git a/wirish/rules.mk b/wirish/rules.mk index 6fa3a28..c72e60f 100644 --- a/wirish/rules.mk +++ b/wirish/rules.mk @@ -5,33 +5,33 @@ d := $(dir) BUILDDIRS += $(BUILD_PATH)/$(d) # Board config -- TODO allow user override -WIRISH_BOARD_PATH := boards/$(BOARD) -BUILDDIRS += $(BUILD_PATH)/$(d)/$(WIRISH_BOARD_PATH) +# WIRISH_BOARD_PATH := boards/$(BOARD) +# BUILDDIRS += $(BUILD_PATH)/$(d)/$(WIRISH_BOARD_PATH) -WIRISH_INCLUDES := -I$(d)/include -I$(d)/$(WIRISH_BOARD_PATH)/include +# WIRISH_INCLUDES := -I$(d)/include -I$(d)/$(WIRISH_BOARD_PATH)/include # Local flags -CFLAGS_$(d) := $(WIRISH_INCLUDES) $(LIBMAPLE_INCLUDES) +CFLAGS_$(d) := $(LIBMAPLE_INCLUDES) # Local rules and targets sSRCS_$(d) := start.S cSRCS_$(d) := start_c.c -cppSRCS_$(d) := wirish_math.cpp \ - Print.cpp \ - boards.cpp \ - HardwareSerial.cpp \ - HardwareSPI.cpp \ - HardwareTimer.cpp \ - usb_serial.cpp \ - cxxabi-compat.cpp \ - wirish_shift.cpp \ - wirish_analog.cpp \ - wirish_time.cpp \ - pwm.cpp \ - ext_interrupts.cpp \ - wirish_digital.cpp -cppSRCS_$(d) += $(WIRISH_BOARD_PATH)/board.cpp +# cppSRCS_$(d) := wirish_math.cpp \ +# Print.cpp \ +# boards.cpp \ +# HardwareSerial.cpp \ +# HardwareSPI.cpp \ +# HardwareTimer.cpp \ +# usb_serial.cpp \ +# cxxabi-compat.cpp \ +# wirish_shift.cpp \ +# wirish_analog.cpp \ +# wirish_time.cpp \ +# pwm.cpp \ +# ext_interrupts.cpp \ +# wirish_digital.cpp +# cppSRCS_$(d) += $(WIRISH_BOARD_PATH)/board.cpp sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%) cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%) -- cgit v1.2.3 From 21468a69ca2e7ff9a5c7ffc03c608a24f1412d64 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Tue, 20 Mar 2012 17:44:34 -0400 Subject: [FIXME] Resurrect boards.cpp for F2 and F1. FIXME: - F1 support currently appears to be failing in start_c.c, for some unknown reason. This will need to get sorted out later. Add a new wirish namespace, and a sub-namespace wirish::priv::. Put a bunch of board setup routines in this namespace, and declare them in new wirish/boards_private.h. boards.cpp uses this to perform initialization tasks in a portable way, with two new boards_setup.cpp files under wirish/stm32f1 and wirish/stm32f2 handling the series-specific details. Signed-off-by: Marti Bolivar --- wirish/boards.cpp | 167 ++++++++++++++++++---------------------- wirish/boards_private.h | 59 ++++++++++++++ wirish/include/wirish/boards.h | 5 -- wirish/rules.mk | 22 ++++-- wirish/stm32f1/boards_setup.cpp | 141 +++++++++++++++++++++++++++++++++ wirish/stm32f2/boards_setup.cpp | 75 ++++++++++++++++++ 6 files changed, 363 insertions(+), 106 deletions(-) create mode 100644 wirish/boards_private.h create mode 100644 wirish/stm32f1/boards_setup.cpp create mode 100644 wirish/stm32f2/boards_setup.cpp (limited to 'wirish/rules.mk') diff --git a/wirish/boards.cpp b/wirish/boards.cpp index 5d5ecb5..7d783db 100644 --- a/wirish/boards.cpp +++ b/wirish/boards.cpp @@ -25,49 +25,55 @@ *****************************************************************************/ /** - * @brief Generic board initialization routines. + * @file boards.cpp + * @brief Generic board routines. * * This file is mostly interesting for the init() function, which * configures Flash, the core sytem clocks, and a variety of other * available peripherals on the board so the rest of Wirish doesn't * have to turn things on before using them. * - * Prior to returning, init() calls boardInit(), which allows boards - * to perform any initialization they need to. + * How init() does this is chip-specific. See the chip-specific pieces + * of Wirish (under e.g. wirish/stm32f1/, wirish/stmf32f2) for + * details. * - * Specifically how init() works varies across boards and MCUs. + * Finally, prior to returning, init() calls boardInit(), which allows + * boards to perform any initialization they need to. This file + * includes a weak no-op definition of boardInit(), so boards that + * don't need any special initialization don't have to define their + * own. */ #include - #include -#include #include #include -#include -#include -#include -#include +#include "boards_private.h" + +static void setup_flash(void); +static void setup_clocks(void); +static void setup_nvic(void); -static void setupFlash(void); -static void setupClocks(void); -static void setupNVIC(void); -static void setupADC(void); -static void setupTimers(void); +/* + * Exported functions + */ void init(void) { - setupFlash(); - setupClocks(); - setupNVIC(); + setup_flash(); + setup_clocks(); + setup_nvic(); systick_init(SYSTICK_RELOAD_VAL); - gpio_init_all(); - afio_init(); - setupADC(); - setupTimers(); - usb_cdcacm_enable(BOARD_USB_DISC_DEV, BOARD_USB_DISC_BIT); + wirish::priv::board_setup_gpio(); + wirish::priv::board_setup_adc(); + wirish::priv::board_setup_timers(); + wirish::priv::board_setup_usb(); boardInit(); } +/* Provide a default boardInit(). */ +__attribute__((weak)) void boardInit(void) { +} + /* You could farm this out to the files in boards/ if e.g. it takes * too long to test on Maple Native (all those FSMC pins...). */ bool boardUsesPin(uint8 pin) { @@ -79,24 +85,56 @@ bool boardUsesPin(uint8 pin) { return false; } -static void setupFlash(void) { - flash_enable_prefetch(); +/* + * Auxiliary routines + */ + +static void setup_flash(void) { + // Turn on as many Flash "go faster" features as + // possible. flash_enable_features() just ignores any flags it + // can't support. + flash_enable_features(FLASH_PREFETCH | FLASH_ICACHE | FLASH_DCACHE); + // Configure the wait states, assuming we're operating at "close + // enough" to 3.3V. flash_set_latency(FLASH_SAFE_WAIT_STATES); } -/* - * Clock setup. Note that some of this only takes effect if we're - * running bare metal and the bootloader hasn't done it for us - * already. - */ -static void setupClocks() { - rcc_clk_init(RCC_CLKSRC_PLL, RCC_PLLSRC_HSE, RCC_PLLMUL_9); - rcc_set_prescaler(RCC_PRESCALER_AHB, RCC_AHB_SYSCLK_DIV_1); - rcc_set_prescaler(RCC_PRESCALER_APB1, RCC_APB1_HCLK_DIV_2); - rcc_set_prescaler(RCC_PRESCALER_APB2, RCC_APB2_HCLK_DIV_1); +static void setup_clocks(void) { + // Turn on HSI. We'll switch to and run off of this while we're + // setting up the main PLL. + rcc_turn_on_clk(RCC_CLK_HSI); + + // Turn off and reset the clock subsystems we'll be using, as well + // as the clock security subsystem (CSS). Note that resetting CFGR + // to its default value of 0 implies a switch to HSI for SYSCLK. + RCC_BASE->CFGR = 0x00000000; + rcc_disable_css(); + rcc_turn_off_clk(RCC_CLK_PLL); + rcc_turn_off_clk(RCC_CLK_HSE); + wirish::priv::board_reset_pll(); + // Clear clock readiness interrupt flags and turn off clock + // readiness interrupts. + RCC_BASE->CIR = 0x00000000; + + // Enable HSE, and wait until it's ready. + rcc_turn_on_clk(RCC_CLK_HSE); + while (!rcc_is_clk_ready(RCC_CLK_HSE)) + ; + + // Configure AHBx, APBx, etc. prescalers and the main PLL. + wirish::priv::board_setup_clock_prescalers(); + rcc_configure_pll(&wirish::priv::board_pll_cfg); + + // Enable the PLL, and wait until it's ready. + rcc_turn_on_clk(RCC_CLK_PLL); + while(!rcc_is_clk_ready(RCC_CLK_PLL)) + ; + + // Finally, switch to the now-ready PLL as the main clock source. + rcc_switch_sysclk(RCC_CLKSRC_PLL); } -static void setupNVIC() { +static void setup_nvic(void) { #ifdef VECT_TAB_FLASH nvic_init(USER_ADDR_ROM, 0); #elif defined VECT_TAB_RAM @@ -107,60 +145,3 @@ static void setupNVIC() { #error "You must select a base address for the vector table." #endif } - -static void adcDefaultConfig(const adc_dev* dev); - -static void setupADC() { - rcc_set_prescaler(RCC_PRESCALER_ADC, RCC_ADCPRE_PCLK_DIV_6); - adc_foreach(adcDefaultConfig); -} - -static void timerDefaultConfig(timer_dev*); - -static void setupTimers() { - timer_foreach(timerDefaultConfig); -} - -static void adcDefaultConfig(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 timerDefaultConfig(timer_dev *dev) { - timer_adv_reg_map *regs = (dev->regs).adv; - const uint16 full_overflow = 0xFFFF; - const uint16 half_duty = 0x8FFF; - - timer_init(dev); - timer_pause(dev); - - regs->CR1 = TIMER_CR1_ARPE; - regs->PSC = 1; - regs->SR = 0; - regs->DIER = 0; - regs->EGR = TIMER_EGR_UG; - - switch (dev->type) { - case TIMER_ADVANCED: - regs->BDTR = TIMER_BDTR_MOE | TIMER_BDTR_LOCK_OFF; - // fall-through - case TIMER_GENERAL: - timer_set_reload(dev, full_overflow); - - for (int channel = 1; channel <= 4; channel++) { - timer_set_compare(dev, channel, half_duty); - timer_oc_set_mode(dev, channel, TIMER_OC_MODE_PWM_1, TIMER_OC_PE); - } - // fall-through - case TIMER_BASIC: - break; - } - - timer_resume(dev); -} diff --git a/wirish/boards_private.h b/wirish/boards_private.h new file mode 100644 index 0000000..a4101c9 --- /dev/null +++ b/wirish/boards_private.h @@ -0,0 +1,59 @@ +/****************************************************************************** + * 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 wirish/boards_private.h + * @author Marti Bolivar + * @brief Private board support header. + */ + +#ifndef _WIRISH_BOARDS_PRIVATE_H_ +#define _WIRISH_BOARDS_PRIVATE_H_ + +namespace wirish { + namespace priv { + + /* + * Chip-specific initialization data + */ + + extern rcc_pll_cfg board_pll_cfg; + + /* + * Chip-specific initialization routines and helper functions. + */ + + 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); + + } +} + +#endif diff --git a/wirish/include/wirish/boards.h b/wirish/include/wirish/boards.h index e708f79..c762542 100644 --- a/wirish/include/wirish/boards.h +++ b/wirish/include/wirish/boards.h @@ -29,11 +29,6 @@ * @author Bryan Newbold , * Marti Bolivar * @brief Board-specific pin information. - * - * To add a new board type, add a new pair of files to - * /wirish/boards/, update the section below with a new "BOARD" type, - * and update /wirish/rules.mk to include your boards/your_board.cpp - * file in the top-level Makefile build. */ #ifndef _WIRISH_BOARDS_H_ diff --git a/wirish/rules.mk b/wirish/rules.mk index c72e60f..17c4d05 100644 --- a/wirish/rules.mk +++ b/wirish/rules.mk @@ -4,22 +4,26 @@ dirstack_$(sp) := $(d) d := $(dir) BUILDDIRS += $(BUILD_PATH)/$(d) -# Board config -- TODO allow user override -# WIRISH_BOARD_PATH := boards/$(BOARD) -# BUILDDIRS += $(BUILD_PATH)/$(d)/$(WIRISH_BOARD_PATH) +# Add board directory and MCU-specific directory to BUILDDIRS. These +# are in subdirectories, but they're logically part of the Wirish +# submodule. +WIRISH_BOARD_PATH := boards/$(BOARD) +BUILDDIRS += $(BUILD_PATH)/$(d)/$(WIRISH_BOARD_PATH) +BUILDDIRS += $(BUILD_PATH)/$(d)/$(MCU_SERIES) -# WIRISH_INCLUDES := -I$(d)/include -I$(d)/$(WIRISH_BOARD_PATH)/include +# Safe includes for Wirish. +WIRISH_INCLUDES := -I$(d)/include -I$(d)/$(WIRISH_BOARD_PATH)/include -# Local flags -CFLAGS_$(d) := $(LIBMAPLE_INCLUDES) +# Local flags. Add -I$(d) to allow for private includes. +CFLAGS_$(d) := $(LIBMAPLE_INCLUDES) $(WIRISH_INCLUDES) -I$(d) # Local rules and targets - sSRCS_$(d) := start.S cSRCS_$(d) := start_c.c +cppSRCS_$(d) := boards.cpp +# TODO: test these on F2 and put them back in: # cppSRCS_$(d) := wirish_math.cpp \ # Print.cpp \ -# boards.cpp \ # HardwareSerial.cpp \ # HardwareSPI.cpp \ # HardwareTimer.cpp \ @@ -31,7 +35,9 @@ cSRCS_$(d) := start_c.c # pwm.cpp \ # ext_interrupts.cpp \ # wirish_digital.cpp +# TODO: Put this back in once we've got the necessary libmaple support back. # cppSRCS_$(d) += $(WIRISH_BOARD_PATH)/board.cpp +cppSRCS_$(d) += $(MCU_SERIES)/boards_setup.cpp sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%) cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%) diff --git a/wirish/stm32f1/boards_setup.cpp b/wirish/stm32f1/boards_setup.cpp new file mode 100644 index 0000000..4ee292a --- /dev/null +++ b/wirish/stm32f1/boards_setup.cpp @@ -0,0 +1,141 @@ +/****************************************************************************** + * 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 wirish/stm32f1/boards_setup.cpp + * @author Marti Bolivar + * @brief STM32F1 chip setup. + */ + +#include +#include +#include +#include +#include + +#include + +/* FIXME: Reintroduce all "#if 0"'ed blocks once libmaple provides + * these definitions again. */ + +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}; + +#if 0 + static void config_adc(const adc_dev* dev); + static void config_timer(timer_dev*); +#endif + + void board_reset_pll(void) { + // TODO + } + + void board_setup_clock_prescalers(void) { + rcc_set_prescaler(RCC_PRESCALER_AHB, RCC_AHB_SYSCLK_DIV_1); + rcc_set_prescaler(RCC_PRESCALER_APB1, RCC_APB1_HCLK_DIV_2); + rcc_set_prescaler(RCC_PRESCALER_APB2, RCC_APB2_HCLK_DIV_1); + } + + void board_setup_gpio(void) { + gpio_init_all(); + // Initialize AFIO here, too, so peripheral remaps and external + // interrupts work out of the box. + 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) { +#if 0 + usb_cdcacm_enable(BOARD_USB_DISC_DEV, BOARD_USB_DISC_BIT); +#endif + } + + /* + * 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) { + timer_adv_reg_map *regs = (dev->regs).adv; + const uint16 full_overflow = 0xFFFF; + const uint16 half_duty = 0x8FFF; + + timer_init(dev); + timer_pause(dev); + + regs->CR1 = TIMER_CR1_ARPE; + regs->PSC = 1; + regs->SR = 0; + regs->DIER = 0; + regs->EGR = TIMER_EGR_UG; + + switch (dev->type) { + case TIMER_ADVANCED: + regs->BDTR = TIMER_BDTR_MOE | TIMER_BDTR_LOCK_OFF; + // fall-through + case TIMER_GENERAL: + timer_set_reload(dev, full_overflow); + + for (int channel = 1; channel <= 4; channel++) { + timer_set_compare(dev, channel, half_duty); + timer_oc_set_mode(dev, channel, TIMER_OC_MODE_PWM_1, TIMER_OC_PE); + } + // fall-through + case TIMER_BASIC: + break; + } + + timer_resume(dev); + } +#endif + } +} diff --git a/wirish/stm32f2/boards_setup.cpp b/wirish/stm32f2/boards_setup.cpp new file mode 100644 index 0000000..b3c690c --- /dev/null +++ b/wirish/stm32f2/boards_setup.cpp @@ -0,0 +1,75 @@ +/****************************************************************************** + * 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 wirish/stm32f2/boards_setup.cpp + * @author Marti Bolivar + * @brief STM32F2 chip setup. + */ + +#include +#include + +#define PLL_Q 5 +#define PLL_P 2 +#define PLL_N 240 +#define PLL_M 25 +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}; + + void board_reset_pll(void) { + // Set PLLCFGR to its reset value. + RCC_BASE->PLLCFGR = 0x24003010; // FIXME lose the magic number. + } + + void board_setup_clock_prescalers(void) { + rcc_set_prescaler(RCC_PRESCALER_AHB, RCC_AHB_SYSCLK_DIV_1); + rcc_set_prescaler(RCC_PRESCALER_APB1, RCC_APB1_HCLK_DIV_4); + rcc_set_prescaler(RCC_PRESCALER_APB2, RCC_APB2_HCLK_DIV_2); + } + + void board_setup_gpio(void) { + gpio_init_all(); + } + + void board_setup_adc(void) { + // TODO + } + + void board_setup_timers(void) { + // TODO + } + + void board_setup_usb(void) { + // TODO + } + + } +} + -- cgit v1.2.3 From 0e83157fcbed12cdae1b596820ad54ddc77a2608 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Thu, 31 May 2012 16:02:37 -0400 Subject: wirish: Build board.cpp. There's enough infrastructure for a basic board.cpp on STM32F2, so we might as well bring this back. Signed-off-by: Marti Bolivar --- wirish/rules.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'wirish/rules.mk') diff --git a/wirish/rules.mk b/wirish/rules.mk index 17c4d05..afd78e2 100644 --- a/wirish/rules.mk +++ b/wirish/rules.mk @@ -36,7 +36,7 @@ cppSRCS_$(d) := boards.cpp # ext_interrupts.cpp \ # wirish_digital.cpp # TODO: Put this back in once we've got the necessary libmaple support back. -# cppSRCS_$(d) += $(WIRISH_BOARD_PATH)/board.cpp +cppSRCS_$(d) += $(WIRISH_BOARD_PATH)/board.cpp cppSRCS_$(d) += $(MCU_SERIES)/boards_setup.cpp sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%) -- cgit v1.2.3 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/rules.mk | 14 ++-- wirish/stm32f1/wirish_digital.cpp | 89 ++++++++++++++++++++++++++ wirish/stm32f2/wirish_digital.cpp | 130 ++++++++++++++++++++++++++++++++++++++ wirish/wirish_digital.cpp | 54 +--------------- 4 files changed, 227 insertions(+), 60 deletions(-) create mode 100644 wirish/stm32f1/wirish_digital.cpp create mode 100644 wirish/stm32f2/wirish_digital.cpp (limited to 'wirish/rules.mk') diff --git a/wirish/rules.mk b/wirish/rules.mk index afd78e2..5e00a5f 100644 --- a/wirish/rules.mk +++ b/wirish/rules.mk @@ -21,6 +21,12 @@ CFLAGS_$(d) := $(LIBMAPLE_INCLUDES) $(WIRISH_INCLUDES) -I$(d) sSRCS_$(d) := start.S cSRCS_$(d) := start_c.c cppSRCS_$(d) := boards.cpp +cppSRCS_$(d) += cxxabi-compat.cpp +cppSRCS_$(d) += wirish_digital.cpp +cppSRCS_$(d) += wirish_time.cpp +cppSRCS_$(d) += $(MCU_SERIES)/boards_setup.cpp +cppSRCS_$(d) += $(MCU_SERIES)/wirish_digital.cpp +cppSRCS_$(d) += $(WIRISH_BOARD_PATH)/board.cpp # TODO: test these on F2 and put them back in: # cppSRCS_$(d) := wirish_math.cpp \ # Print.cpp \ @@ -28,16 +34,10 @@ cppSRCS_$(d) := boards.cpp # HardwareSPI.cpp \ # HardwareTimer.cpp \ # usb_serial.cpp \ -# cxxabi-compat.cpp \ # wirish_shift.cpp \ # wirish_analog.cpp \ -# wirish_time.cpp \ # pwm.cpp \ -# ext_interrupts.cpp \ -# wirish_digital.cpp -# TODO: Put this back in once we've got the necessary libmaple support back. -cppSRCS_$(d) += $(WIRISH_BOARD_PATH)/board.cpp -cppSRCS_$(d) += $(MCU_SERIES)/boards_setup.cpp +# ext_interrupts.cpp sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%) cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%) diff --git a/wirish/stm32f1/wirish_digital.cpp b/wirish/stm32f1/wirish_digital.cpp new file mode 100644 index 0000000..8371b0e --- /dev/null +++ b/wirish/stm32f1/wirish_digital.cpp @@ -0,0 +1,89 @@ +/****************************************************************************** + * 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 + * 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. + *****************************************************************************/ + +/* + * STM32F1 implementations for basic GPIO functionality. + */ + +#include + +#include +#include + +#include + +void pinMode(uint8 pin, WiringPinMode mode) { + gpio_pin_mode outputMode; + bool pwm = false; + + if (pin >= BOARD_NR_GPIO_PINS) { + return; + } + + switch(mode) { + case OUTPUT: + outputMode = GPIO_OUTPUT_PP; + break; + case OUTPUT_OPEN_DRAIN: + outputMode = GPIO_OUTPUT_OD; + break; + case INPUT: + case INPUT_FLOATING: + outputMode = GPIO_INPUT_FLOATING; + break; + case INPUT_ANALOG: + outputMode = GPIO_INPUT_ANALOG; + break; + case INPUT_PULLUP: + outputMode = GPIO_INPUT_PU; + break; + case INPUT_PULLDOWN: + outputMode = GPIO_INPUT_PD; + break; + case PWM: + outputMode = GPIO_AF_OUTPUT_PP; + pwm = true; + break; + case PWM_OPEN_DRAIN: + outputMode = GPIO_AF_OUTPUT_OD; + pwm = true; + break; + default: + ASSERT(0); + return; + } + + gpio_set_mode(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit, outputMode); + + if (PIN_MAP[pin].timer_device != NULL) { + /* Enable/disable timer channels if we're switching into or + * out of PWM. */ + timer_set_mode(PIN_MAP[pin].timer_device, + PIN_MAP[pin].timer_channel, + pwm ? TIMER_PWM : TIMER_DISABLED); + } +} 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); + } +} diff --git a/wirish/wirish_digital.cpp b/wirish/wirish_digital.cpp index 6be1a29..a7f10cd 100644 --- a/wirish/wirish_digital.cpp +++ b/wirish/wirish_digital.cpp @@ -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 @@ -36,59 +37,6 @@ #include #include -void pinMode(uint8 pin, WiringPinMode mode) { - gpio_pin_mode outputMode; - bool pwm = false; - - if (pin >= BOARD_NR_GPIO_PINS) { - return; - } - - switch(mode) { - case OUTPUT: - outputMode = GPIO_OUTPUT_PP; - break; - case OUTPUT_OPEN_DRAIN: - outputMode = GPIO_OUTPUT_OD; - break; - case INPUT: - case INPUT_FLOATING: - outputMode = GPIO_INPUT_FLOATING; - break; - case INPUT_ANALOG: - outputMode = GPIO_INPUT_ANALOG; - break; - case INPUT_PULLUP: - outputMode = GPIO_INPUT_PU; - break; - case INPUT_PULLDOWN: - outputMode = GPIO_INPUT_PD; - break; - case PWM: - outputMode = GPIO_AF_OUTPUT_PP; - pwm = true; - break; - case PWM_OPEN_DRAIN: - outputMode = GPIO_AF_OUTPUT_OD; - pwm = true; - break; - default: - ASSERT(0); - return; - } - - gpio_set_mode(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit, outputMode); - - if (PIN_MAP[pin].timer_device != NULL) { - /* Enable/disable timer channels if we're switching into or - * out of PWM. */ - timer_set_mode(PIN_MAP[pin].timer_device, - PIN_MAP[pin].timer_channel, - pwm ? TIMER_PWM : TIMER_DISABLED); - } -} - - uint32 digitalRead(uint8 pin) { if (pin >= BOARD_NR_GPIO_PINS) { return 0; -- cgit v1.2.3 From 77abda29002216bd8186b430f484c98666a52339 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Thu, 31 May 2012 18:47:39 -0400 Subject: Replace shiftOut(), also fixing a possible bug. The current shiftOut() is borrowed from Arduino, and is in an LGPL file. Replace that file with a new MIT-licensed version containing a new implementation. The new version brings the clock line LOW before starting, to make sure that the first pulse is detected if the clock line was previously HIGH. Signed-off-by: Marti Bolivar --- wirish/rules.mk | 2 +- wirish/wirish_shift.cpp | 59 +++++++++++++++++++++++-------------------------- 2 files changed, 29 insertions(+), 32 deletions(-) (limited to 'wirish/rules.mk') diff --git a/wirish/rules.mk b/wirish/rules.mk index 5e00a5f..0b0b82c 100644 --- a/wirish/rules.mk +++ b/wirish/rules.mk @@ -24,6 +24,7 @@ cppSRCS_$(d) := boards.cpp cppSRCS_$(d) += cxxabi-compat.cpp cppSRCS_$(d) += wirish_digital.cpp cppSRCS_$(d) += wirish_time.cpp +cppSRCS_$(d) += wirish_shift.cpp cppSRCS_$(d) += $(MCU_SERIES)/boards_setup.cpp cppSRCS_$(d) += $(MCU_SERIES)/wirish_digital.cpp cppSRCS_$(d) += $(WIRISH_BOARD_PATH)/board.cpp @@ -34,7 +35,6 @@ cppSRCS_$(d) += $(WIRISH_BOARD_PATH)/board.cpp # HardwareSPI.cpp \ # HardwareTimer.cpp \ # usb_serial.cpp \ -# wirish_shift.cpp \ # wirish_analog.cpp \ # pwm.cpp \ # ext_interrupts.cpp diff --git a/wirish/wirish_shift.cpp b/wirish/wirish_shift.cpp index 0f24f59..a032d50 100644 --- a/wirish/wirish_shift.cpp +++ b/wirish/wirish_shift.cpp @@ -1,40 +1,37 @@ -/* - * wiring_shift.c - shiftOut() function - * Part of Arduino - http://www.arduino.cc/ +/****************************************************************************** + * The MIT License * - * Copyright (c) 2005-2006 David A. Mellis + * Copyright (c) 2012 LeafLabs, LLC. * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. + * 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: * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - * - * $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ - */ + * 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 -void shiftOut(uint8 dataPin, uint8 clockPin, uint8 bitOrder, uint8 val) { - int i; - - for (i = 0; i < 8; i++) { - if (bitOrder == LSBFIRST) { - digitalWrite(dataPin, !!(val & (1 << i))); - } else { - digitalWrite(dataPin, !!(val & (1 << (7 - i)))); - } - - digitalWrite(clockPin, HIGH); - digitalWrite(clockPin, LOW); +void shiftOut(uint8 dataPin, uint8 clockPin, uint8 bitOrder, uint8 value) { + digitalWrite(clockPin, LOW); + for (int i = 0; i < 8; i++) { + int bit = bitOrder == LSBFIRST ? i : (7 - i); + digitalWrite(dataPin, (value >> bit) & 0x1); + togglePin(clockPin); + togglePin(clockPin); } } -- cgit v1.2.3 From bf47524bc9956030ff03ec776660994d71224ddb Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Thu, 31 May 2012 18:57:41 -0400 Subject: Bring back wirish/Print.cpp. The only nonportable parts of this file are based on the assumption that we're on ILP32. Signed-off-by: Marti Bolivar --- wirish/rules.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'wirish/rules.mk') diff --git a/wirish/rules.mk b/wirish/rules.mk index 0b0b82c..b795f60 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) += Print.cpp cppSRCS_$(d) += wirish_digital.cpp cppSRCS_$(d) += wirish_time.cpp cppSRCS_$(d) += wirish_shift.cpp @@ -30,7 +31,6 @@ cppSRCS_$(d) += $(MCU_SERIES)/wirish_digital.cpp cppSRCS_$(d) += $(WIRISH_BOARD_PATH)/board.cpp # TODO: test these on F2 and put them back in: # cppSRCS_$(d) := wirish_math.cpp \ -# Print.cpp \ # HardwareSerial.cpp \ # HardwareSPI.cpp \ # HardwareTimer.cpp \ -- cgit v1.2.3 From bb3fa82563a121e76680f3d4b38fe4ecdf809dde Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Thu, 31 May 2012 19:15:43 -0400 Subject: wirish/rules.mk: Cosmetics. Signed-off-by: Marti Bolivar --- wirish/rules.mk | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'wirish/rules.mk') diff --git a/wirish/rules.mk b/wirish/rules.mk index b795f60..0e99e2c 100644 --- a/wirish/rules.mk +++ b/wirish/rules.mk @@ -24,20 +24,20 @@ cppSRCS_$(d) := boards.cpp cppSRCS_$(d) += cxxabi-compat.cpp cppSRCS_$(d) += Print.cpp cppSRCS_$(d) += wirish_digital.cpp -cppSRCS_$(d) += wirish_time.cpp cppSRCS_$(d) += wirish_shift.cpp +cppSRCS_$(d) += wirish_time.cpp cppSRCS_$(d) += $(MCU_SERIES)/boards_setup.cpp cppSRCS_$(d) += $(MCU_SERIES)/wirish_digital.cpp cppSRCS_$(d) += $(WIRISH_BOARD_PATH)/board.cpp -# TODO: test these on F2 and put them back in: -# cppSRCS_$(d) := wirish_math.cpp \ -# HardwareSerial.cpp \ -# HardwareSPI.cpp \ -# HardwareTimer.cpp \ -# usb_serial.cpp \ -# wirish_analog.cpp \ -# pwm.cpp \ -# ext_interrupts.cpp +# TODO: revise these appropriately F2 and put them back in: +# wirish_math.cpp +# HardwareSerial.cpp +# HardwareSPI.cpp +# HardwareTimer.cpp +# usb_serial.cpp +# wirish_analog.cpp +# pwm.cpp +# ext_interrupts.cpp sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%) cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%) -- cgit v1.2.3 From b1e06d3acaa72976042314c1debec008c5ac54d7 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Thu, 31 May 2012 19:20:01 -0400 Subject: Bring back wirish/wirish_math.cpp. This is portable. Signed-off-by: Marti Bolivar --- wirish/rules.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'wirish/rules.mk') diff --git a/wirish/rules.mk b/wirish/rules.mk index 0e99e2c..903c817 100644 --- a/wirish/rules.mk +++ b/wirish/rules.mk @@ -24,13 +24,13 @@ cppSRCS_$(d) := boards.cpp cppSRCS_$(d) += cxxabi-compat.cpp cppSRCS_$(d) += Print.cpp cppSRCS_$(d) += wirish_digital.cpp +cppSRCS_$(d) += wirish_math.cpp cppSRCS_$(d) += wirish_shift.cpp cppSRCS_$(d) += wirish_time.cpp cppSRCS_$(d) += $(MCU_SERIES)/boards_setup.cpp cppSRCS_$(d) += $(MCU_SERIES)/wirish_digital.cpp cppSRCS_$(d) += $(WIRISH_BOARD_PATH)/board.cpp # TODO: revise these appropriately F2 and put them back in: -# wirish_math.cpp # HardwareSerial.cpp # HardwareSPI.cpp # HardwareTimer.cpp -- cgit v1.2.3 From d483f8fa0c7c1f65c926b24d6c66275953d03c4f Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Fri, 1 Jun 2012 01:10:47 -0400 Subject: Bring back HardwareSerial. To make this happen, we need to have tell us whether or not it's got each of the USARTs. Do that with BOARD_HAVE_USARTn, for n = 1,...,6. This lets us define HardwareSerial instances only when appropriate, and gets rid of some board-specific hacks we'd accumulated. The new now has a convenience function for determining the bus rate by using the appropriate STM32_PCLKx macro, so we can shave a uint32 per instance, which is nice given that they're all going to be in memory. This changes the constructor arguments, but the API only specifies the semantics of the predefined instances, so this is still backwards-compatible. (We should look into storing the instances in Flash -- they don't change, after all.) We don't actually need struct usart_dev's definition in HardwareSerial.h, so replace it with a forward declaration and include it in HardwareSerial.cpp instead. Assert some copyrights. Signed-off-by: Marti Bolivar --- libmaple/include/libmaple/usart.h | 1 + wirish/HardwareSerial.cpp | 98 ++++++++++++---------- wirish/boards/VLDiscovery/include/board/board.h | 6 ++ wirish/boards/maple/include/board/board.h | 9 +- wirish/boards/maple_RET6/include/board/board.h | 11 ++- wirish/boards/maple_mini/include/board/board.h | 6 ++ wirish/boards/maple_native/include/board/board.h | 6 ++ .../boards/olimex_stm32_h103/include/board/board.h | 6 ++ .../boards/st_stm3220g_eval/include/board/board.h | 12 ++- wirish/include/wirish/HardwareSerial.h | 26 ++++-- wirish/rules.mk | 2 +- 11 files changed, 127 insertions(+), 56 deletions(-) (limited to 'wirish/rules.mk') diff --git a/libmaple/include/libmaple/usart.h b/libmaple/include/libmaple/usart.h index ad7eb51..293d59e 100644 --- a/libmaple/include/libmaple/usart.h +++ b/libmaple/include/libmaple/usart.h @@ -395,6 +395,7 @@ typedef struct usart_dev { void usart_init(usart_dev *dev); +/* FIXME document this function */ struct gpio_dev; /* forward declaration */ void usart_async_gpio_cfg(usart_dev *udev, struct gpio_dev *rx_dev, uint8 rx, diff --git a/wirish/HardwareSerial.cpp b/wirish/HardwareSerial.cpp index 0f12e72..3f418e2 100644 --- a/wirish/HardwareSerial.cpp +++ b/wirish/HardwareSerial.cpp @@ -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 @@ -34,36 +35,36 @@ #include #include #include +#include -#include - -#define TX1 BOARD_USART1_TX_PIN -#define RX1 BOARD_USART1_RX_PIN -#define TX2 BOARD_USART2_TX_PIN -#define RX2 BOARD_USART2_RX_PIN -#define TX3 BOARD_USART3_TX_PIN -#define RX3 BOARD_USART3_RX_PIN -#if defined STM32_HIGH_DENSITY && !defined(BOARD_maple_RET6) -#define TX4 BOARD_UART4_TX_PIN -#define RX4 BOARD_UART4_RX_PIN -#define TX5 BOARD_UART5_TX_PIN -#define RX5 BOARD_UART5_RX_PIN -#endif +#define DEFINE_HWSERIAL(name, n) \ + HardwareSerial name(USART##n, \ + BOARD_USART##n##_TX_PIN, \ + BOARD_USART##n##_RX_PIN) -HardwareSerial Serial1(USART1, TX1, RX1, STM32_PCLK2); -HardwareSerial Serial2(USART2, TX2, RX2, STM32_PCLK1); -HardwareSerial Serial3(USART3, TX3, RX3, STM32_PCLK1); -#if defined(STM32_HIGH_DENSITY) && !defined(BOARD_maple_RET6) -HardwareSerial Serial4(UART4, TX4, RX4, STM32_PCLK1); -HardwareSerial Serial5(UART5, TX5, RX5, STM32_PCLK1); +#if BOARD_HAVE_USART1 +DEFINE_HWSERIAL(Serial1, 1); +#endif +#if BOARD_HAVE_USART2 +DEFINE_HWSERIAL(Serial2, 2); +#endif +#if BOARD_HAVE_USART3 +DEFINE_HWSERIAL(Serial3, 3); +#endif +#if BOARD_HAVE_UART4 +DEFINE_HWSERIAL(Serial4, 4); +#endif +#if BOARD_HAVE_UART5 +DEFINE_HWSERIAL(Serial5, 5); +#endif +#if BOARD_HAVE_USART6 +DEFINE_HWSERIAL(Serial6, 6); #endif HardwareSerial::HardwareSerial(usart_dev *usart_device, uint8 tx_pin, - uint8 rx_pin, - uint32 clock_speed) { + uint8 rx_pin) { this->usart_device = usart_device; - this->clock_speed = clock_speed; this->tx_pin = tx_pin; this->rx_pin = rx_pin; } @@ -72,31 +73,44 @@ HardwareSerial::HardwareSerial(usart_dev *usart_device, * Set up/tear down */ +#if STM32_MCU_SERIES == STM32_SERIES_F1 +/* F1 MCUs have no GPIO_AFR[HL], so turn off PWM if there's a conflict + * on this GPIO bit. */ +static void disable_timer_if_necessary(timer_dev *dev, uint8 ch) { + if (txi->timer_device != NULL) { + timer_set_mode(txi->timer_device, txi->timer_channel, TIMER_DISABLED); + } +} +#elif (STM32_MCU_SERIES == STM32_SERIES_F2) || \ + (STM32_MCU_SERIES == STM32_SERIES_F4) +#define disable_timer_if_necessary(dev, ch) ((void)0) +#else +#warn "Unsupported STM32 series; timer conflicts are possible" +#endif + void HardwareSerial::begin(uint32 baud) { - ASSERT(baud <= usart_device->max_baud); + ASSERT(baud <= this->usart_device->max_baud); - if (baud > usart_device->max_baud) { + if (baud > this->usart_device->max_baud) { return; } - const stm32_pin_info *txi = &PIN_MAP[tx_pin]; - const stm32_pin_info *rxi = &PIN_MAP[rx_pin]; + const stm32_pin_info *txi = &PIN_MAP[this->tx_pin]; + const stm32_pin_info *rxi = &PIN_MAP[this->rx_pin]; - gpio_set_mode(txi->gpio_device, txi->gpio_bit, GPIO_AF_OUTPUT_PP); - gpio_set_mode(rxi->gpio_device, rxi->gpio_bit, GPIO_INPUT_FLOATING); - - if (txi->timer_device != NULL) { - /* Turn off any PWM if there's a conflict on this GPIO bit. */ - timer_set_mode(txi->timer_device, txi->timer_channel, TIMER_DISABLED); - } + disable_timer_if_necessary(txi->timer_device, txi->timer_channel); - usart_init(usart_device); - usart_set_baud_rate(usart_device, clock_speed, baud); - usart_enable(usart_device); + usart_async_gpio_cfg(this->usart_device, + rxi->gpio_device, rxi->gpio_bit, + txi->gpio_device, txi->gpio_bit, + 0); + usart_init(this->usart_device); + usart_set_baud_rate(this->usart_device, USART_USE_PCLK, baud); + usart_enable(this->usart_device); } void HardwareSerial::end(void) { - usart_disable(usart_device); + usart_disable(this->usart_device); } /* @@ -104,17 +118,17 @@ void HardwareSerial::end(void) { */ uint8 HardwareSerial::read(void) { - return usart_getc(usart_device); + return usart_getc(this->usart_device); } uint32 HardwareSerial::available(void) { - return usart_data_available(usart_device); + return usart_data_available(this->usart_device); } void HardwareSerial::write(unsigned char ch) { - usart_putc(usart_device, ch); + usart_putc(this->usart_device, ch); } void HardwareSerial::flush(void) { - usart_reset_rx(usart_device); + usart_reset_rx(this->usart_device); } diff --git a/wirish/boards/VLDiscovery/include/board/board.h b/wirish/boards/VLDiscovery/include/board/board.h index 04d21c7..c54abc1 100644 --- a/wirish/boards/VLDiscovery/include/board/board.h +++ b/wirish/boards/VLDiscovery/include/board/board.h @@ -45,6 +45,12 @@ /* Number of USARTs/UARTs whose pins are broken out to headers */ #define BOARD_NR_USARTS 3 +#define BOARD_HAVE_USART1 1 +#define BOARD_HAVE_USART2 1 +#define BOARD_HAVE_USART3 1 +#define BOARD_HAVE_UART4 0 +#define BOARD_HAVE_UART5 0 +#define BOARD_HAVE_USART6 0 /* Default USART pin numbers (not considering AFIO remap) */ #define BOARD_USART1_TX_PIN 7 diff --git a/wirish/boards/maple/include/board/board.h b/wirish/boards/maple/include/board/board.h index 49f5b9a..ed89fee 100644 --- a/wirish/boards/maple/include/board/board.h +++ b/wirish/boards/maple/include/board/board.h @@ -39,8 +39,15 @@ #define BOARD_BUTTON_PIN 38 #define BOARD_LED_PIN 13 -/* Number of USARTs/UARTs whose pins are broken out to headers */ +/* Number of USARTs/UARTs whose pins are broken out to headers, and + * macros saying which ones they are. */ #define BOARD_NR_USARTS 3 +#define BOARD_HAVE_USART1 1 +#define BOARD_HAVE_USART2 1 +#define BOARD_HAVE_USART3 1 +#define BOARD_HAVE_UART4 0 +#define BOARD_HAVE_UART5 0 +#define BOARD_HAVE_USART6 0 /* Default USART pin numbers (not considering AFIO remap) */ #define BOARD_USART1_TX_PIN 7 diff --git a/wirish/boards/maple_RET6/include/board/board.h b/wirish/boards/maple_RET6/include/board/board.h index 1a0365a..3291498 100644 --- a/wirish/boards/maple_RET6/include/board/board.h +++ b/wirish/boards/maple_RET6/include/board/board.h @@ -36,17 +36,20 @@ #ifndef _BOARDS_MAPLE_RET6_H_ #define _BOARDS_MAPLE_RET6_H_ -/* A few of these values will seem strange given that it's a - * high-density board. */ - #define CYCLES_PER_MICROSECOND 72 #define SYSTICK_RELOAD_VAL 71999 /* takes a cycle to reload */ #define BOARD_BUTTON_PIN 38 #define BOARD_LED_PIN 13 -/* Note: UART4 and UART5 have pins which aren't broken out :( */ +/* UART4 and UART5 have pins which aren't broken out :( */ #define BOARD_NR_USARTS 3 +#define BOARD_HAVE_USART1 1 +#define BOARD_HAVE_USART2 1 +#define BOARD_HAVE_USART3 1 +#define BOARD_HAVE_UART4 0 +#define BOARD_HAVE_UART5 0 +#define BOARD_HAVE_USART6 0 #define BOARD_USART1_TX_PIN 7 #define BOARD_USART1_RX_PIN 8 #define BOARD_USART2_TX_PIN 1 diff --git a/wirish/boards/maple_mini/include/board/board.h b/wirish/boards/maple_mini/include/board/board.h index bfba46d..8ba91ce 100644 --- a/wirish/boards/maple_mini/include/board/board.h +++ b/wirish/boards/maple_mini/include/board/board.h @@ -43,6 +43,12 @@ #define BOARD_LED_PIN 33 #define BOARD_NR_USARTS 3 +#define BOARD_HAVE_USART1 1 +#define BOARD_HAVE_USART2 1 +#define BOARD_HAVE_USART3 1 +#define BOARD_HAVE_UART4 0 +#define BOARD_HAVE_UART5 0 +#define BOARD_HAVE_USART6 0 #define BOARD_USART1_TX_PIN 26 #define BOARD_USART1_RX_PIN 25 #define BOARD_USART2_TX_PIN 9 diff --git a/wirish/boards/maple_native/include/board/board.h b/wirish/boards/maple_native/include/board/board.h index 397afaf..a4f8896 100644 --- a/wirish/boards/maple_native/include/board/board.h +++ b/wirish/boards/maple_native/include/board/board.h @@ -43,6 +43,12 @@ #define BOARD_BUTTON_PIN 6 #define BOARD_NR_USARTS 5 +#define BOARD_HAVE_USART1 1 +#define BOARD_HAVE_USART2 1 +#define BOARD_HAVE_USART3 1 +#define BOARD_HAVE_UART4 1 +#define BOARD_HAVE_UART5 1 +#define BOARD_HAVE_USART6 0 #define BOARD_USART1_TX_PIN 24 #define BOARD_USART1_RX_PIN 25 #define BOARD_USART2_TX_PIN 50 diff --git a/wirish/boards/olimex_stm32_h103/include/board/board.h b/wirish/boards/olimex_stm32_h103/include/board/board.h index b312e26..46367ac 100644 --- a/wirish/boards/olimex_stm32_h103/include/board/board.h +++ b/wirish/boards/olimex_stm32_h103/include/board/board.h @@ -42,6 +42,12 @@ /* Number of USARTs/UARTs whose pins are broken out to headers */ #define BOARD_NR_USARTS 3 +#define BOARD_HAVE_USART1 1 +#define BOARD_HAVE_USART2 1 +#define BOARD_HAVE_USART3 1 +#define BOARD_HAVE_UART4 0 +#define BOARD_HAVE_UART5 0 +#define BOARD_HAVE_USART6 0 /* Default USART pin numbers (not considering AFIO remap) */ #define BOARD_USART1_TX_PIN 3 diff --git a/wirish/boards/st_stm3220g_eval/include/board/board.h b/wirish/boards/st_stm3220g_eval/include/board/board.h index 08b935e..f99a585 100644 --- a/wirish/boards/st_stm3220g_eval/include/board/board.h +++ b/wirish/boards/st_stm3220g_eval/include/board/board.h @@ -27,7 +27,11 @@ /** * @file wirish/boards/st_stm3220g_eval/include/board/board.h * @author Marti Bolivar - * @brief STM3220G-EVAL board header. + * @brief STM3220G-EVAL board stub header. + * + * This (and the corresponding board.cpp) needs to be fixed and + * fleshed out. Do it later? Maybe someone who wants support for this + * board will do it. */ #ifndef _BOARD_ST_STM3220G_EVAL_H_ @@ -40,6 +44,12 @@ #define BOARD_LED_PIN 0 #define BOARD_NR_USARTS 0 +#define BOARD_HAVE_USART1 0 +#define BOARD_HAVE_USART2 0 +#define BOARD_HAVE_USART3 0 +#define BOARD_HAVE_UART4 0 +#define BOARD_HAVE_UART5 0 +#define BOARD_HAVE_USART6 0 #define BOARD_NR_SPI 0 #define BOARD_NR_GPIO_PINS 6 #define BOARD_NR_PWM_PINS 0 diff --git a/wirish/include/wirish/HardwareSerial.h b/wirish/include/wirish/HardwareSerial.h index 1eaacb6..2b1e747 100644 --- a/wirish/include/wirish/HardwareSerial.h +++ b/wirish/include/wirish/HardwareSerial.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 @@ -33,9 +34,9 @@ #define _WIRISH_HARDWARESERIAL_H_ #include -#include #include +#include /* * IMPORTANT: @@ -47,12 +48,13 @@ * the documentation accordingly. */ +struct usart_dev; + class HardwareSerial : public Print { public: - HardwareSerial(usart_dev *usart_device, + HardwareSerial(struct usart_dev *usart_device, uint8 tx_pin, - uint8 rx_pin, - uint32 clock_speed); + uint8 rx_pin); /* Set up/tear down */ void begin(uint32 baud); @@ -69,18 +71,28 @@ public: int txPin(void) { return this->tx_pin; } int rxPin(void) { return this->rx_pin; } private: - usart_dev *usart_device; + struct usart_dev *usart_device; uint8 tx_pin; uint8 rx_pin; - uint32 clock_speed; }; +#if BOARD_HAVE_USART1 extern HardwareSerial Serial1; +#endif +#if BOARD_HAVE_USART2 extern HardwareSerial Serial2; +#endif +#if BOARD_HAVE_USART3 extern HardwareSerial Serial3; -#if defined(STM32_HIGH_DENSITY) && !defined(BOARD_maple_RET6) +#endif +#if BOARD_HAVE_UART4 extern HardwareSerial Serial4; +#endif +#if BOARD_HAVE_UART5 extern HardwareSerial Serial5; #endif +#if BOARD_HAVE_USART6 +extern HardwareSerial Serial6; +#endif #endif diff --git a/wirish/rules.mk b/wirish/rules.mk index 903c817..4084448 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) += HardwareSerial.cpp cppSRCS_$(d) += Print.cpp cppSRCS_$(d) += wirish_digital.cpp cppSRCS_$(d) += wirish_math.cpp @@ -31,7 +32,6 @@ cppSRCS_$(d) += $(MCU_SERIES)/boards_setup.cpp cppSRCS_$(d) += $(MCU_SERIES)/wirish_digital.cpp cppSRCS_$(d) += $(WIRISH_BOARD_PATH)/board.cpp # TODO: revise these appropriately F2 and put them back in: -# HardwareSerial.cpp # HardwareSPI.cpp # HardwareTimer.cpp # usb_serial.cpp -- cgit v1.2.3 From 33a2fff2fc60ea0e6938d72c81812b2afb3bfb0e Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Fri, 1 Jun 2012 02:04:59 -0400 Subject: Bring back analogRead(). Yay, it just worked! Still, while we're here, touch up the make-up on wirish_analog.cpp. Signed-off-by: Marti Bolivar --- wirish/rules.mk | 2 +- wirish/wirish_analog.cpp | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'wirish/rules.mk') diff --git a/wirish/rules.mk b/wirish/rules.mk index 4084448..deb3906 100644 --- a/wirish/rules.mk +++ b/wirish/rules.mk @@ -24,6 +24,7 @@ cppSRCS_$(d) := boards.cpp cppSRCS_$(d) += cxxabi-compat.cpp cppSRCS_$(d) += HardwareSerial.cpp cppSRCS_$(d) += Print.cpp +cppSRCS_$(d) += wirish_analog.cpp cppSRCS_$(d) += wirish_digital.cpp cppSRCS_$(d) += wirish_math.cpp cppSRCS_$(d) += wirish_shift.cpp @@ -35,7 +36,6 @@ cppSRCS_$(d) += $(WIRISH_BOARD_PATH)/board.cpp # HardwareSPI.cpp # HardwareTimer.cpp # usb_serial.cpp -# wirish_analog.cpp # pwm.cpp # ext_interrupts.cpp diff --git a/wirish/wirish_analog.cpp b/wirish/wirish_analog.cpp index 7a12156..91ca0e2 100644 --- a/wirish/wirish_analog.cpp +++ b/wirish/wirish_analog.cpp @@ -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 @@ -25,17 +26,17 @@ *****************************************************************************/ /** - * @brief Arduino-compatible ADC implementation. + * @file wirish/wirish_analog.cpp + * @brief Wiring-style analogRead() implementation. */ #include - #include - #include -/* Assumes that the ADC has been initialized and that the pin is set - * to INPUT_ANALOG */ +/* Unlike Wiring and Arduino, this assumes that the pin's mode is set + * to INPUT_ANALOG. That's faster, but it does require some extra work + * on the user's part. Not too much, we think ;). */ uint16 analogRead(uint8 pin) { const adc_dev *dev = PIN_MAP[pin].adc_device; if (dev == NULL) { -- cgit v1.2.3 From 73f2cefbdf6d8f255bc5284c64d315f38ee45616 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Fri, 1 Jun 2012 03:26:19 -0400 Subject: Bring back HardwareTimer. Untested, but the timers work on F2 (see exampes/test-timers.cpp), so I'm hoping this is mostly OK. Note that there's an issue with TIMER2 and TIMER5 on F2: these timers have 32-bit counters, and the HardwareTimer methods are all based on uint16 (like on F1). I'm sorely tempted to keep this as-is; exposing the extra bits is just extra documentation, and the HardwareTimer interface is already way too complicated. The interface should still _work_; it just hides the fact that you're missing out on the extra bits for some of the timers. Signed-off-by: Marti Bolivar --- wirish/HardwareTimer.cpp | 123 ++++++++++++++++++++++++++++------ wirish/include/wirish/HardwareTimer.h | 2 +- wirish/rules.mk | 2 +- 3 files changed, 104 insertions(+), 23 deletions(-) (limited to 'wirish/rules.mk') diff --git a/wirish/HardwareTimer.cpp b/wirish/HardwareTimer.cpp index 52257bf..ca8ea63 100644 --- a/wirish/HardwareTimer.cpp +++ b/wirish/HardwareTimer.cpp @@ -30,33 +30,114 @@ // TODO [0.1.0] Remove deprecated pieces -#ifdef STM32_MEDIUM_DENSITY -#define NR_TIMERS 4 -#elif defined(STM32_HIGH_DENSITY) -#define NR_TIMERS 8 +#define MAX_RELOAD ((1 << 16) - 1) + +/* + * Big ugly table of timers available on the MCU. Needed by the + * HardwareTimer constructor. Sigh; maybe predefined instances weren't + * such a bad idea. Oh well, at least the HardwareTimer interface is + * officially unstable since v0.0.12; we can always get rid of this + * later. + */ + +#define MAX_NR_TIMERS 17 // No STM32 I've ever heard of has higher than TIMER17 + +static timer_dev *devs[MAX_NR_TIMERS] = { +#if STM32_HAVE_TIMER(1) + TIMER1, +#else + NULL, +#endif +#if STM32_HAVE_TIMER(2) + TIMER2, +#else + NULL, +#endif +#if STM32_HAVE_TIMER(3) + TIMER3, +#else + NULL, +#endif +#if STM32_HAVE_TIMER(4) + TIMER4, +#else + NULL, +#endif +#if STM32_HAVE_TIMER(5) + TIMER5, +#else + NULL, +#endif +#if STM32_HAVE_TIMER(6) + TIMER6, +#else + NULL, +#endif +#if STM32_HAVE_TIMER(7) + TIMER7, +#else + NULL, +#endif +#if STM32_HAVE_TIMER(8) + TIMER8, +#else + NULL, +#endif +#if STM32_HAVE_TIMER(9) + TIMER9, #else -#error "Unsupported density" + NULL, #endif +#if STM32_HAVE_TIMER(10) + TIMER10, +#else + NULL, +#endif +#if STM32_HAVE_TIMER(11) + TIMER11, +#else + NULL, +#endif +#if STM32_HAVE_TIMER(12) + TIMER12, +#else + NULL, +#endif +#if STM32_HAVE_TIMER(13) + TIMER13, +#else + NULL, +#endif +#if STM32_HAVE_TIMER(14) + TIMER14, +#else + NULL, +#endif +#if STM32_HAVE_TIMER(15) + TIMER15, +#else + NULL, +#endif +#if STM32_HAVE_TIMER(16) + TIMER16, +#else + NULL, +#endif +#if STM32_HAVE_TIMER(17) + TIMER17, +#else + NULL, +#endif +}; -#define MAX_RELOAD ((1 << 16) - 1) +/* + * HardwareTimer routines + */ HardwareTimer::HardwareTimer(uint8 timerNum) { - if (timerNum > NR_TIMERS) { - ASSERT(0); - } - timer_dev *devs[] = { - TIMER1, - TIMER2, - TIMER3, - TIMER4, -#ifdef STM32_HIGH_DENSITY - TIMER5, - TIMER6, - TIMER7, - TIMER8, -#endif - }; + ASSERT(timerNum <= MAX_NR_TIMERS); this->dev = devs[timerNum - 1]; + ASSERT(this->dev != NULL); } void HardwareTimer::pause(void) { diff --git a/wirish/include/wirish/HardwareTimer.h b/wirish/include/wirish/HardwareTimer.h index bdcca5d..d322033 100644 --- a/wirish/include/wirish/HardwareTimer.h +++ b/wirish/include/wirish/HardwareTimer.h @@ -313,7 +313,7 @@ extern HardwareTimer Timer3; * Pre-instantiated timer. */ extern HardwareTimer Timer4; -#ifdef STM32_HIGH_DENSITY +#if (STM32_MCU_SERIES == STM32_SERIES_F1) && defined(STM32_HIGH_DENSITY) /** * @brief Deprecated. * diff --git a/wirish/rules.mk b/wirish/rules.mk index deb3906..54c9180 100644 --- a/wirish/rules.mk +++ b/wirish/rules.mk @@ -23,6 +23,7 @@ cSRCS_$(d) := start_c.c cppSRCS_$(d) := boards.cpp cppSRCS_$(d) += cxxabi-compat.cpp cppSRCS_$(d) += HardwareSerial.cpp +cppSRCS_$(d) += HardwareTimer.cpp cppSRCS_$(d) += Print.cpp cppSRCS_$(d) += wirish_analog.cpp cppSRCS_$(d) += wirish_digital.cpp @@ -34,7 +35,6 @@ cppSRCS_$(d) += $(MCU_SERIES)/wirish_digital.cpp cppSRCS_$(d) += $(WIRISH_BOARD_PATH)/board.cpp # TODO: revise these appropriately F2 and put them back in: # HardwareSPI.cpp -# HardwareTimer.cpp # usb_serial.cpp # pwm.cpp # ext_interrupts.cpp -- cgit v1.2.3 From 7943836c4a967e70ced14a2f4accf21a0469b238 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Sat, 2 Jun 2012 21:15:17 -0400 Subject: Bring back/tweak pwmWrite(). Works on F1, doesn't on F2. Will figure that out next. Signed-off-by: Marti Bolivar --- wirish/pwm.cpp | 13 ++++++++----- wirish/rules.mk | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'wirish/rules.mk') diff --git a/wirish/pwm.cpp b/wirish/pwm.cpp index a55f245..44884cd 100644 --- a/wirish/pwm.cpp +++ b/wirish/pwm.cpp @@ -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 @@ -25,7 +26,8 @@ *****************************************************************************/ /** - * @brief Arduino-style PWM implementation. + * @file wirish/pwm.cpp + * @brief Wiring-style pwmWrite(). */ #include @@ -36,10 +38,11 @@ #include void pwmWrite(uint8 pin, uint16 duty_cycle) { - timer_dev *dev = PIN_MAP[pin].timer_device; - if (pin >= BOARD_NR_GPIO_PINS || dev == NULL || dev->type == TIMER_BASIC) { + if (pin >= BOARD_NR_GPIO_PINS) { return; } - - timer_set_compare(dev, PIN_MAP[pin].timer_channel, duty_cycle); + timer_dev *dev = PIN_MAP[pin].timer_device; + uint8 cc_channel = PIN_MAP[pin].timer_channel; + ASSERT(dev && cc_channel); + timer_set_compare(dev, cc_channel, duty_cycle); } diff --git a/wirish/rules.mk b/wirish/rules.mk index 54c9180..176ba6a 100644 --- a/wirish/rules.mk +++ b/wirish/rules.mk @@ -25,6 +25,7 @@ cppSRCS_$(d) += cxxabi-compat.cpp cppSRCS_$(d) += HardwareSerial.cpp cppSRCS_$(d) += HardwareTimer.cpp cppSRCS_$(d) += Print.cpp +cppSRCS_$(d) += pwm.cpp cppSRCS_$(d) += wirish_analog.cpp cppSRCS_$(d) += wirish_digital.cpp cppSRCS_$(d) += wirish_math.cpp @@ -36,7 +37,6 @@ cppSRCS_$(d) += $(WIRISH_BOARD_PATH)/board.cpp # TODO: revise these appropriately F2 and put them back in: # HardwareSPI.cpp # usb_serial.cpp -# pwm.cpp # ext_interrupts.cpp sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%) -- cgit v1.2.3 From 4723f6525215ee5bce550ceb615326f05f8fbc3f Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Sun, 3 Jun 2012 02:15:57 -0400 Subject: Typo fix. Signed-off-by: Marti Bolivar --- wirish/rules.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'wirish/rules.mk') diff --git a/wirish/rules.mk b/wirish/rules.mk index 176ba6a..147857a 100644 --- a/wirish/rules.mk +++ b/wirish/rules.mk @@ -34,7 +34,7 @@ cppSRCS_$(d) += wirish_time.cpp cppSRCS_$(d) += $(MCU_SERIES)/boards_setup.cpp cppSRCS_$(d) += $(MCU_SERIES)/wirish_digital.cpp cppSRCS_$(d) += $(WIRISH_BOARD_PATH)/board.cpp -# TODO: revise these appropriately F2 and put them back in: +# TODO: revise these appropriately for F2 and put them back in: # HardwareSPI.cpp # usb_serial.cpp # ext_interrupts.cpp -- cgit v1.2.3 From 378c3a70f81ddfbbddf3656977f81b7dfd8f96cd Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Sun, 3 Jun 2012 06:00:41 -0400 Subject: Slightly improve and generify the USB infrastructure. The good news is that and did turn out generic enough in what they specify to go on unchanged. However, we can't just go on assuming that there's USB just because we're on an F1. Now that there's value line in the tree, we need to be more careful (value line F1s don't have USB peripherals). To that end, make all the F1 board-includes/*.mk files specify what line their MCU is with an MCU_F1_LINE variable. Use that to hack libmaple/usb/rules.mk so we only try to build the USB module under appropriate circumstances. While we're at it, add a vector_symbols.inc for value line MCUs under support/ld/. We need this to get the target-config.mk modifications implied by the addition of MCU_F1_LINE. We'll fix up some other performance-line-isms under libmaple/stm32f1 in a separate commit. Also in libmaple/usb/: - Move everything into a new stm32f1 directory. Due to aforementioned rules.mk hacks, there is no immediate need for an stm32f2 directory (USB support doesn't exist there). - Update the README for style and content. Signed-off-by: Marti Bolivar --- Makefile | 2 +- libmaple/include/libmaple/usb.h | 2 +- libmaple/usb/README | 69 +- libmaple/usb/rules.mk | 27 +- libmaple/usb/stm32f1/usb.c | 381 +++++++++++ libmaple/usb/stm32f1/usb_cdcacm.c | 762 +++++++++++++++++++++ libmaple/usb/stm32f1/usb_descriptors.h | 148 ++++ libmaple/usb/stm32f1/usb_lib_globals.h | 55 ++ libmaple/usb/stm32f1/usb_reg_map.c | 79 +++ libmaple/usb/stm32f1/usb_reg_map.h | 433 ++++++++++++ libmaple/usb/usb.c | 381 ----------- libmaple/usb/usb_cdcacm.c | 762 --------------------- libmaple/usb/usb_descriptors.h | 148 ---- libmaple/usb/usb_lib_globals.h | 55 -- libmaple/usb/usb_reg_map.c | 79 --- libmaple/usb/usb_reg_map.h | 433 ------------ .../stm32/series/stm32f1/value/vector_symbols.inc | 78 +++ support/make/board-includes/VLDiscovery.mk | 1 + support/make/board-includes/maple.mk | 1 + support/make/board-includes/maple_RET6.mk | 1 + support/make/board-includes/maple_mini.mk | 1 + support/make/board-includes/maple_native.mk | 1 + support/make/board-includes/olimex_stm32_h103.mk | 1 + support/make/target-config.mk | 6 +- wirish/include/wirish/usb_serial.h | 5 +- wirish/rules.mk | 4 +- wirish/stm32f1/boards_setup.cpp | 10 +- wirish/usb_serial.cpp | 9 + 28 files changed, 2015 insertions(+), 1919 deletions(-) create mode 100644 libmaple/usb/stm32f1/usb.c create mode 100644 libmaple/usb/stm32f1/usb_cdcacm.c create mode 100644 libmaple/usb/stm32f1/usb_descriptors.h create mode 100644 libmaple/usb/stm32f1/usb_lib_globals.h create mode 100644 libmaple/usb/stm32f1/usb_reg_map.c create mode 100644 libmaple/usb/stm32f1/usb_reg_map.h delete mode 100644 libmaple/usb/usb.c delete mode 100644 libmaple/usb/usb_cdcacm.c delete mode 100644 libmaple/usb/usb_descriptors.h delete mode 100644 libmaple/usb/usb_lib_globals.h delete mode 100644 libmaple/usb/usb_reg_map.c delete mode 100644 libmaple/usb/usb_reg_map.h create mode 100644 support/ld/stm32/series/stm32f1/value/vector_symbols.inc (limited to 'wirish/rules.mk') diff --git a/Makefile b/Makefile index 0784644..e3a1e4f 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 # The USB module is kept separate LIBMAPLE_MODULES += $(LIBMAPLE_MODULE_SERIES) # STM32 series submodule in libmaple LIBMAPLE_MODULES += $(SRCROOT)/wirish # Official libraries: diff --git a/libmaple/include/libmaple/usb.h b/libmaple/include/libmaple/usb.h index 82bace9..8555aca 100644 --- a/libmaple/include/libmaple/usb.h +++ b/libmaple/include/libmaple/usb.h @@ -1,7 +1,7 @@ /****************************************************************************** * The MIT License * - * Copyright (c) 2010 LeafLabs LLC. + * 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 diff --git a/libmaple/usb/README b/libmaple/usb/README index 2c55364..d0fca8d 100644 --- a/libmaple/usb/README +++ b/libmaple/usb/README @@ -1,35 +1,24 @@ -The USB submodule of libmaple is responsible for: - - Initializing the USB peripheral, scaling the peripheral clocks - appropriately, enabling the interrupt channels to USB, defining - the USB IRQ, resetting the USB DISC pin (used to tell the host - were alive). Additionally, the USB submodule defines the virtual - COM port interface that is exposed to user sketches via SerialUSB. - -To use it: - - SerialUSB.print/ln, available(), read(), write() implement the same - interface as Serial1/2/3. +The USB submodule of libmaple is a separate piece of the codebase for +reasons that are largely historical. Current Status: - Currently, the USB submodule relies on the low level core library - provided by ST to implement the USB transfer protocol for control - endpoint transfers. The high level virtual com port application - is unfortunately hard to untangle from this low level dependence, - and when a new USB core library is written (to nix ST dependence) - changes will likely have to be made to virtual com application - code. Ideally, the new core library should mimic the form of MyUSB - (LUFA), since this library (USB for AVR) is growing in popularity - and in example applications. + There's only support for the USB device peripheral found on + STM32F103s. - The virtual com port serves two important purposes. + We rely on the low level core library provided by ST to implement + the USB transfer protocol for control endpoint transfers. - 1) It allows serial data transfers between user sketches an a - host computer. + The virtual com port (which is exposed via + ) serves two important purposes. - 2) It allows the host machine to issue a system reset by - asserting the DTR signal. + 1) It allows serial data transfers between user sketches an a + host computer. + + 2) It allows the host PC to issue a system reset into the DFU + bootloader with the DTR + RTS + "1EAF" sequence (see + leaflabs.com/docs/bootloader.html for more information on + this). After reset, Maple will run the DFU bootloader for a few seconds, during which the user can begin a DFU upload operation (uploads @@ -38,11 +27,11 @@ Current Status: the chip in order to enable the bootloader. If you would like to develop your own USB application for whatever - reason (uses faster isochronous enpoints for streaming audio, or - implements the USB HID or Mass Storage specs for examples) then + reason (e.g. to use faster isochronous enpoints for streaming + audio, or implement the USB HID or Mass Storage specs), then ensure that you leave some hook for resetting Maple remotely in - order to spin up the DFU bootloader. Please make sure to give - yourself a unique vendor/product ID pair in your application, as + order to spin up the DFU bootloader. Please make sure to get + yourself a unique vendor/product ID pair for your application, as some operating systems will assign a host-side driver based on these tags. @@ -52,21 +41,23 @@ Current Status: be a burden from the host driver side, as Windows and *nix handle compound USB devices quite differently. - Be mindful that enabling the USB peripheral isnt "free." The + Be mindful that enabling the USB peripheral isn't "free." The device must respond to periodic bus activity (every few milliseconds) by servicing an ISR. Therefore, the USB application - should be disabled inside of timing critical applications. In - order to disconnect the device from the host, the USB_DISC pin can - be asserted (on Maple this is GPIO C12). Alternatively, the NVIC + should be disabled inside of timing critical applications. + + In order to disconnect the device from the host, a USB_DISC pin is + asserted (e.g. on Maple, this is PC12). Alternatively, the NVIC can be directly configured to disable the USB LP/HP IRQ's. The files inside of usb_lib were provided by ST and are subject to their own license, all other files were written by the LeafLabs team and fall under the MIT license. -Todo: +TODO: - - write custom low level USB stack to strip out any remaining - dependence on ST code - - add a high level USB application library that would allow users - to make their own HID/Mass Storage/Audio/Video devices. + - Generic USB driver core with series-provided backends, like + libopencm3 has. + - Strip out ST code. + - Integration with a high level USB library (like LUFA/MyUSB) to + allow users to write custom USB applications. diff --git a/libmaple/usb/rules.mk b/libmaple/usb/rules.mk index 816fad6..e8ccc15 100644 --- a/libmaple/usb/rules.mk +++ b/libmaple/usb/rules.mk @@ -3,20 +3,29 @@ 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) $(LIBMAPLE_PRIVATE_INCLUDES) -Wall +CFLAGS_$(d) = -I$(d) -I$(d)/$(MCU_SERIES) -I$(d)/usb_lib $(LIBMAPLE_INCLUDES) $(LIBMAPLE_PRIVATE_INCLUDES) -Wall + +# Add usblib and series subdirectory to BUILDDIRS. +BUILDDIRS += $(BUILD_PATH)/$(d)/$(MCU_SERIES) +BUILDDIRS += $(BUILD_PATH)/$(d)/usb_lib # 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 +cSRCS_$(d) := +# We currently only have F1 performance line support. Sigh. +ifeq ($(MCU_SERIES), stm32f1) +ifeq ($(MCU_F1_LINE), performance) +cSRCS_$(d) += $(MCU_SERIES)/usb.c +cSRCS_$(d) += $(MCU_SERIES)/usb_reg_map.c +cSRCS_$(d) += $(MCU_SERIES)/usb_cdcacm.c +cSRCS_$(d) += usb_lib/usb_core.c +cSRCS_$(d) += usb_lib/usb_init.c +cSRCS_$(d) += usb_lib/usb_mem.c +cSRCS_$(d) += usb_lib/usb_regs.c +endif +endif sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%) cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%) diff --git a/libmaple/usb/stm32f1/usb.c b/libmaple/usb/stm32f1/usb.c new file mode 100644 index 0000000..0130bab --- /dev/null +++ b/libmaple/usb/stm32f1/usb.c @@ -0,0 +1,381 @@ +/****************************************************************************** + * 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 libmaple/usb/usb.c + * @brief USB support. + * + * This is a mess. What we need almost amounts to a ground-up rewrite. + */ + +#include + +#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" + +static void dispatch_ctr_lp(void); + +/* + * usb_lib/ globals + */ + +uint16 SaveTState; /* caches TX status for later use */ +uint16 SaveRState; /* caches RX status for later use */ + +/* + * Other state + */ + +typedef enum { + RESUME_EXTERNAL, + RESUME_INTERNAL, + RESUME_LATER, + RESUME_WAIT, + RESUME_START, + RESUME_ON, + RESUME_OFF, + RESUME_ESOF +} RESUME_STATE; + +struct { + volatile RESUME_STATE eState; + volatile uint8 bESOFcnt; +} ResumeS; + +static usblib_dev usblib = { + .irq_mask = USB_ISR_MSK, + .state = USB_UNCONNECTED, + .clk_id = RCC_USB, +}; +usblib_dev *USBLIB = &usblib; + +/* + * Routines + */ + +void usb_init_usblib(usblib_dev *dev, + void (**ep_int_in)(void), + void (**ep_int_out)(void)) { + rcc_clk_enable(dev->clk_id); + + dev->ep_int_in = ep_int_in; + dev->ep_int_out = ep_int_out; + + /* usb_lib/ declares both and then assumes that pFoo points to Foo + * (even though the names don't always match), which is stupid for + * all of the obvious reasons, but whatever. Here we are. */ + pInformation = &Device_Info; + pProperty = &Device_Property; + pUser_Standard_Requests = &User_Standard_Requests; + + pInformation->ControlState = 2; /* FIXME [0.0.12] use + CONTROL_STATE enumerator */ + pProperty->Init(); +} + +static void usb_suspend(void) { + uint16 cntr; + + /* TODO decide if read/modify/write is really what we want + * (e.g. usb_resume_init() reconfigures CNTR). */ + cntr = USB_BASE->CNTR; + cntr |= USB_CNTR_FSUSP; + USB_BASE->CNTR = cntr; + cntr |= USB_CNTR_LP_MODE; + USB_BASE->CNTR = cntr; + + USBLIB->state = USB_SUSPENDED; +} + +static void usb_resume_init(void) { + uint16 cntr; + + cntr = USB_BASE->CNTR; + cntr &= ~USB_CNTR_LP_MODE; + USB_BASE->CNTR = cntr; + + /* Enable interrupt lines */ + USB_BASE->CNTR = USB_ISR_MSK; +} + +static void usb_resume(RESUME_STATE eResumeSetVal) { + uint16 cntr; + + if (eResumeSetVal != RESUME_ESOF) + ResumeS.eState = eResumeSetVal; + + switch (ResumeS.eState) + { + case RESUME_EXTERNAL: + usb_resume_init(); + ResumeS.eState = RESUME_OFF; + break; + case RESUME_INTERNAL: + usb_resume_init(); + ResumeS.eState = RESUME_START; + break; + case RESUME_LATER: + ResumeS.bESOFcnt = 2; + ResumeS.eState = RESUME_WAIT; + break; + case RESUME_WAIT: + ResumeS.bESOFcnt--; + if (ResumeS.bESOFcnt == 0) + ResumeS.eState = RESUME_START; + break; + case RESUME_START: + cntr = USB_BASE->CNTR; + cntr |= USB_CNTR_RESUME; + USB_BASE->CNTR = cntr; + ResumeS.eState = RESUME_ON; + ResumeS.bESOFcnt = 10; + break; + case RESUME_ON: + ResumeS.bESOFcnt--; + if (ResumeS.bESOFcnt == 0) { + cntr = USB_BASE->CNTR; + cntr &= ~USB_CNTR_RESUME; + USB_BASE->CNTR = cntr; + ResumeS.eState = RESUME_OFF; + } + break; + case RESUME_OFF: + case RESUME_ESOF: + default: + ResumeS.eState = RESUME_OFF; + break; + } +} + +#define SUSPEND_ENABLED 1 +void __irq_usb_lp_can_rx0(void) { + uint16 istr = USB_BASE->ISTR; + + /* Use USB_ISR_MSK to only include code for bits we care about. */ + +#if (USB_ISR_MSK & USB_ISTR_RESET) + if (istr & USB_ISTR_RESET & USBLIB->irq_mask) { + USB_BASE->ISTR = ~USB_ISTR_RESET; + pProperty->Reset(); + } +#endif + +#if (USB_ISR_MSK & USB_ISTR_PMAOVR) + if (istr & ISTR_PMAOVR & USBLIB->irq_mask) { + USB_BASE->ISTR = ~USB_ISTR_PMAOVR; + } +#endif + +#if (USB_ISR_MSK & USB_ISTR_ERR) + if (istr & USB_ISTR_ERR & USBLIB->irq_mask) { + USB_BASE->ISTR = ~USB_ISTR_ERR; + } +#endif + +#if (USB_ISR_MSK & USB_ISTR_WKUP) + if (istr & USB_ISTR_WKUP & USBLIB->irq_mask) { + USB_BASE->ISTR = ~USB_ISTR_WKUP; + usb_resume(RESUME_EXTERNAL); + } +#endif + +#if (USB_ISR_MSK & USB_ISTR_SUSP) + if (istr & USB_ISTR_SUSP & USBLIB->irq_mask) { + /* check if SUSPEND is possible */ + if (SUSPEND_ENABLED) { + usb_suspend(); + } else { + /* if not possible then resume after xx ms */ + usb_resume(RESUME_LATER); + } + /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */ + USB_BASE->ISTR = ~USB_ISTR_SUSP; +} +#endif + +#if (USB_ISR_MSK & USB_ISTR_SOF) + if (istr & USB_ISTR_SOF & USBLIB->irq_mask) { + USB_BASE->ISTR = ~USB_ISTR_SOF; + } +#endif + +#if (USB_ISR_MSK & USB_ISTR_ESOF) + if (istr & USB_ISTR_ESOF & USBLIB->irq_mask) { + USB_BASE->ISTR = ~USB_ISTR_ESOF; + /* resume handling timing is made with ESOFs */ + usb_resume(RESUME_ESOF); /* request without change of the machine state */ + } +#endif + + /* + * Service the correct transfer interrupt. + */ + +#if (USB_ISR_MSK & USB_ISTR_CTR) + if (istr & USB_ISTR_CTR & USBLIB->irq_mask) { + dispatch_ctr_lp(); + } +#endif +} + +/* + * Auxiliary routines + */ + +static inline uint8 dispatch_endpt_zero(uint16 istr_dir); +static inline void dispatch_endpt(uint8 ep); +static inline void set_rx_tx_status0(uint16 rx, uint16 tx); + +static void handle_setup0(void); +static void handle_in0(void); +static void handle_out0(void); + +static void dispatch_ctr_lp() { + uint16 istr; + while (((istr = USB_BASE->ISTR) & USB_ISTR_CTR) != 0) { + /* TODO WTF, figure this out: RM0008 says CTR is read-only, + * but ST's firmware claims it's clear-only, and emphasizes + * the importance of clearing it in more than one place. */ + USB_BASE->ISTR = ~USB_ISTR_CTR; + uint8 ep_id = istr & USB_ISTR_EP_ID; + if (ep_id == 0) { + /* TODO figure out why it's OK to break out of the loop + * once we're done serving endpoint zero, but not okay if + * there are multiple nonzero endpoint transfers to + * handle. */ + if (dispatch_endpt_zero(istr & USB_ISTR_DIR)) + return; + } else { + dispatch_endpt(ep_id); + } + } +} + +/* FIXME Dataflow on endpoint 0 RX/TX status is based off of ST's + * code, and is ugly/confusing in its use of SaveRState/SaveTState. + * Fixing this requires filling in handle_in0(), handle_setup0(), + * handle_out0(). */ +static inline uint8 dispatch_endpt_zero(uint16 istr_dir) { + uint32 epr = (uint16)USB_BASE->EP[0]; + + if (!(epr & (USB_EP_CTR_TX | USB_EP_SETUP | USB_EP_CTR_RX))) { + return 0; + } + + /* Cache RX/TX statuses in SaveRState/SaveTState, respectively. + * The various handle_foo0() may clobber these values + * before we reset them at the end of this routine. */ + SaveRState = epr & USB_EP_STAT_RX; + SaveTState = epr & USB_EP_STAT_TX; + + /* Set actual RX/TX statuses to NAK while we're thinking */ + set_rx_tx_status0(USB_EP_STAT_RX_NAK, USB_EP_STAT_TX_NAK); + + if (istr_dir == 0) { + /* ST RM0008: "If DIR bit=0, CTR_TX bit is set in the USB_EPnR + * register related to the interrupting endpoint. The + * interrupting transaction is of IN type (data transmitted by + * the USB peripheral to the host PC)." */ + ASSERT_FAULT(epr & USB_EP_CTR_TX); + usb_clear_ctr_tx(USB_EP0); + handle_in0(); + } else { + /* RM0008: "If DIR bit=1, CTR_RX bit or both CTR_TX/CTR_RX + * are set in the USB_EPnR register related to the + * interrupting endpoint. The interrupting transaction is of + * OUT type (data received by the USB peripheral from the host + * PC) or two pending transactions are waiting to be + * processed." + * + * [mbolivar] Note how the following control flow (which + * replicates ST's) doesn't seem to actually handle both + * interrupts that are ostensibly pending when both CTR_RX and + * CTR_TX are set. + * + * TODO sort this mess out. + */ + if (epr & USB_EP_CTR_TX) { + usb_clear_ctr_tx(USB_EP0); + handle_in0(); + } else { /* SETUP or CTR_RX */ + /* SETUP is held constant while CTR_RX is set, so clear it + * either way */ + usb_clear_ctr_rx(USB_EP0); + if (epr & USB_EP_SETUP) { + handle_setup0(); + } else { /* CTR_RX */ + handle_out0(); + } + } + } + + set_rx_tx_status0(SaveRState, SaveTState); + return 1; +} + +static inline void dispatch_endpt(uint8 ep) { + uint32 epr = USB_BASE->EP[ep]; + /* If ISTR_CTR is set and the ISTR gave us this EP_ID to handle, + * then presumably at least one of CTR_RX and CTR_TX is set, but + * again, ST's control flow allows for the possibility of neither. + * + * TODO try to find out if neither being set is possible. */ + if (epr & USB_EP_CTR_RX) { + usb_clear_ctr_rx(ep); + (USBLIB->ep_int_out[ep - 1])(); + } + if (epr & USB_EP_CTR_TX) { + usb_clear_ctr_tx(ep); + (USBLIB->ep_int_in[ep - 1])(); + } +} + +static inline void set_rx_tx_status0(uint16 rx, uint16 tx) { + usb_set_ep_rx_stat(USB_EP0, rx); + usb_set_ep_tx_stat(USB_EP0, tx); +} + +/* TODO Rip out usb_lib/ dependency from the following functions: */ + +static void handle_setup0(void) { + Setup0_Process(); +} + +static void handle_in0(void) { + In0_Process(); +} + +static void handle_out0(void) { + Out0_Process(); +} diff --git a/libmaple/usb/stm32f1/usb_cdcacm.c b/libmaple/usb/stm32f1/usb_cdcacm.c new file mode 100644 index 0000000..6ef4806 --- /dev/null +++ b/libmaple/usb/stm32f1/usb_cdcacm.c @@ -0,0 +1,762 @@ +/****************************************************************************** + * 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 libmaple/usb/usb_cdcacm.c + * @brief USB CDC ACM (a.k.a. virtual serial terminal, VCOM). + * + * FIXME: this works on the STM32F1 USB peripherals, and probably no + * place else. Nonportable bits really need to be factored out, and + * the result made cleaner. + */ + +#include + +#include +#include +#include + +/* 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" + +/****************************************************************************** + ****************************************************************************** + *** + *** HACK ALERT! FIXME FIXME FIXME FIXME! + *** + *** A bunch of LeafLabs-specific configuration lives in here for + *** now. This mess REALLY needs to get teased apart, with + *** appropriate pieces moved into Wirish. + *** + ****************************************************************************** + *****************************************************************************/ + +#if !(defined(BOARD_maple) || defined(BOARD_maple_RET6) || \ + defined(BOARD_maple_mini) || defined(BOARD_maple_native)) +#warning USB CDC ACM relies on LeafLabs board-specific configuration.\ + You may have problems on non-LeafLabs boards. +#endif + +static void vcomDataTxCb(void); +static void vcomDataRxCb(void); +static uint8* vcomGetSetLineCoding(uint16); + +static void usbInit(void); +static void usbReset(void); +static RESULT usbDataSetup(uint8 request); +static RESULT usbNoDataSetup(uint8 request); +static RESULT usbGetInterfaceSetting(uint8 interface, uint8 alt_setting); +static uint8* usbGetDeviceDescriptor(uint16 length); +static uint8* usbGetConfigDescriptor(uint16 length); +static uint8* usbGetStringDescriptor(uint16 length); +static void usbSetConfiguration(void); +static void usbSetDeviceAddress(void); + +static void wait_reset(void); + +/* + * VCOM config + */ + +#define VCOM_CTRL_EPNUM 0x00 +#define VCOM_CTRL_RX_ADDR 0x40 +#define VCOM_CTRL_TX_ADDR 0x80 +#define VCOM_CTRL_EPSIZE 0x40 + +#define VCOM_TX_ENDP 1 +#define VCOM_TX_EPNUM 0x01 +#define VCOM_TX_ADDR 0xC0 +#define VCOM_TX_EPSIZE 0x40 + +#define VCOM_NOTIFICATION_ENDP 2 +#define VCOM_NOTIFICATION_EPNUM 0x02 +#define VCOM_NOTIFICATION_ADDR 0x100 +#define VCOM_NOTIFICATION_EPSIZE 0x40 + +#define VCOM_RX_ENDP 3 +#define VCOM_RX_EPNUM 0x03 +#define VCOM_RX_ADDR 0x110 +#define VCOM_RX_EPSIZE 0x40 +#define VCOM_RX_BUFLEN (VCOM_RX_EPSIZE*3) + +/* + * CDC ACM Requests + */ + +#define SET_LINE_CODING 0x20 +#define GET_LINE_CODING 0x21 +#define SET_COMM_FEATURE 0x02 +#define SET_CONTROL_LINE_STATE 0x22 +#define CONTROL_LINE_DTR (0x01) +#define CONTROL_LINE_RTS (0x02) + +/* + * Descriptors + */ + +#define USB_DEVICE_CLASS_CDC 0x02 +#define USB_DEVICE_SUBCLASS_CDC 0x00 +#define LEAFLABS_ID_VENDOR 0x1EAF +#define MAPLE_ID_PRODUCT 0x0004 +const USB_Descriptor_Device usbVcomDescriptor_Device = { + .bLength = sizeof(USB_Descriptor_Device), + .bDescriptorType = USB_DESCRIPTOR_TYPE_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = USB_DEVICE_CLASS_CDC, + .bDeviceSubClass = USB_DEVICE_SUBCLASS_CDC, + .bDeviceProtocol = 0x00, + .bMaxPacketSize0 = 0x40, + .idVendor = LEAFLABS_ID_VENDOR, + .idProduct = MAPLE_ID_PRODUCT, + .bcdDevice = 0x0200, + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x00, + .bNumConfigurations = 0x01, +}; + +#define MAX_POWER (100 >> 1) +const USB_Descriptor_Config usbVcomDescriptor_Config = { + .Config_Header = { + .bLength = sizeof(USB_Descriptor_Config_Header), + .bDescriptorType = USB_DESCRIPTOR_TYPE_CONFIGURATION, + .wTotalLength = sizeof(USB_Descriptor_Config), + .bNumInterfaces = 0x02, + .bConfigurationValue = 0x01, + .iConfiguration = 0x00, + .bmAttributes = (USB_CONFIG_ATTR_BUSPOWERED | + USB_CONFIG_ATTR_SELF_POWERED), + .bMaxPower = MAX_POWER, + }, + + .CCI_Interface = { + .bLength = sizeof(USB_Descriptor_Interface), + .bDescriptorType = USB_DESCRIPTOR_TYPE_INTERFACE, + .bInterfaceNumber = 0x00, + .bAlternateSetting = 0x00, + .bNumEndpoints = 0x01, + .bInterfaceClass = USB_INTERFACE_CLASS_CDC, + .bInterfaceSubClass = USB_INTERFACE_SUBCLASS_CDC_ACM, + .bInterfaceProtocol = 0x01, /* Common AT Commands */ + .iInterface = 0x00, + }, + + .CDC_Functional_IntHeader = { + .bLength = CDC_FUNCTIONAL_DESCRIPTOR_SIZE(2), + .bDescriptorType = 0x24, + .SubType = 0x00, + .Data = {0x01, 0x10}, + }, + + .CDC_Functional_CallManagement = { + .bLength = CDC_FUNCTIONAL_DESCRIPTOR_SIZE(2), + .bDescriptorType = 0x24, + .SubType = 0x01, + .Data = {0x03, 0x01}, + }, + + .CDC_Functional_ACM = { + .bLength = CDC_FUNCTIONAL_DESCRIPTOR_SIZE(1), + .bDescriptorType = 0x24, + .SubType = 0x02, + .Data = {0x06}, + }, + + .CDC_Functional_Union = { + .bLength = CDC_FUNCTIONAL_DESCRIPTOR_SIZE(2), + .bDescriptorType = 0x24, + .SubType = 0x06, + .Data = {0x00, 0x01}, + }, + + .ManagementEndpoint = { + .bLength = sizeof(USB_Descriptor_Endpoint), + .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT, + .bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_IN | + VCOM_NOTIFICATION_EPNUM), + .bmAttributes = EP_TYPE_INTERRUPT, + .wMaxPacketSize = VCOM_NOTIFICATION_EPSIZE, + .bInterval = 0xFF, + }, + + .DCI_Interface = { + .bLength = sizeof(USB_Descriptor_Interface), + .bDescriptorType = USB_DESCRIPTOR_TYPE_INTERFACE, + .bInterfaceNumber = 0x01, + .bAlternateSetting = 0x00, + .bNumEndpoints = 0x02, + .bInterfaceClass = USB_INTERFACE_CLASS_DIC, + .bInterfaceSubClass = 0x00, /* None */ + .bInterfaceProtocol = 0x00, /* None */ + .iInterface = 0x00, + }, + + .DataOutEndpoint = { + .bLength = sizeof(USB_Descriptor_Endpoint), + .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT, + .bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_OUT | VCOM_RX_EPNUM), + .bmAttributes = EP_TYPE_BULK, + .wMaxPacketSize = VCOM_RX_EPSIZE, + .bInterval = 0x00, + }, + + .DataInEndpoint = { + .bLength = sizeof(USB_Descriptor_Endpoint), + .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT, + .bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_IN | VCOM_TX_EPNUM), + .bmAttributes = EP_TYPE_BULK, + .wMaxPacketSize = VCOM_TX_EPSIZE, + .bInterval = 0x00, + }, +}; + +/* + String Identifiers: + + we may choose to specify any or none of the following string + identifiers: + + iManufacturer: LeafLabs + iProduct: Maple + iSerialNumber: NONE + iConfiguration: NONE + iInterface(CCI): NONE + iInterface(DCI): NONE + + additionally we must provide the unicode language identifier, + which is 0x0409 for US English +*/ + +const uint8 usbVcomDescriptor_LangID[USB_DESCRIPTOR_STRING_LEN(1)] = { + USB_DESCRIPTOR_STRING_LEN(1), + USB_DESCRIPTOR_TYPE_STRING, + 0x09, + 0x04, +}; + +const uint8 usbVcomDescriptor_iManufacturer[USB_DESCRIPTOR_STRING_LEN(8)] = { + USB_DESCRIPTOR_STRING_LEN(8), + USB_DESCRIPTOR_TYPE_STRING, + 'L', 0, 'e', 0, 'a', 0, 'f', 0, + 'L', 0, 'a', 0, 'b', 0, 's', 0, +}; + +const uint8 usbVcomDescriptor_iProduct[USB_DESCRIPTOR_STRING_LEN(8)] = { + USB_DESCRIPTOR_STRING_LEN(8), + USB_DESCRIPTOR_TYPE_STRING, + 'M', 0, 'a', 0, 'p', 0, 'l', 0, + 'e', 0, ' ', 0, ' ', 0, ' ', 0 +}; + +ONE_DESCRIPTOR Device_Descriptor = { + (uint8*)&usbVcomDescriptor_Device, + sizeof(USB_Descriptor_Device) +}; + +ONE_DESCRIPTOR Config_Descriptor = { + (uint8*)&usbVcomDescriptor_Config, + sizeof(USB_Descriptor_Config) +}; + +ONE_DESCRIPTOR String_Descriptor[3] = { + {(uint8*)&usbVcomDescriptor_LangID, USB_DESCRIPTOR_STRING_LEN(1)}, + {(uint8*)&usbVcomDescriptor_iManufacturer,USB_DESCRIPTOR_STRING_LEN(8)}, + {(uint8*)&usbVcomDescriptor_iProduct, USB_DESCRIPTOR_STRING_LEN(8)} +}; + +/* + * Etc. + */ + +typedef enum { + DTR_UNSET, + DTR_HIGH, + DTR_NEGEDGE, + DTR_LOW +} RESET_STATE; + +typedef struct { + uint32 bitrate; + uint8 format; + uint8 paritytype; + uint8 datatype; +} USB_Line_Coding; + +uint8 last_request = 0; +USB_Line_Coding line_coding = { + .bitrate = 115200, + .format = 0x00, /* stop bits-1 */ + .paritytype = 0x00, + .datatype = 0x08 +}; +uint8 vcomBufferRx[VCOM_RX_BUFLEN]; +volatile uint32 countTx = 0; +volatile uint32 recvBufIn = 0; +volatile uint32 recvBufOut = 0; +volatile uint32 maxNewBytes = VCOM_RX_BUFLEN; +volatile uint32 newBytes = 0; +RESET_STATE reset_state = DTR_UNSET; +uint8 line_dtr_rts = 0; + +/* + * Endpoint callbacks + */ + +static void (*ep_int_in[7])(void) = + {vcomDataTxCb, + NOP_Process, + NOP_Process, + NOP_Process, + NOP_Process, + NOP_Process, + NOP_Process}; + +static void (*ep_int_out[7])(void) = + {NOP_Process, + NOP_Process, + vcomDataRxCb, + NOP_Process, + NOP_Process, + NOP_Process, + NOP_Process}; + +/* + * Globals required by usb_lib/ + */ + +#define NUM_ENDPTS 0x04 +DEVICE Device_Table = { + .Total_Endpoint = NUM_ENDPTS, + .Total_Configuration = 1 +}; + +#define MAX_PACKET_SIZE 0x40 /* 64B, maximum for USB FS Devices */ +DEVICE_PROP Device_Property = { + .Init = usbInit, + .Reset = usbReset, + .Process_Status_IN = NOP_Process, + .Process_Status_OUT = NOP_Process, + .Class_Data_Setup = usbDataSetup, + .Class_NoData_Setup = usbNoDataSetup, + .Class_Get_Interface_Setting = usbGetInterfaceSetting, + .GetDeviceDescriptor = usbGetDeviceDescriptor, + .GetConfigDescriptor = usbGetConfigDescriptor, + .GetStringDescriptor = usbGetStringDescriptor, + .RxEP_buffer = NULL, + .MaxPacketSize = MAX_PACKET_SIZE +}; + +USER_STANDARD_REQUESTS User_Standard_Requests = { + .User_GetConfiguration = NOP_Process, + .User_SetConfiguration = usbSetConfiguration, + .User_GetInterface = NOP_Process, + .User_SetInterface = NOP_Process, + .User_GetStatus = NOP_Process, + .User_ClearFeature = NOP_Process, + .User_SetEndPointFeature = NOP_Process, + .User_SetDeviceFeature = NOP_Process, + .User_SetDeviceAddress = usbSetDeviceAddress +}; + +/* + * CDC ACM interface + */ + +void usb_cdcacm_enable(gpio_dev *disc_dev, uint8 disc_bit) { + /* Present ourselves to the host */ + gpio_set_mode(disc_dev, disc_bit, GPIO_OUTPUT_PP); + gpio_write_bit(disc_dev, disc_bit, 0); // presents us to the host + + /* initialize USB peripheral */ + usb_init_usblib(USBLIB, ep_int_in, ep_int_out); +} + +void usb_cdcacm_disable(gpio_dev *disc_dev, uint8 disc_bit) { + // These are just guesses about how to do this, but it seems to work. + // TODO: verify this with USB spec + nvic_irq_disable(NVIC_USB_LP_CAN_RX0); + gpio_write_bit(disc_dev, disc_bit, 1); +} + +void usb_cdcacm_putc(char ch) { + while (!usb_cdcacm_tx((uint8*)&ch, 1)) + ; +} + +/* This function is non-blocking. + * + * It copies data from a usercode buffer into the USB peripheral TX + * buffer and return the number placed in that buffer. + */ +uint32 usb_cdcacm_tx(const uint8* buf, uint32 len) { + /* Last transmission hasn't finished, abort */ + if (countTx) { + return 0; + } + + // We can only put VCOM_TX_EPSIZE bytes in the buffer + /* FIXME then why are we only copying half as many? */ + if (len > VCOM_TX_EPSIZE / 2) { + len = VCOM_TX_EPSIZE / 2; + } + + // Try to load some bytes if we can + if (len) { + usb_copy_to_pma(buf, len, VCOM_TX_ADDR); + usb_set_ep_tx_count(VCOM_TX_ENDP, len); + countTx += len; + usb_set_ep_tx_stat(VCOM_TX_ENDP, USB_EP_STAT_TX_VALID); + } + + return len; +} + +/* returns the number of available bytes are in the recv FIFO */ +uint32 usb_cdcacm_data_available(void) { + return newBytes; +} + +uint16 usb_cdcacm_get_pending() { + return countTx; +} + +/* Nonblocking byte receive. + * + * Copies up to len bytes from our private data buffer (*NOT* the PMA) + * into buf and deq's the FIFO. */ +uint32 usb_cdcacm_rx(uint8* buf, uint32 len) { + static int offset = 0; + int i; + + if (len > newBytes) { + len = newBytes; + } + + for (i = 0; i < len; i++) { + buf[i] = vcomBufferRx[i + offset]; + } + + newBytes -= len; + offset += len; + + /* Re-enable the RX endpoint, which we had set to receive 0 bytes */ + if (newBytes == 0) { + usb_set_ep_rx_count(VCOM_RX_ENDP, VCOM_RX_EPSIZE); + usb_set_ep_rx_stat(VCOM_RX_ENDP, USB_EP_STAT_RX_VALID); + offset = 0; + } + + return len; +} + +uint8 usb_cdcacm_get_dtr() { + return ((line_dtr_rts & CONTROL_LINE_DTR) != 0); +} + +uint8 usb_cdcacm_get_rts() { + return ((line_dtr_rts & CONTROL_LINE_RTS) != 0); +} + +/* + * Callbacks + */ + +static void vcomDataTxCb(void) { + /* assumes tx transactions are atomic 64 bytes (nearly certain they are) */ + countTx = 0; +} + +#define EXC_RETURN 0xFFFFFFF9 +#define DEFAULT_CPSR 0x61000000 +static void vcomDataRxCb(void) { + /* FIXME this is mad buggy */ + + /* setEPRxCount on the previous cycle should garuntee + we havnt received more bytes than we can fit */ + newBytes = usb_get_ep_rx_count(VCOM_RX_ENDP); + usb_set_ep_rx_stat(VCOM_RX_ENDP, USB_EP_STAT_RX_NAK); + + /* magic number, {0x31, 0x45, 0x41, 0x46} is "1EAF" */ + uint8 chkBuf[4]; + uint8 cmpBuf[4] = {0x31, 0x45, 0x41, 0x46}; + if (reset_state == DTR_NEGEDGE) { + reset_state = DTR_LOW; + + if (newBytes >= 4) { + unsigned int target = (unsigned int)wait_reset | 0x1; + + usb_copy_from_pma(chkBuf, 4, VCOM_RX_ADDR); + + int i; + USB_Bool cmpMatch = TRUE; + for (i = 0; i < 4; i++) { + if (chkBuf[i] != cmpBuf[i]) { + cmpMatch = FALSE; + } + } + + if (cmpMatch) { + asm volatile("mov r0, %[stack_top] \n\t" // Reset stack + "mov sp, r0 \n\t" + "mov r0, #1 \n\t" + "mov r1, %[target_addr] \n\t" + "mov r2, %[cpsr] \n\t" + "push {r2} \n\t" // Fake xPSR + "push {r1} \n\t" // PC target addr + "push {r0} \n\t" // Fake LR + "push {r0} \n\t" // Fake R12 + "push {r0} \n\t" // Fake R3 + "push {r0} \n\t" // Fake R2 + "push {r0} \n\t" // Fake R1 + "push {r0} \n\t" // Fake R0 + "mov lr, %[exc_return] \n\t" + "bx lr" + : + : [stack_top] "r" (STACK_TOP), + [target_addr] "r" (target), + [exc_return] "r" (EXC_RETURN), + [cpsr] "r" (DEFAULT_CPSR) + : "r0", "r1", "r2"); + /* should never get here */ + } + } + } + + usb_copy_from_pma(vcomBufferRx, newBytes, VCOM_RX_ADDR); +} + +static uint8* vcomGetSetLineCoding(uint16 length) { + if (length == 0) { + pInformation->Ctrl_Info.Usb_wLength = sizeof(USB_Line_Coding); + } + return (uint8*)&line_coding; +} + +static void usbInit(void) { + pInformation->Current_Configuration = 0; + + USB_BASE->CNTR = USB_CNTR_FRES; + + USBLIB->irq_mask = 0; + USB_BASE->CNTR = USBLIB->irq_mask; + USB_BASE->ISTR = 0; + USBLIB->irq_mask = USB_CNTR_RESETM | USB_CNTR_SUSPM | USB_CNTR_WKUPM; + USB_BASE->CNTR = USBLIB->irq_mask; + + USB_BASE->ISTR = 0; + USBLIB->irq_mask = USB_ISR_MSK; + USB_BASE->CNTR = USBLIB->irq_mask; + + nvic_irq_enable(NVIC_USB_LP_CAN_RX0); + USBLIB->state = USB_UNCONNECTED; +} + +/* choose addresses to give endpoints the max 64 byte buffers */ +#define BTABLE_ADDRESS 0x00 +static void usbReset(void) { + pInformation->Current_Configuration = 0; + + /* current feature is current bmAttributes */ + pInformation->Current_Feature = (USB_CONFIG_ATTR_BUSPOWERED | + USB_CONFIG_ATTR_SELF_POWERED); + + USB_BASE->BTABLE = BTABLE_ADDRESS; + + /* setup control endpoint 0 */ + usb_set_ep_type(USB_EP0, USB_EP_EP_TYPE_CONTROL); + usb_set_ep_tx_stat(USB_EP0, USB_EP_STAT_TX_STALL); + usb_set_ep_rx_addr(USB_EP0, VCOM_CTRL_RX_ADDR); + usb_set_ep_tx_addr(USB_EP0, VCOM_CTRL_TX_ADDR); + usb_clear_status_out(USB_EP0); + + usb_set_ep_rx_count(USB_EP0, pProperty->MaxPacketSize); + usb_set_ep_rx_stat(USB_EP0, USB_EP_STAT_RX_VALID); + + /* setup management endpoint 1 */ + usb_set_ep_type(VCOM_NOTIFICATION_ENDP, USB_EP_EP_TYPE_INTERRUPT); + usb_set_ep_tx_addr(VCOM_NOTIFICATION_ENDP, VCOM_NOTIFICATION_ADDR); + usb_set_ep_tx_stat(VCOM_NOTIFICATION_ENDP, USB_EP_STAT_TX_NAK); + usb_set_ep_rx_stat(VCOM_NOTIFICATION_ENDP, USB_EP_STAT_RX_DISABLED); + + /* TODO figure out differences in style between RX/TX EP setup */ + + /* set up data endpoint OUT (RX) */ + usb_set_ep_type(VCOM_RX_ENDP, USB_EP_EP_TYPE_BULK); + usb_set_ep_rx_addr(VCOM_RX_ENDP, 0x110); + usb_set_ep_rx_count(VCOM_RX_ENDP, 64); + usb_set_ep_rx_stat(VCOM_RX_ENDP, USB_EP_STAT_RX_VALID); + + /* set up data endpoint IN (TX) */ + usb_set_ep_type(VCOM_TX_ENDP, USB_EP_EP_TYPE_BULK); + usb_set_ep_tx_addr(VCOM_TX_ENDP, VCOM_TX_ADDR); + usb_set_ep_tx_stat(VCOM_TX_ENDP, USB_EP_STAT_TX_NAK); + usb_set_ep_rx_stat(VCOM_TX_ENDP, USB_EP_STAT_RX_DISABLED); + + USBLIB->state = USB_ATTACHED; + SetDeviceAddress(0); + + /* reset the rx fifo */ + recvBufIn = 0; + recvBufOut = 0; + maxNewBytes = VCOM_RX_EPSIZE; + countTx = 0; +} + +static RESULT usbDataSetup(uint8 request) { + uint8 *(*CopyRoutine)(uint16); + CopyRoutine = NULL; + + if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) { + switch (request) { + case (GET_LINE_CODING): + CopyRoutine = vcomGetSetLineCoding; + last_request = GET_LINE_CODING; + break; + case (SET_LINE_CODING): + CopyRoutine = vcomGetSetLineCoding; + last_request = SET_LINE_CODING; + break; + default: + break; + } + } + + if (CopyRoutine == NULL) { + return USB_UNSUPPORT; + } + + pInformation->Ctrl_Info.CopyData = CopyRoutine; + pInformation->Ctrl_Info.Usb_wOffset = 0; + (*CopyRoutine)(0); + return USB_SUCCESS; +} + +static RESULT usbNoDataSetup(uint8 request) { + uint8 new_signal; + + /* we support set com feature but dont handle it */ + if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) { + + switch (request) { + case (SET_COMM_FEATURE): + return USB_SUCCESS; + case (SET_CONTROL_LINE_STATE): + /* to reset the board, pull both dtr and rts low + then pulse dtr by itself */ + new_signal = (pInformation->USBwValues.bw.bb0 & + (CONTROL_LINE_DTR | CONTROL_LINE_RTS)); + line_dtr_rts = new_signal & 0x03; + + switch (reset_state) { + /* no default, covered enum */ + case DTR_UNSET: + if ((new_signal & CONTROL_LINE_DTR) == 0 ) { + reset_state = DTR_LOW; + } else { + reset_state = DTR_HIGH; + } + break; + + case DTR_HIGH: + if ((new_signal & CONTROL_LINE_DTR) == 0 ) { + reset_state = DTR_NEGEDGE; + } else { + reset_state = DTR_HIGH; + } + break; + + case DTR_NEGEDGE: + if ((new_signal & CONTROL_LINE_DTR) == 0 ) { + reset_state = DTR_LOW; + } else { + reset_state = DTR_HIGH; + } + break; + + case DTR_LOW: + if ((new_signal & CONTROL_LINE_DTR) == 0 ) { + reset_state = DTR_LOW; + } else { + reset_state = DTR_HIGH; + } + break; + } + + return USB_SUCCESS; + } + } + return USB_UNSUPPORT; +} + +static RESULT usbGetInterfaceSetting(uint8 interface, uint8 alt_setting) { + if (alt_setting > 0) { + return USB_UNSUPPORT; + } else if (interface > 1) { + return USB_UNSUPPORT; + } + + return USB_SUCCESS; +} + +static uint8* usbGetDeviceDescriptor(uint16 length) { + return Standard_GetDescriptorData(length, &Device_Descriptor); +} + +static uint8* usbGetConfigDescriptor(uint16 length) { + return Standard_GetDescriptorData(length, &Config_Descriptor); +} + +static uint8* usbGetStringDescriptor(uint16 length) { + uint8 wValue0 = pInformation->USBwValue0; + + if (wValue0 > 2) { + return NULL; + } + return Standard_GetDescriptorData(length, &String_Descriptor[wValue0]); +} + +static void usbSetConfiguration(void) { + if (pInformation->Current_Configuration != 0) { + USBLIB->state = USB_CONFIGURED; + } +} + +static void usbSetDeviceAddress(void) { + USBLIB->state = USB_ADDRESSED; +} + +#define RESET_DELAY 100000 +static void wait_reset(void) { + delay_us(RESET_DELAY); + nvic_sys_reset(); +} diff --git a/libmaple/usb/stm32f1/usb_descriptors.h b/libmaple/usb/stm32f1/usb_descriptors.h new file mode 100644 index 0000000..9bcb2b6 --- /dev/null +++ b/libmaple/usb/stm32f1/usb_descriptors.h @@ -0,0 +1,148 @@ +/****************************************************************************** + * 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. + *****************************************************************************/ + +#ifndef _USB_DESCRIPTORS_H_ +#define _USB_DESCRIPTORS_H_ + +#include + +#define USB_DESCRIPTOR_TYPE_DEVICE 0x01 +#define USB_DESCRIPTOR_TYPE_CONFIGURATION 0x02 +#define USB_DESCRIPTOR_TYPE_STRING 0x03 +#define USB_DESCRIPTOR_TYPE_INTERFACE 0x04 +#define USB_DESCRIPTOR_TYPE_ENDPOINT 0x05 + +#define USB_DEVICE_CLASS_CDC 0x02 +#define USB_DEVICE_SUBCLASS_CDC 0x00 +#define USB_INTERFACE_CLASS_CDC 0x02 +/* CDC Abstract Control Model */ +#define USB_INTERFACE_SUBCLASS_CDC_ACM 0x02 +#define USB_INTERFACE_CLASS_DIC 0x0A + +#define USB_CONFIG_ATTR_BUSPOWERED 0b10000000 +#define USB_CONFIG_ATTR_SELF_POWERED 0b11000000 + +#define EP_TYPE_INTERRUPT 0x03 +#define EP_TYPE_BULK 0x02 + +#define USB_DESCRIPTOR_ENDPOINT_IN 0x80 +#define USB_DESCRIPTOR_ENDPOINT_OUT 0x00 + +#define USB_DESCRIPTOR_STRING_LEN(x) (2 + (x << 1)) + +#if defined(__cplusplus) +extern "C" { +#endif + +#define USB_DESCRIPTOR_STRING(len) \ + struct { \ + uint8 bLength; \ + uint8 bDescriptorType; \ + uint16 bString[len]; \ + } __packed + +#define CDC_FUNCTIONAL_DESCRIPTOR_SIZE(DataSize) (3 + DataSize) +#define CDC_FUNCTIONAL_DESCRIPTOR(DataSize) \ + struct { \ + uint8 bLength; \ + uint8 bDescriptorType; \ + uint8 SubType; \ + uint8 Data[DataSize]; \ + } __packed + +typedef struct { + uint8 bLength; + uint8 bDescriptorType; + uint16 bcdUSB; + uint8 bDeviceClass; + uint8 bDeviceSubClass; + uint8 bDeviceProtocol; + uint8 bMaxPacketSize0; + uint16 idVendor; + uint16 idProduct; + uint16 bcdDevice; + uint8 iManufacturer; + uint8 iProduct; + uint8 iSerialNumber; + uint8 bNumConfigurations; +} __packed USB_Descriptor_Device; + +typedef struct { + uint8 bLength; + uint8 bDescriptorType; + uint16 wTotalLength; + uint8 bNumInterfaces; + uint8 bConfigurationValue; + uint8 iConfiguration; + uint8 bmAttributes; + uint8 bMaxPower; +} __packed USB_Descriptor_Config_Header; + +typedef struct { + uint8 bLength; + uint8 bDescriptorType; + uint8 bInterfaceNumber; + uint8 bAlternateSetting; + uint8 bNumEndpoints; + uint8 bInterfaceClass; + uint8 bInterfaceSubClass; + uint8 bInterfaceProtocol; + uint8 iInterface; +} __packed USB_Descriptor_Interface; + +typedef struct { + uint8 bLength; + uint8 bDescriptorType; + uint8 bEndpointAddress; + uint8 bmAttributes; + uint16 wMaxPacketSize; + uint8 bInterval; +} __packed USB_Descriptor_Endpoint; + +typedef struct { + USB_Descriptor_Config_Header Config_Header; + USB_Descriptor_Interface CCI_Interface; + CDC_FUNCTIONAL_DESCRIPTOR(2) CDC_Functional_IntHeader; + CDC_FUNCTIONAL_DESCRIPTOR(2) CDC_Functional_CallManagement; + CDC_FUNCTIONAL_DESCRIPTOR(1) CDC_Functional_ACM; + CDC_FUNCTIONAL_DESCRIPTOR(2) CDC_Functional_Union; + USB_Descriptor_Endpoint ManagementEndpoint; + USB_Descriptor_Interface DCI_Interface; + USB_Descriptor_Endpoint DataOutEndpoint; + USB_Descriptor_Endpoint DataInEndpoint; +} __packed USB_Descriptor_Config; + +typedef struct { + uint8 bLength; + uint8 bDescriptorType; + uint16 bString[]; +} USB_Descriptor_String; + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/libmaple/usb/stm32f1/usb_lib_globals.h b/libmaple/usb/stm32f1/usb_lib_globals.h new file mode 100644 index 0000000..1cd2754 --- /dev/null +++ b/libmaple/usb/stm32f1/usb_lib_globals.h @@ -0,0 +1,55 @@ +/****************************************************************************** + * 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. + *****************************************************************************/ + +#ifndef _USB_LIB_GLOBALS_H_ +#define _USB_LIB_GLOBALS_H_ + +/* usb_lib headers */ +#include "usb_type.h" +#include "usb_core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern USER_STANDARD_REQUESTS User_Standard_Requests; +extern USER_STANDARD_REQUESTS *pUser_Standard_Requests; + +extern DEVICE_PROP Device_Property; +extern DEVICE_PROP *pProperty; + +extern DEVICE_INFO Device_Info; +extern DEVICE_INFO *pInformation; + +extern DEVICE Device_Table; +extern u16 SaveRState; +extern u16 SaveTState; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libmaple/usb/stm32f1/usb_reg_map.c b/libmaple/usb/stm32f1/usb_reg_map.c new file mode 100644 index 0000000..75562e1 --- /dev/null +++ b/libmaple/usb/stm32f1/usb_reg_map.c @@ -0,0 +1,79 @@ +/****************************************************************************** + * 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. + *****************************************************************************/ + +#include "usb_reg_map.h" + +/* TODO these could use some improvement; they're fairly + * straightforward ports of the analogous ST code. The PMA blit + * routines in particular are obvious targets for performance + * measurement and tuning. */ + +void usb_copy_to_pma(const uint8 *buf, uint16 len, uint16 pma_offset) { + uint16 *dst = (uint16*)usb_pma_ptr(pma_offset); + uint16 n = len >> 1; + uint16 i; + for (i = 0; i < n; i++) { + *dst = (uint16)(*buf) | *(buf + 1) << 8; + buf += 2; + dst += 2; + } + if (len & 1) { + *dst = *buf; + } +} + +void usb_copy_from_pma(uint8 *buf, uint16 len, uint16 pma_offset) { + uint32 *src = (uint32*)usb_pma_ptr(pma_offset); + uint16 *dst = (uint16*)buf; + uint16 n = len >> 1; + uint16 i; + for (i = 0; i < n; i++) { + *dst++ = *src++; + } + if (len & 1) { + *dst = *src & 0xFF; + } +} + +void usb_set_ep_rx_count(uint8 ep, uint16 count) { + uint32 *rxc = usb_ep_rx_count_ptr(ep); + uint16 nblocks; + if (count > 62) { + /* use 32-byte memory block size */ + nblocks = count >> 5; + if ((count & 0x1F) == 0) { + nblocks--; + } + *rxc = (nblocks << 10) | 0x8000; + } else { + /* use 2-byte memory block size */ + nblocks = count >> 1; + if ((count & 0x1) != 0) { + nblocks++; + } + *rxc = nblocks << 10; + } +} diff --git a/libmaple/usb/stm32f1/usb_reg_map.h b/libmaple/usb/stm32f1/usb_reg_map.h new file mode 100644 index 0000000..ce80842 --- /dev/null +++ b/libmaple/usb/stm32f1/usb_reg_map.h @@ -0,0 +1,433 @@ +/****************************************************************************** + * 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. + *****************************************************************************/ + +#include +#include + +#ifndef _USB_REG_MAP_H_ +#define _USB_REG_MAP_H_ + +/* TODO: + * - Pick one of "endp", "ep" "endpt" + */ + +/* + * Register map and base pointer + */ + +#define USB_NR_EP_REGS 8 + +/** USB register map type */ +typedef struct usb_reg_map { + __io uint32 EP[USB_NR_EP_REGS]; /**< Endpoint registers */ + const uint32 RESERVED[8]; /**< Reserved */ + __io uint32 CNTR; /**< Control register */ + __io uint32 ISTR; /**< Interrupt status register */ + __io uint32 FNR; /**< Frame number register */ + __io uint32 DADDR; /**< Device address */ + __io uint32 BTABLE; /**< @brief Buffer table address + * + * Address offset within the USB + * packet memory area which points + * to the base of the buffer + * descriptor table. Must be + * aligned to an 8 byte boundary. + */ +} usb_reg_map; + +/** USB register map base pointer */ +#define USB_BASE ((struct usb_reg_map*)0x40005C00) + +/* + * Register bit definitions + */ + +/* Endpoint registers (USB_EPnR) */ + +#define USB_EP_CTR_RX_BIT 15 +#define USB_EP_DTOG_RX_BIT 14 +#define USB_EP_SETUP_BIT 11 +#define USB_EP_EP_KIND_BIT 8 +#define USB_EP_CTR_TX_BIT 7 +#define USB_EP_DTOG_TX_BIT 6 + +#define USB_EP_CTR_RX BIT(USB_EP_CTR_RX_BIT) +#define USB_EP_DTOG_RX BIT(USB_EP_DTOG_RX_BIT) +#define USB_EP_STAT_RX (0x3 << 12) +#define USB_EP_STAT_RX_DISABLED (0x0 << 12) +#define USB_EP_STAT_RX_STALL (0x1 << 12) +#define USB_EP_STAT_RX_NAK (0x2 << 12) +#define USB_EP_STAT_RX_VALID (0x3 << 12) +#define USB_EP_SETUP BIT(USB_EP_SETUP_BIT) +#define USB_EP_EP_TYPE (0x3 << 9) +#define USB_EP_EP_TYPE_BULK (0x0 << 9) +#define USB_EP_EP_TYPE_CONTROL (0x1 << 9) +#define USB_EP_EP_TYPE_ISO (0x2 << 9) +#define USB_EP_EP_TYPE_INTERRUPT (0x3 << 9) +#define USB_EP_EP_KIND BIT(USB_EP_EP_KIND_BIT) +#define USB_EP_CTR_TX BIT(USB_EP_CTR_TX_BIT) +#define USB_EP_DTOG_TX BIT(USB_EP_DTOG_TX_BIT) +#define USB_EP_STAT_TX (0x3 << 4) +#define USB_EP_STAT_TX_DISABLED (0x0 << 4) +#define USB_EP_STAT_TX_STALL (0x1 << 4) +#define USB_EP_STAT_TX_NAK (0x2 << 4) +#define USB_EP_STAT_TX_VALID (0x3 << 4) +#define USB_EP_EA 0xF + +/* Control register (USB_CNTR) */ + +#define USB_CNTR_CTRM_BIT 15 +#define USB_CNTR_PMAOVERM_BIT 14 +#define USB_CNTR_ERRM_BIT 13 +#define USB_CNTR_WKUPM_BIT 12 +#define USB_CNTR_SUSPM_BIT 11 +#define USB_CNTR_RESETM_BIT 10 +#define USB_CNTR_SOFM_BIT 9 +#define USB_CNTR_ESOFM_BIT 8 +#define USB_CNTR_RESUME_BIT 4 +#define USB_CNTR_FSUSP_BIT 3 +#define USB_CNTR_LP_MODE_BIT 2 +#define USB_CNTR_PDWN_BIT 1 +#define USB_CNTR_FRES_BIT 0 + +#define USB_CNTR_CTRM BIT(USB_CNTR_CTRM_BIT) +#define USB_CNTR_PMAOVERM BIT(USB_CNTR_PMAOVERM_BIT) +#define USB_CNTR_ERRM BIT(USB_CNTR_ERRM_BIT) +#define USB_CNTR_WKUPM BIT(USB_CNTR_WKUPM_BIT) +#define USB_CNTR_SUSPM BIT(USB_CNTR_SUSPM_BIT) +#define USB_CNTR_RESETM BIT(USB_CNTR_RESETM_BIT) +#define USB_CNTR_SOFM BIT(USB_CNTR_SOFM_BIT) +#define USB_CNTR_ESOFM BIT(USB_CNTR_ESOFM_BIT) +#define USB_CNTR_RESUME BIT(USB_CNTR_RESUME_BIT) +#define USB_CNTR_FSUSP BIT(USB_CNTR_FSUSP_BIT) +#define USB_CNTR_LP_MODE BIT(USB_CNTR_LP_MODE_BIT) +#define USB_CNTR_PDWN BIT(USB_CNTR_PDWN_BIT) +#define USB_CNTR_FRES BIT(USB_CNTR_FRES_BIT) + +/* Interrupt status register (USB_ISTR) */ + +#define USB_ISTR_CTR_BIT 15 +#define USB_ISTR_PMAOVR_BIT 14 +#define USB_ISTR_ERR_BIT 13 +#define USB_ISTR_WKUP_BIT 12 +#define USB_ISTR_SUSP_BIT 11 +#define USB_ISTR_RESET_BIT 10 +#define USB_ISTR_SOF_BIT 9 +#define USB_ISTR_ESOF_BIT 8 +#define USB_ISTR_DIR_BIT 4 + +#define USB_ISTR_CTR BIT(USB_ISTR_CTR_BIT) +#define USB_ISTR_PMAOVR BIT(USB_ISTR_PMAOVR_BIT) +#define USB_ISTR_ERR BIT(USB_ISTR_ERR_BIT) +#define USB_ISTR_WKUP BIT(USB_ISTR_WKUP_BIT) +#define USB_ISTR_SUSP BIT(USB_ISTR_SUSP_BIT) +#define USB_ISTR_RESET BIT(USB_ISTR_RESET_BIT) +#define USB_ISTR_SOF BIT(USB_ISTR_SOF_BIT) +#define USB_ISTR_ESOF BIT(USB_ISTR_ESOF_BIT) +#define USB_ISTR_DIR BIT(USB_ISTR_DIR_BIT) +#define USB_ISTR_EP_ID 0xF + +/* Frame number register (USB_FNR) */ + +#define USB_FNR_RXDP_BIT 15 +#define USB_FNR_RXDM_BIT 14 +#define USB_FNR_LCK_BIT 13 + +#define USB_FNR_RXDP BIT(USB_FNR_RXDP_BIT) +#define USB_FNR_RXDM BIT(USB_FNR_RXDM_BIT) +#define USB_FNR_LCK BIT(USB_FNR_LCK_BIT) +#define USB_FNR_LSOF (0x3 << 11) +#define USB_FNR_FN 0x7FF + +/* Device address (USB_DADDR) */ + +#define USB_DADDR_EF_BIT 7 +#define USB_DADDR_ADD6_BIT 6 +#define USB_DADDR_ADD5_BIT 5 +#define USB_DADDR_ADD4_BIT 4 +#define USB_DADDR_ADD3_BIT 3 +#define USB_DADDR_ADD2_BIT 2 +#define USB_DADDR_ADD1_BIT 1 +#define USB_DADDR_ADD0_BIT 0 + +#define USB_DADDR_EF BIT(USB_DADDR_EF_BIT) +#define USB_DADDR_ADD6 BIT(USB_DADDR_ADD6_BIT) +#define USB_DADDR_ADD5 BIT(USB_DADDR_ADD5_BIT) +#define USB_DADDR_ADD4 BIT(USB_DADDR_ADD4_BIT) +#define USB_DADDR_ADD3 BIT(USB_DADDR_ADD3_BIT) +#define USB_DADDR_ADD2 BIT(USB_DADDR_ADD2_BIT) +#define USB_DADDR_ADD1 BIT(USB_DADDR_ADD1_BIT) +#define USB_DADDR_ADD0 BIT(USB_DADDR_ADD0_BIT) + +/* Buffer table address (USB_BTABLE) */ + +#define USB_BTABLE_BTABLE (0x1FFF << 3) + +/* + * Register convenience routines + */ + +#define __EP_CTR_NOP (USB_EP_CTR_RX | USB_EP_CTR_TX) +#define __EP_NONTOGGLE (USB_EP_CTR_RX | USB_EP_SETUP | \ + USB_EP_EP_TYPE | USB_EP_EP_KIND | \ + USB_EP_CTR_TX | USB_EP_EA) + +static inline void usb_clear_ctr_rx(uint8 ep) { + uint32 epr = USB_BASE->EP[ep]; + USB_BASE->EP[ep] = epr & ~USB_EP_CTR_RX & __EP_NONTOGGLE; +} + +static inline void usb_clear_ctr_tx(uint8 ep) { + uint32 epr = USB_BASE->EP[ep]; + USB_BASE->EP[ep] = epr & ~USB_EP_CTR_TX & __EP_NONTOGGLE; +} + +static inline void usb_set_ep_rx_stat(uint8 ep, uint32 status) { + uint32 epr = USB_BASE->EP[ep]; + epr &= ~(USB_EP_STAT_TX | USB_EP_DTOG_RX | USB_EP_DTOG_TX); + epr |= __EP_CTR_NOP; + epr ^= status; + USB_BASE->EP[ep] = epr; +} + +static inline void usb_set_ep_tx_stat(uint8 ep, uint32 status) { + uint32 epr = USB_BASE->EP[ep]; + epr &= ~(USB_EP_STAT_RX | USB_EP_DTOG_RX | USB_EP_DTOG_TX); + epr |= __EP_CTR_NOP; + epr ^= status; + USB_BASE->EP[ep] = epr; +} + +static inline void usb_set_ep_type(uint8 ep, uint32 type) { + uint32 epr = USB_BASE->EP[ep]; + epr &= ~USB_EP_EP_TYPE & __EP_NONTOGGLE; + epr |= type; + USB_BASE->EP[ep] = epr; +} + +static inline void usb_set_ep_kind(uint8 ep, uint32 kind) { + uint32 epr = USB_BASE->EP[ep]; + epr &= ~USB_EP_EP_KIND & __EP_NONTOGGLE; + epr |= kind; + USB_BASE->EP[ep] = epr; +} + +static inline void usb_clear_status_out(uint8 ep) { + usb_set_ep_kind(ep, 0); +} + +/* + * Packet memory area (PMA) base pointer + */ + +/** + * @brief USB packet memory area (PMA) base pointer. + * + * The USB PMA is SRAM shared between USB and CAN. The USB peripheral + * accesses this memory directly via the packet buffer interface. */ +#define USB_PMA_BASE ((__io void*)0x40006000) + +/* + * PMA conveniences + */ + +void usb_copy_to_pma(const uint8 *buf, uint16 len, uint16 pma_offset); +void usb_copy_from_pma(uint8 *buf, uint16 len, uint16 pma_offset); + +static inline void* usb_pma_ptr(uint32 offset) { + return (void*)(USB_PMA_BASE + 2 * offset); +} + +/* + * BTABLE + */ + +/* (Forward-declared) BTABLE entry. + * + * The BTABLE can be viewed as an array of usb_btable_ent values; + * these vary in structure according to the configuration of the + * endpoint. + */ +union usb_btable_ent; + +/* Bidirectional endpoint BTABLE entry */ +typedef struct usb_btable_bidi { + __io uint16 addr_tx; const uint16 PAD1; + __io uint16 count_tx; const uint16 PAD2; + __io uint16 addr_rx; const uint16 PAD3; + __io uint16 count_rx; const uint16 PAD4; +} usb_btable_bidi; + +/* Unidirectional receive-only endpoint BTABLE entry */ +typedef struct usb_btable_uni_rx { + __io uint16 empty1; const uint16 PAD1; + __io uint16 empty2; const uint16 PAD2; + __io uint16 addr_rx; const uint16 PAD3; + __io uint16 count_rx; const uint16 PAD4; +} usb_btable_uni_rx; + +/* Unidirectional transmit-only endpoint BTABLE entry */ +typedef struct usb_btable_uni_tx { + __io uint16 addr_tx; const uint16 PAD1; + __io uint16 count_tx; const uint16 PAD2; + __io uint16 empty1; const uint16 PAD3; + __io uint16 empty2; const uint16 PAD4; +} usb_btable_uni_tx; + +/* Double-buffered transmission endpoint BTABLE entry */ +typedef struct usb_btable_dbl_tx { + __io uint16 addr_tx0; const uint16 PAD1; + __io uint16 count_tx0; const uint16 PAD2; + __io uint16 addr_tx1; const uint16 PAD3; + __io uint16 count_tx1; const uint16 PAD4; +} usb_btable_dbl_tx; + +/* Double-buffered reception endpoint BTABLE entry */ +typedef struct usb_btable_dbl_rx { + __io uint16 addr_rx0; const uint16 PAD1; + __io uint16 count_rx0; const uint16 PAD2; + __io uint16 addr_rx1; const uint16 PAD3; + __io uint16 count_rx1; const uint16 PAD4; +} usb_btable_dbl_rx; + +/* TODO isochronous endpoint entries */ + +/* Definition for above forward-declared BTABLE entry. */ +typedef union usb_btable_ent { + usb_btable_bidi bidi; + usb_btable_uni_rx u_rx; + usb_btable_uni_tx u_tx; + usb_btable_dbl_tx d_tx; + usb_btable_dbl_rx d_rx; +} usb_btable_ent; + +/* + * BTABLE conveniences + */ + +/* TODO (?) Convert usages of the many (and lengthily-named) + * accessors/mutators below to just manipulating usb_btable_entry + * values. */ + +static inline uint32* usb_btable_ptr(uint32 offset) { + return (uint32*)usb_pma_ptr(USB_BASE->BTABLE + offset); +} + +static inline usb_btable_ent *usb_btable(void) { + return (usb_btable_ent*)usb_btable_ptr(0); +} + +/* TX address */ + +static inline uint32* usb_ep_tx_addr_ptr(uint8 ep) { + return usb_btable_ptr(ep * 8); +} + +static inline uint16 usb_get_ep_tx_addr(uint8 ep) { + return (uint16)*usb_ep_tx_addr_ptr(ep); +} + +static inline void usb_set_ep_tx_addr(uint8 ep, uint16 addr) { + uint32 *tx_addr = usb_ep_tx_addr_ptr(ep); + *tx_addr = addr & ~0x1; +} + +/* RX address */ + +static inline uint32* usb_ep_rx_addr_ptr(uint8 ep) { + return usb_btable_ptr(ep * 8 + 4); +} + +static inline uint16 usb_get_ep_rx_addr(uint8 ep) { + return (uint16)*usb_ep_rx_addr_ptr(ep); +} + +static inline void usb_set_ep_rx_addr(uint8 ep, uint16 addr) { + uint32 *rx_addr = usb_ep_rx_addr_ptr(ep); + *rx_addr = addr & ~0x1; +} + +/* TX count (doesn't cover double-buffered and isochronous in) */ + +static inline uint32* usb_ep_tx_count_ptr(uint8 ep) { + return usb_btable_ptr(ep * 8 + 2); +} + +static inline uint16 usb_get_ep_tx_count(uint8 ep) { + return (uint16)*usb_ep_tx_count_ptr(ep); +} + +static inline void usb_set_ep_tx_count(uint8 ep, uint16 count) { + uint32 *txc = usb_ep_tx_count_ptr(ep); + *txc = count; +} + +/* RX count */ + +static inline uint32* usb_ep_rx_count_ptr(uint8 ep) { + return usb_btable_ptr(ep * 8 + 6); +} + +static inline uint16 usb_get_ep_rx_count(uint8 ep) { + return (uint16)*usb_ep_rx_count_ptr(ep) & 0x3FF; +} + +void usb_set_ep_rx_count(uint8 ep, uint16 count); + +/* + * Misc. types + */ + +typedef enum usb_ep { + USB_EP0, + USB_EP1, + USB_EP2, + USB_EP3, + USB_EP4, + USB_EP5, + USB_EP6, + USB_EP7, +} usb_ep; + +typedef enum usb_ep_type { + USB_EP_T_CTL = USB_EP_EP_TYPE_CONTROL, + USB_EP_T_BULK = USB_EP_EP_TYPE_BULK, + USB_EP_T_INT = USB_EP_EP_TYPE_INTERRUPT, + USB_EP_T_ISO = USB_EP_EP_TYPE_ISO +} usb_ep_type; + +typedef enum usb_ep_stat { + USB_EP_ST_RX_DIS = USB_EP_STAT_RX_DISABLED, + USB_EP_ST_RX_STL = USB_EP_STAT_RX_STALL, + USB_EP_ST_RX_NAK = USB_EP_STAT_RX_NAK, + USB_EP_ST_RX_VAL = USB_EP_STAT_RX_VALID, + USB_EP_ST_TX_DIS = USB_EP_STAT_TX_DISABLED, + USB_EP_ST_TX_STL = USB_EP_STAT_TX_STALL, + USB_EP_ST_TX_NAK = USB_EP_STAT_TX_NAK, + USB_EP_ST_TX_VAL = USB_EP_STAT_TX_VALID +} usb_ep_stat; + +#endif diff --git a/libmaple/usb/usb.c b/libmaple/usb/usb.c deleted file mode 100644 index 0130bab..0000000 --- a/libmaple/usb/usb.c +++ /dev/null @@ -1,381 +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 libmaple/usb/usb.c - * @brief USB support. - * - * This is a mess. What we need almost amounts to a ground-up rewrite. - */ - -#include - -#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" - -static void dispatch_ctr_lp(void); - -/* - * usb_lib/ globals - */ - -uint16 SaveTState; /* caches TX status for later use */ -uint16 SaveRState; /* caches RX status for later use */ - -/* - * Other state - */ - -typedef enum { - RESUME_EXTERNAL, - RESUME_INTERNAL, - RESUME_LATER, - RESUME_WAIT, - RESUME_START, - RESUME_ON, - RESUME_OFF, - RESUME_ESOF -} RESUME_STATE; - -struct { - volatile RESUME_STATE eState; - volatile uint8 bESOFcnt; -} ResumeS; - -static usblib_dev usblib = { - .irq_mask = USB_ISR_MSK, - .state = USB_UNCONNECTED, - .clk_id = RCC_USB, -}; -usblib_dev *USBLIB = &usblib; - -/* - * Routines - */ - -void usb_init_usblib(usblib_dev *dev, - void (**ep_int_in)(void), - void (**ep_int_out)(void)) { - rcc_clk_enable(dev->clk_id); - - dev->ep_int_in = ep_int_in; - dev->ep_int_out = ep_int_out; - - /* usb_lib/ declares both and then assumes that pFoo points to Foo - * (even though the names don't always match), which is stupid for - * all of the obvious reasons, but whatever. Here we are. */ - pInformation = &Device_Info; - pProperty = &Device_Property; - pUser_Standard_Requests = &User_Standard_Requests; - - pInformation->ControlState = 2; /* FIXME [0.0.12] use - CONTROL_STATE enumerator */ - pProperty->Init(); -} - -static void usb_suspend(void) { - uint16 cntr; - - /* TODO decide if read/modify/write is really what we want - * (e.g. usb_resume_init() reconfigures CNTR). */ - cntr = USB_BASE->CNTR; - cntr |= USB_CNTR_FSUSP; - USB_BASE->CNTR = cntr; - cntr |= USB_CNTR_LP_MODE; - USB_BASE->CNTR = cntr; - - USBLIB->state = USB_SUSPENDED; -} - -static void usb_resume_init(void) { - uint16 cntr; - - cntr = USB_BASE->CNTR; - cntr &= ~USB_CNTR_LP_MODE; - USB_BASE->CNTR = cntr; - - /* Enable interrupt lines */ - USB_BASE->CNTR = USB_ISR_MSK; -} - -static void usb_resume(RESUME_STATE eResumeSetVal) { - uint16 cntr; - - if (eResumeSetVal != RESUME_ESOF) - ResumeS.eState = eResumeSetVal; - - switch (ResumeS.eState) - { - case RESUME_EXTERNAL: - usb_resume_init(); - ResumeS.eState = RESUME_OFF; - break; - case RESUME_INTERNAL: - usb_resume_init(); - ResumeS.eState = RESUME_START; - break; - case RESUME_LATER: - ResumeS.bESOFcnt = 2; - ResumeS.eState = RESUME_WAIT; - break; - case RESUME_WAIT: - ResumeS.bESOFcnt--; - if (ResumeS.bESOFcnt == 0) - ResumeS.eState = RESUME_START; - break; - case RESUME_START: - cntr = USB_BASE->CNTR; - cntr |= USB_CNTR_RESUME; - USB_BASE->CNTR = cntr; - ResumeS.eState = RESUME_ON; - ResumeS.bESOFcnt = 10; - break; - case RESUME_ON: - ResumeS.bESOFcnt--; - if (ResumeS.bESOFcnt == 0) { - cntr = USB_BASE->CNTR; - cntr &= ~USB_CNTR_RESUME; - USB_BASE->CNTR = cntr; - ResumeS.eState = RESUME_OFF; - } - break; - case RESUME_OFF: - case RESUME_ESOF: - default: - ResumeS.eState = RESUME_OFF; - break; - } -} - -#define SUSPEND_ENABLED 1 -void __irq_usb_lp_can_rx0(void) { - uint16 istr = USB_BASE->ISTR; - - /* Use USB_ISR_MSK to only include code for bits we care about. */ - -#if (USB_ISR_MSK & USB_ISTR_RESET) - if (istr & USB_ISTR_RESET & USBLIB->irq_mask) { - USB_BASE->ISTR = ~USB_ISTR_RESET; - pProperty->Reset(); - } -#endif - -#if (USB_ISR_MSK & USB_ISTR_PMAOVR) - if (istr & ISTR_PMAOVR & USBLIB->irq_mask) { - USB_BASE->ISTR = ~USB_ISTR_PMAOVR; - } -#endif - -#if (USB_ISR_MSK & USB_ISTR_ERR) - if (istr & USB_ISTR_ERR & USBLIB->irq_mask) { - USB_BASE->ISTR = ~USB_ISTR_ERR; - } -#endif - -#if (USB_ISR_MSK & USB_ISTR_WKUP) - if (istr & USB_ISTR_WKUP & USBLIB->irq_mask) { - USB_BASE->ISTR = ~USB_ISTR_WKUP; - usb_resume(RESUME_EXTERNAL); - } -#endif - -#if (USB_ISR_MSK & USB_ISTR_SUSP) - if (istr & USB_ISTR_SUSP & USBLIB->irq_mask) { - /* check if SUSPEND is possible */ - if (SUSPEND_ENABLED) { - usb_suspend(); - } else { - /* if not possible then resume after xx ms */ - usb_resume(RESUME_LATER); - } - /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */ - USB_BASE->ISTR = ~USB_ISTR_SUSP; -} -#endif - -#if (USB_ISR_MSK & USB_ISTR_SOF) - if (istr & USB_ISTR_SOF & USBLIB->irq_mask) { - USB_BASE->ISTR = ~USB_ISTR_SOF; - } -#endif - -#if (USB_ISR_MSK & USB_ISTR_ESOF) - if (istr & USB_ISTR_ESOF & USBLIB->irq_mask) { - USB_BASE->ISTR = ~USB_ISTR_ESOF; - /* resume handling timing is made with ESOFs */ - usb_resume(RESUME_ESOF); /* request without change of the machine state */ - } -#endif - - /* - * Service the correct transfer interrupt. - */ - -#if (USB_ISR_MSK & USB_ISTR_CTR) - if (istr & USB_ISTR_CTR & USBLIB->irq_mask) { - dispatch_ctr_lp(); - } -#endif -} - -/* - * Auxiliary routines - */ - -static inline uint8 dispatch_endpt_zero(uint16 istr_dir); -static inline void dispatch_endpt(uint8 ep); -static inline void set_rx_tx_status0(uint16 rx, uint16 tx); - -static void handle_setup0(void); -static void handle_in0(void); -static void handle_out0(void); - -static void dispatch_ctr_lp() { - uint16 istr; - while (((istr = USB_BASE->ISTR) & USB_ISTR_CTR) != 0) { - /* TODO WTF, figure this out: RM0008 says CTR is read-only, - * but ST's firmware claims it's clear-only, and emphasizes - * the importance of clearing it in more than one place. */ - USB_BASE->ISTR = ~USB_ISTR_CTR; - uint8 ep_id = istr & USB_ISTR_EP_ID; - if (ep_id == 0) { - /* TODO figure out why it's OK to break out of the loop - * once we're done serving endpoint zero, but not okay if - * there are multiple nonzero endpoint transfers to - * handle. */ - if (dispatch_endpt_zero(istr & USB_ISTR_DIR)) - return; - } else { - dispatch_endpt(ep_id); - } - } -} - -/* FIXME Dataflow on endpoint 0 RX/TX status is based off of ST's - * code, and is ugly/confusing in its use of SaveRState/SaveTState. - * Fixing this requires filling in handle_in0(), handle_setup0(), - * handle_out0(). */ -static inline uint8 dispatch_endpt_zero(uint16 istr_dir) { - uint32 epr = (uint16)USB_BASE->EP[0]; - - if (!(epr & (USB_EP_CTR_TX | USB_EP_SETUP | USB_EP_CTR_RX))) { - return 0; - } - - /* Cache RX/TX statuses in SaveRState/SaveTState, respectively. - * The various handle_foo0() may clobber these values - * before we reset them at the end of this routine. */ - SaveRState = epr & USB_EP_STAT_RX; - SaveTState = epr & USB_EP_STAT_TX; - - /* Set actual RX/TX statuses to NAK while we're thinking */ - set_rx_tx_status0(USB_EP_STAT_RX_NAK, USB_EP_STAT_TX_NAK); - - if (istr_dir == 0) { - /* ST RM0008: "If DIR bit=0, CTR_TX bit is set in the USB_EPnR - * register related to the interrupting endpoint. The - * interrupting transaction is of IN type (data transmitted by - * the USB peripheral to the host PC)." */ - ASSERT_FAULT(epr & USB_EP_CTR_TX); - usb_clear_ctr_tx(USB_EP0); - handle_in0(); - } else { - /* RM0008: "If DIR bit=1, CTR_RX bit or both CTR_TX/CTR_RX - * are set in the USB_EPnR register related to the - * interrupting endpoint. The interrupting transaction is of - * OUT type (data received by the USB peripheral from the host - * PC) or two pending transactions are waiting to be - * processed." - * - * [mbolivar] Note how the following control flow (which - * replicates ST's) doesn't seem to actually handle both - * interrupts that are ostensibly pending when both CTR_RX and - * CTR_TX are set. - * - * TODO sort this mess out. - */ - if (epr & USB_EP_CTR_TX) { - usb_clear_ctr_tx(USB_EP0); - handle_in0(); - } else { /* SETUP or CTR_RX */ - /* SETUP is held constant while CTR_RX is set, so clear it - * either way */ - usb_clear_ctr_rx(USB_EP0); - if (epr & USB_EP_SETUP) { - handle_setup0(); - } else { /* CTR_RX */ - handle_out0(); - } - } - } - - set_rx_tx_status0(SaveRState, SaveTState); - return 1; -} - -static inline void dispatch_endpt(uint8 ep) { - uint32 epr = USB_BASE->EP[ep]; - /* If ISTR_CTR is set and the ISTR gave us this EP_ID to handle, - * then presumably at least one of CTR_RX and CTR_TX is set, but - * again, ST's control flow allows for the possibility of neither. - * - * TODO try to find out if neither being set is possible. */ - if (epr & USB_EP_CTR_RX) { - usb_clear_ctr_rx(ep); - (USBLIB->ep_int_out[ep - 1])(); - } - if (epr & USB_EP_CTR_TX) { - usb_clear_ctr_tx(ep); - (USBLIB->ep_int_in[ep - 1])(); - } -} - -static inline void set_rx_tx_status0(uint16 rx, uint16 tx) { - usb_set_ep_rx_stat(USB_EP0, rx); - usb_set_ep_tx_stat(USB_EP0, tx); -} - -/* TODO Rip out usb_lib/ dependency from the following functions: */ - -static void handle_setup0(void) { - Setup0_Process(); -} - -static void handle_in0(void) { - In0_Process(); -} - -static void handle_out0(void) { - Out0_Process(); -} diff --git a/libmaple/usb/usb_cdcacm.c b/libmaple/usb/usb_cdcacm.c deleted file mode 100644 index 6ef4806..0000000 --- a/libmaple/usb/usb_cdcacm.c +++ /dev/null @@ -1,762 +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 libmaple/usb/usb_cdcacm.c - * @brief USB CDC ACM (a.k.a. virtual serial terminal, VCOM). - * - * FIXME: this works on the STM32F1 USB peripherals, and probably no - * place else. Nonportable bits really need to be factored out, and - * the result made cleaner. - */ - -#include - -#include -#include -#include - -/* 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" - -/****************************************************************************** - ****************************************************************************** - *** - *** HACK ALERT! FIXME FIXME FIXME FIXME! - *** - *** A bunch of LeafLabs-specific configuration lives in here for - *** now. This mess REALLY needs to get teased apart, with - *** appropriate pieces moved into Wirish. - *** - ****************************************************************************** - *****************************************************************************/ - -#if !(defined(BOARD_maple) || defined(BOARD_maple_RET6) || \ - defined(BOARD_maple_mini) || defined(BOARD_maple_native)) -#warning USB CDC ACM relies on LeafLabs board-specific configuration.\ - You may have problems on non-LeafLabs boards. -#endif - -static void vcomDataTxCb(void); -static void vcomDataRxCb(void); -static uint8* vcomGetSetLineCoding(uint16); - -static void usbInit(void); -static void usbReset(void); -static RESULT usbDataSetup(uint8 request); -static RESULT usbNoDataSetup(uint8 request); -static RESULT usbGetInterfaceSetting(uint8 interface, uint8 alt_setting); -static uint8* usbGetDeviceDescriptor(uint16 length); -static uint8* usbGetConfigDescriptor(uint16 length); -static uint8* usbGetStringDescriptor(uint16 length); -static void usbSetConfiguration(void); -static void usbSetDeviceAddress(void); - -static void wait_reset(void); - -/* - * VCOM config - */ - -#define VCOM_CTRL_EPNUM 0x00 -#define VCOM_CTRL_RX_ADDR 0x40 -#define VCOM_CTRL_TX_ADDR 0x80 -#define VCOM_CTRL_EPSIZE 0x40 - -#define VCOM_TX_ENDP 1 -#define VCOM_TX_EPNUM 0x01 -#define VCOM_TX_ADDR 0xC0 -#define VCOM_TX_EPSIZE 0x40 - -#define VCOM_NOTIFICATION_ENDP 2 -#define VCOM_NOTIFICATION_EPNUM 0x02 -#define VCOM_NOTIFICATION_ADDR 0x100 -#define VCOM_NOTIFICATION_EPSIZE 0x40 - -#define VCOM_RX_ENDP 3 -#define VCOM_RX_EPNUM 0x03 -#define VCOM_RX_ADDR 0x110 -#define VCOM_RX_EPSIZE 0x40 -#define VCOM_RX_BUFLEN (VCOM_RX_EPSIZE*3) - -/* - * CDC ACM Requests - */ - -#define SET_LINE_CODING 0x20 -#define GET_LINE_CODING 0x21 -#define SET_COMM_FEATURE 0x02 -#define SET_CONTROL_LINE_STATE 0x22 -#define CONTROL_LINE_DTR (0x01) -#define CONTROL_LINE_RTS (0x02) - -/* - * Descriptors - */ - -#define USB_DEVICE_CLASS_CDC 0x02 -#define USB_DEVICE_SUBCLASS_CDC 0x00 -#define LEAFLABS_ID_VENDOR 0x1EAF -#define MAPLE_ID_PRODUCT 0x0004 -const USB_Descriptor_Device usbVcomDescriptor_Device = { - .bLength = sizeof(USB_Descriptor_Device), - .bDescriptorType = USB_DESCRIPTOR_TYPE_DEVICE, - .bcdUSB = 0x0200, - .bDeviceClass = USB_DEVICE_CLASS_CDC, - .bDeviceSubClass = USB_DEVICE_SUBCLASS_CDC, - .bDeviceProtocol = 0x00, - .bMaxPacketSize0 = 0x40, - .idVendor = LEAFLABS_ID_VENDOR, - .idProduct = MAPLE_ID_PRODUCT, - .bcdDevice = 0x0200, - .iManufacturer = 0x01, - .iProduct = 0x02, - .iSerialNumber = 0x00, - .bNumConfigurations = 0x01, -}; - -#define MAX_POWER (100 >> 1) -const USB_Descriptor_Config usbVcomDescriptor_Config = { - .Config_Header = { - .bLength = sizeof(USB_Descriptor_Config_Header), - .bDescriptorType = USB_DESCRIPTOR_TYPE_CONFIGURATION, - .wTotalLength = sizeof(USB_Descriptor_Config), - .bNumInterfaces = 0x02, - .bConfigurationValue = 0x01, - .iConfiguration = 0x00, - .bmAttributes = (USB_CONFIG_ATTR_BUSPOWERED | - USB_CONFIG_ATTR_SELF_POWERED), - .bMaxPower = MAX_POWER, - }, - - .CCI_Interface = { - .bLength = sizeof(USB_Descriptor_Interface), - .bDescriptorType = USB_DESCRIPTOR_TYPE_INTERFACE, - .bInterfaceNumber = 0x00, - .bAlternateSetting = 0x00, - .bNumEndpoints = 0x01, - .bInterfaceClass = USB_INTERFACE_CLASS_CDC, - .bInterfaceSubClass = USB_INTERFACE_SUBCLASS_CDC_ACM, - .bInterfaceProtocol = 0x01, /* Common AT Commands */ - .iInterface = 0x00, - }, - - .CDC_Functional_IntHeader = { - .bLength = CDC_FUNCTIONAL_DESCRIPTOR_SIZE(2), - .bDescriptorType = 0x24, - .SubType = 0x00, - .Data = {0x01, 0x10}, - }, - - .CDC_Functional_CallManagement = { - .bLength = CDC_FUNCTIONAL_DESCRIPTOR_SIZE(2), - .bDescriptorType = 0x24, - .SubType = 0x01, - .Data = {0x03, 0x01}, - }, - - .CDC_Functional_ACM = { - .bLength = CDC_FUNCTIONAL_DESCRIPTOR_SIZE(1), - .bDescriptorType = 0x24, - .SubType = 0x02, - .Data = {0x06}, - }, - - .CDC_Functional_Union = { - .bLength = CDC_FUNCTIONAL_DESCRIPTOR_SIZE(2), - .bDescriptorType = 0x24, - .SubType = 0x06, - .Data = {0x00, 0x01}, - }, - - .ManagementEndpoint = { - .bLength = sizeof(USB_Descriptor_Endpoint), - .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT, - .bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_IN | - VCOM_NOTIFICATION_EPNUM), - .bmAttributes = EP_TYPE_INTERRUPT, - .wMaxPacketSize = VCOM_NOTIFICATION_EPSIZE, - .bInterval = 0xFF, - }, - - .DCI_Interface = { - .bLength = sizeof(USB_Descriptor_Interface), - .bDescriptorType = USB_DESCRIPTOR_TYPE_INTERFACE, - .bInterfaceNumber = 0x01, - .bAlternateSetting = 0x00, - .bNumEndpoints = 0x02, - .bInterfaceClass = USB_INTERFACE_CLASS_DIC, - .bInterfaceSubClass = 0x00, /* None */ - .bInterfaceProtocol = 0x00, /* None */ - .iInterface = 0x00, - }, - - .DataOutEndpoint = { - .bLength = sizeof(USB_Descriptor_Endpoint), - .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT, - .bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_OUT | VCOM_RX_EPNUM), - .bmAttributes = EP_TYPE_BULK, - .wMaxPacketSize = VCOM_RX_EPSIZE, - .bInterval = 0x00, - }, - - .DataInEndpoint = { - .bLength = sizeof(USB_Descriptor_Endpoint), - .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT, - .bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_IN | VCOM_TX_EPNUM), - .bmAttributes = EP_TYPE_BULK, - .wMaxPacketSize = VCOM_TX_EPSIZE, - .bInterval = 0x00, - }, -}; - -/* - String Identifiers: - - we may choose to specify any or none of the following string - identifiers: - - iManufacturer: LeafLabs - iProduct: Maple - iSerialNumber: NONE - iConfiguration: NONE - iInterface(CCI): NONE - iInterface(DCI): NONE - - additionally we must provide the unicode language identifier, - which is 0x0409 for US English -*/ - -const uint8 usbVcomDescriptor_LangID[USB_DESCRIPTOR_STRING_LEN(1)] = { - USB_DESCRIPTOR_STRING_LEN(1), - USB_DESCRIPTOR_TYPE_STRING, - 0x09, - 0x04, -}; - -const uint8 usbVcomDescriptor_iManufacturer[USB_DESCRIPTOR_STRING_LEN(8)] = { - USB_DESCRIPTOR_STRING_LEN(8), - USB_DESCRIPTOR_TYPE_STRING, - 'L', 0, 'e', 0, 'a', 0, 'f', 0, - 'L', 0, 'a', 0, 'b', 0, 's', 0, -}; - -const uint8 usbVcomDescriptor_iProduct[USB_DESCRIPTOR_STRING_LEN(8)] = { - USB_DESCRIPTOR_STRING_LEN(8), - USB_DESCRIPTOR_TYPE_STRING, - 'M', 0, 'a', 0, 'p', 0, 'l', 0, - 'e', 0, ' ', 0, ' ', 0, ' ', 0 -}; - -ONE_DESCRIPTOR Device_Descriptor = { - (uint8*)&usbVcomDescriptor_Device, - sizeof(USB_Descriptor_Device) -}; - -ONE_DESCRIPTOR Config_Descriptor = { - (uint8*)&usbVcomDescriptor_Config, - sizeof(USB_Descriptor_Config) -}; - -ONE_DESCRIPTOR String_Descriptor[3] = { - {(uint8*)&usbVcomDescriptor_LangID, USB_DESCRIPTOR_STRING_LEN(1)}, - {(uint8*)&usbVcomDescriptor_iManufacturer,USB_DESCRIPTOR_STRING_LEN(8)}, - {(uint8*)&usbVcomDescriptor_iProduct, USB_DESCRIPTOR_STRING_LEN(8)} -}; - -/* - * Etc. - */ - -typedef enum { - DTR_UNSET, - DTR_HIGH, - DTR_NEGEDGE, - DTR_LOW -} RESET_STATE; - -typedef struct { - uint32 bitrate; - uint8 format; - uint8 paritytype; - uint8 datatype; -} USB_Line_Coding; - -uint8 last_request = 0; -USB_Line_Coding line_coding = { - .bitrate = 115200, - .format = 0x00, /* stop bits-1 */ - .paritytype = 0x00, - .datatype = 0x08 -}; -uint8 vcomBufferRx[VCOM_RX_BUFLEN]; -volatile uint32 countTx = 0; -volatile uint32 recvBufIn = 0; -volatile uint32 recvBufOut = 0; -volatile uint32 maxNewBytes = VCOM_RX_BUFLEN; -volatile uint32 newBytes = 0; -RESET_STATE reset_state = DTR_UNSET; -uint8 line_dtr_rts = 0; - -/* - * Endpoint callbacks - */ - -static void (*ep_int_in[7])(void) = - {vcomDataTxCb, - NOP_Process, - NOP_Process, - NOP_Process, - NOP_Process, - NOP_Process, - NOP_Process}; - -static void (*ep_int_out[7])(void) = - {NOP_Process, - NOP_Process, - vcomDataRxCb, - NOP_Process, - NOP_Process, - NOP_Process, - NOP_Process}; - -/* - * Globals required by usb_lib/ - */ - -#define NUM_ENDPTS 0x04 -DEVICE Device_Table = { - .Total_Endpoint = NUM_ENDPTS, - .Total_Configuration = 1 -}; - -#define MAX_PACKET_SIZE 0x40 /* 64B, maximum for USB FS Devices */ -DEVICE_PROP Device_Property = { - .Init = usbInit, - .Reset = usbReset, - .Process_Status_IN = NOP_Process, - .Process_Status_OUT = NOP_Process, - .Class_Data_Setup = usbDataSetup, - .Class_NoData_Setup = usbNoDataSetup, - .Class_Get_Interface_Setting = usbGetInterfaceSetting, - .GetDeviceDescriptor = usbGetDeviceDescriptor, - .GetConfigDescriptor = usbGetConfigDescriptor, - .GetStringDescriptor = usbGetStringDescriptor, - .RxEP_buffer = NULL, - .MaxPacketSize = MAX_PACKET_SIZE -}; - -USER_STANDARD_REQUESTS User_Standard_Requests = { - .User_GetConfiguration = NOP_Process, - .User_SetConfiguration = usbSetConfiguration, - .User_GetInterface = NOP_Process, - .User_SetInterface = NOP_Process, - .User_GetStatus = NOP_Process, - .User_ClearFeature = NOP_Process, - .User_SetEndPointFeature = NOP_Process, - .User_SetDeviceFeature = NOP_Process, - .User_SetDeviceAddress = usbSetDeviceAddress -}; - -/* - * CDC ACM interface - */ - -void usb_cdcacm_enable(gpio_dev *disc_dev, uint8 disc_bit) { - /* Present ourselves to the host */ - gpio_set_mode(disc_dev, disc_bit, GPIO_OUTPUT_PP); - gpio_write_bit(disc_dev, disc_bit, 0); // presents us to the host - - /* initialize USB peripheral */ - usb_init_usblib(USBLIB, ep_int_in, ep_int_out); -} - -void usb_cdcacm_disable(gpio_dev *disc_dev, uint8 disc_bit) { - // These are just guesses about how to do this, but it seems to work. - // TODO: verify this with USB spec - nvic_irq_disable(NVIC_USB_LP_CAN_RX0); - gpio_write_bit(disc_dev, disc_bit, 1); -} - -void usb_cdcacm_putc(char ch) { - while (!usb_cdcacm_tx((uint8*)&ch, 1)) - ; -} - -/* This function is non-blocking. - * - * It copies data from a usercode buffer into the USB peripheral TX - * buffer and return the number placed in that buffer. - */ -uint32 usb_cdcacm_tx(const uint8* buf, uint32 len) { - /* Last transmission hasn't finished, abort */ - if (countTx) { - return 0; - } - - // We can only put VCOM_TX_EPSIZE bytes in the buffer - /* FIXME then why are we only copying half as many? */ - if (len > VCOM_TX_EPSIZE / 2) { - len = VCOM_TX_EPSIZE / 2; - } - - // Try to load some bytes if we can - if (len) { - usb_copy_to_pma(buf, len, VCOM_TX_ADDR); - usb_set_ep_tx_count(VCOM_TX_ENDP, len); - countTx += len; - usb_set_ep_tx_stat(VCOM_TX_ENDP, USB_EP_STAT_TX_VALID); - } - - return len; -} - -/* returns the number of available bytes are in the recv FIFO */ -uint32 usb_cdcacm_data_available(void) { - return newBytes; -} - -uint16 usb_cdcacm_get_pending() { - return countTx; -} - -/* Nonblocking byte receive. - * - * Copies up to len bytes from our private data buffer (*NOT* the PMA) - * into buf and deq's the FIFO. */ -uint32 usb_cdcacm_rx(uint8* buf, uint32 len) { - static int offset = 0; - int i; - - if (len > newBytes) { - len = newBytes; - } - - for (i = 0; i < len; i++) { - buf[i] = vcomBufferRx[i + offset]; - } - - newBytes -= len; - offset += len; - - /* Re-enable the RX endpoint, which we had set to receive 0 bytes */ - if (newBytes == 0) { - usb_set_ep_rx_count(VCOM_RX_ENDP, VCOM_RX_EPSIZE); - usb_set_ep_rx_stat(VCOM_RX_ENDP, USB_EP_STAT_RX_VALID); - offset = 0; - } - - return len; -} - -uint8 usb_cdcacm_get_dtr() { - return ((line_dtr_rts & CONTROL_LINE_DTR) != 0); -} - -uint8 usb_cdcacm_get_rts() { - return ((line_dtr_rts & CONTROL_LINE_RTS) != 0); -} - -/* - * Callbacks - */ - -static void vcomDataTxCb(void) { - /* assumes tx transactions are atomic 64 bytes (nearly certain they are) */ - countTx = 0; -} - -#define EXC_RETURN 0xFFFFFFF9 -#define DEFAULT_CPSR 0x61000000 -static void vcomDataRxCb(void) { - /* FIXME this is mad buggy */ - - /* setEPRxCount on the previous cycle should garuntee - we havnt received more bytes than we can fit */ - newBytes = usb_get_ep_rx_count(VCOM_RX_ENDP); - usb_set_ep_rx_stat(VCOM_RX_ENDP, USB_EP_STAT_RX_NAK); - - /* magic number, {0x31, 0x45, 0x41, 0x46} is "1EAF" */ - uint8 chkBuf[4]; - uint8 cmpBuf[4] = {0x31, 0x45, 0x41, 0x46}; - if (reset_state == DTR_NEGEDGE) { - reset_state = DTR_LOW; - - if (newBytes >= 4) { - unsigned int target = (unsigned int)wait_reset | 0x1; - - usb_copy_from_pma(chkBuf, 4, VCOM_RX_ADDR); - - int i; - USB_Bool cmpMatch = TRUE; - for (i = 0; i < 4; i++) { - if (chkBuf[i] != cmpBuf[i]) { - cmpMatch = FALSE; - } - } - - if (cmpMatch) { - asm volatile("mov r0, %[stack_top] \n\t" // Reset stack - "mov sp, r0 \n\t" - "mov r0, #1 \n\t" - "mov r1, %[target_addr] \n\t" - "mov r2, %[cpsr] \n\t" - "push {r2} \n\t" // Fake xPSR - "push {r1} \n\t" // PC target addr - "push {r0} \n\t" // Fake LR - "push {r0} \n\t" // Fake R12 - "push {r0} \n\t" // Fake R3 - "push {r0} \n\t" // Fake R2 - "push {r0} \n\t" // Fake R1 - "push {r0} \n\t" // Fake R0 - "mov lr, %[exc_return] \n\t" - "bx lr" - : - : [stack_top] "r" (STACK_TOP), - [target_addr] "r" (target), - [exc_return] "r" (EXC_RETURN), - [cpsr] "r" (DEFAULT_CPSR) - : "r0", "r1", "r2"); - /* should never get here */ - } - } - } - - usb_copy_from_pma(vcomBufferRx, newBytes, VCOM_RX_ADDR); -} - -static uint8* vcomGetSetLineCoding(uint16 length) { - if (length == 0) { - pInformation->Ctrl_Info.Usb_wLength = sizeof(USB_Line_Coding); - } - return (uint8*)&line_coding; -} - -static void usbInit(void) { - pInformation->Current_Configuration = 0; - - USB_BASE->CNTR = USB_CNTR_FRES; - - USBLIB->irq_mask = 0; - USB_BASE->CNTR = USBLIB->irq_mask; - USB_BASE->ISTR = 0; - USBLIB->irq_mask = USB_CNTR_RESETM | USB_CNTR_SUSPM | USB_CNTR_WKUPM; - USB_BASE->CNTR = USBLIB->irq_mask; - - USB_BASE->ISTR = 0; - USBLIB->irq_mask = USB_ISR_MSK; - USB_BASE->CNTR = USBLIB->irq_mask; - - nvic_irq_enable(NVIC_USB_LP_CAN_RX0); - USBLIB->state = USB_UNCONNECTED; -} - -/* choose addresses to give endpoints the max 64 byte buffers */ -#define BTABLE_ADDRESS 0x00 -static void usbReset(void) { - pInformation->Current_Configuration = 0; - - /* current feature is current bmAttributes */ - pInformation->Current_Feature = (USB_CONFIG_ATTR_BUSPOWERED | - USB_CONFIG_ATTR_SELF_POWERED); - - USB_BASE->BTABLE = BTABLE_ADDRESS; - - /* setup control endpoint 0 */ - usb_set_ep_type(USB_EP0, USB_EP_EP_TYPE_CONTROL); - usb_set_ep_tx_stat(USB_EP0, USB_EP_STAT_TX_STALL); - usb_set_ep_rx_addr(USB_EP0, VCOM_CTRL_RX_ADDR); - usb_set_ep_tx_addr(USB_EP0, VCOM_CTRL_TX_ADDR); - usb_clear_status_out(USB_EP0); - - usb_set_ep_rx_count(USB_EP0, pProperty->MaxPacketSize); - usb_set_ep_rx_stat(USB_EP0, USB_EP_STAT_RX_VALID); - - /* setup management endpoint 1 */ - usb_set_ep_type(VCOM_NOTIFICATION_ENDP, USB_EP_EP_TYPE_INTERRUPT); - usb_set_ep_tx_addr(VCOM_NOTIFICATION_ENDP, VCOM_NOTIFICATION_ADDR); - usb_set_ep_tx_stat(VCOM_NOTIFICATION_ENDP, USB_EP_STAT_TX_NAK); - usb_set_ep_rx_stat(VCOM_NOTIFICATION_ENDP, USB_EP_STAT_RX_DISABLED); - - /* TODO figure out differences in style between RX/TX EP setup */ - - /* set up data endpoint OUT (RX) */ - usb_set_ep_type(VCOM_RX_ENDP, USB_EP_EP_TYPE_BULK); - usb_set_ep_rx_addr(VCOM_RX_ENDP, 0x110); - usb_set_ep_rx_count(VCOM_RX_ENDP, 64); - usb_set_ep_rx_stat(VCOM_RX_ENDP, USB_EP_STAT_RX_VALID); - - /* set up data endpoint IN (TX) */ - usb_set_ep_type(VCOM_TX_ENDP, USB_EP_EP_TYPE_BULK); - usb_set_ep_tx_addr(VCOM_TX_ENDP, VCOM_TX_ADDR); - usb_set_ep_tx_stat(VCOM_TX_ENDP, USB_EP_STAT_TX_NAK); - usb_set_ep_rx_stat(VCOM_TX_ENDP, USB_EP_STAT_RX_DISABLED); - - USBLIB->state = USB_ATTACHED; - SetDeviceAddress(0); - - /* reset the rx fifo */ - recvBufIn = 0; - recvBufOut = 0; - maxNewBytes = VCOM_RX_EPSIZE; - countTx = 0; -} - -static RESULT usbDataSetup(uint8 request) { - uint8 *(*CopyRoutine)(uint16); - CopyRoutine = NULL; - - if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) { - switch (request) { - case (GET_LINE_CODING): - CopyRoutine = vcomGetSetLineCoding; - last_request = GET_LINE_CODING; - break; - case (SET_LINE_CODING): - CopyRoutine = vcomGetSetLineCoding; - last_request = SET_LINE_CODING; - break; - default: - break; - } - } - - if (CopyRoutine == NULL) { - return USB_UNSUPPORT; - } - - pInformation->Ctrl_Info.CopyData = CopyRoutine; - pInformation->Ctrl_Info.Usb_wOffset = 0; - (*CopyRoutine)(0); - return USB_SUCCESS; -} - -static RESULT usbNoDataSetup(uint8 request) { - uint8 new_signal; - - /* we support set com feature but dont handle it */ - if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) { - - switch (request) { - case (SET_COMM_FEATURE): - return USB_SUCCESS; - case (SET_CONTROL_LINE_STATE): - /* to reset the board, pull both dtr and rts low - then pulse dtr by itself */ - new_signal = (pInformation->USBwValues.bw.bb0 & - (CONTROL_LINE_DTR | CONTROL_LINE_RTS)); - line_dtr_rts = new_signal & 0x03; - - switch (reset_state) { - /* no default, covered enum */ - case DTR_UNSET: - if ((new_signal & CONTROL_LINE_DTR) == 0 ) { - reset_state = DTR_LOW; - } else { - reset_state = DTR_HIGH; - } - break; - - case DTR_HIGH: - if ((new_signal & CONTROL_LINE_DTR) == 0 ) { - reset_state = DTR_NEGEDGE; - } else { - reset_state = DTR_HIGH; - } - break; - - case DTR_NEGEDGE: - if ((new_signal & CONTROL_LINE_DTR) == 0 ) { - reset_state = DTR_LOW; - } else { - reset_state = DTR_HIGH; - } - break; - - case DTR_LOW: - if ((new_signal & CONTROL_LINE_DTR) == 0 ) { - reset_state = DTR_LOW; - } else { - reset_state = DTR_HIGH; - } - break; - } - - return USB_SUCCESS; - } - } - return USB_UNSUPPORT; -} - -static RESULT usbGetInterfaceSetting(uint8 interface, uint8 alt_setting) { - if (alt_setting > 0) { - return USB_UNSUPPORT; - } else if (interface > 1) { - return USB_UNSUPPORT; - } - - return USB_SUCCESS; -} - -static uint8* usbGetDeviceDescriptor(uint16 length) { - return Standard_GetDescriptorData(length, &Device_Descriptor); -} - -static uint8* usbGetConfigDescriptor(uint16 length) { - return Standard_GetDescriptorData(length, &Config_Descriptor); -} - -static uint8* usbGetStringDescriptor(uint16 length) { - uint8 wValue0 = pInformation->USBwValue0; - - if (wValue0 > 2) { - return NULL; - } - return Standard_GetDescriptorData(length, &String_Descriptor[wValue0]); -} - -static void usbSetConfiguration(void) { - if (pInformation->Current_Configuration != 0) { - USBLIB->state = USB_CONFIGURED; - } -} - -static void usbSetDeviceAddress(void) { - USBLIB->state = USB_ADDRESSED; -} - -#define RESET_DELAY 100000 -static void wait_reset(void) { - delay_us(RESET_DELAY); - nvic_sys_reset(); -} diff --git a/libmaple/usb/usb_descriptors.h b/libmaple/usb/usb_descriptors.h deleted file mode 100644 index 9bcb2b6..0000000 --- a/libmaple/usb/usb_descriptors.h +++ /dev/null @@ -1,148 +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. - *****************************************************************************/ - -#ifndef _USB_DESCRIPTORS_H_ -#define _USB_DESCRIPTORS_H_ - -#include - -#define USB_DESCRIPTOR_TYPE_DEVICE 0x01 -#define USB_DESCRIPTOR_TYPE_CONFIGURATION 0x02 -#define USB_DESCRIPTOR_TYPE_STRING 0x03 -#define USB_DESCRIPTOR_TYPE_INTERFACE 0x04 -#define USB_DESCRIPTOR_TYPE_ENDPOINT 0x05 - -#define USB_DEVICE_CLASS_CDC 0x02 -#define USB_DEVICE_SUBCLASS_CDC 0x00 -#define USB_INTERFACE_CLASS_CDC 0x02 -/* CDC Abstract Control Model */ -#define USB_INTERFACE_SUBCLASS_CDC_ACM 0x02 -#define USB_INTERFACE_CLASS_DIC 0x0A - -#define USB_CONFIG_ATTR_BUSPOWERED 0b10000000 -#define USB_CONFIG_ATTR_SELF_POWERED 0b11000000 - -#define EP_TYPE_INTERRUPT 0x03 -#define EP_TYPE_BULK 0x02 - -#define USB_DESCRIPTOR_ENDPOINT_IN 0x80 -#define USB_DESCRIPTOR_ENDPOINT_OUT 0x00 - -#define USB_DESCRIPTOR_STRING_LEN(x) (2 + (x << 1)) - -#if defined(__cplusplus) -extern "C" { -#endif - -#define USB_DESCRIPTOR_STRING(len) \ - struct { \ - uint8 bLength; \ - uint8 bDescriptorType; \ - uint16 bString[len]; \ - } __packed - -#define CDC_FUNCTIONAL_DESCRIPTOR_SIZE(DataSize) (3 + DataSize) -#define CDC_FUNCTIONAL_DESCRIPTOR(DataSize) \ - struct { \ - uint8 bLength; \ - uint8 bDescriptorType; \ - uint8 SubType; \ - uint8 Data[DataSize]; \ - } __packed - -typedef struct { - uint8 bLength; - uint8 bDescriptorType; - uint16 bcdUSB; - uint8 bDeviceClass; - uint8 bDeviceSubClass; - uint8 bDeviceProtocol; - uint8 bMaxPacketSize0; - uint16 idVendor; - uint16 idProduct; - uint16 bcdDevice; - uint8 iManufacturer; - uint8 iProduct; - uint8 iSerialNumber; - uint8 bNumConfigurations; -} __packed USB_Descriptor_Device; - -typedef struct { - uint8 bLength; - uint8 bDescriptorType; - uint16 wTotalLength; - uint8 bNumInterfaces; - uint8 bConfigurationValue; - uint8 iConfiguration; - uint8 bmAttributes; - uint8 bMaxPower; -} __packed USB_Descriptor_Config_Header; - -typedef struct { - uint8 bLength; - uint8 bDescriptorType; - uint8 bInterfaceNumber; - uint8 bAlternateSetting; - uint8 bNumEndpoints; - uint8 bInterfaceClass; - uint8 bInterfaceSubClass; - uint8 bInterfaceProtocol; - uint8 iInterface; -} __packed USB_Descriptor_Interface; - -typedef struct { - uint8 bLength; - uint8 bDescriptorType; - uint8 bEndpointAddress; - uint8 bmAttributes; - uint16 wMaxPacketSize; - uint8 bInterval; -} __packed USB_Descriptor_Endpoint; - -typedef struct { - USB_Descriptor_Config_Header Config_Header; - USB_Descriptor_Interface CCI_Interface; - CDC_FUNCTIONAL_DESCRIPTOR(2) CDC_Functional_IntHeader; - CDC_FUNCTIONAL_DESCRIPTOR(2) CDC_Functional_CallManagement; - CDC_FUNCTIONAL_DESCRIPTOR(1) CDC_Functional_ACM; - CDC_FUNCTIONAL_DESCRIPTOR(2) CDC_Functional_Union; - USB_Descriptor_Endpoint ManagementEndpoint; - USB_Descriptor_Interface DCI_Interface; - USB_Descriptor_Endpoint DataOutEndpoint; - USB_Descriptor_Endpoint DataInEndpoint; -} __packed USB_Descriptor_Config; - -typedef struct { - uint8 bLength; - uint8 bDescriptorType; - uint16 bString[]; -} USB_Descriptor_String; - -#if defined(__cplusplus) -} -#endif - -#endif diff --git a/libmaple/usb/usb_lib_globals.h b/libmaple/usb/usb_lib_globals.h deleted file mode 100644 index 1cd2754..0000000 --- a/libmaple/usb/usb_lib_globals.h +++ /dev/null @@ -1,55 +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. - *****************************************************************************/ - -#ifndef _USB_LIB_GLOBALS_H_ -#define _USB_LIB_GLOBALS_H_ - -/* usb_lib headers */ -#include "usb_type.h" -#include "usb_core.h" - -#ifdef __cplusplus -extern "C" { -#endif - -extern USER_STANDARD_REQUESTS User_Standard_Requests; -extern USER_STANDARD_REQUESTS *pUser_Standard_Requests; - -extern DEVICE_PROP Device_Property; -extern DEVICE_PROP *pProperty; - -extern DEVICE_INFO Device_Info; -extern DEVICE_INFO *pInformation; - -extern DEVICE Device_Table; -extern u16 SaveRState; -extern u16 SaveTState; - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/libmaple/usb/usb_reg_map.c b/libmaple/usb/usb_reg_map.c deleted file mode 100644 index 75562e1..0000000 --- a/libmaple/usb/usb_reg_map.c +++ /dev/null @@ -1,79 +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. - *****************************************************************************/ - -#include "usb_reg_map.h" - -/* TODO these could use some improvement; they're fairly - * straightforward ports of the analogous ST code. The PMA blit - * routines in particular are obvious targets for performance - * measurement and tuning. */ - -void usb_copy_to_pma(const uint8 *buf, uint16 len, uint16 pma_offset) { - uint16 *dst = (uint16*)usb_pma_ptr(pma_offset); - uint16 n = len >> 1; - uint16 i; - for (i = 0; i < n; i++) { - *dst = (uint16)(*buf) | *(buf + 1) << 8; - buf += 2; - dst += 2; - } - if (len & 1) { - *dst = *buf; - } -} - -void usb_copy_from_pma(uint8 *buf, uint16 len, uint16 pma_offset) { - uint32 *src = (uint32*)usb_pma_ptr(pma_offset); - uint16 *dst = (uint16*)buf; - uint16 n = len >> 1; - uint16 i; - for (i = 0; i < n; i++) { - *dst++ = *src++; - } - if (len & 1) { - *dst = *src & 0xFF; - } -} - -void usb_set_ep_rx_count(uint8 ep, uint16 count) { - uint32 *rxc = usb_ep_rx_count_ptr(ep); - uint16 nblocks; - if (count > 62) { - /* use 32-byte memory block size */ - nblocks = count >> 5; - if ((count & 0x1F) == 0) { - nblocks--; - } - *rxc = (nblocks << 10) | 0x8000; - } else { - /* use 2-byte memory block size */ - nblocks = count >> 1; - if ((count & 0x1) != 0) { - nblocks++; - } - *rxc = nblocks << 10; - } -} diff --git a/libmaple/usb/usb_reg_map.h b/libmaple/usb/usb_reg_map.h deleted file mode 100644 index ce80842..0000000 --- a/libmaple/usb/usb_reg_map.h +++ /dev/null @@ -1,433 +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. - *****************************************************************************/ - -#include -#include - -#ifndef _USB_REG_MAP_H_ -#define _USB_REG_MAP_H_ - -/* TODO: - * - Pick one of "endp", "ep" "endpt" - */ - -/* - * Register map and base pointer - */ - -#define USB_NR_EP_REGS 8 - -/** USB register map type */ -typedef struct usb_reg_map { - __io uint32 EP[USB_NR_EP_REGS]; /**< Endpoint registers */ - const uint32 RESERVED[8]; /**< Reserved */ - __io uint32 CNTR; /**< Control register */ - __io uint32 ISTR; /**< Interrupt status register */ - __io uint32 FNR; /**< Frame number register */ - __io uint32 DADDR; /**< Device address */ - __io uint32 BTABLE; /**< @brief Buffer table address - * - * Address offset within the USB - * packet memory area which points - * to the base of the buffer - * descriptor table. Must be - * aligned to an 8 byte boundary. - */ -} usb_reg_map; - -/** USB register map base pointer */ -#define USB_BASE ((struct usb_reg_map*)0x40005C00) - -/* - * Register bit definitions - */ - -/* Endpoint registers (USB_EPnR) */ - -#define USB_EP_CTR_RX_BIT 15 -#define USB_EP_DTOG_RX_BIT 14 -#define USB_EP_SETUP_BIT 11 -#define USB_EP_EP_KIND_BIT 8 -#define USB_EP_CTR_TX_BIT 7 -#define USB_EP_DTOG_TX_BIT 6 - -#define USB_EP_CTR_RX BIT(USB_EP_CTR_RX_BIT) -#define USB_EP_DTOG_RX BIT(USB_EP_DTOG_RX_BIT) -#define USB_EP_STAT_RX (0x3 << 12) -#define USB_EP_STAT_RX_DISABLED (0x0 << 12) -#define USB_EP_STAT_RX_STALL (0x1 << 12) -#define USB_EP_STAT_RX_NAK (0x2 << 12) -#define USB_EP_STAT_RX_VALID (0x3 << 12) -#define USB_EP_SETUP BIT(USB_EP_SETUP_BIT) -#define USB_EP_EP_TYPE (0x3 << 9) -#define USB_EP_EP_TYPE_BULK (0x0 << 9) -#define USB_EP_EP_TYPE_CONTROL (0x1 << 9) -#define USB_EP_EP_TYPE_ISO (0x2 << 9) -#define USB_EP_EP_TYPE_INTERRUPT (0x3 << 9) -#define USB_EP_EP_KIND BIT(USB_EP_EP_KIND_BIT) -#define USB_EP_CTR_TX BIT(USB_EP_CTR_TX_BIT) -#define USB_EP_DTOG_TX BIT(USB_EP_DTOG_TX_BIT) -#define USB_EP_STAT_TX (0x3 << 4) -#define USB_EP_STAT_TX_DISABLED (0x0 << 4) -#define USB_EP_STAT_TX_STALL (0x1 << 4) -#define USB_EP_STAT_TX_NAK (0x2 << 4) -#define USB_EP_STAT_TX_VALID (0x3 << 4) -#define USB_EP_EA 0xF - -/* Control register (USB_CNTR) */ - -#define USB_CNTR_CTRM_BIT 15 -#define USB_CNTR_PMAOVERM_BIT 14 -#define USB_CNTR_ERRM_BIT 13 -#define USB_CNTR_WKUPM_BIT 12 -#define USB_CNTR_SUSPM_BIT 11 -#define USB_CNTR_RESETM_BIT 10 -#define USB_CNTR_SOFM_BIT 9 -#define USB_CNTR_ESOFM_BIT 8 -#define USB_CNTR_RESUME_BIT 4 -#define USB_CNTR_FSUSP_BIT 3 -#define USB_CNTR_LP_MODE_BIT 2 -#define USB_CNTR_PDWN_BIT 1 -#define USB_CNTR_FRES_BIT 0 - -#define USB_CNTR_CTRM BIT(USB_CNTR_CTRM_BIT) -#define USB_CNTR_PMAOVERM BIT(USB_CNTR_PMAOVERM_BIT) -#define USB_CNTR_ERRM BIT(USB_CNTR_ERRM_BIT) -#define USB_CNTR_WKUPM BIT(USB_CNTR_WKUPM_BIT) -#define USB_CNTR_SUSPM BIT(USB_CNTR_SUSPM_BIT) -#define USB_CNTR_RESETM BIT(USB_CNTR_RESETM_BIT) -#define USB_CNTR_SOFM BIT(USB_CNTR_SOFM_BIT) -#define USB_CNTR_ESOFM BIT(USB_CNTR_ESOFM_BIT) -#define USB_CNTR_RESUME BIT(USB_CNTR_RESUME_BIT) -#define USB_CNTR_FSUSP BIT(USB_CNTR_FSUSP_BIT) -#define USB_CNTR_LP_MODE BIT(USB_CNTR_LP_MODE_BIT) -#define USB_CNTR_PDWN BIT(USB_CNTR_PDWN_BIT) -#define USB_CNTR_FRES BIT(USB_CNTR_FRES_BIT) - -/* Interrupt status register (USB_ISTR) */ - -#define USB_ISTR_CTR_BIT 15 -#define USB_ISTR_PMAOVR_BIT 14 -#define USB_ISTR_ERR_BIT 13 -#define USB_ISTR_WKUP_BIT 12 -#define USB_ISTR_SUSP_BIT 11 -#define USB_ISTR_RESET_BIT 10 -#define USB_ISTR_SOF_BIT 9 -#define USB_ISTR_ESOF_BIT 8 -#define USB_ISTR_DIR_BIT 4 - -#define USB_ISTR_CTR BIT(USB_ISTR_CTR_BIT) -#define USB_ISTR_PMAOVR BIT(USB_ISTR_PMAOVR_BIT) -#define USB_ISTR_ERR BIT(USB_ISTR_ERR_BIT) -#define USB_ISTR_WKUP BIT(USB_ISTR_WKUP_BIT) -#define USB_ISTR_SUSP BIT(USB_ISTR_SUSP_BIT) -#define USB_ISTR_RESET BIT(USB_ISTR_RESET_BIT) -#define USB_ISTR_SOF BIT(USB_ISTR_SOF_BIT) -#define USB_ISTR_ESOF BIT(USB_ISTR_ESOF_BIT) -#define USB_ISTR_DIR BIT(USB_ISTR_DIR_BIT) -#define USB_ISTR_EP_ID 0xF - -/* Frame number register (USB_FNR) */ - -#define USB_FNR_RXDP_BIT 15 -#define USB_FNR_RXDM_BIT 14 -#define USB_FNR_LCK_BIT 13 - -#define USB_FNR_RXDP BIT(USB_FNR_RXDP_BIT) -#define USB_FNR_RXDM BIT(USB_FNR_RXDM_BIT) -#define USB_FNR_LCK BIT(USB_FNR_LCK_BIT) -#define USB_FNR_LSOF (0x3 << 11) -#define USB_FNR_FN 0x7FF - -/* Device address (USB_DADDR) */ - -#define USB_DADDR_EF_BIT 7 -#define USB_DADDR_ADD6_BIT 6 -#define USB_DADDR_ADD5_BIT 5 -#define USB_DADDR_ADD4_BIT 4 -#define USB_DADDR_ADD3_BIT 3 -#define USB_DADDR_ADD2_BIT 2 -#define USB_DADDR_ADD1_BIT 1 -#define USB_DADDR_ADD0_BIT 0 - -#define USB_DADDR_EF BIT(USB_DADDR_EF_BIT) -#define USB_DADDR_ADD6 BIT(USB_DADDR_ADD6_BIT) -#define USB_DADDR_ADD5 BIT(USB_DADDR_ADD5_BIT) -#define USB_DADDR_ADD4 BIT(USB_DADDR_ADD4_BIT) -#define USB_DADDR_ADD3 BIT(USB_DADDR_ADD3_BIT) -#define USB_DADDR_ADD2 BIT(USB_DADDR_ADD2_BIT) -#define USB_DADDR_ADD1 BIT(USB_DADDR_ADD1_BIT) -#define USB_DADDR_ADD0 BIT(USB_DADDR_ADD0_BIT) - -/* Buffer table address (USB_BTABLE) */ - -#define USB_BTABLE_BTABLE (0x1FFF << 3) - -/* - * Register convenience routines - */ - -#define __EP_CTR_NOP (USB_EP_CTR_RX | USB_EP_CTR_TX) -#define __EP_NONTOGGLE (USB_EP_CTR_RX | USB_EP_SETUP | \ - USB_EP_EP_TYPE | USB_EP_EP_KIND | \ - USB_EP_CTR_TX | USB_EP_EA) - -static inline void usb_clear_ctr_rx(uint8 ep) { - uint32 epr = USB_BASE->EP[ep]; - USB_BASE->EP[ep] = epr & ~USB_EP_CTR_RX & __EP_NONTOGGLE; -} - -static inline void usb_clear_ctr_tx(uint8 ep) { - uint32 epr = USB_BASE->EP[ep]; - USB_BASE->EP[ep] = epr & ~USB_EP_CTR_TX & __EP_NONTOGGLE; -} - -static inline void usb_set_ep_rx_stat(uint8 ep, uint32 status) { - uint32 epr = USB_BASE->EP[ep]; - epr &= ~(USB_EP_STAT_TX | USB_EP_DTOG_RX | USB_EP_DTOG_TX); - epr |= __EP_CTR_NOP; - epr ^= status; - USB_BASE->EP[ep] = epr; -} - -static inline void usb_set_ep_tx_stat(uint8 ep, uint32 status) { - uint32 epr = USB_BASE->EP[ep]; - epr &= ~(USB_EP_STAT_RX | USB_EP_DTOG_RX | USB_EP_DTOG_TX); - epr |= __EP_CTR_NOP; - epr ^= status; - USB_BASE->EP[ep] = epr; -} - -static inline void usb_set_ep_type(uint8 ep, uint32 type) { - uint32 epr = USB_BASE->EP[ep]; - epr &= ~USB_EP_EP_TYPE & __EP_NONTOGGLE; - epr |= type; - USB_BASE->EP[ep] = epr; -} - -static inline void usb_set_ep_kind(uint8 ep, uint32 kind) { - uint32 epr = USB_BASE->EP[ep]; - epr &= ~USB_EP_EP_KIND & __EP_NONTOGGLE; - epr |= kind; - USB_BASE->EP[ep] = epr; -} - -static inline void usb_clear_status_out(uint8 ep) { - usb_set_ep_kind(ep, 0); -} - -/* - * Packet memory area (PMA) base pointer - */ - -/** - * @brief USB packet memory area (PMA) base pointer. - * - * The USB PMA is SRAM shared between USB and CAN. The USB peripheral - * accesses this memory directly via the packet buffer interface. */ -#define USB_PMA_BASE ((__io void*)0x40006000) - -/* - * PMA conveniences - */ - -void usb_copy_to_pma(const uint8 *buf, uint16 len, uint16 pma_offset); -void usb_copy_from_pma(uint8 *buf, uint16 len, uint16 pma_offset); - -static inline void* usb_pma_ptr(uint32 offset) { - return (void*)(USB_PMA_BASE + 2 * offset); -} - -/* - * BTABLE - */ - -/* (Forward-declared) BTABLE entry. - * - * The BTABLE can be viewed as an array of usb_btable_ent values; - * these vary in structure according to the configuration of the - * endpoint. - */ -union usb_btable_ent; - -/* Bidirectional endpoint BTABLE entry */ -typedef struct usb_btable_bidi { - __io uint16 addr_tx; const uint16 PAD1; - __io uint16 count_tx; const uint16 PAD2; - __io uint16 addr_rx; const uint16 PAD3; - __io uint16 count_rx; const uint16 PAD4; -} usb_btable_bidi; - -/* Unidirectional receive-only endpoint BTABLE entry */ -typedef struct usb_btable_uni_rx { - __io uint16 empty1; const uint16 PAD1; - __io uint16 empty2; const uint16 PAD2; - __io uint16 addr_rx; const uint16 PAD3; - __io uint16 count_rx; const uint16 PAD4; -} usb_btable_uni_rx; - -/* Unidirectional transmit-only endpoint BTABLE entry */ -typedef struct usb_btable_uni_tx { - __io uint16 addr_tx; const uint16 PAD1; - __io uint16 count_tx; const uint16 PAD2; - __io uint16 empty1; const uint16 PAD3; - __io uint16 empty2; const uint16 PAD4; -} usb_btable_uni_tx; - -/* Double-buffered transmission endpoint BTABLE entry */ -typedef struct usb_btable_dbl_tx { - __io uint16 addr_tx0; const uint16 PAD1; - __io uint16 count_tx0; const uint16 PAD2; - __io uint16 addr_tx1; const uint16 PAD3; - __io uint16 count_tx1; const uint16 PAD4; -} usb_btable_dbl_tx; - -/* Double-buffered reception endpoint BTABLE entry */ -typedef struct usb_btable_dbl_rx { - __io uint16 addr_rx0; const uint16 PAD1; - __io uint16 count_rx0; const uint16 PAD2; - __io uint16 addr_rx1; const uint16 PAD3; - __io uint16 count_rx1; const uint16 PAD4; -} usb_btable_dbl_rx; - -/* TODO isochronous endpoint entries */ - -/* Definition for above forward-declared BTABLE entry. */ -typedef union usb_btable_ent { - usb_btable_bidi bidi; - usb_btable_uni_rx u_rx; - usb_btable_uni_tx u_tx; - usb_btable_dbl_tx d_tx; - usb_btable_dbl_rx d_rx; -} usb_btable_ent; - -/* - * BTABLE conveniences - */ - -/* TODO (?) Convert usages of the many (and lengthily-named) - * accessors/mutators below to just manipulating usb_btable_entry - * values. */ - -static inline uint32* usb_btable_ptr(uint32 offset) { - return (uint32*)usb_pma_ptr(USB_BASE->BTABLE + offset); -} - -static inline usb_btable_ent *usb_btable(void) { - return (usb_btable_ent*)usb_btable_ptr(0); -} - -/* TX address */ - -static inline uint32* usb_ep_tx_addr_ptr(uint8 ep) { - return usb_btable_ptr(ep * 8); -} - -static inline uint16 usb_get_ep_tx_addr(uint8 ep) { - return (uint16)*usb_ep_tx_addr_ptr(ep); -} - -static inline void usb_set_ep_tx_addr(uint8 ep, uint16 addr) { - uint32 *tx_addr = usb_ep_tx_addr_ptr(ep); - *tx_addr = addr & ~0x1; -} - -/* RX address */ - -static inline uint32* usb_ep_rx_addr_ptr(uint8 ep) { - return usb_btable_ptr(ep * 8 + 4); -} - -static inline uint16 usb_get_ep_rx_addr(uint8 ep) { - return (uint16)*usb_ep_rx_addr_ptr(ep); -} - -static inline void usb_set_ep_rx_addr(uint8 ep, uint16 addr) { - uint32 *rx_addr = usb_ep_rx_addr_ptr(ep); - *rx_addr = addr & ~0x1; -} - -/* TX count (doesn't cover double-buffered and isochronous in) */ - -static inline uint32* usb_ep_tx_count_ptr(uint8 ep) { - return usb_btable_ptr(ep * 8 + 2); -} - -static inline uint16 usb_get_ep_tx_count(uint8 ep) { - return (uint16)*usb_ep_tx_count_ptr(ep); -} - -static inline void usb_set_ep_tx_count(uint8 ep, uint16 count) { - uint32 *txc = usb_ep_tx_count_ptr(ep); - *txc = count; -} - -/* RX count */ - -static inline uint32* usb_ep_rx_count_ptr(uint8 ep) { - return usb_btable_ptr(ep * 8 + 6); -} - -static inline uint16 usb_get_ep_rx_count(uint8 ep) { - return (uint16)*usb_ep_rx_count_ptr(ep) & 0x3FF; -} - -void usb_set_ep_rx_count(uint8 ep, uint16 count); - -/* - * Misc. types - */ - -typedef enum usb_ep { - USB_EP0, - USB_EP1, - USB_EP2, - USB_EP3, - USB_EP4, - USB_EP5, - USB_EP6, - USB_EP7, -} usb_ep; - -typedef enum usb_ep_type { - USB_EP_T_CTL = USB_EP_EP_TYPE_CONTROL, - USB_EP_T_BULK = USB_EP_EP_TYPE_BULK, - USB_EP_T_INT = USB_EP_EP_TYPE_INTERRUPT, - USB_EP_T_ISO = USB_EP_EP_TYPE_ISO -} usb_ep_type; - -typedef enum usb_ep_stat { - USB_EP_ST_RX_DIS = USB_EP_STAT_RX_DISABLED, - USB_EP_ST_RX_STL = USB_EP_STAT_RX_STALL, - USB_EP_ST_RX_NAK = USB_EP_STAT_RX_NAK, - USB_EP_ST_RX_VAL = USB_EP_STAT_RX_VALID, - USB_EP_ST_TX_DIS = USB_EP_STAT_TX_DISABLED, - USB_EP_ST_TX_STL = USB_EP_STAT_TX_STALL, - USB_EP_ST_TX_NAK = USB_EP_STAT_TX_NAK, - USB_EP_ST_TX_VAL = USB_EP_STAT_TX_VALID -} usb_ep_stat; - -#endif diff --git a/support/ld/stm32/series/stm32f1/value/vector_symbols.inc b/support/ld/stm32/series/stm32f1/value/vector_symbols.inc new file mode 100644 index 0000000..f8726f9 --- /dev/null +++ b/support/ld/stm32/series/stm32f1/value/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_adc1) +EXTERN(__stm32reservedexception14) +EXTERN(__stm32reservedexception15) +EXTERN(__stm32reservedexception16) +EXTERN(__stm32reservedexception17) +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_cec) +EXTERN(__irq_tim12) +EXTERN(__irq_tim13) +EXTERN(__irq_tim14) +EXTERN(__stm32reservedexception18) +EXTERN(__stm32reservedexception19) +EXTERN(__irq_fsmc) +EXTERN(__stm32reservedexception20) +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) +EXTERN(__irq_dma2_channel5) /* on remap only */ diff --git a/support/make/board-includes/VLDiscovery.mk b/support/make/board-includes/VLDiscovery.mk index 82d1b23..441f078 100644 --- a/support/make/board-includes/VLDiscovery.mk +++ b/support/make/board-includes/VLDiscovery.mk @@ -3,3 +3,4 @@ PRODUCT_ID := 0003 ERROR_LED_PORT := GPIOC ERROR_LED_PIN := 9 MCU_SERIES := stm32f1 +MCU_F1_LINE := value diff --git a/support/make/board-includes/maple.mk b/support/make/board-includes/maple.mk index d31ad83..4de4bab 100644 --- a/support/make/board-includes/maple.mk +++ b/support/make/board-includes/maple.mk @@ -3,3 +3,4 @@ PRODUCT_ID := 0003 ERROR_LED_PORT := GPIOA ERROR_LED_PIN := 5 MCU_SERIES := stm32f1 +MCU_F1_LINE := performance diff --git a/support/make/board-includes/maple_RET6.mk b/support/make/board-includes/maple_RET6.mk index d06f068..104ae08 100644 --- a/support/make/board-includes/maple_RET6.mk +++ b/support/make/board-includes/maple_RET6.mk @@ -3,3 +3,4 @@ PRODUCT_ID := 0003 ERROR_LED_PORT := GPIOA ERROR_LED_PIN := 5 MCU_SERIES := stm32f1 +MCU_F1_LINE := performance diff --git a/support/make/board-includes/maple_mini.mk b/support/make/board-includes/maple_mini.mk index 835adc3..70ef506 100644 --- a/support/make/board-includes/maple_mini.mk +++ b/support/make/board-includes/maple_mini.mk @@ -3,3 +3,4 @@ PRODUCT_ID := 0003 ERROR_LED_PORT := GPIOB ERROR_LED_PIN := 1 MCU_SERIES := stm32f1 +MCU_F1_LINE := performance diff --git a/support/make/board-includes/maple_native.mk b/support/make/board-includes/maple_native.mk index 3e88e7b..86746a6 100644 --- a/support/make/board-includes/maple_native.mk +++ b/support/make/board-includes/maple_native.mk @@ -3,3 +3,4 @@ PRODUCT_ID := 0003 ERROR_LED_PORT := GPIOC ERROR_LED_PIN := 15 MCU_SERIES := stm32f1 +MCU_F1_LINE := performance diff --git a/support/make/board-includes/olimex_stm32_h103.mk b/support/make/board-includes/olimex_stm32_h103.mk index 96d6976..31f2c04 100644 --- a/support/make/board-includes/olimex_stm32_h103.mk +++ b/support/make/board-includes/olimex_stm32_h103.mk @@ -3,3 +3,4 @@ PRODUCT_ID := 0003 ERROR_LED_PORT := GPIOC ERROR_LED_PIN := 12 MCU_SERIES := stm32f1 +MCU_F1_LINE := performance diff --git a/support/make/target-config.mk b/support/make/target-config.mk index 48a33de..e13504d 100644 --- a/support/make/target-config.mk +++ b/support/make/target-config.mk @@ -15,9 +15,9 @@ TARGET_FLAGS += -DBOARD_$(BOARD) -DMCU_$(MCU) \ LD_SERIES_PATH := $(LDDIR)/stm32/series/$(MCU_SERIES) ifeq ($(MCU_SERIES), stm32f1) - # Hack: force F1 to performance line; this will need to change if - # you add connectivity etc. line support. - LD_SERIES_PATH := $(LD_SERIES_PATH)/performance +# Due to the Balkanization on F1, we need to specify the line when +# making linker decisions. +LD_SERIES_PATH := $(LD_SERIES_PATH)/$(MCU_F1_LINE) endif LIBMAPLE_MODULE_SERIES := $(LIBMAPLE_PATH)/$(MCU_SERIES) diff --git a/wirish/include/wirish/usb_serial.h b/wirish/include/wirish/usb_serial.h index 81e9e97..f36671b 100644 --- a/wirish/include/wirish/usb_serial.h +++ b/wirish/include/wirish/usb_serial.h @@ -25,13 +25,14 @@ *****************************************************************************/ /** - * @brief Wirish virtual serial port + * @brief Wirish USB virtual serial port (SerialUSB). */ #ifndef _WIRISH_USB_SERIAL_H_ #define _WIRISH_USB_SERIAL_H_ #include +#include /** * @brief Virtual serial terminal. @@ -58,7 +59,9 @@ public: uint8 pending(); }; +#if BOARD_HAVE_SERIALUSB extern USBSerial SerialUSB; +#endif #endif diff --git a/wirish/rules.mk b/wirish/rules.mk index 147857a..6d96cbe 100644 --- a/wirish/rules.mk +++ b/wirish/rules.mk @@ -26,6 +26,9 @@ cppSRCS_$(d) += HardwareSerial.cpp cppSRCS_$(d) += HardwareTimer.cpp cppSRCS_$(d) += Print.cpp cppSRCS_$(d) += pwm.cpp +ifeq ($(MCU_SERIES), stm32f1) +cppSRCS_$(d) += usb_serial.cpp # HACK: this is currently STM32F1 only. +endif cppSRCS_$(d) += wirish_analog.cpp cppSRCS_$(d) += wirish_digital.cpp cppSRCS_$(d) += wirish_math.cpp @@ -36,7 +39,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 -# usb_serial.cpp # ext_interrupts.cpp sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%) diff --git a/wirish/stm32f1/boards_setup.cpp b/wirish/stm32f1/boards_setup.cpp index 423e5ec..1dec579 100644 --- a/wirish/stm32f1/boards_setup.cpp +++ b/wirish/stm32f1/boards_setup.cpp @@ -38,9 +38,9 @@ #include #include -#include -#include +#include +#include // Allow boards to provide a PLL multiplier. This is useful for // e.g. STM32F100 value line MCUs, which use slower multipliers. @@ -80,10 +80,8 @@ namespace wirish { } void board_setup_usb(void) { -#if 0 -# if STM32_HAVE_USB - usb_cdcacm_enable(BOARD_USB_DISC_DEV, BOARD_USB_DISC_BIT); -# endif +#if BOARD_HAVE_SERIALUSB + SerialUSB.begin(); #endif } } diff --git a/wirish/usb_serial.cpp b/wirish/usb_serial.cpp index 388c739..a01900f 100644 --- a/wirish/usb_serial.cpp +++ b/wirish/usb_serial.cpp @@ -40,14 +40,21 @@ #define USB_TIMEOUT 50 USBSerial::USBSerial(void) { +#if !BOARD_HAVE_SERIALUSB + ASSERT(0); +#endif } void USBSerial::begin(void) { +#if BOARD_HAVE_SERIALUSB usb_cdcacm_enable(BOARD_USB_DISC_DEV, BOARD_USB_DISC_BIT); +#endif } void USBSerial::end(void) { +#if BOARD_HAVE_SERIALUSB usb_cdcacm_disable(BOARD_USB_DISC_DEV, BOARD_USB_DISC_BIT); +#endif } void USBSerial::write(uint8 ch) { @@ -117,4 +124,6 @@ uint8 USBSerial::getRTS(void) { return usb_cdcacm_get_rts(); } +#if BOARD_HAVE_SERIALUSB USBSerial SerialUSB; +#endif -- 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 'wirish/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 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 'wirish/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 3193ae1326c738b54067674a6073287f90ecaa85 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Fri, 8 Jun 2012 18:34:33 -0400 Subject: Bring back . Signed-off-by: Marti Bolivar --- wirish/include/wirish/wirish.h | 2 +- wirish/include/wirish/wirish_debug.h | 8 ++--- wirish/rules.mk | 1 + wirish/stm32f1/wirish_debug.cpp | 41 ++++++++++++++++++++++++ wirish/stm32f2/wirish_debug.cpp | 60 ++++++++++++++++++++++++++++++++++++ 5 files changed, 105 insertions(+), 7 deletions(-) create mode 100644 wirish/stm32f1/wirish_debug.cpp create mode 100644 wirish/stm32f2/wirish_debug.cpp (limited to 'wirish/rules.mk') diff --git a/wirish/include/wirish/wirish.h b/wirish/include/wirish/wirish.h index 6810e4f..360b502 100644 --- a/wirish/include/wirish/wirish.h +++ b/wirish/include/wirish/wirish.h @@ -39,7 +39,7 @@ #include #include #include -/* FIXME put this back when you can #include */ +#include #include #include /* FIXME put this back when you can #include */ diff --git a/wirish/include/wirish/wirish_debug.h b/wirish/include/wirish/wirish_debug.h index cb1be3d..4edfd27 100644 --- a/wirish/include/wirish/wirish_debug.h +++ b/wirish/include/wirish/wirish_debug.h @@ -42,9 +42,7 @@ * * @see enableDebugPorts() */ -static inline void disableDebugPorts(void) { - afio_cfg_debug_ports(AFIO_DEBUG_NONE); -} +void disableDebugPorts(void); /** * @brief Enable the JTAG and Serial Wire (SW) debug ports. @@ -54,8 +52,6 @@ static inline void disableDebugPorts(void) { * * @see disableDebugPorts() */ -static inline void enableDebugPorts(void) { - afio_cfg_debug_ports(AFIO_DEBUG_FULL_SWJ); -} +void enableDebugPorts(void); #endif diff --git a/wirish/rules.mk b/wirish/rules.mk index acf4c46..5138c82 100644 --- a/wirish/rules.mk +++ b/wirish/rules.mk @@ -38,6 +38,7 @@ cppSRCS_$(d) += wirish_shift.cpp cppSRCS_$(d) += wirish_time.cpp cppSRCS_$(d) += $(MCU_SERIES)/boards_setup.cpp cppSRCS_$(d) += $(MCU_SERIES)/wirish_digital.cpp +cppSRCS_$(d) += $(MCU_SERIES)/wirish_debug.cpp cppSRCS_$(d) += $(WIRISH_BOARD_PATH)/board.cpp # TODO: revise these appropriately for F2 and put them back in: # HardwareSPI.cpp diff --git a/wirish/stm32f1/wirish_debug.cpp b/wirish/stm32f1/wirish_debug.cpp new file mode 100644 index 0000000..28de96d --- /dev/null +++ b/wirish/stm32f1/wirish_debug.cpp @@ -0,0 +1,41 @@ +/****************************************************************************** + * 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 wirish/stm32f1/wirish_debug.cpp + * @brief High level debug port configuration + */ + +#include +#include + +void disableDebugPorts(void) { + afio_cfg_debug_ports(AFIO_DEBUG_NONE); +} + +void enableDebugPorts(void) { + afio_cfg_debug_ports(AFIO_DEBUG_FULL_SWJ); +} diff --git a/wirish/stm32f2/wirish_debug.cpp b/wirish/stm32f2/wirish_debug.cpp new file mode 100644 index 0000000..af6c78b --- /dev/null +++ b/wirish/stm32f2/wirish_debug.cpp @@ -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. + *****************************************************************************/ + +/** + * @file wirish/stm32f2/wirish_debug.cpp + * @brief High level debug port configuration + */ + +#include +#include + +// TODO is it worth optimizing these into raw MODER and AFR[LH] writes? + +void disableDebugPorts(void) { + // PA13-PA15 and PB3-PB4 are in system alternate function mode on + // reset, to support JTAG. Just put them in input mode to release + // them. + gpio_set_mode(GPIOA, 13, GPIO_MODE_INPUT); + gpio_set_mode(GPIOA, 14, GPIO_MODE_INPUT); + gpio_set_mode(GPIOA, 15, GPIO_MODE_INPUT); + gpio_set_mode(GPIOB, 3, GPIO_MODE_INPUT); + gpio_set_mode(GPIOB, 4, GPIO_MODE_INPUT); +} + +void enableDebugPorts(void) { + // Put PA13-PA15 and PB3-PB4 back in system AF mode. + gpio_set_mode(GPIOA, 13, GPIO_MODE_AF); + gpio_set_mode(GPIOA, 14, GPIO_MODE_AF); + gpio_set_mode(GPIOA, 15, GPIO_MODE_AF); + gpio_set_mode(GPIOB, 3, GPIO_MODE_AF); + gpio_set_mode(GPIOB, 4, GPIO_MODE_AF); + gpio_set_af(GPIOA, 13, GPIO_AF_SYS); + gpio_set_af(GPIOA, 14, GPIO_AF_SYS); + gpio_set_af(GPIOA, 15, GPIO_AF_SYS); + gpio_set_af(GPIOB, 3, GPIO_AF_SYS); + gpio_set_af(GPIOB, 4, GPIO_AF_SYS); +} -- cgit v1.2.3 From fbbf35ee079d1c979909981c95132ba7eaca7215 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Tue, 26 Jun 2012 18:03:40 -0400 Subject: Bring back and fix up util.c functionality. Rip out the existing nonportable pieces, and shove them under wirish/stm32f1, using weak symbols so users who only want libmaple proper don't end up with build errors. Add stubbed-out (and only partially functional) definitions for F2 targets under wirish/stm32f2. The behavior on F103 targets is the same as it was before (though the assertion framework has always been broken and badly needs replacement, that awaits another commit). We additionally now skip re-enabling USB on F1 targets without USB, to make things work on value line MCUs. Signed-off-by: Marti Bolivar --- libmaple/util.c | 119 ++++++++++++++++---------------------------- wirish/rules.mk | 1 + wirish/stm32f1/util_hooks.c | 83 ++++++++++++++++++++++++++++++ wirish/stm32f2/util_hooks.c | 45 +++++++++++++++++ 4 files changed, 171 insertions(+), 77 deletions(-) create mode 100644 wirish/stm32f1/util_hooks.c create mode 100644 wirish/stm32f2/util_hooks.c (limited to 'wirish/rules.mk') diff --git a/libmaple/util.c b/libmaple/util.c index 88da075..2ee5ede 100644 --- a/libmaple/util.c +++ b/libmaple/util.c @@ -26,27 +26,17 @@ /** * @file libmaple/util.c - * @brief Utility procedures for debugging, mostly an error LED fade - * and messages dumped over a UART for failed asserts. + * @brief Utility procedures for debugging */ #include #include #include #include -#include -#include -/* FIXME [0.0.13] put this stuff back in some form. Move to Wirish? */ - -/* Failed ASSERT()s send out a message using this USART config. */ -#ifndef ERROR_USART -#define ERROR_USART USART2 -#define ERROR_USART_CLK_SPEED STM32_PCLK1 -#define ERROR_USART_BAUD 9600 -#define ERROR_TX_PORT GPIOA -#define ERROR_TX_PIN 2 -#endif +/* (Undocumented) hooks used by Wirish to direct our behavior here */ +extern __weak void __lm_error(void); +extern __weak usart_dev* __lm_enable_error_usart(void); /* If you define ERROR_LED_PORT and ERROR_LED_PIN, then a failed * ASSERT() will also throb() an LED connected to that port and pin. @@ -55,100 +45,75 @@ #define HAVE_ERROR_LED #endif -/** - * @brief Disables all peripheral interrupts except USB and fades the - * error LED. - */ /* (Called from exc.S with global interrupts disabled.) */ -void __error(void) { - /* Turn off peripheral interrupts */ - nvic_irq_disable_all(); - - /* /\* Turn off timers *\/ */ - /* timer_disable_all(); */ - - /* /\* Turn off ADC *\/ */ - /* adc_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); */ - +__attribute__((noreturn)) void __error(void) { + if (__lm_error) { + __lm_error(); + } /* Reenable global interrupts */ nvic_globalirq_enable(); throb(); } -/** - * @brief Enable the error USART for writing. - * @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); */ -} - -/** - * @brief Print an error message on a UART upon a failed assertion - * and throb the error LED, if there is one defined. +/* + * Print an error message on a UART upon a failed assertion (if one is + * available), and punt to __error(). + * * @param file Source file of failed assertion * @param line Source line of failed assertion * @param exp String representation of failed assertion * @sideeffect Turns of all peripheral interrupts except USB. */ 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'); */ - + if (__lm_enable_error_usart) { + /* Initialize the error USART */ + usart_dev *err_usart = __lm_enable_error_usart(); + + /* Print failed assert message */ + usart_putstr(err_usart, "ERROR: FAILED ASSERT("); + usart_putstr(err_usart, exp); + usart_putstr(err_usart, "): "); + usart_putstr(err_usart, file); + usart_putstr(err_usart, ": "); + usart_putudec(err_usart, line); + usart_putc(err_usart, '\n'); + usart_putc(err_usart, '\r'); + } /* Shutdown and error fade */ __error(); } -/** - * @brief Provide an __assert_func handler to libc so that calls to assert() get - * redirected to _fail. +/* + * Provide an __assert_func handler to libc so that calls to assert() + * get redirected to _fail. */ void __assert_func(const char* file, int line, const char* method, const char* expression) { _fail(file, line, expression); } -/** - * @brief Provide an abort() implementation that aborts execution and enters an - * error state with the throbbing LED indicator. +/* + * Provide an abort() implementation that aborts execution and punts + * to __error(). */ void abort() { - /* /\* Initialize the error USART *\/ */ - /* _enable_error_usart(); */ - - /* /\* Print abort message. *\/ */ - /* usart_putstr(ERROR_USART, "ERROR: PROGRAM ABORTED VIA abort()\n\r"); */ + if (__lm_enable_error_usart) { + /* Initialize the error USART */ + usart_dev *err_usart = __lm_enable_error_usart(); + /* Print abort message. */ + usart_putstr(err_usart, "ERROR: PROGRAM ABORTED VIA abort()\r\n"); + } - /* /\* Shutdown and error fade *\/ */ - /* __error(); */ - while (1) - ; + /* Shutdown and error fade */ + __error(); } +/* This was public as of v0.0.12, so we've got to keep it public. */ /** * @brief Fades the error LED on and off * @sideeffect Sets output push-pull on ERROR_LED_PIN. */ -void throb(void) { +__attribute__((noreturn)) void throb(void) { #ifdef HAVE_ERROR_LED int32 slope = 1; uint32 CC = 0x0000; diff --git a/wirish/rules.mk b/wirish/rules.mk index 5138c82..f895213 100644 --- a/wirish/rules.mk +++ b/wirish/rules.mk @@ -21,6 +21,7 @@ CFLAGS_$(d) := $(LIBMAPLE_INCLUDES) $(WIRISH_INCLUDES) -I$(d) sSRCS_$(d) := start.S cSRCS_$(d) := start_c.c cSRCS_$(d) += syscalls.c +cSRCS_$(d) += $(MCU_SERIES)/util_hooks.c cppSRCS_$(d) := boards.cpp cppSRCS_$(d) += cxxabi-compat.cpp cppSRCS_$(d) += ext_interrupts.cpp diff --git a/wirish/stm32f1/util_hooks.c b/wirish/stm32f1/util_hooks.c new file mode 100644 index 0000000..8f798a1 --- /dev/null +++ b/wirish/stm32f1/util_hooks.c @@ -0,0 +1,83 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Perry Hung (from libmaple/util.c). + * 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. + *****************************************************************************/ + +/* + * STM32F1 implementations for libmaple/util.c hooks + * + * These need more love and attention before being made public API + * (this includes being easily overridable by user code). + */ + +#include +#include +#include +#include +#include +#include + +/* Failed ASSERT()s send out a message using this USART config. */ +#ifndef ERROR_USART +#define ERROR_USART USART2 +#define ERROR_USART_BAUD 9600 +#define ERROR_TX_PORT GPIOA +#define ERROR_TX_PIN 2 +#endif + +/* + * Disables all peripheral interrupts except USB (when available), + * turns off commonly-used peripherals. Called by __error() with + * global interrupts disabled. + */ +void __lm_error(void) { + /* Turn off peripheral interrupts */ + nvic_irq_disable_all(); + + /* Turn off timers */ + timer_disable_all(); + + /* Turn off ADC */ + adc_disable_all(); + + /* Turn off all USARTs */ + usart_disable_all(); + +#if STM32_HAVE_USB + /* 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); +#endif +} + +/* + * Enable the error USART for writing. + */ +usart_dev* __lm_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, USART_USE_PCLK, ERROR_USART_BAUD); + return ERROR_USART; +} diff --git a/wirish/stm32f2/util_hooks.c b/wirish/stm32f2/util_hooks.c new file mode 100644 index 0000000..1b519ab --- /dev/null +++ b/wirish/stm32f2/util_hooks.c @@ -0,0 +1,45 @@ +/****************************************************************************** + * 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 libmaple util.c hooks + * FIXME these are just minimal stubs + */ + +#include + +/* + * Disables all peripheral interrupts. Called by __error() with global + * interrupts disabled. + */ +void __lm_error(void) { + nvic_irq_disable_all(); +} + +/* + * Enable the error USART for writing. + */ +/* usart_dev* __lm_enable_error_usart(void) { (TODO) } */ -- cgit v1.2.3 From c6073e4886da4606679bc3e9d770c9cff9390597 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Tue, 26 Jun 2012 18:13:12 -0400 Subject: STM32F1: Bring back HardwareSPI. We're going to merge into master without F2 support for this. Signed-off-by: Marti Bolivar --- wirish/include/wirish/wirish.h | 6 +++++- wirish/rules.mk | 3 +-- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'wirish/rules.mk') diff --git a/wirish/include/wirish/wirish.h b/wirish/include/wirish/wirish.h index 360b502..4ebd66f 100644 --- a/wirish/include/wirish/wirish.h +++ b/wirish/include/wirish/wirish.h @@ -34,6 +34,8 @@ #ifndef _WIRISH_WIRISH_H_ #define _WIRISH_WIRISH_H_ +#include + #include #include #include @@ -42,7 +44,9 @@ #include #include #include -/* FIXME put this back when you can #include */ +#if STM32_MCU_SERIES == STM32_SERIES_F1 /* FIXME [0.0.13?] port to F2 */ +#include +#endif #include #include #include diff --git a/wirish/rules.mk b/wirish/rules.mk index f895213..1cac74a 100644 --- a/wirish/rules.mk +++ b/wirish/rules.mk @@ -31,6 +31,7 @@ cppSRCS_$(d) += Print.cpp cppSRCS_$(d) += pwm.cpp ifeq ($(MCU_SERIES), stm32f1) cppSRCS_$(d) += usb_serial.cpp # HACK: this is currently STM32F1 only. +cppSRCS_$(d) += HardwareSPI.cpp # FIXME: port to F2 and fix wirish.h endif cppSRCS_$(d) += wirish_analog.cpp cppSRCS_$(d) += wirish_digital.cpp @@ -41,8 +42,6 @@ cppSRCS_$(d) += $(MCU_SERIES)/boards_setup.cpp cppSRCS_$(d) += $(MCU_SERIES)/wirish_digital.cpp cppSRCS_$(d) += $(MCU_SERIES)/wirish_debug.cpp cppSRCS_$(d) += $(WIRISH_BOARD_PATH)/board.cpp -# TODO: revise these appropriately for F2 and put them back in: -# HardwareSPI.cpp sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%) cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%) -- cgit v1.2.3