diff --git a/BootLoaders/Boards/boards.txt b/BootLoaders/Boards/avr/boards.txt similarity index 100% rename from BootLoaders/Boards/boards.txt rename to BootLoaders/Boards/avr/boards.txt diff --git a/BootLoaders/Boards/bootloaders/Multi4in1/AtmegaMultiBoot.hex b/BootLoaders/Boards/avr/bootloaders/Multi4in1/AtmegaMultiBoot.hex similarity index 100% rename from BootLoaders/Boards/bootloaders/Multi4in1/AtmegaMultiBoot.hex rename to BootLoaders/Boards/avr/bootloaders/Multi4in1/AtmegaMultiBoot.hex diff --git a/BootLoaders/Boards/bootloaders/Multi4in1/AtmegaMultiEmpty.hex b/BootLoaders/Boards/avr/bootloaders/Multi4in1/AtmegaMultiEmpty.hex similarity index 100% rename from BootLoaders/Boards/bootloaders/Multi4in1/AtmegaMultiEmpty.hex rename to BootLoaders/Boards/avr/bootloaders/Multi4in1/AtmegaMultiEmpty.hex diff --git a/BootLoaders/Boards/platform.local.txt b/BootLoaders/Boards/avr/platform.local.txt similarity index 100% rename from BootLoaders/Boards/platform.local.txt rename to BootLoaders/Boards/avr/platform.local.txt diff --git a/BootLoaders/Boards/platform.txt b/BootLoaders/Boards/avr/platform.txt similarity index 100% rename from BootLoaders/Boards/platform.txt rename to BootLoaders/Boards/avr/platform.txt diff --git a/BootLoaders/Boards/stm32/boards.txt b/BootLoaders/Boards/stm32/boards.txt new file mode 100644 index 0000000..0163101 --- /dev/null +++ b/BootLoaders/Boards/stm32/boards.txt @@ -0,0 +1,64 @@ +# See: https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification +# See: http://code.google.com/p/arduino/wiki/Platforms + +############################################################## + +menu.upload_method=Upload method +menu.bootloader=Bootloader + +############################################################## +## Multi 4-in-1 STM32 +## -------------------------------------------------- +multistm32f103c.name=Multi 4-in-1 (STM32F103CB) + +multistm32f103c.vid.0=0x1EAF +multistm32f103c.pid.0=0x0004 +multistm32f103c.build.variant=generic_stm32f103c +multistm32f103c.build.vect=VECT_TAB_ADDR=0x8000000 +multistm32f103c.build.core=maple +multistm32f103c.build.board=MULTI_STM32_FLASH_FROM_TX +multistm32f103c.upload.use_1200bps_touch=false +multistm32f103c.upload.file_type=bin +multistm32f103c.upload.auto_reset=true +multistm32f103c.upload.tool=maple_upload +multistm32f103c.upload.protocol=maple_dfu + +multistm32f103c.build.cpu_flags=-DMCU_STM32F103CB +multistm32f103c.build.ldscript=ld/jtag.ld +multistm32f103c.upload.maximum_size=131072 +multistm32f103c.upload.maximum_data_size=20480 + +multistm32f103c.build.f_cpu=72000000L +multistm32f103c.build.flags.optimize=-Os +multistm32f103c.build.flags.ldspecs= + +multistm32f103c.bootloader.tool=serial_upload + +#---------------------------- UPLOAD METHODS --------------------------- + +multistm32f103c.menu.upload_method.TxFlashMethod=Flash from Tx +multistm32f103c.menu.upload_method.TxFlashMethod.upload.tool=tx_upload +multistm32f103c.menu.upload_method.TxFlashMethod.build.upload_flags=-DSERIAL_USB -DGENERIC_BOOTLOADER +multistm32f103c.menu.upload_method.TxFlashMethod.build.vect=VECT_TAB_ADDR=0x8002000 +multistm32f103c.menu.upload_method.TxFlashMethod.build.ldscript=ld/bootloader_20.ld +multistm32f103c.menu.upload_method.TxFlashMethod.build.board=MULTI_STM32_FLASH_FROM_TX +multistm32f103c.menu.upload_method.TxFlashMethod.bootloader.file=Multi4in1/StmMultiBoot.bin + +multistm32f103c.menu.upload_method.DFUUploadMethod=Upload via USB +multistm32f103c.menu.upload_method.DFUUploadMethod.upload.protocol=maple_dfu +multistm32f103c.menu.upload_method.DFUUploadMethod.upload.tool=maple_upload +multistm32f103c.menu.upload_method.DFUUploadMethod.build.upload_flags=-DSERIAL_USB -DGENERIC_BOOTLOADER +multistm32f103c.menu.upload_method.DFUUploadMethod.build.vect=VECT_TAB_ADDR=0x8002000 +multistm32f103c.menu.upload_method.DFUUploadMethod.build.ldscript=ld/bootloader_20.ld +multistm32f103c.menu.upload_method.DFUUploadMethod.build.board=MULTI_STM32_NO_BOOT +multistm32f103c.menu.upload_method.DFUUploadMethod.upload.usbID=1EAF:0003 +multistm32f103c.menu.upload_method.DFUUploadMethod.upload.altID=2 +multistm32f103c.menu.upload_method.DFUUploadMethod.bootloader.file=Multi4in1/StmMultiUSB.bin + +multistm32f103c.menu.upload_method.serialMethod=Upload via Serial (FTDI) +multistm32f103c.menu.upload_method.serialMethod.upload.protocol=maple_serial +multistm32f103c.menu.upload_method.serialMethod.upload.tool=serial_upload +multistm32f103c.menu.upload_method.serialMethod.build.upload_flags=-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG +multistm32f103c.menu.upload_method.serialMethod.build.board=MULTI_STM32_NO_BOOT + +############################################################## diff --git a/BootLoaders/Boards/stm32/bootloaders/Multi4in1/StmMultiBoot.bin b/BootLoaders/Boards/stm32/bootloaders/Multi4in1/StmMultiBoot.bin new file mode 100644 index 0000000..022e373 Binary files /dev/null and b/BootLoaders/Boards/stm32/bootloaders/Multi4in1/StmMultiBoot.bin differ diff --git a/BootLoaders/Boards/stm32/bootloaders/Multi4in1/StmMultiUSB.bin b/BootLoaders/Boards/stm32/bootloaders/Multi4in1/StmMultiUSB.bin new file mode 100644 index 0000000..e8da0d6 Binary files /dev/null and b/BootLoaders/Boards/stm32/bootloaders/Multi4in1/StmMultiUSB.bin differ diff --git a/BootLoaders/Boards/stm32/cores/maple/Arduino.h b/BootLoaders/Boards/stm32/cores/maple/Arduino.h new file mode 100644 index 0000000..63432a1 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/Arduino.h @@ -0,0 +1,44 @@ +/****************************************************************************** + * 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 _WIRISH_WPROGRAM_H_ +#define _WIRISH_WPROGRAM_H_ + +#include "wirish.h" + +void setup(); +void loop(); +#ifdef __cplusplus +extern "C"{ +#endif // __cplusplus +void yield(void); +#ifdef __cplusplus +} +#endif // __cplusplus + +#include "variant.h" + +#endif diff --git a/BootLoaders/Boards/stm32/cores/maple/Client.h b/BootLoaders/Boards/stm32/cores/maple/Client.h new file mode 100644 index 0000000..b8e5d93 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/Client.h @@ -0,0 +1,45 @@ +/* + Client.h - Base class that provides Client + Copyright (c) 2011 Adrian McEwen. All right reserved. + + 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. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef client_h +#define client_h +#include "Print.h" +#include "Stream.h" +#include "IPAddress.h" + +class Client : public Stream { + +public: + virtual int connect(IPAddress ip, uint16_t port) =0; + virtual int connect(const char *host, uint16_t port) =0; + virtual size_t write(uint8_t) =0; + virtual size_t write(const uint8_t *buf, size_t size) =0; + virtual int available() = 0; + virtual int read() = 0; + virtual int read(uint8_t *buf, size_t size) = 0; + virtual int peek() = 0; + virtual void flush() = 0; + virtual void stop() = 0; + virtual uint8_t connected() = 0; + virtual operator bool() = 0; +protected: + uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; +}; + +#endif diff --git a/BootLoaders/Boards/stm32/cores/maple/HardwareSerial.cpp b/BootLoaders/Boards/stm32/cores/maple/HardwareSerial.cpp new file mode 100644 index 0000000..024efbc --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/HardwareSerial.cpp @@ -0,0 +1,200 @@ +/****************************************************************************** + * 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 + * 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/HardwareSerial.cpp + * @brief Wirish serial port implementation. + */ + +#include "HardwareSerial.h" + +#include +#include +#include +#include + +#if 0 + + #define DEFINE_HWSERIAL(name, n) \ + HardwareSerial name(USART##n, \ + BOARD_USART##n##_TX_PIN, \ + BOARD_USART##n##_RX_PIN) + + #define DEFINE_HWSERIAL_UART(name, n) \ + HardwareSerial name(UART##n, \ + BOARD_USART##n##_TX_PIN, \ + BOARD_USART##n##_RX_PIN) + + #ifdef SERIAL_USB + #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_UART(Serial4, 4); + #endif + #if BOARD_HAVE_UART5 + DEFINE_HWSERIAL_UART(Serial5, 5); + #endif + #if BOARD_HAVE_USART6 + DEFINE_HWSERIAL_UART(Serial6, 6); + #endif + #else + #if BOARD_HAVE_USART1 + DEFINE_HWSERIAL(Serial, 1); + #endif + #if BOARD_HAVE_USART2 + DEFINE_HWSERIAL(Serial1, 2); + #endif + #if BOARD_HAVE_USART3 + DEFINE_HWSERIAL(Serial2, 3); + #endif + #if BOARD_HAVE_UART4 + DEFINE_HWSERIAL_UART(Serial3, 4); + #endif + #if BOARD_HAVE_UART5 + DEFINE_HWSERIAL_UART(Serial4, 5); + #endif + #if BOARD_HAVE_USART6 + DEFINE_HWSERIAL_UART(Serial5, 6); + #endif + #endif + +#endif +HardwareSerial::HardwareSerial(usart_dev *usart_device, + uint8 tx_pin, + uint8 rx_pin) { + this->usart_device = usart_device; + this->tx_pin = tx_pin; + this->rx_pin = rx_pin; +} + +/* + * 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 (dev != NULL) { + timer_set_mode(dev, ch, 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 +#warning "Unsupported STM32 series; timer conflicts are possible" +#endif + +void HardwareSerial::begin(uint32 baud) +{ + begin(baud,SERIAL_8N1); +} +/* + * Roger Clark. + * Note. The config parameter is not currently used. This is a work in progress. + * Code needs to be written to set the config of the hardware serial control register in question. + * +*/ + +void HardwareSerial::begin(uint32 baud, uint8_t config) +{ + // ASSERT(baud <= this->usart_device->max_baud);// Roger Clark. Assert doesn't do anything useful, we may as well save the space in flash and ram etc + + if (baud > this->usart_device->max_baud) { + return; + } + + const stm32_pin_info *txi = &PIN_MAP[this->tx_pin]; + const stm32_pin_info *rxi = &PIN_MAP[this->rx_pin]; + + disable_timer_if_necessary(txi->timer_device, txi->timer_channel); + + usart_init(this->usart_device); + usart_config_gpios_async(this->usart_device, + rxi->gpio_device, rxi->gpio_bit, + txi->gpio_device, txi->gpio_bit, + config); + usart_set_baud_rate(this->usart_device, USART_USE_PCLK, baud); + usart_enable(this->usart_device); +} + +void HardwareSerial::end(void) { + usart_disable(this->usart_device); +} + +/* + * I/O + */ + +int HardwareSerial::read(void) { + if(usart_data_available(usart_device) > 0) { + return usart_getc(usart_device); + } else { + return -1; + } +} + +int HardwareSerial::available(void) { + return usart_data_available(this->usart_device); +} + +/* Roger Clark. Added function missing from LibMaple code */ + +int HardwareSerial::peek(void) +{ + return usart_peek(this->usart_device); +} + +int HardwareSerial::availableForWrite(void) +{ +/* Roger Clark. + * Currently there isn't an output ring buffer, chars are sent straight to the hardware. + * so just return 1, meaning that 1 char can be written + * This will be slower than a ring buffer implementation, but it should at least work ! + */ + return 1; +} + +size_t HardwareSerial::write(unsigned char ch) { + + usart_putc(this->usart_device, ch); + return 1; +} + +/* edogaldo: Waits for the transmission of outgoing serial data to complete (Arduino 1.0 api specs) */ +void HardwareSerial::flush(void) { + while(!rb_is_empty(this->usart_device->wb)); // wait for TX buffer empty + while(!((this->usart_device->regs->SR) & (1< + +#include "Print.h" +#include "boards.h" +#include "Stream.h" +/* + * IMPORTANT: + * + * This class documented "by hand" (i.e., not using Doxygen) in the + * leaflabs-docs/ repository. + * + * If you alter the public HardwareSerial interface, you MUST update + * the documentation accordingly. + */ + + + +// Define constants and variables for buffering incoming serial data. We're +// using a ring buffer (I think), in which head is the index of the location +// to which to write the next incoming character and tail is the index of the +// location from which to read. +#if !(defined(SERIAL_TX_BUFFER_SIZE) && defined(SERIAL_RX_BUFFER_SIZE)) +#if (RAMEND < 1000) +#define SERIAL_TX_BUFFER_SIZE 16 +#define SERIAL_RX_BUFFER_SIZE 16 +#else +#define SERIAL_TX_BUFFER_SIZE 64 +#define SERIAL_RX_BUFFER_SIZE 64 +#endif +#endif +#if (SERIAL_TX_BUFFER_SIZE>256) +typedef uint16_t tx_buffer_index_t; +#else +typedef uint8_t tx_buffer_index_t; +#endif +#if (SERIAL_RX_BUFFER_SIZE>256) +typedef uint16_t rx_buffer_index_t; +#else +typedef uint8_t rx_buffer_index_t; +#endif + +struct usart_dev; + +/* Roger Clark + * + * Added config defines from AVR + * Note. The values will need to be changed to match STM32 USART config register values, these are just place holders. + */ +// Define config for Serial.begin(baud, config); +// Note. STM32 doesn't support as many different Serial modes as AVR or SAM cores. +// The word legth bit M must be set when using parity bit. + +#define SERIAL_8N1 0B00000000 +#define SERIAL_8N2 0B00100000 +#define SERIAL_9N1 0B00001000 +#define SERIAL_9N2 0B00101000 + +#define SERIAL_8E1 0B00001010 +#define SERIAL_8E2 0B00101010 +/* not supported: +#define SERIAL_9E1 0B00001010 +#define SERIAL_9E2 0B00101010 +*/ +#define SERIAL_8O1 0B00001011 +#define SERIAL_8O2 0B00101011 +/* not supported: +#define SERIAL_9O1 0B00001011 +#define SERIAL_9O2 0B00101011 +*/ + +/* Roger Clark + * Moved macros from hardwareSerial.cpp + */ + +#define DEFINE_HWSERIAL(name, n) \ + HardwareSerial name(USART##n, \ + BOARD_USART##n##_TX_PIN, \ + BOARD_USART##n##_RX_PIN) + +#define DEFINE_HWSERIAL_UART(name, n) \ + HardwareSerial name(UART##n, \ + BOARD_USART##n##_TX_PIN, \ + BOARD_USART##n##_RX_PIN) + + +/* Roger clark. Changed class inheritance from Print to Stream. + * Also added new functions for peek() and availableForWrite() + * Note. AvailableForWrite is only a stub function in the cpp + */ +class HardwareSerial : public Stream { + +public: + HardwareSerial(struct usart_dev *usart_device, + uint8 tx_pin, + uint8 rx_pin); + + /* Set up/tear down */ + void begin(uint32 baud); + void begin(uint32 baud,uint8_t config); + void end(); + virtual int available(void); + virtual int peek(void); + virtual int read(void); + int availableForWrite(void); + virtual void flush(void); + virtual size_t write(uint8_t); + inline size_t write(unsigned long n) { return write((uint8_t)n); } + inline size_t write(long n) { return write((uint8_t)n); } + inline size_t write(unsigned int n) { return write((uint8_t)n); } + inline size_t write(int n) { return write((uint8_t)n); } + using Print::write; + + /* Pin accessors */ + int txPin(void) { return this->tx_pin; } + int rxPin(void) { return this->rx_pin; } + + operator bool() { return true; } + + /* Escape hatch into libmaple */ + /* FIXME [0.0.13] documentation */ + struct usart_dev* c_dev(void) { return this->usart_device; } +private: + struct usart_dev *usart_device; + uint8 tx_pin; + uint8 rx_pin; + protected: +#if 0 + volatile uint8_t * const _ubrrh; + volatile uint8_t * const _ubrrl; + volatile uint8_t * const _ucsra; + volatile uint8_t * const _ucsrb; + volatile uint8_t * const _ucsrc; + volatile uint8_t * const _udr; + // Has any byte been written to the UART since begin() + bool _written; + + volatile rx_buffer_index_t _rx_buffer_head; + volatile rx_buffer_index_t _rx_buffer_tail; + volatile tx_buffer_index_t _tx_buffer_head; + volatile tx_buffer_index_t _tx_buffer_tail; + // Don't put any members after these buffers, since only the first + // 32 bytes of this struct can be accessed quickly using the ldd + // instruction. + unsigned char _rx_buffer[SERIAL_RX_BUFFER_SIZE]; + unsigned char _tx_buffer[SERIAL_TX_BUFFER_SIZE]; +#endif +}; + +#ifdef SERIAL_USB + #if BOARD_HAVE_USART1 + extern HardwareSerial Serial1; + #endif + #if BOARD_HAVE_USART2 + extern HardwareSerial Serial2; + #endif + #if BOARD_HAVE_USART3 + extern HardwareSerial Serial3; + #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 +#else + #if BOARD_HAVE_USART1 + extern HardwareSerial Serial; + #endif + #if BOARD_HAVE_USART2 + extern HardwareSerial Serial1; + #endif + #if BOARD_HAVE_USART3 + extern HardwareSerial Serial2; + #endif + #if BOARD_HAVE_UART4 + extern HardwareSerial Serial3; + #endif + #if BOARD_HAVE_UART5 + extern HardwareSerial Serial4; + #endif + #if BOARD_HAVE_USART6 + extern HardwareSerial Serial5; + #endif +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/cores/maple/HardwareTimer.cpp b/BootLoaders/Boards/stm32/cores/maple/HardwareTimer.cpp new file mode 100644 index 0000000..abf1e62 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/HardwareTimer.cpp @@ -0,0 +1,192 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Bryan Newbold. + * + * 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 "HardwareTimer.h" + +#include +#include "ext_interrupts.h" // for noInterrupts(), interrupts() +#include "wirish_math.h" +#include // for CYCLES_PER_MICROSECOND + +// TODO [0.1.0] Remove deprecated pieces + +/* + * Evil hack to infer this->dev from timerNum in the HardwareTimer + * constructor. See: + * + * http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.2 + * http://yosefk.com/c++fqa/function.html#fqa-33.2 + */ + +extern "C" { + static timer_dev **this_devp; + static rcc_clk_id this_id; + static void set_this_dev(timer_dev *dev) { + if (dev->clk_id == this_id) { + *this_devp = dev; + } + } +} + +/* + * HardwareTimer routines + */ + +HardwareTimer::HardwareTimer(uint8 timerNum) { + rcc_clk_id timerID = (rcc_clk_id)(RCC_TIMER1 + (timerNum - 1)); + this->dev = NULL; + noInterrupts(); // Hack to ensure we're the only ones using + // set_this_dev() and friends. TODO: use a lock. + this_id = timerID; + this_devp = &this->dev; + timer_foreach(set_this_dev); + interrupts(); + ASSERT(this->dev != NULL); +} + +void HardwareTimer::pause(void) { + timer_pause(this->dev); +} + +void HardwareTimer::resume(void) { + timer_resume(this->dev); +} + +uint32 HardwareTimer::getPrescaleFactor(void) { + return timer_get_prescaler(this->dev) + 1; +} + +void HardwareTimer::setPrescaleFactor(uint32 factor) { + timer_set_prescaler(this->dev, (uint16)(factor - 1)); +} + +uint16 HardwareTimer::getOverflow() { + return timer_get_reload(this->dev); +} + +void HardwareTimer::setOverflow(uint16 val) { + timer_set_reload(this->dev, val); +} + +uint16 HardwareTimer::getCount(void) { + return timer_get_count(this->dev); +} + +void HardwareTimer::setCount(uint16 val) { + uint16 ovf = this->getOverflow(); + timer_set_count(this->dev, min(val, ovf)); +} + +#define MAX_RELOAD ((1 << 16) - 1) +uint16 HardwareTimer::setPeriod(uint32 microseconds) { + // Not the best way to handle this edge case? + if (!microseconds) { + this->setPrescaleFactor(1); + this->setOverflow(1); + return this->getOverflow(); + } + + uint32 period_cyc = microseconds * CYCLES_PER_MICROSECOND; + uint16 prescaler = (uint16)(period_cyc / MAX_RELOAD + 1); + uint16 overflow = (uint16)((period_cyc + (prescaler / 2)) / prescaler); + this->setPrescaleFactor(prescaler); + this->setOverflow(overflow); + return overflow; +} + +void HardwareTimer::setMode(int channel, timer_mode mode) { + timer_set_mode(this->dev, (uint8)channel, (timer_mode)mode); +} + +uint16 HardwareTimer::getCompare(int channel) { + return timer_get_compare(this->dev, (uint8)channel); +} + +void HardwareTimer::setCompare(int channel, uint16 val) { + uint16 ovf = this->getOverflow(); + timer_set_compare(this->dev, (uint8)channel, min(val, ovf)); +} + +void HardwareTimer::attachInterrupt(int channel, voidFuncPtr handler) { + timer_attach_interrupt(this->dev, (uint8)channel, handler); +} + +void HardwareTimer::detachInterrupt(int channel) { + timer_detach_interrupt(this->dev, (uint8)channel); +} + + +void HardwareTimer::enableDMA(int channel) { + timer_dma_enable_req(this->dev, (uint8)channel); +} + +void HardwareTimer::disableDMA(int channel) { + timer_dma_disable_req(this->dev, (uint8)channel); +} + +void HardwareTimer::refresh(void) { + timer_generate_update(this->dev); +} + +void HardwareTimer::setMasterModeTrGo(uint32_t mode) { + this->dev->regs.bas->CR2 &= ~TIMER_CR2_MMS; + this->dev->regs.bas->CR2 |= mode; +} + +/* CARLOS Changes to add encoder mode.*/ + +//direction of movement. (to be better described). + uint8 HardwareTimer::getDirection(){ + return get_direction(this->dev); + } + +//set if the encoder will count edges on one, which or both channels. + void HardwareTimer::setEdgeCounting(uint32 counting) { + (dev->regs).gen->SMCR = counting;//TIMER_SMCR_SMS_ENCODER3; //choose encoder 3, counting on + + } + + uint8 HardwareTimer::getEdgeCounting() { + return (dev->regs).gen->SMCR; + } + + + +//set the polarity of counting... not sure how interesting this is.. + void HardwareTimer::setPolarity(){} + +/* -- Deprecated predefined instances -------------------------------------- */ + +HardwareTimer Timer1(1); +HardwareTimer Timer2(2); +HardwareTimer Timer3(3); +HardwareTimer Timer4(4); +#ifdef STM32_HIGH_DENSITY +HardwareTimer Timer5(5); +HardwareTimer Timer6(6); +HardwareTimer Timer7(7); +HardwareTimer Timer8(8); +#endif diff --git a/BootLoaders/Boards/stm32/cores/maple/HardwareTimer.h b/BootLoaders/Boards/stm32/cores/maple/HardwareTimer.h new file mode 100644 index 0000000..d5356ca --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/HardwareTimer.h @@ -0,0 +1,381 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Bryan Newbold. + * + * 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. + *****************************************************************************/ + +/** + * @brief Wirish timer class. + */ + +#ifndef _WIRISH_HARDWARETIMER_H_ +#define _WIRISH_HARDWARETIMER_H_ + +// TODO [0.1.0] Remove deprecated pieces, pick a better API + +#include + +/** Timer mode. */ +typedef timer_mode TimerMode; + +//CARLOS +//defines for the ENCODER mode. + + +/** + * @brief Interface to one of the 16-bit timer peripherals. + */ +class HardwareTimer { +private: + timer_dev *dev; + +public: + /** + * @brief Construct a new HardwareTimer instance. + * @param timerNum number of the timer to control. + */ + HardwareTimer(uint8 timerNum); + + /** + * @brief Stop the counter, without affecting its configuration. + * + * @see HardwareTimer::resume() + */ + void pause(void); + + /** + * @brief Resume a paused timer, without affecting its configuration. + * + * The timer will resume counting and firing interrupts as + * appropriate. + * + * Note that there is some function call overhead associated with + * using this method, so using it in concert with + * HardwareTimer::pause() is not a robust way to align multiple + * timers to the same count value. + * + * @see HardwareTimer::pause() + */ + void resume(void); + + /** + * @brief Get the timer's prescale factor. + * @return Timer prescaler, from 1 to 65,536. + * @see HardwareTimer::setPrescaleFactor() + */ + uint32 getPrescaleFactor(); + + /** + * @brief Set the timer's prescale factor. + * + * The new value won't take effect until the next time the counter + * overflows. You can force the counter to reset using + * HardwareTimer::refresh(). + * + * @param factor The new prescale value to set, from 1 to 65,536. + * @see HardwareTimer::refresh() + */ + void setPrescaleFactor(uint32 factor); + + /** + * @brief Get the timer overflow value. + * @see HardwareTimer::setOverflow() + */ + uint16 getOverflow(); + + /** + * @brief Set the timer overflow (or "reload") value. + * + * The new value won't take effect until the next time the counter + * overflows. You can force the counter to reset using + * HardwareTimer::refresh(). + * + * @param val The new overflow value to set + * @see HardwareTimer::refresh() + */ + void setOverflow(uint16 val); + + /** + * @brief Get the current timer count. + * + * @return The timer's current count value + */ + uint16 getCount(void); + + /** + * @brief Set the current timer count. + * + * @param val The new count value to set. If this value exceeds + * the timer's overflow value, it is truncated to the + * overflow value. + */ + void setCount(uint16 val); + + /** + * @brief Set the timer's period in microseconds. + * + * Configures the prescaler and overflow values to generate a timer + * reload with a period as close to the given number of + * microseconds as possible. + * + * @param microseconds The desired period of the timer. This must be + * greater than zero. + * @return The new overflow value. + */ + uint16 setPeriod(uint32 microseconds); + + /** + * @brief Configure a timer channel's mode. + * @param channel Timer channel, from 1 to 4 + * @param mode Mode to set + */ + void setMode(int channel, timer_mode mode); + + /** + * @brief Get the compare value for the given channel. + * @see HardwareTimer::setCompare() + */ + uint16 getCompare(int channel); + + /** + * @brief Set the compare value for the given channel. + * + * @param channel the channel whose compare to set, from 1 to 4. + * @param compare The compare value to set. If greater than this + * timer's overflow value, it will be truncated to + * the overflow value. + * + * @see timer_mode + * @see HardwareTimer::setMode() + * @see HardwareTimer::attachInterrupt() + */ + void setCompare(int channel, uint16 compare); + + /** + * @brief Attach an interrupt handler to the given channel. + * + * This interrupt handler will be called when the timer's counter + * reaches the given channel compare value. + * + * @param channel the channel to attach the ISR to, from 1 to 4. + * @param handler The ISR to attach to the given channel. + * @see voidFuncPtr + */ + void attachInterrupt(int channel, voidFuncPtr handler); + + /** + * @brief Remove the interrupt handler attached to the given + * channel, if any. + * + * The handler will no longer be called by this timer. + * + * @param channel the channel whose interrupt to detach, from 1 to 4. + * @see HardwareTimer::attachInterrupt() + */ + void detachInterrupt(int channel); + + /** + * @brief Reset the counter, and update the prescaler and overflow + * values. + * + * This will reset the counter to 0 in upcounting mode (the + * default). It will also update the timer's prescaler and + * overflow, if you have set them up to be changed using + * HardwareTimer::setPrescaleFactor() or + * HardwareTimer::setOverflow(). + * + * @see HardwareTimer::setPrescaleFactor() + * @see HardwareTimer::setOverflow() + */ + void refresh(void); + + // SYFRE + /** + * @brief Set the Master mode TRGO signal + * These bits allow to select the information to be sent in master mode to slave timers for + * synchronization (TRGO). + * mode: + * TIMER_CR2_MMS_RESET + * TIMER_CR2_MMS_ENABLE + * TIMER_CR2_MMS_UPDATE + * TIMER_CR2_MMS_COMPARE_PULSE + * TIMER_CR2_MMS_COMPARE_OC1REF + * TIMER_CR2_MMS_COMPARE_OC2REF + * TIMER_CR2_MMS_COMPARE_OC3REF + * TIMER_CR2_MMS_COMPARE_OC4REF + */ + void setMasterModeTrGo(uint32_t mode); + +//CARLOS. +/* + added these functions to make sense for the encoder mode. +*/ +//direction of movement. (to be better described). + uint8 getDirection(); + +//set if the encoder will count edges on one, which or both channels. + void setEdgeCounting(uint32 counting); + uint8 getEdgeCounting(); //not sure if needed. + +//set the polarity of counting... not sure how interesting this is.. + void setPolarity(); + +//add the filtering definition for the input channel. + + + /* Escape hatch */ + + /** + * @brief Enable/disable DMA request for the input channel. + */ + void enableDMA(int channel); + void disableDMA(int channel); + + /** + * @brief Get a pointer to the underlying libmaple timer_dev for + * this HardwareTimer instance. + */ + timer_dev* c_dev(void) { return this->dev; } + +/* -- The rest of this file is deprecated. --------------------------------- */ + + /** @brief Deprecated; use setMode(channel, mode) instead. */ + void setChannelMode(int channel, timer_mode mode) { + setMode(channel, mode); + } + + /** @brief Deprecated; use setMode(TIMER_CH1, mode) instead. */ + void setChannel1Mode(timer_mode mode) { setMode(TIMER_CH1, mode); } + + /** @brief Deprecated; use setMode(TIMER_CH2, mode) instead. */ + void setChannel2Mode(timer_mode mode) { setMode(TIMER_CH2, mode); } + + /** @brief Deprecated; use setMode(TIMER_CH3, mode) instead. */ + void setChannel3Mode(timer_mode mode) { setMode(TIMER_CH3, mode); } + + /** @brief Deprecated; use setMode(TIMER_CH4, mode) instead. */ + void setChannel4Mode(timer_mode mode) { setMode(TIMER_CH4, mode); } + + /** @brief Deprecated; use return getCompare(TIMER_CH1) instead. */ + uint16 getCompare1() { return getCompare(TIMER_CH1); } + + /** @brief Deprecated; use return getCompare(TIMER_CH2) instead. */ + uint16 getCompare2() { return getCompare(TIMER_CH2); } + + /** @brief Deprecated; use return getCompare(TIMER_CH3) instead. */ + uint16 getCompare3() { return getCompare(TIMER_CH3); } + + /** @brief Deprecated; use return getCompare(TIMER_CH4) instead. */ + uint16 getCompare4() { return getCompare(TIMER_CH4); } + + /** @brief Deprecated; use setCompare(TIMER_CH1, compare) instead. */ + void setCompare1(uint16 compare) { setCompare(TIMER_CH1, compare); } + + /** @brief Deprecated; use setCompare(TIMER_CH2, compare) instead. */ + void setCompare2(uint16 compare) { setCompare(TIMER_CH2, compare); } + + /** @brief Deprecated; use setCompare(TIMER_CH3, compare) instead. */ + void setCompare3(uint16 compare) { setCompare(TIMER_CH3, compare); } + + /** @brief Deprecated; use setCompare(TIMER_CH4, compare) instead. */ + void setCompare4(uint16 compare) { setCompare(TIMER_CH4, compare); } + + /** @brief Deprecated; use attachInterrupt(TIMER_CH1, handler) instead. */ + void attachCompare1Interrupt(voidFuncPtr handler) { + attachInterrupt(TIMER_CH1, handler); + } + + /** @brief Deprecated; use attachInterrupt(TIMER_CH2, handler) instead. */ + void attachCompare2Interrupt(voidFuncPtr handler) { + attachInterrupt(TIMER_CH2, handler); + } + + /** @brief Deprecated; use attachInterrupt(TIMER_CH3, handler) instead. */ + void attachCompare3Interrupt(voidFuncPtr handler) { + attachInterrupt(TIMER_CH3, handler); + } + + /** @brief Deprecated; use attachInterrupt(TIMER_CH4, handler) instead. */ + void attachCompare4Interrupt(voidFuncPtr handler) { + attachInterrupt(TIMER_CH4, handler); + } + + /** @brief Deprecated; use detachInterrupt(TIMER_CH1) instead. */ + void detachCompare1Interrupt(void) { detachInterrupt(TIMER_CH1); } + + /** @brief Deprecated; use detachInterrupt(TIMER_CH2) instead. */ + void detachCompare2Interrupt(void) { detachInterrupt(TIMER_CH2); } + + /** @brief Deprecated; use detachInterrupt(TIMER_CH3) instead. */ + void detachCompare3Interrupt(void) { detachInterrupt(TIMER_CH3); } + + /** @brief Deprecated; use detachInterrupt(TIMER_CH4) instead. */ + void detachCompare4Interrupt(void) { detachInterrupt(TIMER_CH4); } + + /** @brief Deprecated; use refresh() instead. */ + void generateUpdate(void) { refresh(); } +}; + +/** @brief Deprecated; use TIMER_OUTPUT_COMPARE instead. */ +#define TIMER_OUTPUTCOMPARE TIMER_OUTPUT_COMPARE + +/** + * @brief Deprecated. + * + * Pre-instantiated timer. + */ +extern HardwareTimer Timer1; +/** + * @brief Deprecated. + * + * Pre-instantiated timer. + */ +extern HardwareTimer Timer2; +/** + * @brief Deprecated. + * + * Pre-instantiated timer. + */ +extern HardwareTimer Timer3; +/** + * @brief Deprecated. + * + * Pre-instantiated timer. + */ +extern HardwareTimer Timer4; +#if (STM32_MCU_SERIES == STM32_SERIES_F1) && defined(STM32_HIGH_DENSITY) +/** + * @brief Deprecated. + * + * Pre-instantiated timer. + */ +extern HardwareTimer Timer5; +/** + * @brief Deprecated. + * + * Pre-instantiated timer. + */ +extern HardwareTimer Timer8; +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/cores/maple/IPAddress.cpp b/BootLoaders/Boards/stm32/cores/maple/IPAddress.cpp new file mode 100644 index 0000000..297307e --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/IPAddress.cpp @@ -0,0 +1,129 @@ +/* + IPAddress.cpp - Base class that provides IPAddress + Copyright (c) 2011 Adrian McEwen. All right reserved. + + 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. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#include + +IPAddress::IPAddress() +{ + _address.dword = 0; +} + +IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) +{ + _address.bytes[0] = first_octet; + _address.bytes[1] = second_octet; + _address.bytes[2] = third_octet; + _address.bytes[3] = fourth_octet; +} + +IPAddress::IPAddress(uint32_t address) +{ + _address.dword = address; +} + +IPAddress::IPAddress(const uint8_t *address) +{ + memcpy(_address.bytes, address, sizeof(_address.bytes)); +} + +bool IPAddress::fromString(const char *address) +{ + // TODO: add support for "a", "a.b", "a.b.c" formats + + uint16_t acc = 0; // Accumulator + uint8_t dots = 0; + + while (*address) + { + char c = *address++; + if (c >= '0' && c <= '9') + { + acc = acc * 10 + (c - '0'); + if (acc > 255) { + // Value out of [0..255] range + return false; + } + } + else if (c == '.') + { + if (dots == 3) { + // Too much dots (there must be 3 dots) + return false; + } + _address.bytes[dots++] = acc; + acc = 0; + } + else + { + // Invalid char + return false; + } + } + + if (dots != 3) { + // Too few dots (there must be 3 dots) + return false; + } + _address.bytes[3] = acc; + return true; +} + +IPAddress& IPAddress::operator=(const uint8_t *address) +{ + memcpy(_address.bytes, address, sizeof(_address.bytes)); + return *this; +} + +IPAddress& IPAddress::operator=(uint32_t address) +{ + _address.dword = address; + return *this; +} + +bool IPAddress::operator==(const uint8_t* addr) const +{ + return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0; +} + +size_t IPAddress::printTo(Print& p) const +{ + size_t n = 0; + for (int i =0; i < 3; i++) + { + n += p.print(_address.bytes[i], DEC); + n += p.print('.'); + } + n += p.print(_address.bytes[3], DEC); + return n; +} + +String IPAddress::toString() +{ + String str = String(_address.bytes[0]); + str += "."; + str += String(_address.bytes[1]); + str += "."; + str += String(_address.bytes[2]); + str += "."; + str += String(_address.bytes[3]); + return str; +} + diff --git a/BootLoaders/Boards/stm32/cores/maple/IPAddress.h b/BootLoaders/Boards/stm32/cores/maple/IPAddress.h new file mode 100644 index 0000000..271b240 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/IPAddress.h @@ -0,0 +1,80 @@ +/* + IPAddress.h - Base class that provides IPAddress + Copyright (c) 2011 Adrian McEwen. All right reserved. + + 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. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef IPAddress_h +#define IPAddress_h + +#include +#include +#include + +// A class to make it easier to handle and pass around IP addresses + +class IPAddress : public Printable { +private: + union { + uint8_t bytes[4]; // IPv4 address + uint32_t dword; + } _address; + + // Access the raw byte array containing the address. Because this returns a pointer + // to the internal structure rather than a copy of the address this function should only + // be used when you know that the usage of the returned uint8_t* will be transient and not + // stored. + uint8_t* raw_address() { return _address.bytes; }; + +public: + // Constructors + IPAddress(); + IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet); + IPAddress(uint32_t address); + IPAddress(const uint8_t *address); + + bool fromString(const char *address); + bool fromString(const String &address) { return fromString(address.c_str()); } + + // Overloaded cast operator to allow IPAddress objects to be used where a pointer + // to a four-byte uint8_t array is expected + operator uint32_t() const { return _address.dword; }; + bool operator==(const IPAddress& addr) const { return _address.dword == addr._address.dword; }; + bool operator==(const uint8_t* addr) const; + + // Overloaded index operator to allow getting and setting individual octets of the address + uint8_t operator[](int index) const { return _address.bytes[index]; }; + uint8_t& operator[](int index) { return _address.bytes[index]; }; + + // Overloaded copy operators to allow initialisation of IPAddress objects from other types + IPAddress& operator=(const uint8_t *address); + IPAddress& operator=(uint32_t address); + + virtual size_t printTo(Print& p) const; + String toString(); + + friend class EthernetClass; + friend class UDP; + friend class Client; + friend class Server; + friend class DhcpClass; + friend class DNSClient; +}; + +const IPAddress INADDR_NONE(0,0,0,0); + + +#endif diff --git a/BootLoaders/Boards/stm32/cores/maple/Print.cpp b/BootLoaders/Boards/stm32/cores/maple/Print.cpp new file mode 100644 index 0000000..0a71cf0 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/Print.cpp @@ -0,0 +1,322 @@ +/* + * Print.cpp - Base class that provides print() and println() + * Copyright (c) 2008 David A. Mellis. All right reserved. + * Copyright (c) 2011 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. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + * Modified 23 November 2006 by David A. Mellis + * Modified 12 April 2011 by Marti Bolivar + */ + +#include "Print.h" + +#include "wirish_math.h" +#include "limits.h" + +#ifndef LLONG_MAX +/* + * Note: + * + * At time of writing (12 April 2011), the limits.h that came with the + * newlib we distributed didn't include LLONG_MAX. Because we're + * staying away from using templates (see /notes/coding_standard.rst, + * "Language Features and Compiler Extensions"), this value was + * copy-pasted from a println() of the value + * + * std::numeric_limits::max(). + */ +#define LLONG_MAX 9223372036854775807LL +#endif + +/* + * Public methods + */ + +size_t Print::write(const char *str) { + size_t n = 0; + while (*str) { + write(*str++); + n++; + } + return n; +} + +size_t Print::write(const void *buffer, uint32 size) { + size_t n = 0; + uint8 *ch = (uint8*)buffer; + while (size--) { + write(*ch++); + n++; + } + return n; +} + +size_t Print::print(uint8 b, int base) { + return print((uint64)b, base); +} + +size_t Print::print(const String &s) +{ + return write(s.c_str(), s.length()); +} + +size_t Print::print(char c) { + return write(c); +} + +size_t Print::print(const char str[]) { + return write(str); +} + +size_t Print::print(int n, int base) { + return print((long long)n, base); +} + +size_t Print::print(unsigned int n, int base) { + return print((unsigned long long)n, base); +} + +size_t Print::print(long n, int base) { + return print((long long)n, base); +} + +size_t Print::print(unsigned long n, int base) { + return print((unsigned long long)n, base); +} + +size_t Print::print(long long n, int base) { + if (n < 0) { + print('-'); + n = -n; + } + return printNumber(n, base); +} + +size_t Print::print(unsigned long long n, int base) { + return printNumber(n, base); +} + +size_t Print::print(double n, int digits) { + return printFloat(n, digits); +} + +size_t Print::print(const __FlashStringHelper *ifsh) +{ + return print(reinterpret_cast(ifsh)); +} + +size_t Print::print(const Printable& x) +{ + return x.printTo(*this); +} + +size_t Print::println(void) +{ + size_t n = print('\r'); + n += print('\n'); + return n; +} + +size_t Print::println(const String &s) +{ + size_t n = print(s); + n += println(); + return n; +} + +size_t Print::println(char c) { + size_t n = print(c); + n += println(); + return n; +} + +size_t Print::println(const char c[]) { + size_t n = print(c); + n += println(); + return n; +} + +size_t Print::println(uint8 b, int base) { + size_t n = print(b, base); + n += println(); + return n; +} + +size_t Print::println(int n, int base) { + size_t s = print(n, base); + s += println(); + return s; +} + +size_t Print::println(unsigned int n, int base) { + size_t s = print(n, base); + s += println(); + return s; +} + +size_t Print::println(long n, int base) { + size_t s = print((long long)n, base); + s += println(); + return s; +} + +size_t Print::println(unsigned long n, int base) { + size_t s = print((unsigned long long)n, base); + s += println(); + return s; +} + +size_t Print::println(long long n, int base) { + size_t s = print(n, base); + s += println(); + return s; +} + +size_t Print::println(unsigned long long n, int base) { + size_t s = print(n, base); + s += println(); + return s; +} + +size_t Print::println(double n, int digits) { + size_t s = print(n, digits); + s += println(); + return s; +} + +size_t Print::println(const __FlashStringHelper *ifsh) +{ + size_t n = print(ifsh); + n += println(); + return n; +} + +size_t Print::println(const Printable& x) +{ + size_t n = print(x); + n += println(); + return n; +} + +#ifdef SUPPORTS_PRINTF +#include +#include +// Work in progress to support printf. +// Need to implement stream FILE to write individual chars to chosen serial port +int Print::printf (__const char *__restrict __format, ...) + { +FILE *__restrict __stream; + int ret_status = 0; + + + va_list args; + va_start(args,__format); + ret_status = vfprintf(__stream, __format, args); + va_end(args); + return ret_status; + } + #endif + +/* + * Private methods + */ + +size_t Print::printNumber(unsigned long long n, uint8 base) { + unsigned char buf[CHAR_BIT * sizeof(long long)]; + unsigned long i = 0; + size_t s=0; + if (n == 0) { + print('0'); + return 1; + } + + while (n > 0) { + buf[i++] = n % base; + n /= base; + } + + for (; i > 0; i--) { + s += print((char)(buf[i - 1] < 10 ? + '0' + buf[i - 1] : + 'A' + buf[i - 1] - 10)); + } + return s; +} + + +/* According to snprintf(), + * + * nextafter((double)numeric_limits::max(), 0.0) ~= 9.22337e+18 + * + * This slightly smaller value was picked semi-arbitrarily. */ +#define LARGE_DOUBLE_TRESHOLD (9.1e18) + +/* THIS FUNCTION SHOULDN'T BE USED IF YOU NEED ACCURATE RESULTS. + * + * This implementation is meant to be simple and not occupy too much + * code size. However, printing floating point values accurately is a + * subtle task, best left to a well-tested library function. + * + * See Steele and White 2003 for more details: + * + * http://kurtstephens.com/files/p372-steele.pdf + */ +size_t Print::printFloat(double number, uint8 digits) { +size_t s=0; + // Hackish fail-fast behavior for large-magnitude doubles + if (abs(number) >= LARGE_DOUBLE_TRESHOLD) { + if (number < 0.0) { + s=print('-'); + } + s+=print(""); + return s; + } + + // Handle negative numbers + if (number < 0.0) { + s+=print('-'); + number = -number; + } + + // Simplistic rounding strategy so that e.g. print(1.999, 2) + // prints as "2.00" + double rounding = 0.5; + for (uint8 i = 0; i < digits; i++) { + rounding /= 10.0; + } + number += rounding; + + // Extract the integer part of the number and print it + long long int_part = (long long)number; + double remainder = number - int_part; + s+=print(int_part); + + // Print the decimal point, but only if there are digits beyond + if (digits > 0) { + s+=print("."); + } + + // Extract digits from the remainder one at a time + while (digits-- > 0) { + remainder *= 10.0; + int to_print = (int)remainder; + s+=print(to_print); + remainder -= to_print; + } + return s; +} + diff --git a/BootLoaders/Boards/stm32/cores/maple/Print.h b/BootLoaders/Boards/stm32/cores/maple/Print.h new file mode 100644 index 0000000..f265fac --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/Print.h @@ -0,0 +1,88 @@ +/* + * Print.h - Base class that provides print() and println() + * Copyright (c) 2008 David A. Mellis. All right reserved. + * + * 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. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA. + * + * Modified 12 April 2011 by Marti Bolivar + */ + +#ifndef _WIRISH_PRINT_H_ +#define _WIRISH_PRINT_H_ + +#include +#include "WString.h" +#include "Printable.h" + +enum { + BIN = 2, + OCT = 8, + DEC = 10, + HEX = 16 +}; + +class Print { +public: + virtual size_t write(uint8 ch) = 0; + virtual size_t write(const char *str); + virtual size_t write(const void *buf, uint32 len); + + size_t print(const String &); + size_t print(char); + size_t print(const char[]); + size_t print(uint8, int=DEC); + size_t print(int, int=DEC); + size_t print(unsigned int, int=DEC); + size_t print(long, int=DEC); + size_t print(unsigned long, int=DEC); + size_t print(long long, int=DEC); + size_t print(unsigned long long, int=DEC); + size_t print(double, int=2); + size_t print(const __FlashStringHelper *); + size_t print(const Printable&); + size_t println(void); + size_t println(const String &s); + size_t println(char); + size_t println(const char[]); + size_t println(uint8, int=DEC); + size_t println(int, int=DEC); + size_t println(unsigned int, int=DEC); + size_t println(long, int=DEC); + size_t println(unsigned long, int=DEC); + size_t println(long long, int=DEC); + size_t println(unsigned long long, int=DEC); + size_t println(double, int=2); + size_t println(const __FlashStringHelper *); + size_t println(const Printable&); +#ifdef SUPPORTS_PRINTF +// Roger Clark. Work in progress to add printf support + int printf(const char * format, ...); +#endif + Print() : write_error(0) {} + + int getWriteError() { return write_error; } + void clearWriteError() { setWriteError(0); } + + protected: + void setWriteError(int err = 1) { write_error = err; } + +private: + int write_error; + size_t printNumber(unsigned long long, uint8); + size_t printFloat(double, uint8); +}; + +#endif diff --git a/BootLoaders/Boards/stm32/cores/maple/Printable.h b/BootLoaders/Boards/stm32/cores/maple/Printable.h new file mode 100644 index 0000000..2a1b2e9 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/Printable.h @@ -0,0 +1,40 @@ +/* + Printable.h - Interface class that allows printing of complex types + Copyright (c) 2011 Adrian McEwen. All right reserved. + + 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. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef Printable_h +#define Printable_h + +#include + +class Print; + +/** The Printable class provides a way for new classes to allow themselves to be printed. + By deriving from Printable and implementing the printTo method, it will then be possible + for users to print out instances of this class by passing them into the usual + Print::print and Print::println methods. +*/ + +class Printable +{ + public: + virtual size_t printTo(Print& p) const = 0; +}; + +#endif + diff --git a/BootLoaders/Boards/stm32/cores/maple/Server.h b/BootLoaders/Boards/stm32/cores/maple/Server.h new file mode 100644 index 0000000..69e3e39 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/Server.h @@ -0,0 +1,30 @@ +/* + Server.h - Base class that provides Server + Copyright (c) 2011 Adrian McEwen. All right reserved. + + 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. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef server_h +#define server_h + +#include "Print.h" + +class Server : public Print { +public: + virtual void begin() =0; +}; + +#endif diff --git a/BootLoaders/Boards/stm32/cores/maple/Stream.cpp b/BootLoaders/Boards/stm32/cores/maple/Stream.cpp new file mode 100644 index 0000000..991fa87 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/Stream.cpp @@ -0,0 +1,335 @@ +/* + Stream.cpp - adds parsing methods to Stream class + Copyright (c) 2008 David A. Mellis. All right reserved. + + 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. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Created July 2011 + parsing functions based on TextFinder library by Michael Margolis + */ + +#include "Arduino.h" +#include "Stream.h" + +#define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait +#define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field + +// private method to read stream with timeout +int Stream::timedRead() +{ + int c; + _startMillis = millis(); + do { + c = read(); + if (c >= 0) return c; + } while(millis() - _startMillis < _timeout); + return -1; // -1 indicates timeout +} + +// private method to peek stream with timeout +int Stream::timedPeek() +{ + int c; + _startMillis = millis(); + do { + c = peek(); + if (c >= 0) return c; + } while(millis() - _startMillis < _timeout); + return -1; // -1 indicates timeout +} + +// returns peek of the next digit in the stream or -1 if timeout +// discards non-numeric characters +int Stream::peekNextDigit() +{ + int c; + while (1) { + c = timedPeek(); + if (c < 0) return c; // timeout + if (c == '-') return c; + if (c >= '0' && c <= '9') return c; + read(); // discard non-numeric + } +} + +// Public Methods +////////////////////////////////////////////////////////////// + +void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait +{ + _timeout = timeout; +} + + // find returns true if the target string is found +bool Stream::find(char *target) +{ + return findUntil(target, (char*)""); +} + +// reads data from the stream until the target string of given length is found +// returns true if target string is found, false if timed out +bool Stream::find(char *target, size_t length) +{ + return findUntil(target, length, NULL, 0); +} + +// as find but search ends if the terminator string is found +bool Stream::findUntil(char *target, char *terminator) +{ + return findUntil(target, strlen(target), terminator, strlen(terminator)); +} + +// reads data from the stream until the target string of the given length is found +// search terminated if the terminator string is found +// returns true if target string is found, false if terminated or timed out +bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t termLen) +{ + size_t index = 0; // maximum target string length is 64k bytes! + size_t termIndex = 0; + int c; + + if( *target == 0) + return true; // return true if target is a null string + while( (c = timedRead()) > 0){ + + if(c != target[index]) + index = 0; // reset index if any char does not match + + if( c == target[index]){ + //////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1); + if(++index >= targetLen){ // return true if all chars in the target match + return true; + } + } + + if(termLen > 0 && c == terminator[termIndex]){ + if(++termIndex >= termLen) + return false; // return false if terminate string found before target string + } + else + termIndex = 0; + } + return false; +} + + +// returns the first valid (long) integer value from the current position. +// initial characters that are not digits (or the minus sign) are skipped +// function is terminated by the first character that is not a digit. +long Stream::parseInt() +{ + return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout) +} + +// as above but a given skipChar is ignored +// this allows format characters (typically commas) in values to be ignored +long Stream::parseInt(char skipChar) +{ + boolean isNegative = false; + long value = 0; + int c; + + c = peekNextDigit(); + // ignore non numeric leading characters + if(c < 0) + return 0; // zero returned if timeout + + do{ + if(c == skipChar) + ; // ignore this charactor + else if(c == '-') + isNegative = true; + else if(c >= '0' && c <= '9') // is c a digit? + value = value * 10 + c - '0'; + read(); // consume the character we got with peek + c = timedPeek(); + } + while( (c >= '0' && c <= '9') || c == skipChar ); + + if(isNegative) + value = -value; + return value; +} + + +// as parseInt but returns a floating point value +float Stream::parseFloat() +{ + return parseFloat(NO_SKIP_CHAR); +} + +// as above but the given skipChar is ignored +// this allows format characters (typically commas) in values to be ignored +float Stream::parseFloat(char skipChar){ + boolean isNegative = false; + boolean isFraction = false; + long value = 0; + int c; + float fraction = 1.0; + + c = peekNextDigit(); + // ignore non numeric leading characters + if(c < 0) + return 0; // zero returned if timeout + + do{ + if(c == skipChar) + ; // ignore + else if(c == '-') + isNegative = true; + else if (c == '.') + isFraction = true; + else if(c >= '0' && c <= '9') { // is c a digit? + value = value * 10 + c - '0'; + if(isFraction) + fraction *= 0.1; + } + read(); // consume the character we got with peek + c = timedPeek(); + } + while( (c >= '0' && c <= '9') || c == '.' || c == skipChar ); + + if(isNegative) + value = -value; + if(isFraction) + return value * fraction; + else + return value; +} + +// read characters from stream into buffer +// terminates if length characters have been read, or timeout (see setTimeout) +// returns the number of characters placed in the buffer +// the buffer is NOT null terminated. +// +size_t Stream::readBytes(char *buffer, size_t length) +{ + size_t count = 0; + while (count < length) { + int c = timedRead(); + if (c < 0) break; + *buffer++ = (char)c; + count++; + } + return count; +} + + +// as readBytes with terminator character +// terminates if length characters have been read, timeout, or if the terminator character detected +// returns the number of characters placed in the buffer (0 means no valid data found) + +size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length) +{ + if (length < 1) return 0; + size_t index = 0; + while (index < length) { + int c = timedRead(); + if (c < 0 || c == terminator) break; + *buffer++ = (char)c; + index++; + } + return index; // return number of characters, not including null terminator +} + +String Stream::readString() +{ + String ret; + int c = timedRead(); + while (c >= 0) + { + ret += (char)c; + c = timedRead(); + } + return ret; +} + +String Stream::readStringUntil(char terminator) +{ + String ret; + int c = timedRead(); + while (c >= 0 && c != terminator) + { + ret += (char)c; + c = timedRead(); + } + return ret; +} + + +int Stream::findMulti( struct Stream::MultiTarget *targets, int tCount) { + // any zero length target string automatically matches and would make + // a mess of the rest of the algorithm. + for (struct MultiTarget *t = targets; t < targets+tCount; ++t) { + if (t->len <= 0) + return t - targets; + } + + while (1) { + int c = timedRead(); + if (c < 0) + return -1; + + for (struct MultiTarget *t = targets; t < targets+tCount; ++t) { + // the simple case is if we match, deal with that first. + if (c == t->str[t->index]) { + if (++t->index == t->len) + return t - targets; + else + continue; + } + + // if not we need to walk back and see if we could have matched further + // down the stream (ie '1112' doesn't match the first position in '11112' + // but it will match the second position so we can't just reset the current + // index to 0 when we find a mismatch. + if (t->index == 0) + continue; + + int origIndex = t->index; + do { + --t->index; + // first check if current char works against the new current index + if (c != t->str[t->index]) + continue; + + // if it's the only char then we're good, nothing more to check + if (t->index == 0) { + t->index++; + break; + } + + // otherwise we need to check the rest of the found string + int diff = origIndex - t->index; + size_t i; + for (i = 0; i < t->index; ++i) { + if (t->str[i] != t->str[i + diff]) + break; + } + + // if we successfully got through the previous loop then our current + // index is good. + if (i == t->index) { + t->index++; + break; + } + + // otherwise we just try the next index + } while (t->index); + } + } + // unreachable + return -1; +} diff --git a/BootLoaders/Boards/stm32/cores/maple/Stream.h b/BootLoaders/Boards/stm32/cores/maple/Stream.h new file mode 100644 index 0000000..abdcd17 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/Stream.h @@ -0,0 +1,115 @@ +/* + Stream.h - base class for character-based streams. + Copyright (c) 2010 David A. Mellis. All right reserved. + + 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. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + parsing functions based on TextFinder library by Michael Margolis +*/ + +#ifndef Stream_h +#define Stream_h + +#include +#include "Print.h" + +// compatability macros for testing +/* +#define getInt() parseInt() +#define getInt(skipChar) parseInt(skipchar) +#define getFloat() parseFloat() +#define getFloat(skipChar) parseFloat(skipChar) +#define getString( pre_string, post_string, buffer, length) +readBytesBetween( pre_string, terminator, buffer, length) +*/ + +class Stream : public Print +{ + protected: + unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read + unsigned long _startMillis; // used for timeout measurement + int timedRead(); // private method to read stream with timeout + int timedPeek(); // private method to peek stream with timeout + int peekNextDigit(); // returns the next numeric digit in the stream or -1 if timeout + + public: + virtual int available() = 0; + virtual int read() = 0; + virtual int peek() = 0; + virtual void flush() = 0; + + Stream() {_timeout=1000;} + +// parsing methods + + void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second + unsigned long getTimeout(void) { return _timeout; } + + bool find(char *target); // reads data from the stream until the target string is found + bool find(uint8_t *target) { return find ((char *)target); } + // returns true if target string is found, false if timed out (see setTimeout) + + bool find(char *target, size_t length); // reads data from the stream until the target string of given length is found + bool find(uint8_t *target, size_t length) { return find ((char *)target, length); } + // returns true if target string is found, false if timed out + + bool find(char target) { return find (&target, 1); } + + bool findUntil(char *target, char *terminator); // as find but search ends if the terminator string is found + bool findUntil(uint8_t *target, char *terminator) { return findUntil((char *)target, terminator); } + + bool findUntil(char *target, size_t targetLen, char *terminate, size_t termLen); // as above but search ends if the terminate string is found + bool findUntil(uint8_t *target, size_t targetLen, char *terminate, size_t termLen) {return findUntil((char *)target, targetLen, terminate, termLen); } + + + long parseInt(); // returns the first valid (long) integer value from the current position. + // initial characters that are not digits (or the minus sign) are skipped + // integer is terminated by the first character that is not a digit. + + float parseFloat(); // float version of parseInt + + size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer + size_t readBytes( uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); } + // terminates if length characters have been read or timeout (see setTimeout) + // returns the number of characters placed in the buffer (0 means no valid data found) + + size_t readBytesUntil( char terminator, char *buffer, size_t length); // as readBytes with terminator character + size_t readBytesUntil( char terminator, uint8_t *buffer, size_t length) { return readBytesUntil(terminator, (char *)buffer, length); } + // terminates if length characters have been read, timeout, or if the terminator character detected + // returns the number of characters placed in the buffer (0 means no valid data found) + + // Arduino String functions to be added here + String readString(); + String readStringUntil(char terminator); + + protected: + long parseInt(char skipChar); // as above but the given skipChar is ignored + // as above but the given skipChar is ignored + // this allows format characters (typically commas) in values to be ignored + + float parseFloat(char skipChar); // as above but the given skipChar is ignored + + struct MultiTarget { + const char *str; // string you're searching for + size_t len; // length of string you're searching for + size_t index; // index used by the search routine. + }; + + // This allows you to search for an arbitrary number of strings. + // Returns index of the target that is found first or -1 if timeout occurs. + int findMulti(struct MultiTarget *targets, int tCount); +}; + +#endif diff --git a/BootLoaders/Boards/stm32/cores/maple/Udp.h b/BootLoaders/Boards/stm32/cores/maple/Udp.h new file mode 100644 index 0000000..dc5644b --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/Udp.h @@ -0,0 +1,88 @@ +/* + * Udp.cpp: Library to send/receive UDP packets. + * + * NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these) + * 1) UDP does not guarantee the order in which assembled UDP packets are received. This + * might not happen often in practice, but in larger network topologies, a UDP + * packet can be received out of sequence. + * 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being + * aware of it. Again, this may not be a concern in practice on small local networks. + * For more information, see http://www.cafeaulait.org/course/week12/35.html + * + * MIT License: + * Copyright (c) 2008 Bjoern Hartmann + * 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. + * + * bjoern@cs.stanford.edu 12/30/2008 + */ + +#ifndef udp_h +#define udp_h + +#include +#include + +class UDP : public Stream { + +public: + virtual uint8_t begin(uint16_t) =0; // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use + virtual void stop() =0; // Finish with the UDP socket + + // Sending UDP packets + + // Start building up a packet to send to the remote host specific in ip and port + // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port + virtual int beginPacket(IPAddress ip, uint16_t port) =0; + // Start building up a packet to send to the remote host specific in host and port + // Returns 1 if successful, 0 if there was a problem resolving the hostname or port + virtual int beginPacket(const char *host, uint16_t port) =0; + // Finish off this packet and send it + // Returns 1 if the packet was sent successfully, 0 if there was an error + virtual int endPacket() =0; + // Write a single byte into the packet + virtual size_t write(uint8_t) =0; + // Write size bytes from buffer into the packet + virtual size_t write(const uint8_t *buffer, size_t size) =0; + + // Start processing the next available incoming packet + // Returns the size of the packet in bytes, or 0 if no packets are available + virtual int parsePacket() =0; + // Number of bytes remaining in the current packet + virtual int available() =0; + // Read a single byte from the current packet + virtual int read() =0; + // Read up to len bytes from the current packet and place them into buffer + // Returns the number of bytes read, or 0 if none are available + virtual int read(unsigned char* buffer, size_t len) =0; + // Read up to len characters from the current packet and place them into buffer + // Returns the number of characters read, or 0 if none are available + virtual int read(char* buffer, size_t len) =0; + // Return the next byte from the current packet without moving on to the next byte + virtual int peek() =0; + virtual void flush() =0; // Finish reading the current packet + + // Return the IP address of the host who sent the current incoming packet + virtual IPAddress remoteIP() =0; + // Return the port of the host who sent the current incoming packet + virtual uint16_t remotePort() =0; +protected: + uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; +}; + +#endif diff --git a/BootLoaders/Boards/stm32/cores/maple/WCharacter.h b/BootLoaders/Boards/stm32/cores/maple/WCharacter.h new file mode 100644 index 0000000..e84b348 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/WCharacter.h @@ -0,0 +1,180 @@ +/* + WCharacter.h - Character utility functions for Wiring & Arduino + Copyright (c) 2010 Hernando Barragan. All right reserved. + + 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. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef Character_h +#define Character_h + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// WCharacter.h prototypes +#if defined ( __GNUC__ ) +inline boolean isAlphaNumeric(int c) __attribute__((always_inline)); +inline boolean isAlpha(int c) __attribute__((always_inline)); +inline boolean isAscii(int c) __attribute__((always_inline)); +inline boolean isWhitespace(int c) __attribute__((always_inline)); +inline boolean isControl(int c) __attribute__((always_inline)); +inline boolean isDigit(int c) __attribute__((always_inline)); +inline boolean isGraph(int c) __attribute__((always_inline)); +inline boolean isLowerCase(int c) __attribute__((always_inline)); +inline boolean isPrintable(int c) __attribute__((always_inline)); +inline boolean isPunct(int c) __attribute__((always_inline)); +inline boolean isSpace(int c) __attribute__((always_inline)); +inline boolean isUpperCase(int c) __attribute__((always_inline)); +inline boolean isHexadecimalDigit(int c) __attribute__((always_inline)); +inline int toAscii(int c) __attribute__((always_inline)); +inline int toLowerCase(int c) __attribute__((always_inline)); +inline int toUpperCase(int c)__attribute__((always_inline)); +#elif defined ( __ICCARM__ ) +#endif + +// Checks for an alphanumeric character. +// It is equivalent to (isalpha(c) || isdigit(c)). +inline boolean isAlphaNumeric(int c) +{ + return ( isalnum(c) == 0 ? false : true); +} + + +// Checks for an alphabetic character. +// It is equivalent to (isupper(c) || islower(c)). +inline boolean isAlpha(int c) +{ + return ( isalpha(c) == 0 ? false : true); +} + + +// Checks whether c is a 7-bit unsigned char value +// that fits into the ASCII character set. +inline boolean isAscii(int c) +{ +/* return ( isascii(c) == 0 ? false : true); */ + return ( (c & ~0x7f) != 0 ? false : true); +} + + +// Checks for a blank character, that is, a space or a tab. +inline boolean isWhitespace(int c) +{ + return ( isblank (c) == 0 ? false : true); +} + + +// Checks for a control character. +inline boolean isControl(int c) +{ + return ( iscntrl (c) == 0 ? false : true); +} + + +// Checks for a digit (0 through 9). +inline boolean isDigit(int c) +{ + return ( isdigit (c) == 0 ? false : true); +} + + +// Checks for any printable character except space. +inline boolean isGraph(int c) +{ + return ( isgraph (c) == 0 ? false : true); +} + + +// Checks for a lower-case character. +inline boolean isLowerCase(int c) +{ + return (islower (c) == 0 ? false : true); +} + + +// Checks for any printable character including space. +inline boolean isPrintable(int c) +{ + return ( isprint (c) == 0 ? false : true); +} + + +// Checks for any printable character which is not a space +// or an alphanumeric character. +inline boolean isPunct(int c) +{ + return ( ispunct (c) == 0 ? false : true); +} + + +// Checks for white-space characters. For the avr-libc library, +// these are: space, formfeed ('\f'), newline ('\n'), carriage +// return ('\r'), horizontal tab ('\t'), and vertical tab ('\v'). +inline boolean isSpace(int c) +{ + return ( isspace (c) == 0 ? false : true); +} + + +// Checks for an uppercase letter. +inline boolean isUpperCase(int c) +{ + return ( isupper (c) == 0 ? false : true); +} + + +// Checks for a hexadecimal digits, i.e. one of 0 1 2 3 4 5 6 7 +// 8 9 a b c d e f A B C D E F. +inline boolean isHexadecimalDigit(int c) +{ + return ( isxdigit (c) == 0 ? false : true); +} + + +// Converts c to a 7-bit unsigned char value that fits into the +// ASCII character set, by clearing the high-order bits. +inline int toAscii(int c) +{ +/* return toascii (c); */ + return (c & 0x7f); +} + + +// Warning: +// Many people will be unhappy if you use this function. +// This function will convert accented letters into random +// characters. + +// Converts the letter c to lower case, if possible. +inline int toLowerCase(int c) +{ + return tolower (c); +} + + +// Converts the letter c to upper case, if possible. +inline int toUpperCase(int c) +{ + return toupper (c); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/cores/maple/WProgram.h b/BootLoaders/Boards/stm32/cores/maple/WProgram.h new file mode 100644 index 0000000..4e476d4 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/WProgram.h @@ -0,0 +1,35 @@ +/****************************************************************************** + * 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 _WIRISH_WPROGRAM_H_ +#define _WIRISH_WPROGRAM_H_ + +#include + +void setup(); +void loop(); + +#endif diff --git a/BootLoaders/Boards/stm32/cores/maple/WString.cpp b/BootLoaders/Boards/stm32/cores/maple/WString.cpp new file mode 100644 index 0000000..5332982 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/WString.cpp @@ -0,0 +1,747 @@ +/* + WString.cpp - String library for Wiring & Arduino + ...mostly rewritten by Paul Stoffregen... + Copyright (c) 2009-10 Hernando Barragan. All rights reserved. + Copyright 2011, Paul Stoffregen, paul@pjrc.com + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "WString.h" +#include "itoa.h" +#include "avr/dtostrf.h" + +/*********************************************/ +/* Constructors */ +/*********************************************/ + +String::String(const char *cstr) +{ + init(); + if (cstr) copy(cstr, strlen(cstr)); +} + +String::String(const String &value) +{ + init(); + *this = value; +} + +String::String(const __FlashStringHelper *pstr) +{ + init(); + *this = pstr; +} + +#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) +String::String(String &&rval) +{ + init(); + move(rval); +} +String::String(StringSumHelper &&rval) +{ + init(); + move(rval); +} +#endif + +String::String(char c) +{ + init(); + char buf[2]; + buf[0] = c; + buf[1] = 0; + *this = buf; +} + +String::String(unsigned char value, unsigned char base) +{ + init(); + char buf[1 + 8 * sizeof(unsigned char)]; + utoa(value, buf, base); + *this = buf; +} + +String::String(int value, unsigned char base) +{ + init(); + char buf[2 + 8 * sizeof(int)]; + itoa(value, buf, base); + *this = buf; +} + +String::String(unsigned int value, unsigned char base) +{ + init(); + char buf[1 + 8 * sizeof(unsigned int)]; + utoa(value, buf, base); + *this = buf; +} + +String::String(long value, unsigned char base) +{ + init(); + char buf[2 + 8 * sizeof(long)]; + ltoa(value, buf, base); + *this = buf; +} + +String::String(unsigned long value, unsigned char base) +{ + init(); + char buf[1 + 8 * sizeof(unsigned long)]; + ultoa(value, buf, base); + *this = buf; +} + +String::String(float value, unsigned char decimalPlaces) +{ + init(); + char buf[33]; + *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); +} + +String::String(double value, unsigned char decimalPlaces) +{ + init(); + char buf[33]; + *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); +} + +String::~String() +{ + free(buffer); +} + +/*********************************************/ +/* Memory Management */ +/*********************************************/ + +inline void String::init(void) +{ + buffer = NULL; + capacity = 0; + len = 0; +} + +void String::invalidate(void) +{ + if (buffer) free(buffer); + buffer = NULL; + capacity = len = 0; +} + +unsigned char String::reserve(unsigned int size) +{ + if (buffer && capacity >= size) return 1; + if (changeBuffer(size)) { + if (len == 0) buffer[0] = 0; + return 1; + } + return 0; +} + +unsigned char String::changeBuffer(unsigned int maxStrLen) +{ + char *newbuffer = (char *)realloc(buffer, maxStrLen + 1); + if (newbuffer) { + buffer = newbuffer; + capacity = maxStrLen; + return 1; + } + return 0; +} + +/*********************************************/ +/* Copy and Move */ +/*********************************************/ + +String & String::copy(const char *cstr, unsigned int length) +{ + if (!reserve(length)) { + invalidate(); + return *this; + } + len = length; + strcpy(buffer, cstr); + return *this; +} + +String & String::copy(const __FlashStringHelper *pstr, unsigned int length) +{ + if (!reserve(length)) { + invalidate(); + return *this; + } + len = length; + strcpy_P(buffer, (PGM_P)pstr); + return *this; +} + +#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) +void String::move(String &rhs) +{ + if (buffer) { + if (rhs && capacity >= rhs.len) { + strcpy(buffer, rhs.buffer); + len = rhs.len; + rhs.len = 0; + return; + } else { + free(buffer); + } + } + buffer = rhs.buffer; + capacity = rhs.capacity; + len = rhs.len; + rhs.buffer = NULL; + rhs.capacity = 0; + rhs.len = 0; +} +#endif + +String & String::operator = (const String &rhs) +{ + if (this == &rhs) return *this; + + if (rhs.buffer) copy(rhs.buffer, rhs.len); + else invalidate(); + + return *this; +} + +#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) +String & String::operator = (String &&rval) +{ + if (this != &rval) move(rval); + return *this; +} + +String & String::operator = (StringSumHelper &&rval) +{ + if (this != &rval) move(rval); + return *this; +} +#endif + +String & String::operator = (const char *cstr) +{ + if (cstr) copy(cstr, strlen(cstr)); + else invalidate(); + + return *this; +} + +String & String::operator = (const __FlashStringHelper *pstr) +{ + if (pstr) copy(pstr, strlen_P((PGM_P)pstr)); + else invalidate(); + + return *this; +} + +/*********************************************/ +/* concat */ +/*********************************************/ + +unsigned char String::concat(const String &s) +{ + return concat(s.buffer, s.len); +} + +unsigned char String::concat(const char *cstr, unsigned int length) +{ + unsigned int newlen = len + length; + if (!cstr) return 0; + if (length == 0) return 1; + if (!reserve(newlen)) return 0; + strcpy(buffer + len, cstr); + len = newlen; + return 1; +} + +unsigned char String::concat(const char *cstr) +{ + if (!cstr) return 0; + return concat(cstr, strlen(cstr)); +} + +unsigned char String::concat(char c) +{ + char buf[2]; + buf[0] = c; + buf[1] = 0; + return concat(buf, 1); +} + +unsigned char String::concat(unsigned char num) +{ + char buf[1 + 3 * sizeof(unsigned char)]; + itoa(num, buf, 10); + return concat(buf, strlen(buf)); +} + +unsigned char String::concat(int num) +{ + char buf[2 + 3 * sizeof(int)]; + itoa(num, buf, 10); + return concat(buf, strlen(buf)); +} + +unsigned char String::concat(unsigned int num) +{ + char buf[1 + 3 * sizeof(unsigned int)]; + utoa(num, buf, 10); + return concat(buf, strlen(buf)); +} + +unsigned char String::concat(long num) +{ + char buf[2 + 3 * sizeof(long)]; + ltoa(num, buf, 10); + return concat(buf, strlen(buf)); +} + +unsigned char String::concat(unsigned long num) +{ + char buf[1 + 3 * sizeof(unsigned long)]; + ultoa(num, buf, 10); + return concat(buf, strlen(buf)); +} + +unsigned char String::concat(float num) +{ + char buf[20]; + char* string = dtostrf(num, 4, 2, buf); + return concat(string, strlen(string)); +} + +unsigned char String::concat(double num) +{ + char buf[20]; + char* string = dtostrf(num, 4, 2, buf); + return concat(string, strlen(string)); +} + +unsigned char String::concat(const __FlashStringHelper * str) +{ + if (!str) return 0; + int length = strlen_P((const char *) str); + if (length == 0) return 1; + unsigned int newlen = len + length; + if (!reserve(newlen)) return 0; + strcpy_P(buffer + len, (const char *) str); + len = newlen; + return 1; +} + +/*********************************************/ +/* Concatenate */ +/*********************************************/ + +StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(rhs.buffer, rhs.len)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr) +{ + StringSumHelper &a = const_cast(lhs); + if (!cstr || !a.concat(cstr, strlen(cstr))) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, char c) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(c)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, int num) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, long num) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, float num) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, double num) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(rhs)) a.invalidate(); + return a; +} + +/*********************************************/ +/* Comparison */ +/*********************************************/ + +int String::compareTo(const String &s) const +{ + if (!buffer || !s.buffer) { + if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer; + if (buffer && len > 0) return *(unsigned char *)buffer; + return 0; + } + return strcmp(buffer, s.buffer); +} + +unsigned char String::equals(const String &s2) const +{ + return (len == s2.len && compareTo(s2) == 0); +} + +unsigned char String::equals(const char *cstr) const +{ + if (len == 0) return (cstr == NULL || *cstr == 0); + if (cstr == NULL) return buffer[0] == 0; + return strcmp(buffer, cstr) == 0; +} + +unsigned char String::operator<(const String &rhs) const +{ + return compareTo(rhs) < 0; +} + +unsigned char String::operator>(const String &rhs) const +{ + return compareTo(rhs) > 0; +} + +unsigned char String::operator<=(const String &rhs) const +{ + return compareTo(rhs) <= 0; +} + +unsigned char String::operator>=(const String &rhs) const +{ + return compareTo(rhs) >= 0; +} + +unsigned char String::equalsIgnoreCase( const String &s2 ) const +{ + if (this == &s2) return 1; + if (len != s2.len) return 0; + if (len == 0) return 1; + const char *p1 = buffer; + const char *p2 = s2.buffer; + while (*p1) { + if (tolower(*p1++) != tolower(*p2++)) return 0; + } + return 1; +} + +unsigned char String::startsWith( const String &s2 ) const +{ + if (len < s2.len) return 0; + return startsWith(s2, 0); +} + +unsigned char String::startsWith( const String &s2, unsigned int offset ) const +{ + if (offset > len - s2.len || !buffer || !s2.buffer) return 0; + return strncmp( &buffer[offset], s2.buffer, s2.len ) == 0; +} + +unsigned char String::endsWith( const String &s2 ) const +{ + if ( len < s2.len || !buffer || !s2.buffer) return 0; + return strcmp(&buffer[len - s2.len], s2.buffer) == 0; +} + +/*********************************************/ +/* Character Access */ +/*********************************************/ + +char String::charAt(unsigned int loc) const +{ + return operator[](loc); +} + +void String::setCharAt(unsigned int loc, char c) +{ + if (loc < len) buffer[loc] = c; +} + +char & String::operator[](unsigned int index) +{ + static char dummy_writable_char; + if (index >= len || !buffer) { + dummy_writable_char = 0; + return dummy_writable_char; + } + return buffer[index]; +} + +char String::operator[]( unsigned int index ) const +{ + if (index >= len || !buffer) return 0; + return buffer[index]; +} + +void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const +{ + if (!bufsize || !buf) return; + if (index >= len) { + buf[0] = 0; + return; + } + unsigned int n = bufsize - 1; + if (n > len - index) n = len - index; + strncpy((char *)buf, buffer + index, n); + buf[n] = 0; +} + +/*********************************************/ +/* Search */ +/*********************************************/ + +int String::indexOf(char c) const +{ + return indexOf(c, 0); +} + +int String::indexOf( char ch, unsigned int fromIndex ) const +{ + if (fromIndex >= len) return -1; + const char* temp = strchr(buffer + fromIndex, ch); + if (temp == NULL) return -1; + return temp - buffer; +} + +int String::indexOf(const String &s2) const +{ + return indexOf(s2, 0); +} + +int String::indexOf(const String &s2, unsigned int fromIndex) const +{ + if (fromIndex >= len) return -1; + const char *found = strstr(buffer + fromIndex, s2.buffer); + if (found == NULL) return -1; + return found - buffer; +} + +int String::lastIndexOf( char theChar ) const +{ + return lastIndexOf(theChar, len - 1); +} + +int String::lastIndexOf(char ch, unsigned int fromIndex) const +{ + if (fromIndex >= len) return -1; + char tempchar = buffer[fromIndex + 1]; + buffer[fromIndex + 1] = '\0'; + char* temp = strrchr( buffer, ch ); + buffer[fromIndex + 1] = tempchar; + if (temp == NULL) return -1; + return temp - buffer; +} + +int String::lastIndexOf(const String &s2) const +{ + return lastIndexOf(s2, len - s2.len); +} + +int String::lastIndexOf(const String &s2, unsigned int fromIndex) const +{ + if (s2.len == 0 || len == 0 || s2.len > len) return -1; + if (fromIndex >= len) fromIndex = len - 1; + int found = -1; + for (char *p = buffer; p <= buffer + fromIndex; p++) { + p = strstr(p, s2.buffer); + if (!p) break; + if ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer; + } + return found; +} + +String String::substring(unsigned int left, unsigned int right) const +{ + if (left > right) { + unsigned int temp = right; + right = left; + left = temp; + } + String out; + if (left >= len) return out; + if (right > len) right = len; + char temp = buffer[right]; // save the replaced character + buffer[right] = '\0'; + out = buffer + left; // pointer arithmetic + buffer[right] = temp; //restore character + return out; +} + +/*********************************************/ +/* Modification */ +/*********************************************/ + +void String::replace(char find, char replace) +{ + if (!buffer) return; + for (char *p = buffer; *p; p++) { + if (*p == find) *p = replace; + } +} + +void String::replace(const String& find, const String& replace) +{ + if (len == 0 || find.len == 0) return; + int diff = replace.len - find.len; + char *readFrom = buffer; + char *foundAt; + if (diff == 0) { + while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { + memcpy(foundAt, replace.buffer, replace.len); + readFrom = foundAt + replace.len; + } + } else if (diff < 0) { + char *writeTo = buffer; + while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { + unsigned int n = foundAt - readFrom; + memcpy(writeTo, readFrom, n); + writeTo += n; + memcpy(writeTo, replace.buffer, replace.len); + writeTo += replace.len; + readFrom = foundAt + find.len; + len += diff; + } + strcpy(writeTo, readFrom); + } else { + unsigned int size = len; // compute size needed for result + while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { + readFrom = foundAt + find.len; + size += diff; + } + if (size == len) return; + if (size > capacity && !changeBuffer(size)) return; // XXX: tell user! + int index = len - 1; + while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) { + readFrom = buffer + index + find.len; + memmove(readFrom + diff, readFrom, len - (readFrom - buffer)); + len += diff; + buffer[len] = 0; + memcpy(buffer + index, replace.buffer, replace.len); + index--; + } + } +} + +void String::remove(unsigned int index){ + // Pass the biggest integer as the count. The remove method + // below will take care of truncating it at the end of the + // string. + remove(index, (unsigned int)-1); +} + +void String::remove(unsigned int index, unsigned int count){ + if (index >= len) { return; } + if (count <= 0) { return; } + if (count > len - index) { count = len - index; } + char *writeTo = buffer + index; + len = len - count; + strncpy(writeTo, buffer + index + count,len - index); + buffer[len] = 0; +} + +void String::toLowerCase(void) +{ + if (!buffer) return; + for (char *p = buffer; *p; p++) { + *p = tolower(*p); + } +} + +void String::toUpperCase(void) +{ + if (!buffer) return; + for (char *p = buffer; *p; p++) { + *p = toupper(*p); + } +} + +void String::trim(void) +{ + if (!buffer || len == 0) return; + char *begin = buffer; + while (isspace(*begin)) begin++; + char *end = buffer + len - 1; + while (isspace(*end) && end >= begin) end--; + len = end + 1 - begin; + if (begin > buffer) memcpy(buffer, begin, len); + buffer[len] = 0; +} + +/*********************************************/ +/* Parsing / Conversion */ +/*********************************************/ + +long String::toInt(void) const +{ + if (buffer) return atol(buffer); + return 0; +} + +float String::toFloat(void) const +{ + if (buffer) return float(atof(buffer)); + return 0; +} diff --git a/BootLoaders/Boards/stm32/cores/maple/WString.h b/BootLoaders/Boards/stm32/cores/maple/WString.h new file mode 100644 index 0000000..0cc27ab --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/WString.h @@ -0,0 +1,228 @@ +/* + WString.h - String library for Wiring & Arduino + ...mostly rewritten by Paul Stoffregen... + Copyright (c) 2009-10 Hernando Barragan. All right reserved. + Copyright 2011, Paul Stoffregen, paul@pjrc.com + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef String_class_h +#define String_class_h +#ifdef __cplusplus + +#include +#include +#include +#include + +// When compiling programs with this class, the following gcc parameters +// dramatically increase performance and memory (RAM) efficiency, typically +// with little or no increase in code size. +// -felide-constructors +// -std=c++0x + +class __FlashStringHelper; +#define F(string_literal) (reinterpret_cast(PSTR(string_literal))) + +// An inherited class for holding the result of a concatenation. These +// result objects are assumed to be writable by subsequent concatenations. +class StringSumHelper; + +// The string class +class String +{ + // use a function pointer to allow for "if (s)" without the + // complications of an operator bool(). for more information, see: + // http://www.artima.com/cppsource/safebool.html + typedef void (String::*StringIfHelperType)() const; + void StringIfHelper() const {} + +public: + // constructors + // creates a copy of the initial value. + // if the initial value is null or invalid, or if memory allocation + // fails, the string will be marked as invalid (i.e. "if (s)" will + // be false). + String(const char *cstr = ""); + String(const String &str); + String(const __FlashStringHelper *str); + #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) + String(String &&rval); + String(StringSumHelper &&rval); + #endif + explicit String(char c); + explicit String(unsigned char, unsigned char base=10); + explicit String(int, unsigned char base=10); + explicit String(unsigned int, unsigned char base=10); + explicit String(long, unsigned char base=10); + explicit String(unsigned long, unsigned char base=10); + explicit String(float, unsigned char decimalPlaces=2); + explicit String(double, unsigned char decimalPlaces=2); + ~String(void); + + // memory management + // return true on success, false on failure (in which case, the string + // is left unchanged). reserve(0), if successful, will validate an + // invalid string (i.e., "if (s)" will be true afterwards) + unsigned char reserve(unsigned int size); + inline unsigned int length(void) const {return len;} + + // creates a copy of the assigned value. if the value is null or + // invalid, or if the memory allocation fails, the string will be + // marked as invalid ("if (s)" will be false). + String & operator = (const String &rhs); + String & operator = (const char *cstr); + String & operator = (const __FlashStringHelper *str); + #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) + String & operator = (String &&rval); + String & operator = (StringSumHelper &&rval); + #endif + + // concatenate (works w/ built-in types) + + // returns true on success, false on failure (in which case, the string + // is left unchanged). if the argument is null or invalid, the + // concatenation is considered unsucessful. + unsigned char concat(const String &str); + unsigned char concat(const char *cstr); + unsigned char concat(char c); + unsigned char concat(unsigned char c); + unsigned char concat(int num); + unsigned char concat(unsigned int num); + unsigned char concat(long num); + unsigned char concat(unsigned long num); + unsigned char concat(float num); + unsigned char concat(double num); + unsigned char concat(const __FlashStringHelper * str); + + // if there's not enough memory for the concatenated value, the string + // will be left unchanged (but this isn't signalled in any way) + String & operator += (const String &rhs) {concat(rhs); return (*this);} + String & operator += (const char *cstr) {concat(cstr); return (*this);} + String & operator += (char c) {concat(c); return (*this);} + String & operator += (unsigned char num) {concat(num); return (*this);} + String & operator += (int num) {concat(num); return (*this);} + String & operator += (unsigned int num) {concat(num); return (*this);} + String & operator += (long num) {concat(num); return (*this);} + String & operator += (unsigned long num) {concat(num); return (*this);} + String & operator += (float num) {concat(num); return (*this);} + String & operator += (double num) {concat(num); return (*this);} + String & operator += (const __FlashStringHelper *str){concat(str); return (*this);} + + friend StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs); + friend StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr); + friend StringSumHelper & operator + (const StringSumHelper &lhs, char c); + friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num); + friend StringSumHelper & operator + (const StringSumHelper &lhs, int num); + friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num); + friend StringSumHelper & operator + (const StringSumHelper &lhs, long num); + friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num); + friend StringSumHelper & operator + (const StringSumHelper &lhs, float num); + friend StringSumHelper & operator + (const StringSumHelper &lhs, double num); + friend StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs); + + // comparison (only works w/ Strings and "strings") + operator StringIfHelperType() const { return buffer ? &String::StringIfHelper : 0; } + int compareTo(const String &s) const; + unsigned char equals(const String &s) const; + unsigned char equals(const char *cstr) const; + unsigned char operator == (const String &rhs) const {return equals(rhs);} + unsigned char operator == (const char *cstr) const {return equals(cstr);} + unsigned char operator != (const String &rhs) const {return !equals(rhs);} + unsigned char operator != (const char *cstr) const {return !equals(cstr);} + unsigned char operator < (const String &rhs) const; + unsigned char operator > (const String &rhs) const; + unsigned char operator <= (const String &rhs) const; + unsigned char operator >= (const String &rhs) const; + unsigned char equalsIgnoreCase(const String &s) const; + unsigned char startsWith( const String &prefix) const; + unsigned char startsWith(const String &prefix, unsigned int offset) const; + unsigned char endsWith(const String &suffix) const; + + // character acccess + char charAt(unsigned int index) const; + void setCharAt(unsigned int index, char c); + char operator [] (unsigned int index) const; + char& operator [] (unsigned int index); + void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index=0) const; + void toCharArray(char *buf, unsigned int bufsize, unsigned int index=0) const + {getBytes((unsigned char *)buf, bufsize, index);} + const char * c_str() const { return buffer; } + char* begin() { return buffer; } + char* end() { return buffer + length(); } + const char* begin() const { return c_str(); } + const char* end() const { return c_str() + length(); } + + // search + int indexOf( char ch ) const; + int indexOf( char ch, unsigned int fromIndex ) const; + int indexOf( const String &str ) const; + int indexOf( const String &str, unsigned int fromIndex ) const; + int lastIndexOf( char ch ) const; + int lastIndexOf( char ch, unsigned int fromIndex ) const; + int lastIndexOf( const String &str ) const; + int lastIndexOf( const String &str, unsigned int fromIndex ) const; + String substring( unsigned int beginIndex ) const { return substring(beginIndex, len); }; + String substring( unsigned int beginIndex, unsigned int endIndex ) const; + + // modification + void replace(char find, char replace); + void replace(const String& find, const String& replace); + void remove(unsigned int index); + void remove(unsigned int index, unsigned int count); + void toLowerCase(void); + void toUpperCase(void); + void trim(void); + + // parsing/conversion + long toInt(void) const; + float toFloat(void) const; + +protected: + char *buffer; // the actual char array + unsigned int capacity; // the array length minus one (for the '\0') + unsigned int len; // the String length (not counting the '\0') +protected: + void init(void); + void invalidate(void); + unsigned char changeBuffer(unsigned int maxStrLen); + unsigned char concat(const char *cstr, unsigned int length); + + // copy and move + String & copy(const char *cstr, unsigned int length); + String & copy(const __FlashStringHelper *pstr, unsigned int length); + #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) + void move(String &rhs); + #endif +}; + +class StringSumHelper : public String +{ +public: + StringSumHelper(const String &s) : String(s) {} + StringSumHelper(const char *p) : String(p) {} + StringSumHelper(char c) : String(c) {} + StringSumHelper(unsigned char num) : String(num) {} + StringSumHelper(int num) : String(num) {} + StringSumHelper(unsigned int num) : String(num) {} + StringSumHelper(long num) : String(num) {} + StringSumHelper(unsigned long num) : String(num) {} + StringSumHelper(float num) : String(num) {} + StringSumHelper(double num) : String(num) {} +}; + +#endif // __cplusplus +#endif // String_class_h diff --git a/BootLoaders/Boards/stm32/cores/maple/avr/dtostrf.c b/BootLoaders/Boards/stm32/cores/maple/avr/dtostrf.c new file mode 100644 index 0000000..7f90154 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/avr/dtostrf.c @@ -0,0 +1,29 @@ +/* + dtostrf - Emulation for dtostrf function from avr-libc + Copyright (c) 2013 Arduino. All rights reserved. + Written by Cristian Maglie + + 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. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include + +char *dtostrf (double val, signed char width, unsigned char prec, char *sout) { + char fmt[20]; + sprintf(fmt, "%%%d.%df", width, prec); + sprintf(sout, fmt, val); + return sout; +} + diff --git a/BootLoaders/Boards/stm32/cores/maple/avr/dtostrf.h b/BootLoaders/Boards/stm32/cores/maple/avr/dtostrf.h new file mode 100644 index 0000000..0bf9f57 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/avr/dtostrf.h @@ -0,0 +1,29 @@ +/* + dtostrf - Emulation for dtostrf function from avr-libc + Copyright (c) 2013 Arduino. All rights reserved. + Written by Cristian Maglie + + 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. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +char *dtostrf (double val, signed char width, unsigned char prec, char *sout); + +#ifdef __cplusplus +} +#endif diff --git a/BootLoaders/Boards/stm32/cores/maple/avr/interrupt.h b/BootLoaders/Boards/stm32/cores/maple/avr/interrupt.h new file mode 100644 index 0000000..e69de29 diff --git a/BootLoaders/Boards/stm32/cores/maple/avr/pgmspace.h b/BootLoaders/Boards/stm32/cores/maple/avr/pgmspace.h new file mode 100644 index 0000000..9b344c9 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/avr/pgmspace.h @@ -0,0 +1,44 @@ +#ifndef __PGMSPACE_H_ +#define __PGMSPACE_H_ 1 + +#include + +#define PROGMEM +#define PGM_P const char * +#define PSTR(str) (str) + +#define _SFR_BYTE(n) (n) + +typedef void prog_void; +typedef char prog_char; +typedef unsigned char prog_uchar; +typedef int8_t prog_int8_t; +typedef uint8_t prog_uint8_t; +typedef int16_t prog_int16_t; +typedef uint16_t prog_uint16_t; +typedef int32_t prog_int32_t; +typedef uint32_t prog_uint32_t; + +#define memcpy_P(dest, src, num) memcpy((dest), (src), (num)) +#define strcpy_P(dest, src) strcpy((dest), (src)) +#define strcat_P(dest, src) strcat((dest), (src)) +#define strcmp_P(a, b) strcmp((a), (b)) +#define strstr_P(a, b) strstr((a), (b)) +#define strlen_P(a) strlen((a)) +#define sprintf_P(s, f, ...) sprintf((s), (f), __VA_ARGS__) + +#define pgm_read_byte(addr) (*(const unsigned char *)(addr)) +#define pgm_read_word(addr) (*(const unsigned short *)(addr)) +#define pgm_read_dword(addr) (*(const unsigned long *)(addr)) +#define pgm_read_float(addr) (*(const float *)(addr)) + +#define pgm_read_byte_near(addr) pgm_read_byte(addr) +#define pgm_read_word_near(addr) pgm_read_word(addr) +#define pgm_read_dword_near(addr) pgm_read_dword(addr) +#define pgm_read_float_near(addr) pgm_read_float(addr) +#define pgm_read_byte_far(addr) pgm_read_byte(addr) +#define pgm_read_word_far(addr) pgm_read_word(addr) +#define pgm_read_dword_far(addr) pgm_read_dword(addr) +#define pgm_read_float_far(addr) pgm_read_float(addr) + +#endif diff --git a/BootLoaders/Boards/stm32/cores/maple/bit_constants.h b/BootLoaders/Boards/stm32/cores/maple/bit_constants.h new file mode 100644 index 0000000..4638f76 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/bit_constants.h @@ -0,0 +1,579 @@ +/****************************************************************************** + * 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. + *****************************************************************************/ + +/** + * @brief BIT[n] and binary literal defines, for Arduino + * compatibility. + */ + +#ifndef _WIRISH_BIT_CONSTANTS_H_ +#define _WIRISH_BIT_CONSTANTS_H_ + +#define BIT0 (1 << 0) +#define BIT1 (1 << 1) +#define BIT2 (1 << 2) +#define BIT3 (1 << 3) +#define BIT4 (1 << 4) +#define BIT5 (1 << 5) +#define BIT6 (1 << 6) +#define BIT7 (1 << 7) +#define BIT8 (1 << 8) +#define BIT9 (1 << 9) +#define BIT10 (1 << 10) +#define BIT11 (1 << 11) +#define BIT12 (1 << 12) +#define BIT13 (1 << 13) +#define BIT14 (1 << 14) +#define BIT15 (1 << 15) +#define BIT16 (1 << 16) +#define BIT17 (1 << 17) +#define BIT18 (1 << 18) +#define BIT19 (1 << 19) +#define BIT20 (1 << 20) +#define BIT21 (1 << 21) +#define BIT22 (1 << 22) +#define BIT23 (1 << 23) +#define BIT24 (1 << 24) +#define BIT25 (1 << 25) +#define BIT26 (1 << 26) +#define BIT27 (1 << 27) +#define BIT28 (1 << 28) +#define BIT29 (1 << 29) +#define BIT30 (1 << 30) +#define BIT31 (1 << 31) + +#define B0 0 +#define B00 0 +#define B000 0 +#define B0000 0 +#define B00000 0 +#define B000000 0 +#define B0000000 0 +#define B00000000 0 +#define B1 1 +#define B01 1 +#define B001 1 +#define B0001 1 +#define B00001 1 +#define B000001 1 +#define B0000001 1 +#define B00000001 1 +#define B10 2 +#define B010 2 +#define B0010 2 +#define B00010 2 +#define B000010 2 +#define B0000010 2 +#define B00000010 2 +#define B11 3 +#define B011 3 +#define B0011 3 +#define B00011 3 +#define B000011 3 +#define B0000011 3 +#define B00000011 3 +#define B100 4 +#define B0100 4 +#define B00100 4 +#define B000100 4 +#define B0000100 4 +#define B00000100 4 +#define B101 5 +#define B0101 5 +#define B00101 5 +#define B000101 5 +#define B0000101 5 +#define B00000101 5 +#define B110 6 +#define B0110 6 +#define B00110 6 +#define B000110 6 +#define B0000110 6 +#define B00000110 6 +#define B111 7 +#define B0111 7 +#define B00111 7 +#define B000111 7 +#define B0000111 7 +#define B00000111 7 +#define B1000 8 +#define B01000 8 +#define B001000 8 +#define B0001000 8 +#define B00001000 8 +#define B1001 9 +#define B01001 9 +#define B001001 9 +#define B0001001 9 +#define B00001001 9 +#define B1010 10 +#define B01010 10 +#define B001010 10 +#define B0001010 10 +#define B00001010 10 +#define B1011 11 +#define B01011 11 +#define B001011 11 +#define B0001011 11 +#define B00001011 11 +#define B1100 12 +#define B01100 12 +#define B001100 12 +#define B0001100 12 +#define B00001100 12 +#define B1101 13 +#define B01101 13 +#define B001101 13 +#define B0001101 13 +#define B00001101 13 +#define B1110 14 +#define B01110 14 +#define B001110 14 +#define B0001110 14 +#define B00001110 14 +#define B1111 15 +#define B01111 15 +#define B001111 15 +#define B0001111 15 +#define B00001111 15 +#define B10000 16 +#define B010000 16 +#define B0010000 16 +#define B00010000 16 +#define B10001 17 +#define B010001 17 +#define B0010001 17 +#define B00010001 17 +#define B10010 18 +#define B010010 18 +#define B0010010 18 +#define B00010010 18 +#define B10011 19 +#define B010011 19 +#define B0010011 19 +#define B00010011 19 +#define B10100 20 +#define B010100 20 +#define B0010100 20 +#define B00010100 20 +#define B10101 21 +#define B010101 21 +#define B0010101 21 +#define B00010101 21 +#define B10110 22 +#define B010110 22 +#define B0010110 22 +#define B00010110 22 +#define B10111 23 +#define B010111 23 +#define B0010111 23 +#define B00010111 23 +#define B11000 24 +#define B011000 24 +#define B0011000 24 +#define B00011000 24 +#define B11001 25 +#define B011001 25 +#define B0011001 25 +#define B00011001 25 +#define B11010 26 +#define B011010 26 +#define B0011010 26 +#define B00011010 26 +#define B11011 27 +#define B011011 27 +#define B0011011 27 +#define B00011011 27 +#define B11100 28 +#define B011100 28 +#define B0011100 28 +#define B00011100 28 +#define B11101 29 +#define B011101 29 +#define B0011101 29 +#define B00011101 29 +#define B11110 30 +#define B011110 30 +#define B0011110 30 +#define B00011110 30 +#define B11111 31 +#define B011111 31 +#define B0011111 31 +#define B00011111 31 +#define B100000 32 +#define B0100000 32 +#define B00100000 32 +#define B100001 33 +#define B0100001 33 +#define B00100001 33 +#define B100010 34 +#define B0100010 34 +#define B00100010 34 +#define B100011 35 +#define B0100011 35 +#define B00100011 35 +#define B100100 36 +#define B0100100 36 +#define B00100100 36 +#define B100101 37 +#define B0100101 37 +#define B00100101 37 +#define B100110 38 +#define B0100110 38 +#define B00100110 38 +#define B100111 39 +#define B0100111 39 +#define B00100111 39 +#define B101000 40 +#define B0101000 40 +#define B00101000 40 +#define B101001 41 +#define B0101001 41 +#define B00101001 41 +#define B101010 42 +#define B0101010 42 +#define B00101010 42 +#define B101011 43 +#define B0101011 43 +#define B00101011 43 +#define B101100 44 +#define B0101100 44 +#define B00101100 44 +#define B101101 45 +#define B0101101 45 +#define B00101101 45 +#define B101110 46 +#define B0101110 46 +#define B00101110 46 +#define B101111 47 +#define B0101111 47 +#define B00101111 47 +#define B110000 48 +#define B0110000 48 +#define B00110000 48 +#define B110001 49 +#define B0110001 49 +#define B00110001 49 +#define B110010 50 +#define B0110010 50 +#define B00110010 50 +#define B110011 51 +#define B0110011 51 +#define B00110011 51 +#define B110100 52 +#define B0110100 52 +#define B00110100 52 +#define B110101 53 +#define B0110101 53 +#define B00110101 53 +#define B110110 54 +#define B0110110 54 +#define B00110110 54 +#define B110111 55 +#define B0110111 55 +#define B00110111 55 +#define B111000 56 +#define B0111000 56 +#define B00111000 56 +#define B111001 57 +#define B0111001 57 +#define B00111001 57 +#define B111010 58 +#define B0111010 58 +#define B00111010 58 +#define B111011 59 +#define B0111011 59 +#define B00111011 59 +#define B111100 60 +#define B0111100 60 +#define B00111100 60 +#define B111101 61 +#define B0111101 61 +#define B00111101 61 +#define B111110 62 +#define B0111110 62 +#define B00111110 62 +#define B111111 63 +#define B0111111 63 +#define B00111111 63 +#define B1000000 64 +#define B01000000 64 +#define B1000001 65 +#define B01000001 65 +#define B1000010 66 +#define B01000010 66 +#define B1000011 67 +#define B01000011 67 +#define B1000100 68 +#define B01000100 68 +#define B1000101 69 +#define B01000101 69 +#define B1000110 70 +#define B01000110 70 +#define B1000111 71 +#define B01000111 71 +#define B1001000 72 +#define B01001000 72 +#define B1001001 73 +#define B01001001 73 +#define B1001010 74 +#define B01001010 74 +#define B1001011 75 +#define B01001011 75 +#define B1001100 76 +#define B01001100 76 +#define B1001101 77 +#define B01001101 77 +#define B1001110 78 +#define B01001110 78 +#define B1001111 79 +#define B01001111 79 +#define B1010000 80 +#define B01010000 80 +#define B1010001 81 +#define B01010001 81 +#define B1010010 82 +#define B01010010 82 +#define B1010011 83 +#define B01010011 83 +#define B1010100 84 +#define B01010100 84 +#define B1010101 85 +#define B01010101 85 +#define B1010110 86 +#define B01010110 86 +#define B1010111 87 +#define B01010111 87 +#define B1011000 88 +#define B01011000 88 +#define B1011001 89 +#define B01011001 89 +#define B1011010 90 +#define B01011010 90 +#define B1011011 91 +#define B01011011 91 +#define B1011100 92 +#define B01011100 92 +#define B1011101 93 +#define B01011101 93 +#define B1011110 94 +#define B01011110 94 +#define B1011111 95 +#define B01011111 95 +#define B1100000 96 +#define B01100000 96 +#define B1100001 97 +#define B01100001 97 +#define B1100010 98 +#define B01100010 98 +#define B1100011 99 +#define B01100011 99 +#define B1100100 100 +#define B01100100 100 +#define B1100101 101 +#define B01100101 101 +#define B1100110 102 +#define B01100110 102 +#define B1100111 103 +#define B01100111 103 +#define B1101000 104 +#define B01101000 104 +#define B1101001 105 +#define B01101001 105 +#define B1101010 106 +#define B01101010 106 +#define B1101011 107 +#define B01101011 107 +#define B1101100 108 +#define B01101100 108 +#define B1101101 109 +#define B01101101 109 +#define B1101110 110 +#define B01101110 110 +#define B1101111 111 +#define B01101111 111 +#define B1110000 112 +#define B01110000 112 +#define B1110001 113 +#define B01110001 113 +#define B1110010 114 +#define B01110010 114 +#define B1110011 115 +#define B01110011 115 +#define B1110100 116 +#define B01110100 116 +#define B1110101 117 +#define B01110101 117 +#define B1110110 118 +#define B01110110 118 +#define B1110111 119 +#define B01110111 119 +#define B1111000 120 +#define B01111000 120 +#define B1111001 121 +#define B01111001 121 +#define B1111010 122 +#define B01111010 122 +#define B1111011 123 +#define B01111011 123 +#define B1111100 124 +#define B01111100 124 +#define B1111101 125 +#define B01111101 125 +#define B1111110 126 +#define B01111110 126 +#define B1111111 127 +#define B01111111 127 +#define B10000000 128 +#define B10000001 129 +#define B10000010 130 +#define B10000011 131 +#define B10000100 132 +#define B10000101 133 +#define B10000110 134 +#define B10000111 135 +#define B10001000 136 +#define B10001001 137 +#define B10001010 138 +#define B10001011 139 +#define B10001100 140 +#define B10001101 141 +#define B10001110 142 +#define B10001111 143 +#define B10010000 144 +#define B10010001 145 +#define B10010010 146 +#define B10010011 147 +#define B10010100 148 +#define B10010101 149 +#define B10010110 150 +#define B10010111 151 +#define B10011000 152 +#define B10011001 153 +#define B10011010 154 +#define B10011011 155 +#define B10011100 156 +#define B10011101 157 +#define B10011110 158 +#define B10011111 159 +#define B10100000 160 +#define B10100001 161 +#define B10100010 162 +#define B10100011 163 +#define B10100100 164 +#define B10100101 165 +#define B10100110 166 +#define B10100111 167 +#define B10101000 168 +#define B10101001 169 +#define B10101010 170 +#define B10101011 171 +#define B10101100 172 +#define B10101101 173 +#define B10101110 174 +#define B10101111 175 +#define B10110000 176 +#define B10110001 177 +#define B10110010 178 +#define B10110011 179 +#define B10110100 180 +#define B10110101 181 +#define B10110110 182 +#define B10110111 183 +#define B10111000 184 +#define B10111001 185 +#define B10111010 186 +#define B10111011 187 +#define B10111100 188 +#define B10111101 189 +#define B10111110 190 +#define B10111111 191 +#define B11000000 192 +#define B11000001 193 +#define B11000010 194 +#define B11000011 195 +#define B11000100 196 +#define B11000101 197 +#define B11000110 198 +#define B11000111 199 +#define B11001000 200 +#define B11001001 201 +#define B11001010 202 +#define B11001011 203 +#define B11001100 204 +#define B11001101 205 +#define B11001110 206 +#define B11001111 207 +#define B11010000 208 +#define B11010001 209 +#define B11010010 210 +#define B11010011 211 +#define B11010100 212 +#define B11010101 213 +#define B11010110 214 +#define B11010111 215 +#define B11011000 216 +#define B11011001 217 +#define B11011010 218 +#define B11011011 219 +#define B11011100 220 +#define B11011101 221 +#define B11011110 222 +#define B11011111 223 +#define B11100000 224 +#define B11100001 225 +#define B11100010 226 +#define B11100011 227 +#define B11100100 228 +#define B11100101 229 +#define B11100110 230 +#define B11100111 231 +#define B11101000 232 +#define B11101001 233 +#define B11101010 234 +#define B11101011 235 +#define B11101100 236 +#define B11101101 237 +#define B11101110 238 +#define B11101111 239 +#define B11110000 240 +#define B11110001 241 +#define B11110010 242 +#define B11110011 243 +#define B11110100 244 +#define B11110101 245 +#define B11110110 246 +#define B11110111 247 +#define B11111000 248 +#define B11111001 249 +#define B11111010 250 +#define B11111011 251 +#define B11111100 252 +#define B11111101 253 +#define B11111110 254 +#define B11111111 255 + +#endif /* _BIT_CONSTANTS_H_ */ diff --git a/BootLoaders/Boards/stm32/cores/maple/bits.h b/BootLoaders/Boards/stm32/cores/maple/bits.h new file mode 100644 index 0000000..6b27f80 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/bits.h @@ -0,0 +1,35 @@ +/****************************************************************************** + * 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. + *****************************************************************************/ + +/* Note: Use of this header file is deprecated. Use bit_constants.h + instead. */ + +#ifndef _WIRISH_BITS_H_ +#define _WIRISH_BITS_H_ + +#include + +#endif diff --git a/BootLoaders/Boards/stm32/cores/maple/boards.h b/BootLoaders/Boards/stm32/cores/maple/boards.h new file mode 100644 index 0000000..518f9a0 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/boards.h @@ -0,0 +1,175 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Bryan Newbold. + * + * 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/include/wirish/boards.h + * @author Bryan Newbold , + * Marti Bolivar + * @brief init() and board-specific pin information. + */ + +#ifndef _WIRISH_BOARDS_H_ +#define _WIRISH_BOARDS_H_ + +#include +#include +#include + +/* Set of all possible pin names; not all boards have all these (note + * that we use the Dx convention since all of the Maple's pins are + * "digital" pins (e.g. can be used with digitalRead() and + * digitalWrite()), but not all of them are connected to ADCs. */ +enum { + D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15, D16, + D17, D18, D19, D20, D21, D22, D23, D24, D25, D26, D27, D28, D29, D30, D31, + D32, D33, D34, D35, D36, D37, D38, D39, D40, D41, D42, D43, D44, D45, D46, + D47, D48, D49, D50, D51, D52, D53, D54, D55, D56, D57, D58, D59, D60, D61, + D62, D63, D64, D65, D66, D67, D68, D69, D70, D71, D72, D73, D74, D75, D76, + D77, D78, D79, D80, D81, D82, D83, D84, D85, D86, D87, D88, D89, D90, D91, + D92, D93, D94, D95, D96, D97, D98, D99, D100, D101, D102, D103, D104, D105, + D106, D107, D108, D109, D110, D111, }; + +/** + * @brief Maps each Maple pin to a corresponding stm32_pin_info. + * @see stm32_pin_info + */ +extern const stm32_pin_info PIN_MAP[]; + +/** + * @brief Pins capable of PWM output. + * + * Its length is BOARD_NR_PWM_PINS. + */ +extern const uint8 boardPWMPins[]; + +/** + * @brief Array of pins capable of analog input. + * + * Its length is BOARD_NR_ADC_PINS. + */ +extern const uint8 boardADCPins[]; + +/** + * @brief Pins which are connected to external hardware. + * + * For example, on Maple boards, it always at least includes + * PB1 for the LED. Its length is BOARD_NR_USED_PINS. + */ +extern const uint8 boardUsedPins[]; + +/** + * @brief Generic board initialization function. + * + * This function is called before main(). It ensures that the clocks + * and peripherals are configured properly for use with wirish, then + * calls boardInit(). + * + * @see boardInit() + */ +void init(void); + +/** + * @brief Board-specific initialization function. + * + * This function is called from init() after all generic board + * initialization has been performed. Each board is required to + * define its own. + * + * @see init() + */ +extern void boardInit(void); + +/** + * @brief Test if a pin is used for a special purpose on your board. + * @param pin Pin to test + * @return true if the given pin is in boardUsedPins, and false otherwise. + * @see boardUsedPins + */ +bool boardUsesPin(uint8 pin); + +/* + * Derived and default board definitions + */ + +#define CLOCK_SPEED_MHZ CYCLES_PER_MICROSECOND +#define CLOCK_SPEED_HZ (CLOCK_SPEED_MHZ * 1000000UL) + +#ifndef SYSTICK_RELOAD_VAL +#define SYSTICK_RELOAD_VAL (1000 * CYCLES_PER_MICROSECOND - 1) +#endif + +#ifndef BOARD_BUTTON_PRESSED_LEVEL +#define BOARD_BUTTON_PRESSED_LEVEL HIGH +#endif + +/** + * @brief Does the board break out a USART/UART's RX and TX pins? + * + * BOARD_HAVE_USART(n) is nonzero iff USARTn is available (n must be + * an integer literal, 1 through 6). Also see BOARD_HAVE_USART1, ..., + * BOARD_HAVE_UART4 (sic), etc. + */ +#define BOARD_HAVE_USART(n) (defined(BOARD_USART##n##_TX_PIN) && \ + defined(BOARD_USART##n##_RX_PIN)) +/** Feature test: nonzero iff the board has USART1. */ +#define BOARD_HAVE_USART1 BOARD_HAVE_USART(1) +/** Feature test: nonzero iff the board has USART2, 0 otherwise. */ +#define BOARD_HAVE_USART2 BOARD_HAVE_USART(2) +/** Feature test: nonzero iff the board has USART3, 0 otherwise. */ +#define BOARD_HAVE_USART3 BOARD_HAVE_USART(3) +/** Feature test: nonzero iff the board has UART4, 0 otherwise. */ +#define BOARD_HAVE_UART4 BOARD_HAVE_USART(4) +/** Feature test: nonzero iff the board has UART5, 0 otherwise. */ +#define BOARD_HAVE_UART5 BOARD_HAVE_USART(5) +/** Feature test: nonzero iff the board has USART6, 0 otherwise. */ +#define BOARD_HAVE_USART6 BOARD_HAVE_USART(6) + +/** + * @brief Does the board break out a SPI peripheral's pins? + * + * BOARD_HAVE_SPI(n) is nonzero iff SPIn is available (n must be an + * integer literal: 1, 2, or 3). Also see BOARD_HAVE_SPI1, + * BOARD_HAVE_SPI2, BOARD_HAVE_SPI3. */ +#define BOARD_HAVE_SPI(n) (defined(BOARD_SPI##n##_NSS_PIN) && \ + defined(BOARD_SPI##n##_SCK_PIN) && \ + defined(BOARD_SPI##n##_MISO_PIN) && \ + defined(BOARD_SPI##n##_MOSI_PIN)) +/** Feature test: nonzero iff the board has SPI1. */ +#define BOARD_HAVE_SPI1 BOARD_HAVE_SPI(1) +/** Feature test: nonzero iff the board has SPI2. */ +#define BOARD_HAVE_SPI2 BOARD_HAVE_SPI(2) +/** Feature test: nonzero iff the board has SPI3. */ +#define BOARD_HAVE_SPI3 BOARD_HAVE_SPI(3) + +/** + * @brief Feature test: nonzero iff the board has SerialUSB. + */ + //Roger Clark. Change so that BOARD_HAVE_SERIALUSB is always true, so that it can be controller by -DSERIAL_USB +#define BOARD_HAVE_SERIALUSB 1 + +/*(defined(BOARD_USB_DISC_DEV) && defined(BOARD_USB_DISC_BIT))*/ + +#endif diff --git a/BootLoaders/Boards/stm32/cores/maple/boards_private.h b/BootLoaders/Boards/stm32/cores/maple/boards_private.h new file mode 100644 index 0000000..49867ca --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/boards_private.h @@ -0,0 +1,71 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file wirish/boards_private.h + * @author Marti Bolivar + * @brief Private board support header. + * + * This file declares chip-specific variables and functions which + * determine how init() behaves. It is not part of the public Wirish + * API, and can change without notice. + */ + +#ifndef _WIRISH_BOARDS_PRIVATE_H_ +#define _WIRISH_BOARDS_PRIVATE_H_ + +#include +#include + +/* Makes the PIN_MAP rows more human-readable. */ +#define PMAP_ROW(gpio_dev, gpio_bit, timer_dev, timer_ch, adc_dev, adc_ch) \ + { gpio_dev, timer_dev, adc_dev, gpio_bit, timer_ch, adc_ch } + +namespace wirish { + namespace priv { + + /* + * Chip-specific initialization data + */ + + extern rcc_pll_cfg w_board_pll_cfg; + extern adc_prescaler w_adc_pre; + extern adc_smp_rate w_adc_smp; + + /* + * Chip-specific initialization routines and helper functions. + */ + + void board_reset_pll(void); + void board_setup_clock_prescalers(void); + void board_setup_gpio(void); + void board_setup_usb(void); + void series_init(void); + + } +} + +#endif diff --git a/BootLoaders/Boards/stm32/cores/maple/cxxabi-compat.cpp b/BootLoaders/Boards/stm32/cores/maple/cxxabi-compat.cpp new file mode 100644 index 0000000..516b112 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/cxxabi-compat.cpp @@ -0,0 +1,6 @@ +/* We compile with nodefaultlibs, so we need to provide an error + * handler for an empty pure virtual function */ +extern "C" void __cxa_pure_virtual(void) { + while(1) + ; +} diff --git a/BootLoaders/Boards/stm32/cores/maple/ext_interrupts.cpp b/BootLoaders/Boards/stm32/cores/maple/ext_interrupts.cpp new file mode 100644 index 0000000..c78912f --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/ext_interrupts.cpp @@ -0,0 +1,90 @@ +/****************************************************************************** + * 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 + * 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/ext_interrupts.cpp + * @brief Wiring-like interface for external interrupts + */ + +#include "ext_interrupts.h" + +#include +#include + +#include "boards.h" + +static inline exti_trigger_mode exti_out_mode(ExtIntTriggerMode mode); + +void attachInterrupt(uint8 pin, voidFuncPtr handler, ExtIntTriggerMode mode) { + if (pin >= BOARD_NR_GPIO_PINS || !handler) { + return; + } + + exti_trigger_mode outMode = exti_out_mode(mode); + + exti_attach_interrupt((exti_num)(PIN_MAP[pin].gpio_bit), + gpio_exti_port(PIN_MAP[pin].gpio_device), + handler, + outMode); +} + +void attachInterrupt(uint8 pin, voidArgumentFuncPtr handler, void *arg, + ExtIntTriggerMode mode) { + if (pin >= BOARD_NR_GPIO_PINS || !handler) { + return; + } + + exti_trigger_mode outMode = exti_out_mode(mode); + + exti_attach_callback((exti_num)(PIN_MAP[pin].gpio_bit), + gpio_exti_port(PIN_MAP[pin].gpio_device), + handler, + arg, + outMode); +} + +void detachInterrupt(uint8 pin) { + if (pin >= BOARD_NR_GPIO_PINS) { + return; + } + + exti_detach_interrupt((exti_num)(PIN_MAP[pin].gpio_bit)); +} + +static inline exti_trigger_mode exti_out_mode(ExtIntTriggerMode mode) { + switch (mode) { + case RISING: + return EXTI_RISING; + case FALLING: + return EXTI_FALLING; + case CHANGE: + return EXTI_RISING_FALLING; + } + // Can't happen + ASSERT(0); + return (exti_trigger_mode)0; +} diff --git a/BootLoaders/Boards/stm32/cores/maple/ext_interrupts.h b/BootLoaders/Boards/stm32/cores/maple/ext_interrupts.h new file mode 100644 index 0000000..a406868 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/ext_interrupts.h @@ -0,0 +1,128 @@ +/****************************************************************************** + * 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/include/wirish/ext_interrupts.h + * @brief Wiring-like external interrupt prototypes and types. + */ + +#ifndef _WIRISH_EXT_INTERRUPTS_H_ +#define _WIRISH_EXT_INTERRUPTS_H_ + +#include +#include + +/** + * The kind of transition on an external pin which should trigger an + * interrupt. + */ +typedef enum ExtIntTriggerMode { + RISING, /**< To trigger an interrupt when the pin transitions LOW + to HIGH */ + FALLING, /**< To trigger an interrupt when the pin transitions + HIGH to LOW */ + CHANGE /**< To trigger an interrupt when the pin transitions from + LOW to HIGH or HIGH to LOW (i.e., when the pin + changes). */ +} ExtIntTriggerMode; + +/** + * @brief Registers an interrupt handler on a pin. + * + * The interrupt will be triggered on a given transition on the pin, + * as specified by the mode parameter. The handler runs in interrupt + * context. The new handler will replace whatever handler is + * currently registered for the pin, if any. + * + * @param pin Pin number + * @param handler Function to run upon external interrupt trigger. + * The handler should take no arguments, and have void + * return type. + * @param mode Type of transition to trigger on, e.g. falling, rising, etc. + * + * @sideeffect Registers a handler + * @see detachInterrupt() + */ +void attachInterrupt(uint8 pin, voidFuncPtr handler, ExtIntTriggerMode mode); + +/** + * @brief Registers an interrupt handler on a pin. + * + * The interrupt will be triggered on a given transition on the pin, + * as specified by the mode parameter. The handler runs in interrupt + * context. The new handler will replace whatever handler is + * currently registered for the pin, if any. + * + * @param pin Pin number + * @param handler Static class member function to run upon external interrupt + * trigger. The handler should take 1 argument and return void + * @param arg Argument that the handler will be passed when it's called. One + * use of this is to pass the specific instance of the class that + * will handle the interrupt. + * @param mode Type of transition to trigger on, e.g. falling, rising, etc. + * + * @sideeffect Registers a handler + * @see detachInterrupt() + */ +void attachInterrupt(uint8 pin, voidArgumentFuncPtr handler, void *arg, + ExtIntTriggerMode mode); + +/** + * @brief Disable any registered external interrupt. + * @param pin Maple pin number + * @sideeffect unregisters external interrupt handler + * @see attachInterrupt() + */ +void detachInterrupt(uint8 pin); + +/** + * Re-enable interrupts. + * + * Call this after noInterrupts() to re-enable interrupt handling, + * after you have finished with a timing-critical section of code. + * + * @see noInterrupts() + */ +static inline __always_inline void interrupts() { + nvic_globalirq_enable(); +} + +/** + * Disable interrupts. + * + * After calling this function, all user-programmable interrupts will + * be disabled. You can call this function before a timing-critical + * section of code, then call interrupts() to re-enable interrupt + * handling. + * + * @see interrupts() + */ +static inline __always_inline void noInterrupts() { + nvic_globalirq_disable(); +} + +#endif + diff --git a/BootLoaders/Boards/stm32/cores/maple/hooks.c b/BootLoaders/Boards/stm32/cores/maple/hooks.c new file mode 100644 index 0000000..641eabc --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/hooks.c @@ -0,0 +1,31 @@ +/* + Copyright (c) 2012 Arduino. All right reserved. + + 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. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/** + * Empty yield() hook. + * + * This function is intended to be used by library writers to build + * libraries or sketches that supports cooperative threads. + * + * Its defined as a weak symbol and it can be redefined to implement a + * real cooperative scheduler. + */ +static void __empty() { + // Empty +} +void yield(void) __attribute__ ((weak, alias("__empty"))); diff --git a/BootLoaders/Boards/stm32/cores/maple/io.h b/BootLoaders/Boards/stm32/cores/maple/io.h new file mode 100644 index 0000000..7b82285 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/io.h @@ -0,0 +1,165 @@ +/****************************************************************************** + * 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/include/wirish/io.h + * @brief Wiring-style pin I/O interface. + */ + +#ifndef _WIRISH_IO_H_ +#define _WIRISH_IO_H_ + +#include +#include + +/** + * Specifies a GPIO pin behavior. + * @see pinMode() + */ +typedef enum WiringPinMode { + OUTPUT, /**< Basic digital output: when the pin is HIGH, the + voltage is held at +3.3v (Vcc) and when it is LOW, it + is pulled down to ground. */ + + OUTPUT_OPEN_DRAIN, /**< In open drain mode, the pin indicates + "low" by accepting current flow to ground + and "high" by providing increased + impedance. An example use would be to + connect a pin to a bus line (which is pulled + up to a positive voltage by a separate + supply through a large resistor). When the + pin is high, not much current flows through + to ground and the line stays at positive + voltage; when the pin is low, the bus + "drains" to ground with a small amount of + current constantly flowing through the large + resistor from the external supply. In this + mode, no current is ever actually sourced + from the pin. */ + + INPUT, /**< Basic digital input. The pin voltage is sampled; when + it is closer to 3.3v (Vcc) the pin status is high, and + when it is closer to 0v (ground) it is low. If no + external circuit is pulling the pin voltage to high or + low, it will tend to randomly oscillate and be very + sensitive to noise (e.g., a breath of air across the pin + might cause the state to flip). */ + + INPUT_ANALOG, /**< This is a special mode for when the pin will be + used for analog (not digital) reads. Enables ADC + conversion to be performed on the voltage at the + pin. */ + + INPUT_PULLUP, /**< The state of the pin in this mode is reported + the same way as with INPUT, but the pin voltage + is gently "pulled up" towards +3.3v. This means + the state will be high unless an external device + is specifically pulling the pin down to ground, + in which case the "gentle" pull up will not + affect the state of the input. */ + + INPUT_PULLDOWN, /**< The state of the pin in this mode is reported + the same way as with INPUT, but the pin voltage + is gently "pulled down" towards 0v. This means + the state will be low unless an external device + is specifically pulling the pin up to 3.3v, in + which case the "gentle" pull down will not + affect the state of the input. */ + + INPUT_FLOATING, /**< Synonym for INPUT. */ + + PWM, /**< This is a special mode for when the pin will be used for + PWM output (a special case of digital output). */ + + PWM_OPEN_DRAIN, /**< Like PWM, except that instead of alternating + cycles of LOW and HIGH, the voltage on the pin + consists of alternating cycles of LOW and + floating (disconnected). */ +} WiringPinMode; + +/** + * Configure behavior of a GPIO pin. + * + * @param pin Number of pin to configure. + * @param mode Mode corresponding to desired pin behavior. + * @see WiringPinMode + */ +void pinMode(uint8 pin, WiringPinMode mode); + +#define HIGH 0x1 +#define LOW 0x0 + +/** + * Writes a (digital) value to a pin. The pin must have its + * mode set to OUTPUT or OUTPUT_OPEN_DRAIN. + * + * @param pin Pin to write to. + * @param value Either LOW (write a 0) or HIGH (write a 1). + * @see pinMode() + */ +void digitalWrite(uint8 pin, uint8 value); + +/** + * Read a digital value from a pin. The pin must have its mode set to + * one of INPUT, INPUT_PULLUP, and INPUT_PULLDOWN. + * + * @param pin Pin to read from. + * @return LOW or HIGH. + * @see pinMode() + */ +uint32 digitalRead(uint8 pin); + +/** + * Read an analog value from pin. This function blocks during ADC + * conversion, and has 12 bits of resolution. The pin must have its + * mode set to INPUT_ANALOG. + * + * @param pin Pin to read from. + * @return Converted voltage, in the range 0--4095, (i.e. a 12-bit ADC + * conversion). + * @see pinMode() + */ +uint16 analogRead(uint8 pin); + +/** + * Shift out a byte of data, one bit at a time. + * + * This function starts at either the most significant or least + * significant bit in a byte value, and shifts out each byte in order + * onto a data pin. After each bit is written to the data pin, a + * separate clock pin is pulsed to indicate that the new bit is + * available. + * + * @param dataPin Pin to shift data out on + * @param clockPin Pin to pulse after each bit is shifted out + * @param bitOrder Either MSBFIRST (big-endian) or LSBFIRST (little-endian). + * @param value Value to shift out + */ +void shiftOut(uint8 dataPin, uint8 clockPin, uint8 bitOrder, uint8 value); + +uint32 shiftIn( uint32 ulDataPin, uint32 ulClockPin, uint32 ulBitOrder ); + +#endif diff --git a/BootLoaders/Boards/stm32/cores/maple/itoa.c b/BootLoaders/Boards/stm32/cores/maple/itoa.c new file mode 100644 index 0000000..33efd14 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/itoa.c @@ -0,0 +1,174 @@ +/* + Copyright (c) 2011 Arduino. All right reserved. + + 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. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "itoa.h" +#include + +#ifdef __cplusplus +extern "C"{ +#endif // __cplusplus + +#if 0 +/* reverse: reverse string s in place */ +static void reverse( char s[] ) +{ + int i, j ; + char c ; + + for ( i = 0, j = strlen(s)-1 ; i < j ; i++, j-- ) + { + c = s[i] ; + s[i] = s[j] ; + s[j] = c ; + } +} + +/* itoa: convert n to characters in s */ +extern void itoa( int n, char s[] ) +{ + int i, sign ; + + if ( (sign = n) < 0 ) /* record sign */ + { + n = -n; /* make n positive */ + } + + i = 0; + do + { /* generate digits in reverse order */ + s[i++] = n % 10 + '0'; /* get next digit */ + } while ((n /= 10) > 0) ; /* delete it */ + + if (sign < 0 ) + { + s[i++] = '-'; + } + + s[i] = '\0'; + + reverse( s ) ; +} + +#else + +extern char* itoa( int value, char *string, int radix ) +{ + return ltoa( value, string, radix ) ; +} + +extern char* ltoa( long value, char *string, int radix ) +{ + char tmp[33]; + char *tp = tmp; + long i; + unsigned long v; + int sign; + char *sp; + + if ( string == NULL ) + { + return 0 ; + } + + if (radix > 36 || radix <= 1) + { + return 0 ; + } + + sign = (radix == 10 && value < 0); + if (sign) + { + v = -value; + } + else + { + v = (unsigned long)value; + } + + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+'0'; + else + *tp++ = i + 'a' - 10; + } + + sp = string; + + if (sign) + *sp++ = '-'; + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; + + return string; +} +#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 9 || \ + (__GNUC_MINOR__ == 9 && __GNUC_PATCHLEVEL__ > 2))) +extern char* utoa( unsigned value, char *string, int radix ) +#else +extern char* utoa( unsigned int value, char *string, int radix ) +#endif +{ + return ultoa( value, string, radix ) ; +} + +extern char* ultoa( unsigned long value, char *string, int radix ) +{ + char tmp[33]; + char *tp = tmp; + long i; + unsigned long v = value; + char *sp; + + if ( string == NULL ) + { + return 0; + } + + if (radix > 36 || radix <= 1) + { + return 0; + } + + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+'0'; + else + *tp++ = i + 'a' - 10; + } + + sp = string; + + + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; + + return string; +} +#endif /* 0 */ + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/BootLoaders/Boards/stm32/cores/maple/itoa.h b/BootLoaders/Boards/stm32/cores/maple/itoa.h new file mode 100644 index 0000000..9997b65 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/itoa.h @@ -0,0 +1,47 @@ +/* + Copyright (c) 2011 Arduino. All right reserved. + + 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. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef _ITOA_ +#define _ITOA_ + +#ifdef __cplusplus +extern "C"{ +#endif // __cplusplus + +#if 0 + +extern void itoa( int n, char s[] ) ; + +#else + +extern char* itoa( int value, char *string, int radix ) ; +extern char* ltoa( long value, char *string, int radix ) ; +#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 9 || \ + (__GNUC_MINOR__ == 9 && __GNUC_PATCHLEVEL__ > 2))) +extern char* utoa( unsigned value, char *string, int radix ) ; +#else +extern char* utoa( unsigned int value, char *string, int radix ) ; +#endif +extern char* ultoa( unsigned long value, char *string, int radix ) ; +#endif /* 0 */ + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif // _ITOA_ diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/adc.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/adc.c new file mode 100644 index 0000000..416cfaa --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/adc.c @@ -0,0 +1,110 @@ +/****************************************************************************** + * 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 + * 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/adc.c + * @author Marti Bolivar , + * Perry Hung + * @brief Analog to digital converter routines + */ + +#include +#include +#include + +/** + * @brief Initialize an ADC peripheral. + * + * Initializes the RCC clock line for the given peripheral. Resets + * ADC device registers. + * + * @param dev ADC peripheral to initialize + */ +void adc_init(adc_dev *dev) { + rcc_clk_enable(dev->clk_id); + rcc_reset_dev(dev->clk_id); +} + +/** + * @brief Set external event select for regular group + * @param dev ADC device + * @param event Event used to trigger the start of conversion. + * @see adc_extsel_event + */ +void adc_set_extsel(adc_dev *dev, adc_extsel_event event) { + uint32 cr2 = dev->regs->CR2; + cr2 &= ~ADC_CR2_EXTSEL; + cr2 |= event; + cr2 |= ADC_CR2_EXTTRIG; + dev->regs->CR2 = cr2; +} + +/** + * @brief Set the sample rate for all channels on an ADC device. + * + * Don't call this during conversion. + * + * @param dev adc device + * @param smp_rate sample rate to set + * @see adc_smp_rate + */ +void adc_set_sample_rate(adc_dev *dev, adc_smp_rate smp_rate) { + uint32 adc_smpr1_val = 0, adc_smpr2_val = 0; + int i; + + for (i = 0; i < 10; i++) { + if (i < 8) { + /* ADC_SMPR1 determines sample time for channels [10,17] */ + adc_smpr1_val |= smp_rate << (i * 3); + } + /* ADC_SMPR2 determines sample time for channels [0,9] */ + adc_smpr2_val |= smp_rate << (i * 3); + } + + dev->regs->SMPR1 = adc_smpr1_val; + dev->regs->SMPR2 = adc_smpr2_val; +} + +/** + * @brief Perform a single synchronous software triggered conversion on a + * channel. + * @param dev ADC device to use for reading. + * @param channel channel to convert + * @return conversion result + */ +uint16 adc_read(adc_dev *dev, uint8 channel) { + adc_reg_map *regs = dev->regs; + + adc_set_reg_seqlen(dev, 1); + + regs->SQR3 = channel; + regs->CR2 |= ADC_CR2_SWSTART; + while (!(regs->SR & ADC_SR_EOC)) + ; + + return (uint16)(regs->DR & ADC_DR_DATA); +} diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/adc_f1.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/adc_f1.c new file mode 100644 index 0000000..d099f6d --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/adc_f1.c @@ -0,0 +1,216 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * Copyright (c) 2010 Perry Hung. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/adc.c + * @author Marti Bolivar , + * Perry Hung + * @brief STM32F1 ADC support. + */ + +#include +#include +#include //Added by bubulindo. + +/* + * Devices + */ + +adc_dev adc1 = { + .regs = ADC1_BASE, + .clk_id = RCC_ADC1, + .handlers = {[3]=0}, //added by bubulindo. EOC, JEOC, AWD + .irq_num = NVIC_ADC_1_2, +}; +/** ADC1 device. */ +adc_dev *ADC1 = &adc1; + +adc_dev adc2 = { + .regs = ADC2_BASE, + .clk_id = RCC_ADC2, +}; +/** ADC2 device. */ +adc_dev *ADC2 = &adc2; + +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) +adc_dev adc3 = { + .regs = ADC3_BASE, + .clk_id = RCC_ADC3, + .handlers = {[3]=0}, //added by bubulindo. EOC, JEOC, AWD + .irq_num = NVIC_ADC3,//added by bubulindo. +}; +/** ADC3 device. */ +adc_dev *ADC3 = &adc3; +#endif + + +/* + adc irq routine. + Added by bubulindo. +*/ +void __irq_adc() { + //get status + uint32 adc_sr = ADC1->regs->SR; +//End Of Conversion + if (adc_sr & (1U << ADC_SR_EOC_BIT)) { + ADC1->regs->SR &= ~(1<handlers[ADC_EOC]; + if (handler) { + handler(); + } + } +//Injected End Of Conversion + if (adc_sr & (1U << ADC_SR_JEOC_BIT)) { + ADC1->regs->SR &= ~(1<handlers[ADC_JEOC]; + if (handler) { + handler(); + } + } +//Analog Watchdog + if (adc_sr & (1U << ADC_SR_AWD_BIT)) { + ADC1->regs->SR &= ~(1<handlers[ADC_AWD]; + if (handler) { + handler(); + } + } +};//end of adc irq + + +/* + ADC3 IRQ handler. + added by bubulindo +*/ +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) +void __irq_adc3() { + //get status + uint32 adc_sr = ADC3->regs->SR; +//End Of Conversion + if (adc_sr & (1U << ADC_SR_EOC_BIT)) { + ADC3->regs->SR &= ~(1<handlers[ADC_EOC]; + if (handler) { + handler(); + } + } +//Injected End Of Conversion + if (adc_sr & (1U << ADC_SR_JEOC_BIT)) { + ADC3->regs->SR &= ~(1<handlers[ADC_JEOC]; + if (handler) { + handler(); + } + } +//Analog Watchdog + if (adc_sr & (1U << ADC_SR_AWD_BIT)) { + ADC3->regs->SR &= ~(1<handlers[ADC_AWD]; + if (handler) { + handler(); + } + } +};//end of ADC3 irq +#endif + +/* + enable interrupts on the ADC: + use ADC_EOC, ADC_JEOC, ADC_AWD + This will set up the interrupt bit in the ADC as well as in the NVIC. + added by bubulindo +*/ +void adc_enable_irq(adc_dev* dev, uint8 interrupt) {//ADC1 for now. + dev->regs->CR1 |= (1U<<(interrupt +ADC_CR1_EOCIE_BIT)); + nvic_irq_enable(dev->irq_num); + } + +/* + attach interrupt functionality for ADC + use ADC_EOC, ADC_JEOC, ADC_AWD + added by bubulindo +*/ + +void adc_attach_interrupt(adc_dev *dev, + uint8 interrupt, + voidFuncPtr handler) { + dev->handlers[interrupt] = handler; + adc_enable_irq(dev, interrupt); + //enable_irq(dev, interrupt); //I need to create this function. to enable NVIC + // nvic_irq_enable() + } + +/* + * STM32F1 routines + */ + +/** + * @brief Calibrate an ADC peripheral + * + * Availability: STM32F1. + * + * @param dev adc device + */ +void adc_calibrate(adc_dev *dev) { + __io uint32 *rstcal_bit = bb_perip(&(dev->regs->CR2), 3); + __io uint32 *cal_bit = bb_perip(&(dev->regs->CR2), 2); + + *rstcal_bit = 1; + while (*rstcal_bit) + ; + + *cal_bit = 1; + while (*cal_bit) + ; +} + +/* + * Common routines + */ + +void adc_set_prescaler(adc_prescaler pre) { + rcc_set_prescaler(RCC_PRESCALER_ADC, (uint32)pre); +} + +void adc_foreach(void (*fn)(adc_dev*)) { + fn(ADC1); + fn(ADC2); +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) + fn(ADC3); +#endif +} + +void adc_config_gpio(adc_dev *ignored, gpio_dev *gdev, uint8 bit) { + gpio_set_mode(gdev, bit, GPIO_INPUT_ANALOG); +} + +void adc_enable_single_swstart(adc_dev *dev) { + adc_init(dev); + adc_set_extsel(dev, ADC_SWSTART); + adc_set_exttrig(dev, 1); + adc_enable(dev); + adc_calibrate(dev); +} diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/bkp_f1.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/bkp_f1.c new file mode 100644 index 0000000..01ad419 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/bkp_f1.c @@ -0,0 +1,129 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/bkp.c + * @brief STM32F1 Backup register support. + */ + +#include +#include +#include +#include + +static inline __io uint32* data_register(uint8 reg); + +bkp_dev bkp = { + .regs = BKP_BASE, +}; +/** Backup device. */ +const bkp_dev *BKP = &bkp; + +/** + * @brief Initialize backup interface. + * + * Enables the power and backup interface clocks, and resets the + * backup device. + */ +void bkp_init(void) { + /* Don't call pwr_init(), or you'll reset the device. We just + * need the clock. */ + rcc_clk_enable(RCC_PWR); + rcc_clk_enable(RCC_BKP); + rcc_reset_dev(RCC_BKP); +} + +/** + * Enable write access to the backup registers. Backup interface must + * be initialized for subsequent register writes to work. + * @see bkp_init() + */ +void bkp_enable_writes(void) { + *bb_perip(&PWR_BASE->CR, PWR_CR_DBP_BIT) = 1; +} + +/** + * Disable write access to the backup registers. + */ +void bkp_disable_writes(void) { + *bb_perip(&PWR_BASE->CR, PWR_CR_DBP_BIT) = 0; +} + +/** + * Read a value from given backup data register. + * @param reg Data register to read, from 1 to BKP_NR_DATA_REGS (10 on + * medium-density devices, 42 on high-density devices). + */ +uint16 bkp_read(uint8 reg) { + __io uint32* dr = data_register(reg); + if (!dr) { + ASSERT(0); /* nonexistent register */ + return 0; + } + return (uint16)*dr; +} + +/** + * @brief Write a value to given data register. + * + * Write access to backup registers must be enabled. + * + * @param reg Data register to write, from 1 to BKP_NR_DATA_REGS (10 + * on medium-density devices, 42 on high-density devices). + * @param val Value to write into the register. + * @see bkp_enable_writes() + */ +void bkp_write(uint8 reg, uint16 val) { + __io uint32* dr = data_register(reg); + if (!dr) { + ASSERT(0); /* nonexistent register */ + return; + } + *dr = (uint32)val; +} + +/* + * Data register memory layout is not contiguous. It's split up from + * 1--NR_LOW_DRS, beginning at BKP_BASE->DR1, through to + * (NR_LOW_DRS+1)--BKP_NR_DATA_REGS, beginning at BKP_BASE->DR11. + */ +#define NR_LOW_DRS 10 + +static inline __io uint32* data_register(uint8 reg) { + if (reg < 1 || reg > BKP_NR_DATA_REGS) { + return 0; + } + +#if BKP_NR_DATA_REGS == NR_LOW_DRS + return (uint32*)BKP_BASE + reg; +#else + if (reg <= NR_LOW_DRS) { + return (uint32*)BKP_BASE + reg; + } else { + return (uint32*)&(BKP_BASE->DR11) + (reg - NR_LOW_DRS - 1); + } +#endif +} diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/dac.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/dac.c new file mode 100644 index 0000000..d802d2b --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/dac.c @@ -0,0 +1,120 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Bryan Newbold. + * Copyright (c) 2011, 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/dac.c + * @brief Digital to analog converter support. + */ + +#include +#include +#include + +#if STM32_HAVE_DAC +dac_dev dac = { + .regs = DAC_BASE, +}; +const dac_dev *DAC = &dac; +#endif + +/** + * @brief Initialize the digital to analog converter + * @param dev DAC device + * @param flags Flags: + * DAC_CH1: Enable channel 1 + * DAC_CH2: Enable channel 2 + * @sideeffect May set PA4 or PA5 to INPUT_ANALOG + */ +void dac_init(const dac_dev *dev, uint32 flags) { + /* First turn on the clock */ + rcc_clk_enable(RCC_DAC); + rcc_reset_dev(RCC_DAC); + + if (flags & DAC_CH1) { + dac_enable_channel(dev, 1); + } + + if (flags & DAC_CH2) { + dac_enable_channel(dev, 2); + } +} + +/** + * @brief Write a 12-bit value to the DAC to output + * @param dev DAC device + * @param channel channel to select (1 or 2) + * @param val value to write + */ +void dac_write_channel(const dac_dev *dev, uint8 channel, uint16 val) { + switch(channel) { + case 1: + dev->regs->DHR12R1 = DAC_DHR12R1_DACC1DHR & val; + break; + case 2: + dev->regs->DHR12R2 = DAC_DHR12R2_DACC2DHR & val; + break; + } +} + +/** + * @brief Enable a DAC channel + * @param dev DAC device + * @param channel channel to enable, either 1 or 2 + * @sideeffect May change pin mode of PA4 or PA5 + */ +void dac_enable_channel(const dac_dev *dev, uint8 channel) { + /* + * Setup ANALOG mode on PA4 and PA5. This mapping is consistent + * across all supported STM32s with a DAC. + */ + switch (channel) { + case 1: + gpio_set_mode(GPIOA, 4, GPIO_MODE_ANALOG); + dev->regs->CR |= DAC_CR_EN1; + break; + case 2: + gpio_set_mode(GPIOA, 5, GPIO_MODE_ANALOG); + dev->regs->CR |= DAC_CR_EN2; + break; + } +} + +/** + * @brief Disable a DAC channel + * @param dev DAC device + * @param channel channel to disable, either 1 or 2 + */ +void dac_disable_channel(const dac_dev *dev, uint8 channel) { + switch (channel) { + case 1: + dev->regs->CR &= ~DAC_CR_EN1; + break; + case 2: + dev->regs->CR &= ~DAC_CR_EN2; + break; + } +} diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/dma.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/dma.c new file mode 100644 index 0000000..d13de10 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/dma.c @@ -0,0 +1,82 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Michael Hope. + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/dma.c + * @author Marti Bolivar ; + * Original implementation by Michael Hope + * @brief Portable DMA routines. + */ + +#include +#include "dma_private.h" +#include "stm32_private.h" + +/* + * Convenience routines + */ + +/** + * @brief Initialize a DMA device. + * @param dev Device to initialize. + */ +void dma_init(dma_dev *dev) { + rcc_clk_enable(dev->clk_id); +} + +/* + * Private API + */ + +enum dma_atype _dma_addr_type(__io void *addr) { + switch (stm32_block_purpose((void*)addr)) { + /* Notice we're treating the code block as memory here. That's + * correct for addresses in Flash and in [0x0, 0x7FFFFFF] + * (provided that those addresses are aliased to Flash, SRAM, or + * FSMC, depending on BOOT[01] and possibly SYSCFG_MEMRMP). It's + * not correct for other addresses in the code block, but those + * will (hopefully) just fail-fast with transfer or bus errors. If + * lots of people get confused, it might be worth being more + * careful here. */ + case STM32_BLOCK_CODE: /* Fall through */ + case STM32_BLOCK_SRAM: /* ... */ + case STM32_BLOCK_FSMC_1_2: /* ... */ + case STM32_BLOCK_FSMC_3_4: + return DMA_ATYPE_MEM; + case STM32_BLOCK_PERIPH: + return DMA_ATYPE_PER; + case STM32_BLOCK_FSMC_REG: /* Fall through */ + /* Is this right? I can't think of a reason to DMA into or out + * of the FSMC registers. [mbolivar] */ + case STM32_BLOCK_UNUSED: /* ... */ + case STM32_BLOCK_CORTEX_INTERNAL: /* ... */ + return DMA_ATYPE_OTHER; + default: + ASSERT(0); /* Can't happen */ + return DMA_ATYPE_OTHER; + } +} diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/dma_f1.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/dma_f1.c new file mode 100644 index 0000000..c7c3c00 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/dma_f1.c @@ -0,0 +1,412 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Michael Hope. + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/dma.c + * @author Marti Bolivar ; + * Original implementation by Michael Hope + * @brief STM32F1 DMA support. + */ + +#include +#include + +/* Hack to ensure inlining in dma_irq_handler() */ +#define DMA_GET_HANDLER(dev, tube) (dev->handlers[tube - 1].handler) +#include "dma_private.h" + +/* + * Devices + */ + +static dma_dev dma1 = { + .regs = DMA1_BASE, + .clk_id = RCC_DMA1, + .handlers = {{ .handler = NULL, .irq_line = NVIC_DMA_CH1 }, + { .handler = NULL, .irq_line = NVIC_DMA_CH2 }, + { .handler = NULL, .irq_line = NVIC_DMA_CH3 }, + { .handler = NULL, .irq_line = NVIC_DMA_CH4 }, + { .handler = NULL, .irq_line = NVIC_DMA_CH5 }, + { .handler = NULL, .irq_line = NVIC_DMA_CH6 }, + { .handler = NULL, .irq_line = NVIC_DMA_CH7 }}, +}; +/** STM32F1 DMA1 device */ +dma_dev *DMA1 = &dma1; + +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) +static dma_dev dma2 = { + .regs = DMA2_BASE, + .clk_id = RCC_DMA2, + .handlers = {{ .handler = NULL, .irq_line = NVIC_DMA2_CH1 }, + { .handler = NULL, .irq_line = NVIC_DMA2_CH2 }, + { .handler = NULL, .irq_line = NVIC_DMA2_CH3 }, + { .handler = NULL, .irq_line = NVIC_DMA2_CH_4_5 }, + { .handler = NULL, .irq_line = NVIC_DMA2_CH_4_5 }}, /* !@#$ */ +}; +/** STM32F1 DMA2 device */ +dma_dev *DMA2 = &dma2; +#endif + +/* + * Auxiliary routines + */ + +/* Can channel serve cfg->tube_req_src? */ +static int cfg_req_ok(dma_channel channel, dma_tube_config *cfg) { + return (cfg->tube_req_src & 0x7) == channel; +} + +/* Can dev serve cfg->tube_req_src? */ +static int cfg_dev_ok(dma_dev *dev, dma_tube_config *cfg) { + return (rcc_clk_id)(cfg->tube_req_src >> 3) == dev->clk_id; +} + +/* Is addr acceptable for use as DMA src/dst? */ +static int cfg_mem_ok(__io void *addr) { + enum dma_atype atype = _dma_addr_type(addr); + return atype == DMA_ATYPE_MEM || atype == DMA_ATYPE_PER; +} + +/* Is the direction implied by src->dst supported? */ +static int cfg_dir_ok(dma_tube_config *cfg) { + /* We can't do peripheral->peripheral transfers. */ + return ((_dma_addr_type(cfg->tube_src) == DMA_ATYPE_MEM) || + (_dma_addr_type(cfg->tube_dst) == DMA_ATYPE_MEM)); +} + +static int preconfig_check(dma_dev *dev, dma_channel channel, + dma_tube_config *cfg) { + if (!cfg_req_ok(channel, cfg)) { + return -DMA_TUBE_CFG_EREQ; + } + if (cfg->tube_nr_xfers > 65535) { + return -DMA_TUBE_CFG_ENDATA; + } + if (!cfg_dev_ok(dev, cfg)) { + return -DMA_TUBE_CFG_EDEV; + } + if (!cfg_mem_ok(cfg->tube_src)) { + return -DMA_TUBE_CFG_ESRC; + } + if (!cfg_mem_ok(cfg->tube_dst)) { + return -DMA_TUBE_CFG_EDST; + } + if (!cfg_dir_ok(cfg)) { + return -DMA_TUBE_CFG_EDIR; + } + return DMA_TUBE_CFG_SUCCESS; +} + +static inline void set_ccr(dma_tube_reg_map *chregs, + dma_xfer_size msize, int minc, + dma_xfer_size psize, int pinc, + uint32 other_flags) { + chregs->CCR = ((msize << 10) | (psize << 8) | + (minc ? DMA_CCR_MINC : 0) | (pinc ? DMA_CCR_PINC : 0) | + other_flags); +} + +static inline uint32 cfg_ccr_flags(unsigned tube_flags) { + /* DMA_CFG_SRC_INC and DMA_CFG_DST_INC are special */ + return tube_flags & ~(DMA_CFG_SRC_INC | DMA_CFG_DST_INC); +} + +/* Configure chregs according to cfg, where cfg->tube_dst is peripheral. */ +static int config_to_per(dma_tube_reg_map *chregs, dma_tube_config *cfg) { + /* Check that ->tube_src is memory (if it's anything else, we + * shouldn't have been called). */ + ASSERT(_dma_addr_type(cfg->tube_src) == DMA_ATYPE_MEM); + + set_ccr(chregs, + cfg->tube_src_size, cfg->tube_flags & DMA_CFG_SRC_INC, + cfg->tube_dst_size, cfg->tube_flags & DMA_CFG_DST_INC, + (cfg_ccr_flags(cfg->tube_flags) | DMA_CCR_DIR_FROM_MEM)); + chregs->CNDTR = cfg->tube_nr_xfers; + chregs->CMAR = (uint32)cfg->tube_src; + chregs->CPAR = (uint32)cfg->tube_dst; + return DMA_TUBE_CFG_SUCCESS; +} + +/* Configure chregs according to cfg, where cfg->tube_dst is memory. */ +static int config_to_mem(dma_tube_reg_map *chregs, dma_tube_config *cfg) { + uint32 mem2mem; + + if ((_dma_addr_type(cfg->tube_src) == DMA_ATYPE_MEM) && + (cfg->tube_flags & DMA_CFG_CIRC)) { + /* Can't do mem-to-mem and circular mode */ + return -DMA_TUBE_CFG_ECFG; + } + + mem2mem = (_dma_addr_type(cfg->tube_src) == DMA_ATYPE_MEM ? + DMA_CCR_MEM2MEM : 0); + set_ccr(chregs, + cfg->tube_dst_size, cfg->tube_flags & DMA_CFG_DST_INC, + cfg->tube_src_size, cfg->tube_flags & DMA_CFG_SRC_INC, + (cfg_ccr_flags(cfg->tube_flags) | + DMA_CCR_DIR_FROM_PER | + mem2mem)); + chregs->CNDTR = cfg->tube_nr_xfers; + chregs->CMAR = (uint32)cfg->tube_dst; + chregs->CPAR = (uint32)cfg->tube_src; + return DMA_TUBE_CFG_SUCCESS; +} + +/* + * Routines + */ + +int dma_tube_cfg(dma_dev *dev, dma_channel channel, dma_tube_config *cfg) { + dma_tube_reg_map *chregs; + int ret = preconfig_check(dev, channel, cfg); + + if (ret < 0) { + return ret; + } + + dma_disable(dev, channel); /* Must disable before reconfiguring */ + dma_clear_isr_bits(dev, channel); /* For sanity and consistency + * with STM32F2. */ + + chregs = dma_tube_regs(dev, channel); + switch (_dma_addr_type(cfg->tube_dst)) { + case DMA_ATYPE_PER: + ret = config_to_per(chregs, cfg); + break; + case DMA_ATYPE_MEM: + ret = config_to_mem(chregs, cfg); + break; + default: + /* Can't happen */ + ASSERT(0); + return -DMA_TUBE_CFG_ECFG; + } + if (ret < 0) { + return ret; + } + chregs->CNDTR = cfg->tube_nr_xfers; + return DMA_TUBE_CFG_SUCCESS; +} + +void dma_set_priority(dma_dev *dev, + dma_channel channel, + dma_priority priority) { + dma_channel_reg_map *channel_regs; + uint32 ccr; + + ASSERT_FAULT(!dma_is_channel_enabled(dev, channel)); + + channel_regs = dma_channel_regs(dev, channel); + ccr = channel_regs->CCR; + ccr &= ~DMA_CCR_PL; + ccr |= (priority << 12); + channel_regs->CCR = ccr; +} + +void dma_set_num_transfers(dma_dev *dev, + dma_channel channel, + uint16 num_transfers) { + dma_channel_reg_map *channel_regs; + + ASSERT_FAULT(!dma_is_channel_enabled(dev, channel)); + + channel_regs = dma_channel_regs(dev, channel); + channel_regs->CNDTR = num_transfers; +} + +void dma_attach_interrupt(dma_dev *dev, dma_channel channel, + void (*handler)(void)) { + DMA_GET_HANDLER(dev, channel) = handler; + nvic_irq_enable(dev->handlers[channel - 1].irq_line); +} + +void dma_detach_interrupt(dma_dev *dev, dma_channel channel) { + /* Don't use nvic_irq_disable()! Think about DMA2 channels 4 and 5. */ + dma_channel_regs(dev, channel)->CCR &= ~0xF; + DMA_GET_HANDLER(dev, channel) = NULL; +} + +void dma_enable(dma_dev *dev, dma_channel channel) { + dma_channel_reg_map *chan_regs = dma_channel_regs(dev, channel); + bb_peri_set_bit(&chan_regs->CCR, DMA_CCR_EN_BIT, 1); +} + +void dma_disable(dma_dev *dev, dma_channel channel) { + dma_channel_reg_map *chan_regs = dma_channel_regs(dev, channel); + bb_peri_set_bit(&chan_regs->CCR, DMA_CCR_EN_BIT, 0); +} + +dma_irq_cause dma_get_irq_cause(dma_dev *dev, dma_channel channel) { + /* Grab and clear the ISR bits. */ + uint8 status_bits = dma_get_isr_bits(dev, channel); + dma_clear_isr_bits(dev, channel); + + /* If the channel global interrupt flag is cleared, then + * something's very wrong. */ + ASSERT(status_bits & 0x1); + /* If GIF is set, then some other flag should be set, barring + * something unexpected (e.g. the user making an unforeseen IFCR + * write). */ + ASSERT(status_bits != 0x1); + + /* ISR flags get set even if the corresponding interrupt enable + * bits in the channel's configuration register are cleared, so we + * can't use a switch here. + * + * Don't change the order of these if statements. */ + if (status_bits & 0x8) { + return DMA_TRANSFER_ERROR; + } else if (status_bits & 0x2) { + return DMA_TRANSFER_COMPLETE; + } else if (status_bits & 0x4) { + return DMA_TRANSFER_HALF_COMPLETE; + } + + /* If we get here, one of our assumptions has been violated, but + * the debug level is too low for the above ASSERTs() to have had + * any effect. In order to fail fast, mimic the DMA controller's + * behavior when an error occurs. */ + dma_disable(dev, channel); + return DMA_TRANSFER_ERROR; +} + +void dma_set_mem_addr(dma_dev *dev, dma_channel channel, __io void *addr) { + dma_channel_reg_map *chan_regs; + + ASSERT_FAULT(!dma_is_channel_enabled(dev, channel)); + + chan_regs = dma_channel_regs(dev, channel); + chan_regs->CMAR = (uint32)addr; +} + +void dma_set_per_addr(dma_dev *dev, dma_channel channel, __io void *addr) { + dma_channel_reg_map *chan_regs; + + ASSERT_FAULT(!dma_is_channel_enabled(dev, channel)); + + chan_regs = dma_channel_regs(dev, channel); + chan_regs->CPAR = (uint32)addr; +} + +/** + * @brief Deprecated. Use dma_tube_cfg() instead. + * + * Set up a DMA transfer. + * + * The channel will be disabled before being reconfigured. The + * transfer will have low priority by default. You may choose another + * priority before the transfer begins using dma_set_priority(), as + * well as performing any other configuration you desire. When the + * channel is configured to your liking, enable it using dma_enable(). + * + * @param dev DMA device. + * @param channel DMA channel. + * @param peripheral_address Base address of peripheral data register + * involved in the transfer. + * @param peripheral_size Peripheral data transfer size. + * @param memory_address Base memory address involved in the transfer. + * @param memory_size Memory data transfer size. + * @param mode Logical OR of dma_mode_flags + * + * @see dma_tube_cfg() + * + * @sideeffect Disables the given DMA channel. + * @see dma_xfer_size + * @see dma_mode_flags + * @see dma_set_num_transfers() + * @see dma_set_priority() + * @see dma_attach_interrupt() + * @see dma_enable() + */ +void dma_setup_transfer(dma_dev *dev, + dma_channel channel, + __io void *peripheral_address, + dma_xfer_size peripheral_size, + __io void *memory_address, + dma_xfer_size memory_size, + uint32 mode) { + dma_channel_reg_map *channel_regs = dma_channel_regs(dev, channel); + + dma_disable(dev, channel); /* can't write to CMAR/CPAR otherwise */ + channel_regs->CCR = (memory_size << 10) | (peripheral_size << 8) | mode; + channel_regs->CMAR = (uint32)memory_address; + channel_regs->CPAR = (uint32)peripheral_address; +} + +/* + * IRQ handlers + */ + +void __irq_dma1_channel1(void) { + dma_irq_handler(DMA1, DMA_CH1); +} + +void __irq_dma1_channel2(void) { + dma_irq_handler(DMA1, DMA_CH2); +} + +void __irq_dma1_channel3(void) { + dma_irq_handler(DMA1, DMA_CH3); +} + +void __irq_dma1_channel4(void) { + dma_irq_handler(DMA1, DMA_CH4); +} + +void __irq_dma1_channel5(void) { + dma_irq_handler(DMA1, DMA_CH5); +} + +void __irq_dma1_channel6(void) { + dma_irq_handler(DMA1, DMA_CH6); +} + +void __irq_dma1_channel7(void) { + dma_irq_handler(DMA1, DMA_CH7); +} + +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) +void __irq_dma2_channel1(void) { + dma_irq_handler(DMA2, DMA_CH1); +} + +void __irq_dma2_channel2(void) { + dma_irq_handler(DMA2, DMA_CH2); +} + +void __irq_dma2_channel3(void) { + dma_irq_handler(DMA2, DMA_CH3); +} + +void __irq_dma2_channel4_5(void) { + if ((DMA2_BASE->CCR4 & DMA_CCR_EN) && (DMA2_BASE->ISR & DMA_ISR_GIF4)) { + dma_irq_handler(DMA2, DMA_CH4); + } + if ((DMA2_BASE->CCR5 & DMA_CCR_EN) && (DMA2_BASE->ISR & DMA_ISR_GIF5)) { + dma_irq_handler(DMA2, DMA_CH5); + } +} +#endif diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/exc.S b/BootLoaders/Boards/stm32/cores/maple/libmaple/exc.S new file mode 100644 index 0000000..7631e48 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/exc.S @@ -0,0 +1,101 @@ +/* ***************************************************************************** + * 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. + * ****************************************************************************/ + +# On an exception, push a fake stack thread mode stack frame and redirect +# thread execution to a thread mode error handler + +# From RM008: +# The SP is decremented by eight words by the completion of the stack push. +# Figure 5-1 shows the contents of the stack after an exception pre-empts the +# current program flow. +# +# Old SP--> +# xPSR +# PC +# LR +# r12 +# r3 +# r2 +# r1 +# SP--> r0 + +.text +.globl __exc_hardfault +.globl __exc_nmi +.globl __exc_hardfault +.globl __exc_memmanage +.globl __exc_busfault +.globl __exc_usagefault + +.code 16 +.thumb_func +__exc_nmi: + mov r0, #1 + b __default_exc + +.thumb_func +__exc_hardfault: + mov r0, #2 + b __default_exc + +.thumb_func +__exc_memmanage: + mov r0, #3 + b __default_exc + +.thumb_func +__exc_busfault: + mov r0, #4 + b __default_exc + +.thumb_func +__exc_usagefault: + mov r0, #5 + b __default_exc + +.thumb_func +__default_exc: + ldr r2, NVIC_CCR @ Enable returning to thread mode even if there are + mov r1 ,#1 @ pending exceptions. See flag NONEBASETHRDENA. + str r1, [r2] + cpsid i @ Disable global interrupts + ldr r2, SYSTICK_CSR @ Disable systick handler + mov r1, #0 + str r1, [r2] + ldr r1, CPSR_MASK @ Set default CPSR + push {r1} + ldr r1, TARGET_PC @ Set target pc + push {r1} + sub sp, sp, #24 @ Don't care + ldr r1, EXC_RETURN @ Return to thread mode + mov lr, r1 + bx lr @ Exception exit + +.align 4 +CPSR_MASK: .word 0x61000000 +EXC_RETURN: .word 0xFFFFFFF9 +TARGET_PC: .word __error +NVIC_CCR: .word 0xE000ED14 @ NVIC configuration control register +SYSTICK_CSR: .word 0xE000E010 @ Systick control register + diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/exti.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/exti.c new file mode 100644 index 0000000..402bec6 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/exti.c @@ -0,0 +1,292 @@ +/****************************************************************************** + * 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 + * 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/exti.c + * @brief External interrupt control routines + */ + +#include +#include +#include +#include + +static inline void dispatch_single_exti(uint32 exti_num); +static inline void dispatch_extis(uint32 start, uint32 stop); + +/* + * Internal state + */ + +typedef struct exti_channel { + void (*handler)(void *); + void *arg; +} exti_channel; + +static exti_channel exti_channels[] = { + { .handler = NULL, .arg = NULL }, // EXTI0 + { .handler = NULL, .arg = NULL }, // EXTI1 + { .handler = NULL, .arg = NULL }, // EXTI2 + { .handler = NULL, .arg = NULL }, // EXTI3 + { .handler = NULL, .arg = NULL }, // EXTI4 + { .handler = NULL, .arg = NULL }, // EXTI5 + { .handler = NULL, .arg = NULL }, // EXTI6 + { .handler = NULL, .arg = NULL }, // EXTI7 + { .handler = NULL, .arg = NULL }, // EXTI8 + { .handler = NULL, .arg = NULL }, // EXTI9 + { .handler = NULL, .arg = NULL }, // EXTI10 + { .handler = NULL, .arg = NULL }, // EXTI11 + { .handler = NULL, .arg = NULL }, // EXTI12 + { .handler = NULL, .arg = NULL }, // EXTI13 + { .handler = NULL, .arg = NULL }, // EXTI14 + { .handler = NULL, .arg = NULL }, // EXTI15 +}; + +/* + * Portable routines + */ + +/** + * @brief Register a handler to run upon external interrupt. + * + * This function assumes that the interrupt request corresponding to + * the given external interrupt is masked. + * + * @param num External interrupt line number. + * @param port Port to use as source input for external interrupt. + * @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 exti_num + * @see exti_cfg + * @see voidFuncPtr + * @see exti_trigger_mode + */ +void exti_attach_interrupt(exti_num num, + exti_cfg port, + voidFuncPtr handler, + exti_trigger_mode mode) { + // Call callback version with arg being null + exti_attach_callback(num, port, (voidArgumentFuncPtr)handler, NULL, mode); +} + +/** + * @brief Register a handler with an argument to run upon external interrupt. + * + * This function assumes that the interrupt request corresponding to + * the given external interrupt is masked. + * + * @param num External interrupt line number. + * @param port Port to use as source input for external interrupt. + * @param handler Function handler to execute when interrupt is triggered. + * @param arg Argument to pass to the interrupt handler. + * @param mode Type of transition to trigger on, one of: + * EXTI_RISING, EXTI_FALLING, EXTI_RISING_FALLING. + * @see exti_num + * @see exti_cfg + * @see voidFuncPtr + * @see exti_trigger_mode + */ +void exti_attach_callback(exti_num num, + exti_cfg port, + voidArgumentFuncPtr handler, + void *arg, + exti_trigger_mode mode) { + ASSERT(handler); + + /* Register the handler */ + exti_channels[num].handler = handler; + exti_channels[num].arg = arg; + + /* Set trigger mode */ + switch (mode) { + case EXTI_RISING: + bb_peri_set_bit(&EXTI_BASE->RTSR, num, 1); + break; + case EXTI_FALLING: + bb_peri_set_bit(&EXTI_BASE->FTSR, num, 1); + break; + case EXTI_RISING_FALLING: + bb_peri_set_bit(&EXTI_BASE->RTSR, num, 1); + bb_peri_set_bit(&EXTI_BASE->FTSR, num, 1); + break; + } + + /* 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); + + /* Enable the interrupt line */ + switch(num) + { + case EXTI0: + nvic_irq_enable(NVIC_EXTI0); + break; + case EXTI1: + nvic_irq_enable(NVIC_EXTI1); + break; + case EXTI2: + nvic_irq_enable(NVIC_EXTI2); + break; + case EXTI3: + nvic_irq_enable(NVIC_EXTI3); + break; + case EXTI4: + nvic_irq_enable(NVIC_EXTI4); + break; + case EXTI5: + case EXTI6: + case EXTI7: + case EXTI8: + case EXTI9: + nvic_irq_enable(NVIC_EXTI_9_5); + break; + case EXTI10: + case EXTI11: + case EXTI12: + case EXTI13: + case EXTI14: + case EXTI15: + nvic_irq_enable(NVIC_EXTI_15_10); + break; + } +} + +/** + * @brief Unregister an external interrupt handler + * @param num External interrupt line to disable. + * @see exti_num + */ +void exti_detach_interrupt(exti_num num) { + /* First, mask the interrupt request */ + bb_peri_set_bit(&EXTI_BASE->IMR, num, 0); + + /* Then, clear the trigger selection registers */ + bb_peri_set_bit(&EXTI_BASE->FTSR, num, 0); + bb_peri_set_bit(&EXTI_BASE->RTSR, num, 0); + + /* Finally, unregister the user's handler */ + exti_channels[num].handler = NULL; + exti_channels[num].arg = NULL; +} + +/* + * 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(EXTI0); +} + +void __irq_exti1(void) { + dispatch_single_exti(EXTI1); +} + +void __irq_exti2(void) { + dispatch_single_exti(EXTI2); +} + +void __irq_exti3(void) { + dispatch_single_exti(EXTI3); +} + +void __irq_exti4(void) { + dispatch_single_exti(EXTI4); +} + +void __irq_exti9_5(void) { + dispatch_extis(5, 9); +} + +void __irq_exti15_10(void) { + dispatch_extis(10, 15); +} + +/* + * Auxiliary functions + */ + +/* Clear the pending bits for EXTIs whose bits are set in exti_msk. + * + * If a pending bit is cleared as the last instruction in an ISR, it + * 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 __always_inline void clear_pending_msk(uint32 exti_msk) { + EXTI_BASE->PR = exti_msk; + asm volatile("nop"); + asm volatile("nop"); +} + +/* This dispatch routine is for non-multiplexed EXTI lines only; i.e., + * it doesn't check EXTI_PR. */ +static inline __always_inline void dispatch_single_exti(uint32 exti) { + voidArgumentFuncPtr handler = exti_channels[exti].handler; + + if (!handler) { + return; + } + + handler(exti_channels[exti].arg); + clear_pending_msk(1U << exti); +} + +/* Dispatch routine for EXTIs which share an IRQ. */ +static inline __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 = (1U << exti); + if (pr & eb) { + voidArgumentFuncPtr handler = exti_channels[exti].handler; + if (handler) { + handler(exti_channels[exti].arg); + handled_msk |= eb; + } + } + } + + /* Clear the pending bits for handled EXTIs. */ + clear_pending_msk(handled_msk); +} diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/exti_f1.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/exti_f1.c new file mode 100644 index 0000000..b9ff401 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/exti_f1.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/BootLoaders/Boards/stm32/cores/maple/libmaple/flash.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/flash.c new file mode 100644 index 0000000..c57bbbf --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/flash.c @@ -0,0 +1,55 @@ +/****************************************************************************** + * 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 + * 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/flash.c + * @brief Flash management functions + */ + +#include +#include + +/** + * @brief Set flash wait states + * + * Note that not all wait states are available on every MCU. See the + * Flash programming manual for your MCU for restrictions on the + * allowed value of wait_states for a given system clock (SYSCLK) + * frequency. + * + * @param wait_states number of wait states (one of + * FLASH_WAIT_STATE_0, FLASH_WAIT_STATE_1, + * ..., FLASH_WAIT_STATE_7). + */ +void flash_set_latency(uint32 wait_states) { + uint32 val = FLASH_BASE->ACR; + + val &= ~FLASH_ACR_LATENCY; + val |= wait_states; + + FLASH_BASE->ACR = val; +} diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/fsmc_f1.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/fsmc_f1.c new file mode 100644 index 0000000..210f0be --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/fsmc_f1.c @@ -0,0 +1,95 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * Copyright (c) 2010 Bryan Newbold. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/fsmc.c + * @author Marti Bolivar , + * Bryan Newbold + * @brief STM32F1 FSMC support. + */ + +#include + +#if STM32_HAVE_FSMC /* Don't try building the rest for MCUs without FSMC */ + +#include +#include + +void fsmc_sram_init_gpios(void) { + /* Data lines... */ + gpio_set_mode(GPIOD, 0, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOD, 1, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOD, 8, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOD, 9, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOD, 10, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOD, 14, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOD, 15, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOE, 7, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOE, 8, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOE, 9, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOE, 10, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOE, 11, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOE, 12, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOE, 13, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOE, 14, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOE, 15, GPIO_AF_OUTPUT_PP); + + /* Address lines... */ + gpio_set_mode(GPIOD, 11, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOD, 12, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOD, 13, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOF, 0, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOF, 1, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOF, 2, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOF, 3, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOF, 4, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOF, 5, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOF, 12, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOF, 13, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOF, 14, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOF, 15, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOG, 0, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOG, 1, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOG, 2, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOG, 3, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOG, 4, GPIO_AF_OUTPUT_PP); + gpio_set_mode(GPIOG, 5, GPIO_AF_OUTPUT_PP); + + /* And control lines... */ + gpio_set_mode(GPIOD, 4, GPIO_AF_OUTPUT_PP); // NOE + gpio_set_mode(GPIOD, 5, GPIO_AF_OUTPUT_PP); // NWE + + gpio_set_mode(GPIOD, 7, GPIO_AF_OUTPUT_PP); // NE1 + gpio_set_mode(GPIOG, 9, GPIO_AF_OUTPUT_PP); // NE2 + gpio_set_mode(GPIOG, 10, GPIO_AF_OUTPUT_PP); // NE3 + gpio_set_mode(GPIOG, 12, GPIO_AF_OUTPUT_PP); // NE4 + + gpio_set_mode(GPIOE, 0, GPIO_AF_OUTPUT_PP); // NBL0 + gpio_set_mode(GPIOE, 1, GPIO_AF_OUTPUT_PP); // NBL1 +} + +#endif /* STM32_HAVE_FSMC */ diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/gpio.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/gpio.c new file mode 100644 index 0000000..6e63d2f --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/gpio.c @@ -0,0 +1,50 @@ +/****************************************************************************** + * 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 + * 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/gpio.c + * @brief Generic STM32 GPIO support. + */ + +#include +#include + +/* + * GPIO routines + */ + +/** + * Initialize a GPIO device. + * + * Enables the clock for and resets the given device. + * + * @param dev GPIO device to initialize. + */ +void gpio_init(gpio_dev *dev) { + rcc_clk_enable(dev->clk_id); + rcc_reset_dev(dev->clk_id); +} diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/gpio_f1.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/gpio_f1.c new file mode 100644 index 0000000..6de16f5 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/gpio_f1.c @@ -0,0 +1,182 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Perry Hung. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/gpio.c + * @brief STM32F1 GPIO support. + */ + +#include +#include + +/* + * GPIO devices + */ + +gpio_dev gpioa = { + .regs = GPIOA_BASE, + .clk_id = RCC_GPIOA, + .exti_port = EXTI_PA, +}; +/** GPIO port A device. */ +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; + +gpio_dev gpioc = { + .regs = GPIOC_BASE, + .clk_id = RCC_GPIOC, + .exti_port = EXTI_PC, +}; +/** GPIO port C device. */ +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; + +#ifdef STM32_HIGH_DENSITY +gpio_dev gpioe = { + .regs = GPIOE_BASE, + .clk_id = RCC_GPIOE, + .exti_port = EXTI_PE, +}; +/** GPIO port E device. */ +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; + +gpio_dev gpiog = { + .regs = GPIOG_BASE, + .clk_id = RCC_GPIOG, + .exti_port = EXTI_PG, +}; +/** GPIO port G device. */ +gpio_dev* const GPIOG = &gpiog; +#endif + +/* + * GPIO routines + */ + +/** + * Initialize and reset all available GPIO devices. + */ +void gpio_init_all(void) { + gpio_init(GPIOA); + gpio_init(GPIOB); + gpio_init(GPIOC); + gpio_init(GPIOD); +#ifdef STM32_HIGH_DENSITY + gpio_init(GPIOE); + gpio_init(GPIOF); + gpio_init(GPIOG); +#endif +} + +/** + * Set the mode of a GPIO pin. + * + * @param dev GPIO device. + * @param pin Pin on the device whose mode to set, 0--15. + * @param mode General purpose or alternate function mode to set the pin to. + * @see gpio_pin_mode + */ +void gpio_set_mode(gpio_dev *dev, uint8 pin, gpio_pin_mode mode) { + gpio_reg_map *regs = dev->regs; + __io uint32 *cr = ®s->CRL + (pin >> 3); + uint32 shift = (pin & 0x7) * 4; + uint32 tmp = *cr; + + tmp &= ~(0xF << shift); + tmp |= (mode == GPIO_INPUT_PU ? GPIO_INPUT_PD : mode) << shift; + *cr = tmp; + + if (mode == GPIO_INPUT_PD) { + regs->ODR &= ~(1U << pin); + } else if (mode == GPIO_INPUT_PU) { + regs->ODR |= (1U << pin); + } +} + +gpio_pin_mode gpio_get_mode(gpio_dev *dev, uint8 pin) { + gpio_reg_map *regs = dev->regs; + __io uint32 *cr = ®s->CRL + (pin >> 3); + uint32 shift = (pin & 0x7) * 4; + + uint32 crMode = (*cr>>shift) & 0x0F; + + // could be pull up or pull down. Nee to check the ODR + if (crMode==GPIO_INPUT_PD && ((regs->ODR >> pin) & 0x01) !=0 ) + { + crMode = GPIO_INPUT_PU; + } + + return(crMode); +} + +/* + * AFIO + */ + +/** + * @brief Initialize the AFIO clock, and reset the AFIO registers. + */ +void afio_init(void) { + rcc_clk_enable(RCC_AFIO); + rcc_reset_dev(RCC_AFIO); +} + +#define AFIO_EXTI_SEL_MASK 0xF + +/** + * @brief Perform an alternate function remap. + * @param remapping Remapping to perform. + */ +void afio_remap(afio_remap_peripheral remapping) { + if (remapping & AFIO_REMAP_USE_MAPR2) { + remapping &= ~AFIO_REMAP_USE_MAPR2; + AFIO_BASE->MAPR2 |= remapping; + } else { + AFIO_BASE->MAPR |= remapping; + } +} diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/i2c.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/i2c.c new file mode 100644 index 0000000..c4ed245 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/i2c.c @@ -0,0 +1,520 @@ +/****************************************************************************** + * 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. + *****************************************************************************/ + +/** + * @file libmaple/i2c.c + * @author Perry Hung + * @brief Inter-Integrated Circuit (I2C) support. + * + * Currently, only master mode is supported. + */ + +#include "i2c_private.h" + +#include +#include +#include +#include +#include +#include + +#include + +static inline int32 wait_for_state_change(i2c_dev *dev, + i2c_state state, + uint32 timeout); +static void set_ccr_trise(i2c_dev *dev, uint32 flags); + +/** + * @brief Fill data register with slave address + * @param dev I2C device + * @param addr Slave address + * @param rw Read/write bit + */ +static inline void i2c_send_slave_addr(i2c_dev *dev, uint32 addr, uint32 rw) { + dev->regs->DR = (addr << 1) | rw; +} + +/* + * Simple debugging trail. Define I2C_DEBUG to turn on. + */ +#ifdef I2C_DEBUG + +#define NR_CRUMBS 128 +static struct crumb crumbs[NR_CRUMBS]; +static uint32 cur_crumb = 0; + +static inline void i2c_drop_crumb(uint32 event, uint32 arg0, uint32 arg1) { + if (cur_crumb < NR_CRUMBS) { + struct crumb *crumb = &crumbs[cur_crumb++]; + crumb->event = event; + crumb->arg0 = arg0; + crumb->arg1 = arg1; + } +} +#define I2C_CRUMB(event, arg0, arg1) i2c_drop_crumb(event, arg0, arg1) + +#else +#define I2C_CRUMB(event, arg0, arg1) +#endif + +struct crumb { + uint32 event; + uint32 arg0; + uint32 arg1; +}; + +enum { + IRQ_ENTRY = 1, + TXE_ONLY = 2, + TXE_BTF = 3, + STOP_SENT = 4, + TEST = 5, + RX_ADDR_START = 6, + RX_ADDR_STOP = 7, + RXNE_ONLY = 8, + RXNE_SENDING = 9, + RXNE_START_SENT = 10, + RXNE_STOP_SENT = 11, + RXNE_DONE = 12, + ERROR_ENTRY = 13, +}; + +/** + * @brief Reset an I2C bus. + * + * Reset is accomplished by clocking out pulses until any hung slaves + * release SDA and SCL, then generating a START condition, then a STOP + * condition. + * + * @param dev I2C device + */ +void i2c_bus_reset(const i2c_dev *dev) { + /* Release both lines */ + i2c_master_release_bus(dev); + + /* + * Make sure the bus is free by clocking it until any slaves release the + * bus. + */ + while (!gpio_read_bit(sda_port(dev), dev->sda_pin)) { + /* Wait for any clock stretching to finish */ + while (!gpio_read_bit(scl_port(dev), dev->scl_pin)) + ; + delay_us(10); + + /* Pull low */ + gpio_write_bit(scl_port(dev), dev->scl_pin, 0); + delay_us(10); + + /* Release high again */ + gpio_write_bit(scl_port(dev), dev->scl_pin, 1); + delay_us(10); + } + + /* Generate start then stop condition */ + gpio_write_bit(sda_port(dev), dev->sda_pin, 0); + delay_us(10); + gpio_write_bit(scl_port(dev), dev->scl_pin, 0); + delay_us(10); + gpio_write_bit(scl_port(dev), dev->scl_pin, 1); + delay_us(10); + gpio_write_bit(sda_port(dev), dev->sda_pin, 1); +} + +/** + * @brief Initialize an I2C device and reset its registers to their + * default values. + * @param dev Device to initialize. + */ +void i2c_init(i2c_dev *dev) { + rcc_reset_dev(dev->clk_id); + rcc_clk_enable(dev->clk_id); +} + +/* Hack for deprecated bit of STM32F1 functionality */ +#ifndef _I2C_HAVE_DEPRECATED_I2C_REMAP +#define _i2c_handle_remap(dev, flags) ((void)0) +#endif + +/** + * @brief Initialize an I2C device as bus master + * @param dev Device to enable + * @param flags Bitwise or of the following I2C options: + * I2C_FAST_MODE: 400 khz operation, + * I2C_DUTY_16_9: 16/9 Tlow/Thigh duty cycle (only applicable for + * fast mode), + * I2C_BUS_RESET: Reset the bus and clock out any hung slaves on + * initialization, + * I2C_10BIT_ADDRESSING: Enable 10-bit addressing, + * I2C_REMAP: (deprecated, STM32F1 only) Remap I2C1 to SCL/PB8 + * SDA/PB9. + */ +void i2c_master_enable(i2c_dev *dev, uint32 flags) { + /* PE must be disabled to configure the device */ + ASSERT(!(dev->regs->CR1 & I2C_CR1_PE)); + + /* Ugh */ + _i2c_handle_remap(dev, flags); + + /* Reset the bus. Clock out any hung slaves. */ + if (flags & I2C_BUS_RESET) { + i2c_bus_reset(dev); + } + + /* Turn on clock and set GPIO modes */ + i2c_init(dev); + i2c_config_gpios(dev); + + /* Configure clock and rise time */ + set_ccr_trise(dev, flags); + + /* Enable event and buffer interrupts */ + nvic_irq_enable(dev->ev_nvic_line); + nvic_irq_enable(dev->er_nvic_line); + i2c_enable_irq(dev, I2C_IRQ_EVENT | I2C_IRQ_BUFFER | I2C_IRQ_ERROR); + + /* Make it go! */ + i2c_peripheral_enable(dev); + + dev->state = I2C_STATE_IDLE; +} + +/** + * @brief Process an i2c transaction. + * + * Transactions are composed of one or more i2c_msg's, and may be read + * or write tranfers. Multiple i2c_msg's will generate a repeated + * start in between messages. + * + * @param dev I2C device + * @param msgs Messages to send/receive + * @param num Number of messages to send/receive + * @param timeout Bus idle timeout in milliseconds before aborting the + * transfer. 0 denotes no timeout. + * @return 0 on success, + * I2C_ERROR_PROTOCOL if there was a protocol error, + * I2C_ERROR_TIMEOUT if the transfer timed out. + */ +int32 i2c_master_xfer(i2c_dev *dev, + i2c_msg *msgs, + uint16 num, + uint32 timeout) { + int32 rc; + + ASSERT(dev->state == I2C_STATE_IDLE); + + dev->msg = msgs; + dev->msgs_left = num; + dev->timestamp = systick_uptime(); + dev->state = I2C_STATE_BUSY; + + i2c_enable_irq(dev, I2C_IRQ_EVENT); + i2c_start_condition(dev); + + rc = wait_for_state_change(dev, I2C_STATE_XFER_DONE, timeout); + if (rc < 0) { + goto out; + } + + dev->state = I2C_STATE_IDLE; +out: + return rc; +} + +/** + * @brief Wait for an I2C event, or time out in case of error. + * @param dev I2C device + * @param state I2C_state state to wait for + * @param timeout Timeout, in milliseconds + * @return 0 if target state is reached, a negative value on error. + */ +static inline int32 wait_for_state_change(i2c_dev *dev, + i2c_state state, + uint32 timeout) { + i2c_state tmp; + + while (1) { + tmp = dev->state; + + if (tmp == I2C_STATE_ERROR) { + return I2C_STATE_ERROR; + } + + if (tmp == state) { + return 0; + } + + if (timeout) { + if (systick_uptime() > (dev->timestamp + timeout)) { + /* TODO: overflow? */ + /* TODO: racy? */ + return I2C_ERROR_TIMEOUT; + } + } + } +} + +/* + * Private API + */ + +/* + * IRQ handler for I2C master. Handles transmission/reception. + */ +void _i2c_irq_handler(i2c_dev *dev) { + /* WTFs: + * - Where is I2C_MSG_10BIT_ADDR handled? + */ + i2c_msg *msg = dev->msg; + + uint8 read = msg->flags & I2C_MSG_READ; + + uint32 sr1 = dev->regs->SR1; + uint32 sr2 = dev->regs->SR2; + I2C_CRUMB(IRQ_ENTRY, sr1, sr2); + + /* + * Reset timeout counter + */ + dev->timestamp = systick_uptime(); + + /* + * EV5: Start condition sent + */ + if (sr1 & I2C_SR1_SB) { + msg->xferred = 0; + i2c_enable_irq(dev, I2C_IRQ_BUFFER); + + /* + * Master receiver + */ + if (read) { + i2c_enable_ack(dev); + } + + i2c_send_slave_addr(dev, msg->addr, read); + sr1 = sr2 = 0; + } + + /* + * EV6: Slave address sent + */ + if (sr1 & I2C_SR1_ADDR) { + /* + * Special case event EV6_1 for master receiver. + * Generate NACK and restart/stop condition after ADDR + * is cleared. + */ + if (read) { + if (msg->length == 1) { + i2c_disable_ack(dev); + if (dev->msgs_left > 1) { + i2c_start_condition(dev); + I2C_CRUMB(RX_ADDR_START, 0, 0); + } else { + i2c_stop_condition(dev); + I2C_CRUMB(RX_ADDR_STOP, 0, 0); + } + } + } else { + /* + * Master transmitter: write first byte to fill shift + * register. We should get another TXE interrupt + * immediately to fill DR again. + */ + if (msg->length > 1) { + i2c_write(dev, msg->data[msg->xferred++]); + } else if (msg->length == 0) { /* We're just sending an address */ + i2c_stop_condition(dev); + /* + * Turn off event interrupts to keep BTF from firing until + * the end of the stop condition. Why on earth they didn't + * have a start/stop condition request clear BTF is beyond + * me. + */ + i2c_disable_irq(dev, I2C_IRQ_EVENT); + I2C_CRUMB(STOP_SENT, 0, 0); + dev->state = I2C_STATE_XFER_DONE; + } /* else we're just sending one byte */ + } + sr1 = sr2 = 0; + } + + /* + * EV8: Master transmitter + * Transmit buffer empty, but we haven't finished transmitting the last + * byte written. + */ + if ((sr1 & I2C_SR1_TXE) && !(sr1 & I2C_SR1_BTF)) { + I2C_CRUMB(TXE_ONLY, 0, 0); + if (dev->msgs_left) { + i2c_write(dev, msg->data[msg->xferred++]); + if (msg->xferred == msg->length) { + /* + * End of this message. Turn off TXE/RXNE and wait for + * BTF to send repeated start or stop condition. + */ + i2c_disable_irq(dev, I2C_IRQ_BUFFER); + dev->msgs_left--; + } + } else { + /* + * This should be impossible... + */ + ASSERT(0); + } + sr1 = sr2 = 0; + } + + /* + * EV8_2: Master transmitter + * Last byte sent, program repeated start/stop + */ + if ((sr1 & I2C_SR1_TXE) && (sr1 & I2C_SR1_BTF)) { + I2C_CRUMB(TXE_BTF, 0, 0); + if (dev->msgs_left) { + I2C_CRUMB(TEST, 0, 0); + /* + * Repeated start insanity: We can't disable ITEVTEN or else SB + * won't interrupt, but if we don't disable ITEVTEN, BTF will + * continually interrupt us. What the fuck ST? + */ + i2c_start_condition(dev); + while (!(dev->regs->SR1 & I2C_SR1_SB)) + ; + dev->msg++; + } else { + i2c_stop_condition(dev); + + /* + * Turn off event interrupts to keep BTF from firing until + * the end of the stop condition. Why on earth they didn't + * have a start/stop condition request clear BTF is beyond + * me. + */ + i2c_disable_irq(dev, I2C_IRQ_EVENT); + I2C_CRUMB(STOP_SENT, 0, 0); + dev->state = I2C_STATE_XFER_DONE; + } + sr1 = sr2 = 0; + } + + /* + * EV7: Master Receiver + */ + if (sr1 & I2C_SR1_RXNE) { + I2C_CRUMB(RXNE_ONLY, 0, 0); + msg->data[msg->xferred++] = dev->regs->DR; + + /* + * EV7_1: Second to last byte in the reception? Set NACK and generate + * stop/restart condition in time for the last byte. We'll get one more + * RXNE interrupt before shutting things down. + */ + if (msg->xferred == (msg->length - 1)) { + i2c_disable_ack(dev); + if (dev->msgs_left > 2) { + i2c_start_condition(dev); + I2C_CRUMB(RXNE_START_SENT, 0, 0); + } else { + i2c_stop_condition(dev); + I2C_CRUMB(RXNE_STOP_SENT, 0, 0); + } + } else if (msg->xferred == msg->length) { + dev->msgs_left--; + if (dev->msgs_left == 0) { + /* + * We're done. + */ + I2C_CRUMB(RXNE_DONE, 0, 0); + dev->state = I2C_STATE_XFER_DONE; + } else { + dev->msg++; + } + } + } +} + +/* + * Interrupt handler for I2C error conditions. Aborts any pending I2C + * transactions. + */ +void _i2c_irq_error_handler(i2c_dev *dev) { + I2C_CRUMB(ERROR_ENTRY, dev->regs->SR1, dev->regs->SR2); + + dev->error_flags = dev->regs->SR1 & (I2C_SR1_BERR | + I2C_SR1_ARLO | + I2C_SR1_AF | + I2C_SR1_OVR); + /* Clear flags */ + dev->regs->SR1 = 0; + dev->regs->SR2 = 0; + + i2c_stop_condition(dev); + i2c_disable_irq(dev, I2C_IRQ_BUFFER | I2C_IRQ_EVENT | I2C_IRQ_ERROR); + dev->state = I2C_STATE_ERROR; +} + +/* + * CCR/TRISE configuration helper + */ +static void set_ccr_trise(i2c_dev *dev, uint32 flags) { + uint32 ccr = 0; + uint32 trise = 0; + uint32 clk_mhz = _i2c_bus_clk(dev); + uint32 clk_hz = clk_mhz * (1000 * 1000); + + i2c_set_input_clk(dev, clk_mhz); + + if (flags & I2C_FAST_MODE) { + ccr |= I2C_CCR_FS; + + if (flags & I2C_DUTY_16_9) { + /* Tlow/Thigh = 16/9 */ + ccr |= I2C_CCR_DUTY_16_9; + ccr |= clk_hz / (400000 * 25); + } else { + /* Tlow/Thigh = 2 */ + ccr |= clk_hz / (400000 * 3); + } + + trise = (300 * clk_mhz / 1000) + 1; + } else { + /* Tlow/Thigh = 1 */ + ccr = clk_hz / (100000 * 2); + trise = clk_mhz + 1; + } + + /* Set minimum required value if CCR < 1*/ + if ((ccr & I2C_CCR_CCR) == 0) { + ccr |= 0x1; + } + + i2c_set_clk_control(dev, ccr); + i2c_set_trise(dev, trise); +} diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/i2c_f1.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/i2c_f1.c new file mode 100644 index 0000000..8439793 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/i2c_f1.c @@ -0,0 +1,129 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/i2c.c + * @brief STM32F1 I2C support + */ + +#include "i2c_private.h" +#include + +/* + * Devices + */ + +static i2c_dev i2c1 = I2C_DEV_OLD(1, &gpiob, 7, 6); +static i2c_dev i2c2 = I2C_DEV_OLD(2, &gpiob, 11, 10); + +/** STM32F1 I2C device 1 */ +i2c_dev* const I2C1 = &i2c1; +/** STM32F1 I2C device 2 */ +i2c_dev* const I2C2 = &i2c2; + +/* + * Routines + */ + +static int i2c1_wants_remap(const i2c_dev *dev) { + /* Check if we've got I2C1 configured for SDA/SCL remap on PB9/PB8 */ + return (dev->clk_id == RCC_I2C1) && + (scl_port(dev)->clk_id == RCC_GPIOB) && + (sda_port(dev)->clk_id == RCC_GPIOB) && + (dev->sda_pin == 9) && + (dev->scl_pin == 8); +} + +void i2c_config_gpios(const i2c_dev *dev) { + if (i2c1_wants_remap(dev)) { + afio_remap(AFIO_REMAP_I2C1); + } + gpio_set_mode(sda_port(dev), dev->sda_pin, GPIO_AF_OUTPUT_OD); + gpio_set_mode(scl_port(dev), dev->scl_pin, GPIO_AF_OUTPUT_OD); +} + +void i2c_master_release_bus(const i2c_dev *dev) { + gpio_write_bit(scl_port(dev), dev->scl_pin, 1); + gpio_write_bit(sda_port(dev), dev->sda_pin, 1); + gpio_set_mode(scl_port(dev), dev->scl_pin, GPIO_OUTPUT_OD); + gpio_set_mode(sda_port(dev), dev->sda_pin, GPIO_OUTPUT_OD); +} + +/* + * IRQ handlers + */ + +void __irq_i2c1_ev(void) { + _i2c_irq_handler(I2C1); +} + +void __irq_i2c2_ev(void) { + _i2c_irq_handler(I2C2); +} + +void __irq_i2c1_er(void) { + _i2c_irq_error_handler(I2C1); +} + +void __irq_i2c2_er(void) { + _i2c_irq_error_handler(I2C2); +} + +/* + * Internal APIs + */ + +void _i2c_irq_priority_fixup(i2c_dev *dev) { + /* + * Important STM32 Errata: + * + * See STM32F10xx8 and STM32F10xxB Errata sheet (Doc ID 14574 Rev 8), + * Section 2.11.1, 2.11.2. + * + * 2.11.1: + * When the EV7, EV7_1, EV6_1, EV6_3, EV2, EV8, and EV3 events are not + * managed before the current byte is being transferred, problems may be + * encountered such as receiving an extra byte, reading the same data twice + * or missing data. + * + * 2.11.2: + * In Master Receiver mode, when closing the communication using + * method 2, the content of the last read data can be corrupted. + * + * If the user software is not able to read the data N-1 before the STOP + * condition is generated on the bus, the content of the shift register + * (data N) will be corrupted. (data N is shifted 1-bit to the left). + * + * ---------------------------------------------------------------------- + * + * In order to ensure that events are not missed, the i2c interrupt must + * not be preempted. We set the i2c interrupt priority to be the highest + * interrupt in the system (priority level 0). All other interrupts have + * been initialized to priority level 16. See nvic_init(). + */ + nvic_irq_set_priority(dev->ev_nvic_line, 0); + nvic_irq_set_priority(dev->er_nvic_line, 0); +} diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/iwdg.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/iwdg.c new file mode 100644 index 0000000..2456235 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/iwdg.c @@ -0,0 +1,62 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Michael Hope. + * + * 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/iwdg.c + * @brief Independent watchdog (IWDG) support + */ + +#include + +/** + * @brief Initialise and start the watchdog + * + * The prescaler and reload set the timeout. For example, a prescaler + * of IWDG_PRE_32 divides the 40 kHz clock by 32 and gives roughly 1 + * ms per reload. + * + * @param prescaler Prescaler for the 40 kHz IWDG clock. + * @param reload Independent watchdog counter reload value. + */ +void iwdg_init(iwdg_prescaler prescaler, uint16 reload) { + IWDG_BASE->KR = IWDG_KR_UNLOCK; + IWDG_BASE->PR = prescaler; + IWDG_BASE->RLR = reload; + + /* Start things off */ + IWDG_BASE->KR = IWDG_KR_START; + iwdg_feed(); +} + +/** + * @brief Reset the IWDG counter. + * + * Calling this function will cause the IWDG counter to be reset to + * its reload value. + */ +void iwdg_feed(void) { + IWDG_BASE->KR = IWDG_KR_FEED; +} diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/nvic.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/nvic.c new file mode 100644 index 0000000..149e780 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/nvic.c @@ -0,0 +1,103 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Perry Hung. + * Copyright (c) 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/nvic.c + * @brief Nested vector interrupt controller support. + */ + +#include +#include +#include + +/** + * @brief Set interrupt priority for an interrupt line + * + * Note: The STM32 only implements 4 bits of priority, ignoring the + * lower 4 bits. This means there are only 16 levels of priority. + * Bits[3:0] read as zero and ignore writes. + * + * @param irqn device to set + * @param priority Priority to set, 0 being highest priority and 15 + * being lowest. + */ +void nvic_irq_set_priority(nvic_irq_num irqn, uint8 priority) { + if (irqn < 0) { + /* This interrupt is in the system handler block */ + SCB_BASE->SHP[((uint32)irqn & 0xF) - 4] = (priority & 0xF) << 4; + } else { + NVIC_BASE->IP[irqn] = (priority & 0xF) << 4; + } +} + +/** + * @brief Initialize the NVIC, setting interrupts to a default priority. + */ +void nvic_init(uint32 address, uint32 offset) { + uint32 i; + + nvic_set_vector_table(address, offset); + + /* + * Lower priority level for all peripheral interrupts to lowest + * possible. + */ + for (i = 0; i < STM32_NR_INTERRUPTS; i++) { + nvic_irq_set_priority((nvic_irq_num)i, 0xF); + } + + /* Lower systick interrupt priority to lowest level */ + nvic_irq_set_priority(NVIC_SYSTICK, 0xF); +} + +/** + * @brief Set the vector table base address. + * + * For stand-alone products, the vector table base address is normally + * the start of Flash (0x08000000). + * + * @param address Vector table base address. + * @param offset Offset from address. Some restrictions apply to the + * use of nonzero offsets; see the ARM Cortex M3 + * Technical Reference Manual. + */ +void nvic_set_vector_table(uint32 address, uint32 offset) { + SCB_BASE->VTOR = address | (offset & 0x1FFFFF80); +} + +/** + * @brief Force a system reset. + * + * Resets all major system components, excluding debug. + */ +void nvic_sys_reset() { + uint32 prigroup = SCB_BASE->AIRCR & SCB_AIRCR_PRIGROUP; + SCB_BASE->AIRCR = SCB_AIRCR_VECTKEY | SCB_AIRCR_SYSRESETREQ | prigroup; + asm volatile("dsb"); + while (1) + ; +} diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/pwr.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/pwr.c new file mode 100644 index 0000000..3cf170f --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/pwr.c @@ -0,0 +1,41 @@ +/****************************************************************************** + * 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/pwr.c + * @brief Power control (PWR) support. + */ + +#include +#include + +/** + * Enables the power interface clock, and resets the power device. + */ +void pwr_init(void) { + rcc_clk_enable(RCC_PWR); + rcc_reset_dev(RCC_PWR); +} diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/rcc.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/rcc.c new file mode 100644 index 0000000..8e7d1ea --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/rcc.c @@ -0,0 +1,169 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Perry Hung. + * Copyright (c) 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/rcc.c + * @brief Portable RCC routines. + */ + +#include + +#include "rcc_private.h" + +/** + * @brief Get a peripheral's clock domain + * @param id Clock ID of the peripheral whose clock domain to return + * @return Clock source for the given clock ID + */ +rcc_clk_domain rcc_dev_clk(rcc_clk_id id) { + return rcc_dev_table[id].clk_domain; +} + +/** + * @brief Switch the clock used as the source of the system clock. + * + * After switching the source, this function blocks until the new + * clock source is in use. + * + * @param sysclk_src New system clock source. + * @see rcc_sysclk_src + */ +void rcc_switch_sysclk(rcc_sysclk_src sysclk_src) { + uint32 cfgr = RCC_BASE->CFGR; + cfgr &= ~RCC_CFGR_SW; + cfgr |= sysclk_src; + + /* Switch SYSCLK source. */ + RCC_BASE->CFGR = cfgr; + + /* Wait for new source to come into use. */ + while ((RCC_BASE->CFGR & RCC_CFGR_SWS) != (sysclk_src << 2)) + ; +} + +/* + * Turning clocks off and on, querying their status. + */ + +/* IMPORTANT NOTE FOR IMPLEMENTORS: + * + * libmaple assumes that enum rcc_clk enumerators are two-byte + * values, stored in a uint16, in the following way: + * + * - The high-order byte is the byte offset (from RCC_BASE) of the register + * to touch when turning on or off the given clock. + * + * - The low-order byte is the bit in that register that turns the + * clock on or off. + * + * Example for STM32F1: Turning on the high-speed external clock (HSE) + * involves setting HSEON, bit 16, of RCC_CR. The high-order byte is + * then offsetof(struct rcc_reg_map, CR) = 0, and the low-order byte + * is 16. + * + * The corresponding value of RCC_CLK_HSE is thus (0 << 8) | 16 = 16. + * + * On all known STM32 series, this encoding has the property that + * adding one to the low byte also gives the bit to check to determine + * if the clock is ready. For example, on STM32F1, RCC_CR_HSERDY is + * bit 17. If that's not the case on your series, rcc_is_clk_ready() + * won't work for you. */ + +/* Returns the RCC register which controls the clock source. */ +static inline __io uint32* rcc_clk_reg(rcc_clk clock) { + return (__io uint32*)((__io uint8*)RCC_BASE + (clock >> 8)); +} + +/* Returns a mask in rcc_clk_reg(clock) to be used for turning the + * clock on and off */ +static inline uint32 rcc_clk_on_mask(rcc_clk clock) { + return 1 << (clock & 0xFF); +} + +/* Returns a mask in rcc_clk_reg(clock) to be used when checking the + * readiness of the clock. */ +static inline uint32 rcc_clk_ready_mask(rcc_clk clock) { + return rcc_clk_on_mask(clock) << 1; +} + +/** + * @brief Turn on a clock source. + * + * After this routine exits, callers should ensure that the clock + * source is ready by waiting until rcc_is_clk_ready(clock) returns + * true. + * + * @param clock Clock to turn on. + * @see rcc_turn_off_clk() + * @see rcc_is_clk_ready() + */ +void rcc_turn_on_clk(rcc_clk clock) { + *rcc_clk_reg(clock) |= rcc_clk_on_mask(clock); +} + +/** + * @brief Turn off a clock source. + * + * In certain configurations, certain clock sources cannot be safely + * turned off. (For example, the main PLL on STM32F1 devices cannot be + * turned off if it has been selected as the SYSCLK source). Consult + * the reference material for your MCU to ensure it is safe to call + * this function. + * + * @param clock Clock to turn off. + * @see rcc_turn_on_clk() + * @see rcc_is_clk_ready() + */ +void rcc_turn_off_clk(rcc_clk clock) { + *rcc_clk_reg(clock) &= ~rcc_clk_on_mask(clock); +} + +/** + * @brief Check if a clock is on. + * @param clock Clock to check. + * @return 1 if the clock is on, 0 if the clock is off. + */ +int rcc_is_clk_on(rcc_clk clock) { + return !!(*rcc_clk_reg(clock) & rcc_clk_on_mask(clock)); +} + +/** + * @brief Check if a clock source is ready. + * + * In general, it is not safe to rely on a clock source unless this + * function returns nonzero. Also note that this function may return + * nonzero for a short period of time after a clock has been turned + * off. Consult the reference material for your MCU for more details. + * + * @param clock Clock whose readiness to check for. + * @return Nonzero if the clock is ready, zero otherwise. + * @see rcc_turn_on_clk() + * @see rcc_turn_off_clk() + */ +int rcc_is_clk_ready(rcc_clk clock) { + return (int)(*rcc_clk_reg(clock) & rcc_clk_ready_mask(clock)); +} diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/rcc_f1.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/rcc_f1.c new file mode 100644 index 0000000..f45f670 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/rcc_f1.c @@ -0,0 +1,173 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Perry Hung. + * Copyright (c) 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/rcc.c + * @brief STM32F1 RCC. + */ + +#include +#include +#include + +#include "rcc_private.h" + +#define APB1 RCC_APB1 +#define APB2 RCC_APB2 +#define AHB RCC_AHB + +/* Device descriptor table, maps rcc_clk_id onto bus and enable/reset + * register bit numbers. */ +const struct rcc_dev_info rcc_dev_table[] = { + [RCC_GPIOA] = { .clk_domain = APB2, .line_num = 2 }, + [RCC_GPIOB] = { .clk_domain = APB2, .line_num = 3 }, + [RCC_GPIOC] = { .clk_domain = APB2, .line_num = 4 }, + [RCC_GPIOD] = { .clk_domain = APB2, .line_num = 5 }, + [RCC_AFIO] = { .clk_domain = APB2, .line_num = 0 }, + [RCC_ADC1] = { .clk_domain = APB2, .line_num = 9 }, + [RCC_ADC2] = { .clk_domain = APB2, .line_num = 10 }, + [RCC_ADC3] = { .clk_domain = APB2, .line_num = 15 }, + [RCC_USART1] = { .clk_domain = APB2, .line_num = 14 }, + [RCC_USART2] = { .clk_domain = APB1, .line_num = 17 }, + [RCC_USART3] = { .clk_domain = APB1, .line_num = 18 }, + [RCC_TIMER1] = { .clk_domain = APB2, .line_num = 11 }, + [RCC_TIMER2] = { .clk_domain = APB1, .line_num = 0 }, + [RCC_TIMER3] = { .clk_domain = APB1, .line_num = 1 }, + [RCC_TIMER4] = { .clk_domain = APB1, .line_num = 2 }, + [RCC_SPI1] = { .clk_domain = APB2, .line_num = 12 }, + [RCC_SPI2] = { .clk_domain = APB1, .line_num = 14 }, + [RCC_DMA1] = { .clk_domain = AHB, .line_num = 0 }, + [RCC_PWR] = { .clk_domain = APB1, .line_num = 28}, + [RCC_BKP] = { .clk_domain = APB1, .line_num = 27}, + [RCC_I2C1] = { .clk_domain = APB1, .line_num = 21 }, + [RCC_I2C2] = { .clk_domain = APB1, .line_num = 22 }, + [RCC_CRC] = { .clk_domain = AHB, .line_num = 6}, + [RCC_FLITF] = { .clk_domain = AHB, .line_num = 4}, + [RCC_SRAM] = { .clk_domain = AHB, .line_num = 2}, + [RCC_USB] = { .clk_domain = APB1, .line_num = 23}, +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) + [RCC_GPIOE] = { .clk_domain = APB2, .line_num = 6 }, + [RCC_GPIOF] = { .clk_domain = APB2, .line_num = 7 }, + [RCC_GPIOG] = { .clk_domain = APB2, .line_num = 8 }, + [RCC_UART4] = { .clk_domain = APB1, .line_num = 19 }, + [RCC_UART5] = { .clk_domain = APB1, .line_num = 20 }, + [RCC_TIMER5] = { .clk_domain = APB1, .line_num = 3 }, + [RCC_TIMER6] = { .clk_domain = APB1, .line_num = 4 }, + [RCC_TIMER7] = { .clk_domain = APB1, .line_num = 5 }, + [RCC_TIMER8] = { .clk_domain = APB2, .line_num = 13 }, + [RCC_FSMC] = { .clk_domain = AHB, .line_num = 8 }, + [RCC_DAC] = { .clk_domain = APB1, .line_num = 29 }, + [RCC_DMA2] = { .clk_domain = AHB, .line_num = 1 }, + [RCC_SDIO] = { .clk_domain = AHB, .line_num = 10 }, + [RCC_SPI3] = { .clk_domain = APB1, .line_num = 15 }, +#endif +#ifdef STM32_XL_DENSITY + [RCC_TIMER9] = { .clk_domain = APB2, .line_num = 19 }, + [RCC_TIMER10] = { .clk_domain = APB2, .line_num = 20 }, + [RCC_TIMER11] = { .clk_domain = APB2, .line_num = 21 }, + [RCC_TIMER12] = { .clk_domain = APB1, .line_num = 6 }, + [RCC_TIMER13] = { .clk_domain = APB1, .line_num = 7 }, + [RCC_TIMER14] = { .clk_domain = APB1, .line_num = 8 }, +#endif +}; + +__deprecated +void rcc_clk_init(rcc_sysclk_src sysclk_src, + rcc_pllsrc pll_src, + rcc_pll_multiplier pll_mul) { + /* Assume that we're going to clock the chip off the PLL, fed by + * the HSE */ + ASSERT(sysclk_src == RCC_CLKSRC_PLL && + pll_src == RCC_PLLSRC_HSE); + + RCC_BASE->CFGR = pll_src | pll_mul | (0x3<<22); + + /* Turn on, and wait for, HSE. */ + rcc_turn_on_clk(RCC_CLK_HSE); + while (!rcc_is_clk_ready(RCC_CLK_HSE)) + ; + + /* Do the same for the main PLL. */ + rcc_turn_on_clk(RCC_CLK_PLL); + while(!rcc_is_clk_ready(RCC_CLK_PLL)) + ; + + /* Finally, switch over to the PLL. */ + rcc_switch_sysclk(RCC_CLKSRC_PLL); +} + +/* pll_cfg->data must point to a valid struct stm32f1_rcc_pll_data. */ +void rcc_configure_pll(rcc_pll_cfg *pll_cfg) { + stm32f1_rcc_pll_data *data = pll_cfg->data; + rcc_pll_multiplier pll_mul = data->pll_mul; + uint32 cfgr; + /* Check that the PLL is disabled. */ + ASSERT_FAULT(!rcc_is_clk_on(RCC_CLK_PLL)); + + cfgr = RCC_BASE->CFGR; + cfgr &= ~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLMUL); + cfgr |= pll_cfg->pllsrc | pll_mul; + + RCC_BASE->CFGR = cfgr; +} + +void rcc_clk_enable(rcc_clk_id id) { + static __io uint32* enable_regs[] = { + [APB1] = &RCC_BASE->APB1ENR, + [APB2] = &RCC_BASE->APB2ENR, + [AHB] = &RCC_BASE->AHBENR, + }; + rcc_do_clk_enable(enable_regs, id); +} + +void rcc_reset_dev(rcc_clk_id id) { + static __io uint32* reset_regs[] = { + [APB1] = &RCC_BASE->APB1RSTR, + [APB2] = &RCC_BASE->APB2RSTR, + }; + rcc_do_reset_dev(reset_regs, id); +} + +void rcc_set_prescaler(rcc_prescaler prescaler, uint32 divider) { + static const uint32 masks[] = { + [RCC_PRESCALER_AHB] = RCC_CFGR_HPRE, + [RCC_PRESCALER_APB1] = RCC_CFGR_PPRE1, + [RCC_PRESCALER_APB2] = RCC_CFGR_PPRE2, + [RCC_PRESCALER_USB] = RCC_CFGR_USBPRE, + [RCC_PRESCALER_ADC] = RCC_CFGR_ADCPRE, + }; + rcc_do_set_prescaler(masks, prescaler, divider); +} + +void rcc_clk_disable(rcc_clk_id id) { + static __io uint32* enable_regs[] = { + [APB1] = &RCC_BASE->APB1ENR, + [APB2] = &RCC_BASE->APB2ENR, + [AHB] = &RCC_BASE->AHBENR, + }; + rcc_do_clk_disable(enable_regs, id); +} \ No newline at end of file diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/spi.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/spi.c new file mode 100644 index 0000000..e0ee90d --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/spi.c @@ -0,0 +1,172 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011, 2012 LeafLabs, LLC. + * Copyright (c) 2010 Perry Hung. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/spi.c + * @author Marti Bolivar + * @brief Serial Peripheral Interface (SPI) support. + * Currently, there is no Integrated Interchip Sound (I2S) support. + */ + +#include +#include + +static void spi_reconfigure(spi_dev *dev, uint32 cr1_config); + +/* + * SPI convenience routines + */ + +/** + * @brief Initialize and reset a SPI device. + * @param dev Device to initialize and reset. + */ +void spi_init(spi_dev *dev) { + rcc_clk_enable(dev->clk_id); + rcc_reset_dev(dev->clk_id); +} + +/** + * @brief Configure and enable a SPI device as bus master. + * + * The device's peripheral will be disabled before being reconfigured. + * + * @param dev Device to configure as bus master + * @param baud Bus baud rate + * @param mode SPI mode + * @param flags Logical OR of spi_cfg_flag values. + * @see spi_cfg_flag + */ +void spi_master_enable(spi_dev *dev, + spi_baud_rate baud, + spi_mode mode, + uint32 flags) { + spi_reconfigure(dev, baud | flags | SPI_CR1_MSTR | mode); +} + + +/** + * @brief Configure and enable a SPI device as a bus slave. + * + * The device's peripheral will be disabled before being reconfigured. + * + * @param dev Device to configure as a bus slave + * @param mode SPI mode + * @param flags Logical OR of spi_cfg_flag values. + * @see spi_cfg_flag + */ +void spi_slave_enable(spi_dev *dev, spi_mode mode, uint32 flags) { + spi_reconfigure(dev, flags | mode); +} + +/** + * @brief Blocking SPI transmit. + * @param dev SPI port to use for transmission + * @param buf Buffer to transmit. The sizeof buf's elements are + * inferred from dev's data frame format (i.e., are + * correctly treated as 8-bit or 16-bit quantities). + * @param len Maximum number of elements to transmit. + * @return Number of elements transmitted. + */ +uint32 spi_tx(spi_dev *dev, const void *buf, uint32 len) { + uint32 txed = len; + spi_reg_map *regs = dev->regs; + if ( spi_dff(dev) == SPI_DFF_8_BIT ) { + const uint8 * dp8 = (const uint8*)buf; + while ( len-- ) { + while ( (regs->SR & SPI_SR_TXE)==0 ) ; //while ( spi_is_tx_empty(dev)==0 ); // wait Tx to be empty + regs->DR = *dp8++; + } + } else { + const uint16 * dp16 = (const uint16*)buf; + while ( len-- ) { + while ( (regs->SR & SPI_SR_TXE)==0 ) ; //while ( spi_is_tx_empty(dev)==0 ); // wait Tx to be empty + regs->DR = *dp16++; + } + } + return txed; +} + +/** + * @brief Enable a SPI peripheral + * @param dev Device to enable + */ +void spi_peripheral_enable(spi_dev *dev) { + bb_peri_set_bit(&dev->regs->CR1, SPI_CR1_SPE_BIT, 1); +} + +/** + * @brief Disable a SPI peripheral + * @param dev Device to disable + */ +void spi_peripheral_disable(spi_dev *dev) { + bb_peri_set_bit(&dev->regs->CR1, SPI_CR1_SPE_BIT, 0); +} + +/** + * @brief Enable DMA requests whenever the transmit buffer is empty + * @param dev SPI device on which to enable TX DMA requests + */ +void spi_tx_dma_enable(spi_dev *dev) { + bb_peri_set_bit(&dev->regs->CR2, SPI_CR2_TXDMAEN_BIT, 1); +} + +/** + * @brief Disable DMA requests whenever the transmit buffer is empty + * @param dev SPI device on which to disable TX DMA requests + */ +void spi_tx_dma_disable(spi_dev *dev) { + bb_peri_set_bit(&dev->regs->CR2, SPI_CR2_TXDMAEN_BIT, 0); +} + +/** + * @brief Enable DMA requests whenever the receive buffer is empty + * @param dev SPI device on which to enable RX DMA requests + */ +void spi_rx_dma_enable(spi_dev *dev) { + bb_peri_set_bit(&dev->regs->CR2, SPI_CR2_RXDMAEN_BIT, 1); +} + +/** + * @brief Disable DMA requests whenever the receive buffer is empty + * @param dev SPI device on which to disable RX DMA requests + */ +void spi_rx_dma_disable(spi_dev *dev) { + bb_peri_set_bit(&dev->regs->CR2, SPI_CR2_RXDMAEN_BIT, 0); +} + +/* + * SPI auxiliary routines + */ + +static void spi_reconfigure(spi_dev *dev, uint32 cr1_config) { +#define MASK (SPI_CR1_CRCEN|SPI_CR1_DFF) + spi_irq_disable(dev, SPI_INTERRUPTS_ALL); + if ( (dev->regs->CR1&MASK)!=(cr1_config&MASK) ) spi_peripheral_disable(dev); + dev->regs->CR1 = cr1_config; + spi_peripheral_enable(dev); +} diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/spi_f1.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/spi_f1.c new file mode 100644 index 0000000..bbea5a4 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/spi_f1.c @@ -0,0 +1,84 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011, 2012 LeafLabs, LLC. + * Copyright (c) 2010 Perry Hung. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/spi.c + * @author Marti Bolivar + * @brief STM32F1 SPI/I2S. + */ + +#include +#include +#include "spi_private.h" + +/* + * Devices + */ + +static spi_dev spi1 = SPI_DEV(1); +static spi_dev spi2 = SPI_DEV(2); + +spi_dev *SPI1 = &spi1; +spi_dev *SPI2 = &spi2; + +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) +static spi_dev spi3 = SPI_DEV(3); +spi_dev *SPI3 = &spi3; +#endif + +/* + * Routines + */ + +void spi_config_gpios(spi_dev *ignored, + uint8 as_master, + gpio_dev *nss_dev, + uint8 nss_bit, + gpio_dev *comm_dev, + uint8 sck_bit, + uint8 miso_bit, + uint8 mosi_bit) { + if (as_master) { + // gpio_set_mode(nss_dev, nss_bit, GPIO_AF_OUTPUT_PP);// Roger Clark. Commented out, so that NSS can be driven as a normal GPIO pin during SPI use + gpio_set_mode(comm_dev, sck_bit, GPIO_AF_OUTPUT_PP); + gpio_set_mode(comm_dev, miso_bit, GPIO_INPUT_FLOATING); + gpio_set_mode(comm_dev, mosi_bit, GPIO_AF_OUTPUT_PP); + } else { + gpio_set_mode(nss_dev, nss_bit, GPIO_INPUT_FLOATING); + gpio_set_mode(comm_dev, sck_bit, GPIO_INPUT_FLOATING); + gpio_set_mode(comm_dev, miso_bit, GPIO_AF_OUTPUT_PP); + gpio_set_mode(comm_dev, mosi_bit, GPIO_INPUT_FLOATING); + } +} + +void spi_foreach(void (*fn)(spi_dev*)) { + fn(SPI1); + fn(SPI2); +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) + fn(SPI3); +#endif +} diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/stm32f1/performance/isrs.S b/BootLoaders/Boards/stm32/cores/maple/libmaple/stm32f1/performance/isrs.S new file mode 100644 index 0000000..8c1a44f --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/stm32f1/performance/isrs.S @@ -0,0 +1,262 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 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. + *****************************************************************************/ + +/* STM32F1 performance line ISR weak declarations */ + +#include + + .thumb + +/* Default handler for all non-overridden interrupts and exceptions */ + .globl __default_handler + .type __default_handler, %function + +__default_handler: + b . + + .weak __exc_nmi + .globl __exc_nmi + .set __exc_nmi, __default_handler + .weak __exc_hardfault + .globl __exc_hardfault + .set __exc_hardfault, __default_handler + .weak __exc_memmanage + .globl __exc_memmanage + .set __exc_memmanage, __default_handler + .weak __exc_busfault + .globl __exc_busfault + .set __exc_busfault, __default_handler + .weak __exc_usagefault + .globl __exc_usagefault + .set __exc_usagefault, __default_handler + .weak __stm32reservedexception7 + .globl __stm32reservedexception7 + .set __stm32reservedexception7, __default_handler + .weak __stm32reservedexception8 + .globl __stm32reservedexception8 + .set __stm32reservedexception8, __default_handler + .weak __stm32reservedexception9 + .globl __stm32reservedexception9 + .set __stm32reservedexception9, __default_handler + .weak __stm32reservedexception10 + .globl __stm32reservedexception10 + .set __stm32reservedexception10, __default_handler + .weak __exc_svc + .globl __exc_svc + .set __exc_svc, __default_handler + .weak __exc_debug_monitor + .globl __exc_debug_monitor + .set __exc_debug_monitor, __default_handler + .weak __stm32reservedexception13 + .globl __stm32reservedexception13 + .set __stm32reservedexception13, __default_handler + .weak __exc_pendsv + .globl __exc_pendsv + .set __exc_pendsv, __default_handler + .weak __exc_systick + .globl __exc_systick + .set __exc_systick, __default_handler + .weak __irq_wwdg + .globl __irq_wwdg + .set __irq_wwdg, __default_handler + .weak __irq_pvd + .globl __irq_pvd + .set __irq_pvd, __default_handler + .weak __irq_tamper + .globl __irq_tamper + .set __irq_tamper, __default_handler + .weak __irq_rtc + .globl __irq_rtc + .set __irq_rtc, __default_handler + .weak __irq_flash + .globl __irq_flash + .set __irq_flash, __default_handler + .weak __irq_rcc + .globl __irq_rcc + .set __irq_rcc, __default_handler + .weak __irq_exti0 + .globl __irq_exti0 + .set __irq_exti0, __default_handler + .weak __irq_exti1 + .globl __irq_exti1 + .set __irq_exti1, __default_handler + .weak __irq_exti2 + .globl __irq_exti2 + .set __irq_exti2, __default_handler + .weak __irq_exti3 + .globl __irq_exti3 + .set __irq_exti3, __default_handler + .weak __irq_exti4 + .globl __irq_exti4 + .set __irq_exti4, __default_handler + .weak __irq_dma1_channel1 + .globl __irq_dma1_channel1 + .set __irq_dma1_channel1, __default_handler + .weak __irq_dma1_channel2 + .globl __irq_dma1_channel2 + .set __irq_dma1_channel2, __default_handler + .weak __irq_dma1_channel3 + .globl __irq_dma1_channel3 + .set __irq_dma1_channel3, __default_handler + .weak __irq_dma1_channel4 + .globl __irq_dma1_channel4 + .set __irq_dma1_channel4, __default_handler + .weak __irq_dma1_channel5 + .globl __irq_dma1_channel5 + .set __irq_dma1_channel5, __default_handler + .weak __irq_dma1_channel6 + .globl __irq_dma1_channel6 + .set __irq_dma1_channel6, __default_handler + .weak __irq_dma1_channel7 + .globl __irq_dma1_channel7 + .set __irq_dma1_channel7, __default_handler + .weak __irq_adc + .globl __irq_adc + .set __irq_adc, __default_handler + .weak __irq_usb_hp_can_tx + .globl __irq_usb_hp_can_tx + .set __irq_usb_hp_can_tx, __default_handler + .weak __irq_usb_lp_can_rx0 + .globl __irq_usb_lp_can_rx0 + .set __irq_usb_lp_can_rx0, __default_handler + .weak __irq_can_rx1 + .globl __irq_can_rx1 + .set __irq_can_rx1, __default_handler + .weak __irq_can_sce + .globl __irq_can_sce + .set __irq_can_sce, __default_handler + .weak __irq_exti9_5 + .globl __irq_exti9_5 + .set __irq_exti9_5, __default_handler + .weak __irq_tim1_brk + .globl __irq_tim1_brk + .set __irq_tim1_brk, __default_handler + .weak __irq_tim1_up + .globl __irq_tim1_up + .set __irq_tim1_up, __default_handler + .weak __irq_tim1_trg_com + .globl __irq_tim1_trg_com + .set __irq_tim1_trg_com, __default_handler + .weak __irq_tim1_cc + .globl __irq_tim1_cc + .set __irq_tim1_cc, __default_handler + + .weakref __irq_tim2, __default_handler + .globl __irq_tim2 + .weakref __irq_tim3, __default_handler + .globl __irq_tim3 + .weakref __irq_tim4, __default_handler + .globl __irq_tim4 + + .weak __irq_i2c1_ev + .globl __irq_i2c1_ev + .set __irq_i2c1_ev, __default_handler + .weak __irq_i2c1_er + .globl __irq_i2c1_er + .set __irq_i2c1_er, __default_handler + .weak __irq_i2c2_ev + .globl __irq_i2c2_ev + .set __irq_i2c2_ev, __default_handler + .weak __irq_i2c2_er + .globl __irq_i2c2_er + .set __irq_i2c2_er, __default_handler + .weak __irq_spi1 + .globl __irq_spi1 + .set __irq_spi1, __default_handler + .weak __irq_spi2 + .globl __irq_spi2 + .set __irq_spi2, __default_handler + .weak __irq_usart1 + .globl __irq_usart1 + .set __irq_usart1, __default_handler + .weak __irq_usart2 + .globl __irq_usart2 + .set __irq_usart2, __default_handler + .weak __irq_usart3 + .globl __irq_usart3 + .set __irq_usart3, __default_handler + .weak __irq_exti15_10 + .globl __irq_exti15_10 + .set __irq_exti15_10, __default_handler + .weak __irq_rtcalarm + .globl __irq_rtcalarm + .set __irq_rtcalarm, __default_handler + .weak __irq_usbwakeup + .globl __irq_usbwakeup + .set __irq_usbwakeup, __default_handler +#if defined (STM32_HIGH_DENSITY) + .weak __irq_tim8_brk + .globl __irq_tim8_brk + .set __irq_tim8_brk, __default_handler + .weak __irq_tim8_up + .globl __irq_tim8_up + .set __irq_tim8_up, __default_handler + .weak __irq_tim8_trg_com + .globl __irq_tim8_trg_com + .set __irq_tim8_trg_com, __default_handler + .weak __irq_tim8_cc + .globl __irq_tim8_cc + .set __irq_tim8_cc, __default_handler + .weak __irq_adc3 + .globl __irq_adc3 + .set __irq_adc3, __default_handler + .weak __irq_fsmc + .globl __irq_fsmc + .set __irq_fsmc, __default_handler + .weak __irq_sdio + .globl __irq_sdio + .set __irq_sdio, __default_handler + .weak __irq_tim5 + .globl __irq_tim5 + .set __irq_tim5, __default_handler + .weak __irq_spi3 + .globl __irq_spi3 + .set __irq_spi3, __default_handler + .weak __irq_uart4 + .globl __irq_uart4 + .set __irq_uart4, __default_handler + .weak __irq_uart5 + .globl __irq_uart5 + .set __irq_uart5, __default_handler + .weak __irq_tim6 + .globl __irq_tim6 + .set __irq_tim6, __default_handler + .weak __irq_tim7 + .globl __irq_tim7 + .set __irq_tim7, __default_handler + .weak __irq_dma2_channel1 + .globl __irq_dma2_channel1 + .set __irq_dma2_channel1, __default_handler + .weak __irq_dma2_channel2 + .globl __irq_dma2_channel2 + .set __irq_dma2_channel2, __default_handler + .weak __irq_dma2_channel3 + .globl __irq_dma2_channel3 + .set __irq_dma2_channel3, __default_handler + .weak __irq_dma2_channel4_5 + .globl __irq_dma2_channel4_5 + .set __irq_dma2_channel4_5, __default_handler +#endif /* STM32_HIGH_DENSITY */ \ No newline at end of file diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/stm32f1/performance/vector_table.S b/BootLoaders/Boards/stm32/cores/maple/libmaple/stm32f1/performance/vector_table.S new file mode 100644 index 0000000..8be3fa6 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/stm32f1/performance/vector_table.S @@ -0,0 +1,118 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 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. + *****************************************************************************/ + +/* STM32F1 performance line vector table */ + +#include + + .section ".stm32.interrupt_vector" + + .globl __stm32_vector_table + .type __stm32_vector_table, %object + +__stm32_vector_table: +/* CM3 core interrupts */ + .long __msp_init + .long __exc_reset + .long __exc_nmi + .long __exc_hardfault + .long __exc_memmanage + .long __exc_busfault + .long __exc_usagefault + .long __stm32reservedexception7 + .long __stm32reservedexception8 + .long __stm32reservedexception9 + .long __stm32reservedexception10 + .long __exc_svc + .long __exc_debug_monitor + .long __stm32reservedexception13 + .long __exc_pendsv + .long __exc_systick +/* Peripheral interrupts */ + .long __irq_wwdg + .long __irq_pvd + .long __irq_tamper + .long __irq_rtc + .long __irq_flash + .long __irq_rcc + .long __irq_exti0 + .long __irq_exti1 + .long __irq_exti2 + .long __irq_exti3 + .long __irq_exti4 + .long __irq_dma1_channel1 + .long __irq_dma1_channel2 + .long __irq_dma1_channel3 + .long __irq_dma1_channel4 + .long __irq_dma1_channel5 + .long __irq_dma1_channel6 + .long __irq_dma1_channel7 + .long __irq_adc + .long __irq_usb_hp_can_tx + .long __irq_usb_lp_can_rx0 + .long __irq_can_rx1 + .long __irq_can_sce + .long __irq_exti9_5 + .long __irq_tim1_brk + .long __irq_tim1_up + .long __irq_tim1_trg_com + .long __irq_tim1_cc + .long __irq_tim2 + .long __irq_tim3 + .long __irq_tim4 + .long __irq_i2c1_ev + .long __irq_i2c1_er + .long __irq_i2c2_ev + .long __irq_i2c2_er + .long __irq_spi1 + .long __irq_spi2 + .long __irq_usart1 + .long __irq_usart2 + .long __irq_usart3 + .long __irq_exti15_10 + .long __irq_rtcalarm + .long __irq_usbwakeup +#if defined (STM32_HIGH_DENSITY) + .long __irq_tim8_brk + .long __irq_tim8_up + .long __irq_tim8_trg_com + .long __irq_tim8_cc + .long __irq_adc3 + .long __irq_fsmc + .long __irq_sdio + .long __irq_tim5 + .long __irq_spi3 + .long __irq_uart4 + .long __irq_uart5 + .long __irq_tim6 + .long __irq_tim7 + .long __irq_dma2_channel1 + .long __irq_dma2_channel2 + .long __irq_dma2_channel3 + .long __irq_dma2_channel4_5 +#endif /* STM32_HIGH_DENSITY */ + + .size __stm32_vector_table, . - __stm32_vector_table diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/systick.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/systick.c new file mode 100644 index 0000000..7568abe --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/systick.c @@ -0,0 +1,88 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Perry Hung. + * Copyright (c) 2010, 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/systick.c + * @brief System timer (SysTick). + */ + +#include + +volatile uint32 systick_uptime_millis; +static void (*systick_user_callback)(void); + +/** + * @brief Initialize and enable SysTick. + * + * Clocks the system timer with the core clock, turns it on, and + * enables interrupts. + * + * @param reload_val Appropriate reload counter to tick every 1 ms. + */ +void systick_init(uint32 reload_val) { + SYSTICK_BASE->RVR = reload_val; + systick_enable(); +} + +/** + * Clock the system timer with the core clock, but don't turn it + * on or enable interrupt. + */ +void systick_disable() { + SYSTICK_BASE->CSR = SYSTICK_CSR_CLKSOURCE_CORE; +} + +/** + * Clock the system timer with the core clock and turn it on; + * interrupt every 1 ms, for systick_timer_millis. + */ +void systick_enable() { + /* re-enables init registers without changing reload val */ + SYSTICK_BASE->CSR = (SYSTICK_CSR_CLKSOURCE_CORE | + SYSTICK_CSR_ENABLE | + SYSTICK_CSR_TICKINT_PEND); +} + +/** + * @brief Attach a callback to be called from the SysTick exception handler. + * + * To detach a callback, call this function again with a null argument. + */ +void systick_attach_callback(void (*callback)(void)) { + systick_user_callback = callback; +} + +/* + * SysTick ISR + */ + +void __exc_systick(void) { + systick_uptime_millis++; + if (systick_user_callback) { + systick_user_callback(); + } +} diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/timer.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/timer.c new file mode 100644 index 0000000..d548d14 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/timer.c @@ -0,0 +1,550 @@ + +/****************************************************************************** + * 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/timer.c + * @author Marti Bolivar + * @brief Portable timer routines. + */ + +#include +#include +#include "timer_private.h" + +static void disable_channel(timer_dev *dev, uint8 channel); +static void pwm_mode(timer_dev *dev, uint8 channel); +static void output_compare_mode(timer_dev *dev, uint8 channel); +static void encoder_mode(timer_dev *dev, uint8 channel) ;//CARLOS + + +static inline void enable_irq(timer_dev *dev, timer_interrupt_id iid); + +/* + * Devices + * + * Defer to the timer_private API for declaring these. + */ + +#if STM32_HAVE_TIMER(1) +timer_dev timer1 = ADVANCED_TIMER(1); +/** Timer 1 device (advanced) */ +timer_dev *const TIMER1 = &timer1; +#endif +#if STM32_HAVE_TIMER(2) +timer_dev timer2 = GENERAL_TIMER(2); +/** Timer 2 device (general-purpose) */ +timer_dev *const TIMER2 = &timer2; +#endif +#if STM32_HAVE_TIMER(3) +timer_dev timer3 = GENERAL_TIMER(3); +/** Timer 3 device (general-purpose) */ +timer_dev *const TIMER3 = &timer3; +#endif +#if STM32_HAVE_TIMER(4) +timer_dev timer4 = GENERAL_TIMER(4); +/** Timer 4 device (general-purpose) */ +timer_dev *const TIMER4 = &timer4; +#endif +#if STM32_HAVE_TIMER(5) +timer_dev timer5 = GENERAL_TIMER(5); +/** Timer 5 device (general-purpose) */ +timer_dev *const TIMER5 = &timer5; +#endif +#if STM32_HAVE_TIMER(6) +timer_dev timer6 = BASIC_TIMER(6); +/** Timer 6 device (basic) */ +timer_dev *const TIMER6 = &timer6; +#endif +#if STM32_HAVE_TIMER(7) +timer_dev timer7 = BASIC_TIMER(7); +/** Timer 7 device (basic) */ +timer_dev *const TIMER7 = &timer7; +#endif +#if STM32_HAVE_TIMER(8) +timer_dev timer8 = ADVANCED_TIMER(8); +/** Timer 8 device (advanced) */ +timer_dev *const TIMER8 = &timer8; +#endif +#if STM32_HAVE_TIMER(9) +timer_dev timer9 = RESTRICTED_GENERAL_TIMER(9, TIMER_DIER_TIE_BIT); +/** Timer 9 device (general-purpose) */ +timer_dev *const TIMER9 = &timer9; +#endif +#if STM32_HAVE_TIMER(10) +timer_dev timer10 = RESTRICTED_GENERAL_TIMER(10, TIMER_DIER_CC1IE_BIT); +/** Timer 10 device (general-purpose) */ +timer_dev *const TIMER10 = &timer10; +#endif +#if STM32_HAVE_TIMER(11) +timer_dev timer11 = RESTRICTED_GENERAL_TIMER(11, TIMER_DIER_CC1IE_BIT); +/** Timer 11 device (general-purpose) */ +timer_dev *const TIMER11 = &timer11; +#endif +#if STM32_HAVE_TIMER(12) +timer_dev timer12 = RESTRICTED_GENERAL_TIMER(12, TIMER_DIER_TIE_BIT); +/** Timer 12 device (general-purpose) */ +timer_dev *const TIMER12 = &timer12; +#endif +#if STM32_HAVE_TIMER(13) +timer_dev timer13 = RESTRICTED_GENERAL_TIMER(13, TIMER_DIER_CC1IE_BIT); +/** Timer 13 device (general-purpose) */ +timer_dev *const TIMER13 = &timer13; +#endif +#if STM32_HAVE_TIMER(14) +timer_dev timer14 = RESTRICTED_GENERAL_TIMER(14, TIMER_DIER_CC1IE_BIT); +/** Timer 14 device (general-purpose) */ +timer_dev *const TIMER14 = &timer14; +#endif + +/* + * Routines + */ + +/** + * @brief Call a function on timer devices. + * @param fn Function to call on each timer device. + */ +void timer_foreach(void (*fn)(timer_dev*)) { +#if STM32_HAVE_TIMER(1) + fn(TIMER1); +#endif +#if STM32_HAVE_TIMER(2) + fn(TIMER2); +#endif +#if STM32_HAVE_TIMER(3) + fn(TIMER3); +#endif +#if STM32_HAVE_TIMER(4) + fn(TIMER4); +#endif +#if STM32_HAVE_TIMER(5) + fn(TIMER5); +#endif +#if STM32_HAVE_TIMER(6) + fn(TIMER6); +#endif +#if STM32_HAVE_TIMER(7) + fn(TIMER7); +#endif +#if STM32_HAVE_TIMER(8) + fn(TIMER8); +#endif +#if STM32_HAVE_TIMER(9) + fn(TIMER9); +#endif +#if STM32_HAVE_TIMER(10) + fn(TIMER10); +#endif +#if STM32_HAVE_TIMER(11) + fn(TIMER11); +#endif +#if STM32_HAVE_TIMER(12) + fn(TIMER12); +#endif +#if STM32_HAVE_TIMER(13) + fn(TIMER13); +#endif +#if STM32_HAVE_TIMER(14) + fn(TIMER14); +#endif +} + +/** + * Initialize a timer, and reset its register map. + * @param dev Timer to initialize + */ +void timer_init(timer_dev *dev) { + rcc_clk_enable(dev->clk_id); + rcc_reset_dev(dev->clk_id); +} + +/** + * @brief Disable a timer. + * + * The timer will stop counting, all DMA requests and interrupts will + * be disabled, and no state changes will be output. + * + * @param dev Timer to disable. + */ +void timer_disable(timer_dev *dev) { + (dev->regs).bas->CR1 = 0; + (dev->regs).bas->DIER = 0; + switch (dev->type) { + case TIMER_ADVANCED: /* fall-through */ + case TIMER_GENERAL: + (dev->regs).gen->CCER = 0; + break; + case TIMER_BASIC: + break; + } +} + +/** + * Sets the mode of an individual timer channel. + * + * Note that not all timers can be configured in every mode. For + * example, basic timers cannot be configured to output compare mode. + * Be sure to use a timer which is appropriate for the mode you want. + * + * @param dev Timer whose channel mode to set + * @param channel Relevant channel + * @param mode New timer mode for channel + */ +void timer_set_mode(timer_dev *dev, uint8 channel, timer_mode mode) { + ASSERT_FAULT(channel > 0 && channel <= 4); + + /* TODO decide about the basic timers */ + ASSERT(dev->type != TIMER_BASIC); + if (dev->type == TIMER_BASIC) + return; + + switch (mode) { + case TIMER_DISABLED: + disable_channel(dev, channel); + break; + case TIMER_PWM: + pwm_mode(dev, channel); + break; + case TIMER_OUTPUT_COMPARE: + output_compare_mode(dev, channel); + break; + //added by CARLOS. + case TIMER_ENCODER: + encoder_mode(dev, channel); //find a way to pass all the needed stuff on the 8bit var + break; + } +} + +/** + * @brief Determine whether a timer has a particular capture/compare channel. + * + * Different timers have different numbers of capture/compare channels + * (and some have none at all). Use this function to test whether a + * given timer/channel combination will work. + * + * @param dev Timer device + * @param channel Capture/compare channel, from 1 to 4 + * @return Nonzero if dev has channel, zero otherwise. + */ +int timer_has_cc_channel(timer_dev *dev, uint8 channel) { + /* On all currently supported series: advanced and "full-featured" + * general purpose timers have all four channels. Of the + * restricted general timers, timers 9 and 12 have channels 1 and + * 2; the others have channel 1 only. Basic timers have none. */ + rcc_clk_id id = dev->clk_id; + ASSERT((1 <= channel) && (channel <= 4)); + if (id <= RCC_TIMER5 || id == RCC_TIMER8) { + return 1; /* 1 and 8 are advanced, 2-5 are "full" general */ + } else if (id <= RCC_TIMER7) { + return 0; /* 6 and 7 are basic */ + } + /* The rest are restricted general. */ + return (((id == RCC_TIMER9 || id == RCC_TIMER12) && channel <= 2) || + channel == 1); +} + +/** + * @brief Attach a timer interrupt. + * @param dev Timer device + * @param interrupt Interrupt number to attach to; this may be any + * timer_interrupt_id or timer_channel value appropriate + * for the timer. + * @param handler Handler to attach to the given interrupt. + * @see timer_interrupt_id + * @see timer_channel + */ +void timer_attach_interrupt(timer_dev *dev, + uint8 interrupt, + voidFuncPtr handler) { + dev->handlers[interrupt] = handler; + timer_enable_irq(dev, interrupt); + enable_irq(dev, interrupt); +} + +/** + * @brief Detach a timer interrupt. + * @param dev Timer device + * @param interrupt Interrupt number to detach; this may be any + * timer_interrupt_id or timer_channel value appropriate + * for the timer. + * @see timer_interrupt_id + * @see timer_channel + */ +void timer_detach_interrupt(timer_dev *dev, uint8 interrupt) { + timer_disable_irq(dev, interrupt); + dev->handlers[interrupt] = NULL; +} + +//CARLOS +uint8 get_direction(timer_dev *dev){ + return *bb_perip(&(dev->regs).gen->CR1, TIMER_CR1_DIR_BIT); +} + + + +/* + * Utilities + */ + +static void disable_channel(timer_dev *dev, uint8 channel) { + timer_detach_interrupt(dev, channel); + timer_cc_disable(dev, channel); +} + +static void pwm_mode(timer_dev *dev, uint8 channel) { + timer_disable_irq(dev, channel); + timer_oc_set_mode(dev, channel, TIMER_OC_MODE_PWM_1, TIMER_OC_PE); + timer_cc_enable(dev, channel); +} + +static void output_compare_mode(timer_dev *dev, uint8 channel) { + timer_oc_set_mode(dev, channel, TIMER_OC_MODE_ACTIVE_ON_MATCH, 0); + timer_cc_enable(dev, channel); +} + +//added by CARLOS. +static void encoder_mode(timer_dev *dev, uint8 channel) { + + //prescaler. + //(dev->regs).gen->PSC = 1; + + //map inputs. + (dev->regs).gen->CCMR1 = TIMER_CCMR1_CC1S_INPUT_TI1 | TIMER_CCMR1_CC2S_INPUT_TI2 | TIMER_CCMR1_IC2F | TIMER_CCMR1_IC1F ; + + (dev->regs).gen->SMCR = TIMER_SMCR_SMS_ENCODER3; //choose encoder 3, counting on both edges. + + //polarity + //(dev->regs).gen->CCER = TIMER_CCER_CC1P; //to invert the counting, only one of the inputs should be inverted. + + //set the interval used by the encoder. + //timer_set_reload(dev, 1000); + +// (dev->regs).gen->CR1 |=TIMER_CR1_UDIS_BIT; + + //run timer + timer_resume(dev); +} + + + +static void enable_adv_irq(timer_dev *dev, timer_interrupt_id id); +static void enable_bas_gen_irq(timer_dev *dev); + +static inline void enable_irq(timer_dev *dev, timer_interrupt_id iid) { + if (dev->type == TIMER_ADVANCED) { + enable_adv_irq(dev, iid); + } else { + enable_bas_gen_irq(dev); + } +} + +/* Advanced control timers have several IRQ lines corresponding to + * different timer interrupts. + * + * Note: This function assumes that the only advanced timers are TIM1 + * and TIM8, and needs the obvious changes if that assumption is + * violated by a later STM32 series. */ +static void enable_adv_irq(timer_dev *dev, timer_interrupt_id id) { + uint8 is_tim1 = dev->clk_id == RCC_TIMER1; + nvic_irq_num irq_num; + switch (id) { + case TIMER_UPDATE_INTERRUPT: + irq_num = (is_tim1 ? + NVIC_TIMER1_UP_TIMER10 : + NVIC_TIMER8_UP_TIMER13); + break; + case TIMER_CC1_INTERRUPT: /* Fall through */ + case TIMER_CC2_INTERRUPT: /* ... */ + case TIMER_CC3_INTERRUPT: /* ... */ + case TIMER_CC4_INTERRUPT: + irq_num = is_tim1 ? NVIC_TIMER1_CC : NVIC_TIMER8_CC; + break; + case TIMER_COM_INTERRUPT: /* Fall through */ + case TIMER_TRG_INTERRUPT: + irq_num = (is_tim1 ? + NVIC_TIMER1_TRG_COM_TIMER11 : + NVIC_TIMER8_TRG_COM_TIMER14); + break; + case TIMER_BREAK_INTERRUPT: + irq_num = (is_tim1 ? + NVIC_TIMER1_BRK_TIMER9 : + NVIC_TIMER8_BRK_TIMER12); + break; + default: + /* Can't happen, but placate the compiler */ + ASSERT(0); + return; + } + nvic_irq_enable(irq_num); +} + +/* Basic and general purpose timers have a single IRQ line, which is + * shared by all interrupts supported by a particular timer. */ +static void enable_bas_gen_irq(timer_dev *dev) { + nvic_irq_num irq_num; + switch (dev->clk_id) { + case RCC_TIMER2: + irq_num = NVIC_TIMER2; + break; + case RCC_TIMER3: + irq_num = NVIC_TIMER3; + break; + case RCC_TIMER4: + irq_num = NVIC_TIMER4; + break; + case RCC_TIMER5: + irq_num = NVIC_TIMER5; + break; + case RCC_TIMER6: + irq_num = NVIC_TIMER6; + break; + case RCC_TIMER7: + irq_num = NVIC_TIMER7; + break; + case RCC_TIMER9: + irq_num = NVIC_TIMER1_BRK_TIMER9; + break; + case RCC_TIMER10: + irq_num = NVIC_TIMER1_UP_TIMER10; + break; + case RCC_TIMER11: + irq_num = NVIC_TIMER1_TRG_COM_TIMER11; + break; + case RCC_TIMER12: + irq_num = NVIC_TIMER8_BRK_TIMER12; + break; + case RCC_TIMER13: + irq_num = NVIC_TIMER8_UP_TIMER13; + break; + case RCC_TIMER14: + irq_num = NVIC_TIMER8_TRG_COM_TIMER14; + break; + default: + ASSERT_FAULT(0); + return; + } + nvic_irq_enable(irq_num); +} + + +/* Note. + * + * 2015/07/06 Roger Clark + * + * The IRQ handlers were initially in timer_f1.c however this seems to cause problems + * in which the compiler / linker doesn't always link all the required handlers. + * The work around was to move the handlers into this file + */ + +/* + * IRQ handlers + * + * Defer to the timer_private dispatch API. + * + * FIXME: The names of these handlers are inaccurate since XL-density + * devices came out. Update these to match the STM32F2 names, maybe + * using some weak symbol magic to preserve backwards compatibility if + * possible. Once that's done, we can just move the IRQ handlers into + * the top-level libmaple/timer.c, and there will be no need for this + * file. + */ + +void __irq_tim1_brk(void) { + dispatch_adv_brk(TIMER1); +#if STM32_HAVE_TIMER(9) + dispatch_tim_9_12(TIMER9); +#endif +} + +void __irq_tim1_up(void) { + dispatch_adv_up(TIMER1); +#if STM32_HAVE_TIMER(10) + dispatch_tim_10_11_13_14(TIMER10); +#endif +} + +void __irq_tim1_trg_com(void) { + dispatch_adv_trg_com(TIMER1); +#if STM32_HAVE_TIMER(11) + dispatch_tim_10_11_13_14(TIMER11); +#endif +} + +void __irq_tim1_cc(void) { + dispatch_adv_cc(TIMER1); +} + +void __irq_tim2(void) { + dispatch_general(TIMER2); +} + +void __irq_tim3(void) { + dispatch_general(TIMER3); +} + +void __irq_tim4(void) { + dispatch_general(TIMER4); +} + +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) +void __irq_tim5(void) { + dispatch_general(TIMER5); +} + +void __irq_tim6(void) { + dispatch_basic(TIMER6); +} + +void __irq_tim7(void) { + dispatch_basic(TIMER7); +} + +void __irq_tim8_brk(void) { + dispatch_adv_brk(TIMER8); +#if STM32_HAVE_TIMER(12) + dispatch_tim_9_12(TIMER12); +#endif +} + +void __irq_tim8_up(void) { + dispatch_adv_up(TIMER8); +#if STM32_HAVE_TIMER(13) + dispatch_tim_10_11_13_14(TIMER13); +#endif +} + +void __irq_tim8_trg_com(void) { + dispatch_adv_trg_com(TIMER8); +#if STM32_HAVE_TIMER(14) + dispatch_tim_10_11_13_14(TIMER14); +#endif +} + +void __irq_tim8_cc(void) { + dispatch_adv_cc(TIMER8); +} +#endif /* defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) */ \ No newline at end of file diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/timer_f1.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/timer_f1.c new file mode 100644 index 0000000..d67cf3f --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/timer_f1.c @@ -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 libmaple/stm32f1/timer.c + * @author Marti Bolivar + * @brief STM32F1 timer. + */ + +/* + * 2015/07/06 + * Note. The IRQ handlers which were initially in this file have been moved to timer.c + * to resolve a linker issue in where some IRQ handlers were not being linked even though + * they were being used. + * This file has been retains for historical reasons, but can be moved at some time in the future + * when full testing of the code in the new location has been completed. + */ + diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/usart.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/usart.c new file mode 100644 index 0000000..d2029ee --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/usart.c @@ -0,0 +1,152 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Perry Hung. + * Copyright (c) 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/usart.c + * @author Marti Bolivar , + * Perry Hung + * @brief Portable USART routines + */ + +#include + +/** + * @brief Initialize a serial port. + * @param dev Serial port to be initialized + */ +void usart_init(usart_dev *dev) { + rb_init(dev->rb, USART_RX_BUF_SIZE, dev->rx_buf); + rb_init(dev->wb, USART_TX_BUF_SIZE, dev->tx_buf); + rcc_clk_enable(dev->clk_id); + nvic_irq_enable(dev->irq_num); +} + +/** + * @brief Enable a serial port. + * + * USART is enabled in single buffer transmission mode, multibuffer + * receiver mode, 8n1. + * + * Serial port must have a baud rate configured to work properly. + * + * @param dev Serial port to enable. + * @see usart_set_baud_rate() + */ +void usart_enable(usart_dev *dev) { + usart_reg_map *regs = dev->regs; + regs->CR1 |= (USART_CR1_TE | USART_CR1_RE | USART_CR1_RXNEIE);// don't change the word length etc, and 'or' in the patten not overwrite |USART_CR1_M_8N1); + regs->CR1 |= USART_CR1_UE; +} + +/** + * @brief Turn off a serial port. + * @param dev Serial port to be disabled + */ +void usart_disable(usart_dev *dev) { + /* FIXME this misbehaves (on F1) if you try to use PWM on TX afterwards */ + usart_reg_map *regs = dev->regs; + + while(!rb_is_empty(dev->wb)) + ; // wait for TX completed + /* TC bit must be high before disabling the USART */ + while((regs->CR1 & USART_CR1_UE) && !(regs->SR & USART_SR_TC)) + ; + + /* Disable UE */ + regs->CR1 &= ~USART_CR1_UE; + + /* Clean up buffer */ + usart_reset_rx(dev); + usart_reset_tx(dev); +} + +/** + * @brief Nonblocking USART transmit + * @param dev Serial port to transmit over + * @param buf Buffer to transmit + * @param len Maximum number of bytes to transmit + * @return Number of bytes transmitted + */ +uint32 usart_tx(usart_dev *dev, const uint8 *buf, uint32 len) { + usart_reg_map *regs = dev->regs; + uint32 txed = 0; + while (rb_is_empty(dev->wb) && (regs->SR & USART_SR_TXE) && (txed < len)) { + regs->DR = buf[txed++]; + } + regs->CR1 &= ~((uint32)USART_CR1_TXEIE); // disable TXEIE while populating the buffer + while (txed < len) { + if (rb_safe_insert(dev->wb, buf[txed])) { + txed++; + } + else + break; + } + if (!rb_is_empty(dev->wb)) { + regs->CR1 |= USART_CR1_TXEIE; + } + return txed; +} + +/** + * @brief Nonblocking USART receive. + * @param dev Serial port to receive bytes from + * @param buf Buffer to store received bytes into + * @param len Maximum number of bytes to store + * @return Number of bytes received + */ +uint32 usart_rx(usart_dev *dev, uint8 *buf, uint32 len) { + uint32 rxed = 0; + while (usart_data_available(dev) && rxed < len) { + *buf++ = usart_getc(dev); + rxed++; + } + return rxed; +} + +/** + * @brief Transmit an unsigned integer to the specified serial port in + * decimal format. + * + * This function blocks until the integer's digits have been + * completely transmitted. + * + * @param dev Serial port to send on + * @param val Number to print + */ +void usart_putudec(usart_dev *dev, uint32 val) { + char digits[12]; + int i = 0; + + do { + digits[i++] = val % 10 + '0'; + val /= 10; + } while (val > 0); + + while (--i >= 0) { + usart_putc(dev, digits[i]); + } +} diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/usart_f1.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/usart_f1.c new file mode 100644 index 0000000..1d3948d --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/usart_f1.c @@ -0,0 +1,225 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * Copyright (c) 2010 Perry Hung. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/usart.c + * @author Marti Bolivar , + * Perry Hung + * @brief STM32F1 USART. + */ + +#include +#include +#include "usart_private.h" + +/* + * Devices + */ + +static ring_buffer usart1_rb; +static ring_buffer usart1_wb; +static usart_dev usart1 = { + .regs = USART1_BASE, + .rb = &usart1_rb, + .wb = &usart1_wb, + .max_baud = 4500000UL, + .clk_id = RCC_USART1, + .irq_num = NVIC_USART1, +}; +/** USART1 device */ +usart_dev *USART1 = &usart1; + +static ring_buffer usart2_rb; +static ring_buffer usart2_wb; +static usart_dev usart2 = { + .regs = USART2_BASE, + .rb = &usart2_rb, + .wb = &usart2_wb, + .max_baud = 2250000UL, + .clk_id = RCC_USART2, + .irq_num = NVIC_USART2, +}; +/** USART2 device */ +usart_dev *USART2 = &usart2; + +static ring_buffer usart3_rb; +static ring_buffer usart3_wb; +static usart_dev usart3 = { + .regs = USART3_BASE, + .rb = &usart3_rb, + .wb = &usart3_wb, + .max_baud = 2250000UL, + .clk_id = RCC_USART3, + .irq_num = NVIC_USART3, +}; +/** USART3 device */ +usart_dev *USART3 = &usart3; + +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) +static ring_buffer uart4_rb; +static ring_buffer uart4_wb; +static usart_dev uart4 = { + .regs = UART4_BASE, + .rb = &uart4_rb, + .wb = &uart4_wb, + .max_baud = 2250000UL, + .clk_id = RCC_UART4, + .irq_num = NVIC_UART4, +}; +/** UART4 device */ +usart_dev *UART4 = &uart4; + +static ring_buffer uart5_rb; +static ring_buffer uart5_wb; +static usart_dev uart5 = { + .regs = UART5_BASE, + .rb = &uart5_rb, + .wb = &uart5_wb, + .max_baud = 2250000UL, + .clk_id = RCC_UART5, + .irq_num = NVIC_UART5, +}; +/** UART5 device */ +usart_dev *UART5 = &uart5; +#endif + +/* + * Routines + */ + +void usart_config_gpios_async(usart_dev *udev, + gpio_dev *rx_dev, uint8 rx, + gpio_dev *tx_dev, uint8 tx, + unsigned flags) { + gpio_set_mode(rx_dev, rx, GPIO_INPUT_FLOATING); + gpio_set_mode(tx_dev, tx, GPIO_AF_OUTPUT_PP); +/* +CR1 bit 12 Word length 0=8 1=9 +CR1 bit 11 wake (default value is 0) we can safely set this value to 0 (zero) each time +CR1 bit 10 parity enable (1 = enabled) +CR1 bit 9 Parity selection 0 = Even 1 = Odd +CR2 bits 13 and 12 00 = 1 01 = 0.5 10 = 2 11 = 1.5 +Not all USARTs support 1.5 or 0.5 bits so its best to avoid them. +When parity enabled the word length must be increased (CR1 bit 12 set). +Word length of 9 bit with parity is not supported. + CR2 CR1 + 0B00 0000 + 0B10 0000 + 0B00 1000 + 0B10 1000 + + 0B00 0010 + 0B10 0010 + 0B00 1010 + 0B10 1010 + + 0B00 0011 + 0B10 0011 + 0B00 1011 + 0B10 1011 + +#define SERIAL_8N1 0B 0000 0000 +#define SERIAL_8N2 0B 0010 0000 +#define SERIAL_9N1 0B 0000 1000 +#define SERIAL_9N2 0B 0010 1000 + +#define SERIAL_8E1 0B 0000 1010 +#define SERIAL_8E2 0B 0010 1010 +//#define SERIAL_9E1 0B 0000 1010 +//#define SERIAL_9E2 0B 0010 1010 + +#define SERIAL_8O1 0B 0000 1011 +#define SERIAL_8O2 0B 0010 1011 +//#define SERIAL_9O1 0B 0000 1011 +//#define SERIAL_9O2 0B 0010 1011 +*/ + + udev->regs->CR1 = (udev->regs->CR1 & 0B1110000111111111) | ((uint32_t)(flags&0x0F)<<9); + udev->regs->CR2 = (udev->regs->CR2 & 0B1100111111111111) | ((uint32_t)(flags&0x30)<<8); +} + +void usart_set_baud_rate(usart_dev *dev, uint32 clock_speed, uint32 baud) { + uint32 integer_part; + uint32 fractional_part; + uint32 tmp; + + /* Figure out the clock speed, if the user doesn't give one. */ + if (clock_speed == 0) { + clock_speed = _usart_clock_freq(dev); + } + ASSERT(clock_speed); + + /* Convert desired baud rate to baud rate register setting. */ + integer_part = (25 * clock_speed) / (4 * baud); + tmp = (integer_part / 100) << 4; + fractional_part = integer_part - (100 * (tmp >> 4)); + tmp |= (((fractional_part * 16) + 50) / 100) & ((uint8)0x0F); + + dev->regs->BRR = (uint16)tmp; +} + +/** + * @brief Call a function on each USART. + * @param fn Function to call. + */ +void usart_foreach(void (*fn)(usart_dev*)) { + fn(USART1); + fn(USART2); + fn(USART3); +#ifdef STM32_HIGH_DENSITY + fn(UART4); + fn(UART5); +#endif +} + +/* + * Interrupt handlers. + */ + +void __irq_usart1(void) { + usart_irq(&usart1_rb, &usart1_wb, USART1_BASE); +} + +/* +void __irq_usart2(void) { + usart_irq(&usart2_rb, &usart2_wb, USART2_BASE); +} + +void __irq_usart3(void) { + usart_irq(&usart3_rb, &usart3_wb, USART3_BASE); +} +*/ + +#ifdef STM32_HIGH_DENSITY +void __irq_uart4(void) { + usart_irq(&uart4_rb, &uart4_wb, UART4_BASE); +} + +void __irq_uart5(void) { + usart_irq(&uart5_rb, &uart5_wb, UART5_BASE); +} +#endif diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/usart_private.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/usart_private.c new file mode 100644 index 0000000..0eaacdf --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/usart_private.c @@ -0,0 +1,41 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/usart_private.c + * @author Marti Bolivar + * @brief Private USART routines. + */ + +#include "usart_private.h" +#include +#include + +uint32 _usart_clock_freq(usart_dev *dev) { + rcc_clk_domain domain = rcc_dev_clk(dev->clk_id); + return (domain == RCC_APB1 ? STM32_PCLK1 : + (domain == RCC_APB2 ? STM32_PCLK2 : 0)); +} diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/usb/README b/BootLoaders/Boards/stm32/cores/maple/libmaple/usb/README new file mode 100644 index 0000000..d0fca8d --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/usb/README @@ -0,0 +1,63 @@ +The USB submodule of libmaple is a separate piece of the codebase for +reasons that are largely historical. + +Current Status: + + There's only support for the USB device peripheral found on + STM32F103s. + + We rely on the low level core library provided by ST to implement + the USB transfer protocol for control endpoint transfers. + + The virtual com port (which is exposed via + ) serves two important purposes. + + 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 + application binary into RAM/FLASH). Thus, without this virtual com + port, it would be necessary to find an alternative means to reset + the chip in order to enable the bootloader. + + If you would like to develop your own USB application for whatever + 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 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. + + It would be possible to build a compound USB device, that + implements endpoints for both the virtual COM port as well as some + other components (mass storage etc.). However, this turns out to + 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 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, 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: + + - 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/BootLoaders/Boards/stm32/cores/maple/libmaple/usb/rules.mk b/BootLoaders/Boards/stm32/cores/maple/libmaple/usb/rules.mk new file mode 100644 index 0000000..e8ccc15 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/usb/rules.mk @@ -0,0 +1,45 @@ +# Standard things +sp := $(sp).x +dirstack_$(sp) := $(d) +d := $(dir) +BUILDDIRS += $(BUILD_PATH)/$(d) + +# Local flags +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) := +# 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)/%) + +OBJS_$(d) := $(sFILES_$(d):%.S=$(BUILD_PATH)/%.o) \ + $(cFILES_$(d):%.c=$(BUILD_PATH)/%.o) +DEPS_$(d) := $(OBJS_$(d):%.o=%.d) + +$(OBJS_$(d)): TGT_CFLAGS := $(CFLAGS_$(d)) +$(OBJS_$(d)): TGT_ASFLAGS := + +TGT_BIN += $(OBJS_$(d)) + +# Standard things +-include $(DEPS_$(d)) +d := $(dirstack_$(sp)) +sp := $(basename $(sp)) diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/usb/stm32f1/usb.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/usb/stm32f1/usb.c new file mode 100644 index 0000000..f837eb6 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/usb/stm32f1/usb.c @@ -0,0 +1,387 @@ +/****************************************************************************** + * 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/stm32f1/usb.c + * @brief USB support. + * + * This is a mess. + */ + +#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, + .prevState = 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->prevState = USBLIB->state; + 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; + USBLIB->state = USBLIB->prevState; + 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; + USBLIB->state = USBLIB->prevState; + 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_ISTR_SUSP); + 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_WKUP | 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/BootLoaders/Boards/stm32/cores/maple/libmaple/usb/stm32f1/usb_cdcacm.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/usb/stm32f1/usb_cdcacm.c new file mode 100644 index 0000000..cba050f --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/usb/stm32f1/usb_cdcacm.c @@ -0,0 +1,809 @@ +/****************************************************************************** + * 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/stm32f1/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_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); + +/* + * Descriptors + */ + +/* FIXME move to Wirish */ +#define LEAFLABS_ID_VENDOR 0x1EAF +#define MAPLE_ID_PRODUCT 0x0004 +static const usb_descriptor_device usbVcomDescriptor_Device = + USB_CDCACM_DECLARE_DEV_DESC(LEAFLABS_ID_VENDOR, MAPLE_ID_PRODUCT); + +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; + +#define MAX_POWER (100 >> 1) +static 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 | + USB_CDCACM_MANAGEMENT_ENDP), + .bmAttributes = USB_EP_TYPE_INTERRUPT, + .wMaxPacketSize = USB_CDCACM_MANAGEMENT_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 | + USB_CDCACM_RX_ENDP), + .bmAttributes = USB_EP_TYPE_BULK, + .wMaxPacketSize = USB_CDCACM_RX_EPSIZE, + .bInterval = 0x00, + }, + + .DataInEndpoint = { + .bLength = sizeof(usb_descriptor_endpoint), + .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT, + .bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_IN | USB_CDCACM_TX_ENDP), + .bmAttributes = USB_EP_TYPE_BULK, + .wMaxPacketSize = USB_CDCACM_TX_EPSIZE, + .bInterval = 0x00, + }, +}; + +/* + String Descriptors: + + 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 + +*/ + +/* Unicode language identifier: 0x0409 is US English */ +/* FIXME move to Wirish */ +static const usb_descriptor_string usbVcomDescriptor_LangID = { + .bLength = USB_DESCRIPTOR_STRING_LEN(1), + .bDescriptorType = USB_DESCRIPTOR_TYPE_STRING, + .bString = {0x09, 0x04}, +}; + +/* FIXME move to Wirish */ +static const usb_descriptor_string usbVcomDescriptor_iManufacturer = { + .bLength = USB_DESCRIPTOR_STRING_LEN(8), + .bDescriptorType = USB_DESCRIPTOR_TYPE_STRING, + .bString = {'L', 0, 'e', 0, 'a', 0, 'f', 0, + 'L', 0, 'a', 0, 'b', 0, 's', 0}, +}; + +/* FIXME move to Wirish */ +static const usb_descriptor_string usbVcomDescriptor_iProduct = { + .bLength = USB_DESCRIPTOR_STRING_LEN(5), + .bDescriptorType = USB_DESCRIPTOR_TYPE_STRING, + .bString = {'M', 0, 'a', 0, 'p', 0, 'l', 0, 'e', 0}, +}; + +static ONE_DESCRIPTOR Device_Descriptor = { + (uint8*)&usbVcomDescriptor_Device, + sizeof(usb_descriptor_device) +}; + +static ONE_DESCRIPTOR Config_Descriptor = { + (uint8*)&usbVcomDescriptor_Config, + sizeof(usb_descriptor_config) +}; + +#define N_STRING_DESCRIPTORS 3 +static ONE_DESCRIPTOR String_Descriptor[N_STRING_DESCRIPTORS] = { + {(uint8*)&usbVcomDescriptor_LangID, USB_DESCRIPTOR_STRING_LEN(1)}, + {(uint8*)&usbVcomDescriptor_iManufacturer,USB_DESCRIPTOR_STRING_LEN(8)}, + {(uint8*)&usbVcomDescriptor_iProduct, USB_DESCRIPTOR_STRING_LEN(5)} +}; + +/* + * Etc. + */ + +/* I/O state */ + +#define CDC_SERIAL_RX_BUFFER_SIZE 256 // must be power of 2 +#define CDC_SERIAL_RX_BUFFER_SIZE_MASK (CDC_SERIAL_RX_BUFFER_SIZE-1) + +/* Received data */ +static volatile uint8 vcomBufferRx[CDC_SERIAL_RX_BUFFER_SIZE]; +/* Write index to vcomBufferRx */ +static volatile uint32 rx_head; +/* Read index from vcomBufferRx */ +static volatile uint32 rx_tail; + +#define CDC_SERIAL_TX_BUFFER_SIZE 256 // must be power of 2 +#define CDC_SERIAL_TX_BUFFER_SIZE_MASK (CDC_SERIAL_TX_BUFFER_SIZE-1) +// Tx data +static volatile uint8 vcomBufferTx[CDC_SERIAL_TX_BUFFER_SIZE]; +// Write index to vcomBufferTx +static volatile uint32 tx_head; +// Read index from vcomBufferTx +static volatile uint32 tx_tail; +// Are we currently sending an IN packet? +static volatile int8 transmitting; + + + +/* Other state (line coding, DTR/RTS) */ + +static volatile usb_cdcacm_line_coding line_coding = { + /* This default is 115200 baud, 8N1. */ + .dwDTERate = 115200, + .bCharFormat = USB_CDCACM_STOP_BITS_1, + .bParityType = USB_CDCACM_PARITY_NONE, + .bDataBits = 8, +}; + +/* DTR in bit 0, RTS in bit 1. */ +static volatile 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/ + * + * Mark these weak so they can be overriden to implement other USB + * functionality. + */ + +#define NUM_ENDPTS 0x04 +__weak DEVICE Device_Table = { + .Total_Endpoint = NUM_ENDPTS, + .Total_Configuration = 1 +}; + +#define MAX_PACKET_SIZE 0x40 /* 64B, maximum for USB FS Devices */ +__weak 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 +}; + +__weak 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 +}; + +/* + * User hooks + */ + +static void (*rx_hook)(unsigned, void*) = 0; +static void (*iface_setup_hook)(unsigned, void*) = 0; + +void usb_cdcacm_set_hooks(unsigned hook_flags, void (*hook)(unsigned, void*)) { + if (hook_flags & USB_CDCACM_HOOK_RX) { + rx_hook = hook; + } + if (hook_flags & USB_CDCACM_HOOK_IFACE_SETUP) { + iface_setup_hook = hook; + } +} + +/* + * CDC ACM interface + */ + +void usb_cdcacm_enable(gpio_dev *disc_dev, uint8 disc_bit) { + /* Present ourselves to the host. Writing 0 to "disc" pin must + * pull USB_DP pin up while leaving USB_DM pulled down by the + * transceiver. See USB 2.0 spec, section 7.1.7.3. */ + + if (disc_dev!=NULL) + { + gpio_set_mode(disc_dev, disc_bit, GPIO_OUTPUT_PP); + gpio_write_bit(disc_dev, disc_bit, 0); + } + + /* Initialize the USB peripheral. */ + usb_init_usblib(USBLIB, ep_int_in, ep_int_out); +} + +void usb_cdcacm_disable(gpio_dev *disc_dev, uint8 disc_bit) { + /* Turn off the interrupt and signal disconnect (see e.g. USB 2.0 + * spec, section 7.1.7.3). */ + nvic_irq_disable(NVIC_USB_LP_CAN_RX0); + if (disc_dev!=NULL) + { + 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 user buffer into the USB peripheral TX + * buffer, and returns the number of bytes copied. */ +uint32 usb_cdcacm_tx(const uint8* buf, uint32 len) +{ + if (len==0) return 0; // no data to send + + uint32 head = tx_head; // load volatile variable + uint32 tx_unsent = (head - tx_tail) & CDC_SERIAL_TX_BUFFER_SIZE_MASK; + + // We can only put bytes in the buffer if there is place + if (len > (CDC_SERIAL_TX_BUFFER_SIZE-tx_unsent-1) ) { + len = (CDC_SERIAL_TX_BUFFER_SIZE-tx_unsent-1); + } + if (len==0) return 0; // buffer full + + uint16 i; + // copy data from user buffer to USB Tx buffer + for (i=0; i0 ? transmitting : 0); +} + +uint16 usb_cdcacm_get_pending(void) { + return (tx_head - tx_tail) & CDC_SERIAL_TX_BUFFER_SIZE_MASK; +} + +/* Non-blocking 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) +{ + /* Copy bytes to buffer. */ + uint32 n_copied = usb_cdcacm_peek(buf, len); + + /* Mark bytes as read. */ + uint16 tail = rx_tail; // load volatile variable + tail = (tail + n_copied) & CDC_SERIAL_RX_BUFFER_SIZE_MASK; + rx_tail = tail; // store volatile variable + + uint32 rx_unread = (rx_head - tail) & CDC_SERIAL_RX_BUFFER_SIZE_MASK; + // If buffer was emptied to a pre-set value, re-enable the RX endpoint + if ( rx_unread <= 64 ) { // experimental value, gives the best performance + usb_set_ep_rx_stat(USB_CDCACM_RX_ENDP, USB_EP_STAT_RX_VALID); + } + return n_copied; +} + +/* Non-blocking byte lookahead. + * + * Looks at unread bytes without marking them as read. */ +uint32 usb_cdcacm_peek(uint8* buf, uint32 len) +{ + int i; + uint32 tail = rx_tail; + uint32 rx_unread = (rx_head-tail) & CDC_SERIAL_RX_BUFFER_SIZE_MASK; + + if (len > rx_unread) { + len = rx_unread; + } + + for (i = 0; i < len; i++) { + buf[i] = vcomBufferRx[tail]; + tail = (tail + 1) & CDC_SERIAL_RX_BUFFER_SIZE_MASK; + } + + return len; +} + +uint32 usb_cdcacm_peek_ex(uint8* buf, uint32 offset, uint32 len) +{ + int i; + uint32 tail = (rx_tail + offset) & CDC_SERIAL_RX_BUFFER_SIZE_MASK ; + uint32 rx_unread = (rx_head-tail) & CDC_SERIAL_RX_BUFFER_SIZE_MASK; + + if (len + offset > rx_unread) { + len = rx_unread - offset; + } + + for (i = 0; i < len; i++) { + buf[i] = vcomBufferRx[tail]; + tail = (tail + 1) & CDC_SERIAL_RX_BUFFER_SIZE_MASK; + } + + return len; +} + +/* Roger Clark. Added. for Arduino 1.0 API support of Serial.peek() */ +int usb_cdcacm_peek_char() +{ + if (usb_cdcacm_data_available() == 0) + { + return -1; + } + + return vcomBufferRx[rx_tail]; +} + +uint8 usb_cdcacm_get_dtr() { + return ((line_dtr_rts & USB_CDCACM_CONTROL_LINE_DTR) != 0); +} + +uint8 usb_cdcacm_get_rts() { + return ((line_dtr_rts & USB_CDCACM_CONTROL_LINE_RTS) != 0); +} + +void usb_cdcacm_get_line_coding(usb_cdcacm_line_coding *ret) { + ret->dwDTERate = line_coding.dwDTERate; + ret->bCharFormat = line_coding.bCharFormat; + ret->bParityType = line_coding.bParityType; + ret->bDataBits = line_coding.bDataBits; +} + +int usb_cdcacm_get_baud(void) { + return line_coding.dwDTERate; +} + +int usb_cdcacm_get_stop_bits(void) { + return line_coding.bCharFormat; +} + +int usb_cdcacm_get_parity(void) { + return line_coding.bParityType; +} + +int usb_cdcacm_get_n_data_bits(void) { + return line_coding.bDataBits; +} + +/* + * Callbacks + */ +static void vcomDataTxCb(void) +{ + uint32 tail = tx_tail; // load volatile variable + uint32 tx_unsent = (tx_head - tail) & CDC_SERIAL_TX_BUFFER_SIZE_MASK; + if (tx_unsent==0) { + if ( (--transmitting)==0) goto flush; // no more data to send + return; // it was already flushed, keep Tx endpoint disabled + } + transmitting = 1; + // We can only send up to USB_CDCACM_TX_EPSIZE bytes in the endpoint. + if (tx_unsent > USB_CDCACM_TX_EPSIZE) { + tx_unsent = USB_CDCACM_TX_EPSIZE; + } + // copy the bytes from USB Tx buffer to PMA buffer + uint32 *dst = usb_pma_ptr(USB_CDCACM_TX_ADDR); + uint16 tmp = 0; + uint16 val; + int i; + for (i = 0; i < tx_unsent; i++) { + val = vcomBufferTx[tail]; + tail = (tail + 1) & CDC_SERIAL_TX_BUFFER_SIZE_MASK; + if (i&1) { + *dst++ = tmp | (val<<8); + } else { + tmp = val; + } + } + if ( tx_unsent&1 ) { + *dst = tmp; + } + tx_tail = tail; // store volatile variable +flush: + // enable Tx endpoint + usb_set_ep_tx_count(USB_CDCACM_TX_ENDP, tx_unsent); + usb_set_ep_tx_stat(USB_CDCACM_TX_ENDP, USB_EP_STAT_TX_VALID); +} + + +static void vcomDataRxCb(void) +{ + uint32 head = rx_head; // load volatile variable + + uint32 ep_rx_size = usb_get_ep_rx_count(USB_CDCACM_RX_ENDP); + // This copy won't overwrite unread bytes as long as there is + // enough room in the USB Rx buffer for next packet + uint32 *src = usb_pma_ptr(USB_CDCACM_RX_ADDR); + uint16 tmp = 0; + uint8 val; + uint32 i; + for (i = 0; i < ep_rx_size; i++) { + if (i&1) { + val = tmp>>8; + } else { + tmp = *src++; + val = tmp&0xFF; + } + vcomBufferRx[head] = val; + head = (head + 1) & CDC_SERIAL_RX_BUFFER_SIZE_MASK; + } + rx_head = head; // store volatile variable + + uint32 rx_unread = (head - rx_tail) & CDC_SERIAL_RX_BUFFER_SIZE_MASK; + // only enable further Rx if there is enough room to receive one more packet + if ( rx_unread < (CDC_SERIAL_RX_BUFFER_SIZE-USB_CDCACM_RX_EPSIZE) ) { + usb_set_ep_rx_stat(USB_CDCACM_RX_ENDP, USB_EP_STAT_RX_VALID); + } + + if (rx_hook) { + rx_hook(USB_CDCACM_HOOK_RX, 0); + } +} + +static uint8* vcomGetSetLineCoding(uint16 length) { + if (length == 0) { + pInformation->Ctrl_Info.Usb_wLength = sizeof(struct usb_cdcacm_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; +} + +#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, USB_CDCACM_CTRL_RX_ADDR); + usb_set_ep_tx_addr(USB_EP0, USB_CDCACM_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(USB_CDCACM_MANAGEMENT_ENDP, USB_EP_EP_TYPE_INTERRUPT); + usb_set_ep_tx_addr(USB_CDCACM_MANAGEMENT_ENDP, + USB_CDCACM_MANAGEMENT_ADDR); + usb_set_ep_tx_stat(USB_CDCACM_MANAGEMENT_ENDP, USB_EP_STAT_TX_NAK); + usb_set_ep_rx_stat(USB_CDCACM_MANAGEMENT_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(USB_CDCACM_RX_ENDP, USB_EP_EP_TYPE_BULK); + usb_set_ep_rx_addr(USB_CDCACM_RX_ENDP, USB_CDCACM_RX_ADDR); + usb_set_ep_rx_count(USB_CDCACM_RX_ENDP, USB_CDCACM_RX_EPSIZE); + usb_set_ep_rx_stat(USB_CDCACM_RX_ENDP, USB_EP_STAT_RX_VALID); + + /* set up data endpoint IN (TX) */ + usb_set_ep_type(USB_CDCACM_TX_ENDP, USB_EP_EP_TYPE_BULK); + usb_set_ep_tx_addr(USB_CDCACM_TX_ENDP, USB_CDCACM_TX_ADDR); + usb_set_ep_tx_stat(USB_CDCACM_TX_ENDP, USB_EP_STAT_TX_NAK); + usb_set_ep_rx_stat(USB_CDCACM_TX_ENDP, USB_EP_STAT_RX_DISABLED); + + USBLIB->state = USB_ATTACHED; + SetDeviceAddress(0); + + /* Reset the RX/TX state */ + rx_head = 0; + rx_tail = 0; + tx_head = 0; + tx_tail = 0; + transmitting = -1; +} + +static RESULT usbDataSetup(uint8 request) { + uint8* (*CopyRoutine)(uint16) = 0; + + if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) { + switch (request) { + case USB_CDCACM_GET_LINE_CODING: + CopyRoutine = vcomGetSetLineCoding; + break; + case USB_CDCACM_SET_LINE_CODING: + CopyRoutine = vcomGetSetLineCoding; + break; + default: + break; + } + + /* Call the user hook. */ + if (iface_setup_hook) { + uint8 req_copy = request; + iface_setup_hook(USB_CDCACM_HOOK_IFACE_SETUP, &req_copy); + } + } + + 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) { + RESULT ret = USB_UNSUPPORT; + + if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) { + switch (request) { + case USB_CDCACM_SET_COMM_FEATURE: + /* We support set comm. feature, but don't handle it. */ + ret = USB_SUCCESS; + break; + case USB_CDCACM_SET_CONTROL_LINE_STATE: + /* Track changes to DTR and RTS. */ + line_dtr_rts = (pInformation->USBwValues.bw.bb0 & + (USB_CDCACM_CONTROL_LINE_DTR | + USB_CDCACM_CONTROL_LINE_RTS)); + ret = USB_SUCCESS; + break; + } + + /* Call the user hook. */ + if (iface_setup_hook) { + uint8 req_copy = request; + iface_setup_hook(USB_CDCACM_HOOK_IFACE_SETUP, &req_copy); + } + } + return ret; +} + +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 > N_STRING_DESCRIPTORS) { + 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; +} diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/usb/stm32f1/usb_reg_map.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/usb/stm32f1/usb_reg_map.c new file mode 100644 index 0000000..3f5446a --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/usb/stm32f1/usb_reg_map.c @@ -0,0 +1,88 @@ +/****************************************************************************** + * 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; + } +} + */ +static void usb_set_ep_rx_count_common(uint32 *rxc, uint16 count) { + 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; + } +} +/* +void usb_set_ep_rx_buf0_count(uint8 ep, uint16 count) { + uint32 *rxc = usb_ep_rx_buf0_count_ptr(ep); + usb_set_ep_rx_count_common(rxc, count); +} +*/ +void usb_set_ep_rx_count(uint8 ep, uint16 count) { + uint32 *rxc = usb_ep_rx_count_ptr(ep); + usb_set_ep_rx_count_common(rxc, count); +} diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/usb/usb_lib/usb_core.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/usb/usb_lib/usb_core.c new file mode 100644 index 0000000..38cfa3e --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/usb/usb_lib/usb_core.c @@ -0,0 +1,1010 @@ +/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** +* File Name : usb_core.c +* Author : MCD Application Team +* Version : V2.2.1 +* Date : 09/22/2008 +* Description : Standard protocol processing (USB v2.0) +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Includes ------------------------------------------------------------------*/ +#include "usb_lib.h" +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +#define ValBit(VAR,Place) (VAR & (1 << Place)) +#define SetBit(VAR,Place) (VAR |= (1 << Place)) +#define ClrBit(VAR,Place) (VAR &= ((1 << Place) ^ 255)) + +#define Send0LengthData() { _SetEPTxCount(ENDP0, 0); \ + vSetEPTxStatus(EP_TX_VALID); \ + } + +#define vSetEPRxStatus(st) (SaveRState = st) +#define vSetEPTxStatus(st) (SaveTState = st) + +#define USB_StatusIn() Send0LengthData() +#define USB_StatusOut() vSetEPRxStatus(EP_RX_VALID) + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +u16_u8 StatusInfo; +USB_Bool Data_Mul_MaxPacketSize = FALSE; +/* Private function prototypes -----------------------------------------------*/ +static void DataStageOut(void); +static void DataStageIn(void); +static void NoData_Setup0(void); +static void Data_Setup0(void); +/* Private functions ---------------------------------------------------------*/ + +/******************************************************************************* +* Function Name : Standard_GetConfiguration. +* Description : Return the current configuration variable address. +* Input : Length - How many bytes are needed. +* Output : None. +* Return : Return 1 , if the request is invalid when "Length" is 0. +* Return "Buffer" if the "Length" is not 0. +*******************************************************************************/ +u8 *Standard_GetConfiguration(u16 Length) +{ + if (Length == 0) + { + pInformation->Ctrl_Info.Usb_wLength = + sizeof(pInformation->Current_Configuration); + return 0; + } + pUser_Standard_Requests->User_GetConfiguration(); + return (u8 *)&pInformation->Current_Configuration; +} + +/******************************************************************************* +* Function Name : Standard_SetConfiguration. +* Description : This routine is called to set the configuration value +* Then each class should configure device themself. +* Input : None. +* Output : None. +* Return : Return USB_SUCCESS, if the request is performed. +* Return USB_UNSUPPORT, if the request is invalid. +*******************************************************************************/ +RESULT Standard_SetConfiguration(void) +{ + + if ((pInformation->USBwValue0 <= + Device_Table.Total_Configuration) && (pInformation->USBwValue1 == 0) + && (pInformation->USBwIndex == 0)) /*call Back usb spec 2.0*/ + { + pInformation->Current_Configuration = pInformation->USBwValue0; + pUser_Standard_Requests->User_SetConfiguration(); + return USB_SUCCESS; + } + else + { + return USB_UNSUPPORT; + } +} + +/******************************************************************************* +* Function Name : Standard_GetInterface. +* Description : Return the Alternate Setting of the current interface. +* Input : Length - How many bytes are needed. +* Output : None. +* Return : Return 0, if the request is invalid when "Length" is 0. +* Return "Buffer" if the "Length" is not 0. +*******************************************************************************/ +u8 *Standard_GetInterface(u16 Length) +{ + if (Length == 0) + { + pInformation->Ctrl_Info.Usb_wLength = + sizeof(pInformation->Current_AlternateSetting); + return 0; + } + pUser_Standard_Requests->User_GetInterface(); + return (u8 *)&pInformation->Current_AlternateSetting; +} + +/******************************************************************************* +* Function Name : Standard_SetInterface. +* Description : This routine is called to set the interface. +* Then each class should configure the interface them self. +* Input : None. +* Output : None. +* Return : - Return USB_SUCCESS, if the request is performed. +* - Return USB_UNSUPPORT, if the request is invalid. +*******************************************************************************/ +RESULT Standard_SetInterface(void) +{ + RESULT Re; + /*Test if the specified Interface and Alternate Setting are supported by + the application Firmware*/ + Re = (*pProperty->Class_Get_Interface_Setting)(pInformation->USBwIndex0, pInformation->USBwValue0); + + if (pInformation->Current_Configuration != 0) + { + if ((Re != USB_SUCCESS) || (pInformation->USBwIndex1 != 0) + || (pInformation->USBwValue1 != 0)) + { + return USB_UNSUPPORT; + } + else if (Re == USB_SUCCESS) + { + pUser_Standard_Requests->User_SetInterface(); + pInformation->Current_Interface = pInformation->USBwIndex0; + pInformation->Current_AlternateSetting = pInformation->USBwValue0; + return USB_SUCCESS; + } + + } + + return USB_UNSUPPORT; +} + +/******************************************************************************* +* Function Name : Standard_GetStatus. +* Description : Copy the device request data to "StatusInfo buffer". +* Input : - Length - How many bytes are needed. +* Output : None. +* Return : Return 0, if the request is at end of data block, +* or is invalid when "Length" is 0. +*******************************************************************************/ +u8 *Standard_GetStatus(u16 Length) +{ + if (Length == 0) + { + pInformation->Ctrl_Info.Usb_wLength = 2; + return 0; + } + + StatusInfo.w = 0; + /* Reset Status Information */ + + if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) + { + /*Get Device Status */ + u8 Feature = pInformation->Current_Feature; + + /* Remote Wakeup enabled */ + if (ValBit(Feature, 5)) + { + SetBit(StatusInfo0, 1); + } + + /* Bus-powered */ + if (ValBit(Feature, 6)) + { + ClrBit(StatusInfo0, 0); + } + else /* Self-powered */ + { + SetBit(StatusInfo0, 0); + } + } + /*Interface Status*/ + else if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) + { + return (u8 *)&StatusInfo; + } + /*Get EndPoint Status*/ + else if (Type_Recipient == (STANDARD_REQUEST | ENDPOINT_RECIPIENT)) + { + u8 Related_Endpoint; + u8 wIndex0 = pInformation->USBwIndex0; + + Related_Endpoint = (wIndex0 & 0x0f); + if (ValBit(wIndex0, 7)) + { + /* IN endpoint */ + if (_GetTxStallStatus(Related_Endpoint)) + { + SetBit(StatusInfo0, 0); /* IN Endpoint stalled */ + } + } + else + { + /* OUT endpoint */ + if (_GetRxStallStatus(Related_Endpoint)) + { + SetBit(StatusInfo0, 0); /* OUT Endpoint stalled */ + } + } + + } + else + { + return NULL; + } + pUser_Standard_Requests->User_GetStatus(); + return (u8 *)&StatusInfo; +} + +/******************************************************************************* +* Function Name : Standard_ClearFeature. +* Description : Clear or disable a specific feature. +* Input : None. +* Output : None. +* Return : - Return USB_SUCCESS, if the request is performed. +* - Return USB_UNSUPPORT, if the request is invalid. +*******************************************************************************/ +RESULT Standard_ClearFeature(void) +{ + u32 Type_Rec = Type_Recipient; + u32 Status; + + + if (Type_Rec == (STANDARD_REQUEST | DEVICE_RECIPIENT)) + {/*Device Clear Feature*/ + ClrBit(pInformation->Current_Feature, 5); + return USB_SUCCESS; + } + else if (Type_Rec == (STANDARD_REQUEST | ENDPOINT_RECIPIENT)) + {/*EndPoint Clear Feature*/ + DEVICE* pDev; + u32 Related_Endpoint; + u32 wIndex0; + u32 rEP; + + if ((pInformation->USBwValue != ENDPOINT_STALL) + || (pInformation->USBwIndex1 != 0)) + { + return USB_UNSUPPORT; + } + + pDev = &Device_Table; + wIndex0 = pInformation->USBwIndex0; + rEP = wIndex0 & ~0x80; + Related_Endpoint = ENDP0 + rEP; + + if (ValBit(pInformation->USBwIndex0, 7)) + { + /*Get Status of endpoint & stall the request if the related_ENdpoint + is Disabled*/ + Status = _GetEPTxStatus(Related_Endpoint); + } + else + { + Status = _GetEPRxStatus(Related_Endpoint); + } + + if ((rEP >= pDev->Total_Endpoint) || (Status == 0) + || (pInformation->Current_Configuration == 0)) + { + return USB_UNSUPPORT; + } + + + if (wIndex0 & 0x80) + { + /* IN endpoint */ + if (_GetTxStallStatus(Related_Endpoint )) + { + ClearDTOG_TX(Related_Endpoint); + SetEPTxStatus(Related_Endpoint, EP_TX_VALID); + } + } + else + { + /* OUT endpoint */ + if (_GetRxStallStatus(Related_Endpoint)) + { + if (Related_Endpoint == ENDP0) + { + /* After clear the STALL, enable the default endpoint receiver */ + SetEPRxCount(Related_Endpoint, Device_Property.MaxPacketSize); + _SetEPRxStatus(Related_Endpoint, EP_RX_VALID); + } + else + { + ClearDTOG_RX(Related_Endpoint); + _SetEPRxStatus(Related_Endpoint, EP_RX_VALID); + } + } + } + pUser_Standard_Requests->User_ClearFeature(); + return USB_SUCCESS; + } + + return USB_UNSUPPORT; +} + +/******************************************************************************* +* Function Name : Standard_SetEndPointFeature +* Description : Set or enable a specific feature of EndPoint +* Input : None. +* Output : None. +* Return : - Return USB_SUCCESS, if the request is performed. +* - Return USB_UNSUPPORT, if the request is invalid. +*******************************************************************************/ +RESULT Standard_SetEndPointFeature(void) +{ + u32 wIndex0; + u32 Related_Endpoint; + u32 rEP; + u32 Status; + + wIndex0 = pInformation->USBwIndex0; + rEP = wIndex0 & ~0x80; + Related_Endpoint = ENDP0 + rEP; + + if (ValBit(pInformation->USBwIndex0, 7)) + { + /* get Status of endpoint & stall the request if the related_ENdpoint + is Disabled*/ + Status = _GetEPTxStatus(Related_Endpoint); + } + else + { + Status = _GetEPRxStatus(Related_Endpoint); + } + + if (Related_Endpoint >= Device_Table.Total_Endpoint + || pInformation->USBwValue != 0 || Status == 0 + || pInformation->Current_Configuration == 0) + { + return USB_UNSUPPORT; + } + else + { + if (wIndex0 & 0x80) + { + /* IN endpoint */ + _SetEPTxStatus(Related_Endpoint, EP_TX_STALL); + } + + else + { + /* OUT endpoint */ + _SetEPRxStatus(Related_Endpoint, EP_RX_STALL); + } + } + pUser_Standard_Requests->User_SetEndPointFeature(); + return USB_SUCCESS; +} + +/******************************************************************************* +* Function Name : Standard_SetDeviceFeature. +* Description : Set or enable a specific feature of Device. +* Input : None. +* Output : None. +* Return : - Return USB_SUCCESS, if the request is performed. +* - Return USB_UNSUPPORT, if the request is invalid. +*******************************************************************************/ +RESULT Standard_SetDeviceFeature(void) +{ + SetBit(pInformation->Current_Feature, 5); + pUser_Standard_Requests->User_SetDeviceFeature(); + return USB_SUCCESS; +} + +/******************************************************************************* +* Function Name : Standard_GetDescriptorData. +* Description : Standard_GetDescriptorData is used for descriptors transfer. +* : This routine is used for the descriptors resident in Flash +* or RAM +* pDesc can be in either Flash or RAM +* The purpose of this routine is to have a versatile way to +* response descriptors request. It allows user to generate +* certain descriptors with software or read descriptors from +* external storage part by part. +* Input : - Length - Length of the data in this transfer. +* - pDesc - A pointer points to descriptor struct. +* The structure gives the initial address of the descriptor and +* its original size. +* Output : None. +* Return : Address of a part of the descriptor pointed by the Usb_ +* wOffset The buffer pointed by this address contains at least +* Length bytes. +*******************************************************************************/ +u8 *Standard_GetDescriptorData(u16 Length, ONE_DESCRIPTOR *pDesc) +{ + u32 wOffset; + + wOffset = pInformation->Ctrl_Info.Usb_wOffset; + if (Length == 0) + { + pInformation->Ctrl_Info.Usb_wLength = pDesc->Descriptor_Size - wOffset; + return 0; + } + + return pDesc->Descriptor + wOffset; +} + +/******************************************************************************* +* Function Name : DataStageOut. +* Description : Data stage of a Control Write Transfer. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void DataStageOut(void) +{ + ENDPOINT_INFO *pEPinfo = &pInformation->Ctrl_Info; + u32 save_rLength; + + save_rLength = pEPinfo->Usb_rLength; + + if (pEPinfo->CopyData && save_rLength) + { + u8 *Buffer; + u32 Length; + + Length = pEPinfo->PacketSize; + if (Length > save_rLength) + { + Length = save_rLength; + } + + Buffer = (*pEPinfo->CopyData)(Length); + pEPinfo->Usb_rLength -= Length; + pEPinfo->Usb_rOffset += Length; + + PMAToUserBufferCopy(Buffer, GetEPRxAddr(ENDP0), Length); + } + + if (pEPinfo->Usb_rLength != 0) + { + vSetEPRxStatus(EP_RX_VALID);/* re-enable for next data reception */ + SetEPTxCount(ENDP0, 0); + vSetEPTxStatus(EP_TX_VALID);/* Expect the host to abort the data OUT stage */ + } + /* Set the next State*/ + if (pEPinfo->Usb_rLength >= pEPinfo->PacketSize) + { + pInformation->ControlState = OUT_DATA; + } + else + { + if (pEPinfo->Usb_rLength > 0) + { + pInformation->ControlState = LAST_OUT_DATA; + } + else if (pEPinfo->Usb_rLength == 0) + { + pInformation->ControlState = WAIT_STATUS_IN; + USB_StatusIn(); + } + } +} + +/******************************************************************************* +* Function Name : DataStageIn. +* Description : Data stage of a Control Read Transfer. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void DataStageIn(void) +{ + ENDPOINT_INFO *pEPinfo = &pInformation->Ctrl_Info; + u32 save_wLength = pEPinfo->Usb_wLength; + u32 ControlState = pInformation->ControlState; + + u8 *DataBuffer; + u32 Length; + + if ((save_wLength == 0) && (ControlState == LAST_IN_DATA)) + { + if(Data_Mul_MaxPacketSize == TRUE) + { + /* No more data to send and empty packet */ + Send0LengthData(); + ControlState = LAST_IN_DATA; + Data_Mul_MaxPacketSize = FALSE; + } + else + { + /* No more data to send so STALL the TX Status*/ + ControlState = WAIT_STATUS_OUT; + vSetEPTxStatus(EP_TX_STALL); + } + + goto Expect_Status_Out; + } + + Length = pEPinfo->PacketSize; + ControlState = (save_wLength <= Length) ? LAST_IN_DATA : IN_DATA; + + if (Length > save_wLength) + { + Length = save_wLength; + } + + DataBuffer = (*pEPinfo->CopyData)(Length); + + UserToPMABufferCopy(DataBuffer, GetEPTxAddr(ENDP0), Length); + + SetEPTxCount(ENDP0, Length); + + pEPinfo->Usb_wLength -= Length; + pEPinfo->Usb_wOffset += Length; + vSetEPTxStatus(EP_TX_VALID); + + USB_StatusOut();/* Expect the host to abort the data IN stage */ + +Expect_Status_Out: + pInformation->ControlState = ControlState; +} + +/******************************************************************************* +* Function Name : NoData_Setup0. +* Description : Proceed the processing of setup request without data stage. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void NoData_Setup0(void) +{ + RESULT Result = USB_UNSUPPORT; + u32 RequestNo = pInformation->USBbRequest; + u32 ControlState; + + if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) + { + /* Device Request*/ + /* SET_CONFIGURATION*/ + if (RequestNo == SET_CONFIGURATION) + { + Result = Standard_SetConfiguration(); + } + + /*SET ADDRESS*/ + else if (RequestNo == SET_ADDRESS) + { + if ((pInformation->USBwValue0 > 127) || (pInformation->USBwValue1 != 0) + || (pInformation->USBwIndex != 0) + || (pInformation->Current_Configuration != 0)) + /* Device Address should be 127 or less*/ + { + ControlState = STALLED; + goto exit_NoData_Setup0; + } + else + { + Result = USB_SUCCESS; + } + } + /*SET FEATURE for Device*/ + else if (RequestNo == SET_FEATURE) + { + if ((pInformation->USBwValue0 == DEVICE_REMOTE_WAKEUP) + && (pInformation->USBwIndex == 0) + && (ValBit(pInformation->Current_Feature, 5))) + { + Result = Standard_SetDeviceFeature(); + } + else + { + Result = USB_UNSUPPORT; + } + } + /*Clear FEATURE for Device */ + else if (RequestNo == CLEAR_FEATURE) + { + if (pInformation->USBwValue0 == DEVICE_REMOTE_WAKEUP + && pInformation->USBwIndex == 0 + && ValBit(pInformation->Current_Feature, 5)) + { + Result = Standard_ClearFeature(); + } + else + { + Result = USB_UNSUPPORT; + } + } + + } + + /* Interface Request*/ + else if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) + { + /*SET INTERFACE*/ + if (RequestNo == SET_INTERFACE) + { + Result = Standard_SetInterface(); + } + } + + /* EndPoint Request*/ + else if (Type_Recipient == (STANDARD_REQUEST | ENDPOINT_RECIPIENT)) + { + /*CLEAR FEATURE for EndPoint*/ + if (RequestNo == CLEAR_FEATURE) + { + Result = Standard_ClearFeature(); + } + /* SET FEATURE for EndPoint*/ + else if (RequestNo == SET_FEATURE) + { + Result = Standard_SetEndPointFeature(); + } + } + else + { + Result = USB_UNSUPPORT; + } + + + if (Result != USB_SUCCESS) + { + Result = (*pProperty->Class_NoData_Setup)(RequestNo); + if (Result == USB_NOT_READY) + { + ControlState = PAUSE; + goto exit_NoData_Setup0; + } + } + + if (Result != USB_SUCCESS) + { + ControlState = STALLED; + goto exit_NoData_Setup0; + } + + ControlState = WAIT_STATUS_IN;/* After no data stage SETUP */ + + USB_StatusIn(); + +exit_NoData_Setup0: + pInformation->ControlState = ControlState; + return; +} + +/******************************************************************************* +* Function Name : Data_Setup0. +* Description : Proceed the processing of setup request with data stage. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void Data_Setup0(void) +{ + u8 *(*CopyRoutine)(u16); + RESULT Result; + u32 Request_No = pInformation->USBbRequest; + + u32 Related_Endpoint, Reserved; + u32 wOffset, Status; + + + + CopyRoutine = NULL; + wOffset = 0; + + if (Request_No == GET_DESCRIPTOR) + { + if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) + { + u8 wValue1 = pInformation->USBwValue1; + if (wValue1 == DEVICE_DESCRIPTOR) + { + CopyRoutine = pProperty->GetDeviceDescriptor; + } + else if (wValue1 == CONFIG_DESCRIPTOR) + { + CopyRoutine = pProperty->GetConfigDescriptor; + } + else if (wValue1 == STRING_DESCRIPTOR) + { + CopyRoutine = pProperty->GetStringDescriptor; + } /* End of GET_DESCRIPTOR */ + } + } + + /*GET STATUS*/ + else if ((Request_No == GET_STATUS) && (pInformation->USBwValue == 0) + && (pInformation->USBwLength == 0x0002) + && (pInformation->USBwIndex1 == 0)) + { + /* GET STATUS for Device*/ + if ((Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) + && (pInformation->USBwIndex == 0)) + { + CopyRoutine = Standard_GetStatus; + } + + /* GET STATUS for Interface*/ + else if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) + { + if (((*pProperty->Class_Get_Interface_Setting)(pInformation->USBwIndex0, 0) == USB_SUCCESS) + && (pInformation->Current_Configuration != 0)) + { + CopyRoutine = Standard_GetStatus; + } + } + + /* GET STATUS for EndPoint*/ + else if (Type_Recipient == (STANDARD_REQUEST | ENDPOINT_RECIPIENT)) + { + Related_Endpoint = (pInformation->USBwIndex0 & 0x0f); + Reserved = pInformation->USBwIndex0 & 0x70; + + if (ValBit(pInformation->USBwIndex0, 7)) + { + /*Get Status of endpoint & stall the request if the related_ENdpoint + is Disabled*/ + Status = _GetEPTxStatus(Related_Endpoint); + } + else + { + Status = _GetEPRxStatus(Related_Endpoint); + } + + if ((Related_Endpoint < Device_Table.Total_Endpoint) && (Reserved == 0) + && (Status != 0)) + { + CopyRoutine = Standard_GetStatus; + } + } + + } + + /*GET CONFIGURATION*/ + else if (Request_No == GET_CONFIGURATION) + { + if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) + { + CopyRoutine = Standard_GetConfiguration; + } + } + /*GET INTERFACE*/ + else if (Request_No == GET_INTERFACE) + { + if ((Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) + && (pInformation->Current_Configuration != 0) && (pInformation->USBwValue == 0) + && (pInformation->USBwIndex1 == 0) && (pInformation->USBwLength == 0x0001) + && ((*pProperty->Class_Get_Interface_Setting)(pInformation->USBwIndex0, 0) == USB_SUCCESS)) + { + CopyRoutine = Standard_GetInterface; + } + + } + + if (CopyRoutine) + { + pInformation->Ctrl_Info.Usb_wOffset = wOffset; + pInformation->Ctrl_Info.CopyData = CopyRoutine; + /* sb in the original the cast to word was directly */ + /* now the cast is made step by step */ + (*CopyRoutine)(0); + Result = USB_SUCCESS; + } + else + { + Result = (*pProperty->Class_Data_Setup)(pInformation->USBbRequest); + if (Result == USB_NOT_READY) + { + pInformation->ControlState = PAUSE; + return; + } + } + + if (pInformation->Ctrl_Info.Usb_wLength == 0xFFFF) + { + /* Data is not ready, wait it */ + pInformation->ControlState = PAUSE; + return; + } + if ((Result == USB_UNSUPPORT) || (pInformation->Ctrl_Info.Usb_wLength == 0)) + { + /* Unsupported request */ + pInformation->ControlState = STALLED; + return; + } + + + if (ValBit(pInformation->USBbmRequestType, 7)) + { + /* Device ==> Host */ + vu32 wLength = pInformation->USBwLength; + + /* Restrict the data length to be the one host asks */ + if (pInformation->Ctrl_Info.Usb_wLength > wLength) + { + pInformation->Ctrl_Info.Usb_wLength = wLength; + } + + else if (pInformation->Ctrl_Info.Usb_wLength < pInformation->USBwLength) + { + if (pInformation->Ctrl_Info.Usb_wLength < pProperty->MaxPacketSize) + { + Data_Mul_MaxPacketSize = FALSE; + } + else if ((pInformation->Ctrl_Info.Usb_wLength % pProperty->MaxPacketSize) == 0) + { + Data_Mul_MaxPacketSize = TRUE; + } + } + + pInformation->Ctrl_Info.PacketSize = pProperty->MaxPacketSize; + DataStageIn(); + } + else + { + pInformation->ControlState = OUT_DATA; + vSetEPRxStatus(EP_RX_VALID); /* enable for next data reception */ + } + + return; +} + +/******************************************************************************* +* Function Name : Setup0_Process +* Description : Get the device request data and dispatch to individual process. +* Input : None. +* Output : None. +* Return : Post0_Process. +*******************************************************************************/ +u8 Setup0_Process(void) +{ + + union + { + u8* b; + u16* w; + } pBuf; + + pBuf.b = PMAAddr + (u8 *)(_GetEPRxAddr(ENDP0) * 2); /* *2 for 32 bits addr */ + + if (pInformation->ControlState != PAUSE) + { + pInformation->USBbmRequestType = *pBuf.b++; /* bmRequestType */ + pInformation->USBbRequest = *pBuf.b++; /* bRequest */ + pBuf.w++; /* word not accessed because of 32 bits addressing */ + pInformation->USBwValue = *pBuf.w++; /* wValue in Little Endian */ + pBuf.w++; /* word not accessed because of 32 bits addressing */ + pInformation->USBwIndex = *pBuf.w++; /* wIndex in Little Endian */ + pBuf.w++; /* word not accessed because of 32 bits addressing */ + pInformation->USBwLength = *pBuf.w; /* wLength in Little Endian */ + } + + pInformation->ControlState = SETTING_UP; + if (pInformation->USBwLength == 0) + { + /* Setup with no data stage */ + NoData_Setup0(); + } + else + { + /* Setup with data stage */ + Data_Setup0(); + } + return Post0_Process(); +} + +/******************************************************************************* +* Function Name : In0_Process +* Description : Process the IN token on all default endpoint. +* Input : None. +* Output : None. +* Return : Post0_Process. +*******************************************************************************/ +u8 In0_Process(void) +{ + u32 ControlState = pInformation->ControlState; + + if ((ControlState == IN_DATA) || (ControlState == LAST_IN_DATA)) + { + DataStageIn(); + /* ControlState may be changed outside the function */ + ControlState = pInformation->ControlState; + } + + else if (ControlState == WAIT_STATUS_IN) + { + if ((pInformation->USBbRequest == SET_ADDRESS) && + (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT))) + { + SetDeviceAddress(pInformation->USBwValue0); + pUser_Standard_Requests->User_SetDeviceAddress(); + } + (*pProperty->Process_Status_IN)(); + ControlState = STALLED; + } + + else + { + ControlState = STALLED; + } + + pInformation->ControlState = ControlState; + + return Post0_Process(); +} + +/******************************************************************************* +* Function Name : Out0_Process +* Description : Process the OUT token on all default endpoint. +* Input : None. +* Output : None. +* Return : Post0_Process. +*******************************************************************************/ +u8 Out0_Process(void) +{ + u32 ControlState = pInformation->ControlState; + + if ((ControlState == OUT_DATA) || (ControlState == LAST_OUT_DATA)) + { + DataStageOut(); + ControlState = pInformation->ControlState; /* may be changed outside the function */ + } + + else if (ControlState == WAIT_STATUS_OUT) + { + (*pProperty->Process_Status_OUT)(); + ControlState = STALLED; + } + + else if ((ControlState == IN_DATA) || (ControlState == LAST_IN_DATA)) + { + /* host aborts the transfer before finish */ + ControlState = STALLED; + } + + /* Unexpect state, STALL the endpoint */ + else + { + ControlState = STALLED; + } + + pInformation->ControlState = ControlState; + + return Post0_Process(); +} + +/******************************************************************************* +* Function Name : Post0_Process +* Description : Stall the Endpoint 0 in case of error. +* Input : None. +* Output : None. +* Return : - 0 if the control State is in PAUSE +* - 1 if not. +*******************************************************************************/ +u8 Post0_Process(void) +{ + SetEPRxCount(ENDP0, Device_Property.MaxPacketSize); + + if (pInformation->ControlState == STALLED) + { + vSetEPRxStatus(EP_RX_STALL); + vSetEPTxStatus(EP_TX_STALL); + } + + return (pInformation->ControlState == PAUSE); +} + +/******************************************************************************* +* Function Name : SetDeviceAddress. +* Description : Set the device and all the used Endpoints addresses. +* Input : - Val: device adress. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetDeviceAddress(u8 Val) +{ + u32 i; + u32 nEP = Device_Table.Total_Endpoint; + + /* set address in every used endpoint */ + for (i = 0; i < nEP; i++) + { + _SetEPAddress((u8)i, (u8)i); + } /* for */ + _SetDADDR(Val | DADDR_EF); /* set device address and enable function */ +} + +/******************************************************************************* +* Function Name : NOP_Process +* Description : No operation function. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void NOP_Process(void) +{ +} + +/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/usb/usb_lib/usb_init.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/usb/usb_lib/usb_init.c new file mode 100644 index 0000000..94f3a83 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/usb/usb_lib/usb_init.c @@ -0,0 +1,64 @@ +/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** +* File Name : usb_init.c +* Author : MCD Application Team +* Version : V2.2.1 +* Date : 09/22/2008 +* Description : Initialization routines & global variables +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Includes ------------------------------------------------------------------*/ +#include "usb_lib.h" + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* The number of current endpoint, it will be used to specify an endpoint */ + u8 EPindex; +/* The number of current device, it is an index to the Device_Table */ +/* u8 Device_no; */ +/* Points to the DEVICE_INFO structure of current device */ +/* The purpose of this register is to speed up the execution */ +DEVICE_INFO *pInformation; +/* Points to the DEVICE_PROP structure of current device */ +/* The purpose of this register is to speed up the execution */ +DEVICE_PROP *pProperty; +/* Temporary save the state of Rx & Tx status. */ +/* Whenever the Rx or Tx state is changed, its value is saved */ +/* in this variable first and will be set to the EPRB or EPRA */ +/* at the end of interrupt process */ +u16 SaveState ; +u16 wInterrupt_Mask; +DEVICE_INFO Device_Info; +USER_STANDARD_REQUESTS *pUser_Standard_Requests; + +/* Extern variables ----------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/******************************************************************************* +* Function Name : USB_Init +* Description : USB system initialization +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void USB_Init(void) +{ + pInformation = &Device_Info; + pInformation->ControlState = 2; + pProperty = &Device_Property; + pUser_Standard_Requests = &User_Standard_Requests; + /* Initialize devices one by one */ + + pProperty->Init(); +} + +/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/usb/usb_lib/usb_mem.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/usb/usb_lib/usb_mem.c new file mode 100644 index 0000000..ad9740a --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/usb/usb_lib/usb_mem.c @@ -0,0 +1,73 @@ +/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** +* File Name : usb_mem.c +* Author : MCD Application Team +* Version : V2.2.1 +* Date : 09/22/2008 +* Description : Utility functions for memory transfers to/from PMA +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Includes ------------------------------------------------------------------*/ +#include "usb_lib.h" + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Extern variables ----------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ +/******************************************************************************* +* Function Name : UserToPMABufferCopy +* Description : Copy a buffer from user memory area to packet memory area (PMA) +* Input : - pbUsrBuf: pointer to user memory area. +* - wPMABufAddr: address into PMA. +* - wNBytes: no. of bytes to be copied. +* Output : None. +* Return : None . +*******************************************************************************/ +void UserToPMABufferCopy(const u8 *pbUsrBuf, u16 wPMABufAddr, u16 wNBytes) +{ + u32 n = (wNBytes + 1) >> 1; /* n = (wNBytes + 1) / 2 */ + u32 i, temp1, temp2; + u16 *pdwVal; + pdwVal = (u16 *)(wPMABufAddr * 2 + PMAAddr); + for (i = n; i != 0; i--) + { + temp1 = (u16) * pbUsrBuf; + pbUsrBuf++; + temp2 = temp1 | (u16) * pbUsrBuf << 8; + *pdwVal++ = temp2; + pdwVal++; + pbUsrBuf++; + } +} +/******************************************************************************* +* Function Name : PMAToUserBufferCopy +* Description : Copy a buffer from user memory area to packet memory area (PMA) +* Input : - pbUsrBuf = pointer to user memory area. +* - wPMABufAddr = address into PMA. +* - wNBytes = no. of bytes to be copied. +* Output : None. +* Return : None. +*******************************************************************************/ +void PMAToUserBufferCopy(u8 *pbUsrBuf, u16 wPMABufAddr, u16 wNBytes) +{ + u32 n = (wNBytes + 1) >> 1;/* /2*/ + u32 i; + u32 *pdwVal; + pdwVal = (u32 *)(wPMABufAddr * 2 + PMAAddr); + for (i = n; i != 0; i--) + { + *(u16*)pbUsrBuf++ = *pdwVal++; + pbUsrBuf++; + } +} + +/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/usb/usb_lib/usb_regs.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/usb/usb_lib/usb_regs.c new file mode 100644 index 0000000..c7e0276 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/usb/usb_lib/usb_regs.c @@ -0,0 +1,748 @@ +/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** +* File Name : usb_regs.c +* Author : MCD Application Team +* Version : V2.2.1 +* Date : 09/22/2008 +* Description : Interface functions to USB cell registers +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Includes ------------------------------------------------------------------*/ +#include "usb_lib.h" + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Extern variables ----------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/******************************************************************************* +* Function Name : SetCNTR. +* Description : Set the CNTR register value. +* Input : wRegValue: new register value. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetCNTR(u16 wRegValue) +{ + _SetCNTR(wRegValue); +} + +/******************************************************************************* +* Function Name : GetCNTR. +* Description : returns the CNTR register value. +* Input : None. +* Output : None. +* Return : CNTR register Value. +*******************************************************************************/ +u16 GetCNTR(void) +{ + return(_GetCNTR()); +} + +/******************************************************************************* +* Function Name : SetISTR. +* Description : Set the ISTR register value. +* Input : wRegValue: new register value. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetISTR(u16 wRegValue) +{ + _SetISTR(wRegValue); +} + +/******************************************************************************* +* Function Name : GetISTR +* Description : Returns the ISTR register value. +* Input : None. +* Output : None. +* Return : ISTR register Value +*******************************************************************************/ +u16 GetISTR(void) +{ + return(_GetISTR()); +} + +/******************************************************************************* +* Function Name : GetFNR +* Description : Returns the FNR register value. +* Input : None. +* Output : None. +* Return : FNR register Value +*******************************************************************************/ +u16 GetFNR(void) +{ + return(_GetFNR()); +} + +/******************************************************************************* +* Function Name : SetDADDR +* Description : Set the DADDR register value. +* Input : wRegValue: new register value. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetDADDR(u16 wRegValue) +{ + _SetDADDR(wRegValue); +} + +/******************************************************************************* +* Function Name : GetDADDR +* Description : Returns the DADDR register value. +* Input : None. +* Output : None. +* Return : DADDR register Value +*******************************************************************************/ +u16 GetDADDR(void) +{ + return(_GetDADDR()); +} + +/******************************************************************************* +* Function Name : SetBTABLE +* Description : Set the BTABLE. +* Input : wRegValue: New register value. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetBTABLE(u16 wRegValue) +{ + _SetBTABLE(wRegValue); +} + +/******************************************************************************* +* Function Name : GetBTABLE. +* Description : Returns the BTABLE register value. +* Input : None. +* Output : None. +* Return : BTABLE address. +*******************************************************************************/ +u16 GetBTABLE(void) +{ + return(_GetBTABLE()); +} + +/******************************************************************************* +* Function Name : SetENDPOINT +* Description : Setthe Endpoint register value. +* Input : bEpNum: Endpoint Number. +* wRegValue. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetENDPOINT(u8 bEpNum, u16 wRegValue) +{ + _SetENDPOINT(bEpNum, wRegValue); +} + +/******************************************************************************* +* Function Name : GetENDPOINT +* Description : Return the Endpoint register value. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : Endpoint register value. +*******************************************************************************/ +u16 GetENDPOINT(u8 bEpNum) +{ + return(_GetENDPOINT(bEpNum)); +} + +/******************************************************************************* +* Function Name : SetEPType +* Description : sets the type in the endpoint register. +* Input : bEpNum: Endpoint Number. +* wType: type definition. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPType(u8 bEpNum, u16 wType) +{ + _SetEPType(bEpNum, wType); +} + +/******************************************************************************* +* Function Name : GetEPType +* Description : Returns the endpoint type. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : Endpoint Type +*******************************************************************************/ +u16 GetEPType(u8 bEpNum) +{ + return(_GetEPType(bEpNum)); +} + +/******************************************************************************* +* Function Name : SetEPTxStatus +* Description : Set the status of Tx endpoint. +* Input : bEpNum: Endpoint Number. +* wState: new state. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPTxStatus(u8 bEpNum, u16 wState) +{ + _SetEPTxStatus(bEpNum, wState); +} + +/******************************************************************************* +* Function Name : SetEPRxStatus +* Description : Set the status of Rx endpoint. +* Input : bEpNum: Endpoint Number. +* wState: new state. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPRxStatus(u8 bEpNum, u16 wState) +{ + _SetEPRxStatus(bEpNum, wState); +} + +/******************************************************************************* +* Function Name : SetDouBleBuffEPStall +* Description : sets the status for Double Buffer Endpoint to STALL +* Input : bEpNum: Endpoint Number. +* bDir: Endpoint direction. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetDouBleBuffEPStall(u8 bEpNum, u8 bDir) +{ + u16 Endpoint_DTOG_Status; + Endpoint_DTOG_Status = GetENDPOINT(bEpNum); + if (bDir == EP_DBUF_OUT) + { /* OUT double buffered endpoint */ + _SetENDPOINT(bEpNum, Endpoint_DTOG_Status & ~EPRX_DTOG1); + } + else if (bDir == EP_DBUF_IN) + { /* IN double buffered endpoint */ + _SetENDPOINT(bEpNum, Endpoint_DTOG_Status & ~EPTX_DTOG1); + } +} + +/******************************************************************************* +* Function Name : GetEPTxStatus +* Description : Returns the endpoint Tx status. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : Endpoint TX Status +*******************************************************************************/ +u16 GetEPTxStatus(u8 bEpNum) +{ + return(_GetEPTxStatus(bEpNum)); +} + +/******************************************************************************* +* Function Name : GetEPRxStatus +* Description : Returns the endpoint Rx status. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : Endpoint RX Status +*******************************************************************************/ +u16 GetEPRxStatus(u8 bEpNum) +{ + return(_GetEPRxStatus(bEpNum)); +} + +/******************************************************************************* +* Function Name : SetEPTxValid +* Description : Valid the endpoint Tx Status. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPTxValid(u8 bEpNum) +{ + _SetEPTxStatus(bEpNum, EP_TX_VALID); +} + +/******************************************************************************* +* Function Name : SetEPRxValid +* Description : Valid the endpoint Rx Status. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPRxValid(u8 bEpNum) +{ + _SetEPRxStatus(bEpNum, EP_RX_VALID); +} + +/******************************************************************************* +* Function Name : SetEP_KIND +* Description : Clear the EP_KIND bit. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEP_KIND(u8 bEpNum) +{ + _SetEP_KIND(bEpNum); +} + +/******************************************************************************* +* Function Name : ClearEP_KIND +* Description : set the EP_KIND bit. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +void ClearEP_KIND(u8 bEpNum) +{ + _ClearEP_KIND(bEpNum); +} +/******************************************************************************* +* Function Name : Clear_Status_Out +* Description : Clear the Status Out of the related Endpoint +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +void Clear_Status_Out(u8 bEpNum) +{ + _ClearEP_KIND(bEpNum); +} +/******************************************************************************* +* Function Name : Set_Status_Out +* Description : Set the Status Out of the related Endpoint +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +void Set_Status_Out(u8 bEpNum) +{ + _SetEP_KIND(bEpNum); +} +/******************************************************************************* +* Function Name : SetEPDoubleBuff +* Description : Enable the double buffer feature for the endpoint. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPDoubleBuff(u8 bEpNum) +{ + _SetEP_KIND(bEpNum); +} +/******************************************************************************* +* Function Name : ClearEPDoubleBuff +* Description : Disable the double buffer feature for the endpoint. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +void ClearEPDoubleBuff(u8 bEpNum) +{ + _ClearEP_KIND(bEpNum); +} +/******************************************************************************* +* Function Name : GetTxStallStatus +* Description : Returns the Stall status of the Tx endpoint. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : Tx Stall status. +*******************************************************************************/ +u16 GetTxStallStatus(u8 bEpNum) +{ + return(_GetTxStallStatus(bEpNum)); +} +/******************************************************************************* +* Function Name : GetRxStallStatus +* Description : Returns the Stall status of the Rx endpoint. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : Rx Stall status. +*******************************************************************************/ +u16 GetRxStallStatus(u8 bEpNum) +{ + return(_GetRxStallStatus(bEpNum)); +} +/******************************************************************************* +* Function Name : ClearEP_CTR_RX +* Description : Clear the CTR_RX bit. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +void ClearEP_CTR_RX(u8 bEpNum) +{ + _ClearEP_CTR_RX(bEpNum); +} +/******************************************************************************* +* Function Name : ClearEP_CTR_TX +* Description : Clear the CTR_TX bit. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +void ClearEP_CTR_TX(u8 bEpNum) +{ + _ClearEP_CTR_TX(bEpNum); +} +/******************************************************************************* +* Function Name : ToggleDTOG_RX +* Description : Toggle the DTOG_RX bit. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +void ToggleDTOG_RX(u8 bEpNum) +{ + _ToggleDTOG_RX(bEpNum); +} +/******************************************************************************* +* Function Name : ToggleDTOG_TX +* Description : Toggle the DTOG_TX bit. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +void ToggleDTOG_TX(u8 bEpNum) +{ + _ToggleDTOG_TX(bEpNum); +} +/******************************************************************************* +* Function Name : ClearDTOG_RX. +* Description : Clear the DTOG_RX bit. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +void ClearDTOG_RX(u8 bEpNum) +{ + _ClearDTOG_RX(bEpNum); +} +/******************************************************************************* +* Function Name : ClearDTOG_TX. +* Description : Clear the DTOG_TX bit. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +void ClearDTOG_TX(u8 bEpNum) +{ + _ClearDTOG_TX(bEpNum); +} +/******************************************************************************* +* Function Name : SetEPAddress +* Description : Set the endpoint address. +* Input : bEpNum: Endpoint Number. +* bAddr: New endpoint address. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPAddress(u8 bEpNum, u8 bAddr) +{ + _SetEPAddress(bEpNum, bAddr); +} +/******************************************************************************* +* Function Name : GetEPAddress +* Description : Get the endpoint address. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : Endpoint address. +*******************************************************************************/ +u8 GetEPAddress(u8 bEpNum) +{ + return(_GetEPAddress(bEpNum)); +} +/******************************************************************************* +* Function Name : SetEPTxAddr +* Description : Set the endpoint Tx buffer address. +* Input : bEpNum: Endpoint Number. +* wAddr: new address. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPTxAddr(u8 bEpNum, u16 wAddr) +{ + _SetEPTxAddr(bEpNum, wAddr); +} +/******************************************************************************* +* Function Name : SetEPRxAddr +* Description : Set the endpoint Rx buffer address. +* Input : bEpNum: Endpoint Number. +* wAddr: new address. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPRxAddr(u8 bEpNum, u16 wAddr) +{ + _SetEPRxAddr(bEpNum, wAddr); +} +/******************************************************************************* +* Function Name : GetEPTxAddr +* Description : Returns the endpoint Tx buffer address. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : Rx buffer address. +*******************************************************************************/ +u16 GetEPTxAddr(u8 bEpNum) +{ + return(_GetEPTxAddr(bEpNum)); +} +/******************************************************************************* +* Function Name : GetEPRxAddr. +* Description : Returns the endpoint Rx buffer address. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : Rx buffer address. +*******************************************************************************/ +u16 GetEPRxAddr(u8 bEpNum) +{ + return(_GetEPRxAddr(bEpNum)); +} +/******************************************************************************* +* Function Name : SetEPTxCount. +* Description : Set the Tx count. +* Input : bEpNum: Endpoint Number. +* wCount: new count value. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPTxCount(u8 bEpNum, u16 wCount) +{ + _SetEPTxCount(bEpNum, wCount); +} +/******************************************************************************* +* Function Name : SetEPCountRxReg. +* Description : Set the Count Rx Register value. +* Input : *pdwReg: point to the register. +* wCount: the new register value. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPCountRxReg(u32 *pdwReg, u16 wCount) +{ + _SetEPCountRxReg(dwReg, wCount); +} +/******************************************************************************* +* Function Name : SetEPRxCount +* Description : Set the Rx count. +* Input : bEpNum: Endpoint Number. +* wCount: the new count value. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPRxCount(u8 bEpNum, u16 wCount) +{ + _SetEPRxCount(bEpNum, wCount); +} +/******************************************************************************* +* Function Name : GetEPTxCount +* Description : Get the Tx count. +* Input : bEpNum: Endpoint Number. +* Output : None +* Return : Tx count value. +*******************************************************************************/ +u16 GetEPTxCount(u8 bEpNum) +{ + return(_GetEPTxCount(bEpNum)); +} +/******************************************************************************* +* Function Name : GetEPRxCount +* Description : Get the Rx count. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : Rx count value. +*******************************************************************************/ +u16 GetEPRxCount(u8 bEpNum) +{ + return(_GetEPRxCount(bEpNum)); +} +/******************************************************************************* +* Function Name : SetEPDblBuffAddr +* Description : Set the addresses of the buffer 0 and 1. +* Input : bEpNum: Endpoint Number. +* wBuf0Addr: new address of buffer 0. +* wBuf1Addr: new address of buffer 1. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPDblBuffAddr(u8 bEpNum, u16 wBuf0Addr, u16 wBuf1Addr) +{ + _SetEPDblBuffAddr(bEpNum, wBuf0Addr, wBuf1Addr); +} +/******************************************************************************* +* Function Name : SetEPDblBuf0Addr +* Description : Set the Buffer 1 address. +* Input : bEpNum: Endpoint Number +* wBuf0Addr: new address. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPDblBuf0Addr(u8 bEpNum, u16 wBuf0Addr) +{ + _SetEPDblBuf0Addr(bEpNum, wBuf0Addr); +} +/******************************************************************************* +* Function Name : SetEPDblBuf1Addr +* Description : Set the Buffer 1 address. +* Input : bEpNum: Endpoint Number +* wBuf1Addr: new address. +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPDblBuf1Addr(u8 bEpNum, u16 wBuf1Addr) +{ + _SetEPDblBuf1Addr(bEpNum, wBuf1Addr); +} +/******************************************************************************* +* Function Name : GetEPDblBuf0Addr +* Description : Returns the address of the Buffer 0. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +u16 GetEPDblBuf0Addr(u8 bEpNum) +{ + return(_GetEPDblBuf0Addr(bEpNum)); +} +/******************************************************************************* +* Function Name : GetEPDblBuf1Addr +* Description : Returns the address of the Buffer 1. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : Address of the Buffer 1. +*******************************************************************************/ +u16 GetEPDblBuf1Addr(u8 bEpNum) +{ + return(_GetEPDblBuf1Addr(bEpNum)); +} +/******************************************************************************* +* Function Name : SetEPDblBuffCount +* Description : Set the number of bytes for a double Buffer +* endpoint. +* Input : bEpNum,bDir, wCount +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPDblBuffCount(u8 bEpNum, u8 bDir, u16 wCount) +{ + _SetEPDblBuffCount(bEpNum, bDir, wCount); +} +/******************************************************************************* +* Function Name : SetEPDblBuf0Count +* Description : Set the number of bytes in the buffer 0 of a double Buffer +* endpoint. +* Input : bEpNum, bDir, wCount +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPDblBuf0Count(u8 bEpNum, u8 bDir, u16 wCount) +{ + _SetEPDblBuf0Count(bEpNum, bDir, wCount); +} +/******************************************************************************* +* Function Name : SetEPDblBuf1Count +* Description : Set the number of bytes in the buffer 0 of a double Buffer +* endpoint. +* Input : bEpNum, bDir, wCount +* Output : None. +* Return : None. +*******************************************************************************/ +void SetEPDblBuf1Count(u8 bEpNum, u8 bDir, u16 wCount) +{ + _SetEPDblBuf1Count(bEpNum, bDir, wCount); +} +/******************************************************************************* +* Function Name : GetEPDblBuf0Count +* Description : Returns the number of byte received in the buffer 0 of a double +* Buffer endpoint. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : Endpoint Buffer 0 count +*******************************************************************************/ +u16 GetEPDblBuf0Count(u8 bEpNum) +{ + return(_GetEPDblBuf0Count(bEpNum)); +} +/******************************************************************************* +* Function Name : GetEPDblBuf1Count +* Description : Returns the number of data received in the buffer 1 of a double +* Buffer endpoint. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : Endpoint Buffer 1 count. +*******************************************************************************/ +u16 GetEPDblBuf1Count(u8 bEpNum) +{ + return(_GetEPDblBuf1Count(bEpNum)); +} +/******************************************************************************* +* Function Name : GetEPDblBufDir +* Description : gets direction of the double buffered endpoint +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : EP_DBUF_OUT, EP_DBUF_IN, +* EP_DBUF_ERR if the endpoint counter not yet programmed. +*******************************************************************************/ +EP_DBUF_DIR GetEPDblBufDir(u8 bEpNum) +{ + if ((u16)(*_pEPRxCount(bEpNum) & 0xFC00) != 0) + return(EP_DBUF_OUT); + else if (((u16)(*_pEPTxCount(bEpNum)) & 0x03FF) != 0) + return(EP_DBUF_IN); + else + return(EP_DBUF_ERR); +} +/******************************************************************************* +* Function Name : FreeUserBuffer +* Description : free buffer used from the application realizing it to the line + toggles bit SW_BUF in the double buffered endpoint register +* Input : bEpNum, bDir +* Output : None. +* Return : None. +*******************************************************************************/ +void FreeUserBuffer(u8 bEpNum, u8 bDir) +{ + if (bDir == EP_DBUF_OUT) + { /* OUT double buffered endpoint */ + _ToggleDTOG_TX(bEpNum); + } + else if (bDir == EP_DBUF_IN) + { /* IN double buffered endpoint */ + _ToggleDTOG_RX(bEpNum); + } +} + +/******************************************************************************* +* Function Name : ToWord +* Description : merge two byte in a word. +* Input : bh: byte high, bl: bytes low. +* Output : None. +* Return : resulted word. +*******************************************************************************/ +u16 ToWord(u8 bh, u8 bl) +{ + u16 wRet; + wRet = (u16)bl | ((u16)bh << 8); + return(wRet); +} +/******************************************************************************* +* Function Name : ByteSwap +* Description : Swap two byte in a word. +* Input : wSwW: word to Swap. +* Output : None. +* Return : resulted word. +*******************************************************************************/ +u16 ByteSwap(u16 wSwW) +{ + u8 bTemp; + u16 wRet; + bTemp = (u8)(wSwW & 0xff); + wRet = (wSwW >> 8) | ((u16)bTemp << 8); + return(wRet); +} + +/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/BootLoaders/Boards/stm32/cores/maple/libmaple/util.c b/BootLoaders/Boards/stm32/cores/maple/libmaple/util.c new file mode 100644 index 0000000..4c0b2c8 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/libmaple/util.c @@ -0,0 +1,150 @@ +/****************************************************************************** + * 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 + * 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/util.c + * @brief Utility procedures for debugging + */ + +#include +#include +#include +#include + +/* (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. + */ +#if defined(ERROR_LED_PORT) && defined(ERROR_LED_PIN) +#define HAVE_ERROR_LED +#endif + +/* (Called from exc.S with global interrupts disabled.) */ +__attribute__((noreturn)) void __error(void) { + if (__lm_error) { + __lm_error(); + } + /* Reenable global interrupts */ + nvic_globalirq_enable(); + throb(); +} + +/* + * 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) { + 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(); +} + +/* + * 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); +} + +/* + * Provide an abort() implementation that aborts execution and punts + * to __error(). + */ +void abort() { + 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(); +} + +/* 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. + */ +__attribute__((noreturn)) void throb(void) { +#ifdef HAVE_ERROR_LED + int32 slope = 1; + uint32 CC = 0x0000; + uint32 TOP_CNT = 0x0200; + uint32 i = 0; + + gpio_set_mode(ERROR_LED_PORT, ERROR_LED_PIN, GPIO_MODE_OUTPUT); + /* Error fade. */ + while (1) { + if (CC == TOP_CNT) { + slope = -1; + } else if (CC == 0) { + slope = 1; + } + + if (i == TOP_CNT) { + CC += slope; + i = 0; + } + + if (i < CC) { + gpio_write_bit(ERROR_LED_PORT, ERROR_LED_PIN, 1); + } else { + gpio_write_bit(ERROR_LED_PORT, ERROR_LED_PIN, 0); + } + i++; + } +#else + /* No error LED is defined; do nothing. */ + while (1) + ; +#endif +} diff --git a/BootLoaders/Boards/stm32/cores/maple/main.cpp b/BootLoaders/Boards/stm32/cores/maple/main.cpp new file mode 100644 index 0000000..3d78443 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/main.cpp @@ -0,0 +1,44 @@ +/****************************************************************************** + * 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. + *****************************************************************************/ + +extern void setup(void); +extern void loop(void); +extern void init(void); + +// Force init to be called *first*, i.e. before static object allocation. +// Otherwise, statically allocated objects that need libmaple may fail. + __attribute__(( constructor (101))) void premain() { + init(); +} + +int main(void) { + setup(); + + while (1) { + loop(); + } + return 0; +} diff --git a/BootLoaders/Boards/stm32/cores/maple/new.cpp b/BootLoaders/Boards/stm32/cores/maple/new.cpp new file mode 100644 index 0000000..f189775 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/new.cpp @@ -0,0 +1,36 @@ +/* + Copyright (c) 2014 Arduino. All right reserved. + + 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. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include + +void *operator new(size_t size) { + return malloc(size); +} + +void *operator new[](size_t size) { + return malloc(size); +} + +void operator delete(void * ptr) { + free(ptr); +} + +void operator delete[](void * ptr) { + free(ptr); +} + diff --git a/BootLoaders/Boards/stm32/cores/maple/pwm.cpp b/BootLoaders/Boards/stm32/cores/maple/pwm.cpp new file mode 100644 index 0000000..6977fd6 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/pwm.cpp @@ -0,0 +1,61 @@ +/****************************************************************************** + * 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 + * 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/pwm.cpp + * @brief Wiring-style pwmWrite(). + */ + +#include "pwm.h" + +#include +#include + +#include "boards.h" +#include "io.h" + +void pwmWrite(uint8 pin, uint16 duty_cycle) { + if (pin >= BOARD_NR_GPIO_PINS) { + return; + } + 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); +} + +/* + * Roger Clark. Added new function to replicate more closely what the Arduino API does + * Note. This implementation is currently slower than it could be, + * because pinMode needs to be called to set the special (new) mode of PWM + * Some optimisation may be possible with pinMode or even in this function + */ +void analogWrite(uint8 pin, int duty_cycle8) +{ + pinMode(pin,PWM); + pwmWrite(pin,duty_cycle8 * 257);// 257 maps 255 to 65535 (i.e 255*257 = 65535) +} diff --git a/BootLoaders/Boards/stm32/cores/maple/pwm.h b/BootLoaders/Boards/stm32/cores/maple/pwm.h new file mode 100644 index 0000000..7775102 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/pwm.h @@ -0,0 +1,59 @@ +/****************************************************************************** + * 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/include/wirish/pwm.h + * @brief Wiring-style PWM interface. + */ + +#ifndef _WIRISH_PWM_H_ +#define _WIRISH_PWM_H_ + +#include + +/** + * Set the PWM duty on the given pin. + * + * User code is expected to determine and honor the maximum value + * (based on the configured period). + * + * @param pin PWM output pin + * @param duty_cycle Duty cycle to set. (Range is 0 to 65535) + */ +void pwmWrite(uint8 pin, uint16 duty_cycle16); + +/** + * Roger Clark. 20140103 + * Added function to replicate the Arduino PWM functionality or range 0 to 255 + * User code is expected to determine and honor the maximum value + * (based on the configured period). + * + * @param pin PWM output pin + * @param duty_cycle Duty cycle to set. (Range is 0 to 255) + */ +void analogWrite(uint8 pin, int duty_cycle8); +#endif + diff --git a/BootLoaders/Boards/stm32/cores/maple/rules.mk b/BootLoaders/Boards/stm32/cores/maple/rules.mk new file mode 100644 index 0000000..1cac74a --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/rules.mk @@ -0,0 +1,62 @@ +# Standard things +sp := $(sp).x +dirstack_$(sp) := $(d) +d := $(dir) +BUILDDIRS += $(BUILD_PATH)/$(d) + +# 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) + +# Safe includes for Wirish. +WIRISH_INCLUDES := -I$(d)/include -I$(d)/$(WIRISH_BOARD_PATH)/include + +# 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 +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 +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. +cppSRCS_$(d) += HardwareSPI.cpp # FIXME: port to F2 and fix wirish.h +endif +cppSRCS_$(d) += wirish_analog.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) += $(MCU_SERIES)/wirish_debug.cpp +cppSRCS_$(d) += $(WIRISH_BOARD_PATH)/board.cpp + +sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%) +cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%) +cppFILES_$(d) := $(cppSRCS_$(d):%=$(d)/%) + +OBJS_$(d) := $(sFILES_$(d):%.S=$(BUILD_PATH)/%.o) \ + $(cFILES_$(d):%.c=$(BUILD_PATH)/%.o) \ + $(cppFILES_$(d):%.cpp=$(BUILD_PATH)/%.o) +DEPS_$(d) := $(OBJS_$(d):%.o=%.d) + +$(OBJS_$(d)): TGT_CFLAGS := $(CFLAGS_$(d)) + +TGT_BIN += $(OBJS_$(d)) + +# Standard things +-include $(DEPS_$(d)) +d := $(dirstack_$(sp)) +sp := $(basename $(sp)) diff --git a/BootLoaders/Boards/stm32/cores/maple/sdio.cpp b/BootLoaders/Boards/stm32/cores/maple/sdio.cpp new file mode 100644 index 0000000..8bd9491 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/sdio.cpp @@ -0,0 +1,198 @@ +/****************************************************************************** + * 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/sdio.c + * @author stevstrong + * @brief Secure digital input/output interface. + */ + +#include +#include +#include +#include "wirish.h" + + +//#include +//#include +//#include +//#include "wirish.h" +//#include "boards.h" +// + +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) + +sdio_dev * SDIO = SDIO_BASE; + +#define DELAY_LONG 10 +#define DELAY_SHORT 1 + +uint8_t dly = DELAY_LONG; // microseconds delay after accessing registers + +/* + * SDIO convenience routines + */ +void sdio_gpios_init(void) +{ + gpio_set_mode(PIN_MAP[BOARD_SDIO_D0].gpio_device, PIN_MAP[BOARD_SDIO_D0].gpio_bit, GPIO_AF_OUTPUT_PP); + gpio_set_mode(PIN_MAP[BOARD_SDIO_D1].gpio_device, PIN_MAP[BOARD_SDIO_D1].gpio_bit, GPIO_AF_OUTPUT_PP); + gpio_set_mode(PIN_MAP[BOARD_SDIO_D2].gpio_device, PIN_MAP[BOARD_SDIO_D2].gpio_bit, GPIO_AF_OUTPUT_PP); + gpio_set_mode(PIN_MAP[BOARD_SDIO_D3].gpio_device, PIN_MAP[BOARD_SDIO_D3].gpio_bit, GPIO_AF_OUTPUT_PP); + gpio_set_mode(PIN_MAP[BOARD_SDIO_CLK].gpio_device, PIN_MAP[BOARD_SDIO_CLK].gpio_bit, GPIO_AF_OUTPUT_PP); + gpio_set_mode(PIN_MAP[BOARD_SDIO_CMD].gpio_device, PIN_MAP[BOARD_SDIO_CMD].gpio_bit, GPIO_AF_OUTPUT_PP); + /* + * Todo just remove it, not needed for F1. + */ + /* + gpio_set_af_mode(BOARD_SDIO_D0, 12); + gpio_set_af_mode(BOARD_SDIO_D1, 12); + gpio_set_af_mode(BOARD_SDIO_D2, 12); + gpio_set_af_mode(BOARD_SDIO_D3, 12); + gpio_set_af_mode(BOARD_SDIO_CLK, 12); + gpio_set_af_mode(BOARD_SDIO_CMD, 12); + */ +} + +void sdio_gpios_deinit(void) +{ + gpio_set_mode(PIN_MAP[BOARD_SDIO_D0].gpio_device, PIN_MAP[BOARD_SDIO_D0].gpio_bit, GPIO_INPUT_FLOATING); + gpio_set_mode(PIN_MAP[BOARD_SDIO_D1].gpio_device, PIN_MAP[BOARD_SDIO_D1].gpio_bit, GPIO_INPUT_FLOATING); + gpio_set_mode(PIN_MAP[BOARD_SDIO_D2].gpio_device, PIN_MAP[BOARD_SDIO_D2].gpio_bit, GPIO_INPUT_FLOATING); + gpio_set_mode(PIN_MAP[BOARD_SDIO_D3].gpio_device, PIN_MAP[BOARD_SDIO_D3].gpio_bit, GPIO_INPUT_FLOATING); + gpio_set_mode(PIN_MAP[BOARD_SDIO_CLK].gpio_device, PIN_MAP[BOARD_SDIO_CLK].gpio_bit, GPIO_INPUT_FLOATING); + gpio_set_mode(PIN_MAP[BOARD_SDIO_CMD].gpio_device, PIN_MAP[BOARD_SDIO_CMD].gpio_bit, GPIO_INPUT_FLOATING); + + /* + * Todo just remove it, not needed for F1. + */ + /* + gpio_set_af_mode(BOARD_SDIO_D0, 0); + gpio_set_af_mode(BOARD_SDIO_D1, 0); + gpio_set_af_mode(BOARD_SDIO_D2, 0); + gpio_set_af_mode(BOARD_SDIO_D3, 0); + gpio_set_af_mode(BOARD_SDIO_CLK, 0); + gpio_set_af_mode(BOARD_SDIO_CMD, 0); + */ +} + +/** + * @brief Initialize and reset the SDIO device. + */ +void sdio_init(void) +{ + rcc_clk_enable(RCC_SDIO); + rcc_reset_dev(RCC_SDIO); +} + +void sdio_power_on(void) +{ + SDIO->POWER = SDIO_POWER_PWRCTRL_ON; +// After a data write, data cannot be written to this register for three SDIOCLK clock periods +// plus two PCLK2 clock periods. + delay_us(DELAY_LONG); +} + +void sdio_power_off(void) +{ + SDIO->POWER = SDIO_POWER_PWRCTRL_OFF; +// After a data write, data cannot be written to this register for three SDIOCLK clock periods +// plus two PCLK2 clock periods. + delay_us(DELAY_LONG); +} + +void sdio_set_clock(uint32_t clk) +{ + if (clk>24000000UL) clk = 24000000UL; // limit the SDIO master clock to 24MHz + + if (clk<1000000) dly = DELAY_LONG; + else dly = DELAY_SHORT; + + sdio_disable(); + SDIO->CLKCR = (SDIO->CLKCR & (~(SDIO_CLKCR_CLKDIV|SDIO_CLKCR_BYPASS))) | SDIO_CLKCR_CLKEN | (((SDIOCLK/clk)-2)&SDIO_CLKCR_CLKDIV); + delay_us(dly); +} + +void sdio_set_dbus_width(uint16_t bus_w) +{ + SDIO->CLKCR = (SDIO->CLKCR & (~SDIO_CLKCR_WIDBUS)) | bus_w; + delay_us(dly); +} + +void sdio_set_dblock_size(uint8_t dbsize) +{ + SDIO->DCTRL = (SDIO->DCTRL&(~SDIO_DCTRL_DBLOCKSIZE)) | ((dbsize&0xF)<<4); + delay_us(dly); +} + +void sdio_enable(void) +{ + SDIO->CLKCR |= SDIO_CLKCR_CLKEN; + delay_us(dly); +} + +void sdio_disable(void) +{ + SDIO->CLKCR ^= SDIO_CLKCR_CLKEN; + delay_us(dly); +} + +/** + * @brief Configure and enable the SDIO device. + */ +void sdio_begin(void) +{ + sdio_gpios_init(); + sdio_init(); + sdio_power_on(); + // Set initial SCK rate. + sdio_set_clock(400000); + delay_us(200); // generate 80 pulses at 400kHz +} + +/** + * @brief Disables the SDIO device. + */ +void sdio_end(void) +{ + sdio_disable(); + while ( sdio_cmd_xfer_ongoing() ); + sdio_power_off(); + rcc_clk_disable(RCC_SDIO); + sdio_gpios_deinit(); +} + +/** + * @brief Send command by the SDIO device. + */ +uint8_t sdio_cmd_send(uint16_t cmd_index_resp_type, uint32_t arg) +{ + uint8_t retries = 10; // in case of errors + do { // retry command if errors detected + // clear interrupt flags - IMPORTANT!!! + SDIO->ICR = SDIO_ICR_CMD_FLAGS; + // write command + SDIO->ARG = arg; + SDIO->CMD = (uint32_t)(SDIO_CMD_CPSMEN | cmd_index_resp_type ); + while ( (SDIO->STA&SDIO_STA_CMDACT) ) ; // wait for actual command transfer to finish + // wait for response, if the case + if ( cmd_index_resp_type&(SDIO_CMD_WAIT_SHORT_RESP|SDIO_CMD_WAIT_LONG_RESP) ) { + while ( !(SDIO->STA&(SDIO_STA_CMDREND|SDIO_STA_CMD_ERROR_FLAGS)) ) ; + } else break; // no response required + if ( SDIO->STA&(SDIO_STA_CMDREND|SDIO_STA_CTIMEOUT) ) + break; // response received or timeout + // ignore CRC error for CMD5 and ACMD41 + if ( ((cmd_index_resp_type&SDIO_CMD_CMDINDEX)==5) || ((cmd_index_resp_type&SDIO_CMD_CMDINDEX)==41) ) + break; + } while ( (--retries) ); + return (uint8_t)retries; +} + +#endif // defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) diff --git a/BootLoaders/Boards/stm32/cores/maple/stm32f1/util_hooks.c b/BootLoaders/Boards/stm32/cores/maple/stm32f1/util_hooks.c new file mode 100644 index 0000000..8f798a1 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/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/BootLoaders/Boards/stm32/cores/maple/stm32f1/wiring_pulse_f1.cpp b/BootLoaders/Boards/stm32/cores/maple/stm32f1/wiring_pulse_f1.cpp new file mode 100644 index 0000000..3abac9d --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/stm32f1/wiring_pulse_f1.cpp @@ -0,0 +1,75 @@ +#include +#include "boards.h" +/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH + * or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds + * to 3 minutes in length, but must be called at least a few dozen microseconds + * before the start of the pulse. */ + + + /* + * Roger Clark + * + * Note. The API spec for this function published on http://www.arduino.cc/en/Reference/PulseIn + * doesn't reflect what either the AVR or SAM version of this function actualy do with regard to the timeout value + * + * "timeout (optional): the number of microseconds to wait for the pulse to start; default is one second (unsigned long) " + * + * Because the timeout, is actually coded as the total time to both wait while the input is in the state requested + * then wait for the opposite state duration + * then count the length of the pulse when it has the value of state (HIGH or LOW) + * + * So I think the code for both the AVR and the Due is wrong in that it doesnt match the spec + * + * I have done basically the same as the AVR and Due code, except to make the timeout a bit more accurate I have put in a dummy volatile varable + * dummyWidth so that both the waiting while loops take the same number of clock cycles to execute as the acount width counting loop + * + * to be slighly more accurate the maxLoops variable really needs to take into account the loop setup code, but its probably as good as necessary + * + */ +uint32_t pulseIn( uint32_t pin, uint32_t state, uint32_t timeout ) +{ + // cache the port and bit of the pin in order to speed up the + // pulse width measuring loop and achieve finer resolution. calling + // digitalRead() instead yields much coarser resolution. + + gpio_dev *dev=PIN_MAP[pin].gpio_device; + uint32_t bit = (1U << PIN_MAP[pin].gpio_bit); + + + uint32_t width = 0; // keep initialization out of time critical area + + // convert the timeout from microseconds to a number of times through + // the initial loop; it takes 16 clock cycles per iteration. + uint32_t numloops = 0; + uint32_t maxloops = timeout * ( F_CPU / 16000000); + volatile uint32_t dummyWidth=0; + + // wait for any previous pulse to end + while ( (dev->regs->IDR & bit) == bit) { + if (numloops++ == maxloops) { + return 0; + } + dummyWidth++; + } + + // wait for the pulse to start + while ((dev->regs->IDR & bit) != bit) { + if (numloops++ == maxloops) { + return 0; + } + dummyWidth++; + } + + // wait for the pulse to stop + while ((dev->regs->IDR & bit) == bit) { + if (numloops++ == maxloops) { + return 0; + } + width++; + } + + // Excluding time taking up by the interrupts, it needs 16 clock cycles to look through the last while loop + // 5 is added as a fiddle factor to correct for interrupts etc. But ultimately this would only be accurate if it was done ona hardware timer + + return (uint32_t)( ( (unsigned long long)(width+5) * (unsigned long long) 16000000.0) /(unsigned long long)F_CPU ) ; +} diff --git a/BootLoaders/Boards/stm32/cores/maple/stm32f1/wirish_debug.cpp b/BootLoaders/Boards/stm32/cores/maple/stm32f1/wirish_debug.cpp new file mode 100644 index 0000000..f057616 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/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/BootLoaders/Boards/stm32/cores/maple/stm32f1/wirish_digital_f1.cpp b/BootLoaders/Boards/stm32/cores/maple/stm32f1/wirish_digital_f1.cpp new file mode 100644 index 0000000..3ea5ed0 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/stm32f1/wirish_digital_f1.cpp @@ -0,0 +1,92 @@ +/****************************************************************************** + * 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) { + if ( pwm ) { // we're switching into PWM, enable timer channels + timer_set_mode(PIN_MAP[pin].timer_device, + PIN_MAP[pin].timer_channel, + TIMER_PWM ); + } else { // disable channel output in non pwm-Mode + timer_cc_disable(PIN_MAP[pin].timer_device, + PIN_MAP[pin].timer_channel); + } + } +} diff --git a/BootLoaders/Boards/stm32/cores/maple/tone.cpp b/BootLoaders/Boards/stm32/cores/maple/tone.cpp new file mode 100644 index 0000000..45cfa0e --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/tone.cpp @@ -0,0 +1,204 @@ +/////////////////////////////////////////////////////////////////////// +// +// tone(pin,frequency[,duration]) generate a tone on a given pin +// +// noTone(pin) switch off the tone on the pin +// +// setToneTimerChannel(timer,channel) force use of given timer/channel +// +/////////////////////////////////////////////////////////////////////// + +#include "Arduino.h" +#include + + +#define PinTimer(pin) (PIN_MAP[pin].timer_device->clk_id-RCC_TIMER1+1) +#define PinChannel(pin) (PIN_MAP[pin].timer_channel) + +// if USE_PIN_TIMER is set, the PWM timer/channel is used for PWM pins +#define USE_PIN_TIMER + +// if USE_BSRR is set the tone pin will be written via the fast BSRR register +// instead of using the slow digitalWrite() function in the interrupt handler +#define USE_BSRR + +// construct static timer array ( + + +#ifdef STM32_HIGH_DENSITY +// define default timer and channel + #ifndef TONE_TIMER + #define TONE_TIMER 8 + #endif + #ifndef TONE_CHANNEL + #define TONE_CHANNEL 8 + #endif + + HardwareTimer TTimer1(1), TTimer2(2), TTimer3(3), TTimer4(4),TTimer5(5), TTimer6(6), TTimer7(7), TTimer8(8); + HardwareTimer *TTimer[8] = { &TTimer1,&TTimer2,&TTimer3,&TTimer4,&TTimer5,&TTimer6,&TTimer7,&TTimer8 }; +#else + // define default timer and channel + #ifndef TONE_TIMER + #define TONE_TIMER 4 + #endif + #ifndef TONE_CHANNEL + #define TONE_CHANNEL 4 + #endif + + HardwareTimer TTimer1(1), TTimer2(2), TTimer3(3), TTimer4(4); + HardwareTimer *TTimer[4] = { &TTimer1,&TTimer2,&TTimer3,&TTimer4 }; +#endif + + +uint8_t tone_force_channel = 0; // forced timer channel +uint8_t tone_force_ntimer = 0; // forced timer + +HardwareTimer *tone_timer;// = TTimer[TONE_TIMER-1]; // timer used to generate frequency +uint8_t tone_channel = TONE_CHANNEL; // timer channel used to generate frequency +uint8_t tone_ntimer = TONE_TIMER; // timer used to generate frequency + +bool tone_state = true; // last pin state for toggling +short tone_pin = -1; // pin for outputting sound +short tone_freq = 444; // tone frequency (0=pause) +volatile uint32_t tone_nhw = 0; // tone duration in number of half waves +uint16_t tone_tcount = 0; // time between handler calls in 1/36 usec +uint16_t tone_ncount = 0; // handler call between toggling +uint16_t tone_n = 0; // remaining handler calls before toggling +uint32_t tone_next = 0; // counter value of next interrupt + +#ifdef USE_BSRR +volatile uint32_t *tone_bsrr; // BSRR set register (lower 16 bits) +uint32_t tone_smask=0; // BSRR set bitmask +uint32_t tone_rmask=0; // BSRR reset bitmask +#endif + + +//////////////////////////////////////////////////////////////////////////////// +// timer hander for tone with no duration specified, +// will keep going until noTone() is called +void tone_handler_1(void) { + tone_next += tone_tcount; // comparator value for next interrupt + tone_timer->setCompare(tone_channel, tone_next); // and install it + if(--tone_n == 0){ + tone_state = !tone_state; // toggle tone output + +#ifdef USE_BSRR + if(tone_state) + *tone_bsrr = tone_smask; + else + *tone_bsrr = tone_rmask; +#else + digitalWrite(tone_pin,tone_state);// and output it +#endif + + tone_n = tone_ncount; // reset interrupt counter + } +} + +//////////////////////////////////////////////////////////////////////////////// +// timer hander for tone with a specified duration, +// will stop automatically when duration time is up. +void tone_handler_2(void) { + tone_next += tone_tcount; + tone_timer->setCompare(tone_channel, tone_next); + if(--tone_n == 0){ + if(tone_freq>0){ // toggle pin + tone_state = !tone_state; +#ifdef USE_BSRR + if(tone_state) + *tone_bsrr = tone_smask; + else + *tone_bsrr = tone_rmask; +#else + digitalWrite(tone_pin,tone_state);// and output it +#endif + } + tone_n = tone_ncount; + if(!--tone_nhw){ // check if tone duration has finished + tone_timer->pause(); // disable timer + pinMode(tone_pin, INPUT); // disable tone pin + } + } +} + +//////////////////////////////////////////////////////////////////////////////// +// play a tone on given pin with given frequency and optional duration in msec +void tone(uint32_t pin, uint32_t freq, uint32_t duration) { + tone_pin = pin; + +#ifdef USE_PIN_TIMER + // if the pin has a PWM timer/channel, use it (unless the timer/channel are forced) + if(PinChannel(tone_pin) && !tone_force_channel){ + tone_channel = PinChannel(tone_pin); + tone_ntimer = PinTimer(tone_pin); + } else +#endif + { + // set timer and channel to default resp values forced with setToneTimerChannel + tone_ntimer = tone_force_channel?tone_force_ntimer:TONE_TIMER; + tone_channel = tone_force_channel?tone_force_channel:TONE_CHANNEL; + } + + tone_timer = TTimer[tone_ntimer-1]; + tone_freq = freq; + tone_nhw = 0; + tone_next = 0; + + tone_timer->pause(); + + if(freq > 0){ + uint32_t count = (F_CPU/4)/freq; // timer counts per half wave + tone_ncount = tone_n = (count>>16)+1; // number of 16-bit count chunk + tone_tcount = count/tone_ncount; // size of count chunk + if(duration > 0) // number of half waves to be generated + tone_nhw = ((duration*freq)/1000)<<1; + else // no duration specified, continuous sound until noTone() called + tone_nhw = 0; + + pinMode(tone_pin, PWM); // configure output pin + pinMode(tone_pin, OUTPUT); // configure output pin + +#ifdef USE_BSRR + // Set up BSRR register values for fast ISR + tone_bsrr = &((PIN_MAP[tone_pin].gpio_device)->regs->BSRR); + tone_smask = (BIT(PIN_MAP[tone_pin].gpio_bit)); + tone_rmask = tone_smask<<16; +#endif + + // Set up an interrupt on given timer and channel + tone_next = tone_tcount; // prepare channel compare register + tone_timer->setMode(tone_channel,TIMER_OUTPUT_COMPARE); + tone_timer->setCompare(tone_channel,tone_next); + // attach corresponding handler routine + tone_timer->attachInterrupt(tone_channel,tone_nhw?tone_handler_2:tone_handler_1); + + // Refresh the tone timer + tone_timer->refresh(); + + // Start the timer counting + tone_timer->resume(); + + } else { + + // detach handler routine + tone_timer->detachInterrupt(tone_channel); + // disactive pin by configuring it as input + pinMode(tone_pin, INPUT); + + } + while(tone_nhw) ; // blocks till duration elapsed +} + +//////////////////////////////////////////////////////////////////////////////// +// disable tone on specified pin, if any +void noTone(uint32_t pin){ + tone(pin,0,0); // it's all handled in tone() +} + +//////////////////////////////////////////////////////////////////////////////// +// set timer and channel to some different value +// must be called before calling tone() or after noTone() was called +void setToneTimerChannel(uint8_t ntimer, uint8_t channel){ + tone_force_ntimer = ntimer; + tone_force_channel = channel; +} diff --git a/BootLoaders/Boards/stm32/cores/maple/tone.h b/BootLoaders/Boards/stm32/cores/maple/tone.h new file mode 100644 index 0000000..cf27051 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/tone.h @@ -0,0 +1,28 @@ +/* + Copyright (c) 2015 Arduino LLC. All right reserved. + + 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. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#pragma once + +#ifdef __cplusplus + +#include "Arduino.h" + +void tone(uint32_t _pin, uint32_t frequency, uint32_t duration = 0); +void noTone(uint32_t _pin); + +#endif diff --git a/BootLoaders/Boards/stm32/cores/maple/usb_serial.cpp b/BootLoaders/Boards/stm32/cores/maple/usb_serial.cpp new file mode 100644 index 0000000..0902c50 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/usb_serial.cpp @@ -0,0 +1,359 @@ +/****************************************************************************** + * 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. + *****************************************************************************/ + +/** + * @brief USB virtual serial terminal + */ + +#include "usb_serial.h" + +#include "string.h" +#include "stdint.h" + +#include +#include +#include +#include + +#include "wirish.h" + +/* + * Hooks used for bootloader reset signalling + */ + +#if BOARD_HAVE_SERIALUSB +static void rxHook(unsigned, void*); +static void ifaceSetupHook(unsigned, void*); +#endif + +/* + * USBSerial interface + */ + +#define USB_TIMEOUT 50 +#if BOARD_HAVE_SERIALUSB +bool USBSerial::_hasBegun = false; +#endif + +USBSerial::USBSerial(void) { +#if !BOARD_HAVE_SERIALUSB + ASSERT(0); +#endif +} + +void USBSerial::begin(void) { + +#if BOARD_HAVE_SERIALUSB + if (_hasBegun) + return; + _hasBegun = true; + + usb_cdcacm_enable(BOARD_USB_DISC_DEV, (uint8_t)BOARD_USB_DISC_BIT); + usb_cdcacm_set_hooks(USB_CDCACM_HOOK_RX, rxHook); + usb_cdcacm_set_hooks(USB_CDCACM_HOOK_IFACE_SETUP, ifaceSetupHook); +#endif +} + +//Roger Clark. Two new begin functions has been added so that normal Arduino Sketches that use Serial.begin(xxx) will compile. +void USBSerial::begin(unsigned long ignoreBaud) +{ +volatile unsigned long removeCompilerWarningsIgnoreBaud=ignoreBaud; + + ignoreBaud=removeCompilerWarningsIgnoreBaud; + begin(); +} +void USBSerial::begin(unsigned long ignoreBaud, uint8_t ignore) +{ +volatile unsigned long removeCompilerWarningsIgnoreBaud=ignoreBaud; +volatile uint8_t removeCompilerWarningsIgnore=ignore; + + ignoreBaud=removeCompilerWarningsIgnoreBaud; + ignore=removeCompilerWarningsIgnore; + begin(); +} + +void USBSerial::end(void) { +#if BOARD_HAVE_SERIALUSB + usb_cdcacm_disable(BOARD_USB_DISC_DEV, (uint8_t)BOARD_USB_DISC_BIT); + usb_cdcacm_remove_hooks(USB_CDCACM_HOOK_RX | USB_CDCACM_HOOK_IFACE_SETUP); + _hasBegun = false; +#endif + +} + +size_t USBSerial::write(uint8 ch) { +size_t n = 0; + this->write(&ch, 1); + return n; +} + +size_t USBSerial::write(const char *str) { +size_t n = 0; + this->write((const uint8*)str, strlen(str)); + return n; +} + +size_t USBSerial::write(const uint8 *buf, uint32 len) +{ +size_t n = 0; + if (!(bool) *this || !buf) { + return 0; + } + + uint32 txed = 0; + while (txed < len) { + txed += usb_cdcacm_tx((const uint8*)buf + txed, len - txed); + } + + return n; +} + +int USBSerial::available(void) { + return usb_cdcacm_data_available(); +} + +int USBSerial::peek(void) +{ + uint8 b; + if (usb_cdcacm_peek(&b, 1)==1) + { + return b; + } + else + { + return -1; + } +} + +void USBSerial::flush(void) +{ +/*Roger Clark. Rather slow method. Need to improve this */ + uint8 b; + while(usb_cdcacm_data_available()) + { + this->read(&b, 1); + } + return; +} + +uint32 USBSerial::read(uint8 * buf, uint32 len) { + uint32 rxed = 0; + while (rxed < len) { + rxed += usb_cdcacm_rx(buf + rxed, len - rxed); + } + + return rxed; +} + +size_t USBSerial::readBytes(char *buf, const size_t& len) +{ + size_t rxed=0; + unsigned long startMillis; + startMillis = millis(); + if (len <= 0) return 0; + do { + rxed += usb_cdcacm_rx((uint8 *)buf + rxed, len - rxed); + if (rxed == len) return rxed; + } while(millis() - startMillis < _timeout); + return rxed; +} + +/* Blocks forever until 1 byte is received */ +int USBSerial::read(void) { + uint8 b; + /* + this->read(&b, 1); + return b; + */ + + if (usb_cdcacm_rx(&b, 1)==0) + { + return -1; + } + else + { + return b; + } +} + +uint8 USBSerial::pending(void) { + return usb_cdcacm_get_pending(); +} + +uint8 USBSerial::getDTR(void) { + return usb_cdcacm_get_dtr(); +} + +uint8 USBSerial::getRTS(void) { + return usb_cdcacm_get_rts(); +} + +USBSerial::operator bool() { + return usb_is_connected(USBLIB) && usb_is_configured(USBLIB) && usb_cdcacm_get_dtr(); +} + +#if BOARD_HAVE_SERIALUSB + #ifdef SERIAL_USB + USBSerial Serial; + #endif +#endif + +/* + * Bootloader hook implementations + */ + +#if BOARD_HAVE_SERIALUSB + +enum reset_state_t { + DTR_UNSET, + DTR_HIGH, + DTR_NEGEDGE, + DTR_LOW +}; + +static reset_state_t reset_state = DTR_UNSET; + +static void ifaceSetupHook(unsigned hook, void *requestvp) { + uint8 request = *(uint8*)requestvp; + + // Ignore requests we're not interested in. + if (request != USB_CDCACM_SET_CONTROL_LINE_STATE) { + return; + } + +#ifdef SERIAL_USB + // We need to see a negative edge on DTR before we start looking + // for the in-band magic reset byte sequence. + uint8 dtr = usb_cdcacm_get_dtr(); + switch (reset_state) { + case DTR_UNSET: + reset_state = dtr ? DTR_HIGH : DTR_LOW; + break; + case DTR_HIGH: + reset_state = dtr ? DTR_HIGH : DTR_NEGEDGE; + break; + case DTR_NEGEDGE: + reset_state = dtr ? DTR_HIGH : DTR_LOW; + break; + case DTR_LOW: + reset_state = dtr ? DTR_HIGH : DTR_LOW; + break; + } +#endif + +#if defined(BOOTLOADER_robotis) + uint8 dtr = usb_cdcacm_get_dtr(); + uint8 rts = usb_cdcacm_get_rts(); + + if (rts && !dtr) { + reset_state = DTR_NEGEDGE; + } +#endif + + if ((usb_cdcacm_get_baud() == 1200) && (reset_state == DTR_NEGEDGE)) { + iwdg_init(IWDG_PRE_4, 10); + while (1); + } +} + +#define RESET_DELAY 100000 +#ifdef SERIAL_USB +static void wait_reset(void) { + delay_us(RESET_DELAY); + nvic_sys_reset(); +} +#endif + +#define STACK_TOP 0x20000800 +#define EXC_RETURN 0xFFFFFFF9 +#define DEFAULT_CPSR 0x61000000 +static void rxHook(unsigned hook, void *ignored) { + /* FIXME this is mad buggy; we need a new reset sequence. E.g. NAK + * after each RX means you can't reset if any bytes are waiting. */ + if (reset_state == DTR_NEGEDGE) { + reset_state = DTR_LOW; + + if (usb_cdcacm_data_available() >= 4) { + // The magic reset sequence is "1EAF". +#ifdef SERIAL_USB + static const uint8 magic[4] = {'1', 'E', 'A', 'F'}; +#else + #if defined(BOOTLOADER_robotis) + static const uint8 magic[4] = {'C', 'M', '9', 'X'}; + #else + static const uint8 magic[4] = {'1', 'E', 'A', 'F'}; + #endif +#endif + + uint8 chkBuf[4]; + + // Peek at the waiting bytes, looking for reset sequence, + // bailing on mismatch. + usb_cdcacm_peek_ex(chkBuf, usb_cdcacm_data_available() - 4, 4); + for (unsigned i = 0; i < sizeof(magic); i++) { + if (chkBuf[i] != magic[i]) { + return; + } + } + +#ifdef SERIAL_USB + // Got the magic sequence -> reset, presumably into the bootloader. + // Return address is wait_reset, but we must set the thumb bit. + uintptr_t target = (uintptr_t)wait_reset | 0x1; + 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"); +#endif + +#if defined(BOOTLOADER_robotis) + iwdg_init(IWDG_PRE_4, 10); +#endif + + /* Can't happen. */ + ASSERT_FAULT(0); + } + } +} + +#endif // BOARD_HAVE_SERIALUSB diff --git a/BootLoaders/Boards/stm32/cores/maple/usb_serial.h b/BootLoaders/Boards/stm32/cores/maple/usb_serial.h new file mode 100644 index 0000000..8351593 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/usb_serial.h @@ -0,0 +1,94 @@ +/****************************************************************************** + * 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. + *****************************************************************************/ + +/** + * @brief Wirish USB virtual serial port (SerialUSB). + */ + +#ifndef _WIRISH_USB_SERIAL_H_ +#define _WIRISH_USB_SERIAL_H_ + +#include "Print.h" +#include "boards.h" +#include "Stream.h" + +/** + * @brief Virtual serial terminal. + */ +class USBSerial : public Stream { +public: + USBSerial(void); + + void begin(void); + + // Roger Clark. Added dummy function so that existing Arduino sketches which specify baud rate will compile. + void begin(unsigned long); + void begin(unsigned long, uint8_t); + void end(void); + + virtual int available(void);// Changed to virtual + + size_t readBytes(char *buf, const size_t& len); + uint32 read(uint8 * buf, uint32 len); + // uint8 read(void); + + // Roger Clark. added functions to support Arduino 1.0 API + virtual int peek(void); + virtual int read(void); + int availableForWrite(void); + virtual void flush(void); + + + size_t write(uint8); + size_t write(const char *str); + size_t write(const uint8*, uint32); + + uint8 getRTS(); + uint8 getDTR(); + uint8 pending(); + + /* SukkoPera: This is the Arduino way to check if an USB CDC serial + * connection is open. + + * Used for instance in cardinfo.ino. + */ + operator bool(); + + /* Old libmaple way to check for serial connection. + * + * Deprecated, use the above. + */ + uint8 isConnected() __attribute__((deprecated("Use !Serial instead"))) { return (bool) *this; } + +protected: + static bool _hasBegun; +}; + +#ifdef SERIAL_USB + extern USBSerial Serial; +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/cores/maple/wiring_private.h b/BootLoaders/Boards/stm32/cores/maple/wiring_private.h new file mode 100644 index 0000000..88fd009 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/wiring_private.h @@ -0,0 +1,4 @@ +#ifndef WiringPrivate_h +#define WiringPrivate_h + +#endif \ No newline at end of file diff --git a/BootLoaders/Boards/stm32/cores/maple/wiring_pulse.h b/BootLoaders/Boards/stm32/cores/maple/wiring_pulse.h new file mode 100644 index 0000000..c98ce4a --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/wiring_pulse.h @@ -0,0 +1,37 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2015 Roger Clark + * + * 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 _WIRISH_PULSE_H_ +#define _WIRISH_PULSE_H_ + +#include + +uint32_t pulseIn( uint32_t ulPin, uint32_t ulState, uint32_t ulTimeout = 1000000L ) ; + + +#endif diff --git a/BootLoaders/Boards/stm32/cores/maple/wirish.h b/BootLoaders/Boards/stm32/cores/maple/wirish.h new file mode 100644 index 0000000..eb07c77 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/wirish.h @@ -0,0 +1,110 @@ +/****************************************************************************** + * 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. + *****************************************************************************/ + +/** + * @brief Main include file for the Wirish core. + * + * Includes most of Wirish, and (transitively or otherwise) + * substantial pieces of libmaple proper. + */ + +#ifndef _WIRISH_WIRISH_H_ +#define _WIRISH_WIRISH_H_ + +/* + * 20141030. Roger Clark + Added the block of includes up to avr/interrupt so that stdlib functions like memcpy would be included and could be used. + */ +#include +#include + + +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if STM32_MCU_SERIES == STM32_SERIES_F1 /* FIXME [0.0.13?] port to F2 */ +//#include +#endif + +#include +#include +#include +#include + +#include + +#include + +#include +#include + +typedef unsigned int word; +// typedef uint16 word;// definition from Arduino website, now appears to be incorrect for 32 bit devices + +/* Wiring macros and bit defines */ + +#define true 0x1 +#define false 0x0 + +#define lowByte(w) ((w) & 0xFF) +#define highByte(w) (((w) >> 8) & 0xFF) +#define bitRead(value, bit) (((value) >> (bit)) & 0x01) +#define bitSet(value, bit) ((value) |= (1UL << (bit))) +#define bitClear(value, bit) ((value) &= ~(1UL << (bit))) +#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : \ + bitClear(value, bit)) +#define bit(b) (1UL << (b)) + +// Roger Clark. Added _BV macro for AVR compatibility. As requested by @sweetlilmre and @stevestrong +#ifndef _BV +#define _BV(bit) (1 << (bit)) +#endif + +#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L ) +#define clockCyclesToMicroseconds(a) ( ((a) * 1000L) / (F_CPU / 1000L) ) +#define microsecondsToClockCycles(a) ( (a) * (F_CPU / 1000000L) ) + +#define digitalPinToInterrupt(pin) (pin) + +#endif + diff --git a/BootLoaders/Boards/stm32/cores/maple/wirish_analog.cpp b/BootLoaders/Boards/stm32/cores/maple/wirish_analog.cpp new file mode 100644 index 0000000..8143996 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/wirish_analog.cpp @@ -0,0 +1,47 @@ +/****************************************************************************** + * 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 + * 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/wirish_analog.cpp + * @brief Wiring-style analogRead() implementation. + */ + +#include "io.h" +#include +#include "boards.h" + +/* 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) { + adc_dev *dev = PIN_MAP[pin].adc_device; + if (dev == NULL) { + return 0; + } + + return adc_read(dev, PIN_MAP[pin].adc_channel); +} diff --git a/BootLoaders/Boards/stm32/cores/maple/wirish_constants.h b/BootLoaders/Boards/stm32/cores/maple/wirish_constants.h new file mode 100644 index 0000000..06a85ae --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/wirish_constants.h @@ -0,0 +1,17 @@ +#ifndef _WIRING_CONSTANTS_ +#define _WIRING_CONSTANTS_ + +#ifdef __cplusplus +extern "C"{ +#endif + +enum BitOrder { + LSBFIRST = 0, + MSBFIRST = 1 +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/cores/maple/wirish_debug.h b/BootLoaders/Boards/stm32/cores/maple/wirish_debug.h new file mode 100644 index 0000000..4edfd27 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/wirish_debug.h @@ -0,0 +1,57 @@ +/****************************************************************************** + * 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 wirish/include/wirish/wirish_debug.h + * @brief High level debug port configuration + */ + +#ifndef _WIRISH_WIRISH_DEBUG_H_ +#define _WIRISH_WIRISH_DEBUG_H_ + +#include + +/** + * @brief Disable the JTAG and Serial Wire (SW) debug ports. + * + * You can call this function in order to use the JTAG and SW debug + * pins as ordinary GPIOs. + * + * @see enableDebugPorts() + */ +void disableDebugPorts(void); + +/** + * @brief Enable the JTAG and Serial Wire (SW) debug ports. + * + * After you call this function, the JTAG and SW debug pins will no + * longer be usable as GPIOs. + * + * @see disableDebugPorts() + */ +void enableDebugPorts(void); + +#endif diff --git a/BootLoaders/Boards/stm32/cores/maple/wirish_digital.cpp b/BootLoaders/Boards/stm32/cores/maple/wirish_digital.cpp new file mode 100644 index 0000000..d0d53af --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/wirish_digital.cpp @@ -0,0 +1,97 @@ +/****************************************************************************** + * 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. + *****************************************************************************/ + +/* + * Arduino-compatible digital I/O implementation. + */ + +#include "io.h" + +#include +#include + +#include "wirish_time.h" +#include "boards.h" + +uint32 digitalRead(uint8 pin) { + if (pin >= BOARD_NR_GPIO_PINS) { + return 0; + } + + return gpio_read_bit(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit) ? + HIGH : LOW; +} + +void digitalWrite(uint8 pin, uint8 val) { + if (pin >= BOARD_NR_GPIO_PINS) { + return; + } + + gpio_write_bit(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit, val); +} + +#if FALSE +// Roger Clark. Deprecated these functions as they are not part of the standard Arduino API +void togglePin(uint8 pin) { + if (pin >= BOARD_NR_GPIO_PINS) { + return; + } + + gpio_toggle_bit(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit); +} + +#define BUTTON_DEBOUNCE_DELAY 1 + +uint8 isButtonPressed(uint8 pin, uint32 pressedLevel) { + if (digitalRead(pin) == pressedLevel) { + delay(BUTTON_DEBOUNCE_DELAY); + while (digitalRead(pin) == pressedLevel) + ; + return true; + } + return false; +} + +uint8 waitForButtonPress(uint32 timeout) { + uint32 start = millis(); + uint32 time; + if (timeout == 0) { + while (!isButtonPressed()) + ; + return true; + } + do { + time = millis(); + /* properly handle wrap-around */ + if ((start > time && time + (0xffffffffU - start) > timeout) || + time - start > timeout) { + return false; + } + } while (!isButtonPressed()); + return true; +} +#endif \ No newline at end of file diff --git a/BootLoaders/Boards/stm32/cores/maple/wirish_math.cpp b/BootLoaders/Boards/stm32/cores/maple/wirish_math.cpp new file mode 100644 index 0000000..f8ada9f --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/wirish_math.cpp @@ -0,0 +1,58 @@ +/* + * Modified by LeafLabs, LLC. + * + * Part of the Wiring project - http://wiring.org.co Copyright (c) + * 2004-06 Hernando Barragan Modified 13 August 2006, David A. Mellis + * for Arduino - http://www.arduino.cc/ + * + * 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. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include "stdlib.h" +#include "wirish_math.h" + +void randomSeed(unsigned int seed) { + if (seed != 0) { + srand(seed); + } +} + +long random(long howbig) { + if (howbig == 0) { + return 0; + } + + return rand() % howbig; +} + +long random(long howsmall, long howbig) { + if (howsmall >= howbig) { + return howsmall; + } + + long diff = howbig - howsmall; + return random(diff) + howsmall; +} + +extern uint16_t makeWord( uint16_t w ) +{ + return w ; +} + +extern uint16_t makeWord( uint8_t h, uint8_t l ) +{ + return (h << 8) | l ; +} diff --git a/BootLoaders/Boards/stm32/cores/maple/wirish_math.h b/BootLoaders/Boards/stm32/cores/maple/wirish_math.h new file mode 100644 index 0000000..b85253f --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/wirish_math.h @@ -0,0 +1,171 @@ +/****************************************************************************** + * 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/include/wirish/wirish_math.h + * @brief Includes ; provides Wiring-compatible math routines. + */ + +#ifndef _WIRISH_WIRISH_MATH_H_ +#define _WIRISH_WIRISH_MATH_H_ + +#include +#include + +/** + * @brief Initialize the pseudo-random number generator. + * @param seed the number used to initialize the seed; cannot be zero. + */ +void randomSeed(unsigned int seed); + +/** + * @brief Generate a pseudo-random number with upper bound. + * @param max An upper bound on the returned value, exclusive. + * @return A pseudo-random number in the range [0,max). + * @see randomSeed() + */ +long random(long max); + +/** + * @brief Generate a pseudo-random number with lower and upper bounds. + * @param min Lower bound on the returned value, inclusive. + * @param max Upper bound on the returned value, exclusive. + * @return A pseudo-random number in the range [min, max). + * @see randomSeed() + */ +long random(long min, long max); + +/** + * @brief Remap a number from one range to another. + * + * That is, a value equal to fromStart gets mapped to toStart, a value + * of fromEnd to toEnd, and other values are mapped proportionately. + * + * Does not constrain value to lie within [fromStart, fromEnd]. + * + * If a "start" value is larger than its corresponding "end", the + * ranges are reversed, so map(n, 1, 10, 10, 1) would reverse the + * range [1,10]. + * + * Negative numbers may appear as any argument. + * + * @param value the value to map. + * @param fromStart the beginning of the value's current range. + * @param fromEnd the end of the value's current range. + * @param toStart the beginning of the value's mapped range. + * @param toEnd the end of the value's mapped range. + * @return the mapped value. + */ + // Fix by Pito 9/2017 + static inline int32_t map(int32_t value, int32_t fromStart, int32_t fromEnd, + int32_t toStart, int32_t toEnd) { + return ((int64_t)(value - fromStart) * (toEnd - toStart)) / (fromEnd - fromStart) + + toStart; + } + +#define PI 3.1415926535897932384626433832795 +#define HALF_PI 1.5707963267948966192313216916398 +#define TWO_PI 6.283185307179586476925286766559 +#define DEG_TO_RAD 0.017453292519943295769236907684886 +#define RAD_TO_DEG 57.295779513082320876798154814105 + + +/* + * Roger Clark 20141113 + * + * Added BitOrder definition from SAM wiring_constants.h, as its needed for SPI + * as Maple doesn't have a wiring_constants file (though it probably should have in the long term to make it more compatible with the Arduino 1.0 + API + * also added definition for EULER and SERIAL and DISPLAY, also from the same SAM header + */ + +#define EULER 2.718281828459045235360287471352 +#define SERIAL 0x0 +#define DISPLAY 0x1 + +#define min(a,b) ((a)<(b)?(a):(b)) +#define max(a,b) ((a)>(b)?(a):(b)) +#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt))) +#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5)) +#define radians(deg) ((deg)*DEG_TO_RAD) +#define degrees(rad) ((rad)*RAD_TO_DEG) +#define sq(x) ((x)*(x)) + +/* undefine stdlib's abs if encountered */ +#ifdef abs +#undef abs +#endif +#define abs(x) (((x) > 0) ? (x) : -(x)) + +/* Following are duplicate declarations (with Doxygen comments) for + * some of the math.h functions; this is for the convenience of the + * Sphinx docs. + */ + +/** + * Compute the cosine of an angle, in radians. + * @param x The radian measure of the angle. + * @return The cosine of x. This value will be between -1 and 1. + */ +double cos(double x); + +/** + * Compute the sine of an angle, in radians. + * @param x The radian measure of the angle. + * @return The sine of x. This value will be between -1 and 1. + */ +double sin(double x); + +/** + * Compute the tangent of an angle, in radians. + * @param x The radian measure of the angle. + * @return The tangent of x. There are no limits on the return value + * of this function. + */ +double tan(double x); + +/** + * Compute the square root of a number. + * @param x The number whose square root to find. This value cannot + * be negative. + * @return The square root of x. The return value is never negative. + */ +double sqrt(double x); + +/** + * Compute an exponentiation. + * @param x the base. This value cannot be zero if y <= 0. This value + * cannot be negative if y is not an integral value. + * @param y the exponent. + * @return x raised to the power y. + */ +double pow(double x, double y); + +extern uint16_t makeWord( uint16_t w ) ; +extern uint16_t makeWord( uint8_t h, uint8_t l ) ; + +#define word(...) makeWord(__VA_ARGS__) + +#endif diff --git a/BootLoaders/Boards/stm32/cores/maple/wirish_shift.cpp b/BootLoaders/Boards/stm32/cores/maple/wirish_shift.cpp new file mode 100644 index 0000000..a263a07 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/wirish_shift.cpp @@ -0,0 +1,62 @@ +/****************************************************************************** + * 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 "wirish.h" + +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); + gpio_toggle_bit(PIN_MAP[clockPin].gpio_device, PIN_MAP[clockPin].gpio_bit);// togglePin(clockPin); + gpio_toggle_bit(PIN_MAP[clockPin].gpio_device, PIN_MAP[clockPin].gpio_bit);// togglePin(clockPin); + } +} + +uint32_t shiftIn( uint32_t ulDataPin, uint32_t ulClockPin, uint32_t ulBitOrder ) +{ + uint8_t value = 0 ; + uint8_t i ; + + + for ( i=0 ; i < 8 ; ++i ) + { + digitalWrite( ulClockPin, HIGH ) ; + + if ( ulBitOrder == LSBFIRST ) + { + value |= digitalRead( ulDataPin ) << i ; + } + else + { + value |= digitalRead( ulDataPin ) << (7 - i) ; + } + + digitalWrite( ulClockPin, LOW ) ; + } + + return value ; +} diff --git a/BootLoaders/Boards/stm32/cores/maple/wirish_time.cpp b/BootLoaders/Boards/stm32/cores/maple/wirish_time.cpp new file mode 100644 index 0000000..6404bec --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/wirish_time.cpp @@ -0,0 +1,48 @@ +/****************************************************************************** + * 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. + *****************************************************************************/ + +/** + * @brief Delay implementation. + */ + +#include "wirish_time.h" + +#include +#include +#include "Arduino.h" + +void delay(unsigned long ms) { + uint32 start = millis(); + do + { + yield(); + } + while (millis() - start < ms); +} + +void delayMicroseconds(uint32 us) { + delay_us(us); +} diff --git a/BootLoaders/Boards/stm32/cores/maple/wirish_time.h b/BootLoaders/Boards/stm32/cores/maple/wirish_time.h new file mode 100644 index 0000000..1703957 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/wirish_time.h @@ -0,0 +1,97 @@ +/****************************************************************************** + * 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/include/wirish/wirish_time.h + * @brief Timing and delay functions. + */ + +#ifndef _WIRISH_WIRISH_TIME_H_ +#define _WIRISH_WIRISH_TIME_H_ + +#include +#include + +#include + +/** + * Returns time (in milliseconds) since the beginning of program + * execution. On overflow, restarts at 0. + * @see micros() + */ +static inline uint32 millis(void) { + return systick_uptime(); +} + +/** + * Returns time (in microseconds) since the beginning of program + * execution. On overflow, restarts at 0. + * @see millis() + */ +static inline uint32 micros(void) { + uint32 ms; + uint32 cycle_cnt; + + do { + ms = millis(); + cycle_cnt = systick_get_count(); + asm volatile("nop"); //allow interrupt to fire + asm volatile("nop"); + } while (ms != millis()); + +#define US_PER_MS 1000 + /* SYSTICK_RELOAD_VAL is 1 less than the number of cycles it + * actually takes to complete a SysTick reload */ + return ((ms * US_PER_MS) + + (SYSTICK_RELOAD_VAL + 1 - cycle_cnt) / CYCLES_PER_MICROSECOND); +#undef US_PER_MS +} + +/** + * Delay for at least the given number of milliseconds. + * + * Interrupts, etc. may cause the actual number of milliseconds to + * exceed ms. However, this function will return no less than ms + * milliseconds from the time it is called. + * + * @param ms the number of milliseconds to delay. + * @see delayMicroseconds() + */ +void delay(unsigned long ms); + +/** + * Delay for at least the given number of microseconds. + * + * Interrupts, etc. may cause the actual number of microseconds to + * exceed us. However, this function will return no less than us + * microseconds from the time it is called. + * + * @param us the number of microseconds to delay. + * @see delay() + */ +void delayMicroseconds(uint32 us); + +#endif diff --git a/BootLoaders/Boards/stm32/cores/maple/wirish_types.h b/BootLoaders/Boards/stm32/cores/maple/wirish_types.h new file mode 100644 index 0000000..195cda8 --- /dev/null +++ b/BootLoaders/Boards/stm32/cores/maple/wirish_types.h @@ -0,0 +1,69 @@ +/****************************************************************************** + * 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 wirish/include/wirish/wirish_types.h + * @author Marti Bolivar + * @brief Wirish library type definitions. + */ + +#ifndef _WIRISH_WIRISH_TYPES_H_ +#define _WIRISH_WIRISH_TYPES_H_ + +#include +#include +#include +#include + +/** + * Invalid stm32_pin_info adc_channel value. + * @see stm32_pin_info + */ +#define ADCx 0xFF + +/** + * @brief Stores STM32-specific information related to a given Maple pin. + * @see PIN_MAP + */ +typedef struct stm32_pin_info { + gpio_dev *gpio_device; /**< Maple pin's GPIO device */ + timer_dev *timer_device; /**< Pin's timer device, if any. */ + adc_dev *adc_device; /**< ADC device, if any. */ + uint8 gpio_bit; /**< Pin's GPIO port bit. */ + uint8 timer_channel; /**< Timer channel, or 0 if none. */ + uint8 adc_channel; /**< Pin ADC channel, or ADCx if none. */ + uint8 pinMode; /**< mode specific by pinMode call (Roger Clark added to optimize compatibility with Arduino API*/ +} stm32_pin_info; + +/** + * Variable attribute, instructs the linker to place the marked + * variable in Flash instead of RAM. */ +#define __FLASH__ __attr_flash + +typedef bool boolean; +typedef uint8 byte; + +#endif diff --git a/BootLoaders/Boards/stm32/drivers/install_drivers.bat b/BootLoaders/Boards/stm32/drivers/install_drivers.bat new file mode 100644 index 0000000..5d82705 --- /dev/null +++ b/BootLoaders/Boards/stm32/drivers/install_drivers.bat @@ -0,0 +1,11 @@ +@echo off + +echo Installing Maple DFU driver... +"%~dp0wdi-simple" --vid 0x1EAF --pid 0x0003 --type 1 --name "Maple DFU" --dest "%~dp0maple-dfu" +echo. + +echo Installing Maple Serial driver... +"%~dp0wdi-simple" --vid 0x1EAF --pid 0x0004 --type 3 --name "Maple Serial" --dest "%~dp0maple-serial" +echo. + +pause diff --git a/BootLoaders/Boards/stm32/drivers/wdi-simple.exe b/BootLoaders/Boards/stm32/drivers/wdi-simple.exe new file mode 100644 index 0000000..44e91f8 Binary files /dev/null and b/BootLoaders/Boards/stm32/drivers/wdi-simple.exe differ diff --git a/BootLoaders/Boards/stm32/libraries/EEPROM/EEPROM.cpp b/BootLoaders/Boards/stm32/libraries/EEPROM/EEPROM.cpp new file mode 100644 index 0000000..289a93a --- /dev/null +++ b/BootLoaders/Boards/stm32/libraries/EEPROM/EEPROM.cpp @@ -0,0 +1,570 @@ +#include "EEPROM.h" +// See http://www.st.com/web/en/resource/technical/document/application_note/CD00165693.pdf + +/** + * @brief Check page for blank + * @param page base address + * @retval Success or error + * EEPROM_BAD_FLASH: page not empty after erase + * EEPROM_OK: page blank + */ +uint16 EEPROMClass::EE_CheckPage(uint32 pageBase, uint16 status) +{ + uint32 pageEnd = pageBase + (uint32)PageSize; + + // Page Status not EEPROM_ERASED and not a "state" + if ((*(__io uint16*)pageBase) != EEPROM_ERASED && (*(__io uint16*)pageBase) != status) + return EEPROM_BAD_FLASH; + for(pageBase += 4; pageBase < pageEnd; pageBase += 4) + if ((*(__io uint32*)pageBase) != 0xFFFFFFFF) // Verify if slot is empty + return EEPROM_BAD_FLASH; + return EEPROM_OK; +} + +/** + * @brief Erase page with increment erase counter (page + 2) + * @param page base address + * @retval Success or error + * FLASH_COMPLETE: success erase + * - Flash error code: on write Flash error + */ +FLASH_Status EEPROMClass::EE_ErasePage(uint32 pageBase) +{ + FLASH_Status FlashStatus; + uint16 data = (*(__io uint16*)(pageBase)); + if ((data == EEPROM_ERASED) || (data == EEPROM_VALID_PAGE) || (data == EEPROM_RECEIVE_DATA)) + data = (*(__io uint16*)(pageBase + 2)) + 1; + else + data = 0; + + FlashStatus = FLASH_ErasePage(pageBase); + if (FlashStatus == FLASH_COMPLETE) + FlashStatus = FLASH_ProgramHalfWord(pageBase + 2, data); + + return FlashStatus; +} + +/** + * @brief Check page for blank and erase it + * @param page base address + * @retval Success or error + * - Flash error code: on write Flash error + * - EEPROM_BAD_FLASH: page not empty after erase + * - EEPROM_OK: page blank + */ +uint16 EEPROMClass::EE_CheckErasePage(uint32 pageBase, uint16 status) +{ + uint16 FlashStatus; + if (EE_CheckPage(pageBase, status) != EEPROM_OK) + { + FlashStatus = EE_ErasePage(pageBase); + if (FlashStatus != FLASH_COMPLETE) + return FlashStatus; + return EE_CheckPage(pageBase, status); + } + return EEPROM_OK; +} + +/** + * @brief Find valid Page for write or read operation + * @param Page0: Page0 base address + * Page1: Page1 base address + * @retval Valid page address (PAGE0 or PAGE1) or NULL in case of no valid page was found + */ +uint32 EEPROMClass::EE_FindValidPage(void) +{ + uint16 status0 = (*(__io uint16*)PageBase0); // Get Page0 actual status + uint16 status1 = (*(__io uint16*)PageBase1); // Get Page1 actual status + + if (status0 == EEPROM_VALID_PAGE && status1 == EEPROM_ERASED) + return PageBase0; + if (status1 == EEPROM_VALID_PAGE && status0 == EEPROM_ERASED) + return PageBase1; + + return 0; +} + +/** + * @brief Calculate unique variables in EEPROM + * @param start: address of first slot to check (page + 4) + * @param end: page end address + * @param address: 16 bit virtual address of the variable to excluse (or 0XFFFF) + * @retval count of variables + */ +uint16 EEPROMClass::EE_GetVariablesCount(uint32 pageBase, uint16 skipAddress) +{ + uint16 varAddress, nextAddress; + uint32 idx; + uint32 pageEnd = pageBase + (uint32)PageSize; + uint16 count = 0; + + for (pageBase += 6; pageBase < pageEnd; pageBase += 4) + { + varAddress = (*(__io uint16*)pageBase); + if (varAddress == 0xFFFF || varAddress == skipAddress) + continue; + + count++; + for(idx = pageBase + 4; idx < pageEnd; idx += 4) + { + nextAddress = (*(__io uint16*)idx); + if (nextAddress == varAddress) + { + count--; + break; + } + } + } + return count; +} + +/** + * @brief Transfers last updated variables data from the full Page to an empty one. + * @param newPage: new page base address + * @param oldPage: old page base address + * @param SkipAddress: 16 bit virtual address of the variable (or 0xFFFF) + * @retval Success or error status: + * - FLASH_COMPLETE: on success + * - EEPROM_OUT_SIZE: if valid new page is full + * - Flash error code: on write Flash error + */ +uint16 EEPROMClass::EE_PageTransfer(uint32 newPage, uint32 oldPage, uint16 SkipAddress) +{ + uint32 oldEnd, newEnd; + uint32 oldIdx, newIdx, idx; + uint16 address, data, found; + FLASH_Status FlashStatus; + + // Transfer process: transfer variables from old to the new active page + newEnd = newPage + ((uint32)PageSize); + + // Find first free element in new page + for (newIdx = newPage + 4; newIdx < newEnd; newIdx += 4) + if ((*(__io uint32*)newIdx) == 0xFFFFFFFF) // Verify if element + break; // contents are 0xFFFFFFFF + if (newIdx >= newEnd) + return EEPROM_OUT_SIZE; + + oldEnd = oldPage + 4; + oldIdx = oldPage + (uint32)(PageSize - 2); + + for (; oldIdx > oldEnd; oldIdx -= 4) + { + address = *(__io uint16*)oldIdx; + if (address == 0xFFFF || address == SkipAddress) + continue; // it's means that power off after write data + + found = 0; + for (idx = newPage + 6; idx < newIdx; idx += 4) + if ((*(__io uint16*)(idx)) == address) + { + found = 1; + break; + } + + if (found) + continue; + + if (newIdx < newEnd) + { + data = (*(__io uint16*)(oldIdx - 2)); + + FlashStatus = FLASH_ProgramHalfWord(newIdx, data); + if (FlashStatus != FLASH_COMPLETE) + return FlashStatus; + + FlashStatus = FLASH_ProgramHalfWord(newIdx + 2, address); + if (FlashStatus != FLASH_COMPLETE) + return FlashStatus; + + newIdx += 4; + } + else + return EEPROM_OUT_SIZE; + } + + // Erase the old Page: Set old Page status to EEPROM_EEPROM_ERASED status + data = EE_CheckErasePage(oldPage, EEPROM_ERASED); + if (data != EEPROM_OK) + return data; + + // Set new Page status + FlashStatus = FLASH_ProgramHalfWord(newPage, EEPROM_VALID_PAGE); + if (FlashStatus != FLASH_COMPLETE) + return FlashStatus; + + return EEPROM_OK; +} + +/** + * @brief Verify if active page is full and Writes variable in EEPROM. + * @param Address: 16 bit virtual address of the variable + * @param Data: 16 bit data to be written as variable value + * @retval Success or error status: + * - FLASH_COMPLETE: on success + * - EEPROM_PAGE_FULL: if valid page is full (need page transfer) + * - EEPROM_NO_VALID_PAGE: if no valid page was found + * - EEPROM_OUT_SIZE: if EEPROM size exceeded + * - Flash error code: on write Flash error + */ +uint16 EEPROMClass::EE_VerifyPageFullWriteVariable(uint16 Address, uint16 Data) +{ + FLASH_Status FlashStatus; + uint32 idx, pageBase, pageEnd, newPage; + uint16 count; + + // Get valid Page for write operation + pageBase = EE_FindValidPage(); + if (pageBase == 0) + return EEPROM_NO_VALID_PAGE; + + // Get the valid Page end Address + pageEnd = pageBase + PageSize; // Set end of page + + for (idx = pageEnd - 2; idx > pageBase; idx -= 4) + { + if ((*(__io uint16*)idx) == Address) // Find last value for address + { + count = (*(__io uint16*)(idx - 2)); // Read last data + if (count == Data) + return EEPROM_OK; + if (count == 0xFFFF) + { + FlashStatus = FLASH_ProgramHalfWord(idx - 2, Data); // Set variable data + if (FlashStatus == FLASH_COMPLETE) + return EEPROM_OK; + } + break; + } + } + + // Check each active page address starting from begining + for (idx = pageBase + 4; idx < pageEnd; idx += 4) + if ((*(__io uint32*)idx) == 0xFFFFFFFF) // Verify if element + { // contents are 0xFFFFFFFF + FlashStatus = FLASH_ProgramHalfWord(idx, Data); // Set variable data + if (FlashStatus != FLASH_COMPLETE) + return FlashStatus; + FlashStatus = FLASH_ProgramHalfWord(idx + 2, Address); // Set variable virtual address + if (FlashStatus != FLASH_COMPLETE) + return FlashStatus; + return EEPROM_OK; + } + + // Empty slot not found, need page transfer + // Calculate unique variables in page + count = EE_GetVariablesCount(pageBase, Address) + 1; + if (count >= (PageSize / 4 - 1)) + return EEPROM_OUT_SIZE; + + if (pageBase == PageBase1) + newPage = PageBase0; // New page address where variable will be moved to + else + newPage = PageBase1; + + // Set the new Page status to RECEIVE_DATA status + FlashStatus = FLASH_ProgramHalfWord(newPage, EEPROM_RECEIVE_DATA); + if (FlashStatus != FLASH_COMPLETE) + return FlashStatus; + + // Write the variable passed as parameter in the new active page + FlashStatus = FLASH_ProgramHalfWord(newPage + 4, Data); + if (FlashStatus != FLASH_COMPLETE) + return FlashStatus; + + FlashStatus = FLASH_ProgramHalfWord(newPage + 6, Address); + if (FlashStatus != FLASH_COMPLETE) + return FlashStatus; + + return EE_PageTransfer(newPage, pageBase, Address); +} + +EEPROMClass::EEPROMClass(void) +{ + PageBase0 = EEPROM_PAGE0_BASE; + PageBase1 = EEPROM_PAGE1_BASE; + PageSize = EEPROM_PAGE_SIZE; + Status = EEPROM_NOT_INIT; +} + +uint16 EEPROMClass::init(uint32 pageBase0, uint32 pageBase1, uint32 pageSize) +{ + PageBase0 = pageBase0; + PageBase1 = pageBase1; + PageSize = pageSize; + return init(); +} + +uint16 EEPROMClass::init(void) +{ + uint16 status0, status1; + FLASH_Status FlashStatus; + + FLASH_Unlock(); + Status = EEPROM_NO_VALID_PAGE; + + status0 = (*(__io uint16 *)PageBase0); + status1 = (*(__io uint16 *)PageBase1); + + switch (status0) + { +/* + Page0 Page1 + ----- ----- + EEPROM_ERASED EEPROM_VALID_PAGE Page1 valid, Page0 erased + EEPROM_RECEIVE_DATA Page1 need set to valid, Page0 erased + EEPROM_ERASED make EE_Format + any Error: EEPROM_NO_VALID_PAGE +*/ + case EEPROM_ERASED: + if (status1 == EEPROM_VALID_PAGE) // Page0 erased, Page1 valid + Status = EE_CheckErasePage(PageBase0, EEPROM_ERASED); + else if (status1 == EEPROM_RECEIVE_DATA) // Page0 erased, Page1 receive + { + FlashStatus = FLASH_ProgramHalfWord(PageBase1, EEPROM_VALID_PAGE); + if (FlashStatus != FLASH_COMPLETE) + Status = FlashStatus; + else + Status = EE_CheckErasePage(PageBase0, EEPROM_ERASED); + } + else if (status1 == EEPROM_ERASED) // Both in erased state so format EEPROM + Status = format(); + break; +/* + Page0 Page1 + ----- ----- + EEPROM_RECEIVE_DATA EEPROM_VALID_PAGE Transfer Page1 to Page0 + EEPROM_ERASED Page0 need set to valid, Page1 erased + any EEPROM_NO_VALID_PAGE +*/ + case EEPROM_RECEIVE_DATA: + if (status1 == EEPROM_VALID_PAGE) // Page0 receive, Page1 valid + Status = EE_PageTransfer(PageBase0, PageBase1, 0xFFFF); + else if (status1 == EEPROM_ERASED) // Page0 receive, Page1 erased + { + Status = EE_CheckErasePage(PageBase1, EEPROM_ERASED); + if (Status == EEPROM_OK) + { + FlashStatus = FLASH_ProgramHalfWord(PageBase0, EEPROM_VALID_PAGE); + if (FlashStatus != FLASH_COMPLETE) + Status = FlashStatus; + else + Status = EEPROM_OK; + } + } + break; +/* + Page0 Page1 + ----- ----- + EEPROM_VALID_PAGE EEPROM_VALID_PAGE Error: EEPROM_NO_VALID_PAGE + EEPROM_RECEIVE_DATA Transfer Page0 to Page1 + any Page0 valid, Page1 erased +*/ + case EEPROM_VALID_PAGE: + if (status1 == EEPROM_VALID_PAGE) // Both pages valid + Status = EEPROM_NO_VALID_PAGE; + else if (status1 == EEPROM_RECEIVE_DATA) + Status = EE_PageTransfer(PageBase1, PageBase0, 0xFFFF); + else + Status = EE_CheckErasePage(PageBase1, EEPROM_ERASED); + break; +/* + Page0 Page1 + ----- ----- + any EEPROM_VALID_PAGE Page1 valid, Page0 erased + EEPROM_RECEIVE_DATA Page1 valid, Page0 erased + any EEPROM_NO_VALID_PAGE +*/ + default: + if (status1 == EEPROM_VALID_PAGE) + Status = EE_CheckErasePage(PageBase0, EEPROM_ERASED); // Check/Erase Page0 + else if (status1 == EEPROM_RECEIVE_DATA) + { + FlashStatus = FLASH_ProgramHalfWord(PageBase1, EEPROM_VALID_PAGE); + if (FlashStatus != FLASH_COMPLETE) + Status = FlashStatus; + else + Status = EE_CheckErasePage(PageBase0, EEPROM_ERASED); + } + break; + } + return Status; +} + +/** + * @brief Erases PAGE0 and PAGE1 and writes EEPROM_VALID_PAGE / 0 header to PAGE0 + * @param PAGE0 and PAGE1 base addresses + * @retval Status of the last operation (Flash write or erase) done during EEPROM formating + */ +uint16 EEPROMClass::format(void) +{ + uint16 status; + FLASH_Status FlashStatus; + + FLASH_Unlock(); + + // Erase Page0 + status = EE_CheckErasePage(PageBase0, EEPROM_VALID_PAGE); + if (status != EEPROM_OK) + return status; + if ((*(__io uint16*)PageBase0) == EEPROM_ERASED) + { + // Set Page0 as valid page: Write VALID_PAGE at Page0 base address + FlashStatus = FLASH_ProgramHalfWord(PageBase0, EEPROM_VALID_PAGE); + if (FlashStatus != FLASH_COMPLETE) + return FlashStatus; + } + // Erase Page1 + return EE_CheckErasePage(PageBase1, EEPROM_ERASED); +} + +/** + * @brief Returns the erase counter for current page + * @param Data: Global variable contains the read variable value + * @retval Success or error status: + * - EEPROM_OK: if erases counter return. + * - EEPROM_NO_VALID_PAGE: if no valid page was found. + */ +uint16 EEPROMClass::erases(uint16 *Erases) +{ + uint32 pageBase; + if (Status != EEPROM_OK) + if (init() != EEPROM_OK) + return Status; + + // Get active Page for read operation + pageBase = EE_FindValidPage(); + if (pageBase == 0) + return EEPROM_NO_VALID_PAGE; + + *Erases = (*(__io uint16*)pageBase+2); + return EEPROM_OK; +} + +/** + * @brief Returns the last stored variable data, if found, + * which correspond to the passed virtual address + * @param Address: Variable virtual address + * @retval Data for variable or EEPROM_DEFAULT_DATA, if any errors + */ +uint16 EEPROMClass::read (uint16 Address) +{ + uint16 data; + read(Address, &data); + return data; +} + +/** + * @brief Returns the last stored variable data, if found, + * which correspond to the passed virtual address + * @param Address: Variable virtual address + * @param Data: Pointer to data variable + * @retval Success or error status: + * - EEPROM_OK: if variable was found + * - EEPROM_BAD_ADDRESS: if the variable was not found + * - EEPROM_NO_VALID_PAGE: if no valid page was found. + */ +uint16 EEPROMClass::read(uint16 Address, uint16 *Data) +{ + uint32 pageBase, pageEnd; + + // Set default data (empty EEPROM) + *Data = EEPROM_DEFAULT_DATA; + + if (Status == EEPROM_NOT_INIT) + if (init() != EEPROM_OK) + return Status; + + // Get active Page for read operation + pageBase = EE_FindValidPage(); + if (pageBase == 0) + return EEPROM_NO_VALID_PAGE; + + // Get the valid Page end Address + pageEnd = pageBase + ((uint32)(PageSize - 2)); + + // Check each active page address starting from end + for (pageBase += 6; pageEnd >= pageBase; pageEnd -= 4) + if ((*(__io uint16*)pageEnd) == Address) // Compare the read address with the virtual address + { + *Data = (*(__io uint16*)(pageEnd - 2)); // Get content of Address-2 which is variable value + return EEPROM_OK; + } + + // Return ReadStatus value: (0: variable exist, 1: variable doesn't exist) + return EEPROM_BAD_ADDRESS; +} + +/** + * @brief Writes/upadtes variable data in EEPROM. + * @param VirtAddress: Variable virtual address + * @param Data: 16 bit data to be written + * @retval Success or error status: + * - FLASH_COMPLETE: on success + * - EEPROM_BAD_ADDRESS: if address = 0xFFFF + * - EEPROM_PAGE_FULL: if valid page is full + * - EEPROM_NO_VALID_PAGE: if no valid page was found + * - EEPROM_OUT_SIZE: if no empty EEPROM variables + * - Flash error code: on write Flash error + */ +uint16 EEPROMClass::write(uint16 Address, uint16 Data) +{ + if (Status == EEPROM_NOT_INIT) + if (init() != EEPROM_OK) + return Status; + + if (Address == 0xFFFF) + return EEPROM_BAD_ADDRESS; + + // Write the variable virtual address and value in the EEPROM + uint16 status = EE_VerifyPageFullWriteVariable(Address, Data); + return status; +} + +/** + * @brief Writes/upadtes variable data in EEPROM. + The value is written only if differs from the one already saved at the same address. + * @param VirtAddress: Variable virtual address + * @param Data: 16 bit data to be written + * @retval Success or error status: + * - EEPROM_SAME_VALUE: If new Data matches existing EEPROM Data + * - FLASH_COMPLETE: on success + * - EEPROM_BAD_ADDRESS: if address = 0xFFFF + * - EEPROM_PAGE_FULL: if valid page is full + * - EEPROM_NO_VALID_PAGE: if no valid page was found + * - EEPROM_OUT_SIZE: if no empty EEPROM variables + * - Flash error code: on write Flash error + */ +uint16 EEPROMClass::update(uint16 Address, uint16 Data) +{ + if (read(Address) == Data) + return EEPROM_SAME_VALUE; + else + return write(Address, Data); +} + +/** + * @brief Return number of variable + * @retval Number of variables + */ +uint16 EEPROMClass::count(uint16 *Count) +{ + if (Status == EEPROM_NOT_INIT) + if (init() != EEPROM_OK) + return Status; + + // Get valid Page for write operation + uint32 pageBase = EE_FindValidPage(); + if (pageBase == 0) + return EEPROM_NO_VALID_PAGE; // No valid page, return max. numbers + + *Count = EE_GetVariablesCount(pageBase, 0xFFFF); + return EEPROM_OK; +} + +uint16 EEPROMClass::maxcount(void) +{ + return ((PageSize / 4)-1); +} + +EEPROMClass EEPROM; diff --git a/BootLoaders/Boards/stm32/libraries/EEPROM/EEPROM.h b/BootLoaders/Boards/stm32/libraries/EEPROM/EEPROM.h new file mode 100644 index 0000000..2957476 --- /dev/null +++ b/BootLoaders/Boards/stm32/libraries/EEPROM/EEPROM.h @@ -0,0 +1,93 @@ +#ifndef __EEPROM_H +#define __EEPROM_H + +#include +#include "flash_stm32.h" + +// HACK ALERT. This definition may not match your processor +// To Do. Work out correct value for EEPROM_PAGE_SIZE on the STM32F103CT6 etc +#define MCU_STM32F103RB + +#ifndef EEPROM_PAGE_SIZE + #if defined (MCU_STM32F103RB) + #define EEPROM_PAGE_SIZE (uint16)0x400 /* Page size = 1KByte */ + #elif defined (MCU_STM32F103ZE) || defined (MCU_STM32F103RE) || defined (MCU_STM32F103RD) + #define EEPROM_PAGE_SIZE (uint16)0x800 /* Page size = 2KByte */ + #else + #error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)." + #endif +#endif + +#ifndef EEPROM_START_ADDRESS + #if defined (MCU_STM32F103RB) + #define EEPROM_START_ADDRESS ((uint32)(0x8000000 + 128 * 1024 - 2 * EEPROM_PAGE_SIZE)) + #elif defined (MCU_STM32F103ZE) || defined (MCU_STM32F103RE) + #define EEPROM_START_ADDRESS ((uint32)(0x8000000 + 512 * 1024 - 2 * EEPROM_PAGE_SIZE)) + #elif defined (MCU_STM32F103RD) + #define EEPROM_START_ADDRESS ((uint32)(0x8000000 + 384 * 1024 - 2 * EEPROM_PAGE_SIZE)) + #else + #error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)." + #endif +#endif + +/* Pages 0 and 1 base and end addresses */ +#define EEPROM_PAGE0_BASE ((uint32)(EEPROM_START_ADDRESS + 0x000)) +#define EEPROM_PAGE1_BASE ((uint32)(EEPROM_START_ADDRESS + EEPROM_PAGE_SIZE)) + +/* Page status definitions */ +#define EEPROM_ERASED ((uint16)0xFFFF) /* PAGE is empty */ +#define EEPROM_RECEIVE_DATA ((uint16)0xEEEE) /* PAGE is marked to receive data */ +#define EEPROM_VALID_PAGE ((uint16)0x0000) /* PAGE containing valid data */ + +/* Page full define */ +enum : uint16 + { + EEPROM_OK = ((uint16)0x0000), + EEPROM_OUT_SIZE = ((uint16)0x0081), + EEPROM_BAD_ADDRESS = ((uint16)0x0082), + EEPROM_BAD_FLASH = ((uint16)0x0083), + EEPROM_NOT_INIT = ((uint16)0x0084), + EEPROM_SAME_VALUE = ((uint16)0x0085), + EEPROM_NO_VALID_PAGE = ((uint16)0x00AB) + }; + +#define EEPROM_DEFAULT_DATA 0xFFFF + + +class EEPROMClass +{ +public: + EEPROMClass(void); + + uint16 init(void); + uint16 init(uint32, uint32, uint32); + + uint16 format(void); + + uint16 erases(uint16 *); + uint16 read (uint16 address); + uint16 read (uint16 address, uint16 *data); + uint16 write(uint16 address, uint16 data); + uint16 update(uint16 address, uint16 data); + uint16 count(uint16 *); + uint16 maxcount(void); + + uint32 PageBase0; + uint32 PageBase1; + uint32 PageSize; + uint16 Status; +private: + FLASH_Status EE_ErasePage(uint32); + + uint16 EE_CheckPage(uint32, uint16); + uint16 EE_CheckErasePage(uint32, uint16); + uint16 EE_Format(void); + uint32 EE_FindValidPage(void); + uint16 EE_GetVariablesCount(uint32, uint16); + uint16 EE_PageTransfer(uint32, uint32, uint16); + uint16 EE_VerifyPageFullWriteVariable(uint16, uint16); +}; + +extern EEPROMClass EEPROM; + +#endif /* __EEPROM_H */ diff --git a/BootLoaders/Boards/stm32/libraries/EEPROM/examples/EEPROM_example/EEPROM_example.ino b/BootLoaders/Boards/stm32/libraries/EEPROM/examples/EEPROM_example/EEPROM_example.ino new file mode 100644 index 0000000..e3c8982 --- /dev/null +++ b/BootLoaders/Boards/stm32/libraries/EEPROM/examples/EEPROM_example/EEPROM_example.ino @@ -0,0 +1,167 @@ +#include + +int ledPin = 13; // LED connected to digital pin 13 +const char HELP_MSG[] = "Press :\r\n" \ + " 0 display configuration\r\n" \ + " 1 set configuration to 0x801F000 / 0x801F800 / 0x400 (RB MCU)\r\n" \ + " 2 set configuration to 0x801F000 / 0x801F800 / 0x800 (ZE/RE MCU)\r\n" \ + " 3 write/read variable\r\n" \ + " 4 increment address\r\n" \ + " 5 display pages top/bottom\r\n" \ + " 6 initialize EEPROM\r\n" \ + " 7 format EEPROM\r\n"; +uint16 DataWrite = 0; +uint16 AddressWrite = 0x10; + +void setup() +{ + // initialize the digital pin as an output: + pinMode(ledPin, OUTPUT); + Serial.begin(115200); + Serial.print(HELP_MSG); + +} + +void loop() +{ + uint16 Status; + uint16 Data; + + while (Serial.available()) + { + char cmd = (char)Serial.read(); + Serial.println(cmd); + if (cmd == '0') + { + DisplayConfig(); + } + else if (cmd == '1') + { + EEPROM.PageBase0 = 0x801F000; + EEPROM.PageBase1 = 0x801F800; + EEPROM.PageSize = 0x400; + DisplayConfig(); + } + else if (cmd == '2') + { + EEPROM.PageBase0 = 0x801F000; + EEPROM.PageBase1 = 0x801F800; + EEPROM.PageSize = 0x800; + DisplayConfig(); + } + else if (cmd == '3') + { + Status = EEPROM.write(AddressWrite, DataWrite); + Serial.print("EEPROM.write(0x"); + Serial.print(AddressWrite, HEX); + Serial.print(", 0x"); + Serial.print(DataWrite, HEX); + Serial.print(") : Status : "); + Serial.println(Status, HEX); + + Status = EEPROM.read(AddressWrite, &Data); + Serial.print("EEPROM.read(0x"); + Serial.print(AddressWrite, HEX); + Serial.print(", &..) = 0x"); + Serial.print(Data, HEX); + Serial.print(" : Status : "); + Serial.println(Status, HEX); + + ++DataWrite; + } + else if (cmd == '4') + { + ++AddressWrite; + } + else if (cmd == '5') + { + DisplayPages(0x20); + DisplayPagesEnd(0x20); + } + else if (cmd == '6') + { + Status = EEPROM.init(); + Serial.print("EEPROM.init() : "); + Serial.println(Status, HEX); + Serial.println(); + } + else if (cmd == '7') + { + Status = EEPROM.format(); + Serial.print("EEPROM.format() : "); + Serial.println(Status, HEX); + } + else + Serial.print(HELP_MSG); + } + digitalWrite(ledPin, HIGH); + delay(500); + digitalWrite(ledPin, LOW); + delay(500); +} + +void DisplayConfig(void) +{ + Serial.print ("EEPROM.PageBase0 : 0x"); + Serial.println(EEPROM.PageBase0, HEX); + Serial.print ("EEPROM.PageBase1 : 0x"); + Serial.println(EEPROM.PageBase1, HEX); + Serial.print ("EEPROM.PageSize : 0x"); + Serial.print (EEPROM.PageSize, HEX); + Serial.print (" ("); + Serial.print (EEPROM.PageSize, DEC); + Serial.println(")"); +} + +void DisplayHex(uint16 value) +{ + if (value <= 0xF) + Serial.print("000"); + else if (value <= 0xFF) + Serial.print("00"); + else if (value <= 0xFFF) + Serial.print("0"); + Serial.print(value, HEX); +} + +void DisplayPages(uint32 endIndex) +{ + Serial.println("Page 0 Top Page 1"); + + for (uint32 idx = 0; idx < endIndex; idx += 4) + { + Serial.print (EEPROM.PageBase0 + idx, HEX); + Serial.print (" : "); + DisplayHex(*(uint16*)(EEPROM.PageBase0 + idx)); + Serial.print (" "); + DisplayHex(*(uint16*)(EEPROM.PageBase0 + idx + 2)); + Serial.print (" "); + Serial.print (EEPROM.PageBase1 + idx, HEX); + Serial.print (" : "); + DisplayHex(*(uint16*)(EEPROM.PageBase1 + idx)); + Serial.print (" "); + DisplayHex(*(uint16*)(EEPROM.PageBase1 + idx + 2)); + Serial.println(); + } +} + +void DisplayPagesEnd(uint32 endIndex) +{ + Serial.println("Page 0 Bottom Page 1"); + + for (uint32 idx = EEPROM.PageSize - endIndex; idx < EEPROM.PageSize; idx += 4) + { + Serial.print (EEPROM.PageBase0 + idx, HEX); + Serial.print (" : "); + DisplayHex(*(uint16*)(EEPROM.PageBase0 + idx)); + Serial.print (" "); + DisplayHex(*(uint16*)(EEPROM.PageBase0 + idx + 2)); + Serial.print (" "); + Serial.print (EEPROM.PageBase1 + idx, HEX); + Serial.print (" : "); + DisplayHex(*(uint16*)(EEPROM.PageBase1 + idx)); + Serial.print (" "); + DisplayHex(*(uint16*)(EEPROM.PageBase1 + idx + 2)); + Serial.println(); + } +} \ No newline at end of file diff --git a/BootLoaders/Boards/stm32/libraries/EEPROM/flash_stm32.c b/BootLoaders/Boards/stm32/libraries/EEPROM/flash_stm32.c new file mode 100644 index 0000000..364e64e --- /dev/null +++ b/BootLoaders/Boards/stm32/libraries/EEPROM/flash_stm32.c @@ -0,0 +1,160 @@ +//#include "libmaple.h" +#include "libmaple/util.h" +#include "libmaple/flash.h" +#include "flash_stm32.h" + +#define FLASH_KEY1 ((uint32)0x45670123) +#define FLASH_KEY2 ((uint32)0xCDEF89AB) + +/* Delay definition */ +#define EraseTimeout ((uint32)0x00000FFF) +#define ProgramTimeout ((uint32)0x0000001F) + +/** + * @brief Inserts a time delay. + * @param None + * @retval None + */ +static void delay(void) +{ + __io uint32 i = 0; + for(i = 0xFF; i != 0; i--) { } +} + +/** + * @brief Returns the FLASH Status. + * @param None + * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG, + * FLASH_ERROR_WRP or FLASH_COMPLETE + */ +FLASH_Status FLASH_GetStatus(void) +{ + if ((FLASH_BASE->SR & FLASH_SR_BSY) == FLASH_SR_BSY) + return FLASH_BUSY; + + if ((FLASH_BASE->SR & FLASH_SR_PGERR) != 0) + return FLASH_ERROR_PG; + + if ((FLASH_BASE->SR & FLASH_SR_WRPRTERR) != 0 ) + return FLASH_ERROR_WRP; + + if ((FLASH_BASE->SR & FLASH_OBR_OPTERR) != 0 ) + return FLASH_ERROR_OPT; + + return FLASH_COMPLETE; +} + +/** + * @brief Waits for a Flash operation to complete or a TIMEOUT to occur. + * @param Timeout: FLASH progamming Timeout + * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG, + * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. + */ +FLASH_Status FLASH_WaitForLastOperation(uint32 Timeout) +{ + FLASH_Status status; + + /* Check for the Flash Status */ + status = FLASH_GetStatus(); + /* Wait for a Flash operation to complete or a TIMEOUT to occur */ + while ((status == FLASH_BUSY) && (Timeout != 0x00)) + { + delay(); + status = FLASH_GetStatus(); + Timeout--; + } + if (Timeout == 0) + status = FLASH_TIMEOUT; + /* Return the operation status */ + return status; +} + +/** + * @brief Erases a specified FLASH page. + * @param Page_Address: The page address to be erased. + * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG, + * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. + */ +FLASH_Status FLASH_ErasePage(uint32 Page_Address) +{ + FLASH_Status status = FLASH_COMPLETE; + /* Check the parameters */ + ASSERT(IS_FLASH_ADDRESS(Page_Address)); + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(EraseTimeout); + + if(status == FLASH_COMPLETE) + { + /* if the previous operation is completed, proceed to erase the page */ + FLASH_BASE->CR |= FLASH_CR_PER; + FLASH_BASE->AR = Page_Address; + FLASH_BASE->CR |= FLASH_CR_STRT; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(EraseTimeout); + if(status != FLASH_TIMEOUT) + { + /* if the erase operation is completed, disable the PER Bit */ + FLASH_BASE->CR &= ~FLASH_CR_PER; + } + FLASH_BASE->SR = (FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPRTERR); + } + /* Return the Erase Status */ + return status; +} + +/** + * @brief Programs a half word at a specified address. + * @param Address: specifies the address to be programmed. + * @param Data: specifies the data to be programmed. + * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG, + * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. + */ +FLASH_Status FLASH_ProgramHalfWord(uint32 Address, uint16 Data) +{ + FLASH_Status status = FLASH_BAD_ADDRESS; + + if (IS_FLASH_ADDRESS(Address)) + { + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(ProgramTimeout); + if(status == FLASH_COMPLETE) + { + /* if the previous operation is completed, proceed to program the new data */ + FLASH_BASE->CR |= FLASH_CR_PG; + *(__io uint16*)Address = Data; + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(ProgramTimeout); + if(status != FLASH_TIMEOUT) + { + /* if the program operation is completed, disable the PG Bit */ + FLASH_BASE->CR &= ~FLASH_CR_PG; + } + FLASH_BASE->SR = (FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPRTERR); + } + } + return status; +} + +/** + * @brief Unlocks the FLASH Program Erase Controller. + * @param None + * @retval None + */ +void FLASH_Unlock(void) +{ + /* Authorize the FPEC Access */ + FLASH_BASE->KEYR = FLASH_KEY1; + FLASH_BASE->KEYR = FLASH_KEY2; +} + +/** + * @brief Locks the FLASH Program Erase Controller. + * @param None + * @retval None + */ +void FLASH_Lock(void) +{ + /* Set the Lock Bit to lock the FPEC and the FCR */ + FLASH_BASE->CR |= FLASH_CR_LOCK; +} diff --git a/BootLoaders/Boards/stm32/libraries/EEPROM/flash_stm32.h b/BootLoaders/Boards/stm32/libraries/EEPROM/flash_stm32.h new file mode 100644 index 0000000..4aa54b9 --- /dev/null +++ b/BootLoaders/Boards/stm32/libraries/EEPROM/flash_stm32.h @@ -0,0 +1,32 @@ +#ifndef __FLASH_STM32_H +#define __FLASH_STM32_H + +#ifdef __cplusplus + extern "C" { +#endif + +typedef enum + { + FLASH_BUSY = 1, + FLASH_ERROR_PG, + FLASH_ERROR_WRP, + FLASH_ERROR_OPT, + FLASH_COMPLETE, + FLASH_TIMEOUT, + FLASH_BAD_ADDRESS + } FLASH_Status; + +#define IS_FLASH_ADDRESS(ADDRESS) (((ADDRESS) >= 0x08000000) && ((ADDRESS) < 0x0807FFFF)) + +FLASH_Status FLASH_WaitForLastOperation(uint32 Timeout); +FLASH_Status FLASH_ErasePage(uint32 Page_Address); +FLASH_Status FLASH_ProgramHalfWord(uint32 Address, uint16 Data); + +void FLASH_Unlock(void); +void FLASH_Lock(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __FLASH_STM32_H */ diff --git a/BootLoaders/Boards/stm32/libraries/EEPROM/keywords.txt b/BootLoaders/Boards/stm32/libraries/EEPROM/keywords.txt new file mode 100644 index 0000000..ecf82c9 --- /dev/null +++ b/BootLoaders/Boards/stm32/libraries/EEPROM/keywords.txt @@ -0,0 +1,27 @@ +####################################### +# Syntax Coloring Map For EEPROM +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +EEPROM KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +init KEYWORD2 +format KEYWORD2 +erases KEYWORD2 +read KEYWORD2 +write KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### +PageBase0 +PageBase1 +PageSize +Status diff --git a/BootLoaders/Boards/stm32/libraries/SPI/examples/using_SPI_ports/using_SPI_ports.ino b/BootLoaders/Boards/stm32/libraries/SPI/examples/using_SPI_ports/using_SPI_ports.ino new file mode 100644 index 0000000..dfffc0d --- /dev/null +++ b/BootLoaders/Boards/stm32/libraries/SPI/examples/using_SPI_ports/using_SPI_ports.ino @@ -0,0 +1,76 @@ +/** + SPI_1 and SPI_2 port example code + + Description: + This sketch sends one byte with value 0x55 over the SPI_1 or SPI_2 port. + The received byte (the answer from the SPI slave device) is stored to the variable. + + The sketch as it is, works with SPI_1 port. For using the SPI_2 port, just + un-comment all the nessesary code lines marked with word. + + Created on 10 Jun 2015 by Vassilis Serasidis + email: avrsite@yahoo.gr + + Using the first SPI port (SPI_1) + SS <--> PA4 <--> BOARD_SPI1_NSS_PIN + SCK <--> PA5 <--> BOARD_SPI1_SCK_PIN + MISO <--> PA6 <--> BOARD_SPI1_MISO_PIN + MOSI <--> PA7 <--> BOARD_SPI1_MOSI_PIN + + Using the second SPI port (SPI_2) + SS <--> PB12 <--> BOARD_SPI2_NSS_PIN + SCK <--> PB13 <--> BOARD_SPI2_SCK_PIN + MISO <--> PB14 <--> BOARD_SPI2_MISO_PIN + MOSI <--> PB15 <--> BOARD_SPI2_MOSI_PIN +*/ + + +#include + +#define SPI1_NSS_PIN PA4 //SPI_1 Chip Select pin is PA4. You can change it to the STM32 pin you want. +#define SPI2_NSS_PIN PB12 //SPI_2 Chip Select pin is PB12. You can change it to the STM32 pin you want. + +SPIClass SPI_2(2); //Create an instance of the SPI Class called SPI_2 that uses the 2nd SPI Port +byte data; + +void setup() { + + // Setup SPI 1 + SPI.begin(); //Initialize the SPI_1 port. + SPI.setBitOrder(MSBFIRST); // Set the SPI_1 bit order + SPI.setDataMode(SPI_MODE0); //Set the SPI_2 data mode 0 + SPI.setClockDivider(SPI_CLOCK_DIV16); // Slow speed (72 / 16 = 4.5 MHz SPI_1 speed) + pinMode(SPI1_NSS_PIN, OUTPUT); + + // Setup SPI 2 + SPI_2.begin(); //Initialize the SPI_2 port. + SPI_2.setBitOrder(MSBFIRST); // Set the SPI_2 bit order + SPI_2.setDataMode(SPI_MODE0); //Set the SPI_2 data mode 0 + SPI_2.setClockDivider(SPI_CLOCK_DIV16); // Use a different speed to SPI 1 + pinMode(SPI2_NSS_PIN, OUTPUT); + + +} + +void loop() { + + sendSPI(); + sendSPI2(); + + delayMicroseconds(10); //Delay 10 micro seconds. +} + +void sendSPI() +{ + digitalWrite(SPI1_NSS_PIN, LOW); // manually take CSN low for SPI_1 transmission + data = SPI.transfer(0x55); //Send the HEX data 0x55 over SPI-1 port and store the received byte to the variable. + digitalWrite(SPI1_NSS_PIN, HIGH); // manually take CSN high between spi transmissions +} + + +void sendSPI2() +{ + digitalWrite(SPI2_NSS_PIN, LOW); // manually take CSN low for SPI_2 transmission + data = SPI_2.transfer(0x55); //Send the HEX data 0x55 over SPI-2 port and store the received byte to the variable. + digitalWrite(SPI2_NSS_PIN, HIGH); // manually take CSN high between spi transmissions +} \ No newline at end of file diff --git a/BootLoaders/Boards/stm32/libraries/SPI/keywords.txt b/BootLoaders/Boards/stm32/libraries/SPI/keywords.txt new file mode 100644 index 0000000..47738f9 --- /dev/null +++ b/BootLoaders/Boards/stm32/libraries/SPI/keywords.txt @@ -0,0 +1,31 @@ +####################################### +# Syntax Coloring Map SPI +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +SPI KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### +begin KEYWORD2 +end KEYWORD2 +transfer KEYWORD2 +#setBitOrder KEYWORD2 +setDataMode KEYWORD2 +setClockDivider KEYWORD2 + + +####################################### +# Constants (LITERAL1) +####################################### +SPI_MODE0 LITERAL1 +SPI_MODE1 LITERAL1 +SPI_MODE2 LITERAL1 +SPI_MODE3 LITERAL1 + +SPI_CONTINUE LITERAL1 +SPI_LAST LITERAL1 diff --git a/BootLoaders/Boards/stm32/libraries/SPI/library.properties b/BootLoaders/Boards/stm32/libraries/SPI/library.properties new file mode 100644 index 0000000..7b5a6aa --- /dev/null +++ b/BootLoaders/Boards/stm32/libraries/SPI/library.properties @@ -0,0 +1,10 @@ +name=SPI +version=1.0 +author=Roger Clark +email= +sentence=Serial Peripheral Interface +paragraph=SPI for STM32F1 +url= +architectures=STM32F1 +maintainer= +category=Communication \ No newline at end of file diff --git a/BootLoaders/Boards/stm32/libraries/SPI/src/README.txt b/BootLoaders/Boards/stm32/libraries/SPI/src/README.txt new file mode 100644 index 0000000..e69de29 diff --git a/BootLoaders/Boards/stm32/libraries/SPI/src/SPI.cpp b/BootLoaders/Boards/stm32/libraries/SPI/src/SPI.cpp new file mode 100644 index 0000000..c07e2ea --- /dev/null +++ b/BootLoaders/Boards/stm32/libraries/SPI/src/SPI.cpp @@ -0,0 +1,776 @@ +/****************************************************************************** + * 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 "SPI.h" + + +#include +#include +#include + +#include "wirish.h" +#include "boards.h" + +//#include "HardwareSerial.h" +/** Time in ms for DMA receive timeout */ +#define DMA_TIMEOUT 100 + +#if CYCLES_PER_MICROSECOND != 72 +/* TODO [0.2.0?] something smarter than this */ +#warning "Unexpected clock speed; SPI frequency calculation will be incorrect" +#endif + +struct spi_pins { + uint8 nss; + uint8 sck; + uint8 miso; + uint8 mosi; +}; + +static const spi_pins* dev_to_spi_pins(spi_dev *dev); + +static void configure_gpios(spi_dev *dev, bool as_master); + +static spi_baud_rate determine_baud_rate(spi_dev *dev, uint32_t freq); + +#if (BOARD_NR_SPI >= 3) && !defined(STM32_HIGH_DENSITY) +#error "The SPI library is misconfigured: 3 SPI ports only available on high density STM32 devices" +#endif + +static const spi_pins board_spi_pins[] __FLASH__ = { +#if BOARD_NR_SPI >= 1 + {BOARD_SPI1_NSS_PIN, + BOARD_SPI1_SCK_PIN, + BOARD_SPI1_MISO_PIN, + BOARD_SPI1_MOSI_PIN}, +#endif +#if BOARD_NR_SPI >= 2 + {BOARD_SPI2_NSS_PIN, + BOARD_SPI2_SCK_PIN, + BOARD_SPI2_MISO_PIN, + BOARD_SPI2_MOSI_PIN}, +#endif +#if BOARD_NR_SPI >= 3 + {BOARD_SPI3_NSS_PIN, + BOARD_SPI3_SCK_PIN, + BOARD_SPI3_MISO_PIN, + BOARD_SPI3_MOSI_PIN}, +#endif +}; + + +/* + * Constructor + */ + +SPIClass::SPIClass(uint32 spi_num) +{ + _currentSetting=&_settings[spi_num-1];// SPI channels are called 1 2 and 3 but the array is zero indexed + + switch (spi_num) { +#if BOARD_NR_SPI >= 1 + case 1: + _currentSetting->spi_d = SPI1; + _spi1_this = (void*) this; + break; +#endif +#if BOARD_NR_SPI >= 2 + case 2: + _currentSetting->spi_d = SPI2; + _spi2_this = (void*) this; + break; +#endif +#if BOARD_NR_SPI >= 3 + case 3: + _currentSetting->spi_d = SPI3; + _spi3_this = (void*) this; + break; +#endif + default: + ASSERT(0); + } + + // Init things specific to each SPI device + // clock divider setup is a bit of hack, and needs to be improved at a later date. + _settings[0].spi_d = SPI1; + _settings[0].clockDivider = determine_baud_rate(_settings[0].spi_d, _settings[0].clock); + _settings[0].spiDmaDev = DMA1; + _settings[0].spiTxDmaChannel = DMA_CH3; + _settings[0].spiRxDmaChannel = DMA_CH2; + _settings[1].spi_d = SPI2; + _settings[1].clockDivider = determine_baud_rate(_settings[1].spi_d, _settings[1].clock); + _settings[1].spiDmaDev = DMA1; + _settings[1].spiTxDmaChannel = DMA_CH5; + _settings[1].spiRxDmaChannel = DMA_CH4; +#if BOARD_NR_SPI >= 3 + _settings[2].spi_d = SPI3; + _settings[2].clockDivider = determine_baud_rate(_settings[2].spi_d, _settings[2].clock); + _settings[2].spiDmaDev = DMA2; + _settings[2].spiTxDmaChannel = DMA_CH2; + _settings[2].spiRxDmaChannel = DMA_CH1; +#endif + + // added for DMA callbacks. + _currentSetting->state = SPI_STATE_IDLE; +} + +/* + * Set up/tear down + */ +void SPIClass::updateSettings(void) { + uint32 flags = ((_currentSetting->bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB) | _currentSetting->dataSize | SPI_SW_SLAVE | SPI_SOFT_SS); + spi_master_enable(_currentSetting->spi_d, (spi_baud_rate)_currentSetting->clockDivider, (spi_mode)_currentSetting->dataMode, flags); +} + +void SPIClass::begin(void) { + spi_init(_currentSetting->spi_d); + configure_gpios(_currentSetting->spi_d, 1); + updateSettings(); + // added for DMA callbacks. + _currentSetting->state = SPI_STATE_READY; +} + +void SPIClass::beginSlave(void) { + spi_init(_currentSetting->spi_d); + configure_gpios(_currentSetting->spi_d, 0); + uint32 flags = ((_currentSetting->bitOrder == MSBFIRST ? SPI_FRAME_MSB : SPI_FRAME_LSB) | _currentSetting->dataSize | SPI_RX_ONLY); + spi_slave_enable(_currentSetting->spi_d, (spi_mode)_currentSetting->dataMode, flags); + // added for DMA callbacks. + _currentSetting->state = SPI_STATE_READY; +} + +void SPIClass::end(void) { + if (!spi_is_enabled(_currentSetting->spi_d)) { + return; + } + + // Follows RM0008's sequence for disabling a SPI in master/slave + // full duplex mode. + while (spi_is_rx_nonempty(_currentSetting->spi_d)) { + // FIXME [0.1.0] remove this once you have an interrupt based driver + volatile uint16 rx __attribute__((unused)) = spi_rx_reg(_currentSetting->spi_d); + } + while (!spi_is_tx_empty(_currentSetting->spi_d)) + ; + while (spi_is_busy(_currentSetting->spi_d)) + ; + spi_peripheral_disable(_currentSetting->spi_d); + // added for DMA callbacks. + // Need to add unsetting the callbacks for the DMA channels. + _currentSetting->state = SPI_STATE_IDLE; +} + +/* Roger Clark added 3 functions */ +void SPIClass::setClockDivider(uint32_t clockDivider) +{ + _currentSetting->clockDivider = clockDivider; + uint32 cr1 = _currentSetting->spi_d->regs->CR1 & ~(SPI_CR1_BR); + _currentSetting->spi_d->regs->CR1 = cr1 | (clockDivider & SPI_CR1_BR); +} + +void SPIClass::setBitOrder(BitOrder bitOrder) +{ + _currentSetting->bitOrder = bitOrder; + uint32 cr1 = _currentSetting->spi_d->regs->CR1 & ~(SPI_CR1_LSBFIRST); + if ( bitOrder==LSBFIRST ) cr1 |= SPI_CR1_LSBFIRST; + _currentSetting->spi_d->regs->CR1 = cr1; +} + +/* Victor Perez. Added to test changing datasize from 8 to 16 bit modes on the fly. +* Input parameter should be SPI_CR1_DFF set to 0 or 1 on a 32bit word. +* +*/ +void SPIClass::setDataSize(uint32 datasize) +{ + _currentSetting->dataSize = datasize; + uint32 cr1 = _currentSetting->spi_d->regs->CR1 & ~(SPI_CR1_DFF); + uint8 en = spi_is_enabled(_currentSetting->spi_d); + spi_peripheral_disable(_currentSetting->spi_d); + _currentSetting->spi_d->regs->CR1 = cr1 | (datasize & SPI_CR1_DFF) | en; +} + +void SPIClass::setDataMode(uint8_t dataMode) +{ +/* Notes. As far as I can tell, the AVR numbers for dataMode appear to match the numbers required by the STM32 + +From the AVR doc http://www.atmel.com/images/doc2585.pdf section 2.4 + +SPI Mode CPOL CPHA Shift SCK-edge Capture SCK-edge +0 0 0 Falling Rising +1 0 1 Rising Falling +2 1 0 Rising Falling +3 1 1 Falling Rising + + +On the STM32 it appears to be + +bit 1 - CPOL : Clock polarity + (This bit should not be changed when communication is ongoing) + 0 : CLK to 0 when idle + 1 : CLK to 1 when idle + +bit 0 - CPHA : Clock phase + (This bit should not be changed when communication is ongoing) + 0 : The first clock transition is the first data capture edge + 1 : The second clock transition is the first data capture edge + +If someone finds this is not the case or sees a logic error with this let me know ;-) + */ + _currentSetting->dataMode = dataMode; + uint32 cr1 = _currentSetting->spi_d->regs->CR1 & ~(SPI_CR1_CPOL|SPI_CR1_CPHA); + _currentSetting->spi_d->regs->CR1 = cr1 | (dataMode & (SPI_CR1_CPOL|SPI_CR1_CPHA)); +} + +void SPIClass::beginTransaction(uint8_t pin, SPISettings settings) +{ + setBitOrder(settings.bitOrder); + setDataMode(settings.dataMode); + setDataSize(settings.dataSize); + setClockDivider(determine_baud_rate(_currentSetting->spi_d, settings.clock)); + begin(); +} + +void SPIClass::beginTransactionSlave(SPISettings settings) +{ + setBitOrder(settings.bitOrder); + setDataMode(settings.dataMode); + setDataSize(settings.dataSize); + beginSlave(); +} + +void SPIClass::endTransaction(void) +{ + //digitalWrite(_SSPin,HIGH); +#if false +// code from SAM core + uint8_t mode = interruptMode; + if (mode > 0) { + if (mode < 16) { + if (mode & 1) PIOA->PIO_IER = interruptMask[0]; + if (mode & 2) PIOB->PIO_IER = interruptMask[1]; + if (mode & 4) PIOC->PIO_IER = interruptMask[2]; + if (mode & 8) PIOD->PIO_IER = interruptMask[3]; + } else { + if (interruptSave) interrupts(); + } + } +#endif +} + + +/* + * I/O + */ + +uint16 SPIClass::read(void) +{ + while ( spi_is_rx_nonempty(_currentSetting->spi_d)==0 ) ; + return (uint16)spi_rx_reg(_currentSetting->spi_d); +} + +void SPIClass::read(uint8 *buf, uint32 len) +{ + if ( len == 0 ) return; + spi_rx_reg(_currentSetting->spi_d); // clear the RX buffer in case a byte is waiting on it. + spi_reg_map * regs = _currentSetting->spi_d->regs; + // start sequence: write byte 0 + regs->DR = 0x00FF; // write the first byte + // main loop + while ( (--len) ) { + while( !(regs->SR & SPI_SR_TXE) ); // wait for TXE flag + noInterrupts(); // go atomic level - avoid interrupts to surely get the previously received data + regs->DR = 0x00FF; // write the next data item to be transmitted into the SPI_DR register. This clears the TXE flag. + while ( !(regs->SR & SPI_SR_RXNE) ); // wait till data is available in the DR register + *buf++ = (uint8)(regs->DR); // read and store the received byte. This clears the RXNE flag. + interrupts(); // let systick do its job + } + // read remaining last byte + while ( !(regs->SR & SPI_SR_RXNE) ); // wait till data is available in the Rx register + *buf++ = (uint8)(regs->DR); // read and store the received byte +} + +void SPIClass::write(uint16 data) +{ + /* Added for 16bit data Victor Perez. Roger Clark + * Improved speed by just directly writing the single byte to the SPI data reg and wait for completion, + * by taking the Tx code from transfer(byte) + * This almost doubles the speed of this function. + */ + spi_tx_reg(_currentSetting->spi_d, data); // write the data to be transmitted into the SPI_DR register (this clears the TXE flag) + while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..." + while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." +} + +void SPIClass::write16(uint16 data) +{ + // Added by stevestrong: write two consecutive bytes in 8 bit mode (DFF=0) + spi_tx_reg(_currentSetting->spi_d, data>>8); // write high byte + while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // Wait until TXE=1 + spi_tx_reg(_currentSetting->spi_d, data); // write low byte + while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // Wait until TXE=1 + while (spi_is_busy(_currentSetting->spi_d) != 0); // wait until BSY=0 +} + +void SPIClass::write(uint16 data, uint32 n) +{ + // Added by stevstrong: Repeatedly send same data by the specified number of times + spi_reg_map * regs = _currentSetting->spi_d->regs; + while ( (n--)>0 ) { + regs->DR = data; // write the data to be transmitted into the SPI_DR register (this clears the TXE flag) + while ( (regs->SR & SPI_SR_TXE)==0 ) ; // wait till Tx empty + } + while ( (regs->SR & SPI_SR_BSY) != 0); // wait until BSY=0 before returning +} + +void SPIClass::write(const void *data, uint32 length) +{ + spi_dev * spi_d = _currentSetting->spi_d; + spi_tx(spi_d, data, length); // data can be array of bytes or words + while (spi_is_tx_empty(spi_d) == 0); // "5. Wait until TXE=1 ..." + while (spi_is_busy(spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." +} + +uint8 SPIClass::transfer(uint8 byte) const +{ + spi_dev * spi_d = _currentSetting->spi_d; + spi_rx_reg(spi_d); // read any previous data + spi_tx_reg(spi_d, byte); // Write the data item to be transmitted into the SPI_DR register + while (spi_is_tx_empty(spi_d) == 0); // "5. Wait until TXE=1 ..." + while (spi_is_busy(spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." + return (uint8)spi_rx_reg(spi_d); // "... and read the last received data." +} + +uint16_t SPIClass::transfer16(uint16_t data) const +{ + // Modified by stevestrong: write & read two consecutive bytes in 8 bit mode (DFF=0) + // This is more effective than two distinct byte transfers + spi_dev * spi_d = _currentSetting->spi_d; + spi_rx_reg(spi_d); // read any previous data + spi_tx_reg(spi_d, data>>8); // write high byte + while (spi_is_tx_empty(spi_d) == 0); // wait until TXE=1 + while (spi_is_busy(spi_d) != 0); // wait until BSY=0 + uint16_t ret = spi_rx_reg(spi_d)<<8; // read and shift high byte + spi_tx_reg(spi_d, data); // write low byte + while (spi_is_tx_empty(spi_d) == 0); // wait until TXE=1 + while (spi_is_busy(spi_d) != 0); // wait until BSY=0 + ret += spi_rx_reg(spi_d); // read low byte + return ret; +} + +/* Roger Clark and Victor Perez, 2015 +* Performs a DMA SPI transfer with at least a receive buffer. +* If a TX buffer is not provided, FF is sent over and over for the lenght of the transfer. +* On exit TX buffer is not modified, and RX buffer cotains the received data. +* Still in progress. +*/ +void SPIClass::dmaTransferSet(const void *transmitBuf, void *receiveBuf) { + dma_init(_currentSetting->spiDmaDev); + //spi_rx_dma_enable(_currentSetting->spi_d); + //spi_tx_dma_enable(_currentSetting->spi_d); + dma_xfer_size dma_bit_size = (_currentSetting->dataSize==DATA_SIZE_16BIT) ? DMA_SIZE_16BITS : DMA_SIZE_8BITS; + dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, &_currentSetting->spi_d->regs->DR, dma_bit_size, + receiveBuf, dma_bit_size, (DMA_MINC_MODE | DMA_TRNS_CMPLT ));// receive buffer DMA + if (!transmitBuf) { + transmitBuf = &ff; + dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &_currentSetting->spi_d->regs->DR, dma_bit_size, + (volatile void*)transmitBuf, dma_bit_size, (DMA_FROM_MEM));// Transmit FF repeatedly + } + else { + dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &_currentSetting->spi_d->regs->DR, dma_bit_size, + (volatile void*)transmitBuf, dma_bit_size, (DMA_MINC_MODE | DMA_FROM_MEM ));// Transmit buffer DMA + } + dma_set_priority(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, DMA_PRIORITY_LOW); + dma_set_priority(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, DMA_PRIORITY_VERY_HIGH); +} + +uint8 SPIClass::dmaTransferRepeat(uint16 length) { + if (length == 0) return 0; + if (spi_is_rx_nonempty(_currentSetting->spi_d) == 1) spi_rx_reg(_currentSetting->spi_d); + _currentSetting->state = SPI_STATE_TRANSFER; + dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, length); + dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, length); + dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel);// enable receive + dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);// enable transmit + spi_rx_dma_enable(_currentSetting->spi_d); + spi_tx_dma_enable(_currentSetting->spi_d); + if (_currentSetting->receiveCallback){ + return 0; + } + //uint32_t m = millis(); + uint8 b = 0; + uint32_t m = millis(); + while ((dma_get_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel) & DMA_ISR_TCIF1)==0) { + //Avoid interrupts and just loop waiting for the flag to be set. + if ((millis() - m) > DMA_TIMEOUT) { b = 2; break; } + } + + while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..." + while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." + spi_tx_dma_disable(_currentSetting->spi_d); + spi_rx_dma_disable(_currentSetting->spi_d); + dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); + dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel); + dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel); + dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); + _currentSetting->state = SPI_STATE_READY; + return b; +} + +/* Roger Clark and Victor Perez, 2015 +* Performs a DMA SPI transfer with at least a receive buffer. +* If a TX buffer is not provided, FF is sent over and over for the length of the transfer. +* On exit TX buffer is not modified, and RX buffer contains the received data. +* Still in progress. +*/ + +uint8 SPIClass::dmaTransfer(const void *transmitBuf, void *receiveBuf, uint16 length) { + dmaTransferSet(transmitBuf, receiveBuf); + return dmaTransferRepeat(length); +} + +/* Roger Clark and Victor Perez, 2015 +* Performs a DMA SPI send using a TX buffer. +* On exit TX buffer is not modified. +* Still in progress. +* 2016 - stevstrong - reworked to automatically detect bit size from SPI setting +*/ + +void SPIClass::dmaSendSet(const void * transmitBuf, bool minc) { + uint32 flags = ( (DMA_MINC_MODE*minc) | DMA_FROM_MEM | DMA_TRNS_CMPLT); + dma_init(_currentSetting->spiDmaDev); + dma_xfer_size dma_bit_size = (_currentSetting->dataSize==DATA_SIZE_16BIT) ? DMA_SIZE_16BITS : DMA_SIZE_8BITS; + dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &_currentSetting->spi_d->regs->DR, dma_bit_size, + (volatile void*)transmitBuf, dma_bit_size, flags);// Transmit buffer DMA + dma_set_priority(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, DMA_PRIORITY_LOW); +} + +uint8 SPIClass::dmaSendRepeat(uint16 length) { + if (length == 0) return 0; + dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); + dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, length); + _currentSetting->state = SPI_STATE_TRANSMIT; + dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);// enable transmit + spi_tx_dma_enable(_currentSetting->spi_d); + if (_currentSetting->transmitCallback) + { + return 0; + } + uint32_t m = millis(); + uint8 b = 0; + while ((dma_get_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel) & DMA_ISR_TCIF1)==0) { + //Avoid interrupts and just loop waiting for the flag to be set. + if ((millis() - m) > DMA_TIMEOUT) { b = 2; break; } + } + while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..." + while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." + spi_tx_dma_disable(_currentSetting->spi_d); + dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); + dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); + _currentSetting->state = SPI_STATE_READY; + return b; +} + +uint8 SPIClass::dmaSend(const void * transmitBuf, uint16 length, bool minc) { + dmaSendSet(transmitBuf, minc); + return dmaSendRepeat(length); +} + +uint8 SPIClass::dmaSendAsync(const void * transmitBuf, uint16 length, bool minc) { + uint8 b = 0; + + if (_currentSetting->state != SPI_STATE_READY) + { + + uint32_t m = millis(); + while ((dma_get_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel) & DMA_ISR_TCIF1)==0) {//Avoid interrupts and just loop waiting for the flag to be set. + //delayMicroseconds(10); + if ((millis() - m) > DMA_TIMEOUT) { b = 2; break; } + } + + while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..." + while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." + spi_tx_dma_disable(_currentSetting->spi_d); + dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); + _currentSetting->state = SPI_STATE_READY; + } + + if (length == 0) return 0; + uint32 flags = ( (DMA_MINC_MODE*minc) | DMA_FROM_MEM | DMA_TRNS_CMPLT); + + dma_init(_currentSetting->spiDmaDev); + // TX + dma_xfer_size dma_bit_size = (_currentSetting->dataSize==DATA_SIZE_16BIT) ? DMA_SIZE_16BITS : DMA_SIZE_8BITS; + dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &_currentSetting->spi_d->regs->DR, dma_bit_size, + (volatile void*)transmitBuf, dma_bit_size, flags);// Transmit buffer DMA + dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, length); + dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); + dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);// enable transmit + spi_tx_dma_enable(_currentSetting->spi_d); + + _currentSetting->state = SPI_STATE_TRANSMIT; + + return b; +} + + +/* + New functions added to manage callbacks. + Victor Perez 2017 +*/ + +void SPIClass::onReceive(void(*callback)(void)) { + _currentSetting->receiveCallback = callback; + if (callback){ + switch (_currentSetting->spi_d->clk_id) { + case RCC_SPI1: + dma_attach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, &SPIClass::_spi1EventCallback); + break; + case RCC_SPI2: + dma_attach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, &SPIClass::_spi2EventCallback); + break; + #if BOARD_NR_SPI >= 3 + case RCC_SPI3: + dma_attach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, &SPIClass::_spi3EventCallback); + break; + #endif + default: + ASSERT(0); + } + } + else { + dma_detach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel); + } +} + +void SPIClass::onTransmit(void(*callback)(void)) { + _currentSetting->transmitCallback = callback; + if (callback){ + switch (_currentSetting->spi_d->clk_id) { + case RCC_SPI1: + dma_attach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &SPIClass::_spi1EventCallback); + break; + case RCC_SPI2: + dma_attach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &SPIClass::_spi2EventCallback); + break; + #if BOARD_NR_SPI >= 3 + case RCC_SPI3: + dma_attach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &SPIClass::_spi3EventCallback); + break; + #endif + default: + ASSERT(0); + } + } + else { + dma_detach_interrupt(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); + } +} + +/* + TODO: check if better to first call the customer code, next disable the DMA requests. + Also see if we need to check whether callbacks are set or not, may be better to be checked during the initial setup and only set the callback to EventCallback if they are set. +*/ + +void SPIClass::EventCallback() { + while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..." + while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0" + switch (_currentSetting->state) { + case SPI_STATE_TRANSFER: + while (spi_is_rx_nonempty(_currentSetting->spi_d)); + _currentSetting->state = SPI_STATE_READY; + spi_tx_dma_disable(_currentSetting->spi_d); + spi_rx_dma_disable(_currentSetting->spi_d); + //dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); + //dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel); + + if (_currentSetting->receiveCallback) + { + _currentSetting->receiveCallback(); + } + break; + case SPI_STATE_TRANSMIT: + _currentSetting->state = SPI_STATE_READY; + spi_tx_dma_disable(_currentSetting->spi_d); + //dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); + if (_currentSetting->transmitCallback) + { + _currentSetting->transmitCallback(); + } + + break; + default: + // we shouldn't get here, so better to add an assert and fail. + return; + } +} + +void SPIClass::attachInterrupt(void) { + // Should be enableInterrupt() +} + +void SPIClass::detachInterrupt(void) { + // Should be disableInterrupt() +} + +/* + * Pin accessors + */ + +uint8 SPIClass::misoPin(void) { + return dev_to_spi_pins(_currentSetting->spi_d)->miso; +} + +uint8 SPIClass::mosiPin(void) { + return dev_to_spi_pins(_currentSetting->spi_d)->mosi; +} + +uint8 SPIClass::sckPin(void) { + return dev_to_spi_pins(_currentSetting->spi_d)->sck; +} + +uint8 SPIClass::nssPin(void) { + return dev_to_spi_pins(_currentSetting->spi_d)->nss; +} + +/* + * Deprecated functions + */ + +uint8 SPIClass::send(uint8 data) { + this->write(data); + return 1; +} + +uint8 SPIClass::send(uint8 *buf, uint32 len) { + this->write(buf, len); + return len; +} + +uint8 SPIClass::recv(void) { + return this->read(); +} + +/* + DMA call back functions, one per port. +*/ + +void SPIClass::_spi1EventCallback() +{ + reinterpret_cast(_spi1_this)->EventCallback(); +} + +void SPIClass::_spi2EventCallback() { + reinterpret_cast(_spi2_this)->EventCallback(); +} +#if BOARD_NR_SPI >= 3 +void SPIClass::_spi3EventCallback() { + reinterpret_cast(_spi3_this)->EventCallback(); +} +#endif +/* +* Auxiliary functions +*/ + +static const spi_pins* dev_to_spi_pins(spi_dev *dev) { + switch (dev->clk_id) { +#if BOARD_NR_SPI >= 1 + case RCC_SPI1: return board_spi_pins; +#endif +#if BOARD_NR_SPI >= 2 + case RCC_SPI2: return board_spi_pins + 1; +#endif +#if BOARD_NR_SPI >= 3 + case RCC_SPI3: return board_spi_pins + 2; +#endif + default: return NULL; + } +} + +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_config_gpios(dev, 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[8] __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, uint32_t freq) { + uint32_t clock = 0, i; + switch (rcc_dev_clk(dev->clk_id)) + { + case RCC_APB2: clock = STM32_PCLK2; break; // 72 Mhz + case RCC_APB1: clock = STM32_PCLK1; break; // 36 Mhz + } + clock /= 2; + i = 0; + while (i < 7 && freq < clock) { + clock /= 2; + i++; + } + return baud_rates[i]; +} + +SPIClass SPI(1); diff --git a/BootLoaders/Boards/stm32/libraries/SPI/src/SPI.h b/BootLoaders/Boards/stm32/libraries/SPI/src/SPI.h new file mode 100644 index 0000000..686d23d --- /dev/null +++ b/BootLoaders/Boards/stm32/libraries/SPI/src/SPI.h @@ -0,0 +1,430 @@ +/****************************************************************************** + * 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/include/wirish/HardwareSPI.h + * @brief High-level SPI interface + * + * This is a "bare essentials" polling driver for now. + */ + +/* TODO [0.1.0] Remove deprecated methods. */ + + + +#ifndef _SPI_H_INCLUDED +#define _SPI_H_INCLUDED + +#include +#include +#include + +#include +#include +#include + +// SPI_HAS_TRANSACTION means SPI has +// - beginTransaction() +// - endTransaction() +// - usingInterrupt() +// - SPISetting(clock, bitOrder, dataMode) +//#define SPI_HAS_TRANSACTION + +#define SPI_CLOCK_DIV2 SPI_BAUD_PCLK_DIV_2 +#define SPI_CLOCK_DIV4 SPI_BAUD_PCLK_DIV_4 +#define SPI_CLOCK_DIV8 SPI_BAUD_PCLK_DIV_8 +#define SPI_CLOCK_DIV16 SPI_BAUD_PCLK_DIV_16 +#define SPI_CLOCK_DIV32 SPI_BAUD_PCLK_DIV_32 +#define SPI_CLOCK_DIV64 SPI_BAUD_PCLK_DIV_64 +#define SPI_CLOCK_DIV128 SPI_BAUD_PCLK_DIV_128 +#define SPI_CLOCK_DIV256 SPI_BAUD_PCLK_DIV_256 + +/* + * Roger Clark. 20150106 + * Commented out redundant AVR defined + * +#define SPI_MODE_MASK 0x0C // CPOL = bit 3, CPHA = bit 2 on SPCR +#define SPI_CLOCK_MASK 0x03 // SPR1 = bit 1, SPR0 = bit 0 on SPCR +#define SPI_2XCLOCK_MASK 0x01 // SPI2X = bit 0 on SPSR + +// define SPI_AVR_EIMSK for AVR boards with external interrupt pins +#if defined(EIMSK) + #define SPI_AVR_EIMSK EIMSK +#elif defined(GICR) + #define SPI_AVR_EIMSK GICR +#elif defined(GIMSK) + #define SPI_AVR_EIMSK GIMSK +#endif +*/ + +#ifndef STM32_LSBFIRST +#define STM32_LSBFIRST 0 +#endif +#ifndef STM32_MSBFIRST +#define STM32_MSBFIRST 1 +#endif + +// PC13 or PA4 +#define BOARD_SPI_DEFAULT_SS PA4 +//#define BOARD_SPI_DEFAULT_SS PC13 + +#define SPI_MODE0 SPI_MODE_0 +#define SPI_MODE1 SPI_MODE_1 +#define SPI_MODE2 SPI_MODE_2 +#define SPI_MODE3 SPI_MODE_3 + +#define DATA_SIZE_8BIT SPI_CR1_DFF_8_BIT +#define DATA_SIZE_16BIT SPI_CR1_DFF_16_BIT + +typedef enum { + SPI_STATE_IDLE, + SPI_STATE_READY, + SPI_STATE_RECEIVE, + SPI_STATE_TRANSMIT, + SPI_STATE_TRANSFER + } spi_mode_t; +class SPISettings { +public: + SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) { + if (__builtin_constant_p(clock)) { + init_AlwaysInline(clock, bitOrder, dataMode, DATA_SIZE_8BIT); + } else { + init_MightInline(clock, bitOrder, dataMode, DATA_SIZE_8BIT); + } + } + SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode, uint32_t dataSize) { + if (__builtin_constant_p(clock)) { + init_AlwaysInline(clock, bitOrder, dataMode, dataSize); + } else { + init_MightInline(clock, bitOrder, dataMode, dataSize); + } + } + SPISettings(uint32_t clock) { + if (__builtin_constant_p(clock)) { + init_AlwaysInline(clock, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT); + } else { + init_MightInline(clock, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT); + } + } + SPISettings() { init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT); } +private: + void init_MightInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode, uint32_t dataSize) { + init_AlwaysInline(clock, bitOrder, dataMode, dataSize); + } + void init_AlwaysInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode, uint32_t dataSize) __attribute__((__always_inline__)) { + this->clock = clock; + this->bitOrder = bitOrder; + this->dataMode = dataMode; + this->dataSize = dataSize; + } + uint32_t clock; + uint32_t dataSize; + uint32_t clockDivider; + BitOrder bitOrder; + uint8_t dataMode; + uint8_t _SSPin; + volatile spi_mode_t state; + spi_dev *spi_d; + dma_channel spiRxDmaChannel, spiTxDmaChannel; + dma_dev* spiDmaDev; + void (*receiveCallback)(void) = NULL; + void (*transmitCallback)(void) = NULL; + + friend class SPIClass; +}; + + +/* + Should move this to within the class once tested out, just for tidyness +*/ +static uint8_t ff = 0XFF; +static void (*_spi1_this); +static void (*_spi2_this); +#if BOARD_NR_SPI >= 3 +static void (*_spi3_this); +#endif + +/** + * @brief Wirish SPI interface. + * + * This implementation uses software slave management, so the caller + * is responsible for controlling the slave select line. + */ +class SPIClass { +public: + + /** + * @param spiPortNumber Number of the SPI port to manage. + */ + SPIClass(uint32 spiPortNumber); + + /* + * Set up/tear down + */ + + /** + * @brief Equivalent to begin(SPI_1_125MHZ, MSBFIRST, 0). + */ + void begin(void); + + /** + * @brief Turn on a SPI port and set its GPIO pin modes for use as a slave. + * + * SPI port is enabled in full duplex mode, with software slave management. + * + * @param bitOrder Either LSBFIRST (little-endian) or MSBFIRST(big-endian) + * @param mode SPI mode to use + */ + void beginSlave(uint32 bitOrder, uint32 mode); + + /** + * @brief Equivalent to beginSlave(MSBFIRST, 0). + */ + void beginSlave(void); + + /** + * @brief Disables the SPI port, but leaves its GPIO pin modes unchanged. + */ + void end(void); + + void beginTransaction(SPISettings settings) { beginTransaction(BOARD_SPI_DEFAULT_SS, settings); } + void beginTransaction(uint8_t pin, SPISettings settings); + void endTransaction(void); + + void beginTransactionSlave(SPISettings settings); + + void setClockDivider(uint32_t clockDivider); + void setBitOrder(BitOrder bitOrder); + void setDataMode(uint8_t dataMode); + + // SPI Configuration methods + void attachInterrupt(void); + void detachInterrupt(void); + + /* Victor Perez. Added to change datasize from 8 to 16 bit modes on the fly. + * Input parameter should be SPI_CR1_DFF set to 0 or 1 on a 32bit word. + * Requires an added function spi_data_size on STM32F1 / cores / maple / libmaple / spi.c + */ + void setDataSize(uint32 ds); + + /* Victor Perez 2017. Added to set and clear callback functions for callback + * on DMA transfer completion. + * onReceive used to set the callback in case of dmaTransfer (tx/rx), once rx is completed + * onTransmit used to set the callback in case of dmaSend (tx only). That function + * will NOT be called in case of TX/RX + */ + void onReceive(void(*)(void)); + void onTransmit(void(*)(void)); + + /* + * I/O + */ + + /** + * @brief Return the next unread byte/word. + * + * If there is no unread byte/word waiting, this function will block + * until one is received. + */ + uint16 read(void); + + /** + * @brief Read length bytes, storing them into buffer. + * @param buffer Buffer to store received bytes into. + * @param length Number of bytes to store in buffer. This + * function will block until the desired number of + * bytes have been read. + */ + void read(uint8 *buffer, uint32 length); + + /** + * @brief Transmit one byte/word. + * @param data to transmit. + */ + void write(uint16 data); + void write16(uint16 data); // write 2 bytes in 8 bit mode (DFF=0) + + /** + * @brief Transmit one byte/word a specified number of times. + * @param data to transmit. + */ + void write(uint16 data, uint32 n); + + /** + * @brief Transmit multiple bytes/words. + * @param buffer Bytes/words to transmit. + * @param length Number of bytes/words in buffer to transmit. + */ + void write(const void * buffer, uint32 length); + + /** + * @brief Transmit a byte, then return the next unread byte. + * + * This function transmits before receiving. + * + * @param data Byte to transmit. + * @return Next unread byte. + */ + uint8 transfer(uint8 data) const; + uint16_t transfer16(uint16_t data) const; + + /** + * @brief Sets up a DMA Transfer for "length" bytes. + * The transfer mode (8 or 16 bit mode) is evaluated from the SPI peripheral setting. + * + * This function transmits and receives to buffers. + * + * @param transmitBuf buffer Bytes to transmit. If passed as 0, it sends FF repeatedly for "length" bytes + * @param receiveBuf buffer Bytes to save received data. + * @param length Number of bytes in buffer to transmit. + */ + uint8 dmaTransfer(const void * transmitBuf, void * receiveBuf, uint16 length); + void dmaTransferSet(const void *transmitBuf, void *receiveBuf); + uint8 dmaTransferRepeat(uint16 length); + + /** + * @brief Sets up a DMA Transmit for SPI 8 or 16 bit transfer mode. + * The transfer mode (8 or 16 bit mode) is evaluated from the SPI peripheral setting. + * + * This function only transmits and does not care about the RX fifo. + * + * @param data buffer half words to transmit, + * @param length Number of bytes in buffer to transmit. + * @param minc Set to use Memory Increment mode, clear to use Circular mode. + */ + uint8 dmaSend(const void * transmitBuf, uint16 length, bool minc = 1); + void dmaSendSet(const void * transmitBuf, bool minc); + uint8 dmaSendRepeat(uint16 length); + + uint8 dmaSendAsync(const void * transmitBuf, uint16 length, bool minc = 1); + /* + * Pin accessors + */ + + /** + * @brief Return the number of the MISO (master in, slave out) pin + */ + uint8 misoPin(void); + + /** + * @brief Return the number of the MOSI (master out, slave in) pin + */ + uint8 mosiPin(void); + + /** + * @brief Return the number of the SCK (serial clock) pin + */ + uint8 sckPin(void); + + /** + * @brief Return the number of the NSS (slave select) pin + */ + uint8 nssPin(void); + + /* Escape hatch */ + + /** + * @brief Get a pointer to the underlying libmaple spi_dev for + * this HardwareSPI instance. + */ + spi_dev* c_dev(void) { return _currentSetting->spi_d; } + + spi_dev *dev(){ return _currentSetting->spi_d;} + + /** + * @brief Sets the number of the SPI peripheral to be used by + * this HardwareSPI instance. + * + * @param spi_num Number of the SPI port. 1-2 in low density devices + * or 1-3 in high density devices. + */ + void setModule(int spi_num) + { + _currentSetting=&_settings[spi_num-1];// SPI channels are called 1 2 and 3 but the array is zero indexed + } + + /* -- The following methods are deprecated --------------------------- */ + + /** + * @brief Deprecated. + * + * Use HardwareSPI::transfer() instead. + * + * @see HardwareSPI::transfer() + */ + uint8 send(uint8 data); + + /** + * @brief Deprecated. + * + * Use HardwareSPI::write() in combination with + * HardwareSPI::read() (or HardwareSPI::transfer()) instead. + * + * @see HardwareSPI::write() + * @see HardwareSPI::read() + * @see HardwareSPI::transfer() + */ + uint8 send(uint8 *data, uint32 length); + + /** + * @brief Deprecated. + * + * Use HardwareSPI::read() instead. + * + * @see HardwareSPI::read() + */ + uint8 recv(void); + +private: + + SPISettings _settings[BOARD_NR_SPI]; + SPISettings *_currentSetting; + + void updateSettings(void); + /* + * Functions added for DMA transfers with Callback. + * Experimental. + */ + + void EventCallback(void); + + static void _spi1EventCallback(void); + static void _spi2EventCallback(void); + #if BOARD_NR_SPI >= 3 + static void _spi3EventCallback(void); + #endif + /* + spi_dev *spi_d; + uint8_t _SSPin; + uint32_t clockDivider; + uint8_t dataMode; + BitOrder bitOrder; + */ +}; + + +extern SPIClass SPI;//(1);// dummy params +#endif diff --git a/BootLoaders/Boards/stm32/platform.txt b/BootLoaders/Boards/stm32/platform.txt new file mode 100644 index 0000000..230f0a5 --- /dev/null +++ b/BootLoaders/Boards/stm32/platform.txt @@ -0,0 +1,157 @@ +# +# +# For more info: +# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification + +name=Multi 4-in-1 STM32 +version=1.0.0 + +compiler.warning_flags=-w -DDEBUG_LEVEL=DEBUG_NONE +compiler.warning_flags.none=-w -DDEBUG_LEVEL=DEBUG_NONE +compiler.warning_flags.default=-DDEBUG_LEVEL=DEBUG_NONE +compiler.warning_flags.more=-Wall -DDEBUG_LEVEL=DEBUG_FAULT +compiler.warning_flags.all=-Wall -Wextra -DDEBUG_LEVEL=DEBUG_ALL + +# compiler variables +# ---------------------- +compiler.path={runtime.tools.arm-none-eabi-gcc.path}/bin/ +compiler.c.cmd=arm-none-eabi-gcc +compiler.c.flags=-c -g {build.flags.optimize} {compiler.warning_flags} -std=gnu11 -MMD -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -DBOARD_{build.variant} -D{build.vect} -DERROR_LED_PORT={build.error_led_port} -DERROR_LED_PIN={build.error_led_pin} +compiler.c.elf.cmd=arm-none-eabi-g++ +compiler.c.elf.flags={build.flags.optimize} -Wl,--gc-sections {build.flags.ldspecs} +compiler.S.cmd=arm-none-eabi-gcc +compiler.S.flags=-c -g -x assembler-with-cpp -MMD +compiler.cpp.cmd=arm-none-eabi-g++ +compiler.cpp.flags=-c -g {build.flags.optimize} {compiler.warning_flags} -std=gnu++11 -MMD -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -DBOARD_{build.variant} -D{build.vect} -DERROR_LED_PORT={build.error_led_port} -DERROR_LED_PIN={build.error_led_pin} +compiler.ar.cmd=arm-none-eabi-ar +compiler.ar.flags=rcs +compiler.objcopy.cmd=arm-none-eabi-objcopy +compiler.objcopy.eep.flags=-O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 +compiler.elf2hex.flags=-O binary +compiler.elf2hex.cmd=arm-none-eabi-objcopy +compiler.ldflags={build.flags.ldspecs} +compiler.size.cmd=arm-none-eabi-size +compiler.define=-DARDUINO= + +# this can be overriden in boards.txt +build.f_cpu=72000000L +build.mcu=cortex-m3 +build.common_flags=-mthumb -march=armv7-m -D__STM32F1__ +build.variant_system_lib=libmaple.a +## LED stuff is not really used but is still required in the code +build.error_led_port=GPIOB +build.error_led_pin=1 +build.cpu_flags= +build.hs_flag= +build.upload_flags= +build.extra_flags= {build.upload_flags} {build.cpu_flags} {build.hs_flag} {build.common_flags} + + + +# These can be overridden in platform.local.txt +compiler.c.extra_flags= +compiler.c.elf.extra_flags="-L{build.variant.path}/ld" +compiler.cpp.extra_flags= +compiler.S.extra_flags= +compiler.ar.extra_flags= +compiler.elf2hex.extra_flags= + + +compiler.libs.c.flags="-I{build.system.path}/libmaple" "-I{build.system.path}/libmaple/include" "-I{build.system.path}/libmaple/stm32f1/include" "-I{build.system.path}/libmaple/usb/stm32f1" "-I{build.system.path}/libmaple/usb/usb_lib" + + + + +# USB Flags +# --------- +## build.usb_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} -DUSBCON '-DUSB_MANUFACTURER={build.usb_manufacturer}' '-DUSB_PRODUCT={build.usb_product}' + +# Default usb manufacturer will be replaced at compile time using +# numeric vendor ID if available or by board's specific value. +## build.usb_manufacturer="Unknown" + + +# build patterns +# --------------------- + +## Compile c files +recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -mcpu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.c.extra_flags} {build.extra_flags} {compiler.libs.c.flags} {includes} "{source_file}" -o "{object_file}" + +## Compile c++ files +recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} -mcpu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {build.cpu_flags} {build.hs_flag} {build.common_flags} {compiler.libs.c.flags} {includes} "{source_file}" -o "{object_file}" + +## Compile S files +recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.S.flags} -mcpu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.S.extra_flags} {build.extra_flags} {build.cpu_flags} {build.hs_flag} {build.common_flags} {compiler.libs.c.flags} {includes} "{source_file}" -o "{object_file}" + +## Create archives +recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}" + +## Combine gc-sections, archives, and objects +recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mcpu={build.mcu} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -lm -lgcc -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group {object_files} "{build.path}/{archive_file}" -Wl,--end-group + +## Create eeprom +recipe.objcopy.eep.pattern= + +## Create hex +recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.bin" + +## Compute size +recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" +recipe.size.regex=^(?:\.text|\.data|\.rodata|\.text.align|\.ARM.exidx)\s+([0-9]+).* +recipe.size.regex.data=^(?:\.data|\.bss|\.noinit)\s+([0-9]+).* + +## Save Compiled Binary +recipe.output.tmp_file={build.project_name}.bin +#recipe.output.save_file={build.project_name}.{build.variant}.bin +recipe.output.save_file=multifw.bin + +# Uploader tools +# ------------------- + +# Upload using Maple bootloader over DFU +tools.maple_upload.cmd=maple_upload +tools.maple_upload.cmd.windows=maple_upload.bat +tools.maple_upload.path={runtime.platform.path}/tools/win +tools.maple_upload.path.macosx={runtime.platform.path}/tools/macosx +tools.maple_upload.path.linux={runtime.platform.path}/tools/linux +tools.maple_upload.path.linux64={runtime.platform.path}/tools/linux64 +tools.maple_upload.upload.params.verbose=-d +tools.maple_upload.upload.params.quiet= +tools.maple_upload.upload.pattern="{path}/{cmd}" {serial.port.file} {upload.altID} {upload.usbID} "{build.path}/{build.project_name}.bin" + +#Added tool for generic STM32 upload via serial to Serial Port 1 (pins PA9 and PA10) - note. Boot0 line needs to high on board reset to enable upload via serial +# at the end up the upload the program is automatically run, without the board being reset + +tools.serial_upload.cmd=serial_upload +tools.serial_upload.cmd.windows=serial_upload.bat +tools.serial_upload.cmd.macosx=serial_upload +tools.serial_upload.path={runtime.platform.path}/tools/win +tools.serial_upload.path.macosx={runtime.platform.path}/tools/macosx +tools.serial_upload.path.linux={runtime.platform.path}/tools/linux +tools.serial_upload.path.linux64={runtime.platform.path}/tools/linux64 +tools.serial_upload.upload.params.verbose=-d +tools.serial_upload.upload.params.quiet=n +tools.serial_upload.upload.pattern="{path}/{cmd}" {serial.port.file} 0x8000000 "{build.path}/{build.project_name}.bin" + +tools.serial_upload.erase.params.verbose= +tools.serial_upload.erase.params.quiet= +tools.serial_upload.erase.pattern= + +tools.serial_upload.bootloader.params.verbose= +tools.serial_upload.bootloader.params.quiet= +tools.serial_upload.bootloader.pattern="{path}/{cmd}" {serial.port.file} 0x0 "{runtime.platform.path}/bootloaders/{bootloader.file}" + +# Dummy tool for "flashing" via Tx +# Doesn't do any actual upload but provides instructions and path to .bin file +tools.tx_upload.cmd=tx_upload +tools.tx_upload.cmd.windows=tx_upload.bat +tools.tx_upload.cmd.macosx=tx_upload +tools.tx_upload.cmd.linux=tx_upload +tools.tx_upload.cmd.linux64=tx_upload +tools.tx_upload.path={runtime.platform.path}/tools/win +tools.tx_upload.path.macosx={runtime.platform.path}/tools/macosx +tools.tx_upload.path.linux={runtime.platform.path}/tools/linux +tools.tx_upload.path.linux64={runtime.platform.path}/tools/linux64 +tools.tx_upload.upload.params.verbose=-d +tools.tx_upload.upload.params.quiet= +tools.tx_upload.upload.pattern="{path}/{cmd}" "{build.path}/{build.project_name}.bin" diff --git a/BootLoaders/Boards/stm32/programmers.txt b/BootLoaders/Boards/stm32/programmers.txt new file mode 100644 index 0000000..a1df209 --- /dev/null +++ b/BootLoaders/Boards/stm32/programmers.txt @@ -0,0 +1,5 @@ +stm32flash.name=stm32flash (FTDI) +stm32flash.communication=serial +stm32flash.protocol=stm32flash +stm32flash.program.protocol=stm32flash +stm32flash.program.tool=serial_upload diff --git a/BootLoaders/Boards/stm32/system/Makefile b/BootLoaders/Boards/stm32/system/Makefile new file mode 100644 index 0000000..0c6dfc0 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/Makefile @@ -0,0 +1,204 @@ +# Try "make help" first + +.DEFAULT_GOAL := sketch + +## +## Useful paths, constants, etc. +## + +ifeq ($(LIB_MAPLE_HOME),) +SRCROOT := . +else +SRCROOT := $(LIB_MAPLE_HOME) +endif + +BUILD_PATH = build +LIBMAPLE_PATH := $(SRCROOT)/libmaple +WIRISH_PATH := $(SRCROOT)/wirish +SUPPORT_PATH := $(SRCROOT)/support +LIBRARIES_PATH := $(SRCROOT)/libraries +# Support files for linker +LDDIR := $(SUPPORT_PATH)/ld +# Support files for this Makefile +MAKEDIR := $(SUPPORT_PATH)/make +BOARD_INCLUDE_DIR := $(MAKEDIR)/board-includes + +## +## Target-specific configuration. This determines some compiler and +## linker options/flags. +## + +# Try "make help" for more information on BOARD and MEMORY_TARGET; +# these default to a Maple Flash build. +BOARD ?= maple +MEMORY_TARGET ?= flash + +# Chooses the bootloader, available: maple and robotis +BOOTLOADER ?= maple + +# This is the serial port used by robotis bootloader +ROBOTIS_PORT ?= /dev/ttyACM0 + +# $(BOARD)- and $(MEMORY_TARGET)-specific configuration +include $(MAKEDIR)/target-config.mk + +## +## Build rules and useful templates +## + +include $(MAKEDIR)/build-rules.mk +include $(MAKEDIR)/build-templates.mk + +## +## Compilation flags +## + +# FIXME: the following allows for deprecated include style, e.g.: +# #include "libmaple.h" +# or +# #include "wirish.h" +# It slows compilation noticeably; remove after 1 release. +TARGET_FLAGS += -I$(LIBMAPLE_PATH)/include/libmaple \ + -I$(WIRISH_PATH)/include/wirish +TARGET_FLAGS += -I$(LIBRARIES_PATH) # for internal lib. includes, e.g. +GLOBAL_CFLAGS := -Os -g3 -gdwarf-2 -nostdlib \ + -ffunction-sections -fdata-sections \ + -Wl,--gc-sections $(TARGET_FLAGS) \ + -DBOOTLOADER_$(BOOTLOADER) +GLOBAL_CXXFLAGS := -fno-rtti -fno-exceptions -Wall $(TARGET_FLAGS) +GLOBAL_ASFLAGS := -x assembler-with-cpp $(TARGET_FLAGS) +LDFLAGS = $(TARGET_LDFLAGS) $(TOOLCHAIN_LDFLAGS) -mcpu=cortex-m3 -mthumb \ + -Xlinker --gc-sections \ + -Xassembler --march=armv7-m -Wall +# -Xlinker --print-gc-sections \ + +## +## Set all submodules here +## + +LIBMAPLE_MODULES += $(SRCROOT)/libmaple +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: +##LIBMAPLE_MODULES += $(SRCROOT)/libraries/Servo +##LIBMAPLE_MODULES += $(SRCROOT)/libraries/LiquidCrystal +##LIBMAPLE_MODULES += $(SRCROOT)/libraries/Wire +# Experimental libraries: +##LIBMAPLE_MODULES += $(SRCROOT)/libraries/FreeRTOS + +# User modules: +ifneq ($(USER_MODULES),) +LIBMAPLE_MODULES += $(USER_MODULES) +endif + +# Call each module's rules.mk: +$(foreach m,$(LIBMAPLE_MODULES),$(eval $(call LIBMAPLE_MODULE_template,$(m)))) + +## +## Targets +## + +# main target +include $(SRCROOT)/build-targets.mk + +.PHONY: install sketch clean help cscope tags ctags ram flash jtag doxygen mrproper list-boards + +# Target upload commands +# USB ID for DFU upload -- FIXME: do something smarter with this +BOARD_USB_VENDOR_ID := 1EAF +BOARD_USB_PRODUCT_ID := 0003 + +ifeq ($(BOOTLOADER),maple) +UPLOAD_ram := $(SUPPORT_PATH)/scripts/reset.py && \ + sleep 1 && \ + $(DFU) -a0 -d $(BOARD_USB_VENDOR_ID):$(BOARD_USB_PRODUCT_ID) -D $(BUILD_PATH)/$(BOARD).bin -R +UPLOAD_flash := $(SUPPORT_PATH)/scripts/reset.py && \ + sleep 1 && \ + $(DFU) -a1 -d $(BOARD_USB_VENDOR_ID):$(BOARD_USB_PRODUCT_ID) -D $(BUILD_PATH)/$(BOARD).bin -R +endif + +ifeq ($(BOOTLOADER),robotis) +UPLOAD_flash := $(SUPPORT_PATH)/scripts/robotis-loader.py $(ROBOTIS_PORT) $(BUILD_PATH)/$(BOARD).bin +endif + +# Conditionally upload to whatever the last build was +install: INSTALL_TARGET = $(shell cat $(BUILD_PATH)/build-type 2>/dev/null) +install: $(BUILD_PATH)/$(BOARD).bin + @echo "Install target:" $(INSTALL_TARGET) + $(UPLOAD_$(INSTALL_TARGET)) + +# Force a rebuild if the target changed +PREV_BUILD_TYPE = $(shell cat $(BUILD_PATH)/build-type 2>/dev/null) +build-check: +ifneq ($(PREV_BUILD_TYPE), $(MEMORY_TARGET)) + $(shell rm -rf $(BUILD_PATH)) +endif + +sketch: build-check MSG_INFO $(BUILD_PATH)/$(BOARD).bin + +clean: + rm -rf build + +mrproper: clean + rm -rf doxygen + +help: + @echo "" + @echo "Basic usage (BOARD defaults to maple):" + @echo " $$ cp your-main.cpp main.cpp" + @echo " $$ make BOARD=your_board" + @echo " $$ make BOARD=your_board install" + @echo "" + @echo "(Multiple source files? Link with libmaple.a (\`$$ make library')" + @echo "or hack build-targets.mk appropriately.)" + @echo "" + @echo "Important targets:" + @echo " sketch: Compile for BOARD to MEMORY_TARGET (default)." + @echo " install: Compile and upload over USB using Maple bootloader" + @echo "" + @echo "You *must* set BOARD if not compiling for Maple (e.g." + @echo "use BOARD=maple_mini for mini, etc.), and MEMORY_TARGET" + @echo "if not compiling to Flash. Run \`$$ make list-boards' for" + @echo "a list of all boards." + @echo "" + @echo "Valid MEMORY_TARGETs (default=flash):" + @echo " ram: Compile to RAM (doesn't touch Flash)" + @echo " flash: Compile to Flash (for Maple bootloader)" + @echo " jtag: Compile for JTAG/SWD upload (overwrites bootloader)" + @echo "" + @echo "Other targets:" + @echo " clean: Remove all build and object files" + @echo " doxygen: Build Doxygen HTML and XML documentation" + @echo " help: Show this message" + @echo " mrproper: Remove all generated files" + @echo "" + +cscope: + rm -rf cscope.* + find . -name '*.[hcS]' -o -name '*.cpp' | xargs cscope -b + +tags: + etags `find . -name "*.c" -o -name "*.cpp" -o -name "*.h"` + @echo "Made TAGS file for EMACS code browsing" + +ctags: + ctags-exuberant -R . + @echo "Made tags file for VIM code browsing" + +ram: + @$(MAKE) MEMORY_TARGET=ram --no-print-directory sketch + +flash: + @$(MAKE) MEMORY_TARGET=flash --no-print-directory sketch + +jtag: + @$(MAKE) MEMORY_TARGET=jtag --no-print-directory sketch + +doxygen: + doxygen $(SUPPORT_PATH)/doxygen/Doxyfile + +# This output is kind of ugly, but I don't understand make very well. +list-boards: + @echo " $(addsuffix "\\n",$(basename $(notdir $(wildcard $(BOARD_INCLUDE_DIR)/*.mk))))" diff --git a/BootLoaders/Boards/stm32/system/build-targets.mk b/BootLoaders/Boards/stm32/system/build-targets.mk new file mode 100644 index 0000000..aaff2d0 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/build-targets.mk @@ -0,0 +1,42 @@ +# main project target +$(BUILD_PATH)/main.o: $(SRCROOT)/main.cpp + $(SILENT_CXX) $(CXX) $(CFLAGS) $(CXXFLAGS) $(LIBMAPLE_INCLUDES) $(WIRISH_INCLUDES) -o $@ -c $< + +$(BUILD_PATH)/libmaple.a: $(BUILDDIRS) $(TGT_BIN) + - rm -f $@ + $(AR) crv $(BUILD_PATH)/libmaple.a $(TGT_BIN) + +library: $(BUILD_PATH)/libmaple.a + +.PHONY: library + +$(BUILD_PATH)/$(BOARD).elf: $(BUILDDIRS) $(TGT_BIN) $(BUILD_PATH)/main.o + $(SILENT_LD) $(CXX) $(LDFLAGS) -o $@ $(TGT_BIN) $(BUILD_PATH)/main.o -Wl,-Map,$(BUILD_PATH)/$(BOARD).map + +$(BUILD_PATH)/$(BOARD).bin: $(BUILD_PATH)/$(BOARD).elf + $(SILENT_OBJCOPY) $(OBJCOPY) -v -Obinary $(BUILD_PATH)/$(BOARD).elf $@ 1>/dev/null + $(SILENT_DISAS) $(DISAS) -d $(BUILD_PATH)/$(BOARD).elf > $(BUILD_PATH)/$(BOARD).disas + @echo " " + @echo "Object file sizes:" + @find $(BUILD_PATH) -iname *.o | xargs $(SIZE) -t > $(BUILD_PATH)/$(BOARD).sizes + @cat $(BUILD_PATH)/$(BOARD).sizes + @echo " " + @echo "Final Size:" + @$(SIZE) $< + @echo $(MEMORY_TARGET) > $(BUILD_PATH)/build-type + +$(BUILDDIRS): + @mkdir -p $@ + +MSG_INFO: + @echo "================================================================================" + @echo "" + @echo " Build info:" + @echo " BOARD: " $(BOARD) + @echo " MCU: " $(MCU) + @echo " MEMORY_TARGET: " $(MEMORY_TARGET) + @echo "" + @echo " See 'make help' for all possible targets" + @echo "" + @echo "================================================================================" + @echo "" diff --git a/BootLoaders/Boards/stm32/system/libmaple/dma_private.h b/BootLoaders/Boards/stm32/system/libmaple/dma_private.h new file mode 100644 index 0000000..f3765fc --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/dma_private.h @@ -0,0 +1,62 @@ +/****************************************************************************** + * 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_DMA_PRIVATE_H_ +#define _LIBMAPLE_DMA_PRIVATE_H_ + +#include +#include + +/* + * IRQ handling + */ + +/* Wrap this in an ifdef to shut up GCC. (We provide DMA_GET_HANDLER + * in the series support files, which need dma_irq_handler().) */ +#ifdef DMA_GET_HANDLER +static inline __always_inline void dma_irq_handler(dma_dev *dev, dma_tube tube) { + + void (*handler)(void) = DMA_GET_HANDLER(dev, tube); + if (handler) { + handler(); + dma_clear_isr_bits(dev, tube); /* in case handler doesn't */ + } +} +#endif + +/* + * Conveniences for dealing with tube sources/destinations + */ + +enum dma_atype { + DMA_ATYPE_MEM, + DMA_ATYPE_PER, + DMA_ATYPE_OTHER, +}; + +enum dma_atype _dma_addr_type(__io void *addr); + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/exti_private.h b/BootLoaders/Boards/stm32/system/libmaple/exti_private.h new file mode 100644 index 0000000..4f0a4cf --- /dev/null +++ b/BootLoaders/Boards/stm32/system/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/BootLoaders/Boards/stm32/system/libmaple/i2c_private.h b/BootLoaders/Boards/stm32/system/libmaple/i2c_private.h new file mode 100644 index 0000000..5b79516 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/i2c_private.h @@ -0,0 +1,79 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +#ifndef _LIBMAPLE_I2C_PRIVATE_H_ +#define _LIBMAPLE_I2C_PRIVATE_H_ + +#include + +/* For old-style definitions (SDA/SCL on same GPIO device) */ +#define I2C_DEV_OLD(num, port, sda, scl) \ + { \ + .regs = I2C##num##_BASE, \ + .gpio_port = port, \ + .scl_port = NULL, \ + .sda_port = NULL, \ + .sda_pin = sda, \ + .scl_pin = scl, \ + .clk_id = RCC_I2C##num, \ + .ev_nvic_line = NVIC_I2C##num##_EV, \ + .er_nvic_line = NVIC_I2C##num##_ER, \ + .state = I2C_STATE_DISABLED, \ + } + +/* For new-style definitions (SDA/SCL may be on different GPIO devices) */ +#define I2C_DEV_NEW(num, sdaport, sdabit, sclport, sclbit) \ + { \ + .regs = I2C##num##_BASE, \ + .gpio_port = NULL, \ + .scl_port = sclport, \ + .scl_pin = sclbit, \ + .sda_port = sdaport, \ + .sda_pin = sdabit, \ + .clk_id = RCC_I2C##num, \ + .ev_nvic_line = NVIC_I2C##num##_EV, \ + .er_nvic_line = NVIC_I2C##num##_ER, \ + .state = I2C_STATE_DISABLED, \ + } + +void _i2c_irq_handler(i2c_dev *dev); +void _i2c_irq_error_handler(i2c_dev *dev); + +struct gpio_dev; + +static inline struct gpio_dev* scl_port(const i2c_dev *dev) { + return (dev->gpio_port == NULL) ? dev->scl_port : dev->gpio_port; +} + +static inline struct gpio_dev* sda_port(const i2c_dev *dev) { + return (dev->gpio_port == NULL) ? dev->sda_port : dev->gpio_port; +} + +/* Auxiliary procedure for enabling an I2C peripheral; `flags' as for + * i2c_master_enable(). */ +void _i2c_set_ccr_trise(i2c_dev *dev, uint32 flags); + +#endif /* _LIBMAPLE_I2C_PRIVATE_H_ */ diff --git a/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/adc.h b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/adc.h new file mode 100644 index 0000000..21efaf5 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/adc.h @@ -0,0 +1,351 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * Copyright (c) 2010 Perry Hung. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/include/libmaple/adc.h + * @author Marti Bolivar , + * Perry Hung + * @brief Analog-to-Digital Conversion (ADC) header. + */ + +#ifndef _LIBMAPLE_ADC_H_ +#define _LIBMAPLE_ADC_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include +#include +#include +#include +/* We include the series header below, after defining the register map + * and device structs. */ + +/* + * Register map + */ + +/** ADC register map type. */ +typedef struct adc_reg_map { + __io uint32 SR; ///< Status register + __io uint32 CR1; ///< Control register 1 + __io uint32 CR2; ///< Control register 2 + __io uint32 SMPR1; ///< Sample time register 1 + __io uint32 SMPR2; ///< Sample time register 2 + __io uint32 JOFR1; ///< Injected channel data offset register 1 + __io uint32 JOFR2; ///< Injected channel data offset register 2 + __io uint32 JOFR3; ///< Injected channel data offset register 3 + __io uint32 JOFR4; ///< Injected channel data offset register 4 + __io uint32 HTR; ///< Watchdog high threshold register + __io uint32 LTR; ///< Watchdog low threshold register + __io uint32 SQR1; ///< Regular sequence register 1 + __io uint32 SQR2; ///< Regular sequence register 2 + __io uint32 SQR3; ///< Regular sequence register 3 + __io uint32 JSQR; ///< Injected sequence register + __io uint32 JDR1; ///< Injected data register 1 + __io uint32 JDR2; ///< Injected data register 2 + __io uint32 JDR3; ///< Injected data register 3 + __io uint32 JDR4; ///< Injected data register 4 + __io uint32 DR; ///< Regular data register +} adc_reg_map; + + +/** ADC device type. */ +typedef struct adc_dev { + adc_reg_map *regs; /**< Register map */ + rcc_clk_id clk_id; /**< RCC clock information */ + nvic_irq_num irq_num; /* Added by bubulindo */ + voidFuncPtr handlers[]; /* Added by bubulindo EOC, JEOC, AWD Interrupts*/ +} adc_dev; + + +//Added by bubulindo - Interrupt ID's for ADC +typedef enum adc_interrupt_id { + ADC_EOC, /**< Update interrupt. */ + ADC_AWD , /**< Capture/compare 1 interrupt. */ + ADC_JEOC, + //ADC_JSTRT, + //ADC_STRT, /**Analog WatchDog interrupt */ +} adc_interrupt_id; + +//Added by bubulindo +void adc_enable_irq(adc_dev* dev, uint8 interrupt); +void adc_attach_interrupt(adc_dev *dev, uint8 interrupt, voidFuncPtr handler); + + +/* Pull in the series header (which may need the above struct + * definitions). + * + * IMPORTANT: The series header must define the following: + * + * - enum adc_extsel_event (and typedef to adc_extsel_event): One per + * external event used to trigger start of conversion of a regular + * group. If two different series support the same event as a + * trigger, they must use the same token for the enumerator for that + * event. (The value of the enumerator is of course allowed to be + * different). + * + * - enum adc_smp_rate (and typedef to adc_smp_rate): One per + * available sampling time. These must be in the form ADC_SMPR_X_Y + * for X.Y cycles (e.g. ADC_SMPR_1_5 means 1.5 cycles), or + * ADC_SMPR_X for X cycles (e.g. ADC_SMPR_3 means 3 cycles). + * + * - enum adc_prescaler (and typedef): One per available prescaler, + * suitable for adc_set_prescaler. Series which have the same + * prescaler dividers (e.g. STM32F1 and STM32F2 both divide PCLK2 by + * 2, 4, 6, or 8) must provide the same tokens as enumerators, for + * portability. + */ + + /* Roger clark. Replaced with line below #include */ +#include "stm32f1/include/series/adc.h" + + +/* + * Register bit definitions + */ + +/* Status register */ + +#define ADC_SR_AWD_BIT 0 +#define ADC_SR_EOC_BIT 1 +#define ADC_SR_JEOC_BIT 2 +#define ADC_SR_JSTRT_BIT 3 +#define ADC_SR_STRT_BIT 4 + +#define ADC_SR_AWD BIT(ADC_SR_AWD_BIT) +#define ADC_SR_EOC BIT(ADC_SR_EOC_BIT) +#define ADC_SR_JEOC BIT(ADC_SR_JEOC_BIT) +#define ADC_SR_JSTRT BIT(ADC_SR_JSTRT_BIT) +#define ADC_SR_STRT BIT(ADC_SR_STRT_BIT) + +/* Control register 1 */ + +#define ADC_CR1_EOCIE_BIT 5 +#define ADC_CR1_AWDIE_BIT 6 +#define ADC_CR1_JEOCIE_BIT 7 +#define ADC_CR1_SCAN_BIT 8 +#define ADC_CR1_AWDSGL_BIT 9 +#define ADC_CR1_JAUTO_BIT 10 +#define ADC_CR1_DISCEN_BIT 11 +#define ADC_CR1_JDISCEN_BIT 12 +#define ADC_CR1_JAWDEN_BIT 22 +#define ADC_CR1_AWDEN_BIT 23 + +#define ADC_CR1_AWDCH (0x1F) +#define ADC_CR1_EOCIE BIT(ADC_CR1_EOCIE_BIT) +#define ADC_CR1_AWDIE BIT(ADC_CR1_AWDIE_BIT) +#define ADC_CR1_JEOCIE BIT(ADC_CR1_JEOCIE_BIT) +#define ADC_CR1_SCAN BIT(ADC_CR1_SCAN_BIT) +#define ADC_CR1_AWDSGL BIT(ADC_CR1_AWDSGL_BIT) +#define ADC_CR1_JAUTO BIT(ADC_CR1_JAUTO_BIT) +#define ADC_CR1_DISCEN BIT(ADC_CR1_DISCEN_BIT) +#define ADC_CR1_JDISCEN BIT(ADC_CR1_JDISCEN_BIT) +#define ADC_CR1_DISCNUM (0xE000) +#define ADC_CR1_JAWDEN BIT(ADC_CR1_JAWDEN_BIT) +#define ADC_CR1_AWDEN BIT(ADC_CR1_AWDEN_BIT) + +/* Control register 2 */ + +/* Because this register varies significantly by series (e.g. some + * bits moved and others disappeared in the F1->F2 transition), its + * definitions are in the series headers. */ + +/* Sample time register 1 */ + +#define ADC_SMPR1_SMP17 (0x7 << 21) +#define ADC_SMPR1_SMP16 (0x7 << 18) +#define ADC_SMPR1_SMP15 (0x7 << 15) +#define ADC_SMPR1_SMP14 (0x7 << 12) +#define ADC_SMPR1_SMP13 (0x7 << 9) +#define ADC_SMPR1_SMP12 (0x7 << 6) +#define ADC_SMPR1_SMP11 (0x7 << 3) +#define ADC_SMPR1_SMP10 0x7 + +/* Sample time register 2 */ + +#define ADC_SMPR2_SMP9 (0x7 << 27) +#define ADC_SMPR2_SMP8 (0x7 << 24) +#define ADC_SMPR2_SMP7 (0x7 << 21) +#define ADC_SMPR2_SMP6 (0x7 << 18) +#define ADC_SMPR2_SMP5 (0x7 << 15) +#define ADC_SMPR2_SMP4 (0x7 << 12) +#define ADC_SMPR2_SMP3 (0x7 << 9) +#define ADC_SMPR2_SMP2 (0x7 << 6) +#define ADC_SMPR2_SMP1 (0x7 << 3) +#define ADC_SMPR2_SMP0 0x7 + +/* Injected channel data offset register */ + +#define ADC_JOFR_JOFFSET 0x3FF + +/* Watchdog high threshold register */ + +#define ADC_HTR_HT 0x3FF + +/* Watchdog low threshold register */ + +#define ADC_LTR_LT 0x3FF + +/* Regular sequence register 1 */ + +#define ADC_SQR1_L (0x1F << 20) +#define ADC_SQR1_SQ16 (0x1F << 15) +#define ADC_SQR1_SQ15 (0x1F << 10) +#define ADC_SQR1_SQ14 (0x1F << 5) +#define ADC_SQR1_SQ13 0x1F + +/* Regular sequence register 2 */ + +#define ADC_SQR2_SQ12 (0x1F << 25) +#define ADC_SQR2_SQ11 (0x1F << 20) +#define ADC_SQR2_SQ10 (0x1F << 16) +#define ADC_SQR2_SQ9 (0x1F << 10) +#define ADC_SQR2_SQ8 (0x1F << 5) +#define ADC_SQR2_SQ7 0x1F + +/* Regular sequence register 3 */ + +#define ADC_SQR3_SQ6 (0x1F << 25) +#define ADC_SQR3_SQ5 (0x1F << 20) +#define ADC_SQR3_SQ4 (0x1F << 16) +#define ADC_SQR3_SQ3 (0x1F << 10) +#define ADC_SQR3_SQ2 (0x1F << 5) +#define ADC_SQR3_SQ1 0x1F + +/* Injected sequence register */ + +#define ADC_JSQR_JL (0x3 << 20) +#define ADC_JSQR_JL_1CONV (0x0 << 20) +#define ADC_JSQR_JL_2CONV (0x1 << 20) +#define ADC_JSQR_JL_3CONV (0x2 << 20) +#define ADC_JSQR_JL_4CONV (0x3 << 20) +#define ADC_JSQR_JSQ4 (0x1F << 15) +#define ADC_JSQR_JSQ3 (0x1F << 10) +#define ADC_JSQR_JSQ2 (0x1F << 5) +#define ADC_JSQR_JSQ1 0x1F + +/* Injected data registers */ + +#define ADC_JDR_JDATA 0xFFFF + +/* Regular data register */ + +#define ADC_DR_ADC2DATA (0xFFFF << 16) +#define ADC_DR_DATA 0xFFFF + +/* + * Routines + */ + +void adc_init(adc_dev *dev); +void adc_set_extsel(adc_dev *dev, adc_extsel_event event); +void adc_set_sample_rate(adc_dev *dev, adc_smp_rate smp_rate); +uint16 adc_read(adc_dev *dev, uint8 channel); + +/** + * @brief Set the ADC prescaler. + * + * This determines the ADC clock for all devices. + */ +extern void adc_set_prescaler(adc_prescaler pre); + +/** + * @brief Call a function on all ADC devices. + * @param fn Function to call on each ADC device. + */ +extern void adc_foreach(void (*fn)(adc_dev*)); + +struct gpio_dev; +/** + * @brief Configure a GPIO pin for ADC conversion. + * @param dev ADC device to use for conversion (currently ignored on + * all targets). + * @param gdev GPIO device to configure. + * @param bit Bit on gdev to configure for ADC conversion. + */ +extern void adc_config_gpio(struct adc_dev *dev, + struct gpio_dev *gdev, + uint8 bit); + +/** + * @brief Enable an ADC and configure it for single conversion mode. + * + * This function performs any initialization necessary to allow the + * ADC device to perform a single synchronous regular software + * triggered conversion, using adc_read(). + * + * @param dev Device to enable. + * @see adc_read() + */ +extern void adc_enable_single_swstart(adc_dev* dev); + +/** + * @brief Set the regular channel sequence length. + * + * Defines the total number of conversions in the regular channel + * conversion sequence. + * + * @param dev ADC device. + * @param length Regular channel sequence length, from 1 to 16. + */ +static inline void adc_set_reg_seqlen(adc_dev *dev, uint8 length) { + uint32 tmp = dev->regs->SQR1; + tmp &= ~ADC_SQR1_L; + tmp |= (length - 1) << 20; + dev->regs->SQR1 = tmp; +} + +/** + * @brief Enable an adc peripheral + * @param dev ADC device to enable + */ +static inline void adc_enable(adc_dev *dev) { + *bb_perip(&dev->regs->CR2, ADC_CR2_ADON_BIT) = 1; +} + +/** + * @brief Disable an ADC peripheral + * @param dev ADC device to disable + */ +static inline void adc_disable(adc_dev *dev) { + *bb_perip(&dev->regs->CR2, ADC_CR2_ADON_BIT) = 0; +} + +/** + * @brief Disable all ADC peripherals. + */ +static inline void adc_disable_all(void) { + adc_foreach(adc_disable); +} + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/bitband.h b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/bitband.h new file mode 100644 index 0000000..6e77991 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/bitband.h @@ -0,0 +1,128 @@ +/****************************************************************************** + * 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/include/libmaple/bitband.h + * + * @brief Bit-banding utility functions + */ + +#ifndef _LIBMAPLE_BITBAND_H_ +#define _LIBMAPLE_BITBAND_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define BB_SRAM_REF 0x20000000 +#define BB_SRAM_BASE 0x22000000 +#define BB_PERI_REF 0x40000000 +#define BB_PERI_BASE 0x42000000 + +static inline volatile uint32* __bb_addr(volatile void*, + uint32, + uint32, + uint32); + +/** + * @brief Obtain a pointer to the bit-band address corresponding to a + * bit in a volatile SRAM address. + * @param address Address in the bit-banded SRAM region + * @param bit Bit in address to bit-band + */ +static inline volatile uint32* bb_sramp(volatile void *address, uint32 bit) { + return __bb_addr(address, bit, BB_SRAM_BASE, BB_SRAM_REF); +} + +/** + * @brief Get a bit from an address in the SRAM bit-band region. + * @param address Address in the SRAM bit-band region to read from + * @param bit Bit in address to read + * @return bit's value in address. + */ +static inline uint8 bb_sram_get_bit(volatile void *address, uint32 bit) { + return *bb_sramp(address, bit); +} + +/** + * @brief Set a bit in an address in the SRAM bit-band region. + * @param address Address in the SRAM bit-band region to write to + * @param bit Bit in address to write to + * @param val Value to write for bit, either 0 or 1. + */ +static inline void bb_sram_set_bit(volatile void *address, + uint32 bit, + uint8 val) { + *bb_sramp(address, bit) = val; +} + +/** + * @brief Obtain a pointer to the bit-band address corresponding to a + * bit in a peripheral address. + * @param address Address in the bit-banded peripheral region + * @param bit Bit in address to bit-band + */ +static inline volatile uint32* bb_perip(volatile void *address, uint32 bit) { + return __bb_addr(address, bit, BB_PERI_BASE, BB_PERI_REF); +} + +/** + * @brief Get a bit from an address in the peripheral bit-band region. + * @param address Address in the peripheral bit-band region to read from + * @param bit Bit in address to read + * @return bit's value in address. + */ +static inline uint8 bb_peri_get_bit(volatile void *address, uint32 bit) { + return *bb_perip(address, bit); +} + +/** + * @brief Set a bit in an address in the peripheral bit-band region. + * @param address Address in the peripheral bit-band region to write to + * @param bit Bit in address to write to + * @param val Value to write for bit, either 0 or 1. + */ +static inline void bb_peri_set_bit(volatile void *address, + uint32 bit, + uint8 val) { + *bb_perip(address, bit) = val; +} + +static inline volatile uint32* __bb_addr(volatile void *address, + uint32 bit, + uint32 bb_base, + uint32 bb_ref) { + return (volatile uint32*)(bb_base + ((uint32)address - bb_ref) * 32 + + bit * 4); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/bkp.h b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/bkp.h new file mode 100644 index 0000000..bb63a2f --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/bkp.h @@ -0,0 +1,166 @@ +/****************************************************************************** + * 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/include/libmaple/bkp.h + * @brief Backup register support (STM32F1 only). + */ + +#ifndef _LIBMAPLE_BKP_H_ +#define _LIBMAPLE_BKP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#if defined(STM32_MEDIUM_DENSITY) +#define BKP_NR_DATA_REGS 10 +#elif defined(STM32_HIGH_DENSITY) +#define BKP_NR_DATA_REGS 42 +#endif + +/** Backup peripheral register map type. */ +typedef struct bkp_reg_map { + const uint32 RESERVED1; ///< Reserved + __io uint32 DR1; ///< Data register 1 + __io uint32 DR2; ///< Data register 2 + __io uint32 DR3; ///< Data register 3 + __io uint32 DR4; ///< Data register 4 + __io uint32 DR5; ///< Data register 5 + __io uint32 DR6; ///< Data register 6 + __io uint32 DR7; ///< Data register 7 + __io uint32 DR8; ///< Data register 8 + __io uint32 DR9; ///< Data register 9 + __io uint32 DR10; ///< Data register 10 + __io uint32 RTCCR; ///< RTC control register + __io uint32 CR; ///< Control register + __io uint32 CSR; ///< Control and status register +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) + const uint32 RESERVED2; ///< Reserved + const uint32 RESERVED3; ///< Reserved + __io uint32 DR11; ///< Data register 11 + __io uint32 DR12; ///< Data register 12 + __io uint32 DR13; ///< Data register 13 + __io uint32 DR14; ///< Data register 14 + __io uint32 DR15; ///< Data register 15 + __io uint32 DR16; ///< Data register 16 + __io uint32 DR17; ///< Data register 17 + __io uint32 DR18; ///< Data register 18 + __io uint32 DR19; ///< Data register 19 + __io uint32 DR20; ///< Data register 20 + __io uint32 DR21; ///< Data register 21 + __io uint32 DR22; ///< Data register 22 + __io uint32 DR23; ///< Data register 23 + __io uint32 DR24; ///< Data register 24 + __io uint32 DR25; ///< Data register 25 + __io uint32 DR26; ///< Data register 26 + __io uint32 DR27; ///< Data register 27 + __io uint32 DR28; ///< Data register 28 + __io uint32 DR29; ///< Data register 29 + __io uint32 DR30; ///< Data register 30 + __io uint32 DR31; ///< Data register 31 + __io uint32 DR32; ///< Data register 32 + __io uint32 DR33; ///< Data register 33 + __io uint32 DR34; ///< Data register 34 + __io uint32 DR35; ///< Data register 35 + __io uint32 DR36; ///< Data register 36 + __io uint32 DR37; ///< Data register 37 + __io uint32 DR38; ///< Data register 38 + __io uint32 DR39; ///< Data register 39 + __io uint32 DR40; ///< Data register 40 + __io uint32 DR41; ///< Data register 41 + __io uint32 DR42; ///< Data register 42 +#endif +} bkp_reg_map; + +/** Backup peripheral register map base pointer. */ +#define BKP_BASE ((struct bkp_reg_map*)0x40006C00) + +/** Backup peripheral device type. */ +typedef struct bkp_dev { + bkp_reg_map *regs; /**< Register map */ +} bkp_dev; + +extern const bkp_dev *BKP; + +/* + * Register bit definitions + */ + +/* Data Registers */ + +#define BKP_DR_D 0xFFFF + +/* RTC Clock Calibration Register */ + +#define BKP_RTCCR_ASOS_BIT 9 +#define BKP_RTCCR_ASOE_BIT 8 +#define BKP_RTCCR_CCO_BIT 7 + +#define BKP_RTCCR_ASOS BIT(BKP_RTCCR_ASOS_BIT) +#define BKP_RTCCR_ASOE BIT(BKP_RTCCR_ASOE_BIT) +#define BKP_RTCCR_CCO BIT(BKP_RTCCR_CCO_BIT) +#define BKP_RTCCR_CAL 0x7F + +/* Backup control register */ + +#define BKP_CR_TPAL_BIT 1 +#define BKP_CR_TPE_BIT 0 + +#define BKP_CR_TPAL BIT(BKP_CR_TPAL_BIT) +#define BKP_CR_TPE BIT(BKP_CR_TPE_BIT) + +/* Backup control/status register */ + +#define BKP_CSR_TIF_BIT 9 +#define BKP_CSR_TEF_BIT 8 +#define BKP_CSR_TPIE_BIT 2 +#define BKP_CSR_CTI_BIT 1 +#define BKP_CSR_CTE_BIT 0 + +#define BKP_CSR_TIF BIT(BKP_CSR_TIF_BIT) +#define BKP_CSR_TEF BIT(BKP_CSR_TEF_BIT) +#define BKP_CSR_TPIE BIT(BKP_CSR_TPIE_BIT) +#define BKP_CSR_CTI BIT(BKP_CSR_CTI_BIT) +#define BKP_CSR_CTE BIT(BKP_CSR_CTE_BIT) + +/* + * Convenience functions + */ + +void bkp_init(void); +void bkp_enable_writes(void); +void bkp_disable_writes(void); +uint16 bkp_read(uint8 reg); +void bkp_write(uint8 reg, uint16 val); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/dac.h b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/dac.h new file mode 100644 index 0000000..7768423 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/dac.h @@ -0,0 +1,162 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011, 2012 LeafLabs, LLC. + * Copyright (c) 2010 Bryan Newbold. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/include/libmaple/dac.h + * @brief Digital to analog converter support. + */ + +/* See notes/dac.txt for more info */ + +#ifndef _LIBMAPLE_DAC_H_ +#define _LIBMAPLE_DAC_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + + /* Roger clark. Replaced with line below #include */ +#include "stm32f1/include/series/dac.h" +#include +#include +#include + +/* + * Register map base and device pointers. + * + * The DACs are the same on all supported targets, so it's not worth + * repeating these in the series headers. + */ + +#define DAC_BASE ((struct dac_reg_map*)0x40007400) + +/** DAC device type. */ +typedef struct dac_dev { + dac_reg_map *regs; /**< Register map */ +} dac_dev; + +#if STM32_HAVE_DAC +extern const dac_dev *DAC; +#endif + +/* + * Register bit definitions + */ + +/* Control register */ + +/* Channel 1 control */ +#define DAC_CR_EN1 (1U << 0) /* Enable */ +#define DAC_CR_BOFF1 (1U << 1) /* Output buffer disable */ +#define DAC_CR_TEN1 (1U << 2) /* Trigger enable */ +#define DAC_CR_TSEL1 (0x7 << 3) /* Trigger selection */ +#define DAC_CR_WAVE1 (0x3 << 6) /* Noise/triangle wave */ +#define DAC_CR_MAMP1 (0xF << 8) /* Mask/amplitude selector */ +#define DAC_CR_DMAEN1 (1U << 12) /* DMA enable */ +/* Channel 2 control */ +#define DAC_CR_EN2 (1U << 16) /* Enable */ +#define DAC_CR_BOFF2 (1U << 17) /* Output buffer disable */ +#define DAC_CR_TEN2 (1U << 18) /* Trigger enable */ +#define DAC_CR_TSEL2 (0x7 << 19) /* Trigger selection */ +#define DAC_CR_WAVE2 (0x3 << 22) /* Noise/triangle wave */ +#define DAC_CR_MAMP2 (0xF << 24) /* Mask/amplitude selector */ +#define DAC_CR_DMAEN2 (1U << 28) /* DMA enable */ + +/* Software trigger register */ + +#define DAC_SWTRIGR_SWTRIG1 (1U << 0) /* Channel 1 software trigger */ +#define DAC_SWTRIGR_SWTRIG2 (1U << 1) /* Channel 2 software trigger */ + +/* Channel 1 12-bit right-aligned data holding register */ + +#define DAC_DHR12R1_DACC1DHR 0x00000FFF + +/* Channel 1 12-bit left-aligned data holding register */ + +#define DAC_DHR12L1_DACC1DHR 0x0000FFF0 + +/* Channel 1 8-bit left-aligned data holding register */ + +#define DAC_DHR8R1_DACC1DHR 0x000000FF + +/* Channel 2 12-bit right-aligned data holding register */ + +#define DAC_DHR12R2_DACC2DHR 0x00000FFF + +/* Channel 2 12-bit left-aligned data holding register */ + +#define DAC_DHR12L2_DACC2DHR 0x0000FFF0 + +/* Channel 2 8-bit left-aligned data holding register */ + +#define DAC_DHR8R2_DACC2DHR 0x000000FF + +/* Dual DAC 12-bit right-aligned data holding register */ + +#define DAC_DHR12RD_DACC1DHR 0x00000FFF +#define DAC_DHR12RD_DACC2DHR 0x0FFF0000 + +/* Dual DAC 12-bit left-aligned data holding register */ + +#define DAC_DHR12LD_DACC1DHR 0x0000FFF0 +#define DAC_DHR12LD_DACC2DHR 0xFFF00000 + +/* Dual DAC 8-bit left-aligned data holding register */ + +#define DAC_DHR8RD_DACC1DHR 0x000000FF +#define DAC_DHR8RD_DACC2DHR 0x0000FF00 + +/* Channel 1 data output register */ + +#define DAC_DOR1_DACC1DOR 0x00000FFF + +/* Channel 1 data output register */ + +#define DAC_DOR2_DACC2DOR 0x00000FFF + +/* + * Routines + */ + +/* We take the dev argument in these for future-proofing */ + +#define DAC_CH1 0x1 +#define DAC_CH2 0x2 +void dac_init(const dac_dev *dev, uint32 flags); + +void dac_write_channel(const dac_dev *dev, uint8 channel, uint16 val); +void dac_enable_channel(const dac_dev *dev, uint8 channel); +void dac_disable_channel(const dac_dev *dev, uint8 channel); + +#define dac_write_channel1(val) ( DAC->regs->DHR12R1 = DAC_DHR12R1_DACC1DHR & val ) +#define dac_write_channel2(val) ( DAC->regs->DHR12R2 = DAC_DHR12R2_DACC2DHR & val ) + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/delay.h b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/delay.h new file mode 100644 index 0000000..472a208 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/delay.h @@ -0,0 +1,65 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Perry Hung. + * Copyright (c) 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/include/libmaple/delay.h + * @brief Delay implementation + */ + +#ifndef _LIBMAPLE_DELAY_H_ +#define _LIBMAPLE_DELAY_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** + * @brief Delay the given number of microseconds. + * + * @param us Number of microseconds to delay. + */ +static inline void delay_us(uint32 us) { + us *= STM32_DELAY_US_MULT; + + /* fudge for function call overhead */ + us--; + asm volatile(" mov r0, %[us] \n\t" + "1: subs r0, #1 \n\t" + " bhi 1b \n\t" + : + : [us] "r" (us) + : "r0"); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/dma.h b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/dma.h new file mode 100644 index 0000000..a75b314 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/dma.h @@ -0,0 +1,447 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Michael Hope. + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/include/libmaple/dma.h + * + * @author Marti Bolivar ; + * Original implementation by Michael Hope + * + * @brief Direct Memory Access peripheral support + */ + +#ifndef _LIBMAPLE_DMA_H_ +#define _LIBMAPLE_DMA_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +/* provides: + * + * - An opaque dma_tube type, and predefined rvalues for each tube + * supported by the series. + * + * A "DMA tube" is a series-specific (hopefully integer) datatype + * that abstracts the conduit through which DMA-ed data flow. + * + * Examples: On STM32F1, dma_tube is just an alias for dma_channel, + * and the tube values are just DMA_CH1 (=1), DMA_CH2 (=2), etc. + * + * Note that a dma_tube doesn't have to be an enum, and its values + * don't have to be integral. They _do_ need to be cheap to pass as + * arguments, though. + * + * - struct dma_tube_reg_map (and typedef to dma_tube_reg_map). DMA + * register maps tend to be split into global registers and per-tube + * registers. It's convenient to pass around pointers to a tube's + * registers, since that makes it possible to configure or otherwise + * mess with a tube without knowing which one you're dealing with. + * + * - Base pointers to the various dma_tube_reg_maps. + * + * Examples: On STM32F1, these are DMAxCHy_BASE. You can access + * registers like DMAxCHy_BASE->CPAR, etc. + * + * - enum dma_request_src (and typedef to dma_request_src). This + * specifies the peripheral DMA request sources (e.g. USART TX DMA + * requests, etc.). + * + * - enum dma_mode_flags (and typedef to dma_mode_flags). Used in + * dma_tube_config. If two series both support the same mode flags, + * they must use the same enumerator names for those flags (the + * values of those enumerators are of course allowed to differ). + * + * - Normal stuff: dma_reg_map and base pointers, register bit + * definitions, dma_dev pointer declarations, and any other + * convenience functions useful for the series. */ + + /* Roger clark. Replaced with line below #include */ +#include "stm32f1/include/series/dma.h" + +/* buys us dma_dev and other necessities. */ +#include +#include + +/* + * Declarations/documentation for some of the series-provided types. + */ + +/** + * @brief (Series-dependent) DMA request sources. + * + * These specify the various pieces of peripheral functionality which + * may make DMA requests. Use them to set up a DMA transfer (see + * struct dma_tube_config, dma_tube_cfg()). + */ +enum dma_request_src; + +/** + * @brief (Series-dependent) DMA tube configuration flags. + * These specify miscellaneous bits of configuration for a DMA tube. + * @see struct dma_mode_config + */ +enum dma_cfg_flags; + +/** + * @brief (Series-dependent) DMA tube register map type. + * This allows you to access a tube's registers as a group. + * @see dma_tube_regs() + */ +struct dma_tube_reg_map; + +/* + * Convenience functions + */ + +/* Initialization */ + +void dma_init(dma_dev *dev); + +/* dma_tube configuration + * + * Use these types and functions to set up DMA transfers, handle + * interrupts, etc. The main function of interest is dma_tube_cfg(), + * which the various series implement separately. */ + +/** + * @brief Specifies a DMA tube configuration. + * + * Use one of these to set up a DMA transfer by passing it to + * dma_tube_cfg(). + * + * @see dma_tube_cfg() + * @see dma_xfer_size + */ +typedef struct dma_tube_config { + /** Source of data */ + __io void *tube_src; + /** Source transfer size */ + dma_xfer_size tube_src_size; + + /** Destination of data */ + __io void *tube_dst; + /** Destination transfer size */ + dma_xfer_size tube_dst_size; + + /** + * Number of data to transfer (0 to 65,535). + * + * Note that this is NOT measured in bytes; it's measured in + * number of data, which occur in multiples of tube_src_size. For + * example, if tube_src_size is DMA_SIZE_32BITS and tube_nr_xfers + * is 2, then 8 total bytes will be transferred. + */ + unsigned tube_nr_xfers; + + /** + * Target-specific configuration flags. + * + * These are an OR of series-specific enum dma_mode_flags values. + * Consult the documentation for your target for what flags you + * can use here. + * + * Typical flag examples: DMA_CFG_SRC_INC, DMA_CFG_DST_INC, + * DMA_CFG_CIRC, DMA_CFG_CMPLT_IE, etc. + */ + unsigned tube_flags; + + /** + * Currently unused. You must set this to 0 or something valid for + * your target. */ + void *target_data; + + /** + * Hardware DMA request source. + * + * This is ignored for memory-to-memory transfers. + */ + enum dma_request_src tube_req_src; +} dma_tube_config; + +#define DMA_TUBE_CFG_SUCCESS 0 +#define DMA_TUBE_CFG_EREQ 1 +#define DMA_TUBE_CFG_ENDATA 2 +#define DMA_TUBE_CFG_EDEV 3 +#define DMA_TUBE_CFG_ESRC 4 +#define DMA_TUBE_CFG_EDST 5 +#define DMA_TUBE_CFG_EDIR 6 +#define DMA_TUBE_CFG_ESIZE 7 +#define DMA_TUBE_CFG_ECFG 0xFF +/** + * @brief Configure a DMA tube. + * + * Use this function to set up a DMA transfer. The tube will be + * disabled before being reconfigured. The transfer will have low + * priority by default. You can choose another priority before the + * transfer begins using dma_set_priority(). You can manage your + * interrupt handlers for the tube using dma_attach_interrupt() and + * dma_detach_interrupt(). + * + * After calling dma_tube_cfg() and performing any other desired + * configuration, start the transfer using dma_enable(). + * + * @param dev DMA device. + * @param tube DMA tube to configure. + * @param cfg Configuration to apply to tube. + * + * @return DMA_TUBE_CFG_SUCCESS (0) on success, <0 on failure. On + * failure, returned value will be the opposite (-) of one of: + * + * - DMA_TUBE_CFG_EREQ: tube doesn't work with cfg->tube_req_src + * - DMA_TUBE_CFG_ENDATA: cfg->tube_[src,dst]_size are + * incompatible with cfg->tube_nr_xfers, or cfg->tube_nr_xfers + * is out of bounds. + * - DMA_TUBE_CFG_EDEV: dev does not support cfg + * - DMA_TUBE_CFG_ESRC: bad cfg->tube_src + * - DMA_TUBE_CFG_EDST: bad cfg->tube_dst + * - DMA_TUBE_CFG_EDIR: dev can't transfer from cfg->tube_src to + * cfg->tube_dst + * - DMA_TUBE_CFG_ESIZE: something ended up wrong due to MSIZE/PSIZE + * - DMA_TUBE_CFG_ECFG: generic "something's wrong" + * + * @sideeffect Disables tube. May alter tube's registers even when an + * error occurs. + * @see struct dma_tube_config + * @see dma_attach_interrupt() + * @see dma_detach_interrupt() + * @see dma_enable() + */ +extern int dma_tube_cfg(dma_dev *dev, dma_tube tube, dma_tube_config *cfg); + +/* Other tube configuration functions. You can use these if + * dma_tube_cfg() isn't enough, or to adjust parts of an existing tube + * configuration. */ + +/** DMA transfer priority. */ +typedef enum dma_priority { + DMA_PRIORITY_LOW = 0, /**< Low priority */ + DMA_PRIORITY_MEDIUM = 1, /**< Medium priority */ + DMA_PRIORITY_HIGH = 2, /**< High priority */ + DMA_PRIORITY_VERY_HIGH = 3, /**< Very high priority */ +} dma_priority; + +/** + * @brief Set the priority of a DMA transfer. + * + * You may not call this function while the tube is enabled. + * + * @param dev DMA device + * @param tube DMA tube + * @param priority priority to set. + */ +extern void dma_set_priority(dma_dev *dev, dma_tube tube, + dma_priority priority); + +/** + * @brief Set the number of data transfers on a DMA tube. + * + * You may not call this function while the tube is enabled. + * + * @param dev DMA device + * @param tube Tube through which the transfer will occur. + * @param num_transfers Number of DMA transactions to set. + */ +extern void dma_set_num_transfers(dma_dev *dev, dma_tube tube, + uint16 num_transfers); + +/** + * @brief Set the base memory address where data will be read from or + * written to. + * + * You must not call this function while the tube is enabled. + * + * If the DMA memory size is 16 bits, the address is automatically + * aligned to a half-word. If the DMA memory size is 32 bits, the + * address is aligned to a word. + * + * @param dev DMA Device + * @param tube Tube whose base memory address to set. + * @param address Memory base address to use. + */ +extern void dma_set_mem_addr(dma_dev *dev, dma_tube tube, __io void *address); + +/** + * @brief Set the base peripheral address where data will be read from + * or written to. + * + * You must not call this function while the channel is enabled. + * + * If the DMA peripheral size is 16 bits, the address is automatically + * aligned to a half-word. If the DMA peripheral size is 32 bits, the + * address is aligned to a word. + * + * @param dev DMA Device + * @param tube Tube whose peripheral data register base address to set. + * @param address Peripheral memory base address to use. + */ +extern void dma_set_per_addr(dma_dev *dev, dma_tube tube, __io void *address); + +/* Interrupt handling */ + +/** + * @brief Attach an interrupt to a DMA transfer. + * + * Interrupts are enabled using series-specific mode flags in + * dma_tube_cfg(). + * + * @param dev DMA device + * @param tube Tube to attach handler to + * @param handler Interrupt handler to call when tube interrupt fires. + * @see dma_tube_cfg() + * @see dma_get_irq_cause() + * @see dma_detach_interrupt() + */ +extern void dma_attach_interrupt(dma_dev *dev, dma_tube tube, + void (*handler)(void)); + + +/** + * @brief Detach a DMA transfer interrupt handler. + * + * After calling this function, the given tube's interrupts will be + * disabled. + * + * @param dev DMA device + * @param tube Tube whose handler to detach + * @sideeffect Clears the tube's interrupt enable bits. + * @see dma_attach_interrupt() + */ +extern void dma_detach_interrupt(dma_dev *dev, dma_tube tube); + +/* Tube enable/disable */ + +/** + * @brief Enable a DMA tube. + * + * If the tube has been properly configured, calling this function + * allows it to start serving DMA requests. + * + * @param dev DMA device + * @param tube Tube to enable + * @see dma_tube_cfg() + */ +extern void dma_enable(dma_dev *dev, dma_tube tube); + +/** + * @brief Disable a DMA channel. + * + * Calling this function makes the tube stop serving DMA requests. + * + * @param dev DMA device + * @param tube Tube to disable + */ +extern void dma_disable(dma_dev *dev, dma_tube tube); + +/** + * @brief Check if a DMA tube is enabled. + * @param dev DMA device. + * @param tube Tube to check. + * @return 0 if the tube is disabled, >0 if it is enabled. + */ +static inline uint8 dma_is_enabled(dma_dev *dev, dma_tube tube); + +/* Other conveniences */ + +/** + * @brief Obtain a pointer to an individual DMA tube's registers. + * + * Examples: + * + * - On STM32F1, dma_channel_regs(DMA1, DMA_CH1)->CCR is DMA1_BASE->CCR1. + * + * @param dev DMA device. + * @param tube DMA tube whose register map to obtain. + * @return (Series-specific) tube register map. + */ +static inline dma_tube_reg_map* dma_tube_regs(dma_dev *dev, dma_tube tube); + +/** + * Encodes the reason why a DMA interrupt was called. + * @see dma_get_irq_cause() + */ +typedef enum dma_irq_cause { + DMA_TRANSFER_COMPLETE, /**< Transfer is complete. */ + DMA_TRANSFER_HALF_COMPLETE, /**< Transfer is half complete. */ + DMA_TRANSFER_ERROR, /**< Error occurred during transfer. */ + DMA_TRANSFER_DME_ERROR, /**< + * @brief Direct mode error occurred during + * transfer. */ + DMA_TRANSFER_FIFO_ERROR, /**< FIFO error occurred during transfer. */ +} dma_irq_cause; + +/** + * @brief Discover the reason why a DMA interrupt was called. + * + * You may only call this function within an attached interrupt + * handler for the given channel. + * + * This function resets the internal DMA register state which encodes + * the cause of the interrupt; consequently, it can only be called + * once per interrupt handler invocation. + * + * @param dev DMA device + * @param tube Tube whose interrupt is being handled. + * @return Reason why the interrupt fired. + * @sideeffect Clears flags in dev's interrupt status registers. + * @see dma_attach_interrupt() + * @see dma_irq_cause + */ +extern dma_irq_cause dma_get_irq_cause(dma_dev *dev, dma_tube tube); + +/** + * @brief Get the ISR status bits for a DMA channel. + * + * The bits are returned right-aligned, in the order they appear in + * the corresponding ISR register. + * + * If you're trying to figure out why a DMA interrupt fired, you may + * find dma_get_irq_cause() more convenient. + * + * @param dev DMA device + * @param tube Tube whose ISR bits to return. + * @see dma_get_irq_cause(). + */ +static inline uint8 dma_get_isr_bits(dma_dev *dev, dma_tube tube); + +/** + * @brief Clear the ISR status bits for a given DMA tube. + * + * If you're trying to clean up after yourself in a DMA interrupt, you + * may find dma_get_irq_cause() more convenient. + * + * @param dev DMA device + * @param tube Tube whose ISR bits to clear. + * @see dma_get_irq_cause() + */ +static inline void dma_clear_isr_bits(dma_dev *dev, dma_tube tube); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/dma_common.h b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/dma_common.h new file mode 100644 index 0000000..3765cd5 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/dma_common.h @@ -0,0 +1,112 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/include/libmaple/dma_common.h + * @author Marti Bolivar + * @brief Common DMA sub-header for and . + * + * CONTENTS UNSTABLE. The existence of this file is an implementation + * detail. Never include it directly. If you need something from + * here, include instead. + */ + +/* + * There's a fair amount of common DMA functionality needed by each + * and . This header exists in order + * to provide it to both, avoiding some hacks and circular + * dependencies. + */ + +#ifndef _LIBMAPLE_DMA_COMMON_H_ +#define _LIBMAPLE_DMA_COMMON_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include +#include +#include + +/* + * Devices + */ + +struct dma_reg_map; + +/* Encapsulates state related to user interrupt handlers. You + * shouldn't touch these directly; use dma_attach_interrupt() and + * dma_detach_interupt() instead. */ +typedef struct dma_handler_config { + void (*handler)(void); /* User handler */ + nvic_irq_num irq_line; /* IRQ line for interrupt */ +} dma_handler_config; + +/** DMA device type */ +typedef struct dma_dev { + struct dma_reg_map *regs; /**< Register map */ + rcc_clk_id clk_id; /**< Clock ID */ + struct dma_handler_config handlers[]; /**< For internal use */ +} dma_dev; + +/** + * @brief DMA channels + * + * Notes: + * - This is also the dma_tube type for STM32F1. + * - Channel 0 is not available on all STM32 series. + * + * @see dma_tube + */ +typedef enum dma_channel { + DMA_CH0 = 0, /**< Channel 0 */ + DMA_CH1 = 1, /**< Channel 1 */ + DMA_CH2 = 2, /**< Channel 2 */ + DMA_CH3 = 3, /**< Channel 3 */ + DMA_CH4 = 4, /**< Channel 4 */ + DMA_CH5 = 5, /**< Channel 5 */ + DMA_CH6 = 6, /**< Channel 6 */ + DMA_CH7 = 7, /**< Channel 7 */ +} dma_channel; + +/** + * @brief Source and destination transfer sizes. + * Use these when initializing a struct dma_tube_config. + * @see struct dma_tube_config + * @see dma_tube_cfg + */ +typedef enum dma_xfer_size { + DMA_SIZE_8BITS = 0, /**< 8-bit transfers */ + DMA_SIZE_16BITS = 1, /**< 16-bit transfers */ + DMA_SIZE_32BITS = 2, /**< 32-bit transfers */ +} dma_xfer_size; + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/exti.h b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/exti.h new file mode 100644 index 0000000..69362d6 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/exti.h @@ -0,0 +1,144 @@ +/****************************************************************************** + * 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/include/libmaple/exti.h + * @brief External interrupt control + */ + +/* See notes/exti.txt for more info */ + +#ifndef _LIBMAPLE_EXTI_H_ +#define _LIBMAPLE_EXTI_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +/* Roger clark. replaced by line below #include */ /* provides EXTI_BASE */ +#include "stm32f1/include/series/exti.h" +#include + +/* + * Register map and base pointer. + */ + +/** EXTI register map type */ +typedef struct exti_reg_map { + __io uint32 IMR; /**< Interrupt mask register */ + __io uint32 EMR; /**< Event mask register */ + __io uint32 RTSR; /**< Rising trigger selection register */ + __io uint32 FTSR; /**< Falling trigger selection register */ + __io uint32 SWIER; /**< Software interrupt event register */ + __io uint32 PR; /**< Pending register */ +} exti_reg_map; + +/* + * 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 */ + EXTI_FALLING, /**< Trigger on the falling edge */ + EXTI_RISING_FALLING /**< Trigger on both the rising and falling edges */ +} exti_trigger_mode; + +/* + * Routines + */ + +void exti_attach_interrupt(exti_num num, + exti_cfg port, + voidFuncPtr handler, + exti_trigger_mode mode); +void exti_attach_callback(exti_num num, + exti_cfg port, + voidArgumentFuncPtr handler, + void *arg, + exti_trigger_mode mode); +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" +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/flash.h b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/flash.h new file mode 100644 index 0000000..3b1d7b3 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/flash.h @@ -0,0 +1,107 @@ +/****************************************************************************** + * 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/include/libmaple/flash.h + * @brief Flash support. + */ + +#ifndef _LIBMAPLE_FLASH_H_ +#define _LIBMAPLE_FLASH_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include + +#define FLASH_WAIT_STATE_0 0x0 +#define FLASH_WAIT_STATE_1 0x1 +#define FLASH_WAIT_STATE_2 0x2 +#define FLASH_WAIT_STATE_3 0x3 +#define FLASH_WAIT_STATE_4 0x4 +#define FLASH_WAIT_STATE_5 0x5 +#define FLASH_WAIT_STATE_6 0x6 +#define FLASH_WAIT_STATE_7 0x7 + +/* The series header must define: + * + * - FLASH_SAFE_WAIT_STATES, the smallest number of wait states that + * it is safe to use when SYSCLK is at its fastest documented rate + * and the MCU is powered at 3.3V (i.e. this doesn't consider + * overclocking or low voltage operation). + * + * - The following bit flags, for flash_enable_features(): + * + * -- FLASH_PREFETCH: prefetcher + * -- FLASH_ICACHE: instruction cache + * -- FLASH_DCACHE: data cache + * + * See that function's Doxygen for more restrictions. + */ + /* Roger clark. Replaced with line below #include */ +#include "stm32f1/include/series/flash.h" + +#ifdef __DOXYGEN__ +/** Flash register map base pointer. */ +#define FLASH_BASE +#endif + +/* + * Flash routines + */ + +void flash_set_latency(uint32 wait_states); + +/** + * @brief Enable Flash memory features + * + * If the target MCU doesn't provide a feature (e.g. instruction and + * data caches on the STM32F1), the flag will be ignored. This allows + * using these flags unconditionally, with the desired effect taking + * place on targets that support them. + * + * @param feature_flags Bitwise OR of the following: + * FLASH_PREFETCH (turns on prefetcher), + * FLASH_ICACHE (turns on instruction cache), + * FLASH_DCACHE (turns on data cache). + */ +static inline void flash_enable_features(uint32 feature_flags) { + FLASH_BASE->ACR |= feature_flags; +} + +/** + * @brief Deprecated. Use flash_enable_features(FLASH_PREFETCH) instead. + */ +static inline void flash_enable_prefetch(void) { + flash_enable_features(FLASH_PREFETCH); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/fsmc.h b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/fsmc.h new file mode 100644 index 0000000..6225fee --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/fsmc.h @@ -0,0 +1,340 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Bryan Newbold. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/include/libmaple/fsmc.h + * @brief Flexible static memory controller support. + */ + +/* + * See ../notes/fsmc.txt for more info + */ + +#ifndef _LIBMAPLE_FSMC_H_ +#define _LIBMAPLE_FSMC_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include +#include + +#if !STM32_HAVE_FSMC +#error "FSMC is unavailable on your MCU" +#endif + +/* + * Register maps and devices + */ + +/** FSMC register map type */ +typedef struct fsmc_reg_map { + __io uint32 BCR1; /**< SRAM/NOR-Flash chip-select control register 1 */ + __io uint32 BTR1; /**< SRAM/NOR-Flash chip-select timing register 1 */ + __io uint32 BCR2; /**< SRAM/NOR-Flash chip-select control register 2 */ + __io uint32 BTR2; /**< SRAM/NOR-Flash chip-select timing register 2 */ + __io uint32 BCR3; /**< SRAM/NOR-Flash chip-select control register 3 */ + __io uint32 BTR3; /**< SRAM/NOR-Flash chip-select timing register 3 */ + __io uint32 BCR4; /**< SRAM/NOR-Flash chip-select control register 4 */ + __io uint32 BTR4; /**< SRAM/NOR-Flash chip-select timing register 4 */ + const uint8 RESERVED1[64]; /**< Reserved */ + __io uint32 PCR2; /**< PC Card/NAND Flash control register 2 */ + __io uint32 SR2; /**< FIFO status and interrupt register 2 */ + __io uint32 PMEM2; /**< Common memory space timing register 2 */ + __io uint32 PATT2; /**< Attribute memory space timing register 2 */ + const uint8 RESERVED2[4]; /**< Reserved */ + __io uint32 ECCR2; /**< ECC result register 2 */ + const uint8 RESERVED3[2]; + __io uint32 PCR3; /**< PC Card/NAND Flash control register 3 */ + __io uint32 SR3; /**< FIFO status and interrupt register 3 */ + __io uint32 PMEM3; /**< Common memory space timing register 3 */ + __io uint32 PATT3; /**< Attribute memory space timing register 3 */ + const uint32 RESERVED4; /**< Reserved */ + __io uint32 ECCR3; /**< ECC result register 3 */ + const uint8 RESERVED5[8]; /**< Reserved */ + __io uint32 PCR4; /**< PC Card/NAND Flash control register 4 */ + __io uint32 SR4; /**< FIFO status and interrupt register 4 */ + __io uint32 PMEM4; /**< Common memory space timing register 4 */ + __io uint32 PATT4; /**< Attribute memory space timing register 4 */ + __io uint32 PIO4; /**< I/O space timing register 4 */ + const uint8 RESERVED6[80]; /**< Reserved */ + __io uint32 BWTR1; /**< SRAM/NOR-Flash write timing register 1 */ + const uint32 RESERVED7; /**< Reserved */ + __io uint32 BWTR2; /**< SRAM/NOR-Flash write timing register 2 */ + const uint32 RESERVED8; /**< Reserved */ + __io uint32 BWTR3; /**< SRAM/NOR-Flash write timing register 3 */ + const uint32 RESERVED9; /**< Reserved */ + __io uint32 BWTR4; /**< SRAM/NOR-Flash write timing register 4 */ +} __attribute__((packed)) fsmc_reg_map; + +#define __FSMCB 0xA0000000 + +/** FSMC register map base pointer */ +#define FSMC_BASE ((struct fsmc_reg_map*)__FSMCB) + +/** FSMC NOR/PSRAM register map type */ +typedef struct fsmc_nor_psram_reg_map { + __io uint32 BCR; /**< Chip-select control register */ + __io uint32 BTR; /**< Chip-select timing register */ + const uint8 RESERVED[252]; /**< Reserved */ + __io uint32 BWTR; /**< Write timing register */ +} fsmc_nor_psram_reg_map; + +/** FSMC NOR/PSRAM base pointer 1 */ +#define FSMC_NOR_PSRAM1_BASE ((struct fsmc_nor_psram_reg_map*)__FSMCB) + +/** FSMC NOR/PSRAM base pointer 2 */ +#define FSMC_NOR_PSRAM2_BASE ((struct fsmc_nor_psram_reg_map*)(__FSMCB + 0x8)) + +/** FSMC NOR/PSRAM base pointer 3 */ +#define FSMC_NOR_PSRAM3_BASE ((struct fsmc_nor_psram_reg_map*)(__FSMCB + 0x10)) + +/** FSMC NOR/PSRAM base pointer 4 */ +#define FSMC_NOR_PSRAM4_BASE ((struct fsmc_nor_psram_reg_map*)(__FSMCB + 0x18)) + +/* + * Register bit definitions + */ + +/* NOR/PSRAM chip-select control registers */ + +#define FSMC_BCR_CBURSTRW_BIT 19 +#define FSMC_BCR_ASYNCWAIT_BIT 15 +#define FSMC_BCR_EXTMOD_BIT 14 +#define FSMC_BCR_WAITEN_BIT 13 +#define FSMC_BCR_WREN_BIT 12 +#define FSMC_BCR_WAITCFG_BIT 11 +#define FSMC_BCR_WRAPMOD_BIT 10 +#define FSMC_BCR_WAITPOL_BIT 9 +#define FSMC_BCR_BURSTEN_BIT 8 +#define FSMC_BCR_FACCEN_BIT 6 +#define FSMC_BCR_MUXEN_BIT 1 +#define FSMC_BCR_MBKEN_BIT 0 + +#define FSMC_BCR_CBURSTRW (1U << FSMC_BCR_CBURSTRW_BIT) +#define FSMC_BCR_ASYNCWAIT (1U << FSMC_BCR_ASYNCWAIT_BIT) +#define FSMC_BCR_EXTMOD (1U << FSMC_BCR_EXTMOD_BIT) +#define FSMC_BCR_WAITEN (1U << FSMC_BCR_WAITEN_BIT) +#define FSMC_BCR_WREN (1U << FSMC_BCR_WREN_BIT) +#define FSMC_BCR_WAITCFG (1U << FSMC_BCR_WAITCFG_BIT) +#define FSMC_BCR_WRAPMOD (1U << FSMC_BCR_WRAPMOD_BIT) +#define FSMC_BCR_WAITPOL (1U << FSMC_BCR_WAITPOL_BIT) +#define FSMC_BCR_BURSTEN (1U << FSMC_BCR_BURSTEN_BIT) +#define FSMC_BCR_FACCEN (1U << FSMC_BCR_FACCEN_BIT) +#define FSMC_BCR_MWID (0x3 << 4) +#define FSMC_BCR_MWID_8BITS (0x0 << 4) +#define FSMC_BCR_MWID_16BITS (0x1 << 4) +#define FSMC_BCR_MTYP (0x3 << 2) +#define FSMC_BCR_MTYP_SRAM (0x0 << 2) +#define FSMC_BCR_MTYP_PSRAM (0x1 << 2) +#define FSMC_BCR_MTYP_NOR_FLASH (0x2 << 2) +#define FSMC_BCR_MUXEN (1U << FSMC_BCR_MUXEN_BIT) +#define FSMC_BCR_MBKEN (1U << FSMC_BCR_MBKEN_BIT) + +/* SRAM/NOR-Flash chip-select timing registers */ + +#define FSMC_BTR_ACCMOD (0x3 << 28) +#define FSMC_BTR_ACCMOD_A (0x0 << 28) +#define FSMC_BTR_ACCMOD_B (0x1 << 28) +#define FSMC_BTR_ACCMOD_C (0x2 << 28) +#define FSMC_BTR_ACCMOD_D (0x3 << 28) +#define FSMC_BTR_DATLAT (0xF << 24) +#define FSMC_BTR_CLKDIV (0xF << 20) +#define FSMC_BTR_BUSTURN (0xF << 16) +#define FSMC_BTR_DATAST (0xFF << 8) +#define FSMC_BTR_ADDHLD (0xF << 4) +#define FSMC_BTR_ADDSET 0xF + +/* SRAM/NOR-Flash write timing registers */ + +#define FSMC_BWTR_ACCMOD (0x3 << 28) +#define FSMC_BWTR_ACCMOD_A (0x0 << 28) +#define FSMC_BWTR_ACCMOD_B (0x1 << 28) +#define FSMC_BWTR_ACCMOD_C (0x2 << 28) +#define FSMC_BWTR_ACCMOD_D (0x3 << 28) +#define FSMC_BWTR_DATLAT (0xF << 24) +#define FSMC_BWTR_CLKDIV (0xF << 20) +#define FSMC_BWTR_DATAST (0xFF << 8) +#define FSMC_BWTR_ADDHLD (0xF << 4) +#define FSMC_BWTR_ADDSET 0xF + +/* NAND Flash/PC Card controller registers */ + +#define FSMC_PCR_ECCEN_BIT 6 +#define FSMC_PCR_PTYP_BIT 3 +#define FSMC_PCR_PBKEN_BIT 2 +#define FSMC_PCR_PWAITEN_BIT 1 + +#define FSMC_PCR_ECCPS (0x7 << 17) +#define FSMC_PCR_ECCPS_256B (0x0 << 17) +#define FSMC_PCR_ECCPS_512B (0x1 << 17) +#define FSMC_PCR_ECCPS_1024B (0x2 << 17) +#define FSMC_PCR_ECCPS_2048B (0x3 << 17) +#define FSMC_PCR_ECCPS_4096B (0x4 << 17) +#define FSMC_PCR_ECCPS_8192B (0x5 << 17) +#define FSMC_PCR_TAR (0xF << 13) +#define FSMC_PCR_TCLR (0xF << 9) +#define FSMC_PCR_ECCEN (1U << FSMC_PCR_ECCEN_BIT) +#define FSMC_PCR_PWID (0x3 << 4) +#define FSMC_PCR_PWID_8BITS (0x0 << 4) +#define FSMC_PCR_PWID_16BITS (0x1 << 4) +#define FSMC_PCR_PTYP (1U << FSMC_PCR_PTYP_BIT) +#define FSMC_PCR_PTYP_PC_CF_PCMCIA (0x0 << FSMC_PCR_PTYP_BIT) +#define FSMC_PCR_PTYP_NAND (0x1 << FSMC_PCR_PTYP_BIT) +#define FSMC_PCR_PBKEN (1U << FSMC_PCR_PBKEN_BIT) +#define FSMC_PCR_PWAITEN (1U << FSMC_PCR_PWAITEN_BIT) + +/* FIFO status and interrupt registers */ + +#define FSMC_SR_FEMPT_BIT 6 +#define FSMC_SR_IFEN_BIT 5 +#define FSMC_SR_ILEN_BIT 4 +#define FSMC_SR_IREN_BIT 3 +#define FSMC_SR_IFS_BIT 2 +#define FSMC_SR_ILS_BIT 1 +#define FSMC_SR_IRS_BIT 0 + +#define FSMC_SR_FEMPT (1U << FSMC_SR_FEMPT_BIT) +#define FSMC_SR_IFEN (1U << FSMC_SR_IFEN_BIT) +#define FSMC_SR_ILEN (1U << FSMC_SR_ILEN_BIT) +#define FSMC_SR_IREN (1U << FSMC_SR_IREN_BIT) +#define FSMC_SR_IFS (1U << FSMC_SR_IFS_BIT) +#define FSMC_SR_ILS (1U << FSMC_SR_ILS_BIT) +#define FSMC_SR_IRS (1U << FSMC_SR_IRS_BIT) + +/* Common memory space timing registers */ + +#define FSMC_PMEM_MEMHIZ (0xFF << 24) +#define FSMC_PMEM_MEMHOLD (0xFF << 16) +#define FSMC_PMEM_MEMWAIT (0xFF << 8) +#define FSMC_PMEM_MEMSET 0xFF + +/* Attribute memory space timing registers */ + +#define FSMC_PATT_ATTHIZ (0xFF << 24) +#define FSMC_PATT_ATTHOLD (0xFF << 16) +#define FSMC_PATT_ATTWAIT (0xFF << 8) +#define FSMC_PATT_ATTSET 0xFF + +/* I/O space timing register 4 */ + +#define FSMC_PIO_IOHIZ (0xFF << 24) +#define FSMC_PIO_IOHOLD (0xFF << 16) +#define FSMC_PIO_IOWAIT (0xFF << 8) +#define FSMC_PIO_IOSET 0xFF + +/* + * Memory bank boundary addresses + */ + +/** + * @brief Void pointer to base address of FSMC memory bank 1 (NOR/PSRAM). + * + * This bank is split into 4 regions. Each region supports interfacing + * with 1 NOR Flash, SRAM, or PSRAM chip. The base addresses of these + * regions are FSMC_NOR_PSRAM_REGIONx, for x = 1, 2, 3, 4. + */ +#define FSMC_BANK1 ((void*)0x60000000) + +/** + * @brief Void pointer to base address of FSMC memory bank 1, region 1 + * (NOR/PSRAM). + */ +#define FSMC_NOR_PSRAM_REGION1 FSMC_BANK1 + +/** + * @brief Void pointer to base address of FSMC memory bank 1, region 2 + * (NOR/PSRAM). + */ +#define FSMC_NOR_PSRAM_REGION2 ((void*)0x64000000) + +/** + * @brief Void pointer to base address of FSMC memory bank 1, region 3 + * (NOR/PSRAM). + */ +#define FSMC_NOR_PSRAM_REGION3 ((void*)0x68000000) + +/** + * @brief Void pointer to base address of FSMC memory bank 1, region 4 + * (NOR/PSRAM). + */ +#define FSMC_NOR_PSRAM_REGION4 ((void*)0x6C000000) + +/** Void pointer to base address of FSMC memory bank 2 (NAND Flash). */ +#define FSMC_BANK2 ((void*)0x70000000) + +/** Void pointer to base address of FSMC memory bank 3 (NAND Flash). */ +#define FSMC_BANK3 ((void*)0x80000000) + +/** + * @brief Void pointer to base address of FSMC memory bank 4 (PC card + * devices). + */ +#define FSMC_BANK4 ((void*)0x90000000) + +/* + * SRAM/NOR Flash routines + */ + +/** + * @brief Configure FSMC GPIOs for use with SRAM. + */ +void fsmc_sram_init_gpios(void); + +/** + * Set the DATAST bits in the given NOR/PSRAM register map's + * chip-select timing register (FSMC_BTR). + * + * @param regs NOR Flash/PSRAM register map whose chip-select timing + * register to set. + * @param datast Value to use for DATAST bits. + */ +static inline void fsmc_nor_psram_set_datast(fsmc_nor_psram_reg_map *regs, + uint8 datast) { + regs->BTR &= ~FSMC_BTR_DATAST; + regs->BTR |= datast << 8; +} + +/** + * Set the ADDHLD bits in the given NOR/PSRAM register map's chip + * select timing register (FSMC_BTRx). + * + * @param regs NOR Flash/PSRAM register map whose chip-select timing + * register to set. + * @param addset Value to use for ADDSET bits. + */ +static inline void fsmc_nor_psram_set_addset(fsmc_nor_psram_reg_map *regs, + uint8 addset) { + regs->BTR &= ~FSMC_BTR_ADDSET; + regs->BTR |= addset & 0xF; +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/gpio.h b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/gpio.h new file mode 100644 index 0000000..aba4e11 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/gpio.h @@ -0,0 +1,123 @@ +/****************************************************************************** + * 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 + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. +*****************************************************************************/ + +/** + * @file libmaple/include/libmaple/gpio.h + * @brief General Purpose I/O (GPIO) interace. + */ + +#ifndef _LIBMAPLE_GPIO_H_ +#define _LIBMAPLE_GPIO_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +/* + * Note: Series header must define: + * - enum gpio_pin_mode (TODO think harder about portability here) + */ + +// roger clark. replaced with line below #include +#include "stm32f1/include/series/gpio.h" +#include +#include +#include + +/* + * 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 flags argument version? */ +void gpio_set_mode(gpio_dev *dev, uint8 pin, gpio_pin_mode mode); +gpio_pin_mode gpio_get_mode(gpio_dev *dev, uint8 pin); +/** + * @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. + * + * Pin must have previously been configured to output mode. + * + * @param dev GPIO device whose pin to set. + * @param pin Pin on to set or reset + * @param val If true, set the pin. If false, reset the pin. + */ +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 = (1U << pin) << (16 * val); +} + +/** + * Determine whether or not a GPIO pin is set. + * + * Pin must have previously been configured to input mode. + * + * @param dev GPIO device whose pin to test. + * @param pin Pin on dev to test. + * @return True if the pin is set, false otherwise. + */ +static inline uint32 gpio_read_bit(gpio_dev *dev, uint8 pin) { + return dev->regs->IDR & (1U << pin); +} + +/** + * Toggle a pin configured as output push-pull. + * @param dev GPIO device. + * @param pin Pin on dev to toggle. + */ +static inline void gpio_toggle_bit(gpio_dev *dev, uint8 pin) { + dev->regs->ODR = dev->regs->ODR ^ (1U << pin); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/i2c.h b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/i2c.h new file mode 100644 index 0000000..92ec29e --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/i2c.h @@ -0,0 +1,414 @@ +/****************************************************************************** + * 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. + *****************************************************************************/ + +/** + * @file libmaple/include/libmaple/i2c.h + * @brief Inter-Integrated Circuit (I2C) peripheral support + * + * Currently master-only. Usage notes: + * + * - Enable an I2C device with i2c_master_enable(). + * - Initialize an array of struct i2c_msg to suit the bus + * transactions (reads/writes) you wish to perform. + * - Call i2c_master_xfer() to do the work. + */ + +#ifndef _LIBMAPLE_I2C_H_ +#define _LIBMAPLE_I2C_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Series header must provide: + * + * - uint32 _i2c_bus_clk(i2c_dev*): Clock frequency of dev's bus, in + * MHz. (This is for internal use only). + * + * - (optional) _I2C_HAVE_IRQ_FIXUP: Leave undefined, or define to 1. + * This is for internal use only. It's a hack to work around a + * silicon bug related to I2C IRQ pre-emption on some targets. If 1, + * the series header must also declare and implement a routine with + * this signature (it may also be provided as a macro): + * + * void _i2c_irq_priority_fixup(i2c_dev*) + * + * This will be called by i2c_enable_irq() before actually enabling + * I2C interrupts. + * + * - Reg. map base pointers, device pointer declarations. + */ + + /* Roger clark. Replaced with line below #include */ +#include "stm32f1/include/series/i2c.h" +#include + +#include +#include +#include +#include + +/** I2C register map type */ +typedef struct i2c_reg_map { + __io uint32 CR1; /**< Control register 1 */ + __io uint32 CR2; /**< Control register 2 */ + __io uint32 OAR1; /**< Own address register 1 */ + __io uint32 OAR2; /**< Own address register 2 */ + __io uint32 DR; /**< Data register */ + __io uint32 SR1; /**< Status register 1 */ + __io uint32 SR2; /**< Status register 2 */ + __io uint32 CCR; /**< Clock control register */ + __io uint32 TRISE; /**< TRISE (rise time) register */ +} i2c_reg_map; + +/** + * @brief I2C message type + */ +typedef struct i2c_msg { + uint16 addr; /**< Address */ + +#define I2C_MSG_READ 0x1 +#define I2C_MSG_10BIT_ADDR 0x2 + /** + * Bitwise OR of: + * - I2C_MSG_READ (write is default) + * - I2C_MSG_10BIT_ADDR (7-bit is default) */ + uint16 flags; + + uint16 length; /**< Message length */ + uint16 xferred; /**< Messages transferred */ + uint8 *data; /**< Data */ +} i2c_msg; + +/* + * Register bit definitions + */ + +/* Control register 1 */ + +#define I2C_CR1_SWRST (1U << 15) // Software reset +#define I2C_CR1_ALERT (1U << 13) // SMBus alert +#define I2C_CR1_PEC (1U << 12) // Packet error checking +#define I2C_CR1_POS (1U << 11) // Acknowledge/PEC position +#define I2C_CR1_ACK (1U << 10) // Acknowledge enable +#define I2C_CR1_STOP (1U << 9) // Stop generation +#define I2C_CR1_START (1U << 8) // Start generation +#define I2C_CR1_NOSTRETCH (1U << 7) // Clock stretching disable +#define I2C_CR1_ENGC (1U << 6) // General call enable +#define I2C_CR1_ENPEC (1U << 5) // PEC enable +#define I2C_CR1_ENARP (1U << 4) // ARP enable +#define I2C_CR1_SMBTYPE (1U << 3) // SMBus type +#define I2C_CR1_SMBTYPE_DEVICE (0U << 3) // SMBus type: device +#define I2C_CR1_SMBTYPE_HOST (1U << 3) // SMBus type: host +#define I2C_CR1_SMBUS (1U << 1) // SMBus mode +#define I2C_CR1_SMBUS_I2C (0U << 1) // SMBus mode: I2C +#define I2C_CR1_SMBUS_SMBUS (1U << 1) // SMBus mode: SMBus +#define I2C_CR1_PE (1U << 0) // Peripheral Enable + +/* Control register 2 */ + +#define I2C_CR2_LAST (1U << 12) // DMA last transfer +#define I2C_CR2_DMAEN (1U << 11) // DMA requests enable +#define I2C_CR2_ITBUFEN (1U << 10) // Buffer interrupt enable +#define I2C_CR2_ITEVTEN (1U << 9) // Event interupt enable +#define I2C_CR2_ITERREN (1U << 8) // Error interupt enable +#define I2C_CR2_FREQ 0x3F // Peripheral input frequency + +/* Own address register 1 */ + +#define I2C_OAR1_ADDMODE (1U << 15) // Addressing mode +#define I2C_OAR1_ADDMODE_7_BIT (0U << 15) // Addressing mode: 7-bit +#define I2C_OAR1_ADDMODE_10_BIT (1U << 15) // Addressing mode: 10-bit +#define I2C_OAR1_ADD 0x3FF // Interface address + +/* Own address register 2 */ + +#define I2C_OAR2_ADD2 0xFE // Interface address +#define I2C_OAR2_ENDUAL 1U // Dual addressing mode enable + +/* Status register 1 */ + +#define I2C_SR1_SMBALERT (1U << 15) // SMBus alert +#define I2C_SR1_TIMEOUT (1U << 14) // Timeout or Tlow error +#define I2C_SR1_PECERR (1U << 12) // PEC Error in reception +#define I2C_SR1_OVR (1U << 11) // Overrun/underrun +#define I2C_SR1_AF (1U << 10) // Acknowledge failure +#define I2C_SR1_ARLO (1U << 9) // Arbitration lost +#define I2C_SR1_BERR (1U << 8) // Bus error +#define I2C_SR1_TXE (1U << 7) // Data register empty +#define I2C_SR1_RXNE (1U << 6) // Data register not empty +#define I2C_SR1_STOPF (1U << 4) // Stop detection +#define I2C_SR1_ADD10 (1U << 3) // 10-bit header sent +#define I2C_SR1_BTF (1U << 2) // Byte transfer finished +#define I2C_SR1_ADDR (1U << 1) // Address sent/matched +#define I2C_SR1_SB (1U << 0) // Start bit + +/* Status register 2 */ + +#define I2C_SR2_PEC 0xFF00 // Packet error checking register +#define I2C_SR2_DUALF (1U << 7) // Dual flag +#define I2C_SR2_SMBHOST (1U << 6) // SMBus host header +#define I2C_SR2_SMBDEFAULT (1U << 5) // SMBus device default address +#define I2C_SR2_GENCALL (1U << 4) // General call address +#define I2C_SR2_TRA (1U << 2) // Transmitter/receiver +#define I2C_SR2_BUSY (1U << 1) // Bus busy +#define I2C_SR2_MSL (1U << 0) // Master/slave + +/* Clock control register */ + +#define I2C_CCR_FS (1U << 15) // Fast mode selection +#define I2C_CCR_DUTY (1U << 14) // Fast mode duty cycle +#define I2C_CCR_DUTY_2_1 (0U << 14) // Fast mode duty: 2/1 +#define I2C_CCR_DUTY_16_9 (1U << 14) // Fast mode duty: 16/9 +#define I2C_CCR_CCR 0xFFF // Clock control bits + +/* + * Convenience routines + */ + +/* Main I2C API */ + +/* I2C enable options */ +#define I2C_FAST_MODE 0x1 // 400 khz +#define I2C_DUTY_16_9 0x2 // 16/9 duty ratio +/* Flag 0x4 is reserved; DO NOT USE. */ +#define I2C_BUS_RESET 0x8 // Perform a bus reset +void i2c_master_enable(i2c_dev *dev, uint32 flags); + +#define I2C_ERROR_PROTOCOL (-1) +#define I2C_ERROR_TIMEOUT (-2) +int32 i2c_master_xfer(i2c_dev *dev, i2c_msg *msgs, uint16 num, uint32 timeout); + +void i2c_bus_reset(const i2c_dev *dev); + +/** + * @brief Disable an I2C device + * + * This function disables the corresponding peripheral and marks dev's + * state as I2C_STATE_DISABLED. + * + * @param dev Device to disable. + */ +static inline void i2c_disable(i2c_dev *dev) { + dev->regs->CR1 &= ~I2C_CR1_PE; + dev->state = I2C_STATE_DISABLED; +} + +/* Start/stop conditions */ + +/** + * @brief Generate a start condition on the bus. + * @param dev I2C device + */ +static inline void i2c_start_condition(i2c_dev *dev) { + uint32 cr1; + while ((cr1 = dev->regs->CR1) & (I2C_CR1_START | + I2C_CR1_STOP | + I2C_CR1_PEC)) { + ; + } + dev->regs->CR1 |= I2C_CR1_START; +} + +/** + * @brief Generate a stop condition on the bus + * @param dev I2C device + */ +static inline void i2c_stop_condition(i2c_dev *dev) { + uint32 cr1; + while ((cr1 = dev->regs->CR1) & (I2C_CR1_START | + I2C_CR1_STOP | + I2C_CR1_PEC)) { + ; + } + dev->regs->CR1 |= I2C_CR1_STOP; + while ((cr1 = dev->regs->CR1) & (I2C_CR1_START | + I2C_CR1_STOP | + I2C_CR1_PEC)) { + ; + } + +} + +/* IRQ enable/disable */ + +#ifndef _I2C_HAVE_IRQ_FIXUP +/* The series header provides this if _I2C_HAVE_IRQ_FIXUP is defined, + * but we need it either way. */ +#define _i2c_irq_priority_fixup(dev) ((void)0) +#endif + +#define I2C_IRQ_ERROR I2C_CR2_ITERREN +#define I2C_IRQ_EVENT I2C_CR2_ITEVTEN +#define I2C_IRQ_BUFFER I2C_CR2_ITBUFEN +/** + * @brief Enable one or more I2C interrupts + * @param dev I2C device + * @param irqs Bitwise or of: + * I2C_IRQ_ERROR (error interrupt), + * I2C_IRQ_EVENT (event interrupt), and + * I2C_IRQ_BUFFER (buffer interrupt). + */ +static inline void i2c_enable_irq(i2c_dev *dev, uint32 irqs) { + _i2c_irq_priority_fixup(dev); + dev->regs->CR2 |= irqs; +} + +/** + * @brief Disable one or more I2C interrupts + * @param dev I2C device + * @param irqs Bitwise or of: + * I2C_IRQ_ERROR (error interrupt), + * I2C_IRQ_EVENT (event interrupt), and + * I2C_IRQ_BUFFER (buffer interrupt). + */ +static inline void i2c_disable_irq(i2c_dev *dev, uint32 irqs) { + dev->regs->CR2 &= ~irqs; +} + +/* ACK/NACK */ + +/** + * @brief Enable I2C acknowledgment + * @param dev I2C device + */ +static inline void i2c_enable_ack(i2c_dev *dev) { + dev->regs->CR1 |= I2C_CR1_ACK; +} + +/** + * @brief Disable I2C acknowledgment + * @param dev I2C device + */ +static inline void i2c_disable_ack(i2c_dev *dev) { + dev->regs->CR1 &= ~I2C_CR1_ACK; +} + +/* GPIO control */ + +/** + * @brief Configure device GPIOs. + * + * Configure GPIO bits dev->sda_pin and dev->scl_pin on GPIO device + * dev->gpio_port for use with I2C device dev. + * + * @param dev I2C Device + * @see i2c_release_gpios() + */ +extern void i2c_config_gpios(const i2c_dev *dev); + +/** + * @brief Release GPIOs controlling an I2C bus + * + * Releases the I2C bus controlled by dev as master, and disconnects + * GPIO bits dev->sda_pin and dev->scl_pin on GPIO device + * dev->gpio_port from I2C device dev. + * + * @param dev I2C device + * @see i2c_config_gpios() + */ +extern void i2c_master_release_bus(const i2c_dev *dev); + +/* Miscellaneous low-level routines */ + +void i2c_init(i2c_dev *dev); + +/** + * @brief Turn on an I2C peripheral + * @param dev Device to enable + */ +static inline void i2c_peripheral_enable(i2c_dev *dev) { + dev->regs->CR1 |= I2C_CR1_PE; +} + +/** + * @brief Turn off an I2C peripheral + * @param dev Device to turn off + */ +static inline void i2c_peripheral_disable(i2c_dev *dev) { + dev->regs->CR1 &= ~I2C_CR1_PE; +} + +/** + * @brief Fill transmit register + * @param dev I2C device + * @param byte Byte to write + */ +static inline void i2c_write(i2c_dev *dev, uint8 byte) { + dev->regs->DR = byte; +} + +/** + * @brief Set input clock frequency, in MHz + * @param dev I2C device + * @param freq Frequency, in MHz. This must be at least 2, and at most + * the APB frequency of dev's bus. (For example, if + * rcc_dev_clk(dev) == RCC_APB1, freq must be at most + * PCLK1, in MHz). There is an additional limit of 46 MHz. + */ +static inline void i2c_set_input_clk(i2c_dev *dev, uint32 freq) { +#define I2C_MAX_FREQ_MHZ 46 + ASSERT(2 <= freq && freq <= _i2c_bus_clk(dev) && freq <= I2C_MAX_FREQ_MHZ); + uint32 cr2 = dev->regs->CR2; + cr2 &= ~I2C_CR2_FREQ; + cr2 |= freq; + dev->regs->CR2 = freq; +#undef I2C_MAX_FREQ_MHZ +} + +/** + * @brief Set I2C clock control register. + * + * See the chip reference manual for the details. + * + * @param dev I2C device + * @param val Value to use for clock control register (in + * Fast/Standard mode) + */ +static inline void i2c_set_clk_control(i2c_dev *dev, uint32 val) { + uint32 ccr = dev->regs->CCR; + ccr &= ~I2C_CCR_CCR; + ccr |= val; + dev->regs->CCR = ccr; +} + +/** + * @brief Set SCL rise time + * @param dev I2C device + * @param trise Maximum rise time in fast/standard mode (see chip + * reference manual for the relevant formulas). + */ +static inline void i2c_set_trise(i2c_dev *dev, uint32 trise) { + dev->regs->TRISE = trise; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/i2c_common.h b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/i2c_common.h new file mode 100644 index 0000000..17cabe3 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/i2c_common.h @@ -0,0 +1,93 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Perry Hung (from ). + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/include/libmaple/i2c_common.h + * @author Marti Bolivar + * @brief This file is an implementation detail + * + * CONTENTS UNSTABLE. The existence of this file is an implementation + * detail. Never include it directly. If you need something from + * here, include instead. + */ + +#ifndef _LIBMAPLE_I2C_COMMON_H_ +#define _LIBMAPLE_I2C_COMMON_H_ + +#include +#include +#include + +struct gpio_dev; +struct i2c_reg_map; +struct i2c_msg; + +/** I2C device states */ +typedef enum i2c_state { + I2C_STATE_DISABLED = 0, /**< Disabled */ + I2C_STATE_IDLE = 1, /**< Idle */ + I2C_STATE_XFER_DONE = 2, /**< Done with transfer */ + I2C_STATE_BUSY = 3, /**< Busy */ + I2C_STATE_ERROR = -1 /**< Error occurred */ +} i2c_state; + +/** + * @brief I2C device type. + */ +typedef struct i2c_dev { + struct i2c_reg_map *regs; /**< Register map */ + struct i2c_msg *msg; /**< Messages */ + uint32 error_flags; /**< Error flags, set on I2C error condition */ + volatile uint32 timestamp; /**< For internal use */ + + /** + * @brief Deprecated. Use .scl_port or .sda_port instead. + * If non-null, this will be used as SDA, SCL pins' GPIO port. If + * null, then .sda_port will be used for SDA, and .sda_port for + * SDA. */ + struct gpio_dev *gpio_port; + + /** + * @brief SDA GPIO device (but see .gpio_port). + */ + struct gpio_dev *sda_port; + + /** + * @brief SCL GPIO device (but see .gpio_port). + */ + struct gpio_dev *scl_port; + + uint16 msgs_left; /**< Messages left */ + uint8 sda_pin; /**< SDA bit on gpio_port */ + uint8 scl_pin; /**< SCL bit on gpio_port */ + rcc_clk_id clk_id; /**< RCC clock information */ + nvic_irq_num ev_nvic_line; /**< Event IRQ number */ + nvic_irq_num er_nvic_line; /**< Error IRQ number */ + volatile i2c_state state; /**< Device state */ +} i2c_dev; + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/iwdg.h b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/iwdg.h new file mode 100644 index 0000000..3a16c55 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/iwdg.h @@ -0,0 +1,115 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Michael Hope. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/include/libmaple/iwdg.h + * @author Michael Hope, Marti Bolivar + * @brief Independent watchdog support. + * + * To use the independent watchdog, first call iwdg_init() with the + * appropriate prescaler and IWDG counter reload values for your + * application. Afterwards, you must periodically call iwdg_feed() + * before the IWDG counter reaches 0 to reset the counter to its + * reload value. If you do not, the chip will reset. + * + * Once started, the independent watchdog cannot be turned off. + */ + +#ifndef _LIBMAPLE_IWDG_H_ +#define _LIBMAPLE_IWDG_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include + +/* + * Register map + */ + +/** Independent watchdog register map type. */ +typedef struct iwdg_reg_map { + __io uint32 KR; /**< Key register. */ + __io uint32 PR; /**< Prescaler register. */ + __io uint32 RLR; /**< Reload register. */ + __io uint32 SR; /**< Status register */ +} iwdg_reg_map; + +/** Independent watchdog base pointer */ +#define IWDG_BASE ((struct iwdg_reg_map*)0x40003000) + +/* + * Register bit definitions + */ + +/* Key register */ + +#define IWDG_KR_UNLOCK 0x5555 +#define IWDG_KR_FEED 0xAAAA +#define IWDG_KR_START 0xCCCC + +/* Prescaler register */ + +#define IWDG_PR_DIV_4 0x0 +#define IWDG_PR_DIV_8 0x1 +#define IWDG_PR_DIV_16 0x2 +#define IWDG_PR_DIV_32 0x3 +#define IWDG_PR_DIV_64 0x4 +#define IWDG_PR_DIV_128 0x5 +#define IWDG_PR_DIV_256 0x6 + +/* Status register */ + +#define IWDG_SR_RVU_BIT 1 +#define IWDG_SR_PVU_BIT 0 + +#define IWDG_SR_RVU (1U << IWDG_SR_RVU_BIT) +#define IWDG_SR_PVU (1U << IWDG_SR_PVU_BIT) + +/** + * @brief Independent watchdog prescalers. + * + * These divide the 40 kHz IWDG clock. + */ +typedef enum iwdg_prescaler { + IWDG_PRE_4 = IWDG_PR_DIV_4, /**< Divide by 4 */ + IWDG_PRE_8 = IWDG_PR_DIV_8, /**< Divide by 8 */ + IWDG_PRE_16 = IWDG_PR_DIV_16, /**< Divide by 16 */ + IWDG_PRE_32 = IWDG_PR_DIV_32, /**< Divide by 32 */ + IWDG_PRE_64 = IWDG_PR_DIV_64, /**< Divide by 64 */ + IWDG_PRE_128 = IWDG_PR_DIV_128, /**< Divide by 128 */ + IWDG_PRE_256 = IWDG_PR_DIV_256 /**< Divide by 256 */ +} iwdg_prescaler; + +void iwdg_init(iwdg_prescaler prescaler, uint16 reload); +void iwdg_feed(void); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/libmaple.h b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/libmaple.h new file mode 100644 index 0000000..c9034d7 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/libmaple.h @@ -0,0 +1,48 @@ +/****************************************************************************** + * 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/include/libmaple/libmaple.h + * @brief General include file for libmaple + */ + +#ifndef _LIBMAPLE_LIBMAPLE_H_ +#define _LIBMAPLE_LIBMAPLE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/libmaple_types.h b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/libmaple_types.h new file mode 100644 index 0000000..398b705 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/libmaple_types.h @@ -0,0 +1,79 @@ +/****************************************************************************** + * 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/include/libmaple/libmaple_types.h + * + * @brief libmaple's types, and operations on types. + */ + +#ifndef _LIBMAPLE_LIBMAPLE_TYPES_H_ +#define _LIBMAPLE_LIBMAPLE_TYPES_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef uint32_t uint32; +typedef unsigned long long uint64; + +typedef signed char int8; +typedef short int16; +typedef int int32; +typedef long long int64; + +typedef void (*voidFuncPtr)(void); +typedef void (*voidArgumentFuncPtr)(void *); + +#define __io volatile +#define __attr_flash __attribute__((section (".USER_FLASH"))) +#define __packed __attribute__((__packed__)) +#define __deprecated __attribute__((__deprecated__)) +#define __weak __attribute__((weak)) +#ifndef __always_inline +#define __always_inline __attribute__((always_inline)) +#endif +#ifndef __unused +#define __unused __attribute__((unused)) +#endif + +#ifndef NULL +#define NULL 0 +#endif + +#ifndef offsetof +#define offsetof(type, member) __builtin_offsetof(type, member) +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/nvic.h b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/nvic.h new file mode 100644 index 0000000..69d9a91 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/nvic.h @@ -0,0 +1,157 @@ +/****************************************************************************** + * 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/include/libmaple/nvic.h + * @brief Nested vectored interrupt controller support. + * + * Basic usage: + * + * @code + * // Initialise the interrupt controller and point to the vector + * // table at the start of flash. + * nvic_init(0x08000000, 0); + * // Bind in a timer interrupt handler + * timer_attach_interrupt(TIMER_CC1_INTERRUPT, handler); + * // Optionally set the priority + * nvic_irq_set_priority(NVIC_TIMER1_CC, 5); + * // All done, enable all interrupts + * nvic_globalirq_enable(); + * @endcode + */ + +#ifndef _LIBMAPLE_NVIC_H_ +#define _LIBMAPLE_NVIC_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include +#include + +/** NVIC register map type. */ +typedef struct nvic_reg_map { + __io uint32 ISER[8]; /**< Interrupt Set Enable Registers */ + /** Reserved */ + uint32 RESERVED0[24]; + + __io uint32 ICER[8]; /**< Interrupt Clear Enable Registers */ + /** Reserved */ + uint32 RESERVED1[24]; + + __io uint32 ISPR[8]; /**< Interrupt Set Pending Registers */ + /** Reserved */ + uint32 RESERVED2[24]; + + __io uint32 ICPR[8]; /**< Interrupt Clear Pending Registers */ + /** Reserved */ + uint32 RESERVED3[24]; + + __io uint32 IABR[8]; /**< Interrupt Active bit Registers */ + /** Reserved */ + uint32 RESERVED4[56]; + + __io uint8 IP[240]; /**< Interrupt Priority Registers */ + /** Reserved */ + uint32 RESERVED5[644]; + + __io uint32 STIR; /**< Software Trigger Interrupt Registers */ +} nvic_reg_map; + +/** NVIC register map base pointer. */ +#define NVIC_BASE ((struct nvic_reg_map*)0xE000E100) + +/* + * Note: The series header must define enum nvic_irq_num, which gives + * descriptive names to the interrupts and exceptions from NMI (-14) + * to the largest interrupt available in the series, where the value + * for nonnegative enumerators corresponds to its position in the + * vector table. + * + * It also must define a static inline nvic_irq_disable_all(), which + * writes 0xFFFFFFFF to all ICE registers available in the series. (We + * place the include here to give the series header access to + * NVIC_BASE, in order to let it do so). + */ + +/* Roger clark. Replaced with line below #include */ +#include "stm32f1/include/series/nvic.h" + +void nvic_init(uint32 address, uint32 offset); +void nvic_set_vector_table(uint32 address, uint32 offset); +void nvic_irq_set_priority(nvic_irq_num irqn, uint8 priority); +void nvic_sys_reset(); + +/** + * Enables interrupts and configurable fault handlers (clear PRIMASK). + */ +static inline __always_inline void nvic_globalirq_enable() { + asm volatile("cpsie i"); +} + +/** + * Disable interrupts and configurable fault handlers (set PRIMASK). + */ +static inline __always_inline void nvic_globalirq_disable() { + asm volatile("cpsid i"); +} + +/** + * @brief Enable interrupt irq_num + * @param irq_num Interrupt to enable + */ +static inline void nvic_irq_enable(nvic_irq_num irq_num) { + if (irq_num < 0) { + return; + } + NVIC_BASE->ISER[irq_num / 32] = BIT(irq_num % 32); +} + +/** + * @brief Disable interrupt irq_num + * @param irq_num Interrupt to disable + */ +static inline void nvic_irq_disable(nvic_irq_num irq_num) { + if (irq_num < 0) { + return; + } + NVIC_BASE->ICER[irq_num / 32] = BIT(irq_num % 32); +} + +/** + * @brief Quickly disable all interrupts. + * + * Calling this function is significantly faster than calling + * nvic_irq_disable() in a loop. + */ +static inline void nvic_irq_disable_all(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/pwr.h b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/pwr.h new file mode 100644 index 0000000..f711c7c --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/pwr.h @@ -0,0 +1,117 @@ +/****************************************************************************** + * 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/include/libmaple/pwr.h + * @brief Power control (PWR). + */ + +#ifndef _LIBMAPLE_PWR_H_ +#define _LIBMAPLE_PWR_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + /* Roger clark. Replaced with line below #include */ +#include "stm32f1/include/series/pwr.h" + + +/** Power interface register map. */ +typedef struct pwr_reg_map { + __io uint32 CR; /**< Control register */ + __io uint32 CSR; /**< Control and status register */ +} pwr_reg_map; + +/** Power peripheral register map base pointer. */ +#define PWR_BASE ((struct pwr_reg_map*)0x40007000) + +/* + * Register bit definitions + */ + +/* Control register */ + +/** Disable backup domain write protection bit */ +#define PWR_CR_DBP_BIT 8 +/** Power voltage detector enable bit */ +#define PWR_CR_PVDE_BIT 4 +/** Clear standby flag bit */ +#define PWR_CR_CSBF_BIT 3 +/** Clear wakeup flag bit */ +#define PWR_CR_CWUF_BIT 2 +/** Power down deepsleep bit */ +#define PWR_CR_PDDS_BIT 1 +/** Low-power deepsleep bit */ +#define PWR_CR_LPDS_BIT 0 + +/** Disable backup domain write protection */ +#define PWR_CR_DBP (1U << PWR_CR_DBP_BIT) +/** Power voltage detector (PVD) level selection */ +#define PWR_CR_PLS (0x7 << 5) +/** Power voltage detector enable */ +#define PWR_CR_PVDE (1U << PWR_CR_PVDE_BIT) +/** Clear standby flag */ +#define PWR_CR_CSBF (1U << PWR_CR_CSBF_BIT) +/** Clear wakeup flag */ +#define PWR_CR_CWUF (1U << PWR_CR_CWUF_BIT) +/** Power down deepsleep */ +#define PWR_CR_PDDS (1U << PWR_CR_PDDS_BIT) +/** Low-power deepsleep */ +#define PWR_CR_LPDS (1U << PWR_CR_LPDS_BIT) + +/* Control and status register */ + +/** Enable wakeup pin bit */ +#define PWR_CSR_EWUP_BIT 8 +/** PVD output bit */ +#define PWR_CSR_PVDO_BIT 2 +/** Standby flag bit */ +#define PWR_CSR_SBF_BIT 1 +/** Wakeup flag bit */ +#define PWR_CSR_WUF_BIT 0 + +/** Enable wakeup pin */ +#define PWR_CSR_EWUP (1U << PWR_CSR_EWUP_BIT) +/** PVD output */ +#define PWR_CSR_PVDO (1U << PWR_CSR_PVDO_BIT) +/** Standby flag */ +#define PWR_CSR_SBF (1U << PWR_CSR_SBF_BIT) +/** Wakeup flag */ +#define PWR_CSR_WUF (1U << PWR_CSR_WUF_BIT) + +/* + * Convenience functions + */ + +void pwr_init(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/rcc.h b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/rcc.h new file mode 100644 index 0000000..27d48fb --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/rcc.h @@ -0,0 +1,182 @@ +/****************************************************************************** + * 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/include/libmaple/rcc.h + * @brief Reset and Clock Control (RCC) interface. + */ + +#ifndef _LIBMAPLE_RCC_H_ +#define _LIBMAPLE_RCC_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include + +/* Put the SYSCLK sources before the series header is included, as it + * might need them. */ +/** + * @brief SYSCLK sources + * @see rcc_switch_sysclk() + */ +typedef enum rcc_sysclk_src { + RCC_CLKSRC_HSI = 0x0, + RCC_CLKSRC_HSE = 0x1, + RCC_CLKSRC_PLL = 0x2, +} rcc_sysclk_src; + +/* Roger clark. Replaced with line below #include */ +#include "stm32f1/include/series/rcc.h" + +/* Note: Beyond the usual (registers, etc.), it's up to the series + * header to define the following types: + * + * - enum rcc_clk: Available system and secondary clock sources, + * e.g. RCC_CLK_HSE, RCC_CLK_PLL, RCC_CLK_LSE. + * + * Note that the inclusion of secondary clock sources (like LSI and + * LSE) makes enum rcc_clk different from the SYSCLK sources, which + * are defined in this header as enum rcc_sysclk_src. + * + * IMPORTANT NOTE TO IMPLEMENTORS: If you are adding support for a + * new STM32 series, see the comment near rcc_clk_reg() in + * libmaple/rcc.c for information on how to choose these values so + * that rcc_turn_on_clk() etc. will work on your series. + * + * - enum rcc_clk_id: For each available peripheral. These are widely used + * as unique IDs (TODO extricate from RCC?). Peripherals which are + * common across STM32 series should use the same token for their + * rcc_clk_id in each series header. + * + * - enum rcc_clk_domain: For each clock domain. This is returned by + * rcc_dev_clk(). For instance, each AHB and APB is a clock domain. + * + * - enum rcc_prescaler: And a suitable set of dividers for + * rcc_set_prescaler(). + * + * - enum rcc_pllsrc: For each PLL source. Same source, same token. + * + * - A target-dependent type to be pointed to by the data field in a + * struct rcc_pll_cfg. + */ + +#ifdef __DOXYGEN__ +/** RCC register map base pointer */ +#define RCC_BASE +#endif + +/* Clock prescaler management. */ + +/** + * @brief Set the divider on a peripheral prescaler + * @param prescaler prescaler to set + * @param divider prescaler divider + */ +extern void rcc_set_prescaler(rcc_prescaler prescaler, uint32 divider); + +/* SYSCLK. */ + +void rcc_switch_sysclk(rcc_sysclk_src sysclk_src); + +/* PLL configuration */ + +/** + * @brief Specifies a configuration for the main PLL. + */ +typedef struct rcc_pll_cfg { + rcc_pllsrc pllsrc; /**< PLL source */ + + /** Series-specific configuration data. */ + void *data; +} rcc_pll_cfg; + +/** + * @brief Configure the main PLL. + * + * You may only call this function while the PLL is disabled. + * + * @param pll_cfg Desired PLL configuration. The contents of this + * struct depend entirely on the target. + */ +extern void rcc_configure_pll(rcc_pll_cfg *pll_cfg); + +/* System and secondary clock sources. */ + +void rcc_turn_on_clk(rcc_clk clock); +void rcc_turn_off_clk(rcc_clk clock); +int rcc_is_clk_on(rcc_clk clock); +int rcc_is_clk_ready(rcc_clk clock); + +/* Peripheral clock lines and clock domains. */ + +/** + * @brief Turn on the clock line on a peripheral + * @param id Clock ID of the peripheral to turn on. + */ +extern void rcc_clk_enable(rcc_clk_id id); + +/** + * @brief Reset a peripheral. + * + * Caution: not all rcc_clk_id values refer to a peripheral which can + * be reset. (Only rcc_clk_ids for peripherals with bits in an RCC + * reset register can be used here.) + * + * @param id Clock ID of the peripheral to reset. + */ +extern void rcc_reset_dev(rcc_clk_id id); + +rcc_clk_domain rcc_dev_clk(rcc_clk_id id); + +/* Clock security system */ + +/** + * @brief Enable the clock security system (CSS). + */ +static inline void rcc_enable_css() { + RCC_BASE->CR |= RCC_CR_CSSON; +} + +/** + * @brief Disable the clock security system (CSS). + */ +static inline void rcc_disable_css() { + RCC_BASE->CR &= ~RCC_CR_CSSON; +} + +/** + * @brief Turn off the clock line on a peripheral + * @param id Clock ID of the peripheral to turn on. + */ +extern void rcc_clk_disable(rcc_clk_id id); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/ring_buffer.h b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/ring_buffer.h new file mode 100644 index 0000000..e99fe62 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/ring_buffer.h @@ -0,0 +1,208 @@ +/****************************************************************************** + * 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/include/libmaple/ring_buffer.h + * @brief Simple circular buffer + * + * This implementation is not thread-safe. In particular, none of + * these functions is guaranteed re-entrant. + */ + +#ifndef _LIBMAPLE_RING_BUFFER_H_ +#define _LIBMAPLE_RING_BUFFER_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include + +/** + * Ring buffer type. + * + * The buffer is empty when head == tail. + * + * The buffer is full when the head is one byte in front of the tail, + * modulo buffer length. + * + * One byte is left free to distinguish empty from full. */ +typedef struct ring_buffer { + volatile uint8 *buf; /**< Buffer items are stored into */ + volatile uint16 head; /**< Index of the next item to remove */ + volatile uint16 tail; /**< Index where the next item will get inserted */ + volatile uint16 size; /**< Buffer capacity minus one */ +} ring_buffer; + +/** + * Initialise a ring buffer. + * + * @param rb Instance to initialise + * + * @param size Number of items in buf. The ring buffer will always + * leave one element unoccupied, so the maximum number of + * elements it can store will be size - 1. Thus, size + * must be at least 2. + * + * @param buf Buffer to store items into + */ +static inline void rb_init(ring_buffer *rb, uint16 size, uint8 *buf) { + rb->head = 0; + rb->tail = 0; + rb->size = size - 1; + rb->buf = buf; +} + +/** + * @brief Return the number of elements stored in the ring buffer. + * @param rb Buffer whose elements to count. + */ +static inline uint16 rb_full_count(ring_buffer *rb) { + __io ring_buffer *arb = rb; + int32 size = arb->tail - arb->head; + if (arb->tail < arb->head) { + size += arb->size + 1; + } + return (uint16)size; +} + +/** + * @brief Returns true if and only if the ring buffer is full. + * @param rb Buffer to test. + */ +static inline int rb_is_full(ring_buffer *rb) { + return (rb->tail + 1 == rb->head) || + (rb->tail == rb->size && rb->head == 0); +} + +/** + * @brief Returns true if and only if the ring buffer is empty. + * @param rb Buffer to test. + */ +static inline int rb_is_empty(ring_buffer *rb) { + return rb->head == rb->tail; +} + +/** + * Append element onto the end of a ring buffer. + * @param rb Buffer to append onto. + * @param element Value to append. + */ +static inline void rb_insert(ring_buffer *rb, uint8 element) { + rb->buf[rb->tail] = element; + rb->tail = (rb->tail == rb->size) ? 0 : rb->tail + 1; +} + +/** + * @brief Remove and return the first item from a ring buffer. + * @param rb Buffer to remove from, must contain at least one element. + */ +static inline uint8 rb_remove(ring_buffer *rb) { + uint8 ch = rb->buf[rb->head]; + rb->head = (rb->head == rb->size) ? 0 : rb->head + 1; + return ch; +} + +/* + * Roger Clark. 20141125, + * added peek function. + * @brief Return the first item from a ring buffer, without removing it + * @param rb Buffer to remove from, must contain at least one element. + */ + +static inline int rb_peek(ring_buffer *rb) +{ + if (rb->head == rb->tail) + { + return -1; + } + else + { + return rb->buf[rb->head]; + } +} + + +/** + * @brief Attempt to remove the first item from a ring buffer. + * + * If the ring buffer is nonempty, removes and returns its first item. + * If it is empty, does nothing and returns a negative value. + * + * @param rb Buffer to attempt to remove from. + */ +static inline int16 rb_safe_remove(ring_buffer *rb) { + return rb_is_empty(rb) ? -1 : rb_remove(rb); +} + +/** + * @brief Attempt to insert an element into a ring buffer. + * + * @param rb Buffer to insert into. + * @param element Value to insert into rb. + * @sideeffect If rb is not full, appends element onto buffer. + * @return If element was appended, then true; otherwise, false. */ +static inline int rb_safe_insert(ring_buffer *rb, uint8 element) { + if (rb_is_full(rb)) { + return 0; + } + rb_insert(rb, element); + return 1; +} + +/** + * @brief Append an item onto the end of a non-full ring buffer. + * + * If the buffer is full, removes its first item, then inserts the new + * element at the end. + * + * @param rb Ring buffer to insert into. + * @param element Value to insert into ring buffer. + * @return On success, returns -1. If an element was popped, returns + * the popped value. + */ +static inline int rb_push_insert(ring_buffer *rb, uint8 element) { + int ret = -1; + if (rb_is_full(rb)) { + ret = rb_remove(rb); + } + rb_insert(rb, element); + return ret; +} + +/** + * @brief Discard all items from a ring buffer. + * @param rb Ring buffer to discard all items from. + */ +static inline void rb_reset(ring_buffer *rb) { + rb->tail = rb->head; +} + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/scb.h b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/scb.h new file mode 100644 index 0000000..c42a0f2 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/scb.h @@ -0,0 +1,214 @@ +/****************************************************************************** + * 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 + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/include/libmaple/scb.h + * @brief System control block header + */ + +/* + * FIXME: STM32F2? + */ + +#ifndef _LIBMAPLE_SCB_H_ +#define _LIBMAPLE_SCB_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* + * Register map and base pointer + */ + +/** System control block register map type */ +typedef struct scb_reg_map { + __io uint32 CPUID; /**< CPU ID Base Register */ + __io uint32 ICSR; /**< Interrupt Control State Register */ + __io uint32 VTOR; /**< Vector Table Offset Register */ + __io uint32 AIRCR; /**< Application Interrupt / Reset Control Register */ + __io uint32 SCR; /**< System Control Register */ + __io uint32 CCR; /**< Configuration and Control Register */ + __io uint8 SHP[12]; /**< System Handler Priority Registers + (4-7, 8-11, 12-15) */ + __io uint32 SHCSR; /**< System Handler Control and State Register */ + __io uint32 CFSR; /**< Configurable Fault Status Register */ + __io uint32 HFSR; /**< Hard Fault Status Register */ + /* DFSR is not documented by ST in PM0056 (as of Revision 4), but + * there's a 4 byte hole in the SCB register map docs right where + * it belongs. Since it's specified as "always implemented" in + * the ARM v7-M ARM, I'm assuming its absence is a bug in the ST + * doc, but I haven't proven it. [mbolivar] */ + __io uint32 DFSR; /**< Debug Fault Status Register */ + __io uint32 MMFAR; /**< Mem Manage Address Register */ + __io uint32 BFAR; /**< Bus Fault Address Register */ +#if 0 + /* The following registers are implementation-defined according to + * ARM v7-M, and I can't find evidence of their existence in ST's + * docs. I'm removing them. Feel free to yell at me if they do + * exist. [mbolivar] + */ + __io uint32 AFSR; /**< Auxiliary Fault Status Register */ + __io uint32 PFR[2]; /**< Processor Feature Register */ + __io uint32 DFR; /**< Debug Feature Register */ + __io uint32 AFR; /**< Auxiliary Feature Register */ + __io uint32 MMFR[4]; /**< Memory Model Feature Register */ + __io uint32 ISAR[5]; /**< ISA Feature Register */ +#endif +} scb_reg_map; + +/** System control block register map base pointer */ +#define SCB_BASE ((struct scb_reg_map*)0xE000ED00) + +/* + * Register bit definitions + */ + +/* No SCB_REG_FIELD_BIT macros as the relevant addresses are not in a + * bit-band region. */ + +/* CPUID base register (SCB_CPUID) */ + +#define SCB_CPUID_IMPLEMENTER (0xFF << 24) +#define SCB_CPUID_VARIANT (0xF << 20) +#define SCB_CPUID_CONSTANT (0xF << 16) +#define SCB_CPUID_PARTNO (0xFFF << 4) +#define SCB_CPUID_REVISION 0xF + +/* Interrupt control state register (SCB_ICSR) */ + +#define SCB_ICSR_NMIPENDSET (1U << 31) +#define SCB_ICSR_PENDSVSET (1U << 28) +#define SCB_ICSR_PENDSVCLR (1U << 27) +#define SCB_ICSR_PENDSTSET (1U << 26) +#define SCB_ICSR_PENDSTCLR (1U << 25) +#define SCB_ICSR_ISRPENDING (1U << 22) +#define SCB_ICSR_VECTPENDING (0x3FF << 12) +#define SCB_ICSR_RETOBASE (1U << 11) +#define SCB_ICSR_VECTACTIVE 0xFF + +/* Vector table offset register (SCB_VTOR) */ + +#define SCB_VTOR_TBLOFF (0x1FFFFF << 9) + +/* Application interrupt and reset control register (SCB_AIRCR) */ + +#define SCB_AIRCR_VECTKEYSTAT (0x5FA << 16) +#define SCB_AIRCR_VECTKEY (0x5FA << 16) +#define SCB_AIRCR_ENDIANNESS (1U << 15) +#define SCB_AIRCR_PRIGROUP (0x3 << 8) +#define SCB_AIRCR_SYSRESETREQ (1U << 2) +#define SCB_AIRCR_VECTCLRACTIVE (1U << 1) +#define SCB_AIRCR_VECTRESET (1U << 0) + +/* System control register (SCB_SCR) */ + +#define SCB_SCR_SEVONPEND (1U << 4) +#define SCB_SCR_SLEEPDEEP (1U << 2) +#define SCB_SCR_SLEEPONEXIT (1U << 1) + +/* Configuration and Control Register (SCB_CCR) */ + +#define SCB_CCR_STKALIGN (1U << 9) +#define SCB_CCR_BFHFNMIGN (1U << 8) +#define SCB_CCR_DIV_0_TRP (1U << 4) +#define SCB_CCR_UNALIGN_TRP (1U << 3) +#define SCB_CCR_USERSETMPEND (1U << 1) +#define SCB_CCR_NONBASETHRDENA (1U << 0) + +/* System handler priority registers (SCB_SHPRx) */ + +#define SCB_SHPR1_PRI6 (0xFF << 16) +#define SCB_SHPR1_PRI5 (0xFF << 8) +#define SCB_SHPR1_PRI4 0xFF + +#define SCB_SHPR2_PRI11 (0xFF << 24) + +#define SCB_SHPR3_PRI15 (0xFF << 24) +#define SCB_SHPR3_PRI14 (0xFF << 16) + +/* System Handler Control and state register (SCB_SHCSR) */ + +#define SCB_SHCSR_USGFAULTENA (1U << 18) +#define SCB_SHCSR_BUSFAULTENA (1U << 17) +#define SCB_SHCSR_MEMFAULTENA (1U << 16) +#define SCB_SHCSR_SVCALLPENDED (1U << 15) +#define SCB_SHCSR_BUSFAULTPENDED (1U << 14) +#define SCB_SHCSR_MEMFAULTPENDED (1U << 13) +#define SCB_SHCSR_USGFAULTPENDED (1U << 12) +#define SCB_SHCSR_SYSTICKACT (1U << 11) +#define SCB_SHCSR_PENDSVACT (1U << 10) +#define SCB_SHCSR_MONITORACT (1U << 8) +#define SCB_SHCSR_SVCALLACT (1U << 7) +#define SCB_SHCSR_USGFAULTACT (1U << 3) +#define SCB_SHCSR_BUSFAULTACT (1U << 1) +#define SCB_SHCSR_MEMFAULTACT (1U << 0) + +/* Configurable fault status register (SCB_CFSR) */ + +#define SCB_CFSR_DIVBYZERO (1U << 25) +#define SCB_CFSR_UNALIGNED (1U << 24) +#define SCB_CFSR_NOCP (1U << 19) +#define SCB_CFSR_INVPC (1U << 18) +#define SCB_CFSR_INVSTATE (1U << 17) +#define SCB_CFSR_UNDEFINSTR (1U << 16) +#define SCB_CFSR_BFARVALID (1U << 15) +#define SCB_CFSR_STKERR (1U << 12) +#define SCB_CFSR_UNSTKERR (1U << 11) +#define SCB_CFSR_IMPRECISERR (1U << 10) +#define SCB_CFSR_PRECISERR (1U << 9) +#define SCB_CFSR_IBUSERR (1U << 8) +#define SCB_CFSR_MMARVALID (1U << 7) +#define SCB_CFSR_MSTKERR (1U << 4) +#define SCB_CFSR_MUNSTKERR (1U << 3) +#define SCB_CFSR_DACCVIOL (1U << 1) +#define SCB_CFSR_IACCVIOL (1U << 0) + +/* Hard Fault Status Register (SCB_HFSR) */ + +#define SCB_HFSR_DEBUG_VT (1U << 31) +#define SCB_CFSR_FORCED (1U << 30) +#define SCB_CFSR_VECTTBL (1U << 1) + +/* Debug Fault Status Register */ + +/* Not specified by PM0056, but required by ARM. The bit definitions + * here are based on the names given in the ARM v7-M ARM. */ + +#define SCB_DFSR_EXTERNAL (1U << 4) +#define SCB_DFSR_VCATCH (1U << 3) +#define SCB_DFSR_DWTTRAP (1U << 2) +#define SCB_DFSR_BKPT (1U << 1) +#define SCB_DFSR_HALTED (1U << 0) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/sdio.h b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/sdio.h new file mode 100644 index 0000000..dec31c8 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/sdio.h @@ -0,0 +1,270 @@ +/****************************************************************************** + * + * 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 sdio.h + * @brief Secure digital input/output interface. + */ + +#ifndef _SDIO_H_ +#define _SDIO_H_ + +#include +#include +#include + + +/* +#include +#include + +//#include +#include +//#include + */ + +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) + +/* + * DMA controller and channel used in STM32F103 + */ + +#define SDIO_DMA_DEV DMA2 +#define SDIO_DMA_CHANNEL DMA_CH4 +/* +#ifdef __cplusplus +extern "C" { +#endif +*/ + +/* + * Register maps and devices + */ + +// SDIO register map type +typedef struct sdio_reg_map { + __io uint32 POWER; // 0x00 + __io uint32 CLKCR; // 0x04 + __io uint32 ARG; // 0x08 + __io uint32 CMD; // 0x0C + __io uint32 RESPCMD; // 0x10 (0x3F) + const uint32 RESP[4]; // 0x14 - contain the card status, which is part of the received response. + __io uint32 DTIMER; // 0x24 - contains the data timeout period, in card bus clock periods. + __io uint32 DLEN; // 0x28 (0x01FF FFFF) - contains the number of data bytes to be transferred + __io uint32 DCTRL; // 0x2C + __io uint32 DCOUNT; // 0x30 (0x01FF FFFF) + __io uint32 STA; // 0x34 + __io uint32 ICR; // 0x38 + __io uint32 MASK; // 0x3C + const uint32 RESERVED1[2]; + __io uint32 FIFOCNT; // 0x48 (0x01FF FFFF) + const uint32 RESERVED2[13]; + __io uint32 FIFO; // 0x80 +} sdio_reg_map; +#define sdio_dev sdio_reg_map + +/** SDIO register map base pointer */ +#define SDIO_BASE ((struct sdio_reg_map*)0x40018000) + +extern sdio_dev * SDIO; + +/* + * Register bit definitions + */ + +/* NOR/PSRAM chip-select control registers */ + +// SDIO_POWER register bits +// At least seven HCLK clock periods are needed between two write accesses to this register. +// After a data write, data cannot be written to this register for three SDIOCLK clock periods +// plus two PCLK2 clock periods. +#define SDIO_POWER_PWRCTRL_OFF 0x00 +#define SDIO_POWER_PWRCTRL_ON 0x03 + +// SDIO_CLKCR register bits +// Controls the SDIO_CK output clock. +// After a data write, data cannot be written to this register for three SDIOCLK clock periods +// plus two PCLK2 clock periods. SDIO_CK can also be stopped during the read wait interval +// for SD I/O cards: in this case the SDIO_CLKCR register does not control SDIO_CK. +#define SDIO_CLKCR_HWFC_EN (1<<14) // HW Flow Control enable - DON'T USE!!! (see errata sheet 2.12.1) + // Overrun errors (Rx mode) and FIFO underrun (Tx mode) + // should be managed by the application software. +#define SDIO_CLKCR_NEGEDGE (1<<13) // SDIO_CK de-phasing selection bit - DON'T USE!!! (see errata sheet 2.12.4) +#define SDIO_CLKCR_WIDBUS (3<<11) // Data bus width +#define SDIO_CLKCR_WIDBUS_1BIT (0<<11) // 1 bit (SDIO_D0 used) +#define SDIO_CLKCR_WIDBUS_4BIT (1<<11) // 4-bit (SDIO_D[3:0] used) +#define SDIO_CLKCR_BYPASS (1<<10) // Clock divider bypass enable bit - SDIO_CK = SDIOCLK, CLKDIV not relevant. +#define SDIO_CLKCR_PWRSAV (1<<9) // 0: SDIO_CK clock is always enabled, 1: SDIO_CK is only enabled when the bus is active +#define SDIO_CLKCR_CLKEN (1<<8) // Clock enable +#define SDIO_CLKCR_CLKDIV (0xFF) // SDIO_CK = SDIOCLK / [CLKDIV + 2] +#define SDIOCLK 72000000UL // SDIO master clock frequency + +// SDIO_CMD register bits +// After a data write, data cannot be written to this register for three SDIOCLK clock periods +// plus two PCLK2 clock periods. +// MultiMediaCards can send two kinds of response: short responses, 48 bits long, or long +// responses,136 bits long. SD card and SD I/O card can send only short responses, the +// argument can vary according to the type of response: the software will distinguish the type +// of response according to the sent command. CE-ATA devices send only short responses. +#define SDIO_CMD_ATACMD (1<<14) +#define SDIO_CMD_NIEN (1<<13) +#define SDIO_CMD_ENCMDCOMPL (1<<12) +#define SDIO_CMD_SDIOSUSPEND (1<<11) +#define SDIO_CMD_CPSMEN (1<<10) +#define SDIO_CMD_WAITPEND (1<<9) +#define SDIO_CMD_WAITINT (1<<8) +#define SDIO_CMD_WAITRESP (3<<6) +#define SDIO_CMD_WAIT_NO_RESP (0<<6) +#define SDIO_CMD_WAIT_SHORT_RESP (1<<6) +#define SDIO_CMD_WAIT_LONG_RESP (3<<6) +#define SDIO_CMD_CMDINDEX (0x3F) + +// SDIO_DLEN register bits +// For a block data transfer, the value in the data length register must be a multiple of the block +// size (see SDIO_DCTRL). A data transfer must be written to the data timer register and the +// data length register before being written to the data control register. +// For an SDIO multibyte transfer the value in the data length register must be between 1 and 512. +#define SDIO_DLEN_DATALENGTH (0x01FFFFFF) + +// SDIO_DCTRL register bits +// Controls the data path state machine (DPSM). +// After a data write, data cannot be written to this register for three SDIOCLK clock periods +// plus two PCLK2 clock periods. +#define SDIO_DCTRL_SDIOEN (1<<11) // the DPSM performs an SD I/O-card-specific operation. +#define SDIO_DCTRL_RWMODE (1<<10) // 0: Read Wait control stopping SDIO_D2, 1:Read Wait control using SDIO_CK +#define SDIO_DCTRL_RWSTOP (1<<9) // 0: Read wait in progress if RWSTART bit is set, 1: Enable for read wait stop if RWSTART bit is set +#define SDIO_DCTRL_RWSTART (1<<8) // read wait operation starts +#define SDIO_DCTRL_DBLOCKSIZE (0xF<<4) // Define the data block length when the block data transfer mode is selected: 2^N bytes +#define SDIO_BLOCKSIZE_64 (6<<4) +#define SDIO_BLOCKSIZE_512 (9<<4) +#define SDIO_DCTRL_DMAEN (1<<3) // DMA enable +#define SDIO_DCTRL_DTMODE (1<<2) // Data transfer mode selection: 0: Block data transfer, 1: Stream or SDIO multi-byte data transfer +#define SDIO_DCTRL_DTDIR (1<<1) // Data transfer direction selection: 0: From controller to card, 1: From card to controller. +#define SDIO_DIR_TX (0<<1) +#define SDIO_DIR_RX (1<<1) +#define SDIO_DCTRL_DTEN (1<<0) // Start data transfer. Depending on the direction bit, DTDIR, + // the DPSM moves to the Wait_S, Wait_R state or Readwait if RW Start is set immediately at + // the beginning of the transfer. It is not necessary to clear the enable bit after the end of a data + // transfer but the SDIO_DCTRL must be updated to enable a new data transfer +// The meaning of the DTMODE bit changes according to the value of the SDIOEN bit: +// When DTEN=0 and DTMODE=1, the MultiMediaCard stream mode is enabled. +// When DTEN=1 and DTMODE=1, the peripheral enables an SDIO multi-byte transfer. + +// SDIO_STA register bits +#define SDIO_STA_CEATAEND (1<<23) // CE-ATA command completion signal received for CMD61 +#define SDIO_STA_SDIOIT (1<<22) // SDIO interrupt received +#define SDIO_STA_RXDAVL (1<<21) // Data available in receive FIFO +#define SDIO_STA_TXDAVL (1<<20) // Data available in transmit FIFO +#define SDIO_STA_RXFIFOE (1<<19) // Receive FIFO empty +#define SDIO_STA_TXFIFOE (1<<18) // Transmit FIFO empty (2 words) +#define SDIO_STA_RXFIFOF (1<<17) // Receive FIFO full (2 words before the FIFO is full.) +#define SDIO_STA_TXFIFOF (1<<16) // Transmit FIFO full +#define SDIO_STA_RXFIFOHF (1<<15) // Receive FIFO half full: there are at least 8 words in the FIFO +#define SDIO_STA_TXFIFOHE (1<<14) // Transmit FIFO half empty: at least 8 words can be written into the FIFO +#define SDIO_STA_RXACT (1<<13) // Data receive in progress +#define SDIO_STA_TXACT (1<<12) // Data transmit in progress +#define SDIO_STA_CMDACT (1<<11) // Command transfer in progress +#define SDIO_STA_DBCKEND (1<<10) // Data block sent/received (CRC check passed) +#define SDIO_STA_STBITERR (1<<9) // Start bit not detected on all data signals in wide bus mode +#define SDIO_STA_DATAEND (1<<8) // Data end (data counter SDIOCOUNT is zero) +#define SDIO_STA_CMDSENT (1<<7) // Command sent (no response required) +#define SDIO_STA_CMDREND (1<<6) // Command response received (CRC check passed) +#define SDIO_STA_RXOVERR (1<<5) // Received FIFO overrun error +#define SDIO_STA_TXUNDERR (1<<4) // Transmit FIFO underrun error +#define SDIO_STA_DTIMEOUT (1<<3) // Data timeout +#define SDIO_STA_CTIMEOUT (1<<2) // Command response timeout. The Command TimeOut period has a fixed value of 64 SDIO_CK clock periods. +#define SDIO_STA_DCRCFAIL (1<<1) // Data block sent/received (CRC check failed) +#define SDIO_STA_CCRCFAIL (1<<0) // Command response received (CRC check failed) + +#define SDIO_STA_CMD_ERROR_FLAGS (SDIO_STA_CTIMEOUT | SDIO_STA_CCRCFAIL) +#define SDIO_STA_TRX_ERROR_FLAGS (SDIO_STA_STBITERR | SDIO_STA_RXOVERR | SDIO_STA_TXUNDERR | SDIO_STA_DTIMEOUT | SDIO_STA_DCRCFAIL) +#define SDIO_STA_TRX_ACT_FLAGS (SDIO_STA_RXACT|SDIO_STA_TXACT) + +// SDIO_ICR register bits (WO - write only) +#define SDIO_ICR_CEATAENDC (1<<23) // clear CEATAEND flag +#define SDIO_ICR_SDIOITC (1<<22) // clear SDIOIT flag +#define SDIO_ICR_DBCKENDC (1<<10) // clear DBCKENDC flag +#define SDIO_ICR_STBITERRC (1<<9) // clear STBITERRC flag +#define SDIO_ICR_DATAENDC (1<<8) // clear DATAENDC flag +#define SDIO_ICR_CMDSENTC (1<<7) // clear CMDSENTC flag +#define SDIO_ICR_CMDRENDC (1<<6) // clear CMDREND flag +#define SDIO_ICR_RXOVERRC (1<<5) // clear RXOVERR flag +#define SDIO_ICR_TXUNDERRC (1<<4) // clear TXUNDERR flag +#define SDIO_ICR_DTIMEOUTC (1<<3) // clear DTIMEOUT flag +#define SDIO_ICR_CTIMEOUTC (1<<2) // clear CTIMEOUT flag +#define SDIO_ICR_DCRCFAILC (1<<1) // clear DCRCFAIL flag +#define SDIO_ICR_CCRCFAILC (1<<0) // clear CCRCFAIL flag + +#define SDIO_ICR_CMD_FLAGS (SDIO_ICR_CEATAENDC | SDIO_ICR_SDIOITC | SDIO_ICR_CMDSENTC | SDIO_ICR_CMDRENDC | SDIO_ICR_CTIMEOUTC | SDIO_ICR_CCRCFAILC) +#define SDIO_ICR_DATA_FLAGS (SDIO_ICR_DBCKENDC | SDIO_ICR_STBITERRC | SDIO_ICR_DATAENDC | SDIO_ICR_RXOVERRC | SDIO_ICR_TXUNDERRC | SDIO_ICR_DTIMEOUTC | SDIO_ICR_DCRCFAILC) + +// SDIO_MASK register bits +// Determines which status flags generate an interrupt request by setting the corresponding bit to 1b. +#define SDIO_MASK_CEATAENDIE (1<<23) // enable CEATAEND interrupt +#define SDIO_MASK_SDIOITIE (1<<22) // enable SDIOIT interrupt +#define SDIO_MASK_RXDAVLIE (1<<21) // enable RXDAVL interrupt +#define SDIO_MASK_TXDAVLIE (1<<20) // enable TXDAVL interrupt +#define SDIO_MASK_RXFIFOEIE (1<<19) // enable RXFIFOE interrupt +#define SDIO_MASK_TXFIFOEIE (1<<18) // enable TXFIFOE interrupt +#define SDIO_MASK_RXFIFOFIE (1<<17) // enable RXFIFOF interrupt +#define SDIO_MASK_TXFIFOFIE (1<<16) // enable TXFIFOF interrupt +#define SDIO_MASK_RXFIFOHFIE (1<<15) // enable RXFIFOHF interrupt +#define SDIO_MASK_TXFIFOHEIE (1<<14) // enable TXFIFOHE interrupt +#define SDIO_MASK_RXACTIE (1<<13) // enable RXACT interrupt +#define SDIO_MASK_TXACTIE (1<<12) // enable TXACT interrupt +#define SDIO_MASK_CMDACTIE (1<<11) // enable CMDACT interrupt +#define SDIO_MASK_DBCKENDIE (1<<10) // enable DBCKENDC interrupt +#define SDIO_MASK_STBITERRIE (1<<9) // enable STBITERR interrupt +#define SDIO_MASK_DATAENDIE (1<<8) // enable DATAENDC interrupt +#define SDIO_MASK_CMDSENTIE (1<<7) // enable CMDSENTC interrupt +#define SDIO_MASK_CMDRENDIE (1<<6) // enable CMDREND interrupt +#define SDIO_MASK_RXOVERRIE (1<<5) // enable RXOVERR interrupt +#define SDIO_MASK_TXUNDERRIE (1<<4) // enable TXUNDERR interrupt +#define SDIO_MASK_DTIMEOUTIE (1<<3) // enable DTIMEOUT interrupt +#define SDIO_MASK_CTIMEOUTIE (1<<2) // enable CTIMEOUT interrupt +#define SDIO_MASK_DCRCFAILIE (1<<1) // enable DCRCFAIL interrupt +#define SDIO_MASK_CCRCFAILIE (1<<0) // enable CCRCFAIL interrupt + + +void sdio_enable(void); +void sdio_disable(void); +void sdio_begin(void); +uint8_t sdio_cmd_send(uint16_t cmd_index_resp_type, uint32_t arg); +void sdio_set_clock(uint32_t clk); +void sdio_set_dbus_width(uint16_t bus_w); +void sdio_set_dblock_size(uint8_t dbsize); +//void sdio_trx_enable(uint8_t dir); +inline void sdio_trx_enable(void) +{ + SDIO->DCTRL |= SDIO_DCTRL_DTEN; // enable data transfer +} + +inline uint32_t sdio_cmd_xfer_ongoing(void) { return (SDIO->STA&SDIO_STA_CMDACT); } +inline uint32_t sdio_cmd_complete(void) { return (SDIO->STA&SDIO_STA_CMDSENT); } + +inline void sdio_setup_transfer(uint32_t dtimer, uint32_t dlen, uint16_t flags) +{ + SDIO->ICR = SDIO_ICR_DATA_FLAGS; // clear data access relevant flags + SDIO->DTIMER = dtimer; + SDIO->DLEN = dlen; + SDIO->DCTRL = flags;// | SDIO_DCTRL_DTEN; // enable data transfer +} + +/* +#ifdef __cplusplus +} // extern "C" +#endif +*/ + +#endif /* (STM32_HIGH_DENSITY) || (STM32_XL_DENSITY) */ + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/spi.h b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/spi.h new file mode 100644 index 0000000..0da4129 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/spi.h @@ -0,0 +1,472 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011, 2012 LeafLabs, LLC. + * Copyright (c) 2010 Perry Hung. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/include/libmaple/spi.h + * @author Marti Bolivar + * @brief Serial Peripheral Interface (SPI) and Integrated + * Interchip Sound (I2S) peripheral support. + * + * I2S support is currently limited to register maps and bit definitions. + */ + +#ifndef _LIBMAPLE_SPI_H_ +#define _LIBMAPLE_SPI_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + /* Roger clark. Replaced with line below #include */ +#include "stm32f1/include/series/spi.h" + + +/* + * Register maps + */ + +/** SPI register map type. */ +typedef struct spi_reg_map { + __io uint32 CR1; /**< Control register 1 */ + __io uint32 CR2; /**< Control register 2 */ + __io uint32 SR; /**< Status register */ + __io uint32 DR; /**< Data register */ + __io uint32 CRCPR; /**< CRC polynomial register */ + __io uint32 RXCRCR; /**< RX CRC register */ + __io uint32 TXCRCR; /**< TX CRC register */ + __io uint32 I2SCFGR; /**< I2S configuration register */ + __io uint32 I2SPR; /**< I2S prescaler register */ +} spi_reg_map; + +/* + * Register bit definitions + */ + +/* Control register 1 */ + +#define SPI_CR1_BIDIMODE_BIT 15 +#define SPI_CR1_BIDIOE_BIT 14 +#define SPI_CR1_CRCEN_BIT 13 +#define SPI_CR1_CRCNEXT_BIT 12 +#define SPI_CR1_DFF_BIT 11 +#define SPI_CR1_RXONLY_BIT 10 +#define SPI_CR1_SSM_BIT 9 +#define SPI_CR1_SSI_BIT 8 +#define SPI_CR1_LSBFIRST_BIT 7 +#define SPI_CR1_SPE_BIT 6 +#define SPI_CR1_MSTR_BIT 2 +#define SPI_CR1_CPOL_BIT 1 +#define SPI_CR1_CPHA_BIT 0 + +#define SPI_CR1_BIDIMODE (1U << SPI_CR1_BIDIMODE_BIT) +#define SPI_CR1_BIDIMODE_2_LINE (0x0 << SPI_CR1_BIDIMODE_BIT) +#define SPI_CR1_BIDIMODE_1_LINE (0x1 << SPI_CR1_BIDIMODE_BIT) +#define SPI_CR1_BIDIOE (1U << SPI_CR1_BIDIOE_BIT) +#define SPI_CR1_CRCEN (1U << SPI_CR1_CRCEN_BIT) +#define SPI_CR1_CRCNEXT (1U << SPI_CR1_CRCNEXT_BIT) +#define SPI_CR1_DFF (1U << SPI_CR1_DFF_BIT) +#define SPI_CR1_DFF_8_BIT (0x0 << SPI_CR1_DFF_BIT) +#define SPI_CR1_DFF_16_BIT (0x1 << SPI_CR1_DFF_BIT) +#define SPI_CR1_RXONLY (1U << SPI_CR1_RXONLY_BIT) +#define SPI_CR1_SSM (1U << SPI_CR1_SSM_BIT) +#define SPI_CR1_SSI (1U << SPI_CR1_SSI_BIT) +#define SPI_CR1_LSBFIRST (1U << SPI_CR1_LSBFIRST_BIT) +#define SPI_CR1_SPE (1U << SPI_CR1_SPE_BIT) +#define SPI_CR1_BR (0x7 << 3) +#define SPI_CR1_BR_PCLK_DIV_2 (0x0 << 3) +#define SPI_CR1_BR_PCLK_DIV_4 (0x1 << 3) +#define SPI_CR1_BR_PCLK_DIV_8 (0x2 << 3) +#define SPI_CR1_BR_PCLK_DIV_16 (0x3 << 3) +#define SPI_CR1_BR_PCLK_DIV_32 (0x4 << 3) +#define SPI_CR1_BR_PCLK_DIV_64 (0x5 << 3) +#define SPI_CR1_BR_PCLK_DIV_128 (0x6 << 3) +#define SPI_CR1_BR_PCLK_DIV_256 (0x7 << 3) +#define SPI_CR1_MSTR (1U << SPI_CR1_MSTR_BIT) +#define SPI_CR1_CPOL (1U << SPI_CR1_CPOL_BIT) +#define SPI_CR1_CPOL_LOW (0x0 << SPI_CR1_CPOL_BIT) +#define SPI_CR1_CPOL_HIGH (0x1 << SPI_CR1_CPOL_BIT) +#define SPI_CR1_CPHA (1U << SPI_CR1_CPHA_BIT) + +/* Control register 2 */ + +#define SPI_CR2_TXEIE_BIT 7 +#define SPI_CR2_RXNEIE_BIT 6 +#define SPI_CR2_ERRIE_BIT 5 +#define SPI_CR2_SSOE_BIT 2 +#define SPI_CR2_TXDMAEN_BIT 1 +#define SPI_CR2_RXDMAEN_BIT 0 + +#define SPI_CR2_TXEIE (1U << SPI_CR2_TXEIE_BIT) +#define SPI_CR2_RXNEIE (1U << SPI_CR2_RXNEIE_BIT) +#define SPI_CR2_ERRIE (1U << SPI_CR2_ERRIE_BIT) +#define SPI_CR2_SSOE (1U << SPI_CR2_SSOE_BIT) +#define SPI_CR2_TXDMAEN (1U << SPI_CR2_TXDMAEN_BIT) +#define SPI_CR2_RXDMAEN (1U << SPI_CR2_RXDMAEN_BIT) + +/* Status register */ + +#define SPI_SR_BSY_BIT 7 +#define SPI_SR_OVR_BIT 6 +#define SPI_SR_MODF_BIT 5 +#define SPI_SR_CRCERR_BIT 4 +#define SPI_SR_UDR_BIT 3 +#define SPI_SR_CHSIDE_BIT 2 +#define SPI_SR_TXE_BIT 1 +#define SPI_SR_RXNE_BIT 0 + +#define SPI_SR_BSY (1U << SPI_SR_BSY_BIT) +#define SPI_SR_OVR (1U << SPI_SR_OVR_BIT) +#define SPI_SR_MODF (1U << SPI_SR_MODF_BIT) +#define SPI_SR_CRCERR (1U << SPI_SR_CRCERR_BIT) +#define SPI_SR_UDR (1U << SPI_SR_UDR_BIT) +#define SPI_SR_CHSIDE (1U << SPI_SR_CHSIDE_BIT) +#define SPI_SR_CHSIDE_LEFT (0x0 << SPI_SR_CHSIDE_BIT) +#define SPI_SR_CHSIDE_RIGHT (0x1 << SPI_SR_CHSIDE_BIT) +#define SPI_SR_TXE (1U << SPI_SR_TXE_BIT) +#define SPI_SR_RXNE (1U << SPI_SR_RXNE_BIT) + +/* I2S configuration register */ + +#define SPI_I2SCFGR_I2SMOD_BIT 11 +#define SPI_I2SCFGR_I2SE_BIT 10 +#define SPI_I2SCFGR_PCMSYNC_BIT 7 +#define SPI_I2SCFGR_CKPOL_BIT 3 +#define SPI_I2SCFGR_CHLEN_BIT 0 + +#define SPI_I2SCFGR_I2SMOD (1U << SPI_I2SCFGR_I2SMOD_BIT) +#define SPI_I2SCFGR_I2SMOD_SPI (0x0 << SPI_I2SCFGR_I2SMOD_BIT) +#define SPI_I2SCFGR_I2SMOD_I2S (0x1 << SPI_I2SCFGR_I2SMOD_BIT) +#define SPI_I2SCFGR_I2SE (1U << SPI_I2SCFGR_I2SE_BIT) +#define SPI_I2SCFGR_I2SCFG (0x3 << 8) +#define SPI_I2SCFGR_I2SCFG_SLAVE_TX (0x0 << 8) +#define SPI_I2SCFGR_I2SCFG_SLAVE_RX (0x1 << 8) +#define SPI_I2SCFGR_I2SCFG_MASTER_TX (0x2 << 8) +#define SPI_I2SCFGR_I2SCFG_MASTER_RX (0x3 << 8) +#define SPI_I2SCFGR_PCMSYNC (1U << SPI_I2SCFGR_PCMSYNC_BIT) +#define SPI_I2SCFGR_PCMSYNC_SHORT (0x0 << SPI_I2SCFGR_PCMSYNC_BIT) +#define SPI_I2SCFGR_PCMSYNC_LONG (0x1 << SPI_I2SCFGR_PCMSYNC_BIT) +#define SPI_I2SCFGR_I2SSTD (0x3 << 4) +#define SPI_I2SCFGR_I2SSTD_PHILLIPS (0x0 << 4) +#define SPI_I2SCFGR_I2SSTD_MSB (0x1 << 4) +#define SPI_I2SCFGR_I2SSTD_LSB (0x2 << 4) +#define SPI_I2SCFGR_I2SSTD_PCM (0x3 << 4) +#define SPI_I2SCFGR_CKPOL (1U << SPI_I2SCFGR_CKPOL_BIT) +#define SPI_I2SCFGR_CKPOL_LOW (0x0 << SPI_I2SCFGR_CKPOL_BIT) +#define SPI_I2SCFGR_CKPOL_HIGH (0x1 << SPI_I2SCFGR_CKPOL_BIT) +#define SPI_I2SCFGR_DATLEN (0x3 << 1) +#define SPI_I2SCFGR_DATLEN_16_BIT (0x0 << 1) +#define SPI_I2SCFGR_DATLEN_24_BIT (0x1 << 1) +#define SPI_I2SCFGR_DATLEN_32_BIT (0x2 << 1) +#define SPI_I2SCFGR_CHLEN (1U << SPI_I2SCFGR_CHLEN_BIT) +#define SPI_I2SCFGR_CHLEN_16_BIT (0x0 << SPI_I2SCFGR_CHLEN_BIT) +#define SPI_I2SCFGR_CHLEN_32_BIT (0x1 << SPI_I2SCFGR_CHLEN_BIT) + +/* I2S prescaler register */ + +#define SPI_I2SPR_MCKOE_BIT 9 +#define SPI_I2SPR_ODD_BIT 8 + +#define SPI_I2SPR_MCKOE (1U << SPI_I2SPR_MCKOE_BIT) +#define SPI_I2SPR_ODD (1U << SPI_I2SPR_ODD_BIT) +#define SPI_I2SPR_I2SDIV 0xFF + +/* + * Devices + */ + +/** SPI device type */ +typedef struct spi_dev { + spi_reg_map *regs; /**< Register map */ + rcc_clk_id clk_id; /**< RCC clock information */ + nvic_irq_num irq_num; /**< NVIC interrupt number */ +} spi_dev; + +/* + * SPI Convenience functions + */ + +void spi_init(spi_dev *dev); + +struct gpio_dev; +/** + * @brief Configure GPIO bit modes for use as a SPI port's pins. + * + * @param dev SPI device + * @param as_master If true, configure as bus master; otherwise, as slave. + * @param nss_dev NSS pin's GPIO device + * @param nss_bit NSS pin's GPIO bit on nss_dev + * @param comm_dev SCK, MISO, MOSI pins' GPIO device + * @param sck_bit SCK pin's GPIO bit on comm_dev + * @param miso_bit MISO pin's GPIO bit on comm_dev + * @param mosi_bit MOSI pin's GPIO bit on comm_dev + */ +extern void spi_config_gpios(spi_dev *dev, + uint8 as_master, + struct gpio_dev *nss_dev, + uint8 nss_bit, + struct gpio_dev *comm_dev, + uint8 sck_bit, + uint8 miso_bit, + uint8 mosi_bit); + +/** + * @brief SPI mode configuration. + * + * A SPI mode determines a combination of the idle state of the clock + * line (the clock polarity, or "CPOL"), and which clock edge triggers + * data capture (the clock phase, or "CPHA"). + */ +typedef enum spi_mode { + /** Clock idles low, data captured on rising edge (first transition) */ + SPI_MODE_LOW_RISING = 0, + /** Clock idles low, data captured on falling edge (second transition) */ + SPI_MODE_LOW_FALLING = 1, + /** Clock idles high, data captured on falling edge (first transition) */ + SPI_MODE_HIGH_FALLING = 2, + /** Clock idles high, data captured on rising edge (second transition) */ + SPI_MODE_HIGH_RISING = 3, + + SPI_MODE_0 = SPI_MODE_LOW_RISING, /**< Same as SPI_MODE_LOW_RISING */ + SPI_MODE_1 = SPI_MODE_LOW_FALLING, /**< Same as SPI_MODE_LOW_FALLING */ + SPI_MODE_2 = SPI_MODE_HIGH_FALLING, /**< Same as SPI_MODE_HIGH_FALLING */ + SPI_MODE_3 = SPI_MODE_HIGH_RISING, /**< Same as SPI_MODE_HIGH_RISING */ +} spi_mode; + +/** + * @brief SPI baud rate configuration, as a divisor of f_PCLK, the + * PCLK clock frequency. + */ +typedef enum spi_baud_rate { + SPI_BAUD_PCLK_DIV_2 = SPI_CR1_BR_PCLK_DIV_2, /**< f_PCLK/2 */ + SPI_BAUD_PCLK_DIV_4 = SPI_CR1_BR_PCLK_DIV_4, /**< f_PCLK/4 */ + SPI_BAUD_PCLK_DIV_8 = SPI_CR1_BR_PCLK_DIV_8, /**< f_PCLK/8 */ + SPI_BAUD_PCLK_DIV_16 = SPI_CR1_BR_PCLK_DIV_16, /**< f_PCLK/16 */ + SPI_BAUD_PCLK_DIV_32 = SPI_CR1_BR_PCLK_DIV_32, /**< f_PCLK/32 */ + SPI_BAUD_PCLK_DIV_64 = SPI_CR1_BR_PCLK_DIV_64, /**< f_PCLK/64 */ + SPI_BAUD_PCLK_DIV_128 = SPI_CR1_BR_PCLK_DIV_128, /**< f_PCLK/128 */ + SPI_BAUD_PCLK_DIV_256 = SPI_CR1_BR_PCLK_DIV_256, /**< f_PCLK/256 */ +} spi_baud_rate; + +/** + * @brief SPI initialization flags. + * @see spi_master_enable() + * @see spi_slave_enable() + */ +typedef enum spi_cfg_flag { + SPI_BIDIMODE = SPI_CR1_BIDIMODE, /**< Bidirectional mode enable */ + SPI_BIDIOE = SPI_CR1_BIDIOE, /**< Output enable in bidirectional + mode */ + SPI_CRCEN = SPI_CR1_CRCEN, /**< Cyclic redundancy check (CRC) + enable */ + SPI_DFF_8_BIT = SPI_CR1_DFF_8_BIT, /**< 8-bit data frame format (this is + the default) */ + SPI_DFF_16_BIT = SPI_CR1_DFF_16_BIT, /**< 16-bit data frame format */ + SPI_RX_ONLY = SPI_CR1_RXONLY, /**< Receive only */ + SPI_SW_SLAVE = SPI_CR1_SSM, /**< Software slave management */ + SPI_SOFT_SS = SPI_CR1_SSI, /**< Software (internal) slave + select. This flag only has an + effect when used in combination + with SPI_SW_SLAVE. */ + SPI_FRAME_LSB = SPI_CR1_LSBFIRST, /**< LSB-first (little-endian) frame + format */ + SPI_FRAME_MSB = 0, /**< MSB-first (big-endian) frame + format (this is the default) */ +} spi_cfg_flag; + +void spi_master_enable(spi_dev *dev, + spi_baud_rate baud, + spi_mode mode, + uint32 flags); + +void spi_slave_enable(spi_dev *dev, + spi_mode mode, + uint32 flags); + +uint32 spi_tx(spi_dev *dev, const void *buf, uint32 len); + +/** + * @brief Call a function on each SPI port + * @param fn Function to call. + */ +extern void spi_foreach(void (*fn)(spi_dev*)); + +void spi_peripheral_enable(spi_dev *dev); +void spi_peripheral_disable(spi_dev *dev); + +void spi_tx_dma_enable(spi_dev *dev); +void spi_tx_dma_disable(spi_dev *dev); + +void spi_rx_dma_enable(spi_dev *dev); +void spi_rx_dma_disable(spi_dev *dev); + +/** + * @brief Determine if a SPI peripheral is enabled. + * @param dev SPI device + * @return True, if and only if dev's peripheral is enabled. + */ +static inline uint8 spi_is_enabled(spi_dev *dev) { + return dev->regs->CR1 & SPI_CR1_SPE_BIT; +} + +/** + * @brief Disable all SPI peripherals + */ +static inline void spi_peripheral_disable_all(void) { + spi_foreach(spi_peripheral_disable); +} + +/** Available SPI interrupts */ +typedef enum spi_interrupt { + SPI_TXE_INTERRUPT = SPI_CR2_TXEIE, /**< TX buffer empty interrupt */ + SPI_RXNE_INTERRUPT = SPI_CR2_RXNEIE, /**< RX buffer not empty interrupt */ + SPI_ERR_INTERRUPT = SPI_CR2_ERRIE /**< + * Error interrupt (CRC, overrun, + * and mode fault errors for SPI; + * underrun, overrun errors for I2S) + */ +} spi_interrupt; + +/** + * @brief Mask for all spi_interrupt values + * @see spi_interrupt + */ +#define SPI_INTERRUPTS_ALL (SPI_TXE_INTERRUPT | \ + SPI_RXNE_INTERRUPT | \ + SPI_ERR_INTERRUPT) + +/** + * @brief Enable SPI interrupt requests + * @param dev SPI device + * @param interrupt_flags Bitwise OR of spi_interrupt values to enable + * @see spi_interrupt + */ +static inline void spi_irq_enable(spi_dev *dev, uint32 interrupt_flags) { + dev->regs->CR2 |= interrupt_flags; + nvic_irq_enable(dev->irq_num); +} + +/** + * @brief Disable SPI interrupt requests + * @param dev SPI device + * @param interrupt_flags Bitwise OR of spi_interrupt values to disable + * @see spi_interrupt + */ +static inline void spi_irq_disable(spi_dev *dev, uint32 interrupt_flags) { + dev->regs->CR2 &= ~interrupt_flags; +} + +/** + * @brief Get the data frame format flags with which a SPI port is + * configured. + * @param dev SPI device whose data frame format to get. + * @return SPI_DFF_8_BIT, if dev has an 8-bit data frame format. + * Otherwise, SPI_DFF_16_BIT. + */ +static inline spi_cfg_flag spi_dff(spi_dev *dev) { + return ((dev->regs->CR1 & SPI_CR1_DFF) == SPI_CR1_DFF_8_BIT ? + SPI_DFF_8_BIT : + SPI_DFF_16_BIT); +} + +/** + * @brief Determine whether the device's peripheral receive (RX) + * register is empty. + * @param dev SPI device + * @return true, iff dev's RX register is empty. + */ +static inline uint8 spi_is_rx_nonempty(spi_dev *dev) { + return dev->regs->SR & SPI_SR_RXNE; +} + +/** + * @brief Retrieve the contents of the device's peripheral receive + * (RX) register. + * + * You may only call this function when the RX register is nonempty. + * Calling this function clears the contents of the RX register. + * + * @param dev SPI device + * @return Contents of dev's peripheral RX register + * @see spi_is_rx_reg_nonempty() + */ +static inline uint16 spi_rx_reg(spi_dev *dev) { + return (uint16)dev->regs->DR; +} + +/** + * @brief Determine whether the device's peripheral transmit (TX) + * register is empty. + * @param dev SPI device + * @return true, iff dev's TX register is empty. + */ +static inline uint8 spi_is_tx_empty(spi_dev *dev) { + return dev->regs->SR & SPI_SR_TXE; +} + +/** + * @brief Load a value into the device's peripheral transmit (TX) register. + * + * You may only call this function when the TX register is empty. + * Calling this function loads val into the peripheral's TX register. + * If the device is properly configured, this will initiate a + * transmission, the completion of which will cause the TX register to + * be empty again. + * + * @param dev SPI device + * @param val Value to load into the TX register. If the SPI data + * frame format is 8 bit, the value must be right-aligned. + * @see spi_is_tx_reg_empty() + * @see spi_init() + * @see spi_master_enable() + * @see spi_slave_enable() + */ +static inline void spi_tx_reg(spi_dev *dev, uint16 val) { + dev->regs->DR = val; +} + +/** + * @brief Determine whether the device's peripheral busy (SPI_SR_BSY) + * flag is set. + * @param dev SPI device + * @return true, iff dev's BSY flag is set. + */ +static inline uint8 spi_is_busy(spi_dev *dev) { + return dev->regs->SR & SPI_SR_BSY; +} + +/* + * I2S convenience functions (TODO) + */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/stm32.h b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/stm32.h new file mode 100644 index 0000000..f1990dd --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/stm32.h @@ -0,0 +1,238 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010, 2011, 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/include/libmaple/stm32.h + * @brief STM32 chip header + * + * This header supplies various chip-specific values for the current + * build target. It's useful both to abstract away hardware details + * (e.g. through use of STM32_NR_INTERRUPTS) and to decide what to do + * when you want something nonportable (e.g. by checking + * STM32_MCU_SERIES). + */ + +#ifndef _LIBMAPLE_STM32_H_ +#define _LIBMAPLE_STM32_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * STM32 series identifiers. + * + * Don't make these into an enum; the preprocessor needs them. + */ + +/** STM32F1 series. */ +#define STM32_SERIES_F1 0 +/** STM32F2 series. */ +#define STM32_SERIES_F2 1 +/** STM32L1 series. */ +#define STM32_SERIES_L1 2 +/** STM32F4 series. */ +#define STM32_SERIES_F4 3 + +/* The series header is responsible for defining: + * + * - Everything in the following __DOXYGEN__ conditional block. + * + * - STM32_HAVE_FSMC: 1 if the MCU has the FSMC peripheral, and 0 + * otherwise. + * + * - STM32_HAVE_USB: 1 if the MCU has a USB peripheral, and 0 + * otherwise. + */ + /* roger clark. replaced with line below #include */ +#include "stm32f1/include/series/stm32.h" + +/* Ensure the series header isn't broken. */ +#if (!defined(STM32_PCLK1) || \ + !defined(STM32_PCLK2) || \ + !defined(STM32_MCU_SERIES) || \ + !defined(STM32_NR_INTERRUPTS) || \ + !defined(STM32_NR_GPIO_PORTS) || \ + !defined(STM32_TIMER_MASK) || \ + !defined(STM32_DELAY_US_MULT) || \ + !defined(STM32_SRAM_END) || \ + !defined(STM32_HAVE_DAC) || \ + !defined(STM32_HAVE_FSMC) || \ + !defined(STM32_HAVE_USB)) +#error "Bad STM32F1 configuration. Check header for your MCU." +#endif + +/* + * Derived macros + */ + +/* FIXME [0.0.13] add this to ReST API page */ +/** + * @brief Statically determine whether a timer is present. + * + * Given a constant timer number n (starting from 1), this macro has a + * nonzero value exactly when TIMERn is available. + */ +#define STM32_HAVE_TIMER(n) (STM32_TIMER_MASK & (1 << (n))) + +/* + * Doxygen for functionality provided by series header. + */ + +#ifdef __DOXYGEN__ + +/* + * Clock configuration. + * + * These defines depend upon how the MCU is configured. Because of + * the potential for a mismatch between them and the actual clock + * configuration, keep their number to a minimum. + */ + +/** + * @brief APB1 clock speed, in Hz. + */ +#define STM32_PCLK1 + +/** + * @brief APB2 clock speed, in Hz. + */ +#define STM32_PCLK2 + +/** @brief Deprecated. Use STM32_PCLK1 instead. */ +#define PCLK1 +/** @brief Deprecated. Use STM32_PCLK2 instead. */ +#define PCLK2 + +/* + * Series- and MCU-specific values. + */ + +/** + * @brief STM32 series value for the MCU being targeted. + * + * At time of writing, allowed values are: STM32_SERIES_F1, + * STM32_SERIES_F2. This set of values will expand as libmaple adds + * support for more STM32 series MCUs. + */ +#define STM32_MCU_SERIES + +/** + * @brief Number of interrupts in the vector table. + * + * This does not include Cortex-M interrupts (NMI, HardFault, etc.). + */ +#define STM32_NR_INTERRUPTS + +/** + * Number of GPIO ports. + */ +#define STM32_NR_GPIO_PORTS + +/* FIXME [0.0.13] add this to ReST API page */ +/** + * @brief Bitmask of timers available on the MCU. + * + * That is, if TIMERn is available, then STM32_TIMER_MASK & (1 << n) + * will be nonzero. For example, a nonzero value of "STM32_TIMER_MASK + * & 0x2" means TIMER1 is available. + * + * A bitmask is necessary as some STM32 MCUs have "holes" in the range + * of available timers. + */ +#define STM32_TIMER_MASK + +/** + * @brief Multiplier to convert microseconds into loop iterations + * in delay_us(). + * + * @see delay_us() + */ +#define STM32_DELAY_US_MULT + +/** + * @brief Pointer to end of built-in SRAM. + * + * Points to the address which is 1 byte past the last valid + * SRAM address. + */ +#define STM32_SRAM_END + +/** + * @brief 1 if the target MCU has a DAC, and 0 otherwise. + */ +#define STM32_HAVE_DAC + +/** + * @brief 1 if the target MCU has the FSMC peripheral, and 0 otherwise. + * + * Note that the feature set of the FSMC peripheral is restricted on + * some MCUs. + */ +#define STM32_HAVE_FSMC + +/** + * @brief 1 if the target MCU has a USB peripheral, and 0 otherwise. + * + * Note that a variety of USB peripherals are available across the + * different series, with widely varying feature sets and programming + * interfaces. This macro will be 1 if any such peripheral is present. + */ +#define STM32_HAVE_USB + +#endif /* __DOXYGEN__ */ + +/* + * The following are for backwards compatibility only. + */ + +/* PCLK1 and PCLK2 are for backwards compatibility only; don't use in + * new code. */ +#ifndef PCLK1 +#define PCLK1 STM32_PCLK1 +#endif +#if PCLK1 != STM32_PCLK1 +#error "PCLK1 (which is deprecated) differs from STM32_PCLK1." +#endif +#ifndef PCLK2 +#define PCLK2 STM32_PCLK2 +#endif +#if PCLK2 != STM32_PCLK2 +#error "PCLK2 (which is deprecated) differs from STM32_PCLK2." +#endif + +/** @brief Deprecated. Use STM32_NR_INTERRUPTS instead. */ +#define NR_INTERRUPTS STM32_NR_INTERRUPTS +/** @brief Deprecated. Use STM32_NR_GPIO_PORTS instead. */ +#define NR_GPIO_PORTS STM32_NR_GPIO_PORTS +/** @brief Deprecated. Use STM32_DELAY_US_MULT instead. */ +#define DELAY_US_MULT STM32_DELAY_US_MULT + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/syscfg.h b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/syscfg.h new file mode 100644 index 0000000..6b375d3 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/syscfg.h @@ -0,0 +1,151 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/include/libmaple/syscfg.h + * @brief System configuration controller (SYSCFG) + * + * Availability: STM32F2, STM32F4. + */ + +#ifndef _LIBMAPLE_SYSCFG_H_ +#define _LIBMAPLE_SYSCFG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* + * Register map and base pointer + */ + +/** + * @brief SYSCFG register map type. + */ +typedef struct syscfg_reg_map { + __io uint32 MEMRMP; /**< Memory remap register */ + __io uint32 PMC; /**< Peripheral mode configuration */ + __io uint32 EXTICR[4]; /**< External interrupt configuration registers */ + const uint32 RESERVED1; + const uint32 RESERVED2; + __io uint32 CMPCR; /**< Compensation cell control register */ +} syscfg_reg_map; + +/** SYSCFG register map base pointer */ +#define SYSCFG_BASE ((struct syscfg_reg_map*)0x40013800) + +/* + * Register bit definitions + */ + +/* Memory remap register */ + +#define SYSCFG_MEMRMP_MEM_MODE 0x3 +#define SYSCFG_MEMRMP_MEM_MODE_FLASH 0x0 +#define SYSCFG_MEMRMP_MEM_MODE_SYS_FLASH 0x1 +#define SYSCFG_MEMRMP_MEM_MODE_FSMC_1 0x2 +#define SYSCFG_MEMRMP_MEM_MODE_EMB_SRAM 0x3 + +/* Peripheral mode configuration register */ + +#define SYSCFG_PMC_MII_RMII_SEL_BIT 23 + +#define SYSCFG_PMC_MII_RMII_SEL (1U << SYSCFG_PMC_MII_RMII_SEL_BIT) +#define SYSCFG_PMC_MII_RMII_SEL_MII (0U << SYSCFG_PMC_MII_RMII_SEL_BIT) +#define SYSCFG_PMC_MII_RMII_SEL_RMII (1U << SYSCFG_PMC_MII_RMII_SEL_BIT) + +/* External interrupt configuration register 1 */ + +#define SYSCFG_EXTICR1_EXTI0 0xF +#define SYSCFG_EXTICR1_EXTI1 0xF0 +#define SYSCFG_EXTICR1_EXTI2 0xF00 +#define SYSCFG_EXTICR1_EXTI3 0xF000 + +/* External interrupt configuration register 2 */ + +#define SYSCFG_EXTICR2_EXTI4 0xF +#define SYSCFG_EXTICR2_EXTI5 0xF0 +#define SYSCFG_EXTICR2_EXTI6 0xF00 +#define SYSCFG_EXTICR2_EXTI7 0xF000 + +/* External interrupt configuration register 3 */ + +#define SYSCFG_EXTICR3_EXTI8 0xF +#define SYSCFG_EXTICR3_EXTI9 0xF0 +#define SYSCFG_EXTICR3_EXTI10 0xF00 +#define SYSCFG_EXTICR3_EXTI11 0xF000 + +/* External interrupt configuration register 4 */ + +#define SYSCFG_EXTICR4_EXTI12 0xF +#define SYSCFG_EXTICR4_EXTI13 0xF0 +#define SYSCFG_EXTICR4_EXTI14 0xF00 +#define SYSCFG_EXTICR4_EXTI15 0xF000 + +/* Compensation cell control register */ + +#define SYSCFG_CMPCR_READY_BIT 8 +#define SYSCFG_CMPCR_CMP_PD_BIT 0 + +#define SYSCFG_CMPCR_READY (1U << SYSCFG_CMPCR_READY_BIT) +#define SYSCFG_CMPCR_CMP_PD (1U << SYSCFG_CMPCR_CMP_PD_BIT) +#define SYSCFG_CMPCR_CMP_PD_PDWN (0U << SYSCFG_CMPCR_CMP_PD_BIT) +#define SYSCFG_CMPCR_CMP_PD_ENABLE (1U << SYSCFG_CMPCR_CMP_PD_BIT) + +/* + * Routines + */ + +void syscfg_init(void); + +void syscfg_enable_io_compensation(void); +void syscfg_disable_io_compensation(void); + +/** + * @brief System memory mode + * These values specify what memory to map to address 0x00000000. + * @see syscfg_set_mem_mode + */ +typedef enum syscfg_mem_mode { + /** Main flash memory is mapped at 0x0. */ + SYCFG_MEM_MODE_FLASH = SYSCFG_MEMRMP_MEM_MODE_FLASH, + /** System flash (i.e. ST's baked-in bootloader) is mapped at 0x0. */ + SYCFG_MEM_MODE_SYSTEM_FLASH = SYSCFG_MEMRMP_MEM_MODE_SYS_FLASH, + /** FSMC bank 1 (NOR/PSRAM 1 and 2) is mapped at 0x0. */ + SYCFG_MEM_MODE_FSMC_BANK_1 = SYSCFG_MEMRMP_MEM_MODE_FSMC_1, + /** Embedded SRAM (i.e., not backup SRAM) is mapped at 0x0. */ + SYCFG_MEM_MODE_SRAM = SYSCFG_MEMRMP_MEM_MODE_EMB_SRAM, +} syscfg_mem_mode; + +void syscfg_set_mem_mode(syscfg_mem_mode); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/systick.h b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/systick.h new file mode 100644 index 0000000..51d0c56 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/systick.h @@ -0,0 +1,121 @@ +/****************************************************************************** + * 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/include/libmaple/systick.h + * @brief System timer definitions + */ + +#ifndef _LIBMAPLE_SYSTICK_H_ +#define _LIBMAPLE_SYSTICK_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include +#include + +/** SysTick register map type */ +typedef struct systick_reg_map { + __io uint32 CSR; /**< Control and status register */ + __io uint32 RVR; /**< Reload value register */ + __io uint32 CNT; /**< Current value register ("count") */ + __io uint32 CVR; /**< Calibration value register */ +} systick_reg_map; + +/** SysTick register map base pointer */ +#define SYSTICK_BASE ((struct systick_reg_map*)0xE000E010) + +/* + * Register bit definitions. + */ + +/* Control and status register */ + +#define SYSTICK_CSR_COUNTFLAG BIT(16) +#define SYSTICK_CSR_CLKSOURCE BIT(2) +#define SYSTICK_CSR_CLKSOURCE_EXTERNAL 0 +#define SYSTICK_CSR_CLKSOURCE_CORE BIT(2) +#define SYSTICK_CSR_TICKINT BIT(1) +#define SYSTICK_CSR_TICKINT_PEND BIT(1) +#define SYSTICK_CSR_TICKINT_NO_PEND 0 +#define SYSTICK_CSR_ENABLE BIT(0) +#define SYSTICK_CSR_ENABLE_MULTISHOT BIT(0) +#define SYSTICK_CSR_ENABLE_DISABLED 0 + +/* Calibration value register */ + +#define SYSTICK_CVR_NOREF BIT(31) +#define SYSTICK_CVR_SKEW BIT(30) +#define SYSTICK_CVR_TENMS 0xFFFFFF + +/** System elapsed time, in milliseconds */ +extern volatile uint32 systick_uptime_millis; + +/** + * @brief Returns the system uptime, in milliseconds. + */ +static inline uint32 systick_uptime(void) { + return systick_uptime_millis; +} + + +void systick_init(uint32 reload_val); +void systick_disable(); +void systick_enable(); + +/** + * @brief Returns the current value of the SysTick counter. + */ +static inline uint32 systick_get_count(void) { + return SYSTICK_BASE->CNT; +} + +/** + * @brief Check for underflow. + * + * This function returns 1 if the SysTick timer has counted to 0 since + * the last time it was called. However, any reads of any part of the + * SysTick Control and Status Register SYSTICK_BASE->CSR will + * interfere with this functionality. See the ARM Cortex M3 Technical + * Reference Manual for more details (e.g. Table 8-3 in revision r1p1). + */ +static inline uint32 systick_check_underflow(void) { + return SYSTICK_BASE->CSR & SYSTICK_CSR_COUNTFLAG; +} + +/** + * @brief prototype for systick_attach_callback + * + */ +extern void systick_attach_callback(void (*callback)(void)); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/timer.h b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/timer.h new file mode 100644 index 0000000..2c83e5e --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/timer.h @@ -0,0 +1,1149 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011, 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/include/libmaple/timer.h + * @author Marti Bolivar + * @brief Timer interface. + */ + +#ifndef _LIBMAPLE_TIMER_H_ +#define _LIBMAPLE_TIMER_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +/* Roger clark. Replaced with line below #include */ +#include "stm32f1/include/series/timer.h" +#include +#include +#include +#include + +/* + * Register maps + */ + +/** Advanced control timer register map type */ +typedef struct timer_adv_reg_map { + __io uint32 CR1; /**< Control register 1 */ + __io uint32 CR2; /**< Control register 2 */ + __io uint32 SMCR; /**< Slave mode control register */ + __io uint32 DIER; /**< DMA/interrupt enable register */ + __io uint32 SR; /**< Status register */ + __io uint32 EGR; /**< Event generation register */ + __io uint32 CCMR1; /**< Capture/compare mode register 1 */ + __io uint32 CCMR2; /**< Capture/compare mode register 2 */ + __io uint32 CCER; /**< Capture/compare enable register */ + __io uint32 CNT; /**< Counter */ + __io uint32 PSC; /**< Prescaler */ + __io uint32 ARR; /**< Auto-reload register */ + __io uint32 RCR; /**< Repetition counter register */ + __io uint32 CCR1; /**< Capture/compare register 1 */ + __io uint32 CCR2; /**< Capture/compare register 2 */ + __io uint32 CCR3; /**< Capture/compare register 3 */ + __io uint32 CCR4; /**< Capture/compare register 4 */ + __io uint32 BDTR; /**< Break and dead-time register */ + __io uint32 DCR; /**< DMA control register */ + __io uint32 DMAR; /**< DMA address for full transfer */ +} timer_adv_reg_map; + +/* General purpose timer register map type: intentionally omitted. + * + * General purpose timers differ slightly across series, so leave it + * up to the series header to define struct timer_gen_reg_map. */ + +/** Basic timer register map type */ +typedef struct timer_bas_reg_map { + __io uint32 CR1; /**< Control register 1 */ + __io uint32 CR2; /**< Control register 2 */ + const uint32 RESERVED1; /**< Reserved */ + __io uint32 DIER; /**< DMA/interrupt enable register */ + __io uint32 SR; /**< Status register */ + __io uint32 EGR; /**< Event generation register */ + const uint32 RESERVED2; /**< Reserved */ + const uint32 RESERVED3; /**< Reserved */ + const uint32 RESERVED4; /**< Reserved */ + __io uint32 CNT; /**< Counter */ + __io uint32 PSC; /**< Prescaler */ + __io uint32 ARR; /**< Auto-reload register */ +} timer_bas_reg_map; + +/* + * Timer devices + */ + +/** + * @brief Timer register map type. + * + * Just holds a pointer to the correct type of register map, based on + * the timer's type. + */ +typedef union timer_reg_map { + timer_adv_reg_map *adv; /**< Advanced register map */ + timer_gen_reg_map *gen; /**< General purpose register map */ + timer_bas_reg_map *bas; /**< Basic register map */ +} timer_reg_map; + +/** + * @brief Timer type + * + * Type marker for timer_dev. + * + * @see timer_dev + */ +typedef enum timer_type { + TIMER_ADVANCED, /**< Advanced type */ + TIMER_GENERAL, /**< General purpose type */ + TIMER_BASIC, /**< Basic type */ +} timer_type; + +/** Timer device type */ +typedef struct timer_dev { + timer_reg_map regs; /**< Register map */ + rcc_clk_id clk_id; /**< RCC clock information */ + timer_type type; /**< Timer's type */ + voidFuncPtr handlers[]; /**< + * Don't touch these. Use these instead: + * @see timer_attach_interrupt() + * @see timer_detach_interrupt() */ +} timer_dev; + +#if STM32_HAVE_TIMER(1) +extern timer_dev *const TIMER1; +extern timer_dev timer1; +#endif +#if STM32_HAVE_TIMER(2) +extern timer_dev *const TIMER2; +extern timer_dev timer2; +#endif +#if STM32_HAVE_TIMER(3) +extern timer_dev *const TIMER3; +extern timer_dev timer3; +#endif +#if STM32_HAVE_TIMER(4) +extern timer_dev *const TIMER4; +extern timer_dev timer4; +#endif +#if STM32_HAVE_TIMER(5) +extern timer_dev *const TIMER5; +extern timer_dev timer5; +#endif +#if STM32_HAVE_TIMER(6) +extern timer_dev *const TIMER6; +extern timer_dev timer6; +#endif +#if STM32_HAVE_TIMER(7) +extern timer_dev *const TIMER7; +extern timer_dev timer7; +#endif +#if STM32_HAVE_TIMER(8) +extern timer_dev *const TIMER8; +extern timer_dev timer8; +#endif +#if STM32_HAVE_TIMER(9) +extern timer_dev *const TIMER9; +extern timer_dev timer9; +#endif +#if STM32_HAVE_TIMER(10) +extern timer_dev *const TIMER10; +extern timer_dev timer10; +#endif +#if STM32_HAVE_TIMER(11) +extern timer_dev *const TIMER11; +extern timer_dev timer11; +#endif +#if STM32_HAVE_TIMER(12) +extern timer_dev *const TIMER12; +extern timer_dev timer12; +#endif +#if STM32_HAVE_TIMER(13) +extern timer_dev *const TIMER13; +extern timer_dev timer13; +#endif +#if STM32_HAVE_TIMER(14) +extern timer_dev *const TIMER14; +extern timer_dev timer14; +#endif + +/* + * Register bit definitions + */ + +/* Control register 1 (CR1) */ + +#define TIMER_CR1_ARPE_BIT 7 +#define TIMER_CR1_DIR_BIT 4 +#define TIMER_CR1_OPM_BIT 3 +#define TIMER_CR1_URS_BIT 2 +#define TIMER_CR1_UDIS_BIT 1 +#define TIMER_CR1_CEN_BIT 0 + +#define TIMER_CR1_CKD (0x3 << 8) +#define TIMER_CR1_CKD_1TCKINT (0x0 << 8) +#define TIMER_CR1_CKD_2TCKINT (0x1 << 8) +#define TIMER_CR1_CKD_4TICKINT (0x2 << 8) +#define TIMER_CR1_ARPE (1U << TIMER_CR1_ARPE_BIT) +#define TIMER_CR1_CKD_CMS (0x3 << 5) +#define TIMER_CR1_CKD_CMS_EDGE (0x0 << 5) +#define TIMER_CR1_CKD_CMS_CENTER1 (0x1 << 5) +#define TIMER_CR1_CKD_CMS_CENTER2 (0x2 << 5) +#define TIMER_CR1_CKD_CMS_CENTER3 (0x3 << 5) +#define TIMER_CR1_DIR (1U << TIMER_CR1_DIR_BIT) +#define TIMER_CR1_OPM (1U << TIMER_CR1_OPM_BIT) +#define TIMER_CR1_URS (1U << TIMER_CR1_URS_BIT) +#define TIMER_CR1_UDIS (1U << TIMER_CR1_UDIS_BIT) +#define TIMER_CR1_CEN (1U << TIMER_CR1_CEN_BIT) + +/* Control register 2 (CR2) */ + +#define TIMER_CR2_OIS4_BIT 14 +#define TIMER_CR2_OIS3N_BIT 13 +#define TIMER_CR2_OIS3_BIT 12 +#define TIMER_CR2_OIS2N_BIT 11 +#define TIMER_CR2_OIS2_BIT 10 +#define TIMER_CR2_OIS1N_BIT 9 +#define TIMER_CR2_OIS1_BIT 8 +#define TIMER_CR2_TI1S_BIT 7 +#define TIMER_CR2_CCDS_BIT 3 +#define TIMER_CR2_CCUS_BIT 2 +#define TIMER_CR2_CCPC_BIT 0 + +#define TIMER_CR2_OIS4 (1U << TIMER_CR2_OIS4_BIT) +#define TIMER_CR2_OIS3N (1U << TIMER_CR2_OIS3N_BIT) +#define TIMER_CR2_OIS3 (1U << TIMER_CR2_OIS3_BIT) +#define TIMER_CR2_OIS2N (1U << TIMER_CR2_OIS2N_BIT) +#define TIMER_CR2_OIS2 (1U << TIMER_CR2_OIS2_BIT) +#define TIMER_CR2_OIS1N (1U << TIMER_CR2_OIS1N_BIT) +#define TIMER_CR2_OIS1 (1U << TIMER_CR2_OIS1_BIT) +#define TIMER_CR2_TI1S (1U << TIMER_CR2_TI1S_BIT) +#define TIMER_CR2_MMS (0x7 << 4) +#define TIMER_CR2_MMS_RESET (0x0 << 4) +#define TIMER_CR2_MMS_ENABLE (0x1 << 4) +#define TIMER_CR2_MMS_UPDATE (0x2 << 4) +#define TIMER_CR2_MMS_COMPARE_PULSE (0x3 << 4) +#define TIMER_CR2_MMS_COMPARE_OC1REF (0x4 << 4) +#define TIMER_CR2_MMS_COMPARE_OC2REF (0x5 << 4) +#define TIMER_CR2_MMS_COMPARE_OC3REF (0x6 << 4) +#define TIMER_CR2_MMS_COMPARE_OC4REF (0x7 << 4) +#define TIMER_CR2_CCDS (1U << TIMER_CR2_CCDS_BIT) +#define TIMER_CR2_CCUS (1U << TIMER_CR2_CCUS_BIT) +#define TIMER_CR2_CCPC (1U << TIMER_CR2_CCPC_BIT) + +/* Slave mode control register (SMCR) */ + +#define TIMER_SMCR_ETP_BIT 15 +#define TIMER_SMCR_ECE_BIT 14 +#define TIMER_SMCR_MSM_BIT 7 + +#define TIMER_SMCR_ETP (1U << TIMER_SMCR_ETP_BIT) +#define TIMER_SMCR_ECE (1U << TIMER_SMCR_ECE_BIT) +#define TIMER_SMCR_ETPS (0x3 << 12) +#define TIMER_SMCR_ETPS_OFF (0x0 << 12) +#define TIMER_SMCR_ETPS_DIV2 (0x1 << 12) +#define TIMER_SMCR_ETPS_DIV4 (0x2 << 12) +#define TIMER_SMCR_ETPS_DIV8 (0x3 << 12) +#define TIMER_SMCR_ETF (0xF << 12) +#define TIMER_SMCR_MSM (1U << TIMER_SMCR_MSM_BIT) +#define TIMER_SMCR_TS (0x7 << 4) +#define TIMER_SMCR_TS_ITR0 (0x0 << 4) +#define TIMER_SMCR_TS_ITR1 (0x1 << 4) +#define TIMER_SMCR_TS_ITR2 (0x2 << 4) +#define TIMER_SMCR_TS_ITR3 (0x3 << 4) +#define TIMER_SMCR_TS_TI1F_ED (0x4 << 4) +#define TIMER_SMCR_TS_TI1FP1 (0x5 << 4) +#define TIMER_SMCR_TS_TI2FP2 (0x6 << 4) +#define TIMER_SMCR_TS_ETRF (0x7 << 4) +#define TIMER_SMCR_SMS 0x7 +#define TIMER_SMCR_SMS_DISABLED 0x0 +#define TIMER_SMCR_SMS_ENCODER1 0x1 +#define TIMER_SMCR_SMS_ENCODER2 0x2 +#define TIMER_SMCR_SMS_ENCODER3 0x3 +#define TIMER_SMCR_SMS_RESET 0x4 +#define TIMER_SMCR_SMS_GATED 0x5 +#define TIMER_SMCR_SMS_TRIGGER 0x6 +#define TIMER_SMCR_SMS_EXTERNAL 0x7 + +/* DMA/Interrupt enable register (DIER) */ + +#define TIMER_DIER_TDE_BIT 14 +#define TIMER_DIER_COMDE_BIT 13 +#define TIMER_DIER_CC4DE_BIT 12 +#define TIMER_DIER_CC3DE_BIT 11 +#define TIMER_DIER_CC2DE_BIT 10 +#define TIMER_DIER_CC1DE_BIT 9 +#define TIMER_DIER_UDE_BIT 8 +#define TIMER_DIER_BIE_BIT 7 +#define TIMER_DIER_TIE_BIT 6 +#define TIMER_DIER_COMIE_BIT 5 +#define TIMER_DIER_CC4IE_BIT 4 +#define TIMER_DIER_CC3IE_BIT 3 +#define TIMER_DIER_CC2IE_BIT 2 +#define TIMER_DIER_CC1IE_BIT 1 +#define TIMER_DIER_UIE_BIT 0 + +#define TIMER_DIER_TDE (1U << TIMER_DIER_TDE_BIT) +#define TIMER_DIER_COMDE (1U << TIMER_DIER_COMDE_BIT) +#define TIMER_DIER_CC4DE (1U << TIMER_DIER_CC4DE_BIT) +#define TIMER_DIER_CC3DE (1U << TIMER_DIER_CC3DE_BIT) +#define TIMER_DIER_CC2DE (1U << TIMER_DIER_CC2DE_BIT) +#define TIMER_DIER_CC1DE (1U << TIMER_DIER_CC1DE_BIT) +#define TIMER_DIER_UDE (1U << TIMER_DIER_UDE_BIT) +#define TIMER_DIER_BIE (1U << TIMER_DIER_BIE_BIT) +#define TIMER_DIER_TIE (1U << TIMER_DIER_TIE_BIT) +#define TIMER_DIER_COMIE (1U << TIMER_DIER_COMIE_BIT) +#define TIMER_DIER_CC4IE (1U << TIMER_DIER_CC4IE_BIT) +#define TIMER_DIER_CC3IE (1U << TIMER_DIER_CC3IE_BIT) +#define TIMER_DIER_CC2IE (1U << TIMER_DIER_CC2IE_BIT) +#define TIMER_DIER_CC1IE (1U << TIMER_DIER_CC1IE_BIT) +#define TIMER_DIER_UIE (1U << TIMER_DIER_UIE_BIT) + +/* Status register (SR) */ + +#define TIMER_SR_CC4OF_BIT 12 +#define TIMER_SR_CC3OF_BIT 11 +#define TIMER_SR_CC2OF_BIT 10 +#define TIMER_SR_CC1OF_BIT 9 +#define TIMER_SR_BIF_BIT 7 +#define TIMER_SR_TIF_BIT 6 +#define TIMER_SR_COMIF_BIT 5 +#define TIMER_SR_CC4IF_BIT 4 +#define TIMER_SR_CC3IF_BIT 3 +#define TIMER_SR_CC2IF_BIT 2 +#define TIMER_SR_CC1IF_BIT 1 +#define TIMER_SR_UIF_BIT 0 + +#define TIMER_SR_CC4OF (1U << TIMER_SR_CC4OF_BIT) +#define TIMER_SR_CC3OF (1U << TIMER_SR_CC3OF_BIT) +#define TIMER_SR_CC2OF (1U << TIMER_SR_CC2OF_BIT) +#define TIMER_SR_CC1OF (1U << TIMER_SR_CC1OF_BIT) +#define TIMER_SR_BIF (1U << TIMER_SR_BIF_BIT) +#define TIMER_SR_TIF (1U << TIMER_SR_TIF_BIT) +#define TIMER_SR_COMIF (1U << TIMER_SR_COMIF_BIT) +#define TIMER_SR_CC4IF (1U << TIMER_SR_CC4IF_BIT) +#define TIMER_SR_CC3IF (1U << TIMER_SR_CC3IF_BIT) +#define TIMER_SR_CC2IF (1U << TIMER_SR_CC2IF_BIT) +#define TIMER_SR_CC1IF (1U << TIMER_SR_CC1IF_BIT) +#define TIMER_SR_UIF (1U << TIMER_SR_UIF_BIT) + +/* Event generation register (EGR) */ + +#define TIMER_EGR_BG_BIT 7 +#define TIMER_EGR_TG_BIT 6 +#define TIMER_EGR_COMG_BIT 5 +#define TIMER_EGR_CC4G_BIT 4 +#define TIMER_EGR_CC3G_BIT 3 +#define TIMER_EGR_CC2G_BIT 2 +#define TIMER_EGR_CC1G_BIT 1 +#define TIMER_EGR_UG_BIT 0 + +#define TIMER_EGR_BG (1U << TIMER_EGR_BG_BIT) +#define TIMER_EGR_TG (1U << TIMER_EGR_TG_BIT) +#define TIMER_EGR_COMG (1U << TIMER_EGR_COMG_BIT) +#define TIMER_EGR_CC4G (1U << TIMER_EGR_CC4G_BIT) +#define TIMER_EGR_CC3G (1U << TIMER_EGR_CC3G_BIT) +#define TIMER_EGR_CC2G (1U << TIMER_EGR_CC2G_BIT) +#define TIMER_EGR_CC1G (1U << TIMER_EGR_CC1G_BIT) +#define TIMER_EGR_UG (1U << TIMER_EGR_UG_BIT) + +/* Capture/compare mode registers, common values */ + +#define TIMER_CCMR_CCS_OUTPUT 0x0 +#define TIMER_CCMR_CCS_INPUT_TI1 0x1 +#define TIMER_CCMR_CCS_INPUT_TI2 0x2 +#define TIMER_CCMR_CCS_INPUT_TRC 0x3 + +/* Capture/compare mode register 1 (CCMR1) */ + +#define TIMER_CCMR1_OC2CE_BIT 15 +#define TIMER_CCMR1_OC2PE_BIT 11 +#define TIMER_CCMR1_OC2FE_BIT 10 +#define TIMER_CCMR1_OC1CE_BIT 7 +#define TIMER_CCMR1_OC1PE_BIT 3 +#define TIMER_CCMR1_OC1FE_BIT 2 + +#define TIMER_CCMR1_OC2CE (1U << TIMER_CCMR1_OC2CE_BIT) +#define TIMER_CCMR1_OC2M (0x3 << 12) +#define TIMER_CCMR1_IC2F (0xF << 12) +#define TIMER_CCMR1_OC2PE (1U << TIMER_CCMR1_OC2PE_BIT) +#define TIMER_CCMR1_OC2FE (1U << TIMER_CCMR1_OC2FE_BIT) +#define TIMER_CCMR1_IC2PSC (0x3 << 10) +#define TIMER_CCMR1_CC2S (0x3 << 8) +#define TIMER_CCMR1_CC2S_OUTPUT (TIMER_CCMR_CCS_OUTPUT << 8) +#define TIMER_CCMR1_CC2S_INPUT_TI1 (TIMER_CCMR_CCS_INPUT_TI1 << 8) +#define TIMER_CCMR1_CC2S_INPUT_TI2 (TIMER_CCMR_CCS_INPUT_TI2 << 8) +#define TIMER_CCMR1_CC2S_INPUT_TRC (TIMER_CCMR_CCS_INPUT_TRC << 8) +#define TIMER_CCMR1_OC1CE (1U << TIMER_CCMR1_OC1CE_BIT) +#define TIMER_CCMR1_OC1M (0x3 << 4) +#define TIMER_CCMR1_IC1F (0xF << 4) +#define TIMER_CCMR1_OC1PE (1U << TIMER_CCMR1_OC1PE_BIT) +#define TIMER_CCMR1_OC1FE (1U << TIMER_CCMR1_OC1FE_BIT) +#define TIMER_CCMR1_IC1PSC (0x3 << 2) +#define TIMER_CCMR1_CC1S 0x3 +#define TIMER_CCMR1_CC1S_OUTPUT TIMER_CCMR_CCS_OUTPUT +#define TIMER_CCMR1_CC1S_INPUT_TI1 TIMER_CCMR_CCS_INPUT_TI1 +#define TIMER_CCMR1_CC1S_INPUT_TI2 TIMER_CCMR_CCS_INPUT_TI2 +#define TIMER_CCMR1_CC1S_INPUT_TRC TIMER_CCMR_CCS_INPUT_TRC + +/* Capture/compare mode register 2 (CCMR2) */ + +#define TIMER_CCMR2_OC4CE_BIT 15 +#define TIMER_CCMR2_OC4PE_BIT 11 +#define TIMER_CCMR2_OC4FE_BIT 10 +#define TIMER_CCMR2_OC3CE_BIT 7 +#define TIMER_CCMR2_OC3PE_BIT 3 +#define TIMER_CCMR2_OC3FE_BIT 2 + +#define TIMER_CCMR2_OC4CE (1U << TIMER_CCMR2_OC4CE_BIT) +#define TIMER_CCMR2_OC4M (0x3 << 12) +#define TIMER_CCMR2_IC4F (0xF << 12) +#define TIMER_CCMR2_OC4PE (1U << TIMER_CCMR2_OC4PE_BIT) +#define TIMER_CCMR2_OC4FE (1U << TIMER_CCMR2_OC4FE_BIT) +#define TIMER_CCMR2_IC4PSC (0x3 << 10) +#define TIMER_CCMR2_CC4S (0x3 << 8) +#define TIMER_CCMR2_CC4S_OUTPUT (TIMER_CCMR_CCS_OUTPUT << 8) +#define TIMER_CCMR2_CC4S_INPUT_TI1 (TIMER_CCMR_CCS_INPUT_TI1 << 8) +#define TIMER_CCMR2_CC4S_INPUT_TI2 (TIMER_CCMR_CCS_INPUT_TI2 << 8) +#define TIMER_CCMR2_CC4S_INPUT_TRC (TIMER_CCMR_CCS_INPUT_TRC << 8) +#define TIMER_CCMR2_OC3CE (1U << TIMER_CCMR2_OC3CE_BIT) +#define TIMER_CCMR2_OC3M (0x3 << 4) +#define TIMER_CCMR2_IC3F (0xF << 4) +#define TIMER_CCMR2_OC3PE (1U << TIMER_CCMR2_OC3PE_BIT) +#define TIMER_CCMR2_OC3FE (1U << TIMER_CCMR2_OC3FE_BIT) +#define TIMER_CCMR2_IC3PSC (0x3 << 2) +#define TIMER_CCMR2_CC3S 0x3 +#define TIMER_CCMR2_CC3S_OUTPUT TIMER_CCMR_CCS_OUTPUT +#define TIMER_CCMR2_CC3S_INPUT_TI1 TIMER_CCMR_CCS_INPUT_TI1 +#define TIMER_CCMR2_CC3S_INPUT_TI2 TIMER_CCMR_CCS_INPUT_TI2 +#define TIMER_CCMR2_CC3S_INPUT_TRC TIMER_CCMR_CCS_INPUT_TRC + +/* Capture/compare enable register (CCER) */ + +#define TIMER_CCER_CC4P_BIT 13 +#define TIMER_CCER_CC4E_BIT 12 +#define TIMER_CCER_CC3NP_BIT 11 +#define TIMER_CCER_CC3NE_BIT 10 +#define TIMER_CCER_CC3P_BIT 9 +#define TIMER_CCER_CC3E_BIT 8 +#define TIMER_CCER_CC2NP_BIT 7 +#define TIMER_CCER_CC2NE_BIT 6 +#define TIMER_CCER_CC2P_BIT 5 +#define TIMER_CCER_CC2E_BIT 4 +#define TIMER_CCER_CC1NP_BIT 3 +#define TIMER_CCER_CC1NE_BIT 2 +#define TIMER_CCER_CC1P_BIT 1 +#define TIMER_CCER_CC1E_BIT 0 + +#define TIMER_CCER_CC4P (1U << TIMER_CCER_CC4P_BIT) +#define TIMER_CCER_CC4E (1U << TIMER_CCER_CC4E_BIT) +#define TIMER_CCER_CC3NP (1U << TIMER_CCER_CC3NP_BIT) +#define TIMER_CCER_CC3NE (1U << TIMER_CCER_CC3NE_BIT) +#define TIMER_CCER_CC3P (1U << TIMER_CCER_CC3P_BIT) +#define TIMER_CCER_CC3E (1U << TIMER_CCER_CC3E_BIT) +#define TIMER_CCER_CC2NP (1U << TIMER_CCER_CC2NP_BIT) +#define TIMER_CCER_CC2NE (1U << TIMER_CCER_CC2NE_BIT) +#define TIMER_CCER_CC2P (1U << TIMER_CCER_CC2P_BIT) +#define TIMER_CCER_CC2E (1U << TIMER_CCER_CC2E_BIT) +#define TIMER_CCER_CC1NP (1U << TIMER_CCER_CC1NP_BIT) +#define TIMER_CCER_CC1NE (1U << TIMER_CCER_CC1NE_BIT) +#define TIMER_CCER_CC1P (1U << TIMER_CCER_CC1P_BIT) +#define TIMER_CCER_CC1E (1U << TIMER_CCER_CC1E_BIT) + +/* Break and dead-time register (BDTR) */ + +#define TIMER_BDTR_MOE_BIT 15 +#define TIMER_BDTR_AOE_BIT 14 +#define TIMER_BDTR_BKP_BIT 13 +#define TIMER_BDTR_BKE_BIT 12 +#define TIMER_BDTR_OSSR_BIT 11 +#define TIMER_BDTR_OSSI_BIT 10 + +#define TIMER_BDTR_MOE (1U << TIMER_BDTR_MOE_BIT) +#define TIMER_BDTR_AOE (1U << TIMER_BDTR_AOE_BIT) +#define TIMER_BDTR_BKP (1U << TIMER_BDTR_BKP_BIT) +#define TIMER_BDTR_BKE (1U << TIMER_BDTR_BKE_BIT) +#define TIMER_BDTR_OSSR (1U << TIMER_BDTR_OSSR_BIT) +#define TIMER_BDTR_OSSI (1U << TIMER_BDTR_OSSI_BIT) +#define TIMER_BDTR_LOCK (0x3 << 8) +#define TIMER_BDTR_LOCK_OFF (0x0 << 8) +#define TIMER_BDTR_LOCK_LEVEL1 (0x1 << 8) +#define TIMER_BDTR_LOCK_LEVEL2 (0x2 << 8) +#define TIMER_BDTR_LOCK_LEVEL3 (0x3 << 8) +#define TIMER_BDTR_DTG 0xFF + +/* DMA control register (DCR) */ + +#define TIMER_DCR_DBL (0x1F << 8) +#define TIMER_DCR_DBL_1_XFER (0x0 << 8) +#define TIMER_DCR_DBL_2_XFER (0x1 << 8) +#define TIMER_DCR_DBL_3_XFER (0x2 << 8) +#define TIMER_DCR_DBL_4_XFER (0x3 << 8) +#define TIMER_DCR_DBL_5_XFER (0x4 << 8) +#define TIMER_DCR_DBL_6_XFER (0x5 << 8) +#define TIMER_DCR_DBL_7_XFER (0x6 << 8) +#define TIMER_DCR_DBL_8_XFER (0x7 << 8) +#define TIMER_DCR_DBL_9_XFER (0x8 << 8) +#define TIMER_DCR_DBL_10_XFER (0x9 << 8) +#define TIMER_DCR_DBL_11_XFER (0xA << 8) +#define TIMER_DCR_DBL_12_XFER (0xB << 8) +#define TIMER_DCR_DBL_13_XFER (0xC << 8) +#define TIMER_DCR_DBL_14_XFER (0xD << 8) +#define TIMER_DCR_DBL_15_XFER (0xE << 8) +#define TIMER_DCR_DBL_16_XFER (0xF << 8) +#define TIMER_DCR_DBL_17_XFER (0x10 << 8) +#define TIMER_DCR_DBL_18_XFER (0x11 << 8) +#define TIMER_DCR_DBA 0x1F +#define TIMER_DCR_DBA_CR1 0x0 +#define TIMER_DCR_DBA_CR2 0x1 +#define TIMER_DCR_DBA_SMCR 0x2 +#define TIMER_DCR_DBA_DIER 0x3 +#define TIMER_DCR_DBA_SR 0x4 +#define TIMER_DCR_DBA_EGR 0x5 +#define TIMER_DCR_DBA_CCMR1 0x6 +#define TIMER_DCR_DBA_CCMR2 0x7 +#define TIMER_DCR_DBA_CCER 0x8 +#define TIMER_DCR_DBA_CNT 0x9 +#define TIMER_DCR_DBA_PSC 0xA +#define TIMER_DCR_DBA_ARR 0xB +#define TIMER_DCR_DBA_RCR 0xC +#define TIMER_DCR_DBA_CCR1 0xD +#define TIMER_DCR_DBA_CCR2 0xE +#define TIMER_DCR_DBA_CCR3 0xF +#define TIMER_DCR_DBA_CCR4 0x10 +#define TIMER_DCR_DBA_BDTR 0x11 +#define TIMER_DCR_DBA_DCR 0x12 +#define TIMER_DCR_DBA_DMAR 0x13 + +/* + * Convenience routines + */ + +/** + * @brief Used to configure the behavior of a timer channel. + * + * Be careful: not all timers can be configured in every mode. + */ +typedef enum timer_mode { + /** + * The timer stops counting, channel interrupts are detached, and + * no state changes are output. */ + TIMER_DISABLED, + + /** PWM output. */ + TIMER_PWM, + + /* TIMER_PWM_CENTER_ALIGNED, TODO: Center-aligned PWM output mode. */ + + /** + * The timer counts from 0 to its reload value repeatedly; every + * time the counter value reaches one of the channel compare + * values, the corresponding interrupt is fired. */ + TIMER_OUTPUT_COMPARE, + + /* TIMER_INPUT_CAPTURE, TODO: In this mode, the timer can measure the + * pulse lengths of input signals */ + /* TIMER_ONE_PULSE, TODO: In this mode, the timer can generate a single + * pulse on a GPIO pin for a specified amount of + * time. */ + + TIMER_ENCODER, //CARLOS Change +} timer_mode; + +/** Timer channel numbers */ +typedef enum timer_channel { + TIMER_CH1 = 1, /**< Channel 1 */ + TIMER_CH2 = 2, /**< Channel 2 */ + TIMER_CH3 = 3, /**< Channel 3 */ + TIMER_CH4 = 4 /**< Channel 4 */ +} timer_channel; + +/* + * Note: Don't require timer_channel arguments! We want to be able to say + * + * for (int channel = 1; channel <= 4; channel++) { + * ... + * } + * + * without the compiler yelling at us. + */ + +void timer_init(timer_dev *dev); +void timer_disable(timer_dev *dev); +void timer_set_mode(timer_dev *dev, uint8 channel, timer_mode mode); +void timer_foreach(void (*fn)(timer_dev*)); +int timer_has_cc_channel(timer_dev *dev, uint8 channel); + +/** + * @brief Timer interrupt number. + * + * Not all timers support all of these values. All timers support + * TIMER_UPDATE_INTERRUPT. "General purpose" timers can be a special + * nuisance in this regard, as they individually support different + * subsets of the available interupts. Consult your target's reference + * manual for the details. + */ +typedef enum timer_interrupt_id { + TIMER_UPDATE_INTERRUPT, /**< Update interrupt. */ + TIMER_CC1_INTERRUPT, /**< Capture/compare 1 interrupt. */ + TIMER_CC2_INTERRUPT, /**< Capture/compare 2 interrupt. */ + TIMER_CC3_INTERRUPT, /**< Capture/compare 3 interrupt. */ + TIMER_CC4_INTERRUPT, /**< Capture/compare 4 interrupt. */ + TIMER_COM_INTERRUPT, /**< COM interrupt. */ + TIMER_TRG_INTERRUPT, /**< Trigger interrupt. */ + TIMER_BREAK_INTERRUPT, /**< Break interrupt. */ +} timer_interrupt_id; + +void timer_attach_interrupt(timer_dev *dev, + uint8 interrupt, + voidFuncPtr handler); +void timer_detach_interrupt(timer_dev *dev, uint8 interrupt); + +//CARLOS +uint8 get_direction(timer_dev *dev); + + + +/** + * Initialize all timer devices on the chip. + */ +static inline void timer_init_all(void) { + timer_foreach(timer_init); +} + +/** + * Disables all timers on the device. + */ +static inline void timer_disable_all(void) { + timer_foreach(timer_disable); +} + +/** + * @brief Stop a timer's counter from changing. + * + * Does not affect the timer's mode or other settings. + * + * @param dev Device whose counter to pause. + */ +static inline void timer_pause(timer_dev *dev) { + *bb_perip(&(dev->regs).bas->CR1, TIMER_CR1_CEN_BIT) = 0; +} + +/** + * @brief Start a timer's counter. + * + * Does not affect the timer's mode or other settings. + * + * @param dev Device whose counter to resume + */ +static inline void timer_resume(timer_dev *dev) { + *bb_perip(&(dev->regs).bas->CR1, TIMER_CR1_CEN_BIT) = 1; +} + +/** + * @brief Returns the timer's counter value. + * + * This value is likely to be inaccurate if the counter is running + * with a low prescaler. + * + * @param dev Timer whose counter to return + */ +static inline uint16 timer_get_count(timer_dev *dev) { + return (uint16)(dev->regs).bas->CNT; +} + +/** + * @brief Sets the counter value for the given timer. + * @param dev Timer whose counter to set + * @param value New counter value + */ +static inline void timer_set_count(timer_dev *dev, uint16 value) { + (dev->regs).bas->CNT = value; +} + +/** + * @brief Returns the given timer's prescaler. + * + * Note that if the timer's prescaler is set (e.g. via + * timer_set_prescaler() or accessing a TIMx_PSC register), the value + * returned by this function will reflect the new setting, but the + * timer's counter will only reflect the new prescaler at the next + * update event. + * + * @param dev Timer whose prescaler to return + * @see timer_generate_update() + */ +static inline uint16 timer_get_prescaler(timer_dev *dev) { + return (uint16)(dev->regs).bas->PSC; +} + +/** + * @brief Set a timer's prescale value. + * + * Divides the input clock by (PSC+1). The new value will not take + * effect until the next update event. + * + * @param dev Timer whose prescaler to set + * @param psc New prescaler value + * @see timer_generate_update() + */ +static inline void timer_set_prescaler(timer_dev *dev, uint16 psc) { + (dev->regs).bas->PSC = psc; +} + +/** + * @brief Returns a timer's reload value. + * @param dev Timer whose reload value to return + */ +static inline uint16 timer_get_reload(timer_dev *dev) { + return (uint16)(dev->regs).bas->ARR; +} + +/** + * @brief Set a timer's reload value. + * @param dev Timer whose reload value to set + * @param arr New reload value to use. Takes effect at next update event. + * @see timer_generate_update() + */ +static inline void timer_set_reload(timer_dev *dev, uint16 arr) { + (dev->regs).bas->ARR = arr; +} + +/** + * @brief Get the compare value for the given timer channel. + * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL. + * @param channel Channel whose compare value to get. + */ +static inline uint16 timer_get_compare(timer_dev *dev, uint8 channel) { + __io uint32 *ccr = &(dev->regs).gen->CCR1 + (channel - 1); + return *ccr; +} + +/** + * @brief Set the compare value for the given timer channel. + * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL. + * @param channel Channel whose compare value to set. + * @param value New compare value. + */ +static inline void timer_set_compare(timer_dev *dev, + uint8 channel, + uint16 value) { + __io uint32 *ccr = &(dev->regs).gen->CCR1 + (channel - 1); + *ccr = value; +} + +/** + * @brief Generate an update event for the given timer. + * + * Normally, this will cause the prescaler and auto-reload values in + * the PSC and ARR registers to take immediate effect. However, this + * function will do nothing if the UDIS bit is set in the timer's CR1 + * register (UDIS is cleared by default). + * + * @param dev Timer device to generate an update for. + */ +static inline void timer_generate_update(timer_dev *dev) { + *bb_perip(&(dev->regs).bas->EGR, TIMER_EGR_UG_BIT) = 1; +} + +/** + * @brief Enable a timer's trigger DMA request + * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL + */ +static inline void timer_dma_enable_trg_req(timer_dev *dev) { + *bb_perip(&(dev->regs).gen->DIER, TIMER_DIER_TDE_BIT) = 1; +} + +/** + * @brief Disable a timer's trigger DMA request + * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL + */ +static inline void timer_dma_disable_trg_req(timer_dev *dev) { + *bb_perip(&(dev->regs).gen->DIER, TIMER_DIER_TDE_BIT) = 0; +} + +/** + * @brief Enable a timer's update DMA request + * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL + */ +static inline void timer_dma_enable_upd_req(timer_dev *dev) { + *bb_perip(&(dev->regs).gen->DIER, TIMER_DIER_UDE_BIT) = 1; +} + +/** + * @brief Disable a timer's update DMA request + * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL + */ +static inline void timer_dma_disable_upd_req(timer_dev *dev) { + *bb_perip(&(dev->regs).gen->DIER, TIMER_DIER_UDE_BIT) = 0; +} + +/** + * @brief Enable a timer channel's DMA request. + * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL + * @param channel Channel whose DMA request to enable. + */ +static inline void timer_dma_enable_req(timer_dev *dev, uint8 channel) { + *bb_perip(&(dev->regs).gen->DIER, channel + 8) = 1; +} + +/** + * @brief Disable a timer channel's DMA request. + * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL. + * @param channel Channel whose DMA request to disable. + */ +static inline void timer_dma_disable_req(timer_dev *dev, uint8 channel) { + *bb_perip(&(dev->regs).gen->DIER, channel + 8) = 0; +} + +/** + * @brief Enable a timer interrupt. + * @param dev Timer device. + * @param interrupt Interrupt number to enable; this may be any + * timer_interrupt_id value appropriate for the timer. + * @see timer_interrupt_id + * @see timer_channel + */ +static inline void timer_enable_irq(timer_dev *dev, uint8 interrupt) { + *bb_perip(&(dev->regs).adv->SR, interrupt) = 0; // clear interrupt flag + *bb_perip(&(dev->regs).adv->DIER, interrupt) = 1; +} + +/** + * @brief Disable a timer interrupt. + * @param dev Timer device. + * @param interrupt Interrupt number to disable; this may be any + * timer_interrupt_id value appropriate for the timer. + * @see timer_interrupt_id + * @see timer_channel + */ +static inline void timer_disable_irq(timer_dev *dev, uint8 interrupt) { + *bb_perip(&(dev->regs).adv->DIER, interrupt) = 0; +} + +/** + * @brief Enable a timer channel's capture/compare signal. + * + * If the channel is configured as output, the corresponding output + * compare signal will be output on the corresponding output pin. If + * the channel is configured as input, enables capture of the counter + * value into the input capture/compare register. + * + * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL. + * @param channel Channel to enable, from 1 to 4. + */ +static inline void timer_cc_enable(timer_dev *dev, uint8 channel) { + *bb_perip(&(dev->regs).gen->CCER, 4 * (channel - 1)) = 1; +} + +/** + * @brief Disable a timer channel's output compare or input capture signal. + * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL. + * @param channel Channel to disable, from 1 to 4. + * @see timer_cc_enable() + */ +static inline void timer_cc_disable(timer_dev *dev, uint8 channel) { + *bb_perip(&(dev->regs).gen->CCER, 4 * (channel - 1)) = 0; +} + +/** + * @brief Get a channel's capture/compare output polarity + * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL. + * @param channel Channel whose capture/compare output polarity to get. + * @return Polarity, either 0 or 1. + * @see timer_cc_set_polarity() + */ +static inline uint8 timer_cc_get_pol(timer_dev *dev, uint8 channel) { + return *bb_perip(&(dev->regs).gen->CCER, 4 * (channel - 1) + 1); +} + +/** + * @brief Set a timer channel's capture/compare output polarity. + * + * If the timer channel is configured as output: polarity == 0 means + * the output channel will be active high; polarity == 1 means active + * low. + * + * If the timer channel is configured as input: polarity == 0 means + * capture is done on the rising edge of ICn; when used as an external + * trigger, ICn is non-inverted. polarity == 1 means capture is done + * on the falling edge of ICn; when used as an external trigger, ICn + * is inverted. + * + * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL. + * @param channel Channel whose capture/compare output polarity to set. + * @param pol New polarity, 0 or 1. + */ +static inline void timer_cc_set_pol(timer_dev *dev, uint8 channel, uint8 pol) { + *bb_perip(&(dev->regs).gen->CCER, 4 * (channel - 1) + 1) = pol; +} + +/** + * @brief Get a timer's DMA burst length. + * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL. + * @return Number of transfers per read or write to timer DMA register, + * from 1 to 18. + */ +static inline uint8 timer_dma_get_burst_len(timer_dev *dev) { + uint32 dbl = ((dev->regs).gen->DCR & TIMER_DCR_DBL) >> 8; + return dbl + 1; /* 0 means 1 transfer, etc. */ +} + +/** + * @brief Set a timer's DMA burst length. + * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL. + * @param length DMA burst length; i.e., number of DMA transfers per + * read/write to timer DMA register, from 1 to 18. + */ +static inline void timer_dma_set_burst_len(timer_dev *dev, uint8 length) { + uint32 tmp = (dev->regs).gen->DCR; + tmp &= ~TIMER_DCR_DBL; + tmp |= (length - 1) << 8; + (dev->regs).gen->DCR = tmp; +} + +/** + * @brief Timer DMA base address. + * + * Defines the base address for DMA transfers. + */ +typedef enum timer_dma_base_addr { + /** Base is control register 1 */ + TIMER_DMA_BASE_CR1 = TIMER_DCR_DBA_CR1, + /** Base is control register 2 */ + TIMER_DMA_BASE_CR2 = TIMER_DCR_DBA_CR2, + /** Base is slave mode control register */ + TIMER_DMA_BASE_SMCR = TIMER_DCR_DBA_SMCR, + /** Base is DMA interrupt enable register */ + TIMER_DMA_BASE_DIER = TIMER_DCR_DBA_DIER, + /** Base is status register */ + TIMER_DMA_BASE_SR = TIMER_DCR_DBA_SR, + /** Base is event generation register */ + TIMER_DMA_BASE_EGR = TIMER_DCR_DBA_EGR, + /** Base is capture/compare mode register 1 */ + TIMER_DMA_BASE_CCMR1 = TIMER_DCR_DBA_CCMR1, + /** Base is capture/compare mode register 2 */ + TIMER_DMA_BASE_CCMR2 = TIMER_DCR_DBA_CCMR2, + /** Base is capture/compare enable register */ + TIMER_DMA_BASE_CCER = TIMER_DCR_DBA_CCER, + /** Base is counter */ + TIMER_DMA_BASE_CNT = TIMER_DCR_DBA_CNT, + /** Base is prescaler */ + TIMER_DMA_BASE_PSC = TIMER_DCR_DBA_PSC, + /** Base is auto-reload register */ + TIMER_DMA_BASE_ARR = TIMER_DCR_DBA_ARR, + /** Base is repetition counter register */ + TIMER_DMA_BASE_RCR = TIMER_DCR_DBA_RCR, + /** Base is capture/compare register 1 */ + TIMER_DMA_BASE_CCR1 = TIMER_DCR_DBA_CCR1, + /** Base is capture/compare register 2 */ + TIMER_DMA_BASE_CCR2 = TIMER_DCR_DBA_CCR2, + /** Base is capture/compare register 3 */ + TIMER_DMA_BASE_CCR3 = TIMER_DCR_DBA_CCR3, + /** Base is capture/compare register 4 */ + TIMER_DMA_BASE_CCR4 = TIMER_DCR_DBA_CCR4, + /** Base is break and dead-time register */ + TIMER_DMA_BASE_BDTR = TIMER_DCR_DBA_BDTR, + /** Base is DMA control register */ + TIMER_DMA_BASE_DCR = TIMER_DCR_DBA_DCR, + /** Base is DMA address for full transfer */ + TIMER_DMA_BASE_DMAR = TIMER_DCR_DBA_DMAR, +} timer_dma_base_addr; + +/** + * @brief Get the timer's DMA base address. + * + * Some restrictions apply; see the reference manual for your chip. + * + * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL. + * @return DMA base address + */ +static inline timer_dma_base_addr timer_dma_get_base_addr(timer_dev *dev) { + uint32 dcr = (dev->regs).gen->DCR; + return (timer_dma_base_addr)(dcr & TIMER_DCR_DBA); +} + +/** + * @brief Set the timer's DMA base address. + * + * Some restrictions apply; see the reference manual for your chip. + * + * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL. + * @param dma_base DMA base address. + */ +static inline void timer_dma_set_base_addr(timer_dev *dev, + timer_dma_base_addr dma_base) { + uint32 tmp = (dev->regs).gen->DCR; + tmp &= ~TIMER_DCR_DBA; + tmp |= dma_base; + (dev->regs).gen->DCR = tmp; +} + +/** + * Timer output compare modes. + */ +typedef enum timer_oc_mode { + /** + * Frozen: comparison between output compare register and counter + * has no effect on the outputs. */ + TIMER_OC_MODE_FROZEN = 0 << 4, + /** + * OCxREF signal is forced high when the count matches the channel + * capture/compare register. */ + TIMER_OC_MODE_ACTIVE_ON_MATCH = 1 << 4, + /** + * OCxREF signal is forced low when the counter matches the + * channel capture/compare register. */ + TIMER_OC_MODE_INACTIVE_ON_MATCH = 2 << 4, + /** + * OCxREF toggles when counter matches the channel capture/compare + * register. */ + TIMER_OC_MODE_TOGGLE = 3 << 4, + /** OCxREF is forced low. */ + TIMER_OC_MODE_FORCE_INACTIVE = 4 << 4, + /** OCxREF is forced high. */ + TIMER_OC_MODE_FORCE_ACTIVE = 5 << 4, + /** + * PWM mode 1. In upcounting, channel is active as long as count + * is less than channel capture/compare register, else inactive. + * In downcounting, channel is inactive as long as count exceeds + * capture/compare register, else active. */ + TIMER_OC_MODE_PWM_1 = 6 << 4, + /** + * PWM mode 2. In upcounting, channel is inactive as long as count + * is less than capture/compare register, else active. In + * downcounting, channel is active as long as count exceeds + * capture/compare register, else inactive. */ + TIMER_OC_MODE_PWM_2 = 7 << 4, +} timer_oc_mode; + +/** + * Timer output compare mode flags. + * @see timer_oc_set_mode() + */ +typedef enum timer_oc_mode_flags { + TIMER_OC_CE = 1U << 7, /**< Output compare clear enable. */ + TIMER_OC_PE = 1U << 3, /**< Output compare preload enable. */ + TIMER_OC_FE = 1U << 2, /**< Output compare fast enable. */ +} timer_oc_mode_flags; + +/** + * @brief Configure a channel's output compare mode. + * + * @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL. + * @param channel Channel to configure in output compare mode. + * @param mode Timer mode to set. + * @param flags OR of timer_oc_mode_flags. + * @see timer_oc_mode + * @see timer_oc_mode_flags + */ +static inline void timer_oc_set_mode(timer_dev *dev, + uint8 channel, + timer_oc_mode mode, + uint8 flags) { + /* channel == 1,2 -> CCMR1; channel == 3,4 -> CCMR2 */ + __io uint32 *ccmr = &(dev->regs).gen->CCMR1 + (((channel - 1) >> 1) & 1); + /* channel == 1,3 -> shift = 0, channel == 2,4 -> shift = 8 */ + uint8 shift = 8 * (1 - (channel & 1)); + + uint32 tmp = *ccmr; + tmp &= ~(0xFF << shift); + tmp |= (mode | flags | TIMER_CCMR_CCS_OUTPUT) << shift; + *ccmr = tmp; +} + +/* + * Old, erroneous bit definitions from previous releases, kept for + * backwards compatibility: + */ + +/** Deprecated. Use TIMER_CCMR1_CC4S_OUTPUT instead. */ +#define TIMER_CCMR1_CC4S_OUTPUT TIMER_CCMR2_CC4S_OUTPUT +/** Deprecated. Use TIMER_CCMR1_CC4S_INPUT_TI1 instead. */ +#define TIMER_CCMR1_CC4S_INPUT_TI1 TIMER_CCMR2_CC4S_INPUT_TI1 +/** Deprecated. Use TIMER_CCMR1_CC4S_INPUT_TI2 instead. */ +#define TIMER_CCMR1_CC4S_INPUT_TI2 TIMER_CCMR2_CC4S_INPUT_TI2 +/** Deprecated. Use TIMER_CCMR1_CC4S_INPUT_TRC instead. */ +#define TIMER_CCMR1_CC4S_INPUT_TRC TIMER_CCMR2_CC4S_INPUT_TRC +/** Deprecated. Use TIMER_CCMR2_IC4F instead. */ +#define TIMER_CCMR2_IC2F TIMER_CCMR2_IC4F +/** Deprecated. Use TIMER_CCMR2_IC4PSC instead. */ +#define TIMER_CCMR2_IC2PSC TIMER_CCMR2_IC4PSC +/** Deprecated. Use TIMER_CCMR2_IC3F instead. */ +#define TIMER_CCMR2_IC1F TIMER_CCMR2_IC3F +/** Deprecated. Use TIMER_CCMR2_IC3PSC instead. */ +#define TIMER_CCMR2_IC1PSC TIMER_CCMR2_IC3PSC +/** Deprecated. Use TIMER_CCMR1_CC3S_OUTPUT instead. */ +#define TIMER_CCMR1_CC3S_OUTPUT TIMER_CCMR2_CC3S_OUTPUT +/** Deprecated. Use TIMER_CCMR1_CC3S_INPUT_TI1 instead. */ +#define TIMER_CCMR1_CC3S_INPUT_TI1 TIMER_CCMR2_CC3S_INPUT_TI1 +/** Deprecated. Use TIMER_CCMR1_CC3S_INPUT_TI2 instead. */ +#define TIMER_CCMR1_CC3S_INPUT_TI2 TIMER_CCMR2_CC3S_INPUT_TI2 +/** Deprecated. Use TIMER_CCMR1_CC3S_INPUT_TRC instead. */ +#define TIMER_CCMR1_CC3S_INPUT_TRC TIMER_CCMR2_CC3S_INPUT_TRC + +/** Deprecated. Use TIMER_DCR_DBL_1_XFER instead. */ +#define TIMER_DCR_DBL_1BYTE TIMER_DCR_DBL_1_XFER +/** Deprecated. Use TIMER_DCR_DBL_2_XFER instead. */ +#define TIMER_DCR_DBL_2BYTE TIMER_DCR_DBL_2_XFER +/** Deprecated. Use TIMER_DCR_DBL_3_XFER instead. */ +#define TIMER_DCR_DBL_3BYTE TIMER_DCR_DBL_3_XFER +/** Deprecated. Use TIMER_DCR_DBL_4_XFER instead. */ +#define TIMER_DCR_DBL_4BYTE TIMER_DCR_DBL_4_XFER +/** Deprecated. Use TIMER_DCR_DBL_5_XFER instead. */ +#define TIMER_DCR_DBL_5BYTE TIMER_DCR_DBL_5_XFER +/** Deprecated. Use TIMER_DCR_DBL_6_XFER instead. */ +#define TIMER_DCR_DBL_6BYTE TIMER_DCR_DBL_6_XFER +/** Deprecated. Use TIMER_DCR_DBL_7_XFER instead. */ +#define TIMER_DCR_DBL_7BYTE TIMER_DCR_DBL_7_XFER +/** Deprecated. Use TIMER_DCR_DBL_8_XFER instead. */ +#define TIMER_DCR_DBL_8BYTE TIMER_DCR_DBL_8_XFER +/** Deprecated. Use TIMER_DCR_DBL_9_XFER instead. */ +#define TIMER_DCR_DBL_9BYTE TIMER_DCR_DBL_9_XFER +/** Deprecated. Use TIMER_DCR_DBL_10_XFER instead. */ +#define TIMER_DCR_DBL_10BYTE TIMER_DCR_DBL_10_XFER +/** Deprecated. Use TIMER_DCR_DBL_11_XFER instead. */ +#define TIMER_DCR_DBL_11BYTE TIMER_DCR_DBL_11_XFER +/** Deprecated. Use TIMER_DCR_DBL_12_XFER instead. */ +#define TIMER_DCR_DBL_12BYTE TIMER_DCR_DBL_12_XFER +/** Deprecated. Use TIMER_DCR_DBL_13_XFER instead. */ +#define TIMER_DCR_DBL_13BYTE TIMER_DCR_DBL_13_XFER +/** Deprecated. Use TIMER_DCR_DBL_14_XFER instead. */ +#define TIMER_DCR_DBL_14BYTE TIMER_DCR_DBL_14_XFER +/** Deprecated. Use TIMER_DCR_DBL_15_XFER instead. */ +#define TIMER_DCR_DBL_15BYTE TIMER_DCR_DBL_15_XFER +/** Deprecated. Use TIMER_DCR_DBL_16_XFER instead. */ +#define TIMER_DCR_DBL_16BYTE TIMER_DCR_DBL_16_XFER +/** Deprecated. Use TIMER_DCR_DBL_17_XFER instead. */ +#define TIMER_DCR_DBL_17BYTE TIMER_DCR_DBL_17_XFER +/** Deprecated. Use TIMER_DCR_DBL_18_XFER instead. */ +#define TIMER_DCR_DBL_18BYTE TIMER_DCR_DBL_18_XFER + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/usart.h b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/usart.h new file mode 100644 index 0000000..245ddab --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/usart.h @@ -0,0 +1,523 @@ +/****************************************************************************** + * 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/include/libmaple/usart.h + * @author Marti Bolivar , + * Perry Hung + * @brief USART definitions and prototypes + */ + +#ifndef _LIBMAPLE_USART_H_ +#define _LIBMAPLE_USART_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include +#include +#include +#include +#include + + /* Roger clark. Replaced with line below #include */ +#include "stm32f1/include/series/usart.h" + +/* + * Register map (common across supported STM32 series). + */ + +/** USART register map type */ +typedef struct usart_reg_map { + __io uint32 SR; /**< Status register */ + __io uint32 DR; /**< Data register */ + __io uint32 BRR; /**< Baud rate register */ + __io uint32 CR1; /**< Control register 1 */ + __io uint32 CR2; /**< Control register 2 */ + __io uint32 CR3; /**< Control register 3 */ + __io uint32 GTPR; /**< Guard time and prescaler register */ +} usart_reg_map; + +/* + * Register bit definitions + */ + +/* Status register */ + +/** Clear to send bit */ +#define USART_SR_CTS_BIT 9 +/** Line break detection bit */ +#define USART_SR_LBD_BIT 8 +/** Transmit data register empty bit */ +#define USART_SR_TXE_BIT 7 +/** Transmission complete bit */ +#define USART_SR_TC_BIT 6 +/** Read data register not empty bit */ +#define USART_SR_RXNE_BIT 5 +/** IDLE line detected bit */ +#define USART_SR_IDLE_BIT 4 +/** Overrun error bit */ +#define USART_SR_ORE_BIT 3 +/** Noise error bit */ +#define USART_SR_NE_BIT 2 +/** + * @brief Synonym for USART_SR_NE_BIT. + * + * Some series (e.g. STM32F2) use "NF" for "noise flag" instead of the + * original "NE" for "noise error". The meaning of the bit is + * unchanged, but the NF flag can be disabled when the line is + * noise-free. + * + * @see USART_SR_NE_BIT + */ +#define USART_SR_NF_BIT USART_SR_NE_BIT +/** Framing error bit */ +#define USART_SR_FE_BIT 1 +/** Parity error bit */ +#define USART_SR_PE_BIT 0 + +/** Clear to send mask */ +#define USART_SR_CTS BIT(USART_SR_CTS_BIT) +/** Line break detected mask */ +#define USART_SR_LBD BIT(USART_SR_LBD_BIT) +/** Transmit data register empty mask */ +#define USART_SR_TXE BIT(USART_SR_TXE_BIT) +/** Transmission complete mask */ +#define USART_SR_TC BIT(USART_SR_TC_BIT) +/** Read data register not empty mask */ +#define USART_SR_RXNE BIT(USART_SR_RXNE_BIT) +/** IDLE line detected mask */ +#define USART_SR_IDLE BIT(USART_SR_IDLE_BIT) +/** Overrun error mask */ +#define USART_SR_ORE BIT(USART_SR_ORE_BIT) +/** Noise error mask */ +#define USART_SR_NE BIT(USART_SR_NE_BIT) +/** + * @brief Synonym for USART_SR_NE. + * @see USART_SR_NF_BIT + */ +#define USART_SR_NF USART_SR_NE +/** Framing error mask */ +#define USART_SR_FE BIT(USART_SR_FE_BIT) +/** Parity error mask */ +#define USART_SR_PE BIT(USART_SR_PE_BIT) + +/* Data register */ + +/** Data register data value mask */ +#define USART_DR_DR 0xFF + +/* Baud rate register */ + +/** Mantissa of USARTDIV mask */ +#define USART_BRR_DIV_MANTISSA (0xFFF << 4) +/** Fraction of USARTDIV mask */ +#define USART_BRR_DIV_FRACTION 0xF + +/* Control register 1 */ + +/** USART enable bit */ +#define USART_CR1_UE_BIT 13 +/** Word length bit */ +#define USART_CR1_M_BIT 12 +/** Wakeup method bit */ +#define USART_CR1_WAKE_BIT 11 +/** Parity control enable bit */ +#define USART_CR1_PCE_BIT 10 +/** Parity selection bit */ +#define USART_CR1_PS_BIT 9 +/** Parity error interrupt enable bit */ +#define USART_CR1_PEIE_BIT 8 +/** Transmit data regsiter not empty interrupt enable bit */ +#define USART_CR1_TXEIE_BIT 7 +/** Transmission complete interrupt enable bit */ +#define USART_CR1_TCIE_BIT 6 +/** RXNE interrupt enable bit */ +#define USART_CR1_RXNEIE_BIT 5 +/** IDLE interrupt enable bit */ +#define USART_CR1_IDLEIE_BIT 4 +/** Transmitter enable bit */ +#define USART_CR1_TE_BIT 3 +/** Receiver enable bit */ +#define USART_CR1_RE_BIT 2 +/** Receiver wakeup bit */ +#define USART_CR1_RWU_BIT 1 +/** Send break bit */ +#define USART_CR1_SBK_BIT 0 + +/** USART enable mask */ +#define USART_CR1_UE BIT(USART_CR1_UE_BIT) +/** Word length mask */ +#define USART_CR1_M BIT(USART_CR1_M_BIT) +/** Word length: 1 start bit, 8 data bits, n stop bit */ +#define USART_CR1_M_8N1 (0 << USART_CR1_M_BIT) +/** Word length: 1 start bit, 9 data bits, n stop bit */ +#define USART_CR1_M_9N1 (1 << USART_CR1_M_BIT) +/** Wakeup method mask */ +#define USART_CR1_WAKE BIT(USART_CR1_WAKE_BIT) +/** Wakeup on idle line */ +#define USART_CR1_WAKE_IDLE (0 << USART_CR1_WAKE_BIT) +/** Wakeup on address mark */ +#define USART_CR1_WAKE_ADDR (1 << USART_CR1_WAKE_BIT) +/** Parity control enable mask */ +#define USART_CR1_PCE BIT(USART_CR1_PCE_BIT) +/** Parity selection mask */ +#define USART_CR1_PS BIT(USART_CR1_PS_BIT) +/** Parity selection: even parity */ +#define USART_CR1_PS_EVEN (0 << USART_CR1_PS_BIT) +/** Parity selection: odd parity */ +#define USART_CR1_PS_ODD (1 << USART_CR1_PS_BIT) +/** Parity error interrupt enable mask */ +#define USART_CR1_PEIE BIT(USART_CR1_PEIE_BIT) +/** Transmit data register empty interrupt enable mask */ +#define USART_CR1_TXEIE BIT(USART_CR1_TXEIE_BIT) +/** Transmission complete interrupt enable mask */ +#define USART_CR1_TCIE BIT(USART_CR1_TCIE_BIT) +/** RXNE interrupt enable mask */ +#define USART_CR1_RXNEIE BIT(USART_CR1_RXNEIE_BIT) +/** IDLE line interrupt enable mask */ +#define USART_CR1_IDLEIE BIT(USART_CR1_IDLEIE_BIT) +/** Transmitter enable mask */ +#define USART_CR1_TE BIT(USART_CR1_TE_BIT) +/** Receiver enable mask */ +#define USART_CR1_RE BIT(USART_CR1_RE_BIT) +/** Receiver wakeup mask */ +#define USART_CR1_RWU BIT(USART_CR1_RWU_BIT) +/** Receiver wakeup: receiver in active mode */ +#define USART_CR1_RWU_ACTIVE (0 << USART_CR1_RWU_BIT) +/** Receiver wakeup: receiver in mute mode */ +#define USART_CR1_RWU_MUTE (1 << USART_CR1_RWU_BIT) +/** Send break */ +#define USART_CR1_SBK BIT(USART_CR1_SBK_BIT) + +/* Control register 2 */ + +/** LIN mode enable bit */ +#define USART_CR2_LINEN_BIT 14 +/** Clock enable bit */ +#define USART_CR2_CLKEN_BIT 11 +/** Clock polarity bit */ +#define USART_CR2_CPOL_BIT 10 +/** Clock phase bit */ +#define USART_CR2_CPHA_BIT 9 +/** Last bit clock pulse bit */ +#define USART_CR2_LBCL_BIT 8 +/** LIN break detection interrupt enable bit */ +#define USART_CR2_LBDIE_BIT 6 +/** LIN break detection length bit */ +#define USART_CR2_LBDL_BIT 5 + +/** LIN mode enable mask */ +#define USART_CR2_LINEN BIT(USART_CR2_LINEN_BIT) +/** STOP bits mask */ +#define USART_CR2_STOP (0x3 << 12) +/** STOP bits: 1 stop bit */ +#define USART_CR2_STOP_BITS_1 (0x0 << 12) +/** + * @brief STOP bits: 0.5 stop bits + * Not available on UART4, UART5. */ +#define USART_CR2_STOP_BITS_POINT_5 (0x1 << 12) +/** STOP bits: 2 stop bits */ +#define USART_CR2_STOP_BITS_2 (0x2 << 12) +/** + * @brief STOP bits: 1.5 stop bits + * Not available on UART4, UART5. */ +#define USART_CR2_STOP_BITS_1_POINT_5 (0x3 << 12) +/** + * @brief Clock enable. + * Not available on UART4, UART5 */ +#define USART_CR2_CLKEN BIT(USART_CR2_CLKEN_BIT) +/** + * @brief Clock polarity mask. + * Not available on UART4, UART5 */ +#define USART_CR2_CPOL BIT(USART_CR2_CPOL_BIT) +/** Clock polarity: low */ +#define USART_CR2_CPOL_LOW (0x0 << USART_CR2_CLKEN_BIT) +/** Clock polarity: high */ +#define USART_CR2_CPOL_HIGH (0x1 << USART_CR2_CLKEN_BIT) +/** + * @brief Clock phase mask. + * Not available on UART4, UART5 */ +#define USART_CR2_CPHA BIT(USART_CR2_CPHA_BIT) +/** + * @brief Clock phase: first + * First clock transition is the first data capture edge. */ +#define USART_CR2_CPHA_FIRST (0x0 << USART_CR2_CPHA_BIT) +/** + * @brief Clock phase: second + * Second clock transition is the first data capture edge. */ +#define USART_CR2_CPHA_SECOND (0x1 << USART_CR2_CPHA_BIT) +/** + * @brief Last bit clock pulse mask. + * + * When set, the last bit transmitted causes a clock pulse in + * synchronous mode. + * + * Not available on UART4, UART5 */ +#define USART_CR2_LBCL BIT(USART_CR2_LBCL_BIT) +/** LIN break detection interrupt enable mask. */ +#define USART_CR2_LBDIE BIT(USART_CR2_LBDIE_BIT) +/** LIN break detection length. */ +#define USART_CR2_LBDL BIT(USART_CR2_LBDL_BIT) +/** LIN break detection length: 10 bits */ +#define USART_CR2_LBDL_10_BIT (0 << USART_CR2_LBDL_BIT) +/** LIN break detection length: 11 bits */ +#define USART_CR2_LBDL_11_BIT (1 << USART_CR2_LBDL_BIT) +/** + * @brief Address of the USART node + * This is useful during multiprocessor communication. */ +#define USART_CR2_ADD 0xF + +/* Control register 3 */ + +/** Clear to send interrupt enable bit */ +#define USART_CR3_CTSIE_BIT 10 +/** Clear to send enable bit */ +#define USART_CR3_CTSE_BIT 9 +/** Ready to send enable bit */ +#define USART_CR3_RTSE_BIT 8 +/** DMA enable transmitter bit */ +#define USART_CR3_DMAT_BIT 7 +/** DMA enable receiver bit */ +#define USART_CR3_DMAR_BIT 6 +/** Smartcard mode enable bit */ +#define USART_CR3_SCEN_BIT 5 +/** Smartcard NACK enable bit */ +#define USART_CR3_NACK_BIT 4 +/** Half-duplex selection bit */ +#define USART_CR3_HDSEL_BIT 3 +/** IrDA low power bit */ +#define USART_CR3_IRLP_BIT 2 +/** IrDA mode enable bit */ +#define USART_CR3_IREN_BIT 1 +/** Error interrupt enable bit */ +#define USART_CR3_EIE_BIT 0 + +/** + * @brief Clear to send interrupt enable + * Not available on UART4, UART5. */ +#define USART_CR3_CTSIE BIT(USART_CR3_CTSIE_BIT) +/** + * @brief Clear to send enable + * Not available on UART4, UART5. */ +#define USART_CR3_CTSE BIT(USART_CR3_CTSE_BIT) +/** + * @brief Ready to send enable + * Not available on UART4, UART5. */ +#define USART_CR3_RTSE BIT(USART_CR3_RTSE_BIT) +/** + * @brief DMA enable transmitter + * Not available on UART5. */ +#define USART_CR3_DMAT BIT(USART_CR3_DMAT_BIT) +/** + * @brief DMA enable receiver + * Not available on UART5. */ +#define USART_CR3_DMAR BIT(USART_CR3_DMAR_BIT) +/** + * @brief Smartcard mode enable + * Not available on UART4, UART5. */ +#define USART_CR3_SCEN BIT(USART_CR3_SCEN_BIT) +/** + * @brief Smartcard NACK enable + * Not available on UART4, UART5. */ +#define USART_CR3_NACK BIT(USART_CR3_NACK_BIT) +/** + * @brief Half-duplex selection + * When set, single-wire half duplex mode is selected. + */ +#define USART_CR3_HDSEL BIT(USART_CR3_HDSEL_BIT) +/** IrDA low power mode */ +#define USART_CR3_IRLP BIT(USART_CR3_IRLP_BIT) +/** IrDA mode: normal */ +#define USART_CR3_IRLP_NORMAL (0U << USART_CR3_IRLP_BIT) +/** IrDA mode: low power */ +#define USART_CR3_IRLP_LOW_POWER (1U << USART_CR3_IRLP_BIT) +/** IrDA mode enable */ +#define USART_CR3_IREN BIT(USART_CR3_IREN_BIT) +/** Error interrupt enable */ +#define USART_CR3_EIE BIT(USART_CR3_EIE_BIT) + +/* Guard time and prescaler register */ + +/** + * @brief Guard time value mask + * Used in Smartcard mode. Not available on UART4, UART5. */ +#define USART_GTPR_GT (0xFF << 8) +/** + * @brief Prescaler value mask + * Restrictions on this value apply, depending on the USART mode. Not + * available on UART4, UART5. */ +#define USART_GTPR_PSC 0xFF + +/* + * Devices + */ + +#ifndef USART_RX_BUF_SIZE +#define USART_RX_BUF_SIZE 64 +#endif + +#ifndef USART_TX_BUF_SIZE +#define USART_TX_BUF_SIZE 64 +#endif + +/** USART device type */ +typedef struct usart_dev { + usart_reg_map *regs; /**< Register map */ + ring_buffer *rb; /**< RX ring buffer */ + ring_buffer *wb; /**< TX ring buffer */ + uint32 max_baud; /**< @brief Deprecated. + * Maximum baud rate. */ + uint8 rx_buf[USART_RX_BUF_SIZE]; /**< @brief Deprecated. + * Actual RX buffer used by rb. + * This field will be removed in + * a future release. */ + uint8 tx_buf[USART_TX_BUF_SIZE]; /**< Actual TX buffer used by wb */ + rcc_clk_id clk_id; /**< RCC clock information */ + nvic_irq_num irq_num; /**< USART NVIC interrupt */ +} usart_dev; + +void usart_init(usart_dev *dev); + +struct gpio_dev; /* forward declaration */ +/* FIXME [PRE 0.0.13] decide if flags are necessary */ +/** + * @brief Configure GPIOs for use as USART TX/RX. + * @param udev USART device to use + * @param rx_dev RX pin gpio_dev + * @param rx RX pin bit on rx_dev + * @param tx_dev TX pin gpio_dev + * @param tx TX pin bit on tx_dev + * @param flags Currently ignored + */ +extern void usart_config_gpios_async(usart_dev *udev, + struct gpio_dev *rx_dev, uint8 rx, + struct gpio_dev *tx_dev, uint8 tx, + unsigned flags); + +#define USART_USE_PCLK 0 +void usart_set_baud_rate(usart_dev *dev, uint32 clock_speed, uint32 baud); + +void usart_enable(usart_dev *dev); +void usart_disable(usart_dev *dev); +void usart_foreach(void (*fn)(usart_dev *dev)); +uint32 usart_tx(usart_dev *dev, const uint8 *buf, uint32 len); +uint32 usart_rx(usart_dev *dev, uint8 *buf, uint32 len); +void usart_putudec(usart_dev *dev, uint32 val); + +/** + * @brief Disable all serial ports. + */ +static inline void usart_disable_all(void) { + usart_foreach(usart_disable); +} + +/** + * @brief Transmit one character on a serial port. + * + * This function blocks until the character has been queued + * for transmission. + * + * @param dev Serial port to send on. + * @param byte Byte to transmit. + */ +static inline void usart_putc(usart_dev* dev, uint8 byte) { + while (!usart_tx(dev, &byte, 1)) + ; +} + +/** + * @brief Transmit a character string on a serial port. + * + * This function blocks until str is completely transmitted. + * + * @param dev Serial port to send on + * @param str String to send + */ +static inline void usart_putstr(usart_dev *dev, const char* str) { + uint32 i = 0; + while (str[i] != '\0') { + usart_putc(dev, str[i++]); + } +} + +/** + * @brief Read one character from a serial port. + * + * It's not safe to call this function if the serial port has no data + * available. + * + * @param dev Serial port to read from + * @return byte read + * @see usart_data_available() + */ +static inline uint8 usart_getc(usart_dev *dev) { + return rb_remove(dev->rb); +} + +/* + * Roger Clark. 20141125, + * added peek function. + * @param dev Serial port to read from + * @return byte read + */ +static inline int usart_peek(usart_dev *dev) +{ + return rb_peek(dev->rb); +} + + +/** + * @brief Return the amount of data available in a serial port's RX buffer. + * @param dev Serial port to check + * @return Number of bytes in dev's RX buffer. + */ +static inline uint32 usart_data_available(usart_dev *dev) { + return rb_full_count(dev->rb); +} + +/** + * @brief Discard the contents of a serial port's RX buffer. + * @param dev Serial port whose buffer to empty. + */ +static inline void usart_reset_rx(usart_dev *dev) { + rb_reset(dev->rb); +} + +/** + * @brief Discard the contents of a serial port's RX buffer. + * @param dev Serial port whose buffer to empty. + */ +static inline void usart_reset_tx(usart_dev *dev) { + rb_reset(dev->wb); +} + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/usb.h b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/usb.h new file mode 100644 index 0000000..ea24030 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/usb.h @@ -0,0 +1,176 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010, 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. + *****************************************************************************/ + +/* + * NOTE: This API is _unstable_ and will change drastically over time. + */ + +#ifndef _LIBMAPLE_USB_H_ +#define _LIBMAPLE_USB_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/* + * Descriptors and other paraphernalia + */ + +/* Descriptor types */ + +#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 + +/* Descriptor structs and declaration helpers */ + +#define USB_DESCRIPTOR_STRING_LEN(x) (2 + (x << 1)) + +#define USB_DESCRIPTOR_STRING(len) \ + struct { \ + uint8 bLength; \ + uint8 bDescriptorType; \ + uint16 bString[len]; \ + } __packed + +typedef struct usb_descriptor_device { + 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 usb_descriptor_config_header { + uint8 bLength; + uint8 bDescriptorType; + uint16 wTotalLength; + uint8 bNumInterfaces; + uint8 bConfigurationValue; + uint8 iConfiguration; + uint8 bmAttributes; + uint8 bMaxPower; +} __packed usb_descriptor_config_header; + +typedef struct usb_descriptor_interface { + uint8 bLength; + uint8 bDescriptorType; + uint8 bInterfaceNumber; + uint8 bAlternateSetting; + uint8 bNumEndpoints; + uint8 bInterfaceClass; + uint8 bInterfaceSubClass; + uint8 bInterfaceProtocol; + uint8 iInterface; +} __packed usb_descriptor_interface; + +typedef struct usb_descriptor_endpoint { + uint8 bLength; + uint8 bDescriptorType; + uint8 bEndpointAddress; + uint8 bmAttributes; + uint16 wMaxPacketSize; + uint8 bInterval; +} __packed usb_descriptor_endpoint; + +typedef struct usb_descriptor_string { + uint8 bLength; + uint8 bDescriptorType; + uint8 bString[]; +} usb_descriptor_string; + +/* Common values that go inside descriptors */ + +#define USB_CONFIG_ATTR_BUSPOWERED 0b10000000 +#define USB_CONFIG_ATTR_SELF_POWERED 0b11000000 + +#define USB_EP_TYPE_INTERRUPT 0x03 +#define USB_EP_TYPE_BULK 0x02 + +#define USB_DESCRIPTOR_ENDPOINT_IN 0x80 +#define USB_DESCRIPTOR_ENDPOINT_OUT 0x00 + +/* + * USB module core + */ + +#ifndef USB_ISR_MSK +/* Handle CTRM, WKUPM, SUSPM, ERRM, SOFM, ESOFM, RESETM */ +#define USB_ISR_MSK 0xBF00 +#endif + +typedef enum usb_dev_state { + USB_UNCONNECTED, + USB_ATTACHED, + USB_POWERED, + USB_SUSPENDED, + USB_ADDRESSED, + USB_CONFIGURED +} usb_dev_state; + +/* Encapsulates global state formerly handled by usb_lib/ */ +typedef struct usblib_dev { + uint32 irq_mask; + void (**ep_int_in)(void); + void (**ep_int_out)(void); + usb_dev_state state; + usb_dev_state prevState; + rcc_clk_id clk_id; +} usblib_dev; + +extern usblib_dev *USBLIB; + +void usb_init_usblib(usblib_dev *dev, + void (**ep_int_in)(void), + void (**ep_int_out)(void)); + +static inline uint8 usb_is_connected(usblib_dev *dev) { + return dev->state != USB_UNCONNECTED; +} + +static inline uint8 usb_is_configured(usblib_dev *dev) { + return dev->state == USB_CONFIGURED; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/usb_cdcacm.h b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/usb_cdcacm.h new file mode 100644 index 0000000..62c9181 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/usb_cdcacm.h @@ -0,0 +1,180 @@ +/****************************************************************************** + * 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/include/libmaple/usb_cdcacm.h + * @brief USB CDC ACM (virtual serial terminal) support + * + * IMPORTANT: this API is unstable, and may change without notice. + */ + +#ifndef _LIBMAPLE_USB_CDCACM_H_ +#define _LIBMAPLE_USB_CDCACM_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * CDC ACM Requests + */ + +#define USB_CDCACM_SET_LINE_CODING 0x20 +#define USB_CDCACM_GET_LINE_CODING 0x21 +#define USB_CDCACM_SET_COMM_FEATURE 0x02 +#define USB_CDCACM_SET_CONTROL_LINE_STATE 0x22 +#define USB_CDCACM_CONTROL_LINE_DTR (0x01) +#define USB_CDCACM_CONTROL_LINE_RTS (0x02) + +/* + * Descriptors, etc. + */ + +#define CDC_FUNCTIONAL_DESCRIPTOR_SIZE(DataSize) (3 + DataSize) +#define CDC_FUNCTIONAL_DESCRIPTOR(DataSize) \ + struct { \ + uint8 bLength; \ + uint8 bDescriptorType; \ + uint8 SubType; \ + uint8 Data[DataSize]; \ + } __packed + +#define USB_DEVICE_CLASS_CDC 0x02 +#define USB_DEVICE_SUBCLASS_CDC 0x00 +#define USB_INTERFACE_CLASS_CDC 0x02 +#define USB_INTERFACE_SUBCLASS_CDC_ACM 0x02 +#define USB_INTERFACE_CLASS_DIC 0x0A + +/* + * Endpoint configuration + */ + +#define USB_CDCACM_CTRL_ENDP 0 +#define USB_CDCACM_CTRL_RX_ADDR 0x40 +#define USB_CDCACM_CTRL_TX_ADDR 0x80 +#define USB_CDCACM_CTRL_EPSIZE 0x40 + +#define USB_CDCACM_TX_ENDP 1 +#define USB_CDCACM_TX_ADDR 0xC0 +#define USB_CDCACM_TX_EPSIZE 0x40 + +#define USB_CDCACM_MANAGEMENT_ENDP 2 +#define USB_CDCACM_MANAGEMENT_ADDR 0x100 +#define USB_CDCACM_MANAGEMENT_EPSIZE 0x40 + +#define USB_CDCACM_RX_ENDP 3 +#define USB_CDCACM_RX_ADDR 0x110 +#define USB_CDCACM_RX_EPSIZE 0x40 + +#ifndef __cplusplus +#define USB_CDCACM_DECLARE_DEV_DESC(vid, pid) \ + { \ + .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 = vid, \ + .idProduct = pid, \ + .bcdDevice = 0x0200, \ + .iManufacturer = 0x01, \ + .iProduct = 0x02, \ + .iSerialNumber = 0x00, \ + .bNumConfigurations = 0x01, \ + } +#endif + +/* + * CDC ACM interface + */ + +void usb_cdcacm_enable(gpio_dev*, uint8); +void usb_cdcacm_disable(gpio_dev*, uint8); + +void usb_cdcacm_putc(char ch); +uint32 usb_cdcacm_tx(const uint8* buf, uint32 len); +uint32 usb_cdcacm_rx(uint8* buf, uint32 len); +uint32 usb_cdcacm_peek(uint8* buf, uint32 len); +uint32 usb_cdcacm_peek_ex(uint8* buf, uint32 offset, uint32 len); + +uint32 usb_cdcacm_data_available(void); /* in RX buffer */ +uint16 usb_cdcacm_get_pending(void); +uint8 usb_cdcacm_is_transmitting(void); + +uint8 usb_cdcacm_get_dtr(void); +uint8 usb_cdcacm_get_rts(void); + +typedef struct usb_cdcacm_line_coding { + uint32 dwDTERate; /* Baud rate */ + +#define USB_CDCACM_STOP_BITS_1 0 +#define USB_CDCACM_STOP_BITS_1_5 1 +#define USB_CDCACM_STOP_BITS_2 2 + uint8 bCharFormat; /* Stop bits */ + +#define USB_CDCACM_PARITY_NONE 0 +#define USB_CDCACM_PARITY_ODD 1 +#define USB_CDCACM_PARITY_EVEN 2 +#define USB_CDCACM_PARITY_MARK 3 +#define USB_CDCACM_PARITY_SPACE 4 + uint8 bParityType; /* Parity type */ + + uint8 bDataBits; /* Data bits: 5, 6, 7, 8, or 16 */ +} __packed usb_cdcacm_line_coding; + +/* Retrieve a copy of the current line coding structure. */ +void usb_cdcacm_get_line_coding(usb_cdcacm_line_coding*); + +/* Line coding conveniences. */ +int usb_cdcacm_get_baud(void); /* dwDTERate */ +int usb_cdcacm_get_stop_bits(void); /* bCharFormat */ +int usb_cdcacm_get_parity(void); /* bParityType */ +int usb_cdcacm_get_n_data_bits(void); /* bDataBits */ + +/* + * Hack: hooks for bootloader reset signalling + */ + +#define USB_CDCACM_HOOK_RX 0x1 +#define USB_CDCACM_HOOK_IFACE_SETUP 0x2 + +void usb_cdcacm_set_hooks(unsigned hook_flags, void (*hook)(unsigned, void*)); + +static inline __always_inline void usb_cdcacm_remove_hooks(unsigned hook_flags) { + usb_cdcacm_set_hooks(hook_flags, 0); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/util.h b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/util.h new file mode 100644 index 0000000..5a70348 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/include/libmaple/util.h @@ -0,0 +1,111 @@ +/****************************************************************************** + * 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/include/libmaple/util.h + * @brief Miscellaneous utility macros and procedures. + */ + +#ifndef _LIBMAPLE_UTIL_H_ +#define _LIBMAPLE_UTIL_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include + +/* + * Bit manipulation + */ + +/** 1UL shifted left by 'shift' */ +#define BIT(shift) (1UL << (shift)) +/** 'Mask' shifted left by 'shift' */ +#define BIT_MASK_SHIFT(mask, shift) ((mask) << (shift)) +/** Bits m to n of x */ +#define GET_BITS(x, m, n) ((((uint32)x) << (31 - (n))) >> ((31 - (n)) + (m))) +/** True iff v is a power of two (1, 2, 4, 8, ...) */ +#define IS_POWER_OF_TWO(v) ((v) && !((v) & ((v) - 1))) + +/* + * Failure routines + */ + +void __error(void); +void _fail(const char*, int, const char*); +void throb(void); + +/* + * Asserts and debug levels + */ + +#define DEBUG_NONE 0 +#define DEBUG_FAULT 1 +#define DEBUG_ALL 2 + +/** + * \def DEBUG_LEVEL + * + * Controls the level of assertion checking. + * + * The higher the debug level, the more assertions will be compiled + * in. This increases the amount of debugging information, but slows + * down (and increases the size of) the binary. + * + * The debug levels, from lowest to highest, are DEBUG_NONE, + * DEBUG_FAULT, and DEBUG_ALL. The default level is DEBUG_ALL. + */ + +#ifndef DEBUG_LEVEL +#define DEBUG_LEVEL DEBUG_ALL +#endif + +#if DEBUG_LEVEL >= DEBUG_ALL +#define ASSERT(exp) \ + if (exp) { \ + } else { \ + _fail(__FILE__, __LINE__, #exp); \ + } +#else +#define ASSERT(exp) (void)((0)) +#endif + +#if DEBUG_LEVEL >= DEBUG_FAULT +#define ASSERT_FAULT(exp) \ + if (exp) { \ + } else { \ + _fail(__FILE__, __LINE__, #exp); \ + } +#else +#define ASSERT_FAULT(exp) (void)((0)) +#endif + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/rcc_private.h b/BootLoaders/Boards/stm32/system/libmaple/rcc_private.h new file mode 100644 index 0000000..afb8a31 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/rcc_private.h @@ -0,0 +1,74 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/* + * RCC private header. + */ + +#ifndef _LIBMAPLE_PRIVATE_RCC_H_ +#define _LIBMAPLE_PRIVATE_RCC_H_ + +#include + +struct rcc_dev_info { + const rcc_clk_domain clk_domain; + const uint8 line_num; +}; + +extern const struct rcc_dev_info rcc_dev_table[]; + +static inline void rcc_do_clk_enable(__io uint32** enable_regs, + rcc_clk_id id) { + __io uint32 *enable_reg = enable_regs[rcc_dev_clk(id)]; + uint8 line_num = rcc_dev_table[id].line_num; + bb_peri_set_bit(enable_reg, line_num, 1); +} + +static inline void rcc_do_reset_dev(__io uint32** reset_regs, + rcc_clk_id id) { + __io uint32 *reset_reg = reset_regs[rcc_dev_clk(id)]; + uint8 line_num = rcc_dev_table[id].line_num; + bb_peri_set_bit(reset_reg, line_num, 1); + bb_peri_set_bit(reset_reg, line_num, 0); +} + +static inline void rcc_do_set_prescaler(const uint32 *masks, + rcc_prescaler prescaler, + uint32 divider) { + uint32 cfgr = RCC_BASE->CFGR; + cfgr &= ~masks[prescaler]; + cfgr |= divider; + RCC_BASE->CFGR = cfgr; +} + +static inline void rcc_do_clk_disable(__io uint32** enable_regs, + rcc_clk_id id) { + __io uint32 *enable_reg = enable_regs[rcc_dev_clk(id)]; + uint8 line_num = rcc_dev_table[id].line_num; + bb_peri_set_bit(enable_reg, line_num, 0); +} + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/rules.mk b/BootLoaders/Boards/stm32/system/libmaple/rules.mk new file mode 100644 index 0000000..71979f0 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/rules.mk @@ -0,0 +1,50 @@ +# Standard things +sp := $(sp).x +dirstack_$(sp) := $(d) +d := $(dir) +BUILDDIRS += $(BUILD_PATH)/$(d) + +LIBMAPLE_INCLUDES := -I$(LIBMAPLE_PATH)/include -I$(LIBMAPLE_MODULE_SERIES)/include +LIBMAPLE_PRIVATE_INCLUDES := -I$(LIBMAPLE_PATH) + +# Local flags +CFLAGS_$(d) = $(LIBMAPLE_PRIVATE_INCLUDES) $(LIBMAPLE_INCLUDES) -Wall -Werror + +# Local rules and targets +cSRCS_$(d) := adc.c +cSRCS_$(d) += dac.c +cSRCS_$(d) += dma.c +cSRCS_$(d) += exti.c +cSRCS_$(d) += flash.c +cSRCS_$(d) += gpio.c +cSRCS_$(d) += iwdg.c +cSRCS_$(d) += nvic.c +cSRCS_$(d) += pwr.c +cSRCS_$(d) += rcc.c +cSRCS_$(d) += spi.c +cSRCS_$(d) += systick.c +cSRCS_$(d) += timer.c +cSRCS_$(d) += usart.c +cSRCS_$(d) += usart_private.c +cSRCS_$(d) += util.c +sSRCS_$(d) := exc.S +# I2C support must be ported to F2: +ifeq ($(MCU_SERIES),stm32f1) +cSRCS_$(d) += i2c.c +endif + +cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%) +sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%) + +OBJS_$(d) := $(cFILES_$(d):%.c=$(BUILD_PATH)/%.o) $(sFILES_$(d):%.S=$(BUILD_PATH)/%.o) +DEPS_$(d) := $(OBJS_$(d):%.o=%.d) + +$(OBJS_$(d)): TGT_CFLAGS := $(CFLAGS_$(d)) +$(OBJS_$(d)): TGT_ASFLAGS := + +TGT_BIN += $(OBJS_$(d)) + +# Standard things +-include $(DEPS_$(d)) +d := $(dirstack_$(sp)) +sp := $(basename $(sp)) diff --git a/BootLoaders/Boards/stm32/system/libmaple/spi_private.h b/BootLoaders/Boards/stm32/system/libmaple/spi_private.h new file mode 100644 index 0000000..f0e0bd1 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/spi_private.h @@ -0,0 +1,37 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +#ifndef _LIBMAPLE_SPI_PRIVATE_H_ +#define _LIBMAPLE_SPI_PRIVATE_H_ + +#define SPI_DEV(num) \ + { \ + .regs = SPI##num##_BASE, \ + .clk_id = RCC_SPI##num, \ + .irq_num = NVIC_SPI##num, \ + } + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/stm32_private.h b/BootLoaders/Boards/stm32/system/libmaple/stm32_private.h new file mode 100644 index 0000000..427417a --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/stm32_private.h @@ -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. +*****************************************************************************/ + +#ifndef _LIBMAPLE_STM32_PRIVATE_H_ +#define _LIBMAPLE_STM32_PRIVATE_H_ + +typedef enum stm32_mem_block_purpose { + STM32_BLOCK_CODE, + STM32_BLOCK_SRAM, + STM32_BLOCK_PERIPH, + STM32_BLOCK_FSMC_1_2, + STM32_BLOCK_FSMC_3_4, + STM32_BLOCK_FSMC_REG, + STM32_BLOCK_UNUSED, + STM32_BLOCK_CORTEX_INTERNAL, +} stm32_mem_block_purpose; + +static inline stm32_mem_block_purpose stm32_block_purpose(void *addr) { + return (stm32_mem_block_purpose)((unsigned)addr >> 29); +} + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/adc.h b/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/adc.h new file mode 100644 index 0000000..98b22e6 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/adc.h @@ -0,0 +1,271 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * Copyright (c) 2010 Perry Hung. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/include/series/adc.h + * @author Marti Bolivar , + * Perry Hung + * @brief STM32F1 ADC header. + */ + +#ifndef _LIBMAPLE_STM32F1_ADC_H_ +#define _LIBMAPLE_STM32F1_ADC_H_ + +#include +#include +#include /* For the prescalers */ + +/* + * Devices + */ +extern adc_dev adc1; +extern struct adc_dev *ADC1; +extern adc_dev adc2; +extern struct adc_dev *ADC2; +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) +extern adc_dev adc3; +extern struct adc_dev *ADC3; +#endif + +/* + * Register map base pointers + */ + +/** STM32F1 ADC1 register map base pointer. */ +#define ADC1_BASE ((struct adc_reg_map*)0x40012400) +/** STM32F1 ADC2 register map base pointer. */ +#define ADC2_BASE ((struct adc_reg_map*)0x40012800) +/** STM32F1 ADC3 register map base pointer. */ +#define ADC3_BASE ((struct adc_reg_map*)0x40013C00) + +/* + * Register bit definitions + */ + +/* Control register 2 */ + +#define ADC_CR2_ADON_BIT 0 +#define ADC_CR2_CONT_BIT 1 +#define ADC_CR2_CAL_BIT 2 +#define ADC_CR2_RSTCAL_BIT 3 +#define ADC_CR2_DMA_BIT 8 +#define ADC_CR2_ALIGN_BIT 11 +#define ADC_CR2_JEXTTRIG_BIT 15 +#define ADC_CR2_EXTTRIG_BIT 20 +#define ADC_CR2_JSWSTART_BIT 21 +#define ADC_CR2_SWSTART_BIT 22 +#define ADC_CR2_TSVREFE_BIT 23 + +#define ADC_CR2_ADON (1U << ADC_CR2_ADON_BIT) +#define ADC_CR2_CONT (1U << ADC_CR2_CONT_BIT) +#define ADC_CR2_CAL (1U << ADC_CR2_CAL_BIT) +#define ADC_CR2_RSTCAL (1U << ADC_CR2_RSTCAL_BIT) +#define ADC_CR2_DMA (1U << ADC_CR2_DMA_BIT) +#define ADC_CR2_ALIGN (1U << ADC_CR2_ALIGN_BIT) +#define ADC_CR2_JEXTSEL 0x7000 +#define ADC_CR2_JEXTSEL_TIM1_TRGO (0x0 << 12) +#define ADC_CR2_JEXTSEL_TIM1_CC4 (0x1 << 12) +#define ADC_CR2_JEXTSEL_TIM2_TRGO (0x2 << 12) +#define ADC_CR2_JEXTSEL_TIM2_CC1 (0x3 << 12) +#define ADC_CR2_JEXTSEL_TIM3_CC4 (0x4 << 12) +#define ADC_CR2_JEXTSEL_TIM4_TRGO (0x5 << 12) +#define ADC_CR2_JEXTSEL_EXTI15 (0x6 << 12) +#define ADC_CR2_JEXTSEL_JSWSTART (0x7 << 12) +#define ADC_CR2_JEXTTRIG (1U << ADC_CR2_JEXTTRIG_BIT) +#define ADC_CR2_EXTSEL 0xE0000 +#define ADC_CR2_EXTSEL_TIM1_CC1 (0x0 << 17) +#define ADC_CR2_EXTSEL_TIM1_CC2 (0x1 << 17) +#define ADC_CR2_EXTSEL_TIM1_CC3 (0x2 << 17) +#define ADC_CR2_EXTSEL_TIM2_CC2 (0x3 << 17) +#define ADC_CR2_EXTSEL_TIM3_TRGO (0x4 << 17) +#define ADC_CR2_EXTSEL_TIM4_CC4 (0x5 << 17) +#define ADC_CR2_EXTSEL_EXTI11 (0x6 << 17) +#define ADC_CR2_EXTSEL_SWSTART (0x7 << 17) +#define ADC_CR2_EXTTRIG (1U << ADC_CR2_EXTTRIG_BIT) +#define ADC_CR2_JSWSTART (1U << ADC_CR2_JSWSTART_BIT) +#define ADC_CR2_SWSTART (1U << ADC_CR2_SWSTART_BIT) +#define ADC_CR2_TSVREFE (1U << ADC_CR2_TSVREFE_BIT) + +/* + * Other types + */ + +/** + * @brief STM32F1 external event selectors for regular group + * conversion. + * + * Some external events are only available on ADCs 1 and 2, others + * only on ADC3, while others are available on all three ADCs. + * Additionally, some events are only available on high- and + * XL-density STM32F1 MCUs, as they use peripherals only available on + * those MCU densities. + * + * For ease of use, each event selector is given along with the ADCs + * it's available on, along with any other availability restrictions. + * + * @see adc_set_extsel() + */ +typedef enum adc_extsel_event { + /* TODO: Smarten this up a bit, as follows. + * + * The EXTSEL bits on F1 are a little brain-damaged in that the + * TIM8 TRGO event has different bits depending on whether you're + * using ADC1/2 or ADC3. We route around this by declaring two + * enumerators, ADC_EXT_EV_ADC12_TIM8_TRGO and + * ADC_EXT_EV_ADC3_TIM8_TRGO. + * + * The right thing to do is to provide a single + * ADC_EXT_EV_TIM8_TRGO enumerator and override adc_set_extsel on + * STM32F1 to handle this situation correctly. We can do that + * later, though, and change the per-ADC enumerator values to + * ADC_EXT_EV_TIM8_TRGO to preserve compatibility. */ + + /* ADC1 and ADC2 only: */ + ADC_EXT_EV_TIM1_CC1 = 0x00000, /**< ADC1, ADC2: Timer 1 CC1 event */ + ADC_EXT_EV_TIM1_CC2 = 0x20000, /**< ADC1, ADC2: Timer 1 CC2 event */ + ADC_EXT_EV_TIM2_CC2 = 0x60000, /**< ADC1, ADC2: Timer 2 CC2 event */ + ADC_EXT_EV_TIM3_TRGO = 0x80000, /**< ADC1, ADC2: Timer 3 TRGO event */ + ADC_EXT_EV_TIM4_CC4 = 0xA0000, /**< ADC1, ADC2: Timer 4 CC4 event */ + ADC_EXT_EV_EXTI11 = 0xC0000, /**< ADC1, ADC2: EXTI11 event */ + + /* Common: */ + ADC_EXT_EV_TIM1_CC3 = 0x40000, /**< ADC1, ADC2, ADC3: Timer 1 CC3 event */ + ADC_EXT_EV_SWSTART = 0xE0000, /**< ADC1, ADC2, ADC3: Software start */ + + /* HD only: */ + ADC_EXT_EV_TIM3_CC1 = 0x00000, /**< + * ADC3: Timer 3 CC1 event + * Availability: high- and XL-density. */ + ADC_EXT_EV_TIM2_CC3 = 0x20000, /**< + * ADC3: Timer 2 CC3 event + * Availability: high- and XL-density. */ + ADC_EXT_EV_TIM8_CC1 = 0x60000, /**< + * ADC3: Timer 8 CC1 event + * Availability: high- and XL-density. */ + ADC_EXT_EV_ADC3_TIM8_TRGO = 0x80000, /**< + * ADC3: Timer 8 TRGO event + * Availability: high- and XL-density. */ + ADC_EXT_EV_TIM5_CC1 = 0xA0000, /**< + * ADC3: Timer 5 CC1 event + * Availability: high- and XL-density. */ + ADC_EXT_EV_ADC12_TIM8_TRGO = 0xC0000, /**< + * ADC1, ADC2: Timer 8 TRGO event + * Availability: high- and XL-density. */ + ADC_EXT_EV_TIM5_CC3 = 0xC0000, /**< + * ADC3: Timer 5 CC3 event + * Availability: high- and XL-density. */ +} adc_extsel_event; + +/* We'll keep these old adc_extsel_event enumerators around for a + * while, for backwards compatibility: */ +/** Deprecated. Use ADC_EXT_EV_TIM1_CC1 instead. */ +#define ADC_ADC12_TIM1_CC1 ADC_EXT_EV_TIM1_CC1 +/** Deprecated. Use ADC_EXT_EV_TIM1_CC2 instead. */ +#define ADC_ADC12_TIM1_CC2 ADC_EXT_EV_TIM1_CC2 +/** Deprecated. Use ADC_EXT_EV_TIM1_CC3 instead. */ +#define ADC_ADC12_TIM1_CC3 ADC_EXT_EV_TIM1_CC3 +/** Deprecated. Use ADC_EXT_EV_TIM2_CC2 instead. */ +#define ADC_ADC12_TIM2_CC2 ADC_EXT_EV_TIM2_CC2 +/** Deprecated. Use ADC_EXT_EV_TIM3_TRGO instead. */ +#define ADC_ADC12_TIM3_TRGO ADC_EXT_EV_TIM3_TRGO +/** Deprecated. Use ADC_EXT_EV_TIM4_CC4 instead. */ +#define ADC_ADC12_TIM4_CC4 ADC_EXT_EV_TIM4_CC4 +/** Deprecated. Use ADC_EXT_EV_EXTI11 instead. */ +#define ADC_ADC12_EXTI11 ADC_EXT_EV_EXTI11 +/** Deprecated. Use ADC_EXT_EV_ADC12_TIM8_TRGO instead. */ +#define ADC_ADC12_TIM8_TRGO ADC_EXT_EV_ADC12_TIM8_TRGO +/** Deprecated. Use ADC_EXT_EV_SWSTART instead. */ +#define ADC_ADC12_SWSTART ADC_EXT_EV_SWSTART +/** Deprecated. Use ADC_EXT_EV_TIM1_CC1 instead. */ +#define ADC_ADC3_TIM3_CC1 ADC_EXT_EV_TIM1_CC1 +/** Deprecated. Use ADC_EXT_EV_TIM1_CC2 instead. */ +#define ADC_ADC3_TIM2_CC3 ADC_EXT_EV_TIM1_CC2 +/** Deprecated. Use ADC_EXT_EV_TIM1_CC3 instead. */ +#define ADC_ADC3_TIM1_CC3 ADC_EXT_EV_TIM1_CC3 +/** Deprecated. Use ADC_EXT_EV_TIM2_CC2 instead. */ +#define ADC_ADC3_TIM8_CC1 ADC_EXT_EV_TIM2_CC2 +/** Deprecated. Use ADC_EXT_EV_TIM3_TRGO instead. */ +#define ADC_ADC3_TIM8_TRGO ADC_EXT_EV_TIM3_TRGO +/** Deprecated. Use ADC_EXT_EV_TIM4_CC4 instead. */ +#define ADC_ADC3_TIM5_CC1 ADC_EXT_EV_TIM4_CC4 +/** Deprecated. Use ADC_EXT_EV_EXTI11 instead. */ +#define ADC_ADC3_TIM5_CC3 ADC_EXT_EV_EXTI11 +/** Deprecated. Use ADC_EXT_EV_TIM8_TRGO instead. */ +#define ADC_ADC3_SWSTART ADC_EXT_EV_TIM8_TRGO +/** Deprecated. Use ADC_EXT_EV_SWSTART instead. */ +#define ADC_SWSTART ADC_EXT_EV_SWSTART + +/** + * @brief STM32F1 sample times, in ADC clock cycles. + * + * These control the amount of time spent sampling the input voltage. + */ +typedef enum adc_smp_rate { + ADC_SMPR_1_5, /**< 1.5 ADC cycles */ + ADC_SMPR_7_5, /**< 7.5 ADC cycles */ + ADC_SMPR_13_5, /**< 13.5 ADC cycles */ + ADC_SMPR_28_5, /**< 28.5 ADC cycles */ + ADC_SMPR_41_5, /**< 41.5 ADC cycles */ + ADC_SMPR_55_5, /**< 55.5 ADC cycles */ + ADC_SMPR_71_5, /**< 71.5 ADC cycles */ + ADC_SMPR_239_5, /**< 239.5 ADC cycles */ +} adc_smp_rate; + +/** + * @brief STM32F1 ADC prescalers, as divisors of PCLK2. + */ +typedef enum adc_prescaler { + /** PCLK2 divided by 2 */ + ADC_PRE_PCLK2_DIV_2 = RCC_ADCPRE_PCLK_DIV_2, + /** PCLK2 divided by 4 */ + ADC_PRE_PCLK2_DIV_4 = RCC_ADCPRE_PCLK_DIV_4, + /** PCLK2 divided by 6 */ + ADC_PRE_PCLK2_DIV_6 = RCC_ADCPRE_PCLK_DIV_6, + /** PCLK2 divided by 8 */ + ADC_PRE_PCLK2_DIV_8 = RCC_ADCPRE_PCLK_DIV_8, +} adc_prescaler; + +/* + * Routines + */ + +void adc_calibrate(adc_dev *dev); + +/** + * @brief Set external trigger conversion mode event for regular channels + * + * Availability: STM32F1. + * + * @param dev ADC device + * @param enable If 1, conversion on external events is enabled; if 0, + * disabled. + */ +static inline void adc_set_exttrig(adc_dev *dev, uint8 enable) { + *bb_perip(&dev->regs->CR2, ADC_CR2_EXTTRIG_BIT) = !!enable; +} + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/dac.h b/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/dac.h new file mode 100644 index 0000000..c0d026b --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/dac.h @@ -0,0 +1,71 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/include/series/dac.h + * @brief STM32F1 DAC support + */ + +#ifndef _LIBMAPLE_STM32F1_DAC_H_ +#define _LIBMAPLE_STM32F1_DAC_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include + +/** STM32F1 DAC register map type. */ +typedef struct dac_reg_map { + __io uint32 CR; /**< Control register */ + __io uint32 SWTRIGR; /**< Software trigger register */ + __io uint32 DHR12R1; /**< Channel 1 12-bit right-aligned data + holding register */ + __io uint32 DHR12L1; /**< Channel 1 12-bit left-aligned data + holding register */ + __io uint32 DHR8R1; /**< Channel 1 8-bit left-aligned data + holding register */ + __io uint32 DHR12R2; /**< Channel 2 12-bit right-aligned data + holding register */ + __io uint32 DHR12L2; /**< Channel 2 12-bit left-aligned data + holding register */ + __io uint32 DHR8R2; /**< Channel 2 8-bit left-aligned data + holding register */ + __io uint32 DHR12RD; /**< Dual DAC 12-bit right-aligned data + holding register */ + __io uint32 DHR12LD; /**< Dual DAC 12-bit left-aligned data + holding register */ + __io uint32 DHR8RD; /**< Dual DAC 8-bit right-aligned data holding + register */ + __io uint32 DOR1; /**< Channel 1 data output register */ + __io uint32 DOR2; /**< Channel 2 data output register */ +} dac_reg_map; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/dma.h b/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/dma.h new file mode 100644 index 0000000..56e559b --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/dma.h @@ -0,0 +1,574 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Michael Hope. + * Copyright (c) 2012 LeafLabs, LLC + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/include/series/dma.h + * @author Marti Bolivar ; + * Original implementation by Michael Hope + * @brief STM32F1 DMA series header. + */ + +/* + * See /notes/dma-stm32f1.txt for more information. + */ + +#ifndef _LIBMAPLE_STM32F1_DMA_H_ +#define _LIBMAPLE_STM32F1_DMA_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include +#include + +/* + * Register maps and base pointers + */ + +/** + * @brief STM32F1 DMA register map type. + * + * Note that DMA controller 2 (register map base pointer DMA2_BASE) + * only supports channels 1--5. + */ +typedef struct dma_reg_map { + __io uint32 ISR; /**< Interrupt status register */ + __io uint32 IFCR; /**< Interrupt flag clear register */ + __io uint32 CCR1; /**< Channel 1 configuration register */ + __io uint32 CNDTR1; /**< Channel 1 number of data register */ + __io uint32 CPAR1; /**< Channel 1 peripheral address register */ + __io uint32 CMAR1; /**< Channel 1 memory address register */ + const uint32 RESERVED1; /**< Reserved. */ + __io uint32 CCR2; /**< Channel 2 configuration register */ + __io uint32 CNDTR2; /**< Channel 2 number of data register */ + __io uint32 CPAR2; /**< Channel 2 peripheral address register */ + __io uint32 CMAR2; /**< Channel 2 memory address register */ + const uint32 RESERVED2; /**< Reserved. */ + __io uint32 CCR3; /**< Channel 3 configuration register */ + __io uint32 CNDTR3; /**< Channel 3 number of data register */ + __io uint32 CPAR3; /**< Channel 3 peripheral address register */ + __io uint32 CMAR3; /**< Channel 3 memory address register */ + const uint32 RESERVED3; /**< Reserved. */ + __io uint32 CCR4; /**< Channel 4 configuration register */ + __io uint32 CNDTR4; /**< Channel 4 number of data register */ + __io uint32 CPAR4; /**< Channel 4 peripheral address register */ + __io uint32 CMAR4; /**< Channel 4 memory address register */ + const uint32 RESERVED4; /**< Reserved. */ + __io uint32 CCR5; /**< Channel 5 configuration register */ + __io uint32 CNDTR5; /**< Channel 5 number of data register */ + __io uint32 CPAR5; /**< Channel 5 peripheral address register */ + __io uint32 CMAR5; /**< Channel 5 memory address register */ + const uint32 RESERVED5; /**< Reserved. */ + __io uint32 CCR6; /**< Channel 6 configuration register */ + __io uint32 CNDTR6; /**< Channel 6 number of data register */ + __io uint32 CPAR6; /**< Channel 6 peripheral address register */ + __io uint32 CMAR6; /**< Channel 6 memory address register */ + const uint32 RESERVED6; /**< Reserved. */ + __io uint32 CCR7; /**< Channel 7 configuration register */ + __io uint32 CNDTR7; /**< Channel 7 number of data register */ + __io uint32 CPAR7; /**< Channel 7 peripheral address register */ + __io uint32 CMAR7; /**< Channel 7 memory address register */ + const uint32 RESERVED7; /**< Reserved. */ +} dma_reg_map; + +/** DMA controller 1 register map base pointer */ +#define DMA1_BASE ((struct dma_reg_map*)0x40020000) +/** DMA controller 2 register map base pointer */ +#define DMA2_BASE ((struct dma_reg_map*)0x40020400) + +/** + * @brief STM32F1 DMA channel (i.e. tube) register map type. + * Provides access to an individual channel's registers. + * @see dma_tube_regs() + */ +typedef struct dma_tube_reg_map { + __io uint32 CCR; /**< Channel configuration register */ + __io uint32 CNDTR; /**< Channel number of data register */ + __io uint32 CPAR; /**< Channel peripheral address register */ + __io uint32 CMAR; /**< Channel memory address register */ +} dma_tube_reg_map; + +/** DMA1 channel 1 register map base pointer */ +#define DMA1CH1_BASE ((struct dma_tube_reg_map*)0x40020008) +/** DMA1 channel 2 register map base pointer */ +#define DMA1CH2_BASE ((struct dma_tube_reg_map*)0x4002001C) +/** DMA1 channel 3 register map base pointer */ +#define DMA1CH3_BASE ((struct dma_tube_reg_map*)0x40020030) +/** DMA1 channel 4 register map base pointer */ +#define DMA1CH4_BASE ((struct dma_tube_reg_map*)0x40020044) +/** DMA1 channel 5 register map base pointer */ +#define DMA1CH5_BASE ((struct dma_tube_reg_map*)0x40020058) +/** DMA1 channel 6 register map base pointer */ +#define DMA1CH6_BASE ((struct dma_tube_reg_map*)0x4002006C) +/** DMA1 channel 7 register map base pointer */ +#define DMA1CH7_BASE ((struct dma_tube_reg_map*)0x40020080) + +/** DMA2 channel 1 register map base pointer */ +#define DMA2CH1_BASE ((struct dma_tube_reg_map*)0x40020408) +/** DMA2 channel 2 register map base pointer */ +#define DMA2CH2_BASE ((struct dma_tube_reg_map*)0x4002041C) +/** DMA2 channel 3 register map base pointer */ +#define DMA2CH3_BASE ((struct dma_tube_reg_map*)0x40020430) +/** DMA2 channel 4 register map base pointer */ +#define DMA2CH4_BASE ((struct dma_tube_reg_map*)0x40020444) +/** DMA2 channel 5 register map base pointer */ +#define DMA2CH5_BASE ((struct dma_tube_reg_map*)0x40020458) + +/* + * Register bit definitions + */ + +/* Interrupt status register */ + +#define DMA_ISR_TEIF_BIT 3 +#define DMA_ISR_HTIF_BIT 2 +#define DMA_ISR_TCIF_BIT 1 +#define DMA_ISR_GIF_BIT 0 + +#define DMA_ISR_TEIF (1 << DMA_ISR_TEIF_BIT) +#define DMA_ISR_HTIF (1 << DMA_ISR_HTIF_BIT) +#define DMA_ISR_TCIF (1 << DMA_ISR_TCIF_BIT) +#define DMA_ISR_GIF (1 << DMA_ISR_GIF_BIT) + +#define DMA_ISR_TEIF7_BIT 27 +#define DMA_ISR_HTIF7_BIT 26 +#define DMA_ISR_TCIF7_BIT 25 +#define DMA_ISR_GIF7_BIT 24 +#define DMA_ISR_TEIF6_BIT 23 +#define DMA_ISR_HTIF6_BIT 22 +#define DMA_ISR_TCIF6_BIT 21 +#define DMA_ISR_GIF6_BIT 20 +#define DMA_ISR_TEIF5_BIT 19 +#define DMA_ISR_HTIF5_BIT 18 +#define DMA_ISR_TCIF5_BIT 17 +#define DMA_ISR_GIF5_BIT 16 +#define DMA_ISR_TEIF4_BIT 15 +#define DMA_ISR_HTIF4_BIT 14 +#define DMA_ISR_TCIF4_BIT 13 +#define DMA_ISR_GIF4_BIT 12 +#define DMA_ISR_TEIF3_BIT 11 +#define DMA_ISR_HTIF3_BIT 10 +#define DMA_ISR_TCIF3_BIT 9 +#define DMA_ISR_GIF3_BIT 8 +#define DMA_ISR_TEIF2_BIT 7 +#define DMA_ISR_HTIF2_BIT 6 +#define DMA_ISR_TCIF2_BIT 5 +#define DMA_ISR_GIF2_BIT 4 +#define DMA_ISR_TEIF1_BIT 3 +#define DMA_ISR_HTIF1_BIT 2 +#define DMA_ISR_TCIF1_BIT 1 +#define DMA_ISR_GIF1_BIT 0 + +#define DMA_ISR_TEIF7 (1U << DMA_ISR_TEIF7_BIT) +#define DMA_ISR_HTIF7 (1U << DMA_ISR_HTIF7_BIT) +#define DMA_ISR_TCIF7 (1U << DMA_ISR_TCIF7_BIT) +#define DMA_ISR_GIF7 (1U << DMA_ISR_GIF7_BIT) +#define DMA_ISR_TEIF6 (1U << DMA_ISR_TEIF6_BIT) +#define DMA_ISR_HTIF6 (1U << DMA_ISR_HTIF6_BIT) +#define DMA_ISR_TCIF6 (1U << DMA_ISR_TCIF6_BIT) +#define DMA_ISR_GIF6 (1U << DMA_ISR_GIF6_BIT) +#define DMA_ISR_TEIF5 (1U << DMA_ISR_TEIF5_BIT) +#define DMA_ISR_HTIF5 (1U << DMA_ISR_HTIF5_BIT) +#define DMA_ISR_TCIF5 (1U << DMA_ISR_TCIF5_BIT) +#define DMA_ISR_GIF5 (1U << DMA_ISR_GIF5_BIT) +#define DMA_ISR_TEIF4 (1U << DMA_ISR_TEIF4_BIT) +#define DMA_ISR_HTIF4 (1U << DMA_ISR_HTIF4_BIT) +#define DMA_ISR_TCIF4 (1U << DMA_ISR_TCIF4_BIT) +#define DMA_ISR_GIF4 (1U << DMA_ISR_GIF4_BIT) +#define DMA_ISR_TEIF3 (1U << DMA_ISR_TEIF3_BIT) +#define DMA_ISR_HTIF3 (1U << DMA_ISR_HTIF3_BIT) +#define DMA_ISR_TCIF3 (1U << DMA_ISR_TCIF3_BIT) +#define DMA_ISR_GIF3 (1U << DMA_ISR_GIF3_BIT) +#define DMA_ISR_TEIF2 (1U << DMA_ISR_TEIF2_BIT) +#define DMA_ISR_HTIF2 (1U << DMA_ISR_HTIF2_BIT) +#define DMA_ISR_TCIF2 (1U << DMA_ISR_TCIF2_BIT) +#define DMA_ISR_GIF2 (1U << DMA_ISR_GIF2_BIT) +#define DMA_ISR_TEIF1 (1U << DMA_ISR_TEIF1_BIT) +#define DMA_ISR_HTIF1 (1U << DMA_ISR_HTIF1_BIT) +#define DMA_ISR_TCIF1 (1U << DMA_ISR_TCIF1_BIT) +#define DMA_ISR_GIF1 (1U << DMA_ISR_GIF1_BIT) + +/* Interrupt flag clear register */ + +#define DMA_IFCR_CTEIF7_BIT 27 +#define DMA_IFCR_CHTIF7_BIT 26 +#define DMA_IFCR_CTCIF7_BIT 25 +#define DMA_IFCR_CGIF7_BIT 24 +#define DMA_IFCR_CTEIF6_BIT 23 +#define DMA_IFCR_CHTIF6_BIT 22 +#define DMA_IFCR_CTCIF6_BIT 21 +#define DMA_IFCR_CGIF6_BIT 20 +#define DMA_IFCR_CTEIF5_BIT 19 +#define DMA_IFCR_CHTIF5_BIT 18 +#define DMA_IFCR_CTCIF5_BIT 17 +#define DMA_IFCR_CGIF5_BIT 16 +#define DMA_IFCR_CTEIF4_BIT 15 +#define DMA_IFCR_CHTIF4_BIT 14 +#define DMA_IFCR_CTCIF4_BIT 13 +#define DMA_IFCR_CGIF4_BIT 12 +#define DMA_IFCR_CTEIF3_BIT 11 +#define DMA_IFCR_CHTIF3_BIT 10 +#define DMA_IFCR_CTCIF3_BIT 9 +#define DMA_IFCR_CGIF3_BIT 8 +#define DMA_IFCR_CTEIF2_BIT 7 +#define DMA_IFCR_CHTIF2_BIT 6 +#define DMA_IFCR_CTCIF2_BIT 5 +#define DMA_IFCR_CGIF2_BIT 4 +#define DMA_IFCR_CTEIF1_BIT 3 +#define DMA_IFCR_CHTIF1_BIT 2 +#define DMA_IFCR_CTCIF1_BIT 1 +#define DMA_IFCR_CGIF1_BIT 0 + +#define DMA_IFCR_CTEIF7 (1U << DMA_IFCR_CTEIF7_BIT) +#define DMA_IFCR_CHTIF7 (1U << DMA_IFCR_CHTIF7_BIT) +#define DMA_IFCR_CTCIF7 (1U << DMA_IFCR_CTCIF7_BIT) +#define DMA_IFCR_CGIF7 (1U << DMA_IFCR_CGIF7_BIT) +#define DMA_IFCR_CTEIF6 (1U << DMA_IFCR_CTEIF6_BIT) +#define DMA_IFCR_CHTIF6 (1U << DMA_IFCR_CHTIF6_BIT) +#define DMA_IFCR_CTCIF6 (1U << DMA_IFCR_CTCIF6_BIT) +#define DMA_IFCR_CGIF6 (1U << DMA_IFCR_CGIF6_BIT) +#define DMA_IFCR_CTEIF5 (1U << DMA_IFCR_CTEIF5_BIT) +#define DMA_IFCR_CHTIF5 (1U << DMA_IFCR_CHTIF5_BIT) +#define DMA_IFCR_CTCIF5 (1U << DMA_IFCR_CTCIF5_BIT) +#define DMA_IFCR_CGIF5 (1U << DMA_IFCR_CGIF5_BIT) +#define DMA_IFCR_CTEIF4 (1U << DMA_IFCR_CTEIF4_BIT) +#define DMA_IFCR_CHTIF4 (1U << DMA_IFCR_CHTIF4_BIT) +#define DMA_IFCR_CTCIF4 (1U << DMA_IFCR_CTCIF4_BIT) +#define DMA_IFCR_CGIF4 (1U << DMA_IFCR_CGIF4_BIT) +#define DMA_IFCR_CTEIF3 (1U << DMA_IFCR_CTEIF3_BIT) +#define DMA_IFCR_CHTIF3 (1U << DMA_IFCR_CHTIF3_BIT) +#define DMA_IFCR_CTCIF3 (1U << DMA_IFCR_CTCIF3_BIT) +#define DMA_IFCR_CGIF3 (1U << DMA_IFCR_CGIF3_BIT) +#define DMA_IFCR_CTEIF2 (1U << DMA_IFCR_CTEIF2_BIT) +#define DMA_IFCR_CHTIF2 (1U << DMA_IFCR_CHTIF2_BIT) +#define DMA_IFCR_CTCIF2 (1U << DMA_IFCR_CTCIF2_BIT) +#define DMA_IFCR_CGIF2 (1U << DMA_IFCR_CGIF2_BIT) +#define DMA_IFCR_CTEIF1 (1U << DMA_IFCR_CTEIF1_BIT) +#define DMA_IFCR_CHTIF1 (1U << DMA_IFCR_CHTIF1_BIT) +#define DMA_IFCR_CTCIF1 (1U << DMA_IFCR_CTCIF1_BIT) +#define DMA_IFCR_CGIF1 (1U << DMA_IFCR_CGIF1_BIT) + +/* Channel configuration register */ + +#define DMA_CCR_MEM2MEM_BIT 14 +#define DMA_CCR_MINC_BIT 7 +#define DMA_CCR_PINC_BIT 6 +#define DMA_CCR_CIRC_BIT 5 +#define DMA_CCR_DIR_BIT 4 +#define DMA_CCR_TEIE_BIT 3 +#define DMA_CCR_HTIE_BIT 2 +#define DMA_CCR_TCIE_BIT 1 +#define DMA_CCR_EN_BIT 0 + +#define DMA_CCR_MEM2MEM (1U << DMA_CCR_MEM2MEM_BIT) +#define DMA_CCR_PL (0x3 << 12) +#define DMA_CCR_PL_LOW (0x0 << 12) +#define DMA_CCR_PL_MEDIUM (0x1 << 12) +#define DMA_CCR_PL_HIGH (0x2 << 12) +#define DMA_CCR_PL_VERY_HIGH (0x3 << 12) +#define DMA_CCR_MSIZE (0x3 << 10) +#define DMA_CCR_MSIZE_8BITS (0x0 << 10) +#define DMA_CCR_MSIZE_16BITS (0x1 << 10) +#define DMA_CCR_MSIZE_32BITS (0x2 << 10) +#define DMA_CCR_PSIZE (0x3 << 8) +#define DMA_CCR_PSIZE_8BITS (0x0 << 8) +#define DMA_CCR_PSIZE_16BITS (0x1 << 8) +#define DMA_CCR_PSIZE_32BITS (0x2 << 8) +#define DMA_CCR_MINC (1U << DMA_CCR_MINC_BIT) +#define DMA_CCR_PINC (1U << DMA_CCR_PINC_BIT) +#define DMA_CCR_CIRC (1U << DMA_CCR_CIRC_BIT) +#define DMA_CCR_DIR (1U << DMA_CCR_DIR_BIT) +#define DMA_CCR_DIR_FROM_PER (0U << DMA_CCR_DIR_BIT) +#define DMA_CCR_DIR_FROM_MEM (1U << DMA_CCR_DIR_BIT) +#define DMA_CCR_TEIE (1U << DMA_CCR_TEIE_BIT) +#define DMA_CCR_HTIE (1U << DMA_CCR_HTIE_BIT) +#define DMA_CCR_TCIE (1U << DMA_CCR_TCIE_BIT) +#define DMA_CCR_EN (1U << DMA_CCR_EN_BIT) + +/* + * Devices + */ + +extern dma_dev *DMA1; +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) +extern dma_dev *DMA2; +#endif + +/* + * Other types needed by, or useful for, . + */ + +/** + * @brief STM32F1 dma_tube. + * On STM32F1, DMA tubes are just channels. + */ +#define dma_tube dma_channel + +/** + * @brief On STM32F1, dma_channel_reg_map is an alias for dma_tube_reg_map. + * This is for backwards compatibility. */ +#define dma_channel_reg_map dma_tube_reg_map + +/** + * @brief STM32F1 configuration flags for dma_tube_config + * @see struct dma_tube_config + */ +typedef enum dma_cfg_flags { + /** + * Source address increment mode + * + * If this flag is set, the source address is incremented (by the + * source size) after each DMA transfer. + */ + DMA_CFG_SRC_INC = 1U << 31, + + /** + * Destination address increment mode + * + * If this flag is set, the destination address is incremented (by + * the destination size) after each DMA transfer. + */ + DMA_CFG_DST_INC = 1U << 30, + + /** + * Circular mode + * + * This mode is not available for memory-to-memory transfers. + */ + DMA_CFG_CIRC = DMA_CCR_CIRC, + + /** Transfer complete interrupt enable */ + DMA_CFG_CMPLT_IE = DMA_CCR_TCIE, + /** Transfer half-complete interrupt enable */ + DMA_CFG_HALF_CMPLT_IE = DMA_CCR_HTIE, + /** Transfer error interrupt enable */ + DMA_CFG_ERR_IE = DMA_CCR_TEIE, +} dma_cfg_flags; + +/** + * @brief STM32F1 DMA request sources. + * + * IMPORTANT: + * + * 1. On STM32F1, each dma_request_src can only be used by a + * particular tube on a particular DMA controller. For example, + * DMA_REQ_SRC_ADC1 belongs to DMA1, tube 1. DMA2 cannot serve + * requests from ADC1, nor can DMA1 tube 2, etc. If you try to use a + * request source with the wrong DMA controller or tube on STM32F1, + * dma_tube_cfg() will fail. + * + * 2. In general, a DMA tube can only serve a single request source at + * a time, and on STM32F1, Terrible Super-Bad Things will happen if + * two request sources are active for a single tube. + * + * To make all this easier to sort out, these dma_request_src + * enumerators are grouped by DMA controller and tube. + * + * @see struct dma_tube_config + * @see dma_tube_cfg() + */ +typedef enum dma_request_src { + /* Each request source encodes the DMA controller and channel it + * belongs to, for error checking in dma_tube_cfg(). */ + + /* DMA1 request sources */ + + /**@{*/ + /** (DMA1, tube 1) */ + DMA_REQ_SRC_ADC1 = (RCC_DMA1 << 3) | 1, + DMA_REQ_SRC_TIM2_CH3 = (RCC_DMA1 << 3) | 1, + DMA_REQ_SRC_TIM4_CH1 = (RCC_DMA1 << 3) | 1, + /**@}*/ + + /**@{*/ + /** (DMA1, tube 2)*/ + DMA_REQ_SRC_SPI1_RX = (RCC_DMA1 << 3) | 2, + DMA_REQ_SRC_USART3_TX = (RCC_DMA1 << 3) | 2, + DMA_REQ_SRC_TIM1_CH1 = (RCC_DMA1 << 3) | 2, + DMA_REQ_SRC_TIM2_UP = (RCC_DMA1 << 3) | 2, + DMA_REQ_SRC_TIM3_CH3 = (RCC_DMA1 << 3) | 2, + /**@}*/ + + /**@{*/ + /** (DMA1, tube 3)*/ + DMA_REQ_SRC_SPI1_TX = (RCC_DMA1 << 3) | 3, + DMA_REQ_SRC_USART3_RX = (RCC_DMA1 << 3) | 3, + DMA_REQ_SRC_TIM1_CH2 = (RCC_DMA1 << 3) | 3, + DMA_REQ_SRC_TIM3_CH4 = (RCC_DMA1 << 3) | 3, + DMA_REQ_SRC_TIM3_UP = (RCC_DMA1 << 3) | 3, + /**@}*/ + + /**@{*/ + /** (DMA1, tube 4)*/ + DMA_REQ_SRC_SPI2_RX = (RCC_DMA1 << 3) | 4, + DMA_REQ_SRC_I2S2_RX = (RCC_DMA1 << 3) | 4, + DMA_REQ_SRC_USART1_TX = (RCC_DMA1 << 3) | 4, + DMA_REQ_SRC_I2C2_TX = (RCC_DMA1 << 3) | 4, + DMA_REQ_SRC_TIM1_CH4 = (RCC_DMA1 << 3) | 4, + DMA_REQ_SRC_TIM1_TRIG = (RCC_DMA1 << 3) | 4, + DMA_REQ_SRC_TIM1_COM = (RCC_DMA1 << 3) | 4, + DMA_REQ_SRC_TIM4_CH2 = (RCC_DMA1 << 3) | 4, + /**@}*/ + + /**@{*/ + /** (DMA1, tube 5)*/ + DMA_REQ_SRC_SPI2_TX = (RCC_DMA1 << 3) | 5, + DMA_REQ_SRC_I2S2_TX = (RCC_DMA1 << 3) | 5, + DMA_REQ_SRC_USART1_RX = (RCC_DMA1 << 3) | 5, + DMA_REQ_SRC_I2C2_RX = (RCC_DMA1 << 3) | 5, + DMA_REQ_SRC_TIM1_UP = (RCC_DMA1 << 3) | 5, + DMA_REQ_SRC_TIM2_CH1 = (RCC_DMA1 << 3) | 5, + DMA_REQ_SRC_TIM4_CH3 = (RCC_DMA1 << 3) | 5, + /**@}*/ + + /**@{*/ + /** (DMA1, tube 6)*/ + DMA_REQ_SRC_USART2_RX = (RCC_DMA1 << 3) | 6, + DMA_REQ_SRC_I2C1_TX = (RCC_DMA1 << 3) | 6, + DMA_REQ_SRC_TIM1_CH3 = (RCC_DMA1 << 3) | 6, + DMA_REQ_SRC_TIM3_CH1 = (RCC_DMA1 << 3) | 6, + DMA_REQ_SRC_TIM3_TRIG = (RCC_DMA1 << 3) | 6, + /**@}*/ + + /**@{*/ + /* Tube 7 */ + DMA_REQ_SRC_USART2_TX = (RCC_DMA1 << 3) | 7, + DMA_REQ_SRC_I2C1_RX = (RCC_DMA1 << 3) | 7, + DMA_REQ_SRC_TIM2_CH2 = (RCC_DMA1 << 3) | 7, + DMA_REQ_SRC_TIM2_CH4 = (RCC_DMA1 << 3) | 7, + DMA_REQ_SRC_TIM4_UP = (RCC_DMA1 << 3) | 7, + /**@}*/ + + /* DMA2 request sources */ + + /**@{*/ + /** (DMA2, tube 1)*/ + DMA_REQ_SRC_SPI3_RX = (RCC_DMA2 << 3) | 1, + DMA_REQ_SRC_I2S3_RX = (RCC_DMA2 << 3) | 1, + DMA_REQ_SRC_TIM5_CH4 = (RCC_DMA2 << 3) | 1, + DMA_REQ_SRC_TIM5_TRIG = (RCC_DMA2 << 3) | 1, + /**@}*/ + + /**@{*/ + /** (DMA2, tube 2)*/ + DMA_REQ_SRC_SPI3_TX = (RCC_DMA2 << 3) | 2, + DMA_REQ_SRC_I2S3_TX = (RCC_DMA2 << 3) | 2, + DMA_REQ_SRC_TIM5_CH3 = (RCC_DMA2 << 3) | 2, + DMA_REQ_SRC_TIM5_UP = (RCC_DMA2 << 3) | 2, + /**@}*/ + + /**@{*/ + /** (DMA2, tube 3)*/ + DMA_REQ_SRC_UART4_RX = (RCC_DMA2 << 3) | 3, + DMA_REQ_SRC_TIM6_UP = (RCC_DMA2 << 3) | 3, + DMA_REQ_SRC_DAC_CH1 = (RCC_DMA2 << 3) | 3, + /**@}*/ + + /**@{*/ + /** (DMA2, tube 4)*/ + DMA_REQ_SRC_SDIO = (RCC_DMA2 << 3) | 4, + DMA_REQ_SRC_TIM5_CH2 = (RCC_DMA2 << 3) | 4, + /**@}*/ + + /**@{*/ + /** (DMA2, tube 5)*/ + DMA_REQ_SRC_ADC3 = (RCC_DMA2 << 3) | 5, + DMA_REQ_SRC_UART4_TX = (RCC_DMA2 << 3) | 5, + DMA_REQ_SRC_TIM5_CH1 = (RCC_DMA2 << 3) | 5, + /**@}*/ +} dma_request_src; + +/* + * Convenience routines. + */ + +/** + * @brief On STM32F1, dma_is_channel_enabled() is an alias for + * dma_is_enabled(). + * This is for backwards compatibility. + */ +#define dma_is_channel_enabled dma_is_enabled + +#define DMA_CHANNEL_NREGS 5 /* accounts for reserved word */ +static inline dma_tube_reg_map* dma_tube_regs(dma_dev *dev, dma_tube tube) { + __io uint32 *ccr1 = &dev->regs->CCR1; + return (dma_channel_reg_map*)(ccr1 + DMA_CHANNEL_NREGS * (tube - 1)); +} + +/** + * @brief On STM32F1, dma_channel_regs() is an alias for dma_tube_regs(). + * This is for backwards compatibility. */ +#define dma_channel_regs(dev, ch) dma_tube_regs(dev, ch) + +static inline uint8 dma_is_enabled(dma_dev *dev, dma_tube tube) { + return (uint8)(dma_tube_regs(dev, tube)->CCR & DMA_CCR_EN); +} + +static inline uint8 dma_get_isr_bits(dma_dev *dev, dma_tube tube) { + uint8 shift = (tube - 1) * 4; + return (dev->regs->ISR >> shift) & 0xF; +} + +static inline void dma_clear_isr_bits(dma_dev *dev, dma_tube tube) { + dev->regs->IFCR = (1U << (4 * (tube - 1))); +} + +/** + * @brief Deprecated + * STM32F1 mode flags for dma_setup_xfer(). Use dma_tube_cfg() instead. + * @see dma_tube_cfg() + */ +typedef enum dma_mode_flags { + DMA_MEM_2_MEM = 1 << 14, /**< Memory to memory mode */ + DMA_MINC_MODE = 1 << 7, /**< Auto-increment memory address */ + DMA_PINC_MODE = 1 << 6, /**< Auto-increment peripheral address */ + DMA_CIRC_MODE = 1 << 5, /**< Circular mode */ + DMA_FROM_MEM = 1 << 4, /**< Read from memory to peripheral */ + DMA_TRNS_ERR = 1 << 3, /**< Interrupt on transfer error */ + DMA_HALF_TRNS = 1 << 2, /**< Interrupt on half-transfer */ + DMA_TRNS_CMPLT = 1 << 1 /**< Interrupt on transfer completion */ +} dma_mode_flags; + +/* Keep this around for backwards compatibility, but it's deprecated. + * New code should use dma_tube_cfg() instead. + * + * (It's not possible to fully configure a DMA stream on F2 with just + * this information, so this interface is too tied to the F1.) */ +void dma_setup_transfer(dma_dev *dev, + dma_channel channel, + __io void *peripheral_address, + dma_xfer_size peripheral_size, + __io void *memory_address, + dma_xfer_size memory_size, + uint32 mode); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/exti.h b/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/exti.h new file mode 100644 index 0000000..1ece664 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/exti.h @@ -0,0 +1,46 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/include/series/exti.h + * @brief STM32F1 external interrupts + */ + +#ifndef _LIBMAPLE_STM32F1_EXTI_H_ +#define _LIBMAPLE_STM32F1_EXTI_H_ + +#ifdef __cpluspus +extern "C" { +#endif + +struct exti_reg_map; +#define EXTI_BASE ((struct exti_reg_map*)0x40010400) + +#ifdef __cpluspus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/flash.h b/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/flash.h new file mode 100644 index 0000000..24efb0b --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/flash.h @@ -0,0 +1,149 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Perry Hung. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/include/series/flash.h + * @brief STM32F1 Flash header. + * + * Provides register map, base pointer, and register bit definitions + * for the Flash controller on the STM32F1 line, along with + * series-specific configuration values. + */ + +#ifndef _LIBMAPLE_STM32F1_FLASH_H_ +#define _LIBMAPLE_STM32F1_FLASH_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include + +/* + * Register map + */ + +/** @brief STM32F1 Flash register map type */ +typedef struct flash_reg_map { + __io uint32 ACR; /**< Access control register */ + __io uint32 KEYR; /**< Key register */ + __io uint32 OPTKEYR; /**< OPTKEY register */ + __io uint32 SR; /**< Status register */ + __io uint32 CR; /**< Control register */ + __io uint32 AR; /**< Address register */ + __io uint32 OBR; /**< Option byte register */ + __io uint32 WRPR; /**< Write protection register */ +} flash_reg_map; + +#define FLASH_BASE ((struct flash_reg_map*)0x40022000) + +/* + * Register bit definitions + */ + +/* Access control register */ + +#define FLASH_ACR_PRFTBS_BIT 5 +#define FLASH_ACR_PRFTBE_BIT 4 +#define FLASH_ACR_HLFCYA_BIT 3 + +#define FLASH_ACR_PRFTBS (1U << FLASH_ACR_PRFTBS_BIT) +#define FLASH_ACR_PRFTBE (1U << FLASH_ACR_PRFTBE_BIT) +#define FLASH_ACR_HLFCYA (1U << FLASH_ACR_HLFCYA_BIT) +#define FLASH_ACR_LATENCY 0x7 + +/* Status register */ + +#define FLASH_SR_EOP_BIT 5 +#define FLASH_SR_WRPRTERR_BIT 4 +#define FLASH_SR_PGERR_BIT 2 +#define FLASH_SR_BSY_BIT 0 + +#define FLASH_SR_EOP (1U << FLASH_SR_EOP_BIT) +#define FLASH_SR_WRPRTERR (1U << FLASH_SR_WRPRTERR_BIT) +#define FLASH_SR_PGERR (1U << FLASH_SR_PGERR_BIT) +#define FLASH_SR_BSY (1U << FLASH_SR_BSY_BIT) + +/* Control register */ + +#define FLASH_CR_EOPIE_BIT 12 +#define FLASH_CR_ERRIE_BIT 10 +#define FLASH_CR_OPTWRE_BIT 9 +#define FLASH_CR_LOCK_BIT 7 +#define FLASH_CR_STRT_BIT 6 +#define FLASH_CR_OPTER_BIT 5 +#define FLASH_CR_OPTPG_BIT 4 +#define FLASH_CR_MER_BIT 2 +#define FLASH_CR_PER_BIT 1 +#define FLASH_CR_PG_BIT 0 + +#define FLASH_CR_EOPIE (1U << FLASH_CR_EOPIE_BIT) +#define FLASH_CR_ERRIE (1U << FLASH_CR_ERRIE_BIT) +#define FLASH_CR_OPTWRE (1U << FLASH_CR_OPTWRE_BIT) +#define FLASH_CR_LOCK (1U << FLASH_CR_LOCK_BIT) +#define FLASH_CR_STRT (1U << FLASH_CR_STRT_BIT) +#define FLASH_CR_OPTER (1U << FLASH_CR_OPTER_BIT) +#define FLASH_CR_OPTPG (1U << FLASH_CR_OPTPG_BIT) +#define FLASH_CR_MER (1U << FLASH_CR_MER_BIT) +#define FLASH_CR_PER (1U << FLASH_CR_PER_BIT) +#define FLASH_CR_PG (1U << FLASH_CR_PG_BIT) + +/* Option byte register */ + +#define FLASH_OBR_nRST_STDBY_BIT 4 +#define FLASH_OBR_nRST_STOP_BIT 3 +#define FLASH_OBR_WDG_SW_BIT 2 +#define FLASH_OBR_RDPRT_BIT 1 +#define FLASH_OBR_OPTERR_BIT 0 + +#define FLASH_OBR_DATA1 (0xFF << 18) +#define FLASH_OBR_DATA0 (0xFF << 10) +#define FLASH_OBR_USER 0x3FF +#define FLASH_OBR_nRST_STDBY (1U << FLASH_OBR_nRST_STDBY_BIT) +#define FLASH_OBR_nRST_STOP (1U << FLASH_OBR_nRST_STOP_BIT) +#define FLASH_OBR_WDG_SW (1U << FLASH_OBR_WDG_SW_BIT) +#define FLASH_OBR_RDPRT (1U << FLASH_OBR_RDPRT_BIT) +#define FLASH_OBR_OPTERR (1U << FLASH_OBR_OPTERR_BIT) + +/* + * Series-specific configuration values. + */ + +#define FLASH_SAFE_WAIT_STATES FLASH_WAIT_STATE_2 + +/* Flash memory features available via ACR */ +enum { + FLASH_PREFETCH = 0x10, + FLASH_HALF_CYCLE = 0x8, + FLASH_ICACHE = 0x0, /* Not available on STM32F1 */ + FLASH_DCACHE = 0x0, /* Not available on STM32F1 */ +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/gpio.h b/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/gpio.h new file mode 100644 index 0000000..aff639b --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/gpio.h @@ -0,0 +1,495 @@ +/****************************************************************************** + * 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 + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. +*****************************************************************************/ + +/** + * @file libmaple/stm32f1/include/series/gpio.h + * @brief STM32F1 GPIO and AFIO support. + * General purpose I/O (GPIO) and Alternate Function I/O (AFIO). + */ + +#ifndef _LIBMAPLE_STM32F1_GPIO_H_ +#define _LIBMAPLE_STM32F1_GPIO_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include +#include +#include + +/* + * GPIO register maps and devices + */ + +/** GPIO register map type */ +typedef struct gpio_reg_map { + __io uint32 CRL; /**< Port configuration register low */ + __io uint32 CRH; /**< Port configuration register high */ + __io uint32 IDR; /**< Port input data register */ + __io uint32 ODR; /**< Port output data register */ + __io uint32 BSRR; /**< Port bit set/reset register */ + __io uint32 BRR; /**< Port bit reset register */ + __io uint32 LCKR; /**< Port configuration lock register */ +} gpio_reg_map; + +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 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 */ +#define GPIOA_BASE ((struct gpio_reg_map*)0x40010800) +/** GPIO port B register map base pointer */ +#define GPIOB_BASE ((struct gpio_reg_map*)0x40010C00) +/** GPIO port C register map base pointer */ +#define GPIOC_BASE ((struct gpio_reg_map*)0x40011000) +/** GPIO port D register map base pointer */ +#define GPIOD_BASE ((struct gpio_reg_map*)0x40011400) +/** 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) + +/* + * GPIO register bit definitions + */ + +/* Control registers, low and high */ + +#define GPIO_CR_CNF (0x3 << 2) +#define GPIO_CR_CNF_INPUT_ANALOG (0x0 << 2) +#define GPIO_CR_CNF_INPUT_FLOATING (0x1 << 2) +#define GPIO_CR_CNF_INPUT_PU_PD (0x2 << 2) +#define GPIO_CR_CNF_OUTPUT_PP (0x0 << 2) +#define GPIO_CR_CNF_OUTPUT_OD (0x1 << 2) +#define GPIO_CR_CNF_AF_OUTPUT_PP (0x2 << 2) +#define GPIO_CR_CNF_AF_OUTPUT_OD (0x3 << 2) +#define GPIO_CR_MODE 0x3 +#define GPIO_CR_MODE_INPUT 0x0 +#define GPIO_CR_MODE_OUTPUT_10MHZ 0x1 +#define GPIO_CR_MODE_OUTPUT_2MHZ 0x2 +#define GPIO_CR_MODE_OUTPUT_50MHZ 0x3 + +/** + * @brief GPIO pin modes. + * + * These only allow for 50MHZ max output speeds; if you want slower, + * use direct register access. + */ +typedef enum gpio_pin_mode { + /** Output push-pull. */ + GPIO_OUTPUT_PP = GPIO_CR_CNF_OUTPUT_PP | GPIO_CR_MODE_OUTPUT_50MHZ, + /** Output open-drain. */ + GPIO_OUTPUT_OD = GPIO_CR_CNF_OUTPUT_OD | GPIO_CR_MODE_OUTPUT_50MHZ, + /** Alternate function output push-pull. */ + GPIO_AF_OUTPUT_PP = GPIO_CR_CNF_AF_OUTPUT_PP | GPIO_CR_MODE_OUTPUT_50MHZ, + /** Alternate function output open drain. */ + GPIO_AF_OUTPUT_OD = GPIO_CR_CNF_AF_OUTPUT_OD | GPIO_CR_MODE_OUTPUT_50MHZ, + /** Analog input. */ + GPIO_INPUT_ANALOG = GPIO_CR_CNF_INPUT_ANALOG | GPIO_CR_MODE_INPUT, + /** Input floating. */ + GPIO_INPUT_FLOATING = GPIO_CR_CNF_INPUT_FLOATING | GPIO_CR_MODE_INPUT, + /** Input pull-down. */ + GPIO_INPUT_PD = GPIO_CR_CNF_INPUT_PU_PD | GPIO_CR_MODE_INPUT, + /** Input pull-up. */ + GPIO_INPUT_PU, /* (treated a special case, for ODR twiddling) */ +} gpio_pin_mode; + +/* Hacks for F2: */ +#define GPIO_MODE_ANALOG GPIO_INPUT_ANALOG +#define GPIO_MODE_OUTPUT GPIO_OUTPUT_PP + +/* + * AFIO register map + */ + +/** AFIO register map */ +typedef struct afio_reg_map { + __io uint32 EVCR; /**< Event control register. */ + __io uint32 MAPR; /**< AF remap and debug I/O configuration register. */ + __io uint32 EXTICR1; /**< External interrupt configuration register 1. */ + __io uint32 EXTICR2; /**< External interrupt configuration register 2. */ + __io uint32 EXTICR3; /**< External interrupt configuration register 3. */ + __io uint32 EXTICR4; /**< External interrupt configuration register 4. */ + __io uint32 MAPR2; /**< + * AF remap and debug I/O configuration register 2. */ +} afio_reg_map; + +/** AFIO register map base pointer. */ +#define AFIO_BASE ((struct afio_reg_map *)0x40010000) + +/* + * AFIO register bit definitions + */ + +/* Event control register */ + +#define AFIO_EVCR_EVOE (0x1 << 7) +#define AFIO_EVCR_PORT_PA (0x0 << 4) +#define AFIO_EVCR_PORT_PB (0x1 << 4) +#define AFIO_EVCR_PORT_PC (0x2 << 4) +#define AFIO_EVCR_PORT_PD (0x3 << 4) +#define AFIO_EVCR_PORT_PE (0x4 << 4) +#define AFIO_EVCR_PIN_0 0x0 +#define AFIO_EVCR_PIN_1 0x1 +#define AFIO_EVCR_PIN_2 0x2 +#define AFIO_EVCR_PIN_3 0x3 +#define AFIO_EVCR_PIN_4 0x4 +#define AFIO_EVCR_PIN_5 0x5 +#define AFIO_EVCR_PIN_6 0x6 +#define AFIO_EVCR_PIN_7 0x7 +#define AFIO_EVCR_PIN_8 0x8 +#define AFIO_EVCR_PIN_9 0x9 +#define AFIO_EVCR_PIN_10 0xA +#define AFIO_EVCR_PIN_11 0xB +#define AFIO_EVCR_PIN_12 0xC +#define AFIO_EVCR_PIN_13 0xD +#define AFIO_EVCR_PIN_14 0xE +#define AFIO_EVCR_PIN_15 0xF + +/* AF remap and debug I/O configuration register */ + +#define AFIO_MAPR_SWJ_CFG (0x7 << 24) +#define AFIO_MAPR_SWJ_CFG_FULL_SWJ (0x0 << 24) +#define AFIO_MAPR_SWJ_CFG_FULL_SWJ_NO_NJRST (0x1 << 24) +#define AFIO_MAPR_SWJ_CFG_NO_JTAG_SW (0x2 << 24) +#define AFIO_MAPR_SWJ_CFG_NO_JTAG_NO_SW (0x4 << 24) +#define AFIO_MAPR_ADC2_ETRGREG_REMAP (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 (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) +#define AFIO_MAPR_TIM3_REMAP_FULL (0x3 << 10) +#define AFIO_MAPR_TIM2_REMAP (0x3 << 8) +#define AFIO_MAPR_TIM2_REMAP_NONE (0x0 << 8) +#define AFIO_MAPR_TIM2_REMAP_PA15_PB3_PA2_PA3 (0x1 << 8) +#define AFIO_MAPR_TIM2_REMAP_PA0_PA1_PB10_PB11 (0x2 << 8) +#define AFIO_MAPR_TIM2_REMAP_FULL (0x3 << 8) +#define AFIO_MAPR_TIM1_REMAP (0x3 << 6) +#define AFIO_MAPR_TIM1_REMAP_NONE (0x0 << 6) +#define AFIO_MAPR_TIM1_REMAP_PARTIAL (0x1 << 6) +#define AFIO_MAPR_TIM1_REMAP_FULL (0x3 << 6) +#define AFIO_MAPR_USART3_REMAP (0x3 << 4) +#define AFIO_MAPR_USART3_REMAP_NONE (0x0 << 4) +#define AFIO_MAPR_USART3_REMAP_PARTIAL (0x1 << 4) +#define AFIO_MAPR_USART3_REMAP_FULL (0x3 << 4) +#define AFIO_MAPR_USART2_REMAP (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 */ + +#define AFIO_EXTICR1_EXTI3 (0xF << 12) +#define AFIO_EXTICR1_EXTI3_PA (0x0 << 12) +#define AFIO_EXTICR1_EXTI3_PB (0x1 << 12) +#define AFIO_EXTICR1_EXTI3_PC (0x2 << 12) +#define AFIO_EXTICR1_EXTI3_PD (0x3 << 12) +#define AFIO_EXTICR1_EXTI3_PE (0x4 << 12) +#define AFIO_EXTICR1_EXTI3_PF (0x5 << 12) +#define AFIO_EXTICR1_EXTI3_PG (0x6 << 12) +#define AFIO_EXTICR1_EXTI2 (0xF << 8) +#define AFIO_EXTICR1_EXTI2_PA (0x0 << 8) +#define AFIO_EXTICR1_EXTI2_PB (0x1 << 8) +#define AFIO_EXTICR1_EXTI2_PC (0x2 << 8) +#define AFIO_EXTICR1_EXTI2_PD (0x3 << 8) +#define AFIO_EXTICR1_EXTI2_PE (0x4 << 8) +#define AFIO_EXTICR1_EXTI2_PF (0x5 << 8) +#define AFIO_EXTICR1_EXTI2_PG (0x6 << 8) +#define AFIO_EXTICR1_EXTI1 (0xF << 4) +#define AFIO_EXTICR1_EXTI1_PA (0x0 << 4) +#define AFIO_EXTICR1_EXTI1_PB (0x1 << 4) +#define AFIO_EXTICR1_EXTI1_PC (0x2 << 4) +#define AFIO_EXTICR1_EXTI1_PD (0x3 << 4) +#define AFIO_EXTICR1_EXTI1_PE (0x4 << 4) +#define AFIO_EXTICR1_EXTI1_PF (0x5 << 4) +#define AFIO_EXTICR1_EXTI1_PG (0x6 << 4) +#define AFIO_EXTICR1_EXTI0 0xF +#define AFIO_EXTICR1_EXTI0_PA 0x0 +#define AFIO_EXTICR1_EXTI0_PB 0x1 +#define AFIO_EXTICR1_EXTI0_PC 0x2 +#define AFIO_EXTICR1_EXTI0_PD 0x3 +#define AFIO_EXTICR1_EXTI0_PE 0x4 +#define AFIO_EXTICR1_EXTI0_PF 0x5 +#define AFIO_EXTICR1_EXTI0_PG 0x6 + +/* External interrupt configuration register 2 */ + +#define AFIO_EXTICR2_EXTI7 (0xF << 12) +#define AFIO_EXTICR2_EXTI7_PA (0x0 << 12) +#define AFIO_EXTICR2_EXTI7_PB (0x1 << 12) +#define AFIO_EXTICR2_EXTI7_PC (0x2 << 12) +#define AFIO_EXTICR2_EXTI7_PD (0x3 << 12) +#define AFIO_EXTICR2_EXTI7_PE (0x4 << 12) +#define AFIO_EXTICR2_EXTI7_PF (0x5 << 12) +#define AFIO_EXTICR2_EXTI7_PG (0x6 << 12) +#define AFIO_EXTICR2_EXTI6 (0xF << 8) +#define AFIO_EXTICR2_EXTI6_PA (0x0 << 8) +#define AFIO_EXTICR2_EXTI6_PB (0x1 << 8) +#define AFIO_EXTICR2_EXTI6_PC (0x2 << 8) +#define AFIO_EXTICR2_EXTI6_PD (0x3 << 8) +#define AFIO_EXTICR2_EXTI6_PE (0x4 << 8) +#define AFIO_EXTICR2_EXTI6_PF (0x5 << 8) +#define AFIO_EXTICR2_EXTI6_PG (0x6 << 8) +#define AFIO_EXTICR2_EXTI5 (0xF << 4) +#define AFIO_EXTICR2_EXTI5_PA (0x0 << 4) +#define AFIO_EXTICR2_EXTI5_PB (0x1 << 4) +#define AFIO_EXTICR2_EXTI5_PC (0x2 << 4) +#define AFIO_EXTICR2_EXTI5_PD (0x3 << 4) +#define AFIO_EXTICR2_EXTI5_PE (0x4 << 4) +#define AFIO_EXTICR2_EXTI5_PF (0x5 << 4) +#define AFIO_EXTICR2_EXTI5_PG (0x6 << 4) +#define AFIO_EXTICR2_EXTI4 0xF +#define AFIO_EXTICR2_EXTI4_PA 0x0 +#define AFIO_EXTICR2_EXTI4_PB 0x1 +#define AFIO_EXTICR2_EXTI4_PC 0x2 +#define AFIO_EXTICR2_EXTI4_PD 0x3 +#define AFIO_EXTICR2_EXTI4_PE 0x4 +#define AFIO_EXTICR2_EXTI4_PF 0x5 +#define AFIO_EXTICR2_EXTI4_PG 0x6 + +/* AF remap and debug I/O configuration register 2 */ + +#define AFIO_MAPR2_FSMC_NADV (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 + */ + +void afio_init(void); + +/* HACK: Use upper bit to denote MAPR2, Bit 31 is reserved and + * not used in either MAPR or MAPR2 */ +#define AFIO_REMAP_USE_MAPR2 (1U << 31) + +/** + * @brief Available peripheral remaps. + * @see afio_remap() + */ +typedef enum afio_remap_peripheral { + /** ADC 2 external trigger regular conversion remapping */ + AFIO_REMAP_ADC2_ETRGREG = AFIO_MAPR_ADC2_ETRGREG_REMAP, + /** ADC 2 external trigger injected conversion remapping */ + AFIO_REMAP_ADC2_ETRGINJ = AFIO_MAPR_ADC2_ETRGINJ_REMAP, + /** ADC 1 external trigger regular conversion remapping */ + AFIO_REMAP_ADC1_ETRGREG = AFIO_MAPR_ADC1_ETRGREG_REMAP, + /** ADC 1 external trigger injected conversion remapping */ + AFIO_REMAP_ADC1_ETRGINJ = AFIO_MAPR_ADC1_ETRGINJ_REMAP, + /** Timer 5 channel 4 internal remapping */ + AFIO_REMAP_TIM5CH4_I = AFIO_MAPR_TIM5CH4_IREMAP, + /** Port D0/Port D1 mapping on OSC_IN/OSC_OUT */ + AFIO_REMAP_PD01 = AFIO_MAPR_PD01_REMAP, + /** CAN alternate function remapping 1 (RX on PB8, TX on PB9) */ + AFIO_REMAP_CAN_1 = AFIO_MAPR_CAN_REMAP_PB8_PB9, + /** CAN alternate function remapping 2 (RX on PD0, TX on PD1) */ + AFIO_REMAP_CAN_2 = AFIO_MAPR_CAN_REMAP_PD0_PD1, + /** Timer 4 remapping */ + AFIO_REMAP_TIM4 = AFIO_MAPR_TIM4_REMAP, + /** Timer 3 partial remapping */ + AFIO_REMAP_TIM3_PARTIAL = AFIO_MAPR_TIM3_REMAP_PARTIAL, + /** Timer 3 full remapping */ + AFIO_REMAP_TIM3_FULL = AFIO_MAPR_TIM3_REMAP_FULL, + /** + * Timer 2 partial remapping 1 (CH1 and ETR on PA15, CH2 on PB3, + * CH3 on PA2, CH4 on PA3) */ + AFIO_REMAP_TIM2_PARTIAL_1 = AFIO_MAPR_TIM2_REMAP_PA15_PB3_PA2_PA3, + /** + * Timer 2 partial remapping 2 (CH1 and ETR on PA0, CH2 on PA1, + * CH3 on PB10, CH4 on PB11) */ + AFIO_REMAP_TIM2_PARTIAL_2 = AFIO_MAPR_TIM2_REMAP_PA0_PA1_PB10_PB11, + /** Timer 2 full remapping */ + AFIO_REMAP_TIM2_FULL = AFIO_MAPR_TIM2_REMAP_FULL, + /** USART 3 part remapping */ + AFIO_REMAP_USART3_PARTIAL = AFIO_MAPR_USART3_REMAP_PARTIAL, + /** USART 2 remapping */ + AFIO_REMAP_USART2 = AFIO_MAPR_USART2_REMAP, + /** USART 1 remapping */ + AFIO_REMAP_USART1 = AFIO_MAPR_USART1_REMAP, + /** I2C 1 remapping */ + AFIO_REMAP_I2C1 = AFIO_MAPR_I2C1_REMAP, + /** SPI 1 remapping */ + AFIO_REMAP_SPI1 = AFIO_MAPR_SPI1_REMAP, + /** NADV signal not connected */ + AFIO_REMAP_FSMC_NADV = AFIO_MAPR2_FSMC_NADV | AFIO_REMAP_USE_MAPR2, + /** Timer 14 remapping */ + AFIO_REMAP_TIM14 = AFIO_MAPR2_TIM14_REMAP | AFIO_REMAP_USE_MAPR2, + /** Timer 13 remapping */ + AFIO_REMAP_TIM13 = AFIO_MAPR2_TIM13_REMAP | AFIO_REMAP_USE_MAPR2, + /** Timer 11 remapping */ + AFIO_REMAP_TIM11 = AFIO_MAPR2_TIM11_REMAP | AFIO_REMAP_USE_MAPR2, + /** Timer 10 remapping */ + AFIO_REMAP_TIM10 = AFIO_MAPR2_TIM10_REMAP | AFIO_REMAP_USE_MAPR2, + /** Timer 9 remapping */ + AFIO_REMAP_TIM9 = AFIO_MAPR2_TIM9_REMAP | AFIO_REMAP_USE_MAPR2, +} afio_remap_peripheral; + +void afio_remap(afio_remap_peripheral p); + +/** + * @brief Debug port configuration + * + * Used to configure the behavior of JTAG and Serial Wire (SW) debug + * ports and their associated GPIO pins. + * + * @see afio_cfg_debug_ports() + */ +typedef enum afio_debug_cfg { + /** Full Serial Wire and JTAG debug */ + AFIO_DEBUG_FULL_SWJ = AFIO_MAPR_SWJ_CFG_FULL_SWJ, + /** Full Serial Wire and JTAG, but no NJTRST. */ + AFIO_DEBUG_FULL_SWJ_NO_NJRST = AFIO_MAPR_SWJ_CFG_FULL_SWJ_NO_NJRST, + /** Serial Wire debug only (JTAG-DP disabled, SW-DP enabled) */ + AFIO_DEBUG_SW_ONLY = AFIO_MAPR_SWJ_CFG_NO_JTAG_SW, + /** No debug; all JTAG and SW pins are free for use as GPIOs. */ + AFIO_DEBUG_NONE = AFIO_MAPR_SWJ_CFG_NO_JTAG_NO_SW, +} afio_debug_cfg; + +/** + * @brief Enable or disable the JTAG and SW debug ports. + * @param config Desired debug port configuration + * @see afio_debug_cfg + */ +static inline void afio_cfg_debug_ports(afio_debug_cfg config) { + __io uint32 *mapr = &AFIO_BASE->MAPR; + *mapr = (*mapr & ~AFIO_MAPR_SWJ_CFG) | config; +} + +/* + * 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 inline __always_inline void afio_exti_select(exti_num exti, exti_cfg port) { + exti_select(exti, port); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/i2c.h b/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/i2c.h new file mode 100644 index 0000000..f407955 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/i2c.h @@ -0,0 +1,85 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Perry Hung (from ). + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/include/series/i2c.h + * @brief STM32F1 I2C + */ + +#ifndef _LIBMAPLE_STM32F1_I2C_H_ +#define _LIBMAPLE_STM32F1_I2C_H_ + +#include +#include +#include + +/* + * Register maps + */ + +struct i2c_reg_map; + +/** STM32F1 I2C1 register map base pointer */ +#define I2C1_BASE ((struct i2c_reg_map*)0x40005400) +/** STM32F1 I2C2 register map base pointer */ +#define I2C2_BASE ((struct i2c_reg_map*)0x40005800) + +/* + * Devices + */ + +extern i2c_dev* const I2C1; +extern i2c_dev* const I2C2; + +/* + * For internal use + */ + +static inline uint32 _i2c_bus_clk(i2c_dev *dev) { + /* Both I2C peripherals are on APB1 */ + return STM32_PCLK1 / (1000 * 1000); +} + +#define _I2C_HAVE_IRQ_FIXUP 1 +void _i2c_irq_priority_fixup(i2c_dev *dev); + +/* + * Deprecated functionality + */ + +/* Flag to use alternate pin mapping in i2c_master_enable(). */ +#define _I2C_HAVE_DEPRECATED_I2C_REMAP 1 +#define I2C_REMAP 0x4 +static inline void _i2c_handle_remap(i2c_dev *dev, uint32 flags) { + if ((dev == I2C1) && (flags & I2C_REMAP)) { + afio_remap(AFIO_REMAP_I2C1); + I2C1->sda_pin = 9; + I2C1->scl_pin = 8; + } +} + +#endif /* _LIBMAPLE_STM32F1_I2C_H_ */ diff --git a/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/nvic.h b/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/nvic.h new file mode 100644 index 0000000..cdac737 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/nvic.h @@ -0,0 +1,173 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Perry Hung. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/include/series/nvic.h + * @brief STM32F1 Nested Vectored Interrupt Controller (NVIC) support. + */ + +#ifndef _LIBMAPLE_STM32F1_NVIC_H_ +#define _LIBMAPLE_STM32F1_NVIC_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include +#include + +/** + * @brief STM32F1 interrupt vector table interrupt numbers. + * @see + */ +typedef enum nvic_irq_num { + NVIC_NMI = -14, /**< Non-maskable interrupt */ + NVIC_HARDFAULT = -13, /**< Hard fault (all class of fault) */ + NVIC_MEM_MANAGE = -12, /**< Memory management */ + NVIC_BUS_FAULT = -11, /**< Bus fault: prefetch fault, memory + access fault. */ + NVIC_USAGE_FAULT = -10, /**< Usage fault: Undefined instruction or + illegal state. */ + NVIC_SVC = -5, /**< System service call via SWI insruction */ + NVIC_DEBUG_MON = -4, /**< Debug monitor */ + NVIC_PEND_SVC = -2, /**< Pendable request for system service */ + NVIC_SYSTICK = -1, /**< System tick timer */ + NVIC_WWDG = 0, /**< Window watchdog interrupt */ + NVIC_PVD = 1, /**< PVD through EXTI line detection */ + NVIC_TAMPER = 2, /**< Tamper */ + NVIC_RTC = 3, /**< Real-time clock */ + NVIC_FLASH = 4, /**< Flash */ + NVIC_RCC = 5, /**< Reset and clock control */ + NVIC_EXTI0 = 6, /**< EXTI line 0 */ + NVIC_EXTI1 = 7, /**< EXTI line 1 */ + NVIC_EXTI2 = 8, /**< EXTI line 2 */ + NVIC_EXTI3 = 9, /**< EXTI line 3 */ + NVIC_EXTI4 = 10, /**< EXTI line 4 */ + NVIC_DMA_CH1 = 11, /**< DMA1 channel 1 */ + NVIC_DMA_CH2 = 12, /**< DMA1 channel 2 */ + NVIC_DMA_CH3 = 13, /**< DMA1 channel 3 */ + NVIC_DMA_CH4 = 14, /**< DMA1 channel 4 */ + NVIC_DMA_CH5 = 15, /**< DMA1 channel 5 */ + NVIC_DMA_CH6 = 16, /**< DMA1 channel 6 */ + NVIC_DMA_CH7 = 17, /**< DMA1 channel 7 */ + NVIC_ADC_1_2 = 18, /**< ADC1 and ADC2 */ + NVIC_USB_HP_CAN_TX = 19, /**< USB high priority or CAN TX */ + NVIC_USB_LP_CAN_RX0 = 20, /**< USB low priority or CAN RX0 */ + NVIC_CAN_RX1 = 21, /**< CAN RX1 */ + NVIC_CAN_SCE = 22, /**< CAN SCE */ + NVIC_EXTI_9_5 = 23, /**< EXTI line [9:5] */ + NVIC_TIMER1_BRK_TIMER9 = 24, /**< Timer 1 break, Timer 9. */ + NVIC_TIMER1_UP_TIMER10 = 25, /**< Timer 1 update, Timer 10. */ + NVIC_TIMER1_TRG_COM_TIMER11 = 26, /**< + * Timer 1 trigger and commutation, + * Timer 11. */ + NVIC_TIMER1_CC = 27, /**< Timer 1 capture/compare */ + NVIC_TIMER2 = 28, /**< Timer 2 */ + NVIC_TIMER3 = 29, /**< Timer 3 */ + NVIC_TIMER4 = 30, /**< Timer 4 */ + NVIC_I2C1_EV = 31, /**< I2C1 event */ + NVIC_I2C1_ER = 32, /**< I2C1 error */ + NVIC_I2C2_EV = 33, /**< I2C2 event */ + NVIC_I2C2_ER = 34, /**< I2C2 error */ + NVIC_SPI1 = 35, /**< SPI1 */ + NVIC_SPI2 = 36, /**< SPI2 */ + NVIC_USART1 = 37, /**< USART1 */ + NVIC_USART2 = 38, /**< USART2 */ + NVIC_USART3 = 39, /**< USART3 */ + NVIC_EXTI_15_10 = 40, /**< EXTI line [15:10] */ + NVIC_RTCALARM = 41, /**< RTC alarm through EXTI line */ + NVIC_USBWAKEUP = 42, /**< USB wakeup from suspend through + EXTI line */ + NVIC_TIMER8_BRK_TIMER12 = 43, /**< Timer 8 break, timer 12 */ + NVIC_TIMER8_UP_TIMER13 = 44, /**< Timer 8 update, timer 13 */ + NVIC_TIMER8_TRG_COM_TIMER14 = 45, /**< + * Timer 8 trigger and commutation, + * Timer 14. */ + NVIC_TIMER8_CC = 46, /**< Timer 8 capture/compare */ + NVIC_ADC3 = 47, /**< ADC3 */ + NVIC_FSMC = 48, /**< FSMC */ + NVIC_SDIO = 49, /**< SDIO */ + NVIC_TIMER5 = 50, /**< Timer 5 */ + NVIC_SPI3 = 51, /**< SPI3 */ + NVIC_UART4 = 52, /**< UART4 */ + NVIC_UART5 = 53, /**< UART5 */ + NVIC_TIMER6 = 54, /**< Timer 6 */ + NVIC_TIMER7 = 55, /**< Timer 7 */ + NVIC_DMA2_CH1 = 56, /**< DMA2 channel 1 */ + NVIC_DMA2_CH2 = 57, /**< DMA2 channel 2 */ + NVIC_DMA2_CH3 = 58, /**< DMA2 channel 3 */ + NVIC_DMA2_CH_4_5 = 59, /**< DMA2 channels 4 and 5 */ + + /* Old enumerators kept around for backwards compatibility: */ + NVIC_TIMER1_BRK = + NVIC_TIMER1_BRK_TIMER9, /**< @brief (Deprecated) Timer 1 break + * + * For backwards compatibility only. + * Use NVIC_TIMER1_BRK_TIMER9 instead. */ + NVIC_TIMER1_UP = + NVIC_TIMER1_UP_TIMER10, /**< @brief (Deprecated) Timer 1 update. + * + * For backwards compatibility only. + * Use NVIC_TIMER1_UP_TIMER10 instead. */ + NVIC_TIMER1_TRG_COM = + NVIC_TIMER1_TRG_COM_TIMER11, /**< @brief (deprecated) Timer 1 trigger + * and commutation. + * + * For backwards compatibility only. + * Use NVIC_TIMER1_TRG_COM_TIMER11 + * instead. */ + NVIC_TIMER8_BRK = + NVIC_TIMER8_BRK_TIMER12, /**< @brief (deprecated) Timer 8 break + * + * For backwards compatibility only. + * Use NVIC_TIMER8_BRK_TIMER12 instead. */ + NVIC_TIMER8_UP = + NVIC_TIMER8_UP_TIMER13, /**< @brief (deprecated) Timer 8 update + * For backwards compatibility only. + * Use NVIC_TIMER8_UP_TIMER13 instead. */ + NVIC_TIMER8_TRG_COM = + NVIC_TIMER8_TRG_COM_TIMER14, /**< @brief (deprecated) Timer 8 trigger + * and commutation. + * For backwards compatibility only. + * Use NVIC_TIMER8_TRG_COM_TIMER14 + * instead. */ +} nvic_irq_num; + +static inline void nvic_irq_disable_all(void) { + /* Even low-density devices have over 32 interrupt lines. */ + NVIC_BASE->ICER[0] = 0xFFFFFFFF; + NVIC_BASE->ICER[1] = 0xFFFFFFFF; +#if STM32_NR_INTERRUPTS > 64 + /* Only some have over 64; e.g. connectivity line MCUs. */ + NVIC_BASE->ICER[2] = 0xFFFFFFFF; +#endif +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/pwr.h b/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/pwr.h new file mode 100644 index 0000000..e143a8c --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/pwr.h @@ -0,0 +1,52 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/include/series/pwr.h + * @author Marti Bolivar + * @brief STM32F1 Power control (PWR) support. + */ + +#ifndef _LIBMAPLE_STM32F1_PWR_H_ +#define _LIBMAPLE_STM32F1_PWR_H_ + +/* + * Register bit definitions + */ + +/* Control register */ + +/* PVD level selection */ +#define PWR_CR_PLS_2_2V (0x0 << 5) +#define PWR_CR_PLS_2_3V (0x1 << 5) +#define PWR_CR_PLS_2_4V (0x2 << 5) +#define PWR_CR_PLS_2_5V (0x3 << 5) +#define PWR_CR_PLS_2_6V (0x4 << 5) +#define PWR_CR_PLS_2_7V (0x5 << 5) +#define PWR_CR_PLS_2_8V (0x6 << 5) +#define PWR_CR_PLS_2_9V (0x7 << 5) + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/rcc.h b/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/rcc.h new file mode 100644 index 0000000..f40dcba --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/rcc.h @@ -0,0 +1,640 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Perry Hung. + * Copyright (c) 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/include/series/rcc.h + * @brief STM32F1 reset and clock control (RCC) support. + */ + +#ifndef _LIBMAPLE_STM32F1_RCC_H_ +#define _LIBMAPLE_STM32F1_RCC_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include +#include + +/* + * Register map + */ + +/** STM32F1 RCC register map type */ +typedef struct rcc_reg_map { + __io uint32 CR; /**< Clock control register */ + __io uint32 CFGR; /**< Clock configuration register */ + __io uint32 CIR; /**< Clock interrupt register */ + __io uint32 APB2RSTR; /**< APB2 peripheral reset register */ + __io uint32 APB1RSTR; /**< APB1 peripheral reset register */ + __io uint32 AHBENR; /**< AHB peripheral clock enable register */ + __io uint32 APB2ENR; /**< APB2 peripheral clock enable register */ + __io uint32 APB1ENR; /**< APB1 peripheral clock enable register */ + __io uint32 BDCR; /**< Backup domain control register */ + __io uint32 CSR; /**< Control/status register */ +} rcc_reg_map; + +#define RCC_BASE ((struct rcc_reg_map*)0x40021000) + +/* + * Register bit definitions + */ + +/* Clock control register */ + +#define RCC_CR_PLLRDY_BIT 25 +#define RCC_CR_PLLON_BIT 24 +#define RCC_CR_CSSON_BIT 19 +#define RCC_CR_HSEBYP_BIT 18 +#define RCC_CR_HSERDY_BIT 17 +#define RCC_CR_HSEON_BIT 16 +#define RCC_CR_HSIRDY_BIT 1 +#define RCC_CR_HSION_BIT 0 + +#define RCC_CR_PLLRDY (1U << RCC_CR_PLLRDY_BIT) +#define RCC_CR_PLLON (1U << RCC_CR_PLLON_BIT) +#define RCC_CR_CSSON (1U << RCC_CR_CSSON_BIT) +#define RCC_CR_HSEBYP (1U << RCC_CR_HSEBYP_BIT) +#define RCC_CR_HSERDY (1U << RCC_CR_HSERDY_BIT) +#define RCC_CR_HSEON (1U << RCC_CR_HSEON_BIT) +#define RCC_CR_HSICAL (0xFF << 8) +#define RCC_CR_HSITRIM (0x1F << 3) +#define RCC_CR_HSIRDY (1U << RCC_CR_HSIRDY_BIT) +#define RCC_CR_HSION (1U << RCC_CR_HSION_BIT) + +/* Clock configuration register */ + +#define RCC_CFGR_USBPRE_BIT 22 +#define RCC_CFGR_PLLXTPRE_BIT 17 +#define RCC_CFGR_PLLSRC_BIT 16 + +#define RCC_CFGR_MCO (0x3 << 24) +#define RCC_CFGR_USBPRE (0x3 << RCC_CFGR_USBPRE_BIT) +#define RCC_CFGR_PLLMUL (0xF << 18) +#define RCC_CFGR_PLLXTPRE (1U << RCC_CFGR_PLLXTPRE_BIT) +#define RCC_CFGR_PLLSRC (1U << RCC_CFGR_PLLSRC_BIT) +#define RCC_CFGR_ADCPRE (0x3 << 14) +#define RCC_CFGR_PPRE2 (0x7 << 11) +#define RCC_CFGR_PPRE1 (0x7 << 8) +#define RCC_CFGR_HPRE (0xF << 4) +#define RCC_CFGR_SWS (0x3 << 2) +#define RCC_CFGR_SWS_PLL (0x2 << 2) +#define RCC_CFGR_SWS_HSE (0x1 << 2) +#define RCC_CFGR_SW 0x3 +#define RCC_CFGR_SW_PLL 0x2 +#define RCC_CFGR_SW_HSE 0x1 + +/* Clock interrupt register */ + +#define RCC_CIR_CSSC_BIT 23 +#define RCC_CIR_PLLRDYC_BIT 20 +#define RCC_CIR_HSERDYC_BIT 19 +#define RCC_CIR_HSIRDYC_BIT 18 +#define RCC_CIR_LSERDYC_BIT 17 +#define RCC_CIR_LSIRDYC_BIT 16 +#define RCC_CIR_PLLRDYIE_BIT 12 +#define RCC_CIR_HSERDYIE_BIT 11 +#define RCC_CIR_HSIRDYIE_BIT 10 +#define RCC_CIR_LSERDYIE_BIT 9 +#define RCC_CIR_LSIRDYIE_BIT 8 +#define RCC_CIR_CSSF_BIT 7 +#define RCC_CIR_PLLRDYF_BIT 4 +#define RCC_CIR_HSERDYF_BIT 3 +#define RCC_CIR_HSIRDYF_BIT 2 +#define RCC_CIR_LSERDYF_BIT 1 +#define RCC_CIR_LSIRDYF_BIT 0 + +#define RCC_CIR_CSSC (1U << RCC_CIR_CSSC_BIT) +#define RCC_CIR_PLLRDYC (1U << RCC_CIR_PLLRDYC_BIT) +#define RCC_CIR_HSERDYC (1U << RCC_CIR_HSERDYC_BIT) +#define RCC_CIR_HSIRDYC (1U << RCC_CIR_HSIRDYC_BIT) +#define RCC_CIR_LSERDYC (1U << RCC_CIR_LSERDYC_BIT) +#define RCC_CIR_LSIRDYC (1U << RCC_CIR_LSIRDYC_BIT) +#define RCC_CIR_PLLRDYIE (1U << RCC_CIR_PLLRDYIE_BIT) +#define RCC_CIR_HSERDYIE (1U << RCC_CIR_HSERDYIE_BIT) +#define RCC_CIR_HSIRDYIE (1U << RCC_CIR_HSIRDYIE_BIT) +#define RCC_CIR_LSERDYIE (1U << RCC_CIR_LSERDYIE_BIT) +#define RCC_CIR_LSIRDYIE (1U << RCC_CIR_LSIRDYIE_BIT) +#define RCC_CIR_CSSF (1U << RCC_CIR_CSSF_BIT) +#define RCC_CIR_PLLRDYF (1U << RCC_CIR_PLLRDYF_BIT) +#define RCC_CIR_HSERDYF (1U << RCC_CIR_HSERDYF_BIT) +#define RCC_CIR_HSIRDYF (1U << RCC_CIR_HSIRDYF_BIT) +#define RCC_CIR_LSERDYF (1U << RCC_CIR_LSERDYF_BIT) +#define RCC_CIR_LSIRDYF (1U << RCC_CIR_LSIRDYF_BIT) + +/* APB2 peripheral reset register */ + +#define RCC_APB2RSTR_TIM11RST_BIT 21 +#define RCC_APB2RSTR_TIM10RST_BIT 20 +#define RCC_APB2RSTR_TIM9RST_BIT 19 +#define RCC_APB2RSTR_ADC3RST_BIT 15 +#define RCC_APB2RSTR_USART1RST_BIT 14 +#define RCC_APB2RSTR_TIM8RST_BIT 13 +#define RCC_APB2RSTR_SPI1RST_BIT 12 +#define RCC_APB2RSTR_TIM1RST_BIT 11 +#define RCC_APB2RSTR_ADC2RST_BIT 10 +#define RCC_APB2RSTR_ADC1RST_BIT 9 +#define RCC_APB2RSTR_IOPGRST_BIT 8 +#define RCC_APB2RSTR_IOPFRST_BIT 7 +#define RCC_APB2RSTR_IOPERST_BIT 6 +#define RCC_APB2RSTR_IOPDRST_BIT 5 +#define RCC_APB2RSTR_IOPCRST_BIT 4 +#define RCC_APB2RSTR_IOPBRST_BIT 3 +#define RCC_APB2RSTR_IOPARST_BIT 2 +#define RCC_APB2RSTR_AFIORST_BIT 0 + +#define RCC_APB2RSTR_TIM11RST (1U << RCC_APB2RSTR_TIM11RST_BIT) +#define RCC_APB2RSTR_TIM10RST (1U << RCC_APB2RSTR_TIM10RST_BIT) +#define RCC_APB2RSTR_TIM9RST (1U << RCC_APB2RSTR_TIM9RST_BIT) +#define RCC_APB2RSTR_ADC3RST (1U << RCC_APB2RSTR_ADC3RST_BIT) +#define RCC_APB2RSTR_USART1RST (1U << RCC_APB2RSTR_USART1RST_BIT) +#define RCC_APB2RSTR_TIM8RST (1U << RCC_APB2RSTR_TIM8RST_BIT) +#define RCC_APB2RSTR_SPI1RST (1U << RCC_APB2RSTR_SPI1RST_BIT) +#define RCC_APB2RSTR_TIM1RST (1U << RCC_APB2RSTR_TIM1RST_BIT) +#define RCC_APB2RSTR_ADC2RST (1U << RCC_APB2RSTR_ADC2RST_BIT) +#define RCC_APB2RSTR_ADC1RST (1U << RCC_APB2RSTR_ADC1RST_BIT) +#define RCC_APB2RSTR_IOPGRST (1U << RCC_APB2RSTR_IOPGRST_BIT) +#define RCC_APB2RSTR_IOPFRST (1U << RCC_APB2RSTR_IOPFRST_BIT) +#define RCC_APB2RSTR_IOPERST (1U << RCC_APB2RSTR_IOPERST_BIT) +#define RCC_APB2RSTR_IOPDRST (1U << RCC_APB2RSTR_IOPDRST_BIT) +#define RCC_APB2RSTR_IOPCRST (1U << RCC_APB2RSTR_IOPCRST_BIT) +#define RCC_APB2RSTR_IOPBRST (1U << RCC_APB2RSTR_IOPBRST_BIT) +#define RCC_APB2RSTR_IOPARST (1U << RCC_APB2RSTR_IOPARST_BIT) +#define RCC_APB2RSTR_AFIORST (1U << RCC_APB2RSTR_AFIORST_BIT) + +/* APB1 peripheral reset register */ + +#define RCC_APB1RSTR_DACRST_BIT 29 +#define RCC_APB1RSTR_PWRRST_BIT 28 +#define RCC_APB1RSTR_BKPRST_BIT 27 +#define RCC_APB1RSTR_CANRST_BIT 25 +#define RCC_APB1RSTR_USBRST_BIT 23 +#define RCC_APB1RSTR_I2C2RST_BIT 22 +#define RCC_APB1RSTR_I2C1RST_BIT 21 +#define RCC_APB1RSTR_UART5RST_BIT 20 +#define RCC_APB1RSTR_UART4RST_BIT 19 +#define RCC_APB1RSTR_USART3RST_BIT 18 +#define RCC_APB1RSTR_USART2RST_BIT 17 +#define RCC_APB1RSTR_SPI3RST_BIT 15 +#define RCC_APB1RSTR_SPI2RST_BIT 14 +#define RCC_APB1RSTR_WWDRST_BIT 11 +#define RCC_APB1RSTR_TIM14RST_BIT 8 +#define RCC_APB1RSTR_TIM13RST_BIT 7 +#define RCC_APB1RSTR_TIM12RST_BIT 6 +#define RCC_APB1RSTR_TIM7RST_BIT 5 +#define RCC_APB1RSTR_TIM6RST_BIT 4 +#define RCC_APB1RSTR_TIM5RST_BIT 3 +#define RCC_APB1RSTR_TIM4RST_BIT 2 +#define RCC_APB1RSTR_TIM3RST_BIT 1 +#define RCC_APB1RSTR_TIM2RST_BIT 0 + +#define RCC_APB1RSTR_DACRST (1U << RCC_APB1RSTR_DACRST_BIT) +#define RCC_APB1RSTR_PWRRST (1U << RCC_APB1RSTR_PWRRST_BIT) +#define RCC_APB1RSTR_BKPRST (1U << RCC_APB1RSTR_BKPRST_BIT) +#define RCC_APB1RSTR_CANRST (1U << RCC_APB1RSTR_CANRST_BIT) +#define RCC_APB1RSTR_USBRST (1U << RCC_APB1RSTR_USBRST_BIT) +#define RCC_APB1RSTR_I2C2RST (1U << RCC_APB1RSTR_I2C2RST_BIT) +#define RCC_APB1RSTR_I2C1RST (1U << RCC_APB1RSTR_I2C1RST_BIT) +#define RCC_APB1RSTR_UART5RST (1U << RCC_APB1RSTR_UART5RST_BIT) +#define RCC_APB1RSTR_UART4RST (1U << RCC_APB1RSTR_UART4RST_BIT) +#define RCC_APB1RSTR_USART3RST (1U << RCC_APB1RSTR_USART3RST_BIT) +#define RCC_APB1RSTR_USART2RST (1U << RCC_APB1RSTR_USART2RST_BIT) +#define RCC_APB1RSTR_SPI3RST (1U << RCC_APB1RSTR_SPI3RST_BIT) +#define RCC_APB1RSTR_SPI2RST (1U << RCC_APB1RSTR_SPI2RST_BIT) +#define RCC_APB1RSTR_WWDRST (1U << RCC_APB1RSTR_WWDRST_BIT) +#define RCC_APB1RSTR_TIM14RST (1U << RCC_APB1RSTR_TIM14RST_BIT) +#define RCC_APB1RSTR_TIM13RST (1U << RCC_APB1RSTR_TIM13RST_BIT) +#define RCC_APB1RSTR_TIM12RST (1U << RCC_APB1RSTR_TIM12RST_BIT) +#define RCC_APB1RSTR_TIM7RST (1U << RCC_APB1RSTR_TIM7RST_BIT) +#define RCC_APB1RSTR_TIM6RST (1U << RCC_APB1RSTR_TIM6RST_BIT) +#define RCC_APB1RSTR_TIM5RST (1U << RCC_APB1RSTR_TIM5RST_BIT) +#define RCC_APB1RSTR_TIM4RST (1U << RCC_APB1RSTR_TIM4RST_BIT) +#define RCC_APB1RSTR_TIM3RST (1U << RCC_APB1RSTR_TIM3RST_BIT) +#define RCC_APB1RSTR_TIM2RST (1U << RCC_APB1RSTR_TIM2RST_BIT) + +/* AHB peripheral clock enable register */ + +#define RCC_AHBENR_SDIOEN_BIT 10 +#define RCC_AHBENR_FSMCEN_BIT 8 +#define RCC_AHBENR_CRCEN_BIT 7 +#define RCC_AHBENR_FLITFEN_BIT 4 +#define RCC_AHBENR_SRAMEN_BIT 2 +#define RCC_AHBENR_DMA2EN_BIT 1 +#define RCC_AHBENR_DMA1EN_BIT 0 + +#define RCC_AHBENR_SDIOEN (1U << RCC_AHBENR_SDIOEN_BIT) +#define RCC_AHBENR_FSMCEN (1U << RCC_AHBENR_FSMCEN_BIT) +#define RCC_AHBENR_CRCEN (1U << RCC_AHBENR_CRCEN_BIT) +#define RCC_AHBENR_FLITFEN (1U << RCC_AHBENR_FLITFEN_BIT) +#define RCC_AHBENR_SRAMEN (1U << RCC_AHBENR_SRAMEN_BIT) +#define RCC_AHBENR_DMA2EN (1U << RCC_AHBENR_DMA2EN_BIT) +#define RCC_AHBENR_DMA1EN (1U << RCC_AHBENR_DMA1EN_BIT) + +/* APB2 peripheral clock enable register */ + +#define RCC_APB2ENR_TIM11EN_BIT 21 +#define RCC_APB2ENR_TIM10EN_BIT 20 +#define RCC_APB2ENR_TIM9EN_BIT 19 +#define RCC_APB2ENR_ADC3EN_BIT 15 +#define RCC_APB2ENR_USART1EN_BIT 14 +#define RCC_APB2ENR_TIM8EN_BIT 13 +#define RCC_APB2ENR_SPI1EN_BIT 12 +#define RCC_APB2ENR_TIM1EN_BIT 11 +#define RCC_APB2ENR_ADC2EN_BIT 10 +#define RCC_APB2ENR_ADC1EN_BIT 9 +#define RCC_APB2ENR_IOPGEN_BIT 8 +#define RCC_APB2ENR_IOPFEN_BIT 7 +#define RCC_APB2ENR_IOPEEN_BIT 6 +#define RCC_APB2ENR_IOPDEN_BIT 5 +#define RCC_APB2ENR_IOPCEN_BIT 4 +#define RCC_APB2ENR_IOPBEN_BIT 3 +#define RCC_APB2ENR_IOPAEN_BIT 2 +#define RCC_APB2ENR_AFIOEN_BIT 0 + +#define RCC_APB2ENR_TIM11EN (1U << RCC_APB2ENR_TIM11EN_BIT) +#define RCC_APB2ENR_TIM10EN (1U << RCC_APB2ENR_TIM10EN_BIT) +#define RCC_APB2ENR_TIM9EN (1U << RCC_APB2ENR_TIM9EN_BIT) +#define RCC_APB2ENR_ADC3EN (1U << RCC_APB2ENR_ADC3EN_BIT) +#define RCC_APB2ENR_USART1EN (1U << RCC_APB2ENR_USART1EN_BIT) +#define RCC_APB2ENR_TIM8EN (1U << RCC_APB2ENR_TIM8EN_BIT) +#define RCC_APB2ENR_SPI1EN (1U << RCC_APB2ENR_SPI1EN_BIT) +#define RCC_APB2ENR_TIM1EN (1U << RCC_APB2ENR_TIM1EN_BIT) +#define RCC_APB2ENR_ADC2EN (1U << RCC_APB2ENR_ADC2EN_BIT) +#define RCC_APB2ENR_ADC1EN (1U << RCC_APB2ENR_ADC1EN_BIT) +#define RCC_APB2ENR_IOPGEN (1U << RCC_APB2ENR_IOPGEN_BIT) +#define RCC_APB2ENR_IOPFEN (1U << RCC_APB2ENR_IOPFEN_BIT) +#define RCC_APB2ENR_IOPEEN (1U << RCC_APB2ENR_IOPEEN_BIT) +#define RCC_APB2ENR_IOPDEN (1U << RCC_APB2ENR_IOPDEN_BIT) +#define RCC_APB2ENR_IOPCEN (1U << RCC_APB2ENR_IOPCEN_BIT) +#define RCC_APB2ENR_IOPBEN (1U << RCC_APB2ENR_IOPBEN_BIT) +#define RCC_APB2ENR_IOPAEN (1U << RCC_APB2ENR_IOPAEN_BIT) +#define RCC_APB2ENR_AFIOEN (1U << RCC_APB2ENR_AFIOEN_BIT) + +/* APB1 peripheral clock enable register */ + +#define RCC_APB1ENR_DACEN_BIT 29 +#define RCC_APB1ENR_PWREN_BIT 28 +#define RCC_APB1ENR_BKPEN_BIT 27 +#define RCC_APB1ENR_CANEN_BIT 25 +#define RCC_APB1ENR_USBEN_BIT 23 +#define RCC_APB1ENR_I2C2EN_BIT 22 +#define RCC_APB1ENR_I2C1EN_BIT 21 +#define RCC_APB1ENR_UART5EN_BIT 20 +#define RCC_APB1ENR_UART4EN_BIT 19 +#define RCC_APB1ENR_USART3EN_BIT 18 +#define RCC_APB1ENR_USART2EN_BIT 17 +#define RCC_APB1ENR_SPI3EN_BIT 15 +#define RCC_APB1ENR_SPI2EN_BIT 14 +#define RCC_APB1ENR_WWDEN_BIT 11 +#define RCC_APB1ENR_TIM14EN_BIT 8 +#define RCC_APB1ENR_TIM13EN_BIT 7 +#define RCC_APB1ENR_TIM12EN_BIT 6 +#define RCC_APB1ENR_TIM7EN_BIT 5 +#define RCC_APB1ENR_TIM6EN_BIT 4 +#define RCC_APB1ENR_TIM5EN_BIT 3 +#define RCC_APB1ENR_TIM4EN_BIT 2 +#define RCC_APB1ENR_TIM3EN_BIT 1 +#define RCC_APB1ENR_TIM2EN_BIT 0 + +#define RCC_APB1ENR_DACEN (1U << RCC_APB1ENR_DACEN_BIT) +#define RCC_APB1ENR_PWREN (1U << RCC_APB1ENR_PWREN_BIT) +#define RCC_APB1ENR_BKPEN (1U << RCC_APB1ENR_BKPEN_BIT) +#define RCC_APB1ENR_CANEN (1U << RCC_APB1ENR_CANEN_BIT) +#define RCC_APB1ENR_USBEN (1U << RCC_APB1ENR_USBEN_BIT) +#define RCC_APB1ENR_I2C2EN (1U << RCC_APB1ENR_I2C2EN_BIT) +#define RCC_APB1ENR_I2C1EN (1U << RCC_APB1ENR_I2C1EN_BIT) +#define RCC_APB1ENR_UART5EN (1U << RCC_APB1ENR_UART5EN_BIT) +#define RCC_APB1ENR_UART4EN (1U << RCC_APB1ENR_UART4EN_BIT) +#define RCC_APB1ENR_USART3EN (1U << RCC_APB1ENR_USART3EN_BIT) +#define RCC_APB1ENR_USART2EN (1U << RCC_APB1ENR_USART2EN_BIT) +#define RCC_APB1ENR_SPI3EN (1U << RCC_APB1ENR_SPI3EN_BIT) +#define RCC_APB1ENR_SPI2EN (1U << RCC_APB1ENR_SPI2EN_BIT) +#define RCC_APB1ENR_WWDEN (1U << RCC_APB1ENR_WWDEN_BIT) +#define RCC_APB1ENR_TIM14EN (1U << RCC_APB1ENR_TIM14EN_BIT) +#define RCC_APB1ENR_TIM13EN (1U << RCC_APB1ENR_TIM13EN_BIT) +#define RCC_APB1ENR_TIM12EN (1U << RCC_APB1ENR_TIM12EN_BIT) +#define RCC_APB1ENR_TIM7EN (1U << RCC_APB1ENR_TIM7EN_BIT) +#define RCC_APB1ENR_TIM6EN (1U << RCC_APB1ENR_TIM6EN_BIT) +#define RCC_APB1ENR_TIM5EN (1U << RCC_APB1ENR_TIM5EN_BIT) +#define RCC_APB1ENR_TIM4EN (1U << RCC_APB1ENR_TIM4EN_BIT) +#define RCC_APB1ENR_TIM3EN (1U << RCC_APB1ENR_TIM3EN_BIT) +#define RCC_APB1ENR_TIM2EN (1U << RCC_APB1ENR_TIM2EN_BIT) + +/* Backup domain control register */ + +#define RCC_BDCR_BDRST_BIT 16 +#define RCC_BDCR_RTCEN_BIT 15 +#define RCC_BDCR_LSEBYP_BIT 2 +#define RCC_BDCR_LSERDY_BIT 1 +#define RCC_BDCR_LSEON_BIT 0 + +#define RCC_BDCR_BDRST (1U << RCC_BDCR_BDRST_BIT) +#define RCC_BDCR_RTCEN (1U << RCC_BDCR_RTC_BIT) +#define RCC_BDCR_RTCSEL (0x3 << 8) +#define RCC_BDCR_RTCSEL_NONE (0x0 << 8) +#define RCC_BDCR_RTCSEL_LSE (0x1 << 8) +#define RCC_BDCR_RTCSEL_LSI (0x2 << 8) // added to support RTClock +#define RCC_BDCR_RTCSEL_HSE (0x3 << 8) +#define RCC_BDCR_LSEBYP (1U << RCC_BDCR_LSEBYP_BIT) +#define RCC_BDCR_LSERDY (1U << RCC_BDCR_LSERDY_BIT) +#define RCC_BDCR_LSEON (1U << RCC_BDCR_LSEON_BIT) + +/* Control/status register */ + +#define RCC_CSR_LPWRRSTF_BIT 31 +#define RCC_CSR_WWDGRSTF_BIT 30 +#define RCC_CSR_IWDGRSTF_BIT 29 +#define RCC_CSR_SFTRSTF_BIT 28 +#define RCC_CSR_PORRSTF_BIT 27 +#define RCC_CSR_PINRSTF_BIT 26 +#define RCC_CSR_RMVF_BIT 24 +#define RCC_CSR_LSIRDY_BIT 1 +#define RCC_CSR_LSION_BIT 0 + +#define RCC_CSR_LPWRRSTF (1U << RCC_CSR_LPWRRSTF_BIT) +#define RCC_CSR_WWDGRSTF (1U << RCC_CSR_WWDGRSTF_BIT) +#define RCC_CSR_IWDGRSTF (1U << RCC_CSR_IWDGRSTF_BIT) +#define RCC_CSR_SFTRSTF (1U << RCC_CSR_SFTRSTF_BIT) +#define RCC_CSR_PORRSTF (1U << RCC_CSR_PORRSTF_BIT) +#define RCC_CSR_PINRSTF (1U << RCC_CSR_PINRSTF_BIT) +#define RCC_CSR_RMVF (1U << RCC_CSR_RMVF_BIT) +#define RCC_CSR_LSIRDY (1U << RCC_CSR_LSIRDY_BIT) +#define RCC_CSR_LSION (1U << RCC_CSR_LSION_BIT) + +/* + * libmaple-mandated enumeration types. + */ + +/** + * @brief STM32F1 rcc_clk_id. + */ +typedef enum rcc_clk_id { + RCC_ADC1, + RCC_ADC2, + RCC_ADC3, + RCC_AFIO, + RCC_BKP, + RCC_CRC, + RCC_DAC, + RCC_DMA1, + RCC_DMA2, + RCC_FLITF, + RCC_FSMC, + RCC_GPIOA, + RCC_GPIOB, + RCC_GPIOC, + RCC_GPIOD, + RCC_GPIOE, + RCC_GPIOF, + RCC_GPIOG, + RCC_I2C1, + RCC_I2C2, + RCC_PWR, + RCC_SDIO, + RCC_SPI1, + RCC_SPI2, + RCC_SPI3, + RCC_SRAM, + RCC_TIMER1, + RCC_TIMER2, + RCC_TIMER3, + RCC_TIMER4, + RCC_TIMER5, + RCC_TIMER6, + RCC_TIMER7, + RCC_TIMER8, + RCC_TIMER9, + RCC_TIMER10, + RCC_TIMER11, + RCC_TIMER12, + RCC_TIMER13, + RCC_TIMER14, + RCC_USART1, + RCC_USART2, + RCC_USART3, + RCC_UART4, + RCC_UART5, + RCC_USB, +} rcc_clk_id; + +/** + * @brief STM32F1 PLL clock sources. + * @see rcc_configure_pll() + */ +typedef enum rcc_pllsrc { + RCC_PLLSRC_HSE = (0x1 << 16), + RCC_PLLSRC_HSI_DIV_2 = (0x0 << 16) +} rcc_pllsrc; + +/** + * @brief STM32F1 clock domains. + * @see rcc_dev_clk() + */ +typedef enum rcc_clk_domain { + RCC_APB1, + RCC_APB2, + RCC_AHB +} rcc_clk_domain; + +/** + * @brief STM32F1 Prescaler identifiers + * @see rcc_set_prescaler() + */ +typedef enum rcc_prescaler { + RCC_PRESCALER_AHB, + RCC_PRESCALER_APB1, + RCC_PRESCALER_APB2, + RCC_PRESCALER_USB, + RCC_PRESCALER_ADC +} rcc_prescaler; + +/** + * @brief STM32F1 ADC prescaler dividers + * @see rcc_set_prescaler() + */ +typedef enum rcc_adc_divider { + RCC_ADCPRE_PCLK_DIV_2 = 0x0 << 14, + RCC_ADCPRE_PCLK_DIV_4 = 0x1 << 14, + RCC_ADCPRE_PCLK_DIV_6 = 0x2 << 14, + RCC_ADCPRE_PCLK_DIV_8 = 0x3 << 14, +} rcc_adc_divider; + +/** + * @brief STM32F1 APB1 prescaler dividers + * @see rcc_set_prescaler() + */ +typedef enum rcc_apb1_divider { + RCC_APB1_HCLK_DIV_1 = 0x0 << 8, + RCC_APB1_HCLK_DIV_2 = 0x4 << 8, + RCC_APB1_HCLK_DIV_4 = 0x5 << 8, + RCC_APB1_HCLK_DIV_8 = 0x6 << 8, + RCC_APB1_HCLK_DIV_16 = 0x7 << 8, +} rcc_apb1_divider; + +/** + * @brief STM32F1 APB2 prescaler dividers + * @see rcc_set_prescaler() + */ +typedef enum rcc_apb2_divider { + RCC_APB2_HCLK_DIV_1 = 0x0 << 11, + RCC_APB2_HCLK_DIV_2 = 0x4 << 11, + RCC_APB2_HCLK_DIV_4 = 0x5 << 11, + RCC_APB2_HCLK_DIV_8 = 0x6 << 11, + RCC_APB2_HCLK_DIV_16 = 0x7 << 11, +} rcc_apb2_divider; + +/** + * @brief STM32F1 AHB prescaler dividers + * @see rcc_set_prescaler() + */ +typedef enum rcc_ahb_divider { + RCC_AHB_SYSCLK_DIV_1 = 0x0 << 4, + RCC_AHB_SYSCLK_DIV_2 = 0x8 << 4, + RCC_AHB_SYSCLK_DIV_4 = 0x9 << 4, + RCC_AHB_SYSCLK_DIV_8 = 0xA << 4, + RCC_AHB_SYSCLK_DIV_16 = 0xB << 4, + RCC_AHB_SYSCLK_DIV_32 = 0xC << 4, + RCC_AHB_SYSCLK_DIV_64 = 0xD << 4, + RCC_AHB_SYSCLK_DIV_128 = 0xD << 4, + RCC_AHB_SYSCLK_DIV_256 = 0xE << 4, + RCC_AHB_SYSCLK_DIV_512 = 0xF << 4, +} rcc_ahb_divider; + +/** + * @brief STM32F1 USB prescaler dividers + * @see rcc_set_prescaler() + */ + /* + Set and reset by software to control the USB clock prescaler value. The USB clock +must be 48MHz. These bits can’t be reset if the USB clock is enabled. +00: (CK_PLL / 1.5) selected +01: CK_PLL selected + */ + +typedef enum rcc_usb_divider { + RCC_USB_SYSCLK_DIV_1 = 0x1 << 22, + RCC_USB_SYSCLK_DIV_1_5 = 0x0 << 22, + RCC_USB_SYSCLK_DIV_2 = 0x3 << 22, + RCC_USB_SYSCLK_DIV_2_5 = 0x2 << 22, +} rcc_usb_divider; + + +/** + * @brief Start the low speed internal oscillator + */ +static inline void rcc_start_lsi(void) { + *bb_perip(&RCC_BASE->CSR, RCC_CSR_LSION_BIT) = 1; + while (*bb_perip(&RCC_BASE->CSR, RCC_CSR_LSIRDY_BIT) == 0); +} + +/** + * @brief STM32F1 clock sources. + */ +typedef enum rcc_clk { + RCC_CLK_PLL = (uint16)((offsetof(struct rcc_reg_map, CR) << 8) | + RCC_CR_PLLON_BIT), /**< Main PLL, clocked by + HSI or HSE. */ + RCC_CLK_HSE = (uint16)((offsetof(struct rcc_reg_map, CR) << 8) | + RCC_CR_HSEON_BIT), /**< High speed external. */ + RCC_CLK_HSI = (uint16)((offsetof(struct rcc_reg_map, CR) << 8) | + RCC_CR_HSION_BIT), /**< High speed internal. */ + RCC_CLK_LSE = (uint16)((offsetof(struct rcc_reg_map, BDCR) << 8) | + RCC_BDCR_LSEON_BIT), /**< Low-speed external + * (32.768 KHz). */ + RCC_CLK_LSI = (uint16)((offsetof(struct rcc_reg_map, CSR) << 8) | + RCC_CSR_LSION_BIT), /**< Low-speed internal + * (approximately 32 KHz). */ +} rcc_clk; + +/** + * @brief STM32F1 PLL multipliers. + */ +typedef enum rcc_pll_multiplier { + RCC_PLLMUL_2 = (0x0 << 18), + RCC_PLLMUL_3 = (0x1 << 18), + RCC_PLLMUL_4 = (0x2 << 18), + RCC_PLLMUL_5 = (0x3 << 18), + RCC_PLLMUL_6 = (0x4 << 18), + RCC_PLLMUL_7 = (0x5 << 18), + RCC_PLLMUL_8 = (0x6 << 18), + RCC_PLLMUL_9 = (0x7 << 18), + RCC_PLLMUL_10 = (0x8 << 18), + RCC_PLLMUL_11 = (0x9 << 18), + RCC_PLLMUL_12 = (0xA << 18), + RCC_PLLMUL_13 = (0xB << 18), + RCC_PLLMUL_14 = (0xC << 18), + RCC_PLLMUL_15 = (0xD << 18), + RCC_PLLMUL_16 = (0xE << 18), +} rcc_pll_multiplier; + +/* FIXME [0.0.13] Just have data point to an rcc_pll_multiplier! */ +/** + * @brief Start the low speed external oscillatior + */ +static inline void rcc_start_lse(void) { + bb_peri_set_bit(&RCC_BASE->BDCR, RCC_BDCR_LSEBYP_BIT, 0); + bb_peri_set_bit(&RCC_BASE->BDCR, RCC_BDCR_LSEON_BIT, 1); + while (bb_peri_get_bit(&RCC_BASE->BDCR, RCC_BDCR_LSERDY_BIT ) == 0); +} + +/** + * @brief STM32F1 PLL configuration values. + * Point to one of these with the "data" field in a struct rcc_pll_cfg. + * @see struct rcc_pll_cfg. + */ +typedef struct stm32f1_rcc_pll_data { + rcc_pll_multiplier pll_mul; /**< PLL multiplication factor. */ +} stm32f1_rcc_pll_data; + +/* + * Deprecated bits. + */ +static inline void rcc_start_hse(void) { // Added to support RTClock +// *bb_perip(&RCC_BASE->CR, RCC_CR_HSEON_BIT) = 1; + while (bb_peri_get_bit(&RCC_BASE->CR, RCC_CR_HSERDY_BIT) == 0); +} + +/** + * @brief Deprecated; STM32F1 only. + * + * Initialize the clock control system. Initializes the system + * clock source to use the PLL driven by an external oscillator. + * + * @param sysclk_src system clock source, must be PLL + * @param pll_src pll clock source, must be HSE + * @param pll_mul pll multiplier + */ +__deprecated +void rcc_clk_init(rcc_sysclk_src sysclk_src, + rcc_pllsrc pll_src, + rcc_pll_multiplier pll_mul); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/spi.h b/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/spi.h new file mode 100644 index 0000000..ec4821c --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/spi.h @@ -0,0 +1,99 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011, 2012 LeafLabs, LLC. + * Copyright (c) 2010 Perry Hung. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/include/series/spi.h + * @author Marti Bolivar + * @brief STM32F1 SPI/I2S series header. + */ + +#ifndef _LIBMAPLE_STM32F1_SPI_H_ +#define _LIBMAPLE_STM32F1_SPI_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Register map base pointers + */ + +struct spi_reg_map; + +#define SPI1_BASE ((struct spi_reg_map*)0x40013000) +#define SPI2_BASE ((struct spi_reg_map*)0x40003800) +#define SPI3_BASE ((struct spi_reg_map*)0x40003C00) + +/* + * Device pointers + */ + +struct spi_dev; + +extern struct spi_dev *SPI1; +extern struct spi_dev *SPI2; +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) +extern struct spi_dev *SPI3; +#endif + +/* + * Routines + */ + +/* spi_gpio_cfg(): Backwards compatibility shim to spi_config_gpios() */ +struct gpio_dev; +extern void spi_config_gpios(struct spi_dev*, uint8, + struct gpio_dev*, uint8, + struct gpio_dev*, uint8, uint8, uint8); +/** + * @brief Deprecated. Use spi_config_gpios() instead. + * @see spi_config_gpios() + */ +static inline __always_inline void spi_gpio_cfg(uint8 as_master, + struct gpio_dev *nss_dev, + uint8 nss_bit, + struct gpio_dev *comm_dev, + uint8 sck_bit, + uint8 miso_bit, + uint8 mosi_bit) { + /* We switched style globally to foo_config_gpios() and always + * taking a foo_dev* argument (that last bit is the important + * part) after this function was written. + * + * However, spi_config_gpios() just ignores the spi_dev* on F1, so + * we can still keep this around for older code. */ + spi_config_gpios(NULL, as_master, nss_dev, nss_bit, + comm_dev, sck_bit, miso_bit, mosi_bit); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/stm32.h b/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/stm32.h new file mode 100644 index 0000000..9386dc3 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/stm32.h @@ -0,0 +1,279 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010, 2011 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/include/series/stm32.h + * @brief STM32F1 chip- and series-specific definitions. + */ + /* + * Modified by Roger Clark. 20141111. Wrapped #define STM32_MEDIUM_DENSITY in #ifndef + * to prevent redefinition warnings as SSTM32_MEDIUM_DENSITY is defined in boards.txt as a compilor define. + */ + +#ifndef _LIBMAPLE_STM32F1_H_ +#define _LIBMAPLE_STM32F1_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define STM32_MCU_SERIES STM32_SERIES_F1 + +/* The STM32F1 series is subdivided into "lines". libmaple currently + * officially supports STM32F103 performance line MCUs (see the + * MCU-specific value section below). + * + * You can use these F1 line defines if porting libmaple to support + * MCUs on other lines. */ +/** STM32F1 value line (STM32F100 MCUs). */ +#define STM32_F1_LINE_VALUE 0 +/** STM32F1 access line (STM32F101 MCUs). */ +#define STM32_F1_LINE_ACCESS 1 +/** STM32F1 USB access line (STM32F102 MCUs). */ +#define STM32_F1_LINE_USB_ACCESS 2 +/** STM32F1 performance line (STM32F103 MCUs). */ +#define STM32_F1_LINE_PERFORMANCE 3 +/** STM32F1 connectivity line (STM32F105/F107 MCUs). */ +#define STM32_F1_LINE_CONNECTIVITY 5 + +/* + * MCU-specific values. + * + * You can use this section to override any of the below settings on a + * per-MCU basis. For example, if your MCU has different STM32_PCLK1 + * or STM32_PCLK2 values, you can set them here and the values for + * STM32F103 microcontrollers set below won't take effect. + */ + +#if defined(MCU_STM32F103T8) +# define STM32_NR_GPIO_PORTS 2 +# define STM32_SRAM_END ((void*)0x20005000) +# define NR_GPIO_PORTS STM32_NR_GPIO_PORTS +# define STM32_F1_LINE STM32_F1_LINE_PERFORMANCE +# define STM32_MEDIUM_DENSITY + +#elif defined(MCU_STM32F103TB) +# define STM32_NR_GPIO_PORTS 2 +# define STM32_SRAM_END ((void*)0x20005000) +# define NR_GPIO_PORTS STM32_NR_GPIO_PORTS +# define STM32_F1_LINE STM32_F1_LINE_PERFORMANCE +# define STM32_MEDIUM_DENSITY + +#elif defined(MCU_STM32F103C8) +# define STM32_NR_GPIO_PORTS 3 +# define STM32_SRAM_END ((void*)0x20005000) +# define NR_GPIO_PORTS STM32_NR_GPIO_PORTS +# define STM32_F1_LINE STM32_F1_LINE_PERFORMANCE +# define STM32_MEDIUM_DENSITY + +#elif defined(MCU_STM32F103CB) +# define STM32_F1_LINE STM32_F1_LINE_PERFORMANCE + /* This STM32_NR_GPIO_PORTS is not true, but only pins 0 and + * exist, and they're used for OSC (e.g. on LeafLabs' Maple Mini), + * so we'll live with this for now. */ +# define STM32_NR_GPIO_PORTS 3 +# define STM32_SRAM_END ((void*)0x20005000) +# define STM32_MEDIUM_DENSITY + +#elif defined(MCU_STM32F103R8) +# define STM32_F1_LINE STM32_F1_LINE_PERFORMANCE +# define STM32_NR_GPIO_PORTS 4 +# define STM32_SRAM_END ((void*)0x20005000) +# define STM32_MEDIUM_DENSITY + +#elif defined(MCU_STM32F103RB) +# define STM32_F1_LINE STM32_F1_LINE_PERFORMANCE +# define STM32_NR_GPIO_PORTS 4 +# define STM32_SRAM_END ((void*)0x20005000) +# define STM32_MEDIUM_DENSITY + +#elif defined(MCU_STM32F103RC) +# define STM32_F1_LINE STM32_F1_LINE_PERFORMANCE +# define STM32_NR_GPIO_PORTS 4 +# define STM32_SRAM_END ((void*)0x2000C000) +# define STM32_HIGH_DENSITY + +#elif defined(MCU_STM32F103RD) || defined(MCU_STM32F103RE) +# define STM32_F1_LINE STM32_F1_LINE_PERFORMANCE +# define STM32_NR_GPIO_PORTS 4 +# define STM32_SRAM_END ((void*)0x20010000) +# define STM32_HIGH_DENSITY + +#elif defined(MCU_STM32F103V8) +# define STM32_F1_LINE STM32_F1_LINE_PERFORMANCE +# define STM32_NR_GPIO_PORTS 5 +# define STM32_SRAM_END ((void*)0x20005000) +# define STM32_MEDIUM_DENSITY + +#elif defined(MCU_STM32F103VB) +# define STM32_F1_LINE STM32_F1_LINE_PERFORMANCE +# define STM32_NR_GPIO_PORTS 5 +# define STM32_SRAM_END ((void*)0x20005000) +# define STM32_MEDIUM_DENSITY + +#elif defined(MCU_STM32F103VC) +# define STM32_F1_LINE STM32_F1_LINE_PERFORMANCE +# define STM32_NR_GPIO_PORTS 5 +# define STM32_SRAM_END ((void*)0x2000C000) +# define STM32_HIGH_DENSITY + +#elif defined(MCU_STM32F103VD) || defined(MCU_STM32F103VE) +# define STM32_F1_LINE STM32_F1_LINE_PERFORMANCE +# define STM32_NR_GPIO_PORTS 5 +# define STM32_SRAM_END ((void*)0x20010000) +# define STM32_HIGH_DENSITY + +#elif defined(MCU_STM32F103ZC) +# define STM32_F1_LINE STM32_F1_LINE_PERFORMANCE +# define STM32_NR_GPIO_PORTS 7 +# define STM32_SRAM_END ((void*)0x2000C000) +# define STM32_HIGH_DENSITY + +#elif defined(MCU_STM32F103ZD) || defined(MCU_STM32F103ZE) +# define STM32_F1_LINE STM32_F1_LINE_PERFORMANCE +# define STM32_NR_GPIO_PORTS 7 +# define STM32_SRAM_END ((void*)0x20010000) +# define STM32_HIGH_DENSITY + +#elif defined(MCU_STM32F100RB) +# define STM32_F1_LINE STM32_F1_LINE_VALUE +# define STM32_NR_GPIO_PORTS 4 +# define STM32_TIMER_MASK 0x380DE /* Timers: 1-4, 6, 7, 15-17. */ +# define STM32_SRAM_END ((void*)0x20002000) +# define STM32_MEDIUM_DENSITY + +#else +#warning "Unsupported or unspecified STM32F1 MCU." +#endif + +/* + * Derived values. + */ + +#if STM32_F1_LINE == STM32_F1_LINE_PERFORMANCE + /* All supported performance line MCUs have a USB peripheral */ +# define STM32_HAVE_USB 1 + +# ifdef STM32_MEDIUM_DENSITY +# define STM32_NR_INTERRUPTS 43 +# define STM32_TIMER_MASK 0x1E /* TIMER1--TIMER4 */ +# define STM32_HAVE_FSMC 0 +# define STM32_HAVE_DAC 0 +# elif defined(STM32_HIGH_DENSITY) +# define STM32_NR_INTERRUPTS 60 +# define STM32_TIMER_MASK 0x1FE /* TIMER1--TIMER8 */ +# define STM32_HAVE_FSMC 1 +# define STM32_HAVE_DAC 1 +# elif defined(STM32_XL_DENSITY) +# define STM32_NR_INTERRUPTS 60 +# define STM32_TIMER_MASK 0x7FFE /* TIMER1--TIMER14 */ +# define STM32_HAVE_FSMC 1 +# define STM32_HAVE_DAC 1 +# endif + +#elif STM32_F1_LINE == STM32_F1_LINE_VALUE + /* Value line MCUs don't have USB peripherals. */ +# define STM32_HAVE_USB 0 + +# ifdef STM32_MEDIUM_DENSITY +# define STM32_NR_INTERRUPTS 56 +# define STM32_HAVE_FSMC 0 +# define STM32_HAVE_DAC 1 +# elif defined(STM32_HIGH_DENSITY) + /* 61 interrupts here counts the possibility for a remapped + * DMA2 channel 5 IRQ occurring at NVIC index 60. */ +# define STM32_NR_INTERRUPTS 61 +# define STM32_HAVE_FSMC 1 +# define STM32_HAVE_DAC 1 +# endif + +#endif + +/* + * Clock configuration. + * + * You can patch these for your line, MCU, clock configuration, + * etc. here or by setting cflags when compiling libmaple. + */ + +#if STM32_F1_LINE == STM32_F1_LINE_PERFORMANCE +# ifndef STM32_PCLK1 +# define STM32_PCLK1 F_CPU/2 +# endif +# ifndef STM32_PCLK2 +# define STM32_PCLK2 F_CPU +# endif +# ifndef STM32_DELAY_US_MULT +# define STM32_DELAY_US_MULT (F_CPU / 6000000L) +# endif +#elif STM32_F1_LINE == STM32_F1_LINE_VALUE /* TODO */ +# ifndef STM32_PCLK1 +# define STM32_PCLK1 12000000U +# endif +# ifndef STM32_PCLK2 +# define STM32_PCLK2 24000000U +# endif +# ifndef STM32_DELAY_US_MULT +# define STM32_DELAY_US_MULT 8 /* FIXME: value is incorrect. */ +# endif +#elif STM32_F1_LINE == STM32_F1_LINE_ACCESS /* TODO */ +#elif STM32_F1_LINE == STM32_F1_LINE_USB_ACCESS /* TODO */ +#elif STM32_F1_LINE == STM32_F1_LINE_CONNECTIVITY /* TODO */ +#endif + +/* + * Sanity checks. + * + * Make sure we have the F1-specific defines we need. + * will check that we've defined everything it needs. + */ + +#if !defined(STM32_F1_LINE) +#error "Bad STM32F1 configuration. Check STM32F1 header." +#endif + +/* + * Doxygen + */ + +#ifdef __DOXYGEN__ + +/** + * @brief STM32 line value for the STM32F1 MCU being targeted. + * + * At time of writing, allowed values are: STM32_F1_LINE_PERFORMANCE, + * STM32_F1_LINE_VALUE. This set of values may expand as libmaple adds + * support for more STM32F1 lines. + */ +#define STM32_F1_LINE + +#endif /* __DOXYGEN__ */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/timer.h b/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/timer.h new file mode 100644 index 0000000..8c1f8f4 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/timer.h @@ -0,0 +1,128 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/include/series/timer.h + * @author Marti Bolivar + * @brief STM32F1 timer support. + */ + +#ifndef _LIBMAPLE_STM32F1_TIMER_H_ +#define _LIBMAPLE_STM32F1_TIMER_H_ + +#include + +/* + * Register maps and base pointers + */ + +/** STM32F1 general purpose timer register map type */ +typedef struct timer_gen_reg_map { + __io uint32 CR1; /**< Control register 1 */ + __io uint32 CR2; /**< Control register 2 */ + __io uint32 SMCR; /**< Slave mode control register */ + __io uint32 DIER; /**< DMA/Interrupt enable register */ + __io uint32 SR; /**< Status register */ + __io uint32 EGR; /**< Event generation register */ + __io uint32 CCMR1; /**< Capture/compare mode register 1 */ + __io uint32 CCMR2; /**< Capture/compare mode register 2 */ + __io uint32 CCER; /**< Capture/compare enable register */ + __io uint32 CNT; /**< Counter */ + __io uint32 PSC; /**< Prescaler */ + __io uint32 ARR; /**< Auto-reload register */ + const uint32 RESERVED1; /**< Reserved */ + __io uint32 CCR1; /**< Capture/compare register 1 */ + __io uint32 CCR2; /**< Capture/compare register 2 */ + __io uint32 CCR3; /**< Capture/compare register 3 */ + __io uint32 CCR4; /**< Capture/compare register 4 */ + const uint32 RESERVED2; /**< Reserved */ + __io uint32 DCR; /**< DMA control register */ + __io uint32 DMAR; /**< DMA address for full transfer */ +} timer_gen_reg_map; + +struct timer_adv_reg_map; +struct timer_bas_reg_map; + +/** Timer 1 register map base pointer */ +#define TIMER1_BASE ((struct timer_adv_reg_map*)0x40012C00) +/** Timer 2 register map base pointer */ +#define TIMER2_BASE ((struct timer_gen_reg_map*)0x40000000) +/** Timer 3 register map base pointer */ +#define TIMER3_BASE ((struct timer_gen_reg_map*)0x40000400) +/** Timer 4 register map base pointer */ +#define TIMER4_BASE ((struct timer_gen_reg_map*)0x40000800) +/** Timer 5 register map base pointer */ +#define TIMER5_BASE ((struct timer_gen_reg_map*)0x40000C00) +/** Timer 6 register map base pointer */ +#define TIMER6_BASE ((struct timer_bas_reg_map*)0x40001000) +/** Timer 7 register map base pointer */ +#define TIMER7_BASE ((struct timer_bas_reg_map*)0x40001400) +/** Timer 8 register map base pointer */ +#define TIMER8_BASE ((struct timer_adv_reg_map*)0x40013400) +/** Timer 9 register map base pointer */ +#define TIMER9_BASE ((struct timer_gen_reg_map*)0x40014C00) +/** Timer 10 register map base pointer */ +#define TIMER10_BASE ((struct timer_gen_reg_map*)0x40015000) +/** Timer 11 register map base pointer */ +#define TIMER11_BASE ((struct timer_gen_reg_map*)0x40015400) +/** Timer 12 register map base pointer */ +#define TIMER12_BASE ((struct timer_gen_reg_map*)0x40001800) +/** Timer 13 register map base pointer */ +#define TIMER13_BASE ((struct timer_gen_reg_map*)0x40001C00) +/** Timer 14 register map base pointer */ +#define TIMER14_BASE ((struct timer_gen_reg_map*)0x40002000) + +/* + * Device pointers + * + * We only declare device pointers to timers which actually exist on + * the target MCU. This helps when porting programs to STM32F1 (or + * within F1 to a lower density MCU), as attempts to use nonexistent + * timers cause build errors instead of undefined behavior. + */ + +struct timer_dev; + +extern struct timer_dev *const TIMER1; +extern struct timer_dev *const TIMER2; +extern struct timer_dev *const TIMER3; +extern struct timer_dev *const TIMER4; +#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) +extern struct timer_dev *const TIMER5; +extern struct timer_dev *const TIMER6; +extern struct timer_dev *const TIMER7; +extern struct timer_dev *const TIMER8; +#endif +#ifdef STM32_XL_DENSITY +extern struct timer_dev *const TIMER9; +extern struct timer_dev *const TIMER10; +extern struct timer_dev *const TIMER11; +extern struct timer_dev *const TIMER12; +extern struct timer_dev *const TIMER13; +extern struct timer_dev *const TIMER14; +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/usart.h b/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/usart.h new file mode 100644 index 0000000..d12a3e2 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/stm32f1/include/series/usart.h @@ -0,0 +1,76 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/include/series/usart.h + * @author Marti Bolivar + * @brief STM32F1 USART support. + */ + +#ifndef _LIBMAPLE_STM32F1_USART_H_ +#define _LIBMAPLE_STM32F1_USART_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +/* + * Register map base pointers + */ + +struct usart_reg_map; + +/** USART1 register map base pointer */ +#define USART1_BASE ((struct usart_reg_map*)0x40013800) +/** USART2 register map base pointer */ +#define USART2_BASE ((struct usart_reg_map*)0x40004400) +/** USART3 register map base pointer */ +#define USART3_BASE ((struct usart_reg_map*)0x40004800) +#ifdef STM32_HIGH_DENSITY +/** UART4 register map base pointer */ +#define UART4_BASE ((struct usart_reg_map*)0x40004C00) +/** UART5 register map base pointer */ +#define UART5_BASE ((struct usart_reg_map*)0x40005000) +#endif + +/* + * Devices + */ + +struct usart_dev; +extern struct usart_dev *USART1; +extern struct usart_dev *USART2; +extern struct usart_dev *USART3; +#ifdef STM32_HIGH_DENSITY +extern struct usart_dev *UART4; +extern struct usart_dev *UART5; +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/stm32f1/rules.mk b/BootLoaders/Boards/stm32/system/libmaple/stm32f1/rules.mk new file mode 100644 index 0000000..f1cc23e --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/stm32f1/rules.mk @@ -0,0 +1,45 @@ +# Standard things +sp := $(sp).x +dirstack_$(sp) := $(d) +d := $(dir) +BUILDDIRS += $(BUILD_PATH)/$(d) + +# Local flags +CFLAGS_$(d) = -I$(d) $(LIBMAPLE_PRIVATE_INCLUDES) $(LIBMAPLE_INCLUDES) -Wall -Werror +ASFLAGS_$(d) = -I$(d) $(LIBMAPLE_PRIVATE_INCLUDES) $(LIBMAPLE_INCLUDES) -Wall -Werror + +# Extra BUILDDIRS +BUILDDIRS += $(BUILD_PATH)/$(d)/$(MCU_F1_LINE) + +# Local rules and targets +sSRCS_$(d) := $(MCU_F1_LINE)/isrs.S +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) += i2c.c +cSRCS_$(d) += rcc.c +cSRCS_$(d) += spi.c +cSRCS_$(d) += timer.c +cSRCS_$(d) += usart.c + +sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%) +cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%) + +OBJS_$(d) := $(sFILES_$(d):%.S=$(BUILD_PATH)/%.o) \ + $(cFILES_$(d):%.c=$(BUILD_PATH)/%.o) +DEPS_$(d) := $(OBJS_$(d):%.o=%.d) + +$(OBJS_$(d)): TGT_ASFLAGS := $(ASFLAGS_$(d)) +$(OBJS_$(d)): TGT_CFLAGS := $(CFLAGS_$(d)) + +TGT_BIN += $(OBJS_$(d)) + +# Standard things +-include $(DEPS_$(d)) +d := $(dirstack_$(sp)) +sp := $(basename $(sp)) diff --git a/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/adc.h b/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/adc.h new file mode 100644 index 0000000..175fe11 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/adc.h @@ -0,0 +1,335 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f2/include/series/adc.h + * @author Marti Bolivar , + * @brief STM32F2 ADC support. + */ + +#ifndef _LIBMAPLE_STM32F2_ADC_H_ +#define _LIBMAPLE_STM32F2_ADC_H_ + +#include + +/* + * Devices + */ + +extern const struct adc_dev *ADC1; +extern const struct adc_dev *ADC2; +extern const struct adc_dev *ADC3; + +/* + * Common register map + */ + +/** ADC common register map type */ +typedef struct adc_common_reg_map { + __io uint32 CSR; /**< Common status register */ + __io uint32 CCR; /**< Common control register */ + __io uint32 CDR; /**< + * @brief Common regular data register + * for dual and triple modes */ +} adc_common_reg_map; + +/* + * Register map base pointers + */ + +/** ADC1 register map base pointer. */ +#define ADC1_BASE ((struct adc_reg_map*)0x40012000) +/** ADC2 register map base pointer. */ +#define ADC2_BASE ((struct adc_reg_map*)0x40012100) +/** ADC3 register map base pointer. */ +#define ADC3_BASE ((struct adc_reg_map*)0x40012200) +/** ADC common register map base pointer. */ +#define ADC_COMMON_BASE ((struct adc_common_reg_map*)0x40012300) + +/* + * Register bit definitions + */ + +/* Status register */ + +/** Overrun bit. */ +#define ADC_SR_OVR_BIT 5 +/** Overrun. */ +#define ADC_SR_OVR (1U << ADC_SR_OVR_BIT) + +/* Control register 1 */ + +/** Overrun interrupt enable bit. */ +#define ADC_CR1_OVRIE_BIT 26 + +/** Overrun interrupt error enable. */ +#define ADC_CR1_OVRIE (1U << ADC_CR1_OVRIE_BIT) +/** Conversion resolution. */ +#define ADC_CR1_RES (0x3U << 24) +/** Conversion resolution: 12 bit (at least 15 ADCCLK cycles). */ +#define ADC_CR1_RES_12BIT (0x0U << 24) +/** Conversion resolution: 10 bit (at least 13 ADCCLK cycles). */ +#define ADC_CR1_RES_10BIT (0x1U << 24) +/** Conversion resolution: 8 bit (at least 11 ADCCLK cycles). */ +#define ADC_CR1_RES_8BIT (0x2U << 24) +/** Conversion resolution: 6 bit (at least 9 ADCCLK cycles). */ +#define ADC_CR1_RES_6BIT (0x3U << 24) + +/* Control register 2 */ + +#define ADC_CR2_SWSTART_BIT 30 +#define ADC_CR2_JSWSTART_BIT 22 +#define ADC_CR2_ALIGN_BIT 11 +#define ADC_CR2_EOCS_BIT 10 +#define ADC_CR2_DDS_BIT 9 +#define ADC_CR2_DMA_BIT 8 +#define ADC_CR2_CONT_BIT 1 +#define ADC_CR2_ADON_BIT 0 + +#define ADC_CR2_SWSTART (1U << ADC_CR2_SWSTART_BIT) +#define ADC_CR2_EXTEN (0x3 << 28) +#define ADC_CR2_EXTEN_DISABLED (0x0 << 28) +#define ADC_CR2_EXTEN_RISE (0x1 << 28) +#define ADC_CR2_EXTEN_FALL (0x2 << 28) +#define ADC_CR2_EXTEN_RISE_FALL (0x3 << 28) +#define ADC_CR2_EXTSEL (0xF << 24) +#define ADC_CR2_EXTSEL_TIM1_CC1 (0x0 << 24) +#define ADC_CR2_EXTSEL_TIM1_CC2 (0x1 << 24) +#define ADC_CR2_EXTSEL_TIM1_CC3 (0x2 << 24) +#define ADC_CR2_EXTSEL_TIM2_CC2 (0x3 << 24) +#define ADC_CR2_EXTSEL_TIM2_CC3 (0x4 << 24) +#define ADC_CR2_EXTSEL_TIM2_CC4 (0x5 << 24) +#define ADC_CR2_EXTSEL_TIM1_TRGO (0x6 << 24) +#define ADC_CR2_EXTSEL_TIM3_CC1 (0x7 << 24) +#define ADC_CR2_EXTSEL_TIM3_TRGO (0x8 << 24) +#define ADC_CR2_EXTSEL_TIM4_CC4 (0x9 << 24) +#define ADC_CR2_EXTSEL_TIM5_CC1 (0xA << 24) +#define ADC_CR2_EXTSEL_TIM5_CC2 (0xB << 24) +#define ADC_CR2_EXTSEL_TIM5_CC3 (0xC << 24) +#define ADC_CR2_EXTSEL_TIM8_CC1 (0xD << 24) +#define ADC_CR2_EXTSEL_TIM8_TRGO (0xE << 24) +#define ADC_CR2_EXTSEL_TIM1_EXTI11 (0xF << 24) +#define ADC_CR2_JSWSTART (1U << ADC_CR2_JSWSTART_BIT) +#define ADC_CR2_JEXTEN (0x3 << 20) +#define ADC_CR2_JEXTEN_DISABLED (0x0 << 20) +#define ADC_CR2_JEXTEN_RISE (0x1 << 20) +#define ADC_CR2_JEXTEN_FALL (0x2 << 20) +#define ADC_CR2_JEXTEN_RISE_FALL (0x3 << 20) +#define ADC_CR2_JEXTSEL (0xF << 16) +#define ADC_CR2_JEXTSEL_TIM1_CC4 (0x0 << 16) +#define ADC_CR2_JEXTSEL_TIM1_TRGO (0x1 << 16) +#define ADC_CR2_JEXTSEL_TIM2_CC1 (0x2 << 16) +#define ADC_CR2_JEXTSEL_TIM2_TRGO (0x3 << 16) +#define ADC_CR2_JEXTSEL_TIM3_CC2 (0x4 << 16) +#define ADC_CR2_JEXTSEL_TIM3_CC4 (0x5 << 16) +#define ADC_CR2_JEXTSEL_TIM4_CC1 (0x6 << 16) +#define ADC_CR2_JEXTSEL_TIM4_CC2 (0x7 << 16) +#define ADC_CR2_JEXTSEL_TIM4_CC3 (0x8 << 16) +#define ADC_CR2_JEXTSEL_TIM4_TRGO (0x9 << 16) +#define ADC_CR2_JEXTSEL_TIM5_CC4 (0xA << 16) +#define ADC_CR2_JEXTSEL_TIM5_TRGO (0xB << 16) +#define ADC_CR2_JEXTSEL_TIM8_CC2 (0xC << 16) +#define ADC_CR2_JEXTSEL_TIM8_CC3 (0xD << 16) +#define ADC_CR2_JEXTSEL_TIM8_CC4 (0xE << 16) +#define ADC_CR2_JEXTSEL_TIM1_EXTI15 (0xF << 16) +#define ADC_CR2_ALIGN (1U << ADC_CR2_ALIGN_BIT) +#define ADC_CR2_ALIGN_RIGHT (0U << ADC_CR2_ALIGN_BIT) +#define ADC_CR2_ALIGN_LEFT (1U << ADC_CR2_ALIGN_BIT) +#define ADC_CR2_EOCS (1U << ADC_CR2_EOCS_BIT) +#define ADC_CR2_EOCS_SEQUENCE (0U << ADC_CR2_EOCS_BIT) +#define ADC_CR2_EOCS_CONVERSION (1U << ADC_CR2_EOCS_BIT) +#define ADC_CR2_DDS (1U << ADC_CR2_DDS_BIT) +#define ADC_CR2_DMA (1U << ADC_CR2_DMA_BIT) +#define ADC_CR2_CONT (1U << ADC_CR2_CONT_BIT) +#define ADC_CR2_ADON (1U << ADC_CR2_ADON_BIT) + +/* Common status register */ + +#define ADC_CSR_OVR3_BIT 21 +#define ADC_CSR_STRT3_BIT 20 +#define ADC_CSR_JSTRT3_BIT 19 +#define ADC_CSR_JEOC3_BIT 18 +#define ADC_CSR_EOC3_BIT 17 +#define ADC_CSR_AWD3_BIT 16 +#define ADC_CSR_OVR2_BIT 13 +#define ADC_CSR_STRT2_BIT 12 +#define ADC_CSR_JSTRT2_BIT 11 +#define ADC_CSR_JEOC2_BIT 10 +#define ADC_CSR_EOC2_BIT 9 +#define ADC_CSR_AWD2_BIT 8 +#define ADC_CSR_OVR1_BIT 5 +#define ADC_CSR_STRT1_BIT 4 +#define ADC_CSR_JSTRT1_BIT 3 +#define ADC_CSR_JEOC1_BIT 2 +#define ADC_CSR_EOC1_BIT 1 +#define ADC_CSR_AWD1_BIT 0 + +#define ADC_CSR_OVR3 (1U << ADC_CSR_OVR3_BIT) +#define ADC_CSR_STRT3 (1U << ADC_CSR_STRT3_BIT) +#define ADC_CSR_JSTRT3 (1U << ADC_CSR_JSTRT3_BIT) +#define ADC_CSR_JEOC3 (1U << ADC_CSR_JEOC3_BIT) +#define ADC_CSR_EOC3 (1U << ADC_CSR_EOC3_BIT) +#define ADC_CSR_AWD3 (1U << ADC_CSR_AWD3_BIT) +#define ADC_CSR_OVR2 (1U << ADC_CSR_OVR2_BIT) +#define ADC_CSR_STRT2 (1U << ADC_CSR_STRT2_BIT) +#define ADC_CSR_JSTRT2 (1U << ADC_CSR_JSTRT2_BIT) +#define ADC_CSR_JEOC2 (1U << ADC_CSR_JEOC2_BIT) +#define ADC_CSR_EOC2 (1U << ADC_CSR_EOC2_BIT) +#define ADC_CSR_AWD2 (1U << ADC_CSR_AWD2_BIT) +#define ADC_CSR_OVR1 (1U << ADC_CSR_OVR1_BIT) +#define ADC_CSR_STRT1 (1U << ADC_CSR_STRT1_BIT) +#define ADC_CSR_JSTRT1 (1U << ADC_CSR_JSTRT1_BIT) +#define ADC_CSR_JEOC1 (1U << ADC_CSR_JEOC1_BIT) +#define ADC_CSR_EOC1 (1U << ADC_CSR_EOC1_BIT) +#define ADC_CSR_AWD1 (1U << ADC_CSR_AWD1_BIT) + +/* Common control register */ + +#define ADC_CCR_TSVREFE_BIT 23 +#define ADC_CCR_VBATE_BIT 22 +#define ADC_CCR_DDS_BIT 13 + +#define ADC_CCR_TSVREFE (1U << ADC_CCR_TSVREFE_BIT) +#define ADC_CCR_VBATE (1U << ADC_CCR_VBATE_BIT) +#define ADC_CCR_ADCPRE (0x3 << 16) +#define ADC_CCR_ADCPRE_PCLK2_DIV_2 (0x0 << 16) +#define ADC_CCR_ADCPRE_PCLK2_DIV_4 (0x1 << 16) +#define ADC_CCR_ADCPRE_PCLK2_DIV_6 (0x2 << 16) +#define ADC_CCR_ADCPRE_PCLK2_DIV_8 (0x3 << 16) +#define ADC_CCR_DMA (0x3 << 14) +#define ADC_CCR_DMA_DIS (0x0 << 14) +#define ADC_CCR_DMA_MODE_1 (0x1 << 14) +#define ADC_CCR_DMA_MODE_2 (0x2 << 14) +#define ADC_CCR_DMA_MODE_3 (0x3 << 14) +#define ADC_CCR_DDS (1U << ADC_CCR_DDS_BIT) +#define ADC_CCR_DELAY (0xF << 8) +#define ADC_CCR_DELAY_5 (0x0 << 8) +#define ADC_CCR_DELAY_6 (0x1 << 8) +#define ADC_CCR_DELAY_7 (0x2 << 8) +#define ADC_CCR_DELAY_8 (0x3 << 8) +#define ADC_CCR_DELAY_9 (0x4 << 8) +#define ADC_CCR_DELAY_10 (0x5 << 8) +#define ADC_CCR_DELAY_11 (0x6 << 8) +#define ADC_CCR_DELAY_12 (0x7 << 8) +#define ADC_CCR_DELAY_13 (0x8 << 8) +#define ADC_CCR_DELAY_14 (0x9 << 8) +#define ADC_CCR_DELAY_15 (0xA << 8) +#define ADC_CCR_DELAY_16 (0xB << 8) +#define ADC_CCR_DELAY_17 (0xC << 8) +#define ADC_CCR_DELAY_18 (0xD << 8) +#define ADC_CCR_DELAY_19 (0xE << 8) +#define ADC_CCR_DELAY_20 (0xF << 8) +/** Multi ADC mode selection. */ +#define ADC_CCR_MULTI 0x1F +/** All ADCs independent. */ +#define ADC_CCR_MULTI_INDEPENDENT 0x0 +/** Dual mode: combined regular simultaneous/injected simultaneous. */ +#define ADC_CCR_MULTI_DUAL_REG_SIM_INJ_SIM 0x1 +/** Dual mode: combined regular simultaneous/alternate trigger. */ +#define ADC_CCR_MULTI_DUAL_REG_SIM_ALT_TRIG 0x2 +/** Dual mode: injected simultaneous mode only. */ +#define ADC_CCR_MULTI_DUAL_INJ_SIM 0x5 +/** Dual mode: regular simultaneous mode only. */ +#define ADC_CCR_MULTI_DUAL_REG_SIM 0x6 +/** Dual mode: interleaved mode only. */ +#define ADC_CCR_MULTI_DUAL_INTER 0x7 +/** Dual mode: alternate trigger mode only. */ +#define ADC_CCR_MULTI_DUAL_ALT_TRIG 0x9 +/** Triple mode: combined regular simultaneous/injected simultaneous. */ +#define ADC_CCR_MULTI_TRIPLE_REG_SIM_INJ_SIM 0x10 +/** Triple mode: combined regular simultaneous/alternate trigger. */ +#define ADC_CCR_MULTI_TRIPLE_REG_SIM_ALT_TRIG 0x11 +/** Triple mode: injected simultaneous mode only. */ +#define ADC_CCR_MULTI_TRIPLE_INJ_SIM 0x12 +/** Triple mode: regular simultaneous mode only. */ +#define ADC_CCR_MULTI_TRIPLE_REG_SIM 0x15 +/** Triple mode: interleaved mode only. */ +#define ADC_CCR_MULTI_TRIPLE_INTER 0x17 +/** Triple mode: alternate trigger mode only. */ +#define ADC_CCR_MULTI_TRIPLE_ALT_TRIG 0x19 + +/* Common regular data register for dual and triple modes */ + +#define ADC_CDR_DATA2 0xFFFF0000 +#define ADC_CDR_DATA1 0xFFFF + +/* + * Other types + */ + +/** + * @brief STM32F2 external event selectors for regular group + * conversion. + * @see adc_set_extsel() + */ +typedef enum adc_extsel_event { + ADC_EXT_EV_TIM1_CC1 = ADC_CR2_EXTSEL_TIM1_CC1, + ADC_EXT_EV_TIM1_CC2 = ADC_CR2_EXTSEL_TIM1_CC2, + ADC_EXT_EV_TIM1_CC3 = ADC_CR2_EXTSEL_TIM1_CC3, + ADC_EXT_EV_TIM2_CC2 = ADC_CR2_EXTSEL_TIM2_CC2, + ADC_EXT_EV_TIM2_CC3 = ADC_CR2_EXTSEL_TIM2_CC3, + ADC_EXT_EV_TIM2_CC4 = ADC_CR2_EXTSEL_TIM2_CC4, + ADC_EXT_EV_TIM1_TRGO = ADC_CR2_EXTSEL_TIM1_TRGO, + ADC_EXT_EV_TIM3_CC1 = ADC_CR2_EXTSEL_TIM3_CC1, + ADC_EXT_EV_TIM3_TRGO = ADC_CR2_EXTSEL_TIM3_TRGO, + ADC_EXT_EV_TIM4_CC4 = ADC_CR2_EXTSEL_TIM4_CC4, + ADC_EXT_EV_TIM5_CC1 = ADC_CR2_EXTSEL_TIM5_CC1, + ADC_EXT_EV_TIM5_CC2 = ADC_CR2_EXTSEL_TIM5_CC2, + ADC_EXT_EV_TIM5_CC3 = ADC_CR2_EXTSEL_TIM5_CC3, + ADC_EXT_EV_TIM8_CC1 = ADC_CR2_EXTSEL_TIM8_CC1, + ADC_EXT_EV_TIM8_TRGO = ADC_CR2_EXTSEL_TIM8_TRGO, + ADC_EXT_EV_TIM1_EXTI11 = ADC_CR2_EXTSEL_TIM1_EXTI11, +} adc_extsel_event; + +/** + * @brief STM32F2 sample times, in ADC clock cycles. + */ +typedef enum adc_smp_rate { + ADC_SMPR_3, /**< 3 ADC cycles */ + ADC_SMPR_15, /**< 15 ADC cycles */ + ADC_SMPR_28, /**< 28 ADC cycles */ + ADC_SMPR_56, /**< 56 ADC cycles */ + ADC_SMPR_84, /**< 84 ADC cycles */ + ADC_SMPR_112, /**< 112 ADC cycles */ + ADC_SMPR_144, /**< 144 ADC cycles */ + ADC_SMPR_480, /**< 480 ADC cycles */ +} adc_smp_rate; + +/** + * @brief STM32F2 ADC prescalers, as divisors of PCLK2. + */ +typedef enum adc_prescaler { + /** PCLK2 divided by 2 */ + ADC_PRE_PCLK2_DIV_2 = ADC_CCR_ADCPRE_PCLK2_DIV_2, + /** PCLK2 divided by 4 */ + ADC_PRE_PCLK2_DIV_4 = ADC_CCR_ADCPRE_PCLK2_DIV_4, + /** PCLK2 divided by 6 */ + ADC_PRE_PCLK2_DIV_6 = ADC_CCR_ADCPRE_PCLK2_DIV_6, + /** PCLK2 divided by 8 */ + ADC_PRE_PCLK2_DIV_8 = ADC_CCR_ADCPRE_PCLK2_DIV_8, +} adc_prescaler; + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/dac.h b/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/dac.h new file mode 100644 index 0000000..0a578ca --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/dac.h @@ -0,0 +1,94 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f2/include/series/dac.h + * @brief STM32F2 DAC support + */ + +#ifndef _LIBMAPLE_STM32F2_DAC_H_ +#define _LIBMAPLE_STM32F2_DAC_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include + +/* + * Register map type + */ + +/** STM32F2 DAC register map type. */ +typedef struct dac_reg_map { + __io uint32 CR; /**< Control register */ + __io uint32 SWTRIGR; /**< Software trigger register */ + __io uint32 DHR12R1; /**< Channel 1 12-bit right-aligned data + holding register */ + __io uint32 DHR12L1; /**< Channel 1 12-bit left-aligned data + holding register */ + __io uint32 DHR8R1; /**< Channel 1 8-bit left-aligned data + holding register */ + __io uint32 DHR12R2; /**< Channel 2 12-bit right-aligned data + holding register */ + __io uint32 DHR12L2; /**< Channel 2 12-bit left-aligned data + holding register */ + __io uint32 DHR8R2; /**< Channel 2 8-bit left-aligned data + holding register */ + __io uint32 DHR12RD; /**< Dual DAC 12-bit right-aligned data + holding register */ + __io uint32 DHR12LD; /**< Dual DAC 12-bit left-aligned data + holding register */ + __io uint32 DHR8RD; /**< Dual DAC 8-bit right-aligned data holding + register */ + __io uint32 DOR1; /**< Channel 1 data output register */ + __io uint32 DOR2; /**< Channel 2 data output register */ + __io uint32 SR; /**< Status register */ +} dac_reg_map; + +/* + * Register bit definitions + */ + +/* Control register */ + +#define DAC_CR_DMAUDRIE1 (1U << 13) /* Channel 1 DMA underrun + * interrupt enable */ +#define DAC_CR_DMAUDRIE2 (1U << 29) /* Channel 2 DMA underrun + * interrupt enable */ + +/* Status register */ + +#define DAC_SR_DMAUDR1 (1U << 13) /* Channel 1 DMA underrun + * occurred */ +#define DAC_SR_DMAUDR2 (1U << 29) /* Channel 2 DMA underrun + * ocurred */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/dma.h b/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/dma.h new file mode 100644 index 0000000..56725e5 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/dma.h @@ -0,0 +1,810 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f2/include/series/dma.h + * @author Marti Bolivar + * @brief STM32F2 DMA series header + */ + +#ifndef _LIBMAPLE_STM32F2_DMA_H_ +#define _LIBMAPLE_STM32F2_DMA_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include +#include + +/* + * Register map and base pointers + */ + +/** + * @brief STM32F2 DMA register map type. + */ +typedef struct dma_reg_map { + /* Isn't it nice how on F1, it's CCR1, but on F2, it's S1CR? */ + + /* Global DMA registers */ + __io uint32 LISR; /**< Low interrupt status register */ + __io uint32 HISR; /**< High interrupt status register */ + __io uint32 LIFCR; /**< Low interrupt flag clear register */ + __io uint32 HIFCR; /**< High interrupt flag clear register */ + /* Stream 0 registers */ + __io uint32 S0CR; /**< Stream 0 control register */ + __io uint32 S0NDTR; /**< Stream 0 number of data register */ + __io uint32 S0PAR; /**< Stream 0 peripheral address register */ + __io uint32 S0M0AR; /**< Stream 0 memory 0 address register */ + __io uint32 S0M1AR; /**< Stream 0 memory 1 address register */ + __io uint32 S0FCR; /**< Stream 0 FIFO control register */ + /* Stream 1 registers */ + __io uint32 S1CR; /**< Stream 1 control register */ + __io uint32 S1NDTR; /**< Stream 1 number of data register */ + __io uint32 S1PAR; /**< Stream 1 peripheral address register */ + __io uint32 S1M0AR; /**< Stream 1 memory 0 address register */ + __io uint32 S1M1AR; /**< Stream 1 memory 1 address register */ + __io uint32 S1FCR; /**< Stream 1 FIFO control register */ + /* Stream 2 registers */ + __io uint32 S2CR; /**< Stream 2 control register */ + __io uint32 S2NDTR; /**< Stream 2 number of data register */ + __io uint32 S2PAR; /**< Stream 2 peripheral address register */ + __io uint32 S2M0AR; /**< Stream 2 memory 0 address register */ + __io uint32 S2M1AR; /**< Stream 2 memory 1 address register */ + __io uint32 S2FCR; /**< Stream 2 FIFO control register */ + /* Stream 3 registers */ + __io uint32 S3CR; /**< Stream 3 control register */ + __io uint32 S3NDTR; /**< Stream 3 number of data register */ + __io uint32 S3PAR; /**< Stream 3 peripheral address register */ + __io uint32 S3M0AR; /**< Stream 3 memory 0 address register */ + __io uint32 S3M1AR; /**< Stream 3 memory 1 address register */ + __io uint32 S3FCR; /**< Stream 3 FIFO control register */ + /* Stream 4 registers */ + __io uint32 S4CR; /**< Stream 4 control register */ + __io uint32 S4NDTR; /**< Stream 4 number of data register */ + __io uint32 S4PAR; /**< Stream 4 peripheral address register */ + __io uint32 S4M0AR; /**< Stream 4 memory 0 address register */ + __io uint32 S4M1AR; /**< Stream 4 memory 1 address register */ + __io uint32 S4FCR; /**< Stream 4 FIFO control register */ + /* Stream 5 registers */ + __io uint32 S5CR; /**< Stream 5 control register */ + __io uint32 S5NDTR; /**< Stream 5 number of data register */ + __io uint32 S5PAR; /**< Stream 5 peripheral address register */ + __io uint32 S5M0AR; /**< Stream 5 memory 0 address register */ + __io uint32 S5M1AR; /**< Stream 5 memory 1 address register */ + __io uint32 S5FCR; /**< Stream 5 FIFO control register */ + /* Stream 6 registers */ + __io uint32 S6CR; /**< Stream 6 control register */ + __io uint32 S6NDTR; /**< Stream 6 number of data register */ + __io uint32 S6PAR; /**< Stream 6 peripheral address register */ + __io uint32 S6M0AR; /**< Stream 6 memory 0 address register */ + __io uint32 S6M1AR; /**< Stream 6 memory 1 address register */ + __io uint32 S6FCR; /**< Stream 6 FIFO control register */ + /* Stream 7 registers */ + __io uint32 S7CR; /**< Stream 7 control register */ + __io uint32 S7NDTR; /**< Stream 7 number of data register */ + __io uint32 S7PAR; /**< Stream 7 peripheral address register */ + __io uint32 S7M0AR; /**< Stream 7 memory 0 address register */ + __io uint32 S7M1AR; /**< Stream 7 memory 1 address register */ + __io uint32 S7FCR; /**< Stream 7 FIFO control register */ +} dma_reg_map; + +/** DMA controller 1 register map base pointer */ +#define DMA1_BASE ((struct dma_reg_map*)0x40026000) +/** DMA controller 2 register map base pointer */ +#define DMA2_BASE ((struct dma_reg_map*)0x40026400) + +/** + * @brief STM32F2 DMA stream (i.e. tube) register map type. + * Provides access to an individual stream's registers. + * @see dma_tube_regs() + */ +typedef struct dma_tube_reg_map { + __io uint32 SCR; /**< Stream configuration register */ + __io uint32 SNDTR; /**< Stream number of data register */ + __io uint32 SPAR; /**< Stream peripheral address register */ + __io uint32 SM0AR; /**< Stream memory 0 address register */ + __io uint32 SM1AR; /**< Stream memory 1 address register */ + __io uint32 SFCR; /**< Stream FIFO control register */ +} dma_tube_reg_map; + +/** DMA1 stream 0 register map base pointer */ +#define DMA1S0_BASE ((struct dma_tube_reg_map*)0x40026010) +/** DMA1 stream 1 register map base pointer */ +#define DMA1S1_BASE ((struct dma_tube_reg_map*)0x40026028) +/** DMA1 stream 2 register map base pointer */ +#define DMA1S2_BASE ((struct dma_tube_reg_map*)0x40026040) +/** DMA1 stream 3 register map base pointer */ +#define DMA1S3_BASE ((struct dma_tube_reg_map*)0x40026058) +/** DMA1 stream 4 register map base pointer */ +#define DMA1S4_BASE ((struct dma_tube_reg_map*)0x40026070) +/** DMA1 stream 5 register map base pointer */ +#define DMA1S5_BASE ((struct dma_tube_reg_map*)0x40026088) +/** DMA1 stream 6 register map base pointer */ +#define DMA1S6_BASE ((struct dma_tube_reg_map*)0x400260A0) +/** DMA1 stream 7 register map base pointer */ +#define DMA1S7_BASE ((struct dma_tube_reg_map*)0x400260B8) + +/** DMA2 stream 0 register map base pointer */ +#define DMA2S0_BASE ((struct dma_tube_reg_map*)0x40026410) +/** DMA2 stream 1 register map base pointer */ +#define DMA2S1_BASE ((struct dma_tube_reg_map*)0x40026028) +/** DMA2 stream 2 register map base pointer */ +#define DMA2S2_BASE ((struct dma_tube_reg_map*)0x40026040) +/** DMA2 stream 3 register map base pointer */ +#define DMA2S3_BASE ((struct dma_tube_reg_map*)0x40026058) +/** DMA2 stream 4 register map base pointer */ +#define DMA2S4_BASE ((struct dma_tube_reg_map*)0x40026070) +/** DMA2 stream 5 register map base pointer */ +#define DMA2S5_BASE ((struct dma_tube_reg_map*)0x40026088) +/** DMA2 stream 6 register map base pointer */ +#define DMA2S6_BASE ((struct dma_tube_reg_map*)0x400260A0) +/** DMA2 stream 7 register map base pointer */ +#define DMA2S7_BASE ((struct dma_tube_reg_map*)0x400260B8) + +/* + * Register bit definitions + */ + +/* Low interrupt status register */ + +#define DMA_LISR_TCIF3_BIT 27 +#define DMA_LISR_HTIF3_BIT 26 +#define DMA_LISR_TEIF3_BIT 25 +#define DMA_LISR_DMEIF3_BIT 24 +#define DMA_LISR_FEIF3_BIT 22 +#define DMA_LISR_TCIF2_BIT 21 +#define DMA_LISR_HTIF2_BIT 20 +#define DMA_LISR_TEIF2_BIT 19 +#define DMA_LISR_DMEIF2_BIT 18 +#define DMA_LISR_FEIF2_BIT 16 +#define DMA_LISR_TCIF1_BIT 11 +#define DMA_LISR_HTIF1_BIT 10 +#define DMA_LISR_TEIF1_BIT 9 +#define DMA_LISR_DMEIF1_BIT 8 +#define DMA_LISR_FEIF1_BIT 6 +#define DMA_LISR_TCIF0_BIT 5 +#define DMA_LISR_HTIF0_BIT 4 +#define DMA_LISR_TEIF0_BIT 3 +#define DMA_LISR_DMEIF0_BIT 2 +#define DMA_LISR_FEIF0_BIT 0 + +#define DMA_LISR_TCIF3 (1U << DMA_LISR_TCIF3_BIT) +#define DMA_LISR_HTIF3 (1U << DMA_LISR_HTIF3_BIT) +#define DMA_LISR_TEIF3 (1U << DMA_LISR_TEIF3_BIT) +#define DMA_LISR_DMEIF3 (1U << DMA_LISR_DMEIF3_BIT) +#define DMA_LISR_FEIF3 (1U << DMA_LISR_FEIF3_BIT) +#define DMA_LISR_TCIF2 (1U << DMA_LISR_TCIF2_BIT) +#define DMA_LISR_HTIF2 (1U << DMA_LISR_HTIF2_BIT) +#define DMA_LISR_TEIF2 (1U << DMA_LISR_TEIF2_BIT) +#define DMA_LISR_DMEIF2 (1U << DMA_LISR_DMEIF2_BIT) +#define DMA_LISR_FEIF2 (1U << DMA_LISR_FEIF2_BIT) +#define DMA_LISR_TCIF1 (1U << DMA_LISR_TCIF1_BIT) +#define DMA_LISR_HTIF1 (1U << DMA_LISR_HTIF1_BIT) +#define DMA_LISR_TEIF1 (1U << DMA_LISR_TEIF1_BIT) +#define DMA_LISR_DMEIF1 (1U << DMA_LISR_DMEIF1_BIT) +#define DMA_LISR_FEIF1 (1U << DMA_LISR_FEIF1_BIT) +#define DMA_LISR_TCIF0 (1U << DMA_LISR_TCIF0_BIT) +#define DMA_LISR_HTIF0 (1U << DMA_LISR_HTIF0_BIT) +#define DMA_LISR_TEIF0 (1U << DMA_LISR_TEIF0_BIT) +#define DMA_LISR_DMEIF0 (1U << DMA_LISR_DMEIF0_BIT) +#define DMA_LISR_FEIF0 (1U << DMA_LISR_FEIF0_BIT) + +/* High interrupt status register */ + +#define DMA_HISR_TCIF7_BIT 27 +#define DMA_HISR_HTIF7_BIT 26 +#define DMA_HISR_TEIF7_BIT 25 +#define DMA_HISR_DMEIF7_BIT 24 +#define DMA_HISR_FEIF7_BIT 22 +#define DMA_HISR_TCIF6_BIT 21 +#define DMA_HISR_HTIF6_BIT 20 +#define DMA_HISR_TEIF6_BIT 19 +#define DMA_HISR_DMEIF6_BIT 18 +#define DMA_HISR_FEIF6_BIT 16 +#define DMA_HISR_TCIF5_BIT 11 +#define DMA_HISR_HTIF5_BIT 10 +#define DMA_HISR_TEIF5_BIT 9 +#define DMA_HISR_DMEIF5_BIT 8 +#define DMA_HISR_FEIF5_BIT 6 +#define DMA_HISR_TCIF4_BIT 5 +#define DMA_HISR_HTIF4_BIT 4 +#define DMA_HISR_TEIF4_BIT 3 +#define DMA_HISR_DMEIF4_BIT 2 +#define DMA_HISR_FEIF4_BIT 0 + +#define DMA_HISR_TCIF7 (1U << DMA_HISR_TCIF7_BIT) +#define DMA_HISR_HTIF7 (1U << DMA_HISR_HTIF7_BIT) +#define DMA_HISR_TEIF7 (1U << DMA_HISR_TEIF7_BIT) +#define DMA_HISR_DMEIF7 (1U << DMA_HISR_DMEIF7_BIT) +#define DMA_HISR_FEIF7 (1U << DMA_HISR_FEIF7_BIT) +#define DMA_HISR_TCIF6 (1U << DMA_HISR_TCIF6_BIT) +#define DMA_HISR_HTIF6 (1U << DMA_HISR_HTIF6_BIT) +#define DMA_HISR_TEIF6 (1U << DMA_HISR_TEIF6_BIT) +#define DMA_HISR_DMEIF6 (1U << DMA_HISR_DMEIF6_BIT) +#define DMA_HISR_FEIF6 (1U << DMA_HISR_FEIF6_BIT) +#define DMA_HISR_TCIF5 (1U << DMA_HISR_TCIF5_BIT) +#define DMA_HISR_HTIF5 (1U << DMA_HISR_HTIF5_BIT) +#define DMA_HISR_TEIF5 (1U << DMA_HISR_TEIF5_BIT) +#define DMA_HISR_DMEIF5 (1U << DMA_HISR_DMEIF5_BIT) +#define DMA_HISR_FEIF5 (1U << DMA_HISR_FEIF5_BIT) +#define DMA_HISR_TCIF4 (1U << DMA_HISR_TCIF4_BIT) +#define DMA_HISR_HTIF4 (1U << DMA_HISR_HTIF4_BIT) +#define DMA_HISR_TEIF4 (1U << DMA_HISR_TEIF4_BIT) +#define DMA_HISR_DMEIF4 (1U << DMA_HISR_DMEIF4_BIT) +#define DMA_HISR_FEIF4 (1U << DMA_HISR_FEIF4_BIT) + +/* Low interrupt flag clear register */ + +#define DMA_LIFCR_CTCIF3_BIT 27 +#define DMA_LIFCR_CHTIF3_BIT 26 +#define DMA_LIFCR_CTEIF3_BIT 25 +#define DMA_LIFCR_CDMEIF3_BIT 24 +#define DMA_LIFCR_CFEIF3_BIT 22 +#define DMA_LIFCR_CTCIF2_BIT 21 +#define DMA_LIFCR_CHTIF2_BIT 20 +#define DMA_LIFCR_CTEIF2_BIT 19 +#define DMA_LIFCR_CDMEIF2_BIT 18 +#define DMA_LIFCR_CFEIF2_BIT 16 +#define DMA_LIFCR_CTCIF1_BIT 11 +#define DMA_LIFCR_CHTIF1_BIT 10 +#define DMA_LIFCR_CTEIF1_BIT 9 +#define DMA_LIFCR_CDMEIF1_BIT 8 +#define DMA_LIFCR_CFEIF1_BIT 6 +#define DMA_LIFCR_CTCIF0_BIT 5 +#define DMA_LIFCR_CHTIF0_BIT 4 +#define DMA_LIFCR_CTEIF0_BIT 3 +#define DMA_LIFCR_CDMEIF0_BIT 2 +#define DMA_LIFCR_CFEIF0_BIT 0 + +#define DMA_LIFCR_CTCIF3 (1U << DMA_LIFCR_CTCIF3_BIT) +#define DMA_LIFCR_CHTIF3 (1U << DMA_LIFCR_CHTIF3_BIT) +#define DMA_LIFCR_CTEIF3 (1U << DMA_LIFCR_CTEIF3_BIT) +#define DMA_LIFCR_CDMEIF3 (1U << DMA_LIFCR_CDMEIF3_BIT) +#define DMA_LIFCR_CFEIF3 (1U << DMA_LIFCR_CFEIF3_BIT) +#define DMA_LIFCR_CTCIF2 (1U << DMA_LIFCR_CTCIF2_BIT) +#define DMA_LIFCR_CHTIF2 (1U << DMA_LIFCR_CHTIF2_BIT) +#define DMA_LIFCR_CTEIF2 (1U << DMA_LIFCR_CTEIF2_BIT) +#define DMA_LIFCR_CDMEIF2 (1U << DMA_LIFCR_CDMEIF2_BIT) +#define DMA_LIFCR_CFEIF2 (1U << DMA_LIFCR_CFEIF2_BIT) +#define DMA_LIFCR_CTCIF1 (1U << DMA_LIFCR_CTCIF1_BIT) +#define DMA_LIFCR_CHTIF1 (1U << DMA_LIFCR_CHTIF1_BIT) +#define DMA_LIFCR_CTEIF1 (1U << DMA_LIFCR_CTEIF1_BIT) +#define DMA_LIFCR_CDMEIF1 (1U << DMA_LIFCR_CDMEIF1_BIT) +#define DMA_LIFCR_CFEIF1 (1U << DMA_LIFCR_CFEIF1_BIT) +#define DMA_LIFCR_CTCIF0 (1U << DMA_LIFCR_CTCIF0_BIT) +#define DMA_LIFCR_CHTIF0 (1U << DMA_LIFCR_CHTIF0_BIT) +#define DMA_LIFCR_CTEIF0 (1U << DMA_LIFCR_CTEIF0_BIT) +#define DMA_LIFCR_CDMEIF0 (1U << DMA_LIFCR_CDMEIF0_BIT) +#define DMA_LIFCR_CFEIF0 (1U << DMA_LIFCR_CFEIF0_BIT) + +/* High interrupt flag clear regsister */ + +#define DMA_HIFCR_CTCIF7_BIT 27 +#define DMA_HIFCR_CHTIF7_BIT 26 +#define DMA_HIFCR_CTEIF7_BIT 25 +#define DMA_HIFCR_CDMEIF7_BIT 24 +#define DMA_HIFCR_CFEIF7_BIT 22 +#define DMA_HIFCR_CTCIF6_BIT 21 +#define DMA_HIFCR_CHTIF6_BIT 20 +#define DMA_HIFCR_CTEIF6_BIT 19 +#define DMA_HIFCR_CDMEIF6_BIT 18 +#define DMA_HIFCR_CFEIF6_BIT 16 +#define DMA_HIFCR_CTCIF5_BIT 11 +#define DMA_HIFCR_CHTIF5_BIT 10 +#define DMA_HIFCR_CTEIF5_BIT 9 +#define DMA_HIFCR_CDMEIF5_BIT 8 +#define DMA_HIFCR_CFEIF5_BIT 6 +#define DMA_HIFCR_CTCIF4_BIT 5 +#define DMA_HIFCR_CHTIF4_BIT 4 +#define DMA_HIFCR_CTEIF4_BIT 3 +#define DMA_HIFCR_CDMEIF4_BIT 2 +#define DMA_HIFCR_CFEIF4_BIT 0 + +#define DMA_HIFCR_CTCIF7 (1U << DMA_HIFCR_CTCIF7_BIT) +#define DMA_HIFCR_CHTIF7 (1U << DMA_HIFCR_CHTIF7_BIT) +#define DMA_HIFCR_CTEIF7 (1U << DMA_HIFCR_CTEIF7_BIT) +#define DMA_HIFCR_CDMEIF7 (1U << DMA_HIFCR_CDMEIF7_BIT) +#define DMA_HIFCR_CFEIF7 (1U << DMA_HIFCR_CFEIF7_BIT) +#define DMA_HIFCR_CTCIF6 (1U << DMA_HIFCR_CTCIF6_BIT) +#define DMA_HIFCR_CHTIF6 (1U << DMA_HIFCR_CHTIF6_BIT) +#define DMA_HIFCR_CTEIF6 (1U << DMA_HIFCR_CTEIF6_BIT) +#define DMA_HIFCR_CDMEIF6 (1U << DMA_HIFCR_CDMEIF6_BIT) +#define DMA_HIFCR_CFEIF6 (1U << DMA_HIFCR_CFEIF6_BIT) +#define DMA_HIFCR_CTCIF5 (1U << DMA_HIFCR_CTCIF5_BIT) +#define DMA_HIFCR_CHTIF5 (1U << DMA_HIFCR_CHTIF5_BIT) +#define DMA_HIFCR_CTEIF5 (1U << DMA_HIFCR_CTEIF5_BIT) +#define DMA_HIFCR_CDMEIF5 (1U << DMA_HIFCR_CDMEIF5_BIT) +#define DMA_HIFCR_CFEIF5 (1U << DMA_HIFCR_CFEIF5_BIT) +#define DMA_HIFCR_CTCIF4 (1U << DMA_HIFCR_CTCIF4_BIT) +#define DMA_HIFCR_CHTIF4 (1U << DMA_HIFCR_CHTIF4_BIT) +#define DMA_HIFCR_CTEIF4 (1U << DMA_HIFCR_CTEIF4_BIT) +#define DMA_HIFCR_CDMEIF4 (1U << DMA_HIFCR_CDMEIF4_BIT) +#define DMA_HIFCR_CFEIF4 (1U << DMA_HIFCR_CFEIF4_BIT) + +/* Stream configuration register */ + +#define DMA_SCR_CT_BIT 19 +#define DMA_SCR_DBM_BIT 18 +#define DMA_SCR_PINCOS_BIT 15 +#define DMA_SCR_MINC_BIT 10 +#define DMA_SCR_PINC_BIT 9 +#define DMA_SCR_CIRC_BIT 8 +#define DMA_SCR_PFCTRL_BIT 5 +#define DMA_SCR_TCIE_BIT 4 +#define DMA_SCR_HTIE_BIT 3 +#define DMA_SCR_TEIE_BIT 2 +#define DMA_SCR_DMEIE_BIT 1 +#define DMA_SCR_EN_BIT 0 + +#define DMA_SCR_CHSEL (0x7 << 25) +#define DMA_SCR_CHSEL_CH_0 (0x0 << 25) +#define DMA_SCR_CHSEL_CH_1 (0x1 << 25) +#define DMA_SCR_CHSEL_CH_2 (0x2 << 25) +#define DMA_SCR_CHSEL_CH_3 (0x3 << 25) +#define DMA_SCR_CHSEL_CH_4 (0x4 << 25) +#define DMA_SCR_CHSEL_CH_5 (0x5 << 25) +#define DMA_SCR_CHSEL_CH_6 (0x6 << 25) +#define DMA_SCR_CHSEL_CH_7 (0x7 << 25) +#define DMA_SCR_MBURST (0x3 << 23) +#define DMA_SCR_MBURST_SINGLE (0x0 << 23) +#define DMA_SCR_MBURST_INCR4 (0x1 << 23) +#define DMA_SCR_MBURST_INCR8 (0x2 << 23) +#define DMA_SCR_MBURST_INCR16 (0x3 << 23) +#define DMA_SCR_PBURST (0x3 << 21) +#define DMA_SCR_PBURST_SINGLE (0x0 << 21) +#define DMA_SCR_PBURST_INCR4 (0x1 << 21) +#define DMA_SCR_PBURST_INCR8 (0x2 << 21) +#define DMA_SCR_PBURST_INCR16 (0x3 << 21) +#define DMA_SCR_CT (1U << DMA_SCR_CT_BIT) +#define DMA_SCR_DBM (1U << DMA_SCR_DBM_BIT) +#define DMA_SCR_PL (0x3 << 16) +#define DMA_SCR_PL_LOW (0x0 << 16) +#define DMA_SCR_PL_MEDIUM (0x1 << 16) +#define DMA_SCR_PL_HIGH (0x2 << 16) +#define DMA_SCR_VERY_HIGH (0x3 << 16) +#define DMA_SCR_PINCOS (1U << DMA_SCR_PINCOS_BIT) +#define DMA_SCR_MSIZE (0x3 << 13) +#define DMA_SCR_MSIZE_8BITS (0x0 << 13) +#define DMA_SCR_MSIZE_16BITS (0x1 << 13) +#define DMA_SCR_MSIZE_32BITS (0x2 << 13) +#define DMA_SCR_PSIZE (0x3 << 11) +#define DMA_SCR_PSIZE_8BITS (0x0 << 11) +#define DMA_SCR_PSIZE_16BITS (0x1 << 11) +#define DMA_SCR_PSIZE_32BITS (0x2 << 11) +#define DMA_SCR_MINC (1U << DMA_SCR_MINC_BIT) +#define DMA_SCR_PINC (1U << DMA_SCR_PINC_BIT) +#define DMA_SCR_CIRC (1U << DMA_SCR_CIRC_BIT) +#define DMA_SCR_DIR (0x3 << 6) +#define DMA_SCR_DIR_PER_TO_MEM (0x0 << 6) +#define DMA_SCR_DIR_MEM_TO_PER (0x1 << 6) +#define DMA_SCR_DIR_MEM_TO_MEM (0x2 << 6) +#define DMA_SCR_PFCTRL (1U << DMA_SCR_PFCTRL_BIT) +#define DMA_SCR_TCIE (1U << DMA_SCR_TCIE_BIT) +#define DMA_SCR_HTIE (1U << DMA_SCR_HTIE_BIT) +#define DMA_SCR_TEIE (1U << DMA_SCR_TEIE_BIT) +#define DMA_SCR_DMEIE (1U << DMA_SCR_DMEIE_BIT) +#define DMA_SCR_EN (1U << DMA_SCR_EN_BIT) + +/* Stream FIFO control register */ + +#define DMA_SFCR_FEIE_BIT 7 +#define DMA_SFCR_DMDIS_BIT 2 + +#define DMA_SFCR_FEIE (1U << DMA_SFCR_FEIE_BIT) +#define DMA_SFCR_FS (0x7 << 3) +#define DMA_SFCR_FS_ZERO_TO_QUARTER (0x0 << 3) +#define DMA_SFCR_FS_QUARTER_TO_HALF (0x1 << 3) +#define DMA_SFCR_FS_HALF_TO_THREE_QUARTERS (0x2 << 3) +#define DMA_SFCR_FS_THREE_QUARTERS_TO_FULL (0x3 << 3) +#define DMA_SFCR_FS_EMPTY (0x4 << 3) +#define DMA_SFCR_FS_FULL (0x5 << 3) +#define DMA_SFCR_DMDIS (1U << DMA_SFCR_DMDIS_BIT) +#define DMA_SFCR_FTH (0x3 << 0) +#define DMA_SFCR_FTH_QUARTER_FULL (0x0 << 3) +#define DMA_SFCR_FTH_HALF_FULL (0x1 << 3) +#define DMA_SFCR_FTH_THREE_QUARTERS_FULL (0x2 << 3) +#define DMA_SFCR_FTH_FULL (0x3 << 3) + +/* + * Devices + */ + +extern dma_dev *DMA1; +extern dma_dev *DMA2; + +/* + * Other types needed by, or useful for, + */ + +/** + * @brief DMA streams + * This is also the dma_tube type for STM32F2. + * @see dma_tube + */ +typedef enum dma_stream { + DMA_S0 = 0, + DMA_S1 = 1, + DMA_S2 = 2, + DMA_S3 = 3, + DMA_S4 = 4, + DMA_S5 = 5, + DMA_S6 = 6, + DMA_S7 = 7, +} dma_stream; + +/** STM32F2 dma_tube (=dma_stream) */ +#define dma_tube dma_stream + +/** + * @brief STM32F2 configuration flags for dma_tube_config. + * @see struct dma_tube_config + */ +typedef enum dma_cfg_flags { + /* NB: flags that aren't SCR bits are treated specially. */ + + /** + * Source address increment mode + * + * If this flag is set, the source address is incremented (by the + * source size) after each DMA transfer. + */ + DMA_CFG_SRC_INC = 1U << 31, + + /** + * Destination address increment mode + * + * If this flag is set, the destination address is incremented (by + * the destination size) after each DMA transfer. + */ + DMA_CFG_DST_INC = 1U << 30, + + /** + * Circular mode + * + * This mode is not available for memory-to-memory transfers. + */ + DMA_CFG_CIRC = DMA_SCR_CIRC, + + /** Transfer complete interrupt enable */ + DMA_CFG_CMPLT_IE = DMA_SCR_TCIE, + /** Transfer half-complete interrupt enable */ + DMA_CFG_HALF_CMPLT_IE = DMA_SCR_HTIE, + /** Transfer error interrupt enable */ + DMA_CFG_ERR_IE = DMA_SCR_TEIE, + /** Direct mode error interrupt enable */ + DMA_CFG_DM_ERR_IE = DMA_SCR_DMEIE, + /** FIFO error interrupt enable */ + DMA_CFG_FIFO_ERR_IE = (1U << 29), +} dma_cfg_flags; + +/** + * @brief STM32F2 DMA request sources. + * + * IMPORTANT: + * + * 1. On STM32F2, a particular dma_request_src is always tied to a + * single DMA controller, but often can be supported by multiple + * streams. For example, DMA requests from ADC1 (DMA_REQ_SRC_ADC1) can + * only be handled by DMA2, but they can go to either stream 0 or + * stream 4 (though not any other stream). If you try to use a request + * source with the wrong DMA controller or the wrong stream on + * STM32F2, dma_tube_cfg() will fail. + * + * 2. A single stream can only handle a single request source at a + * time. If you change a stream's request source later, it will stop + * serving requests from the old source. However, for some streams, + * some sources conflict with one another (when they correspond to the + * same channel on that stream), and on STM32F2, Terrible Super-Bad + * Things will happen if two conflicting request sources are active at + * the same time. + * + * @see struct dma_tube_config + * @see dma_tube_cfg() + */ +typedef enum dma_request_src { + /* These are constructed like so (though this may change, so user + * code shouldn't depend on it): + * + * Bits 0--2: Channel associated with request source + * + * Bits 3--9: rcc_clk_id of DMA controller associated with request source + * + * Bits 10--17: Bit mask of streams which can handle that request + * source. (E.g., bit 10 set means stream 0 can + * handle the source, bit 11 set means stream 1 can, + * etc.) + * + * Among other things, this is used for error checking in + * dma_tube_cfg(). If you change this bit encoding, you need to + * update the helper functions in stm32f2/dma.c. + */ +#define _DMA_STM32F2_REQ_SRC(stream_mask, clk_id, channel) \ + (((stream_mask) << 10) | ((clk_id) << 3) | (channel)) +#define _DMA_S(n) (1U << (n)) + + /* DMA1 request sources */ +#define _DMA_1_REQ_SRC(stream_mask, channel) \ + _DMA_STM32F2_REQ_SRC(stream_mask, RCC_DMA1, channel) + + /* Channel 0 */ + DMA_REQ_SRC_SPI3_RX = _DMA_1_REQ_SRC(_DMA_S(0) | _DMA_S(2), 0), + DMA_REQ_SRC_SPI2_RX = _DMA_1_REQ_SRC(_DMA_S(3), 0), + DMA_REQ_SRC_SPI2_TX = _DMA_1_REQ_SRC(_DMA_S(4), 0), + DMA_REQ_SRC_SPI3_TX = _DMA_1_REQ_SRC(_DMA_S(5) | _DMA_S(7), 0), + + /* Channel 1 */ + DMA_REQ_SRC_I2C1_RX = _DMA_1_REQ_SRC(_DMA_S(0) | _DMA_S(5), 1), + DMA_REQ_SRC_TIM7_UP = _DMA_1_REQ_SRC(_DMA_S(2) | _DMA_S(4), 1), + DMA_REQ_SRC_I2C1_TX = _DMA_1_REQ_SRC(_DMA_S(6) | _DMA_S(7), 1), + + /* Channel 2 */ + DMA_REQ_SRC_TIM4_CH1 = _DMA_1_REQ_SRC(_DMA_S(0), 2), + DMA_REQ_SRC_TIM4_CH2 = _DMA_1_REQ_SRC(_DMA_S(3), 2), + DMA_REQ_SRC_TIM4_UP = _DMA_1_REQ_SRC(_DMA_S(6), 2), + DMA_REQ_SRC_TIM4_CH3 = _DMA_1_REQ_SRC(_DMA_S(7), 2), + + /* Channel 3 */ + DMA_REQ_SRC_TIM2_UP = _DMA_1_REQ_SRC(_DMA_S(1) | _DMA_S(7), 3), + DMA_REQ_SRC_TIM2_CH3 = _DMA_1_REQ_SRC(_DMA_S(1), 3), + DMA_REQ_SRC_I2C3_RX = _DMA_1_REQ_SRC(_DMA_S(2), 3), + DMA_REQ_SRC_I2C3_TX = _DMA_1_REQ_SRC(_DMA_S(4), 3), + DMA_REQ_SRC_TIM2_CH1 = _DMA_1_REQ_SRC(_DMA_S(5), 3), + DMA_REQ_SRC_TIM2_CH2 = _DMA_1_REQ_SRC(_DMA_S(6), 3), + DMA_REQ_SRC_TIM2_CH4 = _DMA_1_REQ_SRC(_DMA_S(6) | _DMA_S(7), 3), + + /* Channel 4 */ + DMA_REQ_SRC_UART5_RX = _DMA_1_REQ_SRC(_DMA_S(0), 4), + DMA_REQ_SRC_USART3_RX = _DMA_1_REQ_SRC(_DMA_S(1), 4), + DMA_REQ_SRC_UART4_RX = _DMA_1_REQ_SRC(_DMA_S(2), 4), + DMA_REQ_SRC_USART3_TX = _DMA_1_REQ_SRC(_DMA_S(3), 4), + DMA_REQ_SRC_UART4_TX = _DMA_1_REQ_SRC(_DMA_S(4), 4), + DMA_REQ_SRC_USART2_RX = _DMA_1_REQ_SRC(_DMA_S(5), 4), + DMA_REQ_SRC_USART2_TX = _DMA_1_REQ_SRC(_DMA_S(6), 4), + DMA_REQ_SRC_UART5_TX = _DMA_1_REQ_SRC(_DMA_S(7), 4), + + /* Channel 5 */ + DMA_REQ_SRC_TIM3_CH4 = _DMA_1_REQ_SRC(_DMA_S(2), 5), + DMA_REQ_SRC_TIM3_UP = _DMA_1_REQ_SRC(_DMA_S(2), 5), + DMA_REQ_SRC_TIM3_CH1 = _DMA_1_REQ_SRC(_DMA_S(4), 5), + DMA_REQ_SRC_TIM3_TRIG = _DMA_1_REQ_SRC(_DMA_S(4), 5), + DMA_REQ_SRC_TIM3_CH2 = _DMA_1_REQ_SRC(_DMA_S(5), 5), + DMA_REQ_SRC_TIM3_CH3 = _DMA_1_REQ_SRC(_DMA_S(7), 5), + + /* Channel 6 */ + DMA_REQ_SRC_TIM5_CH3 = _DMA_1_REQ_SRC(_DMA_S(0), 6), + DMA_REQ_SRC_TIM5_UP = _DMA_1_REQ_SRC(_DMA_S(0) | _DMA_S(6), 6), + DMA_REQ_SRC_TIM5_CH4 = _DMA_1_REQ_SRC(_DMA_S(1) | _DMA_S(3), 6), + DMA_REQ_SRC_TIM5_TRIG = _DMA_1_REQ_SRC(_DMA_S(1) | _DMA_S(3), 6), + DMA_REQ_SRC_TIM5_CH1 = _DMA_1_REQ_SRC(_DMA_S(2), 6), + DMA_REQ_SRC_TIM5_CH2 = _DMA_1_REQ_SRC(_DMA_S(4), 6), + + /* Channel 7 */ + DMA_REQ_SRC_TIM6_UP = _DMA_1_REQ_SRC(_DMA_S(1), 7), + DMA_REQ_SRC_I2C2_RX = _DMA_1_REQ_SRC(_DMA_S(2) | _DMA_S(3), 7), + DMA_REQ_SRC_USART3_TX_ALTERNATE = _DMA_1_REQ_SRC(_DMA_S(4), 7), + DMA_REQ_SRC_DAC1 = _DMA_1_REQ_SRC(_DMA_S(5), 7), + DMA_REQ_SRC_DAC2 = _DMA_1_REQ_SRC(_DMA_S(6), 7), + DMA_REQ_SRC_I2C2_TX = _DMA_1_REQ_SRC(_DMA_S(7), 7), +#undef _DMA_1_REQ_SRC + + /* DMA2 request sources */ +#define _DMA_2_REQ_SRC(stream_mask, channel) \ + _DMA_STM32F2_REQ_SRC(stream_mask, RCC_DMA2, channel) + + /* Channel 0 */ + DMA_REQ_SRC_ADC1 = _DMA_2_REQ_SRC(_DMA_S(0) | _DMA_S(4), 0), + /* You can use these "DMA_REQ_SRC_TIMx_CHx_ALTERNATE" if you know + * what you're doing, but the other ones (for channels 6 and 7), + * are better, in that they don't conflict with one another. */ + DMA_REQ_SRC_TIM8_CH1_ALTERNATE = _DMA_2_REQ_SRC(_DMA_S(2), 0), + DMA_REQ_SRC_TIM8_CH2_ALTERNATE = _DMA_2_REQ_SRC(_DMA_S(2), 0), + DMA_REQ_SRC_TIM8_CH3_ALTERNATE = _DMA_2_REQ_SRC(_DMA_S(2), 0), + DMA_REQ_SRC_TIM1_CH1_ALTERNATE = _DMA_2_REQ_SRC(_DMA_S(6), 0), + DMA_REQ_SRC_TIM1_CH2_ALTERNATE = _DMA_2_REQ_SRC(_DMA_S(6), 0), + DMA_REQ_SRC_TIM1_CH3_ALTENRATE = _DMA_2_REQ_SRC(_DMA_S(6), 0), + + /* Channel 1 */ + DMA_REQ_SRC_DCMI = _DMA_2_REQ_SRC(_DMA_S(1) | _DMA_S(7), 1), + DMA_REQ_SRC_ADC2 = _DMA_2_REQ_SRC(_DMA_S(2) | _DMA_S(3), 1), + + /* Channel 2 */ + DMA_REQ_SRC_ADC3 = _DMA_2_REQ_SRC(_DMA_S(0) | _DMA_S(1), 2), + DMA_REQ_SRC_CRYP_OUT = _DMA_2_REQ_SRC(_DMA_S(5), 2), + DMA_REQ_SRC_CRYP_IN = _DMA_2_REQ_SRC(_DMA_S(6), 2), + DMA_REQ_SRC_HASH_IN = _DMA_2_REQ_SRC(_DMA_S(7), 2), + + /* Channel 3 */ + DMA_REQ_SRC_SPI1_RX = _DMA_2_REQ_SRC(_DMA_S(0) | _DMA_S(2), 3), + DMA_REQ_SRC_SPI1_TX = _DMA_2_REQ_SRC(_DMA_S(3) | _DMA_S(5), 3), + + /* Channel 4 */ + DMA_REQ_SRC_USART1_RX = _DMA_2_REQ_SRC(_DMA_S(2) | _DMA_S(5), 4), + DMA_REQ_SRC_SDIO = _DMA_2_REQ_SRC(_DMA_S(3) | _DMA_S(6), 4), + DMA_REQ_SRC_USART1_TX = _DMA_2_REQ_SRC(_DMA_S(7), 4), + + /* Channel 5 */ + DMA_REQ_SRC_USART6_RX = _DMA_2_REQ_SRC(_DMA_S(1) | _DMA_S(2), 5), + DMA_REQ_SRC_USART6_TX = _DMA_2_REQ_SRC(_DMA_S(6) | _DMA_S(7), 5), + + /* Channel 6 */ + DMA_REQ_SRC_TIM1_TRIG = _DMA_2_REQ_SRC(_DMA_S(0) | _DMA_S(4), 6), + DMA_REQ_SRC_TIM1_CH1 = _DMA_2_REQ_SRC(_DMA_S(1) | _DMA_S(3), 6), + DMA_REQ_SRC_TIM1_CH2 = _DMA_2_REQ_SRC(_DMA_S(3), 6), + DMA_REQ_SRC_TIM1_CH4 = _DMA_2_REQ_SRC(_DMA_S(4), 6), + DMA_REQ_SRC_TIM1_COM = _DMA_2_REQ_SRC(_DMA_S(4), 6), + DMA_REQ_SRC_TIM1_UP = _DMA_2_REQ_SRC(_DMA_S(5), 6), + DMA_REQ_SRC_TIM1_CH3 = _DMA_2_REQ_SRC(_DMA_S(6), 6), + + /* Channel 7 */ + DMA_REQ_SRC_TIM8_UP = _DMA_2_REQ_SRC(_DMA_S(1), 7), + DMA_REQ_SRC_TIM8_CH1 = _DMA_2_REQ_SRC(_DMA_S(2), 7), + DMA_REQ_SRC_TIM8_CH2 = _DMA_2_REQ_SRC(_DMA_S(3), 7), + DMA_REQ_SRC_TIM8_CH3 = _DMA_2_REQ_SRC(_DMA_S(4), 7), + DMA_REQ_SRC_TIM8_CH4 = _DMA_2_REQ_SRC(_DMA_S(7), 7), + DMA_REQ_SRC_TIM8_TRIG = _DMA_2_REQ_SRC(_DMA_S(7), 7), + DMA_REQ_SRC_TIM8_COM = _DMA_2_REQ_SRC(_DMA_S(7), 7), +#undef _DMA_2_REQ_SRC +#undef _DMA_S +} dma_request_src; + +/* + * Tube conveniences + */ + +static inline dma_tube_reg_map* dma_tube_regs(dma_dev *dev, + dma_tube tube) { + ASSERT(DMA_S0 <= tube && tube <= DMA_S7); + switch (dev->clk_id) { + case RCC_DMA1: + return DMA1S0_BASE + (int)tube; + case RCC_DMA2: + return DMA2S0_BASE + (int)tube; + default: + /* Can't happen */ + ASSERT(0); + return 0; + } +} + +static inline uint8 dma_is_enabled(dma_dev *dev, dma_tube tube) { + return dma_tube_regs(dev, tube)->SCR & DMA_SCR_EN; +} + +/* F2-only; available because of double-buffering. */ +void dma_set_mem_n_addr(dma_dev *dev, dma_tube tube, int n, + __io void *address); + +/** + * @brief Set memory 0 address. + * Availability: STM32F2. + * + * @param dev DMA device + * @param tube Tube whose memory 0 address to set + * @param addr Address to use as memory 0 + */ +static inline __always_inline void +dma_set_mem0_addr(dma_dev *dev, dma_tube tube, __io void *addr) { + dma_set_mem_n_addr(dev, tube, 0, addr); +} + +/** + * @brief Set memory 1 address. + * Availability: STM32F2. + * + * @param dev DMA device + * @param tube Tube whose memory 1 address to set + * @param addr Address to use as memory 1 + */ +static inline __always_inline void +dma_set_mem1_addr(dma_dev *dev, dma_tube tube, __io void *addr) { + dma_set_mem_n_addr(dev, tube, 1, addr); +} + +/* Assume the user means SM0AR in a non-double-buffered configuration. */ +static inline __always_inline void +dma_set_mem_addr(dma_dev *dev, dma_tube tube, __io void *addr) { + dma_set_mem0_addr(dev, tube, addr); +} + +/* SM0AR and SM1AR are treated as though they have the same size */ +static inline dma_xfer_size dma_get_mem_size(dma_dev *dev, dma_tube tube) { + return (dma_xfer_size)(dma_tube_regs(dev, tube)->SCR >> 13); +} + +static inline dma_xfer_size dma_get_per_size(dma_dev *dev, dma_tube tube) { + return (dma_xfer_size)(dma_tube_regs(dev, tube)->SCR >> 11); +} + +void dma_enable_fifo(dma_dev *dev, dma_tube tube); +void dma_disable_fifo(dma_dev *dev, dma_tube tube); + +static inline __always_inline int dma_is_fifo_enabled(dma_dev *dev, dma_tube tube) { + return dma_tube_regs(dev, tube)->SFCR & DMA_SFCR_DMDIS; +} + +/* + * TODO: + * - Double-buffer configuration function + * - FIFO configuration function + * - MBURST/PBURST configuration function + */ + +/* + * ISR/IFCR conveniences. + */ + +/* (undocumented) helper for reading LISR/HISR and writing + * LIFCR/HIFCR. For these registers, + * + * S0, S4: bits start at bit 0 + * S1, S5: 6 + * S2, S6: 16 + * S3, S7: 22 + * + * I can't imagine why ST didn't just use a byte for each group. The + * bits fit, and it would have made functions like these simpler and + * faster. Oh well. */ +static inline __always_inline uint32 _dma_sr_fcr_shift(dma_tube tube) { + switch (tube) { + case DMA_S0: /* fall through */ + case DMA_S4: + return 0; + case DMA_S1: /* fall through */ + case DMA_S5: + return 6; + case DMA_S2: /* fall through */ + case DMA_S6: + return 16; + case DMA_S3: /* fall through */ + case DMA_S7: + return 22; + } + /* Can't happen */ + ASSERT(0); + return 0; +} + +static inline uint8 dma_get_isr_bits(dma_dev *dev, dma_tube tube) { + dma_reg_map *regs = dev->regs; + __io uint32 *isr = tube > DMA_S3 ? ®s->HISR : ®s->LISR; + return (*isr >> _dma_sr_fcr_shift(tube)) & 0x3D; +} + +static inline void dma_clear_isr_bits(dma_dev *dev, dma_tube tube) { + dma_reg_map *regs = dev->regs; + __io uint32 *ifcr = tube > DMA_S3 ? ®s->HIFCR : ®s->LIFCR; + *ifcr = (0x3D << _dma_sr_fcr_shift(tube)); +} + +#undef _DMA_IRQ_BIT_SHIFT + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/exti.h b/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/exti.h new file mode 100644 index 0000000..4643fcf --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/exti.h @@ -0,0 +1,46 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f1/include/series/exti.h + * @brief STM32F2 external interrupts + */ + +#ifndef _LIBMAPLE_STM32F2_EXTI_H_ +#define _LIBMAPLE_STM32F2_EXTI_H_ + +#ifdef __cpluspus +extern "C" { +#endif + +struct exti_reg_map; +#define EXTI_BASE ((struct exti_reg_map*)0x40013C00) + +#ifdef __cpluspus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/flash.h b/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/flash.h new file mode 100644 index 0000000..a3c3933 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/flash.h @@ -0,0 +1,202 @@ +/****************************************************************************** + * 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/stm32f2/include/series/flash.h + * @brief STM32F2 Flash header. + * + * Provides register map, base pointer, and register bit definitions + * for the Flash controller on the STM32F2 series, along with + * series-specific configuration values. + */ + +#ifndef _LIBMAPLE_STM32F2_FLASH_H_ +#define _LIBMAPLE_STM32F2_FLASH_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include + +/* + * Register map + */ + +/** @brief STM32F2 Flash register map type */ +typedef struct flash_reg_map { + __io uint32 ACR; /**< Access control register */ + __io uint32 KEYR; /**< Key register */ + __io uint32 OPTKEYR; /**< Option key register */ + __io uint32 SR; /**< Status register */ + __io uint32 CR; /**< Control register */ + __io uint32 OPTCR; /**< Option control register */ +} flash_reg_map; + +#define FLASH_BASE ((struct flash_reg_map*)0x40023C00) + +/* + * Register bit definitions + */ + +/* Access control register */ + +#define FLASH_ACR_DCRST_BIT 12 +#define FLASH_ACR_ICRST_BIT 11 +#define FLASH_ACR_DCEN_BIT 10 +#define FLASH_ACR_ICEN_BIT 9 +#define FLASH_ACR_PRFTEN_BIT 8 + +#define FLASH_ACR_DCRST (1U << FLASH_ACR_DCRST_BIT) +#define FLASH_ACR_ICRST (1U << FLASH_ACR_ICRST_BIT) +#define FLASH_ACR_DCEN (1U << FLASH_ACR_DCEN_BIT) +#define FLASH_ACR_ICEN (1U << FLASH_ACR_ICEN_BIT) +#define FLASH_ACR_PRFTEN (1U << FLASH_ACR_PRFTEN_BIT) +#define FLASH_ACR_LATENCY 0x7 +#define FLASH_ACR_LATENCY_0WS 0x0 +#define FLASH_ACR_LATENCY_1WS 0x1 +#define FLASH_ACR_LATENCY_2WS 0x2 +#define FLASH_ACR_LATENCY_3WS 0x3 +#define FLASH_ACR_LATENCY_4WS 0x4 +#define FLASH_ACR_LATENCY_5WS 0x5 +#define FLASH_ACR_LATENCY_6WS 0x6 +#define FLASH_ACR_LATENCY_7WS 0x7 + +/* Key register */ + +#define FLASH_KEYR_KEY1 0x45670123 +#define FLASH_KEYR_KEY2 0xCDEF89AB + +/* Option key register */ + +#define FLASH_OPTKEYR_OPTKEY1 0x08192A3B +#define FLASH_OPTKEYR_OPTKEY2 0x4C5D6E7F + +/* Status register */ + +#define FLASH_SR_BSY_BIT 16 +#define FLASH_SR_PGSERR_BIT 7 +#define FLASH_SR_PGPERR_BIT 6 +#define FLASH_SR_PGAERR_BIT 5 +#define FLASH_SR_WRPERR_BIT 4 +#define FLASH_SR_OPERR_BIT 1 +#define FLASH_SR_EOP_BIT 0 + +#define FLASH_SR_BSY (1U << FLASH_SR_BSY_BIT) +#define FLASH_SR_PGSERR (1U << FLASH_SR_PGSERR_BIT) +#define FLASH_SR_PGPERR (1U << FLASH_SR_PGPERR_BIT) +#define FLASH_SR_PGAERR (1U << FLASH_SR_PGAERR_BIT) +#define FLASH_SR_WRPERR (1U << FLASH_SR_WRPERR_BIT) +#define FLASH_SR_OPERR (1U << FLASH_SR_OPERR_BIT) +#define FLASH_SR_EOP (1U << FLASH_SR_EOP_BIT) + +/* Control register */ + +#define FLASH_CR_LOCK_BIT 31 +#define FLASH_CR_ERRIE_BIT 25 +#define FLASH_CR_EOPIE_BIT 24 +#define FLASH_CR_STRT_BIT 16 +#define FLASH_CR_MER_BIT 2 +#define FLASH_CR_SER_BIT 1 +#define FLASH_CR_PG_BIT 0 + +#define FLASH_CR_LOCK (1U << FLASH_CR_LOCK_BIT) +#define FLASH_CR_ERRIE (1U << FLASH_CR_ERRIE_BIT) +#define FLASH_CR_EOPIE (1U << FLASH_CR_EOPIE_BIT) +#define FLASH_CR_STRT (1U << FLASH_CR_STRT_BIT) + +#define FLASH_CR_PSIZE (0x3 << 8) +#define FLASH_CR_PSIZE_MUL8 (0x0 << 8) +#define FLASH_CR_PSIZE_MUL16 (0x1 << 8) +#define FLASH_CR_PSIZE_MUL32 (0x2 << 8) +#define FLASH_CR_PSIZE_MUL64 (0x3 << 8) + +#define FLASH_CR_SNB (0xF << 3) +#define FLASH_CR_SNB_0 (0x0 << 3) +#define FLASH_CR_SNB_1 (0x1 << 3) +#define FLASH_CR_SNB_2 (0x2 << 3) +#define FLASH_CR_SNB_3 (0x3 << 3) +#define FLASH_CR_SNB_4 (0x4 << 3) +#define FLASH_CR_SNB_5 (0x5 << 3) +#define FLASH_CR_SNB_6 (0x6 << 3) +#define FLASH_CR_SNB_7 (0x7 << 3) +#define FLASH_CR_SNB_8 (0x8 << 3) +#define FLASH_CR_SNB_9 (0x9 << 3) +#define FLASH_CR_SNB_10 (0xA << 3) +#define FLASH_CR_SNB_11 (0xB << 3) + +#define FLASH_CR_MER (1U << FLASH_CR_MER_BIT) +#define FLASH_CR_SER (1U << FLASH_CR_SER_BIT) +#define FLASH_CR_PG (1U << FLASH_CR_PG_BIT) + +/* Option control register */ + +#define FLASH_OPTCR_NRST_STDBY_BIT 7 +#define FLASH_OPTCR_NRST_STOP_BIT 6 +#define FLASH_OPTCR_WDG_SW_BIT 5 +#define FLASH_OPTCR_OPTSTRT_BIT 1 +#define FLASH_OPTCR_OPTLOCK_BIT 0 + +#define FLASH_OPTCR_NWRP (0x3FF << 16) + +/* Excluded: The many level 1 values */ +#define FLASH_OPTCR_RDP (0xFF << 8) +#define FLASH_OPTCR_RDP_LEVEL0 (0xAA << 8) +#define FLASH_OPTCR_RDP_LEVEL2 (0xCC << 8) + +#define FLASH_OPTCR_USER (0x7 << 5) +#define FLASH_OPTCR_nRST_STDBY (1U << FLASH_OPTCR_nRST_STDBY_BIT) +#define FLASH_OPTCR_nRST_STOP (1U << FLASH_OPTCR_nRST_STOP_BIT) +#define FLASH_OPTCR_WDG_SW (1U << FLASH_OPTCR_WDG_SW_BIT) + +#define FLASH_OPTCR_BOR_LEV (0x3 << 2) +#define FLASH_OPTCR_BOR_LEVEL3 (0x0 << 2) +#define FLASH_OPTCR_BOR_LEVEL2 (0x1 << 2) +#define FLASH_OPTCR_BOR_LEVEL1 (0x2 << 2) +#define FLASH_OPTCR_BOR_OFF (0x3 << 2) + +#define FLASH_OPTCR_OPTSTRT (1U << FLASH_OPTCR_OPTSTRT_BIT) +#define FLASH_OPTCR_OPTLOCK (1U << FLASH_OPTCR_OPTLOCK_BIT) + +/* + * Series-specific configuration values + */ + +/* Note that this value depends on a 2.7V--3.6V supply voltage */ +#define FLASH_SAFE_WAIT_STATES FLASH_WAIT_STATE_3 + +/* Flash memory features available via ACR. */ +enum { + FLASH_PREFETCH = 0x100, + FLASH_ICACHE = 0x200, + FLASH_DCACHE = 0x400, +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/gpio.h b/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/gpio.h new file mode 100644 index 0000000..4d0d98c --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/gpio.h @@ -0,0 +1,264 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011, 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. +*****************************************************************************/ + +/** + * @file libmaple/stm32f2/include/series/gpio.h + * @brief STM32F2 GPIO support. + */ + +#ifndef _LIBMAPLE_STM32F2_GPIO_H_ +#define _LIBMAPLE_STM32F2_GPIO_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include + +/* + * GPIO register maps and devices + */ + +/** GPIO register map type */ +typedef struct gpio_reg_map { + __io uint32 MODER; /**< Mode register */ + __io uint32 OTYPER; /**< Output type register */ + __io uint32 OSPEEDR; /**< Output speed register */ + __io uint32 PUPDR; /**< Pull-up/pull-down register */ + __io uint32 IDR; /**< Input data register */ + __io uint32 ODR; /**< Output data register */ + __io uint32 BSRR; /**< Bit set/reset register */ + __io uint32 LCKR; /**< Configuration lock register */ + __io uint32 AFRL; /**< Alternate function low register */ + __io uint32 AFRH; /**< Alternate function high register */ +} gpio_reg_map; + +/** GPIO port A register map base pointer */ +#define GPIOA_BASE ((struct gpio_reg_map*)0x40020000) +/** GPIO port B register map base pointer */ +#define GPIOB_BASE ((struct gpio_reg_map*)0x40020400) +/** GPIO port C register map base pointer */ +#define GPIOC_BASE ((struct gpio_reg_map*)0x40020800) +/** GPIO port D register map base pointer */ +#define GPIOD_BASE ((struct gpio_reg_map*)0x40020C00) +/** GPIO port E register map base pointer */ +#define GPIOE_BASE ((struct gpio_reg_map*)0x40021000) +/** GPIO port F register map base pointer */ +#define GPIOF_BASE ((struct gpio_reg_map*)0x40021400) +/** GPIO port G register map base pointer */ +#define GPIOG_BASE ((struct gpio_reg_map*)0x40021800) +/** GPIO port H register map base pointer */ +#define GPIOH_BASE ((struct gpio_reg_map*)0x40021C00) +/** GPIO port I register map base pointer */ +#define GPIOI_BASE ((struct gpio_reg_map*)0x40022000) + +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 + * + * Currently, we only provide masks to be used for shifting for some + * registers, rather than repeating the same values 16 times. + */ + +/* Mode register */ + +#define GPIO_MODER_INPUT 0x0 +#define GPIO_MODER_OUTPUT 0x1 +#define GPIO_MODER_AF 0x2 +#define GPIO_MODER_ANALOG 0x3 + +/* Output type register */ + +#define GPIO_OTYPER_PP 0x0 +#define GPIO_OTYPER_OD 0x1 + +/* Output speed register */ + +#define GPIO_OSPEEDR_LOW 0x0 +#define GPIO_OSPEEDR_MED 0x1 +#define GPIO_OSPEEDR_FAST 0x2 +#define GPIO_OSPEEDR_HIGH 0x3 + +/* Pull-up/pull-down register */ + +#define GPIO_PUPDR_NOPUPD 0x0 +#define GPIO_PUPDR_PU 0x1 +#define GPIO_PUPDR_PD 0x2 + +/* Alternate function register low */ + +#define GPIO_AFRL_AF0 (0xFU << 0) +#define GPIO_AFRL_AF1 (0xFU << 4) +#define GPIO_AFRL_AF2 (0xFU << 8) +#define GPIO_AFRL_AF3 (0xFU << 12) +#define GPIO_AFRL_AF4 (0xFU << 16) +#define GPIO_AFRL_AF5 (0xFU << 20) +#define GPIO_AFRL_AF6 (0xFU << 24) +#define GPIO_AFRL_AF7 (0xFU << 28) + +/* Alternate function register high */ + +#define GPIO_AFRH_AF8 (0xFU << 0) +#define GPIO_AFRH_AF9 (0xFU << 4) +#define GPIO_AFRH_AF10 (0xFU << 8) +#define GPIO_AFRH_AF11 (0xFU << 12) +#define GPIO_AFRH_AF12 (0xFU << 16) +#define GPIO_AFRH_AF13 (0xFU << 20) +#define GPIO_AFRH_AF14 (0xFU << 24) +#define GPIO_AFRH_AF15 (0xFU << 28) + +/* + * GPIO routines + */ + +/** + * @brief GPIO pin modes + */ +typedef enum gpio_pin_mode { + GPIO_MODE_INPUT = GPIO_MODER_INPUT, /**< Input mode */ + GPIO_MODE_OUTPUT = GPIO_MODER_OUTPUT, /**< Output mode */ + GPIO_MODE_AF = GPIO_MODER_AF, /**< Alternate function mode */ + GPIO_MODE_ANALOG = GPIO_MODER_ANALOG, /**< Analog mode */ +} gpio_pin_mode; + +/** + * @brief Additional flags to be used when setting a pin's mode. + * + * Beyond the basic modes (input, general purpose output, alternate + * function, and analog), there are three parameters that can affect a + * pin's mode: + * + * 1. Output type: push/pull or open-drain. This only has an effect + * for output modes. Choices are: GPIO_MODEF_TYPE_PP (the default) + * and GPIO_MODEF_TYPE_OD. + * + * 2. Output speed: specifies the frequency at which a pin changes + * state. This only has an effect for output modes. Choices are: + * GPIO_MODEF_SPEED_LOW (default), GPIO_MODEF_SPEED_MED, + * GPIO_MODEF_SPEED_FAST, and GPIO_MODEF_SPEED_HIGH. + * + * 3. Push/pull setting: All GPIO pins have weak pull-up and pull-down + * resistors that can be enabled when the pin's mode is + * set. Choices are: GPIO_MODEF_PUPD_NONE (default), + * GPIO_MODEF_PUPD_PU, and GPIO_MODEF_PUPD_PD. + */ +typedef enum gpio_mode_flags { + /* Output type in bit 0 */ + GPIO_MODEF_TYPE_PP = GPIO_OTYPER_PP, /**< Output push/pull (default). + Applies only when the mode + specifies output. */ + GPIO_MODEF_TYPE_OD = GPIO_OTYPER_OD, /**< Output open drain. + Applies only when the mode + specifies output. */ + + /* Speed in bits 2:1 */ + GPIO_MODEF_SPEED_LOW = GPIO_OSPEEDR_LOW << 1, /**< Low speed (default): + 2 MHz. */ + GPIO_MODEF_SPEED_MED = GPIO_OSPEEDR_MED << 1, /**< Medium speed: 25 MHz. */ + GPIO_MODEF_SPEED_FAST = GPIO_OSPEEDR_FAST << 1, /**< Fast speed: 50 MHz. */ + GPIO_MODEF_SPEED_HIGH = GPIO_OSPEEDR_HIGH << 1, /**< High speed: + 100 MHz on 30 pF, + 80 MHz on 15 pF. */ + + /* Pull-up/pull-down in bits 4:3 */ + GPIO_MODEF_PUPD_NONE = GPIO_PUPDR_NOPUPD << 3, /**< No pull-up/pull-down + (default). */ + GPIO_MODEF_PUPD_PU = GPIO_PUPDR_PU << 3, /**< Pull-up */ + GPIO_MODEF_PUPD_PD = GPIO_PUPDR_PD << 3, /**< Pull-down */ +} gpio_mode_flags; + +void gpio_set_modef(struct gpio_dev *dev, + uint8 bit, + gpio_pin_mode mode, + unsigned flags); + +/** + * @brief Set the mode of a GPIO pin. + * + * Calling this function is equivalent to calling gpio_set_modef(dev, + * pin, mode, GPIO_MODE_SPEED_HIGH). Note that this overrides the + * default speed. + * + * @param dev GPIO device. + * @param bit Bit on the device whose mode to set, 0--15. + * @param mode Mode to set the pin to. + */ +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); +} + +/** + * @brief GPIO alternate functions. + * Use these to select an alternate function for a pin. + * @see gpio_set_af() + */ +typedef enum gpio_af { + GPIO_AF_SYS = 0, /**< System. */ + GPIO_AF_TIM_1_2 = 1, /**< Timers 1 and 2. */ + GPIO_AF_TIM_3_4_5 = 2, /**< Timers 3, 4, and 5. */ + GPIO_AF_TIM_8_9_10_11 = 3, /**< Timers 8 through 11. */ + GPIO_AF_I2C = 4, /**< I2C 1, 2, and 3. */ + GPIO_AF_SPI_1_2 = 5, /**< SPI1, SPI2/I2S2. */ + GPIO_AF_SPI3 = 6, /**< SPI3/I2S3. */ + GPIO_AF_USART_1_2_3 = 7, /**< USART 1, 2, and 3. */ + GPIO_AF_USART_4_5_6 = 8, /**< UART 4 and 5, USART 6. */ + GPIO_AF_CAN_1_2_TIM_12_13_14 = 9, /**< + * CAN 1 and 2, timers 12, 13, and 14. */ + GPIO_AF_USB_OTG_FS_HS = 10, /**< USB OTG HS and FS. */ + GPIO_AF_ETH = 11, /**< Ethernet MII and RMII. */ + GPIO_AF_FSMC_SDIO_OTG_FS = 12, /**< FSMC, SDIO, and USB OTG FS. */ + GPIO_AF_DCMI = 13, /**< DCMI. */ + GPIO_AF_EVENTOUT = 15, /**< EVENTOUT. */ +} gpio_af; + +void gpio_set_af(struct gpio_dev *dev, uint8 bit, gpio_af af); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/nvic.h b/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/nvic.h new file mode 100644 index 0000000..dc03806 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/nvic.h @@ -0,0 +1,160 @@ +/****************************************************************************** + * 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/stm32f2/include/series/nvic.h + * @brief STM32F2 nested vectored interrupt controller (NVIC) header. + */ + +#ifndef _LIBMAPLE_STM32F2_NVIC_H_ +#define _LIBMAPLE_STM32F2_NVIC_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +/** + * @brief STM32F2 interrupt vector table interrupt numbers. + */ +typedef enum nvic_irq_num { + NVIC_NMI = -14, /**< Non-maskable interrupt */ + NVIC_HARDFAULT = -13, /**< Hard fault (all class of fault) */ + NVIC_MEM_MANAGE = -12, /**< Memory management */ + NVIC_BUS_FAULT = -11, /**< Bus fault: prefetch fault, memory + access fault. */ + NVIC_USAGE_FAULT = -10, /**< Usage fault: Undefined instruction + or illegal state. */ + NVIC_SVC = -5, /**< System service call via SWI + instruction */ + NVIC_DEBUG_MON = -4, /**< Debug monitor */ + NVIC_PEND_SVC = -2, /**< Pendable request for system + service */ + NVIC_SYSTICK = -1, /**< System tick timer */ + NVIC_WWDG = 0, /**< Window watchdog interrupt */ + NVIC_PVD = 1, /**< PVD through EXTI line detection */ + NVIC_TAMP_STAMP = 2, /**< Tamper and TimeStamp */ + NVIC_RTC_WKUP = 3, /**< Real-time clock wakeup */ + NVIC_FLASH = 4, /**< Flash */ + NVIC_RCC = 5, /**< Reset and clock control */ + NVIC_EXTI0 = 6, /**< EXTI line 0 */ + NVIC_EXTI1 = 7, /**< EXTI line 1 */ + NVIC_EXTI2 = 8, /**< EXTI line 2 */ + NVIC_EXTI3 = 9, /**< EXTI line 3 */ + NVIC_EXTI4 = 10, /**< EXTI line 4 */ + NVIC_DMA1_STREAM0 = 11, /**< DMA1 stream 0 */ + NVIC_DMA1_STREAM1 = 12, /**< DMA1 stream 1 */ + NVIC_DMA1_STREAM2 = 13, /**< DMA1 stream 2 */ + NVIC_DMA1_STREAM3 = 14, /**< DMA1 stream 3 */ + NVIC_DMA1_STREAM4 = 15, /**< DMA1 stream 4 */ + NVIC_DMA1_STREAM5 = 16, /**< DMA1 stream 5 */ + NVIC_DMA1_STREAM6 = 17, /**< DMA1 stream 6 */ + NVIC_ADC = 18, /**< ADC */ + NVIC_CAN1_TX = 19, /**< CAN1 TX */ + NVIC_CAN1_RX0 = 20, /**< CAN1 RX0 */ + NVIC_CAN1_RX1 = 21, /**< CAN1 RX1 */ + NVIC_CAN1_SCE = 22, /**< CAN1 SCE */ + NVIC_EXTI_9_5 = 23, /**< EXTI lines [9:5] */ + NVIC_TIMER1_BRK_TIMER9 = 24, /**< Timer 1 break and timer 9 */ + NVIC_TIMER1_UP_TIMER10 = 25, /**< Timer 1 update and timer 10 */ + NVIC_TIMER1_TRG_COM_TIMER11 = 26, /**< Timer 1 trigger and commutation and + timer 11.*/ + NVIC_TIMER1_CC = 27, /**< Timer 1 capture and compare */ + NVIC_TIMER2 = 28, /**< Timer 2 */ + NVIC_TIMER3 = 29, /**< Timer 3 */ + NVIC_TIMER4 = 30, /**< Timer 4 */ + NVIC_I2C1_EV = 31, /**< I2C1 event */ + NVIC_I2C1_ER = 32, /**< I2C2 error */ + NVIC_I2C2_EV = 33, /**< I2C2 event */ + NVIC_I2C2_ER = 34, /**< I2C2 error */ + NVIC_SPI1 = 35, /**< SPI1 */ + NVIC_SPI2 = 36, /**< SPI2 */ + NVIC_USART1 = 37, /**< USART1 */ + NVIC_USART2 = 38, /**< USART2 */ + NVIC_USART3 = 39, /**< USART3 */ + NVIC_EXTI_15_10 = 40, /**< EXTI lines [15:10] */ + NVIC_RTCALARM = 41, /**< RTC alarms A and B through EXTI */ + NVIC_OTG_FS_WKUP = 42, /**< USB on-the-go full-speed wakeup + through EXTI*/ + NVIC_TIMER8_BRK_TIMER12 = 43, /**< Timer 8 break and timer 12 */ + NVIC_TIMER8_UP_TIMER13 = 44, /**< Timer 8 update and timer 13 */ + NVIC_TIMER8_TRG_COM_TIMER14 = 45, /**< Timer 8 trigger and commutation and + timer 14 */ + NVIC_TIMER8_CC = 46, /**< Timer 8 capture and compare */ + NVIC_DMA1_STREAM7 = 47, /**< DMA1 stream 7 */ + NVIC_FSMC = 48, /**< FSMC */ + NVIC_SDIO = 49, /**< SDIO */ + NVIC_TIMER5 = 50, /**< Timer 5 */ + NVIC_SPI3 = 51, /**< SPI3 */ + NVIC_UART4 = 52, /**< UART4 */ + NVIC_UART5 = 53, /**< UART5 */ + NVIC_TIMER6_DAC = 54, /**< Timer 6 and DAC underrun */ + NVIC_TIMER7 = 55, /**< Timer 7 */ + NVIC_DMA2_STREAM0 = 56, /**< DMA2 stream 0 */ + NVIC_DMA2_STREAM1 = 57, /**< DMA2 stream 1 */ + NVIC_DMA2_STREAM2 = 58, /**< DMA2 stream 2 */ + NVIC_DMA2_STREAM3 = 59, /**< DMA2 stream 3 */ + NVIC_DMA2_STREAM4 = 60, /**< DMA2 stream 4 */ + NVIC_ETH = 61, /**< Ethernet */ + NVIC_ETH_WKUP = 62, /**< Ethernet wakeup through EXTI */ + NVIC_CAN2_TX = 63, /**< CAN2 TX */ + NVIC_CAN2_RX0 = 64, /**< CAN2 RX0 */ + NVIC_CAN2_RX1 = 65, /**< CAN2 RX1 */ + NVIC_CAN2_SCE = 66, /**< CAN2 SCE */ + NVIC_OTG_FS = 67, /**< USB on-the-go full-speed */ + NVIC_DMA2_STREAM5 = 68, /**< DMA2 stream 5 */ + NVIC_DMA2_STREAM6 = 69, /**< DMA2 stream 6 */ + NVIC_DMA2_STREAM7 = 70, /**< DMA2 stream 7 */ + NVIC_USART6 = 71, /**< USART6 */ + NVIC_I2C3_EV = 72, /**< I2C3 event */ + NVIC_I2C3_ER = 73, /**< I2C3 error */ + NVIC_OTG_HS_EP1_OUT = 74, /**< USB on-the-go high-speed + endpoint 1 OUT */ + NVIC_OTG_HS_EP1_IN = 75, /**< USB on-the-go high-speed + endpoint 1 IN */ + NVIC_OTG_HS_WKUP = 76, /**< USB on-the-go high-speed wakeup + through EXTI*/ + NVIC_OTG_HS = 77, /**< USB on-the-go high-speed */ + NVIC_DCMI = 78, /**< DCMI */ + NVIC_CRYP = 79, /**< Cryptographic processor */ + NVIC_HASH_RNG = 80, /**< Hash and random number + generation */ + + /* Fake enumerator values, for compatiblity with F1. + * TODO decide if this is actually a good idea. */ + NVIC_TIMER6 = NVIC_TIMER6_DAC, /**< For compatibility with STM32F1. */ +} nvic_irq_num; + +static inline void nvic_irq_disable_all(void) { + NVIC_BASE->ICER[0] = 0xFFFFFFFF; + NVIC_BASE->ICER[1] = 0xFFFFFFFF; + NVIC_BASE->ICER[2] = 0xFFFFFFFF; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/pwr.h b/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/pwr.h new file mode 100644 index 0000000..96353a4 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/pwr.h @@ -0,0 +1,73 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f2/include/series/pwr.h + * @author Marti Bolivar + * @brief STM32F2 Power control (PWR) support. + */ + +#ifndef _LIBMAPLE_STM32F2_PWR_H_ +#define _LIBMAPLE_STM32F2_PWR_H_ + +/* + * Additional register bits + */ + +/* Control register */ + +/** + * @brief Flash power down in stop mode bit. + * Availability: STM32F2 */ +#define PWR_CR_FPDS_BIT 9 +/** + * @brief Flash power down in stop mode. + * Availability: STM32F2 */ +#define PWR_CR_FPDS (1U << PWR_CR_FPDS_BIT) + +/* PVD level selection */ +#define PWR_CR_PLS_2_0V (0x0 << 5) +#define PWR_CR_PLS_2_1V (0x1 << 5) +#define PWR_CR_PLS_2_3V (0x2 << 5) +#define PWR_CR_PLS_2_5V (0x3 << 5) +#define PWR_CR_PLS_2_6V (0x4 << 5) +#define PWR_CR_PLS_2_7V (0x5 << 5) +#define PWR_CR_PLS_2_8V (0x6 << 5) +#define PWR_CR_PLS_2_9V (0x7 << 5) + +/* Control/Status register */ + +/** Backup regulator enable bit. */ +#define PWR_CSR_BRE_BIT 9 +/** Backup regulator ready bit. */ +#define PWR_CSR_BRR_BIT 3 + +/** Backup regulator enable. */ +#define PWR_CSR_BRE (1U << PWR_CSR_BRE_BIT) +/** Backup regulator ready. */ +#define PWR_CSR_BRR (1U << PWR_CSR_BRR_BIT) + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/rcc.h b/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/rcc.h new file mode 100644 index 0000000..441a5a8 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/rcc.h @@ -0,0 +1,951 @@ +/****************************************************************************** + * 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/stm32f2/include/series/rcc.h + * @brief STM32F2 reset and clock control (RCC) support. + */ + +#ifndef _LIBMAPLE_STM32F2_RCC_H_ +#define _LIBMAPLE_STM32F2_RCC_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include + +/* + * Register map + */ + +/** STM32F2 RCC register map type */ +typedef struct rcc_reg_map { + __io uint32 CR; /**< Clock control register */ + __io uint32 PLLCFGR; /**< PLL configuration register */ + __io uint32 CFGR; /**< Clock configuration register */ + __io uint32 CIR; /**< Clock interrupt register */ + __io uint32 AHB1RSTR; /**< AHB1 peripheral reset register */ + __io uint32 AHB2RSTR; /**< AHB2 peripheral reset register */ + __io uint32 AHB3RSTR; /**< AHB3 peripheral reset register */ + const uint32 RESERVED1; /**< Reserved */ + __io uint32 APB1RSTR; /**< APB1 peripheral reset register */ + __io uint32 APB2RSTR; /**< APB2 peripheral reset register */ + const uint32 RESERVED2; /**< Reserved */ + const uint32 RESERVED3; /**< Reserved */ + __io uint32 AHB1ENR; /**< AHB1 peripheral clock enable register */ + __io uint32 AHB2ENR; /**< AHB2 peripheral clock enable register */ + __io uint32 AHB3ENR; /**< AHB3 peripheral clock enable register */ + const uint32 RESERVED4; /**< Reserved */ + __io uint32 APB1ENR; /**< APB1 peripheral clock enable register */ + __io uint32 APB2ENR; /**< APB2 peripheral clock enable register */ + const uint32 RESERVED5; /**< Reserved */ + const uint32 RESERVED6; /**< Reserved */ + __io uint32 AHB1LPENR; /**< AHB1 peripheral clock enable in + low power mode register */ + __io uint32 AHB2LPENR; /**< AHB2 peripheral clock enable in + low power mode register */ + __io uint32 AHB3LPENR; /**< AHB3 peripheral clock enable in + low power mode register */ + const uint32 RESERVED7; /**< Reserved */ + __io uint32 APB1LPENR; /**< APB1 peripheral clock enable in + low power mode register */ + __io uint32 APB2LPENR; /**< APB2 peripheral clock enable in + low power mode register */ + const uint32 RESERVED8; /**< Reserved */ + const uint32 RESERVED9; /**< Reserved */ + __io uint32 BDCR; /**< Backup domain control register */ + __io uint32 CSR; /**< Clock control and status register */ + const uint32 RESERVED10; /**< Reserved */ + const uint32 RESERVED11; /**< Reserved */ + __io uint32 SSCGR; /**< Spread spectrum clock generation + register */ + __io uint32 PLLI2SCFGR; /**< PLLI2S configuration register */ +} rcc_reg_map; + +#define RCC_BASE ((struct rcc_reg_map*)0x40023800) + +/* + * Register bit definitions + */ + +/* Clock control register */ + +#define RCC_CR_PLLI2SRDY_BIT 27 +#define RCC_CR_PLLI2SON_BIT 26 +#define RCC_CR_PLLRDY_BIT 25 +#define RCC_CR_PLLON_BIT 24 +#define RCC_CR_CSSON_BIT 19 +#define RCC_CR_HSEBYP_BIT 18 +#define RCC_CR_HSERDY_BIT 17 +#define RCC_CR_HSEON_BIT 16 +#define RCC_CR_HSIRDY_BIT 1 +#define RCC_CR_HSION_BIT 0 + +#define RCC_CR_PLLI2SRDY (1U << RCC_CR_PLLI2SRDY_BIT) +#define RCC_CR_PLLI2SON (1U << RCC_CR_PLLI2SON_BIT) +#define RCC_CR_PLLRDY (1U << RCC_CR_PLLRDY_BIT) +#define RCC_CR_PLLON (1U << RCC_CR_PLLON_BIT) +#define RCC_CR_CSSON (1U << RCC_CR_CSSON_BIT) +#define RCC_CR_HSEBYP (1U << RCC_CR_HSEBYP_BIT) +#define RCC_CR_HSERDY (1U << RCC_CR_HSERDY_BIT) +#define RCC_CR_HSEON (1U << RCC_CR_HSEON_BIT) +#define RCC_CR_HSICAL (0xFF << 8) +#define RCC_CR_HSITRIM (0x1F << 3) +#define RCC_CR_HSIRDY (1U << RCC_CR_HSIRDY_BIT) +#define RCC_CR_HSION (1U << RCC_CR_HSION_BIT) + +/* PLL configuration register */ + +#define RCC_PLLCFGR_PLLSRC_BIT 22 + +#define RCC_PLLCFGR_PLLQ (0xF << 24) +#define RCC_PLLCFGR_PLLSRC (1U << RCC_PLLCFGR_PLLSRC_BIT) +#define RCC_PLLCFGR_PLLSRC_HSI (0x0 << RCC_PLLCFGR_PLLSRC_BIT) +#define RCC_PLLCFGR_PLLSRC_HSE (0x1 << RCC_PLLCFGR_PLLSRC_BIT) +#define RCC_PLLCFGR_PLLP (0x3 << 16) +#define RCC_PLLCFGR_PLLN (0x1FF << 6) +#define RCC_PLLCFGR_PLLM 0x1F + +/* Clock configuration register */ + +#define RCC_CFGR_I2SSRC_BIT 23 + +#define RCC_CFGR_MCO2 (0x3 << 30) +#define RCC_CFGR_MCO2_SYSCLK (0x0 << 30) +#define RCC_CFGR_MCO2_PLLI2S (0x1 << 30) +#define RCC_CFGR_MCO2_HSE (0x2 << 30) +#define RCC_CFGR_MCO2_PLL (0x3 << 30) + +#define RCC_CFGR_MCO2PRE (0x7 << 27) +#define RCC_CFGR_MCO2PRE_DIV_1 (0x0 << 27) +#define RCC_CFGR_MCO2PRE_DIV_2 (0x4 << 27) +#define RCC_CFGR_MCO2PRE_DIV_3 (0x5 << 27) +#define RCC_CFGR_MCO2PRE_DIV_4 (0x6 << 27) +#define RCC_CFGR_MCO2PRE_DIV_5 (0x7 << 27) + +#define RCC_CFGR_MCO1PRE (0x7 << 24) +#define RCC_CFGR_MCO1PRE_DIV_1 (0x0 << 24) +#define RCC_CFGR_MCO1PRE_DIV_2 (0x4 << 24) +#define RCC_CFGR_MCO1PRE_DIV_3 (0x5 << 24) +#define RCC_CFGR_MCO1PRE_DIV_4 (0x6 << 24) +#define RCC_CFGR_MCO1PRE_DIV_5 (0x7 << 24) + +#define RCC_CFGR_I2SSRC (1U << RCC_CFGR_I2SSRC_BIT) +#define RCC_CFGR_I2SSRC_PLLI2S (0 << RCC_CFGR_I2SSRC_BIT) +#define RCC_CFGR_I2SSRC_I2S_CKIN (1 << RCC_CFGR_I2SSRC_BIT) + +#define RCC_CFGR_MCO1 (0x3 << 21) +#define RCC_CFGR_MCO1_HSI (0x0 << 21) +#define RCC_CFGR_MCO1_LSE (0x1 << 21) +#define RCC_CFGR_MCO1_HSE (0x2 << 21) +#define RCC_CFGR_MCO1_PLL (0x3 << 21) + +#define RCC_CFGR_RTCPRE (0x1F << 16) + +/* Skipped: all the 0b0xx values meaning "not divided" */ +#define RCC_CFGR_PPRE2 (0x7 << 13) +#define RCC_CFGR_PPRE2_AHB_DIV_2 (0x4 << 13) +#define RCC_CFGR_PPRE2_AHB_DIV_4 (0x5 << 13) +#define RCC_CFGR_PPRE2_AHB_DIV_8 (0x6 << 13) +#define RCC_CFGR_PPRE2_AHB_DIV_16 (0x7 << 13) + +/* Skipped: all the 0b0xx values meaning "not divided" */ +#define RCC_CFGR_PPRE1 (0x7 << 10) +#define RCC_CFGR_PPRE1_AHB_DIV_2 (0x4 << 10) +#define RCC_CFGR_PPRE1_AHB_DIV_4 (0x5 << 10) +#define RCC_CFGR_PPRE1_AHB_DIV_8 (0x6 << 10) +#define RCC_CFGR_PPRE1_AHB_DIV_16 (0x7 << 10) + +/* Skipped: all the 0b0xxx values meaning "not divided" */ +#define RCC_CFGR_HPRE (0xF << 4) +#define RCC_CFGR_HPRE_SYSCLK_DIV_2 (0x8 << 4) +#define RCC_CFGR_HPRE_SYSCLK_DIV_4 (0x9 << 4) +#define RCC_CFGR_HPRE_SYSCLK_DIV_8 (0xA << 4) +#define RCC_CFGR_HPRE_SYSCLK_DIV_16 (0xB << 4) +#define RCC_CFGR_HPRE_SYSCLK_DIV_64 (0xC << 4) +#define RCC_CFGR_HPRE_SYSCLK_DIV_128 (0xD << 4) +#define RCC_CFGR_HPRE_SYSCLK_DIV_256 (0xE << 4) +#define RCC_CFGR_HPRE_SYSCLK_DIV_512 (0xF << 4) + +#define RCC_CFGR_SWS (0x3 << 2) +#define RCC_CFGR_SWS_HSI (0x0 << 2) +#define RCC_CFGR_SWS_HSE (0x1 << 2) +#define RCC_CFGR_SWS_PLL (0x2 << 2) + +#define RCC_CFGR_SW 0x3 +#define RCC_CFGR_SW_HSI 0x0 +#define RCC_CFGR_SW_HSE 0x1 +#define RCC_CFGR_SW_PLL 0x2 + +/* Clock interrupt register */ + +#define RCC_CIR_CSSC_BIT 23 + +#define RCC_CIR_PLLI2SRDYC_BIT 21 +#define RCC_CIR_PLLRDYC_BIT 20 +#define RCC_CIR_HSERDYC_BIT 19 +#define RCC_CIR_HSIRDYC_BIT 18 +#define RCC_CIR_LSERDYC_BIT 17 +#define RCC_CIR_LSIRDYC_BIT 16 + +#define RCC_CIR_PLLI2SRDYIE_BIT 13 +#define RCC_CIR_PLLRDYIE_BIT 12 +#define RCC_CIR_HSERDYIE_BIT 11 +#define RCC_CIR_HSIRDYIE_BIT 10 +#define RCC_CIR_LSERDYIE_BIT 9 +#define RCC_CIR_LSIRDYIE_BIT 8 + +#define RCC_CIR_CSSF_BIT 7 + +#define RCC_CIR_PLLI2SRDYF_BIT 5 +#define RCC_CIR_PLLRDYF_BIT 4 +#define RCC_CIR_HSERDYF_BIT 3 +#define RCC_CIR_HSIRDYF_BIT 2 +#define RCC_CIR_LSERDYF_BIT 1 +#define RCC_CIR_LSIRDYF_BIT 0 + +#define RCC_CIR_CSSC (1U << RCC_CIR_CSSC_BIT) + +#define RCC_CIR_PLLI2SRDYC (1U << RCC_CIR_PLLI2SRDYC_BIT) +#define RCC_CIR_PLLRDYC (1U << RCC_CIR_PLLRDYC_BIT) +#define RCC_CIR_HSERDYC (1U << RCC_CIR_HSERDYC_BIT) +#define RCC_CIR_HSIRDYC (1U << RCC_CIR_HSIRDYC_BIT) +#define RCC_CIR_LSERDYC (1U << RCC_CIR_LSERDYC_BIT) +#define RCC_CIR_LSIRDYC (1U << RCC_CIR_LSIRDYC_BIT) + +#define RCC_CIR_PLLI2SRDYIE (1U << RCC_CIR_PLLI2SRDYIE_BIT) +#define RCC_CIR_PLLRDYIE (1U << RCC_CIR_PLLRDYIE_BIT) +#define RCC_CIR_HSERDYIE (1U << RCC_CIR_HSERDYIE_BIT) +#define RCC_CIR_HSIRDYIE (1U << RCC_CIR_HSIRDYIE_BIT) +#define RCC_CIR_LSERDYIE (1U << RCC_CIR_LSERDYIE_BIT) +#define RCC_CIR_LSIRDYIE (1U << RCC_CIR_LSIRDYIE_BIT) + +#define RCC_CIR_CSSF (1U << RCC_CIR_CSSF_BIT) + +#define RCC_CIR_PLLI2SRDYF (1U << RCC_CIR_PLLI2SRDYF_BIT) +#define RCC_CIR_PLLRDYF (1U << RCC_CIR_PLLRDYF_BIT) +#define RCC_CIR_HSERDYF (1U << RCC_CIR_HSERDYF_BIT) +#define RCC_CIR_HSIRDYF (1U << RCC_CIR_HSIRDYF_BIT) +#define RCC_CIR_LSERDYF (1U << RCC_CIR_LSERDYF_BIT) +#define RCC_CIR_LSIRDYF (1U << RCC_CIR_LSIRDYF_BIT) + +/* AHB1 peripheral reset register */ + +#define RCC_AHB1RSTR_OTGHSRST_BIT 29 +#define RCC_AHB1RSTR_ETHMACRST_BIT 25 +#define RCC_AHB1RSTR_DMA2RST_BIT 22 +#define RCC_AHB1RSTR_DMA1RST_BIT 21 +#define RCC_AHB1RSTR_CRCRST_BIT 12 +#define RCC_AHB1RSTR_GPIOIRST_BIT 8 +#define RCC_AHB1RSTR_GPIOHRST_BIT 7 +#define RCC_AHB1RSTR_GPIOGRST_BIT 6 +#define RCC_AHB1RSTR_GPIOFRST_BIT 5 +#define RCC_AHB1RSTR_GPIOERST_BIT 4 +#define RCC_AHB1RSTR_GPIODRST_BIT 3 +#define RCC_AHB1RSTR_GPIOCRST_BIT 2 +#define RCC_AHB1RSTR_GPIOBRST_BIT 1 +#define RCC_AHB1RSTR_GPIOARST_BIT 0 + +#define RCC_AHB1RSTR_OTGHSRST (1U << RCC_AHB1RSTR_OTGHSRST_BIT) +#define RCC_AHB1RSTR_ETHMACRST (1U << RCC_AHB1RSTR_ETHMACRST_BIT) +#define RCC_AHB1RSTR_DMA2RST (1U << RCC_AHB1RSTR_DMA2RST_BIT) +#define RCC_AHB1RSTR_DMA1RST (1U << RCC_AHB1RSTR_DMA1RST_BIT) +#define RCC_AHB1RSTR_CRCRST (1U << RCC_AHB1RSTR_CRCRST_BIT) +#define RCC_AHB1RSTR_GPIOIRST (1U << RCC_AHB1RSTR_GPIOIRST_BIT) +#define RCC_AHB1RSTR_GPIOHRST (1U << RCC_AHB1RSTR_GPIOHRST_BIT) +#define RCC_AHB1RSTR_GPIOGRST (1U << RCC_AHB1RSTR_GPIOGRST_BIT) +#define RCC_AHB1RSTR_GPIOFRST (1U << RCC_AHB1RSTR_GPIOFRST_BIT) +#define RCC_AHB1RSTR_GPIOERST (1U << RCC_AHB1RSTR_GPIOERST_BIT) +#define RCC_AHB1RSTR_GPIODRST (1U << RCC_AHB1RSTR_GPIODRST_BIT) +#define RCC_AHB1RSTR_GPIOCRST (1U << RCC_AHB1RSTR_GPIOCRST_BIT) +#define RCC_AHB1RSTR_GPIOBRST (1U << RCC_AHB1RSTR_GPIOBRST_BIT) +#define RCC_AHB1RSTR_GPIOARST (1U << RCC_AHB1RSTR_GPIOARST_BIT) + +/* AHB2 peripheral reset register */ + +#define RCC_AHB2RSTR_OTGFSRST_BIT 7 +#define RCC_AHB2RSTR_RNGRST_BIT 6 +#define RCC_AHB2RSTR_HASHRST_BIT 5 +#define RCC_AHB2RSTR_CRYPRST_BIT 4 +#define RCC_AHB2RSTR_DCMIRST_BIT 0 + +#define RCC_AHB2RSTR_OTGFSRST (1U << RCC_AHB2RSTR_OTGFSRST_BIT) +#define RCC_AHB2RSTR_RNGRST (1U << RCC_AHB2RSTR_RNGRST_BIT) +#define RCC_AHB2RSTR_HASHRST (1U << RCC_AHB2RSTR_HASHRST_BIT) +#define RCC_AHB2RSTR_CRYPRST (1U << RCC_AHB2RSTR_CRYPRST_BIT) +#define RCC_AHB2RSTR_DCMIRST (1U << RCC_AHB2RSTR_DCMIRST_BIT) + +/* AHB3 peripheral reset register */ + +#define RCC_AHB3RSTR_FSMCRST_BIT 0 + +#define RCC_AHB3RSTR_FSMCRST (1U << RCC_AHB3RSTR_FSMCRST_BIT) + +/* APB1 peripheral reset register */ + +#define RCC_APB1RSTR_DACRST_BIT 29 +#define RCC_APB1RSTR_PWRRST_BIT 28 +#define RCC_APB1RSTR_CAN2RST_BIT 26 +#define RCC_APB1RSTR_CAN1RST_BIT 25 +#define RCC_APB1RSTR_I2C3RST_BIT 23 +#define RCC_APB1RSTR_I2C2RST_BIT 22 +#define RCC_APB1RSTR_I2C1RST_BIT 21 +#define RCC_APB1RSTR_UART5RST_BIT 20 +#define RCC_APB1RSTR_UART4RST_BIT 19 +#define RCC_APB1RSTR_UART3RST_BIT 18 +#define RCC_APB1RSTR_UART2RST_BIT 17 +#define RCC_APB1RSTR_SPI3RST_BIT 15 +#define RCC_APB1RSTR_SPI2RST_BIT 14 +#define RCC_APB1RSTR_WWDGRST_BIT 11 +#define RCC_APB1RSTR_TIM14RST_BIT 8 +#define RCC_APB1RSTR_TIM13RST_BIT 7 +#define RCC_APB1RSTR_TIM12RST_BIT 6 +#define RCC_APB1RSTR_TIM7RST_BIT 5 +#define RCC_APB1RSTR_TIM6RST_BIT 4 +#define RCC_APB1RSTR_TIM5RST_BIT 3 +#define RCC_APB1RSTR_TIM4RST_BIT 2 +#define RCC_APB1RSTR_TIM3RST_BIT 1 +#define RCC_APB1RSTR_TIM2RST_BIT 0 + +#define RCC_APB1RSTR_DACRST (1U << RCC_APB1RSTR_DACRST_BIT) +#define RCC_APB1RSTR_PWRRST (1U << RCC_APB1RSTR_PWRRST_BIT) +#define RCC_APB1RSTR_CAN2RST (1U << RCC_APB1RSTR_CAN2RST_BIT) +#define RCC_APB1RSTR_CAN1RST (1U << RCC_APB1RSTR_CAN1RST_BIT) +#define RCC_APB1RSTR_I2C3RST (1U << RCC_APB1RSTR_I2C3RST_BIT) +#define RCC_APB1RSTR_I2C2RST (1U << RCC_APB1RSTR_I2C2RST_BIT) +#define RCC_APB1RSTR_I2C1RST (1U << RCC_APB1RSTR_I2C1RST_BIT) +#define RCC_APB1RSTR_UART5RST (1U << RCC_APB1RSTR_UART5RST_BIT) +#define RCC_APB1RSTR_UART4RST (1U << RCC_APB1RSTR_UART4RST_BIT) +#define RCC_APB1RSTR_UART3RST (1U << RCC_APB1RSTR_UART3RST_BIT) +#define RCC_APB1RSTR_UART2RST (1U << RCC_APB1RSTR_UART2RST_BIT) +#define RCC_APB1RSTR_SPI3RST (1U << RCC_APB1RSTR_SPI3RST_BIT) +#define RCC_APB1RSTR_SPI2RST (1U << RCC_APB1RSTR_SPI2RST_BIT) +#define RCC_APB1RSTR_WWDGRST (1U << RCC_APB1RSTR_WWDGRST_BIT) +#define RCC_APB1RSTR_TIM14RST (1U << RCC_APB1RSTR_TIM14RST_BIT) +#define RCC_APB1RSTR_TIM13RST (1U << RCC_APB1RSTR_TIM13RST_BIT) +#define RCC_APB1RSTR_TIM12RST (1U << RCC_APB1RSTR_TIM12RST_BIT) +#define RCC_APB1RSTR_TIM7RST (1U << RCC_APB1RSTR_TIM7RST_BIT) +#define RCC_APB1RSTR_TIM6RST (1U << RCC_APB1RSTR_TIM6RST_BIT) +#define RCC_APB1RSTR_TIM5RST (1U << RCC_APB1RSTR_TIM5RST_BIT) +#define RCC_APB1RSTR_TIM4RST (1U << RCC_APB1RSTR_TIM4RST_BIT) +#define RCC_APB1RSTR_TIM3RST (1U << RCC_APB1RSTR_TIM3RST_BIT) +#define RCC_APB1RSTR_TIM2RST (1U << RCC_APB1RSTR_TIM2RST_BIT) + +/* APB2 peripheral reset register */ + +#define RCC_APB2RSTR_TIM11RST_BIT 18 +#define RCC_APB2RSTR_TIM10RST_BIT 17 +#define RCC_APB2RSTR_TIM9RST_BIT 16 +#define RCC_APB2RSTR_SYSCFGRST_BIT 14 +#define RCC_APB2RSTR_SPI1RST_BIT 12 +#define RCC_APB2RSTR_SDIORST_BIT 11 +#define RCC_APB2RSTR_ADCRST_BIT 8 +#define RCC_APB2RSTR_USART6RST_BIT 5 +#define RCC_APB2RSTR_USART1RST_BIT 4 +#define RCC_APB2RSTR_TIM8RST_BIT 1 +#define RCC_APB2RSTR_TIM1RST_BIT 0 + +#define RCC_APB2RSTR_TIM11RST (1U << RCC_APB2RSTR_TIM11RST_BIT) +#define RCC_APB2RSTR_TIM10RST (1U << RCC_APB2RSTR_TIM10RST_BIT) +#define RCC_APB2RSTR_TIM9RST (1U << RCC_APB2RSTR_TIM9RST_BIT) +#define RCC_APB2RSTR_SYSCFGRST (1U << RCC_APB2RSTR_SYSCFGRST_BIT) +#define RCC_APB2RSTR_SPI1RST (1U << RCC_APB2RSTR_SPI1RST_BIT) +#define RCC_APB2RSTR_SDIORST (1U << RCC_APB2RSTR_SDIORST_BIT) +#define RCC_APB2RSTR_ADCRST (1U << RCC_APB2RSTR_ADCRST_BIT) +#define RCC_APB2RSTR_USART6RST (1U << RCC_APB2RSTR_USART6RST_BIT) +#define RCC_APB2RSTR_USART1RST (1U << RCC_APB2RSTR_USART1RST_BIT) +#define RCC_APB2RSTR_TIM8RST (1U << RCC_APB2RSTR_TIM8RST_BIT) +#define RCC_APB2RSTR_TIM1RST (1U << RCC_APB2RSTR_TIM1RST_BIT) + +/* AHB1 peripheral clock enable register */ + +#define RCC_AHB1ENR_OTGHSULPIEN_BIT 30 +#define RCC_AHB1ENR_OTGHSEN_BIT 29 +#define RCC_AHB1ENR_ETHMACPTPEN_BIT 28 +#define RCC_AHB1ENR_ETHMACRXEN_BIT 27 +#define RCC_AHB1ENR_ETHMACTXEN_BIT 26 +#define RCC_AHB1ENR_ETHMACEN_BIT 25 +#define RCC_AHB1ENR_DMA2EN_BIT 22 +#define RCC_AHB1ENR_DMA1EN_BIT 21 +#define RCC_AHB1ENR_BKPSRAMEN_BIT 18 +#define RCC_AHB1ENR_CRCEN_BIT 12 +#define RCC_AHB1ENR_GPIOIEN_BIT 8 +#define RCC_AHB1ENR_GPIOHEN_BIT 7 +#define RCC_AHB1ENR_GPIOGEN_BIT 6 +#define RCC_AHB1ENR_GPIOFEN_BIT 5 +#define RCC_AHB1ENR_GPIOEEN_BIT 4 +#define RCC_AHB1ENR_GPIODEN_BIT 3 +#define RCC_AHB1ENR_GPIOCEN_BIT 2 +#define RCC_AHB1ENR_GPIOBEN_BIT 1 +#define RCC_AHB1ENR_GPIOAEN_BIT 0 + +#define RCC_AHB1ENR_OTGHSULPIEN (1U << RCC_AHB1ENR_OTGHSULPIEN_BIT) +#define RCC_AHB1ENR_OTGHSEN (1U << RCC_AHB1ENR_OTGHSEN_BIT) +#define RCC_AHB1ENR_ETHMACPTPEN (1U << RCC_AHB1ENR_ETHMACPTPEN_BIT) +#define RCC_AHB1ENR_ETHMACRXEN (1U << RCC_AHB1ENR_ETHMACRXEN_BIT) +#define RCC_AHB1ENR_ETHMACTXEN (1U << RCC_AHB1ENR_ETHMACTXEN_BIT) +#define RCC_AHB1ENR_ETHMACEN (1U << RCC_AHB1ENR_ETHMACEN_BIT) +#define RCC_AHB1ENR_DMA2EN (1U << RCC_AHB1ENR_DMA2EN_BIT) +#define RCC_AHB1ENR_DMA1EN (1U << RCC_AHB1ENR_DMA1EN_BIT) +#define RCC_AHB1ENR_BKPSRAMEN (1U << RCC_AHB1ENR_BKPSRAMEN_BIT) +#define RCC_AHB1ENR_CRCEN (1U << RCC_AHB1ENR_CRCEN_BIT) +#define RCC_AHB1ENR_GPIOIEN (1U << RCC_AHB1ENR_GPIOIEN_BIT) +#define RCC_AHB1ENR_GPIOHEN (1U << RCC_AHB1ENR_GPIOHEN_BIT) +#define RCC_AHB1ENR_GPIOGEN (1U << RCC_AHB1ENR_GPIOGEN_BIT) +#define RCC_AHB1ENR_GPIOFEN (1U << RCC_AHB1ENR_GPIOFEN_BIT) +#define RCC_AHB1ENR_GPIOEEN (1U << RCC_AHB1ENR_GPIOEEN_BIT) +#define RCC_AHB1ENR_GPIODEN (1U << RCC_AHB1ENR_GPIODEN_BIT) +#define RCC_AHB1ENR_GPIOCEN (1U << RCC_AHB1ENR_GPIOCEN_BIT) +#define RCC_AHB1ENR_GPIOBEN (1U << RCC_AHB1ENR_GPIOBEN_BIT) +#define RCC_AHB1ENR_GPIOAEN (1U << RCC_AHB1ENR_GPIOAEN_BIT) + +/* AHB2 peripheral clock enable register */ + +#define RCC_AHB2ENR_OTGFSEN_BIT 7 +#define RCC_AHB2ENR_RNGEN_BIT 6 +#define RCC_AHB2ENR_HASHEN_BIT 5 +#define RCC_AHB2ENR_CRYPEN_BIT 4 +#define RCC_AHB2ENR_DCMIEN_BIT 0 + +#define RCC_AHB2ENR_OTGFSEN (1U << RCC_AHB2ENR_OTGFSEN_BIT) +#define RCC_AHB2ENR_RNGEN (1U << RCC_AHB2ENR_RNGEN_BIT) +#define RCC_AHB2ENR_HASHEN (1U << RCC_AHB2ENR_HASHEN_BIT) +#define RCC_AHB2ENR_CRYPEN (1U << RCC_AHB2ENR_CRYPEN_BIT) +#define RCC_AHB2ENR_DCMIEN (1U << RCC_AHB2ENR_DCMIEN_BIT) + +/* AHB3 peripheral clock enable register */ + +#define RCC_AHB3ENR_FSMCEN_BIT 0 + +#define RCC_AHB3ENR_FSMCEN (1U << RCC_AHB3ENR_FSMCEN_BIT) + +/* APB1 peripheral clock enable register */ + +#define RCC_APB1ENR_DACEN_BIT 29 +#define RCC_APB1ENR_PWREN_BIT 28 +#define RCC_APB1ENR_CAN2EN_BIT 26 +#define RCC_APB1ENR_CAN1EN_BIT 25 +#define RCC_APB1ENR_I2C3EN_BIT 23 +#define RCC_APB1ENR_I2C2EN_BIT 22 +#define RCC_APB1ENR_I2C1EN_BIT 21 +#define RCC_APB1ENR_UART5EN_BIT 20 +#define RCC_APB1ENR_UART4EN_BIT 19 +#define RCC_APB1ENR_USART3EN_BIT 18 +#define RCC_APB1ENR_USART2EN_BIT 17 +#define RCC_APB1ENR_SPI3EN_BIT 15 +#define RCC_APB1ENR_SPI2EN_BIT 14 +#define RCC_APB1ENR_WWDGEN_BIT 11 +#define RCC_APB1ENR_TIM14EN_BIT 8 +#define RCC_APB1ENR_TIM13EN_BIT 7 +#define RCC_APB1ENR_TIM12EN_BIT 6 +#define RCC_APB1ENR_TIM7EN_BIT 5 +#define RCC_APB1ENR_TIM6EN_BIT 4 +#define RCC_APB1ENR_TIM5EN_BIT 3 +#define RCC_APB1ENR_TIM4EN_BIT 2 +#define RCC_APB1ENR_TIM3EN_BIT 1 +#define RCC_APB1ENR_TIM2EN_BIT 0 + +#define RCC_APB1ENR_DACEN (1U << RCC_APB1ENR_DACEN_BIT) +#define RCC_APB1ENR_PWREN (1U << RCC_APB1ENR_PWREN_BIT) +#define RCC_APB1ENR_CAN2EN (1U << RCC_APB1ENR_CAN2EN_BIT) +#define RCC_APB1ENR_CAN1EN (1U << RCC_APB1ENR_CAN1EN_BIT) +#define RCC_APB1ENR_I2C3EN (1U << RCC_APB1ENR_I2C3EN_BIT) +#define RCC_APB1ENR_I2C2EN (1U << RCC_APB1ENR_I2C2EN_BIT) +#define RCC_APB1ENR_I2C1EN (1U << RCC_APB1ENR_I2C1EN_BIT) +#define RCC_APB1ENR_UART5EN (1U << RCC_APB1ENR_UART5EN_BIT) +#define RCC_APB1ENR_UART4EN (1U << RCC_APB1ENR_UART4EN_BIT) +#define RCC_APB1ENR_USART3EN (1U << RCC_APB1ENR_USART3EN_BIT) +#define RCC_APB1ENR_USART2EN (1U << RCC_APB1ENR_USART2EN_BIT) +#define RCC_APB1ENR_SPI3EN (1U << RCC_APB1ENR_SPI3EN_BIT) +#define RCC_APB1ENR_SPI2EN (1U << RCC_APB1ENR_SPI2EN_BIT) +#define RCC_APB1ENR_WWDGEN (1U << RCC_APB1ENR_WWDGEN_BIT) +#define RCC_APB1ENR_TIM14EN (1U << RCC_APB1ENR_TIM14EN_BIT) +#define RCC_APB1ENR_TIM13EN (1U << RCC_APB1ENR_TIM13EN_BIT) +#define RCC_APB1ENR_TIM12EN (1U << RCC_APB1ENR_TIM12EN_BIT) +#define RCC_APB1ENR_TIM7EN (1U << RCC_APB1ENR_TIM7EN_BIT) +#define RCC_APB1ENR_TIM6EN (1U << RCC_APB1ENR_TIM6EN_BIT) +#define RCC_APB1ENR_TIM5EN (1U << RCC_APB1ENR_TIM5EN_BIT) +#define RCC_APB1ENR_TIM4EN (1U << RCC_APB1ENR_TIM4EN_BIT) +#define RCC_APB1ENR_TIM3EN (1U << RCC_APB1ENR_TIM3EN_BIT) +#define RCC_APB1ENR_TIM2EN (1U << RCC_APB1ENR_TIM2EN_BIT) + +/* APB2 peripheral clock enable register */ + +#define RCC_APB2ENR_TIM11EN_BIT 18 +#define RCC_APB2ENR_TIM10EN_BIT 17 +#define RCC_APB2ENR_TIM9EN_BIT 16 +#define RCC_APB2ENR_SYSCFGEN_BIT 14 +#define RCC_APB2ENR_SPI1EN_BIT 12 +#define RCC_APB2ENR_SDIOEN_BIT 11 +#define RCC_APB2ENR_ADC3EN_BIT 10 +#define RCC_APB2ENR_ADC2EN_BIT 9 +#define RCC_APB2ENR_ADC1EN_BIT 8 +#define RCC_APB2ENR_USART6EN_BIT 5 +#define RCC_APB2ENR_USART1EN_BIT 4 +#define RCC_APB2ENR_TIM8EN_BIT 1 +#define RCC_APB2ENR_TIM1EN_BIT 0 + +#define RCC_APB2ENR_TIM11EN (1U << RCC_APB2ENR_TIM11EN_BIT) +#define RCC_APB2ENR_TIM10EN (1U << RCC_APB2ENR_TIM10EN_BIT) +#define RCC_APB2ENR_TIM9EN (1U << RCC_APB2ENR_TIM9EN_BIT) +#define RCC_APB2ENR_SYSCFGEN (1U << RCC_APB2ENR_SYSCFGEN_BIT) +#define RCC_APB2ENR_SPI1EN (1U << RCC_APB2ENR_SPI1EN_BIT) +#define RCC_APB2ENR_SDIOEN (1U << RCC_APB2ENR_SDIOEN_BIT) +#define RCC_APB2ENR_ADC3EN (1U << RCC_APB2ENR_ADC3EN_BIT) +#define RCC_APB2ENR_ADC2EN (1U << RCC_APB2ENR_ADC2EN_BIT) +#define RCC_APB2ENR_ADC1EN (1U << RCC_APB2ENR_ADC1EN_BIT) +#define RCC_APB2ENR_USART6EN (1U << RCC_APB2ENR_USART6EN_BIT) +#define RCC_APB2ENR_USART1EN (1U << RCC_APB2ENR_USART1EN_BIT) +#define RCC_APB2ENR_TIM8EN (1U << RCC_APB2ENR_TIM8EN_BIT) +#define RCC_APB2ENR_TIM1EN (1U << RCC_APB2ENR_TIM1EN_BIT) + +/* AHB1 peripheral clock enable in low power mode register */ + +#define RCC_AHB1LPENR_OTGHSULPILPEN_BIT 30 +#define RCC_AHB1LPENR_OTGHSLPEN_BIT 29 +#define RCC_AHB1LPENR_ETHMACPTPLPEN_BIT 28 +#define RCC_AHB1LPENR_ETHMACRXLPEN_BIT 27 +#define RCC_AHB1LPENR_ETHMACTXLPEN_BIT 26 +#define RCC_AHB1LPENR_ETHMACLPEN_BIT 25 +#define RCC_AHB1LPENR_DMA2LPEN_BIT 22 +#define RCC_AHB1LPENR_DMA1LPEN_BIT 21 +#define RCC_AHB1LPENR_BKPSRAMLPEN_BIT 18 +#define RCC_AHB1LPENR_SRAM2LPEN_BIT 17 +#define RCC_AHB1LPENR_SRAM1LPEN_BIT 16 +#define RCC_AHB1LPENR_FLITFLPEN_BIT 15 +#define RCC_AHB1LPENR_CRCLPEN_BIT 12 +#define RCC_AHB1LPENR_GPIOILPEN_BIT 8 +#define RCC_AHB1LPENR_GPIOGLPEN_BIT 6 +#define RCC_AHB1LPENR_GPIOFLPEN_BIT 5 +#define RCC_AHB1LPENR_GPIOELPEN_BIT 4 +#define RCC_AHB1LPENR_GPIODLPEN_BIT 3 +#define RCC_AHB1LPENR_GPIOCLPEN_BIT 2 +#define RCC_AHB1LPENR_GPIOBLPEN_BIT 1 +#define RCC_AHB1LPENR_GPIOALPEN_BIT 0 + +#define RCC_AHB1LPENR_OTGHSULPILPEN (1U << RCC_AHB1LPENR_OTGHSULPILPEN_BIT) +#define RCC_AHB1LPENR_OTGHSLPEN (1U << RCC_AHB1LPENR_OTGHSLPEN_BIT) +#define RCC_AHB1LPENR_ETHMACPTPLPEN (1U << RCC_AHB1LPENR_ETHMACPTPLPEN_BIT) +#define RCC_AHB1LPENR_ETHMACRXLPEN (1U << RCC_AHB1LPENR_ETHMACRXLPEN_BIT) +#define RCC_AHB1LPENR_ETHMACTXLPEN (1U << RCC_AHB1LPENR_ETHMACTXLPEN_BIT) +#define RCC_AHB1LPENR_ETHMACLPEN (1U << RCC_AHB1LPENR_ETHMACLPEN_BIT) +#define RCC_AHB1LPENR_DMA2LPEN (1U << RCC_AHB1LPENR_DMA2LPEN_BIT) +#define RCC_AHB1LPENR_DMA1LPEN (1U << RCC_AHB1LPENR_DMA1LPEN_BIT) +#define RCC_AHB1LPENR_BKPSRAMLPEN (1U << RCC_AHB1LPENR_BKPSRAMLPEN_BIT) +#define RCC_AHB1LPENR_SRAM2LPEN (1U << RCC_AHB1LPENR_SRAM2LPEN_BIT) +#define RCC_AHB1LPENR_SRAM1LPEN (1U << RCC_AHB1LPENR_SRAM1LPEN_BIT) +#define RCC_AHB1LPENR_FLITFLPEN (1U << RCC_AHB1LPENR_FLITFLPEN_BIT) +#define RCC_AHB1LPENR_CRCLPEN (1U << RCC_AHB1LPENR_CRCLPEN_BIT) +#define RCC_AHB1LPENR_GPIOILPEN (1U << RCC_AHB1LPENR_GPIOILPEN_BIT) +#define RCC_AHB1LPENR_GPIOGLPEN (1U << RCC_AHB1LPENR_GPIOGLPEN_BIT) +#define RCC_AHB1LPENR_GPIOFLPEN (1U << RCC_AHB1LPENR_GPIOFLPEN_BIT) +#define RCC_AHB1LPENR_GPIOELPEN (1U << RCC_AHB1LPENR_GPIOELPEN_BIT) +#define RCC_AHB1LPENR_GPIODLPEN (1U << RCC_AHB1LPENR_GPIODLPEN_BIT) +#define RCC_AHB1LPENR_GPIOCLPEN (1U << RCC_AHB1LPENR_GPIOCLPEN_BIT) +#define RCC_AHB1LPENR_GPIOBLPEN (1U << RCC_AHB1LPENR_GPIOBLPEN_BIT) +#define RCC_AHB1LPENR_GPIOALPEN (1U << RCC_AHB1LPENR_GPIOALPEN_BIT) + +/* AHB2 peripheral clock enable in low power mode register */ + +#define RCC_AHB2LPENR_OTGFSLPEN_BIT 7 +#define RCC_AHB2LPENR_RNGLPEN_BIT 6 +#define RCC_AHB2LPENR_HASHLPEN_BIT 5 +#define RCC_AHB2LPENR_CRYPLPEN_BIT 4 +#define RCC_AHB2LPENR_DCMILPEN_BIT 0 + +#define RCC_AHB2LPENR_OTGFSLPEN (1U << RCC_AHB2LPENR_OTGFSLPEN_BIT) +#define RCC_AHB2LPENR_RNGLPEN (1U << RCC_AHB2LPENR_RNGLPEN_BIT) +#define RCC_AHB2LPENR_HASHLPEN (1U << RCC_AHB2LPENR_HASHLPEN_BIT) +#define RCC_AHB2LPENR_CRYPLPEN (1U << RCC_AHB2LPENR_CRYPLPEN_BIT) +#define RCC_AHB2LPENR_DCMILPEN (1U << RCC_AHB2LPENR_DCMILPEN_BIT) + +/* AHB3 peripheral clock enable in low power mode register */ + +#define RCC_AHB3LPENR_FSMCLPEN_BIT 0 + +#define RCC_AHB3LPENR_FSMCLPEN (1U << RCC_AHB3LPENR_FSMCLPEN_BIT) + +/* APB1 peripheral clock enable in low power mode register */ + +#define RCC_APB1LPENR_DACLPEN_BIT 29 +#define RCC_APB1LPENR_PWRLPEN_BIT 28 +#define RCC_APB1LPENR_CAN2LPEN_BIT 26 +#define RCC_APB1LPENR_CAN1LPEN_BIT 25 +#define RCC_APB1LPENR_I2C3LPEN_BIT 23 +#define RCC_APB1LPENR_I2C2LPEN_BIT 22 +#define RCC_APB1LPENR_I2C1LPEN_BIT 21 +#define RCC_APB1LPENR_UART5LPEN_BIT 20 +#define RCC_APB1LPENR_UART4LPEN_BIT 19 +#define RCC_APB1LPENR_USART3LPEN_BIT 18 +#define RCC_APB1LPENR_USART2LPEN_BIT 17 +#define RCC_APB1LPENR_SPI3LPEN_BIT 15 +#define RCC_APB1LPENR_SPI2LPEN_BIT 14 +#define RCC_APB1LPENR_WWDGLPEN_BIT 11 +#define RCC_APB1LPENR_TIM14LPEN_BIT 8 +#define RCC_APB1LPENR_TIM13LPEN_BIT 7 +#define RCC_APB1LPENR_TIM12LPEN_BIT 6 +#define RCC_APB1LPENR_TIM7LPEN_BIT 5 +#define RCC_APB1LPENR_TIM6LPEN_BIT 4 +#define RCC_APB1LPENR_TIM5LPEN_BIT 3 +#define RCC_APB1LPENR_TIM4LPEN_BIT 2 +#define RCC_APB1LPENR_TIM3LPEN_BIT 1 +#define RCC_APB1LPENR_TIM2LPEN_BIT 0 + +#define RCC_APB1LPENR_DACLPEN (1U << RCC_APB1LPENR_DACLPEN_BIT) +#define RCC_APB1LPENR_PWRLPEN (1U << RCC_APB1LPENR_PWRLPEN_BIT) +#define RCC_APB1LPENR_CAN2LPEN (1U << RCC_APB1LPENR_CAN2LPEN_BIT) +#define RCC_APB1LPENR_CAN1LPEN (1U << RCC_APB1LPENR_CAN1LPEN_BIT) +#define RCC_APB1LPENR_I2C3LPEN (1U << RCC_APB1LPENR_I2C3LPEN_BIT) +#define RCC_APB1LPENR_I2C2LPEN (1U << RCC_APB1LPENR_I2C2LPEN_BIT) +#define RCC_APB1LPENR_I2C1LPEN (1U << RCC_APB1LPENR_I2C1LPEN_BIT) +#define RCC_APB1LPENR_UART5LPEN (1U << RCC_APB1LPENR_UART5LPEN_BIT) +#define RCC_APB1LPENR_UART4LPEN (1U << RCC_APB1LPENR_UART4LPEN_BIT) +#define RCC_APB1LPENR_USART3LPEN (1U << RCC_APB1LPENR_USART3LPEN_BIT) +#define RCC_APB1LPENR_USART2LPEN (1U << RCC_APB1LPENR_USART2LPEN_BIT) +#define RCC_APB1LPENR_SPI3LPEN (1U << RCC_APB1LPENR_SPI3LPEN_BIT) +#define RCC_APB1LPENR_SPI2LPEN (1U << RCC_APB1LPENR_SPI2LPEN_BIT) +#define RCC_APB1LPENR_WWDGLPEN (1U << RCC_APB1LPENR_WWDGLPEN_BIT) +#define RCC_APB1LPENR_TIM14LPEN (1U << RCC_APB1LPENR_TIM14LPEN_BIT) +#define RCC_APB1LPENR_TIM13LPEN (1U << RCC_APB1LPENR_TIM13LPEN_BIT) +#define RCC_APB1LPENR_TIM12LPEN (1U << RCC_APB1LPENR_TIM12LPEN_BIT) +#define RCC_APB1LPENR_TIM7LPEN (1U << RCC_APB1LPENR_TIM7LPEN_BIT) +#define RCC_APB1LPENR_TIM6LPEN (1U << RCC_APB1LPENR_TIM6LPEN_BIT) +#define RCC_APB1LPENR_TIM5LPEN (1U << RCC_APB1LPENR_TIM5LPEN_BIT) +#define RCC_APB1LPENR_TIM4LPEN (1U << RCC_APB1LPENR_TIM4LPEN_BIT) +#define RCC_APB1LPENR_TIM3LPEN (1U << RCC_APB1LPENR_TIM3LPEN_BIT) +#define RCC_APB1LPENR_TIM2LPEN (1U << RCC_APB1LPENR_TIM2LPEN_BIT) + +/* APB2 peripheral clock enable in low power mode register */ + +#define RCC_APB2LPENR_TIM11LPEN_BIT 18 +#define RCC_APB2LPENR_TIM10LPEN_BIT 17 +#define RCC_APB2LPENR_TIM9LPEN_BIT 16 +#define RCC_APB2LPENR_SYSCFGLPEN_BIT 14 +#define RCC_APB2LPENR_SPI1LPEN_BIT 12 +#define RCC_APB2LPENR_SDIOLPEN_BIT 11 +#define RCC_APB2LPENR_ADC3LPEN_BIT 10 +#define RCC_APB2LPENR_ADC2LPEN_BIT 9 +#define RCC_APB2LPENR_ADC1LPEN_BIT 8 +#define RCC_APB2LPENR_USART6LPEN_BIT 5 +#define RCC_APB2LPENR_USART1LPEN_BIT 4 +#define RCC_APB2LPENR_TIM8LPEN_BIT 1 +#define RCC_APB2LPENR_TIM1LPEN_BIT 0 + +#define RCC_APB2LPENR_TIM11LPEN (1U << RCC_APB2LPENR_TIM11LPEN_BIT) +#define RCC_APB2LPENR_TIM10LPEN (1U << RCC_APB2LPENR_TIM10LPEN_BIT) +#define RCC_APB2LPENR_TIM9LPEN (1U << RCC_APB2LPENR_TIM9LPEN_BIT) +#define RCC_APB2LPENR_SYSCFGLPEN (1U << RCC_APB2LPENR_SYSCFGLPEN_BIT) +#define RCC_APB2LPENR_SPI1LPEN (1U << RCC_APB2LPENR_SPI1LPEN_BIT) +#define RCC_APB2LPENR_SDIOLPEN (1U << RCC_APB2LPENR_SDIOLPEN_BIT) +#define RCC_APB2LPENR_ADC3LPEN (1U << RCC_APB2LPENR_ADC3LPEN_BIT) +#define RCC_APB2LPENR_ADC2LPEN (1U << RCC_APB2LPENR_ADC2LPEN_BIT) +#define RCC_APB2LPENR_ADC1LPEN (1U << RCC_APB2LPENR_ADC1LPEN_BIT) +#define RCC_APB2LPENR_USART6LPEN (1U << RCC_APB2LPENR_USART6LPEN_BIT) +#define RCC_APB2LPENR_USART1LPEN (1U << RCC_APB2LPENR_USART1LPEN_BIT) +#define RCC_APB2LPENR_TIM8LPEN (1U << RCC_APB2LPENR_TIM8LPEN_BIT) +#define RCC_APB2LPENR_TIM1LPEN (1U << RCC_APB2LPENR_TIM1LPEN_BIT) + +/* Backup domain control register */ + +#define RCC_BDCR_BDRST_BIT 16 +#define RCC_BDCR_RTCEN_BIT 15 +#define RCC_BDCR_LSEBYP_BIT 2 +#define RCC_BDCR_LSERDY_BIT 1 +#define RCC_BDCR_LSEON_BIT 0 + +#define RCC_BDCR_BDRST (1U << RCC_BDCR_BDRST_BIT) +#define RCC_BDCR_RTCEN (1U << RCC_BDCR_RTCEN_BIT) +#define RCC_BDCR_RTCSEL (0x3 << 8) +#define RCC_BDCR_RTCSEL_NOCLOCK (0x0 << 8) +#define RCC_BDCR_RTCSEL_LSE (0x1 << 8) +#define RCC_BDCR_RTCSEL_LSI (0x2 << 8) +#define RCC_BDCR_RTCSEL_HSE_DIV (0x3 << 8) +#define RCC_BDCR_LSEBYP (1U << RCC_BDCR_LSEBYP_BIT) +#define RCC_BDCR_LSERDY (1U << RCC_BDCR_LSERDY_BIT) +#define RCC_BDCR_LSEON (1U << RCC_BDCR_LSEON_BIT) + +/* Clock control and status register */ + +#define RCC_CSR_LPWRRSTF_BIT 31 +#define RCC_CSR_WWDGRSTF_BIT 30 +#define RCC_CSR_IWDGRSTF_BIT 29 +#define RCC_CSR_SFTRSTF_BIT 28 +#define RCC_CSR_PORRSTF_BIT 27 +#define RCC_CSR_PINRSTF_BIT 26 +#define RCC_CSR_BORRSTF_BIT 25 +#define RCC_CSR_RMVF_BIT 24 +#define RCC_CSR_LSIRDY_BIT 1 +#define RCC_CSR_LSION_BIT 0 + +#define RCC_CSR_LPWRRSTF (1U << RCC_CSR_LPWRRSTF_BIT) +#define RCC_CSR_WWDGRSTF (1U << RCC_CSR_WWDGRSTF_BIT) +#define RCC_CSR_IWDGRSTF (1U << RCC_CSR_IWDGRSTF_BIT) +#define RCC_CSR_SFTRSTF (1U << RCC_CSR_SFTRSTF_BIT) +#define RCC_CSR_PORRSTF (1U << RCC_CSR_PORRSTF_BIT) +#define RCC_CSR_PINRSTF (1U << RCC_CSR_PINRSTF_BIT) +#define RCC_CSR_BORRSTF (1U << RCC_CSR_BORRSTF_BIT) +#define RCC_CSR_RMVF (1U << RCC_CSR_RMVF_BIT) +#define RCC_CSR_LSIRDY (1U << RCC_CSR_LSIRDY_BIT) +#define RCC_CSR_LSION (1U << RCC_CSR_LSION_BIT) + +/* Spread spectrum clock generation register */ + +#define RCC_SSCGR_SSCGEN_BIT 31 +#define RCC_SSCGR_SPREADSEL_BIT 30 + +#define RCC_SSCGR_SSCGEN (1U << RCC_SSCGR_SSCGEN_BIT) +#define RCC_SSCGR_SPREADSEL (1U << RCC_SSCGR_SPREADSEL_BIT) +#define RCC_SSCGR_SPREADSEL_CENTER (0x0 << RCC_SSCGR_SPREADSEL_BIT) +#define RCC_SSCGR_SPREADSEL_DOWN (0x1 << RCC_SSCGR_SPREADSEL_BIT) +#define RCC_SSCGR_INCSTEP (0xFFF << 16) +#define RCC_SSCGR_MODPER 0xFFFF + +/* PLLI2S configuration register */ + +#define RCC_PLLI2SCFGR_PLLI2SR (0x7 << 28) +#define RCC_PLLI2SCFGR_PLLI2SN (0x1FF << 6) + +/* + * Clock sources, domains, and peripheral clock IDs. + */ + +/** + * @brief STM32F2 clock sources. + */ +typedef enum rcc_clk { + RCC_CLK_PLLI2S = (uint16)((offsetof(struct rcc_reg_map, CR) << 8) | + RCC_CR_PLLI2SON_BIT), /**< Dedicated PLL + for I2S. */ + RCC_CLK_PLL = (uint16)((offsetof(struct rcc_reg_map, CR) << 8) | + RCC_CR_PLLON_BIT), /**< Main PLL, clocked by + HSI or HSE. */ + RCC_CLK_HSE = (uint16)((offsetof(struct rcc_reg_map, CR) << 8) | + RCC_CR_HSEON_BIT), /**< High speed external. */ + RCC_CLK_HSI = (uint16)((offsetof(struct rcc_reg_map, CR) << 8) | + RCC_CR_HSION_BIT), /**< High speed internal. */ + RCC_CLK_LSE = (uint16)((offsetof(struct rcc_reg_map, BDCR) << 8) | + RCC_BDCR_LSEON_BIT), /**< Low-speed external + * (32.768 KHz). */ + RCC_CLK_LSI = (uint16)((offsetof(struct rcc_reg_map, CSR) << 8) | + RCC_CSR_LSION_BIT), /**< Low-speed internal + * (approximately 32 KHz). */ +} rcc_clk; + +/** + * @brief STM32F2 rcc_clk_id. + */ +typedef enum rcc_clk_id { + RCC_ADC1, + RCC_ADC2, + RCC_ADC3, + RCC_BKPSRAM, + RCC_CAN1, + RCC_CAN2, + RCC_CRC, + RCC_CRYP, + RCC_DAC, + RCC_DCMI, + RCC_DMA1, + RCC_DMA2, + RCC_ETHMAC, + RCC_ETHMACPTP, + RCC_ETHMACRX, + RCC_ETHMACTX, + RCC_FSMC, + RCC_GPIOA, + RCC_GPIOB, + RCC_GPIOC, + RCC_GPIOD, + RCC_GPIOE, + RCC_GPIOF, + RCC_GPIOG, + RCC_GPIOH, + RCC_GPIOI, + RCC_HASH, + RCC_I2C1, + RCC_I2C2, + RCC_I2C3, + RCC_OTGFS, + RCC_OTGHS, + RCC_OTGHSULPI, + RCC_PWR, + RCC_RNG, + RCC_SDIO, + RCC_SPI1, + RCC_SPI2, + RCC_SPI3, + RCC_SYSCFG, + RCC_TIMER1, + RCC_TIMER10, + RCC_TIMER11, + RCC_TIMER12, + RCC_TIMER13, + RCC_TIMER14, + RCC_TIMER2, + RCC_TIMER3, + RCC_TIMER4, + RCC_TIMER5, + RCC_TIMER6, + RCC_TIMER7, + RCC_TIMER8, + RCC_TIMER9, + RCC_USART1, + RCC_USART2, + RCC_USART3, + RCC_UART4, + RCC_UART5, + RCC_USART6, + RCC_WWDG, +} rcc_clk_id; + +/** + * @brief STM32F2 PLL entry clock source + * @see rcc_configure_pll() + */ +typedef enum rcc_pllsrc { + RCC_PLLSRC_HSI = 0, + RCC_PLLSRC_HSE = RCC_PLLCFGR_PLLSRC, +} rcc_pllsrc; + +/** + * @brief STM32F2 Peripheral clock domains. + */ +typedef enum rcc_clk_domain { + RCC_APB1, + RCC_APB2, + RCC_AHB1, + RCC_AHB2, + RCC_AHB3, +} rcc_clk_domain; + +/* + * Prescalers and dividers. + */ + +/** + * @brief STM32F2 Prescaler identifiers. + */ +typedef enum rcc_prescaler { + RCC_PRESCALER_MCO2, + RCC_PRESCALER_MCO1, + RCC_PRESCALER_RTC, + RCC_PRESCALER_APB2, + RCC_PRESCALER_APB1, + RCC_PRESCALER_AHB +} rcc_prescaler; + +/** + * @brief STM32F2 MCO2 prescaler dividers. + */ +typedef enum rcc_mco2_divider { + RCC_MCO2_DIV_1 = RCC_CFGR_MCO2PRE_DIV_1, + RCC_MCO2_DIV_2 = RCC_CFGR_MCO2PRE_DIV_2, + RCC_MCO2_DIV_3 = RCC_CFGR_MCO2PRE_DIV_3, + RCC_MCO2_DIV_4 = RCC_CFGR_MCO2PRE_DIV_4, + RCC_MCO2_DIV_5 = RCC_CFGR_MCO2PRE_DIV_5, +} rcc_mco2_divider; + +/** + * @brief STM32F2 MCO1 prescaler dividers. + */ +typedef enum rcc_mco1_divider { + RCC_MCO1_DIV_1 = RCC_CFGR_MCO1PRE_DIV_1, + RCC_MCO1_DIV_2 = RCC_CFGR_MCO1PRE_DIV_2, + RCC_MCO1_DIV_3 = RCC_CFGR_MCO1PRE_DIV_3, + RCC_MCO1_DIV_4 = RCC_CFGR_MCO1PRE_DIV_4, + RCC_MCO1_DIV_5 = RCC_CFGR_MCO1PRE_DIV_5, +} rcc_mco1_divider; + +/** + * @brief STM32F2 RTC prescaler dividers. + */ +typedef enum rcc_rtc_divider { /* FIXME [0.0.13] TODO */ + RCC_RTC_DIV_TODO = 0xFFFFFFFF, +} rcc_rtc_divider; + +/** + * @brief STM32F2 AP2 prescaler dividers. + */ +typedef enum rcc_apb2_divider { + RCC_APB2_HCLK_DIV_1 = 0, + RCC_APB2_HCLK_DIV_2 = RCC_CFGR_PPRE2_AHB_DIV_2, + RCC_APB2_HCLK_DIV_4 = RCC_CFGR_PPRE2_AHB_DIV_4, + RCC_APB2_HCLK_DIV_8 = RCC_CFGR_PPRE2_AHB_DIV_8, + RCC_APB2_HCLK_DIV_16 = RCC_CFGR_PPRE2_AHB_DIV_16, +} rcc_apb2_divider; + +/** + * @brief STM32F2 APB1 prescaler dividers. + */ +typedef enum rcc_apb1_divider { + RCC_APB1_HCLK_DIV_1 = 0, + RCC_APB1_HCLK_DIV_2 = RCC_CFGR_PPRE1_AHB_DIV_2, + RCC_APB1_HCLK_DIV_4 = RCC_CFGR_PPRE1_AHB_DIV_4, + RCC_APB1_HCLK_DIV_8 = RCC_CFGR_PPRE1_AHB_DIV_8, + RCC_APB1_HCLK_DIV_16 = RCC_CFGR_PPRE1_AHB_DIV_16, +} rcc_apb1_divider; + +/** + * @brief STM32F2 AHB prescaler dividers. + */ +typedef enum rcc_ahb_divider { + RCC_AHB_SYSCLK_DIV_1 = 0, + RCC_AHB_SYSCLK_DIV_2 = RCC_CFGR_HPRE_SYSCLK_DIV_2, + RCC_AHB_SYSCLK_DIV_4 = RCC_CFGR_HPRE_SYSCLK_DIV_4, + RCC_AHB_SYSCLK_DIV_8 = RCC_CFGR_HPRE_SYSCLK_DIV_8, + RCC_AHB_SYSCLK_DIV_16 = RCC_CFGR_HPRE_SYSCLK_DIV_16, + RCC_AHB_SYSCLK_DIV_64 = RCC_CFGR_HPRE_SYSCLK_DIV_64, + RCC_AHB_SYSCLK_DIV_128 = RCC_CFGR_HPRE_SYSCLK_DIV_128, + RCC_AHB_SYSCLK_DIV_256 = RCC_CFGR_HPRE_SYSCLK_DIV_256, + RCC_AHB_SYSCLK_DIV_512 = RCC_CFGR_HPRE_SYSCLK_DIV_512, +} rcc_ahb_divider; + +/** + * @brief STM32F2 PLL configuration values. + * Point to one of these with the "data" field in a struct rcc_pll_cfg. + * @see struct rcc_pll_cfg. + */ +typedef struct stm32f2_rcc_pll_data { + uint8 pllq; /**< + * @brief PLLQ value. + * Allowed values: 4, 5, ..., 15. */ + uint8 pllp; /**< + * @brief PLLP value. + * Allowed values: 2, 4, 6, 8. */ + uint16 plln; /**< + * @brief PLLN value. + * Allowed values: 192, 193, ..., 432. */ + uint8 pllm; /**< + * @brief PLLM value. + * Allowed values: 2, 3, ..., 63. */ +} stm32f2_rcc_pll_data; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/spi.h b/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/spi.h new file mode 100644 index 0000000..7b9f94a --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/spi.h @@ -0,0 +1,88 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f2/include/series/spi.h + * @author Marti Bolivar + * @brief STM32F2 SPI/I2S series header. + */ + +#ifndef _LIBMAPLE_STM32F2_SPI_H_ +#define _LIBMAPLE_STM32F2_SPI_H_ + +#include /* for gpio_af */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Register map base pointers + */ + +struct spi_reg_map; + +#define SPI1_BASE ((struct spi_reg_map*)0x40013000) +#define SPI2_BASE ((struct spi_reg_map*)0x40003800) +#define SPI3_BASE ((struct spi_reg_map*)0x40003C00) + +/* + * Register bit definitions + */ + +/* Control register 2 */ + +#define SPI_CR2_FRF_BIT 4 + +#define SPI_CR2_FRF (1U << SPI_CR2_FRF_BIT) + +/* Status register */ + +#define SPI_SR_TIFRFE_BIT 8 + +#define SPI_SR_TIFRFE (1U << SPI_SR_TIFRFE_BIT) + +/* + * Device pointers + */ + +struct spi_dev; + +extern struct spi_dev *SPI1; +extern struct spi_dev *SPI2; +extern struct spi_dev *SPI3; + +/* + * Routines + */ + +gpio_af spi_get_af(struct spi_dev *dev); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/stm32.h b/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/stm32.h new file mode 100644 index 0000000..180ab30 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/stm32.h @@ -0,0 +1,77 @@ +/****************************************************************************** + * 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/stm32f2/include/series/stm32.h + * @brief STM32F2 chip- and series-specific definitions. + */ + +#ifndef _LIBMAPLE_STM32F2_STM32_H_ +#define _LIBMAPLE_STM32F2_STM32_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Chip configuration + */ + +#ifndef STM32_PCLK1 +#define STM32_PCLK1 30000000U +#endif + +#ifndef STM32_PCLK2 +#define STM32_PCLK2 60000000U +#endif + +#ifndef STM32_DELAY_US_MULT +#define STM32_DELAY_US_MULT 20 /* FIXME: dummy value. */ +#endif + +/* + * Series- and MCU-specific values + */ + +#define STM32_MCU_SERIES STM32_SERIES_F2 +#define STM32_NR_INTERRUPTS 81 +#define STM32_HAVE_FSMC 1 +#define STM32_HAVE_USB 1 +#define STM32_HAVE_DAC 1 + +#if defined(MCU_STM32F207IC) || defined(MCU_STM32F207IG) +# define STM32_NR_GPIO_PORTS 9 +# define STM32_TIMER_MASK 0x7FFE /* TIMER1-TIMER14. */ +# define STM32_SRAM_END ((void*)0x20020000) +#else +#warning "Unsupported or unspecified STM32F2 MCU." +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/timer.h b/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/timer.h new file mode 100644 index 0000000..a7ac276 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/timer.h @@ -0,0 +1,176 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011,2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f2/include/series/timer.h + * @author Marti Bolivar + * @brief STM32F2 timer support. + */ + +#ifndef _LIBMAPLE_STM32F2_TIMER_H_ +#define _LIBMAPLE_STM32F2_TIMER_H_ + +#include +#include /* for gpio_af */ + +/* + * Register maps and base pointers + */ + +/** + * @brief STM32F2 general purpose timer register map type + * + * Note that not all general purpose timers have all of these + * registers. Consult your chip's reference manual for the details. + */ +typedef struct timer_gen_reg_map { + __io uint32 CR1; /**< Control register 1 */ + __io uint32 CR2; /**< Control register 2 */ + __io uint32 SMCR; /**< Slave mode control register */ + __io uint32 DIER; /**< DMA/Interrupt enable register */ + __io uint32 SR; /**< Status register */ + __io uint32 EGR; /**< Event generation register */ + __io uint32 CCMR1; /**< Capture/compare mode register 1 */ + __io uint32 CCMR2; /**< Capture/compare mode register 2 */ + __io uint32 CCER; /**< Capture/compare enable register */ + __io uint32 CNT; /**< Counter */ + __io uint32 PSC; /**< Prescaler */ + __io uint32 ARR; /**< Auto-reload register */ + const uint32 RESERVED1; /**< Reserved */ + __io uint32 CCR1; /**< Capture/compare register 1 */ + __io uint32 CCR2; /**< Capture/compare register 2 */ + __io uint32 CCR3; /**< Capture/compare register 3 */ + __io uint32 CCR4; /**< Capture/compare register 4 */ + const uint32 RESERVED2; /**< Reserved */ + __io uint32 DCR; /**< DMA control register */ + __io uint32 DMAR; /**< DMA address for full transfer */ + __io uint32 OR; /**< Option register. */ +} timer_gen_reg_map; + +struct timer_adv_reg_map; +struct timer_bas_reg_map; + +/** Timer 1 register map base pointer */ +#define TIMER1_BASE ((struct timer_adv_reg_map*)0x40010000) +/** Timer 2 register map base pointer */ +#define TIMER2_BASE ((struct timer_gen_reg_map*)0x40000000) +/** Timer 3 register map base pointer */ +#define TIMER3_BASE ((struct timer_gen_reg_map*)0x40000400) +/** Timer 4 register map base pointer */ +#define TIMER4_BASE ((struct timer_gen_reg_map*)0x40000800) +/** Timer 5 register map base pointer */ +#define TIMER5_BASE ((struct timer_gen_reg_map*)0x40000C00) +/** Timer 6 register map base pointer */ +#define TIMER6_BASE ((struct timer_bas_reg_map*)0x40001000) +/** Timer 7 register map base pointer */ +#define TIMER7_BASE ((struct timer_bas_reg_map*)0x40001400) +/** Timer 8 register map base pointer */ +#define TIMER8_BASE ((struct timer_adv_reg_map*)0x40010400) +/** Timer 9 register map base pointer */ +#define TIMER9_BASE ((struct timer_gen_reg_map*)0x40014000) +/** Timer 10 register map base pointer */ +#define TIMER10_BASE ((struct timer_gen_reg_map*)0x40014400) +/** Timer 11 register map base pointer */ +#define TIMER11_BASE ((struct timer_gen_reg_map*)0x40014800) +/** Timer 12 register map base pointer */ +#define TIMER12_BASE ((struct timer_gen_reg_map*)0x40001800) +/** Timer 13 register map base pointer */ +#define TIMER13_BASE ((struct timer_gen_reg_map*)0x40001C00) +/** Timer 14 register map base pointer */ +#define TIMER14_BASE ((struct timer_gen_reg_map*)0x40002000) + +/* + * Register bit definitions + */ + +/* TIM2 option register */ + +/** Timer 2 option register internal trigger 1 remap */ +#define TIMER2_OR_ITR1_RMP (0x3 << 10) +/** Timer 2 OR internal trigger 1: TIM8_TRGOUT */ +#define TIMER2_OR_ITR1_RMP_TIM8_TRGOUT (0x0 << 10) +/** Timer 2 OR internal trigger 1: Ethernet PTP trigger output */ +#define TIMER2_OR_ITR1_RMP_PTP_TRGOUT (0x1 << 10) +/** Timer 2 OR internal trigger 1: USB OTG full speed start of frame */ +#define TIMER2_OR_ITR1_RMP_OTG_FS_SOF (0x2 << 10) +/** Timer 2 OR internal trigger 1: USB OTG high speed start of frame */ +#define TIMER2_OR_ITR1_RMP_OTG_HS_SOF (0x3 << 10) + +/* TIM5 option register */ + +/** + * Timer 5 option register input 4 remap. + * + * These bits control whether TIM5_CH4 is connected to a GPIO or a + * clock. Connecting to a GPIO is the normal mode, useful for e.g. PWM + * generation or input pulse duration measurement. Connecting to a + * clock is useful for calibrating that clock. + */ +#define TIMER5_OR_TI4_RMP (0x3 << 6) +/** + * Timer 5 OR input 4: Timer 5 channel 4 connected to GPIO. */ +#define TIMER5_OR_TI4_RMP_GPIO (0x0 << 6) +/** + * Timer 5 OR input 4: low speed internal clock (LSI) is connected to + * TIM5_CH4. */ +#define TIMER5_OR_TI4_RMP_LSI (0x1 << 6) +/** + * Timer 5 OR input 4: low speed external clock (LSE) is connected to + * TIM5_CH4. */ +#define TIMER5_OR_TI4_RMP_LSE (0x2 << 6) +/** + * Timer 5 OR input 4: real time clock (RTC) output is connected to + * TIM5_CH4. */ +#define TIMER5_OR_TI4_RMP_RTC (0x3 << 6) + +/* + * Device pointers + */ + +struct timer_dev; + +extern struct timer_dev *TIMER1; +extern struct timer_dev *TIMER2; +extern struct timer_dev *TIMER3; +extern struct timer_dev *TIMER4; +extern struct timer_dev *TIMER5; +extern struct timer_dev *TIMER6; +extern struct timer_dev *TIMER7; +extern struct timer_dev *TIMER8; +extern struct timer_dev *TIMER9; +extern struct timer_dev *TIMER10; +extern struct timer_dev *TIMER11; +extern struct timer_dev *TIMER12; +extern struct timer_dev *TIMER13; +extern struct timer_dev *TIMER14; + +/* + * Routines + */ + +gpio_af timer_get_af(struct timer_dev *dev); + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/usart.h b/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/usart.h new file mode 100644 index 0000000..8936efa --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/stm32f2/include/series/usart.h @@ -0,0 +1,111 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/stm32f2/include/series/usart.h + * @author Marti Bolivar + * @brief STM32F2 USART support. + */ + +#ifndef _LIBMAPLE_STM32F2_USART_H_ +#define _LIBMAPLE_STM32F2_USART_H_ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include /* for gpio_af */ + +/* + * Register map base pointers. + */ + +struct usart_reg_map; + +/** USART1 register map base pointer */ +#define USART1_BASE ((struct usart_reg_map*)0x40011000) +/** USART2 register map base pointer */ +#define USART2_BASE ((struct usart_reg_map*)0x40004400) +/** USART3 register map base pointer */ +#define USART3_BASE ((struct usart_reg_map*)0x40004800) +/** UART4 register map base pointer */ +#define UART4_BASE ((struct usart_reg_map*)0x40004C00) +/** UART5 register map base pointer */ +#define UART5_BASE ((struct usart_reg_map*)0x40005000) +/** USART6 register map base pointer */ +#define USART6_BASE ((struct usart_reg_map*)0x40011400) + +/* + * F2-only register bit definitions. + */ + +/* Control register 1 */ + +/** + * @brief Oversampling mode bit. + * Availability: STM32F2. */ +#define USART_CR1_OVER8_BIT 15 + +/** + * @brief Oversampling mode. + * Availability: STM32F2. */ +#define USART_CR1_OVER8 (1U << USART_CR1_OVER8_BIT) + +/* Control register 3 */ + +/** One sample bit method enable bit. */ +#define USART_CR3_ONEBIT_BIT 11 + +/** One bit sample method enable. */ +#define USART_CR3_ONEBIT (1 << USART_CR3_ONEBIT_BIT) +/** Sample method: Three sample bit method. */ +#define USART_CR3_ONEBIT_3SAMPLE (0 << USART_CR3_ONEBIT_BIT) +/** Sample method: One sample bit method. */ +#define USART_CR3_ONEBIT_1SAMPLE (1 << USART_CR3_ONEBIT_BIT) + +/* + * Devices + */ + +struct usart_dev; +extern struct usart_dev *USART1; +extern struct usart_dev *USART2; +extern struct usart_dev *USART3; +extern struct usart_dev *UART4; +extern struct usart_dev *UART5; +extern struct usart_dev *USART6; + +/* + * Routines + */ + +gpio_af usart_get_af(struct usart_dev *dev); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/stm32f2/rules.mk b/BootLoaders/Boards/stm32/system/libmaple/stm32f2/rules.mk new file mode 100644 index 0000000..4c62cc2 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/stm32f2/rules.mk @@ -0,0 +1,40 @@ +# Standard things +sp := $(sp).x +dirstack_$(sp) := $(d) +d := $(dir) +BUILDDIRS += $(BUILD_PATH)/$(d) + +# Local flags +CFLAGS_$(d) = -I$(d) $(LIBMAPLE_INCLUDES) $(LIBMAPLE_PRIVATE_INCLUDES) -Wall -Werror + +# Local rules and targets +sSRCS_$(d) := isrs.S +sSRCS_$(d) += vector_table.S + +cSRCS_$(d) := adc.c +cSRCS_$(d) += dma.c +cSRCS_$(d) += exti.c +cSRCS_$(d) += fsmc.c +cSRCS_$(d) += gpio.c +cSRCS_$(d) += rcc.c +cSRCS_$(d) += spi.c +cSRCS_$(d) += syscfg.c +cSRCS_$(d) += timer.c +cSRCS_$(d) += usart.c + +sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%) +cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%) + +OBJS_$(d) := $(sFILES_$(d):%.S=$(BUILD_PATH)/%.o) \ + $(cFILES_$(d):%.c=$(BUILD_PATH)/%.o) +DEPS_$(d) := $(OBJS_$(d):%.o=%.d) + +$(OBJS_$(d)): TGT_ASFLAGS := +$(OBJS_$(d)): TGT_CFLAGS := $(CFLAGS_$(d)) + +TGT_BIN += $(OBJS_$(d)) + +# Standard things +-include $(DEPS_$(d)) +d := $(dirstack_$(sp)) +sp := $(basename $(sp)) diff --git a/BootLoaders/Boards/stm32/system/libmaple/timer_private.h b/BootLoaders/Boards/stm32/system/libmaple/timer_private.h new file mode 100644 index 0000000..55e2caf --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/timer_private.h @@ -0,0 +1,235 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2011, 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/timer_private.h + * @author Marti Bolivar + * @brief Private, internal timer APIs. + */ + +#ifndef _LIBMAPLE_TIMER_PRIVATE_H_ +#define _LIBMAPLE_TIMER_PRIVATE_H_ + +/* + * Helper macros for declaring timer_devs of various timer_types + */ + +/* The indexes of user handlers in a timer_dev.handlers are just like + * the corresponding DIER bits, as follows: */ + +/* Advanced timers: + * [0] = Update handler; + * [1,2,3,4] = capture/compare 1,2,3,4 handlers, respectively; + * [5] = COM; + * [6] = TRG; + * [7] = BRK. */ +#define NR_ADV_HANDLERS 8 +/* General purpose timers: + * [0] = update; + * [1,2,3,4] = capture/compare 1,2,3,4; + * [5] = ; + * [6] = trigger. */ +#define NR_GEN_HANDLERS 7 +/* Basic timers: + * [0] = update. */ +#define NR_BAS_HANDLERS 1 + +/* For declaring advanced timers. */ +#define ADVANCED_TIMER(num) \ + { \ + .regs = { .adv = TIMER##num##_BASE }, \ + .clk_id = RCC_TIMER##num, \ + .type = TIMER_ADVANCED, \ + .handlers = { [NR_ADV_HANDLERS - 1] = 0 }, \ + } + +/* For declaring full-featured general purpose timers. */ +#define GENERAL_TIMER(num) \ + { \ + .regs = { .gen = TIMER##num##_BASE }, \ + .clk_id = RCC_TIMER##num, \ + .type = TIMER_GENERAL, \ + .handlers = { [NR_GEN_HANDLERS - 1] = 0 }, \ + } + +/* For declaring general purpose timers with limited interrupt + * capability (e.g. timers 9 through 14 on STM32F2 and XL-density + * STM32F1). */ +#define RESTRICTED_GENERAL_TIMER(num, max_dier_bit) \ + { \ + .regs = { .gen = TIMER##num##_BASE }, \ + .clk_id = RCC_TIMER##num, \ + .type = TIMER_GENERAL, \ + .handlers = { [max_dier_bit] = 0 }, \ + } + +/* For declaring basic timers (e.g. TIM6 and TIM7). */ +#define BASIC_TIMER(num) \ + { \ + .regs = { .bas = TIMER##num##_BASE }, \ + .clk_id = RCC_TIMER##num, \ + .type = TIMER_BASIC, \ + .handlers = { [NR_BAS_HANDLERS - 1] = 0 }, \ + } + +/* + * IRQ handlers + * + * These decode TIMx_DIER and TIMx_SR, then dispatch to the user-level + * IRQ handlers. They also clean up TIMx_SR afterwards, so the user + * doesn't have to deal with register details. + * + * Notes: + * + * - These dispatch routines make use of the fact that DIER interrupt + * enable bits and SR interrupt flags have common bit positions. + * Thus, ANDing DIER and SR lets us check if an interrupt is enabled + * and if it has occurred simultaneously. + * + * - We force these routines to inline to avoid call overhead, but + * there aren't any measurements to prove that this is actually a + * good idea. Profile-directed optimizations are definitely wanted. */ + +/* A special-case dispatch routine for timers which only serve a + * single interrupt on a given IRQ line. + * + * This function still checks DIER & SR, as in some cases, a timer may + * only serve a single interrupt on a particular NVIC line, but that + * line may be shared with another timer. For example, the timer 1 + * update interrupt shares an IRQ line with the timer 10 interrupt on + * STM32F1 (XL-density), STM32F2, and STM32F4. */ +static inline __always_inline void dispatch_single_irq(timer_dev *dev, + timer_interrupt_id iid, + uint32 irq_mask) { + timer_bas_reg_map *regs = (dev->regs).bas; + if (regs->DIER & regs->SR & irq_mask) { + void (*handler)(void) = dev->handlers[iid]; + if (handler) { + handler(); + regs->SR &= ~irq_mask; + } + } +} + +/* Helper macro for dispatch routines which service multiple interrupts. */ +#define handle_irq(dier_sr, irq_mask, handlers, iid, handled_irq) do { \ + if ((dier_sr) & (irq_mask)) { \ + void (*__handler)(void) = (handlers)[iid]; \ + if (__handler) { \ + __handler(); \ + handled_irq |= (irq_mask); \ + } \ + } \ + } while (0) + +static inline __always_inline void dispatch_adv_brk(timer_dev *dev) { + dispatch_single_irq(dev, TIMER_BREAK_INTERRUPT, TIMER_SR_BIF); +} + +static inline __always_inline void dispatch_adv_up(timer_dev *dev) { + dispatch_single_irq(dev, TIMER_UPDATE_INTERRUPT, TIMER_SR_UIF); +} + +static inline __always_inline void dispatch_adv_trg_com(timer_dev *dev) { + timer_adv_reg_map *regs = (dev->regs).adv; + uint32 dsr = regs->DIER & regs->SR; + void (**hs)(void) = dev->handlers; + uint32 handled = 0; /* Logical OR of SR interrupt flags we end up + * handling. We clear these. User handlers + * must clear overcapture flags, to avoid + * wasting time in output mode. */ + + handle_irq(dsr, TIMER_SR_TIF, hs, TIMER_TRG_INTERRUPT, handled); + handle_irq(dsr, TIMER_SR_COMIF, hs, TIMER_COM_INTERRUPT, handled); + + regs->SR &= ~handled; +} + +static inline __always_inline void dispatch_adv_cc(timer_dev *dev) { + timer_adv_reg_map *regs = (dev->regs).adv; + uint32 dsr = regs->DIER & regs->SR; + void (**hs)(void) = dev->handlers; + uint32 handled = 0; + + handle_irq(dsr, TIMER_SR_CC4IF, hs, TIMER_CC4_INTERRUPT, handled); + handle_irq(dsr, TIMER_SR_CC3IF, hs, TIMER_CC3_INTERRUPT, handled); + handle_irq(dsr, TIMER_SR_CC2IF, hs, TIMER_CC2_INTERRUPT, handled); + handle_irq(dsr, TIMER_SR_CC1IF, hs, TIMER_CC1_INTERRUPT, handled); + + regs->SR &= ~handled; +} + +static inline __always_inline void dispatch_general(timer_dev *dev) { + timer_gen_reg_map *regs = (dev->regs).gen; + uint32 dsr = regs->DIER & regs->SR; + void (**hs)(void) = dev->handlers; + uint32 handled = 0; + + handle_irq(dsr, TIMER_SR_TIF, hs, TIMER_TRG_INTERRUPT, handled); + handle_irq(dsr, TIMER_SR_CC4IF, hs, TIMER_CC4_INTERRUPT, handled); + handle_irq(dsr, TIMER_SR_CC3IF, hs, TIMER_CC3_INTERRUPT, handled); + handle_irq(dsr, TIMER_SR_CC2IF, hs, TIMER_CC2_INTERRUPT, handled); + handle_irq(dsr, TIMER_SR_CC1IF, hs, TIMER_CC1_INTERRUPT, handled); + handle_irq(dsr, TIMER_SR_UIF, hs, TIMER_UPDATE_INTERRUPT, handled); + + regs->SR &= ~handled; +} + +/* On F1 (XL-density), F2, and F4, TIM9 and TIM12 are restricted + * general-purpose timers with update, CC1, CC2, and TRG interrupts. */ +static inline __always_inline void dispatch_tim_9_12(timer_dev *dev) { + timer_gen_reg_map *regs = (dev->regs).gen; + uint32 dsr = regs->DIER & regs->SR; + void (**hs)(void) = dev->handlers; + uint32 handled = 0; + + handle_irq(dsr, TIMER_SR_TIF, hs, TIMER_TRG_INTERRUPT, handled); + handle_irq(dsr, TIMER_SR_CC2IF, hs, TIMER_CC2_INTERRUPT, handled); + handle_irq(dsr, TIMER_SR_CC1IF, hs, TIMER_CC1_INTERRUPT, handled); + handle_irq(dsr, TIMER_SR_UIF, hs, TIMER_UPDATE_INTERRUPT, handled); + + regs->SR &= ~handled; +} + +/* On F1 (XL-density), F2, and F4, timers 10, 11, 13, and 14 are + * restricted general-purpose timers with update and CC1 interrupts. */ +static inline __always_inline void dispatch_tim_10_11_13_14(timer_dev *dev) { + timer_gen_reg_map *regs = (dev->regs).gen; + uint32 dsr = regs->DIER & regs->SR; + void (**hs)(void) = dev->handlers; + uint32 handled = 0; + + handle_irq(dsr, TIMER_SR_CC1IF, hs, TIMER_CC1_INTERRUPT, handled); + handle_irq(dsr, TIMER_SR_UIF, hs, TIMER_UPDATE_INTERRUPT, handled); + + regs->SR &= ~handled; +} + +static inline __always_inline void dispatch_basic(timer_dev *dev) { + dispatch_single_irq(dev, TIMER_UPDATE_INTERRUPT, TIMER_SR_UIF); +} + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/usart_private.h b/BootLoaders/Boards/stm32/system/libmaple/usart_private.h new file mode 100644 index 0000000..34aaf4b --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/usart_private.h @@ -0,0 +1,67 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * Copyright (c) 2010 Perry Hung. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file libmaple/usart_private.h + * @author Marti Bolivar + * @brief Private USART header. + */ + +#ifndef _LIBMAPLE_USART_PRIVATE_H_ +#define _LIBMAPLE_USART_PRIVATE_H_ + +#include +#include + +static inline __always_inline void usart_irq(ring_buffer *rb, ring_buffer *wb, usart_reg_map *regs) { + /* Handling RXNEIE and TXEIE interrupts. + * RXNE signifies availability of a byte in DR. + * + * See table 198 (sec 27.4, p809) in STM document RM0008 rev 15. + * We enable RXNEIE. */ + if ((regs->CR1 & USART_CR1_RXNEIE) && (regs->SR & USART_SR_RXNE)) { +#ifdef USART_SAFE_INSERT + /* If the buffer is full and the user defines USART_SAFE_INSERT, + * ignore new bytes. */ + rb_safe_insert(rb, (uint8)regs->DR); +#else + /* By default, push bytes around in the ring buffer. */ + rb_push_insert(rb, (uint8)regs->DR); +#endif + } + /* TXE signifies readiness to send a byte to DR. */ + if ((regs->CR1 & USART_CR1_TXEIE) && (regs->SR & USART_SR_TXE)) { + if (!rb_is_empty(wb)) + regs->DR=rb_remove(wb); + else + regs->CR1 &= ~((uint32)USART_CR1_TXEIE); // disable TXEIE + } +} + +uint32 _usart_clock_freq(usart_dev *dev); + +#endif diff --git a/BootLoaders/Boards/stm32/system/libmaple/usb/README b/BootLoaders/Boards/stm32/system/libmaple/usb/README new file mode 100644 index 0000000..d0fca8d --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/usb/README @@ -0,0 +1,63 @@ +The USB submodule of libmaple is a separate piece of the codebase for +reasons that are largely historical. + +Current Status: + + There's only support for the USB device peripheral found on + STM32F103s. + + We rely on the low level core library provided by ST to implement + the USB transfer protocol for control endpoint transfers. + + The virtual com port (which is exposed via + ) serves two important purposes. + + 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 + application binary into RAM/FLASH). Thus, without this virtual com + port, it would be necessary to find an alternative means to reset + the chip in order to enable the bootloader. + + If you would like to develop your own USB application for whatever + 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 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. + + It would be possible to build a compound USB device, that + implements endpoints for both the virtual COM port as well as some + other components (mass storage etc.). However, this turns out to + 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 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, 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: + + - 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/BootLoaders/Boards/stm32/system/libmaple/usb/rules.mk b/BootLoaders/Boards/stm32/system/libmaple/usb/rules.mk new file mode 100644 index 0000000..e8ccc15 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/usb/rules.mk @@ -0,0 +1,45 @@ +# Standard things +sp := $(sp).x +dirstack_$(sp) := $(d) +d := $(dir) +BUILDDIRS += $(BUILD_PATH)/$(d) + +# Local flags +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) := +# 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)/%) + +OBJS_$(d) := $(sFILES_$(d):%.S=$(BUILD_PATH)/%.o) \ + $(cFILES_$(d):%.c=$(BUILD_PATH)/%.o) +DEPS_$(d) := $(OBJS_$(d):%.o=%.d) + +$(OBJS_$(d)): TGT_CFLAGS := $(CFLAGS_$(d)) +$(OBJS_$(d)): TGT_ASFLAGS := + +TGT_BIN += $(OBJS_$(d)) + +# Standard things +-include $(DEPS_$(d)) +d := $(dirstack_$(sp)) +sp := $(basename $(sp)) diff --git a/BootLoaders/Boards/stm32/system/libmaple/usb/stm32f1/usb_lib_globals.h b/BootLoaders/Boards/stm32/system/libmaple/usb/stm32f1/usb_lib_globals.h new file mode 100644 index 0000000..1cd2754 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/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/BootLoaders/Boards/stm32/system/libmaple/usb/stm32f1/usb_reg_map.h b/BootLoaders/Boards/stm32/system/libmaple/usb/stm32f1/usb_reg_map.h new file mode 100644 index 0000000..d0423fc --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/usb/stm32f1/usb_reg_map.h @@ -0,0 +1,617 @@ +/****************************************************************************** + * 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_EP_KIND_DBL_BUF (0x1 << 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 uint32 usb_get_ep_dtog_tx(uint8 ep) { + uint32 epr = USB_BASE->EP[ep]; + return epr & USB_EP_DTOG_TX; +} + +static inline uint32 usb_get_ep_dtog_rx(uint8 ep) { + uint32 epr = USB_BASE->EP[ep]; + return epr & USB_EP_DTOG_RX; +} + +static inline uint32 usb_get_ep_tx_sw_buf(uint8 ep) { + return usb_get_ep_dtog_rx(ep); +} + +static inline uint32 usb_get_ep_rx_sw_buf(uint8 ep) { + return usb_get_ep_dtog_tx(ep); +} + +static inline void usb_toggle_ep_dtog_tx(uint8 ep) { + uint32 epr = USB_BASE->EP[ep]; + epr &= __EP_NONTOGGLE; + epr |= USB_EP_DTOG_TX; + USB_BASE->EP[ep] = epr; +} + +static inline void usb_toggle_ep_dtog_rx(uint8 ep) { + uint32 epr = USB_BASE->EP[ep]; + epr &= __EP_NONTOGGLE; + epr |= USB_EP_DTOG_RX; + USB_BASE->EP[ep] = epr; +} + +static inline void usb_clear_ep_dtog_tx(uint8 ep) { + if (usb_get_ep_dtog_tx(ep) != 0) { + usb_toggle_ep_dtog_tx(ep); + } +} + +static inline void usb_clear_ep_dtog_rx(uint8 ep) { + if (usb_get_ep_dtog_rx(ep) != 0) { + usb_toggle_ep_dtog_rx(ep); + } +} + +static inline void usb_set_ep_dtog_tx(uint8 ep) { + if (usb_get_ep_dtog_tx(ep) == 0) { + usb_toggle_ep_dtog_tx(ep); + } +} + +static inline void usb_set_ep_dtog_rx(uint8 ep) { + if (usb_get_ep_dtog_rx(ep) == 0) { + usb_toggle_ep_dtog_rx(ep); + } +} + +static inline void usb_toggle_ep_rx_sw_buf(uint8 ep) { + usb_toggle_ep_dtog_tx(ep); +} + +static inline void usb_toggle_ep_tx_sw_buf(uint8 ep) { + usb_toggle_ep_dtog_rx(ep); +} + +static inline void usb_clear_ep_rx_sw_buf(uint8 ep) { + usb_clear_ep_dtog_tx(ep); +} + +static inline void usb_clear_ep_tx_sw_buf(uint8 ep) { + usb_clear_ep_dtog_rx(ep); +} + +static inline void usb_set_ep_rx_sw_buf(uint8 ep) { + usb_set_ep_dtog_tx(ep); +} + +static inline void usb_set_ep_tx_sw_buf(uint8 ep) { + usb_set_ep_dtog_rx(ep); +} + +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 uint32 usb_get_ep_type(uint8 ep) { + uint32 epr = USB_BASE->EP[ep]; + return epr & USB_EP_EP_TYPE; +} + +static inline uint32 usb_get_ep_kind(uint8 ep) { + uint32 epr = USB_BASE->EP[ep]; + return epr & USB_EP_EP_TYPE; +} + + +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 uint32 * usb_pma_ptr(uint32 offset) { + return (uint32*)(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); +} + +/* 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) { + volatile 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) { + volatile 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) { + /* FIXME: this is broken somehow; calling it seems to + * confuse/crash the chip. */ + return (uint16)(*usb_ep_tx_count_ptr(ep) & 0x3FF); +} + +static inline void usb_set_ep_tx_count(uint8 ep, uint16 count) { + volatile 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); + +/* double buffer definitions */ +static inline uint32* usb_get_ep_tx_buf0_addr_ptr(uint8 ep) { + return usb_ep_tx_addr_ptr(ep); +} + +static inline uint16 usb_get_ep_tx_buf0_addr(uint8 ep) { + return usb_get_ep_tx_addr(ep); +} + +static inline void usb_set_ep_tx_buf0_addr(uint8 ep, uint16 addr) { + usb_set_ep_tx_addr(ep, addr); +} + +static inline uint32* usb_get_ep_tx_buf1_addr_ptr(uint8 ep) { + return usb_ep_rx_addr_ptr(ep); +} + +static inline uint16 usb_get_ep_tx_buf1_addr(uint8 ep) { + return usb_get_ep_rx_addr(ep); +} + +static inline void usb_set_ep_tx_buf1_addr(uint8 ep, uint16 addr) { + usb_set_ep_rx_addr(ep, addr); +} + +static inline uint32* usb_ep_tx_buf0_count_ptr(uint8 ep) { + return usb_ep_tx_count_ptr(ep); +} + +static inline uint16 usb_get_ep_tx_buf0_count(uint8 ep) { + return usb_get_ep_tx_count(ep); +} + +static inline void usb_set_ep_tx_buf0_count(uint8 ep, uint16 count) { + usb_set_ep_tx_count(ep, count); +} + +static inline uint32* usb_ep_tx_buf1_count_ptr(uint8 ep) { + return usb_ep_rx_count_ptr(ep); +} + +static inline uint16 usb_get_ep_tx_buf1_count(uint8 ep) { + return usb_get_ep_rx_count(ep); +} + +static inline void usb_set_ep_tx_buf1_count(uint8 ep, uint16 count) { + usb_set_ep_rx_count(ep, count); +} +static inline uint32* usb_get_ep_rx_buf0_addr_ptr(uint8 ep) { + return usb_ep_tx_addr_ptr(ep); +} + +static inline uint16 usb_get_ep_rx_buf0_addr(uint8 ep) { + return usb_get_ep_tx_addr(ep); +} + +static inline void usb_set_ep_rx_buf0_addr(uint8 ep, uint16 addr) { + usb_set_ep_tx_addr(ep, addr); +} + +static inline uint32* usb_get_ep_rx_buf1_addr_ptr(uint8 ep) { + return usb_ep_rx_addr_ptr(ep); +} + +static inline uint16 usb_get_ep_rx_buf1_addr(uint8 ep) { + return usb_get_ep_rx_addr(ep); +} + +static inline void usb_set_ep_rx_buf1_addr(uint8 ep, uint16 addr) { + usb_set_ep_rx_addr(ep, addr); +} + +static inline uint32* usb_ep_rx_buf0_count_ptr(uint8 ep) { + return usb_ep_tx_count_ptr(ep); +} + +static inline uint16 usb_get_ep_rx_buf0_count(uint8 ep) { + return usb_get_ep_tx_count(ep); +} + +//void usb_set_ep_rx_buf0_count(uint8 ep, uint16 count); + +static inline uint32* usb_ep_rx_buf1_count_ptr(uint8 ep) { + return usb_ep_rx_count_ptr(ep); +} + +static inline uint16 usb_get_ep_rx_buf1_count(uint8 ep) { + return usb_get_ep_rx_count(ep); +} + +static inline void usb_set_ep_rx_buf1_count(uint8 ep, uint16 count) { + usb_set_ep_rx_count(ep, 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/BootLoaders/Boards/stm32/system/libmaple/usb/usb_lib/usb_core.h b/BootLoaders/Boards/stm32/system/libmaple/usb/usb_lib/usb_core.h new file mode 100644 index 0000000..cb8c21e --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/usb/usb_lib/usb_core.h @@ -0,0 +1,254 @@ +/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** +* File Name : usb_core.h +* Author : MCD Application Team +* Version : V2.2.1 +* Date : 09/22/2008 +* Description : Standard protocol processing functions prototypes +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_CORE_H +#define __USB_CORE_H + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +/* Exported types ------------------------------------------------------------*/ +typedef enum _CONTROL_STATE +{ + WAIT_SETUP, /* 0 */ + SETTING_UP, /* 1 */ + IN_DATA, /* 2 */ + OUT_DATA, /* 3 */ + LAST_IN_DATA, /* 4 */ + LAST_OUT_DATA, /* 5 */ + WAIT_STATUS_IN, /* 7 */ + WAIT_STATUS_OUT, /* 8 */ + STALLED, /* 9 */ + PAUSE /* 10 */ +} CONTROL_STATE; /* The state machine states of a control pipe */ + +typedef struct OneDescriptor +{ + u8 *Descriptor; + u16 Descriptor_Size; +} +ONE_DESCRIPTOR, *PONE_DESCRIPTOR; +/* All the request process routines return a value of this type + If the return value is not SUCCESS or NOT_READY, + the software will STALL the correspond endpoint */ +typedef enum _RESULT +{ + USB_SUCCESS = 0, /* Process sucessfully */ + USB_ERROR, + USB_UNSUPPORT, + USB_NOT_READY /* The process has not been finished, endpoint will be + NAK to further rquest */ +} RESULT; + + +/*-*-*-*-*-*-*-*-*-*-* Definitions for endpoint level -*-*-*-*-*-*-*-*-*-*-*-*/ +typedef struct _ENDPOINT_INFO +{ + /* When send data out of the device, + CopyData() is used to get data buffer 'Length' bytes data + if Length is 0, + CopyData() returns the total length of the data + if the request is not supported, returns 0 + (NEW Feature ) + if CopyData() returns -1, the calling routine should not proceed + further and will resume the SETUP process by the class device + if Length is not 0, + CopyData() returns a pointer to indicate the data location + Usb_wLength is the data remain to be sent, + Usb_wOffset is the Offset of original data + When receive data from the host, + CopyData() is used to get user data buffer which is capable + of Length bytes data to copy data from the endpoint buffer. + if Length is 0, + CopyData() returns the available data length, + if Length is not 0, + CopyData() returns user buffer address + Usb_rLength is the data remain to be received, + Usb_rPointer is the Offset of data buffer + */ + u16 Usb_wLength; + u16 Usb_wOffset; + u16 PacketSize; + u8 *(*CopyData)(u16 Length); +}ENDPOINT_INFO; + +/*-*-*-*-*-*-*-*-*-*-*-* Definitions for device level -*-*-*-*-*-*-*-*-*-*-*-*/ + +typedef struct _DEVICE +{ + u8 Total_Endpoint; /* Number of endpoints that are used */ + u8 Total_Configuration;/* Number of configuration available */ +} +DEVICE; + +typedef union +{ + u16 w; + struct BW + { + /* Little Endian */ + u8 bb0; + u8 bb1; + } + bw; +} u16_u8; + +typedef struct _DEVICE_INFO +{ + u8 USBbmRequestType; /* bmRequestType */ + u8 USBbRequest; /* bRequest */ + u16_u8 USBwValues; /* wValue */ + u16_u8 USBwIndexs; /* wIndex */ + u16_u8 USBwLengths; /* wLength */ + + u8 ControlState; /* of type CONTROL_STATE */ + u8 Current_Feature; + u8 Current_Configuration; /* Selected configuration */ + u8 Current_Interface; /* Selected interface of current configuration */ + u8 Current_AlternateSetting;/* Selected Alternate Setting of current + interface*/ + + ENDPOINT_INFO Ctrl_Info; +}DEVICE_INFO; + +typedef struct _DEVICE_PROP +{ + void (*Init)(void); /* Initialize the device */ + void (*Reset)(void); /* Reset routine of this device */ + + /* Device dependent process after the status stage */ + void (*Process_Status_IN)(void); + void (*Process_Status_OUT)(void); + + /* Procedure of process on setup stage of a class specified request with data stage */ + /* All class specified requests with data stage are processed in Class_Data_Setup + Class_Data_Setup() + responses to check all special requests and fills ENDPOINT_INFO + according to the request + If IN tokens are expected, then wLength & wOffset will be filled + with the total transferring bytes and the starting position + If OUT tokens are expected, then rLength & rOffset will be filled + with the total expected bytes and the starting position in the buffer + + If the request is valid, Class_Data_Setup returns SUCCESS, else UNSUPPORT + + CAUTION: + Since GET_CONFIGURATION & GET_INTERFACE are highly related to + the individual classes, they will be checked and processed here. + */ + RESULT (*Class_Data_Setup)(u8 RequestNo); + + /* Procedure of process on setup stage of a class specified request without data stage */ + /* All class specified requests without data stage are processed in Class_NoData_Setup + Class_NoData_Setup + responses to check all special requests and perform the request + + CAUTION: + Since SET_CONFIGURATION & SET_INTERFACE are highly related to + the individual classes, they will be checked and processed here. + */ + RESULT (*Class_NoData_Setup)(u8 RequestNo); + + /*Class_Get_Interface_Setting + This function is used by the file usb_core.c to test if the selected Interface + and Alternate Setting (u8 Interface, u8 AlternateSetting) are supported by + the application. + This function is writing by user. It should return "SUCCESS" if the Interface + and Alternate Setting are supported by the application or "UNSUPPORT" if they + are not supported. */ + + RESULT (*Class_Get_Interface_Setting)(u8 Interface, u8 AlternateSetting); + + u8* (*GetDeviceDescriptor)(u16 Length); + u8* (*GetConfigDescriptor)(u16 Length); + u8* (*GetStringDescriptor)(u16 Length); + + u8* RxEP_buffer; + u8 MaxPacketSize; + +}DEVICE_PROP; + +typedef struct _USER_STANDARD_REQUESTS +{ + void (*User_GetConfiguration)(void); /* Get Configuration */ + void (*User_SetConfiguration)(void); /* Set Configuration */ + void (*User_GetInterface)(void); /* Get Interface */ + void (*User_SetInterface)(void); /* Set Interface */ + void (*User_GetStatus)(void); /* Get Status */ + void (*User_ClearFeature)(void); /* Clear Feature */ + void (*User_SetEndPointFeature)(void); /* Set Endpoint Feature */ + void (*User_SetDeviceFeature)(void); /* Set Device Feature */ + void (*User_SetDeviceAddress)(void); /* Set Device Address */ +} +USER_STANDARD_REQUESTS; + +/* Exported constants --------------------------------------------------------*/ +#define Type_Recipient (pInformation->USBbmRequestType & (REQUEST_TYPE | RECIPIENT)) + +#define Usb_rLength Usb_wLength +#define Usb_rOffset Usb_wOffset + +#define USBwValue USBwValues.w +#define USBwValue0 USBwValues.bw.bb0 +#define USBwValue1 USBwValues.bw.bb1 +#define USBwIndex USBwIndexs.w +#define USBwIndex0 USBwIndexs.bw.bb0 +#define USBwIndex1 USBwIndexs.bw.bb1 +#define USBwLength USBwLengths.w +#define USBwLength0 USBwLengths.bw.bb0 +#define USBwLength1 USBwLengths.bw.bb1 +#define StatusInfo0 StatusInfo.bw.bb0 +#define StatusInfo1 StatusInfo.bw.bb1 + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ +u8 Setup0_Process(void); +u8 Post0_Process(void); +u8 Out0_Process(void); +u8 In0_Process(void); + +RESULT Standard_SetEndPointFeature(void); +RESULT Standard_SetDeviceFeature(void); + +u8 *Standard_GetConfiguration(u16 Length); +RESULT Standard_SetConfiguration(void); +u8 *Standard_GetInterface(u16 Length); +RESULT Standard_SetInterface(void); +u8 *Standard_GetDescriptorData(u16 Length, PONE_DESCRIPTOR pDesc); + +u8 *Standard_GetStatus(u16 Length); +RESULT Standard_ClearFeature(void); +void SetDeviceAddress(u8); +void NOP_Process(void); + +extern DEVICE_PROP Device_Property; +extern USER_STANDARD_REQUESTS User_Standard_Requests; +extern DEVICE Device_Table; +extern DEVICE_INFO Device_Info; + +/* cells saving status during interrupt servicing */ +extern u16 SaveRState; +extern u16 SaveTState; + +#if defined(__cplusplus) +} +#endif + +#endif /* __USB_CORE_H */ + +/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/BootLoaders/Boards/stm32/system/libmaple/usb/usb_lib/usb_def.h b/BootLoaders/Boards/stm32/system/libmaple/usb/usb_lib/usb_def.h new file mode 100644 index 0000000..80aa303 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/usb/usb_lib/usb_def.h @@ -0,0 +1,88 @@ +/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** +* File Name : usb_def.h +* Author : MCD Application Team +* Version : V2.2.1 +* Date : 09/22/2008 +* Description : Definitions related to USB Core +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_DEF_H +#define __USB_DEF_H + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +/* Exported types ------------------------------------------------------------*/ +typedef enum _RECIPIENT_TYPE +{ + DEVICE_RECIPIENT, /* Recipient device */ + INTERFACE_RECIPIENT, /* Recipient interface */ + ENDPOINT_RECIPIENT, /* Recipient endpoint */ + OTHER_RECIPIENT +} RECIPIENT_TYPE; + + +typedef enum _STANDARD_REQUESTS +{ + GET_STATUS = 0, + CLEAR_FEATURE, + RESERVED1, + SET_FEATURE, + RESERVED2, + SET_ADDRESS, + GET_DESCRIPTOR, + SET_DESCRIPTOR, + GET_CONFIGURATION, + SET_CONFIGURATION, + GET_INTERFACE, + SET_INTERFACE, + TOTAL_sREQUEST, /* Total number of Standard request */ + SYNCH_FRAME = 12 +} STANDARD_REQUESTS; + +/* Definition of "USBwValue" */ +typedef enum _DESCRIPTOR_TYPE +{ + DEVICE_DESCRIPTOR = 1, + CONFIG_DESCRIPTOR, + STRING_DESCRIPTOR, + INTERFACE_DESCRIPTOR, + ENDPOINT_DESCRIPTOR +} DESCRIPTOR_TYPE; + +/* Feature selector of a SET_FEATURE or CLEAR_FEATURE */ +typedef enum _FEATURE_SELECTOR +{ + ENDPOINT_STALL, + DEVICE_REMOTE_WAKEUP +} FEATURE_SELECTOR; + +/* Exported constants --------------------------------------------------------*/ +/* Definition of "USBbmRequestType" */ +#define REQUEST_TYPE 0x60 /* Mask to get request type */ +#define STANDARD_REQUEST 0x00 /* Standard request */ +#define CLASS_REQUEST 0x20 /* Class request */ +#define VENDOR_REQUEST 0x40 /* Vendor request */ + +#define RECIPIENT 0x1F /* Mask to get recipient */ + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ + +#if defined(__cplusplus) +} +#endif + +#endif /* __USB_DEF_H */ + +/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/BootLoaders/Boards/stm32/system/libmaple/usb/usb_lib/usb_init.h b/BootLoaders/Boards/stm32/system/libmaple/usb/usb_lib/usb_init.h new file mode 100644 index 0000000..80ee2fb --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/usb/usb_lib/usb_init.h @@ -0,0 +1,57 @@ +/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** +* File Name : usb_init.h +* Author : MCD Application Team +* Version : V2.2.1 +* Date : 09/22/2008 +* Description : Initialization routines & global variables +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_INIT_H +#define __USB_INIT_H + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ +void USB_Init(void); + +/* External variables --------------------------------------------------------*/ +/* The number of current endpoint, it will be used to specify an endpoint */ +extern u8 EPindex; +/* The number of current device, it is an index to the Device_Table */ +/*extern u8 Device_no; */ +/* Points to the DEVICE_INFO structure of current device */ +/* The purpose of this register is to speed up the execution */ +extern DEVICE_INFO* pInformation; +/* Points to the DEVICE_PROP structure of current device */ +/* The purpose of this register is to speed up the execution */ +extern DEVICE_PROP* pProperty; +/* Temporary save the state of Rx & Tx status. */ +/* Whenever the Rx or Tx state is changed, its value is saved */ +/* in this variable first and will be set to the EPRB or EPRA */ +/* at the end of interrupt process */ +extern USER_STANDARD_REQUESTS *pUser_Standard_Requests; + +extern u16 SaveState ; +extern u16 wInterrupt_Mask; + +#if defined(__cplusplus) +} +#endif + +#endif /* __USB_INIT_H */ + +/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/BootLoaders/Boards/stm32/system/libmaple/usb/usb_lib/usb_lib.h b/BootLoaders/Boards/stm32/system/libmaple/usb/usb_lib/usb_lib.h new file mode 100644 index 0000000..85f94ab --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/usb/usb_lib/usb_lib.h @@ -0,0 +1,36 @@ +/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** +* File Name : usb_lib.h +* Author : MCD Application Team +* Version : V2.2.1 +* Date : 09/22/2008 +* Description : USB library include files +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_LIB_H +#define __USB_LIB_H + +/* Includes ------------------------------------------------------------------*/ +#include "usb_type.h" +#include "usb_regs.h" +#include "usb_def.h" +#include "usb_core.h" +#include "usb_init.h" +#include "usb_mem.h" + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ +/* External variables --------------------------------------------------------*/ + +#endif /* __USB_LIB_H */ + +/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/BootLoaders/Boards/stm32/system/libmaple/usb/usb_lib/usb_mem.h b/BootLoaders/Boards/stm32/system/libmaple/usb/usb_lib/usb_mem.h new file mode 100644 index 0000000..b0e0474 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/usb/usb_lib/usb_mem.h @@ -0,0 +1,40 @@ +/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** +* File Name : usb_mem.h +* Author : MCD Application Team +* Version : V2.2.1 +* Date : 09/22/2008 +* Description : Utility prototypes functions for memory/PMA transfers +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_MEM_H +#define __USB_MEM_H + +/* Includes ------------------------------------------------------------------*/ +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ +#if defined(__cplusplus) +extern "C" { +#endif + +void UserToPMABufferCopy(const u8 *pbUsrBuf, u16 wPMABufAddr, u16 wNBytes); +void PMAToUserBufferCopy(u8 *pbUsrBuf, u16 wPMABufAddr, u16 wNBytes); + +#if defined(__cplusplus) +} +#endif + +/* External variables --------------------------------------------------------*/ + +#endif /*__USB_MEM_H*/ + +/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/BootLoaders/Boards/stm32/system/libmaple/usb/usb_lib/usb_regs.h b/BootLoaders/Boards/stm32/system/libmaple/usb/usb_lib/usb_regs.h new file mode 100644 index 0000000..b63cc5f --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/usb/usb_lib/usb_regs.h @@ -0,0 +1,627 @@ +/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** +* File Name : usb_regs.h +* Author : MCD Application Team +* Version : V2.2.1 +* Date : 09/22/2008 +* Description : Interface prototype functions to USB cell registers +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_REGS_H +#define __USB_REGS_H + +/* Includes ------------------------------------------------------------------*/ +/* Exported types ------------------------------------------------------------*/ +#if defined(__cplusplus) +extern "C" { +#endif + +typedef enum _EP_DBUF_DIR +{ + /* double buffered endpoint direction */ + EP_DBUF_ERR, + EP_DBUF_OUT, + EP_DBUF_IN +}EP_DBUF_DIR; + +/* endpoint buffer number */ +enum EP_BUF_NUM +{ + EP_NOBUF, + EP_BUF0, + EP_BUF1 +}; + +/* Exported constants --------------------------------------------------------*/ +#define RegBase (0x40005C00L) /* USB_IP Peripheral Registers base address */ +#define PMAAddr (0x40006000L) /* USB_IP Packet Memory Area base address */ + +/******************************************************************************/ +/* General registers */ +/******************************************************************************/ + +/* Control register */ +#define CNTR ((volatile unsigned *)(RegBase + 0x40)) +/* Interrupt status register */ +#define ISTR ((volatile unsigned *)(RegBase + 0x44)) +/* Frame number register */ +#define FNR ((volatile unsigned *)(RegBase + 0x48)) +/* Device address register */ +#define DADDR ((volatile unsigned *)(RegBase + 0x4C)) +/* Buffer Table address register */ +#define BTABLE ((volatile unsigned *)(RegBase + 0x50)) +/******************************************************************************/ +/* Endpoint registers */ +/******************************************************************************/ +#define EP0REG ((volatile unsigned *)(RegBase)) /* endpoint 0 register address */ + +/* endpoints enumeration */ +#define ENDP0 ((u8)0) +#define ENDP1 ((u8)1) +#define ENDP2 ((u8)2) +#define ENDP3 ((u8)3) +#define ENDP4 ((u8)4) +#define ENDP5 ((u8)5) +#define ENDP6 ((u8)6) +#define ENDP7 ((u8)7) +/******************************************************************************/ +/* ISTR interrupt events */ +/******************************************************************************/ +#define ISTR_CTR (0x8000) /* Correct TRansfer (clear-only bit) */ +#define ISTR_DOVR (0x4000) /* DMA OVeR/underrun (clear-only bit) */ +#define ISTR_ERR (0x2000) /* ERRor (clear-only bit) */ +#define ISTR_WKUP (0x1000) /* WaKe UP (clear-only bit) */ +#define ISTR_SUSP (0x0800) /* SUSPend (clear-only bit) */ +#define ISTR_RESET (0x0400) /* RESET (clear-only bit) */ +#define ISTR_SOF (0x0200) /* Start Of Frame (clear-only bit) */ +#define ISTR_ESOF (0x0100) /* Expected Start Of Frame (clear-only bit) */ + + +#define ISTR_DIR (0x0010) /* DIRection of transaction (read-only bit) */ +#define ISTR_EP_ID (0x000F) /* EndPoint IDentifier (read-only bit) */ + +#define CLR_CTR (~ISTR_CTR) /* clear Correct TRansfer bit */ +#define CLR_DOVR (~ISTR_DOVR) /* clear DMA OVeR/underrun bit*/ +#define CLR_ERR (~ISTR_ERR) /* clear ERRor bit */ +#define CLR_WKUP (~ISTR_WKUP) /* clear WaKe UP bit */ +#define CLR_SUSP (~ISTR_SUSP) /* clear SUSPend bit */ +#define CLR_RESET (~ISTR_RESET) /* clear RESET bit */ +#define CLR_SOF (~ISTR_SOF) /* clear Start Of Frame bit */ +#define CLR_ESOF (~ISTR_ESOF) /* clear Expected Start Of Frame bit */ + +/******************************************************************************/ +/* CNTR control register bits definitions */ +/******************************************************************************/ +#define CNTR_CTRM (0x8000) /* Correct TRansfer Mask */ +#define CNTR_DOVRM (0x4000) /* DMA OVeR/underrun Mask */ +#define CNTR_ERRM (0x2000) /* ERRor Mask */ +#define CNTR_WKUPM (0x1000) /* WaKe UP Mask */ +#define CNTR_SUSPM (0x0800) /* SUSPend Mask */ +#define CNTR_RESETM (0x0400) /* RESET Mask */ +#define CNTR_SOFM (0x0200) /* Start Of Frame Mask */ +#define CNTR_ESOFM (0x0100) /* Expected Start Of Frame Mask */ + + +#define CNTR_RESUME (0x0010) /* RESUME request */ +#define CNTR_FSUSP (0x0008) /* Force SUSPend */ +#define CNTR_LPMODE (0x0004) /* Low-power MODE */ +#define CNTR_PDWN (0x0002) /* Power DoWN */ +#define CNTR_FRES (0x0001) /* Force USB RESet */ + +/******************************************************************************/ +/* FNR Frame Number Register bit definitions */ +/******************************************************************************/ +#define FNR_RXDP (0x8000) /* status of D+ data line */ +#define FNR_RXDM (0x4000) /* status of D- data line */ +#define FNR_LCK (0x2000) /* LoCKed */ +#define FNR_LSOF (0x1800) /* Lost SOF */ +#define FNR_FN (0x07FF) /* Frame Number */ +/******************************************************************************/ +/* DADDR Device ADDRess bit definitions */ +/******************************************************************************/ +#define DADDR_EF (0x80) +#define DADDR_ADD (0x7F) +/******************************************************************************/ +/* Endpoint register */ +/******************************************************************************/ +/* bit positions */ +#define EP_CTR_RX (0x8000) /* EndPoint Correct TRansfer RX */ +#define EP_DTOG_RX (0x4000) /* EndPoint Data TOGGLE RX */ +#define EPRX_STAT (0x3000) /* EndPoint RX STATus bit field */ +#define EP_SETUP (0x0800) /* EndPoint SETUP */ +#define EP_T_FIELD (0x0600) /* EndPoint TYPE */ +#define EP_KIND (0x0100) /* EndPoint KIND */ +#define EP_CTR_TX (0x0080) /* EndPoint Correct TRansfer TX */ +#define EP_DTOG_TX (0x0040) /* EndPoint Data TOGGLE TX */ +#define EPTX_STAT (0x0030) /* EndPoint TX STATus bit field */ +#define EPADDR_FIELD (0x000F) /* EndPoint ADDRess FIELD */ + +/* EndPoint REGister MASK (no toggle fields) */ +#define EPREG_MASK (EP_CTR_RX|EP_SETUP|EP_T_FIELD|EP_KIND|EP_CTR_TX|EPADDR_FIELD) + +/* EP_TYPE[1:0] EndPoint TYPE */ +#define EP_TYPE_MASK (0x0600) /* EndPoint TYPE Mask */ +#define EP_BULK (0x0000) /* EndPoint BULK */ +#define EP_CONTROL (0x0200) /* EndPoint CONTROL */ +#define EP_ISOCHRONOUS (0x0400) /* EndPoint ISOCHRONOUS */ +#define EP_INTERRUPT (0x0600) /* EndPoint INTERRUPT */ +#define EP_T_MASK (~EP_T_FIELD & EPREG_MASK) + + +/* EP_KIND EndPoint KIND */ +#define EPKIND_MASK (~EP_KIND & EPREG_MASK) + +/* STAT_TX[1:0] STATus for TX transfer */ +#define EP_TX_DIS (0x0000) /* EndPoint TX DISabled */ +#define EP_TX_STALL (0x0010) /* EndPoint TX STALLed */ +#define EP_TX_NAK (0x0020) /* EndPoint TX NAKed */ +#define EP_TX_VALID (0x0030) /* EndPoint TX VALID */ +#define EPTX_DTOG1 (0x0010) /* EndPoint TX Data TOGgle bit1 */ +#define EPTX_DTOG2 (0x0020) /* EndPoint TX Data TOGgle bit2 */ +#define EPTX_DTOGMASK (EPTX_STAT|EPREG_MASK) + +/* STAT_RX[1:0] STATus for RX transfer */ +#define EP_RX_DIS (0x0000) /* EndPoint RX DISabled */ +#define EP_RX_STALL (0x1000) /* EndPoint RX STALLed */ +#define EP_RX_NAK (0x2000) /* EndPoint RX NAKed */ +#define EP_RX_VALID (0x3000) /* EndPoint RX VALID */ +#define EPRX_DTOG1 (0x1000) /* EndPoint RX Data TOGgle bit1 */ +#define EPRX_DTOG2 (0x2000) /* EndPoint RX Data TOGgle bit1 */ +#define EPRX_DTOGMASK (EPRX_STAT|EPREG_MASK) +/* Exported macro ------------------------------------------------------------*/ +/* SetCNTR */ +#define _SetCNTR(wRegValue) (*CNTR = (u16)wRegValue) + +/* SetISTR */ +#define _SetISTR(wRegValue) (*ISTR = (u16)wRegValue) + +/* SetDADDR */ +#define _SetDADDR(wRegValue) (*DADDR = (u16)wRegValue) + +/* SetBTABLE */ +#define _SetBTABLE(wRegValue)(*BTABLE = (u16)(wRegValue & 0xFFF8)) + +/* GetCNTR */ +#define _GetCNTR() ((u16) *CNTR) + +/* GetISTR */ +#define _GetISTR() ((u16) *ISTR) + +/* GetFNR */ +#define _GetFNR() ((u16) *FNR) + +/* GetDADDR */ +#define _GetDADDR() ((u16) *DADDR) + +/* GetBTABLE */ +#define _GetBTABLE() ((u16) *BTABLE) + +/* SetENDPOINT */ +#define _SetENDPOINT(bEpNum,wRegValue) (*(EP0REG + bEpNum)= \ + (u16)wRegValue) + +/* GetENDPOINT */ +#define _GetENDPOINT(bEpNum) ((u16)(*(EP0REG + bEpNum))) + +/******************************************************************************* +* Macro Name : SetEPType +* Description : sets the type in the endpoint register(bits EP_TYPE[1:0]) +* Input : bEpNum: Endpoint Number. +* wType +* Output : None. +* Return : None. +*******************************************************************************/ +#define _SetEPType(bEpNum,wType) (_SetENDPOINT(bEpNum,\ + ((_GetENDPOINT(bEpNum) & EP_T_MASK) | wType))) + +/******************************************************************************* +* Macro Name : GetEPType +* Description : gets the type in the endpoint register(bits EP_TYPE[1:0]) +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : Endpoint Type +*******************************************************************************/ +#define _GetEPType(bEpNum) (_GetENDPOINT(bEpNum) & EP_T_FIELD) + +/******************************************************************************* +* Macro Name : SetEPTxStatus +* Description : sets the status for tx transfer (bits STAT_TX[1:0]). +* Input : bEpNum: Endpoint Number. +* wState: new state +* Output : None. +* Return : None. +*******************************************************************************/ +#define _SetEPTxStatus(bEpNum,wState) {\ + register u16 _wRegVal; \ + _wRegVal = _GetENDPOINT(bEpNum) & EPTX_DTOGMASK;\ + /* toggle first bit ? */ \ + if((EPTX_DTOG1 & wState)!= 0) \ + _wRegVal ^= EPTX_DTOG1; \ + /* toggle second bit ? */ \ + if((EPTX_DTOG2 & wState)!= 0) \ + _wRegVal ^= EPTX_DTOG2; \ + _SetENDPOINT(bEpNum, _wRegVal); \ + } /* _SetEPTxStatus */ + +/******************************************************************************* +* Macro Name : SetEPRxStatus +* Description : sets the status for rx transfer (bits STAT_TX[1:0]) +* Input : bEpNum: Endpoint Number. +* wState: new state. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _SetEPRxStatus(bEpNum,wState) {\ + register u16 _wRegVal; \ + \ + _wRegVal = _GetENDPOINT(bEpNum) & EPRX_DTOGMASK;\ + /* toggle first bit ? */ \ + if((EPRX_DTOG1 & wState)!= 0) \ + _wRegVal ^= EPRX_DTOG1; \ + /* toggle second bit ? */ \ + if((EPRX_DTOG2 & wState)!= 0) \ + _wRegVal ^= EPRX_DTOG2; \ + _SetENDPOINT(bEpNum, _wRegVal); \ + } /* _SetEPRxStatus */ +/******************************************************************************* +* Macro Name : GetEPTxStatus / GetEPRxStatus +* Description : gets the status for tx/rx transfer (bits STAT_TX[1:0] +* /STAT_RX[1:0]) +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : status . +*******************************************************************************/ +#define _GetEPTxStatus(bEpNum) ((u16)_GetENDPOINT(bEpNum) & EPTX_STAT) + +#define _GetEPRxStatus(bEpNum) ((u16)_GetENDPOINT(bEpNum) & EPRX_STAT) + +/******************************************************************************* +* Macro Name : SetEPTxValid / SetEPRxValid +* Description : sets directly the VALID tx/rx-status into the enpoint register +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _SetEPTxValid(bEpNum) (_SetEPTxStatus(bEpNum, EP_TX_VALID)) + +#define _SetEPRxValid(bEpNum) (_SetEPRxStatus(bEpNum, EP_RX_VALID)) + +/******************************************************************************* +* Macro Name : GetTxStallStatus / GetRxStallStatus. +* Description : checks stall condition in an endpoint. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : TRUE = endpoint in stall condition. +*******************************************************************************/ +#define _GetTxStallStatus(bEpNum) (_GetEPTxStatus(bEpNum) \ + == EP_TX_STALL) +#define _GetRxStallStatus(bEpNum) (_GetEPRxStatus(bEpNum) \ + == EP_RX_STALL) + +/******************************************************************************* +* Macro Name : SetEP_KIND / ClearEP_KIND. +* Description : set & clear EP_KIND bit. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _SetEP_KIND(bEpNum) (_SetENDPOINT(bEpNum, \ + (_GetENDPOINT(bEpNum) | EP_KIND) & EPREG_MASK)) +#define _ClearEP_KIND(bEpNum) (_SetENDPOINT(bEpNum, \ + (_GetENDPOINT(bEpNum) & EPKIND_MASK))) + +/******************************************************************************* +* Macro Name : Set_Status_Out / Clear_Status_Out. +* Description : Sets/clears directly STATUS_OUT bit in the endpoint register. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _Set_Status_Out(bEpNum) _SetEP_KIND(bEpNum) +#define _Clear_Status_Out(bEpNum) _ClearEP_KIND(bEpNum) + +/******************************************************************************* +* Macro Name : SetEPDoubleBuff / ClearEPDoubleBuff. +* Description : Sets/clears directly EP_KIND bit in the endpoint register. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _SetEPDoubleBuff(bEpNum) _SetEP_KIND(bEpNum) +#define _ClearEPDoubleBuff(bEpNum) _ClearEP_KIND(bEpNum) + +/******************************************************************************* +* Macro Name : ClearEP_CTR_RX / ClearEP_CTR_TX. +* Description : Clears bit CTR_RX / CTR_TX in the endpoint register. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _ClearEP_CTR_RX(bEpNum) (_SetENDPOINT(bEpNum,\ + _GetENDPOINT(bEpNum) & 0x7FFF & EPREG_MASK)) +#define _ClearEP_CTR_TX(bEpNum) (_SetENDPOINT(bEpNum,\ + _GetENDPOINT(bEpNum) & 0xFF7F & EPREG_MASK)) + +/******************************************************************************* +* Macro Name : ToggleDTOG_RX / ToggleDTOG_TX . +* Description : Toggles DTOG_RX / DTOG_TX bit in the endpoint register. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _ToggleDTOG_RX(bEpNum) (_SetENDPOINT(bEpNum, \ + EP_DTOG_RX | (_GetENDPOINT(bEpNum) & EPREG_MASK))) +#define _ToggleDTOG_TX(bEpNum) (_SetENDPOINT(bEpNum, \ + EP_DTOG_TX | (_GetENDPOINT(bEpNum) & EPREG_MASK))) + +/******************************************************************************* +* Macro Name : ClearDTOG_RX / ClearDTOG_TX. +* Description : Clears DTOG_RX / DTOG_TX bit in the endpoint register. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _ClearDTOG_RX(bEpNum) if((_GetENDPOINT(bEpNum) & EP_DTOG_RX) != 0)\ + _ToggleDTOG_RX(bEpNum) +#define _ClearDTOG_TX(bEpNum) if((_GetENDPOINT(bEpNum) & EP_DTOG_TX) != 0)\ + _ToggleDTOG_TX(bEpNum) +/******************************************************************************* +* Macro Name : SetEPAddress. +* Description : Sets address in an endpoint register. +* Input : bEpNum: Endpoint Number. +* bAddr: Address. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _SetEPAddress(bEpNum,bAddr) _SetENDPOINT(bEpNum,\ + (_GetENDPOINT(bEpNum) & EPREG_MASK) | bAddr) + +/******************************************************************************* +* Macro Name : GetEPAddress. +* Description : Gets address in an endpoint register. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _GetEPAddress(bEpNum) ((u8)(_GetENDPOINT(bEpNum) & EPADDR_FIELD)) + +#define _pEPTxAddr(bEpNum) ((u32 *)((_GetBTABLE()+bEpNum*8 )*2 + PMAAddr)) +#define _pEPTxCount(bEpNum) ((u32 *)((_GetBTABLE()+bEpNum*8+2)*2 + PMAAddr)) +#define _pEPRxAddr(bEpNum) ((u32 *)((_GetBTABLE()+bEpNum*8+4)*2 + PMAAddr)) +#define _pEPRxCount(bEpNum) ((u32 *)((_GetBTABLE()+bEpNum*8+6)*2 + PMAAddr)) + +/******************************************************************************* +* Macro Name : SetEPTxAddr / SetEPRxAddr. +* Description : sets address of the tx/rx buffer. +* Input : bEpNum: Endpoint Number. +* wAddr: address to be set (must be word aligned). +* Output : None. +* Return : None. +*******************************************************************************/ +#define _SetEPTxAddr(bEpNum,wAddr) (*_pEPTxAddr(bEpNum) = ((wAddr >> 1) << 1)) +#define _SetEPRxAddr(bEpNum,wAddr) (*_pEPRxAddr(bEpNum) = ((wAddr >> 1) << 1)) + +/******************************************************************************* +* Macro Name : GetEPTxAddr / GetEPRxAddr. +* Description : Gets address of the tx/rx buffer. +* Input : bEpNum: Endpoint Number. +* Output : None. +* Return : address of the buffer. +*******************************************************************************/ +#define _GetEPTxAddr(bEpNum) ((u16)*_pEPTxAddr(bEpNum)) +#define _GetEPRxAddr(bEpNum) ((u16)*_pEPRxAddr(bEpNum)) + +/******************************************************************************* +* Macro Name : SetEPCountRxReg. +* Description : Sets counter of rx buffer with no. of blocks. +* Input : pdwReg: pointer to counter. +* wCount: Counter. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _BlocksOf32(dwReg,wCount,wNBlocks) {\ + wNBlocks = wCount >> 5;\ + if((wCount & 0x1f) == 0)\ + wNBlocks--;\ + *pdwReg = (u32)((wNBlocks << 10) | 0x8000);\ + }/* _BlocksOf32 */ + +#define _BlocksOf2(dwReg,wCount,wNBlocks) {\ + wNBlocks = wCount >> 1;\ + if((wCount & 0x1) != 0)\ + wNBlocks++;\ + *pdwReg = (u32)(wNBlocks << 10);\ + }/* _BlocksOf2 */ + +#define _SetEPCountRxReg(dwReg,wCount) {\ + u16 wNBlocks;\ + if(wCount > 62){_BlocksOf32(dwReg,wCount,wNBlocks);}\ + else {_BlocksOf2(dwReg,wCount,wNBlocks);}\ + }/* _SetEPCountRxReg */ + + + +#define _SetEPRxDblBuf0Count(bEpNum,wCount) {\ + u32 *pdwReg = _pEPTxCount(bEpNum); \ + _SetEPCountRxReg(pdwReg, wCount);\ + } +/******************************************************************************* +* Macro Name : SetEPTxCount / SetEPRxCount. +* Description : sets counter for the tx/rx buffer. +* Input : bEpNum: endpoint number. +* wCount: Counter value. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _SetEPTxCount(bEpNum,wCount) (*_pEPTxCount(bEpNum) = wCount) +#define _SetEPRxCount(bEpNum,wCount) {\ + u32 *pdwReg = _pEPRxCount(bEpNum); \ + _SetEPCountRxReg(pdwReg, wCount);\ + } +/******************************************************************************* +* Macro Name : GetEPTxCount / GetEPRxCount. +* Description : gets counter of the tx buffer. +* Input : bEpNum: endpoint number. +* Output : None. +* Return : Counter value. +*******************************************************************************/ +#define _GetEPTxCount(bEpNum)((u16)(*_pEPTxCount(bEpNum)) & 0x3ff) +#define _GetEPRxCount(bEpNum)((u16)(*_pEPRxCount(bEpNum)) & 0x3ff) + +/******************************************************************************* +* Macro Name : SetEPDblBuf0Addr / SetEPDblBuf1Addr. +* Description : Sets buffer 0/1 address in a double buffer endpoint. +* Input : bEpNum: endpoint number. +* : wBuf0Addr: buffer 0 address. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _SetEPDblBuf0Addr(bEpNum,wBuf0Addr) {_SetEPTxAddr(bEpNum, wBuf0Addr);} +#define _SetEPDblBuf1Addr(bEpNum,wBuf1Addr) {_SetEPRxAddr(bEpNum, wBuf1Addr);} + +/******************************************************************************* +* Macro Name : SetEPDblBuffAddr. +* Description : Sets addresses in a double buffer endpoint. +* Input : bEpNum: endpoint number. +* : wBuf0Addr: buffer 0 address. +* : wBuf1Addr = buffer 1 address. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _SetEPDblBuffAddr(bEpNum,wBuf0Addr,wBuf1Addr) { \ + _SetEPDblBuf0Addr(bEpNum, wBuf0Addr);\ + _SetEPDblBuf1Addr(bEpNum, wBuf1Addr);\ + } /* _SetEPDblBuffAddr */ + +/******************************************************************************* +* Macro Name : GetEPDblBuf0Addr / GetEPDblBuf1Addr. +* Description : Gets buffer 0/1 address of a double buffer endpoint. +* Input : bEpNum: endpoint number. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _GetEPDblBuf0Addr(bEpNum) (_GetEPTxAddr(bEpNum)) +#define _GetEPDblBuf1Addr(bEpNum) (_GetEPRxAddr(bEpNum)) + +/******************************************************************************* +* Macro Name : SetEPDblBuffCount / SetEPDblBuf0Count / SetEPDblBuf1Count. +* Description : Gets buffer 0/1 address of a double buffer endpoint. +* Input : bEpNum: endpoint number. +* : bDir: endpoint dir EP_DBUF_OUT = OUT +* EP_DBUF_IN = IN +* : wCount: Counter value +* Output : None. +* Return : None. +*******************************************************************************/ +#define _SetEPDblBuf0Count(bEpNum, bDir, wCount) { \ + if(bDir == EP_DBUF_OUT)\ + /* OUT endpoint */ \ + {_SetEPRxDblBuf0Count(bEpNum,wCount);} \ + else if(bDir == EP_DBUF_IN)\ + /* IN endpoint */ \ + *_pEPTxCount(bEpNum) = (u32)wCount; \ + } /* SetEPDblBuf0Count*/ + +#define _SetEPDblBuf1Count(bEpNum, bDir, wCount) { \ + if(bDir == EP_DBUF_OUT)\ + /* OUT endpoint */ \ + {_SetEPRxCount(bEpNum,wCount);}\ + else if(bDir == EP_DBUF_IN)\ + /* IN endpoint */\ + *_pEPRxCount(bEpNum) = (u32)wCount; \ + } /* SetEPDblBuf1Count */ + +#define _SetEPDblBuffCount(bEpNum, bDir, wCount) {\ + _SetEPDblBuf0Count(bEpNum, bDir, wCount); \ + _SetEPDblBuf1Count(bEpNum, bDir, wCount); \ + } /* _SetEPDblBuffCount */ + +/******************************************************************************* +* Macro Name : GetEPDblBuf0Count / GetEPDblBuf1Count. +* Description : Gets buffer 0/1 rx/tx counter for double buffering. +* Input : bEpNum: endpoint number. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _GetEPDblBuf0Count(bEpNum) (_GetEPTxCount(bEpNum)) +#define _GetEPDblBuf1Count(bEpNum) (_GetEPRxCount(bEpNum)) + + +/* External variables --------------------------------------------------------*/ +extern volatile u16 wIstr; /* ISTR register last read value */ + +/* Exported functions ------------------------------------------------------- */ +void SetCNTR(u16 /*wRegValue*/); +void SetISTR(u16 /*wRegValue*/); +void SetDADDR(u16 /*wRegValue*/); +void SetBTABLE(u16 /*wRegValue*/); +u16 GetCNTR(void); +u16 GetISTR(void); +u16 GetFNR(void); +u16 GetDADDR(void); +u16 GetBTABLE(void); +void SetENDPOINT(u8 /*bEpNum*/, u16 /*wRegValue*/); +u16 GetENDPOINT(u8 /*bEpNum*/); +void SetEPType(u8 /*bEpNum*/, u16 /*wType*/); +u16 GetEPType(u8 /*bEpNum*/); +void SetEPTxStatus(u8 /*bEpNum*/, u16 /*wState*/); +void SetEPRxStatus(u8 /*bEpNum*/, u16 /*wState*/); +void SetDouBleBuffEPStall(u8 /*bEpNum*/, u8 bDir); +u16 GetEPTxStatus(u8 /*bEpNum*/); +u16 GetEPRxStatus(u8 /*bEpNum*/); +void SetEPTxValid(u8 /*bEpNum*/); +void SetEPRxValid(u8 /*bEpNum*/); +u16 GetTxStallStatus(u8 /*bEpNum*/); +u16 GetRxStallStatus(u8 /*bEpNum*/); +void SetEP_KIND(u8 /*bEpNum*/); +void ClearEP_KIND(u8 /*bEpNum*/); +void Set_Status_Out(u8 /*bEpNum*/); +void Clear_Status_Out(u8 /*bEpNum*/); +void SetEPDoubleBuff(u8 /*bEpNum*/); +void ClearEPDoubleBuff(u8 /*bEpNum*/); +void ClearEP_CTR_RX(u8 /*bEpNum*/); +void ClearEP_CTR_TX(u8 /*bEpNum*/); +void ToggleDTOG_RX(u8 /*bEpNum*/); +void ToggleDTOG_TX(u8 /*bEpNum*/); +void ClearDTOG_RX(u8 /*bEpNum*/); +void ClearDTOG_TX(u8 /*bEpNum*/); +void SetEPAddress(u8 /*bEpNum*/, u8 /*bAddr*/); +u8 GetEPAddress(u8 /*bEpNum*/); +void SetEPTxAddr(u8 /*bEpNum*/, u16 /*wAddr*/); +void SetEPRxAddr(u8 /*bEpNum*/, u16 /*wAddr*/); +u16 GetEPTxAddr(u8 /*bEpNum*/); +u16 GetEPRxAddr(u8 /*bEpNum*/); +void SetEPCountRxReg(u32 * /*pdwReg*/, u16 /*wCount*/); +void SetEPTxCount(u8 /*bEpNum*/, u16 /*wCount*/); +void SetEPRxCount(u8 /*bEpNum*/, u16 /*wCount*/); +u16 GetEPTxCount(u8 /*bEpNum*/); +u16 GetEPRxCount(u8 /*bEpNum*/); +void SetEPDblBuf0Addr(u8 /*bEpNum*/, u16 /*wBuf0Addr*/); +void SetEPDblBuf1Addr(u8 /*bEpNum*/, u16 /*wBuf1Addr*/); +void SetEPDblBuffAddr(u8 /*bEpNum*/, u16 /*wBuf0Addr*/, u16 /*wBuf1Addr*/); +u16 GetEPDblBuf0Addr(u8 /*bEpNum*/); +u16 GetEPDblBuf1Addr(u8 /*bEpNum*/); +void SetEPDblBuffCount(u8 /*bEpNum*/, u8 /*bDir*/, u16 /*wCount*/); +void SetEPDblBuf0Count(u8 /*bEpNum*/, u8 /*bDir*/, u16 /*wCount*/); +void SetEPDblBuf1Count(u8 /*bEpNum*/, u8 /*bDir*/, u16 /*wCount*/); +u16 GetEPDblBuf0Count(u8 /*bEpNum*/); +u16 GetEPDblBuf1Count(u8 /*bEpNum*/); +EP_DBUF_DIR GetEPDblBufDir(u8 /*bEpNum*/); +void FreeUserBuffer(u8 bEpNum/*bEpNum*/, u8 bDir); +u16 ToWord(u8, u8); +u16 ByteSwap(u16); + +#if defined(__cplusplus) +} +#endif + +#endif /* __USB_REGS_H */ + +/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/BootLoaders/Boards/stm32/system/libmaple/usb/usb_lib/usb_type.h b/BootLoaders/Boards/stm32/system/libmaple/usb/usb_lib/usb_type.h new file mode 100644 index 0000000..34b3bf5 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/libmaple/usb/usb_lib/usb_type.h @@ -0,0 +1,77 @@ +/******************** (C) COPYRIGHT 2008 STMicroelectronics ******************** +* File Name : usb_type.h +* Author : MCD Application Team +* Version : V2.2.1 +* Date : 09/22/2008 +* Description : Type definitions used by the USB Library +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_TYPE_H +#define __USB_TYPE_H + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +#ifndef NULL +#define NULL ((void *)0) +#endif + +typedef signed long s32; +typedef signed short s16; +typedef signed char s8; + +typedef volatile signed long vs32; +typedef volatile signed short vs16; +typedef volatile signed char vs8; + +typedef unsigned long u32; +typedef unsigned short u16; +typedef unsigned char u8; + +typedef unsigned long const uc32; /* Read Only */ +typedef unsigned short const uc16; /* Read Only */ +typedef unsigned char const uc8; /* Read Only */ + +typedef volatile unsigned long vu32; +typedef volatile unsigned short vu16; +typedef volatile unsigned char vu8; + +typedef volatile unsigned long const vuc32; /* Read Only */ +typedef volatile unsigned short const vuc16; /* Read Only */ +typedef volatile unsigned char const vuc8; /* Read Only */ + + +typedef enum +{ + FALSE = 0, TRUE = !FALSE +} +USB_Bool; + +typedef enum { RESET = 0, SET = !RESET } FlagStatus, ITStatus; + +typedef enum { DISABLE = 0, ENABLE = !DISABLE} FunctionalState; + +typedef enum { ERROR = 0, SUCCESS = !ERROR} ErrorStatus; + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ +/* External variables --------------------------------------------------------*/ + +#if defined(__cplusplus) +} +#endif + +#endif /* __USB_TYPE_H */ + +/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/ diff --git a/BootLoaders/Boards/stm32/system/support/doxygen/Doxyfile b/BootLoaders/Boards/stm32/system/support/doxygen/Doxyfile new file mode 100644 index 0000000..170cff4 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/doxygen/Doxyfile @@ -0,0 +1,1648 @@ +# Doxyfile 1.7.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = libmaple + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = custom-build + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = ./doxygen + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = "sideeffect=\par Side Effects:\n" + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen to replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = YES + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penality. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will rougly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = YES + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = NO + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = NO + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = NO + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = ./libmaple/ \ + ./wirish/ \ + ./libraries/ + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS = *.h *.c + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +# We include the FreeRTOS sources. That's probably a mistake. Oh well. +EXCLUDE = ./libraries/FreeRTOS/ + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +# Trick Doxygen into thinking series headers are in separate +# namespaces; see the Evil Mangler source for more information. +FILTER_PATTERNS = */libmaple/stm32*/include/series/*.h=./support/doxygen/evil_mangler.awk + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the stylesheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvances is that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = YES + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = YES + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = NO + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = __attribute__()= \ + __deprecated= \ + __always_inline= \ + __packed = \ + __weak = \ + __cplusplus \ + STM32_MEDIUM_DENSITY \ + STM32_HIGH_DENSITY \ + STM32_XL_DENSITY \ + PCLK1=0 STM32_PCLK1=0 \ + PCLK2=0 STM32_PCLK2=0 \ + STM32_HAVE_TIMER(x)=1 \ + __DOXYGEN__ + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = NO + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will write a font called FreeSans.ttf to the output +# directory and reference it in all dot files that doxygen generates. This +# font does not include all possible unicode characters however, so when you need +# these (or just want a differently looking font) you can specify the font name +# using DOT_FONTNAME. You need need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = FreeSans.ttf + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = NO + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = NO + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = NO + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/BootLoaders/Boards/stm32/system/support/doxygen/evil_mangler.awk b/BootLoaders/Boards/stm32/system/support/doxygen/evil_mangler.awk new file mode 100644 index 0000000..b07da72 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/doxygen/evil_mangler.awk @@ -0,0 +1,38 @@ +#!/usr/bin/awk -f + +# libmaple's own Evil Mangler +# +# Input filter hack to trick Doxygen into thinking that a series +# header is in a separate namespace. This is necessary because Doxygen +# doesn't know how to cope with two data structures with the same name +# in different places in the project. (We do that all the time, +# e.g. for foo_reg_map structs.) +# +# E.g., an STM32F1 header gets transformed into: +# +# namespace stm32f1 { +# +# } + +BEGIN { + # For extracting series component from header FILENAME. + series_regex = "/stm32[flw][0-9]*/"; + # Holds header FILENAME. Cargo-culted; not sure why it's necessary. + f = ""; + # Holds series component. + series = ""; +} +{ + if (f != FILENAME) { + f = FILENAME; + match(f, series_regex); + series = substr(f, RSTART + 1, RLENGTH - 2); + printf("namespace %s {\n", series); + } + print; +} +END { + if (series != "") { + print "}" + } +} diff --git a/BootLoaders/Boards/stm32/system/support/gdb/gpio/gpio.gdb b/BootLoaders/Boards/stm32/system/support/gdb/gpio/gpio.gdb new file mode 100644 index 0000000..4376cfd --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/gdb/gpio/gpio.gdb @@ -0,0 +1,12 @@ +set print pretty on + +print "GPIOA registers:" +p/x *GPIOA->regs +print "GPIOB registers:" +p/x *GPIOB->regs +print "GPIOC registers:" +p/x *GPIOC->regs +print "GPIOD registers:" +p/x *GPIOD->regs +print "AFIO registers:" +p/x *(struct afio_reg_map*)0x40010000 diff --git a/BootLoaders/Boards/stm32/system/support/gdb/i2c/test.gdb b/BootLoaders/Boards/stm32/system/support/gdb/i2c/test.gdb new file mode 100644 index 0000000..8b71320 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/gdb/i2c/test.gdb @@ -0,0 +1,112 @@ +define i2c_sr1_flags +set $s = $arg0 +printf "SR1: " + +if (($s & (1 << 15))) + printf "SMBALERT " +end + +if (($s & (1 << 14))) + printf "TIMEOUT " +end + +if (($s & (1 << 12))) + printf "PECERR " +end + +if (($s & (1 << 11))) + printf "OVR " +end + +if (($s & (1 << 10))) + printf "AF " +end + +if (($s & (1 << 9))) + printf "ARLO " +end + +if (($s & (1 << 8))) + printf "BERR " +end + +if (($s & (1 << 7))) + printf "TXE " +end + +if (($s & (1 << 6))) + printf "RXNE " +end + +if (($s & (1 << 4))) + printf "STOPF " +end + +if (($s & (1 << 3))) + printf "ADD10 " +end + +if (($s & (1 << 2))) + printf "BTF " +end + +if (($s & (1 << 1))) + printf "ADDR " +end + +if (($s & (1 << 0))) + printf "SB " +end +end + +define i2c_sr2_flags +set $s = $arg0 +printf "SR2: " + +if (($s & (1 << 7))) + printf "DUALF " +end + +if (($s & (1 << 6))) + printf "SMBHOST " +end + +if (($s & (1 << 5))) + printf "SMBDEFAULT " +end + +if (($s & (1 << 4))) + printf "GENCALL " +end + + +if (($s & (1 << 2))) + printf "TRA " +end + +if (($s & (1 << 1))) + printf "BUSY " +end + +if (($s & (1 << 0))) + printf "MSL " +end + +end + +define pbc +set $c = crumbs +while ($c->event) + if ($c->event != 0) + printf "Event: %d ", $c->event + if ($c->event == 1) + i2c_sr1_flags $c->sr1 + printf "\t" + i2c_sr2_flags $c->sr2 + end + printf "\n" + end + set $c = $c + 1 +end + + diff --git a/BootLoaders/Boards/stm32/system/support/ld/common.inc b/BootLoaders/Boards/stm32/system/support/ld/common.inc new file mode 100644 index 0000000..f5a0f5b --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/ld/common.inc @@ -0,0 +1,219 @@ +/* + * Linker script for libmaple. + * + * Original author "lanchon" from ST forums, with modifications by LeafLabs. + */ + +OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") + +/* + * Configure other libraries we want in the link. + * + * libgcc, libc, and libm are common across supported toolchains. + * However, some toolchains require additional archives which aren't + * present everywhere (e.g. ARM's gcc-arm-embedded releases). + * + * To hack around this, we let the build system specify additional + * archives by putting the right extra_libs.inc (in a directory under + * toolchains/) in our search path. + */ +GROUP(libgcc.a libc.a libm.a) +INCLUDE extra_libs.inc + +/* + * These force the linker to search for vector table symbols. + * + * These symbols vary by STM32 family (and also within families). + * It's up to the build system to configure the link's search path + * properly for the target MCU. + */ +INCLUDE vector_symbols.inc + +/* STM32 vector table. */ +EXTERN(__stm32_vector_table) + +/* C runtime initialization function. */ +EXTERN(start_c) + +/* main entry point */ +EXTERN(main) + +/* Initial stack pointer value. */ +EXTERN(__msp_init) +PROVIDE(__msp_init = ORIGIN(ram) + LENGTH(ram)); + +/* Reset vector and chip reset entry point */ +EXTERN(__start__) +ENTRY(__start__) +PROVIDE(__exc_reset = __start__); + +/* Heap boundaries, for libmaple */ +EXTERN(_lm_heap_start); +EXTERN(_lm_heap_end); + +SECTIONS +{ + .text : + { + __text_start__ = .; + /* + * STM32 vector table. Leave this here. Yes, really. + */ + *(.stm32.interrupt_vector) + + /* + * Program code and vague linking + */ + *(.text .text.* .gnu.linkonce.t.*) + *(.plt) + *(.gnu.warning) + *(.glue_7t) *(.glue_7) *(.vfp11_veneer) + + *(.ARM.extab* .gnu.linkonce.armextab.*) + *(.gcc_except_table) + *(.eh_frame_hdr) + *(.eh_frame) + + . = ALIGN(4); + KEEP(*(.init)) + + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(0x4); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + } > REGION_TEXT + + /* + * End of text + */ + .text.align : + { + . = ALIGN(8); + __text_end__ = .; + } > REGION_TEXT + + /* + * .ARM.exidx exception unwinding; mandated by ARM's C++ ABI + */ + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > REGION_RODATA + __exidx_end = .; + + /* + * .data + */ + .data : + { + . = ALIGN(8); + __data_start__ = .; + + *(.got.plt) *(.got) + *(.data .data.* .gnu.linkonce.d.*) + + . = ALIGN(8); + __data_end__ = .; + } > REGION_DATA AT> REGION_RODATA + + /* + * Read-only data + */ + .rodata : + { + *(.rodata .rodata.* .gnu.linkonce.r.*) + /* .USER_FLASH: We allow users to allocate into Flash here */ + *(.USER_FLASH) + /* ROM image configuration; for C startup */ + . = ALIGN(4); + _lm_rom_img_cfgp = .; + LONG(LOADADDR(.data)); + /* + * Heap: Linker scripts may choose a custom heap by overriding + * _lm_heap_start and _lm_heap_end. Otherwise, the heap is in + * internal SRAM, beginning after .bss, and growing towards + * the stack. + * + * I'm shoving these here naively; there's probably a cleaner way + * to go about this. [mbolivar] + */ + _lm_heap_start = DEFINED(_lm_heap_start) ? _lm_heap_start : _end; + _lm_heap_end = DEFINED(_lm_heap_end) ? _lm_heap_end : __msp_init; + } > REGION_RODATA + + /* + * .bss + */ + .bss : + { + . = ALIGN(8); + __bss_start__ = .; + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + __bss_end__ = .; + _end = __bss_end__; + } > REGION_BSS + + /* + * Debugging sections + */ + .stab 0 (NOLOAD) : { *(.stab) } + .stabstr 0 (NOLOAD) : { *(.stabstr) } + /* DWARF debug sections. + * Symbols in the DWARF debugging sections are relative to the beginning + * of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + + .note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) } + .ARM.attributes 0 : { KEEP (*(.ARM.attributes)) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/BootLoaders/Boards/stm32/system/support/ld/flash.ld b/BootLoaders/Boards/stm32/system/support/ld/flash.ld new file mode 100644 index 0000000..9e250cd --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/ld/flash.ld @@ -0,0 +1,26 @@ +/* + * libmaple linker script for "Flash" builds. + * + * A Flash build puts .text (and .rodata) in Flash, and + * .data/.bss/heap (of course) in SRAM, but offsets the sections by + * enough space to store the Maple bootloader, which lives in low + * Flash and uses low memory. + */ + +/* + * This pulls in the appropriate MEMORY declaration from the right + * subdirectory of stm32/mem/ (the environment must call ld with the + * right include directory flags to make this happen). Boards can also + * use this file to use any of libmaple's memory-related hooks (like + * where the heap should live). + */ +INCLUDE mem-flash.inc + +/* Provide memory region aliases for common.inc */ +REGION_ALIAS("REGION_TEXT", rom); +REGION_ALIAS("REGION_DATA", ram); +REGION_ALIAS("REGION_BSS", ram); +REGION_ALIAS("REGION_RODATA", rom); + +/* Let common.inc handle the real work. */ +INCLUDE common.inc diff --git a/BootLoaders/Boards/stm32/system/support/ld/jtag.ld b/BootLoaders/Boards/stm32/system/support/ld/jtag.ld new file mode 100644 index 0000000..0612f95 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/ld/jtag.ld @@ -0,0 +1,31 @@ +/* + * libmaple linker script for "JTAG" builds. + * + * A "JTAG" build puts .text (and .rodata) in Flash, and + * .data/.bss/heap (of course) in SRAM, but links starting at the + * Flash and SRAM starting addresses (0x08000000 and 0x20000000 + * respectively). This will wipe out a Maple bootloader if there's one + * on the board, so only use this if you know what you're doing. + * + * Of course, a "JTAG" build is perfectly usable for upload over SWD, + * the system memory bootloader, etc. The name is just a historical + * artifact. + */ + +/* + * This pulls in the appropriate MEMORY declaration from the right + * subdirectory of stm32/mem/ (the environment must call ld with the + * right include directory flags to make this happen). Boards can also + * use this file to use any of libmaple's memory-related hooks (like + * where the heap should live). + */ +INCLUDE mem-jtag.inc + +/* Provide memory region aliases for common.inc */ +REGION_ALIAS("REGION_TEXT", rom); +REGION_ALIAS("REGION_DATA", ram); +REGION_ALIAS("REGION_BSS", ram); +REGION_ALIAS("REGION_RODATA", rom); + +/* Let common.inc handle the real work. */ +INCLUDE common.inc diff --git a/BootLoaders/Boards/stm32/system/support/ld/ram.ld b/BootLoaders/Boards/stm32/system/support/ld/ram.ld new file mode 100644 index 0000000..34b468e --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/ld/ram.ld @@ -0,0 +1,25 @@ +/* + * libmaple linker script for RAM builds. + * + * A Flash build puts .text, .rodata, and .data/.bss/heap (of course) + * in SRAM, but offsets the sections by enough space to store the + * Maple bootloader, which uses low memory. + */ + +/* + * This pulls in the appropriate MEMORY declaration from the right + * subdirectory of stm32/mem/ (the environment must call ld with the + * right include directory flags to make this happen). Boards can also + * use this file to use any of libmaple's memory-related hooks (like + * where the heap should live). + */ +INCLUDE mem-ram.inc + +/* Provide memory region aliases for common.inc */ +REGION_ALIAS("REGION_TEXT", ram); +REGION_ALIAS("REGION_DATA", ram); +REGION_ALIAS("REGION_BSS", ram); +REGION_ALIAS("REGION_RODATA", ram); + +/* Let common.inc handle the real work. */ +INCLUDE common.inc diff --git a/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/maple_native/maple_native_heap.inc b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/maple_native/maple_native_heap.inc new file mode 100644 index 0000000..34b5a2d --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/maple_native/maple_native_heap.inc @@ -0,0 +1,3 @@ +/* Specify heap boundary addresses on the external SRAM chip */ +_lm_heap_start = 0x60000000; +_lm_heap_end = 0x60100000; diff --git a/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/maple_native/mem-flash.inc b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/maple_native/mem-flash.inc new file mode 100644 index 0000000..bae4f39 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/maple_native/mem-flash.inc @@ -0,0 +1,7 @@ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 61K + rom (rx) : ORIGIN = 0x08005000, LENGTH = 492K +} + +INCLUDE maple_native_heap.inc diff --git a/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/maple_native/mem-jtag.inc b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/maple_native/mem-jtag.inc new file mode 100644 index 0000000..508ed44 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/maple_native/mem-jtag.inc @@ -0,0 +1,7 @@ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 64K + rom (rx) : ORIGIN = 0x08000000, LENGTH = 512K +} + +INCLUDE maple_native_heap.inc diff --git a/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/maple_native/mem-ram.inc b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/maple_native/mem-ram.inc new file mode 100644 index 0000000..6ae11ef --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/maple_native/mem-ram.inc @@ -0,0 +1,7 @@ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 61K + rom (rx) : ORIGIN = 0x08005000, LENGTH = 0K +} + +INCLUDE maple_native_heap.inc diff --git a/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_112k_flash_1024k/mem-jtag.inc b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_112k_flash_1024k/mem-jtag.inc new file mode 100644 index 0000000..e0d2da1 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_112k_flash_1024k/mem-jtag.inc @@ -0,0 +1,5 @@ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 112K + rom (rx) : ORIGIN = 0x08000000, LENGTH = 1024K +} diff --git a/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_112k_flash_1024k/mem-ram.inc b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_112k_flash_1024k/mem-ram.inc new file mode 100644 index 0000000..d21f17c --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_112k_flash_1024k/mem-ram.inc @@ -0,0 +1,5 @@ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 112K + rom (rx) : ORIGIN = 0x08000000, LENGTH = 0K +} diff --git a/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_20k_flash_128k/mem-flash.inc b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_20k_flash_128k/mem-flash.inc new file mode 100644 index 0000000..a9091ca --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_20k_flash_128k/mem-flash.inc @@ -0,0 +1,5 @@ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 17K + rom (rx) : ORIGIN = 0x08005000, LENGTH = 108K +} diff --git a/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_20k_flash_128k/mem-jtag.inc b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_20k_flash_128k/mem-jtag.inc new file mode 100644 index 0000000..20fbec0 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_20k_flash_128k/mem-jtag.inc @@ -0,0 +1,5 @@ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K +} diff --git a/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_20k_flash_128k/mem-ram.inc b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_20k_flash_128k/mem-ram.inc new file mode 100644 index 0000000..f02453b --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_20k_flash_128k/mem-ram.inc @@ -0,0 +1,5 @@ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 17K + rom (rx) : ORIGIN = 0x08005000, LENGTH = 0K +} diff --git a/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_20k_flash_128k_robotis/mem-flash.inc b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_20k_flash_128k_robotis/mem-flash.inc new file mode 100644 index 0000000..2c03ea9 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_20k_flash_128k_robotis/mem-flash.inc @@ -0,0 +1,5 @@ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 17K + rom (rx) : ORIGIN = 0x08003000, LENGTH = 108K +} diff --git a/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_20k_flash_128k_robotis/mem-jtag.inc b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_20k_flash_128k_robotis/mem-jtag.inc new file mode 100644 index 0000000..20fbec0 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_20k_flash_128k_robotis/mem-jtag.inc @@ -0,0 +1,5 @@ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K +} diff --git a/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_20k_flash_128k_robotis/mem-ram.inc b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_20k_flash_128k_robotis/mem-ram.inc new file mode 100644 index 0000000..f02453b --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_20k_flash_128k_robotis/mem-ram.inc @@ -0,0 +1,5 @@ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 17K + rom (rx) : ORIGIN = 0x08005000, LENGTH = 0K +} diff --git a/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_64k_flash_512k/mem-flash.inc b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_64k_flash_512k/mem-flash.inc new file mode 100644 index 0000000..ddb8876 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_64k_flash_512k/mem-flash.inc @@ -0,0 +1,5 @@ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 61K + rom (rx) : ORIGIN = 0x08005000, LENGTH = 492K +} diff --git a/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_64k_flash_512k/mem-jtag.inc b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_64k_flash_512k/mem-jtag.inc new file mode 100644 index 0000000..d3ed992 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_64k_flash_512k/mem-jtag.inc @@ -0,0 +1,5 @@ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 64K + rom (rx) : ORIGIN = 0x08000000, LENGTH = 512K +} diff --git a/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_64k_flash_512k/mem-ram.inc b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_64k_flash_512k/mem-ram.inc new file mode 100644 index 0000000..360beaf --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_64k_flash_512k/mem-ram.inc @@ -0,0 +1,5 @@ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 61K + rom (rx) : ORIGIN = 0x08005000, LENGTH = 0K +} diff --git a/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_8k_flash_128k/mem-flash.inc b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_8k_flash_128k/mem-flash.inc new file mode 100644 index 0000000..19372b7 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_8k_flash_128k/mem-flash.inc @@ -0,0 +1,5 @@ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 8K + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K +} diff --git a/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_8k_flash_128k/mem-jtag.inc b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_8k_flash_128k/mem-jtag.inc new file mode 100644 index 0000000..19372b7 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_8k_flash_128k/mem-jtag.inc @@ -0,0 +1,5 @@ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 8K + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K +} diff --git a/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_8k_flash_128k/mem-ram.inc b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_8k_flash_128k/mem-ram.inc new file mode 100644 index 0000000..4063ab4 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/ld/stm32/mem/sram_8k_flash_128k/mem-ram.inc @@ -0,0 +1,5 @@ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 8K + rom (rx) : ORIGIN = 0x08000000, LENGTH = 0K +} diff --git a/BootLoaders/Boards/stm32/system/support/ld/stm32/series/stm32f1/performance/vector_symbols.inc b/BootLoaders/Boards/stm32/system/support/ld/stm32/series/stm32f1/performance/vector_symbols.inc new file mode 100644 index 0000000..f8519bb --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/ld/stm32/series/stm32f1/performance/vector_symbols.inc @@ -0,0 +1,78 @@ +EXTERN(__msp_init) +EXTERN(__exc_reset) +EXTERN(__exc_nmi) +EXTERN(__exc_hardfault) +EXTERN(__exc_memmanage) +EXTERN(__exc_busfault) +EXTERN(__exc_usagefault) +EXTERN(__stm32reservedexception7) +EXTERN(__stm32reservedexception8) +EXTERN(__stm32reservedexception9) +EXTERN(__stm32reservedexception10) +EXTERN(__exc_svc) +EXTERN(__exc_debug_monitor) +EXTERN(__stm32reservedexception13) +EXTERN(__exc_pendsv) +EXTERN(__exc_systick) + +EXTERN(__irq_wwdg) +EXTERN(__irq_pvd) +EXTERN(__irq_tamper) +EXTERN(__irq_rtc) +EXTERN(__irq_flash) +EXTERN(__irq_rcc) +EXTERN(__irq_exti0) +EXTERN(__irq_exti1) +EXTERN(__irq_exti2) +EXTERN(__irq_exti3) +EXTERN(__irq_exti4) +EXTERN(__irq_dma1_channel1) +EXTERN(__irq_dma1_channel2) +EXTERN(__irq_dma1_channel3) +EXTERN(__irq_dma1_channel4) +EXTERN(__irq_dma1_channel5) +EXTERN(__irq_dma1_channel6) +EXTERN(__irq_dma1_channel7) +EXTERN(__irq_adc) +EXTERN(__irq_usb_hp_can_tx) +EXTERN(__irq_usb_lp_can_rx0) +EXTERN(__irq_can_rx1) +EXTERN(__irq_can_sce) +EXTERN(__irq_exti9_5) +EXTERN(__irq_tim1_brk) +EXTERN(__irq_tim1_up) +EXTERN(__irq_tim1_trg_com) +EXTERN(__irq_tim1_cc) +EXTERN(__irq_tim2) +EXTERN(__irq_tim3) +EXTERN(__irq_tim4) +EXTERN(__irq_i2c1_ev) +EXTERN(__irq_i2c1_er) +EXTERN(__irq_i2c2_ev) +EXTERN(__irq_i2c2_er) +EXTERN(__irq_spi1) +EXTERN(__irq_spi2) +EXTERN(__irq_usart1) +EXTERN(__irq_usart2) +EXTERN(__irq_usart3) +EXTERN(__irq_exti15_10) +EXTERN(__irq_rtcalarm) +EXTERN(__irq_usbwakeup) + +EXTERN(__irq_tim8_brk) +EXTERN(__irq_tim8_up) +EXTERN(__irq_tim8_trg_com) +EXTERN(__irq_tim8_cc) +EXTERN(__irq_adc3) +EXTERN(__irq_fsmc) +EXTERN(__irq_sdio) +EXTERN(__irq_tim5) +EXTERN(__irq_spi3) +EXTERN(__irq_uart4) +EXTERN(__irq_uart5) +EXTERN(__irq_tim6) +EXTERN(__irq_tim7) +EXTERN(__irq_dma2_channel1) +EXTERN(__irq_dma2_channel2) +EXTERN(__irq_dma2_channel3) +EXTERN(__irq_dma2_channel4_5) diff --git a/BootLoaders/Boards/stm32/system/support/ld/stm32/series/stm32f1/value/vector_symbols.inc b/BootLoaders/Boards/stm32/system/support/ld/stm32/series/stm32f1/value/vector_symbols.inc new file mode 100644 index 0000000..f8726f9 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/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/BootLoaders/Boards/stm32/system/support/ld/stm32/series/stm32f2/vector_symbols.inc b/BootLoaders/Boards/stm32/system/support/ld/stm32/series/stm32f2/vector_symbols.inc new file mode 100644 index 0000000..d275ec3 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/ld/stm32/series/stm32f2/vector_symbols.inc @@ -0,0 +1,98 @@ +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_tamp_stamp) +EXTERN(__irq_rtc_wkup) +EXTERN(__irq_flash) +EXTERN(__irq_rcc) +EXTERN(__irq_exti0) +EXTERN(__irq_exti1) +EXTERN(__irq_exti2) +EXTERN(__irq_exti3) +EXTERN(__irq_exti4) +EXTERN(__irq_dma1_stream0) +EXTERN(__irq_dma1_stream1) +EXTERN(__irq_dma1_stream2) +EXTERN(__irq_dma1_stream3) +EXTERN(__irq_dma1_stream4) +EXTERN(__irq_dma1_stream5) +EXTERN(__irq_dma1_stream6) +EXTERN(__irq_adc) +EXTERN(__irq_can1_tx) +EXTERN(__irq_can1_rx0) +EXTERN(__irq_can1_rx1) +EXTERN(__irq_can1_sce) +EXTERN(__irq_exti9_5) +EXTERN(__irq_tim1_brk_tim9) +EXTERN(__irq_tim1_up_tim10) +EXTERN(__irq_tim1_trg_com_tim11) +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_rtc_alarm) +EXTERN(__irq_otg_fs_wkup) +EXTERN(__irq_tim8_brk_tim12) +EXTERN(__irq_tim8_up_tim13) +EXTERN(__irq_tim8_trg_com_tim14) +EXTERN(__irq_tim8_cc) +EXTERN(__irq_dma1_stream7) +EXTERN(__irq_fsmc) +EXTERN(__irq_sdio) +EXTERN(__irq_tim5) +EXTERN(__irq_spi3) +EXTERN(__irq_uart4) +EXTERN(__irq_uart5) +EXTERN(__irq_tim6_dac) +EXTERN(__irq_tim7) +EXTERN(__irq_dma2_stream0) +EXTERN(__irq_dma2_stream1) +EXTERN(__irq_dma2_stream2) +EXTERN(__irq_dma2_stream3) +EXTERN(__irq_dma2_stream4) +EXTERN(__irq_eth) +EXTERN(__irq_eth_wkup) +EXTERN(__irq_can2_tx) +EXTERN(__irq_can2_rx0) +EXTERN(__irq_can2_rx1) +EXTERN(__irq_can2_sce) +EXTERN(__irq_otg_fs) +EXTERN(__irq_dma2_stream5) +EXTERN(__irq_dma2_stream6) +EXTERN(__irq_dma2_stream7) +EXTERN(__irq_usart6) +EXTERN(__irq_i2c3_ev) +EXTERN(__irq_i2c3_er) +EXTERN(__irq_otg_hs_ep1_out) +EXTERN(__irq_otg_hs_ep1_in) +EXTERN(__irq_otg_hs_wkup) +EXTERN(__irq_otg_hs) +EXTERN(__irq_dcmi) +EXTERN(__irq_cryp) +EXTERN(__irq_hash_rng) diff --git a/BootLoaders/Boards/stm32/system/support/ld/toolchains/gcc-arm-embedded/extra_libs.inc b/BootLoaders/Boards/stm32/system/support/ld/toolchains/gcc-arm-embedded/extra_libs.inc new file mode 100644 index 0000000..dd2c84f --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/ld/toolchains/gcc-arm-embedded/extra_libs.inc @@ -0,0 +1,7 @@ +/* + * Extra archives needed by ARM's GCC ARM Embedded arm-none-eabi- + * releases (https://launchpad.net/gcc-arm-embedded/). + */ + +/* This is for the provided newlib. */ +GROUP(libnosys.a) diff --git a/BootLoaders/Boards/stm32/system/support/ld/toolchains/generic/extra_libs.inc b/BootLoaders/Boards/stm32/system/support/ld/toolchains/generic/extra_libs.inc new file mode 100644 index 0000000..e69de29 diff --git a/BootLoaders/Boards/stm32/system/support/make/board-includes/VLDiscovery.mk b/BootLoaders/Boards/stm32/system/support/make/board-includes/VLDiscovery.mk new file mode 100644 index 0000000..76cd85a --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/make/board-includes/VLDiscovery.mk @@ -0,0 +1,7 @@ +MCU := STM32F100RB +PRODUCT_ID := 0003 +ERROR_LED_PORT := GPIOC +ERROR_LED_PIN := 9 +MCU_SERIES := stm32f1 +MCU_F1_LINE := value +LD_MEM_DIR := sram_8k_flash_128k diff --git a/BootLoaders/Boards/stm32/system/support/make/board-includes/cm900.mk b/BootLoaders/Boards/stm32/system/support/make/board-includes/cm900.mk new file mode 100644 index 0000000..9f70a1b --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/make/board-includes/cm900.mk @@ -0,0 +1,15 @@ +MCU := STM32F103C8 +PRODUCT_ID := 0003 +ERROR_LED_PORT := GPIOB +ERROR_LED_PIN := 2 +MCU_SERIES := stm32f1 +MCU_F1_LINE := performance +# This crap is due to ld-script limitations. If you know of a better +# way to go about this (like some magic ld switches to specify MEMORY +# at the command line), please tell us! +ifeq ($(BOOTLOADER),maple) +LD_MEM_DIR := sram_20k_flash_128k +endif +ifeq ($(BOOTLOADER),robotis) +LD_MEM_DIR := sram_20k_flash_128k_robotis +endif diff --git a/BootLoaders/Boards/stm32/system/support/make/board-includes/maple.mk b/BootLoaders/Boards/stm32/system/support/make/board-includes/maple.mk new file mode 100644 index 0000000..a2943ce --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/make/board-includes/maple.mk @@ -0,0 +1,10 @@ +MCU := STM32F103RB +PRODUCT_ID := 0003 +ERROR_LED_PORT := GPIOA +ERROR_LED_PIN := 5 +MCU_SERIES := stm32f1 +MCU_F1_LINE := performance +# This crap is due to ld-script limitations. If you know of a better +# way to go about this (like some magic ld switches to specify MEMORY +# at the command line), please tell us! +LD_MEM_DIR := sram_20k_flash_128k diff --git a/BootLoaders/Boards/stm32/system/support/make/board-includes/maple_RET6.mk b/BootLoaders/Boards/stm32/system/support/make/board-includes/maple_RET6.mk new file mode 100644 index 0000000..138722f --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/make/board-includes/maple_RET6.mk @@ -0,0 +1,7 @@ +MCU := STM32F103RE +PRODUCT_ID := 0003 +ERROR_LED_PORT := GPIOA +ERROR_LED_PIN := 5 +MCU_SERIES := stm32f1 +MCU_F1_LINE := performance +LD_MEM_DIR := sram_64k_flash_512k diff --git a/BootLoaders/Boards/stm32/system/support/make/board-includes/maple_mini.mk b/BootLoaders/Boards/stm32/system/support/make/board-includes/maple_mini.mk new file mode 100644 index 0000000..b022537 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/make/board-includes/maple_mini.mk @@ -0,0 +1,7 @@ +MCU := STM32F103CB +PRODUCT_ID := 0003 +ERROR_LED_PORT := GPIOB +ERROR_LED_PIN := 1 +MCU_SERIES := stm32f1 +MCU_F1_LINE := performance +LD_MEM_DIR := sram_20k_flash_128k diff --git a/BootLoaders/Boards/stm32/system/support/make/board-includes/maple_native.mk b/BootLoaders/Boards/stm32/system/support/make/board-includes/maple_native.mk new file mode 100644 index 0000000..87e58e3 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/make/board-includes/maple_native.mk @@ -0,0 +1,7 @@ +MCU := STM32F103ZE +PRODUCT_ID := 0003 +ERROR_LED_PORT := GPIOC +ERROR_LED_PIN := 15 +MCU_SERIES := stm32f1 +MCU_F1_LINE := performance +LD_MEM_DIR := maple_native # The SRAM chip makes this board special diff --git a/BootLoaders/Boards/stm32/system/support/make/board-includes/olimex_stm32_h103.mk b/BootLoaders/Boards/stm32/system/support/make/board-includes/olimex_stm32_h103.mk new file mode 100644 index 0000000..a3304a1 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/make/board-includes/olimex_stm32_h103.mk @@ -0,0 +1,7 @@ +MCU := STM32F103RB +PRODUCT_ID := 0003 +ERROR_LED_PORT := GPIOC +ERROR_LED_PIN := 12 +MCU_SERIES := stm32f1 +MCU_F1_LINE := performance +LD_MEM_DIR := sram_20k_flash_128k diff --git a/BootLoaders/Boards/stm32/system/support/make/board-includes/opencm904.mk b/BootLoaders/Boards/stm32/system/support/make/board-includes/opencm904.mk new file mode 100644 index 0000000..64d3351 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/make/board-includes/opencm904.mk @@ -0,0 +1,15 @@ +MCU := STM32F103CB +PRODUCT_ID := 0003 +ERROR_LED_PORT := GPIOB +ERROR_LED_PIN := 9 +MCU_SERIES := stm32f1 +MCU_F1_LINE := performance +# This crap is due to ld-script limitations. If you know of a better +# way to go about this (like some magic ld switches to specify MEMORY +# at the command line), please tell us! +ifeq ($(BOOTLOADER),maple) +LD_MEM_DIR := sram_20k_flash_128k +endif +ifeq ($(BOOTLOADER),robotis) +LD_MEM_DIR := sram_20k_flash_128k_robotis +endif diff --git a/BootLoaders/Boards/stm32/system/support/make/board-includes/st_stm3220g_eval.mk b/BootLoaders/Boards/stm32/system/support/make/board-includes/st_stm3220g_eval.mk new file mode 100644 index 0000000..8aaefc9 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/make/board-includes/st_stm3220g_eval.mk @@ -0,0 +1,5 @@ +MCU := STM32F207IG +ERROR_LED_PORT := GPIOG +ERROR_LED_PIN := 6 +MCU_SERIES := stm32f2 +LD_MEM_DIR := sram_112k_flash_1024k diff --git a/BootLoaders/Boards/stm32/system/support/make/build-rules.mk b/BootLoaders/Boards/stm32/system/support/make/build-rules.mk new file mode 100644 index 0000000..7c918d8 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/make/build-rules.mk @@ -0,0 +1,59 @@ +# Useful tools +CROSS_COMPILE ?= arm-none-eabi- + +CC := $(CROSS_COMPILE)gcc +CXX := $(CROSS_COMPILE)g++ +LD := $(CROSS_COMPILE)ld -v +AR := $(CROSS_COMPILE)ar +AS := $(CROSS_COMPILE)gcc +OBJCOPY := $(CROSS_COMPILE)objcopy +DISAS := $(CROSS_COMPILE)objdump +OBJDUMP := $(CROSS_COMPILE)objdump +SIZE := $(CROSS_COMPILE)size +DFU ?= dfu-util + +# Suppress annoying output unless V is set +ifndef V + SILENT_CC = @echo ' [CC] ' $(@:$(BUILD_PATH)/%.o=%.c); + SILENT_AS = @echo ' [AS] ' $(@:$(BUILD_PATH)/%.o=%.S); + SILENT_CXX = @echo ' [CXX] ' $(@:$(BUILD_PATH)/%.o=%.cpp); + SILENT_LD = @echo ' [LD] ' $(@F); + SILENT_AR = @echo ' [AR] ' + SILENT_OBJCOPY = @echo ' [OBJCOPY] ' $(@F); + SILENT_DISAS = @echo ' [DISAS] ' $(@:$(BUILD_PATH)/%.bin=%).disas; + SILENT_OBJDUMP = @echo ' [OBJDUMP] ' $(OBJDUMP); +endif + +# Extra build configuration + +BUILDDIRS := +TGT_BIN := + +CFLAGS = $(GLOBAL_CFLAGS) $(TGT_CFLAGS) +CXXFLAGS = $(GLOBAL_CXXFLAGS) $(TGT_CXXFLAGS) +ASFLAGS = $(GLOBAL_ASFLAGS) $(TGT_ASFLAGS) + +# Hacks to determine extra libraries we need to link against based on +# the toolchain. The default specifies no extra libraries, but it can +# be overridden. +LD_TOOLCHAIN_PATH := $(LDDIR)/toolchains/generic +ifneq ($(findstring ARM/embedded,$(shell $(CC) --version)),) +# GCC ARM Embedded, https://launchpad.net/gcc-arm-embedded/ +LD_TOOLCHAIN_PATH := $(LDDIR)/toolchains/gcc-arm-embedded +endif +ifneq ($(findstring Linaro GCC,$(shell $(CC) --version)),) +# Summon/Linaro GCC ARM Embedded, https://github.com/esden/summon-arm-toolchain +LD_TOOLCHAIN_PATH := $(LDDIR)/toolchains/gcc-arm-embedded +endif +# Add toolchain directory to LD search path +TOOLCHAIN_LDFLAGS := -L $(LD_TOOLCHAIN_PATH) + +# General directory independent build rules, generate dependency information +$(BUILD_PATH)/%.o: %.c + $(SILENT_CC) $(CC) $(CFLAGS) -MMD -MP -MF $(@:%.o=%.d) -MT $@ -o $@ -c $< + +$(BUILD_PATH)/%.o: %.cpp + $(SILENT_CXX) $(CXX) $(CFLAGS) $(CXXFLAGS) -MMD -MP -MF $(@:%.o=%.d) -MT $@ -o $@ -c $< + +$(BUILD_PATH)/%.o: %.S + $(SILENT_AS) $(AS) $(ASFLAGS) -MMD -MP -MF $(@:%.o=%.d) -MT $@ -o $@ -c $< diff --git a/BootLoaders/Boards/stm32/system/support/make/build-templates.mk b/BootLoaders/Boards/stm32/system/support/make/build-templates.mk new file mode 100644 index 0000000..4371f13 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/make/build-templates.mk @@ -0,0 +1,5 @@ +define LIBMAPLE_MODULE_template +dir := $(1) +include $$(dir)/rules.mk +endef + diff --git a/BootLoaders/Boards/stm32/system/support/make/footer.mk b/BootLoaders/Boards/stm32/system/support/make/footer.mk new file mode 100644 index 0000000..2242416 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/make/footer.mk @@ -0,0 +1,18 @@ +sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%) +cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%) +cppFILES_$(d) := $(cppSRCS_$(d):%=$(d)/%) + +OBJS_$(d) := $(sFILES_$(d):%.S=$(BUILD_PATH)/%.o) \ + $(cFILES_$(d):%.c=$(BUILD_PATH)/%.o) \ + $(cppFILES_$(d):%.cpp=$(BUILD_PATH)/%.o) +DEPS_$(d) := $(OBJS_$(d):%.o=%.d) + +$(OBJS_$(d)): TGT_CFLAGS := $(CFLAGS_$(d)) +$(OBJS_$(d)): TGT_CXXFLAGS := $(CXXFLAGS_$(d)) +$(OBJS_$(d)): TGT_ASFLAGS := $(ASFLAGS_$(d)) + +TGT_BIN += $(OBJS_$(d)) + +-include $(DEPS_$(d)) +d := $(dirstack_$(sp)) +sp := $(basename $(sp)) diff --git a/BootLoaders/Boards/stm32/system/support/make/header.mk b/BootLoaders/Boards/stm32/system/support/make/header.mk new file mode 100644 index 0000000..c85594a --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/make/header.mk @@ -0,0 +1,4 @@ +sp := $(sp).x +dirstack_$(sp) := $(d) +d := $(dir) +BUILDDIRS += $(BUILD_PATH)/$(d) diff --git a/BootLoaders/Boards/stm32/system/support/make/target-config.mk b/BootLoaders/Boards/stm32/system/support/make/target-config.mk new file mode 100644 index 0000000..0e3a2c2 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/make/target-config.mk @@ -0,0 +1,54 @@ +# TARGET_FLAGS are to be passed while compiling, assembling, linking. +TARGET_FLAGS := +# TARGET_LDFLAGS go to the linker +TARGET_LDFLAGS := + +# Configuration derived from $(MEMORY_TARGET) + +LD_SCRIPT_PATH := $(LDDIR)/$(MEMORY_TARGET).ld + +ifeq ($(MEMORY_TARGET), ram) +VECT_BASE_ADDR := VECT_TAB_RAM +endif +ifeq ($(MEMORY_TARGET), flash) +VECT_BASE_ADDR := VECT_TAB_FLASH +endif +ifeq ($(MEMORY_TARGET), jtag) +VECT_BASE_ADDR := VECT_TAB_BASE +endif + +# Pull in the board configuration file here, so it can override the +# above. + +include $(BOARD_INCLUDE_DIR)/$(BOARD).mk + +# Configuration derived from $(BOARD).mk + +LD_SERIES_PATH := $(LDDIR)/stm32/series/$(MCU_SERIES) +LD_MEM_PATH := $(LDDIR)/stm32/mem/$(LD_MEM_DIR) +ifeq ($(MCU_SERIES), stm32f1) +# 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 + +ifeq ($(MCU_SERIES), stm32f1) +TARGET_FLAGS += -mcpu=cortex-m3 -march=armv7-m +endif +ifeq ($(MCU_SERIES), stm32f2) +TARGET_FLAGS += -mcpu=cortex-m3 -march=armv7-m +endif +ifeq ($(MCU_SERIES), stm32f4) +TARGET_FLAGS += -mcpu=cortex-m4 -march=armv7e-m -mfloat-abi=hard -mfpu=fpv4-sp-d16 +endif + +TARGET_LDFLAGS += -Xlinker -T$(LD_SCRIPT_PATH) \ + -L $(LD_SERIES_PATH) \ + -L $(LD_MEM_PATH) \ + -L $(LDDIR) +TARGET_FLAGS += -mthumb -DBOARD_$(BOARD) -DMCU_$(MCU) \ + -DERROR_LED_PORT=$(ERROR_LED_PORT) \ + -DERROR_LED_PIN=$(ERROR_LED_PIN) \ + -D$(VECT_BASE_ADDR) + +LIBMAPLE_MODULE_SERIES := $(LIBMAPLE_PATH)/$(MCU_SERIES) diff --git a/BootLoaders/Boards/stm32/system/support/scripts/45-maple.rules b/BootLoaders/Boards/stm32/system/support/scripts/45-maple.rules new file mode 100644 index 0000000..d1bda5f --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/scripts/45-maple.rules @@ -0,0 +1,5 @@ +ATTRS{idProduct}=="1001", ATTRS{idVendor}=="0110", MODE="664", GROUP="plugdev" +ATTRS{idProduct}=="1002", ATTRS{idVendor}=="0110", MODE="664", GROUP="plugdev" +ATTRS{idProduct}=="0003", ATTRS{idVendor}=="1eaf", MODE="664", GROUP="plugdev" SYMLINK+="maple" +ATTRS{idProduct}=="0004", ATTRS{idVendor}=="1eaf", MODE="664", GROUP="plugdev" SYMLINK+="maple" + diff --git a/BootLoaders/Boards/stm32/system/support/scripts/copy-to-ide b/BootLoaders/Boards/stm32/system/support/scripts/copy-to-ide new file mode 100644 index 0000000..e68abca --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/scripts/copy-to-ide @@ -0,0 +1,54 @@ +#!/bin/sh + +# This hack copies libmaple's source, linker scripts, and support +# libraries into the Maple IDE repository (which is expected as its +# first argument). + +DEST=$1 + +DEST_CORES=$DEST/hardware/leaflabs/cores/maple +DEST_LIBS=$DEST/libraries + +LMAPLE_SRC="LICENSE + ./libmaple/*.h + ./libmaple/*.c + ./libmaple/*.S + ./libmaple/usb/*.h + ./libmaple/usb/*.c + ./libmaple/usb/usb_lib/*.h + ./libmaple/usb/usb_lib/*.c + ./wirish/*.h + ./wirish/main.cxx + ./wirish/*.cpp + ./wirish/comm/*.cpp + ./wirish/comm/*.h + ./wirish/boards/*.h + ./wirish/boards/*.cpp + ./support/ld/common.inc + ./support/ld/maple + ./support/ld/maple_mini + ./support/ld/maple_native + ./support/ld/maple_RET6 + ./support/ld/names.inc" + +echo "First make sure DEST exists: $DEST" +if !(test -d $DEST) +then + echo "Nope! Make sure you're doing this right?" + exit -1 +fi + +# source +echo Copying libmaple source +rm -rf $DEST_CORES/*.c $DEST_CORES/*.cpp $DEST_CORES/*.h $DEST_CORES/*.cxx $DEST_CORES/*.S +rm -rf $DEST_CORES/*.inc $DEST_CORES/*.a $DEST_CORES/maple $DEST_CORES/maple_* +cp -R $LMAPLE_SRC $DEST_CORES + +echo Copying over libraries +cp -R libraries/* $DEST_LIBS + +# libmaple version +echo Creating libmaple-version.txt +git show-ref HEAD | cut -c 1-10 > $DEST/libmaple-version.txt + +echo Done. diff --git a/BootLoaders/Boards/stm32/system/support/scripts/reset.py b/BootLoaders/Boards/stm32/system/support/scripts/reset.py new file mode 100644 index 0000000..67a72c1 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/scripts/reset.py @@ -0,0 +1,145 @@ +#!/usr/bin/env python + +from __future__ import print_function + +import serial +import os +import platform +import sys +import time +from struct import pack + +def unix_get_maple_path(file_prefix, dev_is_maple=lambda dev: True): + """Try to find the device file for the Maple on *nix. + + This function works assuming that the device file globs like + '/dev/*'. The caller may pass an additional + dev_is_maple predicate if the platform supports additional tests + to determine if a device is a Maple. + + If there are multiple possibilities, ask the user what to do. If + the user chooses not to say, returns None.""" + possible_paths = [os.path.join('/dev', x) for x in os.listdir('/dev') \ + if x.startswith(file_prefix) and dev_is_maple(x)] + return choose_path(possible_paths) + +def linux_get_maple_path(file_prefix='ttyACM'): + """Specialized unix_get_maple_path() for Linux. + + Attempts to check that a candidate device has the correct ID in + the /sys tree when deciding if it's a Maple.""" + return unix_get_maple_path(file_prefix, linux_tty_is_maple) + +def linux_tty_is_maple(device): + try: + sysfile = open("/sys/class/tty/%s/device/uevent" % device, "r") + text = "".join(sysfile.readlines()) + return "PRODUCT=1eaf/4" in text + except IOError: # no udev info available + return True + +def windows_get_maple_path(): + """Similar to unix_get_maple_path(), but on Windows.""" + import _winreg as reg + p = 'HARDWARE\\DEVICEMAP\\SERIALCOMM' + k = reg.OpenKey(reg.HKEY_LOCAL_MACHINE, p) + possible_paths = [] + i = 0 + while True: + try: + possible_paths.append(reg.EnumValue(k, i)[1]) + i += 1 + except WindowsError: + break + return choose_path(possible_paths) + +def choose_path(possible_paths): + if len(possible_paths) == 0: + return None + elif len(possible_paths) == 1: + return possible_paths[0] + else: + print('Found multiple candidates for the Maple device:') + return choose_among_options(possible_paths) + +def choose_among_options(options): + for (i,p) in enumerate(options): + print('\t%d. %s' % (i+1, p)) + + prompt = 'Enter a number to select one, or q to quit: ' + while True: + resp = raw_input(prompt).strip().lower() + if resp == 'q': sys.exit() + + try: + i = int(resp, 10) + except ValueError: + pass + else: + if 0 <= i-1 < len(options): + return options[i-1] + + prompt = 'Please enter a number from the list, or q to quit: ' + +plat_sys = platform.system() +plat_bits = platform.architecture()[0] +if plat_sys == 'Linux': + maple_path = linux_get_maple_path() + # fall back on /dev/maple if that doesn't work + if maple_path is None: + maple_path = '/dev/maple' + print('Could not find Maple serial port; defaulting to /dev/maple.') +elif plat_sys == 'Darwin': + maple_path = unix_get_maple_path('tty.usbmodem') +elif plat_sys == 'Windows': + maple_path = windows_get_maple_path() +else: + maple_path = raw_input('Unrecognized platform. Please enter ' + "the path to the Maple's serial port device file:") + +if maple_path is None: + print('Could not find the Maple serial port for reset.', + 'Perhaps this is your first upload, or the board is already', + 'in bootloader mode.') + print() + print("If your sketch doesn't upload, try putting your Maple", + 'into bootloader mode manually by pressing the RESET button', + 'then letting it go and quickly pressing button BUT', + '(hold for several seconds).') + sys.exit() + +print('Using %s as Maple serial port' % maple_path) + +try: + ser = serial.Serial(maple_path, baudrate=115200, xonxoff=1) + + try: + # try to toggle DTR/RTS (old scheme) + ser.setRTS(0) + time.sleep(0.01) + ser.setDTR(0) + time.sleep(0.01) + ser.setDTR(1) + time.sleep(0.01) + ser.setDTR(0) + + # try magic number + ser.setRTS(1) + time.sleep(0.01) + ser.setDTR(1) + time.sleep(0.01) + ser.setDTR(0) + time.sleep(0.01) + ser.write("1EAF".encode("ascii")) + ser.flush() + + # Delay a bit before proceeding + time.sleep(0.1) + finally: + # ok we're done here + ser.close() + +except Exception as e: + print('Failed to open serial port %s for reset' % maple_path) + sys.exit() + diff --git a/BootLoaders/Boards/stm32/system/support/scripts/robotis-loader.py b/BootLoaders/Boards/stm32/system/support/scripts/robotis-loader.py new file mode 100644 index 0000000..95d4e71 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/scripts/robotis-loader.py @@ -0,0 +1,94 @@ +#!/usr/bin/python + +# This script sends a program on a robotis board (OpenCM9.04 or CM900) +# using the robotis bootloader (used in OpenCM IDE) +# +# Usage: +# python robotis-loader.py +# +# Example: +# python robotis-loader.py /dev/ttyACM0 firmware.bin +# +# https://github.com/Gregwar/robotis-loader + +import serial, sys, os, time + +print('~~ Robotis loader ~~') +print('') + +# Reading command line +if len(sys.argv) != 3: + exit('! Usage: robotis-loader.py ') +pgm, port, binary = sys.argv + +# Helper to prints a progress bar +def progressBar(percent, precision=65): + threshold=precision*percent/100.0 + sys.stdout.write('[ ') + for x in xrange(0, precision): + if x < threshold: sys.stdout.write('#') + else: sys.stdout.write(' ') + sys.stdout.write(' ] ') + sys.stdout.flush() + +# Opening the firmware file +try: + stat = os.stat(binary) + size = stat.st_size + firmware = file(binary, 'rb') + print('* Opening %s, size=%d' % (binary, size)) +except: + exit('! Unable to open file %s' % binary) + +# Opening serial port +try: + s = serial.Serial(port, baudrate=115200) +except: + exit('! Unable to open serial port %s' % port) + +print('* Resetting the board') +s.setRTS(True) +s.setDTR(False) +time.sleep(0.1) +s.setRTS(False) +s.write('CM9X') +s.close() +time.sleep(1.0); + +print('* Connecting...') +s = serial.Serial(port, baudrate=115200) +s.write('AT&LD') +print('* Download signal transmitted, waiting...') + +# Entering bootloader sequence +while True: + line = s.readline().strip() + if line.endswith('Ready..'): + print('* Board ready, sending data') + cs = 0 + pos = 0 + while True: + c = firmware.read(2048) + if len(c): + pos += len(c) + sys.stdout.write("\r") + progressBar(100*float(pos)/float(size)) + s.write(c) + for k in range(0,len(c)): + cs = (cs+ord(c[k]))%256 + else: + break + print('') + s.setDTR(True) + print('* Checksum: %d' % (cs)) + s.write(chr(cs)) + print('* Firmware was sent') + else: + if line == 'Success..': + print('* Success, running the code') + print('') + s.write('AT&RST') + s.close() + exit() + else: + print('Board -> '+line) diff --git a/BootLoaders/Boards/stm32/system/support/scripts/win-list-com-ports.py b/BootLoaders/Boards/stm32/system/support/scripts/win-list-com-ports.py new file mode 100644 index 0000000..3e6ecb8 --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/scripts/win-list-com-ports.py @@ -0,0 +1,29 @@ +# Windows program for listing COM (serial) ports. +# +# enumerate_serial_ports() is by Eli Bendersky: +# +# http://eli.thegreenplace.net/2009/07/31/listing-all-serial-ports-on-windows-with-python/ + +import _winreg as winreg +import itertools + +def enumerate_serial_ports(): + """ Uses the Win32 registry to return an + iterator of serial (COM) ports + existing on this computer. + """ + path = 'HARDWARE\\DEVICEMAP\\SERIALCOMM' + try: + key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, path) + except WindowsError: + raise IterationError + + for i in itertools.count(): + try: + val = winreg.EnumValue(key, i) + yield str(val[1]) + except EnvironmentError: + break + +for com in enumerate_serial_ports(): + print com diff --git a/BootLoaders/Boards/stm32/system/support/stm32loader.py b/BootLoaders/Boards/stm32/system/support/stm32loader.py new file mode 100644 index 0000000..50686bf --- /dev/null +++ b/BootLoaders/Boards/stm32/system/support/stm32loader.py @@ -0,0 +1,532 @@ +#!/usr/bin/env python + +# -*- coding: utf-8 -*- +# vim: sw=4:ts=4:si:et:enc=utf-8 + +# Author: Ivan A-R +# Project page: http://tuxotronic.org/wiki/projects/stm32loader +# +# This file is part of stm32loader. +# +# stm32loader is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 3, or (at your option) any later +# version. +# +# stm32loader is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License +# along with stm32loader; see the file COPYING3. If not see +# . + +from __future__ import print_function + +import sys, getopt +import serial +import time +import glob +import time +import tempfile +import os +import subprocess + +try: + from progressbar import * + usepbar = 1 +except: + usepbar = 0 + +# Verbose level +QUIET = 5 + +def mdebug(level, message): + if QUIET >= level: + print(message, file=sys.stderr) + +# Takes chip IDs (obtained via Get ID command) to human-readable names +CHIP_ID_STRS = {0x410: 'STM32F1, performance, medium-density', + 0x411: 'STM32F2', + 0x412: 'STM32F1, performance, low-density', + 0x413: 'STM32F4', + 0x414: 'STM32F1, performance, high-density', + 0x416: 'STM32L1, performance, medium-density', + 0x418: 'STM32F1, connectivity', + 0x420: 'STM32F1, value, medium-density', + 0x428: 'STM32F1, value, high-density', + 0x430: 'STM32F1, performance, XL-density'} + +class CmdException(Exception): + pass + +class CommandInterface(object): + def open(self, aport='/dev/tty.usbserial-FTD3TMCH', abaudrate=115200) : + self.sp = serial.Serial( + port=aport, + baudrate=abaudrate, # baudrate + bytesize=8, # number of databits + parity=serial.PARITY_EVEN, + stopbits=1, + xonxoff=0, # enable software flow control + rtscts=0, # disable RTS/CTS flow control + timeout=0.5 # set a timeout value, None for waiting forever + ) + + + def _wait_for_ack(self, info="", timeout=0): + stop = time.time() + timeout + got = None + while not got: + got = self.sp.read(1) + if time.time() > stop: + break + + if not got: + raise CmdException("No response to %s" % info) + + # wait for ask + ask = ord(got) + + if ask == 0x79: + # ACK + return 1 + elif ask == 0x1F: + # NACK + raise CmdException("Chip replied with a NACK during %s" % info) + + # Unknown response + raise CmdException("Unrecognised response 0x%x to %s" % (ask, info)) + + def reset(self): + self.sp.setDTR(0) + time.sleep(0.1) + self.sp.setDTR(1) + time.sleep(0.5) + + def initChip(self): + # Set boot + self.sp.setRTS(0) + self.reset() + + # Be a bit more persistent when trying to initialise the chip + stop = time.time() + 5.0 + + while time.time() <= stop: + self.sp.write('\x7f') + + got = self.sp.read() + + # The chip will ACK a sync the very first time and + # NACK it every time afterwards + if got and got in '\x79\x1f': + # Synced up + return + + raise CmdException('No response while trying to sync') + + def releaseChip(self): + self.sp.setRTS(1) + self.reset() + + def cmdGeneric(self, cmd): + self.sp.write(chr(cmd)) + self.sp.write(chr(cmd ^ 0xFF)) # Control byte + return self._wait_for_ack(hex(cmd)) + + def cmdGet(self): + if self.cmdGeneric(0x00): + mdebug(10, "*** Get command"); + len = ord(self.sp.read()) + version = ord(self.sp.read()) + mdebug(10, " Bootloader version: "+hex(version)) + dat = map(lambda c: hex(ord(c)), self.sp.read(len)) + mdebug(10, " Available commands: "+str(dat)) + self._wait_for_ack("0x00 end") + return version + else: + raise CmdException("Get (0x00) failed") + + def cmdGetVersion(self): + if self.cmdGeneric(0x01): + mdebug(10, "*** GetVersion command") + version = ord(self.sp.read()) + self.sp.read(2) + self._wait_for_ack("0x01 end") + mdebug(10, " Bootloader version: "+hex(version)) + return version + else: + raise CmdException("GetVersion (0x01) failed") + + def cmdGetID(self): + if self.cmdGeneric(0x02): + mdebug(10, "*** GetID command") + len = ord(self.sp.read()) + id = self.sp.read(len+1) + self._wait_for_ack("0x02 end") + return id + else: + raise CmdException("GetID (0x02) failed") + + + def _encode_addr(self, addr): + byte3 = (addr >> 0) & 0xFF + byte2 = (addr >> 8) & 0xFF + byte1 = (addr >> 16) & 0xFF + byte0 = (addr >> 24) & 0xFF + crc = byte0 ^ byte1 ^ byte2 ^ byte3 + return (chr(byte0) + chr(byte1) + chr(byte2) + chr(byte3) + chr(crc)) + + + def cmdReadMemory(self, addr, lng): + assert(lng <= 256) + if self.cmdGeneric(0x11): + mdebug(10, "*** ReadMemory command") + self.sp.write(self._encode_addr(addr)) + self._wait_for_ack("0x11 address failed") + N = (lng - 1) & 0xFF + crc = N ^ 0xFF + self.sp.write(chr(N) + chr(crc)) + self._wait_for_ack("0x11 length failed") + return map(lambda c: ord(c), self.sp.read(lng)) + else: + raise CmdException("ReadMemory (0x11) failed") + + + def cmdGo(self, addr): + if self.cmdGeneric(0x21): + mdebug(10, "*** Go command") + self.sp.write(self._encode_addr(addr)) + self._wait_for_ack("0x21 go failed") + else: + raise CmdException("Go (0x21) failed") + + + def cmdWriteMemory(self, addr, data): + assert(len(data) <= 256) + if self.cmdGeneric(0x31): + mdebug(10, "*** Write memory command") + self.sp.write(self._encode_addr(addr)) + self._wait_for_ack("0x31 address failed") + #map(lambda c: hex(ord(c)), data) + lng = (len(data)-1) & 0xFF + mdebug(10, " %s bytes to write" % [lng+1]); + self.sp.write(chr(lng)) # len really + crc = 0xFF + for c in data: + crc = crc ^ c + self.sp.write(chr(c)) + self.sp.write(chr(crc)) + self._wait_for_ack("0x31 programming failed") + mdebug(10, " Write memory done") + else: + raise CmdException("Write memory (0x31) failed") + + + def cmdEraseMemory(self, sectors = None): + if self.cmdGeneric(0x43): + mdebug(10, "*** Erase memory command") + if sectors is None: + # Global erase + self.sp.write(chr(0xFF)) + self.sp.write(chr(0x00)) + else: + # Sectors erase + self.sp.write(chr((len(sectors)-1) & 0xFF)) + crc = 0xFF + for c in sectors: + crc = crc ^ c + self.sp.write(chr(c)) + self.sp.write(chr(crc)) + self._wait_for_ack("0x43 erasing failed") + mdebug(10, " Erase memory done") + else: + raise CmdException("Erase memory (0x43) failed") + + + # TODO support for non-global mass erase + GLOBAL_ERASE_TIMEOUT_SECONDS = 20 # This takes a while + def cmdExtendedEraseMemory(self): + if self.cmdGeneric(0x44): + mdebug(10, "*** Extended erase memory command") + # Global mass erase + mdebug(5, "Global mass erase; this may take a while") + self.sp.write(chr(0xFF)) + self.sp.write(chr(0xFF)) + # Checksum + self.sp.write(chr(0x00)) + self._wait_for_ack("0x44 extended erase failed", + timeout=self.GLOBAL_ERASE_TIMEOUT_SECONDS) + mdebug(10, " Extended erase memory done") + else: + raise CmdException("Extended erase memory (0x44) failed") + + + def cmdWriteProtect(self, sectors): + if self.cmdGeneric(0x63): + mdebug(10, "*** Write protect command") + self.sp.write(chr((len(sectors)-1) & 0xFF)) + crc = 0xFF + for c in sectors: + crc = crc ^ c + self.sp.write(chr(c)) + self.sp.write(chr(crc)) + self._wait_for_ack("0x63 write protect failed") + mdebug(10, " Write protect done") + else: + raise CmdException("Write Protect memory (0x63) failed") + + def cmdWriteUnprotect(self): + if self.cmdGeneric(0x73): + mdebug(10, "*** Write Unprotect command") + self._wait_for_ack("0x73 write unprotect failed") + self._wait_for_ack("0x73 write unprotect 2 failed") + mdebug(10, " Write Unprotect done") + else: + raise CmdException("Write Unprotect (0x73) failed") + + def cmdReadoutProtect(self): + if self.cmdGeneric(0x82): + mdebug(10, "*** Readout protect command") + self._wait_for_ack("0x82 readout protect failed") + self._wait_for_ack("0x82 readout protect 2 failed") + mdebug(10, " Read protect done") + else: + raise CmdException("Readout protect (0x82) failed") + + def cmdReadoutUnprotect(self): + if self.cmdGeneric(0x92): + mdebug(10, "*** Readout Unprotect command") + self._wait_for_ack("0x92 readout unprotect failed") + self._wait_for_ack("0x92 readout unprotect 2 failed") + mdebug(10, " Read Unprotect done") + else: + raise CmdException("Readout unprotect (0x92) failed") + + +# Complex commands section + + def readMemory(self, addr, lng): + data = [] + if usepbar: + widgets = ['Reading: ', Percentage(),', ', ETA(), ' ', Bar()] + pbar = ProgressBar(widgets=widgets,maxval=lng, term_width=79).start() + + while lng > 256: + if usepbar: + pbar.update(pbar.maxval-lng) + else: + mdebug(5, "Read %(len)d bytes at 0x%(addr)X" % {'addr': addr, 'len': 256}) + data = data + self.cmdReadMemory(addr, 256) + addr = addr + 256 + lng = lng - 256 + if usepbar: + pbar.update(pbar.maxval-lng) + pbar.finish() + else: + mdebug(5, "Read %(len)d bytes at 0x%(addr)X" % {'addr': addr, 'len': 256}) + data = data + self.cmdReadMemory(addr, lng) + return data + + def writeMemory(self, addr, data): + lng = len(data) + + mdebug(5, "Writing %(lng)d bytes to start address 0x%(addr)X" % + { 'lng': lng, 'addr': addr}) + + if usepbar: + widgets = ['Writing: ', Percentage(),' ', ETA(), ' ', Bar()] + pbar = ProgressBar(widgets=widgets, maxval=lng, term_width=79).start() + + offs = 0 + while lng > 256: + if usepbar: + pbar.update(pbar.maxval-lng) + else: + mdebug(5, "Write %(len)d bytes at 0x%(addr)X" % {'addr': addr, 'len': 256}) + self.cmdWriteMemory(addr, data[offs:offs+256]) + offs = offs + 256 + addr = addr + 256 + lng = lng - 256 + if usepbar: + pbar.update(pbar.maxval-lng) + pbar.finish() + else: + mdebug(5, "Write %(len)d bytes at 0x%(addr)X" % {'addr': addr, 'len': 256}) + self.cmdWriteMemory(addr, data[offs:offs+lng] + ([0xFF] * (256-lng)) ) + + +def usage(): + print("""Usage: %s [-hqVewvr] [-l length] [-p port] [-b baud] [-a addr] [file.bin] + -h This help + -q Quiet + -V Verbose + -e Erase + -w Write + -v Verify + -r Read + -l length Length of read + -p port Serial port (default: first USB-like port in /dev) + -b baud Baud speed (default: 115200) + -a addr Target address + + ./stm32loader.py -e -w -v example/main.bin + + """ % sys.argv[0]) + +def read(filename): + """Read the file to be programmed and turn it into a binary""" + with open(filename, 'rb') as f: + bytes = f.read() + + if bytes.startswith('\x7FELF'): + # Actually an ELF file. Convert to binary + handle, path = tempfile.mkstemp(suffix='.bin', prefix='stm32loader') + + try: + os.close(handle) + + # Try a couple of options for objcopy + for name in ['arm-none-eabi-objcopy', 'arm-linux-gnueabi-objcopy']: + try: + code = subprocess.call([name, '-Obinary', filename, path]) + + if code == 0: + return read(path) + except OSError: + pass + else: + raise Exception('Error %d while converting to a binary file' % code) + finally: + # Remove the temporary file + os.unlink(path) + else: + return [ord(x) for x in bytes] + +if __name__ == "__main__": + + conf = { + 'port': 'auto', + 'baud': 115200, + 'address': 0x08000000, + 'erase': 0, + 'write': 0, + 'verify': 0, + 'read': 0, + 'len': 1000, + 'fname':'', + } + +# http://www.python.org/doc/2.5.2/lib/module-getopt.html + + try: + opts, args = getopt.getopt(sys.argv[1:], "hqVewvrp:b:a:l:") + except getopt.GetoptError as err: + # print help information and exit: + print(str(err)) # will print something like "option -a not recognized" + usage() + sys.exit(2) + + for o, a in opts: + if o == '-V': + QUIET = 10 + elif o == '-q': + QUIET = 0 + elif o == '-h': + usage() + sys.exit(0) + elif o == '-e': + conf['erase'] = 1 + elif o == '-w': + conf['write'] = 1 + elif o == '-v': + conf['verify'] = 1 + elif o == '-r': + conf['read'] = 1 + elif o == '-p': + conf['port'] = a + elif o == '-b': + conf['baud'] = eval(a) + elif o == '-a': + conf['address'] = eval(a) + elif o == '-l': + conf['len'] = eval(a) + else: + assert False, "unhandled option" + + # Try and find the port automatically + if conf['port'] == 'auto': + ports = [] + + # Get a list of all USB-like names in /dev + for name in ['tty.usbserial', 'ttyUSB']: + ports.extend(glob.glob('/dev/%s*' % name)) + + ports = sorted(ports) + + if ports: + # Found something - take it + conf['port'] = ports[0] + + cmd = CommandInterface() + cmd.open(conf['port'], conf['baud']) + mdebug(10, "Open port %(port)s, baud %(baud)d" % {'port':conf['port'], + 'baud':conf['baud']}) + try: + if (conf['write'] or conf['verify']): + mdebug(5, "Reading data from %s" % args[0]) + data = read(args[0]) + + try: + cmd.initChip() + except CmdException: + print("Can't init. Ensure BOOT0=1, BOOT1=0, and reset device") + + bootversion = cmd.cmdGet() + + mdebug(0, "Bootloader version 0x%X" % bootversion) + + if bootversion < 20 or bootversion >= 100: + raise Exception('Unreasonable bootloader version %d' % bootversion) + + chip_id = cmd.cmdGetID() + assert len(chip_id) == 2, "Unreasonable chip id: %s" % repr(chip_id) + chip_id_num = (ord(chip_id[0]) << 8) | ord(chip_id[1]) + chip_id_str = CHIP_ID_STRS.get(chip_id_num, None) + + if chip_id_str is None: + mdebug(0, 'Warning: unrecognised chip ID 0x%x' % chip_id_num) + else: + mdebug(0, "Chip id 0x%x, %s" % (chip_id_num, chip_id_str)) + + if conf['erase']: + # Pre-3.0 bootloaders use the erase memory + # command. Starting with 3.0, extended erase memory + # replaced this command. + if bootversion < 0x30: + cmd.cmdEraseMemory() + else: + cmd.cmdExtendedEraseMemory() + + if conf['write']: + cmd.writeMemory(conf['address'], data) + + if conf['verify']: + verify = cmd.readMemory(conf['address'], len(data)) + if(data == verify): + print("Verification OK") + else: + print("Verification FAILED") + print(str(len(data)) + ' vs ' + str(len(verify))) + for i in xrange(0, len(data)): + if data[i] != verify[i]: + print(hex(i) + ': ' + hex(data[i]) + ' vs ' + hex(verify[i])) + + if not conf['write'] and conf['read']: + rdata = cmd.readMemory(conf['address'], conf['len']) + file(args[0], 'wb').write(''.join(map(chr,rdata))) + + finally: + cmd.releaseChip() + diff --git a/BootLoaders/Boards/stm32/tools/boards.txt b/BootLoaders/Boards/stm32/tools/boards.txt new file mode 100644 index 0000000..e69de29 diff --git a/BootLoaders/Boards/stm32/tools/linux/45-maple.rules b/BootLoaders/Boards/stm32/tools/linux/45-maple.rules new file mode 100644 index 0000000..e53d969 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/45-maple.rules @@ -0,0 +1,5 @@ +ATTRS{idProduct}=="1001", ATTRS{idVendor}=="0110", MODE="664", GROUP="plugdev" +ATTRS{idProduct}=="1002", ATTRS{idVendor}=="0110", MODE="664", GROUP="plugdev" +ATTRS{idProduct}=="0003", ATTRS{idVendor}=="1eaf", MODE="664", GROUP="plugdev" SYMLINK+="maple", ENV{ID_MM_DEVICE_IGNORE}="1" +ATTRS{idProduct}=="0004", ATTRS{idVendor}=="1eaf", MODE="664", GROUP="plugdev" SYMLINK+="maple", ENV{ID_MM_DEVICE_IGNORE}="1" + diff --git a/BootLoaders/Boards/stm32/tools/linux/49-stlinkv1.rules b/BootLoaders/Boards/stm32/tools/linux/49-stlinkv1.rules new file mode 100644 index 0000000..d474d6a --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/49-stlinkv1.rules @@ -0,0 +1,11 @@ +# stm32 discovery boards, with onboard st/linkv1 +# ie, STM32VL + +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3744", \ + MODE:="0666", \ + SYMLINK+="stlinkv1_%n" + +# If you share your linux system with other users, or just don't like the +# idea of write permission for everybody, you can replace MODE:="0666" with +# OWNER:="yourusername" to create the device owned by you, or with +# GROUP:="somegroupname" and mange access using standard unix groups. diff --git a/BootLoaders/Boards/stm32/tools/linux/49-stlinkv2-1.rules b/BootLoaders/Boards/stm32/tools/linux/49-stlinkv2-1.rules new file mode 100644 index 0000000..a5a79b9 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/49-stlinkv2-1.rules @@ -0,0 +1,12 @@ +# stm32 nucleo boards, with onboard st/linkv2-1 +# ie, STM32F0, STM32F4. +# STM32VL has st/linkv1, which is quite different + +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374b", \ + MODE:="0666", \ + SYMLINK+="stlinkv2-1_%n" + +# If you share your linux system with other users, or just don't like the +# idea of write permission for everybody, you can replace MODE:="0666" with +# OWNER:="yourusername" to create the device owned by you, or with +# GROUP:="somegroupname" and mange access using standard unix groups. diff --git a/BootLoaders/Boards/stm32/tools/linux/49-stlinkv2.rules b/BootLoaders/Boards/stm32/tools/linux/49-stlinkv2.rules new file mode 100644 index 0000000..a11215c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/49-stlinkv2.rules @@ -0,0 +1,12 @@ +# stm32 discovery boards, with onboard st/linkv2 +# ie, STM32L, STM32F4. +# STM32VL has st/linkv1, which is quite different + +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3748", \ + MODE:="0666", \ + SYMLINK+="stlinkv2_%n" + +# If you share your linux system with other users, or just don't like the +# idea of write permission for everybody, you can replace MODE:="0666" with +# OWNER:="yourusername" to create the device owned by you, or with +# GROUP:="somegroupname" and mange access using standard unix groups. diff --git a/BootLoaders/Boards/stm32/tools/linux/dfu-util/dfu-prefix b/BootLoaders/Boards/stm32/tools/linux/dfu-util/dfu-prefix new file mode 100644 index 0000000..88e2d04 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux/dfu-util/dfu-prefix differ diff --git a/BootLoaders/Boards/stm32/tools/linux/dfu-util/dfu-suffix b/BootLoaders/Boards/stm32/tools/linux/dfu-util/dfu-suffix new file mode 100644 index 0000000..e96df29 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux/dfu-util/dfu-suffix differ diff --git a/BootLoaders/Boards/stm32/tools/linux/dfu-util/dfu-util b/BootLoaders/Boards/stm32/tools/linux/dfu-util/dfu-util new file mode 100644 index 0000000..e9a9599 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux/dfu-util/dfu-util differ diff --git a/BootLoaders/Boards/stm32/tools/linux/install.sh b/BootLoaders/Boards/stm32/tools/linux/install.sh new file mode 100644 index 0000000..29ddb2f --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/install.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +if sudo [ -w /etc/udev/rules.d ]; then + echo "Copying Maple-specific udev rules..." + sudo cp -v 45-maple.rules /etc/udev/rules.d/45-maple.rules + sudo chown root:root /etc/udev/rules.d/45-maple.rules + sudo chmod 644 /etc/udev/rules.d/45-maple.rules + sudo cp -v 49-stlinkv1.rules /etc/udev/rules.d/49-stlinkv1.rules + sudo chown root:root /etc/udev/rules.d/49-stlinkv1.rules + sudo chmod 644 /etc/udev/rules.d/49-stlinkv1.rules + sudo cp -v 49-stlinkv2.rules /etc/udev/rules.d/49-stlinkv2.rules + sudo chown root:root /etc/udev/rules.d/49-stlinkv2.rules + sudo chmod 644 /etc/udev/rules.d/49-stlinkv2.rules + sudo cp -v 49-stlinkv2-1.rules /etc/udev/rules.d/49-stlinkv2-1.rules + sudo chown root:root /etc/udev/rules.d/49-stlinkv2-1.rules + sudo chmod 644 /etc/udev/rules.d/49-stlinkv2-1.rules + echo "Reloading udev rules" + sudo udevadm control --reload-rules + echo "Adding current user to dialout group" + sudo adduser $USER dialout +else + echo "Couldn't copy to /etc/udev/rules.d/; you probably have to run this script as root? Or your distribution of Linux doesn't include udev; try running the IDE itself as root." +fi + diff --git a/BootLoaders/Boards/stm32/tools/linux/jlink_upload b/BootLoaders/Boards/stm32/tools/linux/jlink_upload new file mode 100644 index 0000000..ca45db1 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/jlink_upload @@ -0,0 +1,9 @@ +#!/bin/bash + +echo erase > "$1".jlink +echo loadbin "$1" , 0x8000000 >> "$1".jlink +echo r >> "$1".jlink +echo q >> "$1".jlink + +/opt/SEGGER/JLink/JLinkExe -device STM32F103C8 -if SWD -speed auto -CommanderScript "$1".jlink + diff --git a/BootLoaders/Boards/stm32/tools/linux/maple_upload b/BootLoaders/Boards/stm32/tools/linux/maple_upload new file mode 100644 index 0000000..50d2ae5 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/maple_upload @@ -0,0 +1,49 @@ +#!/bin/bash + +#set -e + + + +if [ $# -lt 4 ]; then + echo "Usage: $0 $# " >&2 + exit 1 +fi +dummy_port="$1"; altID="$2"; usbID="$3"; binfile="$4"; dummy_port_fullpath="/dev/$1" +if [ $# -eq 5 ]; then + dfuse_addr="--dfuse-address $5" +else + dfuse_addr="" +fi + + +# Get the directory where the script is running. +DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +# ----------------- IMPORTANT ----------------- +# The 2nd parameter to upload-reset is the delay after resetting before it exits +# This value is in milliseonds +# You may need to tune this to your system +# 750ms to 1500ms seems to work on my Mac + + +"${DIR}/upload-reset" ${dummy_port_fullpath} 750 + + +#DFU_UTIL=$(dirname $0)/dfu-util/dfu-util +DFU_UTIL=/usr/bin/dfu-util +DFU_UTIL=${DIR}/dfu-util/dfu-util +if [ ! -x "${DFU_UTIL}" ]; then + echo "$0: error: cannot find ${DFU_UTIL}" >&2 + exit 2 +fi + +"${DFU_UTIL}" -d ${usbID} -a ${altID} -D ${binfile} ${dfuse_addr} -R + +echo -n Waiting for ${dummy_port_fullpath} serial... + +COUNTER=0 +while [ ! -r ${dummy_port_fullpath} ] && ((COUNTER++ < 40)); do + sleep 0.1 +done + +echo Done diff --git a/BootLoaders/Boards/stm32/tools/linux/readme.txt b/BootLoaders/Boards/stm32/tools/linux/readme.txt new file mode 100644 index 0000000..2d13beb --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/readme.txt @@ -0,0 +1 @@ +The maple upload script needs its rights to be set to 755 \ No newline at end of file diff --git a/BootLoaders/Boards/stm32/tools/linux/serial_upload b/BootLoaders/Boards/stm32/tools/linux/serial_upload new file mode 100644 index 0000000..755444a --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/serial_upload @@ -0,0 +1,2 @@ +#!/bin/bash +$(dirname $0)/stm32flash/stm32flash -g 0x8000000 -b 115200 -w "$4" /dev/"$1" diff --git a/BootLoaders/Boards/stm32/tools/linux/src/build_dfu-util.sh b/BootLoaders/Boards/stm32/tools/linux/src/build_dfu-util.sh new file mode 100644 index 0000000..3563f57 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/build_dfu-util.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +sudo apt-get build-dep dfu-util +sudo apt-get install build-essentials +sudo apt-get install libusb-1.0-0-dev +sudo apt-get install autoconf automake autotools-dev + +cd dfu-util +./autogen.sh +./configure +make +cp src/dfu-util ../../linux/dfu-util +cp src/dfu-suffix ../../linux/dfu-util +cp src/dfu-prefix ../../linux/dfu-util + diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/AUTHORS b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/AUTHORS new file mode 100644 index 0000000..1b36c73 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/AUTHORS @@ -0,0 +1,30 @@ +Authors ordered by first contribution. + +Harald Welte +Werner Almesberger +Michael Lauer +Jim Huang +Stefan Schmidt +Daniel Willmann +Mike Frysinger +Uwe Hermann +C. Scott Ananian +Bernard Blackham +Holger Freyther +Marc Singer +James Perkins +Tommi Keisala +Pascal Schweizer +Bradley Scott +Uwe Bonnes +Andrey Smirnov +Jussi Timperi +Hans Petter Selasky +Bo Shen +Henrique de Almeida Mendonca +Bernd Krumboeck +Dennis Meier +Veli-Pekka Peltola +Dave Hylands +Michael Grzeschik +Paul Fertser diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/COPYING b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/COPYING new file mode 100644 index 0000000..d60c31a --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/ChangeLog b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/ChangeLog new file mode 100644 index 0000000..37f1add --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/ChangeLog @@ -0,0 +1,93 @@ +0.8: + o New, separate dfu-prefix tool (Uwe Bonnes) + o Allow filtering on serial number (Uwe Bonnes) + o Improved VID/PID/serial filtering (Bradley Scott) + o Support reading firmware from stdin (Tormod Volden) + o Warn if missing DFU suffix (Tormod Volden) + o Improved progress bar (Hans Petter Selasky) + o Fix dfuse leave option (Uwe Bonnes) + o Major code rework (Hans Petter Selasky) + o MS Visual Studio build support (Henrique Mendonca) + o dfuse-pack.py tool for .dfu files (Antonio Galeo) + o Many other fixes from many people + +2014-09-13: Tormod Volden + +0.7: + o Support for TI Stellaris devices (Tommi Keisala) + o Fix libusb detection on MacOSX (Marc Singer) + o Fix libusb detection on FreeBSD (Tormod Volden) + o Improved DfuSe support (Tormod Volden) + o Support all special commands (leave, unprotect, mass-erase) + o Arbitrary upload lengths + o "force" option for various possible (dangerous) overrides + +2012-10-07: Tormod Volden + +0.6: + o Add detach mode (Stefan Schmidt) + o Check return value on all libusb calls (Tormod Volden) + o Fix segmentation fault with -s option (Tormod Volden) + o Add DFU suffix manipulation tool (Stefan Schmidt) + o Port to Windows: (Tormod Volden, some parts based on work from Satz + Klauer) + o Port file handling to stdio streams + o Sleep() macros + o C99 types + o Pack structs + o Detect DfuSe device correctly on big-endian architectures (Tormod + Volden) + o Add dfuse progress indication on download (Tormod Volden) + o Cleanup: gcc pedantic, gcc extension, ... (Tormod Volden) + o Rely on page size from functional descriptor. Please report if you get + an error about it. (Tormod Volden) + o Add quirk for Maple since it reports wrong DFU version (Tormod Volden) + +2012-04-22: Stefan Schmidt + +0.5: + o DfuSe extension support for ST devices (Tormod Volden) + o Add initial support for bitWillDetach flag from DFU 1.1 (Tormod + Volden) + o Internal cleanup and some manual page fixes (Tormod Volden) + +2011-11-02: Stefan Schmidt + +0.4: + o Rework to use libusb-1.0 (Stefan Schmidt) + o DFU suffix support (Tormod Volden, Stefan Schmidt) + o Sspeed up DFU downloads directly into memory (Bernard Blackham) + o More flexible -d vid:pid parsing (Tormod Volden) + o Many bug fixes and cleanups + +2011-07-20: Stefan Schmidt + +0.3: + o quirks: Add OpenOCD to the poll timeout quirk table. + +2010-12-22: Stefan Schmidt + +0.2: + o Fix some typos on the website and the README (Antonio Ospite, Uwe + Hermann) + o Remove build rule for a static binary. We can use autotools for this. + (Mike Frysinger) + o Fix infinite loop in download error path (C. Scott Ananian) + o Break out to show the 'finished' in upload (C. Scott Ananian) + o Add GPLv2+ headers (Harald Welte) + o Remove dead code (commands.[ch]) remnescent of dfu-programmer (Harald + Welte) + o Simple quirk system with Openmoko quirk for missing bwPollTimeout (Tormod Volden) + o New default (1024) and clamping of transfer size (Tormod Volden) + o Verify sending of completion packet (Tormod Volden) + o Look for DFU functional descriptor among all descriptors (Tormod + Volden) + o Print out in which direction we are transferring data + o Abort in upload if the file already exists + +2010-11-17 Stefan Schmidt + +0.1: + Initial release + +2010-05-23 Stefan Schmidt diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/DEVICES.txt b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/DEVICES.txt new file mode 100644 index 0000000..bdd9f1f --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/DEVICES.txt @@ -0,0 +1,20 @@ +List of supported software and hardware products: + +Software user (bootloader, etc) +------------------------------- +- Sam7DFU: http://www.openpcd.org/Sam7dfu +- U-boot: DFU patches +- Barebox: http://www.barebox.org/ +- Leaflabs: http://code.google.com/p/leaflabs/ +- Blackmagic DFU + +Products using DFU +------------------ +- OpenPCD (sam7dfu) +- Openmoko Neo 1973 and Freerunner (u-boot with DFU patches) +- Leaflabs Maple +- ATUSB from Qi Hardware +- STM32F105/7, STM32F2/F3/F4 in System Bootloader +- Blackmagic debug probe +- NXP LPC31xx/LPC43XX, e.g. LPC-Link and LPC-Link2, need binaries + with LPC prefix and encoding (LPC-Link) diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/Makefile.am b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/Makefile.am new file mode 100644 index 0000000..641dda5 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = src doc + +EXTRA_DIST = autogen.sh TODO DEVICES.txt dfuse-pack.py diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/README b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/README new file mode 100644 index 0000000..0f8f262 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/README @@ -0,0 +1,20 @@ +Dfu-util - Device Firmware Upgrade Utilities + +Dfu-util is the host side implementation of the DFU 1.0 [1] and DFU 1.1 [2] +specification of the USB forum. + +DFU is intended to download and upload firmware to devices connected over +USB. It ranges from small devices like micro-controller boards up to mobile +phones. With dfu-util you are able to download firmware to your device or +upload firmware from it. + +dfu-util has been tested with Openmoko Neo1973 and Freerunner and many +other devices. + +[1] DFU 1.0 spec: http://www.usb.org/developers/devclass_docs/usbdfu10.pdf +[2] DFU 1.1 spec: http://www.usb.org/developers/devclass_docs/DFU_1.1.pdf + +The official website is: + + http://dfu-util.gnumonks.org/ + diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/TODO b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/TODO new file mode 100644 index 0000000..900c30c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/TODO @@ -0,0 +1,14 @@ +DfuSe: +- Do erase and write in two separate passes when downloading +- Skip "Set Address" command when downloading contiguous blocks +- Implement "Get Commands" command + +Devices: +- Research iPhone/iPod/iPad support + Heavily modified dfu-util fork here: + https://github.com/planetbeing/xpwn/tree/master/dfu-util +- Test against Niftylights + +Non-Code: +- Logo +- Re-License as LGPL for usage as library? diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/autogen.sh b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/autogen.sh new file mode 100644 index 0000000..e67aed3 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/autogen.sh @@ -0,0 +1,2 @@ +#! /bin/sh +autoreconf -v -i diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/configure.ac b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/configure.ac new file mode 100644 index 0000000..8622114 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/configure.ac @@ -0,0 +1,41 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.59) +AC_INIT([dfu-util],[0.8],[dfu-util@lists.gnumonks.org],,[http://dfu-util.gnumonks.org]) +AC_CONFIG_AUX_DIR(m4) +AM_INIT_AUTOMAKE([foreign]) +AC_CONFIG_HEADERS([config.h]) + +# Test for new silent rules and enable only if they are available +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +# Checks for programs. +AC_PROG_CC + +# Checks for libraries. +# On FreeBSD the libusb-1.0 is called libusb and resides in system location +AC_CHECK_LIB([usb], [libusb_init],, [native_libusb=no],) +AS_IF([test x$native_libusb = xno], [ + PKG_CHECK_MODULES([USB], [libusb-1.0 >= 1.0.0],, + AC_MSG_ERROR([*** Required libusb-1.0 >= 1.0.0 not installed ***])) +]) +AC_CHECK_LIB([usbpath],[usb_path2devnum],,,-lusb) + +LIBS="$LIBS $USB_LIBS" +CFLAGS="$CFLAGS $USB_CFLAGS" + +# Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS([usbpath.h windows.h sysexits.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_TYPE_SIZE_T + +# Checks for library functions. +AC_FUNC_MEMCMP +AC_CHECK_FUNCS([ftruncate getpagesize nanosleep err]) + +AC_CONFIG_FILES(Makefile src/Makefile doc/Makefile) +AC_OUTPUT diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/README b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/README new file mode 100644 index 0000000..00d3d1a --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/README @@ -0,0 +1,77 @@ +Device: +------- +qi-hardware-atusb: +- Qi Hardware ben-wpan +- DFU implementation: + http://projects.qi-hardware.com/index.php/p/ben-wpan/source/tree/master/atusb/fw/usb +- Tester: Stefan Schmidt + +openpcd: +- OpenPCD RFID reader +- DFU implementation: SAM7DFU + http://www.openpcd.org/Sam7dfu, git://git.gnumonks.org/openpcd.git +- Tester: Stefan Schmidt + +simtrace: +- Sysmocom SimTrace +- DFU implementation: SAM7DFU + http://www.openpcd.org/Sam7dfu, git://git.gnumonks.org/openpcd.git +- Tester: Stefan Schmidt + +openmoko-freerunner: +- Openmoko Freerunner +- DFU implementation: Old U-Boot + http://git.openmoko.org/?p=u-boot.git;a=shortlog;h=refs/heads/mokopatches +- Tester: Stefan Schmidt + +openmoko-neo1973: +- Openmoko Neo1073 +- DFU implementation: Old U-Boot + http://git.openmoko.org/?p=u-boot.git;a=shortlog;h=refs/heads/mokopatches +- Tester: Stefan Schmidt + +tdk-bluetooth: +- TDK Corp. Bluetooth Adapter +- DFU implementation: closed soure +- Only upload has been tested +- Tester: Stefan Schmidt + +stm32f107: +- STM32 microcontrollers with built-in (ROM) DFU loader +- DFU implementation: Closed source but probably similar to the one + in their USB device libraries. Some relevant application notes: + http://www.st.com -> AN3156 and AN2606 +- Tested by Uwe Bonnes + +stm32f4discovery: +- STM32 microcontroller board with built-in (ROM) DFU loader +- DFU implementation: Closed source, probably similar to stm32f107. +- Tested by Joe Rothweiler + +dso-nano: +- DSO Nano pocket oscilloscope +- DFU implementation: Based on ST Microelectronics USB FS Library 1.0 + http://dsonano.googlecode.com/files/DS0201_OpenSource.rar +- Tester: Tormod Volden + +opc-20: +- Custom devices based on STM32F1xx +- DFU implementation: ST Microelectronics USB FS Device Library 3.1.0 + http://www.st.com -> um0424.zip +- Tester: Tormod Volden + +lpc-link, lpclink2: +- NXP LPCXpresso debug adapters +- Proprietary DFU implementation, uses special download files with + LPC prefix and encoding of the target firmware code +- Tested by Uwe Bonnes + +Adding the lsusb output and a download log of your device here helps +us to avoid regressions for hardware we cannot test while working on +the code. To extract the lsusb output use this command: +sudo lsusb -v -d $USBID > $DEVICE.lsusb +Prepare a description snippet as above, and send it to us. A log +(copy-paste of the command window) of a firmware download is also +nice, please use the double verbose option -v -v and include the +command line in the log file. + diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/dsonano.lsusb b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/dsonano.lsusb new file mode 100644 index 0000000..140a7bc --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/dsonano.lsusb @@ -0,0 +1,60 @@ + +Bus 002 Device 004: ID 0483:df11 SGS Thomson Microelectronics +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x0483 SGS Thomson Microelectronics + idProduct 0xdf11 + bcdDevice 1.1a + iManufacturer 1 STMicroelectronics + iProduct 2 STM32 DFU + iSerial 3 001 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 36 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 64mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 0 + iInterface 4 @Internal Flash /0x08000000/12*001Ka,116*001Kg + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 0 + iInterface 5 @SPI Flash : M25P64/0x00000000/64*064Kg,64*064Kg + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 11 + Will Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 255 milliseconds + wTransferSize 1024 bytes + bcdDFUVersion 1.1a +Device Status: 0x0000 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/lpclink.log b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/lpclink.log new file mode 100644 index 0000000..7de4dd3 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/lpclink.log @@ -0,0 +1,59 @@ +(The on-board LPC3154 has some encryption key set and LPCXpressoWIN.enc +is encrypted.) + +$ lsusb | grep NXP +Bus 003 Device 011: ID 0471:df55 Philips (or NXP) LPCXpresso LPC-Link + +$ dfu-util -v -v -v -R -D /opt/lpc/lpcxpresso/bin/LPCXpressoWIN.enc + +dfu-util 0.7 + +Copyright 2005-2008 Weston Schmidt, Harald Welte and OpenMoko Inc. +Copyright 2010-2012 Tormod Volden and Stefan Schmidt +This program is Free Software and has ABSOLUTELY NO WARRANTY +Please report bugs to dfu-util@lists.gnumonks.org + +dfu-util: Invalid DFU suffix signature +dfu-util: A valid DFU suffix will be required in a future dfu-util release!!! +Deducing device DFU version from functional descriptor length +Opening DFU capable USB device... +ID 0471:df55 +Run-time device DFU version 0100 +Claiming USB DFU Runtime Interface... +Determining device status: +state = dfuIDLE, status = 0 +dfu-util: WARNING: Runtime device already in DFU state ?!? +Claiming USB DFU Interface... +Setting Alternate Setting #0 ... +Determining device status: +state = dfuIDLE, status = 0 +dfuIDLE, continuing +DFU mode device DFU version 0100 +Device returned transfer size 2048 +Copying data from PC to DFU device +Download [ ] 0% 0 bytes +Download [= ] 6% 2048 bytes +Download [=== ] 13% 4096 bytes +Download [==== ] 19% 6144 bytes +Download [====== ] 26% 8192 bytes +Download [======== ] 32% 10240 bytes +Download [========= ] 39% 12288 bytes +Download [=========== ] 45% 14336 bytes +Download [============= ] 52% 16384 bytes +Download [============== ] 59% 18432 bytes +Download [================ ] 65% 20480 bytes +Download [================== ] 72% 22528 bytes +Download [=================== ] 78% 24576 bytes +Download [===================== ] 85% 26624 bytes +Download [====================== ] 91% 28672 bytes +Download [======================== ] 98% 29192 bytes +Download [=========================] 100% 29192 bytes +Download done. +Sent a total of 29192 bytes +state(8) = dfuMANIFEST-WAIT-RESET, status(0) = No error condition is present +Done! +dfu-util: can't detach +Resetting USB to switch back to runtime mode + +$ lsusb | grep NXP +Bus 003 Device 012: ID 1fc9:0009 NXP Semiconductors diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/lpclink.lsusb b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/lpclink.lsusb new file mode 100644 index 0000000..867b2a2 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/lpclink.lsusb @@ -0,0 +1,58 @@ + +Bus 003 Device 008: ID 0471:df55 Philips (or NXP) LPCXpresso LPC-Link +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x0471 Philips (or NXP) + idProduct 0xdf55 LPCXpresso LPC-Link + bcdDevice 0.01 + iManufacturer 0 + iProduct 0 + iSerial 0 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 25 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 0 + iInterface 0 + Device Firmware Upgrade Interface Descriptor: + bLength 7 + bDescriptorType 33 + bmAttributes 1 + Will Not Detach + Manifestation Intolerant + Upload Unsupported + Download Supported + wDetachTimeout 65535 milliseconds + wTransferSize 2048 bytes +Device Qualifier (for other device speed): + bLength 10 + bDescriptorType 6 + bcdUSB 2.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + bNumConfigurations 1 +Device Status: 0x0000 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/lpclink2.log b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/lpclink2.log new file mode 100644 index 0000000..4681eff --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/lpclink2.log @@ -0,0 +1,59 @@ +$ lsusb | grep NXP +Bus 003 Device 013: ID 1fc9:000c NXP Semiconductors + +$ dfu-util -D ~/devel/dfu-util/firmware.bin.qthdr + +dfu-util 0.7 + +Copyright 2005-2008 Weston Schmidt, Harald Welte and OpenMoko Inc. +Copyright 2010-2012 Tormod Volden and Stefan Schmidt +This program is Free Software and has ABSOLUTELY NO WARRANTY +Please report bugs to dfu-util@lists.gnumonks.org + +dfu-util: Invalid DFU suffix signature +dfu-util: A valid DFU suffix will be required in a future dfu-util release!!! +Possible unencryptes NXP LPC DFU prefix with the following properties +Payload length: 39 kiByte +Opening DFU capable USB device... +ID 1fc9:000c +Run-time device DFU version 0100 +Claiming USB DFU Runtime Interface... +Determining device status: +state = dfuIDLE, status = 0 +dfu-util: WARNING: Runtime device already in DFU state ?!? +Claiming USB DFU Interface... +Setting Alternate Setting #0 ... +Determining device status: +state = dfuIDLE, status = 0 +dfuIDLE, continuing +DFU mode device DFU version 0100 +Device returned transfer size 2048 +Copying data from PC to DFU device +Download [ ] 0% 0 bytes +Download [= ] 4% 2048 bytes +Download [== ] 9% 4096 bytes +Download [=== ] 14% 6144 bytes +Download [==== ] 19% 8192 bytes +Download [====== ] 24% 10240 bytes +Download [======= ] 28% 12288 bytes +Download [======== ] 33% 14336 bytes +Download [========= ] 38% 16384 bytes +Download [========== ] 43% 18432 bytes +Download [============ ] 48% 20480 bytes +Download [============= ] 53% 22528 bytes +Download [============== ] 57% 24576 bytes +Download [=============== ] 62% 26624 bytes +Download [================ ] 67% 28672 bytes +Download [================== ] 72% 30720 bytes +Download [=================== ] 77% 32768 bytes +Download [==================== ] 82% 34816 bytes +Download [===================== ] 86% 36864 bytes +Download [====================== ] 91% 38912 bytes +Download [======================== ] 96% 40356 bytes +Download [=========================] 100% 40356 bytes +Download done. +Sent a total of 40356 bytes +dfu-util: unable to read DFU status + +$ lsusb | grep NXP +Bus 003 Device 014: ID 1fc9:0018 NXP Semiconductors diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/lpclink2.lsusb b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/lpclink2.lsusb new file mode 100644 index 0000000..b833fca --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/lpclink2.lsusb @@ -0,0 +1,203 @@ + +Bus 003 Device 007: ID 0c72:000c PEAK System PCAN-USB +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 16 + idVendor 0x0c72 PEAK System + idProduct 0x000c PCAN-USB + bcdDevice 1c.ff + iManufacturer 0 + iProduct 3 VER1:PEAK +VER2:02.8.01 +DAT :06.05.2004 +TIME:09:35:37 + ... + iSerial 0 + bNumConfigurations 3 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 46 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 200mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 4 + bInterfaceClass 0 (Defined at Interface level) + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 20 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x01 EP 1 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 20 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 46 + bNumInterfaces 1 + bConfigurationValue 2 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 394mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 4 + bInterfaceClass 0 (Defined at Interface level) + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 20 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x01 EP 1 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 20 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 46 + bNumInterfaces 1 + bConfigurationValue 3 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 200mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 4 + bInterfaceClass 0 (Defined at Interface level) + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x01 EP 1 OUT + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 +Device Status: 0x0001 + Self Powered diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/opc-20.lsusb b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/opc-20.lsusb new file mode 100644 index 0000000..580df90 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/opc-20.lsusb @@ -0,0 +1,60 @@ + +Bus 001 Device 004: ID 0483:df11 SGS Thomson Microelectronics +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x0483 SGS Thomson Microelectronics + idProduct 0xdf11 + bcdDevice 2.00 + iManufacturer 1 STMicroelectronics + iProduct 2 STM32 DFU + iSerial 3 ÿÿÿÿÿÿÿÿÿÿÿÿ + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 36 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0xc0 + Self Powered + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 4 @Internal Flash /0x08000000/12*001Ka,116*001Kg + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 5 @SPI Flash : M25P64/0x00000000/128*64Kg + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 11 + Will Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 255 milliseconds + wTransferSize 1024 bytes + bcdDFUVersion 1a.01 +Device Status: 0x0001 + Self Powered diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/openmoko-freerunner-dfumode.lsusb b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/openmoko-freerunner-dfumode.lsusb new file mode 100644 index 0000000..4c0abfb --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/openmoko-freerunner-dfumode.lsusb @@ -0,0 +1,109 @@ +Bus 003 Device 017: ID 1d50:5119 OpenMoko, Inc. GTA01/GTA02 U-Boot Bootloader +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 16 + idVendor 0x1d50 OpenMoko, Inc. + idProduct 0x5119 GTA01/GTA02 U-Boot Bootloader + bcdDevice 0.00 + iManufacturer 1 OpenMoko, Inc + iProduct 2 Neo1973 Bootloader U-Boot 1.3.2-moko12 + iSerial 3 0000000 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 81 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 7 USB Device Firmware Upgrade + bmAttributes 0x80 + (Bus Powered) + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 8 RAM 0x32000000 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 9 u-boot + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 2 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 10 u-boot_env + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 3 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 11 kernel + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 4 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 12 splash + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 5 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 13 factory + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 6 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 14 rootfs + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 7 + Will Not Detach + Manifestation Tolerant + Upload Supported + Download Supported + wDetachTimeout 65280 milliseconds + wTransferSize 4096 bytes + bcdDFUVersion 1.00 +Device Status: 0x0a00 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/openmoko-freerunner.lsusb b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/openmoko-freerunner.lsusb new file mode 100644 index 0000000..835708d --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/openmoko-freerunner.lsusb @@ -0,0 +1,179 @@ +Bus 005 Device 033: ID 1d50:5119 OpenMoko, Inc. GTA01/GTA02 U-Boot Bootloader +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.10 + bDeviceClass 2 Communications + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 16 + idVendor 0x1d50 OpenMoko, Inc. + idProduct 0x5119 GTA01/GTA02 U-Boot Bootloader + bcdDevice 0.00 + iManufacturer 1 OpenMoko, Inc + iProduct 2 Neo1973 Bootloader U-Boot 1.3.2-moko12 + iSerial 3 0000000 + bNumConfigurations 2 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 85 + bNumInterfaces 3 + bConfigurationValue 1 + iConfiguration 4 TTY via USB + bmAttributes 0x80 + (Bus Powered) + MaxPower 500mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 2 Communications + bInterfaceSubClass 2 Abstract (modem) + bInterfaceProtocol 1 AT-commands (v.25ter) + iInterface 6 Control Interface + CDC Header: + bcdCDC 0.6e + CDC Call Management: + bmCapabilities 0x00 + bDataInterface 1 + CDC ACM: + bmCapabilities 0x00 + CDC Union: + bMasterInterface 0 + bSlaveInterface 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 10 CDC Data + bInterfaceSubClass 0 Unused + bInterfaceProtocol 0 + iInterface 5 Bulk Data Interface + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 2 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 1 + iInterface 7 USB Device Firmware Upgrade + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 7 + Will Not Detach + Manifestation Tolerant + Upload Supported + Download Supported + wDetachTimeout 65280 milliseconds + wTransferSize 4096 bytes + bcdDFUVersion 1.00 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 67 + bNumInterfaces 2 + bConfigurationValue 2 + iConfiguration 4 TTY via USB + bmAttributes 0x80 + (Bus Powered) + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 2 Communications + bInterfaceSubClass 2 Abstract (modem) + bInterfaceProtocol 1 AT-commands (v.25ter) + iInterface 6 Control Interface + CDC Header: + bcdCDC 0.6e + CDC Call Management: + bmCapabilities 0x00 + bDataInterface 1 + CDC ACM: + bmCapabilities 0x00 + CDC Union: + bMasterInterface 0 + bSlaveInterface 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 10 CDC Data + bInterfaceSubClass 0 Unused + bInterfaceProtocol 0 + iInterface 5 Bulk Data Interface + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 +Device Status: 0x9a00 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/openmoko-neo1973.lsusb b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/openmoko-neo1973.lsusb new file mode 100644 index 0000000..0778950 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/openmoko-neo1973.lsusb @@ -0,0 +1,182 @@ + +Bus 006 Device 020: ID 1457:5119 First International Computer, Inc. OpenMoko Neo1973 u-boot cdc_acm serial port +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.10 + bDeviceClass 2 Communications + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 16 + idVendor 0x1457 First International Computer, Inc. + idProduct 0x5119 OpenMoko Neo1973 u-boot cdc_acm serial port + bcdDevice 0.00 + iManufacturer 1 + iProduct 2 + iSerial 3 + bNumConfigurations 2 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 85 + bNumInterfaces 3 + bConfigurationValue 1 + iConfiguration 4 + bmAttributes 0x80 + (Bus Powered) + MaxPower 500mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 2 Communications + bInterfaceSubClass 2 Abstract (modem) + bInterfaceProtocol 1 AT-commands (v.25ter) + iInterface 6 + CDC Header: + bcdCDC 0.6e + CDC Call Management: + bmCapabilities 0x00 + bDataInterface 1 + CDC ACM: + bmCapabilities 0x00 + CDC Union: + bMasterInterface 0 + bSlaveInterface 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 10 CDC Data + bInterfaceSubClass 0 Unused + bInterfaceProtocol 0 + iInterface 5 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 2 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 1 + iInterface 7 + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 7 + Will Not Detach + Manifestation Tolerant + Upload Supported + Download Supported + wDetachTimeout 65280 milliseconds + wTransferSize 4096 bytes + bcdDFUVersion 1.00 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 67 + bNumInterfaces 2 + bConfigurationValue 2 + iConfiguration 4 + bmAttributes 0x80 + (Bus Powered) + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 2 Communications + bInterfaceSubClass 2 Abstract (modem) + bInterfaceProtocol 1 AT-commands (v.25ter) + iInterface 6 + CDC Header: + bcdCDC 0.6e + CDC Call Management: + bmCapabilities 0x00 + bDataInterface 1 + CDC ACM: + bmCapabilities 0x00 + CDC Union: + bMasterInterface 0 + bSlaveInterface 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 10 CDC Data + bInterfaceSubClass 0 Unused + bInterfaceProtocol 0 + iInterface 5 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 +Device Status: 0x0006 + (Bus Powered) + Remote Wakeup Enabled + Test Mode diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/openpcd.lsusb b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/openpcd.lsusb new file mode 100644 index 0000000..f6255a9 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/openpcd.lsusb @@ -0,0 +1,60 @@ + +Bus 006 Device 016: ID 16c0:076b VOTI OpenPCD 13.56MHz RFID Reader +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 8 + idVendor 0x16c0 VOTI + idProduct 0x076b OpenPCD 13.56MHz RFID Reader + bcdDevice 0.00 + iManufacturer 1 + iProduct 2 OpenPCD RFID Simulator - DFU Mode + iSerial 0 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 36 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 200mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 0 + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 3 + Will Not Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 65280 milliseconds + wTransferSize 256 bytes + bcdDFUVersion 1.00 +Device Status: 0x0000 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/qi-hardware-atusb.lsusb b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/qi-hardware-atusb.lsusb new file mode 100644 index 0000000..bfc1701 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/qi-hardware-atusb.lsusb @@ -0,0 +1,59 @@ + +Bus 006 Device 013: ID 20b7:1540 Qi Hardware ben-wpan, AT86RF230-based +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 255 Vendor Specific Class + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x20b7 Qi Hardware + idProduct 0x1540 ben-wpan, AT86RF230-based + bcdDevice 0.01 + iManufacturer 0 + iProduct 0 + iSerial 1 4630333438371508231a + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 34 + bNumInterfaces 2 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 40mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 255 Vendor Specific Class + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 1 + iInterface 0 +Device Status: 0x0000 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/simtrace.lsusb b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/simtrace.lsusb new file mode 100644 index 0000000..578ddf0 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/simtrace.lsusb @@ -0,0 +1,70 @@ + +Bus 006 Device 017: ID 16c0:0762 VOTI +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 8 + idVendor 0x16c0 VOTI + idProduct 0x0762 + bcdDevice 0.00 + iManufacturer 1 sysmocom - systems for mobile communications GmbH + iProduct 2 SimTrace SIM Sniffer - DFU Mode + iSerial 0 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 45 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 3 SimTrace DFU Configuration + bmAttributes 0x80 + (Bus Powered) + MaxPower 200mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 4 SimTrace DFU Interface - Application Partition + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 5 SimTrace DFU Interface - Bootloader Partition + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 2 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 6 SimTrace DFU Interface - RAM + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 3 + Will Not Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 65280 milliseconds + wTransferSize 256 bytes + bcdDFUVersion 1.00 +Device Status: 0x0000 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/sparkcore.lsusb b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/sparkcore.lsusb new file mode 100644 index 0000000..b6029ff --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/sparkcore.lsusb @@ -0,0 +1,60 @@ + +Bus 001 Device 008: ID 1d50:607f OpenMoko, Inc. +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x1d50 OpenMoko, Inc. + idProduct 0x607f + bcdDevice 2.00 + iManufacturer 1 Spark Devices + iProduct 2 CORE DFU + iSerial 3 8D80527B5055 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 36 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0xc0 + Self Powered + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 4 @Internal Flash /0x08000000/20*001Ka,108*001Kg + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 5 @SPI Flash : SST25x/0x00000000/512*04Kg + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 11 + Will Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 255 milliseconds + wTransferSize 1024 bytes + bcdDFUVersion 1.1a +Device Status: 0x0001 + Self Powered diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/stm32f107.bin-download b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/stm32f107.bin-download new file mode 100644 index 0000000..45b714f --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/stm32f107.bin-download @@ -0,0 +1,48 @@ +> src/dfu-util --intf 0 --alt 0 -v -v -v -s 0x8000000 -D test3 +dfu-util 0.4 + +(C) 2005-2008 by Weston Schmidt, Harald Welte and OpenMoko Inc. +(C) 2010-2011 Tormod Volden (DfuSe support) +This program is Free Software and has ABSOLUTELY NO WARRANTY + +dfu-util does currently only support DFU version 1.0 + +Opening DFU USB device... ID 0483:df11 +Run-time device DFU version 011a +Found DFU: [0483:df11] devnum=0, cfg=1, intf=0, alt=0, name="@Internal Flash /0x08000000/128*002Kg" +Claiming USB DFU Interface... +Setting Alternate Setting #0 ... +Determining device status: state = dfuIDLE, status = 0 +dfuIDLE, continuing +DFU mode device DFU version 011a +Device returned transfer size 2048 +No valid DFU suffix signature +Warning: File has no DFU suffix +DfuSe interface name: "Internal Flash " +Memory segment at 0x08000000 128 x 2048 = 262144 (rew) +Uploading to address = 0x08000000, size = 16384 +Erasing page size 2048 at address 0x08000000, page starting at 0x08000000 + Download from image offset 00000000 to memory 08000000-080007ff, size 2048 + Setting address pointer to 0x08000000 +Erasing page size 2048 at address 0x08000800, page starting at 0x08000800 + Download from image offset 00000800 to memory 08000800-08000fff, size 2048 + Setting address pointer to 0x08000800 +Erasing page size 2048 at address 0x08001000, page starting at 0x08001000 + Download from image offset 00001000 to memory 08001000-080017ff, size 2048 + Setting address pointer to 0x08001000 +Erasing page size 2048 at address 0x08001800, page starting at 0x08001800 + Download from image offset 00001800 to memory 08001800-08001fff, size 2048 + Setting address pointer to 0x08001800 +Erasing page size 2048 at address 0x08002000, page starting at 0x08002000 + Download from image offset 00002000 to memory 08002000-080027ff, size 2048 + Setting address pointer to 0x08002000 +Erasing page size 2048 at address 0x08002800, page starting at 0x08002800 + Download from image offset 00002800 to memory 08002800-08002fff, size 2048 + Setting address pointer to 0x08002800 +Erasing page size 2048 at address 0x08003000, page starting at 0x08003000 + Download from image offset 00003000 to memory 08003000-080037ff, size 2048 + Setting address pointer to 0x08003000 +Erasing page size 2048 at address 0x08003800, page starting at 0x08003800 + Download from image offset 00003800 to memory 08003800-08003fff, size 2048 + Setting address pointer to 0x08003800 + diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/stm32f107.lsusb b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/stm32f107.lsusb new file mode 100644 index 0000000..14b45cd --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/stm32f107.lsusb @@ -0,0 +1,60 @@ + +Bus 001 Device 028: ID 0483:df11 SGS Thomson Microelectronics STM Device in DFU Mode +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x0483 SGS Thomson Microelectronics + idProduct 0xdf11 STM Device in DFU Mode + bcdDevice 20.00 + iManufacturer 1 STMicroelectronics + iProduct 2 STM32 0x418 DFU Bootloader + iSerial 3 STM32 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 36 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0xc0 + Self Powered + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 4 @Internal Flash /0x08000000/128*002Kg + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 5 @Option Bytes /0x1FFFF800/01*016 g + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 11 + Will Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 255 milliseconds + wTransferSize 2048 bytes + bcdDFUVersion 1.1a +Device Status: 0x0000 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/stm32f4discovery.bin-download b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/stm32f4discovery.bin-download new file mode 100644 index 0000000..96e1722 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/stm32f4discovery.bin-download @@ -0,0 +1,36 @@ +dfu-util --device 0483:df11 --alt 0 \ + --dfuse-address 0x08000000 \ + -v -v -v \ + --download arm/iotoggle.bin +No valid DFU suffix signature +Warning: File has no DFU suffix +dfu-util 0.5 + +(C) 2005-2008 by Weston Schmidt, Harald Welte and OpenMoko Inc. +(C) 2010-2011 Tormod Volden (DfuSe support) +This program is Free Software and has ABSOLUTELY NO WARRANTY + +dfu-util does currently only support DFU version 1.0 + +Filter on vendor = 0x0483 product = 0xdf11 +Opening DFU capable USB device... ID 0483:df11 +Run-time device DFU version 011a +Found DFU: [0483:df11] devnum=0, cfg=1, intf=0, alt=0, name="@Internal Flash /0x08000000/04*016Kg,01*064Kg,07*128Kg" +Claiming USB DFU Interface... +Setting Alternate Setting #0 ... +Determining device status: state = dfuERROR, status = 10 +dfuERROR, clearing status +Determining device status: state = dfuIDLE, status = 0 +dfuIDLE, continuing +DFU mode device DFU version 011a +Device returned transfer size 2048 +DfuSe interface name: "Internal Flash " +Memory segment at 0x08000000 4 x 16384 = 65536 (rew) +Memory segment at 0x08010000 1 x 65536 = 65536 (rew) +Memory segment at 0x08020000 7 x 131072 = 917504 (rew) +Uploading to address = 0x08000000, size = 2308 +Erasing page size 16384 at address 0x08000000, page starting at 0x08000000 + Download from image offset 00000000 to memory 08000000-080007ff, size 2048 + Setting address pointer to 0x08000000 + Download from image offset 00000800 to memory 08000800-08000903, size 260 + Setting address pointer to 0x08000800 diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/stm32f4discovery.lsusb b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/stm32f4discovery.lsusb new file mode 100644 index 0000000..0b870de --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/stm32f4discovery.lsusb @@ -0,0 +1,80 @@ + +Bus 001 Device 010: ID 0483:df11 SGS Thomson Microelectronics STM Device in DFU Mode +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x0483 SGS Thomson Microelectronics + idProduct 0xdf11 STM Device in DFU Mode + bcdDevice 21.00 + iManufacturer 1 STMicroelectronics + iProduct 2 STM32 BOOTLOADER + iSerial 3 315A28A0B956 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 54 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0xc0 + Self Powered + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 4 @Internal Flash /0x08000000/04*016Kg,01*064Kg,07*128Kg + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 5 @Option Bytes /0x1FFFC000/01*016 g + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 2 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 6 @OTP Memory /0x1FFF7800/01*512 g,01*016 g + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 3 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 7 @Device Feature/0xFFFF0000/01*004 g + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 11 + Will Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 255 milliseconds + wTransferSize 2048 bytes + bcdDFUVersion 1.1a +Device Status: 0x0001 + Self Powered diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/tdk-bluetooth.lsusb b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/tdk-bluetooth.lsusb new file mode 100644 index 0000000..c0cface --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/device-logs/tdk-bluetooth.lsusb @@ -0,0 +1,269 @@ + +Bus 006 Device 014: ID 04bf:0320 TDK Corp. Bluetooth Adapter +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 224 Wireless + bDeviceSubClass 1 Radio Frequency + bDeviceProtocol 1 Bluetooth + bMaxPacketSize0 64 + idVendor 0x04bf TDK Corp. + idProduct 0x0320 Bluetooth Adapter + bcdDevice 26.52 + iManufacturer 1 Ezurio + iProduct 2 Turbo Bluetooth Adapter + iSerial 3 008098D4FFBD + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 193 + bNumInterfaces 3 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 64mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 3 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0000 1x 0 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0000 1x 0 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 1 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0009 1x 9 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0009 1x 9 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 2 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0011 1x 17 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0011 1x 17 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 3 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0019 1x 25 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0019 1x 25 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 4 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0021 1x 33 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0021 1x 33 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 5 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0031 1x 49 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0031 1x 49 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 2 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 0 + iInterface 0 + Device Firmware Upgrade Interface Descriptor: + bLength 7 + bDescriptorType 33 + bmAttributes 7 + Will Not Detach + Manifestation Tolerant + Upload Supported + Download Supported + wDetachTimeout 5000 milliseconds + wTransferSize 1023 bytes +Device Status: 0x0000 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/dfuse-pack.py b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/dfuse-pack.py new file mode 100644 index 0000000..875cc5c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/dfuse-pack.py @@ -0,0 +1,121 @@ +#!/usr/bin/python + +# Written by Antonio Galea - 2010/11/18 +# Distributed under Gnu LGPL 3.0 +# see http://www.gnu.org/licenses/lgpl-3.0.txt + +import sys,struct,zlib,os +from optparse import OptionParser + +DEFAULT_DEVICE="0x0483:0xdf11" + +def named(tuple,names): + return dict(zip(names.split(),tuple)) +def consume(fmt,data,names): + n = struct.calcsize(fmt) + return named(struct.unpack(fmt,data[:n]),names),data[n:] +def cstring(string): + return string.split('\0',1)[0] +def compute_crc(data): + return 0xFFFFFFFF & -zlib.crc32(data) -1 + +def parse(file,dump_images=False): + print 'File: "%s"' % file + data = open(file,'rb').read() + crc = compute_crc(data[:-4]) + prefix, data = consume('<5sBIB',data,'signature version size targets') + print '%(signature)s v%(version)d, image size: %(size)d, targets: %(targets)d' % prefix + for t in range(prefix['targets']): + tprefix, data = consume('<6sBI255s2I',data,'signature altsetting named name size elements') + tprefix['num'] = t + if tprefix['named']: + tprefix['name'] = cstring(tprefix['name']) + else: + tprefix['name'] = '' + print '%(signature)s %(num)d, alt setting: %(altsetting)s, name: "%(name)s", size: %(size)d, elements: %(elements)d' % tprefix + tsize = tprefix['size'] + target, data = data[:tsize], data[tsize:] + for e in range(tprefix['elements']): + eprefix, target = consume('<2I',target,'address size') + eprefix['num'] = e + print ' %(num)d, address: 0x%(address)08x, size: %(size)d' % eprefix + esize = eprefix['size'] + image, target = target[:esize], target[esize:] + if dump_images: + out = '%s.target%d.image%d.bin' % (file,t,e) + open(out,'wb').write(image) + print ' DUMPED IMAGE TO "%s"' % out + if len(target): + print "target %d: PARSE ERROR" % t + suffix = named(struct.unpack('<4H3sBI',data[:16]),'device product vendor dfu ufd len crc') + print 'usb: %(vendor)04x:%(product)04x, device: 0x%(device)04x, dfu: 0x%(dfu)04x, %(ufd)s, %(len)d, 0x%(crc)08x' % suffix + if crc != suffix['crc']: + print "CRC ERROR: computed crc32 is 0x%08x" % crc + data = data[16:] + if data: + print "PARSE ERROR" + +def build(file,targets,device=DEFAULT_DEVICE): + data = '' + for t,target in enumerate(targets): + tdata = '' + for image in target: + tdata += struct.pack('<2I',image['address'],len(image['data']))+image['data'] + tdata = struct.pack('<6sBI255s2I','Target',0,1,'ST...',len(tdata),len(target)) + tdata + data += tdata + data = struct.pack('<5sBIB','DfuSe',1,len(data)+11,len(targets)) + data + v,d=map(lambda x: int(x,0) & 0xFFFF, device.split(':',1)) + data += struct.pack('<4H3sB',0,d,v,0x011a,'UFD',16) + crc = compute_crc(data) + data += struct.pack(' and +Harald Welte . Over time, nearly complete +support of DFU 1.0, DFU 1.1 and DfuSe ("1.1a") has been added. +.SH LICENCE +.B dfu-util +is covered by the GNU General Public License (GPL), version 2 or later. +.SH COPYRIGHT +This manual page was originally written by Uwe Hermann , +and is now part of the dfu-util project. diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/msvc/README_msvc.txt b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/msvc/README_msvc.txt new file mode 100644 index 0000000..6e68ec6 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/msvc/README_msvc.txt @@ -0,0 +1,10 @@ +# (C) Roger Meier +# (C) Pascal Schweizer +# msvc folder is GPL-2.0+, LGPL-2.1+, BSD-3-Clause or MIT license(SPDX) + +Building dfu-util native on Windows with Visual Studio + +3rd party dependencies: +- libusbx ( git clone https://github.com/libusbx/libusbx.git ) + - getopt (part of libusbx: libusbx/examples/getopt) + diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/msvc/dfu-suffix_2010.vcxproj b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/msvc/dfu-suffix_2010.vcxproj new file mode 100644 index 0000000..0c316c2 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/msvc/dfu-suffix_2010.vcxproj @@ -0,0 +1,100 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA} + dfusuffix + dfu-suffix + + + + Application + true + MultiByte + + + Application + false + true + MultiByte + + + + + + + + + + + + + $(SolutionDir)..\..\libusbx\examples\getopt;$(SolutionDir)..\..\libusbx\libusb;$(IncludePath) + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\dll;$(LibraryPath) + $(VCInstallDir)atlmfc\lib;$(VCInstallDir)lib + $(ExecutablePath) + + + $(ExecutablePath) + $(SolutionDir)..\..\libusbx\examples\getopt;$(SolutionDir)..\..\libusbx\libusb;$(IncludePath) + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\dll;$(LibraryPath) + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + + + + Level3 + Disabled + HAVE_WINDOWS_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreadedDebug + + + true + + + + + Level3 + MaxSpeed + true + true + HAVE_WINDOWS_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreaded + + + true + true + true + + + + + + + + + + + + + {a2169bc8-cf99-40bf-83f3-b0e38f7067bd} + + + {349ee8f9-7d25-4909-aaf5-ff3fade72187} + + + + + + \ No newline at end of file diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/msvc/dfu-util_2010.sln b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/msvc/dfu-util_2010.sln new file mode 100644 index 0000000..ef79723 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/msvc/dfu-util_2010.sln @@ -0,0 +1,54 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dfu-util", "dfu-util_2010.vcxproj", "{0E071A60-7EF2-4427-BAA8-9143CACB5BCB}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C4F8746D-B27E-4806-95E5-2052174E923B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dfu-suffix", "dfu-suffix_2010.vcxproj", "{8F7600A2-3B37-4956-B39B-A1D43EF29EDA}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "getopt_2010", "..\..\libusbx\msvc\getopt_2010.vcxproj", "{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (static)", "..\..\libusbx\msvc\libusb_static_2010.vcxproj", "{349EE8F9-7D25-4909-AAF5-FF3FADE72187}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB}.Debug|Win32.ActiveCfg = Debug|Win32 + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB}.Debug|Win32.Build.0 = Debug|Win32 + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB}.Debug|x64.ActiveCfg = Debug|Win32 + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB}.Release|Win32.ActiveCfg = Release|Win32 + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB}.Release|Win32.Build.0 = Release|Win32 + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB}.Release|x64.ActiveCfg = Release|Win32 + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA}.Debug|Win32.ActiveCfg = Debug|Win32 + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA}.Debug|Win32.Build.0 = Debug|Win32 + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA}.Debug|x64.ActiveCfg = Debug|Win32 + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA}.Release|Win32.ActiveCfg = Release|Win32 + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA}.Release|Win32.Build.0 = Release|Win32 + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA}.Release|x64.ActiveCfg = Release|Win32 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|Win32.ActiveCfg = Debug|Win32 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|Win32.Build.0 = Debug|Win32 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|x64.ActiveCfg = Debug|x64 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|x64.Build.0 = Debug|x64 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|Win32.ActiveCfg = Release|Win32 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|Win32.Build.0 = Release|Win32 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|x64.ActiveCfg = Release|x64 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|x64.Build.0 = Release|x64 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.ActiveCfg = Debug|Win32 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.Build.0 = Debug|Win32 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.ActiveCfg = Debug|x64 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.Build.0 = Debug|x64 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.ActiveCfg = Release|Win32 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.Build.0 = Release|Win32 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.ActiveCfg = Release|x64 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/msvc/dfu-util_2010.vcxproj b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/msvc/dfu-util_2010.vcxproj new file mode 100644 index 0000000..17a8bee --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/msvc/dfu-util_2010.vcxproj @@ -0,0 +1,120 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB} + dfuutil + dfu-util + + + + Application + true + MultiByte + + + Application + false + true + MultiByte + + + + + + + + + + + + + $(SolutionDir)..\..\libusbx\examples\getopt;$(SolutionDir)..\..\libusbx\libusb;$(IncludePath) + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + $(SolutionDir)..\$(Platform)\getopt\$(Configuration);$(LibraryPath) + $(VCInstallDir)atlmfc\lib;$(VCInstallDir)lib + $(ExecutablePath) + + + $(ExecutablePath) + $(SolutionDir)..\..\libusbx\examples\getopt;$(SolutionDir)..\..\libusbx\libusb;$(IncludePath) + $(SolutionDir)..\$(Platform)\getopt\$(Configuration);$(LibraryPath) + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + + + + Level3 + Disabled + HAVE_WINDOWS_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreadedDebug + + + true + + + + + + + + + Level3 + MaxSpeed + true + true + HAVE_WINDOWS_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreaded + + + true + true + true + + + copy $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0.dll $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + + + + + + + + + + + + + + + + + + + + + + + + + + {a2169bc8-cf99-40bf-83f3-b0e38f7067bd} + + + {349ee8f9-7d25-4909-aaf5-ff3fade72187} + + + + + + \ No newline at end of file diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/Makefile.am b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/Makefile.am new file mode 100644 index 0000000..70179c4 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/Makefile.am @@ -0,0 +1,28 @@ +AM_CFLAGS = -Wall -Wextra + +bin_PROGRAMS = dfu-util dfu-suffix dfu-prefix +dfu_util_SOURCES = main.c \ + portable.h \ + dfu_load.c \ + dfu_load.h \ + dfu_util.c \ + dfu_util.h \ + dfuse.c \ + dfuse.h \ + dfuse_mem.c \ + dfuse_mem.h \ + dfu.c \ + dfu.h \ + usb_dfu.h \ + dfu_file.c \ + dfu_file.h \ + quirks.c \ + quirks.h + +dfu_suffix_SOURCES = suffix.c \ + dfu_file.h \ + dfu_file.c + +dfu_prefix_SOURCES = prefix.c \ + dfu_file.h \ + dfu_file.c diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfu.c b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfu.c new file mode 100644 index 0000000..14d7673 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfu.c @@ -0,0 +1,357 @@ +/* + * Low-level DFU communication routines, originally taken from + * $Id: dfu.c,v 1.3 2006/06/20 06:28:04 schmidtw Exp $ + * (part of dfu-programmer). + * + * Copyright 2005-2006 Weston Schmidt + * Copyright 2011-2014 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include + +#include "portable.h" +#include "dfu.h" +#include "quirks.h" + +static int dfu_timeout = 5000; /* 5 seconds - default */ + +/* + * DFU_DETACH Request (DFU Spec 1.0, Section 5.1) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * timeout - the timeout in ms the USB device should wait for a pending + * USB reset before giving up and terminating the operation + * + * returns 0 or < 0 on error + */ +int dfu_detach( libusb_device_handle *device, + const unsigned short interface, + const unsigned short timeout ) +{ + return libusb_control_transfer( device, + /* bmRequestType */ LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_DETACH, + /* wValue */ timeout, + /* wIndex */ interface, + /* Data */ NULL, + /* wLength */ 0, + dfu_timeout ); +} + + +/* + * DFU_DNLOAD Request (DFU Spec 1.0, Section 6.1.1) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * length - the total number of bytes to transfer to the USB + * device - must be less than wTransferSize + * data - the data to transfer + * + * returns the number of bytes written or < 0 on error + */ +int dfu_download( libusb_device_handle *device, + const unsigned short interface, + const unsigned short length, + const unsigned short transaction, + unsigned char* data ) +{ + int status; + + status = libusb_control_transfer( device, + /* bmRequestType */ LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_DNLOAD, + /* wValue */ transaction, + /* wIndex */ interface, + /* Data */ data, + /* wLength */ length, + dfu_timeout ); + return status; +} + + +/* + * DFU_UPLOAD Request (DFU Spec 1.0, Section 6.2) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * length - the maximum number of bytes to receive from the USB + * device - must be less than wTransferSize + * data - the buffer to put the received data in + * + * returns the number of bytes received or < 0 on error + */ +int dfu_upload( libusb_device_handle *device, + const unsigned short interface, + const unsigned short length, + const unsigned short transaction, + unsigned char* data ) +{ + int status; + + status = libusb_control_transfer( device, + /* bmRequestType */ LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_UPLOAD, + /* wValue */ transaction, + /* wIndex */ interface, + /* Data */ data, + /* wLength */ length, + dfu_timeout ); + return status; +} + + +/* + * DFU_GETSTATUS Request (DFU Spec 1.0, Section 6.1.2) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * status - the data structure to be populated with the results + * + * return the number of bytes read in or < 0 on an error + */ +int dfu_get_status( struct dfu_if *dif, struct dfu_status *status ) +{ + unsigned char buffer[6]; + int result; + + /* Initialize the status data structure */ + status->bStatus = DFU_STATUS_ERROR_UNKNOWN; + status->bwPollTimeout = 0; + status->bState = STATE_DFU_ERROR; + status->iString = 0; + + result = libusb_control_transfer( dif->dev_handle, + /* bmRequestType */ LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_GETSTATUS, + /* wValue */ 0, + /* wIndex */ dif->interface, + /* Data */ buffer, + /* wLength */ 6, + dfu_timeout ); + + if( 6 == result ) { + status->bStatus = buffer[0]; + if (dif->quirks & QUIRK_POLLTIMEOUT) + status->bwPollTimeout = DEFAULT_POLLTIMEOUT; + else + status->bwPollTimeout = ((0xff & buffer[3]) << 16) | + ((0xff & buffer[2]) << 8) | + (0xff & buffer[1]); + status->bState = buffer[4]; + status->iString = buffer[5]; + } + + return result; +} + + +/* + * DFU_CLRSTATUS Request (DFU Spec 1.0, Section 6.1.3) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * + * return 0 or < 0 on an error + */ +int dfu_clear_status( libusb_device_handle *device, + const unsigned short interface ) +{ + return libusb_control_transfer( device, + /* bmRequestType */ LIBUSB_ENDPOINT_OUT| LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_CLRSTATUS, + /* wValue */ 0, + /* wIndex */ interface, + /* Data */ NULL, + /* wLength */ 0, + dfu_timeout ); +} + + +/* + * DFU_GETSTATE Request (DFU Spec 1.0, Section 6.1.5) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * length - the maximum number of bytes to receive from the USB + * device - must be less than wTransferSize + * data - the buffer to put the received data in + * + * returns the state or < 0 on error + */ +int dfu_get_state( libusb_device_handle *device, + const unsigned short interface ) +{ + int result; + unsigned char buffer[1]; + + result = libusb_control_transfer( device, + /* bmRequestType */ LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_GETSTATE, + /* wValue */ 0, + /* wIndex */ interface, + /* Data */ buffer, + /* wLength */ 1, + dfu_timeout ); + + /* Return the error if there is one. */ + if (result < 1) + return -1; + + /* Return the state. */ + return buffer[0]; +} + + +/* + * DFU_ABORT Request (DFU Spec 1.0, Section 6.1.4) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * + * returns 0 or < 0 on an error + */ +int dfu_abort( libusb_device_handle *device, + const unsigned short interface ) +{ + return libusb_control_transfer( device, + /* bmRequestType */ LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_ABORT, + /* wValue */ 0, + /* wIndex */ interface, + /* Data */ NULL, + /* wLength */ 0, + dfu_timeout ); +} + + +const char* dfu_state_to_string( int state ) +{ + const char *message; + + switch (state) { + case STATE_APP_IDLE: + message = "appIDLE"; + break; + case STATE_APP_DETACH: + message = "appDETACH"; + break; + case STATE_DFU_IDLE: + message = "dfuIDLE"; + break; + case STATE_DFU_DOWNLOAD_SYNC: + message = "dfuDNLOAD-SYNC"; + break; + case STATE_DFU_DOWNLOAD_BUSY: + message = "dfuDNBUSY"; + break; + case STATE_DFU_DOWNLOAD_IDLE: + message = "dfuDNLOAD-IDLE"; + break; + case STATE_DFU_MANIFEST_SYNC: + message = "dfuMANIFEST-SYNC"; + break; + case STATE_DFU_MANIFEST: + message = "dfuMANIFEST"; + break; + case STATE_DFU_MANIFEST_WAIT_RESET: + message = "dfuMANIFEST-WAIT-RESET"; + break; + case STATE_DFU_UPLOAD_IDLE: + message = "dfuUPLOAD-IDLE"; + break; + case STATE_DFU_ERROR: + message = "dfuERROR"; + break; + default: + message = NULL; + break; + } + + return message; +} + +/* Chapter 6.1.2 */ +static const char *dfu_status_names[] = { + /* DFU_STATUS_OK */ + "No error condition is present", + /* DFU_STATUS_errTARGET */ + "File is not targeted for use by this device", + /* DFU_STATUS_errFILE */ + "File is for this device but fails some vendor-specific test", + /* DFU_STATUS_errWRITE */ + "Device is unable to write memory", + /* DFU_STATUS_errERASE */ + "Memory erase function failed", + /* DFU_STATUS_errCHECK_ERASED */ + "Memory erase check failed", + /* DFU_STATUS_errPROG */ + "Program memory function failed", + /* DFU_STATUS_errVERIFY */ + "Programmed memory failed verification", + /* DFU_STATUS_errADDRESS */ + "Cannot program memory due to received address that is out of range", + /* DFU_STATUS_errNOTDONE */ + "Received DFU_DNLOAD with wLength = 0, but device does not think that it has all data yet", + /* DFU_STATUS_errFIRMWARE */ + "Device's firmware is corrupt. It cannot return to run-time (non-DFU) operations", + /* DFU_STATUS_errVENDOR */ + "iString indicates a vendor specific error", + /* DFU_STATUS_errUSBR */ + "Device detected unexpected USB reset signalling", + /* DFU_STATUS_errPOR */ + "Device detected unexpected power on reset", + /* DFU_STATUS_errUNKNOWN */ + "Something went wrong, but the device does not know what it was", + /* DFU_STATUS_errSTALLEDPKT */ + "Device stalled an unexpected request" +}; + + +const char *dfu_status_to_string(int status) +{ + if (status > DFU_STATUS_errSTALLEDPKT) + return "INVALID"; + return dfu_status_names[status]; +} + +int dfu_abort_to_idle(struct dfu_if *dif) +{ + int ret; + struct dfu_status dst; + + ret = dfu_abort(dif->dev_handle, dif->interface); + if (ret < 0) { + errx(EX_IOERR, "Error sending dfu abort request"); + exit(1); + } + ret = dfu_get_status(dif, &dst); + if (ret < 0) { + errx(EX_IOERR, "Error during abort get_status"); + exit(1); + } + if (dst.bState != DFU_STATE_dfuIDLE) { + errx(EX_IOERR, "Failed to enter idle state on abort"); + exit(1); + } + milli_sleep(dst.bwPollTimeout); + return ret; +} diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfu.h b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfu.h new file mode 100644 index 0000000..8e3caeb --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfu.h @@ -0,0 +1,133 @@ +/* + * dfu-programmer + * + * $Id: dfu.h,v 1.2 2005/09/25 01:27:42 schmidtw Exp $ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DFU_H +#define DFU_H + +#include +#include "usb_dfu.h" + +/* DFU states */ +#define STATE_APP_IDLE 0x00 +#define STATE_APP_DETACH 0x01 +#define STATE_DFU_IDLE 0x02 +#define STATE_DFU_DOWNLOAD_SYNC 0x03 +#define STATE_DFU_DOWNLOAD_BUSY 0x04 +#define STATE_DFU_DOWNLOAD_IDLE 0x05 +#define STATE_DFU_MANIFEST_SYNC 0x06 +#define STATE_DFU_MANIFEST 0x07 +#define STATE_DFU_MANIFEST_WAIT_RESET 0x08 +#define STATE_DFU_UPLOAD_IDLE 0x09 +#define STATE_DFU_ERROR 0x0a + + +/* DFU status */ +#define DFU_STATUS_OK 0x00 +#define DFU_STATUS_ERROR_TARGET 0x01 +#define DFU_STATUS_ERROR_FILE 0x02 +#define DFU_STATUS_ERROR_WRITE 0x03 +#define DFU_STATUS_ERROR_ERASE 0x04 +#define DFU_STATUS_ERROR_CHECK_ERASED 0x05 +#define DFU_STATUS_ERROR_PROG 0x06 +#define DFU_STATUS_ERROR_VERIFY 0x07 +#define DFU_STATUS_ERROR_ADDRESS 0x08 +#define DFU_STATUS_ERROR_NOTDONE 0x09 +#define DFU_STATUS_ERROR_FIRMWARE 0x0a +#define DFU_STATUS_ERROR_VENDOR 0x0b +#define DFU_STATUS_ERROR_USBR 0x0c +#define DFU_STATUS_ERROR_POR 0x0d +#define DFU_STATUS_ERROR_UNKNOWN 0x0e +#define DFU_STATUS_ERROR_STALLEDPKT 0x0f + +/* DFU commands */ +#define DFU_DETACH 0 +#define DFU_DNLOAD 1 +#define DFU_UPLOAD 2 +#define DFU_GETSTATUS 3 +#define DFU_CLRSTATUS 4 +#define DFU_GETSTATE 5 +#define DFU_ABORT 6 + +/* DFU interface */ +#define DFU_IFF_DFU 0x0001 /* DFU Mode, (not Runtime) */ + +/* This is based off of DFU_GETSTATUS + * + * 1 unsigned byte bStatus + * 3 unsigned byte bwPollTimeout + * 1 unsigned byte bState + * 1 unsigned byte iString +*/ + +struct dfu_status { + unsigned char bStatus; + unsigned int bwPollTimeout; + unsigned char bState; + unsigned char iString; +}; + +struct dfu_if { + struct usb_dfu_func_descriptor func_dfu; + uint16_t quirks; + uint16_t busnum; + uint16_t devnum; + uint16_t vendor; + uint16_t product; + uint16_t bcdDevice; + uint8_t configuration; + uint8_t interface; + uint8_t altsetting; + uint8_t flags; + uint8_t bMaxPacketSize0; + char *alt_name; + char *serial_name; + libusb_device *dev; + libusb_device_handle *dev_handle; + struct dfu_if *next; +}; + +int dfu_detach( libusb_device_handle *device, + const unsigned short interface, + const unsigned short timeout ); +int dfu_download( libusb_device_handle *device, + const unsigned short interface, + const unsigned short length, + const unsigned short transaction, + unsigned char* data ); +int dfu_upload( libusb_device_handle *device, + const unsigned short interface, + const unsigned short length, + const unsigned short transaction, + unsigned char* data ); +int dfu_get_status( struct dfu_if *dif, + struct dfu_status *status ); +int dfu_clear_status( libusb_device_handle *device, + const unsigned short interface ); +int dfu_get_state( libusb_device_handle *device, + const unsigned short interface ); +int dfu_abort( libusb_device_handle *device, + const unsigned short interface ); +int dfu_abort_to_idle( struct dfu_if *dif); + +const char *dfu_state_to_string( int state ); + +const char *dfu_status_to_string( int status ); + +#endif /* DFU_H */ diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfu_file.c b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfu_file.c new file mode 100644 index 0000000..7c897d4 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfu_file.c @@ -0,0 +1,444 @@ +/* + * Load or store DFU files including suffix and prefix + * + * Copyright 2014 Tormod Volden + * Copyright 2012 Stefan Schmidt + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "portable.h" +#include "dfu_file.h" + +#define DFU_SUFFIX_LENGTH 16 +#define LMDFU_PREFIX_LENGTH 8 +#define LPCDFU_PREFIX_LENGTH 16 +#define PROGRESS_BAR_WIDTH 25 +#define STDIN_CHUNK_SIZE 65536 + +static const unsigned long crc32_table[] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d}; + +static uint32_t crc32_byte(uint32_t accum, uint8_t delta) +{ + return crc32_table[(accum ^ delta) & 0xff] ^ (accum >> 8); +} + +static int probe_prefix(struct dfu_file *file) +{ + uint8_t *prefix = file->firmware; + + if (file->size.total < LMDFU_PREFIX_LENGTH) + return 1; + if ((prefix[0] == 0x01) && (prefix[1] == 0x00)) { + file->prefix_type = LMDFU_PREFIX; + file->size.prefix = LMDFU_PREFIX_LENGTH; + file->lmdfu_address = 1024 * ((prefix[3] << 8) | prefix[2]); + } + else if (((prefix[0] & 0x3f) == 0x1a) && ((prefix[1] & 0x3f)== 0x3f)) { + file->prefix_type = LPCDFU_UNENCRYPTED_PREFIX; + file->size.prefix = LPCDFU_PREFIX_LENGTH; + } + + if (file->size.prefix + file->size.suffix > file->size.total) + return 1; + return 0; +} + +void dfu_progress_bar(const char *desc, unsigned long long curr, + unsigned long long max) +{ + static char buf[PROGRESS_BAR_WIDTH + 1]; + static unsigned long long last_progress = -1; + static time_t last_time; + time_t curr_time = time(NULL); + unsigned long long progress; + unsigned long long x; + + /* check for not known maximum */ + if (max < curr) + max = curr + 1; + /* make none out of none give zero */ + if (max == 0 && curr == 0) + max = 1; + + /* compute completion */ + progress = (PROGRESS_BAR_WIDTH * curr) / max; + if (progress > PROGRESS_BAR_WIDTH) + progress = PROGRESS_BAR_WIDTH; + if (progress == last_progress && + curr_time == last_time) + return; + last_progress = progress; + last_time = curr_time; + + for (x = 0; x != PROGRESS_BAR_WIDTH; x++) { + if (x < progress) + buf[x] = '='; + else + buf[x] = ' '; + } + buf[x] = 0; + + printf("\r%s\t[%s] %3lld%% %12lld bytes", desc, buf, + (100ULL * curr) / max, curr); + + if (progress == PROGRESS_BAR_WIDTH) + printf("\n%s done.\n", desc); +} + +void *dfu_malloc(size_t size) +{ + void *ptr = malloc(size); + if (ptr == NULL) + errx(EX_SOFTWARE, "Cannot allocate memory of size %d bytes", (int)size); + return (ptr); +} + +uint32_t dfu_file_write_crc(int f, uint32_t crc, const void *buf, int size) +{ + int x; + + /* compute CRC */ + for (x = 0; x != size; x++) + crc = crc32_byte(crc, ((uint8_t *)buf)[x]); + + /* write data */ + if (write(f, buf, size) != size) + err(EX_IOERR, "Could not write %d bytes to file %d", size, f); + + return (crc); +} + +void dfu_load_file(struct dfu_file *file, enum suffix_req check_suffix, enum prefix_req check_prefix) +{ + off_t offset; + int f; + int i; + int res; + + file->size.prefix = 0; + file->size.suffix = 0; + + /* default values, if no valid suffix is found */ + file->bcdDFU = 0; + file->idVendor = 0xffff; /* wildcard value */ + file->idProduct = 0xffff; /* wildcard value */ + file->bcdDevice = 0xffff; /* wildcard value */ + + /* default values, if no valid prefix is found */ + file->lmdfu_address = 0; + + free(file->firmware); + + if (!strcmp(file->name, "-")) { + int read_bytes; + +#ifdef WIN32 + _setmode( _fileno( stdin ), _O_BINARY ); +#endif + file->firmware = (uint8_t*) dfu_malloc(STDIN_CHUNK_SIZE); + read_bytes = fread(file->firmware, 1, STDIN_CHUNK_SIZE, stdin); + file->size.total = read_bytes; + while (read_bytes == STDIN_CHUNK_SIZE) { + file->firmware = (uint8_t*) realloc(file->firmware, file->size.total + STDIN_CHUNK_SIZE); + if (!file->firmware) + err(EX_IOERR, "Could not allocate firmware buffer"); + read_bytes = fread(file->firmware + file->size.total, 1, STDIN_CHUNK_SIZE, stdin); + file->size.total += read_bytes; + } + if (verbose) + printf("Read %i bytes from stdin\n", file->size.total); + /* Never require suffix when reading from stdin */ + check_suffix = MAYBE_SUFFIX; + } else { + f = open(file->name, O_RDONLY | O_BINARY); + if (f < 0) + err(EX_IOERR, "Could not open file %s for reading", file->name); + + offset = lseek(f, 0, SEEK_END); + + if ((int)offset < 0 || (int)offset != offset) + err(EX_IOERR, "File size is too big"); + + if (lseek(f, 0, SEEK_SET) != 0) + err(EX_IOERR, "Could not seek to beginning"); + + file->size.total = offset; + file->firmware = dfu_malloc(file->size.total); + + if (read(f, file->firmware, file->size.total) != file->size.total) { + err(EX_IOERR, "Could not read %d bytes from %s", + file->size.total, file->name); + } + close(f); + } + + /* Check for possible DFU file suffix by trying to parse one */ + { + uint32_t crc = 0xffffffff; + const uint8_t *dfusuffix; + int missing_suffix = 0; + const char *reason; + + if (file->size.total < DFU_SUFFIX_LENGTH) { + reason = "File too short for DFU suffix"; + missing_suffix = 1; + goto checked; + } + + dfusuffix = file->firmware + file->size.total - + DFU_SUFFIX_LENGTH; + + for (i = 0; i < file->size.total - 4; i++) + crc = crc32_byte(crc, file->firmware[i]); + + if (dfusuffix[10] != 'D' || + dfusuffix[9] != 'F' || + dfusuffix[8] != 'U') { + reason = "Invalid DFU suffix signature"; + missing_suffix = 1; + goto checked; + } + + file->dwCRC = (dfusuffix[15] << 24) + + (dfusuffix[14] << 16) + + (dfusuffix[13] << 8) + + dfusuffix[12]; + + if (file->dwCRC != crc) { + reason = "DFU suffix CRC does not match"; + missing_suffix = 1; + goto checked; + } + + /* At this point we believe we have a DFU suffix + so we require further checks to succeed */ + + file->bcdDFU = (dfusuffix[7] << 8) + dfusuffix[6]; + + if (verbose) + printf("DFU suffix version %x\n", file->bcdDFU); + + file->size.suffix = dfusuffix[11]; + + if (file->size.suffix < DFU_SUFFIX_LENGTH) { + errx(EX_IOERR, "Unsupported DFU suffix length %d", + file->size.suffix); + } + + if (file->size.suffix > file->size.total) { + errx(EX_IOERR, "Invalid DFU suffix length %d", + file->size.suffix); + } + + file->idVendor = (dfusuffix[5] << 8) + dfusuffix[4]; + file->idProduct = (dfusuffix[3] << 8) + dfusuffix[2]; + file->bcdDevice = (dfusuffix[1] << 8) + dfusuffix[0]; + +checked: + if (missing_suffix) { + if (check_suffix == NEEDS_SUFFIX) { + warnx("%s", reason); + errx(EX_IOERR, "Valid DFU suffix needed"); + } else if (check_suffix == MAYBE_SUFFIX) { + warnx("%s", reason); + warnx("A valid DFU suffix will be required in " + "a future dfu-util release!!!"); + } + } else { + if (check_suffix == NO_SUFFIX) { + errx(EX_SOFTWARE, "Please remove existing DFU suffix before adding a new one.\n"); + } + } + } + res = probe_prefix(file); + if ((res || file->size.prefix == 0) && check_prefix == NEEDS_PREFIX) + errx(EX_IOERR, "Valid DFU prefix needed"); + if (file->size.prefix && check_prefix == NO_PREFIX) + errx(EX_IOERR, "A prefix already exists, please delete it first"); + if (file->size.prefix && verbose) { + uint8_t *data = file->firmware; + if (file->prefix_type == LMDFU_PREFIX) + printf("Possible TI Stellaris DFU prefix with " + "the following properties\n" + "Address: 0x%08x\n" + "Payload length: %d\n", + file->lmdfu_address, + data[4] | (data[5] << 8) | + (data[6] << 16) | (data[7] << 14)); + else if (file->prefix_type == LPCDFU_UNENCRYPTED_PREFIX) + printf("Possible unencrypted NXP LPC DFU prefix with " + "the following properties\n" + "Payload length: %d kiByte\n", + data[2] >>1 | (data[3] << 7) ); + else + errx(EX_IOERR, "Unknown DFU prefix type"); + } +} + +void dfu_store_file(struct dfu_file *file, int write_suffix, int write_prefix) +{ + uint32_t crc = 0xffffffff; + int f; + + f = open(file->name, O_WRONLY | O_BINARY | O_TRUNC | O_CREAT, 0666); + if (f < 0) + err(EX_IOERR, "Could not open file %s for writing", file->name); + + /* write prefix, if any */ + if (write_prefix) { + if (file->prefix_type == LMDFU_PREFIX) { + uint8_t lmdfu_prefix[LMDFU_PREFIX_LENGTH]; + uint32_t addr = file->lmdfu_address / 1024; + + /* lmdfu_dfu_prefix payload length excludes prefix and suffix */ + uint32_t len = file->size.total - + file->size.prefix - file->size.suffix; + + lmdfu_prefix[0] = 0x01; /* STELLARIS_DFU_PROG */ + lmdfu_prefix[1] = 0x00; /* Reserved */ + lmdfu_prefix[2] = (uint8_t)(addr & 0xff); + lmdfu_prefix[3] = (uint8_t)(addr >> 8); + lmdfu_prefix[4] = (uint8_t)(len & 0xff); + lmdfu_prefix[5] = (uint8_t)(len >> 8) & 0xff; + lmdfu_prefix[6] = (uint8_t)(len >> 16) & 0xff; + lmdfu_prefix[7] = (uint8_t)(len >> 24); + + crc = dfu_file_write_crc(f, crc, lmdfu_prefix, LMDFU_PREFIX_LENGTH); + } + if (file->prefix_type == LPCDFU_UNENCRYPTED_PREFIX) { + uint8_t lpcdfu_prefix[LPCDFU_PREFIX_LENGTH] = {0}; + int i; + + /* Payload is firmware and prefix rounded to 512 bytes */ + uint32_t len = (file->size.total - file->size.suffix + 511) /512; + + lpcdfu_prefix[0] = 0x1a; /* Unencypted*/ + lpcdfu_prefix[1] = 0x3f; /* Reserved */ + lpcdfu_prefix[2] = (uint8_t)(len & 0xff); + lpcdfu_prefix[3] = (uint8_t)((len >> 8) & 0xff); + for (i = 12; i < LPCDFU_PREFIX_LENGTH; i++) + lpcdfu_prefix[i] = 0xff; + + crc = dfu_file_write_crc(f, crc, lpcdfu_prefix, LPCDFU_PREFIX_LENGTH); + } + } + /* write firmware binary */ + crc = dfu_file_write_crc(f, crc, file->firmware + file->size.prefix, + file->size.total - file->size.prefix - file->size.suffix); + + /* write suffix, if any */ + if (write_suffix) { + uint8_t dfusuffix[DFU_SUFFIX_LENGTH]; + + dfusuffix[0] = file->bcdDevice & 0xff; + dfusuffix[1] = file->bcdDevice >> 8; + dfusuffix[2] = file->idProduct & 0xff; + dfusuffix[3] = file->idProduct >> 8; + dfusuffix[4] = file->idVendor & 0xff; + dfusuffix[5] = file->idVendor >> 8; + dfusuffix[6] = file->bcdDFU & 0xff; + dfusuffix[7] = file->bcdDFU >> 8; + dfusuffix[8] = 'U'; + dfusuffix[9] = 'F'; + dfusuffix[10] = 'D'; + dfusuffix[11] = DFU_SUFFIX_LENGTH; + + crc = dfu_file_write_crc(f, crc, dfusuffix, + DFU_SUFFIX_LENGTH - 4); + + dfusuffix[12] = crc; + dfusuffix[13] = crc >> 8; + dfusuffix[14] = crc >> 16; + dfusuffix[15] = crc >> 24; + + crc = dfu_file_write_crc(f, crc, dfusuffix + 12, 4); + } + close(f); +} + +void show_suffix_and_prefix(struct dfu_file *file) +{ + if (file->size.prefix == LMDFU_PREFIX_LENGTH) { + printf("The file %s contains a TI Stellaris DFU prefix with the following properties:\n", file->name); + printf("Address:\t0x%08x\n", file->lmdfu_address); + } else if (file->size.prefix == LPCDFU_PREFIX_LENGTH) { + uint8_t * prefix = file->firmware; + printf("The file %s contains a NXP unencrypted LPC DFU prefix with the following properties:\n", file->name); + printf("Size:\t%5d kiB\n", prefix[2]>>1|prefix[3]<<7); + } else if (file->size.prefix != 0) { + printf("The file %s contains an unknown prefix\n", file->name); + } + if (file->size.suffix > 0) { + printf("The file %s contains a DFU suffix with the following properties:\n", file->name); + printf("BCD device:\t0x%04X\n", file->bcdDevice); + printf("Product ID:\t0x%04X\n",file->idProduct); + printf("Vendor ID:\t0x%04X\n", file->idVendor); + printf("BCD DFU:\t0x%04X\n", file->bcdDFU); + printf("Length:\t\t%i\n", file->size.suffix); + printf("CRC:\t\t0x%08X\n", file->dwCRC); + } +} diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfu_file.h b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfu_file.h new file mode 100644 index 0000000..abebd44 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfu_file.h @@ -0,0 +1,60 @@ + +#ifndef DFU_FILE_H +#define DFU_FILE_H + +#include + +struct dfu_file { + /* File name */ + const char *name; + /* Pointer to file loaded into memory */ + uint8_t *firmware; + /* Different sizes */ + struct { + int total; + int prefix; + int suffix; + } size; + /* From prefix fields */ + uint32_t lmdfu_address; + /* From prefix fields */ + uint32_t prefix_type; + + /* From DFU suffix fields */ + uint32_t dwCRC; + uint16_t bcdDFU; + uint16_t idVendor; + uint16_t idProduct; + uint16_t bcdDevice; +}; + +enum suffix_req { + NO_SUFFIX, + NEEDS_SUFFIX, + MAYBE_SUFFIX +}; + +enum prefix_req { + NO_PREFIX, + NEEDS_PREFIX, + MAYBE_PREFIX +}; + +enum prefix_type { + ZERO_PREFIX, + LMDFU_PREFIX, + LPCDFU_UNENCRYPTED_PREFIX +}; + +extern int verbose; + +void dfu_load_file(struct dfu_file *file, enum suffix_req check_suffix, enum prefix_req check_prefix); +void dfu_store_file(struct dfu_file *file, int write_suffix, int write_prefix); + +void dfu_progress_bar(const char *desc, unsigned long long curr, + unsigned long long max); +void *dfu_malloc(size_t size); +uint32_t dfu_file_write_crc(int f, uint32_t crc, const void *buf, int size); +void show_suffix_and_prefix(struct dfu_file *file); + +#endif /* DFU_FILE_H */ diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfu_load.c b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfu_load.c new file mode 100644 index 0000000..64f7009 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfu_load.c @@ -0,0 +1,196 @@ +/* + * DFU transfer routines + * + * This is supposed to be a general DFU implementation, as specified in the + * USB DFU 1.0 and 1.1 specification. + * + * The code was originally intended to interface with a USB device running the + * "sam7dfu" firmware (see http://www.openpcd.org/) on an AT91SAM7 processor. + * + * Copyright 2007-2008 Harald Welte + * Copyright 2013 Hans Petter Selasky + * Copyright 2014 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include + +#include "portable.h" +#include "dfu.h" +#include "usb_dfu.h" +#include "dfu_file.h" +#include "dfu_load.h" +#include "quirks.h" + +int dfuload_do_upload(struct dfu_if *dif, int xfer_size, + int expected_size, int fd) +{ + int total_bytes = 0; + unsigned short transaction = 0; + unsigned char *buf; + int ret; + + buf = dfu_malloc(xfer_size); + + printf("Copying data from DFU device to PC\n"); + dfu_progress_bar("Upload", 0, 1); + + while (1) { + int rc; + rc = dfu_upload(dif->dev_handle, dif->interface, + xfer_size, transaction++, buf); + if (rc < 0) { + warnx("Error during upload"); + ret = rc; + goto out_free; + } + + dfu_file_write_crc(fd, 0, buf, rc); + total_bytes += rc; + + if (total_bytes < 0) + errx(EX_SOFTWARE, "Received too many bytes (wraparound)"); + + if (rc < xfer_size) { + /* last block, return */ + ret = total_bytes; + break; + } + dfu_progress_bar("Upload", total_bytes, expected_size); + } + ret = 0; + +out_free: + dfu_progress_bar("Upload", total_bytes, total_bytes); + if (total_bytes == 0) + printf("\nFailed.\n"); + free(buf); + if (verbose) + printf("Received a total of %i bytes\n", total_bytes); + if (expected_size != 0 && total_bytes != expected_size) + errx(EX_SOFTWARE, "Unexpected number of bytes uploaded from device"); + return ret; +} + +int dfuload_do_dnload(struct dfu_if *dif, int xfer_size, struct dfu_file *file) +{ + int bytes_sent; + int expected_size; + unsigned char *buf; + unsigned short transaction = 0; + struct dfu_status dst; + int ret; + + printf("Copying data from PC to DFU device\n"); + + buf = file->firmware; + expected_size = file->size.total - file->size.suffix; + bytes_sent = 0; + + dfu_progress_bar("Download", 0, 1); + while (bytes_sent < expected_size) { + int bytes_left; + int chunk_size; + + bytes_left = expected_size - bytes_sent; + if (bytes_left < xfer_size) + chunk_size = bytes_left; + else + chunk_size = xfer_size; + + ret = dfu_download(dif->dev_handle, dif->interface, + chunk_size, transaction++, chunk_size ? buf : NULL); + if (ret < 0) { + warnx("Error during download"); + goto out; + } + bytes_sent += chunk_size; + buf += chunk_size; + + do { + ret = dfu_get_status(dif, &dst); + if (ret < 0) { + errx(EX_IOERR, "Error during download get_status"); + goto out; + } + + if (dst.bState == DFU_STATE_dfuDNLOAD_IDLE || + dst.bState == DFU_STATE_dfuERROR) + break; + + /* Wait while device executes flashing */ + milli_sleep(dst.bwPollTimeout); + + } while (1); + if (dst.bStatus != DFU_STATUS_OK) { + printf(" failed!\n"); + printf("state(%u) = %s, status(%u) = %s\n", dst.bState, + dfu_state_to_string(dst.bState), dst.bStatus, + dfu_status_to_string(dst.bStatus)); + ret = -1; + goto out; + } + dfu_progress_bar("Download", bytes_sent, bytes_sent + bytes_left); + } + + /* send one zero sized download request to signalize end */ + ret = dfu_download(dif->dev_handle, dif->interface, + 0, transaction, NULL); + if (ret < 0) { + errx(EX_IOERR, "Error sending completion packet"); + goto out; + } + + dfu_progress_bar("Download", bytes_sent, bytes_sent); + + if (verbose) + printf("Sent a total of %i bytes\n", bytes_sent); + +get_status: + /* Transition to MANIFEST_SYNC state */ + ret = dfu_get_status(dif, &dst); + if (ret < 0) { + warnx("unable to read DFU status after completion"); + goto out; + } + printf("state(%u) = %s, status(%u) = %s\n", dst.bState, + dfu_state_to_string(dst.bState), dst.bStatus, + dfu_status_to_string(dst.bStatus)); + + milli_sleep(dst.bwPollTimeout); + + /* FIXME: deal correctly with ManifestationTolerant=0 / WillDetach bits */ + switch (dst.bState) { + case DFU_STATE_dfuMANIFEST_SYNC: + case DFU_STATE_dfuMANIFEST: + /* some devices (e.g. TAS1020b) need some time before we + * can obtain the status */ + milli_sleep(1000); + goto get_status; + break; + case DFU_STATE_dfuIDLE: + break; + } + printf("Done!\n"); + +out: + return bytes_sent; +} diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfu_load.h b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfu_load.h new file mode 100644 index 0000000..be23e9b --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfu_load.h @@ -0,0 +1,7 @@ +#ifndef DFU_LOAD_H +#define DFU_LOAD_H + +int dfuload_do_upload(struct dfu_if *dif, int xfer_size, int expected_size, int fd); +int dfuload_do_dnload(struct dfu_if *dif, int xfer_size, struct dfu_file *file); + +#endif /* DFU_LOAD_H */ diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfu_util.c b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfu_util.c new file mode 100644 index 0000000..b94c7cc --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfu_util.c @@ -0,0 +1,346 @@ +/* + * Functions for detecting DFU USB entities + * + * Written by Harald Welte + * Copyright 2007-2008 by OpenMoko, Inc. + * Copyright 2013 Hans Petter Selasky + * + * Based on existing code of dfu-programmer-0.4 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include "portable.h" +#include "dfu.h" +#include "usb_dfu.h" +#include "dfu_file.h" +#include "dfu_load.h" +#include "dfu_util.h" +#include "dfuse.h" +#include "quirks.h" + +#ifdef HAVE_USBPATH_H +#include +#endif + +/* + * Look for a descriptor in a concatenated descriptor list. Will + * return upon the first match of the given descriptor type. Returns length of + * found descriptor, limited to res_size + */ +static int find_descriptor(const uint8_t *desc_list, int list_len, + uint8_t desc_type, void *res_buf, int res_size) +{ + int p = 0; + + if (list_len < 2) + return (-1); + + while (p + 1 < list_len) { + int desclen; + + desclen = (int) desc_list[p]; + if (desclen == 0) { + warnx("Invalid descriptor list"); + return -1; + } + if (desc_list[p + 1] == desc_type) { + if (desclen > res_size) + desclen = res_size; + if (p + desclen > list_len) + desclen = list_len - p; + memcpy(res_buf, &desc_list[p], desclen); + return desclen; + } + p += (int) desc_list[p]; + } + return -1; +} + +static void probe_configuration(libusb_device *dev, struct libusb_device_descriptor *desc) +{ + struct usb_dfu_func_descriptor func_dfu; + libusb_device_handle *devh; + struct dfu_if *pdfu; + struct libusb_config_descriptor *cfg; + const struct libusb_interface_descriptor *intf; + const struct libusb_interface *uif; + char alt_name[MAX_DESC_STR_LEN + 1]; + char serial_name[MAX_DESC_STR_LEN + 1]; + int cfg_idx; + int intf_idx; + int alt_idx; + int ret; + int has_dfu; + + for (cfg_idx = 0; cfg_idx != desc->bNumConfigurations; cfg_idx++) { + memset(&func_dfu, 0, sizeof(func_dfu)); + has_dfu = 0; + + ret = libusb_get_config_descriptor(dev, cfg_idx, &cfg); + if (ret != 0) + return; + if (match_config_index > -1 && match_config_index != cfg->bConfigurationValue) { + libusb_free_config_descriptor(cfg); + continue; + } + + /* + * In some cases, noticably FreeBSD if uid != 0, + * the configuration descriptors are empty + */ + if (!cfg) + return; + + ret = find_descriptor(cfg->extra, cfg->extra_length, + USB_DT_DFU, &func_dfu, sizeof(func_dfu)); + if (ret > -1) + goto found_dfu; + + for (intf_idx = 0; intf_idx < cfg->bNumInterfaces; + intf_idx++) { + uif = &cfg->interface[intf_idx]; + if (!uif) + break; + + for (alt_idx = 0; alt_idx < cfg->interface[intf_idx].num_altsetting; + alt_idx++) { + intf = &uif->altsetting[alt_idx]; + + ret = find_descriptor(intf->extra, intf->extra_length, USB_DT_DFU, + &func_dfu, sizeof(func_dfu)); + if (ret > -1) + goto found_dfu; + + if (intf->bInterfaceClass != 0xfe || + intf->bInterfaceSubClass != 1) + continue; + + has_dfu = 1; + } + } + if (has_dfu) { + /* + * Finally try to retrieve it requesting the + * device directly This is not supported on + * all devices for non-standard types + */ + if (libusb_open(dev, &devh) == 0) { + ret = libusb_get_descriptor(devh, USB_DT_DFU, 0, + (void *)&func_dfu, sizeof(func_dfu)); + libusb_close(devh); + if (ret > -1) + goto found_dfu; + } + warnx("Device has DFU interface, " + "but has no DFU functional descriptor"); + + /* fake version 1.0 */ + func_dfu.bLength = 7; + func_dfu.bcdDFUVersion = libusb_cpu_to_le16(0x0100); + goto found_dfu; + } + libusb_free_config_descriptor(cfg); + continue; + +found_dfu: + if (func_dfu.bLength == 7) { + printf("Deducing device DFU version from functional descriptor " + "length\n"); + func_dfu.bcdDFUVersion = libusb_cpu_to_le16(0x0100); + } else if (func_dfu.bLength < 9) { + printf("Error obtaining DFU functional descriptor\n"); + printf("Please report this as a bug!\n"); + printf("Warning: Assuming DFU version 1.0\n"); + func_dfu.bcdDFUVersion = libusb_cpu_to_le16(0x0100); + printf("Warning: Transfer size can not be detected\n"); + func_dfu.wTransferSize = 0; + } + + for (intf_idx = 0; intf_idx < cfg->bNumInterfaces; + intf_idx++) { + if (match_iface_index > -1 && match_iface_index != intf_idx) + continue; + + uif = &cfg->interface[intf_idx]; + if (!uif) + break; + + for (alt_idx = 0; + alt_idx < uif->num_altsetting; alt_idx++) { + int dfu_mode; + + intf = &uif->altsetting[alt_idx]; + + if (intf->bInterfaceClass != 0xfe || + intf->bInterfaceSubClass != 1) + continue; + + dfu_mode = (intf->bInterfaceProtocol == 2); + /* e.g. DSO Nano has bInterfaceProtocol 0 instead of 2 */ + if (func_dfu.bcdDFUVersion == 0x011a && intf->bInterfaceProtocol == 0) + dfu_mode = 1; + + if (dfu_mode && + match_iface_alt_index > -1 && match_iface_alt_index != alt_idx) + continue; + + if (dfu_mode) { + if ((match_vendor_dfu >= 0 && match_vendor_dfu != desc->idVendor) || + (match_product_dfu >= 0 && match_product_dfu != desc->idProduct)) { + continue; + } + } else { + if ((match_vendor >= 0 && match_vendor != desc->idVendor) || + (match_product >= 0 && match_product != desc->idProduct)) { + continue; + } + } + + if (libusb_open(dev, &devh)) { + warnx("Cannot open DFU device %04x:%04x", desc->idVendor, desc->idProduct); + break; + } + if (intf->iInterface != 0) + ret = libusb_get_string_descriptor_ascii(devh, + intf->iInterface, (void *)alt_name, MAX_DESC_STR_LEN); + else + ret = -1; + if (ret < 1) + strcpy(alt_name, "UNKNOWN"); + if (desc->iSerialNumber != 0) + ret = libusb_get_string_descriptor_ascii(devh, + desc->iSerialNumber, (void *)serial_name, MAX_DESC_STR_LEN); + else + ret = -1; + if (ret < 1) + strcpy(serial_name, "UNKNOWN"); + libusb_close(devh); + + if (dfu_mode && + match_iface_alt_name != NULL && strcmp(alt_name, match_iface_alt_name)) + continue; + + if (dfu_mode) { + if (match_serial_dfu != NULL && strcmp(match_serial_dfu, serial_name)) + continue; + } else { + if (match_serial != NULL && strcmp(match_serial, serial_name)) + continue; + } + + pdfu = dfu_malloc(sizeof(*pdfu)); + + memset(pdfu, 0, sizeof(*pdfu)); + + pdfu->func_dfu = func_dfu; + pdfu->dev = libusb_ref_device(dev); + pdfu->quirks = get_quirks(desc->idVendor, + desc->idProduct, desc->bcdDevice); + pdfu->vendor = desc->idVendor; + pdfu->product = desc->idProduct; + pdfu->bcdDevice = desc->bcdDevice; + pdfu->configuration = cfg->bConfigurationValue; + pdfu->interface = intf->bInterfaceNumber; + pdfu->altsetting = intf->bAlternateSetting; + pdfu->devnum = libusb_get_device_address(dev); + pdfu->busnum = libusb_get_bus_number(dev); + pdfu->alt_name = strdup(alt_name); + if (pdfu->alt_name == NULL) + errx(EX_SOFTWARE, "Out of memory"); + pdfu->serial_name = strdup(serial_name); + if (pdfu->serial_name == NULL) + errx(EX_SOFTWARE, "Out of memory"); + if (dfu_mode) + pdfu->flags |= DFU_IFF_DFU; + if (pdfu->quirks & QUIRK_FORCE_DFU11) { + pdfu->func_dfu.bcdDFUVersion = + libusb_cpu_to_le16(0x0110); + } + pdfu->bMaxPacketSize0 = desc->bMaxPacketSize0; + + /* queue into list */ + pdfu->next = dfu_root; + dfu_root = pdfu; + } + } + libusb_free_config_descriptor(cfg); + } +} + +void probe_devices(libusb_context *ctx) +{ + libusb_device **list; + ssize_t num_devs; + ssize_t i; + + num_devs = libusb_get_device_list(ctx, &list); + for (i = 0; i < num_devs; ++i) { + struct libusb_device_descriptor desc; + struct libusb_device *dev = list[i]; + + if (match_bus > -1 && match_bus != libusb_get_bus_number(dev)) + continue; + if (match_device > -1 && match_device != libusb_get_device_address(dev)) + continue; + if (libusb_get_device_descriptor(dev, &desc)) + continue; + probe_configuration(dev, &desc); + } + libusb_free_device_list(list, 0); +} + +void disconnect_devices(void) +{ + struct dfu_if *pdfu; + struct dfu_if *prev = NULL; + + for (pdfu = dfu_root; pdfu != NULL; pdfu = pdfu->next) { + free(prev); + libusb_unref_device(pdfu->dev); + free(pdfu->alt_name); + free(pdfu->serial_name); + prev = pdfu; + } + free(prev); + dfu_root = NULL; +} + +void print_dfu_if(struct dfu_if *dfu_if) +{ + printf("Found %s: [%04x:%04x] ver=%04x, devnum=%u, cfg=%u, intf=%u, " + "alt=%u, name=\"%s\", serial=\"%s\"\n", + dfu_if->flags & DFU_IFF_DFU ? "DFU" : "Runtime", + dfu_if->vendor, dfu_if->product, + dfu_if->bcdDevice, dfu_if->devnum, + dfu_if->configuration, dfu_if->interface, + dfu_if->altsetting, dfu_if->alt_name, + dfu_if->serial_name); +} + +/* Walk the device tree and print out DFU devices */ +void list_dfu_interfaces(void) +{ + struct dfu_if *pdfu; + + for (pdfu = dfu_root; pdfu != NULL; pdfu = pdfu->next) + print_dfu_if(pdfu); +} diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfu_util.h b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfu_util.h new file mode 100644 index 0000000..fc0c19d --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfu_util.h @@ -0,0 +1,36 @@ +#ifndef DFU_UTIL_H +#define DFU_UTIL_H + +/* USB string descriptor should contain max 126 UTF-16 characters + * but 253 would even accomodate any UTF-8 encoding */ +#define MAX_DESC_STR_LEN 253 + +enum mode { + MODE_NONE, + MODE_VERSION, + MODE_LIST, + MODE_DETACH, + MODE_UPLOAD, + MODE_DOWNLOAD +}; + +extern struct dfu_if *dfu_root; +extern int match_bus; +extern int match_device; +extern int match_vendor; +extern int match_product; +extern int match_vendor_dfu; +extern int match_product_dfu; +extern int match_config_index; +extern int match_iface_index; +extern int match_iface_alt_index; +extern const char *match_iface_alt_name; +extern const char *match_serial; +extern const char *match_serial_dfu; + +void probe_devices(libusb_context *); +void disconnect_devices(void); +void print_dfu_if(struct dfu_if *); +void list_dfu_interfaces(void); + +#endif /* DFU_UTIL_H */ diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfuse.c b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfuse.c new file mode 100644 index 0000000..fce29fe --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfuse.c @@ -0,0 +1,652 @@ +/* + * DfuSe specific functions + * + * This implements the ST Microsystems DFU extensions (DfuSe) + * as per the DfuSe 1.1a specification (ST documents AN3156, AN2606) + * The DfuSe file format is described in ST document UM0391. + * + * Copyright 2010-2014 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "portable.h" +#include "dfu.h" +#include "usb_dfu.h" +#include "dfu_file.h" +#include "dfuse.h" +#include "dfuse_mem.h" + +#define DFU_TIMEOUT 5000 + +extern int verbose; +static unsigned int last_erased_page = 1; /* non-aligned value, won't match */ +static struct memsegment *mem_layout; +static unsigned int dfuse_address = 0; +static unsigned int dfuse_length = 0; +static int dfuse_force = 0; +static int dfuse_leave = 0; +static int dfuse_unprotect = 0; +static int dfuse_mass_erase = 0; + +unsigned int quad2uint(unsigned char *p) +{ + return (*p + (*(p + 1) << 8) + (*(p + 2) << 16) + (*(p + 3) << 24)); +} + +void dfuse_parse_options(const char *options) +{ + char *end; + const char *endword; + unsigned int number; + + /* address, possibly empty, must be first */ + if (*options != ':') { + endword = strchr(options, ':'); + if (!endword) + endword = options + strlen(options); /* GNU strchrnul */ + + number = strtoul(options, &end, 0); + if (end == endword) { + dfuse_address = number; + } else { + errx(EX_IOERR, "Invalid dfuse address: %s", options); + } + options = endword; + } + + while (*options) { + if (*options == ':') { + options++; + continue; + } + endword = strchr(options, ':'); + if (!endword) + endword = options + strlen(options); + + if (!strncmp(options, "force", endword - options)) { + dfuse_force++; + options += 5; + continue; + } + if (!strncmp(options, "leave", endword - options)) { + dfuse_leave = 1; + options += 5; + continue; + } + if (!strncmp(options, "unprotect", endword - options)) { + dfuse_unprotect = 1; + options += 9; + continue; + } + if (!strncmp(options, "mass-erase", endword - options)) { + dfuse_mass_erase = 1; + options += 10; + continue; + } + + /* any valid number is interpreted as upload length */ + number = strtoul(options, &end, 0); + if (end == endword) { + dfuse_length = number; + } else { + errx(EX_IOERR, "Invalid dfuse modifier: %s", options); + } + options = endword; + } +} + +/* DFU_UPLOAD request for DfuSe 1.1a */ +int dfuse_upload(struct dfu_if *dif, const unsigned short length, + unsigned char *data, unsigned short transaction) +{ + int status; + + status = libusb_control_transfer(dif->dev_handle, + /* bmRequestType */ LIBUSB_ENDPOINT_IN | + LIBUSB_REQUEST_TYPE_CLASS | + LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_UPLOAD, + /* wValue */ transaction, + /* wIndex */ dif->interface, + /* Data */ data, + /* wLength */ length, + DFU_TIMEOUT); + if (status < 0) { + errx(EX_IOERR, "%s: libusb_control_msg returned %d", + __FUNCTION__, status); + } + return status; +} + +/* DFU_DNLOAD request for DfuSe 1.1a */ +int dfuse_download(struct dfu_if *dif, const unsigned short length, + unsigned char *data, unsigned short transaction) +{ + int status; + + status = libusb_control_transfer(dif->dev_handle, + /* bmRequestType */ LIBUSB_ENDPOINT_OUT | + LIBUSB_REQUEST_TYPE_CLASS | + LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_DNLOAD, + /* wValue */ transaction, + /* wIndex */ dif->interface, + /* Data */ data, + /* wLength */ length, + DFU_TIMEOUT); + if (status < 0) { + errx(EX_IOERR, "%s: libusb_control_transfer returned %d", + __FUNCTION__, status); + } + return status; +} + +/* DfuSe only commands */ +/* Leaves the device in dfuDNLOAD-IDLE state */ +int dfuse_special_command(struct dfu_if *dif, unsigned int address, + enum dfuse_command command) +{ + const char* dfuse_command_name[] = { "SET_ADDRESS" , "ERASE_PAGE", + "MASS_ERASE", "READ_UNPROTECT"}; + unsigned char buf[5]; + int length; + int ret; + struct dfu_status dst; + int firstpoll = 1; + + if (command == ERASE_PAGE) { + struct memsegment *segment; + int page_size; + + segment = find_segment(mem_layout, address); + if (!segment || !(segment->memtype & DFUSE_ERASABLE)) { + errx(EX_IOERR, "Page at 0x%08x can not be erased", + address); + } + page_size = segment->pagesize; + if (verbose > 1) + printf("Erasing page size %i at address 0x%08x, page " + "starting at 0x%08x\n", page_size, address, + address & ~(page_size - 1)); + buf[0] = 0x41; /* Erase command */ + length = 5; + last_erased_page = address & ~(page_size - 1); + } else if (command == SET_ADDRESS) { + if (verbose > 2) + printf(" Setting address pointer to 0x%08x\n", + address); + buf[0] = 0x21; /* Set Address Pointer command */ + length = 5; + } else if (command == MASS_ERASE) { + buf[0] = 0x41; /* Mass erase command when length = 1 */ + length = 1; + } else if (command == READ_UNPROTECT) { + buf[0] = 0x92; + length = 1; + } else { + errx(EX_IOERR, "Non-supported special command %d", command); + } + buf[1] = address & 0xff; + buf[2] = (address >> 8) & 0xff; + buf[3] = (address >> 16) & 0xff; + buf[4] = (address >> 24) & 0xff; + + ret = dfuse_download(dif, length, buf, 0); + if (ret < 0) { + errx(EX_IOERR, "Error during special command \"%s\" download", + dfuse_command_name[command]); + } + do { + ret = dfu_get_status(dif, &dst); + if (ret < 0) { + errx(EX_IOERR, "Error during special command \"%s\" get_status", + dfuse_command_name[command]); + } + if (firstpoll) { + firstpoll = 0; + if (dst.bState != DFU_STATE_dfuDNBUSY) { + printf("state(%u) = %s, status(%u) = %s\n", dst.bState, + dfu_state_to_string(dst.bState), dst.bStatus, + dfu_status_to_string(dst.bStatus)); + errx(EX_IOERR, "Wrong state after command \"%s\" download", + dfuse_command_name[command]); + } + } + /* wait while command is executed */ + if (verbose) + printf(" Poll timeout %i ms\n", dst.bwPollTimeout); + milli_sleep(dst.bwPollTimeout); + if (command == READ_UNPROTECT) + return ret; + } while (dst.bState == DFU_STATE_dfuDNBUSY); + + if (dst.bStatus != DFU_STATUS_OK) { + errx(EX_IOERR, "%s not correctly executed", + dfuse_command_name[command]); + } + return ret; +} + +int dfuse_dnload_chunk(struct dfu_if *dif, unsigned char *data, int size, + int transaction) +{ + int bytes_sent; + struct dfu_status dst; + int ret; + + ret = dfuse_download(dif, size, size ? data : NULL, transaction); + if (ret < 0) { + errx(EX_IOERR, "Error during download"); + return ret; + } + bytes_sent = ret; + + do { + ret = dfu_get_status(dif, &dst); + if (ret < 0) { + errx(EX_IOERR, "Error during download get_status"); + return ret; + } + milli_sleep(dst.bwPollTimeout); + } while (dst.bState != DFU_STATE_dfuDNLOAD_IDLE && + dst.bState != DFU_STATE_dfuERROR && + dst.bState != DFU_STATE_dfuMANIFEST); + + if (dst.bState == DFU_STATE_dfuMANIFEST) + printf("Transitioning to dfuMANIFEST state\n"); + + if (dst.bStatus != DFU_STATUS_OK) { + printf(" failed!\n"); + printf("state(%u) = %s, status(%u) = %s\n", dst.bState, + dfu_state_to_string(dst.bState), dst.bStatus, + dfu_status_to_string(dst.bStatus)); + return -1; + } + return bytes_sent; +} + +int dfuse_do_upload(struct dfu_if *dif, int xfer_size, int fd, + const char *dfuse_options) +{ + int total_bytes = 0; + int upload_limit = 0; + unsigned char *buf; + int transaction; + int ret; + + buf = dfu_malloc(xfer_size); + + if (dfuse_options) + dfuse_parse_options(dfuse_options); + if (dfuse_length) + upload_limit = dfuse_length; + if (dfuse_address) { + struct memsegment *segment; + + mem_layout = parse_memory_layout((char *)dif->alt_name); + if (!mem_layout) + errx(EX_IOERR, "Failed to parse memory layout"); + + segment = find_segment(mem_layout, dfuse_address); + if (!dfuse_force && + (!segment || !(segment->memtype & DFUSE_READABLE))) + errx(EX_IOERR, "Page at 0x%08x is not readable", + dfuse_address); + + if (!upload_limit) { + upload_limit = segment->end - dfuse_address + 1; + printf("Limiting upload to end of memory segment, " + "%i bytes\n", upload_limit); + } + dfuse_special_command(dif, dfuse_address, SET_ADDRESS); + dfu_abort_to_idle(dif); + } else { + /* Boot loader decides the start address, unknown to us */ + /* Use a short length to lower risk of running out of bounds */ + if (!upload_limit) + upload_limit = 0x4000; + printf("Limiting default upload to %i bytes\n", upload_limit); + } + + dfu_progress_bar("Upload", 0, 1); + + transaction = 2; + while (1) { + int rc; + + /* last chunk can be smaller than original xfer_size */ + if (upload_limit - total_bytes < xfer_size) + xfer_size = upload_limit - total_bytes; + rc = dfuse_upload(dif, xfer_size, buf, transaction++); + if (rc < 0) { + ret = rc; + goto out_free; + } + + dfu_file_write_crc(fd, 0, buf, rc); + total_bytes += rc; + + if (total_bytes < 0) + errx(EX_SOFTWARE, "Received too many bytes"); + + if (rc < xfer_size || total_bytes >= upload_limit) { + /* last block, return successfully */ + ret = total_bytes; + break; + } + dfu_progress_bar("Upload", total_bytes, upload_limit); + } + + dfu_progress_bar("Upload", total_bytes, total_bytes); + + dfu_abort_to_idle(dif); + if (dfuse_leave) { + dfuse_special_command(dif, dfuse_address, SET_ADDRESS); + dfuse_dnload_chunk(dif, NULL, 0, 2); /* Zero-size */ + } + + out_free: + free(buf); + + return ret; +} + +/* Writes an element of any size to the device, taking care of page erases */ +/* returns 0 on success, otherwise -EINVAL */ +int dfuse_dnload_element(struct dfu_if *dif, unsigned int dwElementAddress, + unsigned int dwElementSize, unsigned char *data, + int xfer_size) +{ + int p; + int ret; + struct memsegment *segment; + + /* Check at least that we can write to the last address */ + segment = + find_segment(mem_layout, dwElementAddress + dwElementSize - 1); + if (!segment || !(segment->memtype & DFUSE_WRITEABLE)) { + errx(EX_IOERR, "Last page at 0x%08x is not writeable", + dwElementAddress + dwElementSize - 1); + } + + dfu_progress_bar("Download", 0, 1); + + for (p = 0; p < (int)dwElementSize; p += xfer_size) { + int page_size; + unsigned int erase_address; + unsigned int address = dwElementAddress + p; + int chunk_size = xfer_size; + + segment = find_segment(mem_layout, address); + if (!segment || !(segment->memtype & DFUSE_WRITEABLE)) { + errx(EX_IOERR, "Page at 0x%08x is not writeable", + address); + } + page_size = segment->pagesize; + + /* check if this is the last chunk */ + if (p + chunk_size > (int)dwElementSize) + chunk_size = dwElementSize - p; + + /* Erase only for flash memory downloads */ + if ((segment->memtype & DFUSE_ERASABLE) && !dfuse_mass_erase) { + /* erase all involved pages */ + for (erase_address = address; + erase_address < address + chunk_size; + erase_address += page_size) + if ((erase_address & ~(page_size - 1)) != + last_erased_page) + dfuse_special_command(dif, + erase_address, + ERASE_PAGE); + + if (((address + chunk_size - 1) & ~(page_size - 1)) != + last_erased_page) { + if (verbose > 2) + printf(" Chunk extends into next page," + " erase it as well\n"); + dfuse_special_command(dif, + address + chunk_size - 1, + ERASE_PAGE); + } + } + + if (verbose) { + printf(" Download from image offset " + "%08x to memory %08x-%08x, size %i\n", + p, address, address + chunk_size - 1, + chunk_size); + } else { + dfu_progress_bar("Download", p, dwElementSize); + } + + dfuse_special_command(dif, address, SET_ADDRESS); + + /* transaction = 2 for no address offset */ + ret = dfuse_dnload_chunk(dif, data + p, chunk_size, 2); + if (ret != chunk_size) { + errx(EX_IOERR, "Failed to write whole chunk: " + "%i of %i bytes", ret, chunk_size); + return -EINVAL; + } + } + if (!verbose) + dfu_progress_bar("Download", dwElementSize, dwElementSize); + return 0; +} + +static void +dfuse_memcpy(unsigned char *dst, unsigned char **src, int *rem, int size) +{ + if (size > *rem) { + errx(EX_IOERR, "Corrupt DfuSe file: " + "Cannot read %d bytes from %d bytes", size, *rem); + } + if (dst != NULL) + memcpy(dst, *src, size); + (*src) += size; + (*rem) -= size; +} + +/* Download raw binary file to DfuSe device */ +int dfuse_do_bin_dnload(struct dfu_if *dif, int xfer_size, + struct dfu_file *file, unsigned int start_address) +{ + unsigned int dwElementAddress; + unsigned int dwElementSize; + unsigned char *data; + int ret; + + dwElementAddress = start_address; + dwElementSize = file->size.total - + file->size.suffix - file->size.prefix; + + printf("Downloading to address = 0x%08x, size = %i\n", + dwElementAddress, dwElementSize); + + data = file->firmware + file->size.prefix; + + ret = dfuse_dnload_element(dif, dwElementAddress, dwElementSize, data, + xfer_size); + if (ret != 0) + goto out_free; + + printf("File downloaded successfully\n"); + ret = dwElementSize; + + out_free: + return ret; +} + +/* Parse a DfuSe file and download contents to device */ +int dfuse_do_dfuse_dnload(struct dfu_if *dif, int xfer_size, + struct dfu_file *file) +{ + uint8_t dfuprefix[11]; + uint8_t targetprefix[274]; + uint8_t elementheader[8]; + int image; + int element; + int bTargets; + int bAlternateSetting; + int dwNbElements; + unsigned int dwElementAddress; + unsigned int dwElementSize; + uint8_t *data; + int ret; + int rem; + int bFirstAddressSaved = 0; + + rem = file->size.total - file->size.prefix - file->size.suffix; + data = file->firmware + file->size.prefix; + + /* Must be larger than a minimal DfuSe header and suffix */ + if (rem < (int)(sizeof(dfuprefix) + + sizeof(targetprefix) + sizeof(elementheader))) { + errx(EX_SOFTWARE, "File too small for a DfuSe file"); + } + + dfuse_memcpy(dfuprefix, &data, &rem, sizeof(dfuprefix)); + + if (strncmp((char *)dfuprefix, "DfuSe", 5)) { + errx(EX_IOERR, "No valid DfuSe signature"); + return -EINVAL; + } + if (dfuprefix[5] != 0x01) { + errx(EX_IOERR, "DFU format revision %i not supported", + dfuprefix[5]); + return -EINVAL; + } + bTargets = dfuprefix[10]; + printf("file contains %i DFU images\n", bTargets); + + for (image = 1; image <= bTargets; image++) { + printf("parsing DFU image %i\n", image); + dfuse_memcpy(targetprefix, &data, &rem, sizeof(targetprefix)); + if (strncmp((char *)targetprefix, "Target", 6)) { + errx(EX_IOERR, "No valid target signature"); + return -EINVAL; + } + bAlternateSetting = targetprefix[6]; + dwNbElements = quad2uint((unsigned char *)targetprefix + 270); + printf("image for alternate setting %i, ", bAlternateSetting); + printf("(%i elements, ", dwNbElements); + printf("total size = %i)\n", + quad2uint((unsigned char *)targetprefix + 266)); + if (bAlternateSetting != dif->altsetting) + printf("Warning: Image does not match current alternate" + " setting.\n" + "Please rerun with the correct -a option setting" + " to download this image!\n"); + for (element = 1; element <= dwNbElements; element++) { + printf("parsing element %i, ", element); + dfuse_memcpy(elementheader, &data, &rem, sizeof(elementheader)); + dwElementAddress = + quad2uint((unsigned char *)elementheader); + dwElementSize = + quad2uint((unsigned char *)elementheader + 4); + printf("address = 0x%08x, ", dwElementAddress); + printf("size = %i\n", dwElementSize); + + if (!bFirstAddressSaved) { + bFirstAddressSaved = 1; + dfuse_address = dwElementAddress; + } + /* sanity check */ + if ((int)dwElementSize > rem) + errx(EX_SOFTWARE, "File too small for element size"); + + if (bAlternateSetting == dif->altsetting) { + ret = dfuse_dnload_element(dif, dwElementAddress, + dwElementSize, data, xfer_size); + } else { + ret = 0; + } + + /* advance read pointer */ + dfuse_memcpy(NULL, &data, &rem, dwElementSize); + + if (ret != 0) + return ret; + } + } + + if (rem != 0) + warnx("%d bytes leftover", rem); + + printf("done parsing DfuSe file\n"); + + return 0; +} + +int dfuse_do_dnload(struct dfu_if *dif, int xfer_size, struct dfu_file *file, + const char *dfuse_options) +{ + int ret; + + if (dfuse_options) + dfuse_parse_options(dfuse_options); + mem_layout = parse_memory_layout((char *)dif->alt_name); + if (!mem_layout) { + errx(EX_IOERR, "Failed to parse memory layout"); + } + if (dfuse_unprotect) { + if (!dfuse_force) { + errx(EX_IOERR, "The read unprotect command " + "will erase the flash memory" + "and can only be used with force\n"); + } + dfuse_special_command(dif, 0, READ_UNPROTECT); + printf("Device disconnects, erases flash and resets now\n"); + exit(0); + } + if (dfuse_mass_erase) { + if (!dfuse_force) { + errx(EX_IOERR, "The mass erase command " + "can only be used with force"); + } + printf("Performing mass erase, this can take a moment\n"); + dfuse_special_command(dif, 0, MASS_ERASE); + } + if (dfuse_address) { + if (file->bcdDFU == 0x11a) { + errx(EX_IOERR, "This is a DfuSe file, not " + "meant for raw download"); + } + ret = dfuse_do_bin_dnload(dif, xfer_size, file, dfuse_address); + } else { + if (file->bcdDFU != 0x11a) { + warnx("Only DfuSe file version 1.1a is supported"); + errx(EX_IOERR, "(for raw binary download, use the " + "--dfuse-address option)"); + } + ret = dfuse_do_dfuse_dnload(dif, xfer_size, file); + } + free_segment_list(mem_layout); + + dfu_abort_to_idle(dif); + + if (dfuse_leave) { + dfuse_special_command(dif, dfuse_address, SET_ADDRESS); + dfuse_dnload_chunk(dif, NULL, 0, 2); /* Zero-size */ + } + return ret; +} diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfuse.h b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfuse.h new file mode 100644 index 0000000..ed1108c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfuse.h @@ -0,0 +1,35 @@ +/* This implements the ST Microsystems DFU extensions (DfuSe) + * as per the DfuSe 1.1a specification (Document UM0391) + * + * (C) 2010-2012 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DFUSE_H +#define DFUSE_H + +#include "dfu.h" + +enum dfuse_command { SET_ADDRESS, ERASE_PAGE, MASS_ERASE, READ_UNPROTECT }; + +int dfuse_special_command(struct dfu_if *dif, unsigned int address, + enum dfuse_command command); +int dfuse_do_upload(struct dfu_if *dif, int xfer_size, int fd, + const char *dfuse_options); +int dfuse_do_dnload(struct dfu_if *dif, int xfer_size, struct dfu_file *file, + const char *dfuse_options); + +#endif /* DFUSE_H */ diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfuse_mem.c b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfuse_mem.c new file mode 100644 index 0000000..a91aacf --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfuse_mem.c @@ -0,0 +1,198 @@ +/* + * Helper functions for reading the memory map of a device + * following the ST DfuSe 1.1a specification. + * + * Copyright 2011-2014 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "portable.h" +#include "dfu_file.h" +#include "dfuse_mem.h" + +int add_segment(struct memsegment **segment_list, struct memsegment segment) +{ + struct memsegment *new_element; + + new_element = dfu_malloc(sizeof(struct memsegment)); + *new_element = segment; + new_element->next = NULL; + + if (*segment_list == NULL) + /* list can be empty on first call */ + *segment_list = new_element; + else { + struct memsegment *next_element; + + /* find last element in list */ + next_element = *segment_list; + while (next_element->next != NULL) + next_element = next_element->next; + next_element->next = new_element; + } + return 0; +} + +struct memsegment *find_segment(struct memsegment *segment_list, + unsigned int address) +{ + while (segment_list != NULL) { + if (segment_list->start <= address && + segment_list->end >= address) + return segment_list; + segment_list = segment_list->next; + } + return NULL; +} + +void free_segment_list(struct memsegment *segment_list) +{ + struct memsegment *next_element; + + while (segment_list->next != NULL) { + next_element = segment_list->next; + free(segment_list); + segment_list = next_element; + } + free(segment_list); +} + +/* Parse memory map from interface descriptor string + * encoded as per ST document UM0424 section 4.3.2. + */ +struct memsegment *parse_memory_layout(char *intf_desc) +{ + + char multiplier, memtype; + unsigned int address; + int sectors, size; + char *name, *typestring; + int ret; + int count = 0; + char separator; + int scanned; + struct memsegment *segment_list = NULL; + struct memsegment segment; + + name = dfu_malloc(strlen(intf_desc)); + + ret = sscanf(intf_desc, "@%[^/]%n", name, &scanned); + if (ret < 1) { + free(name); + warnx("Could not read name, sscanf returned %d", ret); + return NULL; + } + printf("DfuSe interface name: \"%s\"\n", name); + + intf_desc += scanned; + typestring = dfu_malloc(strlen(intf_desc)); + + while (ret = sscanf(intf_desc, "/0x%x/%n", &address, &scanned), + ret > 0) { + + intf_desc += scanned; + while (ret = sscanf(intf_desc, "%d*%d%c%[^,/]%n", + §ors, &size, &multiplier, typestring, + &scanned), ret > 2) { + intf_desc += scanned; + + count++; + memtype = 0; + if (ret == 4) { + if (strlen(typestring) == 1 + && typestring[0] != '/') + memtype = typestring[0]; + else { + warnx("Parsing type identifier '%s' " + "failed for segment %i", + typestring, count); + continue; + } + } + + /* Quirk for STM32F4 devices */ + if (strcmp(name, "Device Feature") == 0) + memtype = 'e'; + + switch (multiplier) { + case 'B': + break; + case 'K': + size *= 1024; + break; + case 'M': + size *= 1024 * 1024; + break; + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + if (!memtype) { + warnx("Non-valid multiplier '%c', " + "interpreted as type " + "identifier instead", + multiplier); + memtype = multiplier; + break; + } + /* fallthrough if memtype was already set */ + default: + warnx("Non-valid multiplier '%c', " + "assuming bytes", multiplier); + } + + if (!memtype) { + warnx("No valid type for segment %d\n", count); + continue; + } + + segment.start = address; + segment.end = address + sectors * size - 1; + segment.pagesize = size; + segment.memtype = memtype & 7; + add_segment(&segment_list, segment); + + if (verbose) + printf("Memory segment at 0x%08x %3d x %4d = " + "%5d (%s%s%s)\n", + address, sectors, size, sectors * size, + memtype & DFUSE_READABLE ? "r" : "", + memtype & DFUSE_ERASABLE ? "e" : "", + memtype & DFUSE_WRITEABLE ? "w" : ""); + + address += sectors * size; + + separator = *intf_desc; + if (separator == ',') + intf_desc += 1; + else + break; + } /* while per segment */ + + } /* while per address */ + free(name); + free(typestring); + + return segment_list; +} diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfuse_mem.h b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfuse_mem.h new file mode 100644 index 0000000..0181f0c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/dfuse_mem.h @@ -0,0 +1,44 @@ +/* Helper functions for reading the memory map in a device + * following the ST DfuSe 1.1a specification. + * + * (C) 2011 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DFUSE_MEM_H +#define DFUSE_MEM_H + +#define DFUSE_READABLE 1 +#define DFUSE_ERASABLE 2 +#define DFUSE_WRITEABLE 4 + +struct memsegment { + unsigned int start; + unsigned int end; + int pagesize; + int memtype; + struct memsegment *next; +}; + +int add_segment(struct memsegment **list, struct memsegment new_element); + +struct memsegment *find_segment(struct memsegment *list, unsigned int address); + +void free_segment_list(struct memsegment *list); + +struct memsegment *parse_memory_layout(char *intf_desc_str); + +#endif /* DFUSE_MEM_H */ diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/main.c b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/main.c new file mode 100644 index 0000000..acaed2f --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/main.c @@ -0,0 +1,699 @@ +/* + * dfu-util + * + * Copyright 2007-2008 by OpenMoko, Inc. + * Copyright 2013-2014 Hans Petter Selasky + * + * Written by Harald Welte + * + * Based on existing code of dfu-programmer-0.4 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "portable.h" +#include "dfu.h" +#include "usb_dfu.h" +#include "dfu_file.h" +#include "dfu_load.h" +#include "dfu_util.h" +#include "dfuse.h" +#include "quirks.h" + +#ifdef HAVE_USBPATH_H +#include +#endif + +int verbose = 0; + +struct dfu_if *dfu_root = NULL; + +int match_bus = -1; +int match_device = -1; +int match_vendor = -1; +int match_product = -1; +int match_vendor_dfu = -1; +int match_product_dfu = -1; +int match_config_index = -1; +int match_iface_index = -1; +int match_iface_alt_index = -1; +const char *match_iface_alt_name = NULL; +const char *match_serial = NULL; +const char *match_serial_dfu = NULL; + +static int parse_match_value(const char *str, int default_value) +{ + char *remainder; + int value; + + if (str == NULL) { + value = default_value; + } else if (*str == '*') { + value = -1; /* Match anything */ + } else if (*str == '-') { + value = 0x10000; /* Impossible vendor/product ID */ + } else { + value = strtoul(str, &remainder, 16); + if (remainder == str) { + value = default_value; + } + } + return value; +} + +static void parse_vendprod(const char *str) +{ + const char *comma; + const char *colon; + + /* Default to match any DFU device in runtime or DFU mode */ + match_vendor = -1; + match_product = -1; + match_vendor_dfu = -1; + match_product_dfu = -1; + + comma = strchr(str, ','); + if (comma == str) { + /* DFU mode vendor/product being specified without any runtime + * vendor/product specification, so don't match any runtime device */ + match_vendor = match_product = 0x10000; + } else { + colon = strchr(str, ':'); + if (colon != NULL) { + ++colon; + if ((comma != NULL) && (colon > comma)) { + colon = NULL; + } + } + match_vendor = parse_match_value(str, match_vendor); + match_product = parse_match_value(colon, match_product); + if (comma != NULL) { + /* Both runtime and DFU mode vendor/product specifications are + * available, so default DFU mode match components to the given + * runtime match components */ + match_vendor_dfu = match_vendor; + match_product_dfu = match_product; + } + } + if (comma != NULL) { + ++comma; + colon = strchr(comma, ':'); + if (colon != NULL) { + ++colon; + } + match_vendor_dfu = parse_match_value(comma, match_vendor_dfu); + match_product_dfu = parse_match_value(colon, match_product_dfu); + } +} + +static void parse_serial(char *str) +{ + char *comma; + + match_serial = str; + comma = strchr(str, ','); + if (comma == NULL) { + match_serial_dfu = match_serial; + } else { + *comma++ = 0; + match_serial_dfu = comma; + } + if (*match_serial == 0) match_serial = NULL; + if (*match_serial_dfu == 0) match_serial_dfu = NULL; +} + +#ifdef HAVE_USBPATH_H + +static int resolve_device_path(char *path) +{ + int res; + + res = usb_path2devnum(path); + if (res < 0) + return -EINVAL; + if (!res) + return 0; + + match_bus = atoi(path); + match_device = res; + + return 0; +} + +#else /* HAVE_USBPATH_H */ + +static int resolve_device_path(char *path) +{ + (void)path; /* Eliminate unused variable warning */ + errx(EX_SOFTWARE, "USB device paths are not supported by this dfu-util.\n"); +} + +#endif /* !HAVE_USBPATH_H */ + +static void help(void) +{ + fprintf(stderr, "Usage: dfu-util [options] ...\n" + " -h --help\t\t\tPrint this help message\n" + " -V --version\t\t\tPrint the version number\n" + " -v --verbose\t\t\tPrint verbose debug statements\n" + " -l --list\t\t\tList currently attached DFU capable devices\n"); + fprintf(stderr, " -e --detach\t\t\tDetach currently attached DFU capable devices\n" + " -E --detach-delay seconds\tTime to wait before reopening a device after detach\n" + " -d --device :[,:]\n" + "\t\t\t\tSpecify Vendor/Product ID(s) of DFU device\n" + " -p --path \tSpecify path to DFU device\n" + " -c --cfg \t\tSpecify the Configuration of DFU device\n" + " -i --intf \t\tSpecify the DFU Interface number\n" + " -S --serial [,]\n" + "\t\t\t\tSpecify Serial String of DFU device\n" + " -a --alt \t\tSpecify the Altsetting of the DFU Interface\n" + "\t\t\t\tby name or by number\n"); + fprintf(stderr, " -t --transfer-size \tSpecify the number of bytes per USB Transfer\n" + " -U --upload \t\tRead firmware from device into \n" + " -Z --upload-size \tSpecify the expected upload size in bytes\n" + " -D --download \t\tWrite firmware from into device\n" + " -R --reset\t\t\tIssue USB Reset signalling once we're finished\n" + " -s --dfuse-address
\tST DfuSe mode, specify target address for\n" + "\t\t\t\traw file download or upload. Not applicable for\n" + "\t\t\t\tDfuSe file (.dfu) downloads\n" + ); + exit(EX_USAGE); +} + +static void print_version(void) +{ + printf(PACKAGE_STRING "\n\n"); + printf("Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.\n" + "Copyright 2010-2014 Tormod Volden and Stefan Schmidt\n" + "This program is Free Software and has ABSOLUTELY NO WARRANTY\n" + "Please report bugs to " PACKAGE_BUGREPORT "\n\n"); +} + +static struct option opts[] = { + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'V' }, + { "verbose", 0, 0, 'v' }, + { "list", 0, 0, 'l' }, + { "detach", 0, 0, 'e' }, + { "detach-delay", 1, 0, 'E' }, + { "device", 1, 0, 'd' }, + { "path", 1, 0, 'p' }, + { "configuration", 1, 0, 'c' }, + { "cfg", 1, 0, 'c' }, + { "interface", 1, 0, 'i' }, + { "intf", 1, 0, 'i' }, + { "altsetting", 1, 0, 'a' }, + { "alt", 1, 0, 'a' }, + { "serial", 1, 0, 'S' }, + { "transfer-size", 1, 0, 't' }, + { "upload", 1, 0, 'U' }, + { "upload-size", 1, 0, 'Z' }, + { "download", 1, 0, 'D' }, + { "reset", 0, 0, 'R' }, + { "dfuse-address", 1, 0, 's' }, + { 0, 0, 0, 0 } +}; + +int main(int argc, char **argv) +{ + int expected_size = 0; + unsigned int transfer_size = 0; + enum mode mode = MODE_NONE; + struct dfu_status status; + libusb_context *ctx; + struct dfu_file file; + char *end; + int final_reset = 0; + int ret; + int dfuse_device = 0; + int fd; + const char *dfuse_options = NULL; + int detach_delay = 5; + uint16_t runtime_vendor; + uint16_t runtime_product; + + memset(&file, 0, sizeof(file)); + + /* make sure all prints are flushed */ + setvbuf(stdout, NULL, _IONBF, 0); + + while (1) { + int c, option_index = 0; + c = getopt_long(argc, argv, "hVvleE:d:p:c:i:a:S:t:U:D:Rs:Z:", opts, + &option_index); + if (c == -1) + break; + + switch (c) { + case 'h': + help(); + break; + case 'V': + mode = MODE_VERSION; + break; + case 'v': + verbose++; + break; + case 'l': + mode = MODE_LIST; + break; + case 'e': + mode = MODE_DETACH; + match_iface_alt_index = 0; + match_iface_index = 0; + break; + case 'E': + detach_delay = atoi(optarg); + break; + case 'd': + parse_vendprod(optarg); + break; + case 'p': + /* Parse device path */ + ret = resolve_device_path(optarg); + if (ret < 0) + errx(EX_SOFTWARE, "Unable to parse '%s'", optarg); + if (!ret) + errx(EX_SOFTWARE, "Cannot find '%s'", optarg); + break; + case 'c': + /* Configuration */ + match_config_index = atoi(optarg); + break; + case 'i': + /* Interface */ + match_iface_index = atoi(optarg); + break; + case 'a': + /* Interface Alternate Setting */ + match_iface_alt_index = strtoul(optarg, &end, 0); + if (*end) { + match_iface_alt_name = optarg; + match_iface_alt_index = -1; + } + break; + case 'S': + parse_serial(optarg); + break; + case 't': + transfer_size = atoi(optarg); + break; + case 'U': + mode = MODE_UPLOAD; + file.name = optarg; + break; + case 'Z': + expected_size = atoi(optarg); + break; + case 'D': + mode = MODE_DOWNLOAD; + file.name = optarg; + break; + case 'R': + final_reset = 1; + break; + case 's': + dfuse_options = optarg; + break; + default: + help(); + break; + } + } + + print_version(); + if (mode == MODE_VERSION) { + exit(0); + } + + if (mode == MODE_NONE) { + fprintf(stderr, "You need to specify one of -D or -U\n"); + help(); + } + + if (match_config_index == 0) { + /* Handle "-c 0" (unconfigured device) as don't care */ + match_config_index = -1; + } + + if (mode == MODE_DOWNLOAD) { + dfu_load_file(&file, MAYBE_SUFFIX, MAYBE_PREFIX); + /* If the user didn't specify product and/or vendor IDs to match, + * use any IDs from the file suffix for device matching */ + if (match_vendor < 0 && file.idVendor != 0xffff) { + match_vendor = file.idVendor; + printf("Match vendor ID from file: %04x\n", match_vendor); + } + if (match_product < 0 && file.idProduct != 0xffff) { + match_product = file.idProduct; + printf("Match product ID from file: %04x\n", match_product); + } + } + + ret = libusb_init(&ctx); + if (ret) + errx(EX_IOERR, "unable to initialize libusb: %i", ret); + + if (verbose > 2) { + libusb_set_debug(ctx, 255); + } + + probe_devices(ctx); + + if (mode == MODE_LIST) { + list_dfu_interfaces(); + exit(0); + } + + if (dfu_root == NULL) { + errx(EX_IOERR, "No DFU capable USB device available"); + } else if (dfu_root->next != NULL) { + /* We cannot safely support more than one DFU capable device + * with same vendor/product ID, since during DFU we need to do + * a USB bus reset, after which the target device will get a + * new address */ + errx(EX_IOERR, "More than one DFU capable USB device found! " + "Try `--list' and specify the serial number " + "or disconnect all but one device\n"); + } + + /* We have exactly one device. Its libusb_device is now in dfu_root->dev */ + + printf("Opening DFU capable USB device...\n"); + ret = libusb_open(dfu_root->dev, &dfu_root->dev_handle); + if (ret || !dfu_root->dev_handle) + errx(EX_IOERR, "Cannot open device"); + + printf("ID %04x:%04x\n", dfu_root->vendor, dfu_root->product); + + printf("Run-time device DFU version %04x\n", + libusb_le16_to_cpu(dfu_root->func_dfu.bcdDFUVersion)); + + /* Transition from run-Time mode to DFU mode */ + if (!(dfu_root->flags & DFU_IFF_DFU)) { + int err; + /* In the 'first round' during runtime mode, there can only be one + * DFU Interface descriptor according to the DFU Spec. */ + + /* FIXME: check if the selected device really has only one */ + + runtime_vendor = dfu_root->vendor; + runtime_product = dfu_root->product; + + printf("Claiming USB DFU Runtime Interface...\n"); + if (libusb_claim_interface(dfu_root->dev_handle, dfu_root->interface) < 0) { + errx(EX_IOERR, "Cannot claim interface %d", + dfu_root->interface); + } + + if (libusb_set_interface_alt_setting(dfu_root->dev_handle, dfu_root->interface, 0) < 0) { + errx(EX_IOERR, "Cannot set alt interface zero"); + } + + printf("Determining device status: "); + + err = dfu_get_status(dfu_root, &status); + if (err == LIBUSB_ERROR_PIPE) { + printf("Device does not implement get_status, assuming appIDLE\n"); + status.bStatus = DFU_STATUS_OK; + status.bwPollTimeout = 0; + status.bState = DFU_STATE_appIDLE; + status.iString = 0; + } else if (err < 0) { + errx(EX_IOERR, "error get_status"); + } else { + printf("state = %s, status = %d\n", + dfu_state_to_string(status.bState), status.bStatus); + } + milli_sleep(status.bwPollTimeout); + + switch (status.bState) { + case DFU_STATE_appIDLE: + case DFU_STATE_appDETACH: + printf("Device really in Runtime Mode, send DFU " + "detach request...\n"); + if (dfu_detach(dfu_root->dev_handle, + dfu_root->interface, 1000) < 0) { + warnx("error detaching"); + } + if (dfu_root->func_dfu.bmAttributes & USB_DFU_WILL_DETACH) { + printf("Device will detach and reattach...\n"); + } else { + printf("Resetting USB...\n"); + ret = libusb_reset_device(dfu_root->dev_handle); + if (ret < 0 && ret != LIBUSB_ERROR_NOT_FOUND) + errx(EX_IOERR, "error resetting " + "after detach"); + } + break; + case DFU_STATE_dfuERROR: + printf("dfuERROR, clearing status\n"); + if (dfu_clear_status(dfu_root->dev_handle, + dfu_root->interface) < 0) { + errx(EX_IOERR, "error clear_status"); + } + /* fall through */ + default: + warnx("WARNING: Runtime device already in DFU state ?!?"); + libusb_release_interface(dfu_root->dev_handle, + dfu_root->interface); + goto dfustate; + } + libusb_release_interface(dfu_root->dev_handle, + dfu_root->interface); + libusb_close(dfu_root->dev_handle); + dfu_root->dev_handle = NULL; + + if (mode == MODE_DETACH) { + libusb_exit(ctx); + exit(0); + } + + /* keeping handles open might prevent re-enumeration */ + disconnect_devices(); + + milli_sleep(detach_delay * 1000); + + /* Change match vendor and product to impossible values to force + * only DFU mode matches in the following probe */ + match_vendor = match_product = 0x10000; + + probe_devices(ctx); + + if (dfu_root == NULL) { + errx(EX_IOERR, "Lost device after RESET?"); + } else if (dfu_root->next != NULL) { + errx(EX_IOERR, "More than one DFU capable USB device found! " + "Try `--list' and specify the serial number " + "or disconnect all but one device"); + } + + /* Check for DFU mode device */ + if (!(dfu_root->flags | DFU_IFF_DFU)) + errx(EX_SOFTWARE, "Device is not in DFU mode"); + + printf("Opening DFU USB Device...\n"); + ret = libusb_open(dfu_root->dev, &dfu_root->dev_handle); + if (ret || !dfu_root->dev_handle) { + errx(EX_IOERR, "Cannot open device"); + } + } else { + /* we're already in DFU mode, so we can skip the detach/reset + * procedure */ + /* If a match vendor/product was specified, use that as the runtime + * vendor/product, otherwise use the DFU mode vendor/product */ + runtime_vendor = match_vendor < 0 ? dfu_root->vendor : match_vendor; + runtime_product = match_product < 0 ? dfu_root->product : match_product; + } + +dfustate: +#if 0 + printf("Setting Configuration %u...\n", dfu_root->configuration); + if (libusb_set_configuration(dfu_root->dev_handle, dfu_root->configuration) < 0) { + errx(EX_IOERR, "Cannot set configuration"); + } +#endif + printf("Claiming USB DFU Interface...\n"); + if (libusb_claim_interface(dfu_root->dev_handle, dfu_root->interface) < 0) { + errx(EX_IOERR, "Cannot claim interface"); + } + + printf("Setting Alternate Setting #%d ...\n", dfu_root->altsetting); + if (libusb_set_interface_alt_setting(dfu_root->dev_handle, dfu_root->interface, dfu_root->altsetting) < 0) { + errx(EX_IOERR, "Cannot set alternate interface"); + } + +status_again: + printf("Determining device status: "); + if (dfu_get_status(dfu_root, &status ) < 0) { + errx(EX_IOERR, "error get_status"); + } + printf("state = %s, status = %d\n", + dfu_state_to_string(status.bState), status.bStatus); + + milli_sleep(status.bwPollTimeout); + + switch (status.bState) { + case DFU_STATE_appIDLE: + case DFU_STATE_appDETACH: + errx(EX_IOERR, "Device still in Runtime Mode!"); + break; + case DFU_STATE_dfuERROR: + printf("dfuERROR, clearing status\n"); + if (dfu_clear_status(dfu_root->dev_handle, dfu_root->interface) < 0) { + errx(EX_IOERR, "error clear_status"); + } + goto status_again; + break; + case DFU_STATE_dfuDNLOAD_IDLE: + case DFU_STATE_dfuUPLOAD_IDLE: + printf("aborting previous incomplete transfer\n"); + if (dfu_abort(dfu_root->dev_handle, dfu_root->interface) < 0) { + errx(EX_IOERR, "can't send DFU_ABORT"); + } + goto status_again; + break; + case DFU_STATE_dfuIDLE: + printf("dfuIDLE, continuing\n"); + break; + default: + break; + } + + if (DFU_STATUS_OK != status.bStatus ) { + printf("WARNING: DFU Status: '%s'\n", + dfu_status_to_string(status.bStatus)); + /* Clear our status & try again. */ + if (dfu_clear_status(dfu_root->dev_handle, dfu_root->interface) < 0) + errx(EX_IOERR, "USB communication error"); + if (dfu_get_status(dfu_root, &status) < 0) + errx(EX_IOERR, "USB communication error"); + if (DFU_STATUS_OK != status.bStatus) + errx(EX_SOFTWARE, "Status is not OK: %d", status.bStatus); + + milli_sleep(status.bwPollTimeout); + } + + printf("DFU mode device DFU version %04x\n", + libusb_le16_to_cpu(dfu_root->func_dfu.bcdDFUVersion)); + + if (dfu_root->func_dfu.bcdDFUVersion == libusb_cpu_to_le16(0x11a)) + dfuse_device = 1; + + /* If not overridden by the user */ + if (!transfer_size) { + transfer_size = libusb_le16_to_cpu( + dfu_root->func_dfu.wTransferSize); + if (transfer_size) { + printf("Device returned transfer size %i\n", + transfer_size); + } else { + errx(EX_IOERR, "Transfer size must be specified"); + } + } + +#ifdef HAVE_GETPAGESIZE +/* autotools lie when cross-compiling for Windows using mingw32/64 */ +#ifndef __MINGW32__ + /* limitation of Linux usbdevio */ + if ((int)transfer_size > getpagesize()) { + transfer_size = getpagesize(); + printf("Limited transfer size to %i\n", transfer_size); + } +#endif /* __MINGW32__ */ +#endif /* HAVE_GETPAGESIZE */ + + if (transfer_size < dfu_root->bMaxPacketSize0) { + transfer_size = dfu_root->bMaxPacketSize0; + printf("Adjusted transfer size to %i\n", transfer_size); + } + + switch (mode) { + case MODE_UPLOAD: + /* open for "exclusive" writing */ + fd = open(file.name, O_WRONLY | O_BINARY | O_CREAT | O_EXCL | O_TRUNC, 0666); + if (fd < 0) + err(EX_IOERR, "Cannot open file %s for writing", file.name); + + if (dfuse_device || dfuse_options) { + if (dfuse_do_upload(dfu_root, transfer_size, fd, + dfuse_options) < 0) + exit(1); + } else { + if (dfuload_do_upload(dfu_root, transfer_size, + expected_size, fd) < 0) { + exit(1); + } + } + close(fd); + break; + + case MODE_DOWNLOAD: + if (((file.idVendor != 0xffff && file.idVendor != runtime_vendor) || + (file.idProduct != 0xffff && file.idProduct != runtime_product)) && + ((file.idVendor != 0xffff && file.idVendor != dfu_root->vendor) || + (file.idProduct != 0xffff && file.idProduct != dfu_root->product))) { + errx(EX_IOERR, "Error: File ID %04x:%04x does " + "not match device (%04x:%04x or %04x:%04x)", + file.idVendor, file.idProduct, + runtime_vendor, runtime_product, + dfu_root->vendor, dfu_root->product); + } + if (dfuse_device || dfuse_options || file.bcdDFU == 0x11a) { + if (dfuse_do_dnload(dfu_root, transfer_size, &file, + dfuse_options) < 0) + exit(1); + } else { + if (dfuload_do_dnload(dfu_root, transfer_size, &file) < 0) + exit(1); + } + break; + case MODE_DETACH: + if (dfu_detach(dfu_root->dev_handle, dfu_root->interface, 1000) < 0) { + warnx("can't detach"); + } + break; + default: + errx(EX_IOERR, "Unsupported mode: %u", mode); + break; + } + + if (final_reset) { + if (dfu_detach(dfu_root->dev_handle, dfu_root->interface, 1000) < 0) { + /* Even if detach failed, just carry on to leave the + device in a known state */ + warnx("can't detach"); + } + printf("Resetting USB to switch back to runtime mode\n"); + ret = libusb_reset_device(dfu_root->dev_handle); + if (ret < 0 && ret != LIBUSB_ERROR_NOT_FOUND) { + errx(EX_IOERR, "error resetting after download"); + } + } + + libusb_close(dfu_root->dev_handle); + dfu_root->dev_handle = NULL; + libusb_exit(ctx); + + return (0); +} diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/portable.h b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/portable.h new file mode 100644 index 0000000..cf8d5df --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/portable.h @@ -0,0 +1,72 @@ + +#ifndef PORTABLE_H +#define PORTABLE_H + +#ifdef HAVE_CONFIG_H +# include "config.h" +#else +# define PACKAGE "dfu-util" +# define PACKAGE_VERSION "0.8-msvc" +# define PACKAGE_STRING "dfu-util 0.8-msvc" +# define PACKAGE_BUGREPORT "dfu-util@lists.gnumonks.org" +#endif /* HAVE_CONFIG_H */ + +#ifdef HAVE_FTRUNCATE +# include +#else +# include +#endif /* HAVE_FTRUNCATE */ + +#ifdef HAVE_NANOSLEEP +# include +# define milli_sleep(msec) do {\ + if (msec) {\ + struct timespec nanosleepDelay = { (msec) / 1000, ((msec) % 1000) * 1000000 };\ + nanosleep(&nanosleepDelay, NULL);\ + } } while (0) +#elif defined HAVE_WINDOWS_H +# define milli_sleep(msec) do {\ + if (msec) {\ + Sleep(msec);\ + } } while (0) +#else +# error "Can't get no sleep! Please report" +#endif /* HAVE_NANOSLEEP */ + +#ifdef HAVE_ERR +# include +#else +# include +# include +# define warnx(...) do {\ + fprintf(stderr, __VA_ARGS__);\ + fprintf(stderr, "\n"); } while (0) +# define errx(eval, ...) do {\ + warnx(__VA_ARGS__);\ + exit(eval); } while (0) +# define warn(...) do {\ + fprintf(stderr, "%s: ", strerror(errno));\ + warnx(__VA_ARGS__); } while (0) +# define err(eval, ...) do {\ + warn(__VA_ARGS__);\ + exit(eval); } while (0) +#endif /* HAVE_ERR */ + +#ifdef HAVE_SYSEXITS_H +# include +#else +# define EX_OK 0 /* successful termination */ +# define EX_USAGE 64 /* command line usage error */ +# define EX_SOFTWARE 70 /* internal software error */ +# define EX_IOERR 74 /* input/output error */ +#endif /* HAVE_SYSEXITS_H */ + +#ifndef O_BINARY +# define O_BINARY 0 +#endif + +#ifndef off_t +# define off_t long int +#endif + +#endif /* PORTABLE_H */ diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/prefix.c b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/prefix.c new file mode 100644 index 0000000..be8e3fa --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/prefix.c @@ -0,0 +1,176 @@ +/* + * dfu-prefix + * + * Copyright 2011-2012 Stefan Schmidt + * Copyright 2013 Hans Petter Selasky + * Copyright 2014 Uwe Bonnes + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include "portable.h" +#include "dfu_file.h" + +enum mode { + MODE_NONE, + MODE_ADD, + MODE_DEL, + MODE_CHECK +}; + +int verbose; + +static void help(void) +{ + fprintf(stderr, "Usage: dfu-prefix [options] ...\n" + " -h --help\t\t\tPrint this help message\n" + " -V --version\t\t\tPrint the version number\n" + " -c --check \t\tCheck DFU prefix of \n" + " -D --delete \t\tDelete DFU prefix from \n" + " -a --add \t\tAdd DFU prefix to \n" + "In combination with -a:\n" + ); + fprintf(stderr, " -s --stellaris-address
Add TI Stellaris address prefix to \n" + "In combination with -D or -c:\n" + " -T --stellaris\t\tAct on TI Stellaris address prefix of \n" + "In combination with -a or -D or -c:\n" + " -L --lpc-prefix\t\tUse NXP LPC DFU prefix format\n" + ); + exit(EX_USAGE); +} + +static void print_version(void) +{ + printf("dfu-prefix (%s) %s\n\n", PACKAGE, PACKAGE_VERSION); + printf("Copyright 2011-2012 Stefan Schmidt, 2014 Uwe Bonnes\n" + "This program is Free Software and has ABSOLUTELY NO WARRANTY\n" + "Please report bugs to %s\n\n", PACKAGE_BUGREPORT); + +} + +static struct option opts[] = { + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'V' }, + { "check", 1, 0, 'c' }, + { "add", 1, 0, 'a' }, + { "delete", 1, 0, 'D' }, + { "stellaris-address", 1, 0, 's' }, + { "stellaris", 0, 0, 'T' }, + { "LPC", 0, 0, 'L' }, +}; +int main(int argc, char **argv) +{ + struct dfu_file file; + enum mode mode = MODE_NONE; + enum prefix_type type = ZERO_PREFIX; + uint32_t lmdfu_flash_address = 0; + char *end; + + /* make sure all prints are flushed */ + setvbuf(stdout, NULL, _IONBF, 0); + + print_version(); + + memset(&file, 0, sizeof(file)); + + while (1) { + int c, option_index = 0; + c = getopt_long(argc, argv, "hVc:a:D:p:v:d:s:TL", opts, + &option_index); + if (c == -1) + break; + + switch (c) { + case 'h': + help(); + break; + case 'V': + exit(0); + break; + case 'D': + file.name = optarg; + mode = MODE_DEL; + break; + case 'c': + file.name = optarg; + mode = MODE_CHECK; + break; + case 'a': + file.name = optarg; + mode = MODE_ADD; + break; + case 's': + lmdfu_flash_address = strtoul(optarg, &end, 0); + if (*end) { + errx(EX_IOERR, "Invalid lmdfu " + "address: %s", optarg); + } + /* fall-through */ + case 'T': + type = LMDFU_PREFIX; + break; + case 'L': + type = LPCDFU_UNENCRYPTED_PREFIX; + break; + default: + help(); + break; + } + } + + if (!file.name) { + fprintf(stderr, "You need to specify a filename\n"); + help(); + } + + switch(mode) { + case MODE_ADD: + if (type == ZERO_PREFIX) + errx(EX_IOERR, "Prefix type must be specified"); + dfu_load_file(&file, MAYBE_SUFFIX, NO_PREFIX); + file.lmdfu_address = lmdfu_flash_address; + file.prefix_type = type; + printf("Adding prefix to file\n"); + dfu_store_file(&file, file.size.suffix != 0, 1); + break; + + case MODE_CHECK: + dfu_load_file(&file, MAYBE_SUFFIX, MAYBE_PREFIX); + show_suffix_and_prefix(&file); + if (type > ZERO_PREFIX && file.prefix_type != type) + errx(EX_IOERR, "No prefix of requested type"); + break; + + case MODE_DEL: + dfu_load_file(&file, MAYBE_SUFFIX, NEEDS_PREFIX); + if (type > ZERO_PREFIX && file.prefix_type != type) + errx(EX_IOERR, "No prefix of requested type"); + printf("Removing prefix from file\n"); + /* if there was a suffix, rewrite it */ + dfu_store_file(&file, file.size.suffix != 0, 0); + break; + + default: + help(); + break; + } + return (0); +} diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/quirks.c b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/quirks.c new file mode 100644 index 0000000..de394a6 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/quirks.c @@ -0,0 +1,56 @@ +/* + * Simple quirk system for dfu-util + * + * Copyright 2010-2014 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include "quirks.h" + +uint16_t get_quirks(uint16_t vendor, uint16_t product, uint16_t bcdDevice) +{ + uint16_t quirks = 0; + + /* Device returns bogus bwPollTimeout values */ + if ((vendor == VENDOR_OPENMOKO || vendor == VENDOR_FIC) && + product >= PRODUCT_FREERUNNER_FIRST && + product <= PRODUCT_FREERUNNER_LAST) + quirks |= QUIRK_POLLTIMEOUT; + + if (vendor == VENDOR_VOTI && + product == PRODUCT_OPENPCD) + quirks |= QUIRK_POLLTIMEOUT; + + /* Reports wrong DFU version in DFU descriptor */ + if (vendor == VENDOR_LEAFLABS && + product == PRODUCT_MAPLE3 && + bcdDevice == 0x0200) + quirks |= QUIRK_FORCE_DFU11; + + /* old devices(bcdDevice == 0) return bogus bwPollTimeout values */ + if (vendor == VENDOR_SIEMENS && + (product == PRODUCT_PXM40 || product == PRODUCT_PXM50) && + bcdDevice == 0) + quirks |= QUIRK_POLLTIMEOUT; + + /* M-Audio Transit returns bogus bwPollTimeout values */ + if (vendor == VENDOR_MIDIMAN && + product == PRODUCT_TRANSIT) + quirks |= QUIRK_POLLTIMEOUT; + + return (quirks); +} diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/quirks.h b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/quirks.h new file mode 100644 index 0000000..0e4b3ec --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/quirks.h @@ -0,0 +1,27 @@ +#ifndef DFU_QUIRKS_H +#define DFU_QUIRKS_H + +#define VENDOR_OPENMOKO 0x1d50 /* Openmoko Freerunner / GTA02 */ +#define VENDOR_FIC 0x1457 /* Openmoko Freerunner / GTA02 */ +#define VENDOR_VOTI 0x16c0 /* OpenPCD Reader */ +#define VENDOR_LEAFLABS 0x1eaf /* Maple */ +#define VENDOR_SIEMENS 0x0908 /* Siemens AG */ +#define VENDOR_MIDIMAN 0x0763 /* Midiman */ + +#define PRODUCT_FREERUNNER_FIRST 0x5117 +#define PRODUCT_FREERUNNER_LAST 0x5126 +#define PRODUCT_OPENPCD 0x076b +#define PRODUCT_MAPLE3 0x0003 /* rev 3 and 5 */ +#define PRODUCT_PXM40 0x02c4 /* Siemens AG, PXM 40 */ +#define PRODUCT_PXM50 0x02c5 /* Siemens AG, PXM 50 */ +#define PRODUCT_TRANSIT 0x2806 /* M-Audio Transit (Midiman) */ + +#define QUIRK_POLLTIMEOUT (1<<0) +#define QUIRK_FORCE_DFU11 (1<<1) + +/* Fallback value, works for OpenMoko */ +#define DEFAULT_POLLTIMEOUT 5 + +uint16_t get_quirks(uint16_t vendor, uint16_t product, uint16_t bcdDevice); + +#endif /* DFU_QUIRKS_H */ diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/suffix.c b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/suffix.c new file mode 100644 index 0000000..0df248f --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/suffix.c @@ -0,0 +1,176 @@ +/* + * dfu-suffix + * + * Copyright 2011-2012 Stefan Schmidt + * Copyright 2013 Hans Petter Selasky + * Copyright 2014 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include "portable.h" +#include "dfu_file.h" + +enum mode { + MODE_NONE, + MODE_ADD, + MODE_DEL, + MODE_CHECK +}; + +int verbose; + +static void help(void) +{ + fprintf(stderr, "Usage: dfu-suffix [options] ...\n" + " -h --help\t\t\tPrint this help message\n" + " -V --version\t\t\tPrint the version number\n" + " -c --check \t\tCheck DFU suffix of \n" + " -a --add \t\tAdd DFU suffix to \n" + " -D --delete \t\tDelete DFU suffix from \n" + " -p --pid \t\tAdd product ID into DFU suffix in \n" + " -v --vid \t\tAdd vendor ID into DFU suffix in \n" + " -d --did \t\tAdd device ID into DFU suffix in \n" + " -S --spec \t\tAdd DFU specification ID into DFU suffix in \n" + ); + exit(EX_USAGE); +} + +static void print_version(void) +{ + printf("dfu-suffix (%s) %s\n\n", PACKAGE, PACKAGE_VERSION); + printf("Copyright 2011-2012 Stefan Schmidt, 2013-2014 Tormod Volden\n" + "This program is Free Software and has ABSOLUTELY NO WARRANTY\n" + "Please report bugs to %s\n\n", PACKAGE_BUGREPORT); + +} + +static struct option opts[] = { + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'V' }, + { "check", 1, 0, 'c' }, + { "add", 1, 0, 'a' }, + { "delete", 1, 0, 'D' }, + { "pid", 1, 0, 'p' }, + { "vid", 1, 0, 'v' }, + { "did", 1, 0, 'd' }, + { "spec", 1, 0, 'S' }, +}; + +int main(int argc, char **argv) +{ + struct dfu_file file; + int pid, vid, did, spec; + enum mode mode = MODE_NONE; + + /* make sure all prints are flushed */ + setvbuf(stdout, NULL, _IONBF, 0); + + print_version(); + + pid = vid = did = 0xffff; + spec = 0x0100; /* Default to bcdDFU version 1.0 */ + memset(&file, 0, sizeof(file)); + + while (1) { + int c, option_index = 0; + c = getopt_long(argc, argv, "hVc:a:D:p:v:d:S:s:T", opts, + &option_index); + if (c == -1) + break; + + switch (c) { + case 'h': + help(); + break; + case 'V': + exit(0); + break; + case 'D': + file.name = optarg; + mode = MODE_DEL; + break; + case 'p': + pid = strtol(optarg, NULL, 16); + break; + case 'v': + vid = strtol(optarg, NULL, 16); + break; + case 'd': + did = strtol(optarg, NULL, 16); + break; + case 'S': + spec = strtol(optarg, NULL, 16); + break; + case 'c': + file.name = optarg; + mode = MODE_CHECK; + break; + case 'a': + file.name = optarg; + mode = MODE_ADD; + break; + default: + help(); + break; + } + } + + if (!file.name) { + fprintf(stderr, "You need to specify a filename\n"); + help(); + } + + if (spec != 0x0100 && spec != 0x011a) { + fprintf(stderr, "Only DFU specification 0x0100 and 0x011a supported\n"); + help(); + } + + switch(mode) { + case MODE_ADD: + dfu_load_file(&file, NO_SUFFIX, MAYBE_PREFIX); + file.idVendor = vid; + file.idProduct = pid; + file.bcdDevice = did; + file.bcdDFU = spec; + /* always write suffix, rewrite prefix if there was one */ + dfu_store_file(&file, 1, file.size.prefix != 0); + printf("Suffix successfully added to file\n"); + break; + + case MODE_CHECK: + dfu_load_file(&file, NEEDS_SUFFIX, MAYBE_PREFIX); + show_suffix_and_prefix(&file); + break; + + case MODE_DEL: + dfu_load_file(&file, NEEDS_SUFFIX, MAYBE_PREFIX); + dfu_store_file(&file, 0, file.size.prefix != 0); + if (file.size.suffix) /* had a suffix */ + printf("Suffix successfully removed from file\n"); + break; + + default: + help(); + break; + } + return (0); +} diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/usb_dfu.h b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/usb_dfu.h new file mode 100644 index 0000000..660bedc --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/src/usb_dfu.h @@ -0,0 +1,99 @@ +#ifndef USB_DFU_H +#define USB_DFU_H +/* USB Device Firmware Update Implementation for OpenPCD + * (C) 2006 by Harald Welte + * + * Protocol definitions for USB DFU + * + * This ought to be compliant to the USB DFU Spec 1.0 as available from + * http://www.usb.org/developers/devclass_docs/usbdfu10.pdf + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#define USB_DT_DFU 0x21 + +#ifdef _MSC_VER +# pragma pack(push) +# pragma pack(1) +#endif /* _MSC_VER */ +struct usb_dfu_func_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bmAttributes; +#define USB_DFU_CAN_DOWNLOAD (1 << 0) +#define USB_DFU_CAN_UPLOAD (1 << 1) +#define USB_DFU_MANIFEST_TOL (1 << 2) +#define USB_DFU_WILL_DETACH (1 << 3) + uint16_t wDetachTimeOut; + uint16_t wTransferSize; + uint16_t bcdDFUVersion; +#ifdef _MSC_VER +}; +# pragma pack(pop) +#elif defined __GNUC__ +} __attribute__ ((packed)); +#else + #warning "No way to pack struct on this compiler? This will break!" +#endif /* _MSC_VER */ + +#define USB_DT_DFU_SIZE 9 + +#define USB_TYPE_DFU (LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE) + +/* DFU class-specific requests (Section 3, DFU Rev 1.1) */ +#define USB_REQ_DFU_DETACH 0x00 +#define USB_REQ_DFU_DNLOAD 0x01 +#define USB_REQ_DFU_UPLOAD 0x02 +#define USB_REQ_DFU_GETSTATUS 0x03 +#define USB_REQ_DFU_CLRSTATUS 0x04 +#define USB_REQ_DFU_GETSTATE 0x05 +#define USB_REQ_DFU_ABORT 0x06 + +/* DFU_GETSTATUS bStatus values (Section 6.1.2, DFU Rev 1.1) */ +#define DFU_STATUS_OK 0x00 +#define DFU_STATUS_errTARGET 0x01 +#define DFU_STATUS_errFILE 0x02 +#define DFU_STATUS_errWRITE 0x03 +#define DFU_STATUS_errERASE 0x04 +#define DFU_STATUS_errCHECK_ERASED 0x05 +#define DFU_STATUS_errPROG 0x06 +#define DFU_STATUS_errVERIFY 0x07 +#define DFU_STATUS_errADDRESS 0x08 +#define DFU_STATUS_errNOTDONE 0x09 +#define DFU_STATUS_errFIRMWARE 0x0a +#define DFU_STATUS_errVENDOR 0x0b +#define DFU_STATUS_errUSBR 0x0c +#define DFU_STATUS_errPOR 0x0d +#define DFU_STATUS_errUNKNOWN 0x0e +#define DFU_STATUS_errSTALLEDPKT 0x0f + +enum dfu_state { + DFU_STATE_appIDLE = 0, + DFU_STATE_appDETACH = 1, + DFU_STATE_dfuIDLE = 2, + DFU_STATE_dfuDNLOAD_SYNC = 3, + DFU_STATE_dfuDNBUSY = 4, + DFU_STATE_dfuDNLOAD_IDLE = 5, + DFU_STATE_dfuMANIFEST_SYNC = 6, + DFU_STATE_dfuMANIFEST = 7, + DFU_STATE_dfuMANIFEST_WAIT_RST = 8, + DFU_STATE_dfuUPLOAD_IDLE = 9, + DFU_STATE_dfuERROR = 10 +}; + +#endif /* USB_DFU_H */ diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/www/build.html b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/www/build.html new file mode 100644 index 0000000..f3036e4 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/www/build.html @@ -0,0 +1,147 @@ + + + + + + + Building dfu-util from source + + + + + + + + + +
+

How to build dfu-util from source

+ +

Prerequisites for building from git

+

Mac OS X

+

+First install MacPorts (and if you are on 10.6 or older, the Java Developer Package) and then run: +

+
+	sudo port install libusb-devel git-core
+
+ +

FreeBSD

+
+	sudo pkg_add -r git pkgconf
+
+ +

Ubuntu and Debian and derivatives

+
+	sudo apt-get build-dep dfu-util
+	sudo apt-get install libusb-1.0-0-dev
+
+ +

Get the source code and build it

+

+The first time you will have to clone the git repository: +

+
+	git clone git://gitorious.org/dfu-util/dfu-util.git
+	cd dfu-util
+
+

+If you later want to update to latest git version, just run this: +

+
+	make maintainer-clean
+	git pull
+
+

+To build the source: +

+
+	./autogen.sh
+	./configure  # on most systems
+	make
+
+ +

+If you are building on Mac OS X, replace the ./configure command with: +

+
+	./configure --libdir=/opt/local/lib --includedir=/opt/local/include  # on MacOSX only
+
+ +

+Your dfu-util binary will be inside the src folder. Use it from there, or install it to /usr/local/bin by running "sudo make install". +

+ +

Cross-building for Windows

+ +

+Windows binaries can be built in a MinGW +environment, on a Windows computer or cross-hosted in another OS. +To build it on a Debian or Ubuntu host, first install build dependencies: +

+
+	sudo apt-get build-dep libusb-1.0-0 dfu-util
+	sudo apt-get install mingw32
+
+ +

+The below example builds dfu-util 0.8 and libusb 1.0.19 from unpacked release +tarballs. If you instead build from git, you will have to run "./autogen.sh" +before running the "./configure" steps. +

+ +
+mkdir -p build
+cd libusb-1.0.19
+PKG_CONFIG_PATH=$PWD/../build/lib/pkgconfig ./configure \
+    --host=i586-mingw32msvc --prefix=$PWD/../build
+# WINVER workaround needed for 1.0.19 only
+make CFLAGS="-DWINVER=0x0501"
+make install
+cd ..
+
+cd dfu-util-0.8
+PKG_CONFIG_PATH=$PWD/../build/lib/pkgconfig ./configure \
+    --host=i586-mingw32msvc --prefix=$PWD/../build
+make
+make install
+cd ..
+
+The build files will now be in build/bin. +

+ +

Building on Windows using MinGW

+This assumes using release tarballs or having run ./autogen.sh on +the git sources. +
+cd libusb-1.0.19
+./configure --prefix=$HOME
+# WINVER workaround needed for 1.0.19 only
+# MKDIR_P setting should not really be needed...
+make CFLAGS="-DWINVER=0x0501" MKDIR_P="mkdir -p"
+make install
+cd ..
+
+cd dfu-util-0.8
+./configure USB_CFLAGS="-I$HOME/include/libusb-1.0" \
+            USB_LIBS="-L $HOME/lib -lusb-1.0" PKG_CONFIG=true
+make
+make install
+cd ..
+
+To link libusb statically into dfu-util.exe use instead of "make": +
+make LDFLAGS=-static
+
+The built executables (and DLL) will now be under $HOME/bin. + +

+[Back to dfu-util main page] +

+ +
+ + diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/www/dfu-util.1.html b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/www/dfu-util.1.html new file mode 100644 index 0000000..62ca40b --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/www/dfu-util.1.html @@ -0,0 +1,411 @@ + + +Man page of DFU-UTIL + + +

DFU-UTIL(1)

+ +  +

NAME

+ +dfu-util - Device firmware update (DFU) USB programmer +  +

SYNOPSIS

+ + +
+
+dfu-util + +-l + +[-v] + +[-d + +vid:pid[,vid:pid]] + +[-p + +path] + +[-c + +configuration] + +[-i + +interface] + +[-a + +alt-intf] + +[-S + +serial[,serial]] + + +
+dfu-util + +[-v] + +[-d + +vid:pid[,vid:pid]] + +[-p + +path] + +[-c + +configuration] + +[-i + +interface] + +[-a + +alt-intf] + +[-S + +serial[,serial]] + +[-t + +size] + +[-Z + +size] + +[-s + +address] + +[-R] + +[-D|-U + +file] + + +
+dfu-util + +[-hV] + +
+  +

DESCRIPTION

+ +dfu-util + +is a program that implements the host (computer) side of the USB DFU +(Universal Serial Bus Device Firmware Upgrade) protocol. +

+dfu-util communicates with devices that implement the device side of the +USB DFU protocol, and is often used to upgrade the firmware of such +devices. +  +

OPTIONS

+ +
+
-l, --list + +
+List the currently attached DFU capable USB devices. +
-d, --device [Run-Time VENDOR]:[Run-Time PRODUCT][,[DFU Mode VENDOR]:[DFU Mode PRODUCT]] + +
+
+Specify run-time and/or DFU mode vendor and/or product IDs of the DFU device +to work with. VENDOR and PRODUCT are hexadecimal numbers (no prefix +needed), "*" (match any), or "-" (match nothing). By default, any DFU capable +device in either run-time or DFU mode will be considered. +

+If you only have one standards-compliant DFU device attached to your computer, +this parameter is optional. However, as soon as you have multiple DFU devices +connected, dfu-util will detect this and abort, asking you to specify which +device to use. +

+If only run-time IDs are specified (e.g. "--device 1457:51ab"), then in +addition to the specified run-time IDs, any DFU mode devices will also be +considered. This is beneficial to allow a DFU capable device to be found +again after a switch to DFU mode, since the vendor and/or product ID of a +device usually changes in DFU mode. +

+If only DFU mode IDs are specified (e.g. "--device ,951:26"), then all +run-time devices will be ignored, making it easy to target a specific device in +DFU mode. +

+If both run-time and DFU mode IDs are specified (e.g. "--device +1457:51ab,:2bc"), then unspecified DFU mode components will use the run-time +value specified. +

+Examples: +

+
--device 1457:51ab,951:26 + +
+
+ +Work with a device in run-time mode with +vendor ID 0x1457 and product ID 0x51ab, or in DFU mode with vendor ID 0x0951 +and product ID 0x0026 +

+

--device 1457:51ab,:2bc + +
+
+ +Work with a device in run-time mode with vendor ID 0x1457 and product ID +0x51ab, or in DFU mode with vendor ID 0x1457 and product ID 0x02bc +

+

--device 1457:51ab + +
+
+ +Work with a device in run-time mode with vendor ID 0x1457 and product ID +0x51ab, or in DFU mode with any vendor and product ID +

+

--device ,951:26 + +
+
+ +Work with a device in DFU mode with vendor ID 0x0951 and product ID 0x0026 +

+

--device *,- + +
+
+ +Work with any device in run-time mode, and ignore any device in DFU mode +

+

--device , + +
+
+ +Ignore any device in run-time mode, and Work with any device in DFU mode +
+
+ +
-p, --path BUS-PORT. ... .PORT + +
+Specify the path to the DFU device. +
-c, --cfg CONFIG-NR + +
+Specify the configuration of the DFU device. Note that this is only used for matching, the configuration is not set by dfu-util. +
-i, --intf INTF-NR + +
+Specify the DFU interface number. +
-a, --alt ALT + +
+Specify the altsetting of the DFU interface by name or by number. +
-S, --serial [Run-Time SERIAL][,[DFU Mode SERIAL]] + +
+Specify the run-time and DFU mode serial numbers used to further restrict +device matches. If multiple, identical DFU devices are simultaneously +connected to a system then vendor and product ID will be insufficient for +targeting a single device. In this situation, it may be possible to use this +parameter to specify a serial number which also must match. +

+If only a single serial number is specified, then the same serial number is +used in both run-time and DFU mode. An empty serial number will match any +serial number in the corresponding mode. +

-t, --transfer-size SIZE + +
+Specify the number of bytes per USB transfer. The optimal value is +usually determined automatically so this option is rarely useful. If +you need to use this option for a device, please report it as a bug. +
-Z, --upload-size SIZE + +
+Specify the expected upload size, in bytes. +
-U, --upload FILE + +
+Read firmware from device into +FILE. + +
-D, --download FILE + +
+Write firmware from +FILE + +into device. +
-R, --reset + +
+Issue USB reset signalling after upload or download has finished. +
-s, --dfuse-address address + +
+Specify target address for raw binary download/upload on DfuSe devices. Do +not + +use this for downloading DfuSe (.dfu) files. Modifiers can be added +to the address, separated by a colon, to perform special DfuSE commands such +as "leave" DFU mode, "unprotect" and "mass-erase" flash memory. +
-v, --verbose + +
+Print more information about dfu-util's operation. A second +-v + +will turn on verbose logging of USB requests. Repeat this option to further +increase verbosity. +
-h, --help + +
+Show a help text and exit. +
-V, --version + +
+Show version information and exit. +
+  +

EXAMPLES

+ +  +

Using dfu-util in the OpenMoko project

+ +(with the Neo1973 hardware) +

+ +Flashing the rootfs: +
+ + $ dfu-util -a rootfs -R -D /path/to/openmoko-devel-image.jffs2 + +

+ +Flashing the kernel: +
+ + $ dfu-util -a kernel -R -D /path/to/uImage + +

+ +Flashing the bootloader: +
+ + $ dfu-util -a u-boot -R -D /path/to/u-boot.bin + +

+ +Copying a kernel into RAM: +
+ + $ dfu-util -a 0 -R -D /path/to/uImage + +

+Once this has finished, the kernel will be available at the default load +address of 0x32000000 in Neo1973 RAM. +Note: + +You cannot transfer more than 2MB of data into RAM using this method. +

+  +

Using dfu-util with a DfuSe device

+ +

+ +Flashing a +.dfu + +(special DfuSe format) file to the device: +
+ + $ dfu-util -a 0 -D /path/to/dfuse-image.dfu + +

+ +Reading out 1 KB of flash starting at address 0x8000000: +
+ + $ dfu-util -a 0 -s 0x08000000:1024 -U newfile.bin + +

+ +Flashing a binary file to address 0x8004000 of device memory and +ask the device to leave DFU mode: +
+ + $ dfu-util -a 0 -s 0x08004000:leave -D /path/to/image.bin + + +  +

BUGS

+ +Please report any bugs to the dfu-util mailing list at +dfu-util@lists.gnumonks.org. + +Please use the +--verbose option (repeated as necessary) to provide more + +information in your bug report. +  +

SEE ALSO

+ +The dfu-util home page is +http://dfu-util.gnumonks.org + +  +

HISTORY

+ +dfu-util was originally written for the OpenMoko project by +Weston Schmidt <weston_schmidt@yahoo.com> and +Harald Welte <hwelte@hmw-consulting.de>. Over time, nearly complete +support of DFU 1.0, DFU 1.1 and DfuSe ("1.1a") has been added. +  +

LICENCE

+ +dfu-util + +is covered by the GNU General Public License (GPL), version 2 or later. +  +

COPYRIGHT

+ +This manual page was originally written by Uwe Hermann <uwe@hermann-uwe.de>, +and is now part of the dfu-util project. +

+ +


+ 

Index

+
+
NAME
+
SYNOPSIS
+
DESCRIPTION
+
OPTIONS
+
EXAMPLES
+
+
Using dfu-util in the OpenMoko project
+
Using dfu-util with a DfuSe device
+
+
BUGS
+
SEE ALSO
+
HISTORY
+
LICENCE
+
COPYRIGHT
+
+
+This document was created by man2html, +using the doc/dfu-util.1 manual page from dfu-util 0.8.
+Time: 14:40:57 GMT, September 13, 2014 + + diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/www/dfuse.html b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/www/dfuse.html new file mode 100644 index 0000000..35e4ffa --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/www/dfuse.html @@ -0,0 +1,135 @@ + + + + + + DfuSe and dfu-util + + + + + + + + + +
+

Using dfu-util with DfuSe devices

+

DfuSe

+

+ DfuSe (DFU with ST Microsystems extensions) is a protocol based on + DFU 1.1. However, in expanding the functionality of the DFU protocol, + ST Microsystems broke all compatibility with the DFU 1.1 standard. + DfuSe devices report the DFU version as "1.1a". +

+

+ DfuSe can be used to download firmware and other data + from a host computer to a conforming device (or upload in the + opposite direction) over USB similar to standard DFU. +

+

+ The main difference from standard DFU is that the target address in + the device (flash) memory is specified by the host, so that a + download can be performed to parts of the device memory. The host + program is also responsible for erasing flash pages before they + are written to. +

+

.dfu files

+

+ A special file format is defined by ST Microsystems to carry firmware + for DfuSe devices. The file contains target information such as address + and alternate interface information in addition to the binary data. + Several blocks of binary data can be combined in one .dfu file. +

+

Alternate interfaces

+

+ Different memory locations of the device may have different + characteristics that the host program (dfu-util) has to take + into considerations, such as flash memory page size, read-only + versus read-write segments, the need to erase, and so on. + These parameters are reported by the device in the string + descriptors meant for describing the USB interfaces. + The host program decodes these strings to build a memory map of + the device. Different memory units or address spaces are listed + in separate alternate interface settings that must be selected + according to the memory unit to access. +

+

+ Note that dfu-util leaves it to the user to select alternate + interface. When parsing a .dfu file it will skip file segments + not matching the selected alternate interface. Also, some + DfuSe device firmware implementations ignore the setting of + alternate interface and deduct the memory unit from the + address, since they have no address space overlap. +

+

DfuSe special commands

+

+ DfuSe special commands are used by the host program during normal + downloads or uploads, such as SET_ADDRESS and ERASE_PAGE. Also + the normal DFU_DNLOAD and DFU_UPLOAD commands have special + implementations in DfuSe. + Many DfuSe devices also support commands to leave DFU mode, + read unprotect the flash memory or mass erase the flash memory. + dfu-util (from version 0.7) + supports adding "leave", "unprotect", or "mass-erase" + to the -s option argument to send such requests in combination + with a download request. These modifiers are separated with a colon. +

+

+ Some DfuSe devices have their DfuSe bootloader running from flash + memory. Erasing the whole flash memory would therefore destroy + the DfuSe bootloader itself and practically brick the device + for most users. Any use of modifiers such as "unprotect" + and "mass-erase" therefore needs to be combined with the "force" + modifer. This is not included in the examples, to not encourage + ignorant users to copy and paste such instructions and shoot + themselves in the foot. +

+

+ Devices based on for instance STM32F103 all run the bootloader + from flash, since there is no USB bootloader in ROM. +

+

+ For instance STM32F107, STM32F2xx and STM32F4xx devices have a + DfuSe bootloader in ROM, so the flash can be erased while + keeping the device available for USB DFU transfers as long + as the device designers use this built-in bootloader and have + not implemented another DfuSe bootloader in flash that the user is + dependent upon. +

+

+ Well-written bootloaders running from flash will report their + own memory region as read-only and not eraseable, but this does + not prevent dfu-util from sending a "unprotect" or "mass-erase" + request which overrides this, if the user insists. +

+

Example usage

+

+ Flashing a .dfu (special DfuSe format) file to the device: +

+
+         $ dfu-util -a 0 -D /path/to/dfuse-image.dfu
+	
+

+ Reading out 1 KB of flash starting at address 0x8000000: +

+
+         $ dfu-util -a 0 -s 0x08000000:1024 -U newfile.bin
+	
+

+ Flashing a binary file to address 0x8004000 of device memory and ask + the device to leave DFU mode: +

+
+         $ dfu-util -a 0 -s 0x08004000:leave -D /path/to/image.bin
+	
+

+ [Back to dfu-util main page] +

+ +
+ + diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/www/index.html b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/www/index.html new file mode 100644 index 0000000..108ddaf --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/www/index.html @@ -0,0 +1,119 @@ + + + + + + dfu-util Homepage + + + + + + + + + +
+

dfu-util - Device Firmware Upgrade Utilities

+

Description

+

+ dfu-util is a host side implementation of the DFU 1.0 and DFU 1.1 specifications of the USB forum. + + DFU is intended to download and upload firmware to/from devices connected + over USB. It ranges from small devices like micro-controller boards + to mobile phones. Using dfu-util you can download firmware to your + DFU-enabled device or upload firmware from it. dfu-util has been + tested with the Openmoko Neo1973 and Freerunner and many other devices. +

+

+ See the manual page for examples of use. +

+

Supported Devices

+ +

Releases

+

+ Releases of the dfu-util software can be found in the + releases folder. + The current release is 0.8. +

+

+ We offer binaries for Microsoft Windows and some other platforms. + dfu-util uses libusb 1.0 to access your device, so + on Windows you have to register the device with the WinUSB driver + (alternatively libusb-win32 or libusbK), please see the libusbx wiki + for more details. +

+

+ Mac OS X users can also get dfu-util from Homebrew with "brew install dfu-util" or from MacPorts. +

+

+ Most Linux distributions ship dfu-util in binary packages for those + who do not want to compile dfu-util from source. + On Debian, Ubuntu, Fedora and Gentoo you can install it through the + normal software package tools. For other distributions +(namely OpenSuSe, Mandriva, and CentOS) Holger Freyther was kind enough to +provide binary packages through the Open Build Service. +

+

Development

+

+ Development happens in a GIT repository. Browse it via the web +interface or clone it with: +

+
+	git clone git://gitorious.org/dfu-util/dfu-util.git
+	
+

+ See our build instructions for how to + build the source on different platforms. +

+

License

+

+ This software is licensed under the GPL version 2. +

+

Contact

+

+ If you have questions about the development or use of dfu-util please + send an e-mail to our dedicated +mailing list for dfu-util. +

+

People

+

+ dfu-util was originally written by + Harald Welte partially based on code from + dfu-programmer 0.4 and is currently maintained by Stefan Schmidt and + Tormod Volden. +

+ +
+ + diff --git a/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/www/simple.css b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/www/simple.css new file mode 100644 index 0000000..98100bc --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/dfu-util/www/simple.css @@ -0,0 +1,56 @@ +body { + margin: 10px; + font-size: 0.82em; + background-color: #EEE; +} + +h1 { + clear: both; + padding: 0 0 12px 0; + margin: 0; + font-size: 2em; + font-weight: bold; +} + +h2 { + clear: both; + margin: 0; + font-size: 1.5em; + font-weight: normal; +} + +h3 { + clear: both; + margin: 15px 0 0 0; + font-size: 1.0em; + font-weight: bold; +} + +p { + line-height: 20px; + padding: 8px 0 8px 0; + margin: 0; + font-size: 1.1em; +} + +pre { + white-space: pre-wrap; + background-color: #CCC; + padding: 3px; +} + +a:hover { + background-color: #DDD; +} + +#middlebox { + width: 600px; + margin: 0px auto; + text-align: left; +} + +#footer { + height: 100px; + padding: 28px 3px 0 0; + margin: 20px 0 20px 0; +} diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/README.md b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/README.md new file mode 100644 index 0000000..c6c9379 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/README.md @@ -0,0 +1,5 @@ +These files build the maple_loader.jar file used on Windows to reset the Sketch via USB Serial, so that the bootloader will run in dfu upload mode, ready for a new sketch to be uploaded + +The files were written by @bobC (github) and have been slightly modified by me (Roger Clark), so that dfu-util no longer attempts to reset the board after upload. +This change to dfu-util's reset command line argument, was required because dfu-util was showing errors on some Windows systems, because the bootloader had reset its self after upload, +before dfu-util had chance to tell it to reset. \ No newline at end of file diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build.xml b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build.xml new file mode 100644 index 0000000..80bdd6f --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + Builds, tests, and runs the project maple_loader. + + + diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/built-jar.properties b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/built-jar.properties new file mode 100644 index 0000000..10752d5 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/built-jar.properties @@ -0,0 +1,4 @@ +#Mon, 20 Jul 2015 11:21:26 +1000 + + +C\:\\Users\\rclark\\Desktop\\maple-asp-master\\installer\\maple_loader= diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/CliTemplate/CliMain.class b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/CliTemplate/CliMain.class new file mode 100644 index 0000000..37ee630 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/CliTemplate/CliMain.class differ diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/CliTemplate/DFUUploader.class b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/CliTemplate/DFUUploader.class new file mode 100644 index 0000000..77087b0 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/CliTemplate/DFUUploader.class differ diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/CliTemplate/ExecCommand.class b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/CliTemplate/ExecCommand.class new file mode 100644 index 0000000..ad95f79 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/CliTemplate/ExecCommand.class differ diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/processing/app/Base.class b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/processing/app/Base.class new file mode 100644 index 0000000..4aa0bde Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/processing/app/Base.class differ diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/processing/app/Preferences.class b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/processing/app/Preferences.class new file mode 100644 index 0000000..89cf010 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/processing/app/Preferences.class differ diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/processing/app/Serial.class b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/processing/app/Serial.class new file mode 100644 index 0000000..cceccdd Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/processing/app/Serial.class differ diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/processing/app/SerialException.class b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/processing/app/SerialException.class new file mode 100644 index 0000000..71048dd Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/processing/app/SerialException.class differ diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/processing/app/debug/MessageConsumer.class b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/processing/app/debug/MessageConsumer.class new file mode 100644 index 0000000..37250e7 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/processing/app/debug/MessageConsumer.class differ diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/processing/app/debug/MessageSiphon.class b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/processing/app/debug/MessageSiphon.class new file mode 100644 index 0000000..e22c8d4 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/processing/app/debug/MessageSiphon.class differ diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/processing/app/debug/RunnerException.class b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/processing/app/debug/RunnerException.class new file mode 100644 index 0000000..710f796 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/processing/app/debug/RunnerException.class differ diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/processing/app/helpers/ProcessUtils.class b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/processing/app/helpers/ProcessUtils.class new file mode 100644 index 0000000..27eca62 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/build/classes/processing/app/helpers/ProcessUtils.class differ diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/dist/README.TXT b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/dist/README.TXT new file mode 100644 index 0000000..255b89c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/dist/README.TXT @@ -0,0 +1,32 @@ +======================== +BUILD OUTPUT DESCRIPTION +======================== + +When you build an Java application project that has a main class, the IDE +automatically copies all of the JAR +files on the projects classpath to your projects dist/lib folder. The IDE +also adds each of the JAR files to the Class-Path element in the application +JAR files manifest file (MANIFEST.MF). + +To run the project from the command line, go to the dist folder and +type the following: + +java -jar "maple_loader.jar" + +To distribute this project, zip up the dist folder (including the lib folder) +and distribute the ZIP file. + +Notes: + +* If two JAR files on the project classpath have the same name, only the first +JAR file is copied to the lib folder. +* Only JAR files are copied to the lib folder. +If the classpath contains other types of files or folders, these files (folders) +are not copied. +* If a library on the projects classpath also has a Class-Path element +specified in the manifest,the content of the Class-Path element has to be on +the projects runtime path. +* To set a main class in a standard Java project, right-click the project node +in the Projects window and choose Properties. Then click Run and enter the +class name in the Main Class field. Alternatively, you can manually type the +class name in the manifest Main-Class element. diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/dist/lib/jssc.jar b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/dist/lib/jssc.jar new file mode 100644 index 0000000..eb74f15 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/dist/lib/jssc.jar differ diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/dist/maple_loader.jar b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/dist/maple_loader.jar new file mode 100644 index 0000000..e1f9965 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/dist/maple_loader.jar differ diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/jars/jssc.jar b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/jars/jssc.jar new file mode 100644 index 0000000..eb74f15 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/jars/jssc.jar differ diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/manifest.mf b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/manifest.mf new file mode 100644 index 0000000..328e8e5 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/manifest.mf @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +X-COMMENT: Main-Class will be added automatically by build + diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/nbproject/build-impl.xml b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/nbproject/build-impl.xml new file mode 100644 index 0000000..a66f349 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/nbproject/build-impl.xml @@ -0,0 +1,1413 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set src.dir + Must set test.src.dir + Must set build.dir + Must set dist.dir + Must set build.classes.dir + Must set dist.javadoc.dir + Must set build.test.classes.dir + Must set build.test.results.dir + Must set build.classes.excludes + Must set dist.jar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + No tests executed. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set JVM to use for profiling in profiler.info.jvm + Must set profiler agent JVM arguments in profiler.info.jvmargs.agent + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + To run this application from the command line without Ant, try: + + java -jar "${dist.jar.resolved}" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set run.class + + + + Must select one file in the IDE or set run.class + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set debug.class + + + + + Must select one file in the IDE or set debug.class + + + + + Must set fix.includes + + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + Must select one file in the IDE or set profile.class + This target only works when run from inside the NetBeans IDE. + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set run.class + + + + + + Must select some files in the IDE or set test.includes + + + + + Must select one file in the IDE or set run.class + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + Some tests failed; see details above. + + + + + + + + + Must select some files in the IDE or set test.includes + + + + Some tests failed; see details above. + + + + Must select some files in the IDE or set test.class + Must select some method in the IDE or set test.method + + + + Some tests failed; see details above. + + + + + Must select one file in the IDE or set test.class + + + + Must select one file in the IDE or set test.class + Must select some method in the IDE or set test.method + + + + + + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/nbproject/genfiles.properties b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/nbproject/genfiles.properties new file mode 100644 index 0000000..c136721 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=2e6a03ba +build.xml.script.CRC32=4676ee6b +build.xml.stylesheet.CRC32=8064a381@1.75.2.48 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=2e6a03ba +nbproject/build-impl.xml.script.CRC32=392b3f79 +nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.75.2.48 diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/nbproject/private/config.properties b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/nbproject/private/config.properties new file mode 100644 index 0000000..e69de29 diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/nbproject/private/private.properties b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/nbproject/private/private.properties new file mode 100644 index 0000000..e5c9f10 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/nbproject/private/private.properties @@ -0,0 +1,6 @@ +compile.on.save=true +do.depend=false +do.jar=true +javac.debug=true +javadoc.preview=true +user.properties.file=C:\\Users\\rclark\\AppData\\Roaming\\NetBeans\\8.0.2\\build.properties diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/nbproject/private/private.xml b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/nbproject/private/private.xml new file mode 100644 index 0000000..a1bbd60 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/nbproject/private/private.xml @@ -0,0 +1,10 @@ + + + + + + file:/C:/Users/rclark/Desktop/maple-asp-master/installer/maple_loader/src/CliTemplate/CliMain.java + file:/C:/Users/rclark/Desktop/maple-asp-master/installer/maple_loader/src/CliTemplate/DFUUploader.java + + + diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/nbproject/project.properties b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/nbproject/project.properties new file mode 100644 index 0000000..7f48d71 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/nbproject/project.properties @@ -0,0 +1,79 @@ +annotation.processing.enabled=true +annotation.processing.enabled.in.editor=false +annotation.processing.processors.list= +annotation.processing.run.all.processors=true +annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output +application.title=maple_loader +application.vendor=bob +build.classes.dir=${build.dir}/classes +build.classes.excludes=**/*.java,**/*.form +# This directory is removed when the project is cleaned: +build.dir=build +build.generated.dir=${build.dir}/generated +build.generated.sources.dir=${build.dir}/generated-sources +# Only compile against the classpath explicitly listed here: +build.sysclasspath=ignore +build.test.classes.dir=${build.dir}/test/classes +build.test.results.dir=${build.dir}/test/results +# Uncomment to specify the preferred debugger connection transport: +#debug.transport=dt_socket +debug.classpath=\ + ${run.classpath} +debug.test.classpath=\ + ${run.test.classpath} +# Files in build.classes.dir which should be excluded from distribution jar +dist.archive.excludes= +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.jar=${dist.dir}/maple_loader.jar +dist.javadoc.dir=${dist.dir}/javadoc +endorsed.classpath= +excludes= +file.reference.jssc.jar=dist/lib/jssc.jar +file.reference.jssc.jar-1=jars/jssc.jar +includes=** +jar.compress=false +javac.classpath=\ + ${file.reference.jssc.jar}:\ + ${file.reference.jssc.jar-1} +# Space-separated list of extra javac options +javac.compilerargs= +javac.deprecation=false +javac.processorpath=\ + ${javac.classpath} +javac.source=1.7 +javac.target=1.7 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +javac.test.processorpath=\ + ${javac.test.classpath} +javadoc.additionalparam= +javadoc.author=false +javadoc.encoding=${source.encoding} +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +main.class=CliTemplate.CliMain +manifest.file=manifest.mf +meta.inf.dir=${src.dir}/META-INF +mkdist.disabled=false +platform.active=default_platform +run.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +# Space-separated list of JVM arguments used when running the project. +# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value. +# To set system properties for unit tests define test-sys-prop.name=value: +run.jvmargs= +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +source.encoding=UTF-8 +src.dir=src +test.src.dir=test diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/nbproject/project.xml b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/nbproject/project.xml new file mode 100644 index 0000000..92218a9 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/nbproject/project.xml @@ -0,0 +1,15 @@ + + + org.netbeans.modules.java.j2seproject + + + maple_loader + + + + + + + + + diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/CliTemplate/CliMain.java b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/CliTemplate/CliMain.java new file mode 100644 index 0000000..c7dc9f0 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/CliTemplate/CliMain.java @@ -0,0 +1,60 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package CliTemplate; + +import java.io.IOException; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import processing.app.Preferences; + +//import processing.app.I18n; +import processing.app.helpers.ProcessUtils; + +/** + * + * @author cousinr + */ +public class CliMain { + + + /** + * @param args the command line arguments + */ + public static void main(String[] args) { + + String comPort = args[0]; // + String altIf = args[1]; // + String usbID = args[2]; // "1EAF:0003"; + String binFile = args[3]; // bin file + + System.out.println("maple_loader v0.1"); + + Preferences.set ("serial.port",comPort); + Preferences.set ("serial.parity","N"); + Preferences.setInteger ("serial.databits", 8); + Preferences.setInteger ("serial.debug_rate",9600); + Preferences.setInteger ("serial.stopbits",1); + + Preferences.setInteger ("programDelay",1200); + + Preferences.set ("upload.usbID", usbID); + Preferences.set ("upload.altID", altIf); + Preferences.setBoolean ("upload.auto_reset", true); + Preferences.setBoolean ("upload.verbose", false); + + // + DFUUploader dfuUploader = new DFUUploader(); + try { + //dfuUploader.uploadViaDFU(binFile); + dfuUploader.uploadViaDFU(binFile); + } catch (Exception e) + { + System.err.print (MessageFormat.format("an error occurred! {0}\n", e.getMessage())); + } + } +} diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/CliTemplate/DFUUploader.java b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/CliTemplate/DFUUploader.java new file mode 100644 index 0000000..3dee0b4 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/CliTemplate/DFUUploader.java @@ -0,0 +1,345 @@ +/* + DFUUploader - uploader implementation using DFU + + Copyright (c) 2010 + Andrew Meyer + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +package CliTemplate; + +import java.io.BufferedReader; +import java.io.File; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import processing.app.Preferences; +import processing.app.Serial; +import processing.app.debug.MessageConsumer; +import processing.app.debug.MessageSiphon; +import processing.app.debug.RunnerException; + +/** + * + * @author bob + */ +public class DFUUploader implements MessageConsumer { + + boolean firstErrorFound; + boolean secondErrorFound; + // part of the PdeMessageConsumer interface + boolean notFoundError; + boolean verbose; + RunnerException exception; + + static final String SUPER_BADNESS = + "Compiler error!"; + + public boolean uploadUsingPreferences(String binPath, boolean verbose) + throws RunnerException { + + this.verbose = verbose; + + return uploadViaDFU(binPath); + } + + // works with old and new versions of dfu-util + private boolean found_device (String dfuData, String usbID) + { + return dfuData.contains(("Found DFU: [0x"+usbID.substring(0,4)).toUpperCase()) || + dfuData.contains(("Found DFU: ["+usbID.substring(0,4)).toUpperCase()); + } + + public boolean uploadViaDFU (String binPath) + throws RunnerException { + + this.verbose = Preferences.getBoolean ("upload.verbose"); + + /* todo, check for size overruns! */ + String fileType="bin"; + + if (fileType.equals("bin")) { + String usbID = Preferences.get("upload.usbID"); + if (usbID == null) { + /* fall back on default */ + /* this isnt great because is default Avrdude or dfu-util? */ + usbID = Preferences.get("upload.usbID"); + } + + /* if auto-reset, then emit the reset pulse on dtr/rts */ + if (Preferences.get("upload.auto_reset") != null) { + if (Preferences.get("upload.auto_reset").toLowerCase().equals("true")) { + System.out.println("Resetting to bootloader via DTR pulse"); + emitResetPulse(); + } + } else { + System.out.println("Resetting to bootloader via DTR pulse"); + emitResetPulse(); + } + + String dfuList = new String(); + List commandCheck = new ArrayList(); + commandCheck.add("dfu-util"); + commandCheck.add("-l"); + long startChecking = System.currentTimeMillis(); + System.out.println("Searching for DFU device [" + usbID + "]..."); + do { + try { + Thread.sleep(100); + } catch (InterruptedException e) {} + dfuList = executeCheckCommand(commandCheck); + //System.out.println(dfuList); + } + while ( !found_device (dfuList.toUpperCase(), usbID) && (System.currentTimeMillis() - startChecking < 7000)); + + if ( !found_device (dfuList.toUpperCase(), usbID) ) + { + System.out.println(dfuList); + System.err.println("Couldn't find the DFU device: [" + usbID + "]"); + return false; + } + System.out.println("Found it!"); + + /* todo, add handle to let user choose altIf at upload time! */ + String altIf = Preferences.get("upload.altID"); + + List commandDownloader = new ArrayList(); + commandDownloader.add("dfu-util"); + commandDownloader.add("-a "+altIf); + commandDownloader.add("-R"); + commandDownloader.add("-d "+usbID); + commandDownloader.add("-D"+ binPath); //"./thisbin.bin"); + + return executeUploadCommand(commandDownloader); + } + + System.err.println("Only .bin files are supported at this time"); + return false; + } + + /* we need to ensure both RTS and DTR are low to start, + then pulse DTR on its own. This is the reset signal + maple responds to + */ + private void emitResetPulse() throws RunnerException { + + /* wait a while for the device to reboot */ + int programDelay = Preferences.getInteger("programDelay"); + + try { + Serial serialPort = new Serial(); + + // try to toggle DTR/RTS (old scheme) + serialPort.setRTS(false); + serialPort.setDTR(false); + serialPort.setDTR(true); + try { + Thread.sleep(50); + } catch (InterruptedException e) {} + serialPort.setDTR(false); + + // try magic number + serialPort.setRTS(true); + serialPort.setDTR(true); + try { + Thread.sleep(50); + } catch (InterruptedException e) {} + serialPort.setDTR(false); + try { + Thread.sleep(50); + } catch (InterruptedException e) {} + serialPort.write("1EAF"); + try { + Thread.sleep(50); + } catch (InterruptedException e) {} + serialPort.dispose(); + + } catch(Exception e) { + System.err.println("Reset via USB Serial Failed! Did you select the right serial port?\nAssuming the board is in perpetual bootloader mode and continuing to attempt dfu programming...\n"); + } + } + + protected String executeCheckCommand(Collection commandDownloader) + throws RunnerException + { + firstErrorFound = false; // haven't found any errors yet + secondErrorFound = false; + notFoundError = false; + int result=0; // pre-initialized to quiet a bogus warning from jikes + + String userdir = System.getProperty("user.dir") + File.separator; + String returnStr = new String(); + + try { + String[] commandArray = new String[commandDownloader.size()]; + commandDownloader.toArray(commandArray); + + String armBasePath; + + //armBasePath = new String(Base.getHardwarePath() + "/tools/arm/bin/"); + armBasePath = ""; + + commandArray[0] = armBasePath + commandArray[0]; + + if (verbose || Preferences.getBoolean("upload.verbose")) { + for(int i = 0; i < commandArray.length; i++) { + System.out.print(commandArray[i] + " "); + } + System.out.println(); + } + + Process process = Runtime.getRuntime().exec(commandArray); + BufferedReader stdInput = new BufferedReader(new + InputStreamReader(process.getInputStream())); + BufferedReader stdError = new BufferedReader(new + InputStreamReader(process.getErrorStream())); + + // wait for the process to finish. if interrupted + // before waitFor returns, continue waiting + // + boolean busy = true; + while (busy) { + try { + result = process.waitFor(); + busy = false; + } catch (InterruptedException intExc) { + } + } + + String s; + while ((s = stdInput.readLine()) != null) { + returnStr += s + "\n"; + } + + process.destroy(); + + if(exception!=null) { + exception.hideStackTrace(); + throw exception; + } + if(result!=0) return "Error!"; + } catch (Exception e) { + e.printStackTrace(); + } + //System.out.println("result2 is "+result); + // if the result isn't a known, expected value it means that something + // is fairly wrong, one possibility is that jikes has crashed. + // + if (exception != null) throw exception; + + if ((result != 0) && (result != 1 )) { + exception = new RunnerException(SUPER_BADNESS); + } + + return returnStr; // ? true : false; + + } + + // Need to overload this from Uploader to use the system-wide dfu-util + protected boolean executeUploadCommand(Collection commandDownloader) + throws RunnerException + { + firstErrorFound = false; // haven't found any errors yet + secondErrorFound = false; + notFoundError = false; + int result=0; // pre-initialized to quiet a bogus warning from jikes + + String userdir = System.getProperty("user.dir") + File.separator; + + try { + String[] commandArray = new String[commandDownloader.size()]; + commandDownloader.toArray(commandArray); + + String armBasePath; + + //armBasePath = new String(Base.getHardwarePath() + "/tools/arm/bin/"); + armBasePath = ""; + + commandArray[0] = armBasePath + commandArray[0]; + + if (verbose || Preferences.getBoolean("upload.verbose")) { + for(int i = 0; i < commandArray.length; i++) { + System.out.print(commandArray[i] + " "); + } + System.out.println(); + } + + Process process = Runtime.getRuntime().exec(commandArray); + new MessageSiphon(process.getInputStream(), this); + new MessageSiphon(process.getErrorStream(), this); + + // wait for the process to finish. if interrupted + // before waitFor returns, continue waiting + // + boolean compiling = true; + while (compiling) { + try { + result = process.waitFor(); + compiling = false; + } catch (InterruptedException intExc) { + } + } + if(exception!=null) { + exception.hideStackTrace(); + throw exception; + } + if(result!=0) + return false; + } catch (Exception e) { + e.printStackTrace(); + } + //System.out.println("result2 is "+result); + // if the result isn't a known, expected value it means that something + // is fairly wrong, one possibility is that jikes has crashed. + // + if (exception != null) throw exception; + + if ((result != 0) && (result != 1 )) { + exception = new RunnerException(SUPER_BADNESS); + //editor.error(exception); + //PdeBase.openURL(BUGS_URL); + //throw new PdeException(SUPER_BADNESS); + } + + return (result == 0); // ? true : false; + + } + + // deal with messages from dfu-util... + public void message(String s) { + + if(s.indexOf("dfu-util - (C) ") != -1) { return; } + if(s.indexOf("This program is Free Software and has ABSOLUTELY NO WARRANTY") != -1) { return; } + + if(s.indexOf("No DFU capable USB device found") != -1) { + System.err.print(s); + exception = new RunnerException("Problem uploading via dfu-util: No Maple found"); + return; + } + + if(s.indexOf("Operation not perimitted") != -1) { + System.err.print(s); + exception = new RunnerException("Problem uploading via dfu-util: Insufficient privilages"); + return; + } + + // else just print everything... + System.out.print(s); + } + +} diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/CliTemplate/ExecCommand.java b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/CliTemplate/ExecCommand.java new file mode 100644 index 0000000..3d6c106 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/CliTemplate/ExecCommand.java @@ -0,0 +1,119 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package CliTemplate; + +import java.io.IOException; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.List; + +import processing.app.debug.MessageConsumer; +import processing.app.debug.MessageSiphon; +import processing.app.debug.RunnerException; +import processing.app.helpers.ProcessUtils; + +/** + * + * @author cousinr + */ +public class ExecCommand implements MessageConsumer { + + private boolean verbose = true; + private boolean firstErrorFound; + private boolean secondErrorFound; + private RunnerException exception; + + /** + * Either succeeds or throws a RunnerException fit for public consumption. + * + * @param command + * @throws RunnerException + */ + public void execAsynchronously(String[] command) throws RunnerException { + + // eliminate any empty array entries + List stringList = new ArrayList<>(); + for (String string : command) { + string = string.trim(); + if (string.length() != 0) + stringList.add(string); + } + command = stringList.toArray(new String[stringList.size()]); + if (command.length == 0) + return; + int result = 0; + + if (verbose) { + for (String c : command) + System.out.print(c + " "); + System.out.println(); + } + + firstErrorFound = false; // haven't found any errors yet + secondErrorFound = false; + + Process process; + try { + process = ProcessUtils.exec(command); + } catch (IOException e) { + RunnerException re = new RunnerException(e.getMessage()); + re.hideStackTrace(); + throw re; + } + + MessageSiphon in = new MessageSiphon(process.getInputStream(), this); + MessageSiphon err = new MessageSiphon(process.getErrorStream(), this); + + // wait for the process to finish. if interrupted + // before waitFor returns, continue waiting + boolean compiling = true; + while (compiling) { + try { + in.join(); + err.join(); + result = process.waitFor(); + //System.out.println("result is " + result); + compiling = false; + } catch (InterruptedException ignored) { } + } + + // an error was queued up by message(), barf this back to compile(), + // which will barf it back to Editor. if you're having trouble + // discerning the imagery, consider how cows regurgitate their food + // to digest it, and the fact that they have five stomaches. + // + //System.out.println("throwing up " + exception); + if (exception != null) + throw exception; + + if (result > 1) { + // a failure in the tool (e.g. unable to locate a sub-executable) + System.err.println(MessageFormat.format("{0} returned {1}", command[0], result)); + } + + if (result != 0) { + RunnerException re = new RunnerException(MessageFormat.format("exit code: {0}", result)); + re.hideStackTrace(); + throw re; + } + } + + /** + * Part of the MessageConsumer interface, this is called + * whenever a piece (usually a line) of error message is spewed + * out from the compiler. The errors are parsed for their contents + * and line number, which is then reported back to Editor. + * @param s + */ + @Override + public void message(String s) { + int i; + + + System.err.print(s); + } + +} diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/processing/app/Base.java b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/processing/app/Base.java new file mode 100644 index 0000000..c3a174d --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/processing/app/Base.java @@ -0,0 +1,53 @@ +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2004-10 Ben Fry and Casey Reas + Copyright (c) 2001-04 Massachusetts Institute of Technology + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +package processing.app; + + +/** + * The base class for the main processing application. + * Primary role of this class is for platform identification and + * general interaction with the system (launching URLs, loading + * files and images, etc) that comes from that. + */ +public class Base { + + /** + * returns true if running on windows. + */ + static public boolean isWindows() { + //return PApplet.platform == PConstants.WINDOWS; + return System.getProperty("os.name").indexOf("Windows") != -1; + } + + + /** + * true if running on linux. + */ + static public boolean isLinux() { + //return PApplet.platform == PConstants.LINUX; + return System.getProperty("os.name").indexOf("Linux") != -1; + } + + + +} diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/processing/app/Preferences.java b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/processing/app/Preferences.java new file mode 100644 index 0000000..6368e38 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/processing/app/Preferences.java @@ -0,0 +1,157 @@ +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2004-09 Ben Fry and Casey Reas + Copyright (c) 2001-04 Massachusetts Institute of Technology + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +package processing.app; + +import java.io.*; +import java.util.*; + + +/** + * Storage class for user preferences and environment settings. + *

+ * This class no longer uses the Properties class, since + * properties files are iso8859-1, which is highly likely to + * be a problem when trying to save sketch folders and locations. + *

+ * The GUI portion in here is really ugly, as it uses exact layout. This was + * done in frustration one evening (and pre-Swing), but that's long since past, + * and it should all be moved to a proper swing layout like BoxLayout. + *

+ * This is very poorly put together, that the preferences panel and the actual + * preferences i/o is part of the same code. But there hasn't yet been a + * compelling reason to bother with the separation aside from concern about + * being lectured by strangers who feel that it doesn't look like what they + * learned in CS class. + *

+ * Would also be possible to change this to use the Java Preferences API. + * Some useful articles + * here and + * here. + * However, haven't implemented this yet for lack of time, but more + * importantly, because it would entail writing to the registry (on Windows), + * or an obscure file location (on Mac OS X) and make it far more difficult to + * find the preferences to tweak them by hand (no! stay out of regedit!) + * or to reset the preferences by simply deleting the preferences.txt file. + */ +public class Preferences { + + // what to call the feller + + static final String PREFS_FILE = "preferences.txt"; + + + // prompt text stuff + + static final String PROMPT_YES = "Yes"; + static final String PROMPT_NO = "No"; + static final String PROMPT_CANCEL = "Cancel"; + static final String PROMPT_OK = "OK"; + static final String PROMPT_BROWSE = "Browse"; + + /** + * Standardized width for buttons. Mac OS X 10.3 wants 70 as its default, + * Windows XP needs 66, and my Ubuntu machine needs 80+, so 80 seems proper. + */ + static public int BUTTON_WIDTH = 80; + + /** + * Standardized button height. Mac OS X 10.3 (Java 1.4) wants 29, + * presumably because it now includes the blue border, where it didn't + * in Java 1.3. Windows XP only wants 23 (not sure what default Linux + * would be). Because of the disparity, on Mac OS X, it will be set + * inside a static block. + */ + static public int BUTTON_HEIGHT = 24; + + // value for the size bars, buttons, etc + + static final int GRID_SIZE = 33; + + + // indents and spacing standards. these probably need to be modified + // per platform as well, since macosx is so huge, windows is smaller, + // and linux is all over the map + + static final int GUI_BIG = 13; + static final int GUI_BETWEEN = 10; + static final int GUI_SMALL = 6; + + + + // data model + + static Hashtable table = new Hashtable();; + static File preferencesFile; + + + static protected void init(String commandLinePrefs) { + + + } + + + public Preferences() { + + } + + // ................................................................. + + // ................................................................. + + // ................................................................. + + // ................................................................. + + + + static public String get(String attribute) { + return (String) table.get(attribute); + } + + static public void set(String attribute, String value) { + table.put(attribute, value); + } + + + static public boolean getBoolean(String attribute) { + String value = get(attribute); + return (new Boolean(value)).booleanValue(); + } + + + static public void setBoolean(String attribute, boolean value) { + set(attribute, value ? "true" : "false"); + } + + + static public int getInteger(String attribute) { + return Integer.parseInt(get(attribute)); + } + + + static public void setInteger(String key, int value) { + set(key, String.valueOf(value)); + } + +} diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/processing/app/Serial.java b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/processing/app/Serial.java new file mode 100644 index 0000000..04566a7 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/processing/app/Serial.java @@ -0,0 +1,527 @@ +/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + PSerial - class for serial port goodness + Part of the Processing project - http://processing.org + + Copyright (c) 2004 Ben Fry & Casey Reas + + 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. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA +*/ + +package processing.app; +//import processing.core.*; + + +import java.io.*; +import java.text.MessageFormat; +import java.util.*; +import jssc.SerialPort; +import jssc.SerialPortEvent; +import jssc.SerialPortEventListener; +import jssc.SerialPortException; +import jssc.SerialPortList; +import processing.app.debug.MessageConsumer; + + +public class Serial implements SerialPortEventListener { + + //PApplet parent; + + // properties can be passed in for default values + // otherwise defaults to 9600 N81 + + // these could be made static, which might be a solution + // for the classloading problem.. because if code ran again, + // the static class would have an object that could be closed + + SerialPort port; + + int rate; + int parity; + int databits; + int stopbits; + boolean monitor = false; + + // read buffer and streams + + InputStream input; + OutputStream output; + + byte buffer[] = new byte[32768]; + int bufferIndex; + int bufferLast; + + MessageConsumer consumer; + + public Serial(boolean monitor) throws SerialException { + this(Preferences.get("serial.port"), + Preferences.getInteger("serial.debug_rate"), + Preferences.get("serial.parity").charAt(0), + Preferences.getInteger("serial.databits"), + new Float(Preferences.get("serial.stopbits")).floatValue()); + this.monitor = monitor; + } + + public Serial() throws SerialException { + this(Preferences.get("serial.port"), + Preferences.getInteger("serial.debug_rate"), + Preferences.get("serial.parity").charAt(0), + Preferences.getInteger("serial.databits"), + new Float(Preferences.get("serial.stopbits")).floatValue()); + } + + public Serial(int irate) throws SerialException { + this(Preferences.get("serial.port"), irate, + Preferences.get("serial.parity").charAt(0), + Preferences.getInteger("serial.databits"), + new Float(Preferences.get("serial.stopbits")).floatValue()); + } + + public Serial(String iname, int irate) throws SerialException { + this(iname, irate, Preferences.get("serial.parity").charAt(0), + Preferences.getInteger("serial.databits"), + new Float(Preferences.get("serial.stopbits")).floatValue()); + } + + public Serial(String iname) throws SerialException { + this(iname, Preferences.getInteger("serial.debug_rate"), + Preferences.get("serial.parity").charAt(0), + Preferences.getInteger("serial.databits"), + new Float(Preferences.get("serial.stopbits")).floatValue()); + } + + public Serial(String iname, int irate, + char iparity, int idatabits, float istopbits) + throws SerialException { + //if (port != null) port.close(); + //this.parent = parent; + //parent.attach(this); + + this.rate = irate; + + parity = SerialPort.PARITY_NONE; + if (iparity == 'E') parity = SerialPort.PARITY_EVEN; + if (iparity == 'O') parity = SerialPort.PARITY_ODD; + + this.databits = idatabits; + + stopbits = SerialPort.STOPBITS_1; + if (istopbits == 1.5f) stopbits = SerialPort.STOPBITS_1_5; + if (istopbits == 2) stopbits = SerialPort.STOPBITS_2; + + try { + port = new SerialPort(iname); + port.openPort(); + port.setParams(rate, databits, stopbits, parity, true, true); + port.addEventListener(this); + } catch (Exception e) { + throw new SerialException(MessageFormat.format("Error opening serial port ''{0}''.", iname), e); + } + + if (port == null) { + throw new SerialException("Serial port '" + iname + "' not found. Did you select the right one from the Tools > Serial Port menu?"); + } + } + + + public void setup() { + //parent.registerCall(this, DISPOSE); + } + + public void dispose() throws IOException { + if (port != null) { + try { + if (port.isOpened()) { + port.closePort(); // close the port + } + } catch (SerialPortException e) { + throw new IOException(e); + } finally { + port = null; + } + } + } + + public void addListener(MessageConsumer consumer) { + this.consumer = consumer; + } + + public synchronized void serialEvent(SerialPortEvent serialEvent) { + if (serialEvent.isRXCHAR()) { + try { + byte[] buf = port.readBytes(serialEvent.getEventValue()); + if (buf.length > 0) { + if (bufferLast == buffer.length) { + byte temp[] = new byte[bufferLast << 1]; + System.arraycopy(buffer, 0, temp, 0, bufferLast); + buffer = temp; + } + if (monitor) { + System.out.print(new String(buf)); + } + if (this.consumer != null) { + this.consumer.message(new String(buf)); + } + } + } catch (SerialPortException e) { + errorMessage("serialEvent", e); + } + } + } + + + /** + * Returns the number of bytes that have been read from serial + * and are waiting to be dealt with by the user. + */ + public synchronized int available() { + return (bufferLast - bufferIndex); + } + + + /** + * Ignore all the bytes read so far and empty the buffer. + */ + public synchronized void clear() { + bufferLast = 0; + bufferIndex = 0; + } + + + /** + * Returns a number between 0 and 255 for the next byte that's + * waiting in the buffer. + * Returns -1 if there was no byte (although the user should + * first check available() to see if things are ready to avoid this) + */ + public synchronized int read() { + if (bufferIndex == bufferLast) return -1; + + int outgoing = buffer[bufferIndex++] & 0xff; + if (bufferIndex == bufferLast) { // rewind + bufferIndex = 0; + bufferLast = 0; + } + return outgoing; + } + + + /** + * Returns the next byte in the buffer as a char. + * Returns -1, or 0xffff, if nothing is there. + */ + public synchronized char readChar() { + if (bufferIndex == bufferLast) return (char)(-1); + return (char) read(); + } + + + /** + * Return a byte array of anything that's in the serial buffer. + * Not particularly memory/speed efficient, because it creates + * a byte array on each read, but it's easier to use than + * readBytes(byte b[]) (see below). + */ + public synchronized byte[] readBytes() { + if (bufferIndex == bufferLast) return null; + + int length = bufferLast - bufferIndex; + byte outgoing[] = new byte[length]; + System.arraycopy(buffer, bufferIndex, outgoing, 0, length); + + bufferIndex = 0; // rewind + bufferLast = 0; + return outgoing; + } + + + /** + * Grab whatever is in the serial buffer, and stuff it into a + * byte buffer passed in by the user. This is more memory/time + * efficient than readBytes() returning a byte[] array. + *

+ * Returns an int for how many bytes were read. If more bytes + * are available than can fit into the byte array, only those + * that will fit are read. + */ + public synchronized int readBytes(byte outgoing[]) { + if (bufferIndex == bufferLast) return 0; + + int length = bufferLast - bufferIndex; + if (length > outgoing.length) length = outgoing.length; + System.arraycopy(buffer, bufferIndex, outgoing, 0, length); + + bufferIndex += length; + if (bufferIndex == bufferLast) { + bufferIndex = 0; // rewind + bufferLast = 0; + } + return length; + } + + + /** + * Reads from the serial port into a buffer of bytes up to and + * including a particular character. If the character isn't in + * the serial buffer, then 'null' is returned. + */ + public synchronized byte[] readBytesUntil(int interesting) { + if (bufferIndex == bufferLast) return null; + byte what = (byte)interesting; + + int found = -1; + for (int k = bufferIndex; k < bufferLast; k++) { + if (buffer[k] == what) { + found = k; + break; + } + } + if (found == -1) return null; + + int length = found - bufferIndex + 1; + byte outgoing[] = new byte[length]; + System.arraycopy(buffer, bufferIndex, outgoing, 0, length); + + bufferIndex = 0; // rewind + bufferLast = 0; + return outgoing; + } + + + /** + * Reads from the serial port into a buffer of bytes until a + * particular character. If the character isn't in the serial + * buffer, then 'null' is returned. + *

+ * If outgoing[] is not big enough, then -1 is returned, + * and an error message is printed on the console. + * If nothing is in the buffer, zero is returned. + * If 'interesting' byte is not in the buffer, then 0 is returned. + */ + public synchronized int readBytesUntil(int interesting, byte outgoing[]) { + if (bufferIndex == bufferLast) return 0; + byte what = (byte)interesting; + + int found = -1; + for (int k = bufferIndex; k < bufferLast; k++) { + if (buffer[k] == what) { + found = k; + break; + } + } + if (found == -1) return 0; + + int length = found - bufferIndex + 1; + if (length > outgoing.length) { + System.err.println("readBytesUntil() byte buffer is" + + " too small for the " + length + + " bytes up to and including char " + interesting); + return -1; + } + //byte outgoing[] = new byte[length]; + System.arraycopy(buffer, bufferIndex, outgoing, 0, length); + + bufferIndex += length; + if (bufferIndex == bufferLast) { + bufferIndex = 0; // rewind + bufferLast = 0; + } + return length; + } + + + /** + * Return whatever has been read from the serial port so far + * as a String. It assumes that the incoming characters are ASCII. + *

+ * If you want to move Unicode data, you can first convert the + * String to a byte stream in the representation of your choice + * (i.e. UTF8 or two-byte Unicode data), and send it as a byte array. + */ + public synchronized String readString() { + if (bufferIndex == bufferLast) return null; + return new String(readBytes()); + } + + + /** + * Combination of readBytesUntil and readString. See caveats in + * each function. Returns null if it still hasn't found what + * you're looking for. + *

+ * If you want to move Unicode data, you can first convert the + * String to a byte stream in the representation of your choice + * (i.e. UTF8 or two-byte Unicode data), and send it as a byte array. + */ + public synchronized String readStringUntil(int interesting) { + byte b[] = readBytesUntil(interesting); + if (b == null) return null; + return new String(b); + } + + + /** + * This will handle both ints, bytes and chars transparently. + */ + public void write(int what) { // will also cover char + try { + port.writeInt(what & 0xff); + } catch (SerialPortException e) { + errorMessage("write", e); + } + } + + + public void write(byte bytes[]) { + try { + port.writeBytes(bytes); + } catch (SerialPortException e) { + errorMessage("write", e); + } + } + + + /** + * Write a String to the output. Note that this doesn't account + * for Unicode (two bytes per char), nor will it send UTF8 + * characters.. It assumes that you mean to send a byte buffer + * (most often the case for networking and serial i/o) and + * will only use the bottom 8 bits of each char in the string. + * (Meaning that internally it uses String.getBytes) + *

+ * If you want to move Unicode data, you can first convert the + * String to a byte stream in the representation of your choice + * (i.e. UTF8 or two-byte Unicode data), and send it as a byte array. + */ + public void write(String what) { + write(what.getBytes()); + } + + public void setDTR(boolean state) { + try { + port.setDTR(state); + } catch (SerialPortException e) { + errorMessage("setDTR", e); + } + } + + public void setRTS(boolean state) { + try { + port.setRTS(state); + } catch (SerialPortException e) { + errorMessage("setRTS", e); + } + } + + static public List list() { + return Arrays.asList(SerialPortList.getPortNames()); + } + + + /** + * General error reporting, all corraled here just in case + * I think of something slightly more intelligent to do. + */ + static public void errorMessage(String where, Throwable e) { + System.err.println("Error inside Serial." + where + "()"); + e.printStackTrace(); + } +} + + + /* + class SerialMenuListener implements ItemListener { + //public SerialMenuListener() { } + + public void itemStateChanged(ItemEvent e) { + int count = serialMenu.getItemCount(); + for (int i = 0; i < count; i++) { + ((CheckboxMenuItem)serialMenu.getItem(i)).setState(false); + } + CheckboxMenuItem item = (CheckboxMenuItem)e.getSource(); + item.setState(true); + String name = item.getLabel(); + //System.out.println(item.getLabel()); + PdeBase.properties.put("serial.port", name); + //System.out.println("set to " + get("serial.port")); + } + } + */ + + + /* + protected Vector buildPortList() { + // get list of names for serial ports + // have the default port checked (if present) + Vector list = new Vector(); + + //SerialMenuListener listener = new SerialMenuListener(); + boolean problem = false; + + // if this is failing, it may be because + // lib/javax.comm.properties is missing. + // java is weird about how it searches for java.comm.properties + // so it tends to be very fragile. i.e. quotes in the CLASSPATH + // environment variable will hose things. + try { + //System.out.println("building port list"); + Enumeration portList = CommPortIdentifier.getPortIdentifiers(); + while (portList.hasMoreElements()) { + CommPortIdentifier portId = + (CommPortIdentifier) portList.nextElement(); + //System.out.println(portId); + + if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) { + //if (portId.getName().equals(port)) { + String name = portId.getName(); + //CheckboxMenuItem mi = + //new CheckboxMenuItem(name, name.equals(defaultName)); + + //mi.addItemListener(listener); + //serialMenu.add(mi); + list.addElement(name); + } + } + } catch (UnsatisfiedLinkError e) { + e.printStackTrace(); + problem = true; + + } catch (Exception e) { + System.out.println("exception building serial menu"); + e.printStackTrace(); + } + + //if (serialMenu.getItemCount() == 0) { + //System.out.println("dimming serial menu"); + //serialMenu.setEnabled(false); + //} + + // only warn them if this is the first time + if (problem && PdeBase.firstTime) { + JOptionPane.showMessageDialog(this, //frame, + "Serial port support not installed.\n" + + "Check the readme for instructions\n" + + "if you need to use the serial port. ", + "Serial Port Warning", + JOptionPane.WARNING_MESSAGE); + } + return list; + } + */ + + + diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/processing/app/SerialException.java b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/processing/app/SerialException.java new file mode 100644 index 0000000..525c240 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/processing/app/SerialException.java @@ -0,0 +1,39 @@ +/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Copyright (c) 2007 David A. Mellis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +package processing.app; + +public class SerialException extends Exception { + public SerialException() { + super(); + } + + public SerialException(String message) { + super(message); + } + + public SerialException(String message, Throwable cause) { + super(message, cause); + } + + public SerialException(Throwable cause) { + super(cause); + } +} diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/processing/app/debug/MessageConsumer.java b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/processing/app/debug/MessageConsumer.java new file mode 100644 index 0000000..5e20429 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/processing/app/debug/MessageConsumer.java @@ -0,0 +1,42 @@ +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2004-06 Ben Fry and Casey Reas + Copyright (c) 2001-04 Massachusetts Institute of Technology + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +package processing.app.debug; + + +/** + * Interface for dealing with parser/compiler output. + *

+ * Different instances of MessageStream need to do different things with + * messages. In particular, a stream instance used for parsing output from + * the compiler compiler has to interpret its messages differently than one + * parsing output from the runtime. + *

+ * Classes which consume messages and do something with them + * should implement this interface. + */ +public interface MessageConsumer { + + public void message(String s); + +} diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/processing/app/debug/MessageSiphon.java b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/processing/app/debug/MessageSiphon.java new file mode 100644 index 0000000..26901c3 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/processing/app/debug/MessageSiphon.java @@ -0,0 +1,104 @@ +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2004-06 Ben Fry and Casey Reas + Copyright (c) 2001-04 Massachusetts Institute of Technology + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +package processing.app.debug; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.SocketException; + +/** + * Slurps up messages from compiler. + */ +public class MessageSiphon implements Runnable { + + private final BufferedReader streamReader; + private final MessageConsumer consumer; + + private Thread thread; + private boolean canRun; + + public MessageSiphon(InputStream stream, MessageConsumer consumer) { + this.streamReader = new BufferedReader(new InputStreamReader(stream)); + this.consumer = consumer; + this.canRun = true; + + thread = new Thread(this); + // don't set priority too low, otherwise exceptions won't + // bubble up in time (i.e. compile errors have a weird delay) + //thread.setPriority(Thread.MIN_PRIORITY); + thread.setPriority(Thread.MAX_PRIORITY - 1); + thread.start(); + } + + + public void run() { + try { + // process data until we hit EOF; this will happily block + // (effectively sleeping the thread) until new data comes in. + // when the program is finally done, null will come through. + // + String currentLine; + while (canRun && (currentLine = streamReader.readLine()) != null) { + // \n is added again because readLine() strips it out + //EditorConsole.systemOut.println("messaging in"); + consumer.message(currentLine + "\n"); + //EditorConsole.systemOut.println("messaging out"); + } + //EditorConsole.systemOut.println("messaging thread done"); + } catch (NullPointerException npe) { + // Fairly common exception during shutdown + } catch (SocketException e) { + // socket has been close while we were wainting for data. nothing to see here, move along + } catch (Exception e) { + // On Linux and sometimes on Mac OS X, a "bad file descriptor" + // message comes up when closing an applet that's run externally. + // That message just gets supressed here.. + String mess = e.getMessage(); + if ((mess != null) && + (mess.indexOf("Bad file descriptor") != -1)) { + //if (e.getMessage().indexOf("Bad file descriptor") == -1) { + //System.err.println("MessageSiphon err " + e); + //e.printStackTrace(); + } else { + e.printStackTrace(); + } + } finally { + thread = null; + } + } + + // Wait until the MessageSiphon thread is complete. + public void join() throws java.lang.InterruptedException { + // Grab a temp copy in case another thread nulls the "thread" + // member variable + Thread t = thread; + if (t != null) t.join(); + } + + public void stop() { + this.canRun = false; + } + +} diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/processing/app/debug/RunnerException.java b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/processing/app/debug/RunnerException.java new file mode 100644 index 0000000..0a67d1e --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/processing/app/debug/RunnerException.java @@ -0,0 +1,161 @@ +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2004-08 Ben Fry and Casey Reas + Copyright (c) 2001-04 Massachusetts Institute of Technology + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +package processing.app.debug; + + +/** + * An exception with a line number attached that occurs + * during either compile time or run time. + */ +@SuppressWarnings("serial") +public class RunnerException extends Exception { + protected String message; + protected int codeIndex; + protected int codeLine; + protected int codeColumn; + protected boolean showStackTrace; + + + public RunnerException(String message) { + this(message, true); + } + + public RunnerException(String message, boolean showStackTrace) { + this(message, -1, -1, -1, showStackTrace); + } + + public RunnerException(String message, int file, int line) { + this(message, file, line, -1, true); + } + + + public RunnerException(String message, int file, int line, int column) { + this(message, file, line, column, true); + } + + + public RunnerException(String message, int file, int line, int column, + boolean showStackTrace) { + this.message = message; + this.codeIndex = file; + this.codeLine = line; + this.codeColumn = column; + this.showStackTrace = showStackTrace; + } + + + public RunnerException(Exception e) { + super(e); + this.showStackTrace = true; + } + + /** + * Override getMessage() in Throwable, so that I can set + * the message text outside the constructor. + */ + public String getMessage() { + return message; + } + + + public void setMessage(String message) { + this.message = message; + } + + + public int getCodeIndex() { + return codeIndex; + } + + + public void setCodeIndex(int index) { + codeIndex = index; + } + + + public boolean hasCodeIndex() { + return codeIndex != -1; + } + + + public int getCodeLine() { + return codeLine; + } + + + public void setCodeLine(int line) { + this.codeLine = line; + } + + + public boolean hasCodeLine() { + return codeLine != -1; + } + + + public void setCodeColumn(int column) { + this.codeColumn = column; + } + + + public int getCodeColumn() { + return codeColumn; + } + + + public void showStackTrace() { + showStackTrace = true; + } + + + public void hideStackTrace() { + showStackTrace = false; + } + + + /** + * Nix the java.lang crap out of an exception message + * because it scares the children. + *

+ * This function must be static to be used with super() + * in each of the constructors above. + */ + /* + static public final String massage(String msg) { + if (msg.indexOf("java.lang.") == 0) { + //int dot = msg.lastIndexOf('.'); + msg = msg.substring("java.lang.".length()); + } + return msg; + //return (dot == -1) ? msg : msg.substring(dot+1); + } + */ + + + public void printStackTrace() { + if (showStackTrace) { + super.printStackTrace(); + } + } +} diff --git a/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/processing/app/helpers/ProcessUtils.java b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/processing/app/helpers/ProcessUtils.java new file mode 100644 index 0000000..c023f58 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/maple_loader/src/processing/app/helpers/ProcessUtils.java @@ -0,0 +1,32 @@ +package processing.app.helpers; + +//import processing.app.Base; + +import java.io.IOException; +import java.util.Map; + +import processing.app.Base; + +public class ProcessUtils { + + public static Process exec(String[] command) throws IOException { + // No problems on linux and mac + if (!Base.isWindows()) { + return Runtime.getRuntime().exec(command); + } + + // Brutal hack to workaround windows command line parsing. + // http://stackoverflow.com/questions/5969724/java-runtime-exec-fails-to-escape-characters-properly + // http://msdn.microsoft.com/en-us/library/a1y7w461.aspx + // http://bugs.sun.com/view_bug.do?bug_id=6468220 + // http://bugs.sun.com/view_bug.do?bug_id=6518827 + String[] cmdLine = new String[command.length]; + for (int i = 0; i < command.length; i++) + cmdLine[i] = command[i].replace("\"", "\\\""); + + ProcessBuilder pb = new ProcessBuilder(cmdLine); + Map env = pb.environment(); + env.put("CYGWIN", "nodosfilewarning"); + return pb.start(); + } +} diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/AUTHORS b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/AUTHORS new file mode 100644 index 0000000..d096f22 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/AUTHORS @@ -0,0 +1,19 @@ +Authors ordered by first contribution. + +Geoffrey McRae +Bret Olmsted +Tormod Volden +Jakob Malm +Reuben Dowle +Matthias Kubisch +Paul Fertser +Daniel Strnad +Jérémie Rapin +Christian Pointner +Mats Erik Andersson +Alexey Borovik +Antonio Borneo +Armin van der Togt +Brian Silverman +Georg Hofmann +Luis Rodrigues diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/Android.mk b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/Android.mk new file mode 100644 index 0000000..7be3d00 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/Android.mk @@ -0,0 +1,20 @@ +TOP_LOCAL_PATH := $(call my-dir) + +include $(call all-named-subdir-makefiles, parsers) + +LOCAL_PATH := $(TOP_LOCAL_PATH) + +include $(CLEAR_VARS) +LOCAL_MODULE := stm32flash +LOCAL_SRC_FILES := \ + dev_table.c \ + i2c.c \ + init.c \ + main.c \ + port.c \ + serial_common.c \ + serial_platform.c \ + stm32.c \ + utils.c +LOCAL_STATIC_LIBRARIES := libparsers +include $(BUILD_EXECUTABLE) diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/HOWTO b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/HOWTO new file mode 100644 index 0000000..d8f32eb --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/HOWTO @@ -0,0 +1,35 @@ +Add new interfaces: +===================================================================== +Current version 0.4 supports the following interfaces: +- UART Windows (either "COMn" and "\\.\COMn"); +- UART posix/Linux (e.g. "/dev/ttyUSB0"); +- I2C Linux through standard driver "i2c-dev" (e.g. "/dev/i2c-n"). + +Starting from version 0.4, the back-end of stm32flash is modular and +ready to be expanded to support new interfaces. +I'm planning adding SPI on Linux through standard driver "spidev". +You are invited to contribute with more interfaces. + +To add a new interface you need to add a new file, populate the struct +port_interface (check at the end of files i2c.c, serial_posix.c and +serial_w32.c) and provide the relative functions to operate on the +interface: open/close, read/write, get_cfg_str and the optional gpio. +The include the new drive in Makefile and register the new struct +port_interface in file port.c in struct port_interface *ports[]. + +There are several USB-I2C adapter in the market, each providing its +own libraries to communicate with the I2C bus. +Could be interesting to provide as back-end a bridge between stm32flash +and such libraries (I have no plan on this item). + + +Add new STM32 devices: +===================================================================== +Add a new line in file dev_table.c, in table devices[]. +The fields of the table are listed in stm32.h, struct stm32_dev. + + +Cross compile on Linux host for Windows target with MinGW: +===================================================================== +I'm using a 64 bit Arch Linux machines, and I usually run: + make CC=x86_64-w64-mingw32-gcc AR=x86_64-w64-mingw32-ar diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/I2C.txt b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/I2C.txt new file mode 100644 index 0000000..4c05ff6 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/I2C.txt @@ -0,0 +1,94 @@ +About I2C back-end communication in stm32flash +========================================================================== + +Starting from version v0.4, beside the serial communication port, +stm32flash adds support for I2C port to talk with STM32 bootloader. + +The current I2C back-end supports only the API provided by Linux kernel +driver "i2c-dev", so only I2C controllers with Linux kernel driver can be +used. +In Linux source code, most of the drivers for I2C and SMBUS controllers +are in + ./drivers/i2c/busses/ +Only I2C is supported by STM32 bootloader, so check the section below +about SMBUS. +No I2C support for Windows is available in stm32flash v0.4. + +Thanks to the new modular back-end, stm32flash can be easily extended to +support new back-ends and API. Check HOWTO file in stm32flash source code +for details. + +In the market there are several USB-to-I2C dongles; most of them are not +supported by kernel drivers. Manufacturer provide proprietary userspace +libraries using not standardized API. +These API and dongles could be supported in feature versions. + +There are currently 3 versions of STM32 bootloader for I2C communications: +- v1.0 using I2C clock stretching synchronization between host and STM32; +- v1.1 superset of v1.0, adds non stretching commands; +- v1.2 superset of v1.1, adds CRC command and compatibility with i2cdetect. +Details in ST application note AN2606. +All the bootloaders above are tested and working with stm32flash. + + +SMBUS controllers +========================================================================== + +Almost 50% of the drivers in Linux source code folder + ./drivers/i2c/busses/ +are for controllers that "only" support SMBUS protocol. They can NOT +operate with STM32 bootloader. +To identify if your controller supports I2C, use command: + i2cdetect -F n +where "n" is the number of the I2C interface (e.g. n=3 for "/dev/i2c-3"). +Controllers that supports I2C will report + I2C yes +Controller that support both I2C and SMBUS are ok. + +If you are interested on details about SMBUS protocol, you can download +the current specs from + http://smbus.org/specs/smbus20.pdf +and you can read the files in Linux source code + ./Documentation/i2c/i2c-protocol + ./Documentation/i2c/smbus-protocol + + +About bootloader v1.0 +========================================================================== + +Version v1.0 can have issues with some I2C controllers due to use of clock +stretching during commands that require long operations, like flash erase +and programming. + +Clock stretching is a technique to synchronize host and I2C device. When +I2C device wants to force a delay in the communication, it push "low" the +I2C clock; the I2C controller detects it and waits until I2C clock returns +"high". +Most I2C controllers set a "timeout" for clock stretching, ranging from +few milli-seconds to seconds depending on specific HW or SW driver. + +It is possible that the timeout in your I2C controller is smaller than the +delay required for flash erase or programming. In this case the I2C +controller will timeout and report error to stm32flash. +There is no possibility for stm32flash to retry, so it can only signal the +error and exit. + +To by-pass the issue with bootloader v1.0 you can modify the kernel driver +of your I2C controller. Not an easy job, since every controller has its own +way to handle the timeout. + +In my case I'm using the I2C controller integrated in the VGA port of my +laptop HP EliteBook 8460p. I built the 0.25$ VGA-to-I2C adapter reported in + http://www.paintyourdragon.com/?p=43 +To change the timeout of the I2C controller I had to modify the kernel file + drivers/gpu/drm/radeon/radeon_i2c.c +line 969 +- i2c->bit.timeout = usecs_to_jiffies(2200); /* from VESA */ ++ i2c->bit.timeout = msecs_to_jiffies(5000); /* 5s for STM32 */ +and recompile it. +Then + $> modprobe i2c-dev + $> chmod 666 /dev/i2c-7 + #> stm32flash -a 0x39 /dev/i2c-7 + +2014-09-16 Antonio Borneo diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/Makefile b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/Makefile new file mode 100644 index 0000000..0328d55 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/Makefile @@ -0,0 +1,38 @@ +PREFIX = /usr/local +CFLAGS += -Wall -g + +INSTALL = install + +OBJS = dev_table.o \ + i2c.o \ + init.o \ + main.o \ + port.o \ + serial_common.o \ + serial_platform.o \ + stm32.o \ + utils.o + +LIBOBJS = parsers/parsers.a + +all: stm32flash + +serial_platform.o: serial_posix.c serial_w32.c + +parsers/parsers.a: + cd parsers && $(MAKE) parsers.a + +stm32flash: $(OBJS) $(LIBOBJS) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBOBJS) + +clean: + rm -f $(OBJS) stm32flash + cd parsers && $(MAKE) $@ + +install: all + $(INSTALL) -d $(DESTDIR)$(PREFIX)/bin + $(INSTALL) -m 755 stm32flash $(DESTDIR)$(PREFIX)/bin + $(INSTALL) -d $(DESTDIR)$(PREFIX)/share/man/man1 + $(INSTALL) -m 644 stm32flash.1 $(DESTDIR)$(PREFIX)/share/man/man1 + +.PHONY: all clean install diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/TODO b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/TODO new file mode 100644 index 0000000..41df614 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/TODO @@ -0,0 +1,7 @@ + +stm32: +- Add support for variable page size + +AUTHORS: +- Add contributors from Geoffrey's commits + diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/dev_table.c b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/dev_table.c new file mode 100644 index 0000000..399cd9d --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/dev_table.c @@ -0,0 +1,70 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + Copyright (C) 2014 Antonio Borneo + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "stm32.h" + +/* + * Device table, corresponds to the "Bootloader device-dependant parameters" + * table in ST document AN2606. + * Note that the option bytes upper range is inclusive! + */ +const stm32_dev_t devices[] = { + /* F0 */ + {0x440, "STM32F051xx" , 0x20001000, 0x20002000, 0x08000000, 0x08010000, 4, 1024, 0x1FFFF800, 0x1FFFF80B, 0x1FFFEC00, 0x1FFFF800}, + {0x444, "STM32F030/F031" , 0x20001000, 0x20002000, 0x08000000, 0x08010000, 4, 1024, 0x1FFFF800, 0x1FFFF80B, 0x1FFFEC00, 0x1FFFF800}, + {0x445, "STM32F042xx" , 0x20001800, 0x20001800, 0x08000000, 0x08008000, 4, 1024, 0x1FFFF800, 0x1FFFF80F, 0x1FFFC400, 0x1FFFF800}, + {0x448, "STM32F072xx" , 0x20001800, 0x20004000, 0x08000000, 0x08020000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFC800, 0x1FFFF800}, + /* F1 */ + {0x412, "Low-density" , 0x20000200, 0x20002800, 0x08000000, 0x08008000, 4, 1024, 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800}, + {0x410, "Medium-density" , 0x20000200, 0x20005000, 0x08000000, 0x08020000, 4, 1024, 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800}, + {0x414, "High-density" , 0x20000200, 0x20010000, 0x08000000, 0x08080000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800}, + {0x420, "Medium-density VL" , 0x20000200, 0x20002000, 0x08000000, 0x08020000, 4, 1024, 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800}, + {0x428, "High-density VL" , 0x20000200, 0x20008000, 0x08000000, 0x08080000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800}, + {0x418, "Connectivity line" , 0x20001000, 0x20010000, 0x08000000, 0x08040000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFB000, 0x1FFFF800}, + {0x430, "XL-density" , 0x20000800, 0x20018000, 0x08000000, 0x08100000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFE000, 0x1FFFF800}, + /* Note that F2 and F4 devices have sectors of different page sizes + and only the first sectors (of one page size) are included here */ + /* F2 */ + {0x411, "STM32F2xx" , 0x20002000, 0x20020000, 0x08000000, 0x08100000, 4, 16384, 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF77DF}, + /* F3 */ + {0x432, "STM32F373/8" , 0x20001400, 0x20008000, 0x08000000, 0x08040000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFD800, 0x1FFFF800}, + {0x422, "F302xB/303xB/358" , 0x20001400, 0x20010000, 0x08000000, 0x08040000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFD800, 0x1FFFF800}, + {0x439, "STM32F302x4(6/8)" , 0x20001800, 0x20004000, 0x08000000, 0x08040000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFD800, 0x1FFFF800}, + {0x438, "F303x4/334/328" , 0x20001800, 0x20003000, 0x08000000, 0x08040000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFD800, 0x1FFFF800}, + /* F4 */ + {0x413, "STM32F40/1" , 0x20002000, 0x20020000, 0x08000000, 0x08100000, 4, 16384, 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF77DF}, + /* 0x419 is also used for STM32F429/39 but with other bootloader ID... */ + {0x419, "STM32F427/37" , 0x20002000, 0x20030000, 0x08000000, 0x08100000, 4, 16384, 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF77FF}, + {0x423, "STM32F401xB(C)" , 0x20003000, 0x20010000, 0x08000000, 0x08100000, 4, 16384, 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF77FF}, + {0x433, "STM32F401xD(E)" , 0x20003000, 0x20018000, 0x08000000, 0x08100000, 4, 16384, 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF77FF}, + /* L0 */ + {0x417, "L05xxx/06xxx" , 0x20001000, 0x20002000, 0x08000000, 0x08010000, 32, 128, 0x1FF80000, 0x1FF8000F, 0x1FF00000, 0x1FF01000}, + /* L1 */ + {0x416, "L1xxx6(8/B)" , 0x20000800, 0x20004000, 0x08000000, 0x08020000, 16, 256, 0x1FF80000, 0x1FF8000F, 0x1FF00000, 0x1FF01000}, + {0x429, "L1xxx6(8/B)A" , 0x20001000, 0x20008000, 0x08000000, 0x08020000, 16, 256, 0x1FF80000, 0x1FF8000F, 0x1FF00000, 0x1FF01000}, + {0x427, "L1xxxC" , 0x20001000, 0x20008000, 0x08000000, 0x08020000, 16, 256, 0x1FF80000, 0x1FF8000F, 0x1FF00000, 0x1FF02000}, + {0x436, "L1xxxD" , 0x20001000, 0x2000C000, 0x08000000, 0x08060000, 16, 256, 0x1ff80000, 0x1ff8000F, 0x1FF00000, 0x1FF02000}, + {0x437, "L1xxxE" , 0x20001000, 0x20014000, 0x08000000, 0x08060000, 16, 256, 0x1ff80000, 0x1ff8000F, 0x1FF00000, 0x1FF02000}, + /* These are not (yet) in AN2606: */ + {0x641, "Medium_Density PL" , 0x20000200, 0x00005000, 0x08000000, 0x08020000, 4, 1024, 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800}, + {0x9a8, "STM32W-128K" , 0x20000200, 0x20002000, 0x08000000, 0x08020000, 1, 1024, 0, 0, 0, 0}, + {0x9b0, "STM32W-256K" , 0x20000200, 0x20004000, 0x08000000, 0x08040000, 1, 2048, 0, 0, 0, 0}, + {0x0} +}; diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/gpl-2.0.txt b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/gpl-2.0.txt new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/gpl-2.0.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/i2c.c b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/i2c.c new file mode 100644 index 0000000..10e6bb1 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/i2c.c @@ -0,0 +1,209 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2014 Antonio Borneo + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "serial.h" +#include "port.h" + + +#if !defined(__linux__) + +static port_err_t i2c_open(struct port_interface *port, + struct port_options *ops) +{ + return PORT_ERR_NODEV; +} + +struct port_interface port_i2c = { + .name = "i2c", + .open = i2c_open, +}; + +#else + +#ifdef __ANDROID__ +#define I2C_SLAVE 0x0703 /* Use this slave address */ +#define I2C_FUNCS 0x0705 /* Get the adapter functionality mask */ +/* To determine what functionality is present */ +#define I2C_FUNC_I2C 0x00000001 +#else +#include +#include +#endif + +#include + +struct i2c_priv { + int fd; + int addr; +}; + +static port_err_t i2c_open(struct port_interface *port, + struct port_options *ops) +{ + struct i2c_priv *h; + int fd, addr, ret; + unsigned long funcs; + + /* 1. check device name match */ + if (strncmp(ops->device, "/dev/i2c-", strlen("/dev/i2c-"))) + return PORT_ERR_NODEV; + + /* 2. check options */ + addr = ops->bus_addr; + if (addr < 0x03 || addr > 0x77) { + fprintf(stderr, "I2C address out of range [0x03-0x77]\n"); + return PORT_ERR_UNKNOWN; + } + + /* 3. open it */ + h = calloc(sizeof(*h), 1); + if (h == NULL) { + fprintf(stderr, "End of memory\n"); + return PORT_ERR_UNKNOWN; + } + fd = open(ops->device, O_RDWR); + if (fd < 0) { + fprintf(stderr, "Unable to open special file \"%s\"\n", + ops->device); + free(h); + return PORT_ERR_UNKNOWN; + } + + /* 3.5. Check capabilities */ + ret = ioctl(fd, I2C_FUNCS, &funcs); + if (ret < 0) { + fprintf(stderr, "I2C ioctl(funcs) error %d\n", errno); + close(fd); + free(h); + return PORT_ERR_UNKNOWN; + } + if ((funcs & I2C_FUNC_I2C) == 0) { + fprintf(stderr, "Error: controller is not I2C, only SMBUS.\n"); + close(fd); + free(h); + return PORT_ERR_UNKNOWN; + } + + /* 4. set options */ + ret = ioctl(fd, I2C_SLAVE, addr); + if (ret < 0) { + fprintf(stderr, "I2C ioctl(slave) error %d\n", errno); + close(fd); + free(h); + return PORT_ERR_UNKNOWN; + } + + h->fd = fd; + h->addr = addr; + port->private = h; + return PORT_ERR_OK; +} + +static port_err_t i2c_close(struct port_interface *port) +{ + struct i2c_priv *h; + + h = (struct i2c_priv *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + close(h->fd); + free(h); + port->private = NULL; + return PORT_ERR_OK; +} + +static port_err_t i2c_read(struct port_interface *port, void *buf, + size_t nbyte) +{ + struct i2c_priv *h; + int ret; + + h = (struct i2c_priv *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + ret = read(h->fd, buf, nbyte); + if (ret != nbyte) + return PORT_ERR_UNKNOWN; + return PORT_ERR_OK; +} + +static port_err_t i2c_write(struct port_interface *port, void *buf, + size_t nbyte) +{ + struct i2c_priv *h; + int ret; + + h = (struct i2c_priv *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + ret = write(h->fd, buf, nbyte); + if (ret != nbyte) + return PORT_ERR_UNKNOWN; + return PORT_ERR_OK; +} + +static port_err_t i2c_gpio(struct port_interface *port, serial_gpio_t n, + int level) +{ + return PORT_ERR_OK; +} + +static const char *i2c_get_cfg_str(struct port_interface *port) +{ + struct i2c_priv *h; + static char str[11]; + + h = (struct i2c_priv *)port->private; + if (h == NULL) + return "INVALID"; + snprintf(str, sizeof(str), "addr 0x%2x", h->addr); + return str; +} + +static struct varlen_cmd i2c_cmd_get_reply[] = { + {0x10, 11}, + {0x11, 17}, + {0x12, 18}, + { /* sentinel */ } +}; + +struct port_interface port_i2c = { + .name = "i2c", + .flags = PORT_STRETCH_W, + .open = i2c_open, + .close = i2c_close, + .read = i2c_read, + .write = i2c_write, + .gpio = i2c_gpio, + .cmd_get_reply = i2c_cmd_get_reply, + .get_cfg_str = i2c_get_cfg_str, +}; + +#endif diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/init.c b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/init.c new file mode 100644 index 0000000..77a571b --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/init.c @@ -0,0 +1,219 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + Copyright (C) 2013 Antonio Borneo + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include "init.h" +#include "serial.h" +#include "stm32.h" +#include "port.h" + +struct gpio_list { + struct gpio_list *next; + int gpio; +}; + + +static int write_to(const char *filename, const char *value) +{ + int fd, ret; + + fd = open(filename, O_WRONLY); + if (fd < 0) { + fprintf(stderr, "Cannot open file \"%s\"\n", filename); + return 0; + } + ret = write(fd, value, strlen(value)); + if (ret < 0) { + fprintf(stderr, "Error writing in file \"%s\"\n", filename); + close(fd); + return 0; + } + close(fd); + return 1; +} + +#if !defined(__linux__) +static int drive_gpio(int n, int level, struct gpio_list **gpio_to_release) +{ + fprintf(stderr, "GPIO control only available in Linux\n"); + return 0; +} +#else +static int drive_gpio(int n, int level, struct gpio_list **gpio_to_release) +{ + char num[16]; /* sized to carry MAX_INT */ + char file[48]; /* sized to carry longest filename */ + struct stat buf; + struct gpio_list *new; + int ret; + + sprintf(file, "/sys/class/gpio/gpio%d/direction", n); + ret = stat(file, &buf); + if (ret) { + /* file miss, GPIO not exported yet */ + sprintf(num, "%d", n); + ret = write_to("/sys/class/gpio/export", num); + if (!ret) + return 0; + ret = stat(file, &buf); + if (ret) { + fprintf(stderr, "GPIO %d not available\n", n); + return 0; + } + new = (struct gpio_list *)malloc(sizeof(struct gpio_list)); + if (new == NULL) { + fprintf(stderr, "Out of memory\n"); + return 0; + } + new->gpio = n; + new->next = *gpio_to_release; + *gpio_to_release = new; + } + + return write_to(file, level ? "high" : "low"); +} +#endif + +static int release_gpio(int n) +{ + char num[16]; /* sized to carry MAX_INT */ + + sprintf(num, "%d", n); + return write_to("/sys/class/gpio/unexport", num); +} + +static int gpio_sequence(struct port_interface *port, const char *s, size_t l) +{ + struct gpio_list *gpio_to_release = NULL, *to_free; + int ret, level, gpio; + + ret = 1; + while (ret == 1 && *s && l > 0) { + if (*s == '-') { + level = 0; + s++; + l--; + } else + level = 1; + + if (isdigit(*s)) { + gpio = atoi(s); + while (isdigit(*s)) { + s++; + l--; + } + } else if (!strncmp(s, "rts", 3)) { + gpio = -GPIO_RTS; + s += 3; + l -= 3; + } else if (!strncmp(s, "dtr", 3)) { + gpio = -GPIO_DTR; + s += 3; + l -= 3; + } else if (!strncmp(s, "brk", 3)) { + gpio = -GPIO_BRK; + s += 3; + l -= 3; + } else { + fprintf(stderr, "Character \'%c\' is not a digit\n", *s); + ret = 0; + break; + } + + if (*s && (l > 0)) { + if (*s == ',') { + s++; + l--; + } else { + fprintf(stderr, "Character \'%c\' is not a separator\n", *s); + ret = 0; + break; + } + } + if (gpio < 0) + ret = (port->gpio(port, -gpio, level) == PORT_ERR_OK); + else + ret = drive_gpio(gpio, level, &gpio_to_release); + usleep(100000); + } + + while (gpio_to_release) { + release_gpio(gpio_to_release->gpio); + to_free = gpio_to_release; + gpio_to_release = gpio_to_release->next; + free(to_free); + } + usleep(500000); + return ret; +} + +static int gpio_bl_entry(struct port_interface *port, const char *seq) +{ + char *s; + + if (seq == NULL || seq[0] == ':') + return 1; + + s = strchr(seq, ':'); + if (s == NULL) + return gpio_sequence(port, seq, strlen(seq)); + + return gpio_sequence(port, seq, s - seq); +} + +static int gpio_bl_exit(struct port_interface *port, const char *seq) +{ + char *s; + + if (seq == NULL) + return 1; + + s = strchr(seq, ':'); + if (s == NULL || s[1] == '\0') + return 1; + + return gpio_sequence(port, s + 1, strlen(s + 1)); +} + +int init_bl_entry(struct port_interface *port, const char *seq) +{ + if (seq) + return gpio_bl_entry(port, seq); + + return 1; +} + +int init_bl_exit(stm32_t *stm, struct port_interface *port, const char *seq) +{ + if (seq) + return gpio_bl_exit(port, seq); + + if (stm32_reset_device(stm) != STM32_ERR_OK) + return 0; + return 1; +} diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/init.h b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/init.h new file mode 100644 index 0000000..6075b51 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/init.h @@ -0,0 +1,31 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + Copyright (C) 2013 Antonio Borneo + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _INIT_H +#define _INIT_H + +#include "stm32.h" +#include "port.h" + +int init_bl_entry(struct port_interface *port, const char *seq); +int init_bl_exit(stm32_t *stm, struct port_interface *port, const char *seq); + +#endif diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/main.c b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/main.c new file mode 100644 index 0000000..f081d61 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/main.c @@ -0,0 +1,774 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright 2010 Geoffrey McRae + Copyright 2011 Steve Markgraf + Copyright 2012 Tormod Volden + Copyright 2013 Antonio Borneo + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "init.h" +#include "utils.h" +#include "serial.h" +#include "stm32.h" +#include "parsers/parser.h" +#include "port.h" + +#include "parsers/binary.h" +#include "parsers/hex.h" + +#define VERSION "Arduino_STM32_0.9" + +/* device globals */ +stm32_t *stm = NULL; + +void *p_st = NULL; +parser_t *parser = NULL; + +/* settings */ +struct port_options port_opts = { + .device = NULL, + .baudRate = SERIAL_BAUD_57600, + .serial_mode = "8e1", + .bus_addr = 0, + .rx_frame_max = STM32_MAX_RX_FRAME, + .tx_frame_max = STM32_MAX_TX_FRAME, +}; +int rd = 0; +int wr = 0; +int wu = 0; +int rp = 0; +int ur = 0; +int eraseOnly = 0; +int crc = 0; +int npages = 0; +int spage = 0; +int no_erase = 0; +char verify = 0; +int retry = 10; +char exec_flag = 0; +uint32_t execute = 0; +char init_flag = 1; +char force_binary = 0; +char reset_flag = 0; +char *filename; +char *gpio_seq = NULL; +uint32_t start_addr = 0; +uint32_t readwrite_len = 0; + +/* functions */ +int parse_options(int argc, char *argv[]); +void show_help(char *name); + +static int is_addr_in_ram(uint32_t addr) +{ + return addr >= stm->dev->ram_start && addr < stm->dev->ram_end; +} + +static int is_addr_in_flash(uint32_t addr) +{ + return addr >= stm->dev->fl_start && addr < stm->dev->fl_end; +} + +static int flash_addr_to_page_floor(uint32_t addr) +{ + if (!is_addr_in_flash(addr)) + return 0; + + return (addr - stm->dev->fl_start) / stm->dev->fl_ps; +} + +static int flash_addr_to_page_ceil(uint32_t addr) +{ + if (!(addr >= stm->dev->fl_start && addr <= stm->dev->fl_end)) + return 0; + + return (addr + stm->dev->fl_ps - 1 - stm->dev->fl_start) + / stm->dev->fl_ps; +} + +static uint32_t flash_page_to_addr(int page) +{ + return stm->dev->fl_start + page * stm->dev->fl_ps; +} + +int main(int argc, char* argv[]) { + struct port_interface *port = NULL; + int ret = 1; + stm32_err_t s_err; + parser_err_t perr; + FILE *diag = stdout; + + fprintf(diag, "stm32flash " VERSION "\n\n"); + fprintf(diag, "http://github.com/rogerclarkmelbourne/arduino_stm32\n\n"); + if (parse_options(argc, argv) != 0) + goto close; + + if (rd && filename[0] == '-') { + diag = stderr; + } + + if (wr) { + /* first try hex */ + if (!force_binary) { + parser = &PARSER_HEX; + p_st = parser->init(); + if (!p_st) { + fprintf(stderr, "%s Parser failed to initialize\n", parser->name); + goto close; + } + } + + if (force_binary || (perr = parser->open(p_st, filename, 0)) != PARSER_ERR_OK) { + if (force_binary || perr == PARSER_ERR_INVALID_FILE) { + if (!force_binary) { + parser->close(p_st); + p_st = NULL; + } + + /* now try binary */ + parser = &PARSER_BINARY; + p_st = parser->init(); + if (!p_st) { + fprintf(stderr, "%s Parser failed to initialize\n", parser->name); + goto close; + } + perr = parser->open(p_st, filename, 0); + } + + /* if still have an error, fail */ + if (perr != PARSER_ERR_OK) { + fprintf(stderr, "%s ERROR: %s\n", parser->name, parser_errstr(perr)); + if (perr == PARSER_ERR_SYSTEM) perror(filename); + goto close; + } + } + + fprintf(diag, "Using Parser : %s\n", parser->name); + } else { + parser = &PARSER_BINARY; + p_st = parser->init(); + if (!p_st) { + fprintf(stderr, "%s Parser failed to initialize\n", parser->name); + goto close; + } + } + + if (port_open(&port_opts, &port) != PORT_ERR_OK) { + fprintf(stderr, "Failed to open port: %s\n", port_opts.device); + goto close; + } + + fprintf(diag, "Interface %s: %s\n", port->name, port->get_cfg_str(port)); + if (init_flag && init_bl_entry(port, gpio_seq) == 0) + goto close; + stm = stm32_init(port, init_flag); + if (!stm) + goto close; + + fprintf(diag, "Version : 0x%02x\n", stm->bl_version); + if (port->flags & PORT_GVR_ETX) { + fprintf(diag, "Option 1 : 0x%02x\n", stm->option1); + fprintf(diag, "Option 2 : 0x%02x\n", stm->option2); + } + fprintf(diag, "Device ID : 0x%04x (%s)\n", stm->pid, stm->dev->name); + fprintf(diag, "- RAM : %dKiB (%db reserved by bootloader)\n", (stm->dev->ram_end - 0x20000000) / 1024, stm->dev->ram_start - 0x20000000); + fprintf(diag, "- Flash : %dKiB (sector size: %dx%d)\n", (stm->dev->fl_end - stm->dev->fl_start ) / 1024, stm->dev->fl_pps, stm->dev->fl_ps); + fprintf(diag, "- Option RAM : %db\n", stm->dev->opt_end - stm->dev->opt_start + 1); + fprintf(diag, "- System RAM : %dKiB\n", (stm->dev->mem_end - stm->dev->mem_start) / 1024); + + uint8_t buffer[256]; + uint32_t addr, start, end; + unsigned int len; + int failed = 0; + int first_page, num_pages; + + /* + * Cleanup addresses: + * + * Starting from options + * start_addr, readwrite_len, spage, npages + * and using device memory size, compute + * start, end, first_page, num_pages + */ + if (start_addr || readwrite_len) { + start = start_addr; + + if (is_addr_in_flash(start)) + end = stm->dev->fl_end; + else { + no_erase = 1; + if (is_addr_in_ram(start)) + end = stm->dev->ram_end; + else + end = start + sizeof(uint32_t); + } + + if (readwrite_len && (end > start + readwrite_len)) + end = start + readwrite_len; + + first_page = flash_addr_to_page_floor(start); + if (!first_page && end == stm->dev->fl_end) + num_pages = 0xff; /* mass erase */ + else + num_pages = flash_addr_to_page_ceil(end) - first_page; + } else if (!spage && !npages) { + start = stm->dev->fl_start; + end = stm->dev->fl_end; + first_page = 0; + num_pages = 0xff; /* mass erase */ + } else { + first_page = spage; + start = flash_page_to_addr(first_page); + if (start > stm->dev->fl_end) { + fprintf(stderr, "Address range exceeds flash size.\n"); + goto close; + } + + if (npages) { + num_pages = npages; + end = flash_page_to_addr(first_page + num_pages); + if (end > stm->dev->fl_end) + end = stm->dev->fl_end; + } else { + end = stm->dev->fl_end; + num_pages = flash_addr_to_page_ceil(end) - first_page; + } + + if (!first_page && end == stm->dev->fl_end) + num_pages = 0xff; /* mass erase */ + } + + if (rd) { + unsigned int max_len = port_opts.rx_frame_max; + + fprintf(diag, "Memory read\n"); + + perr = parser->open(p_st, filename, 1); + if (perr != PARSER_ERR_OK) { + fprintf(stderr, "%s ERROR: %s\n", parser->name, parser_errstr(perr)); + if (perr == PARSER_ERR_SYSTEM) + perror(filename); + goto close; + } + + fflush(diag); + addr = start; + while(addr < end) { + uint32_t left = end - addr; + len = max_len > left ? left : max_len; + s_err = stm32_read_memory(stm, addr, buffer, len); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Failed to read memory at address 0x%08x, target write-protected?\n", addr); + goto close; + } + if (parser->write(p_st, buffer, len) != PARSER_ERR_OK) + { + fprintf(stderr, "Failed to write data to file\n"); + goto close; + } + addr += len; + + fprintf(diag, + "\rRead address 0x%08x (%.2f%%) ", + addr, + (100.0f / (float)(end - start)) * (float)(addr - start) + ); + fflush(diag); + } + fprintf(diag, "Done.\n"); + ret = 0; + goto close; + } else if (rp) { + fprintf(stdout, "Read-Protecting flash\n"); + /* the device automatically performs a reset after the sending the ACK */ + reset_flag = 0; + stm32_readprot_memory(stm); + fprintf(stdout, "Done.\n"); + } else if (ur) { + fprintf(stdout, "Read-UnProtecting flash\n"); + /* the device automatically performs a reset after the sending the ACK */ + reset_flag = 0; + stm32_runprot_memory(stm); + fprintf(stdout, "Done.\n"); + } else if (eraseOnly) { + ret = 0; + fprintf(stdout, "Erasing flash\n"); + + if (num_pages != 0xff && + (start != flash_page_to_addr(first_page) + || end != flash_page_to_addr(first_page + num_pages))) { + fprintf(stderr, "Specified start & length are invalid (must be page aligned)\n"); + ret = 1; + goto close; + } + + s_err = stm32_erase_memory(stm, first_page, num_pages); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Failed to erase memory\n"); + ret = 1; + goto close; + } + } else if (wu) { + fprintf(diag, "Write-unprotecting flash\n"); + /* the device automatically performs a reset after the sending the ACK */ + reset_flag = 0; + stm32_wunprot_memory(stm); + fprintf(diag, "Done.\n"); + + } else if (wr) { + fprintf(diag, "Write to memory\n"); + + off_t offset = 0; + ssize_t r; + unsigned int size; + unsigned int max_wlen, max_rlen; + + max_wlen = port_opts.tx_frame_max - 2; /* skip len and crc */ + max_wlen &= ~3; /* 32 bit aligned */ + + max_rlen = port_opts.rx_frame_max; + max_rlen = max_rlen < max_wlen ? max_rlen : max_wlen; + + /* Assume data from stdin is whole device */ + if (filename[0] == '-' && filename[1] == '\0') + size = end - start; + else + size = parser->size(p_st); + + // TODO: It is possible to write to non-page boundaries, by reading out flash + // from partial pages and combining with the input data + // if ((start % stm->dev->fl_ps) != 0 || (end % stm->dev->fl_ps) != 0) { + // fprintf(stderr, "Specified start & length are invalid (must be page aligned)\n"); + // goto close; + // } + + // TODO: If writes are not page aligned, we should probably read out existing flash + // contents first, so it can be preserved and combined with new data + if (!no_erase && num_pages) { + fprintf(diag, "Erasing memory\n"); + s_err = stm32_erase_memory(stm, first_page, num_pages); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Failed to erase memory\n"); + goto close; + } + } + + fflush(diag); + addr = start; + while(addr < end && offset < size) { + uint32_t left = end - addr; + len = max_wlen > left ? left : max_wlen; + len = len > size - offset ? size - offset : len; + + if (parser->read(p_st, buffer, &len) != PARSER_ERR_OK) + goto close; + + if (len == 0) { + if (filename[0] == '-') { + break; + } else { + fprintf(stderr, "Failed to read input file\n"); + goto close; + } + } + + again: + s_err = stm32_write_memory(stm, addr, buffer, len); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Failed to write memory at address 0x%08x\n", addr); + goto close; + } + + if (verify) { + uint8_t compare[len]; + unsigned int offset, rlen; + + offset = 0; + while (offset < len) { + rlen = len - offset; + rlen = rlen < max_rlen ? rlen : max_rlen; + s_err = stm32_read_memory(stm, addr + offset, compare + offset, rlen); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Failed to read memory at address 0x%08x\n", addr + offset); + goto close; + } + offset += rlen; + } + + for(r = 0; r < len; ++r) + if (buffer[r] != compare[r]) { + if (failed == retry) { + fprintf(stderr, "Failed to verify at address 0x%08x, expected 0x%02x and found 0x%02x\n", + (uint32_t)(addr + r), + buffer [r], + compare[r] + ); + goto close; + } + ++failed; + goto again; + } + + failed = 0; + } + + addr += len; + offset += len; + + fprintf(diag, + "\rWrote %saddress 0x%08x (%.2f%%) ", + verify ? "and verified " : "", + addr, + (100.0f / size) * offset + ); + fflush(diag); + + } + + fprintf(diag, "Done.\n"); + ret = 0; + goto close; + } else if (crc) { + uint32_t crc_val = 0; + + fprintf(diag, "CRC computation\n"); + + s_err = stm32_crc_wrapper(stm, start, end - start, &crc_val); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Failed to read CRC\n"); + goto close; + } + fprintf(diag, "CRC(0x%08x-0x%08x) = 0x%08x\n", start, end, + crc_val); + ret = 0; + goto close; + } else + ret = 0; + +close: + if (stm && exec_flag && ret == 0) { + if (execute == 0) + execute = stm->dev->fl_start; + + fprintf(diag, "\nStarting execution at address 0x%08x... ", execute); + fflush(diag); + if (stm32_go(stm, execute) == STM32_ERR_OK) { + reset_flag = 0; + fprintf(diag, "done.\n"); + } else + fprintf(diag, "failed.\n"); + } + + if (stm && reset_flag) { + fprintf(diag, "\nResetting device... "); + fflush(diag); + if (init_bl_exit(stm, port, gpio_seq)) + fprintf(diag, "done.\n"); + else fprintf(diag, "failed.\n"); + } + + if (p_st ) parser->close(p_st); + if (stm ) stm32_close (stm); + if (port) + port->close(port); + + fprintf(diag, "\n"); + return ret; +} + +int parse_options(int argc, char *argv[]) +{ + int c; + char *pLen; + + while ((c = getopt(argc, argv, "a:b:m:r:w:e:vn:g:jkfcChuos:S:F:i:R")) != -1) { + switch(c) { + case 'a': + port_opts.bus_addr = strtoul(optarg, NULL, 0); + break; + + case 'b': + port_opts.baudRate = serial_get_baud(strtoul(optarg, NULL, 0)); + if (port_opts.baudRate == SERIAL_BAUD_INVALID) { + serial_baud_t baudrate; + fprintf(stderr, "Invalid baud rate, valid options are:\n"); + for (baudrate = SERIAL_BAUD_1200; baudrate != SERIAL_BAUD_INVALID; ++baudrate) + fprintf(stderr, " %d\n", serial_get_baud_int(baudrate)); + return 1; + } + break; + + case 'm': + if (strlen(optarg) != 3 + || serial_get_bits(optarg) == SERIAL_BITS_INVALID + || serial_get_parity(optarg) == SERIAL_PARITY_INVALID + || serial_get_stopbit(optarg) == SERIAL_STOPBIT_INVALID) { + fprintf(stderr, "Invalid serial mode\n"); + return 1; + } + port_opts.serial_mode = optarg; + break; + + case 'r': + case 'w': + rd = rd || c == 'r'; + wr = wr || c == 'w'; + if (rd && wr) { + fprintf(stderr, "ERROR: Invalid options, can't read & write at the same time\n"); + return 1; + } + filename = optarg; + if (filename[0] == '-') { + force_binary = 1; + } + break; + case 'e': + if (readwrite_len || start_addr) { + fprintf(stderr, "ERROR: Invalid options, can't specify start page / num pages and start address/length\n"); + return 1; + } + npages = strtoul(optarg, NULL, 0); + if (npages > 0xFF || npages < 0) { + fprintf(stderr, "ERROR: You need to specify a page count between 0 and 255"); + return 1; + } + if (!npages) + no_erase = 1; + break; + case 'u': + wu = 1; + if (rd || wr) { + fprintf(stderr, "ERROR: Invalid options, can't write unprotect and read/write at the same time\n"); + return 1; + } + break; + + case 'j': + rp = 1; + if (rd || wr) { + fprintf(stderr, "ERROR: Invalid options, can't read protect and read/write at the same time\n"); + return 1; + } + break; + + case 'k': + ur = 1; + if (rd || wr) { + fprintf(stderr, "ERROR: Invalid options, can't read unprotect and read/write at the same time\n"); + return 1; + } + break; + + case 'o': + eraseOnly = 1; + if (rd || wr) { + fprintf(stderr, "ERROR: Invalid options, can't erase-only and read/write at the same time\n"); + return 1; + } + break; + + case 'v': + verify = 1; + break; + + case 'n': + retry = strtoul(optarg, NULL, 0); + break; + + case 'g': + exec_flag = 1; + execute = strtoul(optarg, NULL, 0); + if (execute % 4 != 0) { + fprintf(stderr, "ERROR: Execution address must be word-aligned\n"); + return 1; + } + break; + case 's': + if (readwrite_len || start_addr) { + fprintf(stderr, "ERROR: Invalid options, can't specify start page / num pages and start address/length\n"); + return 1; + } + spage = strtoul(optarg, NULL, 0); + break; + case 'S': + if (spage || npages) { + fprintf(stderr, "ERROR: Invalid options, can't specify start page / num pages and start address/length\n"); + return 1; + } else { + start_addr = strtoul(optarg, &pLen, 0); + if (*pLen == ':') { + pLen++; + readwrite_len = strtoul(pLen, NULL, 0); + if (readwrite_len == 0) { + fprintf(stderr, "ERROR: Invalid options, can't specify zero length\n"); + return 1; + } + } + } + break; + case 'F': + port_opts.rx_frame_max = strtoul(optarg, &pLen, 0); + if (*pLen == ':') { + pLen++; + port_opts.tx_frame_max = strtoul(pLen, NULL, 0); + } + if (port_opts.rx_frame_max < 0 + || port_opts.tx_frame_max < 0) { + fprintf(stderr, "ERROR: Invalid negative value for option -F\n"); + return 1; + } + if (port_opts.rx_frame_max == 0) + port_opts.rx_frame_max = STM32_MAX_RX_FRAME; + if (port_opts.tx_frame_max == 0) + port_opts.tx_frame_max = STM32_MAX_TX_FRAME; + if (port_opts.rx_frame_max < 20 + || port_opts.tx_frame_max < 5) { + fprintf(stderr, "ERROR: current code cannot work with small frames.\n"); + fprintf(stderr, "min(RX) = 20, min(TX) = 5\n"); + return 1; + } + if (port_opts.rx_frame_max > STM32_MAX_RX_FRAME) { + fprintf(stderr, "WARNING: Ignore RX length in option -F\n"); + port_opts.rx_frame_max = STM32_MAX_RX_FRAME; + } + if (port_opts.tx_frame_max > STM32_MAX_TX_FRAME) { + fprintf(stderr, "WARNING: Ignore TX length in option -F\n"); + port_opts.tx_frame_max = STM32_MAX_TX_FRAME; + } + break; + case 'f': + force_binary = 1; + break; + + case 'c': + init_flag = 0; + break; + + case 'h': + show_help(argv[0]); + exit(0); + + case 'i': + gpio_seq = optarg; + break; + + case 'R': + reset_flag = 1; + break; + + case 'C': + crc = 1; + break; + } + } + + for (c = optind; c < argc; ++c) { + if (port_opts.device) { + fprintf(stderr, "ERROR: Invalid parameter specified\n"); + show_help(argv[0]); + return 1; + } + port_opts.device = argv[c]; + } + + if (port_opts.device == NULL) { + fprintf(stderr, "ERROR: Device not specified\n"); + show_help(argv[0]); + return 1; + } + + if (!wr && verify) { + fprintf(stderr, "ERROR: Invalid usage, -v is only valid when writing\n"); + show_help(argv[0]); + return 1; + } + + return 0; +} + +void show_help(char *name) { + fprintf(stderr, + "Usage: %s [-bvngfhc] [-[rw] filename] [tty_device | i2c_device]\n" + " -a bus_address Bus address (e.g. for I2C port)\n" + " -b rate Baud rate (default 57600)\n" + " -m mode Serial port mode (default 8e1)\n" + " -r filename Read flash to file (or - stdout)\n" + " -w filename Write flash from file (or - stdout)\n" + " -C Compute CRC of flash content\n" + " -u Disable the flash write-protection\n" + " -j Enable the flash read-protection\n" + " -k Disable the flash read-protection\n" + " -o Erase only\n" + " -e n Only erase n pages before writing the flash\n" + " -v Verify writes\n" + " -n count Retry failed writes up to count times (default 10)\n" + " -g address Start execution at specified address (0 = flash start)\n" + " -S address[:length] Specify start address and optionally length for\n" + " read/write/erase operations\n" + " -F RX_length[:TX_length] Specify the max length of RX and TX frame\n" + " -s start_page Flash at specified page (0 = flash start)\n" + " -f Force binary parser\n" + " -h Show this help\n" + " -c Resume the connection (don't send initial INIT)\n" + " *Baud rate must be kept the same as the first init*\n" + " This is useful if the reset fails\n" + " -i GPIO_string GPIO sequence to enter/exit bootloader mode\n" + " GPIO_string=[entry_seq][:[exit_seq]]\n" + " sequence=[-]n[,sequence]\n" + " -R Reset device at exit.\n" + "\n" + "Examples:\n" + " Get device information:\n" + " %s /dev/ttyS0\n" + " or:\n" + " %s /dev/i2c-0\n" + "\n" + " Write with verify and then start execution:\n" + " %s -w filename -v -g 0x0 /dev/ttyS0\n" + "\n" + " Read flash to file:\n" + " %s -r filename /dev/ttyS0\n" + "\n" + " Read 100 bytes of flash from 0x1000 to stdout:\n" + " %s -r - -S 0x1000:100 /dev/ttyS0\n" + "\n" + " Start execution:\n" + " %s -g 0x0 /dev/ttyS0\n" + "\n" + " GPIO sequence:\n" + " - entry sequence: GPIO_3=low, GPIO_2=low, GPIO_2=high\n" + " - exit sequence: GPIO_3=high, GPIO_2=low, GPIO_2=high\n" + " %s -i -3,-2,2:3,-2,2 /dev/ttyS0\n", + name, + name, + name, + name, + name, + name, + name, + name + ); +} + diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/parsers/Android.mk b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/parsers/Android.mk new file mode 100644 index 0000000..afec18c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/parsers/Android.mk @@ -0,0 +1,6 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := libparsers +LOCAL_SRC_FILES := binary.c hex.c +include $(BUILD_STATIC_LIBRARY) diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/parsers/Makefile b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/parsers/Makefile new file mode 100644 index 0000000..bb7df1e --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/parsers/Makefile @@ -0,0 +1,12 @@ + +CFLAGS += -Wall -g + +all: parsers.a + +parsers.a: binary.o hex.o + $(AR) rc $@ binary.o hex.o + +clean: + rm -f *.o parsers.a + +.PHONY: all clean diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/parsers/binary.c b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/parsers/binary.c new file mode 100644 index 0000000..f491952 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/parsers/binary.c @@ -0,0 +1,140 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#include +#include +#include +#include +#include + +#include "binary.h" + +typedef struct { + int fd; + char write; + struct stat stat; +} binary_t; + +void* binary_init() { + return calloc(sizeof(binary_t), 1); +} + +parser_err_t binary_open(void *storage, const char *filename, const char write) { + binary_t *st = storage; + if (write) { + if (filename[0] == '-') + st->fd = 1; + else + st->fd = open( + filename, +#ifndef __WIN32__ + O_WRONLY | O_CREAT | O_TRUNC, +#else + O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, +#endif +#ifndef __WIN32__ + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH +#else + 0 +#endif + ); + st->stat.st_size = 0; + } else { + if (filename[0] == '-') { + st->fd = 0; + } else { + if (stat(filename, &st->stat) != 0) + return PARSER_ERR_INVALID_FILE; + st->fd = open(filename, +#ifndef __WIN32__ + O_RDONLY +#else + O_RDONLY | O_BINARY +#endif + ); + } + } + + st->write = write; + return st->fd == -1 ? PARSER_ERR_SYSTEM : PARSER_ERR_OK; +} + +parser_err_t binary_close(void *storage) { + binary_t *st = storage; + + if (st->fd) close(st->fd); + free(st); + return PARSER_ERR_OK; +} + +unsigned int binary_size(void *storage) { + binary_t *st = storage; + return st->stat.st_size; +} + +parser_err_t binary_read(void *storage, void *data, unsigned int *len) { + binary_t *st = storage; + unsigned int left = *len; + if (st->write) return PARSER_ERR_WRONLY; + + ssize_t r; + while(left > 0) { + r = read(st->fd, data, left); + /* If there is no data to read at all, return OK, but with zero read */ + if (r == 0 && left == *len) { + *len = 0; + return PARSER_ERR_OK; + } + if (r <= 0) return PARSER_ERR_SYSTEM; + left -= r; + data += r; + } + + *len = *len - left; + return PARSER_ERR_OK; +} + +parser_err_t binary_write(void *storage, void *data, unsigned int len) { + binary_t *st = storage; + if (!st->write) return PARSER_ERR_RDONLY; + + ssize_t r; + while(len > 0) { + r = write(st->fd, data, len); + if (r < 1) return PARSER_ERR_SYSTEM; + st->stat.st_size += r; + + len -= r; + data += r; + } + + return PARSER_ERR_OK; +} + +parser_t PARSER_BINARY = { + "Raw BINARY", + binary_init, + binary_open, + binary_close, + binary_size, + binary_read, + binary_write +}; + diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/parsers/binary.h b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/parsers/binary.h new file mode 100644 index 0000000..d989acf --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/parsers/binary.h @@ -0,0 +1,27 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _PARSER_BINARY_H +#define _PARSER_BINARY_H + +#include "parser.h" + +extern parser_t PARSER_BINARY; +#endif diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/parsers/hex.c b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/parsers/hex.c new file mode 100644 index 0000000..3baf856 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/parsers/hex.c @@ -0,0 +1,224 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#include +#include +#include +#include +#include +#include +#include + +#include "hex.h" +#include "../utils.h" + +typedef struct { + size_t data_len, offset; + uint8_t *data; + uint8_t base; +} hex_t; + +void* hex_init() { + return calloc(sizeof(hex_t), 1); +} + +parser_err_t hex_open(void *storage, const char *filename, const char write) { + hex_t *st = storage; + if (write) { + return PARSER_ERR_RDONLY; + } else { + char mark; + int i, fd; + uint8_t checksum; + unsigned int c; + uint32_t base = 0; + unsigned int last_address = 0x0; + + fd = open(filename, O_RDONLY); + if (fd < 0) + return PARSER_ERR_SYSTEM; + + /* read in the file */ + + while(read(fd, &mark, 1) != 0) { + if (mark == '\n' || mark == '\r') continue; + if (mark != ':') + return PARSER_ERR_INVALID_FILE; + + char buffer[9]; + unsigned int reclen, address, type; + uint8_t *record = NULL; + + /* get the reclen, address, and type */ + buffer[8] = 0; + if (read(fd, &buffer, 8) != 8) return PARSER_ERR_INVALID_FILE; + if (sscanf(buffer, "%2x%4x%2x", &reclen, &address, &type) != 3) { + close(fd); + return PARSER_ERR_INVALID_FILE; + } + + /* setup the checksum */ + checksum = + reclen + + ((address & 0xFF00) >> 8) + + ((address & 0x00FF) >> 0) + + type; + + switch(type) { + /* data record */ + case 0: + c = address - last_address; + st->data = realloc(st->data, st->data_len + c + reclen); + + /* if there is a gap, set it to 0xff and increment the length */ + if (c > 0) { + memset(&st->data[st->data_len], 0xff, c); + st->data_len += c; + } + + last_address = address + reclen; + record = &st->data[st->data_len]; + st->data_len += reclen; + break; + + /* extended segment address record */ + case 2: + base = 0; + break; + + /* extended linear address record */ + case 4: + base = address; + break; + } + + buffer[2] = 0; + for(i = 0; i < reclen; ++i) { + if (read(fd, &buffer, 2) != 2 || sscanf(buffer, "%2x", &c) != 1) { + close(fd); + return PARSER_ERR_INVALID_FILE; + } + + /* add the byte to the checksum */ + checksum += c; + + switch(type) { + case 0: + if (record != NULL) { + record[i] = c; + } else { + return PARSER_ERR_INVALID_FILE; + } + break; + + case 2: + case 4: + base = (base << 8) | c; + break; + } + } + + /* read, scan, and verify the checksum */ + if ( + read(fd, &buffer, 2 ) != 2 || + sscanf(buffer, "%2x", &c) != 1 || + (uint8_t)(checksum + c) != 0x00 + ) { + close(fd); + return PARSER_ERR_INVALID_FILE; + } + + switch(type) { + /* EOF */ + case 1: + close(fd); + return PARSER_ERR_OK; + + /* address record */ + case 2: base = base << 4; + case 4: base = be_u32(base); + /* Reset last_address since our base changed */ + last_address = 0; + + if (st->base == 0) { + st->base = base; + break; + } + + /* we cant cope with files out of order */ + if (base < st->base) { + close(fd); + return PARSER_ERR_INVALID_FILE; + } + + /* if there is a gap, enlarge and fill with zeros */ + unsigned int len = base - st->base; + if (len > st->data_len) { + st->data = realloc(st->data, len); + memset(&st->data[st->data_len], 0, len - st->data_len); + st->data_len = len; + } + break; + } + } + + close(fd); + return PARSER_ERR_OK; + } +} + +parser_err_t hex_close(void *storage) { + hex_t *st = storage; + if (st) free(st->data); + free(st); + return PARSER_ERR_OK; +} + +unsigned int hex_size(void *storage) { + hex_t *st = storage; + return st->data_len; +} + +parser_err_t hex_read(void *storage, void *data, unsigned int *len) { + hex_t *st = storage; + unsigned int left = st->data_len - st->offset; + unsigned int get = left > *len ? *len : left; + + memcpy(data, &st->data[st->offset], get); + st->offset += get; + + *len = get; + return PARSER_ERR_OK; +} + +parser_err_t hex_write(void *storage, void *data, unsigned int len) { + return PARSER_ERR_RDONLY; +} + +parser_t PARSER_HEX = { + "Intel HEX", + hex_init, + hex_open, + hex_close, + hex_size, + hex_read, + hex_write +}; + diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/parsers/hex.h b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/parsers/hex.h new file mode 100644 index 0000000..02413c9 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/parsers/hex.h @@ -0,0 +1,27 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _PARSER_HEX_H +#define _PARSER_HEX_H + +#include "parser.h" + +extern parser_t PARSER_HEX; +#endif diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/parsers/parser.h b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/parsers/parser.h new file mode 100644 index 0000000..c2fae3c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/parsers/parser.h @@ -0,0 +1,56 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _H_PARSER +#define _H_PARSER + +enum parser_err { + PARSER_ERR_OK, + PARSER_ERR_SYSTEM, + PARSER_ERR_INVALID_FILE, + PARSER_ERR_WRONLY, + PARSER_ERR_RDONLY +}; +typedef enum parser_err parser_err_t; + +struct parser { + const char *name; + void* (*init )(); /* initialise the parser */ + parser_err_t (*open )(void *storage, const char *filename, const char write); /* open the file for read|write */ + parser_err_t (*close)(void *storage); /* close and free the parser */ + unsigned int (*size )(void *storage); /* get the total data size */ + parser_err_t (*read )(void *storage, void *data, unsigned int *len); /* read a block of data */ + parser_err_t (*write)(void *storage, void *data, unsigned int len); /* write a block of data */ +}; +typedef struct parser parser_t; + +static inline const char* parser_errstr(parser_err_t err) { + switch(err) { + case PARSER_ERR_OK : return "OK"; + case PARSER_ERR_SYSTEM : return "System Error"; + case PARSER_ERR_INVALID_FILE: return "Invalid File"; + case PARSER_ERR_WRONLY : return "Parser can only write"; + case PARSER_ERR_RDONLY : return "Parser can only read"; + default: + return "Unknown Error"; + } +} + +#endif diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/port.c b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/port.c new file mode 100644 index 0000000..08e58cc --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/port.c @@ -0,0 +1,59 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2014 Antonio Borneo + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include + +#include "serial.h" +#include "port.h" + + +extern struct port_interface port_serial; +extern struct port_interface port_i2c; + +static struct port_interface *ports[] = { + &port_serial, + &port_i2c, + NULL, +}; + + +port_err_t port_open(struct port_options *ops, struct port_interface **outport) +{ + int ret; + static struct port_interface **port; + + for (port = ports; *port; port++) { + ret = (*port)->open(*port, ops); + if (ret == PORT_ERR_NODEV) + continue; + if (ret == PORT_ERR_OK) + break; + fprintf(stderr, "Error probing interface \"%s\"\n", + (*port)->name); + } + if (*port == NULL) { + fprintf(stderr, "Cannot handle device \"%s\"\n", + ops->device); + return PORT_ERR_UNKNOWN; + } + + *outport = *port; + return PORT_ERR_OK; +} diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/port.h b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/port.h new file mode 100644 index 0000000..290f034 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/port.h @@ -0,0 +1,75 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2014 Antonio Borneo + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _H_PORT +#define _H_PORT + +typedef enum { + PORT_ERR_OK = 0, + PORT_ERR_NODEV, /* No such device */ + PORT_ERR_TIMEDOUT, /* Operation timed out */ + PORT_ERR_UNKNOWN, +} port_err_t; + +/* flags */ +#define PORT_BYTE (1 << 0) /* byte (not frame) oriented */ +#define PORT_GVR_ETX (1 << 1) /* cmd GVR returns protection status */ +#define PORT_CMD_INIT (1 << 2) /* use INIT cmd to autodetect speed */ +#define PORT_RETRY (1 << 3) /* allowed read() retry after timeout */ +#define PORT_STRETCH_W (1 << 4) /* warning for no-stretching commands */ + +/* all options and flags used to open and configure an interface */ +struct port_options { + const char *device; + serial_baud_t baudRate; + const char *serial_mode; + int bus_addr; + int rx_frame_max; + int tx_frame_max; +}; + +/* + * Specify the length of reply for command GET + * This is helpful for frame-oriented protocols, e.g. i2c, to avoid time + * consuming try-fail-timeout-retry operation. + * On byte-oriented protocols, i.e. UART, this information would be skipped + * after read the first byte, so not needed. + */ +struct varlen_cmd { + uint8_t version; + uint8_t length; +}; + +struct port_interface { + const char *name; + unsigned flags; + port_err_t (*open)(struct port_interface *port, struct port_options *ops); + port_err_t (*close)(struct port_interface *port); + port_err_t (*read)(struct port_interface *port, void *buf, size_t nbyte); + port_err_t (*write)(struct port_interface *port, void *buf, size_t nbyte); + port_err_t (*gpio)(struct port_interface *port, serial_gpio_t n, int level); + const char *(*get_cfg_str)(struct port_interface *port); + struct varlen_cmd *cmd_get_reply; + void *private; +}; + +port_err_t port_open(struct port_options *ops, struct port_interface **outport); + +#endif diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/protocol.txt b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/protocol.txt new file mode 100644 index 0000000..0391099 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/protocol.txt @@ -0,0 +1,19 @@ +The communication protocol used by ST bootloader is documented in following ST +application notes, depending on communication port. + +In current version of stm32flash are supported only UART and I2C ports. + +* AN3154: CAN protocol used in the STM32 bootloader + http://www.st.com/web/en/resource/technical/document/application_note/CD00264321.pdf + +* AN3155: USART protocol used in the STM32(TM) bootloader + http://www.st.com/web/en/resource/technical/document/application_note/CD00264342.pdf + +* AN4221: I2C protocol used in the STM32 bootloader + http://www.st.com/web/en/resource/technical/document/application_note/DM00072315.pdf + +* AN4286: SPI protocol used in the STM32 bootloader + http://www.st.com/web/en/resource/technical/document/application_note/DM00081379.pdf + +Boot mode selection for STM32 is documented in ST application note AN2606, available in ST website: + http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/serial.h b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/serial.h new file mode 100644 index 0000000..227ba16 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/serial.h @@ -0,0 +1,90 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _SERIAL_H +#define _SERIAL_H + +typedef struct serial serial_t; + +typedef enum { + SERIAL_PARITY_NONE, + SERIAL_PARITY_EVEN, + SERIAL_PARITY_ODD, + + SERIAL_PARITY_INVALID +} serial_parity_t; + +typedef enum { + SERIAL_BITS_5, + SERIAL_BITS_6, + SERIAL_BITS_7, + SERIAL_BITS_8, + + SERIAL_BITS_INVALID +} serial_bits_t; + +typedef enum { + SERIAL_BAUD_1200, + SERIAL_BAUD_1800, + SERIAL_BAUD_2400, + SERIAL_BAUD_4800, + SERIAL_BAUD_9600, + SERIAL_BAUD_19200, + SERIAL_BAUD_38400, + SERIAL_BAUD_57600, + SERIAL_BAUD_115200, + SERIAL_BAUD_128000, + SERIAL_BAUD_230400, + SERIAL_BAUD_256000, + SERIAL_BAUD_460800, + SERIAL_BAUD_500000, + SERIAL_BAUD_576000, + SERIAL_BAUD_921600, + SERIAL_BAUD_1000000, + SERIAL_BAUD_1500000, + SERIAL_BAUD_2000000, + + SERIAL_BAUD_INVALID +} serial_baud_t; + +typedef enum { + SERIAL_STOPBIT_1, + SERIAL_STOPBIT_2, + + SERIAL_STOPBIT_INVALID +} serial_stopbit_t; + +typedef enum { + GPIO_RTS = 1, + GPIO_DTR, + GPIO_BRK, +} serial_gpio_t; + +/* common helper functions */ +serial_baud_t serial_get_baud(const unsigned int baud); +unsigned int serial_get_baud_int(const serial_baud_t baud); +serial_bits_t serial_get_bits(const char *mode); +unsigned int serial_get_bits_int(const serial_bits_t bits); +serial_parity_t serial_get_parity(const char *mode); +char serial_get_parity_str(const serial_parity_t parity); +serial_stopbit_t serial_get_stopbit(const char *mode); +unsigned int serial_get_stopbit_int(const serial_stopbit_t stopbit); + +#endif diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/serial_common.c b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/serial_common.c new file mode 100644 index 0000000..43e48e1 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/serial_common.c @@ -0,0 +1,154 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "serial.h" + +serial_baud_t serial_get_baud(const unsigned int baud) { + switch(baud) { + case 1200: return SERIAL_BAUD_1200 ; + case 1800: return SERIAL_BAUD_1800 ; + case 2400: return SERIAL_BAUD_2400 ; + case 4800: return SERIAL_BAUD_4800 ; + case 9600: return SERIAL_BAUD_9600 ; + case 19200: return SERIAL_BAUD_19200 ; + case 38400: return SERIAL_BAUD_38400 ; + case 57600: return SERIAL_BAUD_57600 ; + case 115200: return SERIAL_BAUD_115200; + case 128000: return SERIAL_BAUD_128000; + case 230400: return SERIAL_BAUD_230400; + case 256000: return SERIAL_BAUD_256000; + case 460800: return SERIAL_BAUD_460800; + case 500000: return SERIAL_BAUD_500000; + case 576000: return SERIAL_BAUD_576000; + case 921600: return SERIAL_BAUD_921600; + case 1000000: return SERIAL_BAUD_1000000; + case 1500000: return SERIAL_BAUD_1500000; + case 2000000: return SERIAL_BAUD_2000000; + + default: + return SERIAL_BAUD_INVALID; + } +} + +unsigned int serial_get_baud_int(const serial_baud_t baud) { + switch(baud) { + case SERIAL_BAUD_1200 : return 1200 ; + case SERIAL_BAUD_1800 : return 1800 ; + case SERIAL_BAUD_2400 : return 2400 ; + case SERIAL_BAUD_4800 : return 4800 ; + case SERIAL_BAUD_9600 : return 9600 ; + case SERIAL_BAUD_19200 : return 19200 ; + case SERIAL_BAUD_38400 : return 38400 ; + case SERIAL_BAUD_57600 : return 57600 ; + case SERIAL_BAUD_115200: return 115200; + case SERIAL_BAUD_128000: return 128000; + case SERIAL_BAUD_230400: return 230400; + case SERIAL_BAUD_256000: return 256000; + case SERIAL_BAUD_460800: return 460800; + case SERIAL_BAUD_500000: return 500000; + case SERIAL_BAUD_576000: return 576000; + case SERIAL_BAUD_921600: return 921600; + case SERIAL_BAUD_1000000: return 1000000; + case SERIAL_BAUD_1500000: return 1500000; + case SERIAL_BAUD_2000000: return 2000000; + + case SERIAL_BAUD_INVALID: + default: + return 0; + } +} + +serial_bits_t serial_get_bits(const char *mode) { + if (!mode) + return SERIAL_BITS_INVALID; + switch(mode[0]) { + case '5': return SERIAL_BITS_5; + case '6': return SERIAL_BITS_6; + case '7': return SERIAL_BITS_7; + case '8': return SERIAL_BITS_8; + + default: + return SERIAL_BITS_INVALID; + } +} + +unsigned int serial_get_bits_int(const serial_bits_t bits) { + switch(bits) { + case SERIAL_BITS_5: return 5; + case SERIAL_BITS_6: return 6; + case SERIAL_BITS_7: return 7; + case SERIAL_BITS_8: return 8; + + default: + return 0; + } +} + +serial_parity_t serial_get_parity(const char *mode) { + if (!mode || !mode[0]) + return SERIAL_PARITY_INVALID; + switch(mode[1]) { + case 'N': + case 'n': + return SERIAL_PARITY_NONE; + case 'E': + case 'e': + return SERIAL_PARITY_EVEN; + case 'O': + case 'o': + return SERIAL_PARITY_ODD; + + default: + return SERIAL_PARITY_INVALID; + } +} + +char serial_get_parity_str(const serial_parity_t parity) { + switch(parity) { + case SERIAL_PARITY_NONE: return 'N'; + case SERIAL_PARITY_EVEN: return 'E'; + case SERIAL_PARITY_ODD : return 'O'; + + default: + return ' '; + } +} + +serial_stopbit_t serial_get_stopbit(const char *mode) { + if (!mode || !mode[0] || !mode[1]) + return SERIAL_STOPBIT_INVALID; + switch(mode[2]) { + case '1': return SERIAL_STOPBIT_1; + case '2': return SERIAL_STOPBIT_2; + + default: + return SERIAL_STOPBIT_INVALID; + } +} + +unsigned int serial_get_stopbit_int(const serial_stopbit_t stopbit) { + switch(stopbit) { + case SERIAL_STOPBIT_1: return 1; + case SERIAL_STOPBIT_2: return 2; + + default: + return 0; + } +} + diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/serial_platform.c b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/serial_platform.c new file mode 100644 index 0000000..98e2569 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/serial_platform.c @@ -0,0 +1,5 @@ +#if defined(__WIN32__) || defined(__CYGWIN__) +# include "serial_w32.c" +#else +# include "serial_posix.c" +#endif diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/serial_posix.c b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/serial_posix.c new file mode 100644 index 0000000..284b35b --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/serial_posix.c @@ -0,0 +1,395 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "serial.h" +#include "port.h" + +struct serial { + int fd; + struct termios oldtio; + struct termios newtio; + char setup_str[11]; +}; + +static serial_t *serial_open(const char *device) +{ + serial_t *h = calloc(sizeof(serial_t), 1); + + h->fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY); + if (h->fd < 0) { + free(h); + return NULL; + } + fcntl(h->fd, F_SETFL, 0); + + tcgetattr(h->fd, &h->oldtio); + tcgetattr(h->fd, &h->newtio); + + return h; +} + +static void serial_flush(const serial_t *h) +{ + tcflush(h->fd, TCIFLUSH); +} + +static void serial_close(serial_t *h) +{ + serial_flush(h); + tcsetattr(h->fd, TCSANOW, &h->oldtio); + close(h->fd); + free(h); +} + +static port_err_t serial_setup(serial_t *h, const serial_baud_t baud, + const serial_bits_t bits, + const serial_parity_t parity, + const serial_stopbit_t stopbit) +{ + speed_t port_baud; + tcflag_t port_bits; + tcflag_t port_parity; + tcflag_t port_stop; + struct termios settings; + + switch (baud) { + case SERIAL_BAUD_1200: port_baud = B1200; break; + case SERIAL_BAUD_1800: port_baud = B1800; break; + case SERIAL_BAUD_2400: port_baud = B2400; break; + case SERIAL_BAUD_4800: port_baud = B4800; break; + case SERIAL_BAUD_9600: port_baud = B9600; break; + case SERIAL_BAUD_19200: port_baud = B19200; break; + case SERIAL_BAUD_38400: port_baud = B38400; break; + case SERIAL_BAUD_57600: port_baud = B57600; break; + case SERIAL_BAUD_115200: port_baud = B115200; break; + case SERIAL_BAUD_230400: port_baud = B230400; break; +#ifdef B460800 + case SERIAL_BAUD_460800: port_baud = B460800; break; +#endif /* B460800 */ +#ifdef B921600 + case SERIAL_BAUD_921600: port_baud = B921600; break; +#endif /* B921600 */ +#ifdef B500000 + case SERIAL_BAUD_500000: port_baud = B500000; break; +#endif /* B500000 */ +#ifdef B576000 + case SERIAL_BAUD_576000: port_baud = B576000; break; +#endif /* B576000 */ +#ifdef B1000000 + case SERIAL_BAUD_1000000: port_baud = B1000000; break; +#endif /* B1000000 */ +#ifdef B1500000 + case SERIAL_BAUD_1500000: port_baud = B1500000; break; +#endif /* B1500000 */ +#ifdef B2000000 + case SERIAL_BAUD_2000000: port_baud = B2000000; break; +#endif /* B2000000 */ + + case SERIAL_BAUD_INVALID: + default: + return PORT_ERR_UNKNOWN; + } + + switch (bits) { + case SERIAL_BITS_5: port_bits = CS5; break; + case SERIAL_BITS_6: port_bits = CS6; break; + case SERIAL_BITS_7: port_bits = CS7; break; + case SERIAL_BITS_8: port_bits = CS8; break; + + default: + return PORT_ERR_UNKNOWN; + } + + switch (parity) { + case SERIAL_PARITY_NONE: port_parity = 0; break; + case SERIAL_PARITY_EVEN: port_parity = PARENB; break; + case SERIAL_PARITY_ODD: port_parity = PARENB | PARODD; break; + + default: + return PORT_ERR_UNKNOWN; + } + + switch (stopbit) { + case SERIAL_STOPBIT_1: port_stop = 0; break; + case SERIAL_STOPBIT_2: port_stop = CSTOPB; break; + + default: + return PORT_ERR_UNKNOWN; + } + + /* reset the settings */ +#ifndef __sun /* Used by GNU and BSD. Ignore __SVR4 in test. */ + cfmakeraw(&h->newtio); +#else /* __sun */ + h->newtio.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR + | IGNCR | ICRNL | IXON); + if (port_parity) + h->newtio.c_iflag |= INPCK; + + h->newtio.c_oflag &= ~OPOST; + h->newtio.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); + h->newtio.c_cflag &= ~(CSIZE | PARENB); + h->newtio.c_cflag |= CS8; +#endif /* __sun */ +#ifdef __QNXNTO__ + h->newtio.c_cflag &= ~(CSIZE | IHFLOW | OHFLOW); +#else + h->newtio.c_cflag &= ~(CSIZE | CRTSCTS); +#endif + h->newtio.c_cflag &= ~(CSIZE | CRTSCTS); + h->newtio.c_iflag &= ~(IXON | IXOFF | IXANY | IGNPAR); + h->newtio.c_lflag &= ~(ECHOK | ECHOCTL | ECHOKE); + h->newtio.c_oflag &= ~(OPOST | ONLCR); + + /* setup the new settings */ + cfsetispeed(&h->newtio, port_baud); + cfsetospeed(&h->newtio, port_baud); + h->newtio.c_cflag |= + port_parity | + port_bits | + port_stop | + CLOCAL | + CREAD; + + h->newtio.c_cc[VMIN] = 0; + h->newtio.c_cc[VTIME] = 5; /* in units of 0.1 s */ + + /* set the settings */ + serial_flush(h); + if (tcsetattr(h->fd, TCSANOW, &h->newtio) != 0) + return PORT_ERR_UNKNOWN; + +/* this check fails on CDC-ACM devices, bits 16 and 17 of cflag differ! + * it has been disabled below for now -jcw, 2015-11-09 + if (settings.c_cflag != h->newtio.c_cflag) + fprintf(stderr, "c_cflag mismatch %lx\n", + settings.c_cflag ^ h->newtio.c_cflag); + */ + + /* confirm they were set */ + tcgetattr(h->fd, &settings); + if (settings.c_iflag != h->newtio.c_iflag || + settings.c_oflag != h->newtio.c_oflag || + //settings.c_cflag != h->newtio.c_cflag || + settings.c_lflag != h->newtio.c_lflag) + return PORT_ERR_UNKNOWN; + + snprintf(h->setup_str, sizeof(h->setup_str), "%u %d%c%d", + serial_get_baud_int(baud), + serial_get_bits_int(bits), + serial_get_parity_str(parity), + serial_get_stopbit_int(stopbit)); + return PORT_ERR_OK; +} + +/* + * Roger clark. + * This function is no longer used. But has just been commented out in case it needs + * to be reinstated in the future + +static int startswith(const char *haystack, const char *needle) { + return strncmp(haystack, needle, strlen(needle)) == 0; +} +*/ + +static int is_tty(const char *path) { + char resolved[PATH_MAX]; + + if(!realpath(path, resolved)) return 0; + + + /* + * Roger Clark + * Commented out this check, because on OSX some devices are /dev/cu + * and some users use symbolic links to devices, hence the name may not even start + * with /dev + + if(startswith(resolved, "/dev/tty")) return 1; + + return 0; + */ + + return 1; +} + +static port_err_t serial_posix_open(struct port_interface *port, + struct port_options *ops) +{ + serial_t *h; + + /* 1. check device name match */ + if (!is_tty(ops->device)) + return PORT_ERR_NODEV; + + /* 2. check options */ + if (ops->baudRate == SERIAL_BAUD_INVALID) + return PORT_ERR_UNKNOWN; + if (serial_get_bits(ops->serial_mode) == SERIAL_BITS_INVALID) + return PORT_ERR_UNKNOWN; + if (serial_get_parity(ops->serial_mode) == SERIAL_PARITY_INVALID) + return PORT_ERR_UNKNOWN; + if (serial_get_stopbit(ops->serial_mode) == SERIAL_STOPBIT_INVALID) + return PORT_ERR_UNKNOWN; + + /* 3. open it */ + h = serial_open(ops->device); + if (h == NULL) + return PORT_ERR_UNKNOWN; + + /* 4. set options */ + if (serial_setup(h, ops->baudRate, + serial_get_bits(ops->serial_mode), + serial_get_parity(ops->serial_mode), + serial_get_stopbit(ops->serial_mode) + ) != PORT_ERR_OK) { + serial_close(h); + return PORT_ERR_UNKNOWN; + } + + port->private = h; + return PORT_ERR_OK; +} + +static port_err_t serial_posix_close(struct port_interface *port) +{ + serial_t *h; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + serial_close(h); + port->private = NULL; + return PORT_ERR_OK; +} + +static port_err_t serial_posix_read(struct port_interface *port, void *buf, + size_t nbyte) +{ + serial_t *h; + ssize_t r; + uint8_t *pos = (uint8_t *)buf; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + while (nbyte) { + r = read(h->fd, pos, nbyte); + if (r == 0) + return PORT_ERR_TIMEDOUT; + if (r < 0) + return PORT_ERR_UNKNOWN; + + nbyte -= r; + pos += r; + } + return PORT_ERR_OK; +} + +static port_err_t serial_posix_write(struct port_interface *port, void *buf, + size_t nbyte) +{ + serial_t *h; + ssize_t r; + const uint8_t *pos = (const uint8_t *)buf; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + while (nbyte) { + r = write(h->fd, pos, nbyte); + if (r < 1) + return PORT_ERR_UNKNOWN; + + nbyte -= r; + pos += r; + } + return PORT_ERR_OK; +} + +static port_err_t serial_posix_gpio(struct port_interface *port, + serial_gpio_t n, int level) +{ + serial_t *h; + int bit, lines; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + switch (n) { + case GPIO_RTS: + bit = TIOCM_RTS; + break; + + case GPIO_DTR: + bit = TIOCM_DTR; + break; + + case GPIO_BRK: + if (level == 0) + return PORT_ERR_OK; + if (tcsendbreak(h->fd, 1)) + return PORT_ERR_UNKNOWN; + return PORT_ERR_OK; + + default: + return PORT_ERR_UNKNOWN; + } + + /* handle RTS/DTR */ + if (ioctl(h->fd, TIOCMGET, &lines)) + return PORT_ERR_UNKNOWN; + lines = level ? lines | bit : lines & ~bit; + if (ioctl(h->fd, TIOCMSET, &lines)) + return PORT_ERR_UNKNOWN; + + return PORT_ERR_OK; +} + +static const char *serial_posix_get_cfg_str(struct port_interface *port) +{ + serial_t *h; + + h = (serial_t *)port->private; + return h ? h->setup_str : "INVALID"; +} + +struct port_interface port_serial = { + .name = "serial_posix", + .flags = PORT_BYTE | PORT_GVR_ETX | PORT_CMD_INIT | PORT_RETRY, + .open = serial_posix_open, + .close = serial_posix_close, + .read = serial_posix_read, + .write = serial_posix_write, + .gpio = serial_posix_gpio, + .get_cfg_str = serial_posix_get_cfg_str, +}; diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/serial_w32.c b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/serial_w32.c new file mode 100644 index 0000000..56772c0 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/serial_w32.c @@ -0,0 +1,341 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + Copyright (C) 2010 Gareth McMullin + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "serial.h" +#include "port.h" + +struct serial { + HANDLE fd; + DCB oldtio; + DCB newtio; + char setup_str[11]; +}; + +static serial_t *serial_open(const char *device) +{ + serial_t *h = calloc(sizeof(serial_t), 1); + char *devName; + + /* timeout in ms */ + COMMTIMEOUTS timeouts = {MAXDWORD, MAXDWORD, 500, 0, 0}; + + /* Fix the device name if required */ + if (strlen(device) > 4 && device[0] != '\\') { + devName = calloc(1, strlen(device) + 5); + sprintf(devName, "\\\\.\\%s", device); + } else { + devName = (char *)device; + } + + /* Create file handle for port */ + h->fd = CreateFile(devName, GENERIC_READ | GENERIC_WRITE, + 0, /* Exclusive access */ + NULL, /* No security */ + OPEN_EXISTING, + 0, /* No overlap */ + NULL); + + if (devName != device) + free(devName); + + if (h->fd == INVALID_HANDLE_VALUE) { + if (GetLastError() == ERROR_FILE_NOT_FOUND) + fprintf(stderr, "File not found: %s\n", device); + return NULL; + } + + SetupComm(h->fd, 4096, 4096); /* Set input and output buffer size */ + + SetCommTimeouts(h->fd, &timeouts); + + SetCommMask(h->fd, EV_ERR); /* Notify us of error events */ + + GetCommState(h->fd, &h->oldtio); /* Retrieve port parameters */ + GetCommState(h->fd, &h->newtio); /* Retrieve port parameters */ + + /* PurgeComm(h->fd, PURGE_RXABORT | PURGE_TXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR); */ + + return h; +} + +static void serial_flush(const serial_t *h) +{ + /* We shouldn't need to flush in non-overlapping (blocking) mode */ + /* tcflush(h->fd, TCIFLUSH); */ +} + +static void serial_close(serial_t *h) +{ + serial_flush(h); + SetCommState(h->fd, &h->oldtio); + CloseHandle(h->fd); + free(h); +} + +static port_err_t serial_setup(serial_t *h, + const serial_baud_t baud, + const serial_bits_t bits, + const serial_parity_t parity, + const serial_stopbit_t stopbit) +{ + switch (baud) { + case SERIAL_BAUD_1200: h->newtio.BaudRate = CBR_1200; break; + /* case SERIAL_BAUD_1800: h->newtio.BaudRate = CBR_1800; break; */ + case SERIAL_BAUD_2400: h->newtio.BaudRate = CBR_2400; break; + case SERIAL_BAUD_4800: h->newtio.BaudRate = CBR_4800; break; + case SERIAL_BAUD_9600: h->newtio.BaudRate = CBR_9600; break; + case SERIAL_BAUD_19200: h->newtio.BaudRate = CBR_19200; break; + case SERIAL_BAUD_38400: h->newtio.BaudRate = CBR_38400; break; + case SERIAL_BAUD_57600: h->newtio.BaudRate = CBR_57600; break; + case SERIAL_BAUD_115200: h->newtio.BaudRate = CBR_115200; break; + case SERIAL_BAUD_128000: h->newtio.BaudRate = CBR_128000; break; + case SERIAL_BAUD_256000: h->newtio.BaudRate = CBR_256000; break; + /* These are not defined in WinBase.h and might work or not */ + case SERIAL_BAUD_230400: h->newtio.BaudRate = 230400; break; + case SERIAL_BAUD_460800: h->newtio.BaudRate = 460800; break; + case SERIAL_BAUD_500000: h->newtio.BaudRate = 500000; break; + case SERIAL_BAUD_576000: h->newtio.BaudRate = 576000; break; + case SERIAL_BAUD_921600: h->newtio.BaudRate = 921600; break; + case SERIAL_BAUD_1000000: h->newtio.BaudRate = 1000000; break; + case SERIAL_BAUD_1500000: h->newtio.BaudRate = 1500000; break; + case SERIAL_BAUD_2000000: h->newtio.BaudRate = 2000000; break; + case SERIAL_BAUD_INVALID: + + default: + return PORT_ERR_UNKNOWN; + } + + switch (bits) { + case SERIAL_BITS_5: h->newtio.ByteSize = 5; break; + case SERIAL_BITS_6: h->newtio.ByteSize = 6; break; + case SERIAL_BITS_7: h->newtio.ByteSize = 7; break; + case SERIAL_BITS_8: h->newtio.ByteSize = 8; break; + + default: + return PORT_ERR_UNKNOWN; + } + + switch (parity) { + case SERIAL_PARITY_NONE: h->newtio.Parity = NOPARITY; break; + case SERIAL_PARITY_EVEN: h->newtio.Parity = EVENPARITY; break; + case SERIAL_PARITY_ODD: h->newtio.Parity = ODDPARITY; break; + + default: + return PORT_ERR_UNKNOWN; + } + + switch (stopbit) { + case SERIAL_STOPBIT_1: h->newtio.StopBits = ONESTOPBIT; break; + case SERIAL_STOPBIT_2: h->newtio.StopBits = TWOSTOPBITS; break; + + default: + return PORT_ERR_UNKNOWN; + } + + /* reset the settings */ + h->newtio.fOutxCtsFlow = FALSE; + h->newtio.fOutxDsrFlow = FALSE; + h->newtio.fOutX = FALSE; + h->newtio.fInX = FALSE; + h->newtio.fNull = 0; + h->newtio.fAbortOnError = 0; + + /* set the settings */ + serial_flush(h); + if (!SetCommState(h->fd, &h->newtio)) + return PORT_ERR_UNKNOWN; + + snprintf(h->setup_str, sizeof(h->setup_str), "%u %d%c%d", + serial_get_baud_int(baud), + serial_get_bits_int(bits), + serial_get_parity_str(parity), + serial_get_stopbit_int(stopbit) + ); + return PORT_ERR_OK; +} + +static port_err_t serial_w32_open(struct port_interface *port, + struct port_options *ops) +{ + serial_t *h; + + /* 1. check device name match */ + if (!((strlen(ops->device) == 4 || strlen(ops->device) == 5) + && !strncmp(ops->device, "COM", 3) && isdigit(ops->device[3])) + && !(!strncmp(ops->device, "\\\\.\\COM", strlen("\\\\.\\COM")) + && isdigit(ops->device[strlen("\\\\.\\COM")]))) + return PORT_ERR_NODEV; + + /* 2. check options */ + if (ops->baudRate == SERIAL_BAUD_INVALID) + return PORT_ERR_UNKNOWN; + if (serial_get_bits(ops->serial_mode) == SERIAL_BITS_INVALID) + return PORT_ERR_UNKNOWN; + if (serial_get_parity(ops->serial_mode) == SERIAL_PARITY_INVALID) + return PORT_ERR_UNKNOWN; + if (serial_get_stopbit(ops->serial_mode) == SERIAL_STOPBIT_INVALID) + return PORT_ERR_UNKNOWN; + + /* 3. open it */ + h = serial_open(ops->device); + if (h == NULL) + return PORT_ERR_UNKNOWN; + + /* 4. set options */ + if (serial_setup(h, ops->baudRate, + serial_get_bits(ops->serial_mode), + serial_get_parity(ops->serial_mode), + serial_get_stopbit(ops->serial_mode) + ) != PORT_ERR_OK) { + serial_close(h); + return PORT_ERR_UNKNOWN; + } + + port->private = h; + return PORT_ERR_OK; +} + +static port_err_t serial_w32_close(struct port_interface *port) +{ + serial_t *h; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + serial_close(h); + port->private = NULL; + return PORT_ERR_OK; +} + +static port_err_t serial_w32_read(struct port_interface *port, void *buf, + size_t nbyte) +{ + serial_t *h; + DWORD r; + uint8_t *pos = (uint8_t *)buf; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + while (nbyte) { + ReadFile(h->fd, pos, nbyte, &r, NULL); + if (r == 0) + return PORT_ERR_TIMEDOUT; + if (r < 0) + return PORT_ERR_UNKNOWN; + + nbyte -= r; + pos += r; + } + return PORT_ERR_OK; +} + +static port_err_t serial_w32_write(struct port_interface *port, void *buf, + size_t nbyte) +{ + serial_t *h; + DWORD r; + uint8_t *pos = (uint8_t *)buf; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + while (nbyte) { + if (!WriteFile(h->fd, pos, nbyte, &r, NULL)) + return PORT_ERR_UNKNOWN; + if (r < 1) + return PORT_ERR_UNKNOWN; + + nbyte -= r; + pos += r; + } + return PORT_ERR_OK; +} + +static port_err_t serial_w32_gpio(struct port_interface *port, + serial_gpio_t n, int level) +{ + serial_t *h; + int bit; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + switch (n) { + case GPIO_RTS: + bit = level ? SETRTS : CLRRTS; + break; + + case GPIO_DTR: + bit = level ? SETDTR : CLRDTR; + break; + + case GPIO_BRK: + if (level == 0) + return PORT_ERR_OK; + if (EscapeCommFunction(h->fd, SETBREAK) == 0) + return PORT_ERR_UNKNOWN; + usleep(500000); + if (EscapeCommFunction(h->fd, CLRBREAK) == 0) + return PORT_ERR_UNKNOWN; + return PORT_ERR_OK; + + default: + return PORT_ERR_UNKNOWN; + } + + /* handle RTS/DTR */ + if (EscapeCommFunction(h->fd, bit) == 0) + return PORT_ERR_UNKNOWN; + + return PORT_ERR_OK; +} + +static const char *serial_w32_get_cfg_str(struct port_interface *port) +{ + serial_t *h; + + h = (serial_t *)port->private; + return h ? h->setup_str : "INVALID"; +} + +struct port_interface port_serial = { + .name = "serial_w32", + .flags = PORT_BYTE | PORT_GVR_ETX | PORT_CMD_INIT | PORT_RETRY, + .open = serial_w32_open, + .close = serial_w32_close, + .read = serial_w32_read, + .write = serial_w32_write, + .gpio = serial_w32_gpio, + .get_cfg_str = serial_w32_get_cfg_str, +}; diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/stm32.c b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/stm32.c new file mode 100644 index 0000000..74047d2 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/stm32.c @@ -0,0 +1,1048 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright 2010 Geoffrey McRae + Copyright 2012-2014 Tormod Volden + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include + +#include "stm32.h" +#include "port.h" +#include "utils.h" + +#define STM32_ACK 0x79 +#define STM32_NACK 0x1F +#define STM32_BUSY 0x76 + +#define STM32_CMD_INIT 0x7F +#define STM32_CMD_GET 0x00 /* get the version and command supported */ +#define STM32_CMD_GVR 0x01 /* get version and read protection status */ +#define STM32_CMD_GID 0x02 /* get ID */ +#define STM32_CMD_RM 0x11 /* read memory */ +#define STM32_CMD_GO 0x21 /* go */ +#define STM32_CMD_WM 0x31 /* write memory */ +#define STM32_CMD_WM_NS 0x32 /* no-stretch write memory */ +#define STM32_CMD_ER 0x43 /* erase */ +#define STM32_CMD_EE 0x44 /* extended erase */ +#define STM32_CMD_EE_NS 0x45 /* extended erase no-stretch */ +#define STM32_CMD_WP 0x63 /* write protect */ +#define STM32_CMD_WP_NS 0x64 /* write protect no-stretch */ +#define STM32_CMD_UW 0x73 /* write unprotect */ +#define STM32_CMD_UW_NS 0x74 /* write unprotect no-stretch */ +#define STM32_CMD_RP 0x82 /* readout protect */ +#define STM32_CMD_RP_NS 0x83 /* readout protect no-stretch */ +#define STM32_CMD_UR 0x92 /* readout unprotect */ +#define STM32_CMD_UR_NS 0x93 /* readout unprotect no-stretch */ +#define STM32_CMD_CRC 0xA1 /* compute CRC */ +#define STM32_CMD_ERR 0xFF /* not a valid command */ + +#define STM32_RESYNC_TIMEOUT 35 /* seconds */ +#define STM32_MASSERASE_TIMEOUT 35 /* seconds */ +#define STM32_SECTERASE_TIMEOUT 5 /* seconds */ +#define STM32_BLKWRITE_TIMEOUT 1 /* seconds */ +#define STM32_WUNPROT_TIMEOUT 1 /* seconds */ +#define STM32_WPROT_TIMEOUT 1 /* seconds */ +#define STM32_RPROT_TIMEOUT 1 /* seconds */ + +#define STM32_CMD_GET_LENGTH 17 /* bytes in the reply */ + +struct stm32_cmd { + uint8_t get; + uint8_t gvr; + uint8_t gid; + uint8_t rm; + uint8_t go; + uint8_t wm; + uint8_t er; /* this may be extended erase */ + uint8_t wp; + uint8_t uw; + uint8_t rp; + uint8_t ur; + uint8_t crc; +}; + +/* Reset code for ARMv7-M (Cortex-M3) and ARMv6-M (Cortex-M0) + * see ARMv7-M or ARMv6-M Architecture Reference Manual (table B3-8) + * or "The definitive guide to the ARM Cortex-M3", section 14.4. + */ +static const uint8_t stm_reset_code[] = { + 0x01, 0x49, // ldr r1, [pc, #4] ; () + 0x02, 0x4A, // ldr r2, [pc, #8] ; () + 0x0A, 0x60, // str r2, [r1, #0] + 0xfe, 0xe7, // endless: b endless + 0x0c, 0xed, 0x00, 0xe0, // .word 0xe000ed0c = NVIC AIRCR register address + 0x04, 0x00, 0xfa, 0x05 // .word 0x05fa0004 = VECTKEY | SYSRESETREQ +}; + +static const uint32_t stm_reset_code_length = sizeof(stm_reset_code); + +extern const stm32_dev_t devices[]; + +static void stm32_warn_stretching(const char *f) +{ + fprintf(stderr, "Attention !!!\n"); + fprintf(stderr, "\tThis %s error could be caused by your I2C\n", f); + fprintf(stderr, "\tcontroller not accepting \"clock stretching\"\n"); + fprintf(stderr, "\tas required by bootloader.\n"); + fprintf(stderr, "\tCheck \"I2C.txt\" in stm32flash source code.\n"); +} + +static stm32_err_t stm32_get_ack_timeout(const stm32_t *stm, time_t timeout) +{ + struct port_interface *port = stm->port; + uint8_t byte; + port_err_t p_err; + time_t t0, t1; + + if (!(port->flags & PORT_RETRY)) + timeout = 0; + + if (timeout) + time(&t0); + + do { + p_err = port->read(port, &byte, 1); + if (p_err == PORT_ERR_TIMEDOUT && timeout) { + time(&t1); + if (t1 < t0 + timeout) + continue; + } + + if (p_err != PORT_ERR_OK) { + fprintf(stderr, "Failed to read ACK byte\n"); + return STM32_ERR_UNKNOWN; + } + + if (byte == STM32_ACK) + return STM32_ERR_OK; + if (byte == STM32_NACK) + return STM32_ERR_NACK; + if (byte != STM32_BUSY) { + fprintf(stderr, "Got byte 0x%02x instead of ACK\n", + byte); + return STM32_ERR_UNKNOWN; + } + } while (1); +} + +static stm32_err_t stm32_get_ack(const stm32_t *stm) +{ + return stm32_get_ack_timeout(stm, 0); +} + +static stm32_err_t stm32_send_command_timeout(const stm32_t *stm, + const uint8_t cmd, + time_t timeout) +{ + struct port_interface *port = stm->port; + stm32_err_t s_err; + port_err_t p_err; + uint8_t buf[2]; + + buf[0] = cmd; + buf[1] = cmd ^ 0xFF; + p_err = port->write(port, buf, 2); + if (p_err != PORT_ERR_OK) { + fprintf(stderr, "Failed to send command\n"); + return STM32_ERR_UNKNOWN; + } + s_err = stm32_get_ack_timeout(stm, timeout); + if (s_err == STM32_ERR_OK) + return STM32_ERR_OK; + if (s_err == STM32_ERR_NACK) + fprintf(stderr, "Got NACK from device on command 0x%02x\n", cmd); + else + fprintf(stderr, "Unexpected reply from device on command 0x%02x\n", cmd); + return STM32_ERR_UNKNOWN; +} + +static stm32_err_t stm32_send_command(const stm32_t *stm, const uint8_t cmd) +{ + return stm32_send_command_timeout(stm, cmd, 0); +} + +/* if we have lost sync, send a wrong command and expect a NACK */ +static stm32_err_t stm32_resync(const stm32_t *stm) +{ + struct port_interface *port = stm->port; + port_err_t p_err; + uint8_t buf[2], ack; + time_t t0, t1; + + time(&t0); + t1 = t0; + + buf[0] = STM32_CMD_ERR; + buf[1] = STM32_CMD_ERR ^ 0xFF; + while (t1 < t0 + STM32_RESYNC_TIMEOUT) { + p_err = port->write(port, buf, 2); + if (p_err != PORT_ERR_OK) { + usleep(500000); + time(&t1); + continue; + } + p_err = port->read(port, &ack, 1); + if (p_err != PORT_ERR_OK) { + time(&t1); + continue; + } + if (ack == STM32_NACK) + return STM32_ERR_OK; + time(&t1); + } + return STM32_ERR_UNKNOWN; +} + +/* + * some command receive reply frame with variable length, and length is + * embedded in reply frame itself. + * We can guess the length, but if we guess wrong the protocol gets out + * of sync. + * Use resync for frame oriented interfaces (e.g. I2C) and byte-by-byte + * read for byte oriented interfaces (e.g. UART). + * + * to run safely, data buffer should be allocated for 256+1 bytes + * + * len is value of the first byte in the frame. + */ +static stm32_err_t stm32_guess_len_cmd(const stm32_t *stm, uint8_t cmd, + uint8_t *data, unsigned int len) +{ + struct port_interface *port = stm->port; + port_err_t p_err; + + if (stm32_send_command(stm, cmd) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + if (port->flags & PORT_BYTE) { + /* interface is UART-like */ + p_err = port->read(port, data, 1); + if (p_err != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + len = data[0]; + p_err = port->read(port, data + 1, len + 1); + if (p_err != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + return STM32_ERR_OK; + } + + p_err = port->read(port, data, len + 2); + if (p_err == PORT_ERR_OK && len == data[0]) + return STM32_ERR_OK; + if (p_err != PORT_ERR_OK) { + /* restart with only one byte */ + if (stm32_resync(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + if (stm32_send_command(stm, cmd) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + p_err = port->read(port, data, 1); + if (p_err != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + } + + fprintf(stderr, "Re sync (len = %d)\n", data[0]); + if (stm32_resync(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + len = data[0]; + if (stm32_send_command(stm, cmd) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + p_err = port->read(port, data, len + 2); + if (p_err != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + return STM32_ERR_OK; +} + +/* + * Some interface, e.g. UART, requires a specific init sequence to let STM32 + * autodetect the interface speed. + * The sequence is only required one time after reset. + * stm32flash has command line flag "-c" to prevent sending the init sequence + * in case it was already sent before. + * User can easily forget adding "-c". In this case the bootloader would + * interpret the init sequence as part of a command message, then waiting for + * the rest of the message blocking the interface. + * This function sends the init sequence and, in case of timeout, recovers + * the interface. + */ +static stm32_err_t stm32_send_init_seq(const stm32_t *stm) +{ + struct port_interface *port = stm->port; + port_err_t p_err; + uint8_t byte, cmd = STM32_CMD_INIT; + + p_err = port->write(port, &cmd, 1); + if (p_err != PORT_ERR_OK) { + fprintf(stderr, "Failed to send init to device\n"); + return STM32_ERR_UNKNOWN; + } + p_err = port->read(port, &byte, 1); + if (p_err == PORT_ERR_OK && byte == STM32_ACK) + return STM32_ERR_OK; + if (p_err == PORT_ERR_OK && byte == STM32_NACK) { + /* We could get error later, but let's continue, for now. */ + fprintf(stderr, + "Warning: the interface was not closed properly.\n"); + return STM32_ERR_OK; + } + if (p_err != PORT_ERR_TIMEDOUT) { + fprintf(stderr, "Failed to init device.\n"); + return STM32_ERR_UNKNOWN; + } + + /* + * Check if previous STM32_CMD_INIT was taken as first byte + * of a command. Send a new byte, we should get back a NACK. + */ + p_err = port->write(port, &cmd, 1); + if (p_err != PORT_ERR_OK) { + fprintf(stderr, "Failed to send init to device\n"); + return STM32_ERR_UNKNOWN; + } + p_err = port->read(port, &byte, 1); + if (p_err == PORT_ERR_OK && byte == STM32_NACK) + return STM32_ERR_OK; + fprintf(stderr, "Failed to init device.\n"); + return STM32_ERR_UNKNOWN; +} + +/* find newer command by higher code */ +#define newer(prev, a) (((prev) == STM32_CMD_ERR) \ + ? (a) \ + : (((prev) > (a)) ? (prev) : (a))) + +stm32_t *stm32_init(struct port_interface *port, const char init) +{ + uint8_t len, val, buf[257]; + stm32_t *stm; + int i, new_cmds; + + stm = calloc(sizeof(stm32_t), 1); + stm->cmd = malloc(sizeof(stm32_cmd_t)); + memset(stm->cmd, STM32_CMD_ERR, sizeof(stm32_cmd_t)); + stm->port = port; + + if ((port->flags & PORT_CMD_INIT) && init) + if (stm32_send_init_seq(stm) != STM32_ERR_OK) + return NULL; + + /* get the version and read protection status */ + if (stm32_send_command(stm, STM32_CMD_GVR) != STM32_ERR_OK) { + stm32_close(stm); + return NULL; + } + + /* From AN, only UART bootloader returns 3 bytes */ + len = (port->flags & PORT_GVR_ETX) ? 3 : 1; + if (port->read(port, buf, len) != PORT_ERR_OK) + return NULL; + stm->version = buf[0]; + stm->option1 = (port->flags & PORT_GVR_ETX) ? buf[1] : 0; + stm->option2 = (port->flags & PORT_GVR_ETX) ? buf[2] : 0; + if (stm32_get_ack(stm) != STM32_ERR_OK) { + stm32_close(stm); + return NULL; + } + + /* get the bootloader information */ + len = STM32_CMD_GET_LENGTH; + if (port->cmd_get_reply) + for (i = 0; port->cmd_get_reply[i].length; i++) + if (stm->version == port->cmd_get_reply[i].version) { + len = port->cmd_get_reply[i].length; + break; + } + if (stm32_guess_len_cmd(stm, STM32_CMD_GET, buf, len) != STM32_ERR_OK) + return NULL; + len = buf[0] + 1; + stm->bl_version = buf[1]; + new_cmds = 0; + for (i = 1; i < len; i++) { + val = buf[i + 1]; + switch (val) { + case STM32_CMD_GET: + stm->cmd->get = val; break; + case STM32_CMD_GVR: + stm->cmd->gvr = val; break; + case STM32_CMD_GID: + stm->cmd->gid = val; break; + case STM32_CMD_RM: + stm->cmd->rm = val; break; + case STM32_CMD_GO: + stm->cmd->go = val; break; + case STM32_CMD_WM: + case STM32_CMD_WM_NS: + stm->cmd->wm = newer(stm->cmd->wm, val); + break; + case STM32_CMD_ER: + case STM32_CMD_EE: + case STM32_CMD_EE_NS: + stm->cmd->er = newer(stm->cmd->er, val); + break; + case STM32_CMD_WP: + case STM32_CMD_WP_NS: + stm->cmd->wp = newer(stm->cmd->wp, val); + break; + case STM32_CMD_UW: + case STM32_CMD_UW_NS: + stm->cmd->uw = newer(stm->cmd->uw, val); + break; + case STM32_CMD_RP: + case STM32_CMD_RP_NS: + stm->cmd->rp = newer(stm->cmd->rp, val); + break; + case STM32_CMD_UR: + case STM32_CMD_UR_NS: + stm->cmd->ur = newer(stm->cmd->ur, val); + break; + case STM32_CMD_CRC: + stm->cmd->crc = newer(stm->cmd->crc, val); + break; + default: + if (new_cmds++ == 0) + fprintf(stderr, + "GET returns unknown commands (0x%2x", + val); + else + fprintf(stderr, ", 0x%2x", val); + } + } + if (new_cmds) + fprintf(stderr, ")\n"); + if (stm32_get_ack(stm) != STM32_ERR_OK) { + stm32_close(stm); + return NULL; + } + + if (stm->cmd->get == STM32_CMD_ERR + || stm->cmd->gvr == STM32_CMD_ERR + || stm->cmd->gid == STM32_CMD_ERR) { + fprintf(stderr, "Error: bootloader did not returned correct information from GET command\n"); + return NULL; + } + + /* get the device ID */ + if (stm32_guess_len_cmd(stm, stm->cmd->gid, buf, 1) != STM32_ERR_OK) { + stm32_close(stm); + return NULL; + } + len = buf[0] + 1; + if (len < 2) { + stm32_close(stm); + fprintf(stderr, "Only %d bytes sent in the PID, unknown/unsupported device\n", len); + return NULL; + } + stm->pid = (buf[1] << 8) | buf[2]; + if (len > 2) { + fprintf(stderr, "This bootloader returns %d extra bytes in PID:", len); + for (i = 2; i <= len ; i++) + fprintf(stderr, " %02x", buf[i]); + fprintf(stderr, "\n"); + } + if (stm32_get_ack(stm) != STM32_ERR_OK) { + stm32_close(stm); + return NULL; + } + + stm->dev = devices; + while (stm->dev->id != 0x00 && stm->dev->id != stm->pid) + ++stm->dev; + + if (!stm->dev->id) { + fprintf(stderr, "Unknown/unsupported device (Device ID: 0x%03x)\n", stm->pid); + stm32_close(stm); + return NULL; + } + + return stm; +} + +void stm32_close(stm32_t *stm) +{ + if (stm) + free(stm->cmd); + free(stm); +} + +stm32_err_t stm32_read_memory(const stm32_t *stm, uint32_t address, + uint8_t data[], unsigned int len) +{ + struct port_interface *port = stm->port; + uint8_t buf[5]; + + if (!len) + return STM32_ERR_OK; + + if (len > 256) { + fprintf(stderr, "Error: READ length limit at 256 bytes\n"); + return STM32_ERR_UNKNOWN; + } + + if (stm->cmd->rm == STM32_CMD_ERR) { + fprintf(stderr, "Error: READ command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->rm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + buf[0] = address >> 24; + buf[1] = (address >> 16) & 0xFF; + buf[2] = (address >> 8) & 0xFF; + buf[3] = address & 0xFF; + buf[4] = buf[0] ^ buf[1] ^ buf[2] ^ buf[3]; + if (port->write(port, buf, 5) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + if (stm32_get_ack(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (stm32_send_command(stm, len - 1) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (port->read(port, data, len) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + + return STM32_ERR_OK; +} + +stm32_err_t stm32_write_memory(const stm32_t *stm, uint32_t address, + const uint8_t data[], unsigned int len) +{ + struct port_interface *port = stm->port; + uint8_t cs, buf[256 + 2]; + unsigned int i, aligned_len; + stm32_err_t s_err; + + if (!len) + return STM32_ERR_OK; + + if (len > 256) { + fprintf(stderr, "Error: READ length limit at 256 bytes\n"); + return STM32_ERR_UNKNOWN; + } + + /* must be 32bit aligned */ + if (address & 0x3 || len & 0x3) { + fprintf(stderr, "Error: WRITE address and length must be 4 byte aligned\n"); + return STM32_ERR_UNKNOWN; + } + + if (stm->cmd->wm == STM32_CMD_ERR) { + fprintf(stderr, "Error: WRITE command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + /* send the address and checksum */ + if (stm32_send_command(stm, stm->cmd->wm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + buf[0] = address >> 24; + buf[1] = (address >> 16) & 0xFF; + buf[2] = (address >> 8) & 0xFF; + buf[3] = address & 0xFF; + buf[4] = buf[0] ^ buf[1] ^ buf[2] ^ buf[3]; + if (port->write(port, buf, 5) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + if (stm32_get_ack(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + aligned_len = (len + 3) & ~3; + cs = aligned_len - 1; + buf[0] = aligned_len - 1; + for (i = 0; i < len; i++) { + cs ^= data[i]; + buf[i + 1] = data[i]; + } + /* padding data */ + for (i = len; i < aligned_len; i++) { + cs ^= 0xFF; + buf[i + 1] = 0xFF; + } + buf[aligned_len + 1] = cs; + if (port->write(port, buf, aligned_len + 2) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + + s_err = stm32_get_ack_timeout(stm, STM32_BLKWRITE_TIMEOUT); + if (s_err != STM32_ERR_OK) { + if (port->flags & PORT_STRETCH_W + && stm->cmd->wm != STM32_CMD_WM_NS) + stm32_warn_stretching("write"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; +} + +stm32_err_t stm32_wunprot_memory(const stm32_t *stm) +{ + struct port_interface *port = stm->port; + stm32_err_t s_err; + + if (stm->cmd->uw == STM32_CMD_ERR) { + fprintf(stderr, "Error: WRITE UNPROTECT command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->uw) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + s_err = stm32_get_ack_timeout(stm, STM32_WUNPROT_TIMEOUT); + if (s_err == STM32_NACK) { + fprintf(stderr, "Error: Failed to WRITE UNPROTECT\n"); + return STM32_ERR_UNKNOWN; + } + if (s_err != STM32_ERR_OK) { + if (port->flags & PORT_STRETCH_W + && stm->cmd->uw != STM32_CMD_UW_NS) + stm32_warn_stretching("WRITE UNPROTECT"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; +} + +stm32_err_t stm32_wprot_memory(const stm32_t *stm) +{ + struct port_interface *port = stm->port; + stm32_err_t s_err; + + if (stm->cmd->wp == STM32_CMD_ERR) { + fprintf(stderr, "Error: WRITE PROTECT command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->wp) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + s_err = stm32_get_ack_timeout(stm, STM32_WPROT_TIMEOUT); + if (s_err == STM32_NACK) { + fprintf(stderr, "Error: Failed to WRITE PROTECT\n"); + return STM32_ERR_UNKNOWN; + } + if (s_err != STM32_ERR_OK) { + if (port->flags & PORT_STRETCH_W + && stm->cmd->wp != STM32_CMD_WP_NS) + stm32_warn_stretching("WRITE PROTECT"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; +} + +stm32_err_t stm32_runprot_memory(const stm32_t *stm) +{ + struct port_interface *port = stm->port; + stm32_err_t s_err; + + if (stm->cmd->ur == STM32_CMD_ERR) { + fprintf(stderr, "Error: READOUT UNPROTECT command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->ur) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + s_err = stm32_get_ack_timeout(stm, STM32_MASSERASE_TIMEOUT); + if (s_err == STM32_NACK) { + fprintf(stderr, "Error: Failed to READOUT UNPROTECT\n"); + return STM32_ERR_UNKNOWN; + } + if (s_err != STM32_ERR_OK) { + if (port->flags & PORT_STRETCH_W + && stm->cmd->ur != STM32_CMD_UR_NS) + stm32_warn_stretching("READOUT UNPROTECT"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; +} + +stm32_err_t stm32_readprot_memory(const stm32_t *stm) +{ + struct port_interface *port = stm->port; + stm32_err_t s_err; + + if (stm->cmd->rp == STM32_CMD_ERR) { + fprintf(stderr, "Error: READOUT PROTECT command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->rp) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + s_err = stm32_get_ack_timeout(stm, STM32_RPROT_TIMEOUT); + if (s_err == STM32_NACK) { + fprintf(stderr, "Error: Failed to READOUT PROTECT\n"); + return STM32_ERR_UNKNOWN; + } + if (s_err != STM32_ERR_OK) { + if (port->flags & PORT_STRETCH_W + && stm->cmd->rp != STM32_CMD_RP_NS) + stm32_warn_stretching("READOUT PROTECT"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; +} + +stm32_err_t stm32_erase_memory(const stm32_t *stm, uint8_t spage, uint8_t pages) +{ + struct port_interface *port = stm->port; + stm32_err_t s_err; + port_err_t p_err; + + if (!pages) + return STM32_ERR_OK; + + if (stm->cmd->er == STM32_CMD_ERR) { + fprintf(stderr, "Error: ERASE command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->er) != STM32_ERR_OK) { + fprintf(stderr, "Can't initiate chip erase!\n"); + return STM32_ERR_UNKNOWN; + } + + /* The erase command reported by the bootloader is either 0x43, 0x44 or 0x45 */ + /* 0x44 is Extended Erase, a 2 byte based protocol and needs to be handled differently. */ + /* 0x45 is clock no-stretching version of Extended Erase for I2C port. */ + if (stm->cmd->er != STM32_CMD_ER) { + /* Not all chips using Extended Erase support mass erase */ + /* Currently known as not supporting mass erase is the Ultra Low Power STM32L15xx range */ + /* So if someone has not overridden the default, but uses one of these chips, take it out of */ + /* mass erase mode, so it will be done page by page. This maximum might not be correct either! */ + if (stm->pid == 0x416 && pages == 0xFF) + pages = 0xF8; /* works for the STM32L152RB with 128Kb flash */ + + if (pages == 0xFF) { + uint8_t buf[3]; + + /* 0xFFFF the magic number for mass erase */ + buf[0] = 0xFF; + buf[1] = 0xFF; + buf[2] = 0x00; /* checksum */ + if (port->write(port, buf, 3) != PORT_ERR_OK) { + fprintf(stderr, "Mass erase error.\n"); + return STM32_ERR_UNKNOWN; + } + s_err = stm32_get_ack_timeout(stm, STM32_MASSERASE_TIMEOUT); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Mass erase failed. Try specifying the number of pages to be erased.\n"); + if (port->flags & PORT_STRETCH_W + && stm->cmd->er != STM32_CMD_EE_NS) + stm32_warn_stretching("erase"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; + } + + uint16_t pg_num; + uint8_t pg_byte; + uint8_t cs = 0; + uint8_t *buf; + int i = 0; + + buf = malloc(2 + 2 * pages + 1); + if (!buf) + return STM32_ERR_UNKNOWN; + + /* Number of pages to be erased - 1, two bytes, MSB first */ + pg_byte = (pages - 1) >> 8; + buf[i++] = pg_byte; + cs ^= pg_byte; + pg_byte = (pages - 1) & 0xFF; + buf[i++] = pg_byte; + cs ^= pg_byte; + + for (pg_num = spage; pg_num < spage + pages; pg_num++) { + pg_byte = pg_num >> 8; + cs ^= pg_byte; + buf[i++] = pg_byte; + pg_byte = pg_num & 0xFF; + cs ^= pg_byte; + buf[i++] = pg_byte; + } + buf[i++] = cs; + p_err = port->write(port, buf, i); + free(buf); + if (p_err != PORT_ERR_OK) { + fprintf(stderr, "Page-by-page erase error.\n"); + return STM32_ERR_UNKNOWN; + } + + s_err = stm32_get_ack_timeout(stm, pages * STM32_SECTERASE_TIMEOUT); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Page-by-page erase failed. Check the maximum pages your device supports.\n"); + if (port->flags & PORT_STRETCH_W + && stm->cmd->er != STM32_CMD_EE_NS) + stm32_warn_stretching("erase"); + return STM32_ERR_UNKNOWN; + } + + return STM32_ERR_OK; + } + + /* And now the regular erase (0x43) for all other chips */ + if (pages == 0xFF) { + s_err = stm32_send_command_timeout(stm, 0xFF, STM32_MASSERASE_TIMEOUT); + if (s_err != STM32_ERR_OK) { + if (port->flags & PORT_STRETCH_W) + stm32_warn_stretching("erase"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; + } else { + uint8_t cs = 0; + uint8_t pg_num; + uint8_t *buf; + int i = 0; + + buf = malloc(1 + pages + 1); + if (!buf) + return STM32_ERR_UNKNOWN; + + buf[i++] = pages - 1; + cs ^= (pages-1); + for (pg_num = spage; pg_num < (pages + spage); pg_num++) { + buf[i++] = pg_num; + cs ^= pg_num; + } + buf[i++] = cs; + p_err = port->write(port, buf, i); + free(buf); + if (p_err != PORT_ERR_OK) { + fprintf(stderr, "Erase failed.\n"); + return STM32_ERR_UNKNOWN; + } + s_err = stm32_get_ack_timeout(stm, STM32_MASSERASE_TIMEOUT); + if (s_err != STM32_ERR_OK) { + if (port->flags & PORT_STRETCH_W) + stm32_warn_stretching("erase"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; + } +} + +static stm32_err_t stm32_run_raw_code(const stm32_t *stm, + uint32_t target_address, + const uint8_t *code, uint32_t code_size) +{ + uint32_t stack_le = le_u32(0x20002000); + uint32_t code_address_le = le_u32(target_address + 8); + uint32_t length = code_size + 8; + uint8_t *mem, *pos; + uint32_t address, w; + + /* Must be 32-bit aligned */ + if (target_address & 0x3) { + fprintf(stderr, "Error: code address must be 4 byte aligned\n"); + return STM32_ERR_UNKNOWN; + } + + mem = malloc(length); + if (!mem) + return STM32_ERR_UNKNOWN; + + memcpy(mem, &stack_le, sizeof(uint32_t)); + memcpy(mem + 4, &code_address_le, sizeof(uint32_t)); + memcpy(mem + 8, code, code_size); + + pos = mem; + address = target_address; + while (length > 0) { + w = length > 256 ? 256 : length; + if (stm32_write_memory(stm, address, pos, w) != STM32_ERR_OK) { + free(mem); + return STM32_ERR_UNKNOWN; + } + + address += w; + pos += w; + length -= w; + } + + free(mem); + return stm32_go(stm, target_address); +} + +stm32_err_t stm32_go(const stm32_t *stm, uint32_t address) +{ + struct port_interface *port = stm->port; + uint8_t buf[5]; + + if (stm->cmd->go == STM32_CMD_ERR) { + fprintf(stderr, "Error: GO command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->go) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + buf[0] = address >> 24; + buf[1] = (address >> 16) & 0xFF; + buf[2] = (address >> 8) & 0xFF; + buf[3] = address & 0xFF; + buf[4] = buf[0] ^ buf[1] ^ buf[2] ^ buf[3]; + if (port->write(port, buf, 5) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (stm32_get_ack(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + return STM32_ERR_OK; +} + +stm32_err_t stm32_reset_device(const stm32_t *stm) +{ + uint32_t target_address = stm->dev->ram_start; + + return stm32_run_raw_code(stm, target_address, stm_reset_code, stm_reset_code_length); +} + +stm32_err_t stm32_crc_memory(const stm32_t *stm, uint32_t address, + uint32_t length, uint32_t *crc) +{ + struct port_interface *port = stm->port; + uint8_t buf[5]; + + if (address & 0x3 || length & 0x3) { + fprintf(stderr, "Start and end addresses must be 4 byte aligned\n"); + return STM32_ERR_UNKNOWN; + } + + if (stm->cmd->crc == STM32_CMD_ERR) { + fprintf(stderr, "Error: CRC command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->crc) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + buf[0] = address >> 24; + buf[1] = (address >> 16) & 0xFF; + buf[2] = (address >> 8) & 0xFF; + buf[3] = address & 0xFF; + buf[4] = buf[0] ^ buf[1] ^ buf[2] ^ buf[3]; + if (port->write(port, buf, 5) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (stm32_get_ack(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + buf[0] = length >> 24; + buf[1] = (length >> 16) & 0xFF; + buf[2] = (length >> 8) & 0xFF; + buf[3] = length & 0xFF; + buf[4] = buf[0] ^ buf[1] ^ buf[2] ^ buf[3]; + if (port->write(port, buf, 5) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (stm32_get_ack(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (stm32_get_ack(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (port->read(port, buf, 5) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (buf[4] != (buf[0] ^ buf[1] ^ buf[2] ^ buf[3])) + return STM32_ERR_UNKNOWN; + + *crc = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; + return STM32_ERR_OK; +} + +/* + * CRC computed by STM32 is similar to the standard crc32_be() + * implemented, for example, in Linux kernel in ./lib/crc32.c + * But STM32 computes it on units of 32 bits word and swaps the + * bytes of the word before the computation. + * Due to byte swap, I cannot use any CRC available in existing + * libraries, so here is a simple not optimized implementation. + */ +#define CRCPOLY_BE 0x04c11db7 +#define CRC_MSBMASK 0x80000000 +#define CRC_INIT_VALUE 0xFFFFFFFF +uint32_t stm32_sw_crc(uint32_t crc, uint8_t *buf, unsigned int len) +{ + int i; + uint32_t data; + + if (len & 0x3) { + fprintf(stderr, "Buffer length must be multiple of 4 bytes\n"); + return 0; + } + + while (len) { + data = *buf++; + data |= *buf++ << 8; + data |= *buf++ << 16; + data |= *buf++ << 24; + len -= 4; + + crc ^= data; + + for (i = 0; i < 32; i++) + if (crc & CRC_MSBMASK) + crc = (crc << 1) ^ CRCPOLY_BE; + else + crc = (crc << 1); + } + return crc; +} + +stm32_err_t stm32_crc_wrapper(const stm32_t *stm, uint32_t address, + uint32_t length, uint32_t *crc) +{ + uint8_t buf[256]; + uint32_t start, total_len, len, current_crc; + + if (address & 0x3 || length & 0x3) { + fprintf(stderr, "Start and end addresses must be 4 byte aligned\n"); + return STM32_ERR_UNKNOWN; + } + + if (stm->cmd->crc != STM32_CMD_ERR) + return stm32_crc_memory(stm, address, length, crc); + + start = address; + total_len = length; + current_crc = CRC_INIT_VALUE; + while (length) { + len = length > 256 ? 256 : length; + if (stm32_read_memory(stm, address, buf, len) != STM32_ERR_OK) { + fprintf(stderr, + "Failed to read memory at address 0x%08x, target write-protected?\n", + address); + return STM32_ERR_UNKNOWN; + } + current_crc = stm32_sw_crc(current_crc, buf, len); + length -= len; + address += len; + + fprintf(stderr, + "\rCRC address 0x%08x (%.2f%%) ", + address, + (100.0f / (float)total_len) * (float)(address - start) + ); + fflush(stderr); + } + fprintf(stderr, "Done.\n"); + *crc = current_crc; + return STM32_ERR_OK; +} diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/stm32.h b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/stm32.h new file mode 100644 index 0000000..1688fcb --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/stm32.h @@ -0,0 +1,84 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _STM32_H +#define _STM32_H + +#include +#include "serial.h" + +#define STM32_MAX_RX_FRAME 256 /* cmd read memory */ +#define STM32_MAX_TX_FRAME (1 + 256 + 1) /* cmd write memory */ + +typedef enum { + STM32_ERR_OK = 0, + STM32_ERR_UNKNOWN, /* Generic error */ + STM32_ERR_NACK, + STM32_ERR_NO_CMD, /* Command not available in bootloader */ +} stm32_err_t; + +typedef struct stm32 stm32_t; +typedef struct stm32_cmd stm32_cmd_t; +typedef struct stm32_dev stm32_dev_t; + +struct stm32 { + const serial_t *serial; + struct port_interface *port; + uint8_t bl_version; + uint8_t version; + uint8_t option1, option2; + uint16_t pid; + stm32_cmd_t *cmd; + const stm32_dev_t *dev; +}; + +struct stm32_dev { + uint16_t id; + const char *name; + uint32_t ram_start, ram_end; + uint32_t fl_start, fl_end; + uint16_t fl_pps; // pages per sector + uint16_t fl_ps; // page size + uint32_t opt_start, opt_end; + uint32_t mem_start, mem_end; +}; + +stm32_t *stm32_init(struct port_interface *port, const char init); +void stm32_close(stm32_t *stm); +stm32_err_t stm32_read_memory(const stm32_t *stm, uint32_t address, + uint8_t data[], unsigned int len); +stm32_err_t stm32_write_memory(const stm32_t *stm, uint32_t address, + const uint8_t data[], unsigned int len); +stm32_err_t stm32_wunprot_memory(const stm32_t *stm); +stm32_err_t stm32_wprot_memory(const stm32_t *stm); +stm32_err_t stm32_erase_memory(const stm32_t *stm, uint8_t spage, + uint8_t pages); +stm32_err_t stm32_go(const stm32_t *stm, uint32_t address); +stm32_err_t stm32_reset_device(const stm32_t *stm); +stm32_err_t stm32_readprot_memory(const stm32_t *stm); +stm32_err_t stm32_runprot_memory(const stm32_t *stm); +stm32_err_t stm32_crc_memory(const stm32_t *stm, uint32_t address, + uint32_t length, uint32_t *crc); +stm32_err_t stm32_crc_wrapper(const stm32_t *stm, uint32_t address, + uint32_t length, uint32_t *crc); +uint32_t stm32_sw_crc(uint32_t crc, uint8_t *buf, unsigned int len); + +#endif + diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/stm32flash.1 b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/stm32flash.1 new file mode 100644 index 0000000..d37292f --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/stm32flash.1 @@ -0,0 +1,407 @@ +.TH STM32FLASH 1 "2013\-11\-03" STM32FLASH "User command" +.SH NAME +stm32flash \- flashing utility for STM32 and STM32W through UART or I2C +.SH SYNOPSIS +.B stm32flash +.RB [ \-cfhjkouvCR ] +.RB [ \-a +.IR bus_address ] +.RB [ \-b +.IR baud_rate ] +.RB [ \-m +.IR serial_mode ] +.RB [ \-r +.IR filename ] +.RB [ \-w +.IR filename ] +.RB [ \-e +.IR num ] +.RB [ \-n +.IR count ] +.RB [ \-g +.IR address ] +.RB [ \-s +.IR start_page ] +.RB [ \-S +.IR address [: length ]] +.RB [ \-F +.IR RX_length [: TX_length ]] +.RB [ \-i +.IR GPIO_string ] +.RI [ tty_device +.R | +.IR i2c_device ] + +.SH DESCRIPTION +.B stm32flash +reads or writes the flash memory of STM32 and STM32W. + +It requires the STM32[W] to embed a bootloader compliant with ST +application note AN3155. +.B stm32flash +uses the serial port +.I tty_device +to interact with the bootloader of STM32[W]. + +.SH OPTIONS +.TP +.BI "\-a" " bus_address" +Specify address on bus for +.IR i2c_device . +This option is mandatory for I2C interface. + +.TP +.BI "\-b" " baud_rate" +Specify baud rate speed of +.IR tty_device . +Please notice that the ST bootloader can automatically detect the baud rate, +as explaned in chapter 2 of AN3155. +This option could be required together with option +.B "\-c" +or if following interaction with bootloader is expected. +Default is +.IR 57600 . + +.TP +.BI "\-m" " mode" +Specify the format of UART data. +.I mode +is a three characters long string where each character specifies, in +this strict order, character size, parity and stop bits. +The only values currenly used are +.I 8e1 +for standard STM32 bootloader and +.I 8n1 +for standard STM32W bootloader. +Default is +.IR 8e1 . + +.TP +.BI "\-r" " filename" +Specify to read the STM32[W] flash and write its content in +.I filename +in raw binary format (see below +.BR "FORMAT CONVERSION" ). + +.TP +.BI "\-w" " filename" +Specify to write the STM32[W] flash with the content of +.IR filename . +File format can be either raw binary or intel hex (see below +.BR "FORMAT CONVERSION" ). +The file format is automatically detected. +To by\-pass format detection and force binary mode (e.g. to +write an intel hex content in STM32[W] flash), use +.B \-f +option. + +.TP +.B \-u +Specify to disable write\-protection from STM32[W] flash. +The STM32[W] will be reset after this operation. + +.TP +.B \-j +Enable the flash read\-protection. + +.TP +.B \-k +Disable the flash read\-protection. + +.TP +.B \-o +Erase only. + +.TP +.BI "\-e" " num" +Specify to erase only +.I num +pages before writing the flash. Default is to erase the whole flash. With +.B \-e 0 +the flash would not be erased. + +.TP +.B \-v +Specify to verify flash content after write operation. + +.TP +.BI "\-n" " count" +Specify to retry failed writes up to +.I count +times. Default is 10 times. + +.TP +.BI "\-g" " address" +Specify address to start execution from (0 = flash start). + +.TP +.BI "\-s" " start_page" +Specify flash page offset (0 = flash start). + +.TP +.BI "\-S" " address" "[:" "length" "]" +Specify start address and optionally length for read/write/erase/crc operations. + +.TP +.BI "\-F" " RX_length" "[:" "TX_length" "]" +Specify the maximum frame size for the current interface. +Due to STM32 bootloader protocol, host will never handle frames bigger than +256 byte in RX or 258 byte in TX. +Due to current code, lowest limit in RX is 20 byte (to read a complete reply +of command GET). Minimum limit in TX is 5 byte, required by protocol. + +.TP +.B \-f +Force binary parser while reading file with +.BR "\-w" "." + +.TP +.B \-h +Show help. + +.TP +.B \-c +Specify to resume the existing UART connection and don't send initial +INIT sequence to detect baud rate. Baud rate must be kept the same as the +existing connection. This is useful if the reset fails. + +.TP +.BI "\-i" " GPIO_string" +Specify the GPIO sequences on the host to force STM32[W] to enter and +exit bootloader mode. GPIO can either be real GPIO connected from host to +STM32[W] beside the UART connection, or UART's modem signals used as +GPIO. (See below +.B BOOTLOADER GPIO SEQUENCE +for the format of +.I GPIO_string +and further explanation). + +.TP +.B \-C +Specify to compute CRC on memory content. +By default the CRC is computed on the whole flash content. +Use +.B "\-S" +to provide different memory address range. + +.TP +.B \-R +Specify to reset the device at exit. +This option is ignored if either +.BR "\-g" "," +.BR "\-j" "," +.B "\-k" +or +.B "\-u" +is also specified. + +.SH BOOTLOADER GPIO SEQUENCE +This feature is currently available on Linux host only. + +As explained in ST application note AN2606, after reset the STM32 will +execute either the application program in user flash or the bootloader, +depending on the level applied at specific pins of STM32 during reset. + +STM32 bootloader is automatically activated by configuring the pins +BOOT0="high" and BOOT1="low" and then by applying a reset. +Application program in user flash is activated by configuring the pin +BOOT0="low" (the level on BOOT1 is ignored) and then by applying a reset. + +When GPIO from host computer are connected to either configuration and +reset pins of STM32, +.B stm32flash +can control the host GPIO to reset STM32 and to force execution of +bootloader or execution of application program. + +The sequence of GPIO values to entry to and exit from bootloader mode is +provided with command line option +.B "\-i" +.IR "GPIO_string" . + +.PD 0 +The format of +.IR "GPIO_string" " is:" +.RS +GPIO_string = [entry sequence][:[exit sequence]] +.P +sequence = [\-]n[,sequence] +.RE +.P +In the above sequences, negative numbers correspond to GPIO at "low" level; +numbers without sign correspond to GPIO at "high" level. +The value "n" can either be the GPIO number on the host system or the +string "rts", "dtr" or "brk". The strings "rts" and "dtr" drive the +corresponding UART's modem lines RTS and DTR as GPIO. +The string "brk" forces the UART to send a BREAK sequence on TX line; +after BREAK the UART is returned in normal "non\-break" mode. +Note: the string "\-brk" has no effect and is ignored. +.PD + +.PD 0 +As example, let's suppose the following connection between host and STM32: +.IP \(bu 2 +host GPIO_3 connected to reset pin of STM32; +.IP \(bu 2 +host GPIO_4 connected to STM32 pin BOOT0; +.IP \(bu 2 +host GPIO_5 connected to STM32 pin BOOT1. +.PD +.P + +In this case, the sequence to enter in bootloader mode is: first put +GPIO_4="high" and GPIO_5="low"; then send reset pulse by GPIO_3="low" +followed by GPIO_3="high". +The corresponding string for +.I GPIO_string +is "4,\-5,\-3,3". + +To exit from bootloade and run the application program, the sequence is: +put GPIO_4="low"; then send reset pulse. +The corresponding string for +.I GPIO_string +is "\-4,\-3,3". + +The complete command line flag is "\-i 4,\-5,\-3,3:\-4,\-3,3". + +STM32W uses pad PA5 to select boot mode; if during reset PA5 is "low" then +STM32W will enter in bootloader mode; if PA5 is "high" it will execute the +program in flash. + +As example, supposing GPIO_3 connected to PA5 and GPIO_2 to STM32W's reset. +The command: +.PD 0 +.RS +stm32flash \-i \-3,\-2,2:3,\-2,2 /dev/ttyS0 +.RE +provides: +.IP \(bu 2 +entry sequence: GPIO_3=low, GPIO_2=low, GPIO_2=high +.IP \(bu 2 +exit sequence: GPIO_3=high, GPIO_2=low, GPIO_2=high +.PD + +.SH EXAMPLES +Get device information: +.RS +.PD 0 +.P +stm32flash /dev/ttyS0 +.PD +.RE + +Write with verify and then start execution: +.RS +.PD 0 +.P +stm32flash \-w filename \-v \-g 0x0 /dev/ttyS0 +.PD +.RE + +Read flash to file: +.RS +.PD 0 +.P +stm32flash \-r filename /dev/ttyS0 +.PD +.RE + +Start execution: +.RS +.PD 0 +.P +stm32flash \-g 0x0 /dev/ttyS0 +.PD +.RE + +Specify: +.PD 0 +.IP \(bu 2 +entry sequence: RTS=low, DTR=low, DTR=high +.IP \(bu 2 +exit sequence: RTS=high, DTR=low, DTR=high +.P +.RS +stm32flash \-i \-rts,\-dtr,dtr:rts,\-dtr,dtr /dev/ttyS0 +.PD +.RE + +.SH FORMAT CONVERSION +Flash images provided by ST or created with ST tools are often in file +format Motorola S\-Record. +Conversion between raw binary, intel hex and Motorola S\-Record can be +done through software package SRecord. + +.SH AUTHORS +The original software package +.B stm32flash +is written by +.I Geoffrey McRae +and is since 2012 maintained by +.IR "Tormod Volden " . + +Man page and extension to STM32W and I2C are written by +.IR "Antonio Borneo " . + +Please report any bugs at the project homepage +http://stm32flash.googlecode.com . + +.SH SEE ALSO +.BR "srec_cat" "(1)," " srec_intel" "(5)," " srec_motorola" "(5)." + +The communication protocol used by ST bootloader is documented in +following ST application notes, depending on communication port. +The current version of +.B stm32flash +only supports +.I UART +and +.I I2C +ports. +.PD 0 +.P +.IP \(bu 2 +AN3154: CAN protocol used in the STM32 bootloader +.P +.RS +http://www.st.com/web/en/resource/technical/document/application_note/CD00264321.pdf +.RE + +.P +.IP \(bu 2 +AN3155: USART protocol used in the STM32(TM) bootloader +.P +.RS +http://www.st.com/web/en/resource/technical/document/application_note/CD00264342.pdf +.RE + +.P +.IP \(bu 2 +AN4221: I2C protocol used in the STM32 bootloader +.P +.RS +http://www.st.com/web/en/resource/technical/document/application_note/DM00072315.pdf +.RE + +.P +.IP \(bu 2 +AN4286: SPI protocol used in the STM32 bootloader +.P +.RS +http://www.st.com/web/en/resource/technical/document/application_note/DM00081379.pdf +.RE + +.PD + + +Boot mode selection for STM32 is documented in ST application note +AN2606, available from the ST website: +.PD 0 +.P +http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf +.PD + +.SH LICENSE +.B stm32flash +is distributed under GNU GENERAL PUBLIC LICENSE Version 2. +Copy of the license is available within the source code in the file +.IR "gpl\-2.0.txt" . diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/utils.c b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/utils.c new file mode 100644 index 0000000..271bb3e --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/utils.c @@ -0,0 +1,45 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include "utils.h" + +/* detect CPU endian */ +char cpu_le() { + const uint32_t cpu_le_test = 0x12345678; + return ((const unsigned char*)&cpu_le_test)[0] == 0x78; +} + +uint32_t be_u32(const uint32_t v) { + if (cpu_le()) + return ((v & 0xFF000000) >> 24) | + ((v & 0x00FF0000) >> 8) | + ((v & 0x0000FF00) << 8) | + ((v & 0x000000FF) << 24); + return v; +} + +uint32_t le_u32(const uint32_t v) { + if (!cpu_le()) + return ((v & 0xFF000000) >> 24) | + ((v & 0x00FF0000) >> 8) | + ((v & 0x0000FF00) << 8) | + ((v & 0x000000FF) << 24); + return v; +} diff --git a/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/utils.h b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/utils.h new file mode 100644 index 0000000..a8d37d2 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/stm32flash_serial/src/utils.h @@ -0,0 +1,30 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _H_UTILS +#define _H_UTILS + +#include + +char cpu_le(); +uint32_t be_u32(const uint32_t v); +uint32_t le_u32(const uint32_t v); + +#endif diff --git a/BootLoaders/Boards/stm32/tools/linux/src/upload-reset/upload-reset.c b/BootLoaders/Boards/stm32/tools/linux/src/upload-reset/upload-reset.c new file mode 100644 index 0000000..1d03bff --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/src/upload-reset/upload-reset.c @@ -0,0 +1,161 @@ +/* Copyright (C) 2015 Roger Clark + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * + * Utility to send the reset sequence on RTS and DTR and chars + * which resets the libmaple and causes the bootloader to be run + * + * + * + * Terminal control code by Heiko Noordhof (see copyright below) + */ + + + +/* Copyright (C) 2003 Heiko Noordhof + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Function prototypes (belong in a seperate header file) */ +int openserial(char *devicename); +void closeserial(void); +int setDTR(unsigned short level); +int setRTS(unsigned short level); + + +/* Two globals for use by this module only */ +static int fd; +static struct termios oldterminfo; + + +void closeserial(void) +{ + tcsetattr(fd, TCSANOW, &oldterminfo); + close(fd); +} + + +int openserial(char *devicename) +{ + struct termios attr; + + if ((fd = open(devicename, O_RDWR)) == -1) return 0; /* Error */ + atexit(closeserial); + + if (tcgetattr(fd, &oldterminfo) == -1) return 0; /* Error */ + attr = oldterminfo; + attr.c_cflag |= CRTSCTS | CLOCAL; + attr.c_oflag = 0; + if (tcflush(fd, TCIOFLUSH) == -1) return 0; /* Error */ + if (tcsetattr(fd, TCSANOW, &attr) == -1) return 0; /* Error */ + + /* Set the lines to a known state, and */ + /* finally return non-zero is successful. */ + return setRTS(0) && setDTR(0); +} + + +/* For the two functions below: + * level=0 to set line to LOW + * level=1 to set line to HIGH + */ + +int setRTS(unsigned short level) +{ + int status; + + if (ioctl(fd, TIOCMGET, &status) == -1) { + perror("setRTS(): TIOCMGET"); + return 0; + } + if (level) status |= TIOCM_RTS; + else status &= ~TIOCM_RTS; + if (ioctl(fd, TIOCMSET, &status) == -1) { + perror("setRTS(): TIOCMSET"); + return 0; + } + return 1; +} + + +int setDTR(unsigned short level) +{ + int status; + + if (ioctl(fd, TIOCMGET, &status) == -1) { + perror("setDTR(): TIOCMGET"); + return 0; + } + if (level) status |= TIOCM_DTR; + else status &= ~TIOCM_DTR; + if (ioctl(fd, TIOCMSET, &status) == -1) { + perror("setDTR: TIOCMSET"); + return 0; + } + return 1; +} + +/* This portion of code was written by Roger Clark + * It was informed by various other pieces of code written by Leaflabs to reset their + * Maple and Maple mini boards + */ + +main(int argc, char *argv[]) +{ + + if (argc<2 || argc >3) + { + printf("Usage upload-reset \n\r"); + return; + } + + if (openserial(argv[1])) + { + // Send magic sequence of DTR and RTS followed by the magic word "1EAF" + setRTS(false); + setDTR(false); + setDTR(true); + + usleep(50000L); + + setDTR(false); + setRTS(true); + setDTR(true); + + usleep(50000L); + + setDTR(false); + + usleep(50000L); + + write(fd,"1EAF",4); + + closeserial(); + if (argc==3) + { + usleep(atol(argv[2])*1000L); + } + } + else + { + printf("Failed to open serial device.\n\r"); + } +} diff --git a/BootLoaders/Boards/stm32/tools/linux/stlink/st-flash b/BootLoaders/Boards/stm32/tools/linux/stlink/st-flash new file mode 100644 index 0000000..951b11a Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux/stlink/st-flash differ diff --git a/BootLoaders/Boards/stm32/tools/linux/stlink/st-info b/BootLoaders/Boards/stm32/tools/linux/stlink/st-info new file mode 100644 index 0000000..0787606 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux/stlink/st-info differ diff --git a/BootLoaders/Boards/stm32/tools/linux/stlink/st-term b/BootLoaders/Boards/stm32/tools/linux/stlink/st-term new file mode 100644 index 0000000..b5425db Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux/stlink/st-term differ diff --git a/BootLoaders/Boards/stm32/tools/linux/stlink/st-util b/BootLoaders/Boards/stm32/tools/linux/stlink/st-util new file mode 100644 index 0000000..c6a0078 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux/stlink/st-util differ diff --git a/BootLoaders/Boards/stm32/tools/linux/stlink_upload b/BootLoaders/Boards/stm32/tools/linux/stlink_upload new file mode 100644 index 0000000..f0dd789 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/stlink_upload @@ -0,0 +1,49 @@ +#!/bin/bash +$(dirname $0)/stlink/st-flash write "$4" 0x8000000 +exit 0 + +## Remove the lines 2 and 3 (above) if you want this script to wait until the Serial device has been enumerated and loaded before the script exits + +# Check for leaf device. +function leaf_status() +{ + +this_leaf_status=$(lsusb |grep "1eaf" | awk '{ print $NF}') +# Find the mode of the leaf bootloader +case $this_leaf_status in + "1eaf:0003") + echo "dfu" + ;; + "1eaf:0004") + echo "ttyACMx" + ;; + *) + #echo "$this_leaf_status" + echo "unknown" + ;; +esac +} + +# You will need the usb-reset code, see https://github.com/rogerclarkmelbourne/Arduino_STM32/wiki/Using-a-generic-stm32-board-on-linux-with-Maple-bootloader +# +USBRESET=$(which usb-reset) || USBRESET="./usb-reset" + +# Check to see if a maple compatible board is attached +LEAF_STATUS=$(leaf_status) +echo "USB Status [$LEAF_STATUS]" + +$(dirname $0)/stlink/st-flash write "$4" 0x8000000 + +sleep 4 +# Reset the usb device to bring up the tty rather than DFU +"$USBRESET" "/dev/bus/usb/$(lsusb |grep "1eaf" |awk '{print $2,$4}'|sed 's/\://g'|sed 's/ /\//g')" >/dev/null 2>&1 +# Check to see if a maple compatible board is attached +LEAF_STATUS=$(leaf_status) +echo "USB Status [$LEAF_STATUS]" +# Check to see if the tty came up +TTY_DEV=$(find /dev -cmin -2 |grep ttyAC) +echo -e "Waiting for tty device $TTY_DEV \n" +sleep 20 +echo -e "$TTY_DEV should now be available.\n" +exit 0 + diff --git a/BootLoaders/Boards/stm32/tools/linux/stm32flash/stm32flash b/BootLoaders/Boards/stm32/tools/linux/stm32flash/stm32flash new file mode 100644 index 0000000..16872bb Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux/stm32flash/stm32flash differ diff --git a/BootLoaders/Boards/stm32/tools/linux/tx_upload b/BootLoaders/Boards/stm32/tools/linux/tx_upload new file mode 100644 index 0000000..fc2f6ba --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/tx_upload @@ -0,0 +1,15 @@ +#!/bin/bash + +# Dummy 'upload' file to provide instructions for flashing the multi-module firmware from the Tx +echo +echo Compiled .bin location: +echo $1 +echo +echo The compiled firmware can now be copied to the \firmware folder on the transmitter for flashing using Maintenance Mode. +echo +echo To enter Maintenance Mode hold down the two outer horizontal trim buttons while powering on the transmitter. Once in +echo Maintenance Mode follow the on-screen prompts to flash the Multi module. +echo +echo Supported transmitters are those running ersky9x r221e2 or newer. +echo +echo Further instructions are available at [need_url]. \ No newline at end of file diff --git a/BootLoaders/Boards/stm32/tools/linux/upload-reset b/BootLoaders/Boards/stm32/tools/linux/upload-reset new file mode 100644 index 0000000..26985b8 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux/upload-reset differ diff --git a/BootLoaders/Boards/stm32/tools/linux/upload_router b/BootLoaders/Boards/stm32/tools/linux/upload_router new file mode 100644 index 0000000..b74244d --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/upload_router @@ -0,0 +1,112 @@ +#!/bin/bash +# Translates the windows Arduino IDE upload call - something like.. +# +# upload_router ttyUSB0 1 1EAF:0003 /tmp/build9114565021046468906.tmp/STM32_Blink.cpp maple_dfu 0 +# +# to the linux dfu-util equivalent of the form... +# +# dfu-util -D ./STM32_Blink.cpp.bin -d 1eaf:0003 --intf 0 --alt 1 +# +# + +function leaf_status() +{ + +this_leaf_status=$(lsusb |grep "1eaf" | awk '{ print $NF}') +# Find the mode of the leaf bootloader +case $this_leaf_status in + "1eaf:0003") + echo "dfu" + ;; + "1eaf:0004") + echo "ttyACMx" + ;; + *) + #echo "$this_leaf_status" + echo "unknown" + ;; +esac +} + + +DEVICE="$3" +# Lowercase the 1eaf device name, since in Windows land everybody shouts. +DEVICE=${DEVICE,,} + +BINFILE="$4.bin" +INTERFACE="$6" +ALT_INTERFACE="$2" + +# You will need the usb-reset code, see https://github.com/rogerclarkmelbourne/Arduino_STM32/wiki/Using-a-generic-stm32-board-on-linux-with-Maple-bootloader +# +USBRESET=$(which usb-reset) || USBRESET="./usb-reset" + +# Check to see if a maple compatible board is attached +LEAF_STATUS=$(leaf_status) + +# Borard not found, or no boot loader on board. +if [[ $(leaf_status) = "unknown" ]] +then + echo "STM32 Maple Bootloader compatible board not found." + sleep 5 + exit 1 +fi + +# We got this far, so we need to get the board in bootloader mode. +# After the timeout period, the board goes back in to serial mode, we need it in dfu mode, which happens for the first few seconds at power on +# so we ask the user to unplug and re-plug the board. +echo -e "\n\rSTM32 Maple board is in $LEAF_STATUS mode." + +echo "Please unplug and replug the USB cable to the Maple device." +sleep 2 +# On unplugging the board will be "unknown" +while [[ $(leaf_status) != "unknown" ]] +do + echo -n "." + sleep 1 +done +# On re-plugging the board will be "dfu" +while [[ $(leaf_status) != "dfu" ]] +do + echo -n "." + sleep 1 +done + +echo -e "\n\rProgramming STM32 device with dfu-util" +until dfu-util -D "$BINFILE" -d "$DEVICE" --intf "$INTERFACE" --alt "$ALT_INTERFACE" 2>&1 +do + echo -n "." + sleep 1 +done + +echo -e "\n\rUnplug and replug the USB cable to the STM32 board again please...." +while [[ $(leaf_status) != "unknown" ]] +do + echo -n "." + sleep 1 +done + +echo -e "\n\rReconnecting" +while [[ $(leaf_status) = "unknown" ]] +do + echo -n "." + sleep 1 +done + +echo -e "\n\rWaiting for bootloader to exit." +for i in {1..6} +do + echo -n "." + sleep 1 +done + +"$USBRESET" "/dev/bus/usb/$(lsusb |grep "1eaf" |awk '{print $2,$4}'|sed 's/\://g'|sed 's/ /\//g')" >/dev/null 2>&1 + +while [[ $(leaf_status) = "unknown" ]] +do + echo -n "." + sleep 1 +done +THIS_TTY=$(find /dev/ttyACM* -cmin -2) +echo -e "\n\rSTM32 Maple board serial port re-created..." +echo -e "\n\rSerial port is $THIS_TTY Please allow 15 seconds before attempting to read from serial port." diff --git a/BootLoaders/Boards/stm32/tools/linux64/45-maple.rules b/BootLoaders/Boards/stm32/tools/linux64/45-maple.rules new file mode 100644 index 0000000..d1bda5f --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/45-maple.rules @@ -0,0 +1,5 @@ +ATTRS{idProduct}=="1001", ATTRS{idVendor}=="0110", MODE="664", GROUP="plugdev" +ATTRS{idProduct}=="1002", ATTRS{idVendor}=="0110", MODE="664", GROUP="plugdev" +ATTRS{idProduct}=="0003", ATTRS{idVendor}=="1eaf", MODE="664", GROUP="plugdev" SYMLINK+="maple" +ATTRS{idProduct}=="0004", ATTRS{idVendor}=="1eaf", MODE="664", GROUP="plugdev" SYMLINK+="maple" + diff --git a/BootLoaders/Boards/stm32/tools/linux64/49-stlinkv1.rules b/BootLoaders/Boards/stm32/tools/linux64/49-stlinkv1.rules new file mode 100644 index 0000000..d474d6a --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/49-stlinkv1.rules @@ -0,0 +1,11 @@ +# stm32 discovery boards, with onboard st/linkv1 +# ie, STM32VL + +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3744", \ + MODE:="0666", \ + SYMLINK+="stlinkv1_%n" + +# If you share your linux system with other users, or just don't like the +# idea of write permission for everybody, you can replace MODE:="0666" with +# OWNER:="yourusername" to create the device owned by you, or with +# GROUP:="somegroupname" and mange access using standard unix groups. diff --git a/BootLoaders/Boards/stm32/tools/linux64/49-stlinkv2-1.rules b/BootLoaders/Boards/stm32/tools/linux64/49-stlinkv2-1.rules new file mode 100644 index 0000000..a5a79b9 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/49-stlinkv2-1.rules @@ -0,0 +1,12 @@ +# stm32 nucleo boards, with onboard st/linkv2-1 +# ie, STM32F0, STM32F4. +# STM32VL has st/linkv1, which is quite different + +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374b", \ + MODE:="0666", \ + SYMLINK+="stlinkv2-1_%n" + +# If you share your linux system with other users, or just don't like the +# idea of write permission for everybody, you can replace MODE:="0666" with +# OWNER:="yourusername" to create the device owned by you, or with +# GROUP:="somegroupname" and mange access using standard unix groups. diff --git a/BootLoaders/Boards/stm32/tools/linux64/49-stlinkv2.rules b/BootLoaders/Boards/stm32/tools/linux64/49-stlinkv2.rules new file mode 100644 index 0000000..a11215c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/49-stlinkv2.rules @@ -0,0 +1,12 @@ +# stm32 discovery boards, with onboard st/linkv2 +# ie, STM32L, STM32F4. +# STM32VL has st/linkv1, which is quite different + +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3748", \ + MODE:="0666", \ + SYMLINK+="stlinkv2_%n" + +# If you share your linux system with other users, or just don't like the +# idea of write permission for everybody, you can replace MODE:="0666" with +# OWNER:="yourusername" to create the device owned by you, or with +# GROUP:="somegroupname" and mange access using standard unix groups. diff --git a/BootLoaders/Boards/stm32/tools/linux64/dfu-util/dfu-prefix b/BootLoaders/Boards/stm32/tools/linux64/dfu-util/dfu-prefix new file mode 100644 index 0000000..88e2d04 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux64/dfu-util/dfu-prefix differ diff --git a/BootLoaders/Boards/stm32/tools/linux64/dfu-util/dfu-suffix b/BootLoaders/Boards/stm32/tools/linux64/dfu-util/dfu-suffix new file mode 100644 index 0000000..e96df29 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux64/dfu-util/dfu-suffix differ diff --git a/BootLoaders/Boards/stm32/tools/linux64/dfu-util/dfu-util b/BootLoaders/Boards/stm32/tools/linux64/dfu-util/dfu-util new file mode 100644 index 0000000..e14a164 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux64/dfu-util/dfu-util differ diff --git a/BootLoaders/Boards/stm32/tools/linux64/install.sh b/BootLoaders/Boards/stm32/tools/linux64/install.sh new file mode 100644 index 0000000..29ddb2f --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/install.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +if sudo [ -w /etc/udev/rules.d ]; then + echo "Copying Maple-specific udev rules..." + sudo cp -v 45-maple.rules /etc/udev/rules.d/45-maple.rules + sudo chown root:root /etc/udev/rules.d/45-maple.rules + sudo chmod 644 /etc/udev/rules.d/45-maple.rules + sudo cp -v 49-stlinkv1.rules /etc/udev/rules.d/49-stlinkv1.rules + sudo chown root:root /etc/udev/rules.d/49-stlinkv1.rules + sudo chmod 644 /etc/udev/rules.d/49-stlinkv1.rules + sudo cp -v 49-stlinkv2.rules /etc/udev/rules.d/49-stlinkv2.rules + sudo chown root:root /etc/udev/rules.d/49-stlinkv2.rules + sudo chmod 644 /etc/udev/rules.d/49-stlinkv2.rules + sudo cp -v 49-stlinkv2-1.rules /etc/udev/rules.d/49-stlinkv2-1.rules + sudo chown root:root /etc/udev/rules.d/49-stlinkv2-1.rules + sudo chmod 644 /etc/udev/rules.d/49-stlinkv2-1.rules + echo "Reloading udev rules" + sudo udevadm control --reload-rules + echo "Adding current user to dialout group" + sudo adduser $USER dialout +else + echo "Couldn't copy to /etc/udev/rules.d/; you probably have to run this script as root? Or your distribution of Linux doesn't include udev; try running the IDE itself as root." +fi + diff --git a/BootLoaders/Boards/stm32/tools/linux64/maple_upload b/BootLoaders/Boards/stm32/tools/linux64/maple_upload new file mode 100644 index 0000000..27e006c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/maple_upload @@ -0,0 +1,49 @@ +#!/bin/bash + +#set -e + + + +if [ $# -lt 4 ]; then + echo "Usage: $0 $# " >&2 + exit 1 +fi +dummy_port="$1"; altID="$2"; usbID="$3"; binfile="$4"; dummy_port_fullpath="/dev/$1" +if [ $# -eq 5 ]; then + dfuse_addr="--dfuse-address $5" +else + dfuse_addr="" +fi + + +# Get the directory where the script is running. +DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +# ----------------- IMPORTANT ----------------- +# The 2nd parameter to upload-reset is the delay after resetting before it exits +# This value is in milliseonds +# You may need to tune this to your system +# 750ms to 1500ms seems to work on my Mac + + +"${DIR}/upload-reset" ${dummy_port_fullpath} 750 + + +#DFU_UTIL=$(dirname $0)/dfu-util/dfu-util +DFU_UTIL=/usr/bin/dfu-util +DFU_UTIL=${DIR}/dfu-util/dfu-util +if [ ! -x "${DFU_UTIL}" ]; then + echo "$0: error: cannot find ${DFU_UTIL}" >&2 + exit 2 +fi + +"${DFU_UTIL}" -d ${usbID} -a ${altID} -D ${binfile} ${dfuse_addr} -R + +echo -n Waiting for ${dummy_port_fullpath} serial... + +COUNTER=0 +while [ ! -c ${dummy_port_fullpath} ] && ((COUNTER++ < 40)); do + sleep 0.1 +done + +echo Done \ No newline at end of file diff --git a/BootLoaders/Boards/stm32/tools/linux64/readme.txt b/BootLoaders/Boards/stm32/tools/linux64/readme.txt new file mode 100644 index 0000000..2d13beb --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/readme.txt @@ -0,0 +1 @@ +The maple upload script needs its rights to be set to 755 \ No newline at end of file diff --git a/BootLoaders/Boards/stm32/tools/linux64/serial_upload b/BootLoaders/Boards/stm32/tools/linux64/serial_upload new file mode 100644 index 0000000..755444a --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/serial_upload @@ -0,0 +1,2 @@ +#!/bin/bash +$(dirname $0)/stm32flash/stm32flash -g 0x8000000 -b 115200 -w "$4" /dev/"$1" diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/build_dfu-util.sh b/BootLoaders/Boards/stm32/tools/linux64/src/build_dfu-util.sh new file mode 100644 index 0000000..3563f57 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/build_dfu-util.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +sudo apt-get build-dep dfu-util +sudo apt-get install build-essentials +sudo apt-get install libusb-1.0-0-dev +sudo apt-get install autoconf automake autotools-dev + +cd dfu-util +./autogen.sh +./configure +make +cp src/dfu-util ../../linux/dfu-util +cp src/dfu-suffix ../../linux/dfu-util +cp src/dfu-prefix ../../linux/dfu-util + diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/AUTHORS b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/AUTHORS new file mode 100644 index 0000000..1b36c73 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/AUTHORS @@ -0,0 +1,30 @@ +Authors ordered by first contribution. + +Harald Welte +Werner Almesberger +Michael Lauer +Jim Huang +Stefan Schmidt +Daniel Willmann +Mike Frysinger +Uwe Hermann +C. Scott Ananian +Bernard Blackham +Holger Freyther +Marc Singer +James Perkins +Tommi Keisala +Pascal Schweizer +Bradley Scott +Uwe Bonnes +Andrey Smirnov +Jussi Timperi +Hans Petter Selasky +Bo Shen +Henrique de Almeida Mendonca +Bernd Krumboeck +Dennis Meier +Veli-Pekka Peltola +Dave Hylands +Michael Grzeschik +Paul Fertser diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/COPYING b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/COPYING new file mode 100644 index 0000000..d60c31a --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/ChangeLog b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/ChangeLog new file mode 100644 index 0000000..37f1add --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/ChangeLog @@ -0,0 +1,93 @@ +0.8: + o New, separate dfu-prefix tool (Uwe Bonnes) + o Allow filtering on serial number (Uwe Bonnes) + o Improved VID/PID/serial filtering (Bradley Scott) + o Support reading firmware from stdin (Tormod Volden) + o Warn if missing DFU suffix (Tormod Volden) + o Improved progress bar (Hans Petter Selasky) + o Fix dfuse leave option (Uwe Bonnes) + o Major code rework (Hans Petter Selasky) + o MS Visual Studio build support (Henrique Mendonca) + o dfuse-pack.py tool for .dfu files (Antonio Galeo) + o Many other fixes from many people + +2014-09-13: Tormod Volden + +0.7: + o Support for TI Stellaris devices (Tommi Keisala) + o Fix libusb detection on MacOSX (Marc Singer) + o Fix libusb detection on FreeBSD (Tormod Volden) + o Improved DfuSe support (Tormod Volden) + o Support all special commands (leave, unprotect, mass-erase) + o Arbitrary upload lengths + o "force" option for various possible (dangerous) overrides + +2012-10-07: Tormod Volden + +0.6: + o Add detach mode (Stefan Schmidt) + o Check return value on all libusb calls (Tormod Volden) + o Fix segmentation fault with -s option (Tormod Volden) + o Add DFU suffix manipulation tool (Stefan Schmidt) + o Port to Windows: (Tormod Volden, some parts based on work from Satz + Klauer) + o Port file handling to stdio streams + o Sleep() macros + o C99 types + o Pack structs + o Detect DfuSe device correctly on big-endian architectures (Tormod + Volden) + o Add dfuse progress indication on download (Tormod Volden) + o Cleanup: gcc pedantic, gcc extension, ... (Tormod Volden) + o Rely on page size from functional descriptor. Please report if you get + an error about it. (Tormod Volden) + o Add quirk for Maple since it reports wrong DFU version (Tormod Volden) + +2012-04-22: Stefan Schmidt + +0.5: + o DfuSe extension support for ST devices (Tormod Volden) + o Add initial support for bitWillDetach flag from DFU 1.1 (Tormod + Volden) + o Internal cleanup and some manual page fixes (Tormod Volden) + +2011-11-02: Stefan Schmidt + +0.4: + o Rework to use libusb-1.0 (Stefan Schmidt) + o DFU suffix support (Tormod Volden, Stefan Schmidt) + o Sspeed up DFU downloads directly into memory (Bernard Blackham) + o More flexible -d vid:pid parsing (Tormod Volden) + o Many bug fixes and cleanups + +2011-07-20: Stefan Schmidt + +0.3: + o quirks: Add OpenOCD to the poll timeout quirk table. + +2010-12-22: Stefan Schmidt + +0.2: + o Fix some typos on the website and the README (Antonio Ospite, Uwe + Hermann) + o Remove build rule for a static binary. We can use autotools for this. + (Mike Frysinger) + o Fix infinite loop in download error path (C. Scott Ananian) + o Break out to show the 'finished' in upload (C. Scott Ananian) + o Add GPLv2+ headers (Harald Welte) + o Remove dead code (commands.[ch]) remnescent of dfu-programmer (Harald + Welte) + o Simple quirk system with Openmoko quirk for missing bwPollTimeout (Tormod Volden) + o New default (1024) and clamping of transfer size (Tormod Volden) + o Verify sending of completion packet (Tormod Volden) + o Look for DFU functional descriptor among all descriptors (Tormod + Volden) + o Print out in which direction we are transferring data + o Abort in upload if the file already exists + +2010-11-17 Stefan Schmidt + +0.1: + Initial release + +2010-05-23 Stefan Schmidt diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/DEVICES.txt b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/DEVICES.txt new file mode 100644 index 0000000..bdd9f1f --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/DEVICES.txt @@ -0,0 +1,20 @@ +List of supported software and hardware products: + +Software user (bootloader, etc) +------------------------------- +- Sam7DFU: http://www.openpcd.org/Sam7dfu +- U-boot: DFU patches +- Barebox: http://www.barebox.org/ +- Leaflabs: http://code.google.com/p/leaflabs/ +- Blackmagic DFU + +Products using DFU +------------------ +- OpenPCD (sam7dfu) +- Openmoko Neo 1973 and Freerunner (u-boot with DFU patches) +- Leaflabs Maple +- ATUSB from Qi Hardware +- STM32F105/7, STM32F2/F3/F4 in System Bootloader +- Blackmagic debug probe +- NXP LPC31xx/LPC43XX, e.g. LPC-Link and LPC-Link2, need binaries + with LPC prefix and encoding (LPC-Link) diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/Makefile.am b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/Makefile.am new file mode 100644 index 0000000..641dda5 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = src doc + +EXTRA_DIST = autogen.sh TODO DEVICES.txt dfuse-pack.py diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/README b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/README new file mode 100644 index 0000000..0f8f262 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/README @@ -0,0 +1,20 @@ +Dfu-util - Device Firmware Upgrade Utilities + +Dfu-util is the host side implementation of the DFU 1.0 [1] and DFU 1.1 [2] +specification of the USB forum. + +DFU is intended to download and upload firmware to devices connected over +USB. It ranges from small devices like micro-controller boards up to mobile +phones. With dfu-util you are able to download firmware to your device or +upload firmware from it. + +dfu-util has been tested with Openmoko Neo1973 and Freerunner and many +other devices. + +[1] DFU 1.0 spec: http://www.usb.org/developers/devclass_docs/usbdfu10.pdf +[2] DFU 1.1 spec: http://www.usb.org/developers/devclass_docs/DFU_1.1.pdf + +The official website is: + + http://dfu-util.gnumonks.org/ + diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/TODO b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/TODO new file mode 100644 index 0000000..900c30c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/TODO @@ -0,0 +1,14 @@ +DfuSe: +- Do erase and write in two separate passes when downloading +- Skip "Set Address" command when downloading contiguous blocks +- Implement "Get Commands" command + +Devices: +- Research iPhone/iPod/iPad support + Heavily modified dfu-util fork here: + https://github.com/planetbeing/xpwn/tree/master/dfu-util +- Test against Niftylights + +Non-Code: +- Logo +- Re-License as LGPL for usage as library? diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/autogen.sh b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/autogen.sh new file mode 100644 index 0000000..e67aed3 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/autogen.sh @@ -0,0 +1,2 @@ +#! /bin/sh +autoreconf -v -i diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/configure.ac b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/configure.ac new file mode 100644 index 0000000..8622114 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/configure.ac @@ -0,0 +1,41 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.59) +AC_INIT([dfu-util],[0.8],[dfu-util@lists.gnumonks.org],,[http://dfu-util.gnumonks.org]) +AC_CONFIG_AUX_DIR(m4) +AM_INIT_AUTOMAKE([foreign]) +AC_CONFIG_HEADERS([config.h]) + +# Test for new silent rules and enable only if they are available +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +# Checks for programs. +AC_PROG_CC + +# Checks for libraries. +# On FreeBSD the libusb-1.0 is called libusb and resides in system location +AC_CHECK_LIB([usb], [libusb_init],, [native_libusb=no],) +AS_IF([test x$native_libusb = xno], [ + PKG_CHECK_MODULES([USB], [libusb-1.0 >= 1.0.0],, + AC_MSG_ERROR([*** Required libusb-1.0 >= 1.0.0 not installed ***])) +]) +AC_CHECK_LIB([usbpath],[usb_path2devnum],,,-lusb) + +LIBS="$LIBS $USB_LIBS" +CFLAGS="$CFLAGS $USB_CFLAGS" + +# Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS([usbpath.h windows.h sysexits.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_TYPE_SIZE_T + +# Checks for library functions. +AC_FUNC_MEMCMP +AC_CHECK_FUNCS([ftruncate getpagesize nanosleep err]) + +AC_CONFIG_FILES(Makefile src/Makefile doc/Makefile) +AC_OUTPUT diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/README b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/README new file mode 100644 index 0000000..00d3d1a --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/README @@ -0,0 +1,77 @@ +Device: +------- +qi-hardware-atusb: +- Qi Hardware ben-wpan +- DFU implementation: + http://projects.qi-hardware.com/index.php/p/ben-wpan/source/tree/master/atusb/fw/usb +- Tester: Stefan Schmidt + +openpcd: +- OpenPCD RFID reader +- DFU implementation: SAM7DFU + http://www.openpcd.org/Sam7dfu, git://git.gnumonks.org/openpcd.git +- Tester: Stefan Schmidt + +simtrace: +- Sysmocom SimTrace +- DFU implementation: SAM7DFU + http://www.openpcd.org/Sam7dfu, git://git.gnumonks.org/openpcd.git +- Tester: Stefan Schmidt + +openmoko-freerunner: +- Openmoko Freerunner +- DFU implementation: Old U-Boot + http://git.openmoko.org/?p=u-boot.git;a=shortlog;h=refs/heads/mokopatches +- Tester: Stefan Schmidt + +openmoko-neo1973: +- Openmoko Neo1073 +- DFU implementation: Old U-Boot + http://git.openmoko.org/?p=u-boot.git;a=shortlog;h=refs/heads/mokopatches +- Tester: Stefan Schmidt + +tdk-bluetooth: +- TDK Corp. Bluetooth Adapter +- DFU implementation: closed soure +- Only upload has been tested +- Tester: Stefan Schmidt + +stm32f107: +- STM32 microcontrollers with built-in (ROM) DFU loader +- DFU implementation: Closed source but probably similar to the one + in their USB device libraries. Some relevant application notes: + http://www.st.com -> AN3156 and AN2606 +- Tested by Uwe Bonnes + +stm32f4discovery: +- STM32 microcontroller board with built-in (ROM) DFU loader +- DFU implementation: Closed source, probably similar to stm32f107. +- Tested by Joe Rothweiler + +dso-nano: +- DSO Nano pocket oscilloscope +- DFU implementation: Based on ST Microelectronics USB FS Library 1.0 + http://dsonano.googlecode.com/files/DS0201_OpenSource.rar +- Tester: Tormod Volden + +opc-20: +- Custom devices based on STM32F1xx +- DFU implementation: ST Microelectronics USB FS Device Library 3.1.0 + http://www.st.com -> um0424.zip +- Tester: Tormod Volden + +lpc-link, lpclink2: +- NXP LPCXpresso debug adapters +- Proprietary DFU implementation, uses special download files with + LPC prefix and encoding of the target firmware code +- Tested by Uwe Bonnes + +Adding the lsusb output and a download log of your device here helps +us to avoid regressions for hardware we cannot test while working on +the code. To extract the lsusb output use this command: +sudo lsusb -v -d $USBID > $DEVICE.lsusb +Prepare a description snippet as above, and send it to us. A log +(copy-paste of the command window) of a firmware download is also +nice, please use the double verbose option -v -v and include the +command line in the log file. + diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/dsonano.lsusb b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/dsonano.lsusb new file mode 100644 index 0000000..140a7bc --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/dsonano.lsusb @@ -0,0 +1,60 @@ + +Bus 002 Device 004: ID 0483:df11 SGS Thomson Microelectronics +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x0483 SGS Thomson Microelectronics + idProduct 0xdf11 + bcdDevice 1.1a + iManufacturer 1 STMicroelectronics + iProduct 2 STM32 DFU + iSerial 3 001 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 36 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 64mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 0 + iInterface 4 @Internal Flash /0x08000000/12*001Ka,116*001Kg + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 0 + iInterface 5 @SPI Flash : M25P64/0x00000000/64*064Kg,64*064Kg + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 11 + Will Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 255 milliseconds + wTransferSize 1024 bytes + bcdDFUVersion 1.1a +Device Status: 0x0000 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/lpclink.log b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/lpclink.log new file mode 100644 index 0000000..7de4dd3 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/lpclink.log @@ -0,0 +1,59 @@ +(The on-board LPC3154 has some encryption key set and LPCXpressoWIN.enc +is encrypted.) + +$ lsusb | grep NXP +Bus 003 Device 011: ID 0471:df55 Philips (or NXP) LPCXpresso LPC-Link + +$ dfu-util -v -v -v -R -D /opt/lpc/lpcxpresso/bin/LPCXpressoWIN.enc + +dfu-util 0.7 + +Copyright 2005-2008 Weston Schmidt, Harald Welte and OpenMoko Inc. +Copyright 2010-2012 Tormod Volden and Stefan Schmidt +This program is Free Software and has ABSOLUTELY NO WARRANTY +Please report bugs to dfu-util@lists.gnumonks.org + +dfu-util: Invalid DFU suffix signature +dfu-util: A valid DFU suffix will be required in a future dfu-util release!!! +Deducing device DFU version from functional descriptor length +Opening DFU capable USB device... +ID 0471:df55 +Run-time device DFU version 0100 +Claiming USB DFU Runtime Interface... +Determining device status: +state = dfuIDLE, status = 0 +dfu-util: WARNING: Runtime device already in DFU state ?!? +Claiming USB DFU Interface... +Setting Alternate Setting #0 ... +Determining device status: +state = dfuIDLE, status = 0 +dfuIDLE, continuing +DFU mode device DFU version 0100 +Device returned transfer size 2048 +Copying data from PC to DFU device +Download [ ] 0% 0 bytes +Download [= ] 6% 2048 bytes +Download [=== ] 13% 4096 bytes +Download [==== ] 19% 6144 bytes +Download [====== ] 26% 8192 bytes +Download [======== ] 32% 10240 bytes +Download [========= ] 39% 12288 bytes +Download [=========== ] 45% 14336 bytes +Download [============= ] 52% 16384 bytes +Download [============== ] 59% 18432 bytes +Download [================ ] 65% 20480 bytes +Download [================== ] 72% 22528 bytes +Download [=================== ] 78% 24576 bytes +Download [===================== ] 85% 26624 bytes +Download [====================== ] 91% 28672 bytes +Download [======================== ] 98% 29192 bytes +Download [=========================] 100% 29192 bytes +Download done. +Sent a total of 29192 bytes +state(8) = dfuMANIFEST-WAIT-RESET, status(0) = No error condition is present +Done! +dfu-util: can't detach +Resetting USB to switch back to runtime mode + +$ lsusb | grep NXP +Bus 003 Device 012: ID 1fc9:0009 NXP Semiconductors diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/lpclink.lsusb b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/lpclink.lsusb new file mode 100644 index 0000000..867b2a2 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/lpclink.lsusb @@ -0,0 +1,58 @@ + +Bus 003 Device 008: ID 0471:df55 Philips (or NXP) LPCXpresso LPC-Link +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x0471 Philips (or NXP) + idProduct 0xdf55 LPCXpresso LPC-Link + bcdDevice 0.01 + iManufacturer 0 + iProduct 0 + iSerial 0 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 25 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 0 + iInterface 0 + Device Firmware Upgrade Interface Descriptor: + bLength 7 + bDescriptorType 33 + bmAttributes 1 + Will Not Detach + Manifestation Intolerant + Upload Unsupported + Download Supported + wDetachTimeout 65535 milliseconds + wTransferSize 2048 bytes +Device Qualifier (for other device speed): + bLength 10 + bDescriptorType 6 + bcdUSB 2.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + bNumConfigurations 1 +Device Status: 0x0000 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/lpclink2.log b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/lpclink2.log new file mode 100644 index 0000000..4681eff --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/lpclink2.log @@ -0,0 +1,59 @@ +$ lsusb | grep NXP +Bus 003 Device 013: ID 1fc9:000c NXP Semiconductors + +$ dfu-util -D ~/devel/dfu-util/firmware.bin.qthdr + +dfu-util 0.7 + +Copyright 2005-2008 Weston Schmidt, Harald Welte and OpenMoko Inc. +Copyright 2010-2012 Tormod Volden and Stefan Schmidt +This program is Free Software and has ABSOLUTELY NO WARRANTY +Please report bugs to dfu-util@lists.gnumonks.org + +dfu-util: Invalid DFU suffix signature +dfu-util: A valid DFU suffix will be required in a future dfu-util release!!! +Possible unencryptes NXP LPC DFU prefix with the following properties +Payload length: 39 kiByte +Opening DFU capable USB device... +ID 1fc9:000c +Run-time device DFU version 0100 +Claiming USB DFU Runtime Interface... +Determining device status: +state = dfuIDLE, status = 0 +dfu-util: WARNING: Runtime device already in DFU state ?!? +Claiming USB DFU Interface... +Setting Alternate Setting #0 ... +Determining device status: +state = dfuIDLE, status = 0 +dfuIDLE, continuing +DFU mode device DFU version 0100 +Device returned transfer size 2048 +Copying data from PC to DFU device +Download [ ] 0% 0 bytes +Download [= ] 4% 2048 bytes +Download [== ] 9% 4096 bytes +Download [=== ] 14% 6144 bytes +Download [==== ] 19% 8192 bytes +Download [====== ] 24% 10240 bytes +Download [======= ] 28% 12288 bytes +Download [======== ] 33% 14336 bytes +Download [========= ] 38% 16384 bytes +Download [========== ] 43% 18432 bytes +Download [============ ] 48% 20480 bytes +Download [============= ] 53% 22528 bytes +Download [============== ] 57% 24576 bytes +Download [=============== ] 62% 26624 bytes +Download [================ ] 67% 28672 bytes +Download [================== ] 72% 30720 bytes +Download [=================== ] 77% 32768 bytes +Download [==================== ] 82% 34816 bytes +Download [===================== ] 86% 36864 bytes +Download [====================== ] 91% 38912 bytes +Download [======================== ] 96% 40356 bytes +Download [=========================] 100% 40356 bytes +Download done. +Sent a total of 40356 bytes +dfu-util: unable to read DFU status + +$ lsusb | grep NXP +Bus 003 Device 014: ID 1fc9:0018 NXP Semiconductors diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/lpclink2.lsusb b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/lpclink2.lsusb new file mode 100644 index 0000000..b833fca --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/lpclink2.lsusb @@ -0,0 +1,203 @@ + +Bus 003 Device 007: ID 0c72:000c PEAK System PCAN-USB +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 16 + idVendor 0x0c72 PEAK System + idProduct 0x000c PCAN-USB + bcdDevice 1c.ff + iManufacturer 0 + iProduct 3 VER1:PEAK +VER2:02.8.01 +DAT :06.05.2004 +TIME:09:35:37 + ... + iSerial 0 + bNumConfigurations 3 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 46 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 200mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 4 + bInterfaceClass 0 (Defined at Interface level) + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 20 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x01 EP 1 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 20 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 46 + bNumInterfaces 1 + bConfigurationValue 2 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 394mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 4 + bInterfaceClass 0 (Defined at Interface level) + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 20 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x01 EP 1 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 20 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 46 + bNumInterfaces 1 + bConfigurationValue 3 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 200mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 4 + bInterfaceClass 0 (Defined at Interface level) + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x01 EP 1 OUT + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 +Device Status: 0x0001 + Self Powered diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/opc-20.lsusb b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/opc-20.lsusb new file mode 100644 index 0000000..580df90 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/opc-20.lsusb @@ -0,0 +1,60 @@ + +Bus 001 Device 004: ID 0483:df11 SGS Thomson Microelectronics +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x0483 SGS Thomson Microelectronics + idProduct 0xdf11 + bcdDevice 2.00 + iManufacturer 1 STMicroelectronics + iProduct 2 STM32 DFU + iSerial 3 ÿÿÿÿÿÿÿÿÿÿÿÿ + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 36 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0xc0 + Self Powered + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 4 @Internal Flash /0x08000000/12*001Ka,116*001Kg + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 5 @SPI Flash : M25P64/0x00000000/128*64Kg + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 11 + Will Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 255 milliseconds + wTransferSize 1024 bytes + bcdDFUVersion 1a.01 +Device Status: 0x0001 + Self Powered diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/openmoko-freerunner-dfumode.lsusb b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/openmoko-freerunner-dfumode.lsusb new file mode 100644 index 0000000..4c0abfb --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/openmoko-freerunner-dfumode.lsusb @@ -0,0 +1,109 @@ +Bus 003 Device 017: ID 1d50:5119 OpenMoko, Inc. GTA01/GTA02 U-Boot Bootloader +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 16 + idVendor 0x1d50 OpenMoko, Inc. + idProduct 0x5119 GTA01/GTA02 U-Boot Bootloader + bcdDevice 0.00 + iManufacturer 1 OpenMoko, Inc + iProduct 2 Neo1973 Bootloader U-Boot 1.3.2-moko12 + iSerial 3 0000000 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 81 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 7 USB Device Firmware Upgrade + bmAttributes 0x80 + (Bus Powered) + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 8 RAM 0x32000000 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 9 u-boot + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 2 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 10 u-boot_env + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 3 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 11 kernel + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 4 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 12 splash + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 5 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 13 factory + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 6 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 14 rootfs + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 7 + Will Not Detach + Manifestation Tolerant + Upload Supported + Download Supported + wDetachTimeout 65280 milliseconds + wTransferSize 4096 bytes + bcdDFUVersion 1.00 +Device Status: 0x0a00 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/openmoko-freerunner.lsusb b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/openmoko-freerunner.lsusb new file mode 100644 index 0000000..835708d --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/openmoko-freerunner.lsusb @@ -0,0 +1,179 @@ +Bus 005 Device 033: ID 1d50:5119 OpenMoko, Inc. GTA01/GTA02 U-Boot Bootloader +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.10 + bDeviceClass 2 Communications + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 16 + idVendor 0x1d50 OpenMoko, Inc. + idProduct 0x5119 GTA01/GTA02 U-Boot Bootloader + bcdDevice 0.00 + iManufacturer 1 OpenMoko, Inc + iProduct 2 Neo1973 Bootloader U-Boot 1.3.2-moko12 + iSerial 3 0000000 + bNumConfigurations 2 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 85 + bNumInterfaces 3 + bConfigurationValue 1 + iConfiguration 4 TTY via USB + bmAttributes 0x80 + (Bus Powered) + MaxPower 500mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 2 Communications + bInterfaceSubClass 2 Abstract (modem) + bInterfaceProtocol 1 AT-commands (v.25ter) + iInterface 6 Control Interface + CDC Header: + bcdCDC 0.6e + CDC Call Management: + bmCapabilities 0x00 + bDataInterface 1 + CDC ACM: + bmCapabilities 0x00 + CDC Union: + bMasterInterface 0 + bSlaveInterface 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 10 CDC Data + bInterfaceSubClass 0 Unused + bInterfaceProtocol 0 + iInterface 5 Bulk Data Interface + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 2 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 1 + iInterface 7 USB Device Firmware Upgrade + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 7 + Will Not Detach + Manifestation Tolerant + Upload Supported + Download Supported + wDetachTimeout 65280 milliseconds + wTransferSize 4096 bytes + bcdDFUVersion 1.00 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 67 + bNumInterfaces 2 + bConfigurationValue 2 + iConfiguration 4 TTY via USB + bmAttributes 0x80 + (Bus Powered) + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 2 Communications + bInterfaceSubClass 2 Abstract (modem) + bInterfaceProtocol 1 AT-commands (v.25ter) + iInterface 6 Control Interface + CDC Header: + bcdCDC 0.6e + CDC Call Management: + bmCapabilities 0x00 + bDataInterface 1 + CDC ACM: + bmCapabilities 0x00 + CDC Union: + bMasterInterface 0 + bSlaveInterface 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 10 CDC Data + bInterfaceSubClass 0 Unused + bInterfaceProtocol 0 + iInterface 5 Bulk Data Interface + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 +Device Status: 0x9a00 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/openmoko-neo1973.lsusb b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/openmoko-neo1973.lsusb new file mode 100644 index 0000000..0778950 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/openmoko-neo1973.lsusb @@ -0,0 +1,182 @@ + +Bus 006 Device 020: ID 1457:5119 First International Computer, Inc. OpenMoko Neo1973 u-boot cdc_acm serial port +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.10 + bDeviceClass 2 Communications + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 16 + idVendor 0x1457 First International Computer, Inc. + idProduct 0x5119 OpenMoko Neo1973 u-boot cdc_acm serial port + bcdDevice 0.00 + iManufacturer 1 + iProduct 2 + iSerial 3 + bNumConfigurations 2 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 85 + bNumInterfaces 3 + bConfigurationValue 1 + iConfiguration 4 + bmAttributes 0x80 + (Bus Powered) + MaxPower 500mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 2 Communications + bInterfaceSubClass 2 Abstract (modem) + bInterfaceProtocol 1 AT-commands (v.25ter) + iInterface 6 + CDC Header: + bcdCDC 0.6e + CDC Call Management: + bmCapabilities 0x00 + bDataInterface 1 + CDC ACM: + bmCapabilities 0x00 + CDC Union: + bMasterInterface 0 + bSlaveInterface 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 10 CDC Data + bInterfaceSubClass 0 Unused + bInterfaceProtocol 0 + iInterface 5 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 2 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 1 + iInterface 7 + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 7 + Will Not Detach + Manifestation Tolerant + Upload Supported + Download Supported + wDetachTimeout 65280 milliseconds + wTransferSize 4096 bytes + bcdDFUVersion 1.00 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 67 + bNumInterfaces 2 + bConfigurationValue 2 + iConfiguration 4 + bmAttributes 0x80 + (Bus Powered) + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 2 Communications + bInterfaceSubClass 2 Abstract (modem) + bInterfaceProtocol 1 AT-commands (v.25ter) + iInterface 6 + CDC Header: + bcdCDC 0.6e + CDC Call Management: + bmCapabilities 0x00 + bDataInterface 1 + CDC ACM: + bmCapabilities 0x00 + CDC Union: + bMasterInterface 0 + bSlaveInterface 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 10 CDC Data + bInterfaceSubClass 0 Unused + bInterfaceProtocol 0 + iInterface 5 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 +Device Status: 0x0006 + (Bus Powered) + Remote Wakeup Enabled + Test Mode diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/openpcd.lsusb b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/openpcd.lsusb new file mode 100644 index 0000000..f6255a9 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/openpcd.lsusb @@ -0,0 +1,60 @@ + +Bus 006 Device 016: ID 16c0:076b VOTI OpenPCD 13.56MHz RFID Reader +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 8 + idVendor 0x16c0 VOTI + idProduct 0x076b OpenPCD 13.56MHz RFID Reader + bcdDevice 0.00 + iManufacturer 1 + iProduct 2 OpenPCD RFID Simulator - DFU Mode + iSerial 0 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 36 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 200mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 0 + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 3 + Will Not Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 65280 milliseconds + wTransferSize 256 bytes + bcdDFUVersion 1.00 +Device Status: 0x0000 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/qi-hardware-atusb.lsusb b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/qi-hardware-atusb.lsusb new file mode 100644 index 0000000..bfc1701 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/qi-hardware-atusb.lsusb @@ -0,0 +1,59 @@ + +Bus 006 Device 013: ID 20b7:1540 Qi Hardware ben-wpan, AT86RF230-based +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 255 Vendor Specific Class + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x20b7 Qi Hardware + idProduct 0x1540 ben-wpan, AT86RF230-based + bcdDevice 0.01 + iManufacturer 0 + iProduct 0 + iSerial 1 4630333438371508231a + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 34 + bNumInterfaces 2 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 40mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 255 Vendor Specific Class + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 1 + iInterface 0 +Device Status: 0x0000 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/simtrace.lsusb b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/simtrace.lsusb new file mode 100644 index 0000000..578ddf0 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/simtrace.lsusb @@ -0,0 +1,70 @@ + +Bus 006 Device 017: ID 16c0:0762 VOTI +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 8 + idVendor 0x16c0 VOTI + idProduct 0x0762 + bcdDevice 0.00 + iManufacturer 1 sysmocom - systems for mobile communications GmbH + iProduct 2 SimTrace SIM Sniffer - DFU Mode + iSerial 0 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 45 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 3 SimTrace DFU Configuration + bmAttributes 0x80 + (Bus Powered) + MaxPower 200mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 4 SimTrace DFU Interface - Application Partition + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 5 SimTrace DFU Interface - Bootloader Partition + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 2 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 6 SimTrace DFU Interface - RAM + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 3 + Will Not Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 65280 milliseconds + wTransferSize 256 bytes + bcdDFUVersion 1.00 +Device Status: 0x0000 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/sparkcore.lsusb b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/sparkcore.lsusb new file mode 100644 index 0000000..b6029ff --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/sparkcore.lsusb @@ -0,0 +1,60 @@ + +Bus 001 Device 008: ID 1d50:607f OpenMoko, Inc. +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x1d50 OpenMoko, Inc. + idProduct 0x607f + bcdDevice 2.00 + iManufacturer 1 Spark Devices + iProduct 2 CORE DFU + iSerial 3 8D80527B5055 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 36 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0xc0 + Self Powered + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 4 @Internal Flash /0x08000000/20*001Ka,108*001Kg + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 5 @SPI Flash : SST25x/0x00000000/512*04Kg + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 11 + Will Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 255 milliseconds + wTransferSize 1024 bytes + bcdDFUVersion 1.1a +Device Status: 0x0001 + Self Powered diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/stm32f107.bin-download b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/stm32f107.bin-download new file mode 100644 index 0000000..45b714f --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/stm32f107.bin-download @@ -0,0 +1,48 @@ +> src/dfu-util --intf 0 --alt 0 -v -v -v -s 0x8000000 -D test3 +dfu-util 0.4 + +(C) 2005-2008 by Weston Schmidt, Harald Welte and OpenMoko Inc. +(C) 2010-2011 Tormod Volden (DfuSe support) +This program is Free Software and has ABSOLUTELY NO WARRANTY + +dfu-util does currently only support DFU version 1.0 + +Opening DFU USB device... ID 0483:df11 +Run-time device DFU version 011a +Found DFU: [0483:df11] devnum=0, cfg=1, intf=0, alt=0, name="@Internal Flash /0x08000000/128*002Kg" +Claiming USB DFU Interface... +Setting Alternate Setting #0 ... +Determining device status: state = dfuIDLE, status = 0 +dfuIDLE, continuing +DFU mode device DFU version 011a +Device returned transfer size 2048 +No valid DFU suffix signature +Warning: File has no DFU suffix +DfuSe interface name: "Internal Flash " +Memory segment at 0x08000000 128 x 2048 = 262144 (rew) +Uploading to address = 0x08000000, size = 16384 +Erasing page size 2048 at address 0x08000000, page starting at 0x08000000 + Download from image offset 00000000 to memory 08000000-080007ff, size 2048 + Setting address pointer to 0x08000000 +Erasing page size 2048 at address 0x08000800, page starting at 0x08000800 + Download from image offset 00000800 to memory 08000800-08000fff, size 2048 + Setting address pointer to 0x08000800 +Erasing page size 2048 at address 0x08001000, page starting at 0x08001000 + Download from image offset 00001000 to memory 08001000-080017ff, size 2048 + Setting address pointer to 0x08001000 +Erasing page size 2048 at address 0x08001800, page starting at 0x08001800 + Download from image offset 00001800 to memory 08001800-08001fff, size 2048 + Setting address pointer to 0x08001800 +Erasing page size 2048 at address 0x08002000, page starting at 0x08002000 + Download from image offset 00002000 to memory 08002000-080027ff, size 2048 + Setting address pointer to 0x08002000 +Erasing page size 2048 at address 0x08002800, page starting at 0x08002800 + Download from image offset 00002800 to memory 08002800-08002fff, size 2048 + Setting address pointer to 0x08002800 +Erasing page size 2048 at address 0x08003000, page starting at 0x08003000 + Download from image offset 00003000 to memory 08003000-080037ff, size 2048 + Setting address pointer to 0x08003000 +Erasing page size 2048 at address 0x08003800, page starting at 0x08003800 + Download from image offset 00003800 to memory 08003800-08003fff, size 2048 + Setting address pointer to 0x08003800 + diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/stm32f107.lsusb b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/stm32f107.lsusb new file mode 100644 index 0000000..14b45cd --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/stm32f107.lsusb @@ -0,0 +1,60 @@ + +Bus 001 Device 028: ID 0483:df11 SGS Thomson Microelectronics STM Device in DFU Mode +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x0483 SGS Thomson Microelectronics + idProduct 0xdf11 STM Device in DFU Mode + bcdDevice 20.00 + iManufacturer 1 STMicroelectronics + iProduct 2 STM32 0x418 DFU Bootloader + iSerial 3 STM32 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 36 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0xc0 + Self Powered + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 4 @Internal Flash /0x08000000/128*002Kg + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 5 @Option Bytes /0x1FFFF800/01*016 g + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 11 + Will Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 255 milliseconds + wTransferSize 2048 bytes + bcdDFUVersion 1.1a +Device Status: 0x0000 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/stm32f4discovery.bin-download b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/stm32f4discovery.bin-download new file mode 100644 index 0000000..96e1722 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/stm32f4discovery.bin-download @@ -0,0 +1,36 @@ +dfu-util --device 0483:df11 --alt 0 \ + --dfuse-address 0x08000000 \ + -v -v -v \ + --download arm/iotoggle.bin +No valid DFU suffix signature +Warning: File has no DFU suffix +dfu-util 0.5 + +(C) 2005-2008 by Weston Schmidt, Harald Welte and OpenMoko Inc. +(C) 2010-2011 Tormod Volden (DfuSe support) +This program is Free Software and has ABSOLUTELY NO WARRANTY + +dfu-util does currently only support DFU version 1.0 + +Filter on vendor = 0x0483 product = 0xdf11 +Opening DFU capable USB device... ID 0483:df11 +Run-time device DFU version 011a +Found DFU: [0483:df11] devnum=0, cfg=1, intf=0, alt=0, name="@Internal Flash /0x08000000/04*016Kg,01*064Kg,07*128Kg" +Claiming USB DFU Interface... +Setting Alternate Setting #0 ... +Determining device status: state = dfuERROR, status = 10 +dfuERROR, clearing status +Determining device status: state = dfuIDLE, status = 0 +dfuIDLE, continuing +DFU mode device DFU version 011a +Device returned transfer size 2048 +DfuSe interface name: "Internal Flash " +Memory segment at 0x08000000 4 x 16384 = 65536 (rew) +Memory segment at 0x08010000 1 x 65536 = 65536 (rew) +Memory segment at 0x08020000 7 x 131072 = 917504 (rew) +Uploading to address = 0x08000000, size = 2308 +Erasing page size 16384 at address 0x08000000, page starting at 0x08000000 + Download from image offset 00000000 to memory 08000000-080007ff, size 2048 + Setting address pointer to 0x08000000 + Download from image offset 00000800 to memory 08000800-08000903, size 260 + Setting address pointer to 0x08000800 diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/stm32f4discovery.lsusb b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/stm32f4discovery.lsusb new file mode 100644 index 0000000..0b870de --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/stm32f4discovery.lsusb @@ -0,0 +1,80 @@ + +Bus 001 Device 010: ID 0483:df11 SGS Thomson Microelectronics STM Device in DFU Mode +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x0483 SGS Thomson Microelectronics + idProduct 0xdf11 STM Device in DFU Mode + bcdDevice 21.00 + iManufacturer 1 STMicroelectronics + iProduct 2 STM32 BOOTLOADER + iSerial 3 315A28A0B956 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 54 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0xc0 + Self Powered + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 4 @Internal Flash /0x08000000/04*016Kg,01*064Kg,07*128Kg + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 5 @Option Bytes /0x1FFFC000/01*016 g + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 2 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 6 @OTP Memory /0x1FFF7800/01*512 g,01*016 g + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 3 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 7 @Device Feature/0xFFFF0000/01*004 g + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 11 + Will Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 255 milliseconds + wTransferSize 2048 bytes + bcdDFUVersion 1.1a +Device Status: 0x0001 + Self Powered diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/tdk-bluetooth.lsusb b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/tdk-bluetooth.lsusb new file mode 100644 index 0000000..c0cface --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/device-logs/tdk-bluetooth.lsusb @@ -0,0 +1,269 @@ + +Bus 006 Device 014: ID 04bf:0320 TDK Corp. Bluetooth Adapter +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 224 Wireless + bDeviceSubClass 1 Radio Frequency + bDeviceProtocol 1 Bluetooth + bMaxPacketSize0 64 + idVendor 0x04bf TDK Corp. + idProduct 0x0320 Bluetooth Adapter + bcdDevice 26.52 + iManufacturer 1 Ezurio + iProduct 2 Turbo Bluetooth Adapter + iSerial 3 008098D4FFBD + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 193 + bNumInterfaces 3 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 64mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 3 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0000 1x 0 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0000 1x 0 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 1 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0009 1x 9 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0009 1x 9 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 2 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0011 1x 17 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0011 1x 17 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 3 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0019 1x 25 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0019 1x 25 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 4 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0021 1x 33 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0021 1x 33 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 5 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0031 1x 49 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0031 1x 49 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 2 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 0 + iInterface 0 + Device Firmware Upgrade Interface Descriptor: + bLength 7 + bDescriptorType 33 + bmAttributes 7 + Will Not Detach + Manifestation Tolerant + Upload Supported + Download Supported + wDetachTimeout 5000 milliseconds + wTransferSize 1023 bytes +Device Status: 0x0000 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/dfuse-pack.py b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/dfuse-pack.py new file mode 100644 index 0000000..875cc5c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/dfuse-pack.py @@ -0,0 +1,121 @@ +#!/usr/bin/python + +# Written by Antonio Galea - 2010/11/18 +# Distributed under Gnu LGPL 3.0 +# see http://www.gnu.org/licenses/lgpl-3.0.txt + +import sys,struct,zlib,os +from optparse import OptionParser + +DEFAULT_DEVICE="0x0483:0xdf11" + +def named(tuple,names): + return dict(zip(names.split(),tuple)) +def consume(fmt,data,names): + n = struct.calcsize(fmt) + return named(struct.unpack(fmt,data[:n]),names),data[n:] +def cstring(string): + return string.split('\0',1)[0] +def compute_crc(data): + return 0xFFFFFFFF & -zlib.crc32(data) -1 + +def parse(file,dump_images=False): + print 'File: "%s"' % file + data = open(file,'rb').read() + crc = compute_crc(data[:-4]) + prefix, data = consume('<5sBIB',data,'signature version size targets') + print '%(signature)s v%(version)d, image size: %(size)d, targets: %(targets)d' % prefix + for t in range(prefix['targets']): + tprefix, data = consume('<6sBI255s2I',data,'signature altsetting named name size elements') + tprefix['num'] = t + if tprefix['named']: + tprefix['name'] = cstring(tprefix['name']) + else: + tprefix['name'] = '' + print '%(signature)s %(num)d, alt setting: %(altsetting)s, name: "%(name)s", size: %(size)d, elements: %(elements)d' % tprefix + tsize = tprefix['size'] + target, data = data[:tsize], data[tsize:] + for e in range(tprefix['elements']): + eprefix, target = consume('<2I',target,'address size') + eprefix['num'] = e + print ' %(num)d, address: 0x%(address)08x, size: %(size)d' % eprefix + esize = eprefix['size'] + image, target = target[:esize], target[esize:] + if dump_images: + out = '%s.target%d.image%d.bin' % (file,t,e) + open(out,'wb').write(image) + print ' DUMPED IMAGE TO "%s"' % out + if len(target): + print "target %d: PARSE ERROR" % t + suffix = named(struct.unpack('<4H3sBI',data[:16]),'device product vendor dfu ufd len crc') + print 'usb: %(vendor)04x:%(product)04x, device: 0x%(device)04x, dfu: 0x%(dfu)04x, %(ufd)s, %(len)d, 0x%(crc)08x' % suffix + if crc != suffix['crc']: + print "CRC ERROR: computed crc32 is 0x%08x" % crc + data = data[16:] + if data: + print "PARSE ERROR" + +def build(file,targets,device=DEFAULT_DEVICE): + data = '' + for t,target in enumerate(targets): + tdata = '' + for image in target: + tdata += struct.pack('<2I',image['address'],len(image['data']))+image['data'] + tdata = struct.pack('<6sBI255s2I','Target',0,1,'ST...',len(tdata),len(target)) + tdata + data += tdata + data = struct.pack('<5sBIB','DfuSe',1,len(data)+11,len(targets)) + data + v,d=map(lambda x: int(x,0) & 0xFFFF, device.split(':',1)) + data += struct.pack('<4H3sB',0,d,v,0x011a,'UFD',16) + crc = compute_crc(data) + data += struct.pack(' and +Harald Welte . Over time, nearly complete +support of DFU 1.0, DFU 1.1 and DfuSe ("1.1a") has been added. +.SH LICENCE +.B dfu-util +is covered by the GNU General Public License (GPL), version 2 or later. +.SH COPYRIGHT +This manual page was originally written by Uwe Hermann , +and is now part of the dfu-util project. diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/msvc/README_msvc.txt b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/msvc/README_msvc.txt new file mode 100644 index 0000000..6e68ec6 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/msvc/README_msvc.txt @@ -0,0 +1,10 @@ +# (C) Roger Meier +# (C) Pascal Schweizer +# msvc folder is GPL-2.0+, LGPL-2.1+, BSD-3-Clause or MIT license(SPDX) + +Building dfu-util native on Windows with Visual Studio + +3rd party dependencies: +- libusbx ( git clone https://github.com/libusbx/libusbx.git ) + - getopt (part of libusbx: libusbx/examples/getopt) + diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/msvc/dfu-suffix_2010.vcxproj b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/msvc/dfu-suffix_2010.vcxproj new file mode 100644 index 0000000..0c316c2 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/msvc/dfu-suffix_2010.vcxproj @@ -0,0 +1,100 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA} + dfusuffix + dfu-suffix + + + + Application + true + MultiByte + + + Application + false + true + MultiByte + + + + + + + + + + + + + $(SolutionDir)..\..\libusbx\examples\getopt;$(SolutionDir)..\..\libusbx\libusb;$(IncludePath) + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\dll;$(LibraryPath) + $(VCInstallDir)atlmfc\lib;$(VCInstallDir)lib + $(ExecutablePath) + + + $(ExecutablePath) + $(SolutionDir)..\..\libusbx\examples\getopt;$(SolutionDir)..\..\libusbx\libusb;$(IncludePath) + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\dll;$(LibraryPath) + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + + + + Level3 + Disabled + HAVE_WINDOWS_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreadedDebug + + + true + + + + + Level3 + MaxSpeed + true + true + HAVE_WINDOWS_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreaded + + + true + true + true + + + + + + + + + + + + + {a2169bc8-cf99-40bf-83f3-b0e38f7067bd} + + + {349ee8f9-7d25-4909-aaf5-ff3fade72187} + + + + + + \ No newline at end of file diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/msvc/dfu-util_2010.sln b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/msvc/dfu-util_2010.sln new file mode 100644 index 0000000..ef79723 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/msvc/dfu-util_2010.sln @@ -0,0 +1,54 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dfu-util", "dfu-util_2010.vcxproj", "{0E071A60-7EF2-4427-BAA8-9143CACB5BCB}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C4F8746D-B27E-4806-95E5-2052174E923B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dfu-suffix", "dfu-suffix_2010.vcxproj", "{8F7600A2-3B37-4956-B39B-A1D43EF29EDA}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "getopt_2010", "..\..\libusbx\msvc\getopt_2010.vcxproj", "{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (static)", "..\..\libusbx\msvc\libusb_static_2010.vcxproj", "{349EE8F9-7D25-4909-AAF5-FF3FADE72187}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB}.Debug|Win32.ActiveCfg = Debug|Win32 + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB}.Debug|Win32.Build.0 = Debug|Win32 + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB}.Debug|x64.ActiveCfg = Debug|Win32 + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB}.Release|Win32.ActiveCfg = Release|Win32 + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB}.Release|Win32.Build.0 = Release|Win32 + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB}.Release|x64.ActiveCfg = Release|Win32 + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA}.Debug|Win32.ActiveCfg = Debug|Win32 + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA}.Debug|Win32.Build.0 = Debug|Win32 + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA}.Debug|x64.ActiveCfg = Debug|Win32 + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA}.Release|Win32.ActiveCfg = Release|Win32 + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA}.Release|Win32.Build.0 = Release|Win32 + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA}.Release|x64.ActiveCfg = Release|Win32 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|Win32.ActiveCfg = Debug|Win32 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|Win32.Build.0 = Debug|Win32 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|x64.ActiveCfg = Debug|x64 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|x64.Build.0 = Debug|x64 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|Win32.ActiveCfg = Release|Win32 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|Win32.Build.0 = Release|Win32 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|x64.ActiveCfg = Release|x64 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|x64.Build.0 = Release|x64 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.ActiveCfg = Debug|Win32 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.Build.0 = Debug|Win32 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.ActiveCfg = Debug|x64 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.Build.0 = Debug|x64 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.ActiveCfg = Release|Win32 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.Build.0 = Release|Win32 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.ActiveCfg = Release|x64 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/msvc/dfu-util_2010.vcxproj b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/msvc/dfu-util_2010.vcxproj new file mode 100644 index 0000000..17a8bee --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/msvc/dfu-util_2010.vcxproj @@ -0,0 +1,120 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB} + dfuutil + dfu-util + + + + Application + true + MultiByte + + + Application + false + true + MultiByte + + + + + + + + + + + + + $(SolutionDir)..\..\libusbx\examples\getopt;$(SolutionDir)..\..\libusbx\libusb;$(IncludePath) + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + $(SolutionDir)..\$(Platform)\getopt\$(Configuration);$(LibraryPath) + $(VCInstallDir)atlmfc\lib;$(VCInstallDir)lib + $(ExecutablePath) + + + $(ExecutablePath) + $(SolutionDir)..\..\libusbx\examples\getopt;$(SolutionDir)..\..\libusbx\libusb;$(IncludePath) + $(SolutionDir)..\$(Platform)\getopt\$(Configuration);$(LibraryPath) + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + + + + Level3 + Disabled + HAVE_WINDOWS_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreadedDebug + + + true + + + + + + + + + Level3 + MaxSpeed + true + true + HAVE_WINDOWS_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreaded + + + true + true + true + + + copy $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0.dll $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + + + + + + + + + + + + + + + + + + + + + + + + + + {a2169bc8-cf99-40bf-83f3-b0e38f7067bd} + + + {349ee8f9-7d25-4909-aaf5-ff3fade72187} + + + + + + \ No newline at end of file diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/Makefile.am b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/Makefile.am new file mode 100644 index 0000000..70179c4 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/Makefile.am @@ -0,0 +1,28 @@ +AM_CFLAGS = -Wall -Wextra + +bin_PROGRAMS = dfu-util dfu-suffix dfu-prefix +dfu_util_SOURCES = main.c \ + portable.h \ + dfu_load.c \ + dfu_load.h \ + dfu_util.c \ + dfu_util.h \ + dfuse.c \ + dfuse.h \ + dfuse_mem.c \ + dfuse_mem.h \ + dfu.c \ + dfu.h \ + usb_dfu.h \ + dfu_file.c \ + dfu_file.h \ + quirks.c \ + quirks.h + +dfu_suffix_SOURCES = suffix.c \ + dfu_file.h \ + dfu_file.c + +dfu_prefix_SOURCES = prefix.c \ + dfu_file.h \ + dfu_file.c diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfu.c b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfu.c new file mode 100644 index 0000000..14d7673 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfu.c @@ -0,0 +1,357 @@ +/* + * Low-level DFU communication routines, originally taken from + * $Id: dfu.c,v 1.3 2006/06/20 06:28:04 schmidtw Exp $ + * (part of dfu-programmer). + * + * Copyright 2005-2006 Weston Schmidt + * Copyright 2011-2014 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include + +#include "portable.h" +#include "dfu.h" +#include "quirks.h" + +static int dfu_timeout = 5000; /* 5 seconds - default */ + +/* + * DFU_DETACH Request (DFU Spec 1.0, Section 5.1) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * timeout - the timeout in ms the USB device should wait for a pending + * USB reset before giving up and terminating the operation + * + * returns 0 or < 0 on error + */ +int dfu_detach( libusb_device_handle *device, + const unsigned short interface, + const unsigned short timeout ) +{ + return libusb_control_transfer( device, + /* bmRequestType */ LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_DETACH, + /* wValue */ timeout, + /* wIndex */ interface, + /* Data */ NULL, + /* wLength */ 0, + dfu_timeout ); +} + + +/* + * DFU_DNLOAD Request (DFU Spec 1.0, Section 6.1.1) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * length - the total number of bytes to transfer to the USB + * device - must be less than wTransferSize + * data - the data to transfer + * + * returns the number of bytes written or < 0 on error + */ +int dfu_download( libusb_device_handle *device, + const unsigned short interface, + const unsigned short length, + const unsigned short transaction, + unsigned char* data ) +{ + int status; + + status = libusb_control_transfer( device, + /* bmRequestType */ LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_DNLOAD, + /* wValue */ transaction, + /* wIndex */ interface, + /* Data */ data, + /* wLength */ length, + dfu_timeout ); + return status; +} + + +/* + * DFU_UPLOAD Request (DFU Spec 1.0, Section 6.2) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * length - the maximum number of bytes to receive from the USB + * device - must be less than wTransferSize + * data - the buffer to put the received data in + * + * returns the number of bytes received or < 0 on error + */ +int dfu_upload( libusb_device_handle *device, + const unsigned short interface, + const unsigned short length, + const unsigned short transaction, + unsigned char* data ) +{ + int status; + + status = libusb_control_transfer( device, + /* bmRequestType */ LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_UPLOAD, + /* wValue */ transaction, + /* wIndex */ interface, + /* Data */ data, + /* wLength */ length, + dfu_timeout ); + return status; +} + + +/* + * DFU_GETSTATUS Request (DFU Spec 1.0, Section 6.1.2) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * status - the data structure to be populated with the results + * + * return the number of bytes read in or < 0 on an error + */ +int dfu_get_status( struct dfu_if *dif, struct dfu_status *status ) +{ + unsigned char buffer[6]; + int result; + + /* Initialize the status data structure */ + status->bStatus = DFU_STATUS_ERROR_UNKNOWN; + status->bwPollTimeout = 0; + status->bState = STATE_DFU_ERROR; + status->iString = 0; + + result = libusb_control_transfer( dif->dev_handle, + /* bmRequestType */ LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_GETSTATUS, + /* wValue */ 0, + /* wIndex */ dif->interface, + /* Data */ buffer, + /* wLength */ 6, + dfu_timeout ); + + if( 6 == result ) { + status->bStatus = buffer[0]; + if (dif->quirks & QUIRK_POLLTIMEOUT) + status->bwPollTimeout = DEFAULT_POLLTIMEOUT; + else + status->bwPollTimeout = ((0xff & buffer[3]) << 16) | + ((0xff & buffer[2]) << 8) | + (0xff & buffer[1]); + status->bState = buffer[4]; + status->iString = buffer[5]; + } + + return result; +} + + +/* + * DFU_CLRSTATUS Request (DFU Spec 1.0, Section 6.1.3) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * + * return 0 or < 0 on an error + */ +int dfu_clear_status( libusb_device_handle *device, + const unsigned short interface ) +{ + return libusb_control_transfer( device, + /* bmRequestType */ LIBUSB_ENDPOINT_OUT| LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_CLRSTATUS, + /* wValue */ 0, + /* wIndex */ interface, + /* Data */ NULL, + /* wLength */ 0, + dfu_timeout ); +} + + +/* + * DFU_GETSTATE Request (DFU Spec 1.0, Section 6.1.5) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * length - the maximum number of bytes to receive from the USB + * device - must be less than wTransferSize + * data - the buffer to put the received data in + * + * returns the state or < 0 on error + */ +int dfu_get_state( libusb_device_handle *device, + const unsigned short interface ) +{ + int result; + unsigned char buffer[1]; + + result = libusb_control_transfer( device, + /* bmRequestType */ LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_GETSTATE, + /* wValue */ 0, + /* wIndex */ interface, + /* Data */ buffer, + /* wLength */ 1, + dfu_timeout ); + + /* Return the error if there is one. */ + if (result < 1) + return -1; + + /* Return the state. */ + return buffer[0]; +} + + +/* + * DFU_ABORT Request (DFU Spec 1.0, Section 6.1.4) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * + * returns 0 or < 0 on an error + */ +int dfu_abort( libusb_device_handle *device, + const unsigned short interface ) +{ + return libusb_control_transfer( device, + /* bmRequestType */ LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_ABORT, + /* wValue */ 0, + /* wIndex */ interface, + /* Data */ NULL, + /* wLength */ 0, + dfu_timeout ); +} + + +const char* dfu_state_to_string( int state ) +{ + const char *message; + + switch (state) { + case STATE_APP_IDLE: + message = "appIDLE"; + break; + case STATE_APP_DETACH: + message = "appDETACH"; + break; + case STATE_DFU_IDLE: + message = "dfuIDLE"; + break; + case STATE_DFU_DOWNLOAD_SYNC: + message = "dfuDNLOAD-SYNC"; + break; + case STATE_DFU_DOWNLOAD_BUSY: + message = "dfuDNBUSY"; + break; + case STATE_DFU_DOWNLOAD_IDLE: + message = "dfuDNLOAD-IDLE"; + break; + case STATE_DFU_MANIFEST_SYNC: + message = "dfuMANIFEST-SYNC"; + break; + case STATE_DFU_MANIFEST: + message = "dfuMANIFEST"; + break; + case STATE_DFU_MANIFEST_WAIT_RESET: + message = "dfuMANIFEST-WAIT-RESET"; + break; + case STATE_DFU_UPLOAD_IDLE: + message = "dfuUPLOAD-IDLE"; + break; + case STATE_DFU_ERROR: + message = "dfuERROR"; + break; + default: + message = NULL; + break; + } + + return message; +} + +/* Chapter 6.1.2 */ +static const char *dfu_status_names[] = { + /* DFU_STATUS_OK */ + "No error condition is present", + /* DFU_STATUS_errTARGET */ + "File is not targeted for use by this device", + /* DFU_STATUS_errFILE */ + "File is for this device but fails some vendor-specific test", + /* DFU_STATUS_errWRITE */ + "Device is unable to write memory", + /* DFU_STATUS_errERASE */ + "Memory erase function failed", + /* DFU_STATUS_errCHECK_ERASED */ + "Memory erase check failed", + /* DFU_STATUS_errPROG */ + "Program memory function failed", + /* DFU_STATUS_errVERIFY */ + "Programmed memory failed verification", + /* DFU_STATUS_errADDRESS */ + "Cannot program memory due to received address that is out of range", + /* DFU_STATUS_errNOTDONE */ + "Received DFU_DNLOAD with wLength = 0, but device does not think that it has all data yet", + /* DFU_STATUS_errFIRMWARE */ + "Device's firmware is corrupt. It cannot return to run-time (non-DFU) operations", + /* DFU_STATUS_errVENDOR */ + "iString indicates a vendor specific error", + /* DFU_STATUS_errUSBR */ + "Device detected unexpected USB reset signalling", + /* DFU_STATUS_errPOR */ + "Device detected unexpected power on reset", + /* DFU_STATUS_errUNKNOWN */ + "Something went wrong, but the device does not know what it was", + /* DFU_STATUS_errSTALLEDPKT */ + "Device stalled an unexpected request" +}; + + +const char *dfu_status_to_string(int status) +{ + if (status > DFU_STATUS_errSTALLEDPKT) + return "INVALID"; + return dfu_status_names[status]; +} + +int dfu_abort_to_idle(struct dfu_if *dif) +{ + int ret; + struct dfu_status dst; + + ret = dfu_abort(dif->dev_handle, dif->interface); + if (ret < 0) { + errx(EX_IOERR, "Error sending dfu abort request"); + exit(1); + } + ret = dfu_get_status(dif, &dst); + if (ret < 0) { + errx(EX_IOERR, "Error during abort get_status"); + exit(1); + } + if (dst.bState != DFU_STATE_dfuIDLE) { + errx(EX_IOERR, "Failed to enter idle state on abort"); + exit(1); + } + milli_sleep(dst.bwPollTimeout); + return ret; +} diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfu.h b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfu.h new file mode 100644 index 0000000..8e3caeb --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfu.h @@ -0,0 +1,133 @@ +/* + * dfu-programmer + * + * $Id: dfu.h,v 1.2 2005/09/25 01:27:42 schmidtw Exp $ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DFU_H +#define DFU_H + +#include +#include "usb_dfu.h" + +/* DFU states */ +#define STATE_APP_IDLE 0x00 +#define STATE_APP_DETACH 0x01 +#define STATE_DFU_IDLE 0x02 +#define STATE_DFU_DOWNLOAD_SYNC 0x03 +#define STATE_DFU_DOWNLOAD_BUSY 0x04 +#define STATE_DFU_DOWNLOAD_IDLE 0x05 +#define STATE_DFU_MANIFEST_SYNC 0x06 +#define STATE_DFU_MANIFEST 0x07 +#define STATE_DFU_MANIFEST_WAIT_RESET 0x08 +#define STATE_DFU_UPLOAD_IDLE 0x09 +#define STATE_DFU_ERROR 0x0a + + +/* DFU status */ +#define DFU_STATUS_OK 0x00 +#define DFU_STATUS_ERROR_TARGET 0x01 +#define DFU_STATUS_ERROR_FILE 0x02 +#define DFU_STATUS_ERROR_WRITE 0x03 +#define DFU_STATUS_ERROR_ERASE 0x04 +#define DFU_STATUS_ERROR_CHECK_ERASED 0x05 +#define DFU_STATUS_ERROR_PROG 0x06 +#define DFU_STATUS_ERROR_VERIFY 0x07 +#define DFU_STATUS_ERROR_ADDRESS 0x08 +#define DFU_STATUS_ERROR_NOTDONE 0x09 +#define DFU_STATUS_ERROR_FIRMWARE 0x0a +#define DFU_STATUS_ERROR_VENDOR 0x0b +#define DFU_STATUS_ERROR_USBR 0x0c +#define DFU_STATUS_ERROR_POR 0x0d +#define DFU_STATUS_ERROR_UNKNOWN 0x0e +#define DFU_STATUS_ERROR_STALLEDPKT 0x0f + +/* DFU commands */ +#define DFU_DETACH 0 +#define DFU_DNLOAD 1 +#define DFU_UPLOAD 2 +#define DFU_GETSTATUS 3 +#define DFU_CLRSTATUS 4 +#define DFU_GETSTATE 5 +#define DFU_ABORT 6 + +/* DFU interface */ +#define DFU_IFF_DFU 0x0001 /* DFU Mode, (not Runtime) */ + +/* This is based off of DFU_GETSTATUS + * + * 1 unsigned byte bStatus + * 3 unsigned byte bwPollTimeout + * 1 unsigned byte bState + * 1 unsigned byte iString +*/ + +struct dfu_status { + unsigned char bStatus; + unsigned int bwPollTimeout; + unsigned char bState; + unsigned char iString; +}; + +struct dfu_if { + struct usb_dfu_func_descriptor func_dfu; + uint16_t quirks; + uint16_t busnum; + uint16_t devnum; + uint16_t vendor; + uint16_t product; + uint16_t bcdDevice; + uint8_t configuration; + uint8_t interface; + uint8_t altsetting; + uint8_t flags; + uint8_t bMaxPacketSize0; + char *alt_name; + char *serial_name; + libusb_device *dev; + libusb_device_handle *dev_handle; + struct dfu_if *next; +}; + +int dfu_detach( libusb_device_handle *device, + const unsigned short interface, + const unsigned short timeout ); +int dfu_download( libusb_device_handle *device, + const unsigned short interface, + const unsigned short length, + const unsigned short transaction, + unsigned char* data ); +int dfu_upload( libusb_device_handle *device, + const unsigned short interface, + const unsigned short length, + const unsigned short transaction, + unsigned char* data ); +int dfu_get_status( struct dfu_if *dif, + struct dfu_status *status ); +int dfu_clear_status( libusb_device_handle *device, + const unsigned short interface ); +int dfu_get_state( libusb_device_handle *device, + const unsigned short interface ); +int dfu_abort( libusb_device_handle *device, + const unsigned short interface ); +int dfu_abort_to_idle( struct dfu_if *dif); + +const char *dfu_state_to_string( int state ); + +const char *dfu_status_to_string( int status ); + +#endif /* DFU_H */ diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfu_file.c b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfu_file.c new file mode 100644 index 0000000..7c897d4 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfu_file.c @@ -0,0 +1,444 @@ +/* + * Load or store DFU files including suffix and prefix + * + * Copyright 2014 Tormod Volden + * Copyright 2012 Stefan Schmidt + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "portable.h" +#include "dfu_file.h" + +#define DFU_SUFFIX_LENGTH 16 +#define LMDFU_PREFIX_LENGTH 8 +#define LPCDFU_PREFIX_LENGTH 16 +#define PROGRESS_BAR_WIDTH 25 +#define STDIN_CHUNK_SIZE 65536 + +static const unsigned long crc32_table[] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d}; + +static uint32_t crc32_byte(uint32_t accum, uint8_t delta) +{ + return crc32_table[(accum ^ delta) & 0xff] ^ (accum >> 8); +} + +static int probe_prefix(struct dfu_file *file) +{ + uint8_t *prefix = file->firmware; + + if (file->size.total < LMDFU_PREFIX_LENGTH) + return 1; + if ((prefix[0] == 0x01) && (prefix[1] == 0x00)) { + file->prefix_type = LMDFU_PREFIX; + file->size.prefix = LMDFU_PREFIX_LENGTH; + file->lmdfu_address = 1024 * ((prefix[3] << 8) | prefix[2]); + } + else if (((prefix[0] & 0x3f) == 0x1a) && ((prefix[1] & 0x3f)== 0x3f)) { + file->prefix_type = LPCDFU_UNENCRYPTED_PREFIX; + file->size.prefix = LPCDFU_PREFIX_LENGTH; + } + + if (file->size.prefix + file->size.suffix > file->size.total) + return 1; + return 0; +} + +void dfu_progress_bar(const char *desc, unsigned long long curr, + unsigned long long max) +{ + static char buf[PROGRESS_BAR_WIDTH + 1]; + static unsigned long long last_progress = -1; + static time_t last_time; + time_t curr_time = time(NULL); + unsigned long long progress; + unsigned long long x; + + /* check for not known maximum */ + if (max < curr) + max = curr + 1; + /* make none out of none give zero */ + if (max == 0 && curr == 0) + max = 1; + + /* compute completion */ + progress = (PROGRESS_BAR_WIDTH * curr) / max; + if (progress > PROGRESS_BAR_WIDTH) + progress = PROGRESS_BAR_WIDTH; + if (progress == last_progress && + curr_time == last_time) + return; + last_progress = progress; + last_time = curr_time; + + for (x = 0; x != PROGRESS_BAR_WIDTH; x++) { + if (x < progress) + buf[x] = '='; + else + buf[x] = ' '; + } + buf[x] = 0; + + printf("\r%s\t[%s] %3lld%% %12lld bytes", desc, buf, + (100ULL * curr) / max, curr); + + if (progress == PROGRESS_BAR_WIDTH) + printf("\n%s done.\n", desc); +} + +void *dfu_malloc(size_t size) +{ + void *ptr = malloc(size); + if (ptr == NULL) + errx(EX_SOFTWARE, "Cannot allocate memory of size %d bytes", (int)size); + return (ptr); +} + +uint32_t dfu_file_write_crc(int f, uint32_t crc, const void *buf, int size) +{ + int x; + + /* compute CRC */ + for (x = 0; x != size; x++) + crc = crc32_byte(crc, ((uint8_t *)buf)[x]); + + /* write data */ + if (write(f, buf, size) != size) + err(EX_IOERR, "Could not write %d bytes to file %d", size, f); + + return (crc); +} + +void dfu_load_file(struct dfu_file *file, enum suffix_req check_suffix, enum prefix_req check_prefix) +{ + off_t offset; + int f; + int i; + int res; + + file->size.prefix = 0; + file->size.suffix = 0; + + /* default values, if no valid suffix is found */ + file->bcdDFU = 0; + file->idVendor = 0xffff; /* wildcard value */ + file->idProduct = 0xffff; /* wildcard value */ + file->bcdDevice = 0xffff; /* wildcard value */ + + /* default values, if no valid prefix is found */ + file->lmdfu_address = 0; + + free(file->firmware); + + if (!strcmp(file->name, "-")) { + int read_bytes; + +#ifdef WIN32 + _setmode( _fileno( stdin ), _O_BINARY ); +#endif + file->firmware = (uint8_t*) dfu_malloc(STDIN_CHUNK_SIZE); + read_bytes = fread(file->firmware, 1, STDIN_CHUNK_SIZE, stdin); + file->size.total = read_bytes; + while (read_bytes == STDIN_CHUNK_SIZE) { + file->firmware = (uint8_t*) realloc(file->firmware, file->size.total + STDIN_CHUNK_SIZE); + if (!file->firmware) + err(EX_IOERR, "Could not allocate firmware buffer"); + read_bytes = fread(file->firmware + file->size.total, 1, STDIN_CHUNK_SIZE, stdin); + file->size.total += read_bytes; + } + if (verbose) + printf("Read %i bytes from stdin\n", file->size.total); + /* Never require suffix when reading from stdin */ + check_suffix = MAYBE_SUFFIX; + } else { + f = open(file->name, O_RDONLY | O_BINARY); + if (f < 0) + err(EX_IOERR, "Could not open file %s for reading", file->name); + + offset = lseek(f, 0, SEEK_END); + + if ((int)offset < 0 || (int)offset != offset) + err(EX_IOERR, "File size is too big"); + + if (lseek(f, 0, SEEK_SET) != 0) + err(EX_IOERR, "Could not seek to beginning"); + + file->size.total = offset; + file->firmware = dfu_malloc(file->size.total); + + if (read(f, file->firmware, file->size.total) != file->size.total) { + err(EX_IOERR, "Could not read %d bytes from %s", + file->size.total, file->name); + } + close(f); + } + + /* Check for possible DFU file suffix by trying to parse one */ + { + uint32_t crc = 0xffffffff; + const uint8_t *dfusuffix; + int missing_suffix = 0; + const char *reason; + + if (file->size.total < DFU_SUFFIX_LENGTH) { + reason = "File too short for DFU suffix"; + missing_suffix = 1; + goto checked; + } + + dfusuffix = file->firmware + file->size.total - + DFU_SUFFIX_LENGTH; + + for (i = 0; i < file->size.total - 4; i++) + crc = crc32_byte(crc, file->firmware[i]); + + if (dfusuffix[10] != 'D' || + dfusuffix[9] != 'F' || + dfusuffix[8] != 'U') { + reason = "Invalid DFU suffix signature"; + missing_suffix = 1; + goto checked; + } + + file->dwCRC = (dfusuffix[15] << 24) + + (dfusuffix[14] << 16) + + (dfusuffix[13] << 8) + + dfusuffix[12]; + + if (file->dwCRC != crc) { + reason = "DFU suffix CRC does not match"; + missing_suffix = 1; + goto checked; + } + + /* At this point we believe we have a DFU suffix + so we require further checks to succeed */ + + file->bcdDFU = (dfusuffix[7] << 8) + dfusuffix[6]; + + if (verbose) + printf("DFU suffix version %x\n", file->bcdDFU); + + file->size.suffix = dfusuffix[11]; + + if (file->size.suffix < DFU_SUFFIX_LENGTH) { + errx(EX_IOERR, "Unsupported DFU suffix length %d", + file->size.suffix); + } + + if (file->size.suffix > file->size.total) { + errx(EX_IOERR, "Invalid DFU suffix length %d", + file->size.suffix); + } + + file->idVendor = (dfusuffix[5] << 8) + dfusuffix[4]; + file->idProduct = (dfusuffix[3] << 8) + dfusuffix[2]; + file->bcdDevice = (dfusuffix[1] << 8) + dfusuffix[0]; + +checked: + if (missing_suffix) { + if (check_suffix == NEEDS_SUFFIX) { + warnx("%s", reason); + errx(EX_IOERR, "Valid DFU suffix needed"); + } else if (check_suffix == MAYBE_SUFFIX) { + warnx("%s", reason); + warnx("A valid DFU suffix will be required in " + "a future dfu-util release!!!"); + } + } else { + if (check_suffix == NO_SUFFIX) { + errx(EX_SOFTWARE, "Please remove existing DFU suffix before adding a new one.\n"); + } + } + } + res = probe_prefix(file); + if ((res || file->size.prefix == 0) && check_prefix == NEEDS_PREFIX) + errx(EX_IOERR, "Valid DFU prefix needed"); + if (file->size.prefix && check_prefix == NO_PREFIX) + errx(EX_IOERR, "A prefix already exists, please delete it first"); + if (file->size.prefix && verbose) { + uint8_t *data = file->firmware; + if (file->prefix_type == LMDFU_PREFIX) + printf("Possible TI Stellaris DFU prefix with " + "the following properties\n" + "Address: 0x%08x\n" + "Payload length: %d\n", + file->lmdfu_address, + data[4] | (data[5] << 8) | + (data[6] << 16) | (data[7] << 14)); + else if (file->prefix_type == LPCDFU_UNENCRYPTED_PREFIX) + printf("Possible unencrypted NXP LPC DFU prefix with " + "the following properties\n" + "Payload length: %d kiByte\n", + data[2] >>1 | (data[3] << 7) ); + else + errx(EX_IOERR, "Unknown DFU prefix type"); + } +} + +void dfu_store_file(struct dfu_file *file, int write_suffix, int write_prefix) +{ + uint32_t crc = 0xffffffff; + int f; + + f = open(file->name, O_WRONLY | O_BINARY | O_TRUNC | O_CREAT, 0666); + if (f < 0) + err(EX_IOERR, "Could not open file %s for writing", file->name); + + /* write prefix, if any */ + if (write_prefix) { + if (file->prefix_type == LMDFU_PREFIX) { + uint8_t lmdfu_prefix[LMDFU_PREFIX_LENGTH]; + uint32_t addr = file->lmdfu_address / 1024; + + /* lmdfu_dfu_prefix payload length excludes prefix and suffix */ + uint32_t len = file->size.total - + file->size.prefix - file->size.suffix; + + lmdfu_prefix[0] = 0x01; /* STELLARIS_DFU_PROG */ + lmdfu_prefix[1] = 0x00; /* Reserved */ + lmdfu_prefix[2] = (uint8_t)(addr & 0xff); + lmdfu_prefix[3] = (uint8_t)(addr >> 8); + lmdfu_prefix[4] = (uint8_t)(len & 0xff); + lmdfu_prefix[5] = (uint8_t)(len >> 8) & 0xff; + lmdfu_prefix[6] = (uint8_t)(len >> 16) & 0xff; + lmdfu_prefix[7] = (uint8_t)(len >> 24); + + crc = dfu_file_write_crc(f, crc, lmdfu_prefix, LMDFU_PREFIX_LENGTH); + } + if (file->prefix_type == LPCDFU_UNENCRYPTED_PREFIX) { + uint8_t lpcdfu_prefix[LPCDFU_PREFIX_LENGTH] = {0}; + int i; + + /* Payload is firmware and prefix rounded to 512 bytes */ + uint32_t len = (file->size.total - file->size.suffix + 511) /512; + + lpcdfu_prefix[0] = 0x1a; /* Unencypted*/ + lpcdfu_prefix[1] = 0x3f; /* Reserved */ + lpcdfu_prefix[2] = (uint8_t)(len & 0xff); + lpcdfu_prefix[3] = (uint8_t)((len >> 8) & 0xff); + for (i = 12; i < LPCDFU_PREFIX_LENGTH; i++) + lpcdfu_prefix[i] = 0xff; + + crc = dfu_file_write_crc(f, crc, lpcdfu_prefix, LPCDFU_PREFIX_LENGTH); + } + } + /* write firmware binary */ + crc = dfu_file_write_crc(f, crc, file->firmware + file->size.prefix, + file->size.total - file->size.prefix - file->size.suffix); + + /* write suffix, if any */ + if (write_suffix) { + uint8_t dfusuffix[DFU_SUFFIX_LENGTH]; + + dfusuffix[0] = file->bcdDevice & 0xff; + dfusuffix[1] = file->bcdDevice >> 8; + dfusuffix[2] = file->idProduct & 0xff; + dfusuffix[3] = file->idProduct >> 8; + dfusuffix[4] = file->idVendor & 0xff; + dfusuffix[5] = file->idVendor >> 8; + dfusuffix[6] = file->bcdDFU & 0xff; + dfusuffix[7] = file->bcdDFU >> 8; + dfusuffix[8] = 'U'; + dfusuffix[9] = 'F'; + dfusuffix[10] = 'D'; + dfusuffix[11] = DFU_SUFFIX_LENGTH; + + crc = dfu_file_write_crc(f, crc, dfusuffix, + DFU_SUFFIX_LENGTH - 4); + + dfusuffix[12] = crc; + dfusuffix[13] = crc >> 8; + dfusuffix[14] = crc >> 16; + dfusuffix[15] = crc >> 24; + + crc = dfu_file_write_crc(f, crc, dfusuffix + 12, 4); + } + close(f); +} + +void show_suffix_and_prefix(struct dfu_file *file) +{ + if (file->size.prefix == LMDFU_PREFIX_LENGTH) { + printf("The file %s contains a TI Stellaris DFU prefix with the following properties:\n", file->name); + printf("Address:\t0x%08x\n", file->lmdfu_address); + } else if (file->size.prefix == LPCDFU_PREFIX_LENGTH) { + uint8_t * prefix = file->firmware; + printf("The file %s contains a NXP unencrypted LPC DFU prefix with the following properties:\n", file->name); + printf("Size:\t%5d kiB\n", prefix[2]>>1|prefix[3]<<7); + } else if (file->size.prefix != 0) { + printf("The file %s contains an unknown prefix\n", file->name); + } + if (file->size.suffix > 0) { + printf("The file %s contains a DFU suffix with the following properties:\n", file->name); + printf("BCD device:\t0x%04X\n", file->bcdDevice); + printf("Product ID:\t0x%04X\n",file->idProduct); + printf("Vendor ID:\t0x%04X\n", file->idVendor); + printf("BCD DFU:\t0x%04X\n", file->bcdDFU); + printf("Length:\t\t%i\n", file->size.suffix); + printf("CRC:\t\t0x%08X\n", file->dwCRC); + } +} diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfu_file.h b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfu_file.h new file mode 100644 index 0000000..abebd44 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfu_file.h @@ -0,0 +1,60 @@ + +#ifndef DFU_FILE_H +#define DFU_FILE_H + +#include + +struct dfu_file { + /* File name */ + const char *name; + /* Pointer to file loaded into memory */ + uint8_t *firmware; + /* Different sizes */ + struct { + int total; + int prefix; + int suffix; + } size; + /* From prefix fields */ + uint32_t lmdfu_address; + /* From prefix fields */ + uint32_t prefix_type; + + /* From DFU suffix fields */ + uint32_t dwCRC; + uint16_t bcdDFU; + uint16_t idVendor; + uint16_t idProduct; + uint16_t bcdDevice; +}; + +enum suffix_req { + NO_SUFFIX, + NEEDS_SUFFIX, + MAYBE_SUFFIX +}; + +enum prefix_req { + NO_PREFIX, + NEEDS_PREFIX, + MAYBE_PREFIX +}; + +enum prefix_type { + ZERO_PREFIX, + LMDFU_PREFIX, + LPCDFU_UNENCRYPTED_PREFIX +}; + +extern int verbose; + +void dfu_load_file(struct dfu_file *file, enum suffix_req check_suffix, enum prefix_req check_prefix); +void dfu_store_file(struct dfu_file *file, int write_suffix, int write_prefix); + +void dfu_progress_bar(const char *desc, unsigned long long curr, + unsigned long long max); +void *dfu_malloc(size_t size); +uint32_t dfu_file_write_crc(int f, uint32_t crc, const void *buf, int size); +void show_suffix_and_prefix(struct dfu_file *file); + +#endif /* DFU_FILE_H */ diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfu_load.c b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfu_load.c new file mode 100644 index 0000000..64f7009 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfu_load.c @@ -0,0 +1,196 @@ +/* + * DFU transfer routines + * + * This is supposed to be a general DFU implementation, as specified in the + * USB DFU 1.0 and 1.1 specification. + * + * The code was originally intended to interface with a USB device running the + * "sam7dfu" firmware (see http://www.openpcd.org/) on an AT91SAM7 processor. + * + * Copyright 2007-2008 Harald Welte + * Copyright 2013 Hans Petter Selasky + * Copyright 2014 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include + +#include "portable.h" +#include "dfu.h" +#include "usb_dfu.h" +#include "dfu_file.h" +#include "dfu_load.h" +#include "quirks.h" + +int dfuload_do_upload(struct dfu_if *dif, int xfer_size, + int expected_size, int fd) +{ + int total_bytes = 0; + unsigned short transaction = 0; + unsigned char *buf; + int ret; + + buf = dfu_malloc(xfer_size); + + printf("Copying data from DFU device to PC\n"); + dfu_progress_bar("Upload", 0, 1); + + while (1) { + int rc; + rc = dfu_upload(dif->dev_handle, dif->interface, + xfer_size, transaction++, buf); + if (rc < 0) { + warnx("Error during upload"); + ret = rc; + goto out_free; + } + + dfu_file_write_crc(fd, 0, buf, rc); + total_bytes += rc; + + if (total_bytes < 0) + errx(EX_SOFTWARE, "Received too many bytes (wraparound)"); + + if (rc < xfer_size) { + /* last block, return */ + ret = total_bytes; + break; + } + dfu_progress_bar("Upload", total_bytes, expected_size); + } + ret = 0; + +out_free: + dfu_progress_bar("Upload", total_bytes, total_bytes); + if (total_bytes == 0) + printf("\nFailed.\n"); + free(buf); + if (verbose) + printf("Received a total of %i bytes\n", total_bytes); + if (expected_size != 0 && total_bytes != expected_size) + errx(EX_SOFTWARE, "Unexpected number of bytes uploaded from device"); + return ret; +} + +int dfuload_do_dnload(struct dfu_if *dif, int xfer_size, struct dfu_file *file) +{ + int bytes_sent; + int expected_size; + unsigned char *buf; + unsigned short transaction = 0; + struct dfu_status dst; + int ret; + + printf("Copying data from PC to DFU device\n"); + + buf = file->firmware; + expected_size = file->size.total - file->size.suffix; + bytes_sent = 0; + + dfu_progress_bar("Download", 0, 1); + while (bytes_sent < expected_size) { + int bytes_left; + int chunk_size; + + bytes_left = expected_size - bytes_sent; + if (bytes_left < xfer_size) + chunk_size = bytes_left; + else + chunk_size = xfer_size; + + ret = dfu_download(dif->dev_handle, dif->interface, + chunk_size, transaction++, chunk_size ? buf : NULL); + if (ret < 0) { + warnx("Error during download"); + goto out; + } + bytes_sent += chunk_size; + buf += chunk_size; + + do { + ret = dfu_get_status(dif, &dst); + if (ret < 0) { + errx(EX_IOERR, "Error during download get_status"); + goto out; + } + + if (dst.bState == DFU_STATE_dfuDNLOAD_IDLE || + dst.bState == DFU_STATE_dfuERROR) + break; + + /* Wait while device executes flashing */ + milli_sleep(dst.bwPollTimeout); + + } while (1); + if (dst.bStatus != DFU_STATUS_OK) { + printf(" failed!\n"); + printf("state(%u) = %s, status(%u) = %s\n", dst.bState, + dfu_state_to_string(dst.bState), dst.bStatus, + dfu_status_to_string(dst.bStatus)); + ret = -1; + goto out; + } + dfu_progress_bar("Download", bytes_sent, bytes_sent + bytes_left); + } + + /* send one zero sized download request to signalize end */ + ret = dfu_download(dif->dev_handle, dif->interface, + 0, transaction, NULL); + if (ret < 0) { + errx(EX_IOERR, "Error sending completion packet"); + goto out; + } + + dfu_progress_bar("Download", bytes_sent, bytes_sent); + + if (verbose) + printf("Sent a total of %i bytes\n", bytes_sent); + +get_status: + /* Transition to MANIFEST_SYNC state */ + ret = dfu_get_status(dif, &dst); + if (ret < 0) { + warnx("unable to read DFU status after completion"); + goto out; + } + printf("state(%u) = %s, status(%u) = %s\n", dst.bState, + dfu_state_to_string(dst.bState), dst.bStatus, + dfu_status_to_string(dst.bStatus)); + + milli_sleep(dst.bwPollTimeout); + + /* FIXME: deal correctly with ManifestationTolerant=0 / WillDetach bits */ + switch (dst.bState) { + case DFU_STATE_dfuMANIFEST_SYNC: + case DFU_STATE_dfuMANIFEST: + /* some devices (e.g. TAS1020b) need some time before we + * can obtain the status */ + milli_sleep(1000); + goto get_status; + break; + case DFU_STATE_dfuIDLE: + break; + } + printf("Done!\n"); + +out: + return bytes_sent; +} diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfu_load.h b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfu_load.h new file mode 100644 index 0000000..be23e9b --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfu_load.h @@ -0,0 +1,7 @@ +#ifndef DFU_LOAD_H +#define DFU_LOAD_H + +int dfuload_do_upload(struct dfu_if *dif, int xfer_size, int expected_size, int fd); +int dfuload_do_dnload(struct dfu_if *dif, int xfer_size, struct dfu_file *file); + +#endif /* DFU_LOAD_H */ diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfu_util.c b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfu_util.c new file mode 100644 index 0000000..b94c7cc --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfu_util.c @@ -0,0 +1,346 @@ +/* + * Functions for detecting DFU USB entities + * + * Written by Harald Welte + * Copyright 2007-2008 by OpenMoko, Inc. + * Copyright 2013 Hans Petter Selasky + * + * Based on existing code of dfu-programmer-0.4 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include "portable.h" +#include "dfu.h" +#include "usb_dfu.h" +#include "dfu_file.h" +#include "dfu_load.h" +#include "dfu_util.h" +#include "dfuse.h" +#include "quirks.h" + +#ifdef HAVE_USBPATH_H +#include +#endif + +/* + * Look for a descriptor in a concatenated descriptor list. Will + * return upon the first match of the given descriptor type. Returns length of + * found descriptor, limited to res_size + */ +static int find_descriptor(const uint8_t *desc_list, int list_len, + uint8_t desc_type, void *res_buf, int res_size) +{ + int p = 0; + + if (list_len < 2) + return (-1); + + while (p + 1 < list_len) { + int desclen; + + desclen = (int) desc_list[p]; + if (desclen == 0) { + warnx("Invalid descriptor list"); + return -1; + } + if (desc_list[p + 1] == desc_type) { + if (desclen > res_size) + desclen = res_size; + if (p + desclen > list_len) + desclen = list_len - p; + memcpy(res_buf, &desc_list[p], desclen); + return desclen; + } + p += (int) desc_list[p]; + } + return -1; +} + +static void probe_configuration(libusb_device *dev, struct libusb_device_descriptor *desc) +{ + struct usb_dfu_func_descriptor func_dfu; + libusb_device_handle *devh; + struct dfu_if *pdfu; + struct libusb_config_descriptor *cfg; + const struct libusb_interface_descriptor *intf; + const struct libusb_interface *uif; + char alt_name[MAX_DESC_STR_LEN + 1]; + char serial_name[MAX_DESC_STR_LEN + 1]; + int cfg_idx; + int intf_idx; + int alt_idx; + int ret; + int has_dfu; + + for (cfg_idx = 0; cfg_idx != desc->bNumConfigurations; cfg_idx++) { + memset(&func_dfu, 0, sizeof(func_dfu)); + has_dfu = 0; + + ret = libusb_get_config_descriptor(dev, cfg_idx, &cfg); + if (ret != 0) + return; + if (match_config_index > -1 && match_config_index != cfg->bConfigurationValue) { + libusb_free_config_descriptor(cfg); + continue; + } + + /* + * In some cases, noticably FreeBSD if uid != 0, + * the configuration descriptors are empty + */ + if (!cfg) + return; + + ret = find_descriptor(cfg->extra, cfg->extra_length, + USB_DT_DFU, &func_dfu, sizeof(func_dfu)); + if (ret > -1) + goto found_dfu; + + for (intf_idx = 0; intf_idx < cfg->bNumInterfaces; + intf_idx++) { + uif = &cfg->interface[intf_idx]; + if (!uif) + break; + + for (alt_idx = 0; alt_idx < cfg->interface[intf_idx].num_altsetting; + alt_idx++) { + intf = &uif->altsetting[alt_idx]; + + ret = find_descriptor(intf->extra, intf->extra_length, USB_DT_DFU, + &func_dfu, sizeof(func_dfu)); + if (ret > -1) + goto found_dfu; + + if (intf->bInterfaceClass != 0xfe || + intf->bInterfaceSubClass != 1) + continue; + + has_dfu = 1; + } + } + if (has_dfu) { + /* + * Finally try to retrieve it requesting the + * device directly This is not supported on + * all devices for non-standard types + */ + if (libusb_open(dev, &devh) == 0) { + ret = libusb_get_descriptor(devh, USB_DT_DFU, 0, + (void *)&func_dfu, sizeof(func_dfu)); + libusb_close(devh); + if (ret > -1) + goto found_dfu; + } + warnx("Device has DFU interface, " + "but has no DFU functional descriptor"); + + /* fake version 1.0 */ + func_dfu.bLength = 7; + func_dfu.bcdDFUVersion = libusb_cpu_to_le16(0x0100); + goto found_dfu; + } + libusb_free_config_descriptor(cfg); + continue; + +found_dfu: + if (func_dfu.bLength == 7) { + printf("Deducing device DFU version from functional descriptor " + "length\n"); + func_dfu.bcdDFUVersion = libusb_cpu_to_le16(0x0100); + } else if (func_dfu.bLength < 9) { + printf("Error obtaining DFU functional descriptor\n"); + printf("Please report this as a bug!\n"); + printf("Warning: Assuming DFU version 1.0\n"); + func_dfu.bcdDFUVersion = libusb_cpu_to_le16(0x0100); + printf("Warning: Transfer size can not be detected\n"); + func_dfu.wTransferSize = 0; + } + + for (intf_idx = 0; intf_idx < cfg->bNumInterfaces; + intf_idx++) { + if (match_iface_index > -1 && match_iface_index != intf_idx) + continue; + + uif = &cfg->interface[intf_idx]; + if (!uif) + break; + + for (alt_idx = 0; + alt_idx < uif->num_altsetting; alt_idx++) { + int dfu_mode; + + intf = &uif->altsetting[alt_idx]; + + if (intf->bInterfaceClass != 0xfe || + intf->bInterfaceSubClass != 1) + continue; + + dfu_mode = (intf->bInterfaceProtocol == 2); + /* e.g. DSO Nano has bInterfaceProtocol 0 instead of 2 */ + if (func_dfu.bcdDFUVersion == 0x011a && intf->bInterfaceProtocol == 0) + dfu_mode = 1; + + if (dfu_mode && + match_iface_alt_index > -1 && match_iface_alt_index != alt_idx) + continue; + + if (dfu_mode) { + if ((match_vendor_dfu >= 0 && match_vendor_dfu != desc->idVendor) || + (match_product_dfu >= 0 && match_product_dfu != desc->idProduct)) { + continue; + } + } else { + if ((match_vendor >= 0 && match_vendor != desc->idVendor) || + (match_product >= 0 && match_product != desc->idProduct)) { + continue; + } + } + + if (libusb_open(dev, &devh)) { + warnx("Cannot open DFU device %04x:%04x", desc->idVendor, desc->idProduct); + break; + } + if (intf->iInterface != 0) + ret = libusb_get_string_descriptor_ascii(devh, + intf->iInterface, (void *)alt_name, MAX_DESC_STR_LEN); + else + ret = -1; + if (ret < 1) + strcpy(alt_name, "UNKNOWN"); + if (desc->iSerialNumber != 0) + ret = libusb_get_string_descriptor_ascii(devh, + desc->iSerialNumber, (void *)serial_name, MAX_DESC_STR_LEN); + else + ret = -1; + if (ret < 1) + strcpy(serial_name, "UNKNOWN"); + libusb_close(devh); + + if (dfu_mode && + match_iface_alt_name != NULL && strcmp(alt_name, match_iface_alt_name)) + continue; + + if (dfu_mode) { + if (match_serial_dfu != NULL && strcmp(match_serial_dfu, serial_name)) + continue; + } else { + if (match_serial != NULL && strcmp(match_serial, serial_name)) + continue; + } + + pdfu = dfu_malloc(sizeof(*pdfu)); + + memset(pdfu, 0, sizeof(*pdfu)); + + pdfu->func_dfu = func_dfu; + pdfu->dev = libusb_ref_device(dev); + pdfu->quirks = get_quirks(desc->idVendor, + desc->idProduct, desc->bcdDevice); + pdfu->vendor = desc->idVendor; + pdfu->product = desc->idProduct; + pdfu->bcdDevice = desc->bcdDevice; + pdfu->configuration = cfg->bConfigurationValue; + pdfu->interface = intf->bInterfaceNumber; + pdfu->altsetting = intf->bAlternateSetting; + pdfu->devnum = libusb_get_device_address(dev); + pdfu->busnum = libusb_get_bus_number(dev); + pdfu->alt_name = strdup(alt_name); + if (pdfu->alt_name == NULL) + errx(EX_SOFTWARE, "Out of memory"); + pdfu->serial_name = strdup(serial_name); + if (pdfu->serial_name == NULL) + errx(EX_SOFTWARE, "Out of memory"); + if (dfu_mode) + pdfu->flags |= DFU_IFF_DFU; + if (pdfu->quirks & QUIRK_FORCE_DFU11) { + pdfu->func_dfu.bcdDFUVersion = + libusb_cpu_to_le16(0x0110); + } + pdfu->bMaxPacketSize0 = desc->bMaxPacketSize0; + + /* queue into list */ + pdfu->next = dfu_root; + dfu_root = pdfu; + } + } + libusb_free_config_descriptor(cfg); + } +} + +void probe_devices(libusb_context *ctx) +{ + libusb_device **list; + ssize_t num_devs; + ssize_t i; + + num_devs = libusb_get_device_list(ctx, &list); + for (i = 0; i < num_devs; ++i) { + struct libusb_device_descriptor desc; + struct libusb_device *dev = list[i]; + + if (match_bus > -1 && match_bus != libusb_get_bus_number(dev)) + continue; + if (match_device > -1 && match_device != libusb_get_device_address(dev)) + continue; + if (libusb_get_device_descriptor(dev, &desc)) + continue; + probe_configuration(dev, &desc); + } + libusb_free_device_list(list, 0); +} + +void disconnect_devices(void) +{ + struct dfu_if *pdfu; + struct dfu_if *prev = NULL; + + for (pdfu = dfu_root; pdfu != NULL; pdfu = pdfu->next) { + free(prev); + libusb_unref_device(pdfu->dev); + free(pdfu->alt_name); + free(pdfu->serial_name); + prev = pdfu; + } + free(prev); + dfu_root = NULL; +} + +void print_dfu_if(struct dfu_if *dfu_if) +{ + printf("Found %s: [%04x:%04x] ver=%04x, devnum=%u, cfg=%u, intf=%u, " + "alt=%u, name=\"%s\", serial=\"%s\"\n", + dfu_if->flags & DFU_IFF_DFU ? "DFU" : "Runtime", + dfu_if->vendor, dfu_if->product, + dfu_if->bcdDevice, dfu_if->devnum, + dfu_if->configuration, dfu_if->interface, + dfu_if->altsetting, dfu_if->alt_name, + dfu_if->serial_name); +} + +/* Walk the device tree and print out DFU devices */ +void list_dfu_interfaces(void) +{ + struct dfu_if *pdfu; + + for (pdfu = dfu_root; pdfu != NULL; pdfu = pdfu->next) + print_dfu_if(pdfu); +} diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfu_util.h b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfu_util.h new file mode 100644 index 0000000..fc0c19d --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfu_util.h @@ -0,0 +1,36 @@ +#ifndef DFU_UTIL_H +#define DFU_UTIL_H + +/* USB string descriptor should contain max 126 UTF-16 characters + * but 253 would even accomodate any UTF-8 encoding */ +#define MAX_DESC_STR_LEN 253 + +enum mode { + MODE_NONE, + MODE_VERSION, + MODE_LIST, + MODE_DETACH, + MODE_UPLOAD, + MODE_DOWNLOAD +}; + +extern struct dfu_if *dfu_root; +extern int match_bus; +extern int match_device; +extern int match_vendor; +extern int match_product; +extern int match_vendor_dfu; +extern int match_product_dfu; +extern int match_config_index; +extern int match_iface_index; +extern int match_iface_alt_index; +extern const char *match_iface_alt_name; +extern const char *match_serial; +extern const char *match_serial_dfu; + +void probe_devices(libusb_context *); +void disconnect_devices(void); +void print_dfu_if(struct dfu_if *); +void list_dfu_interfaces(void); + +#endif /* DFU_UTIL_H */ diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfuse.c b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfuse.c new file mode 100644 index 0000000..fce29fe --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfuse.c @@ -0,0 +1,652 @@ +/* + * DfuSe specific functions + * + * This implements the ST Microsystems DFU extensions (DfuSe) + * as per the DfuSe 1.1a specification (ST documents AN3156, AN2606) + * The DfuSe file format is described in ST document UM0391. + * + * Copyright 2010-2014 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "portable.h" +#include "dfu.h" +#include "usb_dfu.h" +#include "dfu_file.h" +#include "dfuse.h" +#include "dfuse_mem.h" + +#define DFU_TIMEOUT 5000 + +extern int verbose; +static unsigned int last_erased_page = 1; /* non-aligned value, won't match */ +static struct memsegment *mem_layout; +static unsigned int dfuse_address = 0; +static unsigned int dfuse_length = 0; +static int dfuse_force = 0; +static int dfuse_leave = 0; +static int dfuse_unprotect = 0; +static int dfuse_mass_erase = 0; + +unsigned int quad2uint(unsigned char *p) +{ + return (*p + (*(p + 1) << 8) + (*(p + 2) << 16) + (*(p + 3) << 24)); +} + +void dfuse_parse_options(const char *options) +{ + char *end; + const char *endword; + unsigned int number; + + /* address, possibly empty, must be first */ + if (*options != ':') { + endword = strchr(options, ':'); + if (!endword) + endword = options + strlen(options); /* GNU strchrnul */ + + number = strtoul(options, &end, 0); + if (end == endword) { + dfuse_address = number; + } else { + errx(EX_IOERR, "Invalid dfuse address: %s", options); + } + options = endword; + } + + while (*options) { + if (*options == ':') { + options++; + continue; + } + endword = strchr(options, ':'); + if (!endword) + endword = options + strlen(options); + + if (!strncmp(options, "force", endword - options)) { + dfuse_force++; + options += 5; + continue; + } + if (!strncmp(options, "leave", endword - options)) { + dfuse_leave = 1; + options += 5; + continue; + } + if (!strncmp(options, "unprotect", endword - options)) { + dfuse_unprotect = 1; + options += 9; + continue; + } + if (!strncmp(options, "mass-erase", endword - options)) { + dfuse_mass_erase = 1; + options += 10; + continue; + } + + /* any valid number is interpreted as upload length */ + number = strtoul(options, &end, 0); + if (end == endword) { + dfuse_length = number; + } else { + errx(EX_IOERR, "Invalid dfuse modifier: %s", options); + } + options = endword; + } +} + +/* DFU_UPLOAD request for DfuSe 1.1a */ +int dfuse_upload(struct dfu_if *dif, const unsigned short length, + unsigned char *data, unsigned short transaction) +{ + int status; + + status = libusb_control_transfer(dif->dev_handle, + /* bmRequestType */ LIBUSB_ENDPOINT_IN | + LIBUSB_REQUEST_TYPE_CLASS | + LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_UPLOAD, + /* wValue */ transaction, + /* wIndex */ dif->interface, + /* Data */ data, + /* wLength */ length, + DFU_TIMEOUT); + if (status < 0) { + errx(EX_IOERR, "%s: libusb_control_msg returned %d", + __FUNCTION__, status); + } + return status; +} + +/* DFU_DNLOAD request for DfuSe 1.1a */ +int dfuse_download(struct dfu_if *dif, const unsigned short length, + unsigned char *data, unsigned short transaction) +{ + int status; + + status = libusb_control_transfer(dif->dev_handle, + /* bmRequestType */ LIBUSB_ENDPOINT_OUT | + LIBUSB_REQUEST_TYPE_CLASS | + LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_DNLOAD, + /* wValue */ transaction, + /* wIndex */ dif->interface, + /* Data */ data, + /* wLength */ length, + DFU_TIMEOUT); + if (status < 0) { + errx(EX_IOERR, "%s: libusb_control_transfer returned %d", + __FUNCTION__, status); + } + return status; +} + +/* DfuSe only commands */ +/* Leaves the device in dfuDNLOAD-IDLE state */ +int dfuse_special_command(struct dfu_if *dif, unsigned int address, + enum dfuse_command command) +{ + const char* dfuse_command_name[] = { "SET_ADDRESS" , "ERASE_PAGE", + "MASS_ERASE", "READ_UNPROTECT"}; + unsigned char buf[5]; + int length; + int ret; + struct dfu_status dst; + int firstpoll = 1; + + if (command == ERASE_PAGE) { + struct memsegment *segment; + int page_size; + + segment = find_segment(mem_layout, address); + if (!segment || !(segment->memtype & DFUSE_ERASABLE)) { + errx(EX_IOERR, "Page at 0x%08x can not be erased", + address); + } + page_size = segment->pagesize; + if (verbose > 1) + printf("Erasing page size %i at address 0x%08x, page " + "starting at 0x%08x\n", page_size, address, + address & ~(page_size - 1)); + buf[0] = 0x41; /* Erase command */ + length = 5; + last_erased_page = address & ~(page_size - 1); + } else if (command == SET_ADDRESS) { + if (verbose > 2) + printf(" Setting address pointer to 0x%08x\n", + address); + buf[0] = 0x21; /* Set Address Pointer command */ + length = 5; + } else if (command == MASS_ERASE) { + buf[0] = 0x41; /* Mass erase command when length = 1 */ + length = 1; + } else if (command == READ_UNPROTECT) { + buf[0] = 0x92; + length = 1; + } else { + errx(EX_IOERR, "Non-supported special command %d", command); + } + buf[1] = address & 0xff; + buf[2] = (address >> 8) & 0xff; + buf[3] = (address >> 16) & 0xff; + buf[4] = (address >> 24) & 0xff; + + ret = dfuse_download(dif, length, buf, 0); + if (ret < 0) { + errx(EX_IOERR, "Error during special command \"%s\" download", + dfuse_command_name[command]); + } + do { + ret = dfu_get_status(dif, &dst); + if (ret < 0) { + errx(EX_IOERR, "Error during special command \"%s\" get_status", + dfuse_command_name[command]); + } + if (firstpoll) { + firstpoll = 0; + if (dst.bState != DFU_STATE_dfuDNBUSY) { + printf("state(%u) = %s, status(%u) = %s\n", dst.bState, + dfu_state_to_string(dst.bState), dst.bStatus, + dfu_status_to_string(dst.bStatus)); + errx(EX_IOERR, "Wrong state after command \"%s\" download", + dfuse_command_name[command]); + } + } + /* wait while command is executed */ + if (verbose) + printf(" Poll timeout %i ms\n", dst.bwPollTimeout); + milli_sleep(dst.bwPollTimeout); + if (command == READ_UNPROTECT) + return ret; + } while (dst.bState == DFU_STATE_dfuDNBUSY); + + if (dst.bStatus != DFU_STATUS_OK) { + errx(EX_IOERR, "%s not correctly executed", + dfuse_command_name[command]); + } + return ret; +} + +int dfuse_dnload_chunk(struct dfu_if *dif, unsigned char *data, int size, + int transaction) +{ + int bytes_sent; + struct dfu_status dst; + int ret; + + ret = dfuse_download(dif, size, size ? data : NULL, transaction); + if (ret < 0) { + errx(EX_IOERR, "Error during download"); + return ret; + } + bytes_sent = ret; + + do { + ret = dfu_get_status(dif, &dst); + if (ret < 0) { + errx(EX_IOERR, "Error during download get_status"); + return ret; + } + milli_sleep(dst.bwPollTimeout); + } while (dst.bState != DFU_STATE_dfuDNLOAD_IDLE && + dst.bState != DFU_STATE_dfuERROR && + dst.bState != DFU_STATE_dfuMANIFEST); + + if (dst.bState == DFU_STATE_dfuMANIFEST) + printf("Transitioning to dfuMANIFEST state\n"); + + if (dst.bStatus != DFU_STATUS_OK) { + printf(" failed!\n"); + printf("state(%u) = %s, status(%u) = %s\n", dst.bState, + dfu_state_to_string(dst.bState), dst.bStatus, + dfu_status_to_string(dst.bStatus)); + return -1; + } + return bytes_sent; +} + +int dfuse_do_upload(struct dfu_if *dif, int xfer_size, int fd, + const char *dfuse_options) +{ + int total_bytes = 0; + int upload_limit = 0; + unsigned char *buf; + int transaction; + int ret; + + buf = dfu_malloc(xfer_size); + + if (dfuse_options) + dfuse_parse_options(dfuse_options); + if (dfuse_length) + upload_limit = dfuse_length; + if (dfuse_address) { + struct memsegment *segment; + + mem_layout = parse_memory_layout((char *)dif->alt_name); + if (!mem_layout) + errx(EX_IOERR, "Failed to parse memory layout"); + + segment = find_segment(mem_layout, dfuse_address); + if (!dfuse_force && + (!segment || !(segment->memtype & DFUSE_READABLE))) + errx(EX_IOERR, "Page at 0x%08x is not readable", + dfuse_address); + + if (!upload_limit) { + upload_limit = segment->end - dfuse_address + 1; + printf("Limiting upload to end of memory segment, " + "%i bytes\n", upload_limit); + } + dfuse_special_command(dif, dfuse_address, SET_ADDRESS); + dfu_abort_to_idle(dif); + } else { + /* Boot loader decides the start address, unknown to us */ + /* Use a short length to lower risk of running out of bounds */ + if (!upload_limit) + upload_limit = 0x4000; + printf("Limiting default upload to %i bytes\n", upload_limit); + } + + dfu_progress_bar("Upload", 0, 1); + + transaction = 2; + while (1) { + int rc; + + /* last chunk can be smaller than original xfer_size */ + if (upload_limit - total_bytes < xfer_size) + xfer_size = upload_limit - total_bytes; + rc = dfuse_upload(dif, xfer_size, buf, transaction++); + if (rc < 0) { + ret = rc; + goto out_free; + } + + dfu_file_write_crc(fd, 0, buf, rc); + total_bytes += rc; + + if (total_bytes < 0) + errx(EX_SOFTWARE, "Received too many bytes"); + + if (rc < xfer_size || total_bytes >= upload_limit) { + /* last block, return successfully */ + ret = total_bytes; + break; + } + dfu_progress_bar("Upload", total_bytes, upload_limit); + } + + dfu_progress_bar("Upload", total_bytes, total_bytes); + + dfu_abort_to_idle(dif); + if (dfuse_leave) { + dfuse_special_command(dif, dfuse_address, SET_ADDRESS); + dfuse_dnload_chunk(dif, NULL, 0, 2); /* Zero-size */ + } + + out_free: + free(buf); + + return ret; +} + +/* Writes an element of any size to the device, taking care of page erases */ +/* returns 0 on success, otherwise -EINVAL */ +int dfuse_dnload_element(struct dfu_if *dif, unsigned int dwElementAddress, + unsigned int dwElementSize, unsigned char *data, + int xfer_size) +{ + int p; + int ret; + struct memsegment *segment; + + /* Check at least that we can write to the last address */ + segment = + find_segment(mem_layout, dwElementAddress + dwElementSize - 1); + if (!segment || !(segment->memtype & DFUSE_WRITEABLE)) { + errx(EX_IOERR, "Last page at 0x%08x is not writeable", + dwElementAddress + dwElementSize - 1); + } + + dfu_progress_bar("Download", 0, 1); + + for (p = 0; p < (int)dwElementSize; p += xfer_size) { + int page_size; + unsigned int erase_address; + unsigned int address = dwElementAddress + p; + int chunk_size = xfer_size; + + segment = find_segment(mem_layout, address); + if (!segment || !(segment->memtype & DFUSE_WRITEABLE)) { + errx(EX_IOERR, "Page at 0x%08x is not writeable", + address); + } + page_size = segment->pagesize; + + /* check if this is the last chunk */ + if (p + chunk_size > (int)dwElementSize) + chunk_size = dwElementSize - p; + + /* Erase only for flash memory downloads */ + if ((segment->memtype & DFUSE_ERASABLE) && !dfuse_mass_erase) { + /* erase all involved pages */ + for (erase_address = address; + erase_address < address + chunk_size; + erase_address += page_size) + if ((erase_address & ~(page_size - 1)) != + last_erased_page) + dfuse_special_command(dif, + erase_address, + ERASE_PAGE); + + if (((address + chunk_size - 1) & ~(page_size - 1)) != + last_erased_page) { + if (verbose > 2) + printf(" Chunk extends into next page," + " erase it as well\n"); + dfuse_special_command(dif, + address + chunk_size - 1, + ERASE_PAGE); + } + } + + if (verbose) { + printf(" Download from image offset " + "%08x to memory %08x-%08x, size %i\n", + p, address, address + chunk_size - 1, + chunk_size); + } else { + dfu_progress_bar("Download", p, dwElementSize); + } + + dfuse_special_command(dif, address, SET_ADDRESS); + + /* transaction = 2 for no address offset */ + ret = dfuse_dnload_chunk(dif, data + p, chunk_size, 2); + if (ret != chunk_size) { + errx(EX_IOERR, "Failed to write whole chunk: " + "%i of %i bytes", ret, chunk_size); + return -EINVAL; + } + } + if (!verbose) + dfu_progress_bar("Download", dwElementSize, dwElementSize); + return 0; +} + +static void +dfuse_memcpy(unsigned char *dst, unsigned char **src, int *rem, int size) +{ + if (size > *rem) { + errx(EX_IOERR, "Corrupt DfuSe file: " + "Cannot read %d bytes from %d bytes", size, *rem); + } + if (dst != NULL) + memcpy(dst, *src, size); + (*src) += size; + (*rem) -= size; +} + +/* Download raw binary file to DfuSe device */ +int dfuse_do_bin_dnload(struct dfu_if *dif, int xfer_size, + struct dfu_file *file, unsigned int start_address) +{ + unsigned int dwElementAddress; + unsigned int dwElementSize; + unsigned char *data; + int ret; + + dwElementAddress = start_address; + dwElementSize = file->size.total - + file->size.suffix - file->size.prefix; + + printf("Downloading to address = 0x%08x, size = %i\n", + dwElementAddress, dwElementSize); + + data = file->firmware + file->size.prefix; + + ret = dfuse_dnload_element(dif, dwElementAddress, dwElementSize, data, + xfer_size); + if (ret != 0) + goto out_free; + + printf("File downloaded successfully\n"); + ret = dwElementSize; + + out_free: + return ret; +} + +/* Parse a DfuSe file and download contents to device */ +int dfuse_do_dfuse_dnload(struct dfu_if *dif, int xfer_size, + struct dfu_file *file) +{ + uint8_t dfuprefix[11]; + uint8_t targetprefix[274]; + uint8_t elementheader[8]; + int image; + int element; + int bTargets; + int bAlternateSetting; + int dwNbElements; + unsigned int dwElementAddress; + unsigned int dwElementSize; + uint8_t *data; + int ret; + int rem; + int bFirstAddressSaved = 0; + + rem = file->size.total - file->size.prefix - file->size.suffix; + data = file->firmware + file->size.prefix; + + /* Must be larger than a minimal DfuSe header and suffix */ + if (rem < (int)(sizeof(dfuprefix) + + sizeof(targetprefix) + sizeof(elementheader))) { + errx(EX_SOFTWARE, "File too small for a DfuSe file"); + } + + dfuse_memcpy(dfuprefix, &data, &rem, sizeof(dfuprefix)); + + if (strncmp((char *)dfuprefix, "DfuSe", 5)) { + errx(EX_IOERR, "No valid DfuSe signature"); + return -EINVAL; + } + if (dfuprefix[5] != 0x01) { + errx(EX_IOERR, "DFU format revision %i not supported", + dfuprefix[5]); + return -EINVAL; + } + bTargets = dfuprefix[10]; + printf("file contains %i DFU images\n", bTargets); + + for (image = 1; image <= bTargets; image++) { + printf("parsing DFU image %i\n", image); + dfuse_memcpy(targetprefix, &data, &rem, sizeof(targetprefix)); + if (strncmp((char *)targetprefix, "Target", 6)) { + errx(EX_IOERR, "No valid target signature"); + return -EINVAL; + } + bAlternateSetting = targetprefix[6]; + dwNbElements = quad2uint((unsigned char *)targetprefix + 270); + printf("image for alternate setting %i, ", bAlternateSetting); + printf("(%i elements, ", dwNbElements); + printf("total size = %i)\n", + quad2uint((unsigned char *)targetprefix + 266)); + if (bAlternateSetting != dif->altsetting) + printf("Warning: Image does not match current alternate" + " setting.\n" + "Please rerun with the correct -a option setting" + " to download this image!\n"); + for (element = 1; element <= dwNbElements; element++) { + printf("parsing element %i, ", element); + dfuse_memcpy(elementheader, &data, &rem, sizeof(elementheader)); + dwElementAddress = + quad2uint((unsigned char *)elementheader); + dwElementSize = + quad2uint((unsigned char *)elementheader + 4); + printf("address = 0x%08x, ", dwElementAddress); + printf("size = %i\n", dwElementSize); + + if (!bFirstAddressSaved) { + bFirstAddressSaved = 1; + dfuse_address = dwElementAddress; + } + /* sanity check */ + if ((int)dwElementSize > rem) + errx(EX_SOFTWARE, "File too small for element size"); + + if (bAlternateSetting == dif->altsetting) { + ret = dfuse_dnload_element(dif, dwElementAddress, + dwElementSize, data, xfer_size); + } else { + ret = 0; + } + + /* advance read pointer */ + dfuse_memcpy(NULL, &data, &rem, dwElementSize); + + if (ret != 0) + return ret; + } + } + + if (rem != 0) + warnx("%d bytes leftover", rem); + + printf("done parsing DfuSe file\n"); + + return 0; +} + +int dfuse_do_dnload(struct dfu_if *dif, int xfer_size, struct dfu_file *file, + const char *dfuse_options) +{ + int ret; + + if (dfuse_options) + dfuse_parse_options(dfuse_options); + mem_layout = parse_memory_layout((char *)dif->alt_name); + if (!mem_layout) { + errx(EX_IOERR, "Failed to parse memory layout"); + } + if (dfuse_unprotect) { + if (!dfuse_force) { + errx(EX_IOERR, "The read unprotect command " + "will erase the flash memory" + "and can only be used with force\n"); + } + dfuse_special_command(dif, 0, READ_UNPROTECT); + printf("Device disconnects, erases flash and resets now\n"); + exit(0); + } + if (dfuse_mass_erase) { + if (!dfuse_force) { + errx(EX_IOERR, "The mass erase command " + "can only be used with force"); + } + printf("Performing mass erase, this can take a moment\n"); + dfuse_special_command(dif, 0, MASS_ERASE); + } + if (dfuse_address) { + if (file->bcdDFU == 0x11a) { + errx(EX_IOERR, "This is a DfuSe file, not " + "meant for raw download"); + } + ret = dfuse_do_bin_dnload(dif, xfer_size, file, dfuse_address); + } else { + if (file->bcdDFU != 0x11a) { + warnx("Only DfuSe file version 1.1a is supported"); + errx(EX_IOERR, "(for raw binary download, use the " + "--dfuse-address option)"); + } + ret = dfuse_do_dfuse_dnload(dif, xfer_size, file); + } + free_segment_list(mem_layout); + + dfu_abort_to_idle(dif); + + if (dfuse_leave) { + dfuse_special_command(dif, dfuse_address, SET_ADDRESS); + dfuse_dnload_chunk(dif, NULL, 0, 2); /* Zero-size */ + } + return ret; +} diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfuse.h b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfuse.h new file mode 100644 index 0000000..ed1108c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfuse.h @@ -0,0 +1,35 @@ +/* This implements the ST Microsystems DFU extensions (DfuSe) + * as per the DfuSe 1.1a specification (Document UM0391) + * + * (C) 2010-2012 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DFUSE_H +#define DFUSE_H + +#include "dfu.h" + +enum dfuse_command { SET_ADDRESS, ERASE_PAGE, MASS_ERASE, READ_UNPROTECT }; + +int dfuse_special_command(struct dfu_if *dif, unsigned int address, + enum dfuse_command command); +int dfuse_do_upload(struct dfu_if *dif, int xfer_size, int fd, + const char *dfuse_options); +int dfuse_do_dnload(struct dfu_if *dif, int xfer_size, struct dfu_file *file, + const char *dfuse_options); + +#endif /* DFUSE_H */ diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfuse_mem.c b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfuse_mem.c new file mode 100644 index 0000000..a91aacf --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfuse_mem.c @@ -0,0 +1,198 @@ +/* + * Helper functions for reading the memory map of a device + * following the ST DfuSe 1.1a specification. + * + * Copyright 2011-2014 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "portable.h" +#include "dfu_file.h" +#include "dfuse_mem.h" + +int add_segment(struct memsegment **segment_list, struct memsegment segment) +{ + struct memsegment *new_element; + + new_element = dfu_malloc(sizeof(struct memsegment)); + *new_element = segment; + new_element->next = NULL; + + if (*segment_list == NULL) + /* list can be empty on first call */ + *segment_list = new_element; + else { + struct memsegment *next_element; + + /* find last element in list */ + next_element = *segment_list; + while (next_element->next != NULL) + next_element = next_element->next; + next_element->next = new_element; + } + return 0; +} + +struct memsegment *find_segment(struct memsegment *segment_list, + unsigned int address) +{ + while (segment_list != NULL) { + if (segment_list->start <= address && + segment_list->end >= address) + return segment_list; + segment_list = segment_list->next; + } + return NULL; +} + +void free_segment_list(struct memsegment *segment_list) +{ + struct memsegment *next_element; + + while (segment_list->next != NULL) { + next_element = segment_list->next; + free(segment_list); + segment_list = next_element; + } + free(segment_list); +} + +/* Parse memory map from interface descriptor string + * encoded as per ST document UM0424 section 4.3.2. + */ +struct memsegment *parse_memory_layout(char *intf_desc) +{ + + char multiplier, memtype; + unsigned int address; + int sectors, size; + char *name, *typestring; + int ret; + int count = 0; + char separator; + int scanned; + struct memsegment *segment_list = NULL; + struct memsegment segment; + + name = dfu_malloc(strlen(intf_desc)); + + ret = sscanf(intf_desc, "@%[^/]%n", name, &scanned); + if (ret < 1) { + free(name); + warnx("Could not read name, sscanf returned %d", ret); + return NULL; + } + printf("DfuSe interface name: \"%s\"\n", name); + + intf_desc += scanned; + typestring = dfu_malloc(strlen(intf_desc)); + + while (ret = sscanf(intf_desc, "/0x%x/%n", &address, &scanned), + ret > 0) { + + intf_desc += scanned; + while (ret = sscanf(intf_desc, "%d*%d%c%[^,/]%n", + §ors, &size, &multiplier, typestring, + &scanned), ret > 2) { + intf_desc += scanned; + + count++; + memtype = 0; + if (ret == 4) { + if (strlen(typestring) == 1 + && typestring[0] != '/') + memtype = typestring[0]; + else { + warnx("Parsing type identifier '%s' " + "failed for segment %i", + typestring, count); + continue; + } + } + + /* Quirk for STM32F4 devices */ + if (strcmp(name, "Device Feature") == 0) + memtype = 'e'; + + switch (multiplier) { + case 'B': + break; + case 'K': + size *= 1024; + break; + case 'M': + size *= 1024 * 1024; + break; + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + if (!memtype) { + warnx("Non-valid multiplier '%c', " + "interpreted as type " + "identifier instead", + multiplier); + memtype = multiplier; + break; + } + /* fallthrough if memtype was already set */ + default: + warnx("Non-valid multiplier '%c', " + "assuming bytes", multiplier); + } + + if (!memtype) { + warnx("No valid type for segment %d\n", count); + continue; + } + + segment.start = address; + segment.end = address + sectors * size - 1; + segment.pagesize = size; + segment.memtype = memtype & 7; + add_segment(&segment_list, segment); + + if (verbose) + printf("Memory segment at 0x%08x %3d x %4d = " + "%5d (%s%s%s)\n", + address, sectors, size, sectors * size, + memtype & DFUSE_READABLE ? "r" : "", + memtype & DFUSE_ERASABLE ? "e" : "", + memtype & DFUSE_WRITEABLE ? "w" : ""); + + address += sectors * size; + + separator = *intf_desc; + if (separator == ',') + intf_desc += 1; + else + break; + } /* while per segment */ + + } /* while per address */ + free(name); + free(typestring); + + return segment_list; +} diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfuse_mem.h b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfuse_mem.h new file mode 100644 index 0000000..0181f0c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/dfuse_mem.h @@ -0,0 +1,44 @@ +/* Helper functions for reading the memory map in a device + * following the ST DfuSe 1.1a specification. + * + * (C) 2011 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DFUSE_MEM_H +#define DFUSE_MEM_H + +#define DFUSE_READABLE 1 +#define DFUSE_ERASABLE 2 +#define DFUSE_WRITEABLE 4 + +struct memsegment { + unsigned int start; + unsigned int end; + int pagesize; + int memtype; + struct memsegment *next; +}; + +int add_segment(struct memsegment **list, struct memsegment new_element); + +struct memsegment *find_segment(struct memsegment *list, unsigned int address); + +void free_segment_list(struct memsegment *list); + +struct memsegment *parse_memory_layout(char *intf_desc_str); + +#endif /* DFUSE_MEM_H */ diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/main.c b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/main.c new file mode 100644 index 0000000..acaed2f --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/main.c @@ -0,0 +1,699 @@ +/* + * dfu-util + * + * Copyright 2007-2008 by OpenMoko, Inc. + * Copyright 2013-2014 Hans Petter Selasky + * + * Written by Harald Welte + * + * Based on existing code of dfu-programmer-0.4 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "portable.h" +#include "dfu.h" +#include "usb_dfu.h" +#include "dfu_file.h" +#include "dfu_load.h" +#include "dfu_util.h" +#include "dfuse.h" +#include "quirks.h" + +#ifdef HAVE_USBPATH_H +#include +#endif + +int verbose = 0; + +struct dfu_if *dfu_root = NULL; + +int match_bus = -1; +int match_device = -1; +int match_vendor = -1; +int match_product = -1; +int match_vendor_dfu = -1; +int match_product_dfu = -1; +int match_config_index = -1; +int match_iface_index = -1; +int match_iface_alt_index = -1; +const char *match_iface_alt_name = NULL; +const char *match_serial = NULL; +const char *match_serial_dfu = NULL; + +static int parse_match_value(const char *str, int default_value) +{ + char *remainder; + int value; + + if (str == NULL) { + value = default_value; + } else if (*str == '*') { + value = -1; /* Match anything */ + } else if (*str == '-') { + value = 0x10000; /* Impossible vendor/product ID */ + } else { + value = strtoul(str, &remainder, 16); + if (remainder == str) { + value = default_value; + } + } + return value; +} + +static void parse_vendprod(const char *str) +{ + const char *comma; + const char *colon; + + /* Default to match any DFU device in runtime or DFU mode */ + match_vendor = -1; + match_product = -1; + match_vendor_dfu = -1; + match_product_dfu = -1; + + comma = strchr(str, ','); + if (comma == str) { + /* DFU mode vendor/product being specified without any runtime + * vendor/product specification, so don't match any runtime device */ + match_vendor = match_product = 0x10000; + } else { + colon = strchr(str, ':'); + if (colon != NULL) { + ++colon; + if ((comma != NULL) && (colon > comma)) { + colon = NULL; + } + } + match_vendor = parse_match_value(str, match_vendor); + match_product = parse_match_value(colon, match_product); + if (comma != NULL) { + /* Both runtime and DFU mode vendor/product specifications are + * available, so default DFU mode match components to the given + * runtime match components */ + match_vendor_dfu = match_vendor; + match_product_dfu = match_product; + } + } + if (comma != NULL) { + ++comma; + colon = strchr(comma, ':'); + if (colon != NULL) { + ++colon; + } + match_vendor_dfu = parse_match_value(comma, match_vendor_dfu); + match_product_dfu = parse_match_value(colon, match_product_dfu); + } +} + +static void parse_serial(char *str) +{ + char *comma; + + match_serial = str; + comma = strchr(str, ','); + if (comma == NULL) { + match_serial_dfu = match_serial; + } else { + *comma++ = 0; + match_serial_dfu = comma; + } + if (*match_serial == 0) match_serial = NULL; + if (*match_serial_dfu == 0) match_serial_dfu = NULL; +} + +#ifdef HAVE_USBPATH_H + +static int resolve_device_path(char *path) +{ + int res; + + res = usb_path2devnum(path); + if (res < 0) + return -EINVAL; + if (!res) + return 0; + + match_bus = atoi(path); + match_device = res; + + return 0; +} + +#else /* HAVE_USBPATH_H */ + +static int resolve_device_path(char *path) +{ + (void)path; /* Eliminate unused variable warning */ + errx(EX_SOFTWARE, "USB device paths are not supported by this dfu-util.\n"); +} + +#endif /* !HAVE_USBPATH_H */ + +static void help(void) +{ + fprintf(stderr, "Usage: dfu-util [options] ...\n" + " -h --help\t\t\tPrint this help message\n" + " -V --version\t\t\tPrint the version number\n" + " -v --verbose\t\t\tPrint verbose debug statements\n" + " -l --list\t\t\tList currently attached DFU capable devices\n"); + fprintf(stderr, " -e --detach\t\t\tDetach currently attached DFU capable devices\n" + " -E --detach-delay seconds\tTime to wait before reopening a device after detach\n" + " -d --device :[,:]\n" + "\t\t\t\tSpecify Vendor/Product ID(s) of DFU device\n" + " -p --path \tSpecify path to DFU device\n" + " -c --cfg \t\tSpecify the Configuration of DFU device\n" + " -i --intf \t\tSpecify the DFU Interface number\n" + " -S --serial [,]\n" + "\t\t\t\tSpecify Serial String of DFU device\n" + " -a --alt \t\tSpecify the Altsetting of the DFU Interface\n" + "\t\t\t\tby name or by number\n"); + fprintf(stderr, " -t --transfer-size \tSpecify the number of bytes per USB Transfer\n" + " -U --upload \t\tRead firmware from device into \n" + " -Z --upload-size \tSpecify the expected upload size in bytes\n" + " -D --download \t\tWrite firmware from into device\n" + " -R --reset\t\t\tIssue USB Reset signalling once we're finished\n" + " -s --dfuse-address

\tST DfuSe mode, specify target address for\n" + "\t\t\t\traw file download or upload. Not applicable for\n" + "\t\t\t\tDfuSe file (.dfu) downloads\n" + ); + exit(EX_USAGE); +} + +static void print_version(void) +{ + printf(PACKAGE_STRING "\n\n"); + printf("Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.\n" + "Copyright 2010-2014 Tormod Volden and Stefan Schmidt\n" + "This program is Free Software and has ABSOLUTELY NO WARRANTY\n" + "Please report bugs to " PACKAGE_BUGREPORT "\n\n"); +} + +static struct option opts[] = { + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'V' }, + { "verbose", 0, 0, 'v' }, + { "list", 0, 0, 'l' }, + { "detach", 0, 0, 'e' }, + { "detach-delay", 1, 0, 'E' }, + { "device", 1, 0, 'd' }, + { "path", 1, 0, 'p' }, + { "configuration", 1, 0, 'c' }, + { "cfg", 1, 0, 'c' }, + { "interface", 1, 0, 'i' }, + { "intf", 1, 0, 'i' }, + { "altsetting", 1, 0, 'a' }, + { "alt", 1, 0, 'a' }, + { "serial", 1, 0, 'S' }, + { "transfer-size", 1, 0, 't' }, + { "upload", 1, 0, 'U' }, + { "upload-size", 1, 0, 'Z' }, + { "download", 1, 0, 'D' }, + { "reset", 0, 0, 'R' }, + { "dfuse-address", 1, 0, 's' }, + { 0, 0, 0, 0 } +}; + +int main(int argc, char **argv) +{ + int expected_size = 0; + unsigned int transfer_size = 0; + enum mode mode = MODE_NONE; + struct dfu_status status; + libusb_context *ctx; + struct dfu_file file; + char *end; + int final_reset = 0; + int ret; + int dfuse_device = 0; + int fd; + const char *dfuse_options = NULL; + int detach_delay = 5; + uint16_t runtime_vendor; + uint16_t runtime_product; + + memset(&file, 0, sizeof(file)); + + /* make sure all prints are flushed */ + setvbuf(stdout, NULL, _IONBF, 0); + + while (1) { + int c, option_index = 0; + c = getopt_long(argc, argv, "hVvleE:d:p:c:i:a:S:t:U:D:Rs:Z:", opts, + &option_index); + if (c == -1) + break; + + switch (c) { + case 'h': + help(); + break; + case 'V': + mode = MODE_VERSION; + break; + case 'v': + verbose++; + break; + case 'l': + mode = MODE_LIST; + break; + case 'e': + mode = MODE_DETACH; + match_iface_alt_index = 0; + match_iface_index = 0; + break; + case 'E': + detach_delay = atoi(optarg); + break; + case 'd': + parse_vendprod(optarg); + break; + case 'p': + /* Parse device path */ + ret = resolve_device_path(optarg); + if (ret < 0) + errx(EX_SOFTWARE, "Unable to parse '%s'", optarg); + if (!ret) + errx(EX_SOFTWARE, "Cannot find '%s'", optarg); + break; + case 'c': + /* Configuration */ + match_config_index = atoi(optarg); + break; + case 'i': + /* Interface */ + match_iface_index = atoi(optarg); + break; + case 'a': + /* Interface Alternate Setting */ + match_iface_alt_index = strtoul(optarg, &end, 0); + if (*end) { + match_iface_alt_name = optarg; + match_iface_alt_index = -1; + } + break; + case 'S': + parse_serial(optarg); + break; + case 't': + transfer_size = atoi(optarg); + break; + case 'U': + mode = MODE_UPLOAD; + file.name = optarg; + break; + case 'Z': + expected_size = atoi(optarg); + break; + case 'D': + mode = MODE_DOWNLOAD; + file.name = optarg; + break; + case 'R': + final_reset = 1; + break; + case 's': + dfuse_options = optarg; + break; + default: + help(); + break; + } + } + + print_version(); + if (mode == MODE_VERSION) { + exit(0); + } + + if (mode == MODE_NONE) { + fprintf(stderr, "You need to specify one of -D or -U\n"); + help(); + } + + if (match_config_index == 0) { + /* Handle "-c 0" (unconfigured device) as don't care */ + match_config_index = -1; + } + + if (mode == MODE_DOWNLOAD) { + dfu_load_file(&file, MAYBE_SUFFIX, MAYBE_PREFIX); + /* If the user didn't specify product and/or vendor IDs to match, + * use any IDs from the file suffix for device matching */ + if (match_vendor < 0 && file.idVendor != 0xffff) { + match_vendor = file.idVendor; + printf("Match vendor ID from file: %04x\n", match_vendor); + } + if (match_product < 0 && file.idProduct != 0xffff) { + match_product = file.idProduct; + printf("Match product ID from file: %04x\n", match_product); + } + } + + ret = libusb_init(&ctx); + if (ret) + errx(EX_IOERR, "unable to initialize libusb: %i", ret); + + if (verbose > 2) { + libusb_set_debug(ctx, 255); + } + + probe_devices(ctx); + + if (mode == MODE_LIST) { + list_dfu_interfaces(); + exit(0); + } + + if (dfu_root == NULL) { + errx(EX_IOERR, "No DFU capable USB device available"); + } else if (dfu_root->next != NULL) { + /* We cannot safely support more than one DFU capable device + * with same vendor/product ID, since during DFU we need to do + * a USB bus reset, after which the target device will get a + * new address */ + errx(EX_IOERR, "More than one DFU capable USB device found! " + "Try `--list' and specify the serial number " + "or disconnect all but one device\n"); + } + + /* We have exactly one device. Its libusb_device is now in dfu_root->dev */ + + printf("Opening DFU capable USB device...\n"); + ret = libusb_open(dfu_root->dev, &dfu_root->dev_handle); + if (ret || !dfu_root->dev_handle) + errx(EX_IOERR, "Cannot open device"); + + printf("ID %04x:%04x\n", dfu_root->vendor, dfu_root->product); + + printf("Run-time device DFU version %04x\n", + libusb_le16_to_cpu(dfu_root->func_dfu.bcdDFUVersion)); + + /* Transition from run-Time mode to DFU mode */ + if (!(dfu_root->flags & DFU_IFF_DFU)) { + int err; + /* In the 'first round' during runtime mode, there can only be one + * DFU Interface descriptor according to the DFU Spec. */ + + /* FIXME: check if the selected device really has only one */ + + runtime_vendor = dfu_root->vendor; + runtime_product = dfu_root->product; + + printf("Claiming USB DFU Runtime Interface...\n"); + if (libusb_claim_interface(dfu_root->dev_handle, dfu_root->interface) < 0) { + errx(EX_IOERR, "Cannot claim interface %d", + dfu_root->interface); + } + + if (libusb_set_interface_alt_setting(dfu_root->dev_handle, dfu_root->interface, 0) < 0) { + errx(EX_IOERR, "Cannot set alt interface zero"); + } + + printf("Determining device status: "); + + err = dfu_get_status(dfu_root, &status); + if (err == LIBUSB_ERROR_PIPE) { + printf("Device does not implement get_status, assuming appIDLE\n"); + status.bStatus = DFU_STATUS_OK; + status.bwPollTimeout = 0; + status.bState = DFU_STATE_appIDLE; + status.iString = 0; + } else if (err < 0) { + errx(EX_IOERR, "error get_status"); + } else { + printf("state = %s, status = %d\n", + dfu_state_to_string(status.bState), status.bStatus); + } + milli_sleep(status.bwPollTimeout); + + switch (status.bState) { + case DFU_STATE_appIDLE: + case DFU_STATE_appDETACH: + printf("Device really in Runtime Mode, send DFU " + "detach request...\n"); + if (dfu_detach(dfu_root->dev_handle, + dfu_root->interface, 1000) < 0) { + warnx("error detaching"); + } + if (dfu_root->func_dfu.bmAttributes & USB_DFU_WILL_DETACH) { + printf("Device will detach and reattach...\n"); + } else { + printf("Resetting USB...\n"); + ret = libusb_reset_device(dfu_root->dev_handle); + if (ret < 0 && ret != LIBUSB_ERROR_NOT_FOUND) + errx(EX_IOERR, "error resetting " + "after detach"); + } + break; + case DFU_STATE_dfuERROR: + printf("dfuERROR, clearing status\n"); + if (dfu_clear_status(dfu_root->dev_handle, + dfu_root->interface) < 0) { + errx(EX_IOERR, "error clear_status"); + } + /* fall through */ + default: + warnx("WARNING: Runtime device already in DFU state ?!?"); + libusb_release_interface(dfu_root->dev_handle, + dfu_root->interface); + goto dfustate; + } + libusb_release_interface(dfu_root->dev_handle, + dfu_root->interface); + libusb_close(dfu_root->dev_handle); + dfu_root->dev_handle = NULL; + + if (mode == MODE_DETACH) { + libusb_exit(ctx); + exit(0); + } + + /* keeping handles open might prevent re-enumeration */ + disconnect_devices(); + + milli_sleep(detach_delay * 1000); + + /* Change match vendor and product to impossible values to force + * only DFU mode matches in the following probe */ + match_vendor = match_product = 0x10000; + + probe_devices(ctx); + + if (dfu_root == NULL) { + errx(EX_IOERR, "Lost device after RESET?"); + } else if (dfu_root->next != NULL) { + errx(EX_IOERR, "More than one DFU capable USB device found! " + "Try `--list' and specify the serial number " + "or disconnect all but one device"); + } + + /* Check for DFU mode device */ + if (!(dfu_root->flags | DFU_IFF_DFU)) + errx(EX_SOFTWARE, "Device is not in DFU mode"); + + printf("Opening DFU USB Device...\n"); + ret = libusb_open(dfu_root->dev, &dfu_root->dev_handle); + if (ret || !dfu_root->dev_handle) { + errx(EX_IOERR, "Cannot open device"); + } + } else { + /* we're already in DFU mode, so we can skip the detach/reset + * procedure */ + /* If a match vendor/product was specified, use that as the runtime + * vendor/product, otherwise use the DFU mode vendor/product */ + runtime_vendor = match_vendor < 0 ? dfu_root->vendor : match_vendor; + runtime_product = match_product < 0 ? dfu_root->product : match_product; + } + +dfustate: +#if 0 + printf("Setting Configuration %u...\n", dfu_root->configuration); + if (libusb_set_configuration(dfu_root->dev_handle, dfu_root->configuration) < 0) { + errx(EX_IOERR, "Cannot set configuration"); + } +#endif + printf("Claiming USB DFU Interface...\n"); + if (libusb_claim_interface(dfu_root->dev_handle, dfu_root->interface) < 0) { + errx(EX_IOERR, "Cannot claim interface"); + } + + printf("Setting Alternate Setting #%d ...\n", dfu_root->altsetting); + if (libusb_set_interface_alt_setting(dfu_root->dev_handle, dfu_root->interface, dfu_root->altsetting) < 0) { + errx(EX_IOERR, "Cannot set alternate interface"); + } + +status_again: + printf("Determining device status: "); + if (dfu_get_status(dfu_root, &status ) < 0) { + errx(EX_IOERR, "error get_status"); + } + printf("state = %s, status = %d\n", + dfu_state_to_string(status.bState), status.bStatus); + + milli_sleep(status.bwPollTimeout); + + switch (status.bState) { + case DFU_STATE_appIDLE: + case DFU_STATE_appDETACH: + errx(EX_IOERR, "Device still in Runtime Mode!"); + break; + case DFU_STATE_dfuERROR: + printf("dfuERROR, clearing status\n"); + if (dfu_clear_status(dfu_root->dev_handle, dfu_root->interface) < 0) { + errx(EX_IOERR, "error clear_status"); + } + goto status_again; + break; + case DFU_STATE_dfuDNLOAD_IDLE: + case DFU_STATE_dfuUPLOAD_IDLE: + printf("aborting previous incomplete transfer\n"); + if (dfu_abort(dfu_root->dev_handle, dfu_root->interface) < 0) { + errx(EX_IOERR, "can't send DFU_ABORT"); + } + goto status_again; + break; + case DFU_STATE_dfuIDLE: + printf("dfuIDLE, continuing\n"); + break; + default: + break; + } + + if (DFU_STATUS_OK != status.bStatus ) { + printf("WARNING: DFU Status: '%s'\n", + dfu_status_to_string(status.bStatus)); + /* Clear our status & try again. */ + if (dfu_clear_status(dfu_root->dev_handle, dfu_root->interface) < 0) + errx(EX_IOERR, "USB communication error"); + if (dfu_get_status(dfu_root, &status) < 0) + errx(EX_IOERR, "USB communication error"); + if (DFU_STATUS_OK != status.bStatus) + errx(EX_SOFTWARE, "Status is not OK: %d", status.bStatus); + + milli_sleep(status.bwPollTimeout); + } + + printf("DFU mode device DFU version %04x\n", + libusb_le16_to_cpu(dfu_root->func_dfu.bcdDFUVersion)); + + if (dfu_root->func_dfu.bcdDFUVersion == libusb_cpu_to_le16(0x11a)) + dfuse_device = 1; + + /* If not overridden by the user */ + if (!transfer_size) { + transfer_size = libusb_le16_to_cpu( + dfu_root->func_dfu.wTransferSize); + if (transfer_size) { + printf("Device returned transfer size %i\n", + transfer_size); + } else { + errx(EX_IOERR, "Transfer size must be specified"); + } + } + +#ifdef HAVE_GETPAGESIZE +/* autotools lie when cross-compiling for Windows using mingw32/64 */ +#ifndef __MINGW32__ + /* limitation of Linux usbdevio */ + if ((int)transfer_size > getpagesize()) { + transfer_size = getpagesize(); + printf("Limited transfer size to %i\n", transfer_size); + } +#endif /* __MINGW32__ */ +#endif /* HAVE_GETPAGESIZE */ + + if (transfer_size < dfu_root->bMaxPacketSize0) { + transfer_size = dfu_root->bMaxPacketSize0; + printf("Adjusted transfer size to %i\n", transfer_size); + } + + switch (mode) { + case MODE_UPLOAD: + /* open for "exclusive" writing */ + fd = open(file.name, O_WRONLY | O_BINARY | O_CREAT | O_EXCL | O_TRUNC, 0666); + if (fd < 0) + err(EX_IOERR, "Cannot open file %s for writing", file.name); + + if (dfuse_device || dfuse_options) { + if (dfuse_do_upload(dfu_root, transfer_size, fd, + dfuse_options) < 0) + exit(1); + } else { + if (dfuload_do_upload(dfu_root, transfer_size, + expected_size, fd) < 0) { + exit(1); + } + } + close(fd); + break; + + case MODE_DOWNLOAD: + if (((file.idVendor != 0xffff && file.idVendor != runtime_vendor) || + (file.idProduct != 0xffff && file.idProduct != runtime_product)) && + ((file.idVendor != 0xffff && file.idVendor != dfu_root->vendor) || + (file.idProduct != 0xffff && file.idProduct != dfu_root->product))) { + errx(EX_IOERR, "Error: File ID %04x:%04x does " + "not match device (%04x:%04x or %04x:%04x)", + file.idVendor, file.idProduct, + runtime_vendor, runtime_product, + dfu_root->vendor, dfu_root->product); + } + if (dfuse_device || dfuse_options || file.bcdDFU == 0x11a) { + if (dfuse_do_dnload(dfu_root, transfer_size, &file, + dfuse_options) < 0) + exit(1); + } else { + if (dfuload_do_dnload(dfu_root, transfer_size, &file) < 0) + exit(1); + } + break; + case MODE_DETACH: + if (dfu_detach(dfu_root->dev_handle, dfu_root->interface, 1000) < 0) { + warnx("can't detach"); + } + break; + default: + errx(EX_IOERR, "Unsupported mode: %u", mode); + break; + } + + if (final_reset) { + if (dfu_detach(dfu_root->dev_handle, dfu_root->interface, 1000) < 0) { + /* Even if detach failed, just carry on to leave the + device in a known state */ + warnx("can't detach"); + } + printf("Resetting USB to switch back to runtime mode\n"); + ret = libusb_reset_device(dfu_root->dev_handle); + if (ret < 0 && ret != LIBUSB_ERROR_NOT_FOUND) { + errx(EX_IOERR, "error resetting after download"); + } + } + + libusb_close(dfu_root->dev_handle); + dfu_root->dev_handle = NULL; + libusb_exit(ctx); + + return (0); +} diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/portable.h b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/portable.h new file mode 100644 index 0000000..cf8d5df --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/portable.h @@ -0,0 +1,72 @@ + +#ifndef PORTABLE_H +#define PORTABLE_H + +#ifdef HAVE_CONFIG_H +# include "config.h" +#else +# define PACKAGE "dfu-util" +# define PACKAGE_VERSION "0.8-msvc" +# define PACKAGE_STRING "dfu-util 0.8-msvc" +# define PACKAGE_BUGREPORT "dfu-util@lists.gnumonks.org" +#endif /* HAVE_CONFIG_H */ + +#ifdef HAVE_FTRUNCATE +# include +#else +# include +#endif /* HAVE_FTRUNCATE */ + +#ifdef HAVE_NANOSLEEP +# include +# define milli_sleep(msec) do {\ + if (msec) {\ + struct timespec nanosleepDelay = { (msec) / 1000, ((msec) % 1000) * 1000000 };\ + nanosleep(&nanosleepDelay, NULL);\ + } } while (0) +#elif defined HAVE_WINDOWS_H +# define milli_sleep(msec) do {\ + if (msec) {\ + Sleep(msec);\ + } } while (0) +#else +# error "Can't get no sleep! Please report" +#endif /* HAVE_NANOSLEEP */ + +#ifdef HAVE_ERR +# include +#else +# include +# include +# define warnx(...) do {\ + fprintf(stderr, __VA_ARGS__);\ + fprintf(stderr, "\n"); } while (0) +# define errx(eval, ...) do {\ + warnx(__VA_ARGS__);\ + exit(eval); } while (0) +# define warn(...) do {\ + fprintf(stderr, "%s: ", strerror(errno));\ + warnx(__VA_ARGS__); } while (0) +# define err(eval, ...) do {\ + warn(__VA_ARGS__);\ + exit(eval); } while (0) +#endif /* HAVE_ERR */ + +#ifdef HAVE_SYSEXITS_H +# include +#else +# define EX_OK 0 /* successful termination */ +# define EX_USAGE 64 /* command line usage error */ +# define EX_SOFTWARE 70 /* internal software error */ +# define EX_IOERR 74 /* input/output error */ +#endif /* HAVE_SYSEXITS_H */ + +#ifndef O_BINARY +# define O_BINARY 0 +#endif + +#ifndef off_t +# define off_t long int +#endif + +#endif /* PORTABLE_H */ diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/prefix.c b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/prefix.c new file mode 100644 index 0000000..be8e3fa --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/prefix.c @@ -0,0 +1,176 @@ +/* + * dfu-prefix + * + * Copyright 2011-2012 Stefan Schmidt + * Copyright 2013 Hans Petter Selasky + * Copyright 2014 Uwe Bonnes + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include "portable.h" +#include "dfu_file.h" + +enum mode { + MODE_NONE, + MODE_ADD, + MODE_DEL, + MODE_CHECK +}; + +int verbose; + +static void help(void) +{ + fprintf(stderr, "Usage: dfu-prefix [options] ...\n" + " -h --help\t\t\tPrint this help message\n" + " -V --version\t\t\tPrint the version number\n" + " -c --check \t\tCheck DFU prefix of \n" + " -D --delete \t\tDelete DFU prefix from \n" + " -a --add \t\tAdd DFU prefix to \n" + "In combination with -a:\n" + ); + fprintf(stderr, " -s --stellaris-address
Add TI Stellaris address prefix to \n" + "In combination with -D or -c:\n" + " -T --stellaris\t\tAct on TI Stellaris address prefix of \n" + "In combination with -a or -D or -c:\n" + " -L --lpc-prefix\t\tUse NXP LPC DFU prefix format\n" + ); + exit(EX_USAGE); +} + +static void print_version(void) +{ + printf("dfu-prefix (%s) %s\n\n", PACKAGE, PACKAGE_VERSION); + printf("Copyright 2011-2012 Stefan Schmidt, 2014 Uwe Bonnes\n" + "This program is Free Software and has ABSOLUTELY NO WARRANTY\n" + "Please report bugs to %s\n\n", PACKAGE_BUGREPORT); + +} + +static struct option opts[] = { + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'V' }, + { "check", 1, 0, 'c' }, + { "add", 1, 0, 'a' }, + { "delete", 1, 0, 'D' }, + { "stellaris-address", 1, 0, 's' }, + { "stellaris", 0, 0, 'T' }, + { "LPC", 0, 0, 'L' }, +}; +int main(int argc, char **argv) +{ + struct dfu_file file; + enum mode mode = MODE_NONE; + enum prefix_type type = ZERO_PREFIX; + uint32_t lmdfu_flash_address = 0; + char *end; + + /* make sure all prints are flushed */ + setvbuf(stdout, NULL, _IONBF, 0); + + print_version(); + + memset(&file, 0, sizeof(file)); + + while (1) { + int c, option_index = 0; + c = getopt_long(argc, argv, "hVc:a:D:p:v:d:s:TL", opts, + &option_index); + if (c == -1) + break; + + switch (c) { + case 'h': + help(); + break; + case 'V': + exit(0); + break; + case 'D': + file.name = optarg; + mode = MODE_DEL; + break; + case 'c': + file.name = optarg; + mode = MODE_CHECK; + break; + case 'a': + file.name = optarg; + mode = MODE_ADD; + break; + case 's': + lmdfu_flash_address = strtoul(optarg, &end, 0); + if (*end) { + errx(EX_IOERR, "Invalid lmdfu " + "address: %s", optarg); + } + /* fall-through */ + case 'T': + type = LMDFU_PREFIX; + break; + case 'L': + type = LPCDFU_UNENCRYPTED_PREFIX; + break; + default: + help(); + break; + } + } + + if (!file.name) { + fprintf(stderr, "You need to specify a filename\n"); + help(); + } + + switch(mode) { + case MODE_ADD: + if (type == ZERO_PREFIX) + errx(EX_IOERR, "Prefix type must be specified"); + dfu_load_file(&file, MAYBE_SUFFIX, NO_PREFIX); + file.lmdfu_address = lmdfu_flash_address; + file.prefix_type = type; + printf("Adding prefix to file\n"); + dfu_store_file(&file, file.size.suffix != 0, 1); + break; + + case MODE_CHECK: + dfu_load_file(&file, MAYBE_SUFFIX, MAYBE_PREFIX); + show_suffix_and_prefix(&file); + if (type > ZERO_PREFIX && file.prefix_type != type) + errx(EX_IOERR, "No prefix of requested type"); + break; + + case MODE_DEL: + dfu_load_file(&file, MAYBE_SUFFIX, NEEDS_PREFIX); + if (type > ZERO_PREFIX && file.prefix_type != type) + errx(EX_IOERR, "No prefix of requested type"); + printf("Removing prefix from file\n"); + /* if there was a suffix, rewrite it */ + dfu_store_file(&file, file.size.suffix != 0, 0); + break; + + default: + help(); + break; + } + return (0); +} diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/quirks.c b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/quirks.c new file mode 100644 index 0000000..de394a6 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/quirks.c @@ -0,0 +1,56 @@ +/* + * Simple quirk system for dfu-util + * + * Copyright 2010-2014 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include "quirks.h" + +uint16_t get_quirks(uint16_t vendor, uint16_t product, uint16_t bcdDevice) +{ + uint16_t quirks = 0; + + /* Device returns bogus bwPollTimeout values */ + if ((vendor == VENDOR_OPENMOKO || vendor == VENDOR_FIC) && + product >= PRODUCT_FREERUNNER_FIRST && + product <= PRODUCT_FREERUNNER_LAST) + quirks |= QUIRK_POLLTIMEOUT; + + if (vendor == VENDOR_VOTI && + product == PRODUCT_OPENPCD) + quirks |= QUIRK_POLLTIMEOUT; + + /* Reports wrong DFU version in DFU descriptor */ + if (vendor == VENDOR_LEAFLABS && + product == PRODUCT_MAPLE3 && + bcdDevice == 0x0200) + quirks |= QUIRK_FORCE_DFU11; + + /* old devices(bcdDevice == 0) return bogus bwPollTimeout values */ + if (vendor == VENDOR_SIEMENS && + (product == PRODUCT_PXM40 || product == PRODUCT_PXM50) && + bcdDevice == 0) + quirks |= QUIRK_POLLTIMEOUT; + + /* M-Audio Transit returns bogus bwPollTimeout values */ + if (vendor == VENDOR_MIDIMAN && + product == PRODUCT_TRANSIT) + quirks |= QUIRK_POLLTIMEOUT; + + return (quirks); +} diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/quirks.h b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/quirks.h new file mode 100644 index 0000000..0e4b3ec --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/quirks.h @@ -0,0 +1,27 @@ +#ifndef DFU_QUIRKS_H +#define DFU_QUIRKS_H + +#define VENDOR_OPENMOKO 0x1d50 /* Openmoko Freerunner / GTA02 */ +#define VENDOR_FIC 0x1457 /* Openmoko Freerunner / GTA02 */ +#define VENDOR_VOTI 0x16c0 /* OpenPCD Reader */ +#define VENDOR_LEAFLABS 0x1eaf /* Maple */ +#define VENDOR_SIEMENS 0x0908 /* Siemens AG */ +#define VENDOR_MIDIMAN 0x0763 /* Midiman */ + +#define PRODUCT_FREERUNNER_FIRST 0x5117 +#define PRODUCT_FREERUNNER_LAST 0x5126 +#define PRODUCT_OPENPCD 0x076b +#define PRODUCT_MAPLE3 0x0003 /* rev 3 and 5 */ +#define PRODUCT_PXM40 0x02c4 /* Siemens AG, PXM 40 */ +#define PRODUCT_PXM50 0x02c5 /* Siemens AG, PXM 50 */ +#define PRODUCT_TRANSIT 0x2806 /* M-Audio Transit (Midiman) */ + +#define QUIRK_POLLTIMEOUT (1<<0) +#define QUIRK_FORCE_DFU11 (1<<1) + +/* Fallback value, works for OpenMoko */ +#define DEFAULT_POLLTIMEOUT 5 + +uint16_t get_quirks(uint16_t vendor, uint16_t product, uint16_t bcdDevice); + +#endif /* DFU_QUIRKS_H */ diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/suffix.c b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/suffix.c new file mode 100644 index 0000000..0df248f --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/suffix.c @@ -0,0 +1,176 @@ +/* + * dfu-suffix + * + * Copyright 2011-2012 Stefan Schmidt + * Copyright 2013 Hans Petter Selasky + * Copyright 2014 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include "portable.h" +#include "dfu_file.h" + +enum mode { + MODE_NONE, + MODE_ADD, + MODE_DEL, + MODE_CHECK +}; + +int verbose; + +static void help(void) +{ + fprintf(stderr, "Usage: dfu-suffix [options] ...\n" + " -h --help\t\t\tPrint this help message\n" + " -V --version\t\t\tPrint the version number\n" + " -c --check \t\tCheck DFU suffix of \n" + " -a --add \t\tAdd DFU suffix to \n" + " -D --delete \t\tDelete DFU suffix from \n" + " -p --pid \t\tAdd product ID into DFU suffix in \n" + " -v --vid \t\tAdd vendor ID into DFU suffix in \n" + " -d --did \t\tAdd device ID into DFU suffix in \n" + " -S --spec \t\tAdd DFU specification ID into DFU suffix in \n" + ); + exit(EX_USAGE); +} + +static void print_version(void) +{ + printf("dfu-suffix (%s) %s\n\n", PACKAGE, PACKAGE_VERSION); + printf("Copyright 2011-2012 Stefan Schmidt, 2013-2014 Tormod Volden\n" + "This program is Free Software and has ABSOLUTELY NO WARRANTY\n" + "Please report bugs to %s\n\n", PACKAGE_BUGREPORT); + +} + +static struct option opts[] = { + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'V' }, + { "check", 1, 0, 'c' }, + { "add", 1, 0, 'a' }, + { "delete", 1, 0, 'D' }, + { "pid", 1, 0, 'p' }, + { "vid", 1, 0, 'v' }, + { "did", 1, 0, 'd' }, + { "spec", 1, 0, 'S' }, +}; + +int main(int argc, char **argv) +{ + struct dfu_file file; + int pid, vid, did, spec; + enum mode mode = MODE_NONE; + + /* make sure all prints are flushed */ + setvbuf(stdout, NULL, _IONBF, 0); + + print_version(); + + pid = vid = did = 0xffff; + spec = 0x0100; /* Default to bcdDFU version 1.0 */ + memset(&file, 0, sizeof(file)); + + while (1) { + int c, option_index = 0; + c = getopt_long(argc, argv, "hVc:a:D:p:v:d:S:s:T", opts, + &option_index); + if (c == -1) + break; + + switch (c) { + case 'h': + help(); + break; + case 'V': + exit(0); + break; + case 'D': + file.name = optarg; + mode = MODE_DEL; + break; + case 'p': + pid = strtol(optarg, NULL, 16); + break; + case 'v': + vid = strtol(optarg, NULL, 16); + break; + case 'd': + did = strtol(optarg, NULL, 16); + break; + case 'S': + spec = strtol(optarg, NULL, 16); + break; + case 'c': + file.name = optarg; + mode = MODE_CHECK; + break; + case 'a': + file.name = optarg; + mode = MODE_ADD; + break; + default: + help(); + break; + } + } + + if (!file.name) { + fprintf(stderr, "You need to specify a filename\n"); + help(); + } + + if (spec != 0x0100 && spec != 0x011a) { + fprintf(stderr, "Only DFU specification 0x0100 and 0x011a supported\n"); + help(); + } + + switch(mode) { + case MODE_ADD: + dfu_load_file(&file, NO_SUFFIX, MAYBE_PREFIX); + file.idVendor = vid; + file.idProduct = pid; + file.bcdDevice = did; + file.bcdDFU = spec; + /* always write suffix, rewrite prefix if there was one */ + dfu_store_file(&file, 1, file.size.prefix != 0); + printf("Suffix successfully added to file\n"); + break; + + case MODE_CHECK: + dfu_load_file(&file, NEEDS_SUFFIX, MAYBE_PREFIX); + show_suffix_and_prefix(&file); + break; + + case MODE_DEL: + dfu_load_file(&file, NEEDS_SUFFIX, MAYBE_PREFIX); + dfu_store_file(&file, 0, file.size.prefix != 0); + if (file.size.suffix) /* had a suffix */ + printf("Suffix successfully removed from file\n"); + break; + + default: + help(); + break; + } + return (0); +} diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/usb_dfu.h b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/usb_dfu.h new file mode 100644 index 0000000..660bedc --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/src/usb_dfu.h @@ -0,0 +1,99 @@ +#ifndef USB_DFU_H +#define USB_DFU_H +/* USB Device Firmware Update Implementation for OpenPCD + * (C) 2006 by Harald Welte + * + * Protocol definitions for USB DFU + * + * This ought to be compliant to the USB DFU Spec 1.0 as available from + * http://www.usb.org/developers/devclass_docs/usbdfu10.pdf + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#define USB_DT_DFU 0x21 + +#ifdef _MSC_VER +# pragma pack(push) +# pragma pack(1) +#endif /* _MSC_VER */ +struct usb_dfu_func_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bmAttributes; +#define USB_DFU_CAN_DOWNLOAD (1 << 0) +#define USB_DFU_CAN_UPLOAD (1 << 1) +#define USB_DFU_MANIFEST_TOL (1 << 2) +#define USB_DFU_WILL_DETACH (1 << 3) + uint16_t wDetachTimeOut; + uint16_t wTransferSize; + uint16_t bcdDFUVersion; +#ifdef _MSC_VER +}; +# pragma pack(pop) +#elif defined __GNUC__ +} __attribute__ ((packed)); +#else + #warning "No way to pack struct on this compiler? This will break!" +#endif /* _MSC_VER */ + +#define USB_DT_DFU_SIZE 9 + +#define USB_TYPE_DFU (LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE) + +/* DFU class-specific requests (Section 3, DFU Rev 1.1) */ +#define USB_REQ_DFU_DETACH 0x00 +#define USB_REQ_DFU_DNLOAD 0x01 +#define USB_REQ_DFU_UPLOAD 0x02 +#define USB_REQ_DFU_GETSTATUS 0x03 +#define USB_REQ_DFU_CLRSTATUS 0x04 +#define USB_REQ_DFU_GETSTATE 0x05 +#define USB_REQ_DFU_ABORT 0x06 + +/* DFU_GETSTATUS bStatus values (Section 6.1.2, DFU Rev 1.1) */ +#define DFU_STATUS_OK 0x00 +#define DFU_STATUS_errTARGET 0x01 +#define DFU_STATUS_errFILE 0x02 +#define DFU_STATUS_errWRITE 0x03 +#define DFU_STATUS_errERASE 0x04 +#define DFU_STATUS_errCHECK_ERASED 0x05 +#define DFU_STATUS_errPROG 0x06 +#define DFU_STATUS_errVERIFY 0x07 +#define DFU_STATUS_errADDRESS 0x08 +#define DFU_STATUS_errNOTDONE 0x09 +#define DFU_STATUS_errFIRMWARE 0x0a +#define DFU_STATUS_errVENDOR 0x0b +#define DFU_STATUS_errUSBR 0x0c +#define DFU_STATUS_errPOR 0x0d +#define DFU_STATUS_errUNKNOWN 0x0e +#define DFU_STATUS_errSTALLEDPKT 0x0f + +enum dfu_state { + DFU_STATE_appIDLE = 0, + DFU_STATE_appDETACH = 1, + DFU_STATE_dfuIDLE = 2, + DFU_STATE_dfuDNLOAD_SYNC = 3, + DFU_STATE_dfuDNBUSY = 4, + DFU_STATE_dfuDNLOAD_IDLE = 5, + DFU_STATE_dfuMANIFEST_SYNC = 6, + DFU_STATE_dfuMANIFEST = 7, + DFU_STATE_dfuMANIFEST_WAIT_RST = 8, + DFU_STATE_dfuUPLOAD_IDLE = 9, + DFU_STATE_dfuERROR = 10 +}; + +#endif /* USB_DFU_H */ diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/www/build.html b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/www/build.html new file mode 100644 index 0000000..f3036e4 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/www/build.html @@ -0,0 +1,147 @@ + + + + + + + Building dfu-util from source + + + + + + + + + +
+

How to build dfu-util from source

+ +

Prerequisites for building from git

+

Mac OS X

+

+First install MacPorts (and if you are on 10.6 or older, the Java Developer Package) and then run: +

+
+	sudo port install libusb-devel git-core
+
+ +

FreeBSD

+
+	sudo pkg_add -r git pkgconf
+
+ +

Ubuntu and Debian and derivatives

+
+	sudo apt-get build-dep dfu-util
+	sudo apt-get install libusb-1.0-0-dev
+
+ +

Get the source code and build it

+

+The first time you will have to clone the git repository: +

+
+	git clone git://gitorious.org/dfu-util/dfu-util.git
+	cd dfu-util
+
+

+If you later want to update to latest git version, just run this: +

+
+	make maintainer-clean
+	git pull
+
+

+To build the source: +

+
+	./autogen.sh
+	./configure  # on most systems
+	make
+
+ +

+If you are building on Mac OS X, replace the ./configure command with: +

+
+	./configure --libdir=/opt/local/lib --includedir=/opt/local/include  # on MacOSX only
+
+ +

+Your dfu-util binary will be inside the src folder. Use it from there, or install it to /usr/local/bin by running "sudo make install". +

+ +

Cross-building for Windows

+ +

+Windows binaries can be built in a MinGW +environment, on a Windows computer or cross-hosted in another OS. +To build it on a Debian or Ubuntu host, first install build dependencies: +

+
+	sudo apt-get build-dep libusb-1.0-0 dfu-util
+	sudo apt-get install mingw32
+
+ +

+The below example builds dfu-util 0.8 and libusb 1.0.19 from unpacked release +tarballs. If you instead build from git, you will have to run "./autogen.sh" +before running the "./configure" steps. +

+ +
+mkdir -p build
+cd libusb-1.0.19
+PKG_CONFIG_PATH=$PWD/../build/lib/pkgconfig ./configure \
+    --host=i586-mingw32msvc --prefix=$PWD/../build
+# WINVER workaround needed for 1.0.19 only
+make CFLAGS="-DWINVER=0x0501"
+make install
+cd ..
+
+cd dfu-util-0.8
+PKG_CONFIG_PATH=$PWD/../build/lib/pkgconfig ./configure \
+    --host=i586-mingw32msvc --prefix=$PWD/../build
+make
+make install
+cd ..
+
+The build files will now be in build/bin. +

+ +

Building on Windows using MinGW

+This assumes using release tarballs or having run ./autogen.sh on +the git sources. +
+cd libusb-1.0.19
+./configure --prefix=$HOME
+# WINVER workaround needed for 1.0.19 only
+# MKDIR_P setting should not really be needed...
+make CFLAGS="-DWINVER=0x0501" MKDIR_P="mkdir -p"
+make install
+cd ..
+
+cd dfu-util-0.8
+./configure USB_CFLAGS="-I$HOME/include/libusb-1.0" \
+            USB_LIBS="-L $HOME/lib -lusb-1.0" PKG_CONFIG=true
+make
+make install
+cd ..
+
+To link libusb statically into dfu-util.exe use instead of "make": +
+make LDFLAGS=-static
+
+The built executables (and DLL) will now be under $HOME/bin. + +

+[Back to dfu-util main page] +

+ +
+ + diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/www/dfu-util.1.html b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/www/dfu-util.1.html new file mode 100644 index 0000000..62ca40b --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/www/dfu-util.1.html @@ -0,0 +1,411 @@ + + +Man page of DFU-UTIL + + +

DFU-UTIL(1)

+ +  +

NAME

+ +dfu-util - Device firmware update (DFU) USB programmer +  +

SYNOPSIS

+ + +
+
+dfu-util + +-l + +[-v] + +[-d + +vid:pid[,vid:pid]] + +[-p + +path] + +[-c + +configuration] + +[-i + +interface] + +[-a + +alt-intf] + +[-S + +serial[,serial]] + + +
+dfu-util + +[-v] + +[-d + +vid:pid[,vid:pid]] + +[-p + +path] + +[-c + +configuration] + +[-i + +interface] + +[-a + +alt-intf] + +[-S + +serial[,serial]] + +[-t + +size] + +[-Z + +size] + +[-s + +address] + +[-R] + +[-D|-U + +file] + + +
+dfu-util + +[-hV] + +
+  +

DESCRIPTION

+ +dfu-util + +is a program that implements the host (computer) side of the USB DFU +(Universal Serial Bus Device Firmware Upgrade) protocol. +

+dfu-util communicates with devices that implement the device side of the +USB DFU protocol, and is often used to upgrade the firmware of such +devices. +  +

OPTIONS

+ +
+
-l, --list + +
+List the currently attached DFU capable USB devices. +
-d, --device [Run-Time VENDOR]:[Run-Time PRODUCT][,[DFU Mode VENDOR]:[DFU Mode PRODUCT]] + +
+
+Specify run-time and/or DFU mode vendor and/or product IDs of the DFU device +to work with. VENDOR and PRODUCT are hexadecimal numbers (no prefix +needed), "*" (match any), or "-" (match nothing). By default, any DFU capable +device in either run-time or DFU mode will be considered. +

+If you only have one standards-compliant DFU device attached to your computer, +this parameter is optional. However, as soon as you have multiple DFU devices +connected, dfu-util will detect this and abort, asking you to specify which +device to use. +

+If only run-time IDs are specified (e.g. "--device 1457:51ab"), then in +addition to the specified run-time IDs, any DFU mode devices will also be +considered. This is beneficial to allow a DFU capable device to be found +again after a switch to DFU mode, since the vendor and/or product ID of a +device usually changes in DFU mode. +

+If only DFU mode IDs are specified (e.g. "--device ,951:26"), then all +run-time devices will be ignored, making it easy to target a specific device in +DFU mode. +

+If both run-time and DFU mode IDs are specified (e.g. "--device +1457:51ab,:2bc"), then unspecified DFU mode components will use the run-time +value specified. +

+Examples: +

+
--device 1457:51ab,951:26 + +
+
+ +Work with a device in run-time mode with +vendor ID 0x1457 and product ID 0x51ab, or in DFU mode with vendor ID 0x0951 +and product ID 0x0026 +

+

--device 1457:51ab,:2bc + +
+
+ +Work with a device in run-time mode with vendor ID 0x1457 and product ID +0x51ab, or in DFU mode with vendor ID 0x1457 and product ID 0x02bc +

+

--device 1457:51ab + +
+
+ +Work with a device in run-time mode with vendor ID 0x1457 and product ID +0x51ab, or in DFU mode with any vendor and product ID +

+

--device ,951:26 + +
+
+ +Work with a device in DFU mode with vendor ID 0x0951 and product ID 0x0026 +

+

--device *,- + +
+
+ +Work with any device in run-time mode, and ignore any device in DFU mode +

+

--device , + +
+
+ +Ignore any device in run-time mode, and Work with any device in DFU mode +
+
+ +
-p, --path BUS-PORT. ... .PORT + +
+Specify the path to the DFU device. +
-c, --cfg CONFIG-NR + +
+Specify the configuration of the DFU device. Note that this is only used for matching, the configuration is not set by dfu-util. +
-i, --intf INTF-NR + +
+Specify the DFU interface number. +
-a, --alt ALT + +
+Specify the altsetting of the DFU interface by name or by number. +
-S, --serial [Run-Time SERIAL][,[DFU Mode SERIAL]] + +
+Specify the run-time and DFU mode serial numbers used to further restrict +device matches. If multiple, identical DFU devices are simultaneously +connected to a system then vendor and product ID will be insufficient for +targeting a single device. In this situation, it may be possible to use this +parameter to specify a serial number which also must match. +

+If only a single serial number is specified, then the same serial number is +used in both run-time and DFU mode. An empty serial number will match any +serial number in the corresponding mode. +

-t, --transfer-size SIZE + +
+Specify the number of bytes per USB transfer. The optimal value is +usually determined automatically so this option is rarely useful. If +you need to use this option for a device, please report it as a bug. +
-Z, --upload-size SIZE + +
+Specify the expected upload size, in bytes. +
-U, --upload FILE + +
+Read firmware from device into +FILE. + +
-D, --download FILE + +
+Write firmware from +FILE + +into device. +
-R, --reset + +
+Issue USB reset signalling after upload or download has finished. +
-s, --dfuse-address address + +
+Specify target address for raw binary download/upload on DfuSe devices. Do +not + +use this for downloading DfuSe (.dfu) files. Modifiers can be added +to the address, separated by a colon, to perform special DfuSE commands such +as "leave" DFU mode, "unprotect" and "mass-erase" flash memory. +
-v, --verbose + +
+Print more information about dfu-util's operation. A second +-v + +will turn on verbose logging of USB requests. Repeat this option to further +increase verbosity. +
-h, --help + +
+Show a help text and exit. +
-V, --version + +
+Show version information and exit. +
+  +

EXAMPLES

+ +  +

Using dfu-util in the OpenMoko project

+ +(with the Neo1973 hardware) +

+ +Flashing the rootfs: +
+ + $ dfu-util -a rootfs -R -D /path/to/openmoko-devel-image.jffs2 + +

+ +Flashing the kernel: +
+ + $ dfu-util -a kernel -R -D /path/to/uImage + +

+ +Flashing the bootloader: +
+ + $ dfu-util -a u-boot -R -D /path/to/u-boot.bin + +

+ +Copying a kernel into RAM: +
+ + $ dfu-util -a 0 -R -D /path/to/uImage + +

+Once this has finished, the kernel will be available at the default load +address of 0x32000000 in Neo1973 RAM. +Note: + +You cannot transfer more than 2MB of data into RAM using this method. +

+  +

Using dfu-util with a DfuSe device

+ +

+ +Flashing a +.dfu + +(special DfuSe format) file to the device: +
+ + $ dfu-util -a 0 -D /path/to/dfuse-image.dfu + +

+ +Reading out 1 KB of flash starting at address 0x8000000: +
+ + $ dfu-util -a 0 -s 0x08000000:1024 -U newfile.bin + +

+ +Flashing a binary file to address 0x8004000 of device memory and +ask the device to leave DFU mode: +
+ + $ dfu-util -a 0 -s 0x08004000:leave -D /path/to/image.bin + + +  +

BUGS

+ +Please report any bugs to the dfu-util mailing list at +dfu-util@lists.gnumonks.org. + +Please use the +--verbose option (repeated as necessary) to provide more + +information in your bug report. +  +

SEE ALSO

+ +The dfu-util home page is +http://dfu-util.gnumonks.org + +  +

HISTORY

+ +dfu-util was originally written for the OpenMoko project by +Weston Schmidt <weston_schmidt@yahoo.com> and +Harald Welte <hwelte@hmw-consulting.de>. Over time, nearly complete +support of DFU 1.0, DFU 1.1 and DfuSe ("1.1a") has been added. +  +

LICENCE

+ +dfu-util + +is covered by the GNU General Public License (GPL), version 2 or later. +  +

COPYRIGHT

+ +This manual page was originally written by Uwe Hermann <uwe@hermann-uwe.de>, +and is now part of the dfu-util project. +

+ +


+ 

Index

+
+
NAME
+
SYNOPSIS
+
DESCRIPTION
+
OPTIONS
+
EXAMPLES
+
+
Using dfu-util in the OpenMoko project
+
Using dfu-util with a DfuSe device
+
+
BUGS
+
SEE ALSO
+
HISTORY
+
LICENCE
+
COPYRIGHT
+
+
+This document was created by man2html, +using the doc/dfu-util.1 manual page from dfu-util 0.8.
+Time: 14:40:57 GMT, September 13, 2014 + + diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/www/dfuse.html b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/www/dfuse.html new file mode 100644 index 0000000..35e4ffa --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/www/dfuse.html @@ -0,0 +1,135 @@ + + + + + + DfuSe and dfu-util + + + + + + + + + +
+

Using dfu-util with DfuSe devices

+

DfuSe

+

+ DfuSe (DFU with ST Microsystems extensions) is a protocol based on + DFU 1.1. However, in expanding the functionality of the DFU protocol, + ST Microsystems broke all compatibility with the DFU 1.1 standard. + DfuSe devices report the DFU version as "1.1a". +

+

+ DfuSe can be used to download firmware and other data + from a host computer to a conforming device (or upload in the + opposite direction) over USB similar to standard DFU. +

+

+ The main difference from standard DFU is that the target address in + the device (flash) memory is specified by the host, so that a + download can be performed to parts of the device memory. The host + program is also responsible for erasing flash pages before they + are written to. +

+

.dfu files

+

+ A special file format is defined by ST Microsystems to carry firmware + for DfuSe devices. The file contains target information such as address + and alternate interface information in addition to the binary data. + Several blocks of binary data can be combined in one .dfu file. +

+

Alternate interfaces

+

+ Different memory locations of the device may have different + characteristics that the host program (dfu-util) has to take + into considerations, such as flash memory page size, read-only + versus read-write segments, the need to erase, and so on. + These parameters are reported by the device in the string + descriptors meant for describing the USB interfaces. + The host program decodes these strings to build a memory map of + the device. Different memory units or address spaces are listed + in separate alternate interface settings that must be selected + according to the memory unit to access. +

+

+ Note that dfu-util leaves it to the user to select alternate + interface. When parsing a .dfu file it will skip file segments + not matching the selected alternate interface. Also, some + DfuSe device firmware implementations ignore the setting of + alternate interface and deduct the memory unit from the + address, since they have no address space overlap. +

+

DfuSe special commands

+

+ DfuSe special commands are used by the host program during normal + downloads or uploads, such as SET_ADDRESS and ERASE_PAGE. Also + the normal DFU_DNLOAD and DFU_UPLOAD commands have special + implementations in DfuSe. + Many DfuSe devices also support commands to leave DFU mode, + read unprotect the flash memory or mass erase the flash memory. + dfu-util (from version 0.7) + supports adding "leave", "unprotect", or "mass-erase" + to the -s option argument to send such requests in combination + with a download request. These modifiers are separated with a colon. +

+

+ Some DfuSe devices have their DfuSe bootloader running from flash + memory. Erasing the whole flash memory would therefore destroy + the DfuSe bootloader itself and practically brick the device + for most users. Any use of modifiers such as "unprotect" + and "mass-erase" therefore needs to be combined with the "force" + modifer. This is not included in the examples, to not encourage + ignorant users to copy and paste such instructions and shoot + themselves in the foot. +

+

+ Devices based on for instance STM32F103 all run the bootloader + from flash, since there is no USB bootloader in ROM. +

+

+ For instance STM32F107, STM32F2xx and STM32F4xx devices have a + DfuSe bootloader in ROM, so the flash can be erased while + keeping the device available for USB DFU transfers as long + as the device designers use this built-in bootloader and have + not implemented another DfuSe bootloader in flash that the user is + dependent upon. +

+

+ Well-written bootloaders running from flash will report their + own memory region as read-only and not eraseable, but this does + not prevent dfu-util from sending a "unprotect" or "mass-erase" + request which overrides this, if the user insists. +

+

Example usage

+

+ Flashing a .dfu (special DfuSe format) file to the device: +

+
+         $ dfu-util -a 0 -D /path/to/dfuse-image.dfu
+	
+

+ Reading out 1 KB of flash starting at address 0x8000000: +

+
+         $ dfu-util -a 0 -s 0x08000000:1024 -U newfile.bin
+	
+

+ Flashing a binary file to address 0x8004000 of device memory and ask + the device to leave DFU mode: +

+
+         $ dfu-util -a 0 -s 0x08004000:leave -D /path/to/image.bin
+	
+

+ [Back to dfu-util main page] +

+ +
+ + diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/www/index.html b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/www/index.html new file mode 100644 index 0000000..108ddaf --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/www/index.html @@ -0,0 +1,119 @@ + + + + + + dfu-util Homepage + + + + + + + + + +
+

dfu-util - Device Firmware Upgrade Utilities

+

Description

+

+ dfu-util is a host side implementation of the DFU 1.0 and DFU 1.1 specifications of the USB forum. + + DFU is intended to download and upload firmware to/from devices connected + over USB. It ranges from small devices like micro-controller boards + to mobile phones. Using dfu-util you can download firmware to your + DFU-enabled device or upload firmware from it. dfu-util has been + tested with the Openmoko Neo1973 and Freerunner and many other devices. +

+

+ See the manual page for examples of use. +

+

Supported Devices

+ +

Releases

+

+ Releases of the dfu-util software can be found in the + releases folder. + The current release is 0.8. +

+

+ We offer binaries for Microsoft Windows and some other platforms. + dfu-util uses libusb 1.0 to access your device, so + on Windows you have to register the device with the WinUSB driver + (alternatively libusb-win32 or libusbK), please see the libusbx wiki + for more details. +

+

+ Mac OS X users can also get dfu-util from Homebrew with "brew install dfu-util" or from MacPorts. +

+

+ Most Linux distributions ship dfu-util in binary packages for those + who do not want to compile dfu-util from source. + On Debian, Ubuntu, Fedora and Gentoo you can install it through the + normal software package tools. For other distributions +(namely OpenSuSe, Mandriva, and CentOS) Holger Freyther was kind enough to +provide binary packages through the Open Build Service. +

+

Development

+

+ Development happens in a GIT repository. Browse it via the web +interface or clone it with: +

+
+	git clone git://gitorious.org/dfu-util/dfu-util.git
+	
+

+ See our build instructions for how to + build the source on different platforms. +

+

License

+

+ This software is licensed under the GPL version 2. +

+

Contact

+

+ If you have questions about the development or use of dfu-util please + send an e-mail to our dedicated +mailing list for dfu-util. +

+

People

+

+ dfu-util was originally written by + Harald Welte partially based on code from + dfu-programmer 0.4 and is currently maintained by Stefan Schmidt and + Tormod Volden. +

+ +
+ + diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/www/simple.css b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/www/simple.css new file mode 100644 index 0000000..98100bc --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/dfu-util/www/simple.css @@ -0,0 +1,56 @@ +body { + margin: 10px; + font-size: 0.82em; + background-color: #EEE; +} + +h1 { + clear: both; + padding: 0 0 12px 0; + margin: 0; + font-size: 2em; + font-weight: bold; +} + +h2 { + clear: both; + margin: 0; + font-size: 1.5em; + font-weight: normal; +} + +h3 { + clear: both; + margin: 15px 0 0 0; + font-size: 1.0em; + font-weight: bold; +} + +p { + line-height: 20px; + padding: 8px 0 8px 0; + margin: 0; + font-size: 1.1em; +} + +pre { + white-space: pre-wrap; + background-color: #CCC; + padding: 3px; +} + +a:hover { + background-color: #DDD; +} + +#middlebox { + width: 600px; + margin: 0px auto; + text-align: left; +} + +#footer { + height: 100px; + padding: 28px 3px 0 0; + margin: 20px 0 20px 0; +} diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/README.md b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/README.md new file mode 100644 index 0000000..c6c9379 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/README.md @@ -0,0 +1,5 @@ +These files build the maple_loader.jar file used on Windows to reset the Sketch via USB Serial, so that the bootloader will run in dfu upload mode, ready for a new sketch to be uploaded + +The files were written by @bobC (github) and have been slightly modified by me (Roger Clark), so that dfu-util no longer attempts to reset the board after upload. +This change to dfu-util's reset command line argument, was required because dfu-util was showing errors on some Windows systems, because the bootloader had reset its self after upload, +before dfu-util had chance to tell it to reset. \ No newline at end of file diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build.xml b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build.xml new file mode 100644 index 0000000..80bdd6f --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + Builds, tests, and runs the project maple_loader. + + + diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/built-jar.properties b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/built-jar.properties new file mode 100644 index 0000000..10752d5 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/built-jar.properties @@ -0,0 +1,4 @@ +#Mon, 20 Jul 2015 11:21:26 +1000 + + +C\:\\Users\\rclark\\Desktop\\maple-asp-master\\installer\\maple_loader= diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/CliTemplate/CliMain.class b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/CliTemplate/CliMain.class new file mode 100644 index 0000000..37ee630 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/CliTemplate/CliMain.class differ diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/CliTemplate/DFUUploader.class b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/CliTemplate/DFUUploader.class new file mode 100644 index 0000000..77087b0 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/CliTemplate/DFUUploader.class differ diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/CliTemplate/ExecCommand.class b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/CliTemplate/ExecCommand.class new file mode 100644 index 0000000..ad95f79 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/CliTemplate/ExecCommand.class differ diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/processing/app/Base.class b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/processing/app/Base.class new file mode 100644 index 0000000..4aa0bde Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/processing/app/Base.class differ diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/processing/app/Preferences.class b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/processing/app/Preferences.class new file mode 100644 index 0000000..89cf010 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/processing/app/Preferences.class differ diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/processing/app/Serial.class b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/processing/app/Serial.class new file mode 100644 index 0000000..cceccdd Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/processing/app/Serial.class differ diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/processing/app/SerialException.class b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/processing/app/SerialException.class new file mode 100644 index 0000000..71048dd Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/processing/app/SerialException.class differ diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/processing/app/debug/MessageConsumer.class b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/processing/app/debug/MessageConsumer.class new file mode 100644 index 0000000..37250e7 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/processing/app/debug/MessageConsumer.class differ diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/processing/app/debug/MessageSiphon.class b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/processing/app/debug/MessageSiphon.class new file mode 100644 index 0000000..e22c8d4 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/processing/app/debug/MessageSiphon.class differ diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/processing/app/debug/RunnerException.class b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/processing/app/debug/RunnerException.class new file mode 100644 index 0000000..710f796 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/processing/app/debug/RunnerException.class differ diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/processing/app/helpers/ProcessUtils.class b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/processing/app/helpers/ProcessUtils.class new file mode 100644 index 0000000..27eca62 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/build/classes/processing/app/helpers/ProcessUtils.class differ diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/dist/README.TXT b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/dist/README.TXT new file mode 100644 index 0000000..255b89c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/dist/README.TXT @@ -0,0 +1,32 @@ +======================== +BUILD OUTPUT DESCRIPTION +======================== + +When you build an Java application project that has a main class, the IDE +automatically copies all of the JAR +files on the projects classpath to your projects dist/lib folder. The IDE +also adds each of the JAR files to the Class-Path element in the application +JAR files manifest file (MANIFEST.MF). + +To run the project from the command line, go to the dist folder and +type the following: + +java -jar "maple_loader.jar" + +To distribute this project, zip up the dist folder (including the lib folder) +and distribute the ZIP file. + +Notes: + +* If two JAR files on the project classpath have the same name, only the first +JAR file is copied to the lib folder. +* Only JAR files are copied to the lib folder. +If the classpath contains other types of files or folders, these files (folders) +are not copied. +* If a library on the projects classpath also has a Class-Path element +specified in the manifest,the content of the Class-Path element has to be on +the projects runtime path. +* To set a main class in a standard Java project, right-click the project node +in the Projects window and choose Properties. Then click Run and enter the +class name in the Main Class field. Alternatively, you can manually type the +class name in the manifest Main-Class element. diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/dist/lib/jssc.jar b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/dist/lib/jssc.jar new file mode 100644 index 0000000..eb74f15 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/dist/lib/jssc.jar differ diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/dist/maple_loader.jar b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/dist/maple_loader.jar new file mode 100644 index 0000000..e1f9965 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/dist/maple_loader.jar differ diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/jars/jssc.jar b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/jars/jssc.jar new file mode 100644 index 0000000..eb74f15 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/jars/jssc.jar differ diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/manifest.mf b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/manifest.mf new file mode 100644 index 0000000..328e8e5 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/manifest.mf @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +X-COMMENT: Main-Class will be added automatically by build + diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/nbproject/build-impl.xml b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/nbproject/build-impl.xml new file mode 100644 index 0000000..a66f349 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/nbproject/build-impl.xml @@ -0,0 +1,1413 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set src.dir + Must set test.src.dir + Must set build.dir + Must set dist.dir + Must set build.classes.dir + Must set dist.javadoc.dir + Must set build.test.classes.dir + Must set build.test.results.dir + Must set build.classes.excludes + Must set dist.jar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + No tests executed. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set JVM to use for profiling in profiler.info.jvm + Must set profiler agent JVM arguments in profiler.info.jvmargs.agent + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + To run this application from the command line without Ant, try: + + java -jar "${dist.jar.resolved}" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set run.class + + + + Must select one file in the IDE or set run.class + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set debug.class + + + + + Must select one file in the IDE or set debug.class + + + + + Must set fix.includes + + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + Must select one file in the IDE or set profile.class + This target only works when run from inside the NetBeans IDE. + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set run.class + + + + + + Must select some files in the IDE or set test.includes + + + + + Must select one file in the IDE or set run.class + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + Some tests failed; see details above. + + + + + + + + + Must select some files in the IDE or set test.includes + + + + Some tests failed; see details above. + + + + Must select some files in the IDE or set test.class + Must select some method in the IDE or set test.method + + + + Some tests failed; see details above. + + + + + Must select one file in the IDE or set test.class + + + + Must select one file in the IDE or set test.class + Must select some method in the IDE or set test.method + + + + + + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/nbproject/genfiles.properties b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/nbproject/genfiles.properties new file mode 100644 index 0000000..c136721 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=2e6a03ba +build.xml.script.CRC32=4676ee6b +build.xml.stylesheet.CRC32=8064a381@1.75.2.48 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=2e6a03ba +nbproject/build-impl.xml.script.CRC32=392b3f79 +nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.75.2.48 diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/nbproject/private/config.properties b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/nbproject/private/config.properties new file mode 100644 index 0000000..e69de29 diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/nbproject/private/private.properties b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/nbproject/private/private.properties new file mode 100644 index 0000000..e5c9f10 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/nbproject/private/private.properties @@ -0,0 +1,6 @@ +compile.on.save=true +do.depend=false +do.jar=true +javac.debug=true +javadoc.preview=true +user.properties.file=C:\\Users\\rclark\\AppData\\Roaming\\NetBeans\\8.0.2\\build.properties diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/nbproject/private/private.xml b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/nbproject/private/private.xml new file mode 100644 index 0000000..a1bbd60 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/nbproject/private/private.xml @@ -0,0 +1,10 @@ + + + + + + file:/C:/Users/rclark/Desktop/maple-asp-master/installer/maple_loader/src/CliTemplate/CliMain.java + file:/C:/Users/rclark/Desktop/maple-asp-master/installer/maple_loader/src/CliTemplate/DFUUploader.java + + + diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/nbproject/project.properties b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/nbproject/project.properties new file mode 100644 index 0000000..7f48d71 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/nbproject/project.properties @@ -0,0 +1,79 @@ +annotation.processing.enabled=true +annotation.processing.enabled.in.editor=false +annotation.processing.processors.list= +annotation.processing.run.all.processors=true +annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output +application.title=maple_loader +application.vendor=bob +build.classes.dir=${build.dir}/classes +build.classes.excludes=**/*.java,**/*.form +# This directory is removed when the project is cleaned: +build.dir=build +build.generated.dir=${build.dir}/generated +build.generated.sources.dir=${build.dir}/generated-sources +# Only compile against the classpath explicitly listed here: +build.sysclasspath=ignore +build.test.classes.dir=${build.dir}/test/classes +build.test.results.dir=${build.dir}/test/results +# Uncomment to specify the preferred debugger connection transport: +#debug.transport=dt_socket +debug.classpath=\ + ${run.classpath} +debug.test.classpath=\ + ${run.test.classpath} +# Files in build.classes.dir which should be excluded from distribution jar +dist.archive.excludes= +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.jar=${dist.dir}/maple_loader.jar +dist.javadoc.dir=${dist.dir}/javadoc +endorsed.classpath= +excludes= +file.reference.jssc.jar=dist/lib/jssc.jar +file.reference.jssc.jar-1=jars/jssc.jar +includes=** +jar.compress=false +javac.classpath=\ + ${file.reference.jssc.jar}:\ + ${file.reference.jssc.jar-1} +# Space-separated list of extra javac options +javac.compilerargs= +javac.deprecation=false +javac.processorpath=\ + ${javac.classpath} +javac.source=1.7 +javac.target=1.7 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +javac.test.processorpath=\ + ${javac.test.classpath} +javadoc.additionalparam= +javadoc.author=false +javadoc.encoding=${source.encoding} +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +main.class=CliTemplate.CliMain +manifest.file=manifest.mf +meta.inf.dir=${src.dir}/META-INF +mkdist.disabled=false +platform.active=default_platform +run.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +# Space-separated list of JVM arguments used when running the project. +# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value. +# To set system properties for unit tests define test-sys-prop.name=value: +run.jvmargs= +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +source.encoding=UTF-8 +src.dir=src +test.src.dir=test diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/nbproject/project.xml b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/nbproject/project.xml new file mode 100644 index 0000000..92218a9 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/nbproject/project.xml @@ -0,0 +1,15 @@ + + + org.netbeans.modules.java.j2seproject + + + maple_loader + + + + + + + + + diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/CliTemplate/CliMain.java b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/CliTemplate/CliMain.java new file mode 100644 index 0000000..c7dc9f0 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/CliTemplate/CliMain.java @@ -0,0 +1,60 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package CliTemplate; + +import java.io.IOException; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import processing.app.Preferences; + +//import processing.app.I18n; +import processing.app.helpers.ProcessUtils; + +/** + * + * @author cousinr + */ +public class CliMain { + + + /** + * @param args the command line arguments + */ + public static void main(String[] args) { + + String comPort = args[0]; // + String altIf = args[1]; // + String usbID = args[2]; // "1EAF:0003"; + String binFile = args[3]; // bin file + + System.out.println("maple_loader v0.1"); + + Preferences.set ("serial.port",comPort); + Preferences.set ("serial.parity","N"); + Preferences.setInteger ("serial.databits", 8); + Preferences.setInteger ("serial.debug_rate",9600); + Preferences.setInteger ("serial.stopbits",1); + + Preferences.setInteger ("programDelay",1200); + + Preferences.set ("upload.usbID", usbID); + Preferences.set ("upload.altID", altIf); + Preferences.setBoolean ("upload.auto_reset", true); + Preferences.setBoolean ("upload.verbose", false); + + // + DFUUploader dfuUploader = new DFUUploader(); + try { + //dfuUploader.uploadViaDFU(binFile); + dfuUploader.uploadViaDFU(binFile); + } catch (Exception e) + { + System.err.print (MessageFormat.format("an error occurred! {0}\n", e.getMessage())); + } + } +} diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/CliTemplate/DFUUploader.java b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/CliTemplate/DFUUploader.java new file mode 100644 index 0000000..3dee0b4 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/CliTemplate/DFUUploader.java @@ -0,0 +1,345 @@ +/* + DFUUploader - uploader implementation using DFU + + Copyright (c) 2010 + Andrew Meyer + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +package CliTemplate; + +import java.io.BufferedReader; +import java.io.File; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import processing.app.Preferences; +import processing.app.Serial; +import processing.app.debug.MessageConsumer; +import processing.app.debug.MessageSiphon; +import processing.app.debug.RunnerException; + +/** + * + * @author bob + */ +public class DFUUploader implements MessageConsumer { + + boolean firstErrorFound; + boolean secondErrorFound; + // part of the PdeMessageConsumer interface + boolean notFoundError; + boolean verbose; + RunnerException exception; + + static final String SUPER_BADNESS = + "Compiler error!"; + + public boolean uploadUsingPreferences(String binPath, boolean verbose) + throws RunnerException { + + this.verbose = verbose; + + return uploadViaDFU(binPath); + } + + // works with old and new versions of dfu-util + private boolean found_device (String dfuData, String usbID) + { + return dfuData.contains(("Found DFU: [0x"+usbID.substring(0,4)).toUpperCase()) || + dfuData.contains(("Found DFU: ["+usbID.substring(0,4)).toUpperCase()); + } + + public boolean uploadViaDFU (String binPath) + throws RunnerException { + + this.verbose = Preferences.getBoolean ("upload.verbose"); + + /* todo, check for size overruns! */ + String fileType="bin"; + + if (fileType.equals("bin")) { + String usbID = Preferences.get("upload.usbID"); + if (usbID == null) { + /* fall back on default */ + /* this isnt great because is default Avrdude or dfu-util? */ + usbID = Preferences.get("upload.usbID"); + } + + /* if auto-reset, then emit the reset pulse on dtr/rts */ + if (Preferences.get("upload.auto_reset") != null) { + if (Preferences.get("upload.auto_reset").toLowerCase().equals("true")) { + System.out.println("Resetting to bootloader via DTR pulse"); + emitResetPulse(); + } + } else { + System.out.println("Resetting to bootloader via DTR pulse"); + emitResetPulse(); + } + + String dfuList = new String(); + List commandCheck = new ArrayList(); + commandCheck.add("dfu-util"); + commandCheck.add("-l"); + long startChecking = System.currentTimeMillis(); + System.out.println("Searching for DFU device [" + usbID + "]..."); + do { + try { + Thread.sleep(100); + } catch (InterruptedException e) {} + dfuList = executeCheckCommand(commandCheck); + //System.out.println(dfuList); + } + while ( !found_device (dfuList.toUpperCase(), usbID) && (System.currentTimeMillis() - startChecking < 7000)); + + if ( !found_device (dfuList.toUpperCase(), usbID) ) + { + System.out.println(dfuList); + System.err.println("Couldn't find the DFU device: [" + usbID + "]"); + return false; + } + System.out.println("Found it!"); + + /* todo, add handle to let user choose altIf at upload time! */ + String altIf = Preferences.get("upload.altID"); + + List commandDownloader = new ArrayList(); + commandDownloader.add("dfu-util"); + commandDownloader.add("-a "+altIf); + commandDownloader.add("-R"); + commandDownloader.add("-d "+usbID); + commandDownloader.add("-D"+ binPath); //"./thisbin.bin"); + + return executeUploadCommand(commandDownloader); + } + + System.err.println("Only .bin files are supported at this time"); + return false; + } + + /* we need to ensure both RTS and DTR are low to start, + then pulse DTR on its own. This is the reset signal + maple responds to + */ + private void emitResetPulse() throws RunnerException { + + /* wait a while for the device to reboot */ + int programDelay = Preferences.getInteger("programDelay"); + + try { + Serial serialPort = new Serial(); + + // try to toggle DTR/RTS (old scheme) + serialPort.setRTS(false); + serialPort.setDTR(false); + serialPort.setDTR(true); + try { + Thread.sleep(50); + } catch (InterruptedException e) {} + serialPort.setDTR(false); + + // try magic number + serialPort.setRTS(true); + serialPort.setDTR(true); + try { + Thread.sleep(50); + } catch (InterruptedException e) {} + serialPort.setDTR(false); + try { + Thread.sleep(50); + } catch (InterruptedException e) {} + serialPort.write("1EAF"); + try { + Thread.sleep(50); + } catch (InterruptedException e) {} + serialPort.dispose(); + + } catch(Exception e) { + System.err.println("Reset via USB Serial Failed! Did you select the right serial port?\nAssuming the board is in perpetual bootloader mode and continuing to attempt dfu programming...\n"); + } + } + + protected String executeCheckCommand(Collection commandDownloader) + throws RunnerException + { + firstErrorFound = false; // haven't found any errors yet + secondErrorFound = false; + notFoundError = false; + int result=0; // pre-initialized to quiet a bogus warning from jikes + + String userdir = System.getProperty("user.dir") + File.separator; + String returnStr = new String(); + + try { + String[] commandArray = new String[commandDownloader.size()]; + commandDownloader.toArray(commandArray); + + String armBasePath; + + //armBasePath = new String(Base.getHardwarePath() + "/tools/arm/bin/"); + armBasePath = ""; + + commandArray[0] = armBasePath + commandArray[0]; + + if (verbose || Preferences.getBoolean("upload.verbose")) { + for(int i = 0; i < commandArray.length; i++) { + System.out.print(commandArray[i] + " "); + } + System.out.println(); + } + + Process process = Runtime.getRuntime().exec(commandArray); + BufferedReader stdInput = new BufferedReader(new + InputStreamReader(process.getInputStream())); + BufferedReader stdError = new BufferedReader(new + InputStreamReader(process.getErrorStream())); + + // wait for the process to finish. if interrupted + // before waitFor returns, continue waiting + // + boolean busy = true; + while (busy) { + try { + result = process.waitFor(); + busy = false; + } catch (InterruptedException intExc) { + } + } + + String s; + while ((s = stdInput.readLine()) != null) { + returnStr += s + "\n"; + } + + process.destroy(); + + if(exception!=null) { + exception.hideStackTrace(); + throw exception; + } + if(result!=0) return "Error!"; + } catch (Exception e) { + e.printStackTrace(); + } + //System.out.println("result2 is "+result); + // if the result isn't a known, expected value it means that something + // is fairly wrong, one possibility is that jikes has crashed. + // + if (exception != null) throw exception; + + if ((result != 0) && (result != 1 )) { + exception = new RunnerException(SUPER_BADNESS); + } + + return returnStr; // ? true : false; + + } + + // Need to overload this from Uploader to use the system-wide dfu-util + protected boolean executeUploadCommand(Collection commandDownloader) + throws RunnerException + { + firstErrorFound = false; // haven't found any errors yet + secondErrorFound = false; + notFoundError = false; + int result=0; // pre-initialized to quiet a bogus warning from jikes + + String userdir = System.getProperty("user.dir") + File.separator; + + try { + String[] commandArray = new String[commandDownloader.size()]; + commandDownloader.toArray(commandArray); + + String armBasePath; + + //armBasePath = new String(Base.getHardwarePath() + "/tools/arm/bin/"); + armBasePath = ""; + + commandArray[0] = armBasePath + commandArray[0]; + + if (verbose || Preferences.getBoolean("upload.verbose")) { + for(int i = 0; i < commandArray.length; i++) { + System.out.print(commandArray[i] + " "); + } + System.out.println(); + } + + Process process = Runtime.getRuntime().exec(commandArray); + new MessageSiphon(process.getInputStream(), this); + new MessageSiphon(process.getErrorStream(), this); + + // wait for the process to finish. if interrupted + // before waitFor returns, continue waiting + // + boolean compiling = true; + while (compiling) { + try { + result = process.waitFor(); + compiling = false; + } catch (InterruptedException intExc) { + } + } + if(exception!=null) { + exception.hideStackTrace(); + throw exception; + } + if(result!=0) + return false; + } catch (Exception e) { + e.printStackTrace(); + } + //System.out.println("result2 is "+result); + // if the result isn't a known, expected value it means that something + // is fairly wrong, one possibility is that jikes has crashed. + // + if (exception != null) throw exception; + + if ((result != 0) && (result != 1 )) { + exception = new RunnerException(SUPER_BADNESS); + //editor.error(exception); + //PdeBase.openURL(BUGS_URL); + //throw new PdeException(SUPER_BADNESS); + } + + return (result == 0); // ? true : false; + + } + + // deal with messages from dfu-util... + public void message(String s) { + + if(s.indexOf("dfu-util - (C) ") != -1) { return; } + if(s.indexOf("This program is Free Software and has ABSOLUTELY NO WARRANTY") != -1) { return; } + + if(s.indexOf("No DFU capable USB device found") != -1) { + System.err.print(s); + exception = new RunnerException("Problem uploading via dfu-util: No Maple found"); + return; + } + + if(s.indexOf("Operation not perimitted") != -1) { + System.err.print(s); + exception = new RunnerException("Problem uploading via dfu-util: Insufficient privilages"); + return; + } + + // else just print everything... + System.out.print(s); + } + +} diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/CliTemplate/ExecCommand.java b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/CliTemplate/ExecCommand.java new file mode 100644 index 0000000..3d6c106 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/CliTemplate/ExecCommand.java @@ -0,0 +1,119 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package CliTemplate; + +import java.io.IOException; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.List; + +import processing.app.debug.MessageConsumer; +import processing.app.debug.MessageSiphon; +import processing.app.debug.RunnerException; +import processing.app.helpers.ProcessUtils; + +/** + * + * @author cousinr + */ +public class ExecCommand implements MessageConsumer { + + private boolean verbose = true; + private boolean firstErrorFound; + private boolean secondErrorFound; + private RunnerException exception; + + /** + * Either succeeds or throws a RunnerException fit for public consumption. + * + * @param command + * @throws RunnerException + */ + public void execAsynchronously(String[] command) throws RunnerException { + + // eliminate any empty array entries + List stringList = new ArrayList<>(); + for (String string : command) { + string = string.trim(); + if (string.length() != 0) + stringList.add(string); + } + command = stringList.toArray(new String[stringList.size()]); + if (command.length == 0) + return; + int result = 0; + + if (verbose) { + for (String c : command) + System.out.print(c + " "); + System.out.println(); + } + + firstErrorFound = false; // haven't found any errors yet + secondErrorFound = false; + + Process process; + try { + process = ProcessUtils.exec(command); + } catch (IOException e) { + RunnerException re = new RunnerException(e.getMessage()); + re.hideStackTrace(); + throw re; + } + + MessageSiphon in = new MessageSiphon(process.getInputStream(), this); + MessageSiphon err = new MessageSiphon(process.getErrorStream(), this); + + // wait for the process to finish. if interrupted + // before waitFor returns, continue waiting + boolean compiling = true; + while (compiling) { + try { + in.join(); + err.join(); + result = process.waitFor(); + //System.out.println("result is " + result); + compiling = false; + } catch (InterruptedException ignored) { } + } + + // an error was queued up by message(), barf this back to compile(), + // which will barf it back to Editor. if you're having trouble + // discerning the imagery, consider how cows regurgitate their food + // to digest it, and the fact that they have five stomaches. + // + //System.out.println("throwing up " + exception); + if (exception != null) + throw exception; + + if (result > 1) { + // a failure in the tool (e.g. unable to locate a sub-executable) + System.err.println(MessageFormat.format("{0} returned {1}", command[0], result)); + } + + if (result != 0) { + RunnerException re = new RunnerException(MessageFormat.format("exit code: {0}", result)); + re.hideStackTrace(); + throw re; + } + } + + /** + * Part of the MessageConsumer interface, this is called + * whenever a piece (usually a line) of error message is spewed + * out from the compiler. The errors are parsed for their contents + * and line number, which is then reported back to Editor. + * @param s + */ + @Override + public void message(String s) { + int i; + + + System.err.print(s); + } + +} diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/processing/app/Base.java b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/processing/app/Base.java new file mode 100644 index 0000000..c3a174d --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/processing/app/Base.java @@ -0,0 +1,53 @@ +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2004-10 Ben Fry and Casey Reas + Copyright (c) 2001-04 Massachusetts Institute of Technology + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +package processing.app; + + +/** + * The base class for the main processing application. + * Primary role of this class is for platform identification and + * general interaction with the system (launching URLs, loading + * files and images, etc) that comes from that. + */ +public class Base { + + /** + * returns true if running on windows. + */ + static public boolean isWindows() { + //return PApplet.platform == PConstants.WINDOWS; + return System.getProperty("os.name").indexOf("Windows") != -1; + } + + + /** + * true if running on linux. + */ + static public boolean isLinux() { + //return PApplet.platform == PConstants.LINUX; + return System.getProperty("os.name").indexOf("Linux") != -1; + } + + + +} diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/processing/app/Preferences.java b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/processing/app/Preferences.java new file mode 100644 index 0000000..6368e38 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/processing/app/Preferences.java @@ -0,0 +1,157 @@ +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2004-09 Ben Fry and Casey Reas + Copyright (c) 2001-04 Massachusetts Institute of Technology + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +package processing.app; + +import java.io.*; +import java.util.*; + + +/** + * Storage class for user preferences and environment settings. + *

+ * This class no longer uses the Properties class, since + * properties files are iso8859-1, which is highly likely to + * be a problem when trying to save sketch folders and locations. + *

+ * The GUI portion in here is really ugly, as it uses exact layout. This was + * done in frustration one evening (and pre-Swing), but that's long since past, + * and it should all be moved to a proper swing layout like BoxLayout. + *

+ * This is very poorly put together, that the preferences panel and the actual + * preferences i/o is part of the same code. But there hasn't yet been a + * compelling reason to bother with the separation aside from concern about + * being lectured by strangers who feel that it doesn't look like what they + * learned in CS class. + *

+ * Would also be possible to change this to use the Java Preferences API. + * Some useful articles + * here and + * here. + * However, haven't implemented this yet for lack of time, but more + * importantly, because it would entail writing to the registry (on Windows), + * or an obscure file location (on Mac OS X) and make it far more difficult to + * find the preferences to tweak them by hand (no! stay out of regedit!) + * or to reset the preferences by simply deleting the preferences.txt file. + */ +public class Preferences { + + // what to call the feller + + static final String PREFS_FILE = "preferences.txt"; + + + // prompt text stuff + + static final String PROMPT_YES = "Yes"; + static final String PROMPT_NO = "No"; + static final String PROMPT_CANCEL = "Cancel"; + static final String PROMPT_OK = "OK"; + static final String PROMPT_BROWSE = "Browse"; + + /** + * Standardized width for buttons. Mac OS X 10.3 wants 70 as its default, + * Windows XP needs 66, and my Ubuntu machine needs 80+, so 80 seems proper. + */ + static public int BUTTON_WIDTH = 80; + + /** + * Standardized button height. Mac OS X 10.3 (Java 1.4) wants 29, + * presumably because it now includes the blue border, where it didn't + * in Java 1.3. Windows XP only wants 23 (not sure what default Linux + * would be). Because of the disparity, on Mac OS X, it will be set + * inside a static block. + */ + static public int BUTTON_HEIGHT = 24; + + // value for the size bars, buttons, etc + + static final int GRID_SIZE = 33; + + + // indents and spacing standards. these probably need to be modified + // per platform as well, since macosx is so huge, windows is smaller, + // and linux is all over the map + + static final int GUI_BIG = 13; + static final int GUI_BETWEEN = 10; + static final int GUI_SMALL = 6; + + + + // data model + + static Hashtable table = new Hashtable();; + static File preferencesFile; + + + static protected void init(String commandLinePrefs) { + + + } + + + public Preferences() { + + } + + // ................................................................. + + // ................................................................. + + // ................................................................. + + // ................................................................. + + + + static public String get(String attribute) { + return (String) table.get(attribute); + } + + static public void set(String attribute, String value) { + table.put(attribute, value); + } + + + static public boolean getBoolean(String attribute) { + String value = get(attribute); + return (new Boolean(value)).booleanValue(); + } + + + static public void setBoolean(String attribute, boolean value) { + set(attribute, value ? "true" : "false"); + } + + + static public int getInteger(String attribute) { + return Integer.parseInt(get(attribute)); + } + + + static public void setInteger(String key, int value) { + set(key, String.valueOf(value)); + } + +} diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/processing/app/Serial.java b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/processing/app/Serial.java new file mode 100644 index 0000000..04566a7 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/processing/app/Serial.java @@ -0,0 +1,527 @@ +/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + PSerial - class for serial port goodness + Part of the Processing project - http://processing.org + + Copyright (c) 2004 Ben Fry & Casey Reas + + 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. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA +*/ + +package processing.app; +//import processing.core.*; + + +import java.io.*; +import java.text.MessageFormat; +import java.util.*; +import jssc.SerialPort; +import jssc.SerialPortEvent; +import jssc.SerialPortEventListener; +import jssc.SerialPortException; +import jssc.SerialPortList; +import processing.app.debug.MessageConsumer; + + +public class Serial implements SerialPortEventListener { + + //PApplet parent; + + // properties can be passed in for default values + // otherwise defaults to 9600 N81 + + // these could be made static, which might be a solution + // for the classloading problem.. because if code ran again, + // the static class would have an object that could be closed + + SerialPort port; + + int rate; + int parity; + int databits; + int stopbits; + boolean monitor = false; + + // read buffer and streams + + InputStream input; + OutputStream output; + + byte buffer[] = new byte[32768]; + int bufferIndex; + int bufferLast; + + MessageConsumer consumer; + + public Serial(boolean monitor) throws SerialException { + this(Preferences.get("serial.port"), + Preferences.getInteger("serial.debug_rate"), + Preferences.get("serial.parity").charAt(0), + Preferences.getInteger("serial.databits"), + new Float(Preferences.get("serial.stopbits")).floatValue()); + this.monitor = monitor; + } + + public Serial() throws SerialException { + this(Preferences.get("serial.port"), + Preferences.getInteger("serial.debug_rate"), + Preferences.get("serial.parity").charAt(0), + Preferences.getInteger("serial.databits"), + new Float(Preferences.get("serial.stopbits")).floatValue()); + } + + public Serial(int irate) throws SerialException { + this(Preferences.get("serial.port"), irate, + Preferences.get("serial.parity").charAt(0), + Preferences.getInteger("serial.databits"), + new Float(Preferences.get("serial.stopbits")).floatValue()); + } + + public Serial(String iname, int irate) throws SerialException { + this(iname, irate, Preferences.get("serial.parity").charAt(0), + Preferences.getInteger("serial.databits"), + new Float(Preferences.get("serial.stopbits")).floatValue()); + } + + public Serial(String iname) throws SerialException { + this(iname, Preferences.getInteger("serial.debug_rate"), + Preferences.get("serial.parity").charAt(0), + Preferences.getInteger("serial.databits"), + new Float(Preferences.get("serial.stopbits")).floatValue()); + } + + public Serial(String iname, int irate, + char iparity, int idatabits, float istopbits) + throws SerialException { + //if (port != null) port.close(); + //this.parent = parent; + //parent.attach(this); + + this.rate = irate; + + parity = SerialPort.PARITY_NONE; + if (iparity == 'E') parity = SerialPort.PARITY_EVEN; + if (iparity == 'O') parity = SerialPort.PARITY_ODD; + + this.databits = idatabits; + + stopbits = SerialPort.STOPBITS_1; + if (istopbits == 1.5f) stopbits = SerialPort.STOPBITS_1_5; + if (istopbits == 2) stopbits = SerialPort.STOPBITS_2; + + try { + port = new SerialPort(iname); + port.openPort(); + port.setParams(rate, databits, stopbits, parity, true, true); + port.addEventListener(this); + } catch (Exception e) { + throw new SerialException(MessageFormat.format("Error opening serial port ''{0}''.", iname), e); + } + + if (port == null) { + throw new SerialException("Serial port '" + iname + "' not found. Did you select the right one from the Tools > Serial Port menu?"); + } + } + + + public void setup() { + //parent.registerCall(this, DISPOSE); + } + + public void dispose() throws IOException { + if (port != null) { + try { + if (port.isOpened()) { + port.closePort(); // close the port + } + } catch (SerialPortException e) { + throw new IOException(e); + } finally { + port = null; + } + } + } + + public void addListener(MessageConsumer consumer) { + this.consumer = consumer; + } + + public synchronized void serialEvent(SerialPortEvent serialEvent) { + if (serialEvent.isRXCHAR()) { + try { + byte[] buf = port.readBytes(serialEvent.getEventValue()); + if (buf.length > 0) { + if (bufferLast == buffer.length) { + byte temp[] = new byte[bufferLast << 1]; + System.arraycopy(buffer, 0, temp, 0, bufferLast); + buffer = temp; + } + if (monitor) { + System.out.print(new String(buf)); + } + if (this.consumer != null) { + this.consumer.message(new String(buf)); + } + } + } catch (SerialPortException e) { + errorMessage("serialEvent", e); + } + } + } + + + /** + * Returns the number of bytes that have been read from serial + * and are waiting to be dealt with by the user. + */ + public synchronized int available() { + return (bufferLast - bufferIndex); + } + + + /** + * Ignore all the bytes read so far and empty the buffer. + */ + public synchronized void clear() { + bufferLast = 0; + bufferIndex = 0; + } + + + /** + * Returns a number between 0 and 255 for the next byte that's + * waiting in the buffer. + * Returns -1 if there was no byte (although the user should + * first check available() to see if things are ready to avoid this) + */ + public synchronized int read() { + if (bufferIndex == bufferLast) return -1; + + int outgoing = buffer[bufferIndex++] & 0xff; + if (bufferIndex == bufferLast) { // rewind + bufferIndex = 0; + bufferLast = 0; + } + return outgoing; + } + + + /** + * Returns the next byte in the buffer as a char. + * Returns -1, or 0xffff, if nothing is there. + */ + public synchronized char readChar() { + if (bufferIndex == bufferLast) return (char)(-1); + return (char) read(); + } + + + /** + * Return a byte array of anything that's in the serial buffer. + * Not particularly memory/speed efficient, because it creates + * a byte array on each read, but it's easier to use than + * readBytes(byte b[]) (see below). + */ + public synchronized byte[] readBytes() { + if (bufferIndex == bufferLast) return null; + + int length = bufferLast - bufferIndex; + byte outgoing[] = new byte[length]; + System.arraycopy(buffer, bufferIndex, outgoing, 0, length); + + bufferIndex = 0; // rewind + bufferLast = 0; + return outgoing; + } + + + /** + * Grab whatever is in the serial buffer, and stuff it into a + * byte buffer passed in by the user. This is more memory/time + * efficient than readBytes() returning a byte[] array. + *

+ * Returns an int for how many bytes were read. If more bytes + * are available than can fit into the byte array, only those + * that will fit are read. + */ + public synchronized int readBytes(byte outgoing[]) { + if (bufferIndex == bufferLast) return 0; + + int length = bufferLast - bufferIndex; + if (length > outgoing.length) length = outgoing.length; + System.arraycopy(buffer, bufferIndex, outgoing, 0, length); + + bufferIndex += length; + if (bufferIndex == bufferLast) { + bufferIndex = 0; // rewind + bufferLast = 0; + } + return length; + } + + + /** + * Reads from the serial port into a buffer of bytes up to and + * including a particular character. If the character isn't in + * the serial buffer, then 'null' is returned. + */ + public synchronized byte[] readBytesUntil(int interesting) { + if (bufferIndex == bufferLast) return null; + byte what = (byte)interesting; + + int found = -1; + for (int k = bufferIndex; k < bufferLast; k++) { + if (buffer[k] == what) { + found = k; + break; + } + } + if (found == -1) return null; + + int length = found - bufferIndex + 1; + byte outgoing[] = new byte[length]; + System.arraycopy(buffer, bufferIndex, outgoing, 0, length); + + bufferIndex = 0; // rewind + bufferLast = 0; + return outgoing; + } + + + /** + * Reads from the serial port into a buffer of bytes until a + * particular character. If the character isn't in the serial + * buffer, then 'null' is returned. + *

+ * If outgoing[] is not big enough, then -1 is returned, + * and an error message is printed on the console. + * If nothing is in the buffer, zero is returned. + * If 'interesting' byte is not in the buffer, then 0 is returned. + */ + public synchronized int readBytesUntil(int interesting, byte outgoing[]) { + if (bufferIndex == bufferLast) return 0; + byte what = (byte)interesting; + + int found = -1; + for (int k = bufferIndex; k < bufferLast; k++) { + if (buffer[k] == what) { + found = k; + break; + } + } + if (found == -1) return 0; + + int length = found - bufferIndex + 1; + if (length > outgoing.length) { + System.err.println("readBytesUntil() byte buffer is" + + " too small for the " + length + + " bytes up to and including char " + interesting); + return -1; + } + //byte outgoing[] = new byte[length]; + System.arraycopy(buffer, bufferIndex, outgoing, 0, length); + + bufferIndex += length; + if (bufferIndex == bufferLast) { + bufferIndex = 0; // rewind + bufferLast = 0; + } + return length; + } + + + /** + * Return whatever has been read from the serial port so far + * as a String. It assumes that the incoming characters are ASCII. + *

+ * If you want to move Unicode data, you can first convert the + * String to a byte stream in the representation of your choice + * (i.e. UTF8 or two-byte Unicode data), and send it as a byte array. + */ + public synchronized String readString() { + if (bufferIndex == bufferLast) return null; + return new String(readBytes()); + } + + + /** + * Combination of readBytesUntil and readString. See caveats in + * each function. Returns null if it still hasn't found what + * you're looking for. + *

+ * If you want to move Unicode data, you can first convert the + * String to a byte stream in the representation of your choice + * (i.e. UTF8 or two-byte Unicode data), and send it as a byte array. + */ + public synchronized String readStringUntil(int interesting) { + byte b[] = readBytesUntil(interesting); + if (b == null) return null; + return new String(b); + } + + + /** + * This will handle both ints, bytes and chars transparently. + */ + public void write(int what) { // will also cover char + try { + port.writeInt(what & 0xff); + } catch (SerialPortException e) { + errorMessage("write", e); + } + } + + + public void write(byte bytes[]) { + try { + port.writeBytes(bytes); + } catch (SerialPortException e) { + errorMessage("write", e); + } + } + + + /** + * Write a String to the output. Note that this doesn't account + * for Unicode (two bytes per char), nor will it send UTF8 + * characters.. It assumes that you mean to send a byte buffer + * (most often the case for networking and serial i/o) and + * will only use the bottom 8 bits of each char in the string. + * (Meaning that internally it uses String.getBytes) + *

+ * If you want to move Unicode data, you can first convert the + * String to a byte stream in the representation of your choice + * (i.e. UTF8 or two-byte Unicode data), and send it as a byte array. + */ + public void write(String what) { + write(what.getBytes()); + } + + public void setDTR(boolean state) { + try { + port.setDTR(state); + } catch (SerialPortException e) { + errorMessage("setDTR", e); + } + } + + public void setRTS(boolean state) { + try { + port.setRTS(state); + } catch (SerialPortException e) { + errorMessage("setRTS", e); + } + } + + static public List list() { + return Arrays.asList(SerialPortList.getPortNames()); + } + + + /** + * General error reporting, all corraled here just in case + * I think of something slightly more intelligent to do. + */ + static public void errorMessage(String where, Throwable e) { + System.err.println("Error inside Serial." + where + "()"); + e.printStackTrace(); + } +} + + + /* + class SerialMenuListener implements ItemListener { + //public SerialMenuListener() { } + + public void itemStateChanged(ItemEvent e) { + int count = serialMenu.getItemCount(); + for (int i = 0; i < count; i++) { + ((CheckboxMenuItem)serialMenu.getItem(i)).setState(false); + } + CheckboxMenuItem item = (CheckboxMenuItem)e.getSource(); + item.setState(true); + String name = item.getLabel(); + //System.out.println(item.getLabel()); + PdeBase.properties.put("serial.port", name); + //System.out.println("set to " + get("serial.port")); + } + } + */ + + + /* + protected Vector buildPortList() { + // get list of names for serial ports + // have the default port checked (if present) + Vector list = new Vector(); + + //SerialMenuListener listener = new SerialMenuListener(); + boolean problem = false; + + // if this is failing, it may be because + // lib/javax.comm.properties is missing. + // java is weird about how it searches for java.comm.properties + // so it tends to be very fragile. i.e. quotes in the CLASSPATH + // environment variable will hose things. + try { + //System.out.println("building port list"); + Enumeration portList = CommPortIdentifier.getPortIdentifiers(); + while (portList.hasMoreElements()) { + CommPortIdentifier portId = + (CommPortIdentifier) portList.nextElement(); + //System.out.println(portId); + + if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) { + //if (portId.getName().equals(port)) { + String name = portId.getName(); + //CheckboxMenuItem mi = + //new CheckboxMenuItem(name, name.equals(defaultName)); + + //mi.addItemListener(listener); + //serialMenu.add(mi); + list.addElement(name); + } + } + } catch (UnsatisfiedLinkError e) { + e.printStackTrace(); + problem = true; + + } catch (Exception e) { + System.out.println("exception building serial menu"); + e.printStackTrace(); + } + + //if (serialMenu.getItemCount() == 0) { + //System.out.println("dimming serial menu"); + //serialMenu.setEnabled(false); + //} + + // only warn them if this is the first time + if (problem && PdeBase.firstTime) { + JOptionPane.showMessageDialog(this, //frame, + "Serial port support not installed.\n" + + "Check the readme for instructions\n" + + "if you need to use the serial port. ", + "Serial Port Warning", + JOptionPane.WARNING_MESSAGE); + } + return list; + } + */ + + + diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/processing/app/SerialException.java b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/processing/app/SerialException.java new file mode 100644 index 0000000..525c240 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/processing/app/SerialException.java @@ -0,0 +1,39 @@ +/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Copyright (c) 2007 David A. Mellis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +package processing.app; + +public class SerialException extends Exception { + public SerialException() { + super(); + } + + public SerialException(String message) { + super(message); + } + + public SerialException(String message, Throwable cause) { + super(message, cause); + } + + public SerialException(Throwable cause) { + super(cause); + } +} diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/processing/app/debug/MessageConsumer.java b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/processing/app/debug/MessageConsumer.java new file mode 100644 index 0000000..5e20429 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/processing/app/debug/MessageConsumer.java @@ -0,0 +1,42 @@ +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2004-06 Ben Fry and Casey Reas + Copyright (c) 2001-04 Massachusetts Institute of Technology + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +package processing.app.debug; + + +/** + * Interface for dealing with parser/compiler output. + *

+ * Different instances of MessageStream need to do different things with + * messages. In particular, a stream instance used for parsing output from + * the compiler compiler has to interpret its messages differently than one + * parsing output from the runtime. + *

+ * Classes which consume messages and do something with them + * should implement this interface. + */ +public interface MessageConsumer { + + public void message(String s); + +} diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/processing/app/debug/MessageSiphon.java b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/processing/app/debug/MessageSiphon.java new file mode 100644 index 0000000..26901c3 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/processing/app/debug/MessageSiphon.java @@ -0,0 +1,104 @@ +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2004-06 Ben Fry and Casey Reas + Copyright (c) 2001-04 Massachusetts Institute of Technology + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +package processing.app.debug; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.SocketException; + +/** + * Slurps up messages from compiler. + */ +public class MessageSiphon implements Runnable { + + private final BufferedReader streamReader; + private final MessageConsumer consumer; + + private Thread thread; + private boolean canRun; + + public MessageSiphon(InputStream stream, MessageConsumer consumer) { + this.streamReader = new BufferedReader(new InputStreamReader(stream)); + this.consumer = consumer; + this.canRun = true; + + thread = new Thread(this); + // don't set priority too low, otherwise exceptions won't + // bubble up in time (i.e. compile errors have a weird delay) + //thread.setPriority(Thread.MIN_PRIORITY); + thread.setPriority(Thread.MAX_PRIORITY - 1); + thread.start(); + } + + + public void run() { + try { + // process data until we hit EOF; this will happily block + // (effectively sleeping the thread) until new data comes in. + // when the program is finally done, null will come through. + // + String currentLine; + while (canRun && (currentLine = streamReader.readLine()) != null) { + // \n is added again because readLine() strips it out + //EditorConsole.systemOut.println("messaging in"); + consumer.message(currentLine + "\n"); + //EditorConsole.systemOut.println("messaging out"); + } + //EditorConsole.systemOut.println("messaging thread done"); + } catch (NullPointerException npe) { + // Fairly common exception during shutdown + } catch (SocketException e) { + // socket has been close while we were wainting for data. nothing to see here, move along + } catch (Exception e) { + // On Linux and sometimes on Mac OS X, a "bad file descriptor" + // message comes up when closing an applet that's run externally. + // That message just gets supressed here.. + String mess = e.getMessage(); + if ((mess != null) && + (mess.indexOf("Bad file descriptor") != -1)) { + //if (e.getMessage().indexOf("Bad file descriptor") == -1) { + //System.err.println("MessageSiphon err " + e); + //e.printStackTrace(); + } else { + e.printStackTrace(); + } + } finally { + thread = null; + } + } + + // Wait until the MessageSiphon thread is complete. + public void join() throws java.lang.InterruptedException { + // Grab a temp copy in case another thread nulls the "thread" + // member variable + Thread t = thread; + if (t != null) t.join(); + } + + public void stop() { + this.canRun = false; + } + +} diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/processing/app/debug/RunnerException.java b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/processing/app/debug/RunnerException.java new file mode 100644 index 0000000..0a67d1e --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/processing/app/debug/RunnerException.java @@ -0,0 +1,161 @@ +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2004-08 Ben Fry and Casey Reas + Copyright (c) 2001-04 Massachusetts Institute of Technology + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +package processing.app.debug; + + +/** + * An exception with a line number attached that occurs + * during either compile time or run time. + */ +@SuppressWarnings("serial") +public class RunnerException extends Exception { + protected String message; + protected int codeIndex; + protected int codeLine; + protected int codeColumn; + protected boolean showStackTrace; + + + public RunnerException(String message) { + this(message, true); + } + + public RunnerException(String message, boolean showStackTrace) { + this(message, -1, -1, -1, showStackTrace); + } + + public RunnerException(String message, int file, int line) { + this(message, file, line, -1, true); + } + + + public RunnerException(String message, int file, int line, int column) { + this(message, file, line, column, true); + } + + + public RunnerException(String message, int file, int line, int column, + boolean showStackTrace) { + this.message = message; + this.codeIndex = file; + this.codeLine = line; + this.codeColumn = column; + this.showStackTrace = showStackTrace; + } + + + public RunnerException(Exception e) { + super(e); + this.showStackTrace = true; + } + + /** + * Override getMessage() in Throwable, so that I can set + * the message text outside the constructor. + */ + public String getMessage() { + return message; + } + + + public void setMessage(String message) { + this.message = message; + } + + + public int getCodeIndex() { + return codeIndex; + } + + + public void setCodeIndex(int index) { + codeIndex = index; + } + + + public boolean hasCodeIndex() { + return codeIndex != -1; + } + + + public int getCodeLine() { + return codeLine; + } + + + public void setCodeLine(int line) { + this.codeLine = line; + } + + + public boolean hasCodeLine() { + return codeLine != -1; + } + + + public void setCodeColumn(int column) { + this.codeColumn = column; + } + + + public int getCodeColumn() { + return codeColumn; + } + + + public void showStackTrace() { + showStackTrace = true; + } + + + public void hideStackTrace() { + showStackTrace = false; + } + + + /** + * Nix the java.lang crap out of an exception message + * because it scares the children. + *

+ * This function must be static to be used with super() + * in each of the constructors above. + */ + /* + static public final String massage(String msg) { + if (msg.indexOf("java.lang.") == 0) { + //int dot = msg.lastIndexOf('.'); + msg = msg.substring("java.lang.".length()); + } + return msg; + //return (dot == -1) ? msg : msg.substring(dot+1); + } + */ + + + public void printStackTrace() { + if (showStackTrace) { + super.printStackTrace(); + } + } +} diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/processing/app/helpers/ProcessUtils.java b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/processing/app/helpers/ProcessUtils.java new file mode 100644 index 0000000..c023f58 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/maple_loader/src/processing/app/helpers/ProcessUtils.java @@ -0,0 +1,32 @@ +package processing.app.helpers; + +//import processing.app.Base; + +import java.io.IOException; +import java.util.Map; + +import processing.app.Base; + +public class ProcessUtils { + + public static Process exec(String[] command) throws IOException { + // No problems on linux and mac + if (!Base.isWindows()) { + return Runtime.getRuntime().exec(command); + } + + // Brutal hack to workaround windows command line parsing. + // http://stackoverflow.com/questions/5969724/java-runtime-exec-fails-to-escape-characters-properly + // http://msdn.microsoft.com/en-us/library/a1y7w461.aspx + // http://bugs.sun.com/view_bug.do?bug_id=6468220 + // http://bugs.sun.com/view_bug.do?bug_id=6518827 + String[] cmdLine = new String[command.length]; + for (int i = 0; i < command.length; i++) + cmdLine[i] = command[i].replace("\"", "\\\""); + + ProcessBuilder pb = new ProcessBuilder(cmdLine); + Map env = pb.environment(); + env.put("CYGWIN", "nodosfilewarning"); + return pb.start(); + } +} diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/AUTHORS b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/AUTHORS new file mode 100644 index 0000000..d096f22 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/AUTHORS @@ -0,0 +1,19 @@ +Authors ordered by first contribution. + +Geoffrey McRae +Bret Olmsted +Tormod Volden +Jakob Malm +Reuben Dowle +Matthias Kubisch +Paul Fertser +Daniel Strnad +Jérémie Rapin +Christian Pointner +Mats Erik Andersson +Alexey Borovik +Antonio Borneo +Armin van der Togt +Brian Silverman +Georg Hofmann +Luis Rodrigues diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/Android.mk b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/Android.mk new file mode 100644 index 0000000..7be3d00 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/Android.mk @@ -0,0 +1,20 @@ +TOP_LOCAL_PATH := $(call my-dir) + +include $(call all-named-subdir-makefiles, parsers) + +LOCAL_PATH := $(TOP_LOCAL_PATH) + +include $(CLEAR_VARS) +LOCAL_MODULE := stm32flash +LOCAL_SRC_FILES := \ + dev_table.c \ + i2c.c \ + init.c \ + main.c \ + port.c \ + serial_common.c \ + serial_platform.c \ + stm32.c \ + utils.c +LOCAL_STATIC_LIBRARIES := libparsers +include $(BUILD_EXECUTABLE) diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/HOWTO b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/HOWTO new file mode 100644 index 0000000..d8f32eb --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/HOWTO @@ -0,0 +1,35 @@ +Add new interfaces: +===================================================================== +Current version 0.4 supports the following interfaces: +- UART Windows (either "COMn" and "\\.\COMn"); +- UART posix/Linux (e.g. "/dev/ttyUSB0"); +- I2C Linux through standard driver "i2c-dev" (e.g. "/dev/i2c-n"). + +Starting from version 0.4, the back-end of stm32flash is modular and +ready to be expanded to support new interfaces. +I'm planning adding SPI on Linux through standard driver "spidev". +You are invited to contribute with more interfaces. + +To add a new interface you need to add a new file, populate the struct +port_interface (check at the end of files i2c.c, serial_posix.c and +serial_w32.c) and provide the relative functions to operate on the +interface: open/close, read/write, get_cfg_str and the optional gpio. +The include the new drive in Makefile and register the new struct +port_interface in file port.c in struct port_interface *ports[]. + +There are several USB-I2C adapter in the market, each providing its +own libraries to communicate with the I2C bus. +Could be interesting to provide as back-end a bridge between stm32flash +and such libraries (I have no plan on this item). + + +Add new STM32 devices: +===================================================================== +Add a new line in file dev_table.c, in table devices[]. +The fields of the table are listed in stm32.h, struct stm32_dev. + + +Cross compile on Linux host for Windows target with MinGW: +===================================================================== +I'm using a 64 bit Arch Linux machines, and I usually run: + make CC=x86_64-w64-mingw32-gcc AR=x86_64-w64-mingw32-ar diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/I2C.txt b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/I2C.txt new file mode 100644 index 0000000..4c05ff6 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/I2C.txt @@ -0,0 +1,94 @@ +About I2C back-end communication in stm32flash +========================================================================== + +Starting from version v0.4, beside the serial communication port, +stm32flash adds support for I2C port to talk with STM32 bootloader. + +The current I2C back-end supports only the API provided by Linux kernel +driver "i2c-dev", so only I2C controllers with Linux kernel driver can be +used. +In Linux source code, most of the drivers for I2C and SMBUS controllers +are in + ./drivers/i2c/busses/ +Only I2C is supported by STM32 bootloader, so check the section below +about SMBUS. +No I2C support for Windows is available in stm32flash v0.4. + +Thanks to the new modular back-end, stm32flash can be easily extended to +support new back-ends and API. Check HOWTO file in stm32flash source code +for details. + +In the market there are several USB-to-I2C dongles; most of them are not +supported by kernel drivers. Manufacturer provide proprietary userspace +libraries using not standardized API. +These API and dongles could be supported in feature versions. + +There are currently 3 versions of STM32 bootloader for I2C communications: +- v1.0 using I2C clock stretching synchronization between host and STM32; +- v1.1 superset of v1.0, adds non stretching commands; +- v1.2 superset of v1.1, adds CRC command and compatibility with i2cdetect. +Details in ST application note AN2606. +All the bootloaders above are tested and working with stm32flash. + + +SMBUS controllers +========================================================================== + +Almost 50% of the drivers in Linux source code folder + ./drivers/i2c/busses/ +are for controllers that "only" support SMBUS protocol. They can NOT +operate with STM32 bootloader. +To identify if your controller supports I2C, use command: + i2cdetect -F n +where "n" is the number of the I2C interface (e.g. n=3 for "/dev/i2c-3"). +Controllers that supports I2C will report + I2C yes +Controller that support both I2C and SMBUS are ok. + +If you are interested on details about SMBUS protocol, you can download +the current specs from + http://smbus.org/specs/smbus20.pdf +and you can read the files in Linux source code + ./Documentation/i2c/i2c-protocol + ./Documentation/i2c/smbus-protocol + + +About bootloader v1.0 +========================================================================== + +Version v1.0 can have issues with some I2C controllers due to use of clock +stretching during commands that require long operations, like flash erase +and programming. + +Clock stretching is a technique to synchronize host and I2C device. When +I2C device wants to force a delay in the communication, it push "low" the +I2C clock; the I2C controller detects it and waits until I2C clock returns +"high". +Most I2C controllers set a "timeout" for clock stretching, ranging from +few milli-seconds to seconds depending on specific HW or SW driver. + +It is possible that the timeout in your I2C controller is smaller than the +delay required for flash erase or programming. In this case the I2C +controller will timeout and report error to stm32flash. +There is no possibility for stm32flash to retry, so it can only signal the +error and exit. + +To by-pass the issue with bootloader v1.0 you can modify the kernel driver +of your I2C controller. Not an easy job, since every controller has its own +way to handle the timeout. + +In my case I'm using the I2C controller integrated in the VGA port of my +laptop HP EliteBook 8460p. I built the 0.25$ VGA-to-I2C adapter reported in + http://www.paintyourdragon.com/?p=43 +To change the timeout of the I2C controller I had to modify the kernel file + drivers/gpu/drm/radeon/radeon_i2c.c +line 969 +- i2c->bit.timeout = usecs_to_jiffies(2200); /* from VESA */ ++ i2c->bit.timeout = msecs_to_jiffies(5000); /* 5s for STM32 */ +and recompile it. +Then + $> modprobe i2c-dev + $> chmod 666 /dev/i2c-7 + #> stm32flash -a 0x39 /dev/i2c-7 + +2014-09-16 Antonio Borneo diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/Makefile b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/Makefile new file mode 100644 index 0000000..0328d55 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/Makefile @@ -0,0 +1,38 @@ +PREFIX = /usr/local +CFLAGS += -Wall -g + +INSTALL = install + +OBJS = dev_table.o \ + i2c.o \ + init.o \ + main.o \ + port.o \ + serial_common.o \ + serial_platform.o \ + stm32.o \ + utils.o + +LIBOBJS = parsers/parsers.a + +all: stm32flash + +serial_platform.o: serial_posix.c serial_w32.c + +parsers/parsers.a: + cd parsers && $(MAKE) parsers.a + +stm32flash: $(OBJS) $(LIBOBJS) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBOBJS) + +clean: + rm -f $(OBJS) stm32flash + cd parsers && $(MAKE) $@ + +install: all + $(INSTALL) -d $(DESTDIR)$(PREFIX)/bin + $(INSTALL) -m 755 stm32flash $(DESTDIR)$(PREFIX)/bin + $(INSTALL) -d $(DESTDIR)$(PREFIX)/share/man/man1 + $(INSTALL) -m 644 stm32flash.1 $(DESTDIR)$(PREFIX)/share/man/man1 + +.PHONY: all clean install diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/TODO b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/TODO new file mode 100644 index 0000000..41df614 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/TODO @@ -0,0 +1,7 @@ + +stm32: +- Add support for variable page size + +AUTHORS: +- Add contributors from Geoffrey's commits + diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/dev_table.c b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/dev_table.c new file mode 100644 index 0000000..399cd9d --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/dev_table.c @@ -0,0 +1,70 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + Copyright (C) 2014 Antonio Borneo + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "stm32.h" + +/* + * Device table, corresponds to the "Bootloader device-dependant parameters" + * table in ST document AN2606. + * Note that the option bytes upper range is inclusive! + */ +const stm32_dev_t devices[] = { + /* F0 */ + {0x440, "STM32F051xx" , 0x20001000, 0x20002000, 0x08000000, 0x08010000, 4, 1024, 0x1FFFF800, 0x1FFFF80B, 0x1FFFEC00, 0x1FFFF800}, + {0x444, "STM32F030/F031" , 0x20001000, 0x20002000, 0x08000000, 0x08010000, 4, 1024, 0x1FFFF800, 0x1FFFF80B, 0x1FFFEC00, 0x1FFFF800}, + {0x445, "STM32F042xx" , 0x20001800, 0x20001800, 0x08000000, 0x08008000, 4, 1024, 0x1FFFF800, 0x1FFFF80F, 0x1FFFC400, 0x1FFFF800}, + {0x448, "STM32F072xx" , 0x20001800, 0x20004000, 0x08000000, 0x08020000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFC800, 0x1FFFF800}, + /* F1 */ + {0x412, "Low-density" , 0x20000200, 0x20002800, 0x08000000, 0x08008000, 4, 1024, 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800}, + {0x410, "Medium-density" , 0x20000200, 0x20005000, 0x08000000, 0x08020000, 4, 1024, 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800}, + {0x414, "High-density" , 0x20000200, 0x20010000, 0x08000000, 0x08080000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800}, + {0x420, "Medium-density VL" , 0x20000200, 0x20002000, 0x08000000, 0x08020000, 4, 1024, 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800}, + {0x428, "High-density VL" , 0x20000200, 0x20008000, 0x08000000, 0x08080000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800}, + {0x418, "Connectivity line" , 0x20001000, 0x20010000, 0x08000000, 0x08040000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFB000, 0x1FFFF800}, + {0x430, "XL-density" , 0x20000800, 0x20018000, 0x08000000, 0x08100000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFE000, 0x1FFFF800}, + /* Note that F2 and F4 devices have sectors of different page sizes + and only the first sectors (of one page size) are included here */ + /* F2 */ + {0x411, "STM32F2xx" , 0x20002000, 0x20020000, 0x08000000, 0x08100000, 4, 16384, 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF77DF}, + /* F3 */ + {0x432, "STM32F373/8" , 0x20001400, 0x20008000, 0x08000000, 0x08040000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFD800, 0x1FFFF800}, + {0x422, "F302xB/303xB/358" , 0x20001400, 0x20010000, 0x08000000, 0x08040000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFD800, 0x1FFFF800}, + {0x439, "STM32F302x4(6/8)" , 0x20001800, 0x20004000, 0x08000000, 0x08040000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFD800, 0x1FFFF800}, + {0x438, "F303x4/334/328" , 0x20001800, 0x20003000, 0x08000000, 0x08040000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFD800, 0x1FFFF800}, + /* F4 */ + {0x413, "STM32F40/1" , 0x20002000, 0x20020000, 0x08000000, 0x08100000, 4, 16384, 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF77DF}, + /* 0x419 is also used for STM32F429/39 but with other bootloader ID... */ + {0x419, "STM32F427/37" , 0x20002000, 0x20030000, 0x08000000, 0x08100000, 4, 16384, 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF77FF}, + {0x423, "STM32F401xB(C)" , 0x20003000, 0x20010000, 0x08000000, 0x08100000, 4, 16384, 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF77FF}, + {0x433, "STM32F401xD(E)" , 0x20003000, 0x20018000, 0x08000000, 0x08100000, 4, 16384, 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF77FF}, + /* L0 */ + {0x417, "L05xxx/06xxx" , 0x20001000, 0x20002000, 0x08000000, 0x08010000, 32, 128, 0x1FF80000, 0x1FF8000F, 0x1FF00000, 0x1FF01000}, + /* L1 */ + {0x416, "L1xxx6(8/B)" , 0x20000800, 0x20004000, 0x08000000, 0x08020000, 16, 256, 0x1FF80000, 0x1FF8000F, 0x1FF00000, 0x1FF01000}, + {0x429, "L1xxx6(8/B)A" , 0x20001000, 0x20008000, 0x08000000, 0x08020000, 16, 256, 0x1FF80000, 0x1FF8000F, 0x1FF00000, 0x1FF01000}, + {0x427, "L1xxxC" , 0x20001000, 0x20008000, 0x08000000, 0x08020000, 16, 256, 0x1FF80000, 0x1FF8000F, 0x1FF00000, 0x1FF02000}, + {0x436, "L1xxxD" , 0x20001000, 0x2000C000, 0x08000000, 0x08060000, 16, 256, 0x1ff80000, 0x1ff8000F, 0x1FF00000, 0x1FF02000}, + {0x437, "L1xxxE" , 0x20001000, 0x20014000, 0x08000000, 0x08060000, 16, 256, 0x1ff80000, 0x1ff8000F, 0x1FF00000, 0x1FF02000}, + /* These are not (yet) in AN2606: */ + {0x641, "Medium_Density PL" , 0x20000200, 0x00005000, 0x08000000, 0x08020000, 4, 1024, 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800}, + {0x9a8, "STM32W-128K" , 0x20000200, 0x20002000, 0x08000000, 0x08020000, 1, 1024, 0, 0, 0, 0}, + {0x9b0, "STM32W-256K" , 0x20000200, 0x20004000, 0x08000000, 0x08040000, 1, 2048, 0, 0, 0, 0}, + {0x0} +}; diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/gpl-2.0.txt b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/gpl-2.0.txt new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/gpl-2.0.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/i2c.c b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/i2c.c new file mode 100644 index 0000000..10e6bb1 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/i2c.c @@ -0,0 +1,209 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2014 Antonio Borneo + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "serial.h" +#include "port.h" + + +#if !defined(__linux__) + +static port_err_t i2c_open(struct port_interface *port, + struct port_options *ops) +{ + return PORT_ERR_NODEV; +} + +struct port_interface port_i2c = { + .name = "i2c", + .open = i2c_open, +}; + +#else + +#ifdef __ANDROID__ +#define I2C_SLAVE 0x0703 /* Use this slave address */ +#define I2C_FUNCS 0x0705 /* Get the adapter functionality mask */ +/* To determine what functionality is present */ +#define I2C_FUNC_I2C 0x00000001 +#else +#include +#include +#endif + +#include + +struct i2c_priv { + int fd; + int addr; +}; + +static port_err_t i2c_open(struct port_interface *port, + struct port_options *ops) +{ + struct i2c_priv *h; + int fd, addr, ret; + unsigned long funcs; + + /* 1. check device name match */ + if (strncmp(ops->device, "/dev/i2c-", strlen("/dev/i2c-"))) + return PORT_ERR_NODEV; + + /* 2. check options */ + addr = ops->bus_addr; + if (addr < 0x03 || addr > 0x77) { + fprintf(stderr, "I2C address out of range [0x03-0x77]\n"); + return PORT_ERR_UNKNOWN; + } + + /* 3. open it */ + h = calloc(sizeof(*h), 1); + if (h == NULL) { + fprintf(stderr, "End of memory\n"); + return PORT_ERR_UNKNOWN; + } + fd = open(ops->device, O_RDWR); + if (fd < 0) { + fprintf(stderr, "Unable to open special file \"%s\"\n", + ops->device); + free(h); + return PORT_ERR_UNKNOWN; + } + + /* 3.5. Check capabilities */ + ret = ioctl(fd, I2C_FUNCS, &funcs); + if (ret < 0) { + fprintf(stderr, "I2C ioctl(funcs) error %d\n", errno); + close(fd); + free(h); + return PORT_ERR_UNKNOWN; + } + if ((funcs & I2C_FUNC_I2C) == 0) { + fprintf(stderr, "Error: controller is not I2C, only SMBUS.\n"); + close(fd); + free(h); + return PORT_ERR_UNKNOWN; + } + + /* 4. set options */ + ret = ioctl(fd, I2C_SLAVE, addr); + if (ret < 0) { + fprintf(stderr, "I2C ioctl(slave) error %d\n", errno); + close(fd); + free(h); + return PORT_ERR_UNKNOWN; + } + + h->fd = fd; + h->addr = addr; + port->private = h; + return PORT_ERR_OK; +} + +static port_err_t i2c_close(struct port_interface *port) +{ + struct i2c_priv *h; + + h = (struct i2c_priv *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + close(h->fd); + free(h); + port->private = NULL; + return PORT_ERR_OK; +} + +static port_err_t i2c_read(struct port_interface *port, void *buf, + size_t nbyte) +{ + struct i2c_priv *h; + int ret; + + h = (struct i2c_priv *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + ret = read(h->fd, buf, nbyte); + if (ret != nbyte) + return PORT_ERR_UNKNOWN; + return PORT_ERR_OK; +} + +static port_err_t i2c_write(struct port_interface *port, void *buf, + size_t nbyte) +{ + struct i2c_priv *h; + int ret; + + h = (struct i2c_priv *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + ret = write(h->fd, buf, nbyte); + if (ret != nbyte) + return PORT_ERR_UNKNOWN; + return PORT_ERR_OK; +} + +static port_err_t i2c_gpio(struct port_interface *port, serial_gpio_t n, + int level) +{ + return PORT_ERR_OK; +} + +static const char *i2c_get_cfg_str(struct port_interface *port) +{ + struct i2c_priv *h; + static char str[11]; + + h = (struct i2c_priv *)port->private; + if (h == NULL) + return "INVALID"; + snprintf(str, sizeof(str), "addr 0x%2x", h->addr); + return str; +} + +static struct varlen_cmd i2c_cmd_get_reply[] = { + {0x10, 11}, + {0x11, 17}, + {0x12, 18}, + { /* sentinel */ } +}; + +struct port_interface port_i2c = { + .name = "i2c", + .flags = PORT_STRETCH_W, + .open = i2c_open, + .close = i2c_close, + .read = i2c_read, + .write = i2c_write, + .gpio = i2c_gpio, + .cmd_get_reply = i2c_cmd_get_reply, + .get_cfg_str = i2c_get_cfg_str, +}; + +#endif diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/init.c b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/init.c new file mode 100644 index 0000000..77a571b --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/init.c @@ -0,0 +1,219 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + Copyright (C) 2013 Antonio Borneo + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include "init.h" +#include "serial.h" +#include "stm32.h" +#include "port.h" + +struct gpio_list { + struct gpio_list *next; + int gpio; +}; + + +static int write_to(const char *filename, const char *value) +{ + int fd, ret; + + fd = open(filename, O_WRONLY); + if (fd < 0) { + fprintf(stderr, "Cannot open file \"%s\"\n", filename); + return 0; + } + ret = write(fd, value, strlen(value)); + if (ret < 0) { + fprintf(stderr, "Error writing in file \"%s\"\n", filename); + close(fd); + return 0; + } + close(fd); + return 1; +} + +#if !defined(__linux__) +static int drive_gpio(int n, int level, struct gpio_list **gpio_to_release) +{ + fprintf(stderr, "GPIO control only available in Linux\n"); + return 0; +} +#else +static int drive_gpio(int n, int level, struct gpio_list **gpio_to_release) +{ + char num[16]; /* sized to carry MAX_INT */ + char file[48]; /* sized to carry longest filename */ + struct stat buf; + struct gpio_list *new; + int ret; + + sprintf(file, "/sys/class/gpio/gpio%d/direction", n); + ret = stat(file, &buf); + if (ret) { + /* file miss, GPIO not exported yet */ + sprintf(num, "%d", n); + ret = write_to("/sys/class/gpio/export", num); + if (!ret) + return 0; + ret = stat(file, &buf); + if (ret) { + fprintf(stderr, "GPIO %d not available\n", n); + return 0; + } + new = (struct gpio_list *)malloc(sizeof(struct gpio_list)); + if (new == NULL) { + fprintf(stderr, "Out of memory\n"); + return 0; + } + new->gpio = n; + new->next = *gpio_to_release; + *gpio_to_release = new; + } + + return write_to(file, level ? "high" : "low"); +} +#endif + +static int release_gpio(int n) +{ + char num[16]; /* sized to carry MAX_INT */ + + sprintf(num, "%d", n); + return write_to("/sys/class/gpio/unexport", num); +} + +static int gpio_sequence(struct port_interface *port, const char *s, size_t l) +{ + struct gpio_list *gpio_to_release = NULL, *to_free; + int ret, level, gpio; + + ret = 1; + while (ret == 1 && *s && l > 0) { + if (*s == '-') { + level = 0; + s++; + l--; + } else + level = 1; + + if (isdigit(*s)) { + gpio = atoi(s); + while (isdigit(*s)) { + s++; + l--; + } + } else if (!strncmp(s, "rts", 3)) { + gpio = -GPIO_RTS; + s += 3; + l -= 3; + } else if (!strncmp(s, "dtr", 3)) { + gpio = -GPIO_DTR; + s += 3; + l -= 3; + } else if (!strncmp(s, "brk", 3)) { + gpio = -GPIO_BRK; + s += 3; + l -= 3; + } else { + fprintf(stderr, "Character \'%c\' is not a digit\n", *s); + ret = 0; + break; + } + + if (*s && (l > 0)) { + if (*s == ',') { + s++; + l--; + } else { + fprintf(stderr, "Character \'%c\' is not a separator\n", *s); + ret = 0; + break; + } + } + if (gpio < 0) + ret = (port->gpio(port, -gpio, level) == PORT_ERR_OK); + else + ret = drive_gpio(gpio, level, &gpio_to_release); + usleep(100000); + } + + while (gpio_to_release) { + release_gpio(gpio_to_release->gpio); + to_free = gpio_to_release; + gpio_to_release = gpio_to_release->next; + free(to_free); + } + usleep(500000); + return ret; +} + +static int gpio_bl_entry(struct port_interface *port, const char *seq) +{ + char *s; + + if (seq == NULL || seq[0] == ':') + return 1; + + s = strchr(seq, ':'); + if (s == NULL) + return gpio_sequence(port, seq, strlen(seq)); + + return gpio_sequence(port, seq, s - seq); +} + +static int gpio_bl_exit(struct port_interface *port, const char *seq) +{ + char *s; + + if (seq == NULL) + return 1; + + s = strchr(seq, ':'); + if (s == NULL || s[1] == '\0') + return 1; + + return gpio_sequence(port, s + 1, strlen(s + 1)); +} + +int init_bl_entry(struct port_interface *port, const char *seq) +{ + if (seq) + return gpio_bl_entry(port, seq); + + return 1; +} + +int init_bl_exit(stm32_t *stm, struct port_interface *port, const char *seq) +{ + if (seq) + return gpio_bl_exit(port, seq); + + if (stm32_reset_device(stm) != STM32_ERR_OK) + return 0; + return 1; +} diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/init.h b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/init.h new file mode 100644 index 0000000..6075b51 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/init.h @@ -0,0 +1,31 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + Copyright (C) 2013 Antonio Borneo + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _INIT_H +#define _INIT_H + +#include "stm32.h" +#include "port.h" + +int init_bl_entry(struct port_interface *port, const char *seq); +int init_bl_exit(stm32_t *stm, struct port_interface *port, const char *seq); + +#endif diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/main.c b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/main.c new file mode 100644 index 0000000..f081d61 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/main.c @@ -0,0 +1,774 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright 2010 Geoffrey McRae + Copyright 2011 Steve Markgraf + Copyright 2012 Tormod Volden + Copyright 2013 Antonio Borneo + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "init.h" +#include "utils.h" +#include "serial.h" +#include "stm32.h" +#include "parsers/parser.h" +#include "port.h" + +#include "parsers/binary.h" +#include "parsers/hex.h" + +#define VERSION "Arduino_STM32_0.9" + +/* device globals */ +stm32_t *stm = NULL; + +void *p_st = NULL; +parser_t *parser = NULL; + +/* settings */ +struct port_options port_opts = { + .device = NULL, + .baudRate = SERIAL_BAUD_57600, + .serial_mode = "8e1", + .bus_addr = 0, + .rx_frame_max = STM32_MAX_RX_FRAME, + .tx_frame_max = STM32_MAX_TX_FRAME, +}; +int rd = 0; +int wr = 0; +int wu = 0; +int rp = 0; +int ur = 0; +int eraseOnly = 0; +int crc = 0; +int npages = 0; +int spage = 0; +int no_erase = 0; +char verify = 0; +int retry = 10; +char exec_flag = 0; +uint32_t execute = 0; +char init_flag = 1; +char force_binary = 0; +char reset_flag = 0; +char *filename; +char *gpio_seq = NULL; +uint32_t start_addr = 0; +uint32_t readwrite_len = 0; + +/* functions */ +int parse_options(int argc, char *argv[]); +void show_help(char *name); + +static int is_addr_in_ram(uint32_t addr) +{ + return addr >= stm->dev->ram_start && addr < stm->dev->ram_end; +} + +static int is_addr_in_flash(uint32_t addr) +{ + return addr >= stm->dev->fl_start && addr < stm->dev->fl_end; +} + +static int flash_addr_to_page_floor(uint32_t addr) +{ + if (!is_addr_in_flash(addr)) + return 0; + + return (addr - stm->dev->fl_start) / stm->dev->fl_ps; +} + +static int flash_addr_to_page_ceil(uint32_t addr) +{ + if (!(addr >= stm->dev->fl_start && addr <= stm->dev->fl_end)) + return 0; + + return (addr + stm->dev->fl_ps - 1 - stm->dev->fl_start) + / stm->dev->fl_ps; +} + +static uint32_t flash_page_to_addr(int page) +{ + return stm->dev->fl_start + page * stm->dev->fl_ps; +} + +int main(int argc, char* argv[]) { + struct port_interface *port = NULL; + int ret = 1; + stm32_err_t s_err; + parser_err_t perr; + FILE *diag = stdout; + + fprintf(diag, "stm32flash " VERSION "\n\n"); + fprintf(diag, "http://github.com/rogerclarkmelbourne/arduino_stm32\n\n"); + if (parse_options(argc, argv) != 0) + goto close; + + if (rd && filename[0] == '-') { + diag = stderr; + } + + if (wr) { + /* first try hex */ + if (!force_binary) { + parser = &PARSER_HEX; + p_st = parser->init(); + if (!p_st) { + fprintf(stderr, "%s Parser failed to initialize\n", parser->name); + goto close; + } + } + + if (force_binary || (perr = parser->open(p_st, filename, 0)) != PARSER_ERR_OK) { + if (force_binary || perr == PARSER_ERR_INVALID_FILE) { + if (!force_binary) { + parser->close(p_st); + p_st = NULL; + } + + /* now try binary */ + parser = &PARSER_BINARY; + p_st = parser->init(); + if (!p_st) { + fprintf(stderr, "%s Parser failed to initialize\n", parser->name); + goto close; + } + perr = parser->open(p_st, filename, 0); + } + + /* if still have an error, fail */ + if (perr != PARSER_ERR_OK) { + fprintf(stderr, "%s ERROR: %s\n", parser->name, parser_errstr(perr)); + if (perr == PARSER_ERR_SYSTEM) perror(filename); + goto close; + } + } + + fprintf(diag, "Using Parser : %s\n", parser->name); + } else { + parser = &PARSER_BINARY; + p_st = parser->init(); + if (!p_st) { + fprintf(stderr, "%s Parser failed to initialize\n", parser->name); + goto close; + } + } + + if (port_open(&port_opts, &port) != PORT_ERR_OK) { + fprintf(stderr, "Failed to open port: %s\n", port_opts.device); + goto close; + } + + fprintf(diag, "Interface %s: %s\n", port->name, port->get_cfg_str(port)); + if (init_flag && init_bl_entry(port, gpio_seq) == 0) + goto close; + stm = stm32_init(port, init_flag); + if (!stm) + goto close; + + fprintf(diag, "Version : 0x%02x\n", stm->bl_version); + if (port->flags & PORT_GVR_ETX) { + fprintf(diag, "Option 1 : 0x%02x\n", stm->option1); + fprintf(diag, "Option 2 : 0x%02x\n", stm->option2); + } + fprintf(diag, "Device ID : 0x%04x (%s)\n", stm->pid, stm->dev->name); + fprintf(diag, "- RAM : %dKiB (%db reserved by bootloader)\n", (stm->dev->ram_end - 0x20000000) / 1024, stm->dev->ram_start - 0x20000000); + fprintf(diag, "- Flash : %dKiB (sector size: %dx%d)\n", (stm->dev->fl_end - stm->dev->fl_start ) / 1024, stm->dev->fl_pps, stm->dev->fl_ps); + fprintf(diag, "- Option RAM : %db\n", stm->dev->opt_end - stm->dev->opt_start + 1); + fprintf(diag, "- System RAM : %dKiB\n", (stm->dev->mem_end - stm->dev->mem_start) / 1024); + + uint8_t buffer[256]; + uint32_t addr, start, end; + unsigned int len; + int failed = 0; + int first_page, num_pages; + + /* + * Cleanup addresses: + * + * Starting from options + * start_addr, readwrite_len, spage, npages + * and using device memory size, compute + * start, end, first_page, num_pages + */ + if (start_addr || readwrite_len) { + start = start_addr; + + if (is_addr_in_flash(start)) + end = stm->dev->fl_end; + else { + no_erase = 1; + if (is_addr_in_ram(start)) + end = stm->dev->ram_end; + else + end = start + sizeof(uint32_t); + } + + if (readwrite_len && (end > start + readwrite_len)) + end = start + readwrite_len; + + first_page = flash_addr_to_page_floor(start); + if (!first_page && end == stm->dev->fl_end) + num_pages = 0xff; /* mass erase */ + else + num_pages = flash_addr_to_page_ceil(end) - first_page; + } else if (!spage && !npages) { + start = stm->dev->fl_start; + end = stm->dev->fl_end; + first_page = 0; + num_pages = 0xff; /* mass erase */ + } else { + first_page = spage; + start = flash_page_to_addr(first_page); + if (start > stm->dev->fl_end) { + fprintf(stderr, "Address range exceeds flash size.\n"); + goto close; + } + + if (npages) { + num_pages = npages; + end = flash_page_to_addr(first_page + num_pages); + if (end > stm->dev->fl_end) + end = stm->dev->fl_end; + } else { + end = stm->dev->fl_end; + num_pages = flash_addr_to_page_ceil(end) - first_page; + } + + if (!first_page && end == stm->dev->fl_end) + num_pages = 0xff; /* mass erase */ + } + + if (rd) { + unsigned int max_len = port_opts.rx_frame_max; + + fprintf(diag, "Memory read\n"); + + perr = parser->open(p_st, filename, 1); + if (perr != PARSER_ERR_OK) { + fprintf(stderr, "%s ERROR: %s\n", parser->name, parser_errstr(perr)); + if (perr == PARSER_ERR_SYSTEM) + perror(filename); + goto close; + } + + fflush(diag); + addr = start; + while(addr < end) { + uint32_t left = end - addr; + len = max_len > left ? left : max_len; + s_err = stm32_read_memory(stm, addr, buffer, len); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Failed to read memory at address 0x%08x, target write-protected?\n", addr); + goto close; + } + if (parser->write(p_st, buffer, len) != PARSER_ERR_OK) + { + fprintf(stderr, "Failed to write data to file\n"); + goto close; + } + addr += len; + + fprintf(diag, + "\rRead address 0x%08x (%.2f%%) ", + addr, + (100.0f / (float)(end - start)) * (float)(addr - start) + ); + fflush(diag); + } + fprintf(diag, "Done.\n"); + ret = 0; + goto close; + } else if (rp) { + fprintf(stdout, "Read-Protecting flash\n"); + /* the device automatically performs a reset after the sending the ACK */ + reset_flag = 0; + stm32_readprot_memory(stm); + fprintf(stdout, "Done.\n"); + } else if (ur) { + fprintf(stdout, "Read-UnProtecting flash\n"); + /* the device automatically performs a reset after the sending the ACK */ + reset_flag = 0; + stm32_runprot_memory(stm); + fprintf(stdout, "Done.\n"); + } else if (eraseOnly) { + ret = 0; + fprintf(stdout, "Erasing flash\n"); + + if (num_pages != 0xff && + (start != flash_page_to_addr(first_page) + || end != flash_page_to_addr(first_page + num_pages))) { + fprintf(stderr, "Specified start & length are invalid (must be page aligned)\n"); + ret = 1; + goto close; + } + + s_err = stm32_erase_memory(stm, first_page, num_pages); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Failed to erase memory\n"); + ret = 1; + goto close; + } + } else if (wu) { + fprintf(diag, "Write-unprotecting flash\n"); + /* the device automatically performs a reset after the sending the ACK */ + reset_flag = 0; + stm32_wunprot_memory(stm); + fprintf(diag, "Done.\n"); + + } else if (wr) { + fprintf(diag, "Write to memory\n"); + + off_t offset = 0; + ssize_t r; + unsigned int size; + unsigned int max_wlen, max_rlen; + + max_wlen = port_opts.tx_frame_max - 2; /* skip len and crc */ + max_wlen &= ~3; /* 32 bit aligned */ + + max_rlen = port_opts.rx_frame_max; + max_rlen = max_rlen < max_wlen ? max_rlen : max_wlen; + + /* Assume data from stdin is whole device */ + if (filename[0] == '-' && filename[1] == '\0') + size = end - start; + else + size = parser->size(p_st); + + // TODO: It is possible to write to non-page boundaries, by reading out flash + // from partial pages and combining with the input data + // if ((start % stm->dev->fl_ps) != 0 || (end % stm->dev->fl_ps) != 0) { + // fprintf(stderr, "Specified start & length are invalid (must be page aligned)\n"); + // goto close; + // } + + // TODO: If writes are not page aligned, we should probably read out existing flash + // contents first, so it can be preserved and combined with new data + if (!no_erase && num_pages) { + fprintf(diag, "Erasing memory\n"); + s_err = stm32_erase_memory(stm, first_page, num_pages); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Failed to erase memory\n"); + goto close; + } + } + + fflush(diag); + addr = start; + while(addr < end && offset < size) { + uint32_t left = end - addr; + len = max_wlen > left ? left : max_wlen; + len = len > size - offset ? size - offset : len; + + if (parser->read(p_st, buffer, &len) != PARSER_ERR_OK) + goto close; + + if (len == 0) { + if (filename[0] == '-') { + break; + } else { + fprintf(stderr, "Failed to read input file\n"); + goto close; + } + } + + again: + s_err = stm32_write_memory(stm, addr, buffer, len); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Failed to write memory at address 0x%08x\n", addr); + goto close; + } + + if (verify) { + uint8_t compare[len]; + unsigned int offset, rlen; + + offset = 0; + while (offset < len) { + rlen = len - offset; + rlen = rlen < max_rlen ? rlen : max_rlen; + s_err = stm32_read_memory(stm, addr + offset, compare + offset, rlen); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Failed to read memory at address 0x%08x\n", addr + offset); + goto close; + } + offset += rlen; + } + + for(r = 0; r < len; ++r) + if (buffer[r] != compare[r]) { + if (failed == retry) { + fprintf(stderr, "Failed to verify at address 0x%08x, expected 0x%02x and found 0x%02x\n", + (uint32_t)(addr + r), + buffer [r], + compare[r] + ); + goto close; + } + ++failed; + goto again; + } + + failed = 0; + } + + addr += len; + offset += len; + + fprintf(diag, + "\rWrote %saddress 0x%08x (%.2f%%) ", + verify ? "and verified " : "", + addr, + (100.0f / size) * offset + ); + fflush(diag); + + } + + fprintf(diag, "Done.\n"); + ret = 0; + goto close; + } else if (crc) { + uint32_t crc_val = 0; + + fprintf(diag, "CRC computation\n"); + + s_err = stm32_crc_wrapper(stm, start, end - start, &crc_val); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Failed to read CRC\n"); + goto close; + } + fprintf(diag, "CRC(0x%08x-0x%08x) = 0x%08x\n", start, end, + crc_val); + ret = 0; + goto close; + } else + ret = 0; + +close: + if (stm && exec_flag && ret == 0) { + if (execute == 0) + execute = stm->dev->fl_start; + + fprintf(diag, "\nStarting execution at address 0x%08x... ", execute); + fflush(diag); + if (stm32_go(stm, execute) == STM32_ERR_OK) { + reset_flag = 0; + fprintf(diag, "done.\n"); + } else + fprintf(diag, "failed.\n"); + } + + if (stm && reset_flag) { + fprintf(diag, "\nResetting device... "); + fflush(diag); + if (init_bl_exit(stm, port, gpio_seq)) + fprintf(diag, "done.\n"); + else fprintf(diag, "failed.\n"); + } + + if (p_st ) parser->close(p_st); + if (stm ) stm32_close (stm); + if (port) + port->close(port); + + fprintf(diag, "\n"); + return ret; +} + +int parse_options(int argc, char *argv[]) +{ + int c; + char *pLen; + + while ((c = getopt(argc, argv, "a:b:m:r:w:e:vn:g:jkfcChuos:S:F:i:R")) != -1) { + switch(c) { + case 'a': + port_opts.bus_addr = strtoul(optarg, NULL, 0); + break; + + case 'b': + port_opts.baudRate = serial_get_baud(strtoul(optarg, NULL, 0)); + if (port_opts.baudRate == SERIAL_BAUD_INVALID) { + serial_baud_t baudrate; + fprintf(stderr, "Invalid baud rate, valid options are:\n"); + for (baudrate = SERIAL_BAUD_1200; baudrate != SERIAL_BAUD_INVALID; ++baudrate) + fprintf(stderr, " %d\n", serial_get_baud_int(baudrate)); + return 1; + } + break; + + case 'm': + if (strlen(optarg) != 3 + || serial_get_bits(optarg) == SERIAL_BITS_INVALID + || serial_get_parity(optarg) == SERIAL_PARITY_INVALID + || serial_get_stopbit(optarg) == SERIAL_STOPBIT_INVALID) { + fprintf(stderr, "Invalid serial mode\n"); + return 1; + } + port_opts.serial_mode = optarg; + break; + + case 'r': + case 'w': + rd = rd || c == 'r'; + wr = wr || c == 'w'; + if (rd && wr) { + fprintf(stderr, "ERROR: Invalid options, can't read & write at the same time\n"); + return 1; + } + filename = optarg; + if (filename[0] == '-') { + force_binary = 1; + } + break; + case 'e': + if (readwrite_len || start_addr) { + fprintf(stderr, "ERROR: Invalid options, can't specify start page / num pages and start address/length\n"); + return 1; + } + npages = strtoul(optarg, NULL, 0); + if (npages > 0xFF || npages < 0) { + fprintf(stderr, "ERROR: You need to specify a page count between 0 and 255"); + return 1; + } + if (!npages) + no_erase = 1; + break; + case 'u': + wu = 1; + if (rd || wr) { + fprintf(stderr, "ERROR: Invalid options, can't write unprotect and read/write at the same time\n"); + return 1; + } + break; + + case 'j': + rp = 1; + if (rd || wr) { + fprintf(stderr, "ERROR: Invalid options, can't read protect and read/write at the same time\n"); + return 1; + } + break; + + case 'k': + ur = 1; + if (rd || wr) { + fprintf(stderr, "ERROR: Invalid options, can't read unprotect and read/write at the same time\n"); + return 1; + } + break; + + case 'o': + eraseOnly = 1; + if (rd || wr) { + fprintf(stderr, "ERROR: Invalid options, can't erase-only and read/write at the same time\n"); + return 1; + } + break; + + case 'v': + verify = 1; + break; + + case 'n': + retry = strtoul(optarg, NULL, 0); + break; + + case 'g': + exec_flag = 1; + execute = strtoul(optarg, NULL, 0); + if (execute % 4 != 0) { + fprintf(stderr, "ERROR: Execution address must be word-aligned\n"); + return 1; + } + break; + case 's': + if (readwrite_len || start_addr) { + fprintf(stderr, "ERROR: Invalid options, can't specify start page / num pages and start address/length\n"); + return 1; + } + spage = strtoul(optarg, NULL, 0); + break; + case 'S': + if (spage || npages) { + fprintf(stderr, "ERROR: Invalid options, can't specify start page / num pages and start address/length\n"); + return 1; + } else { + start_addr = strtoul(optarg, &pLen, 0); + if (*pLen == ':') { + pLen++; + readwrite_len = strtoul(pLen, NULL, 0); + if (readwrite_len == 0) { + fprintf(stderr, "ERROR: Invalid options, can't specify zero length\n"); + return 1; + } + } + } + break; + case 'F': + port_opts.rx_frame_max = strtoul(optarg, &pLen, 0); + if (*pLen == ':') { + pLen++; + port_opts.tx_frame_max = strtoul(pLen, NULL, 0); + } + if (port_opts.rx_frame_max < 0 + || port_opts.tx_frame_max < 0) { + fprintf(stderr, "ERROR: Invalid negative value for option -F\n"); + return 1; + } + if (port_opts.rx_frame_max == 0) + port_opts.rx_frame_max = STM32_MAX_RX_FRAME; + if (port_opts.tx_frame_max == 0) + port_opts.tx_frame_max = STM32_MAX_TX_FRAME; + if (port_opts.rx_frame_max < 20 + || port_opts.tx_frame_max < 5) { + fprintf(stderr, "ERROR: current code cannot work with small frames.\n"); + fprintf(stderr, "min(RX) = 20, min(TX) = 5\n"); + return 1; + } + if (port_opts.rx_frame_max > STM32_MAX_RX_FRAME) { + fprintf(stderr, "WARNING: Ignore RX length in option -F\n"); + port_opts.rx_frame_max = STM32_MAX_RX_FRAME; + } + if (port_opts.tx_frame_max > STM32_MAX_TX_FRAME) { + fprintf(stderr, "WARNING: Ignore TX length in option -F\n"); + port_opts.tx_frame_max = STM32_MAX_TX_FRAME; + } + break; + case 'f': + force_binary = 1; + break; + + case 'c': + init_flag = 0; + break; + + case 'h': + show_help(argv[0]); + exit(0); + + case 'i': + gpio_seq = optarg; + break; + + case 'R': + reset_flag = 1; + break; + + case 'C': + crc = 1; + break; + } + } + + for (c = optind; c < argc; ++c) { + if (port_opts.device) { + fprintf(stderr, "ERROR: Invalid parameter specified\n"); + show_help(argv[0]); + return 1; + } + port_opts.device = argv[c]; + } + + if (port_opts.device == NULL) { + fprintf(stderr, "ERROR: Device not specified\n"); + show_help(argv[0]); + return 1; + } + + if (!wr && verify) { + fprintf(stderr, "ERROR: Invalid usage, -v is only valid when writing\n"); + show_help(argv[0]); + return 1; + } + + return 0; +} + +void show_help(char *name) { + fprintf(stderr, + "Usage: %s [-bvngfhc] [-[rw] filename] [tty_device | i2c_device]\n" + " -a bus_address Bus address (e.g. for I2C port)\n" + " -b rate Baud rate (default 57600)\n" + " -m mode Serial port mode (default 8e1)\n" + " -r filename Read flash to file (or - stdout)\n" + " -w filename Write flash from file (or - stdout)\n" + " -C Compute CRC of flash content\n" + " -u Disable the flash write-protection\n" + " -j Enable the flash read-protection\n" + " -k Disable the flash read-protection\n" + " -o Erase only\n" + " -e n Only erase n pages before writing the flash\n" + " -v Verify writes\n" + " -n count Retry failed writes up to count times (default 10)\n" + " -g address Start execution at specified address (0 = flash start)\n" + " -S address[:length] Specify start address and optionally length for\n" + " read/write/erase operations\n" + " -F RX_length[:TX_length] Specify the max length of RX and TX frame\n" + " -s start_page Flash at specified page (0 = flash start)\n" + " -f Force binary parser\n" + " -h Show this help\n" + " -c Resume the connection (don't send initial INIT)\n" + " *Baud rate must be kept the same as the first init*\n" + " This is useful if the reset fails\n" + " -i GPIO_string GPIO sequence to enter/exit bootloader mode\n" + " GPIO_string=[entry_seq][:[exit_seq]]\n" + " sequence=[-]n[,sequence]\n" + " -R Reset device at exit.\n" + "\n" + "Examples:\n" + " Get device information:\n" + " %s /dev/ttyS0\n" + " or:\n" + " %s /dev/i2c-0\n" + "\n" + " Write with verify and then start execution:\n" + " %s -w filename -v -g 0x0 /dev/ttyS0\n" + "\n" + " Read flash to file:\n" + " %s -r filename /dev/ttyS0\n" + "\n" + " Read 100 bytes of flash from 0x1000 to stdout:\n" + " %s -r - -S 0x1000:100 /dev/ttyS0\n" + "\n" + " Start execution:\n" + " %s -g 0x0 /dev/ttyS0\n" + "\n" + " GPIO sequence:\n" + " - entry sequence: GPIO_3=low, GPIO_2=low, GPIO_2=high\n" + " - exit sequence: GPIO_3=high, GPIO_2=low, GPIO_2=high\n" + " %s -i -3,-2,2:3,-2,2 /dev/ttyS0\n", + name, + name, + name, + name, + name, + name, + name, + name + ); +} + diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/parsers/Android.mk b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/parsers/Android.mk new file mode 100644 index 0000000..afec18c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/parsers/Android.mk @@ -0,0 +1,6 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := libparsers +LOCAL_SRC_FILES := binary.c hex.c +include $(BUILD_STATIC_LIBRARY) diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/parsers/Makefile b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/parsers/Makefile new file mode 100644 index 0000000..bb7df1e --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/parsers/Makefile @@ -0,0 +1,12 @@ + +CFLAGS += -Wall -g + +all: parsers.a + +parsers.a: binary.o hex.o + $(AR) rc $@ binary.o hex.o + +clean: + rm -f *.o parsers.a + +.PHONY: all clean diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/parsers/binary.c b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/parsers/binary.c new file mode 100644 index 0000000..f491952 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/parsers/binary.c @@ -0,0 +1,140 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#include +#include +#include +#include +#include + +#include "binary.h" + +typedef struct { + int fd; + char write; + struct stat stat; +} binary_t; + +void* binary_init() { + return calloc(sizeof(binary_t), 1); +} + +parser_err_t binary_open(void *storage, const char *filename, const char write) { + binary_t *st = storage; + if (write) { + if (filename[0] == '-') + st->fd = 1; + else + st->fd = open( + filename, +#ifndef __WIN32__ + O_WRONLY | O_CREAT | O_TRUNC, +#else + O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, +#endif +#ifndef __WIN32__ + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH +#else + 0 +#endif + ); + st->stat.st_size = 0; + } else { + if (filename[0] == '-') { + st->fd = 0; + } else { + if (stat(filename, &st->stat) != 0) + return PARSER_ERR_INVALID_FILE; + st->fd = open(filename, +#ifndef __WIN32__ + O_RDONLY +#else + O_RDONLY | O_BINARY +#endif + ); + } + } + + st->write = write; + return st->fd == -1 ? PARSER_ERR_SYSTEM : PARSER_ERR_OK; +} + +parser_err_t binary_close(void *storage) { + binary_t *st = storage; + + if (st->fd) close(st->fd); + free(st); + return PARSER_ERR_OK; +} + +unsigned int binary_size(void *storage) { + binary_t *st = storage; + return st->stat.st_size; +} + +parser_err_t binary_read(void *storage, void *data, unsigned int *len) { + binary_t *st = storage; + unsigned int left = *len; + if (st->write) return PARSER_ERR_WRONLY; + + ssize_t r; + while(left > 0) { + r = read(st->fd, data, left); + /* If there is no data to read at all, return OK, but with zero read */ + if (r == 0 && left == *len) { + *len = 0; + return PARSER_ERR_OK; + } + if (r <= 0) return PARSER_ERR_SYSTEM; + left -= r; + data += r; + } + + *len = *len - left; + return PARSER_ERR_OK; +} + +parser_err_t binary_write(void *storage, void *data, unsigned int len) { + binary_t *st = storage; + if (!st->write) return PARSER_ERR_RDONLY; + + ssize_t r; + while(len > 0) { + r = write(st->fd, data, len); + if (r < 1) return PARSER_ERR_SYSTEM; + st->stat.st_size += r; + + len -= r; + data += r; + } + + return PARSER_ERR_OK; +} + +parser_t PARSER_BINARY = { + "Raw BINARY", + binary_init, + binary_open, + binary_close, + binary_size, + binary_read, + binary_write +}; + diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/parsers/binary.h b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/parsers/binary.h new file mode 100644 index 0000000..d989acf --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/parsers/binary.h @@ -0,0 +1,27 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _PARSER_BINARY_H +#define _PARSER_BINARY_H + +#include "parser.h" + +extern parser_t PARSER_BINARY; +#endif diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/parsers/hex.c b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/parsers/hex.c new file mode 100644 index 0000000..3baf856 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/parsers/hex.c @@ -0,0 +1,224 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#include +#include +#include +#include +#include +#include +#include + +#include "hex.h" +#include "../utils.h" + +typedef struct { + size_t data_len, offset; + uint8_t *data; + uint8_t base; +} hex_t; + +void* hex_init() { + return calloc(sizeof(hex_t), 1); +} + +parser_err_t hex_open(void *storage, const char *filename, const char write) { + hex_t *st = storage; + if (write) { + return PARSER_ERR_RDONLY; + } else { + char mark; + int i, fd; + uint8_t checksum; + unsigned int c; + uint32_t base = 0; + unsigned int last_address = 0x0; + + fd = open(filename, O_RDONLY); + if (fd < 0) + return PARSER_ERR_SYSTEM; + + /* read in the file */ + + while(read(fd, &mark, 1) != 0) { + if (mark == '\n' || mark == '\r') continue; + if (mark != ':') + return PARSER_ERR_INVALID_FILE; + + char buffer[9]; + unsigned int reclen, address, type; + uint8_t *record = NULL; + + /* get the reclen, address, and type */ + buffer[8] = 0; + if (read(fd, &buffer, 8) != 8) return PARSER_ERR_INVALID_FILE; + if (sscanf(buffer, "%2x%4x%2x", &reclen, &address, &type) != 3) { + close(fd); + return PARSER_ERR_INVALID_FILE; + } + + /* setup the checksum */ + checksum = + reclen + + ((address & 0xFF00) >> 8) + + ((address & 0x00FF) >> 0) + + type; + + switch(type) { + /* data record */ + case 0: + c = address - last_address; + st->data = realloc(st->data, st->data_len + c + reclen); + + /* if there is a gap, set it to 0xff and increment the length */ + if (c > 0) { + memset(&st->data[st->data_len], 0xff, c); + st->data_len += c; + } + + last_address = address + reclen; + record = &st->data[st->data_len]; + st->data_len += reclen; + break; + + /* extended segment address record */ + case 2: + base = 0; + break; + + /* extended linear address record */ + case 4: + base = address; + break; + } + + buffer[2] = 0; + for(i = 0; i < reclen; ++i) { + if (read(fd, &buffer, 2) != 2 || sscanf(buffer, "%2x", &c) != 1) { + close(fd); + return PARSER_ERR_INVALID_FILE; + } + + /* add the byte to the checksum */ + checksum += c; + + switch(type) { + case 0: + if (record != NULL) { + record[i] = c; + } else { + return PARSER_ERR_INVALID_FILE; + } + break; + + case 2: + case 4: + base = (base << 8) | c; + break; + } + } + + /* read, scan, and verify the checksum */ + if ( + read(fd, &buffer, 2 ) != 2 || + sscanf(buffer, "%2x", &c) != 1 || + (uint8_t)(checksum + c) != 0x00 + ) { + close(fd); + return PARSER_ERR_INVALID_FILE; + } + + switch(type) { + /* EOF */ + case 1: + close(fd); + return PARSER_ERR_OK; + + /* address record */ + case 2: base = base << 4; + case 4: base = be_u32(base); + /* Reset last_address since our base changed */ + last_address = 0; + + if (st->base == 0) { + st->base = base; + break; + } + + /* we cant cope with files out of order */ + if (base < st->base) { + close(fd); + return PARSER_ERR_INVALID_FILE; + } + + /* if there is a gap, enlarge and fill with zeros */ + unsigned int len = base - st->base; + if (len > st->data_len) { + st->data = realloc(st->data, len); + memset(&st->data[st->data_len], 0, len - st->data_len); + st->data_len = len; + } + break; + } + } + + close(fd); + return PARSER_ERR_OK; + } +} + +parser_err_t hex_close(void *storage) { + hex_t *st = storage; + if (st) free(st->data); + free(st); + return PARSER_ERR_OK; +} + +unsigned int hex_size(void *storage) { + hex_t *st = storage; + return st->data_len; +} + +parser_err_t hex_read(void *storage, void *data, unsigned int *len) { + hex_t *st = storage; + unsigned int left = st->data_len - st->offset; + unsigned int get = left > *len ? *len : left; + + memcpy(data, &st->data[st->offset], get); + st->offset += get; + + *len = get; + return PARSER_ERR_OK; +} + +parser_err_t hex_write(void *storage, void *data, unsigned int len) { + return PARSER_ERR_RDONLY; +} + +parser_t PARSER_HEX = { + "Intel HEX", + hex_init, + hex_open, + hex_close, + hex_size, + hex_read, + hex_write +}; + diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/parsers/hex.h b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/parsers/hex.h new file mode 100644 index 0000000..02413c9 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/parsers/hex.h @@ -0,0 +1,27 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _PARSER_HEX_H +#define _PARSER_HEX_H + +#include "parser.h" + +extern parser_t PARSER_HEX; +#endif diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/parsers/parser.h b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/parsers/parser.h new file mode 100644 index 0000000..c2fae3c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/parsers/parser.h @@ -0,0 +1,56 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _H_PARSER +#define _H_PARSER + +enum parser_err { + PARSER_ERR_OK, + PARSER_ERR_SYSTEM, + PARSER_ERR_INVALID_FILE, + PARSER_ERR_WRONLY, + PARSER_ERR_RDONLY +}; +typedef enum parser_err parser_err_t; + +struct parser { + const char *name; + void* (*init )(); /* initialise the parser */ + parser_err_t (*open )(void *storage, const char *filename, const char write); /* open the file for read|write */ + parser_err_t (*close)(void *storage); /* close and free the parser */ + unsigned int (*size )(void *storage); /* get the total data size */ + parser_err_t (*read )(void *storage, void *data, unsigned int *len); /* read a block of data */ + parser_err_t (*write)(void *storage, void *data, unsigned int len); /* write a block of data */ +}; +typedef struct parser parser_t; + +static inline const char* parser_errstr(parser_err_t err) { + switch(err) { + case PARSER_ERR_OK : return "OK"; + case PARSER_ERR_SYSTEM : return "System Error"; + case PARSER_ERR_INVALID_FILE: return "Invalid File"; + case PARSER_ERR_WRONLY : return "Parser can only write"; + case PARSER_ERR_RDONLY : return "Parser can only read"; + default: + return "Unknown Error"; + } +} + +#endif diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/port.c b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/port.c new file mode 100644 index 0000000..08e58cc --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/port.c @@ -0,0 +1,59 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2014 Antonio Borneo + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include + +#include "serial.h" +#include "port.h" + + +extern struct port_interface port_serial; +extern struct port_interface port_i2c; + +static struct port_interface *ports[] = { + &port_serial, + &port_i2c, + NULL, +}; + + +port_err_t port_open(struct port_options *ops, struct port_interface **outport) +{ + int ret; + static struct port_interface **port; + + for (port = ports; *port; port++) { + ret = (*port)->open(*port, ops); + if (ret == PORT_ERR_NODEV) + continue; + if (ret == PORT_ERR_OK) + break; + fprintf(stderr, "Error probing interface \"%s\"\n", + (*port)->name); + } + if (*port == NULL) { + fprintf(stderr, "Cannot handle device \"%s\"\n", + ops->device); + return PORT_ERR_UNKNOWN; + } + + *outport = *port; + return PORT_ERR_OK; +} diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/port.h b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/port.h new file mode 100644 index 0000000..290f034 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/port.h @@ -0,0 +1,75 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2014 Antonio Borneo + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _H_PORT +#define _H_PORT + +typedef enum { + PORT_ERR_OK = 0, + PORT_ERR_NODEV, /* No such device */ + PORT_ERR_TIMEDOUT, /* Operation timed out */ + PORT_ERR_UNKNOWN, +} port_err_t; + +/* flags */ +#define PORT_BYTE (1 << 0) /* byte (not frame) oriented */ +#define PORT_GVR_ETX (1 << 1) /* cmd GVR returns protection status */ +#define PORT_CMD_INIT (1 << 2) /* use INIT cmd to autodetect speed */ +#define PORT_RETRY (1 << 3) /* allowed read() retry after timeout */ +#define PORT_STRETCH_W (1 << 4) /* warning for no-stretching commands */ + +/* all options and flags used to open and configure an interface */ +struct port_options { + const char *device; + serial_baud_t baudRate; + const char *serial_mode; + int bus_addr; + int rx_frame_max; + int tx_frame_max; +}; + +/* + * Specify the length of reply for command GET + * This is helpful for frame-oriented protocols, e.g. i2c, to avoid time + * consuming try-fail-timeout-retry operation. + * On byte-oriented protocols, i.e. UART, this information would be skipped + * after read the first byte, so not needed. + */ +struct varlen_cmd { + uint8_t version; + uint8_t length; +}; + +struct port_interface { + const char *name; + unsigned flags; + port_err_t (*open)(struct port_interface *port, struct port_options *ops); + port_err_t (*close)(struct port_interface *port); + port_err_t (*read)(struct port_interface *port, void *buf, size_t nbyte); + port_err_t (*write)(struct port_interface *port, void *buf, size_t nbyte); + port_err_t (*gpio)(struct port_interface *port, serial_gpio_t n, int level); + const char *(*get_cfg_str)(struct port_interface *port); + struct varlen_cmd *cmd_get_reply; + void *private; +}; + +port_err_t port_open(struct port_options *ops, struct port_interface **outport); + +#endif diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/protocol.txt b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/protocol.txt new file mode 100644 index 0000000..0391099 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/protocol.txt @@ -0,0 +1,19 @@ +The communication protocol used by ST bootloader is documented in following ST +application notes, depending on communication port. + +In current version of stm32flash are supported only UART and I2C ports. + +* AN3154: CAN protocol used in the STM32 bootloader + http://www.st.com/web/en/resource/technical/document/application_note/CD00264321.pdf + +* AN3155: USART protocol used in the STM32(TM) bootloader + http://www.st.com/web/en/resource/technical/document/application_note/CD00264342.pdf + +* AN4221: I2C protocol used in the STM32 bootloader + http://www.st.com/web/en/resource/technical/document/application_note/DM00072315.pdf + +* AN4286: SPI protocol used in the STM32 bootloader + http://www.st.com/web/en/resource/technical/document/application_note/DM00081379.pdf + +Boot mode selection for STM32 is documented in ST application note AN2606, available in ST website: + http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/serial.h b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/serial.h new file mode 100644 index 0000000..227ba16 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/serial.h @@ -0,0 +1,90 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _SERIAL_H +#define _SERIAL_H + +typedef struct serial serial_t; + +typedef enum { + SERIAL_PARITY_NONE, + SERIAL_PARITY_EVEN, + SERIAL_PARITY_ODD, + + SERIAL_PARITY_INVALID +} serial_parity_t; + +typedef enum { + SERIAL_BITS_5, + SERIAL_BITS_6, + SERIAL_BITS_7, + SERIAL_BITS_8, + + SERIAL_BITS_INVALID +} serial_bits_t; + +typedef enum { + SERIAL_BAUD_1200, + SERIAL_BAUD_1800, + SERIAL_BAUD_2400, + SERIAL_BAUD_4800, + SERIAL_BAUD_9600, + SERIAL_BAUD_19200, + SERIAL_BAUD_38400, + SERIAL_BAUD_57600, + SERIAL_BAUD_115200, + SERIAL_BAUD_128000, + SERIAL_BAUD_230400, + SERIAL_BAUD_256000, + SERIAL_BAUD_460800, + SERIAL_BAUD_500000, + SERIAL_BAUD_576000, + SERIAL_BAUD_921600, + SERIAL_BAUD_1000000, + SERIAL_BAUD_1500000, + SERIAL_BAUD_2000000, + + SERIAL_BAUD_INVALID +} serial_baud_t; + +typedef enum { + SERIAL_STOPBIT_1, + SERIAL_STOPBIT_2, + + SERIAL_STOPBIT_INVALID +} serial_stopbit_t; + +typedef enum { + GPIO_RTS = 1, + GPIO_DTR, + GPIO_BRK, +} serial_gpio_t; + +/* common helper functions */ +serial_baud_t serial_get_baud(const unsigned int baud); +unsigned int serial_get_baud_int(const serial_baud_t baud); +serial_bits_t serial_get_bits(const char *mode); +unsigned int serial_get_bits_int(const serial_bits_t bits); +serial_parity_t serial_get_parity(const char *mode); +char serial_get_parity_str(const serial_parity_t parity); +serial_stopbit_t serial_get_stopbit(const char *mode); +unsigned int serial_get_stopbit_int(const serial_stopbit_t stopbit); + +#endif diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/serial_common.c b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/serial_common.c new file mode 100644 index 0000000..43e48e1 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/serial_common.c @@ -0,0 +1,154 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "serial.h" + +serial_baud_t serial_get_baud(const unsigned int baud) { + switch(baud) { + case 1200: return SERIAL_BAUD_1200 ; + case 1800: return SERIAL_BAUD_1800 ; + case 2400: return SERIAL_BAUD_2400 ; + case 4800: return SERIAL_BAUD_4800 ; + case 9600: return SERIAL_BAUD_9600 ; + case 19200: return SERIAL_BAUD_19200 ; + case 38400: return SERIAL_BAUD_38400 ; + case 57600: return SERIAL_BAUD_57600 ; + case 115200: return SERIAL_BAUD_115200; + case 128000: return SERIAL_BAUD_128000; + case 230400: return SERIAL_BAUD_230400; + case 256000: return SERIAL_BAUD_256000; + case 460800: return SERIAL_BAUD_460800; + case 500000: return SERIAL_BAUD_500000; + case 576000: return SERIAL_BAUD_576000; + case 921600: return SERIAL_BAUD_921600; + case 1000000: return SERIAL_BAUD_1000000; + case 1500000: return SERIAL_BAUD_1500000; + case 2000000: return SERIAL_BAUD_2000000; + + default: + return SERIAL_BAUD_INVALID; + } +} + +unsigned int serial_get_baud_int(const serial_baud_t baud) { + switch(baud) { + case SERIAL_BAUD_1200 : return 1200 ; + case SERIAL_BAUD_1800 : return 1800 ; + case SERIAL_BAUD_2400 : return 2400 ; + case SERIAL_BAUD_4800 : return 4800 ; + case SERIAL_BAUD_9600 : return 9600 ; + case SERIAL_BAUD_19200 : return 19200 ; + case SERIAL_BAUD_38400 : return 38400 ; + case SERIAL_BAUD_57600 : return 57600 ; + case SERIAL_BAUD_115200: return 115200; + case SERIAL_BAUD_128000: return 128000; + case SERIAL_BAUD_230400: return 230400; + case SERIAL_BAUD_256000: return 256000; + case SERIAL_BAUD_460800: return 460800; + case SERIAL_BAUD_500000: return 500000; + case SERIAL_BAUD_576000: return 576000; + case SERIAL_BAUD_921600: return 921600; + case SERIAL_BAUD_1000000: return 1000000; + case SERIAL_BAUD_1500000: return 1500000; + case SERIAL_BAUD_2000000: return 2000000; + + case SERIAL_BAUD_INVALID: + default: + return 0; + } +} + +serial_bits_t serial_get_bits(const char *mode) { + if (!mode) + return SERIAL_BITS_INVALID; + switch(mode[0]) { + case '5': return SERIAL_BITS_5; + case '6': return SERIAL_BITS_6; + case '7': return SERIAL_BITS_7; + case '8': return SERIAL_BITS_8; + + default: + return SERIAL_BITS_INVALID; + } +} + +unsigned int serial_get_bits_int(const serial_bits_t bits) { + switch(bits) { + case SERIAL_BITS_5: return 5; + case SERIAL_BITS_6: return 6; + case SERIAL_BITS_7: return 7; + case SERIAL_BITS_8: return 8; + + default: + return 0; + } +} + +serial_parity_t serial_get_parity(const char *mode) { + if (!mode || !mode[0]) + return SERIAL_PARITY_INVALID; + switch(mode[1]) { + case 'N': + case 'n': + return SERIAL_PARITY_NONE; + case 'E': + case 'e': + return SERIAL_PARITY_EVEN; + case 'O': + case 'o': + return SERIAL_PARITY_ODD; + + default: + return SERIAL_PARITY_INVALID; + } +} + +char serial_get_parity_str(const serial_parity_t parity) { + switch(parity) { + case SERIAL_PARITY_NONE: return 'N'; + case SERIAL_PARITY_EVEN: return 'E'; + case SERIAL_PARITY_ODD : return 'O'; + + default: + return ' '; + } +} + +serial_stopbit_t serial_get_stopbit(const char *mode) { + if (!mode || !mode[0] || !mode[1]) + return SERIAL_STOPBIT_INVALID; + switch(mode[2]) { + case '1': return SERIAL_STOPBIT_1; + case '2': return SERIAL_STOPBIT_2; + + default: + return SERIAL_STOPBIT_INVALID; + } +} + +unsigned int serial_get_stopbit_int(const serial_stopbit_t stopbit) { + switch(stopbit) { + case SERIAL_STOPBIT_1: return 1; + case SERIAL_STOPBIT_2: return 2; + + default: + return 0; + } +} + diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/serial_platform.c b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/serial_platform.c new file mode 100644 index 0000000..98e2569 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/serial_platform.c @@ -0,0 +1,5 @@ +#if defined(__WIN32__) || defined(__CYGWIN__) +# include "serial_w32.c" +#else +# include "serial_posix.c" +#endif diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/serial_posix.c b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/serial_posix.c new file mode 100644 index 0000000..284b35b --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/serial_posix.c @@ -0,0 +1,395 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "serial.h" +#include "port.h" + +struct serial { + int fd; + struct termios oldtio; + struct termios newtio; + char setup_str[11]; +}; + +static serial_t *serial_open(const char *device) +{ + serial_t *h = calloc(sizeof(serial_t), 1); + + h->fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY); + if (h->fd < 0) { + free(h); + return NULL; + } + fcntl(h->fd, F_SETFL, 0); + + tcgetattr(h->fd, &h->oldtio); + tcgetattr(h->fd, &h->newtio); + + return h; +} + +static void serial_flush(const serial_t *h) +{ + tcflush(h->fd, TCIFLUSH); +} + +static void serial_close(serial_t *h) +{ + serial_flush(h); + tcsetattr(h->fd, TCSANOW, &h->oldtio); + close(h->fd); + free(h); +} + +static port_err_t serial_setup(serial_t *h, const serial_baud_t baud, + const serial_bits_t bits, + const serial_parity_t parity, + const serial_stopbit_t stopbit) +{ + speed_t port_baud; + tcflag_t port_bits; + tcflag_t port_parity; + tcflag_t port_stop; + struct termios settings; + + switch (baud) { + case SERIAL_BAUD_1200: port_baud = B1200; break; + case SERIAL_BAUD_1800: port_baud = B1800; break; + case SERIAL_BAUD_2400: port_baud = B2400; break; + case SERIAL_BAUD_4800: port_baud = B4800; break; + case SERIAL_BAUD_9600: port_baud = B9600; break; + case SERIAL_BAUD_19200: port_baud = B19200; break; + case SERIAL_BAUD_38400: port_baud = B38400; break; + case SERIAL_BAUD_57600: port_baud = B57600; break; + case SERIAL_BAUD_115200: port_baud = B115200; break; + case SERIAL_BAUD_230400: port_baud = B230400; break; +#ifdef B460800 + case SERIAL_BAUD_460800: port_baud = B460800; break; +#endif /* B460800 */ +#ifdef B921600 + case SERIAL_BAUD_921600: port_baud = B921600; break; +#endif /* B921600 */ +#ifdef B500000 + case SERIAL_BAUD_500000: port_baud = B500000; break; +#endif /* B500000 */ +#ifdef B576000 + case SERIAL_BAUD_576000: port_baud = B576000; break; +#endif /* B576000 */ +#ifdef B1000000 + case SERIAL_BAUD_1000000: port_baud = B1000000; break; +#endif /* B1000000 */ +#ifdef B1500000 + case SERIAL_BAUD_1500000: port_baud = B1500000; break; +#endif /* B1500000 */ +#ifdef B2000000 + case SERIAL_BAUD_2000000: port_baud = B2000000; break; +#endif /* B2000000 */ + + case SERIAL_BAUD_INVALID: + default: + return PORT_ERR_UNKNOWN; + } + + switch (bits) { + case SERIAL_BITS_5: port_bits = CS5; break; + case SERIAL_BITS_6: port_bits = CS6; break; + case SERIAL_BITS_7: port_bits = CS7; break; + case SERIAL_BITS_8: port_bits = CS8; break; + + default: + return PORT_ERR_UNKNOWN; + } + + switch (parity) { + case SERIAL_PARITY_NONE: port_parity = 0; break; + case SERIAL_PARITY_EVEN: port_parity = PARENB; break; + case SERIAL_PARITY_ODD: port_parity = PARENB | PARODD; break; + + default: + return PORT_ERR_UNKNOWN; + } + + switch (stopbit) { + case SERIAL_STOPBIT_1: port_stop = 0; break; + case SERIAL_STOPBIT_2: port_stop = CSTOPB; break; + + default: + return PORT_ERR_UNKNOWN; + } + + /* reset the settings */ +#ifndef __sun /* Used by GNU and BSD. Ignore __SVR4 in test. */ + cfmakeraw(&h->newtio); +#else /* __sun */ + h->newtio.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR + | IGNCR | ICRNL | IXON); + if (port_parity) + h->newtio.c_iflag |= INPCK; + + h->newtio.c_oflag &= ~OPOST; + h->newtio.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); + h->newtio.c_cflag &= ~(CSIZE | PARENB); + h->newtio.c_cflag |= CS8; +#endif /* __sun */ +#ifdef __QNXNTO__ + h->newtio.c_cflag &= ~(CSIZE | IHFLOW | OHFLOW); +#else + h->newtio.c_cflag &= ~(CSIZE | CRTSCTS); +#endif + h->newtio.c_cflag &= ~(CSIZE | CRTSCTS); + h->newtio.c_iflag &= ~(IXON | IXOFF | IXANY | IGNPAR); + h->newtio.c_lflag &= ~(ECHOK | ECHOCTL | ECHOKE); + h->newtio.c_oflag &= ~(OPOST | ONLCR); + + /* setup the new settings */ + cfsetispeed(&h->newtio, port_baud); + cfsetospeed(&h->newtio, port_baud); + h->newtio.c_cflag |= + port_parity | + port_bits | + port_stop | + CLOCAL | + CREAD; + + h->newtio.c_cc[VMIN] = 0; + h->newtio.c_cc[VTIME] = 5; /* in units of 0.1 s */ + + /* set the settings */ + serial_flush(h); + if (tcsetattr(h->fd, TCSANOW, &h->newtio) != 0) + return PORT_ERR_UNKNOWN; + +/* this check fails on CDC-ACM devices, bits 16 and 17 of cflag differ! + * it has been disabled below for now -jcw, 2015-11-09 + if (settings.c_cflag != h->newtio.c_cflag) + fprintf(stderr, "c_cflag mismatch %lx\n", + settings.c_cflag ^ h->newtio.c_cflag); + */ + + /* confirm they were set */ + tcgetattr(h->fd, &settings); + if (settings.c_iflag != h->newtio.c_iflag || + settings.c_oflag != h->newtio.c_oflag || + //settings.c_cflag != h->newtio.c_cflag || + settings.c_lflag != h->newtio.c_lflag) + return PORT_ERR_UNKNOWN; + + snprintf(h->setup_str, sizeof(h->setup_str), "%u %d%c%d", + serial_get_baud_int(baud), + serial_get_bits_int(bits), + serial_get_parity_str(parity), + serial_get_stopbit_int(stopbit)); + return PORT_ERR_OK; +} + +/* + * Roger clark. + * This function is no longer used. But has just been commented out in case it needs + * to be reinstated in the future + +static int startswith(const char *haystack, const char *needle) { + return strncmp(haystack, needle, strlen(needle)) == 0; +} +*/ + +static int is_tty(const char *path) { + char resolved[PATH_MAX]; + + if(!realpath(path, resolved)) return 0; + + + /* + * Roger Clark + * Commented out this check, because on OSX some devices are /dev/cu + * and some users use symbolic links to devices, hence the name may not even start + * with /dev + + if(startswith(resolved, "/dev/tty")) return 1; + + return 0; + */ + + return 1; +} + +static port_err_t serial_posix_open(struct port_interface *port, + struct port_options *ops) +{ + serial_t *h; + + /* 1. check device name match */ + if (!is_tty(ops->device)) + return PORT_ERR_NODEV; + + /* 2. check options */ + if (ops->baudRate == SERIAL_BAUD_INVALID) + return PORT_ERR_UNKNOWN; + if (serial_get_bits(ops->serial_mode) == SERIAL_BITS_INVALID) + return PORT_ERR_UNKNOWN; + if (serial_get_parity(ops->serial_mode) == SERIAL_PARITY_INVALID) + return PORT_ERR_UNKNOWN; + if (serial_get_stopbit(ops->serial_mode) == SERIAL_STOPBIT_INVALID) + return PORT_ERR_UNKNOWN; + + /* 3. open it */ + h = serial_open(ops->device); + if (h == NULL) + return PORT_ERR_UNKNOWN; + + /* 4. set options */ + if (serial_setup(h, ops->baudRate, + serial_get_bits(ops->serial_mode), + serial_get_parity(ops->serial_mode), + serial_get_stopbit(ops->serial_mode) + ) != PORT_ERR_OK) { + serial_close(h); + return PORT_ERR_UNKNOWN; + } + + port->private = h; + return PORT_ERR_OK; +} + +static port_err_t serial_posix_close(struct port_interface *port) +{ + serial_t *h; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + serial_close(h); + port->private = NULL; + return PORT_ERR_OK; +} + +static port_err_t serial_posix_read(struct port_interface *port, void *buf, + size_t nbyte) +{ + serial_t *h; + ssize_t r; + uint8_t *pos = (uint8_t *)buf; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + while (nbyte) { + r = read(h->fd, pos, nbyte); + if (r == 0) + return PORT_ERR_TIMEDOUT; + if (r < 0) + return PORT_ERR_UNKNOWN; + + nbyte -= r; + pos += r; + } + return PORT_ERR_OK; +} + +static port_err_t serial_posix_write(struct port_interface *port, void *buf, + size_t nbyte) +{ + serial_t *h; + ssize_t r; + const uint8_t *pos = (const uint8_t *)buf; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + while (nbyte) { + r = write(h->fd, pos, nbyte); + if (r < 1) + return PORT_ERR_UNKNOWN; + + nbyte -= r; + pos += r; + } + return PORT_ERR_OK; +} + +static port_err_t serial_posix_gpio(struct port_interface *port, + serial_gpio_t n, int level) +{ + serial_t *h; + int bit, lines; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + switch (n) { + case GPIO_RTS: + bit = TIOCM_RTS; + break; + + case GPIO_DTR: + bit = TIOCM_DTR; + break; + + case GPIO_BRK: + if (level == 0) + return PORT_ERR_OK; + if (tcsendbreak(h->fd, 1)) + return PORT_ERR_UNKNOWN; + return PORT_ERR_OK; + + default: + return PORT_ERR_UNKNOWN; + } + + /* handle RTS/DTR */ + if (ioctl(h->fd, TIOCMGET, &lines)) + return PORT_ERR_UNKNOWN; + lines = level ? lines | bit : lines & ~bit; + if (ioctl(h->fd, TIOCMSET, &lines)) + return PORT_ERR_UNKNOWN; + + return PORT_ERR_OK; +} + +static const char *serial_posix_get_cfg_str(struct port_interface *port) +{ + serial_t *h; + + h = (serial_t *)port->private; + return h ? h->setup_str : "INVALID"; +} + +struct port_interface port_serial = { + .name = "serial_posix", + .flags = PORT_BYTE | PORT_GVR_ETX | PORT_CMD_INIT | PORT_RETRY, + .open = serial_posix_open, + .close = serial_posix_close, + .read = serial_posix_read, + .write = serial_posix_write, + .gpio = serial_posix_gpio, + .get_cfg_str = serial_posix_get_cfg_str, +}; diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/serial_w32.c b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/serial_w32.c new file mode 100644 index 0000000..56772c0 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/serial_w32.c @@ -0,0 +1,341 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + Copyright (C) 2010 Gareth McMullin + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "serial.h" +#include "port.h" + +struct serial { + HANDLE fd; + DCB oldtio; + DCB newtio; + char setup_str[11]; +}; + +static serial_t *serial_open(const char *device) +{ + serial_t *h = calloc(sizeof(serial_t), 1); + char *devName; + + /* timeout in ms */ + COMMTIMEOUTS timeouts = {MAXDWORD, MAXDWORD, 500, 0, 0}; + + /* Fix the device name if required */ + if (strlen(device) > 4 && device[0] != '\\') { + devName = calloc(1, strlen(device) + 5); + sprintf(devName, "\\\\.\\%s", device); + } else { + devName = (char *)device; + } + + /* Create file handle for port */ + h->fd = CreateFile(devName, GENERIC_READ | GENERIC_WRITE, + 0, /* Exclusive access */ + NULL, /* No security */ + OPEN_EXISTING, + 0, /* No overlap */ + NULL); + + if (devName != device) + free(devName); + + if (h->fd == INVALID_HANDLE_VALUE) { + if (GetLastError() == ERROR_FILE_NOT_FOUND) + fprintf(stderr, "File not found: %s\n", device); + return NULL; + } + + SetupComm(h->fd, 4096, 4096); /* Set input and output buffer size */ + + SetCommTimeouts(h->fd, &timeouts); + + SetCommMask(h->fd, EV_ERR); /* Notify us of error events */ + + GetCommState(h->fd, &h->oldtio); /* Retrieve port parameters */ + GetCommState(h->fd, &h->newtio); /* Retrieve port parameters */ + + /* PurgeComm(h->fd, PURGE_RXABORT | PURGE_TXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR); */ + + return h; +} + +static void serial_flush(const serial_t *h) +{ + /* We shouldn't need to flush in non-overlapping (blocking) mode */ + /* tcflush(h->fd, TCIFLUSH); */ +} + +static void serial_close(serial_t *h) +{ + serial_flush(h); + SetCommState(h->fd, &h->oldtio); + CloseHandle(h->fd); + free(h); +} + +static port_err_t serial_setup(serial_t *h, + const serial_baud_t baud, + const serial_bits_t bits, + const serial_parity_t parity, + const serial_stopbit_t stopbit) +{ + switch (baud) { + case SERIAL_BAUD_1200: h->newtio.BaudRate = CBR_1200; break; + /* case SERIAL_BAUD_1800: h->newtio.BaudRate = CBR_1800; break; */ + case SERIAL_BAUD_2400: h->newtio.BaudRate = CBR_2400; break; + case SERIAL_BAUD_4800: h->newtio.BaudRate = CBR_4800; break; + case SERIAL_BAUD_9600: h->newtio.BaudRate = CBR_9600; break; + case SERIAL_BAUD_19200: h->newtio.BaudRate = CBR_19200; break; + case SERIAL_BAUD_38400: h->newtio.BaudRate = CBR_38400; break; + case SERIAL_BAUD_57600: h->newtio.BaudRate = CBR_57600; break; + case SERIAL_BAUD_115200: h->newtio.BaudRate = CBR_115200; break; + case SERIAL_BAUD_128000: h->newtio.BaudRate = CBR_128000; break; + case SERIAL_BAUD_256000: h->newtio.BaudRate = CBR_256000; break; + /* These are not defined in WinBase.h and might work or not */ + case SERIAL_BAUD_230400: h->newtio.BaudRate = 230400; break; + case SERIAL_BAUD_460800: h->newtio.BaudRate = 460800; break; + case SERIAL_BAUD_500000: h->newtio.BaudRate = 500000; break; + case SERIAL_BAUD_576000: h->newtio.BaudRate = 576000; break; + case SERIAL_BAUD_921600: h->newtio.BaudRate = 921600; break; + case SERIAL_BAUD_1000000: h->newtio.BaudRate = 1000000; break; + case SERIAL_BAUD_1500000: h->newtio.BaudRate = 1500000; break; + case SERIAL_BAUD_2000000: h->newtio.BaudRate = 2000000; break; + case SERIAL_BAUD_INVALID: + + default: + return PORT_ERR_UNKNOWN; + } + + switch (bits) { + case SERIAL_BITS_5: h->newtio.ByteSize = 5; break; + case SERIAL_BITS_6: h->newtio.ByteSize = 6; break; + case SERIAL_BITS_7: h->newtio.ByteSize = 7; break; + case SERIAL_BITS_8: h->newtio.ByteSize = 8; break; + + default: + return PORT_ERR_UNKNOWN; + } + + switch (parity) { + case SERIAL_PARITY_NONE: h->newtio.Parity = NOPARITY; break; + case SERIAL_PARITY_EVEN: h->newtio.Parity = EVENPARITY; break; + case SERIAL_PARITY_ODD: h->newtio.Parity = ODDPARITY; break; + + default: + return PORT_ERR_UNKNOWN; + } + + switch (stopbit) { + case SERIAL_STOPBIT_1: h->newtio.StopBits = ONESTOPBIT; break; + case SERIAL_STOPBIT_2: h->newtio.StopBits = TWOSTOPBITS; break; + + default: + return PORT_ERR_UNKNOWN; + } + + /* reset the settings */ + h->newtio.fOutxCtsFlow = FALSE; + h->newtio.fOutxDsrFlow = FALSE; + h->newtio.fOutX = FALSE; + h->newtio.fInX = FALSE; + h->newtio.fNull = 0; + h->newtio.fAbortOnError = 0; + + /* set the settings */ + serial_flush(h); + if (!SetCommState(h->fd, &h->newtio)) + return PORT_ERR_UNKNOWN; + + snprintf(h->setup_str, sizeof(h->setup_str), "%u %d%c%d", + serial_get_baud_int(baud), + serial_get_bits_int(bits), + serial_get_parity_str(parity), + serial_get_stopbit_int(stopbit) + ); + return PORT_ERR_OK; +} + +static port_err_t serial_w32_open(struct port_interface *port, + struct port_options *ops) +{ + serial_t *h; + + /* 1. check device name match */ + if (!((strlen(ops->device) == 4 || strlen(ops->device) == 5) + && !strncmp(ops->device, "COM", 3) && isdigit(ops->device[3])) + && !(!strncmp(ops->device, "\\\\.\\COM", strlen("\\\\.\\COM")) + && isdigit(ops->device[strlen("\\\\.\\COM")]))) + return PORT_ERR_NODEV; + + /* 2. check options */ + if (ops->baudRate == SERIAL_BAUD_INVALID) + return PORT_ERR_UNKNOWN; + if (serial_get_bits(ops->serial_mode) == SERIAL_BITS_INVALID) + return PORT_ERR_UNKNOWN; + if (serial_get_parity(ops->serial_mode) == SERIAL_PARITY_INVALID) + return PORT_ERR_UNKNOWN; + if (serial_get_stopbit(ops->serial_mode) == SERIAL_STOPBIT_INVALID) + return PORT_ERR_UNKNOWN; + + /* 3. open it */ + h = serial_open(ops->device); + if (h == NULL) + return PORT_ERR_UNKNOWN; + + /* 4. set options */ + if (serial_setup(h, ops->baudRate, + serial_get_bits(ops->serial_mode), + serial_get_parity(ops->serial_mode), + serial_get_stopbit(ops->serial_mode) + ) != PORT_ERR_OK) { + serial_close(h); + return PORT_ERR_UNKNOWN; + } + + port->private = h; + return PORT_ERR_OK; +} + +static port_err_t serial_w32_close(struct port_interface *port) +{ + serial_t *h; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + serial_close(h); + port->private = NULL; + return PORT_ERR_OK; +} + +static port_err_t serial_w32_read(struct port_interface *port, void *buf, + size_t nbyte) +{ + serial_t *h; + DWORD r; + uint8_t *pos = (uint8_t *)buf; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + while (nbyte) { + ReadFile(h->fd, pos, nbyte, &r, NULL); + if (r == 0) + return PORT_ERR_TIMEDOUT; + if (r < 0) + return PORT_ERR_UNKNOWN; + + nbyte -= r; + pos += r; + } + return PORT_ERR_OK; +} + +static port_err_t serial_w32_write(struct port_interface *port, void *buf, + size_t nbyte) +{ + serial_t *h; + DWORD r; + uint8_t *pos = (uint8_t *)buf; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + while (nbyte) { + if (!WriteFile(h->fd, pos, nbyte, &r, NULL)) + return PORT_ERR_UNKNOWN; + if (r < 1) + return PORT_ERR_UNKNOWN; + + nbyte -= r; + pos += r; + } + return PORT_ERR_OK; +} + +static port_err_t serial_w32_gpio(struct port_interface *port, + serial_gpio_t n, int level) +{ + serial_t *h; + int bit; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + switch (n) { + case GPIO_RTS: + bit = level ? SETRTS : CLRRTS; + break; + + case GPIO_DTR: + bit = level ? SETDTR : CLRDTR; + break; + + case GPIO_BRK: + if (level == 0) + return PORT_ERR_OK; + if (EscapeCommFunction(h->fd, SETBREAK) == 0) + return PORT_ERR_UNKNOWN; + usleep(500000); + if (EscapeCommFunction(h->fd, CLRBREAK) == 0) + return PORT_ERR_UNKNOWN; + return PORT_ERR_OK; + + default: + return PORT_ERR_UNKNOWN; + } + + /* handle RTS/DTR */ + if (EscapeCommFunction(h->fd, bit) == 0) + return PORT_ERR_UNKNOWN; + + return PORT_ERR_OK; +} + +static const char *serial_w32_get_cfg_str(struct port_interface *port) +{ + serial_t *h; + + h = (serial_t *)port->private; + return h ? h->setup_str : "INVALID"; +} + +struct port_interface port_serial = { + .name = "serial_w32", + .flags = PORT_BYTE | PORT_GVR_ETX | PORT_CMD_INIT | PORT_RETRY, + .open = serial_w32_open, + .close = serial_w32_close, + .read = serial_w32_read, + .write = serial_w32_write, + .gpio = serial_w32_gpio, + .get_cfg_str = serial_w32_get_cfg_str, +}; diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/stm32.c b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/stm32.c new file mode 100644 index 0000000..74047d2 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/stm32.c @@ -0,0 +1,1048 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright 2010 Geoffrey McRae + Copyright 2012-2014 Tormod Volden + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include + +#include "stm32.h" +#include "port.h" +#include "utils.h" + +#define STM32_ACK 0x79 +#define STM32_NACK 0x1F +#define STM32_BUSY 0x76 + +#define STM32_CMD_INIT 0x7F +#define STM32_CMD_GET 0x00 /* get the version and command supported */ +#define STM32_CMD_GVR 0x01 /* get version and read protection status */ +#define STM32_CMD_GID 0x02 /* get ID */ +#define STM32_CMD_RM 0x11 /* read memory */ +#define STM32_CMD_GO 0x21 /* go */ +#define STM32_CMD_WM 0x31 /* write memory */ +#define STM32_CMD_WM_NS 0x32 /* no-stretch write memory */ +#define STM32_CMD_ER 0x43 /* erase */ +#define STM32_CMD_EE 0x44 /* extended erase */ +#define STM32_CMD_EE_NS 0x45 /* extended erase no-stretch */ +#define STM32_CMD_WP 0x63 /* write protect */ +#define STM32_CMD_WP_NS 0x64 /* write protect no-stretch */ +#define STM32_CMD_UW 0x73 /* write unprotect */ +#define STM32_CMD_UW_NS 0x74 /* write unprotect no-stretch */ +#define STM32_CMD_RP 0x82 /* readout protect */ +#define STM32_CMD_RP_NS 0x83 /* readout protect no-stretch */ +#define STM32_CMD_UR 0x92 /* readout unprotect */ +#define STM32_CMD_UR_NS 0x93 /* readout unprotect no-stretch */ +#define STM32_CMD_CRC 0xA1 /* compute CRC */ +#define STM32_CMD_ERR 0xFF /* not a valid command */ + +#define STM32_RESYNC_TIMEOUT 35 /* seconds */ +#define STM32_MASSERASE_TIMEOUT 35 /* seconds */ +#define STM32_SECTERASE_TIMEOUT 5 /* seconds */ +#define STM32_BLKWRITE_TIMEOUT 1 /* seconds */ +#define STM32_WUNPROT_TIMEOUT 1 /* seconds */ +#define STM32_WPROT_TIMEOUT 1 /* seconds */ +#define STM32_RPROT_TIMEOUT 1 /* seconds */ + +#define STM32_CMD_GET_LENGTH 17 /* bytes in the reply */ + +struct stm32_cmd { + uint8_t get; + uint8_t gvr; + uint8_t gid; + uint8_t rm; + uint8_t go; + uint8_t wm; + uint8_t er; /* this may be extended erase */ + uint8_t wp; + uint8_t uw; + uint8_t rp; + uint8_t ur; + uint8_t crc; +}; + +/* Reset code for ARMv7-M (Cortex-M3) and ARMv6-M (Cortex-M0) + * see ARMv7-M or ARMv6-M Architecture Reference Manual (table B3-8) + * or "The definitive guide to the ARM Cortex-M3", section 14.4. + */ +static const uint8_t stm_reset_code[] = { + 0x01, 0x49, // ldr r1, [pc, #4] ; () + 0x02, 0x4A, // ldr r2, [pc, #8] ; () + 0x0A, 0x60, // str r2, [r1, #0] + 0xfe, 0xe7, // endless: b endless + 0x0c, 0xed, 0x00, 0xe0, // .word 0xe000ed0c = NVIC AIRCR register address + 0x04, 0x00, 0xfa, 0x05 // .word 0x05fa0004 = VECTKEY | SYSRESETREQ +}; + +static const uint32_t stm_reset_code_length = sizeof(stm_reset_code); + +extern const stm32_dev_t devices[]; + +static void stm32_warn_stretching(const char *f) +{ + fprintf(stderr, "Attention !!!\n"); + fprintf(stderr, "\tThis %s error could be caused by your I2C\n", f); + fprintf(stderr, "\tcontroller not accepting \"clock stretching\"\n"); + fprintf(stderr, "\tas required by bootloader.\n"); + fprintf(stderr, "\tCheck \"I2C.txt\" in stm32flash source code.\n"); +} + +static stm32_err_t stm32_get_ack_timeout(const stm32_t *stm, time_t timeout) +{ + struct port_interface *port = stm->port; + uint8_t byte; + port_err_t p_err; + time_t t0, t1; + + if (!(port->flags & PORT_RETRY)) + timeout = 0; + + if (timeout) + time(&t0); + + do { + p_err = port->read(port, &byte, 1); + if (p_err == PORT_ERR_TIMEDOUT && timeout) { + time(&t1); + if (t1 < t0 + timeout) + continue; + } + + if (p_err != PORT_ERR_OK) { + fprintf(stderr, "Failed to read ACK byte\n"); + return STM32_ERR_UNKNOWN; + } + + if (byte == STM32_ACK) + return STM32_ERR_OK; + if (byte == STM32_NACK) + return STM32_ERR_NACK; + if (byte != STM32_BUSY) { + fprintf(stderr, "Got byte 0x%02x instead of ACK\n", + byte); + return STM32_ERR_UNKNOWN; + } + } while (1); +} + +static stm32_err_t stm32_get_ack(const stm32_t *stm) +{ + return stm32_get_ack_timeout(stm, 0); +} + +static stm32_err_t stm32_send_command_timeout(const stm32_t *stm, + const uint8_t cmd, + time_t timeout) +{ + struct port_interface *port = stm->port; + stm32_err_t s_err; + port_err_t p_err; + uint8_t buf[2]; + + buf[0] = cmd; + buf[1] = cmd ^ 0xFF; + p_err = port->write(port, buf, 2); + if (p_err != PORT_ERR_OK) { + fprintf(stderr, "Failed to send command\n"); + return STM32_ERR_UNKNOWN; + } + s_err = stm32_get_ack_timeout(stm, timeout); + if (s_err == STM32_ERR_OK) + return STM32_ERR_OK; + if (s_err == STM32_ERR_NACK) + fprintf(stderr, "Got NACK from device on command 0x%02x\n", cmd); + else + fprintf(stderr, "Unexpected reply from device on command 0x%02x\n", cmd); + return STM32_ERR_UNKNOWN; +} + +static stm32_err_t stm32_send_command(const stm32_t *stm, const uint8_t cmd) +{ + return stm32_send_command_timeout(stm, cmd, 0); +} + +/* if we have lost sync, send a wrong command and expect a NACK */ +static stm32_err_t stm32_resync(const stm32_t *stm) +{ + struct port_interface *port = stm->port; + port_err_t p_err; + uint8_t buf[2], ack; + time_t t0, t1; + + time(&t0); + t1 = t0; + + buf[0] = STM32_CMD_ERR; + buf[1] = STM32_CMD_ERR ^ 0xFF; + while (t1 < t0 + STM32_RESYNC_TIMEOUT) { + p_err = port->write(port, buf, 2); + if (p_err != PORT_ERR_OK) { + usleep(500000); + time(&t1); + continue; + } + p_err = port->read(port, &ack, 1); + if (p_err != PORT_ERR_OK) { + time(&t1); + continue; + } + if (ack == STM32_NACK) + return STM32_ERR_OK; + time(&t1); + } + return STM32_ERR_UNKNOWN; +} + +/* + * some command receive reply frame with variable length, and length is + * embedded in reply frame itself. + * We can guess the length, but if we guess wrong the protocol gets out + * of sync. + * Use resync for frame oriented interfaces (e.g. I2C) and byte-by-byte + * read for byte oriented interfaces (e.g. UART). + * + * to run safely, data buffer should be allocated for 256+1 bytes + * + * len is value of the first byte in the frame. + */ +static stm32_err_t stm32_guess_len_cmd(const stm32_t *stm, uint8_t cmd, + uint8_t *data, unsigned int len) +{ + struct port_interface *port = stm->port; + port_err_t p_err; + + if (stm32_send_command(stm, cmd) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + if (port->flags & PORT_BYTE) { + /* interface is UART-like */ + p_err = port->read(port, data, 1); + if (p_err != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + len = data[0]; + p_err = port->read(port, data + 1, len + 1); + if (p_err != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + return STM32_ERR_OK; + } + + p_err = port->read(port, data, len + 2); + if (p_err == PORT_ERR_OK && len == data[0]) + return STM32_ERR_OK; + if (p_err != PORT_ERR_OK) { + /* restart with only one byte */ + if (stm32_resync(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + if (stm32_send_command(stm, cmd) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + p_err = port->read(port, data, 1); + if (p_err != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + } + + fprintf(stderr, "Re sync (len = %d)\n", data[0]); + if (stm32_resync(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + len = data[0]; + if (stm32_send_command(stm, cmd) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + p_err = port->read(port, data, len + 2); + if (p_err != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + return STM32_ERR_OK; +} + +/* + * Some interface, e.g. UART, requires a specific init sequence to let STM32 + * autodetect the interface speed. + * The sequence is only required one time after reset. + * stm32flash has command line flag "-c" to prevent sending the init sequence + * in case it was already sent before. + * User can easily forget adding "-c". In this case the bootloader would + * interpret the init sequence as part of a command message, then waiting for + * the rest of the message blocking the interface. + * This function sends the init sequence and, in case of timeout, recovers + * the interface. + */ +static stm32_err_t stm32_send_init_seq(const stm32_t *stm) +{ + struct port_interface *port = stm->port; + port_err_t p_err; + uint8_t byte, cmd = STM32_CMD_INIT; + + p_err = port->write(port, &cmd, 1); + if (p_err != PORT_ERR_OK) { + fprintf(stderr, "Failed to send init to device\n"); + return STM32_ERR_UNKNOWN; + } + p_err = port->read(port, &byte, 1); + if (p_err == PORT_ERR_OK && byte == STM32_ACK) + return STM32_ERR_OK; + if (p_err == PORT_ERR_OK && byte == STM32_NACK) { + /* We could get error later, but let's continue, for now. */ + fprintf(stderr, + "Warning: the interface was not closed properly.\n"); + return STM32_ERR_OK; + } + if (p_err != PORT_ERR_TIMEDOUT) { + fprintf(stderr, "Failed to init device.\n"); + return STM32_ERR_UNKNOWN; + } + + /* + * Check if previous STM32_CMD_INIT was taken as first byte + * of a command. Send a new byte, we should get back a NACK. + */ + p_err = port->write(port, &cmd, 1); + if (p_err != PORT_ERR_OK) { + fprintf(stderr, "Failed to send init to device\n"); + return STM32_ERR_UNKNOWN; + } + p_err = port->read(port, &byte, 1); + if (p_err == PORT_ERR_OK && byte == STM32_NACK) + return STM32_ERR_OK; + fprintf(stderr, "Failed to init device.\n"); + return STM32_ERR_UNKNOWN; +} + +/* find newer command by higher code */ +#define newer(prev, a) (((prev) == STM32_CMD_ERR) \ + ? (a) \ + : (((prev) > (a)) ? (prev) : (a))) + +stm32_t *stm32_init(struct port_interface *port, const char init) +{ + uint8_t len, val, buf[257]; + stm32_t *stm; + int i, new_cmds; + + stm = calloc(sizeof(stm32_t), 1); + stm->cmd = malloc(sizeof(stm32_cmd_t)); + memset(stm->cmd, STM32_CMD_ERR, sizeof(stm32_cmd_t)); + stm->port = port; + + if ((port->flags & PORT_CMD_INIT) && init) + if (stm32_send_init_seq(stm) != STM32_ERR_OK) + return NULL; + + /* get the version and read protection status */ + if (stm32_send_command(stm, STM32_CMD_GVR) != STM32_ERR_OK) { + stm32_close(stm); + return NULL; + } + + /* From AN, only UART bootloader returns 3 bytes */ + len = (port->flags & PORT_GVR_ETX) ? 3 : 1; + if (port->read(port, buf, len) != PORT_ERR_OK) + return NULL; + stm->version = buf[0]; + stm->option1 = (port->flags & PORT_GVR_ETX) ? buf[1] : 0; + stm->option2 = (port->flags & PORT_GVR_ETX) ? buf[2] : 0; + if (stm32_get_ack(stm) != STM32_ERR_OK) { + stm32_close(stm); + return NULL; + } + + /* get the bootloader information */ + len = STM32_CMD_GET_LENGTH; + if (port->cmd_get_reply) + for (i = 0; port->cmd_get_reply[i].length; i++) + if (stm->version == port->cmd_get_reply[i].version) { + len = port->cmd_get_reply[i].length; + break; + } + if (stm32_guess_len_cmd(stm, STM32_CMD_GET, buf, len) != STM32_ERR_OK) + return NULL; + len = buf[0] + 1; + stm->bl_version = buf[1]; + new_cmds = 0; + for (i = 1; i < len; i++) { + val = buf[i + 1]; + switch (val) { + case STM32_CMD_GET: + stm->cmd->get = val; break; + case STM32_CMD_GVR: + stm->cmd->gvr = val; break; + case STM32_CMD_GID: + stm->cmd->gid = val; break; + case STM32_CMD_RM: + stm->cmd->rm = val; break; + case STM32_CMD_GO: + stm->cmd->go = val; break; + case STM32_CMD_WM: + case STM32_CMD_WM_NS: + stm->cmd->wm = newer(stm->cmd->wm, val); + break; + case STM32_CMD_ER: + case STM32_CMD_EE: + case STM32_CMD_EE_NS: + stm->cmd->er = newer(stm->cmd->er, val); + break; + case STM32_CMD_WP: + case STM32_CMD_WP_NS: + stm->cmd->wp = newer(stm->cmd->wp, val); + break; + case STM32_CMD_UW: + case STM32_CMD_UW_NS: + stm->cmd->uw = newer(stm->cmd->uw, val); + break; + case STM32_CMD_RP: + case STM32_CMD_RP_NS: + stm->cmd->rp = newer(stm->cmd->rp, val); + break; + case STM32_CMD_UR: + case STM32_CMD_UR_NS: + stm->cmd->ur = newer(stm->cmd->ur, val); + break; + case STM32_CMD_CRC: + stm->cmd->crc = newer(stm->cmd->crc, val); + break; + default: + if (new_cmds++ == 0) + fprintf(stderr, + "GET returns unknown commands (0x%2x", + val); + else + fprintf(stderr, ", 0x%2x", val); + } + } + if (new_cmds) + fprintf(stderr, ")\n"); + if (stm32_get_ack(stm) != STM32_ERR_OK) { + stm32_close(stm); + return NULL; + } + + if (stm->cmd->get == STM32_CMD_ERR + || stm->cmd->gvr == STM32_CMD_ERR + || stm->cmd->gid == STM32_CMD_ERR) { + fprintf(stderr, "Error: bootloader did not returned correct information from GET command\n"); + return NULL; + } + + /* get the device ID */ + if (stm32_guess_len_cmd(stm, stm->cmd->gid, buf, 1) != STM32_ERR_OK) { + stm32_close(stm); + return NULL; + } + len = buf[0] + 1; + if (len < 2) { + stm32_close(stm); + fprintf(stderr, "Only %d bytes sent in the PID, unknown/unsupported device\n", len); + return NULL; + } + stm->pid = (buf[1] << 8) | buf[2]; + if (len > 2) { + fprintf(stderr, "This bootloader returns %d extra bytes in PID:", len); + for (i = 2; i <= len ; i++) + fprintf(stderr, " %02x", buf[i]); + fprintf(stderr, "\n"); + } + if (stm32_get_ack(stm) != STM32_ERR_OK) { + stm32_close(stm); + return NULL; + } + + stm->dev = devices; + while (stm->dev->id != 0x00 && stm->dev->id != stm->pid) + ++stm->dev; + + if (!stm->dev->id) { + fprintf(stderr, "Unknown/unsupported device (Device ID: 0x%03x)\n", stm->pid); + stm32_close(stm); + return NULL; + } + + return stm; +} + +void stm32_close(stm32_t *stm) +{ + if (stm) + free(stm->cmd); + free(stm); +} + +stm32_err_t stm32_read_memory(const stm32_t *stm, uint32_t address, + uint8_t data[], unsigned int len) +{ + struct port_interface *port = stm->port; + uint8_t buf[5]; + + if (!len) + return STM32_ERR_OK; + + if (len > 256) { + fprintf(stderr, "Error: READ length limit at 256 bytes\n"); + return STM32_ERR_UNKNOWN; + } + + if (stm->cmd->rm == STM32_CMD_ERR) { + fprintf(stderr, "Error: READ command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->rm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + buf[0] = address >> 24; + buf[1] = (address >> 16) & 0xFF; + buf[2] = (address >> 8) & 0xFF; + buf[3] = address & 0xFF; + buf[4] = buf[0] ^ buf[1] ^ buf[2] ^ buf[3]; + if (port->write(port, buf, 5) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + if (stm32_get_ack(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (stm32_send_command(stm, len - 1) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (port->read(port, data, len) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + + return STM32_ERR_OK; +} + +stm32_err_t stm32_write_memory(const stm32_t *stm, uint32_t address, + const uint8_t data[], unsigned int len) +{ + struct port_interface *port = stm->port; + uint8_t cs, buf[256 + 2]; + unsigned int i, aligned_len; + stm32_err_t s_err; + + if (!len) + return STM32_ERR_OK; + + if (len > 256) { + fprintf(stderr, "Error: READ length limit at 256 bytes\n"); + return STM32_ERR_UNKNOWN; + } + + /* must be 32bit aligned */ + if (address & 0x3 || len & 0x3) { + fprintf(stderr, "Error: WRITE address and length must be 4 byte aligned\n"); + return STM32_ERR_UNKNOWN; + } + + if (stm->cmd->wm == STM32_CMD_ERR) { + fprintf(stderr, "Error: WRITE command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + /* send the address and checksum */ + if (stm32_send_command(stm, stm->cmd->wm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + buf[0] = address >> 24; + buf[1] = (address >> 16) & 0xFF; + buf[2] = (address >> 8) & 0xFF; + buf[3] = address & 0xFF; + buf[4] = buf[0] ^ buf[1] ^ buf[2] ^ buf[3]; + if (port->write(port, buf, 5) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + if (stm32_get_ack(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + aligned_len = (len + 3) & ~3; + cs = aligned_len - 1; + buf[0] = aligned_len - 1; + for (i = 0; i < len; i++) { + cs ^= data[i]; + buf[i + 1] = data[i]; + } + /* padding data */ + for (i = len; i < aligned_len; i++) { + cs ^= 0xFF; + buf[i + 1] = 0xFF; + } + buf[aligned_len + 1] = cs; + if (port->write(port, buf, aligned_len + 2) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + + s_err = stm32_get_ack_timeout(stm, STM32_BLKWRITE_TIMEOUT); + if (s_err != STM32_ERR_OK) { + if (port->flags & PORT_STRETCH_W + && stm->cmd->wm != STM32_CMD_WM_NS) + stm32_warn_stretching("write"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; +} + +stm32_err_t stm32_wunprot_memory(const stm32_t *stm) +{ + struct port_interface *port = stm->port; + stm32_err_t s_err; + + if (stm->cmd->uw == STM32_CMD_ERR) { + fprintf(stderr, "Error: WRITE UNPROTECT command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->uw) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + s_err = stm32_get_ack_timeout(stm, STM32_WUNPROT_TIMEOUT); + if (s_err == STM32_NACK) { + fprintf(stderr, "Error: Failed to WRITE UNPROTECT\n"); + return STM32_ERR_UNKNOWN; + } + if (s_err != STM32_ERR_OK) { + if (port->flags & PORT_STRETCH_W + && stm->cmd->uw != STM32_CMD_UW_NS) + stm32_warn_stretching("WRITE UNPROTECT"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; +} + +stm32_err_t stm32_wprot_memory(const stm32_t *stm) +{ + struct port_interface *port = stm->port; + stm32_err_t s_err; + + if (stm->cmd->wp == STM32_CMD_ERR) { + fprintf(stderr, "Error: WRITE PROTECT command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->wp) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + s_err = stm32_get_ack_timeout(stm, STM32_WPROT_TIMEOUT); + if (s_err == STM32_NACK) { + fprintf(stderr, "Error: Failed to WRITE PROTECT\n"); + return STM32_ERR_UNKNOWN; + } + if (s_err != STM32_ERR_OK) { + if (port->flags & PORT_STRETCH_W + && stm->cmd->wp != STM32_CMD_WP_NS) + stm32_warn_stretching("WRITE PROTECT"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; +} + +stm32_err_t stm32_runprot_memory(const stm32_t *stm) +{ + struct port_interface *port = stm->port; + stm32_err_t s_err; + + if (stm->cmd->ur == STM32_CMD_ERR) { + fprintf(stderr, "Error: READOUT UNPROTECT command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->ur) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + s_err = stm32_get_ack_timeout(stm, STM32_MASSERASE_TIMEOUT); + if (s_err == STM32_NACK) { + fprintf(stderr, "Error: Failed to READOUT UNPROTECT\n"); + return STM32_ERR_UNKNOWN; + } + if (s_err != STM32_ERR_OK) { + if (port->flags & PORT_STRETCH_W + && stm->cmd->ur != STM32_CMD_UR_NS) + stm32_warn_stretching("READOUT UNPROTECT"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; +} + +stm32_err_t stm32_readprot_memory(const stm32_t *stm) +{ + struct port_interface *port = stm->port; + stm32_err_t s_err; + + if (stm->cmd->rp == STM32_CMD_ERR) { + fprintf(stderr, "Error: READOUT PROTECT command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->rp) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + s_err = stm32_get_ack_timeout(stm, STM32_RPROT_TIMEOUT); + if (s_err == STM32_NACK) { + fprintf(stderr, "Error: Failed to READOUT PROTECT\n"); + return STM32_ERR_UNKNOWN; + } + if (s_err != STM32_ERR_OK) { + if (port->flags & PORT_STRETCH_W + && stm->cmd->rp != STM32_CMD_RP_NS) + stm32_warn_stretching("READOUT PROTECT"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; +} + +stm32_err_t stm32_erase_memory(const stm32_t *stm, uint8_t spage, uint8_t pages) +{ + struct port_interface *port = stm->port; + stm32_err_t s_err; + port_err_t p_err; + + if (!pages) + return STM32_ERR_OK; + + if (stm->cmd->er == STM32_CMD_ERR) { + fprintf(stderr, "Error: ERASE command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->er) != STM32_ERR_OK) { + fprintf(stderr, "Can't initiate chip erase!\n"); + return STM32_ERR_UNKNOWN; + } + + /* The erase command reported by the bootloader is either 0x43, 0x44 or 0x45 */ + /* 0x44 is Extended Erase, a 2 byte based protocol and needs to be handled differently. */ + /* 0x45 is clock no-stretching version of Extended Erase for I2C port. */ + if (stm->cmd->er != STM32_CMD_ER) { + /* Not all chips using Extended Erase support mass erase */ + /* Currently known as not supporting mass erase is the Ultra Low Power STM32L15xx range */ + /* So if someone has not overridden the default, but uses one of these chips, take it out of */ + /* mass erase mode, so it will be done page by page. This maximum might not be correct either! */ + if (stm->pid == 0x416 && pages == 0xFF) + pages = 0xF8; /* works for the STM32L152RB with 128Kb flash */ + + if (pages == 0xFF) { + uint8_t buf[3]; + + /* 0xFFFF the magic number for mass erase */ + buf[0] = 0xFF; + buf[1] = 0xFF; + buf[2] = 0x00; /* checksum */ + if (port->write(port, buf, 3) != PORT_ERR_OK) { + fprintf(stderr, "Mass erase error.\n"); + return STM32_ERR_UNKNOWN; + } + s_err = stm32_get_ack_timeout(stm, STM32_MASSERASE_TIMEOUT); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Mass erase failed. Try specifying the number of pages to be erased.\n"); + if (port->flags & PORT_STRETCH_W + && stm->cmd->er != STM32_CMD_EE_NS) + stm32_warn_stretching("erase"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; + } + + uint16_t pg_num; + uint8_t pg_byte; + uint8_t cs = 0; + uint8_t *buf; + int i = 0; + + buf = malloc(2 + 2 * pages + 1); + if (!buf) + return STM32_ERR_UNKNOWN; + + /* Number of pages to be erased - 1, two bytes, MSB first */ + pg_byte = (pages - 1) >> 8; + buf[i++] = pg_byte; + cs ^= pg_byte; + pg_byte = (pages - 1) & 0xFF; + buf[i++] = pg_byte; + cs ^= pg_byte; + + for (pg_num = spage; pg_num < spage + pages; pg_num++) { + pg_byte = pg_num >> 8; + cs ^= pg_byte; + buf[i++] = pg_byte; + pg_byte = pg_num & 0xFF; + cs ^= pg_byte; + buf[i++] = pg_byte; + } + buf[i++] = cs; + p_err = port->write(port, buf, i); + free(buf); + if (p_err != PORT_ERR_OK) { + fprintf(stderr, "Page-by-page erase error.\n"); + return STM32_ERR_UNKNOWN; + } + + s_err = stm32_get_ack_timeout(stm, pages * STM32_SECTERASE_TIMEOUT); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Page-by-page erase failed. Check the maximum pages your device supports.\n"); + if (port->flags & PORT_STRETCH_W + && stm->cmd->er != STM32_CMD_EE_NS) + stm32_warn_stretching("erase"); + return STM32_ERR_UNKNOWN; + } + + return STM32_ERR_OK; + } + + /* And now the regular erase (0x43) for all other chips */ + if (pages == 0xFF) { + s_err = stm32_send_command_timeout(stm, 0xFF, STM32_MASSERASE_TIMEOUT); + if (s_err != STM32_ERR_OK) { + if (port->flags & PORT_STRETCH_W) + stm32_warn_stretching("erase"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; + } else { + uint8_t cs = 0; + uint8_t pg_num; + uint8_t *buf; + int i = 0; + + buf = malloc(1 + pages + 1); + if (!buf) + return STM32_ERR_UNKNOWN; + + buf[i++] = pages - 1; + cs ^= (pages-1); + for (pg_num = spage; pg_num < (pages + spage); pg_num++) { + buf[i++] = pg_num; + cs ^= pg_num; + } + buf[i++] = cs; + p_err = port->write(port, buf, i); + free(buf); + if (p_err != PORT_ERR_OK) { + fprintf(stderr, "Erase failed.\n"); + return STM32_ERR_UNKNOWN; + } + s_err = stm32_get_ack_timeout(stm, STM32_MASSERASE_TIMEOUT); + if (s_err != STM32_ERR_OK) { + if (port->flags & PORT_STRETCH_W) + stm32_warn_stretching("erase"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; + } +} + +static stm32_err_t stm32_run_raw_code(const stm32_t *stm, + uint32_t target_address, + const uint8_t *code, uint32_t code_size) +{ + uint32_t stack_le = le_u32(0x20002000); + uint32_t code_address_le = le_u32(target_address + 8); + uint32_t length = code_size + 8; + uint8_t *mem, *pos; + uint32_t address, w; + + /* Must be 32-bit aligned */ + if (target_address & 0x3) { + fprintf(stderr, "Error: code address must be 4 byte aligned\n"); + return STM32_ERR_UNKNOWN; + } + + mem = malloc(length); + if (!mem) + return STM32_ERR_UNKNOWN; + + memcpy(mem, &stack_le, sizeof(uint32_t)); + memcpy(mem + 4, &code_address_le, sizeof(uint32_t)); + memcpy(mem + 8, code, code_size); + + pos = mem; + address = target_address; + while (length > 0) { + w = length > 256 ? 256 : length; + if (stm32_write_memory(stm, address, pos, w) != STM32_ERR_OK) { + free(mem); + return STM32_ERR_UNKNOWN; + } + + address += w; + pos += w; + length -= w; + } + + free(mem); + return stm32_go(stm, target_address); +} + +stm32_err_t stm32_go(const stm32_t *stm, uint32_t address) +{ + struct port_interface *port = stm->port; + uint8_t buf[5]; + + if (stm->cmd->go == STM32_CMD_ERR) { + fprintf(stderr, "Error: GO command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->go) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + buf[0] = address >> 24; + buf[1] = (address >> 16) & 0xFF; + buf[2] = (address >> 8) & 0xFF; + buf[3] = address & 0xFF; + buf[4] = buf[0] ^ buf[1] ^ buf[2] ^ buf[3]; + if (port->write(port, buf, 5) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (stm32_get_ack(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + return STM32_ERR_OK; +} + +stm32_err_t stm32_reset_device(const stm32_t *stm) +{ + uint32_t target_address = stm->dev->ram_start; + + return stm32_run_raw_code(stm, target_address, stm_reset_code, stm_reset_code_length); +} + +stm32_err_t stm32_crc_memory(const stm32_t *stm, uint32_t address, + uint32_t length, uint32_t *crc) +{ + struct port_interface *port = stm->port; + uint8_t buf[5]; + + if (address & 0x3 || length & 0x3) { + fprintf(stderr, "Start and end addresses must be 4 byte aligned\n"); + return STM32_ERR_UNKNOWN; + } + + if (stm->cmd->crc == STM32_CMD_ERR) { + fprintf(stderr, "Error: CRC command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->crc) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + buf[0] = address >> 24; + buf[1] = (address >> 16) & 0xFF; + buf[2] = (address >> 8) & 0xFF; + buf[3] = address & 0xFF; + buf[4] = buf[0] ^ buf[1] ^ buf[2] ^ buf[3]; + if (port->write(port, buf, 5) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (stm32_get_ack(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + buf[0] = length >> 24; + buf[1] = (length >> 16) & 0xFF; + buf[2] = (length >> 8) & 0xFF; + buf[3] = length & 0xFF; + buf[4] = buf[0] ^ buf[1] ^ buf[2] ^ buf[3]; + if (port->write(port, buf, 5) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (stm32_get_ack(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (stm32_get_ack(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (port->read(port, buf, 5) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (buf[4] != (buf[0] ^ buf[1] ^ buf[2] ^ buf[3])) + return STM32_ERR_UNKNOWN; + + *crc = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; + return STM32_ERR_OK; +} + +/* + * CRC computed by STM32 is similar to the standard crc32_be() + * implemented, for example, in Linux kernel in ./lib/crc32.c + * But STM32 computes it on units of 32 bits word and swaps the + * bytes of the word before the computation. + * Due to byte swap, I cannot use any CRC available in existing + * libraries, so here is a simple not optimized implementation. + */ +#define CRCPOLY_BE 0x04c11db7 +#define CRC_MSBMASK 0x80000000 +#define CRC_INIT_VALUE 0xFFFFFFFF +uint32_t stm32_sw_crc(uint32_t crc, uint8_t *buf, unsigned int len) +{ + int i; + uint32_t data; + + if (len & 0x3) { + fprintf(stderr, "Buffer length must be multiple of 4 bytes\n"); + return 0; + } + + while (len) { + data = *buf++; + data |= *buf++ << 8; + data |= *buf++ << 16; + data |= *buf++ << 24; + len -= 4; + + crc ^= data; + + for (i = 0; i < 32; i++) + if (crc & CRC_MSBMASK) + crc = (crc << 1) ^ CRCPOLY_BE; + else + crc = (crc << 1); + } + return crc; +} + +stm32_err_t stm32_crc_wrapper(const stm32_t *stm, uint32_t address, + uint32_t length, uint32_t *crc) +{ + uint8_t buf[256]; + uint32_t start, total_len, len, current_crc; + + if (address & 0x3 || length & 0x3) { + fprintf(stderr, "Start and end addresses must be 4 byte aligned\n"); + return STM32_ERR_UNKNOWN; + } + + if (stm->cmd->crc != STM32_CMD_ERR) + return stm32_crc_memory(stm, address, length, crc); + + start = address; + total_len = length; + current_crc = CRC_INIT_VALUE; + while (length) { + len = length > 256 ? 256 : length; + if (stm32_read_memory(stm, address, buf, len) != STM32_ERR_OK) { + fprintf(stderr, + "Failed to read memory at address 0x%08x, target write-protected?\n", + address); + return STM32_ERR_UNKNOWN; + } + current_crc = stm32_sw_crc(current_crc, buf, len); + length -= len; + address += len; + + fprintf(stderr, + "\rCRC address 0x%08x (%.2f%%) ", + address, + (100.0f / (float)total_len) * (float)(address - start) + ); + fflush(stderr); + } + fprintf(stderr, "Done.\n"); + *crc = current_crc; + return STM32_ERR_OK; +} diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/stm32.h b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/stm32.h new file mode 100644 index 0000000..1688fcb --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/stm32.h @@ -0,0 +1,84 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _STM32_H +#define _STM32_H + +#include +#include "serial.h" + +#define STM32_MAX_RX_FRAME 256 /* cmd read memory */ +#define STM32_MAX_TX_FRAME (1 + 256 + 1) /* cmd write memory */ + +typedef enum { + STM32_ERR_OK = 0, + STM32_ERR_UNKNOWN, /* Generic error */ + STM32_ERR_NACK, + STM32_ERR_NO_CMD, /* Command not available in bootloader */ +} stm32_err_t; + +typedef struct stm32 stm32_t; +typedef struct stm32_cmd stm32_cmd_t; +typedef struct stm32_dev stm32_dev_t; + +struct stm32 { + const serial_t *serial; + struct port_interface *port; + uint8_t bl_version; + uint8_t version; + uint8_t option1, option2; + uint16_t pid; + stm32_cmd_t *cmd; + const stm32_dev_t *dev; +}; + +struct stm32_dev { + uint16_t id; + const char *name; + uint32_t ram_start, ram_end; + uint32_t fl_start, fl_end; + uint16_t fl_pps; // pages per sector + uint16_t fl_ps; // page size + uint32_t opt_start, opt_end; + uint32_t mem_start, mem_end; +}; + +stm32_t *stm32_init(struct port_interface *port, const char init); +void stm32_close(stm32_t *stm); +stm32_err_t stm32_read_memory(const stm32_t *stm, uint32_t address, + uint8_t data[], unsigned int len); +stm32_err_t stm32_write_memory(const stm32_t *stm, uint32_t address, + const uint8_t data[], unsigned int len); +stm32_err_t stm32_wunprot_memory(const stm32_t *stm); +stm32_err_t stm32_wprot_memory(const stm32_t *stm); +stm32_err_t stm32_erase_memory(const stm32_t *stm, uint8_t spage, + uint8_t pages); +stm32_err_t stm32_go(const stm32_t *stm, uint32_t address); +stm32_err_t stm32_reset_device(const stm32_t *stm); +stm32_err_t stm32_readprot_memory(const stm32_t *stm); +stm32_err_t stm32_runprot_memory(const stm32_t *stm); +stm32_err_t stm32_crc_memory(const stm32_t *stm, uint32_t address, + uint32_t length, uint32_t *crc); +stm32_err_t stm32_crc_wrapper(const stm32_t *stm, uint32_t address, + uint32_t length, uint32_t *crc); +uint32_t stm32_sw_crc(uint32_t crc, uint8_t *buf, unsigned int len); + +#endif + diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/stm32flash.1 b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/stm32flash.1 new file mode 100644 index 0000000..d37292f --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/stm32flash.1 @@ -0,0 +1,407 @@ +.TH STM32FLASH 1 "2013\-11\-03" STM32FLASH "User command" +.SH NAME +stm32flash \- flashing utility for STM32 and STM32W through UART or I2C +.SH SYNOPSIS +.B stm32flash +.RB [ \-cfhjkouvCR ] +.RB [ \-a +.IR bus_address ] +.RB [ \-b +.IR baud_rate ] +.RB [ \-m +.IR serial_mode ] +.RB [ \-r +.IR filename ] +.RB [ \-w +.IR filename ] +.RB [ \-e +.IR num ] +.RB [ \-n +.IR count ] +.RB [ \-g +.IR address ] +.RB [ \-s +.IR start_page ] +.RB [ \-S +.IR address [: length ]] +.RB [ \-F +.IR RX_length [: TX_length ]] +.RB [ \-i +.IR GPIO_string ] +.RI [ tty_device +.R | +.IR i2c_device ] + +.SH DESCRIPTION +.B stm32flash +reads or writes the flash memory of STM32 and STM32W. + +It requires the STM32[W] to embed a bootloader compliant with ST +application note AN3155. +.B stm32flash +uses the serial port +.I tty_device +to interact with the bootloader of STM32[W]. + +.SH OPTIONS +.TP +.BI "\-a" " bus_address" +Specify address on bus for +.IR i2c_device . +This option is mandatory for I2C interface. + +.TP +.BI "\-b" " baud_rate" +Specify baud rate speed of +.IR tty_device . +Please notice that the ST bootloader can automatically detect the baud rate, +as explaned in chapter 2 of AN3155. +This option could be required together with option +.B "\-c" +or if following interaction with bootloader is expected. +Default is +.IR 57600 . + +.TP +.BI "\-m" " mode" +Specify the format of UART data. +.I mode +is a three characters long string where each character specifies, in +this strict order, character size, parity and stop bits. +The only values currenly used are +.I 8e1 +for standard STM32 bootloader and +.I 8n1 +for standard STM32W bootloader. +Default is +.IR 8e1 . + +.TP +.BI "\-r" " filename" +Specify to read the STM32[W] flash and write its content in +.I filename +in raw binary format (see below +.BR "FORMAT CONVERSION" ). + +.TP +.BI "\-w" " filename" +Specify to write the STM32[W] flash with the content of +.IR filename . +File format can be either raw binary or intel hex (see below +.BR "FORMAT CONVERSION" ). +The file format is automatically detected. +To by\-pass format detection and force binary mode (e.g. to +write an intel hex content in STM32[W] flash), use +.B \-f +option. + +.TP +.B \-u +Specify to disable write\-protection from STM32[W] flash. +The STM32[W] will be reset after this operation. + +.TP +.B \-j +Enable the flash read\-protection. + +.TP +.B \-k +Disable the flash read\-protection. + +.TP +.B \-o +Erase only. + +.TP +.BI "\-e" " num" +Specify to erase only +.I num +pages before writing the flash. Default is to erase the whole flash. With +.B \-e 0 +the flash would not be erased. + +.TP +.B \-v +Specify to verify flash content after write operation. + +.TP +.BI "\-n" " count" +Specify to retry failed writes up to +.I count +times. Default is 10 times. + +.TP +.BI "\-g" " address" +Specify address to start execution from (0 = flash start). + +.TP +.BI "\-s" " start_page" +Specify flash page offset (0 = flash start). + +.TP +.BI "\-S" " address" "[:" "length" "]" +Specify start address and optionally length for read/write/erase/crc operations. + +.TP +.BI "\-F" " RX_length" "[:" "TX_length" "]" +Specify the maximum frame size for the current interface. +Due to STM32 bootloader protocol, host will never handle frames bigger than +256 byte in RX or 258 byte in TX. +Due to current code, lowest limit in RX is 20 byte (to read a complete reply +of command GET). Minimum limit in TX is 5 byte, required by protocol. + +.TP +.B \-f +Force binary parser while reading file with +.BR "\-w" "." + +.TP +.B \-h +Show help. + +.TP +.B \-c +Specify to resume the existing UART connection and don't send initial +INIT sequence to detect baud rate. Baud rate must be kept the same as the +existing connection. This is useful if the reset fails. + +.TP +.BI "\-i" " GPIO_string" +Specify the GPIO sequences on the host to force STM32[W] to enter and +exit bootloader mode. GPIO can either be real GPIO connected from host to +STM32[W] beside the UART connection, or UART's modem signals used as +GPIO. (See below +.B BOOTLOADER GPIO SEQUENCE +for the format of +.I GPIO_string +and further explanation). + +.TP +.B \-C +Specify to compute CRC on memory content. +By default the CRC is computed on the whole flash content. +Use +.B "\-S" +to provide different memory address range. + +.TP +.B \-R +Specify to reset the device at exit. +This option is ignored if either +.BR "\-g" "," +.BR "\-j" "," +.B "\-k" +or +.B "\-u" +is also specified. + +.SH BOOTLOADER GPIO SEQUENCE +This feature is currently available on Linux host only. + +As explained in ST application note AN2606, after reset the STM32 will +execute either the application program in user flash or the bootloader, +depending on the level applied at specific pins of STM32 during reset. + +STM32 bootloader is automatically activated by configuring the pins +BOOT0="high" and BOOT1="low" and then by applying a reset. +Application program in user flash is activated by configuring the pin +BOOT0="low" (the level on BOOT1 is ignored) and then by applying a reset. + +When GPIO from host computer are connected to either configuration and +reset pins of STM32, +.B stm32flash +can control the host GPIO to reset STM32 and to force execution of +bootloader or execution of application program. + +The sequence of GPIO values to entry to and exit from bootloader mode is +provided with command line option +.B "\-i" +.IR "GPIO_string" . + +.PD 0 +The format of +.IR "GPIO_string" " is:" +.RS +GPIO_string = [entry sequence][:[exit sequence]] +.P +sequence = [\-]n[,sequence] +.RE +.P +In the above sequences, negative numbers correspond to GPIO at "low" level; +numbers without sign correspond to GPIO at "high" level. +The value "n" can either be the GPIO number on the host system or the +string "rts", "dtr" or "brk". The strings "rts" and "dtr" drive the +corresponding UART's modem lines RTS and DTR as GPIO. +The string "brk" forces the UART to send a BREAK sequence on TX line; +after BREAK the UART is returned in normal "non\-break" mode. +Note: the string "\-brk" has no effect and is ignored. +.PD + +.PD 0 +As example, let's suppose the following connection between host and STM32: +.IP \(bu 2 +host GPIO_3 connected to reset pin of STM32; +.IP \(bu 2 +host GPIO_4 connected to STM32 pin BOOT0; +.IP \(bu 2 +host GPIO_5 connected to STM32 pin BOOT1. +.PD +.P + +In this case, the sequence to enter in bootloader mode is: first put +GPIO_4="high" and GPIO_5="low"; then send reset pulse by GPIO_3="low" +followed by GPIO_3="high". +The corresponding string for +.I GPIO_string +is "4,\-5,\-3,3". + +To exit from bootloade and run the application program, the sequence is: +put GPIO_4="low"; then send reset pulse. +The corresponding string for +.I GPIO_string +is "\-4,\-3,3". + +The complete command line flag is "\-i 4,\-5,\-3,3:\-4,\-3,3". + +STM32W uses pad PA5 to select boot mode; if during reset PA5 is "low" then +STM32W will enter in bootloader mode; if PA5 is "high" it will execute the +program in flash. + +As example, supposing GPIO_3 connected to PA5 and GPIO_2 to STM32W's reset. +The command: +.PD 0 +.RS +stm32flash \-i \-3,\-2,2:3,\-2,2 /dev/ttyS0 +.RE +provides: +.IP \(bu 2 +entry sequence: GPIO_3=low, GPIO_2=low, GPIO_2=high +.IP \(bu 2 +exit sequence: GPIO_3=high, GPIO_2=low, GPIO_2=high +.PD + +.SH EXAMPLES +Get device information: +.RS +.PD 0 +.P +stm32flash /dev/ttyS0 +.PD +.RE + +Write with verify and then start execution: +.RS +.PD 0 +.P +stm32flash \-w filename \-v \-g 0x0 /dev/ttyS0 +.PD +.RE + +Read flash to file: +.RS +.PD 0 +.P +stm32flash \-r filename /dev/ttyS0 +.PD +.RE + +Start execution: +.RS +.PD 0 +.P +stm32flash \-g 0x0 /dev/ttyS0 +.PD +.RE + +Specify: +.PD 0 +.IP \(bu 2 +entry sequence: RTS=low, DTR=low, DTR=high +.IP \(bu 2 +exit sequence: RTS=high, DTR=low, DTR=high +.P +.RS +stm32flash \-i \-rts,\-dtr,dtr:rts,\-dtr,dtr /dev/ttyS0 +.PD +.RE + +.SH FORMAT CONVERSION +Flash images provided by ST or created with ST tools are often in file +format Motorola S\-Record. +Conversion between raw binary, intel hex and Motorola S\-Record can be +done through software package SRecord. + +.SH AUTHORS +The original software package +.B stm32flash +is written by +.I Geoffrey McRae +and is since 2012 maintained by +.IR "Tormod Volden " . + +Man page and extension to STM32W and I2C are written by +.IR "Antonio Borneo " . + +Please report any bugs at the project homepage +http://stm32flash.googlecode.com . + +.SH SEE ALSO +.BR "srec_cat" "(1)," " srec_intel" "(5)," " srec_motorola" "(5)." + +The communication protocol used by ST bootloader is documented in +following ST application notes, depending on communication port. +The current version of +.B stm32flash +only supports +.I UART +and +.I I2C +ports. +.PD 0 +.P +.IP \(bu 2 +AN3154: CAN protocol used in the STM32 bootloader +.P +.RS +http://www.st.com/web/en/resource/technical/document/application_note/CD00264321.pdf +.RE + +.P +.IP \(bu 2 +AN3155: USART protocol used in the STM32(TM) bootloader +.P +.RS +http://www.st.com/web/en/resource/technical/document/application_note/CD00264342.pdf +.RE + +.P +.IP \(bu 2 +AN4221: I2C protocol used in the STM32 bootloader +.P +.RS +http://www.st.com/web/en/resource/technical/document/application_note/DM00072315.pdf +.RE + +.P +.IP \(bu 2 +AN4286: SPI protocol used in the STM32 bootloader +.P +.RS +http://www.st.com/web/en/resource/technical/document/application_note/DM00081379.pdf +.RE + +.PD + + +Boot mode selection for STM32 is documented in ST application note +AN2606, available from the ST website: +.PD 0 +.P +http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf +.PD + +.SH LICENSE +.B stm32flash +is distributed under GNU GENERAL PUBLIC LICENSE Version 2. +Copy of the license is available within the source code in the file +.IR "gpl\-2.0.txt" . diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/utils.c b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/utils.c new file mode 100644 index 0000000..271bb3e --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/utils.c @@ -0,0 +1,45 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include "utils.h" + +/* detect CPU endian */ +char cpu_le() { + const uint32_t cpu_le_test = 0x12345678; + return ((const unsigned char*)&cpu_le_test)[0] == 0x78; +} + +uint32_t be_u32(const uint32_t v) { + if (cpu_le()) + return ((v & 0xFF000000) >> 24) | + ((v & 0x00FF0000) >> 8) | + ((v & 0x0000FF00) << 8) | + ((v & 0x000000FF) << 24); + return v; +} + +uint32_t le_u32(const uint32_t v) { + if (!cpu_le()) + return ((v & 0xFF000000) >> 24) | + ((v & 0x00FF0000) >> 8) | + ((v & 0x0000FF00) << 8) | + ((v & 0x000000FF) << 24); + return v; +} diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/utils.h b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/utils.h new file mode 100644 index 0000000..a8d37d2 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/stm32flash_serial/src/utils.h @@ -0,0 +1,30 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _H_UTILS +#define _H_UTILS + +#include + +char cpu_le(); +uint32_t be_u32(const uint32_t v); +uint32_t le_u32(const uint32_t v); + +#endif diff --git a/BootLoaders/Boards/stm32/tools/linux64/src/upload-reset/upload-reset.c b/BootLoaders/Boards/stm32/tools/linux64/src/upload-reset/upload-reset.c new file mode 100644 index 0000000..1d03bff --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/src/upload-reset/upload-reset.c @@ -0,0 +1,161 @@ +/* Copyright (C) 2015 Roger Clark + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * + * Utility to send the reset sequence on RTS and DTR and chars + * which resets the libmaple and causes the bootloader to be run + * + * + * + * Terminal control code by Heiko Noordhof (see copyright below) + */ + + + +/* Copyright (C) 2003 Heiko Noordhof + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Function prototypes (belong in a seperate header file) */ +int openserial(char *devicename); +void closeserial(void); +int setDTR(unsigned short level); +int setRTS(unsigned short level); + + +/* Two globals for use by this module only */ +static int fd; +static struct termios oldterminfo; + + +void closeserial(void) +{ + tcsetattr(fd, TCSANOW, &oldterminfo); + close(fd); +} + + +int openserial(char *devicename) +{ + struct termios attr; + + if ((fd = open(devicename, O_RDWR)) == -1) return 0; /* Error */ + atexit(closeserial); + + if (tcgetattr(fd, &oldterminfo) == -1) return 0; /* Error */ + attr = oldterminfo; + attr.c_cflag |= CRTSCTS | CLOCAL; + attr.c_oflag = 0; + if (tcflush(fd, TCIOFLUSH) == -1) return 0; /* Error */ + if (tcsetattr(fd, TCSANOW, &attr) == -1) return 0; /* Error */ + + /* Set the lines to a known state, and */ + /* finally return non-zero is successful. */ + return setRTS(0) && setDTR(0); +} + + +/* For the two functions below: + * level=0 to set line to LOW + * level=1 to set line to HIGH + */ + +int setRTS(unsigned short level) +{ + int status; + + if (ioctl(fd, TIOCMGET, &status) == -1) { + perror("setRTS(): TIOCMGET"); + return 0; + } + if (level) status |= TIOCM_RTS; + else status &= ~TIOCM_RTS; + if (ioctl(fd, TIOCMSET, &status) == -1) { + perror("setRTS(): TIOCMSET"); + return 0; + } + return 1; +} + + +int setDTR(unsigned short level) +{ + int status; + + if (ioctl(fd, TIOCMGET, &status) == -1) { + perror("setDTR(): TIOCMGET"); + return 0; + } + if (level) status |= TIOCM_DTR; + else status &= ~TIOCM_DTR; + if (ioctl(fd, TIOCMSET, &status) == -1) { + perror("setDTR: TIOCMSET"); + return 0; + } + return 1; +} + +/* This portion of code was written by Roger Clark + * It was informed by various other pieces of code written by Leaflabs to reset their + * Maple and Maple mini boards + */ + +main(int argc, char *argv[]) +{ + + if (argc<2 || argc >3) + { + printf("Usage upload-reset \n\r"); + return; + } + + if (openserial(argv[1])) + { + // Send magic sequence of DTR and RTS followed by the magic word "1EAF" + setRTS(false); + setDTR(false); + setDTR(true); + + usleep(50000L); + + setDTR(false); + setRTS(true); + setDTR(true); + + usleep(50000L); + + setDTR(false); + + usleep(50000L); + + write(fd,"1EAF",4); + + closeserial(); + if (argc==3) + { + usleep(atol(argv[2])*1000L); + } + } + else + { + printf("Failed to open serial device.\n\r"); + } +} diff --git a/BootLoaders/Boards/stm32/tools/linux64/stlink/st-flash b/BootLoaders/Boards/stm32/tools/linux64/stlink/st-flash new file mode 100644 index 0000000..9a0ac65 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux64/stlink/st-flash differ diff --git a/BootLoaders/Boards/stm32/tools/linux64/stlink/st-info b/BootLoaders/Boards/stm32/tools/linux64/stlink/st-info new file mode 100644 index 0000000..3a5e5e8 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux64/stlink/st-info differ diff --git a/BootLoaders/Boards/stm32/tools/linux64/stlink/st-term b/BootLoaders/Boards/stm32/tools/linux64/stlink/st-term new file mode 100644 index 0000000..8bdc1a6 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux64/stlink/st-term differ diff --git a/BootLoaders/Boards/stm32/tools/linux64/stlink/st-util b/BootLoaders/Boards/stm32/tools/linux64/stlink/st-util new file mode 100644 index 0000000..014919f Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux64/stlink/st-util differ diff --git a/BootLoaders/Boards/stm32/tools/linux64/stlink_upload b/BootLoaders/Boards/stm32/tools/linux64/stlink_upload new file mode 100644 index 0000000..24e528d --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/stlink_upload @@ -0,0 +1,45 @@ +#!/bin/bash + +# Check for leaf device. +function leaf_status() +{ + +this_leaf_status=$(lsusb |grep "1eaf" | awk '{ print $NF}') +# Find the mode of the leaf bootloader +case $this_leaf_status in + "1eaf:0003") + echo "dfu" + ;; + "1eaf:0004") + echo "ttyACMx" + ;; + *) + #echo "$this_leaf_status" + echo "unknown" + ;; +esac +} + +# You will need the usb-reset code, see https://github.com/rogerclarkmelbourne/Arduino_STM32/wiki/Using-a-generic-stm32-board-on-linux-with-Maple-bootloader +# +USBRESET=$(which usb-reset) || USBRESET="./usb-reset" + +# Check to see if a maple compatible board is attached +LEAF_STATUS=$(leaf_status) +echo "USB Status [$LEAF_STATUS]" + +$(dirname $0)/stlink/st-flash write "$4" 0x8000000 + +sleep 4 +# Reset the usb device to bring up the tty rather than DFU +"$USBRESET" "/dev/bus/usb/$(lsusb |grep "1eaf" |awk '{print $2,$4}'|sed 's/\://g'|sed 's/ /\//g')" >/dev/null 2>&1 +# Check to see if a maple compatible board is attached +LEAF_STATUS=$(leaf_status) +echo "USB Status [$LEAF_STATUS]" +# Check to see if the tty came up +TTY_DEV=$(find /dev -cmin -2 |grep ttyAC) +echo -e "Waiting for tty device $TTY_DEV \n" +sleep 20 +echo -e "$TTY_DEV should now be available.\n" +exit 0 + diff --git a/BootLoaders/Boards/stm32/tools/linux64/stm32flash/stm32flash b/BootLoaders/Boards/stm32/tools/linux64/stm32flash/stm32flash new file mode 100644 index 0000000..7e067ae Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux64/stm32flash/stm32flash differ diff --git a/BootLoaders/Boards/stm32/tools/linux64/tx_upload b/BootLoaders/Boards/stm32/tools/linux64/tx_upload new file mode 100644 index 0000000..fc2f6ba --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/tx_upload @@ -0,0 +1,15 @@ +#!/bin/bash + +# Dummy 'upload' file to provide instructions for flashing the multi-module firmware from the Tx +echo +echo Compiled .bin location: +echo $1 +echo +echo The compiled firmware can now be copied to the \firmware folder on the transmitter for flashing using Maintenance Mode. +echo +echo To enter Maintenance Mode hold down the two outer horizontal trim buttons while powering on the transmitter. Once in +echo Maintenance Mode follow the on-screen prompts to flash the Multi module. +echo +echo Supported transmitters are those running ersky9x r221e2 or newer. +echo +echo Further instructions are available at [need_url]. \ No newline at end of file diff --git a/BootLoaders/Boards/stm32/tools/linux64/upload-reset b/BootLoaders/Boards/stm32/tools/linux64/upload-reset new file mode 100644 index 0000000..26985b8 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/linux64/upload-reset differ diff --git a/BootLoaders/Boards/stm32/tools/linux64/upload_router b/BootLoaders/Boards/stm32/tools/linux64/upload_router new file mode 100644 index 0000000..b74244d --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/upload_router @@ -0,0 +1,112 @@ +#!/bin/bash +# Translates the windows Arduino IDE upload call - something like.. +# +# upload_router ttyUSB0 1 1EAF:0003 /tmp/build9114565021046468906.tmp/STM32_Blink.cpp maple_dfu 0 +# +# to the linux dfu-util equivalent of the form... +# +# dfu-util -D ./STM32_Blink.cpp.bin -d 1eaf:0003 --intf 0 --alt 1 +# +# + +function leaf_status() +{ + +this_leaf_status=$(lsusb |grep "1eaf" | awk '{ print $NF}') +# Find the mode of the leaf bootloader +case $this_leaf_status in + "1eaf:0003") + echo "dfu" + ;; + "1eaf:0004") + echo "ttyACMx" + ;; + *) + #echo "$this_leaf_status" + echo "unknown" + ;; +esac +} + + +DEVICE="$3" +# Lowercase the 1eaf device name, since in Windows land everybody shouts. +DEVICE=${DEVICE,,} + +BINFILE="$4.bin" +INTERFACE="$6" +ALT_INTERFACE="$2" + +# You will need the usb-reset code, see https://github.com/rogerclarkmelbourne/Arduino_STM32/wiki/Using-a-generic-stm32-board-on-linux-with-Maple-bootloader +# +USBRESET=$(which usb-reset) || USBRESET="./usb-reset" + +# Check to see if a maple compatible board is attached +LEAF_STATUS=$(leaf_status) + +# Borard not found, or no boot loader on board. +if [[ $(leaf_status) = "unknown" ]] +then + echo "STM32 Maple Bootloader compatible board not found." + sleep 5 + exit 1 +fi + +# We got this far, so we need to get the board in bootloader mode. +# After the timeout period, the board goes back in to serial mode, we need it in dfu mode, which happens for the first few seconds at power on +# so we ask the user to unplug and re-plug the board. +echo -e "\n\rSTM32 Maple board is in $LEAF_STATUS mode." + +echo "Please unplug and replug the USB cable to the Maple device." +sleep 2 +# On unplugging the board will be "unknown" +while [[ $(leaf_status) != "unknown" ]] +do + echo -n "." + sleep 1 +done +# On re-plugging the board will be "dfu" +while [[ $(leaf_status) != "dfu" ]] +do + echo -n "." + sleep 1 +done + +echo -e "\n\rProgramming STM32 device with dfu-util" +until dfu-util -D "$BINFILE" -d "$DEVICE" --intf "$INTERFACE" --alt "$ALT_INTERFACE" 2>&1 +do + echo -n "." + sleep 1 +done + +echo -e "\n\rUnplug and replug the USB cable to the STM32 board again please...." +while [[ $(leaf_status) != "unknown" ]] +do + echo -n "." + sleep 1 +done + +echo -e "\n\rReconnecting" +while [[ $(leaf_status) = "unknown" ]] +do + echo -n "." + sleep 1 +done + +echo -e "\n\rWaiting for bootloader to exit." +for i in {1..6} +do + echo -n "." + sleep 1 +done + +"$USBRESET" "/dev/bus/usb/$(lsusb |grep "1eaf" |awk '{print $2,$4}'|sed 's/\://g'|sed 's/ /\//g')" >/dev/null 2>&1 + +while [[ $(leaf_status) = "unknown" ]] +do + echo -n "." + sleep 1 +done +THIS_TTY=$(find /dev/ttyACM* -cmin -2) +echo -e "\n\rSTM32 Maple board serial port re-created..." +echo -e "\n\rSerial port is $THIS_TTY Please allow 15 seconds before attempting to read from serial port." diff --git a/BootLoaders/Boards/stm32/tools/macosx/dfu-util/dfu-prefix b/BootLoaders/Boards/stm32/tools/macosx/dfu-util/dfu-prefix new file mode 100644 index 0000000..fdd2671 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/macosx/dfu-util/dfu-prefix differ diff --git a/BootLoaders/Boards/stm32/tools/macosx/dfu-util/dfu-suffix b/BootLoaders/Boards/stm32/tools/macosx/dfu-util/dfu-suffix new file mode 100644 index 0000000..6d17d7e Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/macosx/dfu-util/dfu-suffix differ diff --git a/BootLoaders/Boards/stm32/tools/macosx/dfu-util/dfu-util b/BootLoaders/Boards/stm32/tools/macosx/dfu-util/dfu-util new file mode 100644 index 0000000..895bb23 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/macosx/dfu-util/dfu-util differ diff --git a/BootLoaders/Boards/stm32/tools/macosx/jlink_upload b/BootLoaders/Boards/stm32/tools/macosx/jlink_upload new file mode 100644 index 0000000..a9e9810 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/jlink_upload @@ -0,0 +1,9 @@ +#!/bin/bash + +echo erase > "$1".jlink +echo loadbin "$1" , 0x8000000 >> "$1".jlink +echo r >> "$1".jlink +echo q >> "$1".jlink + +/Applications/SEGGER/JLink/JLinkExe -device STM32F103C8 -if SWD -speed auto -CommanderScript "$1".jlink + diff --git a/BootLoaders/Boards/stm32/tools/macosx/maple_upload b/BootLoaders/Boards/stm32/tools/macosx/maple_upload new file mode 100644 index 0000000..3521aa1 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/maple_upload @@ -0,0 +1,62 @@ +#!/bin/bash + +set -e + +if [ $# -lt 4 ]; then + echo "Usage: $0 $# " >&2 + exit 1 +fi +dummy_port=$1; altID=$2; usbID=$3; binfile=$4;dummy_port_fullpath="/dev/$1" + + +# Get the directory where the script is running. +DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + + +# ----------------- Old code to reset the USB - which doesn't seem to work -------- +# +#if we can find the Serial device try resetting it and then sleeping for 1 sec while the board reboots +#if [ -e $dummy_port_fullpath ]; then +# echo "resetting " $dummy_port_fullpath +# stty -f $dummy_port_fullpath 1200 +# sleep 1 +## stty -f $dummy_port_fullpath 1200 +## sleep 1 +#fi +# ------------------ End of old code ----------------- + +# ----------------- IMPORTANT ----------------- +# The 2nd parameter to upload-reset is the delay after resetting before it exits +# This value is in milliseonds +# You may need to tune this to your system +# 750ms to 1500ms seems to work on my Mac + +${DIR}/upload-reset ${dummy_port_fullpath} 750 + +if [ $# -eq 5 ]; then + dfuse_addr="--dfuse-address $5" +else + dfuse_addr="" +fi + +#DFU_UTIL=/usr/local/bin/dfu-util +DFU_UTIL=${DIR}/dfu-util/dfu-util +if [ ! -x ${DFU_UTIL} ]; then + DFU_UTIL=/opt/local/bin/dfu-util +fi + +if [ ! -x ${DFU_UTIL} ]; then + echo "$0: error: cannot find ${DFU_UTIL}" >&2 + exit 2 +fi + +${DFU_UTIL} -d ${usbID} -a ${altID} -D ${binfile} -R ${dfuse_addr} -R + +echo -n Waiting for ${dummy_port_fullpath} serial... + +COUNTER=0 +while [ ! -c ${dummy_port_fullpath} ] && ((COUNTER++ < 40)); do + sleep 0.1 +done + +echo Done diff --git a/BootLoaders/Boards/stm32/tools/macosx/serial_upload b/BootLoaders/Boards/stm32/tools/macosx/serial_upload new file mode 100644 index 0000000..755444a --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/serial_upload @@ -0,0 +1,2 @@ +#!/bin/bash +$(dirname $0)/stm32flash/stm32flash -g 0x8000000 -b 115200 -w "$4" /dev/"$1" diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/build_dfu-util.sh b/BootLoaders/Boards/stm32/tools/macosx/src/build_dfu-util.sh new file mode 100644 index 0000000..3563f57 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/build_dfu-util.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +sudo apt-get build-dep dfu-util +sudo apt-get install build-essentials +sudo apt-get install libusb-1.0-0-dev +sudo apt-get install autoconf automake autotools-dev + +cd dfu-util +./autogen.sh +./configure +make +cp src/dfu-util ../../linux/dfu-util +cp src/dfu-suffix ../../linux/dfu-util +cp src/dfu-prefix ../../linux/dfu-util + diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/AUTHORS b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/AUTHORS new file mode 100644 index 0000000..1b36c73 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/AUTHORS @@ -0,0 +1,30 @@ +Authors ordered by first contribution. + +Harald Welte +Werner Almesberger +Michael Lauer +Jim Huang +Stefan Schmidt +Daniel Willmann +Mike Frysinger +Uwe Hermann +C. Scott Ananian +Bernard Blackham +Holger Freyther +Marc Singer +James Perkins +Tommi Keisala +Pascal Schweizer +Bradley Scott +Uwe Bonnes +Andrey Smirnov +Jussi Timperi +Hans Petter Selasky +Bo Shen +Henrique de Almeida Mendonca +Bernd Krumboeck +Dennis Meier +Veli-Pekka Peltola +Dave Hylands +Michael Grzeschik +Paul Fertser diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/COPYING b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/COPYING new file mode 100644 index 0000000..d60c31a --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/ChangeLog b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/ChangeLog new file mode 100644 index 0000000..37f1add --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/ChangeLog @@ -0,0 +1,93 @@ +0.8: + o New, separate dfu-prefix tool (Uwe Bonnes) + o Allow filtering on serial number (Uwe Bonnes) + o Improved VID/PID/serial filtering (Bradley Scott) + o Support reading firmware from stdin (Tormod Volden) + o Warn if missing DFU suffix (Tormod Volden) + o Improved progress bar (Hans Petter Selasky) + o Fix dfuse leave option (Uwe Bonnes) + o Major code rework (Hans Petter Selasky) + o MS Visual Studio build support (Henrique Mendonca) + o dfuse-pack.py tool for .dfu files (Antonio Galeo) + o Many other fixes from many people + +2014-09-13: Tormod Volden + +0.7: + o Support for TI Stellaris devices (Tommi Keisala) + o Fix libusb detection on MacOSX (Marc Singer) + o Fix libusb detection on FreeBSD (Tormod Volden) + o Improved DfuSe support (Tormod Volden) + o Support all special commands (leave, unprotect, mass-erase) + o Arbitrary upload lengths + o "force" option for various possible (dangerous) overrides + +2012-10-07: Tormod Volden + +0.6: + o Add detach mode (Stefan Schmidt) + o Check return value on all libusb calls (Tormod Volden) + o Fix segmentation fault with -s option (Tormod Volden) + o Add DFU suffix manipulation tool (Stefan Schmidt) + o Port to Windows: (Tormod Volden, some parts based on work from Satz + Klauer) + o Port file handling to stdio streams + o Sleep() macros + o C99 types + o Pack structs + o Detect DfuSe device correctly on big-endian architectures (Tormod + Volden) + o Add dfuse progress indication on download (Tormod Volden) + o Cleanup: gcc pedantic, gcc extension, ... (Tormod Volden) + o Rely on page size from functional descriptor. Please report if you get + an error about it. (Tormod Volden) + o Add quirk for Maple since it reports wrong DFU version (Tormod Volden) + +2012-04-22: Stefan Schmidt + +0.5: + o DfuSe extension support for ST devices (Tormod Volden) + o Add initial support for bitWillDetach flag from DFU 1.1 (Tormod + Volden) + o Internal cleanup and some manual page fixes (Tormod Volden) + +2011-11-02: Stefan Schmidt + +0.4: + o Rework to use libusb-1.0 (Stefan Schmidt) + o DFU suffix support (Tormod Volden, Stefan Schmidt) + o Sspeed up DFU downloads directly into memory (Bernard Blackham) + o More flexible -d vid:pid parsing (Tormod Volden) + o Many bug fixes and cleanups + +2011-07-20: Stefan Schmidt + +0.3: + o quirks: Add OpenOCD to the poll timeout quirk table. + +2010-12-22: Stefan Schmidt + +0.2: + o Fix some typos on the website and the README (Antonio Ospite, Uwe + Hermann) + o Remove build rule for a static binary. We can use autotools for this. + (Mike Frysinger) + o Fix infinite loop in download error path (C. Scott Ananian) + o Break out to show the 'finished' in upload (C. Scott Ananian) + o Add GPLv2+ headers (Harald Welte) + o Remove dead code (commands.[ch]) remnescent of dfu-programmer (Harald + Welte) + o Simple quirk system with Openmoko quirk for missing bwPollTimeout (Tormod Volden) + o New default (1024) and clamping of transfer size (Tormod Volden) + o Verify sending of completion packet (Tormod Volden) + o Look for DFU functional descriptor among all descriptors (Tormod + Volden) + o Print out in which direction we are transferring data + o Abort in upload if the file already exists + +2010-11-17 Stefan Schmidt + +0.1: + Initial release + +2010-05-23 Stefan Schmidt diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/DEVICES.txt b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/DEVICES.txt new file mode 100644 index 0000000..bdd9f1f --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/DEVICES.txt @@ -0,0 +1,20 @@ +List of supported software and hardware products: + +Software user (bootloader, etc) +------------------------------- +- Sam7DFU: http://www.openpcd.org/Sam7dfu +- U-boot: DFU patches +- Barebox: http://www.barebox.org/ +- Leaflabs: http://code.google.com/p/leaflabs/ +- Blackmagic DFU + +Products using DFU +------------------ +- OpenPCD (sam7dfu) +- Openmoko Neo 1973 and Freerunner (u-boot with DFU patches) +- Leaflabs Maple +- ATUSB from Qi Hardware +- STM32F105/7, STM32F2/F3/F4 in System Bootloader +- Blackmagic debug probe +- NXP LPC31xx/LPC43XX, e.g. LPC-Link and LPC-Link2, need binaries + with LPC prefix and encoding (LPC-Link) diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/Makefile.am b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/Makefile.am new file mode 100644 index 0000000..641dda5 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = src doc + +EXTRA_DIST = autogen.sh TODO DEVICES.txt dfuse-pack.py diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/README b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/README new file mode 100644 index 0000000..0f8f262 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/README @@ -0,0 +1,20 @@ +Dfu-util - Device Firmware Upgrade Utilities + +Dfu-util is the host side implementation of the DFU 1.0 [1] and DFU 1.1 [2] +specification of the USB forum. + +DFU is intended to download and upload firmware to devices connected over +USB. It ranges from small devices like micro-controller boards up to mobile +phones. With dfu-util you are able to download firmware to your device or +upload firmware from it. + +dfu-util has been tested with Openmoko Neo1973 and Freerunner and many +other devices. + +[1] DFU 1.0 spec: http://www.usb.org/developers/devclass_docs/usbdfu10.pdf +[2] DFU 1.1 spec: http://www.usb.org/developers/devclass_docs/DFU_1.1.pdf + +The official website is: + + http://dfu-util.gnumonks.org/ + diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/TODO b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/TODO new file mode 100644 index 0000000..900c30c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/TODO @@ -0,0 +1,14 @@ +DfuSe: +- Do erase and write in two separate passes when downloading +- Skip "Set Address" command when downloading contiguous blocks +- Implement "Get Commands" command + +Devices: +- Research iPhone/iPod/iPad support + Heavily modified dfu-util fork here: + https://github.com/planetbeing/xpwn/tree/master/dfu-util +- Test against Niftylights + +Non-Code: +- Logo +- Re-License as LGPL for usage as library? diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/autogen.sh b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/autogen.sh new file mode 100644 index 0000000..e67aed3 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/autogen.sh @@ -0,0 +1,2 @@ +#! /bin/sh +autoreconf -v -i diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/configure.ac b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/configure.ac new file mode 100644 index 0000000..8622114 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/configure.ac @@ -0,0 +1,41 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.59) +AC_INIT([dfu-util],[0.8],[dfu-util@lists.gnumonks.org],,[http://dfu-util.gnumonks.org]) +AC_CONFIG_AUX_DIR(m4) +AM_INIT_AUTOMAKE([foreign]) +AC_CONFIG_HEADERS([config.h]) + +# Test for new silent rules and enable only if they are available +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +# Checks for programs. +AC_PROG_CC + +# Checks for libraries. +# On FreeBSD the libusb-1.0 is called libusb and resides in system location +AC_CHECK_LIB([usb], [libusb_init],, [native_libusb=no],) +AS_IF([test x$native_libusb = xno], [ + PKG_CHECK_MODULES([USB], [libusb-1.0 >= 1.0.0],, + AC_MSG_ERROR([*** Required libusb-1.0 >= 1.0.0 not installed ***])) +]) +AC_CHECK_LIB([usbpath],[usb_path2devnum],,,-lusb) + +LIBS="$LIBS $USB_LIBS" +CFLAGS="$CFLAGS $USB_CFLAGS" + +# Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS([usbpath.h windows.h sysexits.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_TYPE_SIZE_T + +# Checks for library functions. +AC_FUNC_MEMCMP +AC_CHECK_FUNCS([ftruncate getpagesize nanosleep err]) + +AC_CONFIG_FILES(Makefile src/Makefile doc/Makefile) +AC_OUTPUT diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/README b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/README new file mode 100644 index 0000000..00d3d1a --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/README @@ -0,0 +1,77 @@ +Device: +------- +qi-hardware-atusb: +- Qi Hardware ben-wpan +- DFU implementation: + http://projects.qi-hardware.com/index.php/p/ben-wpan/source/tree/master/atusb/fw/usb +- Tester: Stefan Schmidt + +openpcd: +- OpenPCD RFID reader +- DFU implementation: SAM7DFU + http://www.openpcd.org/Sam7dfu, git://git.gnumonks.org/openpcd.git +- Tester: Stefan Schmidt + +simtrace: +- Sysmocom SimTrace +- DFU implementation: SAM7DFU + http://www.openpcd.org/Sam7dfu, git://git.gnumonks.org/openpcd.git +- Tester: Stefan Schmidt + +openmoko-freerunner: +- Openmoko Freerunner +- DFU implementation: Old U-Boot + http://git.openmoko.org/?p=u-boot.git;a=shortlog;h=refs/heads/mokopatches +- Tester: Stefan Schmidt + +openmoko-neo1973: +- Openmoko Neo1073 +- DFU implementation: Old U-Boot + http://git.openmoko.org/?p=u-boot.git;a=shortlog;h=refs/heads/mokopatches +- Tester: Stefan Schmidt + +tdk-bluetooth: +- TDK Corp. Bluetooth Adapter +- DFU implementation: closed soure +- Only upload has been tested +- Tester: Stefan Schmidt + +stm32f107: +- STM32 microcontrollers with built-in (ROM) DFU loader +- DFU implementation: Closed source but probably similar to the one + in their USB device libraries. Some relevant application notes: + http://www.st.com -> AN3156 and AN2606 +- Tested by Uwe Bonnes + +stm32f4discovery: +- STM32 microcontroller board with built-in (ROM) DFU loader +- DFU implementation: Closed source, probably similar to stm32f107. +- Tested by Joe Rothweiler + +dso-nano: +- DSO Nano pocket oscilloscope +- DFU implementation: Based on ST Microelectronics USB FS Library 1.0 + http://dsonano.googlecode.com/files/DS0201_OpenSource.rar +- Tester: Tormod Volden + +opc-20: +- Custom devices based on STM32F1xx +- DFU implementation: ST Microelectronics USB FS Device Library 3.1.0 + http://www.st.com -> um0424.zip +- Tester: Tormod Volden + +lpc-link, lpclink2: +- NXP LPCXpresso debug adapters +- Proprietary DFU implementation, uses special download files with + LPC prefix and encoding of the target firmware code +- Tested by Uwe Bonnes + +Adding the lsusb output and a download log of your device here helps +us to avoid regressions for hardware we cannot test while working on +the code. To extract the lsusb output use this command: +sudo lsusb -v -d $USBID > $DEVICE.lsusb +Prepare a description snippet as above, and send it to us. A log +(copy-paste of the command window) of a firmware download is also +nice, please use the double verbose option -v -v and include the +command line in the log file. + diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/dsonano.lsusb b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/dsonano.lsusb new file mode 100644 index 0000000..140a7bc --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/dsonano.lsusb @@ -0,0 +1,60 @@ + +Bus 002 Device 004: ID 0483:df11 SGS Thomson Microelectronics +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x0483 SGS Thomson Microelectronics + idProduct 0xdf11 + bcdDevice 1.1a + iManufacturer 1 STMicroelectronics + iProduct 2 STM32 DFU + iSerial 3 001 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 36 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 64mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 0 + iInterface 4 @Internal Flash /0x08000000/12*001Ka,116*001Kg + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 0 + iInterface 5 @SPI Flash : M25P64/0x00000000/64*064Kg,64*064Kg + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 11 + Will Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 255 milliseconds + wTransferSize 1024 bytes + bcdDFUVersion 1.1a +Device Status: 0x0000 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/lpclink.log b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/lpclink.log new file mode 100644 index 0000000..7de4dd3 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/lpclink.log @@ -0,0 +1,59 @@ +(The on-board LPC3154 has some encryption key set and LPCXpressoWIN.enc +is encrypted.) + +$ lsusb | grep NXP +Bus 003 Device 011: ID 0471:df55 Philips (or NXP) LPCXpresso LPC-Link + +$ dfu-util -v -v -v -R -D /opt/lpc/lpcxpresso/bin/LPCXpressoWIN.enc + +dfu-util 0.7 + +Copyright 2005-2008 Weston Schmidt, Harald Welte and OpenMoko Inc. +Copyright 2010-2012 Tormod Volden and Stefan Schmidt +This program is Free Software and has ABSOLUTELY NO WARRANTY +Please report bugs to dfu-util@lists.gnumonks.org + +dfu-util: Invalid DFU suffix signature +dfu-util: A valid DFU suffix will be required in a future dfu-util release!!! +Deducing device DFU version from functional descriptor length +Opening DFU capable USB device... +ID 0471:df55 +Run-time device DFU version 0100 +Claiming USB DFU Runtime Interface... +Determining device status: +state = dfuIDLE, status = 0 +dfu-util: WARNING: Runtime device already in DFU state ?!? +Claiming USB DFU Interface... +Setting Alternate Setting #0 ... +Determining device status: +state = dfuIDLE, status = 0 +dfuIDLE, continuing +DFU mode device DFU version 0100 +Device returned transfer size 2048 +Copying data from PC to DFU device +Download [ ] 0% 0 bytes +Download [= ] 6% 2048 bytes +Download [=== ] 13% 4096 bytes +Download [==== ] 19% 6144 bytes +Download [====== ] 26% 8192 bytes +Download [======== ] 32% 10240 bytes +Download [========= ] 39% 12288 bytes +Download [=========== ] 45% 14336 bytes +Download [============= ] 52% 16384 bytes +Download [============== ] 59% 18432 bytes +Download [================ ] 65% 20480 bytes +Download [================== ] 72% 22528 bytes +Download [=================== ] 78% 24576 bytes +Download [===================== ] 85% 26624 bytes +Download [====================== ] 91% 28672 bytes +Download [======================== ] 98% 29192 bytes +Download [=========================] 100% 29192 bytes +Download done. +Sent a total of 29192 bytes +state(8) = dfuMANIFEST-WAIT-RESET, status(0) = No error condition is present +Done! +dfu-util: can't detach +Resetting USB to switch back to runtime mode + +$ lsusb | grep NXP +Bus 003 Device 012: ID 1fc9:0009 NXP Semiconductors diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/lpclink.lsusb b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/lpclink.lsusb new file mode 100644 index 0000000..867b2a2 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/lpclink.lsusb @@ -0,0 +1,58 @@ + +Bus 003 Device 008: ID 0471:df55 Philips (or NXP) LPCXpresso LPC-Link +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x0471 Philips (or NXP) + idProduct 0xdf55 LPCXpresso LPC-Link + bcdDevice 0.01 + iManufacturer 0 + iProduct 0 + iSerial 0 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 25 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 0 + iInterface 0 + Device Firmware Upgrade Interface Descriptor: + bLength 7 + bDescriptorType 33 + bmAttributes 1 + Will Not Detach + Manifestation Intolerant + Upload Unsupported + Download Supported + wDetachTimeout 65535 milliseconds + wTransferSize 2048 bytes +Device Qualifier (for other device speed): + bLength 10 + bDescriptorType 6 + bcdUSB 2.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + bNumConfigurations 1 +Device Status: 0x0000 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/lpclink2.log b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/lpclink2.log new file mode 100644 index 0000000..4681eff --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/lpclink2.log @@ -0,0 +1,59 @@ +$ lsusb | grep NXP +Bus 003 Device 013: ID 1fc9:000c NXP Semiconductors + +$ dfu-util -D ~/devel/dfu-util/firmware.bin.qthdr + +dfu-util 0.7 + +Copyright 2005-2008 Weston Schmidt, Harald Welte and OpenMoko Inc. +Copyright 2010-2012 Tormod Volden and Stefan Schmidt +This program is Free Software and has ABSOLUTELY NO WARRANTY +Please report bugs to dfu-util@lists.gnumonks.org + +dfu-util: Invalid DFU suffix signature +dfu-util: A valid DFU suffix will be required in a future dfu-util release!!! +Possible unencryptes NXP LPC DFU prefix with the following properties +Payload length: 39 kiByte +Opening DFU capable USB device... +ID 1fc9:000c +Run-time device DFU version 0100 +Claiming USB DFU Runtime Interface... +Determining device status: +state = dfuIDLE, status = 0 +dfu-util: WARNING: Runtime device already in DFU state ?!? +Claiming USB DFU Interface... +Setting Alternate Setting #0 ... +Determining device status: +state = dfuIDLE, status = 0 +dfuIDLE, continuing +DFU mode device DFU version 0100 +Device returned transfer size 2048 +Copying data from PC to DFU device +Download [ ] 0% 0 bytes +Download [= ] 4% 2048 bytes +Download [== ] 9% 4096 bytes +Download [=== ] 14% 6144 bytes +Download [==== ] 19% 8192 bytes +Download [====== ] 24% 10240 bytes +Download [======= ] 28% 12288 bytes +Download [======== ] 33% 14336 bytes +Download [========= ] 38% 16384 bytes +Download [========== ] 43% 18432 bytes +Download [============ ] 48% 20480 bytes +Download [============= ] 53% 22528 bytes +Download [============== ] 57% 24576 bytes +Download [=============== ] 62% 26624 bytes +Download [================ ] 67% 28672 bytes +Download [================== ] 72% 30720 bytes +Download [=================== ] 77% 32768 bytes +Download [==================== ] 82% 34816 bytes +Download [===================== ] 86% 36864 bytes +Download [====================== ] 91% 38912 bytes +Download [======================== ] 96% 40356 bytes +Download [=========================] 100% 40356 bytes +Download done. +Sent a total of 40356 bytes +dfu-util: unable to read DFU status + +$ lsusb | grep NXP +Bus 003 Device 014: ID 1fc9:0018 NXP Semiconductors diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/lpclink2.lsusb b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/lpclink2.lsusb new file mode 100644 index 0000000..b833fca --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/lpclink2.lsusb @@ -0,0 +1,203 @@ + +Bus 003 Device 007: ID 0c72:000c PEAK System PCAN-USB +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 16 + idVendor 0x0c72 PEAK System + idProduct 0x000c PCAN-USB + bcdDevice 1c.ff + iManufacturer 0 + iProduct 3 VER1:PEAK +VER2:02.8.01 +DAT :06.05.2004 +TIME:09:35:37 + ... + iSerial 0 + bNumConfigurations 3 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 46 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 200mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 4 + bInterfaceClass 0 (Defined at Interface level) + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 20 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x01 EP 1 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 20 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 46 + bNumInterfaces 1 + bConfigurationValue 2 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 394mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 4 + bInterfaceClass 0 (Defined at Interface level) + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 20 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x01 EP 1 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 20 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 46 + bNumInterfaces 1 + bConfigurationValue 3 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 200mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 4 + bInterfaceClass 0 (Defined at Interface level) + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x01 EP 1 OUT + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 +Device Status: 0x0001 + Self Powered diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/opc-20.lsusb b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/opc-20.lsusb new file mode 100644 index 0000000..580df90 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/opc-20.lsusb @@ -0,0 +1,60 @@ + +Bus 001 Device 004: ID 0483:df11 SGS Thomson Microelectronics +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x0483 SGS Thomson Microelectronics + idProduct 0xdf11 + bcdDevice 2.00 + iManufacturer 1 STMicroelectronics + iProduct 2 STM32 DFU + iSerial 3 ÿÿÿÿÿÿÿÿÿÿÿÿ + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 36 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0xc0 + Self Powered + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 4 @Internal Flash /0x08000000/12*001Ka,116*001Kg + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 5 @SPI Flash : M25P64/0x00000000/128*64Kg + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 11 + Will Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 255 milliseconds + wTransferSize 1024 bytes + bcdDFUVersion 1a.01 +Device Status: 0x0001 + Self Powered diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/openmoko-freerunner-dfumode.lsusb b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/openmoko-freerunner-dfumode.lsusb new file mode 100644 index 0000000..4c0abfb --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/openmoko-freerunner-dfumode.lsusb @@ -0,0 +1,109 @@ +Bus 003 Device 017: ID 1d50:5119 OpenMoko, Inc. GTA01/GTA02 U-Boot Bootloader +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 16 + idVendor 0x1d50 OpenMoko, Inc. + idProduct 0x5119 GTA01/GTA02 U-Boot Bootloader + bcdDevice 0.00 + iManufacturer 1 OpenMoko, Inc + iProduct 2 Neo1973 Bootloader U-Boot 1.3.2-moko12 + iSerial 3 0000000 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 81 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 7 USB Device Firmware Upgrade + bmAttributes 0x80 + (Bus Powered) + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 8 RAM 0x32000000 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 9 u-boot + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 2 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 10 u-boot_env + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 3 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 11 kernel + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 4 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 12 splash + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 5 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 13 factory + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 6 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 14 rootfs + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 7 + Will Not Detach + Manifestation Tolerant + Upload Supported + Download Supported + wDetachTimeout 65280 milliseconds + wTransferSize 4096 bytes + bcdDFUVersion 1.00 +Device Status: 0x0a00 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/openmoko-freerunner.lsusb b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/openmoko-freerunner.lsusb new file mode 100644 index 0000000..835708d --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/openmoko-freerunner.lsusb @@ -0,0 +1,179 @@ +Bus 005 Device 033: ID 1d50:5119 OpenMoko, Inc. GTA01/GTA02 U-Boot Bootloader +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.10 + bDeviceClass 2 Communications + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 16 + idVendor 0x1d50 OpenMoko, Inc. + idProduct 0x5119 GTA01/GTA02 U-Boot Bootloader + bcdDevice 0.00 + iManufacturer 1 OpenMoko, Inc + iProduct 2 Neo1973 Bootloader U-Boot 1.3.2-moko12 + iSerial 3 0000000 + bNumConfigurations 2 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 85 + bNumInterfaces 3 + bConfigurationValue 1 + iConfiguration 4 TTY via USB + bmAttributes 0x80 + (Bus Powered) + MaxPower 500mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 2 Communications + bInterfaceSubClass 2 Abstract (modem) + bInterfaceProtocol 1 AT-commands (v.25ter) + iInterface 6 Control Interface + CDC Header: + bcdCDC 0.6e + CDC Call Management: + bmCapabilities 0x00 + bDataInterface 1 + CDC ACM: + bmCapabilities 0x00 + CDC Union: + bMasterInterface 0 + bSlaveInterface 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 10 CDC Data + bInterfaceSubClass 0 Unused + bInterfaceProtocol 0 + iInterface 5 Bulk Data Interface + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 2 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 1 + iInterface 7 USB Device Firmware Upgrade + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 7 + Will Not Detach + Manifestation Tolerant + Upload Supported + Download Supported + wDetachTimeout 65280 milliseconds + wTransferSize 4096 bytes + bcdDFUVersion 1.00 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 67 + bNumInterfaces 2 + bConfigurationValue 2 + iConfiguration 4 TTY via USB + bmAttributes 0x80 + (Bus Powered) + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 2 Communications + bInterfaceSubClass 2 Abstract (modem) + bInterfaceProtocol 1 AT-commands (v.25ter) + iInterface 6 Control Interface + CDC Header: + bcdCDC 0.6e + CDC Call Management: + bmCapabilities 0x00 + bDataInterface 1 + CDC ACM: + bmCapabilities 0x00 + CDC Union: + bMasterInterface 0 + bSlaveInterface 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 10 CDC Data + bInterfaceSubClass 0 Unused + bInterfaceProtocol 0 + iInterface 5 Bulk Data Interface + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 +Device Status: 0x9a00 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/openmoko-neo1973.lsusb b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/openmoko-neo1973.lsusb new file mode 100644 index 0000000..0778950 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/openmoko-neo1973.lsusb @@ -0,0 +1,182 @@ + +Bus 006 Device 020: ID 1457:5119 First International Computer, Inc. OpenMoko Neo1973 u-boot cdc_acm serial port +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.10 + bDeviceClass 2 Communications + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 16 + idVendor 0x1457 First International Computer, Inc. + idProduct 0x5119 OpenMoko Neo1973 u-boot cdc_acm serial port + bcdDevice 0.00 + iManufacturer 1 + iProduct 2 + iSerial 3 + bNumConfigurations 2 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 85 + bNumInterfaces 3 + bConfigurationValue 1 + iConfiguration 4 + bmAttributes 0x80 + (Bus Powered) + MaxPower 500mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 2 Communications + bInterfaceSubClass 2 Abstract (modem) + bInterfaceProtocol 1 AT-commands (v.25ter) + iInterface 6 + CDC Header: + bcdCDC 0.6e + CDC Call Management: + bmCapabilities 0x00 + bDataInterface 1 + CDC ACM: + bmCapabilities 0x00 + CDC Union: + bMasterInterface 0 + bSlaveInterface 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 10 CDC Data + bInterfaceSubClass 0 Unused + bInterfaceProtocol 0 + iInterface 5 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 2 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 1 + iInterface 7 + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 7 + Will Not Detach + Manifestation Tolerant + Upload Supported + Download Supported + wDetachTimeout 65280 milliseconds + wTransferSize 4096 bytes + bcdDFUVersion 1.00 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 67 + bNumInterfaces 2 + bConfigurationValue 2 + iConfiguration 4 + bmAttributes 0x80 + (Bus Powered) + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 2 Communications + bInterfaceSubClass 2 Abstract (modem) + bInterfaceProtocol 1 AT-commands (v.25ter) + iInterface 6 + CDC Header: + bcdCDC 0.6e + CDC Call Management: + bmCapabilities 0x00 + bDataInterface 1 + CDC ACM: + bmCapabilities 0x00 + CDC Union: + bMasterInterface 0 + bSlaveInterface 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 10 CDC Data + bInterfaceSubClass 0 Unused + bInterfaceProtocol 0 + iInterface 5 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 +Device Status: 0x0006 + (Bus Powered) + Remote Wakeup Enabled + Test Mode diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/openpcd.lsusb b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/openpcd.lsusb new file mode 100644 index 0000000..f6255a9 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/openpcd.lsusb @@ -0,0 +1,60 @@ + +Bus 006 Device 016: ID 16c0:076b VOTI OpenPCD 13.56MHz RFID Reader +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 8 + idVendor 0x16c0 VOTI + idProduct 0x076b OpenPCD 13.56MHz RFID Reader + bcdDevice 0.00 + iManufacturer 1 + iProduct 2 OpenPCD RFID Simulator - DFU Mode + iSerial 0 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 36 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 200mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 0 + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 3 + Will Not Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 65280 milliseconds + wTransferSize 256 bytes + bcdDFUVersion 1.00 +Device Status: 0x0000 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/qi-hardware-atusb.lsusb b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/qi-hardware-atusb.lsusb new file mode 100644 index 0000000..bfc1701 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/qi-hardware-atusb.lsusb @@ -0,0 +1,59 @@ + +Bus 006 Device 013: ID 20b7:1540 Qi Hardware ben-wpan, AT86RF230-based +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 255 Vendor Specific Class + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x20b7 Qi Hardware + idProduct 0x1540 ben-wpan, AT86RF230-based + bcdDevice 0.01 + iManufacturer 0 + iProduct 0 + iSerial 1 4630333438371508231a + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 34 + bNumInterfaces 2 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 40mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 255 Vendor Specific Class + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 1 + iInterface 0 +Device Status: 0x0000 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/simtrace.lsusb b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/simtrace.lsusb new file mode 100644 index 0000000..578ddf0 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/simtrace.lsusb @@ -0,0 +1,70 @@ + +Bus 006 Device 017: ID 16c0:0762 VOTI +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 8 + idVendor 0x16c0 VOTI + idProduct 0x0762 + bcdDevice 0.00 + iManufacturer 1 sysmocom - systems for mobile communications GmbH + iProduct 2 SimTrace SIM Sniffer - DFU Mode + iSerial 0 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 45 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 3 SimTrace DFU Configuration + bmAttributes 0x80 + (Bus Powered) + MaxPower 200mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 4 SimTrace DFU Interface - Application Partition + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 5 SimTrace DFU Interface - Bootloader Partition + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 2 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 6 SimTrace DFU Interface - RAM + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 3 + Will Not Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 65280 milliseconds + wTransferSize 256 bytes + bcdDFUVersion 1.00 +Device Status: 0x0000 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/sparkcore.lsusb b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/sparkcore.lsusb new file mode 100644 index 0000000..b6029ff --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/sparkcore.lsusb @@ -0,0 +1,60 @@ + +Bus 001 Device 008: ID 1d50:607f OpenMoko, Inc. +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x1d50 OpenMoko, Inc. + idProduct 0x607f + bcdDevice 2.00 + iManufacturer 1 Spark Devices + iProduct 2 CORE DFU + iSerial 3 8D80527B5055 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 36 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0xc0 + Self Powered + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 4 @Internal Flash /0x08000000/20*001Ka,108*001Kg + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 5 @SPI Flash : SST25x/0x00000000/512*04Kg + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 11 + Will Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 255 milliseconds + wTransferSize 1024 bytes + bcdDFUVersion 1.1a +Device Status: 0x0001 + Self Powered diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/stm32f107.bin-download b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/stm32f107.bin-download new file mode 100644 index 0000000..45b714f --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/stm32f107.bin-download @@ -0,0 +1,48 @@ +> src/dfu-util --intf 0 --alt 0 -v -v -v -s 0x8000000 -D test3 +dfu-util 0.4 + +(C) 2005-2008 by Weston Schmidt, Harald Welte and OpenMoko Inc. +(C) 2010-2011 Tormod Volden (DfuSe support) +This program is Free Software and has ABSOLUTELY NO WARRANTY + +dfu-util does currently only support DFU version 1.0 + +Opening DFU USB device... ID 0483:df11 +Run-time device DFU version 011a +Found DFU: [0483:df11] devnum=0, cfg=1, intf=0, alt=0, name="@Internal Flash /0x08000000/128*002Kg" +Claiming USB DFU Interface... +Setting Alternate Setting #0 ... +Determining device status: state = dfuIDLE, status = 0 +dfuIDLE, continuing +DFU mode device DFU version 011a +Device returned transfer size 2048 +No valid DFU suffix signature +Warning: File has no DFU suffix +DfuSe interface name: "Internal Flash " +Memory segment at 0x08000000 128 x 2048 = 262144 (rew) +Uploading to address = 0x08000000, size = 16384 +Erasing page size 2048 at address 0x08000000, page starting at 0x08000000 + Download from image offset 00000000 to memory 08000000-080007ff, size 2048 + Setting address pointer to 0x08000000 +Erasing page size 2048 at address 0x08000800, page starting at 0x08000800 + Download from image offset 00000800 to memory 08000800-08000fff, size 2048 + Setting address pointer to 0x08000800 +Erasing page size 2048 at address 0x08001000, page starting at 0x08001000 + Download from image offset 00001000 to memory 08001000-080017ff, size 2048 + Setting address pointer to 0x08001000 +Erasing page size 2048 at address 0x08001800, page starting at 0x08001800 + Download from image offset 00001800 to memory 08001800-08001fff, size 2048 + Setting address pointer to 0x08001800 +Erasing page size 2048 at address 0x08002000, page starting at 0x08002000 + Download from image offset 00002000 to memory 08002000-080027ff, size 2048 + Setting address pointer to 0x08002000 +Erasing page size 2048 at address 0x08002800, page starting at 0x08002800 + Download from image offset 00002800 to memory 08002800-08002fff, size 2048 + Setting address pointer to 0x08002800 +Erasing page size 2048 at address 0x08003000, page starting at 0x08003000 + Download from image offset 00003000 to memory 08003000-080037ff, size 2048 + Setting address pointer to 0x08003000 +Erasing page size 2048 at address 0x08003800, page starting at 0x08003800 + Download from image offset 00003800 to memory 08003800-08003fff, size 2048 + Setting address pointer to 0x08003800 + diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/stm32f107.lsusb b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/stm32f107.lsusb new file mode 100644 index 0000000..14b45cd --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/stm32f107.lsusb @@ -0,0 +1,60 @@ + +Bus 001 Device 028: ID 0483:df11 SGS Thomson Microelectronics STM Device in DFU Mode +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x0483 SGS Thomson Microelectronics + idProduct 0xdf11 STM Device in DFU Mode + bcdDevice 20.00 + iManufacturer 1 STMicroelectronics + iProduct 2 STM32 0x418 DFU Bootloader + iSerial 3 STM32 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 36 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0xc0 + Self Powered + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 4 @Internal Flash /0x08000000/128*002Kg + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 5 @Option Bytes /0x1FFFF800/01*016 g + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 11 + Will Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 255 milliseconds + wTransferSize 2048 bytes + bcdDFUVersion 1.1a +Device Status: 0x0000 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/stm32f4discovery.bin-download b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/stm32f4discovery.bin-download new file mode 100644 index 0000000..96e1722 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/stm32f4discovery.bin-download @@ -0,0 +1,36 @@ +dfu-util --device 0483:df11 --alt 0 \ + --dfuse-address 0x08000000 \ + -v -v -v \ + --download arm/iotoggle.bin +No valid DFU suffix signature +Warning: File has no DFU suffix +dfu-util 0.5 + +(C) 2005-2008 by Weston Schmidt, Harald Welte and OpenMoko Inc. +(C) 2010-2011 Tormod Volden (DfuSe support) +This program is Free Software and has ABSOLUTELY NO WARRANTY + +dfu-util does currently only support DFU version 1.0 + +Filter on vendor = 0x0483 product = 0xdf11 +Opening DFU capable USB device... ID 0483:df11 +Run-time device DFU version 011a +Found DFU: [0483:df11] devnum=0, cfg=1, intf=0, alt=0, name="@Internal Flash /0x08000000/04*016Kg,01*064Kg,07*128Kg" +Claiming USB DFU Interface... +Setting Alternate Setting #0 ... +Determining device status: state = dfuERROR, status = 10 +dfuERROR, clearing status +Determining device status: state = dfuIDLE, status = 0 +dfuIDLE, continuing +DFU mode device DFU version 011a +Device returned transfer size 2048 +DfuSe interface name: "Internal Flash " +Memory segment at 0x08000000 4 x 16384 = 65536 (rew) +Memory segment at 0x08010000 1 x 65536 = 65536 (rew) +Memory segment at 0x08020000 7 x 131072 = 917504 (rew) +Uploading to address = 0x08000000, size = 2308 +Erasing page size 16384 at address 0x08000000, page starting at 0x08000000 + Download from image offset 00000000 to memory 08000000-080007ff, size 2048 + Setting address pointer to 0x08000000 + Download from image offset 00000800 to memory 08000800-08000903, size 260 + Setting address pointer to 0x08000800 diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/stm32f4discovery.lsusb b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/stm32f4discovery.lsusb new file mode 100644 index 0000000..0b870de --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/stm32f4discovery.lsusb @@ -0,0 +1,80 @@ + +Bus 001 Device 010: ID 0483:df11 SGS Thomson Microelectronics STM Device in DFU Mode +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x0483 SGS Thomson Microelectronics + idProduct 0xdf11 STM Device in DFU Mode + bcdDevice 21.00 + iManufacturer 1 STMicroelectronics + iProduct 2 STM32 BOOTLOADER + iSerial 3 315A28A0B956 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 54 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0xc0 + Self Powered + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 4 @Internal Flash /0x08000000/04*016Kg,01*064Kg,07*128Kg + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 5 @Option Bytes /0x1FFFC000/01*016 g + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 2 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 6 @OTP Memory /0x1FFF7800/01*512 g,01*016 g + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 3 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 7 @Device Feature/0xFFFF0000/01*004 g + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 11 + Will Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 255 milliseconds + wTransferSize 2048 bytes + bcdDFUVersion 1.1a +Device Status: 0x0001 + Self Powered diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/tdk-bluetooth.lsusb b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/tdk-bluetooth.lsusb new file mode 100644 index 0000000..c0cface --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/device-logs/tdk-bluetooth.lsusb @@ -0,0 +1,269 @@ + +Bus 006 Device 014: ID 04bf:0320 TDK Corp. Bluetooth Adapter +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 224 Wireless + bDeviceSubClass 1 Radio Frequency + bDeviceProtocol 1 Bluetooth + bMaxPacketSize0 64 + idVendor 0x04bf TDK Corp. + idProduct 0x0320 Bluetooth Adapter + bcdDevice 26.52 + iManufacturer 1 Ezurio + iProduct 2 Turbo Bluetooth Adapter + iSerial 3 008098D4FFBD + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 193 + bNumInterfaces 3 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 64mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 3 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0000 1x 0 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0000 1x 0 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 1 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0009 1x 9 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0009 1x 9 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 2 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0011 1x 17 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0011 1x 17 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 3 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0019 1x 25 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0019 1x 25 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 4 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0021 1x 33 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0021 1x 33 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 5 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0031 1x 49 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0031 1x 49 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 2 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 0 + iInterface 0 + Device Firmware Upgrade Interface Descriptor: + bLength 7 + bDescriptorType 33 + bmAttributes 7 + Will Not Detach + Manifestation Tolerant + Upload Supported + Download Supported + wDetachTimeout 5000 milliseconds + wTransferSize 1023 bytes +Device Status: 0x0000 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/dfuse-pack.py b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/dfuse-pack.py new file mode 100644 index 0000000..875cc5c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/dfuse-pack.py @@ -0,0 +1,121 @@ +#!/usr/bin/python + +# Written by Antonio Galea - 2010/11/18 +# Distributed under Gnu LGPL 3.0 +# see http://www.gnu.org/licenses/lgpl-3.0.txt + +import sys,struct,zlib,os +from optparse import OptionParser + +DEFAULT_DEVICE="0x0483:0xdf11" + +def named(tuple,names): + return dict(zip(names.split(),tuple)) +def consume(fmt,data,names): + n = struct.calcsize(fmt) + return named(struct.unpack(fmt,data[:n]),names),data[n:] +def cstring(string): + return string.split('\0',1)[0] +def compute_crc(data): + return 0xFFFFFFFF & -zlib.crc32(data) -1 + +def parse(file,dump_images=False): + print 'File: "%s"' % file + data = open(file,'rb').read() + crc = compute_crc(data[:-4]) + prefix, data = consume('<5sBIB',data,'signature version size targets') + print '%(signature)s v%(version)d, image size: %(size)d, targets: %(targets)d' % prefix + for t in range(prefix['targets']): + tprefix, data = consume('<6sBI255s2I',data,'signature altsetting named name size elements') + tprefix['num'] = t + if tprefix['named']: + tprefix['name'] = cstring(tprefix['name']) + else: + tprefix['name'] = '' + print '%(signature)s %(num)d, alt setting: %(altsetting)s, name: "%(name)s", size: %(size)d, elements: %(elements)d' % tprefix + tsize = tprefix['size'] + target, data = data[:tsize], data[tsize:] + for e in range(tprefix['elements']): + eprefix, target = consume('<2I',target,'address size') + eprefix['num'] = e + print ' %(num)d, address: 0x%(address)08x, size: %(size)d' % eprefix + esize = eprefix['size'] + image, target = target[:esize], target[esize:] + if dump_images: + out = '%s.target%d.image%d.bin' % (file,t,e) + open(out,'wb').write(image) + print ' DUMPED IMAGE TO "%s"' % out + if len(target): + print "target %d: PARSE ERROR" % t + suffix = named(struct.unpack('<4H3sBI',data[:16]),'device product vendor dfu ufd len crc') + print 'usb: %(vendor)04x:%(product)04x, device: 0x%(device)04x, dfu: 0x%(dfu)04x, %(ufd)s, %(len)d, 0x%(crc)08x' % suffix + if crc != suffix['crc']: + print "CRC ERROR: computed crc32 is 0x%08x" % crc + data = data[16:] + if data: + print "PARSE ERROR" + +def build(file,targets,device=DEFAULT_DEVICE): + data = '' + for t,target in enumerate(targets): + tdata = '' + for image in target: + tdata += struct.pack('<2I',image['address'],len(image['data']))+image['data'] + tdata = struct.pack('<6sBI255s2I','Target',0,1,'ST...',len(tdata),len(target)) + tdata + data += tdata + data = struct.pack('<5sBIB','DfuSe',1,len(data)+11,len(targets)) + data + v,d=map(lambda x: int(x,0) & 0xFFFF, device.split(':',1)) + data += struct.pack('<4H3sB',0,d,v,0x011a,'UFD',16) + crc = compute_crc(data) + data += struct.pack(' and +Harald Welte . Over time, nearly complete +support of DFU 1.0, DFU 1.1 and DfuSe ("1.1a") has been added. +.SH LICENCE +.B dfu-util +is covered by the GNU General Public License (GPL), version 2 or later. +.SH COPYRIGHT +This manual page was originally written by Uwe Hermann , +and is now part of the dfu-util project. diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/msvc/README_msvc.txt b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/msvc/README_msvc.txt new file mode 100644 index 0000000..6e68ec6 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/msvc/README_msvc.txt @@ -0,0 +1,10 @@ +# (C) Roger Meier +# (C) Pascal Schweizer +# msvc folder is GPL-2.0+, LGPL-2.1+, BSD-3-Clause or MIT license(SPDX) + +Building dfu-util native on Windows with Visual Studio + +3rd party dependencies: +- libusbx ( git clone https://github.com/libusbx/libusbx.git ) + - getopt (part of libusbx: libusbx/examples/getopt) + diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/msvc/dfu-suffix_2010.vcxproj b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/msvc/dfu-suffix_2010.vcxproj new file mode 100644 index 0000000..0c316c2 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/msvc/dfu-suffix_2010.vcxproj @@ -0,0 +1,100 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA} + dfusuffix + dfu-suffix + + + + Application + true + MultiByte + + + Application + false + true + MultiByte + + + + + + + + + + + + + $(SolutionDir)..\..\libusbx\examples\getopt;$(SolutionDir)..\..\libusbx\libusb;$(IncludePath) + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\dll;$(LibraryPath) + $(VCInstallDir)atlmfc\lib;$(VCInstallDir)lib + $(ExecutablePath) + + + $(ExecutablePath) + $(SolutionDir)..\..\libusbx\examples\getopt;$(SolutionDir)..\..\libusbx\libusb;$(IncludePath) + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\dll;$(LibraryPath) + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + + + + Level3 + Disabled + HAVE_WINDOWS_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreadedDebug + + + true + + + + + Level3 + MaxSpeed + true + true + HAVE_WINDOWS_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreaded + + + true + true + true + + + + + + + + + + + + + {a2169bc8-cf99-40bf-83f3-b0e38f7067bd} + + + {349ee8f9-7d25-4909-aaf5-ff3fade72187} + + + + + + \ No newline at end of file diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/msvc/dfu-util_2010.sln b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/msvc/dfu-util_2010.sln new file mode 100644 index 0000000..ef79723 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/msvc/dfu-util_2010.sln @@ -0,0 +1,54 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dfu-util", "dfu-util_2010.vcxproj", "{0E071A60-7EF2-4427-BAA8-9143CACB5BCB}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C4F8746D-B27E-4806-95E5-2052174E923B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dfu-suffix", "dfu-suffix_2010.vcxproj", "{8F7600A2-3B37-4956-B39B-A1D43EF29EDA}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "getopt_2010", "..\..\libusbx\msvc\getopt_2010.vcxproj", "{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (static)", "..\..\libusbx\msvc\libusb_static_2010.vcxproj", "{349EE8F9-7D25-4909-AAF5-FF3FADE72187}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB}.Debug|Win32.ActiveCfg = Debug|Win32 + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB}.Debug|Win32.Build.0 = Debug|Win32 + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB}.Debug|x64.ActiveCfg = Debug|Win32 + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB}.Release|Win32.ActiveCfg = Release|Win32 + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB}.Release|Win32.Build.0 = Release|Win32 + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB}.Release|x64.ActiveCfg = Release|Win32 + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA}.Debug|Win32.ActiveCfg = Debug|Win32 + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA}.Debug|Win32.Build.0 = Debug|Win32 + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA}.Debug|x64.ActiveCfg = Debug|Win32 + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA}.Release|Win32.ActiveCfg = Release|Win32 + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA}.Release|Win32.Build.0 = Release|Win32 + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA}.Release|x64.ActiveCfg = Release|Win32 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|Win32.ActiveCfg = Debug|Win32 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|Win32.Build.0 = Debug|Win32 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|x64.ActiveCfg = Debug|x64 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|x64.Build.0 = Debug|x64 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|Win32.ActiveCfg = Release|Win32 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|Win32.Build.0 = Release|Win32 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|x64.ActiveCfg = Release|x64 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|x64.Build.0 = Release|x64 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.ActiveCfg = Debug|Win32 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.Build.0 = Debug|Win32 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.ActiveCfg = Debug|x64 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.Build.0 = Debug|x64 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.ActiveCfg = Release|Win32 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.Build.0 = Release|Win32 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.ActiveCfg = Release|x64 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/msvc/dfu-util_2010.vcxproj b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/msvc/dfu-util_2010.vcxproj new file mode 100644 index 0000000..17a8bee --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/msvc/dfu-util_2010.vcxproj @@ -0,0 +1,120 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB} + dfuutil + dfu-util + + + + Application + true + MultiByte + + + Application + false + true + MultiByte + + + + + + + + + + + + + $(SolutionDir)..\..\libusbx\examples\getopt;$(SolutionDir)..\..\libusbx\libusb;$(IncludePath) + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + $(SolutionDir)..\$(Platform)\getopt\$(Configuration);$(LibraryPath) + $(VCInstallDir)atlmfc\lib;$(VCInstallDir)lib + $(ExecutablePath) + + + $(ExecutablePath) + $(SolutionDir)..\..\libusbx\examples\getopt;$(SolutionDir)..\..\libusbx\libusb;$(IncludePath) + $(SolutionDir)..\$(Platform)\getopt\$(Configuration);$(LibraryPath) + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + + + + Level3 + Disabled + HAVE_WINDOWS_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreadedDebug + + + true + + + + + + + + + Level3 + MaxSpeed + true + true + HAVE_WINDOWS_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreaded + + + true + true + true + + + copy $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0.dll $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + + + + + + + + + + + + + + + + + + + + + + + + + + {a2169bc8-cf99-40bf-83f3-b0e38f7067bd} + + + {349ee8f9-7d25-4909-aaf5-ff3fade72187} + + + + + + \ No newline at end of file diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/Makefile.am b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/Makefile.am new file mode 100644 index 0000000..70179c4 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/Makefile.am @@ -0,0 +1,28 @@ +AM_CFLAGS = -Wall -Wextra + +bin_PROGRAMS = dfu-util dfu-suffix dfu-prefix +dfu_util_SOURCES = main.c \ + portable.h \ + dfu_load.c \ + dfu_load.h \ + dfu_util.c \ + dfu_util.h \ + dfuse.c \ + dfuse.h \ + dfuse_mem.c \ + dfuse_mem.h \ + dfu.c \ + dfu.h \ + usb_dfu.h \ + dfu_file.c \ + dfu_file.h \ + quirks.c \ + quirks.h + +dfu_suffix_SOURCES = suffix.c \ + dfu_file.h \ + dfu_file.c + +dfu_prefix_SOURCES = prefix.c \ + dfu_file.h \ + dfu_file.c diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfu.c b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfu.c new file mode 100644 index 0000000..14d7673 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfu.c @@ -0,0 +1,357 @@ +/* + * Low-level DFU communication routines, originally taken from + * $Id: dfu.c,v 1.3 2006/06/20 06:28:04 schmidtw Exp $ + * (part of dfu-programmer). + * + * Copyright 2005-2006 Weston Schmidt + * Copyright 2011-2014 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include + +#include "portable.h" +#include "dfu.h" +#include "quirks.h" + +static int dfu_timeout = 5000; /* 5 seconds - default */ + +/* + * DFU_DETACH Request (DFU Spec 1.0, Section 5.1) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * timeout - the timeout in ms the USB device should wait for a pending + * USB reset before giving up and terminating the operation + * + * returns 0 or < 0 on error + */ +int dfu_detach( libusb_device_handle *device, + const unsigned short interface, + const unsigned short timeout ) +{ + return libusb_control_transfer( device, + /* bmRequestType */ LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_DETACH, + /* wValue */ timeout, + /* wIndex */ interface, + /* Data */ NULL, + /* wLength */ 0, + dfu_timeout ); +} + + +/* + * DFU_DNLOAD Request (DFU Spec 1.0, Section 6.1.1) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * length - the total number of bytes to transfer to the USB + * device - must be less than wTransferSize + * data - the data to transfer + * + * returns the number of bytes written or < 0 on error + */ +int dfu_download( libusb_device_handle *device, + const unsigned short interface, + const unsigned short length, + const unsigned short transaction, + unsigned char* data ) +{ + int status; + + status = libusb_control_transfer( device, + /* bmRequestType */ LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_DNLOAD, + /* wValue */ transaction, + /* wIndex */ interface, + /* Data */ data, + /* wLength */ length, + dfu_timeout ); + return status; +} + + +/* + * DFU_UPLOAD Request (DFU Spec 1.0, Section 6.2) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * length - the maximum number of bytes to receive from the USB + * device - must be less than wTransferSize + * data - the buffer to put the received data in + * + * returns the number of bytes received or < 0 on error + */ +int dfu_upload( libusb_device_handle *device, + const unsigned short interface, + const unsigned short length, + const unsigned short transaction, + unsigned char* data ) +{ + int status; + + status = libusb_control_transfer( device, + /* bmRequestType */ LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_UPLOAD, + /* wValue */ transaction, + /* wIndex */ interface, + /* Data */ data, + /* wLength */ length, + dfu_timeout ); + return status; +} + + +/* + * DFU_GETSTATUS Request (DFU Spec 1.0, Section 6.1.2) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * status - the data structure to be populated with the results + * + * return the number of bytes read in or < 0 on an error + */ +int dfu_get_status( struct dfu_if *dif, struct dfu_status *status ) +{ + unsigned char buffer[6]; + int result; + + /* Initialize the status data structure */ + status->bStatus = DFU_STATUS_ERROR_UNKNOWN; + status->bwPollTimeout = 0; + status->bState = STATE_DFU_ERROR; + status->iString = 0; + + result = libusb_control_transfer( dif->dev_handle, + /* bmRequestType */ LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_GETSTATUS, + /* wValue */ 0, + /* wIndex */ dif->interface, + /* Data */ buffer, + /* wLength */ 6, + dfu_timeout ); + + if( 6 == result ) { + status->bStatus = buffer[0]; + if (dif->quirks & QUIRK_POLLTIMEOUT) + status->bwPollTimeout = DEFAULT_POLLTIMEOUT; + else + status->bwPollTimeout = ((0xff & buffer[3]) << 16) | + ((0xff & buffer[2]) << 8) | + (0xff & buffer[1]); + status->bState = buffer[4]; + status->iString = buffer[5]; + } + + return result; +} + + +/* + * DFU_CLRSTATUS Request (DFU Spec 1.0, Section 6.1.3) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * + * return 0 or < 0 on an error + */ +int dfu_clear_status( libusb_device_handle *device, + const unsigned short interface ) +{ + return libusb_control_transfer( device, + /* bmRequestType */ LIBUSB_ENDPOINT_OUT| LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_CLRSTATUS, + /* wValue */ 0, + /* wIndex */ interface, + /* Data */ NULL, + /* wLength */ 0, + dfu_timeout ); +} + + +/* + * DFU_GETSTATE Request (DFU Spec 1.0, Section 6.1.5) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * length - the maximum number of bytes to receive from the USB + * device - must be less than wTransferSize + * data - the buffer to put the received data in + * + * returns the state or < 0 on error + */ +int dfu_get_state( libusb_device_handle *device, + const unsigned short interface ) +{ + int result; + unsigned char buffer[1]; + + result = libusb_control_transfer( device, + /* bmRequestType */ LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_GETSTATE, + /* wValue */ 0, + /* wIndex */ interface, + /* Data */ buffer, + /* wLength */ 1, + dfu_timeout ); + + /* Return the error if there is one. */ + if (result < 1) + return -1; + + /* Return the state. */ + return buffer[0]; +} + + +/* + * DFU_ABORT Request (DFU Spec 1.0, Section 6.1.4) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * + * returns 0 or < 0 on an error + */ +int dfu_abort( libusb_device_handle *device, + const unsigned short interface ) +{ + return libusb_control_transfer( device, + /* bmRequestType */ LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_ABORT, + /* wValue */ 0, + /* wIndex */ interface, + /* Data */ NULL, + /* wLength */ 0, + dfu_timeout ); +} + + +const char* dfu_state_to_string( int state ) +{ + const char *message; + + switch (state) { + case STATE_APP_IDLE: + message = "appIDLE"; + break; + case STATE_APP_DETACH: + message = "appDETACH"; + break; + case STATE_DFU_IDLE: + message = "dfuIDLE"; + break; + case STATE_DFU_DOWNLOAD_SYNC: + message = "dfuDNLOAD-SYNC"; + break; + case STATE_DFU_DOWNLOAD_BUSY: + message = "dfuDNBUSY"; + break; + case STATE_DFU_DOWNLOAD_IDLE: + message = "dfuDNLOAD-IDLE"; + break; + case STATE_DFU_MANIFEST_SYNC: + message = "dfuMANIFEST-SYNC"; + break; + case STATE_DFU_MANIFEST: + message = "dfuMANIFEST"; + break; + case STATE_DFU_MANIFEST_WAIT_RESET: + message = "dfuMANIFEST-WAIT-RESET"; + break; + case STATE_DFU_UPLOAD_IDLE: + message = "dfuUPLOAD-IDLE"; + break; + case STATE_DFU_ERROR: + message = "dfuERROR"; + break; + default: + message = NULL; + break; + } + + return message; +} + +/* Chapter 6.1.2 */ +static const char *dfu_status_names[] = { + /* DFU_STATUS_OK */ + "No error condition is present", + /* DFU_STATUS_errTARGET */ + "File is not targeted for use by this device", + /* DFU_STATUS_errFILE */ + "File is for this device but fails some vendor-specific test", + /* DFU_STATUS_errWRITE */ + "Device is unable to write memory", + /* DFU_STATUS_errERASE */ + "Memory erase function failed", + /* DFU_STATUS_errCHECK_ERASED */ + "Memory erase check failed", + /* DFU_STATUS_errPROG */ + "Program memory function failed", + /* DFU_STATUS_errVERIFY */ + "Programmed memory failed verification", + /* DFU_STATUS_errADDRESS */ + "Cannot program memory due to received address that is out of range", + /* DFU_STATUS_errNOTDONE */ + "Received DFU_DNLOAD with wLength = 0, but device does not think that it has all data yet", + /* DFU_STATUS_errFIRMWARE */ + "Device's firmware is corrupt. It cannot return to run-time (non-DFU) operations", + /* DFU_STATUS_errVENDOR */ + "iString indicates a vendor specific error", + /* DFU_STATUS_errUSBR */ + "Device detected unexpected USB reset signalling", + /* DFU_STATUS_errPOR */ + "Device detected unexpected power on reset", + /* DFU_STATUS_errUNKNOWN */ + "Something went wrong, but the device does not know what it was", + /* DFU_STATUS_errSTALLEDPKT */ + "Device stalled an unexpected request" +}; + + +const char *dfu_status_to_string(int status) +{ + if (status > DFU_STATUS_errSTALLEDPKT) + return "INVALID"; + return dfu_status_names[status]; +} + +int dfu_abort_to_idle(struct dfu_if *dif) +{ + int ret; + struct dfu_status dst; + + ret = dfu_abort(dif->dev_handle, dif->interface); + if (ret < 0) { + errx(EX_IOERR, "Error sending dfu abort request"); + exit(1); + } + ret = dfu_get_status(dif, &dst); + if (ret < 0) { + errx(EX_IOERR, "Error during abort get_status"); + exit(1); + } + if (dst.bState != DFU_STATE_dfuIDLE) { + errx(EX_IOERR, "Failed to enter idle state on abort"); + exit(1); + } + milli_sleep(dst.bwPollTimeout); + return ret; +} diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfu.h b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfu.h new file mode 100644 index 0000000..8e3caeb --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfu.h @@ -0,0 +1,133 @@ +/* + * dfu-programmer + * + * $Id: dfu.h,v 1.2 2005/09/25 01:27:42 schmidtw Exp $ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DFU_H +#define DFU_H + +#include +#include "usb_dfu.h" + +/* DFU states */ +#define STATE_APP_IDLE 0x00 +#define STATE_APP_DETACH 0x01 +#define STATE_DFU_IDLE 0x02 +#define STATE_DFU_DOWNLOAD_SYNC 0x03 +#define STATE_DFU_DOWNLOAD_BUSY 0x04 +#define STATE_DFU_DOWNLOAD_IDLE 0x05 +#define STATE_DFU_MANIFEST_SYNC 0x06 +#define STATE_DFU_MANIFEST 0x07 +#define STATE_DFU_MANIFEST_WAIT_RESET 0x08 +#define STATE_DFU_UPLOAD_IDLE 0x09 +#define STATE_DFU_ERROR 0x0a + + +/* DFU status */ +#define DFU_STATUS_OK 0x00 +#define DFU_STATUS_ERROR_TARGET 0x01 +#define DFU_STATUS_ERROR_FILE 0x02 +#define DFU_STATUS_ERROR_WRITE 0x03 +#define DFU_STATUS_ERROR_ERASE 0x04 +#define DFU_STATUS_ERROR_CHECK_ERASED 0x05 +#define DFU_STATUS_ERROR_PROG 0x06 +#define DFU_STATUS_ERROR_VERIFY 0x07 +#define DFU_STATUS_ERROR_ADDRESS 0x08 +#define DFU_STATUS_ERROR_NOTDONE 0x09 +#define DFU_STATUS_ERROR_FIRMWARE 0x0a +#define DFU_STATUS_ERROR_VENDOR 0x0b +#define DFU_STATUS_ERROR_USBR 0x0c +#define DFU_STATUS_ERROR_POR 0x0d +#define DFU_STATUS_ERROR_UNKNOWN 0x0e +#define DFU_STATUS_ERROR_STALLEDPKT 0x0f + +/* DFU commands */ +#define DFU_DETACH 0 +#define DFU_DNLOAD 1 +#define DFU_UPLOAD 2 +#define DFU_GETSTATUS 3 +#define DFU_CLRSTATUS 4 +#define DFU_GETSTATE 5 +#define DFU_ABORT 6 + +/* DFU interface */ +#define DFU_IFF_DFU 0x0001 /* DFU Mode, (not Runtime) */ + +/* This is based off of DFU_GETSTATUS + * + * 1 unsigned byte bStatus + * 3 unsigned byte bwPollTimeout + * 1 unsigned byte bState + * 1 unsigned byte iString +*/ + +struct dfu_status { + unsigned char bStatus; + unsigned int bwPollTimeout; + unsigned char bState; + unsigned char iString; +}; + +struct dfu_if { + struct usb_dfu_func_descriptor func_dfu; + uint16_t quirks; + uint16_t busnum; + uint16_t devnum; + uint16_t vendor; + uint16_t product; + uint16_t bcdDevice; + uint8_t configuration; + uint8_t interface; + uint8_t altsetting; + uint8_t flags; + uint8_t bMaxPacketSize0; + char *alt_name; + char *serial_name; + libusb_device *dev; + libusb_device_handle *dev_handle; + struct dfu_if *next; +}; + +int dfu_detach( libusb_device_handle *device, + const unsigned short interface, + const unsigned short timeout ); +int dfu_download( libusb_device_handle *device, + const unsigned short interface, + const unsigned short length, + const unsigned short transaction, + unsigned char* data ); +int dfu_upload( libusb_device_handle *device, + const unsigned short interface, + const unsigned short length, + const unsigned short transaction, + unsigned char* data ); +int dfu_get_status( struct dfu_if *dif, + struct dfu_status *status ); +int dfu_clear_status( libusb_device_handle *device, + const unsigned short interface ); +int dfu_get_state( libusb_device_handle *device, + const unsigned short interface ); +int dfu_abort( libusb_device_handle *device, + const unsigned short interface ); +int dfu_abort_to_idle( struct dfu_if *dif); + +const char *dfu_state_to_string( int state ); + +const char *dfu_status_to_string( int status ); + +#endif /* DFU_H */ diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfu_file.c b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfu_file.c new file mode 100644 index 0000000..7c897d4 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfu_file.c @@ -0,0 +1,444 @@ +/* + * Load or store DFU files including suffix and prefix + * + * Copyright 2014 Tormod Volden + * Copyright 2012 Stefan Schmidt + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "portable.h" +#include "dfu_file.h" + +#define DFU_SUFFIX_LENGTH 16 +#define LMDFU_PREFIX_LENGTH 8 +#define LPCDFU_PREFIX_LENGTH 16 +#define PROGRESS_BAR_WIDTH 25 +#define STDIN_CHUNK_SIZE 65536 + +static const unsigned long crc32_table[] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d}; + +static uint32_t crc32_byte(uint32_t accum, uint8_t delta) +{ + return crc32_table[(accum ^ delta) & 0xff] ^ (accum >> 8); +} + +static int probe_prefix(struct dfu_file *file) +{ + uint8_t *prefix = file->firmware; + + if (file->size.total < LMDFU_PREFIX_LENGTH) + return 1; + if ((prefix[0] == 0x01) && (prefix[1] == 0x00)) { + file->prefix_type = LMDFU_PREFIX; + file->size.prefix = LMDFU_PREFIX_LENGTH; + file->lmdfu_address = 1024 * ((prefix[3] << 8) | prefix[2]); + } + else if (((prefix[0] & 0x3f) == 0x1a) && ((prefix[1] & 0x3f)== 0x3f)) { + file->prefix_type = LPCDFU_UNENCRYPTED_PREFIX; + file->size.prefix = LPCDFU_PREFIX_LENGTH; + } + + if (file->size.prefix + file->size.suffix > file->size.total) + return 1; + return 0; +} + +void dfu_progress_bar(const char *desc, unsigned long long curr, + unsigned long long max) +{ + static char buf[PROGRESS_BAR_WIDTH + 1]; + static unsigned long long last_progress = -1; + static time_t last_time; + time_t curr_time = time(NULL); + unsigned long long progress; + unsigned long long x; + + /* check for not known maximum */ + if (max < curr) + max = curr + 1; + /* make none out of none give zero */ + if (max == 0 && curr == 0) + max = 1; + + /* compute completion */ + progress = (PROGRESS_BAR_WIDTH * curr) / max; + if (progress > PROGRESS_BAR_WIDTH) + progress = PROGRESS_BAR_WIDTH; + if (progress == last_progress && + curr_time == last_time) + return; + last_progress = progress; + last_time = curr_time; + + for (x = 0; x != PROGRESS_BAR_WIDTH; x++) { + if (x < progress) + buf[x] = '='; + else + buf[x] = ' '; + } + buf[x] = 0; + + printf("\r%s\t[%s] %3lld%% %12lld bytes", desc, buf, + (100ULL * curr) / max, curr); + + if (progress == PROGRESS_BAR_WIDTH) + printf("\n%s done.\n", desc); +} + +void *dfu_malloc(size_t size) +{ + void *ptr = malloc(size); + if (ptr == NULL) + errx(EX_SOFTWARE, "Cannot allocate memory of size %d bytes", (int)size); + return (ptr); +} + +uint32_t dfu_file_write_crc(int f, uint32_t crc, const void *buf, int size) +{ + int x; + + /* compute CRC */ + for (x = 0; x != size; x++) + crc = crc32_byte(crc, ((uint8_t *)buf)[x]); + + /* write data */ + if (write(f, buf, size) != size) + err(EX_IOERR, "Could not write %d bytes to file %d", size, f); + + return (crc); +} + +void dfu_load_file(struct dfu_file *file, enum suffix_req check_suffix, enum prefix_req check_prefix) +{ + off_t offset; + int f; + int i; + int res; + + file->size.prefix = 0; + file->size.suffix = 0; + + /* default values, if no valid suffix is found */ + file->bcdDFU = 0; + file->idVendor = 0xffff; /* wildcard value */ + file->idProduct = 0xffff; /* wildcard value */ + file->bcdDevice = 0xffff; /* wildcard value */ + + /* default values, if no valid prefix is found */ + file->lmdfu_address = 0; + + free(file->firmware); + + if (!strcmp(file->name, "-")) { + int read_bytes; + +#ifdef WIN32 + _setmode( _fileno( stdin ), _O_BINARY ); +#endif + file->firmware = (uint8_t*) dfu_malloc(STDIN_CHUNK_SIZE); + read_bytes = fread(file->firmware, 1, STDIN_CHUNK_SIZE, stdin); + file->size.total = read_bytes; + while (read_bytes == STDIN_CHUNK_SIZE) { + file->firmware = (uint8_t*) realloc(file->firmware, file->size.total + STDIN_CHUNK_SIZE); + if (!file->firmware) + err(EX_IOERR, "Could not allocate firmware buffer"); + read_bytes = fread(file->firmware + file->size.total, 1, STDIN_CHUNK_SIZE, stdin); + file->size.total += read_bytes; + } + if (verbose) + printf("Read %i bytes from stdin\n", file->size.total); + /* Never require suffix when reading from stdin */ + check_suffix = MAYBE_SUFFIX; + } else { + f = open(file->name, O_RDONLY | O_BINARY); + if (f < 0) + err(EX_IOERR, "Could not open file %s for reading", file->name); + + offset = lseek(f, 0, SEEK_END); + + if ((int)offset < 0 || (int)offset != offset) + err(EX_IOERR, "File size is too big"); + + if (lseek(f, 0, SEEK_SET) != 0) + err(EX_IOERR, "Could not seek to beginning"); + + file->size.total = offset; + file->firmware = dfu_malloc(file->size.total); + + if (read(f, file->firmware, file->size.total) != file->size.total) { + err(EX_IOERR, "Could not read %d bytes from %s", + file->size.total, file->name); + } + close(f); + } + + /* Check for possible DFU file suffix by trying to parse one */ + { + uint32_t crc = 0xffffffff; + const uint8_t *dfusuffix; + int missing_suffix = 0; + const char *reason; + + if (file->size.total < DFU_SUFFIX_LENGTH) { + reason = "File too short for DFU suffix"; + missing_suffix = 1; + goto checked; + } + + dfusuffix = file->firmware + file->size.total - + DFU_SUFFIX_LENGTH; + + for (i = 0; i < file->size.total - 4; i++) + crc = crc32_byte(crc, file->firmware[i]); + + if (dfusuffix[10] != 'D' || + dfusuffix[9] != 'F' || + dfusuffix[8] != 'U') { + reason = "Invalid DFU suffix signature"; + missing_suffix = 1; + goto checked; + } + + file->dwCRC = (dfusuffix[15] << 24) + + (dfusuffix[14] << 16) + + (dfusuffix[13] << 8) + + dfusuffix[12]; + + if (file->dwCRC != crc) { + reason = "DFU suffix CRC does not match"; + missing_suffix = 1; + goto checked; + } + + /* At this point we believe we have a DFU suffix + so we require further checks to succeed */ + + file->bcdDFU = (dfusuffix[7] << 8) + dfusuffix[6]; + + if (verbose) + printf("DFU suffix version %x\n", file->bcdDFU); + + file->size.suffix = dfusuffix[11]; + + if (file->size.suffix < DFU_SUFFIX_LENGTH) { + errx(EX_IOERR, "Unsupported DFU suffix length %d", + file->size.suffix); + } + + if (file->size.suffix > file->size.total) { + errx(EX_IOERR, "Invalid DFU suffix length %d", + file->size.suffix); + } + + file->idVendor = (dfusuffix[5] << 8) + dfusuffix[4]; + file->idProduct = (dfusuffix[3] << 8) + dfusuffix[2]; + file->bcdDevice = (dfusuffix[1] << 8) + dfusuffix[0]; + +checked: + if (missing_suffix) { + if (check_suffix == NEEDS_SUFFIX) { + warnx("%s", reason); + errx(EX_IOERR, "Valid DFU suffix needed"); + } else if (check_suffix == MAYBE_SUFFIX) { + warnx("%s", reason); + warnx("A valid DFU suffix will be required in " + "a future dfu-util release!!!"); + } + } else { + if (check_suffix == NO_SUFFIX) { + errx(EX_SOFTWARE, "Please remove existing DFU suffix before adding a new one.\n"); + } + } + } + res = probe_prefix(file); + if ((res || file->size.prefix == 0) && check_prefix == NEEDS_PREFIX) + errx(EX_IOERR, "Valid DFU prefix needed"); + if (file->size.prefix && check_prefix == NO_PREFIX) + errx(EX_IOERR, "A prefix already exists, please delete it first"); + if (file->size.prefix && verbose) { + uint8_t *data = file->firmware; + if (file->prefix_type == LMDFU_PREFIX) + printf("Possible TI Stellaris DFU prefix with " + "the following properties\n" + "Address: 0x%08x\n" + "Payload length: %d\n", + file->lmdfu_address, + data[4] | (data[5] << 8) | + (data[6] << 16) | (data[7] << 14)); + else if (file->prefix_type == LPCDFU_UNENCRYPTED_PREFIX) + printf("Possible unencrypted NXP LPC DFU prefix with " + "the following properties\n" + "Payload length: %d kiByte\n", + data[2] >>1 | (data[3] << 7) ); + else + errx(EX_IOERR, "Unknown DFU prefix type"); + } +} + +void dfu_store_file(struct dfu_file *file, int write_suffix, int write_prefix) +{ + uint32_t crc = 0xffffffff; + int f; + + f = open(file->name, O_WRONLY | O_BINARY | O_TRUNC | O_CREAT, 0666); + if (f < 0) + err(EX_IOERR, "Could not open file %s for writing", file->name); + + /* write prefix, if any */ + if (write_prefix) { + if (file->prefix_type == LMDFU_PREFIX) { + uint8_t lmdfu_prefix[LMDFU_PREFIX_LENGTH]; + uint32_t addr = file->lmdfu_address / 1024; + + /* lmdfu_dfu_prefix payload length excludes prefix and suffix */ + uint32_t len = file->size.total - + file->size.prefix - file->size.suffix; + + lmdfu_prefix[0] = 0x01; /* STELLARIS_DFU_PROG */ + lmdfu_prefix[1] = 0x00; /* Reserved */ + lmdfu_prefix[2] = (uint8_t)(addr & 0xff); + lmdfu_prefix[3] = (uint8_t)(addr >> 8); + lmdfu_prefix[4] = (uint8_t)(len & 0xff); + lmdfu_prefix[5] = (uint8_t)(len >> 8) & 0xff; + lmdfu_prefix[6] = (uint8_t)(len >> 16) & 0xff; + lmdfu_prefix[7] = (uint8_t)(len >> 24); + + crc = dfu_file_write_crc(f, crc, lmdfu_prefix, LMDFU_PREFIX_LENGTH); + } + if (file->prefix_type == LPCDFU_UNENCRYPTED_PREFIX) { + uint8_t lpcdfu_prefix[LPCDFU_PREFIX_LENGTH] = {0}; + int i; + + /* Payload is firmware and prefix rounded to 512 bytes */ + uint32_t len = (file->size.total - file->size.suffix + 511) /512; + + lpcdfu_prefix[0] = 0x1a; /* Unencypted*/ + lpcdfu_prefix[1] = 0x3f; /* Reserved */ + lpcdfu_prefix[2] = (uint8_t)(len & 0xff); + lpcdfu_prefix[3] = (uint8_t)((len >> 8) & 0xff); + for (i = 12; i < LPCDFU_PREFIX_LENGTH; i++) + lpcdfu_prefix[i] = 0xff; + + crc = dfu_file_write_crc(f, crc, lpcdfu_prefix, LPCDFU_PREFIX_LENGTH); + } + } + /* write firmware binary */ + crc = dfu_file_write_crc(f, crc, file->firmware + file->size.prefix, + file->size.total - file->size.prefix - file->size.suffix); + + /* write suffix, if any */ + if (write_suffix) { + uint8_t dfusuffix[DFU_SUFFIX_LENGTH]; + + dfusuffix[0] = file->bcdDevice & 0xff; + dfusuffix[1] = file->bcdDevice >> 8; + dfusuffix[2] = file->idProduct & 0xff; + dfusuffix[3] = file->idProduct >> 8; + dfusuffix[4] = file->idVendor & 0xff; + dfusuffix[5] = file->idVendor >> 8; + dfusuffix[6] = file->bcdDFU & 0xff; + dfusuffix[7] = file->bcdDFU >> 8; + dfusuffix[8] = 'U'; + dfusuffix[9] = 'F'; + dfusuffix[10] = 'D'; + dfusuffix[11] = DFU_SUFFIX_LENGTH; + + crc = dfu_file_write_crc(f, crc, dfusuffix, + DFU_SUFFIX_LENGTH - 4); + + dfusuffix[12] = crc; + dfusuffix[13] = crc >> 8; + dfusuffix[14] = crc >> 16; + dfusuffix[15] = crc >> 24; + + crc = dfu_file_write_crc(f, crc, dfusuffix + 12, 4); + } + close(f); +} + +void show_suffix_and_prefix(struct dfu_file *file) +{ + if (file->size.prefix == LMDFU_PREFIX_LENGTH) { + printf("The file %s contains a TI Stellaris DFU prefix with the following properties:\n", file->name); + printf("Address:\t0x%08x\n", file->lmdfu_address); + } else if (file->size.prefix == LPCDFU_PREFIX_LENGTH) { + uint8_t * prefix = file->firmware; + printf("The file %s contains a NXP unencrypted LPC DFU prefix with the following properties:\n", file->name); + printf("Size:\t%5d kiB\n", prefix[2]>>1|prefix[3]<<7); + } else if (file->size.prefix != 0) { + printf("The file %s contains an unknown prefix\n", file->name); + } + if (file->size.suffix > 0) { + printf("The file %s contains a DFU suffix with the following properties:\n", file->name); + printf("BCD device:\t0x%04X\n", file->bcdDevice); + printf("Product ID:\t0x%04X\n",file->idProduct); + printf("Vendor ID:\t0x%04X\n", file->idVendor); + printf("BCD DFU:\t0x%04X\n", file->bcdDFU); + printf("Length:\t\t%i\n", file->size.suffix); + printf("CRC:\t\t0x%08X\n", file->dwCRC); + } +} diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfu_file.h b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfu_file.h new file mode 100644 index 0000000..abebd44 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfu_file.h @@ -0,0 +1,60 @@ + +#ifndef DFU_FILE_H +#define DFU_FILE_H + +#include + +struct dfu_file { + /* File name */ + const char *name; + /* Pointer to file loaded into memory */ + uint8_t *firmware; + /* Different sizes */ + struct { + int total; + int prefix; + int suffix; + } size; + /* From prefix fields */ + uint32_t lmdfu_address; + /* From prefix fields */ + uint32_t prefix_type; + + /* From DFU suffix fields */ + uint32_t dwCRC; + uint16_t bcdDFU; + uint16_t idVendor; + uint16_t idProduct; + uint16_t bcdDevice; +}; + +enum suffix_req { + NO_SUFFIX, + NEEDS_SUFFIX, + MAYBE_SUFFIX +}; + +enum prefix_req { + NO_PREFIX, + NEEDS_PREFIX, + MAYBE_PREFIX +}; + +enum prefix_type { + ZERO_PREFIX, + LMDFU_PREFIX, + LPCDFU_UNENCRYPTED_PREFIX +}; + +extern int verbose; + +void dfu_load_file(struct dfu_file *file, enum suffix_req check_suffix, enum prefix_req check_prefix); +void dfu_store_file(struct dfu_file *file, int write_suffix, int write_prefix); + +void dfu_progress_bar(const char *desc, unsigned long long curr, + unsigned long long max); +void *dfu_malloc(size_t size); +uint32_t dfu_file_write_crc(int f, uint32_t crc, const void *buf, int size); +void show_suffix_and_prefix(struct dfu_file *file); + +#endif /* DFU_FILE_H */ diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfu_load.c b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfu_load.c new file mode 100644 index 0000000..64f7009 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfu_load.c @@ -0,0 +1,196 @@ +/* + * DFU transfer routines + * + * This is supposed to be a general DFU implementation, as specified in the + * USB DFU 1.0 and 1.1 specification. + * + * The code was originally intended to interface with a USB device running the + * "sam7dfu" firmware (see http://www.openpcd.org/) on an AT91SAM7 processor. + * + * Copyright 2007-2008 Harald Welte + * Copyright 2013 Hans Petter Selasky + * Copyright 2014 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include + +#include "portable.h" +#include "dfu.h" +#include "usb_dfu.h" +#include "dfu_file.h" +#include "dfu_load.h" +#include "quirks.h" + +int dfuload_do_upload(struct dfu_if *dif, int xfer_size, + int expected_size, int fd) +{ + int total_bytes = 0; + unsigned short transaction = 0; + unsigned char *buf; + int ret; + + buf = dfu_malloc(xfer_size); + + printf("Copying data from DFU device to PC\n"); + dfu_progress_bar("Upload", 0, 1); + + while (1) { + int rc; + rc = dfu_upload(dif->dev_handle, dif->interface, + xfer_size, transaction++, buf); + if (rc < 0) { + warnx("Error during upload"); + ret = rc; + goto out_free; + } + + dfu_file_write_crc(fd, 0, buf, rc); + total_bytes += rc; + + if (total_bytes < 0) + errx(EX_SOFTWARE, "Received too many bytes (wraparound)"); + + if (rc < xfer_size) { + /* last block, return */ + ret = total_bytes; + break; + } + dfu_progress_bar("Upload", total_bytes, expected_size); + } + ret = 0; + +out_free: + dfu_progress_bar("Upload", total_bytes, total_bytes); + if (total_bytes == 0) + printf("\nFailed.\n"); + free(buf); + if (verbose) + printf("Received a total of %i bytes\n", total_bytes); + if (expected_size != 0 && total_bytes != expected_size) + errx(EX_SOFTWARE, "Unexpected number of bytes uploaded from device"); + return ret; +} + +int dfuload_do_dnload(struct dfu_if *dif, int xfer_size, struct dfu_file *file) +{ + int bytes_sent; + int expected_size; + unsigned char *buf; + unsigned short transaction = 0; + struct dfu_status dst; + int ret; + + printf("Copying data from PC to DFU device\n"); + + buf = file->firmware; + expected_size = file->size.total - file->size.suffix; + bytes_sent = 0; + + dfu_progress_bar("Download", 0, 1); + while (bytes_sent < expected_size) { + int bytes_left; + int chunk_size; + + bytes_left = expected_size - bytes_sent; + if (bytes_left < xfer_size) + chunk_size = bytes_left; + else + chunk_size = xfer_size; + + ret = dfu_download(dif->dev_handle, dif->interface, + chunk_size, transaction++, chunk_size ? buf : NULL); + if (ret < 0) { + warnx("Error during download"); + goto out; + } + bytes_sent += chunk_size; + buf += chunk_size; + + do { + ret = dfu_get_status(dif, &dst); + if (ret < 0) { + errx(EX_IOERR, "Error during download get_status"); + goto out; + } + + if (dst.bState == DFU_STATE_dfuDNLOAD_IDLE || + dst.bState == DFU_STATE_dfuERROR) + break; + + /* Wait while device executes flashing */ + milli_sleep(dst.bwPollTimeout); + + } while (1); + if (dst.bStatus != DFU_STATUS_OK) { + printf(" failed!\n"); + printf("state(%u) = %s, status(%u) = %s\n", dst.bState, + dfu_state_to_string(dst.bState), dst.bStatus, + dfu_status_to_string(dst.bStatus)); + ret = -1; + goto out; + } + dfu_progress_bar("Download", bytes_sent, bytes_sent + bytes_left); + } + + /* send one zero sized download request to signalize end */ + ret = dfu_download(dif->dev_handle, dif->interface, + 0, transaction, NULL); + if (ret < 0) { + errx(EX_IOERR, "Error sending completion packet"); + goto out; + } + + dfu_progress_bar("Download", bytes_sent, bytes_sent); + + if (verbose) + printf("Sent a total of %i bytes\n", bytes_sent); + +get_status: + /* Transition to MANIFEST_SYNC state */ + ret = dfu_get_status(dif, &dst); + if (ret < 0) { + warnx("unable to read DFU status after completion"); + goto out; + } + printf("state(%u) = %s, status(%u) = %s\n", dst.bState, + dfu_state_to_string(dst.bState), dst.bStatus, + dfu_status_to_string(dst.bStatus)); + + milli_sleep(dst.bwPollTimeout); + + /* FIXME: deal correctly with ManifestationTolerant=0 / WillDetach bits */ + switch (dst.bState) { + case DFU_STATE_dfuMANIFEST_SYNC: + case DFU_STATE_dfuMANIFEST: + /* some devices (e.g. TAS1020b) need some time before we + * can obtain the status */ + milli_sleep(1000); + goto get_status; + break; + case DFU_STATE_dfuIDLE: + break; + } + printf("Done!\n"); + +out: + return bytes_sent; +} diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfu_load.h b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfu_load.h new file mode 100644 index 0000000..be23e9b --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfu_load.h @@ -0,0 +1,7 @@ +#ifndef DFU_LOAD_H +#define DFU_LOAD_H + +int dfuload_do_upload(struct dfu_if *dif, int xfer_size, int expected_size, int fd); +int dfuload_do_dnload(struct dfu_if *dif, int xfer_size, struct dfu_file *file); + +#endif /* DFU_LOAD_H */ diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfu_util.c b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfu_util.c new file mode 100644 index 0000000..b94c7cc --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfu_util.c @@ -0,0 +1,346 @@ +/* + * Functions for detecting DFU USB entities + * + * Written by Harald Welte + * Copyright 2007-2008 by OpenMoko, Inc. + * Copyright 2013 Hans Petter Selasky + * + * Based on existing code of dfu-programmer-0.4 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include "portable.h" +#include "dfu.h" +#include "usb_dfu.h" +#include "dfu_file.h" +#include "dfu_load.h" +#include "dfu_util.h" +#include "dfuse.h" +#include "quirks.h" + +#ifdef HAVE_USBPATH_H +#include +#endif + +/* + * Look for a descriptor in a concatenated descriptor list. Will + * return upon the first match of the given descriptor type. Returns length of + * found descriptor, limited to res_size + */ +static int find_descriptor(const uint8_t *desc_list, int list_len, + uint8_t desc_type, void *res_buf, int res_size) +{ + int p = 0; + + if (list_len < 2) + return (-1); + + while (p + 1 < list_len) { + int desclen; + + desclen = (int) desc_list[p]; + if (desclen == 0) { + warnx("Invalid descriptor list"); + return -1; + } + if (desc_list[p + 1] == desc_type) { + if (desclen > res_size) + desclen = res_size; + if (p + desclen > list_len) + desclen = list_len - p; + memcpy(res_buf, &desc_list[p], desclen); + return desclen; + } + p += (int) desc_list[p]; + } + return -1; +} + +static void probe_configuration(libusb_device *dev, struct libusb_device_descriptor *desc) +{ + struct usb_dfu_func_descriptor func_dfu; + libusb_device_handle *devh; + struct dfu_if *pdfu; + struct libusb_config_descriptor *cfg; + const struct libusb_interface_descriptor *intf; + const struct libusb_interface *uif; + char alt_name[MAX_DESC_STR_LEN + 1]; + char serial_name[MAX_DESC_STR_LEN + 1]; + int cfg_idx; + int intf_idx; + int alt_idx; + int ret; + int has_dfu; + + for (cfg_idx = 0; cfg_idx != desc->bNumConfigurations; cfg_idx++) { + memset(&func_dfu, 0, sizeof(func_dfu)); + has_dfu = 0; + + ret = libusb_get_config_descriptor(dev, cfg_idx, &cfg); + if (ret != 0) + return; + if (match_config_index > -1 && match_config_index != cfg->bConfigurationValue) { + libusb_free_config_descriptor(cfg); + continue; + } + + /* + * In some cases, noticably FreeBSD if uid != 0, + * the configuration descriptors are empty + */ + if (!cfg) + return; + + ret = find_descriptor(cfg->extra, cfg->extra_length, + USB_DT_DFU, &func_dfu, sizeof(func_dfu)); + if (ret > -1) + goto found_dfu; + + for (intf_idx = 0; intf_idx < cfg->bNumInterfaces; + intf_idx++) { + uif = &cfg->interface[intf_idx]; + if (!uif) + break; + + for (alt_idx = 0; alt_idx < cfg->interface[intf_idx].num_altsetting; + alt_idx++) { + intf = &uif->altsetting[alt_idx]; + + ret = find_descriptor(intf->extra, intf->extra_length, USB_DT_DFU, + &func_dfu, sizeof(func_dfu)); + if (ret > -1) + goto found_dfu; + + if (intf->bInterfaceClass != 0xfe || + intf->bInterfaceSubClass != 1) + continue; + + has_dfu = 1; + } + } + if (has_dfu) { + /* + * Finally try to retrieve it requesting the + * device directly This is not supported on + * all devices for non-standard types + */ + if (libusb_open(dev, &devh) == 0) { + ret = libusb_get_descriptor(devh, USB_DT_DFU, 0, + (void *)&func_dfu, sizeof(func_dfu)); + libusb_close(devh); + if (ret > -1) + goto found_dfu; + } + warnx("Device has DFU interface, " + "but has no DFU functional descriptor"); + + /* fake version 1.0 */ + func_dfu.bLength = 7; + func_dfu.bcdDFUVersion = libusb_cpu_to_le16(0x0100); + goto found_dfu; + } + libusb_free_config_descriptor(cfg); + continue; + +found_dfu: + if (func_dfu.bLength == 7) { + printf("Deducing device DFU version from functional descriptor " + "length\n"); + func_dfu.bcdDFUVersion = libusb_cpu_to_le16(0x0100); + } else if (func_dfu.bLength < 9) { + printf("Error obtaining DFU functional descriptor\n"); + printf("Please report this as a bug!\n"); + printf("Warning: Assuming DFU version 1.0\n"); + func_dfu.bcdDFUVersion = libusb_cpu_to_le16(0x0100); + printf("Warning: Transfer size can not be detected\n"); + func_dfu.wTransferSize = 0; + } + + for (intf_idx = 0; intf_idx < cfg->bNumInterfaces; + intf_idx++) { + if (match_iface_index > -1 && match_iface_index != intf_idx) + continue; + + uif = &cfg->interface[intf_idx]; + if (!uif) + break; + + for (alt_idx = 0; + alt_idx < uif->num_altsetting; alt_idx++) { + int dfu_mode; + + intf = &uif->altsetting[alt_idx]; + + if (intf->bInterfaceClass != 0xfe || + intf->bInterfaceSubClass != 1) + continue; + + dfu_mode = (intf->bInterfaceProtocol == 2); + /* e.g. DSO Nano has bInterfaceProtocol 0 instead of 2 */ + if (func_dfu.bcdDFUVersion == 0x011a && intf->bInterfaceProtocol == 0) + dfu_mode = 1; + + if (dfu_mode && + match_iface_alt_index > -1 && match_iface_alt_index != alt_idx) + continue; + + if (dfu_mode) { + if ((match_vendor_dfu >= 0 && match_vendor_dfu != desc->idVendor) || + (match_product_dfu >= 0 && match_product_dfu != desc->idProduct)) { + continue; + } + } else { + if ((match_vendor >= 0 && match_vendor != desc->idVendor) || + (match_product >= 0 && match_product != desc->idProduct)) { + continue; + } + } + + if (libusb_open(dev, &devh)) { + warnx("Cannot open DFU device %04x:%04x", desc->idVendor, desc->idProduct); + break; + } + if (intf->iInterface != 0) + ret = libusb_get_string_descriptor_ascii(devh, + intf->iInterface, (void *)alt_name, MAX_DESC_STR_LEN); + else + ret = -1; + if (ret < 1) + strcpy(alt_name, "UNKNOWN"); + if (desc->iSerialNumber != 0) + ret = libusb_get_string_descriptor_ascii(devh, + desc->iSerialNumber, (void *)serial_name, MAX_DESC_STR_LEN); + else + ret = -1; + if (ret < 1) + strcpy(serial_name, "UNKNOWN"); + libusb_close(devh); + + if (dfu_mode && + match_iface_alt_name != NULL && strcmp(alt_name, match_iface_alt_name)) + continue; + + if (dfu_mode) { + if (match_serial_dfu != NULL && strcmp(match_serial_dfu, serial_name)) + continue; + } else { + if (match_serial != NULL && strcmp(match_serial, serial_name)) + continue; + } + + pdfu = dfu_malloc(sizeof(*pdfu)); + + memset(pdfu, 0, sizeof(*pdfu)); + + pdfu->func_dfu = func_dfu; + pdfu->dev = libusb_ref_device(dev); + pdfu->quirks = get_quirks(desc->idVendor, + desc->idProduct, desc->bcdDevice); + pdfu->vendor = desc->idVendor; + pdfu->product = desc->idProduct; + pdfu->bcdDevice = desc->bcdDevice; + pdfu->configuration = cfg->bConfigurationValue; + pdfu->interface = intf->bInterfaceNumber; + pdfu->altsetting = intf->bAlternateSetting; + pdfu->devnum = libusb_get_device_address(dev); + pdfu->busnum = libusb_get_bus_number(dev); + pdfu->alt_name = strdup(alt_name); + if (pdfu->alt_name == NULL) + errx(EX_SOFTWARE, "Out of memory"); + pdfu->serial_name = strdup(serial_name); + if (pdfu->serial_name == NULL) + errx(EX_SOFTWARE, "Out of memory"); + if (dfu_mode) + pdfu->flags |= DFU_IFF_DFU; + if (pdfu->quirks & QUIRK_FORCE_DFU11) { + pdfu->func_dfu.bcdDFUVersion = + libusb_cpu_to_le16(0x0110); + } + pdfu->bMaxPacketSize0 = desc->bMaxPacketSize0; + + /* queue into list */ + pdfu->next = dfu_root; + dfu_root = pdfu; + } + } + libusb_free_config_descriptor(cfg); + } +} + +void probe_devices(libusb_context *ctx) +{ + libusb_device **list; + ssize_t num_devs; + ssize_t i; + + num_devs = libusb_get_device_list(ctx, &list); + for (i = 0; i < num_devs; ++i) { + struct libusb_device_descriptor desc; + struct libusb_device *dev = list[i]; + + if (match_bus > -1 && match_bus != libusb_get_bus_number(dev)) + continue; + if (match_device > -1 && match_device != libusb_get_device_address(dev)) + continue; + if (libusb_get_device_descriptor(dev, &desc)) + continue; + probe_configuration(dev, &desc); + } + libusb_free_device_list(list, 0); +} + +void disconnect_devices(void) +{ + struct dfu_if *pdfu; + struct dfu_if *prev = NULL; + + for (pdfu = dfu_root; pdfu != NULL; pdfu = pdfu->next) { + free(prev); + libusb_unref_device(pdfu->dev); + free(pdfu->alt_name); + free(pdfu->serial_name); + prev = pdfu; + } + free(prev); + dfu_root = NULL; +} + +void print_dfu_if(struct dfu_if *dfu_if) +{ + printf("Found %s: [%04x:%04x] ver=%04x, devnum=%u, cfg=%u, intf=%u, " + "alt=%u, name=\"%s\", serial=\"%s\"\n", + dfu_if->flags & DFU_IFF_DFU ? "DFU" : "Runtime", + dfu_if->vendor, dfu_if->product, + dfu_if->bcdDevice, dfu_if->devnum, + dfu_if->configuration, dfu_if->interface, + dfu_if->altsetting, dfu_if->alt_name, + dfu_if->serial_name); +} + +/* Walk the device tree and print out DFU devices */ +void list_dfu_interfaces(void) +{ + struct dfu_if *pdfu; + + for (pdfu = dfu_root; pdfu != NULL; pdfu = pdfu->next) + print_dfu_if(pdfu); +} diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfu_util.h b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfu_util.h new file mode 100644 index 0000000..fc0c19d --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfu_util.h @@ -0,0 +1,36 @@ +#ifndef DFU_UTIL_H +#define DFU_UTIL_H + +/* USB string descriptor should contain max 126 UTF-16 characters + * but 253 would even accomodate any UTF-8 encoding */ +#define MAX_DESC_STR_LEN 253 + +enum mode { + MODE_NONE, + MODE_VERSION, + MODE_LIST, + MODE_DETACH, + MODE_UPLOAD, + MODE_DOWNLOAD +}; + +extern struct dfu_if *dfu_root; +extern int match_bus; +extern int match_device; +extern int match_vendor; +extern int match_product; +extern int match_vendor_dfu; +extern int match_product_dfu; +extern int match_config_index; +extern int match_iface_index; +extern int match_iface_alt_index; +extern const char *match_iface_alt_name; +extern const char *match_serial; +extern const char *match_serial_dfu; + +void probe_devices(libusb_context *); +void disconnect_devices(void); +void print_dfu_if(struct dfu_if *); +void list_dfu_interfaces(void); + +#endif /* DFU_UTIL_H */ diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfuse.c b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfuse.c new file mode 100644 index 0000000..fce29fe --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfuse.c @@ -0,0 +1,652 @@ +/* + * DfuSe specific functions + * + * This implements the ST Microsystems DFU extensions (DfuSe) + * as per the DfuSe 1.1a specification (ST documents AN3156, AN2606) + * The DfuSe file format is described in ST document UM0391. + * + * Copyright 2010-2014 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "portable.h" +#include "dfu.h" +#include "usb_dfu.h" +#include "dfu_file.h" +#include "dfuse.h" +#include "dfuse_mem.h" + +#define DFU_TIMEOUT 5000 + +extern int verbose; +static unsigned int last_erased_page = 1; /* non-aligned value, won't match */ +static struct memsegment *mem_layout; +static unsigned int dfuse_address = 0; +static unsigned int dfuse_length = 0; +static int dfuse_force = 0; +static int dfuse_leave = 0; +static int dfuse_unprotect = 0; +static int dfuse_mass_erase = 0; + +unsigned int quad2uint(unsigned char *p) +{ + return (*p + (*(p + 1) << 8) + (*(p + 2) << 16) + (*(p + 3) << 24)); +} + +void dfuse_parse_options(const char *options) +{ + char *end; + const char *endword; + unsigned int number; + + /* address, possibly empty, must be first */ + if (*options != ':') { + endword = strchr(options, ':'); + if (!endword) + endword = options + strlen(options); /* GNU strchrnul */ + + number = strtoul(options, &end, 0); + if (end == endword) { + dfuse_address = number; + } else { + errx(EX_IOERR, "Invalid dfuse address: %s", options); + } + options = endword; + } + + while (*options) { + if (*options == ':') { + options++; + continue; + } + endword = strchr(options, ':'); + if (!endword) + endword = options + strlen(options); + + if (!strncmp(options, "force", endword - options)) { + dfuse_force++; + options += 5; + continue; + } + if (!strncmp(options, "leave", endword - options)) { + dfuse_leave = 1; + options += 5; + continue; + } + if (!strncmp(options, "unprotect", endword - options)) { + dfuse_unprotect = 1; + options += 9; + continue; + } + if (!strncmp(options, "mass-erase", endword - options)) { + dfuse_mass_erase = 1; + options += 10; + continue; + } + + /* any valid number is interpreted as upload length */ + number = strtoul(options, &end, 0); + if (end == endword) { + dfuse_length = number; + } else { + errx(EX_IOERR, "Invalid dfuse modifier: %s", options); + } + options = endword; + } +} + +/* DFU_UPLOAD request for DfuSe 1.1a */ +int dfuse_upload(struct dfu_if *dif, const unsigned short length, + unsigned char *data, unsigned short transaction) +{ + int status; + + status = libusb_control_transfer(dif->dev_handle, + /* bmRequestType */ LIBUSB_ENDPOINT_IN | + LIBUSB_REQUEST_TYPE_CLASS | + LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_UPLOAD, + /* wValue */ transaction, + /* wIndex */ dif->interface, + /* Data */ data, + /* wLength */ length, + DFU_TIMEOUT); + if (status < 0) { + errx(EX_IOERR, "%s: libusb_control_msg returned %d", + __FUNCTION__, status); + } + return status; +} + +/* DFU_DNLOAD request for DfuSe 1.1a */ +int dfuse_download(struct dfu_if *dif, const unsigned short length, + unsigned char *data, unsigned short transaction) +{ + int status; + + status = libusb_control_transfer(dif->dev_handle, + /* bmRequestType */ LIBUSB_ENDPOINT_OUT | + LIBUSB_REQUEST_TYPE_CLASS | + LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_DNLOAD, + /* wValue */ transaction, + /* wIndex */ dif->interface, + /* Data */ data, + /* wLength */ length, + DFU_TIMEOUT); + if (status < 0) { + errx(EX_IOERR, "%s: libusb_control_transfer returned %d", + __FUNCTION__, status); + } + return status; +} + +/* DfuSe only commands */ +/* Leaves the device in dfuDNLOAD-IDLE state */ +int dfuse_special_command(struct dfu_if *dif, unsigned int address, + enum dfuse_command command) +{ + const char* dfuse_command_name[] = { "SET_ADDRESS" , "ERASE_PAGE", + "MASS_ERASE", "READ_UNPROTECT"}; + unsigned char buf[5]; + int length; + int ret; + struct dfu_status dst; + int firstpoll = 1; + + if (command == ERASE_PAGE) { + struct memsegment *segment; + int page_size; + + segment = find_segment(mem_layout, address); + if (!segment || !(segment->memtype & DFUSE_ERASABLE)) { + errx(EX_IOERR, "Page at 0x%08x can not be erased", + address); + } + page_size = segment->pagesize; + if (verbose > 1) + printf("Erasing page size %i at address 0x%08x, page " + "starting at 0x%08x\n", page_size, address, + address & ~(page_size - 1)); + buf[0] = 0x41; /* Erase command */ + length = 5; + last_erased_page = address & ~(page_size - 1); + } else if (command == SET_ADDRESS) { + if (verbose > 2) + printf(" Setting address pointer to 0x%08x\n", + address); + buf[0] = 0x21; /* Set Address Pointer command */ + length = 5; + } else if (command == MASS_ERASE) { + buf[0] = 0x41; /* Mass erase command when length = 1 */ + length = 1; + } else if (command == READ_UNPROTECT) { + buf[0] = 0x92; + length = 1; + } else { + errx(EX_IOERR, "Non-supported special command %d", command); + } + buf[1] = address & 0xff; + buf[2] = (address >> 8) & 0xff; + buf[3] = (address >> 16) & 0xff; + buf[4] = (address >> 24) & 0xff; + + ret = dfuse_download(dif, length, buf, 0); + if (ret < 0) { + errx(EX_IOERR, "Error during special command \"%s\" download", + dfuse_command_name[command]); + } + do { + ret = dfu_get_status(dif, &dst); + if (ret < 0) { + errx(EX_IOERR, "Error during special command \"%s\" get_status", + dfuse_command_name[command]); + } + if (firstpoll) { + firstpoll = 0; + if (dst.bState != DFU_STATE_dfuDNBUSY) { + printf("state(%u) = %s, status(%u) = %s\n", dst.bState, + dfu_state_to_string(dst.bState), dst.bStatus, + dfu_status_to_string(dst.bStatus)); + errx(EX_IOERR, "Wrong state after command \"%s\" download", + dfuse_command_name[command]); + } + } + /* wait while command is executed */ + if (verbose) + printf(" Poll timeout %i ms\n", dst.bwPollTimeout); + milli_sleep(dst.bwPollTimeout); + if (command == READ_UNPROTECT) + return ret; + } while (dst.bState == DFU_STATE_dfuDNBUSY); + + if (dst.bStatus != DFU_STATUS_OK) { + errx(EX_IOERR, "%s not correctly executed", + dfuse_command_name[command]); + } + return ret; +} + +int dfuse_dnload_chunk(struct dfu_if *dif, unsigned char *data, int size, + int transaction) +{ + int bytes_sent; + struct dfu_status dst; + int ret; + + ret = dfuse_download(dif, size, size ? data : NULL, transaction); + if (ret < 0) { + errx(EX_IOERR, "Error during download"); + return ret; + } + bytes_sent = ret; + + do { + ret = dfu_get_status(dif, &dst); + if (ret < 0) { + errx(EX_IOERR, "Error during download get_status"); + return ret; + } + milli_sleep(dst.bwPollTimeout); + } while (dst.bState != DFU_STATE_dfuDNLOAD_IDLE && + dst.bState != DFU_STATE_dfuERROR && + dst.bState != DFU_STATE_dfuMANIFEST); + + if (dst.bState == DFU_STATE_dfuMANIFEST) + printf("Transitioning to dfuMANIFEST state\n"); + + if (dst.bStatus != DFU_STATUS_OK) { + printf(" failed!\n"); + printf("state(%u) = %s, status(%u) = %s\n", dst.bState, + dfu_state_to_string(dst.bState), dst.bStatus, + dfu_status_to_string(dst.bStatus)); + return -1; + } + return bytes_sent; +} + +int dfuse_do_upload(struct dfu_if *dif, int xfer_size, int fd, + const char *dfuse_options) +{ + int total_bytes = 0; + int upload_limit = 0; + unsigned char *buf; + int transaction; + int ret; + + buf = dfu_malloc(xfer_size); + + if (dfuse_options) + dfuse_parse_options(dfuse_options); + if (dfuse_length) + upload_limit = dfuse_length; + if (dfuse_address) { + struct memsegment *segment; + + mem_layout = parse_memory_layout((char *)dif->alt_name); + if (!mem_layout) + errx(EX_IOERR, "Failed to parse memory layout"); + + segment = find_segment(mem_layout, dfuse_address); + if (!dfuse_force && + (!segment || !(segment->memtype & DFUSE_READABLE))) + errx(EX_IOERR, "Page at 0x%08x is not readable", + dfuse_address); + + if (!upload_limit) { + upload_limit = segment->end - dfuse_address + 1; + printf("Limiting upload to end of memory segment, " + "%i bytes\n", upload_limit); + } + dfuse_special_command(dif, dfuse_address, SET_ADDRESS); + dfu_abort_to_idle(dif); + } else { + /* Boot loader decides the start address, unknown to us */ + /* Use a short length to lower risk of running out of bounds */ + if (!upload_limit) + upload_limit = 0x4000; + printf("Limiting default upload to %i bytes\n", upload_limit); + } + + dfu_progress_bar("Upload", 0, 1); + + transaction = 2; + while (1) { + int rc; + + /* last chunk can be smaller than original xfer_size */ + if (upload_limit - total_bytes < xfer_size) + xfer_size = upload_limit - total_bytes; + rc = dfuse_upload(dif, xfer_size, buf, transaction++); + if (rc < 0) { + ret = rc; + goto out_free; + } + + dfu_file_write_crc(fd, 0, buf, rc); + total_bytes += rc; + + if (total_bytes < 0) + errx(EX_SOFTWARE, "Received too many bytes"); + + if (rc < xfer_size || total_bytes >= upload_limit) { + /* last block, return successfully */ + ret = total_bytes; + break; + } + dfu_progress_bar("Upload", total_bytes, upload_limit); + } + + dfu_progress_bar("Upload", total_bytes, total_bytes); + + dfu_abort_to_idle(dif); + if (dfuse_leave) { + dfuse_special_command(dif, dfuse_address, SET_ADDRESS); + dfuse_dnload_chunk(dif, NULL, 0, 2); /* Zero-size */ + } + + out_free: + free(buf); + + return ret; +} + +/* Writes an element of any size to the device, taking care of page erases */ +/* returns 0 on success, otherwise -EINVAL */ +int dfuse_dnload_element(struct dfu_if *dif, unsigned int dwElementAddress, + unsigned int dwElementSize, unsigned char *data, + int xfer_size) +{ + int p; + int ret; + struct memsegment *segment; + + /* Check at least that we can write to the last address */ + segment = + find_segment(mem_layout, dwElementAddress + dwElementSize - 1); + if (!segment || !(segment->memtype & DFUSE_WRITEABLE)) { + errx(EX_IOERR, "Last page at 0x%08x is not writeable", + dwElementAddress + dwElementSize - 1); + } + + dfu_progress_bar("Download", 0, 1); + + for (p = 0; p < (int)dwElementSize; p += xfer_size) { + int page_size; + unsigned int erase_address; + unsigned int address = dwElementAddress + p; + int chunk_size = xfer_size; + + segment = find_segment(mem_layout, address); + if (!segment || !(segment->memtype & DFUSE_WRITEABLE)) { + errx(EX_IOERR, "Page at 0x%08x is not writeable", + address); + } + page_size = segment->pagesize; + + /* check if this is the last chunk */ + if (p + chunk_size > (int)dwElementSize) + chunk_size = dwElementSize - p; + + /* Erase only for flash memory downloads */ + if ((segment->memtype & DFUSE_ERASABLE) && !dfuse_mass_erase) { + /* erase all involved pages */ + for (erase_address = address; + erase_address < address + chunk_size; + erase_address += page_size) + if ((erase_address & ~(page_size - 1)) != + last_erased_page) + dfuse_special_command(dif, + erase_address, + ERASE_PAGE); + + if (((address + chunk_size - 1) & ~(page_size - 1)) != + last_erased_page) { + if (verbose > 2) + printf(" Chunk extends into next page," + " erase it as well\n"); + dfuse_special_command(dif, + address + chunk_size - 1, + ERASE_PAGE); + } + } + + if (verbose) { + printf(" Download from image offset " + "%08x to memory %08x-%08x, size %i\n", + p, address, address + chunk_size - 1, + chunk_size); + } else { + dfu_progress_bar("Download", p, dwElementSize); + } + + dfuse_special_command(dif, address, SET_ADDRESS); + + /* transaction = 2 for no address offset */ + ret = dfuse_dnload_chunk(dif, data + p, chunk_size, 2); + if (ret != chunk_size) { + errx(EX_IOERR, "Failed to write whole chunk: " + "%i of %i bytes", ret, chunk_size); + return -EINVAL; + } + } + if (!verbose) + dfu_progress_bar("Download", dwElementSize, dwElementSize); + return 0; +} + +static void +dfuse_memcpy(unsigned char *dst, unsigned char **src, int *rem, int size) +{ + if (size > *rem) { + errx(EX_IOERR, "Corrupt DfuSe file: " + "Cannot read %d bytes from %d bytes", size, *rem); + } + if (dst != NULL) + memcpy(dst, *src, size); + (*src) += size; + (*rem) -= size; +} + +/* Download raw binary file to DfuSe device */ +int dfuse_do_bin_dnload(struct dfu_if *dif, int xfer_size, + struct dfu_file *file, unsigned int start_address) +{ + unsigned int dwElementAddress; + unsigned int dwElementSize; + unsigned char *data; + int ret; + + dwElementAddress = start_address; + dwElementSize = file->size.total - + file->size.suffix - file->size.prefix; + + printf("Downloading to address = 0x%08x, size = %i\n", + dwElementAddress, dwElementSize); + + data = file->firmware + file->size.prefix; + + ret = dfuse_dnload_element(dif, dwElementAddress, dwElementSize, data, + xfer_size); + if (ret != 0) + goto out_free; + + printf("File downloaded successfully\n"); + ret = dwElementSize; + + out_free: + return ret; +} + +/* Parse a DfuSe file and download contents to device */ +int dfuse_do_dfuse_dnload(struct dfu_if *dif, int xfer_size, + struct dfu_file *file) +{ + uint8_t dfuprefix[11]; + uint8_t targetprefix[274]; + uint8_t elementheader[8]; + int image; + int element; + int bTargets; + int bAlternateSetting; + int dwNbElements; + unsigned int dwElementAddress; + unsigned int dwElementSize; + uint8_t *data; + int ret; + int rem; + int bFirstAddressSaved = 0; + + rem = file->size.total - file->size.prefix - file->size.suffix; + data = file->firmware + file->size.prefix; + + /* Must be larger than a minimal DfuSe header and suffix */ + if (rem < (int)(sizeof(dfuprefix) + + sizeof(targetprefix) + sizeof(elementheader))) { + errx(EX_SOFTWARE, "File too small for a DfuSe file"); + } + + dfuse_memcpy(dfuprefix, &data, &rem, sizeof(dfuprefix)); + + if (strncmp((char *)dfuprefix, "DfuSe", 5)) { + errx(EX_IOERR, "No valid DfuSe signature"); + return -EINVAL; + } + if (dfuprefix[5] != 0x01) { + errx(EX_IOERR, "DFU format revision %i not supported", + dfuprefix[5]); + return -EINVAL; + } + bTargets = dfuprefix[10]; + printf("file contains %i DFU images\n", bTargets); + + for (image = 1; image <= bTargets; image++) { + printf("parsing DFU image %i\n", image); + dfuse_memcpy(targetprefix, &data, &rem, sizeof(targetprefix)); + if (strncmp((char *)targetprefix, "Target", 6)) { + errx(EX_IOERR, "No valid target signature"); + return -EINVAL; + } + bAlternateSetting = targetprefix[6]; + dwNbElements = quad2uint((unsigned char *)targetprefix + 270); + printf("image for alternate setting %i, ", bAlternateSetting); + printf("(%i elements, ", dwNbElements); + printf("total size = %i)\n", + quad2uint((unsigned char *)targetprefix + 266)); + if (bAlternateSetting != dif->altsetting) + printf("Warning: Image does not match current alternate" + " setting.\n" + "Please rerun with the correct -a option setting" + " to download this image!\n"); + for (element = 1; element <= dwNbElements; element++) { + printf("parsing element %i, ", element); + dfuse_memcpy(elementheader, &data, &rem, sizeof(elementheader)); + dwElementAddress = + quad2uint((unsigned char *)elementheader); + dwElementSize = + quad2uint((unsigned char *)elementheader + 4); + printf("address = 0x%08x, ", dwElementAddress); + printf("size = %i\n", dwElementSize); + + if (!bFirstAddressSaved) { + bFirstAddressSaved = 1; + dfuse_address = dwElementAddress; + } + /* sanity check */ + if ((int)dwElementSize > rem) + errx(EX_SOFTWARE, "File too small for element size"); + + if (bAlternateSetting == dif->altsetting) { + ret = dfuse_dnload_element(dif, dwElementAddress, + dwElementSize, data, xfer_size); + } else { + ret = 0; + } + + /* advance read pointer */ + dfuse_memcpy(NULL, &data, &rem, dwElementSize); + + if (ret != 0) + return ret; + } + } + + if (rem != 0) + warnx("%d bytes leftover", rem); + + printf("done parsing DfuSe file\n"); + + return 0; +} + +int dfuse_do_dnload(struct dfu_if *dif, int xfer_size, struct dfu_file *file, + const char *dfuse_options) +{ + int ret; + + if (dfuse_options) + dfuse_parse_options(dfuse_options); + mem_layout = parse_memory_layout((char *)dif->alt_name); + if (!mem_layout) { + errx(EX_IOERR, "Failed to parse memory layout"); + } + if (dfuse_unprotect) { + if (!dfuse_force) { + errx(EX_IOERR, "The read unprotect command " + "will erase the flash memory" + "and can only be used with force\n"); + } + dfuse_special_command(dif, 0, READ_UNPROTECT); + printf("Device disconnects, erases flash and resets now\n"); + exit(0); + } + if (dfuse_mass_erase) { + if (!dfuse_force) { + errx(EX_IOERR, "The mass erase command " + "can only be used with force"); + } + printf("Performing mass erase, this can take a moment\n"); + dfuse_special_command(dif, 0, MASS_ERASE); + } + if (dfuse_address) { + if (file->bcdDFU == 0x11a) { + errx(EX_IOERR, "This is a DfuSe file, not " + "meant for raw download"); + } + ret = dfuse_do_bin_dnload(dif, xfer_size, file, dfuse_address); + } else { + if (file->bcdDFU != 0x11a) { + warnx("Only DfuSe file version 1.1a is supported"); + errx(EX_IOERR, "(for raw binary download, use the " + "--dfuse-address option)"); + } + ret = dfuse_do_dfuse_dnload(dif, xfer_size, file); + } + free_segment_list(mem_layout); + + dfu_abort_to_idle(dif); + + if (dfuse_leave) { + dfuse_special_command(dif, dfuse_address, SET_ADDRESS); + dfuse_dnload_chunk(dif, NULL, 0, 2); /* Zero-size */ + } + return ret; +} diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfuse.h b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfuse.h new file mode 100644 index 0000000..ed1108c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfuse.h @@ -0,0 +1,35 @@ +/* This implements the ST Microsystems DFU extensions (DfuSe) + * as per the DfuSe 1.1a specification (Document UM0391) + * + * (C) 2010-2012 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DFUSE_H +#define DFUSE_H + +#include "dfu.h" + +enum dfuse_command { SET_ADDRESS, ERASE_PAGE, MASS_ERASE, READ_UNPROTECT }; + +int dfuse_special_command(struct dfu_if *dif, unsigned int address, + enum dfuse_command command); +int dfuse_do_upload(struct dfu_if *dif, int xfer_size, int fd, + const char *dfuse_options); +int dfuse_do_dnload(struct dfu_if *dif, int xfer_size, struct dfu_file *file, + const char *dfuse_options); + +#endif /* DFUSE_H */ diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfuse_mem.c b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfuse_mem.c new file mode 100644 index 0000000..a91aacf --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfuse_mem.c @@ -0,0 +1,198 @@ +/* + * Helper functions for reading the memory map of a device + * following the ST DfuSe 1.1a specification. + * + * Copyright 2011-2014 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "portable.h" +#include "dfu_file.h" +#include "dfuse_mem.h" + +int add_segment(struct memsegment **segment_list, struct memsegment segment) +{ + struct memsegment *new_element; + + new_element = dfu_malloc(sizeof(struct memsegment)); + *new_element = segment; + new_element->next = NULL; + + if (*segment_list == NULL) + /* list can be empty on first call */ + *segment_list = new_element; + else { + struct memsegment *next_element; + + /* find last element in list */ + next_element = *segment_list; + while (next_element->next != NULL) + next_element = next_element->next; + next_element->next = new_element; + } + return 0; +} + +struct memsegment *find_segment(struct memsegment *segment_list, + unsigned int address) +{ + while (segment_list != NULL) { + if (segment_list->start <= address && + segment_list->end >= address) + return segment_list; + segment_list = segment_list->next; + } + return NULL; +} + +void free_segment_list(struct memsegment *segment_list) +{ + struct memsegment *next_element; + + while (segment_list->next != NULL) { + next_element = segment_list->next; + free(segment_list); + segment_list = next_element; + } + free(segment_list); +} + +/* Parse memory map from interface descriptor string + * encoded as per ST document UM0424 section 4.3.2. + */ +struct memsegment *parse_memory_layout(char *intf_desc) +{ + + char multiplier, memtype; + unsigned int address; + int sectors, size; + char *name, *typestring; + int ret; + int count = 0; + char separator; + int scanned; + struct memsegment *segment_list = NULL; + struct memsegment segment; + + name = dfu_malloc(strlen(intf_desc)); + + ret = sscanf(intf_desc, "@%[^/]%n", name, &scanned); + if (ret < 1) { + free(name); + warnx("Could not read name, sscanf returned %d", ret); + return NULL; + } + printf("DfuSe interface name: \"%s\"\n", name); + + intf_desc += scanned; + typestring = dfu_malloc(strlen(intf_desc)); + + while (ret = sscanf(intf_desc, "/0x%x/%n", &address, &scanned), + ret > 0) { + + intf_desc += scanned; + while (ret = sscanf(intf_desc, "%d*%d%c%[^,/]%n", + §ors, &size, &multiplier, typestring, + &scanned), ret > 2) { + intf_desc += scanned; + + count++; + memtype = 0; + if (ret == 4) { + if (strlen(typestring) == 1 + && typestring[0] != '/') + memtype = typestring[0]; + else { + warnx("Parsing type identifier '%s' " + "failed for segment %i", + typestring, count); + continue; + } + } + + /* Quirk for STM32F4 devices */ + if (strcmp(name, "Device Feature") == 0) + memtype = 'e'; + + switch (multiplier) { + case 'B': + break; + case 'K': + size *= 1024; + break; + case 'M': + size *= 1024 * 1024; + break; + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + if (!memtype) { + warnx("Non-valid multiplier '%c', " + "interpreted as type " + "identifier instead", + multiplier); + memtype = multiplier; + break; + } + /* fallthrough if memtype was already set */ + default: + warnx("Non-valid multiplier '%c', " + "assuming bytes", multiplier); + } + + if (!memtype) { + warnx("No valid type for segment %d\n", count); + continue; + } + + segment.start = address; + segment.end = address + sectors * size - 1; + segment.pagesize = size; + segment.memtype = memtype & 7; + add_segment(&segment_list, segment); + + if (verbose) + printf("Memory segment at 0x%08x %3d x %4d = " + "%5d (%s%s%s)\n", + address, sectors, size, sectors * size, + memtype & DFUSE_READABLE ? "r" : "", + memtype & DFUSE_ERASABLE ? "e" : "", + memtype & DFUSE_WRITEABLE ? "w" : ""); + + address += sectors * size; + + separator = *intf_desc; + if (separator == ',') + intf_desc += 1; + else + break; + } /* while per segment */ + + } /* while per address */ + free(name); + free(typestring); + + return segment_list; +} diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfuse_mem.h b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfuse_mem.h new file mode 100644 index 0000000..0181f0c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/dfuse_mem.h @@ -0,0 +1,44 @@ +/* Helper functions for reading the memory map in a device + * following the ST DfuSe 1.1a specification. + * + * (C) 2011 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DFUSE_MEM_H +#define DFUSE_MEM_H + +#define DFUSE_READABLE 1 +#define DFUSE_ERASABLE 2 +#define DFUSE_WRITEABLE 4 + +struct memsegment { + unsigned int start; + unsigned int end; + int pagesize; + int memtype; + struct memsegment *next; +}; + +int add_segment(struct memsegment **list, struct memsegment new_element); + +struct memsegment *find_segment(struct memsegment *list, unsigned int address); + +void free_segment_list(struct memsegment *list); + +struct memsegment *parse_memory_layout(char *intf_desc_str); + +#endif /* DFUSE_MEM_H */ diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/main.c b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/main.c new file mode 100644 index 0000000..acaed2f --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/main.c @@ -0,0 +1,699 @@ +/* + * dfu-util + * + * Copyright 2007-2008 by OpenMoko, Inc. + * Copyright 2013-2014 Hans Petter Selasky + * + * Written by Harald Welte + * + * Based on existing code of dfu-programmer-0.4 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "portable.h" +#include "dfu.h" +#include "usb_dfu.h" +#include "dfu_file.h" +#include "dfu_load.h" +#include "dfu_util.h" +#include "dfuse.h" +#include "quirks.h" + +#ifdef HAVE_USBPATH_H +#include +#endif + +int verbose = 0; + +struct dfu_if *dfu_root = NULL; + +int match_bus = -1; +int match_device = -1; +int match_vendor = -1; +int match_product = -1; +int match_vendor_dfu = -1; +int match_product_dfu = -1; +int match_config_index = -1; +int match_iface_index = -1; +int match_iface_alt_index = -1; +const char *match_iface_alt_name = NULL; +const char *match_serial = NULL; +const char *match_serial_dfu = NULL; + +static int parse_match_value(const char *str, int default_value) +{ + char *remainder; + int value; + + if (str == NULL) { + value = default_value; + } else if (*str == '*') { + value = -1; /* Match anything */ + } else if (*str == '-') { + value = 0x10000; /* Impossible vendor/product ID */ + } else { + value = strtoul(str, &remainder, 16); + if (remainder == str) { + value = default_value; + } + } + return value; +} + +static void parse_vendprod(const char *str) +{ + const char *comma; + const char *colon; + + /* Default to match any DFU device in runtime or DFU mode */ + match_vendor = -1; + match_product = -1; + match_vendor_dfu = -1; + match_product_dfu = -1; + + comma = strchr(str, ','); + if (comma == str) { + /* DFU mode vendor/product being specified without any runtime + * vendor/product specification, so don't match any runtime device */ + match_vendor = match_product = 0x10000; + } else { + colon = strchr(str, ':'); + if (colon != NULL) { + ++colon; + if ((comma != NULL) && (colon > comma)) { + colon = NULL; + } + } + match_vendor = parse_match_value(str, match_vendor); + match_product = parse_match_value(colon, match_product); + if (comma != NULL) { + /* Both runtime and DFU mode vendor/product specifications are + * available, so default DFU mode match components to the given + * runtime match components */ + match_vendor_dfu = match_vendor; + match_product_dfu = match_product; + } + } + if (comma != NULL) { + ++comma; + colon = strchr(comma, ':'); + if (colon != NULL) { + ++colon; + } + match_vendor_dfu = parse_match_value(comma, match_vendor_dfu); + match_product_dfu = parse_match_value(colon, match_product_dfu); + } +} + +static void parse_serial(char *str) +{ + char *comma; + + match_serial = str; + comma = strchr(str, ','); + if (comma == NULL) { + match_serial_dfu = match_serial; + } else { + *comma++ = 0; + match_serial_dfu = comma; + } + if (*match_serial == 0) match_serial = NULL; + if (*match_serial_dfu == 0) match_serial_dfu = NULL; +} + +#ifdef HAVE_USBPATH_H + +static int resolve_device_path(char *path) +{ + int res; + + res = usb_path2devnum(path); + if (res < 0) + return -EINVAL; + if (!res) + return 0; + + match_bus = atoi(path); + match_device = res; + + return 0; +} + +#else /* HAVE_USBPATH_H */ + +static int resolve_device_path(char *path) +{ + (void)path; /* Eliminate unused variable warning */ + errx(EX_SOFTWARE, "USB device paths are not supported by this dfu-util.\n"); +} + +#endif /* !HAVE_USBPATH_H */ + +static void help(void) +{ + fprintf(stderr, "Usage: dfu-util [options] ...\n" + " -h --help\t\t\tPrint this help message\n" + " -V --version\t\t\tPrint the version number\n" + " -v --verbose\t\t\tPrint verbose debug statements\n" + " -l --list\t\t\tList currently attached DFU capable devices\n"); + fprintf(stderr, " -e --detach\t\t\tDetach currently attached DFU capable devices\n" + " -E --detach-delay seconds\tTime to wait before reopening a device after detach\n" + " -d --device :[,:]\n" + "\t\t\t\tSpecify Vendor/Product ID(s) of DFU device\n" + " -p --path \tSpecify path to DFU device\n" + " -c --cfg \t\tSpecify the Configuration of DFU device\n" + " -i --intf \t\tSpecify the DFU Interface number\n" + " -S --serial [,]\n" + "\t\t\t\tSpecify Serial String of DFU device\n" + " -a --alt \t\tSpecify the Altsetting of the DFU Interface\n" + "\t\t\t\tby name or by number\n"); + fprintf(stderr, " -t --transfer-size \tSpecify the number of bytes per USB Transfer\n" + " -U --upload \t\tRead firmware from device into \n" + " -Z --upload-size \tSpecify the expected upload size in bytes\n" + " -D --download \t\tWrite firmware from into device\n" + " -R --reset\t\t\tIssue USB Reset signalling once we're finished\n" + " -s --dfuse-address

\tST DfuSe mode, specify target address for\n" + "\t\t\t\traw file download or upload. Not applicable for\n" + "\t\t\t\tDfuSe file (.dfu) downloads\n" + ); + exit(EX_USAGE); +} + +static void print_version(void) +{ + printf(PACKAGE_STRING "\n\n"); + printf("Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.\n" + "Copyright 2010-2014 Tormod Volden and Stefan Schmidt\n" + "This program is Free Software and has ABSOLUTELY NO WARRANTY\n" + "Please report bugs to " PACKAGE_BUGREPORT "\n\n"); +} + +static struct option opts[] = { + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'V' }, + { "verbose", 0, 0, 'v' }, + { "list", 0, 0, 'l' }, + { "detach", 0, 0, 'e' }, + { "detach-delay", 1, 0, 'E' }, + { "device", 1, 0, 'd' }, + { "path", 1, 0, 'p' }, + { "configuration", 1, 0, 'c' }, + { "cfg", 1, 0, 'c' }, + { "interface", 1, 0, 'i' }, + { "intf", 1, 0, 'i' }, + { "altsetting", 1, 0, 'a' }, + { "alt", 1, 0, 'a' }, + { "serial", 1, 0, 'S' }, + { "transfer-size", 1, 0, 't' }, + { "upload", 1, 0, 'U' }, + { "upload-size", 1, 0, 'Z' }, + { "download", 1, 0, 'D' }, + { "reset", 0, 0, 'R' }, + { "dfuse-address", 1, 0, 's' }, + { 0, 0, 0, 0 } +}; + +int main(int argc, char **argv) +{ + int expected_size = 0; + unsigned int transfer_size = 0; + enum mode mode = MODE_NONE; + struct dfu_status status; + libusb_context *ctx; + struct dfu_file file; + char *end; + int final_reset = 0; + int ret; + int dfuse_device = 0; + int fd; + const char *dfuse_options = NULL; + int detach_delay = 5; + uint16_t runtime_vendor; + uint16_t runtime_product; + + memset(&file, 0, sizeof(file)); + + /* make sure all prints are flushed */ + setvbuf(stdout, NULL, _IONBF, 0); + + while (1) { + int c, option_index = 0; + c = getopt_long(argc, argv, "hVvleE:d:p:c:i:a:S:t:U:D:Rs:Z:", opts, + &option_index); + if (c == -1) + break; + + switch (c) { + case 'h': + help(); + break; + case 'V': + mode = MODE_VERSION; + break; + case 'v': + verbose++; + break; + case 'l': + mode = MODE_LIST; + break; + case 'e': + mode = MODE_DETACH; + match_iface_alt_index = 0; + match_iface_index = 0; + break; + case 'E': + detach_delay = atoi(optarg); + break; + case 'd': + parse_vendprod(optarg); + break; + case 'p': + /* Parse device path */ + ret = resolve_device_path(optarg); + if (ret < 0) + errx(EX_SOFTWARE, "Unable to parse '%s'", optarg); + if (!ret) + errx(EX_SOFTWARE, "Cannot find '%s'", optarg); + break; + case 'c': + /* Configuration */ + match_config_index = atoi(optarg); + break; + case 'i': + /* Interface */ + match_iface_index = atoi(optarg); + break; + case 'a': + /* Interface Alternate Setting */ + match_iface_alt_index = strtoul(optarg, &end, 0); + if (*end) { + match_iface_alt_name = optarg; + match_iface_alt_index = -1; + } + break; + case 'S': + parse_serial(optarg); + break; + case 't': + transfer_size = atoi(optarg); + break; + case 'U': + mode = MODE_UPLOAD; + file.name = optarg; + break; + case 'Z': + expected_size = atoi(optarg); + break; + case 'D': + mode = MODE_DOWNLOAD; + file.name = optarg; + break; + case 'R': + final_reset = 1; + break; + case 's': + dfuse_options = optarg; + break; + default: + help(); + break; + } + } + + print_version(); + if (mode == MODE_VERSION) { + exit(0); + } + + if (mode == MODE_NONE) { + fprintf(stderr, "You need to specify one of -D or -U\n"); + help(); + } + + if (match_config_index == 0) { + /* Handle "-c 0" (unconfigured device) as don't care */ + match_config_index = -1; + } + + if (mode == MODE_DOWNLOAD) { + dfu_load_file(&file, MAYBE_SUFFIX, MAYBE_PREFIX); + /* If the user didn't specify product and/or vendor IDs to match, + * use any IDs from the file suffix for device matching */ + if (match_vendor < 0 && file.idVendor != 0xffff) { + match_vendor = file.idVendor; + printf("Match vendor ID from file: %04x\n", match_vendor); + } + if (match_product < 0 && file.idProduct != 0xffff) { + match_product = file.idProduct; + printf("Match product ID from file: %04x\n", match_product); + } + } + + ret = libusb_init(&ctx); + if (ret) + errx(EX_IOERR, "unable to initialize libusb: %i", ret); + + if (verbose > 2) { + libusb_set_debug(ctx, 255); + } + + probe_devices(ctx); + + if (mode == MODE_LIST) { + list_dfu_interfaces(); + exit(0); + } + + if (dfu_root == NULL) { + errx(EX_IOERR, "No DFU capable USB device available"); + } else if (dfu_root->next != NULL) { + /* We cannot safely support more than one DFU capable device + * with same vendor/product ID, since during DFU we need to do + * a USB bus reset, after which the target device will get a + * new address */ + errx(EX_IOERR, "More than one DFU capable USB device found! " + "Try `--list' and specify the serial number " + "or disconnect all but one device\n"); + } + + /* We have exactly one device. Its libusb_device is now in dfu_root->dev */ + + printf("Opening DFU capable USB device...\n"); + ret = libusb_open(dfu_root->dev, &dfu_root->dev_handle); + if (ret || !dfu_root->dev_handle) + errx(EX_IOERR, "Cannot open device"); + + printf("ID %04x:%04x\n", dfu_root->vendor, dfu_root->product); + + printf("Run-time device DFU version %04x\n", + libusb_le16_to_cpu(dfu_root->func_dfu.bcdDFUVersion)); + + /* Transition from run-Time mode to DFU mode */ + if (!(dfu_root->flags & DFU_IFF_DFU)) { + int err; + /* In the 'first round' during runtime mode, there can only be one + * DFU Interface descriptor according to the DFU Spec. */ + + /* FIXME: check if the selected device really has only one */ + + runtime_vendor = dfu_root->vendor; + runtime_product = dfu_root->product; + + printf("Claiming USB DFU Runtime Interface...\n"); + if (libusb_claim_interface(dfu_root->dev_handle, dfu_root->interface) < 0) { + errx(EX_IOERR, "Cannot claim interface %d", + dfu_root->interface); + } + + if (libusb_set_interface_alt_setting(dfu_root->dev_handle, dfu_root->interface, 0) < 0) { + errx(EX_IOERR, "Cannot set alt interface zero"); + } + + printf("Determining device status: "); + + err = dfu_get_status(dfu_root, &status); + if (err == LIBUSB_ERROR_PIPE) { + printf("Device does not implement get_status, assuming appIDLE\n"); + status.bStatus = DFU_STATUS_OK; + status.bwPollTimeout = 0; + status.bState = DFU_STATE_appIDLE; + status.iString = 0; + } else if (err < 0) { + errx(EX_IOERR, "error get_status"); + } else { + printf("state = %s, status = %d\n", + dfu_state_to_string(status.bState), status.bStatus); + } + milli_sleep(status.bwPollTimeout); + + switch (status.bState) { + case DFU_STATE_appIDLE: + case DFU_STATE_appDETACH: + printf("Device really in Runtime Mode, send DFU " + "detach request...\n"); + if (dfu_detach(dfu_root->dev_handle, + dfu_root->interface, 1000) < 0) { + warnx("error detaching"); + } + if (dfu_root->func_dfu.bmAttributes & USB_DFU_WILL_DETACH) { + printf("Device will detach and reattach...\n"); + } else { + printf("Resetting USB...\n"); + ret = libusb_reset_device(dfu_root->dev_handle); + if (ret < 0 && ret != LIBUSB_ERROR_NOT_FOUND) + errx(EX_IOERR, "error resetting " + "after detach"); + } + break; + case DFU_STATE_dfuERROR: + printf("dfuERROR, clearing status\n"); + if (dfu_clear_status(dfu_root->dev_handle, + dfu_root->interface) < 0) { + errx(EX_IOERR, "error clear_status"); + } + /* fall through */ + default: + warnx("WARNING: Runtime device already in DFU state ?!?"); + libusb_release_interface(dfu_root->dev_handle, + dfu_root->interface); + goto dfustate; + } + libusb_release_interface(dfu_root->dev_handle, + dfu_root->interface); + libusb_close(dfu_root->dev_handle); + dfu_root->dev_handle = NULL; + + if (mode == MODE_DETACH) { + libusb_exit(ctx); + exit(0); + } + + /* keeping handles open might prevent re-enumeration */ + disconnect_devices(); + + milli_sleep(detach_delay * 1000); + + /* Change match vendor and product to impossible values to force + * only DFU mode matches in the following probe */ + match_vendor = match_product = 0x10000; + + probe_devices(ctx); + + if (dfu_root == NULL) { + errx(EX_IOERR, "Lost device after RESET?"); + } else if (dfu_root->next != NULL) { + errx(EX_IOERR, "More than one DFU capable USB device found! " + "Try `--list' and specify the serial number " + "or disconnect all but one device"); + } + + /* Check for DFU mode device */ + if (!(dfu_root->flags | DFU_IFF_DFU)) + errx(EX_SOFTWARE, "Device is not in DFU mode"); + + printf("Opening DFU USB Device...\n"); + ret = libusb_open(dfu_root->dev, &dfu_root->dev_handle); + if (ret || !dfu_root->dev_handle) { + errx(EX_IOERR, "Cannot open device"); + } + } else { + /* we're already in DFU mode, so we can skip the detach/reset + * procedure */ + /* If a match vendor/product was specified, use that as the runtime + * vendor/product, otherwise use the DFU mode vendor/product */ + runtime_vendor = match_vendor < 0 ? dfu_root->vendor : match_vendor; + runtime_product = match_product < 0 ? dfu_root->product : match_product; + } + +dfustate: +#if 0 + printf("Setting Configuration %u...\n", dfu_root->configuration); + if (libusb_set_configuration(dfu_root->dev_handle, dfu_root->configuration) < 0) { + errx(EX_IOERR, "Cannot set configuration"); + } +#endif + printf("Claiming USB DFU Interface...\n"); + if (libusb_claim_interface(dfu_root->dev_handle, dfu_root->interface) < 0) { + errx(EX_IOERR, "Cannot claim interface"); + } + + printf("Setting Alternate Setting #%d ...\n", dfu_root->altsetting); + if (libusb_set_interface_alt_setting(dfu_root->dev_handle, dfu_root->interface, dfu_root->altsetting) < 0) { + errx(EX_IOERR, "Cannot set alternate interface"); + } + +status_again: + printf("Determining device status: "); + if (dfu_get_status(dfu_root, &status ) < 0) { + errx(EX_IOERR, "error get_status"); + } + printf("state = %s, status = %d\n", + dfu_state_to_string(status.bState), status.bStatus); + + milli_sleep(status.bwPollTimeout); + + switch (status.bState) { + case DFU_STATE_appIDLE: + case DFU_STATE_appDETACH: + errx(EX_IOERR, "Device still in Runtime Mode!"); + break; + case DFU_STATE_dfuERROR: + printf("dfuERROR, clearing status\n"); + if (dfu_clear_status(dfu_root->dev_handle, dfu_root->interface) < 0) { + errx(EX_IOERR, "error clear_status"); + } + goto status_again; + break; + case DFU_STATE_dfuDNLOAD_IDLE: + case DFU_STATE_dfuUPLOAD_IDLE: + printf("aborting previous incomplete transfer\n"); + if (dfu_abort(dfu_root->dev_handle, dfu_root->interface) < 0) { + errx(EX_IOERR, "can't send DFU_ABORT"); + } + goto status_again; + break; + case DFU_STATE_dfuIDLE: + printf("dfuIDLE, continuing\n"); + break; + default: + break; + } + + if (DFU_STATUS_OK != status.bStatus ) { + printf("WARNING: DFU Status: '%s'\n", + dfu_status_to_string(status.bStatus)); + /* Clear our status & try again. */ + if (dfu_clear_status(dfu_root->dev_handle, dfu_root->interface) < 0) + errx(EX_IOERR, "USB communication error"); + if (dfu_get_status(dfu_root, &status) < 0) + errx(EX_IOERR, "USB communication error"); + if (DFU_STATUS_OK != status.bStatus) + errx(EX_SOFTWARE, "Status is not OK: %d", status.bStatus); + + milli_sleep(status.bwPollTimeout); + } + + printf("DFU mode device DFU version %04x\n", + libusb_le16_to_cpu(dfu_root->func_dfu.bcdDFUVersion)); + + if (dfu_root->func_dfu.bcdDFUVersion == libusb_cpu_to_le16(0x11a)) + dfuse_device = 1; + + /* If not overridden by the user */ + if (!transfer_size) { + transfer_size = libusb_le16_to_cpu( + dfu_root->func_dfu.wTransferSize); + if (transfer_size) { + printf("Device returned transfer size %i\n", + transfer_size); + } else { + errx(EX_IOERR, "Transfer size must be specified"); + } + } + +#ifdef HAVE_GETPAGESIZE +/* autotools lie when cross-compiling for Windows using mingw32/64 */ +#ifndef __MINGW32__ + /* limitation of Linux usbdevio */ + if ((int)transfer_size > getpagesize()) { + transfer_size = getpagesize(); + printf("Limited transfer size to %i\n", transfer_size); + } +#endif /* __MINGW32__ */ +#endif /* HAVE_GETPAGESIZE */ + + if (transfer_size < dfu_root->bMaxPacketSize0) { + transfer_size = dfu_root->bMaxPacketSize0; + printf("Adjusted transfer size to %i\n", transfer_size); + } + + switch (mode) { + case MODE_UPLOAD: + /* open for "exclusive" writing */ + fd = open(file.name, O_WRONLY | O_BINARY | O_CREAT | O_EXCL | O_TRUNC, 0666); + if (fd < 0) + err(EX_IOERR, "Cannot open file %s for writing", file.name); + + if (dfuse_device || dfuse_options) { + if (dfuse_do_upload(dfu_root, transfer_size, fd, + dfuse_options) < 0) + exit(1); + } else { + if (dfuload_do_upload(dfu_root, transfer_size, + expected_size, fd) < 0) { + exit(1); + } + } + close(fd); + break; + + case MODE_DOWNLOAD: + if (((file.idVendor != 0xffff && file.idVendor != runtime_vendor) || + (file.idProduct != 0xffff && file.idProduct != runtime_product)) && + ((file.idVendor != 0xffff && file.idVendor != dfu_root->vendor) || + (file.idProduct != 0xffff && file.idProduct != dfu_root->product))) { + errx(EX_IOERR, "Error: File ID %04x:%04x does " + "not match device (%04x:%04x or %04x:%04x)", + file.idVendor, file.idProduct, + runtime_vendor, runtime_product, + dfu_root->vendor, dfu_root->product); + } + if (dfuse_device || dfuse_options || file.bcdDFU == 0x11a) { + if (dfuse_do_dnload(dfu_root, transfer_size, &file, + dfuse_options) < 0) + exit(1); + } else { + if (dfuload_do_dnload(dfu_root, transfer_size, &file) < 0) + exit(1); + } + break; + case MODE_DETACH: + if (dfu_detach(dfu_root->dev_handle, dfu_root->interface, 1000) < 0) { + warnx("can't detach"); + } + break; + default: + errx(EX_IOERR, "Unsupported mode: %u", mode); + break; + } + + if (final_reset) { + if (dfu_detach(dfu_root->dev_handle, dfu_root->interface, 1000) < 0) { + /* Even if detach failed, just carry on to leave the + device in a known state */ + warnx("can't detach"); + } + printf("Resetting USB to switch back to runtime mode\n"); + ret = libusb_reset_device(dfu_root->dev_handle); + if (ret < 0 && ret != LIBUSB_ERROR_NOT_FOUND) { + errx(EX_IOERR, "error resetting after download"); + } + } + + libusb_close(dfu_root->dev_handle); + dfu_root->dev_handle = NULL; + libusb_exit(ctx); + + return (0); +} diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/portable.h b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/portable.h new file mode 100644 index 0000000..cf8d5df --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/portable.h @@ -0,0 +1,72 @@ + +#ifndef PORTABLE_H +#define PORTABLE_H + +#ifdef HAVE_CONFIG_H +# include "config.h" +#else +# define PACKAGE "dfu-util" +# define PACKAGE_VERSION "0.8-msvc" +# define PACKAGE_STRING "dfu-util 0.8-msvc" +# define PACKAGE_BUGREPORT "dfu-util@lists.gnumonks.org" +#endif /* HAVE_CONFIG_H */ + +#ifdef HAVE_FTRUNCATE +# include +#else +# include +#endif /* HAVE_FTRUNCATE */ + +#ifdef HAVE_NANOSLEEP +# include +# define milli_sleep(msec) do {\ + if (msec) {\ + struct timespec nanosleepDelay = { (msec) / 1000, ((msec) % 1000) * 1000000 };\ + nanosleep(&nanosleepDelay, NULL);\ + } } while (0) +#elif defined HAVE_WINDOWS_H +# define milli_sleep(msec) do {\ + if (msec) {\ + Sleep(msec);\ + } } while (0) +#else +# error "Can't get no sleep! Please report" +#endif /* HAVE_NANOSLEEP */ + +#ifdef HAVE_ERR +# include +#else +# include +# include +# define warnx(...) do {\ + fprintf(stderr, __VA_ARGS__);\ + fprintf(stderr, "\n"); } while (0) +# define errx(eval, ...) do {\ + warnx(__VA_ARGS__);\ + exit(eval); } while (0) +# define warn(...) do {\ + fprintf(stderr, "%s: ", strerror(errno));\ + warnx(__VA_ARGS__); } while (0) +# define err(eval, ...) do {\ + warn(__VA_ARGS__);\ + exit(eval); } while (0) +#endif /* HAVE_ERR */ + +#ifdef HAVE_SYSEXITS_H +# include +#else +# define EX_OK 0 /* successful termination */ +# define EX_USAGE 64 /* command line usage error */ +# define EX_SOFTWARE 70 /* internal software error */ +# define EX_IOERR 74 /* input/output error */ +#endif /* HAVE_SYSEXITS_H */ + +#ifndef O_BINARY +# define O_BINARY 0 +#endif + +#ifndef off_t +# define off_t long int +#endif + +#endif /* PORTABLE_H */ diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/prefix.c b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/prefix.c new file mode 100644 index 0000000..be8e3fa --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/prefix.c @@ -0,0 +1,176 @@ +/* + * dfu-prefix + * + * Copyright 2011-2012 Stefan Schmidt + * Copyright 2013 Hans Petter Selasky + * Copyright 2014 Uwe Bonnes + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include "portable.h" +#include "dfu_file.h" + +enum mode { + MODE_NONE, + MODE_ADD, + MODE_DEL, + MODE_CHECK +}; + +int verbose; + +static void help(void) +{ + fprintf(stderr, "Usage: dfu-prefix [options] ...\n" + " -h --help\t\t\tPrint this help message\n" + " -V --version\t\t\tPrint the version number\n" + " -c --check \t\tCheck DFU prefix of \n" + " -D --delete \t\tDelete DFU prefix from \n" + " -a --add \t\tAdd DFU prefix to \n" + "In combination with -a:\n" + ); + fprintf(stderr, " -s --stellaris-address
Add TI Stellaris address prefix to \n" + "In combination with -D or -c:\n" + " -T --stellaris\t\tAct on TI Stellaris address prefix of \n" + "In combination with -a or -D or -c:\n" + " -L --lpc-prefix\t\tUse NXP LPC DFU prefix format\n" + ); + exit(EX_USAGE); +} + +static void print_version(void) +{ + printf("dfu-prefix (%s) %s\n\n", PACKAGE, PACKAGE_VERSION); + printf("Copyright 2011-2012 Stefan Schmidt, 2014 Uwe Bonnes\n" + "This program is Free Software and has ABSOLUTELY NO WARRANTY\n" + "Please report bugs to %s\n\n", PACKAGE_BUGREPORT); + +} + +static struct option opts[] = { + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'V' }, + { "check", 1, 0, 'c' }, + { "add", 1, 0, 'a' }, + { "delete", 1, 0, 'D' }, + { "stellaris-address", 1, 0, 's' }, + { "stellaris", 0, 0, 'T' }, + { "LPC", 0, 0, 'L' }, +}; +int main(int argc, char **argv) +{ + struct dfu_file file; + enum mode mode = MODE_NONE; + enum prefix_type type = ZERO_PREFIX; + uint32_t lmdfu_flash_address = 0; + char *end; + + /* make sure all prints are flushed */ + setvbuf(stdout, NULL, _IONBF, 0); + + print_version(); + + memset(&file, 0, sizeof(file)); + + while (1) { + int c, option_index = 0; + c = getopt_long(argc, argv, "hVc:a:D:p:v:d:s:TL", opts, + &option_index); + if (c == -1) + break; + + switch (c) { + case 'h': + help(); + break; + case 'V': + exit(0); + break; + case 'D': + file.name = optarg; + mode = MODE_DEL; + break; + case 'c': + file.name = optarg; + mode = MODE_CHECK; + break; + case 'a': + file.name = optarg; + mode = MODE_ADD; + break; + case 's': + lmdfu_flash_address = strtoul(optarg, &end, 0); + if (*end) { + errx(EX_IOERR, "Invalid lmdfu " + "address: %s", optarg); + } + /* fall-through */ + case 'T': + type = LMDFU_PREFIX; + break; + case 'L': + type = LPCDFU_UNENCRYPTED_PREFIX; + break; + default: + help(); + break; + } + } + + if (!file.name) { + fprintf(stderr, "You need to specify a filename\n"); + help(); + } + + switch(mode) { + case MODE_ADD: + if (type == ZERO_PREFIX) + errx(EX_IOERR, "Prefix type must be specified"); + dfu_load_file(&file, MAYBE_SUFFIX, NO_PREFIX); + file.lmdfu_address = lmdfu_flash_address; + file.prefix_type = type; + printf("Adding prefix to file\n"); + dfu_store_file(&file, file.size.suffix != 0, 1); + break; + + case MODE_CHECK: + dfu_load_file(&file, MAYBE_SUFFIX, MAYBE_PREFIX); + show_suffix_and_prefix(&file); + if (type > ZERO_PREFIX && file.prefix_type != type) + errx(EX_IOERR, "No prefix of requested type"); + break; + + case MODE_DEL: + dfu_load_file(&file, MAYBE_SUFFIX, NEEDS_PREFIX); + if (type > ZERO_PREFIX && file.prefix_type != type) + errx(EX_IOERR, "No prefix of requested type"); + printf("Removing prefix from file\n"); + /* if there was a suffix, rewrite it */ + dfu_store_file(&file, file.size.suffix != 0, 0); + break; + + default: + help(); + break; + } + return (0); +} diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/quirks.c b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/quirks.c new file mode 100644 index 0000000..de394a6 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/quirks.c @@ -0,0 +1,56 @@ +/* + * Simple quirk system for dfu-util + * + * Copyright 2010-2014 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include "quirks.h" + +uint16_t get_quirks(uint16_t vendor, uint16_t product, uint16_t bcdDevice) +{ + uint16_t quirks = 0; + + /* Device returns bogus bwPollTimeout values */ + if ((vendor == VENDOR_OPENMOKO || vendor == VENDOR_FIC) && + product >= PRODUCT_FREERUNNER_FIRST && + product <= PRODUCT_FREERUNNER_LAST) + quirks |= QUIRK_POLLTIMEOUT; + + if (vendor == VENDOR_VOTI && + product == PRODUCT_OPENPCD) + quirks |= QUIRK_POLLTIMEOUT; + + /* Reports wrong DFU version in DFU descriptor */ + if (vendor == VENDOR_LEAFLABS && + product == PRODUCT_MAPLE3 && + bcdDevice == 0x0200) + quirks |= QUIRK_FORCE_DFU11; + + /* old devices(bcdDevice == 0) return bogus bwPollTimeout values */ + if (vendor == VENDOR_SIEMENS && + (product == PRODUCT_PXM40 || product == PRODUCT_PXM50) && + bcdDevice == 0) + quirks |= QUIRK_POLLTIMEOUT; + + /* M-Audio Transit returns bogus bwPollTimeout values */ + if (vendor == VENDOR_MIDIMAN && + product == PRODUCT_TRANSIT) + quirks |= QUIRK_POLLTIMEOUT; + + return (quirks); +} diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/quirks.h b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/quirks.h new file mode 100644 index 0000000..0e4b3ec --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/quirks.h @@ -0,0 +1,27 @@ +#ifndef DFU_QUIRKS_H +#define DFU_QUIRKS_H + +#define VENDOR_OPENMOKO 0x1d50 /* Openmoko Freerunner / GTA02 */ +#define VENDOR_FIC 0x1457 /* Openmoko Freerunner / GTA02 */ +#define VENDOR_VOTI 0x16c0 /* OpenPCD Reader */ +#define VENDOR_LEAFLABS 0x1eaf /* Maple */ +#define VENDOR_SIEMENS 0x0908 /* Siemens AG */ +#define VENDOR_MIDIMAN 0x0763 /* Midiman */ + +#define PRODUCT_FREERUNNER_FIRST 0x5117 +#define PRODUCT_FREERUNNER_LAST 0x5126 +#define PRODUCT_OPENPCD 0x076b +#define PRODUCT_MAPLE3 0x0003 /* rev 3 and 5 */ +#define PRODUCT_PXM40 0x02c4 /* Siemens AG, PXM 40 */ +#define PRODUCT_PXM50 0x02c5 /* Siemens AG, PXM 50 */ +#define PRODUCT_TRANSIT 0x2806 /* M-Audio Transit (Midiman) */ + +#define QUIRK_POLLTIMEOUT (1<<0) +#define QUIRK_FORCE_DFU11 (1<<1) + +/* Fallback value, works for OpenMoko */ +#define DEFAULT_POLLTIMEOUT 5 + +uint16_t get_quirks(uint16_t vendor, uint16_t product, uint16_t bcdDevice); + +#endif /* DFU_QUIRKS_H */ diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/suffix.c b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/suffix.c new file mode 100644 index 0000000..0df248f --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/suffix.c @@ -0,0 +1,176 @@ +/* + * dfu-suffix + * + * Copyright 2011-2012 Stefan Schmidt + * Copyright 2013 Hans Petter Selasky + * Copyright 2014 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include "portable.h" +#include "dfu_file.h" + +enum mode { + MODE_NONE, + MODE_ADD, + MODE_DEL, + MODE_CHECK +}; + +int verbose; + +static void help(void) +{ + fprintf(stderr, "Usage: dfu-suffix [options] ...\n" + " -h --help\t\t\tPrint this help message\n" + " -V --version\t\t\tPrint the version number\n" + " -c --check \t\tCheck DFU suffix of \n" + " -a --add \t\tAdd DFU suffix to \n" + " -D --delete \t\tDelete DFU suffix from \n" + " -p --pid \t\tAdd product ID into DFU suffix in \n" + " -v --vid \t\tAdd vendor ID into DFU suffix in \n" + " -d --did \t\tAdd device ID into DFU suffix in \n" + " -S --spec \t\tAdd DFU specification ID into DFU suffix in \n" + ); + exit(EX_USAGE); +} + +static void print_version(void) +{ + printf("dfu-suffix (%s) %s\n\n", PACKAGE, PACKAGE_VERSION); + printf("Copyright 2011-2012 Stefan Schmidt, 2013-2014 Tormod Volden\n" + "This program is Free Software and has ABSOLUTELY NO WARRANTY\n" + "Please report bugs to %s\n\n", PACKAGE_BUGREPORT); + +} + +static struct option opts[] = { + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'V' }, + { "check", 1, 0, 'c' }, + { "add", 1, 0, 'a' }, + { "delete", 1, 0, 'D' }, + { "pid", 1, 0, 'p' }, + { "vid", 1, 0, 'v' }, + { "did", 1, 0, 'd' }, + { "spec", 1, 0, 'S' }, +}; + +int main(int argc, char **argv) +{ + struct dfu_file file; + int pid, vid, did, spec; + enum mode mode = MODE_NONE; + + /* make sure all prints are flushed */ + setvbuf(stdout, NULL, _IONBF, 0); + + print_version(); + + pid = vid = did = 0xffff; + spec = 0x0100; /* Default to bcdDFU version 1.0 */ + memset(&file, 0, sizeof(file)); + + while (1) { + int c, option_index = 0; + c = getopt_long(argc, argv, "hVc:a:D:p:v:d:S:s:T", opts, + &option_index); + if (c == -1) + break; + + switch (c) { + case 'h': + help(); + break; + case 'V': + exit(0); + break; + case 'D': + file.name = optarg; + mode = MODE_DEL; + break; + case 'p': + pid = strtol(optarg, NULL, 16); + break; + case 'v': + vid = strtol(optarg, NULL, 16); + break; + case 'd': + did = strtol(optarg, NULL, 16); + break; + case 'S': + spec = strtol(optarg, NULL, 16); + break; + case 'c': + file.name = optarg; + mode = MODE_CHECK; + break; + case 'a': + file.name = optarg; + mode = MODE_ADD; + break; + default: + help(); + break; + } + } + + if (!file.name) { + fprintf(stderr, "You need to specify a filename\n"); + help(); + } + + if (spec != 0x0100 && spec != 0x011a) { + fprintf(stderr, "Only DFU specification 0x0100 and 0x011a supported\n"); + help(); + } + + switch(mode) { + case MODE_ADD: + dfu_load_file(&file, NO_SUFFIX, MAYBE_PREFIX); + file.idVendor = vid; + file.idProduct = pid; + file.bcdDevice = did; + file.bcdDFU = spec; + /* always write suffix, rewrite prefix if there was one */ + dfu_store_file(&file, 1, file.size.prefix != 0); + printf("Suffix successfully added to file\n"); + break; + + case MODE_CHECK: + dfu_load_file(&file, NEEDS_SUFFIX, MAYBE_PREFIX); + show_suffix_and_prefix(&file); + break; + + case MODE_DEL: + dfu_load_file(&file, NEEDS_SUFFIX, MAYBE_PREFIX); + dfu_store_file(&file, 0, file.size.prefix != 0); + if (file.size.suffix) /* had a suffix */ + printf("Suffix successfully removed from file\n"); + break; + + default: + help(); + break; + } + return (0); +} diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/usb_dfu.h b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/usb_dfu.h new file mode 100644 index 0000000..660bedc --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/src/usb_dfu.h @@ -0,0 +1,99 @@ +#ifndef USB_DFU_H +#define USB_DFU_H +/* USB Device Firmware Update Implementation for OpenPCD + * (C) 2006 by Harald Welte + * + * Protocol definitions for USB DFU + * + * This ought to be compliant to the USB DFU Spec 1.0 as available from + * http://www.usb.org/developers/devclass_docs/usbdfu10.pdf + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#define USB_DT_DFU 0x21 + +#ifdef _MSC_VER +# pragma pack(push) +# pragma pack(1) +#endif /* _MSC_VER */ +struct usb_dfu_func_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bmAttributes; +#define USB_DFU_CAN_DOWNLOAD (1 << 0) +#define USB_DFU_CAN_UPLOAD (1 << 1) +#define USB_DFU_MANIFEST_TOL (1 << 2) +#define USB_DFU_WILL_DETACH (1 << 3) + uint16_t wDetachTimeOut; + uint16_t wTransferSize; + uint16_t bcdDFUVersion; +#ifdef _MSC_VER +}; +# pragma pack(pop) +#elif defined __GNUC__ +} __attribute__ ((packed)); +#else + #warning "No way to pack struct on this compiler? This will break!" +#endif /* _MSC_VER */ + +#define USB_DT_DFU_SIZE 9 + +#define USB_TYPE_DFU (LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE) + +/* DFU class-specific requests (Section 3, DFU Rev 1.1) */ +#define USB_REQ_DFU_DETACH 0x00 +#define USB_REQ_DFU_DNLOAD 0x01 +#define USB_REQ_DFU_UPLOAD 0x02 +#define USB_REQ_DFU_GETSTATUS 0x03 +#define USB_REQ_DFU_CLRSTATUS 0x04 +#define USB_REQ_DFU_GETSTATE 0x05 +#define USB_REQ_DFU_ABORT 0x06 + +/* DFU_GETSTATUS bStatus values (Section 6.1.2, DFU Rev 1.1) */ +#define DFU_STATUS_OK 0x00 +#define DFU_STATUS_errTARGET 0x01 +#define DFU_STATUS_errFILE 0x02 +#define DFU_STATUS_errWRITE 0x03 +#define DFU_STATUS_errERASE 0x04 +#define DFU_STATUS_errCHECK_ERASED 0x05 +#define DFU_STATUS_errPROG 0x06 +#define DFU_STATUS_errVERIFY 0x07 +#define DFU_STATUS_errADDRESS 0x08 +#define DFU_STATUS_errNOTDONE 0x09 +#define DFU_STATUS_errFIRMWARE 0x0a +#define DFU_STATUS_errVENDOR 0x0b +#define DFU_STATUS_errUSBR 0x0c +#define DFU_STATUS_errPOR 0x0d +#define DFU_STATUS_errUNKNOWN 0x0e +#define DFU_STATUS_errSTALLEDPKT 0x0f + +enum dfu_state { + DFU_STATE_appIDLE = 0, + DFU_STATE_appDETACH = 1, + DFU_STATE_dfuIDLE = 2, + DFU_STATE_dfuDNLOAD_SYNC = 3, + DFU_STATE_dfuDNBUSY = 4, + DFU_STATE_dfuDNLOAD_IDLE = 5, + DFU_STATE_dfuMANIFEST_SYNC = 6, + DFU_STATE_dfuMANIFEST = 7, + DFU_STATE_dfuMANIFEST_WAIT_RST = 8, + DFU_STATE_dfuUPLOAD_IDLE = 9, + DFU_STATE_dfuERROR = 10 +}; + +#endif /* USB_DFU_H */ diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/www/build.html b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/www/build.html new file mode 100644 index 0000000..f3036e4 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/www/build.html @@ -0,0 +1,147 @@ + + + + + + + Building dfu-util from source + + + + + + + + + +
+

How to build dfu-util from source

+ +

Prerequisites for building from git

+

Mac OS X

+

+First install MacPorts (and if you are on 10.6 or older, the Java Developer Package) and then run: +

+
+	sudo port install libusb-devel git-core
+
+ +

FreeBSD

+
+	sudo pkg_add -r git pkgconf
+
+ +

Ubuntu and Debian and derivatives

+
+	sudo apt-get build-dep dfu-util
+	sudo apt-get install libusb-1.0-0-dev
+
+ +

Get the source code and build it

+

+The first time you will have to clone the git repository: +

+
+	git clone git://gitorious.org/dfu-util/dfu-util.git
+	cd dfu-util
+
+

+If you later want to update to latest git version, just run this: +

+
+	make maintainer-clean
+	git pull
+
+

+To build the source: +

+
+	./autogen.sh
+	./configure  # on most systems
+	make
+
+ +

+If you are building on Mac OS X, replace the ./configure command with: +

+
+	./configure --libdir=/opt/local/lib --includedir=/opt/local/include  # on MacOSX only
+
+ +

+Your dfu-util binary will be inside the src folder. Use it from there, or install it to /usr/local/bin by running "sudo make install". +

+ +

Cross-building for Windows

+ +

+Windows binaries can be built in a MinGW +environment, on a Windows computer or cross-hosted in another OS. +To build it on a Debian or Ubuntu host, first install build dependencies: +

+
+	sudo apt-get build-dep libusb-1.0-0 dfu-util
+	sudo apt-get install mingw32
+
+ +

+The below example builds dfu-util 0.8 and libusb 1.0.19 from unpacked release +tarballs. If you instead build from git, you will have to run "./autogen.sh" +before running the "./configure" steps. +

+ +
+mkdir -p build
+cd libusb-1.0.19
+PKG_CONFIG_PATH=$PWD/../build/lib/pkgconfig ./configure \
+    --host=i586-mingw32msvc --prefix=$PWD/../build
+# WINVER workaround needed for 1.0.19 only
+make CFLAGS="-DWINVER=0x0501"
+make install
+cd ..
+
+cd dfu-util-0.8
+PKG_CONFIG_PATH=$PWD/../build/lib/pkgconfig ./configure \
+    --host=i586-mingw32msvc --prefix=$PWD/../build
+make
+make install
+cd ..
+
+The build files will now be in build/bin. +

+ +

Building on Windows using MinGW

+This assumes using release tarballs or having run ./autogen.sh on +the git sources. +
+cd libusb-1.0.19
+./configure --prefix=$HOME
+# WINVER workaround needed for 1.0.19 only
+# MKDIR_P setting should not really be needed...
+make CFLAGS="-DWINVER=0x0501" MKDIR_P="mkdir -p"
+make install
+cd ..
+
+cd dfu-util-0.8
+./configure USB_CFLAGS="-I$HOME/include/libusb-1.0" \
+            USB_LIBS="-L $HOME/lib -lusb-1.0" PKG_CONFIG=true
+make
+make install
+cd ..
+
+To link libusb statically into dfu-util.exe use instead of "make": +
+make LDFLAGS=-static
+
+The built executables (and DLL) will now be under $HOME/bin. + +

+[Back to dfu-util main page] +

+ +
+ + diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/www/dfu-util.1.html b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/www/dfu-util.1.html new file mode 100644 index 0000000..62ca40b --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/www/dfu-util.1.html @@ -0,0 +1,411 @@ + + +Man page of DFU-UTIL + + +

DFU-UTIL(1)

+ +  +

NAME

+ +dfu-util - Device firmware update (DFU) USB programmer +  +

SYNOPSIS

+ + +
+
+dfu-util + +-l + +[-v] + +[-d + +vid:pid[,vid:pid]] + +[-p + +path] + +[-c + +configuration] + +[-i + +interface] + +[-a + +alt-intf] + +[-S + +serial[,serial]] + + +
+dfu-util + +[-v] + +[-d + +vid:pid[,vid:pid]] + +[-p + +path] + +[-c + +configuration] + +[-i + +interface] + +[-a + +alt-intf] + +[-S + +serial[,serial]] + +[-t + +size] + +[-Z + +size] + +[-s + +address] + +[-R] + +[-D|-U + +file] + + +
+dfu-util + +[-hV] + +
+  +

DESCRIPTION

+ +dfu-util + +is a program that implements the host (computer) side of the USB DFU +(Universal Serial Bus Device Firmware Upgrade) protocol. +

+dfu-util communicates with devices that implement the device side of the +USB DFU protocol, and is often used to upgrade the firmware of such +devices. +  +

OPTIONS

+ +
+
-l, --list + +
+List the currently attached DFU capable USB devices. +
-d, --device [Run-Time VENDOR]:[Run-Time PRODUCT][,[DFU Mode VENDOR]:[DFU Mode PRODUCT]] + +
+
+Specify run-time and/or DFU mode vendor and/or product IDs of the DFU device +to work with. VENDOR and PRODUCT are hexadecimal numbers (no prefix +needed), "*" (match any), or "-" (match nothing). By default, any DFU capable +device in either run-time or DFU mode will be considered. +

+If you only have one standards-compliant DFU device attached to your computer, +this parameter is optional. However, as soon as you have multiple DFU devices +connected, dfu-util will detect this and abort, asking you to specify which +device to use. +

+If only run-time IDs are specified (e.g. "--device 1457:51ab"), then in +addition to the specified run-time IDs, any DFU mode devices will also be +considered. This is beneficial to allow a DFU capable device to be found +again after a switch to DFU mode, since the vendor and/or product ID of a +device usually changes in DFU mode. +

+If only DFU mode IDs are specified (e.g. "--device ,951:26"), then all +run-time devices will be ignored, making it easy to target a specific device in +DFU mode. +

+If both run-time and DFU mode IDs are specified (e.g. "--device +1457:51ab,:2bc"), then unspecified DFU mode components will use the run-time +value specified. +

+Examples: +

+
--device 1457:51ab,951:26 + +
+
+ +Work with a device in run-time mode with +vendor ID 0x1457 and product ID 0x51ab, or in DFU mode with vendor ID 0x0951 +and product ID 0x0026 +

+

--device 1457:51ab,:2bc + +
+
+ +Work with a device in run-time mode with vendor ID 0x1457 and product ID +0x51ab, or in DFU mode with vendor ID 0x1457 and product ID 0x02bc +

+

--device 1457:51ab + +
+
+ +Work with a device in run-time mode with vendor ID 0x1457 and product ID +0x51ab, or in DFU mode with any vendor and product ID +

+

--device ,951:26 + +
+
+ +Work with a device in DFU mode with vendor ID 0x0951 and product ID 0x0026 +

+

--device *,- + +
+
+ +Work with any device in run-time mode, and ignore any device in DFU mode +

+

--device , + +
+
+ +Ignore any device in run-time mode, and Work with any device in DFU mode +
+
+ +
-p, --path BUS-PORT. ... .PORT + +
+Specify the path to the DFU device. +
-c, --cfg CONFIG-NR + +
+Specify the configuration of the DFU device. Note that this is only used for matching, the configuration is not set by dfu-util. +
-i, --intf INTF-NR + +
+Specify the DFU interface number. +
-a, --alt ALT + +
+Specify the altsetting of the DFU interface by name or by number. +
-S, --serial [Run-Time SERIAL][,[DFU Mode SERIAL]] + +
+Specify the run-time and DFU mode serial numbers used to further restrict +device matches. If multiple, identical DFU devices are simultaneously +connected to a system then vendor and product ID will be insufficient for +targeting a single device. In this situation, it may be possible to use this +parameter to specify a serial number which also must match. +

+If only a single serial number is specified, then the same serial number is +used in both run-time and DFU mode. An empty serial number will match any +serial number in the corresponding mode. +

-t, --transfer-size SIZE + +
+Specify the number of bytes per USB transfer. The optimal value is +usually determined automatically so this option is rarely useful. If +you need to use this option for a device, please report it as a bug. +
-Z, --upload-size SIZE + +
+Specify the expected upload size, in bytes. +
-U, --upload FILE + +
+Read firmware from device into +FILE. + +
-D, --download FILE + +
+Write firmware from +FILE + +into device. +
-R, --reset + +
+Issue USB reset signalling after upload or download has finished. +
-s, --dfuse-address address + +
+Specify target address for raw binary download/upload on DfuSe devices. Do +not + +use this for downloading DfuSe (.dfu) files. Modifiers can be added +to the address, separated by a colon, to perform special DfuSE commands such +as "leave" DFU mode, "unprotect" and "mass-erase" flash memory. +
-v, --verbose + +
+Print more information about dfu-util's operation. A second +-v + +will turn on verbose logging of USB requests. Repeat this option to further +increase verbosity. +
-h, --help + +
+Show a help text and exit. +
-V, --version + +
+Show version information and exit. +
+  +

EXAMPLES

+ +  +

Using dfu-util in the OpenMoko project

+ +(with the Neo1973 hardware) +

+ +Flashing the rootfs: +
+ + $ dfu-util -a rootfs -R -D /path/to/openmoko-devel-image.jffs2 + +

+ +Flashing the kernel: +
+ + $ dfu-util -a kernel -R -D /path/to/uImage + +

+ +Flashing the bootloader: +
+ + $ dfu-util -a u-boot -R -D /path/to/u-boot.bin + +

+ +Copying a kernel into RAM: +
+ + $ dfu-util -a 0 -R -D /path/to/uImage + +

+Once this has finished, the kernel will be available at the default load +address of 0x32000000 in Neo1973 RAM. +Note: + +You cannot transfer more than 2MB of data into RAM using this method. +

+  +

Using dfu-util with a DfuSe device

+ +

+ +Flashing a +.dfu + +(special DfuSe format) file to the device: +
+ + $ dfu-util -a 0 -D /path/to/dfuse-image.dfu + +

+ +Reading out 1 KB of flash starting at address 0x8000000: +
+ + $ dfu-util -a 0 -s 0x08000000:1024 -U newfile.bin + +

+ +Flashing a binary file to address 0x8004000 of device memory and +ask the device to leave DFU mode: +
+ + $ dfu-util -a 0 -s 0x08004000:leave -D /path/to/image.bin + + +  +

BUGS

+ +Please report any bugs to the dfu-util mailing list at +dfu-util@lists.gnumonks.org. + +Please use the +--verbose option (repeated as necessary) to provide more + +information in your bug report. +  +

SEE ALSO

+ +The dfu-util home page is +http://dfu-util.gnumonks.org + +  +

HISTORY

+ +dfu-util was originally written for the OpenMoko project by +Weston Schmidt <weston_schmidt@yahoo.com> and +Harald Welte <hwelte@hmw-consulting.de>. Over time, nearly complete +support of DFU 1.0, DFU 1.1 and DfuSe ("1.1a") has been added. +  +

LICENCE

+ +dfu-util + +is covered by the GNU General Public License (GPL), version 2 or later. +  +

COPYRIGHT

+ +This manual page was originally written by Uwe Hermann <uwe@hermann-uwe.de>, +and is now part of the dfu-util project. +

+ +


+ 

Index

+
+
NAME
+
SYNOPSIS
+
DESCRIPTION
+
OPTIONS
+
EXAMPLES
+
+
Using dfu-util in the OpenMoko project
+
Using dfu-util with a DfuSe device
+
+
BUGS
+
SEE ALSO
+
HISTORY
+
LICENCE
+
COPYRIGHT
+
+
+This document was created by man2html, +using the doc/dfu-util.1 manual page from dfu-util 0.8.
+Time: 14:40:57 GMT, September 13, 2014 + + diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/www/dfuse.html b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/www/dfuse.html new file mode 100644 index 0000000..35e4ffa --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/www/dfuse.html @@ -0,0 +1,135 @@ + + + + + + DfuSe and dfu-util + + + + + + + + + +
+

Using dfu-util with DfuSe devices

+

DfuSe

+

+ DfuSe (DFU with ST Microsystems extensions) is a protocol based on + DFU 1.1. However, in expanding the functionality of the DFU protocol, + ST Microsystems broke all compatibility with the DFU 1.1 standard. + DfuSe devices report the DFU version as "1.1a". +

+

+ DfuSe can be used to download firmware and other data + from a host computer to a conforming device (or upload in the + opposite direction) over USB similar to standard DFU. +

+

+ The main difference from standard DFU is that the target address in + the device (flash) memory is specified by the host, so that a + download can be performed to parts of the device memory. The host + program is also responsible for erasing flash pages before they + are written to. +

+

.dfu files

+

+ A special file format is defined by ST Microsystems to carry firmware + for DfuSe devices. The file contains target information such as address + and alternate interface information in addition to the binary data. + Several blocks of binary data can be combined in one .dfu file. +

+

Alternate interfaces

+

+ Different memory locations of the device may have different + characteristics that the host program (dfu-util) has to take + into considerations, such as flash memory page size, read-only + versus read-write segments, the need to erase, and so on. + These parameters are reported by the device in the string + descriptors meant for describing the USB interfaces. + The host program decodes these strings to build a memory map of + the device. Different memory units or address spaces are listed + in separate alternate interface settings that must be selected + according to the memory unit to access. +

+

+ Note that dfu-util leaves it to the user to select alternate + interface. When parsing a .dfu file it will skip file segments + not matching the selected alternate interface. Also, some + DfuSe device firmware implementations ignore the setting of + alternate interface and deduct the memory unit from the + address, since they have no address space overlap. +

+

DfuSe special commands

+

+ DfuSe special commands are used by the host program during normal + downloads or uploads, such as SET_ADDRESS and ERASE_PAGE. Also + the normal DFU_DNLOAD and DFU_UPLOAD commands have special + implementations in DfuSe. + Many DfuSe devices also support commands to leave DFU mode, + read unprotect the flash memory or mass erase the flash memory. + dfu-util (from version 0.7) + supports adding "leave", "unprotect", or "mass-erase" + to the -s option argument to send such requests in combination + with a download request. These modifiers are separated with a colon. +

+

+ Some DfuSe devices have their DfuSe bootloader running from flash + memory. Erasing the whole flash memory would therefore destroy + the DfuSe bootloader itself and practically brick the device + for most users. Any use of modifiers such as "unprotect" + and "mass-erase" therefore needs to be combined with the "force" + modifer. This is not included in the examples, to not encourage + ignorant users to copy and paste such instructions and shoot + themselves in the foot. +

+

+ Devices based on for instance STM32F103 all run the bootloader + from flash, since there is no USB bootloader in ROM. +

+

+ For instance STM32F107, STM32F2xx and STM32F4xx devices have a + DfuSe bootloader in ROM, so the flash can be erased while + keeping the device available for USB DFU transfers as long + as the device designers use this built-in bootloader and have + not implemented another DfuSe bootloader in flash that the user is + dependent upon. +

+

+ Well-written bootloaders running from flash will report their + own memory region as read-only and not eraseable, but this does + not prevent dfu-util from sending a "unprotect" or "mass-erase" + request which overrides this, if the user insists. +

+

Example usage

+

+ Flashing a .dfu (special DfuSe format) file to the device: +

+
+         $ dfu-util -a 0 -D /path/to/dfuse-image.dfu
+	
+

+ Reading out 1 KB of flash starting at address 0x8000000: +

+
+         $ dfu-util -a 0 -s 0x08000000:1024 -U newfile.bin
+	
+

+ Flashing a binary file to address 0x8004000 of device memory and ask + the device to leave DFU mode: +

+
+         $ dfu-util -a 0 -s 0x08004000:leave -D /path/to/image.bin
+	
+

+ [Back to dfu-util main page] +

+ +
+ + diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/www/index.html b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/www/index.html new file mode 100644 index 0000000..108ddaf --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/www/index.html @@ -0,0 +1,119 @@ + + + + + + dfu-util Homepage + + + + + + + + + +
+

dfu-util - Device Firmware Upgrade Utilities

+

Description

+

+ dfu-util is a host side implementation of the DFU 1.0 and DFU 1.1 specifications of the USB forum. + + DFU is intended to download and upload firmware to/from devices connected + over USB. It ranges from small devices like micro-controller boards + to mobile phones. Using dfu-util you can download firmware to your + DFU-enabled device or upload firmware from it. dfu-util has been + tested with the Openmoko Neo1973 and Freerunner and many other devices. +

+

+ See the manual page for examples of use. +

+

Supported Devices

+ +

Releases

+

+ Releases of the dfu-util software can be found in the + releases folder. + The current release is 0.8. +

+

+ We offer binaries for Microsoft Windows and some other platforms. + dfu-util uses libusb 1.0 to access your device, so + on Windows you have to register the device with the WinUSB driver + (alternatively libusb-win32 or libusbK), please see the libusbx wiki + for more details. +

+

+ Mac OS X users can also get dfu-util from Homebrew with "brew install dfu-util" or from MacPorts. +

+

+ Most Linux distributions ship dfu-util in binary packages for those + who do not want to compile dfu-util from source. + On Debian, Ubuntu, Fedora and Gentoo you can install it through the + normal software package tools. For other distributions +(namely OpenSuSe, Mandriva, and CentOS) Holger Freyther was kind enough to +provide binary packages through the Open Build Service. +

+

Development

+

+ Development happens in a GIT repository. Browse it via the web +interface or clone it with: +

+
+	git clone git://gitorious.org/dfu-util/dfu-util.git
+	
+

+ See our build instructions for how to + build the source on different platforms. +

+

License

+

+ This software is licensed under the GPL version 2. +

+

Contact

+

+ If you have questions about the development or use of dfu-util please + send an e-mail to our dedicated +mailing list for dfu-util. +

+

People

+

+ dfu-util was originally written by + Harald Welte partially based on code from + dfu-programmer 0.4 and is currently maintained by Stefan Schmidt and + Tormod Volden. +

+ +
+ + diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/www/simple.css b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/www/simple.css new file mode 100644 index 0000000..98100bc --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/dfu-util/www/simple.css @@ -0,0 +1,56 @@ +body { + margin: 10px; + font-size: 0.82em; + background-color: #EEE; +} + +h1 { + clear: both; + padding: 0 0 12px 0; + margin: 0; + font-size: 2em; + font-weight: bold; +} + +h2 { + clear: both; + margin: 0; + font-size: 1.5em; + font-weight: normal; +} + +h3 { + clear: both; + margin: 15px 0 0 0; + font-size: 1.0em; + font-weight: bold; +} + +p { + line-height: 20px; + padding: 8px 0 8px 0; + margin: 0; + font-size: 1.1em; +} + +pre { + white-space: pre-wrap; + background-color: #CCC; + padding: 3px; +} + +a:hover { + background-color: #DDD; +} + +#middlebox { + width: 600px; + margin: 0px auto; + text-align: left; +} + +#footer { + height: 100px; + padding: 28px 3px 0 0; + margin: 20px 0 20px 0; +} diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/README.md b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/README.md new file mode 100644 index 0000000..c6c9379 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/README.md @@ -0,0 +1,5 @@ +These files build the maple_loader.jar file used on Windows to reset the Sketch via USB Serial, so that the bootloader will run in dfu upload mode, ready for a new sketch to be uploaded + +The files were written by @bobC (github) and have been slightly modified by me (Roger Clark), so that dfu-util no longer attempts to reset the board after upload. +This change to dfu-util's reset command line argument, was required because dfu-util was showing errors on some Windows systems, because the bootloader had reset its self after upload, +before dfu-util had chance to tell it to reset. \ No newline at end of file diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build.xml b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build.xml new file mode 100644 index 0000000..80bdd6f --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + Builds, tests, and runs the project maple_loader. + + + diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/built-jar.properties b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/built-jar.properties new file mode 100644 index 0000000..10752d5 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/built-jar.properties @@ -0,0 +1,4 @@ +#Mon, 20 Jul 2015 11:21:26 +1000 + + +C\:\\Users\\rclark\\Desktop\\maple-asp-master\\installer\\maple_loader= diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/CliTemplate/CliMain.class b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/CliTemplate/CliMain.class new file mode 100644 index 0000000..37ee630 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/CliTemplate/CliMain.class differ diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/CliTemplate/DFUUploader.class b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/CliTemplate/DFUUploader.class new file mode 100644 index 0000000..77087b0 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/CliTemplate/DFUUploader.class differ diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/CliTemplate/ExecCommand.class b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/CliTemplate/ExecCommand.class new file mode 100644 index 0000000..ad95f79 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/CliTemplate/ExecCommand.class differ diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/processing/app/Base.class b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/processing/app/Base.class new file mode 100644 index 0000000..4aa0bde Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/processing/app/Base.class differ diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/processing/app/Preferences.class b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/processing/app/Preferences.class new file mode 100644 index 0000000..89cf010 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/processing/app/Preferences.class differ diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/processing/app/Serial.class b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/processing/app/Serial.class new file mode 100644 index 0000000..cceccdd Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/processing/app/Serial.class differ diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/processing/app/SerialException.class b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/processing/app/SerialException.class new file mode 100644 index 0000000..71048dd Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/processing/app/SerialException.class differ diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/processing/app/debug/MessageConsumer.class b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/processing/app/debug/MessageConsumer.class new file mode 100644 index 0000000..37250e7 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/processing/app/debug/MessageConsumer.class differ diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/processing/app/debug/MessageSiphon.class b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/processing/app/debug/MessageSiphon.class new file mode 100644 index 0000000..e22c8d4 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/processing/app/debug/MessageSiphon.class differ diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/processing/app/debug/RunnerException.class b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/processing/app/debug/RunnerException.class new file mode 100644 index 0000000..710f796 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/processing/app/debug/RunnerException.class differ diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/processing/app/helpers/ProcessUtils.class b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/processing/app/helpers/ProcessUtils.class new file mode 100644 index 0000000..27eca62 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/build/classes/processing/app/helpers/ProcessUtils.class differ diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/dist/README.TXT b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/dist/README.TXT new file mode 100644 index 0000000..255b89c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/dist/README.TXT @@ -0,0 +1,32 @@ +======================== +BUILD OUTPUT DESCRIPTION +======================== + +When you build an Java application project that has a main class, the IDE +automatically copies all of the JAR +files on the projects classpath to your projects dist/lib folder. The IDE +also adds each of the JAR files to the Class-Path element in the application +JAR files manifest file (MANIFEST.MF). + +To run the project from the command line, go to the dist folder and +type the following: + +java -jar "maple_loader.jar" + +To distribute this project, zip up the dist folder (including the lib folder) +and distribute the ZIP file. + +Notes: + +* If two JAR files on the project classpath have the same name, only the first +JAR file is copied to the lib folder. +* Only JAR files are copied to the lib folder. +If the classpath contains other types of files or folders, these files (folders) +are not copied. +* If a library on the projects classpath also has a Class-Path element +specified in the manifest,the content of the Class-Path element has to be on +the projects runtime path. +* To set a main class in a standard Java project, right-click the project node +in the Projects window and choose Properties. Then click Run and enter the +class name in the Main Class field. Alternatively, you can manually type the +class name in the manifest Main-Class element. diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/dist/lib/jssc.jar b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/dist/lib/jssc.jar new file mode 100644 index 0000000..eb74f15 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/dist/lib/jssc.jar differ diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/dist/maple_loader.jar b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/dist/maple_loader.jar new file mode 100644 index 0000000..e1f9965 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/dist/maple_loader.jar differ diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/jars/jssc.jar b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/jars/jssc.jar new file mode 100644 index 0000000..eb74f15 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/jars/jssc.jar differ diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/manifest.mf b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/manifest.mf new file mode 100644 index 0000000..328e8e5 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/manifest.mf @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +X-COMMENT: Main-Class will be added automatically by build + diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/nbproject/build-impl.xml b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/nbproject/build-impl.xml new file mode 100644 index 0000000..a66f349 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/nbproject/build-impl.xml @@ -0,0 +1,1413 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set src.dir + Must set test.src.dir + Must set build.dir + Must set dist.dir + Must set build.classes.dir + Must set dist.javadoc.dir + Must set build.test.classes.dir + Must set build.test.results.dir + Must set build.classes.excludes + Must set dist.jar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + No tests executed. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set JVM to use for profiling in profiler.info.jvm + Must set profiler agent JVM arguments in profiler.info.jvmargs.agent + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + To run this application from the command line without Ant, try: + + java -jar "${dist.jar.resolved}" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set run.class + + + + Must select one file in the IDE or set run.class + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set debug.class + + + + + Must select one file in the IDE or set debug.class + + + + + Must set fix.includes + + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + Must select one file in the IDE or set profile.class + This target only works when run from inside the NetBeans IDE. + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set run.class + + + + + + Must select some files in the IDE or set test.includes + + + + + Must select one file in the IDE or set run.class + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + Some tests failed; see details above. + + + + + + + + + Must select some files in the IDE or set test.includes + + + + Some tests failed; see details above. + + + + Must select some files in the IDE or set test.class + Must select some method in the IDE or set test.method + + + + Some tests failed; see details above. + + + + + Must select one file in the IDE or set test.class + + + + Must select one file in the IDE or set test.class + Must select some method in the IDE or set test.method + + + + + + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/nbproject/genfiles.properties b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/nbproject/genfiles.properties new file mode 100644 index 0000000..c136721 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=2e6a03ba +build.xml.script.CRC32=4676ee6b +build.xml.stylesheet.CRC32=8064a381@1.75.2.48 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=2e6a03ba +nbproject/build-impl.xml.script.CRC32=392b3f79 +nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.75.2.48 diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/nbproject/private/config.properties b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/nbproject/private/config.properties new file mode 100644 index 0000000..e69de29 diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/nbproject/private/private.properties b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/nbproject/private/private.properties new file mode 100644 index 0000000..e5c9f10 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/nbproject/private/private.properties @@ -0,0 +1,6 @@ +compile.on.save=true +do.depend=false +do.jar=true +javac.debug=true +javadoc.preview=true +user.properties.file=C:\\Users\\rclark\\AppData\\Roaming\\NetBeans\\8.0.2\\build.properties diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/nbproject/private/private.xml b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/nbproject/private/private.xml new file mode 100644 index 0000000..a1bbd60 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/nbproject/private/private.xml @@ -0,0 +1,10 @@ + + + + + + file:/C:/Users/rclark/Desktop/maple-asp-master/installer/maple_loader/src/CliTemplate/CliMain.java + file:/C:/Users/rclark/Desktop/maple-asp-master/installer/maple_loader/src/CliTemplate/DFUUploader.java + + + diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/nbproject/project.properties b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/nbproject/project.properties new file mode 100644 index 0000000..7f48d71 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/nbproject/project.properties @@ -0,0 +1,79 @@ +annotation.processing.enabled=true +annotation.processing.enabled.in.editor=false +annotation.processing.processors.list= +annotation.processing.run.all.processors=true +annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output +application.title=maple_loader +application.vendor=bob +build.classes.dir=${build.dir}/classes +build.classes.excludes=**/*.java,**/*.form +# This directory is removed when the project is cleaned: +build.dir=build +build.generated.dir=${build.dir}/generated +build.generated.sources.dir=${build.dir}/generated-sources +# Only compile against the classpath explicitly listed here: +build.sysclasspath=ignore +build.test.classes.dir=${build.dir}/test/classes +build.test.results.dir=${build.dir}/test/results +# Uncomment to specify the preferred debugger connection transport: +#debug.transport=dt_socket +debug.classpath=\ + ${run.classpath} +debug.test.classpath=\ + ${run.test.classpath} +# Files in build.classes.dir which should be excluded from distribution jar +dist.archive.excludes= +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.jar=${dist.dir}/maple_loader.jar +dist.javadoc.dir=${dist.dir}/javadoc +endorsed.classpath= +excludes= +file.reference.jssc.jar=dist/lib/jssc.jar +file.reference.jssc.jar-1=jars/jssc.jar +includes=** +jar.compress=false +javac.classpath=\ + ${file.reference.jssc.jar}:\ + ${file.reference.jssc.jar-1} +# Space-separated list of extra javac options +javac.compilerargs= +javac.deprecation=false +javac.processorpath=\ + ${javac.classpath} +javac.source=1.7 +javac.target=1.7 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +javac.test.processorpath=\ + ${javac.test.classpath} +javadoc.additionalparam= +javadoc.author=false +javadoc.encoding=${source.encoding} +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +main.class=CliTemplate.CliMain +manifest.file=manifest.mf +meta.inf.dir=${src.dir}/META-INF +mkdist.disabled=false +platform.active=default_platform +run.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +# Space-separated list of JVM arguments used when running the project. +# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value. +# To set system properties for unit tests define test-sys-prop.name=value: +run.jvmargs= +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +source.encoding=UTF-8 +src.dir=src +test.src.dir=test diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/nbproject/project.xml b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/nbproject/project.xml new file mode 100644 index 0000000..92218a9 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/nbproject/project.xml @@ -0,0 +1,15 @@ + + + org.netbeans.modules.java.j2seproject + + + maple_loader + + + + + + + + + diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/CliTemplate/CliMain.java b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/CliTemplate/CliMain.java new file mode 100644 index 0000000..c7dc9f0 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/CliTemplate/CliMain.java @@ -0,0 +1,60 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package CliTemplate; + +import java.io.IOException; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import processing.app.Preferences; + +//import processing.app.I18n; +import processing.app.helpers.ProcessUtils; + +/** + * + * @author cousinr + */ +public class CliMain { + + + /** + * @param args the command line arguments + */ + public static void main(String[] args) { + + String comPort = args[0]; // + String altIf = args[1]; // + String usbID = args[2]; // "1EAF:0003"; + String binFile = args[3]; // bin file + + System.out.println("maple_loader v0.1"); + + Preferences.set ("serial.port",comPort); + Preferences.set ("serial.parity","N"); + Preferences.setInteger ("serial.databits", 8); + Preferences.setInteger ("serial.debug_rate",9600); + Preferences.setInteger ("serial.stopbits",1); + + Preferences.setInteger ("programDelay",1200); + + Preferences.set ("upload.usbID", usbID); + Preferences.set ("upload.altID", altIf); + Preferences.setBoolean ("upload.auto_reset", true); + Preferences.setBoolean ("upload.verbose", false); + + // + DFUUploader dfuUploader = new DFUUploader(); + try { + //dfuUploader.uploadViaDFU(binFile); + dfuUploader.uploadViaDFU(binFile); + } catch (Exception e) + { + System.err.print (MessageFormat.format("an error occurred! {0}\n", e.getMessage())); + } + } +} diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/CliTemplate/DFUUploader.java b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/CliTemplate/DFUUploader.java new file mode 100644 index 0000000..3dee0b4 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/CliTemplate/DFUUploader.java @@ -0,0 +1,345 @@ +/* + DFUUploader - uploader implementation using DFU + + Copyright (c) 2010 + Andrew Meyer + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +package CliTemplate; + +import java.io.BufferedReader; +import java.io.File; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import processing.app.Preferences; +import processing.app.Serial; +import processing.app.debug.MessageConsumer; +import processing.app.debug.MessageSiphon; +import processing.app.debug.RunnerException; + +/** + * + * @author bob + */ +public class DFUUploader implements MessageConsumer { + + boolean firstErrorFound; + boolean secondErrorFound; + // part of the PdeMessageConsumer interface + boolean notFoundError; + boolean verbose; + RunnerException exception; + + static final String SUPER_BADNESS = + "Compiler error!"; + + public boolean uploadUsingPreferences(String binPath, boolean verbose) + throws RunnerException { + + this.verbose = verbose; + + return uploadViaDFU(binPath); + } + + // works with old and new versions of dfu-util + private boolean found_device (String dfuData, String usbID) + { + return dfuData.contains(("Found DFU: [0x"+usbID.substring(0,4)).toUpperCase()) || + dfuData.contains(("Found DFU: ["+usbID.substring(0,4)).toUpperCase()); + } + + public boolean uploadViaDFU (String binPath) + throws RunnerException { + + this.verbose = Preferences.getBoolean ("upload.verbose"); + + /* todo, check for size overruns! */ + String fileType="bin"; + + if (fileType.equals("bin")) { + String usbID = Preferences.get("upload.usbID"); + if (usbID == null) { + /* fall back on default */ + /* this isnt great because is default Avrdude or dfu-util? */ + usbID = Preferences.get("upload.usbID"); + } + + /* if auto-reset, then emit the reset pulse on dtr/rts */ + if (Preferences.get("upload.auto_reset") != null) { + if (Preferences.get("upload.auto_reset").toLowerCase().equals("true")) { + System.out.println("Resetting to bootloader via DTR pulse"); + emitResetPulse(); + } + } else { + System.out.println("Resetting to bootloader via DTR pulse"); + emitResetPulse(); + } + + String dfuList = new String(); + List commandCheck = new ArrayList(); + commandCheck.add("dfu-util"); + commandCheck.add("-l"); + long startChecking = System.currentTimeMillis(); + System.out.println("Searching for DFU device [" + usbID + "]..."); + do { + try { + Thread.sleep(100); + } catch (InterruptedException e) {} + dfuList = executeCheckCommand(commandCheck); + //System.out.println(dfuList); + } + while ( !found_device (dfuList.toUpperCase(), usbID) && (System.currentTimeMillis() - startChecking < 7000)); + + if ( !found_device (dfuList.toUpperCase(), usbID) ) + { + System.out.println(dfuList); + System.err.println("Couldn't find the DFU device: [" + usbID + "]"); + return false; + } + System.out.println("Found it!"); + + /* todo, add handle to let user choose altIf at upload time! */ + String altIf = Preferences.get("upload.altID"); + + List commandDownloader = new ArrayList(); + commandDownloader.add("dfu-util"); + commandDownloader.add("-a "+altIf); + commandDownloader.add("-R"); + commandDownloader.add("-d "+usbID); + commandDownloader.add("-D"+ binPath); //"./thisbin.bin"); + + return executeUploadCommand(commandDownloader); + } + + System.err.println("Only .bin files are supported at this time"); + return false; + } + + /* we need to ensure both RTS and DTR are low to start, + then pulse DTR on its own. This is the reset signal + maple responds to + */ + private void emitResetPulse() throws RunnerException { + + /* wait a while for the device to reboot */ + int programDelay = Preferences.getInteger("programDelay"); + + try { + Serial serialPort = new Serial(); + + // try to toggle DTR/RTS (old scheme) + serialPort.setRTS(false); + serialPort.setDTR(false); + serialPort.setDTR(true); + try { + Thread.sleep(50); + } catch (InterruptedException e) {} + serialPort.setDTR(false); + + // try magic number + serialPort.setRTS(true); + serialPort.setDTR(true); + try { + Thread.sleep(50); + } catch (InterruptedException e) {} + serialPort.setDTR(false); + try { + Thread.sleep(50); + } catch (InterruptedException e) {} + serialPort.write("1EAF"); + try { + Thread.sleep(50); + } catch (InterruptedException e) {} + serialPort.dispose(); + + } catch(Exception e) { + System.err.println("Reset via USB Serial Failed! Did you select the right serial port?\nAssuming the board is in perpetual bootloader mode and continuing to attempt dfu programming...\n"); + } + } + + protected String executeCheckCommand(Collection commandDownloader) + throws RunnerException + { + firstErrorFound = false; // haven't found any errors yet + secondErrorFound = false; + notFoundError = false; + int result=0; // pre-initialized to quiet a bogus warning from jikes + + String userdir = System.getProperty("user.dir") + File.separator; + String returnStr = new String(); + + try { + String[] commandArray = new String[commandDownloader.size()]; + commandDownloader.toArray(commandArray); + + String armBasePath; + + //armBasePath = new String(Base.getHardwarePath() + "/tools/arm/bin/"); + armBasePath = ""; + + commandArray[0] = armBasePath + commandArray[0]; + + if (verbose || Preferences.getBoolean("upload.verbose")) { + for(int i = 0; i < commandArray.length; i++) { + System.out.print(commandArray[i] + " "); + } + System.out.println(); + } + + Process process = Runtime.getRuntime().exec(commandArray); + BufferedReader stdInput = new BufferedReader(new + InputStreamReader(process.getInputStream())); + BufferedReader stdError = new BufferedReader(new + InputStreamReader(process.getErrorStream())); + + // wait for the process to finish. if interrupted + // before waitFor returns, continue waiting + // + boolean busy = true; + while (busy) { + try { + result = process.waitFor(); + busy = false; + } catch (InterruptedException intExc) { + } + } + + String s; + while ((s = stdInput.readLine()) != null) { + returnStr += s + "\n"; + } + + process.destroy(); + + if(exception!=null) { + exception.hideStackTrace(); + throw exception; + } + if(result!=0) return "Error!"; + } catch (Exception e) { + e.printStackTrace(); + } + //System.out.println("result2 is "+result); + // if the result isn't a known, expected value it means that something + // is fairly wrong, one possibility is that jikes has crashed. + // + if (exception != null) throw exception; + + if ((result != 0) && (result != 1 )) { + exception = new RunnerException(SUPER_BADNESS); + } + + return returnStr; // ? true : false; + + } + + // Need to overload this from Uploader to use the system-wide dfu-util + protected boolean executeUploadCommand(Collection commandDownloader) + throws RunnerException + { + firstErrorFound = false; // haven't found any errors yet + secondErrorFound = false; + notFoundError = false; + int result=0; // pre-initialized to quiet a bogus warning from jikes + + String userdir = System.getProperty("user.dir") + File.separator; + + try { + String[] commandArray = new String[commandDownloader.size()]; + commandDownloader.toArray(commandArray); + + String armBasePath; + + //armBasePath = new String(Base.getHardwarePath() + "/tools/arm/bin/"); + armBasePath = ""; + + commandArray[0] = armBasePath + commandArray[0]; + + if (verbose || Preferences.getBoolean("upload.verbose")) { + for(int i = 0; i < commandArray.length; i++) { + System.out.print(commandArray[i] + " "); + } + System.out.println(); + } + + Process process = Runtime.getRuntime().exec(commandArray); + new MessageSiphon(process.getInputStream(), this); + new MessageSiphon(process.getErrorStream(), this); + + // wait for the process to finish. if interrupted + // before waitFor returns, continue waiting + // + boolean compiling = true; + while (compiling) { + try { + result = process.waitFor(); + compiling = false; + } catch (InterruptedException intExc) { + } + } + if(exception!=null) { + exception.hideStackTrace(); + throw exception; + } + if(result!=0) + return false; + } catch (Exception e) { + e.printStackTrace(); + } + //System.out.println("result2 is "+result); + // if the result isn't a known, expected value it means that something + // is fairly wrong, one possibility is that jikes has crashed. + // + if (exception != null) throw exception; + + if ((result != 0) && (result != 1 )) { + exception = new RunnerException(SUPER_BADNESS); + //editor.error(exception); + //PdeBase.openURL(BUGS_URL); + //throw new PdeException(SUPER_BADNESS); + } + + return (result == 0); // ? true : false; + + } + + // deal with messages from dfu-util... + public void message(String s) { + + if(s.indexOf("dfu-util - (C) ") != -1) { return; } + if(s.indexOf("This program is Free Software and has ABSOLUTELY NO WARRANTY") != -1) { return; } + + if(s.indexOf("No DFU capable USB device found") != -1) { + System.err.print(s); + exception = new RunnerException("Problem uploading via dfu-util: No Maple found"); + return; + } + + if(s.indexOf("Operation not perimitted") != -1) { + System.err.print(s); + exception = new RunnerException("Problem uploading via dfu-util: Insufficient privilages"); + return; + } + + // else just print everything... + System.out.print(s); + } + +} diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/CliTemplate/ExecCommand.java b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/CliTemplate/ExecCommand.java new file mode 100644 index 0000000..3d6c106 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/CliTemplate/ExecCommand.java @@ -0,0 +1,119 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package CliTemplate; + +import java.io.IOException; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.List; + +import processing.app.debug.MessageConsumer; +import processing.app.debug.MessageSiphon; +import processing.app.debug.RunnerException; +import processing.app.helpers.ProcessUtils; + +/** + * + * @author cousinr + */ +public class ExecCommand implements MessageConsumer { + + private boolean verbose = true; + private boolean firstErrorFound; + private boolean secondErrorFound; + private RunnerException exception; + + /** + * Either succeeds or throws a RunnerException fit for public consumption. + * + * @param command + * @throws RunnerException + */ + public void execAsynchronously(String[] command) throws RunnerException { + + // eliminate any empty array entries + List stringList = new ArrayList<>(); + for (String string : command) { + string = string.trim(); + if (string.length() != 0) + stringList.add(string); + } + command = stringList.toArray(new String[stringList.size()]); + if (command.length == 0) + return; + int result = 0; + + if (verbose) { + for (String c : command) + System.out.print(c + " "); + System.out.println(); + } + + firstErrorFound = false; // haven't found any errors yet + secondErrorFound = false; + + Process process; + try { + process = ProcessUtils.exec(command); + } catch (IOException e) { + RunnerException re = new RunnerException(e.getMessage()); + re.hideStackTrace(); + throw re; + } + + MessageSiphon in = new MessageSiphon(process.getInputStream(), this); + MessageSiphon err = new MessageSiphon(process.getErrorStream(), this); + + // wait for the process to finish. if interrupted + // before waitFor returns, continue waiting + boolean compiling = true; + while (compiling) { + try { + in.join(); + err.join(); + result = process.waitFor(); + //System.out.println("result is " + result); + compiling = false; + } catch (InterruptedException ignored) { } + } + + // an error was queued up by message(), barf this back to compile(), + // which will barf it back to Editor. if you're having trouble + // discerning the imagery, consider how cows regurgitate their food + // to digest it, and the fact that they have five stomaches. + // + //System.out.println("throwing up " + exception); + if (exception != null) + throw exception; + + if (result > 1) { + // a failure in the tool (e.g. unable to locate a sub-executable) + System.err.println(MessageFormat.format("{0} returned {1}", command[0], result)); + } + + if (result != 0) { + RunnerException re = new RunnerException(MessageFormat.format("exit code: {0}", result)); + re.hideStackTrace(); + throw re; + } + } + + /** + * Part of the MessageConsumer interface, this is called + * whenever a piece (usually a line) of error message is spewed + * out from the compiler. The errors are parsed for their contents + * and line number, which is then reported back to Editor. + * @param s + */ + @Override + public void message(String s) { + int i; + + + System.err.print(s); + } + +} diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/processing/app/Base.java b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/processing/app/Base.java new file mode 100644 index 0000000..c3a174d --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/processing/app/Base.java @@ -0,0 +1,53 @@ +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2004-10 Ben Fry and Casey Reas + Copyright (c) 2001-04 Massachusetts Institute of Technology + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +package processing.app; + + +/** + * The base class for the main processing application. + * Primary role of this class is for platform identification and + * general interaction with the system (launching URLs, loading + * files and images, etc) that comes from that. + */ +public class Base { + + /** + * returns true if running on windows. + */ + static public boolean isWindows() { + //return PApplet.platform == PConstants.WINDOWS; + return System.getProperty("os.name").indexOf("Windows") != -1; + } + + + /** + * true if running on linux. + */ + static public boolean isLinux() { + //return PApplet.platform == PConstants.LINUX; + return System.getProperty("os.name").indexOf("Linux") != -1; + } + + + +} diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/processing/app/Preferences.java b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/processing/app/Preferences.java new file mode 100644 index 0000000..6368e38 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/processing/app/Preferences.java @@ -0,0 +1,157 @@ +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2004-09 Ben Fry and Casey Reas + Copyright (c) 2001-04 Massachusetts Institute of Technology + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +package processing.app; + +import java.io.*; +import java.util.*; + + +/** + * Storage class for user preferences and environment settings. + *

+ * This class no longer uses the Properties class, since + * properties files are iso8859-1, which is highly likely to + * be a problem when trying to save sketch folders and locations. + *

+ * The GUI portion in here is really ugly, as it uses exact layout. This was + * done in frustration one evening (and pre-Swing), but that's long since past, + * and it should all be moved to a proper swing layout like BoxLayout. + *

+ * This is very poorly put together, that the preferences panel and the actual + * preferences i/o is part of the same code. But there hasn't yet been a + * compelling reason to bother with the separation aside from concern about + * being lectured by strangers who feel that it doesn't look like what they + * learned in CS class. + *

+ * Would also be possible to change this to use the Java Preferences API. + * Some useful articles + * here and + * here. + * However, haven't implemented this yet for lack of time, but more + * importantly, because it would entail writing to the registry (on Windows), + * or an obscure file location (on Mac OS X) and make it far more difficult to + * find the preferences to tweak them by hand (no! stay out of regedit!) + * or to reset the preferences by simply deleting the preferences.txt file. + */ +public class Preferences { + + // what to call the feller + + static final String PREFS_FILE = "preferences.txt"; + + + // prompt text stuff + + static final String PROMPT_YES = "Yes"; + static final String PROMPT_NO = "No"; + static final String PROMPT_CANCEL = "Cancel"; + static final String PROMPT_OK = "OK"; + static final String PROMPT_BROWSE = "Browse"; + + /** + * Standardized width for buttons. Mac OS X 10.3 wants 70 as its default, + * Windows XP needs 66, and my Ubuntu machine needs 80+, so 80 seems proper. + */ + static public int BUTTON_WIDTH = 80; + + /** + * Standardized button height. Mac OS X 10.3 (Java 1.4) wants 29, + * presumably because it now includes the blue border, where it didn't + * in Java 1.3. Windows XP only wants 23 (not sure what default Linux + * would be). Because of the disparity, on Mac OS X, it will be set + * inside a static block. + */ + static public int BUTTON_HEIGHT = 24; + + // value for the size bars, buttons, etc + + static final int GRID_SIZE = 33; + + + // indents and spacing standards. these probably need to be modified + // per platform as well, since macosx is so huge, windows is smaller, + // and linux is all over the map + + static final int GUI_BIG = 13; + static final int GUI_BETWEEN = 10; + static final int GUI_SMALL = 6; + + + + // data model + + static Hashtable table = new Hashtable();; + static File preferencesFile; + + + static protected void init(String commandLinePrefs) { + + + } + + + public Preferences() { + + } + + // ................................................................. + + // ................................................................. + + // ................................................................. + + // ................................................................. + + + + static public String get(String attribute) { + return (String) table.get(attribute); + } + + static public void set(String attribute, String value) { + table.put(attribute, value); + } + + + static public boolean getBoolean(String attribute) { + String value = get(attribute); + return (new Boolean(value)).booleanValue(); + } + + + static public void setBoolean(String attribute, boolean value) { + set(attribute, value ? "true" : "false"); + } + + + static public int getInteger(String attribute) { + return Integer.parseInt(get(attribute)); + } + + + static public void setInteger(String key, int value) { + set(key, String.valueOf(value)); + } + +} diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/processing/app/Serial.java b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/processing/app/Serial.java new file mode 100644 index 0000000..04566a7 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/processing/app/Serial.java @@ -0,0 +1,527 @@ +/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + PSerial - class for serial port goodness + Part of the Processing project - http://processing.org + + Copyright (c) 2004 Ben Fry & Casey Reas + + 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. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA +*/ + +package processing.app; +//import processing.core.*; + + +import java.io.*; +import java.text.MessageFormat; +import java.util.*; +import jssc.SerialPort; +import jssc.SerialPortEvent; +import jssc.SerialPortEventListener; +import jssc.SerialPortException; +import jssc.SerialPortList; +import processing.app.debug.MessageConsumer; + + +public class Serial implements SerialPortEventListener { + + //PApplet parent; + + // properties can be passed in for default values + // otherwise defaults to 9600 N81 + + // these could be made static, which might be a solution + // for the classloading problem.. because if code ran again, + // the static class would have an object that could be closed + + SerialPort port; + + int rate; + int parity; + int databits; + int stopbits; + boolean monitor = false; + + // read buffer and streams + + InputStream input; + OutputStream output; + + byte buffer[] = new byte[32768]; + int bufferIndex; + int bufferLast; + + MessageConsumer consumer; + + public Serial(boolean monitor) throws SerialException { + this(Preferences.get("serial.port"), + Preferences.getInteger("serial.debug_rate"), + Preferences.get("serial.parity").charAt(0), + Preferences.getInteger("serial.databits"), + new Float(Preferences.get("serial.stopbits")).floatValue()); + this.monitor = monitor; + } + + public Serial() throws SerialException { + this(Preferences.get("serial.port"), + Preferences.getInteger("serial.debug_rate"), + Preferences.get("serial.parity").charAt(0), + Preferences.getInteger("serial.databits"), + new Float(Preferences.get("serial.stopbits")).floatValue()); + } + + public Serial(int irate) throws SerialException { + this(Preferences.get("serial.port"), irate, + Preferences.get("serial.parity").charAt(0), + Preferences.getInteger("serial.databits"), + new Float(Preferences.get("serial.stopbits")).floatValue()); + } + + public Serial(String iname, int irate) throws SerialException { + this(iname, irate, Preferences.get("serial.parity").charAt(0), + Preferences.getInteger("serial.databits"), + new Float(Preferences.get("serial.stopbits")).floatValue()); + } + + public Serial(String iname) throws SerialException { + this(iname, Preferences.getInteger("serial.debug_rate"), + Preferences.get("serial.parity").charAt(0), + Preferences.getInteger("serial.databits"), + new Float(Preferences.get("serial.stopbits")).floatValue()); + } + + public Serial(String iname, int irate, + char iparity, int idatabits, float istopbits) + throws SerialException { + //if (port != null) port.close(); + //this.parent = parent; + //parent.attach(this); + + this.rate = irate; + + parity = SerialPort.PARITY_NONE; + if (iparity == 'E') parity = SerialPort.PARITY_EVEN; + if (iparity == 'O') parity = SerialPort.PARITY_ODD; + + this.databits = idatabits; + + stopbits = SerialPort.STOPBITS_1; + if (istopbits == 1.5f) stopbits = SerialPort.STOPBITS_1_5; + if (istopbits == 2) stopbits = SerialPort.STOPBITS_2; + + try { + port = new SerialPort(iname); + port.openPort(); + port.setParams(rate, databits, stopbits, parity, true, true); + port.addEventListener(this); + } catch (Exception e) { + throw new SerialException(MessageFormat.format("Error opening serial port ''{0}''.", iname), e); + } + + if (port == null) { + throw new SerialException("Serial port '" + iname + "' not found. Did you select the right one from the Tools > Serial Port menu?"); + } + } + + + public void setup() { + //parent.registerCall(this, DISPOSE); + } + + public void dispose() throws IOException { + if (port != null) { + try { + if (port.isOpened()) { + port.closePort(); // close the port + } + } catch (SerialPortException e) { + throw new IOException(e); + } finally { + port = null; + } + } + } + + public void addListener(MessageConsumer consumer) { + this.consumer = consumer; + } + + public synchronized void serialEvent(SerialPortEvent serialEvent) { + if (serialEvent.isRXCHAR()) { + try { + byte[] buf = port.readBytes(serialEvent.getEventValue()); + if (buf.length > 0) { + if (bufferLast == buffer.length) { + byte temp[] = new byte[bufferLast << 1]; + System.arraycopy(buffer, 0, temp, 0, bufferLast); + buffer = temp; + } + if (monitor) { + System.out.print(new String(buf)); + } + if (this.consumer != null) { + this.consumer.message(new String(buf)); + } + } + } catch (SerialPortException e) { + errorMessage("serialEvent", e); + } + } + } + + + /** + * Returns the number of bytes that have been read from serial + * and are waiting to be dealt with by the user. + */ + public synchronized int available() { + return (bufferLast - bufferIndex); + } + + + /** + * Ignore all the bytes read so far and empty the buffer. + */ + public synchronized void clear() { + bufferLast = 0; + bufferIndex = 0; + } + + + /** + * Returns a number between 0 and 255 for the next byte that's + * waiting in the buffer. + * Returns -1 if there was no byte (although the user should + * first check available() to see if things are ready to avoid this) + */ + public synchronized int read() { + if (bufferIndex == bufferLast) return -1; + + int outgoing = buffer[bufferIndex++] & 0xff; + if (bufferIndex == bufferLast) { // rewind + bufferIndex = 0; + bufferLast = 0; + } + return outgoing; + } + + + /** + * Returns the next byte in the buffer as a char. + * Returns -1, or 0xffff, if nothing is there. + */ + public synchronized char readChar() { + if (bufferIndex == bufferLast) return (char)(-1); + return (char) read(); + } + + + /** + * Return a byte array of anything that's in the serial buffer. + * Not particularly memory/speed efficient, because it creates + * a byte array on each read, but it's easier to use than + * readBytes(byte b[]) (see below). + */ + public synchronized byte[] readBytes() { + if (bufferIndex == bufferLast) return null; + + int length = bufferLast - bufferIndex; + byte outgoing[] = new byte[length]; + System.arraycopy(buffer, bufferIndex, outgoing, 0, length); + + bufferIndex = 0; // rewind + bufferLast = 0; + return outgoing; + } + + + /** + * Grab whatever is in the serial buffer, and stuff it into a + * byte buffer passed in by the user. This is more memory/time + * efficient than readBytes() returning a byte[] array. + *

+ * Returns an int for how many bytes were read. If more bytes + * are available than can fit into the byte array, only those + * that will fit are read. + */ + public synchronized int readBytes(byte outgoing[]) { + if (bufferIndex == bufferLast) return 0; + + int length = bufferLast - bufferIndex; + if (length > outgoing.length) length = outgoing.length; + System.arraycopy(buffer, bufferIndex, outgoing, 0, length); + + bufferIndex += length; + if (bufferIndex == bufferLast) { + bufferIndex = 0; // rewind + bufferLast = 0; + } + return length; + } + + + /** + * Reads from the serial port into a buffer of bytes up to and + * including a particular character. If the character isn't in + * the serial buffer, then 'null' is returned. + */ + public synchronized byte[] readBytesUntil(int interesting) { + if (bufferIndex == bufferLast) return null; + byte what = (byte)interesting; + + int found = -1; + for (int k = bufferIndex; k < bufferLast; k++) { + if (buffer[k] == what) { + found = k; + break; + } + } + if (found == -1) return null; + + int length = found - bufferIndex + 1; + byte outgoing[] = new byte[length]; + System.arraycopy(buffer, bufferIndex, outgoing, 0, length); + + bufferIndex = 0; // rewind + bufferLast = 0; + return outgoing; + } + + + /** + * Reads from the serial port into a buffer of bytes until a + * particular character. If the character isn't in the serial + * buffer, then 'null' is returned. + *

+ * If outgoing[] is not big enough, then -1 is returned, + * and an error message is printed on the console. + * If nothing is in the buffer, zero is returned. + * If 'interesting' byte is not in the buffer, then 0 is returned. + */ + public synchronized int readBytesUntil(int interesting, byte outgoing[]) { + if (bufferIndex == bufferLast) return 0; + byte what = (byte)interesting; + + int found = -1; + for (int k = bufferIndex; k < bufferLast; k++) { + if (buffer[k] == what) { + found = k; + break; + } + } + if (found == -1) return 0; + + int length = found - bufferIndex + 1; + if (length > outgoing.length) { + System.err.println("readBytesUntil() byte buffer is" + + " too small for the " + length + + " bytes up to and including char " + interesting); + return -1; + } + //byte outgoing[] = new byte[length]; + System.arraycopy(buffer, bufferIndex, outgoing, 0, length); + + bufferIndex += length; + if (bufferIndex == bufferLast) { + bufferIndex = 0; // rewind + bufferLast = 0; + } + return length; + } + + + /** + * Return whatever has been read from the serial port so far + * as a String. It assumes that the incoming characters are ASCII. + *

+ * If you want to move Unicode data, you can first convert the + * String to a byte stream in the representation of your choice + * (i.e. UTF8 or two-byte Unicode data), and send it as a byte array. + */ + public synchronized String readString() { + if (bufferIndex == bufferLast) return null; + return new String(readBytes()); + } + + + /** + * Combination of readBytesUntil and readString. See caveats in + * each function. Returns null if it still hasn't found what + * you're looking for. + *

+ * If you want to move Unicode data, you can first convert the + * String to a byte stream in the representation of your choice + * (i.e. UTF8 or two-byte Unicode data), and send it as a byte array. + */ + public synchronized String readStringUntil(int interesting) { + byte b[] = readBytesUntil(interesting); + if (b == null) return null; + return new String(b); + } + + + /** + * This will handle both ints, bytes and chars transparently. + */ + public void write(int what) { // will also cover char + try { + port.writeInt(what & 0xff); + } catch (SerialPortException e) { + errorMessage("write", e); + } + } + + + public void write(byte bytes[]) { + try { + port.writeBytes(bytes); + } catch (SerialPortException e) { + errorMessage("write", e); + } + } + + + /** + * Write a String to the output. Note that this doesn't account + * for Unicode (two bytes per char), nor will it send UTF8 + * characters.. It assumes that you mean to send a byte buffer + * (most often the case for networking and serial i/o) and + * will only use the bottom 8 bits of each char in the string. + * (Meaning that internally it uses String.getBytes) + *

+ * If you want to move Unicode data, you can first convert the + * String to a byte stream in the representation of your choice + * (i.e. UTF8 or two-byte Unicode data), and send it as a byte array. + */ + public void write(String what) { + write(what.getBytes()); + } + + public void setDTR(boolean state) { + try { + port.setDTR(state); + } catch (SerialPortException e) { + errorMessage("setDTR", e); + } + } + + public void setRTS(boolean state) { + try { + port.setRTS(state); + } catch (SerialPortException e) { + errorMessage("setRTS", e); + } + } + + static public List list() { + return Arrays.asList(SerialPortList.getPortNames()); + } + + + /** + * General error reporting, all corraled here just in case + * I think of something slightly more intelligent to do. + */ + static public void errorMessage(String where, Throwable e) { + System.err.println("Error inside Serial." + where + "()"); + e.printStackTrace(); + } +} + + + /* + class SerialMenuListener implements ItemListener { + //public SerialMenuListener() { } + + public void itemStateChanged(ItemEvent e) { + int count = serialMenu.getItemCount(); + for (int i = 0; i < count; i++) { + ((CheckboxMenuItem)serialMenu.getItem(i)).setState(false); + } + CheckboxMenuItem item = (CheckboxMenuItem)e.getSource(); + item.setState(true); + String name = item.getLabel(); + //System.out.println(item.getLabel()); + PdeBase.properties.put("serial.port", name); + //System.out.println("set to " + get("serial.port")); + } + } + */ + + + /* + protected Vector buildPortList() { + // get list of names for serial ports + // have the default port checked (if present) + Vector list = new Vector(); + + //SerialMenuListener listener = new SerialMenuListener(); + boolean problem = false; + + // if this is failing, it may be because + // lib/javax.comm.properties is missing. + // java is weird about how it searches for java.comm.properties + // so it tends to be very fragile. i.e. quotes in the CLASSPATH + // environment variable will hose things. + try { + //System.out.println("building port list"); + Enumeration portList = CommPortIdentifier.getPortIdentifiers(); + while (portList.hasMoreElements()) { + CommPortIdentifier portId = + (CommPortIdentifier) portList.nextElement(); + //System.out.println(portId); + + if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) { + //if (portId.getName().equals(port)) { + String name = portId.getName(); + //CheckboxMenuItem mi = + //new CheckboxMenuItem(name, name.equals(defaultName)); + + //mi.addItemListener(listener); + //serialMenu.add(mi); + list.addElement(name); + } + } + } catch (UnsatisfiedLinkError e) { + e.printStackTrace(); + problem = true; + + } catch (Exception e) { + System.out.println("exception building serial menu"); + e.printStackTrace(); + } + + //if (serialMenu.getItemCount() == 0) { + //System.out.println("dimming serial menu"); + //serialMenu.setEnabled(false); + //} + + // only warn them if this is the first time + if (problem && PdeBase.firstTime) { + JOptionPane.showMessageDialog(this, //frame, + "Serial port support not installed.\n" + + "Check the readme for instructions\n" + + "if you need to use the serial port. ", + "Serial Port Warning", + JOptionPane.WARNING_MESSAGE); + } + return list; + } + */ + + + diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/processing/app/SerialException.java b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/processing/app/SerialException.java new file mode 100644 index 0000000..525c240 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/processing/app/SerialException.java @@ -0,0 +1,39 @@ +/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Copyright (c) 2007 David A. Mellis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +package processing.app; + +public class SerialException extends Exception { + public SerialException() { + super(); + } + + public SerialException(String message) { + super(message); + } + + public SerialException(String message, Throwable cause) { + super(message, cause); + } + + public SerialException(Throwable cause) { + super(cause); + } +} diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/processing/app/debug/MessageConsumer.java b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/processing/app/debug/MessageConsumer.java new file mode 100644 index 0000000..5e20429 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/processing/app/debug/MessageConsumer.java @@ -0,0 +1,42 @@ +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2004-06 Ben Fry and Casey Reas + Copyright (c) 2001-04 Massachusetts Institute of Technology + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +package processing.app.debug; + + +/** + * Interface for dealing with parser/compiler output. + *

+ * Different instances of MessageStream need to do different things with + * messages. In particular, a stream instance used for parsing output from + * the compiler compiler has to interpret its messages differently than one + * parsing output from the runtime. + *

+ * Classes which consume messages and do something with them + * should implement this interface. + */ +public interface MessageConsumer { + + public void message(String s); + +} diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/processing/app/debug/MessageSiphon.java b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/processing/app/debug/MessageSiphon.java new file mode 100644 index 0000000..26901c3 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/processing/app/debug/MessageSiphon.java @@ -0,0 +1,104 @@ +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2004-06 Ben Fry and Casey Reas + Copyright (c) 2001-04 Massachusetts Institute of Technology + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +package processing.app.debug; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.SocketException; + +/** + * Slurps up messages from compiler. + */ +public class MessageSiphon implements Runnable { + + private final BufferedReader streamReader; + private final MessageConsumer consumer; + + private Thread thread; + private boolean canRun; + + public MessageSiphon(InputStream stream, MessageConsumer consumer) { + this.streamReader = new BufferedReader(new InputStreamReader(stream)); + this.consumer = consumer; + this.canRun = true; + + thread = new Thread(this); + // don't set priority too low, otherwise exceptions won't + // bubble up in time (i.e. compile errors have a weird delay) + //thread.setPriority(Thread.MIN_PRIORITY); + thread.setPriority(Thread.MAX_PRIORITY - 1); + thread.start(); + } + + + public void run() { + try { + // process data until we hit EOF; this will happily block + // (effectively sleeping the thread) until new data comes in. + // when the program is finally done, null will come through. + // + String currentLine; + while (canRun && (currentLine = streamReader.readLine()) != null) { + // \n is added again because readLine() strips it out + //EditorConsole.systemOut.println("messaging in"); + consumer.message(currentLine + "\n"); + //EditorConsole.systemOut.println("messaging out"); + } + //EditorConsole.systemOut.println("messaging thread done"); + } catch (NullPointerException npe) { + // Fairly common exception during shutdown + } catch (SocketException e) { + // socket has been close while we were wainting for data. nothing to see here, move along + } catch (Exception e) { + // On Linux and sometimes on Mac OS X, a "bad file descriptor" + // message comes up when closing an applet that's run externally. + // That message just gets supressed here.. + String mess = e.getMessage(); + if ((mess != null) && + (mess.indexOf("Bad file descriptor") != -1)) { + //if (e.getMessage().indexOf("Bad file descriptor") == -1) { + //System.err.println("MessageSiphon err " + e); + //e.printStackTrace(); + } else { + e.printStackTrace(); + } + } finally { + thread = null; + } + } + + // Wait until the MessageSiphon thread is complete. + public void join() throws java.lang.InterruptedException { + // Grab a temp copy in case another thread nulls the "thread" + // member variable + Thread t = thread; + if (t != null) t.join(); + } + + public void stop() { + this.canRun = false; + } + +} diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/processing/app/debug/RunnerException.java b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/processing/app/debug/RunnerException.java new file mode 100644 index 0000000..0a67d1e --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/processing/app/debug/RunnerException.java @@ -0,0 +1,161 @@ +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2004-08 Ben Fry and Casey Reas + Copyright (c) 2001-04 Massachusetts Institute of Technology + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +package processing.app.debug; + + +/** + * An exception with a line number attached that occurs + * during either compile time or run time. + */ +@SuppressWarnings("serial") +public class RunnerException extends Exception { + protected String message; + protected int codeIndex; + protected int codeLine; + protected int codeColumn; + protected boolean showStackTrace; + + + public RunnerException(String message) { + this(message, true); + } + + public RunnerException(String message, boolean showStackTrace) { + this(message, -1, -1, -1, showStackTrace); + } + + public RunnerException(String message, int file, int line) { + this(message, file, line, -1, true); + } + + + public RunnerException(String message, int file, int line, int column) { + this(message, file, line, column, true); + } + + + public RunnerException(String message, int file, int line, int column, + boolean showStackTrace) { + this.message = message; + this.codeIndex = file; + this.codeLine = line; + this.codeColumn = column; + this.showStackTrace = showStackTrace; + } + + + public RunnerException(Exception e) { + super(e); + this.showStackTrace = true; + } + + /** + * Override getMessage() in Throwable, so that I can set + * the message text outside the constructor. + */ + public String getMessage() { + return message; + } + + + public void setMessage(String message) { + this.message = message; + } + + + public int getCodeIndex() { + return codeIndex; + } + + + public void setCodeIndex(int index) { + codeIndex = index; + } + + + public boolean hasCodeIndex() { + return codeIndex != -1; + } + + + public int getCodeLine() { + return codeLine; + } + + + public void setCodeLine(int line) { + this.codeLine = line; + } + + + public boolean hasCodeLine() { + return codeLine != -1; + } + + + public void setCodeColumn(int column) { + this.codeColumn = column; + } + + + public int getCodeColumn() { + return codeColumn; + } + + + public void showStackTrace() { + showStackTrace = true; + } + + + public void hideStackTrace() { + showStackTrace = false; + } + + + /** + * Nix the java.lang crap out of an exception message + * because it scares the children. + *

+ * This function must be static to be used with super() + * in each of the constructors above. + */ + /* + static public final String massage(String msg) { + if (msg.indexOf("java.lang.") == 0) { + //int dot = msg.lastIndexOf('.'); + msg = msg.substring("java.lang.".length()); + } + return msg; + //return (dot == -1) ? msg : msg.substring(dot+1); + } + */ + + + public void printStackTrace() { + if (showStackTrace) { + super.printStackTrace(); + } + } +} diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/processing/app/helpers/ProcessUtils.java b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/processing/app/helpers/ProcessUtils.java new file mode 100644 index 0000000..c023f58 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/maple_loader/src/processing/app/helpers/ProcessUtils.java @@ -0,0 +1,32 @@ +package processing.app.helpers; + +//import processing.app.Base; + +import java.io.IOException; +import java.util.Map; + +import processing.app.Base; + +public class ProcessUtils { + + public static Process exec(String[] command) throws IOException { + // No problems on linux and mac + if (!Base.isWindows()) { + return Runtime.getRuntime().exec(command); + } + + // Brutal hack to workaround windows command line parsing. + // http://stackoverflow.com/questions/5969724/java-runtime-exec-fails-to-escape-characters-properly + // http://msdn.microsoft.com/en-us/library/a1y7w461.aspx + // http://bugs.sun.com/view_bug.do?bug_id=6468220 + // http://bugs.sun.com/view_bug.do?bug_id=6518827 + String[] cmdLine = new String[command.length]; + for (int i = 0; i < command.length; i++) + cmdLine[i] = command[i].replace("\"", "\\\""); + + ProcessBuilder pb = new ProcessBuilder(cmdLine); + Map env = pb.environment(); + env.put("CYGWIN", "nodosfilewarning"); + return pb.start(); + } +} diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/AUTHORS b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/AUTHORS new file mode 100644 index 0000000..d096f22 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/AUTHORS @@ -0,0 +1,19 @@ +Authors ordered by first contribution. + +Geoffrey McRae +Bret Olmsted +Tormod Volden +Jakob Malm +Reuben Dowle +Matthias Kubisch +Paul Fertser +Daniel Strnad +Jérémie Rapin +Christian Pointner +Mats Erik Andersson +Alexey Borovik +Antonio Borneo +Armin van der Togt +Brian Silverman +Georg Hofmann +Luis Rodrigues diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/Android.mk b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/Android.mk new file mode 100644 index 0000000..7be3d00 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/Android.mk @@ -0,0 +1,20 @@ +TOP_LOCAL_PATH := $(call my-dir) + +include $(call all-named-subdir-makefiles, parsers) + +LOCAL_PATH := $(TOP_LOCAL_PATH) + +include $(CLEAR_VARS) +LOCAL_MODULE := stm32flash +LOCAL_SRC_FILES := \ + dev_table.c \ + i2c.c \ + init.c \ + main.c \ + port.c \ + serial_common.c \ + serial_platform.c \ + stm32.c \ + utils.c +LOCAL_STATIC_LIBRARIES := libparsers +include $(BUILD_EXECUTABLE) diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/HOWTO b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/HOWTO new file mode 100644 index 0000000..d8f32eb --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/HOWTO @@ -0,0 +1,35 @@ +Add new interfaces: +===================================================================== +Current version 0.4 supports the following interfaces: +- UART Windows (either "COMn" and "\\.\COMn"); +- UART posix/Linux (e.g. "/dev/ttyUSB0"); +- I2C Linux through standard driver "i2c-dev" (e.g. "/dev/i2c-n"). + +Starting from version 0.4, the back-end of stm32flash is modular and +ready to be expanded to support new interfaces. +I'm planning adding SPI on Linux through standard driver "spidev". +You are invited to contribute with more interfaces. + +To add a new interface you need to add a new file, populate the struct +port_interface (check at the end of files i2c.c, serial_posix.c and +serial_w32.c) and provide the relative functions to operate on the +interface: open/close, read/write, get_cfg_str and the optional gpio. +The include the new drive in Makefile and register the new struct +port_interface in file port.c in struct port_interface *ports[]. + +There are several USB-I2C adapter in the market, each providing its +own libraries to communicate with the I2C bus. +Could be interesting to provide as back-end a bridge between stm32flash +and such libraries (I have no plan on this item). + + +Add new STM32 devices: +===================================================================== +Add a new line in file dev_table.c, in table devices[]. +The fields of the table are listed in stm32.h, struct stm32_dev. + + +Cross compile on Linux host for Windows target with MinGW: +===================================================================== +I'm using a 64 bit Arch Linux machines, and I usually run: + make CC=x86_64-w64-mingw32-gcc AR=x86_64-w64-mingw32-ar diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/I2C.txt b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/I2C.txt new file mode 100644 index 0000000..4c05ff6 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/I2C.txt @@ -0,0 +1,94 @@ +About I2C back-end communication in stm32flash +========================================================================== + +Starting from version v0.4, beside the serial communication port, +stm32flash adds support for I2C port to talk with STM32 bootloader. + +The current I2C back-end supports only the API provided by Linux kernel +driver "i2c-dev", so only I2C controllers with Linux kernel driver can be +used. +In Linux source code, most of the drivers for I2C and SMBUS controllers +are in + ./drivers/i2c/busses/ +Only I2C is supported by STM32 bootloader, so check the section below +about SMBUS. +No I2C support for Windows is available in stm32flash v0.4. + +Thanks to the new modular back-end, stm32flash can be easily extended to +support new back-ends and API. Check HOWTO file in stm32flash source code +for details. + +In the market there are several USB-to-I2C dongles; most of them are not +supported by kernel drivers. Manufacturer provide proprietary userspace +libraries using not standardized API. +These API and dongles could be supported in feature versions. + +There are currently 3 versions of STM32 bootloader for I2C communications: +- v1.0 using I2C clock stretching synchronization between host and STM32; +- v1.1 superset of v1.0, adds non stretching commands; +- v1.2 superset of v1.1, adds CRC command and compatibility with i2cdetect. +Details in ST application note AN2606. +All the bootloaders above are tested and working with stm32flash. + + +SMBUS controllers +========================================================================== + +Almost 50% of the drivers in Linux source code folder + ./drivers/i2c/busses/ +are for controllers that "only" support SMBUS protocol. They can NOT +operate with STM32 bootloader. +To identify if your controller supports I2C, use command: + i2cdetect -F n +where "n" is the number of the I2C interface (e.g. n=3 for "/dev/i2c-3"). +Controllers that supports I2C will report + I2C yes +Controller that support both I2C and SMBUS are ok. + +If you are interested on details about SMBUS protocol, you can download +the current specs from + http://smbus.org/specs/smbus20.pdf +and you can read the files in Linux source code + ./Documentation/i2c/i2c-protocol + ./Documentation/i2c/smbus-protocol + + +About bootloader v1.0 +========================================================================== + +Version v1.0 can have issues with some I2C controllers due to use of clock +stretching during commands that require long operations, like flash erase +and programming. + +Clock stretching is a technique to synchronize host and I2C device. When +I2C device wants to force a delay in the communication, it push "low" the +I2C clock; the I2C controller detects it and waits until I2C clock returns +"high". +Most I2C controllers set a "timeout" for clock stretching, ranging from +few milli-seconds to seconds depending on specific HW or SW driver. + +It is possible that the timeout in your I2C controller is smaller than the +delay required for flash erase or programming. In this case the I2C +controller will timeout and report error to stm32flash. +There is no possibility for stm32flash to retry, so it can only signal the +error and exit. + +To by-pass the issue with bootloader v1.0 you can modify the kernel driver +of your I2C controller. Not an easy job, since every controller has its own +way to handle the timeout. + +In my case I'm using the I2C controller integrated in the VGA port of my +laptop HP EliteBook 8460p. I built the 0.25$ VGA-to-I2C adapter reported in + http://www.paintyourdragon.com/?p=43 +To change the timeout of the I2C controller I had to modify the kernel file + drivers/gpu/drm/radeon/radeon_i2c.c +line 969 +- i2c->bit.timeout = usecs_to_jiffies(2200); /* from VESA */ ++ i2c->bit.timeout = msecs_to_jiffies(5000); /* 5s for STM32 */ +and recompile it. +Then + $> modprobe i2c-dev + $> chmod 666 /dev/i2c-7 + #> stm32flash -a 0x39 /dev/i2c-7 + +2014-09-16 Antonio Borneo diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/Makefile b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/Makefile new file mode 100644 index 0000000..0328d55 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/Makefile @@ -0,0 +1,38 @@ +PREFIX = /usr/local +CFLAGS += -Wall -g + +INSTALL = install + +OBJS = dev_table.o \ + i2c.o \ + init.o \ + main.o \ + port.o \ + serial_common.o \ + serial_platform.o \ + stm32.o \ + utils.o + +LIBOBJS = parsers/parsers.a + +all: stm32flash + +serial_platform.o: serial_posix.c serial_w32.c + +parsers/parsers.a: + cd parsers && $(MAKE) parsers.a + +stm32flash: $(OBJS) $(LIBOBJS) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBOBJS) + +clean: + rm -f $(OBJS) stm32flash + cd parsers && $(MAKE) $@ + +install: all + $(INSTALL) -d $(DESTDIR)$(PREFIX)/bin + $(INSTALL) -m 755 stm32flash $(DESTDIR)$(PREFIX)/bin + $(INSTALL) -d $(DESTDIR)$(PREFIX)/share/man/man1 + $(INSTALL) -m 644 stm32flash.1 $(DESTDIR)$(PREFIX)/share/man/man1 + +.PHONY: all clean install diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/TODO b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/TODO new file mode 100644 index 0000000..41df614 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/TODO @@ -0,0 +1,7 @@ + +stm32: +- Add support for variable page size + +AUTHORS: +- Add contributors from Geoffrey's commits + diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/dev_table.c b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/dev_table.c new file mode 100644 index 0000000..399cd9d --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/dev_table.c @@ -0,0 +1,70 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + Copyright (C) 2014 Antonio Borneo + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "stm32.h" + +/* + * Device table, corresponds to the "Bootloader device-dependant parameters" + * table in ST document AN2606. + * Note that the option bytes upper range is inclusive! + */ +const stm32_dev_t devices[] = { + /* F0 */ + {0x440, "STM32F051xx" , 0x20001000, 0x20002000, 0x08000000, 0x08010000, 4, 1024, 0x1FFFF800, 0x1FFFF80B, 0x1FFFEC00, 0x1FFFF800}, + {0x444, "STM32F030/F031" , 0x20001000, 0x20002000, 0x08000000, 0x08010000, 4, 1024, 0x1FFFF800, 0x1FFFF80B, 0x1FFFEC00, 0x1FFFF800}, + {0x445, "STM32F042xx" , 0x20001800, 0x20001800, 0x08000000, 0x08008000, 4, 1024, 0x1FFFF800, 0x1FFFF80F, 0x1FFFC400, 0x1FFFF800}, + {0x448, "STM32F072xx" , 0x20001800, 0x20004000, 0x08000000, 0x08020000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFC800, 0x1FFFF800}, + /* F1 */ + {0x412, "Low-density" , 0x20000200, 0x20002800, 0x08000000, 0x08008000, 4, 1024, 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800}, + {0x410, "Medium-density" , 0x20000200, 0x20005000, 0x08000000, 0x08020000, 4, 1024, 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800}, + {0x414, "High-density" , 0x20000200, 0x20010000, 0x08000000, 0x08080000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800}, + {0x420, "Medium-density VL" , 0x20000200, 0x20002000, 0x08000000, 0x08020000, 4, 1024, 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800}, + {0x428, "High-density VL" , 0x20000200, 0x20008000, 0x08000000, 0x08080000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800}, + {0x418, "Connectivity line" , 0x20001000, 0x20010000, 0x08000000, 0x08040000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFB000, 0x1FFFF800}, + {0x430, "XL-density" , 0x20000800, 0x20018000, 0x08000000, 0x08100000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFE000, 0x1FFFF800}, + /* Note that F2 and F4 devices have sectors of different page sizes + and only the first sectors (of one page size) are included here */ + /* F2 */ + {0x411, "STM32F2xx" , 0x20002000, 0x20020000, 0x08000000, 0x08100000, 4, 16384, 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF77DF}, + /* F3 */ + {0x432, "STM32F373/8" , 0x20001400, 0x20008000, 0x08000000, 0x08040000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFD800, 0x1FFFF800}, + {0x422, "F302xB/303xB/358" , 0x20001400, 0x20010000, 0x08000000, 0x08040000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFD800, 0x1FFFF800}, + {0x439, "STM32F302x4(6/8)" , 0x20001800, 0x20004000, 0x08000000, 0x08040000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFD800, 0x1FFFF800}, + {0x438, "F303x4/334/328" , 0x20001800, 0x20003000, 0x08000000, 0x08040000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFD800, 0x1FFFF800}, + /* F4 */ + {0x413, "STM32F40/1" , 0x20002000, 0x20020000, 0x08000000, 0x08100000, 4, 16384, 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF77DF}, + /* 0x419 is also used for STM32F429/39 but with other bootloader ID... */ + {0x419, "STM32F427/37" , 0x20002000, 0x20030000, 0x08000000, 0x08100000, 4, 16384, 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF77FF}, + {0x423, "STM32F401xB(C)" , 0x20003000, 0x20010000, 0x08000000, 0x08100000, 4, 16384, 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF77FF}, + {0x433, "STM32F401xD(E)" , 0x20003000, 0x20018000, 0x08000000, 0x08100000, 4, 16384, 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF77FF}, + /* L0 */ + {0x417, "L05xxx/06xxx" , 0x20001000, 0x20002000, 0x08000000, 0x08010000, 32, 128, 0x1FF80000, 0x1FF8000F, 0x1FF00000, 0x1FF01000}, + /* L1 */ + {0x416, "L1xxx6(8/B)" , 0x20000800, 0x20004000, 0x08000000, 0x08020000, 16, 256, 0x1FF80000, 0x1FF8000F, 0x1FF00000, 0x1FF01000}, + {0x429, "L1xxx6(8/B)A" , 0x20001000, 0x20008000, 0x08000000, 0x08020000, 16, 256, 0x1FF80000, 0x1FF8000F, 0x1FF00000, 0x1FF01000}, + {0x427, "L1xxxC" , 0x20001000, 0x20008000, 0x08000000, 0x08020000, 16, 256, 0x1FF80000, 0x1FF8000F, 0x1FF00000, 0x1FF02000}, + {0x436, "L1xxxD" , 0x20001000, 0x2000C000, 0x08000000, 0x08060000, 16, 256, 0x1ff80000, 0x1ff8000F, 0x1FF00000, 0x1FF02000}, + {0x437, "L1xxxE" , 0x20001000, 0x20014000, 0x08000000, 0x08060000, 16, 256, 0x1ff80000, 0x1ff8000F, 0x1FF00000, 0x1FF02000}, + /* These are not (yet) in AN2606: */ + {0x641, "Medium_Density PL" , 0x20000200, 0x00005000, 0x08000000, 0x08020000, 4, 1024, 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800}, + {0x9a8, "STM32W-128K" , 0x20000200, 0x20002000, 0x08000000, 0x08020000, 1, 1024, 0, 0, 0, 0}, + {0x9b0, "STM32W-256K" , 0x20000200, 0x20004000, 0x08000000, 0x08040000, 1, 2048, 0, 0, 0, 0}, + {0x0} +}; diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/gpl-2.0.txt b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/gpl-2.0.txt new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/gpl-2.0.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/i2c.c b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/i2c.c new file mode 100644 index 0000000..10e6bb1 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/i2c.c @@ -0,0 +1,209 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2014 Antonio Borneo + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "serial.h" +#include "port.h" + + +#if !defined(__linux__) + +static port_err_t i2c_open(struct port_interface *port, + struct port_options *ops) +{ + return PORT_ERR_NODEV; +} + +struct port_interface port_i2c = { + .name = "i2c", + .open = i2c_open, +}; + +#else + +#ifdef __ANDROID__ +#define I2C_SLAVE 0x0703 /* Use this slave address */ +#define I2C_FUNCS 0x0705 /* Get the adapter functionality mask */ +/* To determine what functionality is present */ +#define I2C_FUNC_I2C 0x00000001 +#else +#include +#include +#endif + +#include + +struct i2c_priv { + int fd; + int addr; +}; + +static port_err_t i2c_open(struct port_interface *port, + struct port_options *ops) +{ + struct i2c_priv *h; + int fd, addr, ret; + unsigned long funcs; + + /* 1. check device name match */ + if (strncmp(ops->device, "/dev/i2c-", strlen("/dev/i2c-"))) + return PORT_ERR_NODEV; + + /* 2. check options */ + addr = ops->bus_addr; + if (addr < 0x03 || addr > 0x77) { + fprintf(stderr, "I2C address out of range [0x03-0x77]\n"); + return PORT_ERR_UNKNOWN; + } + + /* 3. open it */ + h = calloc(sizeof(*h), 1); + if (h == NULL) { + fprintf(stderr, "End of memory\n"); + return PORT_ERR_UNKNOWN; + } + fd = open(ops->device, O_RDWR); + if (fd < 0) { + fprintf(stderr, "Unable to open special file \"%s\"\n", + ops->device); + free(h); + return PORT_ERR_UNKNOWN; + } + + /* 3.5. Check capabilities */ + ret = ioctl(fd, I2C_FUNCS, &funcs); + if (ret < 0) { + fprintf(stderr, "I2C ioctl(funcs) error %d\n", errno); + close(fd); + free(h); + return PORT_ERR_UNKNOWN; + } + if ((funcs & I2C_FUNC_I2C) == 0) { + fprintf(stderr, "Error: controller is not I2C, only SMBUS.\n"); + close(fd); + free(h); + return PORT_ERR_UNKNOWN; + } + + /* 4. set options */ + ret = ioctl(fd, I2C_SLAVE, addr); + if (ret < 0) { + fprintf(stderr, "I2C ioctl(slave) error %d\n", errno); + close(fd); + free(h); + return PORT_ERR_UNKNOWN; + } + + h->fd = fd; + h->addr = addr; + port->private = h; + return PORT_ERR_OK; +} + +static port_err_t i2c_close(struct port_interface *port) +{ + struct i2c_priv *h; + + h = (struct i2c_priv *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + close(h->fd); + free(h); + port->private = NULL; + return PORT_ERR_OK; +} + +static port_err_t i2c_read(struct port_interface *port, void *buf, + size_t nbyte) +{ + struct i2c_priv *h; + int ret; + + h = (struct i2c_priv *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + ret = read(h->fd, buf, nbyte); + if (ret != nbyte) + return PORT_ERR_UNKNOWN; + return PORT_ERR_OK; +} + +static port_err_t i2c_write(struct port_interface *port, void *buf, + size_t nbyte) +{ + struct i2c_priv *h; + int ret; + + h = (struct i2c_priv *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + ret = write(h->fd, buf, nbyte); + if (ret != nbyte) + return PORT_ERR_UNKNOWN; + return PORT_ERR_OK; +} + +static port_err_t i2c_gpio(struct port_interface *port, serial_gpio_t n, + int level) +{ + return PORT_ERR_OK; +} + +static const char *i2c_get_cfg_str(struct port_interface *port) +{ + struct i2c_priv *h; + static char str[11]; + + h = (struct i2c_priv *)port->private; + if (h == NULL) + return "INVALID"; + snprintf(str, sizeof(str), "addr 0x%2x", h->addr); + return str; +} + +static struct varlen_cmd i2c_cmd_get_reply[] = { + {0x10, 11}, + {0x11, 17}, + {0x12, 18}, + { /* sentinel */ } +}; + +struct port_interface port_i2c = { + .name = "i2c", + .flags = PORT_STRETCH_W, + .open = i2c_open, + .close = i2c_close, + .read = i2c_read, + .write = i2c_write, + .gpio = i2c_gpio, + .cmd_get_reply = i2c_cmd_get_reply, + .get_cfg_str = i2c_get_cfg_str, +}; + +#endif diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/init.c b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/init.c new file mode 100644 index 0000000..77a571b --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/init.c @@ -0,0 +1,219 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + Copyright (C) 2013 Antonio Borneo + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include "init.h" +#include "serial.h" +#include "stm32.h" +#include "port.h" + +struct gpio_list { + struct gpio_list *next; + int gpio; +}; + + +static int write_to(const char *filename, const char *value) +{ + int fd, ret; + + fd = open(filename, O_WRONLY); + if (fd < 0) { + fprintf(stderr, "Cannot open file \"%s\"\n", filename); + return 0; + } + ret = write(fd, value, strlen(value)); + if (ret < 0) { + fprintf(stderr, "Error writing in file \"%s\"\n", filename); + close(fd); + return 0; + } + close(fd); + return 1; +} + +#if !defined(__linux__) +static int drive_gpio(int n, int level, struct gpio_list **gpio_to_release) +{ + fprintf(stderr, "GPIO control only available in Linux\n"); + return 0; +} +#else +static int drive_gpio(int n, int level, struct gpio_list **gpio_to_release) +{ + char num[16]; /* sized to carry MAX_INT */ + char file[48]; /* sized to carry longest filename */ + struct stat buf; + struct gpio_list *new; + int ret; + + sprintf(file, "/sys/class/gpio/gpio%d/direction", n); + ret = stat(file, &buf); + if (ret) { + /* file miss, GPIO not exported yet */ + sprintf(num, "%d", n); + ret = write_to("/sys/class/gpio/export", num); + if (!ret) + return 0; + ret = stat(file, &buf); + if (ret) { + fprintf(stderr, "GPIO %d not available\n", n); + return 0; + } + new = (struct gpio_list *)malloc(sizeof(struct gpio_list)); + if (new == NULL) { + fprintf(stderr, "Out of memory\n"); + return 0; + } + new->gpio = n; + new->next = *gpio_to_release; + *gpio_to_release = new; + } + + return write_to(file, level ? "high" : "low"); +} +#endif + +static int release_gpio(int n) +{ + char num[16]; /* sized to carry MAX_INT */ + + sprintf(num, "%d", n); + return write_to("/sys/class/gpio/unexport", num); +} + +static int gpio_sequence(struct port_interface *port, const char *s, size_t l) +{ + struct gpio_list *gpio_to_release = NULL, *to_free; + int ret, level, gpio; + + ret = 1; + while (ret == 1 && *s && l > 0) { + if (*s == '-') { + level = 0; + s++; + l--; + } else + level = 1; + + if (isdigit(*s)) { + gpio = atoi(s); + while (isdigit(*s)) { + s++; + l--; + } + } else if (!strncmp(s, "rts", 3)) { + gpio = -GPIO_RTS; + s += 3; + l -= 3; + } else if (!strncmp(s, "dtr", 3)) { + gpio = -GPIO_DTR; + s += 3; + l -= 3; + } else if (!strncmp(s, "brk", 3)) { + gpio = -GPIO_BRK; + s += 3; + l -= 3; + } else { + fprintf(stderr, "Character \'%c\' is not a digit\n", *s); + ret = 0; + break; + } + + if (*s && (l > 0)) { + if (*s == ',') { + s++; + l--; + } else { + fprintf(stderr, "Character \'%c\' is not a separator\n", *s); + ret = 0; + break; + } + } + if (gpio < 0) + ret = (port->gpio(port, -gpio, level) == PORT_ERR_OK); + else + ret = drive_gpio(gpio, level, &gpio_to_release); + usleep(100000); + } + + while (gpio_to_release) { + release_gpio(gpio_to_release->gpio); + to_free = gpio_to_release; + gpio_to_release = gpio_to_release->next; + free(to_free); + } + usleep(500000); + return ret; +} + +static int gpio_bl_entry(struct port_interface *port, const char *seq) +{ + char *s; + + if (seq == NULL || seq[0] == ':') + return 1; + + s = strchr(seq, ':'); + if (s == NULL) + return gpio_sequence(port, seq, strlen(seq)); + + return gpio_sequence(port, seq, s - seq); +} + +static int gpio_bl_exit(struct port_interface *port, const char *seq) +{ + char *s; + + if (seq == NULL) + return 1; + + s = strchr(seq, ':'); + if (s == NULL || s[1] == '\0') + return 1; + + return gpio_sequence(port, s + 1, strlen(s + 1)); +} + +int init_bl_entry(struct port_interface *port, const char *seq) +{ + if (seq) + return gpio_bl_entry(port, seq); + + return 1; +} + +int init_bl_exit(stm32_t *stm, struct port_interface *port, const char *seq) +{ + if (seq) + return gpio_bl_exit(port, seq); + + if (stm32_reset_device(stm) != STM32_ERR_OK) + return 0; + return 1; +} diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/init.h b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/init.h new file mode 100644 index 0000000..6075b51 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/init.h @@ -0,0 +1,31 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + Copyright (C) 2013 Antonio Borneo + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _INIT_H +#define _INIT_H + +#include "stm32.h" +#include "port.h" + +int init_bl_entry(struct port_interface *port, const char *seq); +int init_bl_exit(stm32_t *stm, struct port_interface *port, const char *seq); + +#endif diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/main.c b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/main.c new file mode 100644 index 0000000..f081d61 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/main.c @@ -0,0 +1,774 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright 2010 Geoffrey McRae + Copyright 2011 Steve Markgraf + Copyright 2012 Tormod Volden + Copyright 2013 Antonio Borneo + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "init.h" +#include "utils.h" +#include "serial.h" +#include "stm32.h" +#include "parsers/parser.h" +#include "port.h" + +#include "parsers/binary.h" +#include "parsers/hex.h" + +#define VERSION "Arduino_STM32_0.9" + +/* device globals */ +stm32_t *stm = NULL; + +void *p_st = NULL; +parser_t *parser = NULL; + +/* settings */ +struct port_options port_opts = { + .device = NULL, + .baudRate = SERIAL_BAUD_57600, + .serial_mode = "8e1", + .bus_addr = 0, + .rx_frame_max = STM32_MAX_RX_FRAME, + .tx_frame_max = STM32_MAX_TX_FRAME, +}; +int rd = 0; +int wr = 0; +int wu = 0; +int rp = 0; +int ur = 0; +int eraseOnly = 0; +int crc = 0; +int npages = 0; +int spage = 0; +int no_erase = 0; +char verify = 0; +int retry = 10; +char exec_flag = 0; +uint32_t execute = 0; +char init_flag = 1; +char force_binary = 0; +char reset_flag = 0; +char *filename; +char *gpio_seq = NULL; +uint32_t start_addr = 0; +uint32_t readwrite_len = 0; + +/* functions */ +int parse_options(int argc, char *argv[]); +void show_help(char *name); + +static int is_addr_in_ram(uint32_t addr) +{ + return addr >= stm->dev->ram_start && addr < stm->dev->ram_end; +} + +static int is_addr_in_flash(uint32_t addr) +{ + return addr >= stm->dev->fl_start && addr < stm->dev->fl_end; +} + +static int flash_addr_to_page_floor(uint32_t addr) +{ + if (!is_addr_in_flash(addr)) + return 0; + + return (addr - stm->dev->fl_start) / stm->dev->fl_ps; +} + +static int flash_addr_to_page_ceil(uint32_t addr) +{ + if (!(addr >= stm->dev->fl_start && addr <= stm->dev->fl_end)) + return 0; + + return (addr + stm->dev->fl_ps - 1 - stm->dev->fl_start) + / stm->dev->fl_ps; +} + +static uint32_t flash_page_to_addr(int page) +{ + return stm->dev->fl_start + page * stm->dev->fl_ps; +} + +int main(int argc, char* argv[]) { + struct port_interface *port = NULL; + int ret = 1; + stm32_err_t s_err; + parser_err_t perr; + FILE *diag = stdout; + + fprintf(diag, "stm32flash " VERSION "\n\n"); + fprintf(diag, "http://github.com/rogerclarkmelbourne/arduino_stm32\n\n"); + if (parse_options(argc, argv) != 0) + goto close; + + if (rd && filename[0] == '-') { + diag = stderr; + } + + if (wr) { + /* first try hex */ + if (!force_binary) { + parser = &PARSER_HEX; + p_st = parser->init(); + if (!p_st) { + fprintf(stderr, "%s Parser failed to initialize\n", parser->name); + goto close; + } + } + + if (force_binary || (perr = parser->open(p_st, filename, 0)) != PARSER_ERR_OK) { + if (force_binary || perr == PARSER_ERR_INVALID_FILE) { + if (!force_binary) { + parser->close(p_st); + p_st = NULL; + } + + /* now try binary */ + parser = &PARSER_BINARY; + p_st = parser->init(); + if (!p_st) { + fprintf(stderr, "%s Parser failed to initialize\n", parser->name); + goto close; + } + perr = parser->open(p_st, filename, 0); + } + + /* if still have an error, fail */ + if (perr != PARSER_ERR_OK) { + fprintf(stderr, "%s ERROR: %s\n", parser->name, parser_errstr(perr)); + if (perr == PARSER_ERR_SYSTEM) perror(filename); + goto close; + } + } + + fprintf(diag, "Using Parser : %s\n", parser->name); + } else { + parser = &PARSER_BINARY; + p_st = parser->init(); + if (!p_st) { + fprintf(stderr, "%s Parser failed to initialize\n", parser->name); + goto close; + } + } + + if (port_open(&port_opts, &port) != PORT_ERR_OK) { + fprintf(stderr, "Failed to open port: %s\n", port_opts.device); + goto close; + } + + fprintf(diag, "Interface %s: %s\n", port->name, port->get_cfg_str(port)); + if (init_flag && init_bl_entry(port, gpio_seq) == 0) + goto close; + stm = stm32_init(port, init_flag); + if (!stm) + goto close; + + fprintf(diag, "Version : 0x%02x\n", stm->bl_version); + if (port->flags & PORT_GVR_ETX) { + fprintf(diag, "Option 1 : 0x%02x\n", stm->option1); + fprintf(diag, "Option 2 : 0x%02x\n", stm->option2); + } + fprintf(diag, "Device ID : 0x%04x (%s)\n", stm->pid, stm->dev->name); + fprintf(diag, "- RAM : %dKiB (%db reserved by bootloader)\n", (stm->dev->ram_end - 0x20000000) / 1024, stm->dev->ram_start - 0x20000000); + fprintf(diag, "- Flash : %dKiB (sector size: %dx%d)\n", (stm->dev->fl_end - stm->dev->fl_start ) / 1024, stm->dev->fl_pps, stm->dev->fl_ps); + fprintf(diag, "- Option RAM : %db\n", stm->dev->opt_end - stm->dev->opt_start + 1); + fprintf(diag, "- System RAM : %dKiB\n", (stm->dev->mem_end - stm->dev->mem_start) / 1024); + + uint8_t buffer[256]; + uint32_t addr, start, end; + unsigned int len; + int failed = 0; + int first_page, num_pages; + + /* + * Cleanup addresses: + * + * Starting from options + * start_addr, readwrite_len, spage, npages + * and using device memory size, compute + * start, end, first_page, num_pages + */ + if (start_addr || readwrite_len) { + start = start_addr; + + if (is_addr_in_flash(start)) + end = stm->dev->fl_end; + else { + no_erase = 1; + if (is_addr_in_ram(start)) + end = stm->dev->ram_end; + else + end = start + sizeof(uint32_t); + } + + if (readwrite_len && (end > start + readwrite_len)) + end = start + readwrite_len; + + first_page = flash_addr_to_page_floor(start); + if (!first_page && end == stm->dev->fl_end) + num_pages = 0xff; /* mass erase */ + else + num_pages = flash_addr_to_page_ceil(end) - first_page; + } else if (!spage && !npages) { + start = stm->dev->fl_start; + end = stm->dev->fl_end; + first_page = 0; + num_pages = 0xff; /* mass erase */ + } else { + first_page = spage; + start = flash_page_to_addr(first_page); + if (start > stm->dev->fl_end) { + fprintf(stderr, "Address range exceeds flash size.\n"); + goto close; + } + + if (npages) { + num_pages = npages; + end = flash_page_to_addr(first_page + num_pages); + if (end > stm->dev->fl_end) + end = stm->dev->fl_end; + } else { + end = stm->dev->fl_end; + num_pages = flash_addr_to_page_ceil(end) - first_page; + } + + if (!first_page && end == stm->dev->fl_end) + num_pages = 0xff; /* mass erase */ + } + + if (rd) { + unsigned int max_len = port_opts.rx_frame_max; + + fprintf(diag, "Memory read\n"); + + perr = parser->open(p_st, filename, 1); + if (perr != PARSER_ERR_OK) { + fprintf(stderr, "%s ERROR: %s\n", parser->name, parser_errstr(perr)); + if (perr == PARSER_ERR_SYSTEM) + perror(filename); + goto close; + } + + fflush(diag); + addr = start; + while(addr < end) { + uint32_t left = end - addr; + len = max_len > left ? left : max_len; + s_err = stm32_read_memory(stm, addr, buffer, len); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Failed to read memory at address 0x%08x, target write-protected?\n", addr); + goto close; + } + if (parser->write(p_st, buffer, len) != PARSER_ERR_OK) + { + fprintf(stderr, "Failed to write data to file\n"); + goto close; + } + addr += len; + + fprintf(diag, + "\rRead address 0x%08x (%.2f%%) ", + addr, + (100.0f / (float)(end - start)) * (float)(addr - start) + ); + fflush(diag); + } + fprintf(diag, "Done.\n"); + ret = 0; + goto close; + } else if (rp) { + fprintf(stdout, "Read-Protecting flash\n"); + /* the device automatically performs a reset after the sending the ACK */ + reset_flag = 0; + stm32_readprot_memory(stm); + fprintf(stdout, "Done.\n"); + } else if (ur) { + fprintf(stdout, "Read-UnProtecting flash\n"); + /* the device automatically performs a reset after the sending the ACK */ + reset_flag = 0; + stm32_runprot_memory(stm); + fprintf(stdout, "Done.\n"); + } else if (eraseOnly) { + ret = 0; + fprintf(stdout, "Erasing flash\n"); + + if (num_pages != 0xff && + (start != flash_page_to_addr(first_page) + || end != flash_page_to_addr(first_page + num_pages))) { + fprintf(stderr, "Specified start & length are invalid (must be page aligned)\n"); + ret = 1; + goto close; + } + + s_err = stm32_erase_memory(stm, first_page, num_pages); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Failed to erase memory\n"); + ret = 1; + goto close; + } + } else if (wu) { + fprintf(diag, "Write-unprotecting flash\n"); + /* the device automatically performs a reset after the sending the ACK */ + reset_flag = 0; + stm32_wunprot_memory(stm); + fprintf(diag, "Done.\n"); + + } else if (wr) { + fprintf(diag, "Write to memory\n"); + + off_t offset = 0; + ssize_t r; + unsigned int size; + unsigned int max_wlen, max_rlen; + + max_wlen = port_opts.tx_frame_max - 2; /* skip len and crc */ + max_wlen &= ~3; /* 32 bit aligned */ + + max_rlen = port_opts.rx_frame_max; + max_rlen = max_rlen < max_wlen ? max_rlen : max_wlen; + + /* Assume data from stdin is whole device */ + if (filename[0] == '-' && filename[1] == '\0') + size = end - start; + else + size = parser->size(p_st); + + // TODO: It is possible to write to non-page boundaries, by reading out flash + // from partial pages and combining with the input data + // if ((start % stm->dev->fl_ps) != 0 || (end % stm->dev->fl_ps) != 0) { + // fprintf(stderr, "Specified start & length are invalid (must be page aligned)\n"); + // goto close; + // } + + // TODO: If writes are not page aligned, we should probably read out existing flash + // contents first, so it can be preserved and combined with new data + if (!no_erase && num_pages) { + fprintf(diag, "Erasing memory\n"); + s_err = stm32_erase_memory(stm, first_page, num_pages); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Failed to erase memory\n"); + goto close; + } + } + + fflush(diag); + addr = start; + while(addr < end && offset < size) { + uint32_t left = end - addr; + len = max_wlen > left ? left : max_wlen; + len = len > size - offset ? size - offset : len; + + if (parser->read(p_st, buffer, &len) != PARSER_ERR_OK) + goto close; + + if (len == 0) { + if (filename[0] == '-') { + break; + } else { + fprintf(stderr, "Failed to read input file\n"); + goto close; + } + } + + again: + s_err = stm32_write_memory(stm, addr, buffer, len); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Failed to write memory at address 0x%08x\n", addr); + goto close; + } + + if (verify) { + uint8_t compare[len]; + unsigned int offset, rlen; + + offset = 0; + while (offset < len) { + rlen = len - offset; + rlen = rlen < max_rlen ? rlen : max_rlen; + s_err = stm32_read_memory(stm, addr + offset, compare + offset, rlen); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Failed to read memory at address 0x%08x\n", addr + offset); + goto close; + } + offset += rlen; + } + + for(r = 0; r < len; ++r) + if (buffer[r] != compare[r]) { + if (failed == retry) { + fprintf(stderr, "Failed to verify at address 0x%08x, expected 0x%02x and found 0x%02x\n", + (uint32_t)(addr + r), + buffer [r], + compare[r] + ); + goto close; + } + ++failed; + goto again; + } + + failed = 0; + } + + addr += len; + offset += len; + + fprintf(diag, + "\rWrote %saddress 0x%08x (%.2f%%) ", + verify ? "and verified " : "", + addr, + (100.0f / size) * offset + ); + fflush(diag); + + } + + fprintf(diag, "Done.\n"); + ret = 0; + goto close; + } else if (crc) { + uint32_t crc_val = 0; + + fprintf(diag, "CRC computation\n"); + + s_err = stm32_crc_wrapper(stm, start, end - start, &crc_val); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Failed to read CRC\n"); + goto close; + } + fprintf(diag, "CRC(0x%08x-0x%08x) = 0x%08x\n", start, end, + crc_val); + ret = 0; + goto close; + } else + ret = 0; + +close: + if (stm && exec_flag && ret == 0) { + if (execute == 0) + execute = stm->dev->fl_start; + + fprintf(diag, "\nStarting execution at address 0x%08x... ", execute); + fflush(diag); + if (stm32_go(stm, execute) == STM32_ERR_OK) { + reset_flag = 0; + fprintf(diag, "done.\n"); + } else + fprintf(diag, "failed.\n"); + } + + if (stm && reset_flag) { + fprintf(diag, "\nResetting device... "); + fflush(diag); + if (init_bl_exit(stm, port, gpio_seq)) + fprintf(diag, "done.\n"); + else fprintf(diag, "failed.\n"); + } + + if (p_st ) parser->close(p_st); + if (stm ) stm32_close (stm); + if (port) + port->close(port); + + fprintf(diag, "\n"); + return ret; +} + +int parse_options(int argc, char *argv[]) +{ + int c; + char *pLen; + + while ((c = getopt(argc, argv, "a:b:m:r:w:e:vn:g:jkfcChuos:S:F:i:R")) != -1) { + switch(c) { + case 'a': + port_opts.bus_addr = strtoul(optarg, NULL, 0); + break; + + case 'b': + port_opts.baudRate = serial_get_baud(strtoul(optarg, NULL, 0)); + if (port_opts.baudRate == SERIAL_BAUD_INVALID) { + serial_baud_t baudrate; + fprintf(stderr, "Invalid baud rate, valid options are:\n"); + for (baudrate = SERIAL_BAUD_1200; baudrate != SERIAL_BAUD_INVALID; ++baudrate) + fprintf(stderr, " %d\n", serial_get_baud_int(baudrate)); + return 1; + } + break; + + case 'm': + if (strlen(optarg) != 3 + || serial_get_bits(optarg) == SERIAL_BITS_INVALID + || serial_get_parity(optarg) == SERIAL_PARITY_INVALID + || serial_get_stopbit(optarg) == SERIAL_STOPBIT_INVALID) { + fprintf(stderr, "Invalid serial mode\n"); + return 1; + } + port_opts.serial_mode = optarg; + break; + + case 'r': + case 'w': + rd = rd || c == 'r'; + wr = wr || c == 'w'; + if (rd && wr) { + fprintf(stderr, "ERROR: Invalid options, can't read & write at the same time\n"); + return 1; + } + filename = optarg; + if (filename[0] == '-') { + force_binary = 1; + } + break; + case 'e': + if (readwrite_len || start_addr) { + fprintf(stderr, "ERROR: Invalid options, can't specify start page / num pages and start address/length\n"); + return 1; + } + npages = strtoul(optarg, NULL, 0); + if (npages > 0xFF || npages < 0) { + fprintf(stderr, "ERROR: You need to specify a page count between 0 and 255"); + return 1; + } + if (!npages) + no_erase = 1; + break; + case 'u': + wu = 1; + if (rd || wr) { + fprintf(stderr, "ERROR: Invalid options, can't write unprotect and read/write at the same time\n"); + return 1; + } + break; + + case 'j': + rp = 1; + if (rd || wr) { + fprintf(stderr, "ERROR: Invalid options, can't read protect and read/write at the same time\n"); + return 1; + } + break; + + case 'k': + ur = 1; + if (rd || wr) { + fprintf(stderr, "ERROR: Invalid options, can't read unprotect and read/write at the same time\n"); + return 1; + } + break; + + case 'o': + eraseOnly = 1; + if (rd || wr) { + fprintf(stderr, "ERROR: Invalid options, can't erase-only and read/write at the same time\n"); + return 1; + } + break; + + case 'v': + verify = 1; + break; + + case 'n': + retry = strtoul(optarg, NULL, 0); + break; + + case 'g': + exec_flag = 1; + execute = strtoul(optarg, NULL, 0); + if (execute % 4 != 0) { + fprintf(stderr, "ERROR: Execution address must be word-aligned\n"); + return 1; + } + break; + case 's': + if (readwrite_len || start_addr) { + fprintf(stderr, "ERROR: Invalid options, can't specify start page / num pages and start address/length\n"); + return 1; + } + spage = strtoul(optarg, NULL, 0); + break; + case 'S': + if (spage || npages) { + fprintf(stderr, "ERROR: Invalid options, can't specify start page / num pages and start address/length\n"); + return 1; + } else { + start_addr = strtoul(optarg, &pLen, 0); + if (*pLen == ':') { + pLen++; + readwrite_len = strtoul(pLen, NULL, 0); + if (readwrite_len == 0) { + fprintf(stderr, "ERROR: Invalid options, can't specify zero length\n"); + return 1; + } + } + } + break; + case 'F': + port_opts.rx_frame_max = strtoul(optarg, &pLen, 0); + if (*pLen == ':') { + pLen++; + port_opts.tx_frame_max = strtoul(pLen, NULL, 0); + } + if (port_opts.rx_frame_max < 0 + || port_opts.tx_frame_max < 0) { + fprintf(stderr, "ERROR: Invalid negative value for option -F\n"); + return 1; + } + if (port_opts.rx_frame_max == 0) + port_opts.rx_frame_max = STM32_MAX_RX_FRAME; + if (port_opts.tx_frame_max == 0) + port_opts.tx_frame_max = STM32_MAX_TX_FRAME; + if (port_opts.rx_frame_max < 20 + || port_opts.tx_frame_max < 5) { + fprintf(stderr, "ERROR: current code cannot work with small frames.\n"); + fprintf(stderr, "min(RX) = 20, min(TX) = 5\n"); + return 1; + } + if (port_opts.rx_frame_max > STM32_MAX_RX_FRAME) { + fprintf(stderr, "WARNING: Ignore RX length in option -F\n"); + port_opts.rx_frame_max = STM32_MAX_RX_FRAME; + } + if (port_opts.tx_frame_max > STM32_MAX_TX_FRAME) { + fprintf(stderr, "WARNING: Ignore TX length in option -F\n"); + port_opts.tx_frame_max = STM32_MAX_TX_FRAME; + } + break; + case 'f': + force_binary = 1; + break; + + case 'c': + init_flag = 0; + break; + + case 'h': + show_help(argv[0]); + exit(0); + + case 'i': + gpio_seq = optarg; + break; + + case 'R': + reset_flag = 1; + break; + + case 'C': + crc = 1; + break; + } + } + + for (c = optind; c < argc; ++c) { + if (port_opts.device) { + fprintf(stderr, "ERROR: Invalid parameter specified\n"); + show_help(argv[0]); + return 1; + } + port_opts.device = argv[c]; + } + + if (port_opts.device == NULL) { + fprintf(stderr, "ERROR: Device not specified\n"); + show_help(argv[0]); + return 1; + } + + if (!wr && verify) { + fprintf(stderr, "ERROR: Invalid usage, -v is only valid when writing\n"); + show_help(argv[0]); + return 1; + } + + return 0; +} + +void show_help(char *name) { + fprintf(stderr, + "Usage: %s [-bvngfhc] [-[rw] filename] [tty_device | i2c_device]\n" + " -a bus_address Bus address (e.g. for I2C port)\n" + " -b rate Baud rate (default 57600)\n" + " -m mode Serial port mode (default 8e1)\n" + " -r filename Read flash to file (or - stdout)\n" + " -w filename Write flash from file (or - stdout)\n" + " -C Compute CRC of flash content\n" + " -u Disable the flash write-protection\n" + " -j Enable the flash read-protection\n" + " -k Disable the flash read-protection\n" + " -o Erase only\n" + " -e n Only erase n pages before writing the flash\n" + " -v Verify writes\n" + " -n count Retry failed writes up to count times (default 10)\n" + " -g address Start execution at specified address (0 = flash start)\n" + " -S address[:length] Specify start address and optionally length for\n" + " read/write/erase operations\n" + " -F RX_length[:TX_length] Specify the max length of RX and TX frame\n" + " -s start_page Flash at specified page (0 = flash start)\n" + " -f Force binary parser\n" + " -h Show this help\n" + " -c Resume the connection (don't send initial INIT)\n" + " *Baud rate must be kept the same as the first init*\n" + " This is useful if the reset fails\n" + " -i GPIO_string GPIO sequence to enter/exit bootloader mode\n" + " GPIO_string=[entry_seq][:[exit_seq]]\n" + " sequence=[-]n[,sequence]\n" + " -R Reset device at exit.\n" + "\n" + "Examples:\n" + " Get device information:\n" + " %s /dev/ttyS0\n" + " or:\n" + " %s /dev/i2c-0\n" + "\n" + " Write with verify and then start execution:\n" + " %s -w filename -v -g 0x0 /dev/ttyS0\n" + "\n" + " Read flash to file:\n" + " %s -r filename /dev/ttyS0\n" + "\n" + " Read 100 bytes of flash from 0x1000 to stdout:\n" + " %s -r - -S 0x1000:100 /dev/ttyS0\n" + "\n" + " Start execution:\n" + " %s -g 0x0 /dev/ttyS0\n" + "\n" + " GPIO sequence:\n" + " - entry sequence: GPIO_3=low, GPIO_2=low, GPIO_2=high\n" + " - exit sequence: GPIO_3=high, GPIO_2=low, GPIO_2=high\n" + " %s -i -3,-2,2:3,-2,2 /dev/ttyS0\n", + name, + name, + name, + name, + name, + name, + name, + name + ); +} + diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/parsers/Android.mk b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/parsers/Android.mk new file mode 100644 index 0000000..afec18c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/parsers/Android.mk @@ -0,0 +1,6 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := libparsers +LOCAL_SRC_FILES := binary.c hex.c +include $(BUILD_STATIC_LIBRARY) diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/parsers/Makefile b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/parsers/Makefile new file mode 100644 index 0000000..bb7df1e --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/parsers/Makefile @@ -0,0 +1,12 @@ + +CFLAGS += -Wall -g + +all: parsers.a + +parsers.a: binary.o hex.o + $(AR) rc $@ binary.o hex.o + +clean: + rm -f *.o parsers.a + +.PHONY: all clean diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/parsers/binary.c b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/parsers/binary.c new file mode 100644 index 0000000..f491952 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/parsers/binary.c @@ -0,0 +1,140 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#include +#include +#include +#include +#include + +#include "binary.h" + +typedef struct { + int fd; + char write; + struct stat stat; +} binary_t; + +void* binary_init() { + return calloc(sizeof(binary_t), 1); +} + +parser_err_t binary_open(void *storage, const char *filename, const char write) { + binary_t *st = storage; + if (write) { + if (filename[0] == '-') + st->fd = 1; + else + st->fd = open( + filename, +#ifndef __WIN32__ + O_WRONLY | O_CREAT | O_TRUNC, +#else + O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, +#endif +#ifndef __WIN32__ + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH +#else + 0 +#endif + ); + st->stat.st_size = 0; + } else { + if (filename[0] == '-') { + st->fd = 0; + } else { + if (stat(filename, &st->stat) != 0) + return PARSER_ERR_INVALID_FILE; + st->fd = open(filename, +#ifndef __WIN32__ + O_RDONLY +#else + O_RDONLY | O_BINARY +#endif + ); + } + } + + st->write = write; + return st->fd == -1 ? PARSER_ERR_SYSTEM : PARSER_ERR_OK; +} + +parser_err_t binary_close(void *storage) { + binary_t *st = storage; + + if (st->fd) close(st->fd); + free(st); + return PARSER_ERR_OK; +} + +unsigned int binary_size(void *storage) { + binary_t *st = storage; + return st->stat.st_size; +} + +parser_err_t binary_read(void *storage, void *data, unsigned int *len) { + binary_t *st = storage; + unsigned int left = *len; + if (st->write) return PARSER_ERR_WRONLY; + + ssize_t r; + while(left > 0) { + r = read(st->fd, data, left); + /* If there is no data to read at all, return OK, but with zero read */ + if (r == 0 && left == *len) { + *len = 0; + return PARSER_ERR_OK; + } + if (r <= 0) return PARSER_ERR_SYSTEM; + left -= r; + data += r; + } + + *len = *len - left; + return PARSER_ERR_OK; +} + +parser_err_t binary_write(void *storage, void *data, unsigned int len) { + binary_t *st = storage; + if (!st->write) return PARSER_ERR_RDONLY; + + ssize_t r; + while(len > 0) { + r = write(st->fd, data, len); + if (r < 1) return PARSER_ERR_SYSTEM; + st->stat.st_size += r; + + len -= r; + data += r; + } + + return PARSER_ERR_OK; +} + +parser_t PARSER_BINARY = { + "Raw BINARY", + binary_init, + binary_open, + binary_close, + binary_size, + binary_read, + binary_write +}; + diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/parsers/binary.h b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/parsers/binary.h new file mode 100644 index 0000000..d989acf --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/parsers/binary.h @@ -0,0 +1,27 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _PARSER_BINARY_H +#define _PARSER_BINARY_H + +#include "parser.h" + +extern parser_t PARSER_BINARY; +#endif diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/parsers/hex.c b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/parsers/hex.c new file mode 100644 index 0000000..3baf856 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/parsers/hex.c @@ -0,0 +1,224 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#include +#include +#include +#include +#include +#include +#include + +#include "hex.h" +#include "../utils.h" + +typedef struct { + size_t data_len, offset; + uint8_t *data; + uint8_t base; +} hex_t; + +void* hex_init() { + return calloc(sizeof(hex_t), 1); +} + +parser_err_t hex_open(void *storage, const char *filename, const char write) { + hex_t *st = storage; + if (write) { + return PARSER_ERR_RDONLY; + } else { + char mark; + int i, fd; + uint8_t checksum; + unsigned int c; + uint32_t base = 0; + unsigned int last_address = 0x0; + + fd = open(filename, O_RDONLY); + if (fd < 0) + return PARSER_ERR_SYSTEM; + + /* read in the file */ + + while(read(fd, &mark, 1) != 0) { + if (mark == '\n' || mark == '\r') continue; + if (mark != ':') + return PARSER_ERR_INVALID_FILE; + + char buffer[9]; + unsigned int reclen, address, type; + uint8_t *record = NULL; + + /* get the reclen, address, and type */ + buffer[8] = 0; + if (read(fd, &buffer, 8) != 8) return PARSER_ERR_INVALID_FILE; + if (sscanf(buffer, "%2x%4x%2x", &reclen, &address, &type) != 3) { + close(fd); + return PARSER_ERR_INVALID_FILE; + } + + /* setup the checksum */ + checksum = + reclen + + ((address & 0xFF00) >> 8) + + ((address & 0x00FF) >> 0) + + type; + + switch(type) { + /* data record */ + case 0: + c = address - last_address; + st->data = realloc(st->data, st->data_len + c + reclen); + + /* if there is a gap, set it to 0xff and increment the length */ + if (c > 0) { + memset(&st->data[st->data_len], 0xff, c); + st->data_len += c; + } + + last_address = address + reclen; + record = &st->data[st->data_len]; + st->data_len += reclen; + break; + + /* extended segment address record */ + case 2: + base = 0; + break; + + /* extended linear address record */ + case 4: + base = address; + break; + } + + buffer[2] = 0; + for(i = 0; i < reclen; ++i) { + if (read(fd, &buffer, 2) != 2 || sscanf(buffer, "%2x", &c) != 1) { + close(fd); + return PARSER_ERR_INVALID_FILE; + } + + /* add the byte to the checksum */ + checksum += c; + + switch(type) { + case 0: + if (record != NULL) { + record[i] = c; + } else { + return PARSER_ERR_INVALID_FILE; + } + break; + + case 2: + case 4: + base = (base << 8) | c; + break; + } + } + + /* read, scan, and verify the checksum */ + if ( + read(fd, &buffer, 2 ) != 2 || + sscanf(buffer, "%2x", &c) != 1 || + (uint8_t)(checksum + c) != 0x00 + ) { + close(fd); + return PARSER_ERR_INVALID_FILE; + } + + switch(type) { + /* EOF */ + case 1: + close(fd); + return PARSER_ERR_OK; + + /* address record */ + case 2: base = base << 4; + case 4: base = be_u32(base); + /* Reset last_address since our base changed */ + last_address = 0; + + if (st->base == 0) { + st->base = base; + break; + } + + /* we cant cope with files out of order */ + if (base < st->base) { + close(fd); + return PARSER_ERR_INVALID_FILE; + } + + /* if there is a gap, enlarge and fill with zeros */ + unsigned int len = base - st->base; + if (len > st->data_len) { + st->data = realloc(st->data, len); + memset(&st->data[st->data_len], 0, len - st->data_len); + st->data_len = len; + } + break; + } + } + + close(fd); + return PARSER_ERR_OK; + } +} + +parser_err_t hex_close(void *storage) { + hex_t *st = storage; + if (st) free(st->data); + free(st); + return PARSER_ERR_OK; +} + +unsigned int hex_size(void *storage) { + hex_t *st = storage; + return st->data_len; +} + +parser_err_t hex_read(void *storage, void *data, unsigned int *len) { + hex_t *st = storage; + unsigned int left = st->data_len - st->offset; + unsigned int get = left > *len ? *len : left; + + memcpy(data, &st->data[st->offset], get); + st->offset += get; + + *len = get; + return PARSER_ERR_OK; +} + +parser_err_t hex_write(void *storage, void *data, unsigned int len) { + return PARSER_ERR_RDONLY; +} + +parser_t PARSER_HEX = { + "Intel HEX", + hex_init, + hex_open, + hex_close, + hex_size, + hex_read, + hex_write +}; + diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/parsers/hex.h b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/parsers/hex.h new file mode 100644 index 0000000..02413c9 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/parsers/hex.h @@ -0,0 +1,27 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _PARSER_HEX_H +#define _PARSER_HEX_H + +#include "parser.h" + +extern parser_t PARSER_HEX; +#endif diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/parsers/parser.h b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/parsers/parser.h new file mode 100644 index 0000000..c2fae3c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/parsers/parser.h @@ -0,0 +1,56 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _H_PARSER +#define _H_PARSER + +enum parser_err { + PARSER_ERR_OK, + PARSER_ERR_SYSTEM, + PARSER_ERR_INVALID_FILE, + PARSER_ERR_WRONLY, + PARSER_ERR_RDONLY +}; +typedef enum parser_err parser_err_t; + +struct parser { + const char *name; + void* (*init )(); /* initialise the parser */ + parser_err_t (*open )(void *storage, const char *filename, const char write); /* open the file for read|write */ + parser_err_t (*close)(void *storage); /* close and free the parser */ + unsigned int (*size )(void *storage); /* get the total data size */ + parser_err_t (*read )(void *storage, void *data, unsigned int *len); /* read a block of data */ + parser_err_t (*write)(void *storage, void *data, unsigned int len); /* write a block of data */ +}; +typedef struct parser parser_t; + +static inline const char* parser_errstr(parser_err_t err) { + switch(err) { + case PARSER_ERR_OK : return "OK"; + case PARSER_ERR_SYSTEM : return "System Error"; + case PARSER_ERR_INVALID_FILE: return "Invalid File"; + case PARSER_ERR_WRONLY : return "Parser can only write"; + case PARSER_ERR_RDONLY : return "Parser can only read"; + default: + return "Unknown Error"; + } +} + +#endif diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/port.c b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/port.c new file mode 100644 index 0000000..08e58cc --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/port.c @@ -0,0 +1,59 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2014 Antonio Borneo + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include + +#include "serial.h" +#include "port.h" + + +extern struct port_interface port_serial; +extern struct port_interface port_i2c; + +static struct port_interface *ports[] = { + &port_serial, + &port_i2c, + NULL, +}; + + +port_err_t port_open(struct port_options *ops, struct port_interface **outport) +{ + int ret; + static struct port_interface **port; + + for (port = ports; *port; port++) { + ret = (*port)->open(*port, ops); + if (ret == PORT_ERR_NODEV) + continue; + if (ret == PORT_ERR_OK) + break; + fprintf(stderr, "Error probing interface \"%s\"\n", + (*port)->name); + } + if (*port == NULL) { + fprintf(stderr, "Cannot handle device \"%s\"\n", + ops->device); + return PORT_ERR_UNKNOWN; + } + + *outport = *port; + return PORT_ERR_OK; +} diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/port.h b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/port.h new file mode 100644 index 0000000..290f034 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/port.h @@ -0,0 +1,75 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2014 Antonio Borneo + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _H_PORT +#define _H_PORT + +typedef enum { + PORT_ERR_OK = 0, + PORT_ERR_NODEV, /* No such device */ + PORT_ERR_TIMEDOUT, /* Operation timed out */ + PORT_ERR_UNKNOWN, +} port_err_t; + +/* flags */ +#define PORT_BYTE (1 << 0) /* byte (not frame) oriented */ +#define PORT_GVR_ETX (1 << 1) /* cmd GVR returns protection status */ +#define PORT_CMD_INIT (1 << 2) /* use INIT cmd to autodetect speed */ +#define PORT_RETRY (1 << 3) /* allowed read() retry after timeout */ +#define PORT_STRETCH_W (1 << 4) /* warning for no-stretching commands */ + +/* all options and flags used to open and configure an interface */ +struct port_options { + const char *device; + serial_baud_t baudRate; + const char *serial_mode; + int bus_addr; + int rx_frame_max; + int tx_frame_max; +}; + +/* + * Specify the length of reply for command GET + * This is helpful for frame-oriented protocols, e.g. i2c, to avoid time + * consuming try-fail-timeout-retry operation. + * On byte-oriented protocols, i.e. UART, this information would be skipped + * after read the first byte, so not needed. + */ +struct varlen_cmd { + uint8_t version; + uint8_t length; +}; + +struct port_interface { + const char *name; + unsigned flags; + port_err_t (*open)(struct port_interface *port, struct port_options *ops); + port_err_t (*close)(struct port_interface *port); + port_err_t (*read)(struct port_interface *port, void *buf, size_t nbyte); + port_err_t (*write)(struct port_interface *port, void *buf, size_t nbyte); + port_err_t (*gpio)(struct port_interface *port, serial_gpio_t n, int level); + const char *(*get_cfg_str)(struct port_interface *port); + struct varlen_cmd *cmd_get_reply; + void *private; +}; + +port_err_t port_open(struct port_options *ops, struct port_interface **outport); + +#endif diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/protocol.txt b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/protocol.txt new file mode 100644 index 0000000..0391099 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/protocol.txt @@ -0,0 +1,19 @@ +The communication protocol used by ST bootloader is documented in following ST +application notes, depending on communication port. + +In current version of stm32flash are supported only UART and I2C ports. + +* AN3154: CAN protocol used in the STM32 bootloader + http://www.st.com/web/en/resource/technical/document/application_note/CD00264321.pdf + +* AN3155: USART protocol used in the STM32(TM) bootloader + http://www.st.com/web/en/resource/technical/document/application_note/CD00264342.pdf + +* AN4221: I2C protocol used in the STM32 bootloader + http://www.st.com/web/en/resource/technical/document/application_note/DM00072315.pdf + +* AN4286: SPI protocol used in the STM32 bootloader + http://www.st.com/web/en/resource/technical/document/application_note/DM00081379.pdf + +Boot mode selection for STM32 is documented in ST application note AN2606, available in ST website: + http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/serial.h b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/serial.h new file mode 100644 index 0000000..227ba16 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/serial.h @@ -0,0 +1,90 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _SERIAL_H +#define _SERIAL_H + +typedef struct serial serial_t; + +typedef enum { + SERIAL_PARITY_NONE, + SERIAL_PARITY_EVEN, + SERIAL_PARITY_ODD, + + SERIAL_PARITY_INVALID +} serial_parity_t; + +typedef enum { + SERIAL_BITS_5, + SERIAL_BITS_6, + SERIAL_BITS_7, + SERIAL_BITS_8, + + SERIAL_BITS_INVALID +} serial_bits_t; + +typedef enum { + SERIAL_BAUD_1200, + SERIAL_BAUD_1800, + SERIAL_BAUD_2400, + SERIAL_BAUD_4800, + SERIAL_BAUD_9600, + SERIAL_BAUD_19200, + SERIAL_BAUD_38400, + SERIAL_BAUD_57600, + SERIAL_BAUD_115200, + SERIAL_BAUD_128000, + SERIAL_BAUD_230400, + SERIAL_BAUD_256000, + SERIAL_BAUD_460800, + SERIAL_BAUD_500000, + SERIAL_BAUD_576000, + SERIAL_BAUD_921600, + SERIAL_BAUD_1000000, + SERIAL_BAUD_1500000, + SERIAL_BAUD_2000000, + + SERIAL_BAUD_INVALID +} serial_baud_t; + +typedef enum { + SERIAL_STOPBIT_1, + SERIAL_STOPBIT_2, + + SERIAL_STOPBIT_INVALID +} serial_stopbit_t; + +typedef enum { + GPIO_RTS = 1, + GPIO_DTR, + GPIO_BRK, +} serial_gpio_t; + +/* common helper functions */ +serial_baud_t serial_get_baud(const unsigned int baud); +unsigned int serial_get_baud_int(const serial_baud_t baud); +serial_bits_t serial_get_bits(const char *mode); +unsigned int serial_get_bits_int(const serial_bits_t bits); +serial_parity_t serial_get_parity(const char *mode); +char serial_get_parity_str(const serial_parity_t parity); +serial_stopbit_t serial_get_stopbit(const char *mode); +unsigned int serial_get_stopbit_int(const serial_stopbit_t stopbit); + +#endif diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/serial_common.c b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/serial_common.c new file mode 100644 index 0000000..43e48e1 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/serial_common.c @@ -0,0 +1,154 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "serial.h" + +serial_baud_t serial_get_baud(const unsigned int baud) { + switch(baud) { + case 1200: return SERIAL_BAUD_1200 ; + case 1800: return SERIAL_BAUD_1800 ; + case 2400: return SERIAL_BAUD_2400 ; + case 4800: return SERIAL_BAUD_4800 ; + case 9600: return SERIAL_BAUD_9600 ; + case 19200: return SERIAL_BAUD_19200 ; + case 38400: return SERIAL_BAUD_38400 ; + case 57600: return SERIAL_BAUD_57600 ; + case 115200: return SERIAL_BAUD_115200; + case 128000: return SERIAL_BAUD_128000; + case 230400: return SERIAL_BAUD_230400; + case 256000: return SERIAL_BAUD_256000; + case 460800: return SERIAL_BAUD_460800; + case 500000: return SERIAL_BAUD_500000; + case 576000: return SERIAL_BAUD_576000; + case 921600: return SERIAL_BAUD_921600; + case 1000000: return SERIAL_BAUD_1000000; + case 1500000: return SERIAL_BAUD_1500000; + case 2000000: return SERIAL_BAUD_2000000; + + default: + return SERIAL_BAUD_INVALID; + } +} + +unsigned int serial_get_baud_int(const serial_baud_t baud) { + switch(baud) { + case SERIAL_BAUD_1200 : return 1200 ; + case SERIAL_BAUD_1800 : return 1800 ; + case SERIAL_BAUD_2400 : return 2400 ; + case SERIAL_BAUD_4800 : return 4800 ; + case SERIAL_BAUD_9600 : return 9600 ; + case SERIAL_BAUD_19200 : return 19200 ; + case SERIAL_BAUD_38400 : return 38400 ; + case SERIAL_BAUD_57600 : return 57600 ; + case SERIAL_BAUD_115200: return 115200; + case SERIAL_BAUD_128000: return 128000; + case SERIAL_BAUD_230400: return 230400; + case SERIAL_BAUD_256000: return 256000; + case SERIAL_BAUD_460800: return 460800; + case SERIAL_BAUD_500000: return 500000; + case SERIAL_BAUD_576000: return 576000; + case SERIAL_BAUD_921600: return 921600; + case SERIAL_BAUD_1000000: return 1000000; + case SERIAL_BAUD_1500000: return 1500000; + case SERIAL_BAUD_2000000: return 2000000; + + case SERIAL_BAUD_INVALID: + default: + return 0; + } +} + +serial_bits_t serial_get_bits(const char *mode) { + if (!mode) + return SERIAL_BITS_INVALID; + switch(mode[0]) { + case '5': return SERIAL_BITS_5; + case '6': return SERIAL_BITS_6; + case '7': return SERIAL_BITS_7; + case '8': return SERIAL_BITS_8; + + default: + return SERIAL_BITS_INVALID; + } +} + +unsigned int serial_get_bits_int(const serial_bits_t bits) { + switch(bits) { + case SERIAL_BITS_5: return 5; + case SERIAL_BITS_6: return 6; + case SERIAL_BITS_7: return 7; + case SERIAL_BITS_8: return 8; + + default: + return 0; + } +} + +serial_parity_t serial_get_parity(const char *mode) { + if (!mode || !mode[0]) + return SERIAL_PARITY_INVALID; + switch(mode[1]) { + case 'N': + case 'n': + return SERIAL_PARITY_NONE; + case 'E': + case 'e': + return SERIAL_PARITY_EVEN; + case 'O': + case 'o': + return SERIAL_PARITY_ODD; + + default: + return SERIAL_PARITY_INVALID; + } +} + +char serial_get_parity_str(const serial_parity_t parity) { + switch(parity) { + case SERIAL_PARITY_NONE: return 'N'; + case SERIAL_PARITY_EVEN: return 'E'; + case SERIAL_PARITY_ODD : return 'O'; + + default: + return ' '; + } +} + +serial_stopbit_t serial_get_stopbit(const char *mode) { + if (!mode || !mode[0] || !mode[1]) + return SERIAL_STOPBIT_INVALID; + switch(mode[2]) { + case '1': return SERIAL_STOPBIT_1; + case '2': return SERIAL_STOPBIT_2; + + default: + return SERIAL_STOPBIT_INVALID; + } +} + +unsigned int serial_get_stopbit_int(const serial_stopbit_t stopbit) { + switch(stopbit) { + case SERIAL_STOPBIT_1: return 1; + case SERIAL_STOPBIT_2: return 2; + + default: + return 0; + } +} + diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/serial_platform.c b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/serial_platform.c new file mode 100644 index 0000000..98e2569 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/serial_platform.c @@ -0,0 +1,5 @@ +#if defined(__WIN32__) || defined(__CYGWIN__) +# include "serial_w32.c" +#else +# include "serial_posix.c" +#endif diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/serial_posix.c b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/serial_posix.c new file mode 100644 index 0000000..284b35b --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/serial_posix.c @@ -0,0 +1,395 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "serial.h" +#include "port.h" + +struct serial { + int fd; + struct termios oldtio; + struct termios newtio; + char setup_str[11]; +}; + +static serial_t *serial_open(const char *device) +{ + serial_t *h = calloc(sizeof(serial_t), 1); + + h->fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY); + if (h->fd < 0) { + free(h); + return NULL; + } + fcntl(h->fd, F_SETFL, 0); + + tcgetattr(h->fd, &h->oldtio); + tcgetattr(h->fd, &h->newtio); + + return h; +} + +static void serial_flush(const serial_t *h) +{ + tcflush(h->fd, TCIFLUSH); +} + +static void serial_close(serial_t *h) +{ + serial_flush(h); + tcsetattr(h->fd, TCSANOW, &h->oldtio); + close(h->fd); + free(h); +} + +static port_err_t serial_setup(serial_t *h, const serial_baud_t baud, + const serial_bits_t bits, + const serial_parity_t parity, + const serial_stopbit_t stopbit) +{ + speed_t port_baud; + tcflag_t port_bits; + tcflag_t port_parity; + tcflag_t port_stop; + struct termios settings; + + switch (baud) { + case SERIAL_BAUD_1200: port_baud = B1200; break; + case SERIAL_BAUD_1800: port_baud = B1800; break; + case SERIAL_BAUD_2400: port_baud = B2400; break; + case SERIAL_BAUD_4800: port_baud = B4800; break; + case SERIAL_BAUD_9600: port_baud = B9600; break; + case SERIAL_BAUD_19200: port_baud = B19200; break; + case SERIAL_BAUD_38400: port_baud = B38400; break; + case SERIAL_BAUD_57600: port_baud = B57600; break; + case SERIAL_BAUD_115200: port_baud = B115200; break; + case SERIAL_BAUD_230400: port_baud = B230400; break; +#ifdef B460800 + case SERIAL_BAUD_460800: port_baud = B460800; break; +#endif /* B460800 */ +#ifdef B921600 + case SERIAL_BAUD_921600: port_baud = B921600; break; +#endif /* B921600 */ +#ifdef B500000 + case SERIAL_BAUD_500000: port_baud = B500000; break; +#endif /* B500000 */ +#ifdef B576000 + case SERIAL_BAUD_576000: port_baud = B576000; break; +#endif /* B576000 */ +#ifdef B1000000 + case SERIAL_BAUD_1000000: port_baud = B1000000; break; +#endif /* B1000000 */ +#ifdef B1500000 + case SERIAL_BAUD_1500000: port_baud = B1500000; break; +#endif /* B1500000 */ +#ifdef B2000000 + case SERIAL_BAUD_2000000: port_baud = B2000000; break; +#endif /* B2000000 */ + + case SERIAL_BAUD_INVALID: + default: + return PORT_ERR_UNKNOWN; + } + + switch (bits) { + case SERIAL_BITS_5: port_bits = CS5; break; + case SERIAL_BITS_6: port_bits = CS6; break; + case SERIAL_BITS_7: port_bits = CS7; break; + case SERIAL_BITS_8: port_bits = CS8; break; + + default: + return PORT_ERR_UNKNOWN; + } + + switch (parity) { + case SERIAL_PARITY_NONE: port_parity = 0; break; + case SERIAL_PARITY_EVEN: port_parity = PARENB; break; + case SERIAL_PARITY_ODD: port_parity = PARENB | PARODD; break; + + default: + return PORT_ERR_UNKNOWN; + } + + switch (stopbit) { + case SERIAL_STOPBIT_1: port_stop = 0; break; + case SERIAL_STOPBIT_2: port_stop = CSTOPB; break; + + default: + return PORT_ERR_UNKNOWN; + } + + /* reset the settings */ +#ifndef __sun /* Used by GNU and BSD. Ignore __SVR4 in test. */ + cfmakeraw(&h->newtio); +#else /* __sun */ + h->newtio.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR + | IGNCR | ICRNL | IXON); + if (port_parity) + h->newtio.c_iflag |= INPCK; + + h->newtio.c_oflag &= ~OPOST; + h->newtio.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); + h->newtio.c_cflag &= ~(CSIZE | PARENB); + h->newtio.c_cflag |= CS8; +#endif /* __sun */ +#ifdef __QNXNTO__ + h->newtio.c_cflag &= ~(CSIZE | IHFLOW | OHFLOW); +#else + h->newtio.c_cflag &= ~(CSIZE | CRTSCTS); +#endif + h->newtio.c_cflag &= ~(CSIZE | CRTSCTS); + h->newtio.c_iflag &= ~(IXON | IXOFF | IXANY | IGNPAR); + h->newtio.c_lflag &= ~(ECHOK | ECHOCTL | ECHOKE); + h->newtio.c_oflag &= ~(OPOST | ONLCR); + + /* setup the new settings */ + cfsetispeed(&h->newtio, port_baud); + cfsetospeed(&h->newtio, port_baud); + h->newtio.c_cflag |= + port_parity | + port_bits | + port_stop | + CLOCAL | + CREAD; + + h->newtio.c_cc[VMIN] = 0; + h->newtio.c_cc[VTIME] = 5; /* in units of 0.1 s */ + + /* set the settings */ + serial_flush(h); + if (tcsetattr(h->fd, TCSANOW, &h->newtio) != 0) + return PORT_ERR_UNKNOWN; + +/* this check fails on CDC-ACM devices, bits 16 and 17 of cflag differ! + * it has been disabled below for now -jcw, 2015-11-09 + if (settings.c_cflag != h->newtio.c_cflag) + fprintf(stderr, "c_cflag mismatch %lx\n", + settings.c_cflag ^ h->newtio.c_cflag); + */ + + /* confirm they were set */ + tcgetattr(h->fd, &settings); + if (settings.c_iflag != h->newtio.c_iflag || + settings.c_oflag != h->newtio.c_oflag || + //settings.c_cflag != h->newtio.c_cflag || + settings.c_lflag != h->newtio.c_lflag) + return PORT_ERR_UNKNOWN; + + snprintf(h->setup_str, sizeof(h->setup_str), "%u %d%c%d", + serial_get_baud_int(baud), + serial_get_bits_int(bits), + serial_get_parity_str(parity), + serial_get_stopbit_int(stopbit)); + return PORT_ERR_OK; +} + +/* + * Roger clark. + * This function is no longer used. But has just been commented out in case it needs + * to be reinstated in the future + +static int startswith(const char *haystack, const char *needle) { + return strncmp(haystack, needle, strlen(needle)) == 0; +} +*/ + +static int is_tty(const char *path) { + char resolved[PATH_MAX]; + + if(!realpath(path, resolved)) return 0; + + + /* + * Roger Clark + * Commented out this check, because on OSX some devices are /dev/cu + * and some users use symbolic links to devices, hence the name may not even start + * with /dev + + if(startswith(resolved, "/dev/tty")) return 1; + + return 0; + */ + + return 1; +} + +static port_err_t serial_posix_open(struct port_interface *port, + struct port_options *ops) +{ + serial_t *h; + + /* 1. check device name match */ + if (!is_tty(ops->device)) + return PORT_ERR_NODEV; + + /* 2. check options */ + if (ops->baudRate == SERIAL_BAUD_INVALID) + return PORT_ERR_UNKNOWN; + if (serial_get_bits(ops->serial_mode) == SERIAL_BITS_INVALID) + return PORT_ERR_UNKNOWN; + if (serial_get_parity(ops->serial_mode) == SERIAL_PARITY_INVALID) + return PORT_ERR_UNKNOWN; + if (serial_get_stopbit(ops->serial_mode) == SERIAL_STOPBIT_INVALID) + return PORT_ERR_UNKNOWN; + + /* 3. open it */ + h = serial_open(ops->device); + if (h == NULL) + return PORT_ERR_UNKNOWN; + + /* 4. set options */ + if (serial_setup(h, ops->baudRate, + serial_get_bits(ops->serial_mode), + serial_get_parity(ops->serial_mode), + serial_get_stopbit(ops->serial_mode) + ) != PORT_ERR_OK) { + serial_close(h); + return PORT_ERR_UNKNOWN; + } + + port->private = h; + return PORT_ERR_OK; +} + +static port_err_t serial_posix_close(struct port_interface *port) +{ + serial_t *h; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + serial_close(h); + port->private = NULL; + return PORT_ERR_OK; +} + +static port_err_t serial_posix_read(struct port_interface *port, void *buf, + size_t nbyte) +{ + serial_t *h; + ssize_t r; + uint8_t *pos = (uint8_t *)buf; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + while (nbyte) { + r = read(h->fd, pos, nbyte); + if (r == 0) + return PORT_ERR_TIMEDOUT; + if (r < 0) + return PORT_ERR_UNKNOWN; + + nbyte -= r; + pos += r; + } + return PORT_ERR_OK; +} + +static port_err_t serial_posix_write(struct port_interface *port, void *buf, + size_t nbyte) +{ + serial_t *h; + ssize_t r; + const uint8_t *pos = (const uint8_t *)buf; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + while (nbyte) { + r = write(h->fd, pos, nbyte); + if (r < 1) + return PORT_ERR_UNKNOWN; + + nbyte -= r; + pos += r; + } + return PORT_ERR_OK; +} + +static port_err_t serial_posix_gpio(struct port_interface *port, + serial_gpio_t n, int level) +{ + serial_t *h; + int bit, lines; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + switch (n) { + case GPIO_RTS: + bit = TIOCM_RTS; + break; + + case GPIO_DTR: + bit = TIOCM_DTR; + break; + + case GPIO_BRK: + if (level == 0) + return PORT_ERR_OK; + if (tcsendbreak(h->fd, 1)) + return PORT_ERR_UNKNOWN; + return PORT_ERR_OK; + + default: + return PORT_ERR_UNKNOWN; + } + + /* handle RTS/DTR */ + if (ioctl(h->fd, TIOCMGET, &lines)) + return PORT_ERR_UNKNOWN; + lines = level ? lines | bit : lines & ~bit; + if (ioctl(h->fd, TIOCMSET, &lines)) + return PORT_ERR_UNKNOWN; + + return PORT_ERR_OK; +} + +static const char *serial_posix_get_cfg_str(struct port_interface *port) +{ + serial_t *h; + + h = (serial_t *)port->private; + return h ? h->setup_str : "INVALID"; +} + +struct port_interface port_serial = { + .name = "serial_posix", + .flags = PORT_BYTE | PORT_GVR_ETX | PORT_CMD_INIT | PORT_RETRY, + .open = serial_posix_open, + .close = serial_posix_close, + .read = serial_posix_read, + .write = serial_posix_write, + .gpio = serial_posix_gpio, + .get_cfg_str = serial_posix_get_cfg_str, +}; diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/serial_w32.c b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/serial_w32.c new file mode 100644 index 0000000..56772c0 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/serial_w32.c @@ -0,0 +1,341 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + Copyright (C) 2010 Gareth McMullin + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "serial.h" +#include "port.h" + +struct serial { + HANDLE fd; + DCB oldtio; + DCB newtio; + char setup_str[11]; +}; + +static serial_t *serial_open(const char *device) +{ + serial_t *h = calloc(sizeof(serial_t), 1); + char *devName; + + /* timeout in ms */ + COMMTIMEOUTS timeouts = {MAXDWORD, MAXDWORD, 500, 0, 0}; + + /* Fix the device name if required */ + if (strlen(device) > 4 && device[0] != '\\') { + devName = calloc(1, strlen(device) + 5); + sprintf(devName, "\\\\.\\%s", device); + } else { + devName = (char *)device; + } + + /* Create file handle for port */ + h->fd = CreateFile(devName, GENERIC_READ | GENERIC_WRITE, + 0, /* Exclusive access */ + NULL, /* No security */ + OPEN_EXISTING, + 0, /* No overlap */ + NULL); + + if (devName != device) + free(devName); + + if (h->fd == INVALID_HANDLE_VALUE) { + if (GetLastError() == ERROR_FILE_NOT_FOUND) + fprintf(stderr, "File not found: %s\n", device); + return NULL; + } + + SetupComm(h->fd, 4096, 4096); /* Set input and output buffer size */ + + SetCommTimeouts(h->fd, &timeouts); + + SetCommMask(h->fd, EV_ERR); /* Notify us of error events */ + + GetCommState(h->fd, &h->oldtio); /* Retrieve port parameters */ + GetCommState(h->fd, &h->newtio); /* Retrieve port parameters */ + + /* PurgeComm(h->fd, PURGE_RXABORT | PURGE_TXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR); */ + + return h; +} + +static void serial_flush(const serial_t *h) +{ + /* We shouldn't need to flush in non-overlapping (blocking) mode */ + /* tcflush(h->fd, TCIFLUSH); */ +} + +static void serial_close(serial_t *h) +{ + serial_flush(h); + SetCommState(h->fd, &h->oldtio); + CloseHandle(h->fd); + free(h); +} + +static port_err_t serial_setup(serial_t *h, + const serial_baud_t baud, + const serial_bits_t bits, + const serial_parity_t parity, + const serial_stopbit_t stopbit) +{ + switch (baud) { + case SERIAL_BAUD_1200: h->newtio.BaudRate = CBR_1200; break; + /* case SERIAL_BAUD_1800: h->newtio.BaudRate = CBR_1800; break; */ + case SERIAL_BAUD_2400: h->newtio.BaudRate = CBR_2400; break; + case SERIAL_BAUD_4800: h->newtio.BaudRate = CBR_4800; break; + case SERIAL_BAUD_9600: h->newtio.BaudRate = CBR_9600; break; + case SERIAL_BAUD_19200: h->newtio.BaudRate = CBR_19200; break; + case SERIAL_BAUD_38400: h->newtio.BaudRate = CBR_38400; break; + case SERIAL_BAUD_57600: h->newtio.BaudRate = CBR_57600; break; + case SERIAL_BAUD_115200: h->newtio.BaudRate = CBR_115200; break; + case SERIAL_BAUD_128000: h->newtio.BaudRate = CBR_128000; break; + case SERIAL_BAUD_256000: h->newtio.BaudRate = CBR_256000; break; + /* These are not defined in WinBase.h and might work or not */ + case SERIAL_BAUD_230400: h->newtio.BaudRate = 230400; break; + case SERIAL_BAUD_460800: h->newtio.BaudRate = 460800; break; + case SERIAL_BAUD_500000: h->newtio.BaudRate = 500000; break; + case SERIAL_BAUD_576000: h->newtio.BaudRate = 576000; break; + case SERIAL_BAUD_921600: h->newtio.BaudRate = 921600; break; + case SERIAL_BAUD_1000000: h->newtio.BaudRate = 1000000; break; + case SERIAL_BAUD_1500000: h->newtio.BaudRate = 1500000; break; + case SERIAL_BAUD_2000000: h->newtio.BaudRate = 2000000; break; + case SERIAL_BAUD_INVALID: + + default: + return PORT_ERR_UNKNOWN; + } + + switch (bits) { + case SERIAL_BITS_5: h->newtio.ByteSize = 5; break; + case SERIAL_BITS_6: h->newtio.ByteSize = 6; break; + case SERIAL_BITS_7: h->newtio.ByteSize = 7; break; + case SERIAL_BITS_8: h->newtio.ByteSize = 8; break; + + default: + return PORT_ERR_UNKNOWN; + } + + switch (parity) { + case SERIAL_PARITY_NONE: h->newtio.Parity = NOPARITY; break; + case SERIAL_PARITY_EVEN: h->newtio.Parity = EVENPARITY; break; + case SERIAL_PARITY_ODD: h->newtio.Parity = ODDPARITY; break; + + default: + return PORT_ERR_UNKNOWN; + } + + switch (stopbit) { + case SERIAL_STOPBIT_1: h->newtio.StopBits = ONESTOPBIT; break; + case SERIAL_STOPBIT_2: h->newtio.StopBits = TWOSTOPBITS; break; + + default: + return PORT_ERR_UNKNOWN; + } + + /* reset the settings */ + h->newtio.fOutxCtsFlow = FALSE; + h->newtio.fOutxDsrFlow = FALSE; + h->newtio.fOutX = FALSE; + h->newtio.fInX = FALSE; + h->newtio.fNull = 0; + h->newtio.fAbortOnError = 0; + + /* set the settings */ + serial_flush(h); + if (!SetCommState(h->fd, &h->newtio)) + return PORT_ERR_UNKNOWN; + + snprintf(h->setup_str, sizeof(h->setup_str), "%u %d%c%d", + serial_get_baud_int(baud), + serial_get_bits_int(bits), + serial_get_parity_str(parity), + serial_get_stopbit_int(stopbit) + ); + return PORT_ERR_OK; +} + +static port_err_t serial_w32_open(struct port_interface *port, + struct port_options *ops) +{ + serial_t *h; + + /* 1. check device name match */ + if (!((strlen(ops->device) == 4 || strlen(ops->device) == 5) + && !strncmp(ops->device, "COM", 3) && isdigit(ops->device[3])) + && !(!strncmp(ops->device, "\\\\.\\COM", strlen("\\\\.\\COM")) + && isdigit(ops->device[strlen("\\\\.\\COM")]))) + return PORT_ERR_NODEV; + + /* 2. check options */ + if (ops->baudRate == SERIAL_BAUD_INVALID) + return PORT_ERR_UNKNOWN; + if (serial_get_bits(ops->serial_mode) == SERIAL_BITS_INVALID) + return PORT_ERR_UNKNOWN; + if (serial_get_parity(ops->serial_mode) == SERIAL_PARITY_INVALID) + return PORT_ERR_UNKNOWN; + if (serial_get_stopbit(ops->serial_mode) == SERIAL_STOPBIT_INVALID) + return PORT_ERR_UNKNOWN; + + /* 3. open it */ + h = serial_open(ops->device); + if (h == NULL) + return PORT_ERR_UNKNOWN; + + /* 4. set options */ + if (serial_setup(h, ops->baudRate, + serial_get_bits(ops->serial_mode), + serial_get_parity(ops->serial_mode), + serial_get_stopbit(ops->serial_mode) + ) != PORT_ERR_OK) { + serial_close(h); + return PORT_ERR_UNKNOWN; + } + + port->private = h; + return PORT_ERR_OK; +} + +static port_err_t serial_w32_close(struct port_interface *port) +{ + serial_t *h; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + serial_close(h); + port->private = NULL; + return PORT_ERR_OK; +} + +static port_err_t serial_w32_read(struct port_interface *port, void *buf, + size_t nbyte) +{ + serial_t *h; + DWORD r; + uint8_t *pos = (uint8_t *)buf; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + while (nbyte) { + ReadFile(h->fd, pos, nbyte, &r, NULL); + if (r == 0) + return PORT_ERR_TIMEDOUT; + if (r < 0) + return PORT_ERR_UNKNOWN; + + nbyte -= r; + pos += r; + } + return PORT_ERR_OK; +} + +static port_err_t serial_w32_write(struct port_interface *port, void *buf, + size_t nbyte) +{ + serial_t *h; + DWORD r; + uint8_t *pos = (uint8_t *)buf; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + while (nbyte) { + if (!WriteFile(h->fd, pos, nbyte, &r, NULL)) + return PORT_ERR_UNKNOWN; + if (r < 1) + return PORT_ERR_UNKNOWN; + + nbyte -= r; + pos += r; + } + return PORT_ERR_OK; +} + +static port_err_t serial_w32_gpio(struct port_interface *port, + serial_gpio_t n, int level) +{ + serial_t *h; + int bit; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + switch (n) { + case GPIO_RTS: + bit = level ? SETRTS : CLRRTS; + break; + + case GPIO_DTR: + bit = level ? SETDTR : CLRDTR; + break; + + case GPIO_BRK: + if (level == 0) + return PORT_ERR_OK; + if (EscapeCommFunction(h->fd, SETBREAK) == 0) + return PORT_ERR_UNKNOWN; + usleep(500000); + if (EscapeCommFunction(h->fd, CLRBREAK) == 0) + return PORT_ERR_UNKNOWN; + return PORT_ERR_OK; + + default: + return PORT_ERR_UNKNOWN; + } + + /* handle RTS/DTR */ + if (EscapeCommFunction(h->fd, bit) == 0) + return PORT_ERR_UNKNOWN; + + return PORT_ERR_OK; +} + +static const char *serial_w32_get_cfg_str(struct port_interface *port) +{ + serial_t *h; + + h = (serial_t *)port->private; + return h ? h->setup_str : "INVALID"; +} + +struct port_interface port_serial = { + .name = "serial_w32", + .flags = PORT_BYTE | PORT_GVR_ETX | PORT_CMD_INIT | PORT_RETRY, + .open = serial_w32_open, + .close = serial_w32_close, + .read = serial_w32_read, + .write = serial_w32_write, + .gpio = serial_w32_gpio, + .get_cfg_str = serial_w32_get_cfg_str, +}; diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/stm32.c b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/stm32.c new file mode 100644 index 0000000..74047d2 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/stm32.c @@ -0,0 +1,1048 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright 2010 Geoffrey McRae + Copyright 2012-2014 Tormod Volden + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include + +#include "stm32.h" +#include "port.h" +#include "utils.h" + +#define STM32_ACK 0x79 +#define STM32_NACK 0x1F +#define STM32_BUSY 0x76 + +#define STM32_CMD_INIT 0x7F +#define STM32_CMD_GET 0x00 /* get the version and command supported */ +#define STM32_CMD_GVR 0x01 /* get version and read protection status */ +#define STM32_CMD_GID 0x02 /* get ID */ +#define STM32_CMD_RM 0x11 /* read memory */ +#define STM32_CMD_GO 0x21 /* go */ +#define STM32_CMD_WM 0x31 /* write memory */ +#define STM32_CMD_WM_NS 0x32 /* no-stretch write memory */ +#define STM32_CMD_ER 0x43 /* erase */ +#define STM32_CMD_EE 0x44 /* extended erase */ +#define STM32_CMD_EE_NS 0x45 /* extended erase no-stretch */ +#define STM32_CMD_WP 0x63 /* write protect */ +#define STM32_CMD_WP_NS 0x64 /* write protect no-stretch */ +#define STM32_CMD_UW 0x73 /* write unprotect */ +#define STM32_CMD_UW_NS 0x74 /* write unprotect no-stretch */ +#define STM32_CMD_RP 0x82 /* readout protect */ +#define STM32_CMD_RP_NS 0x83 /* readout protect no-stretch */ +#define STM32_CMD_UR 0x92 /* readout unprotect */ +#define STM32_CMD_UR_NS 0x93 /* readout unprotect no-stretch */ +#define STM32_CMD_CRC 0xA1 /* compute CRC */ +#define STM32_CMD_ERR 0xFF /* not a valid command */ + +#define STM32_RESYNC_TIMEOUT 35 /* seconds */ +#define STM32_MASSERASE_TIMEOUT 35 /* seconds */ +#define STM32_SECTERASE_TIMEOUT 5 /* seconds */ +#define STM32_BLKWRITE_TIMEOUT 1 /* seconds */ +#define STM32_WUNPROT_TIMEOUT 1 /* seconds */ +#define STM32_WPROT_TIMEOUT 1 /* seconds */ +#define STM32_RPROT_TIMEOUT 1 /* seconds */ + +#define STM32_CMD_GET_LENGTH 17 /* bytes in the reply */ + +struct stm32_cmd { + uint8_t get; + uint8_t gvr; + uint8_t gid; + uint8_t rm; + uint8_t go; + uint8_t wm; + uint8_t er; /* this may be extended erase */ + uint8_t wp; + uint8_t uw; + uint8_t rp; + uint8_t ur; + uint8_t crc; +}; + +/* Reset code for ARMv7-M (Cortex-M3) and ARMv6-M (Cortex-M0) + * see ARMv7-M or ARMv6-M Architecture Reference Manual (table B3-8) + * or "The definitive guide to the ARM Cortex-M3", section 14.4. + */ +static const uint8_t stm_reset_code[] = { + 0x01, 0x49, // ldr r1, [pc, #4] ; () + 0x02, 0x4A, // ldr r2, [pc, #8] ; () + 0x0A, 0x60, // str r2, [r1, #0] + 0xfe, 0xe7, // endless: b endless + 0x0c, 0xed, 0x00, 0xe0, // .word 0xe000ed0c = NVIC AIRCR register address + 0x04, 0x00, 0xfa, 0x05 // .word 0x05fa0004 = VECTKEY | SYSRESETREQ +}; + +static const uint32_t stm_reset_code_length = sizeof(stm_reset_code); + +extern const stm32_dev_t devices[]; + +static void stm32_warn_stretching(const char *f) +{ + fprintf(stderr, "Attention !!!\n"); + fprintf(stderr, "\tThis %s error could be caused by your I2C\n", f); + fprintf(stderr, "\tcontroller not accepting \"clock stretching\"\n"); + fprintf(stderr, "\tas required by bootloader.\n"); + fprintf(stderr, "\tCheck \"I2C.txt\" in stm32flash source code.\n"); +} + +static stm32_err_t stm32_get_ack_timeout(const stm32_t *stm, time_t timeout) +{ + struct port_interface *port = stm->port; + uint8_t byte; + port_err_t p_err; + time_t t0, t1; + + if (!(port->flags & PORT_RETRY)) + timeout = 0; + + if (timeout) + time(&t0); + + do { + p_err = port->read(port, &byte, 1); + if (p_err == PORT_ERR_TIMEDOUT && timeout) { + time(&t1); + if (t1 < t0 + timeout) + continue; + } + + if (p_err != PORT_ERR_OK) { + fprintf(stderr, "Failed to read ACK byte\n"); + return STM32_ERR_UNKNOWN; + } + + if (byte == STM32_ACK) + return STM32_ERR_OK; + if (byte == STM32_NACK) + return STM32_ERR_NACK; + if (byte != STM32_BUSY) { + fprintf(stderr, "Got byte 0x%02x instead of ACK\n", + byte); + return STM32_ERR_UNKNOWN; + } + } while (1); +} + +static stm32_err_t stm32_get_ack(const stm32_t *stm) +{ + return stm32_get_ack_timeout(stm, 0); +} + +static stm32_err_t stm32_send_command_timeout(const stm32_t *stm, + const uint8_t cmd, + time_t timeout) +{ + struct port_interface *port = stm->port; + stm32_err_t s_err; + port_err_t p_err; + uint8_t buf[2]; + + buf[0] = cmd; + buf[1] = cmd ^ 0xFF; + p_err = port->write(port, buf, 2); + if (p_err != PORT_ERR_OK) { + fprintf(stderr, "Failed to send command\n"); + return STM32_ERR_UNKNOWN; + } + s_err = stm32_get_ack_timeout(stm, timeout); + if (s_err == STM32_ERR_OK) + return STM32_ERR_OK; + if (s_err == STM32_ERR_NACK) + fprintf(stderr, "Got NACK from device on command 0x%02x\n", cmd); + else + fprintf(stderr, "Unexpected reply from device on command 0x%02x\n", cmd); + return STM32_ERR_UNKNOWN; +} + +static stm32_err_t stm32_send_command(const stm32_t *stm, const uint8_t cmd) +{ + return stm32_send_command_timeout(stm, cmd, 0); +} + +/* if we have lost sync, send a wrong command and expect a NACK */ +static stm32_err_t stm32_resync(const stm32_t *stm) +{ + struct port_interface *port = stm->port; + port_err_t p_err; + uint8_t buf[2], ack; + time_t t0, t1; + + time(&t0); + t1 = t0; + + buf[0] = STM32_CMD_ERR; + buf[1] = STM32_CMD_ERR ^ 0xFF; + while (t1 < t0 + STM32_RESYNC_TIMEOUT) { + p_err = port->write(port, buf, 2); + if (p_err != PORT_ERR_OK) { + usleep(500000); + time(&t1); + continue; + } + p_err = port->read(port, &ack, 1); + if (p_err != PORT_ERR_OK) { + time(&t1); + continue; + } + if (ack == STM32_NACK) + return STM32_ERR_OK; + time(&t1); + } + return STM32_ERR_UNKNOWN; +} + +/* + * some command receive reply frame with variable length, and length is + * embedded in reply frame itself. + * We can guess the length, but if we guess wrong the protocol gets out + * of sync. + * Use resync for frame oriented interfaces (e.g. I2C) and byte-by-byte + * read for byte oriented interfaces (e.g. UART). + * + * to run safely, data buffer should be allocated for 256+1 bytes + * + * len is value of the first byte in the frame. + */ +static stm32_err_t stm32_guess_len_cmd(const stm32_t *stm, uint8_t cmd, + uint8_t *data, unsigned int len) +{ + struct port_interface *port = stm->port; + port_err_t p_err; + + if (stm32_send_command(stm, cmd) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + if (port->flags & PORT_BYTE) { + /* interface is UART-like */ + p_err = port->read(port, data, 1); + if (p_err != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + len = data[0]; + p_err = port->read(port, data + 1, len + 1); + if (p_err != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + return STM32_ERR_OK; + } + + p_err = port->read(port, data, len + 2); + if (p_err == PORT_ERR_OK && len == data[0]) + return STM32_ERR_OK; + if (p_err != PORT_ERR_OK) { + /* restart with only one byte */ + if (stm32_resync(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + if (stm32_send_command(stm, cmd) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + p_err = port->read(port, data, 1); + if (p_err != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + } + + fprintf(stderr, "Re sync (len = %d)\n", data[0]); + if (stm32_resync(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + len = data[0]; + if (stm32_send_command(stm, cmd) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + p_err = port->read(port, data, len + 2); + if (p_err != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + return STM32_ERR_OK; +} + +/* + * Some interface, e.g. UART, requires a specific init sequence to let STM32 + * autodetect the interface speed. + * The sequence is only required one time after reset. + * stm32flash has command line flag "-c" to prevent sending the init sequence + * in case it was already sent before. + * User can easily forget adding "-c". In this case the bootloader would + * interpret the init sequence as part of a command message, then waiting for + * the rest of the message blocking the interface. + * This function sends the init sequence and, in case of timeout, recovers + * the interface. + */ +static stm32_err_t stm32_send_init_seq(const stm32_t *stm) +{ + struct port_interface *port = stm->port; + port_err_t p_err; + uint8_t byte, cmd = STM32_CMD_INIT; + + p_err = port->write(port, &cmd, 1); + if (p_err != PORT_ERR_OK) { + fprintf(stderr, "Failed to send init to device\n"); + return STM32_ERR_UNKNOWN; + } + p_err = port->read(port, &byte, 1); + if (p_err == PORT_ERR_OK && byte == STM32_ACK) + return STM32_ERR_OK; + if (p_err == PORT_ERR_OK && byte == STM32_NACK) { + /* We could get error later, but let's continue, for now. */ + fprintf(stderr, + "Warning: the interface was not closed properly.\n"); + return STM32_ERR_OK; + } + if (p_err != PORT_ERR_TIMEDOUT) { + fprintf(stderr, "Failed to init device.\n"); + return STM32_ERR_UNKNOWN; + } + + /* + * Check if previous STM32_CMD_INIT was taken as first byte + * of a command. Send a new byte, we should get back a NACK. + */ + p_err = port->write(port, &cmd, 1); + if (p_err != PORT_ERR_OK) { + fprintf(stderr, "Failed to send init to device\n"); + return STM32_ERR_UNKNOWN; + } + p_err = port->read(port, &byte, 1); + if (p_err == PORT_ERR_OK && byte == STM32_NACK) + return STM32_ERR_OK; + fprintf(stderr, "Failed to init device.\n"); + return STM32_ERR_UNKNOWN; +} + +/* find newer command by higher code */ +#define newer(prev, a) (((prev) == STM32_CMD_ERR) \ + ? (a) \ + : (((prev) > (a)) ? (prev) : (a))) + +stm32_t *stm32_init(struct port_interface *port, const char init) +{ + uint8_t len, val, buf[257]; + stm32_t *stm; + int i, new_cmds; + + stm = calloc(sizeof(stm32_t), 1); + stm->cmd = malloc(sizeof(stm32_cmd_t)); + memset(stm->cmd, STM32_CMD_ERR, sizeof(stm32_cmd_t)); + stm->port = port; + + if ((port->flags & PORT_CMD_INIT) && init) + if (stm32_send_init_seq(stm) != STM32_ERR_OK) + return NULL; + + /* get the version and read protection status */ + if (stm32_send_command(stm, STM32_CMD_GVR) != STM32_ERR_OK) { + stm32_close(stm); + return NULL; + } + + /* From AN, only UART bootloader returns 3 bytes */ + len = (port->flags & PORT_GVR_ETX) ? 3 : 1; + if (port->read(port, buf, len) != PORT_ERR_OK) + return NULL; + stm->version = buf[0]; + stm->option1 = (port->flags & PORT_GVR_ETX) ? buf[1] : 0; + stm->option2 = (port->flags & PORT_GVR_ETX) ? buf[2] : 0; + if (stm32_get_ack(stm) != STM32_ERR_OK) { + stm32_close(stm); + return NULL; + } + + /* get the bootloader information */ + len = STM32_CMD_GET_LENGTH; + if (port->cmd_get_reply) + for (i = 0; port->cmd_get_reply[i].length; i++) + if (stm->version == port->cmd_get_reply[i].version) { + len = port->cmd_get_reply[i].length; + break; + } + if (stm32_guess_len_cmd(stm, STM32_CMD_GET, buf, len) != STM32_ERR_OK) + return NULL; + len = buf[0] + 1; + stm->bl_version = buf[1]; + new_cmds = 0; + for (i = 1; i < len; i++) { + val = buf[i + 1]; + switch (val) { + case STM32_CMD_GET: + stm->cmd->get = val; break; + case STM32_CMD_GVR: + stm->cmd->gvr = val; break; + case STM32_CMD_GID: + stm->cmd->gid = val; break; + case STM32_CMD_RM: + stm->cmd->rm = val; break; + case STM32_CMD_GO: + stm->cmd->go = val; break; + case STM32_CMD_WM: + case STM32_CMD_WM_NS: + stm->cmd->wm = newer(stm->cmd->wm, val); + break; + case STM32_CMD_ER: + case STM32_CMD_EE: + case STM32_CMD_EE_NS: + stm->cmd->er = newer(stm->cmd->er, val); + break; + case STM32_CMD_WP: + case STM32_CMD_WP_NS: + stm->cmd->wp = newer(stm->cmd->wp, val); + break; + case STM32_CMD_UW: + case STM32_CMD_UW_NS: + stm->cmd->uw = newer(stm->cmd->uw, val); + break; + case STM32_CMD_RP: + case STM32_CMD_RP_NS: + stm->cmd->rp = newer(stm->cmd->rp, val); + break; + case STM32_CMD_UR: + case STM32_CMD_UR_NS: + stm->cmd->ur = newer(stm->cmd->ur, val); + break; + case STM32_CMD_CRC: + stm->cmd->crc = newer(stm->cmd->crc, val); + break; + default: + if (new_cmds++ == 0) + fprintf(stderr, + "GET returns unknown commands (0x%2x", + val); + else + fprintf(stderr, ", 0x%2x", val); + } + } + if (new_cmds) + fprintf(stderr, ")\n"); + if (stm32_get_ack(stm) != STM32_ERR_OK) { + stm32_close(stm); + return NULL; + } + + if (stm->cmd->get == STM32_CMD_ERR + || stm->cmd->gvr == STM32_CMD_ERR + || stm->cmd->gid == STM32_CMD_ERR) { + fprintf(stderr, "Error: bootloader did not returned correct information from GET command\n"); + return NULL; + } + + /* get the device ID */ + if (stm32_guess_len_cmd(stm, stm->cmd->gid, buf, 1) != STM32_ERR_OK) { + stm32_close(stm); + return NULL; + } + len = buf[0] + 1; + if (len < 2) { + stm32_close(stm); + fprintf(stderr, "Only %d bytes sent in the PID, unknown/unsupported device\n", len); + return NULL; + } + stm->pid = (buf[1] << 8) | buf[2]; + if (len > 2) { + fprintf(stderr, "This bootloader returns %d extra bytes in PID:", len); + for (i = 2; i <= len ; i++) + fprintf(stderr, " %02x", buf[i]); + fprintf(stderr, "\n"); + } + if (stm32_get_ack(stm) != STM32_ERR_OK) { + stm32_close(stm); + return NULL; + } + + stm->dev = devices; + while (stm->dev->id != 0x00 && stm->dev->id != stm->pid) + ++stm->dev; + + if (!stm->dev->id) { + fprintf(stderr, "Unknown/unsupported device (Device ID: 0x%03x)\n", stm->pid); + stm32_close(stm); + return NULL; + } + + return stm; +} + +void stm32_close(stm32_t *stm) +{ + if (stm) + free(stm->cmd); + free(stm); +} + +stm32_err_t stm32_read_memory(const stm32_t *stm, uint32_t address, + uint8_t data[], unsigned int len) +{ + struct port_interface *port = stm->port; + uint8_t buf[5]; + + if (!len) + return STM32_ERR_OK; + + if (len > 256) { + fprintf(stderr, "Error: READ length limit at 256 bytes\n"); + return STM32_ERR_UNKNOWN; + } + + if (stm->cmd->rm == STM32_CMD_ERR) { + fprintf(stderr, "Error: READ command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->rm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + buf[0] = address >> 24; + buf[1] = (address >> 16) & 0xFF; + buf[2] = (address >> 8) & 0xFF; + buf[3] = address & 0xFF; + buf[4] = buf[0] ^ buf[1] ^ buf[2] ^ buf[3]; + if (port->write(port, buf, 5) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + if (stm32_get_ack(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (stm32_send_command(stm, len - 1) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (port->read(port, data, len) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + + return STM32_ERR_OK; +} + +stm32_err_t stm32_write_memory(const stm32_t *stm, uint32_t address, + const uint8_t data[], unsigned int len) +{ + struct port_interface *port = stm->port; + uint8_t cs, buf[256 + 2]; + unsigned int i, aligned_len; + stm32_err_t s_err; + + if (!len) + return STM32_ERR_OK; + + if (len > 256) { + fprintf(stderr, "Error: READ length limit at 256 bytes\n"); + return STM32_ERR_UNKNOWN; + } + + /* must be 32bit aligned */ + if (address & 0x3 || len & 0x3) { + fprintf(stderr, "Error: WRITE address and length must be 4 byte aligned\n"); + return STM32_ERR_UNKNOWN; + } + + if (stm->cmd->wm == STM32_CMD_ERR) { + fprintf(stderr, "Error: WRITE command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + /* send the address and checksum */ + if (stm32_send_command(stm, stm->cmd->wm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + buf[0] = address >> 24; + buf[1] = (address >> 16) & 0xFF; + buf[2] = (address >> 8) & 0xFF; + buf[3] = address & 0xFF; + buf[4] = buf[0] ^ buf[1] ^ buf[2] ^ buf[3]; + if (port->write(port, buf, 5) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + if (stm32_get_ack(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + aligned_len = (len + 3) & ~3; + cs = aligned_len - 1; + buf[0] = aligned_len - 1; + for (i = 0; i < len; i++) { + cs ^= data[i]; + buf[i + 1] = data[i]; + } + /* padding data */ + for (i = len; i < aligned_len; i++) { + cs ^= 0xFF; + buf[i + 1] = 0xFF; + } + buf[aligned_len + 1] = cs; + if (port->write(port, buf, aligned_len + 2) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + + s_err = stm32_get_ack_timeout(stm, STM32_BLKWRITE_TIMEOUT); + if (s_err != STM32_ERR_OK) { + if (port->flags & PORT_STRETCH_W + && stm->cmd->wm != STM32_CMD_WM_NS) + stm32_warn_stretching("write"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; +} + +stm32_err_t stm32_wunprot_memory(const stm32_t *stm) +{ + struct port_interface *port = stm->port; + stm32_err_t s_err; + + if (stm->cmd->uw == STM32_CMD_ERR) { + fprintf(stderr, "Error: WRITE UNPROTECT command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->uw) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + s_err = stm32_get_ack_timeout(stm, STM32_WUNPROT_TIMEOUT); + if (s_err == STM32_NACK) { + fprintf(stderr, "Error: Failed to WRITE UNPROTECT\n"); + return STM32_ERR_UNKNOWN; + } + if (s_err != STM32_ERR_OK) { + if (port->flags & PORT_STRETCH_W + && stm->cmd->uw != STM32_CMD_UW_NS) + stm32_warn_stretching("WRITE UNPROTECT"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; +} + +stm32_err_t stm32_wprot_memory(const stm32_t *stm) +{ + struct port_interface *port = stm->port; + stm32_err_t s_err; + + if (stm->cmd->wp == STM32_CMD_ERR) { + fprintf(stderr, "Error: WRITE PROTECT command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->wp) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + s_err = stm32_get_ack_timeout(stm, STM32_WPROT_TIMEOUT); + if (s_err == STM32_NACK) { + fprintf(stderr, "Error: Failed to WRITE PROTECT\n"); + return STM32_ERR_UNKNOWN; + } + if (s_err != STM32_ERR_OK) { + if (port->flags & PORT_STRETCH_W + && stm->cmd->wp != STM32_CMD_WP_NS) + stm32_warn_stretching("WRITE PROTECT"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; +} + +stm32_err_t stm32_runprot_memory(const stm32_t *stm) +{ + struct port_interface *port = stm->port; + stm32_err_t s_err; + + if (stm->cmd->ur == STM32_CMD_ERR) { + fprintf(stderr, "Error: READOUT UNPROTECT command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->ur) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + s_err = stm32_get_ack_timeout(stm, STM32_MASSERASE_TIMEOUT); + if (s_err == STM32_NACK) { + fprintf(stderr, "Error: Failed to READOUT UNPROTECT\n"); + return STM32_ERR_UNKNOWN; + } + if (s_err != STM32_ERR_OK) { + if (port->flags & PORT_STRETCH_W + && stm->cmd->ur != STM32_CMD_UR_NS) + stm32_warn_stretching("READOUT UNPROTECT"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; +} + +stm32_err_t stm32_readprot_memory(const stm32_t *stm) +{ + struct port_interface *port = stm->port; + stm32_err_t s_err; + + if (stm->cmd->rp == STM32_CMD_ERR) { + fprintf(stderr, "Error: READOUT PROTECT command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->rp) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + s_err = stm32_get_ack_timeout(stm, STM32_RPROT_TIMEOUT); + if (s_err == STM32_NACK) { + fprintf(stderr, "Error: Failed to READOUT PROTECT\n"); + return STM32_ERR_UNKNOWN; + } + if (s_err != STM32_ERR_OK) { + if (port->flags & PORT_STRETCH_W + && stm->cmd->rp != STM32_CMD_RP_NS) + stm32_warn_stretching("READOUT PROTECT"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; +} + +stm32_err_t stm32_erase_memory(const stm32_t *stm, uint8_t spage, uint8_t pages) +{ + struct port_interface *port = stm->port; + stm32_err_t s_err; + port_err_t p_err; + + if (!pages) + return STM32_ERR_OK; + + if (stm->cmd->er == STM32_CMD_ERR) { + fprintf(stderr, "Error: ERASE command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->er) != STM32_ERR_OK) { + fprintf(stderr, "Can't initiate chip erase!\n"); + return STM32_ERR_UNKNOWN; + } + + /* The erase command reported by the bootloader is either 0x43, 0x44 or 0x45 */ + /* 0x44 is Extended Erase, a 2 byte based protocol and needs to be handled differently. */ + /* 0x45 is clock no-stretching version of Extended Erase for I2C port. */ + if (stm->cmd->er != STM32_CMD_ER) { + /* Not all chips using Extended Erase support mass erase */ + /* Currently known as not supporting mass erase is the Ultra Low Power STM32L15xx range */ + /* So if someone has not overridden the default, but uses one of these chips, take it out of */ + /* mass erase mode, so it will be done page by page. This maximum might not be correct either! */ + if (stm->pid == 0x416 && pages == 0xFF) + pages = 0xF8; /* works for the STM32L152RB with 128Kb flash */ + + if (pages == 0xFF) { + uint8_t buf[3]; + + /* 0xFFFF the magic number for mass erase */ + buf[0] = 0xFF; + buf[1] = 0xFF; + buf[2] = 0x00; /* checksum */ + if (port->write(port, buf, 3) != PORT_ERR_OK) { + fprintf(stderr, "Mass erase error.\n"); + return STM32_ERR_UNKNOWN; + } + s_err = stm32_get_ack_timeout(stm, STM32_MASSERASE_TIMEOUT); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Mass erase failed. Try specifying the number of pages to be erased.\n"); + if (port->flags & PORT_STRETCH_W + && stm->cmd->er != STM32_CMD_EE_NS) + stm32_warn_stretching("erase"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; + } + + uint16_t pg_num; + uint8_t pg_byte; + uint8_t cs = 0; + uint8_t *buf; + int i = 0; + + buf = malloc(2 + 2 * pages + 1); + if (!buf) + return STM32_ERR_UNKNOWN; + + /* Number of pages to be erased - 1, two bytes, MSB first */ + pg_byte = (pages - 1) >> 8; + buf[i++] = pg_byte; + cs ^= pg_byte; + pg_byte = (pages - 1) & 0xFF; + buf[i++] = pg_byte; + cs ^= pg_byte; + + for (pg_num = spage; pg_num < spage + pages; pg_num++) { + pg_byte = pg_num >> 8; + cs ^= pg_byte; + buf[i++] = pg_byte; + pg_byte = pg_num & 0xFF; + cs ^= pg_byte; + buf[i++] = pg_byte; + } + buf[i++] = cs; + p_err = port->write(port, buf, i); + free(buf); + if (p_err != PORT_ERR_OK) { + fprintf(stderr, "Page-by-page erase error.\n"); + return STM32_ERR_UNKNOWN; + } + + s_err = stm32_get_ack_timeout(stm, pages * STM32_SECTERASE_TIMEOUT); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Page-by-page erase failed. Check the maximum pages your device supports.\n"); + if (port->flags & PORT_STRETCH_W + && stm->cmd->er != STM32_CMD_EE_NS) + stm32_warn_stretching("erase"); + return STM32_ERR_UNKNOWN; + } + + return STM32_ERR_OK; + } + + /* And now the regular erase (0x43) for all other chips */ + if (pages == 0xFF) { + s_err = stm32_send_command_timeout(stm, 0xFF, STM32_MASSERASE_TIMEOUT); + if (s_err != STM32_ERR_OK) { + if (port->flags & PORT_STRETCH_W) + stm32_warn_stretching("erase"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; + } else { + uint8_t cs = 0; + uint8_t pg_num; + uint8_t *buf; + int i = 0; + + buf = malloc(1 + pages + 1); + if (!buf) + return STM32_ERR_UNKNOWN; + + buf[i++] = pages - 1; + cs ^= (pages-1); + for (pg_num = spage; pg_num < (pages + spage); pg_num++) { + buf[i++] = pg_num; + cs ^= pg_num; + } + buf[i++] = cs; + p_err = port->write(port, buf, i); + free(buf); + if (p_err != PORT_ERR_OK) { + fprintf(stderr, "Erase failed.\n"); + return STM32_ERR_UNKNOWN; + } + s_err = stm32_get_ack_timeout(stm, STM32_MASSERASE_TIMEOUT); + if (s_err != STM32_ERR_OK) { + if (port->flags & PORT_STRETCH_W) + stm32_warn_stretching("erase"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; + } +} + +static stm32_err_t stm32_run_raw_code(const stm32_t *stm, + uint32_t target_address, + const uint8_t *code, uint32_t code_size) +{ + uint32_t stack_le = le_u32(0x20002000); + uint32_t code_address_le = le_u32(target_address + 8); + uint32_t length = code_size + 8; + uint8_t *mem, *pos; + uint32_t address, w; + + /* Must be 32-bit aligned */ + if (target_address & 0x3) { + fprintf(stderr, "Error: code address must be 4 byte aligned\n"); + return STM32_ERR_UNKNOWN; + } + + mem = malloc(length); + if (!mem) + return STM32_ERR_UNKNOWN; + + memcpy(mem, &stack_le, sizeof(uint32_t)); + memcpy(mem + 4, &code_address_le, sizeof(uint32_t)); + memcpy(mem + 8, code, code_size); + + pos = mem; + address = target_address; + while (length > 0) { + w = length > 256 ? 256 : length; + if (stm32_write_memory(stm, address, pos, w) != STM32_ERR_OK) { + free(mem); + return STM32_ERR_UNKNOWN; + } + + address += w; + pos += w; + length -= w; + } + + free(mem); + return stm32_go(stm, target_address); +} + +stm32_err_t stm32_go(const stm32_t *stm, uint32_t address) +{ + struct port_interface *port = stm->port; + uint8_t buf[5]; + + if (stm->cmd->go == STM32_CMD_ERR) { + fprintf(stderr, "Error: GO command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->go) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + buf[0] = address >> 24; + buf[1] = (address >> 16) & 0xFF; + buf[2] = (address >> 8) & 0xFF; + buf[3] = address & 0xFF; + buf[4] = buf[0] ^ buf[1] ^ buf[2] ^ buf[3]; + if (port->write(port, buf, 5) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (stm32_get_ack(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + return STM32_ERR_OK; +} + +stm32_err_t stm32_reset_device(const stm32_t *stm) +{ + uint32_t target_address = stm->dev->ram_start; + + return stm32_run_raw_code(stm, target_address, stm_reset_code, stm_reset_code_length); +} + +stm32_err_t stm32_crc_memory(const stm32_t *stm, uint32_t address, + uint32_t length, uint32_t *crc) +{ + struct port_interface *port = stm->port; + uint8_t buf[5]; + + if (address & 0x3 || length & 0x3) { + fprintf(stderr, "Start and end addresses must be 4 byte aligned\n"); + return STM32_ERR_UNKNOWN; + } + + if (stm->cmd->crc == STM32_CMD_ERR) { + fprintf(stderr, "Error: CRC command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->crc) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + buf[0] = address >> 24; + buf[1] = (address >> 16) & 0xFF; + buf[2] = (address >> 8) & 0xFF; + buf[3] = address & 0xFF; + buf[4] = buf[0] ^ buf[1] ^ buf[2] ^ buf[3]; + if (port->write(port, buf, 5) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (stm32_get_ack(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + buf[0] = length >> 24; + buf[1] = (length >> 16) & 0xFF; + buf[2] = (length >> 8) & 0xFF; + buf[3] = length & 0xFF; + buf[4] = buf[0] ^ buf[1] ^ buf[2] ^ buf[3]; + if (port->write(port, buf, 5) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (stm32_get_ack(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (stm32_get_ack(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (port->read(port, buf, 5) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (buf[4] != (buf[0] ^ buf[1] ^ buf[2] ^ buf[3])) + return STM32_ERR_UNKNOWN; + + *crc = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; + return STM32_ERR_OK; +} + +/* + * CRC computed by STM32 is similar to the standard crc32_be() + * implemented, for example, in Linux kernel in ./lib/crc32.c + * But STM32 computes it on units of 32 bits word and swaps the + * bytes of the word before the computation. + * Due to byte swap, I cannot use any CRC available in existing + * libraries, so here is a simple not optimized implementation. + */ +#define CRCPOLY_BE 0x04c11db7 +#define CRC_MSBMASK 0x80000000 +#define CRC_INIT_VALUE 0xFFFFFFFF +uint32_t stm32_sw_crc(uint32_t crc, uint8_t *buf, unsigned int len) +{ + int i; + uint32_t data; + + if (len & 0x3) { + fprintf(stderr, "Buffer length must be multiple of 4 bytes\n"); + return 0; + } + + while (len) { + data = *buf++; + data |= *buf++ << 8; + data |= *buf++ << 16; + data |= *buf++ << 24; + len -= 4; + + crc ^= data; + + for (i = 0; i < 32; i++) + if (crc & CRC_MSBMASK) + crc = (crc << 1) ^ CRCPOLY_BE; + else + crc = (crc << 1); + } + return crc; +} + +stm32_err_t stm32_crc_wrapper(const stm32_t *stm, uint32_t address, + uint32_t length, uint32_t *crc) +{ + uint8_t buf[256]; + uint32_t start, total_len, len, current_crc; + + if (address & 0x3 || length & 0x3) { + fprintf(stderr, "Start and end addresses must be 4 byte aligned\n"); + return STM32_ERR_UNKNOWN; + } + + if (stm->cmd->crc != STM32_CMD_ERR) + return stm32_crc_memory(stm, address, length, crc); + + start = address; + total_len = length; + current_crc = CRC_INIT_VALUE; + while (length) { + len = length > 256 ? 256 : length; + if (stm32_read_memory(stm, address, buf, len) != STM32_ERR_OK) { + fprintf(stderr, + "Failed to read memory at address 0x%08x, target write-protected?\n", + address); + return STM32_ERR_UNKNOWN; + } + current_crc = stm32_sw_crc(current_crc, buf, len); + length -= len; + address += len; + + fprintf(stderr, + "\rCRC address 0x%08x (%.2f%%) ", + address, + (100.0f / (float)total_len) * (float)(address - start) + ); + fflush(stderr); + } + fprintf(stderr, "Done.\n"); + *crc = current_crc; + return STM32_ERR_OK; +} diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/stm32.h b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/stm32.h new file mode 100644 index 0000000..1688fcb --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/stm32.h @@ -0,0 +1,84 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _STM32_H +#define _STM32_H + +#include +#include "serial.h" + +#define STM32_MAX_RX_FRAME 256 /* cmd read memory */ +#define STM32_MAX_TX_FRAME (1 + 256 + 1) /* cmd write memory */ + +typedef enum { + STM32_ERR_OK = 0, + STM32_ERR_UNKNOWN, /* Generic error */ + STM32_ERR_NACK, + STM32_ERR_NO_CMD, /* Command not available in bootloader */ +} stm32_err_t; + +typedef struct stm32 stm32_t; +typedef struct stm32_cmd stm32_cmd_t; +typedef struct stm32_dev stm32_dev_t; + +struct stm32 { + const serial_t *serial; + struct port_interface *port; + uint8_t bl_version; + uint8_t version; + uint8_t option1, option2; + uint16_t pid; + stm32_cmd_t *cmd; + const stm32_dev_t *dev; +}; + +struct stm32_dev { + uint16_t id; + const char *name; + uint32_t ram_start, ram_end; + uint32_t fl_start, fl_end; + uint16_t fl_pps; // pages per sector + uint16_t fl_ps; // page size + uint32_t opt_start, opt_end; + uint32_t mem_start, mem_end; +}; + +stm32_t *stm32_init(struct port_interface *port, const char init); +void stm32_close(stm32_t *stm); +stm32_err_t stm32_read_memory(const stm32_t *stm, uint32_t address, + uint8_t data[], unsigned int len); +stm32_err_t stm32_write_memory(const stm32_t *stm, uint32_t address, + const uint8_t data[], unsigned int len); +stm32_err_t stm32_wunprot_memory(const stm32_t *stm); +stm32_err_t stm32_wprot_memory(const stm32_t *stm); +stm32_err_t stm32_erase_memory(const stm32_t *stm, uint8_t spage, + uint8_t pages); +stm32_err_t stm32_go(const stm32_t *stm, uint32_t address); +stm32_err_t stm32_reset_device(const stm32_t *stm); +stm32_err_t stm32_readprot_memory(const stm32_t *stm); +stm32_err_t stm32_runprot_memory(const stm32_t *stm); +stm32_err_t stm32_crc_memory(const stm32_t *stm, uint32_t address, + uint32_t length, uint32_t *crc); +stm32_err_t stm32_crc_wrapper(const stm32_t *stm, uint32_t address, + uint32_t length, uint32_t *crc); +uint32_t stm32_sw_crc(uint32_t crc, uint8_t *buf, unsigned int len); + +#endif + diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/stm32flash.1 b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/stm32flash.1 new file mode 100644 index 0000000..d37292f --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/stm32flash.1 @@ -0,0 +1,407 @@ +.TH STM32FLASH 1 "2013\-11\-03" STM32FLASH "User command" +.SH NAME +stm32flash \- flashing utility for STM32 and STM32W through UART or I2C +.SH SYNOPSIS +.B stm32flash +.RB [ \-cfhjkouvCR ] +.RB [ \-a +.IR bus_address ] +.RB [ \-b +.IR baud_rate ] +.RB [ \-m +.IR serial_mode ] +.RB [ \-r +.IR filename ] +.RB [ \-w +.IR filename ] +.RB [ \-e +.IR num ] +.RB [ \-n +.IR count ] +.RB [ \-g +.IR address ] +.RB [ \-s +.IR start_page ] +.RB [ \-S +.IR address [: length ]] +.RB [ \-F +.IR RX_length [: TX_length ]] +.RB [ \-i +.IR GPIO_string ] +.RI [ tty_device +.R | +.IR i2c_device ] + +.SH DESCRIPTION +.B stm32flash +reads or writes the flash memory of STM32 and STM32W. + +It requires the STM32[W] to embed a bootloader compliant with ST +application note AN3155. +.B stm32flash +uses the serial port +.I tty_device +to interact with the bootloader of STM32[W]. + +.SH OPTIONS +.TP +.BI "\-a" " bus_address" +Specify address on bus for +.IR i2c_device . +This option is mandatory for I2C interface. + +.TP +.BI "\-b" " baud_rate" +Specify baud rate speed of +.IR tty_device . +Please notice that the ST bootloader can automatically detect the baud rate, +as explaned in chapter 2 of AN3155. +This option could be required together with option +.B "\-c" +or if following interaction with bootloader is expected. +Default is +.IR 57600 . + +.TP +.BI "\-m" " mode" +Specify the format of UART data. +.I mode +is a three characters long string where each character specifies, in +this strict order, character size, parity and stop bits. +The only values currenly used are +.I 8e1 +for standard STM32 bootloader and +.I 8n1 +for standard STM32W bootloader. +Default is +.IR 8e1 . + +.TP +.BI "\-r" " filename" +Specify to read the STM32[W] flash and write its content in +.I filename +in raw binary format (see below +.BR "FORMAT CONVERSION" ). + +.TP +.BI "\-w" " filename" +Specify to write the STM32[W] flash with the content of +.IR filename . +File format can be either raw binary or intel hex (see below +.BR "FORMAT CONVERSION" ). +The file format is automatically detected. +To by\-pass format detection and force binary mode (e.g. to +write an intel hex content in STM32[W] flash), use +.B \-f +option. + +.TP +.B \-u +Specify to disable write\-protection from STM32[W] flash. +The STM32[W] will be reset after this operation. + +.TP +.B \-j +Enable the flash read\-protection. + +.TP +.B \-k +Disable the flash read\-protection. + +.TP +.B \-o +Erase only. + +.TP +.BI "\-e" " num" +Specify to erase only +.I num +pages before writing the flash. Default is to erase the whole flash. With +.B \-e 0 +the flash would not be erased. + +.TP +.B \-v +Specify to verify flash content after write operation. + +.TP +.BI "\-n" " count" +Specify to retry failed writes up to +.I count +times. Default is 10 times. + +.TP +.BI "\-g" " address" +Specify address to start execution from (0 = flash start). + +.TP +.BI "\-s" " start_page" +Specify flash page offset (0 = flash start). + +.TP +.BI "\-S" " address" "[:" "length" "]" +Specify start address and optionally length for read/write/erase/crc operations. + +.TP +.BI "\-F" " RX_length" "[:" "TX_length" "]" +Specify the maximum frame size for the current interface. +Due to STM32 bootloader protocol, host will never handle frames bigger than +256 byte in RX or 258 byte in TX. +Due to current code, lowest limit in RX is 20 byte (to read a complete reply +of command GET). Minimum limit in TX is 5 byte, required by protocol. + +.TP +.B \-f +Force binary parser while reading file with +.BR "\-w" "." + +.TP +.B \-h +Show help. + +.TP +.B \-c +Specify to resume the existing UART connection and don't send initial +INIT sequence to detect baud rate. Baud rate must be kept the same as the +existing connection. This is useful if the reset fails. + +.TP +.BI "\-i" " GPIO_string" +Specify the GPIO sequences on the host to force STM32[W] to enter and +exit bootloader mode. GPIO can either be real GPIO connected from host to +STM32[W] beside the UART connection, or UART's modem signals used as +GPIO. (See below +.B BOOTLOADER GPIO SEQUENCE +for the format of +.I GPIO_string +and further explanation). + +.TP +.B \-C +Specify to compute CRC on memory content. +By default the CRC is computed on the whole flash content. +Use +.B "\-S" +to provide different memory address range. + +.TP +.B \-R +Specify to reset the device at exit. +This option is ignored if either +.BR "\-g" "," +.BR "\-j" "," +.B "\-k" +or +.B "\-u" +is also specified. + +.SH BOOTLOADER GPIO SEQUENCE +This feature is currently available on Linux host only. + +As explained in ST application note AN2606, after reset the STM32 will +execute either the application program in user flash or the bootloader, +depending on the level applied at specific pins of STM32 during reset. + +STM32 bootloader is automatically activated by configuring the pins +BOOT0="high" and BOOT1="low" and then by applying a reset. +Application program in user flash is activated by configuring the pin +BOOT0="low" (the level on BOOT1 is ignored) and then by applying a reset. + +When GPIO from host computer are connected to either configuration and +reset pins of STM32, +.B stm32flash +can control the host GPIO to reset STM32 and to force execution of +bootloader or execution of application program. + +The sequence of GPIO values to entry to and exit from bootloader mode is +provided with command line option +.B "\-i" +.IR "GPIO_string" . + +.PD 0 +The format of +.IR "GPIO_string" " is:" +.RS +GPIO_string = [entry sequence][:[exit sequence]] +.P +sequence = [\-]n[,sequence] +.RE +.P +In the above sequences, negative numbers correspond to GPIO at "low" level; +numbers without sign correspond to GPIO at "high" level. +The value "n" can either be the GPIO number on the host system or the +string "rts", "dtr" or "brk". The strings "rts" and "dtr" drive the +corresponding UART's modem lines RTS and DTR as GPIO. +The string "brk" forces the UART to send a BREAK sequence on TX line; +after BREAK the UART is returned in normal "non\-break" mode. +Note: the string "\-brk" has no effect and is ignored. +.PD + +.PD 0 +As example, let's suppose the following connection between host and STM32: +.IP \(bu 2 +host GPIO_3 connected to reset pin of STM32; +.IP \(bu 2 +host GPIO_4 connected to STM32 pin BOOT0; +.IP \(bu 2 +host GPIO_5 connected to STM32 pin BOOT1. +.PD +.P + +In this case, the sequence to enter in bootloader mode is: first put +GPIO_4="high" and GPIO_5="low"; then send reset pulse by GPIO_3="low" +followed by GPIO_3="high". +The corresponding string for +.I GPIO_string +is "4,\-5,\-3,3". + +To exit from bootloade and run the application program, the sequence is: +put GPIO_4="low"; then send reset pulse. +The corresponding string for +.I GPIO_string +is "\-4,\-3,3". + +The complete command line flag is "\-i 4,\-5,\-3,3:\-4,\-3,3". + +STM32W uses pad PA5 to select boot mode; if during reset PA5 is "low" then +STM32W will enter in bootloader mode; if PA5 is "high" it will execute the +program in flash. + +As example, supposing GPIO_3 connected to PA5 and GPIO_2 to STM32W's reset. +The command: +.PD 0 +.RS +stm32flash \-i \-3,\-2,2:3,\-2,2 /dev/ttyS0 +.RE +provides: +.IP \(bu 2 +entry sequence: GPIO_3=low, GPIO_2=low, GPIO_2=high +.IP \(bu 2 +exit sequence: GPIO_3=high, GPIO_2=low, GPIO_2=high +.PD + +.SH EXAMPLES +Get device information: +.RS +.PD 0 +.P +stm32flash /dev/ttyS0 +.PD +.RE + +Write with verify and then start execution: +.RS +.PD 0 +.P +stm32flash \-w filename \-v \-g 0x0 /dev/ttyS0 +.PD +.RE + +Read flash to file: +.RS +.PD 0 +.P +stm32flash \-r filename /dev/ttyS0 +.PD +.RE + +Start execution: +.RS +.PD 0 +.P +stm32flash \-g 0x0 /dev/ttyS0 +.PD +.RE + +Specify: +.PD 0 +.IP \(bu 2 +entry sequence: RTS=low, DTR=low, DTR=high +.IP \(bu 2 +exit sequence: RTS=high, DTR=low, DTR=high +.P +.RS +stm32flash \-i \-rts,\-dtr,dtr:rts,\-dtr,dtr /dev/ttyS0 +.PD +.RE + +.SH FORMAT CONVERSION +Flash images provided by ST or created with ST tools are often in file +format Motorola S\-Record. +Conversion between raw binary, intel hex and Motorola S\-Record can be +done through software package SRecord. + +.SH AUTHORS +The original software package +.B stm32flash +is written by +.I Geoffrey McRae +and is since 2012 maintained by +.IR "Tormod Volden " . + +Man page and extension to STM32W and I2C are written by +.IR "Antonio Borneo " . + +Please report any bugs at the project homepage +http://stm32flash.googlecode.com . + +.SH SEE ALSO +.BR "srec_cat" "(1)," " srec_intel" "(5)," " srec_motorola" "(5)." + +The communication protocol used by ST bootloader is documented in +following ST application notes, depending on communication port. +The current version of +.B stm32flash +only supports +.I UART +and +.I I2C +ports. +.PD 0 +.P +.IP \(bu 2 +AN3154: CAN protocol used in the STM32 bootloader +.P +.RS +http://www.st.com/web/en/resource/technical/document/application_note/CD00264321.pdf +.RE + +.P +.IP \(bu 2 +AN3155: USART protocol used in the STM32(TM) bootloader +.P +.RS +http://www.st.com/web/en/resource/technical/document/application_note/CD00264342.pdf +.RE + +.P +.IP \(bu 2 +AN4221: I2C protocol used in the STM32 bootloader +.P +.RS +http://www.st.com/web/en/resource/technical/document/application_note/DM00072315.pdf +.RE + +.P +.IP \(bu 2 +AN4286: SPI protocol used in the STM32 bootloader +.P +.RS +http://www.st.com/web/en/resource/technical/document/application_note/DM00081379.pdf +.RE + +.PD + + +Boot mode selection for STM32 is documented in ST application note +AN2606, available from the ST website: +.PD 0 +.P +http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf +.PD + +.SH LICENSE +.B stm32flash +is distributed under GNU GENERAL PUBLIC LICENSE Version 2. +Copy of the license is available within the source code in the file +.IR "gpl\-2.0.txt" . diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/utils.c b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/utils.c new file mode 100644 index 0000000..271bb3e --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/utils.c @@ -0,0 +1,45 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include "utils.h" + +/* detect CPU endian */ +char cpu_le() { + const uint32_t cpu_le_test = 0x12345678; + return ((const unsigned char*)&cpu_le_test)[0] == 0x78; +} + +uint32_t be_u32(const uint32_t v) { + if (cpu_le()) + return ((v & 0xFF000000) >> 24) | + ((v & 0x00FF0000) >> 8) | + ((v & 0x0000FF00) << 8) | + ((v & 0x000000FF) << 24); + return v; +} + +uint32_t le_u32(const uint32_t v) { + if (!cpu_le()) + return ((v & 0xFF000000) >> 24) | + ((v & 0x00FF0000) >> 8) | + ((v & 0x0000FF00) << 8) | + ((v & 0x000000FF) << 24); + return v; +} diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/utils.h b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/utils.h new file mode 100644 index 0000000..a8d37d2 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/stm32flash_serial/src/utils.h @@ -0,0 +1,30 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _H_UTILS +#define _H_UTILS + +#include + +char cpu_le(); +uint32_t be_u32(const uint32_t v); +uint32_t le_u32(const uint32_t v); + +#endif diff --git a/BootLoaders/Boards/stm32/tools/macosx/src/upload-reset/upload-reset.c b/BootLoaders/Boards/stm32/tools/macosx/src/upload-reset/upload-reset.c new file mode 100644 index 0000000..1d03bff --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/src/upload-reset/upload-reset.c @@ -0,0 +1,161 @@ +/* Copyright (C) 2015 Roger Clark + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * + * Utility to send the reset sequence on RTS and DTR and chars + * which resets the libmaple and causes the bootloader to be run + * + * + * + * Terminal control code by Heiko Noordhof (see copyright below) + */ + + + +/* Copyright (C) 2003 Heiko Noordhof + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Function prototypes (belong in a seperate header file) */ +int openserial(char *devicename); +void closeserial(void); +int setDTR(unsigned short level); +int setRTS(unsigned short level); + + +/* Two globals for use by this module only */ +static int fd; +static struct termios oldterminfo; + + +void closeserial(void) +{ + tcsetattr(fd, TCSANOW, &oldterminfo); + close(fd); +} + + +int openserial(char *devicename) +{ + struct termios attr; + + if ((fd = open(devicename, O_RDWR)) == -1) return 0; /* Error */ + atexit(closeserial); + + if (tcgetattr(fd, &oldterminfo) == -1) return 0; /* Error */ + attr = oldterminfo; + attr.c_cflag |= CRTSCTS | CLOCAL; + attr.c_oflag = 0; + if (tcflush(fd, TCIOFLUSH) == -1) return 0; /* Error */ + if (tcsetattr(fd, TCSANOW, &attr) == -1) return 0; /* Error */ + + /* Set the lines to a known state, and */ + /* finally return non-zero is successful. */ + return setRTS(0) && setDTR(0); +} + + +/* For the two functions below: + * level=0 to set line to LOW + * level=1 to set line to HIGH + */ + +int setRTS(unsigned short level) +{ + int status; + + if (ioctl(fd, TIOCMGET, &status) == -1) { + perror("setRTS(): TIOCMGET"); + return 0; + } + if (level) status |= TIOCM_RTS; + else status &= ~TIOCM_RTS; + if (ioctl(fd, TIOCMSET, &status) == -1) { + perror("setRTS(): TIOCMSET"); + return 0; + } + return 1; +} + + +int setDTR(unsigned short level) +{ + int status; + + if (ioctl(fd, TIOCMGET, &status) == -1) { + perror("setDTR(): TIOCMGET"); + return 0; + } + if (level) status |= TIOCM_DTR; + else status &= ~TIOCM_DTR; + if (ioctl(fd, TIOCMSET, &status) == -1) { + perror("setDTR: TIOCMSET"); + return 0; + } + return 1; +} + +/* This portion of code was written by Roger Clark + * It was informed by various other pieces of code written by Leaflabs to reset their + * Maple and Maple mini boards + */ + +main(int argc, char *argv[]) +{ + + if (argc<2 || argc >3) + { + printf("Usage upload-reset \n\r"); + return; + } + + if (openserial(argv[1])) + { + // Send magic sequence of DTR and RTS followed by the magic word "1EAF" + setRTS(false); + setDTR(false); + setDTR(true); + + usleep(50000L); + + setDTR(false); + setRTS(true); + setDTR(true); + + usleep(50000L); + + setDTR(false); + + usleep(50000L); + + write(fd,"1EAF",4); + + closeserial(); + if (argc==3) + { + usleep(atol(argv[2])*1000L); + } + } + else + { + printf("Failed to open serial device.\n\r"); + } +} diff --git a/BootLoaders/Boards/stm32/tools/macosx/stlink/st-flash b/BootLoaders/Boards/stm32/tools/macosx/stlink/st-flash new file mode 100644 index 0000000..a474397 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/macosx/stlink/st-flash differ diff --git a/BootLoaders/Boards/stm32/tools/macosx/stlink/st-info b/BootLoaders/Boards/stm32/tools/macosx/stlink/st-info new file mode 100644 index 0000000..ba9a99f Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/macosx/stlink/st-info differ diff --git a/BootLoaders/Boards/stm32/tools/macosx/stlink/st-term b/BootLoaders/Boards/stm32/tools/macosx/stlink/st-term new file mode 100644 index 0000000..e3c8640 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/macosx/stlink/st-term differ diff --git a/BootLoaders/Boards/stm32/tools/macosx/stlink/st-util b/BootLoaders/Boards/stm32/tools/macosx/stlink/st-util new file mode 100644 index 0000000..9e60e7a Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/macosx/stlink/st-util differ diff --git a/BootLoaders/Boards/stm32/tools/macosx/stlink_upload b/BootLoaders/Boards/stm32/tools/macosx/stlink_upload new file mode 100644 index 0000000..7c107c7 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/stlink_upload @@ -0,0 +1,2 @@ +#!/bin/bash +$(dirname $0)/stlink/st-flash write "$4" 0x8000000 diff --git a/BootLoaders/Boards/stm32/tools/macosx/stm32flash/stm32flash b/BootLoaders/Boards/stm32/tools/macosx/stm32flash/stm32flash new file mode 100644 index 0000000..dc8d422 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/macosx/stm32flash/stm32flash differ diff --git a/BootLoaders/Boards/stm32/tools/macosx/tx_upload b/BootLoaders/Boards/stm32/tools/macosx/tx_upload new file mode 100644 index 0000000..fc2f6ba --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/tx_upload @@ -0,0 +1,15 @@ +#!/bin/bash + +# Dummy 'upload' file to provide instructions for flashing the multi-module firmware from the Tx +echo +echo Compiled .bin location: +echo $1 +echo +echo The compiled firmware can now be copied to the \firmware folder on the transmitter for flashing using Maintenance Mode. +echo +echo To enter Maintenance Mode hold down the two outer horizontal trim buttons while powering on the transmitter. Once in +echo Maintenance Mode follow the on-screen prompts to flash the Multi module. +echo +echo Supported transmitters are those running ersky9x r221e2 or newer. +echo +echo Further instructions are available at [need_url]. \ No newline at end of file diff --git a/BootLoaders/Boards/stm32/tools/macosx/upload-reset b/BootLoaders/Boards/stm32/tools/macosx/upload-reset new file mode 100644 index 0000000..2929031 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/macosx/upload-reset differ diff --git a/BootLoaders/Boards/stm32/tools/macosx/upload_router b/BootLoaders/Boards/stm32/tools/macosx/upload_router new file mode 100644 index 0000000..5743986 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/upload_router @@ -0,0 +1,21 @@ +#!/bin/bash + +set -e + +if [ $# -lt 4 ]; then + echo "Usage: $0 $# " >&2 + exit 1 +fi +dummy_port=$1; altID=$2; usbID=$3; binfile=$4 + +DFU_UTIL=/usr/local/bin/dfu-util +if [ ! -x ${DFU_UTIL} ]; then + DFU_UTIL=/opt/local/bin/dfu-util +fi + +if [ ! -x ${DFU_UTIL} ]; then + echo "$0: error: cannot find ${DFU_UTIL}" >&2 + exit 2 +fi + +${DFU_UTIL} -d ${usbID} -a ${altID} -D ${binfile} diff --git a/BootLoaders/Boards/stm32/tools/win/dfu-util-0.9-win64/README.txt b/BootLoaders/Boards/stm32/tools/win/dfu-util-0.9-win64/README.txt new file mode 100644 index 0000000..5aa2e67 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/dfu-util-0.9-win64/README.txt @@ -0,0 +1,26 @@ +dfu-util 0.9 + +These binaries are for Microsoft Windows 64-bit + +They were built using MinGW-64 from MSYS2 with gcc 5.3.0, +for build instructions please see: +http://dfu-util.sourceforge.net/build.html + +Source code: +https://sourceforge.net/p/dfu-util/dfu-util/ci/v0.9/tree/ + +dfu-util.exe requires libusb-1.0.dll. The shipped libusb-1.0.dll +is built from libusb 1.0.20 and can be replaced with another +version if desired. + +dfu-util-static.exe has the libusb 1.0.20 code embedded and runs +without any libusb-1.0.dll. + +Notes: +1. To work around a bug in gcc/mingw, a small patch was applied, see + https://sourceforge.net/p/dfu-util/tickets/13/ +2. The dfu-util-static.exe includes libusb that has been patched + to work around a silicon bug in STM32F42X devices: + https://github.com/axoloti/axoloti/blob/master/platform_osx/src/libusb.stdfu.patch + +2016-02-11 Tormod Volden diff --git a/BootLoaders/Boards/stm32/tools/win/dfu-util-0.9-win64/dfu-prefix.exe b/BootLoaders/Boards/stm32/tools/win/dfu-util-0.9-win64/dfu-prefix.exe new file mode 100644 index 0000000..5ae0888 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/win/dfu-util-0.9-win64/dfu-prefix.exe differ diff --git a/BootLoaders/Boards/stm32/tools/win/dfu-util-0.9-win64/dfu-suffix.exe b/BootLoaders/Boards/stm32/tools/win/dfu-util-0.9-win64/dfu-suffix.exe new file mode 100644 index 0000000..e54eb25 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/win/dfu-util-0.9-win64/dfu-suffix.exe differ diff --git a/BootLoaders/Boards/stm32/tools/win/dfu-util-0.9-win64/dfu-util-manual.pdf b/BootLoaders/Boards/stm32/tools/win/dfu-util-0.9-win64/dfu-util-manual.pdf new file mode 100644 index 0000000..12f5c81 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/win/dfu-util-0.9-win64/dfu-util-manual.pdf differ diff --git a/BootLoaders/Boards/stm32/tools/win/dfu-util-0.9-win64/dfu-util-static.exe b/BootLoaders/Boards/stm32/tools/win/dfu-util-0.9-win64/dfu-util-static.exe new file mode 100644 index 0000000..fe7f875 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/win/dfu-util-0.9-win64/dfu-util-static.exe differ diff --git a/BootLoaders/Boards/stm32/tools/win/dfu-util-0.9-win64/dfu-util.exe b/BootLoaders/Boards/stm32/tools/win/dfu-util-0.9-win64/dfu-util.exe new file mode 100644 index 0000000..fff0d39 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/win/dfu-util-0.9-win64/dfu-util.exe differ diff --git a/BootLoaders/Boards/stm32/tools/win/dfu-util-0.9-win64/libusb-1.0.dll b/BootLoaders/Boards/stm32/tools/win/dfu-util-0.9-win64/libusb-1.0.dll new file mode 100644 index 0000000..c8d7717 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/win/dfu-util-0.9-win64/libusb-1.0.dll differ diff --git a/BootLoaders/Boards/stm32/tools/win/dfu-util.exe b/BootLoaders/Boards/stm32/tools/win/dfu-util.exe new file mode 100644 index 0000000..f735c03 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/win/dfu-util.exe differ diff --git a/BootLoaders/Boards/stm32/tools/win/get_version.bat b/BootLoaders/Boards/stm32/tools/win/get_version.bat new file mode 100644 index 0000000..9babfbe --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/get_version.bat @@ -0,0 +1,9 @@ +@ECHO OFF + +FOR /F "tokens=* usebackq skip=2" %%A in (`find "#define VERSION_MAJOR" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%A") do SET MAJOR_VERSION=%%i +FOR /F "tokens=* usebackq skip=2" %%B in (`find "#define VERSION_MINOR" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%B") do SET MINOR_VERSION=%%i +FOR /F "tokens=* usebackq skip=2" %%C in (`find "#define VERSION_REVISION" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%C") do SET REVISION_VERSION=%%i +FOR /F "tokens=* usebackq skip=2" %%D in (`find "#define VERSION_PATCH_LEVEL" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%D") do SET PATCH_VERSION=%%i + +SET MULTI_VER=%MAJOR_VERSION%.%MINOR_VERSION%.%REVISION_VERSION%.%PATCH_VERSION% +ECHO %MULTI_VER% diff --git a/BootLoaders/Boards/stm32/tools/win/lib/jssc.jar b/BootLoaders/Boards/stm32/tools/win/lib/jssc.jar new file mode 100644 index 0000000..d2b5c07 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/win/lib/jssc.jar differ diff --git a/BootLoaders/Boards/stm32/tools/win/libusb0.dll b/BootLoaders/Boards/stm32/tools/win/libusb0.dll new file mode 100644 index 0000000..9387bed Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/win/libusb0.dll differ diff --git a/BootLoaders/Boards/stm32/tools/win/maple_loader.jar b/BootLoaders/Boards/stm32/tools/win/maple_loader.jar new file mode 100644 index 0000000..e64676c Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/win/maple_loader.jar differ diff --git a/BootLoaders/Boards/stm32/tools/win/maple_upload.bat b/BootLoaders/Boards/stm32/tools/win/maple_upload.bat new file mode 100644 index 0000000..7d59bf5 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/maple_upload.bat @@ -0,0 +1,18 @@ +@echo off +rem: Note %~dp0 get path of this batch file +rem: Need to change drive if My Documents is on a drive other than C: +set driverLetter=%~dp0 +set driverLetter=%driverLetter:~0,2% +%driverLetter% +cd %~dp0 +java -jar maple_loader.jar %1 %2 %3 %4 %5 %6 %7 %8 %9 + +for /l %%x in (1, 1, 40) do ( + ping -w 50 -n 1 192.0.2.1 > nul + mode %1 > nul + if ERRORLEVEL 0 goto comPortFound +) + +echo timeout waiting for %1 serial + +:comPortFound diff --git a/BootLoaders/Boards/stm32/tools/win/serial_upload.bat b/BootLoaders/Boards/stm32/tools/win/serial_upload.bat new file mode 100644 index 0000000..65a42bc --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/serial_upload.bat @@ -0,0 +1,27 @@ +@echo off +rem: Note %~dp0 get path of this batch file +rem: Need to change drive if My Documents is on a drive other than C: +set driverLetter=%~dp0 +set driverLetter=%driverLetter:~0,2% +%driverLetter% +cd %~dp0 +rem: the two line below are needed to fix path issues with incorrect slashes before the bin file name +set str=%3 +set str=%str:/=\% + +echo stm32flash -v -g %2 -b 57600 -w %str% %1 +echo. + +stm32flash -v -g %2 -b 57600 -w %str% %1 +rem: C:\Python27\python.exe stm32loader.py -e -w -p %1 -g -b 115200 %str% + +rem: ------------- use STM's own uploader +rem: ---- Need to remove the COM bit from the comm port as the STM prog just wants the number +set commport=%1 +set commportnum=%commport:COM=% +rem: --- The maple board may nee the -i setting to be -i STM32_Med-density_128K or STM32_Med-density_64K +rem: ---- 64 bit version +rem: "%ProgramFiles(x86)%\STMicroelectronics\Software\Flash Loader Demonstrator\STMFlashLoader.exe" -c --pn %commportnum% --br 230400 -i STM32_High-density_256K -e --all -d --fn %str% --a 0x8000000 -r --a 0x8000000 + +rem: -- 32 bit version +rem: "%ProgramFiles%\STMicroelectronics\Software\Flash Loader Demonstrator\STMFlashLoader.exe" -c --pn %commportnum% --br 230400 -i STM32_Med-density_64K -e --all -d --fn %str% --a 0x8000000 -r --a 0x8000000 diff --git a/BootLoaders/Boards/stm32/tools/win/src/build_dfu-util.sh b/BootLoaders/Boards/stm32/tools/win/src/build_dfu-util.sh new file mode 100644 index 0000000..3563f57 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/build_dfu-util.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +sudo apt-get build-dep dfu-util +sudo apt-get install build-essentials +sudo apt-get install libusb-1.0-0-dev +sudo apt-get install autoconf automake autotools-dev + +cd dfu-util +./autogen.sh +./configure +make +cp src/dfu-util ../../linux/dfu-util +cp src/dfu-suffix ../../linux/dfu-util +cp src/dfu-prefix ../../linux/dfu-util + diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/AUTHORS b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/AUTHORS new file mode 100644 index 0000000..1b36c73 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/AUTHORS @@ -0,0 +1,30 @@ +Authors ordered by first contribution. + +Harald Welte +Werner Almesberger +Michael Lauer +Jim Huang +Stefan Schmidt +Daniel Willmann +Mike Frysinger +Uwe Hermann +C. Scott Ananian +Bernard Blackham +Holger Freyther +Marc Singer +James Perkins +Tommi Keisala +Pascal Schweizer +Bradley Scott +Uwe Bonnes +Andrey Smirnov +Jussi Timperi +Hans Petter Selasky +Bo Shen +Henrique de Almeida Mendonca +Bernd Krumboeck +Dennis Meier +Veli-Pekka Peltola +Dave Hylands +Michael Grzeschik +Paul Fertser diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/COPYING b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/COPYING new file mode 100644 index 0000000..d60c31a --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/ChangeLog b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/ChangeLog new file mode 100644 index 0000000..37f1add --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/ChangeLog @@ -0,0 +1,93 @@ +0.8: + o New, separate dfu-prefix tool (Uwe Bonnes) + o Allow filtering on serial number (Uwe Bonnes) + o Improved VID/PID/serial filtering (Bradley Scott) + o Support reading firmware from stdin (Tormod Volden) + o Warn if missing DFU suffix (Tormod Volden) + o Improved progress bar (Hans Petter Selasky) + o Fix dfuse leave option (Uwe Bonnes) + o Major code rework (Hans Petter Selasky) + o MS Visual Studio build support (Henrique Mendonca) + o dfuse-pack.py tool for .dfu files (Antonio Galeo) + o Many other fixes from many people + +2014-09-13: Tormod Volden + +0.7: + o Support for TI Stellaris devices (Tommi Keisala) + o Fix libusb detection on MacOSX (Marc Singer) + o Fix libusb detection on FreeBSD (Tormod Volden) + o Improved DfuSe support (Tormod Volden) + o Support all special commands (leave, unprotect, mass-erase) + o Arbitrary upload lengths + o "force" option for various possible (dangerous) overrides + +2012-10-07: Tormod Volden + +0.6: + o Add detach mode (Stefan Schmidt) + o Check return value on all libusb calls (Tormod Volden) + o Fix segmentation fault with -s option (Tormod Volden) + o Add DFU suffix manipulation tool (Stefan Schmidt) + o Port to Windows: (Tormod Volden, some parts based on work from Satz + Klauer) + o Port file handling to stdio streams + o Sleep() macros + o C99 types + o Pack structs + o Detect DfuSe device correctly on big-endian architectures (Tormod + Volden) + o Add dfuse progress indication on download (Tormod Volden) + o Cleanup: gcc pedantic, gcc extension, ... (Tormod Volden) + o Rely on page size from functional descriptor. Please report if you get + an error about it. (Tormod Volden) + o Add quirk for Maple since it reports wrong DFU version (Tormod Volden) + +2012-04-22: Stefan Schmidt + +0.5: + o DfuSe extension support for ST devices (Tormod Volden) + o Add initial support for bitWillDetach flag from DFU 1.1 (Tormod + Volden) + o Internal cleanup and some manual page fixes (Tormod Volden) + +2011-11-02: Stefan Schmidt + +0.4: + o Rework to use libusb-1.0 (Stefan Schmidt) + o DFU suffix support (Tormod Volden, Stefan Schmidt) + o Sspeed up DFU downloads directly into memory (Bernard Blackham) + o More flexible -d vid:pid parsing (Tormod Volden) + o Many bug fixes and cleanups + +2011-07-20: Stefan Schmidt + +0.3: + o quirks: Add OpenOCD to the poll timeout quirk table. + +2010-12-22: Stefan Schmidt + +0.2: + o Fix some typos on the website and the README (Antonio Ospite, Uwe + Hermann) + o Remove build rule for a static binary. We can use autotools for this. + (Mike Frysinger) + o Fix infinite loop in download error path (C. Scott Ananian) + o Break out to show the 'finished' in upload (C. Scott Ananian) + o Add GPLv2+ headers (Harald Welte) + o Remove dead code (commands.[ch]) remnescent of dfu-programmer (Harald + Welte) + o Simple quirk system with Openmoko quirk for missing bwPollTimeout (Tormod Volden) + o New default (1024) and clamping of transfer size (Tormod Volden) + o Verify sending of completion packet (Tormod Volden) + o Look for DFU functional descriptor among all descriptors (Tormod + Volden) + o Print out in which direction we are transferring data + o Abort in upload if the file already exists + +2010-11-17 Stefan Schmidt + +0.1: + Initial release + +2010-05-23 Stefan Schmidt diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/DEVICES.txt b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/DEVICES.txt new file mode 100644 index 0000000..bdd9f1f --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/DEVICES.txt @@ -0,0 +1,20 @@ +List of supported software and hardware products: + +Software user (bootloader, etc) +------------------------------- +- Sam7DFU: http://www.openpcd.org/Sam7dfu +- U-boot: DFU patches +- Barebox: http://www.barebox.org/ +- Leaflabs: http://code.google.com/p/leaflabs/ +- Blackmagic DFU + +Products using DFU +------------------ +- OpenPCD (sam7dfu) +- Openmoko Neo 1973 and Freerunner (u-boot with DFU patches) +- Leaflabs Maple +- ATUSB from Qi Hardware +- STM32F105/7, STM32F2/F3/F4 in System Bootloader +- Blackmagic debug probe +- NXP LPC31xx/LPC43XX, e.g. LPC-Link and LPC-Link2, need binaries + with LPC prefix and encoding (LPC-Link) diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/Makefile.am b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/Makefile.am new file mode 100644 index 0000000..641dda5 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = src doc + +EXTRA_DIST = autogen.sh TODO DEVICES.txt dfuse-pack.py diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/README b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/README new file mode 100644 index 0000000..0f8f262 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/README @@ -0,0 +1,20 @@ +Dfu-util - Device Firmware Upgrade Utilities + +Dfu-util is the host side implementation of the DFU 1.0 [1] and DFU 1.1 [2] +specification of the USB forum. + +DFU is intended to download and upload firmware to devices connected over +USB. It ranges from small devices like micro-controller boards up to mobile +phones. With dfu-util you are able to download firmware to your device or +upload firmware from it. + +dfu-util has been tested with Openmoko Neo1973 and Freerunner and many +other devices. + +[1] DFU 1.0 spec: http://www.usb.org/developers/devclass_docs/usbdfu10.pdf +[2] DFU 1.1 spec: http://www.usb.org/developers/devclass_docs/DFU_1.1.pdf + +The official website is: + + http://dfu-util.gnumonks.org/ + diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/TODO b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/TODO new file mode 100644 index 0000000..900c30c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/TODO @@ -0,0 +1,14 @@ +DfuSe: +- Do erase and write in two separate passes when downloading +- Skip "Set Address" command when downloading contiguous blocks +- Implement "Get Commands" command + +Devices: +- Research iPhone/iPod/iPad support + Heavily modified dfu-util fork here: + https://github.com/planetbeing/xpwn/tree/master/dfu-util +- Test against Niftylights + +Non-Code: +- Logo +- Re-License as LGPL for usage as library? diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/autogen.sh b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/autogen.sh new file mode 100644 index 0000000..e67aed3 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/autogen.sh @@ -0,0 +1,2 @@ +#! /bin/sh +autoreconf -v -i diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/configure.ac b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/configure.ac new file mode 100644 index 0000000..8622114 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/configure.ac @@ -0,0 +1,41 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.59) +AC_INIT([dfu-util],[0.8],[dfu-util@lists.gnumonks.org],,[http://dfu-util.gnumonks.org]) +AC_CONFIG_AUX_DIR(m4) +AM_INIT_AUTOMAKE([foreign]) +AC_CONFIG_HEADERS([config.h]) + +# Test for new silent rules and enable only if they are available +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +# Checks for programs. +AC_PROG_CC + +# Checks for libraries. +# On FreeBSD the libusb-1.0 is called libusb and resides in system location +AC_CHECK_LIB([usb], [libusb_init],, [native_libusb=no],) +AS_IF([test x$native_libusb = xno], [ + PKG_CHECK_MODULES([USB], [libusb-1.0 >= 1.0.0],, + AC_MSG_ERROR([*** Required libusb-1.0 >= 1.0.0 not installed ***])) +]) +AC_CHECK_LIB([usbpath],[usb_path2devnum],,,-lusb) + +LIBS="$LIBS $USB_LIBS" +CFLAGS="$CFLAGS $USB_CFLAGS" + +# Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS([usbpath.h windows.h sysexits.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_TYPE_SIZE_T + +# Checks for library functions. +AC_FUNC_MEMCMP +AC_CHECK_FUNCS([ftruncate getpagesize nanosleep err]) + +AC_CONFIG_FILES(Makefile src/Makefile doc/Makefile) +AC_OUTPUT diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/README b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/README new file mode 100644 index 0000000..00d3d1a --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/README @@ -0,0 +1,77 @@ +Device: +------- +qi-hardware-atusb: +- Qi Hardware ben-wpan +- DFU implementation: + http://projects.qi-hardware.com/index.php/p/ben-wpan/source/tree/master/atusb/fw/usb +- Tester: Stefan Schmidt + +openpcd: +- OpenPCD RFID reader +- DFU implementation: SAM7DFU + http://www.openpcd.org/Sam7dfu, git://git.gnumonks.org/openpcd.git +- Tester: Stefan Schmidt + +simtrace: +- Sysmocom SimTrace +- DFU implementation: SAM7DFU + http://www.openpcd.org/Sam7dfu, git://git.gnumonks.org/openpcd.git +- Tester: Stefan Schmidt + +openmoko-freerunner: +- Openmoko Freerunner +- DFU implementation: Old U-Boot + http://git.openmoko.org/?p=u-boot.git;a=shortlog;h=refs/heads/mokopatches +- Tester: Stefan Schmidt + +openmoko-neo1973: +- Openmoko Neo1073 +- DFU implementation: Old U-Boot + http://git.openmoko.org/?p=u-boot.git;a=shortlog;h=refs/heads/mokopatches +- Tester: Stefan Schmidt + +tdk-bluetooth: +- TDK Corp. Bluetooth Adapter +- DFU implementation: closed soure +- Only upload has been tested +- Tester: Stefan Schmidt + +stm32f107: +- STM32 microcontrollers with built-in (ROM) DFU loader +- DFU implementation: Closed source but probably similar to the one + in their USB device libraries. Some relevant application notes: + http://www.st.com -> AN3156 and AN2606 +- Tested by Uwe Bonnes + +stm32f4discovery: +- STM32 microcontroller board with built-in (ROM) DFU loader +- DFU implementation: Closed source, probably similar to stm32f107. +- Tested by Joe Rothweiler + +dso-nano: +- DSO Nano pocket oscilloscope +- DFU implementation: Based on ST Microelectronics USB FS Library 1.0 + http://dsonano.googlecode.com/files/DS0201_OpenSource.rar +- Tester: Tormod Volden + +opc-20: +- Custom devices based on STM32F1xx +- DFU implementation: ST Microelectronics USB FS Device Library 3.1.0 + http://www.st.com -> um0424.zip +- Tester: Tormod Volden + +lpc-link, lpclink2: +- NXP LPCXpresso debug adapters +- Proprietary DFU implementation, uses special download files with + LPC prefix and encoding of the target firmware code +- Tested by Uwe Bonnes + +Adding the lsusb output and a download log of your device here helps +us to avoid regressions for hardware we cannot test while working on +the code. To extract the lsusb output use this command: +sudo lsusb -v -d $USBID > $DEVICE.lsusb +Prepare a description snippet as above, and send it to us. A log +(copy-paste of the command window) of a firmware download is also +nice, please use the double verbose option -v -v and include the +command line in the log file. + diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/dsonano.lsusb b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/dsonano.lsusb new file mode 100644 index 0000000..140a7bc --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/dsonano.lsusb @@ -0,0 +1,60 @@ + +Bus 002 Device 004: ID 0483:df11 SGS Thomson Microelectronics +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x0483 SGS Thomson Microelectronics + idProduct 0xdf11 + bcdDevice 1.1a + iManufacturer 1 STMicroelectronics + iProduct 2 STM32 DFU + iSerial 3 001 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 36 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 64mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 0 + iInterface 4 @Internal Flash /0x08000000/12*001Ka,116*001Kg + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 0 + iInterface 5 @SPI Flash : M25P64/0x00000000/64*064Kg,64*064Kg + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 11 + Will Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 255 milliseconds + wTransferSize 1024 bytes + bcdDFUVersion 1.1a +Device Status: 0x0000 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/lpclink.log b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/lpclink.log new file mode 100644 index 0000000..7de4dd3 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/lpclink.log @@ -0,0 +1,59 @@ +(The on-board LPC3154 has some encryption key set and LPCXpressoWIN.enc +is encrypted.) + +$ lsusb | grep NXP +Bus 003 Device 011: ID 0471:df55 Philips (or NXP) LPCXpresso LPC-Link + +$ dfu-util -v -v -v -R -D /opt/lpc/lpcxpresso/bin/LPCXpressoWIN.enc + +dfu-util 0.7 + +Copyright 2005-2008 Weston Schmidt, Harald Welte and OpenMoko Inc. +Copyright 2010-2012 Tormod Volden and Stefan Schmidt +This program is Free Software and has ABSOLUTELY NO WARRANTY +Please report bugs to dfu-util@lists.gnumonks.org + +dfu-util: Invalid DFU suffix signature +dfu-util: A valid DFU suffix will be required in a future dfu-util release!!! +Deducing device DFU version from functional descriptor length +Opening DFU capable USB device... +ID 0471:df55 +Run-time device DFU version 0100 +Claiming USB DFU Runtime Interface... +Determining device status: +state = dfuIDLE, status = 0 +dfu-util: WARNING: Runtime device already in DFU state ?!? +Claiming USB DFU Interface... +Setting Alternate Setting #0 ... +Determining device status: +state = dfuIDLE, status = 0 +dfuIDLE, continuing +DFU mode device DFU version 0100 +Device returned transfer size 2048 +Copying data from PC to DFU device +Download [ ] 0% 0 bytes +Download [= ] 6% 2048 bytes +Download [=== ] 13% 4096 bytes +Download [==== ] 19% 6144 bytes +Download [====== ] 26% 8192 bytes +Download [======== ] 32% 10240 bytes +Download [========= ] 39% 12288 bytes +Download [=========== ] 45% 14336 bytes +Download [============= ] 52% 16384 bytes +Download [============== ] 59% 18432 bytes +Download [================ ] 65% 20480 bytes +Download [================== ] 72% 22528 bytes +Download [=================== ] 78% 24576 bytes +Download [===================== ] 85% 26624 bytes +Download [====================== ] 91% 28672 bytes +Download [======================== ] 98% 29192 bytes +Download [=========================] 100% 29192 bytes +Download done. +Sent a total of 29192 bytes +state(8) = dfuMANIFEST-WAIT-RESET, status(0) = No error condition is present +Done! +dfu-util: can't detach +Resetting USB to switch back to runtime mode + +$ lsusb | grep NXP +Bus 003 Device 012: ID 1fc9:0009 NXP Semiconductors diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/lpclink.lsusb b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/lpclink.lsusb new file mode 100644 index 0000000..867b2a2 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/lpclink.lsusb @@ -0,0 +1,58 @@ + +Bus 003 Device 008: ID 0471:df55 Philips (or NXP) LPCXpresso LPC-Link +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x0471 Philips (or NXP) + idProduct 0xdf55 LPCXpresso LPC-Link + bcdDevice 0.01 + iManufacturer 0 + iProduct 0 + iSerial 0 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 25 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 0 + iInterface 0 + Device Firmware Upgrade Interface Descriptor: + bLength 7 + bDescriptorType 33 + bmAttributes 1 + Will Not Detach + Manifestation Intolerant + Upload Unsupported + Download Supported + wDetachTimeout 65535 milliseconds + wTransferSize 2048 bytes +Device Qualifier (for other device speed): + bLength 10 + bDescriptorType 6 + bcdUSB 2.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + bNumConfigurations 1 +Device Status: 0x0000 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/lpclink2.log b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/lpclink2.log new file mode 100644 index 0000000..4681eff --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/lpclink2.log @@ -0,0 +1,59 @@ +$ lsusb | grep NXP +Bus 003 Device 013: ID 1fc9:000c NXP Semiconductors + +$ dfu-util -D ~/devel/dfu-util/firmware.bin.qthdr + +dfu-util 0.7 + +Copyright 2005-2008 Weston Schmidt, Harald Welte and OpenMoko Inc. +Copyright 2010-2012 Tormod Volden and Stefan Schmidt +This program is Free Software and has ABSOLUTELY NO WARRANTY +Please report bugs to dfu-util@lists.gnumonks.org + +dfu-util: Invalid DFU suffix signature +dfu-util: A valid DFU suffix will be required in a future dfu-util release!!! +Possible unencryptes NXP LPC DFU prefix with the following properties +Payload length: 39 kiByte +Opening DFU capable USB device... +ID 1fc9:000c +Run-time device DFU version 0100 +Claiming USB DFU Runtime Interface... +Determining device status: +state = dfuIDLE, status = 0 +dfu-util: WARNING: Runtime device already in DFU state ?!? +Claiming USB DFU Interface... +Setting Alternate Setting #0 ... +Determining device status: +state = dfuIDLE, status = 0 +dfuIDLE, continuing +DFU mode device DFU version 0100 +Device returned transfer size 2048 +Copying data from PC to DFU device +Download [ ] 0% 0 bytes +Download [= ] 4% 2048 bytes +Download [== ] 9% 4096 bytes +Download [=== ] 14% 6144 bytes +Download [==== ] 19% 8192 bytes +Download [====== ] 24% 10240 bytes +Download [======= ] 28% 12288 bytes +Download [======== ] 33% 14336 bytes +Download [========= ] 38% 16384 bytes +Download [========== ] 43% 18432 bytes +Download [============ ] 48% 20480 bytes +Download [============= ] 53% 22528 bytes +Download [============== ] 57% 24576 bytes +Download [=============== ] 62% 26624 bytes +Download [================ ] 67% 28672 bytes +Download [================== ] 72% 30720 bytes +Download [=================== ] 77% 32768 bytes +Download [==================== ] 82% 34816 bytes +Download [===================== ] 86% 36864 bytes +Download [====================== ] 91% 38912 bytes +Download [======================== ] 96% 40356 bytes +Download [=========================] 100% 40356 bytes +Download done. +Sent a total of 40356 bytes +dfu-util: unable to read DFU status + +$ lsusb | grep NXP +Bus 003 Device 014: ID 1fc9:0018 NXP Semiconductors diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/lpclink2.lsusb b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/lpclink2.lsusb new file mode 100644 index 0000000..b833fca --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/lpclink2.lsusb @@ -0,0 +1,203 @@ + +Bus 003 Device 007: ID 0c72:000c PEAK System PCAN-USB +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 16 + idVendor 0x0c72 PEAK System + idProduct 0x000c PCAN-USB + bcdDevice 1c.ff + iManufacturer 0 + iProduct 3 VER1:PEAK +VER2:02.8.01 +DAT :06.05.2004 +TIME:09:35:37 + ... + iSerial 0 + bNumConfigurations 3 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 46 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 200mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 4 + bInterfaceClass 0 (Defined at Interface level) + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 20 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x01 EP 1 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 20 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 46 + bNumInterfaces 1 + bConfigurationValue 2 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 394mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 4 + bInterfaceClass 0 (Defined at Interface level) + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 20 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x01 EP 1 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 20 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 46 + bNumInterfaces 1 + bConfigurationValue 3 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 200mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 4 + bInterfaceClass 0 (Defined at Interface level) + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x01 EP 1 OUT + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 +Device Status: 0x0001 + Self Powered diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/opc-20.lsusb b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/opc-20.lsusb new file mode 100644 index 0000000..580df90 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/opc-20.lsusb @@ -0,0 +1,60 @@ + +Bus 001 Device 004: ID 0483:df11 SGS Thomson Microelectronics +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x0483 SGS Thomson Microelectronics + idProduct 0xdf11 + bcdDevice 2.00 + iManufacturer 1 STMicroelectronics + iProduct 2 STM32 DFU + iSerial 3 ÿÿÿÿÿÿÿÿÿÿÿÿ + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 36 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0xc0 + Self Powered + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 4 @Internal Flash /0x08000000/12*001Ka,116*001Kg + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 5 @SPI Flash : M25P64/0x00000000/128*64Kg + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 11 + Will Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 255 milliseconds + wTransferSize 1024 bytes + bcdDFUVersion 1a.01 +Device Status: 0x0001 + Self Powered diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/openmoko-freerunner-dfumode.lsusb b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/openmoko-freerunner-dfumode.lsusb new file mode 100644 index 0000000..4c0abfb --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/openmoko-freerunner-dfumode.lsusb @@ -0,0 +1,109 @@ +Bus 003 Device 017: ID 1d50:5119 OpenMoko, Inc. GTA01/GTA02 U-Boot Bootloader +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 16 + idVendor 0x1d50 OpenMoko, Inc. + idProduct 0x5119 GTA01/GTA02 U-Boot Bootloader + bcdDevice 0.00 + iManufacturer 1 OpenMoko, Inc + iProduct 2 Neo1973 Bootloader U-Boot 1.3.2-moko12 + iSerial 3 0000000 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 81 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 7 USB Device Firmware Upgrade + bmAttributes 0x80 + (Bus Powered) + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 8 RAM 0x32000000 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 9 u-boot + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 2 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 10 u-boot_env + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 3 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 11 kernel + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 4 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 12 splash + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 5 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 13 factory + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 6 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 14 rootfs + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 7 + Will Not Detach + Manifestation Tolerant + Upload Supported + Download Supported + wDetachTimeout 65280 milliseconds + wTransferSize 4096 bytes + bcdDFUVersion 1.00 +Device Status: 0x0a00 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/openmoko-freerunner.lsusb b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/openmoko-freerunner.lsusb new file mode 100644 index 0000000..835708d --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/openmoko-freerunner.lsusb @@ -0,0 +1,179 @@ +Bus 005 Device 033: ID 1d50:5119 OpenMoko, Inc. GTA01/GTA02 U-Boot Bootloader +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.10 + bDeviceClass 2 Communications + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 16 + idVendor 0x1d50 OpenMoko, Inc. + idProduct 0x5119 GTA01/GTA02 U-Boot Bootloader + bcdDevice 0.00 + iManufacturer 1 OpenMoko, Inc + iProduct 2 Neo1973 Bootloader U-Boot 1.3.2-moko12 + iSerial 3 0000000 + bNumConfigurations 2 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 85 + bNumInterfaces 3 + bConfigurationValue 1 + iConfiguration 4 TTY via USB + bmAttributes 0x80 + (Bus Powered) + MaxPower 500mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 2 Communications + bInterfaceSubClass 2 Abstract (modem) + bInterfaceProtocol 1 AT-commands (v.25ter) + iInterface 6 Control Interface + CDC Header: + bcdCDC 0.6e + CDC Call Management: + bmCapabilities 0x00 + bDataInterface 1 + CDC ACM: + bmCapabilities 0x00 + CDC Union: + bMasterInterface 0 + bSlaveInterface 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 10 CDC Data + bInterfaceSubClass 0 Unused + bInterfaceProtocol 0 + iInterface 5 Bulk Data Interface + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 2 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 1 + iInterface 7 USB Device Firmware Upgrade + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 7 + Will Not Detach + Manifestation Tolerant + Upload Supported + Download Supported + wDetachTimeout 65280 milliseconds + wTransferSize 4096 bytes + bcdDFUVersion 1.00 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 67 + bNumInterfaces 2 + bConfigurationValue 2 + iConfiguration 4 TTY via USB + bmAttributes 0x80 + (Bus Powered) + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 2 Communications + bInterfaceSubClass 2 Abstract (modem) + bInterfaceProtocol 1 AT-commands (v.25ter) + iInterface 6 Control Interface + CDC Header: + bcdCDC 0.6e + CDC Call Management: + bmCapabilities 0x00 + bDataInterface 1 + CDC ACM: + bmCapabilities 0x00 + CDC Union: + bMasterInterface 0 + bSlaveInterface 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 10 CDC Data + bInterfaceSubClass 0 Unused + bInterfaceProtocol 0 + iInterface 5 Bulk Data Interface + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 +Device Status: 0x9a00 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/openmoko-neo1973.lsusb b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/openmoko-neo1973.lsusb new file mode 100644 index 0000000..0778950 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/openmoko-neo1973.lsusb @@ -0,0 +1,182 @@ + +Bus 006 Device 020: ID 1457:5119 First International Computer, Inc. OpenMoko Neo1973 u-boot cdc_acm serial port +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.10 + bDeviceClass 2 Communications + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 16 + idVendor 0x1457 First International Computer, Inc. + idProduct 0x5119 OpenMoko Neo1973 u-boot cdc_acm serial port + bcdDevice 0.00 + iManufacturer 1 + iProduct 2 + iSerial 3 + bNumConfigurations 2 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 85 + bNumInterfaces 3 + bConfigurationValue 1 + iConfiguration 4 + bmAttributes 0x80 + (Bus Powered) + MaxPower 500mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 2 Communications + bInterfaceSubClass 2 Abstract (modem) + bInterfaceProtocol 1 AT-commands (v.25ter) + iInterface 6 + CDC Header: + bcdCDC 0.6e + CDC Call Management: + bmCapabilities 0x00 + bDataInterface 1 + CDC ACM: + bmCapabilities 0x00 + CDC Union: + bMasterInterface 0 + bSlaveInterface 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 10 CDC Data + bInterfaceSubClass 0 Unused + bInterfaceProtocol 0 + iInterface 5 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 2 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 1 + iInterface 7 + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 7 + Will Not Detach + Manifestation Tolerant + Upload Supported + Download Supported + wDetachTimeout 65280 milliseconds + wTransferSize 4096 bytes + bcdDFUVersion 1.00 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 67 + bNumInterfaces 2 + bConfigurationValue 2 + iConfiguration 4 + bmAttributes 0x80 + (Bus Powered) + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 2 Communications + bInterfaceSubClass 2 Abstract (modem) + bInterfaceProtocol 1 AT-commands (v.25ter) + iInterface 6 + CDC Header: + bcdCDC 0.6e + CDC Call Management: + bmCapabilities 0x00 + bDataInterface 1 + CDC ACM: + bmCapabilities 0x00 + CDC Union: + bMasterInterface 0 + bSlaveInterface 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 10 CDC Data + bInterfaceSubClass 0 Unused + bInterfaceProtocol 0 + iInterface 5 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 255 +Device Status: 0x0006 + (Bus Powered) + Remote Wakeup Enabled + Test Mode diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/openpcd.lsusb b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/openpcd.lsusb new file mode 100644 index 0000000..f6255a9 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/openpcd.lsusb @@ -0,0 +1,60 @@ + +Bus 006 Device 016: ID 16c0:076b VOTI OpenPCD 13.56MHz RFID Reader +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 8 + idVendor 0x16c0 VOTI + idProduct 0x076b OpenPCD 13.56MHz RFID Reader + bcdDevice 0.00 + iManufacturer 1 + iProduct 2 OpenPCD RFID Simulator - DFU Mode + iSerial 0 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 36 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 200mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 0 + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 3 + Will Not Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 65280 milliseconds + wTransferSize 256 bytes + bcdDFUVersion 1.00 +Device Status: 0x0000 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/qi-hardware-atusb.lsusb b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/qi-hardware-atusb.lsusb new file mode 100644 index 0000000..bfc1701 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/qi-hardware-atusb.lsusb @@ -0,0 +1,59 @@ + +Bus 006 Device 013: ID 20b7:1540 Qi Hardware ben-wpan, AT86RF230-based +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 255 Vendor Specific Class + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x20b7 Qi Hardware + idProduct 0x1540 ben-wpan, AT86RF230-based + bcdDevice 0.01 + iManufacturer 0 + iProduct 0 + iSerial 1 4630333438371508231a + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 34 + bNumInterfaces 2 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 40mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 255 Vendor Specific Class + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 1 + iInterface 0 +Device Status: 0x0000 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/simtrace.lsusb b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/simtrace.lsusb new file mode 100644 index 0000000..578ddf0 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/simtrace.lsusb @@ -0,0 +1,70 @@ + +Bus 006 Device 017: ID 16c0:0762 VOTI +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 8 + idVendor 0x16c0 VOTI + idProduct 0x0762 + bcdDevice 0.00 + iManufacturer 1 sysmocom - systems for mobile communications GmbH + iProduct 2 SimTrace SIM Sniffer - DFU Mode + iSerial 0 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 45 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 3 SimTrace DFU Configuration + bmAttributes 0x80 + (Bus Powered) + MaxPower 200mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 4 SimTrace DFU Interface - Application Partition + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 5 SimTrace DFU Interface - Bootloader Partition + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 2 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 6 SimTrace DFU Interface - RAM + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 3 + Will Not Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 65280 milliseconds + wTransferSize 256 bytes + bcdDFUVersion 1.00 +Device Status: 0x0000 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/sparkcore.lsusb b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/sparkcore.lsusb new file mode 100644 index 0000000..b6029ff --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/sparkcore.lsusb @@ -0,0 +1,60 @@ + +Bus 001 Device 008: ID 1d50:607f OpenMoko, Inc. +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x1d50 OpenMoko, Inc. + idProduct 0x607f + bcdDevice 2.00 + iManufacturer 1 Spark Devices + iProduct 2 CORE DFU + iSerial 3 8D80527B5055 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 36 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0xc0 + Self Powered + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 4 @Internal Flash /0x08000000/20*001Ka,108*001Kg + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 5 @SPI Flash : SST25x/0x00000000/512*04Kg + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 11 + Will Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 255 milliseconds + wTransferSize 1024 bytes + bcdDFUVersion 1.1a +Device Status: 0x0001 + Self Powered diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/stm32f107.bin-download b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/stm32f107.bin-download new file mode 100644 index 0000000..45b714f --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/stm32f107.bin-download @@ -0,0 +1,48 @@ +> src/dfu-util --intf 0 --alt 0 -v -v -v -s 0x8000000 -D test3 +dfu-util 0.4 + +(C) 2005-2008 by Weston Schmidt, Harald Welte and OpenMoko Inc. +(C) 2010-2011 Tormod Volden (DfuSe support) +This program is Free Software and has ABSOLUTELY NO WARRANTY + +dfu-util does currently only support DFU version 1.0 + +Opening DFU USB device... ID 0483:df11 +Run-time device DFU version 011a +Found DFU: [0483:df11] devnum=0, cfg=1, intf=0, alt=0, name="@Internal Flash /0x08000000/128*002Kg" +Claiming USB DFU Interface... +Setting Alternate Setting #0 ... +Determining device status: state = dfuIDLE, status = 0 +dfuIDLE, continuing +DFU mode device DFU version 011a +Device returned transfer size 2048 +No valid DFU suffix signature +Warning: File has no DFU suffix +DfuSe interface name: "Internal Flash " +Memory segment at 0x08000000 128 x 2048 = 262144 (rew) +Uploading to address = 0x08000000, size = 16384 +Erasing page size 2048 at address 0x08000000, page starting at 0x08000000 + Download from image offset 00000000 to memory 08000000-080007ff, size 2048 + Setting address pointer to 0x08000000 +Erasing page size 2048 at address 0x08000800, page starting at 0x08000800 + Download from image offset 00000800 to memory 08000800-08000fff, size 2048 + Setting address pointer to 0x08000800 +Erasing page size 2048 at address 0x08001000, page starting at 0x08001000 + Download from image offset 00001000 to memory 08001000-080017ff, size 2048 + Setting address pointer to 0x08001000 +Erasing page size 2048 at address 0x08001800, page starting at 0x08001800 + Download from image offset 00001800 to memory 08001800-08001fff, size 2048 + Setting address pointer to 0x08001800 +Erasing page size 2048 at address 0x08002000, page starting at 0x08002000 + Download from image offset 00002000 to memory 08002000-080027ff, size 2048 + Setting address pointer to 0x08002000 +Erasing page size 2048 at address 0x08002800, page starting at 0x08002800 + Download from image offset 00002800 to memory 08002800-08002fff, size 2048 + Setting address pointer to 0x08002800 +Erasing page size 2048 at address 0x08003000, page starting at 0x08003000 + Download from image offset 00003000 to memory 08003000-080037ff, size 2048 + Setting address pointer to 0x08003000 +Erasing page size 2048 at address 0x08003800, page starting at 0x08003800 + Download from image offset 00003800 to memory 08003800-08003fff, size 2048 + Setting address pointer to 0x08003800 + diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/stm32f107.lsusb b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/stm32f107.lsusb new file mode 100644 index 0000000..14b45cd --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/stm32f107.lsusb @@ -0,0 +1,60 @@ + +Bus 001 Device 028: ID 0483:df11 SGS Thomson Microelectronics STM Device in DFU Mode +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x0483 SGS Thomson Microelectronics + idProduct 0xdf11 STM Device in DFU Mode + bcdDevice 20.00 + iManufacturer 1 STMicroelectronics + iProduct 2 STM32 0x418 DFU Bootloader + iSerial 3 STM32 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 36 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0xc0 + Self Powered + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 4 @Internal Flash /0x08000000/128*002Kg + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 5 @Option Bytes /0x1FFFF800/01*016 g + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 11 + Will Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 255 milliseconds + wTransferSize 2048 bytes + bcdDFUVersion 1.1a +Device Status: 0x0000 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/stm32f4discovery.bin-download b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/stm32f4discovery.bin-download new file mode 100644 index 0000000..96e1722 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/stm32f4discovery.bin-download @@ -0,0 +1,36 @@ +dfu-util --device 0483:df11 --alt 0 \ + --dfuse-address 0x08000000 \ + -v -v -v \ + --download arm/iotoggle.bin +No valid DFU suffix signature +Warning: File has no DFU suffix +dfu-util 0.5 + +(C) 2005-2008 by Weston Schmidt, Harald Welte and OpenMoko Inc. +(C) 2010-2011 Tormod Volden (DfuSe support) +This program is Free Software and has ABSOLUTELY NO WARRANTY + +dfu-util does currently only support DFU version 1.0 + +Filter on vendor = 0x0483 product = 0xdf11 +Opening DFU capable USB device... ID 0483:df11 +Run-time device DFU version 011a +Found DFU: [0483:df11] devnum=0, cfg=1, intf=0, alt=0, name="@Internal Flash /0x08000000/04*016Kg,01*064Kg,07*128Kg" +Claiming USB DFU Interface... +Setting Alternate Setting #0 ... +Determining device status: state = dfuERROR, status = 10 +dfuERROR, clearing status +Determining device status: state = dfuIDLE, status = 0 +dfuIDLE, continuing +DFU mode device DFU version 011a +Device returned transfer size 2048 +DfuSe interface name: "Internal Flash " +Memory segment at 0x08000000 4 x 16384 = 65536 (rew) +Memory segment at 0x08010000 1 x 65536 = 65536 (rew) +Memory segment at 0x08020000 7 x 131072 = 917504 (rew) +Uploading to address = 0x08000000, size = 2308 +Erasing page size 16384 at address 0x08000000, page starting at 0x08000000 + Download from image offset 00000000 to memory 08000000-080007ff, size 2048 + Setting address pointer to 0x08000000 + Download from image offset 00000800 to memory 08000800-08000903, size 260 + Setting address pointer to 0x08000800 diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/stm32f4discovery.lsusb b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/stm32f4discovery.lsusb new file mode 100644 index 0000000..0b870de --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/stm32f4discovery.lsusb @@ -0,0 +1,80 @@ + +Bus 001 Device 010: ID 0483:df11 SGS Thomson Microelectronics STM Device in DFU Mode +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 1.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x0483 SGS Thomson Microelectronics + idProduct 0xdf11 STM Device in DFU Mode + bcdDevice 21.00 + iManufacturer 1 STMicroelectronics + iProduct 2 STM32 BOOTLOADER + iSerial 3 315A28A0B956 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 54 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0xc0 + Self Powered + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 4 @Internal Flash /0x08000000/04*016Kg,01*064Kg,07*128Kg + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 1 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 5 @Option Bytes /0x1FFFC000/01*016 g + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 2 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 6 @OTP Memory /0x1FFF7800/01*512 g,01*016 g + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 3 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 2 + iInterface 7 @Device Feature/0xFFFF0000/01*004 g + Device Firmware Upgrade Interface Descriptor: + bLength 9 + bDescriptorType 33 + bmAttributes 11 + Will Detach + Manifestation Intolerant + Upload Supported + Download Supported + wDetachTimeout 255 milliseconds + wTransferSize 2048 bytes + bcdDFUVersion 1.1a +Device Status: 0x0001 + Self Powered diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/tdk-bluetooth.lsusb b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/tdk-bluetooth.lsusb new file mode 100644 index 0000000..c0cface --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/device-logs/tdk-bluetooth.lsusb @@ -0,0 +1,269 @@ + +Bus 006 Device 014: ID 04bf:0320 TDK Corp. Bluetooth Adapter +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 224 Wireless + bDeviceSubClass 1 Radio Frequency + bDeviceProtocol 1 Bluetooth + bMaxPacketSize0 64 + idVendor 0x04bf TDK Corp. + idProduct 0x0320 Bluetooth Adapter + bcdDevice 26.52 + iManufacturer 1 Ezurio + iProduct 2 Turbo Bluetooth Adapter + iSerial 3 008098D4FFBD + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 193 + bNumInterfaces 3 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 64mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 3 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x02 EP 2 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0000 1x 0 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0000 1x 0 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 1 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0009 1x 9 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0009 1x 9 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 2 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0011 1x 17 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0011 1x 17 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 3 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0019 1x 25 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0019 1x 25 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 4 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0021 1x 33 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0021 1x 33 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 5 + bNumEndpoints 2 + bInterfaceClass 224 Wireless + bInterfaceSubClass 1 Radio Frequency + bInterfaceProtocol 1 Bluetooth + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x03 EP 3 OUT + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0031 1x 49 bytes + bInterval 1 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0031 1x 49 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 2 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 254 Application Specific Interface + bInterfaceSubClass 1 Device Firmware Update + bInterfaceProtocol 0 + iInterface 0 + Device Firmware Upgrade Interface Descriptor: + bLength 7 + bDescriptorType 33 + bmAttributes 7 + Will Not Detach + Manifestation Tolerant + Upload Supported + Download Supported + wDetachTimeout 5000 milliseconds + wTransferSize 1023 bytes +Device Status: 0x0000 + (Bus Powered) diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/dfuse-pack.py b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/dfuse-pack.py new file mode 100644 index 0000000..875cc5c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/dfuse-pack.py @@ -0,0 +1,121 @@ +#!/usr/bin/python + +# Written by Antonio Galea - 2010/11/18 +# Distributed under Gnu LGPL 3.0 +# see http://www.gnu.org/licenses/lgpl-3.0.txt + +import sys,struct,zlib,os +from optparse import OptionParser + +DEFAULT_DEVICE="0x0483:0xdf11" + +def named(tuple,names): + return dict(zip(names.split(),tuple)) +def consume(fmt,data,names): + n = struct.calcsize(fmt) + return named(struct.unpack(fmt,data[:n]),names),data[n:] +def cstring(string): + return string.split('\0',1)[0] +def compute_crc(data): + return 0xFFFFFFFF & -zlib.crc32(data) -1 + +def parse(file,dump_images=False): + print 'File: "%s"' % file + data = open(file,'rb').read() + crc = compute_crc(data[:-4]) + prefix, data = consume('<5sBIB',data,'signature version size targets') + print '%(signature)s v%(version)d, image size: %(size)d, targets: %(targets)d' % prefix + for t in range(prefix['targets']): + tprefix, data = consume('<6sBI255s2I',data,'signature altsetting named name size elements') + tprefix['num'] = t + if tprefix['named']: + tprefix['name'] = cstring(tprefix['name']) + else: + tprefix['name'] = '' + print '%(signature)s %(num)d, alt setting: %(altsetting)s, name: "%(name)s", size: %(size)d, elements: %(elements)d' % tprefix + tsize = tprefix['size'] + target, data = data[:tsize], data[tsize:] + for e in range(tprefix['elements']): + eprefix, target = consume('<2I',target,'address size') + eprefix['num'] = e + print ' %(num)d, address: 0x%(address)08x, size: %(size)d' % eprefix + esize = eprefix['size'] + image, target = target[:esize], target[esize:] + if dump_images: + out = '%s.target%d.image%d.bin' % (file,t,e) + open(out,'wb').write(image) + print ' DUMPED IMAGE TO "%s"' % out + if len(target): + print "target %d: PARSE ERROR" % t + suffix = named(struct.unpack('<4H3sBI',data[:16]),'device product vendor dfu ufd len crc') + print 'usb: %(vendor)04x:%(product)04x, device: 0x%(device)04x, dfu: 0x%(dfu)04x, %(ufd)s, %(len)d, 0x%(crc)08x' % suffix + if crc != suffix['crc']: + print "CRC ERROR: computed crc32 is 0x%08x" % crc + data = data[16:] + if data: + print "PARSE ERROR" + +def build(file,targets,device=DEFAULT_DEVICE): + data = '' + for t,target in enumerate(targets): + tdata = '' + for image in target: + tdata += struct.pack('<2I',image['address'],len(image['data']))+image['data'] + tdata = struct.pack('<6sBI255s2I','Target',0,1,'ST...',len(tdata),len(target)) + tdata + data += tdata + data = struct.pack('<5sBIB','DfuSe',1,len(data)+11,len(targets)) + data + v,d=map(lambda x: int(x,0) & 0xFFFF, device.split(':',1)) + data += struct.pack('<4H3sB',0,d,v,0x011a,'UFD',16) + crc = compute_crc(data) + data += struct.pack(' and +Harald Welte . Over time, nearly complete +support of DFU 1.0, DFU 1.1 and DfuSe ("1.1a") has been added. +.SH LICENCE +.B dfu-util +is covered by the GNU General Public License (GPL), version 2 or later. +.SH COPYRIGHT +This manual page was originally written by Uwe Hermann , +and is now part of the dfu-util project. diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/msvc/README_msvc.txt b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/msvc/README_msvc.txt new file mode 100644 index 0000000..6e68ec6 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/msvc/README_msvc.txt @@ -0,0 +1,10 @@ +# (C) Roger Meier +# (C) Pascal Schweizer +# msvc folder is GPL-2.0+, LGPL-2.1+, BSD-3-Clause or MIT license(SPDX) + +Building dfu-util native on Windows with Visual Studio + +3rd party dependencies: +- libusbx ( git clone https://github.com/libusbx/libusbx.git ) + - getopt (part of libusbx: libusbx/examples/getopt) + diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/msvc/dfu-suffix_2010.vcxproj b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/msvc/dfu-suffix_2010.vcxproj new file mode 100644 index 0000000..0c316c2 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/msvc/dfu-suffix_2010.vcxproj @@ -0,0 +1,100 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA} + dfusuffix + dfu-suffix + + + + Application + true + MultiByte + + + Application + false + true + MultiByte + + + + + + + + + + + + + $(SolutionDir)..\..\libusbx\examples\getopt;$(SolutionDir)..\..\libusbx\libusb;$(IncludePath) + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\dll;$(LibraryPath) + $(VCInstallDir)atlmfc\lib;$(VCInstallDir)lib + $(ExecutablePath) + + + $(ExecutablePath) + $(SolutionDir)..\..\libusbx\examples\getopt;$(SolutionDir)..\..\libusbx\libusb;$(IncludePath) + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\dll;$(LibraryPath) + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + + + + Level3 + Disabled + HAVE_WINDOWS_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreadedDebug + + + true + + + + + Level3 + MaxSpeed + true + true + HAVE_WINDOWS_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreaded + + + true + true + true + + + + + + + + + + + + + {a2169bc8-cf99-40bf-83f3-b0e38f7067bd} + + + {349ee8f9-7d25-4909-aaf5-ff3fade72187} + + + + + + \ No newline at end of file diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/msvc/dfu-util_2010.sln b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/msvc/dfu-util_2010.sln new file mode 100644 index 0000000..ef79723 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/msvc/dfu-util_2010.sln @@ -0,0 +1,54 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dfu-util", "dfu-util_2010.vcxproj", "{0E071A60-7EF2-4427-BAA8-9143CACB5BCB}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C4F8746D-B27E-4806-95E5-2052174E923B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dfu-suffix", "dfu-suffix_2010.vcxproj", "{8F7600A2-3B37-4956-B39B-A1D43EF29EDA}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "getopt_2010", "..\..\libusbx\msvc\getopt_2010.vcxproj", "{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (static)", "..\..\libusbx\msvc\libusb_static_2010.vcxproj", "{349EE8F9-7D25-4909-AAF5-FF3FADE72187}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB}.Debug|Win32.ActiveCfg = Debug|Win32 + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB}.Debug|Win32.Build.0 = Debug|Win32 + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB}.Debug|x64.ActiveCfg = Debug|Win32 + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB}.Release|Win32.ActiveCfg = Release|Win32 + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB}.Release|Win32.Build.0 = Release|Win32 + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB}.Release|x64.ActiveCfg = Release|Win32 + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA}.Debug|Win32.ActiveCfg = Debug|Win32 + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA}.Debug|Win32.Build.0 = Debug|Win32 + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA}.Debug|x64.ActiveCfg = Debug|Win32 + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA}.Release|Win32.ActiveCfg = Release|Win32 + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA}.Release|Win32.Build.0 = Release|Win32 + {8F7600A2-3B37-4956-B39B-A1D43EF29EDA}.Release|x64.ActiveCfg = Release|Win32 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|Win32.ActiveCfg = Debug|Win32 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|Win32.Build.0 = Debug|Win32 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|x64.ActiveCfg = Debug|x64 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|x64.Build.0 = Debug|x64 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|Win32.ActiveCfg = Release|Win32 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|Win32.Build.0 = Release|Win32 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|x64.ActiveCfg = Release|x64 + {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|x64.Build.0 = Release|x64 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.ActiveCfg = Debug|Win32 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.Build.0 = Debug|Win32 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.ActiveCfg = Debug|x64 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.Build.0 = Debug|x64 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.ActiveCfg = Release|Win32 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.Build.0 = Release|Win32 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.ActiveCfg = Release|x64 + {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/msvc/dfu-util_2010.vcxproj b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/msvc/dfu-util_2010.vcxproj new file mode 100644 index 0000000..17a8bee --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/msvc/dfu-util_2010.vcxproj @@ -0,0 +1,120 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {0E071A60-7EF2-4427-BAA8-9143CACB5BCB} + dfuutil + dfu-util + + + + Application + true + MultiByte + + + Application + false + true + MultiByte + + + + + + + + + + + + + $(SolutionDir)..\..\libusbx\examples\getopt;$(SolutionDir)..\..\libusbx\libusb;$(IncludePath) + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + $(SolutionDir)..\$(Platform)\getopt\$(Configuration);$(LibraryPath) + $(VCInstallDir)atlmfc\lib;$(VCInstallDir)lib + $(ExecutablePath) + + + $(ExecutablePath) + $(SolutionDir)..\..\libusbx\examples\getopt;$(SolutionDir)..\..\libusbx\libusb;$(IncludePath) + $(SolutionDir)..\$(Platform)\getopt\$(Configuration);$(LibraryPath) + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + + + + Level3 + Disabled + HAVE_WINDOWS_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreadedDebug + + + true + + + + + + + + + Level3 + MaxSpeed + true + true + HAVE_WINDOWS_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreaded + + + true + true + true + + + copy $(SolutionDir)..\$(Platform)\$(Configuration)\dll\libusb-1.0.dll $(SolutionDir)..\$(Platform)\$(ProjectName)\$(Configuration)\ + + + + + + + + + + + + + + + + + + + + + + + + + + {a2169bc8-cf99-40bf-83f3-b0e38f7067bd} + + + {349ee8f9-7d25-4909-aaf5-ff3fade72187} + + + + + + \ No newline at end of file diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/Makefile.am b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/Makefile.am new file mode 100644 index 0000000..70179c4 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/Makefile.am @@ -0,0 +1,28 @@ +AM_CFLAGS = -Wall -Wextra + +bin_PROGRAMS = dfu-util dfu-suffix dfu-prefix +dfu_util_SOURCES = main.c \ + portable.h \ + dfu_load.c \ + dfu_load.h \ + dfu_util.c \ + dfu_util.h \ + dfuse.c \ + dfuse.h \ + dfuse_mem.c \ + dfuse_mem.h \ + dfu.c \ + dfu.h \ + usb_dfu.h \ + dfu_file.c \ + dfu_file.h \ + quirks.c \ + quirks.h + +dfu_suffix_SOURCES = suffix.c \ + dfu_file.h \ + dfu_file.c + +dfu_prefix_SOURCES = prefix.c \ + dfu_file.h \ + dfu_file.c diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfu.c b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfu.c new file mode 100644 index 0000000..14d7673 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfu.c @@ -0,0 +1,357 @@ +/* + * Low-level DFU communication routines, originally taken from + * $Id: dfu.c,v 1.3 2006/06/20 06:28:04 schmidtw Exp $ + * (part of dfu-programmer). + * + * Copyright 2005-2006 Weston Schmidt + * Copyright 2011-2014 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include + +#include "portable.h" +#include "dfu.h" +#include "quirks.h" + +static int dfu_timeout = 5000; /* 5 seconds - default */ + +/* + * DFU_DETACH Request (DFU Spec 1.0, Section 5.1) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * timeout - the timeout in ms the USB device should wait for a pending + * USB reset before giving up and terminating the operation + * + * returns 0 or < 0 on error + */ +int dfu_detach( libusb_device_handle *device, + const unsigned short interface, + const unsigned short timeout ) +{ + return libusb_control_transfer( device, + /* bmRequestType */ LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_DETACH, + /* wValue */ timeout, + /* wIndex */ interface, + /* Data */ NULL, + /* wLength */ 0, + dfu_timeout ); +} + + +/* + * DFU_DNLOAD Request (DFU Spec 1.0, Section 6.1.1) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * length - the total number of bytes to transfer to the USB + * device - must be less than wTransferSize + * data - the data to transfer + * + * returns the number of bytes written or < 0 on error + */ +int dfu_download( libusb_device_handle *device, + const unsigned short interface, + const unsigned short length, + const unsigned short transaction, + unsigned char* data ) +{ + int status; + + status = libusb_control_transfer( device, + /* bmRequestType */ LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_DNLOAD, + /* wValue */ transaction, + /* wIndex */ interface, + /* Data */ data, + /* wLength */ length, + dfu_timeout ); + return status; +} + + +/* + * DFU_UPLOAD Request (DFU Spec 1.0, Section 6.2) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * length - the maximum number of bytes to receive from the USB + * device - must be less than wTransferSize + * data - the buffer to put the received data in + * + * returns the number of bytes received or < 0 on error + */ +int dfu_upload( libusb_device_handle *device, + const unsigned short interface, + const unsigned short length, + const unsigned short transaction, + unsigned char* data ) +{ + int status; + + status = libusb_control_transfer( device, + /* bmRequestType */ LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_UPLOAD, + /* wValue */ transaction, + /* wIndex */ interface, + /* Data */ data, + /* wLength */ length, + dfu_timeout ); + return status; +} + + +/* + * DFU_GETSTATUS Request (DFU Spec 1.0, Section 6.1.2) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * status - the data structure to be populated with the results + * + * return the number of bytes read in or < 0 on an error + */ +int dfu_get_status( struct dfu_if *dif, struct dfu_status *status ) +{ + unsigned char buffer[6]; + int result; + + /* Initialize the status data structure */ + status->bStatus = DFU_STATUS_ERROR_UNKNOWN; + status->bwPollTimeout = 0; + status->bState = STATE_DFU_ERROR; + status->iString = 0; + + result = libusb_control_transfer( dif->dev_handle, + /* bmRequestType */ LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_GETSTATUS, + /* wValue */ 0, + /* wIndex */ dif->interface, + /* Data */ buffer, + /* wLength */ 6, + dfu_timeout ); + + if( 6 == result ) { + status->bStatus = buffer[0]; + if (dif->quirks & QUIRK_POLLTIMEOUT) + status->bwPollTimeout = DEFAULT_POLLTIMEOUT; + else + status->bwPollTimeout = ((0xff & buffer[3]) << 16) | + ((0xff & buffer[2]) << 8) | + (0xff & buffer[1]); + status->bState = buffer[4]; + status->iString = buffer[5]; + } + + return result; +} + + +/* + * DFU_CLRSTATUS Request (DFU Spec 1.0, Section 6.1.3) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * + * return 0 or < 0 on an error + */ +int dfu_clear_status( libusb_device_handle *device, + const unsigned short interface ) +{ + return libusb_control_transfer( device, + /* bmRequestType */ LIBUSB_ENDPOINT_OUT| LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_CLRSTATUS, + /* wValue */ 0, + /* wIndex */ interface, + /* Data */ NULL, + /* wLength */ 0, + dfu_timeout ); +} + + +/* + * DFU_GETSTATE Request (DFU Spec 1.0, Section 6.1.5) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * length - the maximum number of bytes to receive from the USB + * device - must be less than wTransferSize + * data - the buffer to put the received data in + * + * returns the state or < 0 on error + */ +int dfu_get_state( libusb_device_handle *device, + const unsigned short interface ) +{ + int result; + unsigned char buffer[1]; + + result = libusb_control_transfer( device, + /* bmRequestType */ LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_GETSTATE, + /* wValue */ 0, + /* wIndex */ interface, + /* Data */ buffer, + /* wLength */ 1, + dfu_timeout ); + + /* Return the error if there is one. */ + if (result < 1) + return -1; + + /* Return the state. */ + return buffer[0]; +} + + +/* + * DFU_ABORT Request (DFU Spec 1.0, Section 6.1.4) + * + * device - the usb_dev_handle to communicate with + * interface - the interface to communicate with + * + * returns 0 or < 0 on an error + */ +int dfu_abort( libusb_device_handle *device, + const unsigned short interface ) +{ + return libusb_control_transfer( device, + /* bmRequestType */ LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_ABORT, + /* wValue */ 0, + /* wIndex */ interface, + /* Data */ NULL, + /* wLength */ 0, + dfu_timeout ); +} + + +const char* dfu_state_to_string( int state ) +{ + const char *message; + + switch (state) { + case STATE_APP_IDLE: + message = "appIDLE"; + break; + case STATE_APP_DETACH: + message = "appDETACH"; + break; + case STATE_DFU_IDLE: + message = "dfuIDLE"; + break; + case STATE_DFU_DOWNLOAD_SYNC: + message = "dfuDNLOAD-SYNC"; + break; + case STATE_DFU_DOWNLOAD_BUSY: + message = "dfuDNBUSY"; + break; + case STATE_DFU_DOWNLOAD_IDLE: + message = "dfuDNLOAD-IDLE"; + break; + case STATE_DFU_MANIFEST_SYNC: + message = "dfuMANIFEST-SYNC"; + break; + case STATE_DFU_MANIFEST: + message = "dfuMANIFEST"; + break; + case STATE_DFU_MANIFEST_WAIT_RESET: + message = "dfuMANIFEST-WAIT-RESET"; + break; + case STATE_DFU_UPLOAD_IDLE: + message = "dfuUPLOAD-IDLE"; + break; + case STATE_DFU_ERROR: + message = "dfuERROR"; + break; + default: + message = NULL; + break; + } + + return message; +} + +/* Chapter 6.1.2 */ +static const char *dfu_status_names[] = { + /* DFU_STATUS_OK */ + "No error condition is present", + /* DFU_STATUS_errTARGET */ + "File is not targeted for use by this device", + /* DFU_STATUS_errFILE */ + "File is for this device but fails some vendor-specific test", + /* DFU_STATUS_errWRITE */ + "Device is unable to write memory", + /* DFU_STATUS_errERASE */ + "Memory erase function failed", + /* DFU_STATUS_errCHECK_ERASED */ + "Memory erase check failed", + /* DFU_STATUS_errPROG */ + "Program memory function failed", + /* DFU_STATUS_errVERIFY */ + "Programmed memory failed verification", + /* DFU_STATUS_errADDRESS */ + "Cannot program memory due to received address that is out of range", + /* DFU_STATUS_errNOTDONE */ + "Received DFU_DNLOAD with wLength = 0, but device does not think that it has all data yet", + /* DFU_STATUS_errFIRMWARE */ + "Device's firmware is corrupt. It cannot return to run-time (non-DFU) operations", + /* DFU_STATUS_errVENDOR */ + "iString indicates a vendor specific error", + /* DFU_STATUS_errUSBR */ + "Device detected unexpected USB reset signalling", + /* DFU_STATUS_errPOR */ + "Device detected unexpected power on reset", + /* DFU_STATUS_errUNKNOWN */ + "Something went wrong, but the device does not know what it was", + /* DFU_STATUS_errSTALLEDPKT */ + "Device stalled an unexpected request" +}; + + +const char *dfu_status_to_string(int status) +{ + if (status > DFU_STATUS_errSTALLEDPKT) + return "INVALID"; + return dfu_status_names[status]; +} + +int dfu_abort_to_idle(struct dfu_if *dif) +{ + int ret; + struct dfu_status dst; + + ret = dfu_abort(dif->dev_handle, dif->interface); + if (ret < 0) { + errx(EX_IOERR, "Error sending dfu abort request"); + exit(1); + } + ret = dfu_get_status(dif, &dst); + if (ret < 0) { + errx(EX_IOERR, "Error during abort get_status"); + exit(1); + } + if (dst.bState != DFU_STATE_dfuIDLE) { + errx(EX_IOERR, "Failed to enter idle state on abort"); + exit(1); + } + milli_sleep(dst.bwPollTimeout); + return ret; +} diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfu.h b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfu.h new file mode 100644 index 0000000..8e3caeb --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfu.h @@ -0,0 +1,133 @@ +/* + * dfu-programmer + * + * $Id: dfu.h,v 1.2 2005/09/25 01:27:42 schmidtw Exp $ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DFU_H +#define DFU_H + +#include +#include "usb_dfu.h" + +/* DFU states */ +#define STATE_APP_IDLE 0x00 +#define STATE_APP_DETACH 0x01 +#define STATE_DFU_IDLE 0x02 +#define STATE_DFU_DOWNLOAD_SYNC 0x03 +#define STATE_DFU_DOWNLOAD_BUSY 0x04 +#define STATE_DFU_DOWNLOAD_IDLE 0x05 +#define STATE_DFU_MANIFEST_SYNC 0x06 +#define STATE_DFU_MANIFEST 0x07 +#define STATE_DFU_MANIFEST_WAIT_RESET 0x08 +#define STATE_DFU_UPLOAD_IDLE 0x09 +#define STATE_DFU_ERROR 0x0a + + +/* DFU status */ +#define DFU_STATUS_OK 0x00 +#define DFU_STATUS_ERROR_TARGET 0x01 +#define DFU_STATUS_ERROR_FILE 0x02 +#define DFU_STATUS_ERROR_WRITE 0x03 +#define DFU_STATUS_ERROR_ERASE 0x04 +#define DFU_STATUS_ERROR_CHECK_ERASED 0x05 +#define DFU_STATUS_ERROR_PROG 0x06 +#define DFU_STATUS_ERROR_VERIFY 0x07 +#define DFU_STATUS_ERROR_ADDRESS 0x08 +#define DFU_STATUS_ERROR_NOTDONE 0x09 +#define DFU_STATUS_ERROR_FIRMWARE 0x0a +#define DFU_STATUS_ERROR_VENDOR 0x0b +#define DFU_STATUS_ERROR_USBR 0x0c +#define DFU_STATUS_ERROR_POR 0x0d +#define DFU_STATUS_ERROR_UNKNOWN 0x0e +#define DFU_STATUS_ERROR_STALLEDPKT 0x0f + +/* DFU commands */ +#define DFU_DETACH 0 +#define DFU_DNLOAD 1 +#define DFU_UPLOAD 2 +#define DFU_GETSTATUS 3 +#define DFU_CLRSTATUS 4 +#define DFU_GETSTATE 5 +#define DFU_ABORT 6 + +/* DFU interface */ +#define DFU_IFF_DFU 0x0001 /* DFU Mode, (not Runtime) */ + +/* This is based off of DFU_GETSTATUS + * + * 1 unsigned byte bStatus + * 3 unsigned byte bwPollTimeout + * 1 unsigned byte bState + * 1 unsigned byte iString +*/ + +struct dfu_status { + unsigned char bStatus; + unsigned int bwPollTimeout; + unsigned char bState; + unsigned char iString; +}; + +struct dfu_if { + struct usb_dfu_func_descriptor func_dfu; + uint16_t quirks; + uint16_t busnum; + uint16_t devnum; + uint16_t vendor; + uint16_t product; + uint16_t bcdDevice; + uint8_t configuration; + uint8_t interface; + uint8_t altsetting; + uint8_t flags; + uint8_t bMaxPacketSize0; + char *alt_name; + char *serial_name; + libusb_device *dev; + libusb_device_handle *dev_handle; + struct dfu_if *next; +}; + +int dfu_detach( libusb_device_handle *device, + const unsigned short interface, + const unsigned short timeout ); +int dfu_download( libusb_device_handle *device, + const unsigned short interface, + const unsigned short length, + const unsigned short transaction, + unsigned char* data ); +int dfu_upload( libusb_device_handle *device, + const unsigned short interface, + const unsigned short length, + const unsigned short transaction, + unsigned char* data ); +int dfu_get_status( struct dfu_if *dif, + struct dfu_status *status ); +int dfu_clear_status( libusb_device_handle *device, + const unsigned short interface ); +int dfu_get_state( libusb_device_handle *device, + const unsigned short interface ); +int dfu_abort( libusb_device_handle *device, + const unsigned short interface ); +int dfu_abort_to_idle( struct dfu_if *dif); + +const char *dfu_state_to_string( int state ); + +const char *dfu_status_to_string( int status ); + +#endif /* DFU_H */ diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfu_file.c b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfu_file.c new file mode 100644 index 0000000..7c897d4 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfu_file.c @@ -0,0 +1,444 @@ +/* + * Load or store DFU files including suffix and prefix + * + * Copyright 2014 Tormod Volden + * Copyright 2012 Stefan Schmidt + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "portable.h" +#include "dfu_file.h" + +#define DFU_SUFFIX_LENGTH 16 +#define LMDFU_PREFIX_LENGTH 8 +#define LPCDFU_PREFIX_LENGTH 16 +#define PROGRESS_BAR_WIDTH 25 +#define STDIN_CHUNK_SIZE 65536 + +static const unsigned long crc32_table[] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d}; + +static uint32_t crc32_byte(uint32_t accum, uint8_t delta) +{ + return crc32_table[(accum ^ delta) & 0xff] ^ (accum >> 8); +} + +static int probe_prefix(struct dfu_file *file) +{ + uint8_t *prefix = file->firmware; + + if (file->size.total < LMDFU_PREFIX_LENGTH) + return 1; + if ((prefix[0] == 0x01) && (prefix[1] == 0x00)) { + file->prefix_type = LMDFU_PREFIX; + file->size.prefix = LMDFU_PREFIX_LENGTH; + file->lmdfu_address = 1024 * ((prefix[3] << 8) | prefix[2]); + } + else if (((prefix[0] & 0x3f) == 0x1a) && ((prefix[1] & 0x3f)== 0x3f)) { + file->prefix_type = LPCDFU_UNENCRYPTED_PREFIX; + file->size.prefix = LPCDFU_PREFIX_LENGTH; + } + + if (file->size.prefix + file->size.suffix > file->size.total) + return 1; + return 0; +} + +void dfu_progress_bar(const char *desc, unsigned long long curr, + unsigned long long max) +{ + static char buf[PROGRESS_BAR_WIDTH + 1]; + static unsigned long long last_progress = -1; + static time_t last_time; + time_t curr_time = time(NULL); + unsigned long long progress; + unsigned long long x; + + /* check for not known maximum */ + if (max < curr) + max = curr + 1; + /* make none out of none give zero */ + if (max == 0 && curr == 0) + max = 1; + + /* compute completion */ + progress = (PROGRESS_BAR_WIDTH * curr) / max; + if (progress > PROGRESS_BAR_WIDTH) + progress = PROGRESS_BAR_WIDTH; + if (progress == last_progress && + curr_time == last_time) + return; + last_progress = progress; + last_time = curr_time; + + for (x = 0; x != PROGRESS_BAR_WIDTH; x++) { + if (x < progress) + buf[x] = '='; + else + buf[x] = ' '; + } + buf[x] = 0; + + printf("\r%s\t[%s] %3lld%% %12lld bytes", desc, buf, + (100ULL * curr) / max, curr); + + if (progress == PROGRESS_BAR_WIDTH) + printf("\n%s done.\n", desc); +} + +void *dfu_malloc(size_t size) +{ + void *ptr = malloc(size); + if (ptr == NULL) + errx(EX_SOFTWARE, "Cannot allocate memory of size %d bytes", (int)size); + return (ptr); +} + +uint32_t dfu_file_write_crc(int f, uint32_t crc, const void *buf, int size) +{ + int x; + + /* compute CRC */ + for (x = 0; x != size; x++) + crc = crc32_byte(crc, ((uint8_t *)buf)[x]); + + /* write data */ + if (write(f, buf, size) != size) + err(EX_IOERR, "Could not write %d bytes to file %d", size, f); + + return (crc); +} + +void dfu_load_file(struct dfu_file *file, enum suffix_req check_suffix, enum prefix_req check_prefix) +{ + off_t offset; + int f; + int i; + int res; + + file->size.prefix = 0; + file->size.suffix = 0; + + /* default values, if no valid suffix is found */ + file->bcdDFU = 0; + file->idVendor = 0xffff; /* wildcard value */ + file->idProduct = 0xffff; /* wildcard value */ + file->bcdDevice = 0xffff; /* wildcard value */ + + /* default values, if no valid prefix is found */ + file->lmdfu_address = 0; + + free(file->firmware); + + if (!strcmp(file->name, "-")) { + int read_bytes; + +#ifdef WIN32 + _setmode( _fileno( stdin ), _O_BINARY ); +#endif + file->firmware = (uint8_t*) dfu_malloc(STDIN_CHUNK_SIZE); + read_bytes = fread(file->firmware, 1, STDIN_CHUNK_SIZE, stdin); + file->size.total = read_bytes; + while (read_bytes == STDIN_CHUNK_SIZE) { + file->firmware = (uint8_t*) realloc(file->firmware, file->size.total + STDIN_CHUNK_SIZE); + if (!file->firmware) + err(EX_IOERR, "Could not allocate firmware buffer"); + read_bytes = fread(file->firmware + file->size.total, 1, STDIN_CHUNK_SIZE, stdin); + file->size.total += read_bytes; + } + if (verbose) + printf("Read %i bytes from stdin\n", file->size.total); + /* Never require suffix when reading from stdin */ + check_suffix = MAYBE_SUFFIX; + } else { + f = open(file->name, O_RDONLY | O_BINARY); + if (f < 0) + err(EX_IOERR, "Could not open file %s for reading", file->name); + + offset = lseek(f, 0, SEEK_END); + + if ((int)offset < 0 || (int)offset != offset) + err(EX_IOERR, "File size is too big"); + + if (lseek(f, 0, SEEK_SET) != 0) + err(EX_IOERR, "Could not seek to beginning"); + + file->size.total = offset; + file->firmware = dfu_malloc(file->size.total); + + if (read(f, file->firmware, file->size.total) != file->size.total) { + err(EX_IOERR, "Could not read %d bytes from %s", + file->size.total, file->name); + } + close(f); + } + + /* Check for possible DFU file suffix by trying to parse one */ + { + uint32_t crc = 0xffffffff; + const uint8_t *dfusuffix; + int missing_suffix = 0; + const char *reason; + + if (file->size.total < DFU_SUFFIX_LENGTH) { + reason = "File too short for DFU suffix"; + missing_suffix = 1; + goto checked; + } + + dfusuffix = file->firmware + file->size.total - + DFU_SUFFIX_LENGTH; + + for (i = 0; i < file->size.total - 4; i++) + crc = crc32_byte(crc, file->firmware[i]); + + if (dfusuffix[10] != 'D' || + dfusuffix[9] != 'F' || + dfusuffix[8] != 'U') { + reason = "Invalid DFU suffix signature"; + missing_suffix = 1; + goto checked; + } + + file->dwCRC = (dfusuffix[15] << 24) + + (dfusuffix[14] << 16) + + (dfusuffix[13] << 8) + + dfusuffix[12]; + + if (file->dwCRC != crc) { + reason = "DFU suffix CRC does not match"; + missing_suffix = 1; + goto checked; + } + + /* At this point we believe we have a DFU suffix + so we require further checks to succeed */ + + file->bcdDFU = (dfusuffix[7] << 8) + dfusuffix[6]; + + if (verbose) + printf("DFU suffix version %x\n", file->bcdDFU); + + file->size.suffix = dfusuffix[11]; + + if (file->size.suffix < DFU_SUFFIX_LENGTH) { + errx(EX_IOERR, "Unsupported DFU suffix length %d", + file->size.suffix); + } + + if (file->size.suffix > file->size.total) { + errx(EX_IOERR, "Invalid DFU suffix length %d", + file->size.suffix); + } + + file->idVendor = (dfusuffix[5] << 8) + dfusuffix[4]; + file->idProduct = (dfusuffix[3] << 8) + dfusuffix[2]; + file->bcdDevice = (dfusuffix[1] << 8) + dfusuffix[0]; + +checked: + if (missing_suffix) { + if (check_suffix == NEEDS_SUFFIX) { + warnx("%s", reason); + errx(EX_IOERR, "Valid DFU suffix needed"); + } else if (check_suffix == MAYBE_SUFFIX) { + warnx("%s", reason); + warnx("A valid DFU suffix will be required in " + "a future dfu-util release!!!"); + } + } else { + if (check_suffix == NO_SUFFIX) { + errx(EX_SOFTWARE, "Please remove existing DFU suffix before adding a new one.\n"); + } + } + } + res = probe_prefix(file); + if ((res || file->size.prefix == 0) && check_prefix == NEEDS_PREFIX) + errx(EX_IOERR, "Valid DFU prefix needed"); + if (file->size.prefix && check_prefix == NO_PREFIX) + errx(EX_IOERR, "A prefix already exists, please delete it first"); + if (file->size.prefix && verbose) { + uint8_t *data = file->firmware; + if (file->prefix_type == LMDFU_PREFIX) + printf("Possible TI Stellaris DFU prefix with " + "the following properties\n" + "Address: 0x%08x\n" + "Payload length: %d\n", + file->lmdfu_address, + data[4] | (data[5] << 8) | + (data[6] << 16) | (data[7] << 14)); + else if (file->prefix_type == LPCDFU_UNENCRYPTED_PREFIX) + printf("Possible unencrypted NXP LPC DFU prefix with " + "the following properties\n" + "Payload length: %d kiByte\n", + data[2] >>1 | (data[3] << 7) ); + else + errx(EX_IOERR, "Unknown DFU prefix type"); + } +} + +void dfu_store_file(struct dfu_file *file, int write_suffix, int write_prefix) +{ + uint32_t crc = 0xffffffff; + int f; + + f = open(file->name, O_WRONLY | O_BINARY | O_TRUNC | O_CREAT, 0666); + if (f < 0) + err(EX_IOERR, "Could not open file %s for writing", file->name); + + /* write prefix, if any */ + if (write_prefix) { + if (file->prefix_type == LMDFU_PREFIX) { + uint8_t lmdfu_prefix[LMDFU_PREFIX_LENGTH]; + uint32_t addr = file->lmdfu_address / 1024; + + /* lmdfu_dfu_prefix payload length excludes prefix and suffix */ + uint32_t len = file->size.total - + file->size.prefix - file->size.suffix; + + lmdfu_prefix[0] = 0x01; /* STELLARIS_DFU_PROG */ + lmdfu_prefix[1] = 0x00; /* Reserved */ + lmdfu_prefix[2] = (uint8_t)(addr & 0xff); + lmdfu_prefix[3] = (uint8_t)(addr >> 8); + lmdfu_prefix[4] = (uint8_t)(len & 0xff); + lmdfu_prefix[5] = (uint8_t)(len >> 8) & 0xff; + lmdfu_prefix[6] = (uint8_t)(len >> 16) & 0xff; + lmdfu_prefix[7] = (uint8_t)(len >> 24); + + crc = dfu_file_write_crc(f, crc, lmdfu_prefix, LMDFU_PREFIX_LENGTH); + } + if (file->prefix_type == LPCDFU_UNENCRYPTED_PREFIX) { + uint8_t lpcdfu_prefix[LPCDFU_PREFIX_LENGTH] = {0}; + int i; + + /* Payload is firmware and prefix rounded to 512 bytes */ + uint32_t len = (file->size.total - file->size.suffix + 511) /512; + + lpcdfu_prefix[0] = 0x1a; /* Unencypted*/ + lpcdfu_prefix[1] = 0x3f; /* Reserved */ + lpcdfu_prefix[2] = (uint8_t)(len & 0xff); + lpcdfu_prefix[3] = (uint8_t)((len >> 8) & 0xff); + for (i = 12; i < LPCDFU_PREFIX_LENGTH; i++) + lpcdfu_prefix[i] = 0xff; + + crc = dfu_file_write_crc(f, crc, lpcdfu_prefix, LPCDFU_PREFIX_LENGTH); + } + } + /* write firmware binary */ + crc = dfu_file_write_crc(f, crc, file->firmware + file->size.prefix, + file->size.total - file->size.prefix - file->size.suffix); + + /* write suffix, if any */ + if (write_suffix) { + uint8_t dfusuffix[DFU_SUFFIX_LENGTH]; + + dfusuffix[0] = file->bcdDevice & 0xff; + dfusuffix[1] = file->bcdDevice >> 8; + dfusuffix[2] = file->idProduct & 0xff; + dfusuffix[3] = file->idProduct >> 8; + dfusuffix[4] = file->idVendor & 0xff; + dfusuffix[5] = file->idVendor >> 8; + dfusuffix[6] = file->bcdDFU & 0xff; + dfusuffix[7] = file->bcdDFU >> 8; + dfusuffix[8] = 'U'; + dfusuffix[9] = 'F'; + dfusuffix[10] = 'D'; + dfusuffix[11] = DFU_SUFFIX_LENGTH; + + crc = dfu_file_write_crc(f, crc, dfusuffix, + DFU_SUFFIX_LENGTH - 4); + + dfusuffix[12] = crc; + dfusuffix[13] = crc >> 8; + dfusuffix[14] = crc >> 16; + dfusuffix[15] = crc >> 24; + + crc = dfu_file_write_crc(f, crc, dfusuffix + 12, 4); + } + close(f); +} + +void show_suffix_and_prefix(struct dfu_file *file) +{ + if (file->size.prefix == LMDFU_PREFIX_LENGTH) { + printf("The file %s contains a TI Stellaris DFU prefix with the following properties:\n", file->name); + printf("Address:\t0x%08x\n", file->lmdfu_address); + } else if (file->size.prefix == LPCDFU_PREFIX_LENGTH) { + uint8_t * prefix = file->firmware; + printf("The file %s contains a NXP unencrypted LPC DFU prefix with the following properties:\n", file->name); + printf("Size:\t%5d kiB\n", prefix[2]>>1|prefix[3]<<7); + } else if (file->size.prefix != 0) { + printf("The file %s contains an unknown prefix\n", file->name); + } + if (file->size.suffix > 0) { + printf("The file %s contains a DFU suffix with the following properties:\n", file->name); + printf("BCD device:\t0x%04X\n", file->bcdDevice); + printf("Product ID:\t0x%04X\n",file->idProduct); + printf("Vendor ID:\t0x%04X\n", file->idVendor); + printf("BCD DFU:\t0x%04X\n", file->bcdDFU); + printf("Length:\t\t%i\n", file->size.suffix); + printf("CRC:\t\t0x%08X\n", file->dwCRC); + } +} diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfu_file.h b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfu_file.h new file mode 100644 index 0000000..abebd44 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfu_file.h @@ -0,0 +1,60 @@ + +#ifndef DFU_FILE_H +#define DFU_FILE_H + +#include + +struct dfu_file { + /* File name */ + const char *name; + /* Pointer to file loaded into memory */ + uint8_t *firmware; + /* Different sizes */ + struct { + int total; + int prefix; + int suffix; + } size; + /* From prefix fields */ + uint32_t lmdfu_address; + /* From prefix fields */ + uint32_t prefix_type; + + /* From DFU suffix fields */ + uint32_t dwCRC; + uint16_t bcdDFU; + uint16_t idVendor; + uint16_t idProduct; + uint16_t bcdDevice; +}; + +enum suffix_req { + NO_SUFFIX, + NEEDS_SUFFIX, + MAYBE_SUFFIX +}; + +enum prefix_req { + NO_PREFIX, + NEEDS_PREFIX, + MAYBE_PREFIX +}; + +enum prefix_type { + ZERO_PREFIX, + LMDFU_PREFIX, + LPCDFU_UNENCRYPTED_PREFIX +}; + +extern int verbose; + +void dfu_load_file(struct dfu_file *file, enum suffix_req check_suffix, enum prefix_req check_prefix); +void dfu_store_file(struct dfu_file *file, int write_suffix, int write_prefix); + +void dfu_progress_bar(const char *desc, unsigned long long curr, + unsigned long long max); +void *dfu_malloc(size_t size); +uint32_t dfu_file_write_crc(int f, uint32_t crc, const void *buf, int size); +void show_suffix_and_prefix(struct dfu_file *file); + +#endif /* DFU_FILE_H */ diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfu_load.c b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfu_load.c new file mode 100644 index 0000000..64f7009 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfu_load.c @@ -0,0 +1,196 @@ +/* + * DFU transfer routines + * + * This is supposed to be a general DFU implementation, as specified in the + * USB DFU 1.0 and 1.1 specification. + * + * The code was originally intended to interface with a USB device running the + * "sam7dfu" firmware (see http://www.openpcd.org/) on an AT91SAM7 processor. + * + * Copyright 2007-2008 Harald Welte + * Copyright 2013 Hans Petter Selasky + * Copyright 2014 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include + +#include "portable.h" +#include "dfu.h" +#include "usb_dfu.h" +#include "dfu_file.h" +#include "dfu_load.h" +#include "quirks.h" + +int dfuload_do_upload(struct dfu_if *dif, int xfer_size, + int expected_size, int fd) +{ + int total_bytes = 0; + unsigned short transaction = 0; + unsigned char *buf; + int ret; + + buf = dfu_malloc(xfer_size); + + printf("Copying data from DFU device to PC\n"); + dfu_progress_bar("Upload", 0, 1); + + while (1) { + int rc; + rc = dfu_upload(dif->dev_handle, dif->interface, + xfer_size, transaction++, buf); + if (rc < 0) { + warnx("Error during upload"); + ret = rc; + goto out_free; + } + + dfu_file_write_crc(fd, 0, buf, rc); + total_bytes += rc; + + if (total_bytes < 0) + errx(EX_SOFTWARE, "Received too many bytes (wraparound)"); + + if (rc < xfer_size) { + /* last block, return */ + ret = total_bytes; + break; + } + dfu_progress_bar("Upload", total_bytes, expected_size); + } + ret = 0; + +out_free: + dfu_progress_bar("Upload", total_bytes, total_bytes); + if (total_bytes == 0) + printf("\nFailed.\n"); + free(buf); + if (verbose) + printf("Received a total of %i bytes\n", total_bytes); + if (expected_size != 0 && total_bytes != expected_size) + errx(EX_SOFTWARE, "Unexpected number of bytes uploaded from device"); + return ret; +} + +int dfuload_do_dnload(struct dfu_if *dif, int xfer_size, struct dfu_file *file) +{ + int bytes_sent; + int expected_size; + unsigned char *buf; + unsigned short transaction = 0; + struct dfu_status dst; + int ret; + + printf("Copying data from PC to DFU device\n"); + + buf = file->firmware; + expected_size = file->size.total - file->size.suffix; + bytes_sent = 0; + + dfu_progress_bar("Download", 0, 1); + while (bytes_sent < expected_size) { + int bytes_left; + int chunk_size; + + bytes_left = expected_size - bytes_sent; + if (bytes_left < xfer_size) + chunk_size = bytes_left; + else + chunk_size = xfer_size; + + ret = dfu_download(dif->dev_handle, dif->interface, + chunk_size, transaction++, chunk_size ? buf : NULL); + if (ret < 0) { + warnx("Error during download"); + goto out; + } + bytes_sent += chunk_size; + buf += chunk_size; + + do { + ret = dfu_get_status(dif, &dst); + if (ret < 0) { + errx(EX_IOERR, "Error during download get_status"); + goto out; + } + + if (dst.bState == DFU_STATE_dfuDNLOAD_IDLE || + dst.bState == DFU_STATE_dfuERROR) + break; + + /* Wait while device executes flashing */ + milli_sleep(dst.bwPollTimeout); + + } while (1); + if (dst.bStatus != DFU_STATUS_OK) { + printf(" failed!\n"); + printf("state(%u) = %s, status(%u) = %s\n", dst.bState, + dfu_state_to_string(dst.bState), dst.bStatus, + dfu_status_to_string(dst.bStatus)); + ret = -1; + goto out; + } + dfu_progress_bar("Download", bytes_sent, bytes_sent + bytes_left); + } + + /* send one zero sized download request to signalize end */ + ret = dfu_download(dif->dev_handle, dif->interface, + 0, transaction, NULL); + if (ret < 0) { + errx(EX_IOERR, "Error sending completion packet"); + goto out; + } + + dfu_progress_bar("Download", bytes_sent, bytes_sent); + + if (verbose) + printf("Sent a total of %i bytes\n", bytes_sent); + +get_status: + /* Transition to MANIFEST_SYNC state */ + ret = dfu_get_status(dif, &dst); + if (ret < 0) { + warnx("unable to read DFU status after completion"); + goto out; + } + printf("state(%u) = %s, status(%u) = %s\n", dst.bState, + dfu_state_to_string(dst.bState), dst.bStatus, + dfu_status_to_string(dst.bStatus)); + + milli_sleep(dst.bwPollTimeout); + + /* FIXME: deal correctly with ManifestationTolerant=0 / WillDetach bits */ + switch (dst.bState) { + case DFU_STATE_dfuMANIFEST_SYNC: + case DFU_STATE_dfuMANIFEST: + /* some devices (e.g. TAS1020b) need some time before we + * can obtain the status */ + milli_sleep(1000); + goto get_status; + break; + case DFU_STATE_dfuIDLE: + break; + } + printf("Done!\n"); + +out: + return bytes_sent; +} diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfu_load.h b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfu_load.h new file mode 100644 index 0000000..be23e9b --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfu_load.h @@ -0,0 +1,7 @@ +#ifndef DFU_LOAD_H +#define DFU_LOAD_H + +int dfuload_do_upload(struct dfu_if *dif, int xfer_size, int expected_size, int fd); +int dfuload_do_dnload(struct dfu_if *dif, int xfer_size, struct dfu_file *file); + +#endif /* DFU_LOAD_H */ diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfu_util.c b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfu_util.c new file mode 100644 index 0000000..b94c7cc --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfu_util.c @@ -0,0 +1,346 @@ +/* + * Functions for detecting DFU USB entities + * + * Written by Harald Welte + * Copyright 2007-2008 by OpenMoko, Inc. + * Copyright 2013 Hans Petter Selasky + * + * Based on existing code of dfu-programmer-0.4 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include "portable.h" +#include "dfu.h" +#include "usb_dfu.h" +#include "dfu_file.h" +#include "dfu_load.h" +#include "dfu_util.h" +#include "dfuse.h" +#include "quirks.h" + +#ifdef HAVE_USBPATH_H +#include +#endif + +/* + * Look for a descriptor in a concatenated descriptor list. Will + * return upon the first match of the given descriptor type. Returns length of + * found descriptor, limited to res_size + */ +static int find_descriptor(const uint8_t *desc_list, int list_len, + uint8_t desc_type, void *res_buf, int res_size) +{ + int p = 0; + + if (list_len < 2) + return (-1); + + while (p + 1 < list_len) { + int desclen; + + desclen = (int) desc_list[p]; + if (desclen == 0) { + warnx("Invalid descriptor list"); + return -1; + } + if (desc_list[p + 1] == desc_type) { + if (desclen > res_size) + desclen = res_size; + if (p + desclen > list_len) + desclen = list_len - p; + memcpy(res_buf, &desc_list[p], desclen); + return desclen; + } + p += (int) desc_list[p]; + } + return -1; +} + +static void probe_configuration(libusb_device *dev, struct libusb_device_descriptor *desc) +{ + struct usb_dfu_func_descriptor func_dfu; + libusb_device_handle *devh; + struct dfu_if *pdfu; + struct libusb_config_descriptor *cfg; + const struct libusb_interface_descriptor *intf; + const struct libusb_interface *uif; + char alt_name[MAX_DESC_STR_LEN + 1]; + char serial_name[MAX_DESC_STR_LEN + 1]; + int cfg_idx; + int intf_idx; + int alt_idx; + int ret; + int has_dfu; + + for (cfg_idx = 0; cfg_idx != desc->bNumConfigurations; cfg_idx++) { + memset(&func_dfu, 0, sizeof(func_dfu)); + has_dfu = 0; + + ret = libusb_get_config_descriptor(dev, cfg_idx, &cfg); + if (ret != 0) + return; + if (match_config_index > -1 && match_config_index != cfg->bConfigurationValue) { + libusb_free_config_descriptor(cfg); + continue; + } + + /* + * In some cases, noticably FreeBSD if uid != 0, + * the configuration descriptors are empty + */ + if (!cfg) + return; + + ret = find_descriptor(cfg->extra, cfg->extra_length, + USB_DT_DFU, &func_dfu, sizeof(func_dfu)); + if (ret > -1) + goto found_dfu; + + for (intf_idx = 0; intf_idx < cfg->bNumInterfaces; + intf_idx++) { + uif = &cfg->interface[intf_idx]; + if (!uif) + break; + + for (alt_idx = 0; alt_idx < cfg->interface[intf_idx].num_altsetting; + alt_idx++) { + intf = &uif->altsetting[alt_idx]; + + ret = find_descriptor(intf->extra, intf->extra_length, USB_DT_DFU, + &func_dfu, sizeof(func_dfu)); + if (ret > -1) + goto found_dfu; + + if (intf->bInterfaceClass != 0xfe || + intf->bInterfaceSubClass != 1) + continue; + + has_dfu = 1; + } + } + if (has_dfu) { + /* + * Finally try to retrieve it requesting the + * device directly This is not supported on + * all devices for non-standard types + */ + if (libusb_open(dev, &devh) == 0) { + ret = libusb_get_descriptor(devh, USB_DT_DFU, 0, + (void *)&func_dfu, sizeof(func_dfu)); + libusb_close(devh); + if (ret > -1) + goto found_dfu; + } + warnx("Device has DFU interface, " + "but has no DFU functional descriptor"); + + /* fake version 1.0 */ + func_dfu.bLength = 7; + func_dfu.bcdDFUVersion = libusb_cpu_to_le16(0x0100); + goto found_dfu; + } + libusb_free_config_descriptor(cfg); + continue; + +found_dfu: + if (func_dfu.bLength == 7) { + printf("Deducing device DFU version from functional descriptor " + "length\n"); + func_dfu.bcdDFUVersion = libusb_cpu_to_le16(0x0100); + } else if (func_dfu.bLength < 9) { + printf("Error obtaining DFU functional descriptor\n"); + printf("Please report this as a bug!\n"); + printf("Warning: Assuming DFU version 1.0\n"); + func_dfu.bcdDFUVersion = libusb_cpu_to_le16(0x0100); + printf("Warning: Transfer size can not be detected\n"); + func_dfu.wTransferSize = 0; + } + + for (intf_idx = 0; intf_idx < cfg->bNumInterfaces; + intf_idx++) { + if (match_iface_index > -1 && match_iface_index != intf_idx) + continue; + + uif = &cfg->interface[intf_idx]; + if (!uif) + break; + + for (alt_idx = 0; + alt_idx < uif->num_altsetting; alt_idx++) { + int dfu_mode; + + intf = &uif->altsetting[alt_idx]; + + if (intf->bInterfaceClass != 0xfe || + intf->bInterfaceSubClass != 1) + continue; + + dfu_mode = (intf->bInterfaceProtocol == 2); + /* e.g. DSO Nano has bInterfaceProtocol 0 instead of 2 */ + if (func_dfu.bcdDFUVersion == 0x011a && intf->bInterfaceProtocol == 0) + dfu_mode = 1; + + if (dfu_mode && + match_iface_alt_index > -1 && match_iface_alt_index != alt_idx) + continue; + + if (dfu_mode) { + if ((match_vendor_dfu >= 0 && match_vendor_dfu != desc->idVendor) || + (match_product_dfu >= 0 && match_product_dfu != desc->idProduct)) { + continue; + } + } else { + if ((match_vendor >= 0 && match_vendor != desc->idVendor) || + (match_product >= 0 && match_product != desc->idProduct)) { + continue; + } + } + + if (libusb_open(dev, &devh)) { + warnx("Cannot open DFU device %04x:%04x", desc->idVendor, desc->idProduct); + break; + } + if (intf->iInterface != 0) + ret = libusb_get_string_descriptor_ascii(devh, + intf->iInterface, (void *)alt_name, MAX_DESC_STR_LEN); + else + ret = -1; + if (ret < 1) + strcpy(alt_name, "UNKNOWN"); + if (desc->iSerialNumber != 0) + ret = libusb_get_string_descriptor_ascii(devh, + desc->iSerialNumber, (void *)serial_name, MAX_DESC_STR_LEN); + else + ret = -1; + if (ret < 1) + strcpy(serial_name, "UNKNOWN"); + libusb_close(devh); + + if (dfu_mode && + match_iface_alt_name != NULL && strcmp(alt_name, match_iface_alt_name)) + continue; + + if (dfu_mode) { + if (match_serial_dfu != NULL && strcmp(match_serial_dfu, serial_name)) + continue; + } else { + if (match_serial != NULL && strcmp(match_serial, serial_name)) + continue; + } + + pdfu = dfu_malloc(sizeof(*pdfu)); + + memset(pdfu, 0, sizeof(*pdfu)); + + pdfu->func_dfu = func_dfu; + pdfu->dev = libusb_ref_device(dev); + pdfu->quirks = get_quirks(desc->idVendor, + desc->idProduct, desc->bcdDevice); + pdfu->vendor = desc->idVendor; + pdfu->product = desc->idProduct; + pdfu->bcdDevice = desc->bcdDevice; + pdfu->configuration = cfg->bConfigurationValue; + pdfu->interface = intf->bInterfaceNumber; + pdfu->altsetting = intf->bAlternateSetting; + pdfu->devnum = libusb_get_device_address(dev); + pdfu->busnum = libusb_get_bus_number(dev); + pdfu->alt_name = strdup(alt_name); + if (pdfu->alt_name == NULL) + errx(EX_SOFTWARE, "Out of memory"); + pdfu->serial_name = strdup(serial_name); + if (pdfu->serial_name == NULL) + errx(EX_SOFTWARE, "Out of memory"); + if (dfu_mode) + pdfu->flags |= DFU_IFF_DFU; + if (pdfu->quirks & QUIRK_FORCE_DFU11) { + pdfu->func_dfu.bcdDFUVersion = + libusb_cpu_to_le16(0x0110); + } + pdfu->bMaxPacketSize0 = desc->bMaxPacketSize0; + + /* queue into list */ + pdfu->next = dfu_root; + dfu_root = pdfu; + } + } + libusb_free_config_descriptor(cfg); + } +} + +void probe_devices(libusb_context *ctx) +{ + libusb_device **list; + ssize_t num_devs; + ssize_t i; + + num_devs = libusb_get_device_list(ctx, &list); + for (i = 0; i < num_devs; ++i) { + struct libusb_device_descriptor desc; + struct libusb_device *dev = list[i]; + + if (match_bus > -1 && match_bus != libusb_get_bus_number(dev)) + continue; + if (match_device > -1 && match_device != libusb_get_device_address(dev)) + continue; + if (libusb_get_device_descriptor(dev, &desc)) + continue; + probe_configuration(dev, &desc); + } + libusb_free_device_list(list, 0); +} + +void disconnect_devices(void) +{ + struct dfu_if *pdfu; + struct dfu_if *prev = NULL; + + for (pdfu = dfu_root; pdfu != NULL; pdfu = pdfu->next) { + free(prev); + libusb_unref_device(pdfu->dev); + free(pdfu->alt_name); + free(pdfu->serial_name); + prev = pdfu; + } + free(prev); + dfu_root = NULL; +} + +void print_dfu_if(struct dfu_if *dfu_if) +{ + printf("Found %s: [%04x:%04x] ver=%04x, devnum=%u, cfg=%u, intf=%u, " + "alt=%u, name=\"%s\", serial=\"%s\"\n", + dfu_if->flags & DFU_IFF_DFU ? "DFU" : "Runtime", + dfu_if->vendor, dfu_if->product, + dfu_if->bcdDevice, dfu_if->devnum, + dfu_if->configuration, dfu_if->interface, + dfu_if->altsetting, dfu_if->alt_name, + dfu_if->serial_name); +} + +/* Walk the device tree and print out DFU devices */ +void list_dfu_interfaces(void) +{ + struct dfu_if *pdfu; + + for (pdfu = dfu_root; pdfu != NULL; pdfu = pdfu->next) + print_dfu_if(pdfu); +} diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfu_util.h b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfu_util.h new file mode 100644 index 0000000..fc0c19d --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfu_util.h @@ -0,0 +1,36 @@ +#ifndef DFU_UTIL_H +#define DFU_UTIL_H + +/* USB string descriptor should contain max 126 UTF-16 characters + * but 253 would even accomodate any UTF-8 encoding */ +#define MAX_DESC_STR_LEN 253 + +enum mode { + MODE_NONE, + MODE_VERSION, + MODE_LIST, + MODE_DETACH, + MODE_UPLOAD, + MODE_DOWNLOAD +}; + +extern struct dfu_if *dfu_root; +extern int match_bus; +extern int match_device; +extern int match_vendor; +extern int match_product; +extern int match_vendor_dfu; +extern int match_product_dfu; +extern int match_config_index; +extern int match_iface_index; +extern int match_iface_alt_index; +extern const char *match_iface_alt_name; +extern const char *match_serial; +extern const char *match_serial_dfu; + +void probe_devices(libusb_context *); +void disconnect_devices(void); +void print_dfu_if(struct dfu_if *); +void list_dfu_interfaces(void); + +#endif /* DFU_UTIL_H */ diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfuse.c b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfuse.c new file mode 100644 index 0000000..fce29fe --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfuse.c @@ -0,0 +1,652 @@ +/* + * DfuSe specific functions + * + * This implements the ST Microsystems DFU extensions (DfuSe) + * as per the DfuSe 1.1a specification (ST documents AN3156, AN2606) + * The DfuSe file format is described in ST document UM0391. + * + * Copyright 2010-2014 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "portable.h" +#include "dfu.h" +#include "usb_dfu.h" +#include "dfu_file.h" +#include "dfuse.h" +#include "dfuse_mem.h" + +#define DFU_TIMEOUT 5000 + +extern int verbose; +static unsigned int last_erased_page = 1; /* non-aligned value, won't match */ +static struct memsegment *mem_layout; +static unsigned int dfuse_address = 0; +static unsigned int dfuse_length = 0; +static int dfuse_force = 0; +static int dfuse_leave = 0; +static int dfuse_unprotect = 0; +static int dfuse_mass_erase = 0; + +unsigned int quad2uint(unsigned char *p) +{ + return (*p + (*(p + 1) << 8) + (*(p + 2) << 16) + (*(p + 3) << 24)); +} + +void dfuse_parse_options(const char *options) +{ + char *end; + const char *endword; + unsigned int number; + + /* address, possibly empty, must be first */ + if (*options != ':') { + endword = strchr(options, ':'); + if (!endword) + endword = options + strlen(options); /* GNU strchrnul */ + + number = strtoul(options, &end, 0); + if (end == endword) { + dfuse_address = number; + } else { + errx(EX_IOERR, "Invalid dfuse address: %s", options); + } + options = endword; + } + + while (*options) { + if (*options == ':') { + options++; + continue; + } + endword = strchr(options, ':'); + if (!endword) + endword = options + strlen(options); + + if (!strncmp(options, "force", endword - options)) { + dfuse_force++; + options += 5; + continue; + } + if (!strncmp(options, "leave", endword - options)) { + dfuse_leave = 1; + options += 5; + continue; + } + if (!strncmp(options, "unprotect", endword - options)) { + dfuse_unprotect = 1; + options += 9; + continue; + } + if (!strncmp(options, "mass-erase", endword - options)) { + dfuse_mass_erase = 1; + options += 10; + continue; + } + + /* any valid number is interpreted as upload length */ + number = strtoul(options, &end, 0); + if (end == endword) { + dfuse_length = number; + } else { + errx(EX_IOERR, "Invalid dfuse modifier: %s", options); + } + options = endword; + } +} + +/* DFU_UPLOAD request for DfuSe 1.1a */ +int dfuse_upload(struct dfu_if *dif, const unsigned short length, + unsigned char *data, unsigned short transaction) +{ + int status; + + status = libusb_control_transfer(dif->dev_handle, + /* bmRequestType */ LIBUSB_ENDPOINT_IN | + LIBUSB_REQUEST_TYPE_CLASS | + LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_UPLOAD, + /* wValue */ transaction, + /* wIndex */ dif->interface, + /* Data */ data, + /* wLength */ length, + DFU_TIMEOUT); + if (status < 0) { + errx(EX_IOERR, "%s: libusb_control_msg returned %d", + __FUNCTION__, status); + } + return status; +} + +/* DFU_DNLOAD request for DfuSe 1.1a */ +int dfuse_download(struct dfu_if *dif, const unsigned short length, + unsigned char *data, unsigned short transaction) +{ + int status; + + status = libusb_control_transfer(dif->dev_handle, + /* bmRequestType */ LIBUSB_ENDPOINT_OUT | + LIBUSB_REQUEST_TYPE_CLASS | + LIBUSB_RECIPIENT_INTERFACE, + /* bRequest */ DFU_DNLOAD, + /* wValue */ transaction, + /* wIndex */ dif->interface, + /* Data */ data, + /* wLength */ length, + DFU_TIMEOUT); + if (status < 0) { + errx(EX_IOERR, "%s: libusb_control_transfer returned %d", + __FUNCTION__, status); + } + return status; +} + +/* DfuSe only commands */ +/* Leaves the device in dfuDNLOAD-IDLE state */ +int dfuse_special_command(struct dfu_if *dif, unsigned int address, + enum dfuse_command command) +{ + const char* dfuse_command_name[] = { "SET_ADDRESS" , "ERASE_PAGE", + "MASS_ERASE", "READ_UNPROTECT"}; + unsigned char buf[5]; + int length; + int ret; + struct dfu_status dst; + int firstpoll = 1; + + if (command == ERASE_PAGE) { + struct memsegment *segment; + int page_size; + + segment = find_segment(mem_layout, address); + if (!segment || !(segment->memtype & DFUSE_ERASABLE)) { + errx(EX_IOERR, "Page at 0x%08x can not be erased", + address); + } + page_size = segment->pagesize; + if (verbose > 1) + printf("Erasing page size %i at address 0x%08x, page " + "starting at 0x%08x\n", page_size, address, + address & ~(page_size - 1)); + buf[0] = 0x41; /* Erase command */ + length = 5; + last_erased_page = address & ~(page_size - 1); + } else if (command == SET_ADDRESS) { + if (verbose > 2) + printf(" Setting address pointer to 0x%08x\n", + address); + buf[0] = 0x21; /* Set Address Pointer command */ + length = 5; + } else if (command == MASS_ERASE) { + buf[0] = 0x41; /* Mass erase command when length = 1 */ + length = 1; + } else if (command == READ_UNPROTECT) { + buf[0] = 0x92; + length = 1; + } else { + errx(EX_IOERR, "Non-supported special command %d", command); + } + buf[1] = address & 0xff; + buf[2] = (address >> 8) & 0xff; + buf[3] = (address >> 16) & 0xff; + buf[4] = (address >> 24) & 0xff; + + ret = dfuse_download(dif, length, buf, 0); + if (ret < 0) { + errx(EX_IOERR, "Error during special command \"%s\" download", + dfuse_command_name[command]); + } + do { + ret = dfu_get_status(dif, &dst); + if (ret < 0) { + errx(EX_IOERR, "Error during special command \"%s\" get_status", + dfuse_command_name[command]); + } + if (firstpoll) { + firstpoll = 0; + if (dst.bState != DFU_STATE_dfuDNBUSY) { + printf("state(%u) = %s, status(%u) = %s\n", dst.bState, + dfu_state_to_string(dst.bState), dst.bStatus, + dfu_status_to_string(dst.bStatus)); + errx(EX_IOERR, "Wrong state after command \"%s\" download", + dfuse_command_name[command]); + } + } + /* wait while command is executed */ + if (verbose) + printf(" Poll timeout %i ms\n", dst.bwPollTimeout); + milli_sleep(dst.bwPollTimeout); + if (command == READ_UNPROTECT) + return ret; + } while (dst.bState == DFU_STATE_dfuDNBUSY); + + if (dst.bStatus != DFU_STATUS_OK) { + errx(EX_IOERR, "%s not correctly executed", + dfuse_command_name[command]); + } + return ret; +} + +int dfuse_dnload_chunk(struct dfu_if *dif, unsigned char *data, int size, + int transaction) +{ + int bytes_sent; + struct dfu_status dst; + int ret; + + ret = dfuse_download(dif, size, size ? data : NULL, transaction); + if (ret < 0) { + errx(EX_IOERR, "Error during download"); + return ret; + } + bytes_sent = ret; + + do { + ret = dfu_get_status(dif, &dst); + if (ret < 0) { + errx(EX_IOERR, "Error during download get_status"); + return ret; + } + milli_sleep(dst.bwPollTimeout); + } while (dst.bState != DFU_STATE_dfuDNLOAD_IDLE && + dst.bState != DFU_STATE_dfuERROR && + dst.bState != DFU_STATE_dfuMANIFEST); + + if (dst.bState == DFU_STATE_dfuMANIFEST) + printf("Transitioning to dfuMANIFEST state\n"); + + if (dst.bStatus != DFU_STATUS_OK) { + printf(" failed!\n"); + printf("state(%u) = %s, status(%u) = %s\n", dst.bState, + dfu_state_to_string(dst.bState), dst.bStatus, + dfu_status_to_string(dst.bStatus)); + return -1; + } + return bytes_sent; +} + +int dfuse_do_upload(struct dfu_if *dif, int xfer_size, int fd, + const char *dfuse_options) +{ + int total_bytes = 0; + int upload_limit = 0; + unsigned char *buf; + int transaction; + int ret; + + buf = dfu_malloc(xfer_size); + + if (dfuse_options) + dfuse_parse_options(dfuse_options); + if (dfuse_length) + upload_limit = dfuse_length; + if (dfuse_address) { + struct memsegment *segment; + + mem_layout = parse_memory_layout((char *)dif->alt_name); + if (!mem_layout) + errx(EX_IOERR, "Failed to parse memory layout"); + + segment = find_segment(mem_layout, dfuse_address); + if (!dfuse_force && + (!segment || !(segment->memtype & DFUSE_READABLE))) + errx(EX_IOERR, "Page at 0x%08x is not readable", + dfuse_address); + + if (!upload_limit) { + upload_limit = segment->end - dfuse_address + 1; + printf("Limiting upload to end of memory segment, " + "%i bytes\n", upload_limit); + } + dfuse_special_command(dif, dfuse_address, SET_ADDRESS); + dfu_abort_to_idle(dif); + } else { + /* Boot loader decides the start address, unknown to us */ + /* Use a short length to lower risk of running out of bounds */ + if (!upload_limit) + upload_limit = 0x4000; + printf("Limiting default upload to %i bytes\n", upload_limit); + } + + dfu_progress_bar("Upload", 0, 1); + + transaction = 2; + while (1) { + int rc; + + /* last chunk can be smaller than original xfer_size */ + if (upload_limit - total_bytes < xfer_size) + xfer_size = upload_limit - total_bytes; + rc = dfuse_upload(dif, xfer_size, buf, transaction++); + if (rc < 0) { + ret = rc; + goto out_free; + } + + dfu_file_write_crc(fd, 0, buf, rc); + total_bytes += rc; + + if (total_bytes < 0) + errx(EX_SOFTWARE, "Received too many bytes"); + + if (rc < xfer_size || total_bytes >= upload_limit) { + /* last block, return successfully */ + ret = total_bytes; + break; + } + dfu_progress_bar("Upload", total_bytes, upload_limit); + } + + dfu_progress_bar("Upload", total_bytes, total_bytes); + + dfu_abort_to_idle(dif); + if (dfuse_leave) { + dfuse_special_command(dif, dfuse_address, SET_ADDRESS); + dfuse_dnload_chunk(dif, NULL, 0, 2); /* Zero-size */ + } + + out_free: + free(buf); + + return ret; +} + +/* Writes an element of any size to the device, taking care of page erases */ +/* returns 0 on success, otherwise -EINVAL */ +int dfuse_dnload_element(struct dfu_if *dif, unsigned int dwElementAddress, + unsigned int dwElementSize, unsigned char *data, + int xfer_size) +{ + int p; + int ret; + struct memsegment *segment; + + /* Check at least that we can write to the last address */ + segment = + find_segment(mem_layout, dwElementAddress + dwElementSize - 1); + if (!segment || !(segment->memtype & DFUSE_WRITEABLE)) { + errx(EX_IOERR, "Last page at 0x%08x is not writeable", + dwElementAddress + dwElementSize - 1); + } + + dfu_progress_bar("Download", 0, 1); + + for (p = 0; p < (int)dwElementSize; p += xfer_size) { + int page_size; + unsigned int erase_address; + unsigned int address = dwElementAddress + p; + int chunk_size = xfer_size; + + segment = find_segment(mem_layout, address); + if (!segment || !(segment->memtype & DFUSE_WRITEABLE)) { + errx(EX_IOERR, "Page at 0x%08x is not writeable", + address); + } + page_size = segment->pagesize; + + /* check if this is the last chunk */ + if (p + chunk_size > (int)dwElementSize) + chunk_size = dwElementSize - p; + + /* Erase only for flash memory downloads */ + if ((segment->memtype & DFUSE_ERASABLE) && !dfuse_mass_erase) { + /* erase all involved pages */ + for (erase_address = address; + erase_address < address + chunk_size; + erase_address += page_size) + if ((erase_address & ~(page_size - 1)) != + last_erased_page) + dfuse_special_command(dif, + erase_address, + ERASE_PAGE); + + if (((address + chunk_size - 1) & ~(page_size - 1)) != + last_erased_page) { + if (verbose > 2) + printf(" Chunk extends into next page," + " erase it as well\n"); + dfuse_special_command(dif, + address + chunk_size - 1, + ERASE_PAGE); + } + } + + if (verbose) { + printf(" Download from image offset " + "%08x to memory %08x-%08x, size %i\n", + p, address, address + chunk_size - 1, + chunk_size); + } else { + dfu_progress_bar("Download", p, dwElementSize); + } + + dfuse_special_command(dif, address, SET_ADDRESS); + + /* transaction = 2 for no address offset */ + ret = dfuse_dnload_chunk(dif, data + p, chunk_size, 2); + if (ret != chunk_size) { + errx(EX_IOERR, "Failed to write whole chunk: " + "%i of %i bytes", ret, chunk_size); + return -EINVAL; + } + } + if (!verbose) + dfu_progress_bar("Download", dwElementSize, dwElementSize); + return 0; +} + +static void +dfuse_memcpy(unsigned char *dst, unsigned char **src, int *rem, int size) +{ + if (size > *rem) { + errx(EX_IOERR, "Corrupt DfuSe file: " + "Cannot read %d bytes from %d bytes", size, *rem); + } + if (dst != NULL) + memcpy(dst, *src, size); + (*src) += size; + (*rem) -= size; +} + +/* Download raw binary file to DfuSe device */ +int dfuse_do_bin_dnload(struct dfu_if *dif, int xfer_size, + struct dfu_file *file, unsigned int start_address) +{ + unsigned int dwElementAddress; + unsigned int dwElementSize; + unsigned char *data; + int ret; + + dwElementAddress = start_address; + dwElementSize = file->size.total - + file->size.suffix - file->size.prefix; + + printf("Downloading to address = 0x%08x, size = %i\n", + dwElementAddress, dwElementSize); + + data = file->firmware + file->size.prefix; + + ret = dfuse_dnload_element(dif, dwElementAddress, dwElementSize, data, + xfer_size); + if (ret != 0) + goto out_free; + + printf("File downloaded successfully\n"); + ret = dwElementSize; + + out_free: + return ret; +} + +/* Parse a DfuSe file and download contents to device */ +int dfuse_do_dfuse_dnload(struct dfu_if *dif, int xfer_size, + struct dfu_file *file) +{ + uint8_t dfuprefix[11]; + uint8_t targetprefix[274]; + uint8_t elementheader[8]; + int image; + int element; + int bTargets; + int bAlternateSetting; + int dwNbElements; + unsigned int dwElementAddress; + unsigned int dwElementSize; + uint8_t *data; + int ret; + int rem; + int bFirstAddressSaved = 0; + + rem = file->size.total - file->size.prefix - file->size.suffix; + data = file->firmware + file->size.prefix; + + /* Must be larger than a minimal DfuSe header and suffix */ + if (rem < (int)(sizeof(dfuprefix) + + sizeof(targetprefix) + sizeof(elementheader))) { + errx(EX_SOFTWARE, "File too small for a DfuSe file"); + } + + dfuse_memcpy(dfuprefix, &data, &rem, sizeof(dfuprefix)); + + if (strncmp((char *)dfuprefix, "DfuSe", 5)) { + errx(EX_IOERR, "No valid DfuSe signature"); + return -EINVAL; + } + if (dfuprefix[5] != 0x01) { + errx(EX_IOERR, "DFU format revision %i not supported", + dfuprefix[5]); + return -EINVAL; + } + bTargets = dfuprefix[10]; + printf("file contains %i DFU images\n", bTargets); + + for (image = 1; image <= bTargets; image++) { + printf("parsing DFU image %i\n", image); + dfuse_memcpy(targetprefix, &data, &rem, sizeof(targetprefix)); + if (strncmp((char *)targetprefix, "Target", 6)) { + errx(EX_IOERR, "No valid target signature"); + return -EINVAL; + } + bAlternateSetting = targetprefix[6]; + dwNbElements = quad2uint((unsigned char *)targetprefix + 270); + printf("image for alternate setting %i, ", bAlternateSetting); + printf("(%i elements, ", dwNbElements); + printf("total size = %i)\n", + quad2uint((unsigned char *)targetprefix + 266)); + if (bAlternateSetting != dif->altsetting) + printf("Warning: Image does not match current alternate" + " setting.\n" + "Please rerun with the correct -a option setting" + " to download this image!\n"); + for (element = 1; element <= dwNbElements; element++) { + printf("parsing element %i, ", element); + dfuse_memcpy(elementheader, &data, &rem, sizeof(elementheader)); + dwElementAddress = + quad2uint((unsigned char *)elementheader); + dwElementSize = + quad2uint((unsigned char *)elementheader + 4); + printf("address = 0x%08x, ", dwElementAddress); + printf("size = %i\n", dwElementSize); + + if (!bFirstAddressSaved) { + bFirstAddressSaved = 1; + dfuse_address = dwElementAddress; + } + /* sanity check */ + if ((int)dwElementSize > rem) + errx(EX_SOFTWARE, "File too small for element size"); + + if (bAlternateSetting == dif->altsetting) { + ret = dfuse_dnload_element(dif, dwElementAddress, + dwElementSize, data, xfer_size); + } else { + ret = 0; + } + + /* advance read pointer */ + dfuse_memcpy(NULL, &data, &rem, dwElementSize); + + if (ret != 0) + return ret; + } + } + + if (rem != 0) + warnx("%d bytes leftover", rem); + + printf("done parsing DfuSe file\n"); + + return 0; +} + +int dfuse_do_dnload(struct dfu_if *dif, int xfer_size, struct dfu_file *file, + const char *dfuse_options) +{ + int ret; + + if (dfuse_options) + dfuse_parse_options(dfuse_options); + mem_layout = parse_memory_layout((char *)dif->alt_name); + if (!mem_layout) { + errx(EX_IOERR, "Failed to parse memory layout"); + } + if (dfuse_unprotect) { + if (!dfuse_force) { + errx(EX_IOERR, "The read unprotect command " + "will erase the flash memory" + "and can only be used with force\n"); + } + dfuse_special_command(dif, 0, READ_UNPROTECT); + printf("Device disconnects, erases flash and resets now\n"); + exit(0); + } + if (dfuse_mass_erase) { + if (!dfuse_force) { + errx(EX_IOERR, "The mass erase command " + "can only be used with force"); + } + printf("Performing mass erase, this can take a moment\n"); + dfuse_special_command(dif, 0, MASS_ERASE); + } + if (dfuse_address) { + if (file->bcdDFU == 0x11a) { + errx(EX_IOERR, "This is a DfuSe file, not " + "meant for raw download"); + } + ret = dfuse_do_bin_dnload(dif, xfer_size, file, dfuse_address); + } else { + if (file->bcdDFU != 0x11a) { + warnx("Only DfuSe file version 1.1a is supported"); + errx(EX_IOERR, "(for raw binary download, use the " + "--dfuse-address option)"); + } + ret = dfuse_do_dfuse_dnload(dif, xfer_size, file); + } + free_segment_list(mem_layout); + + dfu_abort_to_idle(dif); + + if (dfuse_leave) { + dfuse_special_command(dif, dfuse_address, SET_ADDRESS); + dfuse_dnload_chunk(dif, NULL, 0, 2); /* Zero-size */ + } + return ret; +} diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfuse.h b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfuse.h new file mode 100644 index 0000000..ed1108c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfuse.h @@ -0,0 +1,35 @@ +/* This implements the ST Microsystems DFU extensions (DfuSe) + * as per the DfuSe 1.1a specification (Document UM0391) + * + * (C) 2010-2012 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DFUSE_H +#define DFUSE_H + +#include "dfu.h" + +enum dfuse_command { SET_ADDRESS, ERASE_PAGE, MASS_ERASE, READ_UNPROTECT }; + +int dfuse_special_command(struct dfu_if *dif, unsigned int address, + enum dfuse_command command); +int dfuse_do_upload(struct dfu_if *dif, int xfer_size, int fd, + const char *dfuse_options); +int dfuse_do_dnload(struct dfu_if *dif, int xfer_size, struct dfu_file *file, + const char *dfuse_options); + +#endif /* DFUSE_H */ diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfuse_mem.c b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfuse_mem.c new file mode 100644 index 0000000..a91aacf --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfuse_mem.c @@ -0,0 +1,198 @@ +/* + * Helper functions for reading the memory map of a device + * following the ST DfuSe 1.1a specification. + * + * Copyright 2011-2014 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "portable.h" +#include "dfu_file.h" +#include "dfuse_mem.h" + +int add_segment(struct memsegment **segment_list, struct memsegment segment) +{ + struct memsegment *new_element; + + new_element = dfu_malloc(sizeof(struct memsegment)); + *new_element = segment; + new_element->next = NULL; + + if (*segment_list == NULL) + /* list can be empty on first call */ + *segment_list = new_element; + else { + struct memsegment *next_element; + + /* find last element in list */ + next_element = *segment_list; + while (next_element->next != NULL) + next_element = next_element->next; + next_element->next = new_element; + } + return 0; +} + +struct memsegment *find_segment(struct memsegment *segment_list, + unsigned int address) +{ + while (segment_list != NULL) { + if (segment_list->start <= address && + segment_list->end >= address) + return segment_list; + segment_list = segment_list->next; + } + return NULL; +} + +void free_segment_list(struct memsegment *segment_list) +{ + struct memsegment *next_element; + + while (segment_list->next != NULL) { + next_element = segment_list->next; + free(segment_list); + segment_list = next_element; + } + free(segment_list); +} + +/* Parse memory map from interface descriptor string + * encoded as per ST document UM0424 section 4.3.2. + */ +struct memsegment *parse_memory_layout(char *intf_desc) +{ + + char multiplier, memtype; + unsigned int address; + int sectors, size; + char *name, *typestring; + int ret; + int count = 0; + char separator; + int scanned; + struct memsegment *segment_list = NULL; + struct memsegment segment; + + name = dfu_malloc(strlen(intf_desc)); + + ret = sscanf(intf_desc, "@%[^/]%n", name, &scanned); + if (ret < 1) { + free(name); + warnx("Could not read name, sscanf returned %d", ret); + return NULL; + } + printf("DfuSe interface name: \"%s\"\n", name); + + intf_desc += scanned; + typestring = dfu_malloc(strlen(intf_desc)); + + while (ret = sscanf(intf_desc, "/0x%x/%n", &address, &scanned), + ret > 0) { + + intf_desc += scanned; + while (ret = sscanf(intf_desc, "%d*%d%c%[^,/]%n", + §ors, &size, &multiplier, typestring, + &scanned), ret > 2) { + intf_desc += scanned; + + count++; + memtype = 0; + if (ret == 4) { + if (strlen(typestring) == 1 + && typestring[0] != '/') + memtype = typestring[0]; + else { + warnx("Parsing type identifier '%s' " + "failed for segment %i", + typestring, count); + continue; + } + } + + /* Quirk for STM32F4 devices */ + if (strcmp(name, "Device Feature") == 0) + memtype = 'e'; + + switch (multiplier) { + case 'B': + break; + case 'K': + size *= 1024; + break; + case 'M': + size *= 1024 * 1024; + break; + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + if (!memtype) { + warnx("Non-valid multiplier '%c', " + "interpreted as type " + "identifier instead", + multiplier); + memtype = multiplier; + break; + } + /* fallthrough if memtype was already set */ + default: + warnx("Non-valid multiplier '%c', " + "assuming bytes", multiplier); + } + + if (!memtype) { + warnx("No valid type for segment %d\n", count); + continue; + } + + segment.start = address; + segment.end = address + sectors * size - 1; + segment.pagesize = size; + segment.memtype = memtype & 7; + add_segment(&segment_list, segment); + + if (verbose) + printf("Memory segment at 0x%08x %3d x %4d = " + "%5d (%s%s%s)\n", + address, sectors, size, sectors * size, + memtype & DFUSE_READABLE ? "r" : "", + memtype & DFUSE_ERASABLE ? "e" : "", + memtype & DFUSE_WRITEABLE ? "w" : ""); + + address += sectors * size; + + separator = *intf_desc; + if (separator == ',') + intf_desc += 1; + else + break; + } /* while per segment */ + + } /* while per address */ + free(name); + free(typestring); + + return segment_list; +} diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfuse_mem.h b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfuse_mem.h new file mode 100644 index 0000000..0181f0c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/dfuse_mem.h @@ -0,0 +1,44 @@ +/* Helper functions for reading the memory map in a device + * following the ST DfuSe 1.1a specification. + * + * (C) 2011 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DFUSE_MEM_H +#define DFUSE_MEM_H + +#define DFUSE_READABLE 1 +#define DFUSE_ERASABLE 2 +#define DFUSE_WRITEABLE 4 + +struct memsegment { + unsigned int start; + unsigned int end; + int pagesize; + int memtype; + struct memsegment *next; +}; + +int add_segment(struct memsegment **list, struct memsegment new_element); + +struct memsegment *find_segment(struct memsegment *list, unsigned int address); + +void free_segment_list(struct memsegment *list); + +struct memsegment *parse_memory_layout(char *intf_desc_str); + +#endif /* DFUSE_MEM_H */ diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/main.c b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/main.c new file mode 100644 index 0000000..acaed2f --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/main.c @@ -0,0 +1,699 @@ +/* + * dfu-util + * + * Copyright 2007-2008 by OpenMoko, Inc. + * Copyright 2013-2014 Hans Petter Selasky + * + * Written by Harald Welte + * + * Based on existing code of dfu-programmer-0.4 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "portable.h" +#include "dfu.h" +#include "usb_dfu.h" +#include "dfu_file.h" +#include "dfu_load.h" +#include "dfu_util.h" +#include "dfuse.h" +#include "quirks.h" + +#ifdef HAVE_USBPATH_H +#include +#endif + +int verbose = 0; + +struct dfu_if *dfu_root = NULL; + +int match_bus = -1; +int match_device = -1; +int match_vendor = -1; +int match_product = -1; +int match_vendor_dfu = -1; +int match_product_dfu = -1; +int match_config_index = -1; +int match_iface_index = -1; +int match_iface_alt_index = -1; +const char *match_iface_alt_name = NULL; +const char *match_serial = NULL; +const char *match_serial_dfu = NULL; + +static int parse_match_value(const char *str, int default_value) +{ + char *remainder; + int value; + + if (str == NULL) { + value = default_value; + } else if (*str == '*') { + value = -1; /* Match anything */ + } else if (*str == '-') { + value = 0x10000; /* Impossible vendor/product ID */ + } else { + value = strtoul(str, &remainder, 16); + if (remainder == str) { + value = default_value; + } + } + return value; +} + +static void parse_vendprod(const char *str) +{ + const char *comma; + const char *colon; + + /* Default to match any DFU device in runtime or DFU mode */ + match_vendor = -1; + match_product = -1; + match_vendor_dfu = -1; + match_product_dfu = -1; + + comma = strchr(str, ','); + if (comma == str) { + /* DFU mode vendor/product being specified without any runtime + * vendor/product specification, so don't match any runtime device */ + match_vendor = match_product = 0x10000; + } else { + colon = strchr(str, ':'); + if (colon != NULL) { + ++colon; + if ((comma != NULL) && (colon > comma)) { + colon = NULL; + } + } + match_vendor = parse_match_value(str, match_vendor); + match_product = parse_match_value(colon, match_product); + if (comma != NULL) { + /* Both runtime and DFU mode vendor/product specifications are + * available, so default DFU mode match components to the given + * runtime match components */ + match_vendor_dfu = match_vendor; + match_product_dfu = match_product; + } + } + if (comma != NULL) { + ++comma; + colon = strchr(comma, ':'); + if (colon != NULL) { + ++colon; + } + match_vendor_dfu = parse_match_value(comma, match_vendor_dfu); + match_product_dfu = parse_match_value(colon, match_product_dfu); + } +} + +static void parse_serial(char *str) +{ + char *comma; + + match_serial = str; + comma = strchr(str, ','); + if (comma == NULL) { + match_serial_dfu = match_serial; + } else { + *comma++ = 0; + match_serial_dfu = comma; + } + if (*match_serial == 0) match_serial = NULL; + if (*match_serial_dfu == 0) match_serial_dfu = NULL; +} + +#ifdef HAVE_USBPATH_H + +static int resolve_device_path(char *path) +{ + int res; + + res = usb_path2devnum(path); + if (res < 0) + return -EINVAL; + if (!res) + return 0; + + match_bus = atoi(path); + match_device = res; + + return 0; +} + +#else /* HAVE_USBPATH_H */ + +static int resolve_device_path(char *path) +{ + (void)path; /* Eliminate unused variable warning */ + errx(EX_SOFTWARE, "USB device paths are not supported by this dfu-util.\n"); +} + +#endif /* !HAVE_USBPATH_H */ + +static void help(void) +{ + fprintf(stderr, "Usage: dfu-util [options] ...\n" + " -h --help\t\t\tPrint this help message\n" + " -V --version\t\t\tPrint the version number\n" + " -v --verbose\t\t\tPrint verbose debug statements\n" + " -l --list\t\t\tList currently attached DFU capable devices\n"); + fprintf(stderr, " -e --detach\t\t\tDetach currently attached DFU capable devices\n" + " -E --detach-delay seconds\tTime to wait before reopening a device after detach\n" + " -d --device :[,:]\n" + "\t\t\t\tSpecify Vendor/Product ID(s) of DFU device\n" + " -p --path \tSpecify path to DFU device\n" + " -c --cfg \t\tSpecify the Configuration of DFU device\n" + " -i --intf \t\tSpecify the DFU Interface number\n" + " -S --serial [,]\n" + "\t\t\t\tSpecify Serial String of DFU device\n" + " -a --alt \t\tSpecify the Altsetting of the DFU Interface\n" + "\t\t\t\tby name or by number\n"); + fprintf(stderr, " -t --transfer-size \tSpecify the number of bytes per USB Transfer\n" + " -U --upload \t\tRead firmware from device into \n" + " -Z --upload-size \tSpecify the expected upload size in bytes\n" + " -D --download \t\tWrite firmware from into device\n" + " -R --reset\t\t\tIssue USB Reset signalling once we're finished\n" + " -s --dfuse-address

\tST DfuSe mode, specify target address for\n" + "\t\t\t\traw file download or upload. Not applicable for\n" + "\t\t\t\tDfuSe file (.dfu) downloads\n" + ); + exit(EX_USAGE); +} + +static void print_version(void) +{ + printf(PACKAGE_STRING "\n\n"); + printf("Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.\n" + "Copyright 2010-2014 Tormod Volden and Stefan Schmidt\n" + "This program is Free Software and has ABSOLUTELY NO WARRANTY\n" + "Please report bugs to " PACKAGE_BUGREPORT "\n\n"); +} + +static struct option opts[] = { + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'V' }, + { "verbose", 0, 0, 'v' }, + { "list", 0, 0, 'l' }, + { "detach", 0, 0, 'e' }, + { "detach-delay", 1, 0, 'E' }, + { "device", 1, 0, 'd' }, + { "path", 1, 0, 'p' }, + { "configuration", 1, 0, 'c' }, + { "cfg", 1, 0, 'c' }, + { "interface", 1, 0, 'i' }, + { "intf", 1, 0, 'i' }, + { "altsetting", 1, 0, 'a' }, + { "alt", 1, 0, 'a' }, + { "serial", 1, 0, 'S' }, + { "transfer-size", 1, 0, 't' }, + { "upload", 1, 0, 'U' }, + { "upload-size", 1, 0, 'Z' }, + { "download", 1, 0, 'D' }, + { "reset", 0, 0, 'R' }, + { "dfuse-address", 1, 0, 's' }, + { 0, 0, 0, 0 } +}; + +int main(int argc, char **argv) +{ + int expected_size = 0; + unsigned int transfer_size = 0; + enum mode mode = MODE_NONE; + struct dfu_status status; + libusb_context *ctx; + struct dfu_file file; + char *end; + int final_reset = 0; + int ret; + int dfuse_device = 0; + int fd; + const char *dfuse_options = NULL; + int detach_delay = 5; + uint16_t runtime_vendor; + uint16_t runtime_product; + + memset(&file, 0, sizeof(file)); + + /* make sure all prints are flushed */ + setvbuf(stdout, NULL, _IONBF, 0); + + while (1) { + int c, option_index = 0; + c = getopt_long(argc, argv, "hVvleE:d:p:c:i:a:S:t:U:D:Rs:Z:", opts, + &option_index); + if (c == -1) + break; + + switch (c) { + case 'h': + help(); + break; + case 'V': + mode = MODE_VERSION; + break; + case 'v': + verbose++; + break; + case 'l': + mode = MODE_LIST; + break; + case 'e': + mode = MODE_DETACH; + match_iface_alt_index = 0; + match_iface_index = 0; + break; + case 'E': + detach_delay = atoi(optarg); + break; + case 'd': + parse_vendprod(optarg); + break; + case 'p': + /* Parse device path */ + ret = resolve_device_path(optarg); + if (ret < 0) + errx(EX_SOFTWARE, "Unable to parse '%s'", optarg); + if (!ret) + errx(EX_SOFTWARE, "Cannot find '%s'", optarg); + break; + case 'c': + /* Configuration */ + match_config_index = atoi(optarg); + break; + case 'i': + /* Interface */ + match_iface_index = atoi(optarg); + break; + case 'a': + /* Interface Alternate Setting */ + match_iface_alt_index = strtoul(optarg, &end, 0); + if (*end) { + match_iface_alt_name = optarg; + match_iface_alt_index = -1; + } + break; + case 'S': + parse_serial(optarg); + break; + case 't': + transfer_size = atoi(optarg); + break; + case 'U': + mode = MODE_UPLOAD; + file.name = optarg; + break; + case 'Z': + expected_size = atoi(optarg); + break; + case 'D': + mode = MODE_DOWNLOAD; + file.name = optarg; + break; + case 'R': + final_reset = 1; + break; + case 's': + dfuse_options = optarg; + break; + default: + help(); + break; + } + } + + print_version(); + if (mode == MODE_VERSION) { + exit(0); + } + + if (mode == MODE_NONE) { + fprintf(stderr, "You need to specify one of -D or -U\n"); + help(); + } + + if (match_config_index == 0) { + /* Handle "-c 0" (unconfigured device) as don't care */ + match_config_index = -1; + } + + if (mode == MODE_DOWNLOAD) { + dfu_load_file(&file, MAYBE_SUFFIX, MAYBE_PREFIX); + /* If the user didn't specify product and/or vendor IDs to match, + * use any IDs from the file suffix for device matching */ + if (match_vendor < 0 && file.idVendor != 0xffff) { + match_vendor = file.idVendor; + printf("Match vendor ID from file: %04x\n", match_vendor); + } + if (match_product < 0 && file.idProduct != 0xffff) { + match_product = file.idProduct; + printf("Match product ID from file: %04x\n", match_product); + } + } + + ret = libusb_init(&ctx); + if (ret) + errx(EX_IOERR, "unable to initialize libusb: %i", ret); + + if (verbose > 2) { + libusb_set_debug(ctx, 255); + } + + probe_devices(ctx); + + if (mode == MODE_LIST) { + list_dfu_interfaces(); + exit(0); + } + + if (dfu_root == NULL) { + errx(EX_IOERR, "No DFU capable USB device available"); + } else if (dfu_root->next != NULL) { + /* We cannot safely support more than one DFU capable device + * with same vendor/product ID, since during DFU we need to do + * a USB bus reset, after which the target device will get a + * new address */ + errx(EX_IOERR, "More than one DFU capable USB device found! " + "Try `--list' and specify the serial number " + "or disconnect all but one device\n"); + } + + /* We have exactly one device. Its libusb_device is now in dfu_root->dev */ + + printf("Opening DFU capable USB device...\n"); + ret = libusb_open(dfu_root->dev, &dfu_root->dev_handle); + if (ret || !dfu_root->dev_handle) + errx(EX_IOERR, "Cannot open device"); + + printf("ID %04x:%04x\n", dfu_root->vendor, dfu_root->product); + + printf("Run-time device DFU version %04x\n", + libusb_le16_to_cpu(dfu_root->func_dfu.bcdDFUVersion)); + + /* Transition from run-Time mode to DFU mode */ + if (!(dfu_root->flags & DFU_IFF_DFU)) { + int err; + /* In the 'first round' during runtime mode, there can only be one + * DFU Interface descriptor according to the DFU Spec. */ + + /* FIXME: check if the selected device really has only one */ + + runtime_vendor = dfu_root->vendor; + runtime_product = dfu_root->product; + + printf("Claiming USB DFU Runtime Interface...\n"); + if (libusb_claim_interface(dfu_root->dev_handle, dfu_root->interface) < 0) { + errx(EX_IOERR, "Cannot claim interface %d", + dfu_root->interface); + } + + if (libusb_set_interface_alt_setting(dfu_root->dev_handle, dfu_root->interface, 0) < 0) { + errx(EX_IOERR, "Cannot set alt interface zero"); + } + + printf("Determining device status: "); + + err = dfu_get_status(dfu_root, &status); + if (err == LIBUSB_ERROR_PIPE) { + printf("Device does not implement get_status, assuming appIDLE\n"); + status.bStatus = DFU_STATUS_OK; + status.bwPollTimeout = 0; + status.bState = DFU_STATE_appIDLE; + status.iString = 0; + } else if (err < 0) { + errx(EX_IOERR, "error get_status"); + } else { + printf("state = %s, status = %d\n", + dfu_state_to_string(status.bState), status.bStatus); + } + milli_sleep(status.bwPollTimeout); + + switch (status.bState) { + case DFU_STATE_appIDLE: + case DFU_STATE_appDETACH: + printf("Device really in Runtime Mode, send DFU " + "detach request...\n"); + if (dfu_detach(dfu_root->dev_handle, + dfu_root->interface, 1000) < 0) { + warnx("error detaching"); + } + if (dfu_root->func_dfu.bmAttributes & USB_DFU_WILL_DETACH) { + printf("Device will detach and reattach...\n"); + } else { + printf("Resetting USB...\n"); + ret = libusb_reset_device(dfu_root->dev_handle); + if (ret < 0 && ret != LIBUSB_ERROR_NOT_FOUND) + errx(EX_IOERR, "error resetting " + "after detach"); + } + break; + case DFU_STATE_dfuERROR: + printf("dfuERROR, clearing status\n"); + if (dfu_clear_status(dfu_root->dev_handle, + dfu_root->interface) < 0) { + errx(EX_IOERR, "error clear_status"); + } + /* fall through */ + default: + warnx("WARNING: Runtime device already in DFU state ?!?"); + libusb_release_interface(dfu_root->dev_handle, + dfu_root->interface); + goto dfustate; + } + libusb_release_interface(dfu_root->dev_handle, + dfu_root->interface); + libusb_close(dfu_root->dev_handle); + dfu_root->dev_handle = NULL; + + if (mode == MODE_DETACH) { + libusb_exit(ctx); + exit(0); + } + + /* keeping handles open might prevent re-enumeration */ + disconnect_devices(); + + milli_sleep(detach_delay * 1000); + + /* Change match vendor and product to impossible values to force + * only DFU mode matches in the following probe */ + match_vendor = match_product = 0x10000; + + probe_devices(ctx); + + if (dfu_root == NULL) { + errx(EX_IOERR, "Lost device after RESET?"); + } else if (dfu_root->next != NULL) { + errx(EX_IOERR, "More than one DFU capable USB device found! " + "Try `--list' and specify the serial number " + "or disconnect all but one device"); + } + + /* Check for DFU mode device */ + if (!(dfu_root->flags | DFU_IFF_DFU)) + errx(EX_SOFTWARE, "Device is not in DFU mode"); + + printf("Opening DFU USB Device...\n"); + ret = libusb_open(dfu_root->dev, &dfu_root->dev_handle); + if (ret || !dfu_root->dev_handle) { + errx(EX_IOERR, "Cannot open device"); + } + } else { + /* we're already in DFU mode, so we can skip the detach/reset + * procedure */ + /* If a match vendor/product was specified, use that as the runtime + * vendor/product, otherwise use the DFU mode vendor/product */ + runtime_vendor = match_vendor < 0 ? dfu_root->vendor : match_vendor; + runtime_product = match_product < 0 ? dfu_root->product : match_product; + } + +dfustate: +#if 0 + printf("Setting Configuration %u...\n", dfu_root->configuration); + if (libusb_set_configuration(dfu_root->dev_handle, dfu_root->configuration) < 0) { + errx(EX_IOERR, "Cannot set configuration"); + } +#endif + printf("Claiming USB DFU Interface...\n"); + if (libusb_claim_interface(dfu_root->dev_handle, dfu_root->interface) < 0) { + errx(EX_IOERR, "Cannot claim interface"); + } + + printf("Setting Alternate Setting #%d ...\n", dfu_root->altsetting); + if (libusb_set_interface_alt_setting(dfu_root->dev_handle, dfu_root->interface, dfu_root->altsetting) < 0) { + errx(EX_IOERR, "Cannot set alternate interface"); + } + +status_again: + printf("Determining device status: "); + if (dfu_get_status(dfu_root, &status ) < 0) { + errx(EX_IOERR, "error get_status"); + } + printf("state = %s, status = %d\n", + dfu_state_to_string(status.bState), status.bStatus); + + milli_sleep(status.bwPollTimeout); + + switch (status.bState) { + case DFU_STATE_appIDLE: + case DFU_STATE_appDETACH: + errx(EX_IOERR, "Device still in Runtime Mode!"); + break; + case DFU_STATE_dfuERROR: + printf("dfuERROR, clearing status\n"); + if (dfu_clear_status(dfu_root->dev_handle, dfu_root->interface) < 0) { + errx(EX_IOERR, "error clear_status"); + } + goto status_again; + break; + case DFU_STATE_dfuDNLOAD_IDLE: + case DFU_STATE_dfuUPLOAD_IDLE: + printf("aborting previous incomplete transfer\n"); + if (dfu_abort(dfu_root->dev_handle, dfu_root->interface) < 0) { + errx(EX_IOERR, "can't send DFU_ABORT"); + } + goto status_again; + break; + case DFU_STATE_dfuIDLE: + printf("dfuIDLE, continuing\n"); + break; + default: + break; + } + + if (DFU_STATUS_OK != status.bStatus ) { + printf("WARNING: DFU Status: '%s'\n", + dfu_status_to_string(status.bStatus)); + /* Clear our status & try again. */ + if (dfu_clear_status(dfu_root->dev_handle, dfu_root->interface) < 0) + errx(EX_IOERR, "USB communication error"); + if (dfu_get_status(dfu_root, &status) < 0) + errx(EX_IOERR, "USB communication error"); + if (DFU_STATUS_OK != status.bStatus) + errx(EX_SOFTWARE, "Status is not OK: %d", status.bStatus); + + milli_sleep(status.bwPollTimeout); + } + + printf("DFU mode device DFU version %04x\n", + libusb_le16_to_cpu(dfu_root->func_dfu.bcdDFUVersion)); + + if (dfu_root->func_dfu.bcdDFUVersion == libusb_cpu_to_le16(0x11a)) + dfuse_device = 1; + + /* If not overridden by the user */ + if (!transfer_size) { + transfer_size = libusb_le16_to_cpu( + dfu_root->func_dfu.wTransferSize); + if (transfer_size) { + printf("Device returned transfer size %i\n", + transfer_size); + } else { + errx(EX_IOERR, "Transfer size must be specified"); + } + } + +#ifdef HAVE_GETPAGESIZE +/* autotools lie when cross-compiling for Windows using mingw32/64 */ +#ifndef __MINGW32__ + /* limitation of Linux usbdevio */ + if ((int)transfer_size > getpagesize()) { + transfer_size = getpagesize(); + printf("Limited transfer size to %i\n", transfer_size); + } +#endif /* __MINGW32__ */ +#endif /* HAVE_GETPAGESIZE */ + + if (transfer_size < dfu_root->bMaxPacketSize0) { + transfer_size = dfu_root->bMaxPacketSize0; + printf("Adjusted transfer size to %i\n", transfer_size); + } + + switch (mode) { + case MODE_UPLOAD: + /* open for "exclusive" writing */ + fd = open(file.name, O_WRONLY | O_BINARY | O_CREAT | O_EXCL | O_TRUNC, 0666); + if (fd < 0) + err(EX_IOERR, "Cannot open file %s for writing", file.name); + + if (dfuse_device || dfuse_options) { + if (dfuse_do_upload(dfu_root, transfer_size, fd, + dfuse_options) < 0) + exit(1); + } else { + if (dfuload_do_upload(dfu_root, transfer_size, + expected_size, fd) < 0) { + exit(1); + } + } + close(fd); + break; + + case MODE_DOWNLOAD: + if (((file.idVendor != 0xffff && file.idVendor != runtime_vendor) || + (file.idProduct != 0xffff && file.idProduct != runtime_product)) && + ((file.idVendor != 0xffff && file.idVendor != dfu_root->vendor) || + (file.idProduct != 0xffff && file.idProduct != dfu_root->product))) { + errx(EX_IOERR, "Error: File ID %04x:%04x does " + "not match device (%04x:%04x or %04x:%04x)", + file.idVendor, file.idProduct, + runtime_vendor, runtime_product, + dfu_root->vendor, dfu_root->product); + } + if (dfuse_device || dfuse_options || file.bcdDFU == 0x11a) { + if (dfuse_do_dnload(dfu_root, transfer_size, &file, + dfuse_options) < 0) + exit(1); + } else { + if (dfuload_do_dnload(dfu_root, transfer_size, &file) < 0) + exit(1); + } + break; + case MODE_DETACH: + if (dfu_detach(dfu_root->dev_handle, dfu_root->interface, 1000) < 0) { + warnx("can't detach"); + } + break; + default: + errx(EX_IOERR, "Unsupported mode: %u", mode); + break; + } + + if (final_reset) { + if (dfu_detach(dfu_root->dev_handle, dfu_root->interface, 1000) < 0) { + /* Even if detach failed, just carry on to leave the + device in a known state */ + warnx("can't detach"); + } + printf("Resetting USB to switch back to runtime mode\n"); + ret = libusb_reset_device(dfu_root->dev_handle); + if (ret < 0 && ret != LIBUSB_ERROR_NOT_FOUND) { + errx(EX_IOERR, "error resetting after download"); + } + } + + libusb_close(dfu_root->dev_handle); + dfu_root->dev_handle = NULL; + libusb_exit(ctx); + + return (0); +} diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/portable.h b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/portable.h new file mode 100644 index 0000000..cf8d5df --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/portable.h @@ -0,0 +1,72 @@ + +#ifndef PORTABLE_H +#define PORTABLE_H + +#ifdef HAVE_CONFIG_H +# include "config.h" +#else +# define PACKAGE "dfu-util" +# define PACKAGE_VERSION "0.8-msvc" +# define PACKAGE_STRING "dfu-util 0.8-msvc" +# define PACKAGE_BUGREPORT "dfu-util@lists.gnumonks.org" +#endif /* HAVE_CONFIG_H */ + +#ifdef HAVE_FTRUNCATE +# include +#else +# include +#endif /* HAVE_FTRUNCATE */ + +#ifdef HAVE_NANOSLEEP +# include +# define milli_sleep(msec) do {\ + if (msec) {\ + struct timespec nanosleepDelay = { (msec) / 1000, ((msec) % 1000) * 1000000 };\ + nanosleep(&nanosleepDelay, NULL);\ + } } while (0) +#elif defined HAVE_WINDOWS_H +# define milli_sleep(msec) do {\ + if (msec) {\ + Sleep(msec);\ + } } while (0) +#else +# error "Can't get no sleep! Please report" +#endif /* HAVE_NANOSLEEP */ + +#ifdef HAVE_ERR +# include +#else +# include +# include +# define warnx(...) do {\ + fprintf(stderr, __VA_ARGS__);\ + fprintf(stderr, "\n"); } while (0) +# define errx(eval, ...) do {\ + warnx(__VA_ARGS__);\ + exit(eval); } while (0) +# define warn(...) do {\ + fprintf(stderr, "%s: ", strerror(errno));\ + warnx(__VA_ARGS__); } while (0) +# define err(eval, ...) do {\ + warn(__VA_ARGS__);\ + exit(eval); } while (0) +#endif /* HAVE_ERR */ + +#ifdef HAVE_SYSEXITS_H +# include +#else +# define EX_OK 0 /* successful termination */ +# define EX_USAGE 64 /* command line usage error */ +# define EX_SOFTWARE 70 /* internal software error */ +# define EX_IOERR 74 /* input/output error */ +#endif /* HAVE_SYSEXITS_H */ + +#ifndef O_BINARY +# define O_BINARY 0 +#endif + +#ifndef off_t +# define off_t long int +#endif + +#endif /* PORTABLE_H */ diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/prefix.c b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/prefix.c new file mode 100644 index 0000000..be8e3fa --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/prefix.c @@ -0,0 +1,176 @@ +/* + * dfu-prefix + * + * Copyright 2011-2012 Stefan Schmidt + * Copyright 2013 Hans Petter Selasky + * Copyright 2014 Uwe Bonnes + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include "portable.h" +#include "dfu_file.h" + +enum mode { + MODE_NONE, + MODE_ADD, + MODE_DEL, + MODE_CHECK +}; + +int verbose; + +static void help(void) +{ + fprintf(stderr, "Usage: dfu-prefix [options] ...\n" + " -h --help\t\t\tPrint this help message\n" + " -V --version\t\t\tPrint the version number\n" + " -c --check \t\tCheck DFU prefix of \n" + " -D --delete \t\tDelete DFU prefix from \n" + " -a --add \t\tAdd DFU prefix to \n" + "In combination with -a:\n" + ); + fprintf(stderr, " -s --stellaris-address
Add TI Stellaris address prefix to \n" + "In combination with -D or -c:\n" + " -T --stellaris\t\tAct on TI Stellaris address prefix of \n" + "In combination with -a or -D or -c:\n" + " -L --lpc-prefix\t\tUse NXP LPC DFU prefix format\n" + ); + exit(EX_USAGE); +} + +static void print_version(void) +{ + printf("dfu-prefix (%s) %s\n\n", PACKAGE, PACKAGE_VERSION); + printf("Copyright 2011-2012 Stefan Schmidt, 2014 Uwe Bonnes\n" + "This program is Free Software and has ABSOLUTELY NO WARRANTY\n" + "Please report bugs to %s\n\n", PACKAGE_BUGREPORT); + +} + +static struct option opts[] = { + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'V' }, + { "check", 1, 0, 'c' }, + { "add", 1, 0, 'a' }, + { "delete", 1, 0, 'D' }, + { "stellaris-address", 1, 0, 's' }, + { "stellaris", 0, 0, 'T' }, + { "LPC", 0, 0, 'L' }, +}; +int main(int argc, char **argv) +{ + struct dfu_file file; + enum mode mode = MODE_NONE; + enum prefix_type type = ZERO_PREFIX; + uint32_t lmdfu_flash_address = 0; + char *end; + + /* make sure all prints are flushed */ + setvbuf(stdout, NULL, _IONBF, 0); + + print_version(); + + memset(&file, 0, sizeof(file)); + + while (1) { + int c, option_index = 0; + c = getopt_long(argc, argv, "hVc:a:D:p:v:d:s:TL", opts, + &option_index); + if (c == -1) + break; + + switch (c) { + case 'h': + help(); + break; + case 'V': + exit(0); + break; + case 'D': + file.name = optarg; + mode = MODE_DEL; + break; + case 'c': + file.name = optarg; + mode = MODE_CHECK; + break; + case 'a': + file.name = optarg; + mode = MODE_ADD; + break; + case 's': + lmdfu_flash_address = strtoul(optarg, &end, 0); + if (*end) { + errx(EX_IOERR, "Invalid lmdfu " + "address: %s", optarg); + } + /* fall-through */ + case 'T': + type = LMDFU_PREFIX; + break; + case 'L': + type = LPCDFU_UNENCRYPTED_PREFIX; + break; + default: + help(); + break; + } + } + + if (!file.name) { + fprintf(stderr, "You need to specify a filename\n"); + help(); + } + + switch(mode) { + case MODE_ADD: + if (type == ZERO_PREFIX) + errx(EX_IOERR, "Prefix type must be specified"); + dfu_load_file(&file, MAYBE_SUFFIX, NO_PREFIX); + file.lmdfu_address = lmdfu_flash_address; + file.prefix_type = type; + printf("Adding prefix to file\n"); + dfu_store_file(&file, file.size.suffix != 0, 1); + break; + + case MODE_CHECK: + dfu_load_file(&file, MAYBE_SUFFIX, MAYBE_PREFIX); + show_suffix_and_prefix(&file); + if (type > ZERO_PREFIX && file.prefix_type != type) + errx(EX_IOERR, "No prefix of requested type"); + break; + + case MODE_DEL: + dfu_load_file(&file, MAYBE_SUFFIX, NEEDS_PREFIX); + if (type > ZERO_PREFIX && file.prefix_type != type) + errx(EX_IOERR, "No prefix of requested type"); + printf("Removing prefix from file\n"); + /* if there was a suffix, rewrite it */ + dfu_store_file(&file, file.size.suffix != 0, 0); + break; + + default: + help(); + break; + } + return (0); +} diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/quirks.c b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/quirks.c new file mode 100644 index 0000000..de394a6 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/quirks.c @@ -0,0 +1,56 @@ +/* + * Simple quirk system for dfu-util + * + * Copyright 2010-2014 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include "quirks.h" + +uint16_t get_quirks(uint16_t vendor, uint16_t product, uint16_t bcdDevice) +{ + uint16_t quirks = 0; + + /* Device returns bogus bwPollTimeout values */ + if ((vendor == VENDOR_OPENMOKO || vendor == VENDOR_FIC) && + product >= PRODUCT_FREERUNNER_FIRST && + product <= PRODUCT_FREERUNNER_LAST) + quirks |= QUIRK_POLLTIMEOUT; + + if (vendor == VENDOR_VOTI && + product == PRODUCT_OPENPCD) + quirks |= QUIRK_POLLTIMEOUT; + + /* Reports wrong DFU version in DFU descriptor */ + if (vendor == VENDOR_LEAFLABS && + product == PRODUCT_MAPLE3 && + bcdDevice == 0x0200) + quirks |= QUIRK_FORCE_DFU11; + + /* old devices(bcdDevice == 0) return bogus bwPollTimeout values */ + if (vendor == VENDOR_SIEMENS && + (product == PRODUCT_PXM40 || product == PRODUCT_PXM50) && + bcdDevice == 0) + quirks |= QUIRK_POLLTIMEOUT; + + /* M-Audio Transit returns bogus bwPollTimeout values */ + if (vendor == VENDOR_MIDIMAN && + product == PRODUCT_TRANSIT) + quirks |= QUIRK_POLLTIMEOUT; + + return (quirks); +} diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/quirks.h b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/quirks.h new file mode 100644 index 0000000..0e4b3ec --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/quirks.h @@ -0,0 +1,27 @@ +#ifndef DFU_QUIRKS_H +#define DFU_QUIRKS_H + +#define VENDOR_OPENMOKO 0x1d50 /* Openmoko Freerunner / GTA02 */ +#define VENDOR_FIC 0x1457 /* Openmoko Freerunner / GTA02 */ +#define VENDOR_VOTI 0x16c0 /* OpenPCD Reader */ +#define VENDOR_LEAFLABS 0x1eaf /* Maple */ +#define VENDOR_SIEMENS 0x0908 /* Siemens AG */ +#define VENDOR_MIDIMAN 0x0763 /* Midiman */ + +#define PRODUCT_FREERUNNER_FIRST 0x5117 +#define PRODUCT_FREERUNNER_LAST 0x5126 +#define PRODUCT_OPENPCD 0x076b +#define PRODUCT_MAPLE3 0x0003 /* rev 3 and 5 */ +#define PRODUCT_PXM40 0x02c4 /* Siemens AG, PXM 40 */ +#define PRODUCT_PXM50 0x02c5 /* Siemens AG, PXM 50 */ +#define PRODUCT_TRANSIT 0x2806 /* M-Audio Transit (Midiman) */ + +#define QUIRK_POLLTIMEOUT (1<<0) +#define QUIRK_FORCE_DFU11 (1<<1) + +/* Fallback value, works for OpenMoko */ +#define DEFAULT_POLLTIMEOUT 5 + +uint16_t get_quirks(uint16_t vendor, uint16_t product, uint16_t bcdDevice); + +#endif /* DFU_QUIRKS_H */ diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/suffix.c b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/suffix.c new file mode 100644 index 0000000..0df248f --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/suffix.c @@ -0,0 +1,176 @@ +/* + * dfu-suffix + * + * Copyright 2011-2012 Stefan Schmidt + * Copyright 2013 Hans Petter Selasky + * Copyright 2014 Tormod Volden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include "portable.h" +#include "dfu_file.h" + +enum mode { + MODE_NONE, + MODE_ADD, + MODE_DEL, + MODE_CHECK +}; + +int verbose; + +static void help(void) +{ + fprintf(stderr, "Usage: dfu-suffix [options] ...\n" + " -h --help\t\t\tPrint this help message\n" + " -V --version\t\t\tPrint the version number\n" + " -c --check \t\tCheck DFU suffix of \n" + " -a --add \t\tAdd DFU suffix to \n" + " -D --delete \t\tDelete DFU suffix from \n" + " -p --pid \t\tAdd product ID into DFU suffix in \n" + " -v --vid \t\tAdd vendor ID into DFU suffix in \n" + " -d --did \t\tAdd device ID into DFU suffix in \n" + " -S --spec \t\tAdd DFU specification ID into DFU suffix in \n" + ); + exit(EX_USAGE); +} + +static void print_version(void) +{ + printf("dfu-suffix (%s) %s\n\n", PACKAGE, PACKAGE_VERSION); + printf("Copyright 2011-2012 Stefan Schmidt, 2013-2014 Tormod Volden\n" + "This program is Free Software and has ABSOLUTELY NO WARRANTY\n" + "Please report bugs to %s\n\n", PACKAGE_BUGREPORT); + +} + +static struct option opts[] = { + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'V' }, + { "check", 1, 0, 'c' }, + { "add", 1, 0, 'a' }, + { "delete", 1, 0, 'D' }, + { "pid", 1, 0, 'p' }, + { "vid", 1, 0, 'v' }, + { "did", 1, 0, 'd' }, + { "spec", 1, 0, 'S' }, +}; + +int main(int argc, char **argv) +{ + struct dfu_file file; + int pid, vid, did, spec; + enum mode mode = MODE_NONE; + + /* make sure all prints are flushed */ + setvbuf(stdout, NULL, _IONBF, 0); + + print_version(); + + pid = vid = did = 0xffff; + spec = 0x0100; /* Default to bcdDFU version 1.0 */ + memset(&file, 0, sizeof(file)); + + while (1) { + int c, option_index = 0; + c = getopt_long(argc, argv, "hVc:a:D:p:v:d:S:s:T", opts, + &option_index); + if (c == -1) + break; + + switch (c) { + case 'h': + help(); + break; + case 'V': + exit(0); + break; + case 'D': + file.name = optarg; + mode = MODE_DEL; + break; + case 'p': + pid = strtol(optarg, NULL, 16); + break; + case 'v': + vid = strtol(optarg, NULL, 16); + break; + case 'd': + did = strtol(optarg, NULL, 16); + break; + case 'S': + spec = strtol(optarg, NULL, 16); + break; + case 'c': + file.name = optarg; + mode = MODE_CHECK; + break; + case 'a': + file.name = optarg; + mode = MODE_ADD; + break; + default: + help(); + break; + } + } + + if (!file.name) { + fprintf(stderr, "You need to specify a filename\n"); + help(); + } + + if (spec != 0x0100 && spec != 0x011a) { + fprintf(stderr, "Only DFU specification 0x0100 and 0x011a supported\n"); + help(); + } + + switch(mode) { + case MODE_ADD: + dfu_load_file(&file, NO_SUFFIX, MAYBE_PREFIX); + file.idVendor = vid; + file.idProduct = pid; + file.bcdDevice = did; + file.bcdDFU = spec; + /* always write suffix, rewrite prefix if there was one */ + dfu_store_file(&file, 1, file.size.prefix != 0); + printf("Suffix successfully added to file\n"); + break; + + case MODE_CHECK: + dfu_load_file(&file, NEEDS_SUFFIX, MAYBE_PREFIX); + show_suffix_and_prefix(&file); + break; + + case MODE_DEL: + dfu_load_file(&file, NEEDS_SUFFIX, MAYBE_PREFIX); + dfu_store_file(&file, 0, file.size.prefix != 0); + if (file.size.suffix) /* had a suffix */ + printf("Suffix successfully removed from file\n"); + break; + + default: + help(); + break; + } + return (0); +} diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/usb_dfu.h b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/usb_dfu.h new file mode 100644 index 0000000..660bedc --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/src/usb_dfu.h @@ -0,0 +1,99 @@ +#ifndef USB_DFU_H +#define USB_DFU_H +/* USB Device Firmware Update Implementation for OpenPCD + * (C) 2006 by Harald Welte + * + * Protocol definitions for USB DFU + * + * This ought to be compliant to the USB DFU Spec 1.0 as available from + * http://www.usb.org/developers/devclass_docs/usbdfu10.pdf + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#define USB_DT_DFU 0x21 + +#ifdef _MSC_VER +# pragma pack(push) +# pragma pack(1) +#endif /* _MSC_VER */ +struct usb_dfu_func_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bmAttributes; +#define USB_DFU_CAN_DOWNLOAD (1 << 0) +#define USB_DFU_CAN_UPLOAD (1 << 1) +#define USB_DFU_MANIFEST_TOL (1 << 2) +#define USB_DFU_WILL_DETACH (1 << 3) + uint16_t wDetachTimeOut; + uint16_t wTransferSize; + uint16_t bcdDFUVersion; +#ifdef _MSC_VER +}; +# pragma pack(pop) +#elif defined __GNUC__ +} __attribute__ ((packed)); +#else + #warning "No way to pack struct on this compiler? This will break!" +#endif /* _MSC_VER */ + +#define USB_DT_DFU_SIZE 9 + +#define USB_TYPE_DFU (LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE) + +/* DFU class-specific requests (Section 3, DFU Rev 1.1) */ +#define USB_REQ_DFU_DETACH 0x00 +#define USB_REQ_DFU_DNLOAD 0x01 +#define USB_REQ_DFU_UPLOAD 0x02 +#define USB_REQ_DFU_GETSTATUS 0x03 +#define USB_REQ_DFU_CLRSTATUS 0x04 +#define USB_REQ_DFU_GETSTATE 0x05 +#define USB_REQ_DFU_ABORT 0x06 + +/* DFU_GETSTATUS bStatus values (Section 6.1.2, DFU Rev 1.1) */ +#define DFU_STATUS_OK 0x00 +#define DFU_STATUS_errTARGET 0x01 +#define DFU_STATUS_errFILE 0x02 +#define DFU_STATUS_errWRITE 0x03 +#define DFU_STATUS_errERASE 0x04 +#define DFU_STATUS_errCHECK_ERASED 0x05 +#define DFU_STATUS_errPROG 0x06 +#define DFU_STATUS_errVERIFY 0x07 +#define DFU_STATUS_errADDRESS 0x08 +#define DFU_STATUS_errNOTDONE 0x09 +#define DFU_STATUS_errFIRMWARE 0x0a +#define DFU_STATUS_errVENDOR 0x0b +#define DFU_STATUS_errUSBR 0x0c +#define DFU_STATUS_errPOR 0x0d +#define DFU_STATUS_errUNKNOWN 0x0e +#define DFU_STATUS_errSTALLEDPKT 0x0f + +enum dfu_state { + DFU_STATE_appIDLE = 0, + DFU_STATE_appDETACH = 1, + DFU_STATE_dfuIDLE = 2, + DFU_STATE_dfuDNLOAD_SYNC = 3, + DFU_STATE_dfuDNBUSY = 4, + DFU_STATE_dfuDNLOAD_IDLE = 5, + DFU_STATE_dfuMANIFEST_SYNC = 6, + DFU_STATE_dfuMANIFEST = 7, + DFU_STATE_dfuMANIFEST_WAIT_RST = 8, + DFU_STATE_dfuUPLOAD_IDLE = 9, + DFU_STATE_dfuERROR = 10 +}; + +#endif /* USB_DFU_H */ diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/www/build.html b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/www/build.html new file mode 100644 index 0000000..f3036e4 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/www/build.html @@ -0,0 +1,147 @@ + + + + + + + Building dfu-util from source + + + + + + + + + +
+

How to build dfu-util from source

+ +

Prerequisites for building from git

+

Mac OS X

+

+First install MacPorts (and if you are on 10.6 or older, the Java Developer Package) and then run: +

+
+	sudo port install libusb-devel git-core
+
+ +

FreeBSD

+
+	sudo pkg_add -r git pkgconf
+
+ +

Ubuntu and Debian and derivatives

+
+	sudo apt-get build-dep dfu-util
+	sudo apt-get install libusb-1.0-0-dev
+
+ +

Get the source code and build it

+

+The first time you will have to clone the git repository: +

+
+	git clone git://gitorious.org/dfu-util/dfu-util.git
+	cd dfu-util
+
+

+If you later want to update to latest git version, just run this: +

+
+	make maintainer-clean
+	git pull
+
+

+To build the source: +

+
+	./autogen.sh
+	./configure  # on most systems
+	make
+
+ +

+If you are building on Mac OS X, replace the ./configure command with: +

+
+	./configure --libdir=/opt/local/lib --includedir=/opt/local/include  # on MacOSX only
+
+ +

+Your dfu-util binary will be inside the src folder. Use it from there, or install it to /usr/local/bin by running "sudo make install". +

+ +

Cross-building for Windows

+ +

+Windows binaries can be built in a MinGW +environment, on a Windows computer or cross-hosted in another OS. +To build it on a Debian or Ubuntu host, first install build dependencies: +

+
+	sudo apt-get build-dep libusb-1.0-0 dfu-util
+	sudo apt-get install mingw32
+
+ +

+The below example builds dfu-util 0.8 and libusb 1.0.19 from unpacked release +tarballs. If you instead build from git, you will have to run "./autogen.sh" +before running the "./configure" steps. +

+ +
+mkdir -p build
+cd libusb-1.0.19
+PKG_CONFIG_PATH=$PWD/../build/lib/pkgconfig ./configure \
+    --host=i586-mingw32msvc --prefix=$PWD/../build
+# WINVER workaround needed for 1.0.19 only
+make CFLAGS="-DWINVER=0x0501"
+make install
+cd ..
+
+cd dfu-util-0.8
+PKG_CONFIG_PATH=$PWD/../build/lib/pkgconfig ./configure \
+    --host=i586-mingw32msvc --prefix=$PWD/../build
+make
+make install
+cd ..
+
+The build files will now be in build/bin. +

+ +

Building on Windows using MinGW

+This assumes using release tarballs or having run ./autogen.sh on +the git sources. +
+cd libusb-1.0.19
+./configure --prefix=$HOME
+# WINVER workaround needed for 1.0.19 only
+# MKDIR_P setting should not really be needed...
+make CFLAGS="-DWINVER=0x0501" MKDIR_P="mkdir -p"
+make install
+cd ..
+
+cd dfu-util-0.8
+./configure USB_CFLAGS="-I$HOME/include/libusb-1.0" \
+            USB_LIBS="-L $HOME/lib -lusb-1.0" PKG_CONFIG=true
+make
+make install
+cd ..
+
+To link libusb statically into dfu-util.exe use instead of "make": +
+make LDFLAGS=-static
+
+The built executables (and DLL) will now be under $HOME/bin. + +

+[Back to dfu-util main page] +

+ +
+ + diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/www/dfu-util.1.html b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/www/dfu-util.1.html new file mode 100644 index 0000000..62ca40b --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/www/dfu-util.1.html @@ -0,0 +1,411 @@ + + +Man page of DFU-UTIL + + +

DFU-UTIL(1)

+ +  +

NAME

+ +dfu-util - Device firmware update (DFU) USB programmer +  +

SYNOPSIS

+ + +
+
+dfu-util + +-l + +[-v] + +[-d + +vid:pid[,vid:pid]] + +[-p + +path] + +[-c + +configuration] + +[-i + +interface] + +[-a + +alt-intf] + +[-S + +serial[,serial]] + + +
+dfu-util + +[-v] + +[-d + +vid:pid[,vid:pid]] + +[-p + +path] + +[-c + +configuration] + +[-i + +interface] + +[-a + +alt-intf] + +[-S + +serial[,serial]] + +[-t + +size] + +[-Z + +size] + +[-s + +address] + +[-R] + +[-D|-U + +file] + + +
+dfu-util + +[-hV] + +
+  +

DESCRIPTION

+ +dfu-util + +is a program that implements the host (computer) side of the USB DFU +(Universal Serial Bus Device Firmware Upgrade) protocol. +

+dfu-util communicates with devices that implement the device side of the +USB DFU protocol, and is often used to upgrade the firmware of such +devices. +  +

OPTIONS

+ +
+
-l, --list + +
+List the currently attached DFU capable USB devices. +
-d, --device [Run-Time VENDOR]:[Run-Time PRODUCT][,[DFU Mode VENDOR]:[DFU Mode PRODUCT]] + +
+
+Specify run-time and/or DFU mode vendor and/or product IDs of the DFU device +to work with. VENDOR and PRODUCT are hexadecimal numbers (no prefix +needed), "*" (match any), or "-" (match nothing). By default, any DFU capable +device in either run-time or DFU mode will be considered. +

+If you only have one standards-compliant DFU device attached to your computer, +this parameter is optional. However, as soon as you have multiple DFU devices +connected, dfu-util will detect this and abort, asking you to specify which +device to use. +

+If only run-time IDs are specified (e.g. "--device 1457:51ab"), then in +addition to the specified run-time IDs, any DFU mode devices will also be +considered. This is beneficial to allow a DFU capable device to be found +again after a switch to DFU mode, since the vendor and/or product ID of a +device usually changes in DFU mode. +

+If only DFU mode IDs are specified (e.g. "--device ,951:26"), then all +run-time devices will be ignored, making it easy to target a specific device in +DFU mode. +

+If both run-time and DFU mode IDs are specified (e.g. "--device +1457:51ab,:2bc"), then unspecified DFU mode components will use the run-time +value specified. +

+Examples: +

+
--device 1457:51ab,951:26 + +
+
+ +Work with a device in run-time mode with +vendor ID 0x1457 and product ID 0x51ab, or in DFU mode with vendor ID 0x0951 +and product ID 0x0026 +

+

--device 1457:51ab,:2bc + +
+
+ +Work with a device in run-time mode with vendor ID 0x1457 and product ID +0x51ab, or in DFU mode with vendor ID 0x1457 and product ID 0x02bc +

+

--device 1457:51ab + +
+
+ +Work with a device in run-time mode with vendor ID 0x1457 and product ID +0x51ab, or in DFU mode with any vendor and product ID +

+

--device ,951:26 + +
+
+ +Work with a device in DFU mode with vendor ID 0x0951 and product ID 0x0026 +

+

--device *,- + +
+
+ +Work with any device in run-time mode, and ignore any device in DFU mode +

+

--device , + +
+
+ +Ignore any device in run-time mode, and Work with any device in DFU mode +
+
+ +
-p, --path BUS-PORT. ... .PORT + +
+Specify the path to the DFU device. +
-c, --cfg CONFIG-NR + +
+Specify the configuration of the DFU device. Note that this is only used for matching, the configuration is not set by dfu-util. +
-i, --intf INTF-NR + +
+Specify the DFU interface number. +
-a, --alt ALT + +
+Specify the altsetting of the DFU interface by name or by number. +
-S, --serial [Run-Time SERIAL][,[DFU Mode SERIAL]] + +
+Specify the run-time and DFU mode serial numbers used to further restrict +device matches. If multiple, identical DFU devices are simultaneously +connected to a system then vendor and product ID will be insufficient for +targeting a single device. In this situation, it may be possible to use this +parameter to specify a serial number which also must match. +

+If only a single serial number is specified, then the same serial number is +used in both run-time and DFU mode. An empty serial number will match any +serial number in the corresponding mode. +

-t, --transfer-size SIZE + +
+Specify the number of bytes per USB transfer. The optimal value is +usually determined automatically so this option is rarely useful. If +you need to use this option for a device, please report it as a bug. +
-Z, --upload-size SIZE + +
+Specify the expected upload size, in bytes. +
-U, --upload FILE + +
+Read firmware from device into +FILE. + +
-D, --download FILE + +
+Write firmware from +FILE + +into device. +
-R, --reset + +
+Issue USB reset signalling after upload or download has finished. +
-s, --dfuse-address address + +
+Specify target address for raw binary download/upload on DfuSe devices. Do +not + +use this for downloading DfuSe (.dfu) files. Modifiers can be added +to the address, separated by a colon, to perform special DfuSE commands such +as "leave" DFU mode, "unprotect" and "mass-erase" flash memory. +
-v, --verbose + +
+Print more information about dfu-util's operation. A second +-v + +will turn on verbose logging of USB requests. Repeat this option to further +increase verbosity. +
-h, --help + +
+Show a help text and exit. +
-V, --version + +
+Show version information and exit. +
+  +

EXAMPLES

+ +  +

Using dfu-util in the OpenMoko project

+ +(with the Neo1973 hardware) +

+ +Flashing the rootfs: +
+ + $ dfu-util -a rootfs -R -D /path/to/openmoko-devel-image.jffs2 + +

+ +Flashing the kernel: +
+ + $ dfu-util -a kernel -R -D /path/to/uImage + +

+ +Flashing the bootloader: +
+ + $ dfu-util -a u-boot -R -D /path/to/u-boot.bin + +

+ +Copying a kernel into RAM: +
+ + $ dfu-util -a 0 -R -D /path/to/uImage + +

+Once this has finished, the kernel will be available at the default load +address of 0x32000000 in Neo1973 RAM. +Note: + +You cannot transfer more than 2MB of data into RAM using this method. +

+  +

Using dfu-util with a DfuSe device

+ +

+ +Flashing a +.dfu + +(special DfuSe format) file to the device: +
+ + $ dfu-util -a 0 -D /path/to/dfuse-image.dfu + +

+ +Reading out 1 KB of flash starting at address 0x8000000: +
+ + $ dfu-util -a 0 -s 0x08000000:1024 -U newfile.bin + +

+ +Flashing a binary file to address 0x8004000 of device memory and +ask the device to leave DFU mode: +
+ + $ dfu-util -a 0 -s 0x08004000:leave -D /path/to/image.bin + + +  +

BUGS

+ +Please report any bugs to the dfu-util mailing list at +dfu-util@lists.gnumonks.org. + +Please use the +--verbose option (repeated as necessary) to provide more + +information in your bug report. +  +

SEE ALSO

+ +The dfu-util home page is +http://dfu-util.gnumonks.org + +  +

HISTORY

+ +dfu-util was originally written for the OpenMoko project by +Weston Schmidt <weston_schmidt@yahoo.com> and +Harald Welte <hwelte@hmw-consulting.de>. Over time, nearly complete +support of DFU 1.0, DFU 1.1 and DfuSe ("1.1a") has been added. +  +

LICENCE

+ +dfu-util + +is covered by the GNU General Public License (GPL), version 2 or later. +  +

COPYRIGHT

+ +This manual page was originally written by Uwe Hermann <uwe@hermann-uwe.de>, +and is now part of the dfu-util project. +

+ +


+ 

Index

+
+
NAME
+
SYNOPSIS
+
DESCRIPTION
+
OPTIONS
+
EXAMPLES
+
+
Using dfu-util in the OpenMoko project
+
Using dfu-util with a DfuSe device
+
+
BUGS
+
SEE ALSO
+
HISTORY
+
LICENCE
+
COPYRIGHT
+
+
+This document was created by man2html, +using the doc/dfu-util.1 manual page from dfu-util 0.8.
+Time: 14:40:57 GMT, September 13, 2014 + + diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/www/dfuse.html b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/www/dfuse.html new file mode 100644 index 0000000..35e4ffa --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/www/dfuse.html @@ -0,0 +1,135 @@ + + + + + + DfuSe and dfu-util + + + + + + + + + +
+

Using dfu-util with DfuSe devices

+

DfuSe

+

+ DfuSe (DFU with ST Microsystems extensions) is a protocol based on + DFU 1.1. However, in expanding the functionality of the DFU protocol, + ST Microsystems broke all compatibility with the DFU 1.1 standard. + DfuSe devices report the DFU version as "1.1a". +

+

+ DfuSe can be used to download firmware and other data + from a host computer to a conforming device (or upload in the + opposite direction) over USB similar to standard DFU. +

+

+ The main difference from standard DFU is that the target address in + the device (flash) memory is specified by the host, so that a + download can be performed to parts of the device memory. The host + program is also responsible for erasing flash pages before they + are written to. +

+

.dfu files

+

+ A special file format is defined by ST Microsystems to carry firmware + for DfuSe devices. The file contains target information such as address + and alternate interface information in addition to the binary data. + Several blocks of binary data can be combined in one .dfu file. +

+

Alternate interfaces

+

+ Different memory locations of the device may have different + characteristics that the host program (dfu-util) has to take + into considerations, such as flash memory page size, read-only + versus read-write segments, the need to erase, and so on. + These parameters are reported by the device in the string + descriptors meant for describing the USB interfaces. + The host program decodes these strings to build a memory map of + the device. Different memory units or address spaces are listed + in separate alternate interface settings that must be selected + according to the memory unit to access. +

+

+ Note that dfu-util leaves it to the user to select alternate + interface. When parsing a .dfu file it will skip file segments + not matching the selected alternate interface. Also, some + DfuSe device firmware implementations ignore the setting of + alternate interface and deduct the memory unit from the + address, since they have no address space overlap. +

+

DfuSe special commands

+

+ DfuSe special commands are used by the host program during normal + downloads or uploads, such as SET_ADDRESS and ERASE_PAGE. Also + the normal DFU_DNLOAD and DFU_UPLOAD commands have special + implementations in DfuSe. + Many DfuSe devices also support commands to leave DFU mode, + read unprotect the flash memory or mass erase the flash memory. + dfu-util (from version 0.7) + supports adding "leave", "unprotect", or "mass-erase" + to the -s option argument to send such requests in combination + with a download request. These modifiers are separated with a colon. +

+

+ Some DfuSe devices have their DfuSe bootloader running from flash + memory. Erasing the whole flash memory would therefore destroy + the DfuSe bootloader itself and practically brick the device + for most users. Any use of modifiers such as "unprotect" + and "mass-erase" therefore needs to be combined with the "force" + modifer. This is not included in the examples, to not encourage + ignorant users to copy and paste such instructions and shoot + themselves in the foot. +

+

+ Devices based on for instance STM32F103 all run the bootloader + from flash, since there is no USB bootloader in ROM. +

+

+ For instance STM32F107, STM32F2xx and STM32F4xx devices have a + DfuSe bootloader in ROM, so the flash can be erased while + keeping the device available for USB DFU transfers as long + as the device designers use this built-in bootloader and have + not implemented another DfuSe bootloader in flash that the user is + dependent upon. +

+

+ Well-written bootloaders running from flash will report their + own memory region as read-only and not eraseable, but this does + not prevent dfu-util from sending a "unprotect" or "mass-erase" + request which overrides this, if the user insists. +

+

Example usage

+

+ Flashing a .dfu (special DfuSe format) file to the device: +

+
+         $ dfu-util -a 0 -D /path/to/dfuse-image.dfu
+	
+

+ Reading out 1 KB of flash starting at address 0x8000000: +

+
+         $ dfu-util -a 0 -s 0x08000000:1024 -U newfile.bin
+	
+

+ Flashing a binary file to address 0x8004000 of device memory and ask + the device to leave DFU mode: +

+
+         $ dfu-util -a 0 -s 0x08004000:leave -D /path/to/image.bin
+	
+

+ [Back to dfu-util main page] +

+ +
+ + diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/www/index.html b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/www/index.html new file mode 100644 index 0000000..108ddaf --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/www/index.html @@ -0,0 +1,119 @@ + + + + + + dfu-util Homepage + + + + + + + + + +
+

dfu-util - Device Firmware Upgrade Utilities

+

Description

+

+ dfu-util is a host side implementation of the DFU 1.0 and DFU 1.1 specifications of the USB forum. + + DFU is intended to download and upload firmware to/from devices connected + over USB. It ranges from small devices like micro-controller boards + to mobile phones. Using dfu-util you can download firmware to your + DFU-enabled device or upload firmware from it. dfu-util has been + tested with the Openmoko Neo1973 and Freerunner and many other devices. +

+

+ See the manual page for examples of use. +

+

Supported Devices

+ +

Releases

+

+ Releases of the dfu-util software can be found in the + releases folder. + The current release is 0.8. +

+

+ We offer binaries for Microsoft Windows and some other platforms. + dfu-util uses libusb 1.0 to access your device, so + on Windows you have to register the device with the WinUSB driver + (alternatively libusb-win32 or libusbK), please see the libusbx wiki + for more details. +

+

+ Mac OS X users can also get dfu-util from Homebrew with "brew install dfu-util" or from MacPorts. +

+

+ Most Linux distributions ship dfu-util in binary packages for those + who do not want to compile dfu-util from source. + On Debian, Ubuntu, Fedora and Gentoo you can install it through the + normal software package tools. For other distributions +(namely OpenSuSe, Mandriva, and CentOS) Holger Freyther was kind enough to +provide binary packages through the Open Build Service. +

+

Development

+

+ Development happens in a GIT repository. Browse it via the web +interface or clone it with: +

+
+	git clone git://gitorious.org/dfu-util/dfu-util.git
+	
+

+ See our build instructions for how to + build the source on different platforms. +

+

License

+

+ This software is licensed under the GPL version 2. +

+

Contact

+

+ If you have questions about the development or use of dfu-util please + send an e-mail to our dedicated +mailing list for dfu-util. +

+

People

+

+ dfu-util was originally written by + Harald Welte partially based on code from + dfu-programmer 0.4 and is currently maintained by Stefan Schmidt and + Tormod Volden. +

+ +
+ + diff --git a/BootLoaders/Boards/stm32/tools/win/src/dfu-util/www/simple.css b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/www/simple.css new file mode 100644 index 0000000..98100bc --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/dfu-util/www/simple.css @@ -0,0 +1,56 @@ +body { + margin: 10px; + font-size: 0.82em; + background-color: #EEE; +} + +h1 { + clear: both; + padding: 0 0 12px 0; + margin: 0; + font-size: 2em; + font-weight: bold; +} + +h2 { + clear: both; + margin: 0; + font-size: 1.5em; + font-weight: normal; +} + +h3 { + clear: both; + margin: 15px 0 0 0; + font-size: 1.0em; + font-weight: bold; +} + +p { + line-height: 20px; + padding: 8px 0 8px 0; + margin: 0; + font-size: 1.1em; +} + +pre { + white-space: pre-wrap; + background-color: #CCC; + padding: 3px; +} + +a:hover { + background-color: #DDD; +} + +#middlebox { + width: 600px; + margin: 0px auto; + text-align: left; +} + +#footer { + height: 100px; + padding: 28px 3px 0 0; + margin: 20px 0 20px 0; +} diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/README.md b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/README.md new file mode 100644 index 0000000..c6c9379 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/README.md @@ -0,0 +1,5 @@ +These files build the maple_loader.jar file used on Windows to reset the Sketch via USB Serial, so that the bootloader will run in dfu upload mode, ready for a new sketch to be uploaded + +The files were written by @bobC (github) and have been slightly modified by me (Roger Clark), so that dfu-util no longer attempts to reset the board after upload. +This change to dfu-util's reset command line argument, was required because dfu-util was showing errors on some Windows systems, because the bootloader had reset its self after upload, +before dfu-util had chance to tell it to reset. \ No newline at end of file diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build.xml b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build.xml new file mode 100644 index 0000000..80bdd6f --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + Builds, tests, and runs the project maple_loader. + + + diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/built-jar.properties b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/built-jar.properties new file mode 100644 index 0000000..10752d5 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/built-jar.properties @@ -0,0 +1,4 @@ +#Mon, 20 Jul 2015 11:21:26 +1000 + + +C\:\\Users\\rclark\\Desktop\\maple-asp-master\\installer\\maple_loader= diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/CliTemplate/CliMain.class b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/CliTemplate/CliMain.class new file mode 100644 index 0000000..37ee630 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/CliTemplate/CliMain.class differ diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/CliTemplate/DFUUploader.class b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/CliTemplate/DFUUploader.class new file mode 100644 index 0000000..77087b0 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/CliTemplate/DFUUploader.class differ diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/CliTemplate/ExecCommand.class b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/CliTemplate/ExecCommand.class new file mode 100644 index 0000000..ad95f79 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/CliTemplate/ExecCommand.class differ diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/processing/app/Base.class b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/processing/app/Base.class new file mode 100644 index 0000000..4aa0bde Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/processing/app/Base.class differ diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/processing/app/Preferences.class b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/processing/app/Preferences.class new file mode 100644 index 0000000..89cf010 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/processing/app/Preferences.class differ diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/processing/app/Serial.class b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/processing/app/Serial.class new file mode 100644 index 0000000..cceccdd Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/processing/app/Serial.class differ diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/processing/app/SerialException.class b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/processing/app/SerialException.class new file mode 100644 index 0000000..71048dd Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/processing/app/SerialException.class differ diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/processing/app/debug/MessageConsumer.class b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/processing/app/debug/MessageConsumer.class new file mode 100644 index 0000000..37250e7 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/processing/app/debug/MessageConsumer.class differ diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/processing/app/debug/MessageSiphon.class b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/processing/app/debug/MessageSiphon.class new file mode 100644 index 0000000..e22c8d4 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/processing/app/debug/MessageSiphon.class differ diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/processing/app/debug/RunnerException.class b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/processing/app/debug/RunnerException.class new file mode 100644 index 0000000..710f796 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/processing/app/debug/RunnerException.class differ diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/processing/app/helpers/ProcessUtils.class b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/processing/app/helpers/ProcessUtils.class new file mode 100644 index 0000000..27eca62 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/build/classes/processing/app/helpers/ProcessUtils.class differ diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/dist/README.TXT b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/dist/README.TXT new file mode 100644 index 0000000..255b89c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/dist/README.TXT @@ -0,0 +1,32 @@ +======================== +BUILD OUTPUT DESCRIPTION +======================== + +When you build an Java application project that has a main class, the IDE +automatically copies all of the JAR +files on the projects classpath to your projects dist/lib folder. The IDE +also adds each of the JAR files to the Class-Path element in the application +JAR files manifest file (MANIFEST.MF). + +To run the project from the command line, go to the dist folder and +type the following: + +java -jar "maple_loader.jar" + +To distribute this project, zip up the dist folder (including the lib folder) +and distribute the ZIP file. + +Notes: + +* If two JAR files on the project classpath have the same name, only the first +JAR file is copied to the lib folder. +* Only JAR files are copied to the lib folder. +If the classpath contains other types of files or folders, these files (folders) +are not copied. +* If a library on the projects classpath also has a Class-Path element +specified in the manifest,the content of the Class-Path element has to be on +the projects runtime path. +* To set a main class in a standard Java project, right-click the project node +in the Projects window and choose Properties. Then click Run and enter the +class name in the Main Class field. Alternatively, you can manually type the +class name in the manifest Main-Class element. diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/dist/lib/jssc.jar b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/dist/lib/jssc.jar new file mode 100644 index 0000000..eb74f15 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/dist/lib/jssc.jar differ diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/dist/maple_loader.jar b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/dist/maple_loader.jar new file mode 100644 index 0000000..e1f9965 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/dist/maple_loader.jar differ diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/jars/jssc.jar b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/jars/jssc.jar new file mode 100644 index 0000000..eb74f15 Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/jars/jssc.jar differ diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/manifest.mf b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/manifest.mf new file mode 100644 index 0000000..328e8e5 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/manifest.mf @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +X-COMMENT: Main-Class will be added automatically by build + diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/nbproject/build-impl.xml b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/nbproject/build-impl.xml new file mode 100644 index 0000000..a66f349 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/nbproject/build-impl.xml @@ -0,0 +1,1413 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set src.dir + Must set test.src.dir + Must set build.dir + Must set dist.dir + Must set build.classes.dir + Must set dist.javadoc.dir + Must set build.test.classes.dir + Must set build.test.results.dir + Must set build.classes.excludes + Must set dist.jar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + No tests executed. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set JVM to use for profiling in profiler.info.jvm + Must set profiler agent JVM arguments in profiler.info.jvmargs.agent + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + To run this application from the command line without Ant, try: + + java -jar "${dist.jar.resolved}" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set run.class + + + + Must select one file in the IDE or set run.class + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set debug.class + + + + + Must select one file in the IDE or set debug.class + + + + + Must set fix.includes + + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + Must select one file in the IDE or set profile.class + This target only works when run from inside the NetBeans IDE. + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set run.class + + + + + + Must select some files in the IDE or set test.includes + + + + + Must select one file in the IDE or set run.class + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + Some tests failed; see details above. + + + + + + + + + Must select some files in the IDE or set test.includes + + + + Some tests failed; see details above. + + + + Must select some files in the IDE or set test.class + Must select some method in the IDE or set test.method + + + + Some tests failed; see details above. + + + + + Must select one file in the IDE or set test.class + + + + Must select one file in the IDE or set test.class + Must select some method in the IDE or set test.method + + + + + + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/nbproject/genfiles.properties b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/nbproject/genfiles.properties new file mode 100644 index 0000000..c136721 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=2e6a03ba +build.xml.script.CRC32=4676ee6b +build.xml.stylesheet.CRC32=8064a381@1.75.2.48 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=2e6a03ba +nbproject/build-impl.xml.script.CRC32=392b3f79 +nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.75.2.48 diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/nbproject/private/config.properties b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/nbproject/private/config.properties new file mode 100644 index 0000000..e69de29 diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/nbproject/private/private.properties b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/nbproject/private/private.properties new file mode 100644 index 0000000..e5c9f10 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/nbproject/private/private.properties @@ -0,0 +1,6 @@ +compile.on.save=true +do.depend=false +do.jar=true +javac.debug=true +javadoc.preview=true +user.properties.file=C:\\Users\\rclark\\AppData\\Roaming\\NetBeans\\8.0.2\\build.properties diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/nbproject/private/private.xml b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/nbproject/private/private.xml new file mode 100644 index 0000000..a1bbd60 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/nbproject/private/private.xml @@ -0,0 +1,10 @@ + + + + + + file:/C:/Users/rclark/Desktop/maple-asp-master/installer/maple_loader/src/CliTemplate/CliMain.java + file:/C:/Users/rclark/Desktop/maple-asp-master/installer/maple_loader/src/CliTemplate/DFUUploader.java + + + diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/nbproject/project.properties b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/nbproject/project.properties new file mode 100644 index 0000000..7f48d71 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/nbproject/project.properties @@ -0,0 +1,79 @@ +annotation.processing.enabled=true +annotation.processing.enabled.in.editor=false +annotation.processing.processors.list= +annotation.processing.run.all.processors=true +annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output +application.title=maple_loader +application.vendor=bob +build.classes.dir=${build.dir}/classes +build.classes.excludes=**/*.java,**/*.form +# This directory is removed when the project is cleaned: +build.dir=build +build.generated.dir=${build.dir}/generated +build.generated.sources.dir=${build.dir}/generated-sources +# Only compile against the classpath explicitly listed here: +build.sysclasspath=ignore +build.test.classes.dir=${build.dir}/test/classes +build.test.results.dir=${build.dir}/test/results +# Uncomment to specify the preferred debugger connection transport: +#debug.transport=dt_socket +debug.classpath=\ + ${run.classpath} +debug.test.classpath=\ + ${run.test.classpath} +# Files in build.classes.dir which should be excluded from distribution jar +dist.archive.excludes= +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.jar=${dist.dir}/maple_loader.jar +dist.javadoc.dir=${dist.dir}/javadoc +endorsed.classpath= +excludes= +file.reference.jssc.jar=dist/lib/jssc.jar +file.reference.jssc.jar-1=jars/jssc.jar +includes=** +jar.compress=false +javac.classpath=\ + ${file.reference.jssc.jar}:\ + ${file.reference.jssc.jar-1} +# Space-separated list of extra javac options +javac.compilerargs= +javac.deprecation=false +javac.processorpath=\ + ${javac.classpath} +javac.source=1.7 +javac.target=1.7 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +javac.test.processorpath=\ + ${javac.test.classpath} +javadoc.additionalparam= +javadoc.author=false +javadoc.encoding=${source.encoding} +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +main.class=CliTemplate.CliMain +manifest.file=manifest.mf +meta.inf.dir=${src.dir}/META-INF +mkdist.disabled=false +platform.active=default_platform +run.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +# Space-separated list of JVM arguments used when running the project. +# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value. +# To set system properties for unit tests define test-sys-prop.name=value: +run.jvmargs= +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +source.encoding=UTF-8 +src.dir=src +test.src.dir=test diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/nbproject/project.xml b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/nbproject/project.xml new file mode 100644 index 0000000..92218a9 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/nbproject/project.xml @@ -0,0 +1,15 @@ + + + org.netbeans.modules.java.j2seproject + + + maple_loader + + + + + + + + + diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/CliTemplate/CliMain.java b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/CliTemplate/CliMain.java new file mode 100644 index 0000000..c7dc9f0 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/CliTemplate/CliMain.java @@ -0,0 +1,60 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package CliTemplate; + +import java.io.IOException; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import processing.app.Preferences; + +//import processing.app.I18n; +import processing.app.helpers.ProcessUtils; + +/** + * + * @author cousinr + */ +public class CliMain { + + + /** + * @param args the command line arguments + */ + public static void main(String[] args) { + + String comPort = args[0]; // + String altIf = args[1]; // + String usbID = args[2]; // "1EAF:0003"; + String binFile = args[3]; // bin file + + System.out.println("maple_loader v0.1"); + + Preferences.set ("serial.port",comPort); + Preferences.set ("serial.parity","N"); + Preferences.setInteger ("serial.databits", 8); + Preferences.setInteger ("serial.debug_rate",9600); + Preferences.setInteger ("serial.stopbits",1); + + Preferences.setInteger ("programDelay",1200); + + Preferences.set ("upload.usbID", usbID); + Preferences.set ("upload.altID", altIf); + Preferences.setBoolean ("upload.auto_reset", true); + Preferences.setBoolean ("upload.verbose", false); + + // + DFUUploader dfuUploader = new DFUUploader(); + try { + //dfuUploader.uploadViaDFU(binFile); + dfuUploader.uploadViaDFU(binFile); + } catch (Exception e) + { + System.err.print (MessageFormat.format("an error occurred! {0}\n", e.getMessage())); + } + } +} diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/CliTemplate/DFUUploader.java b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/CliTemplate/DFUUploader.java new file mode 100644 index 0000000..3dee0b4 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/CliTemplate/DFUUploader.java @@ -0,0 +1,345 @@ +/* + DFUUploader - uploader implementation using DFU + + Copyright (c) 2010 + Andrew Meyer + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +package CliTemplate; + +import java.io.BufferedReader; +import java.io.File; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import processing.app.Preferences; +import processing.app.Serial; +import processing.app.debug.MessageConsumer; +import processing.app.debug.MessageSiphon; +import processing.app.debug.RunnerException; + +/** + * + * @author bob + */ +public class DFUUploader implements MessageConsumer { + + boolean firstErrorFound; + boolean secondErrorFound; + // part of the PdeMessageConsumer interface + boolean notFoundError; + boolean verbose; + RunnerException exception; + + static final String SUPER_BADNESS = + "Compiler error!"; + + public boolean uploadUsingPreferences(String binPath, boolean verbose) + throws RunnerException { + + this.verbose = verbose; + + return uploadViaDFU(binPath); + } + + // works with old and new versions of dfu-util + private boolean found_device (String dfuData, String usbID) + { + return dfuData.contains(("Found DFU: [0x"+usbID.substring(0,4)).toUpperCase()) || + dfuData.contains(("Found DFU: ["+usbID.substring(0,4)).toUpperCase()); + } + + public boolean uploadViaDFU (String binPath) + throws RunnerException { + + this.verbose = Preferences.getBoolean ("upload.verbose"); + + /* todo, check for size overruns! */ + String fileType="bin"; + + if (fileType.equals("bin")) { + String usbID = Preferences.get("upload.usbID"); + if (usbID == null) { + /* fall back on default */ + /* this isnt great because is default Avrdude or dfu-util? */ + usbID = Preferences.get("upload.usbID"); + } + + /* if auto-reset, then emit the reset pulse on dtr/rts */ + if (Preferences.get("upload.auto_reset") != null) { + if (Preferences.get("upload.auto_reset").toLowerCase().equals("true")) { + System.out.println("Resetting to bootloader via DTR pulse"); + emitResetPulse(); + } + } else { + System.out.println("Resetting to bootloader via DTR pulse"); + emitResetPulse(); + } + + String dfuList = new String(); + List commandCheck = new ArrayList(); + commandCheck.add("dfu-util"); + commandCheck.add("-l"); + long startChecking = System.currentTimeMillis(); + System.out.println("Searching for DFU device [" + usbID + "]..."); + do { + try { + Thread.sleep(100); + } catch (InterruptedException e) {} + dfuList = executeCheckCommand(commandCheck); + //System.out.println(dfuList); + } + while ( !found_device (dfuList.toUpperCase(), usbID) && (System.currentTimeMillis() - startChecking < 7000)); + + if ( !found_device (dfuList.toUpperCase(), usbID) ) + { + System.out.println(dfuList); + System.err.println("Couldn't find the DFU device: [" + usbID + "]"); + return false; + } + System.out.println("Found it!"); + + /* todo, add handle to let user choose altIf at upload time! */ + String altIf = Preferences.get("upload.altID"); + + List commandDownloader = new ArrayList(); + commandDownloader.add("dfu-util"); + commandDownloader.add("-a "+altIf); + commandDownloader.add("-R"); + commandDownloader.add("-d "+usbID); + commandDownloader.add("-D"+ binPath); //"./thisbin.bin"); + + return executeUploadCommand(commandDownloader); + } + + System.err.println("Only .bin files are supported at this time"); + return false; + } + + /* we need to ensure both RTS and DTR are low to start, + then pulse DTR on its own. This is the reset signal + maple responds to + */ + private void emitResetPulse() throws RunnerException { + + /* wait a while for the device to reboot */ + int programDelay = Preferences.getInteger("programDelay"); + + try { + Serial serialPort = new Serial(); + + // try to toggle DTR/RTS (old scheme) + serialPort.setRTS(false); + serialPort.setDTR(false); + serialPort.setDTR(true); + try { + Thread.sleep(50); + } catch (InterruptedException e) {} + serialPort.setDTR(false); + + // try magic number + serialPort.setRTS(true); + serialPort.setDTR(true); + try { + Thread.sleep(50); + } catch (InterruptedException e) {} + serialPort.setDTR(false); + try { + Thread.sleep(50); + } catch (InterruptedException e) {} + serialPort.write("1EAF"); + try { + Thread.sleep(50); + } catch (InterruptedException e) {} + serialPort.dispose(); + + } catch(Exception e) { + System.err.println("Reset via USB Serial Failed! Did you select the right serial port?\nAssuming the board is in perpetual bootloader mode and continuing to attempt dfu programming...\n"); + } + } + + protected String executeCheckCommand(Collection commandDownloader) + throws RunnerException + { + firstErrorFound = false; // haven't found any errors yet + secondErrorFound = false; + notFoundError = false; + int result=0; // pre-initialized to quiet a bogus warning from jikes + + String userdir = System.getProperty("user.dir") + File.separator; + String returnStr = new String(); + + try { + String[] commandArray = new String[commandDownloader.size()]; + commandDownloader.toArray(commandArray); + + String armBasePath; + + //armBasePath = new String(Base.getHardwarePath() + "/tools/arm/bin/"); + armBasePath = ""; + + commandArray[0] = armBasePath + commandArray[0]; + + if (verbose || Preferences.getBoolean("upload.verbose")) { + for(int i = 0; i < commandArray.length; i++) { + System.out.print(commandArray[i] + " "); + } + System.out.println(); + } + + Process process = Runtime.getRuntime().exec(commandArray); + BufferedReader stdInput = new BufferedReader(new + InputStreamReader(process.getInputStream())); + BufferedReader stdError = new BufferedReader(new + InputStreamReader(process.getErrorStream())); + + // wait for the process to finish. if interrupted + // before waitFor returns, continue waiting + // + boolean busy = true; + while (busy) { + try { + result = process.waitFor(); + busy = false; + } catch (InterruptedException intExc) { + } + } + + String s; + while ((s = stdInput.readLine()) != null) { + returnStr += s + "\n"; + } + + process.destroy(); + + if(exception!=null) { + exception.hideStackTrace(); + throw exception; + } + if(result!=0) return "Error!"; + } catch (Exception e) { + e.printStackTrace(); + } + //System.out.println("result2 is "+result); + // if the result isn't a known, expected value it means that something + // is fairly wrong, one possibility is that jikes has crashed. + // + if (exception != null) throw exception; + + if ((result != 0) && (result != 1 )) { + exception = new RunnerException(SUPER_BADNESS); + } + + return returnStr; // ? true : false; + + } + + // Need to overload this from Uploader to use the system-wide dfu-util + protected boolean executeUploadCommand(Collection commandDownloader) + throws RunnerException + { + firstErrorFound = false; // haven't found any errors yet + secondErrorFound = false; + notFoundError = false; + int result=0; // pre-initialized to quiet a bogus warning from jikes + + String userdir = System.getProperty("user.dir") + File.separator; + + try { + String[] commandArray = new String[commandDownloader.size()]; + commandDownloader.toArray(commandArray); + + String armBasePath; + + //armBasePath = new String(Base.getHardwarePath() + "/tools/arm/bin/"); + armBasePath = ""; + + commandArray[0] = armBasePath + commandArray[0]; + + if (verbose || Preferences.getBoolean("upload.verbose")) { + for(int i = 0; i < commandArray.length; i++) { + System.out.print(commandArray[i] + " "); + } + System.out.println(); + } + + Process process = Runtime.getRuntime().exec(commandArray); + new MessageSiphon(process.getInputStream(), this); + new MessageSiphon(process.getErrorStream(), this); + + // wait for the process to finish. if interrupted + // before waitFor returns, continue waiting + // + boolean compiling = true; + while (compiling) { + try { + result = process.waitFor(); + compiling = false; + } catch (InterruptedException intExc) { + } + } + if(exception!=null) { + exception.hideStackTrace(); + throw exception; + } + if(result!=0) + return false; + } catch (Exception e) { + e.printStackTrace(); + } + //System.out.println("result2 is "+result); + // if the result isn't a known, expected value it means that something + // is fairly wrong, one possibility is that jikes has crashed. + // + if (exception != null) throw exception; + + if ((result != 0) && (result != 1 )) { + exception = new RunnerException(SUPER_BADNESS); + //editor.error(exception); + //PdeBase.openURL(BUGS_URL); + //throw new PdeException(SUPER_BADNESS); + } + + return (result == 0); // ? true : false; + + } + + // deal with messages from dfu-util... + public void message(String s) { + + if(s.indexOf("dfu-util - (C) ") != -1) { return; } + if(s.indexOf("This program is Free Software and has ABSOLUTELY NO WARRANTY") != -1) { return; } + + if(s.indexOf("No DFU capable USB device found") != -1) { + System.err.print(s); + exception = new RunnerException("Problem uploading via dfu-util: No Maple found"); + return; + } + + if(s.indexOf("Operation not perimitted") != -1) { + System.err.print(s); + exception = new RunnerException("Problem uploading via dfu-util: Insufficient privilages"); + return; + } + + // else just print everything... + System.out.print(s); + } + +} diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/CliTemplate/ExecCommand.java b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/CliTemplate/ExecCommand.java new file mode 100644 index 0000000..3d6c106 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/CliTemplate/ExecCommand.java @@ -0,0 +1,119 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package CliTemplate; + +import java.io.IOException; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.List; + +import processing.app.debug.MessageConsumer; +import processing.app.debug.MessageSiphon; +import processing.app.debug.RunnerException; +import processing.app.helpers.ProcessUtils; + +/** + * + * @author cousinr + */ +public class ExecCommand implements MessageConsumer { + + private boolean verbose = true; + private boolean firstErrorFound; + private boolean secondErrorFound; + private RunnerException exception; + + /** + * Either succeeds or throws a RunnerException fit for public consumption. + * + * @param command + * @throws RunnerException + */ + public void execAsynchronously(String[] command) throws RunnerException { + + // eliminate any empty array entries + List stringList = new ArrayList<>(); + for (String string : command) { + string = string.trim(); + if (string.length() != 0) + stringList.add(string); + } + command = stringList.toArray(new String[stringList.size()]); + if (command.length == 0) + return; + int result = 0; + + if (verbose) { + for (String c : command) + System.out.print(c + " "); + System.out.println(); + } + + firstErrorFound = false; // haven't found any errors yet + secondErrorFound = false; + + Process process; + try { + process = ProcessUtils.exec(command); + } catch (IOException e) { + RunnerException re = new RunnerException(e.getMessage()); + re.hideStackTrace(); + throw re; + } + + MessageSiphon in = new MessageSiphon(process.getInputStream(), this); + MessageSiphon err = new MessageSiphon(process.getErrorStream(), this); + + // wait for the process to finish. if interrupted + // before waitFor returns, continue waiting + boolean compiling = true; + while (compiling) { + try { + in.join(); + err.join(); + result = process.waitFor(); + //System.out.println("result is " + result); + compiling = false; + } catch (InterruptedException ignored) { } + } + + // an error was queued up by message(), barf this back to compile(), + // which will barf it back to Editor. if you're having trouble + // discerning the imagery, consider how cows regurgitate their food + // to digest it, and the fact that they have five stomaches. + // + //System.out.println("throwing up " + exception); + if (exception != null) + throw exception; + + if (result > 1) { + // a failure in the tool (e.g. unable to locate a sub-executable) + System.err.println(MessageFormat.format("{0} returned {1}", command[0], result)); + } + + if (result != 0) { + RunnerException re = new RunnerException(MessageFormat.format("exit code: {0}", result)); + re.hideStackTrace(); + throw re; + } + } + + /** + * Part of the MessageConsumer interface, this is called + * whenever a piece (usually a line) of error message is spewed + * out from the compiler. The errors are parsed for their contents + * and line number, which is then reported back to Editor. + * @param s + */ + @Override + public void message(String s) { + int i; + + + System.err.print(s); + } + +} diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/processing/app/Base.java b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/processing/app/Base.java new file mode 100644 index 0000000..c3a174d --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/processing/app/Base.java @@ -0,0 +1,53 @@ +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2004-10 Ben Fry and Casey Reas + Copyright (c) 2001-04 Massachusetts Institute of Technology + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +package processing.app; + + +/** + * The base class for the main processing application. + * Primary role of this class is for platform identification and + * general interaction with the system (launching URLs, loading + * files and images, etc) that comes from that. + */ +public class Base { + + /** + * returns true if running on windows. + */ + static public boolean isWindows() { + //return PApplet.platform == PConstants.WINDOWS; + return System.getProperty("os.name").indexOf("Windows") != -1; + } + + + /** + * true if running on linux. + */ + static public boolean isLinux() { + //return PApplet.platform == PConstants.LINUX; + return System.getProperty("os.name").indexOf("Linux") != -1; + } + + + +} diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/processing/app/Preferences.java b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/processing/app/Preferences.java new file mode 100644 index 0000000..6368e38 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/processing/app/Preferences.java @@ -0,0 +1,157 @@ +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2004-09 Ben Fry and Casey Reas + Copyright (c) 2001-04 Massachusetts Institute of Technology + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +package processing.app; + +import java.io.*; +import java.util.*; + + +/** + * Storage class for user preferences and environment settings. + *

+ * This class no longer uses the Properties class, since + * properties files are iso8859-1, which is highly likely to + * be a problem when trying to save sketch folders and locations. + *

+ * The GUI portion in here is really ugly, as it uses exact layout. This was + * done in frustration one evening (and pre-Swing), but that's long since past, + * and it should all be moved to a proper swing layout like BoxLayout. + *

+ * This is very poorly put together, that the preferences panel and the actual + * preferences i/o is part of the same code. But there hasn't yet been a + * compelling reason to bother with the separation aside from concern about + * being lectured by strangers who feel that it doesn't look like what they + * learned in CS class. + *

+ * Would also be possible to change this to use the Java Preferences API. + * Some useful articles + * here and + * here. + * However, haven't implemented this yet for lack of time, but more + * importantly, because it would entail writing to the registry (on Windows), + * or an obscure file location (on Mac OS X) and make it far more difficult to + * find the preferences to tweak them by hand (no! stay out of regedit!) + * or to reset the preferences by simply deleting the preferences.txt file. + */ +public class Preferences { + + // what to call the feller + + static final String PREFS_FILE = "preferences.txt"; + + + // prompt text stuff + + static final String PROMPT_YES = "Yes"; + static final String PROMPT_NO = "No"; + static final String PROMPT_CANCEL = "Cancel"; + static final String PROMPT_OK = "OK"; + static final String PROMPT_BROWSE = "Browse"; + + /** + * Standardized width for buttons. Mac OS X 10.3 wants 70 as its default, + * Windows XP needs 66, and my Ubuntu machine needs 80+, so 80 seems proper. + */ + static public int BUTTON_WIDTH = 80; + + /** + * Standardized button height. Mac OS X 10.3 (Java 1.4) wants 29, + * presumably because it now includes the blue border, where it didn't + * in Java 1.3. Windows XP only wants 23 (not sure what default Linux + * would be). Because of the disparity, on Mac OS X, it will be set + * inside a static block. + */ + static public int BUTTON_HEIGHT = 24; + + // value for the size bars, buttons, etc + + static final int GRID_SIZE = 33; + + + // indents and spacing standards. these probably need to be modified + // per platform as well, since macosx is so huge, windows is smaller, + // and linux is all over the map + + static final int GUI_BIG = 13; + static final int GUI_BETWEEN = 10; + static final int GUI_SMALL = 6; + + + + // data model + + static Hashtable table = new Hashtable();; + static File preferencesFile; + + + static protected void init(String commandLinePrefs) { + + + } + + + public Preferences() { + + } + + // ................................................................. + + // ................................................................. + + // ................................................................. + + // ................................................................. + + + + static public String get(String attribute) { + return (String) table.get(attribute); + } + + static public void set(String attribute, String value) { + table.put(attribute, value); + } + + + static public boolean getBoolean(String attribute) { + String value = get(attribute); + return (new Boolean(value)).booleanValue(); + } + + + static public void setBoolean(String attribute, boolean value) { + set(attribute, value ? "true" : "false"); + } + + + static public int getInteger(String attribute) { + return Integer.parseInt(get(attribute)); + } + + + static public void setInteger(String key, int value) { + set(key, String.valueOf(value)); + } + +} diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/processing/app/Serial.java b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/processing/app/Serial.java new file mode 100644 index 0000000..04566a7 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/processing/app/Serial.java @@ -0,0 +1,527 @@ +/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + PSerial - class for serial port goodness + Part of the Processing project - http://processing.org + + Copyright (c) 2004 Ben Fry & Casey Reas + + 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. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA +*/ + +package processing.app; +//import processing.core.*; + + +import java.io.*; +import java.text.MessageFormat; +import java.util.*; +import jssc.SerialPort; +import jssc.SerialPortEvent; +import jssc.SerialPortEventListener; +import jssc.SerialPortException; +import jssc.SerialPortList; +import processing.app.debug.MessageConsumer; + + +public class Serial implements SerialPortEventListener { + + //PApplet parent; + + // properties can be passed in for default values + // otherwise defaults to 9600 N81 + + // these could be made static, which might be a solution + // for the classloading problem.. because if code ran again, + // the static class would have an object that could be closed + + SerialPort port; + + int rate; + int parity; + int databits; + int stopbits; + boolean monitor = false; + + // read buffer and streams + + InputStream input; + OutputStream output; + + byte buffer[] = new byte[32768]; + int bufferIndex; + int bufferLast; + + MessageConsumer consumer; + + public Serial(boolean monitor) throws SerialException { + this(Preferences.get("serial.port"), + Preferences.getInteger("serial.debug_rate"), + Preferences.get("serial.parity").charAt(0), + Preferences.getInteger("serial.databits"), + new Float(Preferences.get("serial.stopbits")).floatValue()); + this.monitor = monitor; + } + + public Serial() throws SerialException { + this(Preferences.get("serial.port"), + Preferences.getInteger("serial.debug_rate"), + Preferences.get("serial.parity").charAt(0), + Preferences.getInteger("serial.databits"), + new Float(Preferences.get("serial.stopbits")).floatValue()); + } + + public Serial(int irate) throws SerialException { + this(Preferences.get("serial.port"), irate, + Preferences.get("serial.parity").charAt(0), + Preferences.getInteger("serial.databits"), + new Float(Preferences.get("serial.stopbits")).floatValue()); + } + + public Serial(String iname, int irate) throws SerialException { + this(iname, irate, Preferences.get("serial.parity").charAt(0), + Preferences.getInteger("serial.databits"), + new Float(Preferences.get("serial.stopbits")).floatValue()); + } + + public Serial(String iname) throws SerialException { + this(iname, Preferences.getInteger("serial.debug_rate"), + Preferences.get("serial.parity").charAt(0), + Preferences.getInteger("serial.databits"), + new Float(Preferences.get("serial.stopbits")).floatValue()); + } + + public Serial(String iname, int irate, + char iparity, int idatabits, float istopbits) + throws SerialException { + //if (port != null) port.close(); + //this.parent = parent; + //parent.attach(this); + + this.rate = irate; + + parity = SerialPort.PARITY_NONE; + if (iparity == 'E') parity = SerialPort.PARITY_EVEN; + if (iparity == 'O') parity = SerialPort.PARITY_ODD; + + this.databits = idatabits; + + stopbits = SerialPort.STOPBITS_1; + if (istopbits == 1.5f) stopbits = SerialPort.STOPBITS_1_5; + if (istopbits == 2) stopbits = SerialPort.STOPBITS_2; + + try { + port = new SerialPort(iname); + port.openPort(); + port.setParams(rate, databits, stopbits, parity, true, true); + port.addEventListener(this); + } catch (Exception e) { + throw new SerialException(MessageFormat.format("Error opening serial port ''{0}''.", iname), e); + } + + if (port == null) { + throw new SerialException("Serial port '" + iname + "' not found. Did you select the right one from the Tools > Serial Port menu?"); + } + } + + + public void setup() { + //parent.registerCall(this, DISPOSE); + } + + public void dispose() throws IOException { + if (port != null) { + try { + if (port.isOpened()) { + port.closePort(); // close the port + } + } catch (SerialPortException e) { + throw new IOException(e); + } finally { + port = null; + } + } + } + + public void addListener(MessageConsumer consumer) { + this.consumer = consumer; + } + + public synchronized void serialEvent(SerialPortEvent serialEvent) { + if (serialEvent.isRXCHAR()) { + try { + byte[] buf = port.readBytes(serialEvent.getEventValue()); + if (buf.length > 0) { + if (bufferLast == buffer.length) { + byte temp[] = new byte[bufferLast << 1]; + System.arraycopy(buffer, 0, temp, 0, bufferLast); + buffer = temp; + } + if (monitor) { + System.out.print(new String(buf)); + } + if (this.consumer != null) { + this.consumer.message(new String(buf)); + } + } + } catch (SerialPortException e) { + errorMessage("serialEvent", e); + } + } + } + + + /** + * Returns the number of bytes that have been read from serial + * and are waiting to be dealt with by the user. + */ + public synchronized int available() { + return (bufferLast - bufferIndex); + } + + + /** + * Ignore all the bytes read so far and empty the buffer. + */ + public synchronized void clear() { + bufferLast = 0; + bufferIndex = 0; + } + + + /** + * Returns a number between 0 and 255 for the next byte that's + * waiting in the buffer. + * Returns -1 if there was no byte (although the user should + * first check available() to see if things are ready to avoid this) + */ + public synchronized int read() { + if (bufferIndex == bufferLast) return -1; + + int outgoing = buffer[bufferIndex++] & 0xff; + if (bufferIndex == bufferLast) { // rewind + bufferIndex = 0; + bufferLast = 0; + } + return outgoing; + } + + + /** + * Returns the next byte in the buffer as a char. + * Returns -1, or 0xffff, if nothing is there. + */ + public synchronized char readChar() { + if (bufferIndex == bufferLast) return (char)(-1); + return (char) read(); + } + + + /** + * Return a byte array of anything that's in the serial buffer. + * Not particularly memory/speed efficient, because it creates + * a byte array on each read, but it's easier to use than + * readBytes(byte b[]) (see below). + */ + public synchronized byte[] readBytes() { + if (bufferIndex == bufferLast) return null; + + int length = bufferLast - bufferIndex; + byte outgoing[] = new byte[length]; + System.arraycopy(buffer, bufferIndex, outgoing, 0, length); + + bufferIndex = 0; // rewind + bufferLast = 0; + return outgoing; + } + + + /** + * Grab whatever is in the serial buffer, and stuff it into a + * byte buffer passed in by the user. This is more memory/time + * efficient than readBytes() returning a byte[] array. + *

+ * Returns an int for how many bytes were read. If more bytes + * are available than can fit into the byte array, only those + * that will fit are read. + */ + public synchronized int readBytes(byte outgoing[]) { + if (bufferIndex == bufferLast) return 0; + + int length = bufferLast - bufferIndex; + if (length > outgoing.length) length = outgoing.length; + System.arraycopy(buffer, bufferIndex, outgoing, 0, length); + + bufferIndex += length; + if (bufferIndex == bufferLast) { + bufferIndex = 0; // rewind + bufferLast = 0; + } + return length; + } + + + /** + * Reads from the serial port into a buffer of bytes up to and + * including a particular character. If the character isn't in + * the serial buffer, then 'null' is returned. + */ + public synchronized byte[] readBytesUntil(int interesting) { + if (bufferIndex == bufferLast) return null; + byte what = (byte)interesting; + + int found = -1; + for (int k = bufferIndex; k < bufferLast; k++) { + if (buffer[k] == what) { + found = k; + break; + } + } + if (found == -1) return null; + + int length = found - bufferIndex + 1; + byte outgoing[] = new byte[length]; + System.arraycopy(buffer, bufferIndex, outgoing, 0, length); + + bufferIndex = 0; // rewind + bufferLast = 0; + return outgoing; + } + + + /** + * Reads from the serial port into a buffer of bytes until a + * particular character. If the character isn't in the serial + * buffer, then 'null' is returned. + *

+ * If outgoing[] is not big enough, then -1 is returned, + * and an error message is printed on the console. + * If nothing is in the buffer, zero is returned. + * If 'interesting' byte is not in the buffer, then 0 is returned. + */ + public synchronized int readBytesUntil(int interesting, byte outgoing[]) { + if (bufferIndex == bufferLast) return 0; + byte what = (byte)interesting; + + int found = -1; + for (int k = bufferIndex; k < bufferLast; k++) { + if (buffer[k] == what) { + found = k; + break; + } + } + if (found == -1) return 0; + + int length = found - bufferIndex + 1; + if (length > outgoing.length) { + System.err.println("readBytesUntil() byte buffer is" + + " too small for the " + length + + " bytes up to and including char " + interesting); + return -1; + } + //byte outgoing[] = new byte[length]; + System.arraycopy(buffer, bufferIndex, outgoing, 0, length); + + bufferIndex += length; + if (bufferIndex == bufferLast) { + bufferIndex = 0; // rewind + bufferLast = 0; + } + return length; + } + + + /** + * Return whatever has been read from the serial port so far + * as a String. It assumes that the incoming characters are ASCII. + *

+ * If you want to move Unicode data, you can first convert the + * String to a byte stream in the representation of your choice + * (i.e. UTF8 or two-byte Unicode data), and send it as a byte array. + */ + public synchronized String readString() { + if (bufferIndex == bufferLast) return null; + return new String(readBytes()); + } + + + /** + * Combination of readBytesUntil and readString. See caveats in + * each function. Returns null if it still hasn't found what + * you're looking for. + *

+ * If you want to move Unicode data, you can first convert the + * String to a byte stream in the representation of your choice + * (i.e. UTF8 or two-byte Unicode data), and send it as a byte array. + */ + public synchronized String readStringUntil(int interesting) { + byte b[] = readBytesUntil(interesting); + if (b == null) return null; + return new String(b); + } + + + /** + * This will handle both ints, bytes and chars transparently. + */ + public void write(int what) { // will also cover char + try { + port.writeInt(what & 0xff); + } catch (SerialPortException e) { + errorMessage("write", e); + } + } + + + public void write(byte bytes[]) { + try { + port.writeBytes(bytes); + } catch (SerialPortException e) { + errorMessage("write", e); + } + } + + + /** + * Write a String to the output. Note that this doesn't account + * for Unicode (two bytes per char), nor will it send UTF8 + * characters.. It assumes that you mean to send a byte buffer + * (most often the case for networking and serial i/o) and + * will only use the bottom 8 bits of each char in the string. + * (Meaning that internally it uses String.getBytes) + *

+ * If you want to move Unicode data, you can first convert the + * String to a byte stream in the representation of your choice + * (i.e. UTF8 or two-byte Unicode data), and send it as a byte array. + */ + public void write(String what) { + write(what.getBytes()); + } + + public void setDTR(boolean state) { + try { + port.setDTR(state); + } catch (SerialPortException e) { + errorMessage("setDTR", e); + } + } + + public void setRTS(boolean state) { + try { + port.setRTS(state); + } catch (SerialPortException e) { + errorMessage("setRTS", e); + } + } + + static public List list() { + return Arrays.asList(SerialPortList.getPortNames()); + } + + + /** + * General error reporting, all corraled here just in case + * I think of something slightly more intelligent to do. + */ + static public void errorMessage(String where, Throwable e) { + System.err.println("Error inside Serial." + where + "()"); + e.printStackTrace(); + } +} + + + /* + class SerialMenuListener implements ItemListener { + //public SerialMenuListener() { } + + public void itemStateChanged(ItemEvent e) { + int count = serialMenu.getItemCount(); + for (int i = 0; i < count; i++) { + ((CheckboxMenuItem)serialMenu.getItem(i)).setState(false); + } + CheckboxMenuItem item = (CheckboxMenuItem)e.getSource(); + item.setState(true); + String name = item.getLabel(); + //System.out.println(item.getLabel()); + PdeBase.properties.put("serial.port", name); + //System.out.println("set to " + get("serial.port")); + } + } + */ + + + /* + protected Vector buildPortList() { + // get list of names for serial ports + // have the default port checked (if present) + Vector list = new Vector(); + + //SerialMenuListener listener = new SerialMenuListener(); + boolean problem = false; + + // if this is failing, it may be because + // lib/javax.comm.properties is missing. + // java is weird about how it searches for java.comm.properties + // so it tends to be very fragile. i.e. quotes in the CLASSPATH + // environment variable will hose things. + try { + //System.out.println("building port list"); + Enumeration portList = CommPortIdentifier.getPortIdentifiers(); + while (portList.hasMoreElements()) { + CommPortIdentifier portId = + (CommPortIdentifier) portList.nextElement(); + //System.out.println(portId); + + if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) { + //if (portId.getName().equals(port)) { + String name = portId.getName(); + //CheckboxMenuItem mi = + //new CheckboxMenuItem(name, name.equals(defaultName)); + + //mi.addItemListener(listener); + //serialMenu.add(mi); + list.addElement(name); + } + } + } catch (UnsatisfiedLinkError e) { + e.printStackTrace(); + problem = true; + + } catch (Exception e) { + System.out.println("exception building serial menu"); + e.printStackTrace(); + } + + //if (serialMenu.getItemCount() == 0) { + //System.out.println("dimming serial menu"); + //serialMenu.setEnabled(false); + //} + + // only warn them if this is the first time + if (problem && PdeBase.firstTime) { + JOptionPane.showMessageDialog(this, //frame, + "Serial port support not installed.\n" + + "Check the readme for instructions\n" + + "if you need to use the serial port. ", + "Serial Port Warning", + JOptionPane.WARNING_MESSAGE); + } + return list; + } + */ + + + diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/processing/app/SerialException.java b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/processing/app/SerialException.java new file mode 100644 index 0000000..525c240 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/processing/app/SerialException.java @@ -0,0 +1,39 @@ +/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Copyright (c) 2007 David A. Mellis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +package processing.app; + +public class SerialException extends Exception { + public SerialException() { + super(); + } + + public SerialException(String message) { + super(message); + } + + public SerialException(String message, Throwable cause) { + super(message, cause); + } + + public SerialException(Throwable cause) { + super(cause); + } +} diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/processing/app/debug/MessageConsumer.java b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/processing/app/debug/MessageConsumer.java new file mode 100644 index 0000000..5e20429 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/processing/app/debug/MessageConsumer.java @@ -0,0 +1,42 @@ +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2004-06 Ben Fry and Casey Reas + Copyright (c) 2001-04 Massachusetts Institute of Technology + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +package processing.app.debug; + + +/** + * Interface for dealing with parser/compiler output. + *

+ * Different instances of MessageStream need to do different things with + * messages. In particular, a stream instance used for parsing output from + * the compiler compiler has to interpret its messages differently than one + * parsing output from the runtime. + *

+ * Classes which consume messages and do something with them + * should implement this interface. + */ +public interface MessageConsumer { + + public void message(String s); + +} diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/processing/app/debug/MessageSiphon.java b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/processing/app/debug/MessageSiphon.java new file mode 100644 index 0000000..26901c3 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/processing/app/debug/MessageSiphon.java @@ -0,0 +1,104 @@ +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2004-06 Ben Fry and Casey Reas + Copyright (c) 2001-04 Massachusetts Institute of Technology + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +package processing.app.debug; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.SocketException; + +/** + * Slurps up messages from compiler. + */ +public class MessageSiphon implements Runnable { + + private final BufferedReader streamReader; + private final MessageConsumer consumer; + + private Thread thread; + private boolean canRun; + + public MessageSiphon(InputStream stream, MessageConsumer consumer) { + this.streamReader = new BufferedReader(new InputStreamReader(stream)); + this.consumer = consumer; + this.canRun = true; + + thread = new Thread(this); + // don't set priority too low, otherwise exceptions won't + // bubble up in time (i.e. compile errors have a weird delay) + //thread.setPriority(Thread.MIN_PRIORITY); + thread.setPriority(Thread.MAX_PRIORITY - 1); + thread.start(); + } + + + public void run() { + try { + // process data until we hit EOF; this will happily block + // (effectively sleeping the thread) until new data comes in. + // when the program is finally done, null will come through. + // + String currentLine; + while (canRun && (currentLine = streamReader.readLine()) != null) { + // \n is added again because readLine() strips it out + //EditorConsole.systemOut.println("messaging in"); + consumer.message(currentLine + "\n"); + //EditorConsole.systemOut.println("messaging out"); + } + //EditorConsole.systemOut.println("messaging thread done"); + } catch (NullPointerException npe) { + // Fairly common exception during shutdown + } catch (SocketException e) { + // socket has been close while we were wainting for data. nothing to see here, move along + } catch (Exception e) { + // On Linux and sometimes on Mac OS X, a "bad file descriptor" + // message comes up when closing an applet that's run externally. + // That message just gets supressed here.. + String mess = e.getMessage(); + if ((mess != null) && + (mess.indexOf("Bad file descriptor") != -1)) { + //if (e.getMessage().indexOf("Bad file descriptor") == -1) { + //System.err.println("MessageSiphon err " + e); + //e.printStackTrace(); + } else { + e.printStackTrace(); + } + } finally { + thread = null; + } + } + + // Wait until the MessageSiphon thread is complete. + public void join() throws java.lang.InterruptedException { + // Grab a temp copy in case another thread nulls the "thread" + // member variable + Thread t = thread; + if (t != null) t.join(); + } + + public void stop() { + this.canRun = false; + } + +} diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/processing/app/debug/RunnerException.java b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/processing/app/debug/RunnerException.java new file mode 100644 index 0000000..0a67d1e --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/processing/app/debug/RunnerException.java @@ -0,0 +1,161 @@ +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2004-08 Ben Fry and Casey Reas + Copyright (c) 2001-04 Massachusetts Institute of Technology + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +package processing.app.debug; + + +/** + * An exception with a line number attached that occurs + * during either compile time or run time. + */ +@SuppressWarnings("serial") +public class RunnerException extends Exception { + protected String message; + protected int codeIndex; + protected int codeLine; + protected int codeColumn; + protected boolean showStackTrace; + + + public RunnerException(String message) { + this(message, true); + } + + public RunnerException(String message, boolean showStackTrace) { + this(message, -1, -1, -1, showStackTrace); + } + + public RunnerException(String message, int file, int line) { + this(message, file, line, -1, true); + } + + + public RunnerException(String message, int file, int line, int column) { + this(message, file, line, column, true); + } + + + public RunnerException(String message, int file, int line, int column, + boolean showStackTrace) { + this.message = message; + this.codeIndex = file; + this.codeLine = line; + this.codeColumn = column; + this.showStackTrace = showStackTrace; + } + + + public RunnerException(Exception e) { + super(e); + this.showStackTrace = true; + } + + /** + * Override getMessage() in Throwable, so that I can set + * the message text outside the constructor. + */ + public String getMessage() { + return message; + } + + + public void setMessage(String message) { + this.message = message; + } + + + public int getCodeIndex() { + return codeIndex; + } + + + public void setCodeIndex(int index) { + codeIndex = index; + } + + + public boolean hasCodeIndex() { + return codeIndex != -1; + } + + + public int getCodeLine() { + return codeLine; + } + + + public void setCodeLine(int line) { + this.codeLine = line; + } + + + public boolean hasCodeLine() { + return codeLine != -1; + } + + + public void setCodeColumn(int column) { + this.codeColumn = column; + } + + + public int getCodeColumn() { + return codeColumn; + } + + + public void showStackTrace() { + showStackTrace = true; + } + + + public void hideStackTrace() { + showStackTrace = false; + } + + + /** + * Nix the java.lang crap out of an exception message + * because it scares the children. + *

+ * This function must be static to be used with super() + * in each of the constructors above. + */ + /* + static public final String massage(String msg) { + if (msg.indexOf("java.lang.") == 0) { + //int dot = msg.lastIndexOf('.'); + msg = msg.substring("java.lang.".length()); + } + return msg; + //return (dot == -1) ? msg : msg.substring(dot+1); + } + */ + + + public void printStackTrace() { + if (showStackTrace) { + super.printStackTrace(); + } + } +} diff --git a/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/processing/app/helpers/ProcessUtils.java b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/processing/app/helpers/ProcessUtils.java new file mode 100644 index 0000000..c023f58 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/maple_loader/src/processing/app/helpers/ProcessUtils.java @@ -0,0 +1,32 @@ +package processing.app.helpers; + +//import processing.app.Base; + +import java.io.IOException; +import java.util.Map; + +import processing.app.Base; + +public class ProcessUtils { + + public static Process exec(String[] command) throws IOException { + // No problems on linux and mac + if (!Base.isWindows()) { + return Runtime.getRuntime().exec(command); + } + + // Brutal hack to workaround windows command line parsing. + // http://stackoverflow.com/questions/5969724/java-runtime-exec-fails-to-escape-characters-properly + // http://msdn.microsoft.com/en-us/library/a1y7w461.aspx + // http://bugs.sun.com/view_bug.do?bug_id=6468220 + // http://bugs.sun.com/view_bug.do?bug_id=6518827 + String[] cmdLine = new String[command.length]; + for (int i = 0; i < command.length; i++) + cmdLine[i] = command[i].replace("\"", "\\\""); + + ProcessBuilder pb = new ProcessBuilder(cmdLine); + Map env = pb.environment(); + env.put("CYGWIN", "nodosfilewarning"); + return pb.start(); + } +} diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/AUTHORS b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/AUTHORS new file mode 100644 index 0000000..d096f22 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/AUTHORS @@ -0,0 +1,19 @@ +Authors ordered by first contribution. + +Geoffrey McRae +Bret Olmsted +Tormod Volden +Jakob Malm +Reuben Dowle +Matthias Kubisch +Paul Fertser +Daniel Strnad +Jérémie Rapin +Christian Pointner +Mats Erik Andersson +Alexey Borovik +Antonio Borneo +Armin van der Togt +Brian Silverman +Georg Hofmann +Luis Rodrigues diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/Android.mk b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/Android.mk new file mode 100644 index 0000000..7be3d00 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/Android.mk @@ -0,0 +1,20 @@ +TOP_LOCAL_PATH := $(call my-dir) + +include $(call all-named-subdir-makefiles, parsers) + +LOCAL_PATH := $(TOP_LOCAL_PATH) + +include $(CLEAR_VARS) +LOCAL_MODULE := stm32flash +LOCAL_SRC_FILES := \ + dev_table.c \ + i2c.c \ + init.c \ + main.c \ + port.c \ + serial_common.c \ + serial_platform.c \ + stm32.c \ + utils.c +LOCAL_STATIC_LIBRARIES := libparsers +include $(BUILD_EXECUTABLE) diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/HOWTO b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/HOWTO new file mode 100644 index 0000000..d8f32eb --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/HOWTO @@ -0,0 +1,35 @@ +Add new interfaces: +===================================================================== +Current version 0.4 supports the following interfaces: +- UART Windows (either "COMn" and "\\.\COMn"); +- UART posix/Linux (e.g. "/dev/ttyUSB0"); +- I2C Linux through standard driver "i2c-dev" (e.g. "/dev/i2c-n"). + +Starting from version 0.4, the back-end of stm32flash is modular and +ready to be expanded to support new interfaces. +I'm planning adding SPI on Linux through standard driver "spidev". +You are invited to contribute with more interfaces. + +To add a new interface you need to add a new file, populate the struct +port_interface (check at the end of files i2c.c, serial_posix.c and +serial_w32.c) and provide the relative functions to operate on the +interface: open/close, read/write, get_cfg_str and the optional gpio. +The include the new drive in Makefile and register the new struct +port_interface in file port.c in struct port_interface *ports[]. + +There are several USB-I2C adapter in the market, each providing its +own libraries to communicate with the I2C bus. +Could be interesting to provide as back-end a bridge between stm32flash +and such libraries (I have no plan on this item). + + +Add new STM32 devices: +===================================================================== +Add a new line in file dev_table.c, in table devices[]. +The fields of the table are listed in stm32.h, struct stm32_dev. + + +Cross compile on Linux host for Windows target with MinGW: +===================================================================== +I'm using a 64 bit Arch Linux machines, and I usually run: + make CC=x86_64-w64-mingw32-gcc AR=x86_64-w64-mingw32-ar diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/I2C.txt b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/I2C.txt new file mode 100644 index 0000000..4c05ff6 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/I2C.txt @@ -0,0 +1,94 @@ +About I2C back-end communication in stm32flash +========================================================================== + +Starting from version v0.4, beside the serial communication port, +stm32flash adds support for I2C port to talk with STM32 bootloader. + +The current I2C back-end supports only the API provided by Linux kernel +driver "i2c-dev", so only I2C controllers with Linux kernel driver can be +used. +In Linux source code, most of the drivers for I2C and SMBUS controllers +are in + ./drivers/i2c/busses/ +Only I2C is supported by STM32 bootloader, so check the section below +about SMBUS. +No I2C support for Windows is available in stm32flash v0.4. + +Thanks to the new modular back-end, stm32flash can be easily extended to +support new back-ends and API. Check HOWTO file in stm32flash source code +for details. + +In the market there are several USB-to-I2C dongles; most of them are not +supported by kernel drivers. Manufacturer provide proprietary userspace +libraries using not standardized API. +These API and dongles could be supported in feature versions. + +There are currently 3 versions of STM32 bootloader for I2C communications: +- v1.0 using I2C clock stretching synchronization between host and STM32; +- v1.1 superset of v1.0, adds non stretching commands; +- v1.2 superset of v1.1, adds CRC command and compatibility with i2cdetect. +Details in ST application note AN2606. +All the bootloaders above are tested and working with stm32flash. + + +SMBUS controllers +========================================================================== + +Almost 50% of the drivers in Linux source code folder + ./drivers/i2c/busses/ +are for controllers that "only" support SMBUS protocol. They can NOT +operate with STM32 bootloader. +To identify if your controller supports I2C, use command: + i2cdetect -F n +where "n" is the number of the I2C interface (e.g. n=3 for "/dev/i2c-3"). +Controllers that supports I2C will report + I2C yes +Controller that support both I2C and SMBUS are ok. + +If you are interested on details about SMBUS protocol, you can download +the current specs from + http://smbus.org/specs/smbus20.pdf +and you can read the files in Linux source code + ./Documentation/i2c/i2c-protocol + ./Documentation/i2c/smbus-protocol + + +About bootloader v1.0 +========================================================================== + +Version v1.0 can have issues with some I2C controllers due to use of clock +stretching during commands that require long operations, like flash erase +and programming. + +Clock stretching is a technique to synchronize host and I2C device. When +I2C device wants to force a delay in the communication, it push "low" the +I2C clock; the I2C controller detects it and waits until I2C clock returns +"high". +Most I2C controllers set a "timeout" for clock stretching, ranging from +few milli-seconds to seconds depending on specific HW or SW driver. + +It is possible that the timeout in your I2C controller is smaller than the +delay required for flash erase or programming. In this case the I2C +controller will timeout and report error to stm32flash. +There is no possibility for stm32flash to retry, so it can only signal the +error and exit. + +To by-pass the issue with bootloader v1.0 you can modify the kernel driver +of your I2C controller. Not an easy job, since every controller has its own +way to handle the timeout. + +In my case I'm using the I2C controller integrated in the VGA port of my +laptop HP EliteBook 8460p. I built the 0.25$ VGA-to-I2C adapter reported in + http://www.paintyourdragon.com/?p=43 +To change the timeout of the I2C controller I had to modify the kernel file + drivers/gpu/drm/radeon/radeon_i2c.c +line 969 +- i2c->bit.timeout = usecs_to_jiffies(2200); /* from VESA */ ++ i2c->bit.timeout = msecs_to_jiffies(5000); /* 5s for STM32 */ +and recompile it. +Then + $> modprobe i2c-dev + $> chmod 666 /dev/i2c-7 + #> stm32flash -a 0x39 /dev/i2c-7 + +2014-09-16 Antonio Borneo diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/Makefile b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/Makefile new file mode 100644 index 0000000..0328d55 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/Makefile @@ -0,0 +1,38 @@ +PREFIX = /usr/local +CFLAGS += -Wall -g + +INSTALL = install + +OBJS = dev_table.o \ + i2c.o \ + init.o \ + main.o \ + port.o \ + serial_common.o \ + serial_platform.o \ + stm32.o \ + utils.o + +LIBOBJS = parsers/parsers.a + +all: stm32flash + +serial_platform.o: serial_posix.c serial_w32.c + +parsers/parsers.a: + cd parsers && $(MAKE) parsers.a + +stm32flash: $(OBJS) $(LIBOBJS) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBOBJS) + +clean: + rm -f $(OBJS) stm32flash + cd parsers && $(MAKE) $@ + +install: all + $(INSTALL) -d $(DESTDIR)$(PREFIX)/bin + $(INSTALL) -m 755 stm32flash $(DESTDIR)$(PREFIX)/bin + $(INSTALL) -d $(DESTDIR)$(PREFIX)/share/man/man1 + $(INSTALL) -m 644 stm32flash.1 $(DESTDIR)$(PREFIX)/share/man/man1 + +.PHONY: all clean install diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/TODO b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/TODO new file mode 100644 index 0000000..41df614 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/TODO @@ -0,0 +1,7 @@ + +stm32: +- Add support for variable page size + +AUTHORS: +- Add contributors from Geoffrey's commits + diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/dev_table.c b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/dev_table.c new file mode 100644 index 0000000..399cd9d --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/dev_table.c @@ -0,0 +1,70 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + Copyright (C) 2014 Antonio Borneo + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "stm32.h" + +/* + * Device table, corresponds to the "Bootloader device-dependant parameters" + * table in ST document AN2606. + * Note that the option bytes upper range is inclusive! + */ +const stm32_dev_t devices[] = { + /* F0 */ + {0x440, "STM32F051xx" , 0x20001000, 0x20002000, 0x08000000, 0x08010000, 4, 1024, 0x1FFFF800, 0x1FFFF80B, 0x1FFFEC00, 0x1FFFF800}, + {0x444, "STM32F030/F031" , 0x20001000, 0x20002000, 0x08000000, 0x08010000, 4, 1024, 0x1FFFF800, 0x1FFFF80B, 0x1FFFEC00, 0x1FFFF800}, + {0x445, "STM32F042xx" , 0x20001800, 0x20001800, 0x08000000, 0x08008000, 4, 1024, 0x1FFFF800, 0x1FFFF80F, 0x1FFFC400, 0x1FFFF800}, + {0x448, "STM32F072xx" , 0x20001800, 0x20004000, 0x08000000, 0x08020000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFC800, 0x1FFFF800}, + /* F1 */ + {0x412, "Low-density" , 0x20000200, 0x20002800, 0x08000000, 0x08008000, 4, 1024, 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800}, + {0x410, "Medium-density" , 0x20000200, 0x20005000, 0x08000000, 0x08020000, 4, 1024, 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800}, + {0x414, "High-density" , 0x20000200, 0x20010000, 0x08000000, 0x08080000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800}, + {0x420, "Medium-density VL" , 0x20000200, 0x20002000, 0x08000000, 0x08020000, 4, 1024, 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800}, + {0x428, "High-density VL" , 0x20000200, 0x20008000, 0x08000000, 0x08080000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800}, + {0x418, "Connectivity line" , 0x20001000, 0x20010000, 0x08000000, 0x08040000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFB000, 0x1FFFF800}, + {0x430, "XL-density" , 0x20000800, 0x20018000, 0x08000000, 0x08100000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFE000, 0x1FFFF800}, + /* Note that F2 and F4 devices have sectors of different page sizes + and only the first sectors (of one page size) are included here */ + /* F2 */ + {0x411, "STM32F2xx" , 0x20002000, 0x20020000, 0x08000000, 0x08100000, 4, 16384, 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF77DF}, + /* F3 */ + {0x432, "STM32F373/8" , 0x20001400, 0x20008000, 0x08000000, 0x08040000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFD800, 0x1FFFF800}, + {0x422, "F302xB/303xB/358" , 0x20001400, 0x20010000, 0x08000000, 0x08040000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFD800, 0x1FFFF800}, + {0x439, "STM32F302x4(6/8)" , 0x20001800, 0x20004000, 0x08000000, 0x08040000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFD800, 0x1FFFF800}, + {0x438, "F303x4/334/328" , 0x20001800, 0x20003000, 0x08000000, 0x08040000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFD800, 0x1FFFF800}, + /* F4 */ + {0x413, "STM32F40/1" , 0x20002000, 0x20020000, 0x08000000, 0x08100000, 4, 16384, 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF77DF}, + /* 0x419 is also used for STM32F429/39 but with other bootloader ID... */ + {0x419, "STM32F427/37" , 0x20002000, 0x20030000, 0x08000000, 0x08100000, 4, 16384, 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF77FF}, + {0x423, "STM32F401xB(C)" , 0x20003000, 0x20010000, 0x08000000, 0x08100000, 4, 16384, 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF77FF}, + {0x433, "STM32F401xD(E)" , 0x20003000, 0x20018000, 0x08000000, 0x08100000, 4, 16384, 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF77FF}, + /* L0 */ + {0x417, "L05xxx/06xxx" , 0x20001000, 0x20002000, 0x08000000, 0x08010000, 32, 128, 0x1FF80000, 0x1FF8000F, 0x1FF00000, 0x1FF01000}, + /* L1 */ + {0x416, "L1xxx6(8/B)" , 0x20000800, 0x20004000, 0x08000000, 0x08020000, 16, 256, 0x1FF80000, 0x1FF8000F, 0x1FF00000, 0x1FF01000}, + {0x429, "L1xxx6(8/B)A" , 0x20001000, 0x20008000, 0x08000000, 0x08020000, 16, 256, 0x1FF80000, 0x1FF8000F, 0x1FF00000, 0x1FF01000}, + {0x427, "L1xxxC" , 0x20001000, 0x20008000, 0x08000000, 0x08020000, 16, 256, 0x1FF80000, 0x1FF8000F, 0x1FF00000, 0x1FF02000}, + {0x436, "L1xxxD" , 0x20001000, 0x2000C000, 0x08000000, 0x08060000, 16, 256, 0x1ff80000, 0x1ff8000F, 0x1FF00000, 0x1FF02000}, + {0x437, "L1xxxE" , 0x20001000, 0x20014000, 0x08000000, 0x08060000, 16, 256, 0x1ff80000, 0x1ff8000F, 0x1FF00000, 0x1FF02000}, + /* These are not (yet) in AN2606: */ + {0x641, "Medium_Density PL" , 0x20000200, 0x00005000, 0x08000000, 0x08020000, 4, 1024, 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800}, + {0x9a8, "STM32W-128K" , 0x20000200, 0x20002000, 0x08000000, 0x08020000, 1, 1024, 0, 0, 0, 0}, + {0x9b0, "STM32W-256K" , 0x20000200, 0x20004000, 0x08000000, 0x08040000, 1, 2048, 0, 0, 0, 0}, + {0x0} +}; diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/gpl-2.0.txt b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/gpl-2.0.txt new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/gpl-2.0.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/i2c.c b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/i2c.c new file mode 100644 index 0000000..10e6bb1 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/i2c.c @@ -0,0 +1,209 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2014 Antonio Borneo + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "serial.h" +#include "port.h" + + +#if !defined(__linux__) + +static port_err_t i2c_open(struct port_interface *port, + struct port_options *ops) +{ + return PORT_ERR_NODEV; +} + +struct port_interface port_i2c = { + .name = "i2c", + .open = i2c_open, +}; + +#else + +#ifdef __ANDROID__ +#define I2C_SLAVE 0x0703 /* Use this slave address */ +#define I2C_FUNCS 0x0705 /* Get the adapter functionality mask */ +/* To determine what functionality is present */ +#define I2C_FUNC_I2C 0x00000001 +#else +#include +#include +#endif + +#include + +struct i2c_priv { + int fd; + int addr; +}; + +static port_err_t i2c_open(struct port_interface *port, + struct port_options *ops) +{ + struct i2c_priv *h; + int fd, addr, ret; + unsigned long funcs; + + /* 1. check device name match */ + if (strncmp(ops->device, "/dev/i2c-", strlen("/dev/i2c-"))) + return PORT_ERR_NODEV; + + /* 2. check options */ + addr = ops->bus_addr; + if (addr < 0x03 || addr > 0x77) { + fprintf(stderr, "I2C address out of range [0x03-0x77]\n"); + return PORT_ERR_UNKNOWN; + } + + /* 3. open it */ + h = calloc(sizeof(*h), 1); + if (h == NULL) { + fprintf(stderr, "End of memory\n"); + return PORT_ERR_UNKNOWN; + } + fd = open(ops->device, O_RDWR); + if (fd < 0) { + fprintf(stderr, "Unable to open special file \"%s\"\n", + ops->device); + free(h); + return PORT_ERR_UNKNOWN; + } + + /* 3.5. Check capabilities */ + ret = ioctl(fd, I2C_FUNCS, &funcs); + if (ret < 0) { + fprintf(stderr, "I2C ioctl(funcs) error %d\n", errno); + close(fd); + free(h); + return PORT_ERR_UNKNOWN; + } + if ((funcs & I2C_FUNC_I2C) == 0) { + fprintf(stderr, "Error: controller is not I2C, only SMBUS.\n"); + close(fd); + free(h); + return PORT_ERR_UNKNOWN; + } + + /* 4. set options */ + ret = ioctl(fd, I2C_SLAVE, addr); + if (ret < 0) { + fprintf(stderr, "I2C ioctl(slave) error %d\n", errno); + close(fd); + free(h); + return PORT_ERR_UNKNOWN; + } + + h->fd = fd; + h->addr = addr; + port->private = h; + return PORT_ERR_OK; +} + +static port_err_t i2c_close(struct port_interface *port) +{ + struct i2c_priv *h; + + h = (struct i2c_priv *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + close(h->fd); + free(h); + port->private = NULL; + return PORT_ERR_OK; +} + +static port_err_t i2c_read(struct port_interface *port, void *buf, + size_t nbyte) +{ + struct i2c_priv *h; + int ret; + + h = (struct i2c_priv *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + ret = read(h->fd, buf, nbyte); + if (ret != nbyte) + return PORT_ERR_UNKNOWN; + return PORT_ERR_OK; +} + +static port_err_t i2c_write(struct port_interface *port, void *buf, + size_t nbyte) +{ + struct i2c_priv *h; + int ret; + + h = (struct i2c_priv *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + ret = write(h->fd, buf, nbyte); + if (ret != nbyte) + return PORT_ERR_UNKNOWN; + return PORT_ERR_OK; +} + +static port_err_t i2c_gpio(struct port_interface *port, serial_gpio_t n, + int level) +{ + return PORT_ERR_OK; +} + +static const char *i2c_get_cfg_str(struct port_interface *port) +{ + struct i2c_priv *h; + static char str[11]; + + h = (struct i2c_priv *)port->private; + if (h == NULL) + return "INVALID"; + snprintf(str, sizeof(str), "addr 0x%2x", h->addr); + return str; +} + +static struct varlen_cmd i2c_cmd_get_reply[] = { + {0x10, 11}, + {0x11, 17}, + {0x12, 18}, + { /* sentinel */ } +}; + +struct port_interface port_i2c = { + .name = "i2c", + .flags = PORT_STRETCH_W, + .open = i2c_open, + .close = i2c_close, + .read = i2c_read, + .write = i2c_write, + .gpio = i2c_gpio, + .cmd_get_reply = i2c_cmd_get_reply, + .get_cfg_str = i2c_get_cfg_str, +}; + +#endif diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/init.c b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/init.c new file mode 100644 index 0000000..77a571b --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/init.c @@ -0,0 +1,219 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + Copyright (C) 2013 Antonio Borneo + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include "init.h" +#include "serial.h" +#include "stm32.h" +#include "port.h" + +struct gpio_list { + struct gpio_list *next; + int gpio; +}; + + +static int write_to(const char *filename, const char *value) +{ + int fd, ret; + + fd = open(filename, O_WRONLY); + if (fd < 0) { + fprintf(stderr, "Cannot open file \"%s\"\n", filename); + return 0; + } + ret = write(fd, value, strlen(value)); + if (ret < 0) { + fprintf(stderr, "Error writing in file \"%s\"\n", filename); + close(fd); + return 0; + } + close(fd); + return 1; +} + +#if !defined(__linux__) +static int drive_gpio(int n, int level, struct gpio_list **gpio_to_release) +{ + fprintf(stderr, "GPIO control only available in Linux\n"); + return 0; +} +#else +static int drive_gpio(int n, int level, struct gpio_list **gpio_to_release) +{ + char num[16]; /* sized to carry MAX_INT */ + char file[48]; /* sized to carry longest filename */ + struct stat buf; + struct gpio_list *new; + int ret; + + sprintf(file, "/sys/class/gpio/gpio%d/direction", n); + ret = stat(file, &buf); + if (ret) { + /* file miss, GPIO not exported yet */ + sprintf(num, "%d", n); + ret = write_to("/sys/class/gpio/export", num); + if (!ret) + return 0; + ret = stat(file, &buf); + if (ret) { + fprintf(stderr, "GPIO %d not available\n", n); + return 0; + } + new = (struct gpio_list *)malloc(sizeof(struct gpio_list)); + if (new == NULL) { + fprintf(stderr, "Out of memory\n"); + return 0; + } + new->gpio = n; + new->next = *gpio_to_release; + *gpio_to_release = new; + } + + return write_to(file, level ? "high" : "low"); +} +#endif + +static int release_gpio(int n) +{ + char num[16]; /* sized to carry MAX_INT */ + + sprintf(num, "%d", n); + return write_to("/sys/class/gpio/unexport", num); +} + +static int gpio_sequence(struct port_interface *port, const char *s, size_t l) +{ + struct gpio_list *gpio_to_release = NULL, *to_free; + int ret, level, gpio; + + ret = 1; + while (ret == 1 && *s && l > 0) { + if (*s == '-') { + level = 0; + s++; + l--; + } else + level = 1; + + if (isdigit(*s)) { + gpio = atoi(s); + while (isdigit(*s)) { + s++; + l--; + } + } else if (!strncmp(s, "rts", 3)) { + gpio = -GPIO_RTS; + s += 3; + l -= 3; + } else if (!strncmp(s, "dtr", 3)) { + gpio = -GPIO_DTR; + s += 3; + l -= 3; + } else if (!strncmp(s, "brk", 3)) { + gpio = -GPIO_BRK; + s += 3; + l -= 3; + } else { + fprintf(stderr, "Character \'%c\' is not a digit\n", *s); + ret = 0; + break; + } + + if (*s && (l > 0)) { + if (*s == ',') { + s++; + l--; + } else { + fprintf(stderr, "Character \'%c\' is not a separator\n", *s); + ret = 0; + break; + } + } + if (gpio < 0) + ret = (port->gpio(port, -gpio, level) == PORT_ERR_OK); + else + ret = drive_gpio(gpio, level, &gpio_to_release); + usleep(100000); + } + + while (gpio_to_release) { + release_gpio(gpio_to_release->gpio); + to_free = gpio_to_release; + gpio_to_release = gpio_to_release->next; + free(to_free); + } + usleep(500000); + return ret; +} + +static int gpio_bl_entry(struct port_interface *port, const char *seq) +{ + char *s; + + if (seq == NULL || seq[0] == ':') + return 1; + + s = strchr(seq, ':'); + if (s == NULL) + return gpio_sequence(port, seq, strlen(seq)); + + return gpio_sequence(port, seq, s - seq); +} + +static int gpio_bl_exit(struct port_interface *port, const char *seq) +{ + char *s; + + if (seq == NULL) + return 1; + + s = strchr(seq, ':'); + if (s == NULL || s[1] == '\0') + return 1; + + return gpio_sequence(port, s + 1, strlen(s + 1)); +} + +int init_bl_entry(struct port_interface *port, const char *seq) +{ + if (seq) + return gpio_bl_entry(port, seq); + + return 1; +} + +int init_bl_exit(stm32_t *stm, struct port_interface *port, const char *seq) +{ + if (seq) + return gpio_bl_exit(port, seq); + + if (stm32_reset_device(stm) != STM32_ERR_OK) + return 0; + return 1; +} diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/init.h b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/init.h new file mode 100644 index 0000000..6075b51 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/init.h @@ -0,0 +1,31 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + Copyright (C) 2013 Antonio Borneo + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _INIT_H +#define _INIT_H + +#include "stm32.h" +#include "port.h" + +int init_bl_entry(struct port_interface *port, const char *seq); +int init_bl_exit(stm32_t *stm, struct port_interface *port, const char *seq); + +#endif diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/main.c b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/main.c new file mode 100644 index 0000000..f081d61 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/main.c @@ -0,0 +1,774 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright 2010 Geoffrey McRae + Copyright 2011 Steve Markgraf + Copyright 2012 Tormod Volden + Copyright 2013 Antonio Borneo + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "init.h" +#include "utils.h" +#include "serial.h" +#include "stm32.h" +#include "parsers/parser.h" +#include "port.h" + +#include "parsers/binary.h" +#include "parsers/hex.h" + +#define VERSION "Arduino_STM32_0.9" + +/* device globals */ +stm32_t *stm = NULL; + +void *p_st = NULL; +parser_t *parser = NULL; + +/* settings */ +struct port_options port_opts = { + .device = NULL, + .baudRate = SERIAL_BAUD_57600, + .serial_mode = "8e1", + .bus_addr = 0, + .rx_frame_max = STM32_MAX_RX_FRAME, + .tx_frame_max = STM32_MAX_TX_FRAME, +}; +int rd = 0; +int wr = 0; +int wu = 0; +int rp = 0; +int ur = 0; +int eraseOnly = 0; +int crc = 0; +int npages = 0; +int spage = 0; +int no_erase = 0; +char verify = 0; +int retry = 10; +char exec_flag = 0; +uint32_t execute = 0; +char init_flag = 1; +char force_binary = 0; +char reset_flag = 0; +char *filename; +char *gpio_seq = NULL; +uint32_t start_addr = 0; +uint32_t readwrite_len = 0; + +/* functions */ +int parse_options(int argc, char *argv[]); +void show_help(char *name); + +static int is_addr_in_ram(uint32_t addr) +{ + return addr >= stm->dev->ram_start && addr < stm->dev->ram_end; +} + +static int is_addr_in_flash(uint32_t addr) +{ + return addr >= stm->dev->fl_start && addr < stm->dev->fl_end; +} + +static int flash_addr_to_page_floor(uint32_t addr) +{ + if (!is_addr_in_flash(addr)) + return 0; + + return (addr - stm->dev->fl_start) / stm->dev->fl_ps; +} + +static int flash_addr_to_page_ceil(uint32_t addr) +{ + if (!(addr >= stm->dev->fl_start && addr <= stm->dev->fl_end)) + return 0; + + return (addr + stm->dev->fl_ps - 1 - stm->dev->fl_start) + / stm->dev->fl_ps; +} + +static uint32_t flash_page_to_addr(int page) +{ + return stm->dev->fl_start + page * stm->dev->fl_ps; +} + +int main(int argc, char* argv[]) { + struct port_interface *port = NULL; + int ret = 1; + stm32_err_t s_err; + parser_err_t perr; + FILE *diag = stdout; + + fprintf(diag, "stm32flash " VERSION "\n\n"); + fprintf(diag, "http://github.com/rogerclarkmelbourne/arduino_stm32\n\n"); + if (parse_options(argc, argv) != 0) + goto close; + + if (rd && filename[0] == '-') { + diag = stderr; + } + + if (wr) { + /* first try hex */ + if (!force_binary) { + parser = &PARSER_HEX; + p_st = parser->init(); + if (!p_st) { + fprintf(stderr, "%s Parser failed to initialize\n", parser->name); + goto close; + } + } + + if (force_binary || (perr = parser->open(p_st, filename, 0)) != PARSER_ERR_OK) { + if (force_binary || perr == PARSER_ERR_INVALID_FILE) { + if (!force_binary) { + parser->close(p_st); + p_st = NULL; + } + + /* now try binary */ + parser = &PARSER_BINARY; + p_st = parser->init(); + if (!p_st) { + fprintf(stderr, "%s Parser failed to initialize\n", parser->name); + goto close; + } + perr = parser->open(p_st, filename, 0); + } + + /* if still have an error, fail */ + if (perr != PARSER_ERR_OK) { + fprintf(stderr, "%s ERROR: %s\n", parser->name, parser_errstr(perr)); + if (perr == PARSER_ERR_SYSTEM) perror(filename); + goto close; + } + } + + fprintf(diag, "Using Parser : %s\n", parser->name); + } else { + parser = &PARSER_BINARY; + p_st = parser->init(); + if (!p_st) { + fprintf(stderr, "%s Parser failed to initialize\n", parser->name); + goto close; + } + } + + if (port_open(&port_opts, &port) != PORT_ERR_OK) { + fprintf(stderr, "Failed to open port: %s\n", port_opts.device); + goto close; + } + + fprintf(diag, "Interface %s: %s\n", port->name, port->get_cfg_str(port)); + if (init_flag && init_bl_entry(port, gpio_seq) == 0) + goto close; + stm = stm32_init(port, init_flag); + if (!stm) + goto close; + + fprintf(diag, "Version : 0x%02x\n", stm->bl_version); + if (port->flags & PORT_GVR_ETX) { + fprintf(diag, "Option 1 : 0x%02x\n", stm->option1); + fprintf(diag, "Option 2 : 0x%02x\n", stm->option2); + } + fprintf(diag, "Device ID : 0x%04x (%s)\n", stm->pid, stm->dev->name); + fprintf(diag, "- RAM : %dKiB (%db reserved by bootloader)\n", (stm->dev->ram_end - 0x20000000) / 1024, stm->dev->ram_start - 0x20000000); + fprintf(diag, "- Flash : %dKiB (sector size: %dx%d)\n", (stm->dev->fl_end - stm->dev->fl_start ) / 1024, stm->dev->fl_pps, stm->dev->fl_ps); + fprintf(diag, "- Option RAM : %db\n", stm->dev->opt_end - stm->dev->opt_start + 1); + fprintf(diag, "- System RAM : %dKiB\n", (stm->dev->mem_end - stm->dev->mem_start) / 1024); + + uint8_t buffer[256]; + uint32_t addr, start, end; + unsigned int len; + int failed = 0; + int first_page, num_pages; + + /* + * Cleanup addresses: + * + * Starting from options + * start_addr, readwrite_len, spage, npages + * and using device memory size, compute + * start, end, first_page, num_pages + */ + if (start_addr || readwrite_len) { + start = start_addr; + + if (is_addr_in_flash(start)) + end = stm->dev->fl_end; + else { + no_erase = 1; + if (is_addr_in_ram(start)) + end = stm->dev->ram_end; + else + end = start + sizeof(uint32_t); + } + + if (readwrite_len && (end > start + readwrite_len)) + end = start + readwrite_len; + + first_page = flash_addr_to_page_floor(start); + if (!first_page && end == stm->dev->fl_end) + num_pages = 0xff; /* mass erase */ + else + num_pages = flash_addr_to_page_ceil(end) - first_page; + } else if (!spage && !npages) { + start = stm->dev->fl_start; + end = stm->dev->fl_end; + first_page = 0; + num_pages = 0xff; /* mass erase */ + } else { + first_page = spage; + start = flash_page_to_addr(first_page); + if (start > stm->dev->fl_end) { + fprintf(stderr, "Address range exceeds flash size.\n"); + goto close; + } + + if (npages) { + num_pages = npages; + end = flash_page_to_addr(first_page + num_pages); + if (end > stm->dev->fl_end) + end = stm->dev->fl_end; + } else { + end = stm->dev->fl_end; + num_pages = flash_addr_to_page_ceil(end) - first_page; + } + + if (!first_page && end == stm->dev->fl_end) + num_pages = 0xff; /* mass erase */ + } + + if (rd) { + unsigned int max_len = port_opts.rx_frame_max; + + fprintf(diag, "Memory read\n"); + + perr = parser->open(p_st, filename, 1); + if (perr != PARSER_ERR_OK) { + fprintf(stderr, "%s ERROR: %s\n", parser->name, parser_errstr(perr)); + if (perr == PARSER_ERR_SYSTEM) + perror(filename); + goto close; + } + + fflush(diag); + addr = start; + while(addr < end) { + uint32_t left = end - addr; + len = max_len > left ? left : max_len; + s_err = stm32_read_memory(stm, addr, buffer, len); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Failed to read memory at address 0x%08x, target write-protected?\n", addr); + goto close; + } + if (parser->write(p_st, buffer, len) != PARSER_ERR_OK) + { + fprintf(stderr, "Failed to write data to file\n"); + goto close; + } + addr += len; + + fprintf(diag, + "\rRead address 0x%08x (%.2f%%) ", + addr, + (100.0f / (float)(end - start)) * (float)(addr - start) + ); + fflush(diag); + } + fprintf(diag, "Done.\n"); + ret = 0; + goto close; + } else if (rp) { + fprintf(stdout, "Read-Protecting flash\n"); + /* the device automatically performs a reset after the sending the ACK */ + reset_flag = 0; + stm32_readprot_memory(stm); + fprintf(stdout, "Done.\n"); + } else if (ur) { + fprintf(stdout, "Read-UnProtecting flash\n"); + /* the device automatically performs a reset after the sending the ACK */ + reset_flag = 0; + stm32_runprot_memory(stm); + fprintf(stdout, "Done.\n"); + } else if (eraseOnly) { + ret = 0; + fprintf(stdout, "Erasing flash\n"); + + if (num_pages != 0xff && + (start != flash_page_to_addr(first_page) + || end != flash_page_to_addr(first_page + num_pages))) { + fprintf(stderr, "Specified start & length are invalid (must be page aligned)\n"); + ret = 1; + goto close; + } + + s_err = stm32_erase_memory(stm, first_page, num_pages); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Failed to erase memory\n"); + ret = 1; + goto close; + } + } else if (wu) { + fprintf(diag, "Write-unprotecting flash\n"); + /* the device automatically performs a reset after the sending the ACK */ + reset_flag = 0; + stm32_wunprot_memory(stm); + fprintf(diag, "Done.\n"); + + } else if (wr) { + fprintf(diag, "Write to memory\n"); + + off_t offset = 0; + ssize_t r; + unsigned int size; + unsigned int max_wlen, max_rlen; + + max_wlen = port_opts.tx_frame_max - 2; /* skip len and crc */ + max_wlen &= ~3; /* 32 bit aligned */ + + max_rlen = port_opts.rx_frame_max; + max_rlen = max_rlen < max_wlen ? max_rlen : max_wlen; + + /* Assume data from stdin is whole device */ + if (filename[0] == '-' && filename[1] == '\0') + size = end - start; + else + size = parser->size(p_st); + + // TODO: It is possible to write to non-page boundaries, by reading out flash + // from partial pages and combining with the input data + // if ((start % stm->dev->fl_ps) != 0 || (end % stm->dev->fl_ps) != 0) { + // fprintf(stderr, "Specified start & length are invalid (must be page aligned)\n"); + // goto close; + // } + + // TODO: If writes are not page aligned, we should probably read out existing flash + // contents first, so it can be preserved and combined with new data + if (!no_erase && num_pages) { + fprintf(diag, "Erasing memory\n"); + s_err = stm32_erase_memory(stm, first_page, num_pages); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Failed to erase memory\n"); + goto close; + } + } + + fflush(diag); + addr = start; + while(addr < end && offset < size) { + uint32_t left = end - addr; + len = max_wlen > left ? left : max_wlen; + len = len > size - offset ? size - offset : len; + + if (parser->read(p_st, buffer, &len) != PARSER_ERR_OK) + goto close; + + if (len == 0) { + if (filename[0] == '-') { + break; + } else { + fprintf(stderr, "Failed to read input file\n"); + goto close; + } + } + + again: + s_err = stm32_write_memory(stm, addr, buffer, len); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Failed to write memory at address 0x%08x\n", addr); + goto close; + } + + if (verify) { + uint8_t compare[len]; + unsigned int offset, rlen; + + offset = 0; + while (offset < len) { + rlen = len - offset; + rlen = rlen < max_rlen ? rlen : max_rlen; + s_err = stm32_read_memory(stm, addr + offset, compare + offset, rlen); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Failed to read memory at address 0x%08x\n", addr + offset); + goto close; + } + offset += rlen; + } + + for(r = 0; r < len; ++r) + if (buffer[r] != compare[r]) { + if (failed == retry) { + fprintf(stderr, "Failed to verify at address 0x%08x, expected 0x%02x and found 0x%02x\n", + (uint32_t)(addr + r), + buffer [r], + compare[r] + ); + goto close; + } + ++failed; + goto again; + } + + failed = 0; + } + + addr += len; + offset += len; + + fprintf(diag, + "\rWrote %saddress 0x%08x (%.2f%%) ", + verify ? "and verified " : "", + addr, + (100.0f / size) * offset + ); + fflush(diag); + + } + + fprintf(diag, "Done.\n"); + ret = 0; + goto close; + } else if (crc) { + uint32_t crc_val = 0; + + fprintf(diag, "CRC computation\n"); + + s_err = stm32_crc_wrapper(stm, start, end - start, &crc_val); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Failed to read CRC\n"); + goto close; + } + fprintf(diag, "CRC(0x%08x-0x%08x) = 0x%08x\n", start, end, + crc_val); + ret = 0; + goto close; + } else + ret = 0; + +close: + if (stm && exec_flag && ret == 0) { + if (execute == 0) + execute = stm->dev->fl_start; + + fprintf(diag, "\nStarting execution at address 0x%08x... ", execute); + fflush(diag); + if (stm32_go(stm, execute) == STM32_ERR_OK) { + reset_flag = 0; + fprintf(diag, "done.\n"); + } else + fprintf(diag, "failed.\n"); + } + + if (stm && reset_flag) { + fprintf(diag, "\nResetting device... "); + fflush(diag); + if (init_bl_exit(stm, port, gpio_seq)) + fprintf(diag, "done.\n"); + else fprintf(diag, "failed.\n"); + } + + if (p_st ) parser->close(p_st); + if (stm ) stm32_close (stm); + if (port) + port->close(port); + + fprintf(diag, "\n"); + return ret; +} + +int parse_options(int argc, char *argv[]) +{ + int c; + char *pLen; + + while ((c = getopt(argc, argv, "a:b:m:r:w:e:vn:g:jkfcChuos:S:F:i:R")) != -1) { + switch(c) { + case 'a': + port_opts.bus_addr = strtoul(optarg, NULL, 0); + break; + + case 'b': + port_opts.baudRate = serial_get_baud(strtoul(optarg, NULL, 0)); + if (port_opts.baudRate == SERIAL_BAUD_INVALID) { + serial_baud_t baudrate; + fprintf(stderr, "Invalid baud rate, valid options are:\n"); + for (baudrate = SERIAL_BAUD_1200; baudrate != SERIAL_BAUD_INVALID; ++baudrate) + fprintf(stderr, " %d\n", serial_get_baud_int(baudrate)); + return 1; + } + break; + + case 'm': + if (strlen(optarg) != 3 + || serial_get_bits(optarg) == SERIAL_BITS_INVALID + || serial_get_parity(optarg) == SERIAL_PARITY_INVALID + || serial_get_stopbit(optarg) == SERIAL_STOPBIT_INVALID) { + fprintf(stderr, "Invalid serial mode\n"); + return 1; + } + port_opts.serial_mode = optarg; + break; + + case 'r': + case 'w': + rd = rd || c == 'r'; + wr = wr || c == 'w'; + if (rd && wr) { + fprintf(stderr, "ERROR: Invalid options, can't read & write at the same time\n"); + return 1; + } + filename = optarg; + if (filename[0] == '-') { + force_binary = 1; + } + break; + case 'e': + if (readwrite_len || start_addr) { + fprintf(stderr, "ERROR: Invalid options, can't specify start page / num pages and start address/length\n"); + return 1; + } + npages = strtoul(optarg, NULL, 0); + if (npages > 0xFF || npages < 0) { + fprintf(stderr, "ERROR: You need to specify a page count between 0 and 255"); + return 1; + } + if (!npages) + no_erase = 1; + break; + case 'u': + wu = 1; + if (rd || wr) { + fprintf(stderr, "ERROR: Invalid options, can't write unprotect and read/write at the same time\n"); + return 1; + } + break; + + case 'j': + rp = 1; + if (rd || wr) { + fprintf(stderr, "ERROR: Invalid options, can't read protect and read/write at the same time\n"); + return 1; + } + break; + + case 'k': + ur = 1; + if (rd || wr) { + fprintf(stderr, "ERROR: Invalid options, can't read unprotect and read/write at the same time\n"); + return 1; + } + break; + + case 'o': + eraseOnly = 1; + if (rd || wr) { + fprintf(stderr, "ERROR: Invalid options, can't erase-only and read/write at the same time\n"); + return 1; + } + break; + + case 'v': + verify = 1; + break; + + case 'n': + retry = strtoul(optarg, NULL, 0); + break; + + case 'g': + exec_flag = 1; + execute = strtoul(optarg, NULL, 0); + if (execute % 4 != 0) { + fprintf(stderr, "ERROR: Execution address must be word-aligned\n"); + return 1; + } + break; + case 's': + if (readwrite_len || start_addr) { + fprintf(stderr, "ERROR: Invalid options, can't specify start page / num pages and start address/length\n"); + return 1; + } + spage = strtoul(optarg, NULL, 0); + break; + case 'S': + if (spage || npages) { + fprintf(stderr, "ERROR: Invalid options, can't specify start page / num pages and start address/length\n"); + return 1; + } else { + start_addr = strtoul(optarg, &pLen, 0); + if (*pLen == ':') { + pLen++; + readwrite_len = strtoul(pLen, NULL, 0); + if (readwrite_len == 0) { + fprintf(stderr, "ERROR: Invalid options, can't specify zero length\n"); + return 1; + } + } + } + break; + case 'F': + port_opts.rx_frame_max = strtoul(optarg, &pLen, 0); + if (*pLen == ':') { + pLen++; + port_opts.tx_frame_max = strtoul(pLen, NULL, 0); + } + if (port_opts.rx_frame_max < 0 + || port_opts.tx_frame_max < 0) { + fprintf(stderr, "ERROR: Invalid negative value for option -F\n"); + return 1; + } + if (port_opts.rx_frame_max == 0) + port_opts.rx_frame_max = STM32_MAX_RX_FRAME; + if (port_opts.tx_frame_max == 0) + port_opts.tx_frame_max = STM32_MAX_TX_FRAME; + if (port_opts.rx_frame_max < 20 + || port_opts.tx_frame_max < 5) { + fprintf(stderr, "ERROR: current code cannot work with small frames.\n"); + fprintf(stderr, "min(RX) = 20, min(TX) = 5\n"); + return 1; + } + if (port_opts.rx_frame_max > STM32_MAX_RX_FRAME) { + fprintf(stderr, "WARNING: Ignore RX length in option -F\n"); + port_opts.rx_frame_max = STM32_MAX_RX_FRAME; + } + if (port_opts.tx_frame_max > STM32_MAX_TX_FRAME) { + fprintf(stderr, "WARNING: Ignore TX length in option -F\n"); + port_opts.tx_frame_max = STM32_MAX_TX_FRAME; + } + break; + case 'f': + force_binary = 1; + break; + + case 'c': + init_flag = 0; + break; + + case 'h': + show_help(argv[0]); + exit(0); + + case 'i': + gpio_seq = optarg; + break; + + case 'R': + reset_flag = 1; + break; + + case 'C': + crc = 1; + break; + } + } + + for (c = optind; c < argc; ++c) { + if (port_opts.device) { + fprintf(stderr, "ERROR: Invalid parameter specified\n"); + show_help(argv[0]); + return 1; + } + port_opts.device = argv[c]; + } + + if (port_opts.device == NULL) { + fprintf(stderr, "ERROR: Device not specified\n"); + show_help(argv[0]); + return 1; + } + + if (!wr && verify) { + fprintf(stderr, "ERROR: Invalid usage, -v is only valid when writing\n"); + show_help(argv[0]); + return 1; + } + + return 0; +} + +void show_help(char *name) { + fprintf(stderr, + "Usage: %s [-bvngfhc] [-[rw] filename] [tty_device | i2c_device]\n" + " -a bus_address Bus address (e.g. for I2C port)\n" + " -b rate Baud rate (default 57600)\n" + " -m mode Serial port mode (default 8e1)\n" + " -r filename Read flash to file (or - stdout)\n" + " -w filename Write flash from file (or - stdout)\n" + " -C Compute CRC of flash content\n" + " -u Disable the flash write-protection\n" + " -j Enable the flash read-protection\n" + " -k Disable the flash read-protection\n" + " -o Erase only\n" + " -e n Only erase n pages before writing the flash\n" + " -v Verify writes\n" + " -n count Retry failed writes up to count times (default 10)\n" + " -g address Start execution at specified address (0 = flash start)\n" + " -S address[:length] Specify start address and optionally length for\n" + " read/write/erase operations\n" + " -F RX_length[:TX_length] Specify the max length of RX and TX frame\n" + " -s start_page Flash at specified page (0 = flash start)\n" + " -f Force binary parser\n" + " -h Show this help\n" + " -c Resume the connection (don't send initial INIT)\n" + " *Baud rate must be kept the same as the first init*\n" + " This is useful if the reset fails\n" + " -i GPIO_string GPIO sequence to enter/exit bootloader mode\n" + " GPIO_string=[entry_seq][:[exit_seq]]\n" + " sequence=[-]n[,sequence]\n" + " -R Reset device at exit.\n" + "\n" + "Examples:\n" + " Get device information:\n" + " %s /dev/ttyS0\n" + " or:\n" + " %s /dev/i2c-0\n" + "\n" + " Write with verify and then start execution:\n" + " %s -w filename -v -g 0x0 /dev/ttyS0\n" + "\n" + " Read flash to file:\n" + " %s -r filename /dev/ttyS0\n" + "\n" + " Read 100 bytes of flash from 0x1000 to stdout:\n" + " %s -r - -S 0x1000:100 /dev/ttyS0\n" + "\n" + " Start execution:\n" + " %s -g 0x0 /dev/ttyS0\n" + "\n" + " GPIO sequence:\n" + " - entry sequence: GPIO_3=low, GPIO_2=low, GPIO_2=high\n" + " - exit sequence: GPIO_3=high, GPIO_2=low, GPIO_2=high\n" + " %s -i -3,-2,2:3,-2,2 /dev/ttyS0\n", + name, + name, + name, + name, + name, + name, + name, + name + ); +} + diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/parsers/Android.mk b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/parsers/Android.mk new file mode 100644 index 0000000..afec18c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/parsers/Android.mk @@ -0,0 +1,6 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := libparsers +LOCAL_SRC_FILES := binary.c hex.c +include $(BUILD_STATIC_LIBRARY) diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/parsers/Makefile b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/parsers/Makefile new file mode 100644 index 0000000..bb7df1e --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/parsers/Makefile @@ -0,0 +1,12 @@ + +CFLAGS += -Wall -g + +all: parsers.a + +parsers.a: binary.o hex.o + $(AR) rc $@ binary.o hex.o + +clean: + rm -f *.o parsers.a + +.PHONY: all clean diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/parsers/binary.c b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/parsers/binary.c new file mode 100644 index 0000000..f491952 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/parsers/binary.c @@ -0,0 +1,140 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#include +#include +#include +#include +#include + +#include "binary.h" + +typedef struct { + int fd; + char write; + struct stat stat; +} binary_t; + +void* binary_init() { + return calloc(sizeof(binary_t), 1); +} + +parser_err_t binary_open(void *storage, const char *filename, const char write) { + binary_t *st = storage; + if (write) { + if (filename[0] == '-') + st->fd = 1; + else + st->fd = open( + filename, +#ifndef __WIN32__ + O_WRONLY | O_CREAT | O_TRUNC, +#else + O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, +#endif +#ifndef __WIN32__ + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH +#else + 0 +#endif + ); + st->stat.st_size = 0; + } else { + if (filename[0] == '-') { + st->fd = 0; + } else { + if (stat(filename, &st->stat) != 0) + return PARSER_ERR_INVALID_FILE; + st->fd = open(filename, +#ifndef __WIN32__ + O_RDONLY +#else + O_RDONLY | O_BINARY +#endif + ); + } + } + + st->write = write; + return st->fd == -1 ? PARSER_ERR_SYSTEM : PARSER_ERR_OK; +} + +parser_err_t binary_close(void *storage) { + binary_t *st = storage; + + if (st->fd) close(st->fd); + free(st); + return PARSER_ERR_OK; +} + +unsigned int binary_size(void *storage) { + binary_t *st = storage; + return st->stat.st_size; +} + +parser_err_t binary_read(void *storage, void *data, unsigned int *len) { + binary_t *st = storage; + unsigned int left = *len; + if (st->write) return PARSER_ERR_WRONLY; + + ssize_t r; + while(left > 0) { + r = read(st->fd, data, left); + /* If there is no data to read at all, return OK, but with zero read */ + if (r == 0 && left == *len) { + *len = 0; + return PARSER_ERR_OK; + } + if (r <= 0) return PARSER_ERR_SYSTEM; + left -= r; + data += r; + } + + *len = *len - left; + return PARSER_ERR_OK; +} + +parser_err_t binary_write(void *storage, void *data, unsigned int len) { + binary_t *st = storage; + if (!st->write) return PARSER_ERR_RDONLY; + + ssize_t r; + while(len > 0) { + r = write(st->fd, data, len); + if (r < 1) return PARSER_ERR_SYSTEM; + st->stat.st_size += r; + + len -= r; + data += r; + } + + return PARSER_ERR_OK; +} + +parser_t PARSER_BINARY = { + "Raw BINARY", + binary_init, + binary_open, + binary_close, + binary_size, + binary_read, + binary_write +}; + diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/parsers/binary.h b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/parsers/binary.h new file mode 100644 index 0000000..d989acf --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/parsers/binary.h @@ -0,0 +1,27 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _PARSER_BINARY_H +#define _PARSER_BINARY_H + +#include "parser.h" + +extern parser_t PARSER_BINARY; +#endif diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/parsers/hex.c b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/parsers/hex.c new file mode 100644 index 0000000..3baf856 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/parsers/hex.c @@ -0,0 +1,224 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#include +#include +#include +#include +#include +#include +#include + +#include "hex.h" +#include "../utils.h" + +typedef struct { + size_t data_len, offset; + uint8_t *data; + uint8_t base; +} hex_t; + +void* hex_init() { + return calloc(sizeof(hex_t), 1); +} + +parser_err_t hex_open(void *storage, const char *filename, const char write) { + hex_t *st = storage; + if (write) { + return PARSER_ERR_RDONLY; + } else { + char mark; + int i, fd; + uint8_t checksum; + unsigned int c; + uint32_t base = 0; + unsigned int last_address = 0x0; + + fd = open(filename, O_RDONLY); + if (fd < 0) + return PARSER_ERR_SYSTEM; + + /* read in the file */ + + while(read(fd, &mark, 1) != 0) { + if (mark == '\n' || mark == '\r') continue; + if (mark != ':') + return PARSER_ERR_INVALID_FILE; + + char buffer[9]; + unsigned int reclen, address, type; + uint8_t *record = NULL; + + /* get the reclen, address, and type */ + buffer[8] = 0; + if (read(fd, &buffer, 8) != 8) return PARSER_ERR_INVALID_FILE; + if (sscanf(buffer, "%2x%4x%2x", &reclen, &address, &type) != 3) { + close(fd); + return PARSER_ERR_INVALID_FILE; + } + + /* setup the checksum */ + checksum = + reclen + + ((address & 0xFF00) >> 8) + + ((address & 0x00FF) >> 0) + + type; + + switch(type) { + /* data record */ + case 0: + c = address - last_address; + st->data = realloc(st->data, st->data_len + c + reclen); + + /* if there is a gap, set it to 0xff and increment the length */ + if (c > 0) { + memset(&st->data[st->data_len], 0xff, c); + st->data_len += c; + } + + last_address = address + reclen; + record = &st->data[st->data_len]; + st->data_len += reclen; + break; + + /* extended segment address record */ + case 2: + base = 0; + break; + + /* extended linear address record */ + case 4: + base = address; + break; + } + + buffer[2] = 0; + for(i = 0; i < reclen; ++i) { + if (read(fd, &buffer, 2) != 2 || sscanf(buffer, "%2x", &c) != 1) { + close(fd); + return PARSER_ERR_INVALID_FILE; + } + + /* add the byte to the checksum */ + checksum += c; + + switch(type) { + case 0: + if (record != NULL) { + record[i] = c; + } else { + return PARSER_ERR_INVALID_FILE; + } + break; + + case 2: + case 4: + base = (base << 8) | c; + break; + } + } + + /* read, scan, and verify the checksum */ + if ( + read(fd, &buffer, 2 ) != 2 || + sscanf(buffer, "%2x", &c) != 1 || + (uint8_t)(checksum + c) != 0x00 + ) { + close(fd); + return PARSER_ERR_INVALID_FILE; + } + + switch(type) { + /* EOF */ + case 1: + close(fd); + return PARSER_ERR_OK; + + /* address record */ + case 2: base = base << 4; + case 4: base = be_u32(base); + /* Reset last_address since our base changed */ + last_address = 0; + + if (st->base == 0) { + st->base = base; + break; + } + + /* we cant cope with files out of order */ + if (base < st->base) { + close(fd); + return PARSER_ERR_INVALID_FILE; + } + + /* if there is a gap, enlarge and fill with zeros */ + unsigned int len = base - st->base; + if (len > st->data_len) { + st->data = realloc(st->data, len); + memset(&st->data[st->data_len], 0, len - st->data_len); + st->data_len = len; + } + break; + } + } + + close(fd); + return PARSER_ERR_OK; + } +} + +parser_err_t hex_close(void *storage) { + hex_t *st = storage; + if (st) free(st->data); + free(st); + return PARSER_ERR_OK; +} + +unsigned int hex_size(void *storage) { + hex_t *st = storage; + return st->data_len; +} + +parser_err_t hex_read(void *storage, void *data, unsigned int *len) { + hex_t *st = storage; + unsigned int left = st->data_len - st->offset; + unsigned int get = left > *len ? *len : left; + + memcpy(data, &st->data[st->offset], get); + st->offset += get; + + *len = get; + return PARSER_ERR_OK; +} + +parser_err_t hex_write(void *storage, void *data, unsigned int len) { + return PARSER_ERR_RDONLY; +} + +parser_t PARSER_HEX = { + "Intel HEX", + hex_init, + hex_open, + hex_close, + hex_size, + hex_read, + hex_write +}; + diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/parsers/hex.h b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/parsers/hex.h new file mode 100644 index 0000000..02413c9 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/parsers/hex.h @@ -0,0 +1,27 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _PARSER_HEX_H +#define _PARSER_HEX_H + +#include "parser.h" + +extern parser_t PARSER_HEX; +#endif diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/parsers/parser.h b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/parsers/parser.h new file mode 100644 index 0000000..c2fae3c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/parsers/parser.h @@ -0,0 +1,56 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _H_PARSER +#define _H_PARSER + +enum parser_err { + PARSER_ERR_OK, + PARSER_ERR_SYSTEM, + PARSER_ERR_INVALID_FILE, + PARSER_ERR_WRONLY, + PARSER_ERR_RDONLY +}; +typedef enum parser_err parser_err_t; + +struct parser { + const char *name; + void* (*init )(); /* initialise the parser */ + parser_err_t (*open )(void *storage, const char *filename, const char write); /* open the file for read|write */ + parser_err_t (*close)(void *storage); /* close and free the parser */ + unsigned int (*size )(void *storage); /* get the total data size */ + parser_err_t (*read )(void *storage, void *data, unsigned int *len); /* read a block of data */ + parser_err_t (*write)(void *storage, void *data, unsigned int len); /* write a block of data */ +}; +typedef struct parser parser_t; + +static inline const char* parser_errstr(parser_err_t err) { + switch(err) { + case PARSER_ERR_OK : return "OK"; + case PARSER_ERR_SYSTEM : return "System Error"; + case PARSER_ERR_INVALID_FILE: return "Invalid File"; + case PARSER_ERR_WRONLY : return "Parser can only write"; + case PARSER_ERR_RDONLY : return "Parser can only read"; + default: + return "Unknown Error"; + } +} + +#endif diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/port.c b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/port.c new file mode 100644 index 0000000..08e58cc --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/port.c @@ -0,0 +1,59 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2014 Antonio Borneo + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include + +#include "serial.h" +#include "port.h" + + +extern struct port_interface port_serial; +extern struct port_interface port_i2c; + +static struct port_interface *ports[] = { + &port_serial, + &port_i2c, + NULL, +}; + + +port_err_t port_open(struct port_options *ops, struct port_interface **outport) +{ + int ret; + static struct port_interface **port; + + for (port = ports; *port; port++) { + ret = (*port)->open(*port, ops); + if (ret == PORT_ERR_NODEV) + continue; + if (ret == PORT_ERR_OK) + break; + fprintf(stderr, "Error probing interface \"%s\"\n", + (*port)->name); + } + if (*port == NULL) { + fprintf(stderr, "Cannot handle device \"%s\"\n", + ops->device); + return PORT_ERR_UNKNOWN; + } + + *outport = *port; + return PORT_ERR_OK; +} diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/port.h b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/port.h new file mode 100644 index 0000000..290f034 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/port.h @@ -0,0 +1,75 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2014 Antonio Borneo + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _H_PORT +#define _H_PORT + +typedef enum { + PORT_ERR_OK = 0, + PORT_ERR_NODEV, /* No such device */ + PORT_ERR_TIMEDOUT, /* Operation timed out */ + PORT_ERR_UNKNOWN, +} port_err_t; + +/* flags */ +#define PORT_BYTE (1 << 0) /* byte (not frame) oriented */ +#define PORT_GVR_ETX (1 << 1) /* cmd GVR returns protection status */ +#define PORT_CMD_INIT (1 << 2) /* use INIT cmd to autodetect speed */ +#define PORT_RETRY (1 << 3) /* allowed read() retry after timeout */ +#define PORT_STRETCH_W (1 << 4) /* warning for no-stretching commands */ + +/* all options and flags used to open and configure an interface */ +struct port_options { + const char *device; + serial_baud_t baudRate; + const char *serial_mode; + int bus_addr; + int rx_frame_max; + int tx_frame_max; +}; + +/* + * Specify the length of reply for command GET + * This is helpful for frame-oriented protocols, e.g. i2c, to avoid time + * consuming try-fail-timeout-retry operation. + * On byte-oriented protocols, i.e. UART, this information would be skipped + * after read the first byte, so not needed. + */ +struct varlen_cmd { + uint8_t version; + uint8_t length; +}; + +struct port_interface { + const char *name; + unsigned flags; + port_err_t (*open)(struct port_interface *port, struct port_options *ops); + port_err_t (*close)(struct port_interface *port); + port_err_t (*read)(struct port_interface *port, void *buf, size_t nbyte); + port_err_t (*write)(struct port_interface *port, void *buf, size_t nbyte); + port_err_t (*gpio)(struct port_interface *port, serial_gpio_t n, int level); + const char *(*get_cfg_str)(struct port_interface *port); + struct varlen_cmd *cmd_get_reply; + void *private; +}; + +port_err_t port_open(struct port_options *ops, struct port_interface **outport); + +#endif diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/protocol.txt b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/protocol.txt new file mode 100644 index 0000000..0391099 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/protocol.txt @@ -0,0 +1,19 @@ +The communication protocol used by ST bootloader is documented in following ST +application notes, depending on communication port. + +In current version of stm32flash are supported only UART and I2C ports. + +* AN3154: CAN protocol used in the STM32 bootloader + http://www.st.com/web/en/resource/technical/document/application_note/CD00264321.pdf + +* AN3155: USART protocol used in the STM32(TM) bootloader + http://www.st.com/web/en/resource/technical/document/application_note/CD00264342.pdf + +* AN4221: I2C protocol used in the STM32 bootloader + http://www.st.com/web/en/resource/technical/document/application_note/DM00072315.pdf + +* AN4286: SPI protocol used in the STM32 bootloader + http://www.st.com/web/en/resource/technical/document/application_note/DM00081379.pdf + +Boot mode selection for STM32 is documented in ST application note AN2606, available in ST website: + http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/serial.h b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/serial.h new file mode 100644 index 0000000..227ba16 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/serial.h @@ -0,0 +1,90 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _SERIAL_H +#define _SERIAL_H + +typedef struct serial serial_t; + +typedef enum { + SERIAL_PARITY_NONE, + SERIAL_PARITY_EVEN, + SERIAL_PARITY_ODD, + + SERIAL_PARITY_INVALID +} serial_parity_t; + +typedef enum { + SERIAL_BITS_5, + SERIAL_BITS_6, + SERIAL_BITS_7, + SERIAL_BITS_8, + + SERIAL_BITS_INVALID +} serial_bits_t; + +typedef enum { + SERIAL_BAUD_1200, + SERIAL_BAUD_1800, + SERIAL_BAUD_2400, + SERIAL_BAUD_4800, + SERIAL_BAUD_9600, + SERIAL_BAUD_19200, + SERIAL_BAUD_38400, + SERIAL_BAUD_57600, + SERIAL_BAUD_115200, + SERIAL_BAUD_128000, + SERIAL_BAUD_230400, + SERIAL_BAUD_256000, + SERIAL_BAUD_460800, + SERIAL_BAUD_500000, + SERIAL_BAUD_576000, + SERIAL_BAUD_921600, + SERIAL_BAUD_1000000, + SERIAL_BAUD_1500000, + SERIAL_BAUD_2000000, + + SERIAL_BAUD_INVALID +} serial_baud_t; + +typedef enum { + SERIAL_STOPBIT_1, + SERIAL_STOPBIT_2, + + SERIAL_STOPBIT_INVALID +} serial_stopbit_t; + +typedef enum { + GPIO_RTS = 1, + GPIO_DTR, + GPIO_BRK, +} serial_gpio_t; + +/* common helper functions */ +serial_baud_t serial_get_baud(const unsigned int baud); +unsigned int serial_get_baud_int(const serial_baud_t baud); +serial_bits_t serial_get_bits(const char *mode); +unsigned int serial_get_bits_int(const serial_bits_t bits); +serial_parity_t serial_get_parity(const char *mode); +char serial_get_parity_str(const serial_parity_t parity); +serial_stopbit_t serial_get_stopbit(const char *mode); +unsigned int serial_get_stopbit_int(const serial_stopbit_t stopbit); + +#endif diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/serial_common.c b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/serial_common.c new file mode 100644 index 0000000..43e48e1 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/serial_common.c @@ -0,0 +1,154 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "serial.h" + +serial_baud_t serial_get_baud(const unsigned int baud) { + switch(baud) { + case 1200: return SERIAL_BAUD_1200 ; + case 1800: return SERIAL_BAUD_1800 ; + case 2400: return SERIAL_BAUD_2400 ; + case 4800: return SERIAL_BAUD_4800 ; + case 9600: return SERIAL_BAUD_9600 ; + case 19200: return SERIAL_BAUD_19200 ; + case 38400: return SERIAL_BAUD_38400 ; + case 57600: return SERIAL_BAUD_57600 ; + case 115200: return SERIAL_BAUD_115200; + case 128000: return SERIAL_BAUD_128000; + case 230400: return SERIAL_BAUD_230400; + case 256000: return SERIAL_BAUD_256000; + case 460800: return SERIAL_BAUD_460800; + case 500000: return SERIAL_BAUD_500000; + case 576000: return SERIAL_BAUD_576000; + case 921600: return SERIAL_BAUD_921600; + case 1000000: return SERIAL_BAUD_1000000; + case 1500000: return SERIAL_BAUD_1500000; + case 2000000: return SERIAL_BAUD_2000000; + + default: + return SERIAL_BAUD_INVALID; + } +} + +unsigned int serial_get_baud_int(const serial_baud_t baud) { + switch(baud) { + case SERIAL_BAUD_1200 : return 1200 ; + case SERIAL_BAUD_1800 : return 1800 ; + case SERIAL_BAUD_2400 : return 2400 ; + case SERIAL_BAUD_4800 : return 4800 ; + case SERIAL_BAUD_9600 : return 9600 ; + case SERIAL_BAUD_19200 : return 19200 ; + case SERIAL_BAUD_38400 : return 38400 ; + case SERIAL_BAUD_57600 : return 57600 ; + case SERIAL_BAUD_115200: return 115200; + case SERIAL_BAUD_128000: return 128000; + case SERIAL_BAUD_230400: return 230400; + case SERIAL_BAUD_256000: return 256000; + case SERIAL_BAUD_460800: return 460800; + case SERIAL_BAUD_500000: return 500000; + case SERIAL_BAUD_576000: return 576000; + case SERIAL_BAUD_921600: return 921600; + case SERIAL_BAUD_1000000: return 1000000; + case SERIAL_BAUD_1500000: return 1500000; + case SERIAL_BAUD_2000000: return 2000000; + + case SERIAL_BAUD_INVALID: + default: + return 0; + } +} + +serial_bits_t serial_get_bits(const char *mode) { + if (!mode) + return SERIAL_BITS_INVALID; + switch(mode[0]) { + case '5': return SERIAL_BITS_5; + case '6': return SERIAL_BITS_6; + case '7': return SERIAL_BITS_7; + case '8': return SERIAL_BITS_8; + + default: + return SERIAL_BITS_INVALID; + } +} + +unsigned int serial_get_bits_int(const serial_bits_t bits) { + switch(bits) { + case SERIAL_BITS_5: return 5; + case SERIAL_BITS_6: return 6; + case SERIAL_BITS_7: return 7; + case SERIAL_BITS_8: return 8; + + default: + return 0; + } +} + +serial_parity_t serial_get_parity(const char *mode) { + if (!mode || !mode[0]) + return SERIAL_PARITY_INVALID; + switch(mode[1]) { + case 'N': + case 'n': + return SERIAL_PARITY_NONE; + case 'E': + case 'e': + return SERIAL_PARITY_EVEN; + case 'O': + case 'o': + return SERIAL_PARITY_ODD; + + default: + return SERIAL_PARITY_INVALID; + } +} + +char serial_get_parity_str(const serial_parity_t parity) { + switch(parity) { + case SERIAL_PARITY_NONE: return 'N'; + case SERIAL_PARITY_EVEN: return 'E'; + case SERIAL_PARITY_ODD : return 'O'; + + default: + return ' '; + } +} + +serial_stopbit_t serial_get_stopbit(const char *mode) { + if (!mode || !mode[0] || !mode[1]) + return SERIAL_STOPBIT_INVALID; + switch(mode[2]) { + case '1': return SERIAL_STOPBIT_1; + case '2': return SERIAL_STOPBIT_2; + + default: + return SERIAL_STOPBIT_INVALID; + } +} + +unsigned int serial_get_stopbit_int(const serial_stopbit_t stopbit) { + switch(stopbit) { + case SERIAL_STOPBIT_1: return 1; + case SERIAL_STOPBIT_2: return 2; + + default: + return 0; + } +} + diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/serial_platform.c b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/serial_platform.c new file mode 100644 index 0000000..98e2569 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/serial_platform.c @@ -0,0 +1,5 @@ +#if defined(__WIN32__) || defined(__CYGWIN__) +# include "serial_w32.c" +#else +# include "serial_posix.c" +#endif diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/serial_posix.c b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/serial_posix.c new file mode 100644 index 0000000..284b35b --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/serial_posix.c @@ -0,0 +1,395 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "serial.h" +#include "port.h" + +struct serial { + int fd; + struct termios oldtio; + struct termios newtio; + char setup_str[11]; +}; + +static serial_t *serial_open(const char *device) +{ + serial_t *h = calloc(sizeof(serial_t), 1); + + h->fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY); + if (h->fd < 0) { + free(h); + return NULL; + } + fcntl(h->fd, F_SETFL, 0); + + tcgetattr(h->fd, &h->oldtio); + tcgetattr(h->fd, &h->newtio); + + return h; +} + +static void serial_flush(const serial_t *h) +{ + tcflush(h->fd, TCIFLUSH); +} + +static void serial_close(serial_t *h) +{ + serial_flush(h); + tcsetattr(h->fd, TCSANOW, &h->oldtio); + close(h->fd); + free(h); +} + +static port_err_t serial_setup(serial_t *h, const serial_baud_t baud, + const serial_bits_t bits, + const serial_parity_t parity, + const serial_stopbit_t stopbit) +{ + speed_t port_baud; + tcflag_t port_bits; + tcflag_t port_parity; + tcflag_t port_stop; + struct termios settings; + + switch (baud) { + case SERIAL_BAUD_1200: port_baud = B1200; break; + case SERIAL_BAUD_1800: port_baud = B1800; break; + case SERIAL_BAUD_2400: port_baud = B2400; break; + case SERIAL_BAUD_4800: port_baud = B4800; break; + case SERIAL_BAUD_9600: port_baud = B9600; break; + case SERIAL_BAUD_19200: port_baud = B19200; break; + case SERIAL_BAUD_38400: port_baud = B38400; break; + case SERIAL_BAUD_57600: port_baud = B57600; break; + case SERIAL_BAUD_115200: port_baud = B115200; break; + case SERIAL_BAUD_230400: port_baud = B230400; break; +#ifdef B460800 + case SERIAL_BAUD_460800: port_baud = B460800; break; +#endif /* B460800 */ +#ifdef B921600 + case SERIAL_BAUD_921600: port_baud = B921600; break; +#endif /* B921600 */ +#ifdef B500000 + case SERIAL_BAUD_500000: port_baud = B500000; break; +#endif /* B500000 */ +#ifdef B576000 + case SERIAL_BAUD_576000: port_baud = B576000; break; +#endif /* B576000 */ +#ifdef B1000000 + case SERIAL_BAUD_1000000: port_baud = B1000000; break; +#endif /* B1000000 */ +#ifdef B1500000 + case SERIAL_BAUD_1500000: port_baud = B1500000; break; +#endif /* B1500000 */ +#ifdef B2000000 + case SERIAL_BAUD_2000000: port_baud = B2000000; break; +#endif /* B2000000 */ + + case SERIAL_BAUD_INVALID: + default: + return PORT_ERR_UNKNOWN; + } + + switch (bits) { + case SERIAL_BITS_5: port_bits = CS5; break; + case SERIAL_BITS_6: port_bits = CS6; break; + case SERIAL_BITS_7: port_bits = CS7; break; + case SERIAL_BITS_8: port_bits = CS8; break; + + default: + return PORT_ERR_UNKNOWN; + } + + switch (parity) { + case SERIAL_PARITY_NONE: port_parity = 0; break; + case SERIAL_PARITY_EVEN: port_parity = PARENB; break; + case SERIAL_PARITY_ODD: port_parity = PARENB | PARODD; break; + + default: + return PORT_ERR_UNKNOWN; + } + + switch (stopbit) { + case SERIAL_STOPBIT_1: port_stop = 0; break; + case SERIAL_STOPBIT_2: port_stop = CSTOPB; break; + + default: + return PORT_ERR_UNKNOWN; + } + + /* reset the settings */ +#ifndef __sun /* Used by GNU and BSD. Ignore __SVR4 in test. */ + cfmakeraw(&h->newtio); +#else /* __sun */ + h->newtio.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR + | IGNCR | ICRNL | IXON); + if (port_parity) + h->newtio.c_iflag |= INPCK; + + h->newtio.c_oflag &= ~OPOST; + h->newtio.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); + h->newtio.c_cflag &= ~(CSIZE | PARENB); + h->newtio.c_cflag |= CS8; +#endif /* __sun */ +#ifdef __QNXNTO__ + h->newtio.c_cflag &= ~(CSIZE | IHFLOW | OHFLOW); +#else + h->newtio.c_cflag &= ~(CSIZE | CRTSCTS); +#endif + h->newtio.c_cflag &= ~(CSIZE | CRTSCTS); + h->newtio.c_iflag &= ~(IXON | IXOFF | IXANY | IGNPAR); + h->newtio.c_lflag &= ~(ECHOK | ECHOCTL | ECHOKE); + h->newtio.c_oflag &= ~(OPOST | ONLCR); + + /* setup the new settings */ + cfsetispeed(&h->newtio, port_baud); + cfsetospeed(&h->newtio, port_baud); + h->newtio.c_cflag |= + port_parity | + port_bits | + port_stop | + CLOCAL | + CREAD; + + h->newtio.c_cc[VMIN] = 0; + h->newtio.c_cc[VTIME] = 5; /* in units of 0.1 s */ + + /* set the settings */ + serial_flush(h); + if (tcsetattr(h->fd, TCSANOW, &h->newtio) != 0) + return PORT_ERR_UNKNOWN; + +/* this check fails on CDC-ACM devices, bits 16 and 17 of cflag differ! + * it has been disabled below for now -jcw, 2015-11-09 + if (settings.c_cflag != h->newtio.c_cflag) + fprintf(stderr, "c_cflag mismatch %lx\n", + settings.c_cflag ^ h->newtio.c_cflag); + */ + + /* confirm they were set */ + tcgetattr(h->fd, &settings); + if (settings.c_iflag != h->newtio.c_iflag || + settings.c_oflag != h->newtio.c_oflag || + //settings.c_cflag != h->newtio.c_cflag || + settings.c_lflag != h->newtio.c_lflag) + return PORT_ERR_UNKNOWN; + + snprintf(h->setup_str, sizeof(h->setup_str), "%u %d%c%d", + serial_get_baud_int(baud), + serial_get_bits_int(bits), + serial_get_parity_str(parity), + serial_get_stopbit_int(stopbit)); + return PORT_ERR_OK; +} + +/* + * Roger clark. + * This function is no longer used. But has just been commented out in case it needs + * to be reinstated in the future + +static int startswith(const char *haystack, const char *needle) { + return strncmp(haystack, needle, strlen(needle)) == 0; +} +*/ + +static int is_tty(const char *path) { + char resolved[PATH_MAX]; + + if(!realpath(path, resolved)) return 0; + + + /* + * Roger Clark + * Commented out this check, because on OSX some devices are /dev/cu + * and some users use symbolic links to devices, hence the name may not even start + * with /dev + + if(startswith(resolved, "/dev/tty")) return 1; + + return 0; + */ + + return 1; +} + +static port_err_t serial_posix_open(struct port_interface *port, + struct port_options *ops) +{ + serial_t *h; + + /* 1. check device name match */ + if (!is_tty(ops->device)) + return PORT_ERR_NODEV; + + /* 2. check options */ + if (ops->baudRate == SERIAL_BAUD_INVALID) + return PORT_ERR_UNKNOWN; + if (serial_get_bits(ops->serial_mode) == SERIAL_BITS_INVALID) + return PORT_ERR_UNKNOWN; + if (serial_get_parity(ops->serial_mode) == SERIAL_PARITY_INVALID) + return PORT_ERR_UNKNOWN; + if (serial_get_stopbit(ops->serial_mode) == SERIAL_STOPBIT_INVALID) + return PORT_ERR_UNKNOWN; + + /* 3. open it */ + h = serial_open(ops->device); + if (h == NULL) + return PORT_ERR_UNKNOWN; + + /* 4. set options */ + if (serial_setup(h, ops->baudRate, + serial_get_bits(ops->serial_mode), + serial_get_parity(ops->serial_mode), + serial_get_stopbit(ops->serial_mode) + ) != PORT_ERR_OK) { + serial_close(h); + return PORT_ERR_UNKNOWN; + } + + port->private = h; + return PORT_ERR_OK; +} + +static port_err_t serial_posix_close(struct port_interface *port) +{ + serial_t *h; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + serial_close(h); + port->private = NULL; + return PORT_ERR_OK; +} + +static port_err_t serial_posix_read(struct port_interface *port, void *buf, + size_t nbyte) +{ + serial_t *h; + ssize_t r; + uint8_t *pos = (uint8_t *)buf; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + while (nbyte) { + r = read(h->fd, pos, nbyte); + if (r == 0) + return PORT_ERR_TIMEDOUT; + if (r < 0) + return PORT_ERR_UNKNOWN; + + nbyte -= r; + pos += r; + } + return PORT_ERR_OK; +} + +static port_err_t serial_posix_write(struct port_interface *port, void *buf, + size_t nbyte) +{ + serial_t *h; + ssize_t r; + const uint8_t *pos = (const uint8_t *)buf; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + while (nbyte) { + r = write(h->fd, pos, nbyte); + if (r < 1) + return PORT_ERR_UNKNOWN; + + nbyte -= r; + pos += r; + } + return PORT_ERR_OK; +} + +static port_err_t serial_posix_gpio(struct port_interface *port, + serial_gpio_t n, int level) +{ + serial_t *h; + int bit, lines; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + switch (n) { + case GPIO_RTS: + bit = TIOCM_RTS; + break; + + case GPIO_DTR: + bit = TIOCM_DTR; + break; + + case GPIO_BRK: + if (level == 0) + return PORT_ERR_OK; + if (tcsendbreak(h->fd, 1)) + return PORT_ERR_UNKNOWN; + return PORT_ERR_OK; + + default: + return PORT_ERR_UNKNOWN; + } + + /* handle RTS/DTR */ + if (ioctl(h->fd, TIOCMGET, &lines)) + return PORT_ERR_UNKNOWN; + lines = level ? lines | bit : lines & ~bit; + if (ioctl(h->fd, TIOCMSET, &lines)) + return PORT_ERR_UNKNOWN; + + return PORT_ERR_OK; +} + +static const char *serial_posix_get_cfg_str(struct port_interface *port) +{ + serial_t *h; + + h = (serial_t *)port->private; + return h ? h->setup_str : "INVALID"; +} + +struct port_interface port_serial = { + .name = "serial_posix", + .flags = PORT_BYTE | PORT_GVR_ETX | PORT_CMD_INIT | PORT_RETRY, + .open = serial_posix_open, + .close = serial_posix_close, + .read = serial_posix_read, + .write = serial_posix_write, + .gpio = serial_posix_gpio, + .get_cfg_str = serial_posix_get_cfg_str, +}; diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/serial_w32.c b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/serial_w32.c new file mode 100644 index 0000000..56772c0 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/serial_w32.c @@ -0,0 +1,341 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + Copyright (C) 2010 Gareth McMullin + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "serial.h" +#include "port.h" + +struct serial { + HANDLE fd; + DCB oldtio; + DCB newtio; + char setup_str[11]; +}; + +static serial_t *serial_open(const char *device) +{ + serial_t *h = calloc(sizeof(serial_t), 1); + char *devName; + + /* timeout in ms */ + COMMTIMEOUTS timeouts = {MAXDWORD, MAXDWORD, 500, 0, 0}; + + /* Fix the device name if required */ + if (strlen(device) > 4 && device[0] != '\\') { + devName = calloc(1, strlen(device) + 5); + sprintf(devName, "\\\\.\\%s", device); + } else { + devName = (char *)device; + } + + /* Create file handle for port */ + h->fd = CreateFile(devName, GENERIC_READ | GENERIC_WRITE, + 0, /* Exclusive access */ + NULL, /* No security */ + OPEN_EXISTING, + 0, /* No overlap */ + NULL); + + if (devName != device) + free(devName); + + if (h->fd == INVALID_HANDLE_VALUE) { + if (GetLastError() == ERROR_FILE_NOT_FOUND) + fprintf(stderr, "File not found: %s\n", device); + return NULL; + } + + SetupComm(h->fd, 4096, 4096); /* Set input and output buffer size */ + + SetCommTimeouts(h->fd, &timeouts); + + SetCommMask(h->fd, EV_ERR); /* Notify us of error events */ + + GetCommState(h->fd, &h->oldtio); /* Retrieve port parameters */ + GetCommState(h->fd, &h->newtio); /* Retrieve port parameters */ + + /* PurgeComm(h->fd, PURGE_RXABORT | PURGE_TXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR); */ + + return h; +} + +static void serial_flush(const serial_t *h) +{ + /* We shouldn't need to flush in non-overlapping (blocking) mode */ + /* tcflush(h->fd, TCIFLUSH); */ +} + +static void serial_close(serial_t *h) +{ + serial_flush(h); + SetCommState(h->fd, &h->oldtio); + CloseHandle(h->fd); + free(h); +} + +static port_err_t serial_setup(serial_t *h, + const serial_baud_t baud, + const serial_bits_t bits, + const serial_parity_t parity, + const serial_stopbit_t stopbit) +{ + switch (baud) { + case SERIAL_BAUD_1200: h->newtio.BaudRate = CBR_1200; break; + /* case SERIAL_BAUD_1800: h->newtio.BaudRate = CBR_1800; break; */ + case SERIAL_BAUD_2400: h->newtio.BaudRate = CBR_2400; break; + case SERIAL_BAUD_4800: h->newtio.BaudRate = CBR_4800; break; + case SERIAL_BAUD_9600: h->newtio.BaudRate = CBR_9600; break; + case SERIAL_BAUD_19200: h->newtio.BaudRate = CBR_19200; break; + case SERIAL_BAUD_38400: h->newtio.BaudRate = CBR_38400; break; + case SERIAL_BAUD_57600: h->newtio.BaudRate = CBR_57600; break; + case SERIAL_BAUD_115200: h->newtio.BaudRate = CBR_115200; break; + case SERIAL_BAUD_128000: h->newtio.BaudRate = CBR_128000; break; + case SERIAL_BAUD_256000: h->newtio.BaudRate = CBR_256000; break; + /* These are not defined in WinBase.h and might work or not */ + case SERIAL_BAUD_230400: h->newtio.BaudRate = 230400; break; + case SERIAL_BAUD_460800: h->newtio.BaudRate = 460800; break; + case SERIAL_BAUD_500000: h->newtio.BaudRate = 500000; break; + case SERIAL_BAUD_576000: h->newtio.BaudRate = 576000; break; + case SERIAL_BAUD_921600: h->newtio.BaudRate = 921600; break; + case SERIAL_BAUD_1000000: h->newtio.BaudRate = 1000000; break; + case SERIAL_BAUD_1500000: h->newtio.BaudRate = 1500000; break; + case SERIAL_BAUD_2000000: h->newtio.BaudRate = 2000000; break; + case SERIAL_BAUD_INVALID: + + default: + return PORT_ERR_UNKNOWN; + } + + switch (bits) { + case SERIAL_BITS_5: h->newtio.ByteSize = 5; break; + case SERIAL_BITS_6: h->newtio.ByteSize = 6; break; + case SERIAL_BITS_7: h->newtio.ByteSize = 7; break; + case SERIAL_BITS_8: h->newtio.ByteSize = 8; break; + + default: + return PORT_ERR_UNKNOWN; + } + + switch (parity) { + case SERIAL_PARITY_NONE: h->newtio.Parity = NOPARITY; break; + case SERIAL_PARITY_EVEN: h->newtio.Parity = EVENPARITY; break; + case SERIAL_PARITY_ODD: h->newtio.Parity = ODDPARITY; break; + + default: + return PORT_ERR_UNKNOWN; + } + + switch (stopbit) { + case SERIAL_STOPBIT_1: h->newtio.StopBits = ONESTOPBIT; break; + case SERIAL_STOPBIT_2: h->newtio.StopBits = TWOSTOPBITS; break; + + default: + return PORT_ERR_UNKNOWN; + } + + /* reset the settings */ + h->newtio.fOutxCtsFlow = FALSE; + h->newtio.fOutxDsrFlow = FALSE; + h->newtio.fOutX = FALSE; + h->newtio.fInX = FALSE; + h->newtio.fNull = 0; + h->newtio.fAbortOnError = 0; + + /* set the settings */ + serial_flush(h); + if (!SetCommState(h->fd, &h->newtio)) + return PORT_ERR_UNKNOWN; + + snprintf(h->setup_str, sizeof(h->setup_str), "%u %d%c%d", + serial_get_baud_int(baud), + serial_get_bits_int(bits), + serial_get_parity_str(parity), + serial_get_stopbit_int(stopbit) + ); + return PORT_ERR_OK; +} + +static port_err_t serial_w32_open(struct port_interface *port, + struct port_options *ops) +{ + serial_t *h; + + /* 1. check device name match */ + if (!((strlen(ops->device) == 4 || strlen(ops->device) == 5) + && !strncmp(ops->device, "COM", 3) && isdigit(ops->device[3])) + && !(!strncmp(ops->device, "\\\\.\\COM", strlen("\\\\.\\COM")) + && isdigit(ops->device[strlen("\\\\.\\COM")]))) + return PORT_ERR_NODEV; + + /* 2. check options */ + if (ops->baudRate == SERIAL_BAUD_INVALID) + return PORT_ERR_UNKNOWN; + if (serial_get_bits(ops->serial_mode) == SERIAL_BITS_INVALID) + return PORT_ERR_UNKNOWN; + if (serial_get_parity(ops->serial_mode) == SERIAL_PARITY_INVALID) + return PORT_ERR_UNKNOWN; + if (serial_get_stopbit(ops->serial_mode) == SERIAL_STOPBIT_INVALID) + return PORT_ERR_UNKNOWN; + + /* 3. open it */ + h = serial_open(ops->device); + if (h == NULL) + return PORT_ERR_UNKNOWN; + + /* 4. set options */ + if (serial_setup(h, ops->baudRate, + serial_get_bits(ops->serial_mode), + serial_get_parity(ops->serial_mode), + serial_get_stopbit(ops->serial_mode) + ) != PORT_ERR_OK) { + serial_close(h); + return PORT_ERR_UNKNOWN; + } + + port->private = h; + return PORT_ERR_OK; +} + +static port_err_t serial_w32_close(struct port_interface *port) +{ + serial_t *h; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + serial_close(h); + port->private = NULL; + return PORT_ERR_OK; +} + +static port_err_t serial_w32_read(struct port_interface *port, void *buf, + size_t nbyte) +{ + serial_t *h; + DWORD r; + uint8_t *pos = (uint8_t *)buf; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + while (nbyte) { + ReadFile(h->fd, pos, nbyte, &r, NULL); + if (r == 0) + return PORT_ERR_TIMEDOUT; + if (r < 0) + return PORT_ERR_UNKNOWN; + + nbyte -= r; + pos += r; + } + return PORT_ERR_OK; +} + +static port_err_t serial_w32_write(struct port_interface *port, void *buf, + size_t nbyte) +{ + serial_t *h; + DWORD r; + uint8_t *pos = (uint8_t *)buf; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + while (nbyte) { + if (!WriteFile(h->fd, pos, nbyte, &r, NULL)) + return PORT_ERR_UNKNOWN; + if (r < 1) + return PORT_ERR_UNKNOWN; + + nbyte -= r; + pos += r; + } + return PORT_ERR_OK; +} + +static port_err_t serial_w32_gpio(struct port_interface *port, + serial_gpio_t n, int level) +{ + serial_t *h; + int bit; + + h = (serial_t *)port->private; + if (h == NULL) + return PORT_ERR_UNKNOWN; + + switch (n) { + case GPIO_RTS: + bit = level ? SETRTS : CLRRTS; + break; + + case GPIO_DTR: + bit = level ? SETDTR : CLRDTR; + break; + + case GPIO_BRK: + if (level == 0) + return PORT_ERR_OK; + if (EscapeCommFunction(h->fd, SETBREAK) == 0) + return PORT_ERR_UNKNOWN; + usleep(500000); + if (EscapeCommFunction(h->fd, CLRBREAK) == 0) + return PORT_ERR_UNKNOWN; + return PORT_ERR_OK; + + default: + return PORT_ERR_UNKNOWN; + } + + /* handle RTS/DTR */ + if (EscapeCommFunction(h->fd, bit) == 0) + return PORT_ERR_UNKNOWN; + + return PORT_ERR_OK; +} + +static const char *serial_w32_get_cfg_str(struct port_interface *port) +{ + serial_t *h; + + h = (serial_t *)port->private; + return h ? h->setup_str : "INVALID"; +} + +struct port_interface port_serial = { + .name = "serial_w32", + .flags = PORT_BYTE | PORT_GVR_ETX | PORT_CMD_INIT | PORT_RETRY, + .open = serial_w32_open, + .close = serial_w32_close, + .read = serial_w32_read, + .write = serial_w32_write, + .gpio = serial_w32_gpio, + .get_cfg_str = serial_w32_get_cfg_str, +}; diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/stm32.c b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/stm32.c new file mode 100644 index 0000000..74047d2 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/stm32.c @@ -0,0 +1,1048 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright 2010 Geoffrey McRae + Copyright 2012-2014 Tormod Volden + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include + +#include "stm32.h" +#include "port.h" +#include "utils.h" + +#define STM32_ACK 0x79 +#define STM32_NACK 0x1F +#define STM32_BUSY 0x76 + +#define STM32_CMD_INIT 0x7F +#define STM32_CMD_GET 0x00 /* get the version and command supported */ +#define STM32_CMD_GVR 0x01 /* get version and read protection status */ +#define STM32_CMD_GID 0x02 /* get ID */ +#define STM32_CMD_RM 0x11 /* read memory */ +#define STM32_CMD_GO 0x21 /* go */ +#define STM32_CMD_WM 0x31 /* write memory */ +#define STM32_CMD_WM_NS 0x32 /* no-stretch write memory */ +#define STM32_CMD_ER 0x43 /* erase */ +#define STM32_CMD_EE 0x44 /* extended erase */ +#define STM32_CMD_EE_NS 0x45 /* extended erase no-stretch */ +#define STM32_CMD_WP 0x63 /* write protect */ +#define STM32_CMD_WP_NS 0x64 /* write protect no-stretch */ +#define STM32_CMD_UW 0x73 /* write unprotect */ +#define STM32_CMD_UW_NS 0x74 /* write unprotect no-stretch */ +#define STM32_CMD_RP 0x82 /* readout protect */ +#define STM32_CMD_RP_NS 0x83 /* readout protect no-stretch */ +#define STM32_CMD_UR 0x92 /* readout unprotect */ +#define STM32_CMD_UR_NS 0x93 /* readout unprotect no-stretch */ +#define STM32_CMD_CRC 0xA1 /* compute CRC */ +#define STM32_CMD_ERR 0xFF /* not a valid command */ + +#define STM32_RESYNC_TIMEOUT 35 /* seconds */ +#define STM32_MASSERASE_TIMEOUT 35 /* seconds */ +#define STM32_SECTERASE_TIMEOUT 5 /* seconds */ +#define STM32_BLKWRITE_TIMEOUT 1 /* seconds */ +#define STM32_WUNPROT_TIMEOUT 1 /* seconds */ +#define STM32_WPROT_TIMEOUT 1 /* seconds */ +#define STM32_RPROT_TIMEOUT 1 /* seconds */ + +#define STM32_CMD_GET_LENGTH 17 /* bytes in the reply */ + +struct stm32_cmd { + uint8_t get; + uint8_t gvr; + uint8_t gid; + uint8_t rm; + uint8_t go; + uint8_t wm; + uint8_t er; /* this may be extended erase */ + uint8_t wp; + uint8_t uw; + uint8_t rp; + uint8_t ur; + uint8_t crc; +}; + +/* Reset code for ARMv7-M (Cortex-M3) and ARMv6-M (Cortex-M0) + * see ARMv7-M or ARMv6-M Architecture Reference Manual (table B3-8) + * or "The definitive guide to the ARM Cortex-M3", section 14.4. + */ +static const uint8_t stm_reset_code[] = { + 0x01, 0x49, // ldr r1, [pc, #4] ; () + 0x02, 0x4A, // ldr r2, [pc, #8] ; () + 0x0A, 0x60, // str r2, [r1, #0] + 0xfe, 0xe7, // endless: b endless + 0x0c, 0xed, 0x00, 0xe0, // .word 0xe000ed0c = NVIC AIRCR register address + 0x04, 0x00, 0xfa, 0x05 // .word 0x05fa0004 = VECTKEY | SYSRESETREQ +}; + +static const uint32_t stm_reset_code_length = sizeof(stm_reset_code); + +extern const stm32_dev_t devices[]; + +static void stm32_warn_stretching(const char *f) +{ + fprintf(stderr, "Attention !!!\n"); + fprintf(stderr, "\tThis %s error could be caused by your I2C\n", f); + fprintf(stderr, "\tcontroller not accepting \"clock stretching\"\n"); + fprintf(stderr, "\tas required by bootloader.\n"); + fprintf(stderr, "\tCheck \"I2C.txt\" in stm32flash source code.\n"); +} + +static stm32_err_t stm32_get_ack_timeout(const stm32_t *stm, time_t timeout) +{ + struct port_interface *port = stm->port; + uint8_t byte; + port_err_t p_err; + time_t t0, t1; + + if (!(port->flags & PORT_RETRY)) + timeout = 0; + + if (timeout) + time(&t0); + + do { + p_err = port->read(port, &byte, 1); + if (p_err == PORT_ERR_TIMEDOUT && timeout) { + time(&t1); + if (t1 < t0 + timeout) + continue; + } + + if (p_err != PORT_ERR_OK) { + fprintf(stderr, "Failed to read ACK byte\n"); + return STM32_ERR_UNKNOWN; + } + + if (byte == STM32_ACK) + return STM32_ERR_OK; + if (byte == STM32_NACK) + return STM32_ERR_NACK; + if (byte != STM32_BUSY) { + fprintf(stderr, "Got byte 0x%02x instead of ACK\n", + byte); + return STM32_ERR_UNKNOWN; + } + } while (1); +} + +static stm32_err_t stm32_get_ack(const stm32_t *stm) +{ + return stm32_get_ack_timeout(stm, 0); +} + +static stm32_err_t stm32_send_command_timeout(const stm32_t *stm, + const uint8_t cmd, + time_t timeout) +{ + struct port_interface *port = stm->port; + stm32_err_t s_err; + port_err_t p_err; + uint8_t buf[2]; + + buf[0] = cmd; + buf[1] = cmd ^ 0xFF; + p_err = port->write(port, buf, 2); + if (p_err != PORT_ERR_OK) { + fprintf(stderr, "Failed to send command\n"); + return STM32_ERR_UNKNOWN; + } + s_err = stm32_get_ack_timeout(stm, timeout); + if (s_err == STM32_ERR_OK) + return STM32_ERR_OK; + if (s_err == STM32_ERR_NACK) + fprintf(stderr, "Got NACK from device on command 0x%02x\n", cmd); + else + fprintf(stderr, "Unexpected reply from device on command 0x%02x\n", cmd); + return STM32_ERR_UNKNOWN; +} + +static stm32_err_t stm32_send_command(const stm32_t *stm, const uint8_t cmd) +{ + return stm32_send_command_timeout(stm, cmd, 0); +} + +/* if we have lost sync, send a wrong command and expect a NACK */ +static stm32_err_t stm32_resync(const stm32_t *stm) +{ + struct port_interface *port = stm->port; + port_err_t p_err; + uint8_t buf[2], ack; + time_t t0, t1; + + time(&t0); + t1 = t0; + + buf[0] = STM32_CMD_ERR; + buf[1] = STM32_CMD_ERR ^ 0xFF; + while (t1 < t0 + STM32_RESYNC_TIMEOUT) { + p_err = port->write(port, buf, 2); + if (p_err != PORT_ERR_OK) { + usleep(500000); + time(&t1); + continue; + } + p_err = port->read(port, &ack, 1); + if (p_err != PORT_ERR_OK) { + time(&t1); + continue; + } + if (ack == STM32_NACK) + return STM32_ERR_OK; + time(&t1); + } + return STM32_ERR_UNKNOWN; +} + +/* + * some command receive reply frame with variable length, and length is + * embedded in reply frame itself. + * We can guess the length, but if we guess wrong the protocol gets out + * of sync. + * Use resync for frame oriented interfaces (e.g. I2C) and byte-by-byte + * read for byte oriented interfaces (e.g. UART). + * + * to run safely, data buffer should be allocated for 256+1 bytes + * + * len is value of the first byte in the frame. + */ +static stm32_err_t stm32_guess_len_cmd(const stm32_t *stm, uint8_t cmd, + uint8_t *data, unsigned int len) +{ + struct port_interface *port = stm->port; + port_err_t p_err; + + if (stm32_send_command(stm, cmd) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + if (port->flags & PORT_BYTE) { + /* interface is UART-like */ + p_err = port->read(port, data, 1); + if (p_err != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + len = data[0]; + p_err = port->read(port, data + 1, len + 1); + if (p_err != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + return STM32_ERR_OK; + } + + p_err = port->read(port, data, len + 2); + if (p_err == PORT_ERR_OK && len == data[0]) + return STM32_ERR_OK; + if (p_err != PORT_ERR_OK) { + /* restart with only one byte */ + if (stm32_resync(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + if (stm32_send_command(stm, cmd) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + p_err = port->read(port, data, 1); + if (p_err != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + } + + fprintf(stderr, "Re sync (len = %d)\n", data[0]); + if (stm32_resync(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + len = data[0]; + if (stm32_send_command(stm, cmd) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + p_err = port->read(port, data, len + 2); + if (p_err != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + return STM32_ERR_OK; +} + +/* + * Some interface, e.g. UART, requires a specific init sequence to let STM32 + * autodetect the interface speed. + * The sequence is only required one time after reset. + * stm32flash has command line flag "-c" to prevent sending the init sequence + * in case it was already sent before. + * User can easily forget adding "-c". In this case the bootloader would + * interpret the init sequence as part of a command message, then waiting for + * the rest of the message blocking the interface. + * This function sends the init sequence and, in case of timeout, recovers + * the interface. + */ +static stm32_err_t stm32_send_init_seq(const stm32_t *stm) +{ + struct port_interface *port = stm->port; + port_err_t p_err; + uint8_t byte, cmd = STM32_CMD_INIT; + + p_err = port->write(port, &cmd, 1); + if (p_err != PORT_ERR_OK) { + fprintf(stderr, "Failed to send init to device\n"); + return STM32_ERR_UNKNOWN; + } + p_err = port->read(port, &byte, 1); + if (p_err == PORT_ERR_OK && byte == STM32_ACK) + return STM32_ERR_OK; + if (p_err == PORT_ERR_OK && byte == STM32_NACK) { + /* We could get error later, but let's continue, for now. */ + fprintf(stderr, + "Warning: the interface was not closed properly.\n"); + return STM32_ERR_OK; + } + if (p_err != PORT_ERR_TIMEDOUT) { + fprintf(stderr, "Failed to init device.\n"); + return STM32_ERR_UNKNOWN; + } + + /* + * Check if previous STM32_CMD_INIT was taken as first byte + * of a command. Send a new byte, we should get back a NACK. + */ + p_err = port->write(port, &cmd, 1); + if (p_err != PORT_ERR_OK) { + fprintf(stderr, "Failed to send init to device\n"); + return STM32_ERR_UNKNOWN; + } + p_err = port->read(port, &byte, 1); + if (p_err == PORT_ERR_OK && byte == STM32_NACK) + return STM32_ERR_OK; + fprintf(stderr, "Failed to init device.\n"); + return STM32_ERR_UNKNOWN; +} + +/* find newer command by higher code */ +#define newer(prev, a) (((prev) == STM32_CMD_ERR) \ + ? (a) \ + : (((prev) > (a)) ? (prev) : (a))) + +stm32_t *stm32_init(struct port_interface *port, const char init) +{ + uint8_t len, val, buf[257]; + stm32_t *stm; + int i, new_cmds; + + stm = calloc(sizeof(stm32_t), 1); + stm->cmd = malloc(sizeof(stm32_cmd_t)); + memset(stm->cmd, STM32_CMD_ERR, sizeof(stm32_cmd_t)); + stm->port = port; + + if ((port->flags & PORT_CMD_INIT) && init) + if (stm32_send_init_seq(stm) != STM32_ERR_OK) + return NULL; + + /* get the version and read protection status */ + if (stm32_send_command(stm, STM32_CMD_GVR) != STM32_ERR_OK) { + stm32_close(stm); + return NULL; + } + + /* From AN, only UART bootloader returns 3 bytes */ + len = (port->flags & PORT_GVR_ETX) ? 3 : 1; + if (port->read(port, buf, len) != PORT_ERR_OK) + return NULL; + stm->version = buf[0]; + stm->option1 = (port->flags & PORT_GVR_ETX) ? buf[1] : 0; + stm->option2 = (port->flags & PORT_GVR_ETX) ? buf[2] : 0; + if (stm32_get_ack(stm) != STM32_ERR_OK) { + stm32_close(stm); + return NULL; + } + + /* get the bootloader information */ + len = STM32_CMD_GET_LENGTH; + if (port->cmd_get_reply) + for (i = 0; port->cmd_get_reply[i].length; i++) + if (stm->version == port->cmd_get_reply[i].version) { + len = port->cmd_get_reply[i].length; + break; + } + if (stm32_guess_len_cmd(stm, STM32_CMD_GET, buf, len) != STM32_ERR_OK) + return NULL; + len = buf[0] + 1; + stm->bl_version = buf[1]; + new_cmds = 0; + for (i = 1; i < len; i++) { + val = buf[i + 1]; + switch (val) { + case STM32_CMD_GET: + stm->cmd->get = val; break; + case STM32_CMD_GVR: + stm->cmd->gvr = val; break; + case STM32_CMD_GID: + stm->cmd->gid = val; break; + case STM32_CMD_RM: + stm->cmd->rm = val; break; + case STM32_CMD_GO: + stm->cmd->go = val; break; + case STM32_CMD_WM: + case STM32_CMD_WM_NS: + stm->cmd->wm = newer(stm->cmd->wm, val); + break; + case STM32_CMD_ER: + case STM32_CMD_EE: + case STM32_CMD_EE_NS: + stm->cmd->er = newer(stm->cmd->er, val); + break; + case STM32_CMD_WP: + case STM32_CMD_WP_NS: + stm->cmd->wp = newer(stm->cmd->wp, val); + break; + case STM32_CMD_UW: + case STM32_CMD_UW_NS: + stm->cmd->uw = newer(stm->cmd->uw, val); + break; + case STM32_CMD_RP: + case STM32_CMD_RP_NS: + stm->cmd->rp = newer(stm->cmd->rp, val); + break; + case STM32_CMD_UR: + case STM32_CMD_UR_NS: + stm->cmd->ur = newer(stm->cmd->ur, val); + break; + case STM32_CMD_CRC: + stm->cmd->crc = newer(stm->cmd->crc, val); + break; + default: + if (new_cmds++ == 0) + fprintf(stderr, + "GET returns unknown commands (0x%2x", + val); + else + fprintf(stderr, ", 0x%2x", val); + } + } + if (new_cmds) + fprintf(stderr, ")\n"); + if (stm32_get_ack(stm) != STM32_ERR_OK) { + stm32_close(stm); + return NULL; + } + + if (stm->cmd->get == STM32_CMD_ERR + || stm->cmd->gvr == STM32_CMD_ERR + || stm->cmd->gid == STM32_CMD_ERR) { + fprintf(stderr, "Error: bootloader did not returned correct information from GET command\n"); + return NULL; + } + + /* get the device ID */ + if (stm32_guess_len_cmd(stm, stm->cmd->gid, buf, 1) != STM32_ERR_OK) { + stm32_close(stm); + return NULL; + } + len = buf[0] + 1; + if (len < 2) { + stm32_close(stm); + fprintf(stderr, "Only %d bytes sent in the PID, unknown/unsupported device\n", len); + return NULL; + } + stm->pid = (buf[1] << 8) | buf[2]; + if (len > 2) { + fprintf(stderr, "This bootloader returns %d extra bytes in PID:", len); + for (i = 2; i <= len ; i++) + fprintf(stderr, " %02x", buf[i]); + fprintf(stderr, "\n"); + } + if (stm32_get_ack(stm) != STM32_ERR_OK) { + stm32_close(stm); + return NULL; + } + + stm->dev = devices; + while (stm->dev->id != 0x00 && stm->dev->id != stm->pid) + ++stm->dev; + + if (!stm->dev->id) { + fprintf(stderr, "Unknown/unsupported device (Device ID: 0x%03x)\n", stm->pid); + stm32_close(stm); + return NULL; + } + + return stm; +} + +void stm32_close(stm32_t *stm) +{ + if (stm) + free(stm->cmd); + free(stm); +} + +stm32_err_t stm32_read_memory(const stm32_t *stm, uint32_t address, + uint8_t data[], unsigned int len) +{ + struct port_interface *port = stm->port; + uint8_t buf[5]; + + if (!len) + return STM32_ERR_OK; + + if (len > 256) { + fprintf(stderr, "Error: READ length limit at 256 bytes\n"); + return STM32_ERR_UNKNOWN; + } + + if (stm->cmd->rm == STM32_CMD_ERR) { + fprintf(stderr, "Error: READ command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->rm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + buf[0] = address >> 24; + buf[1] = (address >> 16) & 0xFF; + buf[2] = (address >> 8) & 0xFF; + buf[3] = address & 0xFF; + buf[4] = buf[0] ^ buf[1] ^ buf[2] ^ buf[3]; + if (port->write(port, buf, 5) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + if (stm32_get_ack(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (stm32_send_command(stm, len - 1) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (port->read(port, data, len) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + + return STM32_ERR_OK; +} + +stm32_err_t stm32_write_memory(const stm32_t *stm, uint32_t address, + const uint8_t data[], unsigned int len) +{ + struct port_interface *port = stm->port; + uint8_t cs, buf[256 + 2]; + unsigned int i, aligned_len; + stm32_err_t s_err; + + if (!len) + return STM32_ERR_OK; + + if (len > 256) { + fprintf(stderr, "Error: READ length limit at 256 bytes\n"); + return STM32_ERR_UNKNOWN; + } + + /* must be 32bit aligned */ + if (address & 0x3 || len & 0x3) { + fprintf(stderr, "Error: WRITE address and length must be 4 byte aligned\n"); + return STM32_ERR_UNKNOWN; + } + + if (stm->cmd->wm == STM32_CMD_ERR) { + fprintf(stderr, "Error: WRITE command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + /* send the address and checksum */ + if (stm32_send_command(stm, stm->cmd->wm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + buf[0] = address >> 24; + buf[1] = (address >> 16) & 0xFF; + buf[2] = (address >> 8) & 0xFF; + buf[3] = address & 0xFF; + buf[4] = buf[0] ^ buf[1] ^ buf[2] ^ buf[3]; + if (port->write(port, buf, 5) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + if (stm32_get_ack(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + aligned_len = (len + 3) & ~3; + cs = aligned_len - 1; + buf[0] = aligned_len - 1; + for (i = 0; i < len; i++) { + cs ^= data[i]; + buf[i + 1] = data[i]; + } + /* padding data */ + for (i = len; i < aligned_len; i++) { + cs ^= 0xFF; + buf[i + 1] = 0xFF; + } + buf[aligned_len + 1] = cs; + if (port->write(port, buf, aligned_len + 2) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + + s_err = stm32_get_ack_timeout(stm, STM32_BLKWRITE_TIMEOUT); + if (s_err != STM32_ERR_OK) { + if (port->flags & PORT_STRETCH_W + && stm->cmd->wm != STM32_CMD_WM_NS) + stm32_warn_stretching("write"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; +} + +stm32_err_t stm32_wunprot_memory(const stm32_t *stm) +{ + struct port_interface *port = stm->port; + stm32_err_t s_err; + + if (stm->cmd->uw == STM32_CMD_ERR) { + fprintf(stderr, "Error: WRITE UNPROTECT command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->uw) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + s_err = stm32_get_ack_timeout(stm, STM32_WUNPROT_TIMEOUT); + if (s_err == STM32_NACK) { + fprintf(stderr, "Error: Failed to WRITE UNPROTECT\n"); + return STM32_ERR_UNKNOWN; + } + if (s_err != STM32_ERR_OK) { + if (port->flags & PORT_STRETCH_W + && stm->cmd->uw != STM32_CMD_UW_NS) + stm32_warn_stretching("WRITE UNPROTECT"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; +} + +stm32_err_t stm32_wprot_memory(const stm32_t *stm) +{ + struct port_interface *port = stm->port; + stm32_err_t s_err; + + if (stm->cmd->wp == STM32_CMD_ERR) { + fprintf(stderr, "Error: WRITE PROTECT command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->wp) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + s_err = stm32_get_ack_timeout(stm, STM32_WPROT_TIMEOUT); + if (s_err == STM32_NACK) { + fprintf(stderr, "Error: Failed to WRITE PROTECT\n"); + return STM32_ERR_UNKNOWN; + } + if (s_err != STM32_ERR_OK) { + if (port->flags & PORT_STRETCH_W + && stm->cmd->wp != STM32_CMD_WP_NS) + stm32_warn_stretching("WRITE PROTECT"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; +} + +stm32_err_t stm32_runprot_memory(const stm32_t *stm) +{ + struct port_interface *port = stm->port; + stm32_err_t s_err; + + if (stm->cmd->ur == STM32_CMD_ERR) { + fprintf(stderr, "Error: READOUT UNPROTECT command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->ur) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + s_err = stm32_get_ack_timeout(stm, STM32_MASSERASE_TIMEOUT); + if (s_err == STM32_NACK) { + fprintf(stderr, "Error: Failed to READOUT UNPROTECT\n"); + return STM32_ERR_UNKNOWN; + } + if (s_err != STM32_ERR_OK) { + if (port->flags & PORT_STRETCH_W + && stm->cmd->ur != STM32_CMD_UR_NS) + stm32_warn_stretching("READOUT UNPROTECT"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; +} + +stm32_err_t stm32_readprot_memory(const stm32_t *stm) +{ + struct port_interface *port = stm->port; + stm32_err_t s_err; + + if (stm->cmd->rp == STM32_CMD_ERR) { + fprintf(stderr, "Error: READOUT PROTECT command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->rp) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + s_err = stm32_get_ack_timeout(stm, STM32_RPROT_TIMEOUT); + if (s_err == STM32_NACK) { + fprintf(stderr, "Error: Failed to READOUT PROTECT\n"); + return STM32_ERR_UNKNOWN; + } + if (s_err != STM32_ERR_OK) { + if (port->flags & PORT_STRETCH_W + && stm->cmd->rp != STM32_CMD_RP_NS) + stm32_warn_stretching("READOUT PROTECT"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; +} + +stm32_err_t stm32_erase_memory(const stm32_t *stm, uint8_t spage, uint8_t pages) +{ + struct port_interface *port = stm->port; + stm32_err_t s_err; + port_err_t p_err; + + if (!pages) + return STM32_ERR_OK; + + if (stm->cmd->er == STM32_CMD_ERR) { + fprintf(stderr, "Error: ERASE command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->er) != STM32_ERR_OK) { + fprintf(stderr, "Can't initiate chip erase!\n"); + return STM32_ERR_UNKNOWN; + } + + /* The erase command reported by the bootloader is either 0x43, 0x44 or 0x45 */ + /* 0x44 is Extended Erase, a 2 byte based protocol and needs to be handled differently. */ + /* 0x45 is clock no-stretching version of Extended Erase for I2C port. */ + if (stm->cmd->er != STM32_CMD_ER) { + /* Not all chips using Extended Erase support mass erase */ + /* Currently known as not supporting mass erase is the Ultra Low Power STM32L15xx range */ + /* So if someone has not overridden the default, but uses one of these chips, take it out of */ + /* mass erase mode, so it will be done page by page. This maximum might not be correct either! */ + if (stm->pid == 0x416 && pages == 0xFF) + pages = 0xF8; /* works for the STM32L152RB with 128Kb flash */ + + if (pages == 0xFF) { + uint8_t buf[3]; + + /* 0xFFFF the magic number for mass erase */ + buf[0] = 0xFF; + buf[1] = 0xFF; + buf[2] = 0x00; /* checksum */ + if (port->write(port, buf, 3) != PORT_ERR_OK) { + fprintf(stderr, "Mass erase error.\n"); + return STM32_ERR_UNKNOWN; + } + s_err = stm32_get_ack_timeout(stm, STM32_MASSERASE_TIMEOUT); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Mass erase failed. Try specifying the number of pages to be erased.\n"); + if (port->flags & PORT_STRETCH_W + && stm->cmd->er != STM32_CMD_EE_NS) + stm32_warn_stretching("erase"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; + } + + uint16_t pg_num; + uint8_t pg_byte; + uint8_t cs = 0; + uint8_t *buf; + int i = 0; + + buf = malloc(2 + 2 * pages + 1); + if (!buf) + return STM32_ERR_UNKNOWN; + + /* Number of pages to be erased - 1, two bytes, MSB first */ + pg_byte = (pages - 1) >> 8; + buf[i++] = pg_byte; + cs ^= pg_byte; + pg_byte = (pages - 1) & 0xFF; + buf[i++] = pg_byte; + cs ^= pg_byte; + + for (pg_num = spage; pg_num < spage + pages; pg_num++) { + pg_byte = pg_num >> 8; + cs ^= pg_byte; + buf[i++] = pg_byte; + pg_byte = pg_num & 0xFF; + cs ^= pg_byte; + buf[i++] = pg_byte; + } + buf[i++] = cs; + p_err = port->write(port, buf, i); + free(buf); + if (p_err != PORT_ERR_OK) { + fprintf(stderr, "Page-by-page erase error.\n"); + return STM32_ERR_UNKNOWN; + } + + s_err = stm32_get_ack_timeout(stm, pages * STM32_SECTERASE_TIMEOUT); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Page-by-page erase failed. Check the maximum pages your device supports.\n"); + if (port->flags & PORT_STRETCH_W + && stm->cmd->er != STM32_CMD_EE_NS) + stm32_warn_stretching("erase"); + return STM32_ERR_UNKNOWN; + } + + return STM32_ERR_OK; + } + + /* And now the regular erase (0x43) for all other chips */ + if (pages == 0xFF) { + s_err = stm32_send_command_timeout(stm, 0xFF, STM32_MASSERASE_TIMEOUT); + if (s_err != STM32_ERR_OK) { + if (port->flags & PORT_STRETCH_W) + stm32_warn_stretching("erase"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; + } else { + uint8_t cs = 0; + uint8_t pg_num; + uint8_t *buf; + int i = 0; + + buf = malloc(1 + pages + 1); + if (!buf) + return STM32_ERR_UNKNOWN; + + buf[i++] = pages - 1; + cs ^= (pages-1); + for (pg_num = spage; pg_num < (pages + spage); pg_num++) { + buf[i++] = pg_num; + cs ^= pg_num; + } + buf[i++] = cs; + p_err = port->write(port, buf, i); + free(buf); + if (p_err != PORT_ERR_OK) { + fprintf(stderr, "Erase failed.\n"); + return STM32_ERR_UNKNOWN; + } + s_err = stm32_get_ack_timeout(stm, STM32_MASSERASE_TIMEOUT); + if (s_err != STM32_ERR_OK) { + if (port->flags & PORT_STRETCH_W) + stm32_warn_stretching("erase"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; + } +} + +static stm32_err_t stm32_run_raw_code(const stm32_t *stm, + uint32_t target_address, + const uint8_t *code, uint32_t code_size) +{ + uint32_t stack_le = le_u32(0x20002000); + uint32_t code_address_le = le_u32(target_address + 8); + uint32_t length = code_size + 8; + uint8_t *mem, *pos; + uint32_t address, w; + + /* Must be 32-bit aligned */ + if (target_address & 0x3) { + fprintf(stderr, "Error: code address must be 4 byte aligned\n"); + return STM32_ERR_UNKNOWN; + } + + mem = malloc(length); + if (!mem) + return STM32_ERR_UNKNOWN; + + memcpy(mem, &stack_le, sizeof(uint32_t)); + memcpy(mem + 4, &code_address_le, sizeof(uint32_t)); + memcpy(mem + 8, code, code_size); + + pos = mem; + address = target_address; + while (length > 0) { + w = length > 256 ? 256 : length; + if (stm32_write_memory(stm, address, pos, w) != STM32_ERR_OK) { + free(mem); + return STM32_ERR_UNKNOWN; + } + + address += w; + pos += w; + length -= w; + } + + free(mem); + return stm32_go(stm, target_address); +} + +stm32_err_t stm32_go(const stm32_t *stm, uint32_t address) +{ + struct port_interface *port = stm->port; + uint8_t buf[5]; + + if (stm->cmd->go == STM32_CMD_ERR) { + fprintf(stderr, "Error: GO command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->go) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + buf[0] = address >> 24; + buf[1] = (address >> 16) & 0xFF; + buf[2] = (address >> 8) & 0xFF; + buf[3] = address & 0xFF; + buf[4] = buf[0] ^ buf[1] ^ buf[2] ^ buf[3]; + if (port->write(port, buf, 5) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (stm32_get_ack(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + return STM32_ERR_OK; +} + +stm32_err_t stm32_reset_device(const stm32_t *stm) +{ + uint32_t target_address = stm->dev->ram_start; + + return stm32_run_raw_code(stm, target_address, stm_reset_code, stm_reset_code_length); +} + +stm32_err_t stm32_crc_memory(const stm32_t *stm, uint32_t address, + uint32_t length, uint32_t *crc) +{ + struct port_interface *port = stm->port; + uint8_t buf[5]; + + if (address & 0x3 || length & 0x3) { + fprintf(stderr, "Start and end addresses must be 4 byte aligned\n"); + return STM32_ERR_UNKNOWN; + } + + if (stm->cmd->crc == STM32_CMD_ERR) { + fprintf(stderr, "Error: CRC command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (stm32_send_command(stm, stm->cmd->crc) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + buf[0] = address >> 24; + buf[1] = (address >> 16) & 0xFF; + buf[2] = (address >> 8) & 0xFF; + buf[3] = address & 0xFF; + buf[4] = buf[0] ^ buf[1] ^ buf[2] ^ buf[3]; + if (port->write(port, buf, 5) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (stm32_get_ack(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + buf[0] = length >> 24; + buf[1] = (length >> 16) & 0xFF; + buf[2] = (length >> 8) & 0xFF; + buf[3] = length & 0xFF; + buf[4] = buf[0] ^ buf[1] ^ buf[2] ^ buf[3]; + if (port->write(port, buf, 5) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (stm32_get_ack(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (stm32_get_ack(stm) != STM32_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (port->read(port, buf, 5) != PORT_ERR_OK) + return STM32_ERR_UNKNOWN; + + if (buf[4] != (buf[0] ^ buf[1] ^ buf[2] ^ buf[3])) + return STM32_ERR_UNKNOWN; + + *crc = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; + return STM32_ERR_OK; +} + +/* + * CRC computed by STM32 is similar to the standard crc32_be() + * implemented, for example, in Linux kernel in ./lib/crc32.c + * But STM32 computes it on units of 32 bits word and swaps the + * bytes of the word before the computation. + * Due to byte swap, I cannot use any CRC available in existing + * libraries, so here is a simple not optimized implementation. + */ +#define CRCPOLY_BE 0x04c11db7 +#define CRC_MSBMASK 0x80000000 +#define CRC_INIT_VALUE 0xFFFFFFFF +uint32_t stm32_sw_crc(uint32_t crc, uint8_t *buf, unsigned int len) +{ + int i; + uint32_t data; + + if (len & 0x3) { + fprintf(stderr, "Buffer length must be multiple of 4 bytes\n"); + return 0; + } + + while (len) { + data = *buf++; + data |= *buf++ << 8; + data |= *buf++ << 16; + data |= *buf++ << 24; + len -= 4; + + crc ^= data; + + for (i = 0; i < 32; i++) + if (crc & CRC_MSBMASK) + crc = (crc << 1) ^ CRCPOLY_BE; + else + crc = (crc << 1); + } + return crc; +} + +stm32_err_t stm32_crc_wrapper(const stm32_t *stm, uint32_t address, + uint32_t length, uint32_t *crc) +{ + uint8_t buf[256]; + uint32_t start, total_len, len, current_crc; + + if (address & 0x3 || length & 0x3) { + fprintf(stderr, "Start and end addresses must be 4 byte aligned\n"); + return STM32_ERR_UNKNOWN; + } + + if (stm->cmd->crc != STM32_CMD_ERR) + return stm32_crc_memory(stm, address, length, crc); + + start = address; + total_len = length; + current_crc = CRC_INIT_VALUE; + while (length) { + len = length > 256 ? 256 : length; + if (stm32_read_memory(stm, address, buf, len) != STM32_ERR_OK) { + fprintf(stderr, + "Failed to read memory at address 0x%08x, target write-protected?\n", + address); + return STM32_ERR_UNKNOWN; + } + current_crc = stm32_sw_crc(current_crc, buf, len); + length -= len; + address += len; + + fprintf(stderr, + "\rCRC address 0x%08x (%.2f%%) ", + address, + (100.0f / (float)total_len) * (float)(address - start) + ); + fflush(stderr); + } + fprintf(stderr, "Done.\n"); + *crc = current_crc; + return STM32_ERR_OK; +} diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/stm32.h b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/stm32.h new file mode 100644 index 0000000..1688fcb --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/stm32.h @@ -0,0 +1,84 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _STM32_H +#define _STM32_H + +#include +#include "serial.h" + +#define STM32_MAX_RX_FRAME 256 /* cmd read memory */ +#define STM32_MAX_TX_FRAME (1 + 256 + 1) /* cmd write memory */ + +typedef enum { + STM32_ERR_OK = 0, + STM32_ERR_UNKNOWN, /* Generic error */ + STM32_ERR_NACK, + STM32_ERR_NO_CMD, /* Command not available in bootloader */ +} stm32_err_t; + +typedef struct stm32 stm32_t; +typedef struct stm32_cmd stm32_cmd_t; +typedef struct stm32_dev stm32_dev_t; + +struct stm32 { + const serial_t *serial; + struct port_interface *port; + uint8_t bl_version; + uint8_t version; + uint8_t option1, option2; + uint16_t pid; + stm32_cmd_t *cmd; + const stm32_dev_t *dev; +}; + +struct stm32_dev { + uint16_t id; + const char *name; + uint32_t ram_start, ram_end; + uint32_t fl_start, fl_end; + uint16_t fl_pps; // pages per sector + uint16_t fl_ps; // page size + uint32_t opt_start, opt_end; + uint32_t mem_start, mem_end; +}; + +stm32_t *stm32_init(struct port_interface *port, const char init); +void stm32_close(stm32_t *stm); +stm32_err_t stm32_read_memory(const stm32_t *stm, uint32_t address, + uint8_t data[], unsigned int len); +stm32_err_t stm32_write_memory(const stm32_t *stm, uint32_t address, + const uint8_t data[], unsigned int len); +stm32_err_t stm32_wunprot_memory(const stm32_t *stm); +stm32_err_t stm32_wprot_memory(const stm32_t *stm); +stm32_err_t stm32_erase_memory(const stm32_t *stm, uint8_t spage, + uint8_t pages); +stm32_err_t stm32_go(const stm32_t *stm, uint32_t address); +stm32_err_t stm32_reset_device(const stm32_t *stm); +stm32_err_t stm32_readprot_memory(const stm32_t *stm); +stm32_err_t stm32_runprot_memory(const stm32_t *stm); +stm32_err_t stm32_crc_memory(const stm32_t *stm, uint32_t address, + uint32_t length, uint32_t *crc); +stm32_err_t stm32_crc_wrapper(const stm32_t *stm, uint32_t address, + uint32_t length, uint32_t *crc); +uint32_t stm32_sw_crc(uint32_t crc, uint8_t *buf, unsigned int len); + +#endif + diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/stm32flash.1 b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/stm32flash.1 new file mode 100644 index 0000000..d37292f --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/stm32flash.1 @@ -0,0 +1,407 @@ +.TH STM32FLASH 1 "2013\-11\-03" STM32FLASH "User command" +.SH NAME +stm32flash \- flashing utility for STM32 and STM32W through UART or I2C +.SH SYNOPSIS +.B stm32flash +.RB [ \-cfhjkouvCR ] +.RB [ \-a +.IR bus_address ] +.RB [ \-b +.IR baud_rate ] +.RB [ \-m +.IR serial_mode ] +.RB [ \-r +.IR filename ] +.RB [ \-w +.IR filename ] +.RB [ \-e +.IR num ] +.RB [ \-n +.IR count ] +.RB [ \-g +.IR address ] +.RB [ \-s +.IR start_page ] +.RB [ \-S +.IR address [: length ]] +.RB [ \-F +.IR RX_length [: TX_length ]] +.RB [ \-i +.IR GPIO_string ] +.RI [ tty_device +.R | +.IR i2c_device ] + +.SH DESCRIPTION +.B stm32flash +reads or writes the flash memory of STM32 and STM32W. + +It requires the STM32[W] to embed a bootloader compliant with ST +application note AN3155. +.B stm32flash +uses the serial port +.I tty_device +to interact with the bootloader of STM32[W]. + +.SH OPTIONS +.TP +.BI "\-a" " bus_address" +Specify address on bus for +.IR i2c_device . +This option is mandatory for I2C interface. + +.TP +.BI "\-b" " baud_rate" +Specify baud rate speed of +.IR tty_device . +Please notice that the ST bootloader can automatically detect the baud rate, +as explaned in chapter 2 of AN3155. +This option could be required together with option +.B "\-c" +or if following interaction with bootloader is expected. +Default is +.IR 57600 . + +.TP +.BI "\-m" " mode" +Specify the format of UART data. +.I mode +is a three characters long string where each character specifies, in +this strict order, character size, parity and stop bits. +The only values currenly used are +.I 8e1 +for standard STM32 bootloader and +.I 8n1 +for standard STM32W bootloader. +Default is +.IR 8e1 . + +.TP +.BI "\-r" " filename" +Specify to read the STM32[W] flash and write its content in +.I filename +in raw binary format (see below +.BR "FORMAT CONVERSION" ). + +.TP +.BI "\-w" " filename" +Specify to write the STM32[W] flash with the content of +.IR filename . +File format can be either raw binary or intel hex (see below +.BR "FORMAT CONVERSION" ). +The file format is automatically detected. +To by\-pass format detection and force binary mode (e.g. to +write an intel hex content in STM32[W] flash), use +.B \-f +option. + +.TP +.B \-u +Specify to disable write\-protection from STM32[W] flash. +The STM32[W] will be reset after this operation. + +.TP +.B \-j +Enable the flash read\-protection. + +.TP +.B \-k +Disable the flash read\-protection. + +.TP +.B \-o +Erase only. + +.TP +.BI "\-e" " num" +Specify to erase only +.I num +pages before writing the flash. Default is to erase the whole flash. With +.B \-e 0 +the flash would not be erased. + +.TP +.B \-v +Specify to verify flash content after write operation. + +.TP +.BI "\-n" " count" +Specify to retry failed writes up to +.I count +times. Default is 10 times. + +.TP +.BI "\-g" " address" +Specify address to start execution from (0 = flash start). + +.TP +.BI "\-s" " start_page" +Specify flash page offset (0 = flash start). + +.TP +.BI "\-S" " address" "[:" "length" "]" +Specify start address and optionally length for read/write/erase/crc operations. + +.TP +.BI "\-F" " RX_length" "[:" "TX_length" "]" +Specify the maximum frame size for the current interface. +Due to STM32 bootloader protocol, host will never handle frames bigger than +256 byte in RX or 258 byte in TX. +Due to current code, lowest limit in RX is 20 byte (to read a complete reply +of command GET). Minimum limit in TX is 5 byte, required by protocol. + +.TP +.B \-f +Force binary parser while reading file with +.BR "\-w" "." + +.TP +.B \-h +Show help. + +.TP +.B \-c +Specify to resume the existing UART connection and don't send initial +INIT sequence to detect baud rate. Baud rate must be kept the same as the +existing connection. This is useful if the reset fails. + +.TP +.BI "\-i" " GPIO_string" +Specify the GPIO sequences on the host to force STM32[W] to enter and +exit bootloader mode. GPIO can either be real GPIO connected from host to +STM32[W] beside the UART connection, or UART's modem signals used as +GPIO. (See below +.B BOOTLOADER GPIO SEQUENCE +for the format of +.I GPIO_string +and further explanation). + +.TP +.B \-C +Specify to compute CRC on memory content. +By default the CRC is computed on the whole flash content. +Use +.B "\-S" +to provide different memory address range. + +.TP +.B \-R +Specify to reset the device at exit. +This option is ignored if either +.BR "\-g" "," +.BR "\-j" "," +.B "\-k" +or +.B "\-u" +is also specified. + +.SH BOOTLOADER GPIO SEQUENCE +This feature is currently available on Linux host only. + +As explained in ST application note AN2606, after reset the STM32 will +execute either the application program in user flash or the bootloader, +depending on the level applied at specific pins of STM32 during reset. + +STM32 bootloader is automatically activated by configuring the pins +BOOT0="high" and BOOT1="low" and then by applying a reset. +Application program in user flash is activated by configuring the pin +BOOT0="low" (the level on BOOT1 is ignored) and then by applying a reset. + +When GPIO from host computer are connected to either configuration and +reset pins of STM32, +.B stm32flash +can control the host GPIO to reset STM32 and to force execution of +bootloader or execution of application program. + +The sequence of GPIO values to entry to and exit from bootloader mode is +provided with command line option +.B "\-i" +.IR "GPIO_string" . + +.PD 0 +The format of +.IR "GPIO_string" " is:" +.RS +GPIO_string = [entry sequence][:[exit sequence]] +.P +sequence = [\-]n[,sequence] +.RE +.P +In the above sequences, negative numbers correspond to GPIO at "low" level; +numbers without sign correspond to GPIO at "high" level. +The value "n" can either be the GPIO number on the host system or the +string "rts", "dtr" or "brk". The strings "rts" and "dtr" drive the +corresponding UART's modem lines RTS and DTR as GPIO. +The string "brk" forces the UART to send a BREAK sequence on TX line; +after BREAK the UART is returned in normal "non\-break" mode. +Note: the string "\-brk" has no effect and is ignored. +.PD + +.PD 0 +As example, let's suppose the following connection between host and STM32: +.IP \(bu 2 +host GPIO_3 connected to reset pin of STM32; +.IP \(bu 2 +host GPIO_4 connected to STM32 pin BOOT0; +.IP \(bu 2 +host GPIO_5 connected to STM32 pin BOOT1. +.PD +.P + +In this case, the sequence to enter in bootloader mode is: first put +GPIO_4="high" and GPIO_5="low"; then send reset pulse by GPIO_3="low" +followed by GPIO_3="high". +The corresponding string for +.I GPIO_string +is "4,\-5,\-3,3". + +To exit from bootloade and run the application program, the sequence is: +put GPIO_4="low"; then send reset pulse. +The corresponding string for +.I GPIO_string +is "\-4,\-3,3". + +The complete command line flag is "\-i 4,\-5,\-3,3:\-4,\-3,3". + +STM32W uses pad PA5 to select boot mode; if during reset PA5 is "low" then +STM32W will enter in bootloader mode; if PA5 is "high" it will execute the +program in flash. + +As example, supposing GPIO_3 connected to PA5 and GPIO_2 to STM32W's reset. +The command: +.PD 0 +.RS +stm32flash \-i \-3,\-2,2:3,\-2,2 /dev/ttyS0 +.RE +provides: +.IP \(bu 2 +entry sequence: GPIO_3=low, GPIO_2=low, GPIO_2=high +.IP \(bu 2 +exit sequence: GPIO_3=high, GPIO_2=low, GPIO_2=high +.PD + +.SH EXAMPLES +Get device information: +.RS +.PD 0 +.P +stm32flash /dev/ttyS0 +.PD +.RE + +Write with verify and then start execution: +.RS +.PD 0 +.P +stm32flash \-w filename \-v \-g 0x0 /dev/ttyS0 +.PD +.RE + +Read flash to file: +.RS +.PD 0 +.P +stm32flash \-r filename /dev/ttyS0 +.PD +.RE + +Start execution: +.RS +.PD 0 +.P +stm32flash \-g 0x0 /dev/ttyS0 +.PD +.RE + +Specify: +.PD 0 +.IP \(bu 2 +entry sequence: RTS=low, DTR=low, DTR=high +.IP \(bu 2 +exit sequence: RTS=high, DTR=low, DTR=high +.P +.RS +stm32flash \-i \-rts,\-dtr,dtr:rts,\-dtr,dtr /dev/ttyS0 +.PD +.RE + +.SH FORMAT CONVERSION +Flash images provided by ST or created with ST tools are often in file +format Motorola S\-Record. +Conversion between raw binary, intel hex and Motorola S\-Record can be +done through software package SRecord. + +.SH AUTHORS +The original software package +.B stm32flash +is written by +.I Geoffrey McRae +and is since 2012 maintained by +.IR "Tormod Volden " . + +Man page and extension to STM32W and I2C are written by +.IR "Antonio Borneo " . + +Please report any bugs at the project homepage +http://stm32flash.googlecode.com . + +.SH SEE ALSO +.BR "srec_cat" "(1)," " srec_intel" "(5)," " srec_motorola" "(5)." + +The communication protocol used by ST bootloader is documented in +following ST application notes, depending on communication port. +The current version of +.B stm32flash +only supports +.I UART +and +.I I2C +ports. +.PD 0 +.P +.IP \(bu 2 +AN3154: CAN protocol used in the STM32 bootloader +.P +.RS +http://www.st.com/web/en/resource/technical/document/application_note/CD00264321.pdf +.RE + +.P +.IP \(bu 2 +AN3155: USART protocol used in the STM32(TM) bootloader +.P +.RS +http://www.st.com/web/en/resource/technical/document/application_note/CD00264342.pdf +.RE + +.P +.IP \(bu 2 +AN4221: I2C protocol used in the STM32 bootloader +.P +.RS +http://www.st.com/web/en/resource/technical/document/application_note/DM00072315.pdf +.RE + +.P +.IP \(bu 2 +AN4286: SPI protocol used in the STM32 bootloader +.P +.RS +http://www.st.com/web/en/resource/technical/document/application_note/DM00081379.pdf +.RE + +.PD + + +Boot mode selection for STM32 is documented in ST application note +AN2606, available from the ST website: +.PD 0 +.P +http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf +.PD + +.SH LICENSE +.B stm32flash +is distributed under GNU GENERAL PUBLIC LICENSE Version 2. +Copy of the license is available within the source code in the file +.IR "gpl\-2.0.txt" . diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/utils.c b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/utils.c new file mode 100644 index 0000000..271bb3e --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/utils.c @@ -0,0 +1,45 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include "utils.h" + +/* detect CPU endian */ +char cpu_le() { + const uint32_t cpu_le_test = 0x12345678; + return ((const unsigned char*)&cpu_le_test)[0] == 0x78; +} + +uint32_t be_u32(const uint32_t v) { + if (cpu_le()) + return ((v & 0xFF000000) >> 24) | + ((v & 0x00FF0000) >> 8) | + ((v & 0x0000FF00) << 8) | + ((v & 0x000000FF) << 24); + return v; +} + +uint32_t le_u32(const uint32_t v) { + if (!cpu_le()) + return ((v & 0xFF000000) >> 24) | + ((v & 0x00FF0000) >> 8) | + ((v & 0x0000FF00) << 8) | + ((v & 0x000000FF) << 24); + return v; +} diff --git a/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/utils.h b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/utils.h new file mode 100644 index 0000000..a8d37d2 --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/stm32flash_serial/src/utils.h @@ -0,0 +1,30 @@ +/* + stm32flash - Open Source ST STM32 flash program for *nix + Copyright (C) 2010 Geoffrey McRae + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +#ifndef _H_UTILS +#define _H_UTILS + +#include + +char cpu_le(); +uint32_t be_u32(const uint32_t v); +uint32_t le_u32(const uint32_t v); + +#endif diff --git a/BootLoaders/Boards/stm32/tools/win/src/upload-reset/upload-reset.c b/BootLoaders/Boards/stm32/tools/win/src/upload-reset/upload-reset.c new file mode 100644 index 0000000..1d03bff --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/src/upload-reset/upload-reset.c @@ -0,0 +1,161 @@ +/* Copyright (C) 2015 Roger Clark + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * + * Utility to send the reset sequence on RTS and DTR and chars + * which resets the libmaple and causes the bootloader to be run + * + * + * + * Terminal control code by Heiko Noordhof (see copyright below) + */ + + + +/* Copyright (C) 2003 Heiko Noordhof + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Function prototypes (belong in a seperate header file) */ +int openserial(char *devicename); +void closeserial(void); +int setDTR(unsigned short level); +int setRTS(unsigned short level); + + +/* Two globals for use by this module only */ +static int fd; +static struct termios oldterminfo; + + +void closeserial(void) +{ + tcsetattr(fd, TCSANOW, &oldterminfo); + close(fd); +} + + +int openserial(char *devicename) +{ + struct termios attr; + + if ((fd = open(devicename, O_RDWR)) == -1) return 0; /* Error */ + atexit(closeserial); + + if (tcgetattr(fd, &oldterminfo) == -1) return 0; /* Error */ + attr = oldterminfo; + attr.c_cflag |= CRTSCTS | CLOCAL; + attr.c_oflag = 0; + if (tcflush(fd, TCIOFLUSH) == -1) return 0; /* Error */ + if (tcsetattr(fd, TCSANOW, &attr) == -1) return 0; /* Error */ + + /* Set the lines to a known state, and */ + /* finally return non-zero is successful. */ + return setRTS(0) && setDTR(0); +} + + +/* For the two functions below: + * level=0 to set line to LOW + * level=1 to set line to HIGH + */ + +int setRTS(unsigned short level) +{ + int status; + + if (ioctl(fd, TIOCMGET, &status) == -1) { + perror("setRTS(): TIOCMGET"); + return 0; + } + if (level) status |= TIOCM_RTS; + else status &= ~TIOCM_RTS; + if (ioctl(fd, TIOCMSET, &status) == -1) { + perror("setRTS(): TIOCMSET"); + return 0; + } + return 1; +} + + +int setDTR(unsigned short level) +{ + int status; + + if (ioctl(fd, TIOCMGET, &status) == -1) { + perror("setDTR(): TIOCMGET"); + return 0; + } + if (level) status |= TIOCM_DTR; + else status &= ~TIOCM_DTR; + if (ioctl(fd, TIOCMSET, &status) == -1) { + perror("setDTR: TIOCMSET"); + return 0; + } + return 1; +} + +/* This portion of code was written by Roger Clark + * It was informed by various other pieces of code written by Leaflabs to reset their + * Maple and Maple mini boards + */ + +main(int argc, char *argv[]) +{ + + if (argc<2 || argc >3) + { + printf("Usage upload-reset \n\r"); + return; + } + + if (openserial(argv[1])) + { + // Send magic sequence of DTR and RTS followed by the magic word "1EAF" + setRTS(false); + setDTR(false); + setDTR(true); + + usleep(50000L); + + setDTR(false); + setRTS(true); + setDTR(true); + + usleep(50000L); + + setDTR(false); + + usleep(50000L); + + write(fd,"1EAF",4); + + closeserial(); + if (argc==3) + { + usleep(atol(argv[2])*1000L); + } + } + else + { + printf("Failed to open serial device.\n\r"); + } +} diff --git a/BootLoaders/Boards/stm32/tools/win/stm32flash.exe b/BootLoaders/Boards/stm32/tools/win/stm32flash.exe new file mode 100644 index 0000000..911c0cc Binary files /dev/null and b/BootLoaders/Boards/stm32/tools/win/stm32flash.exe differ diff --git a/BootLoaders/Boards/stm32/tools/win/stm32loader.py b/BootLoaders/Boards/stm32/tools/win/stm32loader.py new file mode 100644 index 0000000..72602bb --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/stm32loader.py @@ -0,0 +1,537 @@ +#!/usr/bin/env python + +# -*- coding: utf-8 -*- +# vim: sw=4:ts=4:si:et:enc=utf-8 + +# Author: Ivan A-R +# Project page: http://tuxotronic.org/wiki/projects/stm32loader +# +# This file is part of stm32loader. +# +# stm32loader is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 3, or (at your option) any later +# version. +# +# stm32loader is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License +# along with stm32loader; see the file COPYING3. If not see +# . + +from __future__ import print_function + +import sys, getopt +import serial +import time +import glob +import time +import tempfile +import os +import subprocess + +try: + from progressbar import * + usepbar = 1 +except: + usepbar = 0 + +# Verbose level +QUIET = 5 + +def mdebug(level, message): + if QUIET >= level: + print(message, file=sys.stderr) + +# Takes chip IDs (obtained via Get ID command) to human-readable names +CHIP_ID_STRS = {0x410: 'STM32F1, performance, medium-density', + 0x411: 'STM32F2', + 0x412: 'STM32F1, performance, low-density', + 0x413: 'STM32F4', + 0x414: 'STM32F1, performance, high-density', + 0x416: 'STM32L1, performance, medium-density', + 0x418: 'STM32F1, connectivity', + 0x420: 'STM32F1, value, medium-density', + 0x428: 'STM32F1, value, high-density', + 0x430: 'STM32F1, performance, XL-density'} + +class CmdException(Exception): + pass + +class CommandInterface(object): + def open(self, aport='/dev/tty.usbserial-FTD3TMCH', abaudrate=115200) : + self.sp = serial.Serial( + port=aport, + baudrate=abaudrate, # baudrate + bytesize=8, # number of databits + parity=serial.PARITY_EVEN, + stopbits=1, + xonxoff=0, # enable software flow control + rtscts=0, # disable RTS/CTS flow control + timeout=0.5 # set a timeout value, None for waiting forever + ) + + + def _wait_for_ack(self, info="", timeout=0): + stop = time.time() + timeout + got = None + while not got: + got = self.sp.read(1) + if time.time() > stop: + break + + if not got: + raise CmdException("No response to %s" % info) + + # wait for ask + ask = ord(got) + + if ask == 0x79: + # ACK + return 1 + elif ask == 0x1F: + # NACK + raise CmdException("Chip replied with a NACK during %s" % info) + + # Unknown response + raise CmdException("Unrecognised response 0x%x to %s" % (ask, info)) + + def reset(self): + self.sp.setDTR(0) + time.sleep(0.1) + self.sp.setDTR(1) + time.sleep(0.5) + + def initChip(self): + # Set boot + self.sp.setRTS(0) + self.reset() + + # Be a bit more persistent when trying to initialise the chip + stop = time.time() + 5.0 + + while time.time() <= stop: + self.sp.write('\x7f') + + got = self.sp.read() + + # The chip will ACK a sync the very first time and + # NACK it every time afterwards + if got and got in '\x79\x1f': + # Synced up + return + + raise CmdException('No response while trying to sync') + + def releaseChip(self): + self.sp.setRTS(1) + self.reset() + + def cmdGeneric(self, cmd): + self.sp.write(chr(cmd)) + self.sp.write(chr(cmd ^ 0xFF)) # Control byte + return self._wait_for_ack(hex(cmd)) + + def cmdGet(self): + if self.cmdGeneric(0x00): + mdebug(10, "*** Get command"); + len = ord(self.sp.read()) + version = ord(self.sp.read()) + mdebug(10, " Bootloader version: "+hex(version)) + dat = map(lambda c: hex(ord(c)), self.sp.read(len)) + mdebug(10, " Available commands: "+str(dat)) + self._wait_for_ack("0x00 end") + return version + else: + raise CmdException("Get (0x00) failed") + + def cmdGetVersion(self): + if self.cmdGeneric(0x01): + mdebug(10, "*** GetVersion command") + version = ord(self.sp.read()) + self.sp.read(2) + self._wait_for_ack("0x01 end") + mdebug(10, " Bootloader version: "+hex(version)) + return version + else: + raise CmdException("GetVersion (0x01) failed") + + def cmdGetID(self): + if self.cmdGeneric(0x02): + mdebug(10, "*** GetID command") + len = ord(self.sp.read()) + id = self.sp.read(len+1) + self._wait_for_ack("0x02 end") + return id + else: + raise CmdException("GetID (0x02) failed") + + + def _encode_addr(self, addr): + byte3 = (addr >> 0) & 0xFF + byte2 = (addr >> 8) & 0xFF + byte1 = (addr >> 16) & 0xFF + byte0 = (addr >> 24) & 0xFF + crc = byte0 ^ byte1 ^ byte2 ^ byte3 + return (chr(byte0) + chr(byte1) + chr(byte2) + chr(byte3) + chr(crc)) + + + def cmdReadMemory(self, addr, lng): + assert(lng <= 256) + if self.cmdGeneric(0x11): + mdebug(10, "*** ReadMemory command") + self.sp.write(self._encode_addr(addr)) + self._wait_for_ack("0x11 address failed") + N = (lng - 1) & 0xFF + crc = N ^ 0xFF + self.sp.write(chr(N) + chr(crc)) + self._wait_for_ack("0x11 length failed") + return map(lambda c: ord(c), self.sp.read(lng)) + else: + raise CmdException("ReadMemory (0x11) failed") + + + def cmdGo(self, addr): + if self.cmdGeneric(0x21): + mdebug(10, "*** Go command") + self.sp.write(self._encode_addr(addr)) + self._wait_for_ack("0x21 go failed") + else: + raise CmdException("Go (0x21) failed") + + + def cmdWriteMemory(self, addr, data): + assert(len(data) <= 256) + if self.cmdGeneric(0x31): + mdebug(10, "*** Write memory command") + self.sp.write(self._encode_addr(addr)) + self._wait_for_ack("0x31 address failed") + #map(lambda c: hex(ord(c)), data) + lng = (len(data)-1) & 0xFF + mdebug(10, " %s bytes to write" % [lng+1]); + self.sp.write(chr(lng)) # len really + crc = 0xFF + for c in data: + crc = crc ^ c + self.sp.write(chr(c)) + self.sp.write(chr(crc)) + self._wait_for_ack("0x31 programming failed") + mdebug(10, " Write memory done") + else: + raise CmdException("Write memory (0x31) failed") + + + def cmdEraseMemory(self, sectors = None): + if self.cmdGeneric(0x43): + mdebug(10, "*** Erase memory command") + if sectors is None: + # Global erase + self.sp.write(chr(0xFF)) + self.sp.write(chr(0x00)) + else: + # Sectors erase + self.sp.write(chr((len(sectors)-1) & 0xFF)) + crc = 0xFF + for c in sectors: + crc = crc ^ c + self.sp.write(chr(c)) + self.sp.write(chr(crc)) + self._wait_for_ack("0x43 erasing failed") + mdebug(10, " Erase memory done") + else: + raise CmdException("Erase memory (0x43) failed") + + + # TODO support for non-global mass erase + GLOBAL_ERASE_TIMEOUT_SECONDS = 20 # This takes a while + def cmdExtendedEraseMemory(self): + if self.cmdGeneric(0x44): + mdebug(10, "*** Extended erase memory command") + # Global mass erase + mdebug(5, "Global mass erase; this may take a while") + self.sp.write(chr(0xFF)) + self.sp.write(chr(0xFF)) + # Checksum + self.sp.write(chr(0x00)) + self._wait_for_ack("0x44 extended erase failed", + timeout=self.GLOBAL_ERASE_TIMEOUT_SECONDS) + mdebug(10, " Extended erase memory done") + else: + raise CmdException("Extended erase memory (0x44) failed") + + + def cmdWriteProtect(self, sectors): + if self.cmdGeneric(0x63): + mdebug(10, "*** Write protect command") + self.sp.write(chr((len(sectors)-1) & 0xFF)) + crc = 0xFF + for c in sectors: + crc = crc ^ c + self.sp.write(chr(c)) + self.sp.write(chr(crc)) + self._wait_for_ack("0x63 write protect failed") + mdebug(10, " Write protect done") + else: + raise CmdException("Write Protect memory (0x63) failed") + + def cmdWriteUnprotect(self): + if self.cmdGeneric(0x73): + mdebug(10, "*** Write Unprotect command") + self._wait_for_ack("0x73 write unprotect failed") + self._wait_for_ack("0x73 write unprotect 2 failed") + mdebug(10, " Write Unprotect done") + else: + raise CmdException("Write Unprotect (0x73) failed") + + def cmdReadoutProtect(self): + if self.cmdGeneric(0x82): + mdebug(10, "*** Readout protect command") + self._wait_for_ack("0x82 readout protect failed") + self._wait_for_ack("0x82 readout protect 2 failed") + mdebug(10, " Read protect done") + else: + raise CmdException("Readout protect (0x82) failed") + + def cmdReadoutUnprotect(self): + if self.cmdGeneric(0x92): + mdebug(10, "*** Readout Unprotect command") + self._wait_for_ack("0x92 readout unprotect failed") + self._wait_for_ack("0x92 readout unprotect 2 failed") + mdebug(10, " Read Unprotect done") + else: + raise CmdException("Readout unprotect (0x92) failed") + + +# Complex commands section + + def readMemory(self, addr, lng): + data = [] + if usepbar: + widgets = ['Reading: ', Percentage(),', ', ETA(), ' ', Bar()] + pbar = ProgressBar(widgets=widgets,maxval=lng, term_width=79).start() + + while lng > 256: + if usepbar: + pbar.update(pbar.maxval-lng) + else: + mdebug(5, "Read %(len)d bytes at 0x%(addr)X" % {'addr': addr, 'len': 256}) + data = data + self.cmdReadMemory(addr, 256) + addr = addr + 256 + lng = lng - 256 + if usepbar: + pbar.update(pbar.maxval-lng) + pbar.finish() + else: + mdebug(5, "Read %(len)d bytes at 0x%(addr)X" % {'addr': addr, 'len': 256}) + data = data + self.cmdReadMemory(addr, lng) + return data + + def writeMemory(self, addr, data): + lng = len(data) + + mdebug(5, "Writing %(lng)d bytes to start address 0x%(addr)X" % + { 'lng': lng, 'addr': addr}) + + if usepbar: + widgets = ['Writing: ', Percentage(),' ', ETA(), ' ', Bar()] + pbar = ProgressBar(widgets=widgets, maxval=lng, term_width=79).start() + + offs = 0 + while lng > 256: + if usepbar: + pbar.update(pbar.maxval-lng) + else: + mdebug(5, "Write %(len)d bytes at 0x%(addr)X" % {'addr': addr, 'len': 256}) + self.cmdWriteMemory(addr, data[offs:offs+256]) + offs = offs + 256 + addr = addr + 256 + lng = lng - 256 + if usepbar: + pbar.update(pbar.maxval-lng) + pbar.finish() + else: + mdebug(5, "Write %(len)d bytes at 0x%(addr)X" % {'addr': addr, 'len': 256}) + self.cmdWriteMemory(addr, data[offs:offs+lng] + ([0xFF] * (256-lng)) ) + + +def usage(): + print("""Usage: %s [-hqVewvr] [-l length] [-p port] [-b baud] [-a addr] [file.bin] + -h This help + -q Quiet + -V Verbose + -e Erase + -w Write + -v Verify + -r Read + -l length Length of read + -p port Serial port (default: first USB-like port in /dev) + -b baud Baud speed (default: 115200) + -a addr Target address + + ./stm32loader.py -e -w -v example/main.bin + + """ % sys.argv[0]) + +def read(filename): + """Read the file to be programmed and turn it into a binary""" + with open(filename, 'rb') as f: + bytes = f.read() + + if bytes.startswith('\x7FELF'): + # Actually an ELF file. Convert to binary + handle, path = tempfile.mkstemp(suffix='.bin', prefix='stm32loader') + + try: + os.close(handle) + + # Try a couple of options for objcopy + for name in ['arm-none-eabi-objcopy', 'arm-linux-gnueabi-objcopy']: + try: + code = subprocess.call([name, '-Obinary', filename, path]) + + if code == 0: + return read(path) + except OSError: + pass + else: + raise Exception('Error %d while converting to a binary file' % code) + finally: + # Remove the temporary file + os.unlink(path) + else: + return [ord(x) for x in bytes] + +if __name__ == "__main__": + + conf = { + 'port': 'auto', + 'baud': 115200, + 'address': 0x08000000, + 'erase': 0, + 'write': 0, + 'verify': 0, + 'read': 0, + 'len': 1000, + 'fname':'' + } + +# http://www.python.org/doc/2.5.2/lib/module-getopt.html + + try: + opts, args = getopt.getopt(sys.argv[1:], "hqVewvrp:b:a:l:g") + except getopt.GetoptError as err: + # print help information and exit: + print(str(err)) # will print something like "option -a not recognized" + usage() + sys.exit(2) + + for o, a in opts: + if o == '-V': + QUIET = 10 + elif o == '-q': + QUIET = 0 + elif o == '-h': + usage() + sys.exit(0) + elif o == '-e': + conf['erase'] = 1 + elif o == '-w': + conf['write'] = 1 + elif o == '-v': + conf['verify'] = 1 + elif o == '-r': + conf['read'] = 1 + elif o == '-p': + conf['port'] = a + elif o == '-b': + conf['baud'] = eval(a) + elif o == '-a': + conf['address'] = eval(a) + elif o == '-l': + conf['len'] = eval(a) + elif o == '-g': + conf['go'] = 1 + else: + assert False, "unhandled option" + + # Try and find the port automatically + if conf['port'] == 'auto': + ports = [] + + # Get a list of all USB-like names in /dev + for name in ['tty.usbserial', 'ttyUSB']: + ports.extend(glob.glob('/dev/%s*' % name)) + + ports = sorted(ports) + + if ports: + # Found something - take it + conf['port'] = ports[0] + + cmd = CommandInterface() + cmd.open(conf['port'], conf['baud']) + mdebug(10, "Open port %(port)s, baud %(baud)d" % {'port':conf['port'], + 'baud':conf['baud']}) + try: + if (conf['write'] or conf['verify']): + mdebug(5, "Reading data from %s" % args[0]) + data = read(args[0]) + + try: + cmd.initChip() + except CmdException: + print("Can't init. Ensure BOOT0=1, BOOT1=0, and reset device") + + bootversion = cmd.cmdGet() + + mdebug(0, "Bootloader version 0x%X" % bootversion) + + if bootversion < 20 or bootversion >= 100: + raise Exception('Unreasonable bootloader version %d' % bootversion) + + chip_id = cmd.cmdGetID() +#assert len(chip_id) == 2, "Unreasonable chip id: %s" % repr(chip_id) + chip_id_num = (ord(chip_id[0]) << 8) | ord(chip_id[1]) + chip_id_str = CHIP_ID_STRS.get(chip_id_num, None) + + if chip_id_str is None: + mdebug(0, 'Warning: unrecognised chip ID 0x%x' % chip_id_num) + else: + mdebug(0, "Chip id 0x%x, %s" % (chip_id_num, chip_id_str)) + + if conf['erase']: + # Pre-3.0 bootloaders use the erase memory + # command. Starting with 3.0, extended erase memory + # replaced this command. + if bootversion < 0x30: + cmd.cmdEraseMemory() + else: + cmd.cmdExtendedEraseMemory() + + if conf['write']: + cmd.writeMemory(conf['address'], data) + + if conf['verify']: + verify = cmd.readMemory(conf['address'], len(data)) + if(data == verify): + print("Verification OK") + else: + print("Verification FAILED") + print(str(len(data)) + ' vs ' + str(len(verify))) + for i in xrange(0, len(data)): + if data[i] != verify[i]: + print(hex(i) + ': ' + hex(data[i]) + ' vs ' + hex(verify[i])) + + if not conf['write'] and conf['read']: + rdata = cmd.readMemory(conf['address'], conf['len']) + file(args[0], 'wb').write(''.join(map(chr,rdata))) + if conf['go']: + cmd.cmdGo(conf['address']) + print("Running from address" ) + + finally: + cmd.releaseChip() + diff --git a/BootLoaders/Boards/stm32/tools/win/tx_upload.bat b/BootLoaders/Boards/stm32/tools/win/tx_upload.bat new file mode 100644 index 0000000..23d83fe --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/tx_upload.bat @@ -0,0 +1,14 @@ +@echo off +REM Dummy 'upload' file to provide instructions for flashing the multi-module firmware from the Tx +echo. +echo Compiled .bin location: +echo %1 +echo. +echo The compiled firmware can now be copied to the \firmware folder on the transmitter for flashing using Maintenance Mode. +echo. +echo To enter Maintenance Mode hold down the two outer horizontal trim buttons while powering on the transmitter. Once in +echo Maintenance Mode follow the on-screen prompts to flash the Multi module. +echo. +echo Supported transmitters are those running ersky9x r221e2 or newer. +echo. +echo Further instructions are available at [need_url]. diff --git a/BootLoaders/Boards/stm32/variants/generic_stm32f103c/board.cpp b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/board.cpp new file mode 100644 index 0000000..8b136f2 --- /dev/null +++ b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/board.cpp @@ -0,0 +1,139 @@ +/****************************************************************************** + * 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 wirish/boards/maple_mini/board.cpp + * &author Marti Bolivar + * &brief Maple Mini board file. + */ + +#include + +#include +#include + +/* Roger Clark. Added next to includes for changes to Serial */ +#include +#include + +#include +#include + +/* Since we want the Serial Wire/JTAG pins as GPIOs, disable both SW + * and JTAG debug support, unless configured otherwise. */ +void boardInit(void) { +#ifndef CONFIG_MAPLE_MINI_NO_DISABLE_DEBUG + disableDebugPorts(); +#endif +} + +// Note. See the enum of pin names in board.h + +extern const stm32_pin_info PIN_MAP[BOARD_NR_GPIO_PINS] = { + + + {&gpioa, &timer2, &adc1, 0, 1, 0}, /* PA0 */ + {&gpioa, &timer2, &adc1, 1, 2, 1}, /* PA1 */ + {&gpioa, &timer2, &adc1, 2, 3, 2}, /* PA2 */ + {&gpioa, &timer2, &adc1, 3, 4, 3}, /* PA3 */ + {&gpioa, NULL, &adc1, 4, 0, 4}, /* PA4 */ + {&gpioa, NULL, &adc1, 5, 0, 5}, /* PA5 */ + {&gpioa, &timer3, &adc1, 6, 1, 6}, /* PA6 */ + {&gpioa, &timer3, &adc1, 7, 2, 7}, /* PA7 */ + {&gpioa, &timer1, NULL, 8, 1, ADCx}, /* PA8 */ + {&gpioa, &timer1, NULL, 9, 2, ADCx}, /* PA9 */ + {&gpioa, &timer1, NULL, 10, 3, ADCx}, /* PA10 */ + {&gpioa, &timer1, NULL, 11, 4, ADCx}, /* PA11 */ + {&gpioa, NULL, NULL, 12, 0, ADCx}, /* PA12 */ + {&gpioa, NULL, NULL, 13, 0, ADCx}, /* PA13 */ + {&gpioa, NULL, NULL, 14, 0, ADCx}, /* PA14 */ + {&gpioa, NULL, NULL, 15, 0, ADCx}, /* PA15 */ + + {&gpiob, &timer3, &adc1, 0, 3, 8}, /* PB0 */ + {&gpiob, &timer3, &adc1, 1, 4, 9}, /* PB1 */ + {&gpiob, NULL, NULL, 2, 0, ADCx}, /* PB2 */ + {&gpiob, NULL, NULL, 3, 0, ADCx}, /* PB3 */ + {&gpiob, NULL, NULL, 4, 0, ADCx}, /* PB4 */ + {&gpiob, NULL, NULL, 5, 0, ADCx}, /* PB5 */ + {&gpiob, &timer4, NULL, 6, 1, ADCx}, /* PB6 */ + {&gpiob, &timer4, NULL, 7, 2, ADCx}, /* PB7 */ + {&gpiob, &timer4, NULL, 8, 3, ADCx}, /* PB8 */ + {&gpiob, &timer4, NULL, 9, 4, ADCx}, /* PB9 */ + {&gpiob, NULL, NULL, 10, 0, ADCx}, /* PB10 */ + {&gpiob, NULL, NULL, 11, 0, ADCx}, /* PB11 */ + {&gpiob, NULL, NULL, 12, 0, ADCx}, /* PB12 */ + {&gpiob, NULL, NULL, 13, 0, ADCx}, /* PB13 */ + {&gpiob, NULL, NULL, 14, 0, ADCx}, /* PB14 */ + {&gpiob, NULL, NULL, 15, 0, ADCx}, /* PB15 */ + + {&gpioc, NULL, NULL, 13, 0, ADCx}, /* PC13 */ + {&gpioc, NULL, NULL, 14, 0, ADCx}, /* PC14 */ + {&gpioc, NULL, NULL, 15, 0, ADCx}, /* PC15 */ + + + +}; + +extern const uint8 boardPWMPins[BOARD_NR_PWM_PINS] __FLASH__ = { + PB0, PA7, PA6, PA3, PA2, PA1, PA0, PB7, PB6, PA10, PA9, PA8 +}; + +extern const uint8 boardADCPins[BOARD_NR_ADC_PINS] __FLASH__ = { + PB0, PA7, PA6 , PA5 , PA4 , PA3 , PA2 , PA1 , PA0 +}; + +// Note. These defines are not really used by generic boards. They are for Maple Serial USB +#define USB_DP PA12 +#define USB_DM PA11 + +// NOte. These definitions are not really used for generic boards, they only relate to boards modified to behave like Maple boards +extern const uint8 boardUsedPins[BOARD_NR_USED_PINS] __FLASH__ = { + USB_DP, USB_DM +}; + + +/* + * Roger Clark + * + * 2015/05/28 + * + * Moved definitions for Hardware Serial devices from HardwareSerial.cpp so that each board can define which Arduino "Serial" instance + * Maps to which hardware serial port on the microprocessor + */ + +#ifdef SERIAL_USB + DEFINE_HWSERIAL(Serial1, 1); + + DEFINE_HWSERIAL(Serial2, 2); + + DEFINE_HWSERIAL(Serial3, 3); +#else + DEFINE_HWSERIAL(Serial, 1); + + DEFINE_HWSERIAL(Serial1, 2); + + DEFINE_HWSERIAL(Serial2, 3); +#endif diff --git a/BootLoaders/Boards/stm32/variants/generic_stm32f103c/board/board.h b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/board/board.h new file mode 100644 index 0000000..c747399 --- /dev/null +++ b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/board/board.h @@ -0,0 +1,85 @@ +/****************************************************************************** + * 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 wirish/boards/maple_mini/include/board/board.h + * @author Marti Bolivar + * @brief Maple Mini board header. + * + * See wirish/boards/maple/include/board/board.h for more information + * on these definitions. + */ + +#ifndef _BOARD_GENERIC_STM32F103C_H_ +#define _BOARD_GENERIC_STM32F103C_H_ + +#define CYCLES_PER_MICROSECOND (F_CPU / 1000000U) +#define SYSTICK_RELOAD_VAL (F_CPU/1000) - 1 /* takes a cycle to reload */ + +#define BOARD_NR_USARTS 3 +#define BOARD_USART1_TX_PIN PA9 +#define BOARD_USART1_RX_PIN PA10 +#define BOARD_USART2_TX_PIN PA2 +#define BOARD_USART2_RX_PIN PA3 +#define BOARD_USART3_TX_PIN PB10 +#define BOARD_USART3_RX_PIN PB11 + +#define BOARD_NR_SPI 2 +#define BOARD_SPI1_NSS_PIN PA4 +#define BOARD_SPI1_MOSI_PIN PA7 +#define BOARD_SPI1_MISO_PIN PA6 +#define BOARD_SPI1_SCK_PIN PA5 + +#define BOARD_SPI2_NSS_PIN PB12 +#define BOARD_SPI2_MOSI_PIN PB15 +#define BOARD_SPI2_MISO_PIN PB14 +#define BOARD_SPI2_SCK_PIN PB13 + +#define BOARD_NR_GPIO_PINS 35 +#define BOARD_NR_PWM_PINS 12 +#define BOARD_NR_ADC_PINS 9 +#define BOARD_NR_USED_PINS 4 + + +#define BOARD_JTMS_SWDIO_PIN 22 +#define BOARD_JTCK_SWCLK_PIN 21 +#define BOARD_JTDI_PIN 20 +#define BOARD_JTDO_PIN 19 +#define BOARD_NJTRST_PIN 18 + +#define BOARD_USB_DISC_DEV NULL +#define BOARD_USB_DISC_BIT NULL + +#define LED_BUILTIN PC13 + +// Note this needs to match with the PIN_MAP array in board.cpp +enum { + PA0, PA1, PA2, PA3, PA4, PA5, PA6, PA7, PA8, PA9, PA10, PA11, PA12, PA13,PA14,PA15, + PB0, PB1, PB2, PB3, PB4, PB5, PB6, PB7, PB8, PB9, PB10, PB11, PB12, PB13,PB14,PB15, + PC13, PC14,PC15 +}; + +#endif diff --git a/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/bootloader_20.ld b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/bootloader_20.ld new file mode 100644 index 0000000..4de3a08 --- /dev/null +++ b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/bootloader_20.ld @@ -0,0 +1,30 @@ +/* + * libmaple linker script for "Flash" builds. + * + * A Flash build puts .text (and .rodata) in Flash, and + * .data/.bss/heap (of course) in SRAM, but offsets the sections by + * enough space to store the Maple bootloader, which lives in low + * Flash and uses low memory. + */ + +/* + * This pulls in the appropriate MEMORY declaration from the right + * subdirectory of stm32/mem/ (the environment must call ld with the + * right include directory flags to make this happen). Boards can also + * use this file to use any of libmaple's memory-related hooks (like + * where the heap should live). + */ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K + rom (rx) : ORIGIN = 0x08002000, LENGTH = 120K +} + +/* Provide memory region aliases for common.inc */ +REGION_ALIAS("REGION_TEXT", rom); +REGION_ALIAS("REGION_DATA", ram); +REGION_ALIAS("REGION_BSS", ram); +REGION_ALIAS("REGION_RODATA", rom); + +/* Let common.inc handle the real work. */ +INCLUDE common.inc diff --git a/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/common.inc b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/common.inc new file mode 100644 index 0000000..e086a58 --- /dev/null +++ b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/common.inc @@ -0,0 +1,220 @@ +/* + * Linker script for libmaple. + * + * Original author "lanchon" from ST forums, with modifications by LeafLabs. + */ + +OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") + +/* + * Configure other libraries we want in the link. + * + * libgcc, libc, and libm are common across supported toolchains. + * However, some toolchains require additional archives which aren't + * present everywhere (e.g. ARM's gcc-arm-embedded releases). + * + * To hack around this, we let the build system specify additional + * archives by putting the right extra_libs.inc (in a directory under + * toolchains/) in our search path. + */ +GROUP(libgcc.a libc.a libm.a) +INCLUDE extra_libs.inc + +/* + * These force the linker to search for vector table symbols. + * + * These symbols vary by STM32 family (and also within families). + * It's up to the build system to configure the link's search path + * properly for the target MCU. + */ +INCLUDE vector_symbols.inc + +/* STM32 vector table. */ +EXTERN(__stm32_vector_table) + +/* C runtime initialization function. */ +EXTERN(start_c) + +/* main entry point */ +EXTERN(main) + +/* Initial stack pointer value. */ +EXTERN(__msp_init) +PROVIDE(__msp_init = ORIGIN(ram) + LENGTH(ram)); + +/* Reset vector and chip reset entry point */ +EXTERN(__start__) +ENTRY(__start__) +PROVIDE(__exc_reset = __start__); + +/* Heap boundaries, for libmaple */ +EXTERN(_lm_heap_start); +EXTERN(_lm_heap_end); + +SECTIONS +{ + .text : + { + __text_start__ = .; + /* + * STM32 vector table. Leave this here. Yes, really. + */ + *(.stm32.interrupt_vector) + + /* + * Program code and vague linking + */ + *(.text .text.* .gnu.linkonce.t.*) + *(.plt) + *(.gnu.warning) + *(.glue_7t) *(.glue_7) *(.vfp11_veneer) + + *(.ARM.extab* .gnu.linkonce.armextab.*) + *(.gcc_except_table) + *(.eh_frame_hdr) + *(.eh_frame) + + . = ALIGN(4); + KEEP(*(.init)) + + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(0x4); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + } > REGION_TEXT + + /* + * End of text + */ + .text.align : + { + . = ALIGN(8); + __text_end__ = .; + } > REGION_TEXT + + /* + * .ARM.exidx exception unwinding; mandated by ARM's C++ ABI + */ + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > REGION_RODATA + __exidx_end = .; + + /* + * .data + */ + .data : + { + __data_start__ = .; + LONG(0) + . = ALIGN(8); + + *(.got.plt) *(.got) + *(.data .data.* .gnu.linkonce.d.*) + + . = ALIGN(8); + __data_end__ = .; + } > REGION_DATA AT> REGION_RODATA + + /* + * Read-only data + */ + .rodata : + { + *(.rodata .rodata.* .gnu.linkonce.r.*) + /* .USER_FLASH: We allow users to allocate into Flash here */ + *(.USER_FLASH) + /* ROM image configuration; for C startup */ + . = ALIGN(4); + _lm_rom_img_cfgp = .; + LONG(LOADADDR(.data)); + /* + * Heap: Linker scripts may choose a custom heap by overriding + * _lm_heap_start and _lm_heap_end. Otherwise, the heap is in + * internal SRAM, beginning after .bss, and growing towards + * the stack. + * + * I'm shoving these here naively; there's probably a cleaner way + * to go about this. [mbolivar] + */ + _lm_heap_start = DEFINED(_lm_heap_start) ? _lm_heap_start : _end; + _lm_heap_end = DEFINED(_lm_heap_end) ? _lm_heap_end : __msp_init; + } > REGION_RODATA + + /* + * .bss + */ + .bss : + { + . = ALIGN(8); + __bss_start__ = .; + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + __bss_end__ = .; + _end = __bss_end__; + } > REGION_BSS + + /* + * Debugging sections + */ + .stab 0 (NOLOAD) : { *(.stab) } + .stabstr 0 (NOLOAD) : { *(.stabstr) } + /* DWARF debug sections. + * Symbols in the DWARF debugging sections are relative to the beginning + * of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + + .note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) } + .ARM.attributes 0 : { KEEP (*(.ARM.attributes)) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/extra_libs.inc b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/extra_libs.inc new file mode 100644 index 0000000..dd2c84f --- /dev/null +++ b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/extra_libs.inc @@ -0,0 +1,7 @@ +/* + * Extra archives needed by ARM's GCC ARM Embedded arm-none-eabi- + * releases (https://launchpad.net/gcc-arm-embedded/). + */ + +/* This is for the provided newlib. */ +GROUP(libnosys.a) diff --git a/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/flash.ld b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/flash.ld new file mode 100644 index 0000000..9e250cd --- /dev/null +++ b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/flash.ld @@ -0,0 +1,26 @@ +/* + * libmaple linker script for "Flash" builds. + * + * A Flash build puts .text (and .rodata) in Flash, and + * .data/.bss/heap (of course) in SRAM, but offsets the sections by + * enough space to store the Maple bootloader, which lives in low + * Flash and uses low memory. + */ + +/* + * This pulls in the appropriate MEMORY declaration from the right + * subdirectory of stm32/mem/ (the environment must call ld with the + * right include directory flags to make this happen). Boards can also + * use this file to use any of libmaple's memory-related hooks (like + * where the heap should live). + */ +INCLUDE mem-flash.inc + +/* Provide memory region aliases for common.inc */ +REGION_ALIAS("REGION_TEXT", rom); +REGION_ALIAS("REGION_DATA", ram); +REGION_ALIAS("REGION_BSS", ram); +REGION_ALIAS("REGION_RODATA", rom); + +/* Let common.inc handle the real work. */ +INCLUDE common.inc diff --git a/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/flash_c8.ld b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/flash_c8.ld new file mode 100644 index 0000000..4603923 --- /dev/null +++ b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/flash_c8.ld @@ -0,0 +1,33 @@ +/* + * libmaple linker script for "Flash" builds. + * + * A Flash build puts .text (and .rodata) in Flash, and + * .data/.bss/heap (of course) in SRAM, but offsets the sections by + * enough space to store the Maple bootloader, which lives in low + * Flash and uses low memory. + */ + +/* + * This pulls in the appropriate MEMORY declaration from the right + * subdirectory of stm32/mem/ (the environment must call ld with the + * right include directory flags to make this happen). Boards can also + * use this file to use any of libmaple's memory-related hooks (like + * where the heap should live). + */ +/*INCLUDE mem-flash.inc*/ + +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 17K + rom (rx) : ORIGIN = 0x08000000, LENGTH = 44K +} + + +/* Provide memory region aliases for common.inc */ +REGION_ALIAS("REGION_TEXT", rom); +REGION_ALIAS("REGION_DATA", ram); +REGION_ALIAS("REGION_BSS", ram); +REGION_ALIAS("REGION_RODATA", rom); + +/* Let common.inc handle the real work. */ +INCLUDE common.inc diff --git a/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/jtag.ld b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/jtag.ld new file mode 100644 index 0000000..0612f95 --- /dev/null +++ b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/jtag.ld @@ -0,0 +1,31 @@ +/* + * libmaple linker script for "JTAG" builds. + * + * A "JTAG" build puts .text (and .rodata) in Flash, and + * .data/.bss/heap (of course) in SRAM, but links starting at the + * Flash and SRAM starting addresses (0x08000000 and 0x20000000 + * respectively). This will wipe out a Maple bootloader if there's one + * on the board, so only use this if you know what you're doing. + * + * Of course, a "JTAG" build is perfectly usable for upload over SWD, + * the system memory bootloader, etc. The name is just a historical + * artifact. + */ + +/* + * This pulls in the appropriate MEMORY declaration from the right + * subdirectory of stm32/mem/ (the environment must call ld with the + * right include directory flags to make this happen). Boards can also + * use this file to use any of libmaple's memory-related hooks (like + * where the heap should live). + */ +INCLUDE mem-jtag.inc + +/* Provide memory region aliases for common.inc */ +REGION_ALIAS("REGION_TEXT", rom); +REGION_ALIAS("REGION_DATA", ram); +REGION_ALIAS("REGION_BSS", ram); +REGION_ALIAS("REGION_RODATA", rom); + +/* Let common.inc handle the real work. */ +INCLUDE common.inc diff --git a/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/jtag_c8.ld b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/jtag_c8.ld new file mode 100644 index 0000000..d9d4a0f --- /dev/null +++ b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/jtag_c8.ld @@ -0,0 +1,36 @@ +/* + * libmaple linker script for "JTAG" builds. + * + * A "JTAG" build puts .text (and .rodata) in Flash, and + * .data/.bss/heap (of course) in SRAM, but links starting at the + * Flash and SRAM starting addresses (0x08000000 and 0x20000000 + * respectively). This will wipe out a Maple bootloader if there's one + * on the board, so only use this if you know what you're doing. + * + * Of course, a "JTAG" build is perfectly usable for upload over SWD, + * the system memory bootloader, etc. The name is just a historical + * artifact. + */ + +/* + * This pulls in the appropriate MEMORY declaration from the right + * subdirectory of stm32/mem/ (the environment must call ld with the + * right include directory flags to make this happen). Boards can also + * use this file to use any of libmaple's memory-related hooks (like + * where the heap should live). + */ + +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K + rom (rx) : ORIGIN = 0x08000000, LENGTH = 64K +} + +/* Provide memory region aliases for common.inc */ +REGION_ALIAS("REGION_TEXT", rom); +REGION_ALIAS("REGION_DATA", ram); +REGION_ALIAS("REGION_BSS", ram); +REGION_ALIAS("REGION_RODATA", rom); + +/* Let common.inc handle the real work. */ +INCLUDE common.inc diff --git a/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/mem-flash.inc b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/mem-flash.inc new file mode 100644 index 0000000..a9091ca --- /dev/null +++ b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/mem-flash.inc @@ -0,0 +1,5 @@ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 17K + rom (rx) : ORIGIN = 0x08005000, LENGTH = 108K +} diff --git a/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/mem-jtag.inc b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/mem-jtag.inc new file mode 100644 index 0000000..20fbec0 --- /dev/null +++ b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/mem-jtag.inc @@ -0,0 +1,5 @@ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K +} diff --git a/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/mem-ram.inc b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/mem-ram.inc new file mode 100644 index 0000000..f02453b --- /dev/null +++ b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/mem-ram.inc @@ -0,0 +1,5 @@ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 17K + rom (rx) : ORIGIN = 0x08005000, LENGTH = 0K +} diff --git a/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/ram.ld b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/ram.ld new file mode 100644 index 0000000..34b468e --- /dev/null +++ b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/ram.ld @@ -0,0 +1,25 @@ +/* + * libmaple linker script for RAM builds. + * + * A Flash build puts .text, .rodata, and .data/.bss/heap (of course) + * in SRAM, but offsets the sections by enough space to store the + * Maple bootloader, which uses low memory. + */ + +/* + * This pulls in the appropriate MEMORY declaration from the right + * subdirectory of stm32/mem/ (the environment must call ld with the + * right include directory flags to make this happen). Boards can also + * use this file to use any of libmaple's memory-related hooks (like + * where the heap should live). + */ +INCLUDE mem-ram.inc + +/* Provide memory region aliases for common.inc */ +REGION_ALIAS("REGION_TEXT", ram); +REGION_ALIAS("REGION_DATA", ram); +REGION_ALIAS("REGION_BSS", ram); +REGION_ALIAS("REGION_RODATA", ram); + +/* Let common.inc handle the real work. */ +INCLUDE common.inc diff --git a/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/ram_c8.ld b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/ram_c8.ld new file mode 100644 index 0000000..71e081e --- /dev/null +++ b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/ram_c8.ld @@ -0,0 +1,31 @@ +/* + * libmaple linker script for RAM builds. + * + * A Flash build puts .text, .rodata, and .data/.bss/heap (of course) + * in SRAM, but offsets the sections by enough space to store the + * Maple bootloader, which uses low memory. + */ + +/* + * This pulls in the appropriate MEMORY declaration from the right + * subdirectory of stm32/mem/ (the environment must call ld with the + * right include directory flags to make this happen). Boards can also + * use this file to use any of libmaple's memory-related hooks (like + * where the heap should live). + */ +/*INCLUDE mem-ram.inc*/ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 17K + rom (rx) : ORIGIN = 0x08005000, LENGTH = 0 +} + + +/* Provide memory region aliases for common.inc */ +REGION_ALIAS("REGION_TEXT", ram); +REGION_ALIAS("REGION_DATA", ram); +REGION_ALIAS("REGION_BSS", ram); +REGION_ALIAS("REGION_RODATA", ram); + +/* Let common.inc handle the real work. */ +INCLUDE common.inc diff --git a/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/vector_symbols.inc b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/vector_symbols.inc new file mode 100644 index 0000000..f8519bb --- /dev/null +++ b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/ld/vector_symbols.inc @@ -0,0 +1,78 @@ +EXTERN(__msp_init) +EXTERN(__exc_reset) +EXTERN(__exc_nmi) +EXTERN(__exc_hardfault) +EXTERN(__exc_memmanage) +EXTERN(__exc_busfault) +EXTERN(__exc_usagefault) +EXTERN(__stm32reservedexception7) +EXTERN(__stm32reservedexception8) +EXTERN(__stm32reservedexception9) +EXTERN(__stm32reservedexception10) +EXTERN(__exc_svc) +EXTERN(__exc_debug_monitor) +EXTERN(__stm32reservedexception13) +EXTERN(__exc_pendsv) +EXTERN(__exc_systick) + +EXTERN(__irq_wwdg) +EXTERN(__irq_pvd) +EXTERN(__irq_tamper) +EXTERN(__irq_rtc) +EXTERN(__irq_flash) +EXTERN(__irq_rcc) +EXTERN(__irq_exti0) +EXTERN(__irq_exti1) +EXTERN(__irq_exti2) +EXTERN(__irq_exti3) +EXTERN(__irq_exti4) +EXTERN(__irq_dma1_channel1) +EXTERN(__irq_dma1_channel2) +EXTERN(__irq_dma1_channel3) +EXTERN(__irq_dma1_channel4) +EXTERN(__irq_dma1_channel5) +EXTERN(__irq_dma1_channel6) +EXTERN(__irq_dma1_channel7) +EXTERN(__irq_adc) +EXTERN(__irq_usb_hp_can_tx) +EXTERN(__irq_usb_lp_can_rx0) +EXTERN(__irq_can_rx1) +EXTERN(__irq_can_sce) +EXTERN(__irq_exti9_5) +EXTERN(__irq_tim1_brk) +EXTERN(__irq_tim1_up) +EXTERN(__irq_tim1_trg_com) +EXTERN(__irq_tim1_cc) +EXTERN(__irq_tim2) +EXTERN(__irq_tim3) +EXTERN(__irq_tim4) +EXTERN(__irq_i2c1_ev) +EXTERN(__irq_i2c1_er) +EXTERN(__irq_i2c2_ev) +EXTERN(__irq_i2c2_er) +EXTERN(__irq_spi1) +EXTERN(__irq_spi2) +EXTERN(__irq_usart1) +EXTERN(__irq_usart2) +EXTERN(__irq_usart3) +EXTERN(__irq_exti15_10) +EXTERN(__irq_rtcalarm) +EXTERN(__irq_usbwakeup) + +EXTERN(__irq_tim8_brk) +EXTERN(__irq_tim8_up) +EXTERN(__irq_tim8_trg_com) +EXTERN(__irq_tim8_cc) +EXTERN(__irq_adc3) +EXTERN(__irq_fsmc) +EXTERN(__irq_sdio) +EXTERN(__irq_tim5) +EXTERN(__irq_spi3) +EXTERN(__irq_uart4) +EXTERN(__irq_uart5) +EXTERN(__irq_tim6) +EXTERN(__irq_tim7) +EXTERN(__irq_dma2_channel1) +EXTERN(__irq_dma2_channel2) +EXTERN(__irq_dma2_channel3) +EXTERN(__irq_dma2_channel4_5) diff --git a/BootLoaders/Boards/stm32/variants/generic_stm32f103c/pins_arduino.h b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/pins_arduino.h new file mode 100644 index 0000000..3052f2e --- /dev/null +++ b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/pins_arduino.h @@ -0,0 +1,6 @@ + + + + +// API compatibility +#include "variant.h" \ No newline at end of file diff --git a/BootLoaders/Boards/stm32/variants/generic_stm32f103c/variant.h b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/variant.h new file mode 100644 index 0000000..4c08d06 --- /dev/null +++ b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/variant.h @@ -0,0 +1,22 @@ +#ifndef _VARIANT_ARDUINO_STM32_ +#define _VARIANT_ARDUINO_STM32_ + +#define digitalPinToPort(P) ( PIN_MAP[P].gpio_device ) +#define digitalPinToBitMask(P) ( BIT(PIN_MAP[P].gpio_bit) ) +#define portOutputRegister(port) ( &(port->regs->ODR) ) +#define portInputRegister(port) ( &(port->regs->IDR) ) + +#define portSetRegister(pin) ( &(PIN_MAP[pin].gpio_device->regs->BSRR) ) +#define portClearRegister(pin) ( &(PIN_MAP[pin].gpio_device->regs->BRR) ) + +#define portConfigRegister(pin) ( &(PIN_MAP[pin].gpio_device->regs->CRL) ) + +static const uint8_t SS = BOARD_SPI1_NSS_PIN; +static const uint8_t SS1 = BOARD_SPI2_NSS_PIN; +static const uint8_t MOSI = BOARD_SPI1_MOSI_PIN; +static const uint8_t MISO = BOARD_SPI1_MISO_PIN; +static const uint8_t SCK = BOARD_SPI1_SCK_PIN; + +#define LED_BUILTIN PC13 + +#endif /* _VARIANT_ARDUINO_STM32_ */ diff --git a/BootLoaders/Boards/stm32/variants/generic_stm32f103c/wirish/boards.cpp b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/wirish/boards.cpp new file mode 100644 index 0000000..0a358ee --- /dev/null +++ b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/wirish/boards.cpp @@ -0,0 +1,229 @@ +/****************************************************************************** + * 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 + * 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.cpp + * @brief init() and board routines. + * + * This file is mostly interesting for the init() function, which + * configures Flash, the core 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. 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. + * + * How init() works is chip-specific. See the boards_setup.cpp files + * under e.g. wirish/stm32f1/, wirish/stmf32f2 for the details, but be + * advised: their contents are unstable, and can/will change without + * notice. + */ + +#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 setup_adcs(void); +static void setup_timers(void); + +/* + * Exported functions + */ + +void init(void) { + setup_flash(); + setup_clocks(); + setup_nvic(); + systick_init(SYSTICK_RELOAD_VAL); + wirish::priv::board_setup_gpio(); + setup_adcs(); + setup_timers(); + wirish::priv::board_setup_usb(); + wirish::priv::series_init(); + boardInit(); +} + +/* Provide a default no-op boardInit(). */ +__weak void boardInit(void) { +} + +/* You could farm this out to the files in boards/ if e.g. it takes + * too long to test on boards with lots of pins. */ +bool boardUsesPin(uint8 pin) { + for (int i = 0; i < BOARD_NR_USED_PINS; i++) { + if (pin == boardUsedPins[i]) { + return true; + } + } + return false; +} + +/* + * 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); +} + +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::w_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); +} + +/* + * These addresses are where usercode starts when a bootloader is + * present. If no bootloader is present, the user NVIC usually starts + * at the Flash base address, 0x08000000. + */ +#if defined(BOOTLOADER_maple) + #define USER_ADDR_ROM 0x08005000 +#else + #if defined(BOOTLOADER_robotis) + #define USER_ADDR_ROM 0x08003000 + #else + #define USER_ADDR_ROM 0x08000000 + #endif +#endif +#define USER_ADDR_RAM 0x20000C00 +extern char __text_start__; + +static void setup_nvic(void) { + +nvic_init((uint32)VECT_TAB_ADDR, 0); + +/* Roger Clark. We now control nvic vector table in boards.txt using the build.vect paramater +#ifdef VECT_TAB_FLASH + nvic_init(USER_ADDR_ROM, 0); +#elif defined VECT_TAB_RAM + nvic_init(USER_ADDR_RAM, 0); +#elif defined VECT_TAB_BASE + nvic_init((uint32)0x08000000, 0); +#elif defined VECT_TAB_ADDR + // A numerically supplied value + nvic_init((uint32)VECT_TAB_ADDR, 0); +#else + // Use the __text_start__ value from the linker script; this + // should be the start of the vector table. + nvic_init((uint32)&__text_start__, 0); +#endif + +*/ +} + +static void adc_default_config( adc_dev *dev) { + adc_enable_single_swstart(dev); + adc_set_sample_rate(dev, wirish::priv::w_adc_smp); +} + +static void setup_adcs(void) { + adc_set_prescaler(wirish::priv::w_adc_pre); + adc_foreach(adc_default_config); +} + +static void timer_default_config(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 (uint8 channel = 1; channel <= 4; channel++) { + if (timer_has_cc_channel(dev, 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_generate_update(dev); + timer_resume(dev); +} + +static void setup_timers(void) { + timer_foreach(timer_default_config); +} diff --git a/BootLoaders/Boards/stm32/variants/generic_stm32f103c/wirish/boards_setup.cpp b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/wirish/boards_setup.cpp new file mode 100644 index 0000000..6ab16e8 --- /dev/null +++ b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/wirish/boards_setup.cpp @@ -0,0 +1,110 @@ +/****************************************************************************** + * 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. + * + * This file controls how init() behaves on the STM32F1. Be very + * careful when changing anything here. Many of these values depend + * upon each other. + */ + +#include "boards_private.h" + +#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. +// (We're leaving the default to RCC_PLLMUL_9 for now, since that +// works for F103 performance line MCUs, which is all that LeafLabs +// currently officially supports). +#ifndef BOARD_RCC_PLLMUL + #if F_CPU==128000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_16 + #elif F_CPU==72000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_9 + #elif F_CPU==48000000 + #define BOARD_RCC_PLLMUL RCC_PLLMUL_6 + #endif +#endif + +namespace wirish { + namespace priv { + + static stm32f1_rcc_pll_data pll_data = {BOARD_RCC_PLLMUL}; + __weak rcc_pll_cfg w_board_pll_cfg = {RCC_PLLSRC_HSE, &pll_data}; + __weak adc_prescaler w_adc_pre = ADC_PRE_PCLK2_DIV_6; + __weak adc_smp_rate w_adc_smp = ADC_SMPR_55_5; + + __weak void board_reset_pll(void) { + // TODO + } + + __weak 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); + rcc_clk_disable(RCC_USB); + #if F_CPU == 72000000 + rcc_set_prescaler(RCC_PRESCALER_USB, RCC_USB_SYSCLK_DIV_1_5); + #elif F_CPU == 48000000 + rcc_set_prescaler(RCC_PRESCALER_USB, RCC_USB_SYSCLK_DIV_1); + #endif + } + + __weak void board_setup_gpio(void) { + gpio_init_all(); + } + + __weak void board_setup_usb(void) { +#ifdef SERIAL_USB + +#ifdef GENERIC_BOOTLOADER + //Reset the USB interface on generic boards - developed by Victor PV + gpio_set_mode(PIN_MAP[PA12].gpio_device, PIN_MAP[PA12].gpio_bit, GPIO_OUTPUT_PP); + gpio_write_bit(PIN_MAP[PA12].gpio_device, PIN_MAP[PA12].gpio_bit,0); + + for(volatile unsigned int i=0;i<512;i++);// Only small delay seems to be needed, and USB pins will get configured in Serial.begin + gpio_set_mode(PIN_MAP[PA12].gpio_device, PIN_MAP[PA12].gpio_bit, GPIO_INPUT_FLOATING); +#endif + Serial.begin();// Roger Clark. Changed SerialUSB to Serial for Arduino sketch compatibility +#endif + } + + __weak void series_init(void) { + // Initialize AFIO here, too, so peripheral remaps and external + // interrupts work out of the box. + afio_init(); + } + + } +} diff --git a/BootLoaders/Boards/stm32/variants/generic_stm32f103c/wirish/start.S b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/wirish/start.S new file mode 100644 index 0000000..8b181aa --- /dev/null +++ b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/wirish/start.S @@ -0,0 +1,57 @@ +/****************************************************************************** + * 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. + *****************************************************************************/ + +/* + * This file is a modified version of a file obtained from + * CodeSourcery Inc. (now part of Mentor Graphics Corp.), in which the + * following text appeared: + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + */ + + .text + .code 16 + .thumb_func + + .globl __start__ + .type __start__, %function +__start__: + .fnstart + ldr r1,=__msp_init + mov sp,r1 + ldr r1,=start_c + bx r1 + .pool + .cantunwind + .fnend diff --git a/BootLoaders/Boards/stm32/variants/generic_stm32f103c/wirish/start_c.c b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/wirish/start_c.c new file mode 100644 index 0000000..655fefb --- /dev/null +++ b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/wirish/start_c.c @@ -0,0 +1,95 @@ +/****************************************************************************** + * 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. + *****************************************************************************/ + +/* + * This file is a modified version of a file obtained from + * CodeSourcery Inc. (now part of Mentor Graphics Corp.), in which the + * following text appeared: + * + * Copyright (c) 2006, 2007 CodeSourcery Inc + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + */ + +#include + +extern void __libc_init_array(void); + +extern int main(int, char**, char**); + +extern void exit(int) __attribute__((noreturn, weak)); + +/* The linker must ensure that these are at least 4-byte aligned. */ +extern char __data_start__, __data_end__; +extern char __bss_start__, __bss_end__; + +struct rom_img_cfg { + int *img_start; +}; + +extern char _lm_rom_img_cfgp; + +void __attribute__((noreturn)) start_c(void) { + struct rom_img_cfg *img_cfg = (struct rom_img_cfg*)&_lm_rom_img_cfgp; + int *src = img_cfg->img_start; + int *dst = (int*)&__data_start__; + int exit_code; + + /* Initialize .data, if necessary. */ + if (src != dst) { + int *end = (int*)&__data_end__; + while (dst < end) { + *dst++ = *src++; + } + } + + /* Zero .bss. */ + dst = (int*)&__bss_start__; + while (dst < (int*)&__bss_end__) { + *dst++ = 0; + } + + /* Run initializers. */ + __libc_init_array(); + + /* Jump to main. */ + exit_code = main(0, 0, 0); + if (exit) { + exit(exit_code); + } + + /* If exit is NULL, make sure we don't return. */ + for (;;) + continue; +} diff --git a/BootLoaders/Boards/stm32/variants/generic_stm32f103c/wirish/syscalls.c b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/wirish/syscalls.c new file mode 100644 index 0000000..d5f2d9f --- /dev/null +++ b/BootLoaders/Boards/stm32/variants/generic_stm32f103c/wirish/syscalls.c @@ -0,0 +1,176 @@ +/****************************************************************************** + * 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 + * 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 +#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 ((void *)&_lm_heap_start) +#endif +#ifndef CONFIG_HEAP_END +extern char _lm_heap_end; +#define CONFIG_HEAP_END ((void *)&_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. + */ +void *_sbrk(int incr) { + static void * pbreak = NULL; /* current program break */ + void * ret; + + if (pbreak == NULL) { + pbreak = CONFIG_HEAP_START; + } + + if ((CONFIG_HEAP_END - pbreak < incr) || + (pbreak - CONFIG_HEAP_START < -incr)) { + errno = ENOMEM; + return (void *)-1; + } + + ret = pbreak; + pbreak += incr; + return ret; +} + +__weak int _open(const char *path, int flags, ...) { + return 1; +} + +__weak int _close(int fd) { + return 0; +} + +__weak int _fstat(int fd, struct stat *st) { + st->st_mode = S_IFCHR; + return 0; +} + +__weak int _isatty(int fd) { + return 1; +} + +__weak int isatty(int fd) { + return 1; +} + +__weak int _lseek(int fd, off_t pos, int whence) { + return -1; +} + +__weak unsigned char getch(void) { + return 0; +} + + +__weak int _read(int fd, char *buf, size_t cnt) { + *buf = getch(); + + return 1; +} + +__weak void putch(unsigned char c) { +} + +__weak 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; +} + +__weak 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 */ +__weak char *fgets(char *s, int bufsize, void *f) { + cgets(s, bufsize); + return s; +} + +__weak void _exit(int exitcode) { + while (1) + ; +} diff --git a/BootLoaders/package_multi_4in1_board_index.json b/BootLoaders/package_multi_4in1_board_index.json index 72cf2fb..5ffaee0 100644 --- a/BootLoaders/package_multi_4in1_board_index.json +++ b/BootLoaders/package_multi_4in1_board_index.json @@ -1,33 +1,51 @@ { - "packages": [ - { - "name": "Multi 4-in-1", - "maintainer": "Pascal Langer", - "websiteURL": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module", - "email": "pascal_langer@yahoo.fr", - "help": { - "online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module" + "packages": [{ + "name": "multi4in1", + "maintainer": "Pascal Langer", + "websiteURL": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module", + "email": "pascal_langer@yahoo.fr", + "help": { + "online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module" + }, + "platforms": [{ + "name": "Multi 4-in-1 AVR Board", + "architecture": "avr", + "version": "1.0.0", + "category": "Contributed", + "help": { + "online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module" + }, + "url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/stm32-board/BootLoaders/package_multi_4in1_board_v1.0.0.zip", + "archiveFileName": "package_multi_4in1_board_v1.0.0.zip", + "checksum": "SHA-256:3DE301E9FC3C8A81CB2CEDE3458A68C626A9A5C37A73FA9C85BE9D841935684D", + "size": "3205", + "boards": [{ + "name": "Multi 4-in-1 (Atmega328p, 3.3V, 16MHz)" + }], + "toolsDependencies": [] }, - "platforms": [ - { - "name": "Multi 4-in-1 AVR Board", - "architecture": "avr", - "version": "1.0", - "category": "Contributed", - "help": { - "online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module" - }, - "url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/raw/master/BootLoaders/package_multi_4in1_board_v1.0.0.zip", - "archiveFileName": "package_multi_4in1_board_v1.0.0.zip", - "checksum": "SHA-256:18388AD5C6FDBA45474D1B69D7521A5AFBCF5A2790D9EB0D91E07508BC2B40F9", - "size": "3201", - "boards": [ - {"name": "Multi 4-in-1 (Atmega328p, 3.3V, 16MHz)"} - ], - "toolsDependencies": [] - } - ], - "tools": [] - } - ] + { + "name": "Multi 4-in-1 STM32 Board", + "architecture": "STM32F1", + "version": "1.0.0", + "category": "Contributed", + "help": { + "online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module" + }, + "url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/raw/stm32-board/BootLoaders/package_multi_4in1_stm32_board_v1.0.0.zip", + "archiveFileName": "package_multi_4in1_stm32_board_v1.0.0.zip", + "checksum": "SHA-256:7B661C6455F5AD7329E61EC297D4ADED9EF19F618E04E09A35A3C840977A56F5", + "size": "10896168", + "boards": [{ + "name": "Multi 4-in-1 (STM32F103C)" + }], + "toolsDependencies": [{ + "packager": "arduino", + "name": "arm-none-eabi-gcc", + "version": "4.8.3-2014q1" + }] + } + ], + "tools": [] + }] } diff --git a/BootLoaders/package_multi_4in1_board_v1.0.0.zip b/BootLoaders/package_multi_4in1_board_v1.0.0.zip index 40818ee..a3bfedb 100644 Binary files a/BootLoaders/package_multi_4in1_board_v1.0.0.zip and b/BootLoaders/package_multi_4in1_board_v1.0.0.zip differ diff --git a/BootLoaders/package_multi_4in1_stm32_board_v1.0.0.zip b/BootLoaders/package_multi_4in1_stm32_board_v1.0.0.zip new file mode 100644 index 0000000..ef6fcd9 Binary files /dev/null and b/BootLoaders/package_multi_4in1_stm32_board_v1.0.0.zip differ diff --git a/Multiprotocol/Validate.h b/Multiprotocol/Validate.h index c8d4204..9eb3328 100644 --- a/Multiprotocol/Validate.h +++ b/Multiprotocol/Validate.h @@ -13,16 +13,16 @@ #endif #if defined (STM32_BOARD) && not defined (ORANGE_TX) //STM32 - #ifndef ARDUINO_GENERIC_STM32F103C - #error You must select the board type "Generic STM32F103C series" + #if not defined(ARDUINO_GENERIC_STM32F103C) && not defined(ARDUINO_MULTI_STM32_FLASH_FROM_TX) && not defined(ARDUINO_MULTI_STM32_NO_BOOT) + #error You must select one of these boards: "Multi 4-in-1 (STM32F103CB)" or "Generic STM32F103C series" #endif #endif //Change/Force configuration for the bootloader option -#if defined ARDUINO_MULTI_FLASH_FROM_TX +#if defined(ARDUINO_MULTI_FLASH_FROM_TX) || defined(ARDUINO_MULTI_STM32_FLASH_FROM_TX) #define CHECK_FOR_BOOTLOADER #endif -#if defined ARDUINO_MULTI_NO_BOOT +#if defined (ARDUINO_MULTI_NO_BOOT) || defined(ARDUINO_MULTI_STM32_NO_BOOT) #undef CHECK_FOR_BOOTLOADER #endif diff --git a/docs/images/boards-menu.jpg b/docs/images/boards-menu.jpg new file mode 100644 index 0000000..bdcba3e Binary files /dev/null and b/docs/images/boards-menu.jpg differ diff --git a/docs/images/ide-prefs.jpg b/docs/images/ide-prefs.jpg new file mode 100644 index 0000000..570bfa4 Binary files /dev/null and b/docs/images/ide-prefs.jpg differ diff --git a/docs/images/multi-boards.jpg b/docs/images/multi-boards.jpg new file mode 100644 index 0000000..d4c5401 Binary files /dev/null and b/docs/images/multi-boards.jpg differ