diff --git a/.gitmodules b/.gitmodules index f9fbe82..c4a0df1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "libopencm3"] path = libopencm3 - url = https://github.com/devanlai/libopencm3.git + url = https://github.com/libopencm3/libopencm3.git diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d3b95f8 --- /dev/null +++ b/Makefile @@ -0,0 +1,96 @@ +## Copyright (c) 2017, Devan Lai +## +## Permission to use, copy, modify, and/or distribute this software +## for any purpose with or without fee is hereby granted, provided +## that the above copyright notice and this permission notice +## appear in all copies. +## +## THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +## WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +## WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +## AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR +## CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +## LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +## NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +## CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +# This Makefile builds all official targets and places the firmware +# bin files in the build/ directory. +# +# For normal development, use the Makefile in the src/ directory. + +# Be silent per default, but 'make V=1' will show all compiler calls. +ifneq ($(V),1) +Q := @ +NULL := 2>/dev/null +MAKE := $(MAKE) --no-print-directory +endif +export V + +BUILD_DIR ?= ./build + +all: MSCboot-Bluepill.bin \ + MSCboot-Bluepill_072.bin \ + MSCboot-MapleMini.bin \ + MSCboot-ERCF-CAN.bin \ + MSCboot-Clockwork2-CAN_103.bin \ + MSCboot-Clockwork2-CAN_072.bin \ + MSCboot-STM32F103.bin \ + MSCboot-STM32F072.bin + +clean: + $(Q)$(RM) $(BUILD_DIR)/*.bin + $(Q)$(MAKE) -C src/ clean + +.PHONY = all clean + +$(BUILD_DIR): + $(Q)mkdir -p $(BUILD_DIR) + +MSCboot-Bluepill.bin: | $(BUILD_DIR) + @printf " BUILD $(@)\n" + $(Q)$(MAKE) TARGET=BLUEPILL -C src/ clean + $(Q)$(MAKE) TARGET=BLUEPILL -C src/ + $(Q)cp src/build/BLUEPILL/MSCboot.bin $(BUILD_DIR)/$(@) + +MSCboot-Bluepill_072.bin: | $(BUILD_DIR) + @printf " BUILD $(@)\n" + $(Q)$(MAKE) TARGET=BLUEPILL_072 -C src/ clean + $(Q)$(MAKE) TARGET=BLUEPILL_072 -C src/ + $(Q)cp src/build/BLUEPILL_072/MSCboot.bin $(BUILD_DIR)/$(@) + +MSCboot-MapleMini.bin: | $(BUILD_DIR) + @printf " BUILD $(@)\n" + $(Q)$(MAKE) TARGET=MAPLEMINI -C src/ clean + $(Q)$(MAKE) TARGET=MAPLEMINI -C src/ + $(Q)cp src/build/MAPLEMINI/MSCboot.bin $(BUILD_DIR)/$(@) + +MSCboot-ERCF-CAN.bin: | $(BUILD_DIR) + @printf " BUILD $(@)\n" + $(Q)$(MAKE) TARGET=ERCF-CAN -C src/ clean + $(Q)$(MAKE) TARGET=ERCF-CAN -C src/ + $(Q)cp src/build/ERCF-CAN/MSCboot.bin $(BUILD_DIR)/$(@) + +MSCboot-Clockwork2-CAN_103.bin: | $(BUILD_DIR) + @printf " BUILD $(@)\n" + $(Q)$(MAKE) TARGET=Clockwork2-CAN_103 -C src/ clean + $(Q)$(MAKE) TARGET=Clockwork2-CAN_103 -C src/ + $(Q)cp src/build/Clockwork2-CAN_103/MSCboot.bin $(BUILD_DIR)/$(@) + +MSCboot-Clockwork2-CAN_072.bin: | $(BUILD_DIR) + @printf " BUILD $(@)\n" + $(Q)$(MAKE) TARGET=Clockwork2-CAN_072 -C src/ clean + $(Q)$(MAKE) TARGET=Clockwork2-CAN_072 -C src/ + $(Q)cp src/build/Clockwork2-CAN_072/MSCboot.bin $(BUILD_DIR)/$(@) + +MSCboot-STM32F103.bin: | $(BUILD_DIR) + @printf " BUILD $(@)\n" + $(Q)$(MAKE) TARGET=STM32F103 -C src/ clean + $(Q)$(MAKE) TARGET=STM32F103 -C src/ + $(Q)cp src/build/STM32F103/MSCboot.bin $(BUILD_DIR)/$(@) + +MSCboot-STM32F072.bin: | $(BUILD_DIR) + @printf " BUILD $(@)\n" + $(Q)$(MAKE) TARGET=STM32F072 -C src/ clean + $(Q)$(MAKE) TARGET=STM32F072 -C src/ + $(Q)cp src/build/STM32F072/MSCboot.bin $(BUILD_DIR)/$(@) \ No newline at end of file diff --git a/README.md b/README.md index 032c40e..b19e744 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,7 @@ -# MSC bootloader for STM32F103 +# MSC bootloader for STM32F072 and STM32F103 This project was initially forked off https://github.com/mmoskal/uf2-stm32f103 though the UF2 functionality has been removed and replaced with the ability to load .bin firmware files. -The size of the bootloader has been reduced to 8KiB. - -## Flashing bootloader from binaries - -You will need a STLink/v2 (or other debugger) to flash it. - -* https://github.com/mmoskal/uf2-stm32f103/releases -* download the latest ZIP file (`uf2-stm32f103-vX.Y.Z.zip`) -* run: `openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg -c "program uf2boot-BLUEPILL.bin verify reset exit 0x8000000"` -* see if a USB drive appears; if not reset the board twice; the LED should be fading in and out about once per second ## Build instructions The default target is a generic STM32F103 dev board with an LED on PC13, commonly referred to as a "bluepill" board. @@ -20,43 +10,36 @@ To build other targets, you can override the `TARGET` variable when invoking `make`. make clean - make TARGET=STLINK + make TARGET=MAPLEMINI ### Targets -| Target Name | Description | Link | -| ----------- | ----------- |----- | -|`BLUEPILL` | Cheap dev board | http://wiki.stm32duino.com/index.php?title=Blue_Pill | -|`MAPLEMINI` | LeafLabs Maple Mini board and clone derivatives | http://wiki.stm32duino.com/index.php?title=Maple_Mini | - +| Target Name | Description | Bootloader offset | Link | +| ----------- | ----------- |------------------ | ---- | +|`STM32F103` | Generic STM32F103 target without LED | 8KiB | | +|`STM32F072` | Generic STM32F072 target without LED | 16KiB | | +|`BLUEPILL` | Cheap dev board | 8KiB | http://wiki.stm32duino.com/index.php?title=Blue_Pill | +|`MAPLEMINI` | LeafLabs Maple Mini board and clone derivatives | 8KiB | http://wiki.stm32duino.com/index.php?title=Maple_Mini | -## Flash instructions - -The `make flash` target will use openocd to upload the bootloader to an attached board. -By default, the Makefile assumes you're using a STLink v2 based probe, but you can override this by overriding `OOCD_INTERFACE` variable. For example: - - make OOCD_INTERFACE=interface/cmsis-dap.cfg flash ## Overriding defaults Local makefile settings can be set by creating a `local.mk`, which is automatically included. -Here is an example `local.mk` that changes the default target to the STLink/v2 and uses an unmodified STLink/v2 to flash it. +Here is an example `local.mk` that changes the default target to the MAPLEMINI. TARGET ?= STLINK - OOCD_INTERFACE ?= interface/stlink-v2.cfg ## Using the bootloader ### Building for the bootloader -The bootloader occupies the lower 8KiB of flash, so your application must offset its flash contents by 8KiB. This can be done by modifying your linker script or flags as appropriate. +The bootloader occupies the lower 8KiB or 16KiB of flash, so your application must offset its flash contents by 8KiB or 16KiB. This can be done by modifying your linker script or flags as appropriate. ### Switching to the bootloader The bootloader can be built to look for arbitrary patterns, but the default for the STM32F103 target looks for a magic value stored in the RTC backup registers. Writing the magic value and then resetting will run the bootloader instead of the main application. +When compiling with the DOUBLE_TAP option, the bootloader can be activated by double-tapping the reset button. ## Licensing All contents of the dapboot project are licensed under terms that are compatible with the terms of the GNU Lesser General Public License version 3. Non-libopencm3 related portions of the dapboot project are licensed under the less restrictive ISC license, except where otherwise specified in the headers of specific files. -The UF2 parts are licensed under MIT. - See the LICENSE file for full details. diff --git a/libopencm3 b/libopencm3 index 90be020..4587663 160000 --- a/libopencm3 +++ b/libopencm3 @@ -1 +1 @@ -Subproject commit 90be02008e6b651ce737019b6b39ddfdf85eda6b +Subproject commit 458766398f6d101a6b22da37bc33fd32265d1106 diff --git a/maple_mini_bootloader_updater/maple_mini_bootloader_updater.ino b/maple_mini_bootloader_updater/maple_mini_bootloader_updater.ino new file mode 100644 index 0000000..163ed3c --- /dev/null +++ b/maple_mini_bootloader_updater/maple_mini_bootloader_updater.ino @@ -0,0 +1,1007 @@ +/** + * + * Maple Mini bootloader updater sketch. + * Based on sketch from Gregwar for Robotis OpenCM9.04, which is based on Maple bootloader code. + * + * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING + * WARNING WARNING + * WARNING This comes with NO WARRANTY, you use it at your own risk WARNING + * WARNING WARNING + * WARNING Please read this warning text and the instructions below WARNING + * WARNING WARNING + * WARNING Running this sketch will erase your bootloader replace it WARNING + * WARNING with the new STM32duino bootloader WARNING + * WARNING WARNING + * WARNING Only use this sketch with Maple mini boards. WARNING + * WARNING WARNING + * WARNING Note. If your bootloader does get messed up, it is possible WARNING + * WARNING to reflash using an external USB to Serial adaptor or another WARNING + * WARNING Arduino board (to act as a USB to Serial device) WARNING + * WARNING WARNING + * WARNING For more information see www.stm32duino.com WARNING + * WARNING WARNING + * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING + * + * + * Instructions. + * + * Upload this sketch onto your Maple mini. + * + * After upload the LED on the board should start to flash slowly (on for 1 sec off for 1 sec) + * + * Open the Serial Monitor and follow the on screen instructions + * + * If the version of the bootloader that is contained in this sketch is already installed, + * a message is displayed and you will not be prompted to update. + * + * If prompted to update, press Y to agree and reflash the bootloader + * + * After the update has finished, the sketch will wait for you to manually reset the board + * or to upload a new sketch + * + * If you just reset the board. This sketch will run again, as it will not be touched by the bootloader update + * However it will display the message to indicate that this bootloader has already been installed + * + * For support please register to www.stm32duino.com + * + * Credit goes to Victor PV, Matthis, Ray. + * + * For source code and binaries for the bootloader see + * www.github.com/rogerclarkmelbourne/stm32duino-bootloader + * + * See also www.rogerclark.net + * + */ + +// Data of bootloader +const char maple_mini_boot_MSC[]={ + 0x00, 0x50, 0x00, 0x20, 0x15, 0x18, 0x00, 0x08, 0x11, 0x18, 0x00, 0x08, + 0x0F, 0x18, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x18, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x18, 0x00, 0x08, + 0x11, 0x18, 0x00, 0x08, 0x10, 0xB5, 0x04, 0x46, 0x4F, 0xF4, 0x67, 0x70, + 0x00, 0xF0, 0x85, 0xFE, 0x40, 0xF2, 0x9B, 0x30, 0x00, 0xF0, 0x81, 0xFE, + 0x05, 0x4B, 0x1A, 0x68, 0x42, 0xF4, 0x80, 0x72, 0x1A, 0x60, 0x04, 0x4A, + 0x14, 0x80, 0x1A, 0x68, 0x22, 0xF4, 0x80, 0x72, 0x1A, 0x60, 0x10, 0xBD, + 0x00, 0x70, 0x00, 0x40, 0x28, 0x6C, 0x00, 0x40, 0x01, 0x4B, 0x18, 0x88, + 0x70, 0x47, 0x00, 0xBF, 0x28, 0x6C, 0x00, 0x40, 0x30, 0xB5, 0x00, 0x24, + 0xA3, 0xB2, 0x9A, 0x42, 0x04, 0xF1, 0x01, 0x04, 0x00, 0xD8, 0x30, 0xBD, + 0xCD, 0x5C, 0xC5, 0x54, 0xF6, 0xE7, 0x00, 0x23, 0xC2, 0x5C, 0x0A, 0xB9, + 0x18, 0x46, 0x70, 0x47, 0x01, 0x33, 0xF9, 0xE7, 0x30, 0xB5, 0x00, 0x24, + 0x01, 0x39, 0xA2, 0x42, 0x06, 0xD0, 0x03, 0x5D, 0x01, 0x34, 0x0D, 0x5D, + 0xAB, 0x42, 0xF8, 0xD0, 0x58, 0x1B, 0x00, 0xE0, 0x00, 0x20, 0x30, 0xBD, + 0x02, 0x21, 0x10, 0xB9, 0x02, 0x48, 0x00, 0xF0, 0x43, 0xBE, 0x01, 0x48, + 0x00, 0xF0, 0x3E, 0xBE, 0x00, 0x0C, 0x01, 0x40, 0x08, 0xB5, 0x40, 0xF2, + 0x17, 0x20, 0x00, 0xF0, 0x49, 0xFE, 0x4F, 0xF4, 0x00, 0x71, 0x02, 0x48, + 0x00, 0xF0, 0x34, 0xFE, 0x01, 0x48, 0x08, 0xBD, 0x00, 0x0C, 0x01, 0x40, + 0x68, 0x1F, 0x00, 0x08, 0x08, 0xB5, 0x44, 0xF2, 0x4D, 0x20, 0xFF, 0xF7, + 0xA1, 0xFF, 0x02, 0x4B, 0x02, 0x4A, 0x1A, 0x60, 0xFE, 0xE7, 0x00, 0xBF, + 0x0C, 0xED, 0x00, 0xE0, 0x04, 0x00, 0xFA, 0x05, 0x08, 0xB5, 0xFF, 0xF7, + 0xAF, 0xFF, 0x44, 0xF2, 0x4D, 0x23, 0x98, 0x42, 0x4F, 0xF0, 0x00, 0x00, + 0x02, 0xD1, 0xFF, 0xF7, 0x8D, 0xFF, 0x01, 0x20, 0x08, 0xBD, 0x00, 0x00, + 0x38, 0xB5, 0x40, 0xF2, 0x03, 0x30, 0x00, 0xF0, 0x10, 0xFE, 0xFF, 0xF7, + 0x9D, 0xFF, 0x44, 0xF2, 0x4C, 0x23, 0x98, 0x42, 0x04, 0xD1, 0x00, 0x20, + 0xFF, 0xF7, 0x7C, 0xFF, 0x01, 0x20, 0x38, 0xBD, 0x18, 0x46, 0xFF, 0xF7, + 0x77, 0xFF, 0x0A, 0x24, 0x0B, 0x4D, 0x01, 0x20, 0xFF, 0xF7, 0xB2, 0xFF, + 0x0A, 0x4B, 0x00, 0xBF, 0x01, 0x3B, 0xFC, 0xD1, 0x02, 0x21, 0x28, 0x46, + 0x00, 0xF0, 0xF2, 0xFD, 0x06, 0x4B, 0x00, 0xBF, 0x01, 0x3B, 0xFC, 0xD1, + 0x01, 0x3C, 0xEE, 0xD1, 0x20, 0x46, 0xFF, 0xF7, 0x61, 0xFF, 0x20, 0x46, + 0xE3, 0xE7, 0x00, 0xBF, 0x00, 0x0C, 0x01, 0x40, 0xC0, 0x27, 0x09, 0x00, + 0x00, 0xF0, 0x0C, 0xBE, 0x2D, 0xE9, 0xF8, 0x43, 0x04, 0x46, 0x15, 0x46, + 0xDF, 0xF8, 0x5C, 0x90, 0xDF, 0xF8, 0x5C, 0x80, 0x8E, 0x1E, 0x0D, 0xB9, + 0x01, 0x20, 0x02, 0xE0, 0x4C, 0x45, 0x02, 0xD9, 0x00, 0x20, 0xBD, 0xE8, + 0xF8, 0x83, 0xD8, 0xF8, 0x00, 0x30, 0x0F, 0x4F, 0xA3, 0x42, 0x02, 0xD9, + 0x3B, 0x68, 0xA3, 0x42, 0x0A, 0xD9, 0x24, 0xF4, 0x7F, 0x70, 0x20, 0xF0, + 0x03, 0x00, 0x00, 0xF5, 0x80, 0x63, 0x38, 0x60, 0xC8, 0xF8, 0x00, 0x30, + 0x00, 0xF0, 0x84, 0xFC, 0x36, 0xF8, 0x02, 0x1F, 0x20, 0x46, 0x02, 0x34, + 0x00, 0xF0, 0x4E, 0xFC, 0x34, 0xF8, 0x02, 0x2C, 0x33, 0x88, 0x3C, 0x60, + 0x9A, 0x42, 0xDD, 0xD1, 0x01, 0x3D, 0xD6, 0xE7, 0x30, 0x00, 0x00, 0x20, + 0xFF, 0xFF, 0x01, 0x08, 0x2C, 0x00, 0x00, 0x20, 0x4F, 0xF4, 0x00, 0x52, + 0x08, 0xB5, 0x04, 0x4B, 0x1A, 0x60, 0x04, 0x4B, 0x1A, 0x68, 0x82, 0xF3, + 0x08, 0x88, 0x5B, 0x68, 0x98, 0x47, 0xFE, 0xE7, 0x08, 0xED, 0x00, 0xE0, + 0x00, 0x20, 0x00, 0x08, 0x04, 0x4B, 0x05, 0x48, 0x1B, 0x68, 0x18, 0x40, + 0x00, 0xF1, 0x60, 0x43, 0x58, 0x42, 0x58, 0x41, 0x70, 0x47, 0x00, 0xBF, + 0x00, 0x20, 0x00, 0x08, 0x00, 0x00, 0xFE, 0x2F, 0x2D, 0xE9, 0xF0, 0x47, + 0x88, 0xB0, 0xFF, 0xF7, 0xED, 0xFF, 0x07, 0x46, 0x20, 0xB1, 0xFF, 0xF7, + 0x61, 0xFF, 0x08, 0xB1, 0xFF, 0xF7, 0xD6, 0xFF, 0x30, 0x4C, 0x00, 0xF0, + 0x33, 0xFD, 0x40, 0xF2, 0x03, 0x30, 0x00, 0xF0, 0x7A, 0xFD, 0x4F, 0xF4, + 0x00, 0x71, 0x20, 0x46, 0x00, 0xF0, 0x70, 0xFD, 0x2B, 0x4B, 0x2C, 0x4A, + 0x23, 0x60, 0x2C, 0x4B, 0x1A, 0x60, 0xFF, 0xF7, 0x59, 0xFF, 0x08, 0xB9, + 0x00, 0x2F, 0xE7, 0xD1, 0x00, 0xF0, 0x32, 0xF9, 0x28, 0x4B, 0x40, 0x22, + 0x06, 0x93, 0x28, 0x4B, 0x00, 0x92, 0x05, 0x93, 0x4F, 0xF4, 0xFA, 0x53, + 0x04, 0x93, 0x26, 0x4B, 0x82, 0x21, 0x03, 0x93, 0x25, 0x4B, 0x81, 0x46, + 0x02, 0x93, 0x25, 0x4B, 0x01, 0x26, 0x01, 0x93, 0x01, 0x23, 0x00, 0xF0, + 0xA3, 0xFB, 0x4F, 0xF4, 0xFA, 0x75, 0x00, 0x24, 0xDF, 0xF8, 0x84, 0x80, + 0xDF, 0xF8, 0x84, 0xA0, 0x01, 0x34, 0xA5, 0x42, 0xD4, 0xBF, 0x00, 0x20, + 0x01, 0x20, 0xFF, 0xF7, 0xFB, 0xFE, 0xB4, 0xF5, 0x2F, 0x7F, 0x19, 0xDB, + 0xD8, 0xF8, 0x00, 0x30, 0x35, 0x44, 0x01, 0x33, 0xB5, 0xF5, 0x2F, 0x7F, + 0xC8, 0xF8, 0x00, 0x30, 0x14, 0xDC, 0x09, 0x2D, 0xD8, 0xBF, 0x02, 0x26, + 0x00, 0xF0, 0x58, 0xF8, 0x8F, 0xB1, 0xDA, 0xF8, 0x00, 0x40, 0x74, 0xB9, + 0x40, 0xF6, 0xB8, 0x33, 0xD8, 0xF8, 0x00, 0x20, 0x9A, 0x42, 0x01, 0xD9, + 0xFF, 0xF7, 0xF8, 0xFE, 0x48, 0x46, 0x00, 0xF0, 0x9D, 0xFD, 0xD7, 0xE7, + 0x6F, 0xF0, 0x01, 0x06, 0xEA, 0xE7, 0x00, 0x24, 0xF6, 0xE7, 0x00, 0xBF, + 0x00, 0x0C, 0x01, 0x40, 0x14, 0x44, 0x48, 0x44, 0x54, 0x44, 0x44, 0x44, + 0x04, 0x0C, 0x01, 0x40, 0x3D, 0x04, 0x00, 0x08, 0xDD, 0x03, 0x00, 0x08, + 0x44, 0x1E, 0x00, 0x08, 0x46, 0x1E, 0x00, 0x08, 0x4A, 0x1E, 0x00, 0x08, + 0x34, 0x00, 0x00, 0x20, 0xBC, 0x0A, 0x00, 0x20, 0x10, 0xB5, 0x10, 0x4B, + 0x10, 0x4C, 0x1A, 0x68, 0x21, 0x68, 0x10, 0x4B, 0x1A, 0x60, 0x4B, 0x1C, + 0x17, 0xD0, 0x0F, 0x4B, 0x1A, 0x78, 0x0A, 0xB1, 0x00, 0x22, 0x1A, 0x70, + 0x4F, 0xF4, 0x80, 0x62, 0x0C, 0x48, 0xFF, 0xF7, 0x9D, 0xFE, 0x48, 0xB1, + 0xFF, 0xF7, 0x0E, 0xFF, 0x4F, 0xF4, 0x00, 0x72, 0x08, 0x49, 0x20, 0x68, + 0xFF, 0xF7, 0x0A, 0xFF, 0x00, 0xF0, 0x26, 0xFD, 0x4F, 0xF0, 0xFF, 0x33, + 0x23, 0x60, 0x10, 0xBD, 0x40, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x20, + 0x3C, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x3C, 0x00, 0x00, 0x20, + 0x0C, 0x4A, 0x08, 0xB5, 0x13, 0x68, 0x01, 0x33, 0x13, 0x60, 0x0B, 0x4A, + 0x12, 0x68, 0x32, 0xB1, 0x93, 0x42, 0x04, 0xD3, 0xFF, 0xF7, 0xC8, 0xFF, + 0xFF, 0xF7, 0x9E, 0xFE, 0xFE, 0xE7, 0x07, 0x4A, 0x12, 0x68, 0x32, 0xB1, + 0x9B, 0x1A, 0x64, 0x2B, 0x03, 0xD9, 0xBD, 0xE8, 0x08, 0x40, 0xFF, 0xF7, + 0xBB, 0xBF, 0x08, 0xBD, 0x40, 0x04, 0x00, 0x20, 0x44, 0x04, 0x00, 0x20, + 0x3C, 0x04, 0x00, 0x20, 0x10, 0xB5, 0x00, 0x24, 0x4B, 0x1E, 0x01, 0xF2, + 0xFF, 0x12, 0x03, 0xF8, 0x01, 0x4F, 0x93, 0x42, 0xFB, 0xD1, 0x98, 0xB9, + 0x0A, 0x46, 0x11, 0x4B, 0x03, 0xF1, 0x3C, 0x00, 0x53, 0xF8, 0x04, 0x4B, + 0x83, 0x42, 0x42, 0xF8, 0x04, 0x4B, 0xF9, 0xD1, 0x1B, 0x88, 0x13, 0x80, + 0x55, 0x23, 0x81, 0xF8, 0xFE, 0x31, 0xAA, 0x23, 0x81, 0xF8, 0xFF, 0x31, + 0x00, 0x20, 0x10, 0xBD, 0x40, 0x28, 0xFB, 0xD8, 0x43, 0x1E, 0x1F, 0x2B, + 0x88, 0xBF, 0xA0, 0xF1, 0x21, 0x03, 0x00, 0x2B, 0xF4, 0xD1, 0xF0, 0x23, + 0x0B, 0x70, 0xFF, 0x23, 0x4B, 0x70, 0x8B, 0x70, 0xCB, 0x70, 0xED, 0xE7, + 0x4C, 0x1E, 0x00, 0x08, 0x2D, 0xE9, 0xF0, 0x41, 0x04, 0x46, 0x01, 0x20, + 0x0F, 0x46, 0xFF, 0xF7, 0x3B, 0xFE, 0x44, 0x2C, 0x3A, 0xD9, 0x20, 0x4A, + 0x13, 0x78, 0x73, 0xB9, 0xF9, 0x78, 0xBB, 0x78, 0x03, 0xEB, 0x01, 0x23, + 0x23, 0xF4, 0x80, 0x53, 0x23, 0xF0, 0x01, 0x03, 0x9B, 0x04, 0x9B, 0x0C, + 0xB3, 0xF5, 0x00, 0x5F, 0x2A, 0xD1, 0x01, 0x23, 0x13, 0x70, 0x18, 0x4D, + 0xDF, 0xF8, 0x6C, 0x80, 0x2E, 0x68, 0xD8, 0xF8, 0x00, 0x30, 0x26, 0xF4, + 0x7F, 0x74, 0x24, 0xF0, 0x03, 0x04, 0x9C, 0x42, 0x09, 0xD0, 0xFF, 0xF7, + 0x5B, 0xFF, 0x4F, 0xF4, 0x80, 0x62, 0x21, 0x46, 0x10, 0x48, 0xC8, 0xF8, + 0x00, 0x40, 0xFF, 0xF7, 0xF1, 0xFD, 0x0E, 0x48, 0xC6, 0xF3, 0x09, 0x06, + 0x4F, 0xF4, 0x00, 0x72, 0x39, 0x46, 0x30, 0x44, 0xFF, 0xF7, 0xE8, 0xFD, + 0x2B, 0x68, 0x0A, 0x4A, 0x03, 0xF5, 0x00, 0x73, 0x2B, 0x60, 0x09, 0x4B, + 0x1B, 0x68, 0x03, 0xF5, 0xFA, 0x73, 0x13, 0x60, 0x00, 0x20, 0xFF, 0xF7, + 0xFB, 0xFD, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x38, 0x00, 0x00, 0x20, + 0x08, 0x00, 0x00, 0x20, 0x3C, 0x00, 0x00, 0x20, 0x44, 0x04, 0x00, 0x20, + 0x40, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x20, 0x1F, 0xB5, 0xFF, 0xF7, + 0xF3, 0xFD, 0x4F, 0xF4, 0x80, 0x63, 0x03, 0x93, 0x06, 0x4B, 0x07, 0x4A, + 0x02, 0x93, 0x04, 0x23, 0x01, 0x93, 0x06, 0x4B, 0x06, 0x49, 0x00, 0x93, + 0x06, 0x4B, 0x00, 0xF0, 0x6F, 0xFC, 0x05, 0xB0, 0x5D, 0xF8, 0x04, 0xFB, + 0x48, 0x04, 0x00, 0x20, 0x93, 0x1E, 0x00, 0x08, 0x10, 0x00, 0x00, 0x20, + 0xA0, 0x1E, 0x00, 0x08, 0x8A, 0x1E, 0x00, 0x08, 0x48, 0x78, 0xFE, 0x28, + 0x04, 0xD0, 0xA0, 0xF1, 0xFF, 0x03, 0x58, 0x42, 0x58, 0x41, 0x70, 0x47, + 0x01, 0x20, 0x03, 0x49, 0x12, 0x68, 0x08, 0x60, 0x00, 0x21, 0x11, 0x70, + 0x18, 0x80, 0x70, 0x47, 0xBC, 0x0A, 0x00, 0x20, 0x37, 0xB5, 0x05, 0x46, + 0x0C, 0x4C, 0x0D, 0x4B, 0x21, 0x79, 0x00, 0x93, 0x02, 0x22, 0x63, 0x79, + 0x00, 0xF0, 0x78, 0xFC, 0x0A, 0x4B, 0xA1, 0x79, 0x00, 0x93, 0x28, 0x46, + 0xE3, 0x79, 0x02, 0x22, 0x00, 0xF0, 0x70, 0xFC, 0x7F, 0x22, 0x21, 0x21, + 0x28, 0x46, 0x06, 0x4B, 0x03, 0xB0, 0xBD, 0xE8, 0x30, 0x40, 0x00, 0xF0, + 0x5A, 0xBD, 0x00, 0xBF, 0x48, 0x08, 0x00, 0x20, 0xBD, 0x07, 0x00, 0x08, + 0x8D, 0x08, 0x00, 0x08, 0x25, 0x05, 0x00, 0x08, 0x70, 0xB5, 0x83, 0x4C, + 0xB0, 0xB9, 0x45, 0xF2, 0x55, 0x33, 0xA4, 0xF8, 0x62, 0x32, 0x45, 0xF2, + 0x42, 0x33, 0xC4, 0xE9, 0x12, 0x00, 0xA4, 0xF8, 0x64, 0x32, 0xD4, 0xF8, + 0x2D, 0x30, 0x84, 0xF8, 0x61, 0x02, 0xC4, 0xF8, 0x66, 0x32, 0xA4, 0xF8, + 0x6A, 0x02, 0xA4, 0xF8, 0x6C, 0x02, 0x84, 0xF8, 0x6E, 0x02, 0x20, 0x65, + 0x94, 0xF8, 0x38, 0x30, 0x12, 0x2B, 0x00, 0xF0, 0x88, 0x80, 0x29, 0xD8, + 0x04, 0x2B, 0x69, 0xD0, 0x0F, 0xD8, 0x6B, 0xB3, 0x03, 0x2B, 0x47, 0xD0, + 0x42, 0xF2, 0x05, 0x03, 0xA4, 0xF8, 0x70, 0x32, 0x00, 0x23, 0x84, 0xF8, + 0x72, 0x32, 0xC4, 0xE9, 0x12, 0x33, 0x01, 0x23, 0x84, 0xF8, 0x6E, 0x32, + 0x58, 0xE0, 0x08, 0x2B, 0x65, 0xD0, 0x0A, 0x2B, 0xEE, 0xD1, 0x00, 0x28, + 0x52, 0xD1, 0x94, 0xF8, 0x39, 0x30, 0x62, 0x8F, 0x1B, 0x04, 0x52, 0xBA, + 0x03, 0xF4, 0xF8, 0x13, 0x92, 0xB2, 0x13, 0x43, 0x63, 0x65, 0x94, 0xF8, + 0x3C, 0x30, 0xC4, 0xE9, 0x16, 0x30, 0x5B, 0x02, 0xA3, 0x64, 0x41, 0xE0, + 0x23, 0x2B, 0x00, 0xF0, 0x97, 0x80, 0x09, 0xD8, 0x1A, 0x2B, 0x3C, 0xD0, + 0x1D, 0x2B, 0xD3, 0xD1, 0x00, 0x23, 0xA4, 0xF8, 0x70, 0x32, 0x84, 0xF8, + 0x72, 0x32, 0x33, 0xE0, 0x28, 0x2B, 0x00, 0xF0, 0x96, 0x80, 0x2A, 0x2B, + 0x00, 0xF0, 0x9F, 0x80, 0x25, 0x2B, 0xC5, 0xD1, 0x50, 0xBB, 0x63, 0x69, + 0x1B, 0xBA, 0x23, 0x66, 0x4F, 0xF4, 0x00, 0x33, 0x63, 0x66, 0x08, 0x23, + 0xE3, 0x64, 0xA4, 0xF8, 0x70, 0x02, 0x84, 0xF8, 0x72, 0x02, 0x1D, 0xE0, + 0xE0, 0xB9, 0x94, 0xF8, 0x3C, 0x30, 0x4C, 0x4A, 0xE3, 0x64, 0x4C, 0x4B, + 0x03, 0xF1, 0x10, 0x06, 0x15, 0x46, 0x18, 0x68, 0x59, 0x68, 0x08, 0x33, + 0x03, 0xC5, 0xB3, 0x42, 0x2A, 0x46, 0xF7, 0xD1, 0x1B, 0x88, 0x2B, 0x80, + 0x94, 0xF8, 0x70, 0x32, 0x84, 0xF8, 0x62, 0x30, 0x94, 0xF8, 0x71, 0x32, + 0x84, 0xF8, 0x6C, 0x30, 0x94, 0xF8, 0x72, 0x32, 0x84, 0xF8, 0x6D, 0x30, + 0x70, 0xBD, 0x00, 0x28, 0xFC, 0xD1, 0x04, 0x23, 0x03, 0x22, 0xE3, 0x64, + 0xA4, 0xF8, 0x60, 0x20, 0x84, 0xF8, 0x62, 0x00, 0xA4, 0xF8, 0x6A, 0x32, + 0xA4, 0xF8, 0x6C, 0x02, 0xF0, 0xE7, 0x00, 0x28, 0xEE, 0xD1, 0x63, 0x8F, + 0x5B, 0xBA, 0x9B, 0xB2, 0x63, 0x65, 0x94, 0xF8, 0x3C, 0x30, 0xC4, 0xE9, + 0x16, 0x30, 0x5B, 0x02, 0xC0, 0xE7, 0x00, 0x28, 0xE2, 0xD1, 0x24, 0x23, + 0xE3, 0x64, 0x31, 0x4B, 0x2E, 0x4A, 0x03, 0xF1, 0x20, 0x06, 0x15, 0x46, + 0x18, 0x68, 0x59, 0x68, 0x08, 0x33, 0x03, 0xC5, 0xB3, 0x42, 0x2A, 0x46, + 0xF7, 0xD1, 0x18, 0x68, 0x28, 0x60, 0xA5, 0x68, 0x28, 0x46, 0xFF, 0xF7, + 0xC6, 0xFC, 0x08, 0x28, 0x02, 0x46, 0x29, 0x46, 0x28, 0xBF, 0x08, 0x22, + 0x26, 0x48, 0xFF, 0xF7, 0xB3, 0xFC, 0xE5, 0x68, 0x28, 0x46, 0xFF, 0xF7, + 0xBA, 0xFC, 0x10, 0x28, 0x02, 0x46, 0x29, 0x46, 0x28, 0xBF, 0x10, 0x22, + 0x21, 0x48, 0xFF, 0xF7, 0xA7, 0xFC, 0x25, 0x69, 0x28, 0x46, 0xFF, 0xF7, + 0xAE, 0xFC, 0x04, 0x28, 0x02, 0x46, 0x29, 0x46, 0x28, 0xBF, 0x04, 0x22, + 0x1C, 0x48, 0xFF, 0xF7, 0x9B, 0xFC, 0x00, 0x23, 0x24, 0x22, 0xA4, 0xF8, + 0x6C, 0x32, 0xA4, 0xF8, 0x6A, 0x22, 0x6E, 0xE7, 0x00, 0x28, 0xA5, 0xD1, + 0x4F, 0xF0, 0x00, 0x63, 0x23, 0x66, 0x63, 0x69, 0x1B, 0xBA, 0x63, 0x66, + 0x4F, 0xF0, 0x02, 0x13, 0xA3, 0x66, 0x0C, 0x23, 0x76, 0xE7, 0x00, 0x28, + 0x98, 0xD1, 0xD4, 0xF8, 0x3A, 0x30, 0x1B, 0xBA, 0x63, 0x65, 0xB4, 0xF8, + 0x3F, 0x30, 0x5B, 0xBA, 0x9B, 0xB2, 0xA3, 0x65, 0xA7, 0xE7, 0x00, 0x28, + 0x8C, 0xD1, 0xD4, 0xF8, 0x3A, 0x30, 0x1B, 0xBA, 0x63, 0x65, 0xB4, 0xF8, + 0x3F, 0x30, 0x5B, 0xBA, 0x9B, 0xB2, 0x3C, 0xE7, 0x48, 0x08, 0x00, 0x20, + 0xA8, 0x08, 0x00, 0x20, 0x3C, 0x1F, 0x00, 0x08, 0x18, 0x1F, 0x00, 0x08, + 0xB0, 0x08, 0x00, 0x20, 0xB8, 0x08, 0x00, 0x20, 0xC8, 0x08, 0x00, 0x20, + 0x70, 0xB5, 0x32, 0x4C, 0x0E, 0x46, 0x23, 0x6D, 0xE1, 0x6C, 0x05, 0x46, + 0x8B, 0x42, 0xA2, 0x6D, 0x21, 0xD2, 0x62, 0xB1, 0xC3, 0xF3, 0x08, 0x03, + 0x4B, 0xB9, 0x60, 0x6D, 0xE2, 0x6D, 0xA3, 0x69, 0x04, 0xF1, 0x60, 0x01, + 0x10, 0x44, 0x98, 0x47, 0xE3, 0x6D, 0x01, 0x33, 0xE3, 0x65, 0xE1, 0x79, + 0xD4, 0xE9, 0x13, 0x32, 0x9B, 0x1A, 0x8B, 0x42, 0xA8, 0xBF, 0x0B, 0x46, + 0xC2, 0xF3, 0x08, 0x02, 0x60, 0x32, 0x9B, 0xB2, 0x22, 0x44, 0x31, 0x46, + 0x28, 0x46, 0x00, 0xF0, 0x41, 0xFB, 0x23, 0x6D, 0x18, 0x44, 0x20, 0x65, + 0x70, 0xBD, 0x3A, 0xB1, 0xE3, 0x6D, 0x93, 0x42, 0x04, 0xD1, 0x00, 0x23, + 0xE3, 0x65, 0x63, 0x6A, 0x03, 0xB1, 0x98, 0x47, 0x94, 0xF8, 0x60, 0x32, + 0x2B, 0xB9, 0x01, 0x20, 0xFF, 0xF7, 0xB0, 0xFE, 0x01, 0x23, 0x84, 0xF8, + 0x60, 0x32, 0x94, 0xF8, 0x61, 0x22, 0xC2, 0xF1, 0x0D, 0x01, 0x00, 0x29, + 0x11, 0xDD, 0xE3, 0x79, 0x02, 0xF2, 0x62, 0x22, 0x8B, 0x42, 0xA8, 0xBF, + 0x0B, 0x46, 0x22, 0x44, 0x9B, 0xB2, 0x31, 0x46, 0x28, 0x46, 0x00, 0xF0, + 0x19, 0xFB, 0x94, 0xF8, 0x61, 0x32, 0x18, 0x44, 0x84, 0xF8, 0x61, 0x02, + 0xD4, 0xE7, 0x0D, 0x2A, 0xD2, 0xD1, 0x00, 0x23, 0x4F, 0xF0, 0xFF, 0x32, + 0xE3, 0x65, 0xC4, 0xE9, 0x15, 0x23, 0x84, 0xF8, 0x28, 0x30, 0xC4, 0xE9, + 0x12, 0x33, 0x23, 0x65, 0xA4, 0xF8, 0x60, 0x32, 0xC4, 0xE7, 0x00, 0xBF, + 0x48, 0x08, 0x00, 0x20, 0xF8, 0xB5, 0x57, 0x4C, 0x05, 0x46, 0x94, 0xF8, + 0x28, 0x20, 0x0E, 0x46, 0xC2, 0xF1, 0x1F, 0x07, 0x00, 0x2F, 0x2C, 0xDC, + 0x22, 0x6D, 0xA1, 0x6C, 0xA3, 0x6D, 0x8A, 0x42, 0x40, 0xD3, 0xE1, 0x6C, + 0x8A, 0x42, 0x80, 0xF0, 0x8B, 0x80, 0x73, 0xB1, 0x00, 0x2A, 0x40, 0xF0, + 0x81, 0x80, 0x23, 0x6A, 0x00, 0x2B, 0x7C, 0xD1, 0x60, 0x6D, 0xE2, 0x6D, + 0xA3, 0x69, 0x4A, 0x49, 0x10, 0x44, 0x98, 0x47, 0xE3, 0x6D, 0x01, 0x33, + 0xE3, 0x65, 0xE1, 0x79, 0xD4, 0xE9, 0x13, 0x32, 0x9B, 0x1A, 0x8B, 0x42, + 0xA8, 0xBF, 0x0B, 0x46, 0xC2, 0xF3, 0x08, 0x02, 0x60, 0x32, 0x9B, 0xB2, + 0x22, 0x44, 0x21, 0x79, 0x28, 0x46, 0x00, 0xF0, 0xCD, 0xFA, 0x23, 0x6D, + 0x18, 0x44, 0x20, 0x65, 0x17, 0xE0, 0xE3, 0x79, 0x29, 0x32, 0xBB, 0x42, + 0xA8, 0xBF, 0x3B, 0x46, 0x22, 0x44, 0x9B, 0xB2, 0x00, 0xF0, 0xC7, 0xFA, + 0x94, 0xF8, 0x28, 0x30, 0x18, 0x44, 0xC0, 0xB2, 0x1F, 0x28, 0x84, 0xF8, + 0x28, 0x00, 0xC1, 0xD1, 0x00, 0x20, 0xFF, 0xF7, 0x37, 0xFE, 0x22, 0x6D, + 0xA3, 0x6C, 0x9A, 0x42, 0xBA, 0xD2, 0xF8, 0xBD, 0x1B, 0xB1, 0x12, 0xB9, + 0x23, 0x6A, 0x03, 0xB1, 0x98, 0x47, 0x22, 0x6D, 0xA3, 0x6C, 0xE1, 0x79, + 0x9B, 0x1A, 0x8B, 0x42, 0xA8, 0xBF, 0x0B, 0x46, 0xC2, 0xF3, 0x08, 0x02, + 0x60, 0x32, 0x9B, 0xB2, 0x22, 0x44, 0x31, 0x46, 0x28, 0x46, 0x00, 0xF0, + 0xA2, 0xFA, 0x23, 0x6D, 0x18, 0x44, 0xA3, 0x6D, 0x20, 0x65, 0x5B, 0xB1, + 0xC0, 0xF3, 0x08, 0x00, 0x40, 0xB9, 0x60, 0x6D, 0xE2, 0x6D, 0xE3, 0x69, + 0x20, 0x49, 0x10, 0x44, 0x98, 0x47, 0xE3, 0x6D, 0x01, 0x33, 0xE3, 0x65, + 0x94, 0xF8, 0x60, 0x32, 0x2B, 0xB9, 0x01, 0x20, 0xFF, 0xF7, 0x06, 0xFE, + 0x01, 0x23, 0x84, 0xF8, 0x60, 0x32, 0x94, 0xF8, 0x61, 0x22, 0xC2, 0xF1, + 0x0D, 0x01, 0x00, 0x29, 0xC9, 0xDD, 0xE3, 0x79, 0x02, 0xF2, 0x62, 0x22, + 0x8B, 0x42, 0xA8, 0xBF, 0x0B, 0x46, 0x22, 0x44, 0x9B, 0xB2, 0x21, 0x79, + 0x28, 0x46, 0x00, 0xF0, 0x6F, 0xFA, 0x94, 0xF8, 0x61, 0x32, 0x18, 0x44, + 0x84, 0xF8, 0x61, 0x02, 0xB7, 0xE7, 0x98, 0x47, 0x23, 0x6D, 0xC3, 0xF3, + 0x08, 0x03, 0x00, 0x2B, 0x85, 0xD1, 0x7B, 0xE7, 0x00, 0x2B, 0xD5, 0xD0, + 0xE2, 0x6D, 0x9A, 0x42, 0xD2, 0xD1, 0x60, 0x6D, 0xE3, 0x69, 0x06, 0x49, + 0x10, 0x44, 0x98, 0x47, 0x00, 0x23, 0xE3, 0x65, 0x63, 0x6A, 0x00, 0x2B, + 0xC8, 0xD0, 0x98, 0x47, 0xC6, 0xE7, 0x00, 0xBF, 0x48, 0x08, 0x00, 0x20, + 0xA8, 0x08, 0x00, 0x20, 0x10, 0xB5, 0x16, 0x4C, 0xA3, 0x71, 0x9D, 0xF8, + 0x08, 0x30, 0x62, 0x71, 0xE3, 0x71, 0x03, 0x9B, 0x4F, 0xF0, 0xFF, 0x32, + 0xA3, 0x60, 0x04, 0x9B, 0x21, 0x71, 0xE3, 0x60, 0x05, 0x9B, 0x10, 0x49, + 0x23, 0x61, 0x06, 0x9B, 0x20, 0x60, 0x01, 0x3B, 0x63, 0x61, 0x07, 0x9B, + 0xA3, 0x61, 0x08, 0x9B, 0xE3, 0x61, 0x00, 0x23, 0xC4, 0xE9, 0x08, 0x33, + 0xC4, 0xE9, 0x15, 0x23, 0xE3, 0x65, 0x84, 0xF8, 0x28, 0x30, 0xC4, 0xE9, + 0x12, 0x33, 0x23, 0x65, 0xA4, 0xF8, 0x60, 0x32, 0xA4, 0xF8, 0x70, 0x32, + 0x84, 0xF8, 0x72, 0x32, 0x00, 0xF0, 0x24, 0xFE, 0x20, 0x46, 0x10, 0xBD, + 0x48, 0x08, 0x00, 0x20, 0x49, 0x05, 0x00, 0x08, 0x06, 0x4B, 0x18, 0x68, + 0x06, 0x4B, 0x1B, 0x88, 0xB3, 0xF5, 0x00, 0x7F, 0x82, 0xBF, 0x05, 0x4B, + 0x1B, 0x68, 0x18, 0x43, 0x00, 0xF0, 0x35, 0x00, 0x70, 0x47, 0x00, 0xBF, + 0x0C, 0x20, 0x02, 0x40, 0xE0, 0xF7, 0xFF, 0x1F, 0x4C, 0x20, 0x02, 0x40, + 0x38, 0xB5, 0x04, 0x46, 0x0D, 0x46, 0x00, 0xF0, 0xA9, 0xF9, 0x11, 0x4B, + 0x1B, 0x88, 0xB3, 0xF5, 0x00, 0x7F, 0x18, 0xD9, 0x0F, 0x4B, 0x9C, 0x42, + 0x15, 0xD9, 0x0F, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x13, 0x60, + 0x25, 0x80, 0x00, 0xF0, 0x99, 0xF9, 0x09, 0x4B, 0x1B, 0x88, 0xB3, 0xF5, + 0x00, 0x7F, 0x0A, 0xD9, 0x07, 0x4B, 0x9C, 0x42, 0x07, 0xD9, 0x07, 0x4A, + 0x13, 0x68, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x38, 0xBD, 0x05, 0x4A, + 0xE8, 0xE7, 0x04, 0x4A, 0xF6, 0xE7, 0x00, 0xBF, 0xE0, 0xF7, 0xFF, 0x1F, + 0xFF, 0xFF, 0x07, 0x08, 0x50, 0x20, 0x02, 0x40, 0x10, 0x20, 0x02, 0x40, + 0x10, 0xB5, 0x04, 0x46, 0x00, 0xF0, 0x7A, 0xF9, 0x15, 0x4B, 0x1B, 0x88, + 0xB3, 0xF5, 0x00, 0x7F, 0x1D, 0xD9, 0x14, 0x4B, 0x9C, 0x42, 0x1A, 0xD9, + 0x13, 0x4B, 0x1A, 0x68, 0x42, 0xF0, 0x02, 0x02, 0x1A, 0x60, 0x12, 0x4A, + 0x14, 0x60, 0x1A, 0x68, 0x42, 0xF0, 0x40, 0x02, 0x1A, 0x60, 0x00, 0xF0, + 0x65, 0xF9, 0x0B, 0x4B, 0x1B, 0x88, 0xB3, 0xF5, 0x00, 0x7F, 0x0F, 0xD9, + 0x09, 0x4B, 0x9C, 0x42, 0x0C, 0xD9, 0x09, 0x4A, 0x13, 0x68, 0x23, 0xF0, + 0x02, 0x03, 0x13, 0x60, 0x10, 0xBD, 0x08, 0x4B, 0x1A, 0x68, 0x42, 0xF0, + 0x02, 0x02, 0x1A, 0x60, 0x06, 0x4A, 0xE3, 0xE7, 0x04, 0x4A, 0xF1, 0xE7, + 0xE0, 0xF7, 0xFF, 0x1F, 0xFF, 0xFF, 0x07, 0x08, 0x50, 0x20, 0x02, 0x40, + 0x54, 0x20, 0x02, 0x40, 0x10, 0x20, 0x02, 0x40, 0x14, 0x20, 0x02, 0x40, + 0x02, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x80, 0x73, 0x13, 0x60, 0x70, 0x47, + 0x00, 0x10, 0x02, 0x40, 0x06, 0x28, 0x09, 0xD8, 0xDF, 0xE8, 0x00, 0xF0, + 0x22, 0x1D, 0x18, 0x13, 0x0E, 0x09, 0x04, 0x00, 0x11, 0x4A, 0x13, 0x68, + 0x9B, 0x07, 0xFC, 0xD5, 0x70, 0x47, 0x10, 0x4A, 0x13, 0x68, 0x99, 0x07, + 0xFC, 0xD5, 0x70, 0x47, 0x0E, 0x4A, 0x13, 0x68, 0x98, 0x07, 0xFC, 0xD5, + 0x70, 0x47, 0x0C, 0x4A, 0x13, 0x68, 0x9B, 0x03, 0xFC, 0xD5, 0x70, 0x47, + 0x09, 0x4A, 0x13, 0x68, 0x99, 0x00, 0xFC, 0xD5, 0x70, 0x47, 0x07, 0x4A, + 0x13, 0x68, 0x18, 0x01, 0xFC, 0xD5, 0x70, 0x47, 0x04, 0x4A, 0x13, 0x68, + 0x9B, 0x01, 0xFC, 0xD5, 0x70, 0x47, 0x00, 0xBF, 0x24, 0x10, 0x02, 0x40, + 0x20, 0x10, 0x02, 0x40, 0x00, 0x10, 0x02, 0x40, 0x06, 0x28, 0x0C, 0xD8, + 0xDF, 0xE8, 0x00, 0xF0, 0x04, 0x06, 0x0C, 0x11, 0x16, 0x1B, 0x1D, 0x00, + 0xFF, 0xF7, 0xBC, 0xBF, 0x0C, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x80, 0x63, + 0x13, 0x60, 0x70, 0x47, 0x09, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x80, 0x53, + 0xF8, 0xE7, 0x07, 0x4A, 0x13, 0x68, 0x43, 0xF4, 0x80, 0x33, 0xF3, 0xE7, + 0x04, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x01, 0x03, 0xEE, 0xE7, 0x03, 0x4A, + 0xF9, 0xE7, 0x03, 0x4A, 0xF7, 0xE7, 0x00, 0xBF, 0x00, 0x10, 0x02, 0x40, + 0x20, 0x10, 0x02, 0x40, 0x24, 0x10, 0x02, 0x40, 0x03, 0x4A, 0x13, 0x68, + 0x23, 0xF0, 0x03, 0x03, 0x18, 0x43, 0x10, 0x60, 0x70, 0x47, 0x00, 0xBF, + 0x04, 0x10, 0x02, 0x40, 0x03, 0x4A, 0x13, 0x68, 0x23, 0xF4, 0x70, 0x13, + 0x43, 0xEA, 0x80, 0x40, 0x10, 0x60, 0x70, 0x47, 0x04, 0x10, 0x02, 0x40, + 0x03, 0x4A, 0x13, 0x68, 0x23, 0xF4, 0x80, 0x33, 0x43, 0xEA, 0x00, 0x40, + 0x10, 0x60, 0x70, 0x47, 0x04, 0x10, 0x02, 0x40, 0x03, 0x4A, 0x13, 0x68, + 0x23, 0xF4, 0x00, 0x33, 0x43, 0xEA, 0x40, 0x40, 0x10, 0x60, 0x70, 0x47, + 0x04, 0x10, 0x02, 0x40, 0x03, 0x4A, 0x13, 0x68, 0x23, 0xF4, 0x40, 0x43, + 0x43, 0xEA, 0x80, 0x30, 0x10, 0x60, 0x70, 0x47, 0x04, 0x10, 0x02, 0x40, + 0x03, 0x4A, 0x13, 0x68, 0x23, 0xF4, 0x60, 0x53, 0x43, 0xEA, 0xC0, 0x20, + 0x10, 0x60, 0x70, 0x47, 0x04, 0x10, 0x02, 0x40, 0x03, 0x4A, 0x13, 0x68, + 0x23, 0xF4, 0xE0, 0x63, 0x43, 0xEA, 0x00, 0x20, 0x10, 0x60, 0x70, 0x47, + 0x04, 0x10, 0x02, 0x40, 0x03, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0xF0, 0x03, + 0x43, 0xEA, 0x00, 0x10, 0x10, 0x60, 0x70, 0x47, 0x04, 0x10, 0x02, 0x40, + 0x08, 0xB5, 0x04, 0x20, 0xFF, 0xF7, 0x82, 0xFF, 0x04, 0x20, 0xFF, 0xF7, + 0x4D, 0xFF, 0x00, 0x20, 0xFF, 0xF7, 0xA6, 0xFF, 0x03, 0x20, 0xFF, 0xF7, + 0x79, 0xFF, 0x03, 0x20, 0xFF, 0xF7, 0x44, 0xFF, 0x01, 0x20, 0xFF, 0xF7, + 0x9D, 0xFF, 0x00, 0x20, 0xFF, 0xF7, 0xE0, 0xFF, 0x03, 0x20, 0xFF, 0xF7, + 0xBF, 0xFF, 0x04, 0x20, 0xFF, 0xF7, 0xD0, 0xFF, 0x00, 0x20, 0xFF, 0xF7, + 0xC3, 0xFF, 0x02, 0x20, 0x00, 0xF0, 0x48, 0xF8, 0x07, 0x20, 0xFF, 0xF7, + 0x95, 0xFF, 0x01, 0x20, 0xFF, 0xF7, 0x9C, 0xFF, 0x00, 0x20, 0xFF, 0xF7, + 0xA3, 0xFF, 0xFF, 0xF7, 0x1F, 0xFF, 0x00, 0x20, 0xFF, 0xF7, 0x24, 0xFF, + 0x02, 0x20, 0xFF, 0xF7, 0x7D, 0xFF, 0x04, 0x4B, 0x04, 0x4A, 0x05, 0x49, + 0x13, 0x60, 0x05, 0x4A, 0x11, 0x60, 0x05, 0x4A, 0x13, 0x60, 0x08, 0xBD, + 0x00, 0xA2, 0x4A, 0x04, 0x20, 0x00, 0x00, 0x20, 0x00, 0x51, 0x25, 0x02, + 0x24, 0x00, 0x00, 0x20, 0x28, 0x00, 0x00, 0x20, 0x01, 0x61, 0x70, 0x47, + 0x09, 0x04, 0x01, 0x61, 0x70, 0x47, 0x43, 0x09, 0x00, 0xF0, 0x1F, 0x02, + 0x01, 0x20, 0x03, 0xF1, 0x80, 0x43, 0x03, 0xF5, 0x04, 0x33, 0x19, 0x68, + 0x90, 0x40, 0x08, 0x43, 0x18, 0x60, 0x70, 0x47, 0x00, 0xF0, 0x1F, 0x02, + 0x43, 0x09, 0x01, 0x20, 0x03, 0xF1, 0x80, 0x43, 0x03, 0xF5, 0x04, 0x33, + 0x19, 0x68, 0x90, 0x40, 0x01, 0x43, 0x19, 0x60, 0x1A, 0x68, 0x22, 0xEA, + 0x00, 0x00, 0x18, 0x60, 0x70, 0x47, 0x00, 0x00, 0x03, 0x4A, 0x13, 0x68, + 0x23, 0xF0, 0x07, 0x03, 0x18, 0x43, 0x10, 0x60, 0x70, 0x47, 0x00, 0xBF, + 0x00, 0x20, 0x02, 0x40, 0x05, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x80, 0x03, + 0x13, 0x60, 0x04, 0x4B, 0x04, 0x4A, 0x1A, 0x60, 0x02, 0xF1, 0x88, 0x32, + 0x1A, 0x60, 0x70, 0x47, 0x10, 0x20, 0x02, 0x40, 0x04, 0x20, 0x02, 0x40, + 0x23, 0x01, 0x67, 0x45, 0x02, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x80, 0x03, + 0x13, 0x60, 0x70, 0x47, 0x10, 0x20, 0x02, 0x40, 0x08, 0xB5, 0xFF, 0xF7, + 0x3B, 0xFE, 0xC3, 0x07, 0xFB, 0xD4, 0x08, 0xBD, 0x2D, 0xE9, 0xF0, 0x41, + 0x1E, 0x46, 0x03, 0x68, 0x17, 0x46, 0x05, 0x46, 0x88, 0x46, 0x98, 0x47, + 0x06, 0x9B, 0x4F, 0xF0, 0xFF, 0x32, 0xC3, 0x60, 0x07, 0x9B, 0xC0, 0xF8, + 0xE0, 0x50, 0x03, 0x61, 0x00, 0x23, 0xC0, 0xE9, 0x39, 0x23, 0x08, 0x9A, + 0xC0, 0xE9, 0x00, 0x87, 0x42, 0x61, 0xBD, 0xF8, 0x24, 0x20, 0x86, 0x60, + 0x02, 0x83, 0x06, 0x4A, 0xC0, 0xE9, 0x33, 0x33, 0x42, 0x67, 0x05, 0x4A, + 0xC0, 0xE9, 0x35, 0x33, 0x02, 0x67, 0x04, 0x4A, 0xC2, 0x66, 0xBD, 0xE8, + 0xF0, 0x81, 0x00, 0xBF, 0x5F, 0x10, 0x00, 0x08, 0xBB, 0x10, 0x00, 0x08, + 0x3F, 0x11, 0x00, 0x08, 0xD0, 0xF8, 0xE0, 0x30, 0x5B, 0x6A, 0x18, 0x47, + 0x10, 0xB4, 0xD0, 0xF8, 0xE0, 0x40, 0xA4, 0x68, 0xA4, 0x46, 0x10, 0xBC, + 0x60, 0x47, 0x37, 0xB5, 0x00, 0x25, 0x04, 0x46, 0x03, 0x68, 0x45, 0x83, + 0xDB, 0x79, 0x2A, 0x46, 0x29, 0x46, 0x00, 0x95, 0xFF, 0xF7, 0xEE, 0xFF, + 0xD4, 0xF8, 0xE0, 0x30, 0x29, 0x46, 0x5B, 0x68, 0x20, 0x46, 0x98, 0x47, + 0x23, 0x6A, 0x1B, 0xB1, 0x03, 0xB0, 0xBD, 0xE8, 0x30, 0x40, 0x18, 0x47, + 0x03, 0xB0, 0x30, 0xBD, 0x10, 0xB4, 0xD0, 0xF8, 0xE0, 0x40, 0xE4, 0x69, + 0xA4, 0x46, 0x10, 0xBC, 0x60, 0x47, 0x10, 0xB4, 0xD0, 0xF8, 0xE0, 0x40, + 0x24, 0x6A, 0xA4, 0x46, 0x10, 0xBC, 0x60, 0x47, 0xD0, 0xF8, 0xE0, 0x30, + 0x1B, 0x69, 0x18, 0x47, 0xD0, 0xF8, 0xE0, 0x30, 0x9B, 0x69, 0x18, 0x47, + 0x10, 0xB5, 0x01, 0x22, 0x00, 0x21, 0x04, 0x46, 0xFF, 0xF7, 0xF2, 0xFF, + 0x00, 0x23, 0x84, 0xF8, 0x30, 0x30, 0x10, 0xBD, 0x70, 0xB5, 0x03, 0x68, + 0xB0, 0xF8, 0x40, 0x20, 0x44, 0x8F, 0xDB, 0x79, 0xA4, 0x1A, 0x9C, 0x42, + 0xA8, 0xBF, 0x1C, 0x46, 0xC1, 0x6B, 0xA6, 0xB2, 0x0A, 0x44, 0x33, 0x46, + 0x00, 0x21, 0x05, 0x46, 0xFF, 0xF7, 0xD5, 0xFF, 0x86, 0x42, 0x05, 0xD0, + 0x28, 0x46, 0xFF, 0xF7, 0xDF, 0xFF, 0x4F, 0xF0, 0xFF, 0x30, 0x70, 0xBD, + 0xB5, 0xF8, 0x40, 0x30, 0xA0, 0xB2, 0x1E, 0x44, 0xA5, 0xF8, 0x40, 0x60, + 0xF7, 0xE7, 0x10, 0xB5, 0x03, 0x68, 0x04, 0x46, 0xD9, 0x79, 0xB0, 0xF8, + 0x40, 0x30, 0xC2, 0x6B, 0x99, 0x42, 0x11, 0xD2, 0x0B, 0x46, 0x00, 0x21, + 0xFF, 0xF7, 0xB2, 0xFF, 0x02, 0x23, 0x84, 0xF8, 0x30, 0x30, 0x23, 0x68, + 0xE2, 0x6B, 0xD9, 0x79, 0xB4, 0xF8, 0x40, 0x30, 0x0A, 0x44, 0x5B, 0x1A, + 0xE2, 0x63, 0xA4, 0xF8, 0x40, 0x30, 0x10, 0xBD, 0x00, 0x21, 0xFF, 0xF7, + 0xA1, 0xFF, 0x94, 0xF8, 0x48, 0x30, 0x00, 0x2B, 0x14, 0xBF, 0x02, 0x23, + 0x03, 0x23, 0x84, 0xF8, 0x30, 0x30, 0x00, 0x23, 0x84, 0xF8, 0x48, 0x30, + 0xA4, 0xF8, 0x40, 0x30, 0xE3, 0x63, 0xEC, 0xE7, 0x2D, 0xE9, 0xF7, 0x4F, + 0x04, 0x46, 0x0E, 0x46, 0x05, 0x46, 0x00, 0xF1, 0x20, 0x0B, 0x00, 0xF1, + 0x3C, 0x08, 0x00, 0xF1, 0x40, 0x09, 0x00, 0xF1, 0x44, 0x0A, 0xEF, 0x6C, + 0x47, 0xB9, 0x4B, 0x46, 0x42, 0x46, 0x31, 0x46, 0x20, 0x46, 0x03, 0xB0, + 0xBD, 0xE8, 0xF0, 0x4F, 0x00, 0xF0, 0xEC, 0xBB, 0x33, 0x78, 0x95, 0xF8, + 0x51, 0x10, 0x95, 0xF8, 0x50, 0x20, 0x0B, 0x40, 0x9A, 0x42, 0x03, 0xD0, + 0x08, 0x35, 0x5D, 0x45, 0xE9, 0xD1, 0xEA, 0xE7, 0xCD, 0xF8, 0x00, 0xA0, + 0x4B, 0x46, 0x42, 0x46, 0x31, 0x46, 0x20, 0x46, 0xB8, 0x47, 0x01, 0x28, + 0xF2, 0xD8, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x38, 0xB5, 0x43, 0x69, + 0x04, 0x46, 0xC3, 0x63, 0x8B, 0x79, 0xCA, 0x79, 0x0D, 0x46, 0x43, 0xEA, + 0x02, 0x23, 0xA0, 0xF8, 0x40, 0x30, 0xFF, 0xF7, 0xC3, 0xFF, 0x08, 0xB3, + 0xEB, 0x88, 0xB3, 0xB1, 0xB4, 0xF8, 0x40, 0x20, 0x21, 0x68, 0x93, 0x42, + 0xC9, 0x79, 0x0E, 0xD9, 0x32, 0xB1, 0xB2, 0xFB, 0xF1, 0xF3, 0x01, 0xFB, + 0x13, 0x22, 0xB2, 0xFA, 0x82, 0xF2, 0x52, 0x09, 0x84, 0xF8, 0x48, 0x20, + 0x20, 0x46, 0xBD, 0xE8, 0x38, 0x40, 0xFF, 0xF7, 0x7E, 0xBF, 0x00, 0x22, + 0xF6, 0xE7, 0x1A, 0x46, 0x19, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0x36, 0xFF, + 0x04, 0x23, 0x84, 0xF8, 0x30, 0x30, 0x38, 0xBD, 0x20, 0x46, 0xBD, 0xE8, + 0x38, 0x40, 0xFF, 0xF7, 0x43, 0xBF, 0x70, 0xB5, 0x00, 0x24, 0x00, 0xF1, + 0x4C, 0x06, 0x56, 0xF8, 0x34, 0x50, 0x2D, 0xB1, 0x01, 0x34, 0x04, 0x2C, + 0xF9, 0xD1, 0x4F, 0xF0, 0xFF, 0x30, 0x70, 0xBD, 0x00, 0xEB, 0xC4, 0x04, + 0x84, 0xF8, 0x50, 0x10, 0x84, 0xF8, 0x51, 0x20, 0xE3, 0x64, 0x28, 0x46, + 0xF5, 0xE7, 0x70, 0xB5, 0x00, 0x25, 0x00, 0xF1, 0x34, 0x06, 0x45, 0x64, + 0x08, 0x23, 0x32, 0x46, 0x29, 0x46, 0x04, 0x46, 0xFF, 0xF7, 0x13, 0xFF, + 0x08, 0x28, 0x04, 0xD0, 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0xFF, 0xF7, + 0x1B, 0xBF, 0x63, 0x8F, 0x2B, 0xB9, 0x31, 0x46, 0x20, 0x46, 0xBD, 0xE8, + 0x70, 0x40, 0xFF, 0xF7, 0x9B, 0xBF, 0x94, 0xF9, 0x34, 0x20, 0x00, 0x2A, + 0xF5, 0xDB, 0x22, 0x8B, 0x9A, 0x42, 0xEB, 0xD3, 0x62, 0x69, 0xA4, 0xF8, + 0x40, 0x50, 0xE2, 0x63, 0x22, 0x68, 0xD2, 0x79, 0x9A, 0x42, 0x34, 0xBF, + 0x05, 0x23, 0x06, 0x23, 0x84, 0xF8, 0x30, 0x30, 0x70, 0xBD, 0x90, 0xF8, + 0x30, 0x30, 0x10, 0xB5, 0x06, 0x2B, 0x04, 0x46, 0x13, 0xD0, 0x07, 0x2B, + 0x28, 0xD0, 0x05, 0x2B, 0x22, 0xD1, 0xFF, 0xF7, 0xFD, 0xFE, 0x00, 0x28, + 0x0A, 0xDB, 0xB4, 0xF8, 0x40, 0x20, 0x63, 0x8F, 0x9B, 0x1A, 0x22, 0x68, + 0xD2, 0x79, 0x93, 0x42, 0x02, 0xDC, 0x06, 0x23, 0x84, 0xF8, 0x30, 0x30, + 0x10, 0xBD, 0xFF, 0xF7, 0xED, 0xFE, 0x00, 0x28, 0xFA, 0xDB, 0x04, 0xF1, + 0x34, 0x01, 0x20, 0x46, 0xFF, 0xF7, 0x34, 0xFF, 0x38, 0xB1, 0x00, 0x23, + 0x20, 0x46, 0x1A, 0x46, 0x19, 0x46, 0xFF, 0xF7, 0xBF, 0xFE, 0x04, 0x23, + 0xEA, 0xE7, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0xFF, 0xF7, 0xCE, 0xBE, + 0x00, 0x23, 0x1A, 0x46, 0x19, 0x46, 0xFF, 0xF7, 0xBA, 0xFE, 0x00, 0x23, + 0x84, 0xF8, 0x30, 0x30, 0x63, 0x6C, 0x1B, 0xB1, 0x04, 0xF1, 0x34, 0x01, + 0x20, 0x46, 0x98, 0x47, 0x00, 0x23, 0x63, 0x64, 0xD6, 0xE7, 0x90, 0xF8, + 0x30, 0x30, 0x10, 0xB5, 0x03, 0x2B, 0x04, 0x46, 0x07, 0xD0, 0x04, 0x2B, + 0x09, 0xD0, 0x02, 0x2B, 0x1C, 0xD1, 0xBD, 0xE8, 0x10, 0x40, 0xFF, 0xF7, + 0xDA, 0xBE, 0x07, 0x23, 0x84, 0xF8, 0x30, 0x30, 0x10, 0xBD, 0x43, 0x6C, + 0x13, 0xB1, 0x00, 0xF1, 0x34, 0x01, 0x98, 0x47, 0x94, 0xF8, 0x34, 0x30, + 0x53, 0xB9, 0x94, 0xF8, 0x35, 0x30, 0x05, 0x2B, 0x06, 0xD1, 0xE1, 0x8E, + 0xD4, 0xF8, 0xE0, 0x30, 0xC9, 0xB2, 0x5B, 0x68, 0x20, 0x46, 0x98, 0x47, + 0x00, 0x23, 0xE7, 0xE7, 0xBD, 0xE8, 0x10, 0x40, 0xFF, 0xF7, 0x92, 0xBE, + 0x10, 0xB5, 0x0B, 0x78, 0x73, 0xB9, 0x4C, 0x88, 0x7F, 0x2C, 0x0B, 0xD8, + 0xD0, 0xF8, 0xE0, 0x30, 0x84, 0x76, 0x93, 0xF8, 0x30, 0x20, 0x1A, 0xB1, + 0x49, 0x88, 0x5B, 0x68, 0xC9, 0xB2, 0x98, 0x47, 0x01, 0x20, 0x00, 0xE0, + 0x00, 0x20, 0x10, 0xBD, 0xF8, 0xB5, 0x0D, 0x46, 0x49, 0x88, 0x04, 0x46, + 0x79, 0xB1, 0x03, 0x68, 0x0D, 0x26, 0x58, 0x7C, 0x00, 0x23, 0x98, 0x42, + 0x01, 0xD8, 0x00, 0x20, 0xF8, 0xBD, 0x62, 0x68, 0x06, 0xFB, 0x03, 0x22, + 0x52, 0x79, 0x8A, 0x42, 0x03, 0xD0, 0x01, 0x33, 0xF3, 0xE7, 0x4F, 0xF0, + 0xFF, 0x33, 0x01, 0x33, 0xDB, 0xB2, 0xE3, 0x76, 0x4B, 0xB9, 0xD4, 0xF8, + 0xE0, 0x30, 0x20, 0x46, 0xDB, 0x68, 0x98, 0x47, 0xD4, 0xF8, 0xCC, 0x30, + 0x9B, 0xB9, 0x01, 0x20, 0xE6, 0xE7, 0x0D, 0x22, 0x53, 0x43, 0x62, 0x68, + 0x0D, 0x3B, 0x13, 0x44, 0x00, 0x22, 0x10, 0x46, 0x19, 0x79, 0x91, 0x42, + 0xEB, 0xD9, 0xD3, 0xF8, 0x09, 0x10, 0x16, 0x01, 0x71, 0x58, 0x01, 0xB1, + 0x08, 0x70, 0x01, 0x32, 0xF4, 0xE7, 0x00, 0x23, 0x04, 0xF1, 0xCC, 0x06, + 0xE3, 0x64, 0x63, 0x65, 0xE3, 0x65, 0x63, 0x66, 0x04, 0xF1, 0xDC, 0x07, + 0x56, 0xF8, 0x04, 0x3B, 0x13, 0xB1, 0x69, 0x88, 0x20, 0x46, 0x98, 0x47, + 0xB7, 0x42, 0xF7, 0xD1, 0xD9, 0xE7, 0x19, 0x88, 0x12, 0x68, 0x01, 0x29, + 0x84, 0xBF, 0x01, 0x21, 0x19, 0x80, 0xC3, 0x7E, 0x2B, 0xB1, 0x41, 0x68, + 0x0D, 0x20, 0x00, 0xFB, 0x03, 0x13, 0x13, 0xF8, 0x08, 0x3C, 0x13, 0x70, + 0x01, 0x20, 0x70, 0x47, 0x30, 0xB5, 0x0D, 0x24, 0xC5, 0x7E, 0x40, 0x68, + 0x6C, 0x43, 0x0D, 0x3C, 0x04, 0x44, 0x8D, 0x88, 0x20, 0x79, 0x85, 0x42, + 0x0C, 0xD2, 0x01, 0x20, 0x18, 0x80, 0x8B, 0x88, 0xD4, 0xF8, 0x09, 0x00, + 0x1B, 0x01, 0x1B, 0x58, 0x03, 0xB1, 0x1B, 0x78, 0x01, 0x20, 0x12, 0x68, + 0x13, 0x70, 0x30, 0xBD, 0x00, 0x20, 0xFC, 0xE7, 0x19, 0x88, 0x01, 0x20, + 0x02, 0x29, 0x84, 0xBF, 0x02, 0x21, 0x19, 0x80, 0x00, 0x23, 0x11, 0x68, + 0x0B, 0x70, 0x12, 0x68, 0x53, 0x70, 0x70, 0x47, 0x10, 0xB5, 0x14, 0x46, + 0x1A, 0x88, 0x02, 0x2A, 0x84, 0xBF, 0x02, 0x22, 0x1A, 0x80, 0x89, 0x88, + 0xC9, 0xB2, 0xFF, 0xF7, 0xEF, 0xFD, 0x00, 0x30, 0x18, 0xBF, 0x01, 0x20, + 0x00, 0x22, 0x23, 0x68, 0x18, 0x70, 0x23, 0x68, 0x01, 0x20, 0x5A, 0x70, + 0x10, 0xBD, 0x08, 0xB5, 0x89, 0x88, 0x01, 0x22, 0xC9, 0xB2, 0xFF, 0xF7, + 0xDB, 0xFD, 0x01, 0x20, 0x08, 0xBD, 0x08, 0xB5, 0x89, 0x88, 0x00, 0x22, + 0xC9, 0xB2, 0xFF, 0xF7, 0xD3, 0xFD, 0x01, 0x20, 0x08, 0xBD, 0x0D, 0x22, + 0x70, 0xB5, 0x1C, 0x46, 0xC3, 0x7E, 0x5A, 0x43, 0x43, 0x68, 0x0D, 0x3A, + 0x13, 0x44, 0x1D, 0x79, 0x8A, 0x88, 0x95, 0x42, 0x18, 0xD9, 0xD3, 0xF8, + 0x09, 0x50, 0x12, 0x01, 0xAE, 0x18, 0x4B, 0x88, 0x36, 0x79, 0x9E, 0x42, + 0x10, 0xD9, 0xAA, 0x58, 0x52, 0xB1, 0x13, 0x70, 0xD0, 0xF8, 0xDC, 0x30, + 0x13, 0xB1, 0x4A, 0x88, 0x89, 0x88, 0x98, 0x47, 0x00, 0x23, 0x01, 0x20, + 0x23, 0x80, 0x70, 0xBD, 0x00, 0x2B, 0xF3, 0xD0, 0x10, 0x46, 0xFA, 0xE7, + 0x00, 0x20, 0xF8, 0xE7, 0x2D, 0xE9, 0xF0, 0x4F, 0x9B, 0x46, 0x4B, 0x88, + 0x89, 0xB0, 0x1C, 0x0A, 0x02, 0x2C, 0x15, 0x46, 0x3B, 0xD0, 0x03, 0xD8, + 0x01, 0x2C, 0x2A, 0xD0, 0x00, 0x24, 0x32, 0xE0, 0x03, 0x2C, 0x00, 0xF0, + 0x22, 0x81, 0x0F, 0x2C, 0xF8, 0xD1, 0x84, 0x68, 0x5C, 0xB3, 0xD0, 0xF8, + 0x14, 0x80, 0xBB, 0xF8, 0x00, 0x50, 0xC2, 0xF8, 0x00, 0x80, 0x26, 0x78, + 0x4F, 0xF0, 0x00, 0x09, 0xAE, 0x42, 0x28, 0xBF, 0x2E, 0x46, 0x21, 0x46, + 0x32, 0x46, 0x40, 0x46, 0xFE, 0xF7, 0x70, 0xFE, 0xAD, 0x1B, 0x94, 0xF8, + 0x00, 0xA0, 0x08, 0xEB, 0x06, 0x03, 0xAD, 0xB2, 0x21, 0x79, 0x1F, 0xFA, + 0x89, 0xF2, 0x91, 0x42, 0x00, 0xF2, 0xE5, 0x80, 0xA8, 0xF8, 0x02, 0xA0, + 0xAB, 0xF8, 0x00, 0x60, 0x32, 0xE0, 0x03, 0x68, 0x13, 0x60, 0x1B, 0x78, + 0xBB, 0xF8, 0x00, 0x20, 0x93, 0x42, 0x28, 0xBF, 0x13, 0x46, 0xAB, 0xF8, + 0x00, 0x30, 0x20, 0x46, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x0D, 0x26, + 0xDB, 0xB2, 0x5E, 0x43, 0x42, 0x69, 0x47, 0x68, 0x2A, 0x60, 0xBD, 0x5D, + 0xBB, 0xF8, 0x00, 0x40, 0xBB, 0x19, 0xA5, 0x42, 0x28, 0xBF, 0x25, 0x46, + 0x01, 0x92, 0x19, 0x46, 0x2A, 0x46, 0x01, 0x98, 0x05, 0x93, 0xFE, 0xF7, + 0x3D, 0xFE, 0x00, 0x22, 0x01, 0x9B, 0x64, 0x1B, 0xBE, 0x5D, 0x2B, 0x44, + 0xA4, 0xB2, 0x03, 0x92, 0x05, 0x9A, 0x11, 0x79, 0xBD, 0xF8, 0x0C, 0x20, + 0x91, 0x42, 0x05, 0xD8, 0x01, 0x9B, 0x5E, 0x80, 0xAB, 0xF8, 0x00, 0x50, + 0x01, 0x24, 0xD4, 0xE7, 0x03, 0x9A, 0x12, 0x01, 0x07, 0x92, 0x05, 0x9A, + 0x07, 0x99, 0xD2, 0xF8, 0x09, 0x20, 0x0A, 0x44, 0xD2, 0xF8, 0x08, 0x80, + 0xB8, 0xF1, 0x00, 0x0F, 0x13, 0xD0, 0x98, 0xF8, 0x00, 0x70, 0x18, 0x46, + 0xA7, 0x42, 0x28, 0xBF, 0x27, 0x46, 0x41, 0x46, 0x3A, 0x46, 0xFE, 0xF7, + 0x13, 0xFE, 0x03, 0x46, 0x98, 0xF8, 0x00, 0x20, 0xE4, 0x1B, 0x3D, 0x44, + 0x16, 0x44, 0x3B, 0x44, 0xA4, 0xB2, 0xAD, 0xB2, 0xB6, 0xB2, 0x00, 0x22, + 0x04, 0x92, 0x05, 0x9A, 0x07, 0x99, 0xD2, 0xF8, 0x09, 0x20, 0x0A, 0x44, + 0x10, 0x79, 0xBD, 0xF8, 0x10, 0x10, 0x88, 0x42, 0x02, 0xD8, 0x03, 0x9A, + 0x01, 0x32, 0xC2, 0xE7, 0x15, 0x20, 0x04, 0x99, 0xD2, 0xF8, 0x0C, 0x90, + 0x00, 0xFB, 0x01, 0xF8, 0x19, 0xF8, 0x08, 0x70, 0x09, 0xEB, 0x08, 0x0A, + 0xA7, 0x42, 0x28, 0xBF, 0x27, 0x46, 0x51, 0x46, 0x3A, 0x46, 0x18, 0x46, + 0xFE, 0xF7, 0xE8, 0xFD, 0x03, 0x46, 0x19, 0xF8, 0x08, 0x20, 0xDA, 0xF8, + 0x0D, 0x10, 0xE4, 0x1B, 0x3D, 0x44, 0x16, 0x44, 0x3B, 0x44, 0xA4, 0xB2, + 0xAD, 0xB2, 0xB6, 0xB2, 0xA9, 0xB1, 0xDA, 0xF8, 0x11, 0x70, 0x18, 0x46, + 0xA7, 0x42, 0xA8, 0xBF, 0x27, 0x46, 0x1F, 0xFA, 0x87, 0xF8, 0x42, 0x46, + 0xFE, 0xF7, 0xD0, 0xFD, 0x03, 0x46, 0xDA, 0xF8, 0x11, 0x20, 0xA4, 0xEB, + 0x08, 0x04, 0x45, 0x44, 0x16, 0x44, 0x43, 0x44, 0xA4, 0xB2, 0xAD, 0xB2, + 0xB6, 0xB2, 0x4F, 0xF0, 0x00, 0x08, 0x9A, 0xF8, 0x04, 0x10, 0x1F, 0xFA, + 0x88, 0xF2, 0x91, 0x42, 0x02, 0xD8, 0x04, 0x9A, 0x01, 0x32, 0xB1, 0xE7, + 0xDA, 0xF8, 0x09, 0x20, 0xC8, 0xEB, 0x08, 0x19, 0x06, 0x92, 0x4A, 0x44, + 0x02, 0x92, 0x06, 0x9A, 0x02, 0x99, 0x12, 0xF8, 0x09, 0x70, 0x18, 0x46, + 0xA7, 0x42, 0x28, 0xBF, 0x27, 0x46, 0x3A, 0x46, 0xFE, 0xF7, 0xA8, 0xFD, + 0x03, 0x46, 0x06, 0x9A, 0xE4, 0x1B, 0x12, 0xF8, 0x09, 0x20, 0x3D, 0x44, + 0x16, 0x44, 0x02, 0x9A, 0x3B, 0x44, 0xD2, 0xF8, 0x07, 0x10, 0xA4, 0xB2, + 0xAD, 0xB2, 0xB6, 0xB2, 0xB1, 0xB1, 0xD2, 0xF8, 0x0B, 0x70, 0x18, 0x46, + 0xA7, 0x42, 0xA8, 0xBF, 0x27, 0x46, 0x1F, 0xFA, 0x87, 0xF9, 0x4A, 0x46, + 0xFE, 0xF7, 0x8E, 0xFD, 0x03, 0x46, 0x02, 0x9A, 0xA4, 0xEB, 0x09, 0x04, + 0xD2, 0xF8, 0x0B, 0x20, 0x4D, 0x44, 0x16, 0x44, 0x4B, 0x44, 0xA4, 0xB2, + 0xAD, 0xB2, 0xB6, 0xB2, 0x08, 0xF1, 0x01, 0x08, 0xBB, 0xE7, 0xD4, 0xF8, + 0x05, 0x20, 0x18, 0x46, 0x52, 0xF8, 0x29, 0x20, 0x09, 0xF1, 0x01, 0x09, + 0x17, 0x78, 0x01, 0x92, 0xAF, 0x42, 0x28, 0xBF, 0x2F, 0x46, 0x01, 0x99, + 0x3A, 0x46, 0xFE, 0xF7, 0x6F, 0xFD, 0x03, 0x46, 0x01, 0x9A, 0xED, 0x1B, + 0x12, 0x78, 0x3E, 0x44, 0x92, 0x44, 0x3B, 0x44, 0xAD, 0xB2, 0xB6, 0xB2, + 0x1F, 0xFA, 0x8A, 0xFA, 0xF8, 0xE6, 0x13, 0xF0, 0xFF, 0x03, 0x46, 0x69, + 0x0F, 0xD1, 0x09, 0x23, 0xB3, 0x70, 0x04, 0x23, 0xF3, 0x70, 0x33, 0x70, + 0xBB, 0xF8, 0x00, 0x30, 0x04, 0x2B, 0x28, 0xBF, 0x04, 0x23, 0xAB, 0xF8, + 0x00, 0x30, 0x03, 0x23, 0x73, 0x70, 0x2E, 0x60, 0x22, 0xE7, 0xD0, 0xF8, + 0xE4, 0x20, 0x9A, 0x42, 0x1C, 0xD1, 0xD0, 0xF8, 0xE8, 0x40, 0x20, 0x46, + 0xFE, 0xF7, 0x51, 0xFD, 0x01, 0x30, 0x40, 0x00, 0xC0, 0xB2, 0x30, 0x70, + 0xBB, 0xF8, 0x00, 0x30, 0x98, 0x42, 0x28, 0xBF, 0x18, 0x46, 0x00, 0x23, + 0xAB, 0xF8, 0x00, 0x00, 0xBB, 0xF8, 0x00, 0x20, 0x52, 0x08, 0x01, 0x3A, + 0x9A, 0x42, 0xE0, 0xDD, 0xE1, 0x5C, 0x06, 0xEB, 0x43, 0x02, 0x51, 0x80, + 0x01, 0x33, 0xF3, 0xE7, 0xC4, 0x68, 0x01, 0x3B, 0x00, 0x2C, 0x3F, 0xF4, + 0xD4, 0xAE, 0x02, 0x69, 0x9A, 0x42, 0x7F, 0xF7, 0x9B, 0xAE, 0x40, 0xF2, + 0x09, 0x42, 0x89, 0x88, 0x91, 0x42, 0x7F, 0xF4, 0x95, 0xAE, 0x54, 0xF8, + 0x23, 0x40, 0x20, 0x46, 0xFE, 0xF7, 0x25, 0xFD, 0x01, 0x30, 0x40, 0x00, + 0xC0, 0xB2, 0x30, 0x70, 0xBB, 0xF8, 0x00, 0x30, 0x98, 0x42, 0x28, 0xBF, + 0x18, 0x46, 0x00, 0x23, 0xAB, 0xF8, 0x00, 0x00, 0xBB, 0xF8, 0x00, 0x20, + 0x52, 0x08, 0x01, 0x3A, 0x9A, 0x42, 0xB4, 0xDD, 0xE1, 0x5C, 0x06, 0xEB, + 0x43, 0x02, 0x51, 0x80, 0x01, 0x33, 0xF3, 0xE7, 0x19, 0x88, 0x01, 0x20, + 0x02, 0x29, 0x84, 0xBF, 0x02, 0x21, 0x19, 0x80, 0x00, 0x23, 0x11, 0x68, + 0x0B, 0x70, 0x12, 0x68, 0x53, 0x70, 0x70, 0x47, 0x00, 0x22, 0x10, 0xB5, + 0x00, 0xF1, 0xCC, 0x04, 0x54, 0xF8, 0x04, 0x3B, 0x2B, 0xB1, 0x01, 0x32, + 0x04, 0x2A, 0xF9, 0xD1, 0x4F, 0xF0, 0xFF, 0x30, 0x10, 0xBD, 0x00, 0xEB, + 0x82, 0x00, 0xC0, 0xF8, 0xCC, 0x10, 0x18, 0x46, 0xF8, 0xE7, 0x00, 0x00, + 0x10, 0xB4, 0x4C, 0x78, 0x09, 0x2C, 0x12, 0xD8, 0xDF, 0xE8, 0x04, 0xF0, + 0x0D, 0x11, 0x11, 0x11, 0x11, 0x0F, 0x0B, 0x11, 0x09, 0x05, 0x07, 0x4C, + 0xA4, 0x46, 0x10, 0xBC, 0x60, 0x47, 0x06, 0x4C, 0xFA, 0xE7, 0x06, 0x4C, + 0xF8, 0xE7, 0x06, 0x4C, 0xF6, 0xE7, 0x06, 0x4C, 0xF4, 0xE7, 0x00, 0x20, + 0x10, 0xBC, 0x70, 0x47, 0xBD, 0x11, 0x00, 0x08, 0x4F, 0x12, 0x00, 0x08, + 0x55, 0x13, 0x00, 0x08, 0xA5, 0x12, 0x00, 0x08, 0x95, 0x11, 0x00, 0x08, + 0x10, 0xB4, 0x4C, 0x78, 0x0A, 0x2C, 0x06, 0xD0, 0x0B, 0x2C, 0x06, 0xD0, + 0x3C, 0xB9, 0x05, 0x4C, 0xA4, 0x46, 0x10, 0xBC, 0x60, 0x47, 0x04, 0x4C, + 0xFA, 0xE7, 0x04, 0x4C, 0xF8, 0xE7, 0x00, 0x20, 0x10, 0xBC, 0x70, 0x47, + 0x7D, 0x16, 0x00, 0x08, 0x71, 0x12, 0x00, 0x08, 0x07, 0x13, 0x00, 0x08, + 0x10, 0xB4, 0x4C, 0x78, 0x01, 0x2C, 0x05, 0xD0, 0x84, 0xB1, 0x03, 0x2C, + 0x07, 0xD0, 0x00, 0x20, 0x10, 0xBC, 0x70, 0x47, 0x4C, 0x88, 0x00, 0x2C, + 0xF9, 0xD1, 0x05, 0x4C, 0x03, 0xE0, 0x4C, 0x88, 0x00, 0x2C, 0xF4, 0xD1, + 0x03, 0x4C, 0xA4, 0x46, 0x10, 0xBC, 0x60, 0x47, 0x02, 0x4C, 0xFA, 0xE7, + 0xF7, 0x12, 0x00, 0x08, 0xE7, 0x12, 0x00, 0x08, 0xBD, 0x12, 0x00, 0x08, + 0x10, 0xB4, 0x0C, 0x78, 0x14, 0xF0, 0x60, 0x0F, 0x06, 0xD1, 0x04, 0xF0, + 0x1F, 0x04, 0x01, 0x2C, 0x08, 0xD0, 0x24, 0xB1, 0x02, 0x2C, 0x08, 0xD0, + 0x00, 0x20, 0x10, 0xBC, 0x70, 0x47, 0x10, 0xBC, 0xFF, 0xF7, 0x94, 0xBF, + 0x10, 0xBC, 0xFF, 0xF7, 0xB5, 0xBF, 0x10, 0xBC, 0xFF, 0xF7, 0xCA, 0xBF, + 0x08, 0xB5, 0x40, 0xF2, 0x97, 0x30, 0xFF, 0xF7, 0xD6, 0xFA, 0x00, 0x23, + 0x05, 0x4A, 0x06, 0x49, 0x13, 0x60, 0x0B, 0x60, 0x41, 0xF8, 0x0C, 0x3C, + 0x4F, 0xF4, 0x1C, 0x43, 0x03, 0x48, 0x13, 0x60, 0x08, 0xBD, 0x00, 0xBF, + 0x40, 0x5C, 0x00, 0x40, 0x50, 0x5C, 0x00, 0x40, 0xC0, 0x0A, 0x00, 0x20, + 0x01, 0x32, 0x52, 0x10, 0x01, 0xEB, 0x42, 0x02, 0x91, 0x42, 0x00, 0xD1, + 0x70, 0x47, 0x31, 0xF8, 0x02, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0xF7, 0xE7, + 0x03, 0x46, 0x70, 0xB5, 0x02, 0xF0, 0x01, 0x04, 0x52, 0x08, 0x01, 0xEB, + 0x82, 0x05, 0xA9, 0x42, 0x04, 0xD1, 0x14, 0xB1, 0x0B, 0x78, 0x00, 0xF8, + 0x12, 0x30, 0x70, 0xBD, 0x31, 0xF8, 0x04, 0x6B, 0x23, 0xF8, 0x02, 0x6B, + 0xF3, 0xE7, 0xFE, 0xE7, 0x70, 0x47, 0x00, 0x00, 0x17, 0x4B, 0x18, 0x4A, + 0x18, 0x49, 0x8B, 0x42, 0x16, 0xD3, 0x00, 0x21, 0x17, 0x4A, 0x93, 0x42, + 0x17, 0xD3, 0x17, 0x4A, 0x17, 0x4C, 0x13, 0x68, 0x17, 0x4D, 0x43, 0xF4, + 0x00, 0x73, 0x13, 0x60, 0xAC, 0x42, 0x11, 0xD3, 0x15, 0x4C, 0x16, 0x4D, + 0xAC, 0x42, 0x11, 0xD3, 0xFE, 0xF7, 0xFC, 0xFC, 0x14, 0x4C, 0x15, 0x4D, + 0xAC, 0x42, 0x0F, 0xD3, 0x52, 0xF8, 0x04, 0x0B, 0x43, 0xF8, 0x04, 0x0B, + 0xE1, 0xE7, 0x43, 0xF8, 0x04, 0x1B, 0xE2, 0xE7, 0x54, 0xF8, 0x04, 0x3B, + 0x98, 0x47, 0xE7, 0xE7, 0x54, 0xF8, 0x04, 0x3B, 0x98, 0x47, 0xE7, 0xE7, + 0x54, 0xF8, 0x04, 0x3B, 0x98, 0x47, 0xE9, 0xE7, 0x00, 0x00, 0x00, 0x20, + 0x9C, 0x1F, 0x00, 0x08, 0x2C, 0x00, 0x00, 0x20, 0xD0, 0x0B, 0x00, 0x20, + 0x14, 0xED, 0x00, 0xE0, 0x9C, 0x1F, 0x00, 0x08, 0x9C, 0x1F, 0x00, 0x08, + 0x9C, 0x1F, 0x00, 0x08, 0x9C, 0x1F, 0x00, 0x08, 0x9C, 0x1F, 0x00, 0x08, + 0x9C, 0x1F, 0x00, 0x08, 0x02, 0x4B, 0x41, 0xF0, 0x80, 0x01, 0x19, 0x60, + 0x70, 0x47, 0x00, 0xBF, 0x4C, 0x5C, 0x00, 0x40, 0x3E, 0x2A, 0x0F, 0x4B, + 0x4F, 0xEA, 0xC1, 0x01, 0x0D, 0xD9, 0x1B, 0x68, 0xD0, 0x06, 0x9B, 0xB2, + 0x19, 0x44, 0x0C, 0x4B, 0x18, 0xBF, 0x20, 0x3A, 0x0B, 0x48, 0x43, 0xEA, + 0x42, 0x12, 0x49, 0x00, 0x92, 0xB2, 0x42, 0x50, 0x70, 0x47, 0x1B, 0x68, + 0xD0, 0x07, 0x9B, 0xB2, 0x48, 0xBF, 0x01, 0x32, 0x19, 0x44, 0x92, 0x02, + 0x04, 0x4B, 0x49, 0x00, 0x92, 0xB2, 0x5A, 0x50, 0x70, 0x47, 0x00, 0xBF, + 0x50, 0x5C, 0x00, 0x40, 0x00, 0x80, 0xFF, 0xFF, 0x0C, 0x60, 0x00, 0x40, + 0x2D, 0xE9, 0xF7, 0x43, 0x1E, 0x46, 0x4F, 0xF0, 0xC0, 0x63, 0x01, 0xF0, + 0x7F, 0x07, 0xBC, 0x00, 0x05, 0x46, 0x04, 0xF1, 0x80, 0x44, 0x4C, 0x48, + 0x04, 0xF5, 0xB8, 0x44, 0xCD, 0xE9, 0x00, 0x03, 0x23, 0x68, 0x02, 0xA8, + 0x23, 0xF4, 0xE0, 0x43, 0x23, 0xF0, 0x7F, 0x03, 0x3B, 0x43, 0x9B, 0xB2, + 0x23, 0x60, 0x23, 0x68, 0x00, 0xEB, 0x42, 0x02, 0x23, 0xF4, 0xEC, 0x43, + 0x32, 0xF8, 0x08, 0x2C, 0x23, 0xF0, 0x70, 0x03, 0x13, 0x43, 0x49, 0xB2, + 0x9B, 0xB2, 0x00, 0x29, 0xDD, 0xF8, 0x28, 0x80, 0x23, 0x60, 0xDF, 0xF8, + 0xFC, 0xC0, 0x4F, 0xEA, 0xC7, 0x0E, 0x2F, 0xDB, 0x77, 0xB3, 0xDC, 0xF8, + 0x00, 0x30, 0xAA, 0x8B, 0x9B, 0xB2, 0x9E, 0x44, 0x38, 0x4B, 0x4F, 0xEA, + 0x4E, 0x0E, 0x43, 0xF8, 0x0E, 0x20, 0x39, 0x46, 0x32, 0x46, 0x28, 0x46, + 0xFF, 0xF7, 0x9C, 0xFF, 0xB8, 0xF1, 0x00, 0x0F, 0x56, 0xD1, 0x23, 0x68, + 0x10, 0x21, 0x23, 0xF4, 0x41, 0x53, 0x23, 0xF0, 0x30, 0x03, 0x1B, 0x04, + 0x1B, 0x0C, 0x23, 0x60, 0x01, 0x23, 0x22, 0x68, 0x22, 0xF4, 0x80, 0x42, + 0x22, 0xF0, 0x70, 0x02, 0x92, 0xB2, 0x5B, 0x00, 0x01, 0x39, 0x9B, 0xB2, + 0x48, 0xD1, 0xAB, 0x8B, 0x42, 0xF4, 0x00, 0x42, 0x42, 0xF0, 0x80, 0x02, + 0x1E, 0x44, 0x22, 0x60, 0xAE, 0x83, 0x31, 0xE0, 0xDC, 0xF8, 0x00, 0x30, + 0xA8, 0x8B, 0x9B, 0xB2, 0x73, 0x44, 0x5B, 0x00, 0x03, 0xF1, 0x80, 0x43, + 0x03, 0xF5, 0xC0, 0x43, 0x18, 0x60, 0xB8, 0xF1, 0x00, 0x0F, 0x04, 0xD0, + 0x0C, 0x23, 0x03, 0xFB, 0x07, 0x53, 0xC3, 0xF8, 0x6C, 0x80, 0x23, 0x68, + 0x4F, 0xF0, 0x10, 0x09, 0x23, 0xF4, 0xE0, 0x43, 0x23, 0xF0, 0x30, 0x03, + 0x1B, 0x04, 0x1B, 0x0C, 0x23, 0x60, 0x01, 0x23, 0x22, 0x68, 0x22, 0xF4, + 0xE0, 0x42, 0x22, 0xF0, 0x40, 0x02, 0x92, 0xB2, 0x5B, 0x00, 0xB9, 0xF1, + 0x01, 0x09, 0x9B, 0xB2, 0x0B, 0xD1, 0x42, 0xF4, 0x00, 0x42, 0x42, 0xF0, + 0x80, 0x02, 0x30, 0x44, 0x00, 0x29, 0x22, 0x60, 0xA8, 0x83, 0x9E, 0xDA, + 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x13, 0xF0, 0x20, 0x0F, 0x18, 0xBF, + 0x5A, 0x40, 0xE9, 0xE7, 0x0C, 0x23, 0x03, 0xFB, 0x07, 0x57, 0xC7, 0xF8, + 0x70, 0x80, 0xA2, 0xE7, 0x13, 0xF4, 0x40, 0x5F, 0x18, 0xBF, 0x5A, 0x40, + 0xAD, 0xE7, 0x00, 0xBF, 0x00, 0x02, 0x00, 0x04, 0x08, 0x60, 0x00, 0x40, + 0x50, 0x5C, 0x00, 0x40, 0x48, 0xF2, 0x80, 0x01, 0x70, 0xB5, 0x0B, 0x4A, + 0x0B, 0x4E, 0x0C, 0x4D, 0x0C, 0x4C, 0x13, 0x68, 0x33, 0x40, 0x0B, 0x43, + 0x9B, 0xB2, 0x13, 0x60, 0x13, 0x68, 0x2B, 0x40, 0x0B, 0x43, 0x9B, 0xB2, + 0x42, 0xF8, 0x04, 0x3B, 0xA2, 0x42, 0xF2, 0xD1, 0x03, 0x68, 0xDB, 0x79, + 0x20, 0x33, 0x5B, 0x00, 0x83, 0x83, 0x70, 0xBD, 0x04, 0x5C, 0x00, 0x40, + 0xBF, 0x8F, 0xFF, 0xFF, 0x8F, 0xBF, 0xFF, 0xFF, 0x20, 0x5C, 0x00, 0x40, + 0x30, 0xB5, 0x00, 0x29, 0x41, 0xD1, 0x00, 0x2A, 0x14, 0xBF, 0x10, 0x25, + 0x20, 0x25, 0x10, 0x24, 0x01, 0x20, 0x33, 0x4B, 0x1B, 0x68, 0x23, 0xF4, + 0xE0, 0x43, 0x23, 0xF0, 0x40, 0x03, 0x9B, 0xB2, 0x28, 0x42, 0x18, 0xBF, + 0x43, 0x40, 0x40, 0x00, 0x01, 0x3C, 0x80, 0xB2, 0xF8, 0xD1, 0x43, 0xF4, + 0x00, 0x43, 0x2B, 0x48, 0x43, 0xF0, 0x80, 0x03, 0x03, 0x60, 0x89, 0x00, + 0x01, 0xF1, 0x80, 0x41, 0x01, 0xF5, 0xB8, 0x41, 0x3A, 0xB9, 0x0B, 0x68, + 0x23, 0xF4, 0x41, 0x53, 0x23, 0xF0, 0x30, 0x03, 0x1B, 0x04, 0x1B, 0x0C, + 0x0B, 0x60, 0x00, 0x2A, 0x14, 0xBF, 0x4F, 0xF4, 0x80, 0x54, 0x4F, 0xF4, + 0x40, 0x54, 0x10, 0x20, 0x01, 0x22, 0x0B, 0x68, 0x23, 0xF4, 0x80, 0x43, + 0x23, 0xF0, 0x70, 0x03, 0x9B, 0xB2, 0x22, 0x42, 0x18, 0xBF, 0x53, 0x40, + 0x52, 0x00, 0x01, 0x38, 0x92, 0xB2, 0xF8, 0xD1, 0x43, 0xF4, 0x00, 0x43, + 0x43, 0xF0, 0x80, 0x03, 0x28, 0xE0, 0x0B, 0x06, 0xD5, 0xD5, 0x00, 0x2A, + 0x14, 0xBF, 0x10, 0x25, 0x20, 0x25, 0x10, 0x24, 0x01, 0x20, 0x01, 0xF0, + 0x7F, 0x01, 0x89, 0x00, 0x01, 0xF1, 0x80, 0x41, 0x01, 0xF5, 0xB8, 0x41, + 0x0B, 0x68, 0x23, 0xF4, 0xE0, 0x43, 0x23, 0xF0, 0x40, 0x03, 0x9B, 0xB2, + 0x28, 0x42, 0x18, 0xBF, 0x43, 0x40, 0x40, 0x00, 0x01, 0x3C, 0x80, 0xB2, + 0xF8, 0xD1, 0x43, 0xF4, 0x00, 0x43, 0x43, 0xF0, 0x80, 0x03, 0x0B, 0x60, + 0x3A, 0xB9, 0x0B, 0x68, 0x23, 0xF4, 0xE0, 0x43, 0x23, 0xF0, 0x30, 0x03, + 0x1B, 0x04, 0x1B, 0x0C, 0x0B, 0x60, 0x30, 0xBD, 0x00, 0x5C, 0x00, 0x40, + 0x0B, 0x06, 0x0E, 0xD5, 0x01, 0xF0, 0x7F, 0x01, 0x89, 0x00, 0x01, 0xF1, + 0x80, 0x41, 0x01, 0xF5, 0xB8, 0x41, 0x08, 0x68, 0x00, 0xF0, 0x30, 0x00, + 0x10, 0x28, 0x14, 0xBF, 0x00, 0x20, 0x01, 0x20, 0x70, 0x47, 0x89, 0x00, + 0x01, 0xF1, 0x80, 0x41, 0x01, 0xF5, 0xB8, 0x41, 0x08, 0x68, 0x00, 0xF4, + 0x40, 0x50, 0xB0, 0xF5, 0x80, 0x5F, 0xF0, 0xE7, 0x0B, 0x06, 0x16, 0xD4, + 0x13, 0x4B, 0x14, 0x48, 0x5A, 0x54, 0x89, 0x00, 0x01, 0xF1, 0x80, 0x41, + 0x01, 0xF5, 0xB8, 0x41, 0x0B, 0x68, 0x03, 0x40, 0x9B, 0xB2, 0x10, 0x20, + 0x7A, 0xB1, 0x01, 0x22, 0x52, 0x00, 0x01, 0x38, 0x92, 0xB2, 0x05, 0xD1, + 0x43, 0xF4, 0x00, 0x43, 0x43, 0xF0, 0x80, 0x03, 0x0B, 0x60, 0x70, 0x47, + 0x12, 0xF4, 0x00, 0x5F, 0x18, 0xBF, 0x53, 0x40, 0xF0, 0xE7, 0x01, 0x22, + 0x52, 0x00, 0x01, 0x38, 0x92, 0xB2, 0xEF, 0xD0, 0x12, 0xF4, 0x40, 0x5F, + 0x18, 0xBF, 0x53, 0x40, 0xF6, 0xE7, 0x00, 0xBF, 0xC8, 0x0B, 0x00, 0x20, + 0x8F, 0xBF, 0xFF, 0xFF, 0x01, 0xF0, 0x7F, 0x01, 0xF8, 0xB5, 0x8C, 0x00, + 0x04, 0xF1, 0x80, 0x44, 0x04, 0xF5, 0xB8, 0x44, 0x1D, 0x46, 0x23, 0x68, + 0x94, 0x46, 0x03, 0xF0, 0x30, 0x03, 0x30, 0x2B, 0x31, 0xD0, 0x1A, 0x4F, + 0xCE, 0x00, 0x3A, 0x68, 0x61, 0x46, 0x92, 0xB2, 0x32, 0x44, 0x52, 0x00, + 0x02, 0xF1, 0x80, 0x42, 0x02, 0xF5, 0xC0, 0x42, 0x10, 0x88, 0x2A, 0x46, + 0x40, 0x00, 0x00, 0xF1, 0x80, 0x40, 0x00, 0xF5, 0xC0, 0x40, 0xFF, 0xF7, + 0xBF, 0xFD, 0x39, 0x68, 0x10, 0x4B, 0x89, 0xB2, 0x0E, 0x44, 0x76, 0x00, + 0x9D, 0x51, 0x10, 0x21, 0x01, 0x23, 0x22, 0x68, 0x22, 0xF4, 0xE0, 0x42, + 0x22, 0xF0, 0x40, 0x02, 0x92, 0xB2, 0x5B, 0x00, 0x01, 0x39, 0x9B, 0xB2, + 0x06, 0xD1, 0x42, 0xF4, 0x00, 0x42, 0x42, 0xF0, 0x80, 0x02, 0x22, 0x60, + 0x28, 0x46, 0xF8, 0xBD, 0x13, 0xF0, 0x30, 0x0F, 0x18, 0xBF, 0x5A, 0x40, + 0xEF, 0xE7, 0x00, 0x25, 0xF6, 0xE7, 0x00, 0xBF, 0x50, 0x5C, 0x00, 0x40, + 0x04, 0x60, 0x00, 0x40, 0xF8, 0xB5, 0x8C, 0x00, 0x04, 0xF1, 0x80, 0x44, + 0x04, 0xF5, 0xB8, 0x44, 0x1D, 0x46, 0x23, 0x68, 0x0E, 0x46, 0x03, 0xF4, + 0x40, 0x53, 0xB3, 0xF5, 0x40, 0x5F, 0x10, 0x46, 0x43, 0xD0, 0x23, 0x49, + 0xF2, 0x00, 0x0B, 0x68, 0x22, 0x4F, 0x9B, 0xB2, 0x13, 0x44, 0x5B, 0x00, + 0xFB, 0x58, 0xC3, 0xF3, 0x09, 0x03, 0xAB, 0x42, 0x06, 0xDA, 0x0B, 0x68, + 0x9B, 0xB2, 0x13, 0x44, 0x5B, 0x00, 0xFD, 0x58, 0xC5, 0xF3, 0x09, 0x05, + 0x0B, 0x68, 0x9B, 0xB2, 0x1A, 0x44, 0x1A, 0x4B, 0x52, 0x00, 0x99, 0x5A, + 0x2A, 0x46, 0x49, 0x00, 0x01, 0xF1, 0x80, 0x41, 0x01, 0xF5, 0xC0, 0x41, + 0xFF, 0xF7, 0x76, 0xFD, 0x23, 0x68, 0x23, 0xF0, 0xF0, 0x03, 0x1B, 0x05, + 0x1B, 0x0D, 0x43, 0xF0, 0x80, 0x03, 0x23, 0x60, 0x11, 0x4B, 0x9B, 0x5D, + 0x83, 0xB9, 0x10, 0x21, 0x01, 0x23, 0x22, 0x68, 0x22, 0xF4, 0x80, 0x42, + 0x22, 0xF0, 0x70, 0x02, 0x92, 0xB2, 0x5B, 0x00, 0x01, 0x39, 0x9B, 0xB2, + 0x06, 0xD1, 0x42, 0xF4, 0x00, 0x42, 0x42, 0xF0, 0x80, 0x02, 0x22, 0x60, + 0x28, 0x46, 0xF8, 0xBD, 0x13, 0xF4, 0x40, 0x5F, 0x18, 0xBF, 0x5A, 0x40, + 0xEF, 0xE7, 0x00, 0x25, 0xF6, 0xE7, 0x00, 0xBF, 0x50, 0x5C, 0x00, 0x40, + 0x0C, 0x60, 0x00, 0x40, 0x08, 0x60, 0x00, 0x40, 0xC8, 0x0B, 0x00, 0x20, + 0x38, 0x4A, 0x70, 0xB5, 0x13, 0x68, 0x04, 0x46, 0x13, 0xF4, 0x80, 0x6F, + 0x9E, 0xB2, 0x15, 0x46, 0x08, 0xD0, 0xBD, 0xE8, 0x70, 0x40, 0x4F, 0xF6, + 0xFF, 0x33, 0x13, 0x60, 0x40, 0x23, 0x83, 0x83, 0xFF, 0xF7, 0x6F, 0xB8, + 0x19, 0x04, 0x24, 0xD5, 0x03, 0xF0, 0x0F, 0x01, 0xC3, 0xF3, 0x00, 0x12, + 0x8B, 0x00, 0x03, 0xF1, 0x80, 0x43, 0x03, 0xF5, 0xB8, 0x43, 0x18, 0x68, + 0x49, 0xB9, 0x00, 0x2A, 0x38, 0xD0, 0x02, 0x06, 0x07, 0xD5, 0x94, 0xF8, + 0x30, 0x20, 0x03, 0x2A, 0x03, 0xD1, 0x08, 0x46, 0x06, 0xE0, 0x00, 0x2A, + 0x2E, 0xD0, 0x10, 0xF4, 0x00, 0x6F, 0x14, 0xBF, 0x02, 0x20, 0x01, 0x20, + 0x01, 0xEB, 0x41, 0x02, 0x02, 0x44, 0x04, 0xEB, 0x82, 0x02, 0xD2, 0x6E, + 0x62, 0xB3, 0x20, 0x46, 0x90, 0x47, 0x32, 0x05, 0x05, 0xD5, 0x4F, 0xF2, + 0xFF, 0x73, 0x2B, 0x60, 0x63, 0x6A, 0x03, 0xB1, 0x98, 0x47, 0xF3, 0x04, + 0x05, 0xD5, 0x4E, 0xF6, 0xFF, 0x73, 0x2B, 0x60, 0xA3, 0x6A, 0x03, 0xB1, + 0x98, 0x47, 0x16, 0xF4, 0x00, 0x7F, 0x14, 0x4E, 0x05, 0xD0, 0x4F, 0xF6, + 0xFF, 0x52, 0xE3, 0x6A, 0x2A, 0x60, 0xD3, 0xB1, 0x98, 0x47, 0xE3, 0x6A, + 0xBB, 0xB1, 0x33, 0x68, 0x43, 0xF4, 0x00, 0x73, 0x33, 0x60, 0x70, 0xBD, + 0x1A, 0x68, 0x00, 0x20, 0x22, 0xF0, 0xF0, 0x02, 0x12, 0x05, 0x12, 0x0D, + 0x42, 0xF4, 0x00, 0x42, 0x1A, 0x60, 0xCB, 0xE7, 0x1A, 0x68, 0x22, 0xF0, + 0xF0, 0x02, 0x12, 0x05, 0x12, 0x0D, 0x42, 0xF0, 0x80, 0x02, 0x1A, 0x60, + 0xCB, 0xE7, 0x33, 0x68, 0x23, 0xF4, 0x00, 0x73, 0xE6, 0xE7, 0x00, 0xBF, + 0x44, 0x5C, 0x00, 0x40, 0x40, 0x5C, 0x00, 0x40, 0x31, 0x00, 0x4D, 0x53, + 0x43, 0x00, 0x41, 0x00, 0xEB, 0x3C, 0x90, 0x55, 0x46, 0x32, 0x20, 0x55, + 0x46, 0x32, 0x20, 0x00, 0x02, 0x01, 0x01, 0x00, 0x02, 0x40, 0x00, 0x3E, + 0x1F, 0xF8, 0x20, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x42, 0x00, 0x42, 0x00, 0x53, + 0x54, 0x4D, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x41, + 0x54, 0x31, 0x36, 0x20, 0x20, 0x20, 0x05, 0x0F, 0x1D, 0x00, 0x01, 0x0C, + 0x00, 0x00, 0x20, 0x09, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0xC0, 0x32, + 0xB4, 0x1E, 0x00, 0x08, 0x12, 0x01, 0x10, 0x02, 0x00, 0x00, 0x00, 0x40, + 0x09, 0x12, 0x42, 0xDB, 0x10, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xE2, 0x1E, 0x00, 0x08, 0x07, 0x05, 0x01, 0x02, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x05, 0x82, 0x02, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x04, + 0x01, 0x00, 0x02, 0x08, 0x06, 0x50, 0x00, 0xC4, 0x1E, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x61, 0x70, 0x6C, 0x65, + 0x00, 0x4D, 0x61, 0x70, 0x6C, 0x65, 0x20, 0x42, 0x6F, 0x6F, 0x74, 0x6C, + 0x6F, 0x61, 0x64, 0x65, 0x72, 0x00, 0x4D, 0x61, 0x70, 0x6C, 0x65, 0x42, + 0x6F, 0x6F, 0x74, 0x00, 0x00, 0x80, 0x04, 0x02, 0x20, 0x00, 0x00, 0x00, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x10, + 0x05, 0x00, 0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47, 0x8B, 0xFD, + 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, + 0xA1, 0x17, 0x00, 0x08, 0xA1, 0x18, 0x00, 0x08, 0xFD, 0x18, 0x00, 0x08, + 0x51, 0x1A, 0x00, 0x08, 0x95, 0x1A, 0x00, 0x08, 0xB1, 0x1B, 0x00, 0x08, + 0x79, 0x1B, 0x00, 0x08, 0x0D, 0x1C, 0x00, 0x08, 0x9D, 0x1C, 0x00, 0x08, + 0x59, 0x1D, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x20, 0x00, 0x08, 0x4E, 0x1F, 0x00, 0x08, 0xF7, 0x1E, 0x00, 0x08, + 0xFD, 0x1E, 0x00, 0x08, 0x44, 0x1E, 0x00, 0x08, 0x0E, 0x1F, 0x00, 0x08, + 0x00, 0x12, 0x7A, 0x00, 0x00, 0x12, 0x7A, 0x00, 0x00, 0x12, 0x7A, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +#define BOARD_LED_PIN 33 + + +typedef struct { + volatile uint32 CR; + volatile uint32 CFGR; + volatile uint32 CIR; + volatile uint32 APB2RSTR; + volatile uint32 APB1RSTR; + volatile uint32 AHBENR; + volatile uint32 APB2ENR; + volatile uint32 APB1ENR; + volatile uint32 BDCR; + volatile uint32 CSR; +} RCC_RegStruct; + +typedef enum { RESET = 0, SET = !RESET } FlagStatus, ITStatus; + +typedef enum { DISABLE = 0, ENABLE = !DISABLE} FunctionalState; + +typedef enum { ERROR = 0, SUCCESS = !ERROR} ErrorStatus; + +#define BOOTLOADER_FLASH ((uint32)0x08000000) +#define PAGE_SIZE 1024 + +#define SET_REG(addr,val) do { *(volatile uint32*)(addr)=val; } while(0) +#define GET_REG(addr) (*(volatile uint32*)(addr)) + + +#define RCC ((uint32)0x40021000) +#define FLASH ((uint32)0x40022000) + +#define RCC_CR RCC +#define RCC_CFGR (RCC + 0x04) +#define RCC_CIR (RCC + 0x08) +#define RCC_AHBENR (RCC + 0x14) +#define RCC_APB2ENR (RCC + 0x18) +#define RCC_APB1ENR (RCC + 0x1C) + +#define FLASH_ACR (FLASH + 0x00) +#define FLASH_KEYR (FLASH + 0x04) +#define FLASH_OPTKEYR (FLASH + 0x08) +#define FLASH_SR (FLASH + 0x0C) +#define FLASH_CR (FLASH + 0x10) +#define FLASH_AR (FLASH + 0x14) +#define FLASH_OBR (FLASH + 0x1C) +#define FLASH_WRPR (FLASH + 0x20) + +#define FLASH_KEY1 0x45670123 +#define FLASH_KEY2 0xCDEF89AB +#define FLASH_RDPRT 0x00A5 +#define FLASH_SR_BSY 0x01 +#define FLASH_CR_PER 0x02 +#define FLASH_CR_PG 0x01 +#define FLASH_CR_START 0x40 + +#define pRCC ((RCC_RegStruct *) RCC) + + + +bool flashErasePage(uint32 pageAddr) { + uint32 rwmVal = GET_REG(FLASH_CR); + rwmVal = FLASH_CR_PER; + SET_REG(FLASH_CR, rwmVal); + + while (GET_REG(FLASH_SR) & FLASH_SR_BSY) {} + SET_REG(FLASH_AR, pageAddr); + SET_REG(FLASH_CR, FLASH_CR_START | FLASH_CR_PER); + while (GET_REG(FLASH_SR) & FLASH_SR_BSY) {} + + /* todo: verify the page was erased */ + + rwmVal = 0x00; + SET_REG(FLASH_CR, rwmVal); + + return true; +} +bool flashErasePages(uint32 pageAddr, uint16 n) { + while (n-- > 0) { + if (!flashErasePage(pageAddr + 0x400 * n)) { + return false; + } + } + + return true; +} + +bool flashWriteWord(uint32 addr, uint32 word) { + volatile uint16 *flashAddr = (volatile uint16 *)addr; + volatile uint32 lhWord = (volatile uint32)word & 0x0000FFFF; + volatile uint32 hhWord = ((volatile uint32)word & 0xFFFF0000) >> 16; + + uint32 rwmVal = GET_REG(FLASH_CR); + SET_REG(FLASH_CR, FLASH_CR_PG); + + /* apparently we need not write to FLASH_AR and can + simply do a native write of a half word */ + while (GET_REG(FLASH_SR) & FLASH_SR_BSY) {} + *(flashAddr + 0x01) = (volatile uint16)hhWord; + while (GET_REG(FLASH_SR) & FLASH_SR_BSY) {} + *(flashAddr) = (volatile uint16)lhWord; + while (GET_REG(FLASH_SR) & FLASH_SR_BSY) {} + + rwmVal &= 0xFFFFFFFE; + SET_REG(FLASH_CR, rwmVal); + + /* verify the write */ + if (*(volatile uint32 *)addr != word) { + return false; + } + + return true; +} + +void flashLock() { + /* take down the HSI oscillator? it may be in use elsewhere */ + + /* ensure all FPEC functions disabled and lock the FPEC */ + SET_REG(FLASH_CR, 0x00000080); +} + +void flashUnlock() { + /* unlock the flash */ + SET_REG(FLASH_KEYR, FLASH_KEY1); + SET_REG(FLASH_KEYR, FLASH_KEY2); +} + +/* Minimum_Source*/ + +void setupFLASH() { + /* configure the HSI oscillator */ + if ((pRCC->CR & 0x01) == 0x00) { + uint32 rwmVal = pRCC->CR; + rwmVal |= 0x01; + pRCC->CR = rwmVal; + } + + /* wait for it to come on */ + while ((pRCC->CR & 0x02) == 0x00) {} +} + +bool writeChunk(uint32 *ptr, int size, const char *data) +{ + flashErasePage((uint32)(ptr)); + + for (int i = 0; i < size; i = i + 4) { + if (!flashWriteWord((uint32)(ptr++), *((uint32 *)(data + i)))) { + return false; + } + } + + return true; +} + +bool isNewBootloaderAlreadyInstalled() +{ + char *existingBootloader = (char *) BOOTLOADER_FLASH; + int bootloaderSize=sizeof(maple_mini_boot_MSC); + + for(int i=0;i(maple_mini_boot_MSC); + int n = 0; + bool alreadyInstalled = isNewBootloaderAlreadyInstalled(); + + pinMode(BOARD_LED_PIN, OUTPUT); + + Serial.begin(9600); + // Wait for the user to open the serial window. + while (!(Serial.isConnected() && (Serial.getDTR() ))) + { + digitalWrite(BOARD_LED_PIN, !digitalRead(BOARD_LED_PIN)); + delay(1000); // Slow blink + } + + if (alreadyInstalled) + { + Serial.print("Congratulations. You have already updated to this version of the bootloader"); + while(1); + } + + + digitalWrite(BOARD_LED_PIN, LOW); + Serial.println ("**************************************************************************************************"); + Serial.println ("*** This sketch will update the bootloader in the Maple Mini to the STM32duino bootloader ****"); + Serial.println ("*** With this you can use up to 120KB of Flash and 20KB of RAM for a Sketch ****"); + Serial.println ("*** Uploading is also considerably faster on OSX (and possibly faster on Linux) ****"); + Serial.println ("*** ****"); + Serial.println ("*** Only use with Maple mini boards ****"); + Serial.println ("*** ****"); + Serial.println ("*** WARNING. If the update fails your Maple mini may not have a functional bootloder. ****"); + Serial.println ("*** ****"); + Serial.println ("*** YOU UPDATE AT YOUR OWN RISK ****"); + Serial.println ("*** ****"); + Serial.println ("*** ****"); + Serial.println ("*** ****"); + Serial.println ("*** ****"); + Serial.println ("**************************************************************************************************"); + Serial.println ("*** ****"); + Serial.println ("*** ****"); + Serial.println ("*** To confirm and proceed, enter Y ****"); + Serial.println ("*** ****"); + + while (Serial.read() != 'Y') + { + delay(1); + } + + Serial.println ("*** ****"); + + n = sizeof(maple_mini_boot_MSC); + + setupFLASH(); + flashUnlock(); + + int success = 1; + int pages = n/PAGE_SIZE; + int currentPage=1; + for (int i = 0; i < n; i += PAGE_SIZE) + { + int size = 0; + uint32* chunk = (uint32 *)(BOOTLOADER_FLASH + i); + + size = n - i; + if (size > PAGE_SIZE) + { + size = PAGE_SIZE; + } + + if (!writeChunk(chunk, size, &bootloader[i])) + { + Serial.println (); + Serial.println ("WARNING, Update Failed!! The sketch will restart in 3 seconds and you can try to flash again"); + delay (3000); + success = 0; + break; + } + Serial.print("Writing flash page ");Serial.print(currentPage++);Serial.print(" of ");Serial.println(pages+1); + } + + if (success) + { + flashLock(); + Serial.println (); + Serial.println ("Update completed successfully. - Please test by uploading a different sketch"); + while (1) { + digitalWrite(BOARD_LED_PIN, LOW); + delay(500); + digitalWrite(BOARD_LED_PIN, HIGH); + delay(500); + } + } +} + +void loop(){} + diff --git a/release.Makefile b/release.Makefile deleted file mode 100644 index 8bc500f..0000000 --- a/release.Makefile +++ /dev/null @@ -1,61 +0,0 @@ -## Copyright (c) 2017, Devan Lai -## -## Permission to use, copy, modify, and/or distribute this software -## for any purpose with or without fee is hereby granted, provided -## that the above copyright notice and this permission notice -## appear in all copies. -## -## THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL -## WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -## WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE -## AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR -## CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -## LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, -## NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -## CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -# This Makefile builds all official targets and places the firmware -# bin files in the build/ directory. -# -# For normal development, use the Makefile in the src/ directory. - -# Be silent per default, but 'make V=1' will show all compiler calls. -ifneq ($(V),1) -Q := @ -NULL := 2>/dev/null -MAKE := $(MAKE) --no-print-directory -endif -export V - -BUILD_DIR ?= ./build - -all: dapboot-bluepill.bin \ - dapboot-maplemini.bin \ - dapboot-stlink.bin - -clean: - $(Q)$(RM) $(BUILD_DIR)/*.bin - $(Q)$(MAKE) -C src/ clean - -.PHONY = all clean - -$(BUILD_DIR): - $(Q)mkdir -p $(BUILD_DIR) - -dapboot-bluepill.bin: | $(BUILD_DIR) - @printf " BUILD $(@)\n" - $(Q)$(MAKE) TARGET=BLUEPILL -C src/ clean - $(Q)$(MAKE) TARGET=BLUEPILL -C src/ - $(Q)cp src/dapboot.bin $(BUILD_DIR)/$(@) - -dapboot-stlink.bin: | $(BUILD_DIR) - @printf " BUILD $(@)\n" - $(Q)$(MAKE) TARGET=STLINK -C src/ clean - $(Q)$(MAKE) TARGET=STLINK -C src/ - $(Q)cp src/dapboot.bin $(BUILD_DIR)/$(@) - -dapboot-maplemini.bin: | $(BUILD_DIR) - @printf " BUILD $(@)\n" - $(Q)$(MAKE) TARGET=MAPLEMINI -C src/ clean - $(Q)$(MAKE) TARGET=MAPLEMINI -C src/ - $(Q)cp src/dapboot.bin $(BUILD_DIR)/$(@) diff --git a/src/Makefile b/src/Makefile index c56f8fa..78de789 100644 --- a/src/Makefile +++ b/src/Makefile @@ -19,8 +19,8 @@ BINARY = MSCboot OPENCM3_DIR = ../libopencm3 -UF2_VERSION_BASE = $(shell git describe --dirty --always --tags) -VER_FLAGS = -DUF2_VERSION='"$(UF2_VERSION_BASE)"' +MSC_VERSION_BASE = $(shell git describe --dirty --always --tags) +VER_FLAGS = -DMSC_VERSION='"$(MSC_VERSION_BASE)"' TARGET ?= BLUEPILL include targets.mk @@ -37,9 +37,9 @@ DEPS = $(addprefix $(BUILD)/,$(SRCS:.c=.d)) ELF = $(BUILD)/$(BINARY).elf all: $(BUILD) $(BUILD)/$(BINARY).bin size - + $(BUILD): - mkdir -p $(BUILD)/stm32f103 + mkdir -p $(BUILD)/$(CPU) clean:: rm -rf build/ @@ -49,25 +49,6 @@ include rules.mk size: $(OBJS) $(ELF) @$(PREFIX)-size $(ELF) -BMP = $(shell ls -1 /dev/cu.usbmodem* | head -1) -BMP_ARGS = -ex "target extended-remote $(BMP)" -ex "mon swdp_scan" -ex "attach 1" -GDB = arm-none-eabi-gdb - -flash: $(ELF) - $(GDB) $(BMP_ARGS) -ex "load" -ex "quit" $(ELF) - -gdb: $(ELF) - $(GDB) $(BMP_ARGS) $(ELF) - -ocd-gdb: $(ELF) - -$(GDB) --eval "target remote | $(OOCD) -f $(OOCD_INTERFACE) -f $(OOCD_BOARD) -f debug.cfg" $(ELF) - -erase: - $(OOCD) -f $(OOCD_INTERFACE) -f $(OOCD_BOARD) \ - -c "init" -c "reset init" \ - -c "stm32f1x unlock 0; reset halt" \ - -c "flash erase_sector 0 0 last" -c "reset" -c "shutdown" - .PHONY += debug size erase OBJS := $(sort $(OBJS)) @@ -79,13 +60,4 @@ CPPFLAGS += -I. CPPFLAGS += -I$(TARGET_COMMON_DIR)/ CPPFLAGS += -I$(TARGET_SPEC_DIR)/ -DROPNAME = uf2-stm32f103-$(UF2_VERSION_BASE) - -do-drop: all - mkdir -p build/$(DROPNAME) - cp $(BUILD)/$(BINARY).bin build/$(DROPNAME)/$(BINARY)-$(TARGET).bin -drop: - rm -rf build - set -e; for t in BLUEPILL PXT32 ; do $(MAKE) TARGET=$$t do-drop ; done - cd build; 7z a $(DROPNAME).zip $(DROPNAME) diff --git a/src/blink/Makefile b/src/blink/Makefile deleted file mode 100644 index 3137eb6..0000000 --- a/src/blink/Makefile +++ /dev/null @@ -1,59 +0,0 @@ -## Copyright (c) 2016, Devan Lai -## -## Permission to use, copy, modify, and/or distribute this software -## for any purpose with or without fee is hereby granted, provided -## that the above copyright notice and this permission notice -## appear in all copies. -## -## THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL -## WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -## WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE -## AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR -## CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -## LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, -## NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -## CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --include ../local.mk - -BINARY = blink -OPENCM3_DIR = ../../libopencm3 - -TARGET ?= BLUEPILL -include ../targets.mk -LDSCRIPT := ./stm32f103x8.ld - -SRCS := $(wildcard *.c) -SRCS += $(wildcard ../$(TARGET_COMMON_DIR)/*.c) -SRCS += $(wildcard ../$(TARGET_SPEC_DIR)/*.c) - -OBJS += $(SRCS:.c=.o) -DEPS = $(SRCS:.c=.d) - -.DEFAULT_GOAL := $(BINARY).uf2 - -$(BINARY).uf2: $(BINARY).bin - python uf2conv.py -c -b 0x08004000 -o "$@" "$<" - -clean:: - @rm -f $(OBJS) - @rm -f $(DEPS) - -include ../rules.mk - -size: $(OBJS) $(BINARY).elf - @$(PREFIX)-size $(OBJS) $(BINARY).elf - -debug: $(BINARY).elf - -$(GDB) --eval "target remote | $(OOCD) -f $(OOCD_INTERFACE) -f $(OOCD_BOARD) -f debug.cfg" $(BINARY).elf - -.PHONY += debug size erase - -OBJS := $(sort $(OBJS)) - -# Add the base directory to the header search path -CPPFLAGS += -I.. - -# Add target config directory to the header search path -CPPFLAGS += -I../$(TARGET_COMMON_DIR)/ -CPPFLAGS += -I../$(TARGET_SPEC_DIR)/ diff --git a/src/blink/uf2conv.py b/src/blink/uf2conv.py deleted file mode 100644 index 80b8327..0000000 --- a/src/blink/uf2conv.py +++ /dev/null @@ -1,242 +0,0 @@ -#!/usr/bin/python -# (c) Microsoft -# License: MIT - -import sys -import struct -import subprocess -import re -import os -import os.path -import argparse - -UF2_MAGIC_START0 = 0x0A324655 # "UF2\n" -UF2_MAGIC_START1 = 0x9E5D5157 # Randomly selected -UF2_MAGIC_END = 0x0AB16F30 # Ditto - -INFO_FILE = "/INFO_UF2.TXT" - -appstartaddr = 0x2000 - -def isUF2(buf): - w = struct.unpack(" 476: - assert False, "Invalid UF2 data size at " + ptr - newaddr = hd[3] - if curraddr == None: - appstartaddr = newaddr - curraddr = newaddr - padding = newaddr - curraddr - if padding < 0: - assert False, "Block out of order at " + ptr - if padding > 10*1024*1024: - assert False, "More than 10M of padding needed at " + ptr - if padding % 4 != 0: - assert False, "Non-word padding size at " + ptr - while padding > 0: - padding -= 4 - outp += "\x00\x00\x00\x00" - outp += block[32 : 32 + datalen] - curraddr = newaddr + datalen - return outp - -def convertToUF2(fileContent): - datapadding = "" - while len(datapadding) < 512 - 256 - 32 - 4: - datapadding += "\x00\x00\x00\x00" - numblocks = (len(fileContent) + 255) / 256 - outp = "" - for blockno in range(0, numblocks): - ptr = 256 * blockno - chunk = fileContent[ptr:ptr + 256] - hd = struct.pack("= 3 and words[1] == "2" and words[2] == "FAT": - drives.append(words[0]) - else: - rootpath = "/media" - if sys.platform == "darwin": - rootpath = "/Volumes" - elif sys.platform == "linux": - tmp = rootpath + "/" + os.environ["USER"] - if os.path.isdir(tmp): - rootpath = tmp - for d in os.listdir(rootpath): - drives.append(os.path.join(rootpath, d)) - - def hasInfo(d): - try: - return os.path.isfile(d + INFO_FILE) - except: - return False - - return filter(hasInfo, drives) - -def boardID(path): - with open(path + INFO_FILE, mode='r') as file: - fileContent = file.read() - return re.search("Board-ID: ([^\r\n]*)", fileContent).group(1) - -def listdrives(): - for d in getdrives(): - print d, boardID(d) - -def writeFile(name, buf): - with open(name, "wb") as f: - f.write(buf) - print "Wrote %d bytes to %s." % (len(buf), name) - -def main(): - global appstartaddr - def error(msg): - print msg - sys.exit(1) - parser = argparse.ArgumentParser(description='Convert to UF2 or flash directly.') - parser.add_argument('input', metavar='INPUT', type=str, nargs='?', - help='input file (HEX, BIN or UF2)') - parser.add_argument('-b' , '--base', dest='base', type=str, - default="0x2000", - help='set base address of application for BIN format (default: 0x2000)') - parser.add_argument('-o' , '--output', metavar="FILE", dest='output', type=str, - help='write output to named file; defaults to "flash.uf2" or "flash.bin" where sensible') - parser.add_argument('-d' , '--device', dest="device_path", - help='select a device path to flash') - parser.add_argument('-l' , '--list', action='store_true', - help='list connected devices') - parser.add_argument('-c' , '--convert', action='store_true', - help='do not flash, just convert') - args = parser.parse_args() - appstartaddr = int(args.base, 0) - if args.list: - listdrives() - else: - if not args.input: - error("Need input file") - with open(args.input, mode='rb') as file: - inpbuf = file.read() - fromUF2 = isUF2(inpbuf) - ext = "uf2" - if fromUF2: - outbuf = convertFromUF2(inpbuf) - ext = "bin" - elif isHEX(inpbuf): - outbuf = convertFromHexToUF2(inpbuf) - else: - outbuf = convertToUF2(inpbuf) - print "Converting to %s, output size: %d, start address: 0x%x" % (ext, len(outbuf), appstartaddr) - - if args.convert: - drives = [] - if args.output == None: - args.output = "flash." + ext - else: - drives = getdrives() - - if args.output: - writeFile(args.output, outbuf) - else: - if len(drives) == 0: - error("No drive to deploy.") - for d in drives: - print "Flashing %s (%s)" % (d, boardID(d)) - writeFile(outbuf, d + "/NEW.UF2") - -if __name__ == "__main__": - main() diff --git a/src/bmp.sh b/src/bmp.sh deleted file mode 100755 index 2d5de3c..0000000 --- a/src/bmp.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -d=$(ls -1 /dev/cu.usbmodem* | head -1) -cat < #include -#include "uf2.h" #include "dapboot.h" #include "target.h" #include "usb_conf.h" -#include "webusb.h" #include "config.h" +#include "ghostfat.h" #include @@ -73,7 +72,6 @@ int main(void) { /* Setup clocks */ target_clock_setup(); - #ifdef DEVICE_DMESG trace_setup(); #endif @@ -82,19 +80,10 @@ int main(void) { target_gpio_setup(); if (target_get_force_bootloader() || !appValid) { - /* Setup USB */ - { - //char serial[USB_SERIAL_NUM_LENGTH+1]; - //serial[0] = '\0'; - //target_get_serial_number(serial, USB_SERIAL_NUM_LENGTH); - //usb_set_serial_number(serial); - } usbd_device* usbd_dev = usb_setup(); - //dfu_setup(usbd_dev, &target_manifest_app, NULL, NULL); usb_msc_init(usbd_dev, 0x82, 64, 0x01, 64, "A", "MSC", - "1", UF2_NUM_BLOCKS, read_block, write_block); - //winusb_setup(usbd_dev); + "1", BIN_NUM_BLOCKS, read_block, write_block); int cycleCount = 0; int br = 500; @@ -115,9 +104,6 @@ int main(void) { else if (br < 10) d = 2; - //int v = msTimer % 500; - //target_set_led(v < 50); - ghostfat_1ms(); if (appValid && !msc_started && msTimer > 3000) { diff --git a/src/debug.cfg b/src/debug.cfg deleted file mode 100644 index 01bb119..0000000 --- a/src/debug.cfg +++ /dev/null @@ -1,12 +0,0 @@ -gdb_port pipe -gdb_memory_map disable - -$_TARGETNAME configure -event gdb-attach { - echo "Halting target" - halt -} - -$_TARGETNAME configure -event gdb-detach { - echo "Resetting target" - reset -} \ No newline at end of file diff --git a/src/dmesg.c b/src/dmesg.c index 038a813..3333339 100644 --- a/src/dmesg.c +++ b/src/dmesg.c @@ -26,12 +26,13 @@ DEALINGS IN THE SOFTWARE. #include #include "libopencm3/cm3/cortex.h" +#ifdef DEVICE_DMESG #include #include #include #include -#ifdef DEVICE_DMESG + void trace_setup(void) { /* Enable trace subsystem (we'll use ITM and TPIU). */ diff --git a/src/gdb.sh b/src/gdb.sh deleted file mode 100755 index 9caa000..0000000 --- a/src/gdb.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -./bmp.sh > build/debug.gdb -arm-none-eabi-gdb --command=build/debug.gdb diff --git a/src/ghostfat.c b/src/ghostfat.c index 6f8ed60..c14b2b0 100644 --- a/src/ghostfat.c +++ b/src/ghostfat.c @@ -1,9 +1,10 @@ -#include "uf2.h" #include #include "target.h" #include "dmesg.h" +#include "ghostfat.h" +#include "config.h" typedef struct { uint8_t JumpInstruction[3]; @@ -44,9 +45,11 @@ typedef struct { uint32_t size; } __attribute__((packed)) DirEntry; +#if (FILE_INFO == 1) static size_t flashSize(void) { - return FLASH_SIZE_OVERRIDE; + return USER_FLASH_END - USER_FLASH_START; } +#endif //#define DBG NOOP #define DBG DMESG @@ -56,36 +59,25 @@ struct TextFile { const char *content; }; -#define NUM_FAT_BLOCKS UF2_NUM_BLOCKS +#define NUM_FAT_BLOCKS BIN_NUM_BLOCKS #define STR0(x) #x #define STR(x) STR0(x) const char infoUf2File[] = // - "UF2 Bootloader " UF2_VERSION "\r\n" + "MSC Bootloader " MSC_VERSION "\r\n" "Model: " PRODUCT_NAME "\r\n" - "Board-ID: " BOARD_ID "\r\n"; - -const char indexFile[] = // - "\n" - "" - "" - "" - "" - "\n"; + "Bootloader size: " BOOTLOADER_SIZE "\r\n"; static const struct TextFile info[] = { -// {.name = "INFO_UF2TXT", .content = infoUf2File}, -// {.name = "INDEX HTM", .content = indexFile}, -// {.name = "CURRENT UF2"}, + {.name = "INFO_MSCTXT", .content = infoUf2File}, + {.name = "CURRENT BIN"}, }; #define NUM_INFO (int)(sizeof(info) / sizeof(info[0])) -#define UF2_SIZE (flashSize() * 2) -#define UF2_SECTORS (UF2_SIZE / 512) -#define UF2_FIRST_SECTOR (NUM_INFO + 1) -#define UF2_LAST_SECTOR (uint32_t)(UF2_FIRST_SECTOR + UF2_SECTORS - 1) +#define BIN_SIZE (flashSize()) +#define BIN_SECTORS (BIN_SIZE / 512) +#define BIN_FIRST_SECTOR (NUM_INFO + 1) +#define BIN_LAST_SECTOR (uint32_t)(BIN_FIRST_SECTOR + BIN_SECTORS - 1) #define RESERVED_SECTORS 1 #define ROOT_DIR_SECTORS 4 @@ -98,7 +90,7 @@ static const struct TextFile info[] = { static const FAT_BootBlock BootBlock = { .JumpInstruction = {0xeb, 0x3c, 0x90}, - .OEMInfo = "UF2 UF2 ", + .OEMInfo = "MSC MSC ", .SectorSize = 512, .SectorsPerCluster = 1, .ReservedSectors = RESERVED_SECTORS, @@ -215,108 +207,51 @@ int read_block(uint32_t block_no, uint8_t *data) { data[i] = 0xff; } } +#if (FILE_INFO == 1) for (int i = 0; i < 256; ++i) { - uint32_t v = sectionIdx * 256 + i; - if (UF2_FIRST_SECTOR <= v && v <= UF2_LAST_SECTOR) - ((uint16_t *)(void *)data)[i] = v == UF2_LAST_SECTOR ? 0xffff : v + 1; + uint32_t v = sectionIdx * 512 + i; + if (BIN_FIRST_SECTOR <= v && v <= BIN_LAST_SECTOR) + ((uint16_t *)(void *)data)[i] = v == BIN_LAST_SECTOR ? 0xffff : v + 1; } +#endif } else if (block_no < START_CLUSTERS) { sectionIdx -= START_ROOTDIR; if (sectionIdx == 0) { - //DirEntry *d = (void *)data; - //padded_memcpy(d->name, (const char *)BootBlock.VolumeLabel, 11); - //d->attrs = 0x28; - //for (int i = 0; i < NUM_INFO; ++i) { - // d++; - // const struct TextFile *inf = &info[i]; - // d->size = inf->content ? strlen(inf->content) : UF2_SIZE; - // d->startCluster = i + 2; - // padded_memcpy(d->name, inf->name, 11); - //} + + DirEntry *d = (void *)data; + padded_memcpy(d->name, (const char *)BootBlock.VolumeLabel, 11); + d->attrs = 0x28; +#if (FILE_INFO == 1) + for (int i = 0; i < NUM_INFO; ++i) { + d++; + const struct TextFile *inf = &info[i]; + d->size = inf->content ? strlen(inf->content) : BIN_SIZE; + d->startCluster = i + 2; + d->attrs = 0x01; + padded_memcpy(d->name, inf->name, 11); + } +#endif } } else { sectionIdx -= START_CLUSTERS; -/* -// if (sectionIdx < NUM_INFO - 1) { - if (sectionIdx < NUM_INFO) { +#if (FILE_INFO == 1) + if (sectionIdx < NUM_INFO - 1) { memcpy(data, info[sectionIdx].content, strlen(info[sectionIdx].content)); } else { sectionIdx -= NUM_INFO - 1; - uint32_t addr = sectionIdx * 256; + uint32_t addr = sectionIdx * 512; if (addr < flashSize()) { - UF2_Block *bl = (void *)data; - bl->magicStart0 = UF2_MAGIC_START0; - bl->magicStart1 = UF2_MAGIC_START1; - bl->magicEnd = UF2_MAGIC_END; - bl->blockNo = sectionIdx; - bl->numBlocks = flashSize() / 256; - bl->targetAddr = addr | 0x8000000; - bl->payloadSize = 256; - memcpy(bl->data, (void *)addr, bl->payloadSize); - } - }*/ - } - - return 0; -} - -static void write_block_core(uint32_t block_no, const uint8_t *data, bool quiet, WriteState *state) { - const UF2_Block *bl = (const void *)data; - - (void)block_no; - - // DBG("Write magic: %x", bl->magicStart0); - - if (!is_uf2_block(bl) || !UF2_IS_MY_FAMILY(bl)) { - return; - } - - if ((bl->flags & UF2_FLAG_NOFLASH) || bl->payloadSize > 256 || (bl->targetAddr & 0xff) || - bl->targetAddr < USER_FLASH_START || bl->targetAddr + bl->payloadSize > USER_FLASH_END) { - DBG("Skip block at %x", bl->targetAddr); - // this happens when we're trying to re-flash CURRENT.UF2 file previously - // copied from a device; we still want to count these blocks to reset properly - } else { - // logval("write block at", bl->targetAddr); - DBG("Write block at %x", bl->targetAddr); - flash_write(bl->targetAddr, bl->data, bl->payloadSize); - } - - bool isSet = false; - if (state && bl->numBlocks) { - if (state->numBlocks != bl->numBlocks) { - if (bl->numBlocks >= MAX_BLOCKS || state->numBlocks) - state->numBlocks = 0xffffffff; - else - state->numBlocks = bl->numBlocks; - } - if (bl->blockNo < MAX_BLOCKS) { - uint8_t mask = 1 << (bl->blockNo % 8); - uint32_t pos = bl->blockNo / 8; - if (!(state->writtenMask[pos] & mask)) { - // logval("incr", state->numWritten); - state->writtenMask[pos] |= mask; - state->numWritten++; - } - if (state->numWritten >= state->numBlocks) { - // wait a little bit before resetting, to avoid Windows transmit error - // https://github.com/Microsoft/uf2-samd21/issues/11 - if (!quiet) { - uf2_timer_start(30); - isSet = true; - } + memcpy(data, (void *)(addr + APP_BASE_ADDRESS), 512); } } - //DBG("wr %d=%d (of %d)", state->numWritten, bl->blockNo, bl->numBlocks); - } - - if (!isSet && !quiet) { - uf2_timer_start(500); +#endif } + return 0; } + static void write_block_bin(uint32_t block_no, const uint8_t *data) { static bool binStart=0; static uint32_t targetAddr = USER_FLASH_START; @@ -336,13 +271,12 @@ static void write_block_bin(uint32_t block_no, const uint8_t *data) { } -WriteState wrState; int write_block(uint32_t lba, const uint8_t *copy_from) { DBG("Write lba: %x", lba); target_set_led(1); - if(lba > 246) { + if(lba > 0x44) { write_block_bin(lba, copy_from); } target_set_led(0); diff --git a/src/ghostfat.h b/src/ghostfat.h new file mode 100644 index 0000000..3994b05 --- /dev/null +++ b/src/ghostfat.h @@ -0,0 +1,9 @@ +#pragma once + +#define BIN_NUM_BLOCKS 8000 +#define USER_FLASH_START (uint32_t)(APP_BASE_ADDRESS) +#define USER_FLASH_END (0x08000000+FLASH_SIZE_OVERRIDE) + +int write_block(uint32_t lba, const uint8_t *copy_from); +int read_block(uint32_t block_no, uint8_t *data); +void ghostfat_1ms(void); diff --git a/src/rules.mk b/src/rules.mk index 4c403d7..900076a 100644 --- a/src/rules.mk +++ b/src/rules.mk @@ -93,7 +93,7 @@ LIB_DIR = $(OPENCM3_DIR)/lib CFLAGS += -Os -g -std=gnu11 CFLAGS += -Wextra -Wshadow -Wimplicit-function-declaration -CFLAGS += -Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes +CFLAGS += -Wredundant-decls -Wstrict-prototypes CFLAGS += -fno-common -ffunction-sections -fdata-sections #################################################################### @@ -107,7 +107,7 @@ CXXFLAGS += -fno-common -ffunction-sections -fdata-sections # C & C++ preprocessor common flags CPPFLAGS += -MD -CPPFLAGS += -Wall -Wundef +CPPFLAGS += -Wall CPPFLAGS += -I$(INCLUDE_DIR) $(DEFS) #################################################################### @@ -163,9 +163,10 @@ locm3: $(LIB_DIR)/lib$(LIBNAME).a %.bin: %.elf @#printf " OBJCOPY $(*).bin\n" - $(Q)$(OBJCOPY) -Obinary $(*).elf $(*).tmpbin - $(Q)(cat $(*).tmpbin; cat /dev/zero) | head -c 8192 > $(*).bin - + #$(Q)$(OBJCOPY) -Obinary $(*).elf $(*).tmpbin + #$(Q)(cat $(*).tmpbin; cat /dev/zero) | head -c 8192 > $(*).bin + $(Q)$(OBJCOPY) -Obinary $(*).elf $(*).bin + %.hex: %.elf @#printf " OBJCOPY $(*).hex\n" $(Q)$(OBJCOPY) -Oihex $(*).elf $(*).hex diff --git a/src/run.sh b/src/run.sh deleted file mode 100755 index 4816aa2..0000000 --- a/src/run.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh - -set -e -make -(./bmp.sh && echo load && echo quit) > build/flash.gdb -arm-none-eabi-gdb --command=build/flash.gdb diff --git a/src/stm32f072/Clockwork2-CAN/config.h b/src/stm32f072/Clockwork2-CAN/config.h new file mode 100644 index 0000000..512dc1b --- /dev/null +++ b/src/stm32f072/Clockwork2-CAN/config.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2016, Devan Lai + * + * Permission to use, copy, modify, and/or distribute this software + * for any purpose with or without fee is hereby granted, provided + * that the above copyright notice and this permission notice + * appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef CONFIG_H_INCLUDED +#define CONFIG_H_INCLUDED + + +#define APP_BASE_ADDRESS 0x08004000 +#define FLASH_SIZE_OVERRIDE 0x20000 +#define FLASH_PAGE_SIZE 2048 + +#define FILE_INFO 1 +#define PRODUCT_NAME "Clockwork2 CAN STM32F072" +#define VOLUME_LABEL "CW2 CAN" +#define BOOTLOADER_SIZE "16k" + + +#define HAVE_LED 1 +#define LED_GPIO_PORT GPIOB +#define LED_GPIO_PIN GPIO5 + +#define LED_OPEN_DRAIN 0 + +#ifndef HAVE_USB_PULLUP_CONTROL +#define HAVE_USB_PULLUP_CONTROL 0 +#endif + +#define DOUBLE_TAP + +#if 0 +#define target_gpio_setup() {\ + rcc_periph_clock_enable(RCC_GPIOA);\ + rcc_periph_clock_enable(RCC_GPIOB);\ + rcc_periph_clock_enable(RCC_GPIOC);\ + GPIO_MODER(GPIOC) = 0x4000000;\ + GPIO_MODER(GPIOA) = 0x29000000;\ + GPIO_OSPEEDR(GPIOA) = 0xc000000;\ + } +#endif + +#endif diff --git a/src/blink/blink.c b/src/stm32f072/backup.c similarity index 62% rename from src/blink/blink.c rename to src/stm32f072/backup.c index 64f04a4..827e090 100644 --- a/src/blink/blink.c +++ b/src/stm32f072/backup.c @@ -16,28 +16,28 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include -#include "target.h" +#include +#include +#include +#include + +#include "backup.h" + +void backup_write(uint16_t value) { + //Todo: stm32f072 + + rcc_periph_clock_enable(RCC_PWR); + + pwr_disable_backup_domain_write_protect(); + PWR_CR |= PWR_CR_DBP; + RTC_BKPXR(4) = value; + pwr_enable_backup_domain_write_protect(); + PWR_CR &= ~PWR_CR_DBP; -static void delay(int n) { - for (int i = 0; i < n*1000000; ++i) - asm("nop"); } -int main(void) { - /* Setup clocks */ - target_clock_setup(); - - /* Initialize GPIO/LEDs if needed */ - target_gpio_setup(); - - while (1) { - target_set_led(1); - delay(1); - target_set_led(0); - delay(1); - } - - return 0; +uint16_t backup_read(void) { + uint16_t value = RTC_BKPXR(4); + return value; } + diff --git a/src/webusb.h b/src/stm32f072/backup.h similarity index 76% rename from src/webusb.h rename to src/stm32f072/backup.h index ce018fd..7b63ec5 100644 --- a/src/webusb.h +++ b/src/stm32f072/backup.h @@ -16,15 +16,10 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#ifndef WEBUSB_H_INCLUDED -#define WEBUSB_H_INCLUDED +#ifndef BACKUP_H_INCLUDED +#define BACKUP_H_INCLUDED -#include "webusb_defs.h" - -// Arbitrary -#define WEBUSB_VENDOR_CODE 0x01 - -extern const struct webusb_platform_descriptor webusb_platform; -extern void webusb_setup(usbd_device* usbd_dev); +extern void backup_write(uint16_t value); +extern uint16_t backup_read(void); #endif diff --git a/src/stm32f072/bluepill/config.h b/src/stm32f072/bluepill/config.h new file mode 100644 index 0000000..7a0db14 --- /dev/null +++ b/src/stm32f072/bluepill/config.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016, Devan Lai + * + * Permission to use, copy, modify, and/or distribute this software + * for any purpose with or without fee is hereby granted, provided + * that the above copyright notice and this permission notice + * appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef CONFIG_H_INCLUDED +#define CONFIG_H_INCLUDED + + +#define APP_BASE_ADDRESS 0x08004000 +#define FLASH_SIZE_OVERRIDE 0x10000 +#define FLASH_PAGE_SIZE 2048 + +#define FILE_INFO 1 +#define PRODUCT_NAME "Bluepill STM32F072CB" +#define VOLUME_LABEL "Bluepill" +#define BOOTLOADER_SIZE "16k" + + +#define HAVE_LED 1 +#define LED_GPIO_PORT GPIOC +#define LED_GPIO_PIN GPIO13 + +#define LED_OPEN_DRAIN 0 + +#ifndef HAVE_USB_PULLUP_CONTROL +#define HAVE_USB_PULLUP_CONTROL 0 +#endif + +#define DOUBLE_TAP + + +/* +#define target_gpio_setup() {\ + rcc_periph_clock_enable(RCC_GPIOA);\ + rcc_periph_clock_enable(RCC_GPIOB);\ + rcc_periph_clock_enable(RCC_GPIOC);\ + GPIO_MODER(GPIOC) = 0x4000000;\ + GPIO_MODER(GPIOA) = 0x29000000;\ + GPIO_OSPEEDR(GPIOA) = 0xc000000;\ + } +*/ + +#endif diff --git a/src/stm32f103/pxt32/config.h b/src/stm32f072/generic/config.h similarity index 56% rename from src/stm32f103/pxt32/config.h rename to src/stm32f072/generic/config.h index 2e45d95..f1396a5 100644 --- a/src/stm32f103/pxt32/config.h +++ b/src/stm32f072/generic/config.h @@ -19,11 +19,15 @@ #ifndef CONFIG_H_INCLUDED #define CONFIG_H_INCLUDED -#define APP_BASE_ADDRESS 0x08004000 -#define FLASH_SIZE_OVERRIDE (512*1024) -#define FLASH_PAGE_SIZE 2048 -#define DFU_UPLOAD_AVAILABLE 1 -#define DFU_DOWNLOAD_AVAILABLE 1 + +#define APP_BASE_ADDRESS 0x08004000 +#define FLASH_SIZE_OVERRIDE 0x10000 +#define FLASH_PAGE_SIZE 2048 + +#define FILE_INFO 1 +#define PRODUCT_NAME "STM32F072" +#define VOLUME_LABEL "STM32F072" +#define BOOTLOADER_SIZE "16k" #ifndef HAVE_LED #define HAVE_LED 0 @@ -37,6 +41,18 @@ #define HAVE_USB_PULLUP_CONTROL 0 #endif -#define UF2_FAMILY 0x5ee21072 +#define DOUBLE_TAP + + +/* +#define target_gpio_setup() {\ + rcc_periph_clock_enable(RCC_GPIOA);\ + rcc_periph_clock_enable(RCC_GPIOB);\ + rcc_periph_clock_enable(RCC_GPIOC);\ + GPIO_MODER(GPIOC) = 0x4000000;\ + GPIO_MODER(GPIOA) = 0x29000000;\ + GPIO_OSPEEDR(GPIOA) = 0xc000000;\ + } +*/ #endif diff --git a/src/blink/stm32f103x8.ld b/src/stm32f072/stm32f072x8.ld similarity index 88% rename from src/blink/stm32f103x8.ld rename to src/stm32f072/stm32f072x8.ld index 82ac85a..ac1d609 100644 --- a/src/blink/stm32f103x8.ld +++ b/src/stm32f072/stm32f072x8.ld @@ -23,9 +23,9 @@ /* 8k for the bootloader */ MEMORY { - rom (rx) : ORIGIN = 0x08004000, LENGTH = 100K - ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K + rom (rx) : ORIGIN = 0x08000000, LENGTH = 16K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 8K } /* Include the common ld script. */ -INCLUDE libopencm3_stm32f1.ld +INCLUDE cortex-m-generic.ld \ No newline at end of file diff --git a/src/stm32f072/target_stm32f072.c b/src/stm32f072/target_stm32f072.c new file mode 100644 index 0000000..60e38f0 --- /dev/null +++ b/src/stm32f072/target_stm32f072.c @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2016, Devan Lai + * + * Permission to use, copy, modify, and/or distribute this software + * for any purpose with or without fee is hereby granted, provided + * that the above copyright notice and this permission notice + * appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* Common STM32F103 target functions */ + +#include +#include +#include +#include +#include +#include + +#include "target.h" +#include "config.h" +#include "backup.h" + +#ifndef USES_GPIOA +#if (HAVE_USB_PULLUP_CONTROL == 0) +#define USES_GPIOA 1 +#else +#define USES_GPIOA 0 +#endif +#endif + +#ifndef USES_GPIOB +#define USES_GPIOB 0 +#endif + +#ifndef USES_GPIOC +#define USES_GPIOC 0 +#endif + +#ifdef FLASH_SIZE_OVERRIDE +_Static_assert((FLASH_BASE + FLASH_SIZE_OVERRIDE >= APP_BASE_ADDRESS), + "Incompatible flash size"); +#endif + +#define RTC_BOOTLOADER_FLAG 0x424C +#define RTC_BOOTLOADER_JUST_UPLOADED 0x424D + +static const uint16_t CMD_BOOT = RTC_BOOTLOADER_FLAG; +static const uint16_t CMD_APP = RTC_BOOTLOADER_JUST_UPLOADED; + +//#define USE_HSI 1 + + +void target_clock_setup(void) { +#ifdef USE_HSI + /* Set the system clock to 48MHz from the internal RC oscillator. + The clock tolerance doesn't meet the official USB spec, but + it's better than nothing. */ + rcc_clock_setup_in_hsi_out_48mhz(); +#else + rcc_clock_setup_in_hse_8mhz_out_48mhz(); +#endif +} + +void target_set_led(int on) { +#if HAVE_LED + if ((on && LED_OPEN_DRAIN) || (!on && !LED_OPEN_DRAIN)) { + gpio_clear(LED_GPIO_PORT, LED_GPIO_PIN); + } else { + gpio_set(LED_GPIO_PORT, LED_GPIO_PIN); + } +#else + (void)on; +#endif +} + +static void sleep_us(int us){ + for (int i = 0; i < us*2; i++) { + __asm__("nop"); + } +} + +#ifndef target_gpio_setup +void target_gpio_setup(void) { + + /* Enable GPIO clocks */ + rcc_periph_clock_enable(RCC_GPIOA); + rcc_periph_clock_enable(RCC_GPIOB); + rcc_periph_clock_enable(RCC_GPIOC); + +#if HAVE_LED + { + const uint8_t conf = (LED_OPEN_DRAIN ? GPIO_OTYPE_OD + : GPIO_OTYPE_PP); + if (LED_OPEN_DRAIN) { + gpio_set(LED_GPIO_PORT, LED_GPIO_PIN); + } else { + gpio_clear(LED_GPIO_PORT, LED_GPIO_PIN); + } + + gpio_mode_setup(LED_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_GPIO_PIN); + gpio_set_output_options(LED_GPIO_PORT, conf, GPIO_OSPEED_LOW, LED_GPIO_PIN); + + /* + * We want to set the config only for the pins mentioned in gpios, + * but keeping the others, so read out the actual config first. + */ + + } +#endif + + /* Setup the internal pull-up/pull-down for the button */ +#ifdef HAVE_BUTTONx + { + const uint8_t mode = GPIO_MODE_INPUT; + const uint8_t conf = GPIO_CNF_INPUT_PULL_UPDOWN; + gpio_set_mode(BUTTON_GPIO_PORT, mode, conf, BUTTON_GPIO_PIN); +#if BUTTON_ACTIVE_HIGH + gpio_clear(BUTTON_GPIO_PORT, BUTTON_GPIO_PIN); +#else + gpio_set(BUTTON_GPIO_PORT, BUTTON_GPIO_PIN); +#endif + } +#endif + +#if HAVE_USB_PULLUP_CONTROL + { + const uint8_t mode = GPIO_MODE_OUTPUT_10_MHZ; + const uint8_t conf = (USB_PULLUP_OPEN_DRAIN ? GPIO_CNF_OUTPUT_OPENDRAIN + : GPIO_CNF_OUTPUT_PUSHPULL); + /* Configure USB pullup transistor, initially disabled */ + if (USB_PULLUP_ACTIVE_HIGH) { + gpio_clear(USB_PULLUP_GPIO_PORT, USB_PULLUP_GPIO_PIN); + } else { + gpio_set(USB_PULLUP_GPIO_PORT, USB_PULLUP_GPIO_PIN); + } + gpio_set_mode(USB_PULLUP_GPIO_PORT, mode, conf, USB_PULLUP_GPIO_PIN); + } +#else + { + /* Drive the USB DP pin to override the pull-up */ + + gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO12); + gpio_set_output_options(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_LOW, GPIO12); + + } +#endif + + +#if 0 + while(1) { + target_set_led(1); + sleep_us(1200000); + target_set_led(0); + sleep_us(1200000); + } + + // TFT + // RST + gpio_clear(GPIOC, (1 << 4)); + sleep_us(20000); + //gpio_set(GPIOC, (1 << 4)); + sleep_us(20000); +#endif + +} +#endif + +const usbd_driver* target_usb_init(void) { + rcc_periph_reset_pulse(RST_USB); + +#if HAVE_USB_PULLUP_CONTROL + /* Enable USB pullup to connect */ + if (USB_PULLUP_ACTIVE_HIGH) { + gpio_set(USB_PULLUP_GPIO_PORT, USB_PULLUP_GPIO_PIN); + } else { + gpio_clear(USB_PULLUP_GPIO_PORT, USB_PULLUP_GPIO_PIN); + } +#else + /* Override hard-wired USB pullup to disconnect and reconnect */ + + rcc_set_usbclk_source(RCC_HSI48); + + gpio_clear(GPIOA, GPIO12); + int i; + for (i = 0; i < 80000; i++) { + __asm__("nop"); + } +#endif + + //return &st_usbfs_v1_usb_driver; + + return &st_usbfs_v2_usb_driver; +} + +void target_manifest_app(void) { + backup_write(CMD_APP); + //scb_reset_system(); + SCB_AIRCR = SCB_AIRCR_VECTKEY | SCB_AIRCR_SYSRESETREQ; + while (1); +} + +bool target_get_force_app(void) { + if (backup_read() == CMD_APP) { + backup_write(0); + return true; + } + return false; +} + +bool target_get_force_bootloader(void) { + /* Enable GPIO clocks */ + //rcc_periph_clock_enable(RCC_GPIOA); + //rcc_periph_clock_enable(RCC_GPIOB); + //rcc_periph_clock_enable(RCC_GPIOC); + + bool force = false; + /* Check the RTC backup register */ + uint16_t cmd = backup_read(); + if (cmd == CMD_BOOT) { + // asked to go into bootloader? + backup_write(0); + return true; + } + +#ifdef DOUBLE_TAP + // wait for second press on reset + backup_write(CMD_BOOT); + for(int x = 0; x< 10;x++) { + target_set_led(1); + sleep_us(60000); + target_set_led(0); + sleep_us(60000); + } + backup_write(0); + //force = false; +#else + // a reset now should go into app + backup_write(BKP0, CMD_APP); +#endif + +#if HAVE_BUTTON + /* Check if the user button is held down */ +#if BUTTON_ACTIVE_HIGH + if (gpio_get(BUTTON_GPIO_PORT, BUTTON_GPIO_PIN)) { + force = true; + } +#else + if (!gpio_get(BUTTON_GPIO_PORT, BUTTON_GPIO_PIN)) { + force = true; + } +#endif +#endif + + return force; +} + +/* +void target_get_serial_number(char* dest, size_t max_chars) { + desig_get_unique_id_as_string(dest, max_chars+1); +} +*/ + +static uint16_t* get_flash_end(void) { +#ifdef FLASH_SIZE_OVERRIDE + /* Allow access to the unofficial full 128KiB flash size */ + return (uint16_t*)(FLASH_BASE + FLASH_SIZE_OVERRIDE); +#else + /* Only allow access to the chip's self-reported flash size */ + return (uint16_t*)(FLASH_BASE + (size_t)DESIG_FLASH_SIZE*FLASH_PAGE_SIZE); +#endif +} + +size_t target_get_max_firmware_size(void) { + uint8_t* flash_end = (uint8_t*)get_flash_end(); + uint8_t* flash_start = (uint8_t*)(APP_BASE_ADDRESS); + + return (flash_end >= flash_start) ? (size_t)(flash_end - flash_start) : 0; +} + +#if 0 +void target_relocate_vector_table(void) { + SCB_VTOR = APP_BASE_ADDRESS & 0xFFFF; +} +#endif + +void target_flash_unlock(void) { + flash_unlock(); +} + +#if 0 +void target_flash_lock(void) { + flash_lock(); +} +#endif + +static inline uint16_t* get_flash_page_address(uint16_t* dest) { + return (uint16_t*)(((uint32_t)dest / FLASH_PAGE_SIZE) * FLASH_PAGE_SIZE); +} + +bool target_flash_program_array(uint16_t* dest, const uint16_t* data, size_t half_word_count) { + bool verified = true; + + /* Remember the bounds of erased data in the current page */ + static uint16_t* erase_start; + static uint16_t* erase_end; + + const uint16_t* flash_end = get_flash_end(); + while (half_word_count > 0) { + /* Avoid writing past the end of flash */ + if (dest >= flash_end) { + verified = false; + break; + } + + if (dest >= erase_end || dest < erase_start) { + erase_start = get_flash_page_address(dest); + erase_end = erase_start + (FLASH_PAGE_SIZE)/sizeof(uint16_t); + flash_erase_page((uint32_t)erase_start); + } + flash_program_half_word((uint32_t)dest, *data); + erase_start = dest + 1; + if (*dest != *data) { + verified = false; + break; + } + dest++; + data++; + half_word_count--; + } + + return verified; +} diff --git a/src/stm32f103/stlink/config.h b/src/stm32f103/Clockwork2-CAN/config.h similarity index 51% rename from src/stm32f103/stlink/config.h rename to src/stm32f103/Clockwork2-CAN/config.h index 545c7d5..b0d4625 100644 --- a/src/stm32f103/stlink/config.h +++ b/src/stm32f103/Clockwork2-CAN/config.h @@ -22,18 +22,41 @@ #define APP_BASE_ADDRESS 0x08004000 #define FLASH_SIZE_OVERRIDE 0x20000 #define FLASH_PAGE_SIZE 1024 -#define DFU_UPLOAD_AVAILABLE 1 -#define DFU_DOWNLOAD_AVAILABLE 1 + +#define FILE_INFO 1 +#define PRODUCT_NAME "Clockwork2 CAN STM32F103" +#define VOLUME_LABEL "CW2 CAN" +#define BOOTLOADER_SIZE "16k" #define HAVE_LED 1 -#define LED_GPIO_PORT GPIOA -#define LED_GPIO_PIN GPIO9 -#define LED_OPEN_DRAIN 0 +#define LED_GPIO_PORT GPIOB +#define LED_GPIO_PIN GPIO5 -#define HAVE_BUTTON 0 +#define LED_OPEN_DRAIN 0 +#ifndef HAVE_USB_PULLUP_CONTROL #define HAVE_USB_PULLUP_CONTROL 0 +#endif -#define USES_GPIOA 1 +//#define USES_GPIOA 1 +//#define USES_GPIOB 1 +//#define USES_GPIOC 0 + +#define DOUBLE_TAP + +#define target_gpio_setup() {\ + rcc_periph_clock_enable(RCC_GPIOA);\ + rcc_periph_clock_enable(RCC_GPIOB);\ + rcc_periph_clock_enable(RCC_AFIO); \ + GPIO_CRL(GPIOB) = 0x44144444;\ + } +#if 0 +#define target_gpio_setup() {\ + rcc_periph_clock_enable(RCC_GPIOA);\ + rcc_periph_clock_enable(RCC_GPIOB);\ +gpio_primary_remap(AFIO_MAPR_SWJ_CFG_FULL_SWJ_NO_JNTRST, 0);\ + } + +#endif #endif diff --git a/src/stm32f103/jacdac/config.h b/src/stm32f103/ERCF-CAN/config.h similarity index 66% rename from src/stm32f103/jacdac/config.h rename to src/stm32f103/ERCF-CAN/config.h index e934664..4447e95 100644 --- a/src/stm32f103/jacdac/config.h +++ b/src/stm32f103/ERCF-CAN/config.h @@ -22,25 +22,28 @@ #define APP_BASE_ADDRESS 0x08004000 #define FLASH_SIZE_OVERRIDE 0x20000 #define FLASH_PAGE_SIZE 1024 -#define DFU_UPLOAD_AVAILABLE 1 -#define DFU_DOWNLOAD_AVAILABLE 1 + +#define FILE_INFO 1 +#define PRODUCT_NAME "ERCF CAN STM32F103" +#define VOLUME_LABEL "ERCF CAN" +#define BOOTLOADER_SIZE "16k" #define HAVE_LED 1 -#define HAVE_BUTTON 0 +#define LED_GPIO_PORT GPIOB +#define LED_GPIO_PIN GPIO12 + +#define LED_OPEN_DRAIN 0 #ifndef HAVE_USB_PULLUP_CONTROL #define HAVE_USB_PULLUP_CONTROL 0 #endif -#define UF2_FAMILY 0x5ee21072 - -#undef VOLUME_LABEL -#define VOLUME_LABEL "JACDAC" -#undef PRODUCT_NAME -#define PRODUCT_NAME "JACDAC Feather STM32F103CB" -#undef BOARD_ID -#define BOARD_ID "STM32F103-jacdac-feather-v0" +#define DOUBLE_TAP -#define CRYSTAL_16MHZ 1 +#define target_gpio_setup() {\ + rcc_periph_clock_enable(RCC_GPIOA);\ + rcc_periph_clock_enable(RCC_GPIOB);\ + GPIO_CRH(GPIOB) = 0x44414444;\ + } #endif diff --git a/src/stm32f103/backup.c b/src/stm32f103/backup.c index 93c1d11..3c2a076 100644 --- a/src/stm32f103/backup.c +++ b/src/stm32f103/backup.c @@ -37,7 +37,7 @@ void backup_write(uint16_t value) { } -uint16_t backup_read() { +uint16_t backup_read(void) { uint16_t value = RTC_BKP_DR(9); return value; diff --git a/src/stm32f103/backup.h b/src/stm32f103/backup.h index 740558c..3022bbe 100644 --- a/src/stm32f103/backup.h +++ b/src/stm32f103/backup.h @@ -28,6 +28,6 @@ enum BackupRegister { }; extern void backup_write(uint16_t value); -extern uint16_t backup_read(); +extern uint16_t backup_read(void); #endif diff --git a/src/stm32f103/bluepill/config.h b/src/stm32f103/bluepill/config.h index 68ee633..f6aba72 100644 --- a/src/stm32f103/bluepill/config.h +++ b/src/stm32f103/bluepill/config.h @@ -22,8 +22,11 @@ #define APP_BASE_ADDRESS 0x08002000 #define FLASH_SIZE_OVERRIDE 0x20000 #define FLASH_PAGE_SIZE 1024 -#define DFU_UPLOAD_AVAILABLE 1 -#define DFU_DOWNLOAD_AVAILABLE 1 + +#define FILE_INFO 0 +#define PRODUCT_NAME "Bluepill" +#define VOLUME_LABEL "Bluepill" +#define BOOTLOADER_SIZE "8k" #ifndef HAVE_LED #define HAVE_LED 0 @@ -37,15 +40,6 @@ #define HAVE_USB_PULLUP_CONTROL 0 #endif -#define UF2_FAMILY 0x5ee21072 - -#undef VOLUME_LABEL -#define VOLUME_LABEL "BLUEPILL" -#undef PRODUCT_NAME -#define PRODUCT_NAME "Blue Pill STM32F103xB" -#undef BOARD_ID -#define BOARD_ID "STM32F103-blue-pill-v0" - #define DOUBLE_TAP #define target_gpio_setup() {\ diff --git a/src/stm32f103/generic/config.h b/src/stm32f103/generic/config.h index eacf46f..467e44c 100644 --- a/src/stm32f103/generic/config.h +++ b/src/stm32f103/generic/config.h @@ -19,11 +19,15 @@ #ifndef CONFIG_H_INCLUDED #define CONFIG_H_INCLUDED -#define APP_BASE_ADDRESS 0x08004000 +#define APP_BASE_ADDRESS 0x08002000 #define FLASH_SIZE_OVERRIDE 0x20000 #define FLASH_PAGE_SIZE 1024 -#define DFU_UPLOAD_AVAILABLE 1 -#define DFU_DOWNLOAD_AVAILABLE 1 + +#define FILE_INFO 0 +#define PRODUCT_NAME "STM32F103" +#define VOLUME_LABEL "STM32F103" +#define BOOTLOADER_SIZE "8k" + #ifndef HAVE_LED #define HAVE_LED 0 @@ -37,6 +41,10 @@ #define HAVE_USB_PULLUP_CONTROL 0 #endif -#define UF2_FAMILY 0x5ee21072 +#define DOUBLE_TAP + +#define target_gpio_setup() {\ + rcc_periph_clock_enable(RCC_GPIOA);\ + } #endif diff --git a/src/stm32f103/maplemini/config.h b/src/stm32f103/maplemini/config.h index df7a9ac..a0ee329 100644 --- a/src/stm32f103/maplemini/config.h +++ b/src/stm32f103/maplemini/config.h @@ -23,6 +23,11 @@ #define FLASH_SIZE_OVERRIDE 0x20000 #define FLASH_PAGE_SIZE 1024 +#define FILE_INFO 0 +#define PRODUCT_NAME "MapleMini" +#define VOLUME_LABEL "MapleMini" +#define BOOTLOADER_SIZE "8k" + #define HAVE_LED 1 #define LED_GPIO_PORT GPIOB #define LED_GPIO_PIN GPIO1 @@ -34,8 +39,6 @@ trigger the ROM serial bootloader and prevent us from running anyways. */ -#define UF2_FAMILY 0x5ee21072 - #define HAVE_USB_PULLUP_CONTROL 1 #define USB_PULLUP_GPIO_PORT GPIOB #define USB_PULLUP_GPIO_PIN GPIO9 diff --git a/src/stm32f103/stm32f103x8_16k.ld b/src/stm32f103/stm32f103x8_16k.ld new file mode 100644 index 0000000..811e71f --- /dev/null +++ b/src/stm32f103/stm32f103x8_16k.ld @@ -0,0 +1,111 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2015 Karl Palsson + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +/* Linker script for STM32F103x8, 64k flash, 20k RAM. */ + +/* Define memory regions. */ +/* 8k for the bootloader */ +MEMORY +{ + rom (rx) : ORIGIN = 0x08000000, LENGTH = 16K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K +} + +/* Include the common ld script. */ +EXTERN (vector_table2) + +/* Define the entry point of the output file. */ +ENTRY(reset_handler) + +/* Define sections. */ +SECTIONS +{ + .text : { + *(.vectors) /* Vector table */ + *(.text*) /* Program code */ + . = ALIGN(4); + *(.rodata*) /* Read-only data */ + . = ALIGN(4); + } >rom + + /* C++ Static constructors/destructors, also used for __attribute__ + * ((constructor)) and the likes */ + .preinit_array : { + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + } >rom + .init_array : { + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + } >rom + .fini_array : { + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + } >rom + + /* + * Another section used by C++ stuff, appears when using newlib with + * 64bit (long long) printf support + */ + .ARM.extab : { + *(.ARM.extab*) + } >rom + .ARM.exidx : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >rom + + . = ALIGN(4); + _etext = .; + + .data : { + _data = .; + *(.data*) /* Read-write initialized data */ + . = ALIGN(4); + _edata = .; + } >ram AT >rom + _data_loadaddr = LOADADDR(.data); + + .bss : { + *(.bss*) /* Read-write zero initialized data */ + *(COMMON) + . = ALIGN(4); + _ebss = .; + } >ram + + /* + * The .eh_frame section appears to be used for C++ exception handling. + * You may need to fix this if you're using C++. + */ + /DISCARD/ : { *(.eh_frame) } + + . = ALIGN(4); + end = .; +} + +PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram)); diff --git a/src/stm32f103/target_stm32f103.c b/src/stm32f103/target_stm32f103.c index c070049..6bff838 100644 --- a/src/stm32f103/target_stm32f103.c +++ b/src/stm32f103/target_stm32f103.c @@ -87,7 +87,6 @@ int memcmp(const void *vl, const void *vr, size_t n) return n ? *l-*r : 0; } -#if 0 void target_clock_setup(void) { #ifdef USE_HSI /* Set the system clock to 48MHz from the internal RC oscillator. @@ -96,14 +95,9 @@ void target_clock_setup(void) { rcc_clock_setup_in_hsi_out_48mhz(); #else /* Set system clock to 72 MHz from an external crystal */ - #ifdef CRYSTAL_16MHZ - rcc_clock_setup_in_hse_16mhz_out_72mhz(); - #else - rcc_clock_setup_in_hse_8mhz_out_72mhz(); - #endif + rcc_clock_setup_pll(&rcc_hse_configs[RCC_CLOCK_HSE8_72MHZ]); #endif } -#endif void target_set_led(int on) { #if HAVE_LED @@ -213,6 +207,7 @@ const usbd_driver* target_usb_init(void) { } #else /* Override hard-wired USB pullup to disconnect and reconnect */ + GPIO_CRH(GPIOA) = 0x44414444; gpio_clear(GPIOA, GPIO12); int i; for (i = 0; i < 800000; i++) { diff --git a/src/target.h b/src/target.h index a721b68..ba0af88 100644 --- a/src/target.h +++ b/src/target.h @@ -27,8 +27,8 @@ #include #include -//extern void target_clock_setup(void); -//extern void target_gpio_setup(void); +extern void target_clock_setup(void); +extern void target_gpio_setup(void); extern const usbd_driver* target_usb_init(void); extern bool target_get_force_bootloader(void); extern bool target_get_force_app(void); @@ -44,7 +44,6 @@ extern void target_set_led(int on); extern void target_pre_main(void); -#define target_clock_setup() rcc_clock_setup_in_hse_8mhz_out_72mhz(); #define target_relocate_vector_table() SCB_VTOR = APP_BASE_ADDRESS & 0xFFFF; #define target_flash_lock() flash_lock(); diff --git a/src/targets.mk b/src/targets.mk index d7a3845..830f645 100644 --- a/src/targets.mk +++ b/src/targets.mk @@ -15,45 +15,66 @@ ## CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ifeq ($(TARGET),STM32F103) - TARGET_COMMON_DIR := ./stm32f103 - TARGET_SPEC_DIR := ./stm32f103/generic - LDSCRIPT := ./stm32f103/stm32f103x8.ld + CPU := stm32f103 + TARGET_COMMON_DIR := ./$(CPU) + TARGET_SPEC_DIR := ./$(CPU)/generic + LDSCRIPT := ./$(CPU)/stm32f103x8.ld ARCH = STM32F1 + +endif +ifeq ($(TARGET),STM32F072) + CPU := stm32f072 + TARGET_COMMON_DIR := ./$(CPU) + TARGET_SPEC_DIR := ./$(CPU)/generic + LDSCRIPT := ./$(CPU)/stm32f072x8.ld + ARCH = STM32F0 + endif ifeq ($(TARGET),BLUEPILL) - TARGET_COMMON_DIR := ./stm32f103 - TARGET_SPEC_DIR := ./stm32f103/bluepill - LDSCRIPT := ./stm32f103/stm32f103x8.ld + CPU = stm32f103 + TARGET_COMMON_DIR := ./$(CPU) + TARGET_SPEC_DIR := ./$(CPU)/bluepill + LDSCRIPT := ./$(CPU)/stm32f103x8.ld ARCH = STM32F1 DEFS += -DHAVE_LED=1 -DLED_GPIO_PORT=GPIOC -DLED_GPIO_PIN=GPIO13 -DLED_OPEN_DRAIN=1 -DUSES_GPIOC=1 endif +ifeq ($(TARGET),BLUEPILL_072) + CPU := stm32f072 + TARGET_COMMON_DIR := ./$(CPU) + TARGET_SPEC_DIR := ./$(CPU)/bluepill + LDSCRIPT := ./$(CPU)/stm32f072x8.ld + ARCH = STM32F0 +endif ifeq ($(TARGET),MAPLEMINI) - TARGET_COMMON_DIR := ./stm32f103 - TARGET_SPEC_DIR := ./stm32f103/maplemini - LDSCRIPT := ./stm32f103/stm32f103x8.ld + CPU := stm32f103 + TARGET_COMMON_DIR := ./$(CPU) + TARGET_SPEC_DIR := ./$(CPU)/maplemini + LDSCRIPT := ./$(CPU)/stm32f103x8.ld ARCH = STM32F1 endif -ifeq ($(TARGET),STLINK) - TARGET_COMMON_DIR := ./stm32f103 - TARGET_SPEC_DIR := ./stm32f103/stlink - LDSCRIPT := ./stm32f103/stm32f103x8.ld +ifeq ($(TARGET),ERCF-CAN) + CPU := stm32f103 + TARGET_COMMON_DIR := ./$(CPU) + TARGET_SPEC_DIR := ./$(CPU)/ERCF-CAN + LDSCRIPT := ./$(CPU)/stm32f103x8_16k.ld ARCH = STM32F1 endif -ifeq ($(TARGET),PXT32) - TARGET_COMMON_DIR := ./stm32f103 - TARGET_SPEC_DIR := ./stm32f103/pxt32 - LDSCRIPT := ./stm32f103/stm32f103x8.ld +ifeq ($(TARGET),Clockwork2-CAN_103) + CPU := stm32f103 + TARGET_COMMON_DIR := ./$(CPU) + TARGET_SPEC_DIR := ./$(CPU)/Clockwork2-CAN + LDSCRIPT := ./$(CPU)/stm32f103x8_16k.ld ARCH = STM32F1 - DEFS += -DHAVE_LED=1 -DLED_GPIO_PORT=GPIOB -DLED_GPIO_PIN=GPIO11 -DLED_OPEN_DRAIN=1 -DUSES_GPIOB=1 endif -ifeq ($(TARGET),JACDAC) - TARGET_COMMON_DIR := ./stm32f103 - TARGET_SPEC_DIR := ./stm32f103/jacdac - LDSCRIPT := ./stm32f103/stm32f103x8.ld - ARCH = STM32F1 - DEFS += -DHAVE_LED=1 -DLED_GPIO_PORT=GPIOB -DLED_GPIO_PIN=GPIO13 -DLED_OPEN_DRAIN=0 +ifeq ($(TARGET),Clockwork2-CAN_072) + CPU := stm32f072 + TARGET_COMMON_DIR := ./$(CPU) + TARGET_SPEC_DIR := ./$(CPU)/Clockwork2-CAN + LDSCRIPT := ./$(CPU)/stm32f072x8.ld + ARCH = STM32F0 endif + ifndef ARCH $(error Unknown target $(TARGET)) endif diff --git a/src/uf2.h b/src/uf2.h deleted file mode 100644 index 734b8c1..0000000 --- a/src/uf2.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef UF2FORMAT_H -#define UF2FORMAT_H 1 - -#include "uf2cfg.h" -#include "target.h" -#include "config.h" - -#include -#include - -// All entries are little endian. - -#define UF2_MAGIC_START0 0x0A324655UL // "UF2\n" -#define UF2_MAGIC_START1 0x9E5D5157UL // Randomly selected -#define UF2_MAGIC_END 0x0AB16F30UL // Ditto - -// If set, the block is "comment" and should not be flashed to the device -#define UF2_FLAG_NOFLASH 0x00000001 -#define UF2_FLAG_FAMILYID_PRESENT 0x00002000 - -#define UF2_IS_MY_FAMILY(bl) \ - (((bl)->flags & UF2_FLAG_FAMILYID_PRESENT) == 0 || (bl)->familyID == UF2_FAMILY) - -#define MAX_BLOCKS (FLASH_SIZE_OVERRIDE / 256 + 100) -typedef struct { - uint32_t numBlocks; - uint32_t numWritten; - uint8_t writtenMask[MAX_BLOCKS / 8 + 1]; -} WriteState; - -typedef struct { - // 32 byte header - uint32_t magicStart0; - uint32_t magicStart1; - uint32_t flags; - uint32_t targetAddr; - uint32_t payloadSize; - uint32_t blockNo; - uint32_t numBlocks; - uint32_t familyID; - - // raw data; - uint8_t data[476]; - - // store magic also at the end to limit damage from partial block reads - uint32_t magicEnd; -} UF2_Block; - -typedef struct { - uint8_t version; - uint8_t ep_in; - uint8_t ep_out; - uint8_t reserved0; - uint32_t cbw_tag; - uint32_t blocks_remaining; - uint8_t *buffer; -} UF2_HandoverArgs; - -int write_block(uint32_t lba, const uint8_t *copy_from); -int read_block(uint32_t block_no, uint8_t *data); -void ghostfat_1ms(void); - -typedef void (*UF2_MSC_Handover_Handler)(UF2_HandoverArgs *handover); -typedef void (*UF2_HID_Handover_Handler)(int ep); - -// this is required to be exactly 16 bytes long by the linker script -typedef struct { - void *reserved0; - UF2_HID_Handover_Handler handoverHID; - UF2_MSC_Handover_Handler handoverMSC; - const char *info_uf2; -} UF2_BInfo; - -#define UF2_BINFO ((UF2_BInfo *)(APP_START_ADDRESS - sizeof(UF2_BInfo))) - -static inline bool is_uf2_block(const void *data) { - const UF2_Block *bl = (const UF2_Block *)data; - return bl->magicStart0 == UF2_MAGIC_START0 && bl->magicStart1 == UF2_MAGIC_START1 && - bl->magicEnd == UF2_MAGIC_END; -} - -static inline bool in_uf2_bootloader_space(const void *addr) { - return USER_FLASH_END <= (uint32_t)addr && (uint32_t)addr < FLASH_SIZE_OVERRIDE; -} - - -#ifdef UF2_DEFINE_HANDOVER -static inline const char *uf2_info(void) { - if (in_uf2_bootloader_space(UF2_BINFO->info_uf2)) - return UF2_BINFO->info_uf2; - return "N/A"; -} - -static inline void hf2_handover(uint8_t ep) { - const char *board_info = UF2_BINFO->info_uf2; - UF2_HID_Handover_Handler fn = UF2_BINFO->handoverHID; - - if (in_uf2_bootloader_space(board_info) && in_uf2_bootloader_space((const void *)fn) && - ((uint32_t)fn & 1)) { - // Pass control to bootloader; never returns - fn(ep & 0xf); - } -} - -// the ep_in/ep_out are without the 0x80 mask -// cbw_tag is in the same bit format as it came -static inline void check_uf2_handover(uint8_t *buffer, uint32_t blocks_remaining, uint8_t ep_in, - uint8_t ep_out, uint32_t cbw_tag) { - if (!is_uf2_block(buffer)) - return; - - const char *board_info = UF2_BINFO->info_uf2; - UF2_MSC_Handover_Handler fn = UF2_BINFO->handoverMSC; - - if (in_uf2_bootloader_space(board_info) && in_uf2_bootloader_space((const void *)fn) && - ((uint32_t)fn & 1)) { - UF2_HandoverArgs hand = { - 1, ep_in, ep_out, 0, cbw_tag, blocks_remaining, buffer, - }; - // Pass control to bootloader; never returns - fn(&hand); - } -} -#endif - -#endif diff --git a/src/uf2cfg.h b/src/uf2cfg.h deleted file mode 100644 index 4159cae..0000000 --- a/src/uf2cfg.h +++ /dev/null @@ -1,8 +0,0 @@ -#define PRODUCT_NAME "STM32 Board" -#define BOARD_ID "STM32F103-generic-v0" -#define INDEX_URL "https://maker.makecode.com" -#define UF2_NUM_BLOCKS 8000 -#define VOLUME_LABEL "STM32" -// where the UF2 files are allowed to write data - we allow MBR, since it seems part of the softdevice .hex file -#define USER_FLASH_START (uint32_t)(APP_BASE_ADDRESS) -#define USER_FLASH_END (0x08000000+FLASH_SIZE_OVERRIDE) diff --git a/src/usb_conf.c b/src/usb_conf.c index 9445b03..b24a2c5 100644 --- a/src/usb_conf.c +++ b/src/usb_conf.c @@ -21,135 +21,92 @@ #include #include "target.h" -#include "webusb.h" +#include #include #include "usb_conf.h" -static const struct usb_device_descriptor dev = { - .bLength = USB_DT_DEVICE_SIZE, - .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = 0x0210, - .bDeviceClass = 0, - .bDeviceSubClass = 0, - .bDeviceProtocol = 0, - .bMaxPacketSize0 = 64, - .idVendor = USB_VID, - .idProduct = USB_PID, - .bcdDevice = 0x0110, - .iManufacturer = 1, - .iProduct = 2, - .iSerialNumber = 3, - .bNumConfigurations = 1, -}; - -static const struct usb_interface_descriptor dfu_iface = { - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = INTF_DFU, - .bAlternateSetting = 0, - .bNumEndpoints = 0, - .bInterfaceClass = 0xFE, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 2, - .iInterface = 4, - - .endpoint = NULL, +static const struct usb_device_descriptor dev_descr = { + .bLength = USB_DT_DEVICE_SIZE, + .bDescriptorType = USB_DT_DEVICE, + .bcdUSB = 0x0110, + .bDeviceClass = 0, + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, + .bMaxPacketSize0 = 64, + .idVendor = USB_VID, + .idProduct = USB_PID, + .bcdDevice = 0x0200, + .iManufacturer = 1, + .iProduct = 2, + .iSerialNumber = 3, + .bNumConfigurations = 1, }; static const struct usb_endpoint_descriptor msc_endp[] = {{ - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x01, - .bmAttributes = USB_ENDPOINT_ATTR_BULK, - .wMaxPacketSize = 64, - .bInterval = 0, + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x01, + .bmAttributes = USB_ENDPOINT_ATTR_BULK, + .wMaxPacketSize = 64, + .bInterval = 0, }, { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x82, - .bmAttributes = USB_ENDPOINT_ATTR_BULK, - .wMaxPacketSize = 64, - .bInterval = 0, -}}; - -static const struct usb_interface_descriptor msc_iface = { - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = INTF_MSC, - .bAlternateSetting = 0, - .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_MSC, - .bInterfaceSubClass = USB_MSC_SUBCLASS_SCSI, - .bInterfaceProtocol = USB_MSC_PROTOCOL_BBB, - .iInterface = 0, - .endpoint = msc_endp, - .extra = NULL, - .extralen = 0 -}; - -static const struct usb_interface interfaces[] = { - /* DFU interface */ - { - .num_altsetting = 1, - .altsetting = &msc_iface, - }, -}; - -static const struct usb_config_descriptor config = { - .bLength = USB_DT_CONFIGURATION_SIZE, - .bDescriptorType = USB_DT_CONFIGURATION, - .wTotalLength = 0, - .bNumInterfaces = sizeof(interfaces)/sizeof(struct usb_interface), - .bConfigurationValue = 1, - .iConfiguration = 0, - .bmAttributes = 0xC0, - .bMaxPower = 0x32, - - .interface = interfaces, -}; - -static const struct usb_device_capability_descriptor* capabilities[] = { - (const struct usb_device_capability_descriptor*)&webusb_platform, -}; - -static const struct usb_bos_descriptor bos = { - .bLength = USB_DT_BOS_SIZE, - .bDescriptorType = USB_DT_BOS, - .wTotalLength = USB_DT_BOS_SIZE + sizeof(webusb_platform), - .bNumDeviceCaps = sizeof(capabilities)/sizeof(capabilities[0]), - .capabilities = capabilities + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x82, + .bmAttributes = USB_ENDPOINT_ATTR_BULK, + .wMaxPacketSize = 64, + .bInterval = 0, +} }; + +static const struct usb_interface_descriptor msc_iface[] = {{ + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_MSC, + .bInterfaceSubClass = USB_MSC_SUBCLASS_SCSI, + .bInterfaceProtocol = USB_MSC_PROTOCOL_BBB, + .iInterface = 0, + .endpoint = msc_endp, + .extra = NULL, + .extralen = 0 +} }; + +static const struct usb_interface ifaces[] = {{ + .num_altsetting = 1, + .altsetting = msc_iface, +} }; + +static const struct usb_config_descriptor config_descr = { + .bLength = USB_DT_CONFIGURATION_SIZE, + .bDescriptorType = USB_DT_CONFIGURATION, + .wTotalLength = 0, + .bNumInterfaces = 1, + .bConfigurationValue = 1, + .iConfiguration = 0, + .bmAttributes = 0x80, + .bMaxPower = 0x32, + .interface = ifaces, }; - -static char serial_number[USB_SERIAL_NUM_LENGTH+1]; - static const char *usb_strings[] = { - "Maple", - "Maple Bootloader", -// serial_number, - "1", - "MapleBoot" + "MSC", + "MSC Bootloader", + "MSC Boot" }; /* Buffer to be used for control requests. */ static uint8_t usbd_control_buffer[USB_CONTROL_BUF_SIZE] __attribute__ ((aligned (2))); -void usb_set_serial_number(const char* serial) { - serial_number[0] = '\0'; - if (serial) { - strncpy(serial_number, serial, USB_SERIAL_NUM_LENGTH); - serial_number[USB_SERIAL_NUM_LENGTH] = '\0'; - } -} usbd_device* usb_setup(void) { - int num_strings = sizeof(usb_strings)/sizeof(const char*); const usbd_driver* driver = target_usb_init(); - usbd_device* usbd_dev = usbd_init(driver, &dev, &config, &bos, - usb_strings, num_strings, + usbd_device* usbd_dev = usbd_init(driver, &dev_descr, &config_descr, + usb_strings, 3, usbd_control_buffer, sizeof(usbd_control_buffer)); return usbd_dev; diff --git a/src/usb_msc.c b/src/usb_msc.c index 364199c..b3e2abc 100644 --- a/src/usb_msc.c +++ b/src/usb_msc.c @@ -242,7 +242,6 @@ static void set_sbc_status(usbd_mass_storage *ms, enum sbc_asc asc, enum sbc_ascq ascq) { - LOG("SBC st %d %d %d", key, asc, ascq); ms->sense.key = (uint8_t) key; ms->sense.asc = (uint8_t) asc; ms->sense.ascq = (uint8_t) ascq; @@ -391,7 +390,10 @@ static void scsi_format_unit(usbd_mass_storage *ms, struct usb_msc_trans *trans, enum trans_event event) { -/* +(void)ms; +(void)trans; +(void)event; + /* if (EVENT_CBW_VALID == event) { uint32_t i; @@ -524,8 +526,6 @@ static void scsi_command(usbd_mass_storage *ms, trans->byte_count = 0; } - LOG("SCSI %x", trans->cbw.cbw.CBWCB[0]); - switch (trans->cbw.cbw.CBWCB[0]) { case SCSI_TEST_UNIT_READY: case SCSI_SEND_DIAGNOSTIC: @@ -771,9 +771,9 @@ int msc_started = 0; /** @brief Handle various control requests related to the msc storage * interface. */ -static int msc_control_request(usbd_device *usbd_dev, - struct usb_setup_data *req, uint8_t **buf, - uint16_t *len, +static enum usbd_request_return_codes +msc_control_request(usbd_device *usbd_dev, + struct usb_setup_data *req, uint8_t **buf, uint16_t *len, usbd_control_complete_callback *complete) { (void)complete; @@ -781,11 +781,9 @@ static int msc_control_request(usbd_device *usbd_dev, switch (req->bRequest) { case USB_MSC_REQ_BULK_ONLY_RESET: - LOG("MSC RESET"); /* Do any special reset code here. */ return USBD_REQ_HANDLED; case USB_MSC_REQ_GET_MAX_LUN: - LOG("GET MAX LUN"); msc_started = 1; /* Return the number of LUNs. We use 0. */ *buf[0] = 0; diff --git a/src/vector.c b/src/vector.c index 8b73ad5..bde3839 100644 --- a/src/vector.c +++ b/src/vector.c @@ -1,65 +1,65 @@ -/* - * This file is part of the libopencm3 project. - * - * Copyright (C) 2010 Piotr Esden-Tempski , - * Copyright (C) 2012 chrysn - * - * This library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library. If not, see . - */ - -#include -#include - -/* load optional platform dependent initialization routines */ - -/* Symbols exported by the linker script(s): */ -extern unsigned _data_loadaddr, _data, _edata, _ebss, _stack; -typedef void (*funcp_t) (void); -extern funcp_t __preinit_array_start, __preinit_array_end; -extern funcp_t __init_array_start, __init_array_end; -extern funcp_t __fini_array_start, __fini_array_end; - -void main(void); -void blocking_handler(void); -void null_handler(void); - -typedef struct { - unsigned int *initial_sp_value; /**< Initial stack pointer value. */ - vector_table_entry_t reset; - vector_table_entry_t nmi; - vector_table_entry_t hard_fault; - vector_table_entry_t memory_manage_fault; /* not in CM0 */ - vector_table_entry_t bus_fault; /* not in CM0 */ - vector_table_entry_t usage_fault; /* not in CM0 */ - vector_table_entry_t reserved_x001c[4]; - vector_table_entry_t sv_call; - vector_table_entry_t debug_monitor; /* not in CM0 */ - vector_table_entry_t reserved_x0034; - vector_table_entry_t pend_sv; - vector_table_entry_t systick; -} vector_table2_t; - -__attribute__ ((section(".vectors"))) -vector_table2_t vector_table2 = { - .initial_sp_value = &_stack, - .reset = reset_handler, - .nmi = nmi_handler, - .hard_fault = hard_fault_handler, - .sv_call = sv_call_handler, - .pend_sv = pend_sv_handler, - .systick = sys_tick_handler, -}; - - - +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2010 Piotr Esden-Tempski , + * Copyright (C) 2012 chrysn + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include +#include + +/* load optional platform dependent initialization routines */ + +/* Symbols exported by the linker script(s): */ +//extern unsigned _data_loadaddr, _data, _edata, _ebss, _stack; +typedef void (*funcp_t) (void); +extern funcp_t __preinit_array_start, __preinit_array_end; +extern funcp_t __init_array_start, __init_array_end; +extern funcp_t __fini_array_start, __fini_array_end; + +void main(void); +void blocking_handler(void); +void null_handler(void); + +typedef struct { + unsigned int *initial_sp_value; /**< Initial stack pointer value. */ + vector_table_entry_t reset; + vector_table_entry_t nmi; + vector_table_entry_t hard_fault; + vector_table_entry_t memory_manage_fault; /* not in CM0 */ + vector_table_entry_t bus_fault; /* not in CM0 */ + vector_table_entry_t usage_fault; /* not in CM0 */ + vector_table_entry_t reserved_x001c[4]; + vector_table_entry_t sv_call; + vector_table_entry_t debug_monitor; /* not in CM0 */ + vector_table_entry_t reserved_x0034; + vector_table_entry_t pend_sv; + vector_table_entry_t systick; +} vector_table2_t; + +__attribute__ ((section(".vectors"))) +vector_table2_t vector_table2 = { + .initial_sp_value = &_stack, + .reset = reset_handler, + .nmi = nmi_handler, + .hard_fault = hard_fault_handler, + .sv_call = sv_call_handler, + .pend_sv = pend_sv_handler, + .systick = sys_tick_handler, +}; + + + diff --git a/src/webusb.c b/src/webusb.c deleted file mode 100644 index 5ea75de..0000000 --- a/src/webusb.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2016, Devan Lai - * - * Permission to use, copy, modify, and/or distribute this software - * for any purpose with or without fee is hereby granted, provided - * that the above copyright notice and this permission notice - * appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include "webusb.h" - -#include "usb_conf.h" -#include "config.h" - -const struct webusb_platform_descriptor webusb_platform = { - .bLength = WEBUSB_PLATFORM_DESCRIPTOR_SIZE, - .bDescriptorType = USB_DT_DEVICE_CAPABILITY, - .bDevCapabilityType = USB_DC_PLATFORM, - .bReserved = 0, - .platformCapabilityUUID = WEBUSB_UUID, - .bcdVersion = 0x0100, - .bVendorCode = WEBUSB_VENDOR_CODE, - .iLandingPage = 1 -}; diff --git a/src/webusb_defs.h b/src/webusb_defs.h deleted file mode 100644 index fd699e9..0000000 --- a/src/webusb_defs.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2016, Devan Lai - * - * Permission to use, copy, modify, and/or distribute this software - * for any purpose with or without fee is hereby granted, provided - * that the above copyright notice and this permission notice - * appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef WEBUSB_DEFS_H_INCLUDED -#define WEBUSB_DEFS_H_INCLUDED - -#include - -#define WEBUSB_REQ_GET_URL 0x02 - -#define WEBUSB_DT_URL 3 - -#define WEBUSB_URL_SCHEME_HTTP 0 -#define WEBUSB_URL_SCHEME_HTTPS 1 - -struct webusb_platform_descriptor { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDevCapabilityType; - uint8_t bReserved; - uint8_t platformCapabilityUUID[16]; - uint16_t bcdVersion; - uint8_t bVendorCode; - uint8_t iLandingPage; -} __attribute__((packed)); - -#define WEBUSB_PLATFORM_DESCRIPTOR_SIZE sizeof(struct webusb_platform_descriptor) - -#define WEBUSB_UUID {0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47,0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65} - -struct webusb_url_descriptor { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bScheme; - char URL[]; -} __attribute__((packed)); - -#define WEBUSB_DT_URL_DESCRIPTOR_SIZE 3 - -#endif diff --git a/src/winusb.c b/src/winusb.c deleted file mode 100644 index 38bf644..0000000 --- a/src/winusb.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2016, Devan Lai - * - * Permission to use, copy, modify, and/or distribute this software - * for any purpose with or without fee is hereby granted, provided - * that the above copyright notice and this permission notice - * appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include "winusb.h" - -#include "usb_conf.h" - -static const struct winusb_compatible_id_descriptor winusb_wcid = { - .dwLength = (WINUSB_COMPATIBLE_ID_HEADER_SIZE + - 1*WINUSB_COMPATIBLE_ID_FUNCTION_SECTION_SIZE), - .bcdVersion = 0x0100, - .wIndex = 0x0004, - .bNumSections = 1, - .reserved = { 0, 0, 0, 0, 0, 0, 0 }, - .functions = { - { - .bInterfaceNumber = 0, - .reserved0 = { 1 }, - .compatibleId = "WINUSB", - .subCompatibleId = "", - .reserved1 = { 0, 0, 0, 0, 0, 0} - }, - } -}; - -static int winusb_control_vendor_request(usbd_device *usbd_dev, - struct usb_setup_data *req, - uint8_t **buf, uint16_t *len, - usbd_control_complete_callback* complete) { - (void)complete; - (void)usbd_dev; - - if (req->bRequest != WINUSB_MS_VENDOR_CODE) { - return USBD_REQ_NEXT_CALLBACK; - } - - int status = USBD_REQ_NOTSUPP; - if (((req->bmRequestType & USB_REQ_TYPE_RECIPIENT) == USB_REQ_TYPE_DEVICE) && - (req->wIndex == WINUSB_REQ_GET_COMPATIBLE_ID_FEATURE_DESCRIPTOR)) { - *buf = (uint8_t*)(&winusb_wcid); - if (*len > winusb_wcid.dwLength) { - *len = winusb_wcid.dwLength; - } - status = USBD_REQ_HANDLED; - } else if (((req->bmRequestType & USB_REQ_TYPE_RECIPIENT) == USB_REQ_TYPE_INTERFACE) && - (req->wIndex == WINUSB_REQ_GET_EXTENDED_PROPERTIES_OS_FEATURE_DESCRIPTOR)) { - status = USBD_REQ_NOTSUPP; - } else { - status = USBD_REQ_NOTSUPP; - } - - return status; -} - -static void winusb_set_config(usbd_device* usbd_dev, uint16_t wValue) { - (void)wValue; - usbd_register_control_callback( - usbd_dev, - USB_REQ_TYPE_VENDOR, - USB_REQ_TYPE_TYPE, - winusb_control_vendor_request); -} - -void winusb_setup(usbd_device* usbd_dev) { - usbd_register_extra_string(usbd_dev, 0xEE, "MSFT100!"); - usbd_register_set_config_callback(usbd_dev, winusb_set_config); - - /* Windows probes the compatible ID before setting the configuration, - so also register the callback now */ - - usbd_register_control_callback( - usbd_dev, - USB_REQ_TYPE_VENDOR, - USB_REQ_TYPE_TYPE, - winusb_control_vendor_request); -} diff --git a/src/winusb.h b/src/winusb.h deleted file mode 100644 index 3bfb4ce..0000000 --- a/src/winusb.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2016, Devan Lai - * - * Permission to use, copy, modify, and/or distribute this software - * for any purpose with or without fee is hereby granted, provided - * that the above copyright notice and this permission notice - * appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef WINUSB_H_INCLUDED -#define WINUSB_H_INCLUDED - -#include "winusb_defs.h" - -/* Arbitrary, but must be equivalent to the last character in - the special OS descriptor string */ -#define WINUSB_MS_VENDOR_CODE 0x21 - -extern void winusb_setup(usbd_device* usbd_dev); - -#endif diff --git a/src/winusb_defs.h b/src/winusb_defs.h deleted file mode 100644 index 5355a1e..0000000 --- a/src/winusb_defs.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2016, Devan Lai - * - * Permission to use, copy, modify, and/or distribute this software - * for any purpose with or without fee is hereby granted, provided - * that the above copyright notice and this permission notice - * appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef WINUSB_DEFS_H_INCLUDED -#define WINUSB_DEFS_H_INCLUDED - -#include - -/* Microsoft OS 1.0 descriptors */ - -/* Extended Compat ID OS Feature Descriptor Specification */ -#define WINUSB_REQ_GET_COMPATIBLE_ID_FEATURE_DESCRIPTOR 0x04 -#define WINUSB_REQ_GET_EXTENDED_PROPERTIES_OS_FEATURE_DESCRIPTOR 0x05 - -/* Table 2. Function Section */ -struct winusb_compatible_id_function_section { - uint8_t bInterfaceNumber; - uint8_t reserved0[1]; - const char compatibleId[8]; - const char subCompatibleId[8]; - uint8_t reserved1[6]; -} __attribute__((packed)); - -#define WINUSB_COMPATIBLE_ID_FUNCTION_SECTION_SIZE 24 - -/* Table 1. Header Section */ -struct winusb_compatible_id_descriptor { - uint32_t dwLength; - uint16_t bcdVersion; - uint16_t wIndex; - uint8_t bNumSections; - uint8_t reserved[7]; - struct winusb_compatible_id_function_section functions[]; -} __attribute__((packed)); - -#define WINUSB_COMPATIBLE_ID_HEADER_SIZE 16 - -/* Microsoft OS 2.0 Descriptors Specification */ - -/* Table 8. Microsoft OS 2.0 descriptor wIndex values */ -#define WINUSB_REQ_MS_OS_20_DESCRIPTOR_INDEX 0x07 -#define WINUSB_REQ_MS_OS_20_SET_ALT_ENUMERATION 0x08 - -/* Table 9. Microsoft OS 2.0 descriptor wDescriptorType values */ -#define WINUSB_DT_MS_OS_20_SET_HEADER_DESCRIPTOR 0x00 -#define WINUSB_DT_MS_OS_20_SUBSET_HEADER_CONFIGURATION 0x01 -#define WINUSB_DT_MS_OS_20_SUBSET_HEADER_FUNCTION 0x02 -#define WINUSB_DT_MS_OS_20_FEATURE_COMPATIBLE_ID 0x03 -#define WINUSB_DT_MS_OS_20_FEATURE_REG_PROPERTY 0x04 -#define WINUSB_DT_MS_OS_20_FEATURE_MIN_RESUME_TIME 0x05 -#define WINUSB_DT_MS_OS_20_FEATURE_MODEL_ID 0x06 -#define WINUSB_DT_MS_OS_20_FEATURE_CCGP_DEVICE 0x07 - -/* Table 3. Microsoft OS 2.0 descriptor platform capability UUID */ -#define WINUSB_OS_20_UUID {0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C, 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F} - -/* Table 5. Descriptor set information structure */ -struct winusb_descriptor_set_information { - uint32_t dwWindowsVersion; - uint16_t wMSOSDescriptorSetTotalLength; - uint8_t bMS_VendorCode; - uint8_t bAltEnumCode; -} __attribute__((packed)); - -/* Table 4. Microsoft OS 2.0 platform capability descriptor header */ -struct winusb_platform_descriptor { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDevCapabilityType; - uint8_t bReserved; - uint8_t platformCapabilityUUID[16]; - struct winusb_descriptor_set_information descriptor_set_information[]; -} __attribute__((packed)); - -/* Table 10. Microsoft OS 2.0 descriptor set header */ -struct winusb_descriptor_set_header { - uint16_t wLength; - uint16_t wDescriptorType; - uint32_t dwWindowsVersion; - uint16_t wTotalLength; -} __attribute__((packed)); - -/* Table 11. Configuration subset header */ -struct winusb_configuration_subset_header { - uint16_t wLength; - uint16_t wDescriptorType; - uint8_t bConfigurationValue; - uint8_t bReserved; - uint16_t wTotalLength; -} __attribute__((packed)); - -/* Table 12. Function subset header */ -struct winusb_function_subset_header { - uint16_t wLength; - uint16_t wDescriptorType; - uint8_t bFirstInterface; - uint8_t bReserved; - uint16_t wSubsetLength; -} __attribute__((packed)); - -/* Table 13. Microsoft OS 2.0 compatible ID descriptor */ -struct winusb_20_compatible_id_feature_descriptor { - uint16_t wLength; - uint16_t wDescriptorType; - const char compatibleId[8]; - const char subCompatibleId[8];; -} __attribute__((packed)); - -/* Table 15. wPropertyDataType values for the Microsoft OS 2.0 registry property descriptor */ -#define WINUSB_PROP_DATA_TYPE_REG_SZ 1 -#define WINUSB_PROP_DATA_TYPE_REG_EXPAND_SZ 2 -#define WINUSB_PROP_DATA_TYPE_REG_BINARY 3 -#define WINUSB_PROP_DATA_TYPE_REG_DWORD_LITTLE_ENDIAN 4 -#define WINUSB_PROP_DATA_TYPE_REG_DWORD_BIG_ENDIAN 5 -#define WINUSB_PROP_DATA_TYPE_REG_LINK 6 -#define WINUSB_PROP_DATA_TYPE_REG_REG_MULTI_SZ 7 - -/* Table 16. Microsoft OS 2.0 minimum USB recovery time descriptor */ -struct winusb_minimum_recovery_time_descriptor { - uint16_t wLength; - uint16_t wDescriptorType; - uint8_t bResumeRecoveryTime; - uint8_t bResumeSignalingTime; -} __attribute__((packed)); - -/* Table 16. Microsoft OS 2.0 model ID descriptor */ -struct winusb_model_id_descriptor { - uint16_t wLength; - uint16_t wDescriptorType; - uint8_t modelId[16]; -} __attribute__((packed)); - -/* Table 17. Microsoft OS 2.0 CCGP device descriptor */ -struct winusb_ccgp_device_descriptor { - uint16_t wLength; - uint16_t wDescriptorType; -} __attribute__((packed)); - -#endif